mirror of
https://github.com/bellingcat/ukraine-timemap.git
synced 2026-06-13 05:48:36 +03:00
Make some timeline into presentational comps
This commit is contained in:
@@ -9,10 +9,10 @@ import TimelineHeader from './presentational/TimelineHeader';
|
||||
import TimelineAxis from './TimelineAxis.jsx';
|
||||
import TimelineClip from './presentational/TimelineClip';
|
||||
import TimelineHandles from './presentational/TimelineHandles.js';
|
||||
import TimelineZoomControls from './TimelineZoomControls.jsx';
|
||||
import TimelineZoomControls from './presentational/TimelineZoomControls.js';
|
||||
import TimelineLabels from './presentational/TimelineLabels.js';
|
||||
import TimelineMarkers from './TimelineMarkers.jsx'
|
||||
import TimelineEvents from './TimelineEvents.jsx';
|
||||
import TimelineMarkers from './presentational/TimelineMarkers.js'
|
||||
import TimelineEvents from './presentational/TimelineEvents.js';
|
||||
import TimelineCategories from './TimelineCategories.jsx';
|
||||
|
||||
class Timeline extends React.Component {
|
||||
@@ -30,7 +30,6 @@ class Timeline extends React.Component {
|
||||
margin_top: 20,
|
||||
trackHeight: 80
|
||||
},
|
||||
softTimeUpdate: 0,
|
||||
scaleX: null,
|
||||
scaleY: null,
|
||||
timerange: [null, null],
|
||||
|
||||
@@ -1,41 +0,0 @@
|
||||
import React from 'react';
|
||||
|
||||
class TimelineEvents extends React.Component {
|
||||
|
||||
getAllEventsAtOnce(eventPoint) {
|
||||
const timestamp = eventPoint.timestamp;
|
||||
const category = eventPoint.category;
|
||||
return this.props.events
|
||||
.filter(event => (event.timestamp === timestamp && category === event.category))
|
||||
}
|
||||
|
||||
renderEvent(event) {
|
||||
return (
|
||||
<circle
|
||||
className="event"
|
||||
cx={0}
|
||||
cy={0}
|
||||
style={{
|
||||
'transform': `translate(${this.props.getEventX(event)}px, ${this.props.getEventY(event)}px)`,
|
||||
'transition': `transform ${this.props.transitionDuration / 1000}s ease`
|
||||
}}
|
||||
r={5}
|
||||
fill={this.props.getCategoryColor(event.category)}
|
||||
onClick={() => {this.props.onSelect(this.getAllEventsAtOnce(event))}}
|
||||
>
|
||||
</circle>
|
||||
)
|
||||
}
|
||||
|
||||
render () {
|
||||
return (
|
||||
<g
|
||||
clipPath={"url(#clip)"}
|
||||
>
|
||||
{this.props.events.map(event => this.renderEvent(event))}
|
||||
</g>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default TimelineEvents;
|
||||
@@ -1,33 +0,0 @@
|
||||
import React from 'react';
|
||||
|
||||
class TimelineMarkers extends React.Component {
|
||||
|
||||
renderMarker(event) {
|
||||
return (
|
||||
<circle
|
||||
className="timeline-marker"
|
||||
cx={0}
|
||||
cy={0}
|
||||
style={{
|
||||
'transform': `translate(${this.props.getEventX(event)}px, ${this.props.getEventY(event)}px)`,
|
||||
'transition': `transform ${this.props.transitionDuration / 1000}s ease`,
|
||||
'opacity': 0.9
|
||||
}}
|
||||
r="10"
|
||||
>
|
||||
</circle>
|
||||
)
|
||||
}
|
||||
|
||||
render () {
|
||||
return (
|
||||
<g
|
||||
clipPath={"url(#clip)"}
|
||||
>
|
||||
{this.props.selected.map(event => this.renderMarker(event))}
|
||||
</g>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default TimelineMarkers;
|
||||
@@ -1,29 +0,0 @@
|
||||
import React from 'react';
|
||||
|
||||
class TimelineZoomControls extends React.Component {
|
||||
|
||||
renderZoom(zoom, idx) {
|
||||
return (
|
||||
<text
|
||||
className={`zoom-level-button ${zoom.active ? 'active' : ''}`}
|
||||
x="60"
|
||||
y={(idx * 15) + 20}
|
||||
onClick={() => this.props.onApplyZoom(zoom)}
|
||||
>
|
||||
{zoom.label}
|
||||
</text>
|
||||
)
|
||||
}
|
||||
|
||||
render() {
|
||||
const dims = this.props.dims;
|
||||
|
||||
return (
|
||||
<g transform={`translate(${dims.width - dims.width_controls}, 0)`}>
|
||||
{this.props.zoomLevels.map((z, idx) => this.renderZoom(z, idx))}
|
||||
</g>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default TimelineZoomControls;
|
||||
40
src/components/presentational/TimelineEvents.js
Normal file
40
src/components/presentational/TimelineEvents.js
Normal file
@@ -0,0 +1,40 @@
|
||||
import React from 'react';
|
||||
|
||||
const TimelineEvents = ({ events, getEventX, getEventY,
|
||||
getCategoryColor, onSelect, transitionDuration }) => {
|
||||
|
||||
function getAllEventsAtOnce(eventPoint) {
|
||||
const timestamp = eventPoint.timestamp;
|
||||
const category = eventPoint.category;
|
||||
return events
|
||||
.filter(event => (event.timestamp === timestamp && category === event.category))
|
||||
}
|
||||
|
||||
function renderEvent(event) {
|
||||
return (
|
||||
<circle
|
||||
className="event"
|
||||
cx={0}
|
||||
cy={0}
|
||||
style={{
|
||||
'transform': `translate(${getEventX(event)}px, ${getEventY(event)}px)`,
|
||||
'transition': `transform ${transitionDuration / 1000}s ease`
|
||||
}}
|
||||
r={5}
|
||||
fill={getCategoryColor(event.category)}
|
||||
onClick={() => {onSelect(getAllEventsAtOnce(event))}}
|
||||
>
|
||||
</circle>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<g
|
||||
clipPath={"url(#clip)"}
|
||||
>
|
||||
{events.map(event => renderEvent(event))}
|
||||
</g>
|
||||
);
|
||||
}
|
||||
|
||||
export default TimelineEvents;
|
||||
@@ -6,14 +6,14 @@ const TimelineHandles = ({ dims, onMoveTime }) => {
|
||||
<g className="time-controls-inline">
|
||||
<g
|
||||
transform={`translate(${dims.margin_left + 20}, 62)`}
|
||||
onClick={() => this.props.onMoveTime('backwards')}
|
||||
onClick={() => onMoveTime('backwards')}
|
||||
>
|
||||
<circle r="15"></circle>
|
||||
<path d="M0,-7.847549217020565L6.796176979388489,3.9237746085102825L-6.796176979388489,3.9237746085102825Z" transform="rotate(270)"></path>
|
||||
</g>
|
||||
<g
|
||||
transform={`translate(${dims.width - dims.width_controls - 20}, 62)`}
|
||||
onClick={() => this.props.onMoveTime('forward')}
|
||||
onClick={() => onMoveTime('forward')}
|
||||
>
|
||||
<circle r="15"></circle>
|
||||
<path d="M0,-7.847549217020565L6.796176979388489,3.9237746085102825L-6.796176979388489,3.9237746085102825Z" transform="rotate(90)"></path>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React from 'react';
|
||||
|
||||
import { formatterWithYear } from '../js/utilities';
|
||||
import { formatterWithYear } from '../../js/utilities.js';
|
||||
|
||||
const TimelineLabels = ({ dims, timelabels }) => {
|
||||
|
||||
|
||||
31
src/components/presentational/TimelineMarkers.js
Normal file
31
src/components/presentational/TimelineMarkers.js
Normal file
@@ -0,0 +1,31 @@
|
||||
import React from 'react';
|
||||
|
||||
const TimelineMarkers = ({ getEventX, getEventY, transitionDuration, selected }) => {
|
||||
function renderMarker(event) {
|
||||
return (
|
||||
<circle
|
||||
className="timeline-marker"
|
||||
cx={0}
|
||||
cy={0}
|
||||
style={{
|
||||
'transform': `translate(${getEventX(event)}px, ${getEventY(event)}px)`,
|
||||
'-webkit-transition': `transform ${transitionDuration / 1000}s ease`,
|
||||
'-moz-transition': 'none',
|
||||
'opacity': 0.9
|
||||
}}
|
||||
r="10"
|
||||
>
|
||||
</circle>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<g
|
||||
clipPath={"url(#clip)"}
|
||||
>
|
||||
{selected.map(event => renderMarker(event))}
|
||||
</g>
|
||||
);
|
||||
}
|
||||
|
||||
export default TimelineMarkers;
|
||||
25
src/components/presentational/TimelineZoomControls.js
Normal file
25
src/components/presentational/TimelineZoomControls.js
Normal file
@@ -0,0 +1,25 @@
|
||||
import React from 'react';
|
||||
|
||||
const TimelineZoomControls = ({ zoomLevels, dims, onApplyZoom }) => {
|
||||
|
||||
function renderZoom(zoom, idx) {
|
||||
return (
|
||||
<text
|
||||
className={`zoom-level-button ${zoom.active ? 'active' : ''}`}
|
||||
x="60"
|
||||
y={(idx * 15) + 20}
|
||||
onClick={() => onApplyZoom(zoom)}
|
||||
>
|
||||
{zoom.label}
|
||||
</text>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<g transform={`translate(${dims.width - dims.width_controls}, 0)`}>
|
||||
{zoomLevels.map((z, idx) => renderZoom(z, idx))}
|
||||
</g>
|
||||
);
|
||||
}
|
||||
|
||||
export default TimelineZoomControls;
|
||||
Reference in New Issue
Block a user