Clean master commit

This commit is contained in:
Franc FC
2018-10-31 14:11:03 -04:00
parent 59aa005a64
commit 92e03fdb07
69 changed files with 12939 additions and 0 deletions

88
src/reducers/app.js Normal file
View File

@@ -0,0 +1,88 @@
import initial from '../store/initial.js';
import {
UPDATE_HIGHLIGHTED,
UPDATE_SELECTED,
UPDATE_FILTERS,
UPDATE_TIMERANGE,
RESET_ALLFILTERS,
TOGGLE_LANGUAGE,
FETCH_ERROR,
} from '../actions';
function updateHighlighted(appState, action) {
return Object.assign({}, appState, {
highlighted: action.highlighted
});
}
function updateSelected(appState, action) {
return Object.assign({}, appState, {
selected: action.selected
});
}
function updateFilters(appState, action) { // XXX
return Object.assign({}, appState, {
filters: Object.assign({}, appState.filters, action.filters)
});
}
function updateTimeRange(appState, action) { // XXX
return Object.assign({}, appState, {
filters: Object.assign({}, appState.filters, action.range),
});
}
function resetAllFilters(appState) { // XXX
return Object.assign({}, appState, {
filters: Object.assign({}, appState.filters, {
tags: [],
categories: [],
range: [
d3.timeParse("%Y-%m-%dT%H:%M:%S")("2014-09-25T12:00:00"),
d3.timeParse("%Y-%m-%dT%H:%M:%S")("2014-09-28T12:00:00")
],
}),
selected: [],
});
}
function toggleLanguage(appState, action) {
let otherLanguage = (appState.language === 'es-MX') ? 'en-US' : 'es-MX';
return Object.assign({}, appState, {
language: action.language || otherLanguage
});
}
function fetchError(state, action) {
return {
...state,
error: action.message,
notifications: [{ type: 'error', message: action.message }]
}
}
function app(appState = initial.app, action) {
switch (action.type) {
case UPDATE_HIGHLIGHTED:
return updateHighlighted(appState, action);
case UPDATE_SELECTED:
return updateSelected(appState, action);
case UPDATE_FILTERS:
return updateFilters(appState, action);
case UPDATE_TIMERANGE:
return updateTimeRange(appState, action);
case RESET_ALLFILTERS:
return resetAllFilters(appState, action);
case TOGGLE_LANGUAGE:
return toggleLanguage(appState, action);
case FETCH_ERROR:
return fetchError(appState, action);
default:
return appState;
}
}
export default app;

25
src/reducers/domain.js Normal file
View File

@@ -0,0 +1,25 @@
import initial from '../store/initial.js';
import {
UPDATE_DOMAIN,
} from '../actions';
import { parseDateTimes } from './utils/helpers.js';
import { validate } from './utils/validators.js';
function updateDomain(domainState, action) {
action.domain.events = parseDateTimes(action.domain.events);
return Object.assign({}, domainState, validate(action.domain));
}
function domain(domainState = initial.domain, action) {
switch (action.type) {
case UPDATE_DOMAIN:
return updateDomain(domainState, action);
default:
return domainState;
}
}
export default domain;

13
src/reducers/index.js Normal file
View File

@@ -0,0 +1,13 @@
import {
combineReducers
} from 'redux'
import domain from './domain.js'
import app from './app.js'
import ui from './ui.js'
export default combineReducers({
app,
domain,
ui
});;

View File

@@ -0,0 +1,12 @@
import Joi from 'joi';
const categorySchema = Joi.object().keys({
category: Joi.string().required(),
category_label: Joi.string().allow('').required(),
group: Joi.string(),
group_label: Joi.string(),
});
const optionalSchema = categorySchema.optionalKeys('group', 'group_label');
export default categorySchema;

View File

@@ -0,0 +1,20 @@
import Joi from 'joi';
const eventSchema = Joi.object().keys({
id: Joi.string().required(),
description: Joi.string().allow('').required(),
date: Joi.string().required(),
time: Joi.string().required(),
time_precision: Joi.string().allow(''),
location: Joi.string().allow('').required(),
latitude: Joi.string().required(),
longitude: Joi.string().required(),
type: Joi.string().allow(''),
category: Joi.string().required(),
source: Joi.string().allow(''),
tags: Joi.string().allow(''),
comments: Joi.string().allow(''),
timestamp: Joi.string().required(),
});
export default eventSchema;

View File

@@ -0,0 +1,11 @@
import Joi from 'joi';
const siteSchema = Joi.object().keys({
id: Joi.string().required(),
description: Joi.string().allow('').required(),
site: Joi.string().required(),
latitude: Joi.string().required(),
longitude: Joi.string().required()
});
export default siteSchema;

