Showing
22 changed files
with
363 additions
and
580 deletions
@@ -100,6 +100,7 @@ export default class AliasController { | @@ -100,6 +100,7 @@ export default class AliasController { | ||
100 | aliasCtrl.resolvedAliasesToStateEntities[aliasId] = | 100 | aliasCtrl.resolvedAliasesToStateEntities[aliasId] = |
101 | aliasCtrl.stateController.getStateParams().entityId; | 101 | aliasCtrl.stateController.getStateParams().entityId; |
102 | } | 102 | } |
103 | + aliasCtrl.$scope.$broadcast('entityAliasResolved', aliasId); | ||
103 | deferred.resolve(aliasInfo); | 104 | deferred.resolve(aliasInfo); |
104 | }, | 105 | }, |
105 | function fail() { | 106 | function fail() { |
@@ -239,6 +240,9 @@ export default class AliasController { | @@ -239,6 +240,9 @@ export default class AliasController { | ||
239 | datasource.name = name; | 240 | datasource.name = name; |
240 | datasource.aliasName = name; | 241 | datasource.aliasName = name; |
241 | datasource.entityName = name; | 242 | datasource.entityName = name; |
243 | + } else if (datasource.unresolvedStateEntity) { | ||
244 | + datasource.name = "Unresolved"; | ||
245 | + datasource.entityName = "Unresolved"; | ||
242 | } | 246 | } |
243 | datasource.dataKeys.forEach(function(dataKey) { | 247 | datasource.dataKeys.forEach(function(dataKey) { |
244 | if (datasource.generated) { | 248 | if (datasource.generated) { |
@@ -73,6 +73,15 @@ export default class Subscription { | @@ -73,6 +73,15 @@ export default class Subscription { | ||
73 | 73 | ||
74 | this.datasources = this.ctx.utils.validateDatasources(options.datasources); | 74 | this.datasources = this.ctx.utils.validateDatasources(options.datasources); |
75 | this.datasourceListeners = []; | 75 | this.datasourceListeners = []; |
76 | + | ||
77 | + /* | ||
78 | + * data = array of datasourceData | ||
79 | + * datasourceData = { | ||
80 | + * tbDatasource, | ||
81 | + * dataKey, { name, config } | ||
82 | + * data = array of [time, value] | ||
83 | + * } | ||
84 | + */ | ||
76 | this.data = []; | 85 | this.data = []; |
77 | this.hiddenData = []; | 86 | this.hiddenData = []; |
78 | this.originalTimewindow = null; | 87 | this.originalTimewindow = null; |
@@ -543,39 +552,6 @@ export default class Subscription { | @@ -543,39 +552,6 @@ export default class Subscription { | ||
543 | var datasource = this.datasources[i]; | 552 | var datasource = this.datasources[i]; |
544 | if (angular.isFunction(datasource)) | 553 | if (angular.isFunction(datasource)) |
545 | continue; | 554 | continue; |
546 | - /* var entityId = null; | ||
547 | - var entityType = null; | ||
548 | - if (datasource.type === this.ctx.types.datasourceType.entity) { | ||
549 | - var aliasName = null; | ||
550 | - var entityName = null; | ||
551 | - if (datasource.entityId) { | ||
552 | - entityId = datasource.entityId; | ||
553 | - entityType = datasource.entityType; | ||
554 | - datasource.name = datasource.entityName; | ||
555 | - aliasName = datasource.entityName; | ||
556 | - entityName = datasource.entityName; | ||
557 | - } else if (datasource.entityAliasId) { | ||
558 | - if (this.ctx.aliasesInfo.entityAliases[datasource.entityAliasId]) { | ||
559 | - entityId = this.ctx.aliasesInfo.entityAliases[datasource.entityAliasId].entityId; | ||
560 | - entityType = this.ctx.aliasesInfo.entityAliases[datasource.entityAliasId].entityType; | ||
561 | - datasource.name = this.ctx.aliasesInfo.entityAliases[datasource.entityAliasId].alias; | ||
562 | - aliasName = this.ctx.aliasesInfo.entityAliases[datasource.entityAliasId].alias; | ||
563 | - entityName = ''; | ||
564 | - var entitiesInfo = this.ctx.aliasesInfo.entityAliasesInfo[datasource.entityAliasId]; | ||
565 | - for (var d = 0; d < entitiesInfo.length; d++) { | ||
566 | - if (entitiesInfo[d].id === entityId) { | ||
567 | - entityName = entitiesInfo[d].name; | ||
568 | - break; | ||
569 | - } | ||
570 | - } | ||
571 | - } | ||
572 | - } | ||
573 | - } else { | ||
574 | - datasource.name = datasource.name || this.ctx.types.datasourceType.function; | ||
575 | - } | ||
576 | - for (var dk = 0; dk < datasource.dataKeys.length; dk++) { | ||
577 | - updateDataKeyLabel(datasource.dataKeys[dk], datasource.name, entityName, aliasName); | ||
578 | - }*/ | ||
579 | 555 | ||
580 | var subscription = this; | 556 | var subscription = this; |
581 | 557 | ||
@@ -606,6 +582,10 @@ export default class Subscription { | @@ -606,6 +582,10 @@ export default class Subscription { | ||
606 | 582 | ||
607 | this.datasourceListeners.push(listener); | 583 | this.datasourceListeners.push(listener); |
608 | this.ctx.datasourceService.subscribeToDatasource(listener); | 584 | this.ctx.datasourceService.subscribeToDatasource(listener); |
585 | + if (datasource.unresolvedStateEntity) { | ||
586 | + this.notifyDataLoaded(); | ||
587 | + this.onDataUpdated(); | ||
588 | + } | ||
609 | } | 589 | } |
610 | } | 590 | } |
611 | 591 | ||
@@ -625,19 +605,6 @@ export default class Subscription { | @@ -625,19 +605,6 @@ export default class Subscription { | ||
625 | } else { | 605 | } else { |
626 | return false; | 606 | return false; |
627 | } | 607 | } |
628 | - /*var deviceId = null; | ||
629 | - if (this.ctx.aliasesInfo.entityAliases[this.targetDeviceAliasId]) { | ||
630 | - deviceId = this.ctx.aliasesInfo.entityAliases[this.targetDeviceAliasId].entityId; | ||
631 | - } | ||
632 | - if (!angular.equals(deviceId, this.targetDeviceId)) { | ||
633 | - this.targetDeviceId = deviceId; | ||
634 | - if (this.targetDeviceId) { | ||
635 | - this.rpcEnabled = true; | ||
636 | - } else { | ||
637 | - this.rpcEnabled = this.ctx.$scope.widgetEditMode ? true : false; | ||
638 | - } | ||
639 | - this.callbacks.rpcStateChanged(this); | ||
640 | - }*/ | ||
641 | } | 608 | } |
642 | 609 | ||
643 | checkSubscriptions(aliasIds) { | 610 | checkSubscriptions(aliasIds) { |
@@ -650,29 +617,8 @@ export default class Subscription { | @@ -650,29 +617,8 @@ export default class Subscription { | ||
650 | break; | 617 | break; |
651 | } | 618 | } |
652 | } | 619 | } |
653 | - /*var entityId = null; | ||
654 | - var entityType = null; | ||
655 | - var aliasName = null; | ||
656 | - if (listener.datasource.type === this.ctx.types.datasourceType.entity) { | ||
657 | - if (listener.datasource.entityAliasId && | ||
658 | - this.ctx.aliasesInfo.entityAliases[listener.datasource.entityAliasId]) { | ||
659 | - entityId = this.ctx.aliasesInfo.entityAliases[listener.datasource.entityAliasId].entityId; | ||
660 | - entityType = this.ctx.aliasesInfo.entityAliases[listener.datasource.entityAliasId].entityType; | ||
661 | - aliasName = this.ctx.aliasesInfo.entityAliases[listener.datasource.entityAliasId].alias; | ||
662 | - } | ||
663 | - if (!angular.equals(entityId, listener.entityId) || | ||
664 | - !angular.equals(entityType, listener.entityType) || | ||
665 | - !angular.equals(aliasName, listener.datasource.name)) { | ||
666 | - subscriptionsChanged = true; | ||
667 | - break; | ||
668 | - } | ||
669 | - }*/ | ||
670 | } | 620 | } |
671 | return subscriptionsChanged; | 621 | return subscriptionsChanged; |
672 | - /*if (subscriptionsChanged) { | ||
673 | - this.unsubscribe(); | ||
674 | - this.subscribe(); | ||
675 | - }*/ | ||
676 | } | 622 | } |
677 | 623 | ||
678 | destroy() { | 624 | destroy() { |
@@ -691,29 +637,6 @@ export default class Subscription { | @@ -691,29 +637,6 @@ export default class Subscription { | ||
691 | 637 | ||
692 | } | 638 | } |
693 | 639 | ||
694 | -/*const varsRegex = /\$\{([^\}]*)\}/g; | ||
695 | - | ||
696 | -function updateDataKeyLabel(dataKey, dsName, entityName, aliasName) { | ||
697 | - var pattern = dataKey.pattern; | ||
698 | - var label = dataKey.pattern; | ||
699 | - var match = varsRegex.exec(pattern); | ||
700 | - while (match !== null) { | ||
701 | - var variable = match[0]; | ||
702 | - var variableName = match[1]; | ||
703 | - if (variableName === 'dsName') { | ||
704 | - label = label.split(variable).join(dsName); | ||
705 | - } else if (variableName === 'entityName') { | ||
706 | - label = label.split(variable).join(entityName); | ||
707 | - } else if (variableName === 'deviceName') { | ||
708 | - label = label.split(variable).join(entityName); | ||
709 | - } else if (variableName === 'aliasName') { | ||
710 | - label = label.split(variable).join(aliasName); | ||
711 | - } | ||
712 | - match = varsRegex.exec(pattern); | ||
713 | - } | ||
714 | - dataKey.label = label; | ||
715 | -}*/ | ||
716 | - | ||
717 | function calculateMin(data) { | 640 | function calculateMin(data) { |
718 | if (data.length > 0) { | 641 | if (data.length > 0) { |
719 | var result = Number(data[0][1]); | 642 | var result = Number(data[0][1]); |
@@ -23,8 +23,10 @@ function DashboardUtils(types, utils, timeService) { | @@ -23,8 +23,10 @@ function DashboardUtils(types, utils, timeService) { | ||
23 | 23 | ||
24 | var service = { | 24 | var service = { |
25 | validateAndUpdateDashboard: validateAndUpdateDashboard, | 25 | validateAndUpdateDashboard: validateAndUpdateDashboard, |
26 | + validateAndUpdateWidget: validateAndUpdateWidget, | ||
26 | getRootStateId: getRootStateId, | 27 | getRootStateId: getRootStateId, |
27 | createSingleWidgetDashboard: createSingleWidgetDashboard, | 28 | createSingleWidgetDashboard: createSingleWidgetDashboard, |
29 | + createSingleEntityFilter: createSingleEntityFilter, | ||
28 | getStateLayoutsData: getStateLayoutsData, | 30 | getStateLayoutsData: getStateLayoutsData, |
29 | createDefaultState: createDefaultState, | 31 | createDefaultState: createDefaultState, |
30 | createDefaultLayoutData: createDefaultLayoutData, | 32 | createDefaultLayoutData: createDefaultLayoutData, |
@@ -39,7 +41,7 @@ function DashboardUtils(types, utils, timeService) { | @@ -39,7 +41,7 @@ function DashboardUtils(types, utils, timeService) { | ||
39 | 41 | ||
40 | return service; | 42 | return service; |
41 | 43 | ||
42 | - function validateAndUpdateEntityAliases(configuration) { | 44 | + function validateAndUpdateEntityAliases(configuration, datasourcesByAliasId, targetDevicesByAliasId) { |
43 | var aliasId, entityAlias; | 45 | var aliasId, entityAlias; |
44 | if (angular.isUndefined(configuration.entityAliases)) { | 46 | if (angular.isUndefined(configuration.entityAliases)) { |
45 | configuration.entityAliases = {}; | 47 | configuration.entityAliases = {}; |
@@ -47,8 +49,8 @@ function DashboardUtils(types, utils, timeService) { | @@ -47,8 +49,8 @@ function DashboardUtils(types, utils, timeService) { | ||
47 | var deviceAliases = configuration.deviceAliases; | 49 | var deviceAliases = configuration.deviceAliases; |
48 | for (aliasId in deviceAliases) { | 50 | for (aliasId in deviceAliases) { |
49 | var deviceAlias = deviceAliases[aliasId]; | 51 | var deviceAlias = deviceAliases[aliasId]; |
50 | - entityAlias = validateAndUpdateDeviceAlias(aliasId, deviceAlias); | ||
51 | - configuration.entityAliases[aliasId] = entityAlias; | 52 | + entityAlias = validateAndUpdateDeviceAlias(aliasId, deviceAlias, datasourcesByAliasId, targetDevicesByAliasId); |
53 | + configuration.entityAliases[entityAlias.id] = entityAlias; | ||
52 | } | 54 | } |
53 | delete configuration.deviceAliases; | 55 | delete configuration.deviceAliases; |
54 | } | 56 | } |
@@ -56,16 +58,43 @@ function DashboardUtils(types, utils, timeService) { | @@ -56,16 +58,43 @@ function DashboardUtils(types, utils, timeService) { | ||
56 | var entityAliases = configuration.entityAliases; | 58 | var entityAliases = configuration.entityAliases; |
57 | for (aliasId in entityAliases) { | 59 | for (aliasId in entityAliases) { |
58 | entityAlias = entityAliases[aliasId]; | 60 | entityAlias = entityAliases[aliasId]; |
59 | - entityAliases[aliasId] = validateAndUpdateEntityAlias(entityAlias); | ||
60 | - if (!entityAliases[aliasId].id) { | ||
61 | - entityAliases[aliasId].id = aliasId; | 61 | + entityAlias = validateAndUpdateEntityAlias(aliasId, entityAlias, datasourcesByAliasId, targetDevicesByAliasId); |
62 | + if (aliasId != entityAlias.id) { | ||
63 | + delete entityAliases[aliasId]; | ||
62 | } | 64 | } |
65 | + entityAliases[entityAlias.id] = entityAlias; | ||
63 | } | 66 | } |
64 | } | 67 | } |
65 | return configuration; | 68 | return configuration; |
66 | } | 69 | } |
67 | 70 | ||
68 | - function validateAndUpdateDeviceAlias(aliasId, deviceAlias) { | 71 | + function validateAliasId(aliasId, datasourcesByAliasId, targetDevicesByAliasId) { |
72 | + if (!aliasId || !angular.isString(aliasId) || aliasId.length != 36) { | ||
73 | + var newAliasId = utils.guid(); | ||
74 | + var aliasDatasources = datasourcesByAliasId[aliasId]; | ||
75 | + if (aliasDatasources) { | ||
76 | + aliasDatasources.forEach( | ||
77 | + function(datasource) { | ||
78 | + datasource.entityAliasId = newAliasId; | ||
79 | + } | ||
80 | + ); | ||
81 | + } | ||
82 | + var targetDeviceAliasIdsList = targetDevicesByAliasId[aliasId]; | ||
83 | + if (targetDeviceAliasIdsList) { | ||
84 | + targetDeviceAliasIdsList.forEach( | ||
85 | + function(targetDeviceAliasIds) { | ||
86 | + targetDeviceAliasIds[0] = newAliasId; | ||
87 | + } | ||
88 | + ); | ||
89 | + } | ||
90 | + return newAliasId; | ||
91 | + } else { | ||
92 | + return aliasId; | ||
93 | + } | ||
94 | + } | ||
95 | + | ||
96 | + function validateAndUpdateDeviceAlias(aliasId, deviceAlias, datasourcesByAliasId, targetDevicesByAliasId) { | ||
97 | + aliasId = validateAliasId(aliasId, datasourcesByAliasId, targetDevicesByAliasId); | ||
69 | var alias = deviceAlias.alias; | 98 | var alias = deviceAlias.alias; |
70 | var entityAlias = { | 99 | var entityAlias = { |
71 | id: aliasId, | 100 | id: aliasId, |
@@ -93,7 +122,8 @@ function DashboardUtils(types, utils, timeService) { | @@ -93,7 +122,8 @@ function DashboardUtils(types, utils, timeService) { | ||
93 | return entityAlias; | 122 | return entityAlias; |
94 | } | 123 | } |
95 | 124 | ||
96 | - function validateAndUpdateEntityAlias(entityAlias) { | 125 | + function validateAndUpdateEntityAlias(aliasId, entityAlias, datasourcesByAliasId, targetDevicesByAliasId) { |
126 | + entityAlias.id = validateAliasId(aliasId, datasourcesByAliasId, targetDevicesByAliasId); | ||
97 | if (!entityAlias.filter) { | 127 | if (!entityAlias.filter) { |
98 | entityAlias.filter = { | 128 | entityAlias.filter = { |
99 | type: entityAlias.entityFilter.useFilter ? types.aliasFilterType.entityName.value : types.aliasFilterType.entityList.value, | 129 | type: entityAlias.entityFilter.useFilter ? types.aliasFilterType.entityName.value : types.aliasFilterType.entityList.value, |
@@ -206,12 +236,33 @@ function DashboardUtils(types, utils, timeService) { | @@ -206,12 +236,33 @@ function DashboardUtils(types, utils, timeService) { | ||
206 | } | 236 | } |
207 | } | 237 | } |
208 | 238 | ||
209 | - /* var datasources = {}; | 239 | + var datasourcesByAliasId = {}; |
240 | + var targetDevicesByAliasId = {}; | ||
210 | for (var widgetId in dashboard.configuration.widgets) { | 241 | for (var widgetId in dashboard.configuration.widgets) { |
242 | + widget = dashboard.configuration.widgets[widgetId]; | ||
243 | + widget.config.datasources.forEach(function (datasource) { | ||
244 | + if (datasource.entityAliasId) { | ||
245 | + var aliasId = datasource.entityAliasId; | ||
246 | + var aliasDatasources = datasourcesByAliasId[aliasId]; | ||
247 | + if (!aliasDatasources) { | ||
248 | + aliasDatasources = []; | ||
249 | + datasourcesByAliasId[aliasId] = aliasDatasources; | ||
250 | + } | ||
251 | + aliasDatasources.push(datasource); | ||
252 | + } | ||
253 | + }); | ||
254 | + if (widget.config.targetDeviceAliasIds && widget.config.targetDeviceAliasIds.length) { | ||
255 | + var aliasId = widget.config.targetDeviceAliasIds[0]; | ||
256 | + var targetDeviceAliasIdsList = targetDevicesByAliasId[aliasId]; | ||
257 | + if (!targetDeviceAliasIdsList) { | ||
258 | + targetDeviceAliasIdsList = []; | ||
259 | + targetDevicesByAliasId[aliasId] = targetDeviceAliasIdsList; | ||
260 | + } | ||
261 | + targetDeviceAliasIdsList.push(widget.config.targetDeviceAliasIds); | ||
262 | + } | ||
263 | + } | ||
211 | 264 | ||
212 | - }*/ | ||
213 | - | ||
214 | - dashboard.configuration = validateAndUpdateEntityAliases(dashboard.configuration); | 265 | + dashboard.configuration = validateAndUpdateEntityAliases(dashboard.configuration, datasourcesByAliasId, targetDevicesByAliasId); |
215 | 266 | ||
216 | if (angular.isUndefined(dashboard.configuration.timewindow)) { | 267 | if (angular.isUndefined(dashboard.configuration.timewindow)) { |
217 | dashboard.configuration.timewindow = timeService.defaultTimewindow(); | 268 | dashboard.configuration.timewindow = timeService.defaultTimewindow(); |
@@ -288,6 +339,16 @@ function DashboardUtils(types, utils, timeService) { | @@ -288,6 +339,16 @@ function DashboardUtils(types, utils, timeService) { | ||
288 | return dashboard; | 339 | return dashboard; |
289 | } | 340 | } |
290 | 341 | ||
342 | + function createSingleEntityFilter(entityType, entityId) { | ||
343 | + return { | ||
344 | + type: types.aliasFilterType.entityList.value, | ||
345 | + stateEntity: false, | ||
346 | + entityList: [entityId], | ||
347 | + entityType: entityType, | ||
348 | + resolveMultiple: false | ||
349 | + }; | ||
350 | + } | ||
351 | + | ||
291 | function getStateLayoutsData(dashboard, targetState) { | 352 | function getStateLayoutsData(dashboard, targetState) { |
292 | var dashboardConfiguration = dashboard.configuration; | 353 | var dashboardConfiguration = dashboard.configuration; |
293 | var states = dashboardConfiguration.states; | 354 | var states = dashboardConfiguration.states; |
@@ -106,6 +106,7 @@ function Utils($mdColorPalette, $rootScope, $window, types) { | @@ -106,6 +106,7 @@ function Utils($mdColorPalette, $rootScope, $window, types) { | ||
106 | isDescriptorSchemaNotEmpty: isDescriptorSchemaNotEmpty, | 106 | isDescriptorSchemaNotEmpty: isDescriptorSchemaNotEmpty, |
107 | filterSearchTextEntities: filterSearchTextEntities, | 107 | filterSearchTextEntities: filterSearchTextEntities, |
108 | guid: guid, | 108 | guid: guid, |
109 | + cleanCopy: cleanCopy, | ||
109 | isLocalUrl: isLocalUrl, | 110 | isLocalUrl: isLocalUrl, |
110 | validateDatasources: validateDatasources, | 111 | validateDatasources: validateDatasources, |
111 | createKey: createKey, | 112 | createKey: createKey, |
@@ -291,6 +292,16 @@ function Utils($mdColorPalette, $rootScope, $window, types) { | @@ -291,6 +292,16 @@ function Utils($mdColorPalette, $rootScope, $window, types) { | ||
291 | s4() + '-' + s4() + s4() + s4(); | 292 | s4() + '-' + s4() + s4() + s4(); |
292 | } | 293 | } |
293 | 294 | ||
295 | + function cleanCopy(object) { | ||
296 | + var copy = angular.copy(object); | ||
297 | + for (var prop in copy) { | ||
298 | + if (prop && prop.startsWith('$$')) { | ||
299 | + delete copy[prop]; | ||
300 | + } | ||
301 | + } | ||
302 | + return copy; | ||
303 | + } | ||
304 | + | ||
294 | function genNextColor(datasources) { | 305 | function genNextColor(datasources) { |
295 | var index = 0; | 306 | var index = 0; |
296 | if (datasources) { | 307 | if (datasources) { |
@@ -85,7 +85,7 @@ function Dashboard() { | @@ -85,7 +85,7 @@ function Dashboard() { | ||
85 | } | 85 | } |
86 | 86 | ||
87 | /*@ngInject*/ | 87 | /*@ngInject*/ |
88 | -function DashboardController($scope, $rootScope, $element, $timeout, $mdMedia, timeService, types, utils) { | 88 | +function DashboardController($scope, $rootScope, $element, $timeout, $mdMedia, $mdUtil, timeService, types, utils) { |
89 | 89 | ||
90 | var highlightedMode = false; | 90 | var highlightedMode = false; |
91 | var highlightedWidget = null; | 91 | var highlightedWidget = null; |
@@ -792,7 +792,7 @@ function DashboardController($scope, $rootScope, $element, $timeout, $mdMedia, t | @@ -792,7 +792,7 @@ function DashboardController($scope, $rootScope, $element, $timeout, $mdMedia, t | ||
792 | } | 792 | } |
793 | 793 | ||
794 | function dashboardLoaded() { | 794 | function dashboardLoaded() { |
795 | - $timeout(function () { | 795 | + $mdUtil.nextTick(function () { |
796 | if (vm.dashboardTimewindowWatch) { | 796 | if (vm.dashboardTimewindowWatch) { |
797 | vm.dashboardTimewindowWatch(); | 797 | vm.dashboardTimewindowWatch(); |
798 | vm.dashboardTimewindowWatch = null; | 798 | vm.dashboardTimewindowWatch = null; |
@@ -802,14 +802,27 @@ function DashboardController($scope, $rootScope, $element, $timeout, $mdMedia, t | @@ -802,14 +802,27 @@ function DashboardController($scope, $rootScope, $element, $timeout, $mdMedia, t | ||
802 | }, true); | 802 | }, true); |
803 | adoptMaxRows(); | 803 | adoptMaxRows(); |
804 | vm.dashboardLoading = false; | 804 | vm.dashboardLoading = false; |
805 | - $timeout(function () { | ||
806 | - var gridsterScope = gridsterElement.scope(); | ||
807 | - vm.gridster = gridsterScope.gridster; | ||
808 | - if (vm.onInit) { | ||
809 | - vm.onInit({dashboard: vm}); | 805 | + if ($scope.gridsterScopeWatcher) { |
806 | + $scope.gridsterScopeWatcher(); | ||
807 | + } | ||
808 | + $scope.gridsterScopeWatcher = $scope.$watch( | ||
809 | + function() { | ||
810 | + var hasScope = gridsterElement.scope() ? true : false; | ||
811 | + return hasScope; | ||
812 | + }, | ||
813 | + function(hasScope) { | ||
814 | + if (hasScope) { | ||
815 | + $scope.gridsterScopeWatcher(); | ||
816 | + $scope.gridsterScopeWatcher = null; | ||
817 | + var gridsterScope = gridsterElement.scope(); | ||
818 | + vm.gridster = gridsterScope.gridster; | ||
819 | + if (vm.onInit) { | ||
820 | + vm.onInit({dashboard: vm}); | ||
821 | + } | ||
822 | + } | ||
810 | } | 823 | } |
811 | - }, 0, false); | ||
812 | - }, 0, false); | 824 | + ); |
825 | + }); | ||
813 | } | 826 | } |
814 | 827 | ||
815 | function loading() { | 828 | function loading() { |
@@ -20,9 +20,9 @@ import Subscription from '../api/subscription'; | @@ -20,9 +20,9 @@ import Subscription from '../api/subscription'; | ||
20 | /* eslint-disable angular/angularelement */ | 20 | /* eslint-disable angular/angularelement */ |
21 | 21 | ||
22 | /*@ngInject*/ | 22 | /*@ngInject*/ |
23 | -export default function WidgetController($scope, $timeout, $window, $element, $q, $log, $injector, $filter, tbRaf, types, utils, timeService, | 23 | +export default function WidgetController($scope, $timeout, $window, $element, $q, $log, $injector, $filter, $compile, tbRaf, types, utils, timeService, |
24 | datasourceService, entityService, deviceService, visibleRect, isEdit, stDiff, dashboardTimewindow, | 24 | datasourceService, entityService, deviceService, visibleRect, isEdit, stDiff, dashboardTimewindow, |
25 | - dashboardTimewindowApi, widget, aliasController, stateController, widgetType) { | 25 | + dashboardTimewindowApi, widget, aliasController, stateController, widgetInfo, widgetType) { |
26 | 26 | ||
27 | var vm = this; | 27 | var vm = this; |
28 | 28 | ||
@@ -42,20 +42,11 @@ export default function WidgetController($scope, $timeout, $window, $element, $q | @@ -42,20 +42,11 @@ export default function WidgetController($scope, $timeout, $window, $element, $q | ||
42 | 42 | ||
43 | var cafs = {}; | 43 | var cafs = {}; |
44 | 44 | ||
45 | - /* | ||
46 | - * data = array of datasourceData | ||
47 | - * datasourceData = { | ||
48 | - * tbDatasource, | ||
49 | - * dataKey, { name, config } | ||
50 | - * data = array of [time, value] | ||
51 | - * } | ||
52 | - */ | ||
53 | - | ||
54 | var widgetContext = { | 45 | var widgetContext = { |
55 | inited: false, | 46 | inited: false, |
56 | $scope: $scope, | 47 | $scope: $scope, |
57 | - $container: $('#container', $element), | ||
58 | - $containerParent: $($element), | 48 | + $container: null, |
49 | + $containerParent: null, | ||
59 | width: 0, | 50 | width: 0, |
60 | height: 0, | 51 | height: 0, |
61 | isEdit: isEdit, | 52 | isEdit: isEdit, |
@@ -82,30 +73,6 @@ export default function WidgetController($scope, $timeout, $window, $element, $q | @@ -82,30 +73,6 @@ export default function WidgetController($scope, $timeout, $window, $element, $q | ||
82 | createSubscription: function(options, subscribe) { | 73 | createSubscription: function(options, subscribe) { |
83 | return createSubscription(options, subscribe); | 74 | return createSubscription(options, subscribe); |
84 | }, | 75 | }, |
85 | - | ||
86 | - | ||
87 | - // type: "timeseries" or "latest" or "rpc" | ||
88 | - /* subscriptionInfo = [ | ||
89 | - { | ||
90 | - entityType: "" | ||
91 | - entityId: "" | ||
92 | - entityName: "" | ||
93 | - timeseries: [{ name: "", label: "" }, ..] | ||
94 | - attributes: [{ name: "", label: "" }, ..] | ||
95 | - } | ||
96 | - .. | ||
97 | - ]*/ | ||
98 | - | ||
99 | - // options = { | ||
100 | - // timeWindowConfig, | ||
101 | - // useDashboardTimewindow, | ||
102 | - // legendConfig, | ||
103 | - // decimals, | ||
104 | - // units, | ||
105 | - // callbacks [ onDataUpdated(subscription, apply) ] | ||
106 | - // } | ||
107 | - // | ||
108 | - | ||
109 | createSubscriptionFromInfo: function (type, subscriptionsInfo, options, useDefaultComponents, subscribe) { | 76 | createSubscriptionFromInfo: function (type, subscriptionsInfo, options, useDefaultComponents, subscribe) { |
110 | return createSubscriptionFromInfo(type, subscriptionsInfo, options, useDefaultComponents, subscribe); | 77 | return createSubscriptionFromInfo(type, subscriptionsInfo, options, useDefaultComponents, subscribe); |
111 | }, | 78 | }, |
@@ -211,21 +178,6 @@ export default function WidgetController($scope, $timeout, $window, $element, $q | @@ -211,21 +178,6 @@ export default function WidgetController($scope, $timeout, $window, $element, $q | ||
211 | } | 178 | } |
212 | ); | 179 | ); |
213 | 180 | ||
214 | - /* | ||
215 | - options = { | ||
216 | - type, | ||
217 | - targetDeviceAliasIds, // RPC | ||
218 | - targetDeviceIds, // RPC | ||
219 | - datasources, | ||
220 | - timeWindowConfig, | ||
221 | - useDashboardTimewindow, | ||
222 | - legendConfig, | ||
223 | - decimals, | ||
224 | - units, | ||
225 | - callbacks | ||
226 | - } | ||
227 | - */ | ||
228 | - | ||
229 | function createSubscriptionFromInfo(type, subscriptionsInfo, options, useDefaultComponents, subscribe) { | 181 | function createSubscriptionFromInfo(type, subscriptionsInfo, options, useDefaultComponents, subscribe) { |
230 | var deferred = $q.defer(); | 182 | var deferred = $q.defer(); |
231 | options.type = type; | 183 | options.type = type; |
@@ -400,6 +352,101 @@ export default function WidgetController($scope, $timeout, $window, $element, $q | @@ -400,6 +352,101 @@ export default function WidgetController($scope, $timeout, $window, $element, $q | ||
400 | return deferred.promise; | 352 | return deferred.promise; |
401 | } | 353 | } |
402 | 354 | ||
355 | + function configureWidgetElement() { | ||
356 | + | ||
357 | + $scope.displayLegend = angular.isDefined(widget.config.showLegend) ? | ||
358 | + widget.config.showLegend : widget.type === types.widgetType.timeseries.value; | ||
359 | + | ||
360 | + if ($scope.displayLegend) { | ||
361 | + $scope.legendConfig = widget.config.legendConfig || | ||
362 | + { | ||
363 | + position: types.position.bottom.value, | ||
364 | + showMin: false, | ||
365 | + showMax: false, | ||
366 | + showAvg: widget.type === types.widgetType.timeseries.value, | ||
367 | + showTotal: false | ||
368 | + }; | ||
369 | + $scope.legendData = { | ||
370 | + keys: [], | ||
371 | + data: [] | ||
372 | + }; | ||
373 | + } | ||
374 | + | ||
375 | + var html = '<div class="tb-absolute-fill tb-widget-error" ng-if="widgetErrorData">' + | ||
376 | + '<span>Widget Error: {{ widgetErrorData.name + ": " + widgetErrorData.message}}</span>' + | ||
377 | + '</div>' + | ||
378 | + '<div class="tb-absolute-fill tb-widget-loading" ng-show="loadingData" layout="column" layout-align="center center">' + | ||
379 | + '<md-progress-circular md-mode="indeterminate" ng-disabled="!loadingData" class="md-accent" md-diameter="40"></md-progress-circular>' + | ||
380 | + '</div>'; | ||
381 | + | ||
382 | + var containerHtml = '<div id="container">' + widgetInfo.templateHtml + '</div>'; | ||
383 | + if ($scope.displayLegend) { | ||
384 | + var layoutType; | ||
385 | + if ($scope.legendConfig.position === types.position.top.value || | ||
386 | + $scope.legendConfig.position === types.position.bottom.value) { | ||
387 | + layoutType = 'column'; | ||
388 | + } else { | ||
389 | + layoutType = 'row'; | ||
390 | + } | ||
391 | + | ||
392 | + var legendStyle; | ||
393 | + switch($scope.legendConfig.position) { | ||
394 | + case types.position.top.value: | ||
395 | + legendStyle = 'padding-bottom: 8px;'; | ||
396 | + break; | ||
397 | + case types.position.bottom.value: | ||
398 | + legendStyle = 'padding-top: 8px;'; | ||
399 | + break; | ||
400 | + case types.position.left.value: | ||
401 | + legendStyle = 'padding-right: 0px;'; | ||
402 | + break; | ||
403 | + case types.position.right.value: | ||
404 | + legendStyle = 'padding-left: 0px;'; | ||
405 | + break; | ||
406 | + } | ||
407 | + | ||
408 | + var legendHtml = '<tb-legend style="'+legendStyle+'" legend-config="legendConfig" legend-data="legendData"></tb-legend>'; | ||
409 | + containerHtml = '<div flex id="widget-container">' + containerHtml + '</div>'; | ||
410 | + html += '<div class="tb-absolute-fill" layout="'+layoutType+'">'; | ||
411 | + if ($scope.legendConfig.position === types.position.top.value || | ||
412 | + $scope.legendConfig.position === types.position.left.value) { | ||
413 | + html += legendHtml; | ||
414 | + html += containerHtml; | ||
415 | + } else { | ||
416 | + html += containerHtml; | ||
417 | + html += legendHtml; | ||
418 | + } | ||
419 | + html += '</div>'; | ||
420 | + } else { | ||
421 | + html += containerHtml; | ||
422 | + } | ||
423 | + | ||
424 | + //TODO: | ||
425 | + /*if (progressElement) { | ||
426 | + progressScope.$destroy(); | ||
427 | + progressScope = null; | ||
428 | + | ||
429 | + progressElement.remove(); | ||
430 | + progressElement = null; | ||
431 | + }*/ | ||
432 | + | ||
433 | + $element.html(html); | ||
434 | + | ||
435 | + var containerElement = $scope.displayLegend ? angular.element($element[0].querySelector('#widget-container')) : $element; | ||
436 | + widgetContext.$container = $('#container', containerElement); | ||
437 | + widgetContext.$containerParent = $(containerElement); | ||
438 | + | ||
439 | + $compile($element.contents())($scope); | ||
440 | + | ||
441 | + addResizeListener(widgetContext.$containerParent[0], onResize); // eslint-disable-line no-undef | ||
442 | + } | ||
443 | + | ||
444 | + function destroyWidgetElement() { | ||
445 | + removeResizeListener(widgetContext.$containerParent[0], onResize); // eslint-disable-line no-undef | ||
446 | + $element.html(''); | ||
447 | + widgetContext.$container = null; | ||
448 | + widgetContext.$containerParent = null; | ||
449 | + } | ||
403 | 450 | ||
404 | function initialize() { | 451 | function initialize() { |
405 | 452 | ||
@@ -407,8 +454,6 @@ export default function WidgetController($scope, $timeout, $window, $element, $q | @@ -407,8 +454,6 @@ export default function WidgetController($scope, $timeout, $window, $element, $q | ||
407 | onEditModeChanged(isEdit); | 454 | onEditModeChanged(isEdit); |
408 | }); | 455 | }); |
409 | 456 | ||
410 | - addResizeListener(widgetContext.$containerParent[0], onResize); // eslint-disable-line no-undef | ||
411 | - | ||
412 | $scope.$watch(function () { | 457 | $scope.$watch(function () { |
413 | return widget.row + ',' + widget.col + ',' + widget.config.mobileOrder; | 458 | return widget.row + ',' + widget.col + ',' + widget.config.mobileOrder; |
414 | }, function () { | 459 | }, function () { |
@@ -439,10 +484,10 @@ export default function WidgetController($scope, $timeout, $window, $element, $q | @@ -439,10 +484,10 @@ export default function WidgetController($scope, $timeout, $window, $element, $q | ||
439 | }); | 484 | }); |
440 | 485 | ||
441 | $scope.$on("$destroy", function () { | 486 | $scope.$on("$destroy", function () { |
442 | - removeResizeListener(widgetContext.$containerParent[0], onResize); // eslint-disable-line no-undef | ||
443 | onDestroy(); | 487 | onDestroy(); |
444 | }); | 488 | }); |
445 | 489 | ||
490 | + configureWidgetElement(); | ||
446 | var deferred = $q.defer(); | 491 | var deferred = $q.defer(); |
447 | if (!vm.useCustomDatasources) { | 492 | if (!vm.useCustomDatasources) { |
448 | createDefaultSubscription().then( | 493 | createDefaultSubscription().then( |
@@ -465,6 +510,7 @@ export default function WidgetController($scope, $timeout, $window, $element, $q | @@ -465,6 +510,7 @@ export default function WidgetController($scope, $timeout, $window, $element, $q | ||
465 | 510 | ||
466 | function reInit() { | 511 | function reInit() { |
467 | onDestroy(); | 512 | onDestroy(); |
513 | + configureWidgetElement(); | ||
468 | if (!vm.useCustomDatasources) { | 514 | if (!vm.useCustomDatasources) { |
469 | createDefaultSubscription().then( | 515 | createDefaultSubscription().then( |
470 | function success() { | 516 | function success() { |
@@ -636,6 +682,7 @@ export default function WidgetController($scope, $timeout, $window, $element, $q | @@ -636,6 +682,7 @@ export default function WidgetController($scope, $timeout, $window, $element, $q | ||
636 | handleWidgetException(e); | 682 | handleWidgetException(e); |
637 | } | 683 | } |
638 | } | 684 | } |
685 | + destroyWidgetElement(); | ||
639 | } | 686 | } |
640 | 687 | ||
641 | //TODO: widgets visibility | 688 | //TODO: widgets visibility |
@@ -28,7 +28,7 @@ export default angular.module('thingsboard.directives.widget', [thingsboardLegen | @@ -28,7 +28,7 @@ export default angular.module('thingsboard.directives.widget', [thingsboardLegen | ||
28 | .name; | 28 | .name; |
29 | 29 | ||
30 | /*@ngInject*/ | 30 | /*@ngInject*/ |
31 | -function Widget($controller, $compile, types, widgetService) { | 31 | +function Widget($controller, widgetService) { |
32 | return { | 32 | return { |
33 | scope: true, | 33 | scope: true, |
34 | link: function (scope, elem, attrs) { | 34 | link: function (scope, elem, attrs) { |
@@ -81,90 +81,9 @@ function Widget($controller, $compile, types, widgetService) { | @@ -81,90 +81,9 @@ function Widget($controller, $compile, types, widgetService) { | ||
81 | 81 | ||
82 | elem.addClass(widgetNamespace); | 82 | elem.addClass(widgetNamespace); |
83 | 83 | ||
84 | - var html = '<div class="tb-absolute-fill tb-widget-error" ng-if="widgetErrorData">' + | ||
85 | - '<span>Widget Error: {{ widgetErrorData.name + ": " + widgetErrorData.message}}</span>' + | ||
86 | - '</div>' + | ||
87 | - '<div class="tb-absolute-fill tb-widget-loading" ng-show="loadingData" layout="column" layout-align="center center">' + | ||
88 | - '<md-progress-circular md-mode="indeterminate" ng-disabled="!loadingData" class="md-accent" md-diameter="40"></md-progress-circular>' + | ||
89 | - '</div>'; | ||
90 | - | ||
91 | - scope.displayLegend = angular.isDefined(widget.config.showLegend) ? | ||
92 | - widget.config.showLegend : widget.type === types.widgetType.timeseries.value; | ||
93 | - | ||
94 | - | ||
95 | - var containerHtml = '<div id="container">' + widgetInfo.templateHtml + '</div>'; | ||
96 | - if (scope.displayLegend) { | ||
97 | - scope.legendConfig = widget.config.legendConfig || | ||
98 | - { | ||
99 | - position: types.position.bottom.value, | ||
100 | - showMin: false, | ||
101 | - showMax: false, | ||
102 | - showAvg: widget.type === types.widgetType.timeseries.value, | ||
103 | - showTotal: false | ||
104 | - }; | ||
105 | - scope.legendData = { | ||
106 | - keys: [], | ||
107 | - data: [] | ||
108 | - }; | ||
109 | - | ||
110 | - var layoutType; | ||
111 | - if (scope.legendConfig.position === types.position.top.value || | ||
112 | - scope.legendConfig.position === types.position.bottom.value) { | ||
113 | - layoutType = 'column'; | ||
114 | - } else { | ||
115 | - layoutType = 'row'; | ||
116 | - } | ||
117 | - | ||
118 | - var legendStyle; | ||
119 | - switch(scope.legendConfig.position) { | ||
120 | - case types.position.top.value: | ||
121 | - legendStyle = 'padding-bottom: 8px;'; | ||
122 | - break; | ||
123 | - case types.position.bottom.value: | ||
124 | - legendStyle = 'padding-top: 8px;'; | ||
125 | - break; | ||
126 | - case types.position.left.value: | ||
127 | - legendStyle = 'padding-right: 0px;'; | ||
128 | - break; | ||
129 | - case types.position.right.value: | ||
130 | - legendStyle = 'padding-left: 0px;'; | ||
131 | - break; | ||
132 | - } | ||
133 | - | ||
134 | - var legendHtml = '<tb-legend style="'+legendStyle+'" legend-config="legendConfig" legend-data="legendData"></tb-legend>'; | ||
135 | - containerHtml = '<div flex id="widget-container">' + containerHtml + '</div>'; | ||
136 | - html += '<div class="tb-absolute-fill" layout="'+layoutType+'">'; | ||
137 | - if (scope.legendConfig.position === types.position.top.value || | ||
138 | - scope.legendConfig.position === types.position.left.value) { | ||
139 | - html += legendHtml; | ||
140 | - html += containerHtml; | ||
141 | - } else { | ||
142 | - html += containerHtml; | ||
143 | - html += legendHtml; | ||
144 | - } | ||
145 | - html += '</div>'; | ||
146 | - } else { | ||
147 | - html += containerHtml; | ||
148 | - } | ||
149 | - | ||
150 | - //TODO: | ||
151 | - /*if (progressElement) { | ||
152 | - progressScope.$destroy(); | ||
153 | - progressScope = null; | ||
154 | - | ||
155 | - progressElement.remove(); | ||
156 | - progressElement = null; | ||
157 | - }*/ | ||
158 | - | ||
159 | - elem.html(html); | ||
160 | - | ||
161 | - var containerElement = scope.displayLegend ? angular.element(elem[0].querySelector('#widget-container')) : elem; | ||
162 | - | ||
163 | - $compile(elem.contents())(scope); | ||
164 | - | ||
165 | var widgetType = widgetService.getWidgetTypeFunction(widget.bundleAlias, widget.typeAlias, widget.isSystemType); | 84 | var widgetType = widgetService.getWidgetTypeFunction(widget.bundleAlias, widget.typeAlias, widget.isSystemType); |
166 | 85 | ||
167 | - angular.extend(locals, {$scope: scope, $element: containerElement, widgetType: widgetType}); | 86 | + angular.extend(locals, {$scope: scope, $element: elem, widgetInfo: widgetInfo, widgetType: widgetType}); |
168 | 87 | ||
169 | widgetController = $controller('WidgetController', locals); | 88 | widgetController = $controller('WidgetController', locals); |
170 | 89 |
@@ -15,7 +15,7 @@ | @@ -15,7 +15,7 @@ | ||
15 | */ | 15 | */ |
16 | 16 | ||
17 | /*@ngInject*/ | 17 | /*@ngInject*/ |
18 | -export default function AliasesEntitySelectPanelController(mdPanelRef, $scope, types, aliasController, onEntityAliasesUpdate) { | 18 | +export default function AliasesEntitySelectPanelController(mdPanelRef, $scope, $filter, types, aliasController, onEntityAliasesUpdate) { |
19 | 19 | ||
20 | var vm = this; | 20 | var vm = this; |
21 | vm._mdPanelRef = mdPanelRef; | 21 | vm._mdPanelRef = mdPanelRef; |
@@ -31,13 +31,18 @@ export default function AliasesEntitySelectPanelController(mdPanelRef, $scope, t | @@ -31,13 +31,18 @@ export default function AliasesEntitySelectPanelController(mdPanelRef, $scope, t | ||
31 | var aliasInfo = vm.aliasController.getInstantAliasInfo(aliasId); | 31 | var aliasInfo = vm.aliasController.getInstantAliasInfo(aliasId); |
32 | if (aliasInfo && !aliasInfo.resolveMultiple && aliasInfo.currentEntity) { | 32 | if (aliasInfo && !aliasInfo.resolveMultiple && aliasInfo.currentEntity) { |
33 | vm.entityAliasesInfo[aliasId] = angular.copy(aliasInfo); | 33 | vm.entityAliasesInfo[aliasId] = angular.copy(aliasInfo); |
34 | + vm.entityAliasesInfo[aliasId].selectedId = aliasInfo.currentEntity.id; | ||
34 | } | 35 | } |
35 | } | 36 | } |
36 | 37 | ||
37 | - function currentAliasEntityChanged(aliasId, currentEntity) { | ||
38 | - vm.aliasController.updateCurrentAliasEntity(aliasId, currentEntity); | ||
39 | - if (onEntityAliasesUpdate) { | ||
40 | - onEntityAliasesUpdate(); | 38 | + function currentAliasEntityChanged(aliasId, selectedId) { |
39 | + var resolvedEntities = vm.entityAliasesInfo[aliasId].resolvedEntities; | ||
40 | + var selected = $filter('filter')(resolvedEntities, {id: selectedId}); | ||
41 | + if (selected && selected.length) { | ||
42 | + vm.aliasController.updateCurrentAliasEntity(aliasId, selected[0]); | ||
43 | + if (onEntityAliasesUpdate) { | ||
44 | + onEntityAliasesUpdate(); | ||
45 | + } | ||
41 | } | 46 | } |
42 | } | 47 | } |
43 | 48 |
@@ -21,8 +21,8 @@ | @@ -21,8 +21,8 @@ | ||
21 | <div flex layout="row" ng-repeat="(aliasId, entityAliasInfo) in vm.entityAliasesInfo"> | 21 | <div flex layout="row" ng-repeat="(aliasId, entityAliasInfo) in vm.entityAliasesInfo"> |
22 | <md-input-container flex> | 22 | <md-input-container flex> |
23 | <label>{{entityAliasInfo.alias}}</label> | 23 | <label>{{entityAliasInfo.alias}}</label> |
24 | - <md-select ng-model="entityAliasInfo.currentEntity" ng-change="vm.currentAliasEntityChanged(aliasId, entityAliasInfo.currentEntity)"> | ||
25 | - <md-option ng-repeat="resolvedEntity in entityAliasInfo.resolvedEntities" ng-value="resolvedEntity"> | 24 | + <md-select ng-model="entityAliasInfo.selectedId" ng-change="vm.currentAliasEntityChanged(aliasId, entityAliasInfo.selectedId)"> |
25 | + <md-option ng-repeat="resolvedEntity in entityAliasInfo.resolvedEntities" ng-value="resolvedEntity.id"> | ||
26 | {{resolvedEntity.name}} | 26 | {{resolvedEntity.name}} |
27 | </md-option> | 27 | </md-option> |
28 | </md-select> | 28 | </md-select> |
@@ -94,6 +94,14 @@ export default function AliasesEntitySelectDirective($compile, $templateCache, $ | @@ -94,6 +94,14 @@ export default function AliasesEntitySelectDirective($compile, $templateCache, $ | ||
94 | $mdPanel.open(config); | 94 | $mdPanel.open(config); |
95 | } | 95 | } |
96 | 96 | ||
97 | + scope.$on('entityAliasesChanged', function() { | ||
98 | + scope.updateView(); | ||
99 | + }); | ||
100 | + | ||
101 | + scope.$on('entityAliasResolved', function() { | ||
102 | + scope.updateView(); | ||
103 | + }); | ||
104 | + | ||
97 | scope.updateView = function () { | 105 | scope.updateView = function () { |
98 | updateDisplayValue(); | 106 | updateDisplayValue(); |
99 | } | 107 | } |
@@ -22,7 +22,7 @@ import selectTargetLayoutTemplate from '../../dashboard/layouts/select-target-la | @@ -22,7 +22,7 @@ import selectTargetLayoutTemplate from '../../dashboard/layouts/select-target-la | ||
22 | /* eslint-enable import/no-unresolved, import/default */ | 22 | /* eslint-enable import/no-unresolved, import/default */ |
23 | 23 | ||
24 | /*@ngInject*/ | 24 | /*@ngInject*/ |
25 | -export default function AddWidgetToDashboardDialogController($scope, $mdDialog, $state, $q, $document, | 25 | +export default function AddWidgetToDashboardDialogController($scope, $mdDialog, $state, $q, $document, dashboardUtils, |
26 | types, itembuffer, dashboardService, entityId, entityType, entityName, widget) { | 26 | types, itembuffer, dashboardService, entityId, entityType, entityName, widget) { |
27 | 27 | ||
28 | var vm = this; | 28 | var vm = this; |
@@ -126,15 +126,8 @@ export default function AddWidgetToDashboardDialogController($scope, $mdDialog, | @@ -126,15 +126,8 @@ export default function AddWidgetToDashboardDialogController($scope, $mdDialog, | ||
126 | targetDeviceAliases: {} | 126 | targetDeviceAliases: {} |
127 | }; | 127 | }; |
128 | aliasesInfo.datasourceAliases[0] = { | 128 | aliasesInfo.datasourceAliases[0] = { |
129 | - id: 1, | ||
130 | alias: entityName, | 129 | alias: entityName, |
131 | - filter: { | ||
132 | - type: types.aliasFilterType.entityList.value, | ||
133 | - stateEntity: false, | ||
134 | - entityList: [entityId], | ||
135 | - entityType: entityType, | ||
136 | - resolveMultiple: false | ||
137 | - } | 130 | + filter: dashboardUtils.createSingleEntityFilter(entityType, entityId) |
138 | }; | 131 | }; |
139 | itembuffer.addWidgetToDashboard(theDashboard, targetState, targetLayout, vm.widget, aliasesInfo, null, 48, null, -1, -1).then( | 132 | itembuffer.addWidgetToDashboard(theDashboard, targetState, targetLayout, vm.widget, aliasesInfo, null, 48, null, -1, -1).then( |
140 | function(theDashboard) { | 133 | function(theDashboard) { |
@@ -26,10 +26,12 @@ import editAttributeValueTemplate from './edit-attribute-value.tpl.html'; | @@ -26,10 +26,12 @@ import editAttributeValueTemplate from './edit-attribute-value.tpl.html'; | ||
26 | /* eslint-enable import/no-unresolved, import/default */ | 26 | /* eslint-enable import/no-unresolved, import/default */ |
27 | 27 | ||
28 | import EditAttributeValueController from './edit-attribute-value.controller'; | 28 | import EditAttributeValueController from './edit-attribute-value.controller'; |
29 | +import AliasController from '../../api/alias-controller'; | ||
29 | 30 | ||
30 | /*@ngInject*/ | 31 | /*@ngInject*/ |
31 | export default function AttributeTableDirective($compile, $templateCache, $rootScope, $q, $mdEditDialog, $mdDialog, | 32 | export default function AttributeTableDirective($compile, $templateCache, $rootScope, $q, $mdEditDialog, $mdDialog, |
32 | - $document, $translate, $filter, utils, types, dashboardService, attributeService, widgetService) { | 33 | + $mdUtil, $document, $translate, $filter, utils, types, dashboardUtils, |
34 | + dashboardService, entityService, attributeService, widgetService) { | ||
33 | 35 | ||
34 | var linker = function (scope, element, attrs) { | 36 | var linker = function (scope, element, attrs) { |
35 | 37 | ||
@@ -246,15 +248,19 @@ export default function AttributeTableDirective($compile, $templateCache, $rootS | @@ -246,15 +248,19 @@ export default function AttributeTableDirective($compile, $templateCache, $rootS | ||
246 | } | 248 | } |
247 | 249 | ||
248 | scope.nextWidget = function() { | 250 | scope.nextWidget = function() { |
249 | - if (scope.widgetsCarousel.index < scope.widgetsList.length-1) { | ||
250 | - scope.widgetsCarousel.index++; | ||
251 | - } | 251 | + $mdUtil.nextTick(function () { |
252 | + if (scope.widgetsCarousel.index < scope.widgetsList.length - 1) { | ||
253 | + scope.widgetsCarousel.index++; | ||
254 | + } | ||
255 | + }); | ||
252 | } | 256 | } |
253 | 257 | ||
254 | scope.prevWidget = function() { | 258 | scope.prevWidget = function() { |
255 | - if (scope.widgetsCarousel.index > 0) { | ||
256 | - scope.widgetsCarousel.index--; | ||
257 | - } | 259 | + $mdUtil.nextTick(function () { |
260 | + if (scope.widgetsCarousel.index > 0) { | ||
261 | + scope.widgetsCarousel.index--; | ||
262 | + } | ||
263 | + }); | ||
258 | } | 264 | } |
259 | 265 | ||
260 | scope.enterWidgetMode = function() { | 266 | scope.enterWidgetMode = function() { |
@@ -281,23 +287,28 @@ export default function AttributeTableDirective($compile, $templateCache, $rootS | @@ -281,23 +287,28 @@ export default function AttributeTableDirective($compile, $templateCache, $rootS | ||
281 | scope.firstBundle = true; | 287 | scope.firstBundle = true; |
282 | scope.selectedWidgetsBundleAlias = types.systemBundleAlias.cards; | 288 | scope.selectedWidgetsBundleAlias = types.systemBundleAlias.cards; |
283 | 289 | ||
284 | - scope.aliasesInfo = { | ||
285 | - entityAliases: { | ||
286 | - '1': {alias: scope.entityName, entityType: scope.entityType, entityId: scope.entityId} | ||
287 | - }, | ||
288 | - entityAliasesInfo: { | ||
289 | - '1': [ | ||
290 | - {name: scope.entityName, entityType: scope.entityType, id: scope.entityId} | ||
291 | - ] | 290 | + var entityAlias = { |
291 | + id: utils.guid(), | ||
292 | + alias: scope.entityName, | ||
293 | + filter: dashboardUtils.createSingleEntityFilter(scope.entityType, scope.entityId) | ||
294 | + }; | ||
295 | + var entitiAliases = {}; | ||
296 | + entitiAliases[entityAlias.id] = entityAlias; | ||
297 | + | ||
298 | + var stateController = { | ||
299 | + getStateParams: function() { | ||
300 | + return {}; | ||
292 | } | 301 | } |
293 | }; | 302 | }; |
303 | + scope.aliasController = new AliasController(scope, $q, $filter, utils, | ||
304 | + types, entityService, stateController, entitiAliases); | ||
294 | 305 | ||
295 | var dataKeyType = scope.attributeScope === types.latestTelemetry ? | 306 | var dataKeyType = scope.attributeScope === types.latestTelemetry ? |
296 | types.dataKeyType.timeseries : types.dataKeyType.attribute; | 307 | types.dataKeyType.timeseries : types.dataKeyType.attribute; |
297 | 308 | ||
298 | var datasource = { | 309 | var datasource = { |
299 | type: types.datasourceType.entity, | 310 | type: types.datasourceType.entity, |
300 | - entityAliasId: '1', | 311 | + entityAliasId: entityAlias.id, |
301 | dataKeys: [] | 312 | dataKeys: [] |
302 | } | 313 | } |
303 | var i = 0; | 314 | var i = 0; |
@@ -156,7 +156,7 @@ | @@ -156,7 +156,7 @@ | ||
156 | rn-swipe-disabled="true"> | 156 | rn-swipe-disabled="true"> |
157 | <li ng-repeat="widgets in widgetsList"> | 157 | <li ng-repeat="widgets in widgetsList"> |
158 | <tb-dashboard | 158 | <tb-dashboard |
159 | - aliases-info="aliasesInfo" | 159 | + alias-controller="aliasController" |
160 | widgets="widgets" | 160 | widgets="widgets" |
161 | get-st-diff="getServerTimeDiff()" | 161 | get-st-diff="getServerTimeDiff()" |
162 | columns="20" | 162 | columns="20" |
@@ -113,12 +113,7 @@ export default function EntityAliasesController(utils, entityService, toast, $sc | @@ -113,12 +113,7 @@ export default function EntityAliasesController(utils, entityService, toast, $sc | ||
113 | } | 113 | } |
114 | 114 | ||
115 | function addAlias() { | 115 | function addAlias() { |
116 | - var aliasId = 0; | ||
117 | - for (var a in vm.entityAliases) { | ||
118 | - aliasId = Math.max(vm.entityAliases[a].id, aliasId); | ||
119 | - } | ||
120 | - aliasId++; | ||
121 | - var entityAlias = {id: aliasId, alias: '', filter: {}, changed: false}; | 116 | + var entityAlias = {id: utils.guid(), alias: '', filter: {}, changed: false}; |
122 | vm.entityAliases.push(entityAlias); | 117 | vm.entityAliases.push(entityAlias); |
123 | } | 118 | } |
124 | 119 | ||
@@ -162,23 +157,21 @@ export default function EntityAliasesController(utils, entityService, toast, $sc | @@ -162,23 +157,21 @@ export default function EntityAliasesController(utils, entityService, toast, $sc | ||
162 | var uniqueAliasList = {}; | 157 | var uniqueAliasList = {}; |
163 | 158 | ||
164 | var valid = true; | 159 | var valid = true; |
165 | - var aliasId, maxAliasId; | 160 | + var aliasId; |
166 | var alias; | 161 | var alias; |
167 | var i; | 162 | var i; |
168 | 163 | ||
169 | if (vm.isSingleEntityAlias) { | 164 | if (vm.isSingleEntityAlias) { |
170 | - maxAliasId = 0; | 165 | + if (!vm.singleEntityAlias.id) { |
166 | + vm.singleEntityAlias.id = utils.guid(); | ||
167 | + } | ||
171 | for (i = 0; i < vm.entityAliases.length; i ++) { | 168 | for (i = 0; i < vm.entityAliases.length; i ++) { |
172 | - aliasId = vm.entityAliases[i].id; | ||
173 | alias = vm.entityAliases[i].alias; | 169 | alias = vm.entityAliases[i].alias; |
174 | if (alias === vm.singleEntityAlias.alias) { | 170 | if (alias === vm.singleEntityAlias.alias) { |
175 | valid = false; | 171 | valid = false; |
176 | break; | 172 | break; |
177 | } | 173 | } |
178 | - maxAliasId = Math.max(aliasId, maxAliasId); | ||
179 | } | 174 | } |
180 | - maxAliasId++; | ||
181 | - vm.singleEntityAlias.id = maxAliasId; | ||
182 | } else { | 175 | } else { |
183 | for (i = 0; i < vm.entityAliases.length; i++) { | 176 | for (i = 0; i < vm.entityAliases.length; i++) { |
184 | aliasId = vm.entityAliases[i].id; | 177 | aliasId = vm.entityAliases[i].id; |
@@ -18,11 +18,20 @@ | @@ -18,11 +18,20 @@ | ||
18 | .md-dialog-content { | 18 | .md-dialog-content { |
19 | padding-bottom: 0px; | 19 | padding-bottom: 0px; |
20 | } | 20 | } |
21 | + .tb-aliases-header { | ||
22 | + min-height: 40px; | ||
23 | + padding: 0 34px 0 34px; | ||
24 | + margin: 5px; | ||
25 | + .tb-header-label { | ||
26 | + font-size: 14px; | ||
27 | + color: rgba(0, 0, 0, 0.570588); | ||
28 | + } | ||
29 | + } | ||
21 | .tb-alias { | 30 | .tb-alias { |
22 | - padding: 10px 0 0 10px; | 31 | + padding: 0 0 0 10px; |
23 | margin: 5px; | 32 | margin: 5px; |
24 | - md-select.tb-entity-type-select { | ||
25 | - padding-bottom: 24px; | 33 | + md-input-container { |
34 | + margin: 0px; | ||
26 | } | 35 | } |
27 | } | 36 | } |
28 | } | 37 | } |
@@ -28,23 +28,28 @@ | @@ -28,23 +28,28 @@ | ||
28 | </md-toolbar> | 28 | </md-toolbar> |
29 | <md-progress-linear class="md-warn" md-mode="indeterminate" ng-disabled="!loading" ng-show="loading"></md-progress-linear> | 29 | <md-progress-linear class="md-warn" md-mode="indeterminate" ng-disabled="!loading" ng-show="loading"></md-progress-linear> |
30 | <span style="min-height: 5px;" flex="" ng-show="!loading"></span> | 30 | <span style="min-height: 5px;" flex="" ng-show="!loading"></span> |
31 | + <div class="tb-aliases-header" ng-show="!vm.isSingleEntityAlias" flex layout="row" layout-align="start center"> | ||
32 | + <span flex="5"></span> | ||
33 | + <div flex layout="row" layout-align="start center"> | ||
34 | + <span class="tb-header-label" translate flex="20" style="min-width: 150px;">entity.alias</span> | ||
35 | + <div flex="80" layout="row" layout-align="start center" style="min-width: 240px; padding-left: 10px;"> | ||
36 | + <span class="tb-header-label" translate flex="70">alias.entity-filter</span> | ||
37 | + <span class="tb-header-label" translate flex="30" style="padding-left: 10px;" >alias.resolve-multiple</span> | ||
38 | + </div> | ||
39 | + <span style="min-width: 40px; margin: 0 6px;"></span> | ||
40 | + </div> | ||
41 | + </div> | ||
42 | + <md-divider ng-show="!vm.isSingleEntityAlias"></md-divider> | ||
31 | <md-dialog-content> | 43 | <md-dialog-content> |
32 | <div class="md-dialog-content"> | 44 | <div class="md-dialog-content"> |
33 | <fieldset ng-disabled="loading"> | 45 | <fieldset ng-disabled="loading"> |
34 | <div ng-show="vm.isSingleEntityAlias" layout="row"> | 46 | <div ng-show="vm.isSingleEntityAlias" layout="row"> |
35 | - <tb-entity-filter flex allowed-entity-types="vm.allowedEntityTypes" ng-model="vm.singleEntityAlias.filter"> | 47 | + <tb-entity-filter flex |
48 | + allowed-entity-types="vm.allowedEntityTypes" | ||
49 | + ng-model="vm.singleEntityAlias.filter"> | ||
36 | </tb-entity-filter> | 50 | </tb-entity-filter> |
37 | </div> | 51 | </div> |
38 | - <div ng-show="!vm.isSingleEntityAlias" flex layout="row" layout-align="start center"> | ||
39 | - <span flex="5"></span> | ||
40 | - <div flex layout="row" layout-align="start center" | ||
41 | - style="padding: 0 0 0 10px; margin: 5px;"> | ||
42 | - <span translate flex="20" style="min-width: 150px;">entity.alias</span> | ||
43 | - <span translate flex="80" style="min-width: 240px; padding-left: 10px;">alias.entity-filter</span> | ||
44 | - <span style="min-width: 40px;"></span> | ||
45 | - </div> | ||
46 | - </div> | ||
47 | - <div ng-show="!vm.isSingleEntityAlias" style="max-height: 500px; overflow: auto; padding-bottom: 20px;"> | 52 | + <div ng-show="!vm.isSingleEntityAlias" style="height: 100%; overflow: auto; padding-bottom: 20px;"> |
48 | <div ng-form name="aliasForm" flex layout="row" layout-align="start center" ng-repeat="entityAlias in vm.entityAliases track by $index"> | 53 | <div ng-form name="aliasForm" flex layout="row" layout-align="start center" ng-repeat="entityAlias in vm.entityAliases track by $index"> |
49 | <span flex="5">{{$index + 1}}.</span> | 54 | <span flex="5">{{$index + 1}}.</span> |
50 | <div class="md-whiteframe-4dp tb-alias" flex layout="row" layout-align="start center"> | 55 | <div class="md-whiteframe-4dp tb-alias" flex layout="row" layout-align="start center"> |
@@ -54,13 +59,12 @@ | @@ -54,13 +59,12 @@ | ||
54 | <div translate ng-message="required">entity.alias-required</div> | 59 | <div translate ng-message="required">entity.alias-required</div> |
55 | </div> | 60 | </div> |
56 | </md-input-container> | 61 | </md-input-container> |
57 | - <section flex="80" layout="column"> | ||
58 | - <tb-entity-filter style="padding-left: 10px;" | ||
59 | - allowed-entity-types="vm.allowedEntityTypes" | ||
60 | - ng-model="entityAlias.filter" | ||
61 | - on-matching-entity-change="vm.onFilterEntityChanged(entity, stateEntity, entityAlias)"> | ||
62 | - </tb-entity-filter> | ||
63 | - </section> | 62 | + <tb-entity-filter flex="80" style="min-width: 240px; padding-left: 10px;" |
63 | + hide-labels | ||
64 | + allowed-entity-types="vm.allowedEntityTypes" | ||
65 | + ng-model="entityAlias.filter" | ||
66 | + on-matching-entity-change="vm.onFilterEntityChanged(entity, stateEntity, entityAlias)"> | ||
67 | + </tb-entity-filter> | ||
64 | <md-button ng-disabled="loading" class="md-icon-button md-primary" style="min-width: 40px;" | 68 | <md-button ng-disabled="loading" class="md-icon-button md-primary" style="min-width: 40px;" |
65 | ng-click="vm.removeAlias($event, entityAlias)" aria-label="{{ 'action.remove' | translate }}"> | 69 | ng-click="vm.removeAlias($event, entityAlias)" aria-label="{{ 'action.remove' | translate }}"> |
66 | <md-tooltip md-direction="top"> | 70 | <md-tooltip md-direction="top"> |
@@ -73,18 +77,18 @@ | @@ -73,18 +77,18 @@ | ||
73 | </div> | 77 | </div> |
74 | </div> | 78 | </div> |
75 | </div> | 79 | </div> |
76 | - <div ng-show="!vm.isSingleEntityAlias && !vm.disableAdd" style="padding-bottom: 10px;"> | ||
77 | - <md-button ng-disabled="loading" class="md-primary md-raised" ng-click="vm.addAlias($event)" aria-label="{{ 'action.add' | translate }}"> | ||
78 | - <md-tooltip md-direction="top"> | ||
79 | - {{ 'entity.add-alias' | translate }} | ||
80 | - </md-tooltip> | ||
81 | - <span translate>action.add</span> | ||
82 | - </md-button> | ||
83 | - </div> | ||
84 | </fieldset> | 80 | </fieldset> |
85 | </div> | 81 | </div> |
86 | </md-dialog-content> | 82 | </md-dialog-content> |
87 | <md-dialog-actions layout="row"> | 83 | <md-dialog-actions layout="row"> |
84 | + <md-button ng-show="!vm.isSingleEntityAlias && !vm.disableAdd" ng-disabled="loading" class="md-primary md-raised" | ||
85 | + ng-click="vm.addAlias($event)" | ||
86 | + aria-label="{{ 'action.add' | translate }}"> | ||
87 | + <md-tooltip md-direction="top"> | ||
88 | + {{ 'entity.add-alias' | translate }} | ||
89 | + </md-tooltip> | ||
90 | + <span translate>action.add</span> | ||
91 | + </md-button> | ||
88 | <span flex></span> | 92 | <span flex></span> |
89 | <md-button ng-disabled="loading || theForm.$invalid || !theForm.$dirty" type="submit" class="md-raised md-primary"> | 93 | <md-button ng-disabled="loading || theForm.$invalid || !theForm.$dirty" type="submit" class="md-raised md-primary"> |
90 | {{ 'action.save' | translate }} | 94 | {{ 'action.save' | translate }} |
@@ -35,46 +35,16 @@ export default function EntityFilterDirective($compile, $templateCache, $q, $doc | @@ -35,46 +35,16 @@ export default function EntityFilterDirective($compile, $templateCache, $q, $doc | ||
35 | 35 | ||
36 | scope.ngModelCtrl = ngModelCtrl; | 36 | scope.ngModelCtrl = ngModelCtrl; |
37 | scope.types = types; | 37 | scope.types = types; |
38 | - | ||
39 | - /* scope.fetchEntities = function(searchText, limit) { | ||
40 | - var deferred = $q.defer(); | ||
41 | - entityService.getEntitiesByNameFilter(scope.entityType, searchText, limit).then(function success(result) { | ||
42 | - if (result) { | ||
43 | - deferred.resolve(result); | ||
44 | - } else { | ||
45 | - deferred.resolve([]); | ||
46 | - } | ||
47 | - }, function fail() { | ||
48 | - deferred.reject(); | ||
49 | - }); | ||
50 | - return deferred.promise; | ||
51 | - }*/ | 38 | + scope.hideLabels = angular.isDefined(attrs.hideLabels); |
52 | 39 | ||
53 | scope.updateValidity = function() { | 40 | scope.updateValidity = function() { |
54 | if (ngModelCtrl.$viewValue) { | 41 | if (ngModelCtrl.$viewValue) { |
55 | var value = ngModelCtrl.$viewValue; | 42 | var value = ngModelCtrl.$viewValue; |
56 | ngModelCtrl.$setValidity('filter', value.type ? true : false); | 43 | ngModelCtrl.$setValidity('filter', value.type ? true : false); |
57 | - /*if (value.useFilter) { | ||
58 | - ngModelCtrl.$setValidity('entityList', true); | ||
59 | - if (angular.isDefined(value.entityNameFilter) && value.entityNameFilter.length > 0) { | ||
60 | - ngModelCtrl.$setValidity('entityNameFilter', true); | ||
61 | - valid = angular.isDefined(scope.model.matchingFilterEntity) && scope.model.matchingFilterEntity != null; | ||
62 | - ngModelCtrl.$setValidity('entityNameFilterEntityMatch', valid); | ||
63 | - } else { | ||
64 | - ngModelCtrl.$setValidity('entityNameFilter', false); | ||
65 | - } | ||
66 | - } else { | ||
67 | - ngModelCtrl.$setValidity('entityNameFilter', true); | ||
68 | - ngModelCtrl.$setValidity('entityNameFilterDeviceMatch', true); | ||
69 | - valid = angular.isDefined(value.entityList) && value.entityList.length > 0; | ||
70 | - ngModelCtrl.$setValidity('entityList', valid); | ||
71 | - }*/ | ||
72 | - | ||
73 | } | 44 | } |
74 | } | 45 | } |
75 | 46 | ||
76 | ngModelCtrl.$render = function () { | 47 | ngModelCtrl.$render = function () { |
77 | - //destroyWatchers(); | ||
78 | if (ngModelCtrl.$viewValue) { | 48 | if (ngModelCtrl.$viewValue) { |
79 | scope.model = angular.copy(ngModelCtrl.$viewValue); | 49 | scope.model = angular.copy(ngModelCtrl.$viewValue); |
80 | } else { | 50 | } else { |
@@ -83,28 +53,6 @@ export default function EntityFilterDirective($compile, $templateCache, $q, $doc | @@ -83,28 +53,6 @@ export default function EntityFilterDirective($compile, $templateCache, $q, $doc | ||
83 | resolveMultiple: false | 53 | resolveMultiple: false |
84 | } | 54 | } |
85 | } | 55 | } |
86 | - /* if (ngModelCtrl.$viewValue) { | ||
87 | - var value = ngModelCtrl.$viewValue; | ||
88 | - var model = scope.model; | ||
89 | - model.useFilter = value.useFilter === true ? true: false; | ||
90 | - model.entityList = []; | ||
91 | - model.entityNameFilter = value.entityNameFilter || ''; | ||
92 | - processEntityNameFilter(model.entityNameFilter).then( | ||
93 | - function(entity) { | ||
94 | - scope.model.matchingFilterEntity = entity; | ||
95 | - if (value.entityList && value.entityList.length > 0) { | ||
96 | - entityService.getEntities(scope.entityType, value.entityList).then(function (entities) { | ||
97 | - model.entityList = entities; | ||
98 | - updateMatchingEntity(); | ||
99 | - initWatchers(); | ||
100 | - }); | ||
101 | - } else { | ||
102 | - updateMatchingEntity(); | ||
103 | - initWatchers(); | ||
104 | - } | ||
105 | - } | ||
106 | - ) | ||
107 | - }*/ | ||
108 | } | 56 | } |
109 | 57 | ||
110 | scope.$watch('model.resolveMultiple', function () { | 58 | scope.$watch('model.resolveMultiple', function () { |
@@ -149,115 +97,6 @@ export default function EntityFilterDirective($compile, $templateCache, $q, $doc | @@ -149,115 +97,6 @@ export default function EntityFilterDirective($compile, $templateCache, $q, $doc | ||
149 | }); | 97 | }); |
150 | } | 98 | } |
151 | 99 | ||
152 | - /* function updateMatchingEntity() { | ||
153 | - if (scope.model.useFilter) { | ||
154 | - scope.model.matchingEntity = scope.model.matchingFilterEntity; | ||
155 | - } else { | ||
156 | - if (scope.model.entityList && scope.model.entityList.length > 0) { | ||
157 | - scope.model.matchingEntity = scope.model.entityList[0]; | ||
158 | - } else { | ||
159 | - scope.model.matchingEntity = null; | ||
160 | - } | ||
161 | - } | ||
162 | - } | ||
163 | - | ||
164 | - function processEntityNameFilter(entityNameFilter) { | ||
165 | - var deferred = $q.defer(); | ||
166 | - if (angular.isDefined(entityNameFilter) && entityNameFilter.length > 0) { | ||
167 | - scope.fetchEntities(entityNameFilter, 1).then(function (entities) { | ||
168 | - if (entities && entities.length > 0) { | ||
169 | - deferred.resolve(entities[0]); | ||
170 | - } else { | ||
171 | - deferred.resolve(null); | ||
172 | - } | ||
173 | - }); | ||
174 | - } else { | ||
175 | - deferred.resolve(null); | ||
176 | - } | ||
177 | - return deferred.promise; | ||
178 | - } | ||
179 | - | ||
180 | - function destroyWatchers() { | ||
181 | - if (scope.entityTypeDeregistration) { | ||
182 | - scope.entityTypeDeregistration(); | ||
183 | - scope.entityTypeDeregistration = null; | ||
184 | - } | ||
185 | - if (scope.entityListDeregistration) { | ||
186 | - scope.entityListDeregistration(); | ||
187 | - scope.entityListDeregistration = null; | ||
188 | - } | ||
189 | - if (scope.useFilterDeregistration) { | ||
190 | - scope.useFilterDeregistration(); | ||
191 | - scope.useFilterDeregistration = null; | ||
192 | - } | ||
193 | - if (scope.entityNameFilterDeregistration) { | ||
194 | - scope.entityNameFilterDeregistration(); | ||
195 | - scope.entityNameFilterDeregistration = null; | ||
196 | - } | ||
197 | - if (scope.matchingEntityDeregistration) { | ||
198 | - scope.matchingEntityDeregistration(); | ||
199 | - scope.matchingEntityDeregistration = null; | ||
200 | - } | ||
201 | - } | ||
202 | - | ||
203 | - function initWatchers() { | ||
204 | - | ||
205 | - scope.entityTypeDeregistration = scope.$watch('entityType', function (newEntityType, prevEntityType) { | ||
206 | - if (!angular.equals(newEntityType, prevEntityType)) { | ||
207 | - scope.model.entityList = []; | ||
208 | - scope.model.entityNameFilter = ''; | ||
209 | - } | ||
210 | - }); | ||
211 | - | ||
212 | - scope.entityListDeregistration = scope.$watch('model.entityList', function () { | ||
213 | - if (ngModelCtrl.$viewValue) { | ||
214 | - var value = ngModelCtrl.$viewValue; | ||
215 | - value.entityList = []; | ||
216 | - if (scope.model.entityList && scope.model.entityList.length > 0) { | ||
217 | - for (var i=0;i<scope.model.entityList.length;i++) { | ||
218 | - value.entityList.push(scope.model.entityList[i].id.id); | ||
219 | - } | ||
220 | - } | ||
221 | - updateMatchingEntity(); | ||
222 | - ngModelCtrl.$setViewValue(value); | ||
223 | - scope.updateValidity(); | ||
224 | - } | ||
225 | - }, true); | ||
226 | - scope.useFilterDeregistration = scope.$watch('model.useFilter', function () { | ||
227 | - if (ngModelCtrl.$viewValue) { | ||
228 | - var value = ngModelCtrl.$viewValue; | ||
229 | - value.useFilter = scope.model.useFilter; | ||
230 | - updateMatchingEntity(); | ||
231 | - ngModelCtrl.$setViewValue(value); | ||
232 | - scope.updateValidity(); | ||
233 | - } | ||
234 | - }); | ||
235 | - scope.entityNameFilterDeregistration = scope.$watch('model.entityNameFilter', function (newNameFilter, prevNameFilter) { | ||
236 | - if (ngModelCtrl.$viewValue) { | ||
237 | - if (!angular.equals(newNameFilter, prevNameFilter)) { | ||
238 | - var value = ngModelCtrl.$viewValue; | ||
239 | - value.entityNameFilter = scope.model.entityNameFilter; | ||
240 | - processEntityNameFilter(value.entityNameFilter).then( | ||
241 | - function(entity) { | ||
242 | - scope.model.matchingFilterEntity = entity; | ||
243 | - updateMatchingEntity(); | ||
244 | - ngModelCtrl.$setViewValue(value); | ||
245 | - scope.updateValidity(); | ||
246 | - } | ||
247 | - ); | ||
248 | - } | ||
249 | - } | ||
250 | - }); | ||
251 | - | ||
252 | - scope.matchingEntityDeregistration = scope.$watch('model.matchingEntity', function (newMatchingEntity, prevMatchingEntity) { | ||
253 | - if (!angular.equals(newMatchingEntity, prevMatchingEntity)) { | ||
254 | - if (scope.onMatchingEntityChange) { | ||
255 | - scope.onMatchingEntityChange({entity: newMatchingEntity}); | ||
256 | - } | ||
257 | - } | ||
258 | - }); | ||
259 | - }*/ | ||
260 | - | ||
261 | $compile(element.contents())(scope); | 100 | $compile(element.contents())(scope); |
262 | 101 | ||
263 | } | 102 | } |
@@ -14,18 +14,6 @@ | @@ -14,18 +14,6 @@ | ||
14 | * limitations under the License. | 14 | * limitations under the License. |
15 | */ | 15 | */ |
16 | .tb-entity-filter { | 16 | .tb-entity-filter { |
17 | - #entity_list_chips { | ||
18 | - .md-chips { | ||
19 | - padding-bottom: 1px; | ||
20 | - } | ||
21 | - } | ||
22 | - .entity-name-filter-input { | ||
23 | - margin-top: 10px; | ||
24 | - margin-bottom: 0px; | ||
25 | - .md-errors-spacer { | ||
26 | - min-height: 0px; | ||
27 | - } | ||
28 | - } | ||
29 | .tb-filter-switch { | 17 | .tb-filter-switch { |
30 | padding-left: 10px; | 18 | padding-left: 10px; |
31 | .filter-switch { | 19 | .filter-switch { |
@@ -39,7 +27,8 @@ | @@ -39,7 +27,8 @@ | ||
39 | margin-top: -11px; | 27 | margin-top: -11px; |
40 | height: 35px; | 28 | height: 35px; |
41 | .tb-error-message { | 29 | .tb-error-message { |
42 | - padding-left: 1px; | 30 | + padding-left: 8px; |
31 | + padding-top: 14px; | ||
43 | } | 32 | } |
44 | } | 33 | } |
45 | } | 34 | } |
@@ -15,80 +15,37 @@ | @@ -15,80 +15,37 @@ | ||
15 | limitations under the License. | 15 | limitations under the License. |
16 | 16 | ||
17 | --> | 17 | --> |
18 | -<section layout='column' class="tb-entity-filter"> | ||
19 | - <section layout='row'> | ||
20 | - <!--section layout="column" flex ng-show="!model.useFilter"> | ||
21 | - <md-chips flex | ||
22 | - id="entity_list_chips" | ||
23 | - ng-required="!useFilter" | ||
24 | - ng-model="model.entityList" md-autocomplete-snap | ||
25 | - md-require-match="true"> | ||
26 | - <md-autocomplete | ||
27 | - md-no-cache="true" | ||
28 | - id="entity" | ||
29 | - md-selected-item="selectedEntity" | ||
30 | - md-search-text="entitySearchText" | ||
31 | - md-items="item in fetchEntities(entitySearchText, 10)" | ||
32 | - md-item-text="item.name" | ||
33 | - md-min-length="0" | ||
34 | - placeholder="{{ 'entity.entity-list' | translate }}"> | ||
35 | - <md-item-template> | ||
36 | - <span md-highlight-text="entitySearchText" md-highlight-flags="^i">{{item.name}}</span> | ||
37 | - </md-item-template> | ||
38 | - <md-not-found> | ||
39 | - <span translate translate-values='{ entity: entitySearchText }'>entity.no-entities-matching</span> | ||
40 | - </md-not-found> | ||
41 | - </md-autocomplete> | ||
42 | - <md-chip-template> | ||
43 | - <span> | ||
44 | - <strong>{{$chip.name}}</strong> | ||
45 | - </span> | ||
46 | - </md-chip-template> | ||
47 | - </md-chips> | ||
48 | - </section> | ||
49 | - <section layout="row" flex ng-show="model.useFilter"> | ||
50 | - <md-input-container flex class="entity-name-filter-input"> | ||
51 | - <label translate>entity.name-starts-with</label> | ||
52 | - <input ng-model="model.entityNameFilter" aria-label="{{ 'entity.name-starts-with' | translate }}"> | ||
53 | - </md-input-container> | ||
54 | - </section--> | ||
55 | - <section layout="row" flex layout-align="start center"> | ||
56 | - <div flex ng-if="model.type">{{ types.aliasFilterType[model.type].name | translate }}</div> | ||
57 | - <md-button ng-if="model.type" ng-disabled="loading" class="md-icon-button md-primary" | ||
58 | - style="min-width: 40px;" | ||
59 | - ng-click="editFilter($event)" | ||
60 | - aria-label="{{ 'alias.edit-entity-filter' | translate }}"> | ||
61 | - <md-tooltip md-direction="top"> | ||
62 | - {{ 'alias.edit-entity-filter' | translate }} | ||
63 | - </md-tooltip> | ||
64 | - <md-icon aria-label="{{ 'alias.edit-entity-filter' | translate }}" | 18 | +<section layout='row' class="tb-entity-filter"> |
19 | + <section layout="row" flex="70"> | ||
20 | + <section flex layout="column" layout-align="center start"> | ||
21 | + <div ng-if="model.type">{{ types.aliasFilterType[model.type].name | translate }}</div> | ||
22 | + <md-button ng-if="!model.type" | ||
23 | + ng-disabled="loading" class="md-primary" | ||
24 | + ng-click="createFilter($event)" | ||
25 | + aria-label="{{ 'alias.create-entity-filter' | translate }}"> | ||
26 | + <md-icon aria-label="{{ 'alias.create-entity-filter' | translate }}" | ||
65 | class="material-icons"> | 27 | class="material-icons"> |
66 | - edit | 28 | + add |
67 | </md-icon> | 29 | </md-icon> |
30 | + {{ 'alias.create-entity-filter' | translate }} | ||
68 | </md-button> | 31 | </md-button> |
69 | - <div ng-if="!model.type" layout="row" layout-align="center start"> | ||
70 | - <md-button ng-disabled="loading" class="md-primary md-raised" | ||
71 | - ng-click="createFilter($event)" | ||
72 | - aria-label="{{ 'alias.create-entity-filter' | translate }}"> | ||
73 | - <md-icon aria-label="{{ 'alias.create-entity-filter' | translate }}" | ||
74 | - class="material-icons"> | ||
75 | - add | ||
76 | - </md-icon> | ||
77 | - {{ 'alias.create-entity-filter' | translate }} | ||
78 | - </md-button> | ||
79 | - </div> | ||
80 | - </section> | ||
81 | - <section class="tb-filter-switch" layout="column" layout-align="center center"> | ||
82 | - <label class="tb-small filter-label" translate>alias.resolve-multiple</label> | ||
83 | - <md-switch class="filter-switch" ng-model="model.resolveMultiple" aria-label="resolve-multiple-switcher"> | ||
84 | - </md-switch> | ||
85 | </section> | 32 | </section> |
33 | + <md-button ng-if="model.type" ng-disabled="loading" class="md-icon-button md-primary" | ||
34 | + style="min-width: 40px;" | ||
35 | + ng-click="editFilter($event)" | ||
36 | + aria-label="{{ 'alias.edit-entity-filter' | translate }}"> | ||
37 | + <md-tooltip md-direction="top"> | ||
38 | + {{ 'alias.edit-entity-filter' | translate }} | ||
39 | + </md-tooltip> | ||
40 | + <md-icon aria-label="{{ 'alias.edit-entity-filter' | translate }}" | ||
41 | + class="material-icons"> | ||
42 | + edit | ||
43 | + </md-icon> | ||
44 | + </md-button> | ||
45 | + </section> | ||
46 | + <section class="tb-filter-switch" layout="column" flex="30" layout-align="center center"> | ||
47 | + <label ng-if="!hideLabels" class="tb-small filter-label" translate>alias.resolve-multiple</label> | ||
48 | + <md-switch class="filter-switch" ng-model="model.resolveMultiple" aria-label="resolve-multiple-switcher"> | ||
49 | + </md-switch> | ||
86 | </section> | 50 | </section> |
87 | - <div class="tb-error-messages" ng-messages="ngModelCtrl.$error" role="alert"> | ||
88 | - <div translate ng-message="filter" class="tb-error-message">alias.entity-filter-required</div> | ||
89 | - <!--div translate ng-message="entityList" class="tb-error-message">entity.entity-list-empty</div> | ||
90 | - <div translate ng-message="entityNameFilter" class="tb-error-message">entity.entity-name-filter-required</div> | ||
91 | - <div translate translate-values='{ entity: model.entityNameFilter }' ng-message="entityNameFilterEntityMatch" | ||
92 | - class="tb-error-message">entity.entity-name-filter-no-entity-matched</div--> | ||
93 | - </div> | ||
94 | -</section> | ||
51 | +</section> |
@@ -24,7 +24,7 @@ import entityAliasesTemplate from '../entity/entity-aliases.tpl.html'; | @@ -24,7 +24,7 @@ import entityAliasesTemplate from '../entity/entity-aliases.tpl.html'; | ||
24 | /* eslint-disable no-undef, angular/window-service, angular/document-service */ | 24 | /* eslint-disable no-undef, angular/window-service, angular/document-service */ |
25 | 25 | ||
26 | /*@ngInject*/ | 26 | /*@ngInject*/ |
27 | -export default function ImportExport($log, $translate, $q, $mdDialog, $document, itembuffer, types, dashboardUtils, | 27 | +export default function ImportExport($log, $translate, $q, $mdDialog, $document, itembuffer, utils, types, dashboardUtils, |
28 | entityService, dashboardService, pluginService, ruleService, widgetService, toast) { | 28 | entityService, dashboardService, pluginService, ruleService, widgetService, toast) { |
29 | 29 | ||
30 | 30 | ||
@@ -415,6 +415,7 @@ export default function ImportExport($log, $translate, $q, $mdDialog, $document, | @@ -415,6 +415,7 @@ export default function ImportExport($log, $translate, $q, $mdDialog, $document, | ||
415 | deferred.reject(); | 415 | deferred.reject(); |
416 | } else { | 416 | } else { |
417 | var widget = widgetItem.widget; | 417 | var widget = widgetItem.widget; |
418 | + widget = dashboardUtils.validateAndUpdateWidget(widget); | ||
418 | var aliasesInfo = prepareAliasesInfo(widgetItem.aliasesInfo); | 419 | var aliasesInfo = prepareAliasesInfo(widgetItem.aliasesInfo); |
419 | var originalColumns = widgetItem.originalColumns; | 420 | var originalColumns = widgetItem.originalColumns; |
420 | var originalSize = widgetItem.originalSize; | 421 | var originalSize = widgetItem.originalSize; |
@@ -425,22 +426,22 @@ export default function ImportExport($log, $translate, $q, $mdDialog, $document, | @@ -425,22 +426,22 @@ export default function ImportExport($log, $translate, $q, $mdDialog, $document, | ||
425 | var entityAliases = {}; | 426 | var entityAliases = {}; |
426 | var datasourceAliasesMap = {}; | 427 | var datasourceAliasesMap = {}; |
427 | var targetDeviceAliasesMap = {}; | 428 | var targetDeviceAliasesMap = {}; |
428 | - var aliasId = 1; | 429 | + var aliasId; |
429 | var datasourceIndex; | 430 | var datasourceIndex; |
430 | if (datasourceAliases) { | 431 | if (datasourceAliases) { |
431 | for (datasourceIndex in datasourceAliases) { | 432 | for (datasourceIndex in datasourceAliases) { |
433 | + aliasId = utils.guid(); | ||
432 | datasourceAliasesMap[aliasId] = datasourceIndex; | 434 | datasourceAliasesMap[aliasId] = datasourceIndex; |
433 | entityAliases[aliasId] = datasourceAliases[datasourceIndex]; | 435 | entityAliases[aliasId] = datasourceAliases[datasourceIndex]; |
434 | entityAliases[aliasId].id = aliasId; | 436 | entityAliases[aliasId].id = aliasId; |
435 | - aliasId++; | ||
436 | } | 437 | } |
437 | } | 438 | } |
438 | if (targetDeviceAliases) { | 439 | if (targetDeviceAliases) { |
439 | for (datasourceIndex in targetDeviceAliases) { | 440 | for (datasourceIndex in targetDeviceAliases) { |
441 | + aliasId = utils.guid(); | ||
440 | targetDeviceAliasesMap[aliasId] = datasourceIndex; | 442 | targetDeviceAliasesMap[aliasId] = datasourceIndex; |
441 | entityAliases[aliasId] = targetDeviceAliases[datasourceIndex]; | 443 | entityAliases[aliasId] = targetDeviceAliases[datasourceIndex]; |
442 | entityAliases[aliasId].id = aliasId; | 444 | entityAliases[aliasId].id = aliasId; |
443 | - aliasId++; | ||
444 | } | 445 | } |
445 | } | 446 | } |
446 | 447 |
@@ -124,7 +124,7 @@ export default angular.module('thingsboard.locale', []) | @@ -124,7 +124,7 @@ export default angular.module('thingsboard.locale', []) | ||
124 | "create-entity-filter": "Create entity filter", | 124 | "create-entity-filter": "Create entity filter", |
125 | "edit-entity-filter": "Edit entity filter", | 125 | "edit-entity-filter": "Edit entity filter", |
126 | "entity-filter-required": "Entity filter is required.", | 126 | "entity-filter-required": "Entity filter is required.", |
127 | - "resolve-multiple": "Multiple", | 127 | + "resolve-multiple": "Resolve as multiple entities", |
128 | "filter-type": "Filter type", | 128 | "filter-type": "Filter type", |
129 | "filter-type-required": "Filter type is required.", | 129 | "filter-type-required": "Filter type is required.", |
130 | "use-state-entity": "Use state entity", | 130 | "use-state-entity": "Use state entity", |
@@ -298,11 +298,7 @@ function ItemBuffer($q, bufferStore, types, utils, dashboardUtils) { | @@ -298,11 +298,7 @@ function ItemBuffer($q, bufferStore, types, utils, dashboardUtils) { | ||
298 | } | 298 | } |
299 | if (!newAliasId) { | 299 | if (!newAliasId) { |
300 | var newAliasName = createEntityAliasName(entityAliases, aliasInfo.alias); | 300 | var newAliasName = createEntityAliasName(entityAliases, aliasInfo.alias); |
301 | - newAliasId = 0; | ||
302 | - for (aliasId in entityAliases) { | ||
303 | - newAliasId = Math.max(newAliasId, aliasId); | ||
304 | - } | ||
305 | - newAliasId++; | 301 | + newAliasId = utils.guid(); |
306 | entityAliases[newAliasId] = {id: newAliasId, alias: newAliasName, filter: aliasInfo.filter}; | 302 | entityAliases[newAliasId] = {id: newAliasId, alias: newAliasName, filter: aliasInfo.filter}; |
307 | } | 303 | } |
308 | return newAliasId; | 304 | return newAliasId; |