From 54fd4b36b2a9bb6b7f4a3b97a1c1aa96ce3180d6 Mon Sep 17 00:00:00 2001 From: RowHeat <40065760+rowheat02@users.noreply.github.com> Date: Thu, 27 Aug 2026 18:26:03 +0545 Subject: [PATCH] Add information for Timeline plugin when no time dimension layer is selected in TOC #11959 (#12828) * show timeline warning when guide layer is hidden on toc * Apply suggestions from code review Co-authored-by: Lorenzo Natali --------- Co-authored-by: Lorenzo Natali (cherry picked from commit 9c7b45389f8e03b273533b4290fe3572192d0d68) --- web/client/plugins/Timeline.jsx | 19 ++++++++++++++++--- .../plugins/__tests__/Timeline-test.jsx | 16 ++++++++++++++++ web/client/themes/default/less/timeline.less | 4 +++- web/client/translations/data.de-DE.json | 1 + web/client/translations/data.en-US.json | 1 + web/client/translations/data.es-ES.json | 1 + web/client/translations/data.fr-FR.json | 1 + web/client/translations/data.it-IT.json | 1 + 8 files changed, 40 insertions(+), 4 deletions(-) diff --git a/web/client/plugins/Timeline.jsx b/web/client/plugins/Timeline.jsx index 156196ac887..770ec84ed80 100644 --- a/web/client/plugins/Timeline.jsx +++ b/web/client/plugins/Timeline.jsx @@ -39,12 +39,14 @@ import withResizeSpy from '../components/misc/enhancers/withResizeSpy'; import Toolbar from '../components/misc/toolbar/Toolbar'; import InlineDateTimeSelector from '../components/time/InlineDateTimeSelector'; import { currentTimeSelector, offsetEnabledSelector } from '../selectors/dimension'; +import { getEffectivelyVisibleLayers } from '../selectors/layers'; import { playbackRangeSelector, statusSelector } from '../selectors/playback'; import { currentTimeRangeSelector, isMapSync, isVisible, rangeSelector, + selectedLayerData, selectedLayerSelector, timelineLayersSelector } from '../selectors/timeline'; @@ -103,7 +105,9 @@ const TimelinePlugin = compose( rangeSelector, (state) => state.timeline?.loader !== undefined, selectedLayerSelector, - (visible, layers, currentTime, currentTimeRange, offsetEnabled, playbackRange, status, viewRange, timelineIsReady, selectedLayer) => ({ + selectedLayerData, + getEffectivelyVisibleLayers, + (visible, layers, currentTime, currentTimeRange, offsetEnabled, playbackRange, status, viewRange, timelineIsReady, selectedLayer, selectedLayerObject, effectivelyVisibleLayers) => ({ visible, layers, currentTime, @@ -113,7 +117,9 @@ const TimelinePlugin = compose( status, viewRange, timelineIsReady, - selectedLayer + selectedLayer, + selectedLayerIsHidden: !!selectedLayerObject + && !effectivelyVisibleLayers.some(({ id }) => id === selectedLayer) }) ), { setCurrentTime: selectTime, @@ -200,7 +206,8 @@ const TimelinePlugin = compose( initialSnap = 'now', resetButton, reset = () => {}, - selectedLayer + selectedLayer, + selectedLayerIsHidden }) => { useEffect(()=>{ // update state with configs coming from configuration file like localConfig.json so that can be used as props initializer @@ -328,6 +335,12 @@ const TimelinePlugin = compose( tooltip={}> + {selectedLayerIsHidden && } {!timelineIsReady &&
diff --git a/web/client/plugins/__tests__/Timeline-test.jsx b/web/client/plugins/__tests__/Timeline-test.jsx index ff9ec814f61..b9584cd9baa 100644 --- a/web/client/plugins/__tests__/Timeline-test.jsx +++ b/web/client/plugins/__tests__/Timeline-test.jsx @@ -134,6 +134,22 @@ describe('Timeline Plugin', () => { ReactDOM.render(, document.getElementById("container")); expect(document.querySelector('.timeline-plugin.hidden')).toBeTruthy(); }); + it('shows the warning when the hidden selected layer is not displayed in the timeline', () => { + const state = { + ...FALSY_STATE, + layers: { + ...FALSY_STATE.layers, + flat: FALSY_STATE.layers.flat.map(layer => + layer.id === 'TEST_LAYER_2' ? { ...layer, visibility: true } : layer + ) + } + }; + const { Plugin } = getPluginForTest(TimelinePlugin, state); + ReactDOM.render(, document.getElementById("container")); + + const warning = document.querySelector('.ms-timeline-visibility-warning'); + expect(warning).toBeTruthy(); + }); it('Timeline plugin is not visible when there are no layers with dimension data', ()=>{ const { Plugin } = getPluginForTest(TimelinePlugin, {}); ReactDOM.render(, document.getElementById("container")); diff --git a/web/client/themes/default/less/timeline.less b/web/client/themes/default/less/timeline.less index 58c249bd331..b78308bd26b 100644 --- a/web/client/themes/default/less/timeline.less +++ b/web/client/themes/default/less/timeline.less @@ -378,11 +378,13 @@ font-weight: bold; } } - .ms-timeline-expand { + .ms-timeline-expand, + .ms-timeline-visibility-warning { flex-shrink: 0; border-radius: 4px; height: 30px; width: 30px; + margin-right: 4px; } /* local mixin to highlight handlers on timeline, used on active and over */ diff --git a/web/client/translations/data.de-DE.json b/web/client/translations/data.de-DE.json index c186fa5f87a..670693b79c1 100644 --- a/web/client/translations/data.de-DE.json +++ b/web/client/translations/data.de-DE.json @@ -3181,6 +3181,7 @@ "disableRange": "Zeitbereich deaktivieren", "enablePlayBack": "Aktivieren Sie die Wiedergabesteuerung", "disablePlayBack": "Deaktivieren Sie die Wiedergabesteuerung", + "hiddenGuideLayerWarning": "Die Führungslayer ist im Inhaltsverzeichnis und auf der Karte ausgeblendet, steuert aber weiterhin das Einrasten der Zeitleiste.", "expand": "Erweitern Sie den Zeitschieberegler", "collapse": "Schieberegler für die Zeitspanne reduzieren", "reset": { diff --git a/web/client/translations/data.en-US.json b/web/client/translations/data.en-US.json index 05c9e9dc490..07af09da298 100644 --- a/web/client/translations/data.en-US.json +++ b/web/client/translations/data.en-US.json @@ -3150,6 +3150,7 @@ "disableRange": "Disable time range", "enablePlayBack": "Enable playback controls", "disablePlayBack": "Disable playback controls", + "hiddenGuideLayerWarning": "The guide layer is hidden in the TOC and on the map, but continues to control timeline snapping.", "expand": "Expand time slider", "collapse": "Collapse time slider", "reset": { diff --git a/web/client/translations/data.es-ES.json b/web/client/translations/data.es-ES.json index 5f1a516a0e8..eb393b78b0c 100644 --- a/web/client/translations/data.es-ES.json +++ b/web/client/translations/data.es-ES.json @@ -3138,6 +3138,7 @@ "disableRange": "Desactivar intervalo de tiempo", "enablePlayBack": "Habilitar controles de reproducción", "disablePlayBack": "Deshabilitar los controles de reproducción", + "hiddenGuideLayerWarning": "La capa guía está oculta en la TOC y en el mapa, pero sigue controlando el ajuste de la línea de tiempo.", "expand": "Expandir el control deslizante de tiempo", "collapse": "Minimizar el control deslizante de tiempo", "reset": { diff --git a/web/client/translations/data.fr-FR.json b/web/client/translations/data.fr-FR.json index 9251f841d68..8e5a6990c7e 100644 --- a/web/client/translations/data.fr-FR.json +++ b/web/client/translations/data.fr-FR.json @@ -3142,6 +3142,7 @@ "disableRange": "Désactiver la plage de temps", "enablePlayBack": "Activer les contrôles de lecture", "disablePlayBack": "Désactiver les contrôles de lecture", + "hiddenGuideLayerWarning": "Le couche de référence est masquée dans la TOC et sur la carte, mais continue de contrôler l'accrochage de la chronologie.", "expand": "Développer le curseur temporel", "collapse": "Réduire le curseur temporel", "reset": { diff --git a/web/client/translations/data.it-IT.json b/web/client/translations/data.it-IT.json index 0ab5574b875..c1e85322cc7 100644 --- a/web/client/translations/data.it-IT.json +++ b/web/client/translations/data.it-IT.json @@ -3142,6 +3142,7 @@ "disableRange": "Disabilita intervallo", "enablePlayBack": "Abilita i controlli di riproduzione", "disablePlayBack": "Disabilita i controlli di riproduzione", + "hiddenGuideLayerWarning": "Il layer guida è nascosto nel TOC e sulla mappa, ma continua a controllare l'aggancio della timeline.", "expand": "Espandi", "collapse": "Riduci", "reset": {