From 96aafa840fa28ccabdba9e333285508132d6e4ad Mon Sep 17 00:00:00 2001 From: Vladyslav_Prykhodko Date: Tue, 28 May 2024 11:54:54 +0300 Subject: [PATCH] UI: Change models and for advanced color telemetry subscribe --- .../battery-level-basic-config.component.html | 4 - .../lib/chart/range-chart-widget.models.ts | 9 ++- .../lib/chart/time-series-chart.models.ts | 42 +++------- .../widget/lib/chart/time-series-chart.ts | 26 +++--- .../widget/lib/digital-gauge.models.ts | 18 ++--- .../components/widget/lib/digital-gauge.ts | 24 +++--- ...me-series-chart-threshold-row.component.ts | 32 ++++---- ...series-chart-thresholds-panel.component.ts | 9 ++- .../common/color-range-list.component.ts | 6 +- .../common/color-settings-panel.component.ts | 13 +-- .../common/color-settings.component.ts | 10 ++- .../common/entity-alias-input.component.ts | 7 +- .../lib/settings/common/gradient.component.ts | 8 +- .../common/value-source-data-key.component.ts | 30 +++---- ...digital-gauge-widget-settings.component.ts | 10 +-- .../shared/models/widget-settings.models.ts | 80 +++++++++---------- 16 files changed, 152 insertions(+), 176 deletions(-) diff --git a/ui-ngx/src/app/modules/home/components/widget/config/basic/indicator/battery-level-basic-config.component.html b/ui-ngx/src/app/modules/home/components/widget/config/basic/indicator/battery-level-basic-config.component.html index 1c377029bb..694fb9d1c5 100644 --- a/ui-ngx/src/app/modules/home/components/widget/config/basic/indicator/battery-level-basic-config.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/config/basic/indicator/battery-level-basic-config.component.html @@ -114,8 +114,6 @@ => { let thresholds: DeepPartial[] = settings.showRangeThresholds ? getMarkPoints(rangeItems).map(item => ({ - ...{type: TimeSeriesChartThresholdType.constant, + ...{type: ValueSourceType.constant, yAxisId: 'default', units, decimals, diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.models.ts b/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.models.ts index e2792c1793..4f896ff2d3 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.models.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.models.ts @@ -26,7 +26,9 @@ import { DateFormatProcessor, DateFormatSettings, Font, - tsToFormatTimeUnit + tsToFormatTimeUnit, + ValueSourceType, + ValueSourceTypeConfig } from '@shared/models/widget-settings.models'; import { CallbackDataParams, @@ -66,7 +68,6 @@ import { FormattedData, WidgetComparisonSettings } from '@shared/models/widget.models'; -import { DataKeyType } from '@shared/models/telemetry/telemetry.models'; import { AbstractControl, ValidationErrors } from '@angular/forms'; import { MarkLine2DDataItemOption } from 'echarts/types/src/component/marker/MarkLineModel'; import { DatePipe } from '@angular/common'; @@ -88,7 +89,8 @@ import { chartColorScheme, ChartFillSettings, ChartFillType, - ChartLabelPosition, ChartLineType, + ChartLabelPosition, + ChartLineType, ChartShape, createChartTextStyle, createLinearOpacityGradient, @@ -522,23 +524,6 @@ export const timeSeriesThresholdLabelPositionTranslations = new Map( - [ - [TimeSeriesChartThresholdType.constant, 'widgets.time-series-chart.threshold.type-constant'], - [TimeSeriesChartThresholdType.latestKey, 'widgets.time-series-chart.threshold.type-latest-key'], - [TimeSeriesChartThresholdType.entity, 'widgets.time-series-chart.threshold.type-entity'] - ] -); - - export enum TimeSeriesChartStateSourceType { constant = 'constant', range = 'range' @@ -737,14 +722,7 @@ export const defaultTimeSeriesChartXAxisSettings: TimeSeriesChartXAxisSettings = export type TimeSeriesChartYAxes = {[id: TimeSeriesChartYAxisId]: TimeSeriesChartYAxisSettings}; -export interface TimeSeriesChartThreshold { - type: TimeSeriesChartThresholdType; - value?: number; - latestKey?: string; - latestKeyType?: DataKeyType.attribute | DataKeyType.timeseries; - entityAlias?: string; - entityKey?: string; - entityKeyType?: DataKeyType.attribute | DataKeyType.timeseries; +export interface TimeSeriesChartThreshold extends ValueSourceTypeConfig { yAxisId: TimeSeriesChartYAxisId; units?: string; decimals?: number; @@ -769,17 +747,17 @@ export const timeSeriesChartThresholdValid = (threshold: TimeSeriesChartThreshol return false; } switch (threshold.type) { - case TimeSeriesChartThresholdType.constant: + case ValueSourceType.constant: if (isUndefinedOrNull(threshold.value)) { return false; } break; - case TimeSeriesChartThresholdType.latestKey: + case ValueSourceType.latestKey: if (!threshold.latestKey || !threshold.latestKeyType) { return false; } break; - case TimeSeriesChartThresholdType.entity: + case ValueSourceType.entity: if (!threshold.entityAlias || !threshold.entityKey || !threshold.entityKeyType) { return false; } @@ -799,7 +777,7 @@ export const timeSeriesChartThresholdValidator = (control: AbstractControl): Val }; export const timeSeriesChartThresholdDefaultSettings: TimeSeriesChartThreshold = { - type: TimeSeriesChartThresholdType.constant, + type: ValueSourceType.constant, yAxisId: 'default', units: null, decimals: 0, diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.ts b/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.ts index 86cf42de0c..354761fa99 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.ts @@ -37,7 +37,6 @@ import { TimeSeriesChartThreshold, timeSeriesChartThresholdDefaultSettings, TimeSeriesChartThresholdItem, - TimeSeriesChartThresholdType, timeSeriesChartTooltipFormatter, TimeSeriesChartTooltipTrigger, TimeSeriesChartTooltipValueFormatFunction, @@ -60,7 +59,7 @@ import { getFocusedSeriesIndex, measureAxisNameSize } from '@home/components/widget/lib/chart/echarts-widget.models'; -import { DateFormatProcessor } from '@shared/models/widget-settings.models'; +import { DateFormatProcessor, ValueSourceType } from '@shared/models/widget-settings.models'; import { formattedDataFormDatasourceData, formatValue, isDefinedAndNotNull, isEqual, mergeDeep } from '@core/utils'; import { DataKey, Datasource, DatasourceType, FormattedData, widgetType } from '@shared/models/widget.models'; import * as echarts from 'echarts/core'; @@ -255,7 +254,7 @@ export class TbTimeSeriesChart { item.latestData = latestData; } for (const item of this.thresholdItems) { - if (item.settings.type === TimeSeriesChartThresholdType.latestKey && item.latestDataKey) { + if (item.settings.type === ValueSourceType.latestKey && item.latestDataKey) { const data = this.ctx.latestData.find(d => d.dataKey === item.latestDataKey); if (data.data[0]) { item.value = parseThresholdData(data.data[0][1]); @@ -435,7 +434,7 @@ export class TbTimeSeriesChart { let latestDataKey: DataKey = null; let entityDataKey: DataKey = null; let value = null; - if (threshold.type === TimeSeriesChartThresholdType.latestKey) { + if (threshold.type === ValueSourceType.latestKey) { if (this.ctx.datasources.length) { for (const datasource of this.ctx.datasources) { latestDataKey = datasource.latestDataKeys?.find(d => @@ -450,7 +449,7 @@ export class TbTimeSeriesChart { if (!latestDataKey) { continue; } - } else if (threshold.type === TimeSeriesChartThresholdType.entity) { + } else if (threshold.type === ValueSourceType.entity) { const entityAliasId = this.ctx.aliasController.getEntityAliasId(threshold.entityAlias); if (!entityAliasId) { continue; @@ -464,14 +463,15 @@ export class TbTimeSeriesChart { }; if (datasource) { datasource.dataKeys.push(entityDataKey); + } else { + datasource = { + type: DatasourceType.entity, + name: threshold.entityAlias, + aliasName: threshold.entityAlias, + entityAliasId, + dataKeys: [entityDataKey] + }; } - datasource = { - type: DatasourceType.entity, - name: threshold.entityAlias, - aliasName: threshold.entityAlias, - entityAliasId, - dataKeys: [ entityDataKey ] - }; thresholdDatasources.push(datasource); } else { // constant value = threshold.value; @@ -567,7 +567,7 @@ export class TbTimeSeriesChart { let update = false; if (subscription.data) { for (const item of this.thresholdItems) { - if (item.settings.type === TimeSeriesChartThresholdType.entity) { + if (item.settings.type === ValueSourceType.entity) { const data = subscription.data.find(d => d.dataKey.settings?.thresholdItemId === item.id); if (data.data[0]) { item.value = parseThresholdData(data.data[0][1]); diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/digital-gauge.models.ts b/ui-ngx/src/app/modules/home/components/widget/lib/digital-gauge.models.ts index c2c59046fe..5c80a820d1 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/digital-gauge.models.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/digital-gauge.models.ts @@ -20,8 +20,8 @@ import { FontSettings } from '@home/components/widget/lib/settings.models'; import { AdvancedColorRange, ColorSettings, - ValueSourceDataKeyType, - ValueSourceWithDataKey + ValueSourceType, + ValueSourceTypeConfig } from '@shared/models/widget-settings.models'; import { DataKeyType } from '@shared/models/telemetry/telemetry.models'; import { isDefinedAndNotNull } from '@core/utils'; @@ -34,8 +34,8 @@ export interface AttributeSourceProperty { } export interface FixedLevelColors { - from?: ValueSourceWithDataKey | number; - to?: ValueSourceWithDataKey | number; + from?: ValueSourceTypeConfig | number; + to?: ValueSourceTypeConfig | number; color: string; } @@ -112,7 +112,7 @@ export interface DigitalGaugeSettings { hideValue?: boolean; hideMinMax?: boolean; showTicks?: boolean; - ticksValue?: ValueSourceWithDataKey[]; + ticksValue?: ValueSourceTypeConfig[]; ticks?: number[]; colorTicks?: string; tickWidth?: number; @@ -127,14 +127,14 @@ export const backwardCompatibilityFixedLevelColors = (fixedLevelColors) => { const valueSourceWithDataKey: AdvancedColorRange[] = []; fixedLevelColors.forEach(fixedLevelColor => valueSourceWithDataKey.push({ from: { - type: fixedLevelColor?.from?.valueSource === 'predefinedValue' ? ValueSourceDataKeyType.constant : ValueSourceDataKeyType.entity, + type: fixedLevelColor?.from?.valueSource === 'predefinedValue' ? ValueSourceType.constant : ValueSourceType.entity, value: fixedLevelColor?.from?.value || null, entityAlias: fixedLevelColor?.from?.entityAlias || '', entityKey: fixedLevelColor?.from?.attribute || '', entityKeyType: DataKeyType.attribute }, to: { - type: fixedLevelColor?.to?.valueSource === 'predefinedValue' ? ValueSourceDataKeyType.constant : ValueSourceDataKeyType.entity, + type: fixedLevelColor?.to?.valueSource === 'predefinedValue' ? ValueSourceType.constant : ValueSourceType.entity, value: fixedLevelColor?.to?.value || null, entityAlias: fixedLevelColor?.to?.entityAlias || '', entityKey: fixedLevelColor?.to?.attribute || '', @@ -146,10 +146,10 @@ export const backwardCompatibilityFixedLevelColors = (fixedLevelColors) => { }; export const backwardCompatibilityTicks = (ticksValue) => { - const ticks: ValueSourceWithDataKey[] = []; + const ticks: ValueSourceTypeConfig[] = []; if (ticksValue?.length && isDefinedAndNotNull(ticksValue[0]?.valueSource)) { ticksValue.forEach(tick => ticks.push({ - type: tick?.valueSource === 'predefinedValue' ? ValueSourceDataKeyType.constant : ValueSourceDataKeyType.entity, + type: tick?.valueSource === 'predefinedValue' ? ValueSourceType.constant : ValueSourceType.entity, value: tick?.value || null, entityAlias: tick?.entityAlias || '', entityKey: tick?.attribute || '', diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/digital-gauge.ts b/ui-ngx/src/app/modules/home/components/widget/lib/digital-gauge.ts index 1958a22cc4..b88106ee1b 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/digital-gauge.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/digital-gauge.ts @@ -34,8 +34,8 @@ import { EMPTY, Observable } from 'rxjs'; import { ColorProcessor, ColorType, - ValueSourceDataKeyType, - ValueSourceWithDataKey + ValueSourceType, + ValueSourceTypeConfig } from '@shared/models/widget-settings.models'; import GenericOptions = CanvasGauges.GenericOptions; @@ -281,13 +281,18 @@ export class TbCanvasDigitalGauge { color: this.localSettings.gaugeColor }); - function setLevelColor(levelSetting, color: string) { - if (levelSetting.type === ValueSourceDataKeyType.constant && isFinite(levelSetting.value)) { + function setLevelColor(levelSetting: ValueSourceTypeConfig | number, color: string) { + if (typeof levelSetting === 'number') { + predefineLevelColors.push({ + value: levelSetting, + color + }); + } else if (levelSetting.type === ValueSourceType.constant && isFinite(levelSetting.value)) { predefineLevelColors.push({ value: levelSetting.value, color }); - } else if (levelSetting.type === ValueSourceDataKeyType.latestKey || levelSetting.type === ValueSourceDataKeyType.entity) { + } else if (levelSetting.type === ValueSourceType.latestKey || levelSetting.type === ValueSourceType.entity) { try { levelColorsDatasource = ColorProcessor.generateDatasource( this.ctx, levelColorsDatasource, levelSetting, {color, index: predefineLevelColors.length} @@ -296,11 +301,6 @@ export class TbCanvasDigitalGauge { return; } predefineLevelColors.push(null); - } else if (isFinite(levelSetting)) { - predefineLevelColors.push({ - value: levelSetting, - color - }); } } @@ -320,12 +320,12 @@ export class TbCanvasDigitalGauge { return predefineLevelColors; } - settingTicksSubscribe(options: ValueSourceWithDataKey[]): number[] { + settingTicksSubscribe(options: ValueSourceTypeConfig[]): number[] { let ticksDatasource: Datasource[] = []; const predefineTicks: number[] = []; for (const tick of options) { - if (tick.type === ValueSourceDataKeyType.constant && isFinite(tick.value)) { + if (tick.type === ValueSourceType.constant && isFinite(tick.value)) { predefineTicks.push(tick.value); } else { try { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-threshold-row.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-threshold-row.component.ts index 168284ec13..f834066a13 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-threshold-row.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-threshold-row.component.ts @@ -36,10 +36,7 @@ import { } from '@angular/forms'; import { TimeSeriesChartThreshold, - TimeSeriesChartThresholdType, - TimeSeriesChartYAxisId, - timeSeriesThresholdTypes, - timeSeriesThresholdTypeTranslations + TimeSeriesChartYAxisId } from '@home/components/widget/lib/chart/time-series-chart.models'; import { TimeSeriesChartThresholdsPanelComponent @@ -50,6 +47,11 @@ import { DataKeysCallbacks } from '@home/components/widget/config/data-keys.comp import { DataKeyType } from '@shared/models/telemetry/telemetry.models'; import { deepClone } from '@core/utils'; import { coerceBoolean } from '@shared/decorators/coercion'; +import { + ValueSourceTypes, + ValueSourceType, + ValueSourceTypeTranslation +} from '@shared/models/widget-settings.models'; @Component({ selector: 'tb-time-series-chart-threshold-row', @@ -70,11 +72,11 @@ export class TimeSeriesChartThresholdRowComponent implements ControlValueAccesso DatasourceType = DatasourceType; - TimeSeriesChartThresholdType = TimeSeriesChartThresholdType; + TimeSeriesChartThresholdType = ValueSourceType; - timeSeriesThresholdTypes = timeSeriesThresholdTypes; + timeSeriesThresholdTypes = ValueSourceTypes; - timeSeriesThresholdTypeTranslations = timeSeriesThresholdTypeTranslations; + timeSeriesThresholdTypeTranslations = ValueSourceTypeTranslation; get aliasController(): IAliasController { return this.thresholdsPanel.aliasController; @@ -209,12 +211,12 @@ export class TimeSeriesChartThresholdRowComponent implements ControlValueAccesso decimals: value.decimals, }, {emitEvent: false} ); - if (value.type === TimeSeriesChartThresholdType.latestKey) { + if (value.type === ValueSourceType.latestKey) { this.latestKeyFormControl.patchValue({ type: value.latestKeyType, name: value.latestKey }, {emitEvent: false}); - } else if (value.type === TimeSeriesChartThresholdType.entity) { + } else if (value.type === ValueSourceType.entity) { this.entityKeyFormControl.patchValue({ type: value.entityKeyType, name: value.entityKey @@ -227,18 +229,18 @@ export class TimeSeriesChartThresholdRowComponent implements ControlValueAccesso } private updateValidators() { - const type: TimeSeriesChartThresholdType = this.thresholdFormGroup.get('type').value; - if (type === TimeSeriesChartThresholdType.constant) { + const type: ValueSourceType = this.thresholdFormGroup.get('type').value; + if (type === ValueSourceType.constant) { this.thresholdFormGroup.get('value').enable({emitEvent: false}); this.thresholdFormGroup.get('entityAlias').disable({emitEvent: false}); this.latestKeyFormControl.disable({emitEvent: false}); this.entityKeyFormControl.disable({emitEvent: false}); - } else if (type === TimeSeriesChartThresholdType.latestKey) { + } else if (type === ValueSourceType.latestKey) { this.thresholdFormGroup.get('value').disable({emitEvent: false}); this.thresholdFormGroup.get('entityAlias').disable({emitEvent: false}); this.latestKeyFormControl.enable({emitEvent: false}); this.entityKeyFormControl.disable({emitEvent: false}); - } else if (type === TimeSeriesChartThresholdType.entity) { + } else if (type === ValueSourceType.entity) { this.thresholdFormGroup.get('value').disable({emitEvent: false}); this.thresholdFormGroup.get('entityAlias').enable({emitEvent: false}); this.latestKeyFormControl.disable({emitEvent: false}); @@ -255,11 +257,11 @@ export class TimeSeriesChartThresholdRowComponent implements ControlValueAccesso this.modelValue.lineColor = value.lineColor; this.modelValue.units = value.units; this.modelValue.decimals = value.decimals; - if (value.type === TimeSeriesChartThresholdType.latestKey) { + if (value.type === ValueSourceType.latestKey) { const latestKey: DataKey = this.latestKeyFormControl.value; this.modelValue.latestKey = latestKey?.name; this.modelValue.latestKeyType = (latestKey?.type as any); - } else if (value.type === TimeSeriesChartThresholdType.entity) { + } else if (value.type === ValueSourceType.entity) { const entityKey: DataKey = this.entityKeyFormControl.value; this.modelValue.entityKey = entityKey?.name; this.modelValue.entityKeyType = (entityKey?.type as any); diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-thresholds-panel.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-thresholds-panel.component.ts index 95e3b242c3..62d2de8402 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-thresholds-panel.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-thresholds-panel.component.ts @@ -29,9 +29,9 @@ import { import { TimeSeriesChartThreshold, timeSeriesChartThresholdDefaultSettings, - TimeSeriesChartThresholdType, timeSeriesChartThresholdValid, - timeSeriesChartThresholdValidator, TimeSeriesChartYAxisId + timeSeriesChartThresholdValidator, + TimeSeriesChartYAxisId } from '@home/components/widget/lib/chart/time-series-chart.models'; import { mergeDeep } from '@core/utils'; import { IAliasController } from '@core/api/widget-api.models'; @@ -39,6 +39,7 @@ import { DataKeysCallbacks } from '@home/components/widget/config/data-keys.comp import { DataKey, Datasource, WidgetConfig } from '@shared/models/widget.models'; import { DataKeyType } from '@shared/models/telemetry/telemetry.models'; import { coerceBoolean } from '@shared/decorators/coercion'; +import { ValueSourceType } from '@shared/models/widget-settings.models'; @Component({ selector: 'tb-time-series-chart-thresholds-panel', @@ -169,7 +170,7 @@ export class TimeSeriesChartThresholdsPanelComponent implements ControlValueAcce const result: TimeSeriesChartThreshold[] = []; const latestKeys = this.datasource?.latestDataKeys || []; for (const threshold of thresholds) { - if (threshold.type === TimeSeriesChartThresholdType.latestKey) { + if (threshold.type === ValueSourceType.latestKey) { const found = latestKeys.find(k => this.isThresholdKey(k, threshold)); if (found) { result.push(threshold); @@ -191,7 +192,7 @@ export class TimeSeriesChartThresholdsPanelComponent implements ControlValueAcce const existingThresholdKeys = latestKeys.filter(k => k.settings?.__thresholdKey === true); const foundThresholdKeys: DataKey[] = []; for (const threshold of thresholds) { - if (threshold.type === TimeSeriesChartThresholdType.latestKey) { + if (threshold.type === ValueSourceType.latestKey) { const found = existingThresholdKeys.find(k => this.isThresholdKey(k, threshold)); if (!found) { const newKey = this.dataKeyCallbacks.generateDataKey(threshold.latestKey, threshold.latestKeyType, diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/color-range-list.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/color-range-list.component.ts index e37186748d..cbc258caa7 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/color-range-list.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/color-range-list.component.ts @@ -30,7 +30,7 @@ import { AdvancedColorRange, ColorRange, ColorRangeSettings, - ValueSourceDataKeyType + ValueSourceType } from '@shared/models/widget-settings.models'; import { TbPopoverComponent } from '@shared/components/popover.component'; import { Subject } from 'rxjs'; @@ -197,10 +197,10 @@ export class ColorRangeListComponent implements OnInit, ControlValueAccessor, On public addAdvancedRange() { const advancedRange: AdvancedColorRange = { from: { - type: ValueSourceDataKeyType.constant + type: ValueSourceType.constant }, to: { - type: ValueSourceDataKeyType.constant + type: ValueSourceType.constant }, color: null }; diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/color-settings-panel.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/color-settings-panel.component.ts index 84d668565f..94cb084512 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/color-settings-panel.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/color-settings-panel.component.ts @@ -30,7 +30,7 @@ import { deepClone } from '@core/utils'; import { WidgetService } from '@core/http/widget.service'; import { ColorSettingsComponent } from '@home/components/widget/lib/settings/common/color-settings.component'; import { IAliasController } from '@core/api/widget-api.models'; -import { coerceBoolean } from '@shared/decorators/coercion'; +import { coerceBoolean, coerceNumber } from '@shared/decorators/coercion'; import { DataKeysCallbacks } from '@home/components/widget/config/data-keys.component.models'; import { Datasource } from '@shared/models/widget.models'; @@ -73,10 +73,12 @@ export class ColorSettingsPanelComponent extends PageComponent implements OnInit gradientAdvancedMode = false; @Input() - minValue: string; + @coerceNumber() + minValue: number; @Input() - maxValue: string; + @coerceNumber() + maxValue: number; colorType = ColorType; @@ -99,7 +101,7 @@ export class ColorSettingsPanelComponent extends PageComponent implements OnInit { type: [this.colorSettings?.type || ColorType.constant, []], color: [this.colorSettings?.color, []], - gradient: [this.colorSettings?.gradient || defaultGradient(+this.minValue, +this.maxValue), []], + gradient: [this.colorSettings?.gradient || defaultGradient(this.minValue, this.maxValue), []], rangeList: [this.colorSettings?.rangeList, []], colorFunction: [this.colorSettings?.colorFunction, []] } @@ -110,8 +112,7 @@ export class ColorSettingsPanelComponent extends PageComponent implements OnInit } copyColorSettings(comp: ColorSettingsComponent) { - const sourceSettings = deepClone(comp.modelValue); - this.colorSettings = sourceSettings; + this.colorSettings = deepClone(comp.modelValue); this.colorSettingsFormGroup.patchValue({ type: this.colorSettings.type, color: this.colorSettings.color, diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/color-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/color-settings.component.ts index 7594719cff..11837804df 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/color-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/color-settings.component.ts @@ -33,7 +33,7 @@ import { } from '@home/components/widget/lib/settings/common/color-settings-panel.component'; import { IAliasController } from '@core/api/widget-api.models'; import { deepClone, isDefinedAndNotNull } from '@core/utils'; -import { coerceBoolean } from '@shared/decorators/coercion'; +import { coerceBoolean, coerceNumber } from '@shared/decorators/coercion'; import { DataKeysCallbacks } from '@home/components/widget/config/data-keys.component.models'; import { Datasource } from '@shared/models/widget.models'; @@ -102,10 +102,12 @@ export class ColorSettingsComponent implements OnInit, ControlValueAccessor, OnD gradientAdvancedMode = false; @Input() - minValue: string; + @coerceNumber() + minValue: number; @Input() - maxValue: string; + @coerceNumber() + maxValue: number; colorType = ColorType; @@ -113,7 +115,7 @@ export class ColorSettingsComponent implements OnInit, ControlValueAccessor, OnD colorStyle: ComponentStyle = {}; - private propagateChange = (v: any) => { }; + private propagateChange: (v: any) => void = () => { }; constructor(private popoverService: TbPopoverService, private renderer: Renderer2, diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/entity-alias-input.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/entity-alias-input.component.ts index dd6d19f14e..d36a4843a1 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/entity-alias-input.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/entity-alias-input.component.ts @@ -15,7 +15,6 @@ /// import { - ChangeDetectorRef, Component, ElementRef, forwardRef, @@ -36,7 +35,6 @@ import { coerceBoolean } from '@shared/decorators/coercion'; import { IAliasController } from '@core/api/widget-api.models'; import { map, mergeMap } from 'rxjs/operators'; import { Observable, of } from 'rxjs'; -import { TimeSeriesChartThresholdType } from '@home/components/widget/lib/chart/time-series-chart.models'; @Component({ selector: 'tb-entity-alias-input', @@ -78,8 +76,7 @@ export class EntityAliasInputComponent implements ControlValueAccessor, OnInit { private propagateChange = (_val: any) => {}; - constructor(private fb: UntypedFormBuilder, - private cd: ChangeDetectorRef) { + constructor(private fb: UntypedFormBuilder) { } ngOnInit() { @@ -151,6 +148,4 @@ export class EntityAliasInputComponent implements ControlValueAccessor, OnInit { const value = this.entityAliasFormControl.value; this.propagateChange(value); } - - protected readonly TimeSeriesChartThresholdType = TimeSeriesChartThresholdType; } diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/gradient.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/gradient.component.ts index b66e5ed1e9..e326cff0d4 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/gradient.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/gradient.component.ts @@ -24,7 +24,7 @@ import { UntypedFormBuilder, UntypedFormGroup } from '@angular/forms'; -import { AdvancedGradient, ColorGradientSettings, ValueSourceDataKeyType } from '@shared/models/widget-settings.models'; +import { AdvancedGradient, ColorGradientSettings, ValueSourceType } from '@shared/models/widget-settings.models'; import { TbPopoverComponent } from '@shared/components/popover.component'; import { Subject } from 'rxjs'; import { takeUntil } from 'rxjs/operators'; @@ -101,12 +101,12 @@ export class GradientComponent implements OnInit, ControlValueAccessor, OnDestro }), gradientAdvanced: this.fb.group({ start: this.fb.group({ - source: [{type: ValueSourceDataKeyType.constant}], + source: [{type: ValueSourceType.constant}], color: ['rgba(0, 255, 0, 1)'] }), gradientList: this.fb.array([]), end: this.fb.group({ - source: [{type: ValueSourceDataKeyType.constant}], + source: [{type: ValueSourceType.constant}], color: ['rgba(255, 0, 0, 1)'] }) }) @@ -241,7 +241,7 @@ export class GradientComponent implements OnInit, ControlValueAccessor, OnDestro addGradient(advanced = false) { if (advanced) { this.advancedGradientListFormArray.push( - this.advancedGradientControl({source: {type: ValueSourceDataKeyType.constant}, color: 'rgba(0,0,0,0.87)'}) + this.advancedGradientControl({source: {type: ValueSourceType.constant}, color: 'rgba(0,0,0,0.87)'}) ); } else { this.gradientListFormArray.push(this.colorGradientControl('rgba(0,0,0,0.87)')); diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/value-source-data-key.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/value-source-data-key.component.ts index ed5f8eadf5..c552effcce 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/value-source-data-key.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/value-source-data-key.component.ts @@ -31,9 +31,9 @@ import { DataKeyType } from '@shared/models/telemetry/telemetry.models'; import { DataKey, Datasource, DatasourceType } from '@app/shared/models/widget.models'; import { DataKeysCallbacks } from '@home/components/widget/config/data-keys.component.models'; import { - ValueSourceDataKeyType, - ValueSourceDataKeyTypes, - ValueSourceDataKeyTypeTranslation + ValueSourceType, + ValueSourceTypes, + ValueSourceTypeTranslation } from '@shared/models/widget-settings.models'; @Component({ @@ -53,9 +53,9 @@ export class ValueSourceDataKeyComponent extends PageComponent implements OnInit dataKeyType = DataKeyType; datasourceType = DatasourceType; - valueSourceDataKeyType = ValueSourceDataKeyType; - valueSourceDataKeyTypes = ValueSourceDataKeyTypes; - valueSourceDataKeyTypeTranslation = ValueSourceDataKeyTypeTranslation; + valueSourceDataKeyType = ValueSourceType; + valueSourceDataKeyTypes = ValueSourceTypes; + valueSourceDataKeyTypeTranslation = ValueSourceTypeTranslation; @Input() disabled: boolean; @@ -86,7 +86,7 @@ export class ValueSourceDataKeyComponent extends PageComponent implements OnInit ngOnInit(): void { this.valueSourceFormGroup = this.fb.group({ - type: [ValueSourceDataKeyType.constant, []], + type: [ValueSourceType.constant, []], value: [null, [Validators.required]], entityAlias: [null, [Validators.required]] }); @@ -134,12 +134,12 @@ export class ValueSourceDataKeyComponent extends PageComponent implements OnInit entityAlias: value.entityAlias }, {emitEvent: false} ); - if (value.type === ValueSourceDataKeyType.latestKey) { + if (value.type === ValueSourceType.latestKey) { this.latestKeyFormControl.patchValue({ type: value.latestKeyType, name: value.latestKey }, {emitEvent: false}); - } else if (value.type === ValueSourceDataKeyType.entity) { + } else if (value.type === ValueSourceType.entity) { this.entityKeyFormControl.patchValue({ type: value.entityKeyType, name: value.entityKey @@ -156,11 +156,11 @@ export class ValueSourceDataKeyComponent extends PageComponent implements OnInit this.modelValue.value = value.value; this.modelValue.entityAlias = value.entityAlias; - if (value.type === ValueSourceDataKeyType.latestKey) { + if (value.type === ValueSourceType.latestKey) { const latestKey: DataKey = this.latestKeyFormControl.value; this.modelValue.latestKey = latestKey?.name; this.modelValue.latestKeyType = (latestKey?.type as any); - } else if (value.type === ValueSourceDataKeyType.entity) { + } else if (value.type === ValueSourceType.entity) { const entityKey: DataKey = this.entityKeyFormControl.value; this.modelValue.entityKey = entityKey?.name; this.modelValue.entityKeyType = (entityKey?.type as any); @@ -169,18 +169,18 @@ export class ValueSourceDataKeyComponent extends PageComponent implements OnInit } private updateValidators(): void { - const type: ValueSourceDataKeyType = this.valueSourceFormGroup.get('type').value; - if (type === ValueSourceDataKeyType.constant) { + const type: ValueSourceType = this.valueSourceFormGroup.get('type').value; + if (type === ValueSourceType.constant) { this.valueSourceFormGroup.get('value').enable({emitEvent: false}); this.valueSourceFormGroup.get('entityAlias').disable({emitEvent: false}); this.latestKeyFormControl.disable({emitEvent: false}); this.entityKeyFormControl.disable({emitEvent: false}); - } else if (type === ValueSourceDataKeyType.latestKey) { + } else if (type === ValueSourceType.latestKey) { this.valueSourceFormGroup.get('value').disable({emitEvent: false}); this.valueSourceFormGroup.get('entityAlias').disable({emitEvent: false}); this.latestKeyFormControl.enable({emitEvent: false}); this.entityKeyFormControl.disable({emitEvent: false}); - } else if (type === ValueSourceDataKeyType.entity) { + } else if (type === ValueSourceType.entity) { this.valueSourceFormGroup.get('value').disable({emitEvent: false}); this.valueSourceFormGroup.get('entityAlias').enable({emitEvent: false}); this.latestKeyFormControl.disable({emitEvent: false}); diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/gauge/digital-gauge-widget-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/gauge/digital-gauge-widget-settings.component.ts index 579e01b830..548941bb45 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/gauge/digital-gauge-widget-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/gauge/digital-gauge-widget-settings.component.ts @@ -35,8 +35,8 @@ import { ColorType, constantColor, simpleDateFormat, - ValueSourceDataKeyType, - ValueSourceWithDataKey + ValueSourceType, + ValueSourceTypeConfig } from '@shared/models/widget-settings.models'; @Component({ @@ -348,7 +348,7 @@ export class DigitalGaugeWidgetSettingsComponent extends WidgetSettingsComponent settingsForm.setControl('ticksValue', this.prepareTicksValueFormArray(settings.ticksValue), {emitEvent: false}); } - private prepareTicksValueFormArray(ticksValue: ValueSourceWithDataKey[] | undefined): UntypedFormArray { + private prepareTicksValueFormArray(ticksValue: ValueSourceTypeConfig[] | undefined): UntypedFormArray { const ticksValueControls: Array = []; if (ticksValue) { ticksValue.forEach((tickValue) => { @@ -371,8 +371,8 @@ export class DigitalGaugeWidgetSettingsComponent extends WidgetSettingsComponent } public addTickValue() { - const tickValue: ValueSourceWithDataKey = { - type: ValueSourceDataKeyType.constant + const tickValue: ValueSourceTypeConfig = { + type: ValueSourceType.constant }; const tickValuesArray = this.digitalGaugeWidgetSettingsForm.get('ticksValue') as UntypedFormArray; const tickValueControl = this.fb.control(tickValue, []); diff --git a/ui-ngx/src/app/shared/models/widget-settings.models.ts b/ui-ngx/src/app/shared/models/widget-settings.models.ts index f4bb216c3a..79d17aed88 100644 --- a/ui-ngx/src/app/shared/models/widget-settings.models.ts +++ b/ui-ngx/src/app/shared/models/widget-settings.models.ts @@ -25,7 +25,7 @@ import { TargetDeviceType, widgetType } from '@shared/models/widget.models'; -import { ChangeDetectorRef, EventEmitter, Injector } from '@angular/core'; +import { EventEmitter, Injector } from '@angular/core'; import { DatePipe } from '@angular/common'; import { DateAgoPipe } from '@shared/pipe/date-ago.pipe'; import { TranslateService } from '@ngx-translate/core'; @@ -37,7 +37,7 @@ import { map } from 'rxjs/operators'; import { DomSanitizer } from '@angular/platform-browser'; import { AVG_MONTH, DAY, HOUR, Interval, IntervalMath, MINUTE, SECOND, YEAR } from '@shared/models/time/time.models'; import moment from 'moment'; -import tinycolor, { ColorInput } from 'tinycolor2'; +import tinycolor from 'tinycolor2'; import { WidgetContext } from '@home/models/widget-component.models'; import { DataKeyType } from '@shared/models/telemetry/telemetry.models'; import { IWidgetSubscription, WidgetSubscriptionOptions } from '@core/api/widget-api.models'; @@ -106,24 +106,24 @@ export interface ColorRange { color: string; } -export enum ValueSourceDataKeyType { +export enum ValueSourceType { constant = 'constant', latestKey = 'latestKey', entity = 'entity' } -export const ValueSourceDataKeyTypes = Object.keys(ValueSourceDataKeyType) as ValueSourceDataKeyType[]; +export const ValueSourceTypes = Object.keys(ValueSourceType) as ValueSourceType[]; -export const ValueSourceDataKeyTypeTranslation = new Map( +export const ValueSourceTypeTranslation = new Map( [ - [ValueSourceDataKeyType.constant, 'widgets.value-source.type-constant'], - [ValueSourceDataKeyType.latestKey, 'widgets.value-source.type-latest-key'], - [ValueSourceDataKeyType.entity, 'widgets.value-source.type-entity'] + [ValueSourceType.constant, 'widgets.value-source.type-constant'], + [ValueSourceType.latestKey, 'widgets.value-source.type-latest-key'], + [ValueSourceType.entity, 'widgets.value-source.type-entity'] ] ); -export interface ValueSourceWithDataKey { - type: ValueSourceDataKeyType; +export interface ValueSourceTypeConfig { + type: ValueSourceType; value?: number; latestKeyType?: DataKeyType.attribute | DataKeyType.timeseries; latestKey?: string; @@ -133,8 +133,8 @@ export interface ValueSourceWithDataKey { } export interface AdvancedColorRange { - from?: ValueSourceWithDataKey; - to?: ValueSourceWithDataKey; + from?: ValueSourceTypeConfig; + to?: ValueSourceTypeConfig; color: string; } @@ -226,7 +226,7 @@ export interface ColorRangeSettings { } export interface AdvancedGradient { - source: ValueSourceWithDataKey; + source: ValueSourceTypeConfig; color: string; } @@ -272,11 +272,11 @@ export const defaultGradient = (minValue?: number, maxValue?: number): ColorGrad gradient: ['rgba(0, 255, 0, 1)', 'rgba(255, 0, 0, 1)'], gradientAdvanced: [ { - source: {type: ValueSourceDataKeyType.constant}, + source: {type: ValueSourceType.constant}, color: 'rgba(0, 255, 0, 1)' }, { - source: {type: ValueSourceDataKeyType.constant}, + source: {type: ValueSourceType.constant}, color: 'rgba(255, 0, 0, 1)' } ], @@ -369,9 +369,9 @@ export abstract class ColorProcessor { static generateDatasource( ctx: WidgetContext, datasources: Datasource[], - valueSource: ValueSourceWithDataKey, + valueSource: ValueSourceTypeConfig, settings: DataKeySettings): Datasource[]{ - if (valueSource.type === ValueSourceDataKeyType.latestKey) { + if (valueSource.type === ValueSourceType.latestKey) { if (ctx.datasources.length) { if (isDefinedAndNotNull(ctx.datasources[0].aliasName)) { datasources = this.parseDatasource(ctx, valueSource, ctx.datasources[0].aliasName, settings, datasources, true); @@ -379,24 +379,24 @@ export abstract class ColorProcessor { datasources = this.parseDatasource(ctx, valueSource, '', settings, datasources, true); } } - } else if (valueSource.type === ValueSourceDataKeyType.entity) { + } else if (valueSource.type === ValueSourceType.entity) { datasources = this.parseDatasource(ctx, valueSource, valueSource.entityAlias, settings, datasources, false); } return datasources; } static parseDatasource(ctx: WidgetContext, - valueSource: ValueSourceWithDataKey, - entityAlias: string, settings: DataKeySettings, - datasources: Datasource[], - isLatest: boolean) { - let dataKey: DataKey = null; + valueSource: ValueSourceTypeConfig, + entityAlias: string, + settings: DataKeySettings, + datasources: Datasource[], + isLatest: boolean) { const dataKeySettings = [settings]; const entityAliasId = ctx.aliasController.getEntityAliasId(entityAlias); let datasource = datasources.find(d => entityAlias ? (d.entityAliasId === entityAliasId) : (d.deviceId === ctx.datasources[0].deviceId) ); - dataKey = { + const dataKey: DataKey = { type: isLatest ? valueSource.latestKeyType : valueSource.entityKeyType, name: isLatest ? valueSource.latestKey : valueSource.entityKey, label: isLatest ? valueSource.latestKey : valueSource.entityKey, @@ -448,23 +448,23 @@ class RangeColorProcessor extends ColorProcessor { private advancedRangeSourcesSubscription: IWidgetSubscription; - private progress; + private progress: number; constructor(protected settings: ColorSettings, protected ctx: WidgetContext) { super(settings); } - advancedRangeSubscribe(options: ColorRangeSettings){ + private advancedRangeSubscribe(options: ColorRangeSettings){ let advancedRangeDatasource: Datasource[] = []; let index = 0; - function setRangeColor(rangeSetting: ValueSourceWithDataKey, color: string) { - if (rangeSetting.type === ValueSourceDataKeyType.constant && isFinite(rangeSetting.value)) { + function setRangeColor(rangeSetting: ValueSourceTypeConfig, color: string) { + if (rangeSetting.type === ValueSourceType.constant && isFinite(rangeSetting.value)) { index++; } else { try { - advancedRangeDatasource = this.generateDatasource(this.ctx, advancedRangeDatasource, + advancedRangeDatasource = ColorProcessor.generateDatasource(this.ctx, advancedRangeDatasource, rangeSetting, {color, index}); } catch (e) { return; @@ -492,7 +492,7 @@ class RangeColorProcessor extends ColorProcessor { } } - subscribeAttributes(datasource: Datasource[]): Observable { + private subscribeAttributes(datasource: Datasource[]): Observable { if (!datasource.length) { return EMPTY; } @@ -513,7 +513,7 @@ class RangeColorProcessor extends ColorProcessor { return this.ctx.subscriptionApi.createSubscription(levelColorsSourcesSubscriptionOptions, true); } - updateAttribute(data: Array) { + private updateAttribute(data: Array) { for (const keyData of data) { if (keyData && keyData.data && keyData.data[0]) { const attrValue = keyData.data[0][1]; @@ -606,8 +606,8 @@ class GradientColorProcessor extends ColorProcessor { private progress: number; - private minValue: number; - private maxValue: number; + private readonly minValue: number; + private readonly maxValue: number; private advancedGradientSourcesSubscription: IWidgetSubscription; @@ -633,7 +633,7 @@ class GradientColorProcessor extends ColorProcessor { } } - calculateProgress(current: number, min: number, max: number) { + private calculateProgress(current: number, min: number, max: number) { if (current < min) { return 0; } else if (current > max) { @@ -642,7 +642,7 @@ class GradientColorProcessor extends ColorProcessor { return (current - min) / (max - min); } - getProgressColor(progress: number, levelColors: Array): string { + private getProgressColor(progress: number, levelColors: Array): string { const colorsCount = levelColors.length; const inc = colorsCount > 1 ? (1 / (colorsCount - 1)) : 1; const colorsRange = []; @@ -683,12 +683,12 @@ class GradientColorProcessor extends ColorProcessor { return colorsRange[colorsRange.length - 1].rgbString; } - advancedRangeSubscribe(options: Array){ + private advancedRangeSubscribe(options: Array){ let advancedGradientDatasource: Datasource[] = []; let index = 0; - function setGradientColor(gradientSetting: ValueSourceWithDataKey) { - if (gradientSetting.type === ValueSourceDataKeyType.constant && isFinite(gradientSetting.value)) { + function setGradientColor(gradientSetting: ValueSourceTypeConfig) { + if (gradientSetting.type === ValueSourceType.constant && isFinite(gradientSetting.value)) { index++; } else { try { @@ -715,7 +715,7 @@ class GradientColorProcessor extends ColorProcessor { } } - subscribeAttributes(datasource: Datasource[]): Observable { + private subscribeAttributes(datasource: Datasource[]): Observable { if (!datasource.length) { return EMPTY; } @@ -736,7 +736,7 @@ class GradientColorProcessor extends ColorProcessor { return this.ctx.subscriptionApi.createSubscription(levelColorsSourcesSubscriptionOptions, true); } - updateAttribute(data: Array) { + private updateAttribute(data: Array) { for (const keyData of data) { if (keyData && keyData.data && keyData.data[0]) { const attrValue = keyData.data[0][1];