mirror of
https://github.com/bellingcat/ukraine-timemap.git
synced 2026-06-12 13:28:36 +03:00
update dimensions of track according to number of categories
This commit is contained in:
@@ -196,6 +196,14 @@ export function updateTimeRange (timerange) {
|
||||
}
|
||||
}
|
||||
|
||||
export const UPDATE_DIMENSIONS = 'UPDATE_DIMENSIONS'
|
||||
export function updateDimensions (dims) {
|
||||
return {
|
||||
type: UPDATE_DIMENSIONS,
|
||||
dims
|
||||
}
|
||||
}
|
||||
|
||||
export const UPDATE_NARRATIVE = 'UPDATE_NARRATIVE'
|
||||
export function updateNarrative (narrative) {
|
||||
return {
|
||||
|
||||
@@ -5,8 +5,13 @@ export const colors = {
|
||||
white: '#fff'
|
||||
}
|
||||
|
||||
export const sizes = {
|
||||
eventDotR: 5
|
||||
}
|
||||
|
||||
export default {
|
||||
darkBackground: colors.black,
|
||||
primaryHighlight: colors.yellow,
|
||||
secondaryHighlight: colors.white
|
||||
secondaryHighlight: colors.white,
|
||||
sizes
|
||||
}
|
||||
|
||||
@@ -37,6 +37,14 @@ class Dashboard extends React.Component {
|
||||
if (!this.props.app.isMobile) {
|
||||
this.props.actions.fetchDomain()
|
||||
.then(domain => this.props.actions.updateDomain(domain))
|
||||
.then(({ domain }) => {
|
||||
// modify trackHeight according to number of categories
|
||||
if (domain.categories.length === 1) {
|
||||
this.props.actions.updateDimensions({ trackHeight: 30 })
|
||||
} else if (domain.categories.length >= 4) {
|
||||
this.props.actions.updateDimensions({ margin_top: 0, trackHeight: 90 })
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ import * as selectors from '../selectors'
|
||||
import hash from 'object-hash'
|
||||
|
||||
import copy from '../common/data/copy.json'
|
||||
import { sizes } from '../common/global'
|
||||
import { formatterWithYear, parseDate } from '../common/utilities'
|
||||
import Header from './presentational/Timeline/Header'
|
||||
import Axis from './TimelineAxis.jsx'
|
||||
@@ -46,12 +47,17 @@ class Timeline extends React.Component {
|
||||
})
|
||||
}
|
||||
|
||||
if (hash(nextProps.domain.categories) !== hash(this.props.domain.categories)) {
|
||||
if ((hash(nextProps.domain.categories) !== hash(this.props.domain.categories)) || hash(nextProps.app.timeline.dimensions) != hash(this.props.app.timeline.dimensions)) {
|
||||
const { trackHeight, margin_top } = nextProps.app.timeline.dimensions
|
||||
this.setState({
|
||||
scaleY: this.makeScaleY(nextProps.domain.categories)
|
||||
scaleY: this.makeScaleY(nextProps.domain.categoriesWithTimeline, trackHeight, margin_top )
|
||||
})
|
||||
}
|
||||
|
||||
if (nextProps.app.timeline.dimensions.trackHeight !== this.props.app.timeline.dimensions.trackHeight) {
|
||||
this.computeDims()
|
||||
}
|
||||
|
||||
if (hash(nextProps.app.selected) !== hash(this.props.app.selected)) {
|
||||
if (!!nextProps.app.selected && nextProps.app.selected.length > 0) {
|
||||
this.onCenterTime(parseDate(nextProps.app.selected[0].timestamp))
|
||||
@@ -73,9 +79,13 @@ class Timeline extends React.Component {
|
||||
.range([this.state.dims.margin_left, this.state.dims.width - this.state.dims.width_controls])
|
||||
}
|
||||
|
||||
makeScaleY (categories) {
|
||||
const tickHeight = 15
|
||||
const catsYpos = categories.map((g, i) => (i + 1) * this.state.dims.trackHeight / categories.length + tickHeight / 2)
|
||||
makeScaleY (categories, trackHeight, marginTop) {
|
||||
const tickHeight = sizes.eventDotR * 2
|
||||
const catHeight = trackHeight / (categories.length)
|
||||
const shiftUp = trackHeight / (categories.length + 1) / 2
|
||||
const marginShift = marginTop === 0 ? 0 : marginTop
|
||||
const manualAdjustment = trackHeight <= 60 ? (trackHeight <= 30 ? -8 : -5) : 0
|
||||
const catsYpos = categories.map((g, i) => ((i + 1) * catHeight) - shiftUp + marginShift + manualAdjustment)
|
||||
return d3.scaleOrdinal()
|
||||
.domain(categories)
|
||||
.range(catsYpos)
|
||||
@@ -109,13 +119,12 @@ class Timeline extends React.Component {
|
||||
|
||||
this.setState({
|
||||
dims: {
|
||||
...this.state.dims,
|
||||
...this.props.app.timeline.dimensions,
|
||||
width: boundingClient.width
|
||||
}
|
||||
},
|
||||
() => {
|
||||
this.setState({ scaleX: this.makeScaleX()
|
||||
})
|
||||
this.setState({ scaleX: this.makeScaleX() })
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -322,6 +331,7 @@ class Timeline extends React.Component {
|
||||
getCategoryY={this.state.scaleY}
|
||||
transitionDuration={this.state.transitionDuration}
|
||||
styles={this.props.ui.styles}
|
||||
noCategories={this.props.domain.categories && this.props.domain.categories.length}
|
||||
/>
|
||||
<Events
|
||||
datetimes={this.props.domain.datetimes}
|
||||
|
||||
@@ -30,7 +30,12 @@ class TimelineCategories extends React.Component {
|
||||
|
||||
return (
|
||||
<React.Fragment>
|
||||
<g class='tick' style={{strokeWidth}} opacity='0.5' transform={`translate(0,${this.props.getCategoryY(category.category)})`}>
|
||||
<g
|
||||
class='tick'
|
||||
style={{strokeWidth}}
|
||||
opacity='0.5'
|
||||
transform={`translate(0,${this.props.getCategoryY(category.category)})`}
|
||||
>
|
||||
<line x1={dims.margin_left} x2={dims.width - dims.width_controls} />
|
||||
</g>
|
||||
<g class='tick' opacity='1' transform={`translate(0,${this.props.getCategoryY(category.category)})`}>
|
||||
@@ -41,7 +46,7 @@ class TimelineCategories extends React.Component {
|
||||
}
|
||||
|
||||
render () {
|
||||
const dims = this.props.dims
|
||||
const { dims } = this.props
|
||||
|
||||
return (
|
||||
<g class='yAxis'>
|
||||
@@ -50,7 +55,7 @@ class TimelineCategories extends React.Component {
|
||||
ref={this.grabRef}
|
||||
class='drag-grabber'
|
||||
x={dims.margin_left}
|
||||
y='20'
|
||||
y={dims.margin_top}
|
||||
width={dims.width - dims.margin_left - dims.width_controls}
|
||||
height={dims.trackHeight}
|
||||
/>
|
||||
|
||||
@@ -2,6 +2,7 @@ import React from 'react'
|
||||
import DatetimeDot from './DatetimeDot'
|
||||
import DatetimeBar from './DatetimeBar'
|
||||
import { getEventOpacity } from '../../../common/utilities'
|
||||
import { sizes } from '../../../common/global'
|
||||
|
||||
// return a list of lists, where each list corresponds to a single category
|
||||
function getDotsToRender (events) {
|
||||
@@ -79,7 +80,6 @@ const TimelineEvents = ({
|
||||
}
|
||||
|
||||
const extraRender = customStyles[1]
|
||||
const eventWidth = 5
|
||||
|
||||
return (
|
||||
<g className='datetime'>
|
||||
@@ -89,7 +89,7 @@ const TimelineEvents = ({
|
||||
events={locatedEvents}
|
||||
x={getDatetimeX(datetime)}
|
||||
y={getCategoryY(dot.category)}
|
||||
r={eventWidth}
|
||||
r={sizes.eventDotR}
|
||||
styleProps={locatedProps}
|
||||
extraRender={extraRender}
|
||||
/>}
|
||||
@@ -99,7 +99,7 @@ const TimelineEvents = ({
|
||||
events={unlocatedEvents}
|
||||
x={getDatetimeX(datetime)}
|
||||
y={dims.margin_top}
|
||||
width={eventWidth}
|
||||
width={(2 * sizes.eventDotR) * 0.9}
|
||||
height={dims.trackHeight}
|
||||
styleProps={unlocatedProps}
|
||||
/>}
|
||||
|
||||
@@ -1,13 +1,15 @@
|
||||
import React from 'react'
|
||||
import colors from '../../../common/global.js'
|
||||
import colors, { sizes } from '../../../common/global'
|
||||
|
||||
const MARKER_DISPLACED = sizes.eventDotR * 2
|
||||
const TimelineMarkers = ({
|
||||
styles,
|
||||
getEventX,
|
||||
getCategoryY,
|
||||
transitionDuration,
|
||||
selected,
|
||||
dims
|
||||
dims,
|
||||
noCategories
|
||||
}) => {
|
||||
function renderMarker (event) {
|
||||
const isLocated = !!event.latitude && !!event.longitude
|
||||
@@ -18,8 +20,7 @@ const TimelineMarkers = ({
|
||||
cy={0}
|
||||
stroke={styles ? styles.stroke : colors.primaryHighlight}
|
||||
stroke-opacity='1'
|
||||
stroke-width={styles ? styles['stroke-width'] : 2}
|
||||
stroke-linecap=''
|
||||
stroke-width={styles ? styles['stroke-width'] : 1}
|
||||
stroke-linejoin='round'
|
||||
stroke-dasharray={styles ? styles['stroke-dasharray'] : '2,2'}
|
||||
style={{
|
||||
@@ -28,19 +29,18 @@ const TimelineMarkers = ({
|
||||
'-moz-transition': 'none',
|
||||
'opacity': 0.9
|
||||
}}
|
||||
r='10'
|
||||
r={sizes.eventDotR * 2}
|
||||
/>
|
||||
) : (
|
||||
<rect
|
||||
className='timeline-marker'
|
||||
x={0}
|
||||
y={-dims.margin_top}
|
||||
width={4}
|
||||
y={-dims.margin_top - (noCategories > 2 ? noCategories * MARKER_DISPLACED : MARKER_DISPLACED)}
|
||||
width={(2 * sizes.eventDotR) * 0.9}
|
||||
height={dims.trackHeight}
|
||||
stroke={styles ? styles.stroke : colors.primaryHighlight}
|
||||
stroke-opacity='1'
|
||||
stroke-width={styles ? styles['stroke-width'] : 2}
|
||||
stroke-linecap=''
|
||||
stroke-width={styles ? styles['stroke-width'] : 1}
|
||||
stroke-dasharray={styles ? styles['stroke-dasharray'] : '2,2'}
|
||||
style={{
|
||||
'transform': `translate(${getEventX(event)}px, 40px)`,
|
||||
@@ -48,7 +48,6 @@ const TimelineMarkers = ({
|
||||
'-moz-transition': 'none',
|
||||
'opacity': 0.9
|
||||
}}
|
||||
r='10'
|
||||
/>
|
||||
|
||||
)
|
||||
|
||||
@@ -7,6 +7,7 @@ import {
|
||||
CLEAR_FILTER,
|
||||
TOGGLE_FILTER,
|
||||
UPDATE_TIMERANGE,
|
||||
UPDATE_DIMENSIONS,
|
||||
UPDATE_NARRATIVE,
|
||||
INCREMENT_NARRATIVE_CURRENT,
|
||||
DECREMENT_NARRATIVE_CURRENT,
|
||||
@@ -152,6 +153,19 @@ function updateTimeRange (appState, action) { // XXX
|
||||
}
|
||||
}
|
||||
|
||||
function updateDimensions (appState, action) {
|
||||
return {
|
||||
...appState,
|
||||
timeline: {
|
||||
...appState.timeline,
|
||||
dimensions: {
|
||||
...appState.timeline.dimensions,
|
||||
...action.dims
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function toggleLanguage (appState, action) {
|
||||
let otherLanguage = (appState.language === 'es-MX') ? 'en-US' : 'es-MX'
|
||||
return Object.assign({}, appState, {
|
||||
@@ -203,6 +217,8 @@ function app (appState = initial.app, action) {
|
||||
return toggleFilter(appState, action)
|
||||
case UPDATE_TIMERANGE:
|
||||
return updateTimeRange(appState, action)
|
||||
case UPDATE_DIMENSIONS:
|
||||
return updateDimensions(appState, action)
|
||||
case UPDATE_NARRATIVE:
|
||||
return updateNarrative(appState, action)
|
||||
case INCREMENT_NARRATIVE_CURRENT:
|
||||
|
||||
@@ -65,8 +65,8 @@ const initial = {
|
||||
width_controls: 100,
|
||||
height_controls: 115,
|
||||
margin_left: 100,
|
||||
margin_top: 20,
|
||||
trackHeight: 80
|
||||
margin_top: 15,
|
||||
trackHeight: 60
|
||||
},
|
||||
range: [
|
||||
new Date(2001, 2, 23, 12),
|
||||
|
||||
Reference in New Issue
Block a user