From 2264a9a3c2bc387829f635801d616d6ed4a7ac6f Mon Sep 17 00:00:00 2001 From: Denys Butenko Date: Tue, 8 Aug 2023 20:12:21 +0700 Subject: [PATCH] NAS-122296 / 24.04 / Update time interval when manual zoom on Reports (#8512) * NAS-122296: Update start/end dates on mouse selection * NAS-122296: Allow to reset zoom on button * NAS-122296: Update date in legend on hover * NAS-122296: Fix timezone for chart interval dates --- .../line-chart/line-chart.component.ts | 7 +- .../components/report/report.component.html | 15 +++- .../components/report/report.component.ts | 88 +++++++++++-------- .../reports-dashboard.module.ts | 3 +- 4 files changed, 71 insertions(+), 42 deletions(-) diff --git a/src/app/pages/reports-dashboard/components/line-chart/line-chart.component.ts b/src/app/pages/reports-dashboard/components/line-chart/line-chart.component.ts index f56a4ec4b45..b1ee09c5a38 100644 --- a/src/app/pages/reports-dashboard/components/line-chart/line-chart.component.ts +++ b/src/app/pages/reports-dashboard/components/line-chart/line-chart.component.ts @@ -1,5 +1,5 @@ import { - Component, Input, AfterViewInit, OnDestroy, OnChanges, ViewChild, ElementRef, + Component, Input, AfterViewInit, OnDestroy, OnChanges, ViewChild, ElementRef, EventEmitter, Output, } from '@angular/core'; import { UUID } from 'angular2-uuid'; import { utcToZonedTime } from 'date-fns-tz'; @@ -54,6 +54,8 @@ export class LineChartComponent implements AfterViewInit, OnDestroy, OnChanges { culling = 6; controlUid = `chart_${UUID.UUID()}`; + @Output() zoomChange = new EventEmitter(); + private utils: ThemeUtils = new ThemeUtils(); constructor( @@ -150,6 +152,9 @@ export class LineChartComponent implements AfterViewInit, OnDestroy, OnChanges { console.warn('axes not found'); } }, + zoomCallback: (startDate: number, endDate: number) => { + this.zoomChange.emit([startDate, endDate]); + }, stackedGraph: this.stacked, } as unknown as dygraphs.Options; diff --git a/src/app/pages/reports-dashboard/components/report/report.component.html b/src/app/pages/reports-dashboard/components/report/report.component.html index 0aa675ca6ea..ae1a19962ba 100644 --- a/src/app/pages/reports-dashboard/components/report/report.component.html +++ b/src/app/pages/reports-dashboard/components/report/report.component.html @@ -46,7 +46,7 @@

{{ reportTitle }}

> {{ reportTitle }} [title]="report.title" [timezone]="timezone" [labelY]="report.vertical_label || ''" + (zoomChange)="onZoomChange($event)" >

{{ 'Start' | translate }}: - {{ currentStartDate | formatDateTime:timezone }} + + {{ currentStartDate | formatDateTime:null }} + {{ currentStartDate | formatDateTime }} + ({{ timezone }})

{{ 'End' | translate }}: - {{ currentEndDate | formatDateTime:timezone }} + + {{ currentEndDate | formatDateTime:null }} + {{ currentEndDate | formatDateTime }} +

@@ -100,7 +107,7 @@

{{ 'Time' | translate }}: - + {{ legendData.xHTML }}

diff --git a/src/app/pages/reports-dashboard/components/report/report.component.ts b/src/app/pages/reports-dashboard/components/report/report.component.ts index 8e70ed64ad7..2f7aebfcdfa 100644 --- a/src/app/pages/reports-dashboard/components/report/report.component.ts +++ b/src/app/pages/reports-dashboard/components/report/report.component.ts @@ -18,6 +18,7 @@ import { delay, distinctUntilChanged, filter, switchMap, throttleTime, } from 'rxjs/operators'; import { toggleMenuDuration } from 'app/constants/toggle-menu-duration'; +import { FormatDateTimePipe } from 'app/core/pipes/format-datetime.pipe'; import { EmptyType } from 'app/enums/empty-type.enum'; import { ReportingGraphName } from 'app/enums/reporting.enum'; import { WINDOW } from 'app/helpers/window.helper'; @@ -72,6 +73,7 @@ export class ReportComponent extends WidgetComponent implements OnInit, OnChange timezone: string; currentStartDate: number; currentEndDate: number; + customZoom = false; zoomLevelMax = Object.keys(ReportZoomLevel).length - 1; zoomLevelMin = 0; zoomLevelIndex = this.zoomLevelMax; @@ -126,6 +128,7 @@ export class ReportComponent extends WidgetComponent implements OnInit, OnChange private core: CoreService, private store$: Store, private themeService: ThemeService, + private formatDateTimePipe: FormatDateTimePipe, @Inject(WINDOW) private window: Window, ) { super(translate); @@ -141,8 +144,8 @@ export class ReportComponent extends WidgetComponent implements OnInit, OnChange untilDestroyed(this), ).subscribe((evt: LegendEvent) => { const clone = { ...evt.data }; - clone.xHTML = this.formatTime(evt.data.xHTML); clone.series = formatLegendSeries(evt.data.series, this.data); + clone.xHTML = this.formatTime(evt.data.x); this.legendData = clone as LegendDataWithStackedTotalHtml; }); @@ -236,12 +239,18 @@ export class ReportComponent extends WidgetComponent implements OnInit, OnChange this.core.unregister({ observerClass: this }); } - formatTime(stamp: string): string { - const parsed = Date.parse(stamp); - const result = this.localeService.formatDateTimeWithNoTz(new Date(parsed)); + formatTime(stamp: number): string { + const result = this.localeService.formatDateTimeWithNoTz(new Date(stamp)); return result.toLowerCase() !== 'invalid date' ? result : null; } + onZoomChange(interval: number[]): void { + const [startDate, endDate] = interval; + this.currentStartDate = startDate; + this.currentEndDate = endDate; + this.customZoom = true; + } + setChartInteractive(value: boolean): void { this.isActive = value; } @@ -251,6 +260,7 @@ export class ReportComponent extends WidgetComponent implements OnInit, OnChange const rrdOptions = this.convertTimespan(this.currentZoomLevel); this.currentStartDate = rrdOptions.start; this.currentEndDate = rrdOptions.end; + this.customZoom = false; const identifier = this.report.identifiers ? this.report.identifiers[0] : null; this.fetchReport$.next({ rrdOptions, identifier, report: this.report }); @@ -265,6 +275,7 @@ export class ReportComponent extends WidgetComponent implements OnInit, OnChange const rrdOptions = this.convertTimespan(this.currentZoomLevel); this.currentStartDate = rrdOptions.start; this.currentEndDate = rrdOptions.end; + this.customZoom = false; const identifier = this.report.identifiers ? this.report.identifiers[0] : null; this.fetchReport$.next({ rrdOptions, identifier, report: this.report }); @@ -279,6 +290,7 @@ export class ReportComponent extends WidgetComponent implements OnInit, OnChange const rrdOptions = this.convertTimespan(this.currentZoomLevel); this.currentStartDate = rrdOptions.start; this.currentEndDate = rrdOptions.end; + this.customZoom = false; const identifier = this.report.identifiers ? this.report.identifiers[0] : null; this.fetchReport$.next({ rrdOptions, identifier, report: this.report }); @@ -318,19 +330,17 @@ export class ReportComponent extends WidgetComponent implements OnInit, OnChange this.fetchReport$.next({ rrdOptions, identifier, report: this.report }); } - // Convert timespan to start/end options for RRDTool + // Convert timespan to start/end options convertTimespan( timespan: ReportZoomLevel, direction = ReportStepDirection.Backward, currentDate?: number, ): TimeData { - let durationUnit: keyof Duration; - let value: number; - + const duration = this.getTimespan(timespan); const now = new Date(); - let startDate: Date; let endDate: Date; + if (direction === ReportStepDirection.Backward && !currentDate) { endDate = now; } else if (direction === ReportStepDirection.Backward && currentDate) { @@ -343,39 +353,16 @@ export class ReportComponent extends WidgetComponent implements OnInit, OnChange ); } - switch (timespan) { - case ReportZoomLevel.HalfYear: - durationUnit = 'months'; - value = 6; - break; - case ReportZoomLevel.Month: - durationUnit = 'months'; - value = 1; - break; - case ReportZoomLevel.Week: - durationUnit = 'days'; - value = 7; - break; - case ReportZoomLevel.Day: - durationUnit = 'hours'; - value = 24; - break; - case ReportZoomLevel.Hour: - durationUnit = 'minutes'; - value = 60; - break; - } - if (direction === ReportStepDirection.Backward) { - startDate = sub(endDate, { [durationUnit]: value }); + startDate = sub(endDate, duration); } else if (direction === ReportStepDirection.Forward) { - endDate = add(startDate, { [durationUnit]: value }); + endDate = add(startDate, duration); } // if endDate is in the future, reset with endDate to now if (endDate.getTime() >= now.getTime()) { - endDate = new Date(); - startDate = sub(endDate, { [durationUnit]: value }); + endDate = now; + startDate = sub(endDate, duration); this.stepForwardDisabled = true; } else { this.stepForwardDisabled = false; @@ -394,6 +381,35 @@ export class ReportComponent extends WidgetComponent implements OnInit, OnChange }; } + getTimespan(zoomLevel: ReportZoomLevel): { [x: string]: number } { + let durationUnit: keyof Duration; + let value: number; + + switch (zoomLevel) { + case ReportZoomLevel.HalfYear: + durationUnit = 'months'; + value = 6; + break; + case ReportZoomLevel.Month: + durationUnit = 'months'; + value = 1; + break; + case ReportZoomLevel.Week: + durationUnit = 'days'; + value = 7; + break; + case ReportZoomLevel.Day: + durationUnit = 'hours'; + value = 24; + break; + case ReportZoomLevel.Hour: + durationUnit = 'minutes'; + value = 60; + break; + } + return { [durationUnit]: value }; + } + fetchReportData(fetchParams: FetchReportParams): void { const { report, identifier, rrdOptions } = fetchParams; // Report options diff --git a/src/app/pages/reports-dashboard/reports-dashboard.module.ts b/src/app/pages/reports-dashboard/reports-dashboard.module.ts index 2d8d99c206c..93e31fcc8a3 100644 --- a/src/app/pages/reports-dashboard/reports-dashboard.module.ts +++ b/src/app/pages/reports-dashboard/reports-dashboard.module.ts @@ -12,6 +12,7 @@ import { MatToolbarModule } from '@angular/material/toolbar'; import { MatTooltipModule } from '@angular/material/tooltip'; import { TranslateModule } from '@ngx-translate/core'; import { CoreComponents } from 'app/core/core-components.module'; +import { FormatDateTimePipe } from 'app/core/pipes/format-datetime.pipe'; import { CommonDirectivesModule } from 'app/directives/common/common-directives.module'; import { AppCommonModule } from 'app/modules/common/app-common.module'; import { EntityModule } from 'app/modules/entity/entity.module'; @@ -45,7 +46,6 @@ import { ReportsGlobalControlsComponent } from './components/reports-global-cont MatCardModule, FlexLayoutModule, CommonDirectivesModule, - EntityModule, LayoutModule, MatButtonToggleModule, MatSlideToggleModule, @@ -58,5 +58,6 @@ import { ReportsGlobalControlsComponent } from './components/reports-global-cont ReportsDashboardComponent, ReportsGlobalControlsComponent, ], + providers: [FormatDateTimePipe], }) export class ReportsDashboardModule {}