From ffb4548fce4466270de8a65e4959aa178cac9a0b Mon Sep 17 00:00:00 2001 From: Lachlan Kermode Date: Fri, 20 Mar 2020 15:45:09 +0100 Subject: [PATCH] update dimensions of track according to number of categories --- src/actions/index.js | 8 ++++++ src/common/global.js | 7 ++++- src/components/Layout.js | 8 ++++++ src/components/Timeline.jsx | 26 +++++++++++++------ src/components/TimelineCategories.jsx | 11 +++++--- .../presentational/Timeline/Events.js | 6 ++--- .../presentational/Timeline/Markers.js | 19 +++++++------- src/reducers/app.js | 16 ++++++++++++ src/store/initial.js | 4 +-- 9 files changed, 78 insertions(+), 27 deletions(-) diff --git a/src/actions/index.js b/src/actions/index.js index ba528b7..b2734d9 100644 --- a/src/actions/index.js +++ b/src/actions/index.js @@ -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 { diff --git a/src/common/global.js b/src/common/global.js index e6da865..b47c13f 100644 --- a/src/common/global.js +++ b/src/common/global.js @@ -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 } diff --git a/src/components/Layout.js b/src/components/Layout.js index 416688e..0e45406 100644 --- a/src/components/Layout.js +++ b/src/components/Layout.js @@ -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 }) + } + }) } } diff --git a/src/components/Timeline.jsx b/src/components/Timeline.jsx index a6b3b9a..51627a1 100644 --- a/src/components/Timeline.jsx +++ b/src/components/Timeline.jsx @@ -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} /> - + @@ -41,7 +46,7 @@ class TimelineCategories extends React.Component { } render () { - const dims = this.props.dims + const { dims } = this.props return ( @@ -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} /> diff --git a/src/components/presentational/Timeline/Events.js b/src/components/presentational/Timeline/Events.js index ce56c3b..1bd747d 100644 --- a/src/components/presentational/Timeline/Events.js +++ b/src/components/presentational/Timeline/Events.js @@ -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 ( @@ -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} />} diff --git a/src/components/presentational/Timeline/Markers.js b/src/components/presentational/Timeline/Markers.js index d3a0932..11a5a8b 100644 --- a/src/components/presentational/Timeline/Markers.js +++ b/src/components/presentational/Timeline/Markers.js @@ -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} /> ) : ( 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' /> ) diff --git a/src/reducers/app.js b/src/reducers/app.js index 5d0f086..ee416f4 100644 --- a/src/reducers/app.js +++ b/src/reducers/app.js @@ -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: diff --git a/src/store/initial.js b/src/store/initial.js index a0690b8..7f98bb5 100644 --- a/src/store/initial.js +++ b/src/store/initial.js @@ -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),