mirror of
https://github.com/bellingcat/ukraine-timemap.git
synced 2026-06-12 13:28:36 +03:00
Merge pull request #31 from forensic-architecture/fix/cleaner-handlers
Fix/cleaner handlers
This commit is contained in:
@@ -27,8 +27,8 @@ class CardStack extends React.Component {
|
||||
getCategoryGroup={this.props.getCategoryGroup}
|
||||
getCategoryColor={this.props.getCategoryColor}
|
||||
getCategoryLabel={this.props.getCategoryLabel}
|
||||
highlight={this.props.highlight}
|
||||
select={this.props.select}
|
||||
highlight={this.props.onHighlight}
|
||||
select={this.props.onSelect}
|
||||
/>
|
||||
);
|
||||
});
|
||||
@@ -54,7 +54,7 @@ class CardStack extends React.Component {
|
||||
<div
|
||||
id='card-stack-header'
|
||||
className='card-stack-header'
|
||||
onClick={() => this.props.toggle('TOGGLE_CARDSTACK')}
|
||||
onClick={() => this.props.onToggle('TOGGLE_CARDSTACK')}
|
||||
>
|
||||
<button className="side-menu-burg is-active"><span></span></button>
|
||||
<p className="header-copy top">
|
||||
|
||||
@@ -21,7 +21,7 @@ class Dashboard extends React.Component {
|
||||
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.updateTimerange = this.updateTimerange.bind(this);
|
||||
|
||||
this.eventsById = {};
|
||||
}
|
||||
@@ -45,7 +45,7 @@ class Dashboard extends React.Component {
|
||||
|
||||
handleSelect(selected) {
|
||||
if (selected) {
|
||||
let eventsToSelect = selected.map(eventId => this.getEventById(eventId));
|
||||
let eventsToSelect = selected.map(event => this.getEventById(event.id));
|
||||
const parser = this.props.ui.tools.parser;
|
||||
|
||||
eventsToSelect = eventsToSelect.sort((a, b) => {
|
||||
@@ -79,7 +79,7 @@ class Dashboard extends React.Component {
|
||||
this.props.actions.updateTagFilters(tag);
|
||||
}
|
||||
|
||||
handleTimeFilter(timeRange) {
|
||||
updateTimerange(timeRange) {
|
||||
this.props.actions.updateTimeRange(timeRange);
|
||||
}
|
||||
|
||||
@@ -126,17 +126,17 @@ class Dashboard extends React.Component {
|
||||
actions={this.props.actions}
|
||||
/>
|
||||
<CardStack
|
||||
select={this.handleSelect}
|
||||
highlight={this.handleHighlight}
|
||||
toggle={this.handleToggle}
|
||||
onSelect={this.handleSelect}
|
||||
onHighlight={this.handleHighlight}
|
||||
onToggle={this.handleToggle}
|
||||
getNarrativeLinks={event => this.getNarrativeLinks(event)}
|
||||
getCategoryColor={category => this.getCategoryColor(category)}
|
||||
/>
|
||||
<Timeline
|
||||
select={this.handleSelect}
|
||||
filter={this.handleTimeFilter}
|
||||
highlight={this.handleHighlight}
|
||||
toggle={() => this.handleToggle('TOGGLE_CARDSTACK')}
|
||||
onSelect={this.handleSelect}
|
||||
onUpdateTimerange={this.updateTimerange}
|
||||
// onHighlight={this.handleHighlight}
|
||||
// onToggle={() => this.handleToggle('TOGGLE_CARDSTACK')}
|
||||
getCategoryColor={category => this.getCategoryColor(category)}
|
||||
/>
|
||||
<InfoPopUp
|
||||
|
||||
@@ -8,51 +8,31 @@ import TimelineLogic from '../js/timeline/timeline.js';
|
||||
class Timeline extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {isFolded: false};
|
||||
this.state = {
|
||||
isFolded: false
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
const domain = {
|
||||
events: this.props.events,
|
||||
narratives: this.props.narratives,
|
||||
categories: this.props.categories
|
||||
}
|
||||
const app = {
|
||||
timerange: this.props.timerange,
|
||||
selected: this.props.selected,
|
||||
language: this.props.language,
|
||||
select: this.props.select,
|
||||
filter: this.props.filter,
|
||||
getCategoryColor: this.props.getCategoryColor
|
||||
}
|
||||
const ui = {
|
||||
tools: this.props.tools,
|
||||
dom: this.props.dom
|
||||
}
|
||||
const ui = {
|
||||
tools: this.props.tools,
|
||||
dom: this.props.dom
|
||||
}
|
||||
|
||||
this.timeline = new TimelineLogic(app, ui);
|
||||
this.timeline.update(domain, app);
|
||||
this.timeline.render(domain);
|
||||
const methods = {
|
||||
onSelect: this.props.onSelect,
|
||||
onUpdateTimerange: this.props.onUpdateTimerange,
|
||||
getCategoryColor: this.props.getCategoryColor
|
||||
}
|
||||
|
||||
this.timeline = new TimelineLogic(this.props.app, ui, methods);
|
||||
this.timeline.update(this.props.domain, this.props.app);
|
||||
this.timeline.render(this.props.domain);
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
const domain = {
|
||||
events: nextProps.events,
|
||||
narratives: nextProps.narratives,
|
||||
categories: nextProps.categories
|
||||
}
|
||||
|
||||
const app = {
|
||||
timerange: nextProps.timerange,
|
||||
selected: nextProps.selected,
|
||||
language: nextProps.language,
|
||||
select: nextProps.select,
|
||||
filter: nextProps.filter,
|
||||
getCategoryColor: nextProps.getCategoryColor
|
||||
}
|
||||
|
||||
this.timeline.update(domain, app);
|
||||
this.timeline.render(domain);
|
||||
this.timeline.update(nextProps.domain, nextProps.app);
|
||||
this.timeline.render(nextProps.domain);
|
||||
}
|
||||
|
||||
onClickArrow() {
|
||||
@@ -70,12 +50,11 @@ class Timeline extends React.Component {
|
||||
}
|
||||
|
||||
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;
|
||||
const labels_title_lang = copy[this.props.app.language].timeline.labels_title;
|
||||
const info_lang = copy[this.props.app.language].timeline.info;
|
||||
let classes = `timeline-wrapper ${(this.state.isFolded) ? ' folded' : ''}`;
|
||||
const date0 = this.props.tools.formatterWithYear(this.props.timerange[0]);
|
||||
const date1 = this.props.tools.formatterWithYear(this.props.timerange[1]);
|
||||
const date0 = this.props.tools.formatterWithYear(this.props.app.timerange[0]);
|
||||
const date1 = this.props.tools.formatterWithYear(this.props.app.timerange[1]);
|
||||
|
||||
return (
|
||||
<div className={classes}>
|
||||
@@ -98,16 +77,20 @@ class Timeline extends React.Component {
|
||||
|
||||
function mapStateToProps(state) {
|
||||
return {
|
||||
// events: selectors.selectEvents(state),
|
||||
events: state.domain.events,
|
||||
categories: selectors.selectCategories(state),
|
||||
language: state.app.language,
|
||||
domain: {
|
||||
events: state.domain.events,
|
||||
categories: selectors.selectCategories(state),
|
||||
narratives: state.domain.narratives
|
||||
},
|
||||
app: {
|
||||
timerange: selectors.getTimeRange(state),
|
||||
selected: state.app.selected,
|
||||
language: state.app.language,
|
||||
zoomLevels: state.app.zoomLevels
|
||||
},
|
||||
tools: state.ui.tools,
|
||||
timerange: selectors.getTimeRange(state),
|
||||
dom: state.ui.dom,
|
||||
selected: state.app.selected
|
||||
}
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps)(Timeline);
|
||||
// export default Timeline
|
||||
export default connect(mapStateToProps)(Timeline);
|
||||
@@ -10,56 +10,16 @@ import {
|
||||
import esLocale from '../data/es-MX.json';
|
||||
import copy from '../data/copy.json';
|
||||
|
||||
export default function(app, ui) {
|
||||
export default function(app, ui, methods) {
|
||||
d3.timeFormatDefaultLocale(esLocale);
|
||||
const formatterWithYear = ui.tools.formatterWithYear;
|
||||
const parser = ui.tools.parser;
|
||||
const zoomLevels = [{
|
||||
label: '3 años',
|
||||
duration: 1576800,
|
||||
active: false
|
||||
},
|
||||
{
|
||||
label: '3 meses',
|
||||
duration: 129600,
|
||||
active: false
|
||||
},
|
||||
{
|
||||
label: '3 días',
|
||||
duration: 4320,
|
||||
active: true
|
||||
},
|
||||
{
|
||||
label: '12 horas',
|
||||
duration: 720,
|
||||
active: false
|
||||
},
|
||||
{
|
||||
label: '2 horas',
|
||||
duration: 120,
|
||||
active: false
|
||||
},
|
||||
{
|
||||
label: '30 min',
|
||||
duration: 30,
|
||||
active: false
|
||||
},
|
||||
{
|
||||
label: '10 min',
|
||||
duration: 10,
|
||||
active: false
|
||||
},
|
||||
];
|
||||
const zoomLevels = app.zoomLevels;
|
||||
let events = [];
|
||||
let categories = [];
|
||||
let selected = [];
|
||||
let timerange = app.timerange;
|
||||
|
||||
const timeFilter = app.filter;
|
||||
const select = app.select;
|
||||
const getCategoryLabel = app.getCategoryLabel;
|
||||
const getCategoryColor = app.getCategoryColor;
|
||||
|
||||
// Drag behavior
|
||||
let dragPos0;
|
||||
let transitionDuration = 500;
|
||||
@@ -224,7 +184,7 @@ export default function(app, ui) {
|
||||
})
|
||||
.on('end', () => {
|
||||
toggleTransition(true);
|
||||
timeFilter(scale.x.domain());
|
||||
methods.onUpdateTimerange(scale.x.domain());
|
||||
});
|
||||
|
||||
/*
|
||||
@@ -286,7 +246,7 @@ export default function(app, ui) {
|
||||
* @param {object} eventPoint data object
|
||||
*/
|
||||
function getEventPointFillColor(eventPoint) {
|
||||
return getCategoryColor(eventPoint.category);
|
||||
return methods.getCategoryColor(eventPoint.category);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -295,11 +255,9 @@ export default function(app, ui) {
|
||||
*/
|
||||
function getAllEventsAtOnce(eventPoint) {
|
||||
const timestamp = eventPoint.timestamp;
|
||||
const categoryGroup = eventPoint.category;
|
||||
return events.filter(event => {
|
||||
return (event.timestamp === timestamp &&
|
||||
categoryGroup === event.category)
|
||||
}).map(event => event.id);
|
||||
const category = eventPoint.category;
|
||||
return events
|
||||
.filter(event => (event.timestamp === timestamp && category === event.category))
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -359,7 +317,7 @@ export default function(app, ui) {
|
||||
const domainF = d3.timeMinute.offset(newCentralTime, zoom.duration / 2);
|
||||
|
||||
scale.x.domain([domain0, domainF]);
|
||||
timeFilter(scale.x.domain());
|
||||
methods.onUpdateTimerange(scale.x.domain());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -367,7 +325,7 @@ export default function(app, ui) {
|
||||
* @param {String} direction: 'forward' / 'backwards'
|
||||
*/
|
||||
function moveTime(direction) {
|
||||
select();
|
||||
methods.onSelect();
|
||||
const extent = getTimeScaleExtent();
|
||||
const newCentralTime = d3.timeMinute.offset(scale.x.domain()[0], extent / 2);
|
||||
|
||||
@@ -382,7 +340,7 @@ export default function(app, ui) {
|
||||
}
|
||||
|
||||
scale.x.domain([domain0, domainF]);
|
||||
timeFilter(scale.x.domain());
|
||||
methods.onUpdateTimerange(scale.x.domain());
|
||||
}
|
||||
|
||||
function toggleTransition(isTransition) {
|
||||
@@ -479,7 +437,9 @@ export default function(app, ui) {
|
||||
.attr('cx', eventPoint => getEventX(eventPoint))
|
||||
.attr('cy', eventPoint => getEventY(eventPoint))
|
||||
.style('fill', eventPoint => getEventPointFillColor(eventPoint))
|
||||
.on('click', eventPoint => select(getAllEventsAtOnce(eventPoint)))
|
||||
.on('click', eventPoint => {
|
||||
return methods.onSelect(getAllEventsAtOnce(eventPoint))
|
||||
})
|
||||
.on('mouseover', handleMouseOver)
|
||||
.on('mouseout', handleMouseOut)
|
||||
.transition()
|
||||
|
||||
@@ -46,6 +46,41 @@ const initial = {
|
||||
isMobile: (/Mobi/.test(navigator.userAgent)),
|
||||
language: 'en-US',
|
||||
mapAnchor: process.env.MAP_ANCHOR,
|
||||
zoomLevels: [{
|
||||
label: '3 años',
|
||||
duration: 1576800,
|
||||
active: false
|
||||
},
|
||||
{
|
||||
label: '3 meses',
|
||||
duration: 129600,
|
||||
active: false
|
||||
},
|
||||
{
|
||||
label: '3 días',
|
||||
duration: 4320,
|
||||
active: true
|
||||
},
|
||||
{
|
||||
label: '12 horas',
|
||||
duration: 720,
|
||||
active: false
|
||||
},
|
||||
{
|
||||
label: '2 horas',
|
||||
duration: 120,
|
||||
active: false
|
||||
},
|
||||
{
|
||||
label: '30 min',
|
||||
duration: 30,
|
||||
active: false
|
||||
},
|
||||
{
|
||||
label: '10 min',
|
||||
duration: 10,
|
||||
active: false
|
||||
}],
|
||||
features: {
|
||||
USE_TAGS: process.env.features.USE_TAGS,
|
||||
USE_SEARCH: process.env.features.USE_SEARCH
|
||||
|
||||
Reference in New Issue
Block a user