mirror of
https://github.com/bellingcat/ukraine-timemap.git
synced 2026-06-08 03:18:36 +03:00
Allows for multiple specified categories that are customizable panelsin left hand side toolbar
This commit is contained in:
@@ -120,7 +120,7 @@ export function fetchDomain() {
|
||||
);
|
||||
}
|
||||
dispatch(toggleFetchingDomain());
|
||||
dispatch(setInitialCategories(result.associations));
|
||||
// dispatch(setInitialCategories(result.associations));
|
||||
dispatch(setInitialShapes(result.shapes));
|
||||
return result;
|
||||
})
|
||||
|
||||
@@ -222,9 +222,7 @@ export function getEventCategories(event, activeCategories) {
|
||||
* Takes a filter's path and concatenates it like so: Parent 1/Parent 2/Child
|
||||
*/
|
||||
export function createFilterPathString(filter) {
|
||||
return filter.mode === ASSOCIATION_MODES.FILTER
|
||||
? filter.filter_paths.join("/")
|
||||
: "";
|
||||
return filter.filter_paths.join("/");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -511,6 +509,11 @@ export function setD3Locale(d3) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the set of associated styles for a given shape type from the entire set of shapes
|
||||
* @param list shapes - The aggregated set of shapes
|
||||
* @param list activeShapes - The set of active shapes in the app
|
||||
*/
|
||||
export function mapStyleByShape(shapes, activeShapes) {
|
||||
const styledShapes = shapes.map((s) => {
|
||||
const { colour, shape, id } = s;
|
||||
@@ -530,3 +533,40 @@ export function mapStyleByShape(shapes, activeShapes) {
|
||||
});
|
||||
return styledShapes;
|
||||
}
|
||||
|
||||
export function mapCategoriesToPaths(categories) {
|
||||
const categoryMap = categories.reduce((acc, cat) => {
|
||||
const type = cat.filter_paths[0];
|
||||
if (!(type in acc)) {
|
||||
acc[type] = [];
|
||||
}
|
||||
acc[type].push(cat);
|
||||
return acc;
|
||||
}, {});
|
||||
return categoryMap;
|
||||
}
|
||||
|
||||
export function getCategoryIdxs(panelCategories, startingIdx) {
|
||||
let idxCounter = startingIdx;
|
||||
// If there are specified categories from the config, filter out the default value; else, leave the default value
|
||||
const catTypes =
|
||||
panelCategories.length > 1 && panelCategories.includes("default")
|
||||
? panelCategories.filter((val) => val !== "default")
|
||||
: panelCategories;
|
||||
return catTypes.reduce((set, val) => {
|
||||
set[val] = idxCounter;
|
||||
idxCounter += 1;
|
||||
return set;
|
||||
}, {});
|
||||
}
|
||||
|
||||
export function getFilterIdx(
|
||||
narrativesExist,
|
||||
categoriesExist,
|
||||
numCategoryPanels
|
||||
) {
|
||||
if (narrativesExist && !categoriesExist) return 1;
|
||||
else if (!narrativesExist && categoriesExist) return numCategoryPanels;
|
||||
else if (narrativesExist && categoriesExist) return numCategoryPanels + 1;
|
||||
else return;
|
||||
}
|
||||
|
||||
@@ -17,6 +17,9 @@ import {
|
||||
getFilterAncestors,
|
||||
addToColoringSet,
|
||||
removeFromColoringSet,
|
||||
mapCategoriesToPaths,
|
||||
getCategoryIdxs,
|
||||
getFilterIdx,
|
||||
} from "../common/utilities.js";
|
||||
|
||||
class Toolbar extends React.Component {
|
||||
@@ -110,21 +113,36 @@ class Toolbar extends React.Component {
|
||||
}
|
||||
|
||||
renderToolbarCategoriesPanel() {
|
||||
const { panels } = this.props.toolbarCopy;
|
||||
if (this.props.features.USE_CATEGORIES) {
|
||||
return (
|
||||
<TabPanel>
|
||||
<CategoriesListPanel
|
||||
categories={this.props.categories}
|
||||
activeCategories={this.props.activeCategories}
|
||||
onCategoryFilter={this.props.methods.onCategoryFilter}
|
||||
language={this.props.language}
|
||||
title={panels.categories.label}
|
||||
description={panels.categories.description}
|
||||
/>
|
||||
</TabPanel>
|
||||
);
|
||||
}
|
||||
const { categories: panelCategories } = this.props.toolbarCopy.panels;
|
||||
const catMap = mapCategoriesToPaths(this.props.categories);
|
||||
console.info(catMap);
|
||||
return (
|
||||
<div>
|
||||
{Object.keys(catMap).map((type) => {
|
||||
const children = catMap[type];
|
||||
return (
|
||||
<TabPanel>
|
||||
<CategoriesListPanel
|
||||
categories={children}
|
||||
activeCategories={this.props.activeCategories}
|
||||
onCategoryFilter={this.props.methods.onCategoryFilter}
|
||||
language={this.props.language}
|
||||
title={
|
||||
panelCategories[type]
|
||||
? panelCategories[type].label
|
||||
: panelCategories.default.label
|
||||
}
|
||||
description={
|
||||
panelCategories[type]
|
||||
? panelCategories[type].description
|
||||
: panelCategories.default.description
|
||||
}
|
||||
/>
|
||||
</TabPanel>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
renderToolbarFilterPanel() {
|
||||
@@ -181,6 +199,21 @@ class Toolbar extends React.Component {
|
||||
);
|
||||
}
|
||||
|
||||
renderToolbarCategoryTabs(idxs) {
|
||||
const { categories: panelCategories } = this.props.toolbarCopy.panels;
|
||||
return (
|
||||
<div>
|
||||
{Object.keys(idxs).map((key) => {
|
||||
return this.renderToolbarTab(
|
||||
idxs[key],
|
||||
panelCategories[key].label,
|
||||
panelCategories[key].icon
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
renderToolbarPanels() {
|
||||
const { features, narratives } = this.props;
|
||||
const classes =
|
||||
@@ -230,14 +263,18 @@ class Toolbar extends React.Component {
|
||||
const { panels } = toolbarCopy;
|
||||
|
||||
const narrativesIdx = 0;
|
||||
const categoriesIdx = narrativesExist ? 1 : 0;
|
||||
const filtersIdx =
|
||||
narrativesExist && features.USE_CATEGORIES
|
||||
? 2
|
||||
: narrativesExist || features.USE_CATEGORIES
|
||||
? 1
|
||||
: 0;
|
||||
const categoryIdxs = getCategoryIdxs(
|
||||
Object.keys(panels.categories),
|
||||
narrativesExist ? 1 : 0
|
||||
);
|
||||
const numCategoryPanels = Object.keys(categoryIdxs).length;
|
||||
const filtersIdx = getFilterIdx(
|
||||
narrativesExist,
|
||||
features.USE_CATEGORIES,
|
||||
numCategoryPanels || 0
|
||||
);
|
||||
const shapesIdx = filtersIdx + 1;
|
||||
|
||||
return (
|
||||
<div className="toolbar">
|
||||
<div className="toolbar-header" onClick={this.props.methods.onTitle}>
|
||||
@@ -252,11 +289,7 @@ class Toolbar extends React.Component {
|
||||
)
|
||||
: null}
|
||||
{features.USE_CATEGORIES
|
||||
? this.renderToolbarTab(
|
||||
categoriesIdx,
|
||||
panels.categories.label,
|
||||
panels.categories.icon
|
||||
)
|
||||
? this.renderToolbarCategoryTabs(categoryIdxs)
|
||||
: null}
|
||||
{features.USE_ASSOCIATIONS
|
||||
? this.renderToolbarTab(
|
||||
|
||||
@@ -112,10 +112,13 @@ const initial = {
|
||||
toolbar: {
|
||||
panels: {
|
||||
categories: {
|
||||
icon: DEFAULT_TAB_ICONS.CATEGORY,
|
||||
label: copy[language].toolbar.categories_label,
|
||||
title: copy[language].toolbar.explore_by_category__title,
|
||||
description: copy[language].toolbar.explore_by_category__description,
|
||||
default: {
|
||||
icon: DEFAULT_TAB_ICONS.CATEGORY,
|
||||
label: copy[language].toolbar.categories_label,
|
||||
title: copy[language].toolbar.explore_by_category__title,
|
||||
description:
|
||||
copy[language].toolbar.explore_by_category__description,
|
||||
},
|
||||
},
|
||||
filters: {
|
||||
icon: DEFAULT_TAB_ICONS.FILTER,
|
||||
@@ -187,6 +190,7 @@ const initial = {
|
||||
},
|
||||
|
||||
features: {
|
||||
USE_MULTIPLE_CATEGORIES: false,
|
||||
USE_COVER: false,
|
||||
USE_ASSOCIATIONS: false,
|
||||
USE_SITES: false,
|
||||
|
||||
Reference in New Issue
Block a user