diff --git a/packages/geoview-core/public/templates/sandbox.html b/packages/geoview-core/public/templates/sandbox.html index 758cdef4892..99c987b7b78 100644 --- a/packages/geoview-core/public/templates/sandbox.html +++ b/packages/geoview-core/public/templates/sandbox.html @@ -143,7 +143,7 @@

Sanbox Map

Top
-
+

This map loads it's configurations from the text area.


@@ -194,11 +194,17 @@

Sanbox Map

// add an event listener when a button is clicked createMapButton.addEventListener('click', function (e) { // delete old map - const mapDiv = cgpv.api.maps['sandboxMap'].remove(false); - mapDiv.classList.remove('geoview-map'); + cgpv.api.maps['sandboxMap'].remove(true); + + // create new map in a new dom node (fix react warning) + const newDiv = document.createElement('div'); + const a = document.createAttribute("id"); + a.value = "sandboxMap"; + newDiv.setAttributeNode(a); + document.getElementById('mapSection').appendChild(newDiv); // create map - setTimeout(() => cgpv.api.createMapFromConfig('sandboxMap', document.getElementById('configGeoview').value), 1000); + setTimeout(() => cgpv.api.createMapFromConfig('sandboxMap', document.getElementById('configGeoview').value), 300); }); // Editor script section=================================================================================================== diff --git a/packages/geoview-core/src/app.tsx b/packages/geoview-core/src/app.tsx index dcd5f32b082..a6b437495ff 100644 --- a/packages/geoview-core/src/app.tsx +++ b/packages/geoview-core/src/app.tsx @@ -101,7 +101,7 @@ async function renderMap(mapElement: Element): Promise { reactRoot[mapId] = createRoot(mapElement!); addReloadListener(mapId); - // TODO: Refactor #1810 - Activate + // TODO: Refactor #1810 - Activate here or in app-start.tsx? reactRoot[mapId].render(); // reactRoot[mapId].render( // diff --git a/packages/geoview-core/src/core/app-start.tsx b/packages/geoview-core/src/core/app-start.tsx index c9d2c7ae6ef..71062c9f029 100644 --- a/packages/geoview-core/src/core/app-start.tsx +++ b/packages/geoview-core/src/core/app-start.tsx @@ -77,8 +77,19 @@ function AppStart(props: AppStartProps): JSX.Element { if (!Object.keys(api.maps).includes(mapId)) api.maps[mapId] = new MapViewer(mapFeaturesConfig, i18nInstance); // Start the process of checking for map readiness - api.maps[mapId].mapReady(); + api.maps[mapId].mapReady().then(() => { + // Start the process of checking for layers result set readiness + api.maps[mapId].layerResultSetReady().then(() => { + // If it's a static map, disable the click/hover listeners + if (mapFeaturesConfig.map.interaction === 'static') { + // No listeners + api.getFeatureInfoLayerSet(mapId).disableClickListener(); + api.getFeatureInfoLayerSet(mapId).disableHoverListener(); + } + }); + }); + // TODO: Refactor #1810 - Activate here or in app.tsx? return ( diff --git a/packages/geoview-core/src/geo/layer/geoview-layers/abstract-geoview-layers.ts b/packages/geoview-core/src/geo/layer/geoview-layers/abstract-geoview-layers.ts index 4b4fbd25768..41ab049c50b 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 @@ -962,7 +962,7 @@ export abstract class AbstractGeoViewLayer { * * @param {TypeBaseLayerEntryConfig} layerConfig The layer config to register. */ - registerToLayerSets(layerConfig: TypeBaseLayerEntryConfig) { + registerToLayerSets(layerConfig: TypeBaseLayerEntryConfig): void { const { layerPath } = layerConfig; if (!this.registerToLayerSetListenerFunctions[layerPath]) this.registerToLayerSetListenerFunctions[layerPath] = {}; @@ -1038,7 +1038,7 @@ export abstract class AbstractGeoViewLayer { * * @param {TypeBaseLayerEntryConfig} layerConfig The layer entry to register. */ - unregisterFromLayerSets(layerConfig: TypeBaseLayerEntryConfig) { + unregisterFromLayerSets(layerConfig: TypeBaseLayerEntryConfig): void { const { layerPath } = layerConfig; api.event.emit(LayerSetPayload.createLayerRegistrationPayload(this.mapId, layerPath, 'remove')); diff --git a/packages/geoview-core/src/geo/map/map-viewer.ts b/packages/geoview-core/src/geo/map/map-viewer.ts index 8d6ccd8b7f8..ab4f51d2998 100644 --- a/packages/geoview-core/src/geo/map/map-viewer.ts +++ b/packages/geoview-core/src/geo/map/map-viewer.ts @@ -187,36 +187,82 @@ export class MapViewer { } /** - * Function called when the map has been rendered and ready to be customized + * Function called to monitor when the map is actually ready */ - mapReady(): void { + mapReady(): Promise { // Log Marker Start logger.logMarkerStart(`mapReady-${this.mapId}`); - const layerInterval = setInterval(() => { - // Log - logger.logTraceDetailed('map-viewer.mapReady?', this.mapId); - - if (this.layer?.geoviewLayers) { - const { geoviewLayers } = this.layer; - let allGeoviewLayerReady = - this.mapFeaturesConfig.map.listOfGeoviewLayerConfig?.length === 0 || Object.keys(geoviewLayers).length !== 0; - Object.keys(geoviewLayers).forEach((geoviewLayerId) => { - const layerIsReady = geoviewLayers[geoviewLayerId].allLayerStatusAreIn(['processed', 'error', 'loaded']); - logger.logTraceDetailed('map-viewer.mapReady? geoview layer ready?', geoviewLayerId, layerIsReady); - allGeoviewLayerReady &&= layerIsReady; + return new Promise((resolve) => { + // Start an interval checker + const mapInterval = setInterval(() => { + if (this.layer?.geoviewLayers) { + const { geoviewLayers } = this.layer; + let allGeoviewLayerReady = + this.mapFeaturesConfig.map.listOfGeoviewLayerConfig?.length === 0 || Object.keys(geoviewLayers).length !== 0; + Object.keys(geoviewLayers).forEach((geoviewLayerId) => { + const layerIsReady = geoviewLayers[geoviewLayerId].allLayerStatusAreIn(['processed', 'error', 'loaded']); + if (!layerIsReady) logger.logTraceDetailed('map-viewer.mapReady? geoview layer not ready, waiting...', geoviewLayerId); + allGeoviewLayerReady &&= layerIsReady; + }); + if (allGeoviewLayerReady) { + // Clear interval + clearInterval(mapInterval); + + // Log + logger.logInfo('Map is ready', this.mapId); + logger.logMarkerCheck(`mapReady-${this.mapId}`, 'for map to be ready'); + + // Resolve the promise + resolve(); + + // ! We added processed to layers check so this map loaded event is fired faster + // TODO: solve this without using a timeout... + setTimeout(() => MapEventProcessor.setMapLoaded(this.mapId), 1000); + } + } + }, 250); + }); + } + + /** + * Function called to monitor when the layers result sets are actually ready + */ + layerResultSetReady(): Promise { + // Start another interval checker + return new Promise((resolve) => { + const layersInterval = setInterval(() => { + // Check if all registered layers have their results set + let allGood = true; + Object.entries(api.maps[this.mapId].layer.registeredLayers).forEach(([layerPath, registeredLayer]) => { + // If not queryable, don't expect a result set + if (!registeredLayer.source?.featureInfo?.queryable) return; + + const resultSet = api.getFeatureInfoLayerSet(this.mapId).resultsSet; + const layerResultSetReady = Object.keys(resultSet).includes(layerPath); + if (!layerResultSetReady) { + logger.logTraceDetailed('map-viewer.mapReady? layer set not ready, waiting...', layerPath); + allGood = false; + } }); - if (allGeoviewLayerReady) { + + // If all good + if (allGood) { + // Clear interval + clearInterval(layersInterval); + + // How many layers resultset? + const resultSetCount = Object.keys(api.getFeatureInfoLayerSet(this.mapId).resultsSet).length; + // Log - logger.logInfo('Map is ready', this.mapId); - logger.logMarkerCheck(`mapReady-${this.mapId}`, 'for map to be ready'); - // ! We added processed to layers check so this map loaded event is fired faster - // TODO: solve this without using a timeout... - setTimeout(() => MapEventProcessor.setMapLoaded(this.mapId), 1000); - clearInterval(layerInterval); + logger.logInfo(`All (${resultSetCount}) Layers ResultSet are ready`, this.mapId); + logger.logMarkerCheck(`mapReady-${this.mapId}`, `for all (${resultSetCount}) Layers ResultSet to be ready`); + + // Resolve the promise + resolve(); } - } - }, 250); + }, 250); + }); } /**