thingsboard-memoizeit

Details

diff --git a/application/src/main/java/org/thingsboard/server/controller/AlarmController.java b/application/src/main/java/org/thingsboard/server/controller/AlarmController.java
index baee889..e301138 100644
--- a/application/src/main/java/org/thingsboard/server/controller/AlarmController.java
+++ b/application/src/main/java/org/thingsboard/server/controller/AlarmController.java
@@ -44,7 +44,7 @@ import java.util.stream.Collectors;
 @RequestMapping("/api")
 public class AlarmController extends BaseController {
 
-    @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
+    @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')")
     @RequestMapping(value = "/alarm/{alarmId}", method = RequestMethod.GET)
     @ResponseBody
     public Alarm getAlarmById(@PathVariable("alarmId") String strAlarmId) throws ThingsboardException {
@@ -57,7 +57,7 @@ public class AlarmController extends BaseController {
         }
     }
 
-    @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
+    @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')")
     @RequestMapping(value = "/alarm/info/{alarmId}", method = RequestMethod.GET)
     @ResponseBody
     public AlarmInfo getAlarmInfoById(@PathVariable("alarmId") String strAlarmId) throws ThingsboardException {
@@ -70,7 +70,7 @@ public class AlarmController extends BaseController {
         }
     }
 
-    @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
+    @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')")
     @RequestMapping(value = "/alarm", method = RequestMethod.POST)
     @ResponseBody
     public Alarm saveAlarm(@RequestBody Alarm alarm) throws ThingsboardException {
@@ -82,7 +82,7 @@ public class AlarmController extends BaseController {
         }
     }
 
-    @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
+    @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')")
     @RequestMapping(value = "/alarm/{alarmId}/ack", method = RequestMethod.POST)
     @ResponseStatus(value = HttpStatus.OK)
     public void ackAlarm(@PathVariable("alarmId") String strAlarmId) throws ThingsboardException {
@@ -96,7 +96,7 @@ public class AlarmController extends BaseController {
         }
     }
 
-    @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
+    @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')")
     @RequestMapping(value = "/alarm/{alarmId}/clear", method = RequestMethod.POST)
     @ResponseStatus(value = HttpStatus.OK)
     public void clearAlarm(@PathVariable("alarmId") String strAlarmId) throws ThingsboardException {
@@ -110,7 +110,7 @@ public class AlarmController extends BaseController {
         }
     }
 
-    @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
+    @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')")
     @RequestMapping(value = "/alarm/{entityType}/{entityId}", method = RequestMethod.GET)
     @ResponseBody
     public TimePageData<AlarmInfo> getAlarms(
@@ -143,7 +143,7 @@ public class AlarmController extends BaseController {
         }
     }
 
-    @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
+    @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')")
     @RequestMapping(value = "/alarm/highestSeverity/{entityType}/{entityId}", method = RequestMethod.GET)
     @ResponseBody
     public AlarmSeverity getHighestAlarmSeverity(
diff --git a/dao/src/main/java/org/thingsboard/server/dao/alarm/BaseAlarmService.java b/dao/src/main/java/org/thingsboard/server/dao/alarm/BaseAlarmService.java
index 06a9b34..785d029 100644
--- a/dao/src/main/java/org/thingsboard/server/dao/alarm/BaseAlarmService.java
+++ b/dao/src/main/java/org/thingsboard/server/dao/alarm/BaseAlarmService.java
@@ -227,6 +227,9 @@ public class BaseAlarmService extends AbstractEntityService implements AlarmServ
                     alarmFutures.add(Futures.transform(
                             entityService.fetchEntityNameAsync(alarmInfo.getOriginator()), (Function<String, AlarmInfo>)
                                     originatorName -> {
+                                        if (originatorName == null) {
+                                            originatorName = "Deleted";
+                                        }
                                         alarmInfo.setOriginatorName(originatorName);
                                         return alarmInfo;
                                     }
diff --git a/dao/src/main/java/org/thingsboard/server/dao/entity/BaseEntityService.java b/dao/src/main/java/org/thingsboard/server/dao/entity/BaseEntityService.java
index 6f9500e..68844dc 100644
--- a/dao/src/main/java/org/thingsboard/server/dao/entity/BaseEntityService.java
+++ b/dao/src/main/java/org/thingsboard/server/dao/entity/BaseEntityService.java
@@ -109,7 +109,7 @@ public class BaseEntityService extends AbstractEntityService implements EntitySe
             default:
                 throw new IllegalStateException("Not Implemented!");
         }
-        entityName = Futures.transform(hasName, (Function<HasName, String>) hasName1 -> hasName1.getName() );
+        entityName = Futures.transform(hasName, (Function<HasName, String>) hasName1 -> hasName1 != null ? hasName1.getName() : null );
         return entityName;
     }
 
diff --git a/dao/src/main/java/org/thingsboard/server/dao/relation/BaseRelationService.java b/dao/src/main/java/org/thingsboard/server/dao/relation/BaseRelationService.java
index 296874e..d9b2f44 100644
--- a/dao/src/main/java/org/thingsboard/server/dao/relation/BaseRelationService.java
+++ b/dao/src/main/java/org/thingsboard/server/dao/relation/BaseRelationService.java
@@ -84,7 +84,6 @@ public class BaseRelationService implements RelationService {
         for (RelationTypeGroup typeGroup : RelationTypeGroup.values()) {
             inboundRelationsList.add(relationDao.findAllByTo(entity, typeGroup));
         }
-        Futures.allAsList(inboundRelationsList);
         ListenableFuture<List<List<EntityRelation>>> inboundRelations = Futures.allAsList(inboundRelationsList);
         ListenableFuture<List<Boolean>> inboundDeletions = Futures.transform(inboundRelations, new AsyncFunction<List<List<EntityRelation>>, List<Boolean>>() {
             @Override
diff --git a/ui/src/app/api/entity.service.js b/ui/src/app/api/entity.service.js
index 20157ce..9cf08d9 100644
--- a/ui/src/app/api/entity.service.js
+++ b/ui/src/app/api/entity.service.js
@@ -35,6 +35,7 @@ function EntityService($http, $q, $filter, $translate, $log, userService, device
         prepareAllowedEntityTypesList: prepareAllowedEntityTypesList,
         getEntityKeys: getEntityKeys,
         createDatasourcesFromSubscriptionsInfo: createDatasourcesFromSubscriptionsInfo,
+        createAlarmSourceFromSubscriptionInfo: createAlarmSourceFromSubscriptionInfo,
         getRelatedEntities: getRelatedEntities,
         saveRelatedEntity: saveRelatedEntity,
         getRelatedEntity: getRelatedEntity,
@@ -757,6 +758,26 @@ function EntityService($http, $q, $filter, $translate, $log, userService, device
         return deferred.promise;
     }
 
+    function createAlarmSourceFromSubscriptionInfo(subscriptionInfo) {
+        var deferred = $q.defer();
+        var datasources = [];
+        if (subscriptionInfo.entityId && subscriptionInfo.entityType) {
+            getEntity(subscriptionInfo.entityType, subscriptionInfo.entityId, {ignoreLoading: true}).then(
+                function success(entity) {
+                    createDatasourceFromSubscription(subscriptionInfo, datasources, entity);
+                    var alarmSource = datasources[0];
+                    deferred.resolve(alarmSource);
+                },
+                function fail() {
+                    deferred.reject();
+                }
+            );
+        } else {
+            deferred.reject();
+        }
+        return deferred.promise;
+    }
+
     function processSubscriptionsInfo(index, subscriptionsInfo, datasources, deferred) {
         if (index < subscriptionsInfo.length) {
             var subscriptionInfo = validateSubscriptionInfo(subscriptionsInfo[index]);
@@ -858,6 +879,9 @@ function EntityService($http, $q, $filter, $translate, $log, userService, device
         if (subscriptionInfo.functions) {
             createDatasourceKeys(subscriptionInfo.functions, types.dataKeyType.function, datasource, datasources);
         }
+        if (subscriptionInfo.alarmFields) {
+            createDatasourceKeys(subscriptionInfo.alarmFields, types.dataKeyType.alarm, datasource, datasources);
+        }
     }
 
     function createDatasourceKeys(keyInfos, type, datasource, datasources) {
diff --git a/ui/src/app/common/types.constant.js b/ui/src/app/common/types.constant.js
index 1a51a1a..43cc0cf 100644
--- a/ui/src/app/common/types.constant.js
+++ b/ui/src/app/common/types.constant.js
@@ -61,47 +61,57 @@ export default angular.module('thingsboard.types', [])
             },
             alarmFields: {
                 createdTime: {
+                    keyName: 'createdTime',
                     value: "createdTime",
                     name: "alarm.created-time",
                     time: true
                 },
                 startTime: {
+                    keyName: 'startTime',
                     value: "startTs",
                     name: "alarm.start-time",
                     time: true
                 },
                 endTime: {
+                    keyName: 'endTime',
                     value: "endTs",
                     name: "alarm.end-time",
                     time: true
                 },
                 ackTime: {
+                    keyName: 'ackTime',
                     value: "ackTs",
                     name: "alarm.ack-time",
                     time: true
                 },
                 clearTime: {
+                    keyName: 'clearTime',
                     value: "clearTs",
                     name: "alarm.clear-time",
                     time: true
                 },
                 originator: {
+                    keyName: 'originator',
                     value: "originatorName",
                     name: "alarm.originator"
                 },
                 originatorType: {
+                    keyName: 'originatorType',
                     value: "originator.entityType",
                     name: "alarm.originator-type"
                 },
                 type: {
+                    keyName: 'type',
                     value: "type",
                     name: "alarm.type"
                 },
                 severity: {
+                    keyName: 'severity',
                     value: "severity",
                     name: "alarm.severity"
                 },
                 status: {
+                    keyName: 'status',
                     value: "status",
                     name: "alarm.status"
                 }
diff --git a/ui/src/app/common/utils.service.js b/ui/src/app/common/utils.service.js
index e6d48ae..e7252e0 100644
--- a/ui/src/app/common/utils.service.js
+++ b/ui/src/app/common/utils.service.js
@@ -106,11 +106,11 @@ function Utils($mdColorPalette, $rootScope, $window, $translate, $q, $timeout, t
     };
 
     var defaultAlarmFields = [
-        'createdTime',
-        'originator',
-        'type',
-        'severity',
-        'status'
+        types.alarmFields.createdTime.keyName,
+        types.alarmFields.originator.keyName,
+        types.alarmFields.type.keyName,
+        types.alarmFields.severity.keyName,
+        types.alarmFields.status.keyName
     ];
 
     var defaultAlarmDataKeys = [];
@@ -413,10 +413,20 @@ function Utils($mdColorPalette, $rootScope, $window, $translate, $q, $timeout, t
     }
 
     function createKey(keyInfo, type, datasources) {
+        var label;
+        if (type === types.dataKeyType.alarm && !keyInfo.label) {
+            var alarmField = types.alarmFields[keyInfo.name];
+            if (alarmField) {
+                label = $translate.instant(alarmField.name)+'';
+            }
+        }
+        if (!label) {
+            label = keyInfo.label || keyInfo.name;
+        }
         var dataKey = {
             name: keyInfo.name,
             type: type,
-            label: keyInfo.label || keyInfo.name,
+            label: label,
             color: genNextColor(datasources),
             funcBody: keyInfo.funcBody,
             settings: {},
diff --git a/ui/src/app/components/widget/widget.controller.js b/ui/src/app/components/widget/widget.controller.js
index 3bda809..b2877f3 100644
--- a/ui/src/app/components/widget/widget.controller.js
+++ b/ui/src/app/components/widget/widget.controller.js
@@ -36,6 +36,8 @@ export default function WidgetController($scope, $timeout, $window, $element, $q
     $scope.rpcEnabled = false;
     $scope.executingRpcRequest = false;
 
+    vm.dashboardTimewindow = dashboardTimewindow;
+
     var gridsterItemInited = false;
     var subscriptionInited = false;
     var widgetSizeDetected = false;
@@ -192,9 +194,20 @@ export default function WidgetController($scope, $timeout, $window, $element, $q
             }
         }
 
-        entityService.createDatasourcesFromSubscriptionsInfo(subscriptionsInfo).then(
-            function (datasources) {
-                options.datasources = datasources;
+        var createDatasourcesPromise;
+        if (options.type == types.widgetType.alarm.value) {
+            createDatasourcesPromise = entityService.createAlarmSourceFromSubscriptionInfo(subscriptionsInfo);
+        } else {
+            createDatasourcesPromise = entityService.createDatasourcesFromSubscriptionsInfo(subscriptionsInfo);
+        }
+
+        createDatasourcesPromise.then(
+            function (result) {
+                if (options.type == types.widgetType.alarm.value) {
+                    options.alarmSource = result;
+                } else {
+                    options.datasources = result;
+                }
                 createSubscription(options, subscribe).then(
                     function success(subscription) {
                         if (useDefaultComponents) {
@@ -213,7 +226,7 @@ export default function WidgetController($scope, $timeout, $window, $element, $q
 
     function createSubscription(options, subscribe) {
         var deferred = $q.defer();
-        options.dashboardTimewindow = dashboardTimewindow;
+        options.dashboardTimewindow = vm.dashboardTimewindow;
         new Subscription(subscriptionContext, options).then(
             function success(subscription) {
                 widgetContext.subscriptions[subscription.id] = subscription;
@@ -234,7 +247,7 @@ export default function WidgetController($scope, $timeout, $window, $element, $q
         options.useDashboardTimewindow = angular.isDefined(widget.config.useDashboardTimewindow)
             ? widget.config.useDashboardTimewindow : true;
 
-        options.timeWindowConfig = options.useDashboardTimewindow ? dashboardTimewindow : widget.config.timewindow;
+        options.timeWindowConfig = options.useDashboardTimewindow ? vm.dashboardTimewindow : widget.config.timewindow;
         options.legendConfig = null;
 
         if ($scope.displayLegend) {
@@ -504,6 +517,10 @@ export default function WidgetController($scope, $timeout, $window, $element, $q
             }
         });
 
+        $scope.$on('dashboardTimewindowChanged', function (event, newDashboardTimewindow) {
+            vm.dashboardTimewindow = newDashboardTimewindow;
+        });
+
         $scope.$on("$destroy", function () {
             onDestroy();
         });