diff --git a/ui-ngx/src/app/core/http/entity.service.ts b/ui-ngx/src/app/core/http/entity.service.ts index 16d3d5126b..ec4820bad8 100644 --- a/ui-ngx/src/app/core/http/entity.service.ts +++ b/ui-ngx/src/app/core/http/entity.service.ts @@ -89,6 +89,7 @@ import { DeviceProfileService } from '@core/http/device-profile.service'; import { QueueService } from '@core/http/queue.service'; import { AssetProfileService } from '@core/http/asset-profile.service'; import { NotificationService } from '@core/http/notification.service'; +import { TenantProfileService } from '@core/http/tenant-profile.service'; @Injectable({ providedIn: 'root' @@ -112,6 +113,7 @@ export class EntityService { private otaPackageService: OtaPackageService, private widgetService: WidgetService, private deviceProfileService: DeviceProfileService, + private tenantProfileService: TenantProfileService, private assetProfileService: AssetProfileService, private utils: UtilsService, private queueService: QueueService, @@ -241,6 +243,11 @@ export class EntityService { (id) => this.deviceProfileService.getDeviceProfileInfo(id, config), entityIds); break; + case EntityType.TENANT_PROFILE: + observable = this.getEntitiesByIdsObservable( + (id) => this.tenantProfileService.getTenantProfileInfo(id, config), + entityIds); + break; case EntityType.ASSET_PROFILE: observable = this.getEntitiesByIdsObservable( (id) => this.assetProfileService.getAssetProfileInfo(id, config), @@ -399,6 +406,10 @@ export class EntityService { pageLink.sortOrder.property = 'name'; entitiesObservable = this.deviceProfileService.getDeviceProfileInfos(pageLink, null, config); break; + case EntityType.TENANT_PROFILE: + pageLink.sortOrder.property = 'name'; + entitiesObservable = this.tenantProfileService.getTenantProfiles(pageLink, config); + break; case EntityType.ASSET_PROFILE: pageLink.sortOrder.property = 'name'; entitiesObservable = this.assetProfileService.getAssetProfileInfos(pageLink, config); diff --git a/ui-ngx/src/app/modules/home/pages/notification-center/rule-table/rule-notification-dialog.component.html b/ui-ngx/src/app/modules/home/pages/notification-center/rule-table/rule-notification-dialog.component.html index 4e72dcbfa4..1a472e7246 100644 --- a/ui-ngx/src/app/modules/home/pages/notification-center/rule-table/rule-notification-dialog.component.html +++ b/ui-ngx/src/app/modules/home/pages/notification-center/rule-table/rule-notification-dialog.component.html @@ -159,16 +159,16 @@ - {{ 'notification.device' | translate }} - {{ 'notification.device-profile' | translate }} + {{ 'device.device' | translate }} + {{ 'device-profile.device-profile' | translate }} @@ -177,8 +177,8 @@ @@ -258,9 +258,14 @@ - - {{ 'notification.notify-only-user-comments' | translate }} - +
+ + {{ 'notification.notify-only-user-comments' | translate }} + + + {{ 'notification.notify-on-comment-update' | translate }} + +
@@ -306,9 +311,17 @@ - - {{ 'notification.notify-on-unassign' | translate }} - + + notification.notify-on + + + {{ alarmAssignmentActionTranslationMap.get(alarmAssignmentAction) | translate }} + + + + {{ 'notification.notify-on-required' | translate }} + +
diff --git a/ui-ngx/src/app/modules/home/pages/notification-center/rule-table/rule-notification-dialog.component.ts b/ui-ngx/src/app/modules/home/pages/notification-center/rule-table/rule-notification-dialog.component.ts index e4335cc130..4939b0e861 100644 --- a/ui-ngx/src/app/modules/home/pages/notification-center/rule-table/rule-notification-dialog.component.ts +++ b/ui-ngx/src/app/modules/home/pages/notification-center/rule-table/rule-notification-dialog.component.ts @@ -17,6 +17,8 @@ import { AlarmAction, AlarmActionTranslationMap, + AlarmAssignmentAction, + AlarmAssignmentActionTranslationMap, NotificationRule, NotificationTarget, TriggerType, @@ -94,6 +96,9 @@ export class RuleNotificationDialogComponent extends alarmActions: AlarmAction[] = Object.values(AlarmAction); alarmActionTranslationMap = AlarmActionTranslationMap; + alarmAssignmentActions: AlarmAssignmentAction[] = Object.values(AlarmAssignmentAction); + alarmAssignmentActionTranslationMap = AlarmAssignmentActionTranslationMap; + entityType = EntityType; entityTypes: EntityType[] = Object.values(EntityType); isAdd = true; @@ -207,7 +212,8 @@ export class RuleNotificationDialogComponent extends alarmTypes: [null], alarmSeverities: [[]], alarmStatuses: [[]], - onlyUserComments: [false] + onlyUserComments: [false], + notifyOnCommentUpdate: [false] }) }); @@ -216,7 +222,7 @@ export class RuleNotificationDialogComponent extends alarmTypes: [null], alarmSeverities: [[]], alarmStatuses: [[]], - notifyOnUnassign: [true] + notifyOn: [[AlarmAssignmentAction.ASSIGNED], Validators.required] }) }); diff --git a/ui-ngx/src/app/modules/home/pages/notification-center/targets-table/target-notification-dialog.component.html b/ui-ngx/src/app/modules/home/pages/notification-center/targets-table/target-notification-dialog.component.html index 4c3583eeaf..bb6e3ba65c 100644 --- a/ui-ngx/src/app/modules/home/pages/notification-center/targets-table/target-notification-dialog.component.html +++ b/ui-ngx/src/app/modules/home/pages/notification-center/targets-table/target-notification-dialog.component.html @@ -56,6 +56,38 @@ + +
+
+ + {{ 'tenant.tenant' | translate }} + {{ 'tenant-profile.tenant-profile' | translate }} + +
+ + + + + + + + +
+
{ this.targetNotificationForm.get('configuration.usersFilter').disable({emitEvent: false}); switch (type) { + case NotificationTargetConfigType.TENANT_ADMINISTRATORS: + if (this.isSysAdmin()) { + this.targetNotificationForm.get('configuration.usersFilter.filterByTenants').enable({onlySelf: true}); + } + break; case NotificationTargetConfigType.USER_LIST: this.targetNotificationForm.get('configuration.usersFilter.usersIds').enable({emitEvent: false}); break; @@ -133,9 +139,25 @@ export class TargetNotificationDialogComponent extends this.targetNotificationForm.get('configuration.usersFilter.type').enable({emitEvent: false}); }); - if (isDefined(data.target)) { + this.targetNotificationForm.get('configuration.usersFilter.filterByTenants').valueChanges.pipe( + takeUntil(this.destroy$) + ).subscribe((value: boolean) => { + if (value) { + this.targetNotificationForm.get('configuration.usersFilter.tenantsIds').enable({emitEvent: false}); + this.targetNotificationForm.get('configuration.usersFilter.tenantProfilesIds').disable({emitEvent: false}); + } else { + this.targetNotificationForm.get('configuration.usersFilter.tenantsIds').disable({emitEvent: false}); + this.targetNotificationForm.get('configuration.usersFilter.tenantProfilesIds').enable({emitEvent: false}); + } + }); + + if (isDefinedAndNotNull(data.target)) { this.targetNotificationForm.patchValue(data.target, {emitEvent: false}); this.targetNotificationForm.get('configuration.type').updateValueAndValidity({onlySelf: true}); + if (this.isSysAdmin() && data.target.configuration.usersFilter.type === NotificationTargetConfigType.TENANT_ADMINISTRATORS) { + this.targetNotificationForm.get('configuration.usersFilter.filterByTenants') + .patchValue(!Array.isArray(this.data.target.configuration.usersFilter.tenantProfilesIds), {onlySelf: true}); + } } } @@ -150,21 +172,27 @@ export class TargetNotificationDialogComponent extends } save() { - let formValue: NotificationTarget = deepTrim(this.targetNotificationForm.value); - if (isDefined(this.data.target)) { + let formValue = deepTrim(this.targetNotificationForm.value); + if (isDefinedAndNotNull(this.data.target)) { formValue = Object.assign({}, this.data.target, formValue); } - if (formValue.configuration.type === NotificationTargetType.PLATFORM_USERS && !formValue.configuration.usersFilter) { - formValue.configuration.usersFilter = { - type: NotificationTargetConfigType.ALL_USERS - } + if (this.isSysAdmin() && formValue.configuration.type === NotificationTargetType.PLATFORM_USERS && + formValue.configuration.usersFilter.type === NotificationTargetConfigType.TENANT_ADMINISTRATORS) { + delete formValue.configuration.usersFilter.filterByTenants; } this.notificationService.saveNotificationTarget(formValue).subscribe( (target) => this.dialogRef.close(target) ); } - public isTenantAdmin(): boolean { - return this.authUser.authority === Authority.TENANT_ADMIN; + isSysAdmin(): boolean { + return this.authUser.authority === Authority.SYS_ADMIN; + } + + private allowNotificationTargetConfigTypes(): NotificationTargetConfigType[] { + if (this.isSysAdmin()) { + return [NotificationTargetConfigType.ALL_USERS, NotificationTargetConfigType.TENANT_ADMINISTRATORS]; + } + return Object.values(NotificationTargetConfigType); } } diff --git a/ui-ngx/src/app/shared/models/notification.models.ts b/ui-ngx/src/app/shared/models/notification.models.ts index a728496e82..bdff88c9fd 100644 --- a/ui-ngx/src/app/shared/models/notification.models.ts +++ b/ui-ngx/src/app/shared/models/notification.models.ts @@ -138,15 +138,15 @@ export interface AlarmCommentNotificationRuleTriggerConfig { alarmTypes?: Array; alarmSeverities?: Array; alarmStatuses?: Array; - notifyOnUnassign?: boolean; onlyUserComments?: boolean; + notifyOnCommentUpdate?: boolean; } export interface AlarmAssignmentNotificationRuleTriggerConfig { alarmTypes?: Array; alarmSeverities?: Array; alarmStatuses?: Array; - notifyOnUnassign?: boolean; + notifyOn: Array; } export enum AlarmAction { @@ -163,6 +163,16 @@ export const AlarmActionTranslationMap = new Map([ [AlarmAction.CLEARED, 'notification.notify-alarm-action.cleared'] ]) +export enum AlarmAssignmentAction { + ASSIGNED = 'ASSIGNED', + UNASSIGNED = 'UNASSIGNED' +} + +export const AlarmAssignmentActionTranslationMap = new Map([ + [AlarmAssignmentAction.ASSIGNED, 'notification.notify-alarm-action.assigned'], + [AlarmAssignmentAction.UNASSIGNED, 'notification.notify-alarm-action.unassigned'] +]) + export interface NotificationRuleRecipientConfig { targets?: Array; escalationTable?: {[key: number]: Array}; @@ -187,18 +197,23 @@ export interface PlatformUsersNotificationTargetConfig { } export interface UsersFilter extends - Partial{ + Partial{ type: NotificationTargetConfigType; } -interface UserListNotificationTargetConfig { +interface UserListFilter { usersIds: Array; } -interface CustomerUsersNotificationTargetConfig { +interface CustomerUsersFilter { customerId: string; } +interface TenantAdministratorsFilter { + tenantsIds?: Array; + tenantProfilesIds?: Array; +} + export interface SlackNotificationTargetConfig { conversationType: SlackChanelType; conversation: SlackConversation; @@ -310,16 +325,20 @@ export const SlackChanelTypesTranslateMap = new Map([ export enum NotificationTargetConfigType { ALL_USERS = 'ALL_USERS', - USER_LIST = 'USER_LIST', + TENANT_ADMINISTRATORS = 'TENANT_ADMINISTRATORS', CUSTOMER_USERS = 'CUSTOMER_USERS', - ORIGINATOR_ENTITY_OWNER_USERS = 'ORIGINATOR_ENTITY_OWNER_USERS' + USER_LIST = 'USER_LIST', + ORIGINATOR_ENTITY_OWNER_USERS = 'ORIGINATOR_ENTITY_OWNER_USERS', + ACTION_TARGET_USER = 'ACTION_TARGET_USER' } export const NotificationTargetConfigTypeTranslateMap = new Map([ [NotificationTargetConfigType.ALL_USERS, 'notification.target-type.all-users'], - [NotificationTargetConfigType.USER_LIST, 'notification.target-type.user-list'], + [NotificationTargetConfigType.TENANT_ADMINISTRATORS, 'notification.target-type.tenant-administrators'], [NotificationTargetConfigType.CUSTOMER_USERS, 'notification.target-type.customer-users'], - [NotificationTargetConfigType.ORIGINATOR_ENTITY_OWNER_USERS, 'notification.target-type.originator-entity-owner-users'] + [NotificationTargetConfigType.USER_LIST, 'notification.target-type.user-list'], + [NotificationTargetConfigType.ORIGINATOR_ENTITY_OWNER_USERS, 'notification.target-type.originator-entity-owner-users'], + [NotificationTargetConfigType.ACTION_TARGET_USER, 'notification.target-type.action-target-user'], ]); export enum NotificationType { diff --git a/ui-ngx/src/assets/locale/locale.constant-en_US.json b/ui-ngx/src/assets/locale/locale.constant-en_US.json index 9b378be529..74b7e31fb5 100644 --- a/ui-ngx/src/assets/locale/locale.constant-en_US.json +++ b/ui-ngx/src/assets/locale/locale.constant-en_US.json @@ -2768,13 +2768,9 @@ }, "delivery-methods": "Delivery methods", "description": "Description", - "device": "Device", "device-inactivity-trigger-settings": "Device inactive trigger settings", "device-list-rule-hint": "If the field is empty, the trigger will be applied to all devices", - "device-profile": "Device profile", - "device-profiles": "Device profiles", "device-profiles-list-rule-hint": "If the field is empty, the trigger will be applied to all device profiles", - "devices": "Devices", "edit-notification-target": "Edit notification recipient", "edit-notification-template": "Edit notification template", "edit-rule": "Edit rule", @@ -2816,13 +2812,16 @@ "notification-target": "Notification recipient", "notify": "notify", "notify-alarm-action": { - "created": "Alarm created", - "severity-changed": "Alarm severity changed", - "acknowledged": "Alarm acknowledged", - "cleared": "Alarm cleared" + "assigned": "Alarm assigned", + "created": "Alarm created", + "severity-changed": "Alarm severity changed", + "acknowledged": "Alarm acknowledged", + "cleared": "Alarm cleared", + "unassigned": "Alarm unassigned" }, "notify-again": "Notify again", "notify-on": "Notify on", + "notify-on-comment-update": "Notify on comment update", "notify-on-required": "Notify on is required", "notify-only-user-comments": "Notify only user comments", "notify-on-unassign": "Notify on unassign", @@ -2866,9 +2865,11 @@ "target-name": "Name", "target-name-required": "Name is required", "target-type": { + "action-target-user": "Action target user", "all-users": "All users", "customer-users": "Customer users", "originator-entity-owner-users": "Users of originator entity owner", + "tenant-administrators": "Tenant administrators", "user-filters": "User filter", "user-list": "User list" }, @@ -2894,6 +2895,8 @@ "general": "General" }, "templates": "Templates", + "tenants-list-rule-hint": "If the field is empty, the trigger will be applied to all tenants", + "tenant-profiles-list-rule-hint": "If the field is empty, the trigger will be applied to all tenant profiles", "time": "Time", "trigger": { "alarm": "Alarm",