From 6b4d66252877d86746752913991885d4cd976056 Mon Sep 17 00:00:00 2001 From: Landry Breuil Date: Wed, 10 Apr 2024 13:53:01 +0200 Subject: [PATCH] support loading COG layers from query params (#9531) * COG services only have a single layer, use provided layer text as title (#9527) * create COG layer on the fly if none is provided (#9527) * use properly named parameters for getLayerConfig call * return layer in case getLayerConfig failed * add documentation about loading COG layer via viewer parameters (#9531) * Update docs/developer-guide/map-query-parameters.md --------- Co-authored-by: Suren --- docs/developer-guide/map-query-parameters.md | 17 +++++++++++++++- web/client/api/catalog/COG.js | 21 +++++++++++++++++++- web/client/epics/catalog.js | 2 +- 3 files changed, 37 insertions(+), 3 deletions(-) diff --git a/docs/developer-guide/map-query-parameters.md b/docs/developer-guide/map-query-parameters.md index e457315bc0..dd24c3331f 100644 --- a/docs/developer-guide/map-query-parameters.md +++ b/docs/developer-guide/map-query-parameters.md @@ -343,7 +343,7 @@ Requirements: - The number of layers should match the number of sources - The source name can be a string that must match a catalog service name present in the map or an object that defines an external catalog (see example) -Supported layer types are WMS, WMTS, WFS, 3D Tiles and GeoJSON. +Supported layer types are WMS, WMTS, WFS, COG, 3D Tiles and GeoJSON. Example: @@ -372,6 +372,21 @@ GET `#/viewer/config?actions=[{"type":"CATALOG:ADD_LAYERS_FROM_CATALOGS","layers Number of objects passed to the options can be different to the number of layers, in this case options will be applied to the first X layers, where X is the length of options array. +The COG service endpoint does not contain a default property for the name of the layer and it returns only a single record for this reason the name used in the layers array will be used to apply the title to the added COG layer: + +```json +{ + "type": "CATALOG:ADD_LAYERS_FROM_CATALOGS", + "layers": ["My huge remote satellite COG"], + "sources": [{ "type":"cog", "url":"https://example.com/satellite_imagery.tif" }] +} +``` + +GET: `#/viewer/config?actions=[{"type":"CATALOG:ADD_LAYERS_FROM_CATALOGS","layers":["My huge remote satellite COG"],"sources":[{"type":"cog","url":"https://example.com/satellite_imagery.tif"}]}]` + +!!! note + Depending on the internal structure optimization done on the remote COG source, the map load time might be long. Furthermore, it is not feasible to cancel metadata fetching for the COG layer(s) when loading layers via query parameters. + The 3D tiles service endpoint does not contain a default property for the name of the layer and it returns only a single record for this reason the name used in the layers array will be used to apply the title to the added 3D Tiles layer: ```json diff --git a/web/client/api/catalog/COG.js b/web/client/api/catalog/COG.js index b4dc74299c..303e8e4b82 100644 --- a/web/client/api/catalog/COG.js +++ b/web/client/api/catalog/COG.js @@ -34,6 +34,7 @@ const searchAndPaginate = (layers, startPosition, maxRecords, text) => { let capabilitiesCache = {}; export const getRecords = (_url, startPosition, maxRecords, text, info = {}) => { const service = get(info, 'options.service'); + const controller = get(info, 'options.controller'); let layers = []; if (service.records) { // each record/url corresponds to a layer @@ -46,7 +47,6 @@ export const getRecords = (_url, startPosition, maxRecords, text, info = {}) => sources: record.sources ?? [{url}], options: record.options ?? (service.options || {}) }; - const controller = get(info, 'options.controller'); const isSave = get(info, 'options.save', false); const cached = capabilitiesCache[url]; if (cached && new Date().getTime() < cached.timestamp + (ConfigUtils.getConfigProp('cacheExpire') || 60) * 1000) { @@ -68,6 +68,25 @@ export const getRecords = (_url, startPosition, maxRecords, text, info = {}) => }); } return Promise.all([...layers]).then((_layers) => { + if (!_layers.length) { + let layer = { + ...service, + title: text, + identifier: _url, + type: COG_LAYER_TYPE, + sources: [{url: _url}], + options: service.options || {} + }; + return LayerUtils.getLayerConfig({url: _url, layer, controller}) + .then(lyr => { + const records = [lyr]; + return { + numberOfRecordsMatched: 1, + numberOfRecordsReturned: 1, + records + }; + }).catch(() => ({...layer})); + } return searchAndPaginate(_layers, startPosition, maxRecords, text); }); }; diff --git a/web/client/epics/catalog.js b/web/client/epics/catalog.js index aa7c3b1b4e..52b961a957 100644 --- a/web/client/epics/catalog.js +++ b/web/client/epics/catalog.js @@ -176,7 +176,7 @@ export default (API) => ({ const layerOptionsParam = get(options, i, searchOptionsSelector(state)); // use the selected layer text as title for 3d tiles // because currently we get only a single record for this service type - const layerOptions = format === '3dtiles' || format === 'geojson' + const layerOptions = format === '3dtiles' || format === 'geojson' || format === 'cog' ? { ...layerOptionsParam, title: isObject(layerOptionsParam?.title)