diff --git a/src/map/prepareLayer.js b/src/map/prepareLayer.js index d5b0a054..821387ed 100644 --- a/src/map/prepareLayer.js +++ b/src/map/prepareLayer.js @@ -2,11 +2,10 @@ import Mustache from 'mustache'; import cloneDeep from 'lodash.clonedeep'; import superset from '@onaio/superset-connector'; -import { hint } from '@mapbox/geojsonhint'; import csvToGEOjson from './csvToGEOjson'; import aggregateFormData from '../connectors/ona-api/aggregateFormData'; import getData from '../connectors/ona-api/data'; -import { loadJSON, loadCSV } from '../utils/files'; +import { loadCSV } from '../utils/files'; import { generateFilterOptions, processFilters, generateFilterOptionsPrev } from '../utils/filters'; import { requestData, receiveData, getCurrentState } from '../store/actions/actions'; import parseData from './../utils/parseData'; @@ -209,465 +208,6 @@ export function renderData(mapId, layer, dispatch, doUpdateTsLayer) { } } -/** - * Loads layer data from CSV or GeoJSON source - */ -function readData(mapId, layer, dispatch, doUpdateTsLayer) { - const layerObj = { ...layer }; - const sourceURL = layer.source.data; - const fileType = - typeof layer.source.data === 'string' - ? sourceURL.split('.').pop() - : typeof sourceURL === 'object' && sourceURL !== null && sourceURL.type; - if (fileType === 'csv') { - loadCSV(layerObj.source.data, data => { - if (!data) return; - - let parsedData; - if (layerObj.source.type === 'geojson') { - parsedData = csvToGEOjson(layerObj, data); - } else if (layerObj['data-parse']) { - parsedData = parseData(layerObj['data-parse'], data); - } else { - parsedData = data; - } - const activeData = parsedData.features || parsedData; - const filteredData = activeData.filter(d => (d.properties || d)[layer.property] !== 'n/a'); - - if (Array.isArray(parsedData)) { - layerObj.source.data = [...filteredData]; - } else { - parsedData.features = [...filteredData]; - layerObj.source.data = { ...parsedData }; - } - - layerObj.mergedData = filteredData; - if (layerObj.aggregate && layerObj.aggregate.filter) { - if (layerObj.layers) { - const currentState = dispatch(getCurrentState()); - layerObj.layers.forEach(sublayer => { - const subLayer = currentState.MAP.layers[sublayer]; - subLayer.filterOptions = generateFilterOptions(subLayer); - }); - } - layerObj.filterOptions = layerObj.aggregate.filterIsPrev - ? generateFilterOptionsPrev(layerObj) - : generateFilterOptions(layerObj); - } - - if (layerObj.aggregate && layerObj.aggregate.type) { - layerObj.source.data = aggregateFormData(layerObj); - } - renderData(mapId, layerObj, dispatch, doUpdateTsLayer); - }); - } - if (fileType === 'geojson') { - const path = - typeof layerObj.source.data === 'string' ? layerObj.source.data : layerObj.source.data.url; - loadJSON(path, data => { - if (layerObj['data-parse']) { - layerObj.source.data = { - ...data, - features: parseData(layerObj['data-parse'], data.features), - }; - } else { - layerObj.source.data = data; - } - if (layerObj.aggregate && layerObj.aggregate.type) { - layerObj.source.data = aggregateFormData(layerObj); - } - if (layerObj.aggregate && layerObj.aggregate.filter) { - layerObj.filterOptions = generateFilterOptions(layerObj); - } - renderData(mapId, layerObj, dispatch, doUpdateTsLayer); - }); - } - if (fileType === 'stringified-geojson') { - if (layerObj['data-parse']) { - layerObj.source.data = { - ...JSON.parse(sourceURL.data), - features: parseData(layerObj['data-parse'], JSON.parse(sourceURL.data).features), - }; - } else { - layerObj.source.data = JSON.parse(sourceURL.data); - } - if (layerObj.aggregate && layerObj.aggregate.type) { - layerObj.source.data = aggregateFormData(layerObj); - } - if (layerObj.aggregate && layerObj.aggregate.filter) { - layerObj.filterOptions = generateFilterOptions(layerObj); - } - const geojsonErrors = hint(sourceURL.data).filter(e => e.level !== 'message'); - - if (!geojsonErrors || !geojsonErrors.length) { - renderData(mapId, layerObj, dispatch, doUpdateTsLayer); - } else { - /** Todo:Add growl notifications */ - // eslint-disable-next-line no-console - console.warn('geojson hint errors', geojsonErrors); - } - } - if (fileType === 'superset') { - const currentState = dispatch(getCurrentState()); - const config = { - endpoint: 'slice', - extraPath: sourceURL['slice-id'], - base: currentState.APP && currentState.APP.supersetBase, - }; - - superset.api - .doFetch( - config, // fetch with config - res => res - ) // pass in callback func to process response - .then(data => { - let processedData = superset.processData(data); - let parsedData; - if (layerObj['data-parse']) { - processedData = parseData(layerObj['data-parse'], processedData); - } - /** - * Build custom filter - * The custom filter introduces an extra field 'no_of_reports'. - * we depend on the field building the quant chart on the filter - */ - if (layerObj && layerObj.aggregate && layerObj.aggregate.hasCustomFilter) { - const uniqueFacilities = [ - ...new Set(processedData.map(facility => facility.facility_id)), - ]; - const reportsPerFacility = {}; - uniqueFacilities.forEach(facility => { - reportsPerFacility[facility] = processedData - .filter(facilityData => facilityData.facility_id === facility) - .map(d => d.reporting_period); - }); - processedData.forEach(pdata => { - if ( - reportsPerFacility[pdata.facility_id] && - reportsPerFacility[pdata.facility_id].length - ) { - pdata.no_of_reports = reportsPerFacility[pdata.facility_id].length; - } else { - pdata.no_of_reports = '0'; - } - }); - } - if (layerObj.source.type === 'geojson') { - parsedData = csvToGEOjson(layerObj, processedData); - if (layerObj.hideZeroVals) { - parsedData = { - type: 'FeatureCollection', - features: parsedData.features.filter(d => d.properties[layerObj.property] !== 0), - }; - } - } else { - parsedData = [...processedData]; - } - - layerObj.source.data = Array.isArray(parsedData) ? [...parsedData] : { ...parsedData }; - - layerObj.mergedData = layerObj.source.data; - - if (layerObj.aggregate && layerObj.aggregate.type) { - layerObj.source.data = aggregateFormData(layerObj, currentState.LOCATIONS); - } - if (layerObj.aggregate && layerObj.aggregate.filter) { - layerObj.filterOptions = generateFilterOptions(layerObj); - } - return renderData(mapId, layerObj, dispatch, doUpdateTsLayer); // call renderData - }); - } -} - -/** - * Loads layer data from multiple CSV or GeoJSON files - * @param {*} layer - * @param {*} dispatch - */ -export function fetchMultipleSources(mapId, layer, dispatch) { - const layerObj = { ...layer }; - const currentState = dispatch(getCurrentState()); - const { APP } = currentState; - let q = d3.queue(); - - const filePaths = layerObj.source.data; - filePaths.forEach(filePath => { - if (Number.isInteger(filePath)) { - q = q.defer(getData, filePath, layerObj.properties, APP); - } else if (typeof filePath === 'object' && filePath !== null && filePath.type) { - // add in SUPERSET.API promise to q.defer - switch (filePath.type) { - case 'superset': { - const config = { - endpoint: 'slice', - extraPath: filePath['slice-id'], - base: APP.supersetBase, - }; - q.defer(superset.api.deferedFetch, config, superset.processData); - break; - } - case 'csv': { - q.defer(d3.csv, filePath.url); - break; - } - case 'json': - case 'geojson': { - q.defer(d3.json, filePath.url); - break; - } - default: { - break; - } - } - } else if (typeof filePath === 'string') q = q.defer(d3.csv, filePath); - }); - - q.awaitAll((error, Data) => { - // parse all data if layer has data parsing spec - const data = !layerObj['data-parse'] - ? [...Data] - : Data.map(D => { - if (Array.isArray(D.features)) { - return { - ...D, - features: parseData(layerObj['data-parse'], D.features), - }; - } - return parseData(layerObj['data-parse'], D); - }); - const { join, relation, type } = layerObj.source; - const isManyToOne = relation && relation.type === 'many-to-one'; - const isOneToMany = relation && relation.type === 'one-to-many'; - const isOneToOne = relation && relation.type === 'one-to-one'; - const isVectorLayer = type === 'vector'; - - let mergedData; - - if (isManyToOne) { - mergedData = {}; - } else { - mergedData = [].concat(...data); - } - - // Filter base data for missing join properties - const intialFilter = d => { - if (!Array.isArray(join[isVectorLayer ? 1 : 0])) { - return typeof d[join[isVectorLayer ? 1 : 0]] !== 'undefined'; - } - for (let j = 0; j < join[isVectorLayer ? 1 : 0].length; j += 1) { - if (typeof d[join[isVectorLayer ? 1 : 0][j]] !== 'undefined') { - return true; - } - } - return false; - }; - - if (Array.isArray(mergedData) && !layerObj['merge-locations']) { - mergedData = mergedData.filter(d => d[layerObj.property] !== null).filter(intialFilter); - } else if (Array.isArray(mergedData.features)) { - mergedData.features = mergedData.features - .filter(d => d[layerObj.property] !== undefined) - .filter(intialFilter); - } - - // Helper func for combining arrays of data - function basicMerge(i, prevData, nextData) { - // Helper func to check nextData datum for single or multiple join props - const basicMergeFilter = d => { - if (!Array.isArray(join[i])) return typeof d[join[i]] !== 'undefined'; - for (let j = 0; j < join[i].length; j += 1) { - if (typeof d[join[i][j]] !== 'undefined') return true; - } - return false; - }; - - if (!nextData || typeof nextData === 'string') { - return { ...prevData }; - } else if (Array.isArray(prevData) && Array.isArray(data[i])) { - return [...prevData, ...data[i].filter(basicMergeFilter)]; - } else if (Array.isArray(prevData) && Array.isArray(data[i].features)) { - return [...prevData, ...data[i].features.filter(basicMergeFilter)]; - } else if (prevData.features && Array.isArray(prevData.features)) { - return { - ...prevData, - features: [ - ...prevData.features, - ...(data[i].features || data[i]).filter(d => typeof d[join[i]] !== 'undefined'), - ], - }; - } - return { ...prevData }; - } - - // Helper func for joining "manys" to "ones" - function manyToOneMerge(i, PrevData, NextData, customFilter) { - const prevData = PrevData; - const nextData = NextData.features || NextData; - let datum; - let joinProp; - for (let d = 0; d < nextData.length; d += 1) { - datum = nextData[d].properties || nextData[d]; - if (Array.isArray(join[i])) { - for (let j = 0; j < join[i].length; j += 1) { - joinProp = typeof datum[join[i][j]] !== 'undefined' ? join[i][j] : null; - if (joinProp) break; - } - } else { - joinProp = join[i]; - } - - if (relation.key[i] === 'one' && datum[joinProp] && prevData[datum[joinProp]]) { - // Merge unique "one" properties from and datum onto prevData[oneId] - prevData[datum[joinProp]] = { - ...prevData[datum[joinProp]], - ...datum, - }; - } else if (relation.key[i] === 'one' && datum[joinProp]) { - // Add unique "one"s to mergedData - prevData[datum[joinProp]] = { ...datum }; - prevData[datum[joinProp]][relation['many-prop'] || 'many'] = []; - if (customFilter) { - prevData[datum[joinProp]].no_of_reports = '0'; - } - } else if (datum[joinProp] && prevData[datum[joinProp]]) { - // Add non-unique "many" to corresponding "one" - datum = { ...datum }; - prevData[datum[joinProp]][relation['many-prop'] || 'many'].push(datum); - if (customFilter) { - prevData[datum[joinProp]].no_of_reports = prevData[datum[joinProp]][ - relation['many-prop'] || 'many' - ].length.toString(); - } - } - } - return { ...prevData }; - } - - // Helper func for joining "ones" to "manys" - function oneToManyMerge(i, PrevData, NextData) { - let prevData = PrevData; - const nextData = NextData.features || NextData; - const j = relation.key.indexOf('many'); // first instance of 'many' - let datum; - let pJoinProp; - let nJoinProp; - - // todo - refactor oneToManyMerge for efficiency and flexibility - // 1) loop through nextData once and build {map} - // 2) map() through prevData once and reference {map} - // 3) reorder everything up front to make sure that all manys exist before mapping ones - - const prevDataMap = pd => { - if (Array.isArray(join[j])) { - for (let k = 0; k < join[j].length; k += 1) { - pJoinProp = typeof pd[join[j][k]] !== 'undefined' ? join[j][k] : null; - if (pJoinProp) break; - } - } else { - pJoinProp = join[j]; - } - return pd[pJoinProp] === datum[nJoinProp] ? { ...pd, ...datum } : pd; - }; - // loop through all next data - for (let d = 0; d < nextData.length; d += 1) { - datum = nextData[d].properties || nextData[d]; - if (Array.isArray(join[i])) { - for (let k = 0; k < join[i].length; k += 1) { - nJoinProp = typeof datum[join[i][k]] !== 'undefined' ? join[i][k] : null; - if (nJoinProp) break; - } - } else { - nJoinProp = join[i]; - } - - // if nextData is another many, add it to the prev data array - if (relation.key[i] === 'many' && datum[nJoinProp] && Array.isArray(prevData)) { - prevData = [...prevData, ...(nextData.features || nextData)]; - // if nextData is one, map it to existing manys in prevData - } else if (relation.key[i] === 'one' && datum[nJoinProp] && Array.isArray(prevData)) { - prevData = j !== -1 ? prevData.map(prevDataMap) : prevData; - } - } - return Array.isArray(prevData) ? [...prevData] : { ...prevData }; - } - - // Helper function to flatten multiple data sources - function oneToOneMerge(i, PrevData, NextData) { - const prevData = PrevData; - const nextData = NextData.features || NextData; - const mergeData = []; - let prevDatum; - let matchDatum; - const findMatch = datum => datum[join[i]] === prevDatum[join[0]]; - // Loop through all previous datum - for (let d = 0; d < prevData.length; d += 1) { - prevDatum = prevData[d]; - matchDatum = nextData.find(findMatch); - // merge datum if a match is found, push datum to mergeData - if (matchDatum) { - mergeData.push({ - ...prevDatum, - ...matchDatum, - }); - } else { - mergeData.push({ ...prevDatum }); - } - } - return mergeData; - } - - // loop through remaining data to basic join with merged data - for (let i = isManyToOne ? 0 : 1; i < data.length; i += 1) { - if (!relation) { - mergedData = basicMerge(i, mergedData, data[i]); - } else if (isManyToOne) { - const hasCustomFilter = - layerObj && layerObj.aggregate && layerObj.aggregate.hasCustomFilter; - - mergedData = manyToOneMerge( - isVectorLayer ? i + 1 : i, - mergedData, - data[i], - hasCustomFilter - ); - } else if (isOneToMany) { - mergedData = oneToManyMerge(isVectorLayer ? i + 1 : i, mergedData, data[i]); - } else if (isOneToOne) { - mergedData = oneToOneMerge(i, mergedData, data[i]); - } - } - - if (isManyToOne) { - layerObj.joinedData = { ...mergedData }; - mergedData = Object.keys(mergedData).map(jd => ({ - ...layerObj.joinedData[jd], - })); - if (layerObj.property) { - mergedData = mergedData.filter(d => d[layerObj.property]); - } - // .filter(jd => jd.reports.length); - } - - // convert to geojson format if necessary - if (layerObj.source.type === 'geojson' && !mergedData.features) { - mergedData = csvToGEOjson(layerObj, mergedData); - } - layerObj.mergedData = Array.isArray(mergedData) ? [...mergedData] : { ...mergedData }; - - if (layerObj.aggregate && layerObj.aggregate.filter) { - layerObj.filterOptions = layerObj.aggregate.filterIsPrev - ? generateFilterOptionsPrev(layerObj) - : generateFilterOptions(layerObj); - } - layerObj.source.data = - layerObj.aggregate && layerObj.aggregate.type - ? aggregateFormData(layerObj, currentState.LOCATIONS, layerObj.filterOptions || false) - : mergedData; - layerObj.loaded = true; - renderData(mapId, layerObj, dispatch); - }); -} - /** * Proceses MapSpec layer and adds it to redux state. * @param {*} layer diff --git a/src/utils/fetchMultipleSourceData.js b/src/utils/fetchMultipleSourceData.js index ac28fb76..a282bf76 100644 --- a/src/utils/fetchMultipleSourceData.js +++ b/src/utils/fetchMultipleSourceData.js @@ -72,7 +72,7 @@ export default function fetchMultipleSources(mapId, layer, dispatch) { let mergedData = isManyToOne ? {} - : (Array.isArray(data[0]) && [...data[0]]) || { ...data[0] }; + : [].concat(...data); // Filter base data for missing join properties const intialFilter = (d) => { @@ -85,13 +85,11 @@ export default function fetchMultipleSources(mapId, layer, dispatch) { return false; }; - if (Array.isArray(mergedData)) { + if (Array.isArray(mergedData) && !layerObj['merge-locations']) { mergedData = mergedData.filter(d => - d[layerObj.property] !== null).filter(intialFilter); } else if (Array.isArray(mergedData.features)) { mergedData.features = mergedData.features.filter(d => - d[layerObj.property] !== undefined).filter(intialFilter); } diff --git a/src/utils/readLayerdata.js b/src/utils/readLayerdata.js index a767c8be..9bc66848 100644 --- a/src/utils/readLayerdata.js +++ b/src/utils/readLayerdata.js @@ -1,8 +1,9 @@ import superset from '@onaio/superset-connector'; +import { hint } from '@mapbox/geojsonhint'; import csvToGEOjson from '../map/csvToGEOjson'; import aggregateFormData from '../connectors/ona-api/aggregateFormData'; import { loadJSON, loadCSV } from '../utils/files'; -import { generateFilterOptions } from '../utils/filters'; +import { generateFilterOptions, generateFilterOptionsPrev } from '../utils/filters'; import parseData from './../utils/parseData'; import {renderData} from '../map/prepareLayer' import { getCurrentState } from '../store/actions/actions'; @@ -16,7 +17,8 @@ export default function readData(mapId, layer, dispatch, doUpdateTsLayer) { && sourceURL !== null && sourceURL.type); if (fileType === 'csv') { - loadCSV(layerObj.source.data, (data) => { + loadCSV(layerObj.source.data, data => { + if (!data) return; let parsedData; if (layerObj.source.type === 'geojson') { parsedData = csvToGEOjson(layerObj, data); @@ -37,7 +39,16 @@ export default function readData(mapId, layer, dispatch, doUpdateTsLayer) { layerObj.mergedData = filteredData; if (layerObj.aggregate && layerObj.aggregate.filter) { - layerObj.filterOptions = generateFilterOptions(layerObj); + if (layerObj.layers) { + const currentState = dispatch(getCurrentState()); + layerObj.layers.forEach(sublayer => { + const subLayer = currentState.MAP.layers[sublayer]; + subLayer.filterOptions = generateFilterOptions(subLayer); + }); + } + layerObj.filterOptions = layerObj.aggregate.filterIsPrev + ? generateFilterOptionsPrev(layerObj) + : generateFilterOptions(layerObj); } if (layerObj.aggregate && layerObj.aggregate.type) { @@ -50,7 +61,7 @@ export default function readData(mapId, layer, dispatch, doUpdateTsLayer) { const path = typeof layerObj.source.data === 'string' ? layerObj.source.data : layerObj.source.data.url; - loadJSON(path, (data) => { + loadJSON(path, data => { if (layerObj['data-parse']) { layerObj.source.data = { ...data, @@ -83,7 +94,15 @@ export default function readData(mapId, layer, dispatch, doUpdateTsLayer) { if (layerObj.aggregate && layerObj.aggregate.filter) { layerObj.filterOptions = generateFilterOptions(layerObj); } - renderData(mapId, layerObj, dispatch, doUpdateTsLayer); + const geojsonErrors = hint(sourceURL.data).filter(e => e.level !== 'message'); + + if (!geojsonErrors || !geojsonErrors.length) { + renderData(mapId, layerObj, dispatch, doUpdateTsLayer); + } else { + /** Todo:Add growl notifications */ + // eslint-disable-next-line no-console + console.warn('geojson hint errors', geojsonErrors); + } } if (fileType === 'superset') { const currentState = dispatch(getCurrentState()); @@ -98,10 +117,45 @@ export default function readData(mapId, layer, dispatch, doUpdateTsLayer) { res => res, ) // pass in callback func to process response .then((data) => { - const processedData = superset.processData(data); + let processedData = superset.processData(data); let parsedData; + if (layerObj['data-parse']) { + processedData = parseData(layerObj['data-parse'], processedData); + } + /** + * Build custom filter + * The custom filter introduces an extra field 'no_of_reports'. + * we depend on the field building the quant chart on the filter + */ + if (layerObj && layerObj.aggregate && layerObj.aggregate.hasCustomFilter) { + const uniqueFacilities = [ + ...new Set(processedData.map(facility => facility.facility_id)), + ]; + const reportsPerFacility = {}; + uniqueFacilities.forEach(facility => { + reportsPerFacility[facility] = processedData + .filter(facilityData => facilityData.facility_id === facility) + .map(d => d.reporting_period); + }); + processedData.forEach(pdata => { + if ( + reportsPerFacility[pdata.facility_id] && + reportsPerFacility[pdata.facility_id].length + ) { + pdata.no_of_reports = reportsPerFacility[pdata.facility_id].length; + } else { + pdata.no_of_reports = '0'; + } + }); + } if (layerObj.source.type === 'geojson') { parsedData = csvToGEOjson(layerObj, processedData); + if (layerObj.hideZeroVals) { + parsedData = { + type: 'FeatureCollection', + features: parsedData.features.filter(d => d.properties[layerObj.property] !== 0), + }; + } } else { parsedData = [...processedData]; } @@ -109,9 +163,9 @@ export default function readData(mapId, layer, dispatch, doUpdateTsLayer) { layerObj.source.data = Array.isArray(parsedData) ? [...parsedData] : { ...parsedData }; - + layerObj.mergedData = layerObj.source.data; if (layerObj.aggregate && layerObj.aggregate.type) { - layerObj.source.data = aggregateFormData(layerObj); + layerObj.source.data = aggregateFormData(layerObj, currentState.LOCATIONS); } if (layerObj.aggregate && layerObj.aggregate.filter) { layerObj.filterOptions = generateFilterOptions(layerObj); diff --git a/test/fixtures/outputs/generateStops-output.json b/test/fixtures/outputs/generateStops-output.json index e079f69a..46d2f180 100644 --- a/test/fixtures/outputs/generateStops-output.json +++ b/test/fixtures/outputs/generateStops-output.json @@ -28,8 +28,8 @@ ["R1720058", "#bdd7e7"], ["R1720059", "#bdd7e7"], ["R1720063", "#bdd7e7"], - ["R1720066", "#bdd7e7"], ["R1720065", "#bdd7e7"], + ["R1720066", "#bdd7e7"], ["R1720055", "#bdd7e7"], ["R1720051", "#bdd7e7"], ["R1720068", "#bdd7e7"], @@ -41,23 +41,23 @@ ["R1720054", "#6baed6"] ], [ - ["R1720060", "#eff3ff"], - ["R1720052", "#eff3ff"], ["R1720056", "#eff3ff"], ["R1720058", "#eff3ff"], - ["R1720061", "#eff3ff"], ["R1720062", "#eff3ff"], + ["R1720061", "#eff3ff"], + ["R1720052", "#eff3ff"], + ["R1720060", "#eff3ff"], ["R1720053", "#eff3ff"], ["R1720065", "#eff3ff"], ["R1720063", "#eff3ff"], - ["R1720066", "#eff3ff"], ["R1720064", "#eff3ff"], + ["R1720066", "#eff3ff"], ["R1720055", "#eff3ff"], ["R1720059", "#bdd7e7"], ["R1720067", "#bdd7e7"], ["R1720057", "#bdd7e7"], - ["R1720068", "#bdd7e7"], ["R1720051", "#bdd7e7"], + ["R1720068", "#bdd7e7"], ["R1720054", "#6baed6"] ], [ @@ -110,8 +110,8 @@ ["R1720058", 6], ["R1720059", 6], ["R1720063", 6], - ["R1720066", 6], ["R1720065", 6], + ["R1720066", 6], ["R1720055", 6], ["R1720051", 6], ["R1720068", 6], @@ -123,23 +123,23 @@ ["R1720054", 9] ], [ - ["R1720060", 3], - ["R1720052", 3], ["R1720056", 3], ["R1720058", 3], - ["R1720061", 3], ["R1720062", 3], + ["R1720061", 3], + ["R1720052", 3], + ["R1720060", 3], ["R1720053", 3], ["R1720065", 3], ["R1720063", 3], - ["R1720066", 3], ["R1720064", 3], + ["R1720066", 3], ["R1720055", 3], ["R1720059", 6], ["R1720067", 6], ["R1720057", 6], - ["R1720068", 6], ["R1720051", 6], + ["R1720068", 6], ["R1720054", 9] ], [ @@ -195,8 +195,8 @@ ["R1720058", 1], ["R1720059", 1], ["R1720063", 1], - ["R1720066", 1], ["R1720065", 1], + ["R1720066", 1], ["R1720055", 1], ["R1720051", 1], ["R1720068", 1], @@ -208,23 +208,23 @@ ["R1720054", 1] ], [ - ["R1720060", 1], - ["R1720052", 1], ["R1720056", 1], ["R1720058", 1], - ["R1720061", 1], ["R1720062", 1], + ["R1720061", 1], + ["R1720052", 1], + ["R1720060", 1], ["R1720053", 1], ["R1720065", 1], ["R1720063", 1], - ["R1720066", 1], ["R1720064", 1], + ["R1720066", 1], ["R1720055", 1], ["R1720059", 1], ["R1720067", 1], ["R1720057", 1], - ["R1720068", 1], ["R1720051", 1], + ["R1720068", 1], ["R1720054", 1] ], [ diff --git a/test/map/__snapshots__/addLayer.test.js.snap b/test/map/__snapshots__/addLayer.test.js.snap index fc1d4cb4..125974d5 100644 --- a/test/map/__snapshots__/addLayer.test.js.snap +++ b/test/map/__snapshots__/addLayer.test.js.snap @@ -308,15 +308,15 @@ Object { "category": "Health Cluster", "colorStops": Array [ Array [ - "R1720119", + "R1720070", "#D80000", ], Array [ - "R1720070", + "R1720085", "#D80000", ], Array [ - "R1720104", + "R1720098", "#D80000", ], Array [ @@ -324,31 +324,31 @@ Object { "#D80000", ], Array [ - "R1720098", + "R1720104", "#D80000", ], Array [ - "R1720085", + "R1720112", "#D80000", ], Array [ - "R1720120", + "R1720119", "#D80000", ], Array [ - "R1720112", + "R1720120", "#D80000", ], Array [ - "R1720113", + "R1720101", "#D80000", ], Array [ - "R1720115", + "R1720113", "#D80000", ], Array [ - "R1720101", + "R1720115", "#D80000", ], Array [ @@ -372,23 +372,23 @@ Object { "#D80000", ], Array [ - "R1720106", + "R1720087", "#D80000", ], Array [ - "R1720087", + "R1720106", "#D80000", ], Array [ - "R1720127", + "R1720091", "#D80000", ], Array [ - "R1720135", + "R1720127", "#D80000", ], Array [ - "R1720091", + "R1720135", "#D80000", ], Array [ @@ -428,11 +428,11 @@ Object { "#D80000", ], Array [ - "R1720141", + "R1720138", "#D80000", ], Array [ - "R1720138", + "R1720141", "#D80000", ], Array [ @@ -1095,15 +1095,15 @@ Object { Array [ Array [ Array [ - "R1720119", + "R1720070", "#D80000", ], Array [ - "R1720070", + "R1720085", "#D80000", ], Array [ - "R1720104", + "R1720098", "#D80000", ], Array [ @@ -1111,31 +1111,31 @@ Object { "#D80000", ], Array [ - "R1720098", + "R1720104", "#D80000", ], Array [ - "R1720085", + "R1720112", "#D80000", ], Array [ - "R1720120", + "R1720119", "#D80000", ], Array [ - "R1720112", + "R1720120", "#D80000", ], Array [ - "R1720113", + "R1720101", "#D80000", ], Array [ - "R1720115", + "R1720113", "#D80000", ], Array [ - "R1720101", + "R1720115", "#D80000", ], Array [ @@ -1159,23 +1159,23 @@ Object { "#D80000", ], Array [ - "R1720106", + "R1720087", "#D80000", ], Array [ - "R1720087", + "R1720106", "#D80000", ], Array [ - "R1720127", + "R1720091", "#D80000", ], Array [ - "R1720135", + "R1720127", "#D80000", ], Array [ - "R1720091", + "R1720135", "#D80000", ], Array [ @@ -1215,11 +1215,11 @@ Object { "#D80000", ], Array [ - "R1720141", + "R1720138", "#D80000", ], Array [ - "R1720138", + "R1720141", "#D80000", ], Array [ @@ -1263,15 +1263,15 @@ Object { Array [ Array [ Array [ - "R1720119", + "R1720070", 3, ], Array [ - "R1720070", + "R1720085", 3, ], Array [ - "R1720104", + "R1720098", 3, ], Array [ @@ -1279,31 +1279,31 @@ Object { 3, ], Array [ - "R1720098", + "R1720104", 3, ], Array [ - "R1720085", + "R1720112", 3, ], Array [ - "R1720120", + "R1720119", 3, ], Array [ - "R1720112", + "R1720120", 3, ], Array [ - "R1720113", + "R1720101", 3, ], Array [ - "R1720115", + "R1720113", 3, ], Array [ - "R1720101", + "R1720115", 3, ], Array [ @@ -1327,23 +1327,23 @@ Object { 6, ], Array [ - "R1720106", + "R1720087", 6, ], Array [ - "R1720087", + "R1720106", 6, ], Array [ - "R1720127", + "R1720091", 6, ], Array [ - "R1720135", + "R1720127", 6, ], Array [ - "R1720091", + "R1720135", 6, ], Array [ @@ -1383,11 +1383,11 @@ Object { 9, ], Array [ - "R1720141", + "R1720138", 9, ], Array [ - "R1720138", + "R1720141", 9, ], Array [ @@ -1444,15 +1444,15 @@ Object { Array [ Array [ Array [ - "R1720119", + "R1720070", 1, ], Array [ - "R1720070", + "R1720085", 1, ], Array [ - "R1720104", + "R1720098", 1, ], Array [ @@ -1460,31 +1460,31 @@ Object { 1, ], Array [ - "R1720098", + "R1720104", 1, ], Array [ - "R1720085", + "R1720112", 1, ], Array [ - "R1720120", + "R1720119", 1, ], Array [ - "R1720112", + "R1720120", 1, ], Array [ - "R1720113", + "R1720101", 1, ], Array [ - "R1720115", + "R1720113", 1, ], Array [ - "R1720101", + "R1720115", 1, ], Array [ @@ -1508,23 +1508,23 @@ Object { 1, ], Array [ - "R1720106", + "R1720087", 1, ], Array [ - "R1720087", + "R1720106", 1, ], Array [ - "R1720127", + "R1720091", 1, ], Array [ - "R1720135", + "R1720127", 1, ], Array [ - "R1720091", + "R1720135", 1, ], Array [ @@ -1564,11 +1564,11 @@ Object { 1, ], Array [ - "R1720141", + "R1720138", 1, ], Array [ - "R1720138", + "R1720141", 1, ], Array [ @@ -1657,15 +1657,15 @@ Object { ], "stopsData": Array [ Array [ - "R1720119", + "R1720070", 3, ], Array [ - "R1720070", + "R1720085", 3, ], Array [ - "R1720104", + "R1720098", 3, ], Array [ @@ -1673,31 +1673,31 @@ Object { 3, ], Array [ - "R1720098", + "R1720104", 3, ], Array [ - "R1720085", + "R1720112", 3, ], Array [ - "R1720120", + "R1720119", 3, ], Array [ - "R1720112", + "R1720120", 3, ], Array [ - "R1720113", + "R1720101", 3, ], Array [ - "R1720115", + "R1720113", 3, ], Array [ - "R1720101", + "R1720115", 3, ], Array [ @@ -1721,23 +1721,23 @@ Object { 6, ], Array [ - "R1720106", + "R1720087", 6, ], Array [ - "R1720087", + "R1720106", 6, ], Array [ - "R1720127", + "R1720091", 6, ], Array [ - "R1720135", + "R1720127", 6, ], Array [ - "R1720091", + "R1720135", 6, ], Array [ @@ -1777,11 +1777,11 @@ Object { 9, ], Array [ - "R1720141", + "R1720138", 9, ], Array [ - "R1720138", + "R1720141", 9, ], Array [ @@ -1829,15 +1829,15 @@ Object { "property": "osm_id", "stops": Array [ Array [ - "R1720119", + "R1720070", "#D80000", ], Array [ - "R1720070", + "R1720085", "#D80000", ], Array [ - "R1720104", + "R1720098", "#D80000", ], Array [ @@ -1845,31 +1845,31 @@ Object { "#D80000", ], Array [ - "R1720098", + "R1720104", "#D80000", ], Array [ - "R1720085", + "R1720112", "#D80000", ], Array [ - "R1720120", + "R1720119", "#D80000", ], Array [ - "R1720112", + "R1720120", "#D80000", ], Array [ - "R1720113", + "R1720101", "#D80000", ], Array [ - "R1720115", + "R1720113", "#D80000", ], Array [ - "R1720101", + "R1720115", "#D80000", ], Array [ @@ -1893,23 +1893,23 @@ Object { "#D80000", ], Array [ - "R1720106", + "R1720087", "#D80000", ], Array [ - "R1720087", + "R1720106", "#D80000", ], Array [ - "R1720127", + "R1720091", "#D80000", ], Array [ - "R1720135", + "R1720127", "#D80000", ], Array [ - "R1720091", + "R1720135", "#D80000", ], Array [ @@ -1949,11 +1949,11 @@ Object { "#D80000", ], Array [ - "R1720141", + "R1720138", "#D80000", ], Array [ - "R1720138", + "R1720141", "#D80000", ], Array [ @@ -2001,15 +2001,15 @@ Object { "property": "osm_id", "stops": Array [ Array [ - "R1720119", + "R1720070", 3, ], Array [ - "R1720070", + "R1720085", 3, ], Array [ - "R1720104", + "R1720098", 3, ], Array [ @@ -2017,31 +2017,31 @@ Object { 3, ], Array [ - "R1720098", + "R1720104", 3, ], Array [ - "R1720085", + "R1720112", 3, ], Array [ - "R1720120", + "R1720119", 3, ], Array [ - "R1720112", + "R1720120", 3, ], Array [ - "R1720113", + "R1720101", 3, ], Array [ - "R1720115", + "R1720113", 3, ], Array [ - "R1720101", + "R1720115", 3, ], Array [ @@ -2065,23 +2065,23 @@ Object { 6, ], Array [ - "R1720106", + "R1720087", 6, ], Array [ - "R1720087", + "R1720106", 6, ], Array [ - "R1720127", + "R1720091", 6, ], Array [ - "R1720135", + "R1720127", 6, ], Array [ - "R1720091", + "R1720135", 6, ], Array [ @@ -2121,11 +2121,11 @@ Object { 9, ], Array [ - "R1720141", + "R1720138", 9, ], Array [ - "R1720138", + "R1720141", 9, ], Array [ @@ -3749,11 +3749,11 @@ Object { "#bdd7e7", ], Array [ - "R1720066", + "R1720065", "#bdd7e7", ], Array [ - "R1720065", + "R1720066", "#bdd7e7", ], Array [ @@ -3795,27 +3795,27 @@ Object { ], Array [ Array [ - "R1720060", + "R1720056", "#eff3ff", ], Array [ - "R1720052", + "R1720058", "#eff3ff", ], Array [ - "R1720056", + "R1720062", "#eff3ff", ], Array [ - "R1720058", + "R1720061", "#eff3ff", ], Array [ - "R1720061", + "R1720052", "#eff3ff", ], Array [ - "R1720062", + "R1720060", "#eff3ff", ], Array [ @@ -3831,11 +3831,11 @@ Object { "#eff3ff", ], Array [ - "R1720066", + "R1720064", "#eff3ff", ], Array [ - "R1720064", + "R1720066", "#eff3ff", ], Array [ @@ -3855,11 +3855,11 @@ Object { "#bdd7e7", ], Array [ - "R1720068", + "R1720051", "#bdd7e7", ], Array [ - "R1720051", + "R1720068", "#bdd7e7", ], Array [ @@ -4047,11 +4047,11 @@ Object { 6, ], Array [ - "R1720066", + "R1720065", 6, ], Array [ - "R1720065", + "R1720066", 6, ], Array [ @@ -4093,27 +4093,27 @@ Object { ], Array [ Array [ - "R1720060", + "R1720056", 3, ], Array [ - "R1720052", + "R1720058", 3, ], Array [ - "R1720056", + "R1720062", 3, ], Array [ - "R1720058", + "R1720061", 3, ], Array [ - "R1720061", + "R1720052", 3, ], Array [ - "R1720062", + "R1720060", 3, ], Array [ @@ -4129,11 +4129,11 @@ Object { 3, ], Array [ - "R1720066", + "R1720064", 3, ], Array [ - "R1720064", + "R1720066", 3, ], Array [ @@ -4153,11 +4153,11 @@ Object { 6, ], Array [ - "R1720068", + "R1720051", 6, ], Array [ - "R1720051", + "R1720068", 6, ], Array [ @@ -4365,11 +4365,11 @@ Object { 1, ], Array [ - "R1720066", + "R1720065", 1, ], Array [ - "R1720065", + "R1720066", 1, ], Array [ @@ -4411,27 +4411,27 @@ Object { ], Array [ Array [ - "R1720060", + "R1720056", 1, ], Array [ - "R1720052", + "R1720058", 1, ], Array [ - "R1720056", + "R1720062", 1, ], Array [ - "R1720058", + "R1720061", 1, ], Array [ - "R1720061", + "R1720052", 1, ], Array [ - "R1720062", + "R1720060", 1, ], Array [ @@ -4447,11 +4447,11 @@ Object { 1, ], Array [ - "R1720066", + "R1720064", 1, ], Array [ - "R1720064", + "R1720066", 1, ], Array [ @@ -4471,11 +4471,11 @@ Object { 1, ], Array [ - "R1720068", + "R1720051", 1, ], Array [ - "R1720051", + "R1720068", 1, ], Array [