allow switch between notif. template body editor > text or email builder
This commit is contained in:
parent
afc9b43734
commit
441af6b2d1
|
@ -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",
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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
|
||||
}
|
|
@ -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`)] });
|
||||
|
|
Loading…
Reference in New Issue