Commit b855d82f7a2abc54d6701f69f8c097bfd24029de
Merge branch 'master' of github.com:thingsboard/thingsboard
Showing
8 changed files
with
81 additions
and
30 deletions
@@ -169,15 +169,7 @@ export default class Subscription { | @@ -169,15 +169,7 @@ export default class Subscription { | ||
169 | }); | 169 | }); |
170 | this.registrations.push(registration); | 170 | this.registrations.push(registration); |
171 | } else { | 171 | } else { |
172 | - registration = this.ctx.$scope.$watch(function () { | ||
173 | - return subscription.timeWindowConfig; | ||
174 | - }, function (newTimewindow, prevTimewindow) { | ||
175 | - if (!angular.equals(newTimewindow, prevTimewindow)) { | ||
176 | - subscription.unsubscribe(); | ||
177 | - subscription.subscribe(); | ||
178 | - } | ||
179 | - }); | ||
180 | - this.registrations.push(registration); | 172 | + this.startWatchingTimewindow(); |
181 | } | 173 | } |
182 | } | 174 | } |
183 | 175 | ||
@@ -188,6 +180,29 @@ export default class Subscription { | @@ -188,6 +180,29 @@ export default class Subscription { | ||
188 | this.registrations.push(registration); | 180 | this.registrations.push(registration); |
189 | } | 181 | } |
190 | 182 | ||
183 | + startWatchingTimewindow() { | ||
184 | + var subscription = this; | ||
185 | + this.timeWindowWatchRegistration = this.ctx.$scope.$watch(function () { | ||
186 | + return subscription.timeWindowConfig; | ||
187 | + }, function (newTimewindow, prevTimewindow) { | ||
188 | + if (!angular.equals(newTimewindow, prevTimewindow)) { | ||
189 | + subscription.unsubscribe(); | ||
190 | + subscription.subscribe(); | ||
191 | + } | ||
192 | + }, true); | ||
193 | + this.registrations.push(this.timeWindowWatchRegistration); | ||
194 | + } | ||
195 | + | ||
196 | + stopWatchingTimewindow() { | ||
197 | + if (this.timeWindowWatchRegistration) { | ||
198 | + this.timeWindowWatchRegistration(); | ||
199 | + var index = this.registrations.indexOf(this.timeWindowWatchRegistration); | ||
200 | + if (index > -1) { | ||
201 | + this.registrations.splice(index, 1); | ||
202 | + } | ||
203 | + } | ||
204 | + } | ||
205 | + | ||
191 | initRpc() { | 206 | initRpc() { |
192 | 207 | ||
193 | if (this.targetDeviceAliasIds && this.targetDeviceAliasIds.length > 0) { | 208 | if (this.targetDeviceAliasIds && this.targetDeviceAliasIds.length > 0) { |
@@ -335,9 +350,9 @@ export default class Subscription { | @@ -335,9 +350,9 @@ export default class Subscription { | ||
335 | var subscription = this; | 350 | var subscription = this; |
336 | this.cafs['dataUpdated'] = this.ctx.tbRaf(function() { | 351 | this.cafs['dataUpdated'] = this.ctx.tbRaf(function() { |
337 | try { | 352 | try { |
338 | - subscription.callbacks.onDataUpdated(this, apply); | 353 | + subscription.callbacks.onDataUpdated(subscription, apply); |
339 | } catch (e) { | 354 | } catch (e) { |
340 | - subscription.callbacks.onDataUpdateError(this, e); | 355 | + subscription.callbacks.onDataUpdateError(subscription, e); |
341 | } | 356 | } |
342 | }); | 357 | }); |
343 | if (apply) { | 358 | if (apply) { |
@@ -354,9 +369,13 @@ export default class Subscription { | @@ -354,9 +369,13 @@ export default class Subscription { | ||
354 | this.ctx.dashboardTimewindowApi.onResetTimewindow(); | 369 | this.ctx.dashboardTimewindowApi.onResetTimewindow(); |
355 | } else { | 370 | } else { |
356 | if (this.originalTimewindow) { | 371 | if (this.originalTimewindow) { |
372 | + this.stopWatchingTimewindow(); | ||
357 | this.timeWindowConfig = angular.copy(this.originalTimewindow); | 373 | this.timeWindowConfig = angular.copy(this.originalTimewindow); |
358 | this.originalTimewindow = null; | 374 | this.originalTimewindow = null; |
359 | this.callbacks.timeWindowUpdated(this, this.timeWindowConfig); | 375 | this.callbacks.timeWindowUpdated(this, this.timeWindowConfig); |
376 | + this.unsubscribe(); | ||
377 | + this.subscribe(); | ||
378 | + this.startWatchingTimewindow(); | ||
360 | } | 379 | } |
361 | } | 380 | } |
362 | } | 381 | } |
@@ -365,11 +384,15 @@ export default class Subscription { | @@ -365,11 +384,15 @@ export default class Subscription { | ||
365 | if (this.useDashboardTimewindow) { | 384 | if (this.useDashboardTimewindow) { |
366 | this.ctx.dashboardTimewindowApi.onUpdateTimewindow(startTimeMs, endTimeMs); | 385 | this.ctx.dashboardTimewindowApi.onUpdateTimewindow(startTimeMs, endTimeMs); |
367 | } else { | 386 | } else { |
387 | + this.stopWatchingTimewindow(); | ||
368 | if (!this.originalTimewindow) { | 388 | if (!this.originalTimewindow) { |
369 | this.originalTimewindow = angular.copy(this.timeWindowConfig); | 389 | this.originalTimewindow = angular.copy(this.timeWindowConfig); |
370 | } | 390 | } |
371 | this.timeWindowConfig = this.ctx.timeService.toHistoryTimewindow(this.timeWindowConfig, startTimeMs, endTimeMs); | 391 | this.timeWindowConfig = this.ctx.timeService.toHistoryTimewindow(this.timeWindowConfig, startTimeMs, endTimeMs); |
372 | this.callbacks.timeWindowUpdated(this, this.timeWindowConfig); | 392 | this.callbacks.timeWindowUpdated(this, this.timeWindowConfig); |
393 | + this.unsubscribe(); | ||
394 | + this.subscribe(); | ||
395 | + this.startWatchingTimewindow(); | ||
373 | } | 396 | } |
374 | } | 397 | } |
375 | 398 |
@@ -342,6 +342,7 @@ function Utils($mdColorPalette, $rootScope, $window, $q, deviceService, types) { | @@ -342,6 +342,7 @@ function Utils($mdColorPalette, $rootScope, $window, $q, deviceService, types) { | ||
342 | datasource = { | 342 | datasource = { |
343 | type: subscriptionInfo.type, | 343 | type: subscriptionInfo.type, |
344 | deviceName: device.name, | 344 | deviceName: device.name, |
345 | + name: device.name, | ||
345 | deviceId: device.id.id, | 346 | deviceId: device.id.id, |
346 | dataKeys: [] | 347 | dataKeys: [] |
347 | } | 348 | } |
@@ -72,7 +72,7 @@ export default function AttributeTableDirective($compile, $templateCache, $rootS | @@ -72,7 +72,7 @@ export default function AttributeTableDirective($compile, $templateCache, $rootS | ||
72 | scope.$watch("deviceId", function(newVal, prevVal) { | 72 | scope.$watch("deviceId", function(newVal, prevVal) { |
73 | if (newVal && !angular.equals(newVal, prevVal)) { | 73 | if (newVal && !angular.equals(newVal, prevVal)) { |
74 | scope.resetFilter(); | 74 | scope.resetFilter(); |
75 | - scope.getDeviceAttributes(); | 75 | + scope.getDeviceAttributes(false, true); |
76 | } | 76 | } |
77 | }); | 77 | }); |
78 | 78 | ||
@@ -81,7 +81,7 @@ export default function AttributeTableDirective($compile, $templateCache, $rootS | @@ -81,7 +81,7 @@ export default function AttributeTableDirective($compile, $templateCache, $rootS | ||
81 | scope.mode = 'default'; | 81 | scope.mode = 'default'; |
82 | scope.query.search = null; | 82 | scope.query.search = null; |
83 | scope.selectedAttributes = []; | 83 | scope.selectedAttributes = []; |
84 | - scope.getDeviceAttributes(); | 84 | + scope.getDeviceAttributes(false, true); |
85 | } | 85 | } |
86 | }); | 86 | }); |
87 | 87 | ||
@@ -117,15 +117,25 @@ export default function AttributeTableDirective($compile, $templateCache, $rootS | @@ -117,15 +117,25 @@ export default function AttributeTableDirective($compile, $templateCache, $rootS | ||
117 | } | 117 | } |
118 | } | 118 | } |
119 | 119 | ||
120 | - scope.getDeviceAttributes = function(forceUpdate) { | 120 | + scope.onReorder = function() { |
121 | + scope.getDeviceAttributes(false, false); | ||
122 | + } | ||
123 | + | ||
124 | + scope.onPaginate = function() { | ||
125 | + scope.getDeviceAttributes(false, false); | ||
126 | + } | ||
127 | + | ||
128 | + scope.getDeviceAttributes = function(forceUpdate, reset) { | ||
121 | if (scope.attributesDeferred) { | 129 | if (scope.attributesDeferred) { |
122 | scope.attributesDeferred.resolve(); | 130 | scope.attributesDeferred.resolve(); |
123 | } | 131 | } |
124 | if (scope.deviceId && scope.attributeScope) { | 132 | if (scope.deviceId && scope.attributeScope) { |
125 | - scope.attributes = { | ||
126 | - count: 0, | ||
127 | - data: [] | ||
128 | - }; | 133 | + if (reset) { |
134 | + scope.attributes = { | ||
135 | + count: 0, | ||
136 | + data: [] | ||
137 | + }; | ||
138 | + } | ||
129 | scope.checkSubscription(); | 139 | scope.checkSubscription(); |
130 | scope.attributesDeferred = deviceService.getDeviceAttributes(scope.deviceId, scope.attributeScope.value, | 140 | scope.attributesDeferred = deviceService.getDeviceAttributes(scope.deviceId, scope.attributeScope.value, |
131 | scope.query, function(attributes, update, apply) { | 141 | scope.query, function(attributes, update, apply) { |
@@ -126,7 +126,7 @@ | @@ -126,7 +126,7 @@ | ||
126 | </md-toolbar> | 126 | </md-toolbar> |
127 | <md-table-container ng-show="mode!='widget'"> | 127 | <md-table-container ng-show="mode!='widget'"> |
128 | <table md-table md-row-select multiple="" ng-model="selectedAttributes" md-progress="attributesDeferred.promise"> | 128 | <table md-table md-row-select multiple="" ng-model="selectedAttributes" md-progress="attributesDeferred.promise"> |
129 | - <thead md-head md-order="query.order" md-on-reorder="getDeviceAttributes"> | 129 | + <thead md-head md-order="query.order" md-on-reorder="onReorder"> |
130 | <tr md-row> | 130 | <tr md-row> |
131 | <th md-column md-order-by="lastUpdateTs"><span>Last update time</span></th> | 131 | <th md-column md-order-by="lastUpdateTs"><span>Last update time</span></th> |
132 | <th md-column md-order-by="key"><span>Key</span></th> | 132 | <th md-column md-order-by="key"><span>Key</span></th> |
@@ -147,7 +147,7 @@ | @@ -147,7 +147,7 @@ | ||
147 | </md-table-container> | 147 | </md-table-container> |
148 | <md-table-pagination ng-show="mode!='widget'" md-limit="query.limit" md-limit-options="[5, 10, 15]" | 148 | <md-table-pagination ng-show="mode!='widget'" md-limit="query.limit" md-limit-options="[5, 10, 15]" |
149 | md-page="query.page" md-total="{{attributes.count}}" | 149 | md-page="query.page" md-total="{{attributes.count}}" |
150 | - md-on-paginate="getDeviceAttributes" md-page-select> | 150 | + md-on-paginate="onPaginate" md-page-select> |
151 | </md-table-pagination> | 151 | </md-table-pagination> |
152 | <ul flex rn-carousel ng-if="mode==='widget'" class="widgets-carousel" | 152 | <ul flex rn-carousel ng-if="mode==='widget'" class="widgets-carousel" |
153 | rn-carousel-index="widgetsCarousel.index" | 153 | rn-carousel-index="widgetsCarousel.index" |
@@ -374,6 +374,10 @@ export default class TbFlot { | @@ -374,6 +374,10 @@ export default class TbFlot { | ||
374 | } | 374 | } |
375 | 375 | ||
376 | update() { | 376 | update() { |
377 | + if (this.updateTimeoutHandle) { | ||
378 | + this.ctx.$scope.$timeout.cancel(this.updateTimeoutHandle); | ||
379 | + this.updateTimeoutHandle = null; | ||
380 | + } | ||
377 | if (this.subscription) { | 381 | if (this.subscription) { |
378 | if (!this.isMouseInteraction && this.ctx.plot) { | 382 | if (!this.isMouseInteraction && this.ctx.plot) { |
379 | if (this.chartType === 'line' || this.chartType === 'bar') { | 383 | if (this.chartType === 'line' || this.chartType === 'bar') { |
@@ -396,6 +400,11 @@ export default class TbFlot { | @@ -396,6 +400,11 @@ export default class TbFlot { | ||
396 | this.ctx.plot.draw(); | 400 | this.ctx.plot.draw(); |
397 | } | 401 | } |
398 | } | 402 | } |
403 | + } else if (this.isMouseInteraction && this.ctx.plot){ | ||
404 | + var tbFlot = this; | ||
405 | + this.updateTimeoutHandle = this.ctx.$scope.$timeout(function() { | ||
406 | + tbFlot.update(); | ||
407 | + }, 30, false); | ||
399 | } | 408 | } |
400 | } | 409 | } |
401 | } | 410 | } |
@@ -217,7 +217,9 @@ export default class TbGoogleMap { | @@ -217,7 +217,9 @@ export default class TbGoogleMap { | ||
217 | this.updateMarkerImage(marker, settings, settings.markerImage, settings.markerImageSize || 34); | 217 | this.updateMarkerImage(marker, settings, settings.markerImage, settings.markerImageSize || 34); |
218 | } | 218 | } |
219 | 219 | ||
220 | - this.createTooltip(marker, settings.tooltipPattern, settings.tooltipReplaceInfo); | 220 | + if (settings.displayTooltip) { |
221 | + this.createTooltip(marker, settings.tooltipPattern, settings.tooltipReplaceInfo); | ||
222 | + } | ||
221 | 223 | ||
222 | if (onClickListener) { | 224 | if (onClickListener) { |
223 | marker.addListener('click', onClickListener); | 225 | marker.addListener('click', onClickListener); |
@@ -19,7 +19,7 @@ import tinycolor from 'tinycolor2'; | @@ -19,7 +19,7 @@ import tinycolor from 'tinycolor2'; | ||
19 | import TbGoogleMap from './google-map'; | 19 | import TbGoogleMap from './google-map'; |
20 | import TbOpenStreetMap from './openstreet-map'; | 20 | import TbOpenStreetMap from './openstreet-map'; |
21 | 21 | ||
22 | -function procesTooltipPattern(tbMap, pattern, datasources) { | 22 | +function procesTooltipPattern(tbMap, pattern, datasources, dsIndex) { |
23 | var match = tbMap.varsRegex.exec(pattern); | 23 | var match = tbMap.varsRegex.exec(pattern); |
24 | var replaceInfo = {}; | 24 | var replaceInfo = {}; |
25 | replaceInfo.variables = []; | 25 | replaceInfo.variables = []; |
@@ -48,11 +48,13 @@ function procesTooltipPattern(tbMap, pattern, datasources) { | @@ -48,11 +48,13 @@ function procesTooltipPattern(tbMap, pattern, datasources) { | ||
48 | var offset = 0; | 48 | var offset = 0; |
49 | for (var i=0;i<datasources.length;i++) { | 49 | for (var i=0;i<datasources.length;i++) { |
50 | var datasource = datasources[i]; | 50 | var datasource = datasources[i]; |
51 | - for (var k = 0; k < datasource.dataKeys.length; k++) { | ||
52 | - var dataKey = datasource.dataKeys[k]; | ||
53 | - if (dataKey.label === label) { | ||
54 | - variableInfo.dataKeyIndex = offset + k; | ||
55 | - break; | 51 | + if (angular.isUndefined(dsIndex) || dsIndex == i) { |
52 | + for (var k = 0; k < datasource.dataKeys.length; k++) { | ||
53 | + var dataKey = datasource.dataKeys[k]; | ||
54 | + if (dataKey.label === label) { | ||
55 | + variableInfo.dataKeyIndex = offset + k; | ||
56 | + break; | ||
57 | + } | ||
56 | } | 58 | } |
57 | } | 59 | } |
58 | offset += datasource.dataKeys.length; | 60 | offset += datasource.dataKeys.length; |
@@ -168,6 +170,7 @@ export default class TbMapWidget { | @@ -168,6 +170,7 @@ export default class TbMapWidget { | ||
168 | latKeyName: localLatKeyName, | 170 | latKeyName: localLatKeyName, |
169 | lngKeyName: localLngKeyName, | 171 | lngKeyName: localLngKeyName, |
170 | showLabel: subscriptionLocationSettings.showLabel !== false, | 172 | showLabel: subscriptionLocationSettings.showLabel !== false, |
173 | + displayTooltip: subscriptionLocationSettings.displayTooltip !== false, | ||
171 | label: datasource.name, | 174 | label: datasource.name, |
172 | labelColor: this.ctx.widgetConfig.color || '#000000', | 175 | labelColor: this.ctx.widgetConfig.color || '#000000', |
173 | color: "#FE7569", | 176 | color: "#FE7569", |
@@ -179,10 +182,10 @@ export default class TbMapWidget { | @@ -179,10 +182,10 @@ export default class TbMapWidget { | ||
179 | useMarkerImageFunction: false, | 182 | useMarkerImageFunction: false, |
180 | markerImageFunction: null, | 183 | markerImageFunction: null, |
181 | markerImages: [], | 184 | markerImages: [], |
182 | - tooltipPattern: "<b>Latitude:</b> ${#"+latKeyIndex+":7}<br/><b>Longitude:</b> ${#"+lngKeyIndex+":7}" | 185 | + tooltipPattern: subscriptionLocationSettings.tooltipPattern || "<b>Latitude:</b> ${latitude:7}<br/><b>Longitude:</b> ${longitude:7}" |
183 | }; | 186 | }; |
184 | 187 | ||
185 | - locationsSettings.tooltipReplaceInfo = procesTooltipPattern(this, locationsSettings.tooltipPattern, this.subscription.datasources); | 188 | + locationsSettings.tooltipReplaceInfo = procesTooltipPattern(this, locationsSettings.tooltipPattern, this.subscription.datasources, i); |
186 | 189 | ||
187 | locationsSettings.useColorFunction = subscriptionLocationSettings.useColorFunction === true; | 190 | locationsSettings.useColorFunction = subscriptionLocationSettings.useColorFunction === true; |
188 | if (angular.isDefined(subscriptionLocationSettings.colorFunction) && subscriptionLocationSettings.colorFunction.length > 0) { | 191 | if (angular.isDefined(subscriptionLocationSettings.colorFunction) && subscriptionLocationSettings.colorFunction.length > 0) { |
@@ -211,6 +214,7 @@ export default class TbMapWidget { | @@ -211,6 +214,7 @@ export default class TbMapWidget { | ||
211 | latKeyName: "lat", | 214 | latKeyName: "lat", |
212 | lngKeyName: "lng", | 215 | lngKeyName: "lng", |
213 | showLabel: true, | 216 | showLabel: true, |
217 | + displayTooltip: true, | ||
214 | label: "", | 218 | label: "", |
215 | labelColor: this.ctx.widgetConfig.color || '#000000', | 219 | labelColor: this.ctx.widgetConfig.color || '#000000', |
216 | color: "#FE7569", | 220 | color: "#FE7569", |
@@ -109,7 +109,9 @@ export default class TbOpenStreetMap { | @@ -109,7 +109,9 @@ export default class TbOpenStreetMap { | ||
109 | this.updateMarkerImage(marker, settings, settings.markerImage, settings.markerImageSize || 34); | 109 | this.updateMarkerImage(marker, settings, settings.markerImage, settings.markerImageSize || 34); |
110 | } | 110 | } |
111 | 111 | ||
112 | - this.createTooltip(marker, settings.tooltipPattern, settings.tooltipReplaceInfo); | 112 | + if (settings.displayTooltip) { |
113 | + this.createTooltip(marker, settings.tooltipPattern, settings.tooltipReplaceInfo); | ||
114 | + } | ||
113 | 115 | ||
114 | if (onClickListener) { | 116 | if (onClickListener) { |
115 | marker.on('click', onClickListener); | 117 | marker.on('click', onClickListener); |