Browse Source

UI: Add settings for new recipients type Slack

pull/8046/head
Vladyslav_Prykhodko 4 years ago
parent
commit
7549ec2804
  1. 2
      ui-ngx/src/app/modules/home/components/notification/slack-conversation-autocomplete.component.html
  2. 37
      ui-ngx/src/app/modules/home/components/notification/slack-conversation-autocomplete.component.ts
  3. 7
      ui-ngx/src/app/modules/home/pages/notification-center/notification-table/targets-table-config.ts
  4. 33
      ui-ngx/src/app/modules/home/pages/notification-center/targets-table/target-notification-dialog.component.html
  5. 9
      ui-ngx/src/app/modules/home/pages/notification-center/targets-table/target-notification-dialog.componet.scss
  6. 38
      ui-ngx/src/app/modules/home/pages/notification-center/targets-table/target-notification-dialog.componet.ts
  7. 30
      ui-ngx/src/app/modules/home/pages/notification-center/template-table/template-notification-dialog.component.html
  8. 10
      ui-ngx/src/app/modules/home/pages/notification-center/template-table/template-notification-dialog.component.ts
  9. 11
      ui-ngx/src/app/shared/models/notification.models.ts
  10. 5
      ui-ngx/src/assets/locale/locale.constant-en_US.json

2
ui-ngx/src/app/modules/home/components/notification/slack-conversation-autocomplete.component.html

@ -31,7 +31,7 @@
</button> </button>
<mat-autocomplete class="tb-autocomplete" <mat-autocomplete class="tb-autocomplete"
#slackAutocomplete="matAutocomplete" #slackAutocomplete="matAutocomplete"
[displayWith]="displayTemplateFn" [displayWith]="displaySlackConversationFn"
> >
<mat-option *ngFor="let template of slackConversation$ | async" [value]="template" class="template-option"> <mat-option *ngFor="let template of slackConversation$ | async" [value]="template" class="template-option">
<span [innerHTML]="template.name | highlight:slackSearchText"></span> <span [innerHTML]="template.name | highlight:slackSearchText"></span>

37
ui-ngx/src/app/modules/home/components/notification/slack-conversation-autocomplete.component.ts

