diff --git a/package.json b/package.json index c1db9538..a0a84167 100644 --- a/package.json +++ b/package.json @@ -68,6 +68,7 @@ "dependencies": { "bricks.js": "^1.7.0", "fuzzy": "^0.1.1", + "html-to-react": "^1.0.0", "js-base64": "^2.1.9", "json-loader": "^0.5.4", "localforage": "^1.4.2", diff --git a/src/components/ControlPane.js b/src/components/ControlPane.js index a86ecaf5..59beb698 100644 --- a/src/components/ControlPane.js +++ b/src/components/ControlPane.js @@ -6,14 +6,17 @@ export default class ControlPane extends React.Component { controlFor(field) { const { entry, getMedia, onChange, onAddMedia, onRemoveMedia } = this.props; const widget = Widgets[field.get('widget')] || Widgets._unknown; - return React.createElement(widget.Control, { - field: field, - value: entry.getIn(['data', field.get('name')]), - onChange: (value) => onChange(entry.setIn(['data', field.get('name')], value)), - onAddMedia: onAddMedia, - onRemoveMedia: onRemoveMedia, - getMedia: getMedia - }); + return
+ + {React.createElement(widget.Control, { + field: field, + value: entry.getIn(['data', field.get('name')]), + onChange: (value) => onChange(entry.setIn(['data', field.get('name')], value)), + onAddMedia: onAddMedia, + onRemoveMedia: onRemoveMedia, + getMedia: getMedia + })} +
; } render() { diff --git a/src/components/PreviewPane.css b/src/components/PreviewPane.css new file mode 100644 index 00000000..6bf62a0a --- /dev/null +++ b/src/components/PreviewPane.css @@ -0,0 +1,6 @@ +.frame { + width: 100%; + height: 100%; + border: none; + background: #fff; +} diff --git a/src/components/PreviewPane.js b/src/components/PreviewPane.js index 731f9c90..24af9229 100644 --- a/src/components/PreviewPane.js +++ b/src/components/PreviewPane.js @@ -1,7 +1,9 @@ import React, { PropTypes } from 'react'; import { render } from 'react-dom'; import ImmutablePropTypes from 'react-immutable-proptypes'; +import { getPreviewTemplate, getPreviewStyles } from '../lib/registry'; import Widgets from './Widgets'; +import styles from './PreviewPane.css'; class Preview extends React.Component { previewFor(field) { @@ -24,23 +26,49 @@ class Preview extends React.Component { } } +Preview.propTypes = { + collection: ImmutablePropTypes.map.isRequired, + entry: ImmutablePropTypes.map.isRequired, + getMedia: PropTypes.func.isRequired, +}; + export default class PreviewPane extends React.Component { constructor(props) { super(props); this.handleIframeRef = this.handleIframeRef.bind(this); + this.widgetFor = this.widgetFor.bind(this); } componentDidUpdate() { this.renderPreview(); } + widgetFor(name) { + const { collection, entry, getMedia } = this.props; + const field = collection.get('fields').find((field) => field.get('name') === name); + const widget = Widgets[field.get('widget')] || Widgets._unknown; + return React.createElement(widget.Preview, { + field: field, + value: entry.getIn(['data', field.get('name')]), + getMedia: getMedia, + }); + } + renderPreview() { - const props = this.props; - render(, this.previewEl); + const props = Object.assign({}, this.props, {widgetFor: this.widgetFor}); + const component = getPreviewTemplate(props.collection.get('name')) || Preview; + + render(React.createElement(component, props), this.previewEl); } handleIframeRef(ref) { if (ref) { + getPreviewStyles().forEach((style) => { + const linkEl = document.createElement('link'); + linkEl.setAttribute('rel', 'stylesheet'); + linkEl.setAttribute('href', style); + ref.contentDocument.head.appendChild(linkEl); + }); this.previewEl = document.createElement('div'); ref.contentDocument.body.appendChild(this.previewEl); this.renderPreview(); @@ -51,7 +79,7 @@ export default class PreviewPane extends React.Component { const { collection } = this.props; if (!collection) { return null; } - return + return } } diff --git a/src/components/Widgets/MarkdownControlElements/VisualEditor/index.js b/src/components/Widgets/MarkdownControlElements/VisualEditor/index.js index 7525bcb5..0f9eb696 100644 --- a/src/components/Widgets/MarkdownControlElements/VisualEditor/index.js +++ b/src/components/Widgets/MarkdownControlElements/VisualEditor/index.js @@ -42,6 +42,7 @@ class VisualEditor extends React.Component { let rawJson; if (props.value !== undefined) { const content = this.markdown.toContent(props.value); + console.log('md: %o', content); rawJson = SlateUtils.encode(content, null, ['mediaproxy'].concat(getPlugins().map(plugin => plugin.id))); } else { rawJson = emptyParagraphBlock; diff --git a/src/index.css b/src/index.css index cd5e3545..4bc2c468 100644 --- a/src/index.css +++ b/src/index.css @@ -59,4 +59,4 @@ button{ line-height: 18px; background-color:#fff; cursor: pointer; -} \ No newline at end of file +} diff --git a/src/index.js b/src/index.js index 13dc95ca..5ef69bb4 100644 --- a/src/index.js +++ b/src/index.js @@ -2,6 +2,7 @@ import React from 'react'; import { render } from 'react-dom'; import { Provider } from 'react-redux'; import { Router } from 'react-router'; +import { registerPreviewStyle,registerPreviewTemplate } from './lib/registry'; import configureStore from './store/configureStore'; import routes from './routing/routes'; import history, { syncHistory } from './routing/history'; @@ -29,3 +30,8 @@ render(( ), el); + +window.CMS = { + registerPreviewStyle: registerPreviewStyle, + registerPreviewTemplate: registerPreviewTemplate +}; diff --git a/src/lib/registry.js b/src/lib/registry.js new file mode 100644 index 00000000..809b9784 --- /dev/null +++ b/src/lib/registry.js @@ -0,0 +1,20 @@ +const registry = { + templates: {}, + previewStyles: [] +}; + +export function registerPreviewStyle(style) { + registry.previewStyles.push(style); +} + +export function registerPreviewTemplate(name, component) { + registry.templates[name] = component; +} + +export function getPreviewTemplate(name) { + return registry.templates[name]; +} + +export function getPreviewStyles() { + return registry.previewStyles; +}