Skip to content

Commit

Permalink
NAS-122296 / 24.04 / Update time interval when manual zoom on Reports (
Browse files Browse the repository at this point in the history
…#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
  • Loading branch information
denysbutenko authored Aug 8, 2023
1 parent 4e389de commit 2264a9a
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 42 deletions.
Original file line number Diff line number Diff line change
@@ -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';
Expand Down Expand Up @@ -54,6 +54,8 @@ export class LineChartComponent implements AfterViewInit, OnDestroy, OnChanges {
culling = 6;
controlUid = `chart_${UUID.UUID()}`;

@Output() zoomChange = new EventEmitter<number[]>();

private utils: ThemeUtils = new ThemeUtils();

constructor(
Expand Down Expand Up @@ -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;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ <h3 class="mat-card-title-text">{{ reportTitle }}</h3>
><ix-icon name="mdi-magnify-minus"></ix-icon></mat-button-toggle>

<mat-button-toggle
[disabled]="zoomLevelIndex === zoomLevelMax && stepForwardDisabled"
[disabled]="zoomLevelIndex === zoomLevelMax && stepForwardDisabled && !customZoom"
[matTooltip]="'Reset Zoom' | translate"
[matTooltipShowDelay]="1000"
(click)="timeZoomReset()"
Expand Down Expand Up @@ -80,18 +80,25 @@ <h3 class="mat-card-title-text">{{ reportTitle }}</h3>
[title]="report.title"
[timezone]="timezone"
[labelY]="report.vertical_label || ''"
(zoomChange)="onZoomChange($event)"
></ix-linechart>
</div>

<div class="legend-wrapper timestamps">
<h4 *ngIf="currentStartDate" class="legend-timestamp">
<strong>{{ 'Start' | translate }}:</strong>
<span class="font-normal">{{ currentStartDate | formatDateTime:timezone }}</span>
<span class="font-normal">
<ng-container *ngIf="customZoom">{{ currentStartDate | formatDateTime:null }}</ng-container>
<ng-container *ngIf="!customZoom">{{ currentStartDate | formatDateTime }}</ng-container>
</span>
<small>({{ timezone }})</small>
</h4>
<h4 *ngIf="currentEndDate" class="legend-timestamp">
<strong>{{ 'End' | translate }}:</strong>
<span class="font-normal">{{ currentEndDate | formatDateTime:timezone }}</span>
<span class="font-normal">
<ng-container *ngIf="customZoom">{{ currentEndDate | formatDateTime:null }}</ng-container>
<ng-container *ngIf="!customZoom">{{ currentEndDate | formatDateTime }}</ng-container>
</span>
</h4>
</div>
</div>
Expand All @@ -100,7 +107,7 @@ <h4 *ngIf="currentEndDate" class="legend-timestamp">
<div *ngIf="report && data?.legend" class="legend-timestamp" fxFlex="32px" fxLayoutAlign="start center">
<h4 *ngIf="data && legendData?.xHTML" fxLayoutGap="8px" fxLayoutAlign="start center">
<strong>{{ 'Time' | translate }}:</strong>
<span *ngIf="legendData && legendData.xHTML" class="font-normal">
<span *ngIf="legendData?.xHTML" class="font-normal">
{{ legendData.xHTML }}
</span>
</h4>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -126,6 +128,7 @@ export class ReportComponent extends WidgetComponent implements OnInit, OnChange
private core: CoreService,
private store$: Store<AppState>,
private themeService: ThemeService,
private formatDateTimePipe: FormatDateTimePipe,
@Inject(WINDOW) private window: Window,
) {
super(translate);
Expand All @@ -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;
});

Expand Down Expand Up @@ -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;
}
Expand All @@ -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 });
Expand All @@ -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 });
Expand All @@ -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 });
Expand Down Expand Up @@ -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) {
Expand All @@ -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;
Expand All @@ -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
Expand Down
3 changes: 2 additions & 1 deletion src/app/pages/reports-dashboard/reports-dashboard.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -45,7 +46,6 @@ import { ReportsGlobalControlsComponent } from './components/reports-global-cont
MatCardModule,
FlexLayoutModule,
CommonDirectivesModule,
EntityModule,
LayoutModule,
MatButtonToggleModule,
MatSlideToggleModule,
Expand All @@ -58,5 +58,6 @@ import { ReportsGlobalControlsComponent } from './components/reports-global-cont
ReportsDashboardComponent,
ReportsGlobalControlsComponent,
],
providers: [FormatDateTimePipe],
})
export class ReportsDashboardModule {}

0 comments on commit 2264a9a

Please sign in to comment.