Pass plugins via context instead of using Redux store

This commit is contained in:
Cássio Zen 2016-08-18 09:09:54 -03:00
parent d22a4da057
commit 986e36c137
4 changed files with 58 additions and 48 deletions

View File

@ -1,5 +1,4 @@
export const SWITCH_VISUAL_MODE = 'SWITCH_VISUAL_MODE';
export const REGISTER_COMPONENT = 'REGISTER_COMPONENT';
export function switchVisualMode(useVisualMode) {
return {
@ -7,10 +6,3 @@ export function switchVisualMode(useVisualMode) {
payload: useVisualMode
};
}
export function registerComponent(options) {
return {
type: REGISTER_COMPONENT,
payload: options
};
}

View File

@ -14,7 +14,7 @@ const store = configureStore();
// Create an enhanced history that syncs navigation events with the store
syncHistory(store);
initPluginAPI(store);
const Plugin = initPluginAPI();
const el = document.createElement('div');
el.id = 'root';
@ -22,8 +22,10 @@ document.body.appendChild(el);
render((
<Provider store={store}>
<Router history={history}>
{routes}
</Router>
<Plugin>
<Router history={history}>
{routes}
</Router>
</Plugin>
</Provider>
), el);

View File

@ -1,40 +1,58 @@
import { registerComponent } from '../actions/editor';
import { Component, PropTypes, Children } from 'react';
import { List, Record } from 'immutable';
import _ from 'lodash';
let storeRef;
const requiredEditorComponentProperties = ['label', 'fields', 'detect', 'fromBlock', 'toBlock'];
const plugins = { editor: List() };
const checkConfigKeys = (config, requiredProps) => {
for (var i = requiredProps.length; i--;) {
if (!config.hasOwnProperty(requiredProps[i])) return false;
}
return true;
};
const wrap = (func) => function() {
func.apply(null, arguments);
};
const catchesNothing = /.^/;
const EditorComponent = Record({
id: null,
label: 'unnamed component',
icon: 'exclamation-triangle',
fields: [],
pattern: catchesNothing,
fromBlock: function(match) { return {}; },
toBlock: function(attributes) { return 'Plugin'; },
toPreview: function(attributes) { return 'Plugin'; }
});
function CMS() {
this.registerEditorComponent = (config) => {
if (checkConfigKeys(config, requiredEditorComponentProperties)) {
const configObj = {
label: config.label || 'unnamed',
icon: config.icon || 'exclamation-triangle',
fields: config.fields,
detect: wrap(config.detect),
fromBlock: wrap(config.fromBlock),
toBlock: wrap(config.toBlock),
toPreview: config.toPreview ? wrap(config.toPreview) : wrap(config.toBlock)
};
storeRef.dispatch(registerComponent(configObj));
} else {
const label = config.label || 'unnamed';
window.console && console.error(`The provided component configuration for ${label} is incorrect.`);
}
const configObj = new EditorComponent({
id: config.id || config.label.replace(/[^A-Z0-9]+/ig, '_'),
label: config.label,
icon: config.icon,
fields: config.fields,
pattern: config.pattern,
fromBlock: _.isFunction(config.fromBlock) ? config.fromBlock.bind(null) : null,
toBlock: _.isFunction(config.toBlock) ? config.toBlock.bind(null) : null,
toPreview: _.isFunction(config.toPreview) ? config.toPreview.bind(null) : config.toBlock.bind(null)
});
plugins.editor = plugins.editor.push(configObj);
};
}
export const initPluginAPI = (store) => {
storeRef = store;
window.CMS = new CMS();
class Plugin extends Component {
getChildContext() {
return { plugins: plugins };
}
render() {
return Children.only(this.props.children);
}
}
Plugin.propTypes = {
children: PropTypes.element.isRequired
};
Plugin.childContextTypes = {
plugins: PropTypes.object
};
export const initPluginAPI = () => {
window.CMS = new CMS();
return Plugin;
};

View File

@ -1,12 +1,10 @@
import { Map, List } from 'immutable';
import { SWITCH_VISUAL_MODE, REGISTER_COMPONENT } from '../actions/editor';
import { Map } from 'immutable';
import { SWITCH_VISUAL_MODE } from '../actions/editor';
const editor = (state = Map({ useVisualMode: true, registeredComponents: List() }), action) => {
const editor = (state = Map({ useVisualMode: true }), action) => {
switch (action.type) {
case SWITCH_VISUAL_MODE:
return state.setIn(['useVisualMode'], action.payload);
case REGISTER_COMPONENT:
return state.updateIn(['registeredComponents'], list => list.push(action.payload));
default:
return state;
}