mirror of
https://github.com/bellingcat/ukraine-timemap.git
synced 2026-06-11 21:08:36 +03:00
Merge pull request #29 from forensic-architecture/topic/rm-categoryGroups
Remove categoryGroups
This commit is contained in:
@@ -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 (
|
||||
<CardCategory
|
||||
categoryTitle={categoryTitle}
|
||||
categoryLabel={categoryLabel}
|
||||
colorType={colorType}
|
||||
color={color}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 (
|
||||
<div>
|
||||
<Viewport
|
||||
domain={{
|
||||
locations: this.props.domain.locations,
|
||||
narratives: this.props.domain.narratives,
|
||||
sites: this.props.domain.sites,
|
||||
categoryGroups: this.props.domain.categoryGroups
|
||||
}}
|
||||
|
||||
app={{
|
||||
views: this.props.app.filters.views,
|
||||
selected: this.props.app.selected,
|
||||
highlighted: this.props.app.highlighted,
|
||||
mapAnchor: this.props.app.mapAnchor,
|
||||
}}
|
||||
|
||||
ui={{
|
||||
dom: this.props.ui.dom,
|
||||
narratives: this.props.ui.style.narratives,
|
||||
groupColors: this.props.ui.style.groupColors
|
||||
}}
|
||||
|
||||
<Viewport
|
||||
methods={{
|
||||
select: this.handleSelect,
|
||||
highlight: this.handleHighlight,
|
||||
getCategoryGroup: category => this.getCategoryGroup(category),
|
||||
getCategoryGroupColor: category => this.getCategoryGroupColor(category)
|
||||
getCategoryColor: category => this.getCategoryColor(category)
|
||||
}}
|
||||
/>
|
||||
<Toolbar
|
||||
tags={this.props.domain.tags}
|
||||
categories={this.props.domain.categories}
|
||||
language={this.props.app.language}
|
||||
tagFilters={this.props.app.filters.tags}
|
||||
categoryFilter={this.props.app.filters.categories}
|
||||
viewFilters={this.props.app.filters.views}
|
||||
features={this.props.app.features}
|
||||
|
||||
filter={this.handleTagFilter}
|
||||
toggle={ (key) => this.handleToggle(key) }
|
||||
actions={this.props.actions}
|
||||
/>
|
||||
<CardStack
|
||||
selected={this.props.app.selected}
|
||||
language={this.props.app.language}
|
||||
tools={this.props.ui.tools}
|
||||
isCardstack={this.props.ui.flags.isCardstack}
|
||||
isLoading={this.props.ui.flags.isFetchingEvents}
|
||||
|
||||
select={this.handleSelect}
|
||||
highlight={this.handleHighlight}
|
||||
toggle={this.handleToggle}
|
||||
getNarrativeLinks={event => this.getNarrativeLinks(event)}
|
||||
getCategoryGroup={category => this.getCategoryGroup(category)}
|
||||
getCategoryGroupColor={category => this.getCategoryGroupColor(category)}
|
||||
getCategoryLabel={category => this.getCategoryLabel(category)}
|
||||
getCategoryColor={category => this.getCategoryColor(category)}
|
||||
/>
|
||||
<Timeline
|
||||
events={this.props.domain.events.filter(item => 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)}
|
||||
/>
|
||||
<InfoPopUp
|
||||
ui={this.props.ui}
|
||||
@@ -212,32 +150,6 @@ class Dashboard extends React.Component {
|
||||
}
|
||||
}
|
||||
|
||||
function mapStateToProps(state) {
|
||||
return Object.assign({}, state, {
|
||||
domain: Object.assign({}, state.domain, {
|
||||
// These items are affected by app selectionFilters
|
||||
events: selectors.selectEvents(state),
|
||||
locations: selectors.selectLocations(state),
|
||||
categories: selectors.selectCategories(state),
|
||||
categoryGroups: selectors.selectCategoryGroups(state),
|
||||
narratives: selectors.selectNarratives(state),
|
||||
|
||||
// These items are not affected by selectionFilters
|
||||
sites: selectors.getSites(state),
|
||||
tags: selectors.getTagTree(state),
|
||||
notifications: selectors.getNotifications(state)
|
||||
}),
|
||||
app: Object.assign({}, state.app, {
|
||||
error: state.app.error,
|
||||
filters: Object.assign({}, state.app.filters, {
|
||||
timerange: selectors.getTimeRange(state),
|
||||
tags: selectors.selectTagList(state)
|
||||
})
|
||||
}),
|
||||
ui: state.ui
|
||||
});
|
||||
}
|
||||
|
||||
function mapDispatchToProps(dispatch) {
|
||||
return {
|
||||
actions: bindActionCreators(actions, dispatch)
|
||||
@@ -245,6 +157,6 @@ function mapDispatchToProps(dispatch) {
|
||||
}
|
||||
|
||||
export default connect(
|
||||
mapStateToProps,
|
||||
state => state,
|
||||
mapDispatchToProps,
|
||||
)(Dashboard);
|
||||
|
||||
@@ -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 (<div className="timeline-label">{label}</div>);
|
||||
});
|
||||
}
|
||||
|
||||
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
|
||||
@@ -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)
|
||||
|
||||
@@ -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 {
|
||||
<div className='map-wrapper'>
|
||||
<div id="map" />
|
||||
</div>
|
||||
);
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import React from 'react';
|
||||
|
||||
const CardCategory = ({ categoryTitle, categoryLabel, colorType }) => (
|
||||
const CardCategory = ({ categoryTitle, categoryLabel, color }) => (
|
||||
<div className="event-card-section category">
|
||||
<h4>{categoryTitle}</h4>
|
||||
<p>
|
||||
<span className={`color-category ${colorType}`}/>
|
||||
<span className='color-category' style={{ background: color }}/>
|
||||
{categoryLabel}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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(''),
|
||||
|
||||
@@ -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; }
|
||||
|
||||
@@ -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; }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -151,7 +151,7 @@ export const selectLocations = createSelector(
|
||||
export const selectCategories = createSelector(
|
||||
[getCategories],
|
||||
(categories) => {
|
||||
return Object.values(categories);
|
||||
return categories.map(v => v.category);
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
@@ -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']
|
||||
|
||||
Reference in New Issue
Block a user