diff --git a/common/config/rush/pnpm-lock.yaml b/common/config/rush/pnpm-lock.yaml
index 297f5e903f0..ba9065963d5 100644
--- a/common/config/rush/pnpm-lock.yaml
+++ b/common/config/rush/pnpm-lock.yaml
@@ -143,7 +143,7 @@ importers:
version: 6.3.1(@emotion/react@11.14.0)(@emotion/styled@11.14.0)(@types/react@18.3.18)(react@18.3.1)
'@mui/x-date-pickers':
specifier: ^7.20.0
- version: 7.23.3(@emotion/react@11.14.0)(@emotion/styled@11.14.0)(@mui/material@6.3.1)(@mui/system@6.3.1)(@types/react@18.3.18)(dayjs@1.11.13)(react-dom@18.3.1)(react@18.3.1)
+ version: 7.23.6(@emotion/react@11.14.0)(@emotion/styled@11.14.0)(@mui/material@6.3.1)(@mui/system@6.3.1)(@types/react@18.3.18)(dayjs@1.11.13)(react-dom@18.3.1)(react@18.3.1)
'@nieuwlandgeo/sldreader':
specifier: ^0.4.3
version: 0.4.3(ol@10.3.1)
@@ -200,7 +200,7 @@ importers:
version: 7.5.1(react@18.3.1)
material-react-table:
specifier: ^3.0.1
- version: 3.1.0(@emotion/react@11.14.0)(@emotion/styled@11.14.0)(@mui/icons-material@6.3.1)(@mui/material@6.3.1)(@mui/x-date-pickers@7.23.3)(react-dom@18.3.1)(react@18.3.1)
+ version: 3.1.0(@emotion/react@11.14.0)(@emotion/styled@11.14.0)(@mui/icons-material@6.3.1)(@mui/material@6.3.1)(@mui/x-date-pickers@7.23.6)(react-dom@18.3.1)(react@18.3.1)
ol:
specifier: ^10.2.1
version: 10.3.1
@@ -2962,8 +2962,8 @@ packages:
react-is: 19.0.0
dev: false
- /@mui/x-date-pickers@7.23.3(@emotion/react@11.14.0)(@emotion/styled@11.14.0)(@mui/material@6.3.1)(@mui/system@6.3.1)(@types/react@18.3.18)(dayjs@1.11.13)(react-dom@18.3.1)(react@18.3.1):
- resolution: {integrity: sha512-bjTYX/QzD5ZhVZNNnastMUS3j2Hy4p4IXmJgPJ0vKvQBvUdfEO+ZF42r3PJNNde0FVT1MmTzkmdTlz0JZ6ukdw==}
+ /@mui/x-date-pickers@7.23.6(@emotion/react@11.14.0)(@emotion/styled@11.14.0)(@mui/material@6.3.1)(@mui/system@6.3.1)(@types/react@18.3.18)(dayjs@1.11.13)(react-dom@18.3.1)(react@18.3.1):
+ resolution: {integrity: sha512-jt6rEAYLju3NZe3y2S+I5KcTiSHV79FW0jeNUEUTceg1qsPzseHbND66k3zVF0hO3N2oZtLtPywof6vN5Doe+Q==}
engines: {node: '>=14.0.0'}
peerDependencies:
'@emotion/react': ^11.9.0
@@ -2971,7 +2971,7 @@ packages:
'@mui/material': ^5.15.14 || ^6.0.0
'@mui/system': ^5.15.14 || ^6.0.0
date-fns: ^2.25.0 || ^3.2.0 || ^4.0.0
- date-fns-jalali: ^2.13.0-0 || ^3.2.0-0
+ date-fns-jalali: ^2.13.0-0 || ^3.2.0-0 || ^4.0.0-0
dayjs: ^1.10.7
luxon: ^3.0.2
moment: ^2.29.4
@@ -3005,7 +3005,7 @@ packages:
'@mui/material': 6.3.1(@emotion/react@11.14.0)(@emotion/styled@11.14.0)(@types/react@18.3.18)(react-dom@18.3.1)(react@18.3.1)
'@mui/system': 6.3.1(@emotion/react@11.14.0)(@emotion/styled@11.14.0)(@types/react@18.3.18)(react@18.3.1)
'@mui/utils': 6.3.1(@types/react@18.3.18)(react@18.3.1)
- '@mui/x-internals': 7.23.0(@types/react@18.3.18)(react@18.3.1)
+ '@mui/x-internals': 7.23.6(@types/react@18.3.18)(react@18.3.1)
'@types/react-transition-group': 4.4.12(@types/react@18.3.18)
clsx: 2.1.1
dayjs: 1.11.13
@@ -3017,8 +3017,8 @@ packages:
- '@types/react'
dev: false
- /@mui/x-internals@7.23.0(@types/react@18.3.18)(react@18.3.1):
- resolution: {integrity: sha512-bPclKpqUiJYIHqmTxSzMVZi6MH51cQsn5U+8jskaTlo3J4QiMeCYJn/gn7YbeR9GOZFp8hetyHjoQoVHKRXCig==}
+ /@mui/x-internals@7.23.6(@types/react@18.3.18)(react@18.3.1):
+ resolution: {integrity: sha512-hT1Pa4PNCnxwiauPbYMC3p4DiEF1x05Iu4C1MtC/jMJ1LtthymLmTuQ6ZQ53/R9FeqK6sYd6A6noR+vNMjp5DA==}
engines: {node: '>=14.0.0'}
peerDependencies:
react: ^17.0.0 || ^18.0.0 || ^19.0.0
@@ -4517,8 +4517,8 @@ packages:
engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7}
hasBin: true
dependencies:
- caniuse-lite: 1.0.30001690
- electron-to-chromium: 1.5.79
+ caniuse-lite: 1.0.30001692
+ electron-to-chromium: 1.5.80
node-releases: 2.0.19
update-browserslist-db: 1.1.2(browserslist@4.24.4)
dev: true
@@ -4592,8 +4592,8 @@ packages:
engines: {node: '>=10'}
dev: true
- /caniuse-lite@1.0.30001690:
- resolution: {integrity: sha512-5ExiE3qQN6oF8Clf8ifIDcMRCRE/dMGcETG/XGMD8/XiXm6HXQgQTh1yZYLXXpSOsEUlJm1Xr7kGULZTuGtP/w==}
+ /caniuse-lite@1.0.30001692:
+ resolution: {integrity: sha512-A95VKan0kdtrsnMubMKxEKUKImOPSuCpYgxSQBo036P5YYgVIcOYJEgt/txJWqObiRQeISNCfef9nvlQ0vbV7A==}
dev: true
/ccount@2.0.1:
@@ -5288,8 +5288,8 @@ packages:
resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==}
dev: true
- /electron-to-chromium@1.5.79:
- resolution: {integrity: sha512-nYOxJNxQ9Om4EC88BE4pPoNI8xwSFf8pU/BAeOl4Hh/b/i6V4biTAzwV7pXi3ARKeoYO5JZKMIXTryXSVer5RA==}
+ /electron-to-chromium@1.5.80:
+ resolution: {integrity: sha512-LTrKpW0AqIuHwmlVNV+cjFYTnXtM9K37OGhpe0ZI10ScPSxqVSryZHIY3WnCS5NSYbBODRTZyhRMS2h5FAEqAw==}
dev: true
/email-addresses@5.0.0:
@@ -6594,8 +6594,8 @@ packages:
toidentifier: 1.0.1
dev: true
- /http-parser-js@0.5.8:
- resolution: {integrity: sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q==}
+ /http-parser-js@0.5.9:
+ resolution: {integrity: sha512-n1XsPy3rXVxlqxVioEWdC+0+M+SQw0DpJynwtOPo1X+ZlvdzTLtDBIJJlDQTnwZIFJrZSzSGmIOUdP8tu+SgLw==}
dev: true
/http-proxy-middleware@2.0.7(@types/express@4.17.21):
@@ -7878,7 +7878,7 @@ packages:
hasBin: true
dev: true
- /material-react-table@3.1.0(@emotion/react@11.14.0)(@emotion/styled@11.14.0)(@mui/icons-material@6.3.1)(@mui/material@6.3.1)(@mui/x-date-pickers@7.23.3)(react-dom@18.3.1)(react@18.3.1):
+ /material-react-table@3.1.0(@emotion/react@11.14.0)(@emotion/styled@11.14.0)(@mui/icons-material@6.3.1)(@mui/material@6.3.1)(@mui/x-date-pickers@7.23.6)(react-dom@18.3.1)(react@18.3.1):
resolution: {integrity: sha512-/zPn38QhxQE7mkwLex4CojX3UP2+/+/u7NVq7CHS5d6P8LdTteJPVYXVzym/uhaXzAzFB1ojsbP7zI/y6iUdtQ==}
engines: {node: '>=16'}
peerDependencies:
@@ -7894,7 +7894,7 @@ packages:
'@emotion/styled': 11.14.0(@emotion/react@11.14.0)(@types/react@18.3.18)(react@18.3.1)
'@mui/icons-material': 6.3.1(@mui/material@6.3.1)(@types/react@18.3.18)(react@18.3.1)
'@mui/material': 6.3.1(@emotion/react@11.14.0)(@emotion/styled@11.14.0)(@types/react@18.3.18)(react-dom@18.3.1)(react@18.3.1)
- '@mui/x-date-pickers': 7.23.3(@emotion/react@11.14.0)(@emotion/styled@11.14.0)(@mui/material@6.3.1)(@mui/system@6.3.1)(@types/react@18.3.18)(dayjs@1.11.13)(react-dom@18.3.1)(react@18.3.1)
+ '@mui/x-date-pickers': 7.23.6(@emotion/react@11.14.0)(@emotion/styled@11.14.0)(@mui/material@6.3.1)(@mui/system@6.3.1)(@types/react@18.3.18)(dayjs@1.11.13)(react-dom@18.3.1)(react@18.3.1)
'@tanstack/match-sorter-utils': 8.19.4
'@tanstack/react-table': 8.20.6(react-dom@18.3.1)(react@18.3.1)
'@tanstack/react-virtual': 3.11.2(react-dom@18.3.1)(react@18.3.1)
@@ -7931,8 +7931,8 @@ packages:
engines: {node: '>= 0.6'}
dev: true
- /memfs@4.15.3:
- resolution: {integrity: sha512-vR/g1SgqvKJgAyYla+06G4p/EOcEmwhYuVb1yc1ixcKf8o/sh7Zngv63957ZSNd1xrZJoinmNyDf2LzuP8WJXw==}
+ /memfs@4.17.0:
+ resolution: {integrity: sha512-4eirfZ7thblFmqFjywlTmuWVSvccHAJbn1r8qQLzmTO11qcqpohOjmY2mFce6x7x7WtskzRqApPD0hv+Oa74jg==}
engines: {node: '>= 4.0.0'}
dependencies:
'@jsonjoy.com/json-pack': 1.1.1(tslib@2.8.1)
@@ -10198,7 +10198,7 @@ packages:
optional: true
dependencies:
colorette: 2.0.20
- memfs: 4.15.3
+ memfs: 4.17.0
mime-types: 2.1.35
on-finished: 2.4.1
range-parser: 1.2.1
@@ -10322,7 +10322,7 @@ packages:
resolution: {integrity: sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==}
engines: {node: '>=0.8.0'}
dependencies:
- http-parser-js: 0.5.8
+ http-parser-js: 0.5.9
safe-buffer: 5.2.1
websocket-extensions: 0.1.4
dev: true
diff --git a/packages/geoview-core/public/templates/demos/demo-function-event.html b/packages/geoview-core/public/templates/demos/demo-function-event.html
index 2e2b02ce8ac..65e538da857 100644
--- a/packages/geoview-core/public/templates/demos/demo-function-event.html
+++ b/packages/geoview-core/public/templates/demos/demo-function-event.html
@@ -207,6 +207,9 @@
Events that will generate notifications:
const LYR_PATH_FEATURE = "esriFeatureLYR5/0";
const LYR_PATH_GEOCORE = "f4c51eaa-a6ca-48b9-a1fc-b0651da20509";
+ var CNT_GENERIC_STATUS_CHANGE = 0;
+ var CNT_SPECIFIC_STATUS_CHANGE = 0;
+
// Register a handler when the map is init
cgpv.onMapInit((mapId) => {
// !!
@@ -269,7 +272,7 @@ Events that will generate notifications:
// listen to ANY/ALL layer status at ANY time (generic event catcher)
cgpv.api.maps[mapId].layer.legendsLayerSet.onLayerStatusUpdated((sender, payload) => {
//cgpv.api.maps.Map1.notifications.addNotificationSuccess(`${payload.layer.layerPath} (generic event) status changed to ${payload.layer.layerStatus}`);
- console.log(`${payload.layer.layerPath} (generic event) status changed to ${payload.layer.layerStatus}`);
+ console.log(`${payload.layer.layerPath} (generic event ${++CNT_GENERIC_STATUS_CHANGE}) status changed to ${payload.layer.layerStatus}`);
});
// listen to layer item visibility changed event (any layers)
@@ -298,9 +301,10 @@ Events that will generate notifications:
// Check the layer status of the particular layer before registering the hook - to really know at which status the layer is.
// GV If you really want to make sure to track ALL status changes for ANY particular layer, you can use a hook such as:
// `cgpv.api.maps[mapId].layer.legendsLayerSet.onLayerStatusUpdated()`. See example in cgpv.onMapInit handler above.
+
cgpv.api.maps.Map1.layer.getLayerEntryConfig(LYR_PATH_UNIQUE)?.onLayerStatusChanged((sender, payload) => {
cgpv.api.maps.Map1.notifications.addNotificationSuccess(`${LYR_PATH_UNIQUE} (specific event) status changed to ${payload.layerStatus}`);
- console.log(`${LYR_PATH_UNIQUE} (specific event) status changed to ${payload.layerStatus}`);
+ console.log(`${LYR_PATH_UNIQUE} (specific event ${++CNT_SPECIFIC_STATUS_CHANGE}) status changed to ${payload.layerStatus}`);
});
// listen to individual layer loaded event
diff --git a/packages/geoview-core/public/templates/demos/demo-osdp-integration.html b/packages/geoview-core/public/templates/demos/demo-osdp-integration.html
index 8eeb08b529a..640d8efa948 100644
--- a/packages/geoview-core/public/templates/demos/demo-osdp-integration.html
+++ b/packages/geoview-core/public/templates/demos/demo-osdp-integration.html
@@ -243,7 +243,7 @@ OSDP Integration
/** OSDP function
* Adds layers to the map.
- *
+ *
* @param layers Array of layers.
*/
function addLayers(layers) {
diff --git a/packages/geoview-core/src/core/components/layers/left-panel/add-new-layer/add-new-layer.tsx b/packages/geoview-core/src/core/components/layers/left-panel/add-new-layer/add-new-layer.tsx
index 10389f713cd..5af4aac8779 100644
--- a/packages/geoview-core/src/core/components/layers/left-panel/add-new-layer/add-new-layer.tsx
+++ b/packages/geoview-core/src/core/components/layers/left-panel/add-new-layer/add-new-layer.tsx
@@ -248,7 +248,7 @@ export function AddNewLayer(): JSX.Element {
geoviewLayerConfig: wmsGeoviewLayerConfig,
layerId: childLayer.Name as string,
layerName: childLayer.Title as string,
- } as OgcWmsLayerEntryConfig)
+ } as unknown as OgcWmsLayerEntryConfig)
);
}
diff --git a/packages/geoview-core/src/core/utils/config/validation-classes/config-base-class.ts b/packages/geoview-core/src/core/utils/config/validation-classes/config-base-class.ts
index b570ef3e581..20f69c5f0e0 100644
--- a/packages/geoview-core/src/core/utils/config/validation-classes/config-base-class.ts
+++ b/packages/geoview-core/src/core/utils/config/validation-classes/config-base-class.ts
@@ -149,6 +149,9 @@ export abstract class ConfigBaseClass {
}
if (newLayerStatus === 'processed' && this.#waitForProcessedBeforeSendingLoaded) this.layerStatus = 'loaded';
+ // GV For quick debug, uncomment the line
+ // if (newLayerStatus === 'error') debugger;
+
// TODO: Cleanup - Commenting this and leaving it here for now.. It turns out that the parentLayerConfig property can't be trusted
// GV due to a bug with different instances of entryconfigs stored in the objects and depending how you navigate the objects, you get
// GV different instances. Example below (where 'parentLayerConfig.listOfLayerEntryConfig[0]' is indeed going back to 'uniqueValueId/uniqueValueId/4')
@@ -222,6 +225,28 @@ export abstract class ConfigBaseClass {
} as unknown as TypeJsonObject;
}
+ /**
+ * Clones the configuration class.
+ *
+ * @returns {ConfigBaseClass} The cloned ConfigBaseClass object.
+ */
+ clone(): ConfigBaseClass {
+ // Redirect to clone the object and return it
+ return this.onClone();
+ }
+
+ /**
+ * Overridable function to clone a child of a ConfigBaseClass.
+ *
+ * @returns {ConfigBaseClass} The cloned child object of a ConfigBaseClass.
+ */
+ protected onClone(): ConfigBaseClass {
+ // Crash on purpose.
+ // GV Make sure to implement a 'protected override onClone(): ConfigBaseClass' in the child-class to
+ // GV use this cloning feature. See OgcWMSLayerEntryConfig for example.
+ throw new Error(`Not implemented exception onClone on layer path ${this.layerPath}`);
+ }
+
/**
* Recursively checks the list of layer entries to see if all of them are greater than or equal to the provided layer status.
*
diff --git a/packages/geoview-core/src/core/utils/config/validation-classes/raster-validation-classes/ogc-wms-layer-entry-config.ts b/packages/geoview-core/src/core/utils/config/validation-classes/raster-validation-classes/ogc-wms-layer-entry-config.ts
index 87796dd0ba7..2a42a3b7874 100644
--- a/packages/geoview-core/src/core/utils/config/validation-classes/raster-validation-classes/ogc-wms-layer-entry-config.ts
+++ b/packages/geoview-core/src/core/utils/config/validation-classes/raster-validation-classes/ogc-wms-layer-entry-config.ts
@@ -1,5 +1,6 @@
import { CONST_LAYER_TYPES } from '@/geo/layer/geoview-layers/abstract-geoview-layers';
import { CONST_LAYER_ENTRY_TYPES, TypeSourceImageWmsInitialConfig } from '@/geo/map/map-schema-types';
+import { ConfigBaseClass } from '@/core/utils/config/validation-classes/config-base-class';
import { AbstractBaseLayerEntryConfig } from '@/core/utils/config/validation-classes/abstract-base-layer-entry-config';
/** ******************************************************************************************************************************
@@ -40,4 +41,13 @@ export class OgcWmsLayerEntryConfig extends AbstractBaseLayerEntryConfig {
// Default value for layerConfig.source.serverType is 'mapserver'.
if (!this.source.serverType) this.source.serverType = 'mapserver';
}
+
+ /**
+ * Clones an instance of a OgcWmsLayerEntryConfig.
+ *
+ * @returns {ConfigBaseClass} The cloned OgcWmsLayerEntryConfig instance
+ */
+ protected override onClone(): ConfigBaseClass {
+ return new OgcWmsLayerEntryConfig(this);
+ }
}
diff --git a/packages/geoview-core/src/geo/layer/geoview-layers/esri-layer-common.ts b/packages/geoview-core/src/geo/layer/geoview-layers/esri-layer-common.ts
index 3a425c35211..323200c9a6b 100644
--- a/packages/geoview-core/src/geo/layer/geoview-layers/esri-layer-common.ts
+++ b/packages/geoview-core/src/geo/layer/geoview-layers/esri-layer-common.ts
@@ -142,7 +142,8 @@ export function commonValidateListOfLayerEntryConfig(
// TODO: Refactor: Do not do this on the fly here anymore with the new configs (quite unpredictable)...
// Don't forget to replace the old version in the registered layers
- MapEventProcessor.getMapViewerLayerAPI(layer.mapId).setLayerEntryConfigObsolete(groupLayerConfig);
+ // TODO: Officially remove setLayerEntryConfigObsolete once passed testing
+ // MapEventProcessor.getMapViewerLayerAPI(layer.mapId).setLayerEntryConfigObsolete(groupLayerConfig);
(layer.metadata!.layers[esriIndex].subLayerIds as TypeJsonArray).forEach((layerId) => {
// Make sure to copy the layerConfig source before recycling it in the constructors. This was causing the 'source' value to leak between layer entry configs
@@ -164,7 +165,8 @@ export function commonValidateListOfLayerEntryConfig(
// FIXME: Temporary patch to keep the behavior until those layer classes don't exist
// TODO: Refactor: Do not do this on the fly here anymore with the new configs (quite unpredictable)... (standardizing this call with the other one above for now)
- MapEventProcessor.getMapViewerLayerAPI(layer.mapId).setLayerEntryConfigObsolete(subLayerEntryConfig);
+ // TODO: Officially remove setLayerEntryConfigObsolete once passed testing
+ // MapEventProcessor.getMapViewerLayerAPI(layer.mapId).setLayerEntryConfigObsolete(subLayerEntryConfig);
});
layer.validateListOfLayerEntryConfig(newListOfLayerEntryConfig);
diff --git a/packages/geoview-core/src/geo/layer/geoview-layers/raster/wms.ts b/packages/geoview-core/src/geo/layer/geoview-layers/raster/wms.ts
index f6bd073d178..03023a20c08 100644
--- a/packages/geoview-core/src/geo/layer/geoview-layers/raster/wms.ts
+++ b/packages/geoview-core/src/geo/layer/geoview-layers/raster/wms.ts
@@ -7,9 +7,7 @@ import { Options as SourceOptions } from 'ol/source/ImageWMS';
import WMSCapabilities from 'ol/format/WMSCapabilities';
import { Extent } from 'ol/extent';
-import cloneDeep from 'lodash/cloneDeep';
-
-import { Cast, TypeJsonArray, TypeJsonObject } from '@/core/types/global-types';
+import { TypeJsonArray, TypeJsonObject } from '@/core/types/global-types';
import { AbstractGeoViewLayer, CONST_LAYER_TYPES } from '@/geo/layer/geoview-layers/abstract-geoview-layers';
import { AbstractGeoViewRaster } from '@/geo/layer/geoview-layers/raster/abstract-geoview-raster';
import { TypeLayerEntryConfig, TypeGeoviewLayerConfig, CONST_LAYER_ENTRY_TYPES, layerEntryIsGroupLayer } from '@/geo/map/map-schema-types';
@@ -21,6 +19,7 @@ import { logger } from '@/core/utils/logger';
import { OgcWmsLayerEntryConfig } from '@/core/utils/config/validation-classes/raster-validation-classes/ogc-wms-layer-entry-config';
import { AbstractBaseLayerEntryConfig } from '@/core/utils/config/validation-classes/abstract-base-layer-entry-config';
import { GroupLayerEntryConfig } from '@/core/utils/config/validation-classes/group-layer-entry-config';
+import { ConfigBaseClass } from '@/core/utils/config/validation-classes/config-base-class';
export interface TypeWMSLayerConfig extends Omit {
geoviewLayerType: typeof CONST_LAYER_TYPES.WMS;
@@ -97,17 +96,21 @@ export class WMS extends AbstractGeoViewRaster {
// GV Layers Refactoring - Obsolete (in config)
protected override async fetchServiceMetadata(): Promise {
const metadataUrl = this.metadataAccessPath;
- if (metadataUrl) {
- const metadataAccessPathIsXmlFile = metadataUrl.slice(-4).toLowerCase() === '.xml';
+ let curatedMetadataUrl = metadataUrl;
+ if (!metadataUrl.includes('request=GetCapabilities')) {
+ curatedMetadataUrl = `${metadataUrl}?service=WMS&version=1.3.0&request=GetCapabilities`;
+ }
+ if (curatedMetadataUrl) {
+ const metadataAccessPathIsXmlFile = curatedMetadataUrl.slice(-4).toLowerCase() === '.xml';
if (metadataAccessPathIsXmlFile) {
// XML metadata is a special case that does not use GetCapabilities to get the metadata
- await this.#fetchXmlServiceMetadata(metadataUrl);
+ await this.#fetchXmlServiceMetadata(curatedMetadataUrl);
} else {
const layerConfigsToQuery = this.#getLayersToQuery();
if (layerConfigsToQuery.length === 0) {
// Use GetCapabilities to get the metadata
try {
- const metadata = await this.#getServiceMetadata(`${metadataUrl}?service=WMS&version=1.3.0&request=GetCapabilities`);
+ const metadata = await this.#getServiceMetadata(curatedMetadataUrl);
this.metadata = metadata;
this.#processMetadataInheritance();
} catch (error) {
@@ -126,9 +129,7 @@ export class WMS extends AbstractGeoViewRaster {
for (i = 0; layerConfigsToQuery[i].layerId !== layerConfig.layerId; i++);
if (i === layerIndex)
// This is the first time we execute this query
- promisedArrayOfMetadata.push(
- this.#getServiceMetadata(`${metadataUrl}?service=WMS&version=1.3.0&request=GetCapabilities&Layers=${layerConfig.layerId}`)
- );
+ promisedArrayOfMetadata.push(this.#getServiceMetadata(`${curatedMetadataUrl}&Layers=${layerConfig.layerId}`));
// query already done. Use previous returned value
else promisedArrayOfMetadata.push(promisedArrayOfMetadata[i]);
});
@@ -396,7 +397,7 @@ export class WMS extends AbstractGeoViewRaster {
}
if ('Layer' in layerFound) {
- this.#createGroupLayer(layerFound, layerConfig as AbstractBaseLayerEntryConfig);
+ this.#createGroupLayer(layerFound, layerConfig as unknown as GroupLayerEntryConfig);
return;
}
@@ -409,11 +410,11 @@ export class WMS extends AbstractGeoViewRaster {
* This method create recursively dynamic group layers from the service metadata.
*
* @param {TypeJsonObject} layer The dynamic group layer metadata.
- * @param {AbstractBaseLayerEntryConfig} layerConfig The layer configurstion associated to the dynamic group.
+ * @param {GroupLayerEntryConfig} layerConfig The group layer configuration associated to the dynamic group.
* @private
*/
// GV Layers Refactoring - Obsolete (in config)
- #createGroupLayer(layer: TypeJsonObject, layerConfig: AbstractBaseLayerEntryConfig): void {
+ #createGroupLayer(layer: TypeJsonObject, layerConfig: GroupLayerEntryConfig): void {
// TODO: Refactor - createGroup is the same thing for all the layers type? group is a geoview structure.
// TO.DOCONT: Should it be handle upper in abstract class to loop in structure and launch the creation of a leaf?
// TODO: The answer is no. Even if the final structure is the same, the input structure is different for each geoview layer types.
@@ -423,17 +424,17 @@ export class WMS extends AbstractGeoViewRaster {
arrayOfLayerMetadata.forEach((subLayer) => {
// Log for pertinent debugging purposes
logger.logTraceCore('WMS - createGroupLayer', 'Cloning the layer config', layerConfig.layerPath);
- const subLayerEntryConfig: TypeLayerEntryConfig = cloneDeep(layerConfig);
- subLayerEntryConfig.parentLayerConfig = Cast(layerConfig);
+ const subLayerEntryConfig: ConfigBaseClass = layerConfig.clone();
+ subLayerEntryConfig.parentLayerConfig = layerConfig;
subLayerEntryConfig.layerId = subLayer.Name as string;
subLayerEntryConfig.layerName = subLayer.Title as string;
- newListOfLayerEntryConfig.push(subLayerEntryConfig);
+ newListOfLayerEntryConfig.push(subLayerEntryConfig as TypeLayerEntryConfig);
// FIXME: Temporary patch to keep the behavior until those layer classes don't exist
this.getMapViewer().layer.registerLayerConfigInit(subLayerEntryConfig);
});
- const switchToGroupLayer = Cast(layerConfig);
+ const switchToGroupLayer = layerConfig;
switchToGroupLayer.entryType = CONST_LAYER_ENTRY_TYPES.GROUP;
switchToGroupLayer.layerName = layer.Title as string;
switchToGroupLayer.isMetadataLayerGroup = true;
diff --git a/packages/geoview-core/src/geo/layer/gv-layers/abstract-gv-layer.ts b/packages/geoview-core/src/geo/layer/gv-layers/abstract-gv-layer.ts
index 35f29637f1b..947c01b2398 100644
--- a/packages/geoview-core/src/geo/layer/gv-layers/abstract-gv-layer.ts
+++ b/packages/geoview-core/src/geo/layer/gv-layers/abstract-gv-layer.ts
@@ -393,15 +393,15 @@ export abstract class AbstractGVLayer extends AbstractBaseLayer {
/**
* Queries the legend.
- * This function raises legend querying and queried events. It calls the overridable getLegend() function.
+ * This function raises legend querying and queried events. It calls the overridable onFetchLegend() function.
* @returns {Promise} The promise when the legend (or null) will be received
*/
queryLegend(): Promise {
// Emit that the legend has been queried
this.#emitLegendQuerying();
- // Get the legend
- const promiseLegend = this.getLegend();
+ // Fetch the legend by calling the overridable function
+ const promiseLegend = this.onFetchLegend();
// Whenever the promise resolves
promiseLegend
@@ -452,8 +452,7 @@ export abstract class AbstractGVLayer extends AbstractBaseLayer {
* of the layerConfig object is undefined, the legend property of the object returned will be null.
* @returns {Promise} The legend of the layer.
*/
- async getLegend(): Promise {
- // TODO: Refactor - Layers refactoring. Rename this function to onFetchLegend() once the layers refactoring is done
+ async onFetchLegend(): Promise {
try {
const legend: TypeLegend = {
type: this.getLayerConfig().geoviewLayerConfig.geoviewLayerType,
diff --git a/packages/geoview-core/src/geo/layer/gv-layers/raster/gv-esri-dynamic.ts b/packages/geoview-core/src/geo/layer/gv-layers/raster/gv-esri-dynamic.ts
index 00cd055c094..a2014201b40 100644
--- a/packages/geoview-core/src/geo/layer/gv-layers/raster/gv-esri-dynamic.ts
+++ b/packages/geoview-core/src/geo/layer/gv-layers/raster/gv-esri-dynamic.ts
@@ -665,10 +665,10 @@ export class GVEsriDynamic extends AbstractGVRaster {
* Overrides the fetching of the legend for an Esri Dynamic layer.
* @returns {Promise} The legend of the layer or null.
*/
- override async getLegend(): Promise {
+ override async onFetchLegend(): Promise {
const layerConfig = this.getLayerConfig();
// Only raster layers need the alternate code
- if (layerConfig.getLayerMetadata()?.type !== 'Raster Layer') return super.getLegend();
+ if (layerConfig.getLayerMetadata()?.type !== 'Raster Layer') return super.onFetchLegend();
try {
if (!layerConfig) return null;
diff --git a/packages/geoview-core/src/geo/layer/gv-layers/raster/gv-esri-image.ts b/packages/geoview-core/src/geo/layer/gv-layers/raster/gv-esri-image.ts
index e4f6802064b..a13b91cbcf9 100644
--- a/packages/geoview-core/src/geo/layer/gv-layers/raster/gv-esri-image.ts
+++ b/packages/geoview-core/src/geo/layer/gv-layers/raster/gv-esri-image.ts
@@ -102,7 +102,7 @@ export class GVEsriImage extends AbstractGVRaster {
* Overrides the fetching of the legend for an Esri image layer.
* @returns {Promise} The legend of the layer or null.
*/
- override async getLegend(): Promise {
+ override async onFetchLegend(): Promise {
const layerConfig = this.getLayerConfig();
try {
if (!layerConfig) return null;
diff --git a/packages/geoview-core/src/geo/layer/gv-layers/raster/gv-image-static.ts b/packages/geoview-core/src/geo/layer/gv-layers/raster/gv-image-static.ts
index 8e3960f7c02..7b89315e784 100644
--- a/packages/geoview-core/src/geo/layer/gv-layers/raster/gv-image-static.ts
+++ b/packages/geoview-core/src/geo/layer/gv-layers/raster/gv-image-static.ts
@@ -102,7 +102,7 @@ export class GVImageStatic extends AbstractGVRaster {
* Overrides the fetching of the legend for an Esri image layer.
* @returns {Promise} The legend of the layer or null.
*/
- override async getLegend(): Promise {
+ override async onFetchLegend(): Promise {
const layerConfig = this.getLayerConfig();
try {
const legendImage = await GVImageStatic.#getLegendImage(layerConfig!);
diff --git a/packages/geoview-core/src/geo/layer/gv-layers/raster/gv-wms.ts b/packages/geoview-core/src/geo/layer/gv-layers/raster/gv-wms.ts
index af8dde51d58..83d7599f46b 100644
--- a/packages/geoview-core/src/geo/layer/gv-layers/raster/gv-wms.ts
+++ b/packages/geoview-core/src/geo/layer/gv-layers/raster/gv-wms.ts
@@ -180,9 +180,12 @@ export class GVWMS extends AbstractGVRaster {
}
}
}
- } else if (infoFormat === 'text/html') {
- featureMember = { html: response.data };
- } else featureMember = { plain_text: { '#text': response.data } };
+ } else if (response.data && response.data.length > 0) {
+ // The response has any data to show
+ if (infoFormat === 'text/html') {
+ featureMember = { html: response.data };
+ } else featureMember = { plain_text: { '#text': response.data } };
+ }
if (featureMember) {
const featureInfoResult = GVWMS.#formatWmsFeatureInfoResult(featureMember, clickCoordinate);
@@ -202,7 +205,7 @@ export class GVWMS extends AbstractGVRaster {
* Overrides the fetching of the legend for a WMS layer.
* @returns {Promise} The legend of the layer or null.
*/
- override async getLegend(): Promise {
+ override async onFetchLegend(): Promise {
try {
// Get the layer config in a loaded phase
const layerConfig = this.getLayerConfig();
@@ -214,7 +217,7 @@ export class GVWMS extends AbstractGVRaster {
// If more than 1
if (this.WMSStyles.length > 1) {
for (let i = 0; i < this.WMSStyles.length; i++) {
- // TODO: refactor - does this await in a loop may haev an impact on performance?
+ // TODO: refactor - does this await in a loop may have an impact on performance?
// TO.DOCONT: In this case here, when glancing at the code, the only reason to await would be if the order that the styleLegend
// TO.DOCONT: get added to the styleLegends array MUST be the same order as they are in the WMSStyles array (as in they are 2 arrays with same indexes pointers).
// TO.DOCONT: Without the await, WMSStyles[2] stuff could be associated with something in styleLegends[1] position for example (1<>2).
@@ -251,7 +254,7 @@ export class GVWMS extends AbstractGVRaster {
return legend;
} catch (error) {
// Log
- logger.logError('gv-wms.getLegend()\n', error);
+ logger.logError('gv-wms.onFetchLegend()\n', error);
return null;
}
}
diff --git a/packages/geoview-core/src/geo/layer/layer.ts b/packages/geoview-core/src/geo/layer/layer.ts
index 418f05da3cd..9e74429fac6 100644
--- a/packages/geoview-core/src/geo/layer/layer.ts
+++ b/packages/geoview-core/src/geo/layer/layer.ts
@@ -250,22 +250,23 @@ export class LayerApi {
return this.#layerEntryConfigs?.[layerPath];
}
- /**
- * Obsolete function to set the layer configuration in the registered layers.
- */
- setLayerEntryConfigObsolete(layerConfig: ConfigBaseClass): void {
- // FIXME: This function should be deleted once the Layers refactoring is done. It unregisters and registers an updated layer entry config.
- // FIX.MECONT: This is because of the EsriDynamic and EsriFeature entry config being generated on-the-fly when registration of layer entry config has already happened.
- // Get the config already existing if any
- const alreadyExisting = this.#layerEntryConfigs[layerConfig.layerPath];
- if (alreadyExisting) {
- // Unregister the old one
- this.unregisterLayerConfig(alreadyExisting, false);
- }
-
- // Register this new one
- this.registerLayerConfigInit(layerConfig);
- }
+ // TODO: Officially remove setLayerEntryConfigObsolete once passed testing
+ // /**
+ // * Obsolete function to set the layer configuration in the registered layers.
+ // */
+ // setLayerEntryConfigObsolete(layerConfig: ConfigBaseClass): void {
+ // // FIXME: This function should be deleted once the Layers refactoring is done. It unregisters and registers an updated layer entry config.
+ // // FIX.MECONT: This is because of the EsriDynamic and EsriFeature entry config being generated on-the-fly when registration of layer entry config has already happened.
+ // // Get the config already existing if any
+ // const alreadyExisting = this.#layerEntryConfigs[layerConfig.layerPath];
+ // if (alreadyExisting) {
+ // // Unregister the old one
+ // this.unregisterLayerConfig(alreadyExisting, false);
+ // }
+
+ // // Register this new one
+ // this.registerLayerConfigInit(layerConfig);
+ // }
/**
* Returns the OpenLayer instance associated with the layer path.
@@ -1202,12 +1203,19 @@ export class LayerApi {
// Remove layer info from registered layers
this.getLayerEntryConfigIds().forEach((registeredLayerPath) => {
if (registeredLayerPath.startsWith(layerPath)) {
- // Remove ol layer
+ // Remove actual OL layer from the map
if (this.getOLLayer(registeredLayerPath)) this.mapViewer.map.removeLayer(this.getOLLayer(registeredLayerPath) as BaseLayer);
- // Unregister layer
+
+ // Unregister layer config from the application
this.unregisterLayerConfig(this.getLayerEntryConfig(registeredLayerPath)!);
- // Remove from registered layers
+
+ // Remove from registered layer configs
delete this.#layerEntryConfigs[registeredLayerPath];
+ delete this.#geoviewLayers[registeredLayerPath];
+
+ // Remove from registered layers
+ delete this.#gvLayers[registeredLayerPath];
+ delete this.#olLayers[registeredLayerPath];
}
});
diff --git a/packages/geoview-core/src/geo/utils/projection.ts b/packages/geoview-core/src/geo/utils/projection.ts
index 2163caa1d0a..b5dde4d2366 100644
--- a/packages/geoview-core/src/geo/utils/projection.ts
+++ b/packages/geoview-core/src/geo/utils/projection.ts
@@ -29,6 +29,7 @@ export abstract class Projection {
3578: 'EPSG:3578',
LCC: 'EPSG:3978',
3979: 'EPSG:3979',
+ 42101: 'EPSG:42101',
102100: 'EPSG:102100', // TODO: Minor - The official name of this projection is ESRI:102100 (not EPSG:102100). However, for the purpose of simplification in GeoView code base, we name it with EPSG prefix.
102184: 'EPSG:102184', // TODO: Minor - The official name of this projection is ESRI:102184 (not EPSG:102184). However, for the purpose of simplification in GeoView code base, we name it with EPSG prefix.
102190: 'EPSG:102190', // TODO: Minor - The official name of this projection is ESRI:102190 (not EPSG:102190). However, for the purpose of simplification in GeoView code base, we name it with EPSG prefix.
@@ -414,6 +415,21 @@ function init4269Projection(): void {
if (projection) Projection.PROJECTIONS['4269'] = projection;
}
+/**
+ * Initializes the EPSG:42101 projection
+ */
+function init42101Projection(): void {
+ proj4.defs(
+ Projection.PROJECTION_NAMES[42101],
+ '+proj=lcc +lat_0=0 +lon_0=-95 +lat_1=49 +lat_2=77 +x_0=0 +y_0=-8000000 +datum=WGS84 +units=m +no_defs +type=crs'
+ );
+ register(proj4);
+
+ const projection = olGetProjection(Projection.PROJECTION_NAMES[42101]);
+
+ if (projection) Projection.PROJECTIONS['42101'] = projection;
+}
+
/**
* Initializes the EPSG:3979 projection
*/
@@ -499,6 +515,7 @@ initCSRS98Projection();
init3578Projection();
init3979Projection();
init4269Projection();
+init42101Projection();
init102100Projection();
init102184Projection();
init102190Projection();