Skip to content

Commit 389ad86

Browse files
authored
Support for time dimension (#2968)
1 parent 07f1d0c commit 389ad86

10 files changed

Lines changed: 210 additions & 20 deletions

File tree

web/client/actions/__tests__/layers-test.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ var {
2222
HIDE_SETTINGS,
2323
UPDATE_SETTINGS,
2424
REFRESH_LAYERS,
25+
UPDATE_LAYERS_DIMENSION,
2526
LAYERS_REFRESHED,
2627
LAYERS_REFRESH_ERROR,
2728
BROWSE_DATA,
@@ -44,6 +45,7 @@ var {
4445
hideSettings,
4546
updateSettings,
4647
refreshLayers,
48+
updateLayerDimension,
4749
layersRefreshed,
4850
layersRefreshError,
4951
browseData,
@@ -111,6 +113,14 @@ describe('Test correctness of the layers actions', () => {
111113
expect(retval.error).toBe('err');
112114
});
113115

116+
it('updateLayerDimension', () => {
117+
const retval = updateLayerDimension( "time", "2016-02-24T03:00:00.000Z", null, "A");
118+
expect(retval).toExist();
119+
expect(retval.type).toBe(UPDATE_LAYERS_DIMENSION);
120+
expect(retval.layers).toBe("A");
121+
expect(retval.dimension).toBe("time");
122+
expect(retval.value).toBe("2016-02-24T03:00:00.000Z");
123+
});
114124
it('toggleNode', () => {
115125
var retval = toggleNode('sample', 'groups', true);
116126

web/client/actions/layers.js

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
*/
88

99
const CHANGE_LAYER_PROPERTIES = 'CHANGE_LAYER_PROPERTIES';
10+
const CHANGE_LAYER_PARAMS = 'LAYERS:CHANGE_LAYER_PARAMS';
1011
const CHANGE_GROUP_PROPERTIES = 'CHANGE_GROUP_PROPERTIES';
1112
const TOGGLE_NODE = 'TOGGLE_NODE';
1213
const CONTEXT_NODE = 'CONTEXT_NODE';
@@ -22,6 +23,7 @@ const SHOW_SETTINGS = 'SHOW_SETTINGS';
2223
const HIDE_SETTINGS = 'HIDE_SETTINGS';
2324
const UPDATE_SETTINGS = 'UPDATE_SETTINGS';
2425
const REFRESH_LAYERS = 'REFRESH_LAYERS';
26+
const UPDATE_LAYERS_DIMENSION = 'LAYERS:UPDATE_LAYERS_DIMENSION';
2527
const LAYERS_REFRESHED = 'LAYERS_REFRESHED';
2628
const LAYERS_REFRESH_ERROR = 'LAYERS_REFRESH_ERROR';
2729
const BROWSE_DATA = 'LAYERS:BROWSE_DATA';
@@ -62,6 +64,20 @@ function changeLayerProperties(layer, properties) {
6264

6365
};
6466
}
67+
/**
68+
* Change params for a layer. Useful for WMS layers, when you need to change only the params (i.e. dimension) merging with existing ones.
69+
* @memberof actions.layers
70+
* @function
71+
* @param {string|string[]} layer id(s) of the layers to change
72+
* @param {object} params the params to change
73+
*/
74+
function changeLayerParams(layer, params) {
75+
return {
76+
type: CHANGE_LAYER_PARAMS,
77+
layer,
78+
params
79+
};
80+
}
6581

6682
function changeGroupProperties(group, properties) {
6783
return {
@@ -184,6 +200,15 @@ function layersRefreshError(layers, error) {
184200
error
185201
};
186202
}
203+
function updateLayerDimension(dimension, value, options, layers) {
204+
return {
205+
type: UPDATE_LAYERS_DIMENSION,
206+
dimension,
207+
value,
208+
options,
209+
layers
210+
};
211+
}
187212
function browseData(layer) {
188213
return {
189214
type: BROWSE_DATA,
@@ -232,12 +257,13 @@ function hideLayerMetadata() {
232257
};
233258
}
234259

235-
module.exports = {changeLayerProperties, changeGroupProperties, toggleNode, sortNode, removeNode, contextNode,
260+
module.exports = {
261+
changeLayerProperties, changeLayerParams, changeGroupProperties, toggleNode, sortNode, removeNode, contextNode,
236262
updateNode, layerLoading, layerLoad, layerError, addLayer, removeLayer, showSettings, hideSettings, updateSettings, refreshLayers,
237-
layersRefreshed, layersRefreshError, refreshLayerVersion, browseData, clearLayers, selectNode, filterLayers, showLayerMetadata,
263+
layersRefreshed, layersRefreshError, refreshLayerVersion, updateLayerDimension, browseData, clearLayers, selectNode, filterLayers, showLayerMetadata,
238264
hideLayerMetadata, download,
239-
CHANGE_LAYER_PROPERTIES, CHANGE_GROUP_PROPERTIES, TOGGLE_NODE, SORT_NODE,
265+
CHANGE_LAYER_PROPERTIES, CHANGE_LAYER_PARAMS, CHANGE_GROUP_PROPERTIES, TOGGLE_NODE, SORT_NODE,
240266
REMOVE_NODE, UPDATE_NODE, LAYER_LOADING, LAYER_LOAD, LAYER_ERROR, ADD_LAYER, REMOVE_LAYER,
241-
SHOW_SETTINGS, HIDE_SETTINGS, UPDATE_SETTINGS, CONTEXT_NODE, REFRESH_LAYERS, LAYERS_REFRESHED, LAYERS_REFRESH_ERROR, BROWSE_DATA, DOWNLOAD,
267+
SHOW_SETTINGS, HIDE_SETTINGS, UPDATE_SETTINGS, CONTEXT_NODE, REFRESH_LAYERS, LAYERS_REFRESHED, LAYERS_REFRESH_ERROR, UPDATE_LAYERS_DIMENSION, BROWSE_DATA, DOWNLOAD,
242268
CLEAR_LAYERS, SELECT_NODE, FILTER_LAYERS, SHOW_LAYER_METADATA, HIDE_LAYER_METADATA
243269
};

web/client/epics/__tests__/layers-test.js

Lines changed: 51 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,15 @@ var expect = require('expect');
1010

1111
const configureMockStore = require('redux-mock-store').default;
1212
const { createEpicMiddleware, combineEpics } = require('redux-observable');
13-
const {refreshLayers, LAYERS_REFRESHED, LAYERS_REFRESH_ERROR, UPDATE_NODE} = require('../../actions/layers');
13+
const {
14+
refreshLayers, LAYERS_REFRESHED, LAYERS_REFRESH_ERROR, UPDATE_NODE,
15+
updateLayerDimension, CHANGE_LAYER_PARAMS
16+
} = require('../../actions/layers');
17+
const {
18+
testEpic
19+
} = require('./epicTestUtils');
1420

15-
const {refresh } = require('../layers');
21+
const { refresh, updateDimension } = require('../layers');
1622
const rootEpic = combineEpics(refresh);
1723
const epicMiddleware = createEpicMiddleware(rootEpic);
1824
const mockStore = configureMockStore([epicMiddleware]);
@@ -77,4 +83,47 @@ describe('layers Epics', () => {
7783
}
7884
});
7985
});
86+
it('test update dimension', done => {
87+
const state = {
88+
layers: {
89+
flat: [{
90+
group: 'test',
91+
id: 'layer001',
92+
visibility: true,
93+
dimensions: [{
94+
name: 'time'
95+
}]
96+
},
97+
{
98+
group: 'test',
99+
id: 'layer002',
100+
visibility: true,
101+
dimensions: [{
102+
name: 'time'
103+
}, {
104+
name: 'elevation'
105+
}]
106+
}]
107+
}
108+
};
109+
testEpic(
110+
updateDimension,
111+
1,
112+
updateLayerDimension('time', "2016-02-24T03:00:00.000Z"),
113+
actions => {
114+
expect(actions.length).toBe(1);
115+
actions.map((action) => {
116+
switch (action.type) {
117+
case CHANGE_LAYER_PARAMS:
118+
expect(action.layer.length).toBe(2);
119+
expect(action.params.time).toBe("2016-02-24T03:00:00.000Z");
120+
break;
121+
default:
122+
expect(true).toBe(false);
123+
124+
}
125+
});
126+
done();
127+
}, state);
128+
});
80129
});

web/client/epics/layers.js

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,12 @@
88

99
const Rx = require('rxjs');
1010
const Api = require('../api/WMS');
11-
const {REFRESH_LAYERS, layersRefreshed, updateNode, layersRefreshError} = require('../actions/layers');
11+
const { REFRESH_LAYERS, UPDATE_LAYERS_DIMENSION, layersRefreshed, updateNode, layersRefreshError, changeLayerParams} = require('../actions/layers');
12+
const {getLayersWithDimension} = require('../selectors/layers');
13+
1214
const LayersUtils = require('../utils/LayersUtils');
1315

16+
1417
const assign = require('object-assign');
1518
const {isArray, head} = require('lodash');
1619

@@ -86,7 +89,26 @@ const refresh = action$ =>
8689
.mergeAll();
8790
});
8891

