mirror of
https://github.com/bellingcat/ukraine-timemap.git
synced 2026-06-12 13:28:36 +03:00
Merging in develop branch
This commit is contained in:
@@ -78,7 +78,7 @@ class Timeline extends React.Component {
|
||||
makeScaleY (categories, trackHeight, marginTop) {
|
||||
const { features } = this.props
|
||||
if (features.GRAPH_NONLOCATED && features.GRAPH_NONLOCATED.categories) {
|
||||
categories = categories.filter(cat => !features.GRAPH_NONLOCATED.categories.includes(cat.category))
|
||||
categories = categories.filter(cat => !features.GRAPH_NONLOCATED.categories.includes(cat.id))
|
||||
}
|
||||
const catHeight = trackHeight / (categories.length)
|
||||
const shiftUp = trackHeight / (categories.length) / 2
|
||||
@@ -87,7 +87,8 @@ class Timeline extends React.Component {
|
||||
const catsYpos = categories.map((g, i) => {
|
||||
return ((i + 1) * catHeight) - shiftUp + marginShift + manualAdjustment
|
||||
})
|
||||
const catMap = categories.map(c => c.category)
|
||||
const catMap = categories.map(c => c.id)
|
||||
|
||||
return (cat) => {
|
||||
const idx = catMap.indexOf(cat)
|
||||
return catsYpos[idx]
|
||||
@@ -268,11 +269,16 @@ class Timeline extends React.Component {
|
||||
|
||||
getY (event) {
|
||||
const { features, domain } = this.props
|
||||
const { USE_CATEGORIES, GRAPH_NONLOCATED } = features
|
||||
const { categories } = domain
|
||||
|
||||
if (!USE_CATEGORIES) { return this.state.dims.trackHeight / 2 }
|
||||
const categoriesExist = categories && categories.length > 0
|
||||
|
||||
const { GRAPH_NONLOCATED } = features
|
||||
|
||||
if (!categoriesExist) { return this.state.dims.trackHeight / 2 }
|
||||
|
||||
const { category, project } = event
|
||||
|
||||
if (GRAPH_NONLOCATED && GRAPH_NONLOCATED.categories.includes(category)) {
|
||||
return this.state.dims.marginTop + domain.projects[project].offset + this.props.ui.eventRadius
|
||||
}
|
||||
@@ -335,7 +341,7 @@ class Timeline extends React.Component {
|
||||
onDragStart={() => { this.onDragStart() }}
|
||||
onDrag={() => { this.onDrag() }}
|
||||
onDragEnd={() => { this.onDragEnd() }}
|
||||
categories={this.props.domain.categories}
|
||||
categories={this.props.app.activeCategories}
|
||||
features={this.props.features}
|
||||
/>
|
||||
<Handles
|
||||
@@ -361,6 +367,7 @@ class Timeline extends React.Component {
|
||||
<Events
|
||||
events={this.props.domain.events}
|
||||
projects={this.props.domain.projects}
|
||||
categories={this.props.domain.categories}
|
||||
styleDatetime={this.styleDatetime}
|
||||
narrative={this.props.app.narrative}
|
||||
getDatetimeX={this.getDatetimeX}
|
||||
@@ -399,6 +406,7 @@ function mapStateToProps (state) {
|
||||
narratives: state.domain.narratives
|
||||
},
|
||||
app: {
|
||||
activeCategories: selectors.getActiveCategories(state),
|
||||
selected: state.app.selected,
|
||||
language: state.app.language,
|
||||
timeline: state.app.timeline,
|
||||
|
||||
@@ -26,11 +26,10 @@ class TimelineCategories extends React.Component {
|
||||
|
||||
renderCategory (cat, idx) {
|
||||
const { features, dims } = this.props
|
||||
const { category } = cat
|
||||
const strokeWidth = 1 // dims.trackHeight / (this.props.categories.length + 1)
|
||||
if (features.GRAPH_NONLOCATED &&
|
||||
features.GRAPH_NONLOCATED.categories &&
|
||||
features.GRAPH_NONLOCATED.categories.includes(category)) {
|
||||
features.GRAPH_NONLOCATED.categories.includes(cat)) {
|
||||
return null
|
||||
}
|
||||
|
||||
@@ -40,26 +39,27 @@ class TimelineCategories extends React.Component {
|
||||
class='tick'
|
||||
style={{ strokeWidth }}
|
||||
opacity='0.5'
|
||||
transform={`translate(0,${this.props.getCategoryY(category)})`}
|
||||
transform={`translate(0,${this.props.getCategoryY(cat)})`}
|
||||
>
|
||||
<line x1={dims.marginLeft} x2={dims.width - dims.width_controls} />
|
||||
</g>
|
||||
<g class='tick' opacity='1' transform={`translate(0,${this.props.getCategoryY(category)})`}>
|
||||
<text x={dims.marginLeft - 5} dy='0.32em'>{category}</text>
|
||||
<g class='tick' opacity='1' transform={`translate(0,${this.props.getCategoryY(cat)})`}>
|
||||
<text x={dims.marginLeft - 5} dy='0.32em'>{cat}</text>
|
||||
</g>
|
||||
</React.Fragment>
|
||||
)
|
||||
}
|
||||
|
||||
render () {
|
||||
const { dims } = this.props
|
||||
const categories = this.props.features.USE_CATEGORIES
|
||||
const { dims, categories } = this.props
|
||||
const categoriesExist = categories && categories.length > 0
|
||||
const renderedCategories = categoriesExist
|
||||
? this.props.categories.map((cat, idx) => this.renderCategory(cat, idx))
|
||||
: this.renderCategory('Events', 0)
|
||||
|
||||
return (
|
||||
<g class='yAxis'>
|
||||
{categories}
|
||||
{renderedCategories}
|
||||
<rect
|
||||
ref={this.grabRef}
|
||||
class='drag-grabber'
|
||||
|
||||
@@ -13,14 +13,14 @@ export default ({
|
||||
<div>
|
||||
{categories.map(cat => {
|
||||
return (<li
|
||||
key={cat.category.replace(/ /g, '_')}
|
||||
key={cat.id.replace(/ /g, '_')}
|
||||
className={'filter-filter active'}
|
||||
style={{ marginLeft: '20px' }}
|
||||
>
|
||||
<Checkbox
|
||||
label={cat.category}
|
||||
isActive={activeCategories.includes(cat.category)}
|
||||
onClickCheckbox={() => onCategoryFilter(cat.category)}
|
||||
label={cat.id}
|
||||
isActive={activeCategories.includes(cat.id)}
|
||||
onClickCheckbox={() => onCategoryFilter(cat.id)}
|
||||
/>
|
||||
</li>)
|
||||
})}
|
||||
|
||||
@@ -4,7 +4,7 @@ import DatetimeBar from './DatetimeBar'
|
||||
import DatetimeSquare from './DatetimeSquare'
|
||||
import DatetimeStar from './DatetimeStar'
|
||||
import Project from './Project'
|
||||
import { calcOpacity } from '../../../common/utilities'
|
||||
import { calcOpacity, getEventCategories } from '../../../common/utilities'
|
||||
|
||||
function renderDot (event, styles, props) {
|
||||
return <DatetimeDot
|
||||
@@ -60,6 +60,7 @@ function renderStar (event, styles, props) {
|
||||
const TimelineEvents = ({
|
||||
events,
|
||||
projects,
|
||||
categories,
|
||||
narrative,
|
||||
getDatetimeX,
|
||||
getY,
|
||||
@@ -75,14 +76,14 @@ const TimelineEvents = ({
|
||||
}) => {
|
||||
const narIds = narrative ? narrative.steps.map(s => s.id) : []
|
||||
|
||||
function renderEvent (event) {
|
||||
function renderEvent (aggregated, event) {
|
||||
if (narrative) {
|
||||
if (!(narIds.includes(event.id))) {
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
const isDot = (!!event.location && !!event.longitude) || (features.GRAPH_NONLOCATED && event.projectOffset !== -1)
|
||||
|
||||
let renderShape = isDot ? renderDot : renderBar
|
||||
if (event.shape) {
|
||||
if (event.shape === 'bar') {
|
||||
@@ -96,23 +97,33 @@ const TimelineEvents = ({
|
||||
}
|
||||
}
|
||||
|
||||
const eventY = getY(event)
|
||||
let colour = event.colour ? event.colour : getCategoryColor(event.category)
|
||||
const styles = {
|
||||
fill: colour,
|
||||
fillOpacity: eventY > 0 ? calcOpacity(1) : 0,
|
||||
transition: `transform ${transitionDuration / 1000}s ease`
|
||||
}
|
||||
const relatedCategories = getEventCategories(event, categories)
|
||||
|
||||
return renderShape(event, styles, {
|
||||
x: getDatetimeX(event.datetime),
|
||||
y: eventY,
|
||||
eventRadius,
|
||||
onSelect: () => onSelect(event),
|
||||
dims,
|
||||
highlights: features.HIGHLIGHT_GROUPS ? getHighlights(event.associations[features.HIGHLIGHT_GROUPS.filterIndexIndicatingGroup]) : [],
|
||||
features
|
||||
})
|
||||
if (relatedCategories && relatedCategories.length > 0) {
|
||||
relatedCategories.forEach(cat => {
|
||||
const eventY = getY({ ...event, category: cat.id })
|
||||
|
||||
let colour = event.colour ? event.colour : getCategoryColor(cat.id)
|
||||
const styles = {
|
||||
fill: colour,
|
||||
fillOpacity: eventY > 0 ? calcOpacity(1) : 0,
|
||||
transition: `transform ${transitionDuration / 1000}s ease`
|
||||
}
|
||||
|
||||
aggregated.push(
|
||||
renderShape(event, styles, {
|
||||
x: getDatetimeX(event.datetime),
|
||||
y: eventY,
|
||||
eventRadius,
|
||||
onSelect: () => onSelect(event),
|
||||
dims,
|
||||
highlights: features.HIGHLIGHT_GROUPS ? getHighlights(event.filters[features.HIGHLIGHT_GROUPS.filterIndexIndicatingGroup]) : [],
|
||||
features
|
||||
})
|
||||
)
|
||||
})
|
||||
}
|
||||
return aggregated
|
||||
}
|
||||
|
||||
let renderProjects = () => null
|
||||
@@ -136,7 +147,7 @@ const TimelineEvents = ({
|
||||
clipPath={'url(#clip)'}
|
||||
>
|
||||
{renderProjects()}
|
||||
{events.map(event => renderEvent(event))}
|
||||
{events.reduce(renderEvent, [])}
|
||||
</g>
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user