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 baee88965e..e30113871d 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 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 06a9b343db..785d029850 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) 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 6f9500ed3b..68844dcdb8 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) hasName1 -> hasName1.getName() ); + entityName = Futures.transform(hasName, (Function) 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 296874e20f..d9b2f442a8 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>> inboundRelations = Futures.allAsList(inboundRelationsList); ListenableFuture> inboundDeletions = Futures.transform(inboundRelations, new AsyncFunction>, List>() { @Override diff --git a/ui/src/app/api/entity.service.js b/ui/src/app/api/entity.service.js index 20157ce918..9cf08d996e 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 81ce0fa4f9..ad36e847ea 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 a3433c255f..09399716db 100644 --- a/ui/src/app/common/utils.service.js +++ b/ui/src/app/common/utils.service.js @@ -96,11 +96,11 @@ function Utils($mdColorPalette, $rootScope, $window, $translate, types) { }; 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 = []; @@ -376,10 +376,20 @@ function Utils($mdColorPalette, $rootScope, $window, $translate, types) { } 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.controller.js b/ui/src/app/components/widget.controller.js index f2e231fa29..b3a332d926 100644 --- a/ui/src/app/components/widget.controller.js +++ b/ui/src/app/components/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(); });