UI: Norification rule
This commit is contained in:
parent
0e83c8ac74
commit
7ea0c23c65
@ -24,7 +24,7 @@ import { Direction } from '@shared/models/page/sort-order';
|
||||
import {
|
||||
NotificationRule,
|
||||
NotificationTarget,
|
||||
NotificationTargetConfigTypeTranslateMap
|
||||
NotificationTargetConfigTypeTranslateMap, TriggerTypeTranslationMap
|
||||
} from '@shared/models/notification.models';
|
||||
import { NotificationService } from '@core/http/notification.service';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
@ -62,8 +62,7 @@ export class RuleTableConfig extends EntityTableConfig<NotificationRule> {
|
||||
this.deleteEntityContent = () => this.translate.instant('notification.delete-rule-text');
|
||||
this.deleteEntity = id => this.notificationService.deleteNotificationRule(id.id);
|
||||
|
||||
this.cellActionDescriptors = this.configureCellActions();
|
||||
|
||||
// this.cellActionDescriptors = this.configureCellActions();
|
||||
this.headerComponent = RuleTableHeaderComponent;
|
||||
this.onEntityAction = action => this.onTargetAction(action);
|
||||
|
||||
@ -71,12 +70,12 @@ export class RuleTableConfig extends EntityTableConfig<NotificationRule> {
|
||||
|
||||
this.columns.push(
|
||||
new EntityTableColumn<NotificationRule>('name', 'notification.rule-name', '30%'),
|
||||
new EntityTableColumn<NotificationRule>('templateId', 'notification.template', '30%',
|
||||
(rule) => `${rule.templateId}`,
|
||||
new EntityTableColumn<NotificationRule>('templateId', 'notification.template', '15%',
|
||||
(rule) => `${rule.templateId.id}`,
|
||||
() => ({}), false),
|
||||
new EntityTableColumn<NotificationRule>('configuration.description', 'notification.description', '40%',
|
||||
(rule) => rule.configuration.description || '',
|
||||
() => ({}), false)
|
||||
new EntityTableColumn<NotificationRule>('triggerType', 'notification.trigger.trigger', '15%',
|
||||
(rule) => this.translate.instant(TriggerTypeTranslationMap.get(rule.triggerType)) || '',
|
||||
() => ({}), true)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -17,22 +17,23 @@
|
||||
-->
|
||||
|
||||
<form [formGroup]="escalationFormGroup" fxLayout="column">
|
||||
<div fxLayout="row" style="align-items: center; min-height: 74px; border-radius: 8px; background: rgba(0,0,0,0.04);">
|
||||
<div fxFlex fxLayout="row">
|
||||
<div fxFlex *ngIf="systemEscalation" style="padding: 0 10px;" translate>notification.first-recipient</div>
|
||||
<div fxFlex *ngIf="!systemEscalation" fxLayout="row" style="align-items: center;">
|
||||
<span style="padding: 0 10px;">After</span>
|
||||
<div class="escalation" fxLayout="row" fxLayout.xs="column" fxLayoutAlign="center center" fxLayoutAlign.xs="start">
|
||||
<div fxFlex fxLayout="row" ngStyle.xs="padding-top: 10px">
|
||||
<div fxFlex [fxShow]="systemEscalation" class="escalation-padding" translate>notification.first-recipient</div>
|
||||
<div fxFlex [fxShow]="!systemEscalation" fxLayout="row" fxLayout.xs="column" fxLayoutAlign="center center">
|
||||
<span class="escalation-padding">After</span>
|
||||
<tb-timeinterval
|
||||
style="min-width: 100px;"
|
||||
ngStyle.xs="padding: 0 10px;"
|
||||
formControlName="delayInSec"
|
||||
[disabledAdvanced]="true"
|
||||
style="padding-top: 8px; width: 150px; min-width: 150px;"></tb-timeinterval>
|
||||
<span fxFlex style="text-align: end; padding: 0 10px;" translate>notification.notify</span>
|
||||
[disabledAdvanced]="true"></tb-timeinterval>
|
||||
<span fxFlex class="escalation-notify" translate>notification.notify</span>
|
||||
</div>
|
||||
</div>
|
||||
<div fxFlex style="padding: 0 10px;">
|
||||
<div fxFlex class="escalation-padding">
|
||||
<tb-entity-list
|
||||
required
|
||||
formControlName="notificationTargetId"
|
||||
formControlName="targets"
|
||||
[entityType]="entityType.NOTIFICATION_TARGET"
|
||||
placeholderText="notification.add-target">
|
||||
</tb-entity-list>
|
||||
|
||||
@ -0,0 +1,34 @@
|
||||
/**
|
||||
* Copyright © 2016-2022 The Thingsboard Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
:host {
|
||||
.escalation {
|
||||
height: 100%;
|
||||
min-height: 74px;
|
||||
max-height: 100%;
|
||||
border-radius: 8px;
|
||||
background: rgba(0,0,0,0.04);
|
||||
}
|
||||
|
||||
.escalation-padding {
|
||||
padding: 0 10px;
|
||||
}
|
||||
|
||||
.escalation-notify {
|
||||
text-align: end;
|
||||
padding: 0 10px;
|
||||
}
|
||||
}
|
||||
@ -22,18 +22,20 @@ import {
|
||||
FormGroup,
|
||||
NG_VALIDATORS,
|
||||
NG_VALUE_ACCESSOR,
|
||||
Validator, Validators
|
||||
Validator,
|
||||
Validators
|
||||
} from '@angular/forms';
|
||||
import { UtilsService } from '@core/services/utils.service';
|
||||
import { isDefinedAndNotNull } from '@core/utils';
|
||||
import { Subscription } from 'rxjs';
|
||||
import { Subject } from 'rxjs';
|
||||
import { NonConfirmedNotificationEscalation } from '@shared/models/notification.models';
|
||||
import { EntityType } from '@shared/models/entity-type.models';
|
||||
import { takeUntil } from 'rxjs/operators';
|
||||
|
||||
@Component({
|
||||
selector: 'tb-escalation-form',
|
||||
templateUrl: './escalation-form.component.html',
|
||||
styleUrls: [],
|
||||
styleUrls: ['./escalation-form.component.scss'],
|
||||
providers: [
|
||||
{
|
||||
provide: NG_VALUE_ACCESSOR,
|
||||
@ -59,10 +61,10 @@ export class EscalationFormComponent implements ControlValueAccessor, OnInit, On
|
||||
|
||||
entityType = EntityType;
|
||||
|
||||
private modelValue: NonConfirmedNotificationEscalation;
|
||||
private modelValue;
|
||||
private propagateChange = null;
|
||||
private propagateChangePending = false;
|
||||
private valueChange$: Subscription = null;
|
||||
private destroy$ = new Subject();
|
||||
|
||||
constructor(private utils: UtilsService,
|
||||
private fb: FormBuilder) {
|
||||
@ -84,19 +86,17 @@ export class EscalationFormComponent implements ControlValueAccessor, OnInit, On
|
||||
ngOnInit() {
|
||||
this.escalationFormGroup = this.fb.group(
|
||||
{
|
||||
delayInSec: [null],
|
||||
notificationTargetId: [null, Validators.required],
|
||||
delayInSec: [0],
|
||||
targets: [null, Validators.required],
|
||||
});
|
||||
this.valueChange$ = this.escalationFormGroup.valueChanges.subscribe(() => {
|
||||
this.updateModel();
|
||||
});
|
||||
this.escalationFormGroup.valueChanges.pipe(
|
||||
takeUntil(this.destroy$)
|
||||
).subscribe(() => this.updateModel());
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
if (this.valueChange$) {
|
||||
this.valueChange$.unsubscribe();
|
||||
this.valueChange$ = null;
|
||||
}
|
||||
this.destroy$.next();
|
||||
this.destroy$.complete();
|
||||
}
|
||||
|
||||
setDisabledState(isDisabled: boolean): void {
|
||||
|
||||
@ -30,11 +30,10 @@ import {
|
||||
import { Store } from '@ngrx/store';
|
||||
import { AppState } from '@app/core/core.state';
|
||||
import { coerceBooleanProperty } from '@angular/cdk/coercion';
|
||||
import { Subscription } from 'rxjs';
|
||||
import { QueueInfo } from '@shared/models/queue.models';
|
||||
import { Subject } from 'rxjs';
|
||||
import { UtilsService } from '@core/services/utils.service';
|
||||
import { guid } from '@core/utils';
|
||||
import { NonConfirmedNotificationEscalation } from '@shared/models/notification.models';
|
||||
import { takeUntil } from 'rxjs/operators';
|
||||
|
||||
@Component({
|
||||
selector: 'tb-escalations-component',
|
||||
@ -71,11 +70,11 @@ export class EscalationsComponent implements ControlValueAccessor, Validator, On
|
||||
disabled: boolean;
|
||||
|
||||
private mainEscalaion = {
|
||||
delayInSec: null,
|
||||
notificationTargetId: null
|
||||
delayInSec: 0,
|
||||
targets: null
|
||||
};
|
||||
|
||||
private valueChangeSubscription$: Subscription = null;
|
||||
private destroy$ = new Subject();
|
||||
|
||||
private propagateChange = (v: any) => { };
|
||||
|
||||
@ -89,9 +88,8 @@ export class EscalationsComponent implements ControlValueAccessor, Validator, On
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
if (this.valueChangeSubscription$) {
|
||||
this.valueChangeSubscription$.unsubscribe();
|
||||
}
|
||||
this.destroy$.next();
|
||||
this.destroy$.complete();
|
||||
}
|
||||
|
||||
registerOnTouched(fn: any): void {
|
||||
@ -101,6 +99,10 @@ export class EscalationsComponent implements ControlValueAccessor, Validator, On
|
||||
this.escalationsFormGroup = this.fb.group({
|
||||
escalations: this.fb.array([])
|
||||
});
|
||||
|
||||
this.escalationsFormGroup.valueChanges.pipe(
|
||||
takeUntil(this.destroy$)
|
||||
).subscribe(() => this.updateModel());
|
||||
}
|
||||
|
||||
get escalationsFormArray(): FormArray {
|
||||
@ -117,26 +119,24 @@ export class EscalationsComponent implements ControlValueAccessor, Validator, On
|
||||
}
|
||||
|
||||
writeValue(escalations: Array<NonConfirmedNotificationEscalation> | null): void {
|
||||
if (this.valueChangeSubscription$) {
|
||||
this.valueChangeSubscription$.unsubscribe();
|
||||
}
|
||||
const escalationsControls: Array<AbstractControl> = [];
|
||||
if (escalations) {
|
||||
escalations.forEach((escalation, index) => {
|
||||
escalationsControls.push(this.fb.control(escalation, [Validators.required]));
|
||||
});
|
||||
if (escalations?.length === this.escalationsFormArray.length) {
|
||||
this.escalationsFormArray.patchValue(escalations, {emitEvent: false});
|
||||
} else {
|
||||
escalationsControls.push(this.fb.control(this.mainEscalaion, [Validators.required]));
|
||||
const escalationsControls: Array<AbstractControl> = [];
|
||||
if (escalations) {
|
||||
escalations.forEach((escalation, index) => {
|
||||
escalationsControls.push(this.fb.control(escalation, [Validators.required]));
|
||||
});
|
||||
} else {
|
||||
escalationsControls.push(this.fb.control(this.mainEscalaion, [Validators.required]));
|
||||
}
|
||||
this.escalationsFormGroup.setControl('escalations', this.fb.array(escalationsControls), {emitEvent: false});
|
||||
if (this.disabled) {
|
||||
this.escalationsFormGroup.disable({emitEvent: false});
|
||||
} else {
|
||||
this.escalationsFormGroup.enable({emitEvent: false});
|
||||
}
|
||||
}
|
||||
this.escalationsFormGroup.setControl('escalations', this.fb.array(escalationsControls));
|
||||
if (this.disabled) {
|
||||
this.escalationsFormGroup.disable({emitEvent: false});
|
||||
} else {
|
||||
this.escalationsFormGroup.enable({emitEvent: false});
|
||||
}
|
||||
this.valueChangeSubscription$ = this.escalationsFormGroup.valueChanges.subscribe(() =>
|
||||
this.updateModel()
|
||||
);
|
||||
}
|
||||
|
||||
public removeEscalation(index: number) {
|
||||
@ -144,9 +144,9 @@ export class EscalationsComponent implements ControlValueAccessor, Validator, On
|
||||
}
|
||||
|
||||
public addEscalation() {
|
||||
const escalation: NonConfirmedNotificationEscalation = {
|
||||
delayInSec: null,
|
||||
notificationTargetId: null
|
||||
const escalation = {
|
||||
delayInSec: 0,
|
||||
targets: null
|
||||
};
|
||||
this.newEscalation = true;
|
||||
const escalationArray = this.escalationsFormGroup.get('escalations') as FormArray;
|
||||
@ -166,7 +166,7 @@ export class EscalationsComponent implements ControlValueAccessor, Validator, On
|
||||
}
|
||||
|
||||
private updateModel() {
|
||||
const escalations: Array<NonConfirmedNotificationEscalation> = this.escalationsFormGroup.get('escalations').value;
|
||||
const escalations = this.escalationsFormGroup.get('escalations').value;
|
||||
this.propagateChange(escalations);
|
||||
}
|
||||
}
|
||||
|
||||
@ -15,224 +15,231 @@
|
||||
limitations under the License.
|
||||
|
||||
-->
|
||||
|
||||
<mat-toolbar color="primary">
|
||||
<h2>{{'notification.add-rule' | translate }}</h2>
|
||||
<span fxFlex></span>
|
||||
<button mat-icon-button
|
||||
(click)="cancel()"
|
||||
type="button">
|
||||
<mat-icon class="material-icons">close</mat-icon>
|
||||
</button>
|
||||
</mat-toolbar>
|
||||
<mat-progress-bar color="warn" mode="indeterminate" *ngIf="isLoading$ | async">
|
||||
</mat-progress-bar>
|
||||
<div style="height: 4px;" *ngIf="!(isLoading$ | async)"></div>
|
||||
<div mat-dialog-content>
|
||||
<mat-horizontal-stepper [linear]="true" labelPosition="end" #addNotificationRule [orientation]="(stepperOrientation | async)"
|
||||
(selectionChange)="changeStep($event)">
|
||||
<ng-template matStepperIcon="edit">
|
||||
<mat-icon>check</mat-icon>
|
||||
</ng-template>
|
||||
<mat-step optional [stepControl]="ruleNotificationForm">
|
||||
<ng-template matStepLabel>{{ 'notification.basic-settings' | translate }}</ng-template>
|
||||
<form [formGroup]="ruleNotificationForm" style="padding-bottom: 16px;">
|
||||
<mat-form-field class="mat-block">
|
||||
<mat-label translate>notification.rule-name</mat-label>
|
||||
<input matInput formControlName="name" required>
|
||||
<mat-error *ngIf="ruleNotificationForm.get('name').hasError('required')">
|
||||
{{ 'notification.rule-name-required' | translate }}
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
<tb-template-autocomplete
|
||||
required
|
||||
formControlName="templateId"
|
||||
labelText="notification.template-name"
|
||||
placeholderText="notification.template-name"
|
||||
requiredText="notification.template-required">
|
||||
</tb-template-autocomplete>
|
||||
<mat-form-field class="mat-block">
|
||||
<mat-label translate>notification.trigger.trigger</mat-label>
|
||||
<mat-select formControlName="trigger" required>
|
||||
<mat-option *ngFor="let trigger of triggerTypes" [value]="trigger">
|
||||
{{ triggerTypeTranslationMap.get(trigger) | translate }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
<mat-error *ngIf="ruleNotificationForm.get('trigger').hasError('required')">
|
||||
{{ 'notification.trigger.trigger-required' | translate }}
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
</form>
|
||||
</mat-step>
|
||||
<mat-step *ngIf="ruleNotificationForm.get('trigger').value === triggerType.ALARM"
|
||||
[stepControl]="alarmTemplateForm">
|
||||
<ng-template matStepLabel>{{ 'notification.type-settings' | translate }}</ng-template>
|
||||
<form [formGroup]="alarmTemplateForm">
|
||||
<fieldset class="fields-group">
|
||||
<span class="fields-group-title" translate>notification.filter</span>
|
||||
<mat-form-field fxFlex class="mat-block" floatLabel="always">
|
||||
<mat-label translate>alarm.alarm-type-list</mat-label>
|
||||
<mat-chip-list #alarmTypeChipList formControlName="alarmTypeList">
|
||||
<mat-chip *ngFor="let type of alarmTypeList()" [selectable]="true"
|
||||
[removable]="true" (removed)="removeAlarmType(type)">
|
||||
{{type}}
|
||||
<mat-icon matChipRemove>cancel</mat-icon>
|
||||
</mat-chip>
|
||||
<input placeholder="{{ !alarmTemplateForm.get('alarmTypeList').value?.length ? ('alarm.any-type' | translate) : '' }}"
|
||||
[matChipInputFor]="alarmTypeChipList"
|
||||
[matChipInputSeparatorKeyCodes]="separatorKeysCodes"
|
||||
matChipInputAddOnBlur
|
||||
(matChipInputTokenEnd)="addAlarmType($event)">
|
||||
</mat-chip-list>
|
||||
<section style="width: 800px; min-width: 100%; max-width: 100%">
|
||||
<mat-toolbar color="primary">
|
||||
<h2>{{'notification.add-rule' | translate }}</h2>
|
||||
<span fxFlex></span>
|
||||
<button mat-icon-button
|
||||
(click)="cancel()"
|
||||
type="button">
|
||||
<mat-icon class="material-icons">close</mat-icon>
|
||||
</button>
|
||||
</mat-toolbar>
|
||||
<mat-progress-bar color="warn" mode="indeterminate" *ngIf="isLoading$ | async">
|
||||
</mat-progress-bar>
|
||||
<div style="height: 4px;" *ngIf="!(isLoading$ | async)"></div>
|
||||
<div mat-dialog-content ngStyle.xs="padding: 0;">
|
||||
<mat-horizontal-stepper [linear]="true" labelPosition="end" #addNotificationRule [orientation]="(stepperOrientation | async)"
|
||||
(selectionChange)="changeStep($event)">
|
||||
<ng-template matStepperIcon="edit">
|
||||
<mat-icon>check</mat-icon>
|
||||
</ng-template>
|
||||
<mat-step optional [stepControl]="ruleNotificationForm">
|
||||
<ng-template matStepLabel>{{ 'notification.basic-settings' | translate }}</ng-template>
|
||||
<form [formGroup]="ruleNotificationForm" style="padding-bottom: 16px;">
|
||||
<mat-form-field class="mat-block">
|
||||
<mat-label translate>notification.rule-name</mat-label>
|
||||
<input matInput formControlName="name" required>
|
||||
<mat-error *ngIf="ruleNotificationForm.get('name').hasError('required')">
|
||||
{{ 'notification.rule-name-required' | translate }}
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field fxFlex class="mat-block">
|
||||
<mat-label translate>alarm.alarm-severity-list</mat-label>
|
||||
<mat-chip-list #severitiesChipList
|
||||
required>
|
||||
<mat-chip *ngFor="let severity of alarmTemplateForm.get('alarmSeverityList').value"
|
||||
[removable]="true" (removed)="onSeverityRemoved(severity)">
|
||||
{{ alarmSeverityTranslationMap.get(severity) | translate }}
|
||||
<mat-icon matChipRemove>cancel</mat-icon>
|
||||
</mat-chip>
|
||||
<input matInput
|
||||
type="text"
|
||||
placeholder="{{ !alarmTemplateForm.get('alarmSeverityList').value?.length ? ('alarm.any-severity' | translate) : '' }}"
|
||||
style="max-width: 200px;"
|
||||
#severityInput
|
||||
(focusin)="onSeverityInputFocus()"
|
||||
matAutocompleteOrigin
|
||||
#origin="matAutocompleteOrigin"
|
||||
(input)="severityInputChange.next(severityInput.value)"
|
||||
[matAutocompleteConnectedTo]="origin"
|
||||
[matAutocomplete]="severityAutocomplete"
|
||||
[matChipInputFor]="severitiesChipList"
|
||||
[matChipInputSeparatorKeyCodes]="separatorKeysCodes"
|
||||
(matChipInputTokenEnd)="addSeverityFromChipInput($event)">
|
||||
</mat-chip-list>
|
||||
<mat-autocomplete #severityAutocomplete="matAutocomplete"
|
||||
class="tb-autocomplete"
|
||||
(optionSelected)="severitySelected($event)"
|
||||
[displayWith]="displaySeverityFn.bind(this)">
|
||||
<mat-option *ngFor="let severity of filteredDisplaySeverities | async" [value]="severity">
|
||||
<span [innerHTML]="alarmSeverityTranslationMap.get(alarmSeverityEnum[severity]) | translate | highlight:severitySearchText"></span>
|
||||
</mat-option>
|
||||
<mat-option *ngIf="(filteredDisplaySeverities | async)?.length === 0" [value]="null" class="tb-not-found">
|
||||
<div class="tb-not-found-content" (click)="$event.stopPropagation()">
|
||||
<div *ngIf="!textIsNotEmpty(severitySearchText); else searchNotEmpty">
|
||||
<span translate>notification.no-severity-found</span>
|
||||
</div>
|
||||
<ng-template #searchNotEmpty>
|
||||
<span>
|
||||
{{ translate.get('notification.no-severity-matching',
|
||||
{severity: truncate.transform(severitySearchText, true, 6, '...')}) | async }}
|
||||
</span>
|
||||
</ng-template>
|
||||
</div>
|
||||
</mat-option>
|
||||
</mat-autocomplete>
|
||||
</mat-form-field>
|
||||
</fieldset>
|
||||
|
||||
<fieldset class="fields-group">
|
||||
<span class="fields-group-title" translate>notification.clear-rule</span>
|
||||
<mat-form-field fxFlex class="mat-block" floatLabel="always">
|
||||
<mat-label translate>alarm.alarm-status-list</mat-label>
|
||||
<mat-select formControlName="alarmStatusList"
|
||||
placeholder="{{ !alarmTemplateForm.get('alarmStatusList').value?.length ? ('alarm.any-status' | translate) : '' }}">
|
||||
<mat-option *ngFor="let searchStatus of alarmSearchStatuses" [value]="searchStatus">
|
||||
{{ alarmSearchStatusTranslationMap.get(searchStatus) | translate }}
|
||||
<tb-template-autocomplete
|
||||
required
|
||||
formControlName="templateId"
|
||||
labelText="notification.template-name"
|
||||
placeholderText="notification.template-name"
|
||||
requiredText="notification.template-required">
|
||||
</tb-template-autocomplete>
|
||||
<mat-form-field class="mat-block">
|
||||
<mat-label translate>notification.trigger.trigger</mat-label>
|
||||
<mat-select formControlName="triggerType" required>
|
||||
<mat-option *ngFor="let trigger of triggerTypes" [value]="trigger">
|
||||
{{ triggerTypeTranslationMap.get(trigger) | translate }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
<mat-error *ngIf="ruleNotificationForm.get('triggerType').hasError('required')">
|
||||
{{ 'notification.trigger.trigger-required' | translate }}
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
</fieldset>
|
||||
</form>
|
||||
</mat-step>
|
||||
<mat-step optional [stepControl]="alarmTemplateForm"
|
||||
*ngIf="ruleNotificationForm.get('triggerType').value === triggerType.ALARM">
|
||||
<ng-template matStepLabel>{{ 'notification.type-settings' | translate }}</ng-template>
|
||||
<form [formGroup]="alarmTemplateForm">
|
||||
<fieldset class="fields-group">
|
||||
<span class="fields-group-title" translate>notification.filter</span>
|
||||
<mat-form-field fxFlex class="mat-block" floatLabel="always">
|
||||
<mat-label translate>alarm.alarm-type-list</mat-label>
|
||||
<mat-chip-list #alarmTypeChipList formControlName="alarmTypes">
|
||||
<mat-chip *ngFor="let type of alarmTypeList()" [selectable]="true"
|
||||
[removable]="true" (removed)="removeAlarmType(type)">
|
||||
{{type}}
|
||||
<mat-icon matChipRemove>cancel</mat-icon>
|
||||
</mat-chip>
|
||||
<input placeholder="{{ !alarmTemplateForm.get('alarmTypes').value?.length ? ('alarm.any-type' | translate) : '' }}"
|
||||
[matChipInputFor]="alarmTypeChipList"
|
||||
[matChipInputSeparatorKeyCodes]="separatorKeysCodes"
|
||||
matChipInputAddOnBlur
|
||||
(matChipInputTokenEnd)="addAlarmType($event)">
|
||||
</mat-chip-list>
|
||||
</mat-form-field>
|
||||
|
||||
<fieldset class="fields-group">
|
||||
<span class="fields-group-title" translate>notification.hierarchy-of-receiving</span>
|
||||
<tb-escalations-component formControlName="escalationConfig"></tb-escalations-component>
|
||||
</fieldset>
|
||||
<mat-form-field fxFlex class="mat-block">
|
||||
<mat-label translate>alarm.alarm-severity-list</mat-label>
|
||||
<mat-chip-list #severitiesChipList formControlName="alarmSeverities"
|
||||
required>
|
||||
<mat-chip *ngFor="let severity of alarmTemplateForm.get('alarmSeverities').value"
|
||||
[removable]="true" (removed)="onSeverityRemoved(severity)">
|
||||
{{ alarmSeverityTranslationMap.get(severity) | translate }}
|
||||
<mat-icon matChipRemove>cancel</mat-icon>
|
||||
</mat-chip>
|
||||
<input matInput
|
||||
type="text"
|
||||
placeholder="{{ !alarmTemplateForm.get('alarmSeverities').value?.length ? ('alarm.any-severity' | translate) : '' }}"
|
||||
style="max-width: 200px;"
|
||||
#severityInput
|
||||
(focusin)="onSeverityInputFocus()"
|
||||
matAutocompleteOrigin
|
||||
#origin="matAutocompleteOrigin"
|
||||
(input)="severityInputChange.next(severityInput.value)"
|
||||
[matAutocompleteConnectedTo]="origin"
|
||||
[matAutocomplete]="severityAutocomplete"
|
||||
[matChipInputFor]="severitiesChipList"
|
||||
[matChipInputSeparatorKeyCodes]="separatorKeysCodes"
|
||||
(matChipInputTokenEnd)="addSeverityFromChipInput($event)">
|
||||
</mat-chip-list>
|
||||
<mat-autocomplete #severityAutocomplete="matAutocomplete"
|
||||
class="tb-autocomplete"
|
||||
(optionSelected)="severitySelected($event)"
|
||||
[displayWith]="displaySeverityFn.bind(this)">
|
||||
<mat-option *ngFor="let severity of filteredDisplaySeverities | async" [value]="severity">
|
||||
<span [innerHTML]="alarmSeverityTranslationMap.get(alarmSeverityEnum[severity]) | translate | highlight:severitySearchText"></span>
|
||||
</mat-option>
|
||||
<mat-option *ngIf="(filteredDisplaySeverities | async)?.length === 0" [value]="null" class="tb-not-found">
|
||||
<div class="tb-not-found-content" (click)="$event.stopPropagation()">
|
||||
<div *ngIf="!textIsNotEmpty(severitySearchText); else searchNotEmpty">
|
||||
<span translate>notification.no-severity-found</span>
|
||||
</div>
|
||||
<ng-template #searchNotEmpty>
|
||||
<span>
|
||||
{{ translate.get('notification.no-severity-matching',
|
||||
{severity: truncate.transform(severitySearchText, true, 6, '...')}) | async }}
|
||||
</span>
|
||||
</ng-template>
|
||||
</div>
|
||||
</mat-option>
|
||||
</mat-autocomplete>
|
||||
</mat-form-field>
|
||||
</fieldset>
|
||||
|
||||
<mat-form-field class="mat-block">
|
||||
<mat-label translate>notification.description</mat-label>
|
||||
<input matInput formControlName="description">
|
||||
</mat-form-field>
|
||||
</form>
|
||||
</mat-step>
|
||||
<fieldset class="fields-group" formGroupName="clearRule">
|
||||
<span class="fields-group-title" translate>notification.clear-rule</span>
|
||||
<mat-form-field fxFlex class="mat-block" floatLabel="always">
|
||||
<mat-label translate>alarm.alarm-status-list</mat-label>
|
||||
<mat-select formControlName="alarmStatus"
|
||||
placeholder="{{ !alarmTemplateForm.get('clearRule.alarmStatus').value?.length ? ('alarm.any-status' | translate) : '' }}">
|
||||
<mat-option *ngFor="let searchStatus of alarmSearchStatuses" [value]="searchStatus">
|
||||
{{ alarmSearchStatusTranslationMap.get(searchStatus) | translate }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
</fieldset>
|
||||
|
||||
<mat-step optional *ngIf="ruleNotificationForm.get('trigger').value === triggerType.DEVICE_INACTIVITY"
|
||||
[stepControl]="deviceInactivityTemplateForm">
|
||||
<ng-template matStepLabel>{{ 'notification.type-settings' | translate }}</ng-template>
|
||||
<form [formGroup]="deviceInactivityTemplateForm">
|
||||
<span translate>notification.filter-by</span>
|
||||
<div fxFlex fxLayoutAlign="center center">
|
||||
<mat-button-toggle-group class="tb-notification-unread-toggle-group"
|
||||
style="width: 250px;"
|
||||
formControlName="filterByDevice">
|
||||
<mat-button-toggle fxFlex [value]=true>{{ 'notification.device' | translate }}</mat-button-toggle>
|
||||
<mat-button-toggle fxFlex [value]=false>{{ 'notification.device-profile' | translate }}</mat-button-toggle>
|
||||
</mat-button-toggle-group>
|
||||
</div>
|
||||
<tb-device-profile-autocomplete
|
||||
*ngIf="!deviceInactivityTemplateForm.get('filterByDevice').value"
|
||||
formControlName="deviceProfileId"
|
||||
[editProfileEnabled]="false">
|
||||
</tb-device-profile-autocomplete>
|
||||
<tb-entity-autocomplete
|
||||
*ngIf="deviceInactivityTemplateForm.get('filterByDevice').value"
|
||||
formControlName="deviceId"
|
||||
[entityType]="entityType.DEVICE">
|
||||
</tb-entity-autocomplete>
|
||||
<tb-entity-list
|
||||
required
|
||||
formControlName="notificationTargetId"
|
||||
[entityType]="entityType.NOTIFICATION_TARGET"
|
||||
placeholderText="notification.target">
|
||||
</tb-entity-list>
|
||||
<mat-form-field class="mat-block">
|
||||
<mat-label translate>notification.description</mat-label>
|
||||
<input matInput formControlName="description">
|
||||
</mat-form-field>
|
||||
</form>
|
||||
</mat-step>
|
||||
<fieldset class="fields-group">
|
||||
<span class="fields-group-title" translate>notification.hierarchy-of-receiving</span>
|
||||
<tb-escalations-component formControlName="escalationTable"></tb-escalations-component>
|
||||
</fieldset>
|
||||
|
||||
<mat-step optional *ngIf="ruleNotificationForm.get('trigger').value === triggerType.ENTITY_ACTION"
|
||||
[stepControl]="entityActionTemplateForm">
|
||||
<ng-template matStepLabel>{{ 'notification.type-settings' | translate }}</ng-template>
|
||||
<form [formGroup]="entityActionTemplateForm">
|
||||
<fieldset class="fields-group">
|
||||
<span class="fields-group-title" translate>notification.filter</span>
|
||||
<tb-entity-type-select required
|
||||
showLabel
|
||||
[allowedEntityTypes]="entityTypes"
|
||||
formControlName="entityType">
|
||||
</tb-entity-type-select>
|
||||
<section formGroupName="status" fxLayout="column" fxLayoutGap="10px">
|
||||
<span fxFlex translate>notification.status</span>
|
||||
<mat-checkbox fxFlex formControlName="created" translate>{{ 'notification.created' | translate }}</mat-checkbox>
|
||||
<mat-checkbox fxFlex formControlName="updated" translate>{{ 'notification.updated' | translate }}</mat-checkbox>
|
||||
<mat-checkbox fxFlex formControlName="deleted" translate>{{ 'notification.deleted' | translate }}</mat-checkbox>
|
||||
</section>
|
||||
</fieldset>
|
||||
<tb-entity-list
|
||||
required
|
||||
formControlName="notificationTargetId"
|
||||
[entityType]="entityType.NOTIFICATION_TARGET"
|
||||
placeholderText="notification.target">
|
||||
</tb-entity-list>
|
||||
<mat-form-field class="mat-block">
|
||||
<mat-label translate>notification.description</mat-label>
|
||||
<input matInput formControlName="description">
|
||||
</mat-form-field>
|
||||
</form>
|
||||
</mat-step>
|
||||
</mat-horizontal-stepper>
|
||||
</div>
|
||||
<mat-divider></mat-divider>
|
||||
<div mat-dialog-actions fxLayout="row">
|
||||
<button mat-stroked-button *ngIf="selectedIndex > 0"
|
||||
(click)="backStep()">{{ 'action.back' | translate }}</button>
|
||||
<span fxFlex></span>
|
||||
<button mat-raised-button
|
||||
color="primary"
|
||||
(click)="nextStep()">{{ nextStepLabel() | translate }}</button>
|
||||
</div>
|
||||
<mat-form-field class="mat-block">
|
||||
<mat-label translate>notification.description</mat-label>
|
||||
<input matInput formControlName="description">
|
||||
</mat-form-field>
|
||||
</form>
|
||||
</mat-step>
|
||||
|
||||
<mat-step optional *ngIf="ruleNotificationForm.get('triggerType').value === triggerType.DEVICE_INACTIVITY"
|
||||
[stepControl]="deviceInactivityTemplateForm">
|
||||
<ng-template matStepLabel>{{ 'notification.type-settings' | translate }}</ng-template>
|
||||
<form [formGroup]="deviceInactivityTemplateForm">
|
||||
<span translate>notification.filter-by</span>
|
||||
<div fxFlex fxLayoutAlign="center center">
|
||||
<mat-button-toggle-group class="tb-notification-unread-toggle-group"
|
||||
style="width: 250px;"
|
||||
formControlName="filterByDevice">
|
||||
<mat-button-toggle fxFlex [value]=true>{{ 'notification.device' | translate }}</mat-button-toggle>
|
||||
<mat-button-toggle fxFlex [value]=false>{{ 'notification.device-profile' | translate }}</mat-button-toggle>
|
||||
</mat-button-toggle-group>
|
||||
</div>
|
||||
<tb-entity-list
|
||||
*ngIf="deviceInactivityTemplateForm.get('filterByDevice').value"
|
||||
required
|
||||
formControlName="devices"
|
||||
[labelText]="translate.instant('notification.devices')"
|
||||
[placeholderText]="translate.instant('notification.device')"
|
||||
[entityType]="entityType.DEVICE">
|
||||
</tb-entity-list>
|
||||
<tb-entity-list
|
||||
*ngIf="!deviceInactivityTemplateForm.get('filterByDevice').value"
|
||||
required
|
||||
formControlName="deviceProfiles"
|
||||
[labelText]="translate.instant('notification.device-profiles')"
|
||||
[placeholderText]="translate.instant('notification.device-profile')"
|
||||
[entityType]="entityType.DEVICE_PROFILE">
|
||||
</tb-entity-list>
|
||||
<tb-entity-list
|
||||
required
|
||||
formControlName="targets"
|
||||
[entityType]="entityType.NOTIFICATION_TARGET"
|
||||
placeholderText="notification.target">
|
||||
</tb-entity-list>
|
||||
<mat-form-field class="mat-block">
|
||||
<mat-label translate>notification.description</mat-label>
|
||||
<input matInput formControlName="description">
|
||||
</mat-form-field>
|
||||
</form>
|
||||
</mat-step>
|
||||
|
||||
<mat-step optional *ngIf="ruleNotificationForm.get('triggerType').value === triggerType.ENTITY_ACTION"
|
||||
[stepControl]="entityActionTemplateForm">
|
||||
<ng-template matStepLabel>{{ 'notification.type-settings' | translate }}</ng-template>
|
||||
<form [formGroup]="entityActionTemplateForm">
|
||||
<fieldset class="fields-group">
|
||||
<span class="fields-group-title" translate>notification.filter</span>
|
||||
<tb-entity-type-select required
|
||||
showLabel
|
||||
[allowedEntityTypes]="entityTypes"
|
||||
formControlName="entityType">
|
||||
</tb-entity-type-select>
|
||||
<section fxLayout="column" fxLayoutGap="10px">
|
||||
<span fxFlex translate>notification.status</span>
|
||||
<mat-checkbox fxFlex formControlName="created" translate>{{ 'notification.created' | translate }}</mat-checkbox>
|
||||
<mat-checkbox fxFlex formControlName="updated" translate>{{ 'notification.updated' | translate }}</mat-checkbox>
|
||||
<mat-checkbox fxFlex formControlName="deleted" translate>{{ 'notification.deleted' | translate }}</mat-checkbox>
|
||||
</section>
|
||||
</fieldset>
|
||||
<tb-entity-list
|
||||
required
|
||||
formControlName="targets"
|
||||
[entityType]="entityType.NOTIFICATION_TARGET"
|
||||
placeholderText="notification.target">
|
||||
</tb-entity-list>
|
||||
<mat-form-field class="mat-block">
|
||||
<mat-label translate>notification.description</mat-label>
|
||||
<input matInput formControlName="description">
|
||||
</mat-form-field>
|
||||
</form>
|
||||
</mat-step>
|
||||
</mat-horizontal-stepper>
|
||||
</div>
|
||||
<mat-divider></mat-divider>
|
||||
<div mat-dialog-actions fxLayout="row">
|
||||
<button mat-stroked-button *ngIf="selectedIndex > 0"
|
||||
(click)="backStep()">{{ 'action.back' | translate }}</button>
|
||||
<span fxFlex></span>
|
||||
<button mat-raised-button
|
||||
color="primary"
|
||||
(click)="nextStep()">{{ nextStepLabel() | translate }}</button>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
@ -17,9 +17,9 @@
|
||||
|
||||
:host {
|
||||
::ng-deep{
|
||||
width: 100%;
|
||||
min-width: 800px !important;
|
||||
max-width: 100%;
|
||||
//width: 100%;
|
||||
//min-width: 800px;
|
||||
//max-width: 100%;
|
||||
|
||||
.mat-button-toggle-group.tb-notification-unread-toggle-group {
|
||||
&.mat-button-toggle-group-appearance-standard {
|
||||
|
||||
@ -23,10 +23,10 @@ import { Router } from '@angular/router';
|
||||
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
|
||||
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
|
||||
import { NotificationService } from '@core/http/notification.service';
|
||||
import { EntityType, entityTypeTranslations } from '@shared/models/entity-type.models';
|
||||
import { EntityType } from '@shared/models/entity-type.models';
|
||||
import { deepTrim, isDefined } from '@core/utils';
|
||||
import { Observable, of, Subject } from 'rxjs';
|
||||
import { map, mergeMap, share, startWith } from 'rxjs/operators';
|
||||
import { map, mergeMap, share, startWith, takeUntil } from 'rxjs/operators';
|
||||
import { StepperOrientation, StepperSelectionEvent } from '@angular/cdk/stepper';
|
||||
import { MatStepper } from '@angular/material/stepper';
|
||||
import { MediaBreakpoints } from '@shared/models/constants';
|
||||
@ -34,12 +34,11 @@ import { BreakpointObserver } from '@angular/cdk/layout';
|
||||
import { MatChipInputEvent, MatChipList } from '@angular/material/chips';
|
||||
import { COMMA, ENTER, SEMICOLON } from '@angular/cdk/keycodes';
|
||||
import {
|
||||
AlarmSearchStatus,
|
||||
alarmSearchStatusTranslations,
|
||||
AlarmSeverity,
|
||||
alarmSeverityTranslations
|
||||
alarmSeverityTranslations,
|
||||
AlarmStatus,
|
||||
alarmStatusTranslations
|
||||
} from '@shared/models/alarm.models';
|
||||
import { CdkDragDrop, moveItemInArray } from '@angular/cdk/drag-drop';
|
||||
import { MatAutocomplete, MatAutocompleteSelectedEvent } from '@angular/material/autocomplete';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { TruncatePipe } from '@shared/pipe/truncate.pipe';
|
||||
@ -80,11 +79,8 @@ export class RuleNotificationDialogComponent extends
|
||||
alarmSeverityEnum = AlarmSeverity;
|
||||
alarmSeverityTranslationMap = alarmSeverityTranslations;
|
||||
|
||||
alarmSearchStatuses = [AlarmSearchStatus.ACTIVE,
|
||||
AlarmSearchStatus.CLEARED,
|
||||
AlarmSearchStatus.ACK,
|
||||
AlarmSearchStatus.UNACK];
|
||||
alarmSearchStatusTranslationMap = alarmSearchStatusTranslations;
|
||||
alarmSearchStatuses = Object.values(AlarmStatus);
|
||||
alarmSearchStatusTranslationMap = alarmStatusTranslations;
|
||||
|
||||
entityType = EntityType;
|
||||
entityTypes = Object.values(EntityType);
|
||||
@ -97,7 +93,7 @@ export class RuleNotificationDialogComponent extends
|
||||
|
||||
severityInputChange = new Subject<string>();
|
||||
|
||||
private readonly destroy$ = new Subject<void>();
|
||||
private destroy$ = new Subject();
|
||||
|
||||
constructor(protected store: Store<AppState>,
|
||||
protected router: Router,
|
||||
@ -120,39 +116,54 @@ export class RuleNotificationDialogComponent extends
|
||||
this.ruleNotificationForm = this.fb.group({
|
||||
name: [null, Validators.required],
|
||||
templateId: [null, Validators.required],
|
||||
trigger: [this.triggerType.ALARM, Validators.required],
|
||||
configuration: this.fb.group({
|
||||
escalationConfig: this.fb.group({
|
||||
escalations: [[]]
|
||||
}),
|
||||
description: [null]
|
||||
triggerType: [null, Validators.required],
|
||||
recipientsConfig: this.fb.group({
|
||||
triggerType: [],
|
||||
}),
|
||||
triggerConfig: this.fb.group({
|
||||
triggerType: []
|
||||
})
|
||||
});
|
||||
|
||||
this.ruleNotificationForm.get('triggerType').valueChanges.pipe(
|
||||
takeUntil(this.destroy$)
|
||||
).subscribe(
|
||||
value => {
|
||||
this.ruleNotificationForm.get('triggerConfig').patchValue({triggerType: value}, {emitEvent: false});
|
||||
this.ruleNotificationForm.get('recipientsConfig').patchValue({triggerType: value}, {emitEvent: false});
|
||||
}
|
||||
);
|
||||
|
||||
this.alarmTemplateForm = this.fb.group({
|
||||
alarmTypeList: [[], Validators.required],
|
||||
alarmSeverityList: [[], Validators.required],
|
||||
alarmStatusList: [[], Validators.required],
|
||||
escalationConfig: [],
|
||||
alarmTypes: [[], Validators.required],
|
||||
alarmSeverities: [[], Validators.required],
|
||||
clearRule: this.fb.group({
|
||||
alarmStatus: []
|
||||
}),
|
||||
escalationTable: [],
|
||||
description: ['']
|
||||
});
|
||||
|
||||
this.deviceInactivityTemplateForm = this.fb.group({
|
||||
filterByDevice: [true],
|
||||
deviceId: [],
|
||||
deviceProfileId: [],
|
||||
notificationTargetId: [],
|
||||
devices: [],
|
||||
deviceProfiles: [],
|
||||
targets: [[], Validators.required],
|
||||
description: ['']
|
||||
});
|
||||
|
||||
this.deviceInactivityTemplateForm.get('filterByDevice').valueChanges.pipe(
|
||||
takeUntil(this.destroy$)
|
||||
).subscribe(
|
||||
value => this.deviceInactivityTemplateForm.get(value ? 'deviceProfiles' : 'devices').patchValue(null, {emitEvent: false})
|
||||
);
|
||||
|
||||
this.entityActionTemplateForm = this.fb.group({
|
||||
entityType: [],
|
||||
status: this.fb.group({
|
||||
created: [false],
|
||||
updated: [false],
|
||||
deleted: [false]
|
||||
}),
|
||||
notificationTargetId: [],
|
||||
created: [false],
|
||||
updated: [false],
|
||||
deleted: [false],
|
||||
targets: [[], Validators.required],
|
||||
description: ['']
|
||||
});
|
||||
|
||||
@ -166,12 +177,12 @@ export class RuleNotificationDialogComponent extends
|
||||
}
|
||||
|
||||
onSeverityRemoved(severity: string): void {
|
||||
const severities: string[] = this.alarmTemplateForm.get('alarmSeverityList').value;
|
||||
const severities: string[] = this.alarmTemplateForm.get('alarmSeverities').value;
|
||||
const index = severities.indexOf(severity);
|
||||
if (index > -1) {
|
||||
severities.splice(index, 1);
|
||||
this.alarmTemplateForm.get('alarmSeverityList').setValue(severities);
|
||||
this.alarmTemplateForm.get('alarmSeverityList').markAsDirty();
|
||||
this.alarmTemplateForm.get('alarmSeverities').setValue(severities);
|
||||
this.alarmTemplateForm.get('alarmSeverities').markAsDirty();
|
||||
this.severitiesChipList.errorState = !severities.length;
|
||||
}
|
||||
}
|
||||
@ -193,12 +204,12 @@ export class RuleNotificationDialogComponent extends
|
||||
|
||||
private addSeverity(existingSeverity: string): boolean {
|
||||
if (existingSeverity) {
|
||||
const displaySeverities: string[] = this.alarmTemplateForm.get('alarmSeverityList').value;
|
||||
const displaySeverities: string[] = this.alarmTemplateForm.get('alarmSeverities').value;
|
||||
const index = displaySeverities.indexOf(existingSeverity);
|
||||
if (index === -1) {
|
||||
displaySeverities.push(existingSeverity);
|
||||
this.alarmTemplateForm.get('alarmSeverityList').setValue(displaySeverities);
|
||||
this.alarmTemplateForm.get('alarmSeverityList').markAsDirty();
|
||||
this.alarmTemplateForm.get('alarmSeverities').setValue(displaySeverities);
|
||||
this.alarmTemplateForm.get('alarmSeverities').markAsDirty();
|
||||
this.severitiesChipList.errorState = false;
|
||||
return true;
|
||||
}
|
||||
@ -239,16 +250,16 @@ export class RuleNotificationDialogComponent extends
|
||||
}
|
||||
|
||||
public alarmTypeList(): string[] {
|
||||
return this.alarmTemplateForm.get('alarmTypeList').value;
|
||||
return this.alarmTemplateForm.get('alarmTypes').value;
|
||||
}
|
||||
|
||||
public removeAlarmType(type: string): void {
|
||||
const types: string[] = this.alarmTemplateForm.get('alarmTypeList').value;
|
||||
const types: string[] = this.alarmTemplateForm.get('alarmTypes').value;
|
||||
const index = types.indexOf(type);
|
||||
if (index >= 0) {
|
||||
types.splice(index, 1);
|
||||
this.alarmTemplateForm.get('alarmTypeList').setValue(types);
|
||||
this.alarmTemplateForm.get('alarmTypeList').markAsDirty();
|
||||
this.alarmTemplateForm.get('alarmTypes').setValue(types);
|
||||
this.alarmTemplateForm.get('alarmTypes').markAsDirty();
|
||||
}
|
||||
}
|
||||
|
||||
@ -256,12 +267,12 @@ export class RuleNotificationDialogComponent extends
|
||||
const input = event.input;
|
||||
const value = event.value;
|
||||
|
||||
const types: string[] = this.alarmTemplateForm.get('alarmTypeList').value;
|
||||
const types: string[] = this.alarmTemplateForm.get('alarmTypes').value;
|
||||
|
||||
if ((value || '').trim()) {
|
||||
types.push(value.trim());
|
||||
this.alarmTemplateForm.get('alarmTypeList').setValue(types);
|
||||
this.alarmTemplateForm.get('alarmTypeList').markAsDirty();
|
||||
this.alarmTemplateForm.get('alarmTypes').setValue(types);
|
||||
this.alarmTemplateForm.get('alarmTypes').markAsDirty();
|
||||
}
|
||||
|
||||
if (input) {
|
||||
@ -307,22 +318,26 @@ export class RuleNotificationDialogComponent extends
|
||||
|
||||
private add(): void {
|
||||
if (this.allValid()) {
|
||||
const formValue: NotificationRule = this.ruleNotificationForm.value;
|
||||
// if (formValue.configuration.deliveryMethodsTemplates.PUSH.enabled) {
|
||||
// Object.assign(formValue.configuration.deliveryMethodsTemplates.PUSH, this.pushTemplateForm.value);
|
||||
// } else {
|
||||
// delete formValue.configuration.deliveryMethodsTemplates.PUSH;
|
||||
// }
|
||||
// if (formValue.configuration.deliveryMethodsTemplates.EMAIL.enabled) {
|
||||
// Object.assign(formValue.configuration.deliveryMethodsTemplates.EMAIL, this.emailTemplateForm.value);
|
||||
// } else {
|
||||
// delete formValue.configuration.deliveryMethodsTemplates.EMAIL;
|
||||
// }
|
||||
// if (formValue.configuration.deliveryMethodsTemplates.SMS.enabled) {
|
||||
// Object.assign(formValue.configuration.deliveryMethodsTemplates.SMS, this.smsTemplateForm.value);
|
||||
// } else {
|
||||
// delete formValue.configuration.deliveryMethodsTemplates.SMS;
|
||||
// }
|
||||
const formValue = this.ruleNotificationForm.value;
|
||||
const triggerType = this.ruleNotificationForm.get('triggerType').value;
|
||||
if (triggerType === TriggerType.ALARM) {
|
||||
Object.assign(formValue.triggerConfig, this.alarmTemplateForm.value);
|
||||
const parsedEscalationTable = {};
|
||||
this.alarmTemplateForm.get('escalationTable').value.forEach(
|
||||
escalation => parsedEscalationTable[escalation.delayInSec] = escalation.targets
|
||||
);
|
||||
formValue.recipientsConfig.escalationTable = parsedEscalationTable;
|
||||
delete formValue.triggerConfig.escalationTable;
|
||||
} else if (triggerType === TriggerType.DEVICE_INACTIVITY) {
|
||||
Object.assign(formValue.triggerConfig, this.deviceInactivityTemplateForm.value);
|
||||
delete formValue.triggerConfig.filterByDevice;
|
||||
} else {
|
||||
Object.assign(formValue.triggerConfig, this.entityActionTemplateForm.value);
|
||||
}
|
||||
if (triggerType === TriggerType.DEVICE_INACTIVITY || triggerType === TriggerType.ENTITY_ACTION) {
|
||||
formValue.recipientsConfig.targets = this.entityActionTemplateForm.get('targets').value;
|
||||
delete formValue.triggerConfig.trigger;
|
||||
}
|
||||
this.notificationService.saveNotificationRule(deepTrim(formValue)).subscribe(
|
||||
(target) => this.dialogRef.close(target)
|
||||
);
|
||||
|
||||
@ -24,6 +24,8 @@ import { NotificationTargetId } from '@shared/models/id/notification-target-id';
|
||||
import { NotificationTemplateId } from '@shared/models/id/notification-template-id';
|
||||
import { EntityId } from '@shared/models/id/entity-id';
|
||||
import { NotificationRuleId } from '@shared/models/id/notification-rule-id';
|
||||
import { AlarmSeverity, AlarmStatus } from '@shared/models/alarm.models';
|
||||
import { EntityType } from '@shared/models/entity-type.models';
|
||||
|
||||
export interface Notification {
|
||||
readonly id: NotificationId;
|
||||
@ -100,18 +102,26 @@ export interface SlackConversation {
|
||||
export interface NotificationRule extends Omit<BaseData<NotificationRuleId>, 'label'>{
|
||||
tenantId: TenantId;
|
||||
templateId: NotificationTemplateId;
|
||||
// deliveryMethods: Array<NotificationDeliveryMethod>;
|
||||
configuration: NotificationRuleConfig;
|
||||
triggerType: TriggerType;
|
||||
triggerConfig: NotificationRuleTriggerConfig;
|
||||
recipientConfig: NotificationRuleRecipientConfig;
|
||||
}
|
||||
|
||||
export interface NotificationRuleConfig {
|
||||
initialNotificationTargetId: NotificationTargetId;
|
||||
escalationConfig: NotificationEscalationConfig;
|
||||
description?: string;
|
||||
export interface NotificationRuleTriggerConfig {
|
||||
alarmTypes?: Array<string>;
|
||||
alarmSeverities?: Array<AlarmSeverity>;
|
||||
clearRule?: AlarmStatus;
|
||||
devices?: Array<string>;
|
||||
devicesProfiles?: Array<string>;
|
||||
entityType?: EntityType;
|
||||
created?: boolean;
|
||||
updated?: boolean;
|
||||
deleted?: boolean;
|
||||
}
|
||||
|
||||
export interface NotificationEscalationConfig {
|
||||
escalations: Array<NonConfirmedNotificationEscalation>;
|
||||
export interface NotificationRuleRecipientConfig {
|
||||
targets?: Array<string>;
|
||||
escalationTable?: {[key: string]: Array<string>};
|
||||
}
|
||||
|
||||
export interface NonConfirmedNotificationEscalation {
|
||||
|
||||
@ -2805,7 +2805,9 @@
|
||||
"notify": "notify",
|
||||
"no-rule": "No rule configured",
|
||||
"device": "Device",
|
||||
"devices": "Devices",
|
||||
"device-profile": "Device profile",
|
||||
"device-profiles": "Device profiles",
|
||||
"filter-by": "Filter by",
|
||||
"entity-type": "Entity type",
|
||||
"created": "Created",
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user