17 changed files with 1158 additions and 832 deletions
@ -0,0 +1,24 @@ |
|||||
|
<!-- |
||||
|
|
||||
|
Copyright © 2016-2022 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. |
||||
|
|
||||
|
--> |
||||
|
|
||||
|
<section [formGroup]="flotBarKeySettingsForm" fxLayout="column"> |
||||
|
<tb-flot-key-settings formControlName="flotKeySettings" |
||||
|
[aliasController]="aliasController" |
||||
|
[chartType]="'bar'"> |
||||
|
</tb-flot-key-settings> |
||||
|
</section> |
||||
@ -0,0 +1,55 @@ |
|||||
|
///
|
||||
|
/// Copyright © 2016-2022 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 { WidgetSettings, WidgetSettingsComponent } from '@shared/models/widget.models'; |
||||
|
import { FormBuilder, FormGroup, Validators } from '@angular/forms'; |
||||
|
import { Store } from '@ngrx/store'; |
||||
|
import { AppState } from '@core/core.state'; |
||||
|
import { flotDataKeyDefaultSettings } from '@home/components/widget/lib/settings/chart/flot-key-settings.component'; |
||||
|
|
||||
|
@Component({ |
||||
|
selector: 'tb-flot-bar-key-settings', |
||||
|
templateUrl: './flot-bar-key-settings.component.html', |
||||
|
styleUrls: [] |
||||
|
}) |
||||
|
export class FlotBarKeySettingsComponent extends WidgetSettingsComponent { |
||||
|
|
||||
|
flotBarKeySettingsForm: FormGroup; |
||||
|
|
||||
|
constructor(protected store: Store<AppState>, |
||||
|
private fb: FormBuilder) { |
||||
|
super(store); |
||||
|
} |
||||
|
|
||||
|
protected settingsForm(): FormGroup { |
||||
|
return this.flotBarKeySettingsForm; |
||||
|
} |
||||
|
|
||||
|
protected defaultSettings(): WidgetSettings { |
||||
|
return flotDataKeyDefaultSettings('bar'); |
||||
|
} |
||||
|
|
||||
|
protected onSettingsSet(settings: WidgetSettings) { |
||||
|
this.flotBarKeySettingsForm = this.fb.group({ |
||||
|
flotKeySettings: [settings, []] |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
protected prepareOutputSettings(settings: any): WidgetSettings { |
||||
|
return settings.flotKeySettings; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,238 @@ |
|||||
|
<!-- |
||||
|
|
||||
|
Copyright © 2016-2022 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. |
||||
|
|
||||
|
--> |
||||
|
<section class="tb-widget-settings" [formGroup]="flotKeySettingsFormGroup" fxLayout="column"> |
||||
|
<fieldset class="fields-group" fxLayout="column"> |
||||
|
<legend class="group-title" translate>widgets.chart.common-settings</legend> |
||||
|
<mat-checkbox formControlName="hideDataByDefault" style="margin-bottom: 16px;"> |
||||
|
{{ 'widgets.chart.data-is-hidden-by-default' | translate }} |
||||
|
</mat-checkbox> |
||||
|
<mat-checkbox formControlName="disableDataHiding" style="margin-bottom: 16px;"> |
||||
|
{{ 'widgets.chart.disable-data-hiding' | translate }} |
||||
|
</mat-checkbox> |
||||
|
<mat-checkbox formControlName="removeFromLegend" style="margin-bottom: 16px;"> |
||||
|
{{ 'widgets.chart.remove-from-legend' | translate }} |
||||
|
</mat-checkbox> |
||||
|
<mat-checkbox formControlName="excludeFromStacking" style="margin-bottom: 16px;"> |
||||
|
{{ 'widgets.chart.exclude-from-stacking' | translate }} |
||||
|
</mat-checkbox> |
||||
|
</fieldset> |
||||
|
<fieldset class="fields-group fields-group-slider"> |
||||
|
<legend class="group-title" translate>widgets.chart.line-settings</legend> |
||||
|
<mat-expansion-panel class="tb-settings" [expanded]="flotKeySettingsFormGroup.get('showLines').value"> |
||||
|
<mat-expansion-panel-header fxLayout="row wrap"> |
||||
|
<mat-panel-title> |
||||
|
<mat-slide-toggle formControlName="showLines" (click)="$event.stopPropagation()" |
||||
|
fxLayoutAlign="center"> |
||||
|
{{ 'widgets.chart.show-line' | translate }} |
||||
|
</mat-slide-toggle> |
||||
|
</mat-panel-title> |
||||
|
<mat-panel-description fxLayoutAlign="end center" fxHide.xs translate> |
||||
|
widget-config.advanced-settings |
||||
|
</mat-panel-description> |
||||
|
</mat-expansion-panel-header> |
||||
|
<ng-template matExpansionPanelContent> |
||||
|
<section fxFlex fxLayout="column" fxLayout.gt-sm="row" fxLayoutGap="8px"> |
||||
|
<mat-form-field fxFlex class="mat-block"> |
||||
|
<mat-label translate>widgets.chart.line-width</mat-label> |
||||
|
<input matInput type="number" min="0" formControlName="lineWidth"> |
||||
|
</mat-form-field> |
||||
|
<mat-checkbox fxFlex formControlName="fillLines" style="margin-bottom: 16px;"> |
||||
|
{{ 'widgets.chart.fill-line' | translate }} |
||||
|
</mat-checkbox> |
||||
|
</section> |
||||
|
</ng-template> |
||||
|
</mat-expansion-panel> |
||||
|
</fieldset> |
||||
|
<fieldset class="fields-group fields-group-slider"> |
||||
|
<legend class="group-title" translate>widgets.chart.points-settings</legend> |
||||
|
<mat-expansion-panel class="tb-settings" [expanded]="flotKeySettingsFormGroup.get('showPoints').value"> |
||||
|
<mat-expansion-panel-header fxLayout="row wrap"> |
||||
|
<mat-panel-title> |
||||
|
<mat-slide-toggle formControlName="showPoints" (click)="$event.stopPropagation()" |
||||
|
fxLayoutAlign="center"> |
||||
|
{{ 'widgets.chart.show-points' | translate }} |
||||
|
</mat-slide-toggle> |
||||
|
</mat-panel-title> |
||||
|
<mat-panel-description fxLayoutAlign="end center" fxHide.xs translate> |
||||
|
widget-config.advanced-settings |
||||
|
</mat-panel-description> |
||||
|
</mat-expansion-panel-header> |
||||
|
<ng-template matExpansionPanelContent> |
||||
|
<section fxLayout="column"> |
||||
|
<section fxFlex fxLayout="column" fxLayout.gt-sm="row" fxLayoutGap="8px"> |
||||
|
<mat-form-field fxFlex class="mat-block"> |
||||
|
<mat-label translate>widgets.chart.points-line-width</mat-label> |
||||
|
<input matInput type="number" min="0" formControlName="showPointsLineWidth"> |
||||
|
</mat-form-field> |
||||
|
<mat-form-field fxFlex class="mat-block"> |
||||
|
<mat-label translate>widgets.chart.points-radius</mat-label> |
||||
|
<input matInput type="number" min="0" formControlName="showPointsRadius"> |
||||
|
</mat-form-field> |
||||
|
</section> |
||||
|
<mat-form-field fxFlex class="mat-block"> |
||||
|
<mat-label translate>widgets.chart.point-shape</mat-label> |
||||
|
<mat-select formControlName="showPointShape"> |
||||
|
<mat-option [value]="'circle'"> |
||||
|
{{ 'widgets.chart.point-shape-circle' | translate }} |
||||
|
</mat-option> |
||||
|
<mat-option [value]="'cross'"> |
||||
|
{{ 'widgets.chart.point-shape-cross' | translate }} |
||||
|
</mat-option> |
||||
|
<mat-option [value]="'diamond'"> |
||||
|
{{ 'widgets.chart.point-shape-diamond' | translate }} |
||||
|
</mat-option> |
||||
|
<mat-option [value]="'square'"> |
||||
|
{{ 'widgets.chart.point-shape-square' | translate }} |
||||
|
</mat-option> |
||||
|
<mat-option [value]="'triangle'"> |
||||
|
{{ 'widgets.chart.point-shape-triangle' | translate }} |
||||
|
</mat-option> |
||||
|
<mat-option [value]="'custom'"> |
||||
|
{{ 'widgets.chart.point-shape-custom' | translate }} |
||||
|
</mat-option> |
||||
|
</mat-select> |
||||
|
</mat-form-field> |
||||
|
<tb-js-func [fxShow]="flotKeySettingsFormGroup.get('showPointShape').value === 'custom'" |
||||
|
formControlName="pointShapeFormatter" |
||||
|
[globalVariables]="functionScopeVariables" |
||||
|
[functionArgs]="['ctx', 'x', 'y', 'radius', 'shadow']" |
||||
|
functionTitle="{{ 'widgets.chart.point-shape-draw-function' | translate }}" |
||||
|
helpId="widget/lib/flot/point_shape_format_fn"> |
||||
|
</tb-js-func> |
||||
|
</section> |
||||
|
</ng-template> |
||||
|
</mat-expansion-panel> |
||||
|
</fieldset> |
||||
|
<fieldset class="fields-group"> |
||||
|
<legend class="group-title" translate>widgets.chart.tooltip-settings</legend> |
||||
|
<tb-js-func |
||||
|
formControlName="tooltipValueFormatter" |
||||
|
[globalVariables]="functionScopeVariables" |
||||
|
[functionArgs]="['value']" |
||||
|
functionTitle="{{ 'widgets.chart.tooltip-value-format-function' | translate }}" |
||||
|
helpId="widget/lib/flot/tooltip_value_format_fn"> |
||||
|
</tb-js-func> |
||||
|
</fieldset> |
||||
|
<fieldset class="fields-group"> |
||||
|
<legend class="group-title" translate>widgets.chart.yaxis-settings</legend> |
||||
|
<mat-slide-toggle formControlName="showSeparateAxis" class="slide-block"> |
||||
|
{{ 'widgets.chart.show-separate-axis' | translate }} |
||||
|
</mat-slide-toggle> |
||||
|
<mat-form-field fxFlex class="mat-block"> |
||||
|
<mat-label translate>widgets.chart.axis-title</mat-label> |
||||
|
<input matInput formControlName="axisTitle"> |
||||
|
</mat-form-field> |
||||
|
<section fxLayout="column" fxLayout.gt-sm="row" fxLayoutGap="8px"> |
||||
|
<mat-form-field fxFlex class="mat-block"> |
||||
|
<mat-label translate>widgets.chart.min-scale-value</mat-label> |
||||
|
<input matInput type="number" formControlName="axisMin"> |
||||
|
</mat-form-field> |
||||
|
<mat-form-field fxFlex class="mat-block"> |
||||
|
<mat-label translate>widgets.chart.max-scale-value</mat-label> |
||||
|
<input matInput type="number" formControlName="axisMax"> |
||||
|
</mat-form-field> |
||||
|
</section> |
||||
|
<mat-form-field fxFlex class="mat-block"> |
||||
|
<mat-label translate>widgets.chart.axis-position</mat-label> |
||||
|
<mat-select formControlName="axisPosition"> |
||||
|
<mat-option [value]="'left'"> |
||||
|
{{ 'widgets.chart.axis-position-left' | translate }} |
||||
|
</mat-option> |
||||
|
<mat-option [value]="'right'"> |
||||
|
{{ 'widgets.chart.axis-position-right' | translate }} |
||||
|
</mat-option> |
||||
|
</mat-select> |
||||
|
</mat-form-field> |
||||
|
<fieldset class="fields-group"> |
||||
|
<legend class="group-title" translate>widgets.chart.yaxis-tick-labels-settings</legend> |
||||
|
<section fxLayout="column" fxLayout.gt-sm="row" fxLayoutGap="8px"> |
||||
|
<mat-form-field fxFlex class="mat-block"> |
||||
|
<mat-label translate>widgets.chart.tick-step-size</mat-label> |
||||
|
<input matInput type="number" formControlName="axisTickSize"> |
||||
|
</mat-form-field> |
||||
|
<mat-form-field fxFlex class="mat-block"> |
||||
|
<mat-label translate>widgets.chart.number-of-decimals</mat-label> |
||||
|
<input matInput type="number" min="0" formControlName="axisTickDecimals"> |
||||
|
</mat-form-field> |
||||
|
</section> |
||||
|
<tb-js-func |
||||
|
formControlName="axisTicksFormatter" |
||||
|
[globalVariables]="functionScopeVariables" |
||||
|
[functionArgs]="['value']" |
||||
|
functionTitle="{{ 'widgets.chart.ticks-formatter-function' | translate }}" |
||||
|
helpId="widget/lib/flot/ticks_formatter_fn"> |
||||
|
</tb-js-func> |
||||
|
</fieldset> |
||||
|
</fieldset> |
||||
|
<fieldset class="fields-group"> |
||||
|
<legend class="group-title" translate>widgets.chart.thresholds</legend> |
||||
|
<div fxLayout="column"> |
||||
|
<div class="tb-control-list tb-drop-list" cdkDropList cdkDropListOrientation="vertical" |
||||
|
(cdkDropListDropped)="thresholdDrop($event)"> |
||||
|
<div cdkDrag class="tb-draggable" *ngFor="let thresholdControl of thresholdsFormArray().controls; trackBy: trackByThreshold; |
||||
|
let $index = index; last as isLast;" |
||||
|
fxLayout="column" [ngStyle]="!isLast ? {paddingBottom: '8px'} : {}"> |
||||
|
<tb-flot-threshold [formControl]="thresholdControl" |
||||
|
[expanded]="thresholdControl.new" |
||||
|
[aliasController]="aliasController" |
||||
|
(removeThreshold)="removeThreshold($index)"> |
||||
|
</tb-flot-threshold> |
||||
|
</div> |
||||
|
</div> |
||||
|
<div *ngIf="!thresholdsFormArray().controls.length"> |
||||
|
<span translate fxLayoutAlign="center center" |
||||
|
class="tb-prompt">widgets.chart.no-thresholds</span> |
||||
|
</div> |
||||
|
<div style="padding-top: 16px;"> |
||||
|
<button mat-raised-button color="primary" |
||||
|
type="button" |
||||
|
(click)="addThreshold()"> |
||||
|
<span translate>widgets.chart.add-threshold</span> |
||||
|
</button> |
||||
|
</div> |
||||
|
</div> |
||||
|
</fieldset> |
||||
|
<fieldset class="fields-group fields-group-slider" formGroupName="comparisonSettings" > |
||||
|
<legend class="group-title" translate>widgets.chart.comparison-settings</legend> |
||||
|
<mat-expansion-panel class="tb-settings" [expanded]="flotKeySettingsFormGroup.get('comparisonSettings.showValuesForComparison').value"> |
||||
|
<mat-expansion-panel-header fxLayout="row wrap"> |
||||
|
<mat-panel-title> |
||||
|
<mat-slide-toggle formControlName="showValuesForComparison" (click)="$event.stopPropagation()" |
||||
|
fxLayoutAlign="center"> |
||||
|
{{ 'widgets.chart.show-values-for-comparison' | translate }} |
||||
|
</mat-slide-toggle> |
||||
|
</mat-panel-title> |
||||
|
<mat-panel-description fxLayoutAlign="end center" fxHide.xs translate> |
||||
|
widget-config.advanced-settings |
||||
|
</mat-panel-description> |
||||
|
</mat-expansion-panel-header> |
||||
|
<ng-template matExpansionPanelContent> |
||||
|
<section fxFlex fxLayout="column" fxLayout.gt-sm="row" fxLayoutGap="8px"> |
||||
|
<mat-form-field fxFlex class="mat-block"> |
||||
|
<mat-label translate>widgets.chart.comparison-values-label</mat-label> |
||||
|
<input matInput formControlName="comparisonValuesLabel"> |
||||
|
</mat-form-field> |
||||
|
<tb-color-input fxFlex |
||||
|
formControlName="color" |
||||
|
label="{{ 'widgets.chart.color' | translate }}" openOnInput colorClearButton> |
||||
|
</tb-color-input> |
||||
|
</section> |
||||
|
</ng-template> |
||||
|
</mat-expansion-panel> |
||||
|
</fieldset> |
||||
|
</section> |
||||
@ -0,0 +1,333 @@ |
|||||
|
///
|
||||
|
/// Copyright © 2016-2022 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, forwardRef, Input, OnInit } from '@angular/core'; |
||||
|
import { |
||||
|
AbstractControl, |
||||
|
ControlValueAccessor, |
||||
|
FormArray, |
||||
|
FormBuilder, |
||||
|
FormControl, |
||||
|
FormGroup, |
||||
|
NG_VALIDATORS, |
||||
|
NG_VALUE_ACCESSOR, |
||||
|
Validator, |
||||
|
Validators |
||||
|
} from '@angular/forms'; |
||||
|
import { PageComponent } from '@shared/components/page.component'; |
||||
|
import { ChartType, TbFlotKeySettings, TbFlotKeyThreshold } from '@home/components/widget/lib/flot-widget.models'; |
||||
|
import { Store } from '@ngrx/store'; |
||||
|
import { AppState } from '@core/core.state'; |
||||
|
import { TranslateService } from '@ngx-translate/core'; |
||||
|
import { WidgetService } from '@core/http/widget.service'; |
||||
|
import { CdkDragDrop } from '@angular/cdk/drag-drop'; |
||||
|
import { IAliasController } from 'src/app/core/api/widget-api.models'; |
||||
|
|
||||
|
export function flotDataKeyDefaultSettings(chartType: ChartType): TbFlotKeySettings { |
||||
|
const settings: TbFlotKeySettings = { |
||||
|
// Common settings
|
||||
|
hideDataByDefault: false, |
||||
|
disableDataHiding: false, |
||||
|
removeFromLegend: false, |
||||
|
excludeFromStacking: false, |
||||
|
|
||||
|
// Line settings
|
||||
|
showLines: chartType === 'graph', |
||||
|
lineWidth: 1, |
||||
|
fillLines: false, |
||||
|
|
||||
|
// Points settings
|
||||
|
showPoints: false, |
||||
|
showPointsLineWidth: 5, |
||||
|
showPointsRadius: 3, |
||||
|
showPointShape: 'circle', |
||||
|
pointShapeFormatter: 'var size = radius * Math.sqrt(Math.PI) / 2;\n' + |
||||
|
'ctx.moveTo(x - size, y - size);\n' + |
||||
|
'ctx.lineTo(x + size, y + size);\n' + |
||||
|
'ctx.moveTo(x - size, y + size);\n' + |
||||
|
'ctx.lineTo(x + size, y - size);', |
||||
|
|
||||
|
// Tooltip settings
|
||||
|
tooltipValueFormatter: '', |
||||
|
|
||||
|
// Y axis settings
|
||||
|
showSeparateAxis: false, |
||||
|
axisTitle: '', |
||||
|
axisMin: null, |
||||
|
axisMax: null, |
||||
|
axisPosition: 'left', |
||||
|
|
||||
|
// --> Y axis tick labels settings
|
||||
|
axisTickSize: null, |
||||
|
axisTickDecimals: null, |
||||
|
axisTicksFormatter: '', |
||||
|
|
||||
|
// Thresholds
|
||||
|
thresholds: [], |
||||
|
|
||||
|
// Comparison settings
|
||||
|
comparisonSettings: { |
||||
|
showValuesForComparison: true, |
||||
|
comparisonValuesLabel: '', |
||||
|
color: '' |
||||
|
} |
||||
|
}; |
||||
|
return settings; |
||||
|
} |
||||
|
|
||||
|
@Component({ |
||||
|
selector: 'tb-flot-key-settings', |
||||
|
templateUrl: './flot-key-settings.component.html', |
||||
|
styleUrls: ['./../widget-settings.scss'], |
||||
|
providers: [ |
||||
|
{ |
||||
|
provide: NG_VALUE_ACCESSOR, |
||||
|
useExisting: forwardRef(() => FlotKeySettingsComponent), |
||||
|
multi: true |
||||
|
}, |
||||
|
{ |
||||
|
provide: NG_VALIDATORS, |
||||
|
useExisting: forwardRef(() => FlotKeySettingsComponent), |
||||
|
multi: true, |
||||
|
} |
||||
|
] |
||||
|
}) |
||||
|
export class FlotKeySettingsComponent extends PageComponent implements OnInit, ControlValueAccessor, Validator { |
||||
|
|
||||
|
@Input() |
||||
|
disabled: boolean; |
||||
|
|
||||
|
@Input() |
||||
|
chartType: ChartType; |
||||
|
|
||||
|
@Input() |
||||
|
aliasController: IAliasController; |
||||
|
|
||||
|
functionScopeVariables = this.widgetService.getWidgetScopeVariables(); |
||||
|
|
||||
|
private modelValue: TbFlotKeySettings; |
||||
|
|
||||
|
private propagateChange = null; |
||||
|
|
||||
|
public flotKeySettingsFormGroup: FormGroup; |
||||
|
|
||||
|
constructor(protected store: Store<AppState>, |
||||
|
private translate: TranslateService, |
||||
|
private widgetService: WidgetService, |
||||
|
private fb: FormBuilder) { |
||||
|
super(store); |
||||
|
} |
||||
|
|
||||
|
ngOnInit(): void { |
||||
|
this.flotKeySettingsFormGroup = this.fb.group({ |
||||
|
|
||||
|
// Common settings
|
||||
|
|
||||
|
hideDataByDefault: [false, []], |
||||
|
disableDataHiding: [false, []], |
||||
|
removeFromLegend: [false, []], |
||||
|
excludeFromStacking: [false, []], |
||||
|
|
||||
|
// Line settings
|
||||
|
|
||||
|
showLines: [this.chartType === 'graph', []], |
||||
|
lineWidth: [1, [Validators.min(0)]], |
||||
|
fillLines: [false, []], |
||||
|
|
||||
|
// Points settings
|
||||
|
|
||||
|
showPoints: [false, []], |
||||
|
showPointsLineWidth: [5, [Validators.min(0)]], |
||||
|
showPointsRadius: [3, [Validators.min(0)]], |
||||
|
showPointShape: ['circle', []], |
||||
|
pointShapeFormatter: ['', []], |
||||
|
|
||||
|
// Tooltip settings
|
||||
|
|
||||
|
tooltipValueFormatter: ['', []], |
||||
|
|
||||
|
// Y axis settings
|
||||
|
|
||||
|
showSeparateAxis: [false, []], |
||||
|
axisTitle: [null, []], |
||||
|
axisMin: [null, []], |
||||
|
axisMax: [null, []], |
||||
|
axisPosition: ['left', []], |
||||
|
|
||||
|
// --> Y axis tick labels settings
|
||||
|
|
||||
|
axisTickSize: [null, [Validators.min(0)]], |
||||
|
axisTickDecimals: [null, [Validators.min(0)]], |
||||
|
axisTicksFormatter: ['', []], |
||||
|
|
||||
|
// Thresholds
|
||||
|
|
||||
|
thresholds: this.fb.array([]), |
||||
|
|
||||
|
// Comparison settings
|
||||
|
|
||||
|
comparisonSettings: this.fb.group({ |
||||
|
showValuesForComparison: [true, []], |
||||
|
comparisonValuesLabel: ['', []], |
||||
|
color: ['', []] |
||||
|
}) |
||||
|
|
||||
|
}); |
||||
|
|
||||
|
this.flotKeySettingsFormGroup.get('showLines').valueChanges.subscribe(() => { |
||||
|
this.updateValidators(true); |
||||
|
}); |
||||
|
|
||||
|
this.flotKeySettingsFormGroup.get('showPoints').valueChanges.subscribe(() => { |
||||
|
this.updateValidators(true); |
||||
|
}); |
||||
|
|
||||
|
this.flotKeySettingsFormGroup.get('comparisonSettings.showValuesForComparison').valueChanges.subscribe(() => { |
||||
|
this.updateValidators(true); |
||||
|
}); |
||||
|
|
||||
|
this.flotKeySettingsFormGroup.valueChanges.subscribe(() => { |
||||
|
this.updateModel(); |
||||
|
}); |
||||
|
|
||||
|
this.updateValidators(false); |
||||
|
} |
||||
|
|
||||
|
registerOnChange(fn: any): void { |
||||
|
this.propagateChange = fn; |
||||
|
} |
||||
|
|
||||
|
registerOnTouched(fn: any): void { |
||||
|
} |
||||
|
|
||||
|
setDisabledState(isDisabled: boolean): void { |
||||
|
this.disabled = isDisabled; |
||||
|
if (isDisabled) { |
||||
|
this.flotKeySettingsFormGroup.disable({emitEvent: false}); |
||||
|
} else { |
||||
|
this.flotKeySettingsFormGroup.enable({emitEvent: false}); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
writeValue(value: TbFlotKeySettings): void { |
||||
|
const thresholds = value?.thresholds; |
||||
|
this.modelValue = value; |
||||
|
this.flotKeySettingsFormGroup.patchValue( |
||||
|
value, {emitEvent: false} |
||||
|
); |
||||
|
const thresholdsControls: Array<AbstractControl> = []; |
||||
|
if (thresholds && thresholds.length) { |
||||
|
thresholds.forEach((threshold) => { |
||||
|
thresholdsControls.push(this.fb.control(threshold, [])); |
||||
|
}); |
||||
|
} |
||||
|
this.flotKeySettingsFormGroup.setControl('thresholds', this.fb.array(thresholdsControls), {emitEvent: false}); |
||||
|
this.updateValidators(false); |
||||
|
} |
||||
|
|
||||
|
validate(c: FormControl) { |
||||
|
return (this.flotKeySettingsFormGroup.valid) ? null : { |
||||
|
flotKeySettings: { |
||||
|
valid: false, |
||||
|
}, |
||||
|
}; |
||||
|
} |
||||
|
|
||||
|
private updateModel() { |
||||
|
const value: TbFlotKeySettings = this.flotKeySettingsFormGroup.value; |
||||
|
this.modelValue = value; |
||||
|
this.propagateChange(this.modelValue); |
||||
|
} |
||||
|
|
||||
|
private updateValidators(emitEvent?: boolean): void { |
||||
|
const showLines: boolean = this.flotKeySettingsFormGroup.get('showLines').value; |
||||
|
const showPoints: boolean = this.flotKeySettingsFormGroup.get('showPoints').value; |
||||
|
const showValuesForComparison: boolean = this.flotKeySettingsFormGroup.get('comparisonSettings.showValuesForComparison').value; |
||||
|
|
||||
|
if (showLines) { |
||||
|
this.flotKeySettingsFormGroup.get('lineWidth').enable({emitEvent}); |
||||
|
this.flotKeySettingsFormGroup.get('fillLines').enable({emitEvent}); |
||||
|
} else { |
||||
|
this.flotKeySettingsFormGroup.get('lineWidth').disable({emitEvent}); |
||||
|
this.flotKeySettingsFormGroup.get('fillLines').disable({emitEvent}); |
||||
|
} |
||||
|
|
||||
|
if (showPoints) { |
||||
|
this.flotKeySettingsFormGroup.get('showPointsLineWidth').enable({emitEvent}); |
||||
|
this.flotKeySettingsFormGroup.get('showPointsRadius').enable({emitEvent}); |
||||
|
this.flotKeySettingsFormGroup.get('showPointShape').enable({emitEvent}); |
||||
|
this.flotKeySettingsFormGroup.get('pointShapeFormatter').enable({emitEvent}); |
||||
|
} else { |
||||
|
this.flotKeySettingsFormGroup.get('showPointsLineWidth').disable({emitEvent}); |
||||
|
this.flotKeySettingsFormGroup.get('showPointsRadius').disable({emitEvent}); |
||||
|
this.flotKeySettingsFormGroup.get('showPointShape').disable({emitEvent}); |
||||
|
this.flotKeySettingsFormGroup.get('pointShapeFormatter').disable({emitEvent}); |
||||
|
} |
||||
|
|
||||
|
if (showValuesForComparison) { |
||||
|
this.flotKeySettingsFormGroup.get('comparisonSettings.comparisonValuesLabel').enable({emitEvent}); |
||||
|
this.flotKeySettingsFormGroup.get('comparisonSettings.color').enable({emitEvent}); |
||||
|
} else { |
||||
|
this.flotKeySettingsFormGroup.get('comparisonSettings.comparisonValuesLabel').disable({emitEvent}); |
||||
|
this.flotKeySettingsFormGroup.get('comparisonSettings.color').disable({emitEvent}); |
||||
|
} |
||||
|
|
||||
|
this.flotKeySettingsFormGroup.get('lineWidth').updateValueAndValidity({emitEvent: false}); |
||||
|
this.flotKeySettingsFormGroup.get('fillLines').updateValueAndValidity({emitEvent: false}); |
||||
|
this.flotKeySettingsFormGroup.get('showPointsLineWidth').updateValueAndValidity({emitEvent: false}); |
||||
|
this.flotKeySettingsFormGroup.get('showPointsRadius').updateValueAndValidity({emitEvent: false}); |
||||
|
this.flotKeySettingsFormGroup.get('showPointShape').updateValueAndValidity({emitEvent: false}); |
||||
|
this.flotKeySettingsFormGroup.get('pointShapeFormatter').updateValueAndValidity({emitEvent: false}); |
||||
|
this.flotKeySettingsFormGroup.get('comparisonSettings.comparisonValuesLabel').updateValueAndValidity({emitEvent: false}); |
||||
|
this.flotKeySettingsFormGroup.get('comparisonSettings.color').updateValueAndValidity({emitEvent: false}); |
||||
|
} |
||||
|
|
||||
|
thresholdsFormArray(): FormArray { |
||||
|
return this.flotKeySettingsFormGroup.get('thresholds') as FormArray; |
||||
|
} |
||||
|
|
||||
|
public trackByThreshold(index: number, thresholdControl: AbstractControl): any { |
||||
|
return thresholdControl; |
||||
|
} |
||||
|
|
||||
|
public removeThreshold(index: number) { |
||||
|
(this.flotKeySettingsFormGroup.get('thresholds') as FormArray).removeAt(index); |
||||
|
} |
||||
|
|
||||
|
public addThreshold() { |
||||
|
const threshold: TbFlotKeyThreshold = { |
||||
|
thresholdValueSource: 'predefinedValue', |
||||
|
thresholdEntityAlias: null, |
||||
|
thresholdAttribute: null, |
||||
|
thresholdValue: null, |
||||
|
lineWidth: null, |
||||
|
color: null |
||||
|
}; |
||||
|
const thresholdsArray = this.flotKeySettingsFormGroup.get('thresholds') as FormArray; |
||||
|
const thresholdControl = this.fb.control(threshold, []); |
||||
|
(thresholdControl as any).new = true; |
||||
|
thresholdsArray.push(thresholdControl); |
||||
|
this.flotKeySettingsFormGroup.updateValueAndValidity(); |
||||
|
} |
||||
|
|
||||
|
thresholdDrop(event: CdkDragDrop<string[]>) { |
||||
|
const thresholdsArray = this.flotKeySettingsFormGroup.get('thresholds') as FormArray; |
||||
|
const threshold = thresholdsArray.at(event.previousIndex); |
||||
|
thresholdsArray.removeAt(event.previousIndex); |
||||
|
thresholdsArray.insert(event.currentIndex, threshold); |
||||
|
} |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,47 @@ |
|||||
|
<!-- |
||||
|
|
||||
|
Copyright © 2016-2022 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. |
||||
|
|
||||
|
--> |
||||
|
<section class="tb-widget-settings" [formGroup]="flotLatestKeySettingsForm" fxLayout="column"> |
||||
|
<fieldset class="fields-group fields-group-slider"> |
||||
|
<legend class="group-title" translate>widgets.chart.threshold-settings</legend> |
||||
|
<mat-expansion-panel class="tb-settings" [expanded]="flotLatestKeySettingsForm.get('useAsThreshold').value"> |
||||
|
<mat-expansion-panel-header fxLayout="row wrap"> |
||||
|
<mat-panel-title> |
||||
|
<mat-slide-toggle formControlName="useAsThreshold" (click)="$event.stopPropagation()" |
||||
|
fxLayoutAlign="center"> |
||||
|
{{ 'widgets.chart.use-as-threshold' | translate }} |
||||
|
</mat-slide-toggle> |
||||
|
</mat-panel-title> |
||||
|
<mat-panel-description fxLayoutAlign="end center" fxHide.xs translate> |
||||
|
widget-config.advanced-settings |
||||
|
</mat-panel-description> |
||||
|
</mat-expansion-panel-header> |
||||
|
<ng-template matExpansionPanelContent> |
||||
|
<section fxLayout="column" fxLayout.gt-sm="row" fxLayoutGap="8px"> |
||||
|
<mat-form-field fxFlex class="mat-block"> |
||||
|
<mat-label translate>widgets.chart.threshold-line-width</mat-label> |
||||
|
<input type="number" min="0" matInput formControlName="thresholdLineWidth"> |
||||
|
</mat-form-field> |
||||
|
<tb-color-input fxFlex |
||||
|
formControlName="thresholdColor" |
||||
|
label="{{ 'widgets.chart.threshold-color' | translate }}" openOnInput colorClearButton> |
||||
|
</tb-color-input> |
||||
|
</section> |
||||
|
</ng-template> |
||||
|
</mat-expansion-panel> |
||||
|
</fieldset> |
||||
|
</section> |
||||
@ -0,0 +1,74 @@ |
|||||
|
///
|
||||
|
/// Copyright © 2016-2022 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 { WidgetSettings, WidgetSettingsComponent } from '@shared/models/widget.models'; |
||||
|
import { FormBuilder, FormGroup, Validators } from '@angular/forms'; |
||||
|
import { Store } from '@ngrx/store'; |
||||
|
import { AppState } from '@core/core.state'; |
||||
|
|
||||
|
@Component({ |
||||
|
selector: 'tb-flot-latest-key-settings', |
||||
|
templateUrl: './flot-latest-key-settings.component.html', |
||||
|
styleUrls: ['./../widget-settings.scss'] |
||||
|
}) |
||||
|
export class FlotLatestKeySettingsComponent extends WidgetSettingsComponent { |
||||
|
|
||||
|
flotLatestKeySettingsForm: FormGroup; |
||||
|
|
||||
|
constructor(protected store: Store<AppState>, |
||||
|
private fb: FormBuilder) { |
||||
|
super(store); |
||||
|
} |
||||
|
|
||||
|
protected settingsForm(): FormGroup { |
||||
|
return this.flotLatestKeySettingsForm; |
||||
|
} |
||||
|
|
||||
|
protected defaultSettings(): WidgetSettings { |
||||
|
return { |
||||
|
useAsThreshold: false, |
||||
|
thresholdLineWidth: null, |
||||
|
thresholdColor: null |
||||
|
}; |
||||
|
} |
||||
|
|
||||
|
protected onSettingsSet(settings: WidgetSettings) { |
||||
|
this.flotLatestKeySettingsForm = this.fb.group({ |
||||
|
useAsThreshold: [settings.useAsThreshold, []], |
||||
|
thresholdLineWidth: [settings.thresholdLineWidth, [Validators.min(0)]], |
||||
|
thresholdColor: [settings.thresholdColor, []] |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
protected validatorTriggers(): string[] { |
||||
|
return ['useAsThreshold']; |
||||
|
} |
||||
|
|
||||
|
protected updateValidators(emitEvent: boolean) { |
||||
|
const useAsThreshold: boolean = this.flotLatestKeySettingsForm.get('useAsThreshold').value; |
||||
|
if (useAsThreshold) { |
||||
|
this.flotLatestKeySettingsForm.get('thresholdLineWidth').enable(); |
||||
|
this.flotLatestKeySettingsForm.get('thresholdColor').enable(); |
||||
|
} else { |
||||
|
this.flotLatestKeySettingsForm.get('thresholdLineWidth').disable(); |
||||
|
this.flotLatestKeySettingsForm.get('thresholdColor').disable(); |
||||
|
} |
||||
|
this.flotLatestKeySettingsForm.get('thresholdLineWidth').updateValueAndValidity({emitEvent}); |
||||
|
this.flotLatestKeySettingsForm.get('thresholdColor').updateValueAndValidity({emitEvent}); |
||||
|
} |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,24 @@ |
|||||
|
<!-- |
||||
|
|
||||
|
Copyright © 2016-2022 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. |
||||
|
|
||||
|
--> |
||||
|
|
||||
|
<section [formGroup]="flotLineKeySettingsForm" fxLayout="column"> |
||||
|
<tb-flot-key-settings formControlName="flotKeySettings" |
||||
|
[aliasController]="aliasController" |
||||
|
[chartType]="'graph'"> |
||||
|
</tb-flot-key-settings> |
||||
|
</section> |
||||
@ -0,0 +1,55 @@ |
|||||
|
///
|
||||
|
/// Copyright © 2016-2022 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 { WidgetSettings, WidgetSettingsComponent } from '@shared/models/widget.models'; |
||||
|
import { FormBuilder, FormGroup, Validators } from '@angular/forms'; |
||||
|
import { Store } from '@ngrx/store'; |
||||
|
import { AppState } from '@core/core.state'; |
||||
|
import { flotDataKeyDefaultSettings } from '@home/components/widget/lib/settings/chart/flot-key-settings.component'; |
||||
|
|
||||
|
@Component({ |
||||
|
selector: 'tb-flot-line-key-settings', |
||||
|
templateUrl: './flot-line-key-settings.component.html', |
||||
|
styleUrls: [] |
||||
|
}) |
||||
|
export class FlotLineKeySettingsComponent extends WidgetSettingsComponent { |
||||
|
|
||||
|
flotLineKeySettingsForm: FormGroup; |
||||
|
|
||||
|
constructor(protected store: Store<AppState>, |
||||
|
private fb: FormBuilder) { |
||||
|
super(store); |
||||
|
} |
||||
|
|
||||
|
protected settingsForm(): FormGroup { |
||||
|
return this.flotLineKeySettingsForm; |
||||
|
} |
||||
|
|
||||
|
protected defaultSettings(): WidgetSettings { |
||||
|
return flotDataKeyDefaultSettings('graph'); |
||||
|
} |
||||
|
|
||||
|
protected onSettingsSet(settings: WidgetSettings) { |
||||
|
this.flotLineKeySettingsForm = this.fb.group({ |
||||
|
flotKeySettings: [settings, []] |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
protected prepareOutputSettings(settings: any): WidgetSettings { |
||||
|
return settings.flotKeySettings; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,57 @@ |
|||||
|
<!-- |
||||
|
|
||||
|
Copyright © 2016-2022 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. |
||||
|
|
||||
|
--> |
||||
|
<mat-expansion-panel class="flot-threshold" fxFlex [formGroup]="thresholdFormGroup" [(expanded)]="expanded"> |
||||
|
<mat-expansion-panel-header> |
||||
|
<div fxFlex fxLayout="row" fxLayoutAlign="start center"> |
||||
|
<mat-panel-title> |
||||
|
<div fxLayout="row" fxFlex fxLayoutAlign="start center"> |
||||
|
<div>{{ thresholdText() }}</div> |
||||
|
<div class="tb-color-preview" style="margin-left: 6px;"> |
||||
|
<div class="tb-color-result" [ngStyle]="{background: thresholdFormGroup.get('color').value}"></div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</mat-panel-title> |
||||
|
<span fxFlex></span> |
||||
|
<button *ngIf="!disabled" mat-icon-button style="min-width: 40px;" |
||||
|
type="button" |
||||
|
(click)="removeThreshold.emit()" |
||||
|
matTooltip="{{ 'action.remove' | translate }}" |
||||
|
matTooltipPosition="above"> |
||||
|
<mat-icon>delete</mat-icon> |
||||
|
</button> |
||||
|
</div> |
||||
|
</mat-expansion-panel-header> |
||||
|
<ng-template matExpansionPanelContent> |
||||
|
<div fxLayout="column" fxLayoutGap="0.5em"> |
||||
|
<mat-divider></mat-divider> |
||||
|
<section class="tb-widget-settings" fxLayout="column"> |
||||
|
<tb-value-source [aliasController]="aliasController" formControlName="valueSource"></tb-value-source> |
||||
|
<section fxLayout="column" fxLayout.gt-sm="row" fxLayoutGap="8px"> |
||||
|
<mat-form-field fxFlex class="mat-block"> |
||||
|
<mat-label translate>widgets.chart.line-width</mat-label> |
||||
|
<input type="number" min="0" matInput formControlName="lineWidth"> |
||||
|
</mat-form-field> |
||||
|
<tb-color-input fxFlex |
||||
|
formControlName="color" |
||||
|
label="{{ 'widgets.chart.color' | translate }}" openOnInput colorClearButton> |
||||
|
</tb-color-input> |
||||
|
</section> |
||||
|
</section> |
||||
|
</div> |
||||
|
</ng-template> |
||||
|
</mat-expansion-panel> |
||||
@ -0,0 +1,40 @@ |
|||||
|
/** |
||||
|
* Copyright © 2016-2022 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 { |
||||
|
display: block; |
||||
|
.mat-expansion-panel { |
||||
|
box-shadow: none; |
||||
|
&.flot-threshold { |
||||
|
border: 1px groove rgba(0, 0, 0, .25); |
||||
|
.mat-expansion-panel-header { |
||||
|
padding: 0 24px 0 8px; |
||||
|
&.mat-expanded { |
||||
|
height: 48px; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
:host ::ng-deep { |
||||
|
.mat-expansion-panel { |
||||
|
&.flot-threshold { |
||||
|
.mat-expansion-panel-body { |
||||
|
padding: 0 8px 8px; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,136 @@ |
|||||
|
///
|
||||
|
/// Copyright © 2016-2022 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 { ValueSourceProperty } from '@home/components/widget/lib/settings/common/value-source.component'; |
||||
|
import { Component, EventEmitter, forwardRef, Input, OnInit, Output } from '@angular/core'; |
||||
|
import { ControlValueAccessor, FormBuilder, FormGroup, NG_VALUE_ACCESSOR, Validators } from '@angular/forms'; |
||||
|
import { PageComponent } from '@shared/components/page.component'; |
||||
|
import { Store } from '@ngrx/store'; |
||||
|
import { AppState } from '@core/core.state'; |
||||
|
import { TranslateService } from '@ngx-translate/core'; |
||||
|
import { isNumber } from '@core/utils'; |
||||
|
import { IAliasController } from '@core/api/widget-api.models'; |
||||
|
import { TbFlotKeyThreshold } from '@home/components/widget/lib/flot-widget.models'; |
||||
|
|
||||
|
@Component({ |
||||
|
selector: 'tb-flot-threshold', |
||||
|
templateUrl: './flot-threshold.component.html', |
||||
|
styleUrls: ['./flot-threshold.component.scss', './../widget-settings.scss'], |
||||
|
providers: [ |
||||
|
{ |
||||
|
provide: NG_VALUE_ACCESSOR, |
||||
|
useExisting: forwardRef(() => FlotThresholdComponent), |
||||
|
multi: true |
||||
|
} |
||||
|
] |
||||
|
}) |
||||
|
export class FlotThresholdComponent extends PageComponent implements OnInit, ControlValueAccessor { |
||||
|
|
||||
|
@Input() |
||||
|
disabled: boolean; |
||||
|
|
||||
|
@Input() |
||||
|
expanded = false; |
||||
|
|
||||
|
@Input() |
||||
|
aliasController: IAliasController; |
||||
|
|
||||
|
@Output() |
||||
|
removeThreshold = new EventEmitter(); |
||||
|
|
||||
|
private modelValue: TbFlotKeyThreshold; |
||||
|
|
||||
|
private propagateChange = null; |
||||
|
|
||||
|
public thresholdFormGroup: FormGroup; |
||||
|
|
||||
|
constructor(protected store: Store<AppState>, |
||||
|
private translate: TranslateService, |
||||
|
private fb: FormBuilder) { |
||||
|
super(store); |
||||
|
} |
||||
|
|
||||
|
ngOnInit(): void { |
||||
|
this.thresholdFormGroup = this.fb.group({ |
||||
|
valueSource: [null, []], |
||||
|
lineWidth: [null, [Validators.min(0)]], |
||||
|
color: [null, []] |
||||
|
}); |
||||
|
this.thresholdFormGroup.valueChanges.subscribe(() => { |
||||
|
this.updateModel(); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
registerOnChange(fn: any): void { |
||||
|
this.propagateChange = fn; |
||||
|
} |
||||
|
|
||||
|
registerOnTouched(fn: any): void { |
||||
|
} |
||||
|
|
||||
|
setDisabledState(isDisabled: boolean): void { |
||||
|
this.disabled = isDisabled; |
||||
|
if (isDisabled) { |
||||
|
this.thresholdFormGroup.disable({emitEvent: false}); |
||||
|
} else { |
||||
|
this.thresholdFormGroup.enable({emitEvent: false}); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
writeValue(value: TbFlotKeyThreshold): void { |
||||
|
this.modelValue = value; |
||||
|
const valueSource: ValueSourceProperty = { |
||||
|
valueSource: value?.thresholdValueSource, |
||||
|
entityAlias: value?.thresholdEntityAlias, |
||||
|
attribute: value?.thresholdAttribute, |
||||
|
value: value?.thresholdValue |
||||
|
}; |
||||
|
this.thresholdFormGroup.patchValue( |
||||
|
{valueSource, lineWidth: value?.lineWidth, color: value?.color}, {emitEvent: false} |
||||
|
); |
||||
|
} |
||||
|
|
||||
|
thresholdText(): string { |
||||
|
const value: ValueSourceProperty = this.thresholdFormGroup.get('valueSource').value; |
||||
|
return this.valueSourcePropertyText(value); |
||||
|
} |
||||
|
|
||||
|
private valueSourcePropertyText(source?: ValueSourceProperty): string { |
||||
|
if (source) { |
||||
|
if (source.valueSource === 'predefinedValue') { |
||||
|
return `${isNumber(source.value) ? source.value : 0}`; |
||||
|
} else if (source.valueSource === 'entityAttribute') { |
||||
|
const alias = source.entityAlias || 'Undefined'; |
||||
|
const key = source.attribute || 'Undefined'; |
||||
|
return `${alias}.${key}`; |
||||
|
} |
||||
|
} |
||||
|
return 'Undefined'; |
||||
|
} |
||||
|
|
||||
|
private updateModel() { |
||||
|
const value: {valueSource: ValueSourceProperty, lineWidth: number, color: string} = this.thresholdFormGroup.value; |
||||
|
this.modelValue = { |
||||
|
thresholdValueSource: value?.valueSource?.valueSource, |
||||
|
thresholdEntityAlias: value?.valueSource?.entityAlias, |
||||
|
thresholdAttribute: value?.valueSource?.attribute, |
||||
|
thresholdValue: value?.valueSource?.value, |
||||
|
lineWidth: value?.lineWidth, |
||||
|
color: value?.color |
||||
|
}; |
||||
|
this.propagateChange(this.modelValue); |
||||
|
} |
||||
|
} |
||||
Loading…
Reference in new issue