From 1700f98e4e12bea2076e6f75c3afc53c1cf6021d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A1ssio=20Zen?= Date: Fri, 10 Jun 2016 14:01:14 -0300 Subject: [PATCH] Refactor on upload media data fow --- src/actions/media.js | 9 ++++++-- src/components/ControlPane.js | 3 ++- src/components/EntryEditor.js | 3 ++- src/components/Widgets/ImageControl.js | 30 +++++++++++--------------- src/containers/EntryPage.js | 14 ++++++------ src/reducers/entryDraft.js | 6 ++++-- src/reducers/medias.js | 15 +++++++------ src/valueObjects/MediaProxy.js | 7 +++--- 8 files changed, 47 insertions(+), 40 deletions(-) diff --git a/src/actions/media.js b/src/actions/media.js index 20fc6df8..88f822ff 100644 --- a/src/actions/media.js +++ b/src/actions/media.js @@ -1,5 +1,10 @@ export const ADD_MEDIA = 'ADD_MEDIA'; +export const REMOVE_MEDIA = 'REMOVE_MEDIA'; -export function addMedia(file) { - return { type: ADD_MEDIA, payload: file }; +export function addMedia(mediaProxy) { + return {type: ADD_MEDIA, payload: mediaProxy}; +} + +export function removeMedia(uri) { + return {type: REMOVE_MEDIA, payload: uri}; } diff --git a/src/components/ControlPane.js b/src/components/ControlPane.js index 4dacd838..18d4fae5 100644 --- a/src/components/ControlPane.js +++ b/src/components/ControlPane.js @@ -3,7 +3,7 @@ import Widgets from './Widgets'; export default class ControlPane extends React.Component { controlFor(field) { - const { entry, getMedia, onChange, onAddMedia } = this.props; + const { entry, getMedia, onChange, onAddMedia, onRemoveMedia } = this.props; const widget = Widgets[field.get('widget')] || Widgets._unknown; return React.createElement(widget.Control, { key: field.get('name'), @@ -11,6 +11,7 @@ export default class ControlPane extends React.Component { value: entry.getIn(['data', field.get('name')]), onChange: (value) => onChange(entry.setIn(['data', field.get('name')], value)), onAddMedia: onAddMedia, + onRemoveMedia: onRemoveMedia, getMedia: getMedia }); } diff --git a/src/components/EntryEditor.js b/src/components/EntryEditor.js index 7ad3f482..5c344364 100644 --- a/src/components/EntryEditor.js +++ b/src/components/EntryEditor.js @@ -5,7 +5,7 @@ import PreviewPane from './PreviewPane'; export default class EntryEditor extends React.Component { render() { - const { collection, entry, getMedia, onChange, onAddMedia, onPersist } = this.props; + const { collection, entry, getMedia, onChange, onAddMedia, onRemoveMedia, onPersist } = this.props; return

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

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

@@ -17,6 +17,7 @@ export default class EntryEditor extends React.Component { getMedia={getMedia} onChange={onChange} onAddMedia={onAddMedia} + onRemoveMedia={onRemoveMedia} />
diff --git a/src/components/Widgets/ImageControl.js b/src/components/Widgets/ImageControl.js index 1e15a0b5..dbf01c67 100644 --- a/src/components/Widgets/ImageControl.js +++ b/src/components/Widgets/ImageControl.js @@ -1,5 +1,6 @@ import React from 'react'; import { truncateMiddle } from '../../lib/textHelper'; +import MediaProxy from '../../valueObjects/MediaProxy'; const MAX_DISPLAY_LENGTH = 50; @@ -7,11 +8,6 @@ export default class ImageControl extends React.Component { constructor(props) { super(props); - this.state = { - currentImage: props.value - }; - - this.revokeCurrentImage = this.revokeCurrentImage.bind(this); this.handleChange = this.handleChange.bind(this); this.handleFileInputRef = this.handleFileInputRef.bind(this); this.handleClick = this.handleClick.bind(this); @@ -20,12 +16,6 @@ export default class ImageControl extends React.Component { this.renderImageName = this.renderImageName.bind(this); } - revokeCurrentImage() { - if (this.state.currentImage) { - //this.props.onRemoveMedia(this.state.currentImage); - } - } - handleFileInputRef(el) { this._fileInput = el; } @@ -47,7 +37,7 @@ export default class ImageControl extends React.Component { handleChange(e) { e.stopPropagation(); e.preventDefault(); - this.revokeCurrentImage(); + const fileList = e.dataTransfer ? e.dataTransfer.files : e.target.files; const files = [...fileList]; const imageType = /^image\//; @@ -59,21 +49,25 @@ export default class ImageControl extends React.Component { } }); + this.props.onRemoveMedia(this.props.value); if (file) { - this.props.onAddMedia(file); - this.props.onChange(file.name); - this.setState({currentImage: file.name}); + const mediaProxy = new MediaProxy(file.name, file); + this.props.onAddMedia(mediaProxy); + this.props.onChange(mediaProxy.uri); } else { this.props.onChange(null); - this.setState({currentImage: null}); } } renderImageName() { + if (!this.props.value) return null; + if (this.value instanceof MediaProxy) { + return truncateMiddle(this.props.value.uri, MAX_DISPLAY_LENGTH); + } else { + return truncateMiddle(this.props.value, MAX_DISPLAY_LENGTH); + } - if (!this.state.currentImage) return null; - return truncateMiddle(this.props.getMedia(this.state.currentImage).uri, MAX_DISPLAY_LENGTH); } render() { diff --git a/src/containers/EntryPage.js b/src/containers/EntryPage.js index 25e6c1ec..aff9eb35 100644 --- a/src/containers/EntryPage.js +++ b/src/containers/EntryPage.js @@ -7,7 +7,7 @@ import { changeDraft, persist } from '../actions/entries'; -import { addMedia } from '../actions/media'; +import { addMedia, removeMedia } from '../actions/media'; import { selectEntry, getMedia } from '../reducers'; import EntryEditor from '../components/EntryEditor'; @@ -40,7 +40,7 @@ class EntryPage extends React.Component { render() { const { - entry, entryDraft, boundGetMedia, collection, handleDraftChange, handleAddMedia, handleDraftRemoveMedia + entry, entryDraft, boundGetMedia, collection, changeDraft, addMedia, removeMedia } = this.props; if (entry == null || entryDraft.get('entry') == undefined || entry.get('isFetching')) { @@ -51,8 +51,9 @@ class EntryPage extends React.Component { entry={entryDraft.get('entry')} getMedia={boundGetMedia} collection={collection} - onChange={handleDraftChange} - onAddMedia={handleAddMedia} + onChange={changeDraft} + onAddMedia={addMedia} + onRemoveMedia={removeMedia} onPersist={this.handlePersist} /> ); @@ -71,8 +72,9 @@ function mapStateToProps(state, ownProps) { export default connect( mapStateToProps, { - handleDraftChange: changeDraft, - handleAddMedia: addMedia, + changeDraft, + addMedia, + removeMedia, loadEntry, createDraft, discardDraft, diff --git a/src/reducers/entryDraft.js b/src/reducers/entryDraft.js index 7b99298a..67c999ff 100644 --- a/src/reducers/entryDraft.js +++ b/src/reducers/entryDraft.js @@ -1,6 +1,6 @@ import { Map, List } from 'immutable'; import { DRAFT_CREATE, DRAFT_DISCARD, DRAFT_CHANGE } from '../actions/entries'; -import { ADD_MEDIA } from '../actions/media'; +import { ADD_MEDIA, REMOVE_MEDIA } from '../actions/media'; const initialState = Map({entry: Map(), mediaFiles: List()}); @@ -22,7 +22,9 @@ const entryDraft = (state = Map(), action) => { return state.set('entry', action.payload); case ADD_MEDIA: - return state.update('mediaFiles', (list) => list.push(action.payload.name)); + return state.update('mediaFiles', (list) => list.push(action.payload.uri)); + case REMOVE_MEDIA: + return state.update('mediaFiles', (list) => list.filterNot((uri) => uri === action.payload)); default: return state; diff --git a/src/reducers/medias.js b/src/reducers/medias.js index 46f11f63..918a170d 100644 --- a/src/reducers/medias.js +++ b/src/reducers/medias.js @@ -1,11 +1,13 @@ import { Map } from 'immutable'; -import { ADD_MEDIA } from '../actions/media'; +import { ADD_MEDIA, REMOVE_MEDIA } from '../actions/media'; import MediaProxy from '../valueObjects/MediaProxy'; const medias = (state = Map(), action) => { switch (action.type) { case ADD_MEDIA: - return state.set(action.payload.name, action.payload); + return state.set(action.payload.uri, action.payload); + case REMOVE_MEDIA: + return state.delete(action.payload); default: return state; } @@ -13,11 +15,10 @@ const medias = (state = Map(), action) => { export default medias; -export const getMedia = (state, filePath) => { - const fileName = filePath.substring(filePath.lastIndexOf('/') + 1); - if (state.has(fileName)) { - return new MediaProxy(fileName, window.URL.createObjectURL(state.get(fileName), {oneTimeOnly: true})); +export const getMedia = (state, uri) => { + if (state.has(uri)) { + return state.get(uri); } else { - return new MediaProxy(filePath, null, filePath, true); + return new MediaProxy(uri, null, true); } }; diff --git a/src/valueObjects/MediaProxy.js b/src/valueObjects/MediaProxy.js index 338139eb..949e79d7 100644 --- a/src/valueObjects/MediaProxy.js +++ b/src/valueObjects/MediaProxy.js @@ -3,11 +3,12 @@ export const setConfig = (configObj) => { config = configObj; }; -export default function MediaProxy(value, objectURL, uri, uploaded = false) { +export default function MediaProxy(value, file, uploaded = false) { this.value = value; + this.file = file; this.uploaded = uploaded; - this.uri = uri || config.media_folder && config.media_folder + '/' + value; + this.uri = config.media_folder && !uploaded ? config.media_folder + '/' + value : value; this.toString = function() { - return uploaded ? this.uri : objectURL; + return uploaded ? this.uri : window.URL.createObjectURL(this.file, {oneTimeOnly: true}); }; }