mirror of
https://github.com/bellingcat/ukraine-timemap.git
synced 2026-06-08 03:18:36 +03:00
Merge pull request #170 from forensic-architecture/fix/recursive-corner-case
Fix/recursive corner case
This commit is contained in:
@@ -116,10 +116,30 @@ export function getImmediateFilterParent (associations, filter) {
|
||||
return parents[parents.length - 1]
|
||||
}
|
||||
|
||||
/**
|
||||
* Grab a meta filter's siblings, by way of the the `filter_path` hierarcy.
|
||||
*/
|
||||
export function getMetaFilterSiblings (allFilters, filterParent, filterKey) {
|
||||
const idxParent = allFilters.map(f => {
|
||||
return f.filter_paths.reduceRight((acc, path, idx) => {
|
||||
if (path === filterParent) return f.filter_paths[idx + 1]
|
||||
return acc
|
||||
}, null)
|
||||
})
|
||||
.filter(metaFilter => !!metaFilter && metaFilter !== filterKey)
|
||||
return [ ...(new Set(idxParent)) ]
|
||||
}
|
||||
|
||||
/**
|
||||
* Grabs a given filter's siblings: the set of associations that share the same immediate filter parent.
|
||||
*/
|
||||
export function getFilterSiblings (allFilters, filterParent, filterKey) {
|
||||
const isMetaFilter = !allFilters.map(filt => filt.id).includes(filterKey)
|
||||
|
||||
if (isMetaFilter) {
|
||||
return getMetaFilterSiblings(allFilters, filterParent, filterKey)
|
||||
}
|
||||
|
||||
return allFilters.reduce((acc, val) => {
|
||||
const valParent = getImmediateFilterParent(allFilters, val.id)
|
||||
if (valParent === filterParent && val.id !== filterKey) acc.push(val.id)
|
||||
|
||||
@@ -1,9 +1,13 @@
|
||||
import React from 'react'
|
||||
import Checkbox from '../presentational/Checkbox'
|
||||
import copy from '../../common/data/copy.json'
|
||||
import { getFilterIdxFromColorSet } from '../../common/utilities'
|
||||
import { getFilterIdxFromColorSet, getFilterParents } from '../../common/utilities'
|
||||
import { colors } from '../../common/global'
|
||||
|
||||
function hasOnParent (filters, activeFilters, filterKey) {
|
||||
return getFilterParents(filters, filterKey).some(r => activeFilters.indexOf(r) >= 0)
|
||||
}
|
||||
|
||||
/** recursively get an array of node keys to toggle */
|
||||
function childrenToToggle (filter, activeFilters, parentOn) {
|
||||
const [key, children] = filter
|
||||
@@ -12,7 +16,7 @@ function childrenToToggle (filter, activeFilters, parentOn) {
|
||||
return [key]
|
||||
}
|
||||
const childKeys = Object.entries(children)
|
||||
.flatMap(filter => childrenToToggle(filter, activeFilters, isOn))
|
||||
.flatMap(filter => childrenToToggle(filter, activeFilters, isOn || parentOn))
|
||||
// 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))) {
|
||||
@@ -46,7 +50,9 @@ function FilterListPanel ({
|
||||
}) {
|
||||
function createNodeComponent (filter, depth) {
|
||||
const [key, children] = filter
|
||||
const matchingKeys = childrenToToggle(filter, activeFilters, activeFilters.includes(key))
|
||||
const anyParentOn = activeFilters.includes(key) || hasOnParent(filters, activeFilters, key)
|
||||
const matchingKeys = childrenToToggle(filter, activeFilters, anyParentOn)
|
||||
|
||||
const idxFromColorSet = getFilterIdxFromColorSet(key, coloringSet)
|
||||
|
||||
const assignedColor = idxFromColorSet !== -1 && activeFilters.includes(key) ? filterColors[idxFromColorSet] : colors.white
|
||||
@@ -65,7 +71,7 @@ function FilterListPanel ({
|
||||
<Checkbox
|
||||
label={key}
|
||||
isActive={activeFilters.includes(key)}
|
||||
onClickCheckbox={() => onSelectFilter(key, matchingKeys)}
|
||||
onClickCheckbox={() => { onSelectFilter(key, matchingKeys) }}
|
||||
backgroundColor={assignedColor}
|
||||
/>
|
||||
{Object.keys(children).length > 0
|
||||
|
||||
@@ -9,7 +9,7 @@ import FilterListPanel from './FilterListPanel'
|
||||
import CategoriesListPanel from './CategoriesListPanel'
|
||||
import BottomActions from './BottomActions'
|
||||
import copy from '../../common/data/copy.json'
|
||||
import { trimAndEllipse, getImmediateFilterParent, getFilterSiblings } from '../../common/utilities.js'
|
||||
import { trimAndEllipse, getImmediateFilterParent, getFilterSiblings, getFilterParents } from '../../common/utilities.js'
|
||||
|
||||
class Toolbar extends React.Component {
|
||||
constructor (props) {
|
||||
@@ -59,10 +59,12 @@ class Toolbar extends React.Component {
|
||||
}
|
||||
|
||||
if (siblingsOff && isTurningOff) {
|
||||
matchingKeys.push(parent)
|
||||
const grandparentsOn = getFilterParents(filters, key).filter(filt => activeFilters.includes(filt))
|
||||
matchingKeys = matchingKeys.concat(grandparentsOn)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.props.methods.onSelectFilter(matchingKeys)
|
||||
}
|
||||
|
||||
|
||||
@@ -8,8 +8,8 @@ export default ({ label, isActive, onClickCheckbox, backgroundColor }) => {
|
||||
|
||||
return (
|
||||
<div className={(isActive) ? 'item active' : 'item'}>
|
||||
<span onClick={() => onClickCheckbox()}>{label}</span>
|
||||
<button onClick={() => onClickCheckbox()}>
|
||||
<span>{label}</span>
|
||||
<button onClick={onClickCheckbox}>
|
||||
<div className='checkbox' style={styles} />
|
||||
</button>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user