Browse Source

UI: Fixed notification system after update Angular15

pull/7911/head
Vladyslav_Prykhodko 4 years ago
parent
commit
571574f0f8
  1. 83
      ui-ngx/src/app/modules/home/pages/notification-center/notification-center.component.html
  2. 57
      ui-ngx/src/app/modules/home/pages/notification-center/notification-center.component.scss
  3. 21
      ui-ngx/src/app/modules/home/pages/notification-center/notification-center.component.ts
  4. 21
      ui-ngx/src/app/modules/home/pages/notification-center/request-table/request-notification-dialog.component.html
  5. 55
      ui-ngx/src/app/modules/home/pages/notification-center/request-table/request-notification-dialog.component.scss
  6. 2
      ui-ngx/src/app/modules/home/pages/notification-center/request-table/request-notification-dialog.componet.ts
  7. 2
      ui-ngx/src/app/modules/home/pages/notification-center/rule-table/alarm-severities-list.component.html
  8. 16
      ui-ngx/src/app/modules/home/pages/notification-center/rule-table/alarm-severities-list.component.ts
  9. 30
      ui-ngx/src/app/modules/home/pages/notification-center/rule-table/escalation-form.component.html
  10. 6
      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. 28
      ui-ngx/src/app/modules/home/pages/notification-center/rule-table/rule-notification-dialog.component.scss
  13. 2
      ui-ngx/src/app/modules/home/pages/notification-center/rule-table/rule-notification-dialog.component.ts
  14. 10
      ui-ngx/src/app/modules/home/pages/notification-center/targets-table/target-notification-dialog.componet.scss
  15. 19
      ui-ngx/src/app/modules/home/pages/notification-center/targets-table/target-notification-dialog.componet.ts
  16. 10
      ui-ngx/src/app/modules/home/pages/notification-center/template-table/template-autocomplete.component.html
  17. 33
      ui-ngx/src/app/modules/home/pages/notification-center/template-table/template-autocomplete.component.scss
  18. 3
      ui-ngx/src/app/modules/home/pages/notification-center/template-table/template-autocomplete.component.ts
  19. 19
      ui-ngx/src/app/modules/home/pages/notification-center/template-table/template-configuration.ts
  20. 17
      ui-ngx/src/app/modules/home/pages/notification-center/template-table/template-notification-dialog.component.html
  21. 75
      ui-ngx/src/app/modules/home/pages/notification-center/template-table/template-notification-dialog.component.scss
  22. 23
      ui-ngx/src/app/modules/home/pages/notification-center/template-table/template-notification-dialog.component.ts
  23. 6
      ui-ngx/src/app/shared/components/entity/entity-list.component.html
  24. 7
      ui-ngx/src/app/shared/components/entity/entity-list.component.ts
  25. 6
      ui-ngx/src/app/shared/components/time/timeinterval.component.html
  26. 4
      ui-ngx/src/app/shared/components/time/timeinterval.component.scss
  27. 4
      ui-ngx/src/app/shared/components/time/timeinterval.component.ts
  28. 2
      ui-ngx/src/assets/locale/locale.constant-en_US.json

83
ui-ngx/src/app/modules/home/pages/notification-center/notification-center.component.html

@ -18,45 +18,52 @@
<div class="tb-notification-center"> <div class="tb-notification-center">
<div class="tb-notification-center-content"> <div class="tb-notification-center-content">
<div class="tabs-container"> <div class="tabs-container">
<mat-tab-group #matTabGroup (selectedIndexChange)="updateData()"> <ng-container *ngIf="isCustomerUser(); else notificationTabs">
<mat-tab label="{{ 'notification.inbox' | translate }}"> <tb-notification-table
<tb-notification-table [notificationType]="entityType.NOTIFICATION">
[notificationType]="entityType.NOTIFICATION"> </tb-notification-table>
</tb-notification-table> </ng-container>
</mat-tab> <ng-template #notificationTabs>
<mat-tab label="{{ 'notification.sent' | translate }}" #requestTab="matTab"> <mat-tab-group #matTabGroup (selectedIndexChange)="updateData()" mat-stretch-tabs="false">
<tb-notification-table <mat-tab label="{{ 'notification.inbox' | translate }}">
#notificationRequest <tb-notification-table
[notificationType]="entityType.NOTIFICATION_REQUEST"> [notificationType]="entityType.NOTIFICATION">
</tb-notification-table> </tb-notification-table>
</mat-tab> </mat-tab>
<mat-tab label="{{ 'notification.templates' | translate }}"> <mat-tab label="{{ 'notification.sent' | translate }}" #requestTab="matTab">
<tb-notification-table <tb-notification-table
[notificationType]="entityType.NOTIFICATION_TEMPLATE"> #notificationRequest
</tb-notification-table> [notificationType]="entityType.NOTIFICATION_REQUEST">
</mat-tab> </tb-notification-table>
<mat-tab label="{{ 'notification.targets' | translate }}"> </mat-tab>
<tb-notification-table <mat-tab label="{{ 'notification.templates' | translate }}">
[notificationType]="entityType.NOTIFICATION_TARGET"> <tb-notification-table
</tb-notification-table> [notificationType]="entityType.NOTIFICATION_TEMPLATE">
</mat-tab> </tb-notification-table>
<mat-tab label="{{ 'notification.rules' | translate }}"> </mat-tab>
<tb-notification-table <mat-tab label="{{ 'notification.targets' | translate }}">
[notificationType]="entityType.NOTIFICATION_RULE"> <tb-notification-table
</tb-notification-table> [notificationType]="entityType.NOTIFICATION_TARGET">
</mat-tab> </tb-notification-table>
<mat-tab disabled> </mat-tab>
<ng-template mat-tab-label> <mat-tab label="{{ 'notification.rules' | translate }}" *ngIf="isTenantAdmin()">
<div fxFlex="100" fxLayout="row" fxLayoutAlign="end center"> <tb-notification-table
<button mat-flat-button color="primary" (click)="sendNotification($event)"> [notificationType]="entityType.NOTIFICATION_RULE">
<div fxLayout="row" fxLayoutAlign="start center"> </tb-notification-table>
<mat-icon>send</mat-icon>{{ 'notification.send-notification' | translate }} </mat-tab>
<mat-tab disabled>
<ng-template mat-tab-label>
<div fxFlex="100" fxLayout="row" fxLayoutAlign="end center">
<button mat-flat-button color="primary" (click)="sendNotification($event)">
<div fxLayout="row" fxLayoutAlign="start center">
<mat-icon>send</mat-icon>{{ 'notification.send-notification' | translate }}
</div>
</button>
</div> </div>
</button> </ng-template>
</div> </mat-tab>
</ng-template> </mat-tab-group>
</mat-tab> </ng-template>
</mat-tab-group>
</div> </div>
</div> </div>
</div> </div>

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

