UI: Updated shared component

This commit is contained in:
Vladyslav_Prykhodko 2025-05-27 11:31:34 +03:00
parent 43176d37fc
commit e5d6b2bf1b
12 changed files with 176 additions and 99 deletions

View File

@ -21,7 +21,8 @@ import {
Component,
ElementRef,
EventEmitter,
Input, NgZone,
Input,
NgZone,
OnChanges,
OnDestroy,
OnInit,
@ -59,7 +60,7 @@ import { EntityTypeTranslation } from '@shared/models/entity-type.models';
import { DialogService } from '@core/services/dialog.service';
import { AddEntityDialogComponent } from './add-entity-dialog.component';
import { AddEntityDialogData, EntityAction } from '@home/models/entity/entity-component.models';
import { calculateIntervalStartEndTime, HistoryWindowType, Timewindow } from '@shared/models/time/time.models';
import { getTimePageLinkInterval, Timewindow } from '@shared/models/time/time.models';
import { DomSanitizer, SafeHtml } from '@angular/platform-browser';
import { TbAnchorComponent } from '@shared/components/tb-anchor.component';
import { isDefined, isEqual, isNotEmptyStr, isUndefined } from '@core/utils';
@ -259,7 +260,7 @@ export class EntitiesTableComponent extends PageComponent implements IEntitiesTa
if (this.entitiesTableConfig.useTimePageLink) {
this.timewindow = this.entitiesTableConfig.defaultTimewindowInterval;
const interval = this.getTimePageLinkInterval();
const interval = getTimePageLinkInterval(this.timewindow);
this.pageLink = new TimePageLink(10, 0, null, sortOrder,
interval.startTime, interval.endTime);
} else {
@ -424,7 +425,7 @@ export class EntitiesTableComponent extends PageComponent implements IEntitiesTa
}
if (this.entitiesTableConfig.useTimePageLink) {
const timePageLink = this.pageLink as TimePageLink;
const interval = this.getTimePageLinkInterval();
const interval = getTimePageLinkInterval(this.timewindow);
timePageLink.startTime = interval.startTime;
timePageLink.endTime = interval.endTime;
}
@ -434,31 +435,6 @@ export class EntitiesTableComponent extends PageComponent implements IEntitiesTa
}
}
private getTimePageLinkInterval(): {startTime?: number; endTime?: number} {
const interval: {startTime?: number; endTime?: number} = {};
switch (this.timewindow.history.historyType) {
case HistoryWindowType.LAST_INTERVAL:
const currentTime = Date.now();
interval.startTime = currentTime - this.timewindow.history.timewindowMs;
interval.endTime = currentTime;
break;
case HistoryWindowType.FIXED:
interval.startTime = this.timewindow.history.fixedTimewindow.startTimeMs;
interval.endTime = this.timewindow.history.fixedTimewindow.endTimeMs;
break;
case HistoryWindowType.INTERVAL:
const startEndTime = calculateIntervalStartEndTime(this.timewindow.history.quickInterval);
interval.startTime = startEndTime[0];
interval.endTime = startEndTime[1];
break;
case HistoryWindowType.FOR_ALL_TIME:
interval.startTime = null;
interval.endTime = null;
break;
}
return interval;
}
private dataLoaded(col?: number, row?: number) {
if (isFinite(col) && isFinite(row)) {
this.clearCellCache(col, row);

View File

@ -17,16 +17,20 @@
-->
<div class="tb-entity-list-select flex flex-row" [formGroup]="entityListSelectFormGroup">
<tb-entity-type-select
[inlineField]="inlineField"
[class.flex-1]="inlineField && !modelValue.entityType"
style="min-width: 100px; padding-right: 8px;"
*ngIf="displayEntityTypeSelect"
[showLabel]="true"
[required]="required"
[useAliasEntityTypes]="useAliasEntityTypes"
[allowedEntityTypes]="allowedEntityTypes"
[filterAllowedEntityTypes]="filterAllowedEntityTypes"
formControlName="entityType">
</tb-entity-type-select>
<tb-entity-list
class="flex-1"
[inlineField]="inlineField"
[class.tb-not-empty]="modelValue.ids?.length > 0"
*ngIf="modelValue.entityType"
[required]="required"

View File

@ -14,16 +14,13 @@
/// limitations under the License.
///
import { AfterViewInit, Component, DestroyRef, forwardRef, Input, OnInit } from '@angular/core';
import { ControlValueAccessor, UntypedFormBuilder, UntypedFormGroup, NG_VALUE_ACCESSOR } from '@angular/forms';
import { Store } from '@ngrx/store';
import { AppState } from '@core/core.state';
import { TranslateService } from '@ngx-translate/core';
import { booleanAttribute, Component, DestroyRef, forwardRef, Input, OnInit } from '@angular/core';
import { ControlValueAccessor, NG_VALUE_ACCESSOR, UntypedFormBuilder, UntypedFormGroup } from '@angular/forms';
import { AliasEntityType, EntityType } from '@shared/models/entity-type.models';
import { EntityService } from '@core/http/entity.service';
import { EntityId } from '@shared/models/id/entity-id';
import { coerceBooleanProperty } from '@angular/cdk/coercion';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { isDefinedAndNotNull } from '@core/utils';
interface EntityListSelectModel {
entityType: EntityType | AliasEntityType;
@ -41,7 +38,7 @@ interface EntityListSelectModel {
}]
})
export class EntityListSelectComponent implements ControlValueAccessor, OnInit, AfterViewInit {
export class EntityListSelectComponent implements ControlValueAccessor, OnInit {
entityListSelectFormGroup: UntypedFormGroup;
@ -53,27 +50,28 @@ export class EntityListSelectComponent implements ControlValueAccessor, OnInit,
@Input()
useAliasEntityTypes: boolean;
private requiredValue: boolean;
get required(): boolean {
return this.requiredValue;
}
@Input()
set required(value: boolean) {
this.requiredValue = coerceBooleanProperty(value);
}
@Input({transform: booleanAttribute})
required: boolean;
@Input()
disabled: boolean;
@Input({transform: booleanAttribute})
inlineField: boolean;
@Input({transform: booleanAttribute})
filterAllowedEntityTypes = true;
@Input()
predefinedEntityType: EntityType | AliasEntityType;
displayEntityTypeSelect: boolean;
private readonly defaultEntityType: EntityType | AliasEntityType = null;
private defaultEntityType: EntityType | AliasEntityType = null;
private propagateChange = (v: any) => { };
private propagateChange = (_v: any) => { };
constructor(private store: Store<AppState>,
private entityService: EntityService,
public translate: TranslateService,
constructor(private entityService: EntityService,
private fb: UntypedFormBuilder,
private destroyRef: DestroyRef) {
@ -96,7 +94,7 @@ export class EntityListSelectComponent implements ControlValueAccessor, OnInit,
this.propagateChange = fn;
}
registerOnTouched(fn: any): void {
registerOnTouched(_fn: any): void {
}
ngOnInit() {
@ -114,9 +112,9 @@ export class EntityListSelectComponent implements ControlValueAccessor, OnInit,
this.updateView(this.modelValue.entityType, values);
}
);
}
ngAfterViewInit(): void {
if (isDefinedAndNotNull(this.predefinedEntityType)) {
this.defaultEntityType = this.predefinedEntityType;
}
}
setDisabledState(isDisabled: boolean): void {
@ -145,7 +143,7 @@ export class EntityListSelectComponent implements ControlValueAccessor, OnInit,
this.entityListSelectFormGroup.get('entityIds').patchValue([...this.modelValue.ids], {emitEvent: true});
}
updateView(entityType: EntityType | AliasEntityType | null, entityIds: Array<string> | null) {
private updateView(entityType: EntityType | AliasEntityType | null, entityIds: Array<string> | null) {
if (this.modelValue.entityType !== entityType ||
!this.compareIds(this.modelValue.ids, entityIds)) {
this.modelValue = {
@ -156,7 +154,7 @@ export class EntityListSelectComponent implements ControlValueAccessor, OnInit,
}
}
compareIds(ids1: Array<string> | null, ids2: Array<string> | null): boolean {
private compareIds(ids1: Array<string> | null, ids2: Array<string> | null): boolean {
if (ids1 !== null && ids2 !== null) {
return JSON.stringify(ids1) === JSON.stringify(ids2);
} else {
@ -164,7 +162,7 @@ export class EntityListSelectComponent implements ControlValueAccessor, OnInit,
}
}
toEntityIds(modelValue: EntityListSelectModel): Array<EntityId> {
private toEntityIds(modelValue: EntityListSelectModel): Array<EntityId> {
if (modelValue !== null && modelValue.entityType && modelValue.ids && modelValue.ids.length > 0) {
const entityType = modelValue.entityType;
return modelValue.ids.map(id => ({entityType, id}));

View File

@ -15,8 +15,13 @@
limitations under the License.
-->
<mat-form-field [formGroup]="entityListFormGroup" class="mat-block" [class.tb-chip-list]="!labelText" [appearance]="appearance" [subscriptSizing]="subscriptSizing">
<mat-label *ngIf="labelText">{{ labelText }}</mat-label>
<mat-form-field [formGroup]="entityListFormGroup" class="mat-block"
[appearance]="inlineField ? 'outline' : appearance"
[class.tb-chip-list]="!labelText && !inlineField"
[class.tb-chips]="inlineField"
[class.flex]="inlineField"
[subscriptSizing]="inlineField ? 'dynamic' : subscriptSizing">
<mat-label *ngIf="!inlineField && labelText">{{ labelText }}</mat-label> <mat-label *ngIf="labelText">{{ labelText }}</mat-label>
<mat-chip-grid #chipList formControlName="entities">
<mat-chip-row
*ngFor="let entity of entities"
@ -48,16 +53,16 @@
</div>
<ng-template #searchNotEmpty>
<span>
{{ translate.get('entity.no-entities-matching', {entity: searchText}) | async }}
{{ 'entity.no-entities-matching' | translate: {entity: searchText} }}
</span>
</ng-template>
</div>
</mat-option>
</mat-autocomplete>
<mat-hint *ngIf="hint">
<mat-hint *ngIf="!inlineField && hint">
{{ hint }}
</mat-hint>
<mat-error *ngIf="entityListFormGroup.get('entities').hasError('required')">
<mat-error *ngIf="!inlineField && entityListFormGroup.get('entities').hasError('required')">
{{ requiredText }}
</mat-error>
<div matSuffix>

View File

@ -14,17 +14,7 @@
/// limitations under the License.
///
import {
AfterViewInit,
Component,
ElementRef,
forwardRef,
Input,
OnChanges,
OnInit,
SimpleChanges,
ViewChild
} from '@angular/core';
import { Component, ElementRef, forwardRef, Input, OnChanges, OnInit, SimpleChanges, ViewChild } from '@angular/core';
import {
ControlValueAccessor,
NG_VALIDATORS,
@ -65,7 +55,7 @@ import { isArray } from 'lodash';
}
]
})
export class EntityListComponent implements ControlValueAccessor, OnInit, AfterViewInit, OnChanges {
export class EntityListComponent implements ControlValueAccessor, OnInit, OnChanges {
entityListFormGroup: UntypedFormGroup;
@ -115,6 +105,10 @@ export class EntityListComponent implements ControlValueAccessor, OnInit, AfterV
@coerceBoolean()
syncIdsWithDB = false;
@Input()
@coerceBoolean()
inlineField: boolean;
@ViewChild('entityInput') entityInput: ElementRef<HTMLInputElement>;
@ViewChild('entityAutocomplete') matAutocomplete: MatAutocomplete;
@ViewChild('chipList', {static: true}) chipList: MatChipGrid;
@ -126,9 +120,9 @@ export class EntityListComponent implements ControlValueAccessor, OnInit, AfterV
private dirty = false;
private propagateChange = (v: any) => { };
private propagateChange = (_v: any) => { };
constructor(public translate: TranslateService,
constructor(private translate: TranslateService,
private entityService: EntityService,
private fb: UntypedFormBuilder) {
this.entityListFormGroup = this.fb.group({
@ -146,7 +140,7 @@ export class EntityListComponent implements ControlValueAccessor, OnInit, AfterV
this.propagateChange = fn;
}
registerOnTouched(fn: any): void {
registerOnTouched(_fn: any): void {
}
ngOnInit() {
@ -178,9 +172,6 @@ export class EntityListComponent implements ControlValueAccessor, OnInit, AfterV
}
}
ngAfterViewInit(): void {
}
setDisabledState(isDisabled: boolean): void {
this.disabled = isDisabled;
if (isDisabled) {

View File

@ -15,14 +15,16 @@
limitations under the License.
-->
<mat-form-field [formGroup]="entityTypeFormGroup" [appearance]="appearance">
<mat-label *ngIf="showLabel">{{ 'entity.type' | translate }}</mat-label>
<mat-form-field [formGroup]="entityTypeFormGroup"
[subscriptSizing]="inlineField ? 'dynamic' : 'fixed'"
[appearance]="inlineField ? 'outline' : appearance">
<mat-label *ngIf="showLabel && !inlineField">{{ label }}</mat-label>
<mat-select [required]="required" formControlName="entityType">
<mat-option *ngFor="let type of entityTypes" [value]="type">
{{ displayEntityTypeFn(type) }}
</mat-option>
</mat-select>
<mat-error *ngIf="entityTypeFormGroup.get('entityType').hasError('required')">
<mat-error *ngIf="!inlineField && entityTypeFormGroup.get('entityType').hasError('required')">
{{ 'entity.type-required' | translate }}
</mat-error>
</mat-form-field>

View File

@ -52,6 +52,9 @@ export class EntityTypeSelectComponent implements ControlValueAccessor, OnInit,
@coerceBoolean()
showLabel: boolean;
@Input()
label = this.translate.instant('entity.type');
@Input()
@coerceBoolean()
required: boolean;
@ -65,12 +68,16 @@ export class EntityTypeSelectComponent implements ControlValueAccessor, OnInit,
@Input()
appearance: MatFormFieldAppearance = 'fill';
@Input()
@coerceBoolean()
inlineField: boolean;
entityTypes: Array<EntityType | AliasEntityType | string>;
private propagateChange = (v: any) => { };
private propagateChange = (_v: any) => { };
constructor(private entityService: EntityService,
public translate: TranslateService,
private translate: TranslateService,
private fb: UntypedFormBuilder,
private destroyRef: DestroyRef) {
this.entityTypeFormGroup = this.fb.group({
@ -82,7 +89,7 @@ export class EntityTypeSelectComponent implements ControlValueAccessor, OnInit,
this.propagateChange = fn;
}
registerOnTouched(fn: any): void {
registerOnTouched(_fn: any): void {
}
ngOnInit() {
@ -97,7 +104,7 @@ export class EntityTypeSelectComponent implements ControlValueAccessor, OnInit,
takeUntilDestroyed(this.destroyRef)
).subscribe(
(value) => {
let modelValue;
let modelValue: EntityType | AliasEntityType;
if (!value || value === '') {
modelValue = null;
} else {

View File

@ -27,7 +27,7 @@
</button>
</div>
<div class="tb-timewindow-form-content tb-form-panel no-border">
<div class="tb-timewindow-form-content tb-form-panel no-border" [class.no-padding]="!panelMode">
<ng-container *ngIf="timewindowForm.get('selectedTab').value === timewindowTypes.REALTIME">
<section class="tb-form-panel stroked" *ngIf="realtimeIntervalSelectionAvailable; else timezoneSelectionPanel">
<div class="tb-flex space-between"
@ -189,8 +189,8 @@
formControlName="timezone">
</tb-timezone>
</ng-template>
<mat-divider></mat-divider>
<div class="tb-panel-actions tb-flex flex-end no-gap">
<mat-divider *ngIf="panelMode"></mat-divider>
<div class="tb-panel-actions tb-flex flex-end no-gap" *ngIf="panelMode">
<button type="button"
mat-button
[disabled]="(isLoading$ | async)"

View File

@ -14,7 +14,17 @@
/// limitations under the License.
///
import { Component, Inject, InjectionToken, OnDestroy, OnInit, ViewContainerRef } from '@angular/core';
import {
Component,
EventEmitter,
Inject,
InjectionToken,
OnDestroy,
OnInit,
Optional,
Output,
ViewContainerRef
} from '@angular/core';
import {
AggregationType,
currentHistoryTimewindow,
@ -57,6 +67,7 @@ export interface TimewindowPanelData {
aggregation: boolean;
timezone: boolean;
isEdit: boolean;
panelMode: boolean;
}
export const TIMEWINDOW_PANEL_DATA = new InjectionToken<any>('TimewindowPanelData');
@ -68,6 +79,9 @@ export const TIMEWINDOW_PANEL_DATA = new InjectionToken<any>('TimewindowPanelDat
})
export class TimewindowPanelComponent extends PageComponent implements OnInit, OnDestroy {
@Output()
changeTimewindow = new EventEmitter<Timewindow>();
historyOnly = false;
forAllTimeEnabled = false;
@ -80,6 +94,8 @@ export class TimewindowPanelComponent extends PageComponent implements OnInit, O
isEdit = false;
panelMode = true;
timewindow: Timewindow;
timewindowForm: UntypedFormGroup;
@ -125,7 +141,7 @@ export class TimewindowPanelComponent extends PageComponent implements OnInit, O
private destroy$ = new Subject<void>();
constructor(@Inject(TIMEWINDOW_PANEL_DATA) public data: TimewindowPanelData,
public overlayRef: OverlayRef,
@Optional() public overlayRef: OverlayRef,
protected store: Store<AppState>,
public fb: UntypedFormBuilder,
private timeService: TimeService,
@ -140,6 +156,7 @@ export class TimewindowPanelComponent extends PageComponent implements OnInit, O
this.aggregation = data.aggregation;
this.timezone = data.timezone;
this.isEdit = data.isEdit;
this.panelMode = data.panelMode;
this.updateTimewindowAdvancedParams();
@ -356,6 +373,15 @@ export class TimewindowPanelComponent extends PageComponent implements OnInit, O
).subscribe((selectedTab: TimewindowType) => {
this.onTimewindowTypeChange(selectedTab);
});
if (!this.panelMode) {
this.timewindowForm.valueChanges.pipe(
takeUntil(this.destroy$)
).subscribe(() => {
this.prepareTimewindowConfig();
this.changeTimewindow.emit(this.timewindow);
});
}
}
ngOnDestroy() {
@ -381,7 +407,7 @@ export class TimewindowPanelComponent extends PageComponent implements OnInit, O
update() {
this.prepareTimewindowConfig();
this.result = this.timewindow;
this.overlayRef.dispose();
this.overlayRef?.dispose();
}
private prepareTimewindowConfig() {
@ -483,7 +509,7 @@ export class TimewindowPanelComponent extends PageComponent implements OnInit, O
}
cancel() {
this.overlayRef.dispose();
this.overlayRef?.dispose();
}
get minRealtimeAggInterval() {

View File

@ -15,7 +15,7 @@
limitations under the License.
-->
<button *ngIf="asButton && !strokedButton && !flatButton"
<button *ngIf="asButton && panelMode && !strokedButton && !flatButton"
[disabled]="timewindowDisabled"
type="button"
mat-raised-button color="primary"
@ -23,7 +23,7 @@
<mat-icon class="material-icons">query_builder</mat-icon>
<span>{{displayValue()}}</span>
</button>
<button *ngIf="asButton && strokedButton"
<button *ngIf="asButton && panelMode && strokedButton"
[disabled]="timewindowDisabled"
type="button"
mat-stroked-button color="primary"
@ -31,7 +31,7 @@
<mat-icon class="material-icons">query_builder</mat-icon>
<span>{{displayValue()}}</span>
</button>
<button *ngIf="asButton && flatButton"
<button *ngIf="asButton && panelMode && flatButton"
[disabled]="timewindowDisabled"
type="button"
mat-button
@ -39,7 +39,7 @@
<mat-icon class="material-icons">query_builder</mat-icon>
<span>{{displayValue()}}</span>
</button>
<section *ngIf="!asButton"
<section *ngIf="!asButton && panelMode"
class="tb-timewindow"
[class]="{'no-padding': noPadding}"
matTooltip="{{ 'timewindow.edit' | translate }}"
@ -55,3 +55,4 @@
<tb-icon *ngIf="computedTimewindowStyle.showIcon && computedTimewindowStyle.iconPosition === 'right'"
[style]="timewindowIconStyle">{{ computedTimewindowStyle.icon }}</tb-icon>
</section>
<ng-container #panelContainer></ng-container>

View File

@ -17,6 +17,7 @@
import {
ChangeDetectorRef,
Component,
DestroyRef,
ElementRef,
forwardRef,
HostBinding,
@ -26,6 +27,7 @@ import {
OnInit,
SimpleChanges,
StaticProvider,
ViewChild,
ViewContainerRef
} from '@angular/core';
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
@ -63,6 +65,7 @@ import {
} from '@shared/models/widget-settings.models';
import { DEFAULT_OVERLAY_POSITIONS } from '@shared/models/overlay.models';
import { fromEvent } from 'rxjs';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
// @dynamic
@Component({
@ -79,6 +82,8 @@ import { fromEvent } from 'rxjs';
})
export class TimewindowComponent implements ControlValueAccessor, OnInit, OnChanges {
@ViewChild('panelContainer', { read: ViewContainerRef, static: true }) panelContainer: ViewContainerRef;
historyOnlyValue = false;
@Input()
@ -180,6 +185,10 @@ export class TimewindowComponent implements ControlValueAccessor, OnInit, OnChan
@coerceBoolean()
disabled: boolean;
@Input()
@coerceBoolean()
panelMode = true;
innerValue: Timewindow;
timewindowDisabled: boolean;
@ -197,7 +206,8 @@ export class TimewindowComponent implements ControlValueAccessor, OnInit, OnChan
private datePipe: DatePipe,
private cd: ChangeDetectorRef,
private nativeElement: ElementRef,
public viewContainerRef: ViewContainerRef) {
private viewContainerRef: ViewContainerRef,
private destroyRef: DestroyRef) {
}
ngOnInit() {
@ -249,7 +259,8 @@ export class TimewindowComponent implements ControlValueAccessor, OnInit, OnChan
quickIntervalOnly: this.quickIntervalOnly,
aggregation: this.aggregation,
timezone: this.timezone,
isEdit: this.isEdit
isEdit: this.isEdit,
panelMode: this.panelMode,
} as TimewindowPanelData
},
{
@ -317,6 +328,9 @@ export class TimewindowComponent implements ControlValueAccessor, OnInit, OnChan
} else {
this.updateDisplayValue();
}
if (!this.panelMode) {
this.createPanel();
}
}
notifyChanged() {
@ -328,6 +342,9 @@ export class TimewindowComponent implements ControlValueAccessor, OnInit, OnChan
}
updateDisplayValue() {
if (!this.panelMode) {
return
}
if (this.innerValue.selectedTab === TimewindowType.REALTIME && !this.historyOnly) {
this.innerValue.displayValue = this.displayTypePrefix ? (this.translate.instant('timewindow.realtime') + ' - ') : '';
if (this.innerValue.realtime.realtimeType === RealtimeWindowType.INTERVAL) {
@ -373,4 +390,29 @@ export class TimewindowComponent implements ControlValueAccessor, OnInit, OnChan
)));
}
private createPanel() {
this.panelContainer.clear();
const panelData = {
timewindow: deepClone(this.innerValue),
historyOnly: this.historyOnly,
forAllTimeEnabled: this.forAllTimeEnabled,
quickIntervalOnly: this.quickIntervalOnly,
aggregation: this.aggregation,
timezone: this.timezone,
isEdit: this.isEdit,
panelMode: this.panelMode,
}
const injector = Injector.create({
providers: [{ provide: TIMEWINDOW_PANEL_DATA, useValue: panelData }],
parent: this.viewContainerRef.injector
});
const componentRef = this.panelContainer.createComponent(TimewindowPanelComponent, {index: 0, injector});
componentRef.instance.changeTimewindow.pipe(
takeUntilDestroyed(this.destroyRef)
).subscribe(value => {
this.innerValue = value;
this.timewindowDisabled = this.isTimewindowDisabled();
this.notifyChanged();
})
}
}

View File

@ -1406,3 +1406,28 @@ export const calculateInterval = (startTime: number, endTime: number,
export const getCurrentTimeForComparison = (timeForComparison: moment_.unitOfTime.DurationConstructor, tz?: string): moment_.Moment =>
getCurrentTime(tz).subtract(1, timeForComparison);
export const getTimePageLinkInterval = (timewindow: Timewindow): {startTime?: number; endTime?: number} => {
const interval: {startTime?: number; endTime?: number} = {};
switch (timewindow.history.historyType) {
case HistoryWindowType.LAST_INTERVAL:
const currentTime = Date.now();
interval.startTime = currentTime - timewindow.history.timewindowMs;
interval.endTime = currentTime;
break;
case HistoryWindowType.FIXED:
interval.startTime = timewindow.history.fixedTimewindow.startTimeMs;
interval.endTime = timewindow.history.fixedTimewindow.endTimeMs;
break;
case HistoryWindowType.INTERVAL:
const startEndTime = calculateIntervalStartEndTime(timewindow.history.quickInterval);
interval.startTime = startEndTime[0];
interval.endTime = startEndTime[1];
break;
case HistoryWindowType.FOR_ALL_TIME:
interval.startTime = null;
interval.endTime = null;
break;
}
return interval;
}