89-
92+
/**
93+
* Update dimension to all layers that have that dimension set, or for the layers indicated in the action.
94+
* @memberof epics.layers
95+
* @param {external:Observable} action$ manages `UPDATE_LAYERS_DIMENSION`
96+
* @return {external:Observable}
97+
*/
98+
const updateDimension = (action$, {getState = () => {}} = {}) =>
99+
action$.ofType(UPDATE_LAYERS_DIMENSION)
100+
.map(({ layers, dimension, ...other }) => ({ ...other, dimension, layers: layers || getLayersWithDimension(getState(), dimension)}))
101+
.switchMap(({layers, dimension, value}) =>
102+
Rx.Observable.of(
103+
changeLayerParams(
104+
layers.map(l => l.id),
105+
{
106+
[dimension]: value
107+
}
108+
)
109+
)
110+
);
90111
module.exports = {
91-
refresh
112+
refresh,
113+
updateDimension
92114
};

web/client/plugins/AutoMapUpdate.jsx

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ const {connect} = require('react-redux');
1212
const {manageAutoMapUpdate} = require('../epics/automapupdate');
1313
const {autoMapUpdateSelector} = require('../selectors/automapupdate');
1414
const {setControlProperty} = require('../actions/controls');
15-
const {refresh} = require('../epics/layers');
1615

