Moved draft state for an entry (when in edit mode) to Redux
This commit is contained in:
parent
2d48743f37
commit
9275aaec90
@ -1,18 +1,31 @@
|
|||||||
import { currentBackend } from '../backends/backend';
|
import { currentBackend } from '../backends/backend';
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Contant Declarations
|
||||||
|
*/
|
||||||
export const ENTRY_REQUEST = 'ENTRY_REQUEST';
|
export const ENTRY_REQUEST = 'ENTRY_REQUEST';
|
||||||
export const ENTRY_SUCCESS = 'ENTRY_SUCCESS';
|
export const ENTRY_SUCCESS = 'ENTRY_SUCCESS';
|
||||||
export const ENTRY_FAILURE = 'ENTRY_FAILURE';
|
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_REQUEST = 'ENTRIES_REQUEST';
|
||||||
export const ENTRIES_SUCCESS = 'ENTRIES_SUCCESS';
|
export const ENTRIES_SUCCESS = 'ENTRIES_SUCCESS';
|
||||||
export const ENTRIES_FAILURE = 'ENTRIES_FAILURE';
|
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 {
|
return {
|
||||||
type: ENTRY_REQUEST,
|
type: ENTRY_REQUEST,
|
||||||
payload: {
|
payload: {
|
||||||
@ -22,7 +35,7 @@ export function entryLoading(collection, slug) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function entryLoaded(collection, entry) {
|
function entryLoaded(collection, entry) {
|
||||||
return {
|
return {
|
||||||
type: ENTRY_SUCCESS,
|
type: ENTRY_SUCCESS,
|
||||||
payload: {
|
payload: {
|
||||||
@ -32,35 +45,7 @@ export function entryLoaded(collection, entry) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function entryPersisting(collection, entry) {
|
function entriesLoading(collection) {
|
||||||
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) {
|
|
||||||
return {
|
return {
|
||||||
type: ENTRIES_REQUEST,
|
type: ENTRIES_REQUEST,
|
||||||
payload: {
|
payload: {
|
||||||
@ -69,7 +54,7 @@ export function entriesLoading(collection) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function entriesLoaded(collection, entries, pagination) {
|
function entriesLoaded(collection, entries, pagination) {
|
||||||
return {
|
return {
|
||||||
type: ENTRIES_SUCCESS,
|
type: ENTRIES_SUCCESS,
|
||||||
payload: {
|
payload: {
|
||||||
@ -80,7 +65,7 @@ export function entriesLoaded(collection, entries, pagination) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function entriesFailed(collection, error) {
|
function entriesFailed(collection, error) {
|
||||||
return {
|
return {
|
||||||
type: ENTRIES_FAILURE,
|
type: ENTRIES_FAILURE,
|
||||||
error: 'Failed to load entries',
|
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) {
|
export function loadEntry(collection, slug) {
|
||||||
return (dispatch, getState) => {
|
return (dispatch, getState) => {
|
||||||
const state = getState();
|
const state = getState();
|
||||||
@ -107,8 +160,10 @@ export function loadEntries(collection) {
|
|||||||
const backend = currentBackend(state.config);
|
const backend = currentBackend(state.config);
|
||||||
|
|
||||||
dispatch(entriesLoading(collection));
|
dispatch(entriesLoading(collection));
|
||||||
backend.entries(collection)
|
backend.entries(collection).then(
|
||||||
.then((response) => dispatch(entriesLoaded(collection, response.entries, response.pagination)));
|
(response) => dispatch(entriesLoaded(collection, response.entries, response.pagination)),
|
||||||
|
(error) => dispatch(entriesFailed(collection, error))
|
||||||
|
);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -67,15 +67,16 @@ class Backend {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
persist(collection, entry, mediaFiles) {
|
persist(collection, entryDraft) {
|
||||||
const entryData = entry.get('data').toJS();
|
|
||||||
|
const entryData = entryDraft.getIn(['entry', 'data']).toJS();
|
||||||
const entryObj = {
|
const entryObj = {
|
||||||
path: entry.get('path'),
|
path: entryDraft.getIn(['entry', 'path']),
|
||||||
slug: entry.get('slug'),
|
slug: entryDraft.getIn(['entry', 'slug']),
|
||||||
raw: this.entryToRaw(collection, entryData)
|
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) {
|
entryToRaw(collection, entry) {
|
||||||
|
@ -19,10 +19,11 @@ function getFileData(file) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Only necessary in test-repo, where images won't actually be persisted on server
|
// 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;
|
let _content = content;
|
||||||
|
|
||||||
mediaFiles.forEach((media, index) => {
|
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]);
|
_content = _content.replace(reg, base64Files[index]);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -74,12 +75,11 @@ export default class TestRepo {
|
|||||||
|
|
||||||
persist(collection, entry, mediaFiles = []) {
|
persist(collection, entry, mediaFiles = []) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
Promise.all(mediaFiles.map((imageProxy) => getFileData(imageProxy.file))).then(
|
Promise.all(mediaFiles.map((file) => getFileData(file))).then(
|
||||||
(base64Files) => {
|
(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 folder = collection.get('folder');
|
||||||
const fileName = entry.path.substring(entry.path.lastIndexOf('/') + 1);
|
const fileName = entry.path.substring(entry.path.lastIndexOf('/') + 1);
|
||||||
|
|
||||||
window.repoFiles[folder][fileName]['content'] = content;
|
window.repoFiles[folder][fileName]['content'] = content;
|
||||||
resolve({collection, entry});
|
resolve({collection, entry});
|
||||||
},
|
},
|
||||||
|
@ -3,15 +3,15 @@ import Widgets from './Widgets';
|
|||||||
|
|
||||||
export default class ControlPane extends React.Component {
|
export default class ControlPane extends React.Component {
|
||||||
controlFor(field) {
|
controlFor(field) {
|
||||||
const { entry } = this.props;
|
const { entry, onChange, onAddMedia, onRemoveMedia } = this.props;
|
||||||
const widget = Widgets[field.get('widget')] || Widgets._unknown;
|
const widget = Widgets[field.get('widget')] || Widgets._unknown;
|
||||||
return React.createElement(widget.Control, {
|
return React.createElement(widget.Control, {
|
||||||
key: field.get('name'),
|
key: field.get('name'),
|
||||||
field: field,
|
field: field,
|
||||||
value: entry.getIn(['data', field.get('name')]),
|
value: entry.getIn(['data', field.get('name')]),
|
||||||
onChange: (value) => this.props.onChange(entry.setIn(['data', field.get('name')], value)),
|
onChange: (value) => onChange(entry.setIn(['data', field.get('name')], value)),
|
||||||
onAddMedia: (mediaFile) => this.props.onAddMedia(mediaFile),
|
onAddMedia: onAddMedia,
|
||||||
onRemoveMedia: (mediaFile) => this.props.onRemoveMedia(mediaFile)
|
onRemoveMedia: onRemoveMedia
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,44 +1,11 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import Immutable from 'immutable';
|
|
||||||
import ControlPane from './ControlPane';
|
import ControlPane from './ControlPane';
|
||||||
import PreviewPane from './PreviewPane';
|
import PreviewPane from './PreviewPane';
|
||||||
|
|
||||||
export default class EntryEditor extends React.Component {
|
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() {
|
render() {
|
||||||
const { collection, entry } = this.props;
|
const { collection, entry, onChange, onAddMedia, onRemoveMedia, onPersist } = this.props;
|
||||||
|
|
||||||
return <div>
|
return <div>
|
||||||
<h1>Entry in {collection.get('label')}</h1>
|
<h1>Entry in {collection.get('label')}</h1>
|
||||||
<h2>{entry && entry.get('title')}</h2>
|
<h2>{entry && entry.get('title')}</h2>
|
||||||
@ -46,17 +13,17 @@ export default class EntryEditor extends React.Component {
|
|||||||
<div className="cms-control-pane" style={styles.pane}>
|
<div className="cms-control-pane" style={styles.pane}>
|
||||||
<ControlPane
|
<ControlPane
|
||||||
collection={collection}
|
collection={collection}
|
||||||
entry={this.state.entry}
|
entry={entry}
|
||||||
onChange={this.handleChange}
|
onChange={onChange}
|
||||||
onAddMedia={this.handleAddMedia}
|
onAddMedia={onAddMedia}
|
||||||
onRemoveMedia={this.handleRemoveMedia}
|
onRemoveMedia={onRemoveMedia}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="cms-preview-pane" style={styles.pane}>
|
<div className="cms-preview-pane" style={styles.pane}>
|
||||||
<PreviewPane collection={collection} entry={this.state.entry}/>
|
<PreviewPane collection={collection} entry={entry}/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<button onClick={this.handleSave}>Save</button>
|
<button onClick={onPersist}>Save</button>
|
||||||
</div>;
|
</div>;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -62,8 +62,8 @@ export default class ImageControl extends React.Component {
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (file) {
|
if (file) {
|
||||||
imageRef = new ImageProxy(file.name, file);
|
imageRef = new ImageProxy(file.name, window.URL.createObjectURL(file, {oneTimeOnly: true}));
|
||||||
this.props.onAddMedia(imageRef);
|
this.props.onAddMedia(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.props.onChange(imageRef);
|
this.props.onChange(imageRef);
|
||||||
|
@ -1,32 +1,56 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { Map } from 'immutable';
|
import {
|
||||||
import { loadEntry, persist } from '../actions/entries';
|
loadEntry,
|
||||||
|
createDraft,
|
||||||
|
discardDraft,
|
||||||
|
changeDraft,
|
||||||
|
addMediaToDraft,
|
||||||
|
removeMediaFromDraft,
|
||||||
|
persist
|
||||||
|
} from '../actions/entries';
|
||||||
import { selectEntry } from '../reducers/entries';
|
import { selectEntry } from '../reducers/entries';
|
||||||
import EntryEditor from '../components/EntryEditor';
|
import EntryEditor from '../components/EntryEditor';
|
||||||
|
|
||||||
class EntryPage extends React.Component {
|
class EntryPage extends React.Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
this.props.dispatch(loadEntry(props.collection, props.slug));
|
this.props.loadEntry(props.collection, props.slug);
|
||||||
|
|
||||||
this.handlePersist = this.handlePersist.bind(this);
|
this.handlePersist = this.handlePersist.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
handlePersist(entry, mediaFiles) {
|
componentDidMount() {
|
||||||
this.props.dispatch(persist(this.props.collection, entry, mediaFiles));
|
if (this.props.entry) {
|
||||||
|
this.props.createDraft(this.props.entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillReceiveProps(nextProps) {
|
||||||
|
if (this.props.entry !== nextProps.entry && !nextProps.entry.get('isFetching')) {
|
||||||
|
this.props.createDraft(nextProps.entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillUnmount() {
|
||||||
|
this.props.discardDraft();
|
||||||
|
}
|
||||||
|
|
||||||
|
handlePersist() {
|
||||||
|
this.props.persist(this.props.collection, this.props.entryDraft);
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { entry, collection } = this.props;
|
const { entry, entryDraft, collection, handleDraftChange, handleDraftAddMedia, handleDraftRemoveMedia } = this.props;
|
||||||
if (entry == null || entry.get('isFetching')) {
|
if (entry == null || entryDraft.get('entry') == undefined || entry.get('isFetching')) {
|
||||||
return <div>Loading...</div>;
|
return <div>Loading...</div>;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<EntryEditor
|
<EntryEditor
|
||||||
entry={entry || new Map()}
|
entry={entryDraft.get('entry')}
|
||||||
collection={collection}
|
collection={collection}
|
||||||
|
onChange={handleDraftChange}
|
||||||
|
onAddMedia={handleDraftAddMedia}
|
||||||
|
onRemoveMedia={handleDraftRemoveMedia}
|
||||||
onPersist={this.handlePersist}
|
onPersist={this.handlePersist}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
@ -34,12 +58,22 @@ class EntryPage extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function mapStateToProps(state, ownProps) {
|
function mapStateToProps(state, ownProps) {
|
||||||
const { collections } = state;
|
const { collections, entryDraft } = state;
|
||||||
const collection = collections.get(ownProps.params.name);
|
const collection = collections.get(ownProps.params.name);
|
||||||
const slug = ownProps.params.slug;
|
const slug = ownProps.params.slug;
|
||||||
const entry = selectEntry(state, collection.get('name'), slug);
|
const entry = selectEntry(state, collection.get('name'), slug);
|
||||||
|
return {collection, collections, entryDraft, slug, entry};
|
||||||
return {collection, collections, slug, entry};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default connect(mapStateToProps)(EntryPage);
|
export default connect(
|
||||||
|
mapStateToProps,
|
||||||
|
{
|
||||||
|
handleDraftChange: changeDraft,
|
||||||
|
handleDraftAddMedia: addMediaToDraft,
|
||||||
|
handleDraftRemoveMedia: removeMediaFromDraft,
|
||||||
|
loadEntry,
|
||||||
|
createDraft,
|
||||||
|
discardDraft,
|
||||||
|
persist
|
||||||
|
}
|
||||||
|
)(EntryPage);
|
||||||
|
@ -7,6 +7,8 @@ import 'file?name=index.html!../example/index.html';
|
|||||||
|
|
||||||
const store = configureStore();
|
const store = configureStore();
|
||||||
|
|
||||||
|
window.store = store;
|
||||||
|
|
||||||
const el = document.createElement('div');
|
const el = document.createElement('div');
|
||||||
document.body.appendChild(el);
|
document.body.appendChild(el);
|
||||||
|
|
||||||
|
34
src/reducers/entryDraft.js
Normal file
34
src/reducers/entryDraft.js
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
import { Map, List } from 'immutable';
|
||||||
|
import { DRAFT_CREATE, DRAFT_DISCARD, DRAFT_CHANGE, DRAFT_ADD_MEDIA, DRAFT_REMOVE_MEDIA } from '../actions/entries';
|
||||||
|
|
||||||
|
const initialState = Map({entry: Map(), mediaFiles: List()});
|
||||||
|
|
||||||
|
export function entryDraft(state = Map(), action) {
|
||||||
|
switch (action.type) {
|
||||||
|
case DRAFT_CREATE:
|
||||||
|
if (!action.payload) {
|
||||||
|
// New entry
|
||||||
|
return initialState;
|
||||||
|
}
|
||||||
|
// Existing Entry
|
||||||
|
return state.withMutations((state) => {
|
||||||
|
state.set('entry', action.payload);
|
||||||
|
state.set('mediaFiles', List());
|
||||||
|
});
|
||||||
|
case DRAFT_DISCARD:
|
||||||
|
return initialState;
|
||||||
|
case DRAFT_CHANGE:
|
||||||
|
return state.set('entry', action.payload);
|
||||||
|
|
||||||
|
case DRAFT_ADD_MEDIA:
|
||||||
|
return state.update('mediaFiles', (list) => list.push(action.payload));
|
||||||
|
|
||||||
|
case DRAFT_REMOVE_MEDIA:
|
||||||
|
const mediaIndex = state.get('mediaFiles').indexOf(action.payload);
|
||||||
|
if (mediaIndex === -1) return state;
|
||||||
|
return state.update('mediaFiles', (list) => list.splice(mediaIndex, 1));
|
||||||
|
|
||||||
|
default:
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
}
|
@ -5,6 +5,7 @@ import { syncHistory, routeReducer } from 'react-router-redux';
|
|||||||
import { auth } from '../reducers/auth';
|
import { auth } from '../reducers/auth';
|
||||||
import { config } from '../reducers/config';
|
import { config } from '../reducers/config';
|
||||||
import { entries } from '../reducers/entries';
|
import { entries } from '../reducers/entries';
|
||||||
|
import { entryDraft } from '../reducers/entryDraft';
|
||||||
import { collections } from '../reducers/collections';
|
import { collections } from '../reducers/collections';
|
||||||
|
|
||||||
const reducer = combineReducers({
|
const reducer = combineReducers({
|
||||||
@ -12,6 +13,7 @@ const reducer = combineReducers({
|
|||||||
config,
|
config,
|
||||||
collections,
|
collections,
|
||||||
entries,
|
entries,
|
||||||
|
entryDraft,
|
||||||
router: routeReducer
|
router: routeReducer
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -3,12 +3,11 @@ export const setConfig = (configObj) => {
|
|||||||
config = configObj;
|
config = configObj;
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function ImageProxy(value, file, uploaded = false) {
|
export default function ImageProxy(value, objectURL, uploaded = false) {
|
||||||
this.value = value;
|
this.value = value;
|
||||||
this.file = file;
|
|
||||||
this.uploaded = uploaded;
|
this.uploaded = uploaded;
|
||||||
this.uri = config.media_folder && !uploaded ? config.media_folder + '/' + value : value;
|
this.uri = config.media_folder && !uploaded ? config.media_folder + '/' + value : value;
|
||||||
this.toString = function() {
|
this.toString = function() {
|
||||||
return uploaded ? this.uri : window.URL.createObjectURL(this.file, {oneTimeOnly: true});
|
return uploaded ? this.uri : objectURL;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user