diff --git a/src/common/constants.js b/src/common/constants.js new file mode 100644 index 0000000..4cd536e --- /dev/null +++ b/src/common/constants.js @@ -0,0 +1,2 @@ +export const FILTER_MODE = 'FILTER' +export const NARRATIVE_MODE = 'NARRATIVE' \ No newline at end of file diff --git a/src/components/Toolbar/FilterListPanel.js b/src/components/Toolbar/FilterListPanel.js index 53bb31a..9c14c10 100644 --- a/src/components/Toolbar/FilterListPanel.js +++ b/src/components/Toolbar/FilterListPanel.js @@ -3,57 +3,73 @@ import Checkbox from '../presentational/Checkbox' import copy from '../../common/data/copy.json' /** recursively get an array of node keys to toggle */ -function childrenToToggle (node, activeFilters, parentOn) { - const isOn = activeFilters.includes(node.key) - if (!node.children) { - return [node.key] +function childrenToToggle (filter, activeFilters, parentOn) { + const [key, children] = filter + const isOn = activeFilters.includes(key) + if (children === {}) { + return [key] } - const childKeys = Object.values(node.children) - .flatMap(n => childrenToToggle(n, activeFilters, isOn)) + const childKeys = Object.entries(children) + .flatMap(filter => childrenToToggle(filter, activeFilters, isOn)) // NB: if turning a parent off, don't toggle off children on. // likewise if turning a parent on, don't toggle on children off if (!((!parentOn && isOn) || (parentOn && !isOn))) { - childKeys.push(node.key) + childKeys.push(key) } return childKeys } +function aggregatePaths (filters) { + const aggregated = {} + + filters.forEach(item => { + let currentDepth = aggregated + + item.filter_paths.forEach(path => { + if (!(path in aggregated)) { + currentDepth[path] = {} + } + currentDepth = currentDepth[path] + }) + }) + + return aggregated +} + function FilterListPanel ({ filters, activeFilters, onSelectFilter, language }) { - function createNodeComponent (node, depth) { - const matchingKeys = childrenToToggle(node, activeFilters, activeFilters.includes(node.key)) - const children = Object.values(node.children) + function createNodeComponent (filter, depth) { + const [key, children] = filter + const matchingKeys = childrenToToggle(filter, activeFilters, activeFilters.includes(key)) + return (
  • - {/* */} - {/* */} - {/* */} - {/* */} - {/* */} onSelectFilter(matchingKeys)} /> - {children.length > 0 - ? children.map(filter => createNodeComponent(filter, depth + 1)) + {Object.keys(children).length > 0 + ? Object.entries(children).map(filter => createNodeComponent(filter, depth + 1)) : null}
  • ) } - function renderTree (children) { + function renderTree (filters) { + const aggregatedFilterPaths = aggregatePaths(filters) + console.info(aggregatedFilterPaths) return (
    - {Object.values(children).map(filter => createNodeComponent(filter, 1))} + {Object.entries(aggregatedFilterPaths).map(filter => createNodeComponent(filter, 1))}
    ) } @@ -62,7 +78,7 @@ function FilterListPanel ({

    {copy[language].toolbar.filters}

    {copy[language].toolbar.explore_by_filter__description}

    - {renderTree(filters.children)} + {renderTree(filters)}
    ) } diff --git a/src/components/Toolbar/Layout.js b/src/components/Toolbar/Layout.js index ce551f1..a2df306 100644 --- a/src/components/Toolbar/Layout.js +++ b/src/components/Toolbar/Layout.js @@ -197,7 +197,7 @@ class Toolbar extends React.Component { function mapStateToProps (state) { return { - filters: selectors.getFilterTree(state), + filters: selectors.getFilters(state), categories: selectors.getCategories(state), narratives: selectors.selectNarratives(state), language: state.app.language, diff --git a/src/reducers/app.js b/src/reducers/app.js index 7b58372..4039f8a 100644 --- a/src/reducers/app.js +++ b/src/reducers/app.js @@ -114,7 +114,7 @@ function toggleFilter (appState, action) { action.value = [action.value] } - let newFilters = appState.filters[action.filter].slice(0) + let newFilters = appState.associations.filters.slice(0) action.value.forEach(vl => { if (newFilters.includes(vl)) { newFilters = newFilters.filter(s => s !== vl) @@ -125,9 +125,9 @@ function toggleFilter (appState, action) { return { ...appState, - filters: { - ...appState.filters, - [action.filter]: newFilters + associations: { + ...appState.associations, + filters: newFilters, } } } diff --git a/src/selectors/index.js b/src/selectors/index.js index c0806d5..d328da1 100644 --- a/src/selectors/index.js +++ b/src/selectors/index.js @@ -1,6 +1,7 @@ import { createSelector } from 'reselect' import { insetSourceFrom, dateMin, dateMax } from '../common/utilities' import { isTimeRangedIn } from './helpers' +import { FILTER_MODE } from '../common/constants' // Input selectors export const getEvents = state => state.domain.events @@ -11,8 +12,8 @@ export const getSelected = state => state.app.selected export const getSites = state => state.domain.sites export const getSources = state => state.domain.sources export const getShapes = state => state.domain.shapes +export const getFilters = state => state.domain.associations.filter(item => item.mode === FILTER_MODE) export const getNotifications = state => state.domain.notifications -export const getFilterTree = state => state.domain.filters export const getActiveFilters = state => state.app.associations.filters export const getActiveCategories = state => state.app.associations.categories export const getTimeRange = state => state.app.timeline.range