Skip to content

Commit 574bafc

Browse files
geosolutions-it#10487: Custom Tile Grids settings for WMS service are not retained when adding a Background layer from Catalog (geosolutions-it#10490)
1 parent d2bee6c commit 574bafc

File tree

5 files changed

+277
-21
lines changed

5 files changed

+277
-21
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,206 @@
1+
/*
2+
* Copyright 2014, GeoSolutions Sas.
3+
* All rights reserved.
4+
*
5+
* This source code is licensed under the BSD-style license found in the
6+
* LICENSE file in the root directory of this source tree.
7+
*/
8+
9+
import expect from 'expect';
10+
11+
import { addBackgroundProperties, SET_BACKGROUND_MODAL_PARAMS } from '../../actions/backgroundselector';
12+
import { testEpic } from './epicTestUtils';
13+
import backgroundEpics from '../backgroundselector';
14+
import MockAdapter from 'axios-mock-adapter';
15+
import axios from '../../libs/ajax';
16+
let mockAxios;
17+
18+
describe('addBackgroundPropertiesEpic Epics', () => {
19+
beforeEach((done) => {
20+
mockAxios = new MockAdapter(axios);
21+
setTimeout(done);
22+
});
23+
afterEach((done) => {
24+
mockAxios.restore();
25+
setTimeout(done);
26+
});
27+
const capabilitiesWMSXmlResponse = `<?xml version="1.0" encoding="UTF-8"?>
28+
<Capabilities xmlns="http://www.opengis.net/wmts/1.0" xmlns:ows="http://www.opengis.net/ows/1.1" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:gml="http://www.opengis.net/gml" xsi:schemaLocation="http://www.opengis.net/wmts/1.0 http://schemas.opengis.net/wmts/1.0/wmtsGetCapabilities_response.xsd" version="1.0.0">
29+
<Contents>
30+
<Layer>
31+
<Title/>
32+
<Abstract/>
33+
<!--Limited list of EPSG projections:-->
34+
<BoundingBox CRS="CRS:84" minx="-124.73142200000001" miny="-43.648056" maxx="148.47914100000003" maxy="49.371735"/>
35+
<Layer queryable="1" opaque="0">
36+
<Name>states_test</Name>
37+
<Title>states_test</Title>
38+
<Abstract>states_test</Abstract>
39+
<KeywordList>
40+
<Keyword>features</Keyword>
41+
<Keyword>states</Keyword>
42+
</KeywordList>
43+
<CRS>EPSG:4326</CRS>
44+
<CRS>CRS:84</CRS>
45+
<EX_GeographicBoundingBox>
46+
<westBoundLongitude>-124.73142200000001</westBoundLongitude>
47+
<eastBoundLongitude>-66.969849</eastBoundLongitude>
48+
<southBoundLatitude>24.955967</southBoundLatitude>
49+
<northBoundLatitude>49.371735</northBoundLatitude>
50+
</EX_GeographicBoundingBox>
51+
<BoundingBox CRS="CRS:84" minx="-124.73142200000001" miny="24.955967" maxx="-66.969849" maxy="49.371735"/>
52+
<BoundingBox CRS="EPSG:4326" minx="24.955967" miny="-124.73142200000001" maxx="49.371735" maxy="-66.969849"/>
53+
<Style>
54+
<Name>polygon</Name>
55+
<Title>A boring default style</Title>
56+
<Abstract>A sample style that just prints out a transparent red interior with a red outline</Abstract>
57+
<LegendURL width="20" height="20">
58+
<Format>image/png</Format>
59+
<OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink" xlink:type="simple" xlink:href="http://gs-stable.geo-solutions.it/geoserver/topp/ows?service=WMS&amp;request=GetLegendGraphic&amp;format=image%2Fpng&amp;width=20&amp;height=20&amp;layer=states_test"/>
60+
</LegendURL>
61+
</Style>
62+
<Format>image/png</Format>
63+
<Format>image/jpeg</Format>
64+
<Format>image/png8</Format>
65+
</Layer>
66+
</Layer>
67+
</Contents>
68+
</Capabilities>`;
69+
70+
const capabilitiesWMTSXmlResponse = `<?xml version="1.0" encoding="UTF-8"?><WMS_Capabilities version="1.3.0" updateSequence="5167" xmlns="http://www.opengis.net/wms" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/wms http://gs-stable.geo-solutions.it/geoserver/schemas/wms/1.3.0/capabilities_1_3_0.xsd">
71+
<Capability>
72+
<Layer>
73+
<Title/>
74+
<Abstract/>
75+
<!--Limited list of EPSG projections:-->
76+
<BoundingBox CRS="CRS:84" minx="-124.73142200000001" miny="-43.648056" maxx="148.47914100000003" maxy="49.371735"/>
77+
<Layer queryable="1" opaque="0">
78+
<Name>states_test</Name>
79+
<Title>states_test</Title>
80+
<Abstract>states_test</Abstract>
81+
<KeywordList>
82+
<Keyword>features</Keyword>
83+
<Keyword>states</Keyword>
84+
</KeywordList>
85+
<CRS>EPSG:4326</CRS>
86+
<CRS>CRS:84</CRS>
87+
<EX_GeographicBoundingBox>
88+
<westBoundLongitude>-124.73142200000001</westBoundLongitude>
89+
<eastBoundLongitude>-66.969849</eastBoundLongitude>
90+
<southBoundLatitude>24.955967</southBoundLatitude>
91+
<northBoundLatitude>49.371735</northBoundLatitude>
92+
</EX_GeographicBoundingBox>
93+
<BoundingBox CRS="CRS:84" minx="-124.73142200000001" miny="24.955967" maxx="-66.969849" maxy="49.371735"/>
94+
<BoundingBox CRS="EPSG:4326" minx="24.955967" miny="-124.73142200000001" maxx="49.371735" maxy="-66.969849"/>
95+
<Style>
96+
<Name>polygon</Name>
97+
<Title>A boring default style</Title>
98+
<Abstract>A sample style that just prints out a transparent red interior with a red outline</Abstract>
99+
<LegendURL width="20" height="20">
100+
<Format>image/png</Format>
101+
<OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink" xlink:type="simple" xlink:href="http://gs-stable.geo-solutions.it/geoserver/topp/ows?service=WMS&amp;request=GetLegendGraphic&amp;format=image%2Fpng&amp;width=20&amp;height=20&amp;layer=states_test"/>
102+
</LegendURL>
103+
</Style>
104+
</Layer>
105+
</Layer>
106+
</Capability>
107+
</WMS_Capabilities>`;
108+
it('test add normal background layer', (done) => {
109+
mockAxios.onGet().reply(200, capabilitiesWMSXmlResponse);
110+
let addBackgroundPropAction = addBackgroundProperties({
111+
layer: {
112+
id: "layer01", allowedSRS: {
113+
"EPSG:3857": true,
114+
"EPSG:900913": true,
115+
"EPSG:4326": true
116+
},
117+
title: "states_test",
118+
type: 'wms',
119+
name: "states_test",
120+
url: ['/geoserver/wms'],
121+
group: "background"
122+
},
123+
editing: false
124+
});
125+
126+
testEpic(backgroundEpics.addBackgroundPropertiesEpic, 2, [addBackgroundPropAction], (res) => {
127+
const action1 = res[0];
128+
const action2 = res[1];
129+
expect(action1).toExist();
130+
expect(action1.type).toEqual(SET_BACKGROUND_MODAL_PARAMS);
131+
expect(action1.modalParams.loading).toEqual(true);
132+
expect(action2).toExist();
133+
expect(action2.type).toEqual(SET_BACKGROUND_MODAL_PARAMS);
134+
expect(action2.modalParams.loading).toEqual(false);
135+
expect(action2.modalParams.capabilities).toExist();
136+
done();
137+
}, {});
138+
139+
});
140+
it('test add wms as a background layer without enabling remote custom tile grid', (done) => {
141+
mockAxios.onGet().reply(200, capabilitiesWMSXmlResponse);
142+
let addBackgroundPropAction = addBackgroundProperties({
143+
layer: {
144+
id: "layer01", allowedSRS: {
145+
"EPSG:3857": true,
146+
"EPSG:900913": true,
147+
"EPSG:4326": true
148+
},
149+
title: "states_test",
150+
type: 'wms',
151+
name: "states_test",
152+
url: '/geoserver/wms',
153+
group: "background"
154+
},
155+
editing: false
156+
});
157+
158+
testEpic(backgroundEpics.addBackgroundPropertiesEpic, 2, [addBackgroundPropAction], (res) => {
159+
const action1 = res[0];
160+
const action2 = res[1];
161+
expect(action1).toExist();
162+
expect(action1.type).toEqual(SET_BACKGROUND_MODAL_PARAMS);
163+
expect(action1.modalParams.loading).toEqual(true);
164+
expect(action2).toExist();
165+
expect(action2.type).toEqual(SET_BACKGROUND_MODAL_PARAMS);
166+
expect(action2.modalParams.loading).toEqual(false);
167+
expect(action2.modalParams.capabilities).toExist();
168+
done();
169+
}, {});
170+
});
171+
it('test add wms as a background layer with enabling remote custom tile grid', (done) => {
172+
mockAxios.onGet().replyOnce(200, capabilitiesWMSXmlResponse);
173+
mockAxios.onGet().replyOnce(200, capabilitiesWMTSXmlResponse);
174+
let addBackgroundPropAction = addBackgroundProperties({
175+
layer: {
176+
id: "layer01", allowedSRS: {
177+
"EPSG:3857": true,
178+
"EPSG:900913": true,
179+
"EPSG:4326": true
180+
},
181+
title: "states_test",
182+
type: 'wms',
183+
name: "states_test",
184+
url: '/geoserver/wms',
185+
group: "background",
186+
remoteTileGrids: true
187+
},
188+
editing: false
189+
});
190+
191+
testEpic(backgroundEpics.addBackgroundPropertiesEpic, 2, [addBackgroundPropAction], (res) => {
192+
const action1 = res[0];
193+
const action2 = res[1];
194+
expect(action1).toExist();
195+
expect(action1.type).toEqual(SET_BACKGROUND_MODAL_PARAMS);
196+
expect(action1.modalParams.loading).toEqual(true);
197+
expect(action2).toExist();
198+
expect(action2.type).toEqual(SET_BACKGROUND_MODAL_PARAMS);
199+
expect(action2.modalParams.loading).toEqual(false);
200+
expect(action2.modalParams.capabilities).toExist();
201+
expect(action2.modalParams.layer.tiled).toEqual(true);
202+
expect(action2.modalParams.layer.tileGridStrategy).toEqual('custom');
203+
done();
204+
}, {});
205+
});
206+
});

web/client/epics/backgroundselector.js

+15-5
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,9 @@ import { UPDATE_NODE, ADD_LAYER, changeLayerProperties, removeNode} from '../act
3232
import { getLayerFromId, currentBackgroundSelector } from '../selectors/layers';
3333
import { backgroundLayersSelector } from '../selectors/backgroundselector';
3434
import { getLayerCapabilities } from '../observables/wms';
35-
import { getLayerOptions } from '../utils/WMSUtils';
35+
import { getCustomTileGridProperties, getLayerOptions } from '../utils/WMSUtils';
36+
import { getLayerTileMatrixSetsInfo } from '../api/WMTS';
37+
import { generateGeoServerWMTSUrl } from '../utils/WMTSUtils';
3638

3739
const accessMetadataExplorer = (action$) =>
3840
action$.ofType(ADD_BACKGROUND)
@@ -46,12 +48,20 @@ const addBackgroundPropertiesEpic = (action$) =>
4648
action$.ofType(ADD_BACKGROUND_PROPERTIES)
4749
.switchMap(({modalParams}) => {
4850
const defaultAction = Rx.Observable.of(setBackgroundModalParams({...modalParams, loading: false}));
51+
const isTileGridNeeded = (!modalParams.editing && modalParams?.layer?.remoteTileGrids);
4952
return modalParams.layer && modalParams.layer.type === 'wms' ?
5053
Rx.Observable.of(setBackgroundModalParams({...modalParams, loading: true}))
51-
.concat(getLayerCapabilities(modalParams.layer)
52-
.switchMap(capabilities => Rx.Observable.of(
53-
setBackgroundModalParams({...modalParams, loading: false, capabilities: getLayerOptions(capabilities)})
54-
))
54+
.concat(Rx.Observable.forkJoin(getLayerCapabilities(modalParams.layer), (!isTileGridNeeded) ?
55+
Rx.Observable.of(null) :
56+
Rx.Observable.defer(() => getLayerTileMatrixSetsInfo(generateGeoServerWMTSUrl(modalParams.layer), modalParams.layer.name, modalParams.layer))
57+
.catch(() => Rx.Observable.of(null)))
58+
59+
.switchMap(([capabilities, tileGridData]) => {
60+
const tileGridProperties = tileGridData ? getCustomTileGridProperties(tileGridData) : {};
61+
return Rx.Observable.of(
62+
setBackgroundModalParams({...modalParams, layer: {...modalParams.layer, ...tileGridProperties}, loading: false, capabilities: getLayerOptions(capabilities)})
63+
);
64+
})
5565
.catch(() => defaultAction)
5666
)
5767
: defaultAction;

web/client/epics/catalog.js

+2-14
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ import { extractGeometryType } from '../utils/WFSLayerUtils';
7676
import { createDefaultStyle } from '../utils/StyleUtils';
7777
import { removeDuplicateLines } from '../utils/StringUtils';
7878
import { logError } from '../utils/DebugUtils';
79-
import { isProjectionAvailable } from '../utils/ProjectionUtils';
79+
import { getCustomTileGridProperties } from '../utils/WMSUtils';
8080
import {getLayerTileMatrixSetsInfo} from '../api/WMTS';
8181
import { getLayerMetadata } from '../api/ArcGIS';
8282

@@ -283,19 +283,7 @@ export default (API) => ({
283283
.catch(() => Rx.Observable.of(null))
284284
)
285285
.switchMap(([results, tileGridData]) => {
286-
let tileGridProperties = {};
287-
if (tileGridData) {
288-
const filteredTileGrids = tileGridData.tileGrids.filter(({ crs }) => isProjectionAvailable(CoordinatesUtils.normalizeSRS(crs)));
289-
tileGridProperties = tileGridData !== undefined ? {
290-
tiled: true,
291-
tileGrids: tileGridData.tileGrids,
292-
tileGridStrategy: 'custom',
293-
tileGridCacheSupport: filteredTileGrids?.length > 0 ?
294-
tileGridData.formats ? {formats: tileGridData.formats} : {}
295-
: undefined
296-
} : {};
297-
298-
}
286+
const tileGridProperties = tileGridData ? getCustomTileGridProperties(tileGridData) : {};
299287
if (results) {
300288
let description = find(results, (desc) => desc.name === layer.name );
301289
if (description && description.owsType === 'WFS') {

web/client/utils/WMSUtils.js

+20-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@
77
*/
88
import { uniq, isObject, castArray } from 'lodash';
99
import { getAvailableInfoFormat } from "./MapInfoUtils";
10-
import { normalizeSRS } from "./CoordinatesUtils";
10+
import CoordinatesUtils, { normalizeSRS } from "./CoordinatesUtils";
11+
import { isProjectionAvailable } from './ProjectionUtils';
1112

1213
// this list provides the supported GetMap formats
1314
// and it will be used to validate GetMap formats coming from capabilities
@@ -112,3 +113,21 @@ export const getTileGridFromLayerOptions = ({
112113
&& !!((tileGrid.tileSizes?.[0]?.[0] || tileGrid.tileSize?.[0]) === tileSize)
113114
);
114115
};
116+
117+
/**
118+
* Return the tileGrids properties like tiled, tileGrids, tileGridCacheSupport and tileGridStrategy
119+
* @param {object} tileGridData tile grid object that includes tileGrids array, formats, tileMatrixSets ..etc
120+
* @return {object} the needed tile grid properties to appended to the layer object
121+
*/
122+
export const getCustomTileGridProperties = (tileGridData) => {
123+
const filteredTileGrids = tileGridData.tileGrids.filter(({ crs }) => isProjectionAvailable(CoordinatesUtils.normalizeSRS(crs)));
124+
const tileGridProperties = tileGridData !== undefined ? {
125+
tiled: true,
126+
tileGrids: tileGridData.tileGrids,
127+
tileGridStrategy: 'custom',
128+
tileGridCacheSupport: filteredTileGrids?.length > 0 ?
129+
tileGridData.formats ? {formats: tileGridData.formats} : {}
130+
: undefined
131+
} : {};
132+
return tileGridProperties;
133+
};

web/client/utils/__tests__/WMSUtils-test.js

+34-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@ import {
1111
isValidGetMapFormat,
1212
isValidGetFeatureInfoFormat,
1313
getLayerOptions,
14-
getTileGridFromLayerOptions
14+
getTileGridFromLayerOptions,
15+
getCustomTileGridProperties
1516
} from '../WMSUtils';
1617

1718
describe('Test the WMSUtils', () => {
@@ -63,4 +64,36 @@ describe('Test the WMSUtils', () => {
6364
expect(getTileGridFromLayerOptions({ projection: 'EPSG:32122', tileSize: 512, tileGrids })).toBe(tileGrids[0]);
6465
expect(getTileGridFromLayerOptions({ projection: 'EPSG:4326', tileSize: 256, tileGrids })).toBe(undefined);
6566
});
67+
it('test getCustomTileGridProperties', () => {
68+
const tileGridData = {
69+
formats: ['image/jpeg', 'image/png'],
70+
tileGrids: [
71+
{
72+
id: 'EPSG:32122',
73+
crs: 'EPSG:32122',
74+
scales: [ 2557541.55271451, 1278770.776357255, 639385.3881786275 ],
75+
origins: [ [ 403035.4105968763, 414783 ], [ 403035.4105968763, 414783 ], [ 403035.4105968763, 323121 ] ],
76+
tileSizes: [[ 512, 512 ], [ 512, 512 ], [ 512, 512 ]]
77+
},
78+
{
79+
id: 'EPSG:900913',
80+
crs: 'EPSG:900913',
81+
scales: [ 559082263.9508929, 279541131.97544646, 139770565.98772323 ],
82+
origin: [ -20037508.34, 20037508 ],
83+
tileSize: [ 256, 256 ]
84+
}
85+
],
86+
tileMatrixSetLinks: [],
87+
tileMatrixSets: [],
88+
styles: []
89+
};
90+
expect(getCustomTileGridProperties(tileGridData)).toEqual({
91+
tileGrids: tileGridData.tileGrids,
92+
tiled: true,
93+
tileGridStrategy: 'custom',
94+
tileGridCacheSupport: {
95+
formats: tileGridData.formats
96+
}
97+
});
98+
});
6699
});

0 commit comments

Comments
 (0)