Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Embeddable editor #697

Open
orangemug opened this issue May 31, 2020 · 6 comments
Open

Embeddable editor #697

orangemug opened this issue May 31, 2020 · 6 comments
Assignees
Milestone

Comments

@orangemug
Copy link
Collaborator

A few companies have embedded Maputnik in their website now. All of the current implementations are a number of custom modifications on top of Maputnik. This is neither good for Maputnik or the people embedding the editor.

We lose out because Maputnik doesn't get updated when we release a new version. Over the years we received a few bug reports about Maputnik being broken, when its nothing to do with the current release of the editor.

Lucky for us the latest of these companies has reached out before proceeding with their custom implementation. I've been in contact with them and they are willing to sponsor this development, the company is @fielda (👋 Fielda)

To be open with the community here's how the work will be split up. I will be breaking apart Maputnik into an npm installable set of react components to make it easy to embed Maputnik in a react application. This will also include adding additional configuration for Maputnik such as changing the styles shown in the 'open' modal, changing the sources in the 'data sources' modal and removing keys from the export modal. There will also be a private part of the work I'll do outside of the Maputnik organisation to integrate Maputnik within their application which will mainly involve custom styling.

The initial needs of @fielda will be prioritised for embedding this into their application. However nothing within the Maputnik codebase will be written with only them in mind, and everything written should be generally useful. However saying that, anything that's not initially a priority for this integration will probably be fleshed out later down the road.

I hope everyone agrees this is a positive thing for Maputnik and adds a feature set useful for many many organisations. Also hopefully it'll allow folks to build Maputnik into products we haven't even considered yet.

This is personally the first paid piece of development for Maputnik that I have done, so thanks again to @fielda for supporting this feature.

It's also worth noting that the current publicly accessible editor will have no noticeable changes to the user.

Implementation

The new embeddable interface for the editor has the following requirements

  • Custom arrangement of parts of the editor, mainly for alternate placement/replacement of the toolbar
  • Change styling to use CSS variables, to allow for custom colors/spacing
  • Move all icons into CSS so they can be modified by CSS variables
  • Custom modal component, to match internal modals of host app (TBD this might be complex)

Here is an example implementation (subject to change)

import '@maputnik/editor/css/default.css';
import {Editor, EditorState} from '@maputnik/editor';

class SimpleCustomEditor extends React.Component {
  constructor () {
    super(props);

    this.editor = new EditorState({
      style: {
        // osmLiberty...
      },
      settings: {
        styles: [
          // Default styles in the editors open modal
        ],
        sources: [
          {
            name: "Foobar transport",
            id: "foobar_transport",
            data: {
              type: "tilejson",
              url: "http://example.com/foobar.geojson",
            },
          },
        ],
        "layer_editor": {
          "json_editor": {
            "visiblity": "collapsed"
          },
        },
        "keyboard_shortcuts": {
          enabled: false, 
        },
        renderers: [
          "mapbox-gl",
          "openlayers",
        ],
      }
    });

    this.editor.on("change", newState => {
      this.setState({editorState: newState});
    });
  }

  render () {
    const {editorState} = this.state;
    return (
      <Editor
        className="maputnik-custom"
        editorState={editorState}
      />
    );
  }
}

A more complex example where we include an imaginary custom toolbar.

import '@maputnik/editor/css/default.css';
import {Map, EditorContent, EditorState} from '@maputnik/editor';

// Because the maputnik toolbar is simple we can easily replace it with a
// totally custom one.
import MaputnikCustomToolbar from './MaputnikCustomToolbar';

class AdvancedCustomEditor extends React.Component {

  constructor () {
    // Same as before...
  }

  render () {
    const {editorState} = this.state;

    return (
      <div className="maputnik-custom">
        <div className="maputnik-custom__top">
          <MaputnikCustomToolbar editorState={editorState} />
        </div> 
        <div className="maputnik-custom__main">
          <div className="maputnik-custom__main__left">
            <EditorContent editorState={editorState} />
          </div>
          <div className="maputnik-custom__main__right">
            <Map editorState={editorState} />
          </div>
        </div> 
      </div>
    );
  }
}

The CSS variables are to be named via the following conventions. Root level variables which effect the UI in it's entirety. These have the following convention

/*[1     ]-[2        ]*/
--maputnik-font-size-1: 26px;
/**
 * 1. namespace - always 'maputnik'
 * 2. name - a name decribing what's being configured
 */

Component level variables have the following convention

/*[1     ]-[2          ]-[3   ]-[4       ]*/
--maputnik-popup-layer-header-border-color: #000;
/**
 * 1. namespace - always 'maputnik'
 * 2. group - name of component
 * 3. sub-group - section of component
 * 4. property - the property you want to change, this mostly corrosponds to
 *    the underlying CSS property although other part of that UI could also use
 *    these along with CSS filters
 */

Following are some examples from my working copy of the new implementation

