This is an automated email from the ASF dual-hosted git repository.

riemer pushed a commit to branch dev
in repository https://gitbox.apache.org/repos/asf/streampipes.git


The following commit(s) were added to refs/heads/dev by this push:
     new 4a2ef4513d fix: Resolve minor bugs in time selection component (#3336)
4a2ef4513d is described below

commit 4a2ef4513dece03f953f65769fd5447cc0e625e5
Author: Dominik Riemer <[email protected]>
AuthorDate: Tue Nov 19 09:53:16 2024 +0100

    fix: Resolve minor bugs in time selection component (#3336)
    
    * Time range selector moved to shared-ui
    
    * Changed imports for time selection serivce
    
    * Modify imports
    
    * Added option to customize date range quick selections
    
    * Add max day range and customizable labels in time range selector
    
    * Add license header for time-selector-model
    
    * Add feature to set date format to local settings
    
    * Fix time selection
    
    ---------
    
    Co-authored-by: Marcelfrueh <[email protected]>
---
 .../src/lib/model/datalake/DateRange.ts            | 48 ++++++++++-
 ui/projects/streampipes/shared-ui/package.json     |  3 +-
 .../time-range-selector.component.html             | 39 +++++----
 .../time-range-selector.component.scss             |  5 +-
 .../time-selector/time-range-selector.component.ts | 66 +++++++++++++---
 .../custom-time-range-selection.component.html     | 18 ++++-
 .../custom-time-range-selection.component.scss     |  5 ++
 .../custom-time-range-selection.component.ts       | 63 +++++++++++++--
 .../time-selector-menu.component.html              | 11 ++-
 .../time-selector-menu.component.scss              |  0
 .../time-selector-menu.component.ts                | 17 +++-
 .../time-selector/time-selector.model.ts}          |  8 +-
 .../src/lib}/services/time-selection.service.ts    | 92 ++++++++++++++--------
 .../shared-ui/src/lib/shared-ui.module.ts          | 18 +++++
 .../streampipes/shared-ui/src/public-api.ts        |  4 +
 .../streampipes/shared-ui/tsconfig.lib.json        |  2 +-
 .../data-explorer-dashboard-panel.component.ts     |  8 +-
 .../data-view/data-explorer-data-view.component.ts |  3 +-
 .../data-explorer-dashboard-widget.component.ts    |  4 +-
 .../base/base-data-explorer-widget.directive.ts    |  4 +-
 ui/src/app/data-explorer/data-explorer.module.ts   | 13 ---
 .../data-explorer-detect-changes.service.ts        |  2 +-
 22 files changed, 328 insertions(+), 105 deletions(-)

