Commit 2435ca5d0ff0dfd6e362de658311b00b853f759a
Merge remote-tracking branch 'origin/master' into asset-alarm-mgmt
Showing
33 changed files
with
303 additions
and
85 deletions
... | ... | @@ -20,7 +20,7 @@ |
20 | 20 | <modelVersion>4.0.0</modelVersion> |
21 | 21 | <parent> |
22 | 22 | <groupId>org.thingsboard</groupId> |
23 | - <version>1.2.3</version> | |
23 | + <version>1.3.0-SNAPSHOT</version> | |
24 | 24 | <artifactId>common</artifactId> |
25 | 25 | </parent> |
26 | 26 | <groupId>org.thingsboard.common</groupId> | ... | ... |
... | ... | @@ -20,7 +20,7 @@ |
20 | 20 | <modelVersion>4.0.0</modelVersion> |
21 | 21 | <parent> |
22 | 22 | <groupId>org.thingsboard</groupId> |
23 | - <version>1.2.3</version> | |
23 | + <version>1.3.0-SNAPSHOT</version> | |
24 | 24 | <artifactId>common</artifactId> |
25 | 25 | </parent> |
26 | 26 | <groupId>org.thingsboard.common</groupId> | ... | ... |
... | ... | @@ -20,7 +20,7 @@ |
20 | 20 | <modelVersion>4.0.0</modelVersion> |
21 | 21 | <parent> |
22 | 22 | <groupId>org.thingsboard</groupId> |
23 | - <version>1.2.3</version> | |
23 | + <version>1.3.0-SNAPSHOT</version> | |
24 | 24 | <artifactId>common</artifactId> |
25 | 25 | </parent> |
26 | 26 | <groupId>org.thingsboard.common</groupId> | ... | ... |
... | ... | @@ -22,7 +22,7 @@ |
22 | 22 | <modelVersion>4.0.0</modelVersion> |
23 | 23 | <parent> |
24 | 24 | <groupId>org.thingsboard</groupId> |
25 | - <version>1.2.3</version> | |
25 | + <version>1.3.0-SNAPSHOT</version> | |
26 | 26 | <artifactId>extensions</artifactId> |
27 | 27 | </parent> |
28 | 28 | <groupId>org.thingsboard.extensions</groupId> | ... | ... |
... | ... | @@ -20,7 +20,7 @@ |
20 | 20 | <modelVersion>4.0.0</modelVersion> |
21 | 21 | <parent> |
22 | 22 | <groupId>org.thingsboard</groupId> |
23 | - <version>1.2.3</version> | |
23 | + <version>1.3.0-SNAPSHOT</version> | |
24 | 24 | <artifactId>extensions</artifactId> |
25 | 25 | </parent> |
26 | 26 | <groupId>org.thingsboard.extensions</groupId> | ... | ... |
... | ... | @@ -22,7 +22,7 @@ |
22 | 22 | <modelVersion>4.0.0</modelVersion> |
23 | 23 | <parent> |
24 | 24 | <groupId>org.thingsboard</groupId> |
25 | - <version>1.2.3</version> | |
25 | + <version>1.3.0-SNAPSHOT</version> | |
26 | 26 | <artifactId>extensions</artifactId> |
27 | 27 | </parent> |
28 | 28 | <groupId>org.thingsboard.extensions</groupId> | ... | ... |
... | ... | @@ -20,7 +20,7 @@ |
20 | 20 | <modelVersion>4.0.0</modelVersion> |
21 | 21 | <parent> |
22 | 22 | <groupId>org.thingsboard</groupId> |
23 | - <version>1.2.3</version> | |
23 | + <version>1.3.0-SNAPSHOT</version> | |
24 | 24 | <artifactId>transport</artifactId> |
25 | 25 | </parent> |
26 | 26 | <groupId>org.thingsboard.transport</groupId> | ... | ... |
... | ... | @@ -20,7 +20,7 @@ |
20 | 20 | <modelVersion>4.0.0</modelVersion> |
21 | 21 | <parent> |
22 | 22 | <groupId>org.thingsboard</groupId> |
23 | - <version>1.2.3</version> | |
23 | + <version>1.3.0-SNAPSHOT</version> | |
24 | 24 | <artifactId>transport</artifactId> |
25 | 25 | </parent> |
26 | 26 | <groupId>org.thingsboard.transport</groupId> | ... | ... |
... | ... | @@ -20,7 +20,7 @@ |
20 | 20 | <modelVersion>4.0.0</modelVersion> |
21 | 21 | <parent> |
22 | 22 | <groupId>org.thingsboard</groupId> |
23 | - <version>1.2.3</version> | |
23 | + <version>1.3.0-SNAPSHOT</version> | |
24 | 24 | <artifactId>transport</artifactId> |
25 | 25 | </parent> |
26 | 26 | <groupId>org.thingsboard.transport</groupId> | ... | ... |
... | ... | @@ -126,6 +126,7 @@ export default class Subscription { |
126 | 126 | dataKey: dataKey, |
127 | 127 | dataIndex: dataIndex++ |
128 | 128 | }; |
129 | + legendKey.dataKey.hidden = false; | |
129 | 130 | this.legendData.keys.push(legendKey); |
130 | 131 | var legendKeyData = { |
131 | 132 | min: null, |
... | ... | @@ -146,11 +147,11 @@ export default class Subscription { |
146 | 147 | this.legendData.keys = this.ctx.$filter('orderBy')(this.legendData.keys, '+label'); |
147 | 148 | registration = this.ctx.$scope.$watch( |
148 | 149 | function() { |
149 | - return subscription.legendData.data; | |
150 | + return subscription.legendData.keys; | |
150 | 151 | }, |
151 | 152 | function (newValue, oldValue) { |
152 | 153 | for(var i = 0; i < newValue.length; i++) { |
153 | - if(newValue[i].hidden != oldValue[i].hidden) { | |
154 | + if(newValue[i].dataKey.hidden != oldValue[i].dataKey.hidden) { | |
154 | 155 | subscription.updateDataVisibility(i); |
155 | 156 | } |
156 | 157 | } |
... | ... | @@ -307,7 +308,7 @@ export default class Subscription { |
307 | 308 | } |
308 | 309 | |
309 | 310 | updateDataVisibility(index) { |
310 | - var hidden = this.legendData.data[index].hidden; | |
311 | + var hidden = this.legendData.keys[index].dataKey.hidden; | |
311 | 312 | if (hidden) { |
312 | 313 | this.hiddenData[index].data = this.data[index].data; |
313 | 314 | this.data[index].data = []; |
... | ... | @@ -418,7 +419,7 @@ export default class Subscription { |
418 | 419 | this.notifyDataLoaded(); |
419 | 420 | var update = true; |
420 | 421 | var currentData; |
421 | - if (this.displayLegend && this.legendData.data[datasourceIndex + dataKeyIndex].hidden) { | |
422 | + if (this.displayLegend && this.legendData.keys[datasourceIndex + dataKeyIndex].dataKey.hidden) { | |
422 | 423 | currentData = this.hiddenData[datasourceIndex + dataKeyIndex]; |
423 | 424 | } else { |
424 | 425 | currentData = this.data[datasourceIndex + dataKeyIndex]; |
... | ... | @@ -445,18 +446,21 @@ export default class Subscription { |
445 | 446 | } |
446 | 447 | |
447 | 448 | updateLegend(dataIndex, data, apply) { |
449 | + var dataKey = this.legendData.keys[dataIndex].dataKey; | |
450 | + var decimals = angular.isDefined(dataKey.decimals) ? dataKey.decimals : this.decimals; | |
451 | + var units = dataKey.units && dataKey.units.length ? dataKey.units : this.units; | |
448 | 452 | var legendKeyData = this.legendData.data[dataIndex]; |
449 | 453 | if (this.legendConfig.showMin) { |
450 | - legendKeyData.min = this.ctx.widgetUtils.formatValue(calculateMin(data), this.decimals, this.units); | |
454 | + legendKeyData.min = this.ctx.widgetUtils.formatValue(calculateMin(data), decimals, units); | |
451 | 455 | } |
452 | 456 | if (this.legendConfig.showMax) { |
453 | - legendKeyData.max = this.ctx.widgetUtils.formatValue(calculateMax(data), this.decimals, this.units); | |
457 | + legendKeyData.max = this.ctx.widgetUtils.formatValue(calculateMax(data), decimals, units); | |
454 | 458 | } |
455 | 459 | if (this.legendConfig.showAvg) { |
456 | - legendKeyData.avg = this.ctx.widgetUtils.formatValue(calculateAvg(data), this.decimals, this.units); | |
460 | + legendKeyData.avg = this.ctx.widgetUtils.formatValue(calculateAvg(data), decimals, units); | |
457 | 461 | } |
458 | 462 | if (this.legendConfig.showTotal) { |
459 | - legendKeyData.total = this.ctx.widgetUtils.formatValue(calculateTotal(data), this.decimals, this.units); | |
463 | + legendKeyData.total = this.ctx.widgetUtils.formatValue(calculateTotal(data), decimals, units); | |
460 | 464 | } |
461 | 465 | this.callbacks.legendDataUpdated(this, apply !== false); |
462 | 466 | } | ... | ... |
... | ... | @@ -76,6 +76,8 @@ function DatakeyConfig($compile, $templateCache, $q, types) { |
76 | 76 | scope.model.name = ngModelCtrl.$viewValue.name; |
77 | 77 | scope.model.label = ngModelCtrl.$viewValue.label; |
78 | 78 | scope.model.color = ngModelCtrl.$viewValue.color; |
79 | + scope.model.units = ngModelCtrl.$viewValue.units; | |
80 | + scope.model.decimals = ngModelCtrl.$viewValue.decimals; | |
79 | 81 | scope.model.funcBody = ngModelCtrl.$viewValue.funcBody; |
80 | 82 | scope.model.postFuncBody = ngModelCtrl.$viewValue.postFuncBody; |
81 | 83 | scope.model.usePostProcessing = scope.model.postFuncBody ? true : false; |
... | ... | @@ -97,6 +99,8 @@ function DatakeyConfig($compile, $templateCache, $q, types) { |
97 | 99 | value.name = scope.model.name; |
98 | 100 | value.label = scope.model.label; |
99 | 101 | value.color = scope.model.color; |
102 | + value.units = scope.model.units; | |
103 | + value.decimals = scope.model.decimals; | |
100 | 104 | value.funcBody = scope.model.funcBody; |
101 | 105 | if (!scope.model.postFuncBody) { |
102 | 106 | delete value.postFuncBody; | ... | ... |
... | ... | @@ -48,6 +48,16 @@ |
48 | 48 | md-color-history="false"> |
49 | 49 | </div> |
50 | 50 | </div> |
51 | + <div layout="row" layout-align="start center"> | |
52 | + <md-input-container flex> | |
53 | + <label translate>datakey.units</label> | |
54 | + <input name="units" ng-model="model.units"> | |
55 | + </md-input-container> | |
56 | + <md-input-container flex> | |
57 | + <label translate>datakey.decimals</label> | |
58 | + <input name="decimals" ng-model="model.decimals" type="number" min="0" max="15" step="1" ng-pattern="/^\d*$/"> | |
59 | + </md-input-container> | |
60 | + </div> | |
51 | 61 | <section layout="column" ng-if="model.type === types.dataKeyType.function"> |
52 | 62 | <span translate>datakey.data-generation-func</span> |
53 | 63 | <br/> | ... | ... |
... | ... | @@ -45,7 +45,7 @@ function Legend($compile, $templateCache, types) { |
45 | 45 | scope.legendConfig.position === types.position.top.value; |
46 | 46 | |
47 | 47 | scope.toggleHideData = function(index) { |
48 | - scope.legendData.data[index].hidden = !scope.legendData.data[index].hidden; | |
48 | + scope.legendData.keys[index].dataKey.hidden = !scope.legendData.keys[index].dataKey.hidden; | |
49 | 49 | } |
50 | 50 | |
51 | 51 | $compile(element.contents())(scope); | ... | ... |
... | ... | @@ -30,7 +30,7 @@ |
30 | 30 | <td><span class="tb-legend-line" ng-style="{backgroundColor: legendKey.dataKey.color}"></span></td> |
31 | 31 | <td class="tb-legend-label" |
32 | 32 | ng-click="toggleHideData(legendKey.dataIndex)" |
33 | - ng-class="{ 'tb-hidden-label': legendData.data[legendKey.dataIndex].hidden, 'tb-horizontal': isHorizontal }"> | |
33 | + ng-class="{ 'tb-hidden-label': legendData.keys[legendKey.dataIndex].dataKey.hidden, 'tb-horizontal': isHorizontal }"> | |
34 | 34 | {{ legendKey.dataKey.label }} |
35 | 35 | </td> |
36 | 36 | <td class="tb-legend-value" ng-if="legendConfig.showMin === true">{{ legendData.data[legendKey.dataIndex].min }}</td> | ... | ... |
... | ... | @@ -355,10 +355,10 @@ function WidgetConfig($compile, $templateCache, $rootScope, $timeout, types, uti |
355 | 355 | var matches = false; |
356 | 356 | do { |
357 | 357 | matches = false; |
358 | - if (value.datasources) { | |
359 | - for (var d in value.datasources) { | |
360 | - var datasource = value.datasources[d]; | |
361 | - for (var k in datasource.dataKeys) { | |
358 | + if (value.config.datasources) { | |
359 | + for (var d=0;d<value.config.datasources.length;d++) { | |
360 | + var datasource = value.config.datasources[d]; | |
361 | + for (var k=0;k<datasource.dataKeys.length;k++) { | |
362 | 362 | var dataKey = datasource.dataKeys[k]; |
363 | 363 | if (dataKey.label === label) { |
364 | 364 | i++; |
... | ... | @@ -375,9 +375,9 @@ function WidgetConfig($compile, $templateCache, $rootScope, $timeout, types, uti |
375 | 375 | scope.genNextColor = function () { |
376 | 376 | var i = 0; |
377 | 377 | var value = ngModelCtrl.$viewValue; |
378 | - if (value.datasources) { | |
379 | - for (var d in value.datasources) { | |
380 | - var datasource = value.datasources[d]; | |
378 | + if (value.config.datasources) { | |
379 | + for (var d=0;d<value.config.datasources.length;d++) { | |
380 | + var datasource = value.config.datasources[d]; | |
381 | 381 | i += datasource.dataKeys.length; |
382 | 382 | } |
383 | 383 | } | ... | ... |
... | ... | @@ -983,8 +983,11 @@ export default function DashboardController(types, dashboardUtils, widgetService |
983 | 983 | if (revert) { |
984 | 984 | vm.dashboard = vm.prevDashboard; |
985 | 985 | vm.dashboardConfiguration = vm.dashboard.configuration; |
986 | + vm.dashboardCtx.dashboardTimewindow = vm.dashboardConfiguration.timewindow; | |
986 | 987 | openDashboardState(vm.prevDashboardState); |
987 | 988 | entityAliasesUpdated(); |
989 | + } else { | |
990 | + vm.dashboard.configuration.timewindow = vm.dashboardCtx.dashboardTimewindow; | |
988 | 991 | } |
989 | 992 | } |
990 | 993 | } | ... | ... |
... | ... | @@ -63,7 +63,7 @@ |
63 | 63 | is-toolbar |
64 | 64 | direction="left" |
65 | 65 | tooltip-direction="bottom" aggregation |
66 | - ng-model="vm.dashboardConfiguration.timewindow"> | |
66 | + ng-model="vm.dashboardCtx.dashboardTimewindow"> | |
67 | 67 | </tb-timewindow> |
68 | 68 | <tb-aliases-entity-select ng-show="!vm.isEdit && vm.displayEntitiesSelect()" |
69 | 69 | tooltip-direction="bottom" | ... | ... |
... | ... | @@ -385,6 +385,8 @@ export default angular.module('thingsboard.locale', []) |
385 | 385 | "advanced": "Advanced", |
386 | 386 | "label": "Label", |
387 | 387 | "color": "Color", |
388 | + "units": "Special symbol to show next to value", | |
389 | + "decimals": "Number of digits after floating point", | |
388 | 390 | "data-generation-func": "Data generation function", |
389 | 391 | "use-data-post-processing-func": "Use data post-processing function", |
390 | 392 | "configuration": "Data key configuration", | ... | ... |
... | ... | @@ -41,8 +41,7 @@ export default class TbAnalogueLinearGauge { |
41 | 41 | |
42 | 42 | var valueInt = settings.valueInt || 3; |
43 | 43 | |
44 | - var valueDec = (angular.isDefined(settings.valueDec) && settings.valueDec !== null) | |
45 | - ? settings.valueDec : ctx.decimals; | |
44 | + var valueDec = getValueDec(settings); | |
46 | 45 | |
47 | 46 | step = parseFloat(parseFloat(step).toFixed(valueDec)); |
48 | 47 | |
... | ... | @@ -74,6 +73,32 @@ export default class TbAnalogueLinearGauge { |
74 | 73 | var progressColorStart = tinycolor(keyColor).setAlpha(0.05).toRgbString(); |
75 | 74 | var progressColorEnd = tinycolor(keyColor).darken().toRgbString(); |
76 | 75 | |
76 | + function getUnits(settings) { | |
77 | + var dataKey; | |
78 | + if (ctx.data && ctx.data[0]) { | |
79 | + dataKey = ctx.data[0].dataKey; | |
80 | + } | |
81 | + if (dataKey && dataKey.units && dataKey.units.length) { | |
82 | + return dataKey.units; | |
83 | + } else { | |
84 | + return angular.isDefined(settings.units) && settings.units.length > 0 ? settings.units : ctx.units; | |
85 | + } | |
86 | + } | |
87 | + | |
88 | + function getValueDec(settings) { | |
89 | + var dataKey; | |
90 | + if (ctx.data && ctx.data[0]) { | |
91 | + dataKey = ctx.data[0].dataKey; | |
92 | + } | |
93 | + if (dataKey && angular.isDefined(dataKey.decimals)) { | |
94 | + return dataKey.decimals; | |
95 | + } else { | |
96 | + return (angular.isDefined(settings.valueDec) && settings.valueDec !== null) | |
97 | + ? settings.valueDec : ctx.decimals; | |
98 | + } | |
99 | + } | |
100 | + | |
101 | + | |
77 | 102 | function getFontFamily(fontSettings) { |
78 | 103 | var family = fontSettings && fontSettings.family ? fontSettings.family : 'Roboto'; |
79 | 104 | if (family === 'RobotoDraft') { |
... | ... | @@ -92,7 +117,7 @@ export default class TbAnalogueLinearGauge { |
92 | 117 | maxValue: maxValue, |
93 | 118 | majorTicks: majorTicks, |
94 | 119 | minorTicks: settings.minorTicks || 2, |
95 | - units: angular.isDefined(settings.units) && settings.units.length > 0 ? settings.units : ctx.units, | |
120 | + units: getUnits(settings), | |
96 | 121 | title: ((settings.showUnitTitle !== false) ? |
97 | 122 | (settings.unitTitle && settings.unitTitle.length > 0 ? |
98 | 123 | settings.unitTitle : dataKey.label) : ''), | ... | ... |
... | ... | @@ -42,8 +42,7 @@ export default class TbAnalogueRadialGauge { |
42 | 42 | |
43 | 43 | var valueInt = settings.valueInt || 3; |
44 | 44 | |
45 | - var valueDec = (angular.isDefined(settings.valueDec) && settings.valueDec !== null) | |
46 | - ? settings.valueDec : ctx.decimals; | |
45 | + var valueDec = getValueDec(settings); | |
47 | 46 | |
48 | 47 | step = parseFloat(parseFloat(step).toFixed(valueDec)); |
49 | 48 | |
... | ... | @@ -71,6 +70,31 @@ export default class TbAnalogueRadialGauge { |
71 | 70 | |
72 | 71 | var colorNumbers = tinycolor(keyColor).darken(20).toRgbString(); |
73 | 72 | |
73 | + function getUnits(settings) { | |
74 | + var dataKey; | |
75 | + if (ctx.data && ctx.data[0]) { | |
76 | + dataKey = ctx.data[0].dataKey; | |
77 | + } | |
78 | + if (dataKey && dataKey.units && dataKey.units.length) { | |
79 | + return dataKey.units; | |
80 | + } else { | |
81 | + return angular.isDefined(settings.units) && settings.units.length > 0 ? settings.units : ctx.units; | |
82 | + } | |
83 | + } | |
84 | + | |
85 | + function getValueDec(settings) { | |
86 | + var dataKey; | |
87 | + if (ctx.data && ctx.data[0]) { | |
88 | + dataKey = ctx.data[0].dataKey; | |
89 | + } | |
90 | + if (dataKey && angular.isDefined(dataKey.decimals)) { | |
91 | + return dataKey.decimals; | |
92 | + } else { | |
93 | + return (angular.isDefined(settings.valueDec) && settings.valueDec !== null) | |
94 | + ? settings.valueDec : ctx.decimals; | |
95 | + } | |
96 | + } | |
97 | + | |
74 | 98 | function getFontFamily(fontSettings) { |
75 | 99 | var family = fontSettings && fontSettings.family ? fontSettings.family : 'Roboto'; |
76 | 100 | if (family === 'RobotoDraft') { |
... | ... | @@ -89,7 +113,7 @@ export default class TbAnalogueRadialGauge { |
89 | 113 | maxValue: maxValue, |
90 | 114 | majorTicks: majorTicks, |
91 | 115 | minorTicks: settings.minorTicks || 2, |
92 | - units: angular.isDefined(settings.units) && settings.units.length > 0 ? settings.units : ctx.units, | |
116 | + units: getUnits(settings), | |
93 | 117 | title: ((settings.showUnitTitle !== false) ? |
94 | 118 | (settings.unitTitle && settings.unitTitle.length > 0 ? |
95 | 119 | settings.unitTitle : dataKey.label) : ''), | ... | ... |
... | ... | @@ -54,10 +54,13 @@ export default class TbCanvasDigitalGauge { |
54 | 54 | this.localSettings.levelColors = settings.levelColors.slice(); |
55 | 55 | } |
56 | 56 | |
57 | - this.localSettings.decimals = (angular.isDefined(settings.decimals) && settings.decimals !== null) | |
58 | - ? settings.decimals : ctx.decimals; | |
57 | + this.localSettings.decimals = angular.isDefined(dataKey.decimals) ? dataKey.decimals : | |
58 | + ((angular.isDefined(settings.decimals) && settings.decimals !== null) | |
59 | + ? settings.decimals : ctx.decimals); | |
60 | + | |
61 | + this.localSettings.units = dataKey.units && dataKey.units.length ? dataKey.units : | |
62 | + (angular.isDefined(settings.units) && settings.units.length > 0 ? settings.units : ctx.units); | |
59 | 63 | |
60 | - this.localSettings.units = angular.isDefined(settings.units) && settings.units.length > 0 ? settings.units : ctx.units; | |
61 | 64 | this.localSettings.hideValue = settings.showValue !== true; |
62 | 65 | this.localSettings.hideMinMax = settings.showMinMax !== true; |
63 | 66 | ... | ... |
... | ... | @@ -104,8 +104,10 @@ export default class TbFlot { |
104 | 104 | |
105 | 105 | if (this.chartType === 'pie') { |
106 | 106 | ctx.tooltipFormatter = function(item) { |
107 | + var units = item.series.dataKey.units && item.series.dataKey.units.length ? item.series.dataKey.units : tbFlot.ctx.trackUnits; | |
108 | + var decimals = angular.isDefined(item.series.dataKey.decimals) ? item.series.dataKey.decimals : tbFlot.ctx.trackDecimals; | |
107 | 109 | var divElement = seriesInfoDiv(item.series.dataKey.label, item.series.dataKey.color, |
108 | - item.datapoint[1][0][1], tbFlot.ctx.trackUnits, tbFlot.ctx.trackDecimals, true, item.series.percent); | |
110 | + item.datapoint[1][0][1], units, decimals, true, item.series.percent); | |
109 | 111 | return divElement.prop('outerHTML'); |
110 | 112 | }; |
111 | 113 | } else { |
... | ... | @@ -127,18 +129,19 @@ export default class TbFlot { |
127 | 129 | if (tbFlot.ctx.tooltipIndividual && seriesHoverInfo.index !== seriesIndex) { |
128 | 130 | continue; |
129 | 131 | } |
132 | + var units = seriesHoverInfo.units && seriesHoverInfo.units.length ? seriesHoverInfo.units : tbFlot.ctx.trackUnits; | |
133 | + var decimals = angular.isDefined(seriesHoverInfo.decimals) ? seriesHoverInfo.decimals : tbFlot.ctx.trackDecimals; | |
130 | 134 | var divElement = seriesInfoDiv(seriesHoverInfo.label, seriesHoverInfo.color, |
131 | - seriesHoverInfo.value, tbFlot.ctx.trackUnits, tbFlot.ctx.trackDecimals, seriesHoverInfo.index === seriesIndex); | |
135 | + seriesHoverInfo.value, units, decimals, seriesHoverInfo.index === seriesIndex); | |
132 | 136 | content += divElement.prop('outerHTML'); |
133 | 137 | } |
134 | 138 | return content; |
135 | 139 | }; |
136 | 140 | } |
137 | 141 | |
138 | - ctx.trackDecimals = angular.isDefined(settings.decimals) ? | |
139 | - settings.decimals : ctx.decimals; | |
142 | + ctx.trackDecimals = ctx.decimals; | |
140 | 143 | |
141 | - ctx.trackUnits = angular.isDefined(settings.units) ? settings.units : ctx.units; | |
144 | + ctx.trackUnits = ctx.units; | |
142 | 145 | |
143 | 146 | ctx.tooltipIndividual = this.chartType === 'pie' || (angular.isDefined(settings.tooltipIndividual) ? settings.tooltipIndividual : false); |
144 | 147 | ctx.tooltipCumulative = angular.isDefined(settings.tooltipCumulative) ? settings.tooltipCumulative : false; |
... | ... | @@ -172,7 +175,7 @@ export default class TbFlot { |
172 | 175 | font: angular.copy(font), |
173 | 176 | labelFont: angular.copy(font) |
174 | 177 | }; |
175 | - options.yaxis = { | |
178 | + this.yaxis = { | |
176 | 179 | font: angular.copy(font), |
177 | 180 | labelFont: angular.copy(font) |
178 | 181 | }; |
... | ... | @@ -188,32 +191,33 @@ export default class TbFlot { |
188 | 191 | options.xaxis.labelFont.size = options.xaxis.font.size+2; |
189 | 192 | options.xaxis.labelFont.weight = "bold"; |
190 | 193 | } |
191 | - if (settings.yaxis) { | |
194 | + | |
195 | + ctx.yAxisTickFormatter = function(value/*, axis*/) { | |
192 | 196 | if (settings.yaxis.showLabels === false) { |
193 | - options.yaxis.tickFormatter = function() { | |
194 | - return ''; | |
195 | - }; | |
196 | - } else if (ctx.trackUnits && ctx.trackUnits.length > 0) { | |
197 | - options.yaxis.tickFormatter = function(value, axis) { | |
198 | - var factor = axis.tickDecimals ? Math.pow(10, axis.tickDecimals) : 1, | |
199 | - formatted = "" + Math.round(value * factor) / factor; | |
200 | - if (axis.tickDecimals != null) { | |
201 | - var decimal = formatted.indexOf("."), | |
202 | - precision = decimal === -1 ? 0 : formatted.length - decimal - 1; | |
203 | - | |
204 | - if (precision < axis.tickDecimals) { | |
205 | - formatted = (precision ? formatted : formatted + ".") + ("" + factor).substr(1, axis.tickDecimals - precision); | |
206 | - } | |
207 | - } | |
208 | - formatted += ' ' + tbFlot.ctx.trackUnits; | |
209 | - return formatted; | |
210 | - }; | |
197 | + return ''; | |
198 | + } | |
199 | + var factor = this.tickDecimals ? Math.pow(10, this.tickDecimals) : 1, | |
200 | + formatted = "" + Math.round(value * factor) / factor; | |
201 | + if (this.tickDecimals != null) { | |
202 | + var decimal = formatted.indexOf("."), | |
203 | + precision = decimal === -1 ? 0 : formatted.length - decimal - 1; | |
204 | + | |
205 | + if (precision < this.tickDecimals) { | |
206 | + formatted = (precision ? formatted : formatted + ".") + ("" + factor).substr(1, this.tickDecimals - precision); | |
207 | + } | |
211 | 208 | } |
212 | - options.yaxis.font.color = settings.yaxis.color || options.yaxis.font.color; | |
213 | - options.yaxis.label = settings.yaxis.title || null; | |
214 | - options.yaxis.labelFont.color = options.yaxis.font.color; | |
215 | - options.yaxis.labelFont.size = options.yaxis.font.size+2; | |
216 | - options.yaxis.labelFont.weight = "bold"; | |
209 | + formatted += ' ' + this.tickUnits; | |
210 | + return formatted; | |
211 | + } | |
212 | + | |
213 | + this.yaxis.tickFormatter = ctx.yAxisTickFormatter; | |
214 | + | |
215 | + if (settings.yaxis) { | |
216 | + this.yaxis.font.color = settings.yaxis.color || this.yaxis.font.color; | |
217 | + this.yaxis.label = settings.yaxis.title || null; | |
218 | + this.yaxis.labelFont.color = this.yaxis.font.color; | |
219 | + this.yaxis.labelFont.size = this.yaxis.font.size+2; | |
220 | + this.yaxis.labelFont.weight = "bold"; | |
217 | 221 | } |
218 | 222 | |
219 | 223 | options.grid.borderWidth = 1; |
... | ... | @@ -229,7 +233,7 @@ export default class TbFlot { |
229 | 233 | options.xaxis.tickLength = 0; |
230 | 234 | } |
231 | 235 | if (settings.grid.horizontalLines === false) { |
232 | - options.yaxis.tickLength = 0; | |
236 | + this.yaxis.tickLength = 0; | |
233 | 237 | } |
234 | 238 | } |
235 | 239 | |
... | ... | @@ -311,6 +315,8 @@ export default class TbFlot { |
311 | 315 | this.subscription = subscription; |
312 | 316 | this.$element = $element; |
313 | 317 | var colors = []; |
318 | + this.yaxes = []; | |
319 | + var yaxesMap = {}; | |
314 | 320 | for (var i = 0; i < this.subscription.data.length; i++) { |
315 | 321 | var series = this.subscription.data[i]; |
316 | 322 | colors.push(series.dataKey.color); |
... | ... | @@ -342,8 +348,29 @@ export default class TbFlot { |
342 | 348 | |
343 | 349 | series.highlightColor = lineColor.toRgbString(); |
344 | 350 | |
351 | + if (this.yaxis) { | |
352 | + var units = series.dataKey.units && series.dataKey.units.length ? series.dataKey.units : this.ctx.trackUnits; | |
353 | + var yaxis; | |
354 | + if (keySettings.showSeparateAxis) { | |
355 | + yaxis = this.createYAxis(keySettings, units); | |
356 | + this.yaxes.push(yaxis); | |
357 | + } else { | |
358 | + yaxis = yaxesMap[units]; | |
359 | + if (!yaxis) { | |
360 | + yaxis = this.createYAxis(keySettings, units); | |
361 | + yaxesMap[units] = yaxis; | |
362 | + this.yaxes.push(yaxis); | |
363 | + } | |
364 | + } | |
365 | + series.yaxisIndex = this.yaxes.indexOf(yaxis); | |
366 | + series.yaxis = series.yaxisIndex+1; | |
367 | + yaxis.keysInfo[i] = {hidden: false}; | |
368 | + yaxis.hidden = false; | |
369 | + } | |
345 | 370 | } |
371 | + | |
346 | 372 | this.options.colors = colors; |
373 | + this.options.yaxes = angular.copy(this.yaxes); | |
347 | 374 | if (this.chartType === 'line' || this.chartType === 'bar') { |
348 | 375 | if (this.chartType === 'bar') { |
349 | 376 | this.options.series.bars.barWidth = this.subscription.timeWindow.interval * 0.6; |
... | ... | @@ -373,6 +400,23 @@ export default class TbFlot { |
373 | 400 | } |
374 | 401 | } |
375 | 402 | |
403 | + createYAxis(keySettings, units) { | |
404 | + var yaxis = angular.copy(this.yaxis); | |
405 | + | |
406 | + var label = keySettings.axisTitle && keySettings.axisTitle.length ? keySettings.axisTitle : yaxis.label; | |
407 | + var tickDecimals = angular.isDefined(keySettings.axisTickDecimals) ? keySettings.axisTickDecimals : 0; | |
408 | + var position = keySettings.axisPosition && keySettings.axisPosition.length ? keySettings.axisPosition : "left"; | |
409 | + | |
410 | + yaxis.label = label; | |
411 | + yaxis.tickUnits = units; | |
412 | + yaxis.tickDecimals = tickDecimals; | |
413 | + yaxis.alignTicksWithAxis = position == "right" ? 1 : null; | |
414 | + yaxis.position = position; | |
415 | + | |
416 | + yaxis.keysInfo = []; | |
417 | + return yaxis; | |
418 | + } | |
419 | + | |
376 | 420 | update() { |
377 | 421 | if (this.updateTimeoutHandle) { |
378 | 422 | this.ctx.$scope.$timeout.cancel(this.updateTimeoutHandle); |
... | ... | @@ -381,17 +425,64 @@ export default class TbFlot { |
381 | 425 | if (this.subscription) { |
382 | 426 | if (!this.isMouseInteraction && this.ctx.plot) { |
383 | 427 | if (this.chartType === 'line' || this.chartType === 'bar') { |
428 | + | |
429 | + var axisVisibilityChanged = false; | |
430 | + if (this.yaxis) { | |
431 | + for (var i = 0; i < this.subscription.data.length; i++) { | |
432 | + var series = this.subscription.data[i]; | |
433 | + var yaxisIndex = series.yaxisIndex; | |
434 | + if (this.yaxes[yaxisIndex].keysInfo[i].hidden != series.dataKey.hidden) { | |
435 | + this.yaxes[yaxisIndex].keysInfo[i].hidden = series.dataKey.hidden; | |
436 | + axisVisibilityChanged = true; | |
437 | + } | |
438 | + } | |
439 | + if (axisVisibilityChanged) { | |
440 | + this.options.yaxes.length = 0; | |
441 | + for (var y = 0; y < this.yaxes.length; y++) { | |
442 | + var yaxis = this.yaxes[y]; | |
443 | + var hidden = true; | |
444 | + for (var k = 0; k < yaxis.keysInfo.length; k++) { | |
445 | + if (yaxis.keysInfo[k]) { | |
446 | + hidden = hidden && yaxis.keysInfo[k].hidden; | |
447 | + } | |
448 | + } | |
449 | + yaxis.hidden = hidden | |
450 | + var newIndex = -1; | |
451 | + if (!yaxis.hidden) { | |
452 | + this.options.yaxes.push(yaxis); | |
453 | + newIndex = this.options.yaxes.length; | |
454 | + } | |
455 | + for (k = 0; k < yaxis.keysInfo.length; k++) { | |
456 | + if (yaxis.keysInfo[k]) { | |
457 | + this.subscription.data[k].yaxis = newIndex; | |
458 | + } | |
459 | + } | |
460 | + | |
461 | + } | |
462 | + this.options.yaxis = { | |
463 | + show: this.options.yaxes.length ? true : false | |
464 | + }; | |
465 | + } | |
466 | + } | |
467 | + | |
384 | 468 | this.options.xaxis.min = this.subscription.timeWindow.minTime; |
385 | 469 | this.options.xaxis.max = this.subscription.timeWindow.maxTime; |
386 | - this.ctx.plot.getOptions().xaxes[0].min = this.subscription.timeWindow.minTime; | |
387 | - this.ctx.plot.getOptions().xaxes[0].max = this.subscription.timeWindow.maxTime; | |
388 | 470 | if (this.chartType === 'bar') { |
389 | 471 | this.options.series.bars.barWidth = this.subscription.timeWindow.interval * 0.6; |
390 | - this.ctx.plot.getOptions().series.bars.barWidth = this.subscription.timeWindow.interval * 0.6; | |
391 | 472 | } |
392 | - this.ctx.plot.setData(this.subscription.data); | |
393 | - this.ctx.plot.setupGrid(); | |
394 | - this.ctx.plot.draw(); | |
473 | + | |
474 | + if (axisVisibilityChanged) { | |
475 | + this.redrawPlot(); | |
476 | + } else { | |
477 | + this.ctx.plot.getOptions().xaxes[0].min = this.subscription.timeWindow.minTime; | |
478 | + this.ctx.plot.getOptions().xaxes[0].max = this.subscription.timeWindow.maxTime; | |
479 | + if (this.chartType === 'bar') { | |
480 | + this.ctx.plot.getOptions().series.bars.barWidth = this.subscription.timeWindow.interval * 0.6; | |
481 | + } | |
482 | + this.ctx.plot.setData(this.subscription.data); | |
483 | + this.ctx.plot.setupGrid(); | |
484 | + this.ctx.plot.draw(); | |
485 | + } | |
395 | 486 | } else if (this.chartType === 'pie') { |
396 | 487 | if (this.ctx.animatedPie) { |
397 | 488 | this.nextPieDataAnimation(true); |
... | ... | @@ -720,6 +811,26 @@ export default class TbFlot { |
720 | 811 | "title": "Show points", |
721 | 812 | "type": "boolean", |
722 | 813 | "default": false |
814 | + }, | |
815 | + "showSeparateAxis": { | |
816 | + "title": "Show separate axis", | |
817 | + "type": "boolean", | |
818 | + "default": false | |
819 | + }, | |
820 | + "axisTitle": { | |
821 | + "title": "Axis title", | |
822 | + "type": "string", | |
823 | + "default": "" | |
824 | + }, | |
825 | + "axisTickDecimals": { | |
826 | + "title": "Axis tick number of digits after floating point", | |
827 | + "type": "number", | |
828 | + "default": 0 | |
829 | + }, | |
830 | + "axisPosition": { | |
831 | + "title": "Axis position", | |
832 | + "type": "string", | |
833 | + "default": "left" | |
723 | 834 | } |
724 | 835 | }, |
725 | 836 | "required": ["showLines", "fillLines", "showPoints"] |
... | ... | @@ -727,7 +838,26 @@ export default class TbFlot { |
727 | 838 | "form": [ |
728 | 839 | "showLines", |
729 | 840 | "fillLines", |
730 | - "showPoints" | |
841 | + "showPoints", | |
842 | + "showSeparateAxis", | |
843 | + "axisTitle", | |
844 | + "axisTickDecimals", | |
845 | + { | |
846 | + "key": "axisPosition", | |
847 | + "type": "rc-select", | |
848 | + "multiple": false, | |
849 | + "items": [ | |
850 | + { | |
851 | + "value": "left", | |
852 | + "label": "Left" | |
853 | + }, | |
854 | + { | |
855 | + "value": "right", | |
856 | + "label": "Right" | |
857 | + } | |
858 | + ] | |
859 | + } | |
860 | + | |
731 | 861 | ] |
732 | 862 | } |
733 | 863 | } |
... | ... | @@ -754,6 +884,17 @@ export default class TbFlot { |
754 | 884 | } |
755 | 885 | } |
756 | 886 | |
887 | + redrawPlot() { | |
888 | + if (this.ctx.plot) { | |
889 | + this.ctx.plot.destroy(); | |
890 | + if (this.chartType === 'pie' && this.ctx.animatedPie) { | |
891 | + this.ctx.plot = $.plot(this.$element, this.pieData, this.options); | |
892 | + } else { | |
893 | + this.ctx.plot = $.plot(this.$element, this.subscription.data, this.options); | |
894 | + } | |
895 | + } | |
896 | + } | |
897 | + | |
757 | 898 | destroy() { |
758 | 899 | if (this.ctx.plot) { |
759 | 900 | this.ctx.plot.destroy(); |
... | ... | @@ -968,6 +1109,8 @@ export default class TbFlot { |
968 | 1109 | hoverIndex: hoverIndex, |
969 | 1110 | color: series.dataKey.color, |
970 | 1111 | label: series.dataKey.label, |
1112 | + units: series.dataKey.units, | |
1113 | + decimals: series.dataKey.decimals, | |
971 | 1114 | time: pointTime, |
972 | 1115 | distance: hoverDistance, |
973 | 1116 | index: i | ... | ... |