# Add a new plugin extension This section shows how to add a plugin using the extension support in MapStore without re-compilation of the bundle of the geonode-mapstore-cient applications. This new extensibility should be used for simple plugins. ## Setup extension Navigate to the `/opt/geonode-project/my_geonode/src/my_geonode/` directory ```shell cd /opt/geonode-project/my_geonode/src/my_geonode/ ``` Run the create script using the mapstore project ```shell npx @mapstore/project create extension ``` These are the properties requested by the create script. MyGeoNodeExtension is the name of the extension and it should be a unique identifier ```shell - Name of extension (default Extension): MyGeoNodeExtension - Name of project (default mapstore-extension): client - Run npm install after creation setup (yes/no default yes): no ``` Create an index.json file inside the `/opt/geonode-project/my_geonode/src/my_geonode/static/mapstore/extensions` directory ```shell mkdir /opt/geonode-project/my_geonode/src/my_geonode/static/mapstore mkdir /opt/geonode-project/my_geonode/src/my_geonode/static/mapstore/extensions touch /opt/geonode-project/my_geonode/src/my_geonode/static/mapstore/extensions/index.json ``` ``` /opt/geonode-project/my_geonode/src/ |-- ... |-- my_geonode/ | |-- ... | |-- client/ | +-- static/ | |-- ... | +-- mapstore/ | |-- ... | +-- extensions/ | |-- ... | +-- index.json |-- ... ``` Configure the `extensions/index.json` file to include the new extension ```shell vim /opt/geonode-project/my_geonode/src/my_geonode/static/mapstore/extensions/index.json ``` Paste this configuration inside the `index.json` ```json { "MyGeoNodeExtension": { "bundle": "MyGeoNodeExtension/index.js", "translations": "MyGeoNodeExtension/translations", "assets": "MyGeoNodeExtension/assets" } } ``` Navigate to the extension client folder ```shell cd /opt/geonode-project/my_geonode/src/my_geonode/client/ ``` Add license file if missing LICENSE.txt Add the `postCompile.js` script file to move the compiled bundle in the correct directory ```shell touch /opt/geonode-project/my_geonode/src/my_geonode/client/postCompile.js vim /opt/geonode-project/my_geonode/src/my_geonode/client/postCompile.js ``` ```js const fs = require('fs-extra'); const path = require('path'); const extensionsPath = path.join(__dirname, '..', 'static', 'mapstore', 'extensions'); const extensionIndexPath = path.join(extensionsPath, 'index.json'); const extensionIndex = fs.existsSync(extensionIndexPath) ? require(extensionIndexPath) : {}; const EXTENSION_NAME = 'MyGeoNodeExtension'; let error = false; Object.keys(extensionIndex).forEach(extensionName => { const endpoints = extensionIndex[extensionName]; Object.keys(endpoints).forEach(key => { if (endpoints[key].match('http://localhost:8082/extension')) { error = true; console.error(''); console.error('//////////////////////////////////////'); console.error('/// Error: dev url ' + key + ': ' + endpoints[key]); console.error('/// -> please replace http://localhost:8082/extension with /static/mapstore/extensions/' + extensionName); console.error('//////////////////////////////////////'); console.error(''); } }); }); if (!error) { fs.moveSync(path.resolve(__dirname, 'dist'), path.resolve(extensionsPath, EXTENSION_NAME), { overwrite: true }); } ``` Modify the package.json to use the new postCompile.js script and to target the mapstore version 2022.01.xx. ```shell vim /opt/geonode-project/my_geonode/src/my_geonode/client/package.json ``` ```diff "scripts": { - "compile": "mapstore-project compile extension", + "compile": "mapstore-project compile extension && node ./postCompile.js", "lint": "eslint js --ext .jsx,.js", "start": "mapstore-project start extension", "test": "mapstore-project test extension", "test:watch": "mapstore-project test:watch extension" }, ... "dependencies": { - "mapstore": "git+https://github.com/geosolutions-it/MapStore2.git#master" + "mapstore": "git+https://github.com/geosolutions-it/MapStore2.git#2022.01.xx" }, ``` Install all needed dependencies ```shell cd /opt/geonode-project/my_geonode/src/my_geonode/client/ npm install ``` Compile the bundle to verify if all the scripts are configured correctly ```shell cd /opt/geonode-project/my_geonode/src/my_geonode/client/ npm run compile ``` After the compile command executes, a new folder is generated inside the extensions directory ```shell /opt/geonode-project/my_geonode/src/ |-- ... |-- my_geonode/ | |-- ... | +-- static/ | |-- ... | +-- mapstore/ | |-- ... | +-- extensions/ | |-- MyGeoNodeExtension/ | +-- index.json |-- ... ``` Edit the `/opt/geonode-project/my_geonode/src/my_geonode/templates/geonode-mapstore-client/_geonode_config.html` template to include this new extension ```shell vim /opt/geonode-project/my_geonode/src/my_geonode/templates/geonode-mapstore-client/_geonode_config.html ``` ```django {% extends 'geonode-mapstore-client/_geonode_config.html' %} {% block override_local_config %} {% endblock %} ``` After these steps a box with a message is visible on the map viewer. ## Develop the extension Temporarily edit the `/opt/geonode-project/my_geonode/src/my_geonode/static/mapstore/extensions/index.json` file using the dev endpoints instead of the static ones (remember to restore this value to the static one) ```shell vim /opt/geonode-project/my_geonode/src/my_geonode/static/mapstore/extensions/index.json ``` ```json { "MyGeoNodeExtension": { "bundle": "http://localhost:8082/extension/index.js", "assets": "http://localhost:8082/extension/assets", "translations": "http://localhost:8082/extension/translations" } } ``` Add the development configuration to the `/opt/geonode-project/my_geonode/src/my_geonode/templates/geonode-mapstore-client/_geonode_config.html` template ```shell vim /opt/geonode-project/my_geonode/src/my_geonode/templates/geonode-mapstore-client/_geonode_config.html ``` ```diff {% extends 'geonode-mapstore-client/_geonode_config.html' %} {% block override_local_config %} {% endblock %} ``` Navigate to the `/opt/geonode-project/my_geonode/src/my_geonode/client/` folder and start the extension endpoints ```shell cd /opt/geonode-project/my_geonode/src/my_geonode/client/ npm start ``` Replace the content of the `/opt/geonode-project/my_geonode/src/my_geonode/client/js/extension/plugins/Extension.jsx` with a new extension. An example could be a floating box that shows the value of the center of the map ```shell vim /opt/geonode-project/my_geonode/src/my_geonode/client/js/extension/plugins/Extension.jsx ``` ```jsx import React from 'react'; import PropTypes from 'prop-types'; import { connect } from 'react-redux'; import { createSelector } from 'reselect'; import { mapSelector } from '@mapstore/framework/selectors/map'; function MyGeoNodeExtension({ center }) { return (
Map Center ({center.crs})
x: {center?.x?.toFixed(6)} {' | '} y: {center?.y?.toFixed(6)}
); } MyGeoNodeExtension.propTypes = { center: PropTypes.object }; MyGeoNodeExtension.defaultProps = { center: {} }; const MyGeoNodeExtensionPlugin = connect( createSelector([ mapSelector ], (map) => ({ center: map?.center })), {} )(MyGeoNodeExtension); export default { name: __MAPSTORE_EXTENSION_CONFIG__.name, component: MyGeoNodeExtensionPlugin, containers: {}, epics: {}, reducers: {} }; ``` ## Build the extension Restore the `/opt/geonode-project/my_geonode/src/my_geonode/static/mapstore/extensions/index.json` points to `MyGeoNodeExtension` static path for the extension ```shell vim /opt/geonode-project/my_geonode/src/my_geonode/static/mapstore/extensions/index.json ``` ```json { "MyGeoNodeExtension": { "bundle": "MyGeoNodeExtension/index.js", "assets": "MyGeoNodeExtension/assets", "translations": "MyGeoNodeExtension/translations" } } ``` Remove the development configuration from the `_geonode_config.html` template ```shell vim /opt/geonode-project/my_geonode/src/my_geonode/templates/geonode-mapstore-client/_geonode_config.html ``` ```diff {% extends 'geonode-mapstore-client/_geonode_config.html' %} {% block override_local_config %} {% endblock %} ``` Compile the bundle ```shell cd /opt/geonode-project/my_geonode/src/my_geonode/client/ npm run compile ``` Now the new extension will be available in the map_viewer page with the changes applied during the development