1716
const OverlayProgressBar = require('../components/misc/progressbars/OverlayProgressBar/OverlayProgressBar');
1817

@@ -78,5 +77,5 @@ const AutoMapUpdatePlugin = connect(autoMapUpdateSelector, {
7877
module.exports = {
7978
AutoMapUpdatePlugin,
8079
reducers: {},
81-
epics: {manageAutoMapUpdate, refresh}
80+
epics: {manageAutoMapUpdate}
8281
};

web/client/reducers/__tests__/layers-test.js

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
*/
88
var expect = require('expect');
99
var layers = require('../layers');
10+
const { changeLayerParams } = require('../../actions/layers');
11+
1012

1113
describe('Test the layers reducer', () => {
1214

@@ -178,7 +180,44 @@ describe('Test the layers reducer', () => {
178180
expect(state.flat[0].visibility).toBe(false);
179181
expect(state.flat[1].visibility).toBe(true);
180182
});
183+
it('changeLayerParams', () => {
184+
const state = {
185+
flat: [{
186+
"type": "osm",
187+
"title": "Open Street Map",
188+
"name": "mapnik",
189+
"id": "mapnik",
190+
"group": "background",
191+
"visibility": true
192+
}, {
193+
"type": "wms",
194+
"url": "/reflector/open/service",
195+
"visibility": false,
196+
"title": "e-Geos Ortofoto RealVista 1.0",
197+
"name": "rv1",
198+
"id": "rv1",
199+
"group": "background",
200+
"format": "image/png"
201+
}, {
202+
"type": "wms",
203+
"url": "/reflector/open/service",
204+
"visibility": false,
205+
"title": "e-Geos Ortofoto RealVista 1.0",
206+
"name": "rv2",
207+
"id": "rv2",
208+
"group": "background",
209+
"format": "image/png"
210+
}]
211+
};
212+
const state1 = layers(state, changeLayerParams("rv1", {elevation: 200}));
213+
expect(state1.flat[1].params).toExist();
214+
expect(state1.flat[1].params.elevation).toBe(200);
215+
expect(state1.flat[2].params).toNotExist();
216+
const state2 = layers(state, changeLayerParams(["rv1", "rv2"], { elevation: 200 }));
217+
expect(state2.flat[1].params.elevation).toBe(200);
218+
expect(state2.flat[2].params.elevation).toBe(200);
181219

220+
});
182221
it('a layer is loading, loading flag is updated', () => {
183222
const action1 = {
184223
type: 'LAYER_LOADING',

web/client/reducers/layers.js

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,15 @@
66
* LICENSE file in the root directory of this source tree.
77
*/
88

9-
var {LAYER_LOADING, LAYER_LOAD, LAYER_ERROR, CHANGE_LAYER_PROPERTIES, CHANGE_GROUP_PROPERTIES,
9+
var { LAYER_LOADING, LAYER_LOAD, LAYER_ERROR, CHANGE_LAYER_PARAMS, CHANGE_LAYER_PROPERTIES, CHANGE_GROUP_PROPERTIES,
1010
TOGGLE_NODE, SORT_NODE, REMOVE_NODE, UPDATE_NODE, ADD_LAYER, REMOVE_LAYER,
1111
SHOW_SETTINGS, HIDE_SETTINGS, UPDATE_SETTINGS, REFRESH_LAYERS, LAYERS_REFRESH_ERROR, LAYERS_REFRESHED, CLEAR_LAYERS, SELECT_NODE, FILTER_LAYERS, SHOW_LAYER_METADATA, HIDE_LAYER_METADATA
1212
} = require('../actions/layers');
1313

1414
const {TOGGLE_CONTROL} = require('../actions/controls');
1515

1616
var assign = require('object-assign');
17-
var {isObject, isArray, head, isString} = require('lodash');
17+
var {isObject, isArray, head, isString, includes, castArray} = require('lodash');
1818

1919
const LayersUtils = require('../utils/LayersUtils');
2020

@@ -102,15 +102,24 @@ function layers(state = [], action) {
102102
});
103103
return assign({}, state, {refreshing: newLayers});
104104
}
105+
case CHANGE_LAYER_PARAMS:
105106
case CHANGE_LAYER_PROPERTIES: {
106107
const flatLayers = (state.flat || []);
107108
let isBackground = flatLayers.reduce(
108109
(background, layer) => background || (layer.id === action.layer && layer.group === 'background'),
109110
false);
110111
const newLayers = flatLayers.map((layer) => {
111-
if (layer.id === action.layer) {
112-
return assign({}, layer, action.newProperties);
113-
} else if (layer.group === 'background' && isBackground && action.newProperties.visibility) {
112+
if ( includes(castArray(action.layer), layer.id )) {
113+
return assign(
114+
{},
115+
layer,
116+
action.newProperties,
117+
action.params
118+
? {
119+
params: assign({}, layer.params, action.params)
120+
}
121+
: {});
122+
} else if (layer.group === 'background' && isBackground && action.newProperties && action.newProperties.visibility) {
114123
// TODO remove
115124
return assign({}, layer, {visibility: false});
116125
}

web/client/selectors/__tests__/layers-test.js

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
const expect = require('expect');
1010
const {layersSelector, layerSelectorWithMarkers, groupsSelector, selectedNodesSelector, layerFilterSelector, layerSettingSelector,
11-
layerMetadataSelector, wfsDownloadSelector, backgroundControlsSelector, currentBackgroundSelector, tempBackgroundSelector, centerToMarkerSelector} = require('../layers');
11+
layerMetadataSelector, wfsDownloadSelector, backgroundControlsSelector, currentBackgroundSelector, tempBackgroundSelector, centerToMarkerSelector, getLayersWithDimension} = require('../layers');
1212

1313
describe('Test layers selectors', () => {
1414
it('test layersSelector from config', () => {
@@ -405,5 +405,32 @@ describe('Test layers selectors', () => {
405405
});
406406
expect(props).toEqual(true);
407407
});
408+
it('test getLayerWidDimension', () => {
409+
const state = {
410+
layers: {
411+
flat: [{
412+
group: 'test',
413+
id: 'layer001',
414+
visibility: true,
415+
dimensions: [{
416+
name: 'time'
417+
}]
418+
},
419+
{
420+
group: 'test',
421+
id: 'layer002',
422+
visibility: true,
423+
dimensions: [{
424+
name: 'time'
425+
}, {
426+
name: 'elevation'
427+
}]
428+
}]
429+
}
430+
};
431+
expect(getLayersWithDimension(state, 'time').length).toBe(2);
432+
expect(getLayersWithDimension(state, 'elevation').length).toBe(1);
433+
expect(getLayersWithDimension(state, 'reference').length).toBe(0);
434+
});
408435

409436
});

web/client/selectors/layers.js

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ const {createSelector} = require('reselect');
1111
const MapInfoUtils = require('../utils/MapInfoUtils');
1212
const LayersUtils = require('../utils/LayersUtils');
1313
const {getNormalizedLatLon} = require('../utils/CoordinatesUtils');
14-
const {get, head, isEmpty, find, isObject} = require('lodash');
14+
const {get, head, isEmpty, find, isObject, castArray} = require('lodash');
1515

1616
const layersSelector = state => state.layers && state.layers.flat || state.layers || state.config && state.config.layers || [];
1717
const currentBackgroundLayerSelector = state => head(layersSelector(state).filter(l => l && l.visibility && l.group === "background"));
@@ -81,14 +81,20 @@ const tempBackgroundSelector = (state) => {
8181
const layers = allBackgroundLayerSelector(state) || [];
8282
return controls.tempLayer && !isEmpty(controls.tempLayer) ? controls.tempLayer : head(layers.filter((l) => l.visibility)) || {};
8383
};
84-
84+
const getLayersWithDimension = (state, dimension) =>
85+
(layersSelector(state) || [])
86+
.filter(l =>
87+
l
88+
&& l.dimensions
89+
&& find(castArray(l.dimensions), {name: dimension}));
8590
module.exports = {
8691
layersSelector,
8792
layerSelectorWithMarkers,
8893
groupsSelector,
8994
currentBackgroundLayerSelector,
9095
allBackgroundLayerSelector,
9196
getLayerFromId,
97+
getLayersWithDimension,
9298
selectedNodesSelector,
9399
getSelectedLayer,
94100
getSelectedLayers,

0 commit comments

Comments
 (0)