Browse Source

UI: Improvement notification componets styles

pull/7911/head
Vladyslav_Prykhodko 4 years ago
parent
commit
82719b89ef
  1. 87
      ui-ngx/src/app/modules/home/pages/notification-center/notification-center.component.scss
  2. 1
      ui-ngx/src/app/modules/home/pages/notification-center/notification-center.module.ts
  3. 12
      ui-ngx/src/app/modules/home/pages/notification-center/notification-table/rule-table-config.ts
  4. 14
      ui-ngx/src/app/modules/home/pages/notification-center/notification-table/targets-table-config.ts
  5. 12
      ui-ngx/src/app/modules/home/pages/notification-center/notification-table/template-table-config.ts
  6. 18
      ui-ngx/src/app/modules/home/pages/notification-center/request-table/request-notification-dialog.component.html
  7. 46
      ui-ngx/src/app/modules/home/pages/notification-center/request-table/request-notification-dialog.component.scss
  8. 8
      ui-ngx/src/app/modules/home/pages/notification-center/request-table/request-notification-dialog.componet.ts
  9. 35
      ui-ngx/src/app/modules/home/pages/notification-center/rule-table/escalation-form.component.html
  10. 33
      ui-ngx/src/app/modules/home/pages/notification-center/rule-table/escalation-form.component.scss
  11. 11
      ui-ngx/src/app/modules/home/pages/notification-center/rule-table/rule-notification-dialog.component.html
  12. 33
      ui-ngx/src/app/modules/home/pages/notification-center/rule-table/rule-notification-dialog.component.scss
  13. 6
      ui-ngx/src/app/modules/home/pages/notification-center/targets-table/target-notification-dialog.component.html
  14. 21
      ui-ngx/src/app/modules/home/pages/notification-center/targets-table/target-notification-dialog.componet.scss
  15. 2
      ui-ngx/src/app/modules/home/pages/notification-center/targets-table/target-notification-dialog.componet.ts
  16. 2
      ui-ngx/src/app/modules/home/pages/notification-center/template-table/template-configuration.ts
  17. 19
      ui-ngx/src/app/modules/home/pages/notification-center/template-table/template-notification-dialog.component.html
  18. 45
      ui-ngx/src/app/modules/home/pages/notification-center/template-table/template-notification-dialog.component.scss
  19. 2
      ui-ngx/src/app/modules/home/pages/notification-center/template-table/template-notification-dialog.component.ts
  20. 1
      ui-ngx/src/app/shared/components/entity/entity-type-select.component.scss
  21. 4
      ui-ngx/src/app/shared/components/notification/notification.component.html
  22. 4
      ui-ngx/src/app/shared/models/notification.models.ts
  23. 2
      ui-ngx/src/assets/locale/locale.constant-en_US.json

87
ui-ngx/src/app/modules/home/pages/notification-center/notification-center.component.scss

@ -46,7 +46,7 @@
} }
.action-buttons { .action-buttons {
color: rgba(0,0,0,.54); color: rgba(0, 0, 0, .54);
} }
} }
@ -55,52 +55,9 @@
flex-direction: column; flex-direction: column;
flex: 1 1 100%; flex: 1 1 100%;
} }
//.mat-toolbar-tools{
// min-height: auto;
//}
//
//.title-container{
// overflow: hidden;
//}
//
//.tb-entity-table-title {
// padding-right: 20px;
// white-space: nowrap;
// overflow: hidden;
// text-overflow: ellipsis;
//}
//
//.table-container {
// overflow: auto;
//}
//
//.tb-entity-table-info{
// white-space: nowrap;
// overflow: hidden;
// text-overflow: ellipsis;
//}
//
//.button-widget-action{
// margin-left: auto;
// overflow: hidden;
// text-overflow: ellipsis;
//}
} }
} }
//@media #{$mat-xs} {
// .mat-toolbar {
// height: auto;
// min-height: 100px;
//
// .tb-entity-table-title{
// padding-bottom: 5px;
// width: 100%;
// }
// }
//}
@media #{$mat-xs} { @media #{$mat-xs} {
.tb-notification-center { .tb-notification-center {
.tb-notification-center-content { .tb-notification-center-content {
@ -158,32 +115,18 @@
} }
} }
} }
}
//:host ::ng-deep { @media #{$mat-xs} {
// .mat-sort-header-sorted .mat-sort-header-arrow { .tabs-container {
// opacity: 1 !important; .mat-tab-group {
// } > .mat-tab-header {
// tb-branch-autocomplete { .mat-tab-label {
// mat-form-field { &.mat-tab-disabled {
// font-size: 16px; width: auto;
// width: 250px; }
// }
// .mat-form-field-wrapper { }
// padding-bottom: 0; }
// } }
// }
// .mat-form-field-underline { }
// bottom: 0;
// }
//
// @media #{$mat-xs} {
// width: 100%;
//
// .mat-form-field-infix {
// width: auto !important;
// }
// }
// }
// }
//}

1
ui-ngx/src/app/modules/home/pages/notification-center/notification-center.module.ts