.maputnik-custom {
  /* Root level */
  --maputnik-font-family: sans-serif;
  --maputnik-font-size-1: 26px;
  --maputnik-font-size-2: 22px;
  --maputnik-font-size-3: 20px;
  /* Component level */
  --maputnik-link-color: #333;
  --maputnik-link-hover-color: #a2a2a2;
  --maputnik-popup-layer-background-color: white;
  --maputnik-popup-layer-color: #000;
  --maputnik-popup-layer-header-background-color: #fafafa;
  --maputnik-popup-layer-header-color: #000;
  --maputnik-popup-layer-header-border-color: #e8e8e8;
  /* more... */
}

You'll also be able to override specific features via .maputnik-<component> {/* rules... */} however these are more likely to break between versions so should be only used where absolutely necessary.

FAQs

Why CSS modules rather than something else like styled components?

CSS modules are standard web functionality, so will be around for a long time. We also use a bunch of different off the shelf libraries and React components. Standard CSS styling/overrides tend to work best with this approach as they always work regardless of the underlying tech.

Why are we adding support for all the companies to change the look and feel of the editor why not just Maputnik?

Companies want an integrated experience and having companies contributing time/money to Maputnik is good for everyone. It also opens the possibility for things like

  • A university creating an intro to cartography online course embedding Maputnik
  • Newsrooms could embed Maputnik into the end of a process to create simple maps. In future you could have locked layers and only allow changing of colors with a 'on brand' color palette (future work)

I think there is lots of future opportunity here.

Won't this make future development of Maputnik harder?

The Maputnik editor will use the same React components in the existing editor, so it'll make a slight difference in that we'll have to be more careful with styling changes. However having already started some of the styling/theming work and it has forced me to tidy up some of our CSS, which has made it a lot nicer.

Feedback

Please let me know any thoughts in the comments below.

@pathmapper
Copy link
Contributor

Thanks for writing this up @orangemug, some thoughts:

A few companies have embedded Maputnik in their website now.

