From 63030bb1c1150a8636981d4ab983aee415ef940e 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 | 47 +-- .../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 | 36 +- .../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 | 49 ++- .../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 | 5 +- .../src/core/components/layers/types.ts | 1 - .../src/core/types/material-ui.d.ts | 1 + .../geoview-layers/abstract-geoview-layers.ts | 34 +- .../layer/geoview-layers/esri-layer-common.ts | 5 + .../layer/geoview-layers/raster/esri-image.ts | 3 - .../geoview-layers/raster/vector-tiles.ts | 6 + .../geo/layer/geoview-layers/raster/wms.ts | 6 +- .../layer/geoview-layers/raster/xyz-tiles.ts | 6 + .../geo/layer/geoview-layers/vector/csv.ts | 7 +- .../layer/geoview-layers/vector/geojson.ts | 6 + .../geoview-layers/vector/ogc-feature.ts | 32 +- .../geo/layer/geoview-layers/vector/wfs.ts | 85 +++-- packages/geoview-core/src/geo/layer/layer.ts | 1 - .../src/geo/map/map-schema-types.ts | 39 +- .../src/geo/utils/feature-info-layer-set.ts | 340 +++++++++--------- .../geoview-core/src/geo/utils/layer-set.ts | 154 ++++---- .../src/geo/utils/legends-layer-set.ts | 116 +++--- .../src/ui/style/themeOptionsGenerator.ts | 2 +- .../geoview-geochart/src/geochart-parsing.ts | 2 +- .../src/panel-content.tsx | 4 +- packages/geoview-swiper/src/swiper.tsx | 14 +- 54 files changed, 666 insertions(+), 781 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..d42276e2fc5 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,28 +453,29 @@

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, + + cgpv.api.event.on( + cgpv.api.eventNames.GET_LEGENDS.LEGEND_LAYERSET_UPDATED, (payload) => { - const { resultsSet } = payload; - displayLegend('LegendsId1', resultsSet); + const { resultSet } = payload; + displayLegend('LegendsId1', resultSet); }, 'LYR1/LegendsLayerSet' ); - }, - 'LYR1' - ); - - listenToLegendLayerSetChanges('HLYR1-state', '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' }); @@ -483,17 +484,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('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 = ''; 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}`; }, 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..1bebc06e0b2 100644 --- a/packages/geoview-core/public/templates/layers/wms.html +++ b/packages/geoview-core/public/templates/layers/wms.html @@ -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 78d853829e7..e6192f56944 100644 --- a/packages/geoview-core/public/templates/package-swiper.html +++ b/packages/geoview-core/public/templates/package-swiper.html @@ -81,11 +81,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 0f551442e64..5a953b899d3 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,4 +1,4 @@ -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 { IFeatureInfoState } from '@/core/stores'; import { GeochartEventProcessor } from './geochart-event-processor'; @@ -41,9 +41,9 @@ export class FeatureInfoEventProcessor extends AbstractEventProcessor { * @param {string} mapId The map identifier of the resul set modified. * @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) { const featureInfoState = this.getFeatureInfoState(mapId); if (eventType === 'click') { /** @@ -51,7 +51,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 @@ -75,7 +75,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') { @@ -84,7 +84,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 7950d7fcb93..ebb913ff174 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,7 @@ 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 { delay } from '@/core/utils/utilities'; import { logger } from '@/core/utils/logger'; import { AbstractEventProcessor } from '../abstract-event-processor'; @@ -135,17 +135,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); @@ -158,14 +157,12 @@ export class LegendEventProcessor extends AbstractEventProcessor { api.maps[mapId].layer.initialLayerOrder.indexOf(entryLayerPath) !== -1 && !layerConfig.parentLayerConfig ? api.maps[mapId].layer.initialLayerOrder.indexOf(entryLayerPath) : existingEntries.length, - // 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, + layerStatus: legendResultSetEntry.layerStatus, layerName: getLocalizedValue(layerConfig.layerName, mapId) || layerConfig.layerId, type: layerConfig.entryType as TypeGeoviewLayerType, isVisible: layerConfig.initialSettings?.visible ? layerConfig.initialSettings.visible : 'yes', - canToggle: legendResultsSetEntry.data?.type !== 'esriImage', + canToggle: legendResultSetEntry.data?.type !== 'esriImage', opacity: layerConfig.initialSettings?.opacity ? layerConfig.initialSettings.opacity : 1, items: [] as TypeLegendItem[], children: [] as TypeLegendLayer[], @@ -186,19 +183,17 @@ export class LegendEventProcessor extends AbstractEventProcessor { : existingEntries.length, 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, + layerName: getLocalizedValue(legendResultSetEntry.data?.layerName, mapId) || layerConfig.layerId!, + layerStatus: legendResultSetEntry.layerStatus, + querySent: legendResultSetEntry.querySent, + styleConfig: legendResultSetEntry.data?.styleConfig, + type: legendResultSetEntry.data?.type, isVisible: layerConfig.initialSettings?.visible || 'yes', - canToggle: legendResultsSetEntry.data?.type !== 'esriImage', + 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 = []; @@ -221,7 +216,7 @@ export class LegendEventProcessor extends AbstractEventProcessor { // ! 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); + const myLayer = api.maps[mapId].layer.geoviewLayers[layerPathNodes[0]]; // Calculate the bounds (the calculation may return undefined when it fails) newLegendLayer.bounds = myLayer.calculateBounds(layerPath); @@ -247,7 +242,7 @@ export class LegendEventProcessor extends AbstractEventProcessor { LegendEventProcessor.propagatedOnce = true; // Give it some time so that each layer has their chance to load on time - await delay(LegendEventProcessor.timeDelayBeforeSelectingLayerInStore); + // await delay(LegendEventProcessor.timeDelayBeforeSelectingLayerInStore); // Find the layers that are processed const validFirstLayer = layers.find((layer) => { 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 1e7f1e9b4ba..a9b4e24466e 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 2fa8b11c3e9..12533066817 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 8c947dbbbf3..a691beda9b4 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); @@ -69,7 +69,6 @@ export function useLegendHelpers() { order: 20, type: 'GeoJSON', layerStatus: 'loaded', - layerPhase: 'processed', isVisible: 'yes', querySent: true, children: [], @@ -83,7 +82,6 @@ export function useLegendHelpers() { order: 21, type: 'GeoJSON', layerStatus: 'loaded', - layerPhase: 'processed', isVisible: 'yes', querySent: true, children: [], @@ -97,7 +95,6 @@ export function useLegendHelpers() { type: 'GeoJSON', order: 22, layerStatus: 'loaded', - layerPhase: 'processed', isVisible: 'yes', querySent: true, children: [ @@ -109,7 +106,6 @@ export function useLegendHelpers() { order: 2, type: 'GeoJSON', layerStatus: 'loaded', - layerPhase: 'processed', isVisible: 'yes', querySent: true, children: [ @@ -121,7 +117,6 @@ export function useLegendHelpers() { type: 'GeoJSON', order: 1, layerStatus: 'error', - layerPhase: 'processed', isVisible: 'no', querySent: true, children: [], @@ -135,7 +130,6 @@ export function useLegendHelpers() { type: 'GeoJSON', order: 2, layerStatus: 'processing', - layerPhase: 'processed', isVisible: 'no', querySent: true, children: [], @@ -149,7 +143,6 @@ export function useLegendHelpers() { type: 'GeoJSON', order: 3, layerStatus: 'newInstance', - layerPhase: 'processed', isVisible: 'yes', querySent: true, children: [], @@ -166,7 +159,6 @@ export function useLegendHelpers() { type: 'GeoJSON', order: 24, layerStatus: 'loaded', - layerPhase: 'processed', isVisible: 'no', querySent: true, children: [], @@ -180,7 +172,6 @@ export function useLegendHelpers() { type: 'GeoJSON', order: 25, layerStatus: 'loaded', - layerPhase: 'processed', isVisible: 'yes', querySent: true, children: [], 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 a7056f26d48..90e49b1c540 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 @@ -74,7 +74,7 @@ export function AddNewLayer(): JSX.Element { // get values from store const mapId = useGeoViewMapId(); const layersList = useLayersList(); - const { setDisplayState, setSelectedLayerPath } = useLayerStoreActions(); + const { setDisplayState } = useLayerStoreActions(); const isMultiple = () => hasMetadata && (layerType === ESRI_DYNAMIC || layerType === WFS || layerType === WMS || layerType === GEOJSON); @@ -866,6 +866,8 @@ export function AddNewLayer(): JSX.Element { } else emitErrorNotLoaded(); } setIsLoading(false); + // TODO: Geoview layers doesn't have a LayerPhase property. This code must be revised + /* let message = ''; switch (geoviewLayerInstance?.layerPhase) { case 'loading': @@ -880,6 +882,7 @@ export function AddNewLayer(): JSX.Element { break; } api.utilities.showMessage(mapId, message, false); + */ setDisplayState('view'); }; diff --git a/packages/geoview-core/src/core/components/layers/types.ts b/packages/geoview-core/src/core/components/layers/types.ts index aa4398fdbe5..ddf82a36efe 100644 --- a/packages/geoview-core/src/core/components/layers/types.ts +++ b/packages/geoview-core/src/core/components/layers/types.ts @@ -35,7 +35,6 @@ export interface TypeLegendLayer { type?: TypeGeoviewLayerType; styleConfig?: TypeStyleConfig | null; layerStatus?: TypeLayerStatus; - layerPhase?: string; querySent?: boolean; isVisible: TypeVisibilityFlags; // is layer is visible 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 ac9f73b04ca..dda8287b0d2 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; @@ -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)); } }); }; @@ -433,8 +426,6 @@ export abstract class AbstractGeoViewLayer { 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); } /** *************************************************************************************************************************** @@ -593,9 +584,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 +627,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, consoleMessage: message }); + throw new Error(message); + } }); } catch (error) { // Log @@ -672,7 +670,13 @@ export abstract class AbstractGeoViewLayer { */ 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. + layerConfig.layerStatus = 'processed'; + // Then, we signal that the loading phase has begun + layerConfig.layerStatus = 'loading'; + return Promise.resolve(layerConfig); } @@ -1320,7 +1324,7 @@ export abstract class AbstractGeoViewLayer { style: TypeStyleConfig; }) | undefined; - + logger.logDebug('getLegend:layerConfig=', layerConfig); if (!layerConfig) { const legend: TypeLegend = { type: this.type, 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 983c8fd8cbc..a1e0430ceb3 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 @@ -376,6 +376,11 @@ 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. + layerConfig.layerStatus = 'processed'; + // Then, we signal that the loading phase has begun + layerConfig.layerStatus = 'loading'; } catch (error) { this.setLayerStatus('error', layerPath); console.log(error); 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..ec64f62fa74 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 @@ -215,11 +215,8 @@ export class EsriImage extends AbstractGeoViewRaster { consoleMessage: `Empty layer group (mapId: ${this.mapId}, layerPath: ${layerPath})`, }); this.setLayerStatus('error', layerPath); - return; } } - - this.setLayerStatus('loading', layerPath); }); } 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..3191bfc173e 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 @@ -263,6 +263,12 @@ export class VectorTiles extends AbstractGeoViewRaster { `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. + layerConfig.layerStatus = 'processed'; + // Then, we signal that the loading phase has begun + layerConfig.layerStatus = 'loading'; + 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 f2d5299845f..ef00090e648 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 @@ -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, @@ -605,6 +604,11 @@ export class WMS extends AbstractGeoViewRaster { } } } + // 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. + layerConfig.layerStatus = 'processed'; + // Then, we signal that the loading phase has begun + layerConfig.layerStatus = 'loading'; resolve(layerConfig); }); return promiseOfExecution; 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..a181da8f4af 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 @@ -269,6 +269,12 @@ export class XYZTiles extends AbstractGeoViewRaster { `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. + layerConfig.layerStatus = 'processed'; + // Then, we signal that the loading phase has begun + layerConfig.layerStatus = 'loading'; + resolve(layerConfig); } }); 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..793c1510e6f 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 @@ -181,8 +181,6 @@ export class CSV extends AbstractGeoViewVector { return; } - this.setLayerStatus('loading', layerPath); - // When no metadata are provided, all layers are considered valid. if (!this.metadata) return; @@ -201,6 +199,11 @@ export class CSV extends AbstractGeoViewVector { */ protected processLayerMetadata(layerConfig: TypeVectorLayerEntryConfig): Promise { const promiseOfExecution = new Promise((resolve) => { + // 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. + layerConfig.layerStatus = 'processed'; + // Then, we signal that the loading phase has begun + layerConfig.layerStatus = 'loading'; resolve(layerConfig); }); 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..44a05465300 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 @@ -242,6 +242,12 @@ export class GeoJSON extends AbstractGeoViewVector { `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. + layerConfig.layerStatus = 'processed'; + // Then, we signal that the loading phase has begun + layerConfig.layerStatus = 'loading'; + resolve(layerConfig); } }); 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..ac30588c06e 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'; @@ -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. + layerConfig.layerStatus = 'processed'; + // Then, we signal that the loading phase has begun + layerConfig.layerStatus = 'loading'; + } 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..c02ce381a99 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'; @@ -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. + layerConfig.layerStatus = 'processed'; + // Then, we signal that the loading phase has begun + layerConfig.layerStatus = 'loading'; + } 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 6c4723be651..93deabe5b97 100644 --- a/packages/geoview-core/src/geo/layer/layer.ts +++ b/packages/geoview-core/src/geo/layer/layer.ts @@ -318,7 +318,6 @@ export class Layer { // 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)); } 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 d1ccbcc0cb7..d5fa053c21f 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'; /** ****************************************************************************************************************************** @@ -659,9 +659,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; @@ -681,6 +678,9 @@ 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'; + /** * The class constructor. * @param {ConfigBaseClass} layerConfig The layer configuration we want to instanciate. @@ -739,6 +739,23 @@ 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 layerId setter method for the ConfigBaseClass class and its descendant classes. + * @param {string} newLayerId The new layerId value. + */ + set layerStatus(layerStatus: TypeLayerStatus) { + this._layerStatus = layerStatus; + api.event.emit(LayerSetPayload.createLayerSetChangeLayerStatusPayload(this.geoviewLayerInstance!.mapId, this.layerPath, layerStatus)); + if (layerStatus === 'processed') this.geoviewLayerInstance!.setLayerPhase('processed', this.layerPath); + } + /** * Register the layer identifier. Duplicate identifier are not allowed. * @@ -749,9 +766,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; } @@ -1313,12 +1330,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; @@ -1395,12 +1406,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/utils/feature-info-layer-set.ts b/packages/geoview-core/src/geo/utils/feature-info-layer-set.ts index b7431e1bef4..f488fcd17fc 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, TypeResultSet, 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,104 +45,149 @@ 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`, {} as TypeResultSet); + 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('FeatureInfoLayerSet registration condition...', 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('FeatureInfoLayerSet initializing layer path...', 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. + * + * @param {PayloadBaseClass} payload The payload to process. + */ + protected changeLayerStatusListenerFunctions(payload: PayloadBaseClass) { + if (payloadIsLayerSetChangeLayerStatus(payload)) { + // Log + logger.logTraceDetailed('legend-layer-set on EVENT_NAMES.LAYER_SET.CHANGE_LAYER_STATUS', this.mapId, 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 + 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); + } + } + } + + /** *************************************************************************************************************************** + * 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.logTraceDetailed('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); + } + + /* ************************************************************************************************************************** + * 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'; + } - /* *********************************************************************************************************************** */ - // 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. + if (dataForEventType.eventListenerEnabled && dataForEventType.queryStatus !== ('error' as TypeQueryStatus)) { + api.event.emit(GetFeatureInfoPayload.createQueryLayerPayload(`${this.mapId}/${layerPath}`, queryType, coordinate, eventType)); + } + }); + }; + + /** *************************************************************************************************************************** + * 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_SINGLE_CLICK, (payload) => { @@ -158,33 +195,20 @@ export class FeatureInfoLayerSet { logger.logTraceCoreAPIEvent('FEATURE-INFO-LAYER-SET - EVENT_MAP_SINGLE_CLICK', this.mapId, payload); if (payloadIsAMapMouseEvent(payload)) { - this.createQueryLayerPayload('click', 'at_long_lat', payload.coordinates.lnglat); - } - }, - this.mapId - ); - - /* *********************************************************************************************************************** */ - // 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? - api.event.on( - EVENT_NAMES.MAP.EVENT_MAP_CROSSHAIR_ENTER, - (payload) => { - // Log - logger.logTraceCoreAPIEvent('FEATURE-INFO-LAYER-SET - EVENT_MAP_CROSSHAIR_ENTER', this.mapId, payload); + // Log + logger.logTraceDetailed('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) => { @@ -192,16 +216,21 @@ export class FeatureInfoLayerSet { logger.logTraceCoreAPIEvent('FEATURE-INFO-LAYER-SET - EVENT_MAP_POINTER_MOVE', this.mapId, payload); if (payloadIsAMapMouseEvent(payload)) { - this.createQueryLayerPayload('hover', 'at_pixel', payload.coordinates.pixel); + // Log + logger.logTraceDetailed('feature-info-layer-set on EVENT_NAMES.MAP.EVENT_MAP_POINTER_MOVE', this.mapId, payload); + + 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 +239,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 +271,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,7 +281,7 @@ 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})`); } @@ -291,10 +293,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; }); } @@ -305,10 +307,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; }); } @@ -321,12 +323,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; } @@ -338,10 +340,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; }); } @@ -352,10 +354,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; }); } @@ -368,12 +370,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 011f708b970..00019bef69f 100644 --- a/packages/geoview-core/src/geo/utils/layer-set.ts +++ b/packages/geoview-core/src/geo/utils/layer-set.ts @@ -2,12 +2,10 @@ 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'; @@ -23,94 +21,108 @@ 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.logTraceDetailed('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) => { + 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, @@ -122,22 +134,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) - ); - } else if (action === 'remove' && layerPath in this.resultsSet) { - delete this.resultsSet[layerPath]; - api.event.emit(LayerSetPayload.createLayerSetUpdatedPayload(this.layerSetId, this.resultsSet, layerPath)); + api.event.emit(LayerSetPayload.createLayerSetUpdatedPayload(this.layerSetId, this.resultSet, layerPath)); + } else if (action === 'remove' && layerPath in this.resultSet) { + delete this.resultSet[layerPath]; + api.event.emit(LayerSetPayload.createLayerSetUpdatedPayload(this.layerSetId, this.resultSet, layerPath)); } } } @@ -155,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 @@ -163,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..c2a918a045a 100644 --- a/packages/geoview-core/src/geo/utils/legends-layer-set.ts +++ b/packages/geoview-core/src/geo/utils/legends-layer-set.ts @@ -2,16 +2,20 @@ import { EVENT_NAMES } from '@/api/events/event-types'; import { GetLegendsPayload, + PayloadBaseClass, payloadIsLegendInfo, - TypeLegendResultsSet, - payloadIsLayerSetUpdated, - TypeResultsSet, + TypeLegendResultSet, + TypeResultSet, + LayerSetPayload, + payloadIsLayerSetChangeLayerStatus, } 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'; +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 * loaded on the specified map will be added to the set. Layers added afterwards will be added to the set and deleted layers @@ -19,18 +23,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,59 +37,51 @@ 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`, {} as TypeResultSet); + this.setUserRegistrationInitFunction(); + this.setLayerInfoListener(); + } - // 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); - - if (payloadIsLayerSetUpdated(layerUpdatedPayload)) { - const { layerPath, resultsSet } = layerUpdatedPayload; - api.event.emit(GetLegendsPayload.createLegendsLayersetUpdatedPayload(`${this.mapId}/LegendsLayerSet`, layerPath, resultsSet)); - } - }, - `${mapId}/LegendsLayerSetStatusChanged` - ); - - api.event.on( - EVENT_NAMES.LAYER_SET.UPDATED, - (layerUpdatedPayload) => { - // Log - logger.logTraceCoreAPIEvent('LEGENDS-LAYER-SET - UPDATED (LegendsLayerSet)', this.mapId, layerUpdatedPayload); + /** *************************************************************************************************************************** + * 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.logTraceDetailed('legend-layer-set on EVENT_NAMES.LAYER_SET.CHANGE_LAYER_STATUS', 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; - } + const { layerPath, layerStatus } = payload; + const layerExists = !!this.resultSet?.[layerPath]; + const statusHasChanged = this.resultSet?.[layerPath]?.layerStatus !== layerStatus; + super.changeLayerStatusListenerFunctions(payload); + if (layerExists && statusHasChanged) { + if (layerStatus === 'processed' && this.resultSet?.[layerPath]?.querySent === false) { + api.event.emit(GetLegendsPayload.createQueryLegendPayload(`${this.mapId}/${layerPath}`, layerPath)); + this.resultSet[layerPath].querySent = true; } - }, - `${mapId}/LegendsLayerSet` - ); + LegendEventProcessor.propagateLegendToStore(this.mapId, layerPath, this.resultSet[layerPath]); + } + } + } - // 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 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.GET_LEGENDS.LEGEND_INFO, (payload) => { @@ -100,11 +90,11 @@ export class LegendsLayerSet { 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]); + if (layerPath in this.resultSet) { + this.resultSet[layerPath].data = legendInfo; + LegendEventProcessor.propagateLegendToStore(this.mapId, layerPath, this.resultSet[layerPath]); api.event.emit( - GetLegendsPayload.createLegendsLayersetUpdatedPayload(`${this.mapId}/LegendsLayerSet`, layerPath, this.resultsSet) + LayerSetPayload.createLayerSetUpdatedPayload(`${this.mapId}/LegendsLayerSet`, this.resultSet as TypeResultSet, layerPath) ); } } diff --git a/packages/geoview-core/src/ui/style/themeOptionsGenerator.ts b/packages/geoview-core/src/ui/style/themeOptionsGenerator.ts index b1edd93738e..defd7d1c8b5 100644 --- a/packages/geoview-core/src/ui/style/themeOptionsGenerator.ts +++ b/packages/geoview-core/src/ui/style/themeOptionsGenerator.ts @@ -260,7 +260,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 b88900a5da2..afaa6976cca 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 }, []); diff --git a/packages/geoview-swiper/src/swiper.tsx b/packages/geoview-swiper/src/swiper.tsx index c908bd32c85..7f6fa989605 100644 --- a/packages/geoview-swiper/src/swiper.tsx +++ b/packages/geoview-swiper/src/swiper.tsx @@ -4,7 +4,7 @@ import { RefObject, useAppDisplayLanguageById } from 'geoview-core'; import { getLocalizedMessage } from 'geoview-core/src/core/utils/utilities'; import { EVENT_NAMES } from 'geoview-core/src/api/events/event-types'; -import { PayloadBaseClass, TypeResultsSet, payloadIsLayerSetUpdated } from 'geoview-core/src/api/events/payloads'; +import { PayloadBaseClass, TypeResultSet, payloadIsLayerSetUpdated } from 'geoview-core/src/api/events/payloads'; import { logger } from 'geoview-core/src/core/utils/logger'; import { getRenderPixel } from 'ol/render'; @@ -124,19 +124,19 @@ export function Swiper(props: SwiperProps): JSX.Element { /** * Sort layers to only include those that are loaded - * @param {TypeResultsSet} resultsSets The resulstSet from the layer set + * @param {TypeResultSet} resultSets The resulstSet from the layer set * * @returns {string[]} array of IDs for layers that are loaded on the map */ - function sortLayerIds(resultsSets: TypeResultsSet) { + function sortLayerIds(resultSets: TypeResultSet) { const layerIds: string[] = []; - Object.keys(resultsSets).forEach((result) => { - if (resultsSets[result].layerStatus === 'loaded') layerIds.push(result.split('/')[0]); + Object.keys(resultSets).forEach((result) => { + if (resultSets[result].layerStatus === 'loaded') layerIds.push(result.split('/')[0]); }); return layerIds; } - const [layersIds, setLayersIds] = useState(sortLayerIds(api.getLegendsLayerSet(mapId).resultsSet)); + const [layersIds, setLayersIds] = useState(sortLayerIds(api.getLegendsLayerSet(mapId).resultSet)); /** * Pre compose, Pre render event callback @@ -265,7 +265,7 @@ export function Swiper(props: SwiperProps): JSX.Element { // Log logger.logTraceCoreAPIEvent('GEOVIEW-SWIPER - layerSetUpdatedHandler', payload); - if (payloadIsLayerSetUpdated(payload) && payload.resultsSet[payload.layerPath]?.layerStatus === 'loaded') { + if (payloadIsLayerSetUpdated(payload) && payload.resultSet[payload.layerPath]?.layerStatus === 'loaded') { const layerId = payload.layerPath.split('/')[0]; const ids = [...layersIds]; if (ids.indexOf(layerId) === -1 && config.layers.includes(layerId)) {

NamePhaseStatus
${layerName}${layerPhase}${layerStatus}