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 472569d5e1 feat: Add time selection menu for single widgets in 
dashboard (#3240)
472569d5e1 is described below

commit 472569d5e1fbf2b5b768f043e4d6d0e4e97dc95b
Author: Marcel Früholz <[email protected]>
AuthorDate: Fri Sep 27 09:21:47 2024 +0200

    feat: Add time selection menu for single widgets in dashboard (#3240)
---
 .../streampipes/model/dashboard/DashboardItem.java | 10 ++++
 .../src/lib/model/dashboard/dashboard.model.ts     |  1 +
 .../src/lib/model/datalake/DateRange.ts            |  5 ++
 .../src/lib/model/gen/streampipes-model.ts         |  6 ++-
 .../custom-time-range-selection.component.html     |  1 +
 .../time-selector-menu.component.html              |  1 +
 .../data-explorer-dashboard-widget.component.html  | 28 ++++++++++
 .../data-explorer-dashboard-widget.component.ts    | 61 ++++++++++++++++++++--
 .../base/base-data-explorer-widget.directive.ts    | 26 +++++----
 ...a-explorer-edit-dashboard-dialog.component.html |  3 +-
 .../models/dataview-dashboard.model.ts             |  1 +
 .../services/time-selection.service.ts             | 10 ++--
 12 files changed, 134 insertions(+), 19 deletions(-)

diff --git 
a/streampipes-model/src/main/java/org/apache/streampipes/model/dashboard/DashboardItem.java
 
b/streampipes-model/src/main/java/org/apache/streampipes/model/dashboard/DashboardItem.java
index c7962b0411..81759642cb 100644
--- 
a/streampipes-model/src/main/java/org/apache/streampipes/model/dashboard/DashboardItem.java
+++ 
b/streampipes-model/src/main/java/org/apache/streampipes/model/dashboard/DashboardItem.java
@@ -18,6 +18,7 @@
 package org.apache.streampipes.model.dashboard;
 
 import java.util.List;
+import java.util.Map;
 
 public class DashboardItem {
 
@@ -31,6 +32,7 @@ public class DashboardItem {
   private Integer rows;
   private Integer x;
   private Integer y;
+  private Map<String, Object> timeSettings;
 
   public DashboardItem() {
 
@@ -99,4 +101,12 @@ public class DashboardItem {
   public void setY(Integer y) {
     this.y = y;
   }
+
+  public Map<String, Object> getTimeSettings() {
+    return timeSettings;
+  }
+
+  public void setTimeSettings(Map<String, Object> timeSettings) {
+    this.timeSettings = timeSettings;
+  }
 }
diff --git 
a/ui/projects/streampipes/platform-services/src/lib/model/dashboard/dashboard.model.ts
 
b/ui/projects/streampipes/platform-services/src/lib/model/dashboard/dashboard.model.ts
index 8a65f934ed..532a19b2d4 100644
--- 
a/ui/projects/streampipes/platform-services/src/lib/model/dashboard/dashboard.model.ts
+++ 
b/ui/projects/streampipes/platform-services/src/lib/model/dashboard/dashboard.model.ts
@@ -25,6 +25,7 @@ export interface DashboardConfig extends GridsterConfig {}
 export interface ClientDashboardItem extends GridsterItem {
     widgetId: string;
     widgetType: string;
+    timeSettings?: TimeSettings;
     id: string;
 }
 
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 6c305f6dd4..9f3cff7d29 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
@@ -24,6 +24,11 @@ export interface TimeSettings {
     timeSelectionId?: TimeSelectionId;
 }
 
+export interface WidgetTimeSettings {
+    timeSettings: TimeSettings;
+    widgetIndex?: number;
+}
+
 export interface TimeString {
     startDate: string;
     startTime: string;
diff --git 
a/ui/projects/streampipes/platform-services/src/lib/model/gen/streampipes-model.ts
 
b/ui/projects/streampipes/platform-services/src/lib/model/gen/streampipes-model.ts
index 7c9650ec20..398a67c5f7 100644
--- 
a/ui/projects/streampipes/platform-services/src/lib/model/gen/streampipes-model.ts
+++ 
b/ui/projects/streampipes/platform-services/src/lib/model/gen/streampipes-model.ts
@@ -20,7 +20,7 @@
 /* tslint:disable */
 /* eslint-disable */
 // @ts-nocheck
-// Generated using typescript-generator version 3.2.1263 on 2024-09-10 
17:11:03.
+// Generated using typescript-generator version 3.2.1263 on 2024-09-18 
15:50:05.
 
 export class NamedStreamPipesEntity implements Storable {
     '@class':
@@ -970,6 +970,7 @@ export class DashboardItem {
     name: string;
     rows: number;
     settings: string[];
+    timeSettings: { [index: string]: any };
     x: number;
     y: number;
 
@@ -989,6 +990,9 @@ export class DashboardItem {
         instance.settings = __getCopyArrayFn(__identity<string>())(
             data.settings,
         );
+        instance.timeSettings = __getCopyObjectFn(__identity<any>())(
+            data.timeSettings,
+        );
         instance.x = data.x;
         instance.y = data.y;
         return instance;
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/src/app/data-explorer/components/time-selector/time-selector-menu/custom-time-range-selection/custom-time-range-selection.component.html
index 9e277f0ca6..1564d9b5dc 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/src/app/data-explorer/components/time-selector/time-selector-menu/custom-time-range-selection/custom-time-range-selection.component.html
@@ -74,6 +74,7 @@
         </div>
     </div>
     <div fxLayout="row" fxLayoutAlign="end center" class="mt-10">
+        <ng-content> </ng-content>
         <button
             mat-raised-button
             color="accent"
diff --git 
a/ui/src/app/data-explorer/components/time-selector/time-selector-menu/time-selector-menu.component.html
 
b/ui/src/app/data-explorer/components/time-selector/time-selector-menu/time-selector-menu.component.html
index 70ded63676..e53550aa43 100644
--- 
a/ui/src/app/data-explorer/components/time-selector/time-selector-menu/time-selector-menu.component.html
+++ 
b/ui/src/app/data-explorer/components/time-selector/time-selector-menu/time-selector-menu.component.html
@@ -46,6 +46,7 @@
                     (timeSettingsEmitter)="timeSettingsEmitter.emit($event)"
                     class="w-100"
                 >
+                    <ng-content> </ng-content>
                 </sp-custom-time-range-selection>
             </div>
         </div>
diff --git 
a/ui/src/app/data-explorer/components/widget/data-explorer-dashboard-widget.component.html
 
b/ui/src/app/data-explorer/components/widget/data-explorer-dashboard-widget.component.html
index fa9617a0ed..ea476a9846 100644
--- 
a/ui/src/app/data-explorer/components/widget/data-explorer-dashboard-widget.component.html
+++ 
b/ui/src/app/data-explorer/components/widget/data-explorer-dashboard-widget.component.html
@@ -111,6 +111,34 @@
                 >
                     <mat-icon>get_app</mat-icon>
                 </button>
+                <button
+                    mat-icon-button
+                    [matMenuTriggerFor]="optMenu"
+                    *ngIf="!globalTimeEnabled"
+                    aria-label="Options"
+                    data-cy="options-data-explorer"
+                    #menuTrigger="matMenuTrigger"
+                >
+                    <mat-icon
+                        [color]="timeSettingsModified ? 'primary' : 'default'"
+                        >alarm_clock</mat-icon
+                    >
+                </button>
+                <mat-menu #optMenu="matMenu" class="large-menu">
+                    <sp-time-selector-menu
+                        [timeSettings]="clonedTimeSettings"
+                        
(timeSettingsEmitter)="modifyWidgetTimeSettings($event)"
+                        class="w-100"
+                    >
+                        <button
+                            mat-raised-button
+                            class="mat-basic"
+                            (click)="resetWidgetTimeSettings()"
+                        >
+                            Reset
+                        </button>
+                    </sp-time-selector-menu>
+                </mat-menu>
                 <button
                     mat-icon-button
                     (click)="removeWidget()"
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 9e3e962de2..21e5170c0e 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
@@ -22,9 +22,11 @@ import {
     ComponentRef,
     EventEmitter,
     Input,
+    OnChanges,
     OnDestroy,
     OnInit,
     Output,
+    SimpleChanges,
     ViewChild,
 } from '@angular/core';
 import { GridsterItemComponent } from 'angular-gridster2';
@@ -45,13 +47,18 @@ 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';
 
 @Component({
     selector: 'sp-data-explorer-dashboard-widget',
     templateUrl: './data-explorer-dashboard-widget.component.html',
     styleUrls: ['./data-explorer-dashboard-widget.component.scss'],
 })
-export class DataExplorerDashboardWidgetComponent implements OnInit, OnDestroy 
{
+export class DataExplorerDashboardWidgetComponent
+    implements OnInit, OnDestroy, OnChanges
+{
+    @ViewChild('menuTrigger') menu: MatMenuTrigger;
     @Input()
     dashboardItem: DashboardItem;
 
@@ -97,6 +104,9 @@ export class DataExplorerDashboardWidgetComponent implements 
OnInit, OnDestroy {
     timerActive = false;
     loadingTime = 0;
 
+    clonedTimeSettings: TimeSettings;
+    timeSettingsModified: boolean = false;
+
     hasDataExplorerWritePrivileges = false;
 
     authSubscription: Subscription;
@@ -116,8 +126,16 @@ export class DataExplorerDashboardWidgetComponent 
implements OnInit, OnDestroy {
         private widgetTypeService: WidgetTypeService,
         private authService: AuthService,
         private currentUserService: CurrentUserService,
+        private timeSelectionService: TimeSelectionService,
     ) {}
 
+    ngOnChanges(changes: SimpleChanges): void {
+        if (changes.widgetIndex && this.componentRef?.instance) {
+            this.componentRef.instance.widgetIndex =
+                changes.widgetIndex.currentValue;
+        }
+    }
+
     ngOnInit(): void {
         this.authSubscription = this.currentUserService.user$.subscribe(
             user => {
@@ -139,6 +157,14 @@ export class DataExplorerDashboardWidgetComponent 
implements OnInit, OnDestroy {
                 },
             );
         this.chooseWidget(this.configuredWidget.widgetType);
+        this.clonedTimeSettings = {
+            startTime: this.timeSettings.startTime,
+            endTime: this.timeSettings.endTime,
+            timeSelectionId: this.timeSettings.timeSelectionId,
+        };
+        if (this.dashboardItem.timeSettings !== undefined) {
+            this.timeSettingsModified = true;
+        }
     }
 
     ngOnDestroy() {
@@ -176,6 +202,7 @@ export class DataExplorerDashboardWidgetComponent 
implements OnInit, OnDestroy {
         this.componentRef.instance.dataExplorerWidget = this.configuredWidget;
         this.componentRef.instance.previewMode = this.previewMode;
         this.componentRef.instance.gridMode = this.gridMode;
+        this.componentRef.instance.widgetIndex = this.widgetIndex;
         const removeSub =
             this.componentRef.instance.removeWidgetCallback.subscribe(ev =>
                 this.removeWidget(),
@@ -196,9 +223,13 @@ export class DataExplorerDashboardWidgetComponent 
implements OnInit, OnDestroy {
     }
 
     getTimeSettings(): TimeSettings {
-        return this.globalTimeEnabled
-            ? this.timeSettings
-            : (this.configuredWidget.timeSettings as TimeSettings);
+        if (this.globalTimeEnabled) {
+            return this.timeSettings;
+        } else if (this.dashboardItem.timeSettings !== undefined) {
+            return this.dashboardItem.timeSettings as TimeSettings;
+        } else {
+            return this.configuredWidget.timeSettings as TimeSettings;
+        }
     }
 
     removeWidget() {
@@ -233,4 +264,26 @@ export class DataExplorerDashboardWidgetComponent 
implements OnInit, OnDestroy {
             this.configuredWidget,
         );
     }
+
+    modifyWidgetTimeSettings(timeSettings: TimeSettings): void {
+        this.dashboardItem.timeSettings = timeSettings;
+        this.timeSelectionService.notify(timeSettings, this.widgetIndex);
+        this.menu.closeMenu();
+        this.timeSettingsModified = true;
+    }
+
+    resetWidgetTimeSettings(): void {
+        this.dashboardItem.timeSettings = undefined;
+        this.clonedTimeSettings = {
+            startTime: this.timeSettings.startTime,
+            endTime: this.timeSettings.endTime,
+            timeSelectionId: this.timeSettings.timeSelectionId,
+        };
+        this.timeSelectionService.notify(
+            this.getTimeSettings(),
+            this.widgetIndex,
+        );
+        this.menu.closeMenu();
+        this.timeSettingsModified = false;
+    }
 }
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 b8e86ffdb9..5df627e9e7 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
@@ -83,6 +83,9 @@ export abstract class BaseDataExplorerWidgetDirective<
     @Input() dataViewDashboardItem: DashboardItem;
     @Input() dataExplorerWidget: T;
 
+    @Input()
+    widgetIndex: number;
+
     @HostBinding('class') className = 'h-100';
 
     public selectedProperties: string[];
@@ -193,16 +196,21 @@ export abstract class BaseDataExplorerWidgetDirective<
         }
         this.timeSelectionSub =
             this.timeSelectionService.timeSelectionChangeSubject.subscribe(
-                ts => {
-                    if (ts) {
-                        this.timeSettings = ts;
-                    } else {
-                        this.timeSelectionService.updateTimeSettings(
-                            this.timeSettings,
-                            new Date(),
-                        );
+                widgetTimeSettings => {
+                    if (
+                        widgetTimeSettings.widgetIndex === undefined ||
+                        widgetTimeSettings.widgetIndex === this.widgetIndex
+                    ) {
+                        if (widgetTimeSettings.timeSettings) {
+                            this.timeSettings = 
widgetTimeSettings.timeSettings;
+                        } else {
+                            this.timeSelectionService.updateTimeSettings(
+                                this.timeSettings,
+                                new Date(),
+                            );
+                        }
+                        this.updateData();
                     }
-                    this.updateData();
                 },
             );
         this.updateData();
diff --git 
a/ui/src/app/data-explorer/dialogs/edit-dashboard/data-explorer-edit-dashboard-dialog.component.html
 
b/ui/src/app/data-explorer/dialogs/edit-dashboard/data-explorer-edit-dashboard-dialog.component.html
index de73ccaeff..98b4312145 100644
--- 
a/ui/src/app/data-explorer/dialogs/edit-dashboard/data-explorer-edit-dashboard-dialog.component.html
+++ 
b/ui/src/app/data-explorer/dialogs/edit-dashboard/data-explorer-edit-dashboard-dialog.component.html
@@ -67,7 +67,8 @@
                         [(ngModel)]="
                             
dashboard.dashboardGeneralSettings.globalTimeEnabled
                         "
-                        >Use global time instead of widget time settings
+                        >Use global time settings instead of widget time
+                        settings
                     </mat-checkbox>
                 </div>
                 <!--<mat-checkbox [(ngModel)]="dashboard.displayHeader">Show 
name and description in dashboard</mat-checkbox>-->
diff --git a/ui/src/app/data-explorer/models/dataview-dashboard.model.ts 
b/ui/src/app/data-explorer/models/dataview-dashboard.model.ts
index 670c73a29d..d3597f69db 100644
--- a/ui/src/app/data-explorer/models/dataview-dashboard.model.ts
+++ b/ui/src/app/data-explorer/models/dataview-dashboard.model.ts
@@ -54,6 +54,7 @@ export interface BaseWidgetData<T extends 
DataExplorerWidgetModel> {
     dataExplorerWidget: T;
     previewMode: boolean;
     gridMode: boolean;
+    widgetIndex?: number;
 
     cleanupSubscriptions(): void;
 }
diff --git a/ui/src/app/data-explorer/services/time-selection.service.ts 
b/ui/src/app/data-explorer/services/time-selection.service.ts
index 11a9515cfc..5c55e7756a 100644
--- a/ui/src/app/data-explorer/services/time-selection.service.ts
+++ b/ui/src/app/data-explorer/services/time-selection.service.ts
@@ -23,6 +23,7 @@ import {
     QuickTimeSelection,
     TimeSelectionId,
     TimeSettings,
+    WidgetTimeSettings,
 } from '@streampipes/platform-services';
 import {
     startOfDay,
@@ -178,10 +179,11 @@ export class TimeSelectionService {
         }
     }
 
-    public timeSelectionChangeSubject: Subject<TimeSettings | undefined> =
-        new Subject<TimeSettings | undefined>();
+    public timeSelectionChangeSubject: Subject<WidgetTimeSettings | undefined> 
=
+        new Subject<WidgetTimeSettings | undefined>();
 
-    public notify(timeSettings?: TimeSettings): void {
-        this.timeSelectionChangeSubject.next(timeSettings);
+    public notify(timeSettings?: TimeSettings, widgetIndex?: number): void {
+        const widgetTimeSettings = { timeSettings, widgetIndex };
+        this.timeSelectionChangeSubject.next(widgetTimeSettings);
     }
 }

Reply via email to