Merge pull request #9020 from rusikv/feature/timeseries-api-improvements-ui

Refactoring of delete timeseries ui
This commit is contained in:
Vladyslav 2023-08-02 17:04:49 +03:00 committed by GitHub
commit 009c4b4c70
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 118 additions and 71 deletions

View File

@ -85,20 +85,12 @@
'attribute.selected-telemetry' : 'attribute.selected-attributes') | translate:{count: dataSource.selection.selected.length} }} 'attribute.selected-telemetry' : 'attribute.selected-attributes') | translate:{count: dataSource.selection.selected.length} }}
</span> </span>
<span fxFlex></span> <span fxFlex></span>
<button [fxShow]="!isClientSideTelemetryTypeMap.get(attributeScope)" <button [fxShow]="attributeScope !== attributeScopeTypes.CLIENT_SCOPE"
class="button-widget-action" class="button-widget-action"
mat-icon-button [disabled]="isLoading$ | async" mat-icon-button [disabled]="isLoading$ | async"
matTooltip="{{ 'action.delete' | translate }}" matTooltip="{{ 'action.delete' | translate }}"
matTooltipPosition="above" matTooltipPosition="above"
(click)="deleteAttributes($event)"> (click)="deleteTelemetry($event)">
<mat-icon>delete</mat-icon>
</button>
<button [fxShow]="attributeScope === latestTelemetryTypes.LATEST_TELEMETRY"
class="button-widget-action"
mat-icon-button [disabled]="isLoading$ | async"
matTooltip="{{ 'action.delete' | translate }}"
matTooltipPosition="above"
(click)="deleteTimeseries($event)">
<mat-icon>delete</mat-icon> <mat-icon>delete</mat-icon>
</button> </button>
<button mat-raised-button color="accent" <button mat-raised-button color="accent"

View File