@ -17,21 +17,11 @@
import { Component, ElementRef, forwardRef, Input, OnChanges, OnInit, SimpleChanges, ViewChild } from '@angular/core'; import { Component, ElementRef, forwardRef, Input, OnChanges, OnInit, SimpleChanges, ViewChild } 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 { import { debounceTime, map, publishReplay, refCount, share, switchMap, tap } from 'rxjs/operators';
debounceTime,
distinctUntilChanged,
map,
publishReplay,
refCount,
share,
switchMap,
tap
} from 'rxjs/operators';
import { Store } from '@ngrx/store'; import { Store } from '@ngrx/store';
import { AppState } from '@core/core.state'; import { AppState } from '@core/core.state';
import { TranslateService } from '@ngx-translate/core'; import { TranslateService } from '@ngx-translate/core';
import { coerceBooleanProperty } from '@angular/cdk/coercion'; import { coerceBooleanProperty } from '@angular/cdk/coercion';
import { EntityId } from '@shared/models/id/entity-id';
import { EntityService } from '@core/http/entity.service'; import { EntityService } from '@core/http/entity.service';
import { TruncatePipe } from '@shared/pipe/truncate.pipe'; import { TruncatePipe } from '@shared/pipe/truncate.pipe';
import { import {
@ -84,7 +74,7 @@ export class SlackConversationAutocompleteComponent implements ControlValueAcces
slackSearchText = ''; slackSearchText = '';
private modelValue: string | null; private modelValue: SlackConversation | null;
private dirty = false; private dirty = false;
private latestSearchConversetionResult: Array<SlackConversation> = null; private latestSearchConversetionResult: Array<SlackConversation> = null;
private slackConversetionFetchObservable$: Observable<Array<SlackConversation>> = null; private slackConversetionFetchObservable$: Observable<Array<SlackConversation>> = null;
@ -122,7 +112,7 @@ export class SlackConversationAutocompleteComponent implements ControlValueAcces
if (typeof value === 'string' || !value) { if (typeof value === 'string' || !value) {
modelValue = null; modelValue = null;
} else { } else {
modelValue = value.id; modelValue = value;
} }
this.updateView(modelValue); this.updateView(modelValue);
if (value === null) { if (value === null) {
@ -160,22 +150,11 @@ export class SlackConversationAutocompleteComponent implements ControlValueAcces
return (text && text.length > 0); return (text && text.length > 0);
} }
writeValue(value: EntityId | null): void { writeValue(value: SlackConversation | null): void {
this.slackSearchText = ''; this.slackSearchText = '';
if (value != null) { if (value != null) {
// this.notificationService.getNotificationTemplateById(value.id, {ignoreLoading: true, ignoreErrors: true}).subscribe( this.modelValue = value;
// (entity) => { this.conversationSlackFormGroup.get('conversation').patchValue(value, {emitEvent: false});
// this.modelValue = entity.id;
// this.conversationSlackFormGroup.get('conversation').patchValue(entity, {emitEvent: false});
// },
// () => {
// this.modelValue = null;
// this.conversationSlackFormGroup.get('conversation').patchValue('', {emitEvent: false});
// if (value !== null) {
// this.propagateChange(this.modelValue);
// }
// }
// );
} else { } else {
this.modelValue = null; this.modelValue = null;
this.conversationSlackFormGroup.get('conversation').patchValue('', {emitEvent: false}); this.conversationSlackFormGroup.get('conversation').patchValue('', {emitEvent: false});
@ -190,14 +169,14 @@ export class SlackConversationAutocompleteComponent implements ControlValueAcces
} }
} }
updateView(value: string | null) { updateView(value: SlackConversation | null) {
if (!isEqual(this.modelValue, value)) { if (!isEqual(this.modelValue, value)) {
this.modelValue = value; this.modelValue = value;
this.propagateChange(this.modelValue); this.propagateChange(this.modelValue);
} }
} }
displayTemplateFn(slackConversation?: SlackConversation): string | undefined { displaySlackConversationFn(slackConversation?: SlackConversation): string | undefined {
return slackConversation ? slackConversation.name : undefined; return slackConversation ? slackConversation.name : undefined;
} }

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

@ -62,9 +62,10 @@ export class TargetsTableConfig extends EntityTableConfig<NotificationTarget> {
this.columns.push( this.columns.push(
new EntityTableColumn<NotificationTarget>('name', 'notification.notification-target', '20%'), new EntityTableColumn<NotificationTarget>('name', 'notification.notification-target', '20%'),
new EntityTableColumn<NotificationTarget>('type', 'notification.type', '40%', new EntityTableColumn<NotificationTarget>('configuration.type', 'notification.type', '40%',
(target) => this.translate.instant(NotificationTargetTypeTranslationMap.get(target.type))), (target) => this.translate.instant(NotificationTargetTypeTranslationMap.get(target.configuration.type)),
new EntityTableColumn<NotificationTarget>('configuration.description', 'notification.description', '40%', () => ({}), false),
new EntityTableColumn<NotificationTarget>('configuration.description', 'notification.description', '40%',
(target) => target.configuration.description || '', (target) => target.configuration.description || '',
() => ({}), false) () => ({}), false)
); );

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

@ -36,18 +36,19 @@
{{ 'notification.target-name-required' | translate }} {{ 'notification.target-name-required' | translate }}
</mat-error> </mat-error>
</mat-form-field> </mat-form-field>
<mat-radio-group formControlName="type">
<mat-radio-button *ngFor="let notificationTargetType of notificationTargetTypes" [value]="notificationTargetType">
<div fxLayout="column">
<div>{{ notificationTargetTypeTranslationMap.get(notificationTargetType) | translate }}</div>
</div>
</mat-radio-button>
</mat-radio-group>
<section formGroupName="configuration"> <section formGroupName="configuration">
<label class="tb-title">{{ 'notification.type' | translate }}</label>
<mat-radio-group formControlName="type">
<mat-radio-button *ngFor="let notificationTargetType of notificationTargetTypes" [value]="notificationTargetType">
<div fxLayout="column">
<div>{{ notificationTargetTypeTranslationMap.get(notificationTargetType) | translate }}</div>
</div>
</mat-radio-button>
</mat-radio-group>
<section formGroupName="usersFilter" <section formGroupName="usersFilter"
*ngIf="targetNotificationForm.get('type').value === notificationTargetType.PLATFORM_USERS"> *ngIf="targetNotificationForm.get('configuration.type').value === notificationTargetType.PLATFORM_USERS">
<mat-form-field class="mat-block"> <mat-form-field class="mat-block">
<mat-label translate>notification.target-type.type</mat-label> <mat-label translate>notification.target-type.user-filters</mat-label>
<mat-select formControlName="type"> <mat-select formControlName="type">
<mat-option *ngFor="let type of notificationTargetConfigTypes" [value]="type"> <mat-option *ngFor="let type of notificationTargetConfigTypes" [value]="type">
{{ notificationTargetConfigTypeTranslateMap.get(type) | translate }} {{ notificationTargetConfigTypeTranslateMap.get(type) | translate }}
@ -76,6 +77,20 @@
</tb-entity-autocomplete> </tb-entity-autocomplete>
</section> </section>
</section> </section>
<section *ngIf="targetNotificationForm.get('configuration.type').value === notificationTargetType.SLACK">
<label class="tb-title">{{ 'notification.recipient-type' | translate }}</label>
<mat-radio-group formControlName="conversationType">
<mat-radio-button *ngFor="let slackChanelType of slackChanelTypes" [value]="slackChanelType">
<div fxLayout="column">
<div>{{ slackChanelTypesTranslateMap.get(slackChanelType) | translate }}</div>
</div>
</mat-radio-button>
</mat-radio-group>
<tb-slack-conversation-autocomplete
formControlName="conversation" required
[slackChanelType]="targetNotificationForm.get('configuration.conversationType').value">
</tb-slack-conversation-autocomplete>
</section>
<mat-form-field class="mat-block"> <mat-form-field class="mat-block">
<mat-label translate>notification.description</mat-label> <mat-label translate>notification.description</mat-label>
<input matInput formControlName="description"> <input matInput formControlName="description">

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

@ -15,11 +15,18 @@
*/ */
@import "../../../../../../theme"; @import "../../../../../../theme";
:host {
.tb-title {
display: block;
padding-bottom: 6px;
}
}
:host ::ng-deep { :host ::ng-deep {
.mat-radio-group { .mat-radio-group {
display: flex; display: flex;
flex-direction: row; flex-direction: row;
margin-bottom: 8px; margin-bottom: 14px;
.mat-radio-button { .mat-radio-button {
flex: 1 1 100%; flex: 1 1 100%;

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

@ -19,7 +19,9 @@ import {
NotificationTargetConfigType, NotificationTargetConfigType,
NotificationTargetConfigTypeTranslateMap, NotificationTargetConfigTypeTranslateMap,
NotificationTargetType, NotificationTargetType,
NotificationTargetTypeTranslationMap NotificationTargetTypeTranslationMap,
SlackChanelType,
SlackChanelTypesTranslateMap
} from '@shared/models/notification.models'; } from '@shared/models/notification.models';
import { Component, Inject, OnDestroy } from '@angular/core'; import { Component, Inject, OnDestroy } from '@angular/core';
import { DialogComponent } from '@shared/components/dialog.component'; import { DialogComponent } from '@shared/components/dialog.component';
@ -54,6 +56,9 @@ export class TargetNotificationDialogComponent extends
notificationTargetConfigType = NotificationTargetConfigType; notificationTargetConfigType = NotificationTargetConfigType;
notificationTargetConfigTypes: NotificationTargetConfigType[] = Object.values(NotificationTargetConfigType); notificationTargetConfigTypes: NotificationTargetConfigType[] = Object.values(NotificationTargetConfigType);
notificationTargetConfigTypeTranslateMap = NotificationTargetConfigTypeTranslateMap; notificationTargetConfigTypeTranslateMap = NotificationTargetConfigTypeTranslateMap;
slackChanelTypes = Object.keys(SlackChanelType) as SlackChanelType[];
slackChanelTypesTranslateMap = SlackChanelTypesTranslateMap;
entityType = EntityType; entityType = EntityType;
isAdd = true; isAdd = true;
@ -73,18 +78,38 @@ export class TargetNotificationDialogComponent extends
this.targetNotificationForm = this.fb.group({ this.targetNotificationForm = this.fb.group({
name: [null, Validators.required], name: [null, Validators.required],
type: [NotificationTargetType.PLATFORM_USERS],
configuration: this.fb.group({ configuration: this.fb.group({
description: [null], type: [NotificationTargetType.PLATFORM_USERS],
usersFilter: this.fb.group({ usersFilter: this.fb.group({
type: [NotificationTargetConfigType.ALL_USERS], type: [NotificationTargetConfigType.ALL_USERS],
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],
getCustomerIdFromOriginatorEntity: [{value: false, disabled: true}] getCustomerIdFromOriginatorEntity: [{value: false, disabled: true}]
}) }),
conversationType: [{value: SlackChanelType.DIRECT, disabled: true}],
conversation: [{value: '', disabled: true}, Validators.required],
description: [null]
}) })
}); });
this.targetNotificationForm.get('configuration.type').valueChanges.pipe(
takeUntil(this.destroy$)
).subscribe((type: NotificationTargetType) => {
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});
break;
case NotificationTargetType.SLACK:
this.targetNotificationForm.get('configuration.conversationType').enable({emitEvent: false});
this.targetNotificationForm.get('configuration.conversation').enable({emitEvent: false});
break;
}
this.targetNotificationForm.get('configuration.type').enable({emitEvent: false});
this.targetNotificationForm.get('configuration.description').enable({emitEvent: false});
});
this.targetNotificationForm.get('configuration.usersFilter.type').valueChanges.pipe( this.targetNotificationForm.get('configuration.usersFilter.type').valueChanges.pipe(
takeUntil(this.destroy$) takeUntil(this.destroy$)
).subscribe((type: NotificationTargetConfigType) => { ).subscribe((type: NotificationTargetConfigType) => {
@ -111,8 +136,7 @@ export class TargetNotificationDialogComponent extends
if (isDefined(data.target)) { if (isDefined(data.target)) {
this.targetNotificationForm.patchValue(data.target, {emitEvent: false}); this.targetNotificationForm.patchValue(data.target, {emitEvent: false});
this.targetNotificationForm.get('type').updateValueAndValidity({onlySelf: true}); this.targetNotificationForm.get('configuration.type').updateValueAndValidity({onlySelf: true});
this.targetNotificationForm.get('configuration.usersFilter.type').updateValueAndValidity({onlySelf: true});
} }
} }
@ -131,7 +155,7 @@ export class TargetNotificationDialogComponent extends
if (isDefined(this.data.target)) { if (isDefined(this.data.target)) {
formValue = Object.assign({}, this.data.target, formValue); formValue = Object.assign({}, this.data.target, formValue);
} }
formValue.configuration.type = formValue.type; formValue.type = formValue.configuration.type;
this.notificationService.saveNotificationTarget(formValue).subscribe( this.notificationService.saveNotificationTarget(formValue).subscribe(
(target) => this.dialogRef.close(target) (target) => this.dialogRef.close(target)
); );

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

@ -93,7 +93,11 @@
</mat-form-field> </mat-form-field>
<mat-form-field class="mat-block" floatLabel="always"> <mat-form-field class="mat-block" floatLabel="always">
<mat-label translate>notification.message</mat-label> <mat-label translate>notification.message</mat-label>
<input matInput formControlName="body" [placeholder]="templateNotificationForm.get('configuration.defaultTextTemplate').value"> <textarea matInput
cdkTextareaAutosize
formControlName="body"
[placeholder]="templateNotificationForm.get('configuration.defaultTextTemplate').value">
</textarea>
</mat-form-field> </mat-form-field>
<section formGroupName="additionalConfig"> <section formGroupName="additionalConfig">
<section formGroupName="icon" class="additional-config-group"> <section formGroupName="icon" class="additional-config-group">
@ -155,7 +159,11 @@
<form [formGroup]="smsTemplateForm"> <form [formGroup]="smsTemplateForm">
<mat-form-field class="mat-block" floatLabel="always"> <mat-form-field class="mat-block" floatLabel="always">
<mat-label translate>notification.message</mat-label> <mat-label translate>notification.message</mat-label>
<input matInput formControlName="body" [placeholder]="templateNotificationForm.get('configuration.defaultTextTemplate').value"> <textarea matInput
cdkTextareaAutosize
formControlName="body"
[placeholder]="templateNotificationForm.get('configuration.defaultTextTemplate').value">
</textarea>
</mat-form-field> </mat-form-field>
</form> </form>
</mat-step> </mat-step>
@ -165,20 +173,12 @@
<form [formGroup]="slackTemplateForm" fxLayoutGap="8px"> <form [formGroup]="slackTemplateForm" fxLayoutGap="8px">
<mat-form-field class="mat-block" floatLabel="always"> <mat-form-field class="mat-block" floatLabel="always">
<mat-label translate>notification.message</mat-label> <mat-label translate>notification.message</mat-label>
<input matInput formControlName="body" [placeholder]="templateNotificationForm.get('configuration.defaultTextTemplate').value"> <textarea matInput
cdkTextareaAutosize
formControlName="body"
[placeholder]="templateNotificationForm.get('configuration.defaultTextTemplate').value">
</textarea>
</mat-form-field> </mat-form-field>
<label>{{ 'Recipient type' | translate }}</label>
<mat-radio-group formControlName="conversationType">
<mat-radio-button *ngFor="let slackChanelType of slackChanelTypes" [value]="slackChanelType">
<div fxLayout="column">
<div>{{ slackChanelTypesTranslateMap.get(slackChanelType) | translate }}</div>
</div>
</mat-radio-button>
</mat-radio-group>
<tb-slack-conversation-autocomplete
formControlName="conversationId" required
[slackChanelType]="slackTemplateForm.get('conversationType').value">
</tb-slack-conversation-autocomplete>
</form> </form>
</mat-step> </mat-step>
</mat-horizontal-stepper> </mat-horizontal-stepper>

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

@ -19,9 +19,7 @@ import {
NotificationDeliveryMethodTranslateMap, NotificationDeliveryMethodTranslateMap,
NotificationTemplate, NotificationTemplate,
NotificationTemplateTypeTranslateMap, NotificationTemplateTypeTranslateMap,
NotificationType, NotificationType
SlackChanelType,
SlackChanelTypesTranslateMap
} from '@shared/models/notification.models'; } from '@shared/models/notification.models';
import { Component, Inject, OnDestroy, ViewChild } from '@angular/core'; import { Component, Inject, OnDestroy, ViewChild } from '@angular/core';
import { DialogComponent } from '@shared/components/dialog.component'; import { DialogComponent } from '@shared/components/dialog.component';
@ -66,11 +64,9 @@ export class TemplateNotificationDialogComponent
dialogTitle = 'notification.edit-notification-template'; dialogTitle = 'notification.edit-notification-template';
notificationTypes = Object.keys(NotificationType) as NotificationType[]; notificationTypes = Object.keys(NotificationType) as NotificationType[];
slackChanelTypes = Object.keys(SlackChanelType) as SlackChanelType[];
notificationDeliveryMethods = Object.keys(NotificationDeliveryMethod) as NotificationDeliveryMethod[]; notificationDeliveryMethods = Object.keys(NotificationDeliveryMethod) as NotificationDeliveryMethod[];
notificationTemplateTypeTranslateMap = NotificationTemplateTypeTranslateMap; notificationTemplateTypeTranslateMap = NotificationTemplateTypeTranslateMap;
notificationDeliveryMethodTranslateMap = NotificationDeliveryMethodTranslateMap; notificationDeliveryMethodTranslateMap = NotificationDeliveryMethodTranslateMap;
slackChanelTypesTranslateMap = SlackChanelTypesTranslateMap;
selectedIndex = 0; selectedIndex = 0;
@ -168,9 +164,7 @@ export class TemplateNotificationDialogComponent
}); });
this.slackTemplateForm = this.fb.group({ this.slackTemplateForm = this.fb.group({
body: [''], body: ['']
conversationId: ['', Validators.required],
conversationType: [SlackChanelType.DIRECT]
}); });
this.deliveryMethodFormsMap = new Map<NotificationDeliveryMethod, FormGroup>([ this.deliveryMethodFormsMap = new Map<NotificationDeliveryMethod, FormGroup>([

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

@ -147,9 +147,8 @@ interface CustomerUsersNotificationTargetConfig {
} }
export interface SlackNotificationTargetConfig { export interface SlackNotificationTargetConfig {
conversationType: SlackConversation; conversationType: SlackChanelType;
conversationId: string; conversation: SlackConversation;
conversationName: string;
} }
export enum NotificationTargetType { export enum NotificationTargetType {
PLATFORM_USERS = 'PLATFORM_USERS', PLATFORM_USERS = 'PLATFORM_USERS',
@ -242,9 +241,9 @@ export enum NotificationRequestStatus {
} }
export const NotificationRequestStatusTranslateMap = new Map<NotificationRequestStatus, string>([ export const NotificationRequestStatusTranslateMap = new Map<NotificationRequestStatus, string>([
[NotificationRequestStatus.PROCESSING, 'notification.requet-status.processing'], [NotificationRequestStatus.PROCESSING, 'notification.request-status.processing'],
[NotificationRequestStatus.SCHEDULED, 'notification.requet-status.scheduled'], [NotificationRequestStatus.SCHEDULED, 'notification.request-status.scheduled'],
[NotificationRequestStatus.SENT, 'notification.requet-status.sent'] [NotificationRequestStatus.SENT, 'notification.request-status.sent']
]); ]);
export enum SlackChanelType { export enum SlackChanelType {

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

@ -2725,8 +2725,9 @@
"notification-center": "Notification center", "notification-center": "Notification center",
"notification-target": "Notification recipient", "notification-target": "Notification recipient",
"notify-again": "Notify again", "notify-again": "Notify again",
"recipient-type": "Recipient type",
"recipients-count": "{ count, plural, 1 {1 Recipient} other {# Recipients} }", "recipients-count": "{ count, plural, 1 {1 Recipient} other {# Recipients} }",
"requet-status": { "request-status": {
"processing": "Processing", "processing": "Processing",
"scheduled": "Scheduled", "scheduled": "Scheduled",
"sent": "Sent" "sent": "Sent"
@ -2759,7 +2760,7 @@
"target-type": { "target-type": {
"all-users": "All users", "all-users": "All users",
"customer-users": "Customer users", "customer-users": "Customer users",
"type": "Type", "user-filters": "User filter",
"user-list": "User list" "user-list": "User list"
}, },
"targets": "Recipients", "targets": "Recipients",

Loading…
Cancel
Save