mirror of
https://github.com/bellingcat/ukraine-timemap.git
synced 2026-06-12 05:18:34 +03:00
Add narrative styling options to store
This commit is contained in:
@@ -15,108 +15,111 @@ import Timeline from './Timeline.jsx';
|
||||
import Notification from './Notification.jsx';
|
||||
|
||||
class Dashboard extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.handleHighlight = this.handleHighlight.bind(this);
|
||||
this.handleSelect = this.handleSelect.bind(this);
|
||||
this.handleToggle = this.handleToggle.bind(this);
|
||||
this.handleTagFilter = this.handleTagFilter.bind(this);
|
||||
this.handleTimeFilter = this.handleTimeFilter.bind(this);
|
||||
this.handleHighlight = this.handleHighlight.bind(this);
|
||||
this.handleSelect = this.handleSelect.bind(this);
|
||||
this.handleToggle = this.handleToggle.bind(this);
|
||||
this.handleTagFilter = this.handleTagFilter.bind(this);
|
||||
this.handleTimeFilter = this.handleTimeFilter.bind(this);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
if (!this.props.app.isMobile) {
|
||||
this.props.actions.fetchDomain()
|
||||
.then((domain) => this.props.actions.updateDomain(domain));
|
||||
}
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
if (!this.props.app.isMobile) {
|
||||
this.props.actions.fetchDomain()
|
||||
.then((domain) => this.props.actions.updateDomain(domain))
|
||||
handleHighlight(highlighted) {
|
||||
this.props.actions.updateHighlighted((highlighted) ? highlighted : null);
|
||||
}
|
||||
|
||||
handleSelect(selected) {
|
||||
if (selected) {
|
||||
//let eventsToSelect = selected.map(eventId => this.props.domain.events[eventId]);
|
||||
const parser = this.props.ui.tools.parser;
|
||||
|
||||
//eventsToSelect = eventsToSelect.sort((a, b) => {
|
||||
// return parser(a.timestamp) - parser(b.timestamp);
|
||||
//});
|
||||
|
||||
//if (eventsToSelect.every(event => (event))) {
|
||||
// this.props.actions.updateSelected(eventsToSelect);
|
||||
//}
|
||||
const enhanceEvent = (ev) => {
|
||||
return Object.assign({}, ev, this.props.domain.events[ev.id]);
|
||||
}
|
||||
}
|
||||
|
||||
handleHighlight(highlighted) {
|
||||
this.props.actions.updateHighlighted((highlighted) ? highlighted : null);
|
||||
}
|
||||
// Now fetch detail data for each event
|
||||
// Add transmitter and receiver data for coevents
|
||||
this.props.actions.fetchEvents(selected)
|
||||
.then((events) => {
|
||||
let eventsSelected = events.map(enhanceEvent);
|
||||
|
||||
handleSelect(selected) {
|
||||
if (selected) {
|
||||
let eventsToSelect = selected.map(eventId => this.props.domain.events[eventId]);
|
||||
const parser = this.props.ui.tools.parser;
|
||||
|
||||
eventsToSelect = eventsToSelect.sort((a, b) => {
|
||||
return parser(a.timestamp) - parser(b.timestamp);
|
||||
});
|
||||
|
||||
if (eventsToSelect.every(event => (event))) {
|
||||
this.props.actions.updateSelected(eventsToSelect);
|
||||
}
|
||||
|
||||
// Now fetch detail data for each event
|
||||
// Add transmitter and receiver data for coevents
|
||||
this.props.actions.fetchEvents(selected)
|
||||
.then((events) => {
|
||||
let eventsSelected = events.map(ev => {
|
||||
return Object.assign({}, ev, this.props.domain.events[ev.id]);
|
||||
});
|
||||
|
||||
eventsSelected = eventsSelected.sort((a, b) => {
|
||||
return parser(a.timestamp) - parser(b.timestamp);
|
||||
});
|
||||
|
||||
this.props.actions.updateSelected(eventsSelected);
|
||||
eventsSelected = eventsSelected.sort((a, b) => {
|
||||
return parser(a.timestamp) - parser(b.timestamp);
|
||||
});
|
||||
} else {
|
||||
|
||||
this.props.actions.updateSelected(eventsSelected);
|
||||
});
|
||||
} else {
|
||||
this.props.actions.updateSelected([]);
|
||||
}
|
||||
}
|
||||
|
||||
handleTagFilter(tag) {
|
||||
this.props.actions.updateTagFilters(tag);
|
||||
}
|
||||
|
||||
handleTimeFilter(timeRange) {
|
||||
this.props.actions.updateTimeRange(timeRange);
|
||||
}
|
||||
|
||||
handleToggle( key ) {
|
||||
switch( key ) {
|
||||
case 'TOGGLE_CARDSTACK': {
|
||||
this.props.actions.updateSelected([]);
|
||||
break;
|
||||
}
|
||||
case 'TOGGLE_INFOPOPUP': {
|
||||
this.props.actions.toggleInfoPopup();
|
||||
break;
|
||||
}
|
||||
case 'TOGGLE_NOTIFICATIONS': {
|
||||
this.props.actions.toggleNotifications();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
handleTagFilter(tag) {
|
||||
this.props.actions.updateTagFilters(tag);
|
||||
}
|
||||
getCategoryGroup(category) {
|
||||
const cat = this.props.domain.categories.find(t => t.category === category)
|
||||
if (cat) return cat.group;
|
||||
return 'other';
|
||||
}
|
||||
|
||||
handleTimeFilter(timeRange) {
|
||||
this.props.actions.updateTimeRange(timeRange);
|
||||
}
|
||||
getCategoryGroupColor(category) {
|
||||
const group = this.getCategoryGroup(category);
|
||||
return this.props.ui.style.groupColors[group];
|
||||
}
|
||||
|
||||
handleToggle( key ) {
|
||||
switch( key ) {
|
||||
case 'TOGGLE_CARDSTACK': {
|
||||
this.props.actions.updateSelected([]);
|
||||
break;
|
||||
}
|
||||
case 'TOGGLE_INFOPOPUP': {
|
||||
this.props.actions.toggleInfoPopup();
|
||||
break;
|
||||
}
|
||||
case 'TOGGLE_NOTIFICATIONS': {
|
||||
this.props.actions.toggleNotifications();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
getCategoryLabel(category) {
|
||||
const categories = this.props.domain.categories;
|
||||
return categories.find(t => t.category === category).category_label;
|
||||
}
|
||||
|
||||
getCategoryGroup(category) {
|
||||
const cat = this.props.domain.categories.find(t => t.category === category)
|
||||
if (cat) return cat.group;
|
||||
return 'other';
|
||||
}
|
||||
getNarrativeLinks(event) {
|
||||
const narrative = this.props.domain.narratives.find(nv => nv.key === event.narrative);
|
||||
if (narrative) return narrative.byId[event.id];
|
||||
return null;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
getNarrativeLinks(event) {
|
||||
const narrative = this.props.domain.narratives.find(nv => nv.key === event.narrative);
|
||||
if (narrative) return narrative.byId[event.id];
|
||||
return null;
|
||||
}
|
||||
|
||||
renderTool() {
|
||||
return (<div>
|
||||
render() {
|
||||
console.log(this.props)
|
||||
return (
|
||||
<div>
|
||||
<Viewport
|
||||
locations={this.props.domain.locations}
|
||||
narratives={this.props.domain.narratives}
|
||||
@@ -128,8 +131,11 @@ class Dashboard extends React.Component {
|
||||
highlighted={this.props.app.highlighted}
|
||||
mapAnchor={this.props.app.mapAnchor}
|
||||
|
||||
dom={this.props.ui.dom}
|
||||
groupColors={this.props.ui.style.groupColors}
|
||||
ui={{
|
||||
dom: this.props.ui.dom,
|
||||
narratives: this.props.ui.style.narratives,
|
||||
groupColors: this.props.ui.style.groupColors
|
||||
}}
|
||||
|
||||
select={this.handleSelect}
|
||||
highlight={this.handleHighlight}
|
||||
@@ -201,18 +207,13 @@ class Dashboard extends React.Component {
|
||||
language={this.props.app.language}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
render() {
|
||||
return (<div>{this.renderTool()}</div>);
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
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),
|
||||
|
||||
@@ -24,12 +24,8 @@ class Viewport extends React.Component {
|
||||
select: this.props.select,
|
||||
mapAnchor: this.props.mapAnchor
|
||||
}
|
||||
const ui = {
|
||||
groupColors: this.props.groupColors,
|
||||
dom: this.props.dom
|
||||
}
|
||||
|
||||
this.map = new Map(app, ui);
|
||||
this.map = new Map(app, this.props.ui);
|
||||
this.map.update(domain, app);
|
||||
}
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@ export default function(newApp, ui) {
|
||||
const getCategoryGroupColor = newApp.getCategoryGroupColor;
|
||||
const select = newApp.select;
|
||||
const groupColors = ui.groupColors;
|
||||
const narrativeProps = ui.narratives;
|
||||
|
||||
// Map Settings
|
||||
const center = newApp.mapAnchor;
|
||||
@@ -360,8 +361,19 @@ Stop and start the development process in terminal after you have added your tok
|
||||
.enter().append('path')
|
||||
.attr('class', 'narrative')
|
||||
.attr('d', sequenceLine)
|
||||
.style('stroke-width', 3)
|
||||
.style('stroke', '#fff')
|
||||
.style('stroke-width', d => {
|
||||
const n = d[0].narrative;
|
||||
return (n) ? narrativeProps[n].strokeWidth : 3;
|
||||
})
|
||||
.style('stroke-dasharray', d => {
|
||||
const n = d[0].narrative;
|
||||
if (narrativeProps[n].style === 'dotted') return "2px 5px";
|
||||
return 'none';
|
||||
})
|
||||
.style('stroke', d => {
|
||||
const n = d[0].narrative;
|
||||
return (n) ? narrativeProps[n].stroke : '#fff';
|
||||
})
|
||||
.style('fill', 'none');
|
||||
}
|
||||
|
||||
|
||||
@@ -10,7 +10,6 @@ export const getSites = (state) => {
|
||||
if (process.env.features.USE_SITES) return state.domain.sites
|
||||
return []
|
||||
}
|
||||
console.log(process.env)
|
||||
export const getNotifications = state => state.domain.notifications;
|
||||
export const getTagTree = state => state.domain.tags;
|
||||
export const getTagsFilter = state => state.app.filters.tags;
|
||||
@@ -103,6 +102,7 @@ export const selectNarratives = createSelector(
|
||||
narratives[evt.narrative].byId[evt.id] = { next: null, prev: null };
|
||||
}
|
||||
});
|
||||
|
||||
Object.keys(narratives).forEach((key) => {
|
||||
const steps = narratives[key].steps;
|
||||
steps.sort((a, b) => {
|
||||
@@ -112,7 +112,8 @@ export const selectNarratives = createSelector(
|
||||
narratives[key].byId[step.id].next = (i < steps.length - 2) ? steps[i + 1] : null;
|
||||
narratives[key].byId[step.id].prev = (i > 0) ? steps[i - 1] : null;
|
||||
});
|
||||
})
|
||||
});
|
||||
|
||||
return Object.values(narratives);
|
||||
});
|
||||
|
||||
|
||||
@@ -59,6 +59,7 @@ const initial = {
|
||||
*/
|
||||
ui: {
|
||||
style: {
|
||||
|
||||
colors: {
|
||||
WHITE: "#efefef",
|
||||
YELLOW: "#ffd800",
|
||||
@@ -70,6 +71,7 @@ const initial = {
|
||||
BLUE: "#F2DE79",//"rgb(48, 103 , 217)",
|
||||
GREEN: "#4FF2F2",//"rgb(0, 158, 86)",
|
||||
},
|
||||
|
||||
groupColors: {
|
||||
category_group00: "#FF0000",
|
||||
category_group01: "#226b22",
|
||||
@@ -78,7 +80,17 @@ const initial = {
|
||||
category_group04: "#d3ce2a",
|
||||
other: "#FF0000"
|
||||
},
|
||||
|
||||
palette: d3.schemeCategory10,
|
||||
|
||||
narratives: {
|
||||
narrative_1: {
|
||||
style: 'dotted', // ['dotted', 'solid']
|
||||
opacity: 0.4, // range between 0 and 1
|
||||
stroke: '#ffffff', // Any hex or rgb code
|
||||
strokeWidth: 2
|
||||
}
|
||||
}
|
||||
},
|
||||
dom: {
|
||||
timeline: "timeline",
|
||||
|
||||
Reference in New Issue
Block a user