diff --git a/src/actions/entries.js b/src/actions/entries.js index a20d13d8..34b806c8 100644 --- a/src/actions/entries.js +++ b/src/actions/entries.js @@ -1,18 +1,31 @@ import { currentBackend } from '../backends/backend'; +/* + * Contant Declarations + */ export const ENTRY_REQUEST = 'ENTRY_REQUEST'; export const ENTRY_SUCCESS = 'ENTRY_SUCCESS'; export const ENTRY_FAILURE = 'ENTRY_FAILURE'; -export const ENTRY_PERSIST_REQUEST = 'ENTRY_PERSIST_REQUEST'; -export const ENTRY_PERSIST_SUCCESS = 'ENTRY_PERSIST_SUCCESS'; -export const ENTRY_PERSIST_FAILURE = 'ENTRY_PERSIST_FAILURE'; - export const ENTRIES_REQUEST = 'ENTRIES_REQUEST'; export const ENTRIES_SUCCESS = 'ENTRIES_SUCCESS'; export const ENTRIES_FAILURE = 'ENTRIES_FAILURE'; -export function entryLoading(collection, slug) { +export const DRAFT_CREATE = 'DRAFT_CREATE'; +export const DRAFT_DISCARD = 'DRAFT_DISCARD'; +export const DRAFT_CHANGE = 'DRAFT_CHANGE'; +export const DRAFT_ADD_MEDIA = 'DRAFT_ADD_MEDIA'; +export const DRAFT_REMOVE_MEDIA = 'DRAFT_REMOVE_MEDIA'; + +export const ENTRY_PERSIST_REQUEST = 'ENTRY_PERSIST_REQUEST'; +export const ENTRY_PERSIST_SUCCESS = 'ENTRY_PERSIST_SUCCESS'; +export const ENTRY_PERSIST_FAILURE = 'ENTRY_PERSIST_FAILURE'; + + +/* + * Simple Action Creators (Internal) + */ +function entryLoading(collection, slug) { return { type: ENTRY_REQUEST, payload: { @@ -22,7 +35,7 @@ export function entryLoading(collection, slug) { }; } -export function entryLoaded(collection, entry) { +function entryLoaded(collection, entry) { return { type: ENTRY_SUCCESS, payload: { @@ -32,35 +45,7 @@ export function entryLoaded(collection, entry) { }; } -export function entryPersisting(collection, entry) { - return { - type: ENTRY_PERSIST_REQUEST, - payload: { - collection: collection, - entry: entry - } - }; -} - -export function entryPersisted(collection, entry) { - return { - type: ENTRY_PERSIST_SUCCESS, - payload: { - collection: collection, - entry: entry - } - }; -} - -export function entryPersistFail(collection, entry, error) { - return { - type: ENTRIES_FAILURE, - error: 'Failed to persist entry', - payload: error.toString() - }; -} - -export function entriesLoading(collection) { +function entriesLoading(collection) { return { type: ENTRIES_REQUEST, payload: { @@ -69,7 +54,7 @@ export function entriesLoading(collection) { }; } -export function entriesLoaded(collection, entries, pagination) { +function entriesLoaded(collection, entries, pagination) { return { type: ENTRIES_SUCCESS, payload: { @@ -80,7 +65,7 @@ export function entriesLoaded(collection, entries, pagination) { }; } -export function entriesFailed(collection, error) { +function entriesFailed(collection, error) { return { type: ENTRIES_FAILURE, error: 'Failed to load entries', @@ -89,6 +74,74 @@ export function entriesFailed(collection, error) { }; } +function entryPersisting(collection, entry) { + return { + type: ENTRY_PERSIST_REQUEST, + payload: { + collection: collection, + entry: entry + } + }; +} + +function entryPersisted(collection, entry) { + return { + type: ENTRY_PERSIST_SUCCESS, + payload: { + collection: collection, + entry: entry + } + }; +} + +function entryPersistFail(collection, entry, error) { + return { + type: ENTRIES_FAILURE, + error: 'Failed to persist entry', + payload: error.toString() + }; +} + +/* + * Exported simple Action Creators + */ +export function createDraft(entry) { + return { + type: DRAFT_CREATE, + payload: entry + }; +} + +export function discardDraft() { + return { + type: DRAFT_DISCARD + }; +} + +export function changeDraft(entry) { + return { + type: DRAFT_CHANGE, + payload: entry + }; +} + +export function addMediaToDraft(mediaFile) { + return { + type: DRAFT_ADD_MEDIA, + payload: mediaFile + }; +} + +export function removeMediaFromDraft(mediaFile) { + return { + type: DRAFT_REMOVE_MEDIA, + payload: mediaFile + }; +} + +/* + * Exported Thunk Action Creators + */ export function loadEntry(collection, slug) { return (dispatch, getState) => { const state = getState(); @@ -107,8 +160,10 @@ export function loadEntries(collection) { const backend = currentBackend(state.config); dispatch(entriesLoading(collection)); - backend.entries(collection) - .then((response) => dispatch(entriesLoaded(collection, response.entries, response.pagination))); + backend.entries(collection).then( + (response) => dispatch(entriesLoaded(collection, response.entries, response.pagination)), + (error) => dispatch(entriesFailed(collection, error)) + ); }; } diff --git a/src/backends/backend.js b/src/backends/backend.js index 8bb51aa4..5b8c7108 100644 --- a/src/backends/backend.js +++ b/src/backends/backend.js @@ -67,15 +67,16 @@ class Backend { }; } - persist(collection, entry, mediaFiles) { - const entryData = entry.get('data').toJS(); + persist(collection, entryDraft) { + + const entryData = entryDraft.getIn(['entry', 'data']).toJS(); const entryObj = { - path: entry.get('path'), - slug: entry.get('slug'), + path: entryDraft.getIn(['entry', 'path']), + slug: entryDraft.getIn(['entry', 'slug']), raw: this.entryToRaw(collection, entryData) }; - return this.implementation.persist(collection, entryObj, mediaFiles.toJS()); + return this.implementation.persist(collection, entryObj, entryDraft.get('mediaFiles').toJS()); } entryToRaw(collection, entry) { diff --git a/src/backends/test-repo/implementation.js b/src/backends/test-repo/implementation.js index 157847da..5493fc6c 100644 --- a/src/backends/test-repo/implementation.js +++ b/src/backends/test-repo/implementation.js @@ -19,10 +19,11 @@ function getFileData(file) { } // Only necessary in test-repo, where images won't actually be persisted on server -function changeFilePathstoBase64(content, mediaFiles, base64Files) { +function changeFilePathstoBase64(mediaFolder, content, mediaFiles, base64Files) { let _content = content; + mediaFiles.forEach((media, index) => { - const reg = new RegExp('\\b' + media.uri + '\\b', 'g'); + const reg = new RegExp('\\b' + mediaFolder + '/' + media.name + '\\b', 'g'); _content = _content.replace(reg, base64Files[index]); }); @@ -74,12 +75,11 @@ export default class TestRepo { persist(collection, entry, mediaFiles = []) { return new Promise((resolve, reject) => { - Promise.all(mediaFiles.map((imageProxy) => getFileData(imageProxy.file))).then( + Promise.all(mediaFiles.map((file) => getFileData(file))).then( (base64Files) => { - const content = changeFilePathstoBase64(entry.raw, mediaFiles, base64Files); + const content = changeFilePathstoBase64(this.config.get('media_folder'), entry.raw, mediaFiles, base64Files); const folder = collection.get('folder'); const fileName = entry.path.substring(entry.path.lastIndexOf('/') + 1); - window.repoFiles[folder][fileName]['content'] = content; resolve({collection, entry}); }, diff --git a/src/components/ControlPane.js b/src/components/ControlPane.js index cd7c08de..ea6f7162 100644 --- a/src/components/ControlPane.js +++ b/src/components/ControlPane.js @@ -3,15 +3,15 @@ import Widgets from './Widgets'; export default class ControlPane extends React.Component { controlFor(field) { - const { entry } = this.props; + const { entry, onChange, onAddMedia, onRemoveMedia } = this.props; const widget = Widgets[field.get('widget')] || Widgets._unknown; return React.createElement(widget.Control, { key: field.get('name'), field: field, value: entry.getIn(['data', field.get('name')]), - onChange: (value) => this.props.onChange(entry.setIn(['data', field.get('name')], value)), - onAddMedia: (mediaFile) => this.props.onAddMedia(mediaFile), - onRemoveMedia: (mediaFile) => this.props.onRemoveMedia(mediaFile) + onChange: (value) => onChange(entry.setIn(['data', field.get('name')], value)), + onAddMedia: onAddMedia, + onRemoveMedia: onRemoveMedia }); } diff --git a/src/components/EntryEditor.js b/src/components/EntryEditor.js index 9bab99a9..38e6cd3c 100644 --- a/src/components/EntryEditor.js +++ b/src/components/EntryEditor.js @@ -1,44 +1,11 @@ import React from 'react'; -import Immutable from 'immutable'; import ControlPane from './ControlPane'; import PreviewPane from './PreviewPane'; export default class EntryEditor extends React.Component { - constructor(props) { - super(props); - this.state = { - entry: props.entry, - mediaFiles: Immutable.List() - }; - this.handleChange = this.handleChange.bind(this); - this.handleAddMedia = this.handleAddMedia.bind(this); - this.handleRemoveMedia = this.handleRemoveMedia.bind(this); - this.handleSave = this.handleSave.bind(this); - } - - handleChange(entry) { - this.setState({entry: entry}); - } - - handleAddMedia(mediaFile) { - this.setState({mediaFiles: this.state.mediaFiles.push(mediaFile)}); - } - - handleRemoveMedia(mediaFile) { - const newState = this.state.mediaFiles.filterNot((item) => item === mediaFile); - this.state = { - entry: this.props.entry, - mediaFiles: Immutable.List(newState) - }; - } - - handleSave() { - this.props.onPersist(this.state.entry, this.state.mediaFiles); - } render() { - const { collection, entry } = this.props; - + const { collection, entry, onChange, onAddMedia, onRemoveMedia, onPersist } = this.props; return