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-content">
<div class="tabs-container">
<mat-tab-group #matTabGroup (selectedIndexChange)="updateData()">
<mat-tab label="{{ 'notification.inbox' | translate }}">
<tb-notification-table
[notificationType]="entityType.NOTIFICATION">
</tb-notification-table>
</mat-tab>
<mat-tab label="{{ 'notification.sent' | translate }}" #requestTab="matTab">
<tb-notification-table
#notificationRequest
[notificationType]="entityType.NOTIFICATION_REQUEST">
</tb-notification-table>
</mat-tab>
<mat-tab label="{{ 'notification.templates' | translate }}">
<tb-notification-table
[notificationType]="entityType.NOTIFICATION_TEMPLATE">
</tb-notification-table>
</mat-tab>
<mat-tab label="{{ 'notification.targets' | translate }}">
<tb-notification-table
[notificationType]="entityType.NOTIFICATION_TARGET">
</tb-notification-table>
</mat-tab>
<mat-tab label="{{ 'notification.rules' | translate }}">
<tb-notification-table
[notificationType]="entityType.NOTIFICATION_RULE">
</tb-notification-table>
</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 }}
<ng-container *ngIf="isCustomerUser(); else notificationTabs">
<tb-notification-table
[notificationType]="entityType.NOTIFICATION">
</tb-notification-table>
</ng-container>
<ng-template #notificationTabs>
<mat-tab-group #matTabGroup (selectedIndexChange)="updateData()" mat-stretch-tabs="false">
<mat-tab label="{{ 'notification.inbox' | translate }}">
<tb-notification-table
[notificationType]="entityType.NOTIFICATION">
</tb-notification-table>
</mat-tab>
<mat-tab label="{{ 'notification.sent' | translate }}" #requestTab="matTab">
<tb-notification-table
#notificationRequest
[notificationType]="entityType.NOTIFICATION_REQUEST">
</tb-notification-table>
</mat-tab>
<mat-tab label="{{ 'notification.templates' | translate }}">
<tb-notification-table
[notificationType]="entityType.NOTIFICATION_TEMPLATE">
</tb-notification-table>
</mat-tab>
<mat-tab label="{{ 'notification.targets' | translate }}">
<tb-notification-table
[notificationType]="entityType.NOTIFICATION_TARGET">
</tb-notification-table>
</mat-tab>
<mat-tab label="{{ 'notification.rules' | translate }}" *ngIf="isTenantAdmin()">
<tb-notification-table
[notificationType]="entityType.NOTIFICATION_RULE">
</tb-notification-table>
</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>
</button>
</div>
</ng-template>
</mat-tab>
</mat-tab-group>
</ng-template>
</mat-tab>
</mat-tab-group>
</ng-template>
</div>
</div>
</div>

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

