From 58b37105f5ebd150d2a66fb1a11e9f73fca8be61 Mon Sep 17 00:00:00 2001 From: Lachlan Kermode Date: Thu, 3 Jan 2019 17:17:50 +0000 Subject: [PATCH] narrative movement fully redux-ized --- src/components/Dashboard.jsx | 93 +++++++++++++++++++------------- src/components/MapEvents.jsx | 19 +++---- src/components/MapNarratives.jsx | 60 ++++++++++----------- 3 files changed, 96 insertions(+), 76 deletions(-) diff --git a/src/components/Dashboard.jsx b/src/components/Dashboard.jsx index f73580a..9986768 100644 --- a/src/components/Dashboard.jsx +++ b/src/components/Dashboard.jsx @@ -1,31 +1,33 @@ -import React from 'react'; +import React from 'react' -import { bindActionCreators } from 'redux'; -import { connect } from 'react-redux'; -import * as actions from '../actions'; +import { bindActionCreators } from 'redux' +import { connect } from 'react-redux' +import * as actions from '../actions' -import SourceOverlay from './SourceOverlay.jsx'; -import LoadingOverlay from './presentational/LoadingOverlay'; -import Map from './Map.jsx'; -import Toolbar from './Toolbar.jsx'; -import CardStack from './CardStack.jsx'; -import NarrativeCard from './NarrativeCard.js'; -import InfoPopUp from './InfoPopup.jsx'; -import Timeline from './Timeline.jsx'; -import Notification from './Notification.jsx'; +import SourceOverlay from './SourceOverlay.jsx' +import LoadingOverlay from './presentational/LoadingOverlay' +import Map from './Map.jsx' +import Toolbar from './Toolbar.jsx' +import CardStack from './CardStack.jsx' +import NarrativeCard from './NarrativeCard.js' +import InfoPopUp from './InfoPopup.jsx' +import Timeline from './Timeline.jsx' +import Notification from './Notification.jsx' -import { parseDate } from '../js/utilities'; +import { parseDate } from '../js/utilities' import { injectNarrative } from '../js/utilities' class Dashboard extends React.Component { constructor(props) { - super(props); + super(props) this.handleViewSource = this.handleViewSource.bind(this) - this.handleHighlight = this.handleHighlight.bind(this); - this.handleSelect = this.handleSelect.bind(this); - this.getCategoryColor = this.getCategoryColor.bind(this); + this.handleHighlight = this.handleHighlight.bind(this) + this.setNarrative = this.setNarrative.bind(this) + this.moveInNarrative = this.moveInNarrative.bind(this) + this.handleSelect = this.handleSelect.bind(this) + this.getCategoryColor = this.getCategoryColor.bind(this) this.eventsById = {} } @@ -33,18 +35,18 @@ class Dashboard extends React.Component { componentDidMount() { if (!this.props.app.isMobile) { this.props.actions.fetchDomain() - .then(domain => this.props.actions.updateDomain(domain)); + .then(domain => this.props.actions.updateDomain(domain)) } } handleHighlight(highlighted) { - this.props.actions.updateHighlighted((highlighted) ? highlighted : null); + this.props.actions.updateHighlighted((highlighted) ? highlighted : null) } getEventById(eventId) { - if (this.eventsById[eventId]) return this.eventsById[eventId]; - this.eventsById[eventId] = this.props.domain.events.find(ev => ev.id === eventId); - return this.eventsById[eventId]; + if (this.eventsById[eventId]) return this.eventsById[eventId] + this.eventsById[eventId] = this.props.domain.events.find(ev => ev.id === eventId) + return this.eventsById[eventId] } handleViewSource(source) { @@ -53,7 +55,7 @@ class Dashboard extends React.Component { handleSelect(selected) { if (selected) { - let eventsToSelect = selected.map(event => this.getEventById(event.id)); + let eventsToSelect = selected.map(event => this.getEventById(event.id)) eventsToSelect = eventsToSelect.sort((a, b) => parseDate(a.timestamp) - parseDate(b.timestamp)) this.props.actions.updateSelected(eventsToSelect) @@ -65,9 +67,29 @@ class Dashboard extends React.Component { } getNarrativeLinks(event) { - const narrative = this.props.domain.narratives.find(nv => nv.id === event.narrative); - if (narrative) return narrative.byId[event.id]; - return null; + const narrative = this.props.domain.narratives.find(nv => nv.id === event.narrative) + if (narrative) return narrative.byId[event.id] + return null + } + + setNarrative(narrative) { + // only handleSelect if narrative is not null + if (!!narrative) + this.handleSelect([ narrative.steps[0] ]) + this.props.actions.updateNarrative(narrative) + } + moveInNarrative(amt) { + const { current } = this.props.app.narrativeState + const { narrative } = this.props.app + + if (amt === 1) { + this.handleSelect([ narrative.steps[current + 1] ]) + this.props.actions.incrementNarrativeCurrent() + } + if (amt === -1) { + this.handleSelect([ narrative.steps[current - 1] ]) + this.props.actions.decrementNarrativeCurrent() + } } render() { @@ -78,14 +100,14 @@ class Dashboard extends React.Component { isNarrative={!!app.narrative} methods={{ onFilter: actions.updateTagFilters, - onSelectNarrative: actions.updateNarrative + onSelectNarrative: this.setNarrative }} /> @@ -98,10 +120,9 @@ class Dashboard extends React.Component { /> this.moveInNarrative(1), + onPrev: () => this.moveInNarrative(-1), + onSelectNarrative: this.setNarrative }} /> - ); + ) } } function mapDispatchToProps(dispatch) { return { actions: bindActionCreators(actions, dispatch) - }; + } } function injectSource(id) { @@ -159,4 +180,4 @@ function injectSource(id) { export default connect( state => state, mapDispatchToProps, -)(Dashboard); +)(Dashboard) diff --git a/src/components/MapEvents.jsx b/src/components/MapEvents.jsx index 6fe3e00..70cac85 100644 --- a/src/components/MapEvents.jsx +++ b/src/components/MapEvents.jsx @@ -33,15 +33,16 @@ class MapEvents extends React.Component { }) if (this.props.narrative) { - // TODO: logic to display narratives in Map - // const { byId } = this.props.narrative - // const eventsInNarrative = events.filter(e => byId.hasOwnProperty(e.id)) - // if (eventsInNarrative.length <= 0) { - // styleProps = { - // ...styleProps, - // fillOpacity: 0.1 - // } - // } + const { steps } = this.props.narrative + const onlyIfInNarrative = e => steps.map(s => s.id).includes(e.id) + const eventsInNarrative = events.filter(onlyIfInNarrative) + + if (eventsInNarrative.length <= 0) { + styleProps = { + ...styleProps, + fillOpacity: 0.1 + } + } } return ( diff --git a/src/components/MapNarratives.jsx b/src/components/MapNarratives.jsx index bbd62ad..8b92bb8 100644 --- a/src/components/MapNarratives.jsx +++ b/src/components/MapNarratives.jsx @@ -1,42 +1,42 @@ -import React from 'react'; -import { Portal } from 'react-portal'; +import React from 'react' +import { Portal } from 'react-portal' class MapNarratives extends React.Component { projectPoint(location) { - const latLng = new L.LatLng(location[0], location[1]); + const latLng = new L.LatLng(location[0], location[1]) return { x: this.props.map.latLngToLayerPoint(latLng).x + this.props.mapTransformX, y: this.props.map.latLngToLayerPoint(latLng).y + this.props.mapTransformY - }; + } } getNarrativeStyle(narrativeId) { const styleName = (narrativeId && narrativeId in this.props.narrativeProps) ? narrativeId - : 'default'; - return this.props.narrativeProps[styleName]; + : 'default' + return this.props.narrativeProps[styleName] } getStrokeWidth(narrative, step) { - if (!step) return 0; - return this.getNarrativeStyle(narrative.id).strokeWidth; + 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'; + 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; + 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; + if (this.props.narrative === null) return 0 + if (!step || narrative.id !== this.props.narrative.id) return 0.1 + return 1 } hasNoLocation(step) { @@ -44,14 +44,14 @@ class MapNarratives extends React.Component { } renderNarrativeStep(allSteps, step, idx, n) { - const { x, y } = this.projectPoint([step.latitude, step.longitude]); - const step2 = allSteps[idx + 1]; + const { x, y } = this.projectPoint([step.latitude, step.longitude]) + const step2 = allSteps[idx + 1] // don't draw if one of the steps has no location if (this.hasNoLocation(step) || this.hasNoLocation(step2)) return null - const p2 = this.projectPoint([step2.latitude, step2.longitude]); + const p2 = this.projectPoint([step2.latitude, step2.longitude]) return ( - ); + ) } renderNarrative(n) { - // TODO: representation for narrative lines - // const steps = n.steps.slice(0, n.steps.length - 1); - // - // return ( - // - // {steps.map((s, idx) => this.renderNarrativeStep(n.steps, s, idx, n))} - // - // ) - return null + const steps = n.steps.slice(0, n.steps.length - 1) + + return ( + + {steps.map((s, idx) => this.renderNarrativeStep(n.steps, s, idx, n))} + + ) } render() { - if (this.props.narrative === null) return (
); + if (this.props.narrative === null) return (
) return ( {this.props.narratives.map(n => this.renderNarrative(n))} - ); + ) } } -export default MapNarratives; +export default MapNarratives