True, and for most of them there is no giving back to this project. Neither by contributing code nor by donating to OSM on behalf of Maputnik (https://maputnik.github.io/donate, https://donate.openstreetmap.org/, not a single donation in almost two years).

We lose out because Maputnik doesn't get updated when we release a new version. Over the years we received a few bug reports about Maputnik being broken, when its nothing to do with the current release of the editor.

All those bug reports I'm remembering were related to http://editor.openmaptiles.org, which is not available anymore and now redirects to a totally different editor. So I think this isn't a current issue.

Won't this make future development of Maputnik harder?

It's not only about implementing the new structure and functionality, it's also about maintaining this and dealing with bug reports and feature requests related to the embedable editor.
My motivation for spending time for this is very low because there is no giving back to this project by most companies as outlined above.

I hope everyone agrees this is a positive thing for Maputnik and adds a feature set useful for many many organisations.

I agree this would be useful for many companies but I'm not sure if it's a positive thing for Maputnik.
This would make it easier to embed and customize the editor so that the user of such an editor wouldn't notice that it's Maputnik so that the visibility of Maputnik might decrease.
Also I think it would increase the time needed for maintaining the project while I don't expect there would be more giving back by companies.

@orangemug
Copy link
Collaborator Author

@pathmapper firstly I totally understand your concerns, I had similar thoughts also. However the more I thought about it the more I think it makes sense. Let me try and go through a few positives.

True, and for most of them there is no giving back to this project. Neither by contributing code nor by donating to OSM on behalf of Maputnik (https://maputnik.github.io/donate, https://donate.openstreetmap.org/, not a single donation in almost two years).

I totally agree, this annoys me also. I really like when I see individuals and universities use it. Even national mapping agencies, when they teach with it #164 (comment). However when companies embed it and don't even talk to us, yeah that's a little rude in my eyes, and I've definitely gone through periods of thinking "I'm working for free", rather than contributing to open source.

That's why I think the Fielda proposition is a good thing, I think they have gone about this in the right way. My interactions with @robert-claypool (👋 Robert) has genuinely been really positive. I also know they are supporting other open source projects.

All those bug reports I'm remembering were related to http://editor.openmaptiles.org, which is not available anymore and now redirects to a totally different editor. So I think this isn't a current issue.

That's true, although my guess would be we could expect the same as we get more usage on other forks.

It's not only about implementing the new structure and functionality, it's also about maintaining this and dealing with bug reports and feature requests related to the embedable editor.
My motivation for spending time for this is very low because there is no giving back to this project by most companies as outlined above.

So let's break this into two parts, CSS modules and Javascript.

So for CSS styling this is something I've wanted to do for a while anyway. It gives us a chance to tidy the CSS. I'd also like to get Maputnik usable on tablets (a lot of kids only have tablets) which would mean increasing spacing, font-size, etc... We also don't currently support increasing font-size via browser settings, which is an accessibility issue. A good tidy of the CSS which would happen as a result of theming would make these a lot easier. There is also the option of theming for the actual editor, like light/dark themes, which is also an accessibility preference for some users.

With regards to adding support for react modules, not a lot changes (also a lot changes) let me explain. So for us Maputnik would just use the same React component API as any other integration. So we would support some additional configuration options. I think those changes are pretty small.

I've given my self quite a bit of time for internal changes to make it all configurable, that is probably quite a bit of work. I really believe that this will make our own dev of the editor easier. I can't give exact details on this yet as I'll be working out the details as I go, but generally it'll be some sort of react context approach.

Also if a company isn't giving back then we shouldn't be doing work for free. It's totally our decision on what we choose to add/support. If a company wants X and isn't going to pay for it and we see no benefit for us, then we shouldn't add it. Even if a company does want to pay for additions then it'd have to make sense for the editor, it's definitely not an anything goes approach. This should always be either mutual benefit or expandable by other means. I can provide a good example of where that has worked well already.

Fielda want to style a single 'data source' rather than multiple. There was talk about 'locking' Maputnik to only allow one data source to be styled. This would be quite 'embed specific', however instead we can look at this another way and instead of locking Maputnik to a single 'data source' we can pre-fill the 'add modal' with the 'data source' if only one source is currently configured. Thats both good for Fielda and for Maputnik, win-win. I'm going to raise a ticket for this today.

With regards to bugs I believe this could be really positive, any company embedding Maputnik has an interest in keeping quality high. As an example if company X gets a bug reported in their style editor (Maputnik), it's their responsibility to reproduce that bug and report that to us. They do a certain amount of the triage for us, some of those bugs might even come with fixes 🤞

This would make it easier to embed and customize the editor so that the user of such an editor wouldn't notice that it's Maputnik so that the visibility of Maputnik might decrease.

Yeah it's a risk, however people are already doing this so why not be the ones in control?

Also I think it would increase the time needed for maintaining the project while I don't expect there would be more giving back by companies.

Although I don't think it will, if this becomes a burden, then we'd have to re-evaluate moving forward. We shouldn't just do stuff larger companies want for free, and if it becomes a pain to maintain 'embed specific' functionality we'd re-address that when it becomes an issue. Also remember that one company (Fielda) has already offered their support, and although there are no guarantees of future work, all conversations have been positive thus far.

Lastly companies are wanting to use Maputnik, as we've seen by various integrations, being an actual component in their organisation rather than a forked repo hopefully increases the chance of more companies reaching out to support us with either code/money contributions.

@pathmapper please let me know your thoughts.

@pathmapper
Copy link
Contributor

I totally understand your concerns, I had similar thoughts also

That's good to hear @orangemug.

I've definitely gone through periods of thinking "I'm working for free", rather than contributing to open source.

Yeah, same for me. And this is what I'm trying to avoid because if this would turn into a permanent feeling I think the consequence would be to stop contributing.

However the more I thought about it, the more I think it makes sense. Let me try and go through a few positives.

Thanks for your further thoughts. Sure, there also some positives and knowing that we are on the same page regarding our concerns makes me feel positive about moving forward and finding out what happens.

@orangemug
Copy link
Collaborator Author

Yeah, same for me. And this is what I'm trying to avoid because if this would turn into a permanent feeling I think the consequence would be to stop contributing.

That would be a huge loss to the project.

Thanks for your further thoughts. Sure, there also some positives and knowing that we are on the same page regarding our concerns makes me feel positive about moving forward and finding out what happens.

This is definitely a change to Maputnik, and we should definitely approach with some caution. @pathmapper if your happy I'd like to take on this work as I think it'll be really good for the project?

On a personal note I'm not working at the moment for a company (apart for the work described above), I'm taking some time off from work and putting that time towards Maputnik, well that and general learning. My main personal aims are accessibility in the short term, as you can probably guess. But I'll raise a v1.9.0 milestone also so we can start to batch up some more tickets.

@pathmapper
Copy link
Contributor

@pathmapper if your happy I'd like to take on this work as I think it'll be really good for the project?

Sure @orangemug, please go ahead! :-)

I think we've reached a point which many open source projects are reaching when the popularity increases: The questions if it's possible to turn from the time investing in a hobby project and learning experience into a (part-)time job. As you've described, the work for @fielda sounds like a good opportunity that fit's also well in your current situation. I really appreciate that you're thinking about ways how the whole project could benefit from this.

@orangemug orangemug added this to the v1.9.0 milestone Jun 10, 2020
@bchapuis
Copy link

bchapuis commented Apr 10, 2021

@orangemug @pathmapper Thanks a lot for your work on Maputnik! I have started integrating maputnik in Baremaps (A pipeline for creating and styling custom vector tiles) and I face an issue similar to the one described here. At the moment, I forked maputnik in the baremaps organisation, did some modifications, built it, and copied the build directory in my app. I tried without success to install and use maputnik as a npm dependency. Is this something that will be addressed with this issue?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants