diff --git a/web/client/components/TOC/fragments/settings/WMSCacheOptions.jsx b/web/client/components/TOC/fragments/settings/WMSCacheOptions.jsx
index 04ac9fd5fc..0df967a465 100644
--- a/web/client/components/TOC/fragments/settings/WMSCacheOptions.jsx
+++ b/web/client/components/TOC/fragments/settings/WMSCacheOptions.jsx
@@ -198,7 +198,10 @@ function WMSCacheOptions({
}) {
const [tileGridLoading, setTileGridLoading] = useState(false);
- const [tileGridsResponseMsgId, setTileGridsResponseMsgId] = useState('');
+ const [tileGridsResponseMsgId, setTileGridsResponseMsgId] = useState(() => {
+ const noTileGrids = layer?.tileGridStrategy === 'custom' && layer?.tiled && layer?.tileGrids?.length === 0;
+ return noTileGrids ? "layerProperties.noConfiguredGridSets" : "";
+ });
const [tileGridsResponseMsgStyle, setTileGridsResponseMsgStyle] = useState('');
const [standardTileGridInfo, setStandardTileGridInfo] = useState({});
diff --git a/web/client/components/TOC/fragments/settings/__tests__/WMSCacheOptions-test.jsx b/web/client/components/TOC/fragments/settings/__tests__/WMSCacheOptions-test.jsx
index fbe7f79991..882cea487a 100644
--- a/web/client/components/TOC/fragments/settings/__tests__/WMSCacheOptions-test.jsx
+++ b/web/client/components/TOC/fragments/settings/__tests__/WMSCacheOptions-test.jsx
@@ -1045,5 +1045,30 @@ describe('WMSCacheOptions', () => {
.catch(done);
});
+ it('should display noConfiguredGridSets warning message if layer is configured from catalog to `Use Cache Options`, with no grid sets available', () => {
+ ReactDOM.render(, document.getElementById('container'));
+ expect(document.querySelector('.ms-wms-cache-options')).toBeTruthy();
+ const inputs = document.querySelectorAll('input[type="checkbox"]');
+ expect(inputs.length).toBe(1);
+ const buttons = document.querySelectorAll('button');
+ expect(buttons.length).toBe(2);
+ expect([...buttons].map(button => button.querySelector('.glyphicon').getAttribute('class'))).toEqual([
+ 'glyphicon glyphicon-refresh',
+ 'glyphicon glyphicon-grid-custom'
+ ]);
+
+ const alert = document.querySelector('.alert');
+ expect(alert.innerText).toBe('layerProperties.noConfiguredGridSets');
+ });
});
diff --git a/web/client/components/catalog/editor/AdvancedSettings/RasterAdvancedSettings.js b/web/client/components/catalog/editor/AdvancedSettings/RasterAdvancedSettings.js
index ea48a0f2ae..6c97d9f8c8 100644
--- a/web/client/components/catalog/editor/AdvancedSettings/RasterAdvancedSettings.js
+++ b/web/client/components/catalog/editor/AdvancedSettings/RasterAdvancedSettings.js
@@ -163,6 +163,14 @@ export default ({
onChange={event => onChangeServiceProperty("layerOptions", { ...service.layerOptions, serverType: event?.value })} />
+ {![ServerTypes.NO_VENDOR].includes(service.layerOptions?.serverType) && service.type === "wms" &&
+ onChangeServiceProperty("layerOptions", { ...service.layerOptions, remoteTileGrids: e.target.checked})}
+ checked={!isNil(service.layerOptions?.remoteTileGrids) ? service.layerOptions?.remoteTileGrids : false}>
+
+ } />
+
+ }
diff --git a/web/client/components/catalog/editor/AdvancedSettings/__tests__/RasterAdvancedSettings-test.js b/web/client/components/catalog/editor/AdvancedSettings/__tests__/RasterAdvancedSettings-test.js
index 4512f22ed3..d04ce06250 100644
--- a/web/client/components/catalog/editor/AdvancedSettings/__tests__/RasterAdvancedSettings-test.js
+++ b/web/client/components/catalog/editor/AdvancedSettings/__tests__/RasterAdvancedSettings-test.js
@@ -33,7 +33,7 @@ describe('Test Raster advanced settings', () => {
const advancedSettingPanel = document.getElementsByClassName("mapstore-switch-panel");
expect(advancedSettingPanel).toBeTruthy();
const fields = document.querySelectorAll(".form-group");
- expect(fields.length).toBe(13);
+ expect(fields.length).toBe(14);
});
it('test csw advanced options', () => {
ReactDOM.render(, document.getElementById("container"));
@@ -209,6 +209,25 @@ describe('Test Raster advanced settings', () => {
expect(spyOn).toHaveBeenCalled();
expect(spyOn.calls[1].arguments).toEqual([ 'allowUnsecureLayers', false ]);
});
+ it('test component onChangeServiceProperty useCacheOption for remote tile grids', () => {
+ const action = {
+ onChangeServiceProperty: () => {}
+ };
+ const spyOn = expect.spyOn(action, 'onChangeServiceProperty');
+ ReactDOM.render(, document.getElementById("container"));
+ const advancedSettingsPanel = document.getElementsByClassName("mapstore-switch-panel");
+ expect(advancedSettingsPanel).toBeTruthy();
+ const formGroup = document.querySelectorAll('.form-group')[6];
+ expect(formGroup.textContent.trim()).toBe('layerProperties.useCacheOptionInfo.label');
+ const useCacheOption = formGroup.querySelector('input[type="checkbox"]');
+ expect(useCacheOption).toBeTruthy();
+ TestUtils.Simulate.change(useCacheOption, { "target": { "checked": true }});
+ expect(spyOn).toHaveBeenCalled();
+ expect(spyOn.calls[0].arguments).toEqual([ 'layerOptions', { remoteTileGrids: true } ]);
+ });
it('test component onChangeServiceProperty singleTile', () => {
const action = {
onChangeServiceProperty: () => {}
diff --git a/web/client/epics/__tests__/catalog-test.js b/web/client/epics/__tests__/catalog-test.js
index c7b143d7a3..b3a7d1c8ff 100644
--- a/web/client/epics/__tests__/catalog-test.js
+++ b/web/client/epics/__tests__/catalog-test.js
@@ -680,6 +680,67 @@ describe('catalog Epics', () => {
}
});
});
+ it('addLayerAndDescribeEpic for wms layer with remoteTileGrids = true', (done) => {
+ const layer = {
+ type: 'wms',
+ url: 'base/web/client/test-resources/wms/DescribeLayers.xml',
+ visibility: true,
+ dimensions: [],
+ name: 'workspace:vector_layer',
+ title: 'workspace:vector_layer',
+ bbox: {"crs": "EPSG:4326", "bounds": {"minx": "-103.87791475407893", "miny": "44.37246687108142", "maxx": "-103.62278893469492", "maxy": "44.50235105543566"}},
+ links: [],
+ params: {
+ CQL_FILTER: 'NAME=\'Test\''
+ },
+ allowedSRS: {
+ 'EPSG:3857': true,
+ 'EPSG:4326': true
+ },
+ remoteTileGrids: true
+ };
+ const NUM_ACTIONS = 3;
+ testEpic(addTimeoutEpic(addLayerAndDescribeEpic, 0), NUM_ACTIONS,
+ addLayerAndDescribe(layer),
+ (actions) => {
+ expect(actions.length).toBe(NUM_ACTIONS);
+ actions.map((action) => {
+ switch (action.type) {
+ case ADD_LAYER:
+ expect(action.layer.name).toBe("workspace:vector_layer");
+ expect(action.layer.title).toBe("workspace:vector_layer");
+ expect(action.layer.type).toBe("wms");
+ expect(action.layer.params).toEqual(layer.params);
+ break;
+ case CHANGE_LAYER_PROPERTIES:
+ expect(action.newProperties).toExist();
+ expect(action.newProperties.search).toExist();
+ expect(action.newProperties.search.url).toBe("http://some.geoserver.org:80/geoserver/wfs");
+ expect(action.newProperties.search.type).toBe("wfs");
+ expect(action.newProperties.tileGridStrategy).toEqual('custom');
+ expect(action.newProperties.tileGrids).toExist();
+ break;
+ case TEST_TIMEOUT:
+ break;
+ default:
+ expect(true).toBe(false);
+ }
+ });
+ done();
+ }, {
+ catalog: {
+ delayAutoSearch: 50,
+ selectedService: "wmsCatalog",
+ services: {
+ "wmsCatalog": {
+ type: "wms",
+ url: "base/web/client/test-resources/wms/GetCapabilities-1.1.1.xml"
+ }
+ },
+ pageSize: 2
+ }
+ });
+ });
it('addLayerAndDescribeEpic multiple urls', (done) => {
const layer = {
type: 'wms',
diff --git a/web/client/epics/catalog.js b/web/client/epics/catalog.js
index 52b961a957..e144d7b661 100644
--- a/web/client/epics/catalog.js
+++ b/web/client/epics/catalog.js
@@ -62,6 +62,7 @@ import {
updateServiceData
} from '../utils/CatalogUtils';
import { getCapabilities, describeLayers, flatLayers } from '../api/WMS';
+import {generateGeoServerWMTSUrl} from '../utils/WMTSUtils';
import CoordinatesUtils from '../utils/CoordinatesUtils';
import ConfigUtils from '../utils/ConfigUtils';
import {getCapabilitiesUrl, getLayerId, getLayerUrl, removeWorkspace, DEFAULT_GROUP_ID} from '../utils/LayersUtils';
@@ -75,6 +76,8 @@ import { extractGeometryType } from '../utils/WFSLayerUtils';
import { createDefaultStyle } from '../utils/StyleUtils';
import { removeDuplicateLines } from '../utils/StringUtils';
import { logError } from '../utils/DebugUtils';
+import { isProjectionAvailable } from '../utils/ProjectionUtils';
+import {getLayerTileMatrixSetsInfo} from '../api/WMTS';
const onErrorRecordSearch = (isNewService, errObj) => {
logError({message: errObj});
@@ -270,8 +273,28 @@ export default (API) => ({
actions.push(zoomToExtent(layer.bbox.bounds, layer.bbox.crs));
}
if (layer.type === 'wms') {
- return Rx.Observable.defer(() => describeLayers(getLayerUrl(layer), layer.name))
- .switchMap(results => {
+ // * fetch the api of cashe option if layer has 'remoteTileGrids' property with true value
+ return Rx.Observable.forkJoin(
+ Rx.Observable.defer(() => describeLayers(getLayerUrl(layer), layer.name)),
+ (!layer?.remoteTileGrids) ?
+ Rx.Observable.of(null) :
+ Rx.Observable.defer(() => getLayerTileMatrixSetsInfo(generateGeoServerWMTSUrl(layer), layer.name, layer))
+ .catch(() => Rx.Observable.of(null))
+ )
+ .switchMap(([results, tileGridData]) => {
+ let tileGridProperties = {};
+ if (tileGridData) {
+ const filteredTileGrids = tileGridData.tileGrids.filter(({ crs }) => isProjectionAvailable(CoordinatesUtils.normalizeSRS(crs)));
+ tileGridProperties = tileGridData !== undefined ? {
+ tiled: true,
+ tileGrids: tileGridData.tileGrids,
+ tileGridStrategy: 'custom',
+ tileGridCacheSupport: filteredTileGrids?.length > 0 ?
+ tileGridData.formats ? {formats: tileGridData.formats} : {}
+ : undefined
+ } : {};
+
+ }
if (results) {
let description = find(results, (desc) => desc.name === layer.name );
if (description && description.owsType === 'WFS') {
@@ -280,9 +303,12 @@ export default (API) => ({
search: {
url: filteredUrl,
type: 'wfs'
- }
+ }, ...tileGridProperties
}));
}
+ return Rx.Observable.of(changeLayerProperties(id, {
+ ...tileGridProperties
+ }));
}
return Rx.Observable.empty();
})
diff --git a/web/client/plugins/widgetbuilder/MapBuilder.jsx b/web/client/plugins/widgetbuilder/MapBuilder.jsx
index d157398840..a483864317 100644
--- a/web/client/plugins/widgetbuilder/MapBuilder.jsx
+++ b/web/client/plugins/widgetbuilder/MapBuilder.jsx
@@ -25,6 +25,10 @@ import mapToolbar from './enhancers/mapToolbar';
import MapLayerSelectorComp from './MapLayerSelector';
import MapSelector from './MapSelector';
import { catalogEditorEnhancer } from './enhancers/catalogEditorEnhancer';
+import { getLayerTileMatrixSetsInfo } from '../../api/WMTS';
+import { generateGeoServerWMTSUrl } from '../../utils/WMTSUtils';
+import { isProjectionAvailable } from '../../utils/ProjectionUtils';
+import { normalizeSRS } from '../../utils/CoordinatesUtils';
const Toolbar = mapToolbar(ToolbarComp);
@@ -51,8 +55,23 @@ const chooseMapEnhancer = compose(
manageLayers,
withHandlers({
onLayerChoice: ({ toggleLayerSelector = () => { }, addLayer = () => { } }) => (layer) => {
- addLayer(layer);
- toggleLayerSelector(false);
+ // fetching 'tileGridData' if layer has truthy flag 'remoteTileGrids' and adding the required props to layer object
+ let tileGridPromise = layer.type === 'wms' && layer.remoteTileGrids ? getLayerTileMatrixSetsInfo(generateGeoServerWMTSUrl(layer), layer.name, layer) : new Promise((resolve) => resolve(null));
+ tileGridPromise.then((tileGridData) => {
+ let tileGridProperties = {};
+ if (tileGridData) {
+ const filteredTileGrids = tileGridData.tileGrids.filter(({ crs }) => isProjectionAvailable(normalizeSRS(crs)));
+ tileGridProperties = tileGridData !== undefined ? {
+ tileGrids: tileGridData.tileGrids,
+ tileGridStrategy: 'custom',
+ tileGridCacheSupport: filteredTileGrids?.length > 0 ?
+ tileGridData.formats ? {formats: tileGridData.formats} : {}
+ : undefined
+ } : {};
+ }
+ addLayer({...layer, ...tileGridProperties});
+ toggleLayerSelector(false);
+ });
}
}),
layerSelector
diff --git a/web/client/translations/data.de-DE.json b/web/client/translations/data.de-DE.json
index e7273ccf9f..c77f45b9c2 100644
--- a/web/client/translations/data.de-DE.json
+++ b/web/client/translations/data.de-DE.json
@@ -207,6 +207,10 @@
"label": "Lokalisierten Stil aktivieren",
"tooltip": "Hinweis: Diese Einstellung benötigt spezifische Konfigurationen im GeoServer"
},
+ "useCacheOptionInfo": {
+ "label": "Verwenden Sie entfernte benutzerdefinierte Kachelraster",
+ "info": "Stellen Sie sicher, dass WMTS aktiviert ist, um benutzerdefinierte Kachelraster verwenden zu können"
+ },
"format": {
"title": "Format",
"tile": "Fliese",
diff --git a/web/client/translations/data.en-US.json b/web/client/translations/data.en-US.json
index 9ae8c5d6bc..9d11b3fdf8 100644
--- a/web/client/translations/data.en-US.json
+++ b/web/client/translations/data.en-US.json
@@ -207,6 +207,10 @@
"label": "Enable localized style",
"tooltip": "Note: This parameter requires specific configurations on GeoServer"
},
+ "useCacheOptionInfo": {
+ "label": "Use remote custom tile grids",
+ "info": "Make sure to have WMTS enabled in order to use custom tile grids"
+ },
"format": {
"title": "Format",
"tile": "Tile",
diff --git a/web/client/translations/data.es-ES.json b/web/client/translations/data.es-ES.json
index 0e79662d5a..4f2e87f2a4 100644
--- a/web/client/translations/data.es-ES.json
+++ b/web/client/translations/data.es-ES.json
@@ -207,6 +207,10 @@
"label": "Habilitar estilo localizado",
"tooltip": "Nota: este parámetro requiere configuraciones específicas en GeoServer"
},
+ "useCacheOptionInfo": {
+ "label": "Utilice cuadrículas de mosaicos personalizadas remotas",
+ "info": "Asegúrese de que WMTS esté habilitado para poder usar cuadrículas de mosaicos personalizadas"
+ },
"format": {
"title": "Formato",
"tile": "Teja",
diff --git a/web/client/translations/data.fr-FR.json b/web/client/translations/data.fr-FR.json
index de5f28047a..7e626abc34 100644
--- a/web/client/translations/data.fr-FR.json
+++ b/web/client/translations/data.fr-FR.json
@@ -207,6 +207,10 @@
"label": "Activer le style localisé",
"tooltip": "Remarque: ce paramètre nécessite des configurations spécifiques sur GeoServer"
},
+ "useCacheOptionInfo": {
+ "label": "Utiliser des grilles de carreaux personnalisées à distance",
+ "info": "Assurez-vous que WMTS est activé afin d'utiliser des grilles de tuiles personnalisées"
+ },
"format": {
"title": "Format",
"tile": "Tile",
diff --git a/web/client/translations/data.it-IT.json b/web/client/translations/data.it-IT.json
index 632f7d7086..a35362ca1e 100644
--- a/web/client/translations/data.it-IT.json
+++ b/web/client/translations/data.it-IT.json
@@ -207,6 +207,10 @@
"label": "Abilita stile localizzato",
"tooltip": "Nota: questo parametro richiede configurazioni specifiche su GeoServer"
},
+ "useCacheOptionInfo": {
+ "label": "Utilizza griglie di riquadri personalizzate remote",
+ "info": "Assicurati che WMTS sia abilitato per utilizzare griglie di riquadri personalizzate"
+ },
"format": {
"title": "Formato",
"tile": "Tile",