From 59d2685879331da92f62a0ecc9a1c737cadbc185 Mon Sep 17 00:00:00 2001 From: Lachlan Kermode Date: Wed, 21 Oct 2020 16:57:26 +0300 Subject: [PATCH 1/6] check for USE_CATEGORIES --- example.config.js | 7 ++----- src/components/Timeline.jsx | 10 ++++++---- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/example.config.js b/example.config.js index a159c4c..e260de3 100644 --- a/example.config.js +++ b/example.config.js @@ -21,13 +21,10 @@ module.exports = { // tiles: 'your-mapbox-account-name/x5678-map-id' }, features: { - USE_CATEGORIES: true, - CATEGORIES_AS_FILTERS: true, + USE_CATEGORIES: false, USE_ASSOCIATIONS: true, - USE_SOURCES: true, + USE_SOURCES: false, USE_COVER: true, - USE_SITES: false, - USE_SHAPES: false, GRAPH_NONLOCATED: false, HIGHLIGHT_GROUPS: false } diff --git a/src/components/Timeline.jsx b/src/components/Timeline.jsx index 58b0a3d..f7bca34 100644 --- a/src/components/Timeline.jsx +++ b/src/components/Timeline.jsx @@ -268,14 +268,16 @@ class Timeline extends React.Component { } getY (event) { + const { features, domain } = this.props + const { USE_CATEGORIES, GRAPH_NONLOCATED } = features const { categories } = domain + const categoriesExist = USE_CATEGORIES && categories && categories.length > 0 - const categoriesExist = categories && categories.length > 0 - const { GRAPH_NONLOCATED } = features - - if (!categoriesExist) { return this.state.dims.trackHeight / 2 } + if (!categoriesExist) { + return this.state.dims.trackHeight / 2 + } const { category, project } = event From 9a1e2f6ad15348ba1c3df3098540fed3af01b14d Mon Sep 17 00:00:00 2001 From: Lachlan Kermode Date: Wed, 21 Oct 2020 17:35:36 +0300 Subject: [PATCH 2/6] fix timeline render when there are no categories --- .../presentational/Timeline/Events.js | 53 ++++++++++--------- 1 file changed, 29 insertions(+), 24 deletions(-) diff --git a/src/components/presentational/Timeline/Events.js b/src/components/presentational/Timeline/Events.js index 5898384..41bf8ee 100644 --- a/src/components/presentational/Timeline/Events.js +++ b/src/components/presentational/Timeline/Events.js @@ -76,7 +76,7 @@ const TimelineEvents = ({ }) => { const narIds = narrative ? narrative.steps.map(s => s.id) : [] - function renderEvent (aggregated, event) { + function renderEvent (event) { if (narrative) { if (!(narIds.includes(event.id))) { return null @@ -97,33 +97,38 @@ const TimelineEvents = ({ } } - const relatedCategories = getEventCategories(event, categories) + // if an event has multiple categories, it should be rendered on each of + // those timelines + const ysAndStyles = getEventCategories(event, categories).map(cat => { + const eventY = getY({ ...event, category: cat.id }) - if (relatedCategories && relatedCategories.length > 0) { - relatedCategories.forEach(cat => { - const eventY = getY({ ...event, category: cat.id }) + let colour = event.colour ? event.colour : getCategoryColor(cat.id) + const styles = { + fill: colour, + fillOpacity: eventY > 0 ? calcOpacity(1) : 0, + transition: `transform ${transitionDuration / 1000}s ease` + } - let colour = event.colour ? event.colour : getCategoryColor(cat.id) - const styles = { - fill: colour, - fillOpacity: eventY > 0 ? calcOpacity(1) : 0, - transition: `transform ${transitionDuration / 1000}s ease` - } + return (eventY, styles) + }) - aggregated.push( - renderShape(event, styles, { - x: getDatetimeX(event.datetime), - y: eventY, - eventRadius, - onSelect: () => onSelect(event), - dims, - highlights: features.HIGHLIGHT_GROUPS ? getHighlights(event.filters[features.HIGHLIGHT_GROUPS.filterIndexIndicatingGroup]) : [], - features - }) - ) + function getRender (y, styles) { + return renderShape(event, styles, { + x: getDatetimeX(event.datetime), + y, + eventRadius, + onSelect: () => onSelect(event), + dims, + highlights: features.HIGHLIGHT_GROUPS ? getHighlights(event.filters[features.HIGHLIGHT_GROUPS.filterIndexIndicatingGroup]) : [], + features }) } - return aggregated + + if (ysAndStyles.length === 0) { + return getRender(getY(event), { fill: getCategoryColor(null) }) + } else { + return ysAndStyles.map(tup => getRender(tup[0], tup[1])) + } } let renderProjects = () => null @@ -147,7 +152,7 @@ const TimelineEvents = ({ clipPath={'url(#clip)'} > {renderProjects()} - {events.reduce(renderEvent, [])} + {events.map(renderEvent)} ) } From 3d010e4558ac1ddfb01c83acafa5bbb3d5b043a5 Mon Sep 17 00:00:00 2001 From: Lachlan Kermode Date: Wed, 21 Oct 2020 17:45:12 +0300 Subject: [PATCH 3/6] return reduce logic for when event shadows exist --- .../presentational/Timeline/Events.js | 24 +++++++++++-------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/src/components/presentational/Timeline/Events.js b/src/components/presentational/Timeline/Events.js index 41bf8ee..d8796d4 100644 --- a/src/components/presentational/Timeline/Events.js +++ b/src/components/presentational/Timeline/Events.js @@ -76,7 +76,7 @@ const TimelineEvents = ({ }) => { const narIds = narrative ? narrative.steps.map(s => s.id) : [] - function renderEvent (event) { + function renderEvent (acc, event) { if (narrative) { if (!(narIds.includes(event.id))) { return null @@ -98,18 +98,19 @@ const TimelineEvents = ({ } // if an event has multiple categories, it should be rendered on each of - // those timelines - const ysAndStyles = getEventCategories(event, categories).map(cat => { - const eventY = getY({ ...event, category: cat.id }) + // those timelines: so we create as many event 'shadows' as there are + // categories + const evShadows = getEventCategories(event, categories).map(cat => { + const y = getY({ ...event, category: cat.id }) let colour = event.colour ? event.colour : getCategoryColor(cat.id) const styles = { fill: colour, - fillOpacity: eventY > 0 ? calcOpacity(1) : 0, + fillOpacity: y > 0 ? calcOpacity(1) : 0, transition: `transform ${transitionDuration / 1000}s ease` } - return (eventY, styles) + return { y, styles } }) function getRender (y, styles) { @@ -124,11 +125,14 @@ const TimelineEvents = ({ }) } - if (ysAndStyles.length === 0) { - return getRender(getY(event), { fill: getCategoryColor(null) }) + if (evShadows.length === 0) { + acc.push(getRender(getY(event), { fill: getCategoryColor(null) })) } else { - return ysAndStyles.map(tup => getRender(tup[0], tup[1])) + evShadows.forEach(evShadow => { + acc.push(getRender(evShadow.y, evShadow.styles)) + }) } + return acc } let renderProjects = () => null @@ -152,7 +156,7 @@ const TimelineEvents = ({ clipPath={'url(#clip)'} > {renderProjects()} - {events.map(renderEvent)} + {events.reduce(renderEvent, [])} ) } From adb5d6f959cef681e5e2bbae5e9e73aaca1cce9e Mon Sep 17 00:00:00 2001 From: Lachlan Kermode Date: Wed, 21 Oct 2020 17:53:56 +0300 Subject: [PATCH 4/6] lint --- src/components/Timeline.jsx | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/components/Timeline.jsx b/src/components/Timeline.jsx index f7bca34..3e55d27 100644 --- a/src/components/Timeline.jsx +++ b/src/components/Timeline.jsx @@ -268,13 +268,11 @@ class Timeline extends React.Component { } getY (event) { - const { features, domain } = this.props const { USE_CATEGORIES, GRAPH_NONLOCATED } = features const { categories } = domain const categoriesExist = USE_CATEGORIES && categories && categories.length > 0 - if (!categoriesExist) { return this.state.dims.trackHeight / 2 } From ceed82e4f3457c9907cd88c5f135e452e5b139e9 Mon Sep 17 00:00:00 2001 From: Lachlan Kermode Date: Wed, 21 Oct 2020 18:33:06 +0300 Subject: [PATCH 5/6] fix corner case where clusters sometimes remain on screen without events --- src/components/Map.jsx | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/components/Map.jsx b/src/components/Map.jsx index 5aa680b..e41e1c6 100644 --- a/src/components/Map.jsx +++ b/src/components/Map.jsx @@ -45,6 +45,7 @@ class Map extends React.Component { if (this.map === null) { this.initializeMap() } + window.dispatchEvent(new Event('resize')) } componentWillReceiveProps (nextProps) { @@ -75,8 +76,11 @@ class Map extends React.Component { } componentDidUpdate (prevState, prevProps) { - if (prevState.domain.locations.length > 0 && this.state.clusters.length === 0) { - this.loadClusterData(prevState.domain.locations) + // HACK: this is required because of something to do with Leaflet and the + // React lifecycle not playing nice... if you don't put this conditional, + // then the map sometimes appear blank on first load. + if (this.props.domain.locations.length > 0 && this.state.clusters.length === 0) { + this.loadClusterData(this.props.domain.locations) } } From 57c7c3f96e6fdb05e2d8cccb3e4a6b24ea1d9532 Mon Sep 17 00:00:00 2001 From: Lachlan Kermode Date: Wed, 21 Oct 2020 18:33:51 +0300 Subject: [PATCH 6/6] lint --- src/components/Map.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/Map.jsx b/src/components/Map.jsx index e41e1c6..8490e11 100644 --- a/src/components/Map.jsx +++ b/src/components/Map.jsx @@ -1,4 +1,4 @@ -/* global L */ +/* global L, Event */ import React from 'react' import { Portal } from 'react-portal' import Supercluster from 'supercluster'