diff --git a/src/components/Card.jsx b/src/components/Card.jsx index a7ad401..d53bc31 100644 --- a/src/components/Card.jsx +++ b/src/components/Card.jsx @@ -33,12 +33,6 @@ class Card extends React.Component { }); } - getCategoryColorClass(category) { - if (category) - return this.props.getCategoryGroup(category); - return 'other'; - } - makeTimelabel(timestamp) { if (timestamp === null) return null; const parsedTimestamp = this.props.tools.parser(timestamp); @@ -48,14 +42,14 @@ class Card extends React.Component { renderCategory() { const categoryTitle = copy[this.props.language].cardstack.category; - const colorType = this.getCategoryColorClass(this.props.event.category); - const categoryLabel = this.props.getCategoryLabel(this.props.event.category); + const categoryLabel = this.props.event.category; + const color = this.props.getCategoryColor(this.props.event.category); return ( ); } diff --git a/src/components/CardStack.jsx b/src/components/CardStack.jsx index f5e20b9..84ae9aa 100644 --- a/src/components/CardStack.jsx +++ b/src/components/CardStack.jsx @@ -1,4 +1,7 @@ import React from 'react'; +import { connect } from 'react-redux' +import * as selectors from '../selectors' + import Card from './Card.jsx'; import copy from '../js/data/copy.json'; import { @@ -22,7 +25,7 @@ class CardStack extends React.Component { isLoading={this.props.isLoading} getNarrativeLinks={this.props.getNarrativeLinks} getCategoryGroup={this.props.getCategoryGroup} - getCategoryGroupColor={this.props.getCategoryGroupColor} + getCategoryColor={this.props.getCategoryColor} getCategoryLabel={this.props.getCategoryLabel} highlight={this.props.highlight} select={this.props.select} @@ -90,4 +93,14 @@ class CardStack extends React.Component { } } -export default CardStack; +function mapStateToProps(state) { + return { + selected: state.app.selected, + language: state.app.language, + tools: state.ui.tools, + isCardstack: state.ui.flags.isCardstack, + isLoading: state.ui.flags.isFetchingEvents + } +} + +export default connect(mapStateToProps)(CardStack) diff --git a/src/components/Dashboard.jsx b/src/components/Dashboard.jsx index cb617a3..1c6d4bf 100644 --- a/src/components/Dashboard.jsx +++ b/src/components/Dashboard.jsx @@ -92,20 +92,8 @@ class Dashboard extends React.Component { } } - getCategoryGroup(category) { - const cat = this.props.domain.categories.find(t => t.category === category) - if (cat) return cat.group; - return 'other'; - } - - getCategoryGroupColor(category) { - const group = this.getCategoryGroup(category); - return this.props.ui.style.groupColors[group]; - } - - getCategoryLabel(category) { - const categories = this.props.domain.categories; - return categories.find(t => t.category === category).category_label; + getCategoryColor(category='other') { + return this.props.ui.style.categories[category] || this.props.style.categories['other'] } getNarrativeLinks(event) { @@ -117,81 +105,31 @@ class Dashboard extends React.Component { render() { return (
- this.getCategoryGroup(category), - getCategoryGroupColor: category => this.getCategoryGroupColor(category) + getCategoryColor: category => this.getCategoryColor(category) }} /> this.handleToggle(key) } actions={this.props.actions} /> this.getNarrativeLinks(event)} - getCategoryGroup={category => this.getCategoryGroup(category)} - getCategoryGroupColor={category => this.getCategoryGroupColor(category)} - getCategoryLabel={category => this.getCategoryLabel(category)} + getCategoryColor={category => this.getCategoryColor(category)} /> item)} - narratives={this.props.domain.narratives} - categoryGroups={this.props.domain.categoryGroups} - - timerange={this.props.app.filters.timerange} - selected={this.props.app.selected} - language={this.props.app.language} - - tools={this.props.ui.tools} - dom={this.props.ui.dom} - select={this.handleSelect} filter={this.handleTimeFilter} highlight={this.handleHighlight} toggle={() => this.handleToggle('TOGGLE_CARDSTACK')} - getCategoryGroup={category => this.getCategoryGroup(category)} - getCategoryGroupColor={category => this.getCategoryGroupColor(category)} - getCategoryLabel={category => this.getCategoryLabel(category)} + getCategoryColor={category => this.getCategoryColor(category)} /> state, mapDispatchToProps, )(Dashboard); diff --git a/src/components/Timeline.jsx b/src/components/Timeline.jsx index 9a2a939..e582bc9 100644 --- a/src/components/Timeline.jsx +++ b/src/components/Timeline.jsx @@ -1,5 +1,8 @@ -import copy from '../js/data/copy.json'; import React from 'react'; +import { connect } from 'react-redux'; +import * as selectors from '../selectors'; + +import copy from '../js/data/copy.json'; import TimelineLogic from '../js/timeline/timeline.js'; class Timeline extends React.Component { @@ -12,7 +15,7 @@ class Timeline extends React.Component { const domain = { events: this.props.events, narratives: this.props.narratives, - categoryGroups: this.props.categoryGroups + categories: this.props.categories } const app = { timerange: this.props.timerange, @@ -20,9 +23,7 @@ class Timeline extends React.Component { language: this.props.language, select: this.props.select, filter: this.props.filter, - getCategoryLabel: this.props.getCategoryLabel, - getCategoryGroup: this.props.getCategoryGroup, - getCategoryGroupColor: this.props.getCategoryGroupColor + getCategoryColor: this.props.getCategoryColor } const ui = { tools: this.props.tools, @@ -38,7 +39,7 @@ class Timeline extends React.Component { const domain = { events: nextProps.events, narratives: nextProps.narratives, - categoryGroups: nextProps.categoryGroups + categories: nextProps.categories } const app = { @@ -47,9 +48,7 @@ class Timeline extends React.Component { language: nextProps.language, select: nextProps.select, filter: nextProps.filter, - getCategoryLabel: nextProps.getCategoryLabel, - getCategoryGroup: nextProps.getCategoryGroup, - getCategoryGroupColor: nextProps.getCategoryGroupColor + getCategoryColor: nextProps.getCategoryColor } this.timeline.update(domain, app); @@ -64,13 +63,14 @@ class Timeline extends React.Component { renderLabels() { const labels = copy[this.props.language].timeline.labels; - return this.props.categoryGroups.map((label) => { - const groupLen = this.props.categoryGroups.length + return this.props.categories.map((label) => { + const groupLen = this.props.categories.length return (
{label}
); }); } render() { + let events = this.props.events const labels_title_lang = copy[this.props.language].timeline.labels_title; const info_lang = copy[this.props.language].timeline.info; let classes = `timeline-wrapper ${(this.state.isFolded) ? ' folded' : ''}`; @@ -96,4 +96,18 @@ class Timeline extends React.Component { } } -export default Timeline; +function mapStateToProps(state) { + return { + // events: selectors.selectEvents(state), + events: state.domain.events, + categories: selectors.selectCategories(state), + language: state.app.language, + tools: state.ui.tools, + timerange: selectors.getTimeRange(state), + dom: state.ui.dom, + selected: state.app.selected + } +} + +export default connect(mapStateToProps)(Timeline); +// export default Timeline \ No newline at end of file diff --git a/src/components/Toolbar.jsx b/src/components/Toolbar.jsx index 368eedd..e7eef11 100644 --- a/src/components/Toolbar.jsx +++ b/src/components/Toolbar.jsx @@ -1,5 +1,7 @@ - import React from 'react'; +import { connect } from 'react-redux' +import * as selectors from '../selectors' + import { Tab, Tabs, TabList, TabPanel } from 'react-tabs'; import Search from './Search.jsx'; import TagListPanel from './TagListPanel.jsx'; @@ -226,4 +228,16 @@ class Toolbar extends React.Component { } } -export default Toolbar; +function mapStateToProps(state) { + return { + tags: selectors.getTagTree(state), + categories: selectors.selectCategories(state), + language: state.app.language, + tagFilters: selectors.selectTagList(state), + categoryFilter: state.app.filters.categories, + viewFilters: state.app.filters.views, + features: state.app.features + } +} + +export default connect(mapStateToProps)(Toolbar) diff --git a/src/components/Viewport.jsx b/src/components/Viewport.jsx index 7fd2c47..363a652 100644 --- a/src/components/Viewport.jsx +++ b/src/components/Viewport.jsx @@ -1,19 +1,21 @@ -import React from 'react'; -import Map from '../js/map/map.js'; -import { areEqual } from '../js/data/utilities.js'; +import React from 'react' +import { connect } from 'react-redux' +import * as selectors from '../selectors' +import Map from '../js/map/map.js' +import { areEqual } from '../js/data/utilities.js' class Viewport extends React.Component { constructor(props) { - super(props); + super(props) } componentDidMount() { - this.map = new Map(this.props.app, this.props.ui, this.props.methods); - this.map.update(this.props.domain, this.props.app); + this.map = new Map(this.props.app, this.props.ui, this.props.methods) + this.map.update(this.props.domain, this.props.app) } componentWillReceiveProps(nextProps) { - this.map.update(nextProps.domain, nextProps.app); + this.map.update(nextProps.domain, nextProps.app) } render() { @@ -21,8 +23,29 @@ class Viewport extends React.Component {
- ); + ) } } -export default Viewport; +function mapStateToProps(state) { + return { + domain: { + locations: selectors.selectLocations(state), + narratives: selectors.selectNarratives(state), + categories: selectors.selectCategories(state), + sites: selectors.getSites(state) + }, + app: { + views: state.app.filters.views, + selected: state.app.selected, + highlighted: state.app.highlighted, + mapAnchor: state.app.mapAnchor + }, + ui: { + dom: state.ui.dom, + narratives: state.ui.style.narratives + } + } +} + +export default connect(mapStateToProps)(Viewport) diff --git a/src/components/presentational/CardCategory.js b/src/components/presentational/CardCategory.js index a106112..43dd010 100644 --- a/src/components/presentational/CardCategory.js +++ b/src/components/presentational/CardCategory.js @@ -1,10 +1,10 @@ import React from 'react'; -const CardCategory = ({ categoryTitle, categoryLabel, colorType }) => ( +const CardCategory = ({ categoryTitle, categoryLabel, color }) => (

{categoryTitle}

- + {categoryLabel}

diff --git a/src/js/map/map.js b/src/js/map/map.js index d940169..d05e555 100644 --- a/src/js/map/map.js +++ b/src/js/map/map.js @@ -8,12 +8,10 @@ import 'leaflet-polylinedecorator'; export default function(newApp, ui, methods) { let svg, g, defs; - let categoryColorGroups = {}; - const domain = { locations: [], narratives: [], - categoryGroups: [], + categories: [], sites: [] } const app = { @@ -22,10 +20,8 @@ export default function(newApp, ui, methods) { views: Object.assign({}, newApp.views), } - const getCategoryGroup = methods.getCategoryGroup; - const getCategoryGroupColor = methods.getCategoryGroupColor; + const getCategoryColor = methods.getCategoryColor; const select = methods.select; - const groupColors = ui.groupColors; const narrativeProps = ui.narratives; // Map Settings @@ -195,7 +191,7 @@ Stop and start the development process in terminal after you have added your tok unmarkPoint(); app.selected.forEach(eventPoint => { if (isNotNullNorUndefined(eventPoint) && isNotNullNorUndefined(eventPoint.location)) { - if (eventPoint.latitude && eventPoint.longitude) { + if (eventPoint.latitude && eventPoint.latitude !== "" && eventPoint.longitude && eventPoint.longitude !== "") { const location = new L.LatLng(eventPoint.latitude, eventPoint.longitude); eventCircleMarkers[eventPoint.id] = L.circleMarker(location, { radius: 32, @@ -227,32 +223,30 @@ Stop and start the development process in terminal after you have added your tok */ function getLocationEventsDistribution(location) { - const eventsHere = {}; - const categoryGroups = domain.categoryGroups; - categoryGroups.sort((a, b) => { - return (+a.slice(-2) > +b.slice(-2)); - }); - categoryGroups.forEach(group => { - eventsHere[group] = 0 + const eventCount = {}; + const categories = domain.categories; + // categories.sort((a, b) => { + // return (+a.slice(-2) > +b.slice(-2)); + // }); + categories.forEach(group => { + eventCount[group] = 0 }); - location.events.forEach((event) => { - const group = getCategoryGroup(event.category); - eventsHere[group] += 1; + location.events.forEach((event) => {; + eventCount[event.category] += 1; }); let i = 0; const events = []; - while (i < categoryGroups.length) { - let eventsCount = eventsHere[categoryGroups[i]]; - for (let j = i + 1; j < categoryGroups.length; j++) { - eventsCount += eventsHere[categoryGroups[j]]; + while (i < categories.length) { + let _eventsCount = eventCount[categories[i]]; + for (let j = i + 1; j < categories.length; j++) { + _eventsCount += eventCount[categories[j]]; } - events.push(eventsCount); + events.push(_eventsCount); i++; } - return events; } @@ -281,9 +275,9 @@ Stop and start the development process in terminal after you have added your tok select(location.events); }); - const eventsDom = g.selectAll('.location').selectAll('.location-event-marker') - .data((d, i) => getLocationEventsDistribution(domain.locations[i]), - (d, i) => 'location-' + i); + const eventsDom = g.selectAll('.location') + .selectAll('.location-event-marker') + .data((d, i) => getLocationEventsDistribution(domain.locations[i])) eventsDom .exit() @@ -298,7 +292,7 @@ Stop and start the development process in terminal after you have added your tok eventsDom .enter().append('circle') .attr('class', 'location-event-marker') - .style('fill', (d, i) => groupColors[domain.categoryGroups[i]]) + .style('fill', (d, i) => getCategoryColor(domain.categories[i])) .transition() .duration(500) .attr('r', d => (d) ? Math.sqrt(16 * d) + 3 : 0); @@ -391,7 +385,7 @@ Stop and start the development process in terminal after you have added your tok if (hash(domain) !== hash(newDomain)) { domain.locations = newDomain.locations; domain.narratives = newDomain.narratives; - domain.categoryGroups = newDomain.categoryGroups; + domain.categories = newDomain.categories; domain.sites = newDomain.sites; renderDomain(); } diff --git a/src/js/timeline/timeline.js b/src/js/timeline/timeline.js index f29b20d..382a90a 100644 --- a/src/js/timeline/timeline.js +++ b/src/js/timeline/timeline.js @@ -50,22 +50,15 @@ export default function(app, ui) { active: false }, ]; - let events = []; - let categoryGroups = []; + let categories = []; let selected = []; let timerange = app.timerange; const timeFilter = app.filter; const select = app.select; const getCategoryLabel = app.getCategoryLabel; - const getCategoryGroupColor = app.getCategoryGroupColor; - const getCategoryGroup = app.getCategoryGroup; - - // Play functions - window.playInterval; - let isPlaying = false; - const playDuration = 1000; + const getCategoryColor = app.getCategoryColor; // Drag behavior let dragPos0; @@ -93,14 +86,15 @@ export default function(app, ui) { .domain(timerange) .range([mg.l, WIDTH]); - const groupStep = (106 - 30) / categoryGroups.length; - const groupYs = new Array(categoryGroups.length); + // calculate group step between categories + const groupStep = (106 - 30) / categories.length; + const groupYs = new Array(categories.length); groupYs.map((g, i) => { return 30 + i * groupStep; }); scale.y = d3.scaleOrdinal() - .domain(categoryGroups) + .domain(categories) .range(groupYs); /** @@ -292,7 +286,7 @@ export default function(app, ui) { * @param {object} eventPoint data object */ function getEventPointFillColor(eventPoint) { - return getCategoryGroupColor(eventPoint.category); + return getCategoryColor(eventPoint.category); } /** @@ -301,10 +295,10 @@ export default function(app, ui) { */ function getAllEventsAtOnce(eventPoint) { const timestamp = eventPoint.timestamp; - const categoryGroup = getCategoryGroup(eventPoint.category); + const categoryGroup = eventPoint.category; return events.filter(event => { return (event.timestamp === timestamp && - categoryGroup === getCategoryGroup(event.category)) + categoryGroup === event.category) }).map(event => event.id); } @@ -313,7 +307,7 @@ export default function(app, ui) { * @param {object} eventPoint: regular eventPoint data */ function getEventY(eventPoint) { - const yGroup = getCategoryGroup(eventPoint.category); + const yGroup = eventPoint.category; return scale.y(yGroup); } @@ -370,7 +364,7 @@ export default function(app, ui) { /** * Shift time range by moving forward or backwards - * @param {Stirng} direction: 'forward' / 'backwards' + * @param {String} direction: 'forward' / 'backwards' */ function moveTime(direction) { select(); @@ -597,20 +591,20 @@ export default function(app, ui) { * @param {Object} app: Redux state app subtree */ function updateAxis(domain) { - categoryGroups = domain.categoryGroups - const groupStep = (106 - 30) / categoryGroups.length; - let groupYs = Array.apply(null, Array(categoryGroups.length)); + const categories = domain.categories + const groupStep = (106 - 30) / categories.length; + let groupYs = Array.apply(null, Array(categories.length)); groupYs = groupYs.map((g, i) => { return 30 + i * groupStep; }); scale.y = d3.scaleOrdinal() - .domain(categoryGroups) + .domain(categories) .range(groupYs); axis.y = d3.axisLeft(scale.y) - .tickValues(categoryGroups); + .tickValues(categories); } function update(domain, app) { diff --git a/src/reducers/schema/categorySchema.js b/src/reducers/schema/categorySchema.js index 4156379..d51b561 100644 --- a/src/reducers/schema/categorySchema.js +++ b/src/reducers/schema/categorySchema.js @@ -2,11 +2,7 @@ import Joi from 'joi'; const categorySchema = Joi.object().keys({ category: Joi.string().required(), - category_label: Joi.string().allow('').required(), - group: Joi.string(), - group_label: Joi.string(), + description: Joi.string(), }); -const optionalSchema = categorySchema.optionalKeys('group', 'group_label'); - export default categorySchema; diff --git a/src/reducers/schema/eventSchema.js b/src/reducers/schema/eventSchema.js index 3ecc635..9dd4f90 100644 --- a/src/reducers/schema/eventSchema.js +++ b/src/reducers/schema/eventSchema.js @@ -7,8 +7,8 @@ const eventSchema = Joi.object().keys({ time: Joi.string().required(), time_precision: Joi.string().allow(''), location: Joi.string().allow('').required(), - latitude: Joi.string().required(), - longitude: Joi.string().required(), + latitude: Joi.string().allow('').required(), + longitude: Joi.string().allow('').required(), type: Joi.string().allow(''), category: Joi.string().required(), narrative: Joi.string().allow(''), diff --git a/src/scss/_colors.scss b/src/scss/_colors.scss index 62e629a..5b8f0e2 100644 --- a/src/scss/_colors.scss +++ b/src/scss/_colors.scss @@ -10,8 +10,13 @@ $midgrey: rgb(44, 44, 44); $darkgrey: #232323; $black: #000000; -$category_group00: #FF0000; -$category_group01: #226b22; -$category_group02: #671f6f; -$category_group03: #0000bf; -$category_group04: #d3ce2a; +// Category colors +$default: red; +$alpha: #00ff00; +$beta: #ff00ff; +$other: yellow; + +.default { background: $default; } +.other { background: $other; } +.alpha { background: $alpha; } +.beta { background: $beta; } diff --git a/src/scss/card.scss b/src/scss/card.scss index 6222ccd..186508a 100644 --- a/src/scss/card.scss +++ b/src/scss/card.scss @@ -112,12 +112,6 @@ border-radius: 20px; display: inline-block; margin: 0px 5px 0 0; - - &.category_group00 { background: $category_group00; } - &.category_group01 { background: $category_group01; } - &.category_group02 { background: $category_group02; } - &.category_group03 { background: $category_group03; } - &.category_group04 { background: $category_group04; } } } diff --git a/src/scss/infopopup.scss b/src/scss/infopopup.scss index 7c3d56e..5b75683 100644 --- a/src/scss/infopopup.scss +++ b/src/scss/infopopup.scss @@ -53,12 +53,6 @@ border-radius: 10px; display: inline-block; margin: 0px 5px 0 0; - - &.category_group00 { background: $category_group00; } - &.category_group01 { background: $category_group01; } - &.category_group02 { background: $category_group02; } - &.category_group03 { background: $category_group03; } - &.category_group04 { background: $category_group04; } } } } diff --git a/src/selectors/index.js b/src/selectors/index.js index 329ff3e..bd1315f 100644 --- a/src/selectors/index.js +++ b/src/selectors/index.js @@ -151,7 +151,7 @@ export const selectLocations = createSelector( export const selectCategories = createSelector( [getCategories], (categories) => { - return Object.values(categories); + return categories.map(v => v.category); } ); diff --git a/src/store/initial.js b/src/store/initial.js index a1d5103..42197fc 100644 --- a/src/store/initial.js +++ b/src/store/initial.js @@ -72,17 +72,16 @@ const initial = { GREEN: "#4FF2F2",//"rgb(0, 158, 86)", }, - groupColors: { - category_group00: "#FF0000", - category_group01: "#226b22", - category_group02: "#671f6f", - category_group03: "#0000bf", - category_group04: "#d3ce2a", - other: "#FF0000" - }, - palette: d3.schemeCategory10, + categories: { + default: 'red', + // Add here other categories to differentiate by color, like: + alpha: '#00ff00', + beta: '#ff0000', + other: 'yellow' + }, + narratives: { default: { style: 'dotted', // ['dotted', 'solid']