diff --git 
a/ui/projects/streampipes/platform-services/src/lib/model/datalake/DateRange.ts 
b/ui/projects/streampipes/platform-services/src/lib/model/datalake/DateRange.ts
index 9f3cff7d29..f061e5daff 100644
--- 
a/ui/projects/streampipes/platform-services/src/lib/model/datalake/DateRange.ts
+++ 
b/ui/projects/streampipes/platform-services/src/lib/model/datalake/DateRange.ts
@@ -21,7 +21,50 @@ export interface TimeSettings {
     endTime: number;
     // deprecated
     dynamicSelection?: 15 | 60 | 1440 | 10080 | 43800 | 525600 | -1;
-    timeSelectionId?: TimeSelectionId;
+    timeSelectionId?: string;
+}
+
+export class TimeSelectionConstants {
+    static CUSTOM = 'custom';
+    static LAST_15_MINUTES = 'last-15-minutes';
+    static LAST_HOUR = 'last-hour';
+    static CURRENT_HOUR = 'current-hour';
+    static LAST_DAY = 'last-day';
+    static CURRENT_DAY = 'current-day';
+    static LAST_WEEK = 'last-week';
+    static CURRENT_WEEK = 'current-week';
+    static LAST_MONTH = 'last-month';
+    static CURRENT_MONTH = 'current-month';
+    static LAST_YEAR = 'last-year';
+    static CURRENT_YEAR = 'current-year';
+
+    static getLegacyTimeSelectionID(legacyID: number) {
+        if (legacyID === 0) {
+            return TimeSelectionConstants.CUSTOM;
+        } else if (legacyID === 1) {
+            return TimeSelectionConstants.LAST_15_MINUTES;
+        } else if (legacyID === 2) {
+            return TimeSelectionConstants.LAST_HOUR;
+        } else if (legacyID === 3) {
+            return TimeSelectionConstants.CURRENT_HOUR;
+        } else if (legacyID === 4) {
+            return TimeSelectionConstants.LAST_DAY;
+        } else if (legacyID === 5) {
+            return TimeSelectionConstants.CURRENT_DAY;
+        } else if (legacyID === 6) {
+            return TimeSelectionConstants.LAST_WEEK;
+        } else if (legacyID === 7) {
+            return TimeSelectionConstants.CURRENT_WEEK;
+        } else if (legacyID === 8) {
+            return TimeSelectionConstants.LAST_MONTH;
+        } else if (legacyID === 9) {
+            return TimeSelectionConstants.CURRENT_MONTH;
+        } else if (legacyID === 10) {
+            return TimeSelectionConstants.LAST_YEAR;
+        } else if (legacyID === 11) {
+            return TimeSelectionConstants.CURRENT_YEAR;
+        }
+    }
 }
 
 export interface WidgetTimeSettings {
@@ -34,6 +77,7 @@ export interface TimeString {
     startTime: string;
     endDate: string;
     endTime: string;
+    sameDay: boolean;
 }
 
 export enum TimeSelectionId {
@@ -53,7 +97,7 @@ export enum TimeSelectionId {
 
 export interface QuickTimeSelection {
     label: string;
-    timeSelectionId: TimeSelectionId;
+    timeSelectionId: string;
     startTime: (now: Date) => Date;
     endTime: (now: Date) => Date;
     addDividerAfter?: boolean;
diff --git a/ui/projects/streampipes/shared-ui/package.json 
b/ui/projects/streampipes/shared-ui/package.json
index f2f8f4d9b5..6f8f27f9ef 100644
--- a/ui/projects/streampipes/shared-ui/package.json
+++ b/ui/projects/streampipes/shared-ui/package.json
@@ -10,7 +10,8 @@
     "@angular/material": "^17.3.3",
     "@angular/router": "^17.3.3",
     "@streampipes/platform-services": "0.0.1",
-    "rxjs": "^7.5.7"
+    "rxjs": "^7.5.7",
+    "date-fns": "^3.6.0"
   },
   "dependencies": {
     "tslib": "^2.6.2"
diff --git 
a/ui/src/app/data-explorer/components/time-selector/time-range-selector.component.html
 
b/ui/projects/streampipes/shared-ui/src/lib/components/time-selector/time-range-selector.component.html
similarity index 70%
rename from 
ui/src/app/data-explorer/components/time-selector/time-range-selector.component.html
rename to 
ui/projects/streampipes/shared-ui/src/lib/components/time-selector/time-range-selector.component.html
index eb51825326..a959404dca 100644
--- 
a/ui/src/app/data-explorer/components/time-selector/time-range-selector.component.html
+++ 
b/ui/projects/streampipes/shared-ui/src/lib/components/time-selector/time-range-selector.component.html
@@ -30,25 +30,28 @@
             color="accent"
             [matMenuTriggerFor]="menu"
             #menuTrigger="matMenuTrigger"
-            matTooltip="Modify time"
+            [matTooltip]="labels.timeRangeSelectorTooltip"
             data-cy="time-selector-menu"
             (menuClosed)="menuTrigger.closeMenu()"
         >
-            <div *ngIf="timeStringMode === 'advanced'">
-                <div class="formatted-datetime">
-                    <span class="formatted-date">{{
-                        timeString.startDate
-                    }}</span
-                    >&nbsp;
-                    <span class="formatted-time">{{
+            <div
+                *ngIf="timeStringMode === 'advanced'"
+                class="formatted-datetime"
+            >
+                <span class="formatted-date">{{ timeString.startDate }}</span>
+                <span *ngIf="enableTimeChange">
+                    &nbsp;<span class="formatted-time">{{
                         timeString.startTime
                     }}</span>
-                </div>
-                -
-                <div class="formatted-datetime">
-                    <span class="formatted-date">{{ timeString.endDate }}</span
-                    >&nbsp;
-                    <span class="formatted-time">{{ timeString.endTime 
}}</span>
+                </span>
+                <div *ngIf="enableTimeChange || !timeString.sameDay">
+                    <span class="formatted-date">&nbsp;-&nbsp;</span>
+                    <span class="formatted-date">{{ timeString.endDate 
}}</span>
+                    <span *ngIf="enableTimeChange">
+                        &nbsp;<span class="formatted-time">{{
+                            timeString.endTime
+                        }}</span>
+                    </span>
                 </div>
             </div>
             <div class="formatted-datetime" *ngIf="timeStringMode === 
'simple'">
@@ -63,7 +66,11 @@
             <sp-time-selector-menu
                 #timeSelectorMenu
                 [timeSettings]="timeSettings"
+                [labels]="labels"
                 (timeSettingsEmitter)="applyCurrentDateRange($event)"
+                [quickSelections]="quickSelections"
+                [enableTimeChange]="enableTimeChange"
+                [maxDayRange]="maxDayRange"
                 class="w-100"
             >
             </sp-time-selector-menu>
@@ -71,12 +78,12 @@
     </div>
     <div fxLayoutAlign="end center">
         <button
-            mat-button
+            mat-icon-button
+            matTooltip="Refresh"
             color="accent"
             (click)="updateTimeSettingsAndReload()"
         >
             <mat-icon>refresh</mat-icon>
-            Refresh
         </button>
     </div>
 </div>
diff --git 
a/ui/src/app/data-explorer/components/time-selector/time-range-selector.component.scss
 
b/ui/projects/streampipes/shared-ui/src/lib/components/time-selector/time-range-selector.component.scss
similarity index 96%
rename from 
ui/src/app/data-explorer/components/time-selector/time-range-selector.component.scss
rename to 
ui/projects/streampipes/shared-ui/src/lib/components/time-selector/time-range-selector.component.scss
index aef8593a37..19107dc1c1 100644
--- 
a/ui/src/app/data-explorer/components/time-selector/time-range-selector.component.scss
+++ 
b/ui/projects/streampipes/shared-ui/src/lib/components/time-selector/time-range-selector.component.scss
@@ -16,8 +16,6 @@
  *
  */
 
-@import '../../../../scss/variables';
-
 .start-date-margin {
     margin-right: 5px;
 }
@@ -65,8 +63,9 @@
 }
 
 .formatted-datetime {
-    display: inline;
+    display: inline-flex;
     background: var(--color-bg-2);
     border-radius: 5px;
     padding: 5px;
+    white-space: nowrap;
 }
diff --git 
a/ui/src/app/data-explorer/components/time-selector/time-range-selector.component.ts
 
b/ui/projects/streampipes/shared-ui/src/lib/components/time-selector/time-range-selector.component.ts
similarity index 69%
rename from 
ui/src/app/data-explorer/components/time-selector/time-range-selector.component.ts
rename to 
ui/projects/streampipes/shared-ui/src/lib/components/time-selector/time-range-selector.component.ts
index a2b663d5b3..ad8ef22523 100644
--- 
a/ui/src/app/data-explorer/components/time-selector/time-range-selector.component.ts
+++ 
b/ui/projects/streampipes/shared-ui/src/lib/components/time-selector/time-range-selector.component.ts
@@ -28,13 +28,16 @@ import {
     ViewEncapsulation,
 } from '@angular/core';
 import {
-    TimeSelectionId,
+    QuickTimeSelection,
+    TimeSelectionConstants,
     TimeSettings,
     TimeString,
 } from '@streampipes/platform-services';
 import { MatMenuTrigger } from '@angular/material/menu';
 import { TimeSelectionService } from '../../services/time-selection.service';
 import { TimeRangeSelectorMenuComponent } from 
'./time-selector-menu/time-selector-menu.component';
+import { TimeSelectorLabel } from './time-selector.model';
+import { differenceInMilliseconds, isSameDay } from 'date-fns';
 
 @Component({
     selector: 'sp-time-range-selector',
@@ -55,13 +58,41 @@ export class TimeRangeSelectorComponent implements OnInit, 
OnChanges {
     @Input()
     showTimeSelector = true;
 
+    @Input()
+    enableTimeChange = true;
+
+    @Input()
+    maxDayRange = 0;
+
+    @Input()
+    quickSelections: QuickTimeSelection[];
+
+    @Input()
+    labels: TimeSelectorLabel = {
+        quickSelectionLabel: 'Quick Selection',
+        customLabel: 'Custom',
+        maxDayRangeErrorLabel:
+            'Maximum of ${this.maxDayRange} days can be displayed. Please 
select a smaller range.',
+        timeRangeSelectorTooltip: 'Modify time range',
+    };
+
     simpleTimeString: string = '';
     timeString: TimeString;
     timeStringMode: 'simple' | 'advanced' = 'simple';
+    dateFormat: Intl.DateTimeFormatOptions = {
+        weekday: 'short',
+        year: 'numeric',
+        month: 'numeric',
+        day: 'numeric',
+    };
 
     constructor(private timeSelectionService: TimeSelectionService) {}
 
     ngOnInit() {
+        if (!this.quickSelections) {
+            this.quickSelections =
+                this.timeSelectionService.defaultQuickTimeSelections;
+        }
         this.createDateString();
     }
 
@@ -95,6 +126,7 @@ export class TimeRangeSelectorComponent implements OnInit, 
OnChanges {
 
     updateTimeSettingsAndReload() {
         this.timeSelectionService.updateTimeSettings(
+            this.quickSelections,
             this.timeSettings,
             new Date(),
         );
@@ -105,14 +137,19 @@ export class TimeRangeSelectorComponent implements 
OnInit, OnChanges {
     }
 
     private changeTimeByInterval(func: (a: number, b: number) => number) {
-        const difference =
-            this.timeSettings.endTime - this.timeSettings.startTime;
-        const newStartTime = func(this.timeSettings.startTime, difference);
-        const newEndTime = func(this.timeSettings.endTime, difference);
+        const timeDiff =
+            (differenceInMilliseconds(
+                this.timeSettings.startTime,
+                this.timeSettings.endTime,
+            ) -
+                1) *
+            -1;
+        const newStartTime = func(this.timeSettings.startTime, timeDiff);
+        const newEndTime = func(this.timeSettings.endTime, timeDiff);
 
         this.timeSettings.startTime = newStartTime;
         this.timeSettings.endTime = newEndTime;
-        this.timeSettings.timeSelectionId = TimeSelectionId.CUSTOM;
+        this.timeSettings.timeSelectionId = TimeSelectionConstants.CUSTOM;
         this.timeSelectorMenu.triggerDisplayUpdate();
         this.createDateString();
         this.reloadData();
@@ -126,8 +163,11 @@ export class TimeRangeSelectorComponent implements OnInit, 
OnChanges {
     }
 
     createDateString(): void {
-        if (this.timeSettings.timeSelectionId !== TimeSelectionId.CUSTOM) {
+        if (
+            this.timeSettings.timeSelectionId !== TimeSelectionConstants.CUSTOM
+        ) {
             this.simpleTimeString = this.timeSelectionService.getTimeSelection(
+                this.quickSelections,
                 this.timeSettings.timeSelectionId,
             ).label;
             this.timeStringMode = 'simple';
@@ -135,12 +175,20 @@ export class TimeRangeSelectorComponent implements 
OnInit, OnChanges {
             const startDate = new Date(this.timeSettings.startTime);
             const endDate = new Date(this.timeSettings.endTime);
             this.timeString = {
-                startDate: startDate.toLocaleDateString(),
-                endDate: endDate.toLocaleDateString(),
+                startDate: this.formatDate(startDate),
+                endDate: this.formatDate(endDate),
                 startTime: startDate.toLocaleTimeString(),
                 endTime: endDate.toLocaleTimeString(),
+                sameDay: isSameDay(startDate, endDate),
             };
+
             this.timeStringMode = 'advanced';
         }
     }
+
+    private formatDate(date: Date): string {
+        return this.enableTimeChange
+            ? date.toLocaleDateString()
+            : date.toLocaleDateString(navigator.language, this.dateFormat);
+    }
 }
diff --git 
a/ui/src/app/data-explorer/components/time-selector/time-selector-menu/custom-time-range-selection/custom-time-range-selection.component.html
 
b/ui/projects/streampipes/shared-ui/src/lib/components/time-selector/time-selector-menu/custom-time-range-selection/custom-time-range-selection.component.html
similarity index 86%
rename from 
ui/src/app/data-explorer/components/time-selector/time-selector-menu/custom-time-range-selection/custom-time-range-selection.component.html
rename to 
ui/projects/streampipes/shared-ui/src/lib/components/time-selector/time-selector-menu/custom-time-range-selection/custom-time-range-selection.component.html
index 1564d9b5dc..38fba4f86d 100644
--- 
a/ui/src/app/data-explorer/components/time-selector/time-selector-menu/custom-time-range-selection/custom-time-range-selection.component.html
+++ 
b/ui/projects/streampipes/shared-ui/src/lib/components/time-selector/time-selector-menu/custom-time-range-selection/custom-time-range-selection.component.html
@@ -26,7 +26,7 @@
             </mat-calendar>
         </mat-card>
 
-        <div fxLayout="column" class="mt-10 mr-5">
+        <div *ngIf="enableTimeChange" fxLayout="column" class="mt-10 mr-5">
             <div fxLayout="row" fxLayoutGap="10px">
                 <div fxFlex="30">
                     <span
@@ -73,6 +73,21 @@
             </div>
         </div>
     </div>
+    <div *ngIf="!enableTimeChange" fxLayout="row" class="mt-10 date-preview">
+        {{ dateRangeString }}
+    </div>
+    <div
+        fxLayout="row"
+        class="mt-5 max-date-range-error"
+        *ngIf="maxDateRangeError"
+    >
+        {{
+            labels.maxDayRangeErrorLabel.replace(
+                '${this.maxDayRange}',
+                maxDayRange.toString()
+            )
+        }}
+    </div>
     <div fxLayout="row" fxLayoutAlign="end center" class="mt-10">
         <ng-content> </ng-content>
         <button
@@ -81,6 +96,7 @@
             data-cy="apply-custom-time"
             (click)="saveSelection()"
             [disabled]="!dateSelectionComplete"
+            *ngIf="enableTimeChange"
         >
             Apply
         </button>
diff --git 
a/ui/src/app/data-explorer/components/time-selector/time-selector-menu/custom-time-range-selection/custom-time-range-selection.component.scss
 
b/ui/projects/streampipes/shared-ui/src/lib/components/time-selector/time-selector-menu/custom-time-range-selection/custom-time-range-selection.component.scss
similarity index 91%
copy from 
ui/src/app/data-explorer/components/time-selector/time-selector-menu/custom-time-range-selection/custom-time-range-selection.component.scss
copy to 
ui/projects/streampipes/shared-ui/src/lib/components/time-selector/time-selector-menu/custom-time-range-selection/custom-time-range-selection.component.scss
index ce53cf59ea..d181ae05dd 100644
--- 
a/ui/src/app/data-explorer/components/time-selector/time-selector-menu/custom-time-range-selection/custom-time-range-selection.component.scss
+++ 
b/ui/projects/streampipes/shared-ui/src/lib/components/time-selector/time-selector-menu/custom-time-range-selection/custom-time-range-selection.component.scss
@@ -20,3 +20,8 @@
     font-family: inherit;
     font-size: 11pt;
 }
+
+.max-date-range-error {
+    font-size: 9pt;
+    color: var(--color-warn);
+}
diff --git 
a/ui/src/app/data-explorer/components/time-selector/time-selector-menu/custom-time-range-selection/custom-time-range-selection.component.ts
 
b/ui/projects/streampipes/shared-ui/src/lib/components/time-selector/time-selector-menu/custom-time-range-selection/custom-time-range-selection.component.ts
similarity index 63%
rename from 
ui/src/app/data-explorer/components/time-selector/time-selector-menu/custom-time-range-selection/custom-time-range-selection.component.ts
rename to 
ui/projects/streampipes/shared-ui/src/lib/components/time-selector/time-selector-menu/custom-time-range-selection/custom-time-range-selection.component.ts
index 2129a521c9..5843f03a68 100644
--- 
a/ui/src/app/data-explorer/components/time-selector/time-selector-menu/custom-time-range-selection/custom-time-range-selection.component.ts
+++ 
b/ui/projects/streampipes/shared-ui/src/lib/components/time-selector/time-selector-menu/custom-time-range-selection/custom-time-range-selection.component.ts
@@ -17,12 +17,17 @@
  */
 
 import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
-import { TimeSelectionId, TimeSettings } from '@streampipes/platform-services';
+import {
+    TimeSelectionConstants,
+    TimeSettings,
+} from '@streampipes/platform-services';
 import {
     DateRange,
     DefaultMatCalendarRangeStrategy,
     MatRangeDateSelectionModel,
 } from '@angular/material/datepicker';
+import { differenceInDays, endOfDay, startOfDay } from 'date-fns';
+import { TimeSelectorLabel } from '../../time-selector.model';
 
 @Component({
     selector: 'sp-custom-time-range-selection',
@@ -31,6 +36,15 @@ import {
 })
 export class CustomTimeRangeSelectionComponent implements OnInit {
     @Input() timeSettings: TimeSettings;
+
+    @Input() labels: TimeSelectorLabel;
+
+    @Input()
+    enableTimeChange: boolean;
+
+    @Input()
+    maxDayRange: number;
+
     @Output() timeSettingsEmitter = new EventEmitter<TimeSettings>();
 
     currentStartDate: string;
@@ -39,6 +53,9 @@ export class CustomTimeRangeSelectionComponent implements 
OnInit {
     currentEndTime: string;
     currentDateRange: DateRange<Date>;
     dateSelectionComplete = false;
+    dateRangeString: string;
+
+    maxDateRangeError = false;
 
     constructor(
         private readonly selectionModel: MatRangeDateSelectionModel<Date>,
@@ -75,13 +92,19 @@ export class CustomTimeRangeSelectionComponent implements 
OnInit {
     updateDateStrings(): void {
         this.currentStartDate = this.formatDate(this.currentDateRange.start);
         this.currentEndDate = this.formatDate(this.currentDateRange.end);
+        this.dateRangeString = `${this.currentStartDate} - 
${this.currentEndDate}`;
     }
 
     formatDate(date: Date): string {
-        return date?.toLocaleDateString() || '-';
+        if (this.enableTimeChange === true) {
+            return date?.toLocaleDateString() || '-';
+        } else {
+            return date?.toLocaleDateString() || ' ';
+        }
     }
 
     onDateChange(selectedDate: Date): void {
+        this.maxDateRangeError = false;
         const newSelection = this.selectionStrategy.selectionFinished(
             selectedDate,
             this.selectionModel.selection,
@@ -91,16 +114,40 @@ export class CustomTimeRangeSelectionComponent implements 
OnInit {
             newSelection.start,
             newSelection.end,
         );
-        this.dateSelectionComplete = this.selectionModel.isComplete();
         this.updateDateStrings();
+        const daysDiff = differenceInDays(newSelection.end, 
newSelection.start);
+        if (this.selectionModel.isComplete()) {
+            if (this.maxDayRange === 0 || daysDiff + 1 <= this.maxDayRange) {
+                this.dateSelectionComplete = true;
+                if (!this.enableTimeChange) {
+                    this.saveSelection();
+                }
+            } else {
+                this.maxDateRangeError = true;
+                this.dateSelectionComplete = false;
+            }
+        }
     }
 
     saveSelection(): void {
-        this.updateDateTime(this.currentDateRange.start, 
this.currentStartTime);
-        this.updateDateTime(this.currentDateRange.end, this.currentEndTime);
-        this.timeSettings.startTime = this.currentDateRange.start.getTime();
-        this.timeSettings.endTime = this.currentDateRange.end.getTime();
-        this.timeSettings.timeSelectionId = TimeSelectionId.CUSTOM;
+        if (this.enableTimeChange === true) {
+            this.updateDateTime(
+                this.currentDateRange.start,
+                this.currentStartTime,
+            );
+            this.updateDateTime(this.currentDateRange.end, 
this.currentEndTime);
+            this.timeSettings.startTime = 
this.currentDateRange.start.getTime();
+            this.timeSettings.endTime = this.currentDateRange.end.getTime();
+        } else {
+            this.timeSettings.startTime = startOfDay(
+                this.currentDateRange.start,
+            ).getTime();
+            this.timeSettings.endTime = endOfDay(
+                this.currentDateRange.end,
+            ).getTime();
+        }
+
+        this.timeSettings.timeSelectionId = TimeSelectionConstants.CUSTOM;
         this.timeSettingsEmitter.emit(this.timeSettings);
     }
 
diff --git 
a/ui/src/app/data-explorer/components/time-selector/time-selector-menu/time-selector-menu.component.html
 
b/ui/projects/streampipes/shared-ui/src/lib/components/time-selector/time-selector-menu/time-selector-menu.component.html
similarity index 84%
rename from 
ui/src/app/data-explorer/components/time-selector/time-selector-menu/time-selector-menu.component.html
rename to 
ui/projects/streampipes/shared-ui/src/lib/components/time-selector/time-selector-menu/time-selector-menu.component.html
index e53550aa43..2bfda05f10 100644
--- 
a/ui/src/app/data-explorer/components/time-selector/time-selector-menu/time-selector-menu.component.html
+++ 
b/ui/projects/streampipes/shared-ui/src/lib/components/time-selector/time-selector-menu/time-selector-menu.component.html
@@ -16,11 +16,13 @@
   ~
   -->
 
-<div class="menu-content" (click)="$event.stopPropagation()">
+<div class="menu-content" (click)="$event.stopPropagation()" *ngIf="labels">
     <div fxLayout="column" fxLayoutGap="10px">
         <div fxLayout="row" fxFlex="100" fxLayoutGap="10px">
             <div fxLayout="column" fxFlex="50" fxLayoutGap="10px">
-                <div class="filter-header">Quick selection</div>
+                <div class="filter-header">
+                    {{ labels.quickSelectionLabel }}
+                </div>
                 <div fxLayout="column" fxLayoutGap="10px" fxFlex="100">
                     <div *ngFor="let quickSelection of quickSelections">
                         <span
@@ -39,11 +41,14 @@
                 </div>
             </div>
             <div fxLayout="column" fxFlex="50">
-                <div class="filter-header">Custom</div>
+                <div class="filter-header">{{ labels.customLabel }}</div>
                 <sp-custom-time-range-selection
                     #timeRangeSelection
                     [timeSettings]="timeSettings"
+                    [labels]="labels"
                     (timeSettingsEmitter)="timeSettingsEmitter.emit($event)"
+                    [enableTimeChange]="enableTimeChange"
+                    [maxDayRange]="maxDayRange"
                     class="w-100"
                 >
                     <ng-content> </ng-content>
diff --git 
a/ui/src/app/data-explorer/components/time-selector/time-selector-menu/time-selector-menu.component.scss
 
b/ui/projects/streampipes/shared-ui/src/lib/components/time-selector/time-selector-menu/time-selector-menu.component.scss
similarity index 100%
rename from 
ui/src/app/data-explorer/components/time-selector/time-selector-menu/time-selector-menu.component.scss
rename to 
ui/projects/streampipes/shared-ui/src/lib/components/time-selector/time-selector-menu/time-selector-menu.component.scss
diff --git 
a/ui/src/app/data-explorer/components/time-selector/time-selector-menu/time-selector-menu.component.ts
 
b/ui/projects/streampipes/shared-ui/src/lib/components/time-selector/time-selector-menu/time-selector-menu.component.ts
similarity index 90%
rename from 
ui/src/app/data-explorer/components/time-selector/time-selector-menu/time-selector-menu.component.ts
rename to 
ui/projects/streampipes/shared-ui/src/lib/components/time-selector/time-selector-menu/time-selector-menu.component.ts
index a24958bb31..a2748d9a47 100644
--- 
a/ui/src/app/data-explorer/components/time-selector/time-selector-menu/time-selector-menu.component.ts
+++ 
b/ui/projects/streampipes/shared-ui/src/lib/components/time-selector/time-selector-menu/time-selector-menu.component.ts
@@ -30,6 +30,7 @@ import {
 } from '@streampipes/platform-services';
 import { TimeSelectionService } from 
'../../../services/time-selection.service';
 import { CustomTimeRangeSelectionComponent } from 
'./custom-time-range-selection/custom-time-range-selection.component';
+import { TimeSelectorLabel } from '../time-selector.model';
 
 @Component({
     selector: 'sp-time-selector-menu',
@@ -40,20 +41,28 @@ export class TimeRangeSelectorMenuComponent implements 
OnInit {
     @Input()
     timeSettings: TimeSettings;
 
+    @Input()
+    labels: TimeSelectorLabel;
+
+    @Input()
+    enableTimeChange: boolean;
+
+    @Input()
+    maxDayRange: number;
+
     @Output()
     timeSettingsEmitter: EventEmitter<TimeSettings> =
         new EventEmitter<TimeSettings>();
 
-    quickSelections: QuickTimeSelection[] = [];
+    @Input()
+    quickSelections: QuickTimeSelection[];
 
     @ViewChild('timeRangeSelection')
     timeRangeSelection: CustomTimeRangeSelectionComponent;
 
     constructor(private timeSelectionService: TimeSelectionService) {}
 
-    ngOnInit(): void {
-        this.quickSelections = this.timeSelectionService.quickTimeSelections;
-    }
+    ngOnInit(): void {}
 
     applyQuickSelection(quickSelection: QuickTimeSelection): void {
         const selectedDateRange =
diff --git 
a/ui/src/app/data-explorer/components/time-selector/time-selector-menu/custom-time-range-selection/custom-time-range-selection.component.scss
 
b/ui/projects/streampipes/shared-ui/src/lib/components/time-selector/time-selector.model.ts
similarity index 82%
rename from 
ui/src/app/data-explorer/components/time-selector/time-selector-menu/custom-time-range-selection/custom-time-range-selection.component.scss
rename to 
ui/projects/streampipes/shared-ui/src/lib/components/time-selector/time-selector.model.ts
index ce53cf59ea..7905f9ff09 100644
--- 
a/ui/src/app/data-explorer/components/time-selector/time-selector-menu/custom-time-range-selection/custom-time-range-selection.component.scss
+++ 
b/ui/projects/streampipes/shared-ui/src/lib/components/time-selector/time-selector.model.ts
@@ -16,7 +16,9 @@
  *
  */
 
-.time-selector {
-    font-family: inherit;
-    font-size: 11pt;
+export interface TimeSelectorLabel {
+    quickSelectionLabel: string;
+    customLabel: string;
+    maxDayRangeErrorLabel: string;
+    timeRangeSelectorTooltip: string;
 }
diff --git a/ui/src/app/data-explorer/services/time-selection.service.ts 
b/ui/projects/streampipes/shared-ui/src/lib/services/time-selection.service.ts
similarity index 62%
rename from ui/src/app/data-explorer/services/time-selection.service.ts
rename to 
ui/projects/streampipes/shared-ui/src/lib/services/time-selection.service.ts
index 5c55e7756a..a635ab1c54 100644
--- a/ui/src/app/data-explorer/services/time-selection.service.ts
+++ 
b/ui/projects/streampipes/shared-ui/src/lib/services/time-selection.service.ts
@@ -21,7 +21,7 @@ import { Subject } from 'rxjs';
 import {
     DateRange,
     QuickTimeSelection,
-    TimeSelectionId,
+    TimeSelectionConstants,
     TimeSettings,
     WidgetTimeSettings,
 } from '@streampipes/platform-services';
@@ -41,79 +41,79 @@ import {
 
 @Injectable({ providedIn: 'root' })
 export class TimeSelectionService {
-    legacyMappings: Record<number, TimeSelectionId> = {
-        15: TimeSelectionId.LAST_15_MINUTES,
-        60: TimeSelectionId.LAST_HOUR,
-        1440: TimeSelectionId.LAST_DAY,
-        10080: TimeSelectionId.LAST_WEEK,
-        43200: TimeSelectionId.LAST_MONTH,
-        525600: TimeSelectionId.LAST_YEAR,
+    legacyMappings: Record<number, string> = {
+        15: TimeSelectionConstants.LAST_15_MINUTES,
+        60: TimeSelectionConstants.LAST_HOUR,
+        1440: TimeSelectionConstants.LAST_DAY,
+        10080: TimeSelectionConstants.LAST_WEEK,
+        43200: TimeSelectionConstants.LAST_MONTH,
+        525600: TimeSelectionConstants.LAST_YEAR,
     };
 
-    quickTimeSelections: QuickTimeSelection[] = [
+    defaultQuickTimeSelections: QuickTimeSelection[] = [
         {
             label: 'Last 15 min',
-            timeSelectionId: TimeSelectionId.LAST_15_MINUTES,
+            timeSelectionId: TimeSelectionConstants.LAST_15_MINUTES,
             startTime: now => subMinutes(now, 15),
             endTime: now => now,
         },
         {
             label: 'Last 1 hour',
-            timeSelectionId: TimeSelectionId.LAST_HOUR,
+            timeSelectionId: TimeSelectionConstants.LAST_HOUR,
             startTime: now => subHours(now, 1),
             endTime: now => now,
         },
         {
             label: 'Last 1 day',
-            timeSelectionId: TimeSelectionId.LAST_DAY,
+            timeSelectionId: TimeSelectionConstants.LAST_DAY,
             startTime: now => subDays(now, 1),
             endTime: now => now,
         },
         {
             label: 'Last 1 week',
-            timeSelectionId: TimeSelectionId.LAST_WEEK,
+            timeSelectionId: TimeSelectionConstants.LAST_WEEK,
             startTime: now => subWeeks(now, 1),
             endTime: now => now,
         },
         {
             label: 'Last 1 month',
-            timeSelectionId: TimeSelectionId.LAST_MONTH,
+            timeSelectionId: TimeSelectionConstants.LAST_MONTH,
             startTime: now => subMonths(now, 1),
             endTime: now => now,
         },
         {
             label: 'Last 1 year',
-            timeSelectionId: TimeSelectionId.LAST_YEAR,
+            timeSelectionId: TimeSelectionConstants.LAST_YEAR,
             startTime: now => subYears(now, 1),
             endTime: now => now,
         },
         {
             label: 'Current day',
-            timeSelectionId: TimeSelectionId.CURRENT_DAY,
+            timeSelectionId: TimeSelectionConstants.CURRENT_DAY,
             startTime: now => startOfDay(now),
             endTime: now => now,
         },
         {
             label: 'Current hour',
-            timeSelectionId: TimeSelectionId.CURRENT_HOUR,
+            timeSelectionId: TimeSelectionConstants.CURRENT_HOUR,
             startTime: now => startOfHour(now),
             endTime: now => now,
         },
         {
             label: 'Current week',
-            timeSelectionId: TimeSelectionId.CURRENT_WEEK,
+            timeSelectionId: TimeSelectionConstants.CURRENT_WEEK,
             startTime: now => startOfWeek(now),
             endTime: now => now,
         },
         {
             label: 'Current month',
-            timeSelectionId: TimeSelectionId.CURRENT_MONTH,
+            timeSelectionId: TimeSelectionConstants.CURRENT_MONTH,
             startTime: now => startOfMonth(now),
             endTime: now => now,
         },
         {
             label: 'Current year',
-            timeSelectionId: TimeSelectionId.CURRENT_YEAR,
+            timeSelectionId: TimeSelectionConstants.CURRENT_YEAR,
             startTime: now => startOfYear(now),
             endTime: now => now,
         },
@@ -129,32 +129,55 @@ export class TimeSelectionService {
 
     public getDefaultTimeSettings(): TimeSettings {
         return this.getTimeSettings(
-            TimeSelectionId.LAST_15_MINUTES,
+            this.defaultQuickTimeSelections,
+            this.defaultQuickTimeSelections[0].timeSelectionId,
             new Date(),
         );
     }
 
     public getTimeSettings(
-        timeSelectionId: TimeSelectionId,
+        quickTimeSelections: QuickTimeSelection[],
+        timeSelectionId: string,
         now: Date,
     ): TimeSettings {
-        const selection = this.getTimeSelection(timeSelectionId);
+        const selection = this.getTimeSelection(
+            quickTimeSelections,
+            timeSelectionId,
+        );
         return {
             startTime: selection.startTime(now).getTime(),
             endTime: selection.endTime(now).getTime(),
             dynamicSelection: -1,
-            timeSelectionId: timeSelectionId,
+            timeSelectionId: selection.timeSelectionId,
         };
     }
 
-    public updateTimeSettings(timeSettings: TimeSettings, now: Date): void {
+    public updateTimeSettings(
+        quickTimeSelections: QuickTimeSelection[],
+        timeSettings: TimeSettings,
+        now: Date,
+    ): void {
         // for backwards compatibility
         if (timeSettings.timeSelectionId === undefined) {
             timeSettings.timeSelectionId =
                 this.findLegacyTimeSelectionId(timeSettings);
+        } else if (typeof timeSettings.timeSelectionId === 'number') {
+            timeSettings.timeSelectionId =
+                TimeSelectionConstants.getLegacyTimeSelectionID(
+                    timeSettings.timeSelectionId,
+                );
         }
-        if (timeSettings.timeSelectionId !== TimeSelectionId.CUSTOM) {
+        if (timeSettings.timeSelectionId !== TimeSelectionConstants.CUSTOM) {
+            if (
+                quickTimeSelections.find(
+                    s => s.timeSelectionId === timeSettings.timeSelectionId,
+                ) === undefined
+            ) {
+                timeSettings.timeSelectionId =
+                    quickTimeSelections[0].timeSelectionId;
+            }
             const updatedTimeSettings = this.getTimeSettings(
+                quickTimeSelections,
                 timeSettings.timeSelectionId,
                 now,
             );
@@ -163,19 +186,22 @@ export class TimeSelectionService {
         }
     }
 
-    public getTimeSelection(timeSelectionId: TimeSelectionId) {
-        return this.quickTimeSelections.find(
-            s => s.timeSelectionId === timeSelectionId,
+    public getTimeSelection(
+        quickTimeSelections: QuickTimeSelection[],
+        timeSelectionId: string,
+    ): QuickTimeSelection {
+        return (
+            quickTimeSelections.find(
+                s => s.timeSelectionId === timeSelectionId,
+            ) || quickTimeSelections[0]
         );
     }
 
-    private findLegacyTimeSelectionId(
-        timeSettings: TimeSettings,
-    ): TimeSelectionId {
+    private findLegacyTimeSelectionId(timeSettings: TimeSettings): string {
         if (timeSettings.dynamicSelection in this.legacyMappings) {
             return this.legacyMappings[timeSettings.dynamicSelection];
         } else {
-            return TimeSelectionId.CUSTOM;
+            return TimeSelectionConstants.CUSTOM;
         }
     }
 
diff --git a/ui/projects/streampipes/shared-ui/src/lib/shared-ui.module.ts 
b/ui/projects/streampipes/shared-ui/src/lib/shared-ui.module.ts
index d5b90cf68d..5a1b150843 100644
--- a/ui/projects/streampipes/shared-ui/src/lib/shared-ui.module.ts
+++ b/ui/projects/streampipes/shared-ui/src/lib/shared-ui.module.ts
@@ -17,7 +17,13 @@
  */
 
 import { NgModule } from '@angular/core';
+import {
+    DefaultMatCalendarRangeStrategy,
+    MatDatepickerModule,
+    MatRangeDateSelectionModel,
+} from '@angular/material/datepicker';
 import { ConfirmDialogComponent } from 
'./dialog/confirm-dialog/confirm-dialog.component';
+import { MatCardModule } from '@angular/material/card';
 import { PanelDialogComponent } from 
'./dialog/panel-dialog/panel-dialog.component';
 import { StandardDialogComponent } from 
'./dialog/standard-dialog/standard-dialog.component';
 import { CommonModule } from '@angular/common';
@@ -55,6 +61,9 @@ import { AssetBrowserFilterTypeComponent } from 
'./components/asset-browser/asse
 import { AssetBrowserHierarchyComponent } from 
'./components/asset-browser/asset-browser-hierarchy/asset-browser-hierarchy.component';
 import { AssetBrowserNodeComponent } from 
'./components/asset-browser/asset-browser-hierarchy/asset-browser-node/asset-browser-node.component';
 import { AssetBrowserNodeInfoComponent } from 
'./components/asset-browser/asset-browser-hierarchy/asset-browser-node/asset-browser-node-info/asset-browser-node-info.component';
+import { TimeRangeSelectorComponent } from 
'./components/time-selector/time-range-selector.component';
+import { TimeRangeSelectorMenuComponent } from 
'./components/time-selector/time-selector-menu/time-selector-menu.component';
+import { CustomTimeRangeSelectionComponent } from 
'./components/time-selector/time-selector-menu/custom-time-range-selection/custom-time-range-selection.component';
 import { MatSelectModule } from '@angular/material/select';
 import { MatFormFieldModule } from '@angular/material/form-field';
 import { MatMenuModule } from '@angular/material/menu';
@@ -74,6 +83,7 @@ import { MatTreeModule } from '@angular/material/tree';
         AssetBrowserNodeInfoComponent,
         AssetBrowserToolbarComponent,
         ConfirmDialogComponent,
+        CustomTimeRangeSelectionComponent,
         PanelDialogComponent,
         StandardDialogComponent,
         SpBasicFieldDescriptionComponent,
@@ -88,6 +98,8 @@ import { MatTreeModule } from '@angular/material/tree';
         SpTableComponent,
         SplitSectionComponent,
         SpWarningBoxComponent,
+        TimeRangeSelectorComponent,
+        TimeRangeSelectorMenuComponent,
     ],
     imports: [
         CommonModule,
@@ -102,6 +114,8 @@ import { MatTreeModule } from '@angular/material/tree';
         MatTabsModule,
         MatTooltipModule,
         MatTreeModule,
+        MatDatepickerModule,
+        MatCardModule,
         PortalModule,
         OverlayModule,
         MatDialogModule,
@@ -109,6 +123,7 @@ import { MatTreeModule } from '@angular/material/tree';
         MatPaginator,
         MatSort,
     ],
+    providers: [DefaultMatCalendarRangeStrategy, MatRangeDateSelectionModel],
     exports: [
         AssetBrowserComponent,
         ConfirmDialogComponent,
@@ -126,6 +141,9 @@ import { MatTreeModule } from '@angular/material/tree';
         SpTableComponent,
         SplitSectionComponent,
         SpWarningBoxComponent,
+        CustomTimeRangeSelectionComponent,
+        TimeRangeSelectorComponent,
+        TimeRangeSelectorMenuComponent,
     ],
 })
 export class SharedUiModule {}
diff --git a/ui/projects/streampipes/shared-ui/src/public-api.ts 
b/ui/projects/streampipes/shared-ui/src/public-api.ts
index a923f5abbc..40fe20fa0a 100644
--- a/ui/projects/streampipes/shared-ui/src/public-api.ts
+++ b/ui/projects/streampipes/shared-ui/src/public-api.ts
@@ -39,6 +39,9 @@ export * from 
'./lib/components/sp-exception-message/exception-details/exception
 export * from './lib/components/sp-label/sp-label.component';
 export * from './lib/components/sp-table/sp-table.component';
 export * from './lib/components/warning-box/warning-box.component';
+export * from './lib/components/time-selector/time-range-selector.component';
+export * from 
'./lib/components/time-selector/time-selector-menu/time-selector-menu.component';
+export * from 
'./lib/components/time-selector/time-selector-menu/custom-time-range-selection/custom-time-range-selection.component';
 
 export * from './lib/models/sp-navigation.model';
 
@@ -47,4 +50,5 @@ export * from './lib/services/jwt-token-storage.service';
 export * from './lib/services/current-user.service';
 export * from './lib/services/echarts-toolbox.service';
 export * from './lib/services/colorization.service';
+export * from './lib/services/time-selection.service';
 export * from './lib/components/asset-browser/asset-browser.service';
diff --git a/ui/projects/streampipes/shared-ui/tsconfig.lib.json 
b/ui/projects/streampipes/shared-ui/tsconfig.lib.json
index e2c590dbbf..0b34959311 100644
--- a/ui/projects/streampipes/shared-ui/tsconfig.lib.json
+++ b/ui/projects/streampipes/shared-ui/tsconfig.lib.json
@@ -8,7 +8,7 @@
     "declarationMap": true,
     "inlineSources": true,
     "types": [],
-    "lib": ["dom", "es2018"]
+    "lib": ["dom", "es2020"]
   },
   "exclude": ["src/test.ts", "**/*.spec.ts"]
 }
diff --git 
a/ui/src/app/data-explorer/components/dashboard/data-explorer-dashboard-panel.component.ts
 
b/ui/src/app/data-explorer/components/dashboard/data-explorer-dashboard-panel.component.ts
index 7a28ff025d..ab3715cefc 100644
--- 
a/ui/src/app/data-explorer/components/dashboard/data-explorer-dashboard-panel.component.ts
+++ 
b/ui/src/app/data-explorer/components/dashboard/data-explorer-dashboard-panel.component.ts
@@ -25,10 +25,9 @@ import {
     DataExplorerWidgetModel,
     DataLakeMeasure,
     DataViewDataExplorerService,
-    TimeSelectionId,
+    TimeSelectionConstants,
     TimeSettings,
 } from '@streampipes/platform-services';
-import { TimeSelectionService } from '../../services/time-selection.service';
 import { AuthService } from '../../../services/auth.service';
 import { UserPrivilege } from '../../../_enums/user-privilege.enum';
 import {
@@ -48,6 +47,7 @@ import { SpDataExplorerRoutes } from 
'../../data-explorer.routes';
 import { DataExplorerRoutingService } from 
'../../services/data-explorer-routing.service';
 import { DataExplorerDetectChangesService } from 
'../../services/data-explorer-detect-changes.service';
 import { SupportsUnsavedChangeDialog } from 
'../../models/dataview-dashboard.model';
+import { TimeSelectionService } from '@streampipes/shared-ui';
 
 @Component({
     selector: 'sp-data-explorer-dashboard-panel',
@@ -224,6 +224,7 @@ export class DataExplorerDashboardPanelComponent
                     this.timeSelectionService.getDefaultTimeSettings();
             } else {
                 this.timeSelectionService.updateTimeSettings(
+                    this.timeSelectionService.defaultQuickTimeSelections,
                     this.dashboard.dashboardTimeSettings,
                     new Date(),
                 );
@@ -242,7 +243,7 @@ export class DataExplorerDashboardPanelComponent
             startTime,
             endTime,
             dynamicSelection: -1,
-            timeSelectionId: TimeSelectionId.CUSTOM,
+            timeSelectionId: TimeSelectionConstants.CUSTOM,
         };
     }
 
@@ -301,6 +302,7 @@ export class DataExplorerDashboardPanelComponent
             .pipe(
                 switchMap(() => {
                     this.timeSelectionService.updateTimeSettings(
+                        this.timeSelectionService.defaultQuickTimeSelections,
                         this.timeSettings,
                         new Date(),
                     );
diff --git 
a/ui/src/app/data-explorer/components/data-view/data-explorer-data-view.component.ts
 
b/ui/src/app/data-explorer/components/data-view/data-explorer-data-view.component.ts
index 202946c582..f78329f924 100644
--- 
a/ui/src/app/data-explorer/components/data-view/data-explorer-data-view.component.ts
+++ 
b/ui/src/app/data-explorer/components/data-view/data-explorer-data-view.component.ts
@@ -30,7 +30,6 @@ import {
     RouterStateSnapshot,
 } from '@angular/router';
 import { ConfirmDialogComponent } from '@streampipes/shared-ui';
-import { TimeSelectionService } from '../../services/time-selection.service';
 import { DataExplorerRoutingService } from 
'../../services/data-explorer-routing.service';
 import { DataExplorerDashboardService } from 
'../../services/data-explorer-dashboard.service';
 import { DataExplorerDetectChangesService } from 
'../../services/data-explorer-detect-changes.service';
@@ -38,6 +37,7 @@ import { SupportsUnsavedChangeDialog } from 
'../../models/dataview-dashboard.mod
 import { Observable, of } from 'rxjs';
 import { MatDialog } from '@angular/material/dialog';
 import { map } from 'rxjs/operators';
+import { TimeSelectionService } from '@streampipes/shared-ui';
 
 @Component({
     selector: 'sp-data-explorer-data-view',
@@ -90,6 +90,7 @@ export class DataExplorerDataViewComponent
                 this.timeSettings = this.makeDefaultTimeSettings();
             } else {
                 this.timeSelectionService.updateTimeSettings(
+                    this.timeSelectionService.defaultQuickTimeSelections,
                     this.dataView.timeSettings as TimeSettings,
                     new Date(),
                 );
diff --git 
a/ui/src/app/data-explorer/components/widget/data-explorer-dashboard-widget.component.ts
 
b/ui/src/app/data-explorer/components/widget/data-explorer-dashboard-widget.component.ts
index 21e5170c0e..32c1d53801 100644
--- 
a/ui/src/app/data-explorer/components/widget/data-explorer-dashboard-widget.component.ts
+++ 
b/ui/src/app/data-explorer/components/widget/data-explorer-dashboard-widget.component.ts
@@ -47,8 +47,8 @@ import { UserPrivilege } from 
'../../../_enums/user-privilege.enum';
 import { CurrentUserService } from '@streampipes/shared-ui';
 import { BaseWidgetData } from '../../models/dataview-dashboard.model';
 import { DataExplorerDashboardService } from 
'../../services/data-explorer-dashboard.service';
-import { TimeSelectionService } from '../../services/time-selection.service';
 import { MatMenuTrigger } from '@angular/material/menu';
+import { TimeSelectionService } from '@streampipes/shared-ui';
 
 @Component({
     selector: 'sp-data-explorer-dashboard-widget',
@@ -162,7 +162,7 @@ export class DataExplorerDashboardWidgetComponent
             endTime: this.timeSettings.endTime,
             timeSelectionId: this.timeSettings.timeSelectionId,
         };
-        if (this.dashboardItem.timeSettings !== undefined) {
+        if (this.dashboardItem?.timeSettings !== undefined) {
             this.timeSettingsModified = true;
         }
     }
diff --git 
a/ui/src/app/data-explorer/components/widgets/base/base-data-explorer-widget.directive.ts
 
b/ui/src/app/data-explorer/components/widgets/base/base-data-explorer-widget.directive.ts
index 5df627e9e7..3d5c8b5d17 100644
--- 
a/ui/src/app/data-explorer/components/widgets/base/base-data-explorer-widget.directive.ts
+++ 
b/ui/src/app/data-explorer/components/widgets/base/base-data-explorer-widget.directive.ts
@@ -45,10 +45,10 @@ import {
 } from '../../../models/dataview-dashboard.model';
 import { Observable, Subject, Subscription, zip } from 'rxjs';
 import { DataExplorerFieldProviderService } from 
'../../../services/data-explorer-field-provider-service';
-import { TimeSelectionService } from 
'../../../services/time-selection.service';
 import { catchError, switchMap } from 'rxjs/operators';
 import { DataExplorerWidgetRegistry } from 
'../../../registry/data-explorer-widget-registry';
 import { SpFieldUpdateService } from '../../../services/field-update.service';
+import { TimeSelectionService } from '@streampipes/shared-ui';
 
 @Directive()
 export abstract class BaseDataExplorerWidgetDirective<
@@ -205,6 +205,8 @@ export abstract class BaseDataExplorerWidgetDirective<
                             this.timeSettings = 
widgetTimeSettings.timeSettings;
                         } else {
                             this.timeSelectionService.updateTimeSettings(
+                                this.timeSelectionService
+                                    .defaultQuickTimeSelections,
                                 this.timeSettings,
                                 new Date(),
                             );
diff --git a/ui/src/app/data-explorer/data-explorer.module.ts 
b/ui/src/app/data-explorer/data-explorer.module.ts
index c3070b45b5..5c5e6790b3 100644
--- a/ui/src/app/data-explorer/data-explorer.module.ts
+++ b/ui/src/app/data-explorer/data-explorer.module.ts
@@ -23,11 +23,6 @@ import { FlexLayoutModule } from '@ngbracket/ngx-layout';
 import { FormsModule, ReactiveFormsModule } from '@angular/forms';
 import { MatChipsModule } from '@angular/material/chips';
 import { MatNativeDateModule } from '@angular/material/core';
-import {
-    DefaultMatCalendarRangeStrategy,
-    MatDatepickerModule,
-    MatRangeDateSelectionModel,
-} from '@angular/material/datepicker';
 import { MatGridListModule } from '@angular/material/grid-list';
 import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
 import { MatSliderModule } from '@angular/material/slider';
@@ -43,7 +38,6 @@ import { CoreUiModule } from '../core-ui/core-ui.module';
 import { DataExplorerDashboardGridComponent } from 
'./components/widget-view/grid-view/data-explorer-dashboard-grid.component';
 import { DataExplorerOverviewComponent } from 
'./components/overview/data-explorer-overview.component';
 import { DataExplorerDashboardPanelComponent } from 
'./components/dashboard/data-explorer-dashboard-panel.component';
-import { TimeRangeSelectorComponent } from 
'./components/time-selector/time-range-selector.component';
 import { DataExplorerDashboardWidgetComponent } from 
'./components/widget/data-explorer-dashboard-widget.component';
 import { ImageWidgetComponent } from 
'./components/widgets/image/image-widget.component';
 import { TrafficLightWidgetComponent } from 
'./components/widgets/traffic-light/traffic-light-widget.component';
@@ -129,8 +123,6 @@ import { DataExplorerDataViewSelectionComponent } from 
'./components/dashboard/d
 import { DataExplorerDashboardWidgetSelectionPanelComponent } from 
'./components/dashboard/dashboard-widget-selection-panel/dashboard-widget-selection-panel.component';
 import { DataExplorerDataViewPreviewComponent } from 
'./components/dashboard/dashboard-widget-selection-panel/data-view-selection/data-view-preview/data-view-preview.component';
 import { DataExplorerDashboardToolbarComponent } from 
'./components/dashboard/dashboard-toolbar/dashboard-toolbar.component';
-import { TimeRangeSelectorMenuComponent } from 
'./components/time-selector/time-selector-menu/time-selector-menu.component';
-import { CustomTimeRangeSelectionComponent } from 
'./components/time-selector/time-selector-menu/custom-time-range-selection/custom-time-range-selection.component';
 import { DataExplorerRefreshIntervalSettingsComponent } from 
'./components/dashboard/dashboard-toolbar/refresh-interval-settings/refresh-interval-settings.component';
 import { OrderSelectionPanelComponent } from 
'./components/data-view/data-view-designer-panel/data-settings/order-selection-panel/order-selection-panel.component';
 import { GaugeWidgetConfigComponent } from 
'./components/widgets/gauge/config/gauge-widget-config.component';
@@ -174,7 +166,6 @@ import { GaugeWidgetConfigComponent } from 
'./components/widgets/gauge/config/ga
         MatProgressSpinnerModule,
         ReactiveFormsModule,
         CoreUiModule,
-        MatDatepickerModule,
         MatNativeDateModule,
         MatSliderModule,
         MatSlideToggleModule,
@@ -215,7 +206,6 @@ import { GaugeWidgetConfigComponent } from 
'./components/widgets/gauge/config/ga
     ],
     declarations: [
         AggregateConfigurationComponent,
-        CustomTimeRangeSelectionComponent,
         DataExplorerDashboardGridComponent,
         DataExplorerOverviewComponent,
         DataExplorerDashboardPanelComponent,
@@ -259,8 +249,6 @@ import { GaugeWidgetConfigComponent } from 
'./components/widgets/gauge/config/ga
         MapWidgetComponent,
         HeatmapWidgetConfigComponent,
         ImageViewerComponent,
-        TimeRangeSelectorComponent,
-        TimeRangeSelectorMenuComponent,
         DataExplorerVisualisationSettingsComponent,
         GroupSelectionPanelComponent,
         DataExplorerVisualisationSettingsComponent,
@@ -283,7 +271,6 @@ import { GaugeWidgetConfigComponent } from 
'./components/widgets/gauge/config/ga
         SpTimeSeriesAppearanceConfigComponent,
         SpDataZoomConfigComponent,
     ],
-    providers: [DefaultMatCalendarRangeStrategy, MatRangeDateSelectionModel],
     exports: [],
 })
 export class DataExplorerModule {
diff --git 
a/ui/src/app/data-explorer/services/data-explorer-detect-changes.service.ts 
b/ui/src/app/data-explorer/services/data-explorer-detect-changes.service.ts
index 241d3315c9..bf3631205d 100644
--- a/ui/src/app/data-explorer/services/data-explorer-detect-changes.service.ts
+++ b/ui/src/app/data-explorer/services/data-explorer-detect-changes.service.ts
@@ -51,7 +51,7 @@ export class DataExplorerDetectChangesService {
         originalTimeSettings: TimeSettings,
         currentTimeSettings: TimeSettings,
     ): boolean {
-        if (originalTimeSettings.timeSelectionId == 0) {
+        if (originalTimeSettings.timeSelectionId === 'custom') {
             return this.hasCustomTimeSettingsChanged(
                 originalTimeSettings,
                 currentTimeSettings,

Reply via email to