Merge pull request #447 from netlify/kitchen-sink
Add kitchen sink example, restore object/list previews
This commit is contained in:
commit
0adb3df4ae
@ -56,3 +56,89 @@ collections: # A list of collections the CMS should be able to edit
|
|||||||
fields:
|
fields:
|
||||||
- {label: "Name", name: "name", widget: "string"}
|
- {label: "Name", name: "name", widget: "string"}
|
||||||
- {label: "Description", name: "description", widget: "markdown"}
|
- {label: "Description", name: "description", widget: "markdown"}
|
||||||
|
|
||||||
|
- name: "kitchenSink" # all the things in one entry, for documentation and quick testing
|
||||||
|
label: "Kitchen Sink"
|
||||||
|
folder: "_sink"
|
||||||
|
create: true
|
||||||
|
fields:
|
||||||
|
- {label: "Title", name: "title", widget: "string"}
|
||||||
|
- {label: "Boolean", name: "boolean", widget: "boolean", default: true}
|
||||||
|
- {label: "Text", name: "text", widget: "text"}
|
||||||
|
- {label: "Number", name: "number", widget: "number"}
|
||||||
|
- {label: "Markdown", name: "markdown", widget: "markdown"}
|
||||||
|
- {label: "Datetime", name: "datetime", widget: "datetime"}
|
||||||
|
- {label: "Date", name: "date", widget: "date"}
|
||||||
|
- {label: "Image", name: "image", widget: "image"}
|
||||||
|
- {label: "File", name: "file", widget: "file"}
|
||||||
|
- {label: "Select", name: "select", widget: "select", options: ["a", "b", "c"]}
|
||||||
|
- label: "Object"
|
||||||
|
name: "object"
|
||||||
|
widget: "object"
|
||||||
|
fields:
|
||||||
|
- {label: "String", name: "string", widget: "string"}
|
||||||
|
- {label: "Boolean", name: "boolean", widget: "boolean", default: false}
|
||||||
|
- {label: "Text", name: "text", widget: "text"}
|
||||||
|
- {label: "Number", name: "number", widget: "number"}
|
||||||
|
- {label: "Markdown", name: "markdown", widget: "markdown"}
|
||||||
|
- {label: "Datetime", name: "datetime", widget: "datetime"}
|
||||||
|
- {label: "Date", name: "date", widget: "date"}
|
||||||
|
- {label: "Image", name: "image", widget: "image"}
|
||||||
|
- {label: "File", name: "file", widget: "file"}
|
||||||
|
- {label: "Select", name: "select", widget: "select", options: ["a", "b", "c"]}
|
||||||
|
- label: "List"
|
||||||
|
name: "list"
|
||||||
|
widget: "list"
|
||||||
|
fields:
|
||||||
|
- {label: "String", name: "string", widget: "string"}
|
||||||
|
- {label: "Boolean", name: "boolean", widget: "boolean"}
|
||||||
|
- {label: "Text", name: "text", widget: "text"}
|
||||||
|
- {label: "Number", name: "number", widget: "number"}
|
||||||
|
- {label: "Markdown", name: "markdown", widget: "markdown"}
|
||||||
|
- {label: "Datetime", name: "datetime", widget: "datetime"}
|
||||||
|
- {label: "Date", name: "date", widget: "date"}
|
||||||
|
- {label: "Image", name: "image", widget: "image"}
|
||||||
|
- {label: "File", name: "file", widget: "file"}
|
||||||
|
- {label: "Select", name: "select", widget: "select", options: ["a", "b", "c"]}
|
||||||
|
- label: "Object"
|
||||||
|
name: "object"
|
||||||
|
widget: "object"
|
||||||
|
fields:
|
||||||
|
- {label: "String", name: "string", widget: "string"}
|
||||||
|
- {label: "Boolean", name: "boolean", widget: "boolean"}
|
||||||
|
- {label: "Text", name: "text", widget: "text"}
|
||||||
|
- {label: "Number", name: "number", widget: "number"}
|
||||||
|
- {label: "Markdown", name: "markdown", widget: "markdown"}
|
||||||
|
- {label: "Datetime", name: "datetime", widget: "datetime"}
|
||||||
|
- {label: "Date", name: "date", widget: "date"}
|
||||||
|
- {label: "Image", name: "image", widget: "image"}
|
||||||
|
- {label: "File", name: "file", widget: "file"}
|
||||||
|
- {label: "Select", name: "select", widget: "select", options: ["a", "b", "c"]}
|
||||||
|
- label: "List"
|
||||||
|
name: "list"
|
||||||
|
widget: "list"
|
||||||
|
fields:
|
||||||
|
- {label: "String", name: "string", widget: "string"}
|
||||||
|
- {label: "Boolean", name: "boolean", widget: "boolean"}
|
||||||
|
- {label: "Text", name: "text", widget: "text"}
|
||||||
|
- {label: "Number", name: "number", widget: "number"}
|
||||||
|
- {label: "Markdown", name: "markdown", widget: "markdown"}
|
||||||
|
- {label: "Datetime", name: "datetime", widget: "datetime"}
|
||||||
|
- {label: "Date", name: "date", widget: "date"}
|
||||||
|
- {label: "Image", name: "image", widget: "image"}
|
||||||
|
- {label: "File", name: "file", widget: "file"}
|
||||||
|
- {label: "Select", name: "select", widget: "select", options: ["a", "b", "c"]}
|
||||||
|
- label: "Object"
|
||||||
|
name: "object"
|
||||||
|
widget: "object"
|
||||||
|
fields:
|
||||||
|
- {label: "String", name: "string", widget: "string"}
|
||||||
|
- {label: "Boolean", name: "boolean", widget: "boolean"}
|
||||||
|
- {label: "Text", name: "text", widget: "text"}
|
||||||
|
- {label: "Number", name: "number", widget: "number"}
|
||||||
|
- {label: "Markdown", name: "markdown", widget: "markdown"}
|
||||||
|
- {label: "Datetime", name: "datetime", widget: "datetime"}
|
||||||
|
- {label: "Date", name: "date", widget: "date"}
|
||||||
|
- {label: "Image", name: "image", widget: "image"}
|
||||||
|
- {label: "File", name: "file", widget: "file"}
|
||||||
|
- {label: "Select", name: "select", widget: "select", options: ["a", "b", "c"]}
|
||||||
|
File diff suppressed because one or more lines are too long
BIN
example/moby-dick.jpg
Normal file
BIN
example/moby-dick.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 10 KiB |
@ -147,7 +147,7 @@
|
|||||||
"react-simple-dnd": "^0.1.2",
|
"react-simple-dnd": "^0.1.2",
|
||||||
"react-sortable": "^1.2.0",
|
"react-sortable": "^1.2.0",
|
||||||
"react-split-pane": "^0.1.57",
|
"react-split-pane": "^0.1.57",
|
||||||
"react-textarea-autosize-inputref": "^4.1.0",
|
"react-textarea-autosize": "^4.3.2",
|
||||||
"react-toolbox": "^1.2.1",
|
"react-toolbox": "^1.2.1",
|
||||||
"react-topbar-progress-indicator": "^1.0.0",
|
"react-topbar-progress-indicator": "^1.0.0",
|
||||||
"react-waypoint": "^3.1.3",
|
"react-waypoint": "^3.1.3",
|
||||||
|
@ -124,6 +124,7 @@ class Backend {
|
|||||||
const format = resolveFormat(collectionOrEntity, entry);
|
const format = resolveFormat(collectionOrEntity, entry);
|
||||||
if (entry && entry.raw !== undefined) {
|
if (entry && entry.raw !== undefined) {
|
||||||
const data = (format && attempt(format.fromFile.bind(null, entry.raw))) || {};
|
const data = (format && attempt(format.fromFile.bind(null, entry.raw))) || {};
|
||||||
|
if (isError(data)) console.error(data);
|
||||||
return Object.assign(entry, { data: isError(data) ? {} : data });
|
return Object.assign(entry, { data: isError(data) ? {} : data });
|
||||||
}
|
}
|
||||||
return format.fromFile(entry);
|
return format.fromFile(entry);
|
||||||
|
@ -15,7 +15,8 @@ export default class PreviewPane extends React.Component {
|
|||||||
getWidget = (field, value, props) => {
|
getWidget = (field, value, props) => {
|
||||||
const { fieldsMetaData, getAsset } = props;
|
const { fieldsMetaData, getAsset } = props;
|
||||||
const widget = resolveWidget(field.get('widget'));
|
const widget = resolveWidget(field.get('widget'));
|
||||||
return React.createElement(widget.preview, {
|
|
||||||
|
return !widget.preview ? null : React.createElement(widget.preview, {
|
||||||
field,
|
field,
|
||||||
key: field.get('name'),
|
key: field.get('name'),
|
||||||
value: value && Map.isMap(value) ? value.get(field.get('name')) : value,
|
value: value && Map.isMap(value) ? value.get(field.get('name')) : value,
|
||||||
@ -37,10 +38,23 @@ export default class PreviewPane extends React.Component {
|
|||||||
if (authorField) this.inferedFields[authorField] = INFERABLE_FIELDS.author;
|
if (authorField) this.inferedFields[authorField] = INFERABLE_FIELDS.author;
|
||||||
}
|
}
|
||||||
|
|
||||||
widgetFor = (name) => {
|
/**
|
||||||
const { fields, entry } = this.props;
|
* Returns the widget component for a named field, and makes recursive calls
|
||||||
const field = fields.find(f => f.get('name') === name);
|
* to retrieve components for nested and deeply nested fields, which occur in
|
||||||
let value = entry.getIn(['data', field.get('name')]);
|
* object and list type fields. Used internally to retrieve widgets, and also
|
||||||
|
* exposed for use in custom preview templates.
|
||||||
|
*/
|
||||||
|
widgetFor = (name, fields = this.props.fields, values = this.props.entry.get('data')) => {
|
||||||
|
// We retrieve the field by name so that this function can also be used in
|
||||||
|
// custom preview templates, where the field object can't be passed in.
|
||||||
|
let field = fields && fields.find(f => f.get('name') === name);
|
||||||
|
let value = values && values.get(field.get('name'));
|
||||||
|
let nestedFields = field.get('fields');
|
||||||
|
|
||||||
|
if (nestedFields) {
|
||||||
|
field = field.set('fields', this.getNestedWidgets(nestedFields, value));
|
||||||
|
}
|
||||||
|
|
||||||
const labelledWidgets = ['string', 'text', 'number'];
|
const labelledWidgets = ['string', 'text', 'number'];
|
||||||
if (Object.keys(this.inferedFields).indexOf(name) !== -1) {
|
if (Object.keys(this.inferedFields).indexOf(name) !== -1) {
|
||||||
value = this.inferedFields[name].defaultPreview(value);
|
value = this.inferedFields[name].defaultPreview(value);
|
||||||
@ -51,6 +65,31 @@ export default class PreviewPane extends React.Component {
|
|||||||
return value ? this.getWidget(field, value, this.props) : null;
|
return value ? this.getWidget(field, value, this.props) : null;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves widgets for nested fields (children of object/list fields)
|
||||||
|
*/
|
||||||
|
getNestedWidgets = (fields, values) => {
|
||||||
|
// Fields nested within a list field will be paired with a List of value Maps.
|
||||||
|
if (List.isList(values)) {
|
||||||
|
return values.map(value => this.widgetsForNestedFields(fields, value));
|
||||||
|
}
|
||||||
|
// Fields nested within an object field will be paired with a single Map of values.
|
||||||
|
return this.widgetsForNestedFields(fields, values);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use widgetFor as a mapping function for recursive widget retrieval
|
||||||
|
*/
|
||||||
|
widgetsForNestedFields = (fields, values) => {
|
||||||
|
return fields.map(field => this.widgetFor(field.get('name'), fields, values));
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function exists entirely to expose nested widgets for object and list
|
||||||
|
* fields to custom preview templates.
|
||||||
|
*
|
||||||
|
* TODO: see if widgetFor can now provide this functionality for preview templates
|
||||||
|
*/
|
||||||
widgetsFor = (name) => {
|
widgetsFor = (name) => {
|
||||||
const { fields, entry } = this.props;
|
const { fields, entry } = this.props;
|
||||||
const field = fields.find(f => f.get('name') === name);
|
const field = fields.find(f => f.get('name') === name);
|
||||||
|
3
src/components/Widgets/BooleanControl.css
Normal file
3
src/components/Widgets/BooleanControl.css
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
.switch {
|
||||||
|
display: inline-block;
|
||||||
|
}
|
@ -1,6 +1,8 @@
|
|||||||
import React, { PropTypes } from 'react';
|
import React, { PropTypes } from 'react';
|
||||||
import ImmutablePropTypes from "react-immutable-proptypes";
|
import ImmutablePropTypes from "react-immutable-proptypes";
|
||||||
import Switch from 'react-toolbox/lib/switch';
|
import Switch from 'react-toolbox/lib/switch';
|
||||||
|
import { isBoolean } from 'lodash';
|
||||||
|
import styles from './BooleanControl.css';
|
||||||
|
|
||||||
export default class BooleanControl extends React.Component {
|
export default class BooleanControl extends React.Component {
|
||||||
render() {
|
render() {
|
||||||
@ -8,7 +10,8 @@ export default class BooleanControl extends React.Component {
|
|||||||
return (
|
return (
|
||||||
<Switch
|
<Switch
|
||||||
id={forID}
|
id={forID}
|
||||||
checked={value === undefined ? field.get('defaultValue', false) : value}
|
className={styles.switch}
|
||||||
|
checked={isBoolean(value) ? value : field.get('defaultValue', false)}
|
||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
@ -9,8 +9,10 @@ class ControlHOC extends Component {
|
|||||||
controlComponent: PropTypes.func.isRequired,
|
controlComponent: PropTypes.func.isRequired,
|
||||||
field: ImmutablePropTypes.map.isRequired,
|
field: ImmutablePropTypes.map.isRequired,
|
||||||
value: PropTypes.oneOfType([
|
value: PropTypes.oneOfType([
|
||||||
|
PropTypes.node,
|
||||||
PropTypes.object,
|
PropTypes.object,
|
||||||
PropTypes.string,
|
PropTypes.string,
|
||||||
|
PropTypes.bool,
|
||||||
]),
|
]),
|
||||||
metadata: ImmutablePropTypes.map,
|
metadata: ImmutablePropTypes.map,
|
||||||
onChange: PropTypes.func.isRequired,
|
onChange: PropTypes.func.isRequired,
|
||||||
|
@ -6,5 +6,5 @@ export default function DatePreview({ value }) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
DatePreview.propTypes = {
|
DatePreview.propTypes = {
|
||||||
value: PropTypes.node,
|
value: PropTypes.object,
|
||||||
};
|
};
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
import React, { PropTypes } from 'react';
|
import React, { PropTypes } from 'react';
|
||||||
import previewStyle from './defaultPreviewStyle';
|
import previewStyle from './defaultPreviewStyle';
|
||||||
|
|
||||||
export default function DatePreview({ value }) {
|
export default function DateTimePreview({ value }) {
|
||||||
return <div style={previewStyle}>{value ? value.toString() : null}</div>;
|
return <div style={previewStyle}>{value ? value.toString() : null}</div>;
|
||||||
}
|
}
|
||||||
|
|
||||||
DatePreview.propTypes = {
|
DateTimePreview.propTypes = {
|
||||||
value: PropTypes.node,
|
value: PropTypes.object,
|
||||||
};
|
};
|
||||||
|
@ -2,6 +2,7 @@ import React, { PropTypes } from 'react';
|
|||||||
import { truncateMiddle } from '../../lib/textHelper';
|
import { truncateMiddle } from '../../lib/textHelper';
|
||||||
import { Loader } from '../UI';
|
import { Loader } from '../UI';
|
||||||
import AssetProxy, { createAssetProxy } from '../../valueObjects/AssetProxy';
|
import AssetProxy, { createAssetProxy } from '../../valueObjects/AssetProxy';
|
||||||
|
import styles from './FileControl.css';
|
||||||
|
|
||||||
const MAX_DISPLAY_LENGTH = 50;
|
const MAX_DISPLAY_LENGTH = 50;
|
||||||
|
|
||||||
@ -77,8 +78,8 @@ export default class FileControl extends React.Component {
|
|||||||
const fileName = this.renderFileName();
|
const fileName = this.renderFileName();
|
||||||
if (processing) {
|
if (processing) {
|
||||||
return (
|
return (
|
||||||
<div style={styles.imageUpload}>
|
<div className={styles.imageUpload}>
|
||||||
<span style={styles.message}>
|
<span className={styles.message}>
|
||||||
<Loader active />
|
<Loader active />
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
@ -86,18 +87,18 @@ export default class FileControl extends React.Component {
|
|||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
style={styles.imageUpload}
|
className={styles.imageUpload}
|
||||||
onDragEnter={this.handleDragEnter}
|
onDragEnter={this.handleDragEnter}
|
||||||
onDragOver={this.handleDragOver}
|
onDragOver={this.handleDragOver}
|
||||||
onDrop={this.handleChange}
|
onDrop={this.handleChange}
|
||||||
>
|
>
|
||||||
<span style={styles.message} onClick={this.handleClick}>
|
<span className={styles.message} onClick={this.handleClick}>
|
||||||
{fileName ? fileName : 'Tip: Click here to select a file to upload, or drag an image directly into this box from your desktop'}
|
{fileName ? fileName : 'Click here to upload a file from your computer, or drag and drop a file directly into this box'}
|
||||||
</span>
|
</span>
|
||||||
<input
|
<input
|
||||||
type="file"
|
type="file"
|
||||||
onChange={this.handleChange}
|
onChange={this.handleChange}
|
||||||
style={styles.input}
|
className={styles.input}
|
||||||
ref={this.handleFileInputRef}
|
ref={this.handleFileInputRef}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@ -105,24 +106,6 @@ export default class FileControl extends React.Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const styles = {
|
|
||||||
input: {
|
|
||||||
display: 'none',
|
|
||||||
},
|
|
||||||
message: {
|
|
||||||
padding: '20px',
|
|
||||||
display: 'block',
|
|
||||||
fontSize: '12px',
|
|
||||||
},
|
|
||||||
imageUpload: {
|
|
||||||
backgroundColor: '#fff',
|
|
||||||
textAlign: 'center',
|
|
||||||
color: '#999',
|
|
||||||
border: '1px dashed #eee',
|
|
||||||
cursor: 'pointer',
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
FileControl.propTypes = {
|
FileControl.propTypes = {
|
||||||
onAddAsset: PropTypes.func.isRequired,
|
onAddAsset: PropTypes.func.isRequired,
|
||||||
onChange: PropTypes.func.isRequired,
|
onChange: PropTypes.func.isRequired,
|
||||||
|
@ -2,7 +2,7 @@ import React, { PropTypes } from 'react';
|
|||||||
import { truncateMiddle } from '../../lib/textHelper';
|
import { truncateMiddle } from '../../lib/textHelper';
|
||||||
import { Loader } from '../UI';
|
import { Loader } from '../UI';
|
||||||
import AssetProxy, { createAssetProxy } from '../../valueObjects/AssetProxy';
|
import AssetProxy, { createAssetProxy } from '../../valueObjects/AssetProxy';
|
||||||
import styles from './ImageControl.css';
|
import styles from './FileControl.css';
|
||||||
|
|
||||||
const MAX_DISPLAY_LENGTH = 50;
|
const MAX_DISPLAY_LENGTH = 50;
|
||||||
|
|
||||||
|
@ -1,36 +1,12 @@
|
|||||||
import React, { PropTypes, Component } from 'react';
|
import React, { PropTypes, Component } from 'react';
|
||||||
import { resolveWidget } from '../Widgets';
|
import { resolveWidget } from '../Widgets';
|
||||||
import previewStyle from './defaultPreviewStyle';
|
import previewStyle from './defaultPreviewStyle';
|
||||||
|
import ObjectPreview from './ObjectPreview';
|
||||||
|
|
||||||
export default class ListPreview extends Component {
|
const ListPreview = ObjectPreview;
|
||||||
widgetFor = (field, value) => {
|
|
||||||
const { getAsset } = this.props;
|
|
||||||
const widget = resolveWidget(field.get('widget'));
|
|
||||||
return (<div key={field.get('name')}>{React.createElement(widget.preview, {
|
|
||||||
key: field.get('name'),
|
|
||||||
value: value && value.get(field.get('name')),
|
|
||||||
field,
|
|
||||||
getAsset,
|
|
||||||
})}</div>);
|
|
||||||
};
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const { field, value } = this.props;
|
|
||||||
const fields = field && field.get('fields');
|
|
||||||
if (fields) {
|
|
||||||
return value ? (<div style={previewStyle}>
|
|
||||||
{value.map((val, index) => <div key={index}>
|
|
||||||
{fields && fields.map(f => this.widgetFor(f, val))}
|
|
||||||
</div>)}
|
|
||||||
</div>) : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return <div style={previewStyle}>{value ? value.join(', ') : null}</div>;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ListPreview.propTypes = {
|
ListPreview.propTypes = {
|
||||||
value: PropTypes.node,
|
|
||||||
field: PropTypes.node,
|
field: PropTypes.node,
|
||||||
getAsset: PropTypes.func.isRequired,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export default ListPreview;
|
||||||
|
@ -3,7 +3,7 @@ import MarkupIt from 'markup-it';
|
|||||||
import markdownSyntax from 'markup-it/syntaxes/markdown';
|
import markdownSyntax from 'markup-it/syntaxes/markdown';
|
||||||
import htmlSyntax from 'markup-it/syntaxes/html';
|
import htmlSyntax from 'markup-it/syntaxes/html';
|
||||||
import CaretPosition from 'textarea-caret-position';
|
import CaretPosition from 'textarea-caret-position';
|
||||||
import TextareaAutosize from 'react-textarea-autosize-inputref';
|
import TextareaAutosize from 'react-textarea-autosize';
|
||||||
import registry from '../../../../lib/registry';
|
import registry from '../../../../lib/registry';
|
||||||
import { createAssetProxy } from '../../../../valueObjects/AssetProxy';
|
import { createAssetProxy } from '../../../../valueObjects/AssetProxy';
|
||||||
import Toolbar from '../Toolbar/Toolbar';
|
import Toolbar from '../Toolbar/Toolbar';
|
||||||
|
@ -10,7 +10,11 @@ export default class ObjectControl extends Component {
|
|||||||
onAddAsset: PropTypes.func.isRequired,
|
onAddAsset: PropTypes.func.isRequired,
|
||||||
onRemoveAsset: PropTypes.func.isRequired,
|
onRemoveAsset: PropTypes.func.isRequired,
|
||||||
getAsset: PropTypes.func.isRequired,
|
getAsset: PropTypes.func.isRequired,
|
||||||
value: PropTypes.node,
|
value: PropTypes.oneOfType([
|
||||||
|
PropTypes.node,
|
||||||
|
PropTypes.object,
|
||||||
|
PropTypes.bool,
|
||||||
|
]),
|
||||||
field: PropTypes.object,
|
field: PropTypes.object,
|
||||||
forID: PropTypes.string,
|
forID: PropTypes.string,
|
||||||
className: PropTypes.string,
|
className: PropTypes.string,
|
||||||
@ -35,6 +39,7 @@ export default class ObjectControl extends Component {
|
|||||||
onAddAsset,
|
onAddAsset,
|
||||||
onRemoveAsset,
|
onRemoveAsset,
|
||||||
getAsset,
|
getAsset,
|
||||||
|
forID: field.get('name'),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
|
@ -2,32 +2,12 @@ import React, { PropTypes, Component } from 'react';
|
|||||||
import { resolveWidget } from '../Widgets';
|
import { resolveWidget } from '../Widgets';
|
||||||
import previewStyle from './defaultPreviewStyle';
|
import previewStyle from './defaultPreviewStyle';
|
||||||
|
|
||||||
export default class ObjectPreview extends Component {
|
const ObjectPreview = ({ field }) => (
|
||||||
widgetFor = (field) => {
|
<div style={previewStyle}>{(field && field.get('fields')) || null}</div>
|
||||||
const { value, getAsset } = this.props;
|
);
|
||||||
const widget = resolveWidget(field.get('widget'));
|
|
||||||
return (
|
|
||||||
<div key={field.get('name')}>
|
|
||||||
{React.createElement(widget.preview, {
|
|
||||||
key: field.get('name'),
|
|
||||||
value: value && value.get(field.get('name')),
|
|
||||||
field,
|
|
||||||
getAsset,
|
|
||||||
})}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const { field } = this.props;
|
|
||||||
const fields = field && field.get('fields');
|
|
||||||
|
|
||||||
return <div style={previewStyle}>{fields ? fields.map(f => this.widgetFor(f)) : null}</div>;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ObjectPreview.propTypes = {
|
ObjectPreview.propTypes = {
|
||||||
value: PropTypes.node,
|
|
||||||
field: PropTypes.node,
|
field: PropTypes.node,
|
||||||
getAsset: PropTypes.func.isRequired,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export default ObjectPreview;
|
||||||
|
@ -34,7 +34,7 @@ SelectControl.propTypes = {
|
|||||||
value: PropTypes.node,
|
value: PropTypes.node,
|
||||||
forID: PropTypes.string.isRequired,
|
forID: PropTypes.string.isRequired,
|
||||||
field: ImmutablePropTypes.contains({
|
field: ImmutablePropTypes.contains({
|
||||||
options: ImmutablePropTypes.listOf(PropTypes.oneOf([
|
options: ImmutablePropTypes.listOf(PropTypes.oneOfType([
|
||||||
PropTypes.string,
|
PropTypes.string,
|
||||||
ImmutablePropTypes.contains({
|
ImmutablePropTypes.contains({
|
||||||
label: PropTypes.string.isRequired,
|
label: PropTypes.string.isRequired,
|
||||||
|
@ -2,7 +2,7 @@ import React, { PropTypes } from 'react';
|
|||||||
import previewStyle from './defaultPreviewStyle';
|
import previewStyle from './defaultPreviewStyle';
|
||||||
|
|
||||||
export default function TextPreview({ value }) {
|
export default function TextPreview({ value }) {
|
||||||
return <div style={previewStyle}>{value ? value.toString() : null}</div>;
|
return <div style={previewStyle}>{value}</div>;
|
||||||
}
|
}
|
||||||
|
|
||||||
TextPreview.propTypes = {
|
TextPreview.propTypes = {
|
||||||
|
@ -7090,9 +7090,11 @@ react-style-proptype@^3.0.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
prop-types "^15.5.4"
|
prop-types "^15.5.4"
|
||||||
|
|
||||||
react-textarea-autosize-inputref@^4.1.0:
|
react-textarea-autosize@^4.3.2:
|
||||||
version "4.1.0"
|
version "4.3.2"
|
||||||
resolved "https://registry.yarnpkg.com/react-textarea-autosize-inputref/-/react-textarea-autosize-inputref-4.1.0.tgz#4a12921f9c992a8e2c6ce569ab46982a96ca48f6"
|
resolved "https://registry.yarnpkg.com/react-textarea-autosize/-/react-textarea-autosize-4.3.2.tgz#962a52c68caceae408c18acecec29049b81e42fa"
|
||||||
|
dependencies:
|
||||||
|
prop-types "^15.5.8"
|
||||||
|
|
||||||
react-themeable@^1.1.0:
|
react-themeable@^1.1.0:
|
||||||
version "1.1.0"
|
version "1.1.0"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user