mirror of
https://github.com/bellingcat/ukraine-timemap.git
synced 2026-06-12 13:28:36 +03:00
load shape data from ext
This commit is contained in:
@@ -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,
|
||||
|
||||
8
src/reducers/schema/shapeSchema.js
Normal file
8
src/reducers/schema/shapeSchema.js
Normal file
@@ -0,0 +1,8 @@
|
||||
import Joi from 'joi'
|
||||
|
||||
const shapeSchema = Joi.object().keys({
|
||||
name: Joi.string().required(),
|
||||
items: Joi.array().required()
|
||||
})
|
||||
|
||||
export default shapeSchema
|
||||
@@ -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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user