@ -34,22 +34,6 @@
display: flex; display: flex;
flex-direction: column; flex-direction: column;
.title-container {
padding: 16px 16px 0;
.title {
margin: 8px;
letter-spacing: 0.1px;
font-size: 24px;
line-height: 24px;
font-weight: 400;
}
.action-buttons {
color: rgba(0, 0, 0, .54);
}
}
.tabs-container { .tabs-container {
position: relative; position: relative;
flex-direction: column; flex-direction: column;
@ -57,39 +41,24 @@
} }
} }
} }
@media #{$mat-xs} {
.tb-notification-center {
.tb-notification-center-content {
.title-container {
padding: 8px;
.title {
margin: 4px 0;
}
}
}
}
}
} }
:host ::ng-deep { :host ::ng-deep {
.tabs-container { .tabs-container {
.mat-tab-group { > .mat-mdc-tab-group {
> .mat-tab-body-wrapper { > .mat-mdc-tab-body-wrapper {
position: absolute; position: absolute;
top: 49px; top: 49px;
left: 0; left: 0;
right: 0; right: 0;
bottom: 0; bottom: 0;
} }
> .mat-tab-header {
.mat-tab-label {
min-width: 40px;
&.mat-tab-disabled { > .mat-mdc-tab-header {
.mat-mdc-tab {
&.mat-mdc-tab-disabled {
opacity: 1; opacity: 1;
width: 100%; //width: 100%;
.mat-tab-label-content { .mat-tab-label-content {
width: 100%; width: 100%;
@ -106,21 +75,21 @@
height: 56px; height: 56px;
} }
.mat-toolbar-single-row { .mat-toolbar-tools > div {
padding: 0 24px 0 12px; width: 100%;
} }
.title-container { .mat-toolbar-single-row {
width: 100%; padding: 0 24px 0 12px;
} }
} }
} }
@media #{$mat-xs} { @media #{$mat-xs} {
.tabs-container { .tabs-container {
.mat-tab-group { > .mat-mdc-tab-group {
> .mat-tab-header { > .mat-mdc-tab-header {
.mat-tab-label { .mat-mdc-tab {
&.mat-tab-disabled { &.mat-tab-disabled {
width: auto; width: auto;
} }

21
ui-ngx/src/app/modules/home/pages/notification-center/notification-center.component.ts

@ -23,6 +23,10 @@ import {
NotificationTableComponent NotificationTableComponent
} from '@home/pages/notification-center/notification-table/notification-table.component'; } from '@home/pages/notification-center/notification-table/notification-table.component';
import { EntityType } from '@shared/models/entity-type.models'; import { EntityType } from '@shared/models/entity-type.models';
import { Authority } from '@shared/models/authority.enum';
import { AuthState } from '@core/auth/auth.models';
import { getCurrentAuthState } from '@core/auth/auth.selectors';
import { AuthUser } from '@shared/models/user.model';
@Component({ @Component({
selector: 'tb-notification-center', selector: 'tb-notification-center',
@ -31,11 +35,14 @@ import { EntityType } from '@shared/models/entity-type.models';
}) })
export class NotificationCenterComponent extends PageComponent { export class NotificationCenterComponent extends PageComponent {
private authState: AuthState = getCurrentAuthState(this.store);
private authUser: AuthUser = this.authState.authUser;
entityType = EntityType; entityType = EntityType;
@ViewChild('matTabGroup', {static: true}) matTabs: MatTabGroup; @ViewChild('matTabGroup') matTabs: MatTabGroup;
@ViewChild('requestTab', {static: true}) requestTab: MatTab; @ViewChild('requestTab') requestTab: MatTab;
@ViewChild('notificationRequest', {static: true}) notificationRequestTable: NotificationTableComponent; @ViewChild('notificationRequest') notificationRequestTable: NotificationTableComponent;
@ViewChildren(NotificationTableComponent) tableComponent: QueryList<NotificationTableComponent>; @ViewChildren(NotificationTableComponent) tableComponent: QueryList<NotificationTableComponent>;
@ -59,4 +66,12 @@ export class NotificationCenterComponent extends PageComponent {
sendNotification($event: Event) { sendNotification($event: Event) {
this.notificationRequestTable.entityTableConfig.onEntityAction({event: $event, action: this.requestTab.isActive ? 'add' : 'add-without-update', entity: null}); this.notificationRequestTable.entityTableConfig.onEntityAction({event: $event, action: this.requestTab.isActive ? 'add' : 'add-without-update', entity: null});
} }
public isTenantAdmin(): boolean {
return this.authUser.authority === Authority.TENANT_ADMIN;
}
public isCustomerUser(): boolean {
return this.authUser.authority === Authority.CUSTOMER_USER;
}
} }

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

@ -55,7 +55,7 @@
<ng-template #scratchTemplate> <ng-template #scratchTemplate>
<section formGroupName="template"> <section formGroupName="template">
<section formGroupName="configuration"> <section formGroupName="configuration">
<mat-form-field class="mat-block tb-form-fields"> <mat-form-field class="mat-block" subscriptSizing="dynamic">
<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')">
@ -63,7 +63,7 @@
</mat-error> </mat-error>
<mat-hint>{{ notificationTemplateTypeTranslateMap.get(notificationType.GENERAL).hint | translate }}</mat-hint> <mat-hint>{{ notificationTemplateTypeTranslateMap.get(notificationType.GENERAL).hint | translate }}</mat-hint>
</mat-form-field> </mat-form-field>
<mat-form-field class="mat-block tb-form-fields"> <mat-form-field class="mat-block tb-form-fields" subscriptSizing="dynamic">
<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')">
@ -75,7 +75,7 @@
[ngClass]="{'tb-error': notificationRequestForm.get('template.configuration.deliveryMethodsTemplates').hasError('atLeastOne')}"> [ngClass]="{'tb-error': notificationRequestForm.get('template.configuration.deliveryMethodsTemplates').hasError('atLeastOne')}">
{{ "notification.delivery-methods" | translate }} {{ "notification.delivery-methods" | translate }}
</label> </label>
<section formGroupName="deliveryMethodsTemplates" fxLayout="row warap"> <section formGroupName="deliveryMethodsTemplates" fxLayout="row wrap">
<section *ngFor="let deliveryMethods of notificationDeliveryMethods; even as isEven" class="delivery-method-container" <section *ngFor="let deliveryMethods of notificationDeliveryMethods; even as isEven" class="delivery-method-container"
[formGroupName]="deliveryMethods" fxFlex="50%" [ngClass]={even:isEven}> [formGroupName]="deliveryMethods" fxFlex="50%" [ngClass]={even:isEven}>
<mat-slide-toggle class="delivery-method" formControlName="enabled"> <mat-slide-toggle class="delivery-method" formControlName="enabled">
@ -97,7 +97,7 @@
<button #createTargetButton <button #createTargetButton
mat-button color="primary" matSuffix mat-button color="primary" matSuffix
(click)="createTarget($event, createTargetButton)"> (click)="createTarget($event, createTargetButton)">
{{ 'notification.create-new' | translate }} <span style="white-space: nowrap">{{ 'notification.create-new' | translate }}</span>
</button> </button>
</tb-entity-list> </tb-entity-list>
<section formGroupName="additionalConfig" class="additional-config-group"> <section formGroupName="additionalConfig" class="additional-config-group">
@ -146,7 +146,8 @@
<mat-slide-toggle formControlName="enabled" class="toggle"> <mat-slide-toggle formControlName="enabled" class="toggle">
{{ 'icon.icon' | translate }} {{ 'icon.icon' | translate }}
</mat-slide-toggle> </mat-slide-toggle>
<div *ngIf="pushTemplateForm.get('additionalConfig.icon.enabled').value" fxLayout="row" fxLayoutGap="12px"> <div *ngIf="pushTemplateForm.get('additionalConfig.icon.enabled').value"
fxLayout="row" fxLayoutGap.gt-xs="8px" fxLayout.xs="column">
<tb-material-icon-select formControlName="icon" required fxFlex> <tb-material-icon-select formControlName="icon" required fxFlex>
</tb-material-icon-select> </tb-material-icon-select>
<tb-color-input formControlName="color" fxFlex> <tb-color-input formControlName="color" fxFlex>
@ -158,7 +159,7 @@
{{ 'notification.action-button' | translate }} {{ 'notification.action-button' | translate }}
</mat-slide-toggle> </mat-slide-toggle>
<div *ngIf="pushTemplateForm.get('additionalConfig.actionButtonConfig.enabled').value"> <div *ngIf="pushTemplateForm.get('additionalConfig.actionButtonConfig.enabled').value">
<div fxLayout="row" fxLayoutGap="8px"> <div fxLayout="row" fxLayoutGap.gt-xs="8px" fxLayout.xs="column">
<mat-form-field class="mat-block" fxFlex> <mat-form-field class="mat-block" fxFlex>
<mat-label translate>notification.button-text</mat-label> <mat-label translate>notification.button-text</mat-label>
<input matInput formControlName="text" required> <input matInput formControlName="text" required>
@ -169,8 +170,8 @@
<tb-color-input formControlName="color" fxFlex> <tb-color-input formControlName="color" fxFlex>
</tb-color-input> </tb-color-input>
</div> </div>
<div fxLayout="row" fxLayoutGap="8px"> <div fxLayout="row" fxLayoutGap.gt-xs="8px" fxLayout.xs="column">
<mat-form-field fxFlex="30"> <mat-form-field fxFlex="30" fxFlex.xs="100">
<mat-label translate>notification.action-type</mat-label> <mat-label translate>notification.action-type</mat-label>
<mat-select formControlName="linkType"> <mat-select formControlName="linkType">
<mat-option *ngFor="let actionButtonLinkType of actionButtonLinkTypes" [value]="actionButtonLinkType"> <mat-option *ngFor="let actionButtonLinkType of actionButtonLinkTypes" [value]="actionButtonLinkType">
@ -188,11 +189,11 @@
</mat-form-field> </mat-form-field>
<ng-template #dashboardSelector> <ng-template #dashboardSelector>
<tb-dashboard-autocomplete <tb-dashboard-autocomplete
fxFlex="35" fxFlex="35" fxFlex.xs="100"
required required
formControlName="dashboardId"> formControlName="dashboardId">
</tb-dashboard-autocomplete> </tb-dashboard-autocomplete>
<tb-dashboard-state-autocomplete fxFlex="35" <tb-dashboard-state-autocomplete fxFlex="35" fxFlex.xs="100"
[dashboardId]="pushTemplateForm.get('additionalConfig.actionButtonConfig.dashboardId').value" [dashboardId]="pushTemplateForm.get('additionalConfig.actionButtonConfig.dashboardId').value"
formControlName="dashboardState"> formControlName="dashboardState">
</tb-dashboard-state-autocomplete> </tb-dashboard-state-autocomplete>

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

@ -16,9 +16,13 @@
@import "../../../../../../scss/constants"; @import "../../../../../../scss/constants";
@import "../../../../../../theme"; @import "../../../../../../theme";
:host-context(.tb-fullscreen-dialog .mat-dialog-container) { :host-context(.tb-fullscreen-dialog .mat-mdc-dialog-container) {
width: 800px; width: 800px;
height: 100%;
max-width: 100%;
max-height: 100vh; max-height: 100vh;
display: flex;
flex-direction: column;
.tb-form-fields { .tb-form-fields {
margin-bottom: 8px; margin-bottom: 8px;
@ -70,11 +74,7 @@
border-radius: 4px; border-radius: 4px;
&.notification { &.notification {
background-color: #F3F6FA; //map_get($tb-mat-indigo, 50); background-color: #F3F6FA;
}
.mat-icon {
color: rgba(0, 0, 0, 0.38);
} }
.group-title { .group-title {
@ -135,16 +135,10 @@
} }
} }
} }
@media #{$mat-gt-xs} {
.mat-dialog-content {
max-height: 75vh;
}
}
} }
:host ::ng-deep { :host ::ng-deep {
.mat-dialog-content { .mat-mdc-dialog-content {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
height: 100%; height: 100%;
@ -159,15 +153,6 @@
flex: 1 1 100%; flex: 1 1 100%;
} }
@media #{$mat-lt-sm} {
.mat-step-label {
white-space: normal;
overflow: visible;
.mat-step-text-label {
overflow: visible;
}
}
}
.mat-horizontal-content-container { .mat-horizontal-content-container {
height: 600px; height: 600px;
max-height: 100%; max-height: 100%;
@ -178,10 +163,6 @@
min-width: 500px; min-width: 500px;
} }
} }
.mat-horizontal-stepper-content[aria-expanded=true] {
height: 100%;
position: relative;
}
} }
} }
@ -239,28 +220,6 @@
} }
} }
.mat-form-field {
.mat-form-field-wrapper {
padding-bottom: 0;
.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);
}
}
}
.preview-group { .preview-group {
.notification-content { .notification-content {
.html-content, .html-content,

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

@ -84,7 +84,7 @@ export class RequestNotificationDialogComponent extends
private dialog: MatDialog) { private dialog: MatDialog) {
super(store, router, dialogRef, fb); super(store, router, dialogRef, fb);
this.stepperOrientation = this.breakpointObserver.observe(MediaBreakpoints['gt-xs']) this.stepperOrientation = this.breakpointObserver.observe(MediaBreakpoints['gt-sm'])
.pipe(map(({matches}) => matches ? 'horizontal' : 'vertical')); .pipe(map(({matches}) => matches ? 'horizontal' : 'vertical'));
this.notificationRequestForm = this.fb.group({ this.notificationRequestForm = this.fb.group({

2
ui-ngx/src/app/modules/home/pages/notification-center/rule-table/alarm-severities-list.component.html

@ -19,7 +19,7 @@
<mat-form-field fxFlex class="mat-block" [floatLabel]="flotLabel"> <mat-form-field fxFlex class="mat-block" [floatLabel]="flotLabel">
<mat-label translate>alarm.alarm-severity-list</mat-label> <mat-label translate>alarm.alarm-severity-list</mat-label>
<mat-chip-grid #severitiesChipList formControlName="alarmSeverities" [required]="required"> <mat-chip-grid #severitiesChipList formControlName="alarmSeverities" [required]="required">
<mat-chip-row *ngFor="let severity of alarmSeveritiesForm.get('alarmSeverities').value" <mat-chip-row *ngFor="let severity of alarmSeverities"
[removable]="!disabled" [removable]="!disabled"
(removed)="onSeverityRemoved(severity)"> (removed)="onSeverityRemoved(severity)">
{{ alarmSeverityTranslationMap.get(severity) | translate }} {{ alarmSeverityTranslationMap.get(severity) | translate }}

16
ui-ngx/src/app/modules/home/pages/notification-center/rule-table/alarm-severities-list.component.ts

@ -47,9 +47,11 @@ export class AlarmSeveritiesListComponent implements ControlValueAccessor{
alarmSeveritiesForm: FormGroup; alarmSeveritiesForm: FormGroup;
alarmSeverityTranslationMap = alarmSeverityTranslations; alarmSeverityTranslationMap = alarmSeverityTranslations;
private alarmSeverities = Object.keys(AlarmSeverity); private alarmSeveritiesValues = Object.keys(AlarmSeverity) as Array<AlarmSeverity>;
alarmSeverity = AlarmSeverity; alarmSeverity = AlarmSeverity;
alarmSeverities: Array<AlarmSeverity> = []
readonly separatorKeysCodes: number[] = [ENTER, COMMA, SEMICOLON]; readonly separatorKeysCodes: number[] = [ENTER, COMMA, SEMICOLON];
private modelValue: Array<string> | null; private modelValue: Array<string> | null;
@ -117,12 +119,14 @@ export class AlarmSeveritiesListComponent implements ControlValueAccessor{
} }
} }
writeValue(value: Array<string> | null): void { writeValue(value: Array<AlarmSeverity> | null): void {
this.searchText = ''; this.searchText = '';
if (value != null && value.length > 0) { if (value != null && value.length > 0) {
this.modelValue = [...value]; this.modelValue = [...value];
this.alarmSeverities = [...value];
this.alarmSeveritiesForm.get('alarmSeverities').setValue(value); this.alarmSeveritiesForm.get('alarmSeverities').setValue(value);
} else { } else {
this.alarmSeverities = [];
this.alarmSeveritiesForm.get('alarmSeverities').setValue(null); this.alarmSeveritiesForm.get('alarmSeverities').setValue(null);
this.modelValue = null; this.modelValue = null;
} }
@ -141,13 +145,14 @@ export class AlarmSeveritiesListComponent implements ControlValueAccessor{
} }
} }
private addSeverity(alarmSeverity: string) { private addSeverity(alarmSeverity: AlarmSeverity) {
if (alarmSeverity) { if (alarmSeverity) {
if (!this.modelValue || this.modelValue.indexOf(alarmSeverity) === -1) { if (!this.modelValue || this.modelValue.indexOf(alarmSeverity) === -1) {
if (!this.modelValue) { if (!this.modelValue) {
this.modelValue = []; this.modelValue = [];
} }
this.modelValue.push(alarmSeverity); this.modelValue.push(alarmSeverity);
this.alarmSeverities.push(alarmSeverity);
this.alarmSeveritiesForm.get('alarmSeverities').setValue(this.modelValue); this.alarmSeveritiesForm.get('alarmSeverities').setValue(this.modelValue);
} }
this.propagateChange(this.modelValue); this.propagateChange(this.modelValue);
@ -164,6 +169,7 @@ export class AlarmSeveritiesListComponent implements ControlValueAccessor{
const index = this.modelValue.indexOf(alarmSeverity); const index = this.modelValue.indexOf(alarmSeverity);
if (index >= 0) { if (index >= 0) {
this.modelValue.splice(index, 1); this.modelValue.splice(index, 1);
this.alarmSeverities.splice(index, 1);
if (!this.modelValue.length) { if (!this.modelValue.length) {
this.modelValue = null; this.modelValue = null;
} }
@ -189,9 +195,9 @@ export class AlarmSeveritiesListComponent implements ControlValueAccessor{
return (text && text.length > 0); return (text && text.length > 0);
} }
private fetchSeverities(searchText?: string): Array<string> { private fetchSeverities(searchText?: string): Array<AlarmSeverity> {
this.searchText = searchText; this.searchText = searchText;
const allowAlarmSeverity = this.alarmSeverities.filter(severity => !this.modelValue?.includes(severity)); const allowAlarmSeverity = this.alarmSeveritiesValues.filter(severity => !this.modelValue?.includes(severity));
if (this.textIsNotEmpty(this.searchText)) { if (this.textIsNotEmpty(this.searchText)) {
const search = this.searchText.toUpperCase(); const search = this.searchText.toUpperCase();
return allowAlarmSeverity.filter(severity => severity.toUpperCase().includes(search)); return allowAlarmSeverity.filter(severity => severity.toUpperCase().includes(search));

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

@ -17,30 +17,30 @@
--> -->
<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 *ngIf="systemEscalation; else selectTime" 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 translate>notification.after</span>
<span translate>notification.after</span> <tb-timeinterval
<tb-timeinterval subscriptSizing="dynamic"
formControlName="delayInSec" formControlName="delayInSec"
min="{{ 0 }}" min="{{ 0 }}"
max="{{ 604800000 }}" max="{{ 604800000 }}"
disabledAdvanced></tb-timeinterval> disabledAdvanced></tb-timeinterval>
<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>-->
<tb-entity-list <tb-entity-list
required required
fxFlex="60" fxFlex="60"
formControlName="targets" formControlName="targets"
subscriptSizing="dynamic"
[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 }} <span style="white-space: nowrap">{{ 'notification.create-new' | translate }}</span>
</button> </button>
</tb-entity-list> </tb-entity-list>
</div> </div>

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

@ -52,14 +52,14 @@
} }
:host ::ng-deep { :host ::ng-deep {
.mat-form-field { .mat-mdc-form-field {
min-width: 100px; min-width: 100px;
.mat-form-field-infix { .mat-mdc-form-field-infix {
width: 100%; width: 100%;
} }
.mat-select { .mat-mdc-select {
min-width: 110px !important; min-width: 110px !important;
} }
} }

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

@ -70,7 +70,7 @@
<button #createTargetButton <button #createTargetButton
mat-button color="primary" matSuffix mat-button color="primary" matSuffix
(click)="createTarget($event, createTargetButton)"> (click)="createTarget($event, createTargetButton)">
{{ 'notification.create-new' | translate }} <span style="white-space: nowrap">{{ 'notification.create-new' | translate }}</span>
</button> </button>
</tb-entity-list> </tb-entity-list>
</section> </section>
@ -98,8 +98,7 @@
</tb-string-items-list> </tb-string-items-list>
<tb-alarm-severities-list formControlName="alarmSeverities" <tb-alarm-severities-list formControlName="alarmSeverities"
flotLabel="always" flotLabel="always">
required>
</tb-alarm-severities-list> </tb-alarm-severities-list>
</fieldset> </fieldset>
@ -144,20 +143,22 @@
<ng-container *ngIf="deviceInactivityTemplateForm.get('triggerConfig.filterByDevice').value; else deviceProfile"> <ng-container *ngIf="deviceInactivityTemplateForm.get('triggerConfig.filterByDevice').value; else deviceProfile">
<tb-entity-list <tb-entity-list
formControlName="devices" formControlName="devices"
subscriptSizing="dynamic"
labelText="{{ 'notification.devices' | translate }}" labelText="{{ 'notification.devices' | translate }}"
placeholderText="{{ 'notification.devices' | translate }}" placeholderText="{{ 'notification.devices' | translate }}"
hint="{{ 'notification.device-list-rule-hint' | translate }}"
[entityType]="entityType.DEVICE"> [entityType]="entityType.DEVICE">
</tb-entity-list> </tb-entity-list>
<div class="tb-hint" translate>notification.device-list-rule-hint</div>
</ng-container> </ng-container>
<ng-template #deviceProfile> <ng-template #deviceProfile>
<tb-entity-list <tb-entity-list
formControlName="deviceProfiles" formControlName="deviceProfiles"
subscriptSizing="dynamic"
labelText="{{ 'notification.device-profiles' | translate }}" labelText="{{ 'notification.device-profiles' | translate }}"
placeholderText="{{ 'notification.device-profiles' | translate }}" placeholderText="{{ 'notification.device-profiles' | translate }}"
hint="{{ 'notification.device-profiles-list-rule-hint' | translate }}"
[entityType]="entityType.DEVICE_PROFILE"> [entityType]="entityType.DEVICE_PROFILE">
</tb-entity-list> </tb-entity-list>
<div class="tb-hint" translate>notification.device-profiles-list-rule-hint</div>
</ng-template> </ng-template>
</section> </section>
</form> </form>

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

@ -18,13 +18,11 @@
:host { :host {
width: 700px; width: 700px;
height: 100%;
max-width: 100%;
max-height: 100vh; max-height: 100vh;
display: flex;
@media #{$mat-gt-xs} { flex-direction: column;
.mat-dialog-content {
max-height: 75vh;
}
}
.tb-hint { .tb-hint {
margin-top: -1.25em; margin-top: -1.25em;
@ -53,7 +51,7 @@
::ng-deep { ::ng-deep {
.mat-dialog-content { .mat-mdc-dialog-content {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
height: 100%; height: 100%;
@ -68,17 +66,6 @@
flex: 1 1 100%; flex: 1 1 100%;
} }
@media #{$mat-lt-sm} {
.mat-step-label {
white-space: normal;
overflow: visible;
.mat-step-text-label {
overflow: visible;
}
}
}
.mat-horizontal-content-container { .mat-horizontal-content-container {
height: 550px; height: 550px;
max-height: 100%; max-height: 100%;
@ -89,11 +76,6 @@
min-width: 500px; min-width: 500px;
} }
} }
.mat-horizontal-stepper-content[aria-expanded=true] {
height: 100%;
position: relative;
}
} }
} }

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

@ -136,7 +136,7 @@ export class RuleNotificationDialogComponent extends
this.alarmTemplateForm = this.fb.group({ this.alarmTemplateForm = this.fb.group({
triggerConfig: this.fb.group({ triggerConfig: this.fb.group({
alarmTypes: [null], alarmTypes: [null],
alarmSeverities: [null, Validators.required], alarmSeverities: [null],
clearRule: this.fb.group({ clearRule: this.fb.group({
alarmStatus: [null] alarmStatus: [null]
}) })

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

@ -33,26 +33,26 @@
} }
:host ::ng-deep { :host ::ng-deep {
.mat-radio-group { .mat-mdc-radio-group {
display: flex; display: flex;
flex-direction: row; flex-direction: row;
margin-bottom: 14px; margin-bottom: 14px;
gap: 8px; gap: 8px;
.mat-radio-button { .mat-mdc-radio-button {
flex: 1 1 100%; flex: 1 1 100%;
padding: 14px; padding: 4px;
border: 1px solid rgba(0, 0, 0, 0.12); border: 1px solid rgba(0, 0, 0, 0.12);
border-radius: 6px; border-radius: 6px;
&.mat-radio-checked { &.mat-mdc-radio-checked {
border-color: map_get($tb-accent, 500); border-color: map_get($tb-accent, 500);
} }
} }
} }
@media #{$mat-xs} { @media #{$mat-xs} {
.mat-radio-group { .mat-mdc-radio-group {
flex-direction: column; flex-direction: column;
} }
} }

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

@ -35,6 +35,10 @@ import { EntityType } from '@shared/models/entity-type.models';
import { deepTrim, isDefined } from '@core/utils'; import { deepTrim, isDefined } from '@core/utils';
import { Subject } from 'rxjs'; import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators'; import { takeUntil } from 'rxjs/operators';
import { Authority } from '@shared/models/authority.enum';
import { AuthState } from '@core/auth/auth.models';
import { getCurrentAuthState } from '@core/auth/auth.selectors';
import { AuthUser } from '@shared/models/user.model';
export interface TargetsNotificationDialogData { export interface TargetsNotificationDialogData {
target?: NotificationTarget; target?: NotificationTarget;
@ -49,6 +53,9 @@ export interface TargetsNotificationDialogData {
export class TargetNotificationDialogComponent extends export class TargetNotificationDialogComponent extends
DialogComponent<TargetNotificationDialogComponent, NotificationTarget> implements OnDestroy { DialogComponent<TargetNotificationDialogComponent, NotificationTarget> implements OnDestroy {
private authState: AuthState = getCurrentAuthState(this.store);
private authUser: AuthUser = this.authState.authUser;
targetNotificationForm: FormGroup; targetNotificationForm: FormGroup;
notificationTargetType = NotificationTargetType; notificationTargetType = NotificationTargetType;
notificationTargetTypes: NotificationTargetType[] = Object.values(NotificationTargetType); notificationTargetTypes: NotificationTargetType[] = Object.values(NotificationTargetType);
@ -81,7 +88,7 @@ export class TargetNotificationDialogComponent extends
configuration: this.fb.group({ configuration: this.fb.group({
type: [NotificationTargetType.PLATFORM_USERS], type: [NotificationTargetType.PLATFORM_USERS],
usersFilter: this.fb.group({ usersFilter: this.fb.group({
type: [NotificationTargetConfigType.ALL_USERS], type: [{value: NotificationTargetConfigType.ALL_USERS, disabled: !this.isTenantAdmin()}],
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]
}), }),
@ -97,8 +104,10 @@ export class TargetNotificationDialogComponent extends
this.targetNotificationForm.get('configuration').disable({emitEvent: false}); this.targetNotificationForm.get('configuration').disable({emitEvent: false});
switch (type) { switch (type) {
case NotificationTargetType.PLATFORM_USERS: case NotificationTargetType.PLATFORM_USERS:
this.targetNotificationForm.get('configuration.usersFilter').enable({emitEvent: false}); if (this.isTenantAdmin()) {
this.targetNotificationForm.get('configuration.usersFilter.type').updateValueAndValidity({onlySelf: true}); this.targetNotificationForm.get('configuration.usersFilter').enable({emitEvent: false});
this.targetNotificationForm.get('configuration.usersFilter.type').updateValueAndValidity({onlySelf: true});
}
break; break;
case NotificationTargetType.SLACK: case NotificationTargetType.SLACK:
this.targetNotificationForm.get('configuration.conversationType').enable({emitEvent: false}); this.targetNotificationForm.get('configuration.conversationType').enable({emitEvent: false});
@ -149,4 +158,8 @@ export class TargetNotificationDialogComponent extends
(target) => this.dialogRef.close(target) (target) => this.dialogRef.close(target)
); );
} }
public isTenantAdmin(): boolean {
return this.authUser.authority === Authority.TENANT_ADMIN;
}
} }

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

@ -33,7 +33,7 @@
mat-button color="primary" matSuffix mat-button color="primary" matSuffix
*ngIf="allowCreate && !selectTemplateFormGroup.get('templateName').value && !disabled" *ngIf="allowCreate && !selectTemplateFormGroup.get('templateName').value && !disabled"
(click)="createTemplate($event, createTemplateButton)"> (click)="createTemplate($event, createTemplateButton)">
{{ 'notification.create-new' | translate }} <span style="white-space: nowrap">{{ 'notification.create-new' | translate }}</span>
</button> </button>
<mat-autocomplete class="tb-autocomplete" <mat-autocomplete class="tb-autocomplete"
#templateAutocomplete="matAutocomplete" #templateAutocomplete="matAutocomplete"
@ -41,11 +41,11 @@
> >
<mat-option *ngFor="let template of filteredTemplate | async" [value]="template" class="template-option"> <mat-option *ngFor="let template of filteredTemplate | async" [value]="template" class="template-option">
<span class="template-option-name" [innerHTML]="template.name | highlight:searchText"></span> <span class="template-option-name" [innerHTML]="template.name | highlight:searchText"></span>
<mat-chip-grid> <mat-chip-set>
<mat-chip-row disabled *ngFor="let method of template.configuration.deliveryMethodsTemplates | keyvalue"> <mat-chip disabled *ngFor="let method of template.configuration.deliveryMethodsTemplates | keyvalue">
{{ notificationDeliveryMethodTranslateMap.get(method.key) | translate }} {{ notificationDeliveryMethodTranslateMap.get(method.key) | translate }}
</mat-chip-row> </mat-chip>
</mat-chip-grid> </mat-chip-set>
</mat-option> </mat-option>
<mat-option *ngIf="!(filteredTemplate | async)?.length" [value]="null" class="tb-not-found"> <mat-option *ngIf="!(filteredTemplate | async)?.length" [value]="null" class="tb-not-found">
<div class="tb-not-found-content" (click)="$event.stopPropagation()"> <div class="tb-not-found-content" (click)="$event.stopPropagation()">

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

@ -13,29 +13,18 @@
* 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.
*/ */
::ng-deep { .template-option {
.template-option { .mdc-list-item__primary-text {
.mat-option-text { display: flex;
display: flex; flex-direction: row;
flex-direction: row; align-items: center;
align-items: center; }
margin-bottom: 4px;
}
.template-option-name {
margin-right: 8px;
}
.mat-chip { .template-option-name {
&.mat-standard-chip { margin-right: 8px;
padding: 4px 8px; }
border-radius: 14px;
min-height: 28px;
&.mat-chip-disabled { .mat-mdc-standard-chip.mdc-evolution-chip--disabled {
opacity: 1; opacity: 1;
}
}
}
} }
} }

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

@ -14,7 +14,7 @@
/// limitations under the License. /// limitations under the License.
/// ///
import { Component, ElementRef, forwardRef, Input, OnInit, ViewChild } from '@angular/core'; import { Component, ElementRef, forwardRef, Input, OnInit, ViewChild, ViewEncapsulation } from '@angular/core';
import { ControlValueAccessor, FormBuilder, FormGroup, NG_VALUE_ACCESSOR, Validators } from '@angular/forms'; import { ControlValueAccessor, FormBuilder, FormGroup, NG_VALUE_ACCESSOR, Validators } from '@angular/forms';
import { Observable, of } from 'rxjs'; import { Observable, of } from 'rxjs';
import { catchError, debounceTime, distinctUntilChanged, map, share, switchMap, tap } from 'rxjs/operators'; import { catchError, debounceTime, distinctUntilChanged, map, share, switchMap, tap } from 'rxjs/operators';
@ -46,6 +46,7 @@ import { coerceBoolean } from '@shared/decorators/coerce-boolean';
selector: 'tb-template-autocomplete', selector: 'tb-template-autocomplete',
templateUrl: './template-autocomplete.component.html', templateUrl: './template-autocomplete.component.html',
styleUrls: ['./template-autocomplete.component.scss'], styleUrls: ['./template-autocomplete.component.scss'],
encapsulation: ViewEncapsulation.None,
providers: [{ providers: [{
provide: NG_VALUE_ACCESSOR, provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => TemplateAutocompleteComponent), useExisting: forwardRef(() => TemplateAutocompleteComponent),

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

@ -136,14 +136,17 @@ export abstract class TemplateConfiguration<T, R = any> extends DialogComponent<
this.pushTemplateForm.get('additionalConfig.actionButtonConfig.linkType').valueChanges.pipe( this.pushTemplateForm.get('additionalConfig.actionButtonConfig.linkType').valueChanges.pipe(
takeUntil(this.destroy$) takeUntil(this.destroy$)
).subscribe((value) => { ).subscribe((value) => {
if (value === ActionButtonLinkType.LINK) { const isEnabled = this.pushTemplateForm.get('additionalConfig.actionButtonConfig.enabled').value;
this.pushTemplateForm.get('additionalConfig.actionButtonConfig.link').enable({emitEvent: false}); if (isEnabled) {
this.pushTemplateForm.get('additionalConfig.actionButtonConfig.dashboardId').disable({emitEvent: false}); if (value === ActionButtonLinkType.LINK) {
this.pushTemplateForm.get('additionalConfig.actionButtonConfig.dashboardState').disable({emitEvent: false}); this.pushTemplateForm.get('additionalConfig.actionButtonConfig.link').enable({emitEvent: false});
} else { this.pushTemplateForm.get('additionalConfig.actionButtonConfig.dashboardId').disable({emitEvent: false});
this.pushTemplateForm.get('additionalConfig.actionButtonConfig.link').disable({emitEvent: false}); this.pushTemplateForm.get('additionalConfig.actionButtonConfig.dashboardState').disable({emitEvent: false});
this.pushTemplateForm.get('additionalConfig.actionButtonConfig.dashboardId').enable({emitEvent: false}); } else {
this.pushTemplateForm.get('additionalConfig.actionButtonConfig.dashboardState').enable({emitEvent: false}); this.pushTemplateForm.get('additionalConfig.actionButtonConfig.link').disable({emitEvent: false});
this.pushTemplateForm.get('additionalConfig.actionButtonConfig.dashboardId').enable({emitEvent: false});
this.pushTemplateForm.get('additionalConfig.actionButtonConfig.dashboardState').enable({emitEvent: false});
}
} }
}); });

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

@ -52,7 +52,7 @@
</mat-select> </mat-select>
</mat-form-field> </mat-form-field>
<section formGroupName="configuration"> <section formGroupName="configuration">
<mat-form-field class="mat-block tb-form-fields"> <mat-form-field class="mat-block" subscriptSizing="dynamic">
<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')">
@ -60,7 +60,7 @@
</mat-error> </mat-error>
<mat-hint>{{ notificationTemplateTypeTranslateMap.get(templateNotificationForm.get('notificationType').value).hint | translate }}</mat-hint> <mat-hint>{{ notificationTemplateTypeTranslateMap.get(templateNotificationForm.get('notificationType').value).hint | translate }}</mat-hint>
</mat-form-field> </mat-form-field>
<mat-form-field class="mat-block tb-form-fields"> <mat-form-field class="mat-block tb-form-fields" subscriptSizing="dynamic">
<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')">
@ -110,7 +110,8 @@
<mat-slide-toggle formControlName="enabled" class="toggle"> <mat-slide-toggle formControlName="enabled" class="toggle">
{{ 'icon.icon' | translate }} {{ 'icon.icon' | translate }}
</mat-slide-toggle> </mat-slide-toggle>
<div *ngIf="pushTemplateForm.get('additionalConfig.icon.enabled').value" fxLayout="row" fxLayoutGap="12px"> <div *ngIf="pushTemplateForm.get('additionalConfig.icon.enabled').value"
fxLayout="row" fxLayoutGap.gt-xs="8px" fxLayout.xs="column">
<tb-material-icon-select formControlName="icon" required fxFlex> <tb-material-icon-select formControlName="icon" required fxFlex>
</tb-material-icon-select> </tb-material-icon-select>
<tb-color-input formControlName="color" fxFlex> <tb-color-input formControlName="color" fxFlex>
@ -122,7 +123,7 @@
{{ 'notification.action-button' | translate }} {{ 'notification.action-button' | translate }}
</mat-slide-toggle> </mat-slide-toggle>
<div *ngIf="pushTemplateForm.get('additionalConfig.actionButtonConfig.enabled').value"> <div *ngIf="pushTemplateForm.get('additionalConfig.actionButtonConfig.enabled').value">
<div fxLayout="row" fxLayoutGap="8px"> <div fxLayout="row" fxLayoutGap.gt-xs="8px" fxLayout.xs="column">
<mat-form-field class="mat-block" fxFlex> <mat-form-field class="mat-block" fxFlex>
<mat-label translate>notification.button-text</mat-label> <mat-label translate>notification.button-text</mat-label>
<input matInput formControlName="text" required> <input matInput formControlName="text" required>
@ -133,8 +134,8 @@
<tb-color-input formControlName="color" fxFlex> <tb-color-input formControlName="color" fxFlex>
</tb-color-input> </tb-color-input>
</div> </div>
<div fxLayout="row" fxLayoutGap="8px"> <div fxLayout="row" fxLayoutGap.gt-xs="8px" fxLayout.xs="column">
<mat-form-field fxFlex="30"> <mat-form-field fxFlex="30" fxFlex.xs="100">
<mat-label translate>notification.action-type</mat-label> <mat-label translate>notification.action-type</mat-label>
<mat-select formControlName="linkType"> <mat-select formControlName="linkType">
<mat-option *ngFor="let actionButtonLinkType of actionButtonLinkTypes" [value]="actionButtonLinkType"> <mat-option *ngFor="let actionButtonLinkType of actionButtonLinkTypes" [value]="actionButtonLinkType">
@ -152,11 +153,11 @@
</mat-form-field> </mat-form-field>
<ng-template #dashboardSelector> <ng-template #dashboardSelector>
<tb-dashboard-autocomplete <tb-dashboard-autocomplete
fxFlex="35" fxFlex="35" fxFlex.xs="100"
required required
formControlName="dashboardId"> formControlName="dashboardId">
</tb-dashboard-autocomplete> </tb-dashboard-autocomplete>
<tb-dashboard-state-autocomplete fxFlex="35" <tb-dashboard-state-autocomplete fxFlex="35" fxFlex.xs="100"
[dashboardId]="pushTemplateForm.get('additionalConfig.actionButtonConfig.dashboardId').value" [dashboardId]="pushTemplateForm.get('additionalConfig.actionButtonConfig.dashboardId').value"
formControlName="dashboardState"> formControlName="dashboardState">
</tb-dashboard-state-autocomplete> </tb-dashboard-state-autocomplete>

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

@ -16,9 +16,13 @@
@import "../../../../../../scss/constants"; @import "../../../../../../scss/constants";
@import "../../../../../../theme"; @import "../../../../../../theme";
:host-context(.tb-fullscreen-dialog .mat-dialog-container) { :host-context(.tb-fullscreen-dialog .mat-mdc-dialog-container) {
width: 830px; width: 830px;
height: 100%;
max-width: 100%;
max-height: 100vh; max-height: 100vh;
display: flex;
flex-direction: column;
.tb-form-fields { .tb-form-fields {
margin-bottom: 8px; margin-bottom: 8px;
@ -66,16 +70,10 @@
margin-bottom: 12px; margin-bottom: 12px;
} }
} }
@media #{$mat-gt-xs} {
.mat-dialog-content {
max-height: 75vh;
}
}
} }
:host ::ng-deep { :host ::ng-deep {
.mat-dialog-content { .mat-mdc-dialog-content {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
height: 100%; height: 100%;
@ -90,15 +88,6 @@
flex: 1 1 100%; flex: 1 1 100%;
} }
@media #{$mat-lt-sm} {
.mat-step-label {
white-space: normal;
overflow: visible;
.mat-step-text-label {
overflow: visible;
}
}
}
.mat-horizontal-content-container { .mat-horizontal-content-container {
height: 550px; height: 550px;
max-height: 100%; max-height: 100%;
@ -109,58 +98,6 @@
min-width: 500px; min-width: 500px;
} }
} }
.mat-horizontal-stepper-content[aria-expanded=true] {
height: 100%;
position: relative;
}
}
}
.mat-radio-group {
display: flex;
flex-direction: row;
margin-bottom: 8px;
.mat-radio-button {
flex: 1 1 100%;
padding: 14px;
border: 1px solid rgba(0, 0, 0, 0.12);
border-radius: 6px;
.mat-radio-label {
white-space: break-spaces;
align-items: start;
}
&:not(:last-child){
margin-bottom: 8px;
}
&.mat-radio-checked {
border-color: map_get($tb-accent, 500);
}
}
}
.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);
}
} }
} }
} }

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

@ -36,6 +36,10 @@ import { BreakpointObserver } from '@angular/cdk/layout';
import { MediaBreakpoints } from '@shared/models/constants'; import { MediaBreakpoints } from '@shared/models/constants';
import { TranslateService } from '@ngx-translate/core'; import { TranslateService } from '@ngx-translate/core';
import { TemplateConfiguration } from '@home/pages/notification-center/template-table/template-configuration'; import { TemplateConfiguration } from '@home/pages/notification-center/template-table/template-configuration';
import { AuthState } from '@core/auth/auth.models';
import { getCurrentAuthState } from '@core/auth/auth.selectors';
import { AuthUser } from '@shared/models/user.model';
import { Authority } from '@shared/models/authority.enum';
export interface TemplateNotificationDialogData { export interface TemplateNotificationDialogData {
template?: NotificationTemplate; template?: NotificationTemplate;
@ -56,21 +60,16 @@ export class TemplateNotificationDialogComponent
stepperOrientation: Observable<StepperOrientation>; stepperOrientation: Observable<StepperOrientation>;
templateNotificationForm: FormGroup;
pushTemplateForm: FormGroup;
emailTemplateForm: FormGroup;
smsTemplateForm: FormGroup;
slackTemplateForm: FormGroup;
dialogTitle = 'notification.edit-notification-template'; dialogTitle = 'notification.edit-notification-template';
notificationTypes = Object.keys(NotificationType) as NotificationType[]; notificationTypes = Object.keys(NotificationType) as NotificationType[];
notificationDeliveryMethods = Object.keys(NotificationDeliveryMethod) as NotificationDeliveryMethod[];
notificationDeliveryMethodTranslateMap = NotificationDeliveryMethodTranslateMap;
selectedIndex = 0; selectedIndex = 0;
hideSelectType = false; hideSelectType = false;
private readonly templateNotification: NotificationTemplate; private readonly templateNotification: NotificationTemplate;
private authState: AuthState = getCurrentAuthState(this.store);
private authUser: AuthUser = this.authState.authUser;
constructor(protected store: Store<AppState>, constructor(protected store: Store<AppState>,
protected router: Router, protected router: Router,
@ -82,7 +81,7 @@ export class TemplateNotificationDialogComponent
private translate: TranslateService) { private translate: TranslateService) {
super(store, router, dialogRef, fb); super(store, router, dialogRef, fb);
this.stepperOrientation = this.breakpointObserver.observe(MediaBreakpoints['gt-xs']) this.stepperOrientation = this.breakpointObserver.observe(MediaBreakpoints['gt-sm'])
.pipe(map(({matches}) => matches ? 'horizontal' : 'vertical')); .pipe(map(({matches}) => matches ? 'horizontal' : 'vertical'));
if (isDefinedAndNotNull(this.data?.predefinedType)) { if (isDefinedAndNotNull(this.data?.predefinedType)) {
@ -90,6 +89,10 @@ export class TemplateNotificationDialogComponent
this.templateNotificationForm.get('notificationType').setValue(this.data.predefinedType, {emitEvents: false}); this.templateNotificationForm.get('notificationType').setValue(this.data.predefinedType, {emitEvents: false});
} }
if (this.isSysAdmin()) {
this.hideSelectType = true;
}
if (data.isAdd || data.isCopy) { if (data.isAdd || data.isCopy) {
this.dialogTitle = 'notification.add-notification-template'; this.dialogTitle = 'notification.add-notification-template';
} }
@ -172,4 +175,8 @@ export class TemplateNotificationDialogComponent
} }
}); });
} }
private isSysAdmin(): boolean {
return this.authUser.authority === Authority.SYS_ADMIN;
}
} }

6
ui-ngx/src/app/shared/components/entity/entity-list.component.html

@ -15,7 +15,7 @@
limitations under the License. limitations under the License.
--> -->
<mat-form-field [formGroup]="entityListFormGroup" class="mat-block tb-chip-list"> <mat-form-field [formGroup]="entityListFormGroup" class="mat-block" [ngClass]="{'tb-chip-list': !labelText}" [subscriptSizing]="subscriptSizing">
<mat-label *ngIf="labelText">{{ labelText }}</mat-label> <mat-label *ngIf="labelText">{{ labelText }}</mat-label>
<mat-chip-grid #chipList formControlName="entities"> <mat-chip-grid #chipList formControlName="entities">
<mat-chip-row <mat-chip-row
@ -26,7 +26,6 @@
<mat-icon matChipRemove *ngIf="!disabled">close</mat-icon> <mat-icon matChipRemove *ngIf="!disabled">close</mat-icon>
</mat-chip-row> </mat-chip-row>
<input matInput type="text" placeholder="{{ !disabled ? placeholderText : '' }}" <input matInput type="text" placeholder="{{ !disabled ? placeholderText : '' }}"
style="max-width: 200px;"
#entityInput #entityInput
(focusin)="onFocus()" (focusin)="onFocus()"
formControlName="entity" formControlName="entity"
@ -48,6 +47,9 @@
</span> </span>
</mat-option> </mat-option>
</mat-autocomplete> </mat-autocomplete>
<mat-hint *ngIf="hint">
{{ hint }}
</mat-hint>
<mat-error *ngIf="entityListFormGroup.get('entities').hasError('required')"> <mat-error *ngIf="entityListFormGroup.get('entities').hasError('required')">
{{ requiredText }} {{ requiredText }}
</mat-error> </mat-error>

7
ui-ngx/src/app/shared/components/entity/entity-list.component.ts

@ -38,6 +38,7 @@ import { EntityService } from '@core/http/entity.service';
import { MatAutocomplete } from '@angular/material/autocomplete'; import { MatAutocomplete } from '@angular/material/autocomplete';
import { MatChipGrid } from '@angular/material/chips'; import { MatChipGrid } from '@angular/material/chips';
import { coerceBooleanProperty } from '@angular/cdk/coercion'; import { coerceBooleanProperty } from '@angular/cdk/coercion';
import { SubscriptSizing } from '@angular/material/form-field';
@Component({ @Component({
selector: 'tb-entity-list', selector: 'tb-entity-list',
@ -88,6 +89,12 @@ export class EntityListComponent implements ControlValueAccessor, OnInit, AfterV
@Input() @Input()
disabled: boolean; disabled: boolean;
@Input()
subscriptSizing: SubscriptSizing = 'fixed'
@Input()
hint: string
@ViewChild('entityInput') entityInput: ElementRef<HTMLInputElement>; @ViewChild('entityInput') entityInput: ElementRef<HTMLInputElement>;
@ViewChild('entityAutocomplete') matAutocomplete: MatAutocomplete; @ViewChild('entityAutocomplete') matAutocomplete: MatAutocomplete;
@ViewChild('chipList', {static: true}) chipList: MatChipGrid; @ViewChild('chipList', {static: true}) chipList: MatChipGrid;

6
ui-ngx/src/app/shared/components/time/timeinterval.component.html

@ -40,9 +40,9 @@
</mat-form-field> </mat-form-field>
</section> </section>
</section> </section>
<section class="interval-section" fxLayout="row" fxFlex [fxShow]="!advanced && (isEdit || !hideFlag)"> <section fxLayout="row" fxFlex [fxShow]="!advanced && (isEdit || !hideFlag)">
<mat-form-field fxFlex> <mat-form-field fxFlex [subscriptSizing]="subscriptSizing">
<mat-label translate>{{ predefinedName }}</mat-label> <mat-label *ngIf="predefinedName" translate>{{ predefinedName }}</mat-label>
<mat-select [disabled]="hideFlag || disabled" [(ngModel)]="intervalMs" (ngModelChange)="onIntervalMsChange()" style="min-width: 150px;"> <mat-select [disabled]="hideFlag || disabled" [(ngModel)]="intervalMs" (ngModelChange)="onIntervalMsChange()" style="min-width: 150px;">
<mat-option *ngFor="let interval of intervals" [value]="interval.value"> <mat-option *ngFor="let interval of intervals" [value]="interval.value">
{{ interval.name | translate:interval.translateParams }} {{ interval.name | translate:interval.translateParams }}

4
ui-ngx/src/app/shared/components/time/timeinterval.component.scss

@ -31,10 +31,6 @@
margin-right: 5px; margin-right: 5px;
} }
.interval-section {
min-height: 66px;
}
@media #{$mat-xs} { @media #{$mat-xs} {
min-width: 0; min-width: 0;
width: 100%; width: 100%;

4
ui-ngx/src/app/shared/components/time/timeinterval.component.ts

@ -18,6 +18,7 @@ import { Component, EventEmitter, forwardRef, Input, OnInit, Output } from '@ang
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms'; import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
import { TimeInterval, TimeService } from '@core/services/time.service'; import { TimeInterval, TimeService } from '@core/services/time.service';
import { coerceBooleanProperty } from '@angular/cdk/coercion'; import { coerceBooleanProperty } from '@angular/cdk/coercion';
import { SubscriptSizing } from '@angular/material/form-field';
@Component({ @Component({
selector: 'tb-timeinterval', selector: 'tb-timeinterval',
@ -93,6 +94,9 @@ export class TimeintervalComponent implements OnInit, ControlValueAccessor {
@Input() disabled: boolean; @Input() disabled: boolean;
@Input()
subscriptSizing: SubscriptSizing = 'fixed';
days = 0; days = 0;
hours = 0; hours = 0;
mins = 1; mins = 1;

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

@ -2786,7 +2786,7 @@
"platform-users": "Platform users", "platform-users": "Platform users",
"recipient": "Recipient", "recipient": "Recipient",
"recipient-type": "Recipient type", "recipient-type": "Recipient type",
"recipients-count": "{ count, plural, 1 {1 Recipient} other {# Recipients} }", "recipients-count": "{ count, plural, =1 {1 Recipient} other {# Recipients} }",
"request-status": { "request-status": {
"processing": "Processing", "processing": "Processing",
"scheduled": "Scheduled", "scheduled": "Scheduled",

Loading…
Cancel
Save