Commit 849f53ca4c973c0a39e6de6d3db35c4e0e56d217

Authored by Igor Kulikov
1 parent 25af06f2

Fix: don't fetch name of deleted alarm originator. Add ability to create dynamic…

… subscriptions for alarms.
... ... @@ -44,7 +44,7 @@ import java.util.stream.Collectors;
44 44 @RequestMapping("/api")
45 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 48 @RequestMapping(value = "/alarm/{alarmId}", method = RequestMethod.GET)
49 49 @ResponseBody
50 50 public Alarm getAlarmById(@PathVariable("alarmId") String strAlarmId) throws ThingsboardException {
... ... @@ -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 61 @RequestMapping(value = "/alarm/info/{alarmId}", method = RequestMethod.GET)
62 62 @ResponseBody
63 63 public AlarmInfo getAlarmInfoById(@PathVariable("alarmId") String strAlarmId) throws ThingsboardException {
... ... @@ -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 74 @RequestMapping(value = "/alarm", method = RequestMethod.POST)
75 75 @ResponseBody
76 76 public Alarm saveAlarm(@RequestBody Alarm alarm) throws ThingsboardException {
... ... @@ -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 86 @RequestMapping(value = "/alarm/{alarmId}/ack", method = RequestMethod.POST)
87 87 @ResponseStatus(value = HttpStatus.OK)
88 88 public void ackAlarm(@PathVariable("alarmId") String strAlarmId) throws ThingsboardException {
... ... @@ -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 100 @RequestMapping(value = "/alarm/{alarmId}/clear", method = RequestMethod.POST)
101 101 @ResponseStatus(value = HttpStatus.OK)
102 102 public void clearAlarm(@PathVariable("alarmId") String strAlarmId) throws ThingsboardException {
... ... @@ -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 114 @RequestMapping(value = "/alarm/{entityType}/{entityId}", method = RequestMethod.GET)
115 115 @ResponseBody
116 116 public TimePageData<AlarmInfo> getAlarms(
... ... @@ -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 147 @RequestMapping(value = "/alarm/highestSeverity/{entityType}/{entityId}", method = RequestMethod.GET)
148 148 @ResponseBody
149 149 public AlarmSeverity getHighestAlarmSeverity(
... ...
... ... @@ -227,6 +227,9 @@ public class BaseAlarmService extends AbstractEntityService implements AlarmServ
227 227 alarmFutures.add(Futures.transform(
228 228 entityService.fetchEntityNameAsync(alarmInfo.getOriginator()), (Function<String, AlarmInfo>)
229 229 originatorName -> {
  230 + if (originatorName == null) {
  231 + originatorName = "Deleted";
  232 + }
230 233 alarmInfo.setOriginatorName(originatorName);
231 234 return alarmInfo;
232 235 }
... ...
... ... @@ -109,7 +109,7 @@ public class BaseEntityService extends AbstractEntityService implements EntitySe
109 109 default:
110 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 113 return entityName;
114 114 }
115 115
... ...
... ... @@ -84,7 +84,6 @@ public class BaseRelationService implements RelationService {
84 84 for (RelationTypeGroup typeGroup : RelationTypeGroup.values()) {
85 85 inboundRelationsList.add(relationDao.findAllByTo(entity, typeGroup));
86 86 }
87   - Futures.allAsList(inboundRelationsList);
88 87 ListenableFuture<List<List<EntityRelation>>> inboundRelations = Futures.allAsList(inboundRelationsList);
89 88 ListenableFuture<List<Boolean>> inboundDeletions = Futures.transform(inboundRelations, new AsyncFunction<List<List<EntityRelation>>, List<Boolean>>() {
90 89 @Override
... ...
... ... @@ -35,6 +35,7 @@ function EntityService($http, $q, $filter, $translate, $log, userService, device
35 35 prepareAllowedEntityTypesList: prepareAllowedEntityTypesList,
36 36 getEntityKeys: getEntityKeys,
37 37 createDatasourcesFromSubscriptionsInfo: createDatasourcesFromSubscriptionsInfo,
  38 + createAlarmSourceFromSubscriptionInfo: createAlarmSourceFromSubscriptionInfo,
38 39 getRelatedEntities: getRelatedEntities,
39 40 saveRelatedEntity: saveRelatedEntity,
40 41 getRelatedEntity: getRelatedEntity,
... ... @@ -757,6 +758,26 @@ function EntityService($http, $q, $filter, $translate, $log, userService, device
757 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 781 function processSubscriptionsInfo(index, subscriptionsInfo, datasources, deferred) {
761 782 if (index < subscriptionsInfo.length) {
762 783 var subscriptionInfo = validateSubscriptionInfo(subscriptionsInfo[index]);
... ... @@ -858,6 +879,9 @@ function EntityService($http, $q, $filter, $translate, $log, userService, device
858 879 if (subscriptionInfo.functions) {
859 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 887 function createDatasourceKeys(keyInfos, type, datasource, datasources) {
... ...
... ... @@ -61,47 +61,57 @@ export default angular.module('thingsboard.types', [])
61 61 },
62 62 alarmFields: {
63 63 createdTime: {
  64 + keyName: 'createdTime',
64 65 value: "createdTime",
65 66 name: "alarm.created-time",
66 67 time: true
67 68 },
68 69 startTime: {
  70 + keyName: 'startTime',
69 71 value: "startTs",
70 72 name: "alarm.start-time",
71 73 time: true
72 74 },
73 75 endTime: {
  76 + keyName: 'endTime',
74 77 value: "endTs",
75 78 name: "alarm.end-time",
76 79 time: true
77 80 },
78 81 ackTime: {
  82 + keyName: 'ackTime',
79 83 value: "ackTs",
80 84 name: "alarm.ack-time",
81 85 time: true
82 86 },
83 87 clearTime: {
  88 + keyName: 'clearTime',
84 89 value: "clearTs",
85 90 name: "alarm.clear-time",
86 91 time: true
87 92 },
88 93 originator: {
  94 + keyName: 'originator',
89 95 value: "originatorName",
90 96 name: "alarm.originator"
91 97 },
92 98 originatorType: {
  99 + keyName: 'originatorType',
93 100 value: "originator.entityType",
94 101 name: "alarm.originator-type"
95 102 },
96 103 type: {
  104 + keyName: 'type',
97 105 value: "type",
98 106 name: "alarm.type"
99 107 },
100 108 severity: {
  109 + keyName: 'severity',
101 110 value: "severity",
102 111 name: "alarm.severity"
103 112 },
104 113 status: {
  114 + keyName: 'status',
105 115 value: "status",
106 116 name: "alarm.status"
107 117 }
... ...
... ... @@ -96,11 +96,11 @@ function Utils($mdColorPalette, $rootScope, $window, $translate, types) {
96 96 };
97 97
98 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 106 var defaultAlarmDataKeys = [];
... ... @@ -376,10 +376,20 @@ function Utils($mdColorPalette, $rootScope, $window, $translate, types) {
376 376 }
377 377
378 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 389 var dataKey = {
380 390 name: keyInfo.name,
381 391 type: type,
382   - label: keyInfo.label || keyInfo.name,
  392 + label: label,
383 393 color: genNextColor(datasources),
384 394 funcBody: keyInfo.funcBody,
385 395 settings: {},
... ...
... ... @@ -36,6 +36,8 @@ export default function WidgetController($scope, $timeout, $window, $element, $q
36 36 $scope.rpcEnabled = false;
37 37 $scope.executingRpcRequest = false;
38 38
  39 + vm.dashboardTimewindow = dashboardTimewindow;
  40 +
39 41 var gridsterItemInited = false;
40 42 var subscriptionInited = false;
41 43 var widgetSizeDetected = false;
... ... @@ -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 211 createSubscription(options, subscribe).then(
199 212 function success(subscription) {
200 213 if (useDefaultComponents) {
... ... @@ -213,7 +226,7 @@ export default function WidgetController($scope, $timeout, $window, $element, $q
213 226
214 227 function createSubscription(options, subscribe) {
215 228 var deferred = $q.defer();
216   - options.dashboardTimewindow = dashboardTimewindow;
  229 + options.dashboardTimewindow = vm.dashboardTimewindow;
217 230 new Subscription(subscriptionContext, options).then(
218 231 function success(subscription) {
219 232 widgetContext.subscriptions[subscription.id] = subscription;
... ... @@ -234,7 +247,7 @@ export default function WidgetController($scope, $timeout, $window, $element, $q
234 247 options.useDashboardTimewindow = angular.isDefined(widget.config.useDashboardTimewindow)
235 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 251 options.legendConfig = null;
239 252
240 253 if ($scope.displayLegend) {
... ... @@ -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 524 $scope.$on("$destroy", function () {
508 525 onDestroy();
509 526 });
... ...