diff --git a/packages/geoview-core/public/configs/package-time-slider2-config-time-slider.json b/packages/geoview-core/public/configs/package-time-slider2-config-time-slider.json index 89ad2aca7f0..e7b61758e95 100644 --- a/packages/geoview-core/public/configs/package-time-slider2-config-time-slider.json +++ b/packages/geoview-core/public/configs/package-time-slider2-config-time-slider.json @@ -10,9 +10,16 @@ "en": "Custom description", "fr": "Descriptif personnalisé" }, - "locked": true, - "reversed": true, - "defaultValue": "" + "locked": false, + "reversed": false, + "temporalDimension": { + "field": "time_slider_date", + "default": ["1940-01-01T05:00:00Z", "1960-01-01T05:00:00Z"], + "unitSymbol": "", + "range": "1900-01-01T05:00:00Z/2000-01-01T05:00:00Z/P1Y", + "nearestValues": "absolute", + "singleHandle": false + } }, { "layerPaths": ["wmsLYR1-spatiotemporel/RADAR_1KM_RSNO"], @@ -26,10 +33,11 @@ }, "locked": true, "reversed": true, - "defaultValue": "" + "defaultValue": "2024-02-21T14:54:00Z" }, { - "layerPaths": ["MSI/msi-94-or-more"] + "layerPaths": ["MSI/msi-94-or-more"], + "defaultValue": "2011-08-15T00:00:00Z" } ], "suportedLanguages": ["en", "fr"] 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 09550af7c3c..cd4308b37cf 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 @@ -32,6 +32,9 @@ export class TimeSliderEventProcessor extends AbstractEventProcessor { initialTimeSliderLayerPaths.forEach((layerPath) => { const timeSliderLayer = TimeSliderEventProcessor.getInitialTimeSliderValues(mapId, layerPath); store.getState().timeSliderState.actions.addTimeSliderLayer(timeSliderLayer); + + const { defaultValue, field, filtering, minAndMax, values } = timeSliderLayer[layerPath]; + TimeSliderEventProcessor.applyFilters(mapId, layerPath, defaultValue, field, filtering, minAndMax, values); }); } }, @@ -109,9 +112,11 @@ export class TimeSliderEventProcessor extends AbstractEventProcessor { const name = getLocalizedValue(api.maps[mapId].layer.geoviewLayers[layerPath.split('/')[0]].geoviewLayerName, mapId) || layerPath; const temporalDimensionInfo = api.maps[mapId].layer.geoviewLayer(layerPath).getTemporalDimension(); const { range } = temporalDimensionInfo.range; - const defaultValue = temporalDimensionInfo.default; + const defaultValueIsArray = Array.isArray(temporalDimensionInfo.default); + const defaultValue = defaultValueIsArray ? temporalDimensionInfo.default[0] : temporalDimensionInfo.default; const minAndMax: number[] = [new Date(range[0]).getTime(), new Date(range[range.length - 1]).getTime()]; const { field, singleHandle } = temporalDimensionInfo; + // If the field type has an alias, use that as a label let fieldAlias = field; const { featureInfo } = api.maps[mapId].layer.registeredLayers[layerPath].source!; @@ -121,7 +126,13 @@ export class TimeSliderEventProcessor extends AbstractEventProcessor { const fieldIndex = localizedOutFields ? localizedOutFields.indexOf(field) : -1; if (fieldIndex !== -1 && localizedAliasFields?.length === localizedOutFields?.length) fieldAlias = localizedAliasFields![fieldIndex]; - const values = singleHandle ? [new Date(temporalDimensionInfo.default).getTime()] : [...minAndMax]; + // eslint-disable-next-line no-nested-ternary + const values = singleHandle + ? [new Date(temporalDimensionInfo.default).getTime()] + : defaultValueIsArray + ? [new Date(temporalDimensionInfo.default[0]).getTime(), new Date(temporalDimensionInfo.default[1]).getTime()] + : [...minAndMax]; + const sliderData: TimeSliderLayerSet = { [layerPath]: { name, 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 05c7476bbfa..9816b9f18c6 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 @@ -166,5 +166,4 @@ export function initializeTimeSliderState(set: TypeSetStore, get: TypeGetStore): // Layer state selectors // ********************************************************** export const useTimeSliderLayers = () => useStore(useGeoViewStore(), (state) => state.timeSliderState.timeSliderLayers); - export const useTimeSliderStoreActions = () => useStore(useGeoViewStore(), (state) => state.timeSliderState.actions); 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..4b4fbd25768 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 @@ -1499,6 +1499,17 @@ export abstract class AbstractGeoViewLayer { return this.layerTemporalDimension[layerPath]; } + /** *************************************************************************************************************************** + * Set the layerTemporalDimension for the layer identified by specified layerPath. + * + * @param {string} layerPath The layer path to the layer's configuration affected by the change. + * @param {TimeDimension} temporalDimension The value to assign to the layer temporal dimension property. + */ + setTemporalDimension(layerPath: string, temporalDimension: TimeDimension): void { + layerPath = layerPath || this.layerPathAssociatedToTheGeoviewLayer; + this.layerTemporalDimension[layerPath] = temporalDimension; + } + /** *************************************************************************************************************************** * Get the bounds of the layer represented in the layerConfig pointed to by the cached layerPath, returns updated bounds * diff --git a/packages/geoview-time-slider/src/index.tsx b/packages/geoview-time-slider/src/index.tsx index 70f4f6d7e42..0b2efafcce3 100644 --- a/packages/geoview-time-slider/src/index.tsx +++ b/packages/geoview-time-slider/src/index.tsx @@ -1,10 +1,11 @@ -import { AnySchemaObject, Cast, toJsonObject, TypeJsonObject, TypeTabs } from 'geoview-core'; +import { AnySchemaObject, api, Cast, TimeDimension, toJsonObject, TypeJsonObject, TypeTabs } from 'geoview-core'; import { TimeSliderIcon } from 'geoview-core/src/ui'; import { FooterPlugin } from 'geoview-core/src/api/plugin/footer-plugin'; import { TimeSliderPanel } from './time-slider-panel'; import schema from '../schema.json'; import defaultConfig from '../default-config-time-slider-panel.json'; +import { SliderProps } from './time-slider-types'; export interface LayerProps { layerPath: string; @@ -96,6 +97,31 @@ class TimeSliderPlugin extends FooterPlugin { }); onCreateContentProps = (): TypeTabs => { + // Set custom time dimension if applicable + this.configObj.sliders.forEach((obj: SliderProps) => { + if (obj.temporalDimension) { + const timeDimension: TimeDimension = { + field: obj.temporalDimension.field, + default: obj.temporalDimension.default, + unitSymbol: obj.temporalDimension.unitSymbol, + nearestValues: obj.temporalDimension.nearestValues, + range: api.dateUtilities.createRangeOGC(obj.temporalDimension.range as unknown as string), + singleHandle: obj.temporalDimension.singleHandle, + }; + api.maps[this.pluginProps.mapId].layer.geoviewLayer(obj.layerPaths[0]).setTemporalDimension(obj.layerPaths[0], timeDimension); + } + + // Set override default value under time dimension if applicable + if (obj.defaultValue) { + const layerPath = obj.layerPaths[0]; + const timeDimension = api.maps[this.pluginProps.mapId].layer.geoviewLayer(layerPath).layerTemporalDimension[layerPath]; + api.maps[this.pluginProps.mapId].layer.geoviewLayer(layerPath).setTemporalDimension(layerPath, { + ...timeDimension, + default: obj.defaultValue, + }); + } + }); + return { id: 'time-slider', value: this.value!, diff --git a/packages/geoview-time-slider/src/time-slider-types.tsx b/packages/geoview-time-slider/src/time-slider-types.tsx index bf74cd4d56a..3bfc37d7a53 100644 --- a/packages/geoview-time-slider/src/time-slider-types.tsx +++ b/packages/geoview-time-slider/src/time-slider-types.tsx @@ -1,3 +1,4 @@ +import { TimeDimension } from 'geoview-core'; import { TypeLocalizedString } from 'geoview-core/src/geo/map/map-schema-types'; export type SliderProps = { @@ -7,6 +8,7 @@ export type SliderProps = { locked: boolean; reversed: boolean; defaultValue: string; + temporalDimension: TimeDimension; }; export type ConfigProps = { diff --git a/packages/geoview-time-slider/src/time-slider.tsx b/packages/geoview-time-slider/src/time-slider.tsx index c20b378c0fd..86352344355 100644 --- a/packages/geoview-time-slider/src/time-slider.tsx +++ b/packages/geoview-time-slider/src/time-slider.tsx @@ -51,7 +51,7 @@ export function TimeSlider(TimeSliderPanelProps: TimeSliderPanelProps) { // Get actions and states from store // TODO: evaluate best option to set value by layer path.... trough a getter? - const { setTitle, setDescription, setDefaultValue, setValues, setLocked, setReversed, setDelay, setFiltering } = + const { setTitle, setDefaultValue, setDescription, setValues, setLocked, setReversed, setDelay, setFiltering } = useTimeSliderStoreActions(); // TODO: check performance as we should technically have one selector by constant @@ -78,14 +78,28 @@ export function TimeSlider(TimeSliderPanelProps: TimeSliderPanelProps) { const sliderConfig = config?.sliders?.find((o: { layerPaths: string[] }) => o.layerPaths.includes(layerPath)); if (title === undefined) setTitle(layerPath, getLocalizedValue(sliderConfig?.title, mapId) || ''); if (description === undefined) setDescription(layerPath, getLocalizedValue(sliderConfig?.description, mapId) || ''); - if (defaultValue === undefined) setDefaultValue(layerPath, sliderConfig?.defaultValue || ''); if (locked === undefined) setLocked(layerPath, sliderConfig?.locked !== undefined ? sliderConfig?.locked : false); if (reversed === undefined) setReversed(layerPath, sliderConfig?.reversed !== undefined ? sliderConfig?.reversed : false); + if (defaultValue === undefined) setDefaultValue(layerPath, sliderConfig?.defaultValue || ''); // eslint-disable-next-line react-hooks/exhaustive-deps }, []); - const timeStampRange = range.map((entry: string | number | Date) => new Date(entry).getTime()); + useEffect(() => { + const sliderConfig = config?.sliders?.find((o: { layerPaths: string[] }) => o.layerPaths.includes(layerPath)); + if (sliderConfig?.defaultValue) { + // update values based on slider's default value + const defaultValueIsArray = Array.isArray(sliderConfig?.defaultValue); + if (defaultValueIsArray) { + setValues(layerPath, [new Date(sliderConfig?.defaultValue[0]).getTime(), new Date(sliderConfig?.defaultValue[1]).getTime()]); + } else if (range.includes(sliderConfig?.defaultValue)) { + setValues(layerPath, [new Date(sliderConfig?.defaultValue).getTime()]); + } else { + setValues(layerPath, [new Date(range[0]).getTime()]); + } + } + }, [config, layerPath, range, setFiltering, setValues]); + const timeStampRange = range.map((entry: string | number | Date) => new Date(entry).getTime()); // Check if range occurs in a single day or year const timeDelta = minAndMax[1] - minAndMax[0]; const dayDelta = new Date(minAndMax[1]).getDate() - new Date(minAndMax[0]).getDate(); @@ -332,7 +346,6 @@ export function TimeSlider(TimeSliderPanelProps: TimeSliderPanelProps) { style={{ width: '80%', color: 'primary' }} min={minAndMax[0]} max={minAndMax[1]} - defaultValue={Number(defaultValue)} value={values} valueLabelFormat={(value) => valueLabelFormat(value)} marks={sliderMarks}