@ -104,6 +104,7 @@ export class AttributeTableComponent extends PageComponent implements AfterViewI
isClientSideTelemetryTypeMap = isClientSideTelemetryType; isClientSideTelemetryTypeMap = isClientSideTelemetryType;
latestTelemetryTypes = LatestTelemetry; latestTelemetryTypes = LatestTelemetry;
attributeScopeTypes = AttributeScope;
mode: 'default' | 'widget' = 'default'; mode: 'default' | 'widget' = 'default';
@ -423,29 +424,29 @@ export class AttributeTableComponent extends PageComponent implements AfterViewI
this.viewContainerRef, injector)); this.viewContainerRef, injector));
componentRef.onDestroy(() => { componentRef.onDestroy(() => {
if (componentRef.instance.result !== null) { if (componentRef.instance.result !== null) {
const strategy = componentRef.instance.result; const result = componentRef.instance.result;
const deleteTimeseries = attribute ? [attribute]: this.dataSource.selection.selected; const deleteTimeseries = attribute ? [attribute]: this.dataSource.selection.selected;
let deleteAllDataForKeys = false; let deleteAllDataForKeys = false;
let rewriteLatestIfDeleted = false; let rewriteLatestIfDeleted = false;
let startTs = null; let startTs = null;
let endTs = null; let endTs = null;
let deleteLatest = true; let deleteLatest = true;
if (strategy === TimeseriesDeleteStrategy.DELETE_ALL_DATA) { if (result.strategy === TimeseriesDeleteStrategy.DELETE_ALL_DATA) {
deleteAllDataForKeys = true; deleteAllDataForKeys = true;
} }
if (strategy === TimeseriesDeleteStrategy.DELETE_ALL_DATA_EXCEPT_LATEST_VALUE) { if (result.strategy === TimeseriesDeleteStrategy.DELETE_ALL_DATA_EXCEPT_LATEST_VALUE) {
deleteAllDataForKeys = true; deleteAllDataForKeys = true;
deleteLatest = false; deleteLatest = false;
} }
if (strategy === TimeseriesDeleteStrategy.DELETE_LATEST_VALUE) { if (result.strategy === TimeseriesDeleteStrategy.DELETE_LATEST_VALUE) {
rewriteLatestIfDeleted = componentRef.instance.rewriteLatestIfDeleted; rewriteLatestIfDeleted = result.rewriteLatest;
startTs = deleteTimeseries[0].lastUpdateTs; startTs = deleteTimeseries[0].lastUpdateTs;
endTs = startTs + 1; endTs = startTs + 1;
} }
if (strategy === TimeseriesDeleteStrategy.DELETE_ALL_DATA_FOR_TIME_PERIOD) { if (result.strategy === TimeseriesDeleteStrategy.DELETE_ALL_DATA_FOR_TIME_PERIOD) {
startTs = componentRef.instance.startDateTime.getTime(); startTs = result.startDateTime.getTime();
endTs = componentRef.instance.endDateTime.getTime(); endTs = result.endDateTime.getTime();
rewriteLatestIfDeleted = componentRef.instance.rewriteLatestIfDeleted; rewriteLatestIfDeleted = result.rewriteLatest;
} }
this.attributeService.deleteEntityTimeseries(this.entityIdValue, deleteTimeseries, deleteAllDataForKeys, this.attributeService.deleteEntityTimeseries(this.entityIdValue, deleteTimeseries, deleteAllDataForKeys,
startTs, endTs, rewriteLatestIfDeleted, deleteLatest).subscribe(() => this.reloadAttributes()); startTs, endTs, rewriteLatestIfDeleted, deleteLatest).subscribe(() => this.reloadAttributes());
@ -477,6 +478,14 @@ export class AttributeTableComponent extends PageComponent implements AfterViewI
} }
} }
deleteTelemetry($event: Event) {
if (this.attributeScope === this.latestTelemetryTypes.LATEST_TELEMETRY) {
this.deleteTimeseries($event);
} else {
this.deleteAttributes($event);
}
}
enterWidgetMode() { enterWidgetMode() {
this.mode = 'widget'; this.mode = 'widget';
this.widgetsList = []; this.widgetsList = [];

View File

@ -16,20 +16,20 @@
--> -->
<div class="mat-elevation-z1" style="max-width: 488px"> <form [formGroup]="deleteTimeseriesFormGroup" style="max-width: 488px">
<mat-toolbar> <mat-toolbar>
<h2>{{ "attribute.delete-timeseries.delete-strategy" | translate }}</h2> <h2>{{ "attribute.delete-timeseries.delete-strategy" | translate }}</h2>
<span fxFlex></span> <span fxFlex></span>
<button mat-icon-button <button mat-icon-button
(click)="cancel()" type="button"
type="button"> (click)="cancel()">
<mat-icon class="material-icons">close</mat-icon> <mat-icon class="material-icons">close</mat-icon>
</button> </button>
</mat-toolbar> </mat-toolbar>
<div style="padding: 16px; min-height: 188px"> <div style="padding: 16px; min-height: 188px">
<mat-form-field fxFlex class="mat-block"> <mat-form-field fxFlex class="mat-block">
<mat-label translate>attribute.delete-timeseries.strategy</mat-label> <mat-label translate>attribute.delete-timeseries.strategy</mat-label>
<mat-select [(ngModel)]="strategy"> <mat-select formControlName="strategy">
<mat-option *ngFor="let strategy of strategiesTranslationsMap.keys()" [value]="strategy"> <mat-option *ngFor="let strategy of strategiesTranslationsMap.keys()" [value]="strategy">
{{ strategiesTranslationsMap.get(strategy) | translate }} {{ strategiesTranslationsMap.get(strategy) | translate }}
</mat-option> </mat-option>
@ -41,24 +41,23 @@
<mat-label translate>attribute.delete-timeseries.start-time</mat-label> <mat-label translate>attribute.delete-timeseries.start-time</mat-label>
<mat-datetimepicker-toggle [for]="startDateTimePicker" matPrefix></mat-datetimepicker-toggle> <mat-datetimepicker-toggle [for]="startDateTimePicker" matPrefix></mat-datetimepicker-toggle>
<mat-datetimepicker #startDateTimePicker type="datetime" openOnFocus="true"></mat-datetimepicker> <mat-datetimepicker #startDateTimePicker type="datetime" openOnFocus="true"></mat-datetimepicker>
<input required matInput [(ngModel)]="startDateTime" [matDatetimepicker]="startDateTimePicker" <input required matInput formControlName="startDateTime" [matDatetimepicker]="startDateTimePicker">
(ngModelChange)="onStartDateTimeChange($event)">
</mat-form-field> </mat-form-field>
<mat-form-field class="mat-block"> <mat-form-field class="mat-block">
<mat-label translate>attribute.delete-timeseries.ends-on</mat-label> <mat-label translate>attribute.delete-timeseries.ends-on</mat-label>
<mat-datetimepicker-toggle [for]="endDatePicker" matPrefix></mat-datetimepicker-toggle> <mat-datetimepicker-toggle [for]="endDatePicker" matPrefix></mat-datetimepicker-toggle>
<mat-datetimepicker #endDatePicker type="datetime" openOnFocus="true"></mat-datetimepicker> <mat-datetimepicker #endDatePicker type="datetime" openOnFocus="true"></mat-datetimepicker>
<input required matInput [(ngModel)]="endDateTime" [matDatetimepicker]="endDatePicker" <input required matInput formControlName="endDateTime" [matDatetimepicker]="endDatePicker">
(ngModelChange)="onEndDateTimeChange($event)">
</mat-form-field> </mat-form-field>
</div> </div>
</div> </div>
<div *ngIf="isPeriodStrategy() || isDeleteLatestStrategy()"> <div *ngIf="isPeriodStrategy() || isDeleteLatestStrategy()">
<mat-slide-toggle [(ngModel)]="rewriteLatestIfDeleted"> <mat-slide-toggle formControlName="rewriteLatest">
{{ "attribute.delete-timeseries.rewrite-latest-value" | translate }} {{ "attribute.delete-timeseries.rewrite-latest-value" | translate }}
</mat-slide-toggle> </mat-slide-toggle>
</div> </div>
</div> </div>
</form>
<div fxLayout="row" class="tb-panel-actions"> <div fxLayout="row" class="tb-panel-actions">
<span fxFlex></span> <span fxFlex></span>
<button mat-button color="primary" <button mat-button color="primary"
@ -67,10 +66,9 @@
{{ 'action.cancel' | translate }} {{ 'action.cancel' | translate }}
</button> </button>
<button mat-button mat-raised-button color="primary" <button mat-button mat-raised-button color="primary"
type="submit" type="button"
(click)="delete()"> (click)="delete()"
[disabled]="deleteTimeseriesFormGroup.invalid">
{{ 'action.apply' | translate }} {{ 'action.apply' | translate }}
</button> </button>
</div> </div>
</div>

View File

@ -22,7 +22,7 @@
} }
:host ::ng-deep{ :host ::ng-deep{
div .mat-toolbar { form .mat-toolbar {
background: none; background: none;
} }
} }

View File

@ -14,13 +14,16 @@
/// limitations under the License. /// limitations under the License.
/// ///
import { Component, Inject, InjectionToken, OnInit } from '@angular/core'; import { Component, Inject, InjectionToken, OnDestroy, OnInit } from '@angular/core';
import { OverlayRef } from '@angular/cdk/overlay'; import { OverlayRef } from '@angular/cdk/overlay';
import { import {
TimeseriesDeleteStrategy, TimeseriesDeleteStrategy,
timeseriesDeleteStrategyTranslations timeseriesDeleteStrategyTranslations
} from '@shared/models/telemetry/telemetry.models'; } from '@shared/models/telemetry/telemetry.models';
import { MINUTE } from '@shared/models/time/time.models'; import { MINUTE } from '@shared/models/time/time.models';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
export const DELETE_TIMESERIES_PANEL_DATA = new InjectionToken<any>('DeleteTimeseriesPanelData'); export const DELETE_TIMESERIES_PANEL_DATA = new InjectionToken<any>('DeleteTimeseriesPanelData');
@ -28,22 +31,23 @@ export interface DeleteTimeseriesPanelData {
isMultipleDeletion: boolean; isMultipleDeletion: boolean;
} }
export interface DeleteTimeseriesPanelResult {
strategy: TimeseriesDeleteStrategy;
startDateTime: Date;
endDateTime: Date;
rewriteLatest: boolean;
}
@Component({ @Component({
selector: 'tb-delete-timeseries-panel', selector: 'tb-delete-timeseries-panel',
templateUrl: './delete-timeseries-panel.component.html', templateUrl: './delete-timeseries-panel.component.html',
styleUrls: ['./delete-timeseries-panel.component.scss'] styleUrls: ['./delete-timeseries-panel.component.scss']
}) })
export class DeleteTimeseriesPanelComponent implements OnInit { export class DeleteTimeseriesPanelComponent implements OnInit, OnDestroy {
strategy: string = TimeseriesDeleteStrategy.DELETE_ALL_DATA; deleteTimeseriesFormGroup: FormGroup;
result: string = null; result: DeleteTimeseriesPanelResult = null;
startDateTime: Date;
endDateTime: Date;
rewriteLatestIfDeleted: boolean = true;
strategiesTranslationsMap = timeseriesDeleteStrategyTranslations; strategiesTranslationsMap = timeseriesDeleteStrategyTranslations;
@ -52,24 +56,60 @@ export class DeleteTimeseriesPanelComponent implements OnInit {
TimeseriesDeleteStrategy.DELETE_ALL_DATA_EXCEPT_LATEST_VALUE TimeseriesDeleteStrategy.DELETE_ALL_DATA_EXCEPT_LATEST_VALUE
]; ];
private destroy$ = new Subject<void>();
constructor(@Inject(DELETE_TIMESERIES_PANEL_DATA) public data: DeleteTimeseriesPanelData, constructor(@Inject(DELETE_TIMESERIES_PANEL_DATA) public data: DeleteTimeseriesPanelData,
public overlayRef: OverlayRef) { } public overlayRef: OverlayRef,
public fb: FormBuilder) { }
ngOnInit(): void { ngOnInit(): void {
let today = new Date(); const today = new Date();
this.startDateTime = new Date(today.getFullYear(), today.getMonth() - 1, today.getDate());
this.endDateTime = today;
if (this.data.isMultipleDeletion) { if (this.data.isMultipleDeletion) {
this.strategiesTranslationsMap = new Map(Array.from(this.strategiesTranslationsMap.entries()) this.strategiesTranslationsMap = new Map(Array.from(this.strategiesTranslationsMap.entries())
.filter(([strategy]) => { .filter(([strategy]) => {
return this.multipleDeletionStrategies.includes(strategy); return this.multipleDeletionStrategies.includes(strategy);
})) }))
} }
this.deleteTimeseriesFormGroup = this.fb.group({
strategy: [TimeseriesDeleteStrategy.DELETE_ALL_DATA],
startDateTime: [
{ value: new Date(today.getFullYear(), today.getMonth() - 1, today.getDate()), disabled: true },
[Validators.required]
],
endDateTime: [{ value: today, disabled: true }, [Validators.required]],
rewriteLatest: [true]
})
this.deleteTimeseriesFormGroup.get('strategy').valueChanges.pipe(
takeUntil(this.destroy$)
).subscribe(value => {
if (value === TimeseriesDeleteStrategy.DELETE_ALL_DATA_FOR_TIME_PERIOD) {
this.deleteTimeseriesFormGroup.get('startDateTime').enable({onlySelf: true, emitEvent: false});
this.deleteTimeseriesFormGroup.get('endDateTime').enable({onlySelf: true, emitEvent: false});
} else {
this.deleteTimeseriesFormGroup.get('startDateTime').disable({onlySelf: true, emitEvent: false});
this.deleteTimeseriesFormGroup.get('endDateTime').disable({onlySelf: true, emitEvent: false});
}
})
this.deleteTimeseriesFormGroup.get('startDateTime').valueChanges.pipe(
takeUntil(this.destroy$)
).subscribe(value => this.onStartDateTimeChange(value));
this.deleteTimeseriesFormGroup.get('endDateTime').valueChanges.pipe(
takeUntil(this.destroy$)
).subscribe(value => this.onEndDateTimeChange(value));
}
ngOnDestroy(): void {
this.destroy$.next();
this.destroy$.complete();
} }
delete(): void { delete(): void {
this.result = this.strategy; if (this.deleteTimeseriesFormGroup.valid) {
this.result = this.deleteTimeseriesFormGroup.value;
this.overlayRef.dispose(); this.overlayRef.dispose();
} else {
this.deleteTimeseriesFormGroup.markAllAsTouched();
}
} }
cancel(): void { cancel(): void {
@ -77,28 +117,36 @@ export class DeleteTimeseriesPanelComponent implements OnInit {
} }
isPeriodStrategy(): boolean { isPeriodStrategy(): boolean {
return this.strategy === TimeseriesDeleteStrategy.DELETE_ALL_DATA_FOR_TIME_PERIOD; return this.deleteTimeseriesFormGroup.get('strategy').value === TimeseriesDeleteStrategy.DELETE_ALL_DATA_FOR_TIME_PERIOD;
} }
isDeleteLatestStrategy(): boolean { isDeleteLatestStrategy(): boolean {
return this.strategy === TimeseriesDeleteStrategy.DELETE_LATEST_VALUE; return this.deleteTimeseriesFormGroup.get('strategy').value === TimeseriesDeleteStrategy.DELETE_LATEST_VALUE;
} }
onStartDateTimeChange(newStartDateTime: Date) { onStartDateTimeChange(newStartDateTime: Date) {
const endDateTimeTs = this.endDateTime.getTime(); if (newStartDateTime) {
const endDateTimeTs = this.deleteTimeseriesFormGroup.get('endDateTime').value.getTime();
if (newStartDateTime.getTime() >= endDateTimeTs) { if (newStartDateTime.getTime() >= endDateTimeTs) {
this.startDateTime = new Date(endDateTimeTs - MINUTE); this.deleteTimeseriesFormGroup.get('startDateTime')
.patchValue(new Date(endDateTimeTs - MINUTE), {onlySelf: true, emitEvent: false});
} else { } else {
this.startDateTime = newStartDateTime; this.deleteTimeseriesFormGroup.get('startDateTime')
.patchValue(newStartDateTime, {onlySelf: true, emitEvent: false});
}
} }
} }
onEndDateTimeChange(newEndDateTime: Date) { onEndDateTimeChange(newEndDateTime: Date) {
const startDateTimeTs = this.startDateTime.getTime(); if (newEndDateTime) {
const startDateTimeTs = this.deleteTimeseriesFormGroup.get('startDateTime').value.getTime();
if (newEndDateTime.getTime() <= startDateTimeTs) { if (newEndDateTime.getTime() <= startDateTimeTs) {
this.endDateTime = new Date(startDateTimeTs + MINUTE); this.deleteTimeseriesFormGroup.get('endDateTime')
.patchValue(new Date(startDateTimeTs + MINUTE), {onlySelf: true, emitEvent: false});
} else { } else {
this.endDateTime = newEndDateTime; this.deleteTimeseriesFormGroup.get('endDateTime')
.patchValue(newEndDateTime, {onlySelf: true, emitEvent: false});
}
} }
} }
} }