@ -34,22 +34,6 @@
display: flex;
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 {
position: relative;
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 {
.tabs-container {
.mat-tab-group {
> .mat-tab-body-wrapper {
> .mat-mdc-tab-group {
> .mat-mdc-tab-body-wrapper {
position: absolute;
top: 49px;
left: 0;
right: 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;
width: 100%;
//width: 100%;
.mat-tab-label-content {
width: 100%;
@ -106,21 +75,21 @@
height: 56px;
}
.mat-toolbar-single-row {
padding: 0 24px 0 12px;
.mat-toolbar-tools > div {
width: 100%;
}
.title-container {
width: 100%;
.mat-toolbar-single-row {
padding: 0 24px 0 12px;
}
}
}
@media #{$mat-xs} {
.tabs-container {
.mat-tab-group {
> .mat-tab-header {
.mat-tab-label {
> .mat-mdc-tab-group {
> .mat-mdc-tab-header {
.mat-mdc-tab {
&.mat-tab-disabled {
width: auto;
}

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

@ -23,6 +23,10 @@ import {
NotificationTableComponent
} from '@home/pages/notification-center/notification-table/notification-table.component';
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({
selector: 'tb-notification-center',
@ -31,11 +35,14 @@ import { EntityType } from '@shared/models/entity-type.models';
})
export class NotificationCenterComponent extends PageComponent {
private authState: AuthState = getCurrentAuthState(this.store);
private authUser: AuthUser = this.authState.authUser;
entityType = EntityType;
@ViewChild('matTabGroup', {static: true}) matTabs: MatTabGroup;
@ViewChild('requestTab', {static: true}) requestTab: MatTab;
@ViewChild('notificationRequest', {static: true}) notificationRequestTable: NotificationTableComponent;
@ViewChild('matTabGroup') matTabs: MatTabGroup;
@ViewChild('requestTab') requestTab: MatTab;
@ViewChild('notificationRequest') notificationRequestTable: NotificationTableComponent;
@ViewChildren(NotificationTableComponent) tableComponent: QueryList<NotificationTableComponent>;
@ -59,4 +66,12 @@ export class NotificationCenterComponent extends PageComponent {
sendNotification($event: Event) {
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>
<section formGroupName="template">
<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>
<input matInput formControlName="notificationSubject" required>
<mat-error *ngIf="notificationRequestForm.get('template.configuration.notificationSubject').hasError('required')">
@ -63,7 +63,7 @@
</mat-error>
<mat-hint>{{ notificationTemplateTypeTranslateMap.get(notificationType.GENERAL).hint | translate }}</mat-hint>
</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>
<input matInput formControlName="defaultTextTemplate" 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')}">
{{ "notification.delivery-methods" | translate }}
</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"
[formGroupName]="deliveryMethods" fxFlex="50%" [ngClass]={even:isEven}>
<mat-slide-toggle class="delivery-method" formControlName="enabled">
@ -97,7 +97,7 @@
<button #createTargetButton
mat-button color="primary" matSuffix
(click)="createTarget($event, createTargetButton)">
{{ 'notification.create-new' | translate }}
<span style="white-space: nowrap">{{ 'notification.create-new' | translate }}</span>
</button>
</tb-entity-list>
<section formGroupName="additionalConfig" class="additional-config-group">
@ -146,7 +146,8 @@
<mat-slide-toggle formControlName="enabled" class="toggle">
{{ 'icon.icon' | translate }}
</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>
<tb-color-input formControlName="color" fxFlex>
@ -158,7 +159,7 @@
{{ 'notification.action-button' | translate }}
</mat-slide-toggle>
<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-label translate>notification.button-text</mat-label>
<input matInput formControlName="text" required>
@ -169,8 +170,8 @@
<tb-color-input formControlName="color" fxFlex>
</tb-color-input>
</div>
<div fxLayout="row" fxLayoutGap="8px">
<mat-form-field fxFlex="30">
<div fxLayout="row" fxLayoutGap.gt-xs="8px" fxLayout.xs="column">
<mat-form-field fxFlex="30" fxFlex.xs="100">
<mat-label translate>notification.action-type</mat-label>
<mat-select formControlName="linkType">
<mat-option *ngFor="let actionButtonLinkType of actionButtonLinkTypes" [value]="actionButtonLinkType">
@ -188,11 +189,11 @@
</mat-form-field>
<ng-template #dashboardSelector>
<tb-dashboard-autocomplete
fxFlex="35"
fxFlex="35" fxFlex.xs="100"
required
formControlName="dashboardId">
</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"
formControlName="dashboardState">
</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 "../../../../../../theme";
:host-context(.tb-fullscreen-dialog .mat-dialog-container) {
:host-context(.tb-fullscreen-dialog .mat-mdc-dialog-container) {
width: 800px;
height: 100%;
max-width: 100%;
max-height: 100vh;
display: flex;
flex-direction: column;
.tb-form-fields {
margin-bottom: 8px;
@ -70,11 +74,7 @@
border-radius: 4px;
&.notification {
background-color: #F3F6FA; //map_get($tb-mat-indigo, 50);
}
.mat-icon {
color: rgba(0, 0, 0, 0.38);
background-color: #F3F6FA;
}
.group-title {
@ -135,16 +135,10 @@
}
}
}
@media #{$mat-gt-xs} {
.mat-dialog-content {
max-height: 75vh;
}
}
}
:host ::ng-deep {
.mat-dialog-content {
.mat-mdc-dialog-content {
display: flex;
flex-direction: column;
height: 100%;
@ -159,15 +153,6 @@
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 {
height: 600px;
max-height: 100%;
@ -178,10 +163,6 @@
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 {
.notification-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) {
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'));
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-label translate>alarm.alarm-severity-list</mat-label>
<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"
(removed)="onSeverityRemoved(severity)">
{{ 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;
alarmSeverityTranslationMap = alarmSeverityTranslations;
private alarmSeverities = Object.keys(AlarmSeverity);
private alarmSeveritiesValues = Object.keys(AlarmSeverity) as Array<AlarmSeverity>;
alarmSeverity = AlarmSeverity;
alarmSeverities: Array<AlarmSeverity> = []
readonly separatorKeysCodes: number[] = [ENTER, COMMA, SEMICOLON];
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 = '';
if (value != null && value.length > 0) {
this.modelValue = [...value];
this.alarmSeverities = [...value];
this.alarmSeveritiesForm.get('alarmSeverities').setValue(value);
} else {
this.alarmSeverities = [];
this.alarmSeveritiesForm.get('alarmSeverities').setValue(null);
this.modelValue = null;
}
@ -141,13 +145,14 @@ export class AlarmSeveritiesListComponent implements ControlValueAccessor{
}
}
private addSeverity(alarmSeverity: string) {
private addSeverity(alarmSeverity: AlarmSeverity) {
if (alarmSeverity) {
if (!this.modelValue || this.modelValue.indexOf(alarmSeverity) === -1) {
if (!this.modelValue) {
this.modelValue = [];
}
this.modelValue.push(alarmSeverity);
this.alarmSeverities.push(alarmSeverity);
this.alarmSeveritiesForm.get('alarmSeverities').setValue(this.modelValue);
}
this.propagateChange(this.modelValue);
@ -164,6 +169,7 @@ export class AlarmSeveritiesListComponent implements ControlValueAccessor{
const index = this.modelValue.indexOf(alarmSeverity);
if (index >= 0) {
this.modelValue.splice(index, 1);
this.alarmSeverities.splice(index, 1);
if (!this.modelValue.length) {
this.modelValue = null;
}
@ -189,9 +195,9 @@ export class AlarmSeveritiesListComponent implements ControlValueAccessor{
return (text && text.length > 0);
}
private fetchSeverities(searchText?: string): Array<string> {
private fetchSeverities(searchText?: string): Array<AlarmSeverity> {
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)) {
const search = this.searchText.toUpperCase();
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">
<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>
<ng-template #selectTime>
<div fxFlex fxLayout="row" fxLayout.xs="column" fxLayoutAlign="center center">
<span translate>notification.after</span>
<tb-timeinterval
formControlName="delayInSec"
min="{{ 0 }}"
max="{{ 604800000 }}"
disabledAdvanced></tb-timeinterval>
<span fxFlex class="escalation-notify" translate>notification.notify</span>
</div>
</ng-template>
<!-- </div>-->
<div fxFlex *ngIf="systemEscalation; else selectTime" translate>notification.first-recipient</div>
<ng-template #selectTime>
<div fxFlex fxLayout="row" fxLayout.xs="column" fxLayoutAlign="center center">
<span translate>notification.after</span>
<tb-timeinterval
subscriptSizing="dynamic"
formControlName="delayInSec"
min="{{ 0 }}"
max="{{ 604800000 }}"
disabledAdvanced></tb-timeinterval>
<span fxFlex class="escalation-notify" translate>notification.notify</span>
</div>
</ng-template>
<tb-entity-list
required
fxFlex="60"
formControlName="targets"
subscriptSizing="dynamic"
[entityType]="entityType.NOTIFICATION_TARGET"
placeholderText="{{ 'notification.add-target' | translate }}">
<button #createTargetButton
mat-button [fxHide]="disabled" matSuffix
(click)="createTarget($event, createTargetButton)">
{{ 'notification.create-new' | translate }}
<span style="white-space: nowrap">{{ 'notification.create-new' | translate }}</span>
</button>
</tb-entity-list>
</div>

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

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

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

@ -18,13 +18,11 @@
:host {
width: 700px;
height: 100%;
max-width: 100%;
max-height: 100vh;
@media #{$mat-gt-xs} {
.mat-dialog-content {
max-height: 75vh;
}
}
display: flex;
flex-direction: column;
.tb-hint {
margin-top: -1.25em;
@ -53,7 +51,7 @@
::ng-deep {
.mat-dialog-content {
.mat-mdc-dialog-content {
display: flex;
flex-direction: column;
height: 100%;
@ -68,17 +66,6 @@
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 {
height: 550px;
max-height: 100%;
@ -89,11 +76,6 @@
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({
triggerConfig: this.fb.group({
alarmTypes: [null],
alarmSeverities: [null, Validators.required],
alarmSeverities: [null],
clearRule: this.fb.group({
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 {
.mat-radio-group {
.mat-mdc-radio-group {
display: flex;
flex-direction: row;
margin-bottom: 14px;
gap: 8px;
.mat-radio-button {
.mat-mdc-radio-button {
flex: 1 1 100%;
padding: 14px;
padding: 4px;
border: 1px solid rgba(0, 0, 0, 0.12);
border-radius: 6px;
&.mat-radio-checked {
&.mat-mdc-radio-checked {
border-color: map_get($tb-accent, 500);
}
}
}
@media #{$mat-xs} {
.mat-radio-group {
.mat-mdc-radio-group {
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 { Subject } from 'rxjs';
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 {
target?: NotificationTarget;
@ -49,6 +53,9 @@ export interface TargetsNotificationDialogData {
export class TargetNotificationDialogComponent extends
DialogComponent<TargetNotificationDialogComponent, NotificationTarget> implements OnDestroy {
private authState: AuthState = getCurrentAuthState(this.store);
private authUser: AuthUser = this.authState.authUser;
targetNotificationForm: FormGroup;
notificationTargetType = NotificationTargetType;
notificationTargetTypes: NotificationTargetType[] = Object.values(NotificationTargetType);
@ -81,7 +88,7 @@ export class TargetNotificationDialogComponent extends
configuration: this.fb.group({
type: [NotificationTargetType.PLATFORM_USERS],
usersFilter: this.fb.group({
type: [NotificationTargetConfigType.ALL_USERS],
type: [{value: NotificationTargetConfigType.ALL_USERS, disabled: !this.isTenantAdmin()}],
usersIds: [{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});
switch (type) {
case NotificationTargetType.PLATFORM_USERS:
this.targetNotificationForm.get('configuration.usersFilter').enable({emitEvent: false});
this.targetNotificationForm.get('configuration.usersFilter.type').updateValueAndValidity({onlySelf: true});
if (this.isTenantAdmin()) {
this.targetNotificationForm.get('configuration.usersFilter').enable({emitEvent: false});
this.targetNotificationForm.get('configuration.usersFilter.type').updateValueAndValidity({onlySelf: true});
}
break;
case NotificationTargetType.SLACK:
this.targetNotificationForm.get('configuration.conversationType').enable({emitEvent: false});
@ -149,4 +158,8 @@ export class TargetNotificationDialogComponent extends
(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
*ngIf="allowCreate && !selectTemplateFormGroup.get('templateName').value && !disabled"
(click)="createTemplate($event, createTemplateButton)">
{{ 'notification.create-new' | translate }}
<span style="white-space: nowrap">{{ 'notification.create-new' | translate }}</span>
</button>
<mat-autocomplete class="tb-autocomplete"
#templateAutocomplete="matAutocomplete"
@ -41,11 +41,11 @@
>
<mat-option *ngFor="let template of filteredTemplate | async" [value]="template" class="template-option">
<span class="template-option-name" [innerHTML]="template.name | highlight:searchText"></span>
<mat-chip-grid>
<mat-chip-row disabled *ngFor="let method of template.configuration.deliveryMethodsTemplates | keyvalue">
<mat-chip-set>
<mat-chip disabled *ngFor="let method of template.configuration.deliveryMethodsTemplates | keyvalue">
{{ notificationDeliveryMethodTranslateMap.get(method.key) | translate }}
</mat-chip-row>
</mat-chip-grid>
</mat-chip>
</mat-chip-set>
</mat-option>
<mat-option *ngIf="!(filteredTemplate | async)?.length" [value]="null" class="tb-not-found">
<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
* limitations under the License.
*/
::ng-deep {
.template-option {
.mat-option-text {
display: flex;
flex-direction: row;
align-items: center;
margin-bottom: 4px;
}
.template-option-name {
margin-right: 8px;
}
.template-option {
.mdc-list-item__primary-text {
display: flex;
flex-direction: row;
align-items: center;
}
.mat-chip {
&.mat-standard-chip {
padding: 4px 8px;
border-radius: 14px;
min-height: 28px;
.template-option-name {
margin-right: 8px;
}
&.mat-chip-disabled {
opacity: 1;
}
}
}
.mat-mdc-standard-chip.mdc-evolution-chip--disabled {
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.
///
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 { Observable, of } from 'rxjs';
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',
templateUrl: './template-autocomplete.component.html',
styleUrls: ['./template-autocomplete.component.scss'],
encapsulation: ViewEncapsulation.None,
providers: [{
provide: NG_VALUE_ACCESSOR,
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(
takeUntil(this.destroy$)
).subscribe((value) => {
if (value === ActionButtonLinkType.LINK) {
this.pushTemplateForm.get('additionalConfig.actionButtonConfig.link').enable({emitEvent: false});
this.pushTemplateForm.get('additionalConfig.actionButtonConfig.dashboardId').disable({emitEvent: false});
this.pushTemplateForm.get('additionalConfig.actionButtonConfig.dashboardState').disable({emitEvent: false});
} else {
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});
const isEnabled = this.pushTemplateForm.get('additionalConfig.actionButtonConfig.enabled').value;
if (isEnabled) {
if (value === ActionButtonLinkType.LINK) {
this.pushTemplateForm.get('additionalConfig.actionButtonConfig.link').enable({emitEvent: false});
this.pushTemplateForm.get('additionalConfig.actionButtonConfig.dashboardId').disable({emitEvent: false});
this.pushTemplateForm.get('additionalConfig.actionButtonConfig.dashboardState').disable({emitEvent: false});
} else {
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-form-field>
<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>
<input matInput formControlName="notificationSubject" required>
<mat-error *ngIf="templateNotificationForm.get('configuration.notificationSubject').hasError('required')">
@ -60,7 +60,7 @@
</mat-error>
<mat-hint>{{ notificationTemplateTypeTranslateMap.get(templateNotificationForm.get('notificationType').value).hint | translate }}</mat-hint>
</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>
<input matInput formControlName="defaultTextTemplate" required>
<mat-error *ngIf="templateNotificationForm.get('configuration.defaultTextTemplate').hasError('required')">
@ -110,7 +110,8 @@
<mat-slide-toggle formControlName="enabled" class="toggle">
{{ 'icon.icon' | translate }}
</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>
<tb-color-input formControlName="color" fxFlex>
@ -122,7 +123,7 @@
{{ 'notification.action-button' | translate }}
</mat-slide-toggle>
<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-label translate>notification.button-text</mat-label>
<input matInput formControlName="text" required>
@ -133,8 +134,8 @@
<tb-color-input formControlName="color" fxFlex>
</tb-color-input>
</div>
<div fxLayout="row" fxLayoutGap="8px">
<mat-form-field fxFlex="30">
<div fxLayout="row" fxLayoutGap.gt-xs="8px" fxLayout.xs="column">
<mat-form-field fxFlex="30" fxFlex.xs="100">
<mat-label translate>notification.action-type</mat-label>
<mat-select formControlName="linkType">
<mat-option *ngFor="let actionButtonLinkType of actionButtonLinkTypes" [value]="actionButtonLinkType">
@ -152,11 +153,11 @@
</mat-form-field>
<ng-template #dashboardSelector>
<tb-dashboard-autocomplete
fxFlex="35"
fxFlex="35" fxFlex.xs="100"
required
formControlName="dashboardId">
</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"
formControlName="dashboardState">
</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 "../../../../../../theme";
:host-context(.tb-fullscreen-dialog .mat-dialog-container) {
:host-context(.tb-fullscreen-dialog .mat-mdc-dialog-container) {
width: 830px;
height: 100%;
max-width: 100%;
max-height: 100vh;
display: flex;
flex-direction: column;
.tb-form-fields {
margin-bottom: 8px;
@ -66,16 +70,10 @@
margin-bottom: 12px;
}
}
@media #{$mat-gt-xs} {
.mat-dialog-content {
max-height: 75vh;
}
}
}
:host ::ng-deep {
.mat-dialog-content {
.mat-mdc-dialog-content {
display: flex;
flex-direction: column;
height: 100%;
@ -90,15 +88,6 @@
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 {
height: 550px;
max-height: 100%;
@ -109,58 +98,6 @@
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 { TranslateService } from '@ngx-translate/core';
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 {
template?: NotificationTemplate;
@ -56,21 +60,16 @@ export class TemplateNotificationDialogComponent
stepperOrientation: Observable<StepperOrientation>;
templateNotificationForm: FormGroup;
pushTemplateForm: FormGroup;
emailTemplateForm: FormGroup;
smsTemplateForm: FormGroup;
slackTemplateForm: FormGroup;
dialogTitle = 'notification.edit-notification-template';
notificationTypes = Object.keys(NotificationType) as NotificationType[];
notificationDeliveryMethods = Object.keys(NotificationDeliveryMethod) as NotificationDeliveryMethod[];
notificationDeliveryMethodTranslateMap = NotificationDeliveryMethodTranslateMap;
selectedIndex = 0;
hideSelectType = false;
private readonly templateNotification: NotificationTemplate;
private authState: AuthState = getCurrentAuthState(this.store);
private authUser: AuthUser = this.authState.authUser;
constructor(protected store: Store<AppState>,
protected router: Router,
@ -82,7 +81,7 @@ export class TemplateNotificationDialogComponent
private translate: TranslateService) {
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'));
if (isDefinedAndNotNull(this.data?.predefinedType)) {
@ -90,6 +89,10 @@ export class TemplateNotificationDialogComponent
this.templateNotificationForm.get('notificationType').setValue(this.data.predefinedType, {emitEvents: false});
}
if (this.isSysAdmin()) {
this.hideSelectType = true;
}
if (data.isAdd || data.isCopy) {
this.dialogTitle = 'notification.add-notification-template';
}
@ -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.
-->
<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-chip-grid #chipList formControlName="entities">
<mat-chip-row
@ -26,7 +26,6 @@
<mat-icon matChipRemove *ngIf="!disabled">close</mat-icon>
</mat-chip-row>
<input matInput type="text" placeholder="{{ !disabled ? placeholderText : '' }}"
style="max-width: 200px;"
#entityInput
(focusin)="onFocus()"
formControlName="entity"
@ -48,6 +47,9 @@
</span>
</mat-option>
</mat-autocomplete>
<mat-hint *ngIf="hint">
{{ hint }}
</mat-hint>
<mat-error *ngIf="entityListFormGroup.get('entities').hasError('required')">
{{ requiredText }}
</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 { MatChipGrid } from '@angular/material/chips';
import { coerceBooleanProperty } from '@angular/cdk/coercion';
import { SubscriptSizing } from '@angular/material/form-field';
@Component({
selector: 'tb-entity-list',
@ -88,6 +89,12 @@ export class EntityListComponent implements ControlValueAccessor, OnInit, AfterV
@Input()
disabled: boolean;
@Input()
subscriptSizing: SubscriptSizing = 'fixed'
@Input()
hint: string
@ViewChild('entityInput') entityInput: ElementRef<HTMLInputElement>;
@ViewChild('entityAutocomplete') matAutocomplete: MatAutocomplete;
@ViewChild('chipList', {static: true}) chipList: MatChipGrid;

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

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

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

@ -31,10 +31,6 @@
margin-right: 5px;
}
.interval-section {
min-height: 66px;
}
@media #{$mat-xs} {
min-width: 0;
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 { TimeInterval, TimeService } from '@core/services/time.service';
import { coerceBooleanProperty } from '@angular/cdk/coercion';
import { SubscriptSizing } from '@angular/material/form-field';
@Component({
selector: 'tb-timeinterval',
@ -93,6 +94,9 @@ export class TimeintervalComponent implements OnInit, ControlValueAccessor {
@Input() disabled: boolean;
@Input()
subscriptSizing: SubscriptSizing = 'fixed';
days = 0;
hours = 0;
mins = 1;

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

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

Loading…
Cancel
Save