mirror of
https://github.com/bellingcat/ukraine-timemap.git
synced 2026-06-11 12:58:35 +03:00
layered projects working; with some bugs
This commit is contained in:
@@ -63,7 +63,6 @@ class Map extends React.Component {
|
||||
}
|
||||
|
||||
initializeMap () {
|
||||
return
|
||||
/**
|
||||
* Creates a Leaflet map and a tilelayer for the map background
|
||||
*/
|
||||
|
||||
@@ -259,8 +259,8 @@ class Timeline extends React.Component {
|
||||
this.props.methods.onUpdateTimerange(this.state.timerange)
|
||||
}
|
||||
|
||||
getDatetimeX (dt) {
|
||||
return this.state.scaleX(parseDate(dt.timestamp))
|
||||
getDatetimeX (timestamp) {
|
||||
return this.state.scaleX(parseDate(timestamp))
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import React from 'react'
|
||||
import DatetimeDot from './DatetimeDot'
|
||||
import DatetimeBar from './DatetimeBar'
|
||||
import Project from './Project'
|
||||
import { getEventOpacity } from '../../../common/utilities'
|
||||
import { sizes } from '../../../common/global'
|
||||
|
||||
@@ -85,7 +86,7 @@ const TimelineEvents = ({
|
||||
onSelect={() => onSelect(unlocatedEvents)}
|
||||
category={dot.category}
|
||||
events={unlocatedEvents}
|
||||
x={getDatetimeX(datetime)}
|
||||
x={getDatetimeX(datetime.timestamp)}
|
||||
y={dims.marginTop}
|
||||
width={sizes.eventDotR}
|
||||
height={dims.trackHeight}
|
||||
@@ -98,7 +99,7 @@ const TimelineEvents = ({
|
||||
onSelect={() => onSelect(unlocatedEvents)}
|
||||
category={dot.category}
|
||||
events={[ev]}
|
||||
x={getDatetimeX(datetime)}
|
||||
x={getDatetimeX(datetime.timestamp)}
|
||||
y={ev.projectOffset >= 0 ? dims.trackHeight - ev.projectOffset : dims.marginTop}
|
||||
width={sizes.eventDotR}
|
||||
height={ev.projectOffset >= 0 ? sizes.eventDotR * 2 : 20}
|
||||
@@ -112,7 +113,7 @@ const TimelineEvents = ({
|
||||
onSelect={() => onSelect(locatedEvents)}
|
||||
category={dot.category}
|
||||
events={locatedEvents}
|
||||
x={getDatetimeX(datetime)}
|
||||
x={getDatetimeX(datetime.timestamp)}
|
||||
y={getCategoryY(dot.category)}
|
||||
r={sizes.eventDotR}
|
||||
styleProps={locatedProps}
|
||||
@@ -125,10 +126,32 @@ const TimelineEvents = ({
|
||||
})
|
||||
}
|
||||
|
||||
// const projOffsets = {}
|
||||
// const pEvents = datetimes.filter(dt => dt.events.some(ev => ev.project !== null))
|
||||
// pEvents.forEach(({ events }) => {
|
||||
// events.forEach(ev => {
|
||||
// if (!projOffsets.hasOwnProperty(ev.project)) {
|
||||
// projOffsets[ev.project] = ev.projectOffset
|
||||
// }
|
||||
// })
|
||||
// })
|
||||
|
||||
let projects
|
||||
if (process.env.features.ASSOCIATIVE_EVENTS_BY_TAG) {
|
||||
projects = datetimes[1]
|
||||
datetimes = datetimes[0]
|
||||
}
|
||||
|
||||
return (
|
||||
<g
|
||||
clipPath={'url(#clip)'}
|
||||
>
|
||||
{projects.map(project => (<Project
|
||||
{...project}
|
||||
getX={getDatetimeX}
|
||||
dims={dims}
|
||||
colour={getCategoryColor(project.category)}
|
||||
/>))}
|
||||
{datetimes.map(datetime => renderDatetime(datetime))}
|
||||
</g>
|
||||
)
|
||||
|
||||
@@ -24,7 +24,7 @@ const TimelineMarkers = ({
|
||||
stroke-linejoin='round'
|
||||
stroke-dasharray={styles ? styles['stroke-dasharray'] : '2,2'}
|
||||
style={{
|
||||
'transform': `translate(${getEventX(event)}px, ${getCategoryY(event.category)}px)`,
|
||||
'transform': `translate(${getEventX(event.timestamp)}px, ${getCategoryY(event.category)}px)`,
|
||||
'-webkit-transition': `transform ${transitionDuration / 1000}s ease`,
|
||||
'-moz-transition': 'none',
|
||||
'opacity': 0.9
|
||||
@@ -43,7 +43,7 @@ const TimelineMarkers = ({
|
||||
stroke-width={styles ? styles['stroke-width'] : 1}
|
||||
stroke-dasharray={styles ? styles['stroke-dasharray'] : '2,2'}
|
||||
style={{
|
||||
'transform': `translate(${getEventX(event)}px, 40px)`,
|
||||
'transform': `translate(${getEventX(event.timestamp)}px, 40px)`,
|
||||
'-webkit-transition': `transform ${transitionDuration / 1000}s ease`,
|
||||
'-moz-transition': 'none',
|
||||
'opacity': 0.9
|
||||
|
||||
23
src/components/presentational/Timeline/Project.js
Normal file
23
src/components/presentational/Timeline/Project.js
Normal file
@@ -0,0 +1,23 @@
|
||||
import React from 'react'
|
||||
import { sizes } from '../../../common/global'
|
||||
|
||||
export default ({
|
||||
id,
|
||||
offset,
|
||||
start,
|
||||
end,
|
||||
getX,
|
||||
dims,
|
||||
colour
|
||||
}) => {
|
||||
const length = getX(end) - getX(start)
|
||||
return <rect
|
||||
onClick={() => alert('TODO: associate all events')}
|
||||
className='project'
|
||||
x={getX(start)}
|
||||
y={dims.trackHeight - offset}
|
||||
width={length}
|
||||
style={{ fill: colour, fillOpacity: 0.1 }}
|
||||
height={2 * sizes.eventDotR}
|
||||
/>
|
||||
}
|
||||
@@ -149,13 +149,16 @@ export const selectLocations = createSelector(
|
||||
events: [...]
|
||||
}
|
||||
*/
|
||||
const IS_PROJ = 'ASSOCIATIVE_EVENTS_BY_TAG' in process.env.features && process.env.features.ASSOCIATIVE_EVENTS_BY_TAG
|
||||
export const selectDatetimes = createSelector(
|
||||
[selectEvents],
|
||||
events => {
|
||||
const projects = {}
|
||||
const datetimes = {}
|
||||
events.forEach(event => {
|
||||
if (process.env.features.ASSOCIATIVE_EVENTS_BY_TAG) {
|
||||
const { timestamp } = event
|
||||
const dtKey = `${timestamp}_1`
|
||||
if (IS_PROJ) {
|
||||
const project = event.tags.length >= 1 ? event.tags[0] : null
|
||||
event = { ...event, project }
|
||||
if (project !== null) {
|
||||
@@ -167,11 +170,16 @@ export const selectDatetimes = createSelector(
|
||||
}
|
||||
}
|
||||
}
|
||||
const { timestamp } = event
|
||||
if (datetimes.hasOwnProperty(timestamp)) {
|
||||
datetimes[timestamp].events.push(event)
|
||||
const tsExists = datetimes.hasOwnProperty(dtKey)
|
||||
const isLocated = !!event.latitude && !!event.longitude
|
||||
if (IS_PROJ && !isLocated && event.project !== null && tsExists) {
|
||||
if (tsExists) {
|
||||
alert('not yet handling cases with multiple... talk to lk@forensic-architecture.org')
|
||||
}
|
||||
} else if (tsExists) {
|
||||
datetimes[dtKey].events.push(event)
|
||||
} else {
|
||||
datetimes[timestamp] = {
|
||||
datetimes[dtKey] = {
|
||||
timestamp: event.timestamp,
|
||||
date: event.date,
|
||||
time: event.time,
|
||||
@@ -179,27 +187,47 @@ export const selectDatetimes = createSelector(
|
||||
}
|
||||
}
|
||||
})
|
||||
// console.log(projects)
|
||||
// console.log(datetimes)
|
||||
const projKeys = Object.keys(projects)
|
||||
function checkActive (pj, dt) {
|
||||
return dt >= projects[pj].start && dt <= projects[pj].end
|
||||
}
|
||||
const output = []
|
||||
let sortedDts = Object.keys(datetimes)
|
||||
sortedDts.sort((a, b) => new Date(a) - new Date(b))
|
||||
sortedDts.sort((a, b) => {
|
||||
const x = a.substring(0, a.length - 2)
|
||||
const y = b.substring(0, b.length - 2)
|
||||
return new Date(x) - new Date(y)
|
||||
})
|
||||
sortedDts.forEach(dt => {
|
||||
const activeProjects = []
|
||||
projKeys.forEach((k, idx) => {
|
||||
if (checkActive(k, dt)) activeProjects.push(k)
|
||||
})
|
||||
datetimes[dt].events = datetimes[dt].events.map(ev => ({
|
||||
...ev,
|
||||
projectOffset: (activeProjects.indexOf(ev.project)) * (2 * sizes.eventDotR + 5)
|
||||
}))
|
||||
output.push({
|
||||
...datetimes[dt],
|
||||
events: datetimes[dt].events.map(ev => {
|
||||
let projectOffset = (activeProjects.indexOf(ev.project) + 1) * (2.5 * sizes.eventDotR)
|
||||
if (ev.project !== null && !projects[ev.project].hasOwnProperty('offset')) {
|
||||
projects[ev.project].offset = projectOffset
|
||||
projects[ev.project].category = ev.category
|
||||
} else if (ev.project !== null) {
|
||||
projectOffset = projects[ev.project].offset
|
||||
}
|
||||
return {
|
||||
...ev,
|
||||
projectOffset
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
// TODO: calculate Y offset based on projects
|
||||
return Object.values(datetimes)
|
||||
const projectsOut = []
|
||||
Object.keys(projects).forEach(projId => {
|
||||
projectsOut.push({ ...projects[projId], id: projId })
|
||||
})
|
||||
if (IS_PROJ) {
|
||||
return [output, projectsOut]
|
||||
}
|
||||
return output
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user