mirror of
https://github.com/bellingcat/ukraine-timemap.git
synced 2026-06-12 21:38:35 +03:00
WIP: refactor Toolbar.jsx
This commit is contained in:
@@ -16,6 +16,8 @@ import Notification from './Notification.jsx';
|
||||
|
||||
import { parseDate } from '../js/utilities';
|
||||
|
||||
import { injectNarrative } from '../js/utilities'
|
||||
|
||||
class Dashboard extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
@@ -87,12 +89,13 @@ class Dashboard extends React.Component {
|
||||
return (
|
||||
<div>
|
||||
<Toolbar
|
||||
isNarrative={!!this.props.app.narrative}
|
||||
onFilter={this.handleTagFilter}
|
||||
onSelectNarrative={this.handleSelectNarrative}
|
||||
actions={this.props.actions}
|
||||
/>
|
||||
<Map
|
||||
mapId="map"
|
||||
mapId='map'
|
||||
methods={{
|
||||
onSelect: this.handleSelect,
|
||||
onSelectNarrative: this.handleSelectNarrative,
|
||||
@@ -106,13 +109,10 @@ class Dashboard extends React.Component {
|
||||
getCategoryColor: category => this.getCategoryColor(category)
|
||||
}}
|
||||
/>
|
||||
{(this.props.app.narrative !== null)
|
||||
? <NarrativeCard
|
||||
onSelect={this.handleSelect}
|
||||
onSelectNarrative={this.handleSelectNarrative}
|
||||
/>
|
||||
: ''
|
||||
}
|
||||
<NarrativeCard
|
||||
onSelect={this.handleSelect}
|
||||
onSelectNarrative={this.handleSelectNarrative}
|
||||
/>
|
||||
<CardStack
|
||||
onViewSource={this.handleViewSource}
|
||||
onSelect={this.handleSelect}
|
||||
@@ -166,5 +166,6 @@ function injectSource(id) {
|
||||
|
||||
export default connect(
|
||||
state => state,
|
||||
// injectNarrative(0),
|
||||
mapDispatchToProps,
|
||||
)(Dashboard);
|
||||
|
||||
@@ -24,6 +24,8 @@ class NarrativeCard extends React.Component {
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
if (!this.props.narrative) return
|
||||
|
||||
const step = this.props.narrative.steps[this.state.step];
|
||||
this.props.onSelect([step]);
|
||||
}
|
||||
@@ -45,7 +47,7 @@ class NarrativeCard extends React.Component {
|
||||
renderClose() {
|
||||
return (
|
||||
<button
|
||||
className="side-menu-burg is-active"
|
||||
className='side-menu-burg is-active'
|
||||
onClick={() => { this.props.onSelectNarrative(null); }}
|
||||
>
|
||||
<span></span>
|
||||
@@ -54,27 +56,30 @@ class NarrativeCard extends React.Component {
|
||||
}
|
||||
|
||||
render() {
|
||||
if (this.props.narrative.steps[this.state.step]) {
|
||||
const steps = this.props.narrative.steps;
|
||||
const step = steps[this.state.step];
|
||||
if (!this.props.narrative) return null
|
||||
|
||||
const { steps, current } = this.props.narrative
|
||||
if (steps[current]) {
|
||||
const step = steps[current];
|
||||
|
||||
return (
|
||||
<div className="narrative-info">
|
||||
<div className='narrative-info'>
|
||||
{this.renderClose()}
|
||||
<h3>{this.props.narrative.label}</h3>
|
||||
<p>{this.props.narrative.description}</p>
|
||||
<h6>
|
||||
<i className="material-icons left">location_on</i>
|
||||
<i className='material-icons left'>location_on</i>
|
||||
{this.state.step + 1}/{steps.length}. {step.location}
|
||||
</h6>
|
||||
<div className="actions">
|
||||
<div className='actions'>
|
||||
<div className={`${(!this.state.step) ? 'disabled ' : ''} action`} onClick={() => this.goToPrevKeyFrame()}>←</div>
|
||||
<div className={`${(this.state.step >= this.props.narrative.steps.length - 1) ? 'disabled ' : ''} action`} onClick={() => this.goToNextKeyFrame()}>→</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
} else {
|
||||
return null
|
||||
}
|
||||
return (<div/>);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -7,25 +7,22 @@ import Search from './Search.jsx';
|
||||
import TagListPanel from './TagListPanel.jsx';
|
||||
import ToolbarBottomActions from './ToolbarBottomActions.jsx';
|
||||
import copy from '../js/data/copy.json';
|
||||
import { isNotNullNorUndefined, trimAndEllipse } from '../js/utilities.js';
|
||||
import { trimAndEllipse } from '../js/utilities.js';
|
||||
|
||||
class Toolbar extends React.Component {
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
tabNum: -1
|
||||
};
|
||||
super(props)
|
||||
this.state = { _selected: -1 }
|
||||
}
|
||||
|
||||
toggleTab(tabNum) {
|
||||
this.setState({ tabNum: (this.state.tabNum === tabNum) ? -1 : tabNum });
|
||||
selectTab(selected) {
|
||||
const _selected = (this.state._selected === selected) ? -1 : selected
|
||||
this.setState({ _selected });
|
||||
}
|
||||
|
||||
renderClosePanel() {
|
||||
return (
|
||||
<div className="panel-header" onClick={() => this.toggleTab(-1)}>
|
||||
<div className="panel-header" onClick={() => this.selectTab(-1)}>
|
||||
<div className="caret"></div>
|
||||
</div>
|
||||
);
|
||||
@@ -49,11 +46,8 @@ class Toolbar extends React.Component {
|
||||
}
|
||||
|
||||
goToNarrative(narrative) {
|
||||
this.setState({
|
||||
tabNum: -1
|
||||
}, () => {
|
||||
this.props.onSelectNarrative(narrative);
|
||||
});
|
||||
this.selectTab(-1) // set all unselected
|
||||
this.props.onSelectNarrative(narrative);
|
||||
}
|
||||
|
||||
renderToolbarNarrativePanel() {
|
||||
@@ -64,7 +58,7 @@ class Toolbar extends React.Component {
|
||||
{this.props.narratives.map((narr) => {
|
||||
return (
|
||||
<div className="panel-action action">
|
||||
<button style={{ backgroundColor: '#000' }} onClick={() => { this.goToNarrative(narr); }}>
|
||||
<button style={{ backgroundColor: '#000' }} onClick={() => { this.goToNarrative(narr) }}>
|
||||
<p>{narr.label}</p>
|
||||
<p><small>{trimAndEllipse(narr.description, 120)}</small></p>
|
||||
</button>
|
||||
@@ -94,12 +88,12 @@ class Toolbar extends React.Component {
|
||||
return '';
|
||||
}
|
||||
|
||||
renderToolbarTab(tabNum, label) {
|
||||
const isActive = (this.state.tabNum === tabNum);
|
||||
renderToolbarTab(_selected, label) {
|
||||
const isActive = (this.state._selected === _selected);
|
||||
let classes = (isActive) ? 'toolbar-tab active' : 'toolbar-tab';
|
||||
|
||||
return (
|
||||
<div className={classes} onClick={() => { this.toggleTab(tabNum); }}>
|
||||
<div className={classes} onClick={() => { this.selectTab(_selected); }}>
|
||||
<i className="material-icons">timeline</i>
|
||||
<div className="tab-caption">{label}</div>
|
||||
</div>
|
||||
@@ -126,12 +120,11 @@ class Toolbar extends React.Component {
|
||||
}
|
||||
|
||||
renderToolbarPanels() {
|
||||
let classes = (this.state.tabNum !== -1) ? 'toolbar-panels' : 'toolbar-panels folded';
|
||||
|
||||
let classes = (this.state._selected >= 0) ? 'toolbar-panels' : 'toolbar-panels folded';
|
||||
return (
|
||||
<div className={classes}>
|
||||
{this.renderClosePanel()}
|
||||
<Tabs selectedIndex={this.state.tabNum}>
|
||||
<Tabs selectedIndex={this.state._selected}>
|
||||
{this.renderToolbarNarrativePanel()}
|
||||
{this.renderToolbarTagPanel()}
|
||||
</Tabs>
|
||||
@@ -142,12 +135,12 @@ class Toolbar extends React.Component {
|
||||
renderToolbarNavs() {
|
||||
if (this.props.narratives) {
|
||||
return this.props.narratives.map((nar, idx) => {
|
||||
const isActive = (idx === this.state.tab);
|
||||
const isActive = (idx === this.state._selected);
|
||||
|
||||
let classes = (isActive) ? 'toolbar-tab active' : 'toolbar-tab';
|
||||
|
||||
return (
|
||||
<div className={classes} onClick={() => { this.toggleTab(idx); }}>
|
||||
<div className={classes} onClick={() => { this.selectTab(idx); }}>
|
||||
<div className="tab-caption">{nar.label}</div>
|
||||
</div>
|
||||
);
|
||||
@@ -176,7 +169,8 @@ class Toolbar extends React.Component {
|
||||
}
|
||||
|
||||
render() {
|
||||
const isNarrative = isNotNullNorUndefined(this.props.narrative);
|
||||
const { isNarrative } = this.props
|
||||
|
||||
return (
|
||||
<div id="toolbar-wrapper" className={`toolbar-wrapper ${(isNarrative) ? 'narrative-mode' : ''}`}>
|
||||
{this.renderToolbarTabs()}
|
||||
|
||||
@@ -77,7 +77,7 @@ export function formatter(datetime) {
|
||||
* Debugging function: put in place of a mapStateToProps function to
|
||||
* view that source modal by default
|
||||
*/
|
||||
function injectSource(id) {
|
||||
export function injectSource(id) {
|
||||
return state => ({
|
||||
...state,
|
||||
app: {
|
||||
@@ -87,3 +87,20 @@ function injectSource(id) {
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Debugging function: put in place of a mapStateToProps function to
|
||||
* view that narrative modal by default
|
||||
*/
|
||||
export function injectNarrative(idx) {
|
||||
return state => {
|
||||
console.log(state.domain.narratives)
|
||||
return {
|
||||
...state,
|
||||
app: {
|
||||
...state.app,
|
||||
narrative: state.domain.narratives.length ? state.domain.narratives[idx] : null
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -33,25 +33,33 @@ function updateSelected(appState, action) {
|
||||
}
|
||||
|
||||
function updateNarrative(appState, action) {
|
||||
if (action.narrative === null) {
|
||||
return Object.assign({}, appState, {
|
||||
narrative: action.narrative,
|
||||
});
|
||||
} else {
|
||||
const dates = action.narrative.steps.map(n => parseDate(n.timestamp).getTime())
|
||||
let minDate = Math.min(...dates);
|
||||
let maxDate = Math.max(...dates);
|
||||
// Add some margin to the datetime extent
|
||||
minDate = minDate - ((maxDate - minDate) / 20);
|
||||
maxDate = maxDate + ((maxDate - minDate) / 20);
|
||||
|
||||
return Object.assign({}, appState, {
|
||||
narrative: action.narrative,
|
||||
filters: Object.assign({}, appState.filters, {
|
||||
timerange: [new Date(minDate), new Date(maxDate)]
|
||||
}),
|
||||
});
|
||||
console.log(action.narrative)
|
||||
return {
|
||||
...appState,
|
||||
narrative: action.narrative
|
||||
}
|
||||
// if (action.narrative === null) {
|
||||
// console.log(action.narrative)
|
||||
// return Object.assign({}, appState, {
|
||||
// narrative: action.narrative,
|
||||
// });
|
||||
// } else {
|
||||
// const dates = action.narrative.steps.map(n => parseDate(n.timestamp).getTime())
|
||||
// let minDate = Math.min(...dates);
|
||||
// let maxDate = Math.max(...dates);
|
||||
// // Add some margin to the datetime extent
|
||||
// minDate = minDate - ((maxDate - minDate) / 20);
|
||||
// maxDate = maxDate + ((maxDate - minDate) / 20);
|
||||
//
|
||||
// const output = Object.assign({}, appState, {
|
||||
// narrative: action.narrative,
|
||||
// filters: Object.assign({}, appState.filters, {
|
||||
// timerange: [new Date(minDate), new Date(maxDate)]
|
||||
// }),
|
||||
// });
|
||||
// console.log(output)
|
||||
// return output
|
||||
// }
|
||||
}
|
||||
|
||||
function updateTagFilters(appState, action) {
|
||||
|
||||
@@ -5,7 +5,10 @@ NARRATIVE INFO
|
||||
position: fixed;
|
||||
top: 10px;
|
||||
left: 10px;
|
||||
// height: auto;
|
||||
min-height: 500px;
|
||||
height: auto;
|
||||
max-height: 500px;
|
||||
width: 370px;
|
||||
box-sizing: border-box;
|
||||
padding: 15px;
|
||||
|
||||
Reference in New Issue
Block a user