From 8d9f8949280acdeb81b7eb4368895906117a4225 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A1ssio=20Zen?= Date: Thu, 17 Nov 2016 11:12:14 -0200 Subject: [PATCH 1/2] Use public_folder to display images persisted with no path reference --- src/components/EntryListing/EntryListing.js | 14 +++++++++----- src/containers/CollectionPage.js | 9 ++++++--- src/reducers/index.js | 2 +- src/reducers/medias.js | 10 +++++++--- 4 files changed, 23 insertions(+), 12 deletions(-) diff --git a/src/components/EntryListing/EntryListing.js b/src/components/EntryListing/EntryListing.js index 776fd6ed..2aaac27f 100644 --- a/src/components/EntryListing/EntryListing.js +++ b/src/components/EntryListing/EntryListing.js @@ -10,6 +10,7 @@ import styles from './EntryListing.css'; export default class EntryListing extends React.Component { static propTypes = { children: PropTypes.node.isRequired, + publicFolder: PropTypes.string.isRequired, collections: PropTypes.oneOfType([ ImmutablePropTypes.map, ImmutablePropTypes.iterable, @@ -23,7 +24,7 @@ export default class EntryListing extends React.Component { this.props.onPaginate(this.props.page + 1); }; - inferFields(collection) { + inferFields(collection) { //eslint-disable-line const titleField = selectInferedField(collection, 'title'); const descriptionField = selectInferedField(collection, 'description'); const imageField = selectInferedField(collection, 'image'); @@ -33,11 +34,14 @@ export default class EntryListing extends React.Component { return { titleField, descriptionField, imageField, remainingFields }; } - renderCard(collection, entry, inferedFields) { + renderCard(collection, entry, inferedFields, publicFolder) { const path = `/collections/${ collection.get('name') }/entries/${ entry.get('slug') }`; const label = entry.get('label'); const title = label || entry.getIn(['data', inferedFields.titleField]); - const image = entry.getIn(['data', inferedFields.imageField]); + let image = entry.getIn(['data', inferedFields.imageField]); + if (image && image.indexOf('/') === -1) { + image = `/${ publicFolder }/${ image }`; + } return ( { - const { collections, entries } = this.props; + const { collections, entries, publicFolder } = this.props; if (Map.isMap(collections)) { const inferedFields = this.inferFields(collections); - return entries.map(entry => this.renderCard(collections, entry, inferedFields)); + return entries.map(entry => this.renderCard(collections, entry, inferedFields, publicFolder)); } return entries.map((entry) => { const collection = collections diff --git a/src/containers/CollectionPage.js b/src/containers/CollectionPage.js index 62199cbf..23030666 100644 --- a/src/containers/CollectionPage.js +++ b/src/containers/CollectionPage.js @@ -12,6 +12,7 @@ class CollectionPage extends React.Component { static propTypes = { collection: ImmutablePropTypes.map.isRequired, collections: ImmutablePropTypes.orderedMap.isRequired, + publicFolder: PropTypes.string.isRequired, dispatch: PropTypes.func.isRequired, page: PropTypes.number, entries: ImmutablePropTypes.list, @@ -37,7 +38,7 @@ class CollectionPage extends React.Component { }; render() { - const { collections, collection, page, entries } = this.props; + const { collections, collection, publicFolder, page, entries } = this.props; if (collections == null) { return

No collections defined in your config.yml

; } @@ -46,6 +47,7 @@ class CollectionPage extends React.Component { @@ -60,14 +62,15 @@ class CollectionPage extends React.Component { function mapStateToProps(state, ownProps) { - const { collections } = state; + const { collections, config } = state; const { name, slug } = ownProps.params; + const publicFolder = config.get('public_folder'); const collection = name ? collections.get(name) : collections.first(); const page = state.entries.getIn(['pages', collection.get('name'), 'page']); const entries = selectEntries(state, collection.get('name')); - return { slug, collection, collections, page, entries }; + return { slug, publicFolder, collection, collections, page, entries }; } export default connect(mapStateToProps)(CollectionPage); diff --git a/src/reducers/index.js b/src/reducers/index.js index 112628d1..99f3448a 100644 --- a/src/reducers/index.js +++ b/src/reducers/index.js @@ -46,4 +46,4 @@ export const selectIntegration = (state, collection, hook) => fromIntegrations.selectIntegration(state.integrations, collection, hook); export const getMedia = (state, path) => - fromMedias.getMedia(state.medias, path); + fromMedias.getMedia(state.config.get('public_folder'), state.medias, path); diff --git a/src/reducers/medias.js b/src/reducers/medias.js index 87b7f8cc..0b551c5c 100644 --- a/src/reducers/medias.js +++ b/src/reducers/medias.js @@ -16,10 +16,14 @@ const medias = (state = Map(), action) => { export default medias; -export const getMedia = (state, path) => { +export const getMedia = (publicFolder, state, path) => { if (state.has(path)) { return state.get(path); - } else { - return new MediaProxy(path, null, true); } + + let localPath = path; + if (path && path.indexOf('/') === -1) { + localPath = `/${ publicFolder }/${ localPath }`; + } + return new MediaProxy(localPath, null, true); }; From 695f533c8e74f46443f25cc2a1ba01536da0c90e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A1ssio=20Zen?= Date: Thu, 17 Nov 2016 15:33:02 -0200 Subject: [PATCH 2/2] Added resolvePath helper to normalize and prepend the public_path and as needed --- src/components/EntryListing/EntryListing.js | 5 ++--- src/lib/pathHelper.js | 18 ++++++++++++++++++ src/reducers/medias.js | 12 +++++++----- 3 files changed, 27 insertions(+), 8 deletions(-) create mode 100644 src/lib/pathHelper.js diff --git a/src/components/EntryListing/EntryListing.js b/src/components/EntryListing/EntryListing.js index 2aaac27f..60b66419 100644 --- a/src/components/EntryListing/EntryListing.js +++ b/src/components/EntryListing/EntryListing.js @@ -3,6 +3,7 @@ import ImmutablePropTypes from 'react-immutable-proptypes'; import Waypoint from 'react-waypoint'; import { Map } from 'immutable'; import history from '../../routing/history'; +import { resolvePath } from '../../lib/pathHelper'; import { selectFields, selectInferedField } from '../../reducers/collections'; import { Card } from '../UI'; import styles from './EntryListing.css'; @@ -39,9 +40,7 @@ export default class EntryListing extends React.Component { const label = entry.get('label'); const title = label || entry.getIn(['data', inferedFields.titleField]); let image = entry.getIn(['data', inferedFields.imageField]); - if (image && image.indexOf('/') === -1) { - image = `/${ publicFolder }/${ image }`; - } + image = resolvePath(image, publicFolder); return ( path.replace(/[\\\/]+/g, '/'); + +export function resolvePath(path, basePath) { // eslint-disable-line + // No path provided, skip + if (!path) return null; + + // It's an absolute path. + if (absolutePath.test(path)) return normalizePath(path); + + if (path.indexOf('/') === -1) { + // It's a single file name, no directories. Prepend public folder + return normalizePath(`/${ basePath }/${ path }`); + } + + // It's a relative path. Prepend a forward slash. + return normalizePath(`/${ path }`); +} diff --git a/src/reducers/medias.js b/src/reducers/medias.js index 0b551c5c..65862b95 100644 --- a/src/reducers/medias.js +++ b/src/reducers/medias.js @@ -1,4 +1,5 @@ import { Map } from 'immutable'; +import { resolvePath } from '../lib/pathHelper'; import { ADD_MEDIA, REMOVE_MEDIA } from '../actions/media'; import MediaProxy from '../valueObjects/MediaProxy'; @@ -17,13 +18,14 @@ const medias = (state = Map(), action) => { export default medias; export const getMedia = (publicFolder, state, path) => { + // No path provided, skip + if (!path) return null; + if (state.has(path)) { + // There is already a MediaProxy in memmory for this path. Use it. return state.get(path); } - let localPath = path; - if (path && path.indexOf('/') === -1) { - localPath = `/${ publicFolder }/${ localPath }`; - } - return new MediaProxy(localPath, null, true); + // Create a new MediaProxy (for consistency) and return it. + return new MediaProxy(resolvePath(path, publicFolder), null, true); };