feat: Add time selection menu for single widgets in dashboard (#3240)
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 c7962b0..8175964 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 @@
private Integer rows;
private Integer x;
private Integer y;
+ private Map<String, Object> timeSettings;
public DashboardItem() {
@@ -99,4 +101,12 @@
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 8a65f93..532a19b 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 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 6c305f6..9f3cff7 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 @@
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 7c9650e..398a67c 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 @@
name: string;
rows: number;
settings: string[];
+ timeSettings: { [index: string]: any };
x: number;
y: number;
@@ -989,6 +990,9 @@
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 9e277f0..1564d9b 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 70ded63..e53550a 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 fa9617a..ea476a9 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
@@ -113,6 +113,34 @@
</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()"
matTooltip="Delete widget"
*ngIf="editMode && hasDataExplorerWritePrivileges"
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 9e3e962..21e5170 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 @@
ComponentRef,
EventEmitter,
Input,
+ OnChanges,
OnDestroy,
OnInit,
Output,
+ SimpleChanges,
ViewChild,
} from '@angular/core';
import { GridsterItemComponent } from 'angular-gridster2';
@@ -45,13 +47,18 @@
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 @@
timerActive = false;
loadingTime = 0;
+ clonedTimeSettings: TimeSettings;
+ timeSettingsModified: boolean = false;
+
hasDataExplorerWritePrivileges = false;
authSubscription: Subscription;
@@ -116,8 +126,16 @@
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 @@
},
);
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 @@
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 @@
}
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 @@
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 b8e86ff..5df627e 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 @@
@Input() dataViewDashboardItem: DashboardItem;
@Input() dataExplorerWidget: T;
+ @Input()
+ widgetIndex: number;
+
@HostBinding('class') className = 'h-100';
public selectedProperties: string[];
@@ -193,16 +196,21 @@
}
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 de73cca..98b4312 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 670c73a..d3597f6 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 @@
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 11a9515..5c55e77 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 @@
QuickTimeSelection,
TimeSelectionId,
TimeSettings,
+ WidgetTimeSettings,
} from '@streampipes/platform-services';
import {
startOfDay,
@@ -178,10 +179,11 @@
}
}
- 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);
}
}