mirror of
https://github.com/bellingcat/ukraine-timemap.git
synced 2026-06-12 13:28:36 +03:00
Merge pull request #37 from forensic-architecture/fix/clean-semantics
Fix/clean semantics
This commit is contained in:
@@ -3,8 +3,8 @@ module.exports = {
|
||||
SERVER_ROOT: 'http://localhost:4040',
|
||||
EVENT_EXT: '/api/example/export_events/rows',
|
||||
CATEGORY_EXT: '/api/example/export_categories/rows',
|
||||
EVENT_DESC_ROOT: '/api/example/export_events/ids',
|
||||
TAG_TREE_EXT: '/api/example/export_tags/tree',
|
||||
SOURCES_EXT: '/api/example/export_events/ids',
|
||||
TAGS_EXT: '/api/example/export_tags/tree',
|
||||
SITES_EXT: '/api/example/export_sites/rows',
|
||||
MAP_ANCHOR: [31.356397, 34.784818],
|
||||
INCOMING_DATETIME_FORMAT: '%m/%d/%YT%H:%M',
|
||||
|
||||
@@ -1,8 +1,18 @@
|
||||
// TODO: move to util lib
|
||||
function urlFromEnv(ext) {
|
||||
if (process.env[ext]) {
|
||||
return `${process.env.SERVER_ROOT}${process.env[ext]}`
|
||||
} else {
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: relegate these URLs entirely to environment variables
|
||||
const EVENT_DATA_URL = `${process.env.SERVER_ROOT}${process.env.EVENT_EXT}`
|
||||
const CATEGORY_URL = `${process.env.SERVER_ROOT}${process.env.CATEGORY_EXT}`
|
||||
const TAG_TREE_URL = `${process.env.SERVER_ROOT}${process.env.TAG_TREE_EXT}`
|
||||
const SITES_URL = `${process.env.SERVER_ROOT}${process.env.SITES_EXT}`
|
||||
const EVENT_DATA_URL = urlFromEnv('EVENT_EXT')
|
||||
const CATEGORY_URL = urlFromEnv('CATEGORY_EXT')
|
||||
const TAG_URL = urlFromEnv('TAGS_EXT')
|
||||
const SOURCES_URL = urlFromEnv('SOURCES_EXT')
|
||||
const SITES_URL = urlFromEnv('SITES_EXT')
|
||||
const eventUrlMap = (event) => `${process.env.SERVER_ROOT}${process.env.EVENT_DESC_ROOT}/${(event.id) ? event.id : event}`
|
||||
|
||||
/*
|
||||
@@ -97,110 +107,128 @@ export function updateDomain(domain) {
|
||||
}
|
||||
}
|
||||
|
||||
export function fetchEvents (events) {
|
||||
|
||||
export function fetchSelected(selected) {
|
||||
if (!selected || !selected.length || selected.length === 0) {
|
||||
console.log('hitting base')
|
||||
return updateSelected([])
|
||||
}
|
||||
return dispatch => {
|
||||
dispatch(toggleFetchingEvents())
|
||||
const urls = events.map(eventUrlMap)
|
||||
return Promise.all(
|
||||
urls.map(url => fetch(url)
|
||||
.then(response => response.json())
|
||||
)
|
||||
)
|
||||
.then(json => {
|
||||
dispatch(toggleFetchingEvents())
|
||||
return json
|
||||
})
|
||||
dispatch(updateSelected(selected))
|
||||
if (!SOURCES_URL) {
|
||||
dispatch(fetchSourceError('No source extension specified.'))
|
||||
} else {
|
||||
dispatch(toggleFetchingSources())
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
export const UPDATE_HIGHLIGHTED = 'UPDATE_HIGHLIGHTED'
|
||||
export function updateHighlighted(highlighted) {
|
||||
return {
|
||||
type: UPDATE_HIGHLIGHTED,
|
||||
highlighted: highlighted
|
||||
}
|
||||
return {
|
||||
type: UPDATE_HIGHLIGHTED,
|
||||
highlighted: highlighted
|
||||
}
|
||||
}
|
||||
|
||||
export const UPDATE_SELECTED = 'UPDATE_SELECTED'
|
||||
export function updateSelected(selected) {
|
||||
return {
|
||||
type: UPDATE_SELECTED,
|
||||
selected: selected
|
||||
}
|
||||
return {
|
||||
type: UPDATE_SELECTED,
|
||||
selected: selected
|
||||
}
|
||||
}
|
||||
|
||||
export const UPDATE_DISTRICT = 'UPDATE_DISTRICT'
|
||||
export function updateDistrict(district) {
|
||||
return {
|
||||
type: UPDATE_DISTRICT,
|
||||
district
|
||||
}
|
||||
return {
|
||||
type: UPDATE_DISTRICT,
|
||||
district
|
||||
}
|
||||
}
|
||||
|
||||
export const UPDATE_TAGFILTERS = 'UPDATE_TIMEFILTERS'
|
||||
export function updateTagFilters(tag) {
|
||||
return {
|
||||
type: UPDATE_TAGFILTERS,
|
||||
tag
|
||||
}
|
||||
return {
|
||||
type: UPDATE_TAGFILTERS,
|
||||
tag
|
||||
}
|
||||
}
|
||||
|
||||
export const UPDATE_TIMERANGE = 'UPDATE_TIMERANGE';
|
||||
export function updateTimeRange(timerange) {
|
||||
return {
|
||||
type: UPDATE_TIMERANGE,
|
||||
timerange
|
||||
};
|
||||
return {
|
||||
type: UPDATE_TIMERANGE,
|
||||
timerange
|
||||
}
|
||||
}
|
||||
|
||||
export const RESET_ALLFILTERS = 'RESET_ALLFILTERS'
|
||||
export function resetAllFilters() {
|
||||
return {
|
||||
type: RESET_ALLFILTERS
|
||||
}
|
||||
return {
|
||||
type: RESET_ALLFILTERS
|
||||
}
|
||||
}
|
||||
|
||||
// UI
|
||||
|
||||
export const TOGGLE_FETCHING_DOMAIN = 'TOGGLE_FETCHING_DOMAIN'
|
||||
export function toggleFetchingDomain() {
|
||||
return {
|
||||
type: TOGGLE_FETCHING_DOMAIN
|
||||
}
|
||||
return {
|
||||
type: TOGGLE_FETCHING_DOMAIN
|
||||
}
|
||||
}
|
||||
|
||||
export const TOGGLE_FETCHING_EVENTS = 'TOGGLE_FETCHING_EVENTS'
|
||||
export function toggleFetchingEvents() {
|
||||
return {
|
||||
type: TOGGLE_FETCHING_EVENTS
|
||||
}
|
||||
export const TOGGLE_FETCHING_SOURCES = 'TOGGLE_FETCHING_SOURCES'
|
||||
export function toggleFetchingSources() {
|
||||
return {
|
||||
type: TOGGLE_FETCHING_SOURCES
|
||||
}
|
||||
}
|
||||
|
||||
export const TOGGLE_LANGUAGE = 'TOGGLE_LANGUAGE';
|
||||
export function toggleLanguage(language) {
|
||||
return {
|
||||
type: TOGGLE_LANGUAGE,
|
||||
language,
|
||||
}
|
||||
return {
|
||||
type: TOGGLE_LANGUAGE,
|
||||
language,
|
||||
}
|
||||
}
|
||||
|
||||
export const CLOSE_TOOLBAR = 'CLOSE_TOOLBAR';
|
||||
export function closeToolbar() {
|
||||
return {
|
||||
type: CLOSE_TOOLBAR
|
||||
}
|
||||
return {
|
||||
type: CLOSE_TOOLBAR
|
||||
}
|
||||
}
|
||||
|
||||
export const TOGGLE_INFOPOPUP = 'TOGGLE_INFOPOPUP';
|
||||
export function toggleInfoPopup() {
|
||||
return {
|
||||
type: TOGGLE_INFOPOPUP
|
||||
}
|
||||
return {
|
||||
type: TOGGLE_INFOPOPUP
|
||||
}
|
||||
}
|
||||
|
||||
export const TOGGLE_NOTIFICATIONS = 'TOGGLE_NOTIFICATIONS'
|
||||
export function toggleNotifications() {
|
||||
return {
|
||||
type: TOGGLE_NOTIFICATIONS
|
||||
}
|
||||
return {
|
||||
type: TOGGLE_NOTIFICATIONS
|
||||
}
|
||||
}
|
||||
|
||||
export const MARK_NOTIFICATIONS_READ = 'MARK_NOTIFICATIONS_READ'
|
||||
export function markNotificationsRead() {
|
||||
return {
|
||||
type: MARK_NOTIFICATIONS_READ
|
||||
}
|
||||
}
|
||||
|
||||
// ERRORS
|
||||
|
||||
export const FETCH_SOURCE_ERROR = 'FETCH_SOURCE_ERROR'
|
||||
export function fetchSourceError(msg) {
|
||||
return {
|
||||
type: FETCH_SOURCE_ERROR,
|
||||
msg
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,7 +22,6 @@ class CardStack extends React.Component {
|
||||
event={event}
|
||||
language={this.props.language}
|
||||
tools={this.props.tools}
|
||||
isLoading={this.props.isLoading}
|
||||
getNarrativeLinks={this.props.getNarrativeLinks}
|
||||
getCategoryGroup={this.props.getCategoryGroup}
|
||||
getCategoryColor={this.props.getCategoryColor}
|
||||
@@ -54,15 +53,12 @@ class CardStack extends React.Component {
|
||||
<div
|
||||
id='card-stack-header'
|
||||
className='card-stack-header'
|
||||
onClick={() => this.props.onToggle('TOGGLE_CARDSTACK')}
|
||||
onClick={() => this.props.onToggleCardstack()}
|
||||
>
|
||||
<button className="side-menu-burg is-active"><span></span></button>
|
||||
<p className="header-copy top">
|
||||
{(this.props.isLoading)
|
||||
? copy[this.props.language].loading
|
||||
: `${this.props.selected.length} ${header_lang}`}
|
||||
{`${this.props.selected.length} ${header_lang}`}
|
||||
</p>
|
||||
{(this.props.isLoading) ? '' : this.renderLocation()}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -71,10 +67,7 @@ class CardStack extends React.Component {
|
||||
return (
|
||||
<div id="card-stack-content" className="card-stack-content">
|
||||
<ul>
|
||||
{(this.props.isLoading)
|
||||
? <Card language={this.props.language} isLoading={true} />
|
||||
: this.renderCards()
|
||||
}
|
||||
{this.renderCards()}
|
||||
</ul>
|
||||
</div>
|
||||
);
|
||||
@@ -99,7 +92,7 @@ function mapStateToProps(state) {
|
||||
language: state.app.language,
|
||||
tools: state.ui.tools,
|
||||
isCardstack: state.ui.flags.isCardstack,
|
||||
isLoading: state.ui.flags.isFetchingEvents
|
||||
isFetchingSources: state.ui.flags.isFetchingSources
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ class Dashboard extends React.Component {
|
||||
|
||||
this.handleHighlight = this.handleHighlight.bind(this);
|
||||
this.handleSelect = this.handleSelect.bind(this);
|
||||
this.handleToggle = this.handleToggle.bind(this);
|
||||
// this.handleToggle = this.handleToggle.bind(this);
|
||||
this.handleTagFilter = this.handleTagFilter.bind(this);
|
||||
this.updateTimerange = this.updateTimerange.bind(this);
|
||||
|
||||
@@ -46,32 +46,11 @@ class Dashboard extends React.Component {
|
||||
handleSelect(selected) {
|
||||
if (selected) {
|
||||
let eventsToSelect = selected.map(event => this.getEventById(event.id));
|
||||
const parser = this.props.ui.tools.parser;
|
||||
const p = this.props.ui.tools.parser;
|
||||
|
||||
eventsToSelect = eventsToSelect.sort((a, b) => {
|
||||
return parser(a.timestamp) - parser(b.timestamp);
|
||||
});
|
||||
eventsToSelect = eventsToSelect.sort((a, b) => p(a.timestamp) - p(b.timestamp))
|
||||
|
||||
if (eventsToSelect.every(event => (event))) {
|
||||
this.props.actions.updateSelected(eventsToSelect);
|
||||
}
|
||||
|
||||
// Now fetch detail data for each event
|
||||
// Add transmitter and receiver data for coevents
|
||||
this.props.actions.fetchEvents(selected)
|
||||
.then((events) => {
|
||||
let eventsSelected = events.map(ev => {
|
||||
return Object.assign({}, ev, this.getEventById(ev.id));
|
||||
});
|
||||
|
||||
eventsSelected = eventsSelected.sort((a, b) => {
|
||||
return parser(a.timestamp) - parser(b.timestamp);
|
||||
});
|
||||
|
||||
this.props.actions.updateSelected(eventsSelected);
|
||||
});
|
||||
} else {
|
||||
this.props.actions.updateSelected([]);
|
||||
this.props.actions.fetchSelected(eventsToSelect)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -83,23 +62,6 @@ class Dashboard extends React.Component {
|
||||
this.props.actions.updateTimeRange(timeRange);
|
||||
}
|
||||
|
||||
handleToggle( key ) {
|
||||
switch( key ) {
|
||||
case 'TOGGLE_CARDSTACK': {
|
||||
this.props.actions.updateSelected([]);
|
||||
break;
|
||||
}
|
||||
case 'TOGGLE_INFOPOPUP': {
|
||||
this.props.actions.toggleInfoPopup();
|
||||
break;
|
||||
}
|
||||
case 'TOGGLE_NOTIFICATIONS': {
|
||||
this.props.actions.toggleNotifications();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
getCategoryColor(category='other') {
|
||||
return this.props.ui.style.categories[category] || this.props.style.categories['other']
|
||||
}
|
||||
@@ -113,41 +75,39 @@ class Dashboard extends React.Component {
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<Viewport
|
||||
<Viewport
|
||||
methods={{
|
||||
select: this.handleSelect,
|
||||
highlight: this.handleHighlight,
|
||||
onSelect: this.handleSelect,
|
||||
getCategoryColor: category => this.getCategoryColor(category)
|
||||
}}
|
||||
/>
|
||||
<Toolbar
|
||||
filter={this.handleTagFilter}
|
||||
toggle={ (key) => this.handleToggle(key) }
|
||||
onFilter={this.handleTagFilter}
|
||||
actions={this.props.actions}
|
||||
/>
|
||||
<CardStack
|
||||
onSelect={this.handleSelect}
|
||||
onHighlight={this.handleHighlight}
|
||||
onToggle={this.handleToggle}
|
||||
onToggleCardstack={() => this.props.actions.updateSelected([])}
|
||||
getNarrativeLinks={event => this.getNarrativeLinks(event)}
|
||||
getCategoryColor={category => this.getCategoryColor(category)}
|
||||
/>
|
||||
<Timeline
|
||||
onSelect={this.handleSelect}
|
||||
onUpdateTimerange={this.updateTimerange}
|
||||
// onHighlight={this.handleHighlight}
|
||||
// onToggle={() => this.handleToggle('TOGGLE_CARDSTACK')}
|
||||
getCategoryColor={category => this.getCategoryColor(category)}
|
||||
methods={{
|
||||
onSelect: this.handleSelect,
|
||||
onUpdateTimerange: this.updateTimerange,
|
||||
getCategoryColor: category => this.getCategoryColor(category)
|
||||
}}
|
||||
/>
|
||||
<InfoPopUp
|
||||
ui={this.props.ui}
|
||||
app={this.props.app}
|
||||
toggle={() => this.handleToggle('TOGGLE_INFOPOPUP')}
|
||||
toggle={() => this.props.actions.toggleInfoPopup()}
|
||||
/>
|
||||
<Notification
|
||||
isNotification={this.props.ui.flags.isNotification}
|
||||
notifications={this.props.domain.notifications}
|
||||
toggle={() => this.handleToggle('TOGGLE_NOTIFICATIONS')}
|
||||
onToggle={this.props.actions.markNotificationsRead}
|
||||
/>
|
||||
<LoadingOverlay
|
||||
ui={this.props.ui.flags.isFetchingDomain}
|
||||
|
||||
@@ -43,8 +43,8 @@ export default class Notification extends React.Component{
|
||||
}
|
||||
|
||||
render() {
|
||||
if (this.props.isNotification) {
|
||||
|
||||
const notificationsToRender = this.props.notifications.filter(n => !('isRead' in n && n.isRead))
|
||||
if (notificationsToRender.length > 0) {
|
||||
return (
|
||||
<div className={`notification-wrapper`}>
|
||||
{this.props.notifications.map((notification) => {
|
||||
@@ -52,7 +52,7 @@ export default class Notification extends React.Component{
|
||||
return (
|
||||
<div className='notification' onClick={() => this.toggleDetails() }>
|
||||
<button
|
||||
onClick={() => this.props.toggle()}
|
||||
onClick={this.props.onToggle}
|
||||
className="side-menu-burg over-white is-active"
|
||||
>
|
||||
<span />
|
||||
|
||||
@@ -19,13 +19,7 @@ class Timeline extends React.Component {
|
||||
dom: this.props.dom
|
||||
}
|
||||
|
||||
const methods = {
|
||||
onSelect: this.props.onSelect,
|
||||
onUpdateTimerange: this.props.onUpdateTimerange,
|
||||
getCategoryColor: this.props.getCategoryColor
|
||||
}
|
||||
|
||||
this.timeline = new TimelineLogic(this.props.app, ui, methods);
|
||||
this.timeline = new TimelineLogic(this.props.app, ui, this.props.methods);
|
||||
this.timeline.update(this.props.domain, this.props.app);
|
||||
this.timeline.render(this.props.domain);
|
||||
}
|
||||
|
||||
@@ -170,7 +170,7 @@ class Toolbar extends React.Component {
|
||||
categories={this.props.categories}
|
||||
tagFilters={this.props.tagFilters}
|
||||
categoryFilters={this.props.categoryFilters}
|
||||
filter={this.props.filter}
|
||||
filter={this.props.onFilter}
|
||||
title={title}
|
||||
overview={overview}
|
||||
language={this.props.language}
|
||||
@@ -189,7 +189,7 @@ class Toolbar extends React.Component {
|
||||
categories={this.props.categories}
|
||||
tagFilters={this.props.tagFilters}
|
||||
categoryFilters={this.props.categoryFilters}
|
||||
filter={this.props.filter}
|
||||
filter={this.props.onFilter}
|
||||
/>
|
||||
</TabPanel>
|
||||
)
|
||||
|
||||
@@ -21,7 +21,6 @@ export default function(newApp, ui, methods) {
|
||||
}
|
||||
|
||||
const getCategoryColor = methods.getCategoryColor;
|
||||
const select = methods.select;
|
||||
const narrativeProps = ui.narratives;
|
||||
|
||||
// Map Settings
|
||||
@@ -272,7 +271,7 @@ Stop and start the development process in terminal after you have added your tok
|
||||
${lMap.latLngToLayerPoint(d.LatLng).y})`;
|
||||
})
|
||||
.on('click', (location) => {
|
||||
select(location.events);
|
||||
methods.onSelect(location.events);
|
||||
});
|
||||
|
||||
const eventsDom = g.selectAll('.location')
|
||||
|
||||
@@ -1,19 +1,32 @@
|
||||
import initial from '../store/initial.js'
|
||||
|
||||
import { UPDATE_DOMAIN } from '../actions'
|
||||
import { UPDATE_DOMAIN, MARK_NOTIFICATIONS_READ } from '../actions'
|
||||
import { parseDateTimes } from './utils/helpers.js'
|
||||
import { validate } from './utils/validators.js'
|
||||
import { validateDomain } from './utils/validators.js'
|
||||
|
||||
function updateDomain (domainState, action) {
|
||||
action.domain.events = parseDateTimes(action.domain.events)
|
||||
|
||||
return Object.assign({}, domainState, validate(action.domain))
|
||||
// return Object.assign({}, domainState, validate(action.domain))
|
||||
return {
|
||||
...domainState,
|
||||
...validateDomain(action.domain)
|
||||
}
|
||||
}
|
||||
|
||||
function markNotificationsRead (domainState, action) {
|
||||
return {
|
||||
...domainState,
|
||||
notifications: domainState.notifications.map(n => ({ ...n, isRead: true }))
|
||||
}
|
||||
}
|
||||
|
||||
function domain (domainState = initial.domain, action) {
|
||||
switch (action.type) {
|
||||
case UPDATE_DOMAIN:
|
||||
return updateDomain(domainState, action)
|
||||
case MARK_NOTIFICATIONS_READ:
|
||||
return markNotificationsRead(domainState, action)
|
||||
default:
|
||||
return domainState
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ import initial from '../store/initial.js';
|
||||
|
||||
import {
|
||||
TOGGLE_FETCHING_DOMAIN,
|
||||
TOGGLE_FETCHING_EVENTS,
|
||||
TOGGLE_FETCHING_SOURCES,
|
||||
TOGGLE_VIEW,
|
||||
TOGGLE_TIMELINE,
|
||||
TOGGLE_INFOPOPUP,
|
||||
@@ -10,49 +10,45 @@ import {
|
||||
} from '../actions'
|
||||
|
||||
function toggleFetchingDomain(uiState, action) {
|
||||
return Object.assign({}, uiState, {
|
||||
flags: Object.assign({}, uiState.flags, {
|
||||
return {
|
||||
...uiState,
|
||||
flags: {
|
||||
...uiState.flags,
|
||||
isFetchingDomain: !uiState.flags.isFetchingDomain
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function toggleFetchingEvents(uiState, action) {
|
||||
return Object.assign({}, uiState, {
|
||||
flags: Object.assign({}, uiState.flags, {
|
||||
isFetchingEvents: !uiState.flags.isFetchingEvents
|
||||
})
|
||||
});
|
||||
function toggleFetchingSources(uiState, action) {
|
||||
return {
|
||||
...uiState,
|
||||
flags: {
|
||||
...uiState.flags,
|
||||
isFetchingSources: !uiState.flags.isFetchingSources
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function toggleInfoPopup(uiState, action) {
|
||||
return Object.assign({}, uiState, {
|
||||
flags: Object.assign({}, uiState.flags, {
|
||||
return {
|
||||
...uiState,
|
||||
flags: {
|
||||
...uiState.flags,
|
||||
isInfopopup: !uiState.flags.isInfopopup
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
function toggleNotifications(uiState, action) {
|
||||
return Object.assign({}, uiState, {
|
||||
flags: Object.assign({}, uiState.flags, {
|
||||
isNotification: !uiState.flags.isNotification
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function ui(uiState = initial.ui, action) {
|
||||
switch (action.type) {
|
||||
case TOGGLE_FETCHING_DOMAIN:
|
||||
return toggleFetchingDomain(uiState, action);
|
||||
case TOGGLE_FETCHING_EVENTS:
|
||||
return toggleFetchingEvents(uiState, action);
|
||||
return toggleFetchingDomain(uiState, action)
|
||||
case TOGGLE_FETCHING_SOURCES:
|
||||
return toggleFetchingSources(uiState, action)
|
||||
case TOGGLE_INFOPOPUP:
|
||||
return toggleInfoPopup(uiState, action);
|
||||
case TOGGLE_NOTIFICATIONS:
|
||||
return toggleNotifications(uiState, action);
|
||||
return toggleInfoPopup(uiState, action)
|
||||
default:
|
||||
return uiState;
|
||||
return uiState
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -52,7 +52,7 @@ function validateTree (node, parent, set, duplicates) {
|
||||
/*
|
||||
* Validate domain schema
|
||||
*/
|
||||
export function validate(domain) {
|
||||
export function validateDomain (domain) {
|
||||
const sanitizedDomain = {
|
||||
events: [],
|
||||
categories: [],
|
||||
|
||||
@@ -30,8 +30,8 @@ const initial = {
|
||||
selected: [],
|
||||
filters: {
|
||||
timerange: [
|
||||
d3.timeParse("%Y-%m-%dT%H:%M:%S")("2014-08-22T12:00:00"),
|
||||
d3.timeParse("%Y-%m-%dT%H:%M:%S")("2014-08-27T12:00:00")
|
||||
d3.timeParse("%Y-%m-%dT%H:%M:%S")("2013-02-23T12:00:00"),
|
||||
d3.timeParse("%Y-%m-%dT%H:%M:%S")("2016-02-23T12:00:00")
|
||||
],
|
||||
tags: [],
|
||||
categories: [],
|
||||
@@ -59,7 +59,7 @@ const initial = {
|
||||
{
|
||||
label: '3 días',
|
||||
duration: 4320,
|
||||
active: true
|
||||
active: false
|
||||
},
|
||||
{
|
||||
label: '12 horas',
|
||||
@@ -120,7 +120,7 @@ const initial = {
|
||||
narratives: {
|
||||
default: {
|
||||
style: 'dotted', // ['dotted', 'solid']
|
||||
opacity: 0.4, // range between 0 and 1
|
||||
opacity: 0.9, // range between 0 and 1
|
||||
stroke: 'red', // Any hex or rgb code
|
||||
strokeWidth: 2
|
||||
},
|
||||
@@ -139,11 +139,10 @@ const initial = {
|
||||
},
|
||||
flags: {
|
||||
isFetchingDomain: false,
|
||||
isFetchingEvents: false,
|
||||
isFetchingSources: false,
|
||||
|
||||
isCardstack: true,
|
||||
isInfopopup: false,
|
||||
isNotification: true
|
||||
isInfopopup: false
|
||||
},
|
||||
tools: {
|
||||
formatter: d3.timeFormat("%d %b, %H:%M"),
|
||||
|
||||
Reference in New Issue
Block a user