UI: Implement widgets config basic mode. Widgets config minor refactoring.
This commit is contained in:
parent
4ab93c8c52
commit
1fe00ac46a
@ -1,42 +0,0 @@
|
||||
<!--
|
||||
|
||||
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.
|
||||
|
||||
-->
|
||||
<ng-container [formGroup]="simpleCardWidgetConfigForm" >
|
||||
<tb-datasources
|
||||
[configMode]="basicMode"
|
||||
formControlName="datasources">
|
||||
</tb-datasources>
|
||||
<div class="tb-widget-config-panel">
|
||||
<div class="tb-widget-config-panel-title" translate>widget-config.appearance</div>
|
||||
<div class="tb-widget-config-row space-between">
|
||||
<div translate>widgets.simple-card.label-position</div>
|
||||
<mat-form-field appearance="outline" subscriptSizing="dynamic">
|
||||
<mat-select formControlName="labelPosition">
|
||||
<mat-option [value]="'left'">
|
||||
{{ 'widgets.simple-card.label-position-left' | translate }}
|
||||
</mat-option>
|
||||
<mat-option [value]="'top'">
|
||||
{{ 'widgets.simple-card.label-position-top' | translate }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
</div>
|
||||
<tb-widget-actions-panel
|
||||
formControlName="actions">
|
||||
</tb-widget-actions-panel>
|
||||
</ng-container>
|
||||
@ -1,58 +0,0 @@
|
||||
///
|
||||
/// 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 } from '@angular/core';
|
||||
import { UntypedFormBuilder, UntypedFormGroup } from '@angular/forms';
|
||||
import { Store } from '@ngrx/store';
|
||||
import { AppState } from '@core/core.state';
|
||||
import { BasicWidgetConfigComponent } from '@home/components/widget/widget-config.component.models';
|
||||
import { WidgetConfigComponentData } from '@home/models/widget-component.models';
|
||||
|
||||
@Component({
|
||||
selector: 'tb-simple-card-basic-config',
|
||||
templateUrl: './simple-card-basic-config.component.html',
|
||||
styleUrls: ['../basic-config.scss', '../../widget-config.scss']
|
||||
})
|
||||
export class SimpleCardBasicConfigComponent extends BasicWidgetConfigComponent {
|
||||
|
||||
simpleCardWidgetConfigForm: UntypedFormGroup;
|
||||
|
||||
constructor(protected store: Store<AppState>,
|
||||
private fb: UntypedFormBuilder) {
|
||||
super(store);
|
||||
}
|
||||
|
||||
protected configForm(): UntypedFormGroup {
|
||||
return this.simpleCardWidgetConfigForm;
|
||||
}
|
||||
|
||||
protected onConfigSet(configData: WidgetConfigComponentData) {
|
||||
this.simpleCardWidgetConfigForm = this.fb.group({
|
||||
datasources: [configData.config.datasources, []],
|
||||
labelPosition: [configData.config.settings?.labelPosition, []],
|
||||
actions: [configData.config.actions || {}, []]
|
||||
});
|
||||
}
|
||||
|
||||
protected prepareOutputConfig(config: any): WidgetConfigComponentData {
|
||||
this.widgetConfig.config.datasources = this.simpleCardWidgetConfigForm.value.datasources;
|
||||
this.widgetConfig.config.actions = this.simpleCardWidgetConfigForm.value.actions;
|
||||
this.widgetConfig.config.settings = this.widgetConfig.config.settings || {};
|
||||
this.widgetConfig.config.settings.labelPosition = this.simpleCardWidgetConfigForm.value.labelPosition;
|
||||
return this.widgetConfig;
|
||||
}
|
||||
|
||||
}
|
||||
@ -24,7 +24,7 @@ import {
|
||||
} from '@home/components/widget/basic-config/cards/simple-card-basic-config.component';
|
||||
import {
|
||||
WidgetActionsPanelComponent
|
||||
} from '@home/components/widget/basic-config/action/widget-actions-panel.component';
|
||||
} from '@home/components/widget/basic-config/common/widget-actions-panel.component';
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
@ -0,0 +1,86 @@
|
||||
<!--
|
||||
|
||||
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.
|
||||
|
||||
-->
|
||||
<ng-container [formGroup]="simpleCardWidgetConfigForm">
|
||||
<tb-timewindow-config-panel *ngIf="displayTimewindowConfig"
|
||||
[onlyHistoryTimewindow]="onlyHistoryTimewindow()"
|
||||
formControlName="timewindowConfig">
|
||||
</tb-timewindow-config-panel>
|
||||
<tb-datasources
|
||||
[configMode]="basicMode"
|
||||
hideDataKeyLabel
|
||||
hideDataKeyColor
|
||||
hideDataKeyUnits
|
||||
hideDataKeyDecimals
|
||||
formControlName="datasources">
|
||||
</tb-datasources>
|
||||
<div class="tb-widget-config-panel">
|
||||
<div class="tb-widget-config-panel-title" translate>widget-config.appearance</div>
|
||||
<div class="tb-widget-config-row">
|
||||
<div translate>widgets.simple-card.label</div>
|
||||
<mat-form-field fxFlex appearance="outline" subscriptSizing="dynamic">
|
||||
<input matInput formControlName="label" placeholder="{{ 'widget-config.set' | translate }}">
|
||||
</mat-form-field>
|
||||
</div>
|
||||
<div class="tb-widget-config-row space-between">
|
||||
<div translate>widgets.simple-card.label-position</div>
|
||||
<mat-form-field appearance="outline" subscriptSizing="dynamic">
|
||||
<mat-select formControlName="labelPosition">
|
||||
<mat-option [value]="'left'">
|
||||
{{ 'widgets.simple-card.label-position-left' | translate }}
|
||||
</mat-option>
|
||||
<mat-option [value]="'top'">
|
||||
{{ 'widgets.simple-card.label-position-top' | translate }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
<div class="tb-widget-config-row space-between">
|
||||
<div translate>widget-config.units-short</div>
|
||||
<mat-form-field appearance="outline" class="center" subscriptSizing="dynamic">
|
||||
<input matInput formControlName="units" placeholder="{{ 'widget-config.set' | translate }}">
|
||||
</mat-form-field>
|
||||
</div>
|
||||
<div class="tb-widget-config-row space-between">
|
||||
<div translate>widget-config.decimals-short</div>
|
||||
<mat-form-field appearance="outline" class="center number" subscriptSizing="dynamic">
|
||||
<input matInput formControlName="decimals" type="number" min="0" max="15" step="1" placeholder="{{ 'widget-config.set' | translate }}">
|
||||
</mat-form-field>
|
||||
</div>
|
||||
<div class="tb-widget-config-row space-between same-padding">
|
||||
<div>{{ 'widget-config.text-color' | translate }}</div>
|
||||
<div fxLayout="row" fxLayoutAlign="start center" fxLayoutGap="16px">
|
||||
<mat-divider vertical></mat-divider>
|
||||
<tb-color-input asBoxInput
|
||||
formControlName="color">
|
||||
</tb-color-input>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tb-widget-config-row space-between same-padding">
|
||||
<div>{{ 'widget-config.background' | translate }}</div>
|
||||
<div fxLayout="row" fxLayoutAlign="start center" fxLayoutGap="16px">
|
||||
<mat-divider vertical></mat-divider>
|
||||
<tb-color-input asBoxInput
|
||||
formControlName="backgroundColor">
|
||||
</tb-color-input>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<tb-widget-actions-panel
|
||||
formControlName="actions">
|
||||
</tb-widget-actions-panel>
|
||||
</ng-container>
|
||||
@ -0,0 +1,110 @@
|
||||
///
|
||||
/// 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 } from '@angular/core';
|
||||
import { UntypedFormBuilder, UntypedFormGroup } from '@angular/forms';
|
||||
import { Store } from '@ngrx/store';
|
||||
import { AppState } from '@core/core.state';
|
||||
import { BasicWidgetConfigComponent } from '@home/components/widget/widget-config.component.models';
|
||||
import { WidgetConfigComponentData } from '@home/models/widget-component.models';
|
||||
import {
|
||||
Datasource,
|
||||
datasourcesHasAggregation,
|
||||
datasourcesHasOnlyComparisonAggregation
|
||||
} from '@shared/models/widget.models';
|
||||
|
||||
@Component({
|
||||
selector: 'tb-simple-card-basic-config',
|
||||
templateUrl: './simple-card-basic-config.component.html',
|
||||
styleUrls: ['../basic-config.scss', '../../widget-config.scss']
|
||||
})
|
||||
export class SimpleCardBasicConfigComponent extends BasicWidgetConfigComponent {
|
||||
|
||||
public get displayTimewindowConfig(): boolean {
|
||||
const datasources = this.simpleCardWidgetConfigForm.get('datasources').value;
|
||||
return datasourcesHasAggregation(datasources);
|
||||
}
|
||||
|
||||
public onlyHistoryTimewindow(): boolean {
|
||||
const datasources = this.simpleCardWidgetConfigForm.get('datasources').value;
|
||||
return datasourcesHasOnlyComparisonAggregation(datasources);
|
||||
}
|
||||
|
||||
simpleCardWidgetConfigForm: UntypedFormGroup;
|
||||
|
||||
constructor(protected store: Store<AppState>,
|
||||
private fb: UntypedFormBuilder) {
|
||||
super(store);
|
||||
}
|
||||
|
||||
protected configForm(): UntypedFormGroup {
|
||||
return this.simpleCardWidgetConfigForm;
|
||||
}
|
||||
|
||||
protected onConfigSet(configData: WidgetConfigComponentData) {
|
||||
this.simpleCardWidgetConfigForm = this.fb.group({
|
||||
timewindowConfig: [{
|
||||
useDashboardTimewindow: configData.config.useDashboardTimewindow,
|
||||
displayTimewindow: configData.config.useDashboardTimewindow,
|
||||
timewindow: configData.config.timewindow
|
||||
}, []],
|
||||
datasources: [configData.config.datasources, []],
|
||||
label: [this.getDataKeyLabel(configData.config.datasources), []],
|
||||
labelPosition: [configData.config.settings?.labelPosition, []],
|
||||
units: [configData.config.units, []],
|
||||
decimals: [configData.config.decimals, []],
|
||||
color: [configData.config.color, []],
|
||||
backgroundColor: [configData.config.backgroundColor, []],
|
||||
actions: [configData.config.actions || {}, []]
|
||||
});
|
||||
}
|
||||
|
||||
protected prepareOutputConfig(config: any): WidgetConfigComponentData {
|
||||
this.widgetConfig.config.useDashboardTimewindow = config.timewindowConfig.useDashboardTimewindow;
|
||||
this.widgetConfig.config.displayTimewindow = config.timewindowConfig.displayTimewindow;
|
||||
this.widgetConfig.config.timewindow = config.timewindowConfig.timewindow;
|
||||
this.widgetConfig.config.datasources = config.datasources;
|
||||
this.setDataKeyLabel(config.label, this.widgetConfig.config.datasources);
|
||||
this.widgetConfig.config.actions = config.actions;
|
||||
this.widgetConfig.config.units = config.units;
|
||||
this.widgetConfig.config.decimals = config.decimals;
|
||||
this.widgetConfig.config.color = config.color;
|
||||
this.widgetConfig.config.backgroundColor = config.backgroundColor;
|
||||
this.widgetConfig.config.settings = this.widgetConfig.config.settings || {};
|
||||
this.widgetConfig.config.settings.labelPosition = config.labelPosition;
|
||||
return this.widgetConfig;
|
||||
}
|
||||
|
||||
private getDataKeyLabel(datasources?: Datasource[]): string {
|
||||
if (datasources && datasources.length) {
|
||||
const dataKeys = datasources[0].dataKeys;
|
||||
if (dataKeys && dataKeys.length) {
|
||||
return dataKeys[0].label;
|
||||
}
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
private setDataKeyLabel(label: string, datasources?: Datasource[]) {
|
||||
if (datasources && datasources.length) {
|
||||
const dataKeys = datasources[0].dataKeys;
|
||||
if (dataKeys && dataKeys.length) {
|
||||
dataKeys[0].label = label;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -40,6 +40,10 @@
|
||||
[widgetType]="data.widgetType"
|
||||
[showPostProcessing]="data.showPostProcessing"
|
||||
[callbacks]="data.callbacks"
|
||||
[hideDataKeyLabel]="data.hideDataKeyLabel"
|
||||
[hideDataKeyColor]="data.hideDataKeyColor"
|
||||
[hideDataKeyUnits]="data.hideDataKeyUnits"
|
||||
[hideDataKeyDecimals]="data.hideDataKeyDecimals"
|
||||
formControlName="dataKey">
|
||||
</tb-data-key-config>
|
||||
</div>
|
||||
@ -40,6 +40,10 @@ export interface DataKeyConfigDialogData {
|
||||
entityAliasId?: string;
|
||||
showPostProcessing?: boolean;
|
||||
callbacks?: DataKeysCallbacks;
|
||||
hideDataKeyLabel: boolean;
|
||||
hideDataKeyColor: boolean;
|
||||
hideDataKeyUnits: boolean;
|
||||
hideDataKeyDecimals: boolean;
|
||||
}
|
||||
|
||||
@Component({
|
||||
@ -40,11 +40,11 @@
|
||||
</mat-autocomplete>
|
||||
</mat-form-field>
|
||||
<div fxLayout="row" fxLayout.xs="column" fxLayoutAlign="start center" fxLayoutAlign.xs fxLayoutGap="8px">
|
||||
<mat-form-field fxFlex class="mat-block">
|
||||
<mat-form-field *ngIf="!hideDataKeyLabel" fxFlex class="mat-block">
|
||||
<mat-label translate>datakey.label</mat-label>
|
||||
<input matInput formControlName="label" required>
|
||||
</mat-form-field>
|
||||
<tb-color-input fxFlex
|
||||
<tb-color-input *ngIf="!hideDataKeyColor" fxFlex
|
||||
required
|
||||
label="{{'datakey.color' | translate}}"
|
||||
icon="format_color_fill"
|
||||
@ -53,11 +53,11 @@
|
||||
</tb-color-input>
|
||||
</div>
|
||||
<div fxLayout="row" fxLayout.xs="column" fxLayoutAlign="start center" fxLayoutAlign.xs fxLayoutGap="8px" *ngIf="modelValue.type !== dataKeyTypes.alarm">
|
||||
<mat-form-field fxFlex>
|
||||
<mat-form-field *ngIf="!hideDataKeyUnits" fxFlex>
|
||||
<mat-label translate>datakey.units</mat-label>
|
||||
<input matInput formControlName="units">
|
||||
</mat-form-field>
|
||||
<mat-form-field fxFlex>
|
||||
<mat-form-field *ngIf="!hideDataKeyDecimals" fxFlex>
|
||||
<mat-label translate>datakey.decimals</mat-label>
|
||||
<input matInput formControlName="decimals" type="number" min="0" max="15" step="1">
|
||||
</mat-form-field>
|
||||
@ -52,6 +52,7 @@ import { Dashboard } from '@shared/models/dashboard.models';
|
||||
import { IAliasController } from '@core/api/widget-api.models';
|
||||
import { aggregationTranslations, AggregationType, ComparisonDuration } from '@shared/models/time/time.models';
|
||||
import { genNextLabel } from '@core/utils';
|
||||
import { coerceBoolean } from '@shared/decorators/coercion';
|
||||
|
||||
@Component({
|
||||
selector: 'tb-data-key-config',
|
||||
@ -120,6 +121,22 @@ export class DataKeyConfigComponent extends PageComponent implements OnInit, Con
|
||||
@Input()
|
||||
showPostProcessing = true;
|
||||
|
||||
@Input()
|
||||
@coerceBoolean()
|
||||
hideDataKeyLabel = false;
|
||||
|
||||
@Input()
|
||||
@coerceBoolean()
|
||||
hideDataKeyColor = false;
|
||||
|
||||
@Input()
|
||||
@coerceBoolean()
|
||||
hideDataKeyUnits = false;
|
||||
|
||||
@Input()
|
||||
@coerceBoolean()
|
||||
hideDataKeyDecimals = false;
|
||||
|
||||
@ViewChild('keyInput') keyInput: ElementRef;
|
||||
|
||||
@ViewChild('funcBodyEdit') funcBodyEdit: JsFuncComponent;
|
||||
@ -62,16 +62,16 @@
|
||||
matTooltip="{{'datakey.timeseries' | translate }}"
|
||||
matTooltipPosition="above">timeline</mat-icon>
|
||||
</ng-container>
|
||||
<span *ngIf="key.label !== key.name">{{key.label}}</span>
|
||||
<span *ngIf="!hideDataKeyLabel && key.label !== key.name">{{key.label}}</span>
|
||||
</div>
|
||||
<div *ngIf="key.label !== key.name" class="tb-chip-separator">: </div>
|
||||
<div *ngIf="!hideDataKeyLabel && key.label !== key.name" class="tb-chip-separator">: </div>
|
||||
<div class="tb-chip-label">
|
||||
<strong>
|
||||
<ng-container *ngTemplateOutlet="keyName; context:{key: key}"></ng-container>
|
||||
</strong>
|
||||
</div>
|
||||
</div>
|
||||
<div style="padding: 3px;">
|
||||
<div *ngIf="!hideDataKeyColor" style="padding: 3px;">
|
||||
<div class="tb-color-preview small box" (click)="showColorPicker(key)">
|
||||
<div class="tb-color-result" [ngStyle]="{background: key.color}"></div>
|
||||
</div>
|
||||
@ -68,6 +68,7 @@ import { AggregationType } from '@shared/models/time/time.models';
|
||||
import { DndDropEvent } from 'ngx-drag-drop/lib/dnd-dropzone.directive';
|
||||
import { moveItemInArray } from '@angular/cdk/drag-drop';
|
||||
import { coerceBoolean } from '@shared/decorators/coercion';
|
||||
import { DatasourceComponent } from '@home/components/widget/datasource.component';
|
||||
|
||||
@Component({
|
||||
selector: 'tb-data-keys',
|
||||
@ -88,6 +89,22 @@ import { coerceBoolean } from '@shared/decorators/coercion';
|
||||
})
|
||||
export class DataKeysComponent implements ControlValueAccessor, OnInit, OnChanges, ErrorStateMatcher {
|
||||
|
||||
public get hideDataKeyLabel(): boolean {
|
||||
return this.datasourceComponent.hideDataKeyLabel;
|
||||
}
|
||||
|
||||
public get hideDataKeyColor(): boolean {
|
||||
return this.datasourceComponent.hideDataKeyColor;
|
||||
}
|
||||
|
||||
public get hideDataKeyUnits(): boolean {
|
||||
return this.datasourceComponent.hideDataKeyUnits;
|
||||
}
|
||||
|
||||
public get hideDataKeyDecimals(): boolean {
|
||||
return this.datasourceComponent.hideDataKeyDecimals;
|
||||
}
|
||||
|
||||
datasourceTypes = DatasourceType;
|
||||
widgetTypes = widgetType;
|
||||
dataKeyTypes = DataKeyType;
|
||||
@ -188,6 +205,7 @@ export class DataKeysComponent implements ControlValueAccessor, OnInit, OnChange
|
||||
|
||||
constructor(private store: Store<AppState>,
|
||||
@SkipSelf() private errorStateMatcher: ErrorStateMatcher,
|
||||
private datasourceComponent: DatasourceComponent,
|
||||
public translate: TranslateService,
|
||||
private utils: UtilsService,
|
||||
private dialogs: DialogService,
|
||||
@ -480,7 +498,11 @@ export class DataKeysComponent implements ControlValueAccessor, OnInit, OnChange
|
||||
deviceId: this.deviceId,
|
||||
entityAliasId: this.entityAliasId,
|
||||
showPostProcessing: this.widgetType !== widgetType.alarm,
|
||||
callbacks: this.callbacks
|
||||
callbacks: this.callbacks,
|
||||
hideDataKeyLabel: this.hideDataKeyLabel,
|
||||
hideDataKeyColor: this.hideDataKeyColor,
|
||||
hideDataKeyUnits: this.hideDataKeyUnits,
|
||||
hideDataKeyDecimals: this.hideDataKeyDecimals
|
||||
}
|
||||
}).afterClosed().subscribe((updatedDataKey) => {
|
||||
if (updatedDataKey) {
|
||||
@ -14,7 +14,7 @@
|
||||
/// limitations under the License.
|
||||
///
|
||||
|
||||
import { Component, forwardRef, Input, OnInit } from '@angular/core';
|
||||
import { Component, forwardRef, Input, OnInit, Optional } from '@angular/core';
|
||||
import {
|
||||
ControlValueAccessor,
|
||||
NG_VALIDATORS,
|
||||
@ -41,6 +41,7 @@ import { EntityAliasSelectCallbacks } from '@home/components/alias/entity-alias-
|
||||
import { FilterSelectCallbacks } from '@home/components/filter/filter-select.component.models';
|
||||
import { DataKeysCallbacks } from '@home/components/widget/data-keys.component.models';
|
||||
import { EntityType } from '@shared/models/entity-type.models';
|
||||
import { DatasourcesComponent } from '@home/components/widget/datasources.component';
|
||||
|
||||
@Component({
|
||||
selector: 'tb-datasource',
|
||||
@ -122,6 +123,22 @@ export class DatasourceComponent implements ControlValueAccessor, OnInit, Valida
|
||||
return this.widgetConfigComponent.widget;
|
||||
}
|
||||
|
||||
public get hideDataKeyLabel(): boolean {
|
||||
return this.datasourcesComponent?.hideDataKeyLabel;
|
||||
}
|
||||
|
||||
public get hideDataKeyColor(): boolean {
|
||||
return this.datasourcesComponent?.hideDataKeyColor;
|
||||
}
|
||||
|
||||
public get hideDataKeyUnits(): boolean {
|
||||
return this.datasourcesComponent?.hideDataKeyUnits;
|
||||
}
|
||||
|
||||
public get hideDataKeyDecimals(): boolean {
|
||||
return this.datasourcesComponent?.hideDataKeyDecimals;
|
||||
}
|
||||
|
||||
@Input()
|
||||
disabled: boolean;
|
||||
|
||||
@ -138,6 +155,8 @@ export class DatasourceComponent implements ControlValueAccessor, OnInit, Valida
|
||||
private propagateChange = (_val: any) => {};
|
||||
|
||||
constructor(private fb: UntypedFormBuilder,
|
||||
@Optional()
|
||||
private datasourcesComponent: DatasourcesComponent,
|
||||
private widgetConfigComponent: WidgetConfigComponent) {
|
||||
}
|
||||
|
||||
@ -41,6 +41,7 @@ import { DataKeyType } from '@shared/models/telemetry/telemetry.models';
|
||||
import { UtilsService } from '@core/services/utils.service';
|
||||
import { DataKeysCallbacks } from '@home/components/widget/data-keys.component.models';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { coerceBoolean } from '@shared/decorators/coercion';
|
||||
|
||||
@Component({
|
||||
selector: 'tb-datasources',
|
||||
@ -87,6 +88,22 @@ export class DatasourcesComponent implements ControlValueAccessor, OnInit, Valid
|
||||
@Input()
|
||||
disabled: boolean;
|
||||
|
||||
@Input()
|
||||
@coerceBoolean()
|
||||
hideDataKeyLabel = false;
|
||||
|
||||
@Input()
|
||||
@coerceBoolean()
|
||||
hideDataKeyColor = false;
|
||||
|
||||
@Input()
|
||||
@coerceBoolean()
|
||||
hideDataKeyUnits = false;
|
||||
|
||||
@Input()
|
||||
@coerceBoolean()
|
||||
hideDataKeyDecimals = false;
|
||||
|
||||
@Input()
|
||||
configMode: WidgetConfigMode;
|
||||
|
||||
@ -18,6 +18,7 @@ import { NgModule } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { SharedModule } from '@app/shared/shared.module';
|
||||
import { AlarmFilterConfigComponent } from '@home/components/alarm/alarm-filter-config.component';
|
||||
import { AlarmAssigneeSelectComponent } from '@home/components/alarm/alarm-assignee-select.component';
|
||||
import { DataKeysComponent } from '@home/components/widget/data-keys.component';
|
||||
import { DataKeyConfigDialogComponent } from '@home/components/widget/data-key-config-dialog.component';
|
||||
import { DataKeyConfigComponent } from '@home/components/widget/data-key-config.component';
|
||||
@ -27,10 +28,12 @@ import { EntityAliasSelectComponent } from '@home/components/alias/entity-alias-
|
||||
import { FilterSelectComponent } from '@home/components/filter/filter-select.component';
|
||||
import { WidgetSettingsModule } from '@home/components/widget/lib/settings/widget-settings.module';
|
||||
import { WidgetSettingsComponent } from '@home/components/widget/widget-settings.component';
|
||||
import { TimewindowConfigPanelComponent } from '@home/components/widget/timewindow-config-panel.component';
|
||||
|
||||
@NgModule({
|
||||
declarations:
|
||||
[
|
||||
AlarmAssigneeSelectComponent,
|
||||
AlarmFilterConfigComponent,
|
||||
DataKeysComponent,
|
||||
DataKeyConfigDialogComponent,
|
||||
@ -39,6 +42,7 @@ import { WidgetSettingsComponent } from '@home/components/widget/widget-settings
|
||||
DatasourcesComponent,
|
||||
EntityAliasSelectComponent,
|
||||
FilterSelectComponent,
|
||||
TimewindowConfigPanelComponent,
|
||||
WidgetSettingsComponent
|
||||
],
|
||||
imports: [
|
||||
@ -47,6 +51,7 @@ import { WidgetSettingsComponent } from '@home/components/widget/widget-settings
|
||||
WidgetSettingsModule
|
||||
],
|
||||
exports: [
|
||||
AlarmAssigneeSelectComponent,
|
||||
AlarmFilterConfigComponent,
|
||||
DataKeysComponent,
|
||||
DataKeyConfigDialogComponent,
|
||||
@ -55,6 +60,7 @@ import { WidgetSettingsComponent } from '@home/components/widget/widget-settings
|
||||
DatasourcesComponent,
|
||||
EntityAliasSelectComponent,
|
||||
FilterSelectComponent,
|
||||
TimewindowConfigPanelComponent,
|
||||
WidgetSettingsComponent
|
||||
]
|
||||
})
|
||||
@ -80,23 +80,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
.tb-widget-config-row {
|
||||
.mat-mdc-form-field {
|
||||
.mat-mdc-text-field-wrapper.mdc-text-field--outlined {
|
||||
padding-right: 12px;
|
||||
padding-left: 12px;
|
||||
&:not(.mdc-text-field--focused):not(.mdc-text-field--disabled):not(:hover) {
|
||||
.mdc-notched-outline__leading, .mdc-notched-outline__trailing {
|
||||
border-color: rgba(0, 0, 0, 0.12);
|
||||
}
|
||||
}
|
||||
.mat-mdc-form-field-infix {
|
||||
padding-top: 7px;
|
||||
padding-bottom: 7px;
|
||||
min-height: 38px;
|
||||
width: 72px;
|
||||
}
|
||||
}
|
||||
&.center {
|
||||
.mat-mdc-text-field-wrapper.mdc-text-field--outlined {
|
||||
.mat-mdc-form-field-infix {
|
||||
@ -119,6 +103,25 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.tb-widget-config-row {
|
||||
.mat-mdc-form-field {
|
||||
.mat-mdc-text-field-wrapper.mdc-text-field--outlined {
|
||||
padding-right: 12px;
|
||||
padding-left: 12px;
|
||||
&:not(.mdc-text-field--focused):not(.mdc-text-field--disabled):not(:hover) {
|
||||
.mdc-notched-outline__leading, .mdc-notched-outline__trailing {
|
||||
border-color: rgba(0, 0, 0, 0.12);
|
||||
}
|
||||
}
|
||||
.mat-mdc-form-field-infix {
|
||||
padding-top: 7px;
|
||||
padding-bottom: 7px;
|
||||
min-height: 38px;
|
||||
width: 72px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.tb-widget-config-panel {
|
||||
@ -16,28 +16,27 @@
|
||||
|
||||
import {
|
||||
AfterViewInit,
|
||||
Component, ComponentFactoryResolver,
|
||||
Component,
|
||||
ComponentFactoryResolver,
|
||||
ComponentRef,
|
||||
forwardRef,
|
||||
Input, OnChanges,
|
||||
Input,
|
||||
OnChanges,
|
||||
OnDestroy,
|
||||
OnInit, SimpleChanges,
|
||||
OnInit,
|
||||
SimpleChanges,
|
||||
ViewChild,
|
||||
ViewContainerRef
|
||||
} from '@angular/core';
|
||||
import { ControlValueAccessor, UntypedFormBuilder, UntypedFormGroup, NG_VALUE_ACCESSOR, Validators } from '@angular/forms';
|
||||
import {
|
||||
IRuleNodeConfigurationComponent,
|
||||
RuleNodeConfiguration,
|
||||
RuleNodeDefinition
|
||||
} from '@shared/models/rule-node.models';
|
||||
ControlValueAccessor,
|
||||
NG_VALUE_ACCESSOR,
|
||||
UntypedFormBuilder,
|
||||
UntypedFormGroup,
|
||||
Validators
|
||||
} from '@angular/forms';
|
||||
import { Subscription } from 'rxjs';
|
||||
import { RuleChainService } from '@core/http/rule-chain.service';
|
||||
import { coerceBooleanProperty } from '@angular/cdk/coercion';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { JsonObjectEditComponent } from '@shared/components/json-object-edit.component';
|
||||
import { deepClone } from '@core/utils';
|
||||
import { RuleChainType } from '@shared/models/rule-chain.models';
|
||||
import { JsonFormComponent } from '@shared/components/json-form/json-form.component';
|
||||
import { JsonFormComponentData } from '@shared/components/json-form/json-form-component.models';
|
||||
import { IWidgetSettingsComponent, Widget, WidgetSettings } from '@shared/models/widget.models';
|
||||
@ -199,31 +199,12 @@
|
||||
</div>
|
||||
</ng-template>
|
||||
<ng-template #data>
|
||||
<div *ngIf="displayTimewindowConfig" [formGroup]="dataSettings" class="tb-widget-config-panel">
|
||||
<div fxLayout="row" fxLayoutAlign="space-between center">
|
||||
<div class="tb-widget-config-panel-title" translate>timewindow.timewindow</div>
|
||||
<tb-toggle-header (valueChange)="dataSettings.get('useDashboardTimewindow').patchValue($event)" ignoreMdLgSize="true"
|
||||
[options]="[
|
||||
{ name: translate.instant('widget-config.use-dashboard-timewindow'), value: true},
|
||||
{ name: translate.instant('widget-config.use-widget-timewindow'), value: false}
|
||||
]"
|
||||
[value]="dataSettings.get('useDashboardTimewindow').value" name="useDashboardTimewindow" useSelectOnMdLg="false">
|
||||
</tb-toggle-header>
|
||||
</div>
|
||||
<div class="tb-widget-config-row">
|
||||
<tb-timewindow asButton="true"
|
||||
strokedButton
|
||||
isEdit="true"
|
||||
alwaysDisplayTypePrefix
|
||||
[historyOnly]="onlyHistoryTimewindow()"
|
||||
quickIntervalOnly="{{ widgetType === widgetTypes.latest }}"
|
||||
aggregation="{{ widgetType === widgetTypes.timeseries }}"
|
||||
formControlName="timewindow"></tb-timewindow>
|
||||
<mat-slide-toggle class="mat-slide" formControlName="displayTimewindow">
|
||||
{{ 'widget-config.display-timewindow' | translate }}
|
||||
</mat-slide-toggle>
|
||||
</div>
|
||||
</div>
|
||||
<ng-container *ngIf="displayTimewindowConfig" [formGroup]="dataSettings">
|
||||
<tb-timewindow-config-panel
|
||||
[onlyHistoryTimewindow]="onlyHistoryTimewindow()"
|
||||
formControlName="timewindowConfig">
|
||||
</tb-timewindow-config-panel>
|
||||
</ng-container>
|
||||
<div *ngIf="widgetType === widgetTypes.alarm" [formGroup]="dataSettings" class="tb-widget-config-panel" fxLayout="column" fxLayoutAlign="center">
|
||||
<tb-alarm-filter-config buttonMode="false" formControlName="alarmFilterConfig"></tb-alarm-filter-config>
|
||||
</div>
|
||||
|
||||
@ -65,7 +65,7 @@ import { Observable, of, Subscription } from 'rxjs';
|
||||
import {
|
||||
IBasicWidgetConfigComponent,
|
||||
WidgetConfigCallbacks
|
||||
} from '@home/components/widget/widget-config.component.models';
|
||||
} from '@home/components/widget/config/widget-config.component.models';
|
||||
import {
|
||||
EntityAliasDialogComponent,
|
||||
EntityAliasDialogData
|
||||
@ -80,8 +80,9 @@ import { Filter, singleEntityFilterFromDeviceId } from '@shared/models/query/que
|
||||
import { FilterDialogComponent, FilterDialogData } from '@home/components/filter/filter-dialog.component';
|
||||
import { ToggleHeaderOption } from '@shared/components/toggle-header.component';
|
||||
import { coerceBoolean } from '@shared/decorators/coercion';
|
||||
import { basicWidgetConfigComponentsMap } from '@home/components/widget/basic-config/basic-widget-config.module';
|
||||
import { basicWidgetConfigComponentsMap } from '@home/components/widget/config/basic/basic-widget-config.module';
|
||||
import Timeout = NodeJS.Timeout;
|
||||
import { TimewindowConfigData } from '@home/components/widget/timewindow-config-panel.component';
|
||||
|
||||
const emptySettingsSchema: JsonSchema = {
|
||||
type: 'object',
|
||||
@ -188,6 +189,8 @@ export class WidgetConfigComponent extends PageComponent implements OnInit, OnDe
|
||||
private advancedSettingsSubscription: Subscription;
|
||||
private actionsSettingsSubscription: Subscription;
|
||||
|
||||
private defaultConfigFormsType: widgetType;
|
||||
|
||||
constructor(protected store: Store<AppState>,
|
||||
private utils: UtilsService,
|
||||
private entityService: EntityService,
|
||||
@ -356,12 +359,11 @@ export class WidgetConfigComponent extends PageComponent implements OnInit, OnDe
|
||||
this.targetDeviceSettings = this.fb.group({});
|
||||
this.advancedSettings = this.fb.group({});
|
||||
if (this.widgetType === widgetType.timeseries || this.widgetType === widgetType.alarm || this.widgetType === widgetType.latest) {
|
||||
this.dataSettings.addControl('useDashboardTimewindow', this.fb.control(true));
|
||||
this.dataSettings.addControl('displayTimewindow', this.fb.control({value: true, disabled: true}));
|
||||
this.dataSettings.addControl('timewindow', this.fb.control({value: null, disabled: true}));
|
||||
this.dataSettings.get('useDashboardTimewindow').valueChanges.subscribe(() => {
|
||||
this.updateDataSettingsEnabledState();
|
||||
});
|
||||
this.dataSettings.addControl('timewindowConfig', this.fb.control({
|
||||
useDashboardTimewindow: true,
|
||||
displayTimewindow: true,
|
||||
timewindow: null
|
||||
}));
|
||||
if (this.widgetType === widgetType.alarm) {
|
||||
this.dataSettings.addControl('alarmFilterConfig', this.fb.control(null));
|
||||
}
|
||||
@ -396,10 +398,12 @@ export class WidgetConfigComponent extends PageComponent implements OnInit, OnDe
|
||||
|
||||
writeValue(value: WidgetConfigComponentData): void {
|
||||
this.modelValue = value;
|
||||
this.widgetType = this.modelValue?.widgetType;
|
||||
this.setupConfig();
|
||||
}
|
||||
|
||||
private setupConfig() {
|
||||
if (this.modelValue) {
|
||||
this.destroyBasicModeComponent();
|
||||
this.removeChangeSubscriptions();
|
||||
if (this.hasBasicModeDirective && this.widgetConfigMode === WidgetConfigMode.basic) {
|
||||
@ -408,6 +412,7 @@ export class WidgetConfigComponent extends PageComponent implements OnInit, OnDe
|
||||
this.setupDefaultConfig();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private setupBasicModeConfig() {
|
||||
const componentType = basicWidgetConfigComponentsMap[this.modelValue.basicModeDirective];
|
||||
@ -451,9 +456,8 @@ export class WidgetConfigComponent extends PageComponent implements OnInit, OnDe
|
||||
}
|
||||
|
||||
private setupDefaultConfig() {
|
||||
if (this.modelValue) {
|
||||
if (this.widgetType !== this.modelValue.widgetType) {
|
||||
this.widgetType = this.modelValue.widgetType;
|
||||
if (this.defaultConfigFormsType !== this.widgetType) {
|
||||
this.defaultConfigFormsType = this.widgetType;
|
||||
this.buildForms();
|
||||
}
|
||||
this.buildHeader();
|
||||
@ -498,17 +502,12 @@ export class WidgetConfigComponent extends PageComponent implements OnInit, OnDe
|
||||
if (this.widgetType === widgetType.timeseries || this.widgetType === widgetType.alarm || this.widgetType === widgetType.latest) {
|
||||
const useDashboardTimewindow = isDefined(config.useDashboardTimewindow) ?
|
||||
config.useDashboardTimewindow : true;
|
||||
this.dataSettings.patchValue(
|
||||
{ useDashboardTimewindow }, {emitEvent: false}
|
||||
);
|
||||
this.dataSettings.patchValue(
|
||||
{ displayTimewindow: isDefined(config.displayTimewindow) ?
|
||||
config.displayTimewindow : true }, {emitEvent: false}
|
||||
);
|
||||
this.dataSettings.patchValue(
|
||||
{ timewindow: config.timewindow }, {emitEvent: false}
|
||||
);
|
||||
this.updateDataSettingsEnabledState();
|
||||
this.dataSettings.get('timewindowConfig').patchValue({
|
||||
useDashboardTimewindow,
|
||||
displayTimewindow: isDefined(config.displayTimewindow) ?
|
||||
config.displayTimewindow : true,
|
||||
timewindow: config.timewindow
|
||||
}, {emitEvent: false});
|
||||
}
|
||||
if (this.modelValue.isDataEnabled) {
|
||||
if (this.widgetType !== widgetType.rpc &&
|
||||
@ -568,7 +567,6 @@ export class WidgetConfigComponent extends PageComponent implements OnInit, OnDe
|
||||
}
|
||||
this.createChangeSubscriptions();
|
||||
}
|
||||
}
|
||||
|
||||
private updateWidgetSettingsEnabledState() {
|
||||
const showTitle: boolean = this.widgetSettings.get('showTitle').value;
|
||||
@ -595,17 +593,6 @@ export class WidgetConfigComponent extends PageComponent implements OnInit, OnDe
|
||||
}
|
||||
}
|
||||
|
||||
private updateDataSettingsEnabledState() {
|
||||
const useDashboardTimewindow: boolean = this.dataSettings.get('useDashboardTimewindow').value;
|
||||
if (useDashboardTimewindow) {
|
||||
this.dataSettings.get('displayTimewindow').disable({emitEvent: false});
|
||||
this.dataSettings.get('timewindow').disable({emitEvent: false});
|
||||
} else {
|
||||
this.dataSettings.get('displayTimewindow').enable({emitEvent: false});
|
||||
this.dataSettings.get('timewindow').enable({emitEvent: false});
|
||||
}
|
||||
}
|
||||
|
||||
private updateSchemaForm(settings?: any) {
|
||||
const widgetSettingsFormData: JsonFormComponentData = {};
|
||||
if (this.modelValue.settingsSchema && this.modelValue.settingsSchema.schema) {
|
||||
@ -626,7 +613,13 @@ export class WidgetConfigComponent extends PageComponent implements OnInit, OnDe
|
||||
private updateDataSettings() {
|
||||
if (this.modelValue) {
|
||||
if (this.modelValue.config) {
|
||||
Object.assign(this.modelValue.config, this.dataSettings.value);
|
||||
let data = this.dataSettings.value;
|
||||
if (data.timewindowConfig) {
|
||||
const timewindowConfig: TimewindowConfigData = data.timewindowConfig;
|
||||
data = {...data, ...timewindowConfig};
|
||||
delete data.timewindowConfig;
|
||||
}
|
||||
Object.assign(this.modelValue.config, data);
|
||||
}
|
||||
this.propagateChange(this.modelValue);
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user