104
src/reducers/ui.js Normal file
View File

@@ -0,0 +1,104 @@
import initial from '../store/initial.js';
import {
TOGGLE_FETCHING_DOMAIN,
TOGGLE_FETCHING_EVENTS,
TOGGLE_VIEW,
TOGGLE_TIMELINE,
OPEN_CABINET,
CLOSE_CABINET,
TOGGLE_INFOPOPUP,
TOGGLE_NOTIFICATIONS
} from '../actions'
function toggleFetchingDomain(uiState, action) {
return Object.assign({}, uiState, {
flags: Object.assign({}, uiState.flags, {
isFetchingDomain: !uiState.flags.isFetchingDomain
})
});
}
function toggleFetchingEvents(uiState, action) {
return Object.assign({}, uiState, {
flags: Object.assign({}, uiState.flags, {
isFetchingEvents: !uiState.flags.isFetchingEvents
})
});
}
function toggleView(uiState, action) {
return Object.assign({}, uiState, {
flags: Object.assign({}, uiState.flags, {
isView2d: !uiState.flags.isView2d
})
});
}
function toggleTimeline(uiState, action) {
return Object.assign({}, uiState, {
flags: Object.assign({}, uiState.flags, {
isTimeline: !uiState.flags.isTimeline
})
});
}
function closeCabinet(uiState, action) {
return Object.assign({}, uiState, {
flags: Object.assign({}, uiState.flags, {
isCabinet: false
})
});
}
function openCabinet(uiState, action) {
return Object.assign({}, uiState, {
flags: Object.assign({}, uiState.flags, {
isCabinet: true
}),
components: Object.assign({}, uiState.components, {
cabinetFileTab: action.tabNum,
})
});
}
function toggleInfoPopup(uiState, action) {
return Object.assign({}, uiState, {
flags: Object.assign({}, 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);
case TOGGLE_VIEW:
return toggleView(uiState, action);
case TOGGLE_TIMELINE:
return toggleTimeline(uiState, action);
case OPEN_CABINET:
return openCabinet(uiState, action);
case CLOSE_CABINET:
return closeCabinet(uiState, action);
case TOGGLE_INFOPOPUP:
return toggleInfoPopup(uiState, action);
case TOGGLE_NOTIFICATIONS:
return toggleNotifications(uiState, action);
default:
return uiState;
}
}
export default ui;

View File

@@ -0,0 +1,18 @@
export function parseDateTimes(arrayToParse) {
const parsedArray = [];
arrayToParse.forEach(item => {
let incoming_datetime = `${item.date}T00:00`;
if (item.time) incoming_datetime = `${item.date}T${item.time}`;
const parser = d3.timeParse(process.env.INCOMING_DATETIME_FORMAT);
item.timestamp = d3.timeFormat("%Y-%m-%dT%H:%M:%S")(parser(incoming_datetime));
parsedArray.push(item);
});
return parsedArray;
}
export function capitalize(string) {
return string.charAt(0).toUpperCase() + string.slice(1);
}

View File

@@ -0,0 +1,75 @@
import Joi from 'joi';
import eventSchema from '../schema/eventSchema.js';
import categorySchema from '../schema/categorySchema.js';
import siteSchema from '../schema/siteSchema.js';
import { capitalize } from './helpers.js';
/*
* Create an error notification object
* Types: ['error', 'warning', 'good', 'neural']
*/
function makeError(type, id, message) {
return {
type: 'error',
id,
message: `${type} ${id}: ${message}`
}
}
/*
* Validate domain schema
*/
export function validate(domain) {
const sanitizedDomain = {
events: [],
categories: [],
sites: [],
notifications: domain.notifications,
tags: domain.tags
}
const discardedDomain = {
events: [],
categories: [],
sites: []
}
function validateItem(item, domainClass, schema) {
const result = Joi.validate(item, schema);
if (result.error !== null) {
const id = item.id || '-';
const domainStr = capitalize(domainClass);
const error = makeError(domainStr, id, result.error.message);
discardedDomain[domainClass].push(Object.assign(item, { error }));
} else {
sanitizedDomain[domainClass].push(item);
}
}
domain.events.forEach(event => {
validateItem(event, 'events', eventSchema);
});
domain.categories.forEach(category => {
validateItem(category, 'categories', categorySchema);
});
domain.sites.forEach(site => {
validateItem(site, 'sites', siteSchema);
});
// Message the number of failed items
Object.keys(discardedDomain).forEach(disc => {
const len = discardedDomain[disc].length;
if (len) {
sanitizedDomain.notifications.push({
message: `${len} invalid ${disc} not displayed.`,
items: discardedDomain[disc],
type: 'error'
});
}
})
return sanitizedDomain;
}