From 421af5e60ca1fb94235a482590a30c21af4ffe48 Mon Sep 17 00:00:00 2001 From: Lachlan Kermode Date: Fri, 27 Mar 2020 17:44:52 +0100 Subject: [PATCH] improve project graph --- src/actions/index.js | 9 +- src/components/TimelineAxis.jsx | 2 +- src/components/presentational/Map/Events.jsx | 1 + .../presentational/Timeline/DatetimeBar.js | 2 - .../presentational/Timeline/Events.js | 21 +-- src/reducers/schema/eventSchema.js | 2 +- src/selectors/index.js | 121 +++++++++++------- 7 files changed, 99 insertions(+), 59 deletions(-) diff --git a/src/actions/index.js b/src/actions/index.js index b2734d9..6526f5b 100644 --- a/src/actions/index.js +++ b/src/actions/index.js @@ -34,9 +34,12 @@ export function fetchDomain () { .then(response => response.json()) .catch(() => handleError(domainMsg('categories'))) - const narPromise = fetch(NARRATIVE_URL) - .then(response => response.json()) - .catch(() => handleError(domainMsg('narratives'))) + let narPromise = Promise.resolve([]) + if (process.env.features.USE_CATEGORIES) { + narPromise = fetch(NARRATIVE_URL) + .then(response => response.json()) + .catch(() => handleError(domainMsg('narratives'))) + } let sitesPromise = Promise.resolve([]) if (process.env.features.USE_SITES) { diff --git a/src/components/TimelineAxis.jsx b/src/components/TimelineAxis.jsx index b6e4cb3..92f6192 100644 --- a/src/components/TimelineAxis.jsx +++ b/src/components/TimelineAxis.jsx @@ -69,7 +69,7 @@ class TimelineAxis extends React.Component { /> diff --git a/src/components/presentational/Map/Events.jsx b/src/components/presentational/Map/Events.jsx index 3df2a34..519cc71 100644 --- a/src/components/presentational/Map/Events.jsx +++ b/src/components/presentational/Map/Events.jsx @@ -94,6 +94,7 @@ function MapEvents ({ getCategoryColor, categories, projectPoint, styleLocation, longitude: '32.2' } */ + if (!location.latitude || !location.longitude) return null const { x, y } = projectPoint([location.latitude, location.longitude]) // in narrative mode, only render events in narrative diff --git a/src/components/presentational/Timeline/DatetimeBar.js b/src/components/presentational/Timeline/DatetimeBar.js index 0509e01..9660baf 100644 --- a/src/components/presentational/Timeline/DatetimeBar.js +++ b/src/components/presentational/Timeline/DatetimeBar.js @@ -21,5 +21,3 @@ export default ({ height={height} /> ) - -// export default () => null diff --git a/src/components/presentational/Timeline/Events.js b/src/components/presentational/Timeline/Events.js index bcb79c1..61bef45 100644 --- a/src/components/presentational/Timeline/Events.js +++ b/src/components/presentational/Timeline/Events.js @@ -136,22 +136,27 @@ const TimelineEvents = ({ // }) // }) - let projects + let renderProjects = () => null if (process.env.features.ASSOCIATIVE_EVENTS_BY_TAG) { - projects = datetimes[1] + const projects = datetimes[1] datetimes = datetimes[0] + renderProjects = function () { + return + {projects.map(project => )} + + } } return ( - {projects.map(project => ())} + {renderProjects()} {datetimes.map(datetime => renderDatetime(datetime))} ) diff --git a/src/reducers/schema/eventSchema.js b/src/reducers/schema/eventSchema.js index 794d6ed..0465ca1 100644 --- a/src/reducers/schema/eventSchema.js +++ b/src/reducers/schema/eventSchema.js @@ -23,7 +23,7 @@ const eventSchema = Joi.object().keys({ narrative___stepStyles: Joi.array() }) .and('latitude', 'longitude') - .and('date', 'time', 'timestamp') + .and('date', 'timestamp') .or('timestamp', 'latitude') export default eventSchema diff --git a/src/selectors/index.js b/src/selectors/index.js index 6ca51b2..b8555e4 100644 --- a/src/selectors/index.js +++ b/src/selectors/index.js @@ -60,6 +60,9 @@ export const selectEvents = createSelector( export const selectNarratives = createSelector( [getEvents, getNarratives, getSources], (events, narrativesMeta, sources) => { + if (!process.env.features.USE_NARRATIVES) { + return [] + } const narratives = {} const narrativeSkeleton = id => ({ id, steps: [] }) @@ -157,7 +160,16 @@ export const selectDatetimes = createSelector( const datetimes = {} events.forEach(event => { const { timestamp } = event - const dtKey = `${timestamp}_1` + /** Create timestamp with fresh dtKey always by default */ + let dtIdx = 1 + let dtKey = `${timestamp}_${dtIdx}` + let tsExists = datetimes.hasOwnProperty(dtKey) + while (tsExists) { + dtIdx += 1 + dtKey = `${timestamp}_${dtIdx}` + tsExists = datetimes.hasOwnProperty(dtKey) + } + if (IS_PROJ) { const project = event.tags.length >= 1 ? event.tags[0] : null event = { ...event, project } @@ -170,64 +182,85 @@ export const selectDatetimes = createSelector( } } } - const tsExists = datetimes.hasOwnProperty(dtKey) - const isLocated = !!event.latitude && !!event.longitude - if (IS_PROJ && !isLocated && event.project !== null && tsExists) { - if (tsExists) { - alert('not yet handling cases with multiple... talk to lk@forensic-architecture.org') + + /** We need to work out whether we can add the event to an existing + * timestamp, or whether we need to create a new one. What determines + * this is whether or not ALL events in a timestamp have a matching + * project. We not only need to check the current dtKey, but also all + * dtKeys that have the same timestamp. + * + * It's a pretty whack algorithm, but I think it does what it's supposed + * to. This is only run when projects are showing. + * TODO: find a more module way to interface with this code. + */ + let shouldCreate = true + if (IS_PROJ && dtIdx >= 2 && !(!!event.latitude && !!event.longitude) && event.project !== null) { + const allExistingIdxs = [...Array(dtIdx - 1).keys()].map(k => k + 1) + let foundMatching = false + allExistingIdxs.forEach(_idx => { + const _dtKey = `${timestamp}_${_idx}` + const isSameTimestampAndAllSameProjects = datetimes[_dtKey].events.every(ev => ev.project === event.project) + if (isSameTimestampAndAllSameProjects) { + dtKey = _dtKey + foundMatching = true + } + }) + if (!foundMatching) { + shouldCreate = true } - } else if (tsExists) { - datetimes[dtKey].events.push(event) - } else { + } + if (shouldCreate) { datetimes[dtKey] = { timestamp: event.timestamp, date: event.date, time: event.time, events: [event] } + } else { + datetimes[dtKey].events.push(event) } }) - const projKeys = Object.keys(projects) - function checkActive (pj, dt) { - return dt >= projects[pj].start && dt <= projects[pj].end - } + const output = [] - let sortedDts = Object.keys(datetimes) - sortedDts.sort((a, b) => { - const x = a.substring(0, a.length - 2) - const y = b.substring(0, b.length - 2) - return new Date(x) - new Date(y) - }) - sortedDts.forEach(dt => { - const activeProjects = [] - projKeys.forEach((k, idx) => { - if (checkActive(k, dt)) activeProjects.push(k) + if (IS_PROJ) { + const projKeys = Object.keys(projects) + let sortedDts = Object.keys(datetimes) + + sortedDts.sort((a, b) => { + const x = a.substring(0, a.length - 2) + const y = b.substring(0, b.length - 2) + return new Date(x) - new Date(y) }) - output.push({ - ...datetimes[dt], - events: datetimes[dt].events.map(ev => { - let projectOffset = (activeProjects.indexOf(ev.project) + 1) * (2.5 * sizes.eventDotR) - if (ev.project !== null && !projects[ev.project].hasOwnProperty('offset')) { - projects[ev.project].offset = projectOffset - projects[ev.project].category = ev.category - } else if (ev.project !== null) { - projectOffset = projects[ev.project].offset - } - return { - ...ev, - projectOffset - } + sortedDts.forEach(dt => { + const activeProjects = [] + projKeys.forEach((k, idx) => { + if (dt >= projects[k].start && dt <= projects[k].end) activeProjects.push(k) + }) + output.push({ + ...datetimes[dt], + events: datetimes[dt].events.map(ev => { + let projectOffset = (activeProjects.indexOf(ev.project) + 1) * (2.5 * sizes.eventDotR) + if (ev.project !== null && !projects[ev.project].hasOwnProperty('offset')) { + projects[ev.project].offset = projectOffset + projects[ev.project].category = ev.category + } else if (ev.project !== null) { + projectOffset = projects[ev.project].offset + } + return { + ...ev, + projectOffset + } + }) }) }) - }) - const projectsOut = [] - Object.keys(projects).forEach(projId => { - projectsOut.push({ ...projects[projId], id: projId }) - }) - if (IS_PROJ) { + const projectsOut = [] + Object.keys(projects).forEach(projId => { + projectsOut.push({ ...projects[projId], id: projId }) + }) return [output, projectsOut] } - return output + + return Object.values(datetimes) } )