allow switch between notif. template body editor > text or email builder

This commit is contained in:
mchouliara 2024-10-03 16:15:49 +03:00
parent afc9b43734
commit 441af6b2d1
15 changed files with 109 additions and 57 deletions

View File

@ -1563,7 +1563,9 @@
"BCC": "BCC",
"BCC-MODE": "BCC Mode",
"EXTRA-DATA-KEYS": "Extra Data Keys",
"FORMATTING": "Formatting"
"FORMATTING": "Formatting",
"TEXT-EDITOR": "Text editor",
"EMAIL-BUILDER": "Email builder"
},
"ACTIONS": {
"SAVE": "Save",

View File

@ -1566,7 +1566,9 @@
"BCC": "BCC",
"BCC-MODE": "BCC Mode",
"EXTRA-DATA-KEYS": "Extra Data Keys",
"FORMATTING": "Formatting"
"FORMATTING": "Formatting",
"TEXT-EDITOR": "Text editor",
"EMAIL-BUILDER": "Email builder"
},
"ACTIONS": {
"SAVE": "Save",

View File

@ -1566,7 +1566,9 @@
"BCC": "BCC",
"BCC-MODE": "BCC Mode",
"EXTRA-DATA-KEYS": "Extra Data Keys",
"FORMATTING": "Formatting"
"FORMATTING": "Formatting",
"TEXT-EDITOR": "Text editor",
"EMAIL-BUILDER": "Email builder"
},
"ACTIONS": {
"SAVE": "Save",

View File

@ -1566,7 +1566,9 @@
"BCC": "BCC",
"BCC-MODE": "BCC Mode",
"EXTRA-DATA-KEYS": "Extra Data Keys",
"FORMATTING": "Formatting"
"FORMATTING": "Formatting",
"TEXT-EDITOR": "Text editor",
"EMAIL-BUILDER": "Email builder"
},
"ACTIONS": {
"SAVE": "Save",

View File

@ -1566,7 +1566,9 @@
"BCC": "BCC",
"BCC-MODE": "BCC Mode",
"EXTRA-DATA-KEYS": "Extra Data Keys",
"FORMATTING": "Formatting"
"FORMATTING": "Formatting",
"TEXT-EDITOR": "Text editor",
"EMAIL-BUILDER": "Email builder"
},
"ACTIONS": {
"SAVE": "Save",

View File

@ -1566,7 +1566,9 @@
"BCC": "BCC",
"BCC-MODE": "BCC Mode",
"EXTRA-DATA-KEYS": "Extra Data Keys",
"FORMATTING": "Formatting"
"FORMATTING": "Formatting",
"TEXT-EDITOR": "Text editor",
"EMAIL-BUILDER": "Email builder"
},
"ACTIONS": {
"SAVE": "Save",

View File

@ -1566,7 +1566,9 @@
"BCC": "BCC",
"BCC-MODE": "BCC Mode",
"EXTRA-DATA-KEYS": "Extra Data Keys",
"FORMATTING": "Formatting"
"FORMATTING": "Formatting",
"TEXT-EDITOR": "Text editor",
"EMAIL-BUILDER": "Email builder"
},
"ACTIONS": {
"SAVE": "Save",

View File

@ -1566,7 +1566,9 @@
"BCC": "BCC",
"BCC-MODE": "BCC Mode",
"EXTRA-DATA-KEYS": "Extra Data Keys",
"FORMATTING": "Formatting"
"FORMATTING": "Formatting",
"TEXT-EDITOR": "Text editor",
"EMAIL-BUILDER": "Email builder"
},
"ACTIONS": {
"SAVE": "Save",

View File

@ -1566,7 +1566,9 @@
"BCC": "BCC",
"BCC-MODE": "BCC Mode",
"EXTRA-DATA-KEYS": "Extra Data Keys",
"FORMATTING": "Formatting"
"FORMATTING": "Formatting",
"TEXT-EDITOR": "Text editor",
"EMAIL-BUILDER": "Email builder"
},
"ACTIONS": {
"SAVE": "Save",

View File

@ -1566,7 +1566,9 @@
"BCC": "BCC",
"BCC-MODE": "BCC Mode",
"EXTRA-DATA-KEYS": "Extra Data Keys",
"FORMATTING": "Formatting"
"FORMATTING": "Formatting",
"TEXT-EDITOR": "Text editor",
"EMAIL-BUILDER": "Email builder"
},
"ACTIONS": {
"SAVE": "Save",

View File

@ -1566,7 +1566,9 @@
"BCC": "BCC",
"BCC-MODE": "BCC Mode",
"EXTRA-DATA-KEYS": "Extra Data Keys",
"FORMATTING": "Formatting"
"FORMATTING": "Formatting",
"TEXT-EDITOR": "Text editor",
"EMAIL-BUILDER": "Email builder"
},
"ACTIONS": {
"SAVE": "Save",

View File

@ -25,7 +25,7 @@ export interface NotificationTemplateValue {
subjectText: string;
subjectKey: string;
subjectFieldOptions: NotificationFieldOptions;
bodyText: string;
bodyText: NotificationTemplateBodyText;
bodyKey: string;
priorityKey: string;
allowAttachments: Boolean;
@ -38,7 +38,7 @@ export interface NotificationTemplateValue {
}
export interface NotificationTemplateBodyText {
design: JSONTemplate;
design: string;
html: string;
}
@ -70,7 +70,7 @@ export interface NotificationTemplateValuePersist {
subjectText: string;
subjectKey: string;
subjectFieldOptions: NotificationFieldOptionsPersist;
bodyText: string;
bodyText: string;//NotificationTemplateBodyText;
bodyKey: string;
priorityKey: string;
allowAttachments: Boolean;

View File

@ -15,7 +15,7 @@
</button>
</div>
<div class="col-auto" *ngIf="canSave">
<button mat-button class="rounded-btn primary" (click)="attemptSave()" [disabled]="!editorReady">
<button mat-button class="rounded-btn primary" (click)="attemptSave()" [disabled]="emailBuilderMode && !editorReady">
<mat-icon>save</mat-icon>
{{'NOTIFICATION-SERVICE.NOTIFICATION-TEMPLATE-EDITOR.ACTIONS.SAVE' | translate}}
</button>
@ -145,29 +145,27 @@
</div>
<div class="col-12">
<h4>{{'NOTIFICATION-SERVICE.NOTIFICATION-TEMPLATE-EDITOR.FIELDS.BODY-TEXT' | translate}}</h4>
<mat-progress-spinner class="ml-auto mr-auto" *ngIf="!editorReady" mode="indeterminate" [diameter]="24"></mat-progress-spinner>
<email-editor
(ready)="onEditorReady($event)"
></email-editor>
<!-- <editor class="w-100 mt-2" [init]="{
base_url: '/tinymce',
suffix: '.min',
height: 800,
menubar: true,
plugins: [
'advlist', 'autolink', 'lists', 'link', 'image', 'charmap', 'print', 'preview', 'anchor',
'searchreplace', 'visualblocks', 'fullpage',
'insertdatetime', 'media', 'table' ,'paste', 'code', 'help', 'wordcount','importcss',
],
extended_valid_elements: '*[*]',
forced_root_block: '',
valid_children: '+body[script],ol[li|div|p|a|ol|table],h2[span],h3[span]',
save_enablewhendirty: false,
toolbar:
'undo redo | formatselect | bold italic backcolor | \
alignleft aligncenter alignright alignjustify | \
bullist numlist outdent indent | code | searchreplace | preview | removeformat | help | link | image'
}" [formControl]="formGroup.get('value').get('bodyText')"></editor> -->
<mat-button-toggle-group id="editorType" appearance="standard" hideSingleSelectionIndicator="true" [formControl]="bodyInputMode" aria-label="editor type" required>
<mat-button-toggle [value]="NotificationBodyInputMode.TextEditor">{{'NOTIFICATION-SERVICE.NOTIFICATION-TEMPLATE-EDITOR.FIELDS.TEXT-EDITOR' |translate}}</mat-button-toggle>
<mat-button-toggle [value]="NotificationBodyInputMode.EmailBuilder">{{'NOTIFICATION-SERVICE.NOTIFICATION-TEMPLATE-EDITOR.FIELDS.EMAIL-BUILDER' |translate}}</mat-button-toggle>
</mat-button-toggle-group>
<span class="d-none" [class.d-block]="emailBuilderMode">
<mat-progress-spinner class="ml-auto mr-auto" *ngIf="!editorReady" mode="indeterminate" [diameter]="24"></mat-progress-spinner>
<email-editor
(ready)="onEditorReady($event)"
></email-editor>
</span>
<textarea
class="d-none w-100"
[class.d-block]="!emailBuilderMode"
[formControl]="formGroup.get('value').get('bodyText').get('html')"
style="min-height: 10rem"
></textarea>
<!-- <rich-text-editor-component
[form]="formGroup.controls.value.controls.bodyText.controls.html"
[editable]="true"
[required]="true"
/> -->
<mat-error *ngIf="formGroup.get('value').get('bodyText').hasError('backendError')">{{formGroup.get('value').get('bodyText').getError('backendError').message}}</mat-error>
<!-- <mat-error *ngIf="formGroup.get('value').get('bodyText').hasError('required')">{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error> -->
</div>

View File

@ -1,9 +1,9 @@
import { Component, OnInit, ViewChild } from '@angular/core';
import { UntypedFormGroup } from '@angular/forms';
import { Component, OnInit, SecurityContext, ViewChild } from '@angular/core';
import { FormControl, UntypedFormGroup } from '@angular/forms';
import { MatCheckboxChange } from '@angular/material/checkbox';
import { MatChipEditedEvent, MatChipInputEvent } from '@angular/material/chips';
import { MatDialog } from '@angular/material/dialog';
import { Title } from '@angular/platform-browser';
import { DomSanitizer, Title } from '@angular/platform-browser';
import { ActivatedRoute, Router } from '@angular/router';
import { AppPermission } from '@app/core/common/enum/permission.enum';
import { Language } from '@app/core/model/language/language';
@ -49,6 +49,9 @@ export class NotificationTemplateEditorComponent extends BaseEditor<Notification
@ViewChild(EmailEditorComponent)
private emailEditor: EmailEditorComponent;
NotificationBodyInputMode = NotificationBodyInputMode;
bodyInputMode = new FormControl<NotificationBodyInputMode>(NotificationBodyInputMode.EmailBuilder);
editorReady = false;
isNew = true;
isDeleted = false;
@ -82,6 +85,10 @@ export class NotificationTemplateEditorComponent extends BaseEditor<Notification
return this.authService.hasPermission(permission) || this.editorModel?.permissions?.includes(permission);
}
get emailBuilderMode() {
return this.bodyInputMode.value === NotificationBodyInputMode.EmailBuilder;
}
constructor(
// BaseFormEditor injected dependencies
protected dialog: MatDialog,
@ -96,6 +103,7 @@ export class NotificationTemplateEditorComponent extends BaseEditor<Notification
protected lockService: LockService,
protected authService: AuthService,
protected configurationService: ConfigurationService,
protected domSanitizer: DomSanitizer,
// Rest dependencies. Inject any other needed deps here:
public enumUtils: NotificationServiceEnumUtils,
private languageHttpService: LanguageHttpService,
@ -137,7 +145,7 @@ export class NotificationTemplateEditorComponent extends BaseEditor<Notification
prepareForm(data: NotificationTemplate) {
try {
this.editorModel = data ? new NotificationTemplateEditorModel().fromModel(data) : new NotificationTemplateEditorModel();
this.editorModel = data ? new NotificationTemplateEditorModel(this.domSanitizer).fromModel(data) : new NotificationTemplateEditorModel(this.domSanitizer);
if (data) {
if (data.value && data.value.subjectFieldOptions) {
@ -154,6 +162,12 @@ export class NotificationTemplateEditorComponent extends BaseEditor<Notification
if (data.value && data.value.bodyFieldOptions && data.value.bodyFieldOptions.formatting) {
this.bodyFormatting = data.value.bodyFieldOptions.formatting;
}
if(data.value?.bodyText?.design){
this.bodyInputMode.setValue(NotificationBodyInputMode.EmailBuilder)
} else {
this.bodyInputMode.setValue(NotificationBodyInputMode.TextEditor)
this.bodyInputMode.disable();
}
this.ccValues = this.editorModel.value.cc;
this.bccValues = this.editorModel.value.bcc;
this.extraDataKeys = this.editorModel.value.extraDataKeys;
@ -188,8 +202,8 @@ export class NotificationTemplateEditorComponent extends BaseEditor<Notification
}
persistEntity(onSuccess?: (response) => void): void {
const formData = this.formService.getValue(this.formGroup.value) as NotificationTemplatePersist;
const formData = this.formService.getValue(this.formGroup.value); //as NotificationTemplatePersist;
formData.value = {...formData.value, bodyText: this.domSanitizer.sanitize(SecurityContext.HTML, formData.value.bodyText.html)}
this.notificationTemplateService.persist(formData)
.pipe(takeUntil(this._destroyed)).subscribe(
complete => onSuccess ? onSuccess(complete) : this.onCallbackSuccess(complete),
@ -198,13 +212,13 @@ export class NotificationTemplateEditorComponent extends BaseEditor<Notification
}
attemptSave(): void {
if(this.emailEditor?.editor){
if(this.emailEditor?.editor && this.bodyInputMode.value === NotificationBodyInputMode.EmailBuilder){
this.emailEditor?.editor?.exportHtml((data) => {
const json: NotificationTemplateBodyText = {
design: data?.design,
design: JSON.stringify(data?.design),
html: data?.html
};
this.formGroup.get('value').get('bodyText').setValue(JSON.stringify(json));
this.formGroup.get('value').get('bodyText').setValue(json);
this.formSubmit();
});
}else {
@ -330,13 +344,19 @@ export class NotificationTemplateEditorComponent extends BaseEditor<Notification
}
onEditorReady() {
this.editorReady = true;
const body = this.formGroup.get('value')?.get('bodyText')?.value;
if(body){
const design = JSON.parse(body)?.design as JSONTemplate;
if(body?.design){
const design = JSON.parse(body?.design) as JSONTemplate;
this.emailEditor.loadDesign(design);
}
this.formGroup.markAsDirty();
this.editorReady = true;
}
}
enum NotificationBodyInputMode {
TextEditor,
EmailBuilder
}

View File

@ -10,19 +10,21 @@ import { NotificationTemplateKind } from '@notification-service/core/enum/notifi
import { NotificationType } from '@notification-service/core/enum/notification-type.enum';
import { EmailOverrideMode } from '@notification-service/core/enum/email-override-mode';
import { NotificationDataType } from '@notification-service/core/enum/notification-data-type';
import { DomSanitizer } from '@angular/platform-browser';
import { SecurityContext } from '@angular/core';
export class NotificationTemplateEditorModel extends BaseEditorModel implements NotificationTemplatePersist {
channel: NotificationTemplateChannel;
notificationType: NotificationType;
kind: NotificationTemplateKind;
languageCode: string;
value: NotificationTemplateValueEditorModel = new NotificationTemplateValueEditorModel();
value: NotificationTemplateValueEditorModel = new NotificationTemplateValueEditorModel(this.sanitizer);
permissions: string[];
public validationErrorModel: ValidationErrorModel = new ValidationErrorModel();
protected formBuilder: UntypedFormBuilder = new UntypedFormBuilder();
constructor() { super();}
constructor(protected sanitizer: DomSanitizer) { super();}
public fromModel(item: NotificationTemplate): NotificationTemplateEditorModel {
if(item){
@ -31,7 +33,7 @@ export class NotificationTemplateEditorModel extends BaseEditorModel implements
this.notificationType = item.notificationType;
this.kind = item.kind;
if(item.languageCode && item.languageCode) this.languageCode = item.languageCode;
if (item.value) { this.value = new NotificationTemplateValueEditorModel(this.validationErrorModel).fromModel(item.value); }
if (item.value) { this.value = new NotificationTemplateValueEditorModel(this.sanitizer, this.validationErrorModel).fromModel(item.value); }
}
return this;
@ -88,7 +90,7 @@ export class NotificationTemplateValueEditorModel implements NotificationTemplat
subjectText: string;
subjectKey: string;
subjectFieldOptions: NotificationFieldOptionsEditorModel = new NotificationFieldOptionsEditorModel();
bodyText: string;
bodyText: string;//NotificationTemplateBodyText;
bodyKey: string;
priorityKey: string;
allowAttachments: Boolean = false;
@ -102,7 +104,8 @@ export class NotificationTemplateValueEditorModel implements NotificationTemplat
protected formBuilder: UntypedFormBuilder = new UntypedFormBuilder();
constructor(
public validationErrorModel: ValidationErrorModel = new ValidationErrorModel()
protected sanitizer: DomSanitizer,
public validationErrorModel: ValidationErrorModel = new ValidationErrorModel(),
) { }
public fromModel(item: NotificationTemplateValue): NotificationTemplateValueEditorModel {
@ -110,7 +113,11 @@ export class NotificationTemplateValueEditorModel implements NotificationTemplat
this.subjectText = item.subjectText;
this.subjectKey = item.subjectKey;
if (item.subjectFieldOptions) this.subjectFieldOptions = new NotificationFieldOptionsEditorModel(this.validationErrorModel).fromModel(item.subjectFieldOptions);
this.bodyText = item.bodyText;
this.bodyText = item.bodyText.toString()
// {
// design: item.bodyText?.design,
// html: item.bodyText?.html ?? item.bodyText.toString()// this.sanitizer.sanitize(SecurityContext.HTML, item.bodyText?.html ?? item.bodyText)
// }
this.bodyKey = item.bodyKey;
this.priorityKey = item.priorityKey;
this.allowAttachments = item.allowAttachments;
@ -143,7 +150,10 @@ export class NotificationTemplateValueEditorModel implements NotificationTemplat
rootPath: `${rootPath}subjectFieldOptions.`,
disabled: disabled
}),
bodyText: [{ value: this.bodyText, disabled: disabled }, context.getValidation('bodyText').validators],
bodyText: this.formBuilder.group({
html: [{value: this.bodyText, disabled: disabled}, context.getValidation('html').validators],
design: [{value: null, disabled: disabled}, context.getValidation('design').validators]
}, {validators: context.getValidation('bodyText').validators}),
bodyKey: [{ value: this.bodyKey, disabled: disabled }, context.getValidation('bodyKey').validators],
priorityKey: [{ value: this.priorityKey, disabled: disabled }, context.getValidation('priorityKey').validators],
allowAttachments: [{ value: this.allowAttachments, disabled: disabled }, context.getValidation('allowAttachments').validators],
@ -170,6 +180,8 @@ export class NotificationTemplateValueEditorModel implements NotificationTemplat
baseValidationArray.push({ key: 'subjectText', validators: [Validators.required, BackendErrorValidator(validationErrorModel, `${rootPath}subjectText`)] });
baseValidationArray.push({ key: 'subjectKey', validators: [Validators.required, BackendErrorValidator(validationErrorModel, `${rootPath}subjectKey`)] });
baseValidationArray.push({ key: 'bodyText', validators: [Validators.required, BackendErrorValidator(validationErrorModel, `${rootPath}bodyText`)] });
baseValidationArray.push({ key: 'html', validators: [Validators.required, BackendErrorValidator(validationErrorModel, `${rootPath}html`)] });
baseValidationArray.push({ key: 'design', validators: [BackendErrorValidator(validationErrorModel, `${rootPath}design`)] });
baseValidationArray.push({ key: 'bodyKey', validators: [Validators.required, BackendErrorValidator(validationErrorModel, `${rootPath}bodyKey`)] });
baseValidationArray.push({ key: 'priorityKey', validators: [Validators.required, BackendErrorValidator(validationErrorModel, `${rootPath}priorityKey`)] });
baseValidationArray.push({ key: 'allowAttachments', validators: [BackendErrorValidator(validationErrorModel, `${rootPath}allowAttachments`)] });