Commit 849f53ca4c973c0a39e6de6d3db35c4e0e56d217
1 parent
25af06f2
Fix: don't fetch name of deleted alarm originator. Add ability to create dynamic…
… subscriptions for alarms.
Showing
8 changed files
with
83 additions
and
20 deletions
@@ -44,7 +44,7 @@ import java.util.stream.Collectors; | @@ -44,7 +44,7 @@ import java.util.stream.Collectors; | ||
44 | @RequestMapping("/api") | 44 | @RequestMapping("/api") |
45 | public class AlarmController extends BaseController { | 45 | public class AlarmController extends BaseController { |
46 | 46 | ||
47 | - @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") | 47 | + @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") |
48 | @RequestMapping(value = "/alarm/{alarmId}", method = RequestMethod.GET) | 48 | @RequestMapping(value = "/alarm/{alarmId}", method = RequestMethod.GET) |
49 | @ResponseBody | 49 | @ResponseBody |
50 | public Alarm getAlarmById(@PathVariable("alarmId") String strAlarmId) throws ThingsboardException { | 50 | public Alarm getAlarmById(@PathVariable("alarmId") String strAlarmId) throws ThingsboardException { |
@@ -57,7 +57,7 @@ public class AlarmController extends BaseController { | @@ -57,7 +57,7 @@ public class AlarmController extends BaseController { | ||
57 | } | 57 | } |
58 | } | 58 | } |
59 | 59 | ||
60 | - @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") | 60 | + @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") |
61 | @RequestMapping(value = "/alarm/info/{alarmId}", method = RequestMethod.GET) | 61 | @RequestMapping(value = "/alarm/info/{alarmId}", method = RequestMethod.GET) |
62 | @ResponseBody | 62 | @ResponseBody |
63 | public AlarmInfo getAlarmInfoById(@PathVariable("alarmId") String strAlarmId) throws ThingsboardException { | 63 | public AlarmInfo getAlarmInfoById(@PathVariable("alarmId") String strAlarmId) throws ThingsboardException { |
@@ -70,7 +70,7 @@ public class AlarmController extends BaseController { | @@ -70,7 +70,7 @@ public class AlarmController extends BaseController { | ||
70 | } | 70 | } |
71 | } | 71 | } |
72 | 72 | ||
73 | - @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") | 73 | + @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") |
74 | @RequestMapping(value = "/alarm", method = RequestMethod.POST) | 74 | @RequestMapping(value = "/alarm", method = RequestMethod.POST) |
75 | @ResponseBody | 75 | @ResponseBody |
76 | public Alarm saveAlarm(@RequestBody Alarm alarm) throws ThingsboardException { | 76 | public Alarm saveAlarm(@RequestBody Alarm alarm) throws ThingsboardException { |
@@ -82,7 +82,7 @@ public class AlarmController extends BaseController { | @@ -82,7 +82,7 @@ public class AlarmController extends BaseController { | ||
82 | } | 82 | } |
83 | } | 83 | } |
84 | 84 | ||
85 | - @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") | 85 | + @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") |
86 | @RequestMapping(value = "/alarm/{alarmId}/ack", method = RequestMethod.POST) | 86 | @RequestMapping(value = "/alarm/{alarmId}/ack", method = RequestMethod.POST) |
87 | @ResponseStatus(value = HttpStatus.OK) | 87 | @ResponseStatus(value = HttpStatus.OK) |
88 | public void ackAlarm(@PathVariable("alarmId") String strAlarmId) throws ThingsboardException { | 88 | public void ackAlarm(@PathVariable("alarmId") String strAlarmId) throws ThingsboardException { |
@@ -96,7 +96,7 @@ public class AlarmController extends BaseController { | @@ -96,7 +96,7 @@ public class AlarmController extends BaseController { | ||
96 | } | 96 | } |
97 | } | 97 | } |
98 | 98 | ||
99 | - @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") | 99 | + @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") |
100 | @RequestMapping(value = "/alarm/{alarmId}/clear", method = RequestMethod.POST) | 100 | @RequestMapping(value = "/alarm/{alarmId}/clear", method = RequestMethod.POST) |
101 | @ResponseStatus(value = HttpStatus.OK) | 101 | @ResponseStatus(value = HttpStatus.OK) |
102 | public void clearAlarm(@PathVariable("alarmId") String strAlarmId) throws ThingsboardException { | 102 | public void clearAlarm(@PathVariable("alarmId") String strAlarmId) throws ThingsboardException { |
@@ -110,7 +110,7 @@ public class AlarmController extends BaseController { | @@ -110,7 +110,7 @@ public class AlarmController extends BaseController { | ||
110 | } | 110 | } |
111 | } | 111 | } |
112 | 112 | ||
113 | - @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") | 113 | + @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") |
114 | @RequestMapping(value = "/alarm/{entityType}/{entityId}", method = RequestMethod.GET) | 114 | @RequestMapping(value = "/alarm/{entityType}/{entityId}", method = RequestMethod.GET) |
115 | @ResponseBody | 115 | @ResponseBody |
116 | public TimePageData<AlarmInfo> getAlarms( | 116 | public TimePageData<AlarmInfo> getAlarms( |
@@ -143,7 +143,7 @@ public class AlarmController extends BaseController { | @@ -143,7 +143,7 @@ public class AlarmController extends BaseController { | ||
143 | } | 143 | } |
144 | } | 144 | } |
145 | 145 | ||
146 | - @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") | 146 | + @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") |
147 | @RequestMapping(value = "/alarm/highestSeverity/{entityType}/{entityId}", method = RequestMethod.GET) | 147 | @RequestMapping(value = "/alarm/highestSeverity/{entityType}/{entityId}", method = RequestMethod.GET) |
148 | @ResponseBody | 148 | @ResponseBody |
149 | public AlarmSeverity getHighestAlarmSeverity( | 149 | public AlarmSeverity getHighestAlarmSeverity( |
@@ -227,6 +227,9 @@ public class BaseAlarmService extends AbstractEntityService implements AlarmServ | @@ -227,6 +227,9 @@ public class BaseAlarmService extends AbstractEntityService implements AlarmServ | ||
227 | alarmFutures.add(Futures.transform( | 227 | alarmFutures.add(Futures.transform( |
228 | entityService.fetchEntityNameAsync(alarmInfo.getOriginator()), (Function<String, AlarmInfo>) | 228 | entityService.fetchEntityNameAsync(alarmInfo.getOriginator()), (Function<String, AlarmInfo>) |
229 | originatorName -> { | 229 | originatorName -> { |
230 | + if (originatorName == null) { | ||
231 | + originatorName = "Deleted"; | ||
232 | + } | ||
230 | alarmInfo.setOriginatorName(originatorName); | 233 | alarmInfo.setOriginatorName(originatorName); |
231 | return alarmInfo; | 234 | return alarmInfo; |
232 | } | 235 | } |
@@ -109,7 +109,7 @@ public class BaseEntityService extends AbstractEntityService implements EntitySe | @@ -109,7 +109,7 @@ public class BaseEntityService extends AbstractEntityService implements EntitySe | ||
109 | default: | 109 | default: |
110 | throw new IllegalStateException("Not Implemented!"); | 110 | throw new IllegalStateException("Not Implemented!"); |
111 | } | 111 | } |
112 | - entityName = Futures.transform(hasName, (Function<HasName, String>) hasName1 -> hasName1.getName() ); | 112 | + entityName = Futures.transform(hasName, (Function<HasName, String>) hasName1 -> hasName1 != null ? hasName1.getName() : null ); |
113 | return entityName; | 113 | return entityName; |
114 | } | 114 | } |
115 | 115 |
@@ -84,7 +84,6 @@ public class BaseRelationService implements RelationService { | @@ -84,7 +84,6 @@ public class BaseRelationService implements RelationService { | ||
84 | for (RelationTypeGroup typeGroup : RelationTypeGroup.values()) { | 84 | for (RelationTypeGroup typeGroup : RelationTypeGroup.values()) { |
85 | inboundRelationsList.add(relationDao.findAllByTo(entity, typeGroup)); | 85 | inboundRelationsList.add(relationDao.findAllByTo(entity, typeGroup)); |
86 | } | 86 | } |
87 | - Futures.allAsList(inboundRelationsList); | ||
88 | ListenableFuture<List<List<EntityRelation>>> inboundRelations = Futures.allAsList(inboundRelationsList); | 87 | ListenableFuture<List<List<EntityRelation>>> inboundRelations = Futures.allAsList(inboundRelationsList); |
89 | ListenableFuture<List<Boolean>> inboundDeletions = Futures.transform(inboundRelations, new AsyncFunction<List<List<EntityRelation>>, List<Boolean>>() { | 88 | ListenableFuture<List<Boolean>> inboundDeletions = Futures.transform(inboundRelations, new AsyncFunction<List<List<EntityRelation>>, List<Boolean>>() { |
90 | @Override | 89 | @Override |
@@ -35,6 +35,7 @@ function EntityService($http, $q, $filter, $translate, $log, userService, device | @@ -35,6 +35,7 @@ function EntityService($http, $q, $filter, $translate, $log, userService, device | ||
35 | prepareAllowedEntityTypesList: prepareAllowedEntityTypesList, | 35 | prepareAllowedEntityTypesList: prepareAllowedEntityTypesList, |
36 | getEntityKeys: getEntityKeys, | 36 | getEntityKeys: getEntityKeys, |
37 | createDatasourcesFromSubscriptionsInfo: createDatasourcesFromSubscriptionsInfo, | 37 | createDatasourcesFromSubscriptionsInfo: createDatasourcesFromSubscriptionsInfo, |
38 | + createAlarmSourceFromSubscriptionInfo: createAlarmSourceFromSubscriptionInfo, | ||
38 | getRelatedEntities: getRelatedEntities, | 39 | getRelatedEntities: getRelatedEntities, |
39 | saveRelatedEntity: saveRelatedEntity, | 40 | saveRelatedEntity: saveRelatedEntity, |
40 | getRelatedEntity: getRelatedEntity, | 41 | getRelatedEntity: getRelatedEntity, |
@@ -757,6 +758,26 @@ function EntityService($http, $q, $filter, $translate, $log, userService, device | @@ -757,6 +758,26 @@ function EntityService($http, $q, $filter, $translate, $log, userService, device | ||
757 | return deferred.promise; | 758 | return deferred.promise; |
758 | } | 759 | } |
759 | 760 | ||
761 | + function createAlarmSourceFromSubscriptionInfo(subscriptionInfo) { | ||
762 | + var deferred = $q.defer(); | ||
763 | + var datasources = []; | ||
764 | + if (subscriptionInfo.entityId && subscriptionInfo.entityType) { | ||
765 | + getEntity(subscriptionInfo.entityType, subscriptionInfo.entityId, {ignoreLoading: true}).then( | ||
766 | + function success(entity) { | ||
767 | + createDatasourceFromSubscription(subscriptionInfo, datasources, entity); | ||
768 | + var alarmSource = datasources[0]; | ||
769 | + deferred.resolve(alarmSource); | ||
770 | + }, | ||
771 | + function fail() { | ||
772 | + deferred.reject(); | ||
773 | + } | ||
774 | + ); | ||
775 | + } else { | ||
776 | + deferred.reject(); | ||
777 | + } | ||
778 | + return deferred.promise; | ||
779 | + } | ||
780 | + | ||
760 | function processSubscriptionsInfo(index, subscriptionsInfo, datasources, deferred) { | 781 | function processSubscriptionsInfo(index, subscriptionsInfo, datasources, deferred) { |
761 | if (index < subscriptionsInfo.length) { | 782 | if (index < subscriptionsInfo.length) { |
762 | var subscriptionInfo = validateSubscriptionInfo(subscriptionsInfo[index]); | 783 | var subscriptionInfo = validateSubscriptionInfo(subscriptionsInfo[index]); |
@@ -858,6 +879,9 @@ function EntityService($http, $q, $filter, $translate, $log, userService, device | @@ -858,6 +879,9 @@ function EntityService($http, $q, $filter, $translate, $log, userService, device | ||
858 | if (subscriptionInfo.functions) { | 879 | if (subscriptionInfo.functions) { |
859 | createDatasourceKeys(subscriptionInfo.functions, types.dataKeyType.function, datasource, datasources); | 880 | createDatasourceKeys(subscriptionInfo.functions, types.dataKeyType.function, datasource, datasources); |
860 | } | 881 | } |
882 | + if (subscriptionInfo.alarmFields) { | ||
883 | + createDatasourceKeys(subscriptionInfo.alarmFields, types.dataKeyType.alarm, datasource, datasources); | ||
884 | + } | ||
861 | } | 885 | } |
862 | 886 | ||
863 | function createDatasourceKeys(keyInfos, type, datasource, datasources) { | 887 | function createDatasourceKeys(keyInfos, type, datasource, datasources) { |
@@ -61,47 +61,57 @@ export default angular.module('thingsboard.types', []) | @@ -61,47 +61,57 @@ export default angular.module('thingsboard.types', []) | ||
61 | }, | 61 | }, |
62 | alarmFields: { | 62 | alarmFields: { |
63 | createdTime: { | 63 | createdTime: { |
64 | + keyName: 'createdTime', | ||
64 | value: "createdTime", | 65 | value: "createdTime", |
65 | name: "alarm.created-time", | 66 | name: "alarm.created-time", |
66 | time: true | 67 | time: true |
67 | }, | 68 | }, |
68 | startTime: { | 69 | startTime: { |
70 | + keyName: 'startTime', | ||
69 | value: "startTs", | 71 | value: "startTs", |
70 | name: "alarm.start-time", | 72 | name: "alarm.start-time", |
71 | time: true | 73 | time: true |
72 | }, | 74 | }, |
73 | endTime: { | 75 | endTime: { |
76 | + keyName: 'endTime', | ||
74 | value: "endTs", | 77 | value: "endTs", |
75 | name: "alarm.end-time", | 78 | name: "alarm.end-time", |
76 | time: true | 79 | time: true |
77 | }, | 80 | }, |
78 | ackTime: { | 81 | ackTime: { |
82 | + keyName: 'ackTime', | ||
79 | value: "ackTs", | 83 | value: "ackTs", |
80 | name: "alarm.ack-time", | 84 | name: "alarm.ack-time", |
81 | time: true | 85 | time: true |
82 | }, | 86 | }, |
83 | clearTime: { | 87 | clearTime: { |
88 | + keyName: 'clearTime', | ||
84 | value: "clearTs", | 89 | value: "clearTs", |
85 | name: "alarm.clear-time", | 90 | name: "alarm.clear-time", |
86 | time: true | 91 | time: true |
87 | }, | 92 | }, |
88 | originator: { | 93 | originator: { |
94 | + keyName: 'originator', | ||
89 | value: "originatorName", | 95 | value: "originatorName", |
90 | name: "alarm.originator" | 96 | name: "alarm.originator" |
91 | }, | 97 | }, |
92 | originatorType: { | 98 | originatorType: { |
99 | + keyName: 'originatorType', | ||
93 | value: "originator.entityType", | 100 | value: "originator.entityType", |
94 | name: "alarm.originator-type" | 101 | name: "alarm.originator-type" |
95 | }, | 102 | }, |
96 | type: { | 103 | type: { |
104 | + keyName: 'type', | ||
97 | value: "type", | 105 | value: "type", |
98 | name: "alarm.type" | 106 | name: "alarm.type" |
99 | }, | 107 | }, |
100 | severity: { | 108 | severity: { |
109 | + keyName: 'severity', | ||
101 | value: "severity", | 110 | value: "severity", |
102 | name: "alarm.severity" | 111 | name: "alarm.severity" |
103 | }, | 112 | }, |
104 | status: { | 113 | status: { |
114 | + keyName: 'status', | ||
105 | value: "status", | 115 | value: "status", |
106 | name: "alarm.status" | 116 | name: "alarm.status" |
107 | } | 117 | } |
@@ -96,11 +96,11 @@ function Utils($mdColorPalette, $rootScope, $window, $translate, types) { | @@ -96,11 +96,11 @@ function Utils($mdColorPalette, $rootScope, $window, $translate, types) { | ||
96 | }; | 96 | }; |
97 | 97 | ||
98 | var defaultAlarmFields = [ | 98 | var defaultAlarmFields = [ |
99 | - 'createdTime', | ||
100 | - 'originator', | ||
101 | - 'type', | ||
102 | - 'severity', | ||
103 | - 'status' | 99 | + types.alarmFields.createdTime.keyName, |
100 | + types.alarmFields.originator.keyName, | ||
101 | + types.alarmFields.type.keyName, | ||
102 | + types.alarmFields.severity.keyName, | ||
103 | + types.alarmFields.status.keyName | ||
104 | ]; | 104 | ]; |
105 | 105 | ||
106 | var defaultAlarmDataKeys = []; | 106 | var defaultAlarmDataKeys = []; |
@@ -376,10 +376,20 @@ function Utils($mdColorPalette, $rootScope, $window, $translate, types) { | @@ -376,10 +376,20 @@ function Utils($mdColorPalette, $rootScope, $window, $translate, types) { | ||
376 | } | 376 | } |
377 | 377 | ||
378 | function createKey(keyInfo, type, datasources) { | 378 | function createKey(keyInfo, type, datasources) { |
379 | + var label; | ||
380 | + if (type === types.dataKeyType.alarm && !keyInfo.label) { | ||
381 | + var alarmField = types.alarmFields[keyInfo.name]; | ||
382 | + if (alarmField) { | ||
383 | + label = $translate.instant(alarmField.name)+''; | ||
384 | + } | ||
385 | + } | ||
386 | + if (!label) { | ||
387 | + label = keyInfo.label || keyInfo.name; | ||
388 | + } | ||
379 | var dataKey = { | 389 | var dataKey = { |
380 | name: keyInfo.name, | 390 | name: keyInfo.name, |
381 | type: type, | 391 | type: type, |
382 | - label: keyInfo.label || keyInfo.name, | 392 | + label: label, |
383 | color: genNextColor(datasources), | 393 | color: genNextColor(datasources), |
384 | funcBody: keyInfo.funcBody, | 394 | funcBody: keyInfo.funcBody, |
385 | settings: {}, | 395 | settings: {}, |
@@ -36,6 +36,8 @@ export default function WidgetController($scope, $timeout, $window, $element, $q | @@ -36,6 +36,8 @@ export default function WidgetController($scope, $timeout, $window, $element, $q | ||
36 | $scope.rpcEnabled = false; | 36 | $scope.rpcEnabled = false; |
37 | $scope.executingRpcRequest = false; | 37 | $scope.executingRpcRequest = false; |
38 | 38 | ||
39 | + vm.dashboardTimewindow = dashboardTimewindow; | ||
40 | + | ||
39 | var gridsterItemInited = false; | 41 | var gridsterItemInited = false; |
40 | var subscriptionInited = false; | 42 | var subscriptionInited = false; |
41 | var widgetSizeDetected = false; | 43 | var widgetSizeDetected = false; |
@@ -192,9 +194,20 @@ export default function WidgetController($scope, $timeout, $window, $element, $q | @@ -192,9 +194,20 @@ export default function WidgetController($scope, $timeout, $window, $element, $q | ||
192 | } | 194 | } |
193 | } | 195 | } |
194 | 196 | ||
195 | - entityService.createDatasourcesFromSubscriptionsInfo(subscriptionsInfo).then( | ||
196 | - function (datasources) { | ||
197 | - options.datasources = datasources; | 197 | + var createDatasourcesPromise; |
198 | + if (options.type == types.widgetType.alarm.value) { | ||
199 | + createDatasourcesPromise = entityService.createAlarmSourceFromSubscriptionInfo(subscriptionsInfo); | ||
200 | + } else { | ||
201 | + createDatasourcesPromise = entityService.createDatasourcesFromSubscriptionsInfo(subscriptionsInfo); | ||
202 | + } | ||
203 | + | ||
204 | + createDatasourcesPromise.then( | ||
205 | + function (result) { | ||
206 | + if (options.type == types.widgetType.alarm.value) { | ||
207 | + options.alarmSource = result; | ||
208 | + } else { | ||
209 | + options.datasources = result; | ||
210 | + } | ||
198 | createSubscription(options, subscribe).then( | 211 | createSubscription(options, subscribe).then( |
199 | function success(subscription) { | 212 | function success(subscription) { |
200 | if (useDefaultComponents) { | 213 | if (useDefaultComponents) { |
@@ -213,7 +226,7 @@ export default function WidgetController($scope, $timeout, $window, $element, $q | @@ -213,7 +226,7 @@ export default function WidgetController($scope, $timeout, $window, $element, $q | ||
213 | 226 | ||
214 | function createSubscription(options, subscribe) { | 227 | function createSubscription(options, subscribe) { |
215 | var deferred = $q.defer(); | 228 | var deferred = $q.defer(); |
216 | - options.dashboardTimewindow = dashboardTimewindow; | 229 | + options.dashboardTimewindow = vm.dashboardTimewindow; |
217 | new Subscription(subscriptionContext, options).then( | 230 | new Subscription(subscriptionContext, options).then( |
218 | function success(subscription) { | 231 | function success(subscription) { |
219 | widgetContext.subscriptions[subscription.id] = subscription; | 232 | widgetContext.subscriptions[subscription.id] = subscription; |
@@ -234,7 +247,7 @@ export default function WidgetController($scope, $timeout, $window, $element, $q | @@ -234,7 +247,7 @@ export default function WidgetController($scope, $timeout, $window, $element, $q | ||
234 | options.useDashboardTimewindow = angular.isDefined(widget.config.useDashboardTimewindow) | 247 | options.useDashboardTimewindow = angular.isDefined(widget.config.useDashboardTimewindow) |
235 | ? widget.config.useDashboardTimewindow : true; | 248 | ? widget.config.useDashboardTimewindow : true; |
236 | 249 | ||
237 | - options.timeWindowConfig = options.useDashboardTimewindow ? dashboardTimewindow : widget.config.timewindow; | 250 | + options.timeWindowConfig = options.useDashboardTimewindow ? vm.dashboardTimewindow : widget.config.timewindow; |
238 | options.legendConfig = null; | 251 | options.legendConfig = null; |
239 | 252 | ||
240 | if ($scope.displayLegend) { | 253 | if ($scope.displayLegend) { |
@@ -504,6 +517,10 @@ export default function WidgetController($scope, $timeout, $window, $element, $q | @@ -504,6 +517,10 @@ export default function WidgetController($scope, $timeout, $window, $element, $q | ||
504 | } | 517 | } |
505 | }); | 518 | }); |
506 | 519 | ||
520 | + $scope.$on('dashboardTimewindowChanged', function (event, newDashboardTimewindow) { | ||
521 | + vm.dashboardTimewindow = newDashboardTimewindow; | ||
522 | + }); | ||
523 | + | ||
507 | $scope.$on("$destroy", function () { | 524 | $scope.$on("$destroy", function () { |
508 | onDestroy(); | 525 | onDestroy(); |
509 | }); | 526 | }); |