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 | 104 | } |
105 | 105 | |
106 | 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 | 110 | options.colorsRange = []; |
109 | 111 | if (options.neonGlowBrightness) { |
110 | 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 | 121 | pct: percentage, |
124 | 122 | color: tColor.toRgb(), |
125 | 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 | 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 | 157 | destroy() { |
141 | 158 | this.contextValueClone = null; |
142 | 159 | this.elementValueClone = null; | ... | ... |
... | ... | @@ -50,10 +50,16 @@ export default class TbCanvasDigitalGauge { |
50 | 50 | this.localSettings.gaugeWidthScale = settings.gaugeWidthScale || 0.75; |
51 | 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 | 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 | 65 | this.localSettings.decimals = angular.isDefined(dataKey.decimals) ? dataKey.decimals : |
... | ... | @@ -191,15 +197,137 @@ export default class TbCanvasDigitalGauge { |
191 | 197 | }; |
192 | 198 | |
193 | 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 | 326 | update() { |
198 | 327 | if (this.ctx.data.length > 0) { |
199 | 328 | var cellData = this.ctx.data[0]; |
200 | 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 | 331 | var timestamp; |
204 | 332 | if (this.localSettings.showTimestamp) { |
205 | 333 | timestamp = tvPair[0]; |
... | ... | @@ -325,6 +453,11 @@ export default class TbCanvasDigitalGauge { |
325 | 453 | "type": "string", |
326 | 454 | "default": null |
327 | 455 | }, |
456 | + "useFixedLevelColor": { | |
457 | + "title": "Use precise value for the color indicator", | |
458 | + "type": "boolean", | |
459 | + "default": false | |
460 | + }, | |
328 | 461 | "levelColors": { |
329 | 462 | "title": "Colors of indicator, from lower to upper", |
330 | 463 | "type": "array", |
... | ... | @@ -333,6 +466,66 @@ export default class TbCanvasDigitalGauge { |
333 | 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 | 529 | "animation": { |
337 | 530 | "title": "Enable animation", |
338 | 531 | "type": "boolean", |
... | ... | @@ -521,8 +714,10 @@ export default class TbCanvasDigitalGauge { |
521 | 714 | "key": "gaugeColor", |
522 | 715 | "type": "color" |
523 | 716 | }, |
717 | + "useFixedLevelColor", | |
524 | 718 | { |
525 | 719 | "key": "levelColors", |
720 | + "condition": "model.useFixedLevelColor !== true", | |
526 | 721 | "items": [ |
527 | 722 | { |
528 | 723 | "key": "levelColors[]", |
... | ... | @@ -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 | 774 | "animation", |
534 | 775 | "animationDuration", |
535 | 776 | { | ... | ... |