Pass plugins via context instead of using Redux store
This commit is contained in:
parent
d22a4da057
commit
986e36c137
@ -1,5 +1,4 @@
|
|||||||
export const SWITCH_VISUAL_MODE = 'SWITCH_VISUAL_MODE';
|
export const SWITCH_VISUAL_MODE = 'SWITCH_VISUAL_MODE';
|
||||||
export const REGISTER_COMPONENT = 'REGISTER_COMPONENT';
|
|
||||||
|
|
||||||
export function switchVisualMode(useVisualMode) {
|
export function switchVisualMode(useVisualMode) {
|
||||||
return {
|
return {
|
||||||
@ -7,10 +6,3 @@ export function switchVisualMode(useVisualMode) {
|
|||||||
payload: useVisualMode
|
payload: useVisualMode
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function registerComponent(options) {
|
|
||||||
return {
|
|
||||||
type: REGISTER_COMPONENT,
|
|
||||||
payload: options
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
10
src/index.js
10
src/index.js
@ -14,7 +14,7 @@ const store = configureStore();
|
|||||||
// Create an enhanced history that syncs navigation events with the store
|
// Create an enhanced history that syncs navigation events with the store
|
||||||
syncHistory(store);
|
syncHistory(store);
|
||||||
|
|
||||||
initPluginAPI(store);
|
const Plugin = initPluginAPI();
|
||||||
|
|
||||||
const el = document.createElement('div');
|
const el = document.createElement('div');
|
||||||
el.id = 'root';
|
el.id = 'root';
|
||||||
@ -22,8 +22,10 @@ document.body.appendChild(el);
|
|||||||
|
|
||||||
render((
|
render((
|
||||||
<Provider store={store}>
|
<Provider store={store}>
|
||||||
<Router history={history}>
|
<Plugin>
|
||||||
{routes}
|
<Router history={history}>
|
||||||
</Router>
|
{routes}
|
||||||
|
</Router>
|
||||||
|
</Plugin>
|
||||||
</Provider>
|
</Provider>
|
||||||
), el);
|
), el);
|
||||||
|
@ -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 plugins = { editor: List() };
|
||||||
const requiredEditorComponentProperties = ['label', 'fields', 'detect', 'fromBlock', 'toBlock'];
|
|
||||||
|
|
||||||
const checkConfigKeys = (config, requiredProps) => {
|
const catchesNothing = /.^/;
|
||||||
for (var i = requiredProps.length; i--;) {
|
const EditorComponent = Record({
|
||||||
if (!config.hasOwnProperty(requiredProps[i])) return false;
|
id: null,
|
||||||
}
|
label: 'unnamed component',
|
||||||
return true;
|
icon: 'exclamation-triangle',
|
||||||
};
|
fields: [],
|
||||||
|
pattern: catchesNothing,
|
||||||
const wrap = (func) => function() {
|
fromBlock: function(match) { return {}; },
|
||||||
func.apply(null, arguments);
|
toBlock: function(attributes) { return 'Plugin'; },
|
||||||
};
|
toPreview: function(attributes) { return 'Plugin'; }
|
||||||
|
});
|
||||||
|
|
||||||
function CMS() {
|
function CMS() {
|
||||||
this.registerEditorComponent = (config) => {
|
this.registerEditorComponent = (config) => {
|
||||||
if (checkConfigKeys(config, requiredEditorComponentProperties)) {
|
const configObj = new EditorComponent({
|
||||||
const configObj = {
|
id: config.id || config.label.replace(/[^A-Z0-9]+/ig, '_'),
|
||||||
label: config.label || 'unnamed',
|
label: config.label,
|
||||||
icon: config.icon || 'exclamation-triangle',
|
icon: config.icon,
|
||||||
fields: config.fields,
|
fields: config.fields,
|
||||||
detect: wrap(config.detect),
|
pattern: config.pattern,
|
||||||
fromBlock: wrap(config.fromBlock),
|
fromBlock: _.isFunction(config.fromBlock) ? config.fromBlock.bind(null) : null,
|
||||||
toBlock: wrap(config.toBlock),
|
toBlock: _.isFunction(config.toBlock) ? config.toBlock.bind(null) : null,
|
||||||
toPreview: config.toPreview ? wrap(config.toPreview) : wrap(config.toBlock)
|
toPreview: _.isFunction(config.toPreview) ? config.toPreview.bind(null) : config.toBlock.bind(null)
|
||||||
};
|
});
|
||||||
storeRef.dispatch(registerComponent(configObj));
|
|
||||||
} else {
|
plugins.editor = plugins.editor.push(configObj);
|
||||||
const label = config.label || 'unnamed';
|
|
||||||
window.console && console.error(`The provided component configuration for ${label} is incorrect.`);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export const initPluginAPI = (store) => {
|
|
||||||
storeRef = store;
|
class Plugin extends Component {
|
||||||
window.CMS = new CMS();
|
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;
|
||||||
};
|
};
|
||||||
|
@ -1,12 +1,10 @@
|
|||||||
import { Map, List } from 'immutable';
|
import { Map } from 'immutable';
|
||||||
import { SWITCH_VISUAL_MODE, REGISTER_COMPONENT } from '../actions/editor';
|
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) {
|
switch (action.type) {
|
||||||
case SWITCH_VISUAL_MODE:
|
case SWITCH_VISUAL_MODE:
|
||||||
return state.setIn(['useVisualMode'], action.payload);
|
return state.setIn(['useVisualMode'], action.payload);
|
||||||
case REGISTER_COMPONENT:
|
|
||||||
return state.updateIn(['registeredComponents'], list => list.push(action.payload));
|
|
||||||
default:
|
default:
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user