Basic editing with some widgets
This commit is contained in:
24
src/components/ControlPane.js
Normal file
24
src/components/ControlPane.js
Normal file
@ -0,0 +1,24 @@
|
||||
import React from 'react';
|
||||
import Widgets from './Widgets';
|
||||
|
||||
export default class ControlPane extends React.Component {
|
||||
controlFor(field) {
|
||||
const { entry } = this.props;
|
||||
const widget = Widgets[field.get('widget')] || Widgets._unknown;
|
||||
return React.createElement(widget.Control, {
|
||||
key: field.get('name'),
|
||||
field: field,
|
||||
value: entry.get(field.get('name')),
|
||||
onChange: (value) => this.props.onChange(entry.set(field.get('name'), value))
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
const { collection } = this.props;
|
||||
if (!collection) { return null; }
|
||||
|
||||
return <div>
|
||||
{collection.get('fields').map((field) => <div>{this.controlFor(field)}</div>)}
|
||||
</div>;
|
||||
}
|
||||
}
|
33
src/components/EntryEditor.js
Normal file
33
src/components/EntryEditor.js
Normal file
@ -0,0 +1,33 @@
|
||||
import React from 'react';
|
||||
import ControlPane from './ControlPane';
|
||||
import PreviewPane from './PreviewPane';
|
||||
|
||||
export default class EntryEditor extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {entry: props.entry};
|
||||
this.handleChange = this.handleChange.bind(this);
|
||||
}
|
||||
|
||||
handleChange(entry) {
|
||||
console.log('Got new entry: %o', entry.toObject());
|
||||
this.setState({entry: entry});
|
||||
}
|
||||
|
||||
render() {
|
||||
const { collection, entry } = this.props;
|
||||
|
||||
return <div>
|
||||
<h1>Entry in {collection.get('label')}</h1>
|
||||
<h2>{entry && entry.get('title')}</h2>
|
||||
<div className="cms-container">
|
||||
<div className="cms-control-pane">
|
||||
<ControlPane collection={collection} entry={this.state.entry} onChange={this.handleChange}/>
|
||||
</div>
|
||||
<div className="cms-preview-pane">
|
||||
<PreviewPane collection={collection} entry={this.state.entry}/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
}
|
23
src/components/PreviewPane.js
Normal file
23
src/components/PreviewPane.js
Normal file
@ -0,0 +1,23 @@
|
||||
import React from 'react';
|
||||
import Widgets from './Widgets';
|
||||
|
||||
export default class PreviewPane extends React.Component {
|
||||
previewFor(field) {
|
||||
const { entry } = this.props;
|
||||
const widget = Widgets[field.get('widget')] || Widgets._unknown;
|
||||
return React.createElement(widget.Preview, {
|
||||
key: field.get('name'),
|
||||
field: field,
|
||||
value: entry.get(field.get('name'))
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
const { collection } = this.props;
|
||||
if (!collection) { return null; }
|
||||
|
||||
return <div>
|
||||
{collection.get('fields').map((field) => <div>{this.previewFor(field)}</div>)}
|
||||
</div>;
|
||||
}
|
||||
}
|
30
src/components/Widgets.js
Normal file
30
src/components/Widgets.js
Normal file
@ -0,0 +1,30 @@
|
||||
import UnknownControl from './widgets/UnknownControl';
|
||||
import UnknownPreview from './widgets/UnknownPreview';
|
||||
import StringControl from './widgets/StringControl';
|
||||
import StringPreview from './widgets/StringPreview';
|
||||
import MarkdownControl from './widgets/MarkdownControl';
|
||||
import MarkdownPreview from './widgets/MarkdownPreview';
|
||||
import ImageControl from './widgets/ImageControl';
|
||||
import ImagePreview from './widgets/ImagePreview';
|
||||
|
||||
|
||||
const Widgets = {
|
||||
_unknown: {
|
||||
Control: UnknownControl,
|
||||
Preview: UnknownPreview
|
||||
},
|
||||
string: {
|
||||
Control: StringControl,
|
||||
Preview: StringPreview
|
||||
},
|
||||
markdown: {
|
||||
Control: MarkdownControl,
|
||||
Preview: MarkdownPreview
|
||||
},
|
||||
image: {
|
||||
Control: ImageControl,
|
||||
Preview: ImagePreview
|
||||
}
|
||||
};
|
||||
|
||||
export default Widgets;
|
16
src/components/Widgets/ImageControl.js
Normal file
16
src/components/Widgets/ImageControl.js
Normal file
@ -0,0 +1,16 @@
|
||||
import React from 'react';
|
||||
|
||||
export default class ImageControl extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.handleChange = this.handleChange.bind(this);
|
||||
}
|
||||
|
||||
handleChange(e) {
|
||||
this.props.onChange(e.target.value);
|
||||
}
|
||||
|
||||
render() {
|
||||
return <input type="file" onChange={this.handleChange}/>;
|
||||
}
|
||||
}
|
13
src/components/Widgets/ImagePreview.js
Normal file
13
src/components/Widgets/ImagePreview.js
Normal file
@ -0,0 +1,13 @@
|
||||
import React from 'react';
|
||||
|
||||
export default class ImagePreview extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
}
|
||||
|
||||
render() {
|
||||
const { value } = this.props;
|
||||
|
||||
return value ? <img src={value}/> : null;
|
||||
}
|
||||
}
|
40
src/components/Widgets/MarkdownControl.js
Normal file
40
src/components/Widgets/MarkdownControl.js
Normal file
@ -0,0 +1,40 @@
|
||||
import React from 'react';
|
||||
import {Editor, EditorState, RichUtils} from 'draft-js';
|
||||
import {stateToMarkdown} from 'draft-js-export-markdown';
|
||||
import {stateFromMarkdown} from 'draft-js-import-markdown';
|
||||
|
||||
export default class MarkdownControl extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
editorState: EditorState.createWithContent(stateFromMarkdown(props.value || ''))
|
||||
};
|
||||
this.handleChange = this.handleChange.bind(this);
|
||||
this.handleKeyCommand = this.handleKeyCommand.bind(this);
|
||||
}
|
||||
|
||||
handleChange(editorState) {
|
||||
const content = editorState.getCurrentContent();
|
||||
this.setState({editorState});
|
||||
this.props.onChange(stateToMarkdown(content));
|
||||
}
|
||||
|
||||
handleKeyCommand(command) {
|
||||
const newState = RichUtils.handleKeyCommand(this.state.editorState, command);
|
||||
if (newState) {
|
||||
this.handleChange(newState);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
render() {
|
||||
const {editorState} = this.state;
|
||||
return (
|
||||
<Editor
|
||||
editorState={editorState}
|
||||
onChange={this.handleChange}
|
||||
handleKeyCommand={this.handleKeyCommand}
|
||||
/>);
|
||||
}
|
||||
}
|
17
src/components/Widgets/MarkdownPreview.js
Normal file
17
src/components/Widgets/MarkdownPreview.js
Normal file
@ -0,0 +1,17 @@
|
||||
import React from 'react';
|
||||
import CommonMark from 'commonmark';
|
||||
import ReactRenderer from'commonmark-react-renderer';
|
||||
|
||||
const parser = new CommonMark.Parser();
|
||||
const renderer = new ReactRenderer();
|
||||
|
||||
export default class MarkdownPreview extends React.Component {
|
||||
render() {
|
||||
const { value } = this.props;
|
||||
console.log(value);
|
||||
if (value == null) { return null; }
|
||||
|
||||
const ast = parser.parse(value);
|
||||
return React.createElement.apply(React, ['div', {}].concat(renderer.render(ast)));
|
||||
}
|
||||
}
|
16
src/components/Widgets/StringControl.js
Normal file
16
src/components/Widgets/StringControl.js
Normal file
@ -0,0 +1,16 @@
|
||||
import React from 'react';
|
||||
|
||||
export default class StringControl extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.handleChange = this.handleChange.bind(this);
|
||||
}
|
||||
|
||||
handleChange(e) {
|
||||
this.props.onChange(e.target.value);
|
||||
}
|
||||
|
||||
render() {
|
||||
return <input value={this.props.value} onChange={this.handleChange}/>;
|
||||
}
|
||||
}
|
9
src/components/Widgets/StringPreview.js
Normal file
9
src/components/Widgets/StringPreview.js
Normal file
@ -0,0 +1,9 @@
|
||||
import React from 'react';
|
||||
|
||||
export default class StringPreview extends React.Component {
|
||||
render() {
|
||||
const { value } = this.props;
|
||||
|
||||
return <span>{value}</span>;
|
||||
}
|
||||
}
|
10
src/components/Widgets/UnknownControl.js
Normal file
10
src/components/Widgets/UnknownControl.js
Normal file
@ -0,0 +1,10 @@
|
||||
import React from 'react';
|
||||
|
||||
export default class UnknownControl extends React.Component {
|
||||
render() {
|
||||
const { field } = this.props;
|
||||
console.log('field: %o', field.toObject());
|
||||
|
||||
return <div>No control for widget '{field.get('widget')}'.</div>;
|
||||
}
|
||||
}
|
9
src/components/Widgets/UnknownPreview.js
Normal file
9
src/components/Widgets/UnknownPreview.js
Normal file
@ -0,0 +1,9 @@
|
||||
import React from 'react';
|
||||
|
||||
export default class UnknownPreview extends React.Component {
|
||||
render() {
|
||||
const { field } = this.props;
|
||||
|
||||
return <div>No preview for widget '{field.widget}'.</div>;
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user