diff --git a/src/components/ControlPane.js b/src/components/ControlPane.js index 59beb698..fc85243b 100644 --- a/src/components/ControlPane.js +++ b/src/components/ControlPane.js @@ -1,14 +1,14 @@ import React, { PropTypes } from 'react'; import ImmutablePropTypes from 'react-immutable-proptypes'; -import Widgets from './Widgets'; +import {resolveWidget} from './Widgets'; 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; + const widget = resolveWidget(field.get('widget')); return
- {React.createElement(widget.Control, { + {React.createElement(widget.control, { field: field, value: entry.getIn(['data', field.get('name')]), onChange: (value) => onChange(entry.setIn(['data', field.get('name')], value)), diff --git a/src/components/EntryEditor.css b/src/components/EntryEditor.css new file mode 100644 index 00000000..b77e517f --- /dev/null +++ b/src/components/EntryEditor.css @@ -0,0 +1,10 @@ +.container { + display: flex +} +.controlPane { + width: 50%; + padding: 0 10px; +} +.previewPane { + width: 50%; +} diff --git a/src/components/EntryEditor.js b/src/components/EntryEditor.js index 6ae93edd..c4a6353b 100644 --- a/src/components/EntryEditor.js +++ b/src/components/EntryEditor.js @@ -2,13 +2,14 @@ import React, { PropTypes } from 'react'; import ImmutablePropTypes from 'react-immutable-proptypes'; import ControlPane from './ControlPane'; import PreviewPane from './PreviewPane'; +import styles from './EntryEditor.css'; export default function EntryEditor({ collection, entry, getMedia, onChange, onAddMedia, onRemoveMedia, onPersist }) { return

Entry in {collection.get('label')}

{entry && entry.get('title')}

-
-
+
+
-
+
@@ -26,20 +27,6 @@ export default function EntryEditor({ collection, entry, getMedia, onChange, onA
; } -const styles = { - container: { - display: 'flex' - }, - controlPane: { - width: '50%', - paddingLeft: '10px', - paddingRight: '10px' - }, - pane: { - width: '50%' - } -}; - EntryEditor.propTypes = { collection: ImmutablePropTypes.map.isRequired, entry: ImmutablePropTypes.map.isRequired, diff --git a/src/components/EntryListing.js b/src/components/EntryListing.js index 28baa927..7ca45393 100644 --- a/src/components/EntryListing.js +++ b/src/components/EntryListing.js @@ -60,7 +60,8 @@ export default class EntryListing extends React.Component { cardFor(collection, entry, link) { //const { entry, getMedia, onChange, onAddMedia, onRemoveMedia } = this.props; - const card = Cards[collection.getIn(['card', 'type'])] || Cards._unknown; + const cartType = collection.getIn(['card', 'type']) || 'alltype'; + const card = Cards[cartType] || Cards._unknown; return React.createElement(card, { key: entry.get('slug'), collection: collection, diff --git a/src/components/PreviewPane.js b/src/components/PreviewPane.js index 24af9229..9ce76ab5 100644 --- a/src/components/PreviewPane.js +++ b/src/components/PreviewPane.js @@ -1,15 +1,15 @@ 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 registry from '../lib/registry'; +import { resolveWidget } from './Widgets'; import styles from './PreviewPane.css'; class Preview extends React.Component { previewFor(field) { const { entry, getMedia } = this.props; - const widget = Widgets[field.get('widget')] || Widgets._unknown; - return React.createElement(widget.Preview, { + const widget = resolveWidget(field.get('widget')); + return React.createElement(widget.preview, { field: field, value: entry.getIn(['data', field.get('name')]), getMedia: getMedia, @@ -46,8 +46,8 @@ export default class PreviewPane extends React.Component { 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, { + const widget = resolveWidget(field.get('widget')); + return React.createElement(widget.preview, { field: field, value: entry.getIn(['data', field.get('name')]), getMedia: getMedia, @@ -56,14 +56,14 @@ export default class PreviewPane extends React.Component { renderPreview() { const props = Object.assign({}, this.props, {widgetFor: this.widgetFor}); - const component = getPreviewTemplate(props.collection.get('name')) || Preview; + const component = registry.getPreviewTemplate(props.collection.get('name')) || Preview; render(React.createElement(component, props), this.previewEl); } handleIframeRef(ref) { if (ref) { - getPreviewStyles().forEach((style) => { + registry.getPreviewStyles().forEach((style) => { const linkEl = document.createElement('link'); linkEl.setAttribute('rel', 'stylesheet'); linkEl.setAttribute('href', style); @@ -79,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.js b/src/components/Widgets.js index 0a86b6b7..e03bfa8f 100644 --- a/src/components/Widgets.js +++ b/src/components/Widgets.js @@ -1,3 +1,4 @@ +import registry from '../lib/registry'; import UnknownControl from './Widgets/UnknownControl'; import UnknownPreview from './Widgets/UnknownPreview'; import StringControl from './Widgets/StringControl'; @@ -6,25 +7,15 @@ import MarkdownControl from './Widgets/MarkdownControl'; import MarkdownPreview from './Widgets/MarkdownPreview'; import ImageControl from './Widgets/ImageControl'; import ImagePreview from './Widgets/ImagePreview'; +import DateTimeControl from './Widgets/DateTimeControl'; +import DateTimePreview from './Widgets/DateTimePreview'; +registry.registerWidget('string', StringControl, StringPreview); +registry.registerWidget('markdown', MarkdownControl, MarkdownPreview); +registry.registerWidget('image', ImageControl, ImagePreview); +registry.registerWidget('datetime', DateTimeControl, DateTimePreview); +registry.registerWidget('_unknown', UnknownControl, UnknownPreview); -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; +export function resolveWidget(name) { + return registry.getWidget(name) || registry.getWidget('_unknown'); +} diff --git a/src/formats/formats.js b/src/formats/formats.js index 9d6f72ad..8e3679b5 100644 --- a/src/formats/formats.js +++ b/src/formats/formats.js @@ -1,5 +1,15 @@ +import YAML from './yaml'; import YAMLFrontmatter from './yaml-frontmatter'; +const yamlFormatter = new YAML(); +const YamlFrontmatterFormatter = new YAMLFrontmatter(); + export function resolveFormat(collection, entry) { - return new YAMLFrontmatter(); + const extension = entry.path.split('.').pop(); + switch (extension) { + case 'yml': + return yamlFormatter; + default: + return YamlFrontmatterFormatter; + } } diff --git a/src/index.css b/src/index.css index 4bc2c468..21a60d09 100644 --- a/src/index.css +++ b/src/index.css @@ -60,3 +60,215 @@ button{ background-color:#fff; cursor: pointer; } + +:global { + & .rdt { + position: relative; + } + & .rdtPicker { + display: none; + position: absolute; + width: 250px; + padding: 4px; + margin-top: 1px; + z-index: 99999 !important; + background: #fff; + box-shadow: 0 1px 3px rgba(0,0,0,.1); + border: 1px solid #f9f9f9; + } + & .rdtOpen .rdtPicker { + display: block; + } + & .rdtStatic .rdtPicker { + box-shadow: none; + position: static; + } + + & .rdtPicker .rdtTimeToggle { + text-align: center; + } + + & .rdtPicker table { + width: 100%; + margin: 0; + } + & .rdtPicker td, + & .rdtPicker th { + text-align: center; + height: 28px; + } + & .rdtPicker td { + cursor: pointer; + } + & .rdtPicker td.rdtDay:hover, + & .rdtPicker td.rdtHour:hover, + & .rdtPicker td.rdtMinute:hover, + & .rdtPicker td.rdtSecond:hover, + & .rdtPicker .rdtTimeToggle:hover { + background: #eeeeee; + cursor: pointer; + } + & .rdtPicker td.rdtOld, + & .rdtPicker td.rdtNew { + color: #999999; + } + & .rdtPicker td.rdtToday { + position: relative; + } + & .rdtPicker td.rdtToday:before { + content: ''; + display: inline-block; + border-left: 7px solid transparent; + border-bottom: 7px solid #428bca; + border-top-color: rgba(0, 0, 0, 0.2); + position: absolute; + bottom: 4px; + right: 4px; + } + & .rdtPicker td.rdtActive, + & .rdtPicker td.rdtActive:hover { + background-color: #428bca; + color: #fff; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); + } + & .rdtPicker td.rdtActive.rdtToday:before { + border-bottom-color: #fff; + } + & .rdtPicker td.rdtDisabled, + & .rdtPicker td.rdtDisabled:hover { + background: none; + color: #999999; + cursor: not-allowed; + } + + & .rdtPicker td span.rdtOld { + color: #999999; + } + & .rdtPicker td span.rdtDisabled, + & .rdtPicker td span.rdtDisabled:hover { + background: none; + color: #999999; + cursor: not-allowed; + } + & .rdtPicker th { + border-bottom: 1px solid #f9f9f9; + } + & .rdtPicker .dow { + width: 14.2857%; + border-bottom: none; + } + & .rdtPicker th.rdtSwitch { + width: 100px; + } + & .rdtPicker th.rdtNext, + & .rdtPicker th.rdtPrev { + font-size: 21px; + vertical-align: top; + } + + & .rdtPrev span, + & .rdtNext span { + display: block; + -webkit-touch-callout: none; /* iOS Safari */ + -webkit-user-select: none; /* Chrome/Safari/Opera */ + -khtml-user-select: none; /* Konqueror */ + -moz-user-select: none; /* Firefox */ + -ms-user-select: none; /* Internet Explorer/Edge */ + user-select: none; + } + + & .rdtPicker th.rdtDisabled, + & .rdtPicker th.rdtDisabled:hover { + background: none; + color: #999999; + cursor: not-allowed; + } + & .rdtPicker thead tr:first-child th { + cursor: pointer; + } + & .rdtPicker thead tr:first-child th:hover { + background: #eeeeee; + } + + & .rdtPicker tfoot { + border-top: 1px solid #f9f9f9; + } + + & .rdtPicker button { + border: none; + background: none; + cursor: pointer; + } + & .rdtPicker button:hover { + background-color: #eee; + } + + & .rdtPicker thead button { + width: 100%; + height: 100%; + } + + & td.rdtMonth, + & td.rdtYear { + height: 50px; + width: 25%; + cursor: pointer; + } + & td.rdtMonth:hover, + & td.rdtYear:hover { + background: #eee; + } + + & .rdtCounters { + display: inline-block; + } + + & .rdtCounters > div { + float: left; + } + + & .rdtCounter { + height: 100px; + } + + & .rdtCounter { + width: 40px; + } + + & .rdtCounterSeparator { + line-height: 100px; + } + + & .rdtCounter .rdtBtn { + height: 40%; + line-height: 40px; + cursor: pointer; + display: block; + + -webkit-touch-callout: none; /* iOS Safari */ + -webkit-user-select: none; /* Chrome/Safari/Opera */ + -khtml-user-select: none; /* Konqueror */ + -moz-user-select: none; /* Firefox */ + -ms-user-select: none; /* Internet Explorer/Edge */ + user-select: none; + } + & .rdtCounter .rdtBtn:hover { + background: #eee; + } + & .rdtCounter .rdtCount { + height: 20%; + font-size: 1.2em; + } + + & .rdtMilli { + vertical-align: middle; + padding-left: 8px; + width: 48px; + } + + & .rdtMilli input { + width: 100%; + font-size: 1.2em; + margin-top: 37px; + } +} diff --git a/src/index.js b/src/index.js index 5ef69bb4..e93eaea1 100644 --- a/src/index.js +++ b/src/index.js @@ -2,7 +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 registry from './lib/registry'; import configureStore from './store/configureStore'; import routes from './routing/routes'; import history, { syncHistory } from './routing/history'; @@ -31,7 +31,8 @@ render(( ), el); -window.CMS = { - registerPreviewStyle: registerPreviewStyle, - registerPreviewTemplate: registerPreviewTemplate -}; +window.CMS = {}; +console.log('reg: ', registry); +for (const method in registry) { + window.CMS[method] = registry[method]; +} diff --git a/src/lib/registry.js b/src/lib/registry.js index 809b9784..84a1eb94 100644 --- a/src/lib/registry.js +++ b/src/lib/registry.js @@ -1,20 +1,26 @@ -const registry = { +const _registry = { templates: {}, - previewStyles: [] + previewStyles: [], + widgets: {} }; -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; -} +export default { + registerPreviewStyle(style) { + _registry.previewStyles.push(style); + }, + registerPreviewTemplate(name, component) { + _registry.templates[name] = component; + }, + getPreviewTemplate(name) { + return _registry.templates[name]; + }, + getPreviewStyles() { + return _registry.previewStyles; + }, + registerWidget(name, control, preview) { + _registry.widgets[name] = { control, preview }; + }, + getWidget(name) { + return _registry.widgets[name]; + } +};