UI: timewindow panel history mode redesign

This commit is contained in:
Chantsova Ekaterina 2024-06-28 18:29:47 +03:00
parent 9b7c8595ee
commit 3d7f6adbdd
7 changed files with 172 additions and 152 deletions

View File

@ -17,7 +17,7 @@
-->
<section class="interval-section" fxLayout="row" fxFlex>
<mat-form-field fxFlex [subscriptSizing]="subscriptSizing" [appearance]="appearance">
<mat-label translate>timewindow.interval</mat-label>
<mat-label *ngIf="displayLabel" translate>timewindow.interval</mat-label>
<mat-select [disabled]="disabled" [(ngModel)]="modelValue" (ngModelChange)="onIntervalChange()">
<mat-option *ngFor="let interval of intervals" [value]="interval">
{{ timeIntervalTranslationMap.get(interval) | translate}}

View File

@ -18,6 +18,7 @@ import { Component, forwardRef, Input, OnInit } from '@angular/core';
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
import { QuickTimeInterval, QuickTimeIntervalTranslationMap } from '@shared/models/time/time.models';
import { MatFormFieldAppearance, SubscriptSizing } from '@angular/material/form-field';
import { coerceBoolean } from '@shared/decorators/coercion';
@Component({
selector: 'tb-quick-time-interval',
@ -40,6 +41,10 @@ export class QuickTimeIntervalComponent implements OnInit, ControlValueAccessor
rendered = false;
@Input()
@coerceBoolean()
displayLabel = true;
@Input() disabled: boolean;
@Input() onlyCurrentInterval = false;

View File

@ -22,19 +22,19 @@
</section>
<section class="interval-section" fxLayout="column" fxFlex [fxShow]="advanced && (isEdit || !hideFlag)">
<section fxLayout="row wrap" fxLayoutAlign="start start" fxFlex fxLayoutGap="6px">
<mat-form-field class="number-input" [appearance]="appearance">
<mat-form-field class="number-input" [subscriptSizing]="subscriptSizing" [appearance]="appearance">
<mat-label translate>timeinterval.days</mat-label>
<input matInput [disabled]="hideFlag || disabled" type="number" step="1" min="0" [(ngModel)]="days" (ngModelChange)="onTimeInputChange('days')"/>
</mat-form-field>
<mat-form-field class="number-input" [appearance]="appearance">
<mat-form-field class="number-input" [subscriptSizing]="subscriptSizing" [appearance]="appearance">
<mat-label translate>timeinterval.hours</mat-label>
<input matInput [disabled]="hideFlag || disabled" type="number" step="1" [(ngModel)]="hours" (ngModelChange)="onTimeInputChange('hours')"/>
</mat-form-field>
<mat-form-field class="number-input" [appearance]="appearance">
<mat-form-field class="number-input" [subscriptSizing]="subscriptSizing" [appearance]="appearance">
<mat-label translate>timeinterval.minutes</mat-label>
<input matInput [disabled]="hideFlag || disabled" type="number" step="1" [(ngModel)]="mins" (ngModelChange)="onTimeInputChange('mins')"/>
</mat-form-field>
<mat-form-field class="number-input" [appearance]="appearance">
<mat-form-field class="number-input" [subscriptSizing]="subscriptSizing" [appearance]="appearance">
<mat-label translate>timeinterval.seconds</mat-label>
<input matInput [disabled]="hideFlag || disabled" type="number" step="1" [(ngModel)]="secs" (ngModelChange)="onTimeInputChange('secs')"/>
</mat-form-field>

View File

@ -16,7 +16,7 @@
-->
<form [formGroup]="timewindowForm" class="mat-content">
<mat-tab-group [ngClass]="{'tb-headless': historyOnly}"
<mat-tab-group [class.tb-headless]="historyOnly"
(selectedTabChange)="onTimewindowTypeChange()" [(selectedIndex)]="timewindow.selectedTab">
<mat-tab label="{{ 'timewindow.realtime' | translate }}">
<div class="tb-flex column">
@ -24,24 +24,18 @@
<div class="tb-form-panel-title">{{ 'timewindow.time-range' | translate }}</div>
<div class="tb-flex align-center space-between">
<ng-container formGroupName="realtime">
<tb-toggle-select *ngIf="!quickIntervalOnly"
[fxShow]="isEdit || (!timewindow.hideLastInterval && !timewindow.hideQuickInterval)"
<tb-toggle-select *ngIf="!quickIntervalOnly || isEdit || (!timewindow.hideLastInterval && !timewindow.hideQuickInterval)"
appearance="fill" [options]="realtimeTimewindowOptions" formControlName="realtimeType"
style="max-width: 100%">
</tb-toggle-select>
</ng-container>
<tb-timezone-select fxFlex [fxShow]="!timewindow.hideTimezone"
localBrowserTimezonePlaceholderOnEmpty="true"
formControlName="timezone"
subscriptSizing="dynamic"
appearance="outline">
</tb-timezone-select>
<ng-container *ngTemplateOutlet="timezoneSelection">
</ng-container>
</div>
<ng-container formGroupName="realtime">
<ng-container *ngIf="isEdit || !timewindow.hideLastInterval &&
timewindowForm.get('realtime.realtimeType').value === realtimeTypes.LAST_INTERVAL">
<ng-container *ngIf="timewindowForm.get('realtime.realtimeType').value === realtimeTypes.LAST_INTERVAL">
<tb-timeinterval
formControlName="timewindowMs"
subscriptSizing="dynamic"
@ -51,9 +45,9 @@
</tb-timeinterval>
</ng-container>
<ng-container *ngIf="!timewindow.hideQuickInterval &&
timewindowForm.get('realtime.realtimeType').value === realtimeTypes.INTERVAL">
<ng-container *ngIf="timewindowForm.get('realtime.realtimeType').value === realtimeTypes.INTERVAL">
<tb-quick-time-interval
displayLabel="false"
formControlName="quickInterval"
onlyCurrentInterval="true"
subscriptSizing="dynamic"
@ -69,73 +63,62 @@
</div>
</mat-tab>
<mat-tab label="{{ 'timewindow.history' | translate }}">
<section fxLayout="row">
<section *ngIf="isEdit" fxLayout="column" fxLayoutAlign="start center"
style="padding-top: 8px; padding-left: 16px;">
<label class="tb-small hide-label" translate>timewindow.hide</label>
<mat-checkbox [ngModelOptions]="{standalone: true}" [(ngModel)]="timewindow.hideInterval"
(ngModelChange)="onHideIntervalChanged()"></mat-checkbox>
</section>
<section fxLayout="column" fxFlex [fxShow]="isEdit || !timewindow.hideInterval">
<div formGroupName="history" class="mat-content mat-padding" style="padding-top: 8px;">
<mat-radio-group formControlName="historyType">
<mat-radio-button *ngIf="forAllTimeEnabled" [value]="historyTypes.FOR_ALL_TIME" color="primary">
<section fxLayout="column">
<span translate>timewindow.for-all-time</span>
</section>
</mat-radio-button>
<mat-radio-button [value]="historyTypes.LAST_INTERVAL" color="primary">
<section fxLayout="column">
<span translate>timewindow.last</span>
<div class="tb-flex column">
<section class="tb-form-panel stroked" [fxShow]="isEdit || !timewindow.hideInterval">
<div class="tb-form-panel-title">{{ 'timewindow.time-range' | translate }}</div>
<div class="tb-flex align-center space-between">
<ng-container formGroupName="history">
<tb-toggle-select appearance="fill" [options]="historyTimewindowOptions" formControlName="historyType"
style="max-width: 100%">
</tb-toggle-select>
</ng-container>
<ng-container *ngTemplateOutlet="timezoneSelection">
</ng-container>
</div>
<ng-container formGroupName="history" *ngIf="isEdit || !timewindow.hideInterval &&
timewindowForm.get('history.historyType').value !== historyTypes.FOR_ALL_TIME">
<ng-container *ngIf="timewindowForm.get('history.historyType').value === historyTypes.LAST_INTERVAL">
<tb-timeinterval
formControlName="timewindowMs"
predefinedName="timewindow.last"
class="history-time-input"
subscriptSizing="dynamic"
appearance="outline"
[fxShow]="timewindowForm.get('history.historyType').value === historyTypes.LAST_INTERVAL"
[required]="timewindow.selectedTab === timewindowTypes.HISTORY &&
timewindowForm.get('history.historyType').value === historyTypes.LAST_INTERVAL"
style="padding-top: 8px;"></tb-timeinterval>
</section>
</mat-radio-button>
<mat-radio-button [value]="historyTypes.FIXED" color="primary">
<section fxLayout="column">
<span translate>timewindow.time-period</span>
timewindowForm.get('history.historyType').value === historyTypes.LAST_INTERVAL">
</tb-timeinterval>
</ng-container>
<ng-container *ngIf="timewindowForm.get('history.historyType').value === historyTypes.FIXED">
<tb-datetime-period
formControlName="fixedTimewindow"
class="history-time-input"
[fxShow]="timewindowForm.get('history.historyType').value === historyTypes.FIXED"
[required]="timewindow.selectedTab === timewindowTypes.HISTORY &&
timewindowForm.get('history.historyType').value === historyTypes.FIXED"
style="padding-top: 8px;"></tb-datetime-period>
</section>
</mat-radio-button>
<mat-radio-button [value]="historyTypes.INTERVAL" color="primary">
<section fxLayout="column">
<span translate>timewindow.interval</span>
timewindowForm.get('history.historyType').value === historyTypes.FIXED">
</tb-datetime-period>
</ng-container>
<ng-container *ngIf="timewindowForm.get('history.historyType').value === historyTypes.INTERVAL">
<tb-quick-time-interval
displayLabel="false"
formControlName="quickInterval"
class="history-time-input"
subscriptSizing="dynamic"
appearance="outline"
[fxShow]="timewindowForm.get('history.historyType').value === historyTypes.INTERVAL"
[required]="timewindow.selectedTab === timewindowTypes.HISTORY &&
timewindowForm.get('history.historyType').value === historyTypes.INTERVAL"
style="padding-top: 8px"></tb-quick-time-interval>
</section>
</mat-radio-button>
</mat-radio-group>
</div>
</section>
timewindowForm.get('history.historyType').value === historyTypes.INTERVAL">
</tb-quick-time-interval>
</ng-container>
</ng-container>
</section>
<ng-container *ngTemplateOutlet="aggregationConfig">
</ng-container>
</div>
</mat-tab>
</mat-tab-group>
<ng-template #aggregationConfig>
<div *ngIf="aggregation" formGroupName="aggregation" class="tb-flex column">
<section class="tb-form-panel stroked" [fxShow]="isEdit || !timewindow.hideAggregation">
<div *ngIf="aggregation" class="tb-flex column">
<ng-container formGroupName="aggregation">
<section class="tb-form-panel stroked" *ngIf="isEdit || !timewindow.hideAggregation">
<div class="tb-form-panel-title">{{ 'aggregation.aggregation' | translate }}</div>
<mat-form-field subscriptSizing="dynamic" appearance="outline">
<mat-select formControlName="type" style="min-width: 150px;">
@ -154,8 +137,11 @@
<div fxLayout="row" fxLayoutAlign="start center" fxFlex>
<mat-slider fxFlex
discrete
showTickMarks
step="{{datapointsLimitSliderStep()}}"
min="{{minDatapointsLimit()}}"
max="{{maxDatapointsLimit()}}"><input matSliderThumb formControlName="limit"/>
max="{{maxDatapointsLimit()}}">
<input matSliderThumb formControlName="limit"/>
</mat-slider>
<mat-form-field class="limit-slider-value" subscriptSizing="dynamic" appearance="outline">
<input matInput formControlName="limit" type="number" step="1"
@ -166,51 +152,47 @@
</div>
</div>
</section>
</div>
<div formGroupName="realtime"
*ngIf="aggregation && timewindowForm.get('aggregation.type').value !== aggregationTypes.NONE &&
timewindow.selectedTab === timewindowTypes.REALTIME" class="mat-content mat-padding" fxLayout="column">
</ng-container>
<section class="tb-form-panel stroked" [fxShow]="(isEdit || !timewindow.hideAggInterval)
&& timewindowForm.get('aggregation.type').value !== aggregationTypes.NONE">
<div class="tb-form-panel-title">{{ 'aggregation.group-interval' | translate }}</div>
<ng-container formGroupName="realtime" *ngIf="timewindow.selectedTab === timewindowTypes.REALTIME">
<tb-timeinterval
formControlName="interval"
[isEdit]="isEdit"
[(hideFlag)]="timewindow.hideAggInterval"
(hideFlagChange)="onHideAggIntervalChanged()"
[min]="minRealtimeAggInterval()" [max]="maxRealtimeAggInterval()"
useCalendarIntervals
subscriptSizing="dynamic"
appearance="outline"
predefinedName="aggregation.group-interval">
appearance="outline">
</tb-timeinterval>
</div>
<div formGroupName="history"
*ngIf="aggregation && timewindowForm.get('aggregation.type').value !== aggregationTypes.NONE &&
timewindow.selectedTab === timewindowTypes.HISTORY" class="mat-content mat-padding" fxLayout="column">
</ng-container>
<ng-container formGroupName="history" *ngIf="timewindow.selectedTab === timewindowTypes.HISTORY">
<tb-timeinterval
formControlName="interval"
[isEdit]="isEdit"
[(hideFlag)]="timewindow.hideAggInterval"
(hideFlagChange)="onHideAggIntervalChanged()"
[min]="minHistoryAggInterval()" [max]="maxHistoryAggInterval()"
useCalendarIntervals
subscriptSizing="dynamic"
appearance="outline"
predefinedName="aggregation.group-interval">
appearance="outline">
</tb-timeinterval>
</div>
<div *ngIf="timezone" class="mat-content mat-padding" fxLayout="row">
<section fxLayout="column" fxLayoutAlign="start center" [fxShow]="isEdit">
<label class="tb-small hide-label" translate>timewindow.hide</label>
<mat-checkbox [ngModelOptions]="{standalone: true}" [(ngModel)]="timewindow.hideTimezone"
(ngModelChange)="onHideTimezoneChanged()"></mat-checkbox>
</ng-container>
</section>
<!-- <tb-timezone-select fxFlex [fxShow]="isEdit || !timewindow.hideTimezone"-->
<!-- localBrowserTimezonePlaceholderOnEmpty="true"-->
<!-- formControlName="timezone"-->
<!-- appearance="outline">-->
<!-- </tb-timezone-select>-->
</div>
</ng-template>
<ng-template #timezoneSelection>
<ng-container *ngIf="timezone && (isEdit || !timewindow.hideTimezone)">
<tb-timezone-select localBrowserTimezonePlaceholderOnEmpty="true"
formControlName="timezone"
subscriptSizing="dynamic"
appearance="outline">
</tb-timezone-select>
</ng-container>
</ng-template>
</form>
<mat-divider></mat-divider>
<div fxLayout="row" class="tb-panel-actions" fxLayoutAlign="end center">
<button type="button"
mat-button

View File

@ -22,6 +22,11 @@
max-width: 100%;
background-color: #fff;
.tb-form-panel {
padding: 12px;
gap: 12px;
}
.tb-flex {
gap: 16px;
}
@ -84,6 +89,6 @@
}
.mat-mdc-tab-body-content {
padding: 16px;
padding: 12px 16px;
}
}

