Skip to content

Commit

Permalink
Fixes #1619, Fixes #1549, Fixes #1103: notification system and docume… (
Browse files Browse the repository at this point in the history
#1620)

* Fixes #1619, Fixes #1549, Fixes #1103: notification system and documentation of the js api

* Fixes #1624: configuration from url for the api example

* Fixed docs
  • Loading branch information
mbarto authored Mar 22, 2017
1 parent ca49d34 commit 19a0656
Show file tree
Hide file tree
Showing 13 changed files with 458 additions and 417 deletions.
9 changes: 4 additions & 5 deletions docma-config.json
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@
"items": [
{ "label": "Framework", "href": "api/framework"},

{ "separator": true },
{ "label": "JavaScript API", "href": "api/jsapi" },
{ "separator": true },
{ "label": "Plugins", "href": "api/plugins" }

Expand Down Expand Up @@ -120,6 +122,7 @@
"web/client/utils/index.jsdoc",
"web/client/utils/PluginsUtils.js"
],
"jsapi": "web/client/jsapi/MapStore2.js",
"plugins": [
"web/client/plugins/index.jsdoc",
"web/client/plugins/Search.jsx",
Expand All @@ -131,12 +134,8 @@
"./docs/**/*md",
{
"readme": "./README.md",
"site": "./docs/index.md",
"developer-guide": "./docs/developer-guide/index.md",
"plugins-architecture": "./docs/developer-guide/plugins-architecture.md",
"building-and-developing": "./docs/developer-guide/plugins-architecture.md",
"plugins-documentation": "./docs/developer-guide/plugins-documentation.md",
"project-creation-script": "./docs/developer-guide/project-creation-script.md"
"site": "./docs/index.md"
}
]
}
8 changes: 2 additions & 6 deletions docs/developer-guide/plugins-documentation.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ Inside the **plugins** section, several modes can be configured (e.g. desktop or
}
```

Each plugin can be simply listed (and the default configuration is used):
Each plugin can be simply listed (and the default configuration is used):

```js
"plugins": {
Expand All @@ -33,15 +33,11 @@ or fully configured:
...
"desktop": [{
"name": "Map",
"cfg": {
...
}
},
...
]
}
```
Look at each plugin documentation page for a list of available configuration properties.

# Plugins List:
* [Map](map-plugin)
Look at the [plugin reference page](./api/plugins) for a list of available configuration properties.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@
},
"//": "replace react-sortable-items with official on npm when 0.0.10 with remove_deprecated PR in included",
"dependencies": {
"@carnesen/redux-add-action-listener-enhancer": "0.0.1",
"ag-grid": "3.3.3",
"ag-grid-react": "3.3.1",
"axios": "0.11.1",
Expand Down
6 changes: 5 additions & 1 deletion web/client/components/app/StandardRouter.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,13 @@ const {Router, Route, hashHistory} = require('react-router');

const Localized = require('../I18N/Localized');

const assign = require('object-assign');

const Theme = connect((state) => ({
theme: state.theme && state.theme.selectedTheme && state.theme.selectedTheme.id
}))(require('../theme/Theme'));
}), {}, (stateProps, dispatchProps, ownProps) => {
return assign({}, stateProps, dispatchProps, ownProps);
})(require('../theme/Theme'));

const StandardRouter = React.createClass({
propTypes: {
Expand Down
2 changes: 1 addition & 1 deletion web/client/containers/Page.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ const Page = React.createClass({
desktop: [...this.props.pagePluginsConfig.desktop, ...this.props.pluginsConfig.desktop],
mobile: [...this.props.pagePluginsConfig.mobile, ...this.props.pluginsConfig.mobile]
};
return (<PluginsContainer key="{this.props.id}" id={"page-" + this.props.id} className={"page page-" + this.props.id}
return (<PluginsContainer key={this.props.id} id={"page-" + this.props.id} className={"page page-" + this.props.id}
pluginsConfig={pluginsConfig}
plugins={this.props.plugins}
params={this.props.params}
Expand Down
18 changes: 16 additions & 2 deletions web/client/examples/api/init.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,15 @@
function init() {
/*eslint-enable */
var cfg;
var cfgUrl;
var theme;
var embeddedPlugins;
var pluginsCfg;

/*eslint-disable */
cfg = MapStore2.loadConfigFromStorage('mapstore.example.plugins.' + MapStore2.getMapNameFromRequest());
cfg = MapStore2.loadConfigFromStorage('mapstore.example.plugins.' + MapStore2.getParamFromRequest('map'));
cfgUrl = MapStore2.getParamFromRequest('config');
theme = MapStore2.getParamFromRequest('theme');
/*eslint-enable */
embeddedPlugins = {
"desktop": [
Expand All @@ -28,14 +32,24 @@ function init() {
/*eslint-disable */
pluginsCfg = cfg && MapStore2.buildPluginsCfg(cfg.pluginsCfg.standard, cfg.userCfg) || embeddedPlugins;
MapStore2.create('container', {
/*eslint-enable */
plugins: pluginsCfg,
configUrl: cfgUrl,
initialState: cfg && cfg.state && {
defaultState: cfg.state
} || null,
style: cfg && cfg.customStyle,
theme: {
theme,
path: '../../dist/themes'
}
});
MapStore2.onAction('CHANGE_MAP_VIEW', function(action) {
console.log('ZOOM: ' + action.zoom);
});
MapStore2.onStateChange(function(map) {
console.log('STATE ZOOM: ' + map.zoom);
}, function(state) {
return (state.map && state.map.present) || state.map || {}
});
/*eslint-enable */
}
156 changes: 148 additions & 8 deletions web/client/jsapi/MapStore2.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/**
/*
* Copyright 2016, GeoSolutions Sas.
* All rights reserved.
*
Expand All @@ -12,7 +12,7 @@ const StandardApp = require('../components/app/StandardApp');
const LocaleUtils = require('../utils/LocaleUtils');
const {connect} = require('react-redux');

const {configureMap} = require('../actions/config');
const {configureMap, loadMapConfig} = require('../actions/config');

const url = require('url');

Expand Down Expand Up @@ -169,7 +169,7 @@ function loadConfigFromStorage(name = 'mapstore.embedded') {
return null;
}

function getMapNameFromRequest(paramName = 'map') {
function getParamFromRequest(paramName) {
const urlQuery = url.parse(window.location.href, true).query;
return urlQuery[paramName] || null;
}
Expand All @@ -196,7 +196,74 @@ function buildPluginsCfg(plugins, cfg) {
};
}

const actionListeners = {};
let stateChangeListeners = [];
let app;

const getInitialActions = (options) => {
if (!options.initialState) {
if (options.configUrl) {
return [loadMapConfig.bind(null, options.configUrl || defaultConfig)];
}
return [configureMap.bind(null, options.config || defaultConfig)];
}
return [];
};


/**
* MapStore2 JavaScript API. Allows embedding MapStore2 functionalities into
* a standard HTML page.
* @class
*/
const MapStore2 = {
/**
* Instantiates an embedded MapStore2 application in the given container.
* @memberof MapStore2
* @static
* @param {string} container id of the DOM element that should contain the embedded MapStore2
* @param {object} options set of options of the embedded app
*
* The options object can contain the following properties, to configure the app UI and state:
* * **plugins**: list of plugins (and the related configuration) to be included in the app
* look at [Plugins documentation](./plugins-documentation) for further details
* * **config**: map configuration object for the application (look at [Map Configuration](./maps-configuration) for details)
* * **configUrl**: map configuration url for the application (look at [Map Configuration](./maps-configuration) for details)
* * **initialState**: allows setting the initial application state (look at [State Configuration](./app-state-configuration) for details)
*
* Styling can be configured either using a **theme**, or a complete custom **less stylesheet**, using the
* following options properties:
* * **style**: less style to be applied
* * **theme**: theme configuration options:
* * path: path/url of the themes folder related to the current page
* * theme: theme name to be used
*
* ```javascript
* {
* plugins: ['Map', 'ZoomIn', 'ZoomOut'],
* config: {
* map: {
* ...
* }
* },
* configUrl: '...',
* initialState: {
* defaultState: {
* ...
* }
* },
* style: '<custom style>',
* theme: {
* theme: 'mytheme',
* path: 'dist/themes'
* }
* }
* ```
* @example
* MapStore2.create('container', {
* plugins: ['Map']
* });
*/
create(container, options) {
const embedded = require('../containers/Embedded');

Expand All @@ -218,9 +285,9 @@ const MapStore2 = {
}))(require('../components/app/StandardRouter'));

const appStore = require('../stores/StandardStore').bind(null, initialState || {}, {});
const initialActions = options.initialState ? [] : [configureMap.bind(null, options.config || defaultConfig)];
const initialActions = getInitialActions(options);
const appConfig = {
storeOpts,
storeOpts: assign({}, storeOpts, {notify: true}),
appStore,
pluginsDef,
initialActions,
Expand All @@ -242,11 +309,84 @@ const MapStore2 = {
};

const themeCfg = options.theme && assign({}, defaultThemeCfg, options.theme) || defaultThemeCfg;
ReactDOM.render(<StandardApp themeCfg={themeCfg} className="fill" {...appConfig}/>, document.getElementById(container));
app = ReactDOM.render(<StandardApp themeCfg={themeCfg} className="fill" {...appConfig}/>, document.getElementById(container));
app.store.addActionListener((action) => {
(actionListeners[action.type] || []).concat(actionListeners['*'] || []).forEach((listener) => {
listener.call(null, action);
});
});
app.store.subscribe(() => {
stateChangeListeners.forEach(({listener, selector}) => {
listener.call(null, selector(app.store.getState()));
});
});
},
buildPluginsCfg,
getMapNameFromRequest,
loadConfigFromStorage
getParamFromRequest,
loadConfigFromStorage,
/**
* Adds a listener that will be notified of all the MapStore2 events (**actions**), or only some of them.
*
* @memberof MapStore2
* @static
* @param {string} type type of actions to be captured (* for all)
* @param {function} listener function to be called for each launched action; it will receive
* the action as the only argument
* @example
* MapStore2.onAction('CHANGE_MAP_VIEW', function(action) {
* console.log(action.zoom);
* });
*/
onAction: (type, listener) => {
const listeners = actionListeners[type] || [];
listeners.push(listener);
actionListeners[type] = listeners;
},
/**
* Removes an action listener.
*
* @memberof MapStore2
* @static
* @param {string} type type of actions that is captured by the listener (* for all)
* @param {function} listener listener to be removed
* @example
* MapStore2.offAction('CHANGE_MAP_VIEW', listener);
*/
offAction: (type, listener) => {
const listeners = (actionListeners[type] || []).filter((l) => l !== listener);
actionListeners[type] = listeners;
},
/**
* Adds a listener that will be notified of each state update.
*
* @memberof MapStore2
* @static
* @param {function} listener function to be called for each state udpate; it will receive
* the new state as the only argument
* @param {function} [selector] optional function that will produce a partial/derived state
* from the global state before calling the listeners
* @example
* MapStore2.onStateChange(function(map) {
* console.log(map.zoom);
* }, function(state) {
* return (state.map && state.map.present) || state.map || {};
* });
*/
onStateChange: (listener, selector = (state) => state) => {
stateChangeListeners.push({listener, selector});
},
/**
* Removes a state listener.
*
* @memberof MapStore2
* @static
* @param {function} listener listener to be removed
* @example
* MapStore2.offStateChange(listener);
*/
offStateChange: (listener) => {
stateChangeListeners = stateChangeListeners.filter((l) => l !== listener);
}
};

if (!global.Intl ) {
Expand Down
Loading

0 comments on commit 19a0656

Please sign in to comment.