From acceff795256965aea87caf2eb9094b9ecc987b1 Mon Sep 17 00:00:00 2001 From: Area52_Nader <86432017+NaderArea52@users.noreply.github.com> Date: Fri, 16 Oct 2026 10:39:26 -0300 Subject: [PATCH] feat: calendar date range as alternative to the time filter slider - New DateRangeFilter component with separate From and To date pickers (NcDateTimePicker). Days outside the available data are grayed out, From can not be after To. Reset selects the full data range. - Settings: choose between Slider and Calendar (timeFilterMode option) - The calendar remembers its selection after a page reload (dateFilterStart/dateFilterEnd options). A bound at the edge of the data is saved as open so new data stays visible. - maxDataTimestamp now ignores data types without dates (they defaulted to now) and includes the newest device point. Implements #1222 Co-Authored-By: Claude Opus 5.5 (1M context) Signed-off-by: Area52_Nader <86432017+NaderArea52@users.noreply.github.com> --- src/components/Map.vue | 12 +- src/components/MapsNavigation.vue | 28 ++++- src/components/map/DateRangeFilter.vue | 165 +++++++++++++++++++++++++ src/views/App.vue | 50 ++++++-- 4 files changed, 246 insertions(+), 9 deletions(-) create mode 100644 src/components/map/DateRangeFilter.vue diff --git a/src/components/Map.vue b/src/components/Map.vue index 8ecc40044..1d457778a 100644 --- a/src/components/Map.vue +++ b/src/components/Map.vue @@ -143,7 +143,13 @@ - + [], devicesEnabled: false, sliderEnabled: false, + timeFilterMode: 'slider', sliderStartTimestamp: 0, sliderEndTimestamp: 0, minDataTimestamp: 0, diff --git a/src/components/MapsNavigation.vue b/src/components/MapsNavigation.vue index c0473c459..7fd1e3895 100644 --- a/src/components/MapsNavigation.vue +++ b/src/components/MapsNavigation.vue @@ -51,6 +51,15 @@ + + + + @@ -77,8 +86,10 @@ import { NcFormBoxButton, NcFormBoxSwitch, NcLoadingIcon, + NcRadioGroup, + NcRadioGroupButton, } from '@nextcloud/vue' -import { reactive, ref } from 'vue' +import { computed, reactive, ref } from 'vue' import IconCog from 'vue-material-design-icons/CogOutline.vue' import IconOpenInApp from 'vue-material-design-icons/OpenInApp.vue' import IconPlus from 'vue-material-design-icons/Plus.vue' @@ -97,10 +108,12 @@ const emit = defineEmits<{ 'toggle-trackme': [enabled: boolean] 'register-geo-link': [] 'toggle-slider': [enabled: boolean] + 'change-time-filter-mode': [mode: string] }>() const optionValues = reactive(optionsController.optionValues) const settingsOpen = ref(false) +const timeFilterMode = computed(() => optionValues.timeFilterMode === 'calendar' ? 'calendar' : 'slider') /** * @param checked whether the position should be tracked @@ -119,6 +132,15 @@ function onDisplaySliderChange(checked: boolean): void { optionsController.saveOptionValues({ displaySlider: optionValues.displaySlider }) emit('toggle-slider', checked) } + +/** + * @param mode 'slider' or 'calendar' + */ +function onTimeFilterModeChange(mode: string): void { + optionValues.timeFilterMode = mode + optionsController.saveOptionValues({ timeFilterMode: mode }) + emit('change-time-filter-mode', mode) +} diff --git a/src/views/App.vue b/src/views/App.vue index ce0661f02..2a45104d5 100644 --- a/src/views/App.vue +++ b/src/views/App.vue @@ -13,6 +13,7 @@ :show-settings="!token" @toggle-trackme="onToggleTrackme" @toggle-slider="onToggleSlider" + @change-time-filter-mode="timeFilterMode = $event" @register-geo-link="onRegisterGeoLink">