@ -51,6 +51,7 @@ import { EscalationFormComponent } from '@home/pages/notification-center/rule-ta
import { import {
AlarmSeveritiesListComponent AlarmSeveritiesListComponent
} from '@home/pages/notification-center/rule-table/alarm-severities-list.component'; } from '@home/pages/notification-center/rule-table/alarm-severities-list.component';
import { TemplateConfiguration } from '@home/pages/notification-center/template-table/template-configuration';
@NgModule({ @NgModule({
declarations: [ declarations: [

12
ui-ngx/src/app/modules/home/pages/notification-center/notification-table/rule-table-config.ts

@ -39,6 +39,8 @@ export class RuleTableConfig extends EntityTableConfig<NotificationRule> {
private dialog: MatDialog) { private dialog: MatDialog) {
super(); super();
this.loadDataOnInit = false; this.loadDataOnInit = false;
this.rowPointer = true;
this.entityTranslations = { this.entityTranslations = {
noEntities: 'notification.no-rules-notification', noEntities: 'notification.no-rules-notification',
search: 'notification.search-rules' search: 'notification.search-rules'
@ -57,6 +59,11 @@ export class RuleTableConfig extends EntityTableConfig<NotificationRule> {
this.defaultSortOrder = {property: 'name', direction: Direction.ASC}; this.defaultSortOrder = {property: 'name', direction: Direction.ASC};
this.handleRowClick = ($event, rule) => {
this.editRule($event, rule)
return true;
}
this.columns.push( this.columns.push(
new EntityTableColumn<NotificationRule>('name', 'notification.rule-name', '30%'), new EntityTableColumn<NotificationRule>('name', 'notification.rule-name', '30%'),
new EntityTableColumn<NotificationRule>('templateName', 'notification.template', '20%'), new EntityTableColumn<NotificationRule>('templateName', 'notification.template', '20%'),
@ -75,11 +82,6 @@ export class RuleTableConfig extends EntityTableConfig<NotificationRule> {
icon: 'content_copy', icon: 'content_copy',
isEnabled: () => true, isEnabled: () => true,
onAction: ($event, entity) => this.editRule($event, entity, false, true) onAction: ($event, entity) => this.editRule($event, entity, false, true)
}, {
name: this.translate.instant('notification.edit-rule'),
icon: 'edit',
isEnabled: () => true,
onAction: ($event, entity) => this.editRule($event, entity)
}]; }];
} }

14
ui-ngx/src/app/modules/home/pages/notification-center/notification-table/targets-table-config.ts

@ -41,6 +41,8 @@ export class TargetsTableConfig extends EntityTableConfig<NotificationTarget> {
private dialog: MatDialog) { private dialog: MatDialog) {
super(); super();
this.loadDataOnInit = false; this.loadDataOnInit = false;
this.rowPointer = true;
this.entityTranslations = { this.entityTranslations = {
noEntities: 'notification.no-targets-notification', noEntities: 'notification.no-targets-notification',
search: 'notification.search-targets' search: 'notification.search-targets'
@ -60,6 +62,11 @@ export class TargetsTableConfig extends EntityTableConfig<NotificationTarget> {
this.defaultSortOrder = {property: 'name', direction: Direction.ASC}; this.defaultSortOrder = {property: 'name', direction: Direction.ASC};
this.handleRowClick = ($event, target) => {
this.editTarget($event, target);
return true;
}
this.columns.push( this.columns.push(
new EntityTableColumn<NotificationTarget>('name', 'notification.notification-target', '20%'), new EntityTableColumn<NotificationTarget>('name', 'notification.notification-target', '20%'),
new EntityTableColumn<NotificationTarget>('configuration.type', 'notification.type', '40%', new EntityTableColumn<NotificationTarget>('configuration.type', 'notification.type', '40%',
@ -72,12 +79,7 @@ export class TargetsTableConfig extends EntityTableConfig<NotificationTarget> {
} }
private configureCellActions(): Array<CellActionDescriptor<NotificationTarget>> { private configureCellActions(): Array<CellActionDescriptor<NotificationTarget>> {
return [{ return [];
name: this.translate.instant('device.make-public'),
icon: 'edit',
isEnabled: () => true,
onAction: ($event, entity) => this.editTarget($event, entity)
}];
} }
private editTarget($event: Event, target: NotificationTarget, isAdd = false) { private editTarget($event: Event, target: NotificationTarget, isAdd = false) {

12
ui-ngx/src/app/modules/home/pages/notification-center/notification-table/template-table-config.ts

@ -41,6 +41,8 @@ export class TemplateTableConfig extends EntityTableConfig<NotificationTemplate>
private dialog: MatDialog) { private dialog: MatDialog) {
super(); super();
this.loadDataOnInit = false; this.loadDataOnInit = false;
this.rowPointer = true;
this.entityTranslations = { this.entityTranslations = {
noEntities: 'notification.no-notification-templates', noEntities: 'notification.no-notification-templates',
search: 'notification.search-templates' search: 'notification.search-templates'
@ -60,6 +62,11 @@ export class TemplateTableConfig extends EntityTableConfig<NotificationTemplate>
this.defaultSortOrder = {property: 'notificationType', direction: Direction.ASC}; this.defaultSortOrder = {property: 'notificationType', direction: Direction.ASC};
this.handleRowClick = ($event, template) => {
this.editTemplate($event, template)
return true;
}
this.columns.push( this.columns.push(
new EntityTableColumn<NotificationTemplate>('notificationType', 'notification.type', '15%', new EntityTableColumn<NotificationTemplate>('notificationType', 'notification.type', '15%',
(template) => this.translate.instant(NotificationTemplateTypeTranslateMap.get(template.notificationType).name)), (template) => this.translate.instant(NotificationTemplateTypeTranslateMap.get(template.notificationType).name)),
@ -78,11 +85,6 @@ export class TemplateTableConfig extends EntityTableConfig<NotificationTemplate>
icon: 'content_copy', icon: 'content_copy',
isEnabled: () => true, isEnabled: () => true,
onAction: ($event, entity) => this.editTemplate($event, entity, false, true) onAction: ($event, entity) => this.editTemplate($event, entity, false, true)
}, {
name: this.translate.instant('notification.edit-template'),
icon: 'edit',
isEnabled: () => true,
onAction: ($event, entity) => this.editTemplate($event, entity)
} }
]; ];
} }

18
ui-ngx/src/app/modules/home/pages/notification-center/request-table/request-notification-dialog.component.html

@ -55,19 +55,21 @@
<ng-template #scratchTemplate> <ng-template #scratchTemplate>
<section formGroupName="template"> <section formGroupName="template">
<section formGroupName="configuration"> <section formGroupName="configuration">
<mat-form-field class="mat-block"> <mat-form-field class="mat-block tb-form-fields">
<mat-label translate>notification.subject</mat-label> <mat-label translate>notification.subject</mat-label>
<input matInput formControlName="notificationSubject" required> <input matInput formControlName="notificationSubject" required>
<mat-error *ngIf="notificationRequestForm.get('template.configuration.notificationSubject').hasError('required')"> <mat-error *ngIf="notificationRequestForm.get('template.configuration.notificationSubject').hasError('required')">
{{ 'notification.subject-required' | translate }} {{ 'notification.subject-required' | translate }}
</mat-error> </mat-error>
<mat-hint>{{ notificationTemplateTypeTranslateMap.get(notificationType.GENERAL).hint | translate }}</mat-hint>
</mat-form-field> </mat-form-field>
<mat-form-field class="mat-block"> <mat-form-field class="mat-block tb-form-fields">
<mat-label translate>notification.message</mat-label> <mat-label translate>notification.message</mat-label>
<input matInput formControlName="defaultTextTemplate" required> <input matInput formControlName="defaultTextTemplate" required>
<mat-error *ngIf="notificationRequestForm.get('template.configuration.defaultTextTemplate').hasError('required')"> <mat-error *ngIf="notificationRequestForm.get('template.configuration.defaultTextTemplate').hasError('required')">
{{ 'notification.message-required' | translate }} {{ 'notification.message-required' | translate }}
</mat-error> </mat-error>
<mat-hint>{{ notificationTemplateTypeTranslateMap.get(notificationType.GENERAL).hint | translate }}</mat-hint>
</mat-form-field> </mat-form-field>
<label class="tb-title tb-required" <label class="tb-title tb-required"
[ngClass]="{'tb-error': notificationRequestForm.get('template.configuration.deliveryMethodsTemplates').hasError('atLeastOne')}"> [ngClass]="{'tb-error': notificationRequestForm.get('template.configuration.deliveryMethodsTemplates').hasError('atLeastOne')}">
@ -104,6 +106,9 @@
notificationRequestForm.get('template.configuration.deliveryMethodsTemplates.PUSH.enabled').value" notificationRequestForm.get('template.configuration.deliveryMethodsTemplates.PUSH.enabled').value"
[stepControl]="pushTemplateForm"> [stepControl]="pushTemplateForm">
<ng-template matStepLabel>{{ 'notification.web-settings' | translate }}</ng-template> <ng-template matStepLabel>{{ 'notification.web-settings' | translate }}</ng-template>
<div class="tb-hint tb-hint-available-params">
{{ notificationTemplateTypeTranslateMap.get(notificationType.GENERAL).hint | translate }}
</div>
<form [formGroup]="pushTemplateForm"> <form [formGroup]="pushTemplateForm">
<mat-form-field class="mat-block" floatLabel="always"> <mat-form-field class="mat-block" floatLabel="always">
<mat-label translate>notification.subject</mat-label> <mat-label translate>notification.subject</mat-label>
@ -164,6 +169,9 @@
[stepControl]="emailTemplateForm"> [stepControl]="emailTemplateForm">
<ng-template matStepLabel>{{ 'notification.email-settings' | translate }}</ng-template> <ng-template matStepLabel>{{ 'notification.email-settings' | translate }}</ng-template>
<ng-template matStepContent> <ng-template matStepContent>
<div class="tb-hint tb-hint-available-params">
{{ notificationTemplateTypeTranslateMap.get(notificationType.GENERAL).hint | translate }}
</div>
<form [formGroup]="emailTemplateForm"> <form [formGroup]="emailTemplateForm">
<mat-form-field class="mat-block" floatLabel="always"> <mat-form-field class="mat-block" floatLabel="always">
<mat-label translate>notification.subject</mat-label> <mat-label translate>notification.subject</mat-label>
@ -178,6 +186,9 @@
notificationRequestForm.get('template.configuration.deliveryMethodsTemplates.SMS.enabled').value" notificationRequestForm.get('template.configuration.deliveryMethodsTemplates.SMS.enabled').value"
[stepControl]="smsTemplateForm"> [stepControl]="smsTemplateForm">
<ng-template matStepLabel>{{ 'notification.sms-settings' | translate }}</ng-template> <ng-template matStepLabel>{{ 'notification.sms-settings' | translate }}</ng-template>
<div class="tb-hint tb-hint-available-params">
{{ notificationTemplateTypeTranslateMap.get(notificationType.GENERAL).hint | translate }}
</div>
<form [formGroup]="smsTemplateForm"> <form [formGroup]="smsTemplateForm">
<mat-form-field class="mat-block" floatLabel="always"> <mat-form-field class="mat-block" floatLabel="always">
<mat-label translate>notification.message</mat-label> <mat-label translate>notification.message</mat-label>
@ -195,6 +206,9 @@
notificationRequestForm.get('template.configuration.deliveryMethodsTemplates.SLACK.enabled').value" notificationRequestForm.get('template.configuration.deliveryMethodsTemplates.SLACK.enabled').value"
[stepControl]="slackTemplateForm"> [stepControl]="slackTemplateForm">
<ng-template matStepLabel>{{ 'notification.slack-settings' | translate }}</ng-template> <ng-template matStepLabel>{{ 'notification.slack-settings' | translate }}</ng-template>
<div class="tb-hint tb-hint-available-params">
{{ notificationTemplateTypeTranslateMap.get(notificationType.GENERAL).hint | translate }}
</div>
<form [formGroup]="slackTemplateForm" fxLayoutGap="8px"> <form [formGroup]="slackTemplateForm" fxLayoutGap="8px">
<mat-form-field class="mat-block" floatLabel="always"> <mat-form-field class="mat-block" floatLabel="always">
<mat-label translate>notification.message</mat-label> <mat-label translate>notification.message</mat-label>

46
ui-ngx/src/app/modules/home/pages/notification-center/request-table/request-notification-dialog.component.scss

@ -18,6 +18,21 @@
:host-context(.tb-fullscreen-dialog .mat-dialog-container) { :host-context(.tb-fullscreen-dialog .mat-dialog-container) {
width: 640px; width: 640px;
max-height: 100vh;
.tb-form-fields {
margin-bottom: 8px;
}
.tb-hint-available-params {
border-radius: 6px;
background-color: rgba(48, 86, 128, 0.04);
line-height: 16px;
letter-spacing: 0.25px;
margin-bottom: 8px;
padding: 8px 12px;
color: rgba(0, 0, 0, 0.54);
}
.delivery-method-container { .delivery-method-container {
padding-bottom: 8px; padding-bottom: 8px;
@ -117,9 +132,13 @@
.mat-stepper-horizontal { .mat-stepper-horizontal {
display: flex; display: flex;
flex-direction: column;
height: 100%; height: 100%;
overflow: hidden; overflow: hidden;
.mat-horizontal-stepper-wrapper {
flex: 1 1 100%;
}
@media #{$mat-lt-sm} { @media #{$mat-lt-sm} {
.mat-step-label { .mat-step-label {
white-space: normal; white-space: normal;
@ -130,7 +149,7 @@
} }
} }
.mat-horizontal-content-container { .mat-horizontal-content-container {
height: 400px; height: 540px;
max-height: 100%; max-height: 100%;
width: 100%;; width: 100%;;
overflow-y: auto; overflow-y: auto;
@ -150,6 +169,7 @@
&.mat-button-toggle-group-appearance-standard { &.mat-button-toggle-group-appearance-standard {
border: none; border: none;
border-radius: 18px; border-radius: 18px;
margin-bottom: 8px;
.mat-button-toggle + .mat-button-toggle { .mat-button-toggle + .mat-button-toggle {
border-left: none; border-left: none;
@ -198,4 +218,26 @@
opacity: .01; opacity: .01;
} }
} }
.mat-form-field {
.mat-form-field-wrapper {
padding-bottom: 0px;
.mat-form-field-underline {
position: initial !important;
display: block;
margin-top: -1px;
}
.mat-form-field-subscript-wrapper,
.mat-form-field-ripple {
position: initial !important;
display: table;
}
.mat-form-field-subscript-wrapper {
min-height: calc(1em + 1px);
}
}
}
} }

8
ui-ngx/src/app/modules/home/pages/notification-center/request-table/request-notification-dialog.componet.ts

@ -146,8 +146,12 @@ export class RequestNotificationDialogComponent extends
} }
nextStepLabel(): string { nextStepLabel(): string {
if (this.selectedIndex >= this.maxStepperIndex) { if (this.selectedIndex !== 0) {
return 'action.send'; if (this.selectedIndex >= this.maxStepperIndex) {
return 'action.send';
} else if (this.createNotification.selected.stepControl.pristine) {
return 'action.skip';
}
} }
return 'action.next'; return 'action.next';
} }

35
ui-ngx/src/app/modules/home/pages/notification-center/rule-table/escalation-form.component.html

@ -17,14 +17,12 @@
--> -->
<form [formGroup]="escalationFormGroup" fxLayout="column"> <form [formGroup]="escalationFormGroup" fxLayout="column">
<div class="escalation" fxLayout="row" fxLayout.xs="column" fxLayoutAlign="center center" fxLayoutAlign.xs="start"> <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 fxLayout="row" ngStyle.xs="padding-top: 10px">-->
<div fxFlex *ngIf="systemEscalation; else selectTime" class="escalation-padding" translate>notification.first-recipient</div> <div fxFlex *ngIf="systemEscalation; else selectTime" translate>notification.first-recipient</div>
<ng-template #selectTime> <ng-template #selectTime>
<div fxFlex fxLayout="row" fxLayout.xs="column" fxLayoutAlign="center center"> <div fxFlex fxLayout="row" fxLayout.xs="column" fxLayoutAlign="center center">
<span class="escalation-padding">After</span> <span translate>notification.after</span>
<tb-timeinterval <tb-timeinterval
style="min-width: 100px;"
ngStyle.xs="padding: 0 10px;"
formControlName="delayInSec" formControlName="delayInSec"
min="{{ 0 }}" min="{{ 0 }}"
max="{{ 604800000 }}" max="{{ 604800000 }}"
@ -32,19 +30,18 @@
<span fxFlex class="escalation-notify" translate>notification.notify</span> <span fxFlex class="escalation-notify" translate>notification.notify</span>
</div> </div>
</ng-template> </ng-template>
</div> <!-- </div>-->
<div fxFlex="60" class="escalation-padding"> <tb-entity-list
<tb-entity-list required
required fxFlex="60"
formControlName="targets" formControlName="targets"
[entityType]="entityType.NOTIFICATION_TARGET" [entityType]="entityType.NOTIFICATION_TARGET"
placeholderText="{{ 'notification.add-target' | translate }}"> placeholderText="{{ 'notification.add-target' | translate }}">
<button #createTargetButton <button #createTargetButton
mat-button [fxHide]="disabled" matSuffix mat-button [fxHide]="disabled" matSuffix
(click)="createTarget($event, createTargetButton)"> (click)="createTarget($event, createTargetButton)">
{{ 'notification.create-new' | translate }} {{ 'notification.create-new' | translate }}
</button> </button>
</tb-entity-list> </tb-entity-list>
</div>
</div> </div>
</form> </form>

33
ui-ngx/src/app/modules/home/pages/notification-center/rule-table/escalation-form.component.scss

@ -13,6 +13,8 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
@import "../../../../../../scss/constants";
:host { :host {
.escalation { .escalation {
height: 100%; height: 100%;
@ -20,24 +22,45 @@
max-height: 100%; max-height: 100%;
border-radius: 8px; border-radius: 8px;
background: rgba(0,0,0,0.04); background: rgba(0,0,0,0.04);
}
.escalation-padding {
padding: 0 10px; padding: 0 10px;
> div:first-child {
padding-right: 10px;
}
} }
.escalation-notify { .escalation-notify {
text-align: end; text-align: center;
}
tb-timeinterval {
min-width: 100px;
padding: 0 10px; padding: 0 10px;
} }
@media #{$mat-xs} {
.escalation {
> div:first-child {
padding: 10px 0 0;
}
}
tb-timeinterval {
padding: 0;
}
}
} }
:host ::ng-deep { :host ::ng-deep {
tb-timeinterval { .mat-form-field {
min-width: 100px; min-width: 100px;
.mat-form-field-infix { .mat-form-field-infix {
width: 100%; width: 100%;
} }
.mat-select {
min-width: 110px !important;
}
} }
} }

11
ui-ngx/src/app/modules/home/pages/notification-center/rule-table/rule-notification-dialog.component.html

@ -35,7 +35,7 @@
</ng-template> </ng-template>
<mat-step [stepControl]="ruleNotificationForm"> <mat-step [stepControl]="ruleNotificationForm">
<ng-template matStepLabel>{{ 'notification.basic-settings' | translate }}</ng-template> <ng-template matStepLabel>{{ 'notification.basic-settings' | translate }}</ng-template>
<form [formGroup]="ruleNotificationForm" style="padding-bottom: 16px;"> <form [formGroup]="ruleNotificationForm">
<mat-form-field class="mat-block"> <mat-form-field class="mat-block">
<mat-label translate>notification.rule-name</mat-label> <mat-label translate>notification.rule-name</mat-label>
<input matInput formControlName="name" required> <input matInput formControlName="name" required>
@ -75,7 +75,7 @@
</tb-entity-list> </tb-entity-list>
</section> </section>
<ng-template #alarmTargesConfig> <ng-template #alarmTargesConfig>
<fieldset class="fields-group" formGroupName="recipientsConfig"> <fieldset class="fields-group tb-hierarchy" formGroupName="recipientsConfig">
<legend translate>notification.hierarchy-of-receiving</legend> <legend translate>notification.hierarchy-of-receiving</legend>
<tb-escalations-component formControlName="escalationTable"></tb-escalations-component> <tb-escalations-component formControlName="escalationTable"></tb-escalations-component>
</fieldset> </fieldset>
@ -87,7 +87,7 @@
<ng-template matStepLabel>{{ 'notification.alarm-trigger-settings' | translate }}</ng-template> <ng-template matStepLabel>{{ 'notification.alarm-trigger-settings' | translate }}</ng-template>
<form [formGroup]="alarmTemplateForm"> <form [formGroup]="alarmTemplateForm">
<section formGroupName="triggerConfig"> <section formGroupName="triggerConfig">
<fieldset class="fields-group"> <fieldset class="fields-group tb-margin">
<legend translate>notification.filter</legend> <legend translate>notification.filter</legend>
<tb-string-items-list <tb-string-items-list
label="{{ 'alarm.alarm-type-list' | translate }}" label="{{ 'alarm.alarm-type-list' | translate }}"
@ -102,7 +102,7 @@
</tb-alarm-severities-list> </tb-alarm-severities-list>
</fieldset> </fieldset>
<fieldset class="fields-group" formGroupName="clearRule"> <fieldset class="fields-group tb-margin" formGroupName="clearRule">
<legend translate>notification.clear-rule</legend> <legend translate>notification.clear-rule</legend>
<mat-form-field fxFlex class="mat-block" floatLabel="always"> <mat-form-field fxFlex class="mat-block" floatLabel="always">
<mat-label translate>alarm.alarm-status-list</mat-label> <mat-label translate>alarm.alarm-status-list</mat-label>
@ -132,7 +132,6 @@
<ng-template matStepLabel>{{ 'notification.device-inactivity-trigger-settings' | translate }}</ng-template> <ng-template matStepLabel>{{ 'notification.device-inactivity-trigger-settings' | translate }}</ng-template>
<form [formGroup]="deviceInactivityTemplateForm"> <form [formGroup]="deviceInactivityTemplateForm">
<section formGroupName="triggerConfig"> <section formGroupName="triggerConfig">
<span translate>notification.filter-by</span>
<div fxFlex fxLayoutAlign="center center"> <div fxFlex fxLayoutAlign="center center">
<mat-button-toggle-group class="tb-notification-unread-toggle-group" <mat-button-toggle-group class="tb-notification-unread-toggle-group"
style="width: 250px;" style="width: 250px;"
@ -175,7 +174,7 @@
[stepControl]="entityActionTemplateForm"> [stepControl]="entityActionTemplateForm">
<ng-template matStepLabel>{{ 'notification.entity-action-trigger-settings' | translate }}</ng-template> <ng-template matStepLabel>{{ 'notification.entity-action-trigger-settings' | translate }}</ng-template>
<form [formGroup]="entityActionTemplateForm"> <form [formGroup]="entityActionTemplateForm">
<fieldset class="fields-group" formGroupName="triggerConfig"> <fieldset class="fields-group tb-margin" formGroupName="triggerConfig">
<legend translate>notification.filter</legend> <legend translate>notification.filter</legend>
<tb-entity-type-select required <tb-entity-type-select required
showLabel showLabel

33
ui-ngx/src/app/modules/home/pages/notification-center/rule-table/rule-notification-dialog.component.scss

@ -16,7 +16,8 @@
@import "../../../../../../theme"; @import "../../../../../../theme";
:host { :host {
width: 800px; width: 700px;
max-height: 100vh;
@media #{$mat-gt-xs} { @media #{$mat-gt-xs} {
.mat-dialog-content { .mat-dialog-content {
@ -31,10 +32,17 @@
.fields-group { .fields-group {
padding: 0 16px 8px; padding: 0 16px 8px;
margin-bottom: 10px;
border: 1px groove rgba(0, 0, 0, .25); border: 1px groove rgba(0, 0, 0, .25);
border-radius: 4px; border-radius: 4px;
&.tb-margin {
margin-bottom: 10px;
}
&.tb-hierarchy {
padding: 0 0 8px 16px;
}
legend { legend {
margin-bottom: 8px; margin-bottom: 8px;
color: rgba(0, 0, 0, .7); color: rgba(0, 0, 0, .7);
@ -52,9 +60,13 @@
.mat-stepper-horizontal { .mat-stepper-horizontal {
display: flex; display: flex;
flex-direction: column;
height: 100%; height: 100%;
overflow: hidden; overflow: hidden;
.mat-horizontal-stepper-wrapper {
flex: 1 1 100%;
}
@media #{$mat-lt-sm} { @media #{$mat-lt-sm} {
.mat-step-label { .mat-step-label {
white-space: normal; white-space: normal;
@ -67,7 +79,7 @@
} }
.mat-horizontal-content-container { .mat-horizontal-content-container {
height: 600px; height: 550px;
max-height: 100%; max-height: 100%;
width: 100%;; width: 100%;;
overflow-y: auto; overflow-y: auto;
@ -87,7 +99,8 @@
.mat-button-toggle-group.tb-notification-unread-toggle-group { .mat-button-toggle-group.tb-notification-unread-toggle-group {
&.mat-button-toggle-group-appearance-standard { &.mat-button-toggle-group-appearance-standard {
border: none; border: none;
border-radius: 14px; border-radius: 18px;
margin-bottom: 8px;
.mat-button-toggle + .mat-button-toggle { .mat-button-toggle + .mat-button-toggle {
border-left: none; border-left: none;
@ -96,7 +109,7 @@
.mat-button-toggle { .mat-button-toggle {
background: rgba(0, 0, 0, 0.06); background: rgba(0, 0, 0, 0.06);
height: 28px; height: 36px;
align-items: center; align-items: center;
display: flex; display: flex;
@ -105,7 +118,7 @@
left: 2px; left: 2px;
right: 2px; right: 2px;
bottom: 2px; bottom: 2px;
border-radius: 12px; border-radius: 18px;
} }
} }
@ -114,20 +127,20 @@
} }
.mat-button-toggle-focus-overlay { .mat-button-toggle-focus-overlay {
border-radius: 14px; border-radius: 18px;
margin: 2px; margin: 2px;
} }
.mat-button-toggle-checked .mat-button-toggle-button { .mat-button-toggle-checked .mat-button-toggle-button {
background-color: $tb-primary-color; background-color: $tb-primary-color;
color: #fff; color: #fff;
border-radius: 14px; border-radius: 18px;
margin-left: 2px; margin-left: 2px;
margin-right: 2px; margin-right: 2px;
} }
.mat-button-toggle-appearance-standard .mat-button-toggle-label-content { .mat-button-toggle-appearance-standard .mat-button-toggle-label-content {
line-height: 24px; line-height: 34px;
font-size: 16px; font-size: 16px;
font-weight: 500; font-weight: 500;
} }

6
ui-ngx/src/app/modules/home/pages/notification-center/targets-table/target-notification-dialog.component.html

@ -15,7 +15,7 @@
limitations under the License. limitations under the License.
--> -->
<form [formGroup]="targetNotificationForm" style="min-width: 560px"> <form [formGroup]="targetNotificationForm" class="tb-dialog-container">
<mat-toolbar color="primary"> <mat-toolbar color="primary">
<h2>{{ (isAdd ? 'notification.add-notification-target' : 'notification.edit-notification-target') | translate }}</h2> <h2>{{ (isAdd ? 'notification.add-notification-target' : 'notification.edit-notification-target') | translate }}</h2>
<span fxFlex></span> <span fxFlex></span>
@ -77,9 +77,7 @@
<label class="tb-title">{{ 'notification.recipient-type' | translate }}</label> <label class="tb-title">{{ 'notification.recipient-type' | translate }}</label>
<mat-radio-group formControlName="conversationType"> <mat-radio-group formControlName="conversationType">
<mat-radio-button *ngFor="let slackChanelType of slackChanelTypes" [value]="slackChanelType"> <mat-radio-button *ngFor="let slackChanelType of slackChanelTypes" [value]="slackChanelType">
<div fxLayout="column"> {{ slackChanelTypesTranslateMap.get(slackChanelType) | translate }}
<div>{{ slackChanelTypesTranslateMap.get(slackChanelType) | translate }}</div>
</div>
</mat-radio-button> </mat-radio-button>
</mat-radio-group> </mat-radio-group>
<tb-slack-conversation-autocomplete <tb-slack-conversation-autocomplete

21
ui-ngx/src/app/modules/home/pages/notification-center/targets-table/target-notification-dialog.componet.scss

@ -13,9 +13,19 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
@import "../../../../../../scss/constants";
@import "../../../../../../theme"; @import "../../../../../../theme";
:host { :host {
form.tb-dialog-container {
min-width: 580px;
max-height: 100vh;
}
.mat-dialog-content {
height: 85%;
}
.tb-title { .tb-title {
display: block; display: block;
padding-bottom: 6px; padding-bottom: 6px;
@ -27,6 +37,7 @@
display: flex; display: flex;
flex-direction: row; flex-direction: row;
margin-bottom: 14px; margin-bottom: 14px;
gap: 8px;
.mat-radio-button { .mat-radio-button {
flex: 1 1 100%; flex: 1 1 100%;
@ -34,13 +45,15 @@
border: 1px solid rgba(0, 0, 0, 0.12); border: 1px solid rgba(0, 0, 0, 0.12);
border-radius: 6px; border-radius: 6px;
&:not(:last-child){
margin-right: 8px;
}
&.mat-radio-checked { &.mat-radio-checked {
border-color: map_get($tb-accent, 500); border-color: map_get($tb-accent, 500);
} }
} }
} }
@media #{$mat-xs} {
.mat-radio-group {
flex-direction: column;
}
}
} }

2
ui-ngx/src/app/modules/home/pages/notification-center/targets-table/target-notification-dialog.componet.ts

@ -85,7 +85,7 @@ export class TargetNotificationDialogComponent extends
usersIds: [{value: null, disabled: true}, Validators.required], usersIds: [{value: null, disabled: true}, Validators.required],
customerId: [{value: null, disabled: true}, Validators.required] customerId: [{value: null, disabled: true}, Validators.required]
}), }),
conversationType: [{value: SlackChanelType.DIRECT, disabled: true}], conversationType: [{value: SlackChanelType.PUBLIC_CHANNEL, disabled: true}],
conversation: [{value: '', disabled: true}, Validators.required], conversation: [{value: '', disabled: true}, Validators.required],
description: [null] description: [null]
}) })

2
ui-ngx/src/app/modules/home/pages/notification-center/template-table/template-configuration.ts

@ -19,6 +19,7 @@ import {
NotificationDeliveryMethod, NotificationDeliveryMethod,
NotificationDeliveryMethodTranslateMap, NotificationDeliveryMethodTranslateMap,
NotificationTemplate, NotificationTemplate,
NotificationTemplateTypeTranslateMap,
NotificationType NotificationType
} from '@shared/models/notification.models'; } from '@shared/models/notification.models';
import { takeUntil } from 'rxjs/operators'; import { takeUntil } from 'rxjs/operators';
@ -42,6 +43,7 @@ export abstract class TemplateConfiguration<T, R = any> extends DialogComponent<
notificationDeliveryMethods = Object.keys(NotificationDeliveryMethod) as NotificationDeliveryMethod[]; notificationDeliveryMethods = Object.keys(NotificationDeliveryMethod) as NotificationDeliveryMethod[];
notificationDeliveryMethodTranslateMap = NotificationDeliveryMethodTranslateMap; notificationDeliveryMethodTranslateMap = NotificationDeliveryMethodTranslateMap;
notificationTemplateTypeTranslateMap = NotificationTemplateTypeTranslateMap;
tinyMceOptions: Record<string, any> = { tinyMceOptions: Record<string, any> = {
base_url: '/assets/tinymce', base_url: '/assets/tinymce',

19
ui-ngx/src/app/modules/home/pages/notification-center/template-table/template-notification-dialog.component.html

@ -50,22 +50,23 @@
{{ notificationTemplateTypeTranslateMap.get(notificationType).name | translate }} {{ notificationTemplateTypeTranslateMap.get(notificationType).name | translate }}
</mat-option> </mat-option>
</mat-select> </mat-select>
<mat-hint>{{ notificationTemplateTypeTranslateMap.get(templateNotificationForm.get('notificationType').value).hint | translate }}</mat-hint>
</mat-form-field> </mat-form-field>
<section formGroupName="configuration"> <section formGroupName="configuration">
<mat-form-field class="mat-block"> <mat-form-field class="mat-block tb-form-fields">
<mat-label translate>notification.subject</mat-label> <mat-label translate>notification.subject</mat-label>
<input matInput formControlName="notificationSubject" required> <input matInput formControlName="notificationSubject" required>
<mat-error *ngIf="templateNotificationForm.get('configuration.notificationSubject').hasError('required')"> <mat-error *ngIf="templateNotificationForm.get('configuration.notificationSubject').hasError('required')">
{{ 'notification.subject-required' | translate }} {{ 'notification.subject-required' | translate }}
</mat-error> </mat-error>
<mat-hint>{{ notificationTemplateTypeTranslateMap.get(templateNotificationForm.get('notificationType').value).hint | translate }}</mat-hint>
</mat-form-field> </mat-form-field>
<mat-form-field class="mat-block"> <mat-form-field class="mat-block tb-form-fields">
<mat-label translate>notification.message</mat-label> <mat-label translate>notification.message</mat-label>
<input matInput formControlName="defaultTextTemplate" required> <input matInput formControlName="defaultTextTemplate" required>
<mat-error *ngIf="templateNotificationForm.get('configuration.defaultTextTemplate').hasError('required')"> <mat-error *ngIf="templateNotificationForm.get('configuration.defaultTextTemplate').hasError('required')">
{{ 'notification.message-required' | translate }} {{ 'notification.message-required' | translate }}
</mat-error> </mat-error>
<mat-hint>{{ notificationTemplateTypeTranslateMap.get(templateNotificationForm.get('notificationType').value).hint | translate }}</mat-hint>
</mat-form-field> </mat-form-field>
<label class="tb-title tb-required" <label class="tb-title tb-required"
[ngClass]="{'tb-error': templateNotificationForm.get('configuration.deliveryMethodsTemplates').hasError('atLeastOne')}"> [ngClass]="{'tb-error': templateNotificationForm.get('configuration.deliveryMethodsTemplates').hasError('atLeastOne')}">
@ -86,6 +87,9 @@
<mat-step optional *ngIf="templateNotificationForm.get('configuration.deliveryMethodsTemplates.PUSH.enabled').value" <mat-step optional *ngIf="templateNotificationForm.get('configuration.deliveryMethodsTemplates.PUSH.enabled').value"
[stepControl]="pushTemplateForm"> [stepControl]="pushTemplateForm">
<ng-template matStepLabel>{{ 'notification.web-settings' | translate }}</ng-template> <ng-template matStepLabel>{{ 'notification.web-settings' | translate }}</ng-template>
<div class="tb-hint tb-hint-available-params">
{{ notificationTemplateTypeTranslateMap.get(templateNotificationForm.get('notificationType').value).hint | translate }}
</div>
<form [formGroup]="pushTemplateForm"> <form [formGroup]="pushTemplateForm">
<mat-form-field class="mat-block" floatLabel="always"> <mat-form-field class="mat-block" floatLabel="always">
<mat-label translate>notification.subject</mat-label> <mat-label translate>notification.subject</mat-label>
@ -145,6 +149,9 @@
[stepControl]="emailTemplateForm"> [stepControl]="emailTemplateForm">
<ng-template matStepLabel>{{ 'notification.email-settings' | translate }}</ng-template> <ng-template matStepLabel>{{ 'notification.email-settings' | translate }}</ng-template>
<ng-template matStepContent> <ng-template matStepContent>
<div class="tb-hint tb-hint-available-params">
{{ notificationTemplateTypeTranslateMap.get(templateNotificationForm.get('notificationType').value).hint | translate }}
</div>
<form [formGroup]="emailTemplateForm"> <form [formGroup]="emailTemplateForm">
<mat-form-field class="mat-block" floatLabel="always"> <mat-form-field class="mat-block" floatLabel="always">
<mat-label translate>notification.subject</mat-label> <mat-label translate>notification.subject</mat-label>
@ -158,6 +165,9 @@
<mat-step optional *ngIf="templateNotificationForm.get('configuration.deliveryMethodsTemplates.SMS.enabled').value" <mat-step optional *ngIf="templateNotificationForm.get('configuration.deliveryMethodsTemplates.SMS.enabled').value"
[stepControl]="smsTemplateForm"> [stepControl]="smsTemplateForm">
<ng-template matStepLabel>{{ 'notification.sms-settings' | translate }}</ng-template> <ng-template matStepLabel>{{ 'notification.sms-settings' | translate }}</ng-template>
<div class="tb-hint tb-hint-available-params">
{{ notificationTemplateTypeTranslateMap.get(templateNotificationForm.get('notificationType').value).hint | translate }}
</div>
<form [formGroup]="smsTemplateForm"> <form [formGroup]="smsTemplateForm">
<mat-form-field class="mat-block" floatLabel="always"> <mat-form-field class="mat-block" floatLabel="always">
<mat-label translate>notification.message</mat-label> <mat-label translate>notification.message</mat-label>
@ -174,6 +184,9 @@
<mat-step optional *ngIf="templateNotificationForm.get('configuration.deliveryMethodsTemplates.SLACK.enabled').value" <mat-step optional *ngIf="templateNotificationForm.get('configuration.deliveryMethodsTemplates.SLACK.enabled').value"
[stepControl]="slackTemplateForm"> [stepControl]="slackTemplateForm">
<ng-template matStepLabel>{{ 'notification.slack-settings' | translate }}</ng-template> <ng-template matStepLabel>{{ 'notification.slack-settings' | translate }}</ng-template>
<div class="tb-hint tb-hint-available-params">
{{ notificationTemplateTypeTranslateMap.get(templateNotificationForm.get('notificationType').value).hint | translate }}
</div>
<form [formGroup]="slackTemplateForm" fxLayoutGap="8px"> <form [formGroup]="slackTemplateForm" fxLayoutGap="8px">
<mat-form-field class="mat-block" floatLabel="always"> <mat-form-field class="mat-block" floatLabel="always">
<mat-label translate>notification.message</mat-label> <mat-label translate>notification.message</mat-label>

45
ui-ngx/src/app/modules/home/pages/notification-center/template-table/template-notification-dialog.component.scss

@ -18,11 +18,26 @@
:host-context(.tb-fullscreen-dialog .mat-dialog-container) { :host-context(.tb-fullscreen-dialog .mat-dialog-container) {
width: 720px; width: 720px;
max-height: 100vh;
.tb-form-fields {
margin-bottom: 8px;
}
.tb-hint { .tb-hint {
padding: 0; padding: 0;
} }
.tb-hint-available-params {
border-radius: 6px;
background-color: rgba(48, 86, 128, 0.04);
line-height: 16px;
letter-spacing: 0.25px;
margin-bottom: 8px;
padding: 8px 12px;
color: rgba(0, 0, 0, 0.54);
}
.delivery-method-container { .delivery-method-container {
padding-bottom: 8px; padding-bottom: 8px;
@ -68,9 +83,13 @@
.mat-stepper-horizontal { .mat-stepper-horizontal {
display: flex; display: flex;
flex-direction: column;
height: 100%; height: 100%;
overflow: hidden; overflow: hidden;
.mat-horizontal-stepper-wrapper {
flex: 1 1 100%;
}
@media #{$mat-lt-sm} { @media #{$mat-lt-sm} {
.mat-step-label { .mat-step-label {
white-space: normal; white-space: normal;
@ -81,7 +100,7 @@
} }
} }
.mat-horizontal-content-container { .mat-horizontal-content-container {
height: 600px; height: 550px;
max-height: 100%; max-height: 100%;
width: 100%;; width: 100%;;
overflow-y: auto; overflow-y: auto;
@ -122,4 +141,26 @@
} }
} }
} }
.mat-form-field {
.mat-form-field-wrapper {
padding-bottom: 0px;
.mat-form-field-underline {
position: initial !important;
display: block;
margin-top: -1px;
}
.mat-form-field-subscript-wrapper,
.mat-form-field-ripple {
position: initial !important;
display: table;
}
.mat-form-field-subscript-wrapper {
min-height: calc(1em + 1px);
}
}
}
} }

2
ui-ngx/src/app/modules/home/pages/notification-center/template-table/template-notification-dialog.component.ts

@ -18,7 +18,6 @@ import {
NotificationDeliveryMethod, NotificationDeliveryMethod,
NotificationDeliveryMethodTranslateMap, NotificationDeliveryMethodTranslateMap,
NotificationTemplate, NotificationTemplate,
NotificationTemplateTypeTranslateMap,
NotificationType NotificationType
} from '@shared/models/notification.models'; } from '@shared/models/notification.models';
import { Component, Inject, OnDestroy, ViewChild } from '@angular/core'; import { Component, Inject, OnDestroy, ViewChild } from '@angular/core';
@ -66,7 +65,6 @@ export class TemplateNotificationDialogComponent
notificationTypes = Object.keys(NotificationType) as NotificationType[]; notificationTypes = Object.keys(NotificationType) as NotificationType[];
notificationDeliveryMethods = Object.keys(NotificationDeliveryMethod) as NotificationDeliveryMethod[]; notificationDeliveryMethods = Object.keys(NotificationDeliveryMethod) as NotificationDeliveryMethod[];
notificationTemplateTypeTranslateMap = NotificationTemplateTypeTranslateMap;
notificationDeliveryMethodTranslateMap = NotificationDeliveryMethodTranslateMap; notificationDeliveryMethodTranslateMap = NotificationDeliveryMethodTranslateMap;
selectedIndex = 0; selectedIndex = 0;

1
ui-ngx/src/app/shared/components/entity/entity-type-select.component.scss

@ -24,7 +24,6 @@
width: 100%; width: 100%;
} }
.mat-select-value { .mat-select-value {
max-width: 200px;
min-width: 100px; min-width: 100px;
} }
} }

4
ui-ngx/src/app/shared/components/notification/notification.component.html

@ -28,8 +28,8 @@
</mat-icon> </mat-icon>
</ng-template> </ng-template>
<div class="content" fxFlex> <div class="content" fxFlex>
<div class="title">{{ notification.subject }}</div> <div class="title" [innerHTML]="(notification.subject | safe: 'html' )"></div>
<div class="message">{{ notification.text }}</div> <div class="message" [innerHTML]="(notification.text | safe: 'html' )"></div>
<button *ngIf="showButton" mat-stroked-button class="button" <button *ngIf="showButton" mat-stroked-button class="button"
[ngStyle]="{color: notification.additionalConfig.actionButtonConfig.color}" [ngStyle]="{color: notification.additionalConfig.actionButtonConfig.color}"
(click)="navigate($event)"> (click)="navigate($event)">

4
ui-ngx/src/app/shared/models/notification.models.ts

@ -250,9 +250,9 @@ export const NotificationRequestStatusTranslateMap = new Map<NotificationRequest
]); ]);
export enum SlackChanelType { export enum SlackChanelType {
DIRECT= 'DIRECT',
PUBLIC_CHANNEL = 'PUBLIC_CHANNEL', PUBLIC_CHANNEL = 'PUBLIC_CHANNEL',
PRIVATE_CHANNEL = 'PRIVATE_CHANNEL' PRIVATE_CHANNEL = 'PRIVATE_CHANNEL',
DIRECT= 'DIRECT'
} }
export const SlackChanelTypesTranslateMap = new Map<SlackChanelType, string>([ export const SlackChanelTypesTranslateMap = new Map<SlackChanelType, string>([

2
ui-ngx/src/assets/locale/locale.constant-en_US.json

@ -2695,6 +2695,7 @@
"add-rule": "Add rule", "add-rule": "Add rule",
"add-target": "Add recipient", "add-target": "Add recipient",
"add-template": "Add template", "add-template": "Add template",
"after": "After",
"alarm-comment-trigger-settings": "Alarm comment trigger settings", "alarm-comment-trigger-settings": "Alarm comment trigger settings",
"alarm-trigger-settings": "Alarm trigger settings", "alarm-trigger-settings": "Alarm trigger settings",
"all": "All", "all": "All",
@ -2746,7 +2747,6 @@
"entity-action-trigger-settings": "Entity action trigger settings", "entity-action-trigger-settings": "Entity action trigger settings",
"entity-type": "Entity type", "entity-type": "Entity type",
"filter": "Filter", "filter": "Filter",
"filter-by": "Filter by",
"first-recipient": "First recipient", "first-recipient": "First recipient",
"hierarchy-of-receiving": "Hierarchy of receiving notifications", "hierarchy-of-receiving": "Hierarchy of receiving notifications",
"inbox": "Inbox", "inbox": "Inbox",

Loading…
Cancel
Save