UI: Add copy/edit notification template and notify again
This commit is contained in:
parent
ebb5c634a3
commit
ac9b3303b6
@ -251,6 +251,9 @@ export class EntityService {
|
||||
(id) => this.widgetService.getWidgetsBundle(id, config),
|
||||
entityIds);
|
||||
break;
|
||||
case EntityType.NOTIFICATION_TARGET:
|
||||
observable = of([]);
|
||||
break;
|
||||
}
|
||||
return observable;
|
||||
}
|
||||
|
||||
@ -81,7 +81,12 @@ export class RequestTableConfig extends EntityTableConfig<NotificationRequest, P
|
||||
}
|
||||
|
||||
private configureCellActions(): Array<CellActionDescriptor<NotificationRequestInfo>> {
|
||||
return [];
|
||||
return [{
|
||||
name: this.translate.instant('notification.notify-again'),
|
||||
mdiIcon: 'mdi:repeat-variant',
|
||||
isEnabled: (request) => request.status !== NotificationRequestStatus.SCHEDULED,
|
||||
onAction: ($event, entity) => this.createRequest($event, entity)
|
||||
}];
|
||||
}
|
||||
|
||||
private createRequest($event: Event, request: NotificationRequest, isAdd = false, updateData = true) {
|
||||
|
||||
@ -21,7 +21,7 @@ import {
|
||||
} from '@home/models/entity/entities-table-config.models';
|
||||
import { EntityTypeResource } from '@shared/models/entity-type.models';
|
||||
import { Direction } from '@shared/models/page/sort-order';
|
||||
import { NotificationTemplate } from '@shared/models/notification.models';
|
||||
import { NotificationTemplate, NotificationTemplateTypeTranslateMap } from '@shared/models/notification.models';
|
||||
import { NotificationService } from '@core/http/notification.service';
|
||||
import { EntityAction } from '@home/models/entity/entity-component.models';
|
||||
import { MatDialog } from '@angular/material/dialog';
|
||||
@ -61,7 +61,8 @@ export class TemplateTableConfig extends EntityTableConfig<NotificationTemplate>
|
||||
this.defaultSortOrder = {property: 'notificationType', direction: Direction.ASC};
|
||||
|
||||
this.columns.push(
|
||||
new EntityTableColumn<NotificationTemplate>('notificationType', 'notification.type', '15%'),
|
||||
new EntityTableColumn<NotificationTemplate>('notificationType', 'notification.type', '15%',
|
||||
(template) => this.translate.instant(NotificationTemplateTypeTranslateMap.get(template.notificationType).name)),
|
||||
new EntityTableColumn<NotificationTemplate>('name', 'notification.template', '25%'),
|
||||
new EntityTableColumn<NotificationTemplate>('configuration.notificationSubject', 'notification.subject', '25%',
|
||||
(template) => template.configuration.notificationSubject, () => ({}), false),
|
||||
@ -71,10 +72,22 @@ export class TemplateTableConfig extends EntityTableConfig<NotificationTemplate>
|
||||
}
|
||||
|
||||
private configureCellActions(): Array<CellActionDescriptor<NotificationTemplate>> {
|
||||
return [];
|
||||
return [
|
||||
{
|
||||
name: this.translate.instant('notification.copy-template'),
|
||||
icon: 'content_copy',
|
||||
isEnabled: () => true,
|
||||
onAction: ($event, entity) => this.editTemplate($event, entity, false, true)
|
||||
}, {
|
||||
name: this.translate.instant('notification.edit-template'),
|
||||
icon: 'edit',
|
||||
isEnabled: () => true,
|
||||
onAction: ($event, entity) => this.editTemplate($event, entity)
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
private editTemplate($event: Event, template: NotificationTemplate, isAdd = false) {
|
||||
private editTemplate($event: Event, template: NotificationTemplate, isAdd = false, isCopy = false) {
|
||||
if ($event) {
|
||||
$event.stopPropagation();
|
||||
}
|
||||
@ -84,6 +97,7 @@ export class TemplateTableConfig extends EntityTableConfig<NotificationTemplate>
|
||||
panelClass: ['tb-dialog', 'tb-fullscreen-dialog'],
|
||||
data: {
|
||||
isAdd,
|
||||
isCopy,
|
||||
template
|
||||
}
|
||||
}).afterClosed()
|
||||
|
||||
@ -16,7 +16,7 @@
|
||||
|
||||
-->
|
||||
<mat-toolbar color="primary">
|
||||
<h2 translate>notification.new-notification</h2>
|
||||
<h2>{{ dialogTitle | translate }}</h2>
|
||||
<span fxFlex></span>
|
||||
<button mat-icon-button
|
||||
(click)="cancel()"
|
||||
|
||||
@ -23,7 +23,7 @@ import { Router } from '@angular/router';
|
||||
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
|
||||
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
|
||||
import { NotificationService } from '@core/http/notification.service';
|
||||
import { deepTrim, isDefined } from '@core/utils';
|
||||
import { deepTrim } from '@core/utils';
|
||||
import { Observable, Subject } from 'rxjs';
|
||||
import { EntityType } from '@shared/models/entity-type.models';
|
||||
import { BreakpointObserver } from '@angular/cdk/layout';
|
||||
@ -55,6 +55,8 @@ export class RequestNotificationDialogComponent extends
|
||||
selectedIndex = 0;
|
||||
preview: NotificationRequestPreview = null;
|
||||
|
||||
dialogTitle = 'notification.notify-again';
|
||||
|
||||
private readonly destroy$ = new Subject<void>();
|
||||
|
||||
constructor(protected store: Store<AppState>,
|
||||
@ -66,10 +68,6 @@ export class RequestNotificationDialogComponent extends
|
||||
private notificationService: NotificationService) {
|
||||
super(store, router, dialogRef);
|
||||
|
||||
if (isDefined(data.isAdd)) {
|
||||
this.isAdd = data.isAdd;
|
||||
}
|
||||
|
||||
this.stepperOrientation = this.breakpointObserver.observe(MediaBreakpoints['gt-xs'])
|
||||
.pipe(map(({matches}) => matches ? 'horizontal' : 'vertical'));
|
||||
|
||||
@ -77,6 +75,13 @@ export class RequestNotificationDialogComponent extends
|
||||
templateId: [null, Validators.required],
|
||||
targets: [null, Validators.required]
|
||||
});
|
||||
|
||||
if (data.isAdd) {
|
||||
this.dialogTitle = 'notification.new-notification';
|
||||
}
|
||||
if (data.request) {
|
||||
this.notificationRequestForm.patchValue(this.data.request, {emitEvent: false});
|
||||
}
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
|
||||
@ -28,7 +28,7 @@
|
||||
</mat-progress-bar>
|
||||
<div style="height: 4px;" *ngIf="!(isLoading$ | async)"></div>
|
||||
<div mat-dialog-content>
|
||||
<mat-horizontal-stepper [linear]="true" labelPosition="end" #addNotificationTemplate [orientation]="(stepperOrientation | async)"
|
||||
<mat-horizontal-stepper [linear]="true" labelPosition="end" #notificationTemplateStepper [orientation]="(stepperOrientation | async)"
|
||||
(selectionChange)="changeStep($event)">
|
||||
<ng-template matStepperIcon="edit">
|
||||
<mat-icon>check</mat-icon>
|
||||
|
||||
@ -31,13 +31,14 @@ import { Router } from '@angular/router';
|
||||
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
|
||||
import { FormBuilder, FormGroup, ValidationErrors, Validators } from '@angular/forms';
|
||||
import { NotificationService } from '@core/http/notification.service';
|
||||
import { deepTrim, isDefined } from '@core/utils';
|
||||
import { deepClone, deepTrim } from '@core/utils';
|
||||
import { Observable, Subject } from 'rxjs';
|
||||
import { map, takeUntil } from 'rxjs/operators';
|
||||
import { StepperOrientation, StepperSelectionEvent } from '@angular/cdk/stepper';
|
||||
import { MatStepper } from '@angular/material/stepper';
|
||||
import { BreakpointObserver } from '@angular/cdk/layout';
|
||||
import { MediaBreakpoints } from '@shared/models/constants';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
|
||||
export interface TemplateNotificationDialogData {
|
||||
template?: NotificationTemplate;
|
||||
@ -53,7 +54,7 @@ export interface TemplateNotificationDialogData {
|
||||
export class TemplateNotificationDialogComponent
|
||||
extends DialogComponent<TemplateNotificationDialogComponent, NotificationTemplate> implements OnDestroy {
|
||||
|
||||
@ViewChild('addNotificationTemplate', {static: true}) addNotificationTemplate: MatStepper;
|
||||
@ViewChild('notificationTemplateStepper', {static: true}) notificationTemplateStepper: MatStepper;
|
||||
|
||||
stepperOrientation: Observable<StepperOrientation>;
|
||||
|
||||
@ -63,7 +64,6 @@ export class TemplateNotificationDialogComponent
|
||||
smsTemplateForm: FormGroup;
|
||||
slackTemplateForm: FormGroup;
|
||||
dialogTitle = 'notification.edit-notification-template';
|
||||
saveButtonLabel = 'action.save';
|
||||
|
||||
notificationTypes = Object.keys(NotificationType) as NotificationType[];
|
||||
slackChanelTypes = Object.keys(SlackChanelType) as SlackChanelType[];
|
||||
@ -74,40 +74,33 @@ export class TemplateNotificationDialogComponent
|
||||
|
||||
selectedIndex = 0;
|
||||
|
||||
tinyMceOptions: Record<string, any>;
|
||||
tinyMceOptions: Record<string, any> = {
|
||||
base_url: '/assets/tinymce',
|
||||
suffix: '.min',
|
||||
plugins: ['link table image imagetools code fullscreen'],
|
||||
menubar: 'edit insert tools view format table',
|
||||
toolbar: 'fontselect fontsizeselect | formatselect | bold italic strikethrough forecolor backcolor ' +
|
||||
'| link | table | image | alignleft aligncenter alignright alignjustify ' +
|
||||
'| numlist bullist outdent indent | removeformat | code | fullscreen',
|
||||
height: 400,
|
||||
autofocus: false,
|
||||
branding: false
|
||||
};
|
||||
|
||||
private readonly destroy$ = new Subject<void>();
|
||||
private readonly templateNotification: NotificationTemplate;
|
||||
|
||||
private deliveryMethodFormsMap: Map<NotificationDeliveryMethod, FormGroup>;
|
||||
constructor(protected store: Store<AppState>,
|
||||
protected router: Router,
|
||||
protected dialogRef: MatDialogRef<TemplateNotificationDialogComponent, NotificationTemplate>,
|
||||
@Inject(MAT_DIALOG_DATA) public data: TemplateNotificationDialogData,
|
||||
private breakpointObserver: BreakpointObserver,
|
||||
private fb: FormBuilder,
|
||||
private notificationService: NotificationService) {
|
||||
private notificationService: NotificationService,
|
||||
private translate: TranslateService) {
|
||||
super(store, router, dialogRef);
|
||||
|
||||
if (data.isAdd) {
|
||||
this.dialogTitle = 'notification.add-notification-template';
|
||||
this.saveButtonLabel = 'action.add';
|
||||
}
|
||||
if (data.isCopy) {
|
||||
this.dialogTitle = 'notification.copy-notification-template';
|
||||
}
|
||||
|
||||
this.tinyMceOptions = {
|
||||
base_url: '/assets/tinymce',
|
||||
suffix: '.min',
|
||||
plugins: ['link table image imagetools code fullscreen'],
|
||||
menubar: 'edit insert tools view format table',
|
||||
toolbar: 'fontselect fontsizeselect | formatselect | bold italic strikethrough forecolor backcolor ' +
|
||||
'| link | table | image | alignleft aligncenter alignright alignjustify ' +
|
||||
'| numlist bullist outdent indent | removeformat | code | fullscreen',
|
||||
height: 400,
|
||||
autofocus: false,
|
||||
branding: false
|
||||
};
|
||||
|
||||
this.stepperOrientation = this.breakpointObserver.observe(MediaBreakpoints['gt-xs'])
|
||||
.pipe(map(({matches}) => matches ? 'horizontal' : 'vertical'));
|
||||
|
||||
@ -122,7 +115,7 @@ export class TemplateNotificationDialogComponent
|
||||
});
|
||||
this.notificationDeliveryMethods.forEach(method => {
|
||||
(this.templateNotificationForm.get('configuration.deliveryMethodsTemplates') as FormGroup)
|
||||
.addControl(method, this.fb.group({method, enabled: method === NotificationDeliveryMethod.PUSH}), {emitEvent: false});
|
||||
.addControl(method, this.fb.group({enabled: method === NotificationDeliveryMethod.PUSH}), {emitEvent: false});
|
||||
});
|
||||
|
||||
this.pushTemplateForm = this.fb.group({
|
||||
@ -179,6 +172,30 @@ export class TemplateNotificationDialogComponent
|
||||
conversationId: ['', Validators.required],
|
||||
conversationType: [SlackChanelType.DIRECT]
|
||||
});
|
||||
|
||||
this.deliveryMethodFormsMap = new Map<NotificationDeliveryMethod, FormGroup>([
|
||||
[NotificationDeliveryMethod.PUSH, this.pushTemplateForm],
|
||||
[NotificationDeliveryMethod.EMAIL, this.emailTemplateForm],
|
||||
[NotificationDeliveryMethod.SMS, this.smsTemplateForm],
|
||||
[NotificationDeliveryMethod.SLACK, this.slackTemplateForm]
|
||||
]);
|
||||
|
||||
if (data.isAdd || data.isCopy) {
|
||||
this.dialogTitle = 'notification.add-notification-template';
|
||||
}
|
||||
this.templateNotification = deepClone(this.data.template);
|
||||
|
||||
if (this.templateNotification) {
|
||||
if (this.data.isCopy) {
|
||||
this.templateNotification.name += ` (${this.translate.instant('action.copy')})`;
|
||||
}
|
||||
this.templateNotificationForm.reset({}, {emitEvent: false});
|
||||
this.templateNotificationForm.patchValue(this.templateNotification, {emitEvent: false});
|
||||
for (const method in this.templateNotification.configuration.deliveryMethodsTemplates) {
|
||||
this.deliveryMethodFormsMap.get(NotificationDeliveryMethod[method])
|
||||
.patchValue(this.templateNotification.configuration.deliveryMethodsTemplates[method]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
@ -191,86 +208,61 @@ export class TemplateNotificationDialogComponent
|
||||
this.dialogRef.close(null);
|
||||
}
|
||||
|
||||
save() {
|
||||
let formValue = deepTrim(this.templateNotificationForm.value);
|
||||
if (isDefined(this.data.template)) {
|
||||
formValue = Object.assign({}, this.data.template, formValue);
|
||||
}
|
||||
this.notificationService.saveNotificationTemplate(formValue).subscribe(
|
||||
(target) => this.dialogRef.close(target)
|
||||
);
|
||||
}
|
||||
|
||||
changeStep($event: StepperSelectionEvent) {
|
||||
this.selectedIndex = $event.selectedIndex;
|
||||
}
|
||||
|
||||
backStep() {
|
||||
this.addNotificationTemplate.previous();
|
||||
this.notificationTemplateStepper.previous();
|
||||
}
|
||||
|
||||
nextStep() {
|
||||
if (this.selectedIndex >= this.maxStepperIndex) {
|
||||
this.add();
|
||||
} else {
|
||||
this.addNotificationTemplate.next();
|
||||
this.notificationTemplateStepper.next();
|
||||
}
|
||||
}
|
||||
|
||||
nextStepLabel(): string {
|
||||
if (this.selectedIndex === 1 && this.selectedIndex < this.maxStepperIndex && this.pushTemplateForm.pristine) {
|
||||
return 'action.skip';
|
||||
}
|
||||
if (this.selectedIndex === 2 && this.selectedIndex < this.maxStepperIndex && this.emailTemplateForm.pristine) {
|
||||
return 'action.skip';
|
||||
}
|
||||
if (this.selectedIndex === 3 && this.selectedIndex < this.maxStepperIndex && this.smsTemplateForm.pristine) {
|
||||
return 'action.skip';
|
||||
}
|
||||
if (this.selectedIndex !== 0 && this.selectedIndex >= this.maxStepperIndex) {
|
||||
return 'action.add';
|
||||
if (this.selectedIndex !== 0) {
|
||||
if (this.selectedIndex >= this.maxStepperIndex) {
|
||||
return (this.data.isAdd || this.data.isCopy) ? 'action.add' : 'action.save';
|
||||
} else if (this.notificationTemplateStepper.selected.stepControl.pristine) {
|
||||
return 'action.skip';
|
||||
}
|
||||
}
|
||||
return 'action.next';
|
||||
}
|
||||
|
||||
private get maxStepperIndex(): number {
|
||||
return this.addNotificationTemplate?._steps?.length - 1;
|
||||
return this.notificationTemplateStepper?._steps?.length - 1;
|
||||
}
|
||||
|
||||
private add(): void {
|
||||
if (this.allValid()) {
|
||||
const formValue: NotificationTemplate = this.templateNotificationForm.value;
|
||||
if (formValue.configuration.deliveryMethodsTemplates.PUSH.enabled) {
|
||||
Object.assign(formValue.configuration.deliveryMethodsTemplates.PUSH, this.pushTemplateForm.value);
|
||||
} else {
|
||||
delete formValue.configuration.deliveryMethodsTemplates.PUSH;
|
||||
let template: NotificationTemplate = this.templateNotificationForm.value;
|
||||
this.notificationDeliveryMethods.forEach(method => {
|
||||
if (template.configuration.deliveryMethodsTemplates[method].enabled) {
|
||||
Object.assign(template.configuration.deliveryMethodsTemplates[method], this.deliveryMethodFormsMap.get(method).value, {method});
|
||||
} else {
|
||||
delete template.configuration.deliveryMethodsTemplates[method];
|
||||
}
|
||||
});
|
||||
if (this.templateNotification) {
|
||||
template = {...this.templateNotification, ...template};
|
||||
}
|
||||
if (formValue.configuration.deliveryMethodsTemplates.EMAIL.enabled) {
|
||||
Object.assign(formValue.configuration.deliveryMethodsTemplates.EMAIL, this.emailTemplateForm.value);
|
||||
} else {
|
||||
delete formValue.configuration.deliveryMethodsTemplates.EMAIL;
|
||||
}
|
||||
if (formValue.configuration.deliveryMethodsTemplates.SMS.enabled) {
|
||||
Object.assign(formValue.configuration.deliveryMethodsTemplates.SMS, this.smsTemplateForm.value);
|
||||
} else {
|
||||
delete formValue.configuration.deliveryMethodsTemplates.SMS;
|
||||
}
|
||||
if (formValue.configuration.deliveryMethodsTemplates.SLACK.enabled) {
|
||||
Object.assign(formValue.configuration.deliveryMethodsTemplates.SLACK, this.slackTemplateForm.value);
|
||||
} else {
|
||||
delete formValue.configuration.deliveryMethodsTemplates.SLACK;
|
||||
}
|
||||
this.notificationService.saveNotificationTemplate(deepTrim(formValue)).subscribe(
|
||||
this.notificationService.saveNotificationTemplate(deepTrim(template)).subscribe(
|
||||
(target) => this.dialogRef.close(target)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private allValid(): boolean {
|
||||
return !this.addNotificationTemplate.steps.find((item, index) => {
|
||||
return !this.notificationTemplateStepper.steps.find((item, index) => {
|
||||
if (item.stepControl.invalid) {
|
||||
item.interacted = true;
|
||||
this.addNotificationTemplate.selectedIndex = index;
|
||||
this.notificationTemplateStepper.selectedIndex = index;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
|
||||
@ -2674,8 +2674,8 @@
|
||||
"add-notification-template": "Add notification template",
|
||||
"add-target": "Add recipient",
|
||||
"add-template": "Add template",
|
||||
"at-least-one-should-be-selected": "At least one should be selected",
|
||||
"all": "All",
|
||||
"at-least-one-should-be-selected": "At least one should be selected",
|
||||
"basic-settings": "Basic settings",
|
||||
"button-text": "Button text",
|
||||
"button-text-required": "Button text is required",
|
||||
@ -2683,6 +2683,7 @@
|
||||
"conversation": "Conversation",
|
||||
"conversation-required": "Conversation is required",
|
||||
"copy-notification-template": "Copy notification template",
|
||||
"copy-template": "Copy template",
|
||||
"create-target": "Create recipient",
|
||||
"created-time": "Created time",
|
||||
"delete-request-text": "Be careful, after the confirmation the notification request will become unrecoverable.",
|
||||
@ -2692,16 +2693,17 @@
|
||||
"delete-template-text": "Be careful, after the confirmation the notification template will become unrecoverable.",
|
||||
"delete-template-title": "Are you sure you want to delete the notification template '{{templateName}}'?",
|
||||
"delivery-method": "Delivery method",
|
||||
"delivery-methods": "Delivery methods",
|
||||
"delivery-method-type": {
|
||||
"email": "Email",
|
||||
"push": "Web",
|
||||
"slack": "Slack",
|
||||
"sms": "SMS"
|
||||
},
|
||||
"delivery-methods": "Delivery methods",
|
||||
"description": "Description",
|
||||
"edit-notification-target": "Edit notification recipient",
|
||||
"edit-notification-template": "Edit notification template",
|
||||
"edit-template": "Edit template",
|
||||
"email-settings": "Email settings",
|
||||
"get-customer-id-from-originator": "Get Customer id from originator",
|
||||
"inbox": "Inbox",
|
||||
@ -2722,6 +2724,7 @@
|
||||
"notification": "Notification",
|
||||
"notification-center": "Notification center",
|
||||
"notification-target": "Notification recipient",
|
||||
"notify-again": "Notify again",
|
||||
"recipients-count": "{ count, plural, 1 {1 Recipient} other {# Recipients} }",
|
||||
"requet-status": {
|
||||
"processing": "Processing",
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user