Commit 90ae060cbeb3a7095924c136322d7edfb88ded4a
Committed by
GitHub
1 parent
a58db6b7
Add gauge color limit (#2479)
Showing
2 changed files
with
275 additions
and
17 deletions
@@ -104,26 +104,32 @@ export default class CanvasDigitalGauge extends canvasGauges.BaseGauge { | @@ -104,26 +104,32 @@ export default class CanvasDigitalGauge extends canvasGauges.BaseGauge { | ||
104 | } | 104 | } |
105 | 105 | ||
106 | var colorsCount = options.levelColors.length; | 106 | var colorsCount = options.levelColors.length; |
107 | - var inc = colorsCount > 1 ? (1 / (colorsCount - 1)) : 1; | 107 | + const inc = colorsCount > 1 ? (1 / (colorsCount - 1)) : 1; |
108 | + var isColorProperty = angular.isString(options.levelColors[0]); | ||
109 | + | ||
108 | options.colorsRange = []; | 110 | options.colorsRange = []; |
109 | if (options.neonGlowBrightness) { | 111 | if (options.neonGlowBrightness) { |
110 | options.neonColorsRange = []; | 112 | options.neonColorsRange = []; |
111 | } | 113 | } |
112 | - for (var i = 0; i < options.levelColors.length; i++) { | ||
113 | - var percentage = inc * i; | ||
114 | - var tColor = tinycolor(options.levelColors[i]); | ||
115 | - options.colorsRange[i] = { | ||
116 | - pct: percentage, | ||
117 | - color: tColor.toRgb(), | ||
118 | - rgbString: tColor.toRgbString() | ||
119 | - }; | ||
120 | - if (options.neonGlowBrightness) { | ||
121 | - tColor = tinycolor(options.levelColors[i]).brighten(options.neonGlowBrightness); | ||
122 | - options.neonColorsRange[i] = { | 114 | + |
115 | + for (let i = 0; i < options.levelColors.length; i++) { | ||
116 | + const levelColor = options.levelColors[i]; | ||
117 | + if (levelColor !== null) { | ||
118 | + let percentage = isColorProperty ? inc * i : CanvasDigitalGauge.normalizeValue(levelColor.value, options.minValue, options.maxValue); | ||
119 | + let tColor = tinycolor(isColorProperty ? levelColor : levelColor.color); | ||
120 | + options.colorsRange[i] = { | ||
123 | pct: percentage, | 121 | pct: percentage, |
124 | color: tColor.toRgb(), | 122 | color: tColor.toRgb(), |
125 | rgbString: tColor.toRgbString() | 123 | rgbString: tColor.toRgbString() |
126 | }; | 124 | }; |
125 | + if (options.neonGlowBrightness) { | ||
126 | + tColor = tinycolor(isColorProperty ? levelColor : levelColor.color).brighten(options.neonGlowBrightness); | ||
127 | + options.neonColorsRange[i] = { | ||
128 | + pct: percentage, | ||
129 | + color: tColor.toRgb(), | ||
130 | + rgbString: tColor.toRgbString() | ||
131 | + }; | ||
132 | + } | ||
127 | } | 133 | } |
128 | } | 134 | } |
129 | 135 | ||
@@ -137,6 +143,17 @@ export default class CanvasDigitalGauge extends canvasGauges.BaseGauge { | @@ -137,6 +143,17 @@ export default class CanvasDigitalGauge extends canvasGauges.BaseGauge { | ||
137 | return canvasGauges.BaseGauge.configure(options); | 143 | return canvasGauges.BaseGauge.configure(options); |
138 | } | 144 | } |
139 | 145 | ||
146 | + static normalizeValue (value, min, max) { | ||
147 | + let normalValue = (value - min) / (max - min); | ||
148 | + if (normalValue <= 0) { | ||
149 | + return 0; | ||
150 | + } | ||
151 | + if (normalValue >= 1) { | ||
152 | + return 1; | ||
153 | + } | ||
154 | + return normalValue; | ||
155 | + } | ||
156 | + | ||
140 | destroy() { | 157 | destroy() { |
141 | this.contextValueClone = null; | 158 | this.contextValueClone = null; |
142 | this.elementValueClone = null; | 159 | this.elementValueClone = null; |
@@ -50,10 +50,16 @@ export default class TbCanvasDigitalGauge { | @@ -50,10 +50,16 @@ export default class TbCanvasDigitalGauge { | ||
50 | this.localSettings.gaugeWidthScale = settings.gaugeWidthScale || 0.75; | 50 | this.localSettings.gaugeWidthScale = settings.gaugeWidthScale || 0.75; |
51 | this.localSettings.gaugeColor = settings.gaugeColor || tinycolor(keyColor).setAlpha(0.2).toRgbString(); | 51 | this.localSettings.gaugeColor = settings.gaugeColor || tinycolor(keyColor).setAlpha(0.2).toRgbString(); |
52 | 52 | ||
53 | - if (!settings.levelColors || settings.levelColors.length <= 0) { | ||
54 | - this.localSettings.levelColors = [keyColor]; | 53 | + this.localSettings.useFixedLevelColor = settings.useFixedLevelColor || false; |
54 | + if (!settings.useFixedLevelColor) { | ||
55 | + if (!settings.levelColors || settings.levelColors.length <= 0) { | ||
56 | + this.localSettings.levelColors = [keyColor]; | ||
57 | + } else { | ||
58 | + this.localSettings.levelColors = settings.levelColors.slice(); | ||
59 | + } | ||
55 | } else { | 60 | } else { |
56 | - this.localSettings.levelColors = settings.levelColors.slice(); | 61 | + this.localSettings.levelColors = [keyColor]; |
62 | + this.localSettings.fixedLevelColors = settings.fixedLevelColors || []; | ||
57 | } | 63 | } |
58 | 64 | ||
59 | this.localSettings.decimals = angular.isDefined(dataKey.decimals) ? dataKey.decimals : | 65 | this.localSettings.decimals = angular.isDefined(dataKey.decimals) ? dataKey.decimals : |
@@ -191,15 +197,137 @@ export default class TbCanvasDigitalGauge { | @@ -191,15 +197,137 @@ export default class TbCanvasDigitalGauge { | ||
191 | }; | 197 | }; |
192 | 198 | ||
193 | this.gauge = new CanvasDigitalGauge(gaugeData).draw(); | 199 | this.gauge = new CanvasDigitalGauge(gaugeData).draw(); |
200 | + this.init(); | ||
201 | + } | ||
202 | + | ||
203 | + init() { | ||
204 | + if (this.localSettings.useFixedLevelColor) { | ||
205 | + if (this.localSettings.fixedLevelColors && this.localSettings.fixedLevelColors.length > 0) { | ||
206 | + this.localSettings.levelColors = this.settingLevelColorsSubscribe(this.localSettings.fixedLevelColors); | ||
207 | + this.updateLevelColors(this.localSettings.levelColors); | ||
208 | + } | ||
209 | + } | ||
210 | + } | ||
211 | + | ||
212 | + settingLevelColorsSubscribe(options) { | ||
213 | + let levelColorsDatasource = []; | ||
214 | + let predefineLevelColors = []; | ||
215 | + | ||
216 | + function setLevelColor(levelSetting, color) { | ||
217 | + if (levelSetting.valueSource === 'predefinedValue' && isFinite(levelSetting.value)) { | ||
218 | + predefineLevelColors.push({ | ||
219 | + value: levelSetting.value, | ||
220 | + color: color | ||
221 | + }) | ||
222 | + } else if (levelSetting.entityAlias && levelSetting.attribute) { | ||
223 | + let entityAliasId = this.ctx.aliasController.getEntityAliasId(levelSetting.entityAlias); | ||
224 | + if (!entityAliasId) { | ||
225 | + return; | ||
226 | + } | ||
227 | + | ||
228 | + let datasource = levelColorsDatasource.filter((datasource) => { | ||
229 | + return datasource.entityAliasId === entityAliasId; | ||
230 | + })[0]; | ||
231 | + | ||
232 | + let dataKey = { | ||
233 | + type: this.ctx.$scope.$injector.get('types').dataKeyType.attribute, | ||
234 | + name: levelSetting.attribute, | ||
235 | + label: levelSetting.attribute, | ||
236 | + settings: [{ | ||
237 | + color: color, | ||
238 | + index: predefineLevelColors.length | ||
239 | + }], | ||
240 | + _hash: Math.random() | ||
241 | + }; | ||
242 | + | ||
243 | + if (datasource) { | ||
244 | + let findDataKey = datasource.dataKeys.filter((dataKey) => { | ||
245 | + return dataKey.name === levelSetting.attribute; | ||
246 | + })[0]; | ||
247 | + | ||
248 | + if (findDataKey) { | ||
249 | + findDataKey.settings.push({ | ||
250 | + color: color, | ||
251 | + index: predefineLevelColors.length | ||
252 | + }); | ||
253 | + } else { | ||
254 | + datasource.dataKeys.push(dataKey) | ||
255 | + } | ||
256 | + } else { | ||
257 | + datasource = { | ||
258 | + type: this.ctx.$scope.$injector.get('types').datasourceType.entity, | ||
259 | + name: levelSetting.entityAlias, | ||
260 | + aliasName: levelSetting.entityAlias, | ||
261 | + entityAliasId: entityAliasId, | ||
262 | + dataKeys: [dataKey] | ||
263 | + }; | ||
264 | + levelColorsDatasource.push(datasource); | ||
265 | + } | ||
266 | + | ||
267 | + predefineLevelColors.push(null); | ||
268 | + } | ||
269 | + } | ||
270 | + | ||
271 | + for (let i = 0; i < options.length; i++) { | ||
272 | + let levelColor = options[i]; | ||
273 | + if (levelColor.from) { | ||
274 | + setLevelColor.call(this, levelColor.from, levelColor.color); | ||
275 | + } | ||
276 | + if (levelColor.to) { | ||
277 | + setLevelColor.call(this, levelColor.to, levelColor.color); | ||
278 | + } | ||
279 | + } | ||
194 | 280 | ||
281 | + this.subscribeLevelColorsAttributes(levelColorsDatasource); | ||
282 | + | ||
283 | + return predefineLevelColors; | ||
284 | + } | ||
285 | + | ||
286 | + updateLevelColors(levelColors) { | ||
287 | + this.gauge.options.levelColors = levelColors; | ||
288 | + this.gauge.options = CanvasDigitalGauge.configure(this.gauge.options); | ||
289 | + this.gauge.update(); | ||
290 | + } | ||
291 | + | ||
292 | + subscribeLevelColorsAttributes(datasources) { | ||
293 | + let TbCanvasDigitalGauge = this; | ||
294 | + let levelColorsSourcesSubscriptionOptions = { | ||
295 | + datasources: datasources, | ||
296 | + useDashboardTimewindow: false, | ||
297 | + type: this.ctx.$scope.$injector.get('types').widgetType.latest.value, | ||
298 | + callbacks: { | ||
299 | + onDataUpdated: (subscription) => { | ||
300 | + for (let i = 0; i < subscription.data.length; i++) { | ||
301 | + let keyData = subscription.data[i]; | ||
302 | + if (keyData && keyData.data && keyData.data[0]) { | ||
303 | + let attrValue = keyData.data[0][1]; | ||
304 | + if (isFinite(attrValue)) { | ||
305 | + for (let i = 0; i < keyData.dataKey.settings.length; i++) { | ||
306 | + let setting = keyData.dataKey.settings[i]; | ||
307 | + this.localSettings.levelColors[setting.index] = { | ||
308 | + value: attrValue, | ||
309 | + color: setting.color | ||
310 | + }; | ||
311 | + } | ||
312 | + } | ||
313 | + } | ||
314 | + } | ||
315 | + this.updateLevelColors(this.localSettings.levelColors); | ||
316 | + } | ||
317 | + } | ||
318 | + }; | ||
319 | + this.ctx.subscriptionApi.createSubscription(levelColorsSourcesSubscriptionOptions, true).then( | ||
320 | + (subscription) => { | ||
321 | + TbCanvasDigitalGauge.levelColorSourcesSubscription = subscription; | ||
322 | + } | ||
323 | + ); | ||
195 | } | 324 | } |
196 | 325 | ||
197 | update() { | 326 | update() { |
198 | if (this.ctx.data.length > 0) { | 327 | if (this.ctx.data.length > 0) { |
199 | var cellData = this.ctx.data[0]; | 328 | var cellData = this.ctx.data[0]; |
200 | if (cellData.data.length > 0) { | 329 | if (cellData.data.length > 0) { |
201 | - var tvPair = cellData.data[cellData.data.length - | ||
202 | - 1]; | 330 | + var tvPair = cellData.data[cellData.data.length - 1]; |
203 | var timestamp; | 331 | var timestamp; |
204 | if (this.localSettings.showTimestamp) { | 332 | if (this.localSettings.showTimestamp) { |
205 | timestamp = tvPair[0]; | 333 | timestamp = tvPair[0]; |
@@ -325,6 +453,11 @@ export default class TbCanvasDigitalGauge { | @@ -325,6 +453,11 @@ export default class TbCanvasDigitalGauge { | ||
325 | "type": "string", | 453 | "type": "string", |
326 | "default": null | 454 | "default": null |
327 | }, | 455 | }, |
456 | + "useFixedLevelColor": { | ||
457 | + "title": "Use precise value for the color indicator", | ||
458 | + "type": "boolean", | ||
459 | + "default": false | ||
460 | + }, | ||
328 | "levelColors": { | 461 | "levelColors": { |
329 | "title": "Colors of indicator, from lower to upper", | 462 | "title": "Colors of indicator, from lower to upper", |
330 | "type": "array", | 463 | "type": "array", |
@@ -333,6 +466,66 @@ export default class TbCanvasDigitalGauge { | @@ -333,6 +466,66 @@ export default class TbCanvasDigitalGauge { | ||
333 | "type": "string" | 466 | "type": "string" |
334 | } | 467 | } |
335 | }, | 468 | }, |
469 | + "fixedLevelColors": { | ||
470 | + "title": "The colors for the indicator using boundary values", | ||
471 | + "type": "array", | ||
472 | + "items": { | ||
473 | + "title": "levelColor", | ||
474 | + "type": "object", | ||
475 | + "properties": { | ||
476 | + "from": { | ||
477 | + "title": "From", | ||
478 | + "type": "object", | ||
479 | + "properties": { | ||
480 | + "valueSource": { | ||
481 | + "title": "[From] Value source", | ||
482 | + "type": "string", | ||
483 | + "default": "predefinedValue" | ||
484 | + }, | ||
485 | + "entityAlias": { | ||
486 | + "title": "[From] Source entity alias", | ||
487 | + "type": "string" | ||
488 | + }, | ||
489 | + "attribute": { | ||
490 | + "title": "[From] Source entity attribute", | ||
491 | + "type": "string" | ||
492 | + }, | ||
493 | + "value": { | ||
494 | + "title": "[From] Value (if predefined value is selected)", | ||
495 | + "type": "number" | ||
496 | + } | ||
497 | + } | ||
498 | + }, | ||
499 | + "to": { | ||
500 | + "title": "To", | ||
501 | + "type": "object", | ||
502 | + "properties": { | ||
503 | + "valueSource": { | ||
504 | + "title": "[To] Value source", | ||
505 | + "type": "string", | ||
506 | + "default": "predefinedValue" | ||
507 | + }, | ||
508 | + "entityAlias": { | ||
509 | + "title": "[To] Source entity alias", | ||
510 | + "type": "string" | ||
511 | + }, | ||
512 | + "attribute": { | ||
513 | + "title": "[To] Source entity attribute", | ||
514 | + "type": "string" | ||
515 | + }, | ||
516 | + "value": { | ||
517 | + "title": "[To] Value (if predefined value is selected)", | ||
518 | + "type": "number" | ||
519 | + } | ||
520 | + } | ||
521 | + }, | ||
522 | + "color": { | ||
523 | + "title": "Color", | ||
524 | + "type": "string" | ||
525 | + } | ||
526 | + } | ||
527 | + } | ||
528 | + }, | ||
336 | "animation": { | 529 | "animation": { |
337 | "title": "Enable animation", | 530 | "title": "Enable animation", |
338 | "type": "boolean", | 531 | "type": "boolean", |
@@ -521,8 +714,10 @@ export default class TbCanvasDigitalGauge { | @@ -521,8 +714,10 @@ export default class TbCanvasDigitalGauge { | ||
521 | "key": "gaugeColor", | 714 | "key": "gaugeColor", |
522 | "type": "color" | 715 | "type": "color" |
523 | }, | 716 | }, |
717 | + "useFixedLevelColor", | ||
524 | { | 718 | { |
525 | "key": "levelColors", | 719 | "key": "levelColors", |
720 | + "condition": "model.useFixedLevelColor !== true", | ||
526 | "items": [ | 721 | "items": [ |
527 | { | 722 | { |
528 | "key": "levelColors[]", | 723 | "key": "levelColors[]", |
@@ -530,6 +725,52 @@ export default class TbCanvasDigitalGauge { | @@ -530,6 +725,52 @@ export default class TbCanvasDigitalGauge { | ||
530 | } | 725 | } |
531 | ] | 726 | ] |
532 | }, | 727 | }, |
728 | + { | ||
729 | + "key": "fixedLevelColors", | ||
730 | + "condition": "model.useFixedLevelColor === true", | ||
731 | + "items": [ | ||
732 | + { | ||
733 | + "key": "fixedLevelColors[].from.valueSource", | ||
734 | + "type": "rc-select", | ||
735 | + "multiple": false, | ||
736 | + "items": [ | ||
737 | + { | ||
738 | + "value": "predefinedValue", | ||
739 | + "label": "Predefined value (Default)" | ||
740 | + }, | ||
741 | + { | ||
742 | + "value": "entityAttribute", | ||
743 | + "label": "Value taken from entity attribute" | ||
744 | + } | ||
745 | + ] | ||
746 | + }, | ||
747 | + "fixedLevelColors[].from.value", | ||
748 | + "fixedLevelColors[].from.entityAlias", | ||
749 | + "fixedLevelColors[].from.attribute", | ||
750 | + { | ||
751 | + "key": "fixedLevelColors[].to.valueSource", | ||
752 | + "type": "rc-select", | ||
753 | + "multiple": false, | ||
754 | + "items": [ | ||
755 | + { | ||
756 | + "value": "predefinedValue", | ||
757 | + "label": "Predefined value (Default)" | ||
758 | + }, | ||
759 | + { | ||
760 | + "value": "entityAttribute", | ||
761 | + "label": "Value taken from entity attribute" | ||
762 | + } | ||
763 | + ] | ||
764 | + }, | ||
765 | + "fixedLevelColors[].to.value", | ||
766 | + "fixedLevelColors[].to.entityAlias", | ||
767 | + "fixedLevelColors[].to.attribute", | ||
768 | + { | ||
769 | + "key": "fixedLevelColors[].color", | ||
770 | + "type": "color" | ||
771 | + } | ||
772 | + ] | ||
773 | + }, | ||
533 | "animation", | 774 | "animation", |
534 | "animationDuration", | 775 | "animationDuration", |
535 | { | 776 | { |