diff --git a/packages/geoview-core/public/datasets/geojson/metadata-new.meta b/packages/geoview-core/public/datasets/geojson/metadata-new.meta index 645cb50792f..7b6a31e1b3a 100644 --- a/packages/geoview-core/public/datasets/geojson/metadata-new.meta +++ b/packages/geoview-core/public/datasets/geojson/metadata-new.meta @@ -274,13 +274,11 @@ } }, "style": { - "Point": { - "styleType": "simple", - "label": "Point label", - "settings": { - "type": "simpleSymbol", - "symbol": "star" - } + "styleType": "simple", + "label": "Point label", + "settings": { + "type": "simpleSymbol", + "symbol": "star" } } }, @@ -338,13 +336,11 @@ } }, "style": { - "Point": { - "styleType": "simple", - "label": "Point label", - "settings": { - "type": "simpleSymbol", - "symbol": "star" - } + "styleType": "simple", + "label": "Point label", + "settings": { + "type": "simpleSymbol", + "symbol": "star" } } }, @@ -397,13 +393,11 @@ } }, "style": { - "Point": { - "styleType": "simple", - "label": "Point label", - "settings": { - "type": "simpleSymbol", - "symbol": "star" - } + "styleType": "simple", + "label": "Point label", + "settings": { + "type": "simpleSymbol", + "symbol": "star" } } }, @@ -456,13 +450,11 @@ } }, "style": { - "Point": { - "styleType": "simple", - "label": "Point label", - "settings": { - "type": "simpleSymbol", - "symbol": "star" - } + "styleType": "simple", + "label": "Point label", + "settings": { + "type": "simpleSymbol", + "symbol": "star" } } } diff --git a/packages/geoview-core/src/api/config/types/classes/geoview-config/raster-config/wms-config.ts b/packages/geoview-core/src/api/config/types/classes/geoview-config/raster-config/wms-config.ts index 825815b0e3c..6934cbb3aaf 100644 --- a/packages/geoview-core/src/api/config/types/classes/geoview-config/raster-config/wms-config.ts +++ b/packages/geoview-core/src/api/config/types/classes/geoview-config/raster-config/wms-config.ts @@ -393,12 +393,15 @@ export class WmsLayerConfig extends AbstractGeoviewLayerConfig { layerConfigsToQuery.forEach((layerConfig: WmsLayerEntryConfig, layerIndex: number) => { // verify if the a request with the same layerId has already been sent up to now. for (i = 0; layerConfigsToQuery[i].layerId !== layerConfig.layerId; i++); - if (i === layerIndex) + if (i === layerIndex) { // if the layer found is the same as the current layer index, // this is the first time we execute this request - promisedArrayOfMetadata.push(this.#executeServiceMetadataRequest(`${this.metadataAccessPath}?Layers=${layerConfig.layerId}`)); - // otherwise, we are already waiting for the same request and we will wait for it to finish. - else promisedArrayOfMetadata.push(promisedArrayOfMetadata[i]); + const urlToQuery = this.metadataAccessPath.includes('?') + ? `${this.metadataAccessPath}&Layers=${layerConfig.layerId}` + : `${this.metadataAccessPath}?Layers=${layerConfig.layerId}`; + promisedArrayOfMetadata.push(this.#executeServiceMetadataRequest(urlToQuery)); + // otherwise, we are already waiting for the same request and we will wait for it to finish. + } else promisedArrayOfMetadata.push(promisedArrayOfMetadata[i]); }); // Since we use Promise.all, If one of the Promise awaited fails, then the whole service metadata fetching will fail. diff --git a/packages/geoview-core/src/api/config/types/classes/sub-layer-config/entry-config-base-class.ts b/packages/geoview-core/src/api/config/types/classes/sub-layer-config/entry-config-base-class.ts index 886f37e3e01..792ab7e373d 100644 --- a/packages/geoview-core/src/api/config/types/classes/sub-layer-config/entry-config-base-class.ts +++ b/packages/geoview-core/src/api/config/types/classes/sub-layer-config/entry-config-base-class.ts @@ -1,8 +1,9 @@ import cloneDeep from 'lodash/cloneDeep'; import { CV_DEFAULT_LAYER_INITIAL_SETTINGS } from '@config/types/config-constants'; -import { TypeJsonObject } from '@config/types/config-types'; +import { toJsonObject, TypeJsonObject } from '@config/types/config-types'; import { AbstractGeoviewLayerConfig } from '@config/types/classes/geoview-config/abstract-geoview-layer-config'; +import { layerEntryIsGroupLayer } from '@config/types/type-guards'; import { TypeGeoviewLayerType, TypeLayerEntryType, @@ -56,7 +57,7 @@ export abstract class EntryConfigBaseClass { bounds: Extent | undefined; /** Layer entry data type. */ - entryType: TypeLayerEntryType; + entryType?: TypeLayerEntryType; // GV NOTE START **************************************************************************************************** // The following attributes use the 'definite assignment assertion' (! after the property name) to indicate that @@ -151,16 +152,6 @@ export abstract class EntryConfigBaseClass { // ================= // #region PROTECTED - /** - * The getter method that returns the language used to create the sublayer. - * - * @returns {TypeDisplayLanguage} The language associated to the config. - * @protected - */ - protected getLanguage(): TypeDisplayLanguage { - return this.#language; - } - /** * Validate the node configuration using the schema associated to its layer type. * @protected @@ -197,6 +188,11 @@ export abstract class EntryConfigBaseClass { return this.#geoviewLayerConfig.geoviewLayerType; } + /** Set the geoview layer that owns this sub-layer configuration. */ + setGeoviewLayerConfig(geoviewLayerConfig: AbstractGeoviewLayerConfig): void { + this.#geoviewLayerConfig = geoviewLayerConfig; + } + /** The geoview layer that owns this sub-layer configuration. */ getGeoviewLayerConfig(): AbstractGeoviewLayerConfig { return this.#geoviewLayerConfig; @@ -221,9 +217,11 @@ export abstract class EntryConfigBaseClass { /** * Method used to set the EntryConfigBaseClass error flag to true. Once this operation has been performed, the layer entry * config is no longer considered viable. + * + * @param {boolean} value The value to assign to the flag. */ - setErrorDetectedFlag(): void { - this.#errorDetectedFlag = true; + setErrorDetectedFlag(value = true): void { + this.#errorDetectedFlag = value; } /** @@ -235,6 +233,15 @@ export abstract class EntryConfigBaseClass { return this.#errorDetectedFlag; } + /** + * Method used to set the parent node. + * + * @param {EntryConfigBaseClass | undefined} parentNode The parent node. + */ + setParentNode(parentNode: EntryConfigBaseClass | undefined): void { + this.#parentNode = parentNode; + } + /** * The getter method that returns the parentNode. * @@ -244,6 +251,24 @@ export abstract class EntryConfigBaseClass { return this.#parentNode; } + /** + * The setter method that sets the language used to create the sublayer. + * + * @param {TypeDisplayLanguage} language The language associated to the config. + */ + setLanguage(language: TypeDisplayLanguage): void { + this.#language = language; + } + + /** + * The getter method that returns the language used to create the sublayer. + * + * @returns {TypeDisplayLanguage} The language associated to the config. + */ + getLanguage(): TypeDisplayLanguage { + return this.#language; + } + /** * This method returns the json string of the entry configuration. The output representation is a multi-line indented * string. Indentation can be controled using the ident parameter. Private variables are not serialized. @@ -264,6 +289,74 @@ export abstract class EntryConfigBaseClass { this.minScale = 0; this.maxScale = 0; } + + /** + * Create a clone of this node. This method is mainly used to clone a node from the layer tree to store a copy in the + * list of layer entry config of the GeoView Layer. It was created to preserve the private fields created using the # + * operator because cloneDeep doesn't copy them to the cloned instance. + * + * @param {EntryConfigBaseClass | undefined} parentNode The layer group that owns this node. + * + * @returns {EntryConfigBaseClass} The clone copy of the node. + */ + clone(parentNode: EntryConfigBaseClass | undefined = undefined): EntryConfigBaseClass { + let cloneOfTheNode: EntryConfigBaseClass = cloneDeep(this); + + // Remove the following properties to avoid schema validation errors. + delete cloneOfTheNode.layerName; + delete cloneOfTheNode.entryType; + if ('listOfLayerEntryConfig' in cloneOfTheNode) cloneOfTheNode.listOfLayerEntryConfig = []; + + // Create a new instance using the cloned config. + if (cloneOfTheNode.isLayerGroup) + cloneOfTheNode = this.#geoviewLayerConfig.createGroupNode( + toJsonObject(cloneOfTheNode), + this.#language, + this.#geoviewLayerConfig, + parentNode + )!; + else + cloneOfTheNode = this.#geoviewLayerConfig.createLeafNode( + toJsonObject(cloneOfTheNode), + this.#language, + this.#geoviewLayerConfig, + parentNode + )!; + // Restore the layerName and the private properties. + cloneOfTheNode.layerName = this.layerName; + cloneOfTheNode.setErrorDetectedFlag(this.#errorDetectedFlag); + cloneOfTheNode.setLayerMetadata(this.#layerMetadata); + return cloneOfTheNode; + } + + /** + * The getter method that returns the sublayer configuration. If the layer path doesn't exists, return undefined. + * + * @returns {EntryConfigBaseClass | undefined} The sublayer configuration. + */ + getSubLayerConfig(layerPath: string): EntryConfigBaseClass | undefined { + // The node is a group + if (this.isLayerGroup && 'listOfLayerEntryConfig' in this) { + const pathItems = layerPath.split('/'); + if (pathItems[0] !== this.layerId) return undefined; + if (pathItems.length === 1) return this; + let { listOfLayerEntryConfig } = this; + let nodeFound: EntryConfigBaseClass | undefined; + for (let i = 1; i < pathItems.length; i++) { + nodeFound = (listOfLayerEntryConfig as EntryConfigBaseClass[]).find( + (layerEntryConfig) => layerEntryConfig.layerId === pathItems[i] + ); + if (!nodeFound) break; + listOfLayerEntryConfig = layerEntryIsGroupLayer(nodeFound) ? nodeFound.listOfLayerEntryConfig : []; + } + return nodeFound; + } + + // The node is a leaf. + if (layerPath === this.layerId) return this; + return undefined; + } + // #endregion PUBLIC // #endregion METHODS // #endregion CLASS HEADER