From 5f2168eee8edb39ac65fadcef9afbfa0d2c2ed2a Mon Sep 17 00:00:00 2001 From: Suren Date: Tue, 19 Mar 2024 22:57:25 +0530 Subject: [PATCH] #10083: Persistence of COG layer's metadata info in catalog service (#10089) (cherry picked from commit 847c1308fe41f3f58f770014b209cc7540f23d30) --- docs/developer-guide/local-config.md | 36 ++++++++++++++++++- web/client/api/catalog/COG.js | 10 +++--- web/client/api/catalog/__tests__/COG-test.js | 3 +- web/client/epics/catalog.js | 5 +-- web/client/utils/CatalogUtils.js | 19 +++++++++- .../utils/__tests__/CatalogUtils-test.js | 9 +++++ 6 files changed, 72 insertions(+), 10 deletions(-) diff --git a/docs/developer-guide/local-config.md b/docs/developer-guide/local-config.md index 16d227a047..34a26cc71b 100644 --- a/docs/developer-guide/local-config.md +++ b/docs/developer-guide/local-config.md @@ -218,7 +218,13 @@ Set `selectedService` value to one of the ID of the services object ("Demo CSW S "filter": { // applicable only for CSW service "staticFilter": "filter is always applied, even when search text is NOT PRESENT", "dynamicFilter": "filter is used when search text is PRESENT and is applied in `AND` with staticFilter. The template is used with ${searchText} placeholder to append search string" - } + }, + "fetchMetadata": true, // "if true, the metadata is fetched for the service, applicable only for COG service + "records": [{ // array of the COG layers of the service, applicable only for COG service + "sourceMetadata": "metadata of the COG layer", + "bbox": "bbox formulated for the COG layer", + "url": "the url pointing to the COG layer data" + }] } ``` @@ -235,6 +241,34 @@ CSW service } ``` +COG service +
`fetchMetadata` - By default, the metadata is fetched on saving the COG service for each layer (url) configured
+
`records` - Records of the COG layer
+
Example:
+ +```javascript +{ + "fetchMetadata": true, + "records": [{ + "url": "https://example.tif", + "sourceMetadata": { + "crs": "EPSG:32632", + "extent": [463560, 5758030, 469410, 5767210], + "height": 900, + "width": 500, + "tileWidth": 256, + "tileHeight": 256, + "origin": [463560, 5767210, 0], + "resolution": [10, -10, 0] + }, + "bbox": { + "crs": "EPSG:32632" + "bounds": {minx: 463560, miny: 5758030, maxx: 469410, maxy: 5767210} + } + }] +} +``` +
Be careful to use unique IDs
Future implementations will try to detect the type from the url.
newService is used internally as the starting object for an empty service. diff --git a/web/client/api/catalog/COG.js b/web/client/api/catalog/COG.js index a7de6e4814..0629141038 100644 --- a/web/client/api/catalog/COG.js +++ b/web/client/api/catalog/COG.js @@ -15,8 +15,8 @@ import { fromUrl as fromGeotiffUrl } from 'geotiff'; import { isValidURL } from '../../utils/URLUtils'; import ConfigUtils from '../../utils/ConfigUtils'; import { isProjectionAvailable } from '../../utils/ProjectionUtils'; +import { COG_LAYER_TYPE } from '../../utils/CatalogUtils'; -export const COG_LAYER_TYPE = 'cog'; const searchAndPaginate = (layers, startPosition, maxRecords, text) => { const filteredLayers = layers .filter(({ title = "" } = {}) => !text @@ -85,11 +85,11 @@ export const getRecords = (_url, startPosition, maxRecords, text, info = {}) => layers = service.records?.map((record) => { const url = record.url; let layer = { - ...service, + ...record, title: record.title, - type: COG_LAYER_TYPE, - sources: [{url}], - options: service.options || {} + type: record.type ?? COG_LAYER_TYPE, + sources: record.sources ?? [{url}], + options: record.options ?? (service.options || {}) }; const controller = get(info, 'options.controller'); const isSave = get(info, 'options.save', false); diff --git a/web/client/api/catalog/__tests__/COG-test.js b/web/client/api/catalog/__tests__/COG-test.js index b9c42116ff..315b996603 100644 --- a/web/client/api/catalog/__tests__/COG-test.js +++ b/web/client/api/catalog/__tests__/COG-test.js @@ -5,7 +5,8 @@ * This source code is licensed under the BSD-style license found in the * LICENSE file in the root directory of this source tree. */ -import { getLayerFromRecord, getCatalogRecords, validate, COG_LAYER_TYPE, getProjectionFromGeoKeys} from '../COG'; +import { COG_LAYER_TYPE } from '../../../utils/CatalogUtils'; +import { getLayerFromRecord, getCatalogRecords, validate, getProjectionFromGeoKeys} from '../COG'; import expect from 'expect'; diff --git a/web/client/epics/catalog.js b/web/client/epics/catalog.js index 50d650f391..ee00fe1ef1 100644 --- a/web/client/epics/catalog.js +++ b/web/client/epics/catalog.js @@ -58,7 +58,8 @@ import { getSelectedLayer, selectedNodesSelector } from '../selectors/layers'; import { buildSRSMap, - extractOGCServicesReferences + extractOGCServicesReferences, + updateServiceData } from '../utils/CatalogUtils'; import { getCapabilities, describeLayers, flatLayers } from '../api/WMS'; import CoordinatesUtils from '../utils/CoordinatesUtils'; @@ -130,7 +131,7 @@ export default (API) => ({ // The records are saved to catalog state on successful saving of the service. // The flag is used to show/hide records on load in Catalog setNewServiceStatus(true), - addCatalogService(options.service), + addCatalogService(updateServiceData(options, result)), success({ title: "notification.success", message: "catalog.notification.addCatalogService", diff --git a/web/client/utils/CatalogUtils.js b/web/client/utils/CatalogUtils.js index 4c3b473513..a4860c9006 100644 --- a/web/client/utils/CatalogUtils.js +++ b/web/client/utils/CatalogUtils.js @@ -7,8 +7,9 @@ */ import assign from 'object-assign'; -import { head, isArray } from 'lodash'; +import { head, isArray, get } from 'lodash'; import CoordinatesUtils from './CoordinatesUtils'; +export const COG_LAYER_TYPE = 'cog'; export const buildSRSMap = (srs) => { return srs.filter(s => CoordinatesUtils.isSRSAllowed(s)).reduce((previous, current) => { @@ -92,3 +93,19 @@ export const toURLArray = (url) => { } return url; }; + +export const updateServiceData = (options, result) => { + const isCOGService = get(options, 'service.type') === COG_LAYER_TYPE; + + if (isCOGService) { + const records = get(options, 'service.records', []); + return { + ...options.service, + records: records.map(record => ({ + ...record, + ...result?.records?.find(_record => _record.url === record.url) + })) + }; + } + return options.service; +}; diff --git a/web/client/utils/__tests__/CatalogUtils-test.js b/web/client/utils/__tests__/CatalogUtils-test.js index 80df71701e..1ba4bb7139 100644 --- a/web/client/utils/__tests__/CatalogUtils-test.js +++ b/web/client/utils/__tests__/CatalogUtils-test.js @@ -46,4 +46,13 @@ describe('Test the CatalogUtils', () => { expect(mergedURL3).toBe("https://a.example.com/wms,https://b.example.com/wms,https://c.example.com/wms"); expect(mergedURL4).toBe("https://a.example.com/wms,https://b.example.com/wms"); }); + it("updateServiceData", () => { + let records = [{"url": "https://example.tif", sourceMetadata: {crs: "EPSG:3003"}}]; + let options = {service: {type: CatalogUtils.COG_LAYER_TYPE, records: [{url: "https://example.tif"}]}}; + expect(CatalogUtils.updateServiceData(options, {records})).toEqual({...options.service, records}); + + records = [{"url": "https://example.tif", sourceMetadata: {crs: "EPSG:3003"}}]; + options = {service: {type: "wms", "autoload": true}}; + expect(CatalogUtils.updateServiceData(options, {records})).toEqual(options.service); + }); });