From 52cdbb8c72eb0feec3f3edd83a6c89990a4d2659 Mon Sep 17 00:00:00 2001
From: Yves Choquette
Date: Tue, 20 Feb 2024 09:28:43 -0500
Subject: [PATCH] See layer in Error #1774
---
.../FeatureInfoLayerSet-event-managment.md | 2 +-
.../draw.io/FeatureInfo-class.drawio.svg | 10 +-
.../LayerSet/LayerSet-event-managment.md | 2 +-
.../draw.io/LayerSet-class.drawio.svg | 8 +-
.../LegendsLayerSet-event-managment.md | 6 +-
.../draw.io/LegendsLayerSet-class.drawio.svg | 10 +-
.../public/templates/layers/csv.html | 2 +-
.../public/templates/layers/esri-dynamic.html | 30 +-
.../public/templates/layers/esri-feature.html | 53 +--
.../public/templates/layers/esri-image.html | 6 +-
.../public/templates/layers/geocore.html | 10 +-
.../public/templates/layers/geojson.html | 10 +-
.../public/templates/layers/geopackage.html | 10 +-
.../public/templates/layers/image-static.html | 6 +-
.../public/templates/layers/layerlib.js | 24 +-
.../public/templates/layers/ogc-feature.html | 10 +-
.../public/templates/layers/wfs.html | 20 +-
.../public/templates/layers/wms.html | 38 +-
.../public/templates/package-swiper.html | 10 +-
.../public/templates/pygeoapi-processes.html | 10 +-
.../geoview-core/public/templates/test.html | 10 +-
.../feature-info-event-processor.ts | 12 +-
.../legend-event-processor.ts | 86 ++---
.../constants/get-feature-info-constants.ts | 14 +-
.../events/constants/get-legends-constants.ts | 7 +-
.../events/constants/layer-set-constants.ts | 7 +-
.../src/api/events/event-types.ts | 5 +-
.../payloads/get-feature-info-payload.ts | 68 +---
.../events/payloads/get-legends-payload.ts | 58 +--
.../api/events/payloads/layer-set-payload.ts | 60 +--
.../hover-tooltip/hover-tooltip.tsx | 8 +-
.../core/components/layers/hooks/helpers.ts | 11 +-
.../add-new-layer/add-new-layer.tsx | 20 +-
.../src/core/components/layers/types.ts | 2 -
.../src/core/types/material-ui.d.ts | 1 +
.../geoview-layers/abstract-geoview-layers.ts | 87 +++--
.../layer/geoview-layers/esri-layer-common.ts | 32 +-
.../geoview-layers/raster/esri-dynamic.ts | 5 +-
.../layer/geoview-layers/raster/esri-image.ts | 10 +-
.../geoview-layers/raster/image-static.ts | 15 +-
.../geoview-layers/raster/vector-tiles.ts | 169 +++++----
.../geo/layer/geoview-layers/raster/wms.ts | 218 +++++------
.../layer/geoview-layers/raster/xyz-tiles.ts | 133 +++----
.../vector/abstract-geoview-vector.ts | 3 +
.../geo/layer/geoview-layers/vector/csv.ts | 19 +-
.../geoview-layers/vector/esri-feature.ts | 2 +-
.../layer/geoview-layers/vector/geojson.ts | 90 ++---
.../layer/geoview-layers/vector/geopackage.ts | 81 ++--
.../geoview-layers/vector/ogc-feature.ts | 42 ++-
.../geo/layer/geoview-layers/vector/wfs.ts | 95 +++--
packages/geoview-core/src/geo/layer/layer.ts | 17 +-
.../geo/layer/other/cluster-placeholder.ts | 16 +-
.../src/geo/map/map-schema-types.ts | 95 ++++-
.../geoview-core/src/geo/map/map-viewer.ts | 6 +-
.../src/geo/utils/feature-info-layer-set.ts | 347 +++++++++---------
.../geoview-core/src/geo/utils/layer-set.ts | 170 ++++-----
.../src/geo/utils/legends-layer-set.ts | 150 +++++---
.../src/ui/style/themeOptionsGenerator.ts | 2 +-
.../geoview-geochart/src/geochart-parsing.ts | 2 +-
.../src/panel-content.tsx | 4 +-
60 files changed, 1191 insertions(+), 1265 deletions(-)
diff --git a/docs/app/event/FeatureInfoLayerSet/FeatureInfoLayerSet-event-managment.md b/docs/app/event/FeatureInfoLayerSet/FeatureInfoLayerSet-event-managment.md
index 0f47be3ba9f..e1eb6e1fa1f 100644
--- a/docs/app/event/FeatureInfoLayerSet/FeatureInfoLayerSet-event-managment.md
+++ b/docs/app/event/FeatureInfoLayerSet/FeatureInfoLayerSet-event-managment.md
@@ -1,6 +1,6 @@
# FeatureInfoLayerSet Class
-The `FeatureInfoLayerSet` class is used to create objects that will keep query results associated with layer paths. It uses internally an instance of the `LayerSet` class to keep track of the layers loaded on the map. The property list of the LayerSet remains synchronized with all layer paths on the map at all times. However, the `LayerSet` has a registration condition function that filter out all layers that are not queryable as defined in their metadata or configuration. If you delete or add a layer to the map, the `LayerSet` will be updated. The feature information is stored in the `resultsSet` property and has a `TypeFeatureInfoResultsSet` type which is an object whose properties are layer paths and the values are of one of the following types: `null`, `undefined` or `TypeArrayOfFeatureInfoEntries`. A `null`value means the `getLgetFeatureInfo` call did not get the expected data due to an error. The `undefined`value is used to identify the layer paths that need to return there result set. A value of `TypeArrayOfFeatureInfoEntries` is the layer path result set. The structure of `TypeArrayOfFeatureInfoEntries` is shown below:
+The `FeatureInfoLayerSet` class is used to create objects that will keep query results associated with layer paths. It uses internally an instance of the `LayerSet` class to keep track of the layers loaded on the map. The property list of the LayerSet remains synchronized with all layer paths on the map at all times. However, the `LayerSet` has a registration condition function that filter out all layers that are not queryable as defined in their metadata or configuration. If you delete or add a layer to the map, the `LayerSet` will be updated. The feature information is stored in the `resultSet` property and has a `TypeFeatureInfoResultSet` type which is an object whose properties are layer paths and the values are of one of the following types: `null`, `undefined` or `TypeArrayOfFeatureInfoEntries`. A `null`value means the `getLgetFeatureInfo` call did not get the expected data due to an error. The `undefined`value is used to identify the layer paths that need to return there result set. A value of `TypeArrayOfFeatureInfoEntries` is the layer path result set. The structure of `TypeArrayOfFeatureInfoEntries` is shown below:
```js
export type TypeArrayOfFeatureInfoEntries = TypeFeatureInfoEntry[];
diff --git a/docs/app/event/FeatureInfoLayerSet/draw.io/FeatureInfo-class.drawio.svg b/docs/app/event/FeatureInfoLayerSet/draw.io/FeatureInfo-class.drawio.svg
index 1d1bea0d2d5..484563079dc 100644
--- a/docs/app/event/FeatureInfoLayerSet/draw.io/FeatureInfo-class.drawio.svg
+++ b/docs/app/event/FeatureInfoLayerSet/draw.io/FeatureInfo-class.drawio.svg
@@ -131,7 +131,7 @@
- + ResultsSet: TypeFeatureInfoResultSet
+ + ResultSet: TypeFeatureInfoResultSet
@@ -183,7 +183,7 @@
- + ResultsSet: Record<string, any>
+ + ResultSet: Record<string, any>
@@ -223,7 +223,7 @@
layerSetId,
- ResultsSet,
+ ResultSet,
@@ -258,7 +258,7 @@
layerSetId,
- ResultsSet,
+ ResultSet,
@@ -276,7 +276,7 @@
- + constructor (mapId, layerSetId, ResultsSet,...
+ + constructor (mapId, layerSetId, ResultSet,...
diff --git a/docs/app/event/LayerSet/LayerSet-event-managment.md b/docs/app/event/LayerSet/LayerSet-event-managment.md
index 427fab702d4..f276e0e08f1 100644
--- a/docs/app/event/LayerSet/LayerSet-event-managment.md
+++ b/docs/app/event/LayerSet/LayerSet-event-managment.md
@@ -1,6 +1,6 @@
# LayerSet class
-The `layerSet` class has four properties. The first is the identifier of the map to which it is attached. The second is the `layerSet` identifier used to differentiate the `layerSet` when we have several of them. Then we have the resultsSet which will have as many properties as there are layer entries (sometimes named layer path) on the attached map. Finally, there is a registration condition function that will filter out layer entries that we don't want registered in the layerSet.
+The `layerSet` class has four properties. The first is the identifier of the map to which it is attached. The second is the `layerSet` identifier used to differentiate the `layerSet` when we have several of them. Then we have the resultSet which will have as many properties as there are layer entries (sometimes named layer path) on the attached map. Finally, there is a registration condition function that will filter out layer entries that we don't want registered in the layerSet.
The class can be instantiated using the constructor or the create method. At creation time, the instance sends a `LAYER_SET.REQUEST_LAYER_INVENTORY` event in order to get the list of all the layerPaths existing on the map. This list is filtered with the registration condition function to keep only the layerPaths of interest. Throughout its existence, the instance listens to the `LAYER_SET.LAYER_REGISTRATION` events which are emitted when a layer is created/destroyed on the map or in response to an inventory request.
diff --git a/docs/app/event/LayerSet/draw.io/LayerSet-class.drawio.svg b/docs/app/event/LayerSet/draw.io/LayerSet-class.drawio.svg
index a9a9ab8c159..56b1a6123a3 100644
--- a/docs/app/event/LayerSet/draw.io/LayerSet-class.drawio.svg
+++ b/docs/app/event/LayerSet/draw.io/LayerSet-class.drawio.svg
@@ -43,7 +43,7 @@
- + ResultsSet: Record<string, any>
+ + ResultSet: Record<string, any>
@@ -83,7 +83,7 @@
layerSetId,
- ResultsSet,
+ ResultSet,
@@ -118,7 +118,7 @@
layerSetId,
- ResultsSet,
+ ResultSet,
@@ -136,7 +136,7 @@
- + constructor (mapId, layerSetId, ResultsSet,...
+ + constructor (mapId, layerSetId, ResultSet,...
diff --git a/docs/app/event/LegendsLayerSet/LegendsLayerSet-event-managment.md b/docs/app/event/LegendsLayerSet/LegendsLayerSet-event-managment.md
index 1e3fac0d1b3..06a6f056338 100644
--- a/docs/app/event/LegendsLayerSet/LegendsLayerSet-event-managment.md
+++ b/docs/app/event/LegendsLayerSet/LegendsLayerSet-event-managment.md
@@ -18,11 +18,11 @@ The `layerPath` parameter is used to link the legend to the layer entry configur
-The class can be instantiated using the constructor or the create method. At creation time, the constructor instantiates a `LayerSet` object which will send a `LAYER_SET.REQUEST_LAYER_INVENTORY` event using a `mapId/LayerSetId` handler in order to get the list of all the layerPaths existing on the map. Throughout its existence, the `LegendsLayerSet` instance listens, through its `LayerSet` property, to the `LAYER_SET.LAYER_REGISTRATION` events that are emitted when a layer is created/destroyed on the map or in response to the inventory request to update its `ResultSet` property. It also listens to the `GET_LEGENDS.LEGEND_INFO` event. This listener receives the legend information returned by the layer's `getLegend` call and store it in the `LayerSet`. If all the registered layers have their legend information, a `GET_LEGENDS.LEGENDS_LAYERSET_UPDATED` event is triggered with a `mapId/LayerSetId` handler.
+The class can be instantiated using the constructor or the create method. At creation time, the constructor instantiates a `LayerSet` object which will send a `LAYER_SET.REQUEST_LAYER_INVENTORY` event using a `mapId/LayerSetId` handler in order to get the list of all the layerPaths existing on the map. Throughout its existence, the `LegendsLayerSet` instance listens, through its `LayerSet` property, to the `LAYER_SET.LAYER_REGISTRATION` events that are emitted when a layer is created/destroyed on the map or in response to the inventory request to update its `ResultSet` property. It also listens to the `GET_LEGENDS.LEGEND_INFO` event. This listener receives the legend information returned by the layer's `getLegend` call and store it in the `LayerSet`. If all the registered layers have their legend information, a `GET_LEGENDS.LEGEND_LAYERSET_UPDATED` event is triggered with a `mapId/LayerSetId` handler.
When the `LegendsLayerSet` is created, a `LAYER_SET.UPDATED` listener is attached to the instance to wait for `LayerSet` modifications. Then, a `GET_LEGENDS.QUERY_LEGEND` event will be emited to all undefined legend of the `LayerSet` to obtain the legends.
-The `LAYER_SET.UPDATED` listener will catch layer add/remove applied to the map. If a layer is added, a `GET_LEGENDS.QUERY_LEGEND` event will be emited for it and when all the registered layers have received their legend information, a `GET_LEGENDS.LEGENDS_LAYERSET_UPDATED` event is emited using the `mapId/LayerSetId` as handler. The `GET_LEGENDS.LEGENDS_LAYERSET_UPDATED` event is also emited when a layer is removed from the map to signal that a legend has been removed.
+The `LAYER_SET.UPDATED` listener will catch layer add/remove applied to the map. If a layer is added, a `GET_LEGENDS.QUERY_LEGEND` event will be emited for it and when all the registered layers have received their legend information, a `GET_LEGENDS.LEGEND_LAYERSET_UPDATED` event is emited using the `mapId/LayerSetId` as handler. The `GET_LEGENDS.LEGEND_LAYERSET_UPDATED` event is also emited when a layer is removed from the map to signal that a legend has been removed.
To see how you can use the `FeatureInfoLayerSet`, you can analyse the code of the following files:
- the constructor of the `DetailsAPI` class defined in [packages/geoview-core/src/core/components/details/details/details-api.ts](../../../../packages/geoview-core/src/core/components/details/details-api.ts#L25) and its `createDetails` function;
@@ -39,7 +39,7 @@ The life cycle of the `LegendsLayerSet` starts with the creation of a `LayerSet`
All map layers added to the `LegendsLayerSet` will fetch their legend, but only when the `LegendsLayerSet` process has been triggered. As long as the `TRIGGER` event is not emitted, the collection of legends is not done.
-Let's follow the thread of events for the first case. We create a `LegendsLayerSet`. As a result, a `LayerSet` is instanciated to associate each layer path with its legend. The `REQUEST_LAYER_INVENTORY` event that is thrown at this point in time is done for nothing, because the map does not contain a layer. However, each time a layer is added to the map, a `LAYER_REGISTRATION` event is emited to add its layer path to the `LayerSet`. This action will trigger a `LAYER_SET.UPDATED` event to tell the `LegendsLayerSet` instance that its `LayerSet` has been modified. If the `LegendsLayerSet` has received its `TRIGGER` event, It will react to the Layer_set.updated and request the legend for the newly added layer path. It is the code of the layer path of the GeoView layer instance that will request the legend and when it is obtained, a `LEGEND_INFO` event will be emitted for the layer path of the map. This will update the `LayerSet` and if all legends are fetched, an `LEGENDS_LAYERSET_UPDATED` event is emited to signal to all listening object that the legends has changed.
+Let's follow the thread of events for the first case. We create a `LegendsLayerSet`. As a result, a `LayerSet` is instanciated to associate each layer path with its legend. The `REQUEST_LAYER_INVENTORY` event that is thrown at this point in time is done for nothing, because the map does not contain a layer. However, each time a layer is added to the map, a `LAYER_REGISTRATION` event is emited to add its layer path to the `LayerSet`. This action will trigger a `LAYER_SET.UPDATED` event to tell the `LegendsLayerSet` instance that its `LayerSet` has been modified. If the `LegendsLayerSet` has received its `TRIGGER` event, It will react to the Layer_set.updated and request the legend for the newly added layer path. It is the code of the layer path of the GeoView layer instance that will request the legend and when it is obtained, a `LEGEND_INFO` event will be emitted for the layer path of the map. This will update the `LayerSet` and if all legends are fetched, an `LEGEND_LAYERSET_UPDATED` event is emited to signal to all listening object that the legends has changed.
The second case differs from the previous one only in the way the `REQUEST_LAYER_INVENTORY` event is handled. Since layers already exist on the map, they will identify themselves for registration. The rest of the logic is the same.
diff --git a/docs/app/event/LegendsLayerSet/draw.io/LegendsLayerSet-class.drawio.svg b/docs/app/event/LegendsLayerSet/draw.io/LegendsLayerSet-class.drawio.svg
index 8a885f00403..0b5c5a77c39 100644
--- a/docs/app/event/LegendsLayerSet/draw.io/LegendsLayerSet-class.drawio.svg
+++ b/docs/app/event/LegendsLayerSet/draw.io/LegendsLayerSet-class.drawio.svg
@@ -134,7 +134,7 @@
- + ResultsSet: TypeLegendResultSet
+ + ResultSet: TypeLegendResultSet
@@ -186,7 +186,7 @@
- + ResultsSet: Record<string, any>
+ + ResultSet: Record<string, any>
@@ -226,7 +226,7 @@
layerSetId,
- ResultsSet,
+ ResultSet,
@@ -261,7 +261,7 @@
layerSetId,
- ResultsSet,
+ ResultSet,
@@ -279,7 +279,7 @@
- + constructor (mapId, layerSetId, ResultsSet,...
+ + constructor (mapId, layerSetId, ResultSet,...
diff --git a/packages/geoview-core/public/templates/layers/csv.html b/packages/geoview-core/public/templates/layers/csv.html
index 2288078f4a3..a01c2520c01 100644
--- a/packages/geoview-core/public/templates/layers/csv.html
+++ b/packages/geoview-core/public/templates/layers/csv.html
@@ -263,7 +263,7 @@ 2. CSV Layers - with footer panel
const LegendLayerSet = cgpv.api.getLegendsLayerSet('CSV1');
cgpv.api.event.on(
- cgpv.api.eventNames.GET_LEGENDS.LEGENDS_LAYERSET_UPDATED,
+ cgpv.api.eventNames.GET_LEGENDS.LEGEND_LAYERSET_UPDATED,
(payload) => {
const { resultSets } = payload;
if (resultSets) displayLegend('LegendsId1', resultSets);
diff --git a/packages/geoview-core/public/templates/layers/esri-dynamic.html b/packages/geoview-core/public/templates/layers/esri-dynamic.html
index fe97332d9e7..09616bf83e9 100644
--- a/packages/geoview-core/public/templates/layers/esri-dynamic.html
+++ b/packages/geoview-core/public/templates/layers/esri-dynamic.html
@@ -1137,17 +1137,17 @@ 4. Many ESRI Dynamic Layers with legend settings in the config -
cgpv.api.event.on(
cgpv.api.eventNames.GET_FEATURE_INFO.ALL_QUERIES_DONE,
(payload) => {
- const { layerSetId, resultsSet, eventType } = payload;
- createInfoTable('LYR1', 'ResultSetId1', resultsSet, eventType);
+ const { layerSetId, resultSet, eventType } = payload;
+ createInfoTable('LYR1', 'ResultSetId1', resultSet, eventType);
},
'LYR1/FeatureInfoLayerSet'
);
cgpv.api.event.on(
- cgpv.api.eventNames.GET_LEGENDS.LEGENDS_LAYERSET_UPDATED,
+ cgpv.api.eventNames.GET_LEGENDS.LEGEND_LAYERSET_UPDATED,
(payload) => {
- const { resultsSet } = payload;
- displayLegend('LegendsId1', resultsSet);
+ const { resultSet } = payload;
+ displayLegend('LegendsId1', resultSet);
},
'LYR1/LegendsLayerSet'
);
@@ -1159,17 +1159,17 @@ 4. Many ESRI Dynamic Layers with legend settings in the config -
cgpv.api.event.on(
cgpv.api.eventNames.GET_FEATURE_INFO.ALL_QUERIES_DONE,
(payload) => {
- const { layerSetId, resultsSet, eventType } = payload;
- createInfoTable('LYR2', 'ResultSetId2', resultsSet, eventType);
+ const { layerSetId, resultSet, eventType } = payload;
+ createInfoTable('LYR2', 'ResultSetId2', resultSet, eventType);
},
'LYR2/FeatureInfoLayerSet'
);
cgpv.api.event.on(
- cgpv.api.eventNames.GET_LEGENDS.LEGENDS_LAYERSET_UPDATED,
+ cgpv.api.eventNames.GET_LEGENDS.LEGEND_LAYERSET_UPDATED,
(payload) => {
- const { resultsSet } = payload;
- displayLegend('LegendsId2', resultsSet);
+ const { resultSet } = payload;
+ displayLegend('LegendsId2', resultSet);
},
'LYR2/LegendsLayerSet'
);
@@ -1181,17 +1181,17 @@ 4. Many ESRI Dynamic Layers with legend settings in the config -
cgpv.api.event.on(
cgpv.api.eventNames.GET_FEATURE_INFO.ALL_QUERIES_DONE,
(payload) => {
- const { layerSetId, resultsSet, eventType } = payload;
- createInfoTable('LYR3', 'ResultSetId3', resultsSet, eventType);
+ const { layerSetId, resultSet, eventType } = payload;
+ createInfoTable('LYR3', 'ResultSetId3', resultSet, eventType);
},
'LYR3/FeatureInfoLayerSet'
);
cgpv.api.event.on(
- cgpv.api.eventNames.GET_LEGENDS.LEGENDS_LAYERSET_UPDATED,
+ cgpv.api.eventNames.GET_LEGENDS.LEGEND_LAYERSET_UPDATED,
(payload) => {
- const { resultsSet } = payload;
- displayLegend('LegendsId3', resultsSet);
+ const { resultSet } = payload;
+ displayLegend('LegendsId3', resultSet);
},
'LYR3/LegendsLayerSet'
);
diff --git a/packages/geoview-core/public/templates/layers/esri-feature.html b/packages/geoview-core/public/templates/layers/esri-feature.html
index 03fa7ae73b2..9d042d0d083 100644
--- a/packages/geoview-core/public/templates/layers/esri-feature.html
+++ b/packages/geoview-core/public/templates/layers/esri-feature.html
@@ -369,7 +369,7 @@ 4. Many Esri Feature Layers - with footer bar
createTableOfFilter('LYR2');
createTableOfFilter('LYR3');
- if (cgpv.api.maps.LYR2.layer.registeredLayers['historical-flood/0'].layerStatus === 'loaded') {
+ if (cgpv.api.maps?.LYR2?.layer?.registeredLayers?.['historical-flood/0']?.layerStatus === 'loaded') {
const field2 = cgpv.api.maps.LYR2.layer.geoviewLayer('historical-flood/0').getTemporalDimension().field;
const LYR2_FILTERS = [`${field2} >= date '01/01/2018 05:00:00' and ${field2} <= date '12/31/2019 19:00:00-05:00'`,
`${field2} > date '01/01/2018 05:00:00' and ${field2} <= date '01/01/2020 05:00:00Z'`,
@@ -390,7 +390,7 @@ 4. Many Esri Feature Layers - with footer bar
}, 3000)
}
- if (cgpv.api.maps.LYR3.layer.registeredLayers['historical-flood/0'].layerStatus === 'loaded') {
+ if (cgpv.api.maps?.LYR3?.layer?.registeredLayers?.['historical-flood/0']?.layerStatus === 'loaded') {
const field3 = cgpv.api.maps.LYR3.layer.geoviewLayer('historical-flood/0').getTemporalDimension().field;
const LYR3_FILTERS = [`${field3} >= date '2018-01-01T00:00:00' and ${field3} <= date '2020-01-01T00:00:00'`,
`${field3} > date '2018-01-01T00:00:00' and ${field3} <= date '2020-01-01T00:00:00'`,
@@ -453,47 +453,48 @@ 4. Many Esri Feature Layers - with footer bar
cgpv.api.event.on(
cgpv.api.eventNames.GET_FEATURE_INFO.ALL_QUERIES_DONE,
(payload) => {
- const { layerSetId, resultsSet, eventType } = payload;
- createInfoTable('LYR1', 'ResultSetId1', resultsSet, eventType);
+ const { layerSetId, resultSet, eventType } = payload;
+ createInfoTable('LYR1', 'ResultSetId1', resultSet, eventType);
},
'LYR1/FeatureInfoLayerSet'
);
+ },
+ 'LYR1'
+ );
- cgpv.api.event.on(
- cgpv.api.eventNames.GET_LEGENDS.LEGENDS_LAYERSET_UPDATED,
- (payload) => {
- const { resultsSet } = payload;
- displayLegend('LegendsId1', resultsSet);
- },
- 'LYR1/LegendsLayerSet'
- );
- },
- 'LYR1'
+ cgpv.api.event.on(
+ cgpv.api.eventNames.GET_LEGENDS.LEGEND_LAYERSET_UPDATED,
+ (payload) => {
+ const { resultSet } = payload;
+ displayLegend('LegendsId1', resultSet);
+ },
+ 'LYR1/LegendsLayerSet'
);
listenToLegendLayerSetChanges('HLYR1-state', 'LYR1/LegendsLayerSet');
// LYR2 ===================================================================================================================
+
const getAllFeatureInfo2 = document.getElementById('AllFeatureInfo2');
getAllFeatureInfo2.addEventListener('click', function (e) {
- cgpv.api.event.emit({ event: 'map/get_all_features', handlerName: 'LYR2' });
- });
+ cgpv.api.event.emit({ event: 'map/get_all_features', handlerName: 'LYR2' });
+ });
cgpv.api.event.on(
cgpv.api.eventNames.GET_FEATURE_INFO.ALL_QUERIES_DONE,
(payload) => {
- const { layerSetId, resultsSet, eventType } = payload;
- createInfoTable('LYR2', 'ResultSetId2', resultsSet, eventType);
+ const { layerSetId, resultSet, eventType } = payload;
+ createInfoTable('LYR2', 'ResultSetId2', resultSet, eventType);
},
'LYR2/FeatureInfoLayerSet'
);
cgpv.api.event.on(
- cgpv.api.eventNames.GET_LEGENDS.LEGENDS_LAYERSET_UPDATED,
+ cgpv.api.eventNames.GET_LEGENDS.LEGEND_LAYERSET_UPDATED,
(payload) => {
- const { resultsSet } = payload;
- displayLegend('LegendsId2', resultsSet);
+ const { resultSet } = payload;
+ displayLegend('LegendsId2', resultSet);
},
'LYR2/LegendsLayerSet'
);
@@ -509,17 +510,17 @@ 4. Many Esri Feature Layers - with footer bar
cgpv.api.event.on(
cgpv.api.eventNames.GET_FEATURE_INFO.ALL_QUERIES_DONE,
(payload) => {
- const { layerSetId, resultsSet, eventType } = payload;
- createInfoTable('LYR3', 'ResultSetId3', resultsSet, eventType);
+ const { layerSetId, resultSet, eventType } = payload;
+ createInfoTable('LYR3', 'ResultSetId3', resultSet, eventType);
},
'LYR3/FeatureInfoLayerSet'
);
cgpv.api.event.on(
- cgpv.api.eventNames.GET_LEGENDS.LEGENDS_LAYERSET_UPDATED,
+ cgpv.api.eventNames.GET_LEGENDS.LEGEND_LAYERSET_UPDATED,
(payload) => {
- const { resultsSet } = payload;
- displayLegend('LegendsId3', resultsSet);
+ const { resultSet } = payload;
+ displayLegend('LegendsId3', resultSet);
},
'LYR3/LegendsLayerSet'
);
diff --git a/packages/geoview-core/public/templates/layers/esri-image.html b/packages/geoview-core/public/templates/layers/esri-image.html
index 52a3b67e1e6..c46743342cf 100644
--- a/packages/geoview-core/public/templates/layers/esri-image.html
+++ b/packages/geoview-core/public/templates/layers/esri-image.html
@@ -273,10 +273,10 @@ 2. ESRI Image Layers - with footer bar
// LYR1 ===================================================================================================================
const LegendsLayerSet1 = cgpv.api.getLegendsLayerSet('Map1', 'LegendsId1');
cgpv.api.event.on(
- cgpv.api.eventNames.GET_LEGENDS.LEGENDS_LAYERSET_UPDATED,
+ cgpv.api.eventNames.GET_LEGENDS.LEGEND_LAYERSET_UPDATED,
(payload) => {
- const { resultsSet } = payload;
- displayLegend('LegendsId1', resultsSet);
+ const { resultSet } = payload;
+ displayLegend('LegendsId1', resultSet);
},
'Map1/LegendsLayerSet'
);
diff --git a/packages/geoview-core/public/templates/layers/geocore.html b/packages/geoview-core/public/templates/layers/geocore.html
index cdfe6e93c21..2e8aa977e98 100644
--- a/packages/geoview-core/public/templates/layers/geocore.html
+++ b/packages/geoview-core/public/templates/layers/geocore.html
@@ -237,18 +237,18 @@ 2. GeoCore Layers - with footer bar
cgpv.api.event.on(
cgpv.api.eventNames.GET_FEATURE_INFO.ALL_QUERIES_DONE,
(payload) => {
- const { layerSetId, resultsSet, eventType } = payload;
- createInfoTable('LYR1', 'ResultSetId1', resultsSet, eventType);
+ const { layerSetId, resultSet, eventType } = payload;
+ createInfoTable('LYR1', 'ResultSetId1', resultSet, eventType);
},
'LYR1/FeatureInfoLayerSet'
);
const LegendsLayerSet1 = cgpv.api.getLegendsLayerSet('LYR1');
cgpv.api.event.on(
- cgpv.api.eventNames.GET_LEGENDS.LEGENDS_LAYERSET_UPDATED,
+ cgpv.api.eventNames.GET_LEGENDS.LEGEND_LAYERSET_UPDATED,
(payload) => {
- const { resultsSet } = payload;
- displayLegend('LegendsId1', resultsSet);
+ const { resultSet } = payload;
+ displayLegend('LegendsId1', resultSet);
},
'LYR1/LegendsLayerSet'
);
diff --git a/packages/geoview-core/public/templates/layers/geojson.html b/packages/geoview-core/public/templates/layers/geojson.html
index 1f3ae454a43..a1e1bfc22ca 100644
--- a/packages/geoview-core/public/templates/layers/geojson.html
+++ b/packages/geoview-core/public/templates/layers/geojson.html
@@ -292,18 +292,18 @@ 2. Many GeoJSON Layers - with footer bar
cgpv.api.event.on(
cgpv.api.eventNames.GET_FEATURE_INFO.ALL_QUERIES_DONE,
(payload) => {
- const { layerSetId, resultsSet, eventType } = payload;
- createInfoTable('LYR1', 'ResultSetId1', resultsSet, eventType);
+ const { layerSetId, resultSet, eventType } = payload;
+ createInfoTable('LYR1', 'ResultSetId1', resultSet, eventType);
},
'LYR1/FeatureInfoLayerSet'
);
const LegendLayerSet = cgpv.api.getLegendsLayerSet('LYR1');
cgpv.api.event.on(
- cgpv.api.eventNames.GET_LEGENDS.LEGENDS_LAYERSET_UPDATED,
+ cgpv.api.eventNames.GET_LEGENDS.LEGEND_LAYERSET_UPDATED,
(payload) => {
- const { resultsSet } = payload;
- displayLegend('LegendsId1', resultsSet);
+ const { resultSet } = payload;
+ displayLegend('LegendsId1', resultSet);
},
'LYR1/LegendsLayerSet'
);
diff --git a/packages/geoview-core/public/templates/layers/geopackage.html b/packages/geoview-core/public/templates/layers/geopackage.html
index 73fd67bc249..9b3d9ddc407 100644
--- a/packages/geoview-core/public/templates/layers/geopackage.html
+++ b/packages/geoview-core/public/templates/layers/geopackage.html
@@ -263,18 +263,18 @@ 3. Geopackage Layers - with footer bar
cgpv.api.event.on(
cgpv.api.eventNames.GET_FEATURE_INFO.ALL_QUERIES_DONE,
(payload) => {
- const { layerSetId, resultsSet, eventType } = payload;
- createInfoTable('LYR1', 'ResultSetId1', resultsSet, eventType);
+ const { layerSetId, resultSet, eventType } = payload;
+ createInfoTable('LYR1', 'ResultSetId1', resultSet, eventType);
},
'LYR1/FeatureInfoLayerSet'
);
const LegendsLayerSet1 = cgpv.api.getLegendsLayerSet('LYR1');
cgpv.api.event.on(
- cgpv.api.eventNames.GET_LEGENDS.LEGENDS_LAYERSET_UPDATED,
+ cgpv.api.eventNames.GET_LEGENDS.LEGEND_LAYERSET_UPDATED,
(payload) => {
- const { resultsSet } = payload;
- displayLegend('LegendsId1', resultsSet);
+ const { resultSet } = payload;
+ displayLegend('LegendsId1', resultSet);
},
'LYR1/LegendsLayerSet'
);
diff --git a/packages/geoview-core/public/templates/layers/image-static.html b/packages/geoview-core/public/templates/layers/image-static.html
index 9fc915e36c8..3de9d1b6322 100644
--- a/packages/geoview-core/public/templates/layers/image-static.html
+++ b/packages/geoview-core/public/templates/layers/image-static.html
@@ -193,10 +193,10 @@ 2. Static Image Layers - with footer bar
// LYR1 ===================================================================================================================
const LegendsLayerSet1 = cgpv.api.getLegendsLayerSet('LYR1', 'LegendsId1');
cgpv.api.event.on(
- cgpv.api.eventNames.GET_LEGENDS.LEGENDS_LAYERSET_UPDATED,
+ cgpv.api.eventNames.GET_LEGENDS.LEGEND_LAYERSET_UPDATED,
(payload) => {
- const { resultsSet } = payload;
- displayLegend('LegendsId1', resultsSet);
+ const { resultSet } = payload;
+ displayLegend('LegendsId1', resultSet);
},
'LYR1/LegendsLayerSet'
);
diff --git a/packages/geoview-core/public/templates/layers/layerlib.js b/packages/geoview-core/public/templates/layers/layerlib.js
index 556720d8604..9a31dd46924 100644
--- a/packages/geoview-core/public/templates/layers/layerlib.js
+++ b/packages/geoview-core/public/templates/layers/layerlib.js
@@ -4,15 +4,15 @@
function listenToLegendLayerSetChanges(elementId, handlerName) {
const mapId = handlerName.split('/')[0];
cgpv.api.event.on(
- cgpv.api.eventNames.GET_LEGENDS.LEGENDS_LAYERSET_UPDATED,
+ cgpv.api.eventNames.LAYER_SET.UPDATED,
(payload) => {
const outputHeader =
'
Name | Phase | Status |
';
const displayField = document.getElementById(elementId);
- const { resultsSet } = payload;
- const output = Object.keys(resultsSet).reduce((outputValue, layerPath) => {
- const layerName = resultsSet[layerPath]?.layerName || '';
- const { layerStatus } = resultsSet[layerPath];
+ const { resultSet } = payload;
+ const output = Object.keys(resultSet).reduce((outputValue, layerPath) => {
+ const layerName = resultSet[layerPath]?.layerName || '';
+ const { layerStatus } = resultSet[layerPath];
const { layerPhase } = cgpv.api.maps[mapId].layer.registeredLayers[layerPath];
return `${outputValue}${layerName} | ${layerPhase} | ${layerStatus} |
`;
}, outputHeader);
@@ -44,17 +44,17 @@ const addBoundsPolygon = (mapId, bbox) => {
};
// ==========================================================================================================================
-const createInfoTable = (mapId, resultsSetId, resultsSet, eventType) => {
+const createInfoTable = (mapId, resultSetId, resultSet, eventType) => {
if (!['click', 'all-features'].includes(eventType)) return;
- const infoTable = document.getElementById(`${resultsSetId}-${eventType}`);
+ const infoTable = document.getElementById(`${resultSetId}-${eventType}`);
infoTable.textContent = '';
const oldContent = document.getElementById(`layer${mapId.slice(-1)}-${eventType}-info`);
if (oldContent) oldContent.remove();
const content = document.createElement('div');
content.id = `layer${mapId.slice(-1)}-${eventType}-info`;
infoTable.appendChild(content);
- Object.keys(resultsSet).forEach((layerPath) => {
- const activeResultSet = resultsSet[layerPath];
+ Object.keys(resultSet).forEach((layerPath) => {
+ const activeResultSet = resultSet[layerPath];
const layerData = activeResultSet.data[eventType].features;
// Header of the layer
@@ -442,7 +442,7 @@ const createTableOfFilter = (mapId) => {
};
// ==========================================================================================================================
-function displayLegend(layerSetId, resultsSet) {
+function displayLegend(layerSetId, resultSet) {
const addHeader = (title, container) => {
const tableHeader = document.createElement('th');
tableHeader.style = 'text-align: center; vertical-align: middle;';
@@ -468,8 +468,8 @@ function displayLegend(layerSetId, resultsSet) {
table.style = 'width:50%';
legendTable.appendChild(table);
let createHeader = true;
- Object.keys(resultsSet).forEach((layerPath) => {
- const activeResultSet = resultsSet[layerPath];
+ Object.keys(resultSet).forEach((layerPath) => {
+ const activeResultSet = resultSet[layerPath];
if (createHeader) {
createHeader = false;
const tableRow1 = document.createElement('tr');
diff --git a/packages/geoview-core/public/templates/layers/ogc-feature.html b/packages/geoview-core/public/templates/layers/ogc-feature.html
index a4945816100..bc249e7fa17 100644
--- a/packages/geoview-core/public/templates/layers/ogc-feature.html
+++ b/packages/geoview-core/public/templates/layers/ogc-feature.html
@@ -190,17 +190,17 @@ 2. OGC Feature API Layers - with footer bar
cgpv.api.event.on(
cgpv.api.eventNames.GET_FEATURE_INFO.ALL_QUERIES_DONE,
(payload) => {
- const { layerSetId, resultsSet, eventType } = payload;
- createInfoTable('LYR1', 'ResultSetId1', resultsSet, eventType);
+ const { layerSetId, resultSet, eventType } = payload;
+ createInfoTable('LYR1', 'ResultSetId1', resultSet, eventType);
},
'LYR1/FeatureInfoLayerSet'
);
cgpv.api.event.on(
- cgpv.api.eventNames.GET_LEGENDS.LEGENDS_LAYERSET_UPDATED,
+ cgpv.api.eventNames.GET_LEGENDS.LEGEND_LAYERSET_UPDATED,
(payload) => {
- const { resultsSet } = payload;
- displayLegend('LegendsId1', resultsSet);
+ const { resultSet } = payload;
+ displayLegend('LegendsId1', resultSet);
},
'LYR1/LegendsLayerSet'
);
diff --git a/packages/geoview-core/public/templates/layers/wfs.html b/packages/geoview-core/public/templates/layers/wfs.html
index bff85133d1d..f3cc9e3f980 100644
--- a/packages/geoview-core/public/templates/layers/wfs.html
+++ b/packages/geoview-core/public/templates/layers/wfs.html
@@ -294,17 +294,17 @@ 3. WFS Layers - with footer bar
cgpv.api.event.on(
cgpv.api.eventNames.GET_FEATURE_INFO.ALL_QUERIES_DONE,
(payload) => {
- const { layerSetId, resultsSet, eventType } = payload;
- createInfoTable('LYR1', 'ResultSetId1', resultsSet, eventType);
+ const { layerSetId, resultSet, eventType } = payload;
+ createInfoTable('LYR1', 'ResultSetId1', resultSet, eventType);
},
'LYR1/FeatureInfoLayerSet'
);
cgpv.api.event.on(
- cgpv.api.eventNames.GET_LEGENDS.LEGENDS_LAYERSET_UPDATED,
+ cgpv.api.eventNames.GET_LEGENDS.LEGEND_LAYERSET_UPDATED,
(payload) => {
- const { resultsSet } = payload;
- displayLegend('LegendsId1', resultsSet);
+ const { resultSet } = payload;
+ displayLegend('LegendsId1', resultSet);
},
'LYR1/LegendsLayerSet'
);
@@ -320,17 +320,17 @@ 3. WFS Layers - with footer bar
cgpv.api.event.on(
cgpv.api.eventNames.GET_FEATURE_INFO.ALL_QUERIES_DONE,
(payload) => {
- const { layerSetId, resultsSet, eventType } = payload;
- createInfoTable('LYR2', 'ResultSetId2', resultsSet, eventType);
+ const { layerSetId, resultSet, eventType } = payload;
+ createInfoTable('LYR2', 'ResultSetId2', resultSet, eventType);
},
'LYR2/FeatureInfoLayerSet'
);
cgpv.api.event.on(
- cgpv.api.eventNames.GET_LEGENDS.LEGENDS_LAYERSET_UPDATED,
+ cgpv.api.eventNames.GET_LEGENDS.LEGEND_LAYERSET_UPDATED,
(payload) => {
- const { resultsSet } = payload;
- displayLegend('LegendsId2', resultsSet);
+ const { resultSet } = payload;
+ displayLegend('LegendsId2', resultSet);
},
'LYR2/LegendsLayerSet'
);
diff --git a/packages/geoview-core/public/templates/layers/wms.html b/packages/geoview-core/public/templates/layers/wms.html
index 0aae0fbf8de..4537f384b7a 100644
--- a/packages/geoview-core/public/templates/layers/wms.html
+++ b/packages/geoview-core/public/templates/layers/wms.html
@@ -590,7 +590,7 @@ 5. Many WMS Layers - with footer bar
const intervalId = window.setInterval(() => {
// If metadata are processed
- if (cgpv.api.maps.LYR3?.layer?.geoviewLayers?.['wmsLYR3-Root']?.allLayerStatusAreIn(['processed', 'loading', 'loaded', 'error'])) {
+ if (cgpv.api.maps.LYR3?.layer?.geoviewLayers?.['wmsLYR3-Root']?.allLayerStatusAreGreaterThanOrEqualTo('processed')) {
const lyr3LayerConfig = cgpv.api.maps.LYR3.layer.registeredLayers['wmsLYR3-Root/landcover_2015_19classes'];
if (Array.isArray(lyr3LayerConfig?.source?.style)) {
const dropDownContent = document.getElementById('style');
@@ -644,18 +644,18 @@ 5. Many WMS Layers - with footer bar
cgpv.api.event.on(
cgpv.api.eventNames.GET_FEATURE_INFO.ALL_QUERIES_DONE,
(payload) => {
- const { layerSetId, resultsSet, eventType } = payload;
- createInfoTable('LYR1', 'ResultSetId1', resultsSet, eventType);
+ const { layerSetId, resultSet, eventType } = payload;
+ createInfoTable('LYR1', 'ResultSetId1', resultSet, eventType);
},
'LYR1/FeatureInfoLayerSet'
);
const LegendsLayerSet1 = cgpv.api.getLegendsLayerSet('LYR1');
cgpv.api.event.on(
- cgpv.api.eventNames.GET_LEGENDS.LEGENDS_LAYERSET_UPDATED,
+ cgpv.api.eventNames.GET_LEGENDS.LEGEND_LAYERSET_UPDATED,
(payload) => {
- const { resultsSet } = payload;
- displayLegend('LegendsId1', resultsSet);
+ const { resultSet } = payload;
+ displayLegend('LegendsId1', resultSet);
},
'LYR1/LegendsLayerSet'
);
@@ -674,18 +674,18 @@ 5. Many WMS Layers - with footer bar
cgpv.api.event.on(
cgpv.api.eventNames.GET_FEATURE_INFO.ALL_QUERIES_DONE,
(payload) => {
- const { layerSetId, resultsSet, eventType } = payload;
- createInfoTable('LYR2', 'ResultSetId2', resultsSet, eventType);
+ const { layerSetId, resultSet, eventType } = payload;
+ createInfoTable('LYR2', 'ResultSetId2', resultSet, eventType);
},
'LYR2/FeatureInfoLayerSet'
);
const LegendsLayerSet2 = cgpv.api.getLegendsLayerSet('LYR2');
cgpv.api.event.on(
- cgpv.api.eventNames.GET_LEGENDS.LEGENDS_LAYERSET_UPDATED,
+ cgpv.api.eventNames.GET_LEGENDS.LEGEND_LAYERSET_UPDATED,
(payload) => {
- const { resultsSet } = payload;
- displayLegend('LegendsId2', resultsSet);
+ const { resultSet } = payload;
+ displayLegend('LegendsId2', resultSet);
},
'LYR2/LegendsLayerSet'
);
@@ -697,18 +697,18 @@ 5. Many WMS Layers - with footer bar
cgpv.api.event.on(
cgpv.api.eventNames.GET_FEATURE_INFO.ALL_QUERIES_DONE,
(payload) => {
- const { layerSetId, resultsSet, eventType } = payload;
- createInfoTable('LYR3', 'ResultSetId3', resultsSet, eventType);
+ const { layerSetId, resultSet, eventType } = payload;
+ createInfoTable('LYR3', 'ResultSetId3', resultSet, eventType);
},
'LYR3/FeatureInfoLayerSet'
);
const LegendsLayerSet3 = cgpv.api.getLegendsLayerSet('LYR3');
cgpv.api.event.on(
- cgpv.api.eventNames.GET_LEGENDS.LEGENDS_LAYERSET_UPDATED,
+ cgpv.api.eventNames.GET_LEGENDS.LEGEND_LAYERSET_UPDATED,
(payload) => {
- const { resultsSet } = payload;
- displayLegend('LegendsId3', resultsSet);
+ const { resultSet } = payload;
+ displayLegend('LegendsId3', resultSet);
},
'LYR3/LegendsLayerSet'
);
@@ -718,10 +718,10 @@ 5. Many WMS Layers - with footer bar
//LYR4 ===================================================================================================================
const LegendsLayerSet4 = cgpv.api.getLegendsLayerSet('LYR4', 'LegendsId4');
cgpv.api.event.on(
- cgpv.api.eventNames.GET_LEGENDS.LEGENDS_LAYERSET_UPDATED,
+ cgpv.api.eventNames.GET_LEGENDS.LEGEND_LAYERSET_UPDATED,
(payload) => {
- const { resultsSet } = payload;
- displayLegend('LegendsId4', resultsSet);
+ const { resultSet } = payload;
+ displayLegend('LegendsId4', resultSet);
},
'LYR4/LegendsLayerSet'
);
diff --git a/packages/geoview-core/public/templates/package-swiper.html b/packages/geoview-core/public/templates/package-swiper.html
index 0f203c16392..a145bcceb3a 100644
--- a/packages/geoview-core/public/templates/package-swiper.html
+++ b/packages/geoview-core/public/templates/package-swiper.html
@@ -99,11 +99,11 @@ (undefined)
window.setInterval(() => {
const displayField1 = document.getElementById('HUC3-state');
- const geoviewLayers = cgpv.api.getFeatureInfoLayerSet('mapWM3').resultsSet;
- if (geoviewLayers) {
- const output = Object.keys(geoviewLayers).reduce((outputValue, layerId) => {
- const { layerPhase, layerStatus } = geoviewLayers[layerId];
- return `${outputValue}${layerId.split('/')[layerId.split('/').length - 1]} - status: ${layerStatus}, phase: ${layerPhase}, `;
+ const featureInfoLayerSet = cgpv.api.getFeatureInfoLayerSet('mapWM3').resultSet;
+ if (featureInfoLayerSet) {
+ const output = Object.keys(featureInfoLayerSet).reduce((outputValue, layerId) => {
+ const { layerStatus } = featureInfoLayerSet[layerId];
+ return `${outputValue}${layerId.split('/')[layerId.split('/').length - 1]} - status: ${layerStatus}, `;
}, '(');
displayField1.textContent = output && output !== '(' ? `${output.slice(0, -2)})` : '(undefined)';
} else displayField1.textContent = '(undefined)';
diff --git a/packages/geoview-core/public/templates/pygeoapi-processes.html b/packages/geoview-core/public/templates/pygeoapi-processes.html
index bfbef6e918f..dd01dfdd234 100644
--- a/packages/geoview-core/public/templates/pygeoapi-processes.html
+++ b/packages/geoview-core/public/templates/pygeoapi-processes.html
@@ -145,18 +145,18 @@ GeoJSON Layer
cgpv.api.event.on(
cgpv.api.eventNames.GET_FEATURE_INFO.ALL_QUERIES_DONE,
(payload) => {
- const { layerSetId, resultsSet, eventType } = payload;
- createInfoTable('LYR5', 'geoJsonResultSetId', resultsSet, eventType);
+ const { layerSetId, resultSet, eventType } = payload;
+ createInfoTable('LYR5', 'geoJsonResultSetId', resultSet, eventType);
},
'LYR5/FeatureInfoLayerSet'
);
const LegendsGeoJsonLayerSet = cgpv.api.getLegendsLayerSet('LYR5');
cgpv.api.event.on(
- cgpv.api.eventNames.GET_LEGENDS.LEGENDS_LAYERSET_UPDATED,
+ cgpv.api.eventNames.GET_LEGENDS.LEGEND_LAYERSET_UPDATED,
(payload) => {
- const { resultsSet } = payload;
- displayLegend('geojsonLegendsId', resultsSet);
+ const { resultSet } = payload;
+ displayLegend('geojsonLegendsId', resultSet);
},
'LYR5/LegendsLayerSet'
);
diff --git a/packages/geoview-core/public/templates/test.html b/packages/geoview-core/public/templates/test.html
index 670a8fafd2e..cf083c3b9c2 100644
--- a/packages/geoview-core/public/templates/test.html
+++ b/packages/geoview-core/public/templates/test.html
@@ -512,17 +512,17 @@ 1. Many ESRI Dynamic Layers with legend settings in the config {
- const { layerSetId, resultsSet, eventType } = payload;
- createInfoTable('LYR1', 'ResultSetId1', resultsSet, eventType);
+ const { layerSetId, resultSet, eventType } = payload;
+ createInfoTable('LYR1', 'ResultSetId1', resultSet, eventType);
},
'LYR1/FeatureInfoLayerSet'
);
cgpv.api.event.on(
- cgpv.api.eventNames.GET_LEGENDS.LEGENDS_LAYERSET_UPDATED,
+ cgpv.api.eventNames.GET_LEGENDS.LEGEND_LAYERSET_UPDATED,
(payload) => {
- const { resultsSet } = payload;
- displayLegend('LegendsId1', resultsSet);
+ const { resultSet } = payload;
+ displayLegend('LegendsId1', resultSet);
},
'LYR1/LegendsLayerSet'
);
diff --git a/packages/geoview-core/src/api/event-processors/event-processor-children/feature-info-event-processor.ts b/packages/geoview-core/src/api/event-processors/event-processor-children/feature-info-event-processor.ts
index 7035c02f621..99e13edb0ba 100644
--- a/packages/geoview-core/src/api/event-processors/event-processor-children/feature-info-event-processor.ts
+++ b/packages/geoview-core/src/api/event-processors/event-processor-children/feature-info-event-processor.ts
@@ -1,5 +1,5 @@
import { GeoviewStoreType, IFeatureInfoState } from '@/core/stores';
-import { TypeFeatureInfoResultsSet, EventType, TypeLayerData, TypeArrayOfLayerData } from '@/api/events/payloads/get-feature-info-payload';
+import { TypeFeatureInfoResultSet, EventType, TypeLayerData, TypeArrayOfLayerData } from '@/api/events/payloads/get-feature-info-payload';
import { logger } from '@/core/utils/logger';
import { AbstractEventProcessor, BatchedPropagationLayerDataArrayByMap } from '../abstract-event-processor';
@@ -157,9 +157,9 @@ export class FeatureInfoEventProcessor extends AbstractEventProcessor {
* @param {string} mapId The map identifier of the modified result set.
* @param {string} layerPath The layer path that has changed.
* @param {EventType} eventType The event type that triggered the layer set update.
- * @param {TypeFeatureInfoResultsSet} resultsSet The resul sets associated to the map.
+ * @param {TypeFeatureInfoResultSet} resultSet The resul sets associated to the map.
*/
- static propagateFeatureInfoToStore(mapId: string, layerPath: string, eventType: EventType, resultsSet: TypeFeatureInfoResultsSet) {
+ static propagateFeatureInfoToStore(mapId: string, layerPath: string, eventType: EventType, resultSet: TypeFeatureInfoResultSet) {
// The feature info state
const featureInfoState = this.getFeatureInfoState(mapId);
@@ -170,7 +170,7 @@ export class FeatureInfoEventProcessor extends AbstractEventProcessor {
*/
const layerDataArray = [...featureInfoState.layerDataArray];
if (!layerDataArray.find((layerEntry) => layerEntry.layerPath === layerPath))
- layerDataArray.push(resultsSet?.[layerPath]?.data.click as TypeLayerData);
+ layerDataArray.push(resultSet?.[layerPath]?.data.click as TypeLayerData);
const atLeastOneFeature = layerDataArray.find((layerEntry) => !!layerEntry.features?.length) || false;
// Update the layer data array in the store, all the time, for all statuses
@@ -191,7 +191,7 @@ export class FeatureInfoEventProcessor extends AbstractEventProcessor {
*/
const hoverDataArray = [...featureInfoState.hoverDataArray];
if (!hoverDataArray.find((layerEntry) => layerEntry.layerPath === layerPath)) {
- hoverDataArray.push(resultsSet?.[layerPath]?.data.hover as TypeLayerData);
+ hoverDataArray.push(resultSet?.[layerPath]?.data.hover as TypeLayerData);
featureInfoState.actions.setHoverDataArray(hoverDataArray);
}
} else if (eventType === 'all-features') {
@@ -200,7 +200,7 @@ export class FeatureInfoEventProcessor extends AbstractEventProcessor {
*/
const allFeaturesDataArray = [...featureInfoState.allFeaturesDataArray];
if (!allFeaturesDataArray.find((layerEntry) => layerEntry.layerPath === layerPath)) {
- allFeaturesDataArray.push(resultsSet?.[layerPath]?.data['all-features'] as TypeLayerData);
+ allFeaturesDataArray.push(resultSet?.[layerPath]?.data['all-features'] as TypeLayerData);
featureInfoState.actions.setAllFeaturesDataArray(allFeaturesDataArray);
}
}
diff --git a/packages/geoview-core/src/api/event-processors/event-processor-children/legend-event-processor.ts b/packages/geoview-core/src/api/event-processors/event-processor-children/legend-event-processor.ts
index 989bb2107e7..07c0cef5138 100644
--- a/packages/geoview-core/src/api/event-processors/event-processor-children/legend-event-processor.ts
+++ b/packages/geoview-core/src/api/event-processors/event-processor-children/legend-event-processor.ts
@@ -1,4 +1,4 @@
-import { TypeLegendResultsSetEntry } from '@/api/events/payloads';
+import { TypeLegendResultSetEntry } from '@/api/events/payloads';
import {
isClassBreakStyleConfig,
isImageStaticLegend,
@@ -14,7 +14,6 @@ import {
} from '@/geo';
import { TypeLegendLayer, TypeLegendLayerIcons, TypeLegendLayerItem, TypeLegendItem } from '@/core/components/layers/types';
import { api, getLocalizedValue, ILayerState } from '@/app';
-import { delay } from '@/core/utils/utilities';
import { logger } from '@/core/utils/logger';
import { AbstractEventProcessor } from '../abstract-event-processor';
@@ -135,17 +134,16 @@ export class LegendEventProcessor extends AbstractEventProcessor {
return undefined;
}
- public static async propagateLegendToStore(
- mapId: string,
- layerPath: string,
- legendResultsSetEntry: TypeLegendResultsSetEntry
- ): Promise {
+ /** ***************************************************************************************************************************
+ * This method propagates the information stored in the legend layer set to the store.
+ *
+ * @param {string} mapId The map identifier.
+ * @param {string} layerPath The layer path that changed.
+ * @param {TypeLegendResultSetEntry} legendResultSetEntry The legend result set that triggered the propagation.
+ */
+ public static propagateLegendToStore(mapId: string, layerPath: string, legendResultSetEntry: TypeLegendResultSetEntry) {
const layerPathNodes = layerPath.split('/');
- const createNewLegendEntries = async (
- layerPathBeginning: string,
- currentLevel: number,
- existingEntries: TypeLegendLayer[]
- ): Promise => {
+ const createNewLegendEntries = (layerPathBeginning: string, currentLevel: number, existingEntries: TypeLegendLayer[]) => {
const entryLayerPath = `${layerPathBeginning}/${layerPathNodes[currentLevel]}`;
const layerConfig = api.maps[mapId].layer.registeredLayers[entryLayerPath] as TypeLayerEntryConfig;
let entryIndex = existingEntries.findIndex((entry) => entry.layerPath === entryLayerPath);
@@ -154,22 +152,23 @@ export class LegendEventProcessor extends AbstractEventProcessor {
const legendLayerEntry: TypeLegendLayer = {
bounds: undefined,
layerId: layerConfig.layerId,
- // TODO: Why do we have the following line in the store? Do we have to fetch the metadata again since the GeoView layer read and keep them?
- metadataAccessPath: getLocalizedValue(layerConfig.geoviewLayerConfig?.metadataAccessPath, mapId) || '',
layerPath: entryLayerPath,
- layerStatus: legendResultsSetEntry.layerStatus,
- layerName: getLocalizedValue(layerConfig.layerName, mapId) || layerConfig.layerId,
+ layerStatus: legendResultSetEntry.layerStatus,
+ layerName:
+ legendResultSetEntry.layerName ||
+ getLocalizedValue(layerConfig.layerName, mapId) ||
+ getLocalizedValue(layerConfig.geoviewLayerInstance?.geoviewLayerName, mapId) ||
+ layerConfig.layerPath,
type: layerConfig.entryType as TypeGeoviewLayerType,
- canToggle: legendResultsSetEntry.data?.type !== 'esriImage',
+ canToggle: legendResultSetEntry.data?.type !== 'esriImage',
opacity: layerConfig.initialSettings?.opacity ? layerConfig.initialSettings.opacity : 1,
items: [] as TypeLegendItem[],
children: [] as TypeLegendLayer[],
};
existingEntries.push(legendLayerEntry);
entryIndex = existingEntries.length - 1;
- } // else
- // We don't need to update it because basic information of a group node is not supposed to change after its creation.
- // Only the children may change and this is handled by the following call.
+ // eslint-disable-next-line no-param-reassign
+ } else existingEntries[entryIndex].layerStatus = layerConfig.layerStatus;
createNewLegendEntries(entryLayerPath, currentLevel + 1, existingEntries[entryIndex].children);
} else if (layerConfig) {
const newLegendLayer: TypeLegendLayer = {
@@ -177,18 +176,20 @@ export class LegendEventProcessor extends AbstractEventProcessor {
layerId: layerPathNodes[currentLevel],
layerPath: entryLayerPath,
layerAttribution: api.maps[mapId].layer.geoviewLayers[layerPathNodes[0]].attributions,
- // ! Why do we have metadataAccessPath here? Do we need to fetch the metadata again? The GeoView layer fetch them and store them in this.metadata.
- metadataAccessPath: getLocalizedValue(layerConfig.geoviewLayerConfig?.metadataAccessPath, mapId) || '',
- layerName: getLocalizedValue(legendResultsSetEntry.data?.layerName, mapId) || layerConfig.layerId!,
- layerStatus: legendResultsSetEntry.layerStatus,
- querySent: legendResultsSetEntry.querySent,
- styleConfig: legendResultsSetEntry.data?.styleConfig,
- type: legendResultsSetEntry.data?.type,
- canToggle: legendResultsSetEntry.data?.type !== 'esriImage',
+ layerName:
+ legendResultSetEntry.layerName ||
+ getLocalizedValue(layerConfig.layerName, mapId) ||
+ getLocalizedValue(layerConfig.geoviewLayerInstance?.geoviewLayerName, mapId) ||
+ layerConfig.layerPath,
+ layerStatus: legendResultSetEntry.layerStatus,
+ querySent: legendResultSetEntry.querySent,
+ styleConfig: legendResultSetEntry.data?.styleConfig,
+ type: legendResultSetEntry.data?.type,
+ canToggle: legendResultSetEntry.data?.type !== 'esriImage',
opacity: layerConfig.initialSettings?.opacity || 1,
items: [] as TypeLegendItem[],
children: [] as TypeLegendLayer[],
- icons: LegendEventProcessor.getLayerIconImage(mapId, layerPath, legendResultsSetEntry.data!),
+ icons: LegendEventProcessor.getLayerIconImage(mapId, layerPath, legendResultSetEntry.data!),
};
newLegendLayer.items = [];
@@ -202,23 +203,9 @@ export class LegendEventProcessor extends AbstractEventProcessor {
// eslint-disable-next-line no-param-reassign
else existingEntries[entryIndex] = newLegendLayer;
- // TODO: find the best place to calculate layers item and assign https://github.com/Canadian-Geospatial-Platform/geoview/issues/1566
- // !Question: What is the relationship between the legend and the bounds? To me, there is no relation between them. The Legend information
- // ! saved in the store is there to list the layers on the map, to inform us if it is loaded on the map or in error, to show the
- // ! symbology of the features, if the data layers is visible or not, etc. I agree that all the other properties of the legend
- // ! type in the store are legit, but I strongly disagree that bounds is part of the legend and that we should throw an error
- // ! in getGeoviewLayerByIdAsync if the layer does not reach the 'processed' or 'error' status. I propose to delete the try/catch
- // ! instructions that follow and place the bounds in a nore logical place.
- try {
- // Await for the Geoview layer in loaded state
- const myLayer = await api.maps[mapId].layer.getGeoviewLayerByIdAsync(layerPathNodes[0], true);
-
- // Calculate the bounds (the calculation may return undefined when it fails)
- newLegendLayer.bounds = myLayer.calculateBounds(layerPath);
- } catch (error) {
- // Log
- logger.logError(`Couldn't initialize legend information on layer ${layerPath}`, error);
- }
+ const myLayer = api.maps[mapId].layer.geoviewLayers[layerPathNodes[0]];
+ // TODO: calculateBounds issue will be tackle ASAP in a next PR
+ newLegendLayer.bounds = myLayer.allLayerStatusAreGreaterThanOrEqualTo('loaded') ? myLayer.calculateBounds(layerPath) : undefined;
}
};
@@ -236,9 +223,7 @@ export class LegendEventProcessor extends AbstractEventProcessor {
// Flag so this is only executed once after initial load
LegendEventProcessor.propagatedOnce = true;
- // Give it some time so that each layer has their chance to load on time
- await delay(LegendEventProcessor.timeDelayBeforeSelectingLayerInStore);
-
+ // TODO: The selected layer issue will be tackle ASAP in a next PR
// Find the layers that are processed
const validFirstLayer = layers.find((layer) => {
return layer.layerStatus === 'processed';
@@ -250,9 +235,6 @@ export class LegendEventProcessor extends AbstractEventProcessor {
this.getLayerState(mapId).actions.setSelectedLayerPath(validFirstLayer.layerPath);
// Log
logger.logDebug(`Selected layer ${validFirstLayer.layerPath}`);
- } else {
- // Log
- logger.logError(`Couldn't select a layer as none were processed in time`);
}
}
}
diff --git a/packages/geoview-core/src/api/events/constants/get-feature-info-constants.ts b/packages/geoview-core/src/api/events/constants/get-feature-info-constants.ts
index 0eeef738e7f..08fbdd32078 100644
--- a/packages/geoview-core/src/api/events/constants/get-feature-info-constants.ts
+++ b/packages/geoview-core/src/api/events/constants/get-feature-info-constants.ts
@@ -6,12 +6,7 @@ import { EventStringId } from '../event-types';
*/
/** Valid keys for the GET_FEATURE_INFO category */
-export type GetFeatureInfoEventKey =
- | 'QUERY_LAYER'
- | 'ALL_QUERIES_DONE'
- | 'GET_ALL_LAYER_FEATURES'
- | 'QUERY_RESULT'
- | 'FEATURE_INFO_LAYERSET_UPDATED';
+export type GetFeatureInfoEventKey = 'QUERY_LAYER' | 'ALL_QUERIES_DONE' | 'QUERY_ALL_FEATURES' | 'QUERY_RESULT';
/** Record that associates GET_FEATURE_INFO's event keys to their event string id */
export const GET_FEATURE_INFO: Record = {
@@ -28,15 +23,10 @@ export const GET_FEATURE_INFO: Record = {
/**
* Event triggered when a user needs to get all features information for alayer on the map
*/
- GET_ALL_LAYER_FEATURES: 'get_feature_info/get_all_layer_features',
+ QUERY_ALL_FEATURES: 'get_feature_info/query_all_features',
/**
* Event triggered to send the result of the query
*/
QUERY_RESULT: 'get_feature_info/query_result',
-
- /**
- * Event triggered to send the result of the query
- */
- FEATURE_INFO_LAYERSET_UPDATED: 'get_feature_info/feature_info_layerset_updated',
};
diff --git a/packages/geoview-core/src/api/events/constants/get-legends-constants.ts b/packages/geoview-core/src/api/events/constants/get-legends-constants.ts
index f8dd3b27a6b..5d2afb79d72 100644
--- a/packages/geoview-core/src/api/events/constants/get-legends-constants.ts
+++ b/packages/geoview-core/src/api/events/constants/get-legends-constants.ts
@@ -6,15 +6,10 @@ import { EventStringId } from '../event-types';
*/
/** Valid keys for the GET_LEGENDS category */
-export type GetLegendsEventKey = 'LEGENDS_LAYERSET_UPDATED' | 'LEGEND_INFO' | 'QUERY_LEGEND' | 'TRIGGER';
+export type GetLegendsEventKey = 'LEGEND_INFO' | 'QUERY_LEGEND' | 'TRIGGER';
/** Record that associates GET_LEGENDS's event keys to their event string id */
export const GET_LEGENDS: Record = {
- /**
- * Event triggered when all the queries of the layer set are done
- */
- LEGENDS_LAYERSET_UPDATED: 'get_legends/legends_layerset_updated',
-
/**
* Event triggered to send the result of the query
*/
diff --git a/packages/geoview-core/src/api/events/constants/layer-set-constants.ts b/packages/geoview-core/src/api/events/constants/layer-set-constants.ts
index 6dcd9e6e40f..54ad2c0501d 100644
--- a/packages/geoview-core/src/api/events/constants/layer-set-constants.ts
+++ b/packages/geoview-core/src/api/events/constants/layer-set-constants.ts
@@ -6,7 +6,7 @@ import { EventStringId } from '../event-types';
*/
/** Valid keys for the LAYER_SET category */
-export type LayerSetEventKey = 'REQUEST_LAYER_INVENTORY' | 'LAYER_REGISTRATION' | 'CHANGE_LAYER_STATUS' | 'CHANGE_LAYER_PHASE' | 'UPDATED';
+export type LayerSetEventKey = 'REQUEST_LAYER_INVENTORY' | 'LAYER_REGISTRATION' | 'CHANGE_LAYER_STATUS' | 'UPDATED';
/** Record that associates LAYER_SET's event keys to their event string id */
export const LAYER_SET: Record = {
@@ -25,11 +25,6 @@ export const LAYER_SET: Record = {
*/
CHANGE_LAYER_STATUS: 'layer_set/change_layer_status',
- /**
- * Event triggered when a layer's phase must be changed
- */
- CHANGE_LAYER_PHASE: 'layer_set/change_layer_phase',
-
/**
* Event triggered when a layer set has changed
*/
diff --git a/packages/geoview-core/src/api/events/event-types.ts b/packages/geoview-core/src/api/events/event-types.ts
index d15425b6360..cf2b7f5d8bc 100644
--- a/packages/geoview-core/src/api/events/event-types.ts
+++ b/packages/geoview-core/src/api/events/event-types.ts
@@ -56,11 +56,9 @@ export type EventStringId =
| 'geometry/on'
| 'geometry/remove'
| 'get_feature_info/all_queries_done'
- | 'get_feature_info/get_all_layer_features'
+ | 'get_feature_info/query_all_features'
| 'get_feature_info/query_layer'
| 'get_feature_info/query_result'
- | 'get_feature_info/feature_info_layerset_updated'
- | 'get_legends/legends_layerset_updated'
| 'get_legends/legend_info'
| 'get_legends/query_legends'
| 'get_legends/trigger'
@@ -75,7 +73,6 @@ export type EventStringId =
| 'interaction/translate_ended'
| 'layer_set/layer_registration'
| 'layer_set/change_layer_status'
- | 'layer_set/change_layer_phase'
| 'layer_set/request_layer_inventory'
| 'layer_set/updated'
| 'layer/add'
diff --git a/packages/geoview-core/src/api/events/payloads/get-feature-info-payload.ts b/packages/geoview-core/src/api/events/payloads/get-feature-info-payload.ts
index 7036357b3b9..6096fe7beeb 100644
--- a/packages/geoview-core/src/api/events/payloads/get-feature-info-payload.ts
+++ b/packages/geoview-core/src/api/events/payloads/get-feature-info-payload.ts
@@ -9,15 +9,13 @@ import { PayloadBaseClass } from './payload-base-class';
import { EventStringId, EVENT_NAMES } from '../event-types';
import { TypeGeoviewLayerType } from '@/geo/layer/geoview-layers/abstract-geoview-layers';
import { TypeLayerStatus } from '@/geo/map/map-schema-types';
-import { TypeResultsSet } from './layer-set-payload';
/** Valid events that can create GetFeatureInfoPayload */
const validEvents: EventStringId[] = [
EVENT_NAMES.GET_FEATURE_INFO.QUERY_LAYER,
- EVENT_NAMES.GET_FEATURE_INFO.GET_ALL_LAYER_FEATURES,
+ EVENT_NAMES.GET_FEATURE_INFO.QUERY_ALL_FEATURES,
EVENT_NAMES.GET_FEATURE_INFO.ALL_QUERIES_DONE,
EVENT_NAMES.GET_FEATURE_INFO.QUERY_RESULT,
- EVENT_NAMES.GET_FEATURE_INFO.FEATURE_INFO_LAYERSET_UPDATED,
];
export type EventType = 'click' | 'hover' | 'crosshaire-enter' | 'all-features';
@@ -93,15 +91,14 @@ export type TypeFeatureInfoByEventTypes = {
[eventName in EventType]?: TypeLayerData;
};
-export type TypeFeatureInfoResultsSetEntry = {
+export type TypeFeatureInfoResultSetEntry = {
+ layerName?: string;
layerStatus: TypeLayerStatus;
- layerPhase: string;
data: TypeFeatureInfoByEventTypes;
- layerName?: string;
};
-export type TypeFeatureInfoResultsSet = {
- [layerPath: string]: TypeFeatureInfoResultsSetEntry;
+export type TypeFeatureInfoResultSet = {
+ [layerPath: string]: TypeFeatureInfoResultSetEntry;
};
/**
@@ -125,7 +122,7 @@ export const payloadIsQueryLayer = (verifyIfPayload: PayloadBaseClass): verifyIf
* @returns {boolean} returns true if the payload is valid
*/
export const payloadIsGetAllLayerFeatures = (verifyIfPayload: PayloadBaseClass): verifyIfPayload is TypeQueryAllLayerFeaturesPayload => {
- return verifyIfPayload?.event === EVENT_NAMES.GET_FEATURE_INFO.GET_ALL_LAYER_FEATURES;
+ return verifyIfPayload?.event === EVENT_NAMES.GET_FEATURE_INFO.QUERY_ALL_FEATURES;
};
/**
@@ -138,20 +135,6 @@ export const payloadIsQueryLayerQueryTypeAtLongLat = (verifyIfPayload: PayloadBa
return payloadIsQueryLayer(verifyIfPayload) && verifyIfPayload.queryType === 'at_long_lat';
};
-/**
- * type guard function that redefines a PayloadBaseClass as a TypeFeatureInfoLayersetUpdatedPayload
- * if the event attribute of the verifyIfPayload parameter is valid. The type assertion
- * applies only to the true block of the if clause.
- *
- * @param {PayloadBaseClass} verifyIfPayload object to test in order to determine if the type assertion is valid
- * @returns {boolean} returns true if the payload is valid
- */
-export const payloadIsFeatureInfoLayersetUpdated = (
- verifyIfPayload: PayloadBaseClass
-): verifyIfPayload is TypeFeatureInfoLayersetUpdatedPayload => {
- return verifyIfPayload?.event === EVENT_NAMES.GET_FEATURE_INFO.FEATURE_INFO_LAYERSET_UPDATED;
-};
-
/**
* Additional attributes needed to define a GetFeatureInfoPayload
*/
@@ -200,8 +183,8 @@ export interface TypeAllQueriesDonePayload extends GetFeatureInfoPayload {
queryType: QueryType;
// The layer set identifier
layerSetId: string;
- // the resultsSet that contains the query results
- resultsSet: TypeFeatureInfoResultsSet;
+ // the resultSet that contains the query results
+ resultSet: TypeFeatureInfoResultSet;
}
/**
@@ -249,7 +232,7 @@ export interface TypeFeatureInfoLayersetUpdatedPayload extends GetFeatureInfoPay
// the layer path updated
layerPath: string;
// The result set containing all the legends of the layers loaded on the map.
- resultsSet: TypeFeatureInfoResultsSet;
+ resultSet: TypeFeatureInfoResultSet;
// The layer status that is associated to the layer path.
layerStatus: TypeLayerStatus;
}
@@ -311,7 +294,7 @@ export class GetFeatureInfoPayload extends PayloadBaseClass {
location?: string
): TypeQueryAllLayerFeaturesPayload => {
const queryLayerPayload = new GetFeatureInfoPayload(
- EVENT_NAMES.GET_FEATURE_INFO.GET_ALL_LAYER_FEATURES,
+ EVENT_NAMES.GET_FEATURE_INFO.QUERY_ALL_FEATURES,
handlerName
) as TypeQueryLayerPayload;
queryLayerPayload.queryType = queryType;
@@ -328,7 +311,7 @@ export class GetFeatureInfoPayload extends PayloadBaseClass {
* @param {string} layerPath the layer path updated
* @param {QueryType} queryType the query's type done
* @param {string} layerSetId the layer set identifier
- * @param {TypeFeatureInfoResultsSet} resultsSet the result set for the query
+ * @param {TypeFeatureInfoResultSet} resultSet the result set for the query
*
* @returns {TypeAllQueriesDonePayload} the TypeAllQueriesDonePayload object created
*/
@@ -338,7 +321,7 @@ export class GetFeatureInfoPayload extends PayloadBaseClass {
layerPath: string,
queryType: QueryType,
layerSetId: string,
- resultsSet: TypeFeatureInfoResultsSet
+ resultSet: TypeFeatureInfoResultSet
): TypeAllQueriesDonePayload => {
const allQueriesDonePayload = new GetFeatureInfoPayload(
EVENT_NAMES.GET_FEATURE_INFO.ALL_QUERIES_DONE,
@@ -348,7 +331,7 @@ export class GetFeatureInfoPayload extends PayloadBaseClass {
allQueriesDonePayload.layerPath = layerPath;
allQueriesDonePayload.queryType = queryType;
allQueriesDonePayload.layerSetId = layerSetId;
- allQueriesDonePayload.resultsSet = resultsSet;
+ allQueriesDonePayload.resultSet = resultSet;
return allQueriesDonePayload;
};
@@ -377,29 +360,4 @@ export class GetFeatureInfoPayload extends PayloadBaseClass {
queryResultPayload.eventType = eventType;
return queryResultPayload;
};
-
- /**
- * Static method used to create a "feature info updated" payload.
- *
- * @param {string | null} handlerName the handler Name
- * @param {string} layerPath the layer path updated
- * @param {TypeResultsSet | TypeFeatureInfoResultsSet} resultsSet the feature info resultset
- *
- * @returns {TypeFeatureInfoLayersetUpdatedPayload} the TypeFeatureInfoLayersetUpdatedPayload object created
- */
- static createFeatureInfoLayersetUpdatedPayload = (
- handlerName: string,
- layerPath: string,
- resultsSet: TypeResultsSet | TypeFeatureInfoResultsSet,
- layerStatus: TypeLayerStatus
- ): TypeFeatureInfoLayersetUpdatedPayload => {
- const featureInfoLayersetUpdatedPayload = new GetFeatureInfoPayload(
- EVENT_NAMES.GET_FEATURE_INFO.FEATURE_INFO_LAYERSET_UPDATED,
- handlerName
- ) as TypeFeatureInfoLayersetUpdatedPayload;
- featureInfoLayersetUpdatedPayload.layerPath = layerPath;
- featureInfoLayersetUpdatedPayload.resultsSet = resultsSet as TypeFeatureInfoResultsSet;
- featureInfoLayersetUpdatedPayload.layerStatus = layerStatus;
- return featureInfoLayersetUpdatedPayload;
- };
}
diff --git a/packages/geoview-core/src/api/events/payloads/get-legends-payload.ts b/packages/geoview-core/src/api/events/payloads/get-legends-payload.ts
index 55104c4538e..641db98a259 100644
--- a/packages/geoview-core/src/api/events/payloads/get-legends-payload.ts
+++ b/packages/geoview-core/src/api/events/payloads/get-legends-payload.ts
@@ -2,42 +2,23 @@ import { PayloadBaseClass } from './payload-base-class';
import { EventStringId, EVENT_NAMES } from '../event-types';
import { TypeLegend } from '@/geo/layer/geoview-layers/abstract-geoview-layers';
-import { TypeLayerStatus, TypeLocalizedString } from '@/geo/map/map-schema-types';
-import { TypeResultsSet } from './layer-set-payload';
+import { TypeLayerStatus } from '@/geo/map/map-schema-types';
/** Valid events that can create GetLegendsPayload */
-const validEvents: EventStringId[] = [
- EVENT_NAMES.GET_LEGENDS.LEGENDS_LAYERSET_UPDATED,
- EVENT_NAMES.GET_LEGENDS.LEGEND_INFO,
- EVENT_NAMES.GET_LEGENDS.QUERY_LEGEND,
-];
+const validEvents: EventStringId[] = [EVENT_NAMES.GET_LEGENDS.LEGEND_INFO, EVENT_NAMES.GET_LEGENDS.QUERY_LEGEND];
-export type TypeLegendResultsSetEntry = {
+export type TypeLegendResultSetEntry = {
+ layerName?: string;
layerStatus: TypeLayerStatus;
- querySent: boolean;
data: TypeLegend | undefined | null;
- layerName?: TypeLocalizedString;
+ querySent: boolean;
};
/** The legend resultset type associate a layer path to a legend object. The undefined value indicate that the get legend query
* hasn't been run and the null value indicate that there was a get legend error.
*/
-export type TypeLegendResultsSet = {
- [layerPath: string]: TypeLegendResultsSetEntry;
-};
-
-/**
- * type guard function that redefines a PayloadBaseClass as a TypeLegendsLayersetUpdatedPayload
- * if the event attribute of the verifyIfPayload parameter is valid. The type ascention
- * applies only to the true block of the if clause.
- *
- * @param {PayloadBaseClass} verifyIfPayload object to test in order to determine if the type ascention is valid
- * @returns {boolean} returns true if the payload is valid
- */
-export const payloadIsLegendsLayersetUpdated = (
- verifyIfPayload: PayloadBaseClass
-): verifyIfPayload is TypeLegendsLayersetUpdatedPayload => {
- return verifyIfPayload?.event === EVENT_NAMES.GET_LEGENDS.LEGENDS_LAYERSET_UPDATED;
+export type TypeLegendResultSet = {
+ [layerPath: string]: TypeLegendResultSetEntry;
};
/**
@@ -47,7 +28,7 @@ export interface TypeLegendsLayersetUpdatedPayload extends GetLegendsPayload {
// the layer path updated
layerPath: string;
// The result set containing all the legends of the layers loaded on the map.
- resultsSet: TypeLegendResultsSet;
+ resultSet: TypeLegendResultSet;
}
/**
@@ -127,29 +108,6 @@ export class GetLegendsPayload extends PayloadBaseClass {
super(event, handlerName);
}
- /**
- * Static method used to create a "legend updated" payload.
- *
- * @param {string | null} handlerName the handler Name
- * @param {string} layerPath the layer path updated
- * @param {TypeResultsSet | TypeLegendResultsSet} resultsSet the legend resultset
- *
- * @returns {TypeLegendsLayersetUpdatedPayload} the TypeLegendsLayersetUpdatedPayload object created
- */
- static createLegendsLayersetUpdatedPayload = (
- handlerName: string,
- layerPath: string,
- resultsSet: TypeResultsSet | TypeLegendResultsSet
- ): TypeLegendsLayersetUpdatedPayload => {
- const legendsLayersetUpdatedPayload = new GetLegendsPayload(
- EVENT_NAMES.GET_LEGENDS.LEGENDS_LAYERSET_UPDATED,
- handlerName
- ) as TypeLegendsLayersetUpdatedPayload;
- legendsLayersetUpdatedPayload.layerPath = layerPath;
- legendsLayersetUpdatedPayload.resultsSet = resultsSet as TypeLegendResultsSet;
- return legendsLayersetUpdatedPayload;
- };
-
/**
* Static method used to create a get legends payload that will return the legend's query result
*
diff --git a/packages/geoview-core/src/api/events/payloads/layer-set-payload.ts b/packages/geoview-core/src/api/events/payloads/layer-set-payload.ts
index 5914d81d58b..f76ef4d63c2 100644
--- a/packages/geoview-core/src/api/events/payloads/layer-set-payload.ts
+++ b/packages/geoview-core/src/api/events/payloads/layer-set-payload.ts
@@ -8,17 +8,18 @@ const validEvents: EventStringId[] = [
EVENT_NAMES.LAYER_SET.LAYER_REGISTRATION,
EVENT_NAMES.LAYER_SET.REQUEST_LAYER_INVENTORY,
EVENT_NAMES.LAYER_SET.CHANGE_LAYER_STATUS,
- EVENT_NAMES.LAYER_SET.CHANGE_LAYER_PHASE,
EVENT_NAMES.LAYER_SET.UPDATED,
];
-export type TypeResultsSet = {
- [layerPath: string]: {
- layerName?: string;
- layerStatus: TypeLayerStatus;
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- data: any;
- };
+export type TypeResultSetEntry = {
+ layerName?: string;
+ layerStatus: TypeLayerStatus;
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ data: any;
+};
+
+export type TypeResultSet = {
+ [layerPath: string]: TypeResultSetEntry;
};
/**
@@ -82,7 +83,7 @@ export const payloadIsLayerSetUpdated = (verifyIfPayload: PayloadBaseClass): ver
*/
export interface TypelayerSetUpdatedPayload extends LayerSetPayload {
/** An object containing the result sets indexed using the layer path */
- resultsSet: TypeResultsSet;
+ resultSet: TypeResultSet;
// The layerPath affected
layerPath: string;
}
@@ -111,16 +112,6 @@ export interface TypeLayerSetChangeLayerStatusPayload extends LayerSetPayload {
layerStatus: TypeLayerStatus;
}
-/**
- * Additional attributes needed to define a TypeLayerSetChangeLayerPhasePayload
- */
-export interface TypeLayerSetChangeLayerPhasePayload extends LayerSetPayload {
- // the layer path affected.
- layerPath: string;
- // The new layer phase to assign to the layer path.
- layerPhase: string;
-}
-
/**
* type guard function that redefines a PayloadBaseClass as a LayerSetPayload
* if the event attribute of the verifyIfPayload parameter is valid. The type ascention
@@ -217,29 +208,6 @@ export class LayerSetPayload extends PayloadBaseClass {
return layerSetChangeLayerStatusPayload;
};
- /**
- * Static method used to create a layer set payload when we need to change a layer phase
- *
- * @param {string} handlerName the handler Name
- * @param {string} layerPath the layer path affected by the change
- * @param {string} layerPhase the value to assign to the layerPhase property
- *
- * @returns {TypelayerSetUpdatedPayload} the requestLayerInventoryPayload object created
- */
- static createLayerSetChangeLayerPhasePayload = (
- handlerName: string,
- layerPath: string,
- layerPhase: string
- ): TypeLayerSetChangeLayerPhasePayload => {
- const layerSetChangeLayerPhasePayload = new LayerSetPayload(
- EVENT_NAMES.LAYER_SET.CHANGE_LAYER_PHASE,
- handlerName
- ) as TypeLayerSetChangeLayerPhasePayload;
- layerSetChangeLayerPhasePayload.layerPath = layerPath;
- layerSetChangeLayerPhasePayload.layerPhase = layerPhase;
- return layerSetChangeLayerPhasePayload;
- };
-
/**
* Static method used to create a layer set payload sent when a layer is updated
*
@@ -248,13 +216,9 @@ export class LayerSetPayload extends PayloadBaseClass {
*
* @returns {TypelayerSetUpdatedPayload} the requestLayerInventoryPayload object created
*/
- static createLayerSetUpdatedPayload = (
- handlerName: string,
- resultsSet: TypeResultsSet,
- layerPath: string
- ): TypelayerSetUpdatedPayload => {
+ static createLayerSetUpdatedPayload = (handlerName: string, resultSet: TypeResultSet, layerPath: string): TypelayerSetUpdatedPayload => {
const layerSetUpdatedPayload = new LayerSetPayload(EVENT_NAMES.LAYER_SET.UPDATED, handlerName) as TypelayerSetUpdatedPayload;
- layerSetUpdatedPayload.resultsSet = resultsSet;
+ layerSetUpdatedPayload.resultSet = resultSet;
layerSetUpdatedPayload.layerPath = layerPath;
return layerSetUpdatedPayload;
};
diff --git a/packages/geoview-core/src/core/components/hover-tooltip/hover-tooltip.tsx b/packages/geoview-core/src/core/components/hover-tooltip/hover-tooltip.tsx
index bdc8eb5d66e..c2b457ca148 100644
--- a/packages/geoview-core/src/core/components/hover-tooltip/hover-tooltip.tsx
+++ b/packages/geoview-core/src/core/components/hover-tooltip/hover-tooltip.tsx
@@ -69,10 +69,10 @@ export function HoverTooltip(): JSX.Element {
logger.logTraceCoreAPIEvent('HOVER-TOOLTIP - allQueriesDoneListenerFunciton', payload);
if (payloadIsAllQueriesDone(payload)) {
- const { eventType, resultsSet } = payload;
+ const { eventType, resultSet } = payload;
if (eventType === 'hover') {
// eslint-disable-next-line no-restricted-syntax
- for (const [, value] of Object.entries(resultsSet)) {
+ for (const [, value] of Object.entries(resultSet)) {
// if there is a result and layer is not ogcWms, and it is not selected, show tooltip
if (
value?.data?.hover?.features &&
@@ -90,8 +90,8 @@ export function HoverTooltip(): JSX.Element {
}
}
} else if (eventType === 'click') {
- Object.keys(resultsSet).every((layerPath) => {
- const features = resultsSet[layerPath]!.data.click?.features;
+ Object.keys(resultSet).every((layerPath) => {
+ const features = resultSet[layerPath]!.data.click?.features;
if (features && features.length > 0 && features[0].geoviewLayerType !== 'ogcWms') {
[selectedFeature.current] = features;
return false;
diff --git a/packages/geoview-core/src/core/components/layers/hooks/helpers.ts b/packages/geoview-core/src/core/components/layers/hooks/helpers.ts
index 165edb9c154..f8a0f21545f 100644
--- a/packages/geoview-core/src/core/components/layers/hooks/helpers.ts
+++ b/packages/geoview-core/src/core/components/layers/hooks/helpers.ts
@@ -12,7 +12,7 @@ export function useLegendHelpers() {
const { mapId } = store.getState();
function populateLegendStoreWithFakeData() {
- const legendInfo = api.getLegendsLayerSet(mapId).resultsSet;
+ const legendInfo = api.getLegendsLayerSet(mapId).resultSet;
// console.log('I got here ', legendInfo, _.keys(legendInfo));
const keys = _.keys(legendInfo);
@@ -68,7 +68,6 @@ export function useLegendHelpers() {
layerName: 'TEST--TestLayer1',
type: 'GeoJSON',
layerStatus: 'loaded',
- layerPhase: 'processed',
querySent: true,
children: [],
items: layerItems,
@@ -80,7 +79,6 @@ export function useLegendHelpers() {
layerName: 'TEST--Layer with groups',
type: 'GeoJSON',
layerStatus: 'loaded',
- layerPhase: 'processed',
querySent: true,
children: [],
items: [],
@@ -92,7 +90,6 @@ export function useLegendHelpers() {
layerName: 'TEST--chrisparentlayer1',
type: 'GeoJSON',
layerStatus: 'loaded',
- layerPhase: 'processed',
querySent: true,
children: [
{
@@ -102,7 +99,6 @@ export function useLegendHelpers() {
layerName: 'TEST--chrisparentchild1',
type: 'GeoJSON',
layerStatus: 'loaded',
- layerPhase: 'processed',
querySent: true,
children: [
{
@@ -112,7 +108,6 @@ export function useLegendHelpers() {
layerName: 'TEST--chris parent child2',
type: 'GeoJSON',
layerStatus: 'error',
- layerPhase: 'processed',
querySent: true,
children: [],
items: layerItems,
@@ -124,7 +119,6 @@ export function useLegendHelpers() {
layerName: 'TEST--chris parent child25555',
type: 'GeoJSON',
layerStatus: 'processing',
- layerPhase: 'processed',
querySent: true,
children: [],
items: layerItems,
@@ -136,7 +130,6 @@ export function useLegendHelpers() {
layerName: 'TEST--chris parent child3',
type: 'GeoJSON',
layerStatus: 'newInstance',
- layerPhase: 'processed',
querySent: true,
children: [],
items: layerItems,
@@ -151,7 +144,6 @@ export function useLegendHelpers() {
layerName: 'TEST--chirslyerss',
type: 'GeoJSON',
layerStatus: 'loaded',
- layerPhase: 'processed',
querySent: true,
children: [],
items: layerItems,
@@ -163,7 +155,6 @@ export function useLegendHelpers() {
layerName: 'TEST--chris-child32edd',
type: 'GeoJSON',
layerStatus: 'loaded',
- layerPhase: 'processed',
querySent: true,
children: [],
items: layerItems,
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 9a483d1f75c..3f754ed4361 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
@@ -72,7 +72,7 @@ export function AddNewLayer(): JSX.Element {
// get values from store
const mapId = useGeoViewMapId();
const layersList = useLayerLegendLayers();
- const { setDisplayState, setSelectedLayerPath } = useLayerStoreActions();
+ const { setDisplayState } = useLayerStoreActions();
const isMultiple = () => hasMetadata && (layerType === ESRI_DYNAMIC || layerType === WFS || layerType === WMS || layerType === GEOJSON);
@@ -859,19 +859,13 @@ export function AddNewLayer(): JSX.Element {
}
setIsLoading(false);
let message = '';
- switch (geoviewLayerInstance?.layerPhase) {
- case 'loading':
- message = api.utilities.replaceParams([layerName], t('layers.layerAddedAndLoading'));
- break;
- case 'error':
- message = api.utilities.replaceParams([layerName], t('layers.layerAddedWithError'));
- break;
- default:
- setSelectedLayerPath(`${geoviewLayerInstance?.geoviewLayerId}/${geoviewLayerInstance?.geoviewLayerId}`);
- message = api.utilities.replaceParams([layerName], t('layers.layerAdded'));
- break;
- }
+ if (geoviewLayerInstance?.allLayerStatusAreGreaterThanOrEqualTo('error'))
+ message = api.utilities.replaceParams([layerName], t('layers.layerAddedWithError'));
+ else if (geoviewLayerInstance?.allLayerStatusAreGreaterThanOrEqualTo('loaded'))
+ message = api.utilities.replaceParams([layerName], t('layers.layerAdded'));
+ else message = api.utilities.replaceParams([layerName], t('layers.layerAddedAndLoading'));
api.utilities.showMessage(mapId, message, false);
+
setDisplayState('view');
MapEventProcessor.setLayerZIndices(mapId);
};
diff --git a/packages/geoview-core/src/core/components/layers/types.ts b/packages/geoview-core/src/core/components/layers/types.ts
index 0b1078d1055..1bb7cca5ff5 100644
--- a/packages/geoview-core/src/core/components/layers/types.ts
+++ b/packages/geoview-core/src/core/components/layers/types.ts
@@ -29,12 +29,10 @@ export interface TypeLegendLayer {
layerId: string;
layerPath: string;
layerAttribution?: string[];
- metadataAccessPath?: string;
layerName: string;
type?: TypeGeoviewLayerType;
styleConfig?: TypeStyleConfig | null;
layerStatus?: TypeLayerStatus;
- layerPhase?: string;
querySent?: boolean;
canToggle?: boolean; // can sublayer visibility be toggled
diff --git a/packages/geoview-core/src/core/types/material-ui.d.ts b/packages/geoview-core/src/core/types/material-ui.d.ts
index 4168641edbc..942876af783 100644
--- a/packages/geoview-core/src/core/types/material-ui.d.ts
+++ b/packages/geoview-core/src/core/types/material-ui.d.ts
@@ -13,6 +13,7 @@ type Shape = {
declare module '@mui/material/styles' {
// allow configuration using `createTheme`
interface ThemeOptions {
+ geoViewColor?: IGeoViewColors;
shape?: Shape;
overrides?: {
button: {
diff --git a/packages/geoview-core/src/geo/layer/geoview-layers/abstract-geoview-layers.ts b/packages/geoview-core/src/geo/layer/geoview-layers/abstract-geoview-layers.ts
index 4b4fbd25768..2b4bfae02e2 100644
--- a/packages/geoview-core/src/geo/layer/geoview-layers/abstract-geoview-layers.ts
+++ b/packages/geoview-core/src/geo/layer/geoview-layers/abstract-geoview-layers.ts
@@ -280,9 +280,6 @@ export abstract class AbstractGeoViewLayer {
/** The unique identifier of the map on which the GeoView layer will be drawn. */
mapId: string;
- /** Flag used to indicate the layer's phase */
- layerPhase = '';
-
/** The type of GeoView layer that is instantiated. */
type: TypeGeoviewLayerType;
@@ -311,7 +308,7 @@ export abstract class AbstractGeoViewLayer {
initialSettings?: TypeLayerInitialSettings;
/** layers of listOfLayerEntryConfig that did not load. */
- layerLoadError: { layer: string; consoleMessage: string }[] = [];
+ layerLoadError: { layer: string; loggerMessage: string }[] = [];
/**
* The structure of the vector or raster layers to be displayed for this GeoView class. This property points to the root of the layer tree,
@@ -404,18 +401,14 @@ export abstract class AbstractGeoViewLayer {
*/
setLayerPhase(layerPhase: string, layerPath?: string) {
if (layerPath) {
- this.layerPhase = layerPhase;
const layerConfig = this.getLayerConfig(layerPath) as TypeBaseLayerEntryConfig;
layerConfig.layerPhase = layerPhase;
- api.event.emit(LayerSetPayload.createLayerSetChangeLayerPhasePayload(this.mapId, layerPath, layerPhase));
} else {
- this.layerPhase = layerPhase;
const changeAllSublayerPhase = (listOfLayerEntryConfig = this.listOfLayerEntryConfig) => {
listOfLayerEntryConfig.forEach((subLayerConfig) => {
if (layerEntryIsGroupLayer(subLayerConfig)) changeAllSublayerPhase(subLayerConfig.listOfLayerEntryConfig);
else {
(subLayerConfig as TypeBaseLayerEntryConfig).layerPhase = layerPhase;
- api.event.emit(LayerSetPayload.createLayerSetChangeLayerPhasePayload(this.mapId, subLayerConfig.layerPath, layerPhase));
}
});
};
@@ -423,37 +416,24 @@ export abstract class AbstractGeoViewLayer {
}
}
- /** ***************************************************************************************************************************
- * Change the layer status property and emit an event to update existing layer sets.
- *
- * @param {TypeLayerStatus} layerStatus The value to assign to the layer status property.
- * @param {string} layerPath The layer path to the layer's configuration affected by the change.
- */
- setLayerStatus(layerStatus: TypeLayerStatus, layerPath?: string) {
- layerPath = layerPath || this.layerPathAssociatedToTheGeoviewLayer;
- const layerConfig = this.getLayerConfig(layerPath) as TypeBaseLayerEntryConfig;
- layerConfig.layerStatus = layerStatus;
- api.event.emit(LayerSetPayload.createLayerSetChangeLayerStatusPayload(this.mapId, layerPath, layerStatus!));
- if (layerStatus === 'processed') this.setLayerPhase('processed', layerPath);
- }
-
/** ***************************************************************************************************************************
* Process recursively the list of layer entries to see if all of them are processed.
*
- * @param {TypeLayerStatus[]} listOfStatusFlag The list of layer's configuration
+ * @param {TypeLayerStatus} layerStatus The layer status to compare with the internal value of the config.
* @param {TypeListOfLayerEntryConfig} listOfLayerEntryConfig The list of layer's configuration
* (default: this.listOfLayerEntryConfig).
*
- * @returns {boolean} true when all layers are processed.
+ * @returns {boolean} true when all layers are greater than or equal to the layerStatus parameter.
*/
- allLayerStatusAreIn(
- listOfStatusFlag: TypeLayerStatus[],
+ allLayerStatusAreGreaterThanOrEqualTo(
+ layerStatus: TypeLayerStatus,
listOfLayerEntryConfig: TypeListOfLayerEntryConfig = this.listOfLayerEntryConfig
): boolean {
- // Try to find an unprocessed layer. If you can, return false
+ // Try to find a layer that is not greater than or equal to the layerStatus parameter. If you can, return false
return !listOfLayerEntryConfig.find((layerConfig: TypeLayerEntryConfig) => {
- if (layerEntryIsGroupLayer(layerConfig)) return !this.allLayerStatusAreIn(listOfStatusFlag, layerConfig.listOfLayerEntryConfig);
- return !listOfStatusFlag.includes((layerConfig as TypeBaseLayerEntryConfig).layerStatus || 'newInstance');
+ if (layerEntryIsGroupLayer(layerConfig))
+ return !this.allLayerStatusAreGreaterThanOrEqualTo(layerStatus, layerConfig.listOfLayerEntryConfig);
+ return !layerConfig.IsGreaterThanOrEqualTo(layerStatus || 'newInstance');
});
}
@@ -484,7 +464,7 @@ export abstract class AbstractGeoViewLayer {
if (layer.isRegistered(layerConfig)) {
this.layerLoadError.push({
layer: layerConfig.layerPath,
- consoleMessage: `Duplicate layerPath (mapId: ${this.mapId}, layerPath: ${layerConfig.layerPath})`,
+ loggerMessage: `Duplicate layerPath (mapId: ${this.mapId}, layerPath: ${layerConfig.layerPath})`,
});
// Duplicat layer can't be kept because it has the same layer path than the first encontered layer.
delete listOfLayerEntryConfig[i];
@@ -593,9 +573,12 @@ export abstract class AbstractGeoViewLayer {
if (metadataUrl) {
try {
const metadataString = await getXMLHttpRequest(`${metadataUrl}?f=json`);
- this.metadata = toJsonObject(JSON.parse(metadataString));
- const { copyrightText } = this.metadata;
- if (copyrightText) this.attributions.push(copyrightText as string);
+ if (metadataString === '{}') this.metadata = null;
+ else {
+ this.metadata = toJsonObject(JSON.parse(metadataString));
+ const { copyrightText } = this.metadata;
+ if (copyrightText) this.attributions.push(copyrightText as string);
+ }
} catch (error) {
// Log
logger.logError(error);
@@ -633,7 +616,11 @@ export abstract class AbstractGeoViewLayer {
}
const arrayOfLayerConfigs = await Promise.all(promisedAllLayerDone);
arrayOfLayerConfigs.forEach((layerConfig) => {
- if (layerConfig.layerStatus !== 'error') this.setLayerStatus('processed', layerConfig.layerPath);
+ if (layerConfig.layerStatus === 'error') {
+ const message = `Error while loading layer path "${layerConfig.layerPath})" on map "${this.mapId}"`;
+ this.layerLoadError.push({ layer: layerConfig.layerPath, loggerMessage: message });
+ throw new Error(message);
+ }
});
} catch (error) {
// Log
@@ -666,13 +653,20 @@ export abstract class AbstractGeoViewLayer {
* This method is used to process the layer's metadata. It will fill the empty outfields and aliasFields properties of the
* layer's configuration when applicable.
*
+ * ! This routine must imperatively ends with layerConfig.layerStatus = 'processed' or 'error' if an error happens.
+ *
* @param {TypeLayerEntryConfig} layerConfig The layer entry configuration to process.
*
* @returns {Promise} A promise that the vector layer configuration has its metadata processed.
*/
protected processLayerMetadata(layerConfig: TypeLayerEntryConfig): Promise {
if (!layerConfig.source) layerConfig.source = {};
- if (!layerConfig.source.featureInfo) layerConfig.source.featureInfo = { queryable: true };
+ if (!layerConfig.source.featureInfo) layerConfig.source.featureInfo = { queryable: false };
+ // When we get here, we know that the metadata (if the service provide some) are processed.
+ // We need to signal to the layer sets that the 'processed' phase is done. Be aware that the
+ // layerStatus setter is doing a lot of things behind the scene.
+ layerConfig.layerStatus = 'processed';
+
return Promise.resolve(layerConfig);
}
@@ -705,7 +699,7 @@ export abstract class AbstractGeoViewLayer {
}
this.layerLoadError.push({
layer: listOfLayerEntryConfig[0].layerPath,
- consoleMessage: `Unable to create group layer ${listOfLayerEntryConfig[0].layerPath} on map ${this.mapId}`,
+ loggerMessage: `Unable to create group layer ${listOfLayerEntryConfig[0].layerPath} on map ${this.mapId}`,
});
return null;
}
@@ -720,9 +714,9 @@ export abstract class AbstractGeoViewLayer {
}
this.layerLoadError.push({
layer: listOfLayerEntryConfig[0].layerPath,
- consoleMessage: `Unable to create layer ${listOfLayerEntryConfig[0].layerPath} on map ${this.mapId}`,
+ loggerMessage: `Unable to create layer ${listOfLayerEntryConfig[0].layerPath} on map ${this.mapId}`,
});
- this.setLayerStatus('error', layerPath);
+ this.getLayerConfig(layerPath)!.layerStatus = 'error';
return null;
}
@@ -758,11 +752,11 @@ export abstract class AbstractGeoViewLayer {
} else {
this.layerLoadError.push({
layer: listOfLayerEntryConfig[i].layerPath,
- consoleMessage: `Unable to create ${layerEntryIsGroupLayer(listOfLayerEntryConfig[i]) ? 'group' : ''} layer ${
+ loggerMessage: `Unable to create ${layerEntryIsGroupLayer(listOfLayerEntryConfig[i]) ? 'group' : ''} layer ${
listOfLayerEntryConfig[i].layerPath
} on map ${this.mapId}`,
});
- this.setLayerStatus('error', layerPath);
+ this.getLayerConfig(layerPath)!.layerStatus = 'error';
}
});
@@ -781,7 +775,12 @@ export abstract class AbstractGeoViewLayer {
*
* @returns {Promise} The GeoView layer that has been created.
*/
- protected abstract processOneLayerEntry(layerConfig: TypeBaseLayerEntryConfig): Promise;
+ protected processOneLayerEntry(layerConfig: TypeBaseLayerEntryConfig): Promise {
+ // ! IMPORTANT: The processOneLayerEntry method of all the children must call this method to ensure that the flow of
+ // ! layerStatus values is correctly sequenced.
+ layerConfig.layerStatus = 'loading';
+ return Promise.resolve(null);
+ }
/** ***************************************************************************************************************************
* Return feature information for the layer specified.
@@ -1581,12 +1580,12 @@ export abstract class AbstractGeoViewLayer {
if (layerEntryIsGroupLayer(layerConfig)) this.setAllLayerStatusTo(newStatus, layerConfig.listOfLayerEntryConfig, errorMessage);
else {
if (layerConfig.layerStatus === 'error') return;
- const { layerPath } = layerConfig;
- this.setLayerStatus(newStatus, layerPath);
+ layerConfig.layerStatus = newStatus;
if (newStatus === 'error') {
+ const { layerPath } = layerConfig;
this.layerLoadError.push({
layer: layerPath,
- consoleMessage: `${errorMessage} for layer ${layerPath} of map ${this.mapId}`,
+ loggerMessage: `${errorMessage} for layer ${layerPath} of map ${this.mapId}`,
});
}
}
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 c6344a66042..5d81084ad96 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
@@ -1,4 +1,4 @@
-/* eslint-disable @typescript-eslint/no-unused-vars, no-param-reassign, no-console */
+/* eslint-disable @typescript-eslint/no-unused-vars, no-param-reassign */
import axios from 'axios';
import { Extent } from 'ol/extent';
@@ -73,27 +73,28 @@ export function commonValidateListOfLayerEntryConfig(this: EsriDynamic | EsriFea
listOfLayerEntryConfig.forEach((layerConfig: TypeLayerEntryConfig, i) => {
const { layerPath } = layerConfig;
if (layerConfig.layerStatus === 'error') return;
+
if (layerEntryIsGroupLayer(layerConfig)) {
this.validateListOfLayerEntryConfig(layerConfig.listOfLayerEntryConfig!);
if (!(layerConfig as TypeLayerGroupEntryConfig).listOfLayerEntryConfig.length) {
this.layerLoadError.push({
layer: layerPath,
- consoleMessage: `Empty layer group (mapId: ${this.mapId}, layerPath: ${layerPath})`,
+ loggerMessage: `Empty layer group (mapId: ${this.mapId}, layerPath: ${layerPath})`,
});
- this.setLayerStatus('error', layerPath);
+ layerConfig.layerStatus = 'error';
return;
}
}
- this.setLayerStatus('processing', layerPath);
+ layerConfig.layerStatus = 'processing';
let esriIndex = Number(layerConfig.layerId);
if (Number.isNaN(esriIndex)) {
this.layerLoadError.push({
layer: layerPath,
- consoleMessage: `ESRI layerId must be a number (mapId: ${this.mapId}, layerPath: ${layerPath})`,
+ loggerMessage: `ESRI layerId must be a number (mapId: ${this.mapId}, layerPath: ${layerPath})`,
});
- this.setLayerStatus('error', layerPath);
+ layerConfig.layerStatus = 'error';
return;
}
@@ -104,9 +105,9 @@ export function commonValidateListOfLayerEntryConfig(this: EsriDynamic | EsriFea
if (esriIndex === -1) {
this.layerLoadError.push({
layer: layerPath,
- consoleMessage: `ESRI layerId not found (mapId: ${this.mapId}, layerPath: ${layerPath})`,
+ loggerMessage: `ESRI layerId not found (mapId: ${this.mapId}, layerPath: ${layerPath})`,
});
- this.setLayerStatus('error', layerPath);
+ layerConfig.layerStatus = 'error';
return;
}
@@ -148,7 +149,7 @@ export function commonValidateListOfLayerEntryConfig(this: EsriDynamic | EsriFea
}
if (this.esriChildHasDetectedAnError(layerConfig, esriIndex)) {
- this.setLayerStatus('error', layerPath);
+ layerConfig.layerStatus = 'error';
return;
}
@@ -331,6 +332,8 @@ export function commonProcessInitialSettings(
* This method is used to process the layer's metadata. It will fill the empty fields of the layer's configuration (renderer,
* initial settings, fields and aliases).
*
+ * ! This routine must imperatively ends with layerConfig.layerStatus = 'processed' or 'error' if an error happens.
+ *
* @param {EsriDynamic | EsriFeature} this The ESRI layer instance pointer.
* @param {TypeLayerEntryConfig} layerConfig The layer entry configuration to process.
*
@@ -351,7 +354,7 @@ export async function commonProcessLayerMetadata(
const { data } = await axios.get(`${queryUrl}?f=pjson`);
// layers must have a fields attribute except if it is an metadata layer group.
if (!data?.fields && !(layerConfig as TypeLayerGroupEntryConfig).isMetadataLayerGroup && layerConfig.schemaTag !== 'esriImage') {
- this.setLayerStatus('error', layerPath);
+ layerConfig.layerStatus = 'error';
if (data?.error) throw new Error(`Error code = ${data.error.code}, ${data.error.message}`);
else throw new Error(`Despite a return code of 200, no fields was returned with this query (${queryUrl}?f=pjson)`);
}
@@ -377,9 +380,14 @@ export async function commonProcessLayerMetadata(
);
commonProcessTemporalDimension.call(this, data.timeInfo as TypeJsonObject, layerConfig);
}
+
+ // When we get here, we know that the metadata (if the service provide some) are processed.
+ // We need to signal to the layer sets that the 'processed' phase is done. Be aware that the
+ // layerStatus setter is doing a lot of things behind the scene.
+ layerConfig.layerStatus = 'processed';
} catch (error) {
- this.setLayerStatus('error', layerPath);
- console.log(error);
+ layerConfig.layerStatus = 'error';
+ logger.logError('Error in commonProcessLayerMetadata', layerConfig, error);
}
}
return layerConfig;
diff --git a/packages/geoview-core/src/geo/layer/geoview-layers/raster/esri-dynamic.ts b/packages/geoview-core/src/geo/layer/geoview-layers/raster/esri-dynamic.ts
index 2443de19b1e..e079aa6b242 100644
--- a/packages/geoview-core/src/geo/layer/geoview-layers/raster/esri-dynamic.ts
+++ b/packages/geoview-core/src/geo/layer/geoview-layers/raster/esri-dynamic.ts
@@ -145,7 +145,7 @@ export class EsriDynamic extends AbstractGeoViewRaster {
if (!this.metadata!.supportsDynamicLayers) {
this.layerLoadError.push({
layer: layerConfig.layerPath,
- consoleMessage: `Layer ${layerConfig.layerPath} of map ${this.mapId} does not support dynamic layers.`,
+ loggerMessage: `Layer ${layerConfig.layerPath} of map ${this.mapId} does not support dynamic layers.`,
});
return true;
}
@@ -247,6 +247,9 @@ export class EsriDynamic extends AbstractGeoViewRaster {
* @returns {TypeBaseRasterLayer} The GeoView raster layer that has been created.
*/
protected processOneLayerEntry(layerConfig: TypeEsriDynamicLayerEntryConfig): Promise {
+ // ! IMPORTANT: The processOneLayerEntry method must call the corresponding method of its parent to ensure that the flow of
+ // ! layerStatus values is correctly sequenced.
+ super.processOneLayerEntry(layerConfig);
const { layerPath } = layerConfig;
this.setLayerPhase('processOneLayerEntry', layerPath);
const sourceOptions: SourceOptions = {};
diff --git a/packages/geoview-core/src/geo/layer/geoview-layers/raster/esri-image.ts b/packages/geoview-core/src/geo/layer/geoview-layers/raster/esri-image.ts
index 28c8925b277..16285c672c2 100644
--- a/packages/geoview-core/src/geo/layer/geoview-layers/raster/esri-image.ts
+++ b/packages/geoview-core/src/geo/layer/geoview-layers/raster/esri-image.ts
@@ -212,14 +212,11 @@ export class EsriImage extends AbstractGeoViewRaster {
if (!layerConfig.listOfLayerEntryConfig.length) {
this.layerLoadError.push({
layer: layerPath,
- consoleMessage: `Empty layer group (mapId: ${this.mapId}, layerPath: ${layerPath})`,
+ loggerMessage: `Empty layer group (mapId: ${this.mapId}, layerPath: ${layerPath})`,
});
- this.setLayerStatus('error', layerPath);
- return;
+ layerConfig.layerStatus = 'error';
}
}
-
- this.setLayerStatus('loading', layerPath);
});
}
@@ -314,6 +311,9 @@ export class EsriImage extends AbstractGeoViewRaster {
* @returns {TypeBaseRasterLayer} The GeoView raster layer that has been created.
*/
protected processOneLayerEntry(layerConfig: TypeEsriImageLayerEntryConfig): Promise {
+ // ! IMPORTANT: The processOneLayerEntry method must call the corresponding method of its parent to ensure that the flow of
+ // ! layerStatus values is correctly sequenced.
+ super.processOneLayerEntry(layerConfig);
const { layerPath } = layerConfig;
this.setLayerPhase('processOneLayerEntry', layerPath);
const sourceOptions: SourceOptions = {};
diff --git a/packages/geoview-core/src/geo/layer/geoview-layers/raster/image-static.ts b/packages/geoview-core/src/geo/layer/geoview-layers/raster/image-static.ts
index d668c2a780b..cde94ecff59 100644
--- a/packages/geoview-core/src/geo/layer/geoview-layers/raster/image-static.ts
+++ b/packages/geoview-core/src/geo/layer/geoview-layers/raster/image-static.ts
@@ -204,14 +204,14 @@ export class ImageStatic extends AbstractGeoViewRaster {
if (!layerConfig.listOfLayerEntryConfig.length) {
this.layerLoadError.push({
layer: layerPath,
- consoleMessage: `Empty layer group (mapId: ${this.mapId}, layerPath: ${layerPath})`,
+ loggerMessage: `Empty layer group (mapId: ${this.mapId}, layerPath: ${layerPath})`,
});
- this.setLayerStatus('error', layerPath);
+ layerConfig.layerStatus = 'error';
return;
}
}
- this.setLayerStatus('processing', layerPath);
+ layerConfig.layerStatus = 'processing';
// When no metadata are provided, all layers are considered valid.
if (!this.metadata) return;
@@ -224,9 +224,9 @@ export class ImageStatic extends AbstractGeoViewRaster {
if (!foundEntry) {
this.layerLoadError.push({
layer: layerPath,
- consoleMessage: `GeoJSON layer not found (mapId: ${this.mapId}, layerPath: ${layerPath})`,
+ loggerMessage: `GeoJSON layer not found (mapId: ${this.mapId}, layerPath: ${layerPath})`,
});
- this.setLayerStatus('error', layerPath);
+ layerConfig.layerStatus = 'error';
return;
}
return;
@@ -246,6 +246,7 @@ export class ImageStatic extends AbstractGeoViewRaster {
* @returns {TypeBaseRasterLayer} The GeoView raster layer that has been created.
*/
processOneLayerEntry(layerConfig: TypeImageStaticLayerEntryConfig): Promise {
+ super.processOneLayerEntry(layerConfig);
const { layerPath } = layerConfig;
this.setLayerPhase('processOneLayerEntry', layerPath);
@@ -271,8 +272,8 @@ export class ImageStatic extends AbstractGeoViewRaster {
if (layerConfig.initialSettings?.maxZoom !== undefined) staticImageOptions.maxZoom = layerConfig.initialSettings?.maxZoom;
if (layerConfig.initialSettings?.minZoom !== undefined) staticImageOptions.minZoom = layerConfig.initialSettings?.minZoom;
if (layerConfig.initialSettings?.opacity !== undefined) staticImageOptions.opacity = layerConfig.initialSettings?.opacity;
- if (layerConfig.initialSettings?.visible !== undefined)
- staticImageOptions.visible = layerConfig.initialSettings?.visible === 'yes' || layerConfig.initialSettings?.visible === 'always';
+ // ! IMPORTANT: The initialSettings.visible flag must be set in the layerConfig.loadedFunction otherwise the layer will stall
+ // ! in the 'loading' state if the flag value is 'no'.
layerConfig.olLayerAndLoadEndListeners = {
olLayer: new ImageLayer(staticImageOptions),
diff --git a/packages/geoview-core/src/geo/layer/geoview-layers/raster/vector-tiles.ts b/packages/geoview-core/src/geo/layer/geoview-layers/raster/vector-tiles.ts
index 87179427ff8..5025e76eab3 100644
--- a/packages/geoview-core/src/geo/layer/geoview-layers/raster/vector-tiles.ts
+++ b/packages/geoview-core/src/geo/layer/geoview-layers/raster/vector-tiles.ts
@@ -32,6 +32,7 @@ import { api } from '@/app';
import { Layer } from '../../layer';
import { LayerSetPayload } from '@/api/events/payloads';
import { MapEventProcessor } from '@/api/event-processors/event-processor-children/map-event-processor';
+import { logger } from '@/core/utils/logger';
// TODO: Implement method to validate Vector Tiles service
// TODO: Add more customization (minZoom, maxZoom, TMS)
@@ -157,14 +158,14 @@ export class VectorTiles extends AbstractGeoViewRaster {
if (!layerConfig?.listOfLayerEntryConfig?.length) {
this.layerLoadError.push({
layer: layerPath,
- consoleMessage: `Empty layer group (mapId: ${this.mapId}, layerPath: ${layerPath})`,
+ loggerMessage: `Empty layer group (mapId: ${this.mapId}, layerPath: ${layerPath})`,
});
- this.setLayerStatus('error', layerPath);
+ layerConfig.layerStatus = 'error';
return;
}
}
- this.setLayerStatus('processing', layerPath);
+ layerConfig.layerStatus = 'processing';
});
}
@@ -176,97 +177,105 @@ export class VectorTiles extends AbstractGeoViewRaster {
* @returns {TypeBaseRasterLayer} The GeoView raster layer that has been created.
*/
protected processOneLayerEntry(layerConfig: TypeVectorTilesLayerEntryConfig): Promise {
- const promisedVectorLayer = new Promise((resolve) => {
- const { layerPath } = layerConfig;
- this.setLayerPhase('processOneLayerEntry', layerPath);
- const sourceOptions: SourceOptions = {
- url: getLocalizedValue(layerConfig.source.dataAccessPath, this.mapId),
- };
- if (
- this.metadata?.tileInfo?.spatialReference?.wkid &&
- MapEventProcessor.getMapState(this.mapId).currentProjection !== this.metadata.tileInfo.spatialReference.wkid
- ) {
- showError(this.mapId, `Error: vector tile layer (${layerConfig.layerId}) projection does not match map projection`);
- // eslint-disable-next-line no-console
- console.log(`Error: vector tile layer (${layerConfig.layerId}) projection does not match map projection`);
- this.setLayerStatus('error', layerPath);
- resolve(null);
- } else if (layerConfig.source.projection) sourceOptions.projection = `EPSG:${layerConfig.source.projection}`;
- if (layerConfig.source.tileGrid) {
- const tileGridOptions: TileGridOptions = {
- origin: layerConfig.source.tileGrid?.origin,
- resolutions: layerConfig.source.tileGrid?.resolutions as number[],
- };
- if (layerConfig.source.tileGrid?.tileSize) tileGridOptions.tileSize = layerConfig.source.tileGrid?.tileSize;
- if (layerConfig.source.tileGrid?.extent) tileGridOptions.extent = layerConfig.source.tileGrid?.extent;
- sourceOptions.tileGrid = new TileGrid(tileGridOptions);
- }
+ // ! IMPORTANT: The processOneLayerEntry method must call the corresponding method of its parent to ensure that the flow of
+ // ! layerStatus values is correctly sequenced.
+ super.processOneLayerEntry(layerConfig);
+ const { layerPath } = layerConfig;
+ this.setLayerPhase('processOneLayerEntry', layerPath);
+ const sourceOptions: SourceOptions = {
+ url: getLocalizedValue(layerConfig.source.dataAccessPath, this.mapId),
+ };
+
+ if (
+ this.metadata?.tileInfo?.spatialReference?.wkid &&
+ MapEventProcessor.getMapState(this.mapId).currentProjection !== this.metadata.tileInfo.spatialReference.wkid
+ ) {
+ showError(this.mapId, `Error: vector tile layer (${layerConfig.layerId}) projection does not match map projection`);
+ logger.logError(`Error: vector tile layer (${layerConfig.layerId}) projection does not match map projection`);
+ layerConfig.layerStatus = 'error';
+ return Promise.resolve(null);
+ }
+
+ if (layerConfig.source.projection) sourceOptions.projection = `EPSG:${layerConfig.source.projection}`;
- // TODO: The following line cause an error now.
- // sourceOptions.format = new MVT();
- sourceOptions.projection = `EPSG:${MapEventProcessor.getMapState(this.mapId).currentProjection}`;
- sourceOptions.tileGrid = new TileGrid(layerConfig.source!.tileGrid!);
- const tileLayerOptions: TileOptions = { source: new VectorTileSource(sourceOptions) };
- // layerConfig.initialSettings cannot be undefined because config-validation set it to {} if it is undefined.
- if (layerConfig.initialSettings?.className !== undefined) tileLayerOptions.className = layerConfig.initialSettings?.className;
- if (layerConfig.initialSettings?.extent !== undefined) tileLayerOptions.extent = layerConfig.initialSettings?.extent;
- if (layerConfig.initialSettings?.maxZoom !== undefined) tileLayerOptions.maxZoom = layerConfig.initialSettings?.maxZoom;
- if (layerConfig.initialSettings?.minZoom !== undefined) tileLayerOptions.minZoom = layerConfig.initialSettings?.minZoom;
- if (layerConfig.initialSettings?.opacity !== undefined) tileLayerOptions.opacity = layerConfig.initialSettings?.opacity;
- if (layerConfig.initialSettings?.visible !== undefined) tileLayerOptions.visible = layerConfig.initialSettings?.visible !== 'no';
-
- // TODO remove after demoing
- // ! Humm! Have we done the demo?
- const declutter = this.mapId !== 'LYR2';
- layerConfig.olLayerAndLoadEndListeners = {
- olLayer: new VectorTileLayer({ ...tileLayerOptions, declutter }),
- loadEndListenerType: 'tile',
+ if (layerConfig.source.tileGrid) {
+ const tileGridOptions: TileGridOptions = {
+ origin: layerConfig.source.tileGrid?.origin,
+ resolutions: layerConfig.source.tileGrid?.resolutions as number[],
};
- layerConfig.geoviewLayerInstance = this;
- if (this.metadata?.defaultStyles)
- applyStyle(
- layerConfig.olLayer as VectorTileLayer,
- `${getLocalizedValue(this.metadataAccessPath, this.mapId)}${this.metadata.defaultStyles}/root.json`
- );
+ if (layerConfig.source.tileGrid?.tileSize) tileGridOptions.tileSize = layerConfig.source.tileGrid?.tileSize;
+ if (layerConfig.source.tileGrid?.extent) tileGridOptions.extent = layerConfig.source.tileGrid?.extent;
+ sourceOptions.tileGrid = new TileGrid(tileGridOptions);
+ }
- resolve(layerConfig.olLayer);
- });
- return promisedVectorLayer;
+ // TODO: The following line cause an error now.
+ // sourceOptions.format = new MVT();
+ sourceOptions.projection = `EPSG:${MapEventProcessor.getMapState(this.mapId).currentProjection}`;
+ sourceOptions.tileGrid = new TileGrid(layerConfig.source!.tileGrid!);
+ const tileLayerOptions: TileOptions = { source: new VectorTileSource(sourceOptions) };
+ // layerConfig.initialSettings cannot be undefined because config-validation set it to {} if it is undefined.
+ if (layerConfig.initialSettings?.className !== undefined) tileLayerOptions.className = layerConfig.initialSettings?.className;
+ if (layerConfig.initialSettings?.extent !== undefined) tileLayerOptions.extent = layerConfig.initialSettings?.extent;
+ if (layerConfig.initialSettings?.maxZoom !== undefined) tileLayerOptions.maxZoom = layerConfig.initialSettings?.maxZoom;
+ if (layerConfig.initialSettings?.minZoom !== undefined) tileLayerOptions.minZoom = layerConfig.initialSettings?.minZoom;
+ if (layerConfig.initialSettings?.opacity !== undefined) tileLayerOptions.opacity = layerConfig.initialSettings?.opacity;
+ // ! IMPORTANT: The initialSettings.visible flag must be set in the layerConfig.loadedFunction otherwise the layer will stall
+ // ! in the 'loading' state if the flag value is 'no'.
+
+ // TODO remove after demoing
+ // ! Humm! Have we done the demo?
+ const declutter = this.mapId !== 'LYR2';
+ layerConfig.olLayerAndLoadEndListeners = {
+ olLayer: new VectorTileLayer({ ...tileLayerOptions, declutter }),
+ loadEndListenerType: 'tile',
+ };
+
+ layerConfig.geoviewLayerInstance = this;
+ if (this.metadata?.defaultStyles)
+ applyStyle(
+ layerConfig.olLayer as VectorTileLayer,
+ `${getLocalizedValue(this.metadataAccessPath, this.mapId)}${this.metadata.defaultStyles}/root.json`
+ );
+
+ return Promise.resolve(layerConfig.olLayer);
}
/** ***************************************************************************************************************************
* This method is used to process the layer's metadata. It will fill the empty fields of the layer's configuration (renderer,
* initial settings, fields and aliases).
*
+ * ! This routine must imperatively ends with layerConfig.layerStatus = 'processed' or 'error' if an error happens.
+ *
* @param {TypeTileLayerEntryConfig} layerConfig The layer entry configuration to process.
*
* @returns {Promise} A promise that the vector layer configuration has its metadata processed.
*/
protected processLayerMetadata(layerConfig: TypeTileLayerEntryConfig): Promise {
- const promiseOfExecution = new Promise((resolve) => {
- if (!this.metadata) resolve(layerConfig);
- else {
- const { tileInfo } = this.metadata;
- const extent = this.metadata.fullExtent;
- const newTileGrid: TypeTileGrid = {
- extent: [extent.xmin as number, extent.ymin as number, extent.xmax as number, extent.ymax as number],
- origin: [tileInfo.origin.x as number, tileInfo.origin.y as number],
- resolutions: (tileInfo.lods as Array).map(({ resolution }) => resolution as number),
- tileSize: [tileInfo.rows as number, tileInfo.cols as number],
- };
- layerConfig.source!.tileGrid = newTileGrid;
-
- if (layerConfig.initialSettings?.extent)
- layerConfig.initialSettings.extent = api.projection.transformExtent(
- layerConfig.initialSettings.extent,
- 'EPSG:4326',
- `EPSG:${MapEventProcessor.getMapState(this.mapId).currentProjection}`
- );
-
- resolve(layerConfig);
- }
- });
- return promiseOfExecution;
+ if (this.metadata) {
+ const { tileInfo } = this.metadata;
+ const extent = this.metadata.fullExtent;
+ const newTileGrid: TypeTileGrid = {
+ extent: [extent.xmin as number, extent.ymin as number, extent.xmax as number, extent.ymax as number],
+ origin: [tileInfo.origin.x as number, tileInfo.origin.y as number],
+ resolutions: (tileInfo.lods as Array).map(({ resolution }) => resolution as number),
+ tileSize: [tileInfo.rows as number, tileInfo.cols as number],
+ };
+ layerConfig.source!.tileGrid = newTileGrid;
+
+ if (layerConfig.initialSettings?.extent)
+ layerConfig.initialSettings.extent = api.projection.transformExtent(
+ layerConfig.initialSettings.extent,
+ 'EPSG:4326',
+ `EPSG:${MapEventProcessor.getMapState(this.mapId).currentProjection}`
+ );
+ }
+
+ // When we get here, we know that the metadata (if the service provide some) are processed.
+ // We need to signal to the layer sets that the 'processed' phase is done. Be aware that the
+ // layerStatus setter is doing a lot of things behind the scene.
+ layerConfig.layerStatus = 'processed';
+
+ return Promise.resolve(layerConfig);
}
/** ***************************************************************************************************************************
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 da769d3ccb5..03e66e5d263 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
@@ -150,11 +150,11 @@ export class WMS extends AbstractGeoViewRaster {
try {
const arrayOfMetadata = await Promise.all(promisedArrayOfMetadata);
for (i = 0; i < arrayOfMetadata.length && !arrayOfMetadata[i]?.Capability; i++)
- this.setLayerStatus('error', layerConfigsToQuery[i].layerPath);
+ this.getLayerConfig(layerConfigsToQuery[i].layerPath)!.layerStatus = 'error';
this.metadata = i < arrayOfMetadata.length ? arrayOfMetadata[i] : null;
if (this.metadata) {
for (; i < arrayOfMetadata.length; i++) {
- if (!arrayOfMetadata[i]?.Capability) this.setLayerStatus('error', layerConfigsToQuery[i].layerPath);
+ if (!arrayOfMetadata[i]?.Capability) this.getLayerConfig(layerConfigsToQuery[i].layerPath)!.layerStatus = 'error';
else if (!this.getLayerMetadataEntry(layerConfigsToQuery[i].layerId!)) {
const metadataLayerPathToAdd = this.getMetadataLayerPath(
layerConfigsToQuery[i].layerId!,
@@ -378,23 +378,23 @@ export class WMS extends AbstractGeoViewRaster {
if (!layerConfig?.listOfLayerEntryConfig?.length) {
this.layerLoadError.push({
layer: layerPath,
- consoleMessage: `Empty layer group (mapId: ${this.mapId}, layerPath: ${layerPath})`,
+ loggerMessage: `Empty layer group (mapId: ${this.mapId}, layerPath: ${layerPath})`,
});
- this.setLayerStatus('error', layerPath);
+ layerConfig.layerStatus = 'error';
}
return;
}
if ((layerConfig as TypeBaseLayerEntryConfig).layerStatus !== 'error') {
- this.setLayerStatus('processing', layerPath);
+ layerConfig.layerStatus = 'processing';
const layerFound = this.getLayerMetadataEntry(layerConfig.layerId!);
if (!layerFound) {
this.layerLoadError.push({
layer: layerPath,
- consoleMessage: `Layer metadata not found (mapId: ${this.mapId}, layerPath: ${layerPath})`,
+ loggerMessage: `Layer metadata not found (mapId: ${this.mapId}, layerPath: ${layerPath})`,
});
- this.setLayerStatus('error', layerPath);
+ layerConfig.layerStatus = 'error';
return;
}
@@ -439,7 +439,6 @@ export class WMS extends AbstractGeoViewRaster {
if (this.registerToLayerSetListenerFunctions[layerPath]) this.unregisterFromLayerSets(layerConfig);
const switchToGroupLayer = Cast(layerConfig);
- delete layerConfig.layerStatus;
switchToGroupLayer.entryType = 'group';
switchToGroupLayer.layerName = {
en: layer.Title as string,
@@ -485,130 +484,133 @@ export class WMS extends AbstractGeoViewRaster {
* @returns {TypeBaseRasterLayer | null} The GeoView raster layer that has been created.
*/
protected processOneLayerEntry(layerConfig: TypeBaseLayerEntryConfig): Promise {
+ // ! IMPORTANT: The processOneLayerEntry method must call the corresponding method of its parent to ensure that the flow of
+ // ! layerStatus values is correctly sequenced.
+ super.processOneLayerEntry(layerConfig);
// Log
logger.logTraceCore('WMS - processOneLayerEntry', layerConfig.layerPath);
- const promisedVectorLayer = new Promise((resolve) => {
- const { layerPath } = layerConfig;
- this.setLayerPhase('processOneLayerEntry', layerPath);
- if (geoviewEntryIsWMS(layerConfig)) {
- const layerCapabilities = this.getLayerMetadataEntry(layerConfig.layerId);
- if (layerCapabilities) {
- const dataAccessPath = getLocalizedValue(layerConfig.source.dataAccessPath, this.mapId)!;
-
- let styleToUse = '';
- if (Array.isArray(layerConfig.source?.style) && layerConfig.source?.style) {
- styleToUse = layerConfig.source?.style[0];
- } else if (layerConfig.source.style) {
- styleToUse = layerConfig.source?.style as string;
- } else if (layerCapabilities.Style) {
- styleToUse = layerCapabilities.Style[0].Name as string;
- }
-
- if (Array.isArray(layerConfig.source?.style)) {
- this.WMSStyles = layerConfig.source.style;
- } else if ((layerCapabilities.Style.length as number) > 1) {
- this.WMSStyles = [];
- for (let i = 0; i < (layerCapabilities.Style.length as number); i++) {
- this.WMSStyles.push(layerCapabilities.Style[i].Name as string);
- }
- } else this.WMSStyles = [styleToUse];
-
- const sourceOptions: SourceOptions = {
- url: dataAccessPath.endsWith('?') ? dataAccessPath : `${dataAccessPath}?`,
- params: { LAYERS: layerConfig.layerId, STYLES: styleToUse },
- };
+ const { layerPath } = layerConfig;
+ this.setLayerPhase('processOneLayerEntry', layerPath);
+ if (geoviewEntryIsWMS(layerConfig)) {
+ const layerCapabilities = this.getLayerMetadataEntry(layerConfig.layerId);
+ if (layerCapabilities) {
+ const dataAccessPath = getLocalizedValue(layerConfig.source.dataAccessPath, this.mapId)!;
+
+ let styleToUse = '';
+ if (Array.isArray(layerConfig.source?.style) && layerConfig.source?.style) {
+ styleToUse = layerConfig.source?.style[0];
+ } else if (layerConfig.source.style) {
+ styleToUse = layerConfig.source?.style as string;
+ } else if (layerCapabilities.Style) {
+ styleToUse = layerCapabilities.Style[0].Name as string;
+ }
- sourceOptions.attributions = this.attributions;
- sourceOptions.serverType = layerConfig.source.serverType;
- if (layerConfig.source.crossOrigin) {
- sourceOptions.crossOrigin = layerConfig.source.crossOrigin;
- } else {
- sourceOptions.crossOrigin = 'Anonymous';
+ if (Array.isArray(layerConfig.source?.style)) {
+ this.WMSStyles = layerConfig.source.style;
+ } else if ((layerCapabilities.Style.length as number) > 1) {
+ this.WMSStyles = [];
+ for (let i = 0; i < (layerCapabilities.Style.length as number); i++) {
+ this.WMSStyles.push(layerCapabilities.Style[i].Name as string);
}
- if (layerConfig.source.projection) sourceOptions.projection = `EPSG:${layerConfig.source.projection}`;
+ } else this.WMSStyles = [styleToUse];
- const imageLayerOptions: ImageOptions = {
- source: new ImageWMS(sourceOptions),
- properties: { layerCapabilities, layerConfig },
- };
- // layerConfig.initialSettings cannot be undefined because config-validation set it to {} if it is undefined.
- if (layerConfig.initialSettings?.className !== undefined) imageLayerOptions.className = layerConfig.initialSettings?.className;
- if (layerConfig.initialSettings?.extent !== undefined) imageLayerOptions.extent = layerConfig.initialSettings?.extent;
- if (layerConfig.initialSettings?.maxZoom !== undefined) imageLayerOptions.maxZoom = layerConfig.initialSettings?.maxZoom;
- if (layerConfig.initialSettings?.minZoom !== undefined) imageLayerOptions.minZoom = layerConfig.initialSettings?.minZoom;
- if (layerConfig.initialSettings?.opacity !== undefined) imageLayerOptions.opacity = layerConfig.initialSettings?.opacity;
- if (layerConfig.initialSettings?.visible !== undefined)
- imageLayerOptions.visible = layerConfig.initialSettings?.visible === 'yes' || layerConfig.initialSettings?.visible === 'always';
-
- layerConfig.olLayerAndLoadEndListeners = {
- olLayer: new ImageLayer(imageLayerOptions),
- loadEndListenerType: 'image',
- };
- layerConfig.geoviewLayerInstance = this;
+ const sourceOptions: SourceOptions = {
+ url: dataAccessPath.endsWith('?') ? dataAccessPath : `${dataAccessPath}?`,
+ params: { LAYERS: layerConfig.layerId, STYLES: styleToUse },
+ };
- resolve(layerConfig.olLayer);
+ sourceOptions.attributions = this.attributions;
+ sourceOptions.serverType = layerConfig.source.serverType;
+ if (layerConfig.source.crossOrigin) {
+ sourceOptions.crossOrigin = layerConfig.source.crossOrigin;
} else {
- const message = replaceParams(
- [layerConfig.layerId, this.geoviewLayerId],
- getLocalizedMessage(this.mapId, 'validation.layer.notfound')
- );
- showError(this.mapId, message);
-
- resolve(null);
+ sourceOptions.crossOrigin = 'Anonymous';
}
- } else {
- logger.logError(`geoviewLayerType must be ${CONST_LAYER_TYPES.WMS}`);
- resolve(null);
+ if (layerConfig.source.projection) sourceOptions.projection = `EPSG:${layerConfig.source.projection}`;
+
+ const imageLayerOptions: ImageOptions = {
+ source: new ImageWMS(sourceOptions),
+ properties: { layerCapabilities, layerConfig },
+ };
+ // layerConfig.initialSettings cannot be undefined because config-validation set it to {} if it is undefined.
+ if (layerConfig.initialSettings?.className !== undefined) imageLayerOptions.className = layerConfig.initialSettings?.className;
+ if (layerConfig.initialSettings?.extent !== undefined) imageLayerOptions.extent = layerConfig.initialSettings?.extent;
+ if (layerConfig.initialSettings?.maxZoom !== undefined) imageLayerOptions.maxZoom = layerConfig.initialSettings?.maxZoom;
+ if (layerConfig.initialSettings?.minZoom !== undefined) imageLayerOptions.minZoom = layerConfig.initialSettings?.minZoom;
+ if (layerConfig.initialSettings?.opacity !== undefined) imageLayerOptions.opacity = layerConfig.initialSettings?.opacity;
+ // ! IMPORTANT: The initialSettings.visible flag must be set in the layerConfig.loadedFunction otherwise the layer will stall
+ // ! in the 'loading' state if the flag value is 'no'.
+
+ layerConfig.olLayerAndLoadEndListeners = {
+ olLayer: new ImageLayer(imageLayerOptions),
+ loadEndListenerType: 'image',
+ };
+ layerConfig.geoviewLayerInstance = this;
+
+ return Promise.resolve(layerConfig.olLayer);
}
- });
- return promisedVectorLayer;
+
+ const message = replaceParams(
+ [layerConfig.layerId, this.geoviewLayerId],
+ getLocalizedMessage(this.mapId, 'validation.layer.notfound')
+ );
+ showError(this.mapId, message);
+ return Promise.resolve(null);
+ }
+
+ logger.logError(`geoviewLayerType must be ${CONST_LAYER_TYPES.WMS}`);
+ return Promise.resolve(null);
}
/** ***************************************************************************************************************************
* This method is used to process the layer's metadata. It will fill the empty fields of the layer's configuration (renderer,
* initial settings, fields and aliases).
*
+ * ! This routine must imperatively ends with layerConfig.layerStatus = 'processed' or 'error' if an error happens.
+ *
* @param {TypeLayerEntryConfig} layerConfig The layer entry configuration to process.
*
* @returns {Promise} A promise that the layer configuration has its metadata processed.
*/
protected processLayerMetadata(layerConfig: TypeLayerEntryConfig): Promise {
- const promiseOfExecution = new Promise((resolve) => {
- if (geoviewEntryIsWMS(layerConfig)) {
- const layerCapabilities = this.getLayerMetadataEntry(layerConfig.layerId)!;
- this.layerMetadata[layerConfig.layerPath] = layerCapabilities;
- if (layerCapabilities) {
- if (layerCapabilities.Attribution) this.attributions.push(layerCapabilities.Attribution.Title as string);
- if (!layerConfig.source.featureInfo) layerConfig.source.featureInfo = { queryable: !!layerCapabilities.queryable };
- MapEventProcessor.setMapLayerQueryable(this.mapId, layerConfig.layerPath, layerConfig.source.featureInfo.queryable);
- // ! TODO: The solution implemented in the following lines is not right. scale and zoom are not the same things.
- // if (layerConfig.initialSettings?.minZoom === undefined && layerCapabilities.MinScaleDenominator !== undefined)
- // layerConfig.initialSettings.minZoom = layerCapabilities.MinScaleDenominator as number;
- // if (layerConfig.initialSettings?.maxZoom === undefined && layerCapabilities.MaxScaleDenominator !== undefined)
- // layerConfig.initialSettings.maxZoom = layerCapabilities.MaxScaleDenominator as number;
- if (layerConfig.initialSettings?.extent)
- layerConfig.initialSettings.extent = api.projection.transformExtent(
- layerConfig.initialSettings.extent,
- 'EPSG:4326',
- `EPSG:${MapEventProcessor.getMapState(this.mapId).currentProjection}`
- );
-
- if (!layerConfig.initialSettings?.bounds && layerCapabilities.EX_GeographicBoundingBox) {
- layerConfig.initialSettings!.bounds = layerCapabilities.EX_GeographicBoundingBox as Extent;
- }
+ if (geoviewEntryIsWMS(layerConfig)) {
+ const layerCapabilities = this.getLayerMetadataEntry(layerConfig.layerId)!;
+ this.layerMetadata[layerConfig.layerPath] = layerCapabilities;
+ if (layerCapabilities) {
+ if (layerCapabilities.Attribution) this.attributions.push(layerCapabilities.Attribution.Title as string);
+ if (!layerConfig.source.featureInfo) layerConfig.source.featureInfo = { queryable: !!layerCapabilities.queryable };
+ MapEventProcessor.setMapLayerQueryable(this.mapId, layerConfig.layerPath, layerConfig.source.featureInfo.queryable);
+ // ! TODO: The solution implemented in the following lines is not right. scale and zoom are not the same things.
+ // if (layerConfig.initialSettings?.minZoom === undefined && layerCapabilities.MinScaleDenominator !== undefined)
+ // layerConfig.initialSettings.minZoom = layerCapabilities.MinScaleDenominator as number;
+ // if (layerConfig.initialSettings?.maxZoom === undefined && layerCapabilities.MaxScaleDenominator !== undefined)
+ // layerConfig.initialSettings.maxZoom = layerCapabilities.MaxScaleDenominator as number;
+ if (layerConfig.initialSettings?.extent)
+ layerConfig.initialSettings.extent = api.projection.transformExtent(
+ layerConfig.initialSettings.extent,
+ 'EPSG:4326',
+ `EPSG:${MapEventProcessor.getMapState(this.mapId).currentProjection}`
+ );
- if (layerCapabilities.Dimension) {
- const temporalDimension: TypeJsonObject | undefined = (layerCapabilities.Dimension as TypeJsonArray).find(
- (dimension) => dimension.name === 'time'
- );
- if (temporalDimension) this.processTemporalDimension(temporalDimension, layerConfig);
- }
+ if (!layerConfig.initialSettings?.bounds && layerCapabilities.EX_GeographicBoundingBox) {
+ layerConfig.initialSettings!.bounds = layerCapabilities.EX_GeographicBoundingBox as Extent;
+ }
+
+ if (layerCapabilities.Dimension) {
+ const temporalDimension: TypeJsonObject | undefined = (layerCapabilities.Dimension as TypeJsonArray).find(
+ (dimension) => dimension.name === 'time'
+ );
+ if (temporalDimension) this.processTemporalDimension(temporalDimension, layerConfig);
}
}
- resolve(layerConfig);
- });
- return promiseOfExecution;
+ }
+ // When we get here, we know that the metadata (if the service provide some) are processed.
+ // We need to signal to the layer sets that the 'processed' phase is done. Be aware that the
+ // layerStatus setter is doing a lot of things behind the scene.
+ layerConfig.layerStatus = 'processed';
+
+ return Promise.resolve(layerConfig);
}
/** ***************************************************************************************************************************
diff --git a/packages/geoview-core/src/geo/layer/geoview-layers/raster/xyz-tiles.ts b/packages/geoview-core/src/geo/layer/geoview-layers/raster/xyz-tiles.ts
index aa8e6c1da2a..64bd5f331ab 100644
--- a/packages/geoview-core/src/geo/layer/geoview-layers/raster/xyz-tiles.ts
+++ b/packages/geoview-core/src/geo/layer/geoview-layers/raster/xyz-tiles.ts
@@ -157,14 +157,14 @@ export class XYZTiles extends AbstractGeoViewRaster {
if (!layerConfig.listOfLayerEntryConfig.length) {
this.layerLoadError.push({
layer: layerPath,
- consoleMessage: `Empty layer group (mapId: ${this.mapId}, layerPath: ${layerPath})`,
+ loggerMessage: `Empty layer group (mapId: ${this.mapId}, layerPath: ${layerPath})`,
});
- this.setLayerStatus('error', layerPath);
+ layerConfig.layerStatus = 'error';
return;
}
}
- this.setLayerStatus('processing', layerPath);
+ layerConfig.layerStatus = 'processing';
// When no metadata are provided, all layers are considered valid.
if (!this.metadata) return;
@@ -177,9 +177,9 @@ export class XYZTiles extends AbstractGeoViewRaster {
if (!foundEntry) {
this.layerLoadError.push({
layer: layerPath,
- consoleMessage: `XYZ layer not found (mapId: ${this.mapId}, layerPath: ${layerPath})`,
+ loggerMessage: `XYZ layer not found (mapId: ${this.mapId}, layerPath: ${layerPath})`,
});
- this.setLayerStatus('error', layerPath);
+ layerConfig.layerStatus = 'error';
return;
}
return;
@@ -199,80 +199,83 @@ export class XYZTiles extends AbstractGeoViewRaster {
* @returns {TypeBaseRasterLayer} The GeoView raster layer that has been created.
*/
protected processOneLayerEntry(layerConfig: TypeXYZTilesLayerEntryConfig): Promise {
- const promisedVectorLayer = new Promise((resolve) => {
- const { layerPath } = layerConfig;
- this.setLayerPhase('processOneLayerEntry', layerPath);
- const sourceOptions: SourceOptions = {
- url: getLocalizedValue(layerConfig.source.dataAccessPath, this.mapId),
- };
- if (layerConfig.source.crossOrigin) {
- sourceOptions.crossOrigin = layerConfig.source.crossOrigin;
- } else {
- sourceOptions.crossOrigin = 'Anonymous';
- }
- if (layerConfig.source.projection) sourceOptions.projection = `EPSG:${layerConfig.source.projection}`;
- if (layerConfig.source.tileGrid) {
- const tileGridOptions: TileGridOptions = {
- origin: layerConfig.source.tileGrid?.origin,
- resolutions: layerConfig.source.tileGrid?.resolutions as number[],
- };
- if (layerConfig.source.tileGrid?.tileSize) tileGridOptions.tileSize = layerConfig.source.tileGrid?.tileSize;
- if (layerConfig.source.tileGrid?.extent) tileGridOptions.extent = layerConfig.source.tileGrid?.extent;
- sourceOptions.tileGrid = new TileGrid(tileGridOptions);
- }
-
- const tileLayerOptions: TileOptions = { source: new XYZ(sourceOptions) };
- // layerConfig.initialSettings cannot be undefined because config-validation set it to {} if it is undefined.
- if (layerConfig.initialSettings?.className !== undefined) tileLayerOptions.className = layerConfig.initialSettings?.className;
- if (layerConfig.initialSettings?.extent !== undefined) tileLayerOptions.extent = layerConfig.initialSettings?.extent;
- if (layerConfig.initialSettings?.maxZoom !== undefined) tileLayerOptions.maxZoom = layerConfig.initialSettings?.maxZoom;
- if (layerConfig.initialSettings?.minZoom !== undefined) tileLayerOptions.minZoom = layerConfig.initialSettings?.minZoom;
- if (layerConfig.initialSettings?.opacity !== undefined) tileLayerOptions.opacity = layerConfig.initialSettings?.opacity;
- if (layerConfig.initialSettings?.visible !== undefined)
- tileLayerOptions.visible = layerConfig.initialSettings?.visible === 'yes' || layerConfig.initialSettings?.visible === 'always';
-
- layerConfig.olLayerAndLoadEndListeners = {
- olLayer: new TileLayer(tileLayerOptions),
- loadEndListenerType: 'tile',
+ // ! IMPORTANT: The processOneLayerEntry method must call the corresponding method of its parent to ensure that the flow of
+ // ! layerStatus values is correctly sequenced.
+ super.processOneLayerEntry(layerConfig);
+ const { layerPath } = layerConfig;
+ this.setLayerPhase('processOneLayerEntry', layerPath);
+ const sourceOptions: SourceOptions = {
+ url: getLocalizedValue(layerConfig.source.dataAccessPath, this.mapId),
+ };
+ if (layerConfig.source.crossOrigin) {
+ sourceOptions.crossOrigin = layerConfig.source.crossOrigin;
+ } else {
+ sourceOptions.crossOrigin = 'Anonymous';
+ }
+ if (layerConfig.source.projection) sourceOptions.projection = `EPSG:${layerConfig.source.projection}`;
+ if (layerConfig.source.tileGrid) {
+ const tileGridOptions: TileGridOptions = {
+ origin: layerConfig.source.tileGrid?.origin,
+ resolutions: layerConfig.source.tileGrid?.resolutions as number[],
};
- layerConfig.geoviewLayerInstance = this;
+ if (layerConfig.source.tileGrid?.tileSize) tileGridOptions.tileSize = layerConfig.source.tileGrid?.tileSize;
+ if (layerConfig.source.tileGrid?.extent) tileGridOptions.extent = layerConfig.source.tileGrid?.extent;
+ sourceOptions.tileGrid = new TileGrid(tileGridOptions);
+ }
- resolve(layerConfig.olLayer);
- });
- return promisedVectorLayer;
+ const tileLayerOptions: TileOptions = { source: new XYZ(sourceOptions) };
+ // layerConfig.initialSettings cannot be undefined because config-validation set it to {} if it is undefined.
+ if (layerConfig.initialSettings?.className !== undefined) tileLayerOptions.className = layerConfig.initialSettings?.className;
+ if (layerConfig.initialSettings?.extent !== undefined) tileLayerOptions.extent = layerConfig.initialSettings?.extent;
+ if (layerConfig.initialSettings?.maxZoom !== undefined) tileLayerOptions.maxZoom = layerConfig.initialSettings?.maxZoom;
+ if (layerConfig.initialSettings?.minZoom !== undefined) tileLayerOptions.minZoom = layerConfig.initialSettings?.minZoom;
+ if (layerConfig.initialSettings?.opacity !== undefined) tileLayerOptions.opacity = layerConfig.initialSettings?.opacity;
+ // ! IMPORTANT: The initialSettings.visible flag must be set in the layerConfig.loadedFunction otherwise the layer will stall
+ // ! in the 'loading' state if the flag value is 'no'.
+
+ layerConfig.olLayerAndLoadEndListeners = {
+ olLayer: new TileLayer(tileLayerOptions),
+ loadEndListenerType: 'tile',
+ };
+ layerConfig.geoviewLayerInstance = this;
+
+ return Promise.resolve(layerConfig.olLayer);
}
/** ***************************************************************************************************************************
* This method is used to process the layer's metadata. It will fill the empty fields of the layer's configuration (renderer,
* initial settings, fields and aliases).
*
+ * ! This routine must imperatively ends with layerConfig.layerStatus = 'processed' or 'error' if an error happens.
+ *
* @param {TypeLayerEntryConfig} layerConfig The layer entry configuration to process.
*
* @returns {Promise} A promise that the vector layer configuration has its metadata processed.
*/
protected processLayerMetadata(layerConfig: TypeLayerEntryConfig): Promise {
- const promiseOfExecution = new Promise((resolve) => {
- if (!this.metadata) resolve(layerConfig);
- else {
- const metadataLayerConfigFound = Cast(this.metadata?.listOfLayerEntryConfig).find(
- (metadataLayerConfig) => metadataLayerConfig.layerId === layerConfig.layerId
+ if (this.metadata) {
+ const metadataLayerConfigFound = Cast(this.metadata?.listOfLayerEntryConfig).find(
+ (metadataLayerConfig) => metadataLayerConfig.layerId === layerConfig.layerId
+ );
+ // metadataLayerConfigFound can not be undefined because we have already validated the config exist
+ this.layerMetadata[layerConfig.layerPath] = toJsonObject(metadataLayerConfigFound);
+ layerConfig.source = defaultsDeep(layerConfig.source, metadataLayerConfigFound!.source);
+ layerConfig.initialSettings = defaultsDeep(layerConfig.initialSettings, metadataLayerConfigFound!.initialSettings);
+
+ if (layerConfig.initialSettings?.extent)
+ layerConfig.initialSettings.extent = api.projection.transformExtent(
+ layerConfig.initialSettings.extent,
+ 'EPSG:4326',
+ `EPSG:${MapEventProcessor.getMapState(this.mapId).currentProjection}`
);
- // metadataLayerConfigFound can not be undefined because we have already validated the config exist
- this.layerMetadata[layerConfig.layerPath] = toJsonObject(metadataLayerConfigFound);
- layerConfig.source = defaultsDeep(layerConfig.source, metadataLayerConfigFound!.source);
- layerConfig.initialSettings = defaultsDeep(layerConfig.initialSettings, metadataLayerConfigFound!.initialSettings);
-
- if (layerConfig.initialSettings?.extent)
- layerConfig.initialSettings.extent = api.projection.transformExtent(
- layerConfig.initialSettings.extent,
- 'EPSG:4326',
- `EPSG:${MapEventProcessor.getMapState(this.mapId).currentProjection}`
- );
-
- resolve(layerConfig);
- }
- });
- return promiseOfExecution;
+ }
+
+ // When we get here, we know that the metadata (if the service provide some) are processed.
+ // We need to signal to the layer sets that the 'processed' phase is done. Be aware that the
+ // layerStatus setter is doing a lot of things behind the scene.
+ layerConfig.layerStatus = 'processed';
+
+ return Promise.resolve(layerConfig);
}
/** ***************************************************************************************************************************
diff --git a/packages/geoview-core/src/geo/layer/geoview-layers/vector/abstract-geoview-vector.ts b/packages/geoview-core/src/geo/layer/geoview-layers/vector/abstract-geoview-vector.ts
index 1223646b60e..23e0b4919e6 100644
--- a/packages/geoview-core/src/geo/layer/geoview-layers/vector/abstract-geoview-vector.ts
+++ b/packages/geoview-core/src/geo/layer/geoview-layers/vector/abstract-geoview-vector.ts
@@ -86,6 +86,9 @@ export abstract class AbstractGeoViewVector extends AbstractGeoViewLayer {
* @returns {Promise} The GeoView base layer that has been created.
*/
protected processOneLayerEntry(layerConfig: TypeBaseLayerEntryConfig): Promise {
+ // ! IMPORTANT: The processOneLayerEntry method must call the corresponding method of its parent to ensure that the flow of
+ // ! layerStatus values is correctly sequenced.
+ super.processOneLayerEntry(layerConfig);
this.setLayerPhase('processOneLayerEntry', layerConfig.layerPath);
const vectorSource = this.createVectorSource(layerConfig);
const vectorLayer = this.createVectorLayer(layerConfig as TypeVectorLayerEntryConfig, vectorSource);
diff --git a/packages/geoview-core/src/geo/layer/geoview-layers/vector/csv.ts b/packages/geoview-core/src/geo/layer/geoview-layers/vector/csv.ts
index 7bf9a9f86ba..83f0e184761 100644
--- a/packages/geoview-core/src/geo/layer/geoview-layers/vector/csv.ts
+++ b/packages/geoview-core/src/geo/layer/geoview-layers/vector/csv.ts
@@ -174,15 +174,13 @@ export class CSV extends AbstractGeoViewVector {
if (!layerConfig.listOfLayerEntryConfig.length) {
this.layerLoadError.push({
layer: layerPath,
- consoleMessage: `Empty layer group (mapId: ${this.mapId}, layerPath: ${layerPath})`,
+ loggerMessage: `Empty layer group (mapId: ${this.mapId}, layerPath: ${layerPath})`,
});
- this.setLayerStatus('error', layerPath);
+ layerConfig.layerStatus = 'error';
}
return;
}
- this.setLayerStatus('loading', layerPath);
-
// When no metadata are provided, all layers are considered valid.
if (!this.metadata) return;
@@ -195,16 +193,19 @@ export class CSV extends AbstractGeoViewVector {
/** ***************************************************************************************************************************
* Metadata is processed when parsing the file.
*
+ * ! This routine must imperatively ends with layerConfig.layerStatus = 'processed' or 'error' if an error happens.
+ *
* @param {TypeVectorLayerEntryConfig} layerConfig The layer entry configuration to process.
*
* @returns {Promise} A promise that the vector layer configuration has its metadata processed.
*/
protected processLayerMetadata(layerConfig: TypeVectorLayerEntryConfig): Promise {
- const promiseOfExecution = new Promise((resolve) => {
- resolve(layerConfig);
- });
+ // When we get here, we know that the metadata (if the service provide some) are processed.
+ // We need to signal to the layer sets that the 'processed' phase is done. Be aware that the
+ // layerStatus setter is doing a lot of things behind the scene.
+ layerConfig.layerStatus = 'processed';
- return promiseOfExecution;
+ return Promise.resolve(layerConfig);
}
/** ***************************************************************************************************************************
@@ -306,7 +307,7 @@ export class CSV extends AbstractGeoViewVector {
if (latIndex === undefined || lonIndex === undefined) {
logger.logError(`Could not find geographic data for ${getLocalizedValue(this.geoviewLayerName, this.mapId)}`);
addNotificationError(this.mapId, `Could not find geographic data for ${getLocalizedValue(this.geoviewLayerName, this.mapId)}`);
- this.setLayerStatus('error', layerConfig.layerPath);
+ layerConfig.layerStatus = 'error';
return null;
}
this.processFeatureInfoConfig(headers, csvRows[1], [latIndex, lonIndex], layerConfig);
diff --git a/packages/geoview-core/src/geo/layer/geoview-layers/vector/esri-feature.ts b/packages/geoview-core/src/geo/layer/geoview-layers/vector/esri-feature.ts
index 0b349d01cc0..2ce7e0e1726 100644
--- a/packages/geoview-core/src/geo/layer/geoview-layers/vector/esri-feature.ts
+++ b/packages/geoview-core/src/geo/layer/geoview-layers/vector/esri-feature.ts
@@ -160,7 +160,7 @@ export class EsriFeature extends AbstractGeoViewVector {
if (this.metadata!.layers[esriIndex].type !== 'Feature Layer') {
this.layerLoadError.push({
layer: layerConfig.layerPath,
- consoleMessage: `LayerId ${layerConfig.layerPath} of map ${this.mapId} is not a feature layer`,
+ loggerMessage: `LayerId ${layerConfig.layerPath} of map ${this.mapId} is not a feature layer`,
});
return true;
}
diff --git a/packages/geoview-core/src/geo/layer/geoview-layers/vector/geojson.ts b/packages/geoview-core/src/geo/layer/geoview-layers/vector/geojson.ts
index a27997ae02f..f93644df740 100644
--- a/packages/geoview-core/src/geo/layer/geoview-layers/vector/geojson.ts
+++ b/packages/geoview-core/src/geo/layer/geoview-layers/vector/geojson.ts
@@ -157,14 +157,14 @@ export class GeoJSON extends AbstractGeoViewVector {
if (!layerConfig.listOfLayerEntryConfig.length) {
this.layerLoadError.push({
layer: layerPath,
- consoleMessage: `Empty layer group (mapId: ${this.mapId}, layerPath: ${layerPath})`,
+ loggerMessage: `Empty layer group (mapId: ${this.mapId}, layerPath: ${layerPath})`,
});
- this.setLayerStatus('error', layerPath);
+ layerConfig.layerStatus = 'error';
}
return;
}
- this.setLayerStatus('processing', layerPath);
+ layerConfig.layerStatus = 'processing';
// When no metadata are provided, all layers are considered valid.
if (!this.metadata) return;
@@ -180,9 +180,9 @@ export class GeoJSON extends AbstractGeoViewVector {
if (!foundEntry) {
this.layerLoadError.push({
layer: layerPath,
- consoleMessage: `GeoJSON layer not found (mapId: ${this.mapId}, layerPath: ${layerPath})`,
+ loggerMessage: `GeoJSON layer not found (mapId: ${this.mapId}, layerPath: ${layerPath})`,
});
- this.setLayerStatus('error', layerPath);
+ layerConfig.layerStatus = 'error';
return;
}
return;
@@ -198,54 +198,56 @@ export class GeoJSON extends AbstractGeoViewVector {
* This method is used to process the layer's metadata. It will fill the empty fields of the layer's configuration (renderer,
* initial settings, fields and aliases).
*
+ * ! This routine must imperatively ends with layerConfig.layerStatus = 'processed' or 'error' if an error happens.
+ *
* @param {TypeVectorLayerEntryConfig} layerConfig The layer entry configuration to process.
*
* @returns {Promise} A promise that the vector layer configuration has its metadata processed.
*/
protected processLayerMetadata(layerConfig: TypeVectorLayerEntryConfig): Promise {
- const promiseOfExecution = new Promise((resolve) => {
- if (!this.metadata) resolve(layerConfig);
- else {
- const metadataLayerList = Cast(this.metadata?.listOfLayerEntryConfig);
- const layerMetadataFound = metadataLayerList.find(
- (layerMetadata) =>
- layerMetadata.layerId === layerConfig.layerId && layerMetadata.layerIdExtension === layerConfig.layerIdExtension
- );
- if (layerMetadataFound) {
- this.layerMetadata[layerConfig.layerPath] = toJsonObject(layerMetadataFound);
- layerConfig.layerName = layerConfig.layerName || layerMetadataFound.layerName;
- layerConfig.source = defaultsDeep(layerConfig.source, layerMetadataFound.source);
- layerConfig.initialSettings = defaultsDeep(layerConfig.initialSettings, layerMetadataFound.initialSettings);
- layerConfig.style = defaultsDeep(layerConfig.style, layerMetadataFound.style);
- // When the dataAccessPath stored in the layerConfig.source object is equal to the root of the metadataAccessPath with a
- // layerId ending, chances are that it was set by the config-validation because of an empty dataAcessPath value in the config.
- // This situation means that we want to use the dataAccessPath found in the metadata if it is set, otherwise we will keep the
- // config dataAccessPath value.
- let metadataAccessPathRoot = getLocalizedValue(layerConfig.geoviewLayerConfig?.metadataAccessPath, this.mapId);
- if (metadataAccessPathRoot) {
- metadataAccessPathRoot =
- metadataAccessPathRoot.split('/').length > 1 ? metadataAccessPathRoot.split('/').slice(0, -1).join('/') : './';
- const metadataAccessPathRootPlusLayerId = `${metadataAccessPathRoot}/${layerConfig.layerId}`;
- if (
- metadataAccessPathRootPlusLayerId === getLocalizedValue(layerConfig.source?.dataAccessPath, this.mapId) &&
- getLocalizedValue(layerMetadataFound.source?.dataAccessPath, this.mapId)
- ) {
- layerConfig.source!.dataAccessPath = { ...layerMetadataFound.source!.dataAccessPath } as TypeLocalizedString;
- }
+ if (this.metadata) {
+ const metadataLayerList = Cast(this.metadata?.listOfLayerEntryConfig);
+ const layerMetadataFound = metadataLayerList.find(
+ (layerMetadata) => layerMetadata.layerId === layerConfig.layerId && layerMetadata.layerIdExtension === layerConfig.layerIdExtension
+ );
+ if (layerMetadataFound) {
+ this.layerMetadata[layerConfig.layerPath] = toJsonObject(layerMetadataFound);
+ layerConfig.layerName = layerConfig.layerName || layerMetadataFound.layerName;
+ layerConfig.source = defaultsDeep(layerConfig.source, layerMetadataFound.source);
+ layerConfig.initialSettings = defaultsDeep(layerConfig.initialSettings, layerMetadataFound.initialSettings);
+ layerConfig.style = defaultsDeep(layerConfig.style, layerMetadataFound.style);
+ // When the dataAccessPath stored in the layerConfig.source object is equal to the root of the metadataAccessPath with a
+ // layerId ending, chances are that it was set by the config-validation because of an empty dataAcessPath value in the config.
+ // This situation means that we want to use the dataAccessPath found in the metadata if it is set, otherwise we will keep the
+ // config dataAccessPath value.
+ let metadataAccessPathRoot = getLocalizedValue(layerConfig.geoviewLayerConfig?.metadataAccessPath, this.mapId);
+ if (metadataAccessPathRoot) {
+ metadataAccessPathRoot =
+ metadataAccessPathRoot.split('/').length > 1 ? metadataAccessPathRoot.split('/').slice(0, -1).join('/') : './';
+ const metadataAccessPathRootPlusLayerId = `${metadataAccessPathRoot}/${layerConfig.layerId}`;
+ if (
+ metadataAccessPathRootPlusLayerId === getLocalizedValue(layerConfig.source?.dataAccessPath, this.mapId) &&
+ getLocalizedValue(layerMetadataFound.source?.dataAccessPath, this.mapId)
+ ) {
+ layerConfig.source!.dataAccessPath = { ...layerMetadataFound.source!.dataAccessPath } as TypeLocalizedString;
}
}
+ }
- if (layerConfig.initialSettings?.extent)
- layerConfig.initialSettings.extent = api.projection.transformExtent(
- layerConfig.initialSettings.extent,
- 'EPSG:4326',
- `EPSG:${MapEventProcessor.getMapState(this.mapId).currentProjection}`
- );
+ if (layerConfig.initialSettings?.extent)
+ layerConfig.initialSettings.extent = api.projection.transformExtent(
+ layerConfig.initialSettings.extent,
+ 'EPSG:4326',
+ `EPSG:${MapEventProcessor.getMapState(this.mapId).currentProjection}`
+ );
+ }
- resolve(layerConfig);
- }
- });
- return promiseOfExecution;
+ // When we get here, we know that the metadata (if the service provide some) are processed.
+ // We need to signal to the layer sets that the 'processed' phase is done. Be aware that the
+ // layerStatus setter is doing a lot of things behind the scene.
+ layerConfig.layerStatus = 'processed';
+
+ return Promise.resolve(layerConfig);
}
/** ***************************************************************************************************************************
diff --git a/packages/geoview-core/src/geo/layer/geoview-layers/vector/geopackage.ts b/packages/geoview-core/src/geo/layer/geoview-layers/vector/geopackage.ts
index db832f28ed0..2a0665f412d 100644
--- a/packages/geoview-core/src/geo/layer/geoview-layers/vector/geopackage.ts
+++ b/packages/geoview-core/src/geo/layer/geoview-layers/vector/geopackage.ts
@@ -183,21 +183,21 @@ export class GeoPackage extends AbstractGeoViewVector {
*/
protected validateListOfLayerEntryConfig(listOfLayerEntryConfig: TypeListOfLayerEntryConfig) {
this.setLayerPhase('validateListOfLayerEntryConfig');
- return listOfLayerEntryConfig.forEach((layerConfig: TypeLayerEntryConfig) => {
+ listOfLayerEntryConfig.forEach((layerConfig: TypeLayerEntryConfig) => {
const { layerPath } = layerConfig;
if (layerEntryIsGroupLayer(layerConfig)) {
this.validateListOfLayerEntryConfig(layerConfig.listOfLayerEntryConfig!);
if (!layerConfig.listOfLayerEntryConfig.length) {
this.layerLoadError.push({
layer: layerPath,
- consoleMessage: `Empty layer group (mapId: ${this.mapId}, layerPath: ${layerPath})`,
+ loggerMessage: `Empty layer group (mapId: ${this.mapId}, layerPath: ${layerPath})`,
});
- this.setLayerStatus('error', layerPath);
+ layerConfig.layerStatus = 'error';
return;
}
}
- this.setLayerStatus('processing', layerPath);
+ layerConfig.layerStatus = 'processing';
});
}
@@ -224,7 +224,7 @@ export class GeoPackage extends AbstractGeoViewVector {
} else {
this.layerLoadError.push({
layer: listOfLayerEntryConfig[0].layerPath,
- consoleMessage: `Unable to create group layer ${listOfLayerEntryConfig[0].layerPath} on map ${this.mapId}`,
+ loggerMessage: `Unable to create group layer ${listOfLayerEntryConfig[0].layerPath} on map ${this.mapId}`,
});
resolve(null);
}
@@ -238,7 +238,6 @@ export class GeoPackage extends AbstractGeoViewVector {
);
listOfLayerEntryConfig.forEach((layerConfig) => {
- const { layerPath } = layerConfig;
if (layerEntryIsGroupLayer(layerConfig)) {
const newLayerGroup = this.createLayerGroup(layerConfig, layerConfig.initialSettings!);
this.processListOfLayerEntryConfig(layerConfig.listOfLayerEntryConfig!, newLayerGroup).then((groupReturned) => {
@@ -247,22 +246,22 @@ export class GeoPackage extends AbstractGeoViewVector {
} else {
this.layerLoadError.push({
layer: listOfLayerEntryConfig[0].layerPath,
- consoleMessage: `Unable to create group layer ${layerConfig.layerPath} on map ${this.mapId}`,
+ loggerMessage: `Unable to create group layer ${layerConfig.layerPath} on map ${this.mapId}`,
});
resolve(null);
}
});
} else {
- this.processOneGeopackage(layerConfig as TypeBaseLayerEntryConfig).then((layers) => {
+ this.processOneLayerEntry(layerConfig as TypeBaseLayerEntryConfig).then((layers) => {
if (layers) {
layerGroup!.getLayers().push(layers);
- this.setLayerStatus('processed', layerPath);
+ layerConfig.layerStatus = 'processed';
} else {
this.layerLoadError.push({
layer: listOfLayerEntryConfig[0].layerPath,
- consoleMessage: `Unable to create layer ${layerConfig.layerPath} on map ${this.mapId}`,
+ loggerMessage: `Unable to create layer ${layerConfig.layerPath} on map ${this.mapId}`,
});
- this.setLayerStatus('error', layerPath);
+ layerConfig.layerStatus = 'error';
}
});
}
@@ -270,17 +269,16 @@ export class GeoPackage extends AbstractGeoViewVector {
if (layerGroup) resolve(layerGroup);
// Single non-group config
} else {
- this.processOneGeopackage(listOfLayerEntryConfig[0] as TypeBaseLayerEntryConfig, layerGroup).then((layer) => {
- const layerPath0 = listOfLayerEntryConfig[0].layerPath;
+ this.processOneLayerEntry(listOfLayerEntryConfig[0] as TypeBaseLayerEntryConfig, layerGroup).then((layer) => {
if (layer) {
- this.setLayerStatus('processed', layerPath0);
+ listOfLayerEntryConfig[0].layerStatus = 'processed';
resolve(layer);
} else {
this.layerLoadError.push({
layer: listOfLayerEntryConfig[0].layerPath,
- consoleMessage: `Unable to create layer ${listOfLayerEntryConfig[0].layerPath} on map ${this.mapId}`,
+ loggerMessage: `Unable to create layer ${listOfLayerEntryConfig[0].layerPath} on map ${this.mapId}`,
});
- this.setLayerStatus('error', layerPath0);
+ listOfLayerEntryConfig[0].layerStatus = 'error';
}
});
}
@@ -558,55 +556,53 @@ export class GeoPackage extends AbstractGeoViewVector {
layerInfo: layerData,
sld?: sldsInterface
): Promise {
- const promisedVectorLayer = new Promise((resolve) => {
- layerConfig.registerLayerConfig();
+ layerConfig.registerLayerConfig();
- const { name, source } = layerInfo;
+ const { name, source } = layerInfo;
- // Extract layer styles if they exist
- if (sld && sld[name]) {
- this.processGeopackageStyle(layerConfig, sld[name]);
- }
-
- if (layerInfo.properties) {
- const { properties } = layerInfo;
- this.processFeatureInfoConfig(properties as TypeJsonObject, layerConfig as TypeVectorLayerEntryConfig);
- }
+ // Extract layer styles if they exist
+ if (sld && sld[name]) {
+ this.processGeopackageStyle(layerConfig, sld[name]);
+ }
- const vectorLayer = this.createVectorLayer(layerConfig as TypeVectorLayerEntryConfig, source);
- this.setLayerStatus('processed', layerConfig.layerPath);
+ if (layerInfo.properties) {
+ const { properties } = layerInfo;
+ this.processFeatureInfoConfig(properties as TypeJsonObject, layerConfig as TypeVectorLayerEntryConfig);
+ }
- resolve(vectorLayer);
- });
+ const vectorLayer = this.createVectorLayer(layerConfig as TypeVectorLayerEntryConfig, source);
+ layerConfig.layerStatus = 'processed';
- return promisedVectorLayer;
+ return Promise.resolve(vectorLayer);
}
/** ***************************************************************************************************************************
- * This method creates all layers from a single geopackage
+ * This method creates all layers from a single geopackage.
*
* @param {TypeLayerEntryConfig} layerConfig Information needed to create the GeoView layer.
* @param {LayerGroup} layerGroup Optional layer group for multiple layers.
*
* @returns {Promise} The GeoView base layer that has been created.
*/
- protected processOneGeopackage(layerConfig: TypeBaseLayerEntryConfig, layerGroup?: LayerGroup): Promise {
+ protected processOneLayerEntry(layerConfig: TypeBaseLayerEntryConfig, layerGroup?: LayerGroup): Promise {
+ // ! IMPORTANT: The processOneLayerEntry method must call the corresponding method of its parent to ensure that the flow of
+ // ! layerStatus values is correctly sequenced.
+ super.processOneLayerEntry(layerConfig);
const promisedLayers = new Promise((resolve) => {
- const { layerPath } = layerConfig;
// eslint-disable-next-line @typescript-eslint/no-unused-vars
this.extractGeopackageData(layerConfig).then(([layers, slds]) => {
if (layers.length === 1) {
this.processOneGeopackageLayer(layerConfig, layers[0], slds).then((baseLayer) => {
if (baseLayer) {
- this.setLayerStatus('processed', layerPath);
+ layerConfig.layerStatus = 'processed';
if (layerGroup) layerGroup.getLayers().push(baseLayer);
resolve(layerGroup || baseLayer);
} else {
this.layerLoadError.push({
layer: layerConfig.layerPath,
- consoleMessage: `Unable to create layer ${layerConfig.layerPath} on map ${this.mapId}`,
+ loggerMessage: `Unable to create layer ${layerConfig.layerPath} on map ${this.mapId}`,
});
- this.setLayerStatus('error', layerPath);
+ layerConfig.layerStatus = 'error';
resolve(null);
}
});
@@ -622,17 +618,16 @@ export class GeoPackage extends AbstractGeoViewVector {
newLayerEntryConfig.parentLayerConfig = Cast(layerConfig);
this.processOneGeopackageLayer(newLayerEntryConfig, layers[i], slds).then((baseLayer) => {
- const newLayerPath = newLayerEntryConfig.layerPath;
if (baseLayer) {
(layerConfig as unknown as TypeLayerGroupEntryConfig).listOfLayerEntryConfig!.push(newLayerEntryConfig);
newLayerGroup.getLayers().push(baseLayer);
- this.setLayerStatus('processed', newLayerPath);
+ layerConfig.layerStatus = 'processed';
} else {
this.layerLoadError.push({
layer: layerConfig.layerPath,
- consoleMessage: `Unable to create layer ${layerConfig.layerPath} on map ${this.mapId}`,
+ loggerMessage: `Unable to create layer ${layerConfig.layerPath} on map ${this.mapId}`,
});
- this.setLayerStatus('error', newLayerPath);
+ layerConfig.layerStatus = 'error';
resolve(null);
}
});
diff --git a/packages/geoview-core/src/geo/layer/geoview-layers/vector/ogc-feature.ts b/packages/geoview-core/src/geo/layer/geoview-layers/vector/ogc-feature.ts
index 3966e9fa48a..08cfc87f3bc 100644
--- a/packages/geoview-core/src/geo/layer/geoview-layers/vector/ogc-feature.ts
+++ b/packages/geoview-core/src/geo/layer/geoview-layers/vector/ogc-feature.ts
@@ -26,6 +26,7 @@ import {
import { getLocalizedValue } from '@/core/utils/utilities';
import { MapEventProcessor } from '@/api/event-processors/event-processor-children/map-event-processor';
import { api } from '@/app';
+import { logger } from '@/core/utils/logger';
export interface TypeSourceOgcFeatureInitialConfig extends TypeVectorSourceInitialConfig {
format: 'featureAPI';
@@ -183,14 +184,14 @@ export class OgcFeature extends AbstractGeoViewVector {
if (!layerConfig.listOfLayerEntryConfig.length) {
this.layerLoadError.push({
layer: layerPath,
- consoleMessage: `Empty layer group (mapId: ${this.mapId}, layerPath: ${layerPath})`,
+ loggerMessage: `Empty layer group (mapId: ${this.mapId}, layerPath: ${layerPath})`,
});
- this.setLayerStatus('error', layerPath);
+ layerConfig.layerStatus = 'error';
return;
}
}
- this.setLayerStatus('processing', layerPath);
+ layerConfig.layerStatus = 'processing';
// Note that the code assumes ogc-feature collections does not contains metadata layer group. If you need layer group,
// you can define them in the configuration section.
@@ -199,9 +200,9 @@ export class OgcFeature extends AbstractGeoViewVector {
if (!foundCollection) {
this.layerLoadError.push({
layer: layerPath,
- consoleMessage: `OGC feature layer not found (mapId: ${this.mapId}, layerPath: ${layerPath})`,
+ loggerMessage: `OGC feature layer not found (mapId: ${this.mapId}, layerPath: ${layerPath})`,
});
- this.setLayerStatus('error', layerPath);
+ layerConfig.layerStatus = 'error';
return;
}
@@ -242,24 +243,29 @@ export class OgcFeature extends AbstractGeoViewVector {
*
* @returns {Promise} A promise that the vector layer configuration has its metadata processed.
*/
- protected processLayerMetadata(layerConfig: TypeVectorLayerEntryConfig): Promise {
- const promiseOfExecution = new Promise((resolve) => {
+ protected async processLayerMetadata(layerConfig: TypeVectorLayerEntryConfig): Promise {
+ try {
const metadataUrl = getLocalizedValue(this.metadataAccessPath, this.mapId);
if (metadataUrl) {
const queryUrl = metadataUrl.endsWith('/')
? `${metadataUrl}collections/${String(layerConfig.layerId)}/queryables?f=json`
: `${metadataUrl}/collections/${String(layerConfig.layerId)}/queryables?f=json`;
- const queryResult = axios.get(queryUrl);
- queryResult.then((response) => {
- if (response.data.properties) {
- this.layerMetadata[layerConfig.layerPath] = response.data.properties;
- this.processFeatureInfoConfig(response.data.properties, layerConfig);
- }
- resolve(layerConfig);
- });
- } else resolve(layerConfig);
- });
- return promiseOfExecution;
+ const queryResult = await axios.get(queryUrl);
+ if (queryResult.data.properties) {
+ this.layerMetadata[layerConfig.layerPath] = queryResult.data.properties;
+ this.processFeatureInfoConfig(queryResult.data.properties, layerConfig);
+ }
+ }
+
+ // When we get here, we know that the metadata (if the service provide some) are processed.
+ // We need to signal to the layer sets that the 'processed' phase is done. Be aware that the
+ // layerStatus setter is doing a lot of things behind the scene.
+ layerConfig.layerStatus = 'processed';
+ } catch (error) {
+ logger.logError(`Error processing layer metadata for layer path "${layerConfig.layerPath}`, error);
+ layerConfig.layerStatus = 'error';
+ }
+ return layerConfig;
}
/** ***************************************************************************************************************************
diff --git a/packages/geoview-core/src/geo/layer/geoview-layers/vector/wfs.ts b/packages/geoview-core/src/geo/layer/geoview-layers/vector/wfs.ts
index 81b2574ff5c..094adbadef7 100644
--- a/packages/geoview-core/src/geo/layer/geoview-layers/vector/wfs.ts
+++ b/packages/geoview-core/src/geo/layer/geoview-layers/vector/wfs.ts
@@ -25,6 +25,7 @@ import {
import { getLocalizedValue, getXMLHttpRequest, xmlToJson, findPropertyNameByRegex } from '@/core/utils/utilities';
import { MapEventProcessor } from '@/api/event-processors/event-processor-children/map-event-processor';
import { api } from '@/app';
+import { logger } from '@/core/utils/logger';
export interface TypeSourceWFSVectorInitialConfig extends TypeVectorSourceInitialConfig {
format: 'WFS';
@@ -194,14 +195,14 @@ export class WFS extends AbstractGeoViewVector {
if (!layerConfig.listOfLayerEntryConfig.length) {
this.layerLoadError.push({
layer: layerPath,
- consoleMessage: `Empty layer group (mapId: ${this.mapId}, layerPath: ${layerPath})`,
+ loggerMessage: `Empty layer group (mapId: ${this.mapId}, layerPath: ${layerPath})`,
});
- this.setLayerStatus('error', layerPath);
+ layerConfig.layerStatus = 'error';
return;
}
}
- this.setLayerStatus('processing', layerPath);
+ layerConfig.layerStatus = 'processing';
// Note that the code assumes wfs feature type list does not contains metadata layer group. If you need layer group,
// you can define them in the configuration section.
@@ -219,9 +220,9 @@ export class WFS extends AbstractGeoViewVector {
if (!foundMetadata) {
this.layerLoadError.push({
layer: layerPath,
- consoleMessage: `WFS feature layer not found (mapId: ${this.mapId}, layerPath: ${layerPath})`,
+ loggerMessage: `WFS feature layer not found (mapId: ${this.mapId}, layerPath: ${layerPath})`,
});
- this.setLayerStatus('error', layerPath);
+ layerConfig.layerStatus = 'error';
return;
}
@@ -252,8 +253,8 @@ export class WFS extends AbstractGeoViewVector {
*
* @returns {Promise} A promise that the vector layer configuration has its metadata processed.
*/
- protected processLayerMetadata(layerConfig: TypeVectorLayerEntryConfig): Promise {
- const promiseOfExecution = new Promise((resolve) => {
+ protected async processLayerMetadata(layerConfig: TypeVectorLayerEntryConfig): Promise {
+ try {
let queryUrl = getLocalizedValue(layerConfig.source!.dataAccessPath, this.mapId);
// check if url contains metadata parameters for the getCapabilities request and reformat the urls
@@ -279,50 +280,46 @@ export class WFS extends AbstractGeoViewVector {
}&outputFormat=${encodeURIComponent(outputFormat as string)}&typeName=${layerConfig.layerId}`;
if (describeFeatureUrl && outputFormat === 'application/json') {
- fetch(describeFeatureUrl)
- .then((fetchResponse) => {
- return fetchResponse.json();
- })
- .then((layerMetadata) => {
- if (Array.isArray(layerMetadata.featureTypes) && Array.isArray(layerMetadata.featureTypes[0].properties)) {
- this.layerMetadata[layerConfig.layerPath] = layerMetadata.featureTypes[0].properties;
- this.processFeatureInfoConfig(layerMetadata.featureTypes[0].properties as TypeJsonArray, layerConfig);
- }
- resolve(layerConfig);
- });
+ const layerMetadata = (await (await fetch(describeFeatureUrl)).json()) as TypeJsonObject;
+ if (Array.isArray(layerMetadata.featureTypes) && Array.isArray(layerMetadata.featureTypes[0].properties)) {
+ this.layerMetadata[layerConfig.layerPath] = layerMetadata.featureTypes[0].properties;
+ this.processFeatureInfoConfig(layerMetadata.featureTypes[0].properties as TypeJsonArray, layerConfig);
+ }
} else if (describeFeatureUrl && outputFormat.toUpperCase().includes('XML')) {
- fetch(describeFeatureUrl)
- .then((fetchResponse) => {
- return fetchResponse.text();
- })
- .then((layerMetadata) => {
- // need to pass a xmldom to xmlToJson to convert xsd schema to json
- const xmlDOMDescribe = new DOMParser().parseFromString(layerMetadata, 'text/xml');
- const xmlJsonDescribe = xmlToJson(xmlDOMDescribe);
- const prefix = Object.keys(xmlJsonDescribe)[0].includes('xsd:') ? 'xsd:' : '';
- const xmlJsonSchema = xmlJsonDescribe[`${prefix}schema`];
- const xmlJsonDescribeElement =
- xmlJsonSchema[`${prefix}complexType`] !== undefined
- ? xmlJsonSchema[`${prefix}complexType`][`${prefix}complexContent`][`${prefix}extension`][`${prefix}sequence`][
- `${prefix}element`
- ]
- : [];
-
- if (Array.isArray(xmlJsonDescribeElement)) {
- // recreate the array of properties as if it was json
- const featureTypeProperties: TypeJsonArray = [];
- xmlJsonDescribeElement.forEach((element) => {
- featureTypeProperties.push(element['@attributes']);
- });
-
- this.layerMetadata[layerConfig.layerPath] = featureTypeProperties as TypeJsonObject;
- this.processFeatureInfoConfig(featureTypeProperties as TypeJsonArray, layerConfig);
- }
- resolve(layerConfig);
+ const layerMetadata = (await (await fetch(describeFeatureUrl)).text()) as string;
+ // need to pass a xmldom to xmlToJson to convert xsd schema to json
+ const xmlDOMDescribe = new DOMParser().parseFromString(layerMetadata, 'text/xml');
+ const xmlJsonDescribe = xmlToJson(xmlDOMDescribe);
+ const prefix = Object.keys(xmlJsonDescribe)[0].includes('xsd:') ? 'xsd:' : '';
+ const xmlJsonSchema = xmlJsonDescribe[`${prefix}schema`];
+ const xmlJsonDescribeElement =
+ xmlJsonSchema[`${prefix}complexType`] !== undefined
+ ? xmlJsonSchema[`${prefix}complexType`][`${prefix}complexContent`][`${prefix}extension`][`${prefix}sequence`][
+ `${prefix}element`
+ ]
+ : [];
+
+ if (Array.isArray(xmlJsonDescribeElement)) {
+ // recreate the array of properties as if it was json
+ const featureTypeProperties: TypeJsonArray = [];
+ xmlJsonDescribeElement.forEach((element) => {
+ featureTypeProperties.push(element['@attributes']);
});
- } else resolve(layerConfig);
- });
- return promiseOfExecution;
+
+ this.layerMetadata[layerConfig.layerPath] = featureTypeProperties as TypeJsonObject;
+ this.processFeatureInfoConfig(featureTypeProperties as TypeJsonArray, layerConfig);
+ }
+ }
+
+ // When we get here, we know that the metadata (if the service provide some) are processed.
+ // We need to signal to the layer sets that the 'processed' phase is done. Be aware that the
+ // layerStatus setter is doing a lot of things behind the scene.
+ layerConfig.layerStatus = 'processed';
+ } catch (error) {
+ logger.logError(`Error processing layer metadata for layer path "${layerConfig.layerPath}`, error);
+ layerConfig.layerStatus = 'error';
+ }
+ return layerConfig;
}
/** ***************************************************************************************************************************
diff --git a/packages/geoview-core/src/geo/layer/layer.ts b/packages/geoview-core/src/geo/layer/layer.ts
index 52862d680fe..55af110a905 100644
--- a/packages/geoview-core/src/geo/layer/layer.ts
+++ b/packages/geoview-core/src/geo/layer/layer.ts
@@ -347,21 +347,20 @@ export class Layer {
// do not add the layer to the map
if (geoviewLayer.layerLoadError.length !== 0) {
geoviewLayer.layerLoadError.forEach((loadError) => {
- const { layer, consoleMessage } = loadError;
+ const { layer, loggerMessage } = loadError;
// Log the details in the console
- logger.logError(consoleMessage);
+ logger.logError(loggerMessage);
const message = replaceParams([layer, this.mapId], getLocalizedMessage(this.mapId, 'validation.layer.loadfailed'));
showError(this.mapId, message);
});
}
- if (geoviewLayer.allLayerStatusAreIn(['error']))
+ if (geoviewLayer.allLayerStatusAreGreaterThanOrEqualTo('error'))
// an empty geoview layer is created
api.event.emit(GeoViewLayerPayload.createGeoviewLayerAddedPayload(`${this.mapId}/${geoviewLayer.geoviewLayerId}`, geoviewLayer));
else {
- geoviewLayer.setAllLayerStatusTo('loading', geoviewLayer.listOfLayerEntryConfig);
api.maps[this.mapId].map.addLayer(geoviewLayer.olLayers!);
api.event.emit(GeoViewLayerPayload.createGeoviewLayerAddedPayload(`${this.mapId}/${geoviewLayer.geoviewLayerId}`, geoviewLayer));
}
@@ -508,7 +507,7 @@ export class Layer {
try {
// Waiting for the processed phase, possibly throwing exception if that's not happening
- await this.waitForProcesseOrErrorStatus(layer, timeout, checkFrequency);
+ await this.waitForAllLayerStatusAreGreaterThanOrEqualTo(layer, timeout, checkFrequency);
return layer;
} catch (error) {
// Throw
@@ -563,11 +562,15 @@ export class Layer {
* @param {string} checkFrequency optionally indicate the frequency at which to check for the condition on the layer
* @throws an exception when the layer failed to become in processed phase before the timeout expired
*/
- waitForProcesseOrErrorStatus = async (layer: AbstractGeoViewLayer, timeout?: number, checkFrequency?: number): Promise => {
+ waitForAllLayerStatusAreGreaterThanOrEqualTo = async (
+ geoviewLayerConfig: AbstractGeoViewLayer,
+ timeout?: number,
+ checkFrequency?: number
+ ): Promise => {
// Wait for the processed phase
await whenThisThen(
() => {
- return layer.allLayerStatusAreIn(['processed', 'loading', 'loaded', 'error']);
+ return geoviewLayerConfig.allLayerStatusAreGreaterThanOrEqualTo('processed');
},
timeout,
checkFrequency
diff --git a/packages/geoview-core/src/geo/layer/other/cluster-placeholder.ts b/packages/geoview-core/src/geo/layer/other/cluster-placeholder.ts
index 727775ec862..06e13e19482 100644
--- a/packages/geoview-core/src/geo/layer/other/cluster-placeholder.ts
+++ b/packages/geoview-core/src/geo/layer/other/cluster-placeholder.ts
@@ -262,7 +262,7 @@
// baseLayer.setVisible(false);
// if (!layerGroup) layerGroup = this.createLayerGroup(unclusteredLayerConfig.parentLayerConfig as TypeLayerEntryConfig);
// layerGroup.getLayers().push(baseLayer);
-// this.setLayerStatus('processed', unclusteredLayerConfig.layerPath);
+// layerConfig.layerStatus = 'processed';
// }
// });
@@ -272,15 +272,15 @@
// this.processOneGeopackageLayer(layerConfig, layers[0], slds).then((baseLayer) => {
// if (baseLayer) {
-// this.setLayerStatus('processed', layerConfig.layerPath);
+// layerConfig.layerStatus = 'processed';
// if (layerGroup) layerGroup.getLayers().push(baseLayer);
// resolve(layerGroup || baseLayer);
// } else {
// this.layerLoadError.push({
// layer: layerConfig.layerPath,
-// consoleMessage: `Unable to create layer ${layerConfig.layerPath} on map ${this.mapId}`,
+// loggerMessage: `Unable to create layer ${layerConfig.layerPath} on map ${this.mapId}`,
// });
-// this.setLayerStatus('error', layerConfig.layerPath);
+// layerConfig.layerStatus = 'error';
// resolve(null);
// }
// });
@@ -303,7 +303,7 @@
// if (baseLayer) {
// baseLayer.setVisible(false);
// newLayerGroup.getLayers().push(baseLayer);
-// this.setLayerStatus('processed', unclusteredLayerConfig.layerPath);
+// newLayerEntryConfig.layerStatus = 'processed';
// }
// });
@@ -315,13 +315,13 @@
// if (baseLayer) {
// (layerConfig as unknown as TypeLayerGroupEntryConfig).listOfLayerEntryConfig!.push(newLayerEntryConfig);
// newLayerGroup.getLayers().push(baseLayer);
-// this.setLayerStatus('processed', newLayerEntryConfig.layerPath;
+// newLayerEntryConfig.layerStatus = 'processed';
// } else {
// this.layerLoadError.push({
// layer: layerConfig.layerPath,
-// consoleMessage: `Unable to create layer ${layerConfig.layerPath} on map ${this.mapId}`,
+// loggerMessage: `Unable to create layer ${layerConfig.layerPath} on map ${this.mapId}`,
// });
-// this.setLayerStatus('error', newLayerEntryConfig.layerPath);
+// newLayerEntryConfig.layerStatus = 'error';
// resolve(null);
// }
// });
diff --git a/packages/geoview-core/src/geo/map/map-schema-types.ts b/packages/geoview-core/src/geo/map/map-schema-types.ts
index 5c9c44bb9f6..da09feaeb07 100644
--- a/packages/geoview-core/src/geo/map/map-schema-types.ts
+++ b/packages/geoview-core/src/geo/map/map-schema-types.ts
@@ -10,7 +10,7 @@ import { AbstractGeoViewLayer, TypeGeoviewLayerType } from '@/geo/layer/geoview-
import { TypeMapMouseInfo } from '@/api/events/payloads';
import { createLocalizedString } from '@/core/utils/utilities';
import { logger } from '@/core/utils/logger';
-import { Cast } from '@/core/types/cgpv-types';
+import { Cast, LayerSetPayload } from '@/core/types/cgpv-types';
import { api } from '@/app';
/** ******************************************************************************************************************************
@@ -502,7 +502,7 @@ export type TypeLayerEntryType = 'vector' | 'vector-tile' | 'vector-heatmap' | '
*
* @returns {boolean} true if the type ascention is valid.
*/
-export const layerEntryIsGroupLayer = (verifyIfLayer: TypeLayerEntryConfig): verifyIfLayer is TypeLayerGroupEntryConfig => {
+export const layerEntryIsGroupLayer = (verifyIfLayer: ConfigBaseClass): verifyIfLayer is TypeLayerGroupEntryConfig => {
return verifyIfLayer?.entryType === 'group';
};
@@ -665,9 +665,6 @@ export class ConfigBaseClass {
/** The geoview layer instance that contains this layer configuration. */
geoviewLayerInstance?: AbstractGeoViewLayer;
- /** It is used to identified unprocessed layers and shows the final layer state */
- layerStatus?: TypeLayerStatus;
-
/** It is used to identified the process phase of the layer */
layerPhase?: string;
@@ -687,6 +684,22 @@ export class ConfigBaseClass {
/** This property is used to link the displayed layer to its layer entry config. it is not part of the schema. */
protected _olLayer: BaseLayer | LayerGroup | null = null;
+ /** It is used to identified unprocessed layers and shows the final layer state */
+ protected _layerStatus: TypeLayerStatus = 'newInstance';
+
+ protected layerStatusWeight = {
+ newInstance: 10,
+ registered: 20,
+ processing: 30,
+ processed: 40,
+ loading: 50,
+ loaded: 60,
+ error: 70,
+ };
+
+ /** Flag indicating that the loaded signal arrived before the processed one */
+ protected waitForProcessedBeforeSendingLoaded = false;
+
/**
* The class constructor.
* @param {ConfigBaseClass} layerConfig The layer configuration we want to instanciate.
@@ -745,6 +758,46 @@ export class ConfigBaseClass {
this._layerPath = ConfigBaseClass.evaluateLayerPath(this);
}
+ /**
+ * The layerId getter method for the ConfigBaseClass class and its descendant classes.
+ */
+ get layerStatus() {
+ return this._layerStatus;
+ }
+
+ /**
+ * The layerStatus setter method for the ConfigBaseClass class and its descendant classes.
+ * @param {string} newLayerStatus The new layerId value.
+ */
+ set layerStatus(newLayerStatus: TypeLayerStatus) {
+ if (
+ newLayerStatus === 'loaded' &&
+ !layerEntryIsGroupLayer(this) &&
+ !this.IsGreaterThanOrEqualTo('loading') &&
+ !this.waitForProcessedBeforeSendingLoaded
+ ) {
+ this.waitForProcessedBeforeSendingLoaded = true;
+ return;
+ }
+ if (!this.IsGreaterThanOrEqualTo(newLayerStatus)) {
+ this._layerStatus = newLayerStatus;
+ // TODO: layerPhase property will be removed soon. We must not use it anymore.
+ this.geoviewLayerInstance!.setLayerPhase(newLayerStatus, this.layerPath);
+ api.event.emit(
+ // TODO: Change createLayerSetChangeLayerStatusPayload events for a direct function call.
+ LayerSetPayload.createLayerSetChangeLayerStatusPayload(this.geoviewLayerInstance!.mapId, this.layerPath, newLayerStatus)
+ );
+ }
+ if (newLayerStatus === 'processed' && this.waitForProcessedBeforeSendingLoaded) this.layerStatus = 'loaded';
+
+ if (
+ this._layerStatus === 'loaded' &&
+ this.parentLayerConfig &&
+ this.geoviewLayerInstance!.allLayerStatusAreGreaterThanOrEqualTo('loaded', [this.parentLayerConfig as TypeLayerGroupEntryConfig])
+ )
+ (this.parentLayerConfig as TypeLayerGroupEntryConfig).layerStatus = 'loaded';
+ }
+
/**
* Register the layer identifier. Duplicate identifier are not allowed.
*
@@ -755,9 +808,9 @@ export class ConfigBaseClass {
const { registeredLayers } = api.maps[this.geoviewLayerInstance!.mapId].layer;
if (registeredLayers[this.layerPath]) return false;
(registeredLayers[this.layerPath] as ConfigBaseClass) = this;
- if (!this.layerStatus) this.geoviewLayerInstance!.setLayerStatus('registered', this.layerPath);
if (this.entryType !== 'group')
(this.geoviewLayerInstance as AbstractGeoViewLayer).registerToLayerSets(Cast(this));
+ this.layerStatus = 'registered';
return true;
}
@@ -772,6 +825,18 @@ export class ConfigBaseClass {
this.geoviewLayerInstance!.layerPathAssociatedToTheGeoviewLayer = layerPath || this.layerPath;
return this.geoviewLayerInstance!;
}
+
+ /**
+ * This method compares the internal layer status of the config with the layer status passed as a parameter and it
+ * returns true if the internal value is greater or equal to the value of the parameter.
+ *
+ * @param {TypeLayerStatus} layerStatus The layer status to compare with the internal value of the config.
+ *
+ * @returns {boolean} Returns true if the internal value is greater or equal than the value of the parameter.
+ */
+ IsGreaterThanOrEqualTo(layerStatus: TypeLayerStatus): boolean {
+ return this.layerStatusWeight[this.layerStatus] >= this.layerStatusWeight[layerStatus];
+ }
}
/** ******************************************************************************************************************************
@@ -830,12 +895,12 @@ export abstract class TypeBaseLayerEntryConfig extends ConfigBaseClass {
const loadEndListener = () => {
this.loadedFunction();
this.geoviewLayerInstance!.setLayerPhase('loaded', this.layerPath);
- this.geoviewLayerInstance!.setLayerStatus('loaded', this.layerPath);
+ this.layerStatus = 'loaded';
this._olLayer!.get('source').un(`${loadEndListenerType}loaderror`, loadErrorListener);
};
loadErrorListener = () => {
- this.geoviewLayerInstance!.setLayerStatus('error', this.layerPath);
+ this.layerStatus = 'error';
this._olLayer!.get('source').un(`${loadEndListenerType}loadend`, loadEndListener);
};
@@ -873,6 +938,8 @@ export abstract class TypeBaseLayerEntryConfig extends ConfigBaseClass {
// Update registration based on metadata that were read since the first registration.
this.geoviewLayerInstance?.registerToLayerSets(this);
this.geoviewLayerInstance?.setVisible(this.initialSettings?.visible !== 'no', this.layerPath);
+ if (this._layerStatus === 'loaded')
+ api.event.emit(LayerSetPayload.createLayerSetChangeLayerStatusPayload(this.geoviewLayerInstance!.mapId, this.layerPath, 'loaded'));
}
}
@@ -1319,12 +1386,6 @@ export class TypeTileLayerEntryConfig extends TypeBaseLayerEntryConfig {
* configuration will handle bilangual informations.
*/
export class TypeGeocoreLayerEntryConfig extends ConfigBaseClass {
- /** This attribute from ConfigBaseClass is not used by groups. */
- declare layerStatus: never;
-
- /** This attribute from ConfigBaseClass is not used by groups. */
- declare layerPhase: never;
-
/** This attribute from ConfigBaseClass is not used by groups. */
declare isMetadataLayerGroup: never;
@@ -1401,12 +1462,6 @@ export type TypeSourceGeocoreConfig = {
* Type used to define a layer group.
*/
export class TypeLayerGroupEntryConfig extends ConfigBaseClass {
- /** This attribute from ConfigBaseClass is not used by groups. */
- declare layerStatus: never;
-
- /** This attribute from ConfigBaseClass is not used by groups. */
- declare layerPhase: never;
-
/** Tag used to link the entry to a specific schema is not used by groups. */
declare schemaTag: never;
diff --git a/packages/geoview-core/src/geo/map/map-viewer.ts b/packages/geoview-core/src/geo/map/map-viewer.ts
index 0086dc3881b..a61c0195db8 100644
--- a/packages/geoview-core/src/geo/map/map-viewer.ts
+++ b/packages/geoview-core/src/geo/map/map-viewer.ts
@@ -193,7 +193,7 @@ export class MapViewer {
MapEventProcessor.setLayerZIndices(this.mapId);
// If metadata are processed
- if (geoviewLayer.allLayerStatusAreIn(['processed', 'loading', 'loaded', 'error'])) {
+ if (geoviewLayer.allLayerStatusAreGreaterThanOrEqualTo('processed')) {
api.event.emit(GeoViewLayerPayload.createTestGeoviewLayersPayload('run cgpv.init callback?'));
}
}
@@ -214,7 +214,7 @@ export class MapViewer {
mapIsReady(): boolean {
if (this.layer === undefined) return false;
return !Object.keys(this.layer.geoviewLayers).find((geoviewLayerId) => {
- return !this.layer.geoviewLayers[geoviewLayerId].allLayerStatusAreIn(['loaded', 'error']);
+ return !this.layer.geoviewLayers[geoviewLayerId].allLayerStatusAreGreaterThanOrEqualTo('loaded');
});
}
@@ -234,7 +234,7 @@ export class MapViewer {
let allGeoviewLayerReady =
this.mapFeaturesConfig.map.listOfGeoviewLayerConfig?.length === 0 || Object.keys(geoviewLayers).length !== 0;
Object.keys(geoviewLayers).forEach((geoviewLayerId) => {
- const layerIsReady = geoviewLayers[geoviewLayerId].allLayerStatusAreIn(['processed', 'error', 'loaded']);
+ const layerIsReady = geoviewLayers[geoviewLayerId].allLayerStatusAreGreaterThanOrEqualTo('processed');
logger.logTraceDetailed('map-viewer.mapReady? geoview layer ready?', geoviewLayerId, layerIsReady);
allGeoviewLayerReady &&= layerIsReady;
});
diff --git a/packages/geoview-core/src/geo/utils/feature-info-layer-set.ts b/packages/geoview-core/src/geo/utils/feature-info-layer-set.ts
index 43ba4120437..18ed7f0184c 100644
--- a/packages/geoview-core/src/geo/utils/feature-info-layer-set.ts
+++ b/packages/geoview-core/src/geo/utils/feature-info-layer-set.ts
@@ -4,10 +4,11 @@ import debounce from 'lodash/debounce';
import { EVENT_NAMES } from '@/api/events/event-types';
import {
GetFeatureInfoPayload,
+ PayloadBaseClass,
payloadIsQueryResult,
- TypeFeatureInfoResultsSet,
+ TypeFeatureInfoResultSet,
+ payloadIsLayerSetChangeLayerStatus,
payloadIsAMapMouseEvent,
- payloadIsALngLat,
ArrayOfEventTypes,
TypeLayerData,
EventType,
@@ -18,7 +19,9 @@ import { LayerSet } from './layer-set';
import { FeatureInfoEventProcessor } from '@/api/event-processors/event-processor-children/feature-info-event-processor';
import { logger } from '@/core/utils/logger';
import { getLocalizedValue } from '@/core/utils/utilities';
-import { Coordinate, TypeQueryStatus, payloadIsFeatureInfoLayersetUpdated, payloadIsGetAllLayerFeatures } from '@/core/types/cgpv-types';
+import { Coordinate, TypeLayerEntryConfig, TypeQueryStatus, payloadIsGetAllLayerFeatures } from '@/core/types/cgpv-types';
+
+type TypeFeatureInfoLayerSetInstance = { [mapId: string]: FeatureInfoLayerSet };
/** ***************************************************************************************************************************
* A class to hold a set of layers associated with an array of TypeArrayOfFeatureInfoEntries. When this class is instantiated,
@@ -28,23 +31,12 @@ import { Coordinate, TypeQueryStatus, payloadIsFeatureInfoLayersetUpdated, paylo
*
* @class FeatureInfoLayerSet
*/
-export class FeatureInfoLayerSet {
+export class FeatureInfoLayerSet extends LayerSet {
/** Private static variable to keep the single instance that can be created by this class for a mapId (see singleton design pattern) */
- private static featureInfoLayerSetInstance: {
- [mapId: string]: FeatureInfoLayerSet;
- } = {};
-
- /** The map identifier the layer set belongs to. */
- private mapId: string;
-
- /** The layer set object. */
- private layerSet: LayerSet;
-
- /** Flag used to disable hover event for the entire layerSet */
- private disableHover = false;
+ private static featureInfoLayerSetInstance: TypeFeatureInfoLayerSetInstance = {};
/** An object containing the result sets indexed using the layer path */
- resultsSet: TypeFeatureInfoResultsSet = {};
+ declare resultSet: TypeFeatureInfoResultSet;
/** ***************************************************************************************************************************
* The class constructor that instanciate a set of layer.
@@ -53,155 +45,187 @@ export class FeatureInfoLayerSet {
*
*/
private constructor(mapId: string) {
- /* *********************************************************************************************************************** */
- // This function determines whether a layer can be registered.
- const registrationConditionFunction = (layerPath: string): boolean => {
+ super(mapId, `${mapId}/FeatureInfoLayerSet`, {});
+ this.setRegistrationConditionFunction();
+ this.setUserRegistrationInitFunction();
+ this.setMapClickListener();
+ this.setMapHoverListener();
+ this.setQueryResultListener();
+ }
+
+ /* **************************************************************************************************************************
+ * This function determines whether a layer can be registered or not.
+ */
+ setRegistrationConditionFunction() {
+ this.registrationConditionFunction = (layerPath: string): boolean => {
// Log
- logger.logTraceCore('FEATURE-INFO-LAYER-SET - registration condition...', layerPath, Object.keys(this.resultsSet));
+ logger.logTraceCore('FEATURE-INFO-LAYER-SET setRegistrationConditionFunction', layerPath, Object.keys(this.resultSet));
- const layerConfig = api.maps[mapId].layer.registeredLayers[layerPath];
+ const layerConfig = api.maps[this.mapId].layer.registeredLayers[layerPath];
const queryable = layerConfig?.source?.featureInfo?.queryable;
return !!queryable;
};
+ }
- /* *********************************************************************************************************************** */
- // Still in the constructor
- // This function is used to initialise the layer path entries of the layer set.
- const registrationUserInitialisation = (layerPath: string) => {
+ /** ***************************************************************************************************************************
+ * Define the initialization function that the registration process will use to create a new entry in the layer set for a
+ * specific layer path.
+ */
+ setUserRegistrationInitFunction() {
+ this.registrationUserInitialisation = (layerPath: string) => {
// Log
- logger.logTraceCore('FEATURE-INFO-LAYER-SET - initializing...', layerPath, Object.keys(this.resultsSet));
+ logger.logTraceCore('FEATURE-INFO-LAYER-SET setUserRegistrationInitFunction', layerPath, Object.keys(this.resultSet));
- const layerConfig = api.maps[mapId].layer.registeredLayers[layerPath];
- this.resultsSet[layerPath] = {
+ const layerConfig = api.maps[this.mapId].layer.registeredLayers[layerPath];
+ this.resultSet[layerPath] = {
layerStatus: layerConfig.layerStatus!,
- layerPhase: layerConfig.layerPhase!,
data: {},
- layerName: getLocalizedValue(layerConfig.layerName, mapId) ?? '',
+ layerName: getLocalizedValue(layerConfig.layerName, this.mapId) ?? '',
};
ArrayOfEventTypes.forEach((eventType) => {
- this.resultsSet[layerPath].data[eventType] = {
- layerName: getLocalizedValue(layerConfig.layerName, mapId) ?? '',
+ this.resultSet[layerPath].data[eventType] = {
+ layerName: getLocalizedValue(layerConfig.layerName, this.mapId) ?? '',
layerStatus: layerConfig.layerStatus!,
eventListenerEnabled: true,
queryStatus: 'processed',
features: [],
layerPath,
};
- FeatureInfoEventProcessor.propagateFeatureInfoToStore(mapId, layerPath, eventType, this.resultsSet);
+ if (eventType === 'all-features') this.setQueryAllFeaturesListener(layerConfig);
+ FeatureInfoEventProcessor.propagateFeatureInfoToStore(this.mapId, layerPath, eventType, this.resultSet);
});
-
- api.event.on(
- EVENT_NAMES.GET_FEATURE_INFO.GET_ALL_LAYER_FEATURES,
- (payload) => {
- // Log
- logger.logTraceCoreAPIEvent('FEATURE-INFO-LAYER-SET - GET_ALL_LAYER_FEATURES', this.mapId, payload);
-
- if (payloadIsGetAllLayerFeatures(payload)) {
- if (!this.resultsSet[layerPath].data['all-features']!.eventListenerEnabled) return;
- const dataForEventType = this.resultsSet[layerPath].data['all-features'] as TypeLayerData;
- if (layerConfig.layerStatus === 'loaded') {
- dataForEventType.features = undefined;
- dataForEventType.queryStatus = 'processing';
- } else {
- dataForEventType.features = null;
- dataForEventType.queryStatus = 'error';
- FeatureInfoEventProcessor.propagateFeatureInfoToStore(mapId, layerPath, 'all-features', this.resultsSet);
- return;
- }
-
- api.event.emit(GetFeatureInfoPayload.createQueryLayerPayload(`${this.mapId}/${layerPath}`, 'all', layerPath));
- FeatureInfoEventProcessor.propagateFeatureInfoToStore(mapId, layerPath, 'all-features', this.resultsSet);
- }
- },
- `${mapId}/${layerPath}`
- );
- FeatureInfoEventProcessor.propagateFeatureInfoToStore(mapId, layerPath, 'click', this.resultsSet);
};
+ }
- /* *********************************************************************************************************************** */
- // Still in the constructor - initialize other properties.
- this.mapId = mapId;
- this.layerSet = new LayerSet(
- mapId,
- `${mapId}/FeatureInfoLayerSet`,
- this.resultsSet,
- registrationConditionFunction,
- registrationUserInitialisation
- );
+ /** ***************************************************************************************************************************
+ * The listener that will handle the CHANGE_LAYER_STATUS event triggered on the map.This method is called by the parent class
+ * LayerSet via the listener created by the setChangeLayerStatusListenerFunctions method.
+ *
+ * @param {PayloadBaseClass} payload The payload to process.
+ */
+ protected changeLayerStatusListenerFunctions(payload: PayloadBaseClass) {
+ if (payloadIsLayerSetChangeLayerStatus(payload)) {
+ // Log
+ logger.logTraceCoreAPIEvent('FEATURE-INFO-LAYER-SET on EVENT_NAMES.LAYER_SET.CHANGE_LAYER_STATUS', this.mapId, payload);
+
+ const { layerPath, layerStatus } = payload;
+ // if layer's status flag exists and is different than the new one
+ if (this.resultSet?.[layerPath]?.layerStatus && this.resultSet?.[layerPath]?.layerStatus !== layerStatus) {
+ if (layerStatus === 'error') delete this.resultSet[layerPath];
+ else super.changeLayerStatusListenerFunctions(payload);
+ }
+ }
+ }
- /* *********************************************************************************************************************** */
- // Still in the constructor
- // Listen to "map click" and send a query layers event to queryable layers. These layers will return a result set
+ /** ***************************************************************************************************************************
+ * Set the listener function that will monitor events sent when we want to retreive all features in the context specified for
+ * a specific layer. For the moment, the context can only be 'all' and the query will return all the features on the layer.
+ * Next generation of this listener will be able to query for features 'using_a_bounding_box' or 'using_a_a polygon' as value
+ * for the context.
+ */
+ private setQueryAllFeaturesListener(layerConfig: TypeLayerEntryConfig) {
api.event.on(
- EVENT_NAMES.GET_FEATURE_INFO.FEATURE_INFO_LAYERSET_UPDATED,
+ EVENT_NAMES.GET_FEATURE_INFO.QUERY_ALL_FEATURES,
(payload) => {
- // Log
- logger.logTraceCoreAPIEvent('FEATURE-INFO-LAYER-SET - FEATURE_INFO_LAYERSET_UPDATED', this.mapId, payload);
+ if (payloadIsGetAllLayerFeatures(payload)) {
+ // Log
+ logger.logTraceCoreAPIEvent('FEATURE-INFO-LAYER-SET on EVENT_NAMES.GET_FEATURE_INFO.QUERY_ALL_FEATURES', this.mapId);
+
+ const { queryType } = payload;
+ if (!this.resultSet[layerConfig.layerPath].data['all-features']!.eventListenerEnabled) return;
+ const dataForEventType = this.resultSet[layerConfig.layerPath].data['all-features'] as TypeLayerData;
+ if (layerConfig.layerStatus === 'loaded') {
+ dataForEventType.features = undefined;
+ dataForEventType.queryStatus = 'processing';
+ } else {
+ dataForEventType.features = null;
+ dataForEventType.queryStatus = 'error';
+ FeatureInfoEventProcessor.propagateFeatureInfoToStore(this.mapId, layerConfig.layerPath, 'all-features', this.resultSet);
+ return;
+ }
- if (payloadIsFeatureInfoLayersetUpdated(payload)) {
- const { layerPath, resultsSet, layerStatus } = payload;
- if (layerStatus === 'error') delete resultsSet[layerPath];
+ api.event.emit(
+ GetFeatureInfoPayload.createQueryLayerPayload(`${this.mapId}/${layerConfig.layerPath}`, queryType, layerConfig.layerPath)
+ );
+ FeatureInfoEventProcessor.propagateFeatureInfoToStore(this.mapId, layerConfig.layerPath, 'all-features', this.resultSet);
}
},
- `${mapId}/FeatureInfoLayerSet`
+ `${this.mapId}/${layerConfig.layerPath}`
);
+ FeatureInfoEventProcessor.propagateFeatureInfoToStore(this.mapId, layerConfig.layerPath, 'click', this.resultSet);
+ }
- /* *********************************************************************************************************************** */
- // Still in the constructor
- // Listen to "map click" and send a query layers event to queryable layers. These layers will return a result set
- // of features.
- api.event.on(
- EVENT_NAMES.MAP.EVENT_MAP_SINGLE_CLICK,
- (payload) => {
- // Log
- logger.logTraceCoreAPIEvent('FEATURE-INFO-LAYER-SET - EVENT_MAP_SINGLE_CLICK', this.mapId, payload);
+ /* **************************************************************************************************************************
+ * Private method used to emit a query layer event for all layers in the result set that are loaded. Layers that has an error
+ * are set with an undefined features array and a queryStatus equal to 'error'.
+ *
+ * @param {EventType} eventType The event type (ex.: "click" | "hover" | "crosshaire-enter" | "all-features")
+ * @param {QueryType} queryType The query type (ex.: "all" | "at_pixel" | "at_coordinate" | "at_long_lat", ...)
+ * @param {Coordinate} coordinate The coordinate of the event
+ */
+ private createQueryLayerPayloadFor = (eventType: EventType, queryType: QueryType, coordinate: Coordinate): void => {
+ // Reinitialize the resultSet
+ // Loop on each layer path in the resultSet
+ Object.keys(this.resultSet).forEach((layerPath) => {
+ const layerConfig = api.maps[this.mapId].layer.registeredLayers[layerPath];
+ const dataForEventType = this.resultSet[layerPath].data[eventType] as TypeLayerData;
+ if (!dataForEventType.eventListenerEnabled) return;
+ if (layerConfig.layerStatus === 'loaded') {
+ dataForEventType.features = undefined;
+ dataForEventType.queryStatus = 'processing';
+ } else {
+ dataForEventType.features = null;
+ dataForEventType.queryStatus = 'error';
+ }
- if (payloadIsAMapMouseEvent(payload)) {
- this.createQueryLayerPayload('click', 'at_long_lat', payload.coordinates.lnglat);
- }
- },
- this.mapId
- );
+ if (dataForEventType.eventListenerEnabled && dataForEventType.queryStatus !== ('error' as TypeQueryStatus)) {
+ api.event.emit(GetFeatureInfoPayload.createQueryLayerPayload(`${this.mapId}/${layerPath}`, queryType, coordinate, eventType));
+ }
+ });
+ };
- /* *********************************************************************************************************************** */
- // Still in the constructor
- // ! Do we want to keep this type of event? I think we already said that we want to remove it.
- // TODO: Refactor - This doesn't seem to be used at all indeed?
+ /** ***************************************************************************************************************************
+ * Listen to "map click" and send a query layers event to queryable layers. These layers will return a result set of features.
+ */
+ setMapClickListener() {
api.event.on(
- EVENT_NAMES.MAP.EVENT_MAP_CROSSHAIR_ENTER,
+ EVENT_NAMES.MAP.EVENT_MAP_SINGLE_CLICK,
(payload) => {
- // Log
- logger.logTraceCoreAPIEvent('FEATURE-INFO-LAYER-SET - EVENT_MAP_CROSSHAIR_ENTER', this.mapId, payload);
+ if (payloadIsAMapMouseEvent(payload)) {
+ // Log
+ logger.logTraceCoreAPIEvent('FEATURE-INFO-LAYER-SET on EVENT_NAMES.MAP.EVENT_MAP_SINGLE_CLICK', this.mapId, payload);
- if (payloadIsALngLat(payload)) {
- this.createQueryLayerPayload('crosshaire-enter', 'at_long_lat', payload.lnglat);
+ this.createQueryLayerPayloadFor('click', 'at_long_lat', payload.coordinates.lnglat);
}
},
this.mapId
);
+ }
- /* *********************************************************************************************************************** */
- // Still in the constructor
- // Listen to "hover" events and send a query layers event to queryable layers. These layers will return a result
- // set of features.
+ /** ***************************************************************************************************************************
+ * Listen to "map hover" and send a query layers event to queryable layers. These layers will return a result set of features.
+ */
+ setMapHoverListener() {
api.event.on(
EVENT_NAMES.MAP.EVENT_MAP_POINTER_MOVE,
debounce((payload) => {
// Log
- logger.logTraceCoreAPIEvent('FEATURE-INFO-LAYER-SET - EVENT_MAP_POINTER_MOVE', this.mapId, payload);
+ logger.logTraceCoreAPIEvent('FEATURE-INFO-LAYER-SET on EVENT_NAMES.MAP.EVENT_MAP_POINTER_MOVE', this.mapId, payload);
if (payloadIsAMapMouseEvent(payload)) {
- this.createQueryLayerPayload('hover', 'at_pixel', payload.coordinates.pixel);
+ this.createQueryLayerPayloadFor('hover', 'at_pixel', payload.coordinates.pixel);
}
}, 750),
this.mapId
);
+ }
- /* *********************************************************************************************************************** */
- // Still in the constructor
- // Listen to "query result" events and send a all query done event when all the layers have returned their result
- // set of features.
+ /** ***************************************************************************************************************************
+ * Listen to "query result" events and send an all query done event when all the layers have returned their result set of
+ * features.
+ */
+ private setQueryResultListener() {
api.event.on(
EVENT_NAMES.GET_FEATURE_INFO.QUERY_RESULT,
(payload) => {
@@ -210,31 +234,31 @@ export class FeatureInfoLayerSet {
if (payloadIsQueryResult(payload)) {
const { layerPath, queryType, arrayOfRecords, eventType } = payload;
- const layerConfig = api.maps[mapId].layer.registeredLayers[layerPath];
- if (this.resultsSet?.[layerPath]?.data) {
- const dataForEventType = this.resultsSet[layerPath].data[eventType] as TypeLayerData;
+ const layerConfig = api.maps[this.mapId].layer.registeredLayers[layerPath];
+ if (this.resultSet?.[layerPath]?.data) {
+ const dataForEventType = this.resultSet[layerPath].data[eventType] as TypeLayerData;
dataForEventType.features = arrayOfRecords;
dataForEventType.layerStatus = layerConfig.layerStatus!;
// When property features is undefined, we are waiting for the query result.
// when Array.isArray(features) is true, the features property contains the query result.
// when property features is null, the query ended with an error.
dataForEventType.queryStatus = arrayOfRecords === null ? 'error' : 'processed';
- FeatureInfoEventProcessor.propagateFeatureInfoToStore(mapId, layerPath, eventType, this.resultsSet);
+ FeatureInfoEventProcessor.propagateFeatureInfoToStore(this.mapId, layerPath, eventType, this.resultSet);
}
- const allDone = Object.keys(this.resultsSet).reduce((doneFlag, layerPathToTest) => {
- return doneFlag && this.resultsSet[layerPathToTest].data[eventType]?.features !== undefined;
+ const allDone = Object.keys(this.resultSet).reduce((doneFlag, layerPathToTest) => {
+ return doneFlag && this.resultSet[layerPathToTest].data[eventType]?.features !== undefined;
}, true);
if (allDone) {
api.event.emit(
GetFeatureInfoPayload.createAllQueriesDonePayload(
- this.layerSet.layerSetId,
+ this.layerSetId,
eventType,
layerPath,
queryType,
- this.layerSet.layerSetId,
- this.resultsSet
+ this.layerSetId,
+ this.resultSet
)
);
}
@@ -242,34 +266,7 @@ export class FeatureInfoLayerSet {
},
this.mapId
);
- } // constructor ends here
-
- /* **************************************************************************************************************************
- * Still in the constructor
- * @param {EventType} eventType The event type (ex.: "click" | "hover" | "crosshaire-enter" | "all-features")
- * @param {QueryType} queryType The query type (ex.: "all" | "at_pixel" | "at_coordinate" | "at_long_lat", ...)
- * @param {Coordinate} coordinate The coordinate of the event
- */
- createQueryLayerPayload = (eventType: EventType, queryType: QueryType, coordinate: Coordinate): void => {
- // Reinitialize the resultsSet
- // Loop on each layer path in the resultsSet
- Object.keys(this.resultsSet).forEach((layerPath) => {
- const layerConfig = api.maps[this.mapId].layer.registeredLayers[layerPath];
- const dataForEventType = this.resultsSet[layerPath].data[eventType] as TypeLayerData;
- if (!dataForEventType.eventListenerEnabled) return;
- if (layerConfig.layerStatus === 'loaded') {
- dataForEventType.features = undefined;
- dataForEventType.queryStatus = 'processing';
- } else {
- dataForEventType.features = null;
- dataForEventType.queryStatus = 'error';
- }
-
- if (dataForEventType.eventListenerEnabled && dataForEventType.queryStatus !== ('error' as TypeQueryStatus)) {
- api.event.emit(GetFeatureInfoPayload.createQueryLayerPayload(`${this.mapId}/${layerPath}`, queryType, coordinate, eventType));
- }
- });
- };
+ }
/**
* Helper function used to launch the query on a layer to get all of its feature information
@@ -279,11 +276,9 @@ export class FeatureInfoLayerSet {
*/
// TODO: (futur development) The queryType is a door opened to allow the triggering using a bounding box or a polygon.
triggerGetAllFeatureInfo(layerPath: string, queryType: QueryType = 'all') {
- if (this.resultsSet[layerPath]) {
+ if (this.resultSet[layerPath])
api.event.emit(GetFeatureInfoPayload.createGetAllLayerFeaturesPayload(`${this.mapId}/${layerPath}`, queryType));
- } else {
- logger.logError(`The triggerGetAllFeatureInfo method cannot be used on an inexistant layer path (${layerPath})`);
- }
+ else logger.logError(`The triggerGetAllFeatureInfo method cannot be used on an inexistant layer path (${layerPath})`);
}
/**
@@ -293,10 +288,10 @@ export class FeatureInfoLayerSet {
* @param {string} layerPath Optional parameter used to enable only one layer
*/
enableClickListener(layerPath?: string) {
- if (layerPath) this.resultsSet[layerPath].data.click!.eventListenerEnabled = true;
+ if (layerPath) this.resultSet[layerPath].data.click!.eventListenerEnabled = true;
else
- Object.keys(this.resultsSet).forEach((key: string) => {
- this.resultsSet[key].data.click!.eventListenerEnabled = true;
+ Object.keys(this.resultSet).forEach((key: string) => {
+ this.resultSet[key].data.click!.eventListenerEnabled = true;
});
}
@@ -307,10 +302,10 @@ export class FeatureInfoLayerSet {
* @param {string} layerPath Optional parameter used to disable only one layer
*/
disableClickListener(layerPath?: string) {
- if (layerPath) this.resultsSet[layerPath].data.click!.eventListenerEnabled = false;
+ if (layerPath) this.resultSet[layerPath].data.click!.eventListenerEnabled = false;
else
- Object.keys(this.resultsSet).forEach((key: string) => {
- this.resultsSet[key].data.click!.eventListenerEnabled = false;
+ Object.keys(this.resultSet).forEach((key: string) => {
+ this.resultSet[key].data.click!.eventListenerEnabled = false;
});
}
@@ -323,12 +318,12 @@ export class FeatureInfoLayerSet {
* @returns {boolean | undefined} The flag value for the map or layer.
*/
isClickListenerEnabled(layerPath?: string): boolean | undefined {
- if (layerPath) return this.resultsSet[layerPath].data.click!.eventListenerEnabled;
+ if (layerPath) return !!this.resultSet?.[layerPath]?.data?.click?.eventListenerEnabled;
let returnValue: boolean | undefined;
- Object.keys(this.resultsSet).forEach((key: string, i) => {
- if (i === 0) returnValue = this.resultsSet[key].data.click!.eventListenerEnabled;
- if (returnValue !== this.resultsSet[key].data.click!.eventListenerEnabled) returnValue = undefined;
+ Object.keys(this.resultSet).forEach((key: string, i) => {
+ if (i === 0) returnValue = this.resultSet[key].data.click!.eventListenerEnabled;
+ if (returnValue !== this.resultSet[key].data.click!.eventListenerEnabled) returnValue = undefined;
});
return returnValue;
}
@@ -340,10 +335,10 @@ export class FeatureInfoLayerSet {
* @param {string} layerPath Optional parameter used to enable only one layer
*/
enableHoverListener(layerPath?: string) {
- if (layerPath) this.resultsSet[layerPath].data.hover!.eventListenerEnabled = true;
+ if (layerPath) this.resultSet[layerPath].data.hover!.eventListenerEnabled = true;
else
- Object.keys(this.resultsSet).forEach((key: string) => {
- this.resultsSet[key].data.hover!.eventListenerEnabled = true;
+ Object.keys(this.resultSet).forEach((key: string) => {
+ this.resultSet[key].data.hover!.eventListenerEnabled = true;
});
}
@@ -354,10 +349,10 @@ export class FeatureInfoLayerSet {
* @param {string} layerPath Optional parameter used to disable only one layer
*/
disableHoverListener(layerPath?: string) {
- if (layerPath) this.resultsSet[layerPath].data.hover!.eventListenerEnabled = false;
+ if (layerPath) this.resultSet[layerPath].data.hover!.eventListenerEnabled = false;
else
- Object.keys(this.resultsSet).forEach((key: string) => {
- this.resultsSet[key].data.hover!.eventListenerEnabled = false;
+ Object.keys(this.resultSet).forEach((key: string) => {
+ this.resultSet[key].data.hover!.eventListenerEnabled = false;
});
}
@@ -370,12 +365,12 @@ export class FeatureInfoLayerSet {
* @returns {boolean | undefined} The flag value for the map or layer.
*/
isHoverListenerEnabled(layerPath?: string): boolean | undefined {
- if (layerPath) return this.resultsSet[layerPath].data.hover!.eventListenerEnabled;
+ if (layerPath) return !!this.resultSet?.[layerPath]?.data?.hover?.eventListenerEnabled;
let returnValue: boolean | undefined;
- Object.keys(this.resultsSet).forEach((key: string, i) => {
- if (i === 0) returnValue = this.resultsSet[key].data.hover!.eventListenerEnabled;
- if (returnValue !== this.resultsSet[key].data.hover!.eventListenerEnabled) returnValue = undefined;
+ Object.keys(this.resultSet).forEach((key: string, i) => {
+ if (i === 0) returnValue = this.resultSet[key].data.hover!.eventListenerEnabled;
+ if (returnValue !== this.resultSet[key].data.hover!.eventListenerEnabled) returnValue = undefined;
});
return returnValue;
}
diff --git a/packages/geoview-core/src/geo/utils/layer-set.ts b/packages/geoview-core/src/geo/utils/layer-set.ts
index 1c083a61717..ff0109f2682 100644
--- a/packages/geoview-core/src/geo/utils/layer-set.ts
+++ b/packages/geoview-core/src/geo/utils/layer-set.ts
@@ -1,14 +1,11 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
-import { MapEventProcessor } from '@/api/event-processors/event-processor-children/map-event-processor';
import { EVENT_NAMES } from '@/api/events/event-types';
import {
LayerSetPayload,
+ PayloadBaseClass,
payloadIsLayerRegistration,
payloadIsLayerSetChangeLayerStatus,
- TypeResultsSet,
- GetLegendsPayload,
- PayloadBaseClass,
- GetFeatureInfoPayload,
+ TypeResultSet,
} from '@/api/events/payloads';
import { api } from '@/app';
import { logger } from '@/core/utils/logger';
@@ -24,94 +21,109 @@ import { createLocalizedString, getLocalizedValue } from '@/core/utils/utilities
*/
export class LayerSet {
/** The map identifier the layer set belongs to. */
- mapId: string;
+ protected mapId: string;
/** The layer set identifier. */
- layerSetId: string;
+ protected layerSetId: string;
/** An object containing the result sets indexed using the layer path */
- resultsSet: TypeResultsSet = {};
+ resultSet: TypeResultSet;
/** Function used to determine if the layerPath can be added to the layer set. */
- registrationConditionFunction: (layerPath: string) => boolean;
+ protected registrationConditionFunction: (layerPath: string) => boolean;
/** Function used to initialise the data property of the layer path entry. */
- registrationUserInitialisation?: (layerPath: string) => void;
+ protected registrationUserInitialisation?: (layerPath: string) => void;
/** Sequence number to append to the layer name when we declare a layer as anonymous. */
- anonymousSequenceNumber = 1;
+ protected anonymousSequenceNumber = 1;
/** ***************************************************************************************************************************
* The class constructor that instanciate a set of layer.
*
* @param {string} mapId The map identifier the layer set belongs to.
* @param {string} layerSetIdentifier The layer set identifier.
- * @param {TypeResultsSet} resultsSet An object that will contain the result sets indexed using the layer path.
+ * @param {TypeResultSet} resultSet An object that will contain the result sets indexed using the layer path.
* @param {(layerPath: string) => boolean} registrationConditionFunction A function to decide if the layer can be added.
* @param {(layerPath: string) => void} registrationUserInitialisation A function to initialise the data property of the layer path entry.
*/
constructor(
mapId: string,
layerSetIdentifier: string,
- resultsSet: TypeResultsSet,
- registrationConditionFunction: (layerPath: string) => boolean,
+ resultSet: TypeResultSet,
+ registrationConditionFunction?: true | ((layerPath: string) => boolean),
registrationUserInitialisation?: (layerPath: string) => void
) {
this.mapId = mapId;
this.layerSetId = layerSetIdentifier;
- this.resultsSet = resultsSet;
- this.registrationConditionFunction = registrationConditionFunction;
+ this.resultSet = resultSet;
+ this.registrationConditionFunction =
+ registrationConditionFunction === true || registrationConditionFunction === undefined
+ ? () => {
+ return true;
+ }
+ : registrationConditionFunction;
this.registrationUserInitialisation = registrationUserInitialisation;
+ this.setChangeLayerStatusListenerFunctions();
+ this.setLayerRegistrationListenerFunctions();
+ }
- const changeLayerStatusListenerFunctions = (payload: PayloadBaseClass) => {
+ /** ***************************************************************************************************************************
+ * The listener that will handle the CHANGE_LAYER_STATUS event triggered on the map.
+ *
+ * @param {PayloadBaseClass} payload The payload to process.
+ */
+ protected changeLayerStatusListenerFunctions(payload: PayloadBaseClass) {
+ if (payloadIsLayerSetChangeLayerStatus(payload)) {
// Log
- logger.logTraceCoreAPIEvent('LAYER-SET - CHANGE_LAYER_STATUS', this.mapId, payload);
+ logger.logTraceCoreAPIEvent('LAYER-SET on EVENT_NAMES.LAYER_SET.CHANGE_LAYER_STATUS', this.mapId, payload);
- if (payloadIsLayerSetChangeLayerStatus(payload)) {
- const { layerPath, layerStatus } = payload;
- if (layerStatus === 'error' && resultsSet[layerPath]) {
- api.event.emit(LayerSetPayload.createLayerSetUpdatedPayload(`${mapId}/LegendsLayerSetStatusChanged`, this.resultsSet, layerPath));
- // eslint-disable-next-line no-param-reassign
- resultsSet[layerPath].layerStatus = 'error';
- api.event.emit(
- GetFeatureInfoPayload.createFeatureInfoLayersetUpdatedPayload(
- `${mapId}/FeatureInfoLayerSet`,
- layerPath,
- resultsSet,
- layerStatus
- )
- );
- } else if (this.resultsSet[layerPath]) {
- const layerConfig = api.maps[mapId].layer.registeredLayers[layerPath];
- if (this.resultsSet[layerPath].layerStatus !== layerStatus) {
- this.resultsSet[layerPath].layerStatus = layerStatus;
- if (!this.resultsSet[layerPath].layerName) {
- this.resultsSet[layerPath].layerName =
- getLocalizedValue(layerConfig.layerName, mapId) ||
- getLocalizedValue(
- {
- en: `Anonymous Layer ${this.anonymousSequenceNumber}`,
- fr: `Couche Anonyme ${this.anonymousSequenceNumber}`,
- },
- mapId
- );
- this.anonymousSequenceNumber++;
- }
- // Synchronize the layer name property in the config and the layer set object when the geoview instance is ready.
- if (layerConfig.geoviewLayerInstance!.allLayerStatusAreIn(['processed', 'error'], [layerConfig]))
- if (layerConfig.layerName) this.resultsSet[layerPath].layerName = getLocalizedValue(layerConfig.layerName, mapId);
- else layerConfig.layerName = createLocalizedString(this.resultsSet[layerPath].layerName!);
- api.event.emit(LayerSetPayload.createLayerSetUpdatedPayload(this.layerSetId, this.resultsSet, layerPath));
- if (this.layerSetId === `${mapId}/LegendsLayerSet`)
- // LegendLayerSet is the absolute reference for finding out whether a layer has been loaded or is in error. Then, every
- // time we modify a layerSet in the Legend family, we have to inform the viewer that a change has occurred.
- api.event.emit(GetLegendsPayload.createLegendsLayersetUpdatedPayload(`${this.mapId}/LegendsLayerSet`, layerPath, resultsSet));
+ const { layerPath, layerStatus } = payload;
+ // if layer's status flag exists and is different than the new one
+ if (this.resultSet?.[layerPath]?.layerStatus && this.resultSet?.[layerPath]?.layerStatus !== layerStatus) {
+ this.resultSet[layerPath].layerStatus = layerStatus;
+ if (['processed', 'error'].includes(layerStatus) && !this.resultSet[layerPath].layerName) {
+ const layerConfig = api.maps[this.mapId].layer.registeredLayers[layerPath];
+ const layerName = getLocalizedValue(layerConfig.layerName, this.mapId);
+ if (layerName) this.resultSet[layerPath].layerName = layerName;
+ else {
+ this.resultSet[layerPath].layerName = getLocalizedValue(
+ {
+ en: `Anonymous Layer ${this.anonymousSequenceNumber}`,
+ fr: `Couche Anonyme ${this.anonymousSequenceNumber}`,
+ },
+ this.mapId
+ );
+ this.anonymousSequenceNumber++;
}
+
+ // Synchronize the layer name property in the config and the layer set object when the geoview instance is ready.
+ if (!layerConfig.layerName) layerConfig.layerName = createLocalizedString(this.resultSet[layerPath].layerName!);
}
+ api.event.emit(LayerSetPayload.createLayerSetUpdatedPayload(this.layerSetId, this.resultSet, layerPath));
}
- };
- api.event.on(EVENT_NAMES.LAYER_SET.CHANGE_LAYER_STATUS, changeLayerStatusListenerFunctions, this.mapId);
+ }
+ }
+ /** ***************************************************************************************************************************
+ * Set the listener that will handle the CHANGE_LAYER_STATUS event triggered on the map.
+ */
+ protected setChangeLayerStatusListenerFunctions() {
+ api.event.on(
+ EVENT_NAMES.LAYER_SET.CHANGE_LAYER_STATUS,
+ (payload) => {
+ // Logger is called in the changeLayerStatusListenerFunctions above.
+ this.changeLayerStatusListenerFunctions.call(this, payload);
+ },
+ this.mapId
+ );
+ }
+
+ /** ***************************************************************************************************************************
+ * Set the listener that will handle the LAYER_REGISTRATION event triggered on the map. Layer registration is the action of
+ * adding or deleting a layer in the layerset
+ */
+ private setLayerRegistrationListenerFunctions() {
// Register a layer to the layer set or unregister the layer when it is deleted from the map.
api.event.on(
EVENT_NAMES.LAYER_SET.LAYER_REGISTRATION,
@@ -123,38 +135,18 @@ export class LayerSet {
const { action, layerPath, layerSetId } = payload;
// update the registration of all layer sets if !payload.layerSetId or update only the specified layer set
if (!layerSetId || layerSetId === this.layerSetId) {
- if (action === 'add' && this.registrationConditionFunction(layerPath) && !(layerPath in this.resultsSet)) {
- const layerConfig = api.maps[mapId].layer.registeredLayers[layerPath];
- this.resultsSet[layerPath] = {
+ if (action === 'add' && this.registrationConditionFunction(layerPath) && !(layerPath in this.resultSet)) {
+ const layerConfig = api.maps[this.mapId].layer.registeredLayers[layerPath];
+ this.resultSet[layerPath] = {
data: undefined,
layerStatus: 'newInstance',
- layerName: getLocalizedValue(layerConfig.layerName, mapId),
+ layerName: getLocalizedValue(layerConfig.layerName, this.mapId),
};
if (this.registrationUserInitialisation) this.registrationUserInitialisation(layerPath);
- api.event.emit(LayerSetPayload.createLayerSetUpdatedPayload(this.layerSetId, this.resultsSet, layerPath));
- if (this.layerSetId === `${mapId}/LegendsLayerSet`)
- api.event.emit(
- LayerSetPayload.createLayerSetUpdatedPayload(`${mapId}/LegendsLayerSetStatusChanged`, this.resultsSet, layerPath)
- );
- if (MapEventProcessor.getMapIndexFromOrderedLayerInfo(this.mapId, layerPath) === -1) {
- if (layerConfig.parentLayerConfig) {
- const parentLayerPathArray = layerPath.split('/');
- parentLayerPathArray.pop();
- const parentLayerPath = parentLayerPathArray.join('/');
- const parentLayerIndex = MapEventProcessor.getMapIndexFromOrderedLayerInfo(this.mapId, parentLayerPath);
- const numberOfLayers = MapEventProcessor.getMapOrderedLayerInfo(this.mapId).filter((layerInfo) =>
- layerInfo.layerPath.startsWith(parentLayerPath)
- ).length;
- if (parentLayerIndex !== -1)
- MapEventProcessor.addOrderedLayerInfo(this.mapId, layerConfig, parentLayerIndex + numberOfLayers);
- else MapEventProcessor.addOrderedLayerInfo(this.mapId, layerConfig.parentLayerConfig);
- } else MapEventProcessor.addOrderedLayerInfo(this.mapId, layerConfig);
- }
- } else if (action === 'remove' && layerPath in this.resultsSet) {
- delete this.resultsSet[layerPath];
- MapEventProcessor.removeOrderedLayerInfo(this.mapId, layerPath);
- api.event.emit(LayerSetPayload.createLayerSetUpdatedPayload(this.layerSetId, this.resultsSet, layerPath));
+ } else if (action === 'remove' && layerPath in this.resultSet) {
+ delete this.resultSet[layerPath];
}
+ api.event.emit(LayerSetPayload.createLayerSetUpdatedPayload(this.layerSetId, this.resultSet, layerPath));
}
}
},
@@ -171,7 +163,7 @@ export class LayerSet {
*
* @param {string} mapId The map identifier the layer set belongs to.
* @param {string} layerSetId The layer set identifier.
- * @param {TypeResultsSet} resultsSet An object that will contain the result sets indexed using the layer path.
+ * @param {TypeResultSet} resultSet An object that will contain the result sets indexed using the layer path.
* @param {(layerPath: string) => boolean} registrationConditionFunction A function to decide if the layer can be added.
*
* @returns {LayerSet} the LayerSet object created
@@ -179,9 +171,9 @@ export class LayerSet {
static create(
mapId: string,
layerSetId: string,
- resultsSet: TypeResultsSet,
+ resultSet: TypeResultSet,
registrationConditionFunction: (layerPath: string) => boolean
): LayerSet {
- return new LayerSet(mapId, layerSetId, resultsSet, registrationConditionFunction);
+ return new LayerSet(mapId, layerSetId, resultSet, registrationConditionFunction);
}
}
diff --git a/packages/geoview-core/src/geo/utils/legends-layer-set.ts b/packages/geoview-core/src/geo/utils/legends-layer-set.ts
index f9cad35b2c2..0414f9650f4 100644
--- a/packages/geoview-core/src/geo/utils/legends-layer-set.ts
+++ b/packages/geoview-core/src/geo/utils/legends-layer-set.ts
@@ -2,15 +2,21 @@
import { EVENT_NAMES } from '@/api/events/event-types';
import {
GetLegendsPayload,
+ PayloadBaseClass,
payloadIsLegendInfo,
- TypeLegendResultsSet,
+ TypeLegendResultSet,
+ TypeResultSet,
+ LayerSetPayload,
+ payloadIsLayerSetChangeLayerStatus,
payloadIsLayerSetUpdated,
- TypeResultsSet,
} from '@/api/events/payloads';
import { api } from '@/app';
import { LayerSet } from './layer-set';
import { LegendEventProcessor } from '@/api/event-processors/event-processor-children/legend-event-processor';
import { logger } from '@/core/utils/logger';
+import { MapEventProcessor } from '@/api/event-processors/event-processor-children/map-event-processor';
+
+type TypeLegendsLayerSetInstance = { [mapId: string]: LegendsLayerSet };
/** *****************************************************************************************************************************
* A class to hold a set of layers associated with an array of TypeLegend. When this class is instantiated, all layers already
@@ -19,18 +25,12 @@ import { logger } from '@/core/utils/logger';
*
* @class LegendsLayerSet
*/
-export class LegendsLayerSet {
+export class LegendsLayerSet extends LayerSet {
/** Private static variable to keep the single instance that can be created by this class for a mapIId (see singleton design pattern) */
- private static legendsLayerSetInstance: Record = {};
-
- /** The map identifier the layer set belongs to. */
- mapId: string;
-
- /** The layer set object. */
- layerSet: LayerSet;
+ private static legendsLayerSetInstance: TypeLegendsLayerSetInstance = {};
/** An object containing the result sets indexed using the layer path */
- resultsSet: TypeLegendResultsSet = {};
+ declare resultSet: TypeLegendResultSet;
/** ***************************************************************************************************************************
* The class constructor that instanciate a set of layer.
@@ -39,77 +39,105 @@ export class LegendsLayerSet {
*
*/
private constructor(mapId: string) {
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
- const registrationConditionFunction = (layerPath: string): boolean => {
- return true;
- };
+ super(mapId, `${mapId}/LegendsLayerSet`, {});
+ this.setUserRegistrationInitFunction();
+ this.setLayerInfoListener();
+ this.setLayerSetUpdatedListener();
+ }
- // This function is used to initialise the date property of the layer path entry.
- const registrationUserInitialisation = (layerPath: string) => {
- this.resultsSet[layerPath].querySent = false;
- this.resultsSet[layerPath].data = undefined;
+ /** ***************************************************************************************************************************
+ * Define the initialization function that the registration process will use to create a new entry in the layer set for a
+ * specific layer path.
+ */
+ setUserRegistrationInitFunction() {
+ this.registrationUserInitialisation = (layerPath: string) => {
+ this.resultSet[layerPath].querySent = false;
+ this.resultSet[layerPath].data = undefined;
};
+ }
- this.mapId = mapId;
- this.layerSet = new LayerSet(
- mapId,
- `${mapId}/LegendsLayerSet`,
- this.resultsSet as TypeResultsSet,
- registrationConditionFunction,
- registrationUserInitialisation
- );
-
- api.event.on(
- EVENT_NAMES.LAYER_SET.UPDATED,
- (layerUpdatedPayload) => {
- // Log
- logger.logTraceCoreAPIEvent('LEGENDS-LAYER-SET - UPDATED (LegendsLayerSetStatusChanged)', this.mapId, layerUpdatedPayload);
+ /** ***************************************************************************************************************************
+ * The listener that will handle the CHANGE_LAYER_STATUS event triggered on the map. This method is called by the parent class
+ * LayerSet via the listener created by the setChangeLayerStatusListenerFunctions method.
+ *
+ * @param {PayloadBaseClass} payload The payload to process.
+ */
+ protected changeLayerStatusListenerFunctions(payload: PayloadBaseClass) {
+ if (payloadIsLayerSetChangeLayerStatus(payload)) {
+ // Log
+ logger.logTraceCoreAPIEvent('LEGEND-LAYER-SET on LAYER_SET.CHANGE_LAYER_STATUS', this.mapId, payload);
- if (payloadIsLayerSetUpdated(layerUpdatedPayload)) {
- const { layerPath, resultsSet } = layerUpdatedPayload;
- api.event.emit(GetLegendsPayload.createLegendsLayersetUpdatedPayload(`${this.mapId}/LegendsLayerSet`, layerPath, resultsSet));
+ const { layerPath, layerStatus } = payload;
+ const layerExists = !!this.resultSet?.[layerPath];
+ const statusHasChanged = this.resultSet?.[layerPath]?.layerStatus !== layerStatus;
+ super.changeLayerStatusListenerFunctions(payload);
+ if (statusHasChanged) {
+ if (layerExists && layerStatus === 'processed' && this.resultSet?.[layerPath]?.querySent === false) {
+ api.event.emit(GetLegendsPayload.createQueryLegendPayload(`${this.mapId}/${layerPath}`, layerPath));
+ this.resultSet[layerPath].querySent = true;
}
- },
- `${mapId}/LegendsLayerSetStatusChanged`
- );
+ if (layerExists || layerStatus === 'loaded')
+ LegendEventProcessor.propagateLegendToStore(this.mapId, layerPath, this.resultSet[layerPath]);
+ }
+ }
+ }
+ /** ***************************************************************************************************************************
+ * Set the listener function that will monitor events that returns the legend information returned by the layer's getLegend
+ * call and store it in the resultSet. Every time a registered layer changes, a LEGEND_LAYERSET_UPDATED event is triggered.
+ */
+ private setLayerInfoListener() {
api.event.on(
- EVENT_NAMES.LAYER_SET.UPDATED,
- (layerUpdatedPayload) => {
+ EVENT_NAMES.GET_LEGENDS.LEGEND_INFO,
+ (payload) => {
// Log
- logger.logTraceCoreAPIEvent('LEGENDS-LAYER-SET - UPDATED (LegendsLayerSet)', this.mapId, layerUpdatedPayload);
+ logger.logTraceCoreAPIEvent('legends-layer-set - GET_LEGENDS.LEGEND_INFO', this.mapId, payload);
- if (payloadIsLayerSetUpdated(layerUpdatedPayload)) {
- const { layerPath, resultsSet } = layerUpdatedPayload;
- if (resultsSet[layerPath]?.layerStatus === 'processed' && !(resultsSet as TypeLegendResultsSet)[layerPath].querySent) {
- api.event.emit(GetLegendsPayload.createQueryLegendPayload(`${this.mapId}/${layerPath}`, layerPath));
- this.resultsSet[layerPath].querySent = true;
+ if (payloadIsLegendInfo(payload)) {
+ const { layerPath, legendInfo } = payload;
+ if (layerPath in this.resultSet) {
+ this.resultSet[layerPath].data = legendInfo;
+ LegendEventProcessor.propagateLegendToStore(this.mapId, layerPath, this.resultSet[layerPath]);
+ api.event.emit(
+ LayerSetPayload.createLayerSetUpdatedPayload(`${this.mapId}/LegendsLayerSet`, this.resultSet as TypeResultSet, layerPath)
+ );
}
}
},
- `${mapId}/LegendsLayerSet`
+ this.mapId
);
+ }
- // This listener receives the legend information returned by the layer's getLegend call and store it in the resultsSet.
- // Every time a registered layer changes, an EVENT_NAMES.GET_LEGENDS.LEGENDS_LAYERSET_UPDATED event is triggered.
+ /** ***************************************************************************************************************************
+ * Set the listener function that will monitor events triggered when a layer is updated.
+ */
+ private setLayerSetUpdatedListener() {
api.event.on(
- EVENT_NAMES.GET_LEGENDS.LEGEND_INFO,
+ EVENT_NAMES.LAYER_SET.UPDATED,
(payload) => {
// Log
- logger.logTraceCoreAPIEvent('LEGENDS-LAYER-SET - LEGEND_INFO', this.mapId, payload);
+ logger.logTraceCoreAPIEvent('legends-layer-set - LAYER_SET.UPDATED', this.mapId, payload);
- if (payloadIsLegendInfo(payload)) {
- const { layerPath, legendInfo } = payload;
- if (layerPath in this.resultsSet) {
- this.resultsSet[layerPath].data = legendInfo;
- LegendEventProcessor.propagateLegendToStore(this.mapId, layerPath, this.resultsSet[layerPath]);
- api.event.emit(
- GetLegendsPayload.createLegendsLayersetUpdatedPayload(`${this.mapId}/LegendsLayerSet`, layerPath, this.resultsSet)
- );
+ if (payloadIsLayerSetUpdated(payload)) {
+ const { layerPath } = payload;
+ if (MapEventProcessor.getMapIndexFromOrderedLayerInfo(this.mapId, layerPath) === -1) {
+ const layerConfig = api.maps[this.mapId].layer.registeredLayers[layerPath];
+ if (layerConfig.parentLayerConfig) {
+ const parentLayerPathArray = layerPath.split('/');
+ parentLayerPathArray.pop();
+ const parentLayerPath = parentLayerPathArray.join('/');
+ const parentLayerIndex = MapEventProcessor.getMapIndexFromOrderedLayerInfo(this.mapId, parentLayerPath);
+ const numberOfLayers = MapEventProcessor.getMapOrderedLayerInfo(this.mapId).filter((layerInfo) =>
+ layerInfo.layerPath.startsWith(parentLayerPath)
+ ).length;
+ if (parentLayerIndex !== -1)
+ MapEventProcessor.addOrderedLayerInfo(this.mapId, layerConfig, parentLayerIndex + numberOfLayers);
+ else MapEventProcessor.addOrderedLayerInfo(this.mapId, layerConfig.parentLayerConfig);
+ } else MapEventProcessor.addOrderedLayerInfo(this.mapId, layerConfig);
}
}
},
- this.mapId
+ this.layerSetId
);
}
diff --git a/packages/geoview-core/src/ui/style/themeOptionsGenerator.ts b/packages/geoview-core/src/ui/style/themeOptionsGenerator.ts
index 5dce8d7a2fe..556f276f4a0 100644
--- a/packages/geoview-core/src/ui/style/themeOptionsGenerator.ts
+++ b/packages/geoview-core/src/ui/style/themeOptionsGenerator.ts
@@ -309,7 +309,7 @@ export const generateThemeOptions = (geoViewColors: IGeoViewColors = defaultGeoV
size: { width: 275, height: 275 },
},
},
- };
+ } as ThemeOptions;
return themeOptions;
};
diff --git a/packages/geoview-geochart/src/geochart-parsing.ts b/packages/geoview-geochart/src/geochart-parsing.ts
index 39e1f04b7e2..d6cf9683406 100644
--- a/packages/geoview-geochart/src/geochart-parsing.ts
+++ b/packages/geoview-geochart/src/geochart-parsing.ts
@@ -70,7 +70,7 @@ const simplifyTypeFeatureInfoEntries = (entries: TypeFeatureInfoEntryPartial[]):
* Finds complete configuration necessary to build a GeoChart based on a given results set.
* @param config PluginGeoChartConfig The complete GeoChart Plugin configuration
* @param registeredLayers { [layerEntryConfigId: string]: TypeLayerEntryConfig } The registered layers
- * @param resultsSet TypeFeatureInfoResultsSet The Results set of results to be simplified
+ * @param resultSet TypeFeatureInfoResultSet The Results set of results to be simplified
* @return [
GeoViewGeoChartConfig | undefined,
GeoViewGeoChartConfigLayer | undefined,
diff --git a/packages/geoview-layers-panel/src/panel-content.tsx b/packages/geoview-layers-panel/src/panel-content.tsx
index 2d77da0d35f..c1c72851fda 100644
--- a/packages/geoview-layers-panel/src/panel-content.tsx
+++ b/packages/geoview-layers-panel/src/panel-content.tsx
@@ -100,11 +100,11 @@ function PanelContent(props: TypePanelContentProps): JSX.Element {
logger.logTraceUseEffect('PANEL-CONTENT - mount 1');
api.event.on(api.eventNames.MAP.EVENT_MAP_LOADED, updateLayers, mapId);
- api.event.on(api.eventNames.GET_LEGENDS.LEGENDS_LAYERSET_UPDATED, updateLayers, `${mapId}/LegendsLayerSet`);
+ api.event.on(api.eventNames.GET_LEGENDS.LEGEND_LAYERSET_UPDATED, updateLayers, `${mapId}/LegendsLayerSet`);
return () => {
api.event.off(api.eventNames.MAP.EVENT_MAP_LOADED, mapId, updateLayers);
- api.event.off(api.eventNames.GET_LEGENDS.LEGENDS_LAYERSET_UPDATED, mapId, updateLayers);
+ api.event.off(api.eventNames.GET_LEGENDS.LEGEND_LAYERSET_UPDATED, mapId, updateLayers);
};
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);