View File

@ -91,11 +91,26 @@ export class TimewindowPanelComponent extends PageComponent implements OnInit {
value: this.realtimeTypes.LAST_INTERVAL
},
{
name: this.translate.instant('timewindow.interval'),
name: this.translate.instant('timewindow.relative'),
value: this.realtimeTypes.INTERVAL
}
];
historyTimewindowOptions: ToggleHeaderOption[] = [
{
name: this.translate.instant('timewindow.last'),
value: this.historyTypes.LAST_INTERVAL
},
{
name: this.translate.instant('timewindow.fixed'),
value: this.historyTypes.FIXED
},
{
name: this.translate.instant('timewindow.relative'),
value: this.historyTypes.INTERVAL
}
];
constructor(@Inject(TIMEWINDOW_PANEL_DATA) public data: TimewindowPanelData,
public overlayRef: OverlayRef,
protected store: Store<AppState>,
@ -106,6 +121,12 @@ export class TimewindowPanelComponent extends PageComponent implements OnInit {
super(store);
this.historyOnly = data.historyOnly;
this.forAllTimeEnabled = data.forAllTimeEnabled;
if (this.forAllTimeEnabled) {
this.historyTimewindowOptions.unshift({
name: this.translate.instant('timewindow.for-all-time'),
value: this.historyTypes.FOR_ALL_TIME
});
}
this.quickIntervalOnly = data.quickIntervalOnly;
this.timewindow = data.timewindow;
this.aggregation = data.aggregation;
@ -273,6 +294,11 @@ export class TimewindowPanelComponent extends PageComponent implements OnInit {
return this.timeService.getMaxDatapointsLimit();
}
// TODO: find more accurate step size for slider
datapointsLimitSliderStep() {
return Math.round(this.maxDatapointsLimit() / 10);
}
minRealtimeAggInterval() {
return this.timeService.minIntervalLimit(this.currentRealtimeTimewindow());
}

View File

@ -4695,7 +4695,9 @@
"color": "Color",
"displayTypePrefix": "Display Realtime/History prefix",
"preview": "Preview",
"time-range": "Time range"
"time-range": "Time range",
"relative": "Relative",
"fixed": "Fixed"
},
"tooltip": {
"trigger": "Trigger",