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..71706976550 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,7 +1,7 @@ +import { GeoviewStoreType, IFeatureInfoState } from '@/core/stores'; import { TypeFeatureInfoResultsSet, EventType, TypeLayerData, TypeArrayOfLayerData } from '@/api/events/payloads/get-feature-info-payload'; -import { IFeatureInfoState } from '@/core/stores'; +import { logger } from '@/core/utils/logger'; -import { GeochartEventProcessor } from './geochart-event-processor'; import { AbstractEventProcessor, BatchedPropagationLayerDataArrayByMap } from '../abstract-event-processor'; import { UIEventProcessor } from './ui-event-processor'; @@ -25,6 +25,45 @@ export class FeatureInfoEventProcessor extends AbstractEventProcessor { // The longer the delay, the longer it'll take to update the UI. The delay can be bypassed using the layer path bypass method. private static timeDelayBetweenPropagationsForBatch = 1000; + /** + * Overrides initialization of the Feature Info Event Processor + * @param {GeoviewStoreType} store The store associated with the Feature Info Event Processor + * @returns An array of the subscriptions callbacks which were created + */ + protected onInitialize(store: GeoviewStoreType): Array<() => void> | void { + // Checks for udpated layers in layer order + const unsubLayerRemoved = store.subscribe( + (state) => state.mapState.layerOrder, + (cur, prev) => { + // Log + logger.logTraceCoreStoreSubscription('FEATUREINFO EVENT PROCESSOR - layerOrder', cur); + + // For each layer path in the layer data array + store + .getState() + .detailsState.layerDataArray.map((layerInfo) => layerInfo.layerPath) + .forEach((layerPath) => { + // If it was in the layer data array and is not anymore + if (prev.includes(layerPath) && !cur.includes(layerPath)) { + // Remove it + FeatureInfoEventProcessor.deleteFeatureInfo(store.getState().mapId, layerPath); + + // Remove it + FeatureInfoEventProcessor.deleteFeatureHoverInfo(store.getState().mapId, layerPath); + + // Remove it + FeatureInfoEventProcessor.deleteFeatureAllInfo(store.getState().mapId, layerPath); + + // Log + logger.logDebug('Removed Feature Info for layer path:', layerPath); + } + }); + } + ); + + return [unsubLayerRemoved]; + } + /** * Shortcut to get the Feature Info state for a given map id * @param {string} mapId The mapId @@ -36,15 +75,87 @@ export class FeatureInfoEventProcessor extends AbstractEventProcessor { } /** - * Static method used to propagate feature info layer sets to the store + * Deletes the specified layer path from the layer sets in the store + * @param {string} mapId The map identifier + * @param {string} layerPath The layer path to delete + */ + private static deleteFeatureInfo(mapId: string, layerPath: string) { + // The feature info state + const featureInfoState = this.getFeatureInfoState(mapId); + + // Find the layer data info to delete from the array + const layerDataInfoToDelIndex = featureInfoState.layerDataArray.findIndex((layerInfo) => layerInfo.layerPath === layerPath); + + // If found + if (layerDataInfoToDelIndex >= 0) { + // Remove from the array + featureInfoState.layerDataArray.splice(layerDataInfoToDelIndex, 1); + + // Update the layer data array in the store + featureInfoState.actions.setLayerDataArray(featureInfoState.layerDataArray); + + // Also propagate in the batched array + FeatureInfoEventProcessor.propagateFeatureInfoToStoreBatch(mapId, featureInfoState.layerDataArray); + } + } + + /** + * Deletes the specified layer path from the hover layers sets in the store + * @param {string} mapId The map identifier + * @param {string} layerPath The layer path to delete + */ + private static deleteFeatureHoverInfo(mapId: string, layerPath: string) { + // The feature info state + const featureInfoState = this.getFeatureInfoState(mapId); + + // Find the layer data info to delete from the array + const layerDataInfoToDelIndex = featureInfoState.hoverDataArray.findIndex((layerInfo) => layerInfo.layerPath === layerPath); + + // If found + if (layerDataInfoToDelIndex >= 0) { + // Remove from the array + featureInfoState.hoverDataArray.splice(layerDataInfoToDelIndex, 1); + + // Update the layer data array in the store + featureInfoState.actions.setHoverDataArray(featureInfoState.hoverDataArray); + } + } + + /** + * Deletes the specified layer path from the all features layers sets in the store + * @param {string} mapId The map identifier + * @param {string} layerPath The layer path to delete + */ + private static deleteFeatureAllInfo(mapId: string, layerPath: string) { + // The feature info state + const featureInfoState = this.getFeatureInfoState(mapId); + + // Find the layer data info to delete from the array + const layerDataInfoToDelIndex = featureInfoState.allFeaturesDataArray.findIndex((layerInfo) => layerInfo.layerPath === layerPath); + + // If found + if (layerDataInfoToDelIndex >= 0) { + // Remove from the array + featureInfoState.allFeaturesDataArray.splice(layerDataInfoToDelIndex, 1); + + // Update the layer data array in the store + featureInfoState.actions.setAllFeaturesDataArray(featureInfoState.allFeaturesDataArray); + } + } + + /** + * Propagates feature info layer sets to the store * - * @param {string} mapId The map identifier of the resul set modified. + * @param {string} mapId The map identifier of the modified result set. * @param {string} layerPath The layer path that has changed. * @param {EventType} eventType The event type that triggered the layer set update. * @param {TypeFeatureInfoResultsSet} resultsSet The resul sets associated to the map. */ static propagateFeatureInfoToStore(mapId: string, layerPath: string, eventType: EventType, resultsSet: TypeFeatureInfoResultsSet) { + // The feature info state const featureInfoState = this.getFeatureInfoState(mapId); + + // Depending on the event type if (eventType === 'click') { /** * Create a details object for each layer which is then used to render layers in details panel. @@ -66,9 +177,6 @@ export class FeatureInfoEventProcessor extends AbstractEventProcessor { // Also propagate in the batched array FeatureInfoEventProcessor.propagateFeatureInfoToStoreBatch(mapId, layerDataArray); - - // Also propagate in the geochart arrays - GeochartEventProcessor.propagateArrayDataToStore(mapId, layerDataArray); } else if (eventType === 'hover') { /** * Create a hover object for each layer which is then used to render layers @@ -91,7 +199,7 @@ export class FeatureInfoEventProcessor extends AbstractEventProcessor { } /** - * Propagate feature info layer sets to the store in a batched manner, every 'timeDelayBetweenPropagationsForBatch' millisecond. + * Propagates feature info layer sets to the store in a batched manner, every 'timeDelayBetweenPropagationsForBatch' millisecond. * This is used to provide another 'layerDataArray', in the store, which updates less often so that we save a couple 'layerDataArray' * update triggers in the components that are listening to the store array. * The propagation can be bypassed using the store 'layerDataArrayBatchLayerPathBypass' state which tells the process to diff --git a/packages/geoview-core/src/api/event-processors/event-processor-children/geochart-event-processor.ts b/packages/geoview-core/src/api/event-processors/event-processor-children/geochart-event-processor.ts index a6c4f479a56..e5fbc3f9785 100644 --- a/packages/geoview-core/src/api/event-processors/event-processor-children/geochart-event-processor.ts +++ b/packages/geoview-core/src/api/event-processors/event-processor-children/geochart-event-processor.ts @@ -32,7 +32,7 @@ export class GeochartEventProcessor extends AbstractEventProcessor { * @returns An array of the subscriptions callbacks which were created */ protected onInitialize(store: GeoviewStoreType): Array<() => void> | void { - // Checks for added and removed layers with time dimension + // Checks for udpated layers in layer order const unsubLayerRemoved = store.subscribe( (state) => state.mapState.layerOrder, (cur, prev) => { @@ -40,20 +40,32 @@ export class GeochartEventProcessor extends AbstractEventProcessor { logger.logTraceCoreStoreSubscription('GEOCHART EVENT PROCESSOR - layerOrder', cur); // For each chart config keys - Object.keys(store.getState().geochartState.geochartChartsConfig).forEach((chartLayerPath: string) => { + Object.keys(store.getState().geochartState.geochartChartsConfig).forEach((layerPath: string) => { // If it was in the layerdata array and is not anymore - if (prev.includes(chartLayerPath) && !cur.includes(chartLayerPath)) { + if (prev.includes(layerPath) && !cur.includes(layerPath)) { // Remove it - GeochartEventProcessor.removeGeochartChart(store.getState().mapId, chartLayerPath); + GeochartEventProcessor.removeGeochartChart(store.getState().mapId, layerPath); // Log - logger.logDebug('Removed GeoChart configs for layer path:', chartLayerPath); + logger.logDebug('Removed GeoChart configs for layer path:', layerPath); } }); } ); - return [unsubLayerRemoved]; + // Checks for updated layers in layer data array + const layerDataArrayUpdate = store.subscribe( + (state) => state.detailsState.layerDataArray, + (cur) => { + // Log + logger.logTraceCoreStoreSubscription('GEOCHART EVENT PROCESSOR - layerDataArray', cur); + + // Also propagate in the geochart arrays + GeochartEventProcessor.propagateArrayDataToStore(store.getState().mapId, cur); + } + ); + + return [unsubLayerRemoved, layerDataArrayUpdate]; } /** @@ -93,7 +105,7 @@ export class GeochartEventProcessor extends AbstractEventProcessor { // set store charts config this.getGeochartState(mapId)?.actions.setGeochartCharts(chartData); - // TODO: Also update the layer array in other store state to inform the later has a geochart attached to it (when code is done over there) + // TODO: Also update the layer array in other store state to inform the later has a geochart attached to it (when code is done over there)? } /** @@ -114,7 +126,7 @@ export class GeochartEventProcessor extends AbstractEventProcessor { // Update the layer data array in the store this.getGeochartState(mapId)!.actions.setGeochartCharts({ ...this.getGeochartState(mapId)?.geochartChartsConfig, ...toAdd }); - // TODO: Also update the layer array in other store state to inform the later has a geochart attached to it (when code is done over there) + // TODO: Also update the layer array in other store state to inform the later has a geochart attached to it (when code is done over there)? } /** @@ -139,7 +151,7 @@ export class GeochartEventProcessor extends AbstractEventProcessor { // Update the layer data array in the store this.getGeochartState(mapId)!.actions.setGeochartCharts({ ...chartConfigs }); - // TODO: Also update the layer array in other store state to inform the later has a geochart attached to it (when code is done over there) + // TODO: Also update the layer array in other store state to inform the later has a geochart attached to it (when code is done over there)? } }