diff --git a/src/actions/index.js b/src/actions/index.js index cad3fa1..c2f6041 100644 --- a/src/actions/index.js +++ b/src/actions/index.js @@ -1,12 +1,14 @@ import { urlFromEnv } from '../js/utilities' -const EVENT_DATA_URL = urlFromEnv('EVENT_EXT'); -const CATEGORY_URL = urlFromEnv('CATEGORY_EXT'); -const TAGS_URL = urlFromEnv('TAGS_EXT'); -const SOURCES_URL = urlFromEnv('SOURCES_EXT'); -const NARRATIVE_URL = urlFromEnv('NARRATIVE_EXT'); -const SITES_URL = urlFromEnv('SITES_EXT'); -const eventUrlMap = (event) => `${process.env.SERVER_ROOT}${process.env.EVENT_DESC_ROOT}/${(event.id) ? event.id : event}`; +// TODO: relegate these URLs entirely to environment variables +const EVENT_DATA_URL = urlFromEnv('EVENT_EXT') +const CATEGORY_URL = urlFromEnv('CATEGORY_EXT') +const TAGS_URL = urlFromEnv('TAGS_EXT') +const SOURCES_URL = urlFromEnv('SOURCES_EXT') +const NARRATIVE_URL = urlFromEnv('NARRATIVE_EXT') +const SITES_URL = urlFromEnv('SITES_EXT') +const SHAPES_URL = urlFromEnv('SHAPES_EXT') +const eventUrlMap = (event) => `${process.env.SERVER_ROOT}${process.env.EVENT_DESC_ROOT}/${(event.id) ? event.id : event}` const domainMsg = (domainType) => `Something went wrong fetching ${domainType}. Check the URL or try disabling them in the config file.` @@ -67,13 +69,21 @@ export function fetchDomain () { } } + let shapesPromise = Promise.resolve([]) + if (process.env.features.USE_SHAPES) { + shapesPromise = fetch(SHAPES_URL) + .then(response => response.json()) + .catch(() => handleError(domainMsg('shapes'))) + } + return Promise.all([ eventPromise, catPromise, narPromise, sitesPromise, tagsPromise, - sourcesPromise + sourcesPromise, + shapesPromise ]) .then(response => { const result = { @@ -83,6 +93,7 @@ export function fetchDomain () { sites: response[3], tags: response[4], sources: response[5], + shapes: response[6], notifications } if (Object.values(result).some(resp => resp.hasOwnProperty('error'))) { @@ -96,7 +107,7 @@ export function fetchDomain () { // TODO: handle this appropriately in React hierarchy alert(err.message) }) - }; + } } export const FETCH_ERROR = 'FETCH_ERROR' @@ -189,7 +200,7 @@ export function updateTimeRange(timerange) { } } -export const UPDATE_NARRATIVE = 'UPDATE_NARRATIVE'; +export const UPDATE_NARRATIVE = 'UPDATE_NARRATIVE' export function updateNarrative(narrative) { return { type: UPDATE_NARRATIVE, @@ -197,14 +208,14 @@ export function updateNarrative(narrative) { } } -export const INCREMENT_NARRATIVE_CURRENT = 'INCREMENT_NARRATIVE_CURRENT'; +export const INCREMENT_NARRATIVE_CURRENT = 'INCREMENT_NARRATIVE_CURRENT' export function incrementNarrativeCurrent() { return { type: INCREMENT_NARRATIVE_CURRENT } } -export const DECREMENT_NARRATIVE_CURRENT = 'DECREMENT_NARRATIVE_CURRENT'; +export const DECREMENT_NARRATIVE_CURRENT = 'DECREMENT_NARRATIVE_CURRENT' export function decrementNarrativeCurrent() { return { type: DECREMENT_NARRATIVE_CURRENT @@ -249,7 +260,7 @@ export function toggleFetchingSources() { } } -export const TOGGLE_LANGUAGE = 'TOGGLE_LANGUAGE'; +export const TOGGLE_LANGUAGE = 'TOGGLE_LANGUAGE' export function toggleLanguage(language) { return { type: TOGGLE_LANGUAGE, @@ -257,21 +268,21 @@ export function toggleLanguage(language) { } } -export const CLOSE_TOOLBAR = 'CLOSE_TOOLBAR'; +export const CLOSE_TOOLBAR = 'CLOSE_TOOLBAR' export function closeToolbar() { return { type: CLOSE_TOOLBAR } } -export const TOGGLE_INFOPOPUP = 'TOGGLE_INFOPOPUP'; +export const TOGGLE_INFOPOPUP = 'TOGGLE_INFOPOPUP' export function toggleInfoPopup() { return { type: TOGGLE_INFOPOPUP } } -export const TOGGLE_MAPVIEW = 'TOGGLE_MAPVIEW'; +export const TOGGLE_MAPVIEW = 'TOGGLE_MAPVIEW' export function toggleMapView(layer) { return { type: TOGGLE_MAPVIEW, diff --git a/src/reducers/schema/shapeSchema.js b/src/reducers/schema/shapeSchema.js new file mode 100644 index 0000000..d02079f --- /dev/null +++ b/src/reducers/schema/shapeSchema.js @@ -0,0 +1,8 @@ +import Joi from 'joi' + +const shapeSchema = Joi.object().keys({ + name: Joi.string().required(), + items: Joi.array().required() +}) + +export default shapeSchema diff --git a/src/reducers/utils/validators.js b/src/reducers/utils/validators.js index 42bf3d3..f52f909 100644 --- a/src/reducers/utils/validators.js +++ b/src/reducers/utils/validators.js @@ -1,12 +1,13 @@ -import Joi from 'joi'; +import Joi from 'joi' -import eventSchema from '../schema/eventSchema'; -import categorySchema from '../schema/categorySchema'; -import siteSchema from '../schema/siteSchema'; -import narrativeSchema from '../schema/narrativeSchema'; +import eventSchema from '../schema/eventSchema' +import categorySchema from '../schema/categorySchema' +import siteSchema from '../schema/siteSchema' +import narrativeSchema from '../schema/narrativeSchema' import sourceSchema from '../schema/sourceSchema' +import shapeSchema from '../schema/shapeSchema' -import { capitalize } from './helpers.js'; +import { capitalize } from './helpers.js' /* * Create an error notification object @@ -21,8 +22,8 @@ function makeError(type, id, message) { } -const isLeaf = node => (Object.keys(node.children).length === 0); -const isDuplicate = (node, set) => { return (set.has(node.key)); }; +const isLeaf = node => (Object.keys(node.children).length === 0) +const isDuplicate = (node, set) => { return (set.has(node.key)) } /* @@ -61,8 +62,9 @@ export function validateDomain (domain) { sites: [], narratives: [], sources: {}, + tags: {}, + shapes: [], notifications: domain.notifications, - tags: {} } const discardedDomain = { @@ -71,18 +73,19 @@ export function validateDomain (domain) { sites: [], narratives: [], sources: [], + shapes: [] } function validateArrayItem(item, domainKey, schema) { - const result = Joi.validate(item, schema); + const result = Joi.validate(item, schema) if (result.error !== null) { - const id = item.id || '-'; - const domainStr = capitalize(domainKey); - const error = makeError(domainStr, id, result.error.message); + const id = item.id || '-' + const domainStr = capitalize(domainKey) + const error = makeError(domainStr, id, result.error.message) - discardedDomain[domainKey].push(Object.assign(item, { error })); + discardedDomain[domainKey].push(Object.assign(item, { error })) } else { - sanitizedDomain[domainKey].push(item); + sanitizedDomain[domainKey].push(item) } } @@ -109,29 +112,46 @@ export function validateDomain (domain) { }) } - validateArray(domain.events, 'events', eventSchema); - validateArray(domain.categories, 'categories', categorySchema); - validateArray(domain.sites, 'sites', siteSchema); - validateArray(domain.narratives, 'narratives', narrativeSchema); - validateObject(domain.sources, 'sources', sourceSchema); + validateArray(domain.events, 'events', eventSchema) + validateArray(domain.categories, 'categories', categorySchema) + validateArray(domain.sites, 'sites', siteSchema) + validateArray(domain.narratives, 'narratives', narrativeSchema) + validateObject(domain.sources, 'sources', sourceSchema) + validateObject(domain.shapes, 'shapes', shapeSchema) + + sanitizedDomain.shapes = sanitizedDomain.shapes.map(shape => { + const points = shape.items.map(coords => { + const _coords = coords.replace(/\s/g, '').split(',') + return { + lat: parseFloat(_coords[0]), + lon: parseFloat(_coords[1]) + } + }) + return { + name: shape.name, + points + } + }) + + console.log(sanitizedDomain) // Message the number of failed items in domain Object.keys(discardedDomain).forEach(disc => { - const len = discardedDomain[disc].length; + const len = discardedDomain[disc].length if (len) { sanitizedDomain.notifications.push({ message: `${len} invalid ${disc} not displayed.`, items: discardedDomain[disc], type: 'error' - }); + }) } - }); + }) // Validate uniqueness of tags - const tagSet = new Set([]); - const duplicateTags = []; - validateTree(domain.tags, {}, tagSet, duplicateTags); + const tagSet = new Set([]) + const duplicateTags = [] + validateTree(domain.tags, {}, tagSet, duplicateTags) // Duplicated tags if (duplicateTags.length > 0) { @@ -139,9 +159,9 @@ export function validateDomain (domain) { message: `Tags are required to be unique. Ignoring duplicates for now.`, items: duplicateTags, type: 'error' - }); + }) } - sanitizedDomain.tags = domain.tags; + sanitizedDomain.tags = domain.tags - return sanitizedDomain; + return sanitizedDomain }