mirror of
https://github.com/bellingcat/ukraine-timemap.git
synced 2026-06-12 13:28:36 +03:00
Pass narratives with links down to cards and events
This commit is contained in:
@@ -137,14 +137,19 @@ class Card extends React.Component {
|
||||
</div>);
|
||||
}
|
||||
|
||||
getTimeLabel(){
|
||||
const timestamp = this.props.tools.parser(this.props.event.timestamp);
|
||||
const timelabel = this.props.tools.formatterWithYear(timestamp);
|
||||
return timelabel;
|
||||
}
|
||||
|
||||
// NB: should be internaionalized.
|
||||
renderTimestamp() {
|
||||
const daytime_lang = copy[this.props.language].cardstack.timestamp;
|
||||
const estimated_lang = copy[this.props.language].cardstack.estimated;
|
||||
|
||||
if (isNotNullNorUndefined(this.props.event.timestamp)) {
|
||||
const timestamp = this.props.tools.parser(this.props.event.timestamp);
|
||||
const timelabel = this.props.tools.formatterWithYear(timestamp);
|
||||
const timelabel = this.getTimeLabel();
|
||||
return (<div className="event-card-section timestamp">
|
||||
<h4>{daytime_lang}</h4>
|
||||
{timelabel}
|
||||
@@ -166,6 +171,27 @@ class Card extends React.Component {
|
||||
</div>);
|
||||
}
|
||||
|
||||
renderCardLink(event, direction) {
|
||||
if (event !== null) {
|
||||
const timelabel = this.getTimeLabel();
|
||||
return (<a onClick={() => this.props.select([event])}>
|
||||
{`${timelabel} - ${event.location}`}
|
||||
</a>);
|
||||
}
|
||||
return (<a className="disabled">None</a>);
|
||||
}
|
||||
|
||||
renderNarrative() {
|
||||
const links = this.props.getNarrativeLinks(this.props.event);
|
||||
if (links !== null) {
|
||||
return (<div className="event-card-section">
|
||||
<h4>Connected events</h4>
|
||||
<p>Next: {this.renderCardLink(links.next, 'next')}</p>
|
||||
<p>Previous: {this.renderCardLink(links.prev, 'prev')}</p>
|
||||
</div>);
|
||||
}
|
||||
}
|
||||
|
||||
renderContent() {
|
||||
if (this.state.isFolded) {
|
||||
return (<div className="card-bottomhalf folded"></div>);
|
||||
@@ -176,16 +202,16 @@ class Card extends React.Component {
|
||||
} else {
|
||||
if (!this.props.event.hasOwnProperty('receiver') && !this.props.event.hasOwnProperty('transmitter')) {
|
||||
return (<div className="card-bottomhalf">
|
||||
{this.renderTimestamp()}
|
||||
{this.renderLocation()}
|
||||
{this.renderTags()}
|
||||
{this.renderSource()}
|
||||
{this.renderNarrative()}
|
||||
</div>);
|
||||
} else {
|
||||
return (<div className="card-bottomhalf">
|
||||
{this.renderTimestamp()}
|
||||
{this.renderTags()}
|
||||
{this.renderSource()}
|
||||
{this.renderNarrative()}
|
||||
</div>);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,10 +25,12 @@ class CardStack extends React.Component {
|
||||
language={this.props.language}
|
||||
tools={this.props.tools}
|
||||
isFetchingEvents={this.props.isFetchingEvents}
|
||||
getNarrativeLinks={this.props.getNarrativeLinks}
|
||||
getCategoryGroup={this.props.getCategoryGroup}
|
||||
getCategoryGroupColor={this.props.getCategoryGroupColor}
|
||||
getCategoryLabel={this.props.getCategoryLabel}
|
||||
highlight={this.props.highlight}
|
||||
select={this.props.select}
|
||||
/>
|
||||
);
|
||||
});
|
||||
|
||||
@@ -109,6 +109,12 @@ class Dashboard extends React.Component {
|
||||
return label;
|
||||
}
|
||||
|
||||
getNarrativeLinks(event) {
|
||||
const narrative = this.props.domain.narratives.find(nv => nv.key === event.narrative);
|
||||
if (narrative) return narrative.byId[event.id];
|
||||
return null;
|
||||
}
|
||||
|
||||
renderTool() {
|
||||
return (<div>
|
||||
<Viewport
|
||||
@@ -157,8 +163,10 @@ class Dashboard extends React.Component {
|
||||
isCardstack={this.props.ui.flags.isCardstack}
|
||||
isFetchingEvents={this.props.ui.flags.isFetchingEvents}
|
||||
|
||||
select={this.handleSelect}
|
||||
highlight={this.handleHighlight}
|
||||
toggle={this.handleToggle}
|
||||
getNarrativeLinks={event => this.getNarrativeLinks(event)}
|
||||
getCategoryGroup={category => this.getCategoryGroup(category)}
|
||||
getCategoryGroupColor={category => this.getCategoryGroupColor(category)}
|
||||
getCategoryLabel={category => this.getCategoryLabel(category)}
|
||||
|
||||
@@ -43,6 +43,15 @@
|
||||
|
||||
.event-card-section {
|
||||
margin-bottom: 10px;
|
||||
|
||||
a:hover {
|
||||
color: $red;
|
||||
cursor: pointer;
|
||||
}
|
||||
a.disabled {
|
||||
color: $midgrey;
|
||||
cursor: default;
|
||||
}
|
||||
}
|
||||
|
||||
.card-toggle p {
|
||||
|
||||
@@ -90,14 +90,20 @@ export const getFilteredNarratives = createSelector(
|
||||
(parseTimestamp(evt.timestamp) < rangeFilter[1]);
|
||||
|
||||
if (isRange && isTagged && evt.narrative) {
|
||||
if (!narratives[evt.narrative]) narratives[evt.narrative] = { key: evt.narrative, steps: [] };
|
||||
if (!narratives[evt.narrative]) narratives[evt.narrative] = { key: evt.narrative, steps: [], byId: {} };
|
||||
narratives[evt.narrative].steps.push(evt);
|
||||
narratives[evt.narrative].byId[evt.id] = { next: null, prev: null };
|
||||
}
|
||||
});
|
||||
Object.keys(narratives).forEach((key) => {
|
||||
narratives[key].steps.sort((a, b) => {
|
||||
const steps = narratives[key].steps;
|
||||
steps.sort((a, b) => {
|
||||
return (parseTimestamp(a.timestamp) > parseTimestamp(b.timestamp));
|
||||
});
|
||||
steps.forEach((step, i) => {
|
||||
narratives[key].byId[step.id].next = (i < steps.length - 2) ? steps[i + 1] : null;
|
||||
narratives[key].byId[step.id].prev = (i > 0) ? steps[i - 1] : null;
|
||||
});
|
||||
})
|
||||
return Object.values(narratives);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user