-
Explore data by tag
-
Explore freely all the data by selecting tags.
+
{copy[this.props.language].toolbar.explore_by_tag__title}
+
{copy[this.props.language].toolbar.explore_by_tag__description}
+ {this.renderCategoryTree()}
{this.renderTree()}
);
diff --git a/src/components/Toolbar.jsx b/src/components/Toolbar.jsx
index 53b0808..4826445 100644
--- a/src/components/Toolbar.jsx
+++ b/src/components/Toolbar.jsx
@@ -81,7 +81,8 @@ class Toolbar extends React.Component {
categories={this.props.categories}
tagFilters={this.props.tagFilters}
categoryFilters={this.props.categoryFilters}
- onFilter={this.props.methods.onFilter}
+ onTagFilter={this.props.methods.onTagFilter}
+ onCategoryFilter={this.props.methods.onCategoryFilter}
language={this.props.language}
/>
@@ -185,11 +186,11 @@ class Toolbar extends React.Component {
function mapStateToProps(state) {
return {
tags: selectors.getTagTree(state),
- categories: selectors.selectCategories(state),
+ categories: selectors.getCategories(state),
narratives: selectors.selectNarratives(state),
language: state.app.language,
tagFilters: selectors.selectTagList(state),
- categoryFilter: state.app.filters.categories,
+ categoryFilters: selectors.selectCategories(state),
viewFilters: state.app.filters.views,
features: state.app.features,
narrative: state.app.narrative,
diff --git a/src/js/data/copy.json b/src/js/data/copy.json
index 039a50d..6453a2a 100644
--- a/src/js/data/copy.json
+++ b/src/js/data/copy.json
@@ -18,6 +18,10 @@
},
"toolbar": {
"title": "TITLE",
+ "categories": "Categories",
+ "tags": "Tags",
+ "explore_by_tag__title": "Explore by tag or category",
+ "explore_by_tag__description": "Selecting tags or categories, you'll see only those events that are tagged accordingly. If you select nothing, as well as everything, all data will be displayed.",
"panels": {
"mentions": {
"title": "Personas",
@@ -105,7 +109,11 @@
}
},
"narrative_panel_title": "Focus narratives",
- "narrative_summary": "Here you can follow some curated stories we have found in the data."
+ "narrative_summary": "Here you can follow some curated stories we have found in the data.",
+ "categories": "Categories",
+ "tags": "Tags",
+ "explore_by_tag__title": "Explore by tag or category",
+ "explore_by_tag__description": "Selecting tags or categories, you'll see only those events that are tagged accordingly. If you select nothing, as well as everything, all data will be displayed."
},
"timeline": {
"zooms": [
diff --git a/src/reducers/app.js b/src/reducers/app.js
index a17ec9a..b7164ea 100644
--- a/src/reducers/app.js
+++ b/src/reducers/app.js
@@ -1,11 +1,10 @@
import initial from '../store/initial.js'
-import { parseDate } from '../js/utilities.js'
-
import {
UPDATE_HIGHLIGHTED,
UPDATE_SELECTED,
UPDATE_TAGFILTERS,
+ UPDATE_CATEGORYFILTERS,
UPDATE_TIMERANGE,
UPDATE_NARRATIVE,
INCREMENT_NARRATIVE_CURRENT,
@@ -136,6 +135,25 @@ function updateTagFilters(appState, action) {
})
}
+function updateCategoryFilters(appState, action) {
+ const categoryFilters = appState.filters.categories.slice(0)
+
+ const catFilter = categoryFilters.find(cF => cF.category === action.category.category);
+
+ if (!catFilter) {
+ categoryFilters.push(action.category)
+ } else {
+ catFilter.active = (!!action.category.active);
+ }
+
+
+ return Object.assign({}, appState, {
+ filters: Object.assign({}, appState.filters, {
+ categories: categoryFilters
+ })
+ })
+}
+
function updateTimeRange(appState, action) { // XXX
return Object.assign({}, appState, {
filters: Object.assign({}, appState.filters, {
@@ -254,6 +272,8 @@ function app(appState = initial.app, action) {
return updateSelected(appState, action)
case UPDATE_TAGFILTERS:
return updateTagFilters(appState, action)
+ case UPDATE_CATEGORYFILTERS:
+ return updateCategoryFilters(appState, action)
case UPDATE_TIMERANGE:
return updateTimeRange(appState, action)
case UPDATE_NARRATIVE:
diff --git a/src/selectors/index.js b/src/selectors/index.js
index aec7e5c..2367b35 100644
--- a/src/selectors/index.js
+++ b/src/selectors/index.js
@@ -20,6 +20,7 @@ export const getSources = state => {
export const getNotifications = state => state.domain.notifications
export const getTagTree = state => state.domain.tags
export const getTagsFilter = state => state.app.filters.tags
+export const getCategoriesFilter = state => state.app.filters.categories
export const getTimeRange = state => state.app.filters.timerange
@@ -42,6 +43,19 @@ function isTaggedIn(event, tagFilters) {
}
}
+/**
+ * Given an event and all categories,
+ * returns true/false if event has a category that is active
+ */
+function isTaggedInWithCategory(event, categories) {
+ if (event.category) {
+ if (categories.find(c => (c.category === event.category && c.active))) return true
+ return false;
+ } else {
+ return false
+ }
+}
+
/*
* Returns true if no tags are selected
*/
@@ -53,6 +67,17 @@ function isNoTags(tagFilters) {
)
}
+/*
+* Returns true if no categories are selected
+*/
+function isNoCategories(categories) {
+ return (
+ categories.length === 0
+ || !process.env.features.CATEGORIES_AS_TAGS
+ || categories.every(c => !c.active)
+ )
+}
+
/**
* Given an event and a time range,
* returns true/false if the event falls within timeRange
@@ -69,14 +94,15 @@ function isTimeRangedIn(event, timeRange) {
* and if TAGS are being used, select them if their tags are enabled
*/
export const selectEvents = createSelector(
- [getEvents, getTagsFilter, getTimeRange],
- (events, tagFilters, timeRange) => {
+ [getEvents, getTagsFilter, getCategoriesFilter, getTimeRange],
+ (events, tagFilters, categories, timeRange) => {
return events.reduce((acc, event) => {
const isTagged = isTaggedIn(event, tagFilters) || isNoTags(tagFilters)
+ const isTaggedWithCategory = isTaggedInWithCategory(event, categories) || isNoCategories(categories)
const isTimeRanged = isTimeRangedIn(event, timeRange)
- if (isTimeRanged && isTagged) {
+ if (isTimeRanged && isTagged && isTaggedWithCategory) {
const eventClone = Object.assign({}, event)
acc[event.id] = eventClone
}
@@ -90,16 +116,14 @@ export const selectEvents = createSelector(
* and if TAGS are being used, select them if their tags are enabled
*/
export const selectNarratives = createSelector(
- [getEvents, getNarratives, getTagsFilter, getTimeRange, getSources],
- (events, narrativesMeta, tagFilters, timeRange, sources) => {
+ [getEvents, getNarratives, getSources],
+ (events, narrativesMeta, sources) => {
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
evt.narratives.forEach(narrative => {
@@ -229,7 +253,13 @@ export const selectSelected = createSelector(
*/
export const selectCategories = createSelector(
[getCategories],
- (categories) => categories
+ (categories) => {
+ categories.map(cat => {
+ cat.active = (!cat.hasOwnProperty('active')) ? false : cat.active
+ });
+ console.log(categories)
+ return categories;
+ }
)