Skip to content

Plugins Architecture

MapStore fully embraces both ReactJS and Redux concepts, enhancing them with the plugin concept.

A plugin in MapStore is a smart ReactJS component that is:

  • connected to a Redux store, so that some properties are automatically wired to the standard MapStore state
  • wired to standard actions for common events

In addition a plugin:

  • declares some reducers that need to be added to the Redux store, if needed
  • declares some epics that need to be added to the redux-observable middleare, if needed
  • is fully configurable to be easily customized to a certain level

Building an application using plugins

To use plugins you need to:

  • declare available (required) plugins, properly requiring them from the root application component
  • load / declare plugins configuration
  • create a store that dynamically includes plugins required reducers
  • use a PluginsContainer component as the container for your plugins enabled application slice (can be the whole application or just a part of it)

Declare available plugins

Create a plugins.js file where you declare all the needed plugins:

plugins.js:

1
2
3
4
5
6
module.exports = {
    plugins: {
        MyPlugin: require('../plugins/My')
    },
    requires: {}
};

Load / Create plugins configuration object

Use pluginsConfig.json to configure your plugins.

pluginsConfig.json:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
{
    ...
    "standard": [
        {
            "name": "Map",
            "cfg": {
                "zoomControl": false,
                "tools": ["locate"]
            }
        },
        ...
    ],
    ...
}

Declare a plugins compatible Redux Store

Create a store that properly initializes plugins reducers and epics (see standardStore.js) :

store.js:

1
2
3
4
5
6
7
8
9
const {combineReducers} = require('../utils/PluginsUtils');
const {createDebugStore} = require('../utils/DebugUtils');

module.exports = (plugins) => {
  const allReducers = combineReducers(plugins, {
     ...
  });
  return createDebugStore(allReducers, {});
};

Use a PluginContainer to render all your plugins

In the root application component require plugins declaration and configuration and use them to initialize both the store and a PluginsContainer (see our PluginContainer.jsx):

App.jsx:

1
2
3
4
5
6
7
8
const {pluginsDef} = require('./plugins.js');
const pluginsCfg = require('./pluginsConfig.json');

const store = require('./store')(pluginsDef);

const plugins = PluginsUtils.getPlugins(pluginsDef);

ReactDOM.render(<PluginsContainer plugins={plugins} mode="standard" pluginsConfig={pluginsCfg}/>, ...container...);

Developing a plugin

An example is better than a thousand words:

My.jsx:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
// this is a dumb component
const MyComponent = require('../components/MyComponent');
const {connect} = require('../utils/PluginsUtils');

// let's wire it to state and actions
const MyPlugin = connect((state) => ({
   myproperty: state.myreducer.property
}), {
   myaction
})(MyComponent);

// let's export the plugin and a set of required reducers
const myreducer = require('../reducers/myreducer');
module.exports = {
   MyPlugin,
   reducers: {myreducer}
};

The Plugins Example Application

The example shows the plugins infrastructure power in an interactive way.

The UI allows to add / remove plugins from the base applications, and to configure them using a JSON object with plugins configuration properties.