diff --git a/package.json b/package.json
index fd14f94d5c..9bc8a9e184 100644
--- a/package.json
+++ b/package.json
@@ -46,6 +46,7 @@
"mocha": "2.4.5",
"ncp": "2.0.0",
"parallelshell": "1.2.0",
+ "raw-loader": "0.5.1",
"react-addons-css-transition-group": "0.14.8",
"react-addons-test-utils": "0.14.8",
"react-hot-loader": "1.3.0",
diff --git a/web/client/components/data/template/jsx/Template.jsx b/web/client/components/data/template/jsx/Template.jsx
index 6255bc0553..2b81f7066d 100644
--- a/web/client/components/data/template/jsx/Template.jsx
+++ b/web/client/components/data/template/jsx/Template.jsx
@@ -13,12 +13,14 @@ const Template = React.createClass({
propTypes: {
template: React.PropTypes.oneOfType([React.PropTypes.string, React.PropTypes.func]),
model: React.PropTypes.object,
- renderContent: React.PropTypes.func
+ renderContent: React.PropTypes.func,
+ onError: React.PropTypes.func
},
getDefaultProps() {
return {
template: "",
- model: {}
+ model: {},
+ onError: () => {}
};
},
componentWillMount() {
@@ -45,7 +47,11 @@ const Template = React.createClass({
},
parseTemplate(temp) {
let template = (typeof temp === 'function') ? temp() : temp;
- this.comp = Babel.transform(template, { presets: ['es2015', 'react', 'stage-0'] }).code;
+ try {
+ this.comp = Babel.transform(template, { presets: ['es2015', 'react', 'stage-0'] }).code;
+ } catch(e) {
+ this.props.onError(e.message);
+ }
}
});
diff --git a/web/client/examples/plugins/actions/config.js b/web/client/examples/plugins/actions/config.js
index be489c344c..9fabd6381d 100644
--- a/web/client/examples/plugins/actions/config.js
+++ b/web/client/examples/plugins/actions/config.js
@@ -6,6 +6,7 @@
* LICENSE file in the root directory of this source tree.
*/
const SAVE_PLUGIN_CONFIG = 'SAVE_PLUGIN_CONFIG';
+const COMPILE_ERROR = 'COMPILE_ERROR';
function savePluginConfig(plugin, cfg) {
return {
@@ -15,4 +16,18 @@ function savePluginConfig(plugin, cfg) {
};
}
-module.exports = {SAVE_PLUGIN_CONFIG, savePluginConfig};
+function compileError(message) {
+ return {
+ type: COMPILE_ERROR,
+ message
+ };
+}
+
+function resetError() {
+ return {
+ type: COMPILE_ERROR,
+ message: null
+ };
+}
+
+module.exports = {SAVE_PLUGIN_CONFIG, COMPILE_ERROR, savePluginConfig, compileError, resetError};
diff --git a/web/client/examples/plugins/app.jsx b/web/client/examples/plugins/app.jsx
index bf5dd0f819..4bf9a905b9 100644
--- a/web/client/examples/plugins/app.jsx
+++ b/web/client/examples/plugins/app.jsx
@@ -25,6 +25,9 @@ const startApp = () => {
const {plugins} = require('./plugins');
+ let userPlugin;
+ const Template = require('../../components/data/template/jsx/Template');
+
let pluginsCfg = {
standard: ['Map', 'Toolbar']
};
@@ -38,12 +41,33 @@ const startApp = () => {
const SaveAndLoad = require('./components/SaveAndLoad');
const Debug = require('../../components/development/Debug');
- const store = require('./store')(plugins);
- const {savePluginConfig} = require('./actions/config');
+ const assign = require('object-assign');
+ const codeSample = require("raw!./sample.js.raw");
+
+ let customReducers;
+
+ const context = require('./context');
+
+ const customReducer = (state={}, action) => {
+ if (customReducers) {
+ const newState = assign({}, state);
+ Object.keys(customReducers).forEach((stateKey) => {
+ assign(newState, {[stateKey]: customReducers[stateKey](state[stateKey], action)});
+ });
+ return newState;
+ }
+ return state;
+ };
+
+ const store = require('./store')(plugins, customReducer);
+
+ const {savePluginConfig, compileError, resetError} = require('./actions/config');
require('./assets/css/plugins.css');
+ const Babel = require('babel-standalone');
+
let mapType = 'leaflet';
const Localized = connect((state) => ({
@@ -71,8 +95,39 @@ const startApp = () => {
callback();
};
+ const customPlugin = (callback, code) => {
+ /*eslint-disable */
+ const require = context;
+ try {
+ customReducers = eval(Babel.transform(code, { presets: ['es2015', 'react', 'stage-0'] }).code).reducers || null;
+
+ /*eslint-enable */
+ userPlugin = connect(() => ({
+ template: code,
+ renderContent: (comp) => {
+ /*eslint-disable */
+ return eval(comp).Plugin;
+ /*eslint-enable */
+ },
+ getReducers() {
+ return this.comp;
+ }
+ }), {
+ onError: compileError
+ })(Template);
+ store.dispatch(resetError());
+ callback();
+ } catch(e) {
+ store.dispatch(compileError(e.message));
+ }
+ };
+
const PluginConfigurator = require('./components/PluginConfigurator');
+ const PluginCreator = connect((state) => ({
+ error: state.pluginsConfig && state.pluginsConfig.error
+ }))(require('./components/PluginCreator'));
+
const renderPlugins = (callback) => {
return Object.keys(plugins).map((plugin) => {
const pluginName = plugin.substring(0, plugin.length - 6);
@@ -93,12 +148,10 @@ const startApp = () => {
name: plugin,
hide: isHidden(plugin),
cfg: userCfg[plugin + 'Plugin'] || {}
- }))
+ })).concat(userPlugin ? ['My'] : [])
};
};
- const assign = require('object-assign');
-
const changeMapType = (callback, e) => {
mapType = e.target.options[e.target.selectedIndex].value;
callback();
@@ -131,6 +184,10 @@ const startApp = () => {
}
};
+ const getPlugins = () => {
+ return assign({}, plugins, userPlugin ? {MyPlugin: {MyPlugin: userPlugin}} : {});
+ };
+
const renderPage = () => {
ReactDOM.render(
(
@@ -146,11 +203,12 @@ const startApp = () => {