diff --git a/packages/geoview-core/public/templates/sandbox.html b/packages/geoview-core/public/templates/sandbox.html index 9854b162252..05288d5929f 100644 --- a/packages/geoview-core/public/templates/sandbox.html +++ b/packages/geoview-core/public/templates/sandbox.html @@ -247,7 +247,7 @@

Sanbox Map

// create map // TODO: the delete has a timeout so we need to wait before trying to recreate the map... - // TD.CONT: this should be cleaner + // TO.DOCONT: this should be cleaner setTimeout(() => { cgpv.api.createMapFromConfig('sandboxMap', document.getElementById('configGeoview').value); }, 1500); diff --git a/packages/geoview-core/src/api/event-processors/event-processor-children/app-event-processor.ts b/packages/geoview-core/src/api/event-processors/event-processor-children/app-event-processor.ts index a1f80941dec..5bc6119a4cd 100644 --- a/packages/geoview-core/src/api/event-processors/event-processor-children/app-event-processor.ts +++ b/packages/geoview-core/src/api/event-processors/event-processor-children/app-event-processor.ts @@ -7,6 +7,8 @@ import { createGuideObject } from '@/core/utils/utilities'; import { MapViewer } from '@/geo/map/map-viewer'; import { MapEventProcessor } from './map-event-processor'; +// GV Important: See notes in header of MapEventProcessor file for information on the paradigm to apply when working with UIEventProcessor vs UIState + export class AppEventProcessor extends AbstractEventProcessor { // Static functions for Typescript files to access store actions // ********************************************************** diff --git a/packages/geoview-core/src/api/event-processors/event-processor-children/data-table-event-processor.ts b/packages/geoview-core/src/api/event-processors/event-processor-children/data-table-event-processor.ts index 0fac413f54c..85b15f68286 100644 --- a/packages/geoview-core/src/api/event-processors/event-processor-children/data-table-event-processor.ts +++ b/packages/geoview-core/src/api/event-processors/event-processor-children/data-table-event-processor.ts @@ -8,19 +8,7 @@ import { TypeLayerData } from '@/geo/layer/layer-sets/abstract-layer-set'; import { TypeAllFeatureInfoResultSet } from '@/geo/layer/layer-sets/all-feature-info-layer-set'; import { MapEventProcessor } from './map-event-processor'; -// GV The paradigm when working with DataTableEventProcessor vs DataTableState goes like this: -// GV DataTableState provides: 'state values', 'actions' and 'setterActions'. -// GV Whereas Zustand would suggest having 'state values' and 'actions', in GeoView, we have a 'DataTableEventProcessor' in the middle. -// GV This is because we wanted to have centralized code between UI actions and backend actions via a DataTableEventProcessor. -// GV In summary: -// GV The UI components should use DataTableState's 'state values' to read and 'actions' to set states (which simply redirect to DataTableEventProcessor). -// GV The back-end code should use DataTableEventProcessor which uses 'state values' and 'setterActions' -// GV Essentially 3 main call-stacks: -// GV - DataTableEventProcessor ---calls---> DataTableState.setterActions -// GV - UI Component ---calls---> DataTableState.actions ---calls---> DataTableEventProcessor ---calls---> DataTableState.setterActions -// GV - DataTableEventProcessor ---triggers---> DataTableViewer events ---calls---> DataTableState.setterActions -// GV The reason for this pattern is so that UI components and processes performing back-end code -// GV both end up running code in DataTableEventProcessor (UI: via 'actions' and back-end code via 'DataTableEventProcessor') +// GV Important: See notes in header of MapEventProcessor file for information on the paradigm to apply when working with UIEventProcessor vs UIState export class DataTableEventProcessor extends AbstractEventProcessor { // ********************************************************** 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 2abcdec9bc5..dd96f6963d3 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 @@ -7,6 +7,8 @@ import { EventType, TypeLayerData } from '@/geo/layer/layer-sets/abstract-layer- import { AbstractEventProcessor, BatchedPropagationLayerDataArrayByMap } from '@/api/event-processors/abstract-event-processor'; import { UIEventProcessor } from './ui-event-processor'; +// GV Important: See notes in header of MapEventProcessor file for information on the paradigm to apply when working with UIEventProcessor vs UIState + /** * Event processor focusing on interacting with the feature info state in the store (currently called detailsState). */ @@ -77,7 +79,7 @@ export class FeatureInfoEventProcessor extends AbstractEventProcessor { // Redirect to helper function this.#deleteFromArray(featureInfoState.layerDataArray, layerPath, (layerArrayResult) => { // Update the layer data array in the store - featureInfoState.actions.setLayerDataArray(layerArrayResult); + featureInfoState.setterActions.setLayerDataArray(layerArrayResult); // Log logger.logInfo('Removed Feature Info in stores for layer path:', layerPath); @@ -135,7 +137,7 @@ export class FeatureInfoEventProcessor extends AbstractEventProcessor { const atLeastOneFeature = layerDataArray.find((layerEntry) => !!layerEntry.features?.length) || false; // Update the layer data array in the store, all the time, for all statuses - featureInfoState.actions.setLayerDataArray(layerDataArray); + featureInfoState.setterActions.setLayerDataArray(layerDataArray); // If there was some features on this propagation if (atLeastOneFeature) { @@ -175,10 +177,10 @@ export class FeatureInfoEventProcessor extends AbstractEventProcessor { layerDataArray, this.#batchedPropagationLayerDataArray, this.#timeDelayBetweenPropagationsForBatch, - featureInfoState.actions.setLayerDataArrayBatch, + featureInfoState.setterActions.setLayerDataArrayBatch, 'feature-info-processor', featureInfoState.layerDataArrayBatchLayerPathBypass, - featureInfoState.actions.setLayerDataArrayBatchLayerPathBypass + featureInfoState.setterActions.setLayerDataArrayBatchLayerPathBypass ); } 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 197ff0133f2..3d1380acfb8 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 @@ -6,6 +6,8 @@ import { TypeLayerData } from '@/geo/layer/layer-sets/abstract-layer-set'; import { AbstractEventProcessor, BatchedPropagationLayerDataArrayByMap } from '@/api/event-processors/abstract-event-processor'; +// GV Important: See notes in header of MapEventProcessor file for information on the paradigm to apply when working with UIEventProcessor vs UIState + /** * Event processor focusing on interacting with the geochart state in the store. */ @@ -102,7 +104,7 @@ export class GeochartEventProcessor extends AbstractEventProcessor { }); // set store charts config - this.getGeochartState(mapId)?.actions.setGeochartCharts(chartData); + this.getGeochartState(mapId)?.setterActions.setGeochartCharts(chartData); // Log logger.logInfo('Added GeoChart configs for layer paths:', layerPaths); @@ -124,7 +126,7 @@ export class GeochartEventProcessor extends AbstractEventProcessor { toAdd[layerPath] = chartConfig; // Update the layer data array in the store - this.getGeochartState(mapId)!.actions.setGeochartCharts({ ...this.getGeochartState(mapId)?.geochartChartsConfig, ...toAdd }); + this.getGeochartState(mapId)!.setterActions.setGeochartCharts({ ...this.getGeochartState(mapId)?.geochartChartsConfig, ...toAdd }); // Log logger.logInfo('Added GeoChart configs for layer path:', layerPath); @@ -150,7 +152,7 @@ export class GeochartEventProcessor extends AbstractEventProcessor { delete chartConfigs[layerPath]; // Update the layer data array in the store - this.getGeochartState(mapId)!.actions.setGeochartCharts({ ...chartConfigs }); + this.getGeochartState(mapId)!.setterActions.setGeochartCharts({ ...chartConfigs }); // Log logger.logInfo('Removed GeoChart configs for layer path:', layerPath); @@ -170,7 +172,7 @@ export class GeochartEventProcessor extends AbstractEventProcessor { if (!this.getGeochartState(mapId)) return; // Update the layer data array in the store - this.getGeochartState(mapId)!.actions.setLayerDataArray(layerDataArray); + this.getGeochartState(mapId)!.setterActions.setLayerDataArray(layerDataArray); } /** @@ -198,10 +200,10 @@ export class GeochartEventProcessor extends AbstractEventProcessor { layerDataArray, this.batchedPropagationLayerDataArray, this.timeDelayBetweenPropagationsForBatch, - geochartState.actions.setLayerDataArrayBatch, + geochartState.setterActions.setLayerDataArrayBatch, 'geochart-processor', geochartState.layerDataArrayBatchLayerPathBypass, - geochartState.actions.setLayerDataArrayBatchLayerPathBypass + geochartState.setterActions.setLayerDataArrayBatchLayerPathBypass ); } 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 45a3772a2ff..2a162405308 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 @@ -25,6 +25,8 @@ import { import { AppEventProcessor } from './app-event-processor'; import { MapEventProcessor } from './map-event-processor'; +// GV Important: See notes in header of MapEventProcessor file for information on the paradigm to apply when working with UIEventProcessor vs UIState + export class LegendEventProcessor extends AbstractEventProcessor { // ********************************************************** // Static functions for Typescript files to access store actions diff --git a/packages/geoview-core/src/api/event-processors/event-processor-children/map-event-processor.ts b/packages/geoview-core/src/api/event-processors/event-processor-children/map-event-processor.ts index 28bb09f284c..207376a1c20 100644 --- a/packages/geoview-core/src/api/event-processors/event-processor-children/map-event-processor.ts +++ b/packages/geoview-core/src/api/event-processors/event-processor-children/map-event-processor.ts @@ -218,7 +218,7 @@ export class MapEventProcessor extends AbstractEventProcessor { try { // Check if the plugins exist // TODO: if you run the code fast enough (only happened to me in the TimeSliderEventProcessor), - // TD.CONT: the getMapViewer should be async, because it can be unset as well ( so not just getMapViewerPlugins() ). + // TO.DOCONT: the getMapViewer should be async, because it can be unset as well ( so not just getMapViewerPlugins() ). await whenThisThen(() => api && api.maps && api.maps[mapId] && api.maps[mapId].plugins); } catch (error) { // Log diff --git a/packages/geoview-core/src/api/event-processors/event-processor-children/swiper-event-processor.ts b/packages/geoview-core/src/api/event-processors/event-processor-children/swiper-event-processor.ts index bbd5a2ec993..d5060f0439f 100644 --- a/packages/geoview-core/src/api/event-processors/event-processor-children/swiper-event-processor.ts +++ b/packages/geoview-core/src/api/event-processors/event-processor-children/swiper-event-processor.ts @@ -3,6 +3,8 @@ import { logger } from '@/core/utils/logger'; import { AbstractEventProcessor } from '@/api/event-processors/abstract-event-processor'; +// GV Important: See notes in header of MapEventProcessor file for information on the paradigm to apply when working with UIEventProcessor vs UIState + /** * Event processor focusing on interacting with the swiper state in the store. */ @@ -34,7 +36,7 @@ export class SwiperEventProcessor extends AbstractEventProcessor { */ static setLayerPaths(mapId: string, layerPaths: string[]): void { // set store layer paths - this.getSwiperState(mapId)?.actions.setLayerPaths(layerPaths); + this.getSwiperState(mapId)?.setterActions.setLayerPaths(layerPaths); // Log logger.logInfo('Added Swiper functionality for layer paths:', layerPaths); @@ -60,7 +62,7 @@ export class SwiperEventProcessor extends AbstractEventProcessor { updatedArray.push(layerPath); // Update the layer data array in the store - this.getSwiperState(mapId)!.actions.setLayerPaths(updatedArray); + this.getSwiperState(mapId)!.setterActions.setLayerPaths(updatedArray); // Log logger.logInfo('Added Swiper functionality for layer path:', layerPath); @@ -93,7 +95,7 @@ export class SwiperEventProcessor extends AbstractEventProcessor { updatedArray.splice(layerIndex, 1); // Update the layer data array in the store - this.getSwiperState(mapId)!.actions.setLayerPaths(updatedArray); + this.getSwiperState(mapId)!.setterActions.setLayerPaths(updatedArray); // Log logger.logInfo('Removed Swiper functionality for layer path:', layerPath); @@ -119,7 +121,7 @@ export class SwiperEventProcessor extends AbstractEventProcessor { const { layerPaths } = this.getSwiperState(mapId)!; // Update the layer data array in the store - this.getSwiperState(mapId)!.actions.setLayerPaths([]); + this.getSwiperState(mapId)!.setterActions.setLayerPaths([]); // Log logger.logInfo('Removed Swiper functionality for all layer paths', layerPaths); diff --git a/packages/geoview-core/src/api/event-processors/event-processor-children/time-slider-event-processor.ts b/packages/geoview-core/src/api/event-processors/event-processor-children/time-slider-event-processor.ts index 68fceaf707d..04839004a26 100644 --- a/packages/geoview-core/src/api/event-processors/event-processor-children/time-slider-event-processor.ts +++ b/packages/geoview-core/src/api/event-processors/event-processor-children/time-slider-event-processor.ts @@ -2,12 +2,15 @@ import { AbstractEventProcessor } from '@/api/event-processors/abstract-event-pr import { AbstractGeoViewVector } from '@/geo/layer/geoview-layers/vector/abstract-geoview-vector'; import { ITimeSliderState, TypeTimeSliderValues } from '@/core/stores/store-interface-and-intial-values/time-slider-state'; import { getLocalizedValue } from '@/core/utils/utilities'; -import { AbstractGeoViewLayer, CONST_LAYER_TYPES } from '@/geo/layer/geoview-layers/abstract-geoview-layers'; +import { CONST_LAYER_TYPES } from '@/geo/layer/geoview-layers/abstract-geoview-layers'; import { EsriDynamic } from '@/geo/layer/geoview-layers/raster/esri-dynamic'; import { WMS } from '@/geo/layer/geoview-layers/raster/wms'; import { TypeFeatureInfoLayerConfig, TypeLayerEntryConfig } from '@/geo/map/map-schema-types'; import { EsriImage } from '@/geo/layer/geoview-layers/raster/esri-image'; import { AppEventProcessor } from './app-event-processor'; +import { MapEventProcessor } from './map-event-processor'; + +// GV Important: See notes in header of MapEventProcessor file for information on the paradigm to apply when working with UIEventProcessor vs UIState export class TimeSliderEventProcessor extends AbstractEventProcessor { // ********************************************************** @@ -33,40 +36,29 @@ export class TimeSliderEventProcessor extends AbstractEventProcessor { /** * Checks if the layer has time slider values. If there are, adds the time slider layer and applies filters. * @param {string} mapId - The map id of the state to act on - * @param {AbstractGeoViewLayer} geoviewLayer - The GeoView layer to act on * @param {TypeLayerEntryConfig} layerConfig - The layer path of the layer to add to the state */ - static checkInitTimeSliderLayerAndApplyFilters( - mapId: string, - geoviewLayer: AbstractGeoViewLayer, - layerConfig: TypeLayerEntryConfig - ): void { + static checkInitTimeSliderLayerAndApplyFilters(mapId: string, layerConfig: TypeLayerEntryConfig): void { // If there is no TimeSlider if (!this.getTimesliderState(mapId)) return; // Get the time slider values - const timeSliderValues = this.getInitialTimeSliderValues(mapId, geoviewLayer, layerConfig); + const timeSliderValues = this.getInitialTimeSliderValues(mapId, layerConfig); // If any if (timeSliderValues) { // Add the time slider in store - this.addTimeSliderLayerAndApplyFilters(mapId, geoviewLayer, layerConfig.layerPath, timeSliderValues); + this.addTimeSliderLayerAndApplyFilters(mapId, layerConfig.layerPath, timeSliderValues); } } /** * Adds a time slider layer to the state * @param {string} mapId - The map id of the state to act on - * @param {AbstractGeoViewLayer} geoviewLayer - The GeoView layer to act on * @param {string} layerPath - The layer path of the layer to add to the state * @param {TypeTimeSliderValues} timeSliderValues - The time slider values to add and apply filters */ - static addTimeSliderLayerAndApplyFilters( - mapId: string, - geoviewLayer: AbstractGeoViewLayer, - layerPath: string, - timeSliderValues: TypeTimeSliderValues - ): void { + static addTimeSliderLayerAndApplyFilters(mapId: string, layerPath: string, timeSliderValues: TypeTimeSliderValues): void { // If there is no TimeSlider if (!this.getTimesliderState(mapId)) return; @@ -74,10 +66,10 @@ export class TimeSliderEventProcessor extends AbstractEventProcessor { const timeSliderLayer = { [layerPath]: timeSliderValues }; // Add it - this.getTimesliderState(mapId)?.actions.addTimeSliderLayer(timeSliderLayer); + this.getTimesliderState(mapId)?.setterActions.addTimeSliderLayer(timeSliderLayer); const { defaultValue, field, filtering, minAndMax, values } = timeSliderLayer[layerPath]; - this.applyFilters(geoviewLayer, layerPath, defaultValue, field, filtering, minAndMax, values); + this.applyFilters(mapId, layerPath, defaultValue, field, filtering, minAndMax, values); } /** @@ -87,25 +79,27 @@ export class TimeSliderEventProcessor extends AbstractEventProcessor { */ static removeTimeSliderLayer(mapId: string, layerPath: string): void { // Redirect - this.getTimesliderState(mapId)?.actions.removeTimeSliderLayer(layerPath); + this.getTimesliderState(mapId)?.setterActions.removeTimeSliderLayer(layerPath); } /** * Get initial values for a layer's time slider states * * @param {string} mapId - The id of the map - * @param {AbstractGeoViewLayer} geoviewLayer - The GeoView layer to act on * @param {TypeLayerEntryConfig} layerConfig - The layer path of the layer to add to the state * @returns {TimeSliderLayer | undefined} */ - static getInitialTimeSliderValues( - mapId: string, - geoviewLayer: AbstractGeoViewLayer, - layerConfig: TypeLayerEntryConfig - ): TypeTimeSliderValues | undefined { - const name = getLocalizedValue(layerConfig.layerName, AppEventProcessor.getDisplayLanguage(mapId)) || layerConfig.layerId; + static getInitialTimeSliderValues(mapId: string, layerConfig: TypeLayerEntryConfig): TypeTimeSliderValues | undefined { + // Get the layer using the map event processor, If no temporal dimension OR layerPath, return undefined + if (!layerConfig.layerPath) return undefined; + const geoviewLayer = MapEventProcessor.getMapViewerLayerAPI(mapId).getGeoviewLayer(layerConfig.layerPath)!; const temporalDimensionInfo = geoviewLayer.getTemporalDimension(layerConfig.layerPath); if (!temporalDimensionInfo || !temporalDimensionInfo.range) return undefined; + + // Get layer name and temporal dimension + const name = getLocalizedValue(layerConfig.layerName, AppEventProcessor.getDisplayLanguage(mapId)) || layerConfig.layerId; + + // Set defaults values from temporal dimension const { range } = temporalDimensionInfo.range; const defaultValueIsArray = Array.isArray(temporalDimensionInfo.default); const defaultValue = defaultValueIsArray ? temporalDimensionInfo.default[0] : temporalDimensionInfo.default; @@ -161,7 +155,7 @@ export class TimeSliderEventProcessor extends AbstractEventProcessor { /** * Filter the layer provided in the layerPath variable according to current states (filtering and values) * - * @param {AbstractGeoViewLayer} geoviewLayer - The GeoView layer to act on + * @param {string} mapId - The id of the map * @param {string} layerPath - The path of the layer to filter * @param {string} defaultValue - The default value to use if filters are off * @param {string} field - The field to filter the layer by @@ -171,7 +165,7 @@ export class TimeSliderEventProcessor extends AbstractEventProcessor { * @returns {void} */ static applyFilters( - geoviewLayer: AbstractGeoViewLayer, + mapId: string, layerPath: string, defaultValue: string, field: string, @@ -179,6 +173,9 @@ export class TimeSliderEventProcessor extends AbstractEventProcessor { minAndMax: number[], values: number[] ): void { + // Get the layer using the map event processor + const geoviewLayer = MapEventProcessor.getMapViewerLayerAPI(mapId).getGeoviewLayer(layerPath)!; + const layerType = geoviewLayer.type; if (layerType === CONST_LAYER_TYPES.WMS) { if (filtering) { @@ -210,6 +207,9 @@ export class TimeSliderEventProcessor extends AbstractEventProcessor { } (geoviewLayer as AbstractGeoViewVector | EsriDynamic).applyViewFilter(layerPath, filter); } + + this.getTimesliderState(mapId)?.setterActions.setFiltering(layerPath, filtering); + this.getTimesliderState(mapId)?.setterActions.setValues(layerPath, values); } // #endregion } diff --git a/packages/geoview-core/src/api/event-processors/event-processor-children/ui-event-processor.ts b/packages/geoview-core/src/api/event-processors/event-processor-children/ui-event-processor.ts index eec837f18ef..f4f54e93366 100644 --- a/packages/geoview-core/src/api/event-processors/event-processor-children/ui-event-processor.ts +++ b/packages/geoview-core/src/api/event-processors/event-processor-children/ui-event-processor.ts @@ -2,19 +2,7 @@ import { TypeMapCorePackages, TypeValidAppBarCoreProps } from '@config/types/map import { AbstractEventProcessor } from '@/api/event-processors/abstract-event-processor'; import { IUIState } from '@/core/stores/store-interface-and-intial-values/ui-state'; -// GV The paradigm when working with UIEventProcessor vs UIState goes like this: -// GV UIState provides: 'state values', 'actions' and 'setterActions'. -// GV Whereas Zustand would suggest having 'state values' and 'actions', in GeoView, we have a 'UIEventProcessor' in the middle. -// GV This is because we wanted to have centralized code between UI actions and backend actions via a UIEventProcessor. -// GV In summary: -// GV The UI components should use UIState's 'state values' to read and 'actions' to set states (which simply redirect to UIEventProcessor). -// GV The back-end code should use UIEventProcessor which uses 'state values' and 'setterActions' -// GV Essentially 3 main call-stacks: -// GV - UIEventProcessor ---calls---> UIState.setterActions -// GV - UI Component ---calls---> UIState.actions ---calls---> UIEventProcessor ---calls---> UIState.setterActions -// GV - UIEventProcessor ---triggers---> UIViewer events ---calls---> UIState.setterActions -// GV The reason for this pattern is so that UI components and processes performing back-end code -// GV both end up running code in UIEventProcessor (UI: via 'actions' and back-end code via 'UIEventProcessor') +// GV Important: See notes in header of MapEventProcessor file for information on the paradigm to apply when working with UIEventProcessor vs UIState export class UIEventProcessor extends AbstractEventProcessor { // ********************************************************** diff --git a/packages/geoview-core/src/app.tsx b/packages/geoview-core/src/app.tsx index 5ca99658861..d30f753e44f 100644 --- a/packages/geoview-core/src/app.tsx +++ b/packages/geoview-core/src/app.tsx @@ -102,8 +102,8 @@ async function getMapConfig(mapElement: Element): Promise } // TODO: inject 'data-geocore-keys' inside the config for later processing by the configAPI - // TD.CONT: This injectioon can be done in api.configApi.getMapConfig with optional parameter keys - // TD.CONT: This will return the listOfGeoviewLAyer with a new entry: {'geoviewLayerType': 'geoCore','geoviewLayerId': '21b821cf-0f1c-40ee-8925-eab12d357668'}, + // TO.DOCONT: This injectioon can be done in api.configApi.getMapConfig with optional parameter keys + // TO.DOCONT: This will return the listOfGeoviewLAyer with a new entry: {'geoviewLayerType': 'geoCore','geoviewLayerId': '21b821cf-0f1c-40ee-8925-eab12d357668'}, // add the map display language and the map id to config (extend the MapFeatureConfig) // eslint-disable-next-line @typescript-eslint/no-explicit-any diff --git a/packages/geoview-core/src/core/stores/store-interface-and-intial-values/app-state.ts b/packages/geoview-core/src/core/stores/store-interface-and-intial-values/app-state.ts index 021fcd3becf..39e61e1d1cf 100644 --- a/packages/geoview-core/src/core/stores/store-interface-and-intial-values/app-state.ts +++ b/packages/geoview-core/src/core/stores/store-interface-and-intial-values/app-state.ts @@ -7,6 +7,12 @@ import { NotificationDetailsType } from '@/core/components/notifications/notific import { TypeHTMLElement, TypeMapFeaturesConfig } from '@/core/types/global-types'; import { logger } from '@/core/utils/logger'; +// GV Important: See notes in header of MapEventProcessor file for information on the paradigm to apply when working with AppEventProcessor vs AppState + +// #region INTERFACES & TYPES + +type AppActions = IAppState['actions']; + export interface IAppState { displayLanguage: TypeDisplayLanguage; displayTheme: TypeDisplayTheme; @@ -40,11 +46,13 @@ export interface IAppState { }; } +// #endregion INTERFACES & TYPES + /** * Initializes an App State and provide functions which use the get/set Zustand mechanisms. * @param {TypeSetStore} set - The setter callback to be used by this state * @param {TypeGetStore} get - The getter callback to be used by this state - * @returns The initialized Map State + * @returns {IAppState} - The initialized App State */ export function initializeAppState(set: TypeSetStore, get: TypeGetStore): IAppState { return { @@ -72,6 +80,7 @@ export function initializeAppState(set: TypeSetStore, get: TypeGetStore): IAppSt }, // #region ACTIONS + actions: { /** * Adds a notification. @@ -132,9 +141,7 @@ export function initializeAppState(set: TypeSetStore, get: TypeGetStore): IAppSt AppEventProcessor.removeNotification(get().mapId, key); }, }, - // #endregion ACTIONS - // #region SETTER ACTIONS setterActions: { /** * Sets the circularProgress state. @@ -232,7 +239,8 @@ export function initializeAppState(set: TypeSetStore, get: TypeGetStore): IAppSt }); }, }, - // #endregion SETTER ACTIONS + + // #endregion ACTIONS } as IAppState; } @@ -258,13 +266,11 @@ export const useAppGeoviewHTMLElement = (): HTMLElement => useStore(useGeoViewSt export const useAppGuide = (): TypeGuideObject | undefined => useStore(useGeoViewStore(), (state) => state.appState.guide); export const useAppNotifications = (): NotificationDetailsType[] => useStore(useGeoViewStore(), (state) => state.appState.notifications); -// GV these 2 selector are use in app-start.tsx before context is assigned to the map +// GV these 2 selectors are use in app-start.tsx before context is assigned to the map // GV DO NOT USE this technique elsewhere, it is only to reload language and theme export const useAppDisplayLanguageById = (mapId: string): TypeDisplayLanguage => useStore(getGeoViewStore(mapId), (state) => state.appState.displayLanguage); export const useAppDisplayThemeById = (mapId: string): TypeDisplayTheme => useStore(getGeoViewStore(mapId), (state) => state.appState.displayTheme); -// TODO: Refactor - We should explicit a type for the appState.actions -// eslint-disable-next-line @typescript-eslint/no-explicit-any -export const useAppStoreActions = (): any => useStore(useGeoViewStore(), (state) => state.appState.actions); +export const useAppStoreActions = (): AppActions => useStore(useGeoViewStore(), (state) => state.appState.actions); diff --git a/packages/geoview-core/src/core/stores/store-interface-and-intial-values/data-table-state.ts b/packages/geoview-core/src/core/stores/store-interface-and-intial-values/data-table-state.ts index cb0a389624e..b5a6c6f916a 100644 --- a/packages/geoview-core/src/core/stores/store-interface-and-intial-values/data-table-state.ts +++ b/packages/geoview-core/src/core/stores/store-interface-and-intial-values/data-table-state.ts @@ -5,7 +5,11 @@ import { TypeFeatureInfoEntry, TypeLayerData } from '@/geo/layer/layer-sets/abst import { TypeSetStore, TypeGetStore } from '@/core/stores/geoview-store'; import { useGeoViewStore } from '@/core/stores/stores-managers'; -// GV Important: See notes in header of DataTableEventProcessor file for information on the paradigm to apply when working with DataTableEventProcessor vs DataTaleState +// GV Important: See notes in header of MapEventProcessor file for information on the paradigm to apply when working with DataTableEventProcessor vs DataTaleState + +// #region INTERFACES & TYPES + +type DataTableActions = IDataTableState['actions']; // Import { MRTColumnFiltersState } from 'material-react-table' fails - This is likely not portable. a type annotation is necessary // Create a type to mimic @@ -60,6 +64,14 @@ export interface IDataTableState { }; } +// #endregion INTERFACES & TYPES + +/** + * Initializes an DataTable State and provide functions which use the get/set Zustand mechanisms. + * @param {TypeSetStore} set - The setter callback to be used by this state + * @param {TypeGetStore} get - The getter callback to be used by this state + * @returns {IDataTableState} - The initialized DataTable State + */ export function initialDataTableState(set: TypeSetStore, get: TypeGetStore): IDataTableState { return { activeLayerData: [], @@ -69,6 +81,8 @@ export function initialDataTableState(set: TypeSetStore, get: TypeGetStore): IDa tableHeight: 600, selectedFeature: null, + // #region ACTIONS + actions: { applyMapFilters: (filterStrings: string): void => { const layerPath = get().dataTableState.selectedLayerPath; @@ -234,6 +248,8 @@ export function initialDataTableState(set: TypeSetStore, get: TypeGetStore): IDa }); }, }, + + // #endregion ACTIONS } as IDataTableState; } @@ -249,6 +265,4 @@ export const useDataTableTableHeight = (): number => useStore(useGeoViewStore(), export const useDataTableSelectedFeature = (): TypeFeatureInfoEntry | null => useStore(useGeoViewStore(), (state) => state.dataTableState.selectedFeature); -// TODO: Refactor - We should explicit a type for the dataTableState.actions -// eslint-disable-next-line @typescript-eslint/no-explicit-any -export const useDataTableStoreActions = (): any => useStore(useGeoViewStore(), (state) => state.dataTableState.actions); +export const useDataTableStoreActions = (): DataTableActions => useStore(useGeoViewStore(), (state) => state.dataTableState.actions); diff --git a/packages/geoview-core/src/core/stores/store-interface-and-intial-values/feature-info-state.ts b/packages/geoview-core/src/core/stores/store-interface-and-intial-values/feature-info-state.ts index caa679dc207..1240c513197 100644 --- a/packages/geoview-core/src/core/stores/store-interface-and-intial-values/feature-info-state.ts +++ b/packages/geoview-core/src/core/stores/store-interface-and-intial-values/feature-info-state.ts @@ -3,6 +3,12 @@ import { TypeSetStore, TypeGetStore } from '@/core/stores/geoview-store'; import { useGeoViewStore } from '@/core/stores/stores-managers'; import { TypeLayerData, TypeFeatureInfoEntry, TypeGeometry } from '@/geo/layer/layer-sets/abstract-layer-set'; +// GV Important: See notes in header of MapEventProcessor file for information on the paradigm to apply when working with FeatureInfoEventProcessor vs FeatureInfoState + +// #region INTERFACES & TYPES + +type FeatureInfoActions = IFeatureInfoState['actions']; + export interface IFeatureInfoState { checkedFeatures: Array; layerDataArray: TypeLayerData[]; @@ -18,8 +24,25 @@ export interface IFeatureInfoState { setLayerDataArrayBatchLayerPathBypass: (layerPath: string) => void; setSelectedLayerPath: (selectedLayerPath: string) => void; }; + + setterActions: { + addCheckedFeature: (feature: TypeFeatureInfoEntry) => void; + removeCheckedFeature: (feature: TypeFeatureInfoEntry | 'all') => void; + setLayerDataArray: (layerDataArray: TypeLayerData[]) => void; + setLayerDataArrayBatch: (layerDataArray: TypeLayerData[]) => void; + setLayerDataArrayBatchLayerPathBypass: (layerPath: string) => void; + setSelectedLayerPath: (selectedLayerPath: string) => void; + }; } +// #endregion INTERFACES & TYPES + +/** + * Initializes an FeatureInfo State and provide functions which use the get/set Zustand mechanisms. + * @param {TypeSetStore} set - The setter callback to be used by this state + * @param {TypeGetStore} get - The getter callback to be used by this state + * @returns {IFeatureInfoState} - The initialized FeatureInfo State + */ export function initFeatureInfoState(set: TypeSetStore, get: TypeGetStore): IFeatureInfoState { return { checkedFeatures: [], @@ -29,7 +52,35 @@ export function initFeatureInfoState(set: TypeSetStore, get: TypeGetStore): IFea selectedLayerPath: '', // #region ACTIONS + actions: { + addCheckedFeature: (feature: TypeFeatureInfoEntry) => { + // Redirect to setter + get().detailsState.setterActions.addCheckedFeature(feature); + }, + removeCheckedFeature: (feature: TypeFeatureInfoEntry | 'all') => { + // Redirect to setter + get().detailsState.setterActions.removeCheckedFeature(feature); + }, + setLayerDataArray(layerDataArray: TypeLayerData[]) { + // Redirect to setter + get().detailsState.setterActions.setLayerDataArray(layerDataArray); + }, + setLayerDataArrayBatch(layerDataArrayBatch: TypeLayerData[]) { + // Redirect to setter + get().detailsState.setterActions.setLayerDataArrayBatch(layerDataArrayBatch); + }, + setLayerDataArrayBatchLayerPathBypass(layerDataArrayBatchLayerPathBypass: string) { + // Redirect to setter + get().detailsState.setterActions.setLayerDataArrayBatchLayerPathBypass(layerDataArrayBatchLayerPathBypass); + }, + setSelectedLayerPath(selectedLayerPath: string) { + // Redirect to setter + get().detailsState.setterActions.setSelectedLayerPath(selectedLayerPath); + }, + }, + + setterActions: { addCheckedFeature: (feature: TypeFeatureInfoEntry) => { set({ detailsState: { @@ -85,6 +136,7 @@ export function initFeatureInfoState(set: TypeSetStore, get: TypeGetStore): IFea }); }, }, + // #endregion ACTIONS } as IFeatureInfoState; } @@ -99,6 +151,4 @@ export const useDetailsLayerDataArrayBatch = (): TypeLayerData[] => useStore(useGeoViewStore(), (state) => state.detailsState.layerDataArrayBatch); export const useDetailsSelectedLayerPath = (): string => useStore(useGeoViewStore(), (state) => state.detailsState.selectedLayerPath); -// TODO: Refactor - We should explicit a type for the featureInfoState.actions -// eslint-disable-next-line @typescript-eslint/no-explicit-any -export const useDetailsStoreActions = (): any => useStore(useGeoViewStore(), (state) => state.detailsState.actions); +export const useDetailsStoreActions = (): FeatureInfoActions => useStore(useGeoViewStore(), (state) => state.detailsState.actions); diff --git a/packages/geoview-core/src/core/stores/store-interface-and-intial-values/geochart-state.ts b/packages/geoview-core/src/core/stores/store-interface-and-intial-values/geochart-state.ts index 8c5721f296b..d4f33e8f1a6 100644 --- a/packages/geoview-core/src/core/stores/store-interface-and-intial-values/geochart-state.ts +++ b/packages/geoview-core/src/core/stores/store-interface-and-intial-values/geochart-state.ts @@ -5,14 +5,16 @@ import { TypeLayerData } from '@/geo/layer/layer-sets/abstract-layer-set'; import { useGeoViewStore } from '@/core/stores/stores-managers'; import { TypeGetStore, TypeSetStore } from '@/core/stores/geoview-store'; +// GV Important: See notes in header of MapEventProcessor file for information on the paradigm to apply when working with GeochartEventProcessor vs GeochartState + +// #region INTERFACES & TYPES + +type GeochartActions = IGeochartState['actions']; + export type GeoChartStoreByLayerPath = { [layerPath: string]: GeoChartConfig; }; -// GV Important: See notes in header of GeochartEventProcessor file for information on the paradigm to apply when working with GeochartEventProcessor vs GeochartState - -// #region INTERFACES - export interface IGeochartState { geochartChartsConfig: GeoChartStoreByLayerPath; layerDataArray: TypeLayerData[]; @@ -37,13 +39,13 @@ export interface IGeochartState { }; } -// #endregion INTERFACES +// #endregion INTERFACES & TYPES /** * Initializes a Geochart state object. - * @param {TypeSetStore} set The store set callback function - * @param {TypeSetStore} get The store get callback function - * @returns {IGeochartState} The Geochart state object + * @param {TypeSetStore} set - The store set callback function + * @param {TypeSetStore} get - The store get callback function + * @returns {IGeochartState} - The Geochart state object */ export function initializeGeochartState(set: TypeSetStore, get: TypeGetStore): IGeochartState { const init = { @@ -137,6 +139,4 @@ export const useGeochartLayerDataArrayBatch = (): TypeLayerData[] => useStore(useGeoViewStore(), (state) => state.geochartState.layerDataArrayBatch); export const useGeochartSelectedLayerPath = (): string => useStore(useGeoViewStore(), (state) => state.geochartState.selectedLayerPath); -// TODO: Refactor - We should explicit a type for the geochartState.actions -// eslint-disable-next-line @typescript-eslint/no-explicit-any -export const useGeochartStoreActions = (): any => useStore(useGeoViewStore(), (state) => state.geochartState.actions); +export const useGeochartStoreActions = (): GeochartActions => useStore(useGeoViewStore(), (state) => state.geochartState.actions); diff --git a/packages/geoview-core/src/core/stores/store-interface-and-intial-values/layer-state.ts b/packages/geoview-core/src/core/stores/store-interface-and-intial-values/layer-state.ts index 04300b87859..f7b33f2c22e 100644 --- a/packages/geoview-core/src/core/stores/store-interface-and-intial-values/layer-state.ts +++ b/packages/geoview-core/src/core/stores/store-interface-and-intial-values/layer-state.ts @@ -14,6 +14,8 @@ import { OL_ZOOM_DURATION, OL_ZOOM_PADDING } from '@/core/utils/constant'; import { MapEventProcessor } from '@/api/event-processors/event-processor-children/map-event-processor'; import { VectorLayerEntryConfig } from '@/core/utils/config/validation-classes/vector-layer-entry-config'; +// #region INTERFACES & TYPES + export interface ILayerState { highlightedLayer: string; selectedLayer: TypeLegendLayer; @@ -39,6 +41,8 @@ export interface ILayerState { }; } +// #endregion INTERFACES & TYPES + export function initializeLayerState(set: TypeSetStore, get: TypeGetStore): ILayerState { const init = { highlightedLayer: '', diff --git a/packages/geoview-core/src/core/stores/store-interface-and-intial-values/map-state.ts b/packages/geoview-core/src/core/stores/store-interface-and-intial-values/map-state.ts index 29e641b189e..424c8ce9445 100644 --- a/packages/geoview-core/src/core/stores/store-interface-and-intial-values/map-state.ts +++ b/packages/geoview-core/src/core/stores/store-interface-and-intial-values/map-state.ts @@ -19,6 +19,10 @@ import { TypeFeatureInfoResultSet } from '@/geo/layer/layer-sets/feature-info-la // GV Important: See notes in header of MapEventProcessor file for information on the paradigm to apply when working with MapEventProcessor vs MapState +// #region INTERFACES & TYPES + +type MapActions = IMapState['actions']; + export interface IMapState { attribution: string[]; basemapOptions: TypeBasemapOptions; @@ -105,11 +109,13 @@ export interface IMapState { }; } +// #endregion INTERFACES & TYPES + /** * Initializes a Map State and provide functions which use the get/set Zustand mechanisms. * @param {TypeSetStore} set - The setter callback to be used by this state * @param {TypeGetStore} get - The getter callback to be used by this state - * @returns The initialized Map State + * @returns {IMapState} - The initialized Map State */ export function initializeMapState(set: TypeSetStore, get: TypeGetStore): IMapState { const init = { @@ -162,6 +168,7 @@ export function initializeMapState(set: TypeSetStore, get: TypeGetStore): IMapSt }, // #region ACTIONS + actions: { /** * Resets the base map. @@ -381,6 +388,7 @@ export function initializeMapState(set: TypeSetStore, get: TypeGetStore): IMapSt */ setOverlayClickMarkerRef: (htmlRef: HTMLElement): void => { // Quick function to set the element on the overlay + // Only fot UI, no redirect to setterAction const overlay = get().mapState.overlayClickMarker; if (overlay !== undefined) overlay.setElement(htmlRef); }, @@ -391,6 +399,7 @@ export function initializeMapState(set: TypeSetStore, get: TypeGetStore): IMapSt */ setOverlayNorthMarkerRef: (htmlRef: HTMLElement): void => { // Quick function to set the element on the overlay + // Only fot UI, no redirect to setterAction const overlay = get().mapState.overlayNorthMarker; if (overlay !== undefined) overlay.setElement(htmlRef); }, @@ -398,7 +407,6 @@ export function initializeMapState(set: TypeSetStore, get: TypeGetStore): IMapSt }, setterActions: { - // #region SETTER ACTIONS /** * Sets the map size and scale. * @param {[number, number]} size - The size of the map. @@ -627,7 +635,7 @@ export function initializeMapState(set: TypeSetStore, get: TypeGetStore): IMapSt setOrderedLayerInfo: (orderedLayerInfo: TypeOrderedLayerInfo[]): void => { // We need to explicitly define ... for the array. If not subscribe does not fired // TODO: refactor - setterActions in setState will recreate array if needed. We need to implement the pattern in all setterActions - // TD.CONT: We should have a deep equality function to compare previous / current + // TO.DOCONT: We should have a deep equality function to compare previous / current set({ mapState: { ...get().mapState, @@ -687,8 +695,9 @@ export function initializeMapState(set: TypeSetStore, get: TypeGetStore): IMapSt }, }); }, - // #endregion SETTER ACTIONS }, + + // #endregion ACTIONS } as IMapState; return init; @@ -740,6 +749,4 @@ export const useMapSize = (): [number, number] => useStore(useGeoViewStore(), (s export const useMapVisibleLayers = (): string[] => useStore(useGeoViewStore(), (state) => state.mapState.visibleLayers); export const useMapZoom = (): number => useStore(useGeoViewStore(), (state) => state.mapState.zoom); -// TODO: Refactor - We should explicit a type for the mapState.actions -// eslint-disable-next-line @typescript-eslint/no-explicit-any -export const useMapStoreActions = (): any => useStore(useGeoViewStore(), (state) => state.mapState.actions); +export const useMapStoreActions = (): MapActions => useStore(useGeoViewStore(), (state) => state.mapState.actions); diff --git a/packages/geoview-core/src/core/stores/store-interface-and-intial-values/swiper-state.ts b/packages/geoview-core/src/core/stores/store-interface-and-intial-values/swiper-state.ts index 72c0f507321..5140d906cee 100644 --- a/packages/geoview-core/src/core/stores/store-interface-and-intial-values/swiper-state.ts +++ b/packages/geoview-core/src/core/stores/store-interface-and-intial-values/swiper-state.ts @@ -2,8 +2,13 @@ import { useStore } from 'zustand'; import { useGeoViewStore } from '@/core/stores/stores-managers'; import { TypeGetStore, TypeSetStore } from '@/core/stores/geoview-store'; +import { SwiperEventProcessor } from '@/api/event-processors/event-processor-children/swiper-event-processor'; -// #region INTERFACES +// GV Important: See notes in header of MapEventProcessor file for information on the paradigm to apply when working with SwiperEventProcessor vs SwiperState + +// #region INTERFACES & TYPES + +type SwiperActions = ISwiperState['actions']; export interface ISwiperState { layerPaths: string[]; @@ -11,15 +16,19 @@ export interface ISwiperState { actions: { setLayerPaths: (layerPaths: string[]) => void; }; + + setterActions: { + setLayerPaths: (layerPaths: string[]) => void; + }; } -// #endregion INTERFACES +// #endregion INTERFACES & TYPES /** * Initializes a Swiper state object. - * @param {TypeSetStore} set The store set callback function - * @param {TypeSetStore} get The store get callback function - * @returns {ISwiperState} The Swiper state object + * @param {TypeSetStore} set - The store set callback function + * @param {TypeSetStore} get - The store get callback function + * @returns {ISwiperState} - The Swiper state object */ export function initializeSwiperState(set: TypeSetStore, get: TypeGetStore): ISwiperState { const init = { @@ -28,6 +37,13 @@ export function initializeSwiperState(set: TypeSetStore, get: TypeGetStore): ISw // #region ACTIONS actions: { + setLayerPaths(layerPaths: string[]) { + // Redirect to SwiperEventProcessor + SwiperEventProcessor.setLayerPaths(get().mapId, layerPaths); + }, + }, + + setterActions: { setLayerPaths(layerPaths: string[]) { set({ swiperState: { @@ -49,6 +65,4 @@ export function initializeSwiperState(set: TypeSetStore, get: TypeGetStore): ISw // ********************************************************** export const useSwiperLayerPaths = (): string[] => useStore(useGeoViewStore(), (state) => state.swiperState.layerPaths); -// TODO: Refactor - We should explicit a type for the swiperState.actions -// eslint-disable-next-line @typescript-eslint/no-explicit-any -export const useSwiperStoreActions = (): any => useStore(useGeoViewStore(), (state) => state.swiperState.actions); +export const useSwiperStoreActions = (): SwiperActions => useStore(useGeoViewStore(), (state) => state.swiperState.actions); diff --git a/packages/geoview-core/src/core/stores/store-interface-and-intial-values/time-slider-state.ts b/packages/geoview-core/src/core/stores/store-interface-and-intial-values/time-slider-state.ts index 3c6de11ac3e..b7f6244879e 100644 --- a/packages/geoview-core/src/core/stores/store-interface-and-intial-values/time-slider-state.ts +++ b/packages/geoview-core/src/core/stores/store-interface-and-intial-values/time-slider-state.ts @@ -2,10 +2,13 @@ import { useStore } from 'zustand'; import { useGeoViewStore } from '@/core/stores/stores-managers'; import { TypeGetStore, TypeSetStore } from '@/core/stores/geoview-store'; import { TimeSliderEventProcessor } from '@/api/event-processors/event-processor-children/time-slider-event-processor'; -import { AbstractGeoViewLayer } from '@/geo/layer/geoview-layers/abstract-geoview-layers'; -import { MapEventProcessor } from '@/api/event-processors/event-processor-children/map-event-processor'; + +// GV Important: See notes in header of MapEventProcessor file for information on the paradigm to apply when working with TimeSliderEventProcessor vs TimeSliderState // #region TYPES & INTERFACES + +type TimeSliderActions = ITimeSliderState['actions']; + export type TimeSliderLayerSet = { [layerPath: string]: TypeTimeSliderValues; }; @@ -32,27 +35,82 @@ export interface ITimeSliderState { timeSliderLayers: TimeSliderLayerSet; actions: { + setTitle: (layerPath: string, title: string) => void; + setDescription: (layerPath: string, description: string) => void; + setDelay: (layerPath: string, delay: number) => void; + setFiltering: (layerPath: string, filter: boolean) => void; + setLocked: (layerPath: string, locked: boolean) => void; + setReversed: (layerPath: string, locked: boolean) => void; + setDefaultValue: (layerPath: string, defaultValue: string) => void; + setValues: (layerPath: string, values: number[]) => void; + }; + + setterActions: { addTimeSliderLayer: (newLayer: TimeSliderLayerSet) => void; - applyFilters: (geoviewLayer: AbstractGeoViewLayer, layerPath: string, values: number[]) => void; removeTimeSliderLayer: (layerPath: string) => void; setTitle: (layerPath: string, title: string) => void; setDescription: (layerPath: string, description: string) => void; setDelay: (layerPath: string, delay: number) => void; - setFiltering: (geoviewLayer: AbstractGeoViewLayer, layerPath: string, filter: boolean) => void; + setFiltering: (layerPath: string, filter: boolean) => void; setLocked: (layerPath: string, locked: boolean) => void; setReversed: (layerPath: string, locked: boolean) => void; setDefaultValue: (layerPath: string, defaultValue: string) => void; setValues: (layerPath: string, values: number[]) => void; }; } + // #endregion INTERFACES +/** + * Initializes an TimeSlider State and provide functions which use the get/set Zustand mechanisms. + * @param {TypeSetStore} set - The setter callback to be used by this state + * @param {TypeGetStore} get - The getter callback to be used by this state + * @returns {ITimeSliderState} - The initialized TimeSlider State + */ export function initializeTimeSliderState(set: TypeSetStore, get: TypeGetStore): ITimeSliderState { const init = { timeSliderLayers: {}, // #region ACTIONS + actions: { + setTitle(layerPath: string, title: string): void { + // Redirect to setter + get().timeSliderState.setterActions.setTitle(layerPath, title); + }, + setDescription(layerPath: string, description: string): void { + // Redirect to setter + get().timeSliderState.setterActions.setDescription(layerPath, description); + }, + setDelay(layerPath: string, delay: number): void { + // Redirect to setter + get().timeSliderState.setterActions.setDelay(layerPath, delay); + }, + setFiltering(layerPath: string, filtering: boolean): void { + // Redirect to TimeSliderEventProcessor + const { defaultValue, field, minAndMax, values } = get().timeSliderState.timeSliderLayers[layerPath]; + TimeSliderEventProcessor.applyFilters(get().mapId, layerPath, defaultValue, field, filtering, minAndMax, values); + }, + setLocked(layerPath: string, locked: boolean): void { + // Redirect to setter + get().timeSliderState.setterActions.setLocked(layerPath, locked); + }, + setReversed(layerPath: string, reversed: boolean): void { + // Redirect to setter + get().timeSliderState.setterActions.setReversed(layerPath, reversed); + }, + setDefaultValue(layerPath: string, defaultValue: string): void { + // Redirect to setter + get().timeSliderState.setterActions.setDefaultValue(layerPath, defaultValue); + }, + setValues(layerPath: string, values: number[]): void { + // Redirect to TimeSliderEventProcessor + const { defaultValue, field, minAndMax, filtering } = get().timeSliderState.timeSliderLayers[layerPath]; + TimeSliderEventProcessor.applyFilters(get().mapId, layerPath, defaultValue, field, filtering, minAndMax, values); + }, + }, + + setterActions: { addTimeSliderLayer(newLayer: TimeSliderLayerSet): void { set({ timeSliderState: { @@ -61,10 +119,6 @@ export function initializeTimeSliderState(set: TypeSetStore, get: TypeGetStore): }, }); }, - applyFilters(geoviewLayer: AbstractGeoViewLayer, layerPath: string, values: number[]): void { - const { defaultValue, field, filtering, minAndMax } = get().timeSliderState.timeSliderLayers[layerPath]; - TimeSliderEventProcessor.applyFilters(geoviewLayer, layerPath, defaultValue, field, filtering, minAndMax, values); - }, removeTimeSliderLayer(layerPath: string): void { const sliderLayers = get().timeSliderState.timeSliderLayers; delete sliderLayers[layerPath]; @@ -105,9 +159,8 @@ export function initializeTimeSliderState(set: TypeSetStore, get: TypeGetStore): }, }); }, - setFiltering(geoviewLayer: AbstractGeoViewLayer, layerPath: string, filtering: boolean): void { + setFiltering(layerPath: string, filtering: boolean): void { const sliderLayers = get().timeSliderState.timeSliderLayers; - const { values } = get().timeSliderState.timeSliderLayers[layerPath]; sliderLayers[layerPath].filtering = filtering; set({ timeSliderState: { @@ -115,7 +168,6 @@ export function initializeTimeSliderState(set: TypeSetStore, get: TypeGetStore): timeSliderLayers: { ...sliderLayers }, }, }); - get().timeSliderState.actions.applyFilters(geoviewLayer, layerPath, values); }, setLocked(layerPath: string, locked: boolean): void { const sliderLayers = get().timeSliderState.timeSliderLayers; @@ -156,15 +208,10 @@ export function initializeTimeSliderState(set: TypeSetStore, get: TypeGetStore): timeSliderLayers: { ...sliderLayers }, }, }); - - // Get the layer using the map event processor (setValues() was called a too many places to provide geoviewLayer by params for now..) - const geoviewLayer = MapEventProcessor.getMapViewerLayerAPI(get().mapId).getGeoviewLayer(layerPath)!; - - // Apply the filters - get().timeSliderState.actions.applyFilters(geoviewLayer, layerPath, values); }, - // #endregion ACTIONS }, + + // #endregion ACTIONS } as ITimeSliderState; return init; @@ -175,6 +222,4 @@ export function initializeTimeSliderState(set: TypeSetStore, get: TypeGetStore): // ********************************************************** export const useTimeSliderLayers = (): TimeSliderLayerSet => useStore(useGeoViewStore(), (state) => state.timeSliderState.timeSliderLayers); -// TODO: Refactor - We should explicit a type for the timeSliderState.actions -// eslint-disable-next-line @typescript-eslint/no-explicit-any -export const useTimeSliderStoreActions = (): any => useStore(useGeoViewStore(), (state) => state.timeSliderState.actions); +export const useTimeSliderStoreActions = (): TimeSliderActions => useStore(useGeoViewStore(), (state) => state.timeSliderState.actions); diff --git a/packages/geoview-core/src/core/stores/store-interface-and-intial-values/ui-state.ts b/packages/geoview-core/src/core/stores/store-interface-and-intial-values/ui-state.ts index a0113af8205..d5c3b199513 100644 --- a/packages/geoview-core/src/core/stores/store-interface-and-intial-values/ui-state.ts +++ b/packages/geoview-core/src/core/stores/store-interface-and-intial-values/ui-state.ts @@ -4,7 +4,11 @@ import { useGeoViewStore } from '@/core/stores/stores-managers'; import { TypeSetStore, TypeGetStore } from '@/core/stores/geoview-store'; import { TypeMapFeaturesConfig } from '@/core/types/global-types'; -// GV Important: See notes in header of UIEventProcessor file for information on the paradigm to apply when working with UIEventProcessor vs UIState +// GV Important: See notes in header of MapEventProcessor file for information on the paradigm to apply when working with UIEventProcessor vs UIState + +// #region INTERFACES & TYPES + +type UIActions = IUIState['actions']; type FocusItemProps = { activeElementId: string | false; @@ -51,6 +55,14 @@ export interface IUIState { }; } +// #endregion INTERFACES & TYPES + +/** + * Initializes an UI State and provide functions which use the get/set Zustand mechanisms. + * @param {TypeSetStore} set - The setter callback to be used by this state + * @param {TypeGetStore} get - The getter callback to be used by this state + * @returns {IUIState} - The initialized UI State + */ export function initializeUIState(set: TypeSetStore, get: TypeGetStore): IUIState { const init = { appBarComponents: ['geolocator'], @@ -78,6 +90,8 @@ export function initializeUIState(set: TypeSetStore, get: TypeGetStore): IUIStat }); }, + // #region ACTIONS + actions: { closeModal: () => { // Redirect to setter @@ -184,7 +198,6 @@ export function initializeUIState(set: TypeSetStore, get: TypeGetStore): IUIStat }); }, setFooterBarIsCollapsed: (collapsed: boolean) => { - // Redirect to setter set({ uiState: { ...get().uiState, @@ -193,6 +206,8 @@ export function initializeUIState(set: TypeSetStore, get: TypeGetStore): IUIStat }); }, }, + + // #endregion ACTIONS } as IUIState; return init; @@ -215,6 +230,4 @@ export const useUIMapInfoExpanded = (): boolean => useStore(useGeoViewStore(), ( export const useUINavbarComponents = (): TypeNavBarProps => useStore(useGeoViewStore(), (state) => state.uiState.navBarComponents); export const useUIFooterBarIsCollapsed = (): boolean => useStore(useGeoViewStore(), (state) => state.uiState.footerBarIsCollapsed); -// TODO: Refactor - We should explicit a type for the uiState.actions -// eslint-disable-next-line @typescript-eslint/no-explicit-any -export const useUIStoreActions = (): any => useStore(useGeoViewStore(), (state) => state.uiState.actions); +export const useUIStoreActions = (): UIActions => useStore(useGeoViewStore(), (state) => state.uiState.actions); diff --git a/packages/geoview-core/src/core/utils/config/validation-classes/config-base-class.ts b/packages/geoview-core/src/core/utils/config/validation-classes/config-base-class.ts index 49d80211385..79639c307be 100644 --- a/packages/geoview-core/src/core/utils/config/validation-classes/config-base-class.ts +++ b/packages/geoview-core/src/core/utils/config/validation-classes/config-base-class.ts @@ -221,9 +221,9 @@ export class ConfigBaseClass { * @param {LayerStatusChangedEvent} event The event to emit * @private */ - // TODO: refactor - if this emit is private with #, abstract-base-layer-entry-config.ts:28 Uncaught (in promise) TypeError: Private element is not present on this object - // TD.CONT: this by pass the error, I need to set this public. The problem come from the groupLayer object trying to emit this event but - // TD.CONT: the event is not define so this.onLayerStatus.... failed + // TODO: refactor - if this emit is privare with #, abstract-base-layer-entry-config.ts:28 Uncaught (in promise) TypeError: Private element is not present on this object + // TO.DOCONT: this by pass the error, I need to set this public. The problem come from the groupLayer object trying to emit this event but + // TO.DOCONT: the event is not define so this.onLayerStatus.... failed #emitLayerStatusChanged(event: LayerStatusChangedEvent): void { // Emit the event for all handlers EventHelper.emitEvent(this, this.#onLayerStatusChangedHandlers, event); diff --git a/packages/geoview-core/src/geo/layer/layer-sets/all-feature-info-layer-set.ts b/packages/geoview-core/src/geo/layer/layer-sets/all-feature-info-layer-set.ts index 9320197a082..9eb42ed4396 100644 --- a/packages/geoview-core/src/geo/layer/layer-sets/all-feature-info-layer-set.ts +++ b/packages/geoview-core/src/geo/layer/layer-sets/all-feature-info-layer-set.ts @@ -42,7 +42,7 @@ export class AllFeatureInfoLayerSet extends AbstractLayerSet { return false; // TODO: there is a synching issue, sometimes source is undefined when layer is registered. To overcome this, - // TD.CONT: if not specified to false by default, we will set it to true + // TO.DOCONT: if not specified to false by default, we will set it to true const queryable = layerConfig?.source?.featureInfo?.queryable; return !!(queryable || queryable === undefined); } diff --git a/packages/geoview-core/src/geo/layer/layer-sets/feature-info-layer-set.ts b/packages/geoview-core/src/geo/layer/layer-sets/feature-info-layer-set.ts index bfd83344456..f10bea9bcd4 100644 --- a/packages/geoview-core/src/geo/layer/layer-sets/feature-info-layer-set.ts +++ b/packages/geoview-core/src/geo/layer/layer-sets/feature-info-layer-set.ts @@ -72,7 +72,7 @@ export class FeatureInfoLayerSet extends AbstractLayerSet { return false; // TODO: there is a synching issue, sometimes source is undefined when layer is registered. To overcome this, - // TD.CONT: if not specified to false by default, we will set it to true + // TO.DOCONT: if not specified to false by default, we will set it to true const queryable = layerConfig?.source?.featureInfo?.queryable; return !!(queryable || queryable === undefined); } diff --git a/packages/geoview-core/src/geo/layer/layer-sets/hover-feature-info-layer-set.ts b/packages/geoview-core/src/geo/layer/layer-sets/hover-feature-info-layer-set.ts index 4645902fe37..420e9ea54e1 100644 --- a/packages/geoview-core/src/geo/layer/layer-sets/hover-feature-info-layer-set.ts +++ b/packages/geoview-core/src/geo/layer/layer-sets/hover-feature-info-layer-set.ts @@ -46,7 +46,7 @@ export class HoverFeatureInfoLayerSet extends AbstractLayerSet { logger.logTraceCore('HOVER-FEATURE-INFO-LAYER-SET - onRegisterLayerCheck', layerConfig.layerPath, Object.keys(this.resultSet)); // TODO: refactor layer - get flag from layer itself, not config - // TD.CONT: we should use the layerPath associated to thelayer we register and do not use layerPath parameter + // TO.DOCONT: we should use the layerPath associated to thelayer we register and do not use layerPath parameter const queryable = layerConfig.schemaTag === CONST_LAYER_TYPES.WMS ? false : layerConfig?.source?.featureInfo?.queryable; return !!queryable; } diff --git a/packages/geoview-core/src/geo/layer/layer.ts b/packages/geoview-core/src/geo/layer/layer.ts index f5d3707d581..f7a87dcdcb5 100644 --- a/packages/geoview-core/src/geo/layer/layer.ts +++ b/packages/geoview-core/src/geo/layer/layer.ts @@ -679,7 +679,7 @@ export class LayerApi { // If the layer is loaded, continue if (geoviewLayer) { // Check and add time slider layer when needed - TimeSliderEventProcessor.checkInitTimeSliderLayerAndApplyFilters(this.mapId, geoviewLayer, layerConfig); + TimeSliderEventProcessor.checkInitTimeSliderLayerAndApplyFilters(this.mapId, layerConfig); } } diff --git a/packages/geoview-core/src/geo/map/map-viewer.ts b/packages/geoview-core/src/geo/map/map-viewer.ts index bfe75e96829..85436a72690 100644 --- a/packages/geoview-core/src/geo/map/map-viewer.ts +++ b/packages/geoview-core/src/geo/map/map-viewer.ts @@ -1442,7 +1442,7 @@ export class MapViewer { // delete the map instance from the maps array, will delete attached plugins // TODO: need a time out here because if not, map is deleted before everything is done on the map - // TD.CONT: This whole sequence need to be async + // TO.DOCONT: This whole sequence need to be async setTimeout(() => delete api.maps[this.mapId], 1000); }) .catch((error) => { @@ -1461,7 +1461,7 @@ export class MapViewer { const mapDiv = this.remove(false); const config = MapEventProcessor.getStoreConfig(this.mapId); // TODO: Remove time out and make this async so remove/recreate work one after the other - // TD.CONT: There is still as problem with bad config schema value and layers loading... should be refactor when config is done + // TO.DOCONT: There is still as problem with bad config schema value and layers loading... should be refactor when config is done setTimeout( // eslint-disable-next-line @typescript-eslint/no-misused-promises () => diff --git a/packages/geoview-time-slider/src/index.tsx b/packages/geoview-time-slider/src/index.tsx index 2bfce52f8ea..82446a79809 100644 --- a/packages/geoview-time-slider/src/index.tsx +++ b/packages/geoview-time-slider/src/index.tsx @@ -170,14 +170,11 @@ class TimeSliderPlugin extends FooterPlugin { const initialTimeSliderLayerPaths = this.#filterTimeSliderLayers(orderedLayerPaths); if (initialTimeSliderLayerPaths) { initialTimeSliderLayerPaths.forEach((layerPath) => { - // Get the layer - const geoviewLayer = this.mapViewer().layer.getGeoviewLayer(layerPath); - // Get the config const layerConfig = this.mapViewer().layer.registeredLayers[layerPath]; // Check and add time slider layer when needed - TimeSliderEventProcessor.checkInitTimeSliderLayerAndApplyFilters(this.pluginProps.mapId, geoviewLayer, layerConfig); + TimeSliderEventProcessor.checkInitTimeSliderLayerAndApplyFilters(this.pluginProps.mapId, layerConfig); }); } });