diff --git a/src/index.js b/src/index.js index 25bbe0d5..fcea9c7f 100644 --- a/src/index.js +++ b/src/index.js @@ -1,11 +1,23 @@ +import app from './store/reducers/app'; +import filter from './store/reducers/filter'; +import layersReducer from './store/reducers/layers'; +import loc from './store/reducers/loc'; +import locationsReducer from './store/reducers/locations'; +import regions from './store/reducers/regions'; +import styles from './store/reducers/styles'; +import supersetConfig from './store/reducers/superset-config'; + const gisida = {}; gisida.version = require('../package.json').version; gisida.initStore = require('./store/initStore').default; gisida.loadLayers = require('./store/initStore').loadLayers; gisida.reducerRegistry = require('./store/reducerRegistry').default; -gisida.createMapReducer = require('./store/reducers/reducers').createMapReducer; -gisida.reducers = require('./store/reducers/reducers').default; +gisida.createMapReducer = require('./store/reducers/app').createMapReducer; + +gisida.reducers = { + ...app, filter, layersReducer, loc, locationsReducer, regions, styles, supersetConfig, +}; gisida.Actions = require('./store/actions/actions').default; gisida.prepareLayer = require('./map/prepareLayer').default; gisida.addPopUp = require('./map/addPopUp').default; @@ -27,8 +39,8 @@ gisida.parseData = require('./utils/parseData').default; gisida.lngLat = require('./utils/lngLat').default; gisida.defaultReducers = {}; -gisida.defaultReducers.APP = require('./store/reducers/reducers').APP; -gisida.defaultReducers.STYLES = require('./store/reducers/reducers').STYLES; +gisida.defaultReducers.APP = require('./store/reducers/app').APP; +gisida.defaultReducers.STYLES = require('./store/reducers/styles'); gisida.files = {}; gisida.files.loadJSON = require('./utils/files').loadJSON; diff --git a/src/store/ducks/APP.js b/src/store/ducks/APP.js index 671a9141..342bbe55 100644 --- a/src/store/ducks/APP.js +++ b/src/store/ducks/APP.js @@ -1,4 +1,4 @@ -import { APP } from '../reducers/reducers'; +import { APP } from '../../store/reducers/app'; export { INIT_APP } from '../constants/actionTypes'; export { initApp } from '../actions/actions'; diff --git a/src/store/ducks/MAP.js b/src/store/ducks/MAP.js index fe3e0e94..3918d952 100644 --- a/src/store/ducks/MAP.js +++ b/src/store/ducks/MAP.js @@ -1,4 +1,4 @@ -import reducers from '../reducers/reducers'; +import reducers from '../reducers/app'; export { MAP_RENDERED, diff --git a/src/store/ducks/STYLES.js b/src/store/ducks/STYLES.js index c467cb91..6aaa13d4 100644 --- a/src/store/ducks/STYLES.js +++ b/src/store/ducks/STYLES.js @@ -1,4 +1,4 @@ -import { STYLES } from '../reducers/reducers'; +import { STYLES } from '../reducers/styles'; export { INIT_STYLES, CHANGE_STYLE } from '../constants/actionTypes'; export { initStyles, changeStyle } from '../actions/actions'; diff --git a/src/store/initStore.js b/src/store/initStore.js index 68cbec38..b87a3291 100644 --- a/src/store/initStore.js +++ b/src/store/initStore.js @@ -1,12 +1,29 @@ import { applyMiddleware, createStore, combineReducers } from 'redux'; import thunk from 'redux-thunk'; import * as actions from './actions/actions'; -import defaultReducers from './reducers/reducers'; +import app from './reducers/app'; +import filter from './reducers/filter'; +import layersReducer from './reducers/layers'; +import loc from './reducers/loc'; +import locationsReducer from './reducers/locations'; +import regions from './reducers/regions'; +import styles from './reducers/styles'; +import supersetConfig from './reducers/superset-config'; + import { loadJSON } from '../utils/files'; import prepareLayer from '../map/prepareLayer'; import reducerRegistry from './reducerRegistry'; - +const defaultReducers = { + supersetConfig, + styles, + regions, + locationsReducer, + loc, + layersReducer, + filter, + ...app, +}; export function loadLayers(mapId, dispatch, layers) { // Check if config has list of layers and add them to store if ((Array.isArray(layers) && layers.length) || Object.keys(layers).length) { @@ -40,7 +57,7 @@ export function loadLayers(mapId, dispatch, layers) { // load local or remote layer spec return loadJSON(path, addLayerToStore); } else if (layer instanceof Object && layer.type) { - // use existing layer spec object + // use existing layer spec object layer.loaded = false; if (layer.visible && !layer.loaded) { prepareLayer(mapId, layer, dispatch); diff --git a/src/store/reducers/reducers.js b/src/store/reducers/app.js similarity index 70% rename from src/store/reducers/reducers.js rename to src/store/reducers/app.js index d8614ff1..78a51e22 100644 --- a/src/store/reducers/reducers.js +++ b/src/store/reducers/app.js @@ -1,7 +1,6 @@ import cloneDeep from 'lodash.clonedeep'; -import defaultState from '../defaultState'; import * as types from '../constants/actionTypes'; -import actions from '../actions/actions'; +import defaultState from '../defaultState'; export function APP(state = defaultState.APP, action) { @@ -17,198 +16,6 @@ export function APP(state = defaultState.APP, action) { } } -function LOC(state = defaultState.LOC, action) { - switch (action.type) { - case types.INIT_LOC: - return { - ...state, - locations: { ...action.config }, - location: { - ...Object.keys(action.config).map(d => action.config[d]).find(d => d.default === true), - doUpdateLOC: false, - }, - doUpdateMap: state.doUpdateMap, - default: Object.keys(action.config).find(d => action.config[d].default === true), - active: Object.keys(action.config).find(d => action.config[d].default === true), - }; - case types.SET_LOCATION: { - const { loc, mapId } = action; - const { active, locations } = state; - return { - ...state, - doUpdateMap: mapId, - active: typeof locations[loc] !== 'undefined' ? loc : active, - location: typeof locations[loc] !== 'undefined' - ? { ...locations[loc], doUpdateLOC: !state.location.doUpdateLOC } - : { ...state.location, doUpdateLOC: false }, - }; - } - case types.TOGGLE_MAP_LOCATION: { - const { loc } = actions; - const { locations } = state; - return { - ...state, - location: typeof locations[loc] !== 'undefined' ? - { ...locations[loc], doUpdateLOC: !state.location.doUpdateLOC } : - { ...state.location, doUpdateLOC: false }, - }; - } - default: - return state; - } -} - -export function STYLES(state = defaultState.STYLES, action) { - switch (action.type) { - case types.INIT_STYLES: { - const styles = action.styles.map((s) => { - const style = s; - if (style.url === action.mapConfig.style) style.current = true; - return style; - }); - return styles; - } - case types.CHANGE_STYLE: { - const updatedStyles = state.map((s) => { - const style = s; - if (action.style === style.url) { - if (action.mapId) { - style[action.mapId] = { current: true }; - } else style.current = true; - } else if (action.mapId) { - style[action.mapId] = { current: false }; - } else style.current = false; - return style; - }); - return updatedStyles; - } - default: - return state; - } -} - -function REGIONS(state = defaultState.REGIONS, action) { - switch (action.type) { - case types.INIT_REGIONS: { - const regions = action.regions ? action.regions.map((r) => { - const region = r; - // check if mapconfig center matches region center to set current region - if ( - region.center[0] === action.mapConfig.center[0] && - region.center[1] === action.mapConfig.center[1]) { - region.current = true; - } - return region; - }) : []; - return regions; - } - case types.CHANGE_REGION: { - const updatedRegions = state.map((r) => { - const region = r; - if (action.region === region.name) { - region.current = true; - } else region.current = false; - return region; - }); - return updatedRegions; - } - default: - return state; - } -} - -function FILTER(state = defaultState.FILTER, action) { - switch (action.type) { - case types.SAVE_FILTER_STATE: { - return { - ...state, - [action.layerId]: { - ...action.filterState, - doUpdate: true, - isClear: action.isClear || false, - }, - }; - } - case types.FILTERS_UPDATED: { - if (!action.layerId) { - return { - ...state, - }; - } - return { - ...state, - [action.layerId]: { - ...state[action.layerId], - doUpdate: false, - }, - }; - } - default: - return state; - } -} - -function LOCATIONS(state = {}, action) { - switch (action.type) { - case types.INIT_LOCATIONS: { - return { ...state, ...action.locations }; - } - default: - return state; - } -} - -function SUPERSET_CONFIGS(state = {}, action) { - switch (action.type) { - case types.INIT_SUPERSET: { - return { - ...state, - ...action.config, - }; - } - default: - return state; - } -} - -function LAYERS(state = defaultState.LAYERS, action) { - switch (action.type) { - case types.ADD_LAYERS_LIST: { - return { - ...state, - layers: [...state.layers, ...action.layers], - }; - } - case types.ADD_LAYER_GROUP: { - // parse action.group for urls - const groupMapper = (layer) => { - if (typeof layer === 'string') { - if (layer.indexOf('http') === -1) { - return layer; - } - const pathSplit = layer.split('/'); - return pathSplit[pathSplit.length - 1]; - } - const subGroup = {}; - Object.keys(layer).forEach((key) => { - subGroup[key] = layer[key].map(groupMapper); - }); - return subGroup; - }; - const group = action.group.map(groupMapper); - return { - ...state, - groups: { - ...state.groups, - [action.groupId]: group, - }, - }; - } - default: - return state; - } -} - export function createMapReducer(mapId) { const initialState = defaultState.MAP; initialState.mapId = mapId; @@ -567,6 +374,7 @@ export function createMapReducer(mapId) { return state; }; } + export default { - APP, LOC, SUPERSET_CONFIGS, STYLES, REGIONS, LOCATIONS, LAYERS, FILTER, 'map-1': createMapReducer('map-1'), + 'map-1': createMapReducer('map-1'), APP, }; diff --git a/src/store/reducers/filter.js b/src/store/reducers/filter.js new file mode 100644 index 00000000..719aef03 --- /dev/null +++ b/src/store/reducers/filter.js @@ -0,0 +1,37 @@ + + +import defaultState from '../defaultState'; +import * as types from '../constants/actionTypes'; + + +export default function FILTER(state = defaultState.FILTER, action) { + switch (action.type) { + case types.SAVE_FILTER_STATE: { + return { + ...state, + [action.layerId]: { + ...action.filterState, + doUpdate: true, + isClear: action.isClear || false, + }, + }; + } + case types.FILTERS_UPDATED: { + if (!action.layerId) { + return { + ...state, + }; + } + return { + ...state, + [action.layerId]: { + ...state[action.layerId], + doUpdate: false, + }, + }; + } + default: + return state; + } +} + diff --git a/src/store/reducers/layers.js b/src/store/reducers/layers.js new file mode 100644 index 00000000..90b38a94 --- /dev/null +++ b/src/store/reducers/layers.js @@ -0,0 +1,41 @@ +import defaultState from '../defaultState'; +import * as types from '../constants/actionTypes'; + + +export default function LAYERS(state = defaultState.LAYERS, action) { + switch (action.type) { + case types.ADD_LAYERS_LIST: { + return { + ...state, + layers: [...state.layers, ...action.layers], + }; + } + case types.ADD_LAYER_GROUP: { + // parse action.group for urls + const groupMapper = (layer) => { + if (typeof layer === 'string') { + if (layer.indexOf('http') === -1) { + return layer; + } + const pathSplit = layer.split('/'); + return pathSplit[pathSplit.length - 1]; + } + const subGroup = {}; + Object.keys(layer).forEach((key) => { + subGroup[key] = layer[key].map(groupMapper); + }); + return subGroup; + }; + const group = action.group.map(groupMapper); + return { + ...state, + groups: { + ...state.groups, + [action.groupId]: group, + }, + }; + } + default: + return state; + } +} diff --git a/src/store/reducers/loc.js b/src/store/reducers/loc.js new file mode 100644 index 00000000..fac96602 --- /dev/null +++ b/src/store/reducers/loc.js @@ -0,0 +1,46 @@ +import defaultState from '../defaultState'; +import * as types from '../constants/actionTypes'; +import actions from '../actions/actions'; + + +export default function LOC(state = defaultState.LOC, action) { + switch (action.type) { + case types.INIT_LOC: + return { + ...state, + locations: { ...action.config }, + location: { + ...Object.keys(action.config).map(d => action.config[d]).find(d => d.default === true), + doUpdateLOC: false, + }, + doUpdateMap: state.doUpdateMap, + default: Object.keys(action.config).find(d => action.config[d].default === true), + active: Object.keys(action.config).find(d => action.config[d].default === true), + }; + case types.SET_LOCATION: { + const { loc, mapId } = action; + const { active, locations } = state; + return { + ...state, + doUpdateMap: mapId, + active: typeof locations[loc] !== 'undefined' ? loc : active, + location: typeof locations[loc] !== 'undefined' + ? { ...locations[loc], doUpdateLOC: !state.location.doUpdateLOC } + : { ...state.location, doUpdateLOC: false }, + }; + } + case types.TOGGLE_MAP_LOCATION: { + const { loc } = actions; + const { locations } = state; + return { + ...state, + location: typeof locations[loc] !== 'undefined' ? + { ...locations[loc], doUpdateLOC: !state.location.doUpdateLOC } : + { ...state.location, doUpdateLOC: false }, + }; + } + default: + return state; + } +} + diff --git a/src/store/reducers/locations.js b/src/store/reducers/locations.js new file mode 100644 index 00000000..ade7690c --- /dev/null +++ b/src/store/reducers/locations.js @@ -0,0 +1,14 @@ + +import * as types from '../constants/actionTypes'; + + +export default function LOCATIONS(state = {}, action) { + switch (action.type) { + case types.INIT_LOCATIONS: { + return { ...state, ...action.locations }; + } + default: + return state; + } +} + diff --git a/src/store/reducers/regions.js b/src/store/reducers/regions.js new file mode 100644 index 00000000..548ac58f --- /dev/null +++ b/src/store/reducers/regions.js @@ -0,0 +1,36 @@ + + +import defaultState from '../defaultState'; +import * as types from '../constants/actionTypes'; + + +export default function REGIONS(state = defaultState.REGIONS, action) { + switch (action.type) { + case types.INIT_REGIONS: { + const regions = action.regions ? action.regions.map((r) => { + const region = r; + // check if mapconfig center matches region center to set current region + if ( + region.center[0] === action.mapConfig.center[0] && + region.center[1] === action.mapConfig.center[1]) { + region.current = true; + } + return region; + }) : []; + return regions; + } + case types.CHANGE_REGION: { + const updatedRegions = state.map((r) => { + const region = r; + if (action.region === region.name) { + region.current = true; + } else region.current = false; + return region; + }); + return updatedRegions; + } + default: + return state; + } +} + diff --git a/src/store/reducers/styles.js b/src/store/reducers/styles.js new file mode 100644 index 00000000..bf2c857b --- /dev/null +++ b/src/store/reducers/styles.js @@ -0,0 +1,34 @@ + +import defaultState from '../defaultState'; +import * as types from '../constants/actionTypes'; + + +export default function STYLES(state = defaultState.STYLES, action) { + switch (action.type) { + case types.INIT_STYLES: { + const styles = action.styles.map((s) => { + const style = s; + if (style.url === action.mapConfig.style) style.current = true; + return style; + }); + return styles; + } + case types.CHANGE_STYLE: { + const updatedStyles = state.map((s) => { + const style = s; + if (action.style === style.url) { + if (action.mapId) { + style[action.mapId] = { current: true }; + } else style.current = true; + } else if (action.mapId) { + style[action.mapId] = { current: false }; + } else style.current = false; + return style; + }); + return updatedStyles; + } + default: + return state; + } +} + diff --git a/src/store/reducers/superset-config.js b/src/store/reducers/superset-config.js new file mode 100644 index 00000000..0c0ba305 --- /dev/null +++ b/src/store/reducers/superset-config.js @@ -0,0 +1,17 @@ + +import * as types from '../constants/actionTypes'; + + +export default function SUPERSET_CONFIGS(state = {}, action) { + switch (action.type) { + case types.INIT_SUPERSET: { + return { + ...state, + ...action.config, + }; + } + default: + return state; + } +} + diff --git a/test/store/reducers/reducers.test.js b/test/store/reducers/reducers.test.js index 44519541..f5bc5bef 100644 --- a/test/store/reducers/reducers.test.js +++ b/test/store/reducers/reducers.test.js @@ -1,4 +1,5 @@ -import reducers from '../../../src/store/reducers/reducers'; +import { APP } from '../../../src/store/reducers/app'; + import * as types from '../../../src/store/constants/actionTypes'; import defaultState from '../../../src/store/defaultState'; @@ -92,6 +93,7 @@ describe('reducers.APP', () => { locations: null, }, }; - expect(reducers.APP(defaultState, action)).toEqual(state); + + expect(APP(defaultState, action)).toEqual(state); }); });