Delete timeseries UI implementation (#8932)
This commit is contained in:
parent
4b7cc4571d
commit
2f1290e7e1
@ -50,10 +50,11 @@ export class AttributeService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public deleteEntityTimeseries(entityId: EntityId, timeseries: Array<AttributeData>, deleteAllDataForKeys = false,
|
public deleteEntityTimeseries(entityId: EntityId, timeseries: Array<AttributeData>, deleteAllDataForKeys = false,
|
||||||
startTs?: number, endTs?: number, config?: RequestConfig): Observable<any> {
|
startTs?: number, endTs?: number, rewriteLatestIfDeleted = false, deleteLatest = false,
|
||||||
|
config?: RequestConfig): Observable<any> {
|
||||||
const keys = timeseries.map(attribute => encodeURIComponent(attribute.key)).join(',');
|
const keys = timeseries.map(attribute => encodeURIComponent(attribute.key)).join(',');
|
||||||
let url = `/api/plugins/telemetry/${entityId.entityType}/${entityId.id}/timeseries/delete` +
|
let url = `/api/plugins/telemetry/${entityId.entityType}/${entityId.id}/timeseries/delete` +
|
||||||
`?keys=${keys}&deleteAllDataForKeys=${deleteAllDataForKeys}`;
|
`?keys=${keys}&deleteAllDataForKeys=${deleteAllDataForKeys}&rewriteLatestIfDeleted=${rewriteLatestIfDeleted}&deleteLatest=${deleteLatest}`;
|
||||||
if (isDefinedAndNotNull(startTs)) {
|
if (isDefinedAndNotNull(startTs)) {
|
||||||
url += `&startTs=${startTs}`;
|
url += `&startTs=${startTs}`;
|
||||||
}
|
}
|
||||||
@ -63,6 +64,12 @@ export class AttributeService {
|
|||||||
return this.http.delete(url, defaultHttpOptionsFromConfig(config));
|
return this.http.delete(url, defaultHttpOptionsFromConfig(config));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public deleteEntityLatestTimeseries(entityId: EntityId, timeseries: Array<AttributeData>, config?: RequestConfig): Observable<any> {
|
||||||
|
const keys = timeseries.map(attribute => encodeURIComponent(attribute.key)).join(',');
|
||||||
|
let url = `/api/plugins/telemetry/${entityId.entityType}/${entityId.id}/timeseries/latest/delete?keys=${keys}`;
|
||||||
|
return this.http.delete(url, defaultHttpOptionsFromConfig(config));
|
||||||
|
}
|
||||||
|
|
||||||
public saveEntityAttributes(entityId: EntityId, attributeScope: AttributeScope, attributes: Array<AttributeData>,
|
public saveEntityAttributes(entityId: EntityId, attributeScope: AttributeScope, attributes: Array<AttributeData>,
|
||||||
config?: RequestConfig): Observable<any> {
|
config?: RequestConfig): Observable<any> {
|
||||||
const attributesData: {[key: string]: any} = {};
|
const attributesData: {[key: string]: any} = {};
|
||||||
@ -103,7 +110,8 @@ export class AttributeService {
|
|||||||
});
|
});
|
||||||
let deleteEntityTimeseriesObservable: Observable<any>;
|
let deleteEntityTimeseriesObservable: Observable<any>;
|
||||||
if (deleteTimeseries.length) {
|
if (deleteTimeseries.length) {
|
||||||
deleteEntityTimeseriesObservable = this.deleteEntityTimeseries(entityId, deleteTimeseries, true, null, null, config);
|
deleteEntityTimeseriesObservable = this.deleteEntityTimeseries(entityId, deleteTimeseries, true,
|
||||||
|
null, null, false, false, config);
|
||||||
} else {
|
} else {
|
||||||
deleteEntityTimeseriesObservable = of(null);
|
deleteEntityTimeseriesObservable = of(null);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -93,6 +93,14 @@
|
|||||||
(click)="deleteAttributes($event)">
|
(click)="deleteAttributes($event)">
|
||||||
<mat-icon>delete</mat-icon>
|
<mat-icon>delete</mat-icon>
|
||||||
</button>
|
</button>
|
||||||
|
<button [fxShow]="attributeScope === latestTelemetryTypes.LATEST_TELEMETRY && dataSource.selection.selected.length > 1"
|
||||||
|
class="button-widget-action"
|
||||||
|
mat-icon-button [disabled]="isLoading$ | async"
|
||||||
|
matTooltip="{{ 'action.delete' | translate }}"
|
||||||
|
matTooltipPosition="above"
|
||||||
|
(click)="deleteTimeseries($event)">
|
||||||
|
<mat-icon>delete</mat-icon>
|
||||||
|
</button>
|
||||||
<button mat-raised-button color="accent"
|
<button mat-raised-button color="accent"
|
||||||
class="button-widget-action"
|
class="button-widget-action"
|
||||||
[disabled]="isLoading$ | async"
|
[disabled]="isLoading$ | async"
|
||||||
@ -198,6 +206,10 @@
|
|||||||
<span [fxShow]="!isClientSideTelemetryTypeMap.get(attributeScope)">
|
<span [fxShow]="!isClientSideTelemetryTypeMap.get(attributeScope)">
|
||||||
<mat-icon>edit</mat-icon>
|
<mat-icon>edit</mat-icon>
|
||||||
</span>
|
</span>
|
||||||
|
<button mat-icon-button [fxShow]="attributeScope === latestTelemetryTypes.LATEST_TELEMETRY"
|
||||||
|
(click)="deleteTimeseries($event, attribute)">
|
||||||
|
<mat-icon>delete</mat-icon>
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</mat-cell>
|
</mat-cell>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|||||||
@ -38,7 +38,7 @@ import { TranslateService } from '@ngx-translate/core';
|
|||||||
import { MatDialog } from '@angular/material/dialog';
|
import { MatDialog } from '@angular/material/dialog';
|
||||||
import { DialogService } from '@core/services/dialog.service';
|
import { DialogService } from '@core/services/dialog.service';
|
||||||
import { Direction, SortOrder } from '@shared/models/page/sort-order';
|
import { Direction, SortOrder } from '@shared/models/page/sort-order';
|
||||||
import { fromEvent, merge } from 'rxjs';
|
import { fromEvent, merge, Observable } from 'rxjs';
|
||||||
import { debounceTime, distinctUntilChanged, tap } from 'rxjs/operators';
|
import { debounceTime, distinctUntilChanged, tap } from 'rxjs/operators';
|
||||||
import { EntityId } from '@shared/models/id/entity-id';
|
import { EntityId } from '@shared/models/id/entity-id';
|
||||||
import {
|
import {
|
||||||
@ -48,7 +48,7 @@ import {
|
|||||||
isClientSideTelemetryType,
|
isClientSideTelemetryType,
|
||||||
LatestTelemetry,
|
LatestTelemetry,
|
||||||
TelemetryType,
|
TelemetryType,
|
||||||
telemetryTypeTranslations,
|
telemetryTypeTranslations, TimeseriesDeleteStrategy,
|
||||||
toTelemetryType
|
toTelemetryType
|
||||||
} from '@shared/models/telemetry/telemetry.models';
|
} from '@shared/models/telemetry/telemetry.models';
|
||||||
import { AttributeDatasource } from '@home/models/datasource/attribute-datasource';
|
import { AttributeDatasource } from '@home/models/datasource/attribute-datasource';
|
||||||
@ -82,10 +82,14 @@ import {
|
|||||||
AddWidgetToDashboardDialogComponent,
|
AddWidgetToDashboardDialogComponent,
|
||||||
AddWidgetToDashboardDialogData
|
AddWidgetToDashboardDialogData
|
||||||
} from '@home/components/attribute/add-widget-to-dashboard-dialog.component';
|
} from '@home/components/attribute/add-widget-to-dashboard-dialog.component';
|
||||||
import { deepClone } from '@core/utils';
|
import { deepClone, isUndefinedOrNull } from '@core/utils';
|
||||||
import { Filters } from '@shared/models/query/query.models';
|
import { Filters } from '@shared/models/query/query.models';
|
||||||
import { hidePageSizePixelValue } from '@shared/models/constants';
|
import { hidePageSizePixelValue } from '@shared/models/constants';
|
||||||
import { ResizeObserver } from '@juggle/resize-observer';
|
import { ResizeObserver } from '@juggle/resize-observer';
|
||||||
|
import {
|
||||||
|
DELETE_TIMESERIES_PANEL_DATA,
|
||||||
|
DeleteTimeseriesPanelComponent, DeleteTimeseriesPanelData
|
||||||
|
} from '@home/components/attribute/delete-timeseries-panel.component';
|
||||||
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
@ -378,6 +382,79 @@ export class AttributeTableComponent extends PageComponent implements AfterViewI
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
deleteTimeseries($event: Event, attribute?: AttributeData) {
|
||||||
|
if ($event) {
|
||||||
|
$event.stopPropagation();
|
||||||
|
}
|
||||||
|
const isMultipleDeletion = isUndefinedOrNull(attribute);
|
||||||
|
const target = $event.target || $event.srcElement || $event.currentTarget;
|
||||||
|
const config = new OverlayConfig();
|
||||||
|
config.backdropClass = 'cdk-overlay-transparent-backdrop';
|
||||||
|
config.hasBackdrop = true;
|
||||||
|
const connectedPosition: ConnectedPosition = {
|
||||||
|
originX: 'start',
|
||||||
|
originY: 'top',
|
||||||
|
overlayX: 'end',
|
||||||
|
overlayY: 'top'
|
||||||
|
};
|
||||||
|
config.positionStrategy = this.overlay.position().flexibleConnectedTo(target as HTMLElement)
|
||||||
|
.withPositions([connectedPosition]);
|
||||||
|
config.maxWidth = '488px';
|
||||||
|
config.width = '100%';
|
||||||
|
const overlayRef = this.overlay.create(config);
|
||||||
|
overlayRef.backdropClick().subscribe(() => {
|
||||||
|
overlayRef.dispose();
|
||||||
|
});
|
||||||
|
|
||||||
|
const providers: StaticProvider[] = [
|
||||||
|
{
|
||||||
|
provide: DELETE_TIMESERIES_PANEL_DATA,
|
||||||
|
useValue: {
|
||||||
|
isMultipleDeletion: isMultipleDeletion
|
||||||
|
} as DeleteTimeseriesPanelData
|
||||||
|
},
|
||||||
|
{
|
||||||
|
provide: OverlayRef,
|
||||||
|
useValue: overlayRef
|
||||||
|
}
|
||||||
|
];
|
||||||
|
const injector = Injector.create({parent: this.viewContainerRef.injector, providers});
|
||||||
|
const componentRef = overlayRef.attach(new ComponentPortal(DeleteTimeseriesPanelComponent,
|
||||||
|
this.viewContainerRef, injector));
|
||||||
|
componentRef.onDestroy(() => {
|
||||||
|
if (componentRef.instance.result !== null) {
|
||||||
|
const strategy = componentRef.instance.result;
|
||||||
|
const timeseries = isMultipleDeletion ? this.dataSource.selection.selected : [attribute];
|
||||||
|
let deleteAllDataForKeys = false;
|
||||||
|
let rewriteLatestIfDeleted = false;
|
||||||
|
let startTs = null;
|
||||||
|
let endTs = null;
|
||||||
|
let deleteLatest = false;
|
||||||
|
let task: Observable<any>;
|
||||||
|
if (strategy === TimeseriesDeleteStrategy.DELETE_ALL_DATA_INCLUDING_KEY) {
|
||||||
|
deleteAllDataForKeys = true;
|
||||||
|
deleteLatest = true;
|
||||||
|
}
|
||||||
|
if (strategy === TimeseriesDeleteStrategy.DELETE_OLD_DATA_EXCEPT_LATEST_VALUE) {
|
||||||
|
deleteAllDataForKeys = true;
|
||||||
|
}
|
||||||
|
if (strategy === TimeseriesDeleteStrategy.DELETE_LATEST_VALUE) {
|
||||||
|
task = this.attributeService.deleteEntityLatestTimeseries(this.entityIdValue, timeseries);
|
||||||
|
}
|
||||||
|
if (strategy === TimeseriesDeleteStrategy.DELETE_DATA_FOR_TIME_PERIOD) {
|
||||||
|
startTs = componentRef.instance.startDateTime.getTime();
|
||||||
|
endTs = componentRef.instance.endDateTime.getTime();
|
||||||
|
rewriteLatestIfDeleted = componentRef.instance.rewriteLatestIfDeleted;
|
||||||
|
}
|
||||||
|
if (!task) {
|
||||||
|
task = this.attributeService.deleteEntityTimeseries(this.entityIdValue, timeseries, deleteAllDataForKeys,
|
||||||
|
startTs, endTs, rewriteLatestIfDeleted, deleteLatest);
|
||||||
|
}
|
||||||
|
task.subscribe(() => this.reloadAttributes());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
deleteAttributes($event: Event) {
|
deleteAttributes($event: Event) {
|
||||||
if ($event) {
|
if ($event) {
|
||||||
$event.stopPropagation();
|
$event.stopPropagation();
|
||||||
|
|||||||
@ -0,0 +1,74 @@
|
|||||||
|
<!--
|
||||||
|
|
||||||
|
Copyright © 2016-2023 The Thingsboard Authors
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
|
||||||
|
-->
|
||||||
|
|
||||||
|
<div class="mat-elevation-z1" style="max-width: 488px">
|
||||||
|
<mat-toolbar>
|
||||||
|
<h2>{{ "attribute.delete-timeseries.delete-strategy" | translate }}</h2>
|
||||||
|
<span fxFlex></span>
|
||||||
|
<button mat-icon-button
|
||||||
|
(click)="cancel()"
|
||||||
|
type="button">
|
||||||
|
<mat-icon class="material-icons">close</mat-icon>
|
||||||
|
</button>
|
||||||
|
</mat-toolbar>
|
||||||
|
<div style="padding: 16px; min-height: 188px">
|
||||||
|
<mat-form-field fxFlex class="mat-block">
|
||||||
|
<mat-label translate>attribute.delete-timeseries.strategy</mat-label>
|
||||||
|
<mat-select [(ngModel)]="strategy">
|
||||||
|
<mat-option *ngFor="let strategy of strategiesTranslationsMap.keys()" [value]="strategy">
|
||||||
|
{{ strategiesTranslationsMap.get(strategy) | translate }}
|
||||||
|
</mat-option>
|
||||||
|
</mat-select>
|
||||||
|
</mat-form-field>
|
||||||
|
<div *ngIf="isPeriodStrategy()">
|
||||||
|
<div fxLayout="row" fxLayoutGap="22px" fxLayout.xs="column" fxLayoutGap.xs="8px">
|
||||||
|
<mat-form-field class="mat-block">
|
||||||
|
<mat-label translate>attribute.delete-timeseries.start-time</mat-label>
|
||||||
|
<mat-datetimepicker-toggle [for]="startDateTimePicker" matPrefix></mat-datetimepicker-toggle>
|
||||||
|
<mat-datetimepicker #startDateTimePicker type="datetime" openOnFocus="true"></mat-datetimepicker>
|
||||||
|
<input required matInput [(ngModel)]="startDateTime" [matDatetimepicker]="startDateTimePicker"
|
||||||
|
(ngModelChange)="onStartDateTimeChange($event)">
|
||||||
|
</mat-form-field>
|
||||||
|
<mat-form-field class="mat-block">
|
||||||
|
<mat-label translate>attribute.delete-timeseries.ends-on</mat-label>
|
||||||
|
<mat-datetimepicker-toggle [for]="endDatePicker" matPrefix></mat-datetimepicker-toggle>
|
||||||
|
<mat-datetimepicker #endDatePicker type="datetime" openOnFocus="true"></mat-datetimepicker>
|
||||||
|
<input required matInput [(ngModel)]="endDateTime" [matDatetimepicker]="endDatePicker"
|
||||||
|
(ngModelChange)="onEndDateTimeChange($event)">
|
||||||
|
</mat-form-field>
|
||||||
|
</div>
|
||||||
|
<mat-slide-toggle [(ngModel)]="rewriteLatestIfDeleted">
|
||||||
|
{{ "attribute.delete-timeseries.rewrite-latest-value-if-deleted" | translate }}
|
||||||
|
</mat-slide-toggle>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div fxLayout="row" class="tb-panel-actions">
|
||||||
|
<span fxFlex></span>
|
||||||
|
<button mat-button color="primary"
|
||||||
|
type="button"
|
||||||
|
(click)="cancel()" cdkFocusInitial>
|
||||||
|
{{ 'action.cancel' | translate }}
|
||||||
|
</button>
|
||||||
|
<button mat-button mat-raised-button color="primary"
|
||||||
|
type="submit"
|
||||||
|
(click)="delete()">
|
||||||
|
{{ 'action.apply' | translate }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
@ -0,0 +1,28 @@
|
|||||||
|
/**
|
||||||
|
* Copyright © 2016-2023 The Thingsboard Authors
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
:host {
|
||||||
|
width: 100%;
|
||||||
|
background-color: #fff;
|
||||||
|
box-shadow: 0px 1px 2px rgba(0, 0, 0, 0.3), 0px 2px 6px 2px rgba(0, 0, 0, 0.15);
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
:host ::ng-deep{
|
||||||
|
div .mat-toolbar {
|
||||||
|
background: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,100 @@
|
|||||||
|
///
|
||||||
|
/// Copyright © 2016-2023 The Thingsboard Authors
|
||||||
|
///
|
||||||
|
/// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
/// you may not use this file except in compliance with the License.
|
||||||
|
/// You may obtain a copy of the License at
|
||||||
|
///
|
||||||
|
/// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
///
|
||||||
|
/// Unless required by applicable law or agreed to in writing, software
|
||||||
|
/// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
/// See the License for the specific language governing permissions and
|
||||||
|
/// limitations under the License.
|
||||||
|
///
|
||||||
|
|
||||||
|
import { Component, Inject, InjectionToken, OnInit } from '@angular/core';
|
||||||
|
import { OverlayRef } from '@angular/cdk/overlay';
|
||||||
|
import {
|
||||||
|
TimeseriesDeleteStrategy,
|
||||||
|
timeseriesDeleteStrategyTranslations
|
||||||
|
} from '@shared/models/telemetry/telemetry.models';
|
||||||
|
import { MINUTE } from '@shared/models/time/time.models';
|
||||||
|
|
||||||
|
export const DELETE_TIMESERIES_PANEL_DATA = new InjectionToken<any>('DeleteTimeseriesPanelData');
|
||||||
|
|
||||||
|
export interface DeleteTimeseriesPanelData {
|
||||||
|
isMultipleDeletion: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'tb-delete-timeseries-panel',
|
||||||
|
templateUrl: './delete-timeseries-panel.component.html',
|
||||||
|
styleUrls: ['./delete-timeseries-panel.component.scss']
|
||||||
|
})
|
||||||
|
export class DeleteTimeseriesPanelComponent implements OnInit {
|
||||||
|
|
||||||
|
strategy: string = TimeseriesDeleteStrategy.DELETE_ALL_DATA_INCLUDING_KEY;
|
||||||
|
|
||||||
|
result: string = null;
|
||||||
|
|
||||||
|
startDateTime: Date;
|
||||||
|
|
||||||
|
endDateTime: Date;
|
||||||
|
|
||||||
|
rewriteLatestIfDeleted: boolean = false;
|
||||||
|
|
||||||
|
strategiesTranslationsMap = timeseriesDeleteStrategyTranslations;
|
||||||
|
|
||||||
|
multipleDeletionStrategies = [
|
||||||
|
TimeseriesDeleteStrategy.DELETE_ALL_DATA_INCLUDING_KEY,
|
||||||
|
TimeseriesDeleteStrategy.DELETE_OLD_DATA_EXCEPT_LATEST_VALUE
|
||||||
|
];
|
||||||
|
|
||||||
|
constructor(@Inject(DELETE_TIMESERIES_PANEL_DATA) public data: DeleteTimeseriesPanelData,
|
||||||
|
public overlayRef: OverlayRef) { }
|
||||||
|
|
||||||
|
ngOnInit(): void {
|
||||||
|
let today = new Date();
|
||||||
|
this.startDateTime = new Date(today.getFullYear(), today.getMonth() - 1, today.getDate());
|
||||||
|
this.endDateTime = today;
|
||||||
|
if (this.data.isMultipleDeletion) {
|
||||||
|
this.strategiesTranslationsMap = new Map(Array.from(this.strategiesTranslationsMap.entries())
|
||||||
|
.filter(([strategy]) => {
|
||||||
|
return this.multipleDeletionStrategies.includes(strategy);
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
delete(): void {
|
||||||
|
this.result = this.strategy;
|
||||||
|
this.overlayRef.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
cancel(): void {
|
||||||
|
this.overlayRef.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
isPeriodStrategy(): boolean {
|
||||||
|
return this.strategy === TimeseriesDeleteStrategy.DELETE_DATA_FOR_TIME_PERIOD;
|
||||||
|
}
|
||||||
|
|
||||||
|
onStartDateTimeChange(newStartDateTime: Date) {
|
||||||
|
const endDateTimeTs = this.endDateTime.getTime();
|
||||||
|
if (newStartDateTime.getTime() >= endDateTimeTs) {
|
||||||
|
this.startDateTime = new Date(endDateTimeTs - MINUTE);
|
||||||
|
} else {
|
||||||
|
this.startDateTime = newStartDateTime;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onEndDateTimeChange(newEndDateTime: Date) {
|
||||||
|
const startDateTimeTs = this.startDateTime.getTime();
|
||||||
|
if (newEndDateTime.getTime() <= startDateTimeTs) {
|
||||||
|
this.endDateTime = new Date(startDateTimeTs + MINUTE);
|
||||||
|
} else {
|
||||||
|
this.endDateTime = newEndDateTime;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -177,6 +177,7 @@ import {
|
|||||||
} from '@home/components/widget/action/manage-widget-actions-dialog.component';
|
} from '@home/components/widget/action/manage-widget-actions-dialog.component';
|
||||||
import { WidgetConfigComponentsModule } from '@home/components/widget/config/widget-config-components.module';
|
import { WidgetConfigComponentsModule } from '@home/components/widget/config/widget-config-components.module';
|
||||||
import { BasicWidgetConfigModule } from '@home/components/widget/config/basic/basic-widget-config.module';
|
import { BasicWidgetConfigModule } from '@home/components/widget/config/basic/basic-widget-config.module';
|
||||||
|
import { DeleteTimeseriesPanelComponent } from '@home/components/attribute/delete-timeseries-panel.component';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations:
|
declarations:
|
||||||
@ -205,6 +206,7 @@ import { BasicWidgetConfigModule } from '@home/components/widget/config/basic/ba
|
|||||||
AttributeTableComponent,
|
AttributeTableComponent,
|
||||||
AddAttributeDialogComponent,
|
AddAttributeDialogComponent,
|
||||||
EditAttributeValuePanelComponent,
|
EditAttributeValuePanelComponent,
|
||||||
|
DeleteTimeseriesPanelComponent,
|
||||||
AliasesEntitySelectPanelComponent,
|
AliasesEntitySelectPanelComponent,
|
||||||
AliasesEntitySelectComponent,
|
AliasesEntitySelectComponent,
|
||||||
AliasesEntityAutocompleteComponent,
|
AliasesEntityAutocompleteComponent,
|
||||||
|
|||||||
@ -61,6 +61,13 @@ export enum TelemetryFeature {
|
|||||||
TIMESERIES = 'TIMESERIES'
|
TIMESERIES = 'TIMESERIES'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export enum TimeseriesDeleteStrategy {
|
||||||
|
DELETE_ALL_DATA_INCLUDING_KEY = 'DELETE_ALL_DATA_INCLUDING_KEY',
|
||||||
|
DELETE_OLD_DATA_EXCEPT_LATEST_VALUE = 'DELETE_OLD_DATA_EXCEPT_LATEST_VALUE',
|
||||||
|
DELETE_LATEST_VALUE = 'DELETE_LATEST_VALUE',
|
||||||
|
DELETE_DATA_FOR_TIME_PERIOD = 'DELETE_DATA_FOR_TIME_PERIOD'
|
||||||
|
}
|
||||||
|
|
||||||
export type TelemetryType = LatestTelemetry | AttributeScope;
|
export type TelemetryType = LatestTelemetry | AttributeScope;
|
||||||
|
|
||||||
export const toTelemetryType = (val: string): TelemetryType => {
|
export const toTelemetryType = (val: string): TelemetryType => {
|
||||||
@ -73,7 +80,7 @@ export const toTelemetryType = (val: string): TelemetryType => {
|
|||||||
|
|
||||||
export const telemetryTypeTranslations = new Map<TelemetryType, string>(
|
export const telemetryTypeTranslations = new Map<TelemetryType, string>(
|
||||||
[
|
[
|
||||||
[LatestTelemetry.LATEST_TELEMETRY, 'attribute.scope-latest-telemetry'],
|
[LatestTelemetry.LATEST_TELEMETRY, 'attribute.scope-telemetry'],
|
||||||
[AttributeScope.CLIENT_SCOPE, 'attribute.scope-client'],
|
[AttributeScope.CLIENT_SCOPE, 'attribute.scope-client'],
|
||||||
[AttributeScope.SERVER_SCOPE, 'attribute.scope-server'],
|
[AttributeScope.SERVER_SCOPE, 'attribute.scope-server'],
|
||||||
[AttributeScope.SHARED_SCOPE, 'attribute.scope-shared']
|
[AttributeScope.SHARED_SCOPE, 'attribute.scope-shared']
|
||||||
@ -89,6 +96,15 @@ export const isClientSideTelemetryType = new Map<TelemetryType, boolean>(
|
|||||||
]
|
]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
export const timeseriesDeleteStrategyTranslations = new Map<TimeseriesDeleteStrategy, string>(
|
||||||
|
[
|
||||||
|
[TimeseriesDeleteStrategy.DELETE_ALL_DATA_INCLUDING_KEY, 'attribute.delete-timeseries.all-data-including-key'],
|
||||||
|
[TimeseriesDeleteStrategy.DELETE_OLD_DATA_EXCEPT_LATEST_VALUE, 'attribute.delete-timeseries.old-data-except-latest'],
|
||||||
|
[TimeseriesDeleteStrategy.DELETE_LATEST_VALUE, 'attribute.delete-timeseries.latest-value'],
|
||||||
|
[TimeseriesDeleteStrategy.DELETE_DATA_FOR_TIME_PERIOD, 'attribute.delete-timeseries.data-for-time-period']
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
export interface AttributeData {
|
export interface AttributeData {
|
||||||
lastUpdateTs?: number;
|
lastUpdateTs?: number;
|
||||||
key: string;
|
key: string;
|
||||||
|
|||||||
@ -632,7 +632,7 @@
|
|||||||
"attributes": "Atributs",
|
"attributes": "Atributs",
|
||||||
"latest-telemetry": "Última telemetria",
|
"latest-telemetry": "Última telemetria",
|
||||||
"attributes-scope": "Abast dels atributs del dispositiu",
|
"attributes-scope": "Abast dels atributs del dispositiu",
|
||||||
"scope-latest-telemetry": "Última telemetria",
|
"scope-telemetry": "Telemetria",
|
||||||
"scope-client": "Atributs del Client",
|
"scope-client": "Atributs del Client",
|
||||||
"scope-server": "Atributs del Servidor",
|
"scope-server": "Atributs del Servidor",
|
||||||
"scope-shared": "Atributs Compartits",
|
"scope-shared": "Atributs Compartits",
|
||||||
|
|||||||
@ -445,7 +445,7 @@
|
|||||||
"attributes": "Atributy",
|
"attributes": "Atributy",
|
||||||
"latest-telemetry": "Poslední telemetrie",
|
"latest-telemetry": "Poslední telemetrie",
|
||||||
"attributes-scope": "Rozsah atributů entity",
|
"attributes-scope": "Rozsah atributů entity",
|
||||||
"scope-latest-telemetry": "Poslední telemetrie",
|
"scope-telemetry": "Telemetrie",
|
||||||
"scope-client": "Atributy klienta",
|
"scope-client": "Atributy klienta",
|
||||||
"scope-server": "Atributy serveru",
|
"scope-server": "Atributy serveru",
|
||||||
"scope-shared": "Sdílené atributy",
|
"scope-shared": "Sdílené atributy",
|
||||||
|
|||||||
@ -453,7 +453,7 @@
|
|||||||
"attributes": "Attributter",
|
"attributes": "Attributter",
|
||||||
"latest-telemetry": "Seneste telemetri",
|
"latest-telemetry": "Seneste telemetri",
|
||||||
"attributes-scope": "Omfang af entitetsattributter",
|
"attributes-scope": "Omfang af entitetsattributter",
|
||||||
"scope-latest-telemetry": "Seneste telemetri",
|
"scope-telemetry": "Telemetri",
|
||||||
"scope-client": "Klientattributter",
|
"scope-client": "Klientattributter",
|
||||||
"scope-server": "Serverattributter",
|
"scope-server": "Serverattributter",
|
||||||
"scope-shared": "Delte attributter",
|
"scope-shared": "Delte attributter",
|
||||||
|
|||||||
@ -324,7 +324,7 @@
|
|||||||
"attributes": "Eigenschaften",
|
"attributes": "Eigenschaften",
|
||||||
"latest-telemetry": "Neueste Telemetrie",
|
"latest-telemetry": "Neueste Telemetrie",
|
||||||
"attributes-scope": "Entitätseigenschaftsbereich",
|
"attributes-scope": "Entitätseigenschaftsbereich",
|
||||||
"scope-latest-telemetry": "Neueste Telemetrie",
|
"scope-telemetry": "Telemetrie",
|
||||||
"scope-client": "Client Eigenschaften",
|
"scope-client": "Client Eigenschaften",
|
||||||
"scope-server": "Server Eigenschaften",
|
"scope-server": "Server Eigenschaften",
|
||||||
"scope-shared": "Gemeinsame Eigenschaften",
|
"scope-shared": "Gemeinsame Eigenschaften",
|
||||||
|
|||||||
@ -291,7 +291,7 @@
|
|||||||
"attributes": "Χαρακτηριστικά",
|
"attributes": "Χαρακτηριστικά",
|
||||||
"latest-telemetry": "Τελευταία τηλεμετρία",
|
"latest-telemetry": "Τελευταία τηλεμετρία",
|
||||||
"attributes-scope": "Πεδίο εφαρμογής Χαρακτηριστικών Οντότητας",
|
"attributes-scope": "Πεδίο εφαρμογής Χαρακτηριστικών Οντότητας",
|
||||||
"scope-latest-telemetry": "Τελευταία τηλεμετρία",
|
"scope-telemetry": "Τηλεμετρία",
|
||||||
"scope-client": "Χαρακτηριστικά Client",
|
"scope-client": "Χαρακτηριστικά Client",
|
||||||
"scope-server": "Χαρακτηριστικά Server",
|
"scope-server": "Χαρακτηριστικά Server",
|
||||||
"scope-shared": "Κοινόχρηστα Χαρακτηριστικά",
|
"scope-shared": "Κοινόχρηστα Χαρακτηριστικά",
|
||||||
|
|||||||
@ -691,7 +691,7 @@
|
|||||||
"attributes": "Attributes",
|
"attributes": "Attributes",
|
||||||
"latest-telemetry": "Latest telemetry",
|
"latest-telemetry": "Latest telemetry",
|
||||||
"attributes-scope": "Entity attributes scope",
|
"attributes-scope": "Entity attributes scope",
|
||||||
"scope-latest-telemetry": "Latest telemetry",
|
"scope-telemetry": "Telemetry",
|
||||||
"scope-client": "Client attributes",
|
"scope-client": "Client attributes",
|
||||||
"scope-server": "Server attributes",
|
"scope-server": "Server attributes",
|
||||||
"scope-shared": "Shared attributes",
|
"scope-shared": "Shared attributes",
|
||||||
@ -717,7 +717,18 @@
|
|||||||
"no-attributes-text": "No attributes found",
|
"no-attributes-text": "No attributes found",
|
||||||
"no-telemetry-text": "No telemetry found",
|
"no-telemetry-text": "No telemetry found",
|
||||||
"copy-key": "Copy key",
|
"copy-key": "Copy key",
|
||||||
"copy-value": "Copy value"
|
"copy-value": "Copy value",
|
||||||
|
"delete-timeseries": {
|
||||||
|
"start-time": "Start time",
|
||||||
|
"ends-on": "Ends on",
|
||||||
|
"strategy": "Strategy",
|
||||||
|
"delete-strategy": "Delete strategy",
|
||||||
|
"all-data-including-key": "Delete all data including key",
|
||||||
|
"old-data-except-latest": "Delete old data except latest value",
|
||||||
|
"latest-value": "Delete latest value",
|
||||||
|
"data-for-time-period": "Delete data for time period",
|
||||||
|
"rewrite-latest-value-if-deleted": "Rewrite latest value if deleted"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"api-usage": {
|
"api-usage": {
|
||||||
"api-features": "API features",
|
"api-features": "API features",
|
||||||
|
|||||||
@ -667,7 +667,7 @@
|
|||||||
"attributes": "Atributos",
|
"attributes": "Atributos",
|
||||||
"latest-telemetry": "Última telemetría",
|
"latest-telemetry": "Última telemetría",
|
||||||
"attributes-scope": "Alcance de los atributos del dispositivo",
|
"attributes-scope": "Alcance de los atributos del dispositivo",
|
||||||
"scope-latest-telemetry": "Última telemetría",
|
"scope-telemetry": "Telemetría",
|
||||||
"scope-client": "Atributos de Cliente",
|
"scope-client": "Atributos de Cliente",
|
||||||
"scope-server": "Atributos de Servidor",
|
"scope-server": "Atributos de Servidor",
|
||||||
"scope-shared": "Atributos Compartidos",
|
"scope-shared": "Atributos Compartidos",
|
||||||
|
|||||||
@ -254,7 +254,7 @@
|
|||||||
"attributes": "ويژگي ها",
|
"attributes": "ويژگي ها",
|
||||||
"latest-telemetry": "آخرين سنجش",
|
"latest-telemetry": "آخرين سنجش",
|
||||||
"attributes-scope": "حوزه ويژگي هاي موجودي",
|
"attributes-scope": "حوزه ويژگي هاي موجودي",
|
||||||
"scope-latest-telemetry": "آخرين سنجش",
|
"scope-telemetry": "تله متری",
|
||||||
"scope-client": "ويژگي هاي مشتري",
|
"scope-client": "ويژگي هاي مشتري",
|
||||||
"scope-server": "ويژگي هاي سِروِر",
|
"scope-server": "ويژگي هاي سِروِر",
|
||||||
"scope-shared": "ويژگي هاي مشترک",
|
"scope-shared": "ويژگي هاي مشترک",
|
||||||
|
|||||||
@ -459,7 +459,7 @@
|
|||||||
"next-widget": "Widget suivant",
|
"next-widget": "Widget suivant",
|
||||||
"prev-widget": "Widget précédent",
|
"prev-widget": "Widget précédent",
|
||||||
"scope-client": "Attributs du client",
|
"scope-client": "Attributs du client",
|
||||||
"scope-latest-telemetry": "Dernière télémétrie",
|
"scope-telemetry": "Télémétrie",
|
||||||
"scope-server": "Attributs du serveur",
|
"scope-server": "Attributs du serveur",
|
||||||
"scope-shared": "Attributs partagés",
|
"scope-shared": "Attributs partagés",
|
||||||
"selected-attributes": "{count, plural, =1 {1 attribut} other {# attributs} } sélectionnés",
|
"selected-attributes": "{count, plural, =1 {1 attribut} other {# attributs} } sélectionnés",
|
||||||
|
|||||||
@ -276,7 +276,7 @@
|
|||||||
"attributes": "Attributi",
|
"attributes": "Attributi",
|
||||||
"latest-telemetry": "Ultima telemetria",
|
"latest-telemetry": "Ultima telemetria",
|
||||||
"attributes-scope": "Visibilità attributi entità",
|
"attributes-scope": "Visibilità attributi entità",
|
||||||
"scope-latest-telemetry": "Ultima telemetria",
|
"scope-telemetry": "Telemetria",
|
||||||
"scope-client": "Attributi client",
|
"scope-client": "Attributi client",
|
||||||
"scope-server": "Attributi server",
|
"scope-server": "Attributi server",
|
||||||
"scope-shared": "Attributi condivisi",
|
"scope-shared": "Attributi condivisi",
|
||||||
|
|||||||
@ -244,7 +244,7 @@
|
|||||||
"attributes": "属性",
|
"attributes": "属性",
|
||||||
"latest-telemetry": "最新テレメトリ",
|
"latest-telemetry": "最新テレメトリ",
|
||||||
"attributes-scope": "エンティティ属性のスコープ",
|
"attributes-scope": "エンティティ属性のスコープ",
|
||||||
"scope-latest-telemetry": "最新テレメトリ",
|
"scope-telemetry": "テレメトリー",
|
||||||
"scope-client": "クライアントの属性",
|
"scope-client": "クライアントの属性",
|
||||||
"scope-server": "サーバーの属性",
|
"scope-server": "サーバーの属性",
|
||||||
"scope-shared": "共有属性",
|
"scope-shared": "共有属性",
|
||||||
|
|||||||
@ -290,7 +290,7 @@
|
|||||||
"attributes": "ატრიბუტები",
|
"attributes": "ატრიბუტები",
|
||||||
"latest-telemetry": "უახლესი ტელემეტრია",
|
"latest-telemetry": "უახლესი ტელემეტრია",
|
||||||
"attributes-scope": "ობიექტის ატრიბუტების ფარგლები",
|
"attributes-scope": "ობიექტის ატრიბუტების ფარგლები",
|
||||||
"scope-latest-telemetry": "უახლესი ტელემეტრია",
|
"scope-telemetry": "ტელემეტრია",
|
||||||
"scope-client": "კლიენტის ატრიბუტები",
|
"scope-client": "კლიენტის ატრიბუტები",
|
||||||
"scope-server": "სერვერის ატრიბუტები",
|
"scope-server": "სერვერის ატრიბუტები",
|
||||||
"scope-shared": "ატრიბუტების გაზიარება",
|
"scope-shared": "ატრიბუტების გაზიარება",
|
||||||
|
|||||||
@ -408,7 +408,7 @@
|
|||||||
"attributes": "속성",
|
"attributes": "속성",
|
||||||
"latest-telemetry": "최근 데이터",
|
"latest-telemetry": "최근 데이터",
|
||||||
"attributes-scope": "장치 속성 범위",
|
"attributes-scope": "장치 속성 범위",
|
||||||
"scope-latest-telemetry": "최근 데이터",
|
"scope-telemetry": "원격 측정",
|
||||||
"scope-client": "클라이언트 속성",
|
"scope-client": "클라이언트 속성",
|
||||||
"scope-server": "서버 속성",
|
"scope-server": "서버 속성",
|
||||||
"scope-shared": "공유 속성",
|
"scope-shared": "공유 속성",
|
||||||
|
|||||||
@ -256,7 +256,7 @@
|
|||||||
"attributes": "Attribūti",
|
"attributes": "Attribūti",
|
||||||
"latest-telemetry": "Jaunākā telemetrija",
|
"latest-telemetry": "Jaunākā telemetrija",
|
||||||
"attributes-scope": "Vienības atribūtu darbības joma",
|
"attributes-scope": "Vienības atribūtu darbības joma",
|
||||||
"scope-latest-telemetry": "Jaunākā telemetrija",
|
"scope-telemetry": "Telemetrija",
|
||||||
"scope-client": "Klientu atribūti",
|
"scope-client": "Klientu atribūti",
|
||||||
"scope-server": "Servera atribūti",
|
"scope-server": "Servera atribūti",
|
||||||
"scope-shared": "Dalītie atribūti",
|
"scope-shared": "Dalītie atribūti",
|
||||||
|
|||||||
@ -309,7 +309,7 @@
|
|||||||
"attributes": "Atributos",
|
"attributes": "Atributos",
|
||||||
"latest-telemetry": "Última telemetria",
|
"latest-telemetry": "Última telemetria",
|
||||||
"attributes-scope": "Escopo de atributos de entidade",
|
"attributes-scope": "Escopo de atributos de entidade",
|
||||||
"scope-latest-telemetry": "Última telemetria",
|
"scope-telemetry": "Telemetria",
|
||||||
"scope-client": "Atributos do cliente",
|
"scope-client": "Atributos do cliente",
|
||||||
"scope-server": "Atributos do servidor",
|
"scope-server": "Atributos do servidor",
|
||||||
"scope-shared": "Atributos compartilhados",
|
"scope-shared": "Atributos compartilhados",
|
||||||
|
|||||||
@ -285,7 +285,7 @@
|
|||||||
"attributes": "Atribute",
|
"attributes": "Atribute",
|
||||||
"latest-telemetry": "Ultimele Date Telemetrice",
|
"latest-telemetry": "Ultimele Date Telemetrice",
|
||||||
"attributes-scope": "Scop Atribute Entitate",
|
"attributes-scope": "Scop Atribute Entitate",
|
||||||
"scope-latest-telemetry": "Ultimele Date Telemetrice",
|
"scope-telemetry": "Telemetrie",
|
||||||
"scope-client": "Atribute Client",
|
"scope-client": "Atribute Client",
|
||||||
"scope-server": "Atribute Server",
|
"scope-server": "Atribute Server",
|
||||||
"scope-shared": "Atribute Partajate",
|
"scope-shared": "Atribute Partajate",
|
||||||
|
|||||||
@ -408,7 +408,7 @@
|
|||||||
"attributes": "Lastnosti",
|
"attributes": "Lastnosti",
|
||||||
"latest-telemetry": "Najnovejša telemetrija",
|
"latest-telemetry": "Najnovejša telemetrija",
|
||||||
"attributes-scope": "Obseg atributov entitete",
|
"attributes-scope": "Obseg atributov entitete",
|
||||||
"scope-latest-telemetry": "Najnovejša telemetrija",
|
"scope-telemetry": "Telemetrija",
|
||||||
"scope-client": "Atributi odjemalca",
|
"scope-client": "Atributi odjemalca",
|
||||||
"scope-server": "Atributi strežnika",
|
"scope-server": "Atributi strežnika",
|
||||||
"scope-shared": "Skupni atributi",
|
"scope-shared": "Skupni atributi",
|
||||||
|
|||||||
@ -445,7 +445,7 @@
|
|||||||
"attributes": "Öznitelikler",
|
"attributes": "Öznitelikler",
|
||||||
"latest-telemetry": "Son telemetri",
|
"latest-telemetry": "Son telemetri",
|
||||||
"attributes-scope": "Varlık öznitelik kapsamı",
|
"attributes-scope": "Varlık öznitelik kapsamı",
|
||||||
"scope-latest-telemetry": "Son telemetri",
|
"scope-telemetry": "telemetri",
|
||||||
"scope-client": "İstemci öznitelikler",
|
"scope-client": "İstemci öznitelikler",
|
||||||
"scope-server": "Sunucu öznitelikler",
|
"scope-server": "Sunucu öznitelikler",
|
||||||
"scope-shared": "Paylaşılan öznitelikler",
|
"scope-shared": "Paylaşılan öznitelikler",
|
||||||
|
|||||||
@ -342,7 +342,7 @@
|
|||||||
"attributes": "Атрибути",
|
"attributes": "Атрибути",
|
||||||
"latest-telemetry": "Остання телеметрія",
|
"latest-telemetry": "Остання телеметрія",
|
||||||
"attributes-scope": "Область видимості атрибутів",
|
"attributes-scope": "Область видимості атрибутів",
|
||||||
"scope-latest-telemetry": "Остання телеметрія",
|
"scope-telemetry": "Телеметрія",
|
||||||
"scope-client": "Клієнтські атрибути",
|
"scope-client": "Клієнтські атрибути",
|
||||||
"scope-server": "Серверні атрибути",
|
"scope-server": "Серверні атрибути",
|
||||||
"scope-shared": "Спільні атрибути",
|
"scope-shared": "Спільні атрибути",
|
||||||
|
|||||||
@ -590,7 +590,7 @@
|
|||||||
"attributes": "属性",
|
"attributes": "属性",
|
||||||
"latest-telemetry": "最新遥测数据",
|
"latest-telemetry": "最新遥测数据",
|
||||||
"attributes-scope": "设备属性范围",
|
"attributes-scope": "设备属性范围",
|
||||||
"scope-latest-telemetry": "最新遥测数据",
|
"scope-telemetry": "遥测",
|
||||||
"scope-client": "客户端属性",
|
"scope-client": "客户端属性",
|
||||||
"scope-server": "服务端属性",
|
"scope-server": "服务端属性",
|
||||||
"scope-shared": "共享属性",
|
"scope-shared": "共享属性",
|
||||||
|
|||||||
@ -519,7 +519,7 @@
|
|||||||
"attributes": "屬性",
|
"attributes": "屬性",
|
||||||
"latest-telemetry": "最新遙測",
|
"latest-telemetry": "最新遙測",
|
||||||
"attributes-scope": "設備屬性範圍",
|
"attributes-scope": "設備屬性範圍",
|
||||||
"scope-latest-telemetry": "最新遙測",
|
"scope-telemetry": "遙測",
|
||||||
"scope-client": "客戶端屬性",
|
"scope-client": "客戶端屬性",
|
||||||
"scope-server": "服務端屬性",
|
"scope-server": "服務端屬性",
|
||||||
"scope-shared": "共享屬性",
|
"scope-shared": "共享屬性",
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user