WIP: gritty rewrite of timestamp handling

This commit is contained in:
Lachlan Kermode
2020-05-31 13:37:19 +02:00
parent cf354d1173
commit e49b0e2fb0
25 changed files with 174 additions and 156 deletions

View File

@@ -1,11 +1,7 @@
import copy from '../common/data/copy.json'
import {
parseDate,
formatterWithYear
} from '../common/utilities'
import React from 'react'
import CardTimestamp from './presentational/Card/Timestamp'
import CardTime from './presentational/Card/Time'
import CardLocation from './presentational/Card/Location'
import CardCaret from './presentational/Card/Caret'
import CardTags from './presentational/Card/Tags'
@@ -27,11 +23,9 @@ class Card extends React.Component {
})
}
makeTimelabel (timestamp) {
if (timestamp === null) return null
const parsedTimestamp = parseDate(timestamp)
const timelabel = formatterWithYear(parsedTimestamp)
return timelabel
makeTimelabel (datetime) {
if (datetime === null) return null
return datetime.toLocaleDateString()
}
renderSummary () {
@@ -87,8 +81,8 @@ class Card extends React.Component {
}
// NB: should be internaionalized.
renderTimestamp () {
let timelabel = this.makeTimelabel(this.props.event.timestamp)
renderTime() {
let timelabel = this.makeTimelabel(this.props.event.datetime)
let precision = this.props.event.time_display
if (precision === '_date_only') {
@@ -104,7 +98,7 @@ class Card extends React.Component {
}
return (
<CardTimestamp
<CardTime
makeTimelabel={timelabel}
language={this.props.language}
timelabel={timelabel}
@@ -132,7 +126,7 @@ class Card extends React.Component {
return (
<div className='card-container'>
<div className='card-row details'>
{this.renderTimestamp()}
{this.renderTime()}
{this.renderLocation()}
</div>
{this.renderSummary()}

View File

@@ -16,7 +16,7 @@ import Notification from './Notification.jsx'
import StaticPage from './StaticPage'
import TemplateCover from './TemplateCover'
import { parseDate, binarySearch } from '../common/utilities'
import { binarySearch } from '../common/utilities'
import { isMobile } from 'react-device-detect'
class Dashboard extends React.Component {
@@ -61,17 +61,18 @@ class Dashboard extends React.Component {
const idx = binarySearch(
events,
selected,
(e1, e2) => new Date(e1.timestamp) - new Date(e2.timestamp)
(e1, e2) => e1.datetime - e2.datetime
)
// check events before
let ptr = idx - 1
while (events[idx].timestamp === events[ptr].timestamp) {
console.log(events)
while (events[idx].datetime === events[ptr].datetime) {
matchedEvents.push(events[ptr])
ptr -= 1
}
// check events after
ptr = idx + 1
while (events[idx].timestamp === events[ptr].timestamp) {
while (events[idx].datetime === events[ptr].datetime) {
matchedEvents.push(events[ptr])
ptr += 1
}

View File

@@ -5,7 +5,6 @@ import * as selectors from '../selectors'
import hash from 'object-hash'
import copy from '../common/data/copy.json'
import { formatterWithYear, parseDate } from '../common/utilities'
import Header from './presentational/Timeline/Header'
import Axis from './TimelineAxis.jsx'
import Clip from './presentational/Timeline/Clip'
@@ -28,14 +27,13 @@ class Timeline extends React.Component {
dims: props.dimensions,
scaleX: null,
scaleY: null,
timerange: [null, null],
timerange: [null, null], // two datetimes
dragPos0: null,
transitionDuration: 300
}
}
componentDidMount () {
this.computeDims()
this.addEventListeners()
}
@@ -60,7 +58,7 @@ class Timeline extends React.Component {
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))
this.onCenterTime(nextProps.app.selected[0].datetime)
}
}
}
@@ -68,9 +66,10 @@ class Timeline extends React.Component {
addEventListeners () {
window.addEventListener('resize', () => { this.computeDims() })
let element = document.querySelector('.timeline-wrapper')
element.addEventListener('transitionend', (event) => {
this.computeDims()
})
if (element !== null)
element.addEventListener('transitionend', (event) => {
this.computeDims()
})
}
makeScaleX () {
@@ -191,8 +190,8 @@ class Timeline extends React.Component {
if (rangeLimits) {
// If the store contains absolute time limits,
// make sure the zoom doesn't go over them
const minDate = parseDate(rangeLimits[0])
const maxDate = parseDate(rangeLimits[1])
const minDate = rangeLimits[0]
const maxDate = rangeLimits[1]
if (newDomain0 < minDate) {
newDomain0 = minDate
@@ -243,8 +242,8 @@ class Timeline extends React.Component {
if (rangeLimits) {
// If the store contains absolute time limits,
// make sure the zoom doesn't go over them
const minDate = parseDate(rangeLimits[0])
const maxDate = parseDate(rangeLimits[1])
const minDate = rangeLimits[0]
const maxDate = rangeLimits[1]
newDomain0 = (newDomain0 < minDate) ? minDate : newDomain0
newDomainF = (newDomainF > maxDate) ? maxDate : newDomainF
@@ -262,8 +261,8 @@ class Timeline extends React.Component {
this.props.methods.onUpdateTimerange(this.state.timerange)
}
getDatetimeX (timestamp) {
return this.state.scaleX(parseDate(timestamp))
getDatetimeX (datetime) {
return this.state.scaleX(datetime)
}
/**
@@ -294,8 +293,8 @@ class Timeline extends React.Component {
<div className={classes} style={extraStyle}>
<Header
title={copy[this.props.app.language].timeline.info}
date0={formatterWithYear(this.state.timerange[0])}
date1={formatterWithYear(this.state.timerange[1])}
from={this.state.timerange[0]}
to={this.state.timerange[1]}
onClick={() => { this.onClickArrow() }}
hideInfo={isNarrative}
/>

View File

@@ -1,12 +1,12 @@
import React from 'react'
import { capitalizeFirstLetter } from '../../../common/utilities.js'
import { capitalize } from '../../../common/utilities.js'
const CardCategory = ({ categoryTitle, categoryLabel, color }) => (
<div className='card-row card-cell category'>
<h4>{categoryTitle}</h4>
<p>
{capitalizeFirstLetter(categoryLabel)}
{capitalize(categoryLabel)}
<span className='color-category' style={{ background: color }} />
</p>
</div>

View File

@@ -3,7 +3,7 @@ import React from 'react'
import copy from '../../../common/data/copy.json'
import { isNotNullNorUndefined } from '../../../common/utilities'
const CardTimestamp = ({ timelabel, language, precision }) => {
const CardTime = ({ timelabel, language, precision }) => {
// const daytimeLang = copy[language].cardstack.timestamp
// const estimatedLang = copy[language].cardstack.estimated
const unknownLang = copy[language].cardstack.unknown_time
@@ -29,4 +29,4 @@ const CardTimestamp = ({ timelabel, language, precision }) => {
}
}
export default CardTimestamp
export default CardTime

View File

@@ -92,19 +92,26 @@ const TimelineEvents = ({
}
}
let defaultY = getCategoryY(event.category)
let eventY = getCategoryY(event.category)
const isNonlocated = !event.latitude && !event.longitude
if (features.GRAPH_NONLOCATED && isNonlocated) {
const { project } = event
if (project) {
const { offset } = projects[project]
eventY = dims.marginTop + offset + sizes.eventDotR
}
}
let colour = event.colour ? event.colour : getCategoryColor(event.category)
const styles = {
fill: colour,
fillOpacity: defaultY > 0 ? calcOpacity(1) : 0,
fillOpacity: eventY > 0 ? calcOpacity(1) : 0,
transition: `transform ${transitionDuration / 1000}s ease`
}
return renderShape(event, styles, {
x: getDatetimeX(event.timestamp),
y: (features.GRAPH_NONLOCATED && !event.latitude && !event.longitude)
? event.projectOffset >= 0 ? dims.trackHeight - event.projectOffset : dims.marginTop
: getCategoryY ? defaultY : () => null,
x: getDatetimeX(event.datetime),
y: eventY,
onSelect: () => onSelect(event),
dims,
highlights: features.HIGHLIGHT_GROUPS ? getHighlights(event.tags[features.HIGHLIGHT_GROUPS.tagIndexIndicatingGroup]) : [],
@@ -113,11 +120,12 @@ const TimelineEvents = ({
}
/* set `renderProjects` */
// TODO(lachlan): remove hardcoded 'Legislation'
let renderProjects = () => null
if (features.GRAPH_NONLOCATED) {
renderProjects = function () {
return <React.Fragment>
{projects.map(project => <Project
{Object.values(projects).map(project => <Project
{...project}
onClick={() => console.log(project)}
getX={getDatetimeX}

View File

@@ -1,15 +1,19 @@
import React from 'react'
const TimelineHeader = ({ title, date0, date1, onClick, hideInfo }) => (
<div className='timeline-header'>
<div className='timeline-toggle' onClick={() => onClick()}>
<p><i className='arrow-down' /></p>
const TimelineHeader = ({ title, from, to, onClick, hideInfo }) => {
const d0 = from && from.toLocaleDateString()
const d1 = to && to.toLocaleDateString()
return (
<div className='timeline-header'>
<div className='timeline-toggle' onClick={() => onClick()}>
<p><i className='arrow-down' /></p>
</div>
<div className={`timeline-info ${hideInfo ? 'hidden' : ''}`}>
<p>{title}</p>
<p>{d0} - {d1}</p>
</div>
</div>
<div className={`timeline-info ${hideInfo ? 'hidden' : ''}`}>
<p>{title}</p>
<p>{date0} - {date1}</p>
</div>
</div>
)
)
}
export default TimelineHeader

View File

@@ -1,7 +1,5 @@
import React from 'react'
import { formatterWithYear } from '../../../js/utilities.js'
const TimelineLabels = ({ dims, timelabels }) => {
return (
<g>
@@ -24,7 +22,7 @@ const TimelineLabels = ({ dims, timelabels }) => {
x='5'
y='15'
>
{formatterWithYear(timelabels[0])}
{timelabels[0]}
</text>
<text
class='timelabelF timeLabel'
@@ -32,7 +30,7 @@ const TimelineLabels = ({ dims, timelabels }) => {
y='15'
style={{ textAnchor: 'end' }}
>
{formatterWithYear(timelabels[1])}
{timelabels[1]}
</text>
</g>
)

View File

@@ -2,21 +2,23 @@ import React from 'react'
import { sizes } from '../../../common/global'
export default ({
id,
offset,
id,
start,
end,
getX,
y,
dims,
colour,
onClick
}) => {
const length = getX(end) - getX(start)
if (offset === undefined) return null
return <rect
onClick={onClick}
className='project'
x={getX(start)}
y={dims.trackHeight - (offset + sizes.eventDotR)}
y={dims.marginTop + 100}
width={length}
style={{ fill: colour, fillOpacity: 0.2 }}
height={2 * sizes.eventDotR}