diff --git a/src/components/MapNarratives.jsx b/src/components/MapNarratives.jsx index 8b92bb8..9d7248b 100644 --- a/src/components/MapNarratives.jsx +++ b/src/components/MapNarratives.jsx @@ -18,59 +18,79 @@ class MapNarratives extends React.Component { return this.props.narrativeProps[styleName] } - getStrokeWidth(narrative, step) { - if (!step) return 0 - return this.getNarrativeStyle(narrative.id).strokeWidth - } - - getStrokeDashArray(narrative, step) { - if (!step) return 'none' - return (this.getNarrativeStyle(narrative.id).style === 'dotted') ? "2px 5px" : 'none' - } - - getStroke(narrative, step) { - if (!step || this.props.narrative === null) return 'none' - return this.getNarrativeStyle(narrative.id).stroke - } - - getStrokeOpacity(narrative, step) { - if (this.props.narrative === null) return 0 - if (!step || narrative.id !== this.props.narrative.id) return 0.1 - return 1 + getStepStyle(name) { + if (name === 'None') return null + return this.props.narrativeProps.stepStyles[name] } hasNoLocation(step) { return (step.latitude === '' || step.longitude === '') } - renderNarrativeStep(allSteps, step, idx, n) { - const { x, y } = this.projectPoint([step.latitude, step.longitude]) - const step2 = allSteps[idx + 1] + renderNarrativeStep(idx, n) { + const step = n.steps[idx] + const step2 = n.steps[idx + 1] // don't draw if one of the steps has no location if (this.hasNoLocation(step) || this.hasNoLocation(step2)) return null + // 0 if not in narrative mode, 1 if active narrative, 0.1 if inactive + let styles = { + strokeOpacity: (n === null) ? 0 + : (step && (n.id === this.props.narrative.id)) ? 1 : 0.1, + strokeWidth: 0, + strokeDasharray: 'none', + stroke: 'none' + } + + const p1 = this.projectPoint([step.latitude, step.longitude]) const p2 = this.projectPoint([step2.latitude, step2.longitude]) + if (step) { + if (process.env.features.NARRATIVE_STEP_STYLES) { + const _idx = step.narratives.indexOf(n.id) + const stepStyle = step.narrative___stepStyles[_idx] + + return this._renderNarrativeStep( + p1, + p2, + { ...styles, ...this.getStepStyle(stepStyle) } + ) + + // otherwise steps are styled per narrative + } else { + styles = { + ...styles, + ...this.getNarrativeStyle(n.id) + } + return this._renderNarrativeStep(p1,p2,styles) + } + } + + } + + _renderNarrativeStep(p1, p2, styles) { + const { stroke, strokeWidth, strokeDasharray, strokeOpacity } = styles return ( this.props.onSelectNarrative(n)} style={{ - strokeWidth: this.getStrokeWidth(n, step), - strokeDasharray: this.getStrokeDashArray(n, step), - strokeOpacity: this.getStrokeOpacity(n, step), - stroke: this.getStroke(n, step) + strokeWidth, + strokeDasharray, + strokeOpacity, + stroke, }} > ) + } renderNarrative(n) { @@ -78,7 +98,7 @@ class MapNarratives extends React.Component { return ( - {steps.map((s, idx) => this.renderNarrativeStep(n.steps, s, idx, n))} + {steps.map((s, idx) => this.renderNarrativeStep(idx, n))} ) } diff --git a/src/components/Md.jsx b/src/components/Md.jsx index 2510359..eefb1ba 100644 --- a/src/components/Md.jsx +++ b/src/components/Md.jsx @@ -12,6 +12,9 @@ class Md extends React.Component { fetch(this.props.path) .then(resp => resp.text()) .then(text => { + if (text.length <= 0) + throw new Error() + this.setState({ md: marked(text) }) }) .catch(err => { @@ -34,7 +37,7 @@ class Md extends React.Component { Md.propTypes = { loader: PropTypes.func, - unloader: PropTypes.func, + unloader: PropTypes.func.isRequired, path: PropTypes.string.isRequired } diff --git a/src/components/SourceOverlay.jsx b/src/components/SourceOverlay.jsx index 452eebf..b9034ff 100644 --- a/src/components/SourceOverlay.jsx +++ b/src/components/SourceOverlay.jsx @@ -7,15 +7,21 @@ import NoSource from './presentational/NoSource' // TODO: move render functions into presentational components function SourceOverlay ({ source, onCancel }) { + function renderError() { + return ( + + ) + } + function renderImage(path) { return (
- } - unloader={} - /> + } + unloader={} + />
) } @@ -45,11 +51,6 @@ function SourceOverlay ({ source, onCancel }) { ) } - function renderError() { - return ( - - ) - } function renderNoSupport(ext) { return ( diff --git a/src/components/Toolbar.jsx b/src/components/Toolbar.jsx index cb3b3da..542456f 100644 --- a/src/components/Toolbar.jsx +++ b/src/components/Toolbar.jsx @@ -29,7 +29,7 @@ class Toolbar extends React.Component { } renderSearch() { - if (this.props.features.USE_SEARCH) { + if (process.env.features.USE_SEARCH) { return ( diff --git a/src/reducers/schema/eventSchema.js b/src/reducers/schema/eventSchema.js index 614eba2..7e9b38a 100644 --- a/src/reducers/schema/eventSchema.js +++ b/src/reducers/schema/eventSchema.js @@ -16,6 +16,9 @@ const eventSchema = Joi.object().keys({ tags: Joi.string().allow(''), comments: Joi.string().allow(''), timestamp: Joi.string().required(), + + // nested + narrative___stepStyles: Joi.array(), }); export default eventSchema; diff --git a/src/store/initial.js b/src/store/initial.js index 8db1642..77e66d3 100644 --- a/src/store/initial.js +++ b/src/store/initial.js @@ -89,10 +89,6 @@ const initial = { duration: 10, active: false }], - features: { - USE_TAGS: process.env.features.USE_TAGS, - USE_SEARCH: process.env.features.USE_SEARCH - }, flags: { isFetchingDomain: false, isFetchingSources: false, @@ -120,16 +116,22 @@ const initial = { narratives: { default: { - style: 'solid', // ['dotted', 'solid'] - opacity: 0.9, // range between 0 and 1 - stroke: 'red', // Any hex or rgb code + opacity: 0.9, + stroke: 'red', strokeWidth: 3 }, narrative_1: { - style: 'solid', // ['dotted', 'solid'] - opacity: 0.4, // range between 0 and 1 - stroke: '#f18f01', // Any hex or rgb code + opacity: 0.4, + stroke: '#f18f01', strokeWidth: 3 + }, + // process.env.features.NARRATIVE_STEP_STYLES + stepStyles: { + Physical: { + stroke: 'yellow', + strokeWidth: 3, + opacity: 0.9, + } } } }, diff --git a/webpack.config.js b/webpack.config.js index 768e021..5475885 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -1,8 +1,6 @@ const webpack = require('webpack'); const MiniCssExtractPlugin = require('mini-css-extract-plugin'); const HtmlWebpackPlugin = require('html-webpack-plugin'); -const userConfig = require('./config'); -const userConfigJSON = {}; const devMode = process.env.NODE_ENV !== 'production'; const path = require('path'); @@ -10,8 +8,16 @@ const path = require('path'); const APP_DIR = path.resolve(__dirname, './src'); const BUILD_DIR = path.resolve(__dirname, './build'); -for (const k in userConfig) { - userConfigJSON[k] = JSON.stringify(userConfig[k]); +/** env variables from config.js */ +const envConfig = require('./config'); +const userConfig = {} +const userFeatures = {} +for (const k in envConfig) { + userConfig[k] = JSON.stringify(envConfig[k]); +} + +for (const k in envConfig['features']) { + userFeatures[k] = JSON.stringify(envConfig['features'][k]) } const config = { @@ -59,14 +65,9 @@ const config = { plugins: [ new webpack.DefinePlugin({ 'process.env': { - ...userConfigJSON, + ...userConfig, 'NODE_ENV': JSON.stringify('production'), - 'features': { - 'USE_TAGS': JSON.stringify(userConfig.features.USE_TAGS), - 'USE_SEARCH': JSON.stringify(userConfig.features.USE_SEARCH), - 'USE_SITES': JSON.stringify(userConfig.features.USE_SITES), - 'USE_SOURCES': JSON.stringify(userConfig.features.USE_SOURCES) - } + 'features': userFeatures } }), new MiniCssExtractPlugin({