factor step state of narrative from NarrativeCard comp to redux

This commit is contained in:
Lachlan Kermode
2019-01-03 16:11:03 +00:00
parent c75405f2ba
commit e6742d0b04
4 changed files with 73 additions and 80 deletions

View File

@@ -1,5 +1,6 @@
import React from 'react';
import { connect } from 'react-redux'
import { selectActiveNarrative } from '../selectors'
class NarrativeCard extends React.Component {
@@ -59,12 +60,10 @@ class NarrativeCard extends React.Component {
// no display if no narrative
if (!this.props.narrative) return null
console.log(this.props.narrative)
const { steps, current } = this.props.narrative
if (steps[current]) {
const step = steps[current];
console.log('here')
return (
<div className='narrative-info'>
@@ -89,7 +88,7 @@ class NarrativeCard extends React.Component {
function mapStateToProps(state) {
return {
narrative: state.app.narrative
narrative: selectActiveNarrative(state)
}
}
export default connect(mapStateToProps)(NarrativeCard);

View File

@@ -35,31 +35,11 @@ function updateSelected(appState, action) {
function updateNarrative(appState, action) {
return {
...appState,
narrative: action.narrative
narrative: action.narrative,
narrativeState: {
current: 0
}
}
// if (action.narrative === null) {
// console.log(action.narrative)
// return Object.assign({}, appState, {
// narrative: action.narrative,
// });
// } else {
// const dates = action.narrative.steps.map(n => parseDate(n.timestamp).getTime())
// let minDate = Math.min(...dates);
// let maxDate = Math.max(...dates);
// // Add some margin to the datetime extent
// minDate = minDate - ((maxDate - minDate) / 20);
// maxDate = maxDate + ((maxDate - minDate) / 20);
//
// const output = Object.assign({}, appState, {
// narrative: action.narrative,
// filters: Object.assign({}, appState.filters, {
// timerange: [new Date(minDate), new Date(maxDate)]
// }),
// });
// console.log(output)
// return output
// }
}
function updateTagFilters(appState, action) {

View File

@@ -2,23 +2,25 @@ import { createSelector} from 'reselect'
import { parseTimestamp, compareTimestamp } from '../js/utilities'
// Input selectors
export const getEvents = state => state.domain.events;
export const getLocations = state => state.domain.locations;
export const getCategories = state => state.domain.categories;
export const getNarratives = state => state.domain.narratives;
export const getSelected = state => state.app.selected;
export const getEvents = state => state.domain.events
export const getLocations = state => state.domain.locations
export const getCategories = state => state.domain.categories
export const getNarratives = state => state.domain.narratives
export const getActiveNarrative = state => state.app.narrative
export const getActiveStep = state => state.app.narrativeState.current
export const getSelected = state => state.app.selected
export const getSites = (state) => {
if (process.env.features.USE_SITES) return state.domain.sites;
return [];
if (process.env.features.USE_SITES) return state.domain.sites
return []
}
export const getSources = state => {
if (process.env.features.USE_SOURCES) return state.domain.sources;
return [];
if (process.env.features.USE_SOURCES) return state.domain.sources
return []
}
export const getNotifications = state => state.domain.notifications;
export const getTagTree = state => state.domain.tags;
export const getTagsFilter = state => state.app.filters.tags;
export const getTimeRange = state => state.app.filters.timerange;
export const getNotifications = state => state.domain.notifications
export const getTagTree = state => state.domain.tags
export const getTagsFilter = state => state.app.filters.tags
export const getTimeRange = state => state.app.filters.timerange
/**
* Some handy helpers
@@ -30,11 +32,11 @@ export const getTimeRange = state => state.app.filters.timerange;
*/
function isTaggedIn(event, tagFilters) {
if (event.tags) {
const tagsInEvent = event.tags.split(",");
const tagsInEvent = event.tags.split(",")
const isTagged = tagsInEvent.some((tag) => {
return tagFilters.find(tF => (tF.key === tag && tF.active));
});
return isTagged;
return tagFilters.find(tF => (tF.key === tag && tF.active))
})
return isTagged
} else {
return false
}
@@ -48,7 +50,7 @@ function isNoTags(tagFilters) {
tagFilters.length === 0
|| !process.env.features.USE_TAGS
|| tagFilters.every(t => !t.active)
);
)
}
/**
@@ -59,7 +61,7 @@ function isTimeRangedIn(event, timeRange) {
return (
timeRange[0] < parseTimestamp(event.timestamp)
&& parseTimestamp(event.timestamp) < timeRange[1]
);
)
}
/**
@@ -71,17 +73,17 @@ export const selectEvents = createSelector(
(events, tagFilters, timeRange) => {
return events.reduce((acc, event) => {
const isTagged = isTaggedIn(event, tagFilters) || isNoTags(tagFilters);
const isTimeRanged = isTimeRangedIn(event, timeRange);
const isTagged = isTaggedIn(event, tagFilters) || isNoTags(tagFilters)
const isTimeRanged = isTimeRangedIn(event, timeRange)
if (isTimeRanged && isTagged) {
const eventClone = Object.assign({}, event);
acc[event.id] = eventClone;
const eventClone = Object.assign({}, event)
acc[event.id] = eventClone
}
return acc;
}, []);
});
return acc
}, [])
})
/**
* Of all available events, selects those that fall within the time range,
@@ -91,14 +93,14 @@ export const selectNarratives = createSelector(
[getEvents, getNarratives, getTagsFilter, getTimeRange],
(events, narrativesMeta, tagFilters, timeRange) => {
const narratives = {};
const narratives = {}
const narrativeSkeleton = id => ({ id, steps: [] })
/* populate narratives dict with events */
events.forEach(evt => {
const isTagged = isTaggedIn(evt, tagFilters) || isNoTags(tagFilters);
const isTimeRanged = isTimeRangedIn(evt, timeRange);
const isInNarrative = evt.narratives.length > 0;
const isTagged = isTaggedIn(evt, tagFilters) || isNoTags(tagFilters)
const isTimeRanged = isTimeRangedIn(evt, timeRange)
const isInNarrative = evt.narratives.length > 0
evt.narratives.forEach(narrative => {
// initialise
@@ -109,19 +111,19 @@ export const selectNarratives = createSelector(
if (isInNarrative)
narratives[narrative].steps.push(evt)
})
});
})
/* sort steps by time */
Object.keys(narratives).forEach(key => {
const steps = narratives[key].steps;
const steps = narratives[key].steps
steps.sort(compareTimestamp);
steps.sort(compareTimestamp)
// steps.forEach((step, i) => {
// narratives[key].byId[step.id].next = (i < steps.length - 2) ? steps[i + 1] : null;
// narratives[key].byId[step.id].prev = (i > 0) ? steps[i - 1] : null;
// });
// narratives[key].byId[step.id].next = (i < steps.length - 2) ? steps[i + 1] : null
// narratives[key].byId[step.id].prev = (i > 0) ? steps[i - 1] : null
// })
if (narrativesMeta.find(n => n.id === key)) {
narratives[key] = {
@@ -129,11 +131,20 @@ export const selectNarratives = createSelector(
...narratives[key]
}
}
});
})
return Object.values(narratives);
});
return Object.values(narratives)
})
/** Aggregate information about the narrative and the current step into
* a single object. If narrative is null, the whole object is null.
*/
export const selectActiveNarrative = createSelector(
[getActiveNarrative, getActiveStep],
(narrative, current) => !!narrative
? { ...narrative, current }
: null
)
/**
* Of all the filtered events, group them by location and return a list of
* locations with at least one event in it, based on the time range and tags
@@ -142,12 +153,12 @@ export const selectLocations = createSelector(
[selectEvents],
(events) => {
const selectedLocations = {};
const selectedLocations = {}
events.forEach(event => {
const location = event.location;
const location = event.location
if (selectedLocations[location]) {
selectedLocations[location].events.push(event);
selectedLocations[location].events.push(event)
} else {
selectedLocations[location] = {
label: location,
@@ -158,9 +169,9 @@ export const selectLocations = createSelector(
}
})
return Object.values(selectedLocations);
return Object.values(selectedLocations)
}
);
)
/**
* Of all the sources, select those that are relevant to the selected events.
@@ -176,7 +187,7 @@ export const selectSelected = createSelector(
const srcs = selected
.map(e => e.sources)
.map(_sources => {
if (!_sources) return [];
if (!_sources) return []
return _sources.map(id => (
sources.hasOwnProperty(id) ? sources[id] : null
))
@@ -196,7 +207,7 @@ export const selectSelected = createSelector(
export const selectCategories = createSelector(
[getCategories],
(categories) => categories
);
)
/**
@@ -206,23 +217,23 @@ export const selectCategories = createSelector(
export const selectTagList = createSelector(
[getTagTree],
(tags) => {
const tagList = [];
let depth = 0;
const tagList = []
let depth = 0
function traverseNode(node, depth) {
node.active = (!node.hasOwnProperty('active')) ? false : node.active;
node.depth = depth;
node.active = (!node.hasOwnProperty('active')) ? false : node.active
node.depth = depth
if (node.active) tagList.push(node)
if (Object.keys(node.children).length > 0) {
Object.values(node.children).forEach((childNode) => {
traverseNode(childNode, depth + 1);
});
traverseNode(childNode, depth + 1)
})
}
}
if (tags && tags !== undefined) {
if (tags.key && tags.children) traverseNode(tags, depth)
}
return tagList;
return tagList
}
)

View File

@@ -33,6 +33,9 @@ const initial = {
selected: [],
source: null,
narrative: null,
narrativeState: {
current: null
},
filters: {
timerange: [
d3.timeParse("%Y-%m-%dT%H:%M:%S")("2013-02-23T12:00:00"),