UI: Add notification template and rule trigger config for entities limit
This commit is contained in:
parent
26618fa3a2
commit
ecdd49d672
@ -46,7 +46,7 @@
|
||||
[notificationType]="entityType.NOTIFICATION_TARGET">
|
||||
</tb-notification-table>
|
||||
</mat-tab>
|
||||
<mat-tab label="{{ 'notification.rules' | translate }}" *ngIf="isTenantAdmin()">
|
||||
<mat-tab label="{{ 'notification.rules' | translate }}">
|
||||
<tb-notification-table
|
||||
[notificationType]="entityType.NOTIFICATION_RULE">
|
||||
</tb-notification-table>
|
||||
|
||||
@ -68,10 +68,6 @@ export class NotificationCenterComponent extends PageComponent {
|
||||
.onEntityAction({event: $event, action: this.requestTab.isActive ? 'add' : 'add-without-update', entity: null});
|
||||
}
|
||||
|
||||
public isTenantAdmin(): boolean {
|
||||
return this.authUser.authority === Authority.TENANT_ADMIN;
|
||||
}
|
||||
|
||||
public isCustomerUser(): boolean {
|
||||
return this.authUser.authority === Authority.CUSTOMER_USER;
|
||||
}
|
||||
|
||||
@ -392,6 +392,44 @@
|
||||
</section>
|
||||
</form>
|
||||
</mat-step>
|
||||
|
||||
<mat-step *ngIf="ruleNotificationForm.get('triggerType').value === triggerType.ENTITIES_LIMIT"
|
||||
[stepControl]="entitiesLimitTemplateForm">
|
||||
<ng-template matStepLabel>{{ 'notification.entities-limit-trigger-settings' | translate }}</ng-template>
|
||||
<form [formGroup]="entitiesLimitTemplateForm">
|
||||
<fieldset class="fields-group tb-margin" formGroupName="triggerConfig">
|
||||
<legend translate>notification.filter</legend>
|
||||
<tb-entity-type-list formControlName="entityTypes"
|
||||
ignoreAuthorityFilter
|
||||
[allowedEntityTypes]="entityTypes">
|
||||
</tb-entity-type-list>
|
||||
<div class="limit-slider-container" fxLayout="row" fxLayoutAlign="start center"
|
||||
fxLayout.xs="column" fxLayoutAlign.xs="stretch">
|
||||
<label translate>notification.threshold</label>
|
||||
<div fxLayout="row" fxLayoutAlign="start center" fxFlex>
|
||||
<mat-slider fxFlex min="0" max="1" step="0.01" discrete [displayWith]="formatLabel">
|
||||
<input matSliderThumb formControlName="threshold">
|
||||
</mat-slider>
|
||||
<mat-form-field class="limit-slider-value">
|
||||
<input matInput formControlName="threshold" type="number" step="0.01"
|
||||
[value]="entitiesLimitTemplateForm.get('triggerConfig.threshold').value"
|
||||
min="0"
|
||||
max="1"/>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
</form>
|
||||
<form [formGroup]="ruleNotificationForm">
|
||||
<section formGroupName="additionalConfig">
|
||||
<mat-form-field class="mat-block">
|
||||
<mat-label translate>notification.description</mat-label>
|
||||
<input matInput formControlName="description">
|
||||
</mat-form-field>
|
||||
</section>
|
||||
</form>
|
||||
</mat-step>
|
||||
|
||||
</mat-horizontal-stepper>
|
||||
</div>
|
||||
<mat-divider></mat-divider>
|
||||
|
||||
@ -66,6 +66,30 @@
|
||||
}
|
||||
}
|
||||
|
||||
.limit-slider-container {
|
||||
.limit-slider-value {
|
||||
margin-left: 16px;
|
||||
min-width: 25px;
|
||||
max-width: 100px;
|
||||
}
|
||||
mat-form-field input[type=number] {
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
@media #{$mat-gt-sm} {
|
||||
.history-time-input {
|
||||
min-width: 364px;
|
||||
}
|
||||
.limit-slider-container {
|
||||
> label {
|
||||
margin-right: 16px;
|
||||
width: min-content;
|
||||
max-width: 40%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
::ng-deep {
|
||||
|
||||
.mat-mdc-dialog-content {
|
||||
|
||||
@ -34,7 +34,7 @@ import { Router } from '@angular/router';
|
||||
import { MAT_DIALOG_DATA, MatDialog, MatDialogRef } from '@angular/material/dialog';
|
||||
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
|
||||
import { NotificationService } from '@core/http/notification.service';
|
||||
import { EntityType } from '@shared/models/entity-type.models';
|
||||
import { EntityType, entityTypeTranslations } from '@shared/models/entity-type.models';
|
||||
import { deepClone, deepTrim, isDefined } from '@core/utils';
|
||||
import { Observable, Subject } from 'rxjs';
|
||||
import { map, takeUntil } from 'rxjs/operators';
|
||||
@ -54,6 +54,10 @@ import {
|
||||
TargetsNotificationDialogData
|
||||
} from '@home/pages/notification-center/targets-table/target-notification-dialog.componet';
|
||||
import { MatButton } from '@angular/material/button';
|
||||
import { AuthState } from '@core/auth/auth.models';
|
||||
import { getCurrentAuthState } from '@core/auth/auth.selectors';
|
||||
import { AuthUser } from '@shared/models/user.model';
|
||||
import { Authority } from '@shared/models/authority.enum';
|
||||
|
||||
export interface RuleNotificationDialogData {
|
||||
rule?: NotificationRule;
|
||||
@ -80,9 +84,10 @@ export class RuleNotificationDialogComponent extends
|
||||
alarmCommentTemplateForm: FormGroup;
|
||||
alarmAssignmentTemplateForm: FormGroup;
|
||||
ruleEngineEventsTemplateForm: FormGroup;
|
||||
entitiesLimitTemplateForm: FormGroup;
|
||||
|
||||
triggerType = TriggerType;
|
||||
triggerTypes: TriggerType[] = Object.values(TriggerType);
|
||||
triggerTypes: TriggerType[];
|
||||
triggerTypeTranslationMap = TriggerTypeTranslationMap;
|
||||
|
||||
alarmSearchStatuses = [
|
||||
@ -106,7 +111,7 @@ export class RuleNotificationDialogComponent extends
|
||||
componentLifecycleEventTranslationMap = ComponentLifecycleEventTranslationMap;
|
||||
|
||||
entityType = EntityType;
|
||||
entityTypes: EntityType[] = Object.values(EntityType);
|
||||
entityTypes = Array.from(entityTypeTranslations.keys()).filter(type => !!this.entityType[type]);
|
||||
isAdd = true;
|
||||
|
||||
selectedIndex = 0;
|
||||
@ -118,6 +123,8 @@ export class RuleNotificationDialogComponent extends
|
||||
private readonly ruleNotification: NotificationRule;
|
||||
|
||||
private triggerTypeFormsMap: Map<TriggerType, FormGroup>;
|
||||
private authState: AuthState = getCurrentAuthState(this.store);
|
||||
private authUser: AuthUser = this.authState.authUser;
|
||||
|
||||
constructor(protected store: Store<AppState>,
|
||||
protected router: Router,
|
||||
@ -130,6 +137,8 @@ export class RuleNotificationDialogComponent extends
|
||||
private dialog: MatDialog) {
|
||||
super(store, router, dialogRef);
|
||||
|
||||
this.triggerTypes = this.allowTriggerTypes();
|
||||
|
||||
if (isDefined(data.isAdd)) {
|
||||
this.isAdd = data.isAdd;
|
||||
}
|
||||
@ -140,10 +149,10 @@ export class RuleNotificationDialogComponent extends
|
||||
this.ruleNotificationForm = this.fb.group({
|
||||
name: [null, Validators.required],
|
||||
templateId: [null, Validators.required],
|
||||
triggerType: [TriggerType.ALARM, Validators.required],
|
||||
triggerType: [this.isSysAdmin() ? TriggerType.ENTITIES_LIMIT : TriggerType.ALARM, Validators.required],
|
||||
recipientsConfig: this.fb.group({
|
||||
targets: [{value: null, disabled: true}, Validators.required],
|
||||
escalationTable: [null, Validators.required]
|
||||
targets: [{value: null, disabled: !this.isSysAdmin()}, Validators.required],
|
||||
escalationTable: [{value: null, disabled: this.isSysAdmin()}, Validators.required]
|
||||
}),
|
||||
triggerConfig: [null],
|
||||
additionalConfig: this.fb.group({
|
||||
@ -243,13 +252,21 @@ export class RuleNotificationDialogComponent extends
|
||||
})
|
||||
});
|
||||
|
||||
this.entitiesLimitTemplateForm = this.fb.group({
|
||||
triggerConfig: this.fb.group({
|
||||
entityTypes: [],
|
||||
threshold: [.8, [Validators.min(0), Validators.max(1)]]
|
||||
})
|
||||
});
|
||||
|
||||
this.triggerTypeFormsMap = new Map<TriggerType, FormGroup>([
|
||||
[TriggerType.ALARM, this.alarmTemplateForm],
|
||||
[TriggerType.ALARM_COMMENT, this.alarmCommentTemplateForm],
|
||||
[TriggerType.DEVICE_INACTIVITY, this.deviceInactivityTemplateForm],
|
||||
[TriggerType.ENTITY_ACTION, this.entityActionTemplateForm],
|
||||
[TriggerType.ALARM_ASSIGNMENT, this.alarmAssignmentTemplateForm],
|
||||
[TriggerType.RULE_ENGINE_COMPONENT_LIFECYCLE_EVENT, this.ruleEngineEventsTemplateForm]
|
||||
[TriggerType.RULE_ENGINE_COMPONENT_LIFECYCLE_EVENT, this.ruleEngineEventsTemplateForm],
|
||||
[TriggerType.ENTITIES_LIMIT, this.entitiesLimitTemplateForm]
|
||||
]);
|
||||
|
||||
if (data.isAdd || data.isCopy) {
|
||||
@ -368,4 +385,20 @@ export class RuleNotificationDialogComponent extends
|
||||
countRecipientsChainConfig(): number {
|
||||
return Object.keys(this.ruleNotificationForm.get('recipientsConfig.escalationTable').value ?? {}).length;
|
||||
}
|
||||
|
||||
formatLabel(value: number): string {
|
||||
const formatValue = (value * 100).toFixed();
|
||||
return `${formatValue}%`;
|
||||
}
|
||||
|
||||
private isSysAdmin(): boolean {
|
||||
return this.authUser.authority === Authority.SYS_ADMIN;
|
||||
}
|
||||
|
||||
private allowTriggerTypes(): TriggerType[] {
|
||||
if (this.isSysAdmin()) {
|
||||
return [TriggerType.ENTITIES_LIMIT];
|
||||
}
|
||||
return Object.values(TriggerType).filter(type => type !== TriggerType.ENTITIES_LIMIT);
|
||||
}
|
||||
}
|
||||
|
||||
@ -57,7 +57,7 @@ export class TemplateNotificationDialogComponent
|
||||
|
||||
dialogTitle = 'notification.edit-notification-template';
|
||||
|
||||
notificationTypes = Object.keys(NotificationType) as NotificationType[];
|
||||
notificationTypes: NotificationType[];
|
||||
|
||||
selectedIndex = 0;
|
||||
hideSelectType = false;
|
||||
@ -76,6 +76,8 @@ export class TemplateNotificationDialogComponent
|
||||
private translate: TranslateService) {
|
||||
super(store, router, dialogRef, fb);
|
||||
|
||||
this.notificationTypes = this.allowNotificationType();
|
||||
|
||||
this.stepperOrientation = this.breakpointObserver.observe(MediaBreakpoints['gt-sm'])
|
||||
.pipe(map(({matches}) => matches ? 'horizontal' : 'vertical'));
|
||||
|
||||
@ -84,10 +86,6 @@ export class TemplateNotificationDialogComponent
|
||||
this.templateNotificationForm.get('notificationType').setValue(this.data.predefinedType, {emitEvents: false});
|
||||
}
|
||||
|
||||
if (this.isSysAdmin()) {
|
||||
this.hideSelectType = true;
|
||||
}
|
||||
|
||||
if (data.isAdd || data.isCopy) {
|
||||
this.dialogTitle = 'notification.add-notification-template';
|
||||
}
|
||||
@ -175,4 +173,11 @@ export class TemplateNotificationDialogComponent
|
||||
private isSysAdmin(): boolean {
|
||||
return this.authUser.authority === Authority.SYS_ADMIN;
|
||||
}
|
||||
|
||||
private allowNotificationType(): NotificationType[] {
|
||||
if (this.isSysAdmin()) {
|
||||
return [NotificationType.GENERAL, NotificationType.ENTITIES_LIMIT];
|
||||
}
|
||||
return Object.values(NotificationType).filter(type => type !== NotificationType.ENTITIES_LIMIT);
|
||||
}
|
||||
}
|
||||
|
||||
@ -27,6 +27,7 @@ import { MatAutocomplete } from '@angular/material/autocomplete';
|
||||
import { MatChipGrid } from '@angular/material/chips';
|
||||
import { coerceBooleanProperty } from '@angular/cdk/coercion';
|
||||
import { SubscriptSizing } from '@angular/material/form-field';
|
||||
import { coerceBoolean } from '@shared/decorators/coerce-boolean';
|
||||
|
||||
interface EntityTypeInfo {
|
||||
name: string;
|
||||
@ -74,6 +75,7 @@ export class EntityTypeListComponent implements ControlValueAccessor, OnInit, Af
|
||||
allowedEntityTypes: Array<EntityType | AliasEntityType>;
|
||||
|
||||
@Input()
|
||||
@coerceBoolean()
|
||||
ignoreAuthorityFilter: boolean;
|
||||
|
||||
@ViewChild('entityTypeInput') entityTypeInput: ElementRef<HTMLInputElement>;
|
||||
|
||||
@ -111,7 +111,7 @@ export interface NotificationRule extends Omit<BaseData<NotificationRuleId>, 'la
|
||||
|
||||
export type NotificationRuleTriggerConfig = Partial<AlarmNotificationRuleTriggerConfig & DeviceInactivityNotificationRuleTriggerConfig &
|
||||
EntityActionNotificationRuleTriggerConfig & AlarmCommentNotificationRuleTriggerConfig & AlarmAssignmentNotificationRuleTriggerConfig &
|
||||
RuleEngineLifecycleEventNotificationRuleTriggerConfig>;
|
||||
RuleEngineLifecycleEventNotificationRuleTriggerConfig & EntitiesLimitNotificationRuleTriggerConfig>;
|
||||
|
||||
export interface AlarmNotificationRuleTriggerConfig {
|
||||
alarmTypes?: Array<string>;
|
||||
@ -160,6 +160,11 @@ export interface RuleEngineLifecycleEventNotificationRuleTriggerConfig {
|
||||
onlyRuleNodeLifecycleFailures: ComponentLifecycleEvent;
|
||||
}
|
||||
|
||||
export interface EntitiesLimitNotificationRuleTriggerConfig {
|
||||
entityTypes: EntityType[];
|
||||
threshold: number;
|
||||
}
|
||||
|
||||
export enum ComponentLifecycleEvent {
|
||||
STARTED = 'STARTED',
|
||||
UPDATED = 'UPDATED',
|
||||
@ -402,7 +407,8 @@ export enum NotificationType {
|
||||
ENTITY_ACTION = 'ENTITY_ACTION',
|
||||
ALARM_COMMENT = 'ALARM_COMMENT',
|
||||
ALARM_ASSIGNMENT = 'ALARM_ASSIGNMENT',
|
||||
RULE_ENGINE_COMPONENT_LIFECYCLE_EVENT = 'RULE_ENGINE_COMPONENT_LIFECYCLE_EVENT'
|
||||
RULE_ENGINE_COMPONENT_LIFECYCLE_EVENT = 'RULE_ENGINE_COMPONENT_LIFECYCLE_EVENT',
|
||||
ENTITIES_LIMIT = 'ENTITIES_LIMIT'
|
||||
}
|
||||
|
||||
export const NotificationTypeIcons = new Map<NotificationType, string | null>([
|
||||
@ -411,7 +417,8 @@ export const NotificationTypeIcons = new Map<NotificationType, string | null>([
|
||||
[NotificationType.ENTITY_ACTION, 'devices'],
|
||||
[NotificationType.ALARM_COMMENT, 'comment'],
|
||||
[NotificationType.ALARM_ASSIGNMENT, 'assignment_turned_in'],
|
||||
[NotificationType.RULE_ENGINE_COMPONENT_LIFECYCLE_EVENT, 'settings_ethernet']
|
||||
[NotificationType.RULE_ENGINE_COMPONENT_LIFECYCLE_EVENT, 'settings_ethernet'],
|
||||
[NotificationType.ENTITIES_LIMIT, 'data_thresholding'],
|
||||
]);
|
||||
|
||||
export const AlarmSeverityNotificationColors = new Map<AlarmSeverity, string>(
|
||||
@ -481,7 +488,12 @@ export const NotificationTemplateTypeTranslateMap = new Map<NotificationType, No
|
||||
name: 'notification.template-type.rule-engine-lifecycle-event',
|
||||
hint: 'notification.template-hint.rule-engine-lifecycle-event'
|
||||
}
|
||||
]
|
||||
],
|
||||
[NotificationType.ENTITIES_LIMIT,
|
||||
{
|
||||
name: 'notification.template-type.entities-limit',
|
||||
hint: 'notification.template-hint.entities-limit'
|
||||
}]
|
||||
]);
|
||||
|
||||
export enum TriggerType {
|
||||
@ -490,7 +502,8 @@ export enum TriggerType {
|
||||
ENTITY_ACTION = 'ENTITY_ACTION',
|
||||
ALARM_COMMENT = 'ALARM_COMMENT',
|
||||
ALARM_ASSIGNMENT = 'ALARM_ASSIGNMENT',
|
||||
RULE_ENGINE_COMPONENT_LIFECYCLE_EVENT = 'RULE_ENGINE_COMPONENT_LIFECYCLE_EVENT'
|
||||
RULE_ENGINE_COMPONENT_LIFECYCLE_EVENT = 'RULE_ENGINE_COMPONENT_LIFECYCLE_EVENT',
|
||||
ENTITIES_LIMIT = 'ENTITIES_LIMIT'
|
||||
}
|
||||
|
||||
export const TriggerTypeTranslationMap = new Map<TriggerType, string>([
|
||||
@ -500,4 +513,5 @@ export const TriggerTypeTranslationMap = new Map<TriggerType, string>([
|
||||
[TriggerType.ALARM_COMMENT, 'notification.trigger.alarm-comment'],
|
||||
[TriggerType.ALARM_ASSIGNMENT, 'notification.trigger.alarm-assignment'],
|
||||
[TriggerType.RULE_ENGINE_COMPONENT_LIFECYCLE_EVENT, 'notification.trigger.rule-engine-lifecycle-event'],
|
||||
[TriggerType.ENTITIES_LIMIT, 'notification.trigger.entities-limit'],
|
||||
]);
|
||||
|
||||
@ -2779,6 +2779,7 @@
|
||||
"edit-rule": "Edit rule",
|
||||
"edit-template": "Edit template",
|
||||
"email-settings": "Email settings",
|
||||
"entities-limit-trigger-settings": "Entities limit trigger settings",
|
||||
"entity-action-trigger-settings": "Entity action trigger settings",
|
||||
"entity-type": "Entity type",
|
||||
"failed-send": "Failed send",
|
||||
@ -2890,6 +2891,7 @@
|
||||
"alarm-assignment": "Available params: ${assigneeFirstName}, ${assigneeLastName}, ${assigneeEmail}, ${assigneeFirstName}, ${userName}, ${alarmId}, ${alarmType}, ${alarmSeverity}, ${alarmStatus}, ${alarmOriginatorEntityType}, ${alarmOriginatorId}, ${alarmId}, ${alarmAction}",
|
||||
"alarm-comment": "Available params: ${comment}, ${alarmType}, ${alarmId}, ${alarmType}, ${alarmSeverity}, ${alarmStatus}, ${alarmOriginatorEntityType}, ${alarmOriginatorId}, ${alarmId}, ${alarmAction}",
|
||||
"device-inactivity": "Available params: ${deviceName}, ${deviceLabel}, ${deviceType}, ${deviceId}",
|
||||
"entities-limit": "Available params: ${entityType}, ${currentCount}, ${limit}",
|
||||
"entity-action": "Available params: ${actionType}, ${entityType}, ${entityName}, ${entityId}, ${originatorUserName}, ${originatorUserId}",
|
||||
"general": "Available params: ${recipientEmail}, ${recipientFirstName}, ${recipientLastName}",
|
||||
"rule-engine-lifecycle-event": "Available params: ${ruleChainName}, ${componentName}, ${eventType}, ${error}, ${ruleChainId}, ${componentId}"
|
||||
@ -2901,6 +2903,7 @@
|
||||
"alarm-assignment": "Alarm assignment",
|
||||
"alarm-comment": "Alarm comment",
|
||||
"device-inactivity": "Device inactivity",
|
||||
"entities-limit": "Entities limit",
|
||||
"entity-action": "Entity action",
|
||||
"general": "General",
|
||||
"rule-engine-lifecycle-event": "Rule engine lifecycle event"
|
||||
@ -2910,11 +2913,13 @@
|
||||
"tenant-profiles-list-rule-hint": "If the field is empty, the trigger will be applied to all tenant profiles",
|
||||
"time": "Time",
|
||||
"track-rule-node-events": "Track rule node events",
|
||||
"threshold": "Threshold",
|
||||
"trigger": {
|
||||
"alarm": "Alarm",
|
||||
"alarm-assignment": "Alarm assignment",
|
||||
"alarm-comment": "Alarm comment",
|
||||
"device-inactivity": "Device inactivity",
|
||||
"entities-limit": "Entities limit",
|
||||
"entity-action": "Entity action",
|
||||
"trigger": "Trigger",
|
||||
"trigger-required": "Trigger is required",
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user