import React from "react"; import { connect } from "react-redux"; import { bindActionCreators } from "redux"; import * as actions from "../actions"; import * as selectors from "../selectors"; import { Tabs, TabList, TabPanel } from "react-tabs"; import FilterListPanel from "./controls/FilterListPanel"; import CategoriesListPanel from "./controls/CategoriesListPanel"; import ShapesListPanel from "./controls/ShapesListPanel"; import BottomActions from "./controls/BottomActions"; import copy from "../common/data/copy.json"; import { trimAndEllipse, getImmediateFilterParent, getFilterSiblings, getFilterAncestors, addToColoringSet, removeFromColoringSet, mapCategoriesToPaths, getCategoryIdxs, getFilterIdx, } from "../common/utilities.js"; import { ToolbarButton } from "./controls/atoms/ToolbarButton"; import { FullscreenToggle } from "./controls/FullScreenToggle"; import DownloadPanel from "./controls/DownloadPanel"; class Toolbar extends React.Component { constructor(props) { super(props); this.onSelectFilter = this.onSelectFilter.bind(this); this.state = { _selected: 0, _active: false }; } selectTab(selected) { let active = true; if (this.state._selected === selected && this.state._active === true) { active = false; } this.setState({ _selected: selected, _active: active }); } onSelectFilter(key, matchingKeys) { const { filters, activeFilters, coloringSet, maxNumOfColors } = this.props; const parent = getImmediateFilterParent(key); const isTurningOff = activeFilters.includes(key); if (!isTurningOff) { const updatedColoringSet = addToColoringSet(coloringSet, matchingKeys); if (updatedColoringSet.length <= maxNumOfColors) { this.props.actions.updateColoringSet(updatedColoringSet); } } else { if (parent && activeFilters.includes(parent)) { const siblings = getFilterSiblings(filters, parent, key); let siblingsOff = true; for (const sibling of siblings) { if (activeFilters.includes(sibling)) { siblingsOff = false; break; } } if (siblingsOff) { const grandparentsOn = getFilterAncestors(key).filter((filt) => activeFilters.includes(filt) ); matchingKeys = matchingKeys.concat(grandparentsOn); } } const updatedColoringSet = removeFromColoringSet( coloringSet, matchingKeys ); this.props.actions.updateColoringSet(updatedColoringSet); } this.props.methods.onSelectFilter(matchingKeys); this.props.actions.updateSelected([]); } renderClosePanel() { return (
this.selectTab(this.state._selected)} >
); } goToNarrative(narrative) { // this.selectTab(-1); // set all unselected within this component this.props.methods.onSelectNarrative(narrative); } renderToolbarNarrativePanel() { const { panels } = this.props.toolbarCopy; return (

{panels.narratives.label}

{panels.narratives.description}

{this.props.narratives.map((narr) => { return (
); })}
); } renderToolbarCategoriesPanel() { const { categories: panelCategories } = this.props.toolbarCopy.panels; const catMap = mapCategoriesToPaths( this.props.categories, Object.keys(panelCategories) ); return (
{Object.keys(catMap).map((type) => { const children = catMap[type]; return ( ); })}
); } renderToolbarFilterPanel() { const { panels } = this.props.toolbarCopy; return ( ); } renderToolbarShapePanel() { const { panels } = this.props.toolbarCopy; if (this.props.features.USE_SHAPES) { return ( ); } } renderToolbarDownloadPanel() { const { panels } = this.props.toolbarCopy; return ( ); } renderToolbarTab(_selected, label, iconKey, key) { return ( { this.selectTab(_selected); }} /> ); } renderToolbarCategoryTabs(idxs) { const { categories: panelCategories } = this.props.toolbarCopy.panels; return (
{Object.keys(idxs).map((key) => { return this.renderToolbarTab( idxs[key], panelCategories[key].label, panelCategories[key].icon, key ); })}
); } renderToolbarPanels() { const { features, narratives } = this.props; const classes = this.state._active === true ? "toolbar-panels" : "toolbar-panels folded"; return (
{this.renderClosePanel()} {narratives && narratives.length !== 0 ? this.renderToolbarNarrativePanel() : null} {features.USE_CATEGORIES ? this.renderToolbarCategoriesPanel() : null} {features.USE_ASSOCIATIONS ? this.renderToolbarFilterPanel() : null} {features.USE_SHAPES ? this.renderToolbarShapePanel() : null} {features.USE_DOWNLOAD ? this.renderToolbarDownloadPanel() : null}
); } renderToolbarNavs() { if (this.props.narratives) { return this.props.narratives.map((nar, idx) => { const isActive = idx === this.state._selected && this.state._active === true; const classes = isActive ? "toolbar-tab active" : "toolbar-tab"; return (
{ this.selectTab(idx); }} >
{nar.label}
); }); } return null; } renderToolbarTabs() { const { features, narratives, toolbarCopy } = this.props; const narrativesExist = narratives && narratives.length !== 0; let title = copy[this.props.language].toolbar.title; if (process.env.display_title) title = process.env.display_title; const { panels } = toolbarCopy; const narrativesIdx = 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 + features.USE_SHAPES; const downloadIdx = shapesIdx + features.USE_DOWNLOAD; return (

{title}

{narrativesExist ? this.renderToolbarTab( narrativesIdx, panels.narratives.label, panels.narratives.icon ) : null} {features.USE_CATEGORIES ? this.renderToolbarCategoryTabs(categoryIdxs) : null} {features.USE_ASSOCIATIONS ? this.renderToolbarTab( filtersIdx, panels.filters.label, panels.filters.icon ) : null} {features.USE_SHAPES ? this.renderToolbarTab( shapesIdx, panels.shapes.label, panels.shapes.icon ) : null} {features.USE_DOWNLOAD ? this.renderToolbarTab( downloadIdx, panels.download.label, panels.download.icon ) : null} {features.USE_FULLSCREEN && ( )}
Made with{" "} TimeMap
Free software from{" "} Forensic Architecture
); } render() { const { isNarrative } = this.props; return (
null} selectedIndex={this.state._selected}> {this.renderToolbarTabs()} {this.renderToolbarPanels()}
); } } function mapStateToProps(state) { return { filters: selectors.getFilters(state), categories: selectors.getCategories(state), narratives: selectors.selectNarratives(state), shapes: selectors.getShapes(state), language: state.app.language, toolbarCopy: state.app.toolbar, activeFilters: selectors.getActiveFilters(state), activeCategories: selectors.getActiveCategories(state), activeShapes: selectors.getActiveShapes(state), viewFilters: state.app.associations.views, narrative: state.app.associations.narrative, sitesShowing: state.app.flags.isShowingSites, infoShowing: state.app.flags.isInfopopup, coloringSet: state.app.associations.coloringSet, maxNumOfColors: state.ui.coloring.maxNumOfColors, filterColors: state.ui.coloring.colors, eventRadius: state.ui.eventRadius, features: selectors.getFeatures(state), }; } function mapDispatchToProps(dispatch) { return { actions: bindActionCreators(actions, dispatch), }; } export default connect(mapStateToProps, mapDispatchToProps)(Toolbar);