Commit 90ae060cbeb3a7095924c136322d7edfb88ded4a

Authored by Vladyslav
Committed by GitHub
1 parent a58db6b7

Add gauge color limit (#2479)

... ... @@ -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 {
... ...