Commit adc7194669d4a8ee0b38ac99f37dcb663e8a62ee
Committed by
GitHub
1 parent
c55ddd9f
[3.0] Add support ticks to digital gauge (#2508)
* Add support ticks to digital gauge * Add link code
Showing
3 changed files
with
329 additions
and
103 deletions
... | ... | @@ -15,12 +15,12 @@ |
15 | 15 | /// |
16 | 16 | |
17 | 17 | import * as CanvasGauges from 'canvas-gauges'; |
18 | -import GenericOptions = CanvasGauges.GenericOptions; | |
19 | -import BaseGauge = CanvasGauges.BaseGauge; | |
20 | 18 | import { FontStyle, FontWeight } from '@home/components/widget/lib/settings.models'; |
21 | 19 | import * as tinycolor_ from 'tinycolor2'; |
22 | 20 | import { ColorFormats } from 'tinycolor2'; |
23 | 21 | import { isDefined, isString, isUndefined } from '@core/utils'; |
22 | +import GenericOptions = CanvasGauges.GenericOptions; | |
23 | +import BaseGauge = CanvasGauges.BaseGauge; | |
24 | 24 | |
25 | 25 | const tinycolor = tinycolor_; |
26 | 26 | |
... | ... | @@ -32,12 +32,12 @@ export interface DigitalGaugeColorRange { |
32 | 32 | rgbString: string; |
33 | 33 | } |
34 | 34 | |
35 | -export interface colorLevelSetting { | |
35 | +export interface ColorLevelSetting { | |
36 | 36 | value: number; |
37 | 37 | color: string; |
38 | 38 | } |
39 | 39 | |
40 | -export type levelColors = Array<string | colorLevelSetting>; | |
40 | +export type levelColors = Array<string | ColorLevelSetting>; | |
41 | 41 | |
42 | 42 | export interface CanvasDigitalGaugeOptions extends GenericOptions { |
43 | 43 | gaugeType?: GaugeType; |
... | ... | @@ -81,6 +81,11 @@ export interface CanvasDigitalGaugeOptions extends GenericOptions { |
81 | 81 | fontValueHeight?: FontHeightInfo; |
82 | 82 | fontMinMaxHeight?: FontHeightInfo; |
83 | 83 | |
84 | + ticksValue?: number[]; | |
85 | + ticks?: number[]; | |
86 | + colorTicks?: string; | |
87 | + tickWidth?: number; | |
88 | + | |
84 | 89 | showTimestamp?: boolean; |
85 | 90 | } |
86 | 91 | |
... | ... | @@ -117,6 +122,10 @@ const defaultDigitalGaugeOptions: CanvasDigitalGaugeOptions = { ...GenericOption |
117 | 122 | |
118 | 123 | neonGlowBrightness: 0, |
119 | 124 | |
125 | + colorTicks: 'gray', | |
126 | + tickWidth: 4, | |
127 | + ticks: [], | |
128 | + | |
120 | 129 | isMobile: false |
121 | 130 | } |
122 | 131 | }; |
... | ... | @@ -243,9 +252,14 @@ export class CanvasDigitalGauge extends BaseGauge { |
243 | 252 | options.neonColorsRange = []; |
244 | 253 | } |
245 | 254 | for (let i = 0; i < options.levelColors.length; i++) { |
246 | - let levelColor: any = options.levelColors[i]; | |
255 | + const levelColor: any = options.levelColors[i]; | |
247 | 256 | if (levelColor !== null) { |
248 | - let percentage = isColorProperty ? inc * i : CanvasDigitalGauge.normalizeValue(levelColor.value, options.minValue, options.maxValue); | |
257 | + let percentage: number; | |
258 | + if(isColorProperty){ | |
259 | + percentage = inc * i; | |
260 | + } else { | |
261 | + percentage = CanvasDigitalGauge.normalizeValue(levelColor.value, options.minValue, options.maxValue); | |
262 | + } | |
249 | 263 | let tColor = tinycolor(isColorProperty ? levelColor : levelColor.color); |
250 | 264 | options.colorsRange.push({ |
251 | 265 | pct: percentage, |
... | ... | @@ -263,6 +277,13 @@ export class CanvasDigitalGauge extends BaseGauge { |
263 | 277 | } |
264 | 278 | } |
265 | 279 | |
280 | + options.ticksValue = []; | |
281 | + for (const tick of options.ticks) { | |
282 | + if (tick !== null) { | |
283 | + options.ticksValue.push(CanvasDigitalGauge.normalizeValue(tick, options.minValue, options.maxValue)) | |
284 | + } | |
285 | + } | |
286 | + | |
266 | 287 | if (options.neonGlowBrightness) { |
267 | 288 | options.neonColorTitle = tinycolor(options.colorTitle).brighten(options.neonGlowBrightness).toHexString(); |
268 | 289 | options.neonColorLabel = tinycolor(options.colorLabel).brighten(options.neonGlowBrightness).toHexString(); |
... | ... | @@ -274,7 +295,7 @@ export class CanvasDigitalGauge extends BaseGauge { |
274 | 295 | } |
275 | 296 | |
276 | 297 | static normalizeValue (value: number, min: number, max: number): number { |
277 | - let normalValue = (value - min) / (max - min); | |
298 | + const normalValue = (value - min) / (max - min); | |
278 | 299 | if (normalValue <= 0) { |
279 | 300 | return 0; |
280 | 301 | } |
... | ... | @@ -657,7 +678,7 @@ function determineFontHeight (options: CanvasDigitalGaugeOptions, target: string |
657 | 678 | fontStyle: options['font' + target + 'Style'] |
658 | 679 | }; |
659 | 680 | const text = $('<span>Hg</span>').css(fontStyle); |
660 | - const block = $('<div style="display: inline-block; width: 1px; height: 0px;"></div>'); | |
681 | + const block = $('<div style="display: inline-block; width: 1px; height: 0;"></div>'); | |
661 | 682 | |
662 | 683 | const div = $('<div></div>'); |
663 | 684 | div.append(text, block); |
... | ... | @@ -884,6 +905,52 @@ function drawBarGlow(context: DigitalGaugeCanvasRenderingContext2D, startX: numb |
884 | 905 | context.stroke(); |
885 | 906 | } |
886 | 907 | |
908 | +function drawTickArc(context: DigitalGaugeCanvasRenderingContext2D, tickValues: number[], Cx: number, Cy: number, | |
909 | + Ri: number, Rm: number, Ro: number, startAngle: number, endAngle: number, | |
910 | + color: string, tickWidth: number) { | |
911 | + if (!tickValues.length) { | |
912 | + return; | |
913 | + } | |
914 | + | |
915 | + const strokeWidth = Ro - Ri; | |
916 | + context.beginPath(); | |
917 | + context.lineWidth = tickWidth; | |
918 | + context.strokeStyle = color; | |
919 | + for (const tick of tickValues) { | |
920 | + const angle = startAngle + tick * endAngle; | |
921 | + const x1 = Cx + (Ri + strokeWidth) * Math.cos(angle); | |
922 | + const y1 = Cy + (Ri + strokeWidth) * Math.sin(angle); | |
923 | + const x2 = Cx + Ri * Math.cos(angle); | |
924 | + const y2 = Cy + Ri * Math.sin(angle); | |
925 | + context.moveTo(x1, y1); | |
926 | + context.lineTo(x2, y2); | |
927 | + } | |
928 | + context.stroke(); | |
929 | +} | |
930 | + | |
931 | +function drawTickBar(context: DigitalGaugeCanvasRenderingContext2D, tickValues: number[], startX: number, startY: number, | |
932 | + distanceBar: number, strokeWidth: number, isVertical: boolean, color: string, tickWidth: number) { | |
933 | + if (!tickValues.length) { | |
934 | + return; | |
935 | + } | |
936 | + | |
937 | + context.beginPath(); | |
938 | + context.lineWidth = tickWidth; | |
939 | + context.strokeStyle = color; | |
940 | + for (const tick of tickValues) { | |
941 | + const tickValue = tick * distanceBar; | |
942 | + if (isVertical) { | |
943 | + context.moveTo(startX - strokeWidth / 2, startY + tickValue - distanceBar); | |
944 | + context.lineTo(startX + strokeWidth / 2, startY + tickValue - distanceBar); | |
945 | + } else { | |
946 | + context.moveTo(startX + tickValue, startY); | |
947 | + context.lineTo(startX + tickValue, startY + strokeWidth); | |
948 | + } | |
949 | + } | |
950 | + context.stroke(); | |
951 | +} | |
952 | + | |
953 | + | |
887 | 954 | function drawProgress(context: DigitalGaugeCanvasRenderingContext2D, |
888 | 955 | options: CanvasDigitalGaugeOptions, progress: number) { |
889 | 956 | let neonColor; |
... | ... | @@ -917,6 +984,8 @@ function drawProgress(context: DigitalGaugeCanvasRenderingContext2D, |
917 | 984 | drawArcGlow(context, Cx, Cy, Ri, Rm, Ro, neonColor, progress, true, |
918 | 985 | options.donutStartAngle, options.donutEndAngle); |
919 | 986 | } |
987 | + drawTickArc(context, options.ticksValue, Cx, Cy, Ri, Rm, Ro, options.donutStartAngle, | |
988 | + options.donutEndAngle - options.donutStartAngle, options.colorTicks, options.tickWidth); | |
920 | 989 | } else if (options.gaugeType === 'arc') { |
921 | 990 | if (options.neonGlowBrightness) { |
922 | 991 | context.strokeStyle = neonColor; |
... | ... | @@ -927,6 +996,7 @@ function drawProgress(context: DigitalGaugeCanvasRenderingContext2D, |
927 | 996 | if (options.neonGlowBrightness && !options.isMobile) { |
928 | 997 | drawArcGlow(context, Cx, Cy, Ri, Rm, Ro, neonColor, progress, false); |
929 | 998 | } |
999 | + drawTickArc(context, options.ticksValue, Cx, Cy, Ri, Rm, Ro, Math.PI, Math.PI, options.colorTicks, options.tickWidth); | |
930 | 1000 | } else if (options.gaugeType === 'horizontalBar') { |
931 | 1001 | if (options.neonGlowBrightness) { |
932 | 1002 | context.strokeStyle = neonColor; |
... | ... | @@ -940,6 +1010,8 @@ function drawProgress(context: DigitalGaugeCanvasRenderingContext2D, |
940 | 1010 | barLeft + (barRight-barLeft)*progress, barTop + strokeWidth/2, |
941 | 1011 | neonColor, strokeWidth, false); |
942 | 1012 | } |
1013 | + drawTickBar(context, options.ticksValue, barLeft, barTop, barRight - barLeft, strokeWidth, | |
1014 | + false, options.colorTicks, options.tickWidth); | |
943 | 1015 | } else if (options.gaugeType === 'verticalBar') { |
944 | 1016 | if (options.neonGlowBrightness) { |
945 | 1017 | context.strokeStyle = neonColor; |
... | ... | @@ -953,6 +1025,8 @@ function drawProgress(context: DigitalGaugeCanvasRenderingContext2D, |
953 | 1025 | baseX + width/2, barBottom - (barBottom-barTop)*progress, |
954 | 1026 | neonColor, strokeWidth, true); |
955 | 1027 | } |
1028 | + drawTickBar(context, options.ticksValue, baseX + width / 2, barTop, barTop - barBottom, strokeWidth, | |
1029 | + true, options.colorTicks, options.tickWidth); | |
956 | 1030 | } |
957 | 1031 | |
958 | 1032 | } | ... | ... |
... | ... | @@ -19,25 +19,27 @@ import { GaugeType } from '@home/components/widget/lib/canvas-digital-gauge'; |
19 | 19 | import { AnimationRule } from '@home/components/widget/lib/analogue-gauge.models'; |
20 | 20 | import { FontSettings } from '@home/components/widget/lib/settings.models'; |
21 | 21 | |
22 | -export interface colorLevelProperty { | |
22 | +export interface AttributeSourceProperty { | |
23 | 23 | valueSource: string; |
24 | 24 | entityAlias?: string; |
25 | 25 | attribute?: string; |
26 | 26 | value?: number; |
27 | 27 | } |
28 | 28 | |
29 | -export interface fixedLevelColors { | |
30 | - from?: colorLevelProperty; | |
31 | - to?: colorLevelProperty; | |
29 | +export interface FixedLevelColors { | |
30 | + from?: AttributeSourceProperty; | |
31 | + to?: AttributeSourceProperty; | |
32 | 32 | color: string; |
33 | 33 | } |
34 | 34 | |
35 | -export interface colorLevelSetting { | |
35 | +export interface ColorLevelSetting { | |
36 | 36 | value: number; |
37 | 37 | color: string; |
38 | 38 | } |
39 | 39 | |
40 | -export type colorLevel = Array<string | colorLevelSetting>; | |
40 | +export type colorLevel = Array<string | ColorLevelSetting>; | |
41 | + | |
42 | +export type attributesGaugeType = 'levelColors' | 'ticks'; | |
41 | 43 | |
42 | 44 | export interface DigitalGaugeSettings { |
43 | 45 | minValue?: number; |
... | ... | @@ -60,7 +62,7 @@ export interface DigitalGaugeSettings { |
60 | 62 | gaugeColor?: string; |
61 | 63 | useFixedLevelColor?: boolean; |
62 | 64 | levelColors?: colorLevel; |
63 | - fixedLevelColors?: fixedLevelColors[]; | |
65 | + fixedLevelColors?: FixedLevelColors[]; | |
64 | 66 | animation?: boolean; |
65 | 67 | animationDuration?: number; |
66 | 68 | animationRule?: AnimationRule; |
... | ... | @@ -72,6 +74,11 @@ export interface DigitalGaugeSettings { |
72 | 74 | units?: string; |
73 | 75 | hideValue?: boolean; |
74 | 76 | hideMinMax?: boolean; |
77 | + showTicks?: boolean; | |
78 | + ticksValue?: AttributeSourceProperty[]; | |
79 | + ticks?: number[]; | |
80 | + colorTicks?: string; | |
81 | + tickWidth?: number; | |
75 | 82 | } |
76 | 83 | |
77 | 84 | export const digitalGaugeSettingsSchema: JsonSettingsSchema = { |
... | ... | @@ -242,6 +249,48 @@ export const digitalGaugeSettingsSchema: JsonSettingsSchema = { |
242 | 249 | } |
243 | 250 | } |
244 | 251 | }, |
252 | + showTicks: { | |
253 | + title: 'Show ticks', | |
254 | + type: 'boolean', | |
255 | + default: false | |
256 | + }, | |
257 | + tickWidth: { | |
258 | + title: 'Width ticks', | |
259 | + type: 'number', | |
260 | + default: 4 | |
261 | + }, | |
262 | + colorTicks: { | |
263 | + title: 'Color ticks', | |
264 | + type: 'string', | |
265 | + default: '#666' | |
266 | + }, | |
267 | + ticksValue: { | |
268 | + title: 'The ticks predefined value', | |
269 | + type: 'array', | |
270 | + items: { | |
271 | + title: 'tickValue', | |
272 | + type: 'object', | |
273 | + properties: { | |
274 | + valueSource: { | |
275 | + title: 'Value source', | |
276 | + type: 'string', | |
277 | + default: 'predefinedValue' | |
278 | + }, | |
279 | + entityAlias: { | |
280 | + title: 'Source entity alias', | |
281 | + type: 'string' | |
282 | + }, | |
283 | + attribute: { | |
284 | + title: 'Source entity attribute', | |
285 | + type: 'string' | |
286 | + }, | |
287 | + value: { | |
288 | + title: 'Value (if predefined value is selected)', | |
289 | + type: 'number' | |
290 | + } | |
291 | + } | |
292 | + } | |
293 | + }, | |
245 | 294 | animation: { |
246 | 295 | title: 'Enable animation', |
247 | 296 | type: 'boolean', |
... | ... | @@ -487,6 +536,40 @@ export const digitalGaugeSettingsSchema: JsonSettingsSchema = { |
487 | 536 | } |
488 | 537 | ] |
489 | 538 | }, |
539 | + 'showTicks', | |
540 | + { | |
541 | + key: 'tickWidth', | |
542 | + condition: 'model.showTicks === true' | |
543 | + }, | |
544 | + { | |
545 | + key: 'colorTicks', | |
546 | + condition: 'model.showTicks === true', | |
547 | + type: 'color' | |
548 | + }, | |
549 | + { | |
550 | + key: 'ticksValue', | |
551 | + condition: 'model.showTicks === true', | |
552 | + items: [ | |
553 | + { | |
554 | + key: 'ticksValue[].valueSource', | |
555 | + type: 'rc-select', | |
556 | + multiple: false, | |
557 | + items: [ | |
558 | + { | |
559 | + value: 'predefinedValue', | |
560 | + label: 'Predefined value (Default)' | |
561 | + }, | |
562 | + { | |
563 | + value: 'entityAttribute', | |
564 | + label: 'Value taken from entity attribute' | |
565 | + } | |
566 | + ] | |
567 | + }, | |
568 | + 'ticksValue[].value', | |
569 | + 'ticksValue[].entityAlias', | |
570 | + 'ticksValue[].attribute' | |
571 | + ] | |
572 | + }, | |
490 | 573 | 'animation', |
491 | 574 | 'animationDuration', |
492 | 575 | { | ... | ... |
... | ... | @@ -17,19 +17,30 @@ |
17 | 17 | import * as CanvasGauges from 'canvas-gauges'; |
18 | 18 | import { WidgetContext } from '@home/models/widget-component.models'; |
19 | 19 | import { |
20 | - colorLevelSetting, | |
20 | + attributesGaugeType, | |
21 | + AttributeSourceProperty, | |
22 | + ColorLevelSetting, | |
21 | 23 | DigitalGaugeSettings, |
22 | - digitalGaugeSettingsSchema | |
24 | + digitalGaugeSettingsSchema, | |
25 | + FixedLevelColors | |
23 | 26 | } from '@home/components/widget/lib/digital-gauge.models'; |
24 | 27 | import * as tinycolor_ from 'tinycolor2'; |
25 | 28 | import { isDefined } from '@core/utils'; |
26 | 29 | import { prepareFontSettings } from '@home/components/widget/lib/settings.models'; |
27 | 30 | import { CanvasDigitalGauge, CanvasDigitalGaugeOptions } from '@home/components/widget/lib/canvas-digital-gauge'; |
28 | 31 | import { DatePipe } from '@angular/common'; |
29 | -import {DataKey, Datasource, DatasourceType, JsonSettingsSchema, widgetType} from '@shared/models/widget.models'; | |
32 | +import { | |
33 | + DataKey, | |
34 | + Datasource, | |
35 | + DatasourceData, | |
36 | + DatasourceType, | |
37 | + JsonSettingsSchema, | |
38 | + widgetType | |
39 | +} from '@shared/models/widget.models'; | |
40 | +import { IWidgetSubscription, WidgetSubscriptionOptions } from '@core/api/widget-api.models'; | |
41 | +import { DataKeyType } from '@shared/models/telemetry/telemetry.models'; | |
42 | +import { EMPTY, Observable } from 'rxjs'; | |
30 | 43 | import GenericOptions = CanvasGauges.GenericOptions; |
31 | -import {IWidgetSubscription, WidgetSubscriptionOptions} from "@core/api/widget-api.models"; | |
32 | -import {DataKeyType} from "@shared/models/telemetry/telemetry.models"; | |
33 | 44 | |
34 | 45 | const tinycolor = tinycolor_; |
35 | 46 | |
... | ... | @@ -37,11 +48,6 @@ const digitalGaugeSettingsSchemaValue = digitalGaugeSettingsSchema; |
37 | 48 | |
38 | 49 | export class TbCanvasDigitalGauge { |
39 | 50 | |
40 | - private localSettings: DigitalGaugeSettings; | |
41 | - private levelColorsSourcesSubscription: IWidgetSubscription; | |
42 | - | |
43 | - private gauge: CanvasDigitalGauge; | |
44 | - | |
45 | 51 | static get settingsSchema(): JsonSettingsSchema { |
46 | 52 | return digitalGaugeSettingsSchemaValue; |
47 | 53 | } |
... | ... | @@ -84,6 +90,12 @@ export class TbCanvasDigitalGauge { |
84 | 90 | this.localSettings.fixedLevelColors = settings.fixedLevelColors || []; |
85 | 91 | } |
86 | 92 | |
93 | + this.localSettings.showTicks = settings.showTicks || false; | |
94 | + this.localSettings.ticks = []; | |
95 | + this.localSettings.ticksValue = settings.ticksValue || []; | |
96 | + this.localSettings.tickWidth = settings.tickWidth || 4; | |
97 | + this.localSettings.colorTicks = settings.colorTicks || '#666'; | |
98 | + | |
87 | 99 | this.localSettings.decimals = isDefined(dataKey.decimals) ? dataKey.decimals : |
88 | 100 | ((isDefined(settings.decimals) && settings.decimals !== null) |
89 | 101 | ? settings.decimals : ctx.decimals); |
... | ... | @@ -137,6 +149,10 @@ export class TbCanvasDigitalGauge { |
137 | 149 | gaugeColor: this.localSettings.gaugeColor, |
138 | 150 | levelColors: this.localSettings.levelColors, |
139 | 151 | |
152 | + colorTicks: this.localSettings.colorTicks, | |
153 | + tickWidth: this.localSettings.tickWidth, | |
154 | + ticks: this.localSettings.ticks, | |
155 | + | |
140 | 156 | title: this.localSettings.title, |
141 | 157 | |
142 | 158 | fontTitleSize: this.localSettings.titleFont.size, |
... | ... | @@ -192,76 +208,92 @@ export class TbCanvasDigitalGauge { |
192 | 208 | this.init(); |
193 | 209 | } |
194 | 210 | |
211 | + private localSettings: DigitalGaugeSettings; | |
212 | + private levelColorsSourcesSubscription: IWidgetSubscription; | |
213 | + private ticksSourcesSubscription: IWidgetSubscription; | |
214 | + | |
215 | + private gauge: CanvasDigitalGauge; | |
216 | + | |
217 | + static generateDatasource(ctx: WidgetContext, datasources: Datasource[], entityAlias: string, | |
218 | + attribute: string, settings: any): Datasource[]{ | |
219 | + const entityAliasId = ctx.aliasController.getEntityAliasId(entityAlias); | |
220 | + if (!entityAliasId) { | |
221 | + throw new Error('Not valid entity aliase name ' + entityAlias); | |
222 | + } | |
223 | + | |
224 | + const datasource = datasources.find((datasourceIteration) => { | |
225 | + return datasourceIteration.entityAliasId === entityAliasId; | |
226 | + }); | |
227 | + | |
228 | + const dataKey: DataKey = { | |
229 | + type: DataKeyType.attribute, | |
230 | + name: attribute, | |
231 | + label: attribute, | |
232 | + settings: [settings], | |
233 | + _hash: Math.random() | |
234 | + }; | |
235 | + | |
236 | + if (datasource) { | |
237 | + const findDataKey = datasource.dataKeys.find((dataKeyIteration) => { | |
238 | + return dataKeyIteration.name === attribute; | |
239 | + }); | |
240 | + | |
241 | + if (findDataKey) { | |
242 | + findDataKey.settings.push(settings); | |
243 | + } else { | |
244 | + datasource.dataKeys.push(dataKey) | |
245 | + } | |
246 | + } else { | |
247 | + const datasourceAttribute: Datasource = { | |
248 | + type: DatasourceType.entity, | |
249 | + name: entityAlias, | |
250 | + aliasName: entityAlias, | |
251 | + entityAliasId, | |
252 | + dataKeys: [dataKey] | |
253 | + }; | |
254 | + datasources.push(datasourceAttribute); | |
255 | + } | |
256 | + | |
257 | + return datasources; | |
258 | + } | |
259 | + | |
195 | 260 | init() { |
196 | 261 | if (this.localSettings.useFixedLevelColor) { |
197 | 262 | if (this.localSettings.fixedLevelColors && this.localSettings.fixedLevelColors.length > 0) { |
198 | 263 | this.localSettings.levelColors = this.settingLevelColorsSubscribe(this.localSettings.fixedLevelColors); |
199 | - this.updateLevelColors(this.localSettings.levelColors); | |
200 | 264 | } |
265 | + | |
266 | + if (this.localSettings.showTicks) { | |
267 | + if (this.localSettings.ticksValue && this.localSettings.ticksValue.length) { | |
268 | + this.localSettings.ticks = this.settingTicksSubscribe(this.localSettings.ticksValue); | |
269 | + } | |
270 | + } | |
271 | + this.updateSetting(); | |
201 | 272 | } |
202 | 273 | } |
203 | 274 | |
204 | - settingLevelColorsSubscribe(options) { | |
275 | + settingLevelColorsSubscribe(options: FixedLevelColors[]): ColorLevelSetting[] { | |
205 | 276 | let levelColorsDatasource: Datasource[] = []; |
206 | - let predefineLevelColors: colorLevelSetting[] = []; | |
277 | + const predefineLevelColors: ColorLevelSetting[] = []; | |
207 | 278 | |
208 | - function setLevelColor(levelSetting, color) { | |
279 | + function setLevelColor(levelSetting: AttributeSourceProperty, color: string) { | |
209 | 280 | if (levelSetting.valueSource === 'predefinedValue' && isFinite(levelSetting.value)) { |
210 | 281 | predefineLevelColors.push({ |
211 | 282 | value: levelSetting.value, |
212 | - color: color | |
283 | + color | |
213 | 284 | }) |
214 | 285 | } else if (levelSetting.entityAlias && levelSetting.attribute) { |
215 | - let entityAliasId = this.ctx.aliasController.getEntityAliasId(levelSetting.entityAlias); | |
216 | - if (!entityAliasId) { | |
286 | + try { | |
287 | + levelColorsDatasource = TbCanvasDigitalGauge.generateDatasource(this.ctx, levelColorsDatasource, | |
288 | + levelSetting.entityAlias, levelSetting.attribute, {color, index: predefineLevelColors.length}); | |
289 | + } catch (e) { | |
217 | 290 | return; |
218 | 291 | } |
219 | - | |
220 | - let datasource = levelColorsDatasource.find((datasource) => { | |
221 | - return datasource.entityAliasId === entityAliasId; | |
222 | - }); | |
223 | - | |
224 | - let dataKey: DataKey = { | |
225 | - type: DataKeyType.attribute, | |
226 | - name: levelSetting.attribute, | |
227 | - label: levelSetting.attribute, | |
228 | - settings: [{ | |
229 | - color: color, | |
230 | - index: predefineLevelColors.length | |
231 | - }], | |
232 | - _hash: Math.random() | |
233 | - }; | |
234 | - | |
235 | - if (datasource) { | |
236 | - let findDataKey = datasource.dataKeys.find((dataKey) => { | |
237 | - return dataKey.name === levelSetting.attribute; | |
238 | - }); | |
239 | - | |
240 | - if (findDataKey) { | |
241 | - findDataKey.settings.push({ | |
242 | - color: color, | |
243 | - index: predefineLevelColors.length | |
244 | - }); | |
245 | - } else { | |
246 | - datasource.dataKeys.push(dataKey) | |
247 | - } | |
248 | - } else { | |
249 | - let datasource: Datasource = { | |
250 | - type: DatasourceType.entity, | |
251 | - name: levelSetting.entityAlias, | |
252 | - aliasName: levelSetting.entityAlias, | |
253 | - entityAliasId: entityAliasId, | |
254 | - dataKeys: [dataKey] | |
255 | - }; | |
256 | - levelColorsDatasource.push(datasource); | |
257 | - } | |
258 | - | |
259 | 292 | predefineLevelColors.push(null); |
260 | 293 | } |
261 | 294 | } |
262 | 295 | |
263 | - for (let i = 0; i < options.length; i++) { | |
264 | - let levelColor = options[i]; | |
296 | + for(const levelColor of options){ | |
265 | 297 | if (levelColor.from) { |
266 | 298 | setLevelColor.call(this, levelColor.from, levelColor.color); |
267 | 299 | } |
... | ... | @@ -270,49 +302,86 @@ export class TbCanvasDigitalGauge { |
270 | 302 | } |
271 | 303 | } |
272 | 304 | |
273 | - this.subscribeLevelColorsAttributes(levelColorsDatasource); | |
305 | + this.subscribeAttributes(levelColorsDatasource, 'levelColors').subscribe((subscription) => { | |
306 | + this.levelColorsSourcesSubscription = subscription; | |
307 | + }); | |
274 | 308 | |
275 | 309 | return predefineLevelColors; |
276 | 310 | } |
277 | 311 | |
278 | - updateLevelColors(levelColors) { | |
279 | - (this.gauge.options as CanvasDigitalGaugeOptions).levelColors = levelColors; | |
280 | - this.gauge.options = CanvasDigitalGauge.configure(this.gauge.options); | |
281 | - this.gauge.update({} as CanvasDigitalGaugeOptions); | |
312 | + settingTicksSubscribe(options: AttributeSourceProperty[]): number[] { | |
313 | + let ticksDatasource: Datasource[] = []; | |
314 | + const predefineTicks: number[] = []; | |
315 | + | |
316 | + for(const tick of options){ | |
317 | + if (tick.valueSource === 'predefinedValue' && isFinite(tick.value)) { | |
318 | + predefineTicks.push(tick.value) | |
319 | + } else if (tick.entityAlias && tick.attribute) { | |
320 | + try { | |
321 | + ticksDatasource = TbCanvasDigitalGauge | |
322 | + .generateDatasource(this.ctx, ticksDatasource, tick.entityAlias, tick.attribute, predefineTicks.length); | |
323 | + } catch (e) { | |
324 | + continue; | |
325 | + } | |
326 | + predefineTicks.push(null); | |
327 | + } | |
328 | + } | |
329 | + | |
330 | + this.subscribeAttributes(ticksDatasource, 'ticks').subscribe((subscription) => { | |
331 | + this.ticksSourcesSubscription = subscription; | |
332 | + }); | |
333 | + | |
334 | + return predefineTicks; | |
282 | 335 | } |
283 | 336 | |
284 | - subscribeLevelColorsAttributes(datasources: Datasource[]) { | |
285 | - let TbCanvasDigitalGauge = this; | |
286 | - let levelColorsSourcesSubscriptionOptions: WidgetSubscriptionOptions = { | |
287 | - datasources: datasources, | |
337 | + subscribeAttributes(datasource: Datasource[], typeAttributes: attributesGaugeType): Observable<IWidgetSubscription> { | |
338 | + if (!datasource.length) { | |
339 | + return EMPTY; | |
340 | + } | |
341 | + | |
342 | + const levelColorsSourcesSubscriptionOptions: WidgetSubscriptionOptions = { | |
343 | + datasources: datasource, | |
288 | 344 | useDashboardTimewindow: false, |
289 | 345 | type: widgetType.latest, |
290 | 346 | callbacks: { |
291 | 347 | onDataUpdated: (subscription) => { |
292 | - for (let i = 0; i < subscription.data.length; i++) { | |
293 | - let keyData = subscription.data[i]; | |
294 | - if (keyData && keyData.data && keyData.data[0]) { | |
295 | - let attrValue = keyData.data[0][1]; | |
296 | - if (isFinite(attrValue)) { | |
297 | - for (let i = 0; i < keyData.dataKey.settings.length; i++) { | |
298 | - let setting = keyData.dataKey.settings[i]; | |
299 | - this.localSettings.levelColors[setting.index] = { | |
300 | - value: attrValue, | |
301 | - color: setting.color | |
302 | - }; | |
303 | - } | |
304 | - } | |
305 | - } | |
306 | - } | |
307 | - this.updateLevelColors(this.localSettings.levelColors); | |
348 | + this.updateAttribute(subscription.data, typeAttributes); | |
308 | 349 | } |
309 | 350 | } |
310 | 351 | }; |
311 | - this.ctx.subscriptionApi.createSubscription(levelColorsSourcesSubscriptionOptions, true).subscribe( | |
312 | - (subscription) => { | |
313 | - TbCanvasDigitalGauge.levelColorsSourcesSubscription = subscription; | |
352 | + | |
353 | + return this.ctx.subscriptionApi.createSubscription(levelColorsSourcesSubscriptionOptions, true); | |
354 | + } | |
355 | + | |
356 | + updateAttribute(data: Array<DatasourceData>, typeAttributes: attributesGaugeType) { | |
357 | + for (const keyData of data) { | |
358 | + if (keyData && keyData.data && keyData.data[0]) { | |
359 | + const attrValue = keyData.data[0][1]; | |
360 | + if (isFinite(attrValue)) { | |
361 | + for (const setting of keyData.dataKey.settings) { | |
362 | + switch (typeAttributes) { | |
363 | + case 'levelColors': | |
364 | + this.localSettings.levelColors[setting.index] = { | |
365 | + value: attrValue, | |
366 | + color: setting.color | |
367 | + }; | |
368 | + break; | |
369 | + case 'ticks': | |
370 | + this.localSettings.ticks[setting] = attrValue; | |
371 | + break; | |
372 | + } | |
373 | + } | |
374 | + } | |
314 | 375 | } |
315 | - ); | |
376 | + } | |
377 | + this.updateSetting(); | |
378 | + } | |
379 | + | |
380 | + updateSetting() { | |
381 | + (this.gauge.options as CanvasDigitalGaugeOptions).ticks = this.localSettings.ticks; | |
382 | + (this.gauge.options as CanvasDigitalGaugeOptions).levelColors = this.localSettings.levelColors; | |
383 | + this.gauge.options = CanvasDigitalGauge.configure(this.gauge.options); | |
384 | + this.gauge.update({} as CanvasDigitalGaugeOptions); | |
316 | 385 | } |
317 | 386 | |
318 | 387 | update() { | ... | ... |