diff --git a/package.json b/package.json index c5d556e..45e07bd 100644 --- a/package.json +++ b/package.json @@ -19,6 +19,7 @@ "marked": "^0.6.0", "normalizr": "^3.2.3", "object-hash": "^1.3.0", + "ramda": "^0.26.1", "react": "^16.6.3", "react-dom": "^16.6.3", "react-image": "^1.5.1", diff --git a/src/components/Dashboard.jsx b/src/components/Dashboard.jsx index e0a59aa..5817f83 100644 --- a/src/components/Dashboard.jsx +++ b/src/components/Dashboard.jsx @@ -14,7 +14,7 @@ import InfoPopUp from './InfoPopup.jsx' import Timeline from './Timeline.jsx' import Notification from './Notification.jsx' -import { parseDate } from '../js/utilities' +import { parseDate, injectSource } from '../js/utilities' class Dashboard extends React.Component { constructor(props) { @@ -60,8 +60,8 @@ class Dashboard extends React.Component { } } - getCategoryColor(category='other') { - return this.props.ui.style.categories[category] || this.props.ui.style.categories['other'] + getCategoryColor(category) { + return this.props.ui.style.categories[category] || this.props.ui.style.categories['default'] } getNarrativeLinks(event) { @@ -171,5 +171,6 @@ function mapDispatchToProps(dispatch) { export default connect( state => state, + // state => injectSource("Youtube - Novodvirske Tank Separatist Patrol Video"), mapDispatchToProps, )(Dashboard) diff --git a/src/components/Md.jsx b/src/components/Md.jsx index eefb1ba..95060e0 100644 --- a/src/components/Md.jsx +++ b/src/components/Md.jsx @@ -25,7 +25,7 @@ class Md extends React.Component { render() { if (this.state.md && !this.state.error) { return ( -
+
) } else if (this.state.error) { return this.props.unloader ||
Error: couldn't load source
diff --git a/src/components/SourceOverlay.jsx b/src/components/SourceOverlay.jsx index ea94e2d..9191307 100644 --- a/src/components/SourceOverlay.jsx +++ b/src/components/SourceOverlay.jsx @@ -6,27 +6,36 @@ import Spinner from './presentational/Spinner' import NoSource from './presentational/NoSource' // TODO: move render functions into presentational components -function SourceOverlay ({ source, onCancel }) { - function renderError() { +class SourceOverlay extends React.Component { + + constructor() { + super() + + this.state = { + idx: 0 + } + } + + renderError() { return ( ) } - function renderImage(path) { + renderImage(path) { return (
} - unloader={} + unloader={} />
) } - function renderVideo(path) { + renderVideo(path) { // NB: assume only one video return (
@@ -39,26 +48,26 @@ function SourceOverlay ({ source, onCancel }) { ) } - function renderText(path) { + renderText(path) { return (
} - unloader={renderError()} + unloader={() => this.renderError()} />
) } - function renderNoSupport(ext) { + renderNoSupport(ext) { return ( ) } - function toMedia(path) { + toMedia(path) { let type; switch (true) { case /\.(png|jpg)$/.test(path): @@ -73,7 +82,7 @@ function SourceOverlay ({ source, onCancel }) { return { type, path } } - function getTypeCounts(media) { + getTypeCounts(media) { let counts = { Image: 0, Video: 0, Text: 0 } media.forEach(m => { counts[m.type] += 1 @@ -81,21 +90,21 @@ function SourceOverlay ({ source, onCancel }) { return counts } - function _renderPath(media) { + _renderPath(media) { const { path, type } = media switch (type) { case 'Image': - return renderImage(path) + return this.renderImage(path) case 'Video': - return renderVideo(path) + return this.renderVideo(path) case 'Text': - return renderText(path) + return this.renderText(path) default: - return renderNoSupport(path.split('.')[1]) + return this.renderNoSupport(path.split('.')[1]) } } - function _renderCounts(counts) { + _renderCounts(counts) { const strFor = type => counts[type] > 0 ? `${counts[type]} ${type.toLowerCase()}${counts[type] > 1 ? 's': ''}` @@ -113,52 +122,84 @@ function SourceOverlay ({ source, onCancel }) { ) } - function _renderContent(media) { + _renderContent(media) { + const el = document.querySelector(`.source-media-gallery`); + const shiftW = (!!el) ? el.getBoundingClientRect().width : 0; return ( - - {media.map(_renderPath)} - +
+ {media.map((m) => this._renderPath(m))} +
) } - if (typeof(source) !== 'object') { - return renderError() + onShiftGallery(shift) { + if (this.state.idx === 0 && shift === -1) return; + if (this.state.idx - 1 === this.props.source.paths.length && shift === 1) return + this.setState({ idx: this.state.idx+shift }); } - const {id, url, title, paths, date, type, desc} = source - const media = paths.map(toMedia) - const counts = getTypeCounts(media) + _renderControls() { + if (this.props.source.paths.length > 1) { + return ( +
+
this.onShiftGallery(-1)}>
+
this.onShiftGallery(1)}>
+
+ ); + } + return ( +
+ ); + } - return ( -
-
{ e.stopPropagation(); }}> -
-
- + render () { + if (typeof(this.props.source) !== 'object') { + return this.renderError() + } + const {id, url, title, paths, date, type, desc} = this.props.source + const media = paths.map(this.toMedia) + const counts = this.getTypeCounts(media) + + return ( +
+
{ e.stopPropagation(); }}> +
+
+ +
+
{this.props.source.title}
-
{source.title}
-
-
- {_renderContent(media)} -
-
-
- {title?

{title}

: null} -
{_renderCounts(counts)}
-
- {type ?

Media type

: null} - {type ?

perm_media{type}

: null} - {date ?

Date

: null} - {date ?

today{date}

: null} - {url ?

Link

: null} - {url ? linkLink to original URL : null} - {desc ?
: null} - {desc ?
{desc}
: null} +
+ {this._renderContent(media)} + {this._renderControls()} +
+
+
+

{`${this.state.idx+1} / ${paths.length}`}

+ {title?

{title}

: null} +
{desc}
+
+ +
+
+ {type ?

Media type

: null} + {type ?

perm_media{type}

: null} +
+
+ {date ?

Date

: null} + {date ?

today{date}

: null} +
+
+ {url ?

Link

: null} + {url ? linkLink to original URL : null} +
+
-
- ) + ) + + } } export default SourceOverlay diff --git a/src/components/Timeline.jsx b/src/components/Timeline.jsx index 5c42e17..8d7104b 100644 --- a/src/components/Timeline.jsx +++ b/src/components/Timeline.jsx @@ -20,6 +20,7 @@ class Timeline extends React.Component { super(props); this.styleDatetime = this.styleDatetime.bind(this) this.getDatetimeX = this.getDatetimeX.bind(this) + this.onApplyZoom = this.onApplyZoom.bind(this) this.svgRef = React.createRef() this.state = { isFolded: false, @@ -99,6 +100,7 @@ class Timeline extends React.Component { * Returns the time scale (x) extent in minutes */ getTimeScaleExtent() { + if (!this.state.scaleX) return 0 const timeDomain = this.state.scaleX.domain(); return (timeDomain[1].getTime() - timeDomain[0].getTime()) / 60000; } @@ -153,7 +155,7 @@ class Timeline extends React.Component { this.setState({ timerange: [domain0, domainF] }, () => { this.props.methods.onUpdateTimerange(this.state.timerange); - }); + }); } /** @@ -284,9 +286,10 @@ class Timeline extends React.Component { onMoveTime={(dir) => { this.onMoveTime(dir) }} /> { this.onApplyZoom(zoom); }} + onApplyZoom={this.onApplyZoom} /> - + ); } } -export default TimelineAxis; \ No newline at end of file +export default TimelineAxis; diff --git a/src/components/TimelineCategories.jsx b/src/components/TimelineCategories.jsx index c90697c..25dce29 100644 --- a/src/components/TimelineCategories.jsx +++ b/src/components/TimelineCategories.jsx @@ -59,4 +59,4 @@ class TimelineCategories extends React.Component { } } -export default TimelineCategories; \ No newline at end of file +export default TimelineCategories; diff --git a/src/components/ToolbarBottomActions.jsx b/src/components/ToolbarBottomActions.jsx index 7e20bd2..e20a4be 100644 --- a/src/components/ToolbarBottomActions.jsx +++ b/src/components/ToolbarBottomActions.jsx @@ -14,7 +14,7 @@ function ToolbarBottomActions (props) { {/* isEnabled={this.props.viewFilters.routes} */} {/* /> */} {/* { - const classes = (isEnabled) ? 'action-button enabled' : 'action-button disabled'; +const SitesIcon = ({ isActive, isDisabled, onClickHandler }) => { + let classes = (isActive) ? 'action-button enabled' : 'action-button'; + if (isDisabled) { + classes = 'action-button disabled' + } return (
) } else { diff --git a/src/components/presentational/TimelineLabels.js b/src/components/presentational/TimelineLabels.js index 3f165aa..36466ba 100644 --- a/src/components/presentational/TimelineLabels.js +++ b/src/components/presentational/TimelineLabels.js @@ -22,23 +22,23 @@ const TimelineLabels = ({ dims, timelabels }) => { y2="20" > - - {formatterWithYear(timelabels[0])} - - - {formatterWithYear(timelabels[1])} - + {/* */} + {/* {formatterWithYear(timelabels[0])} */} + {/* */} + {/* */} + {/* {formatterWithYear(timelabels[1])} */} + {/* */} ) } -export default TimelineLabels; \ No newline at end of file +export default TimelineLabels; diff --git a/src/components/presentational/TimelineZoomControls.js b/src/components/presentational/TimelineZoomControls.js index 9b4f6c2..3c0a564 100644 --- a/src/components/presentational/TimelineZoomControls.js +++ b/src/components/presentational/TimelineZoomControls.js @@ -1,11 +1,11 @@ import React from 'react'; -const TimelineZoomControls = ({ zoomLevels, dims, onApplyZoom }) => { - +const TimelineZoomControls = ({ extent, zoomLevels, dims, onApplyZoom }) => { function renderZoom(zoom, idx) { + const isActive = (zoom.duration === extent) return ( onApplyZoom(zoom)} @@ -22,4 +22,4 @@ const TimelineZoomControls = ({ zoomLevels, dims, onApplyZoom }) => { ); } -export default TimelineZoomControls; \ No newline at end of file +export default TimelineZoomControls; diff --git a/src/js/utilities.js b/src/js/utilities.js index 5568b17..dc242c3 100644 --- a/src/js/utilities.js +++ b/src/js/utilities.js @@ -108,13 +108,15 @@ export function insetSourceFrom(allSources) { * view that source modal by default */ export function injectSource(id) { - return state => ({ - ...state, - app: { - ...state.app, - source: state.domain.sources[id] + return state => { + return { + ...state, + app: { + ...state.app, + source: state.domain.sources[id] + } } - }) + } } export function urlFromEnv(ext) { diff --git a/src/reducers/app.js b/src/reducers/app.js index b7164ea..43e39aa 100644 --- a/src/reducers/app.js +++ b/src/reducers/app.js @@ -1,4 +1,5 @@ import initial from '../store/initial.js' +import { parseDate } from '../js/utilities' import { UPDATE_HIGHLIGHTED, @@ -35,49 +36,49 @@ function updateSelected(appState, action) { } function updateNarrative(appState, action) { - let minTime = appState.filters.timerange[0]; - let maxTime = appState.filters.timerange[1]; + let minTime = appState.filters.timerange[0] + let maxTime = appState.filters.timerange[1] - let cornerBound0 = [180, 180]; - let cornerBound1 = [-180, -180]; + let cornerBound0 = [180, 180] + let cornerBound1 = [-180, -180] // Compute narrative time range and map bounds if (!!action.narrative) { - minTime = parseDate('2100-01-01T00:00:00'); - maxTime = parseDate('1900-01-01T00:00:00'); + minTime = parseDate('2100-01-01T00:00:00') + maxTime = parseDate('1900-01-01T00:00:00') // Find max and mins coordinates of narrative events action.narrative.steps.forEach(step => { - const stepTime = parseDate(step.timestamp); - if (stepTime < minTime) minTime = stepTime; - if (stepTime > maxTime) maxTime = stepTime; + const stepTime = parseDate(step.timestamp) + if (stepTime < minTime) minTime = stepTime + if (stepTime > maxTime) maxTime = stepTime if (!!step.longitude && !!step.latitude) { - if (+step.longitude < cornerBound0[1]) cornerBound0[1] = +step.longitude; - if (+step.longitude > cornerBound1[1]) cornerBound1[1] = +step.longitude; - if (+step.latitude < cornerBound0[0]) cornerBound0[0] = +step.latitude; - if (+step.latitude > cornerBound1[0]) cornerBound1[0] = +step.latitude; + if (+step.longitude < cornerBound0[1]) cornerBound0[1] = +step.longitude + if (+step.longitude > cornerBound1[1]) cornerBound1[1] = +step.longitude + if (+step.latitude < cornerBound0[0]) cornerBound0[0] = +step.latitude + if (+step.latitude > cornerBound1[0]) cornerBound1[0] = +step.latitude } - }); + }) // Adjust bounds to center around first event, while keeping visible all others // Takes first event, finds max ditance with first attempt bounds, and use this max distance // on the other side, both in latitude and longitude - const first = action.narrative.steps[0]; + const first = action.narrative.steps[0] if (!!first.longitude && !!first.latitude) { - const firstToLong0 = Math.abs(+first.longitude - cornerBound0[1]); - const firstToLong1 = Math.abs(+first.longitude - cornerBound1[1]); - const firstToLat0 = Math.abs(+first.latitude - cornerBound0[0]); - const firstToLat1 = Math.abs(+first.latitude - cornerBound1[0]); + const firstToLong0 = Math.abs(+first.longitude - cornerBound0[1]) + const firstToLong1 = Math.abs(+first.longitude - cornerBound1[1]) + const firstToLat0 = Math.abs(+first.latitude - cornerBound0[0]) + const firstToLat1 = Math.abs(+first.latitude - cornerBound1[0]) - if (firstToLong0 > firstToLong1) cornerBound1[1] = +first.longitude + firstToLong0; - if (firstToLong0 < firstToLong1) cornerBound0[1] = +first.longitude - firstToLong1; - if (firstToLat0 > firstToLat1) cornerBound1[0] = +first.latitude + firstToLat0; - if (firstToLat0 < firstToLat1) cornerBound0[0] = +first.latitude - firstToLat1; + if (firstToLong0 > firstToLong1) cornerBound1[1] = +first.longitude + firstToLong0 + if (firstToLong0 < firstToLong1) cornerBound0[1] = +first.longitude - firstToLong1 + if (firstToLat0 > firstToLat1) cornerBound1[0] = +first.latitude + firstToLat0 + if (firstToLat0 < firstToLat1) cornerBound0[0] = +first.latitude - firstToLat1 } - + // Add some buffer on both sides of the time extent - minTime = new Date(minTime.getTime() - Math.abs((maxTime - minTime) / 10)); - maxTime = new Date(maxTime.getTime() + Math.abs((maxTime - minTime) / 10)); + minTime = new Date(minTime.getTime() - Math.abs((maxTime - minTime) / 10)) + maxTime = new Date(maxTime.getTime() + Math.abs((maxTime - minTime) / 10)) } return { @@ -138,14 +139,14 @@ function updateTagFilters(appState, action) { function updateCategoryFilters(appState, action) { const categoryFilters = appState.filters.categories.slice(0) - const catFilter = categoryFilters.find(cF => cF.category === action.category.category); + const catFilter = categoryFilters.find(cF => cF.category === action.category.category) if (!catFilter) { categoryFilters.push(action.category) } else { - catFilter.active = (!!action.category.active); + catFilter.active = (!!action.category.active) } - + return Object.assign({}, appState, { filters: Object.assign({}, appState.filters, { diff --git a/src/reducers/schema/eventSchema.js b/src/reducers/schema/eventSchema.js index ae308e0..fb42cf5 100644 --- a/src/reducers/schema/eventSchema.js +++ b/src/reducers/schema/eventSchema.js @@ -3,22 +3,25 @@ import Joi from 'joi'; const eventSchema = Joi.object().keys({ id: Joi.string().required(), description: Joi.string().allow('').required(), - date: Joi.string().required(), - time: Joi.string().required(), + date: Joi.string().allow(''), + time: Joi.string().allow(''), time_precision: Joi.string().allow(''), - location: Joi.string().allow('').required(), - latitude: Joi.string().allow('').required(), - longitude: Joi.string().allow('').required(), + location: Joi.string().allow(''), + latitude: Joi.string().allow(''), + longitude: Joi.string().allow(''), type: Joi.string().allow(''), category: Joi.string().required(), narratives: Joi.array(), sources: Joi.array(), tags: Joi.array().allow(''), comments: Joi.string().allow(''), - timestamp: Joi.string().required(), + timestamp: Joi.string(), // nested narrative___stepStyles: Joi.array(), -}); +}) + .and('latitude', 'longitude') + .and('date', 'time', 'timestamp') + .or('timestamp', 'latitude') -export default eventSchema; +export default eventSchema diff --git a/src/scss/cardstack.scss b/src/scss/cardstack.scss index a79a44e..230d63c 100644 --- a/src/scss/cardstack.scss +++ b/src/scss/cardstack.scss @@ -2,16 +2,16 @@ @import 'card'; $card-width: 370px; -$narrative-info-max-height: 170px; +$narrative-info-max-height: 200px; $timeline-height: 170px; .card-stack { position: absolute; top: 10px; right: 10px; - max-height: calc(100% - 208px); + max-height: calc(100% - 180px); height: auto; - overflow: hidden; + overflow-y: scroll; box-shadow: 0 19px 38px rgba(0, 0, 0, 0.3), 0 15px 12px rgba(0, 0, 0, 0.22); z-index: $header; color: white; diff --git a/src/scss/mediaoverlay.scss b/src/scss/mediaoverlay.scss index d48a851..0bad5a2 100644 --- a/src/scss/mediaoverlay.scss +++ b/src/scss/mediaoverlay.scss @@ -1,7 +1,8 @@ -$panel-width: 800px; +$panel-width: 1000px; $panel-height: 700px; $vimeo-width: $panel-width - 100; $vimeo-height: $panel-height / 2; + $padding: 20px; $header-inset: 10px; @@ -20,6 +21,7 @@ $header-inset: 10px; } .mo-container { + background-color: rgba(239, 239, 239, 0.9); // max-width: $panel-width; // min-width: $panel-width; // max-height: $panel-height; @@ -27,43 +29,30 @@ $header-inset: 10px; display: flex; flex-direction: column; align-items: center; - max-height: 80vh; + height: 80vh; + width: $panel-width; max-width: 90vw; box-shadow: 0 19px 19px rgba(0, 0, 0, 0.3), 0 15px 12px rgba(0, 0, 0, 0.22); - .mo-media-container { - flex: 1; - display: flex; - flex-direction: column; - align-items: center; - } -} - -.mo-header { - min-height: 42px; - max-height: 42px; - margin-bottom: 2px; - border-radius: 2px; - width: 100%; - display: flex; - flex-direction: row; - background-color: black; - color: white; - - .mo-header-close { - display: flex; - justify-content: center; - align-items: center; - margin-left: $header-inset + 8px; + .back, .next { + width: 30px; + height: 30px; + background: $darkgrey; + color: $offwhite; + cursor: pointer; + box-shadow: 0 19px 19px rgba(0, 0, 0, 0.3), 0 15px 12px rgba(0, 0, 0, 0.22); + svg path { fill: $offwhite; } + z-index: 1; } - .mo-header-text { - flex: 1; - display: flex; - align-items: center; - justify-content: flex-end; - padding-right: $padding; - font-family: "Lato", Helvetica, sans-serif; + .back { + left: 10px; + svg path { transform: translate(17px,15px)rotate(-90deg)} + } + .next { + margin-left: calc(100% - 60px); + right: 10px; + svg path { transform: translate(17px,15px)rotate(90deg)} } } @@ -94,12 +83,17 @@ $header-inset: 10px; } .mo-media-container { - background-color: rgba(239, 239, 239, 0.9); + flex: 1; + /*display: flex; + flex-direction: row; + justify-content: center; + align-items: center;*/ + display: inline-block; + overflow-x: hidden; box-sizing: border-box; - min-width: 100%; + width: 100%; max-height: 60vh; padding: 20px; - overflow-y: auto; font-family: "Lato", Helvetica, sans-serif; .media-player { @@ -112,6 +106,14 @@ $header-inset: 10px; flex-direction: column; } + .media-gallery-controls { + height: 100%; + display: flex; + justify-content: center; + align-items: center; + margin-top: -50%; + } + // NB: topcushion seems to be necessary with certain overflows.. &.topcushion { padding-top: 150px; @@ -119,23 +121,24 @@ $header-inset: 10px; } .mo-meta-container { - background-color: rgba(239, 239, 239, 0.9); display: flex; - justify-content: center; - box-sizing: border-box; - min-height: 100px; - min-width: $panel-width; - max-width: $panel-height; - display: flex; - justify-content: center; + flex-direction: column; + justify-content: center; box-sizing: border-box; min-height: 100px; width: 100%; padding: $padding; + .mo-box-title { + display: flex; + flex-direction: row; + justify-content: space-between; + } + .mo-box { display: flex; - flex-direction: column; + flex-direction: row; + justify-content: space-around; max-width: $panel-width; width: 100%; padding: $padding 0; @@ -148,7 +151,7 @@ $header-inset: 10px; text-transform: uppercase; font-size: $xsmall; color: $darkwhite; - font-weight: 100; + font-weight: 100; } p { @@ -160,7 +163,7 @@ $header-inset: 10px; font-size: $normal; color: $darkwhite; margin-right: 5px; - } + } a { font-size: $large; @@ -223,19 +226,73 @@ $header-inset: 10px; } } -.source-image-container, .source-text-container { - padding: $padding; - display: inline-block; - align-items: center; +.source-media-gallery { + display: flex; + flex-direction: row; + height: 100%; + transition: transform 0.6s ease 0s; + width: 100%; + // min-width: $panel-width - 30px; + // min-height: $panel-height; +} + +.source-text-container { + padding: 20px; + display: flex; + justify-content: center; + background: $lightwhite; + box-sizing: border-box; + padding: 0 calc(50% - 400px); + overflow-y: scroll; + font-family: 'Merriweather', Georgia, serif; + line-height: 1.5em; + + a { + color: $darkgrey; + border-bottom: 1px solid $red; + &:hover { border-bottom: 1px solid $darkgrey; color: $darkgrey; } + } + + .md-container { + width: 100%; + overflow-wrap: break-word; + } +} + +.source-image-container, .media-player { + display: flex; + justify-content: center; + width: calc(100% - 20px); + height: 100%; + min-width: calc(100% - 20px); + margin: 0 10px; + background: $lightwhite; + border-radius: 2px; +} + +.media-player { + box-sizing: border-box; + width: 100%; + min-width: 100%; + max-width: 100%; + height: 100%; + min-height: 100%; + max-height: 100%; + padding: 20px 10%; + align-self: center; } .source-image, .source-video { max-width: calc(100% - 20px); - max-height: 350px !important; - // height: 100%; - padding: 10px; + max-height: calc(100% - 20px); + padding: 0px; + font-family: 'Lato', Helvetica, sans-serif; } -.media-player { - overflow-y: hidden; +.video-react .video-react-progress-control { + align-self: center; } + +.video-react .video-react-control { + min-height: 100%; +} \ No newline at end of file diff --git a/src/scss/narrativecard.scss b/src/scss/narrativecard.scss index 9bf86a4..adf5e8b 100644 --- a/src/scss/narrativecard.scss +++ b/src/scss/narrativecard.scss @@ -1,4 +1,4 @@ -$narrative-info-width: 370px; +$narrative-info-width: 386px; $timeline-height: 170px; /* @@ -8,8 +8,8 @@ NARRATIVE INFO position: fixed; top: 30px; left: auto; - right: 10px; - height: 170px; + right: 9px; + height: 205px; width: $narrative-info-width; box-sizing: border-box; max-height: calc(100% - 250px); @@ -39,7 +39,8 @@ NARRATIVE INFO } .narrative-info-desc { - overflow: auto; + height: 153px; + overflow-y: auto; } p { @@ -117,7 +118,7 @@ NARRATIVE INFO &.right { // right: calc(#{$narrative-info-width} + 10px); - right: 10px; + right: 25px; } .material-icons { diff --git a/src/scss/toolbar.scss b/src/scss/toolbar.scss index 0d9d400..29a81ef 100644 --- a/src/scss/toolbar.scss +++ b/src/scss/toolbar.scss @@ -96,6 +96,10 @@ } } + &:hover { + cursor: pointer; + } + &:hover:not(.disabled) { transition: 0.2s ease; border: 1px solid $offwhite; diff --git a/src/store/initial.js b/src/store/initial.js index dbfbd19..9cb4a2a 100644 --- a/src/store/initial.js +++ b/src/store/initial.js @@ -1,3 +1,5 @@ +import { mergeDeepLeft } from 'ramda' + const initial = { /* * The Domain or 'domain' of this state refers to the tree of data @@ -38,8 +40,8 @@ const initial = { }, filters: { timerange: [ - d3.timeParse("%Y-%m-%dT%H:%M:%S")("2013-02-23T12:00:00"), - d3.timeParse("%Y-%m-%dT%H:%M:%S")("2016-02-23T12:00:00") + new Date(2013, 2, 23, 12), + new Date(2016, 2, 23, 12) ], mapBounds: null, tags: [], @@ -51,45 +53,18 @@ const initial = { sites: true }, }, - base_uri: 'http://127.0.0.1:8000/', // Modify accordingly on production setup. isMobile: (/Mobi/.test(navigator.userAgent)), language: 'en-US', - mapAnchor: process.env.MAP_ANCHOR, - zoomLevels: [{ - label: '3 years', - duration: 1576800, - active: false - }, - { - label: '3 months', - duration: 129600, - active: false - }, - { - label: '3 days', - duration: 4320, - active: false - }, - { - label: '12 hours', - duration: 720, - active: false - }, - { - label: '2 hours', - duration: 120, - active: false - }, - { - label: '30 min', - duration: 30, - active: false - }, - { - label: '10 min', - duration: 10, - active: false - }], + mapAnchor: [31.356397, 34.784818], + zoomLevels: [ + { label: '3 years', duration: 1576800 }, + { label: '3 months', duration: 129600 }, + { label: '3 days', duration: 4320 }, + { label: '12 hours', duration: 720 }, + { label: '2 hours', duration: 120 }, + { label: '30 min', duration: 30 }, + { label: '10 min', duration: 10 } + ], flags: { isFetchingDomain: false, isFetchingSources: false, @@ -108,30 +83,13 @@ const initial = { ui: { style: { categories: { - default: 'yellow', - // Add here other categories to differentiate by color, like: - alpha: '#00ff00', - beta: '#ff0000', - other: '#f3de2c' + default: '#f3de2c', }, narratives: { default: { opacity: 0.9, stroke: 'red', strokeWidth: 3 - }, - narrative_1: { - opacity: 0.4, - stroke: '#f18f01', - strokeWidth: 3 - }, - // process.env.features.NARRATIVE_STEP_STYLES - stepStyles: { - Physical: { - stroke: 'yellow', - strokeWidth: 3, - opacity: 0.9, - } } } }, @@ -143,4 +101,15 @@ const initial = { } }; -export default initial; +let appStore; +if (process.env.store) { + appStore = mergeDeepLeft(process.env.store, initial); +} else { + appStore = initial +} + +// NB: config.js dates get implicitly converted to strings in mergeDeepLeft +appStore.app.filters.timerange[0] = new Date(appStore.app.filters.timerange[0]) +appStore.app.filters.timerange[1] = new Date(appStore.app.filters.timerange[1]) + +export default appStore diff --git a/yarn.lock b/yarn.lock index 9f5e536..2f8e62f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5059,6 +5059,11 @@ quick-lru@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-1.1.0.tgz#4360b17c61136ad38078397ff11416e186dcfbb8" +ramda@^0.26.1: + version "0.26.1" + resolved "https://registry.yarnpkg.com/ramda/-/ramda-0.26.1.tgz#8d41351eb8111c55353617fc3bbffad8e4d35d06" + integrity sha512-hLWjpy7EnsDBb0p+Z3B7rPi3GDeRG5ZtiI33kJhTt+ORCd38AbAIjB/9zRIUoeTbE/AVX5ZkU7m6bznsvrf8eQ== + randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5: version "2.0.6" resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.0.6.tgz#d302c522948588848a8d300c932b44c24231da80"