correct timeline selection

This commit is contained in:
Lachlan Kermode
2020-05-29 14:57:09 +02:00
parent 3fc1ff4c28
commit 3b4a3312d5
10 changed files with 104 additions and 70 deletions

View File

@@ -16,7 +16,7 @@ import Notification from './Notification.jsx'
import StaticPage from './StaticPage'
import TemplateCover from './TemplateCover'
import { parseDate } from '../common/utilities'
import { parseDate, binarySearch } from '../common/utilities'
import { isMobile } from 'react-device-detect'
class Dashboard extends React.Component {
@@ -29,8 +29,6 @@ class Dashboard extends React.Component {
this.moveInNarrative = this.moveInNarrative.bind(this)
this.handleSelect = this.handleSelect.bind(this)
this.getCategoryColor = this.getCategoryColor.bind(this)
this.eventsById = {}
}
componentDidMount () {
@@ -49,23 +47,36 @@ class Dashboard extends React.Component {
this.props.actions.updateHighlighted((highlighted) || null)
}
getEventById (eventId) {
if (this.eventsById[eventId]) return this.eventsById[eventId]
this.eventsById[eventId] = this.props.domain.events.find(ev => ev.id === eventId)
return this.eventsById[eventId]
}
handleViewSource (source) {
this.props.actions.updateSource(source)
}
handleSelect (selected) {
if (selected) {
let eventsToSelect = selected.map(event => this.getEventById(event.id))
eventsToSelect = eventsToSelect.sort((a, b) => parseDate(a.timestamp) - parseDate(b.timestamp))
this.props.actions.updateSelected(eventsToSelect)
handleSelect (selected, axis) {
const matchedEvents = [selected]
const TIMELINE_AXIS = 0
if (axis === TIMELINE_AXIS) {
// find in events
const { events } = this.props.domain
const idx = binarySearch(
events,
selected,
(e1, e2) => new Date(e1.timestamp) - new Date(e2.timestamp)
)
// check events before
let ptr = idx - 1
while (events[idx].timestamp === events[ptr].timestamp) {
matchedEvents.push(events[ptr])
ptr -= 1
}
// check events after
ptr = idx + 1
while (events[idx].timestamp === events[ptr].timestamp) {
matchedEvents.push(events[ptr])
ptr += 1
}
}
this.props.actions.updateSelected(matchedEvents)
}
getCategoryColor (category) {

View File

@@ -272,7 +272,7 @@ function mapStateToProps (state) {
},
app: {
views: state.app.filters.views,
selected: state.app.selected,
selected: selectors.selectSelected(state),
highlighted: state.app.highlighted,
map: state.app.map,
narrative: state.app.narrative,

View File

@@ -14,6 +14,7 @@ import ZoomControls from './presentational/Timeline/ZoomControls.js'
import Markers from './presentational/Timeline/Markers.js'
import Events from './presentational/Timeline/Events.js'
import Categories from './TimelineCategories.jsx'
const TIMELINE_AXIS = 0
class Timeline extends React.Component {
constructor (props) {
@@ -336,14 +337,14 @@ class Timeline extends React.Component {
dims={dims}
selected={this.props.app.selected}
getEventX={this.getDatetimeX}
getY={e => this.state.scaleY(e.category)}
getCategoryY={this.state.scaleY}
transitionDuration={this.state.transitionDuration}
styles={this.props.ui.styles}
noCategories={this.props.domain.categories && this.props.domain.categories.length}
features={this.props.features}
/>
<Events
events={this.props.domain.eventsAndProjects[0]}
projects={this.props.domain.eventsAndProjects[1]}
events={this.props.domain.events}
projects={this.props.domain.projects}
styleDatetime={this.styleDatetime}
narrative={this.props.app.narrative}
getDatetimeX={this.getDatetimeX}
@@ -356,7 +357,7 @@ class Timeline extends React.Component {
}}
getCategoryColor={this.props.methods.getCategoryColor}
transitionDuration={this.state.transitionDuration}
onSelect={this.props.methods.onSelect}
onSelect={ev => this.props.methods.onSelect(ev, TIMELINE_AXIS)}
dims={dims}
features={this.props.features}
/>
@@ -373,7 +374,8 @@ function mapStateToProps (state) {
dimensions: selectors.selectDimensions(state),
isNarrative: !!state.app.narrative,
domain: {
eventsAndProjects: selectors.selectEventsAndProjects(state),
events: selectors.selectStackedEvents(state),
projects: selectors.selectProjects(state),
categories: selectors.getCategories(state),
narratives: state.domain.narratives
},

View File

@@ -21,7 +21,7 @@ function renderDot (event, styles, props) {
function renderBar (event, styles, props) {
const fillOpacity = props.features.GRAPH_NONLOCATED
? event.projectOffset >= 0 ? styles.opacity : 0.05
? event.projectOffset >= 0 ? styles.opacity : 0.5
: 0.6
return <DatetimeBar
@@ -80,7 +80,8 @@ const TimelineEvents = ({
}
}
let renderShape = renderDot
const isDot = (!!event.location && !!event.longitude) || (features.GRAPH_NONLOCATED && event.projectOffset !== -1)
let renderShape = isDot ? renderDot : renderBar
if (event.shape) {
if (event.shape === 'bar') {
renderShape = renderBar
@@ -103,7 +104,7 @@ const TimelineEvents = ({
y: (features.GRAPH_NONLOCATED && !event.latitude && !event.longitude)
? event.projectOffset >= 0 ? dims.trackHeight - event.projectOffset : dims.marginTop
: getCategoryY ? getCategoryY(event.category) : () => null,
onSelect: () => onSelect([event]),
onSelect: () => onSelect(event),
dims,
highlights: features.HIGHLIGHT_GROUPS ? getHighlights(event.tags[features.HIGHLIGHT_GROUPS.tagIndexIndicatingGroup]) : [],
features

View File

@@ -4,14 +4,18 @@ import colors, { sizes } from '../../../common/global'
const TimelineMarkers = ({
styles,
getEventX,
getY,
getCategoryY,
transitionDuration,
selected,
dims,
noCategories
features
}) => {
function renderMarker (event) {
function renderCircle () {
const yVal = (features.GRAPH_NONLOCATED && !event.latitude && !event.longitude)
? event.projectOffset >= 0 ? dims.trackHeight - event.projectOffset : dims.marginTop
: getCategoryY ? getCategoryY(event.category) : () => null
return <circle
className='timeline-marker'
cx={0}
@@ -22,7 +26,7 @@ const TimelineMarkers = ({
stroke-linejoin='round'
stroke-dasharray={styles ? styles['stroke-dasharray'] : '2,2'}
style={{
'transform': `translate(${getEventX(event.timestamp)}px, ${getY(event)}px)`,
'transform': `translate(${getEventX(event.timestamp)}px, ${yVal}px)`,
'-webkit-transition': `transform ${transitionDuration / 1000}s ease`,
'-moz-transition': 'none',
'opacity': 0.9
@@ -47,7 +51,7 @@ const TimelineMarkers = ({
}}
/>
}
const isLocated = !!event.latitude && !!event.longitude
const isDot = (!features.GRAPH_NONLOCATED && !!event.latitude && !!event.longitude) || (features.GRAPH_NONLOCATED && (event.projectOffset !== -1 || (!!event.latitude && !!event.longitude)))
switch (event.shape) {
case 'circle':
return renderCircle()
@@ -58,7 +62,7 @@ const TimelineMarkers = ({
case 'star':
return renderCircle()
default:
return isLocated ? renderBar() : renderCircle()
return isDot ? renderCircle() : renderBar()
}
}