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

Fixes #1645: custom connect to be used in plugins definition; propert… #1650

Merged
merged 1 commit into from
Mar 28, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,4 @@ _site
.jekyll-metadata
*.lock
docs/developer-guide/reference/
web/client/mapstore/docs/
2 changes: 1 addition & 1 deletion web/client/components/plugins/PluginsContainer.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ const PluginsContainer = React.createClass({
.filter((Plugin) => !Plugin.impl.loadPlugin)
.filter(this.filterPlugins)
.map((Plugin) => <Plugin.impl key={Plugin.id}
{...this.props.params} {...Plugin.cfg} items={Plugin.items}/>);
{...this.props.params} {...Plugin.cfg} pluginCfg={Plugin.cfg} items={Plugin.items}/>);
},
render() {
if (this.props.pluginsConfig) {
Expand Down
2 changes: 1 addition & 1 deletion web/client/plugins/ScaleBox.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
*/

const React = require('react');
const {connect} = require('react-redux');
const {connect} = require('../utils/PluginsUtils');
const {createSelector} = require('reselect');

const {mapSelector} = require('../selectors/map');
Expand Down
20 changes: 20 additions & 0 deletions web/client/utils/PluginsUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
const assign = require('object-assign');
const {omit, isObject, head, isArray, isString} = require('lodash');
const {combineReducers} = require('redux');
const {connect} = require('react-redux');

const {combineEpics} = require('redux-observable');

const {memoize, get} = require('lodash');
Expand Down Expand Up @@ -122,6 +124,11 @@ const getReducers = (plugins) => Object.keys(plugins).map((name) => plugins[name
const getEpics = (plugins) => Object.keys(plugins).map((name) => plugins[name].epics)
.reduce((previous, current) => assign({}, previous, current), {});

const pluginsMergeProps = (stateProps, dispatchProps, ownProps) => {
const {pluginCfg, ...otherProps} = ownProps;
return assign({}, otherProps, stateProps, dispatchProps, pluginCfg || {});
Copy link
Member

@offtherailz offtherailz Mar 28, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Didn't understand how to configure it.
pluginsCfg always wins over stateProps.
Could it be that pluginsCfg can be overridden by stateProps? Or do you mean that all the other Props are overridable while pluginCfg is the way to set fixed config.

can you document it?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pluginCfg is the way to set fixed config, but plugins cfg can be dynamic, using expressions.

};

/**
* Utilities to manage plugins
* @class
Expand Down Expand Up @@ -193,6 +200,19 @@ const PluginsUtils = {
items: getPluginItems(state, plugins, pluginsConfig, name, id, isDefault, loadedPlugins)
};
},
/**
* Custom react-redux connect function that can override state property with plugin config.
* The plugin config properties are taken from the **pluginCfg** property.

* @param {function} [mapStateToProps] state to properties selector
* @param {function} [mapDispatchToProps] dispatchable actions selector
* @param {function} [mergeProps] merge function, if not defined, the internal override applies
* @param {object} [options] connect options (look at react-redux docs for details)
* @returns {function} funtion to be applied to the dumb object to connect it to state / dispatchers
*/
connect: (mapStateToProps, mapDispatchToProps, mergeProps, options) => {
return connect(mapStateToProps, mapDispatchToProps, mergeProps || pluginsMergeProps, options);
},
getMorePrioritizedContainer
};
module.exports = PluginsUtils;
26 changes: 22 additions & 4 deletions web/client/utils/__tests__/PluginUtils-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,23 @@
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree.
*/
const React = require('react');
const ReactDOM = require('react-dom');
const {Provider} = require('react-redux');
const expect = require('expect');
const PluginsUtils = require('../PluginsUtils');
const assign = require('object-assign');
const MapSearchPlugin = require('../../plugins/MapSearch');

describe('PluginsUtils', () => {
beforeEach( () => {

beforeEach((done) => {
document.body.innerHTML = '<div id="container"></div>';
setTimeout(done);
});

afterEach((done) => {
ReactDOM.unmountComponentAtNode(document.getElementById("container"));
document.body.innerHTML = '';

setTimeout(done);
});
it('combineReducers', () => {
Expand Down Expand Up @@ -79,5 +84,18 @@ describe('PluginsUtils', () => {
const epics = PluginsUtils.combineEpics(plugins, appEpics);
expect(typeof epics ).toEqual('function');
});

it('connect', () => {
const MyComponent = (props) => <div>{props.test}</div>;
const Connected = PluginsUtils.connect((state) => ({test: state.test}), {})(MyComponent);
const store = {
dispatch: () => {},
subscribe: () => {},
getState: () => ({
test: "statetest"
})
};
const app = ReactDOM.render(<Provider store={store}><Connected test="propstest" pluginCfg={{test: "plugintest"}}/></Provider>, document.getElementById("container"));
const domElement = ReactDOM.findDOMNode(app);
expect(domElement.innerText).toBe("plugintest");
});
});