@flusys/ng-email 4.1.1 → 5.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -392
- package/fesm2022/flusys-ng-email-email-config-form.component-M0g9fxU1.mjs +793 -0
- package/fesm2022/flusys-ng-email-email-config-form.component-M0g9fxU1.mjs.map +1 -0
- package/fesm2022/{flusys-ng-email-email-config-list.component-oznfQvxo.mjs → flusys-ng-email-email-config-list.component-DorIeenX.mjs} +149 -72
- package/fesm2022/flusys-ng-email-email-config-list.component-DorIeenX.mjs.map +1 -0
- package/fesm2022/{flusys-ng-email-template-form.component-B2vIO6ow.mjs → flusys-ng-email-template-form.component-SbeCuxm5.mjs} +19 -24
- package/fesm2022/flusys-ng-email-template-form.component-SbeCuxm5.mjs.map +1 -0
- package/fesm2022/{flusys-ng-email-template-list.component-0PJxS33a.mjs → flusys-ng-email-template-list.component-DrtU0xLq.mjs} +43 -40
- package/fesm2022/flusys-ng-email-template-list.component-DrtU0xLq.mjs.map +1 -0
- package/fesm2022/flusys-ng-email.mjs +89 -185
- package/fesm2022/flusys-ng-email.mjs.map +1 -1
- package/package.json +4 -4
- package/types/flusys-ng-email.d.ts +0 -2
- package/fesm2022/flusys-ng-email-email-config-form.component-Cj2U6Tgf.mjs +0 -718
- package/fesm2022/flusys-ng-email-email-config-form.component-Cj2U6Tgf.mjs.map +0 -1
- package/fesm2022/flusys-ng-email-email-config-list.component-oznfQvxo.mjs.map +0 -1
- package/fesm2022/flusys-ng-email-template-form.component-B2vIO6ow.mjs.map +0 -1
- package/fesm2022/flusys-ng-email-template-list.component-0PJxS33a.mjs.map +0 -1
|
@@ -86,7 +86,7 @@ class TemplateFormComponent {
|
|
|
86
86
|
async loadTemplate(id) {
|
|
87
87
|
this.isLoading.set(true);
|
|
88
88
|
try {
|
|
89
|
-
const response = await this.templateService.
|
|
89
|
+
const response = await this.templateService.findById(id);
|
|
90
90
|
if (response.success && response.data) {
|
|
91
91
|
const template = response.data;
|
|
92
92
|
this.existingTemplate.set(template);
|
|
@@ -177,8 +177,8 @@ class TemplateFormComponent {
|
|
|
177
177
|
if (!this.isFormValid()) {
|
|
178
178
|
this.messageService.add({
|
|
179
179
|
severity: 'warn',
|
|
180
|
-
summary: this.translate('
|
|
181
|
-
detail: this.translate('
|
|
180
|
+
summary: this.translate('shared.validation'),
|
|
181
|
+
detail: this.translate('shared.fill.required.fields'),
|
|
182
182
|
});
|
|
183
183
|
return;
|
|
184
184
|
}
|
|
@@ -204,18 +204,13 @@ class TemplateFormComponent {
|
|
|
204
204
|
isActive: model.isActive,
|
|
205
205
|
isHtml: model.isHtml,
|
|
206
206
|
};
|
|
207
|
-
|
|
208
|
-
await this.templateService.
|
|
209
|
-
|
|
210
|
-
else {
|
|
211
|
-
await this.templateService.insertAsync(data);
|
|
212
|
-
}
|
|
207
|
+
const response = this.isEditMode()
|
|
208
|
+
? await this.templateService.update({ id: model.id, ...data })
|
|
209
|
+
: await this.templateService.insert(data);
|
|
213
210
|
this.messageService.add({
|
|
214
211
|
severity: 'success',
|
|
215
|
-
summary: this.translate('
|
|
216
|
-
detail: this.translate(
|
|
217
|
-
? 'email.template.updated'
|
|
218
|
-
: 'email.template.created'),
|
|
212
|
+
summary: this.translate('shared.success'),
|
|
213
|
+
detail: this.translate(response.messageKey ?? response.message, response.messageVariables),
|
|
219
214
|
});
|
|
220
215
|
this.router.navigate(['../'], { relativeTo: this.route });
|
|
221
216
|
}
|
|
@@ -247,7 +242,7 @@ class TemplateFormComponent {
|
|
|
247
242
|
</h3>
|
|
248
243
|
@if (showCompanyInfo()) {
|
|
249
244
|
<p class="text-sm text-muted-color mt-1">
|
|
250
|
-
{{ '
|
|
245
|
+
{{ 'shared.company' | translate }}: {{ currentCompanyName() }}
|
|
251
246
|
</p>
|
|
252
247
|
}
|
|
253
248
|
</div>
|
|
@@ -299,7 +294,7 @@ class TemplateFormComponent {
|
|
|
299
294
|
|
|
300
295
|
<div class="field">
|
|
301
296
|
<label for="description" class="block font-medium mb-2">{{
|
|
302
|
-
'
|
|
297
|
+
'email.template.desc' | translate
|
|
303
298
|
}}</label>
|
|
304
299
|
<input
|
|
305
300
|
pInputText
|
|
@@ -312,7 +307,7 @@ class TemplateFormComponent {
|
|
|
312
307
|
|
|
313
308
|
<div class="field flex items-center gap-2">
|
|
314
309
|
<p-toggleswitch [formField]="templateForm.isActive" />
|
|
315
|
-
<label>{{ '
|
|
310
|
+
<label>{{ 'shared.active' | translate }}</label>
|
|
316
311
|
</div>
|
|
317
312
|
</div>
|
|
318
313
|
|
|
@@ -413,14 +408,14 @@ class TemplateFormComponent {
|
|
|
413
408
|
<!-- Form Actions -->
|
|
414
409
|
<div class="flex justify-end gap-2 mt-6 pt-4 border-t border-surface">
|
|
415
410
|
<p-button
|
|
416
|
-
[label]="'
|
|
411
|
+
[label]="'shared.cancel' | translate"
|
|
417
412
|
severity="secondary"
|
|
418
413
|
[outlined]="true"
|
|
419
414
|
routerLink="../"
|
|
420
415
|
/>
|
|
421
416
|
<p-button
|
|
422
417
|
[label]="
|
|
423
|
-
(isEditMode() ? '
|
|
418
|
+
(isEditMode() ? 'shared.update' : 'shared.create') | translate
|
|
424
419
|
"
|
|
425
420
|
icon="pi pi-save"
|
|
426
421
|
[loading]="isLoading()"
|
|
@@ -456,7 +451,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImpor
|
|
|
456
451
|
</h3>
|
|
457
452
|
@if (showCompanyInfo()) {
|
|
458
453
|
<p class="text-sm text-muted-color mt-1">
|
|
459
|
-
{{ '
|
|
454
|
+
{{ 'shared.company' | translate }}: {{ currentCompanyName() }}
|
|
460
455
|
</p>
|
|
461
456
|
}
|
|
462
457
|
</div>
|
|
@@ -508,7 +503,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImpor
|
|
|
508
503
|
|
|
509
504
|
<div class="field">
|
|
510
505
|
<label for="description" class="block font-medium mb-2">{{
|
|
511
|
-
'
|
|
506
|
+
'email.template.desc' | translate
|
|
512
507
|
}}</label>
|
|
513
508
|
<input
|
|
514
509
|
pInputText
|
|
@@ -521,7 +516,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImpor
|
|
|
521
516
|
|
|
522
517
|
<div class="field flex items-center gap-2">
|
|
523
518
|
<p-toggleswitch [formField]="templateForm.isActive" />
|
|
524
|
-
<label>{{ '
|
|
519
|
+
<label>{{ 'shared.active' | translate }}</label>
|
|
525
520
|
</div>
|
|
526
521
|
</div>
|
|
527
522
|
|
|
@@ -622,14 +617,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImpor
|
|
|
622
617
|
<!-- Form Actions -->
|
|
623
618
|
<div class="flex justify-end gap-2 mt-6 pt-4 border-t border-surface">
|
|
624
619
|
<p-button
|
|
625
|
-
[label]="'
|
|
620
|
+
[label]="'shared.cancel' | translate"
|
|
626
621
|
severity="secondary"
|
|
627
622
|
[outlined]="true"
|
|
628
623
|
routerLink="../"
|
|
629
624
|
/>
|
|
630
625
|
<p-button
|
|
631
626
|
[label]="
|
|
632
|
-
(isEditMode() ? '
|
|
627
|
+
(isEditMode() ? 'shared.update' : 'shared.create') | translate
|
|
633
628
|
"
|
|
634
629
|
icon="pi pi-save"
|
|
635
630
|
[loading]="isLoading()"
|
|
@@ -645,4 +640,4 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImpor
|
|
|
645
640
|
}], ctorParameters: () => [] });
|
|
646
641
|
|
|
647
642
|
export { TemplateFormComponent };
|
|
648
|
-
//# sourceMappingURL=flusys-ng-email-template-form.component-
|
|
643
|
+
//# sourceMappingURL=flusys-ng-email-template-form.component-SbeCuxm5.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"flusys-ng-email-template-form.component-SbeCuxm5.mjs","sources":["../../../projects/ng-email/pages/template/template-form.component.ts"],"sourcesContent":["import { Component, computed, effect, inject, signal } from '@angular/core';\nimport { toSignal } from '@angular/core/rxjs-interop';\nimport { form, FormField, required } from '@angular/forms/signals';\nimport { ActivatedRoute, Router } from '@angular/router';\nimport {\n APP_CONFIG,\n DEFAULT_APP_NAME,\n TRANSLATE_ADAPTER,\n} from '@flusys/ng-core';\nimport { LAYOUT_AUTH_STATE } from '@flusys/ng-layout';\nimport { AngularModule, PrimeModule, TranslatePipe } from '@flusys/ng-shared';\nimport { MessageService } from 'primeng/api';\nimport { IEmailTemplate } from '../../interfaces/email-template.interface';\nimport { EmailBuilderStateService } from '../../services/email-builder-state.service';\nimport { EmailTemplateApiService } from '../../services/email-template-api.service';\n\n/** Form model interface for email template */\ninterface IEmailTemplateFormModel {\n id: string;\n name: string;\n slug: string;\n description: string;\n subject: string;\n htmlContent: string;\n textContent: string;\n isActive: boolean;\n isHtml: boolean;\n}\n\n/**\n * Email template form component (create/edit)\n * Uses Angular Signal Forms for reactive form handling\n */\n@Component({\n selector: 'lib-template-form',\n imports: [AngularModule, PrimeModule, FormField, TranslatePipe],\n providers: [MessageService, EmailBuilderStateService],\n template: `\n <div class=\"card mb-4\">\n <!-- Header -->\n <div\n class=\"flex flex-col sm:flex-row justify-between items-start sm:items-center gap-3 mb-4\"\n >\n <div>\n <h3 class=\"text-lg sm:text-xl font-semibold m-0\">\n {{\n (isEditMode()\n ? 'email.template.edit.title'\n : 'email.template.new.title'\n ) | translate\n }}\n </h3>\n @if (showCompanyInfo()) {\n <p class=\"text-sm text-muted-color mt-1\">\n {{ 'shared.company' | translate }}: {{ currentCompanyName() }}\n </p>\n }\n </div>\n </div>\n\n <!-- Form Fields -->\n <div class=\"grid grid-cols-1 md:grid-cols-2 gap-4\">\n <div class=\"field\">\n <label for=\"name\" class=\"block font-medium mb-2\"\n >{{ 'email.template.name' | translate }} *</label\n >\n <input\n pInputText\n id=\"name\"\n [formField]=\"templateForm.name\"\n class=\"w-full\"\n [placeholder]=\"'email.template.name.example' | translate\"\n />\n </div>\n\n <div class=\"field\">\n <label for=\"slug\" class=\"block font-medium mb-2\"\n >{{ 'email.template.slug' | translate }} *</label\n >\n <input\n pInputText\n id=\"slug\"\n [formField]=\"templateForm.slug\"\n class=\"w-full\"\n [placeholder]=\"'email.template.slug.example' | translate\"\n />\n </div>\n\n <div class=\"field md:col-span-2\">\n <label for=\"subject\" class=\"block font-medium mb-2\"\n >{{ 'email.template.subject' | translate }} *</label\n >\n <input\n pInputText\n id=\"subject\"\n [formField]=\"templateForm.subject\"\n class=\"w-full\"\n [placeholder]=\"'email.template.subject.example' | translate\"\n />\n <small class=\"text-muted-color\">{{\n 'email.template.variable.hint' | translate\n }}</small>\n </div>\n\n <div class=\"field\">\n <label for=\"description\" class=\"block font-medium mb-2\">{{\n 'email.template.desc' | translate\n }}</label>\n <input\n pInputText\n id=\"description\"\n [formField]=\"templateForm.description\"\n class=\"w-full\"\n [placeholder]=\"'email.template.desc.placeholder' | translate\"\n />\n </div>\n\n <div class=\"field flex items-center gap-2\">\n <p-toggleswitch [formField]=\"templateForm.isActive\" />\n <label>{{ 'shared.active' | translate }}</label>\n </div>\n </div>\n\n <!-- Content Editor & Preview -->\n <div\n class=\"grid grid-cols-1 gap-4\"\n [class.lg:grid-cols-2]=\"editorMode() === 'html'\"\n >\n <!-- Editor Panel -->\n <div class=\"card\">\n <div class=\"flex justify-between items-center mb-3\">\n <h3 class=\"font-semibold\">\n {{ 'email.template.content' | translate }}\n </h3>\n <div class=\"flex gap-1\">\n <p-button\n [label]=\"'email.template.html' | translate\"\n [outlined]=\"editorMode() !== 'html'\"\n [severity]=\"editorMode() === 'html' ? 'primary' : 'secondary'\"\n size=\"small\"\n (onClick)=\"setEditorMode('html')\"\n />\n <p-button\n [label]=\"'email.template.plain.text' | translate\"\n [outlined]=\"editorMode() !== 'text'\"\n [severity]=\"editorMode() === 'text' ? 'primary' : 'secondary'\"\n size=\"small\"\n (onClick)=\"setEditorMode('text')\"\n />\n </div>\n </div>\n\n <div class=\"h-[400px]\">\n @if (editorMode() === 'html') {\n <textarea\n pTextarea\n [ngModel]=\"formModel().htmlContent\"\n (ngModelChange)=\"updateFormField('htmlContent', $event)\"\n class=\"w-full h-full font-mono text-sm resize-none overflow-auto border border-surface rounded\"\n [placeholder]=\"'email.template.html.placeholder' | translate\"\n wrap=\"off\"\n ></textarea>\n } @else {\n <textarea\n pTextarea\n [ngModel]=\"formModel().textContent\"\n (ngModelChange)=\"updateFormField('textContent', $event)\"\n class=\"w-full h-full font-mono text-sm resize-none overflow-auto border border-surface rounded\"\n [placeholder]=\"'email.template.text.placeholder' | translate\"\n wrap=\"off\"\n ></textarea>\n }\n </div>\n @if (editorMode() === 'text') {\n <small class=\"text-muted-color mt-2 block\">\n <i class=\"pi pi-info-circle mr-1\"></i>\n {{ 'email.template.plain.text.hint' | translate }}\n </small>\n }\n </div>\n\n <!-- Preview Panel (HTML mode only) -->\n @if (editorMode() === 'html') {\n <div class=\"card\">\n <div class=\"flex flex-wrap justify-between items-center gap-2 mb-3\">\n <h3 class=\"font-semibold m-0\">\n {{ 'email.template.preview' | translate }}\n </h3>\n <p-tag\n [value]=\"'email.template.live.preview' | translate\"\n severity=\"info\"\n />\n </div>\n <div class=\"border border-surface rounded h-[400px] overflow-auto\">\n @if (formModel().htmlContent) {\n <iframe\n [srcdoc]=\"getPreviewHtml()\"\n class=\"w-full h-full border-0\"\n sandbox=\"allow-same-origin\"\n ></iframe>\n } @else {\n <div\n class=\"flex items-center justify-center h-full text-muted-color\"\n >\n <div class=\"text-center p-4\">\n <i class=\"pi pi-eye text-4xl mb-2\"></i>\n <p class=\"m-0\">\n {{ 'email.template.enter.html.preview' | translate }}\n </p>\n </div>\n </div>\n }\n </div>\n </div>\n }\n </div>\n\n <!-- Form Actions -->\n <div class=\"flex justify-end gap-2 mt-6 pt-4 border-t border-surface\">\n <p-button\n [label]=\"'shared.cancel' | translate\"\n severity=\"secondary\"\n [outlined]=\"true\"\n routerLink=\"../\"\n />\n <p-button\n [label]=\"\n (isEditMode() ? 'shared.update' : 'shared.create') | translate\n \"\n icon=\"pi pi-save\"\n [loading]=\"isLoading()\"\n [disabled]=\"!isFormValid()\"\n (onClick)=\"onSave()\"\n />\n </div>\n </div>\n\n <p-toast />\n `,\n})\nexport class TemplateFormComponent {\n private readonly route = inject(ActivatedRoute);\n private readonly router = inject(Router);\n private readonly templateService = inject(EmailTemplateApiService);\n private readonly messageService = inject(MessageService);\n private readonly appConfig = inject(APP_CONFIG);\n private readonly companyContext = inject(LAYOUT_AUTH_STATE, {\n optional: true,\n });\n private readonly translateAdapter = inject(TRANSLATE_ADAPTER, {\n optional: true,\n });\n readonly state = inject(EmailBuilderStateService);\n\n // Route params as signal\n private readonly routeParams = toSignal(this.route.paramMap);\n\n readonly isLoading = signal(false);\n readonly existingTemplate = signal<IEmailTemplate | null>(null);\n readonly isEditMode = computed(() => !!this.existingTemplate());\n readonly editorMode = signal<'html' | 'text'>('html');\n\n readonly showCompanyInfo = computed(\n () => this.appConfig.enableCompanyFeature && !!this.companyContext,\n );\n readonly currentCompanyName = computed(\n () => this.companyContext?.currentCompanyInfo()?.name ?? DEFAULT_APP_NAME,\n );\n\n /** Form model using signal */\n readonly formModel = signal<IEmailTemplateFormModel>({\n id: '',\n name: '',\n slug: '',\n description: '',\n subject: '',\n htmlContent: '',\n textContent: '',\n isActive: true,\n isHtml: true,\n });\n\n /** Form with validation using Angular Signal Forms */\n readonly templateForm = form(this.formModel, (f) => {\n required(f.name);\n required(f.slug);\n required(f.subject);\n });\n\n /** Check if form is valid */\n readonly isFormValid = computed(() => {\n const model = this.formModel();\n return (\n model.name.trim().length > 0 &&\n model.slug.trim().length > 0 &&\n model.subject.trim().length > 0\n );\n });\n\n /** Update a single form field */\n updateFormField<K extends keyof IEmailTemplateFormModel>(\n field: K,\n value: IEmailTemplateFormModel[K],\n ): void {\n this.formModel.update((m) => ({ ...m, [field]: value }));\n }\n\n constructor() {\n // Effect to handle route-based initialization\n effect(() => {\n const params = this.routeParams();\n if (!params) return;\n\n const id = params.get('id');\n if (id) {\n this.loadTemplate(id);\n }\n });\n }\n\n async loadTemplate(id: string): Promise<void> {\n this.isLoading.set(true);\n try {\n const response = await this.templateService.findById(id);\n if (response.success && response.data) {\n const template = response.data;\n this.existingTemplate.set(template);\n this.formModel.set({\n id: template.id,\n name: template.name,\n slug: template.slug,\n description: template.description || '',\n subject: template.subject,\n htmlContent: template.htmlContent,\n textContent: template.textContent || '',\n isActive: template.isActive,\n isHtml: template.isHtml ?? true,\n });\n // Set editor mode based on saved template type\n this.editorMode.set(template.isHtml ? 'html' : 'text');\n this.state.loadSchema(template.schema);\n }\n } catch {\n // Error toast handled by global interceptor\n } finally {\n this.isLoading.set(false);\n }\n }\n\n setEditorMode(mode: 'html' | 'text'): void {\n const currentMode = this.editorMode();\n const model = this.formModel();\n\n // Sync content when switching modes\n if (currentMode === 'text' && mode === 'html') {\n // Switching from text to html - convert text to basic HTML if htmlContent is empty\n if (!model.htmlContent && model.textContent) {\n this.formModel.update((m) => ({\n ...m,\n htmlContent: this.textToHtml(m.textContent),\n }));\n }\n } else if (currentMode === 'html' && mode === 'text') {\n // Switching from html to text - generate text from HTML if textContent is empty\n if (!model.textContent && model.htmlContent) {\n this.formModel.update((m) => ({\n ...m,\n textContent: this.htmlToPlainText(m.htmlContent),\n }));\n }\n }\n\n this.editorMode.set(mode);\n this.formModel.update((m) => ({ ...m, isHtml: mode === 'html' }));\n }\n\n /** Convert plain text to basic HTML */\n private textToHtml(text: string): string {\n if (!text) return '';\n // Convert line breaks to paragraphs\n return text\n .split(/\\n\\n+/)\n .map((p) => `<p>${p.replace(/\\n/g, '<br>')}</p>`)\n .join('\\n');\n }\n\n /** Convert HTML to plain text (using DOMParser for safe parsing) */\n private htmlToPlainText(html: string): string {\n if (!html) return '';\n // Use DOMParser for safe HTML parsing (prevents XSS)\n const parser = new DOMParser();\n const doc = parser.parseFromString(html, 'text/html');\n // Get text content and clean up whitespace\n return (doc.body.textContent || '').replace(/\\s+/g, ' ').trim();\n }\n\n /** Get HTML for preview iframe */\n getPreviewHtml(): string {\n const baseStyles = `\n <style>\n body {\n font-family: Arial, sans-serif;\n margin: 16px;\n background-color: #ffffff;\n color: #333333;\n }\n img { max-width: 100%; height: auto; }\n </style>\n `;\n return baseStyles + (this.formModel().htmlContent || '');\n }\n\n async onSave(): Promise<void> {\n if (!this.isFormValid()) {\n this.messageService.add({\n severity: 'warn',\n summary: this.translate('shared.validation'),\n detail: this.translate('shared.fill.required.fields'),\n });\n return;\n }\n\n this.isLoading.set(true);\n try {\n const model = this.formModel();\n const schema = this.state.schema();\n // Use user-provided plain text, or auto-generate from HTML if empty\n const textContent =\n model.textContent || this.htmlToPlainText(model.htmlContent);\n\n const data = {\n name: model.name,\n slug: model.slug,\n description: model.description || undefined,\n subject: model.subject,\n schema: {\n ...schema,\n name: model.name,\n subject: model.subject,\n },\n htmlContent:\n model.htmlContent ||\n `<p>${this.translate('email.template.default.content')}</p>`,\n textContent: textContent || undefined,\n isActive: model.isActive,\n isHtml: model.isHtml,\n };\n\n const response = this.isEditMode()\n ? await this.templateService.update({ id: model.id, ...data })\n : await this.templateService.insert(data);\n\n this.messageService.add({\n severity: 'success',\n summary: this.translate('shared.success'),\n detail: this.translate(\n response.messageKey ?? response.message,\n response.messageVariables,\n ),\n });\n\n this.router.navigate(['../'], { relativeTo: this.route });\n } catch {\n // Error toast handled by global interceptor\n } finally {\n this.isLoading.set(false);\n }\n }\n\n private translate(key: string, variables?: Record<string, unknown>): string {\n return this.translateAdapter?.translate(key, variables) ?? key;\n }\n}\n"],"names":["i3","i4","i5","i7","i8"],"mappings":"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"}
|
|
@@ -67,7 +67,7 @@ class TemplateListComponent {
|
|
|
67
67
|
this._variableValues.update((v) => ({ ...v, [key]: value }));
|
|
68
68
|
}
|
|
69
69
|
configOptions = computed(() => this.configs().map((c) => ({
|
|
70
|
-
label: `${c.name} (${this.translate(`email.
|
|
70
|
+
label: `${c.name} (${this.translate(`email.provider.${c.provider}`)})`,
|
|
71
71
|
value: c.id,
|
|
72
72
|
})), ...(ngDevMode ? [{ debugName: "configOptions" }] : []));
|
|
73
73
|
/** Extract variables from template content */
|
|
@@ -98,7 +98,7 @@ class TemplateListComponent {
|
|
|
98
98
|
async loadTemplates() {
|
|
99
99
|
this.isLoading.set(true);
|
|
100
100
|
try {
|
|
101
|
-
const response = await
|
|
101
|
+
const response = await this.templateService.getAll({
|
|
102
102
|
pagination: {
|
|
103
103
|
currentPage: Math.floor(this.first() / this.pageSize()),
|
|
104
104
|
pageSize: this.pageSize(),
|
|
@@ -106,7 +106,7 @@ class TemplateListComponent {
|
|
|
106
106
|
filter: {},
|
|
107
107
|
select: [],
|
|
108
108
|
sort: {},
|
|
109
|
-
})
|
|
109
|
+
});
|
|
110
110
|
if (response.success) {
|
|
111
111
|
this.templates.set(response.data ?? []);
|
|
112
112
|
this.totalRecords.set(response.meta?.total ?? 0);
|
|
@@ -134,12 +134,12 @@ class TemplateListComponent {
|
|
|
134
134
|
async loadConfigs() {
|
|
135
135
|
this.isLoadingConfigs.set(true);
|
|
136
136
|
try {
|
|
137
|
-
const response = await
|
|
137
|
+
const response = await this.configService.getAll({
|
|
138
138
|
pagination: { currentPage: 0, pageSize: 100 },
|
|
139
139
|
filter: { isActive: true },
|
|
140
140
|
select: [],
|
|
141
141
|
sort: {},
|
|
142
|
-
})
|
|
142
|
+
});
|
|
143
143
|
if (response.success) {
|
|
144
144
|
this.configs.set(response.data ?? []);
|
|
145
145
|
}
|
|
@@ -157,7 +157,7 @@ class TemplateListComponent {
|
|
|
157
157
|
if (!template || !model.configId || !model.recipient) {
|
|
158
158
|
this.messageService.add({
|
|
159
159
|
severity: 'warn',
|
|
160
|
-
summary: this.translate('
|
|
160
|
+
summary: this.translate('shared.validation'),
|
|
161
161
|
detail: this.translate('email.template.select.config.and.recipient'),
|
|
162
162
|
});
|
|
163
163
|
return;
|
|
@@ -180,19 +180,20 @@ class TemplateListComponent {
|
|
|
180
180
|
if (response.data?.success) {
|
|
181
181
|
this.messageService.add({
|
|
182
182
|
severity: 'success',
|
|
183
|
-
summary: this.translate('
|
|
184
|
-
detail:
|
|
185
|
-
|
|
186
|
-
|
|
183
|
+
summary: this.translate('shared.success'),
|
|
184
|
+
detail: response.messageKey
|
|
185
|
+
? this.translate(response.messageKey, response.messageVariables)
|
|
186
|
+
: response.message,
|
|
187
187
|
});
|
|
188
188
|
this.showTestDialog.set(false);
|
|
189
189
|
}
|
|
190
190
|
else {
|
|
191
191
|
this.messageService.add({
|
|
192
192
|
severity: 'error',
|
|
193
|
-
summary: this.translate('
|
|
194
|
-
detail: response.
|
|
195
|
-
this.translate(
|
|
193
|
+
summary: this.translate('shared.error'),
|
|
194
|
+
detail: response.messageKey
|
|
195
|
+
? this.translate(response.messageKey, response.messageVariables)
|
|
196
|
+
: response.data?.error,
|
|
196
197
|
});
|
|
197
198
|
}
|
|
198
199
|
}
|
|
@@ -205,7 +206,7 @@ class TemplateListComponent {
|
|
|
205
206
|
}
|
|
206
207
|
onDelete(template) {
|
|
207
208
|
this.confirmationService.confirm({
|
|
208
|
-
message: this.translate('
|
|
209
|
+
message: this.translate('shared.confirm.delete.item', {
|
|
209
210
|
name: template.name,
|
|
210
211
|
}),
|
|
211
212
|
header: this.translate('email.template.delete.title'),
|
|
@@ -213,14 +214,16 @@ class TemplateListComponent {
|
|
|
213
214
|
acceptButtonStyleClass: 'p-button-danger',
|
|
214
215
|
accept: async () => {
|
|
215
216
|
try {
|
|
216
|
-
await this.templateService.
|
|
217
|
+
const response = await this.templateService.delete({
|
|
217
218
|
id: template.id,
|
|
218
219
|
type: 'delete',
|
|
219
220
|
});
|
|
220
221
|
this.messageService.add({
|
|
221
222
|
severity: 'success',
|
|
222
|
-
summary: this.translate('
|
|
223
|
-
detail:
|
|
223
|
+
summary: this.translate('shared.success'),
|
|
224
|
+
detail: response?.messageKey
|
|
225
|
+
? this.translate(response.messageKey, response.messageVariables)
|
|
226
|
+
: (response?.message ?? ''),
|
|
224
227
|
});
|
|
225
228
|
this.loadTemplates();
|
|
226
229
|
}
|
|
@@ -246,7 +249,7 @@ class TemplateListComponent {
|
|
|
246
249
|
</h3>
|
|
247
250
|
@if (showCompanyInfo()) {
|
|
248
251
|
<p class="text-sm text-muted-color mt-1">
|
|
249
|
-
{{ '
|
|
252
|
+
{{ 'shared.company' | translate }}: {{ currentCompanyName() }}
|
|
250
253
|
</p>
|
|
251
254
|
}
|
|
252
255
|
</div>
|
|
@@ -275,19 +278,19 @@ class TemplateListComponent {
|
|
|
275
278
|
>
|
|
276
279
|
<ng-template #header>
|
|
277
280
|
<tr>
|
|
278
|
-
<th>{{ '
|
|
281
|
+
<th>{{ 'shared.name' | translate }}</th>
|
|
279
282
|
<th class="hidden md:table-cell">
|
|
280
283
|
{{ 'email.template.slug' | translate }}
|
|
281
284
|
</th>
|
|
282
285
|
<th class="hidden lg:table-cell">
|
|
283
286
|
{{ 'email.template.subject' | translate }}
|
|
284
287
|
</th>
|
|
285
|
-
<th>{{ '
|
|
286
|
-
<th>{{ '
|
|
288
|
+
<th>{{ 'shared.type' | translate }}</th>
|
|
289
|
+
<th>{{ 'shared.status' | translate }}</th>
|
|
287
290
|
<th class="hidden xl:table-cell">
|
|
288
|
-
{{ '
|
|
291
|
+
{{ 'shared.created' | translate }}
|
|
289
292
|
</th>
|
|
290
|
-
<th class="w-[120px]">{{ '
|
|
293
|
+
<th class="w-[120px]">{{ 'shared.actions' | translate }}</th>
|
|
291
294
|
</tr>
|
|
292
295
|
</ng-template>
|
|
293
296
|
|
|
@@ -317,7 +320,7 @@ class TemplateListComponent {
|
|
|
317
320
|
<td>
|
|
318
321
|
<p-tag
|
|
319
322
|
[value]="
|
|
320
|
-
(template.isActive ? '
|
|
323
|
+
(template.isActive ? 'shared.active' : 'shared.inactive')
|
|
321
324
|
| translate
|
|
322
325
|
"
|
|
323
326
|
[severity]="template.isActive ? 'success' : 'secondary'"
|
|
@@ -342,7 +345,7 @@ class TemplateListComponent {
|
|
|
342
345
|
[text]="true"
|
|
343
346
|
severity="secondary"
|
|
344
347
|
size="small"
|
|
345
|
-
[pTooltip]="'
|
|
348
|
+
[pTooltip]="'shared.edit' | translate"
|
|
346
349
|
(onClick)="onEdit(template.id)"
|
|
347
350
|
/>
|
|
348
351
|
<p-button
|
|
@@ -351,7 +354,7 @@ class TemplateListComponent {
|
|
|
351
354
|
[text]="true"
|
|
352
355
|
severity="danger"
|
|
353
356
|
size="small"
|
|
354
|
-
[pTooltip]="'
|
|
357
|
+
[pTooltip]="'shared.delete' | translate"
|
|
355
358
|
(onClick)="onDelete(template)"
|
|
356
359
|
/>
|
|
357
360
|
</div>
|
|
@@ -457,13 +460,13 @@ class TemplateListComponent {
|
|
|
457
460
|
|
|
458
461
|
<ng-template #footer>
|
|
459
462
|
<p-button
|
|
460
|
-
[label]="'
|
|
463
|
+
[label]="'shared.cancel' | translate"
|
|
461
464
|
severity="secondary"
|
|
462
465
|
[outlined]="true"
|
|
463
466
|
(onClick)="showTestDialog.set(false)"
|
|
464
467
|
/>
|
|
465
468
|
<p-button
|
|
466
|
-
[label]="'email.template.send
|
|
469
|
+
[label]="'email.template.test.send' | translate"
|
|
467
470
|
icon="pi pi-send"
|
|
468
471
|
[loading]="isSendingTest()"
|
|
469
472
|
(onClick)="sendTestEmail()"
|
|
@@ -492,7 +495,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImpor
|
|
|
492
495
|
</h3>
|
|
493
496
|
@if (showCompanyInfo()) {
|
|
494
497
|
<p class="text-sm text-muted-color mt-1">
|
|
495
|
-
{{ '
|
|
498
|
+
{{ 'shared.company' | translate }}: {{ currentCompanyName() }}
|
|
496
499
|
</p>
|
|
497
500
|
}
|
|
498
501
|
</div>
|
|
@@ -521,19 +524,19 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImpor
|
|
|
521
524
|
>
|
|
522
525
|
<ng-template #header>
|
|
523
526
|
<tr>
|
|
524
|
-
<th>{{ '
|
|
527
|
+
<th>{{ 'shared.name' | translate }}</th>
|
|
525
528
|
<th class="hidden md:table-cell">
|
|
526
529
|
{{ 'email.template.slug' | translate }}
|
|
527
530
|
</th>
|
|
528
531
|
<th class="hidden lg:table-cell">
|
|
529
532
|
{{ 'email.template.subject' | translate }}
|
|
530
533
|
</th>
|
|
531
|
-
<th>{{ '
|
|
532
|
-
<th>{{ '
|
|
534
|
+
<th>{{ 'shared.type' | translate }}</th>
|
|
535
|
+
<th>{{ 'shared.status' | translate }}</th>
|
|
533
536
|
<th class="hidden xl:table-cell">
|
|
534
|
-
{{ '
|
|
537
|
+
{{ 'shared.created' | translate }}
|
|
535
538
|
</th>
|
|
536
|
-
<th class="w-[120px]">{{ '
|
|
539
|
+
<th class="w-[120px]">{{ 'shared.actions' | translate }}</th>
|
|
537
540
|
</tr>
|
|
538
541
|
</ng-template>
|
|
539
542
|
|
|
@@ -563,7 +566,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImpor
|
|
|
563
566
|
<td>
|
|
564
567
|
<p-tag
|
|
565
568
|
[value]="
|
|
566
|
-
(template.isActive ? '
|
|
569
|
+
(template.isActive ? 'shared.active' : 'shared.inactive')
|
|
567
570
|
| translate
|
|
568
571
|
"
|
|
569
572
|
[severity]="template.isActive ? 'success' : 'secondary'"
|
|
@@ -588,7 +591,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImpor
|
|
|
588
591
|
[text]="true"
|
|
589
592
|
severity="secondary"
|
|
590
593
|
size="small"
|
|
591
|
-
[pTooltip]="'
|
|
594
|
+
[pTooltip]="'shared.edit' | translate"
|
|
592
595
|
(onClick)="onEdit(template.id)"
|
|
593
596
|
/>
|
|
594
597
|
<p-button
|
|
@@ -597,7 +600,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImpor
|
|
|
597
600
|
[text]="true"
|
|
598
601
|
severity="danger"
|
|
599
602
|
size="small"
|
|
600
|
-
[pTooltip]="'
|
|
603
|
+
[pTooltip]="'shared.delete' | translate"
|
|
601
604
|
(onClick)="onDelete(template)"
|
|
602
605
|
/>
|
|
603
606
|
</div>
|
|
@@ -703,13 +706,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImpor
|
|
|
703
706
|
|
|
704
707
|
<ng-template #footer>
|
|
705
708
|
<p-button
|
|
706
|
-
[label]="'
|
|
709
|
+
[label]="'shared.cancel' | translate"
|
|
707
710
|
severity="secondary"
|
|
708
711
|
[outlined]="true"
|
|
709
712
|
(onClick)="showTestDialog.set(false)"
|
|
710
713
|
/>
|
|
711
714
|
<p-button
|
|
712
|
-
[label]="'email.template.send
|
|
715
|
+
[label]="'email.template.test.send' | translate"
|
|
713
716
|
icon="pi pi-send"
|
|
714
717
|
[loading]="isSendingTest()"
|
|
715
718
|
(onClick)="sendTestEmail()"
|
|
@@ -724,4 +727,4 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImpor
|
|
|
724
727
|
}] });
|
|
725
728
|
|
|
726
729
|
export { TemplateListComponent };
|
|
727
|
-
//# sourceMappingURL=flusys-ng-email-template-list.component-
|
|
730
|
+
//# sourceMappingURL=flusys-ng-email-template-list.component-DrtU0xLq.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"flusys-ng-email-template-list.component-DrtU0xLq.mjs","sources":["../../../projects/ng-email/pages/template/template-list.component.ts"],"sourcesContent":["import { Component, computed, inject, signal } from '@angular/core';\nimport { Router } from '@angular/router';\nimport {\n APP_CONFIG,\n DEFAULT_APP_NAME,\n TRANSLATE_ADAPTER,\n} from '@flusys/ng-core';\nimport { LAYOUT_AUTH_STATE } from '@flusys/ng-layout';\nimport {\n AngularModule,\n EMAIL_TEMPLATE_PERMISSIONS,\n HasPermissionDirective,\n PrimeModule,\n TranslatePipe,\n} from '@flusys/ng-shared';\nimport { ConfirmationService, MessageService } from 'primeng/api';\nimport { firstValueFrom } from 'rxjs';\nimport { IEmailConfig } from '../../interfaces/email-config.interface';\nimport { IEmailTemplate } from '../../interfaces/email-template.interface';\nimport { EmailConfigApiService } from '../../services/email-config-api.service';\nimport { EmailSendService } from '../../services/email-send.service';\nimport { EmailTemplateApiService } from '../../services/email-template-api.service';\n\n/**\n * Email template list component\n */\n@Component({\n selector: 'lib-template-list',\n imports: [AngularModule, PrimeModule, HasPermissionDirective, TranslatePipe],\n providers: [ConfirmationService, MessageService],\n template: `\n <div class=\"card\">\n <div\n class=\"flex flex-col sm:flex-row justify-between items-start sm:items-center gap-3 mb-4\"\n >\n <div>\n <h3 class=\"text-lg sm:text-xl font-semibold m-0\">\n {{ 'email.template.title' | translate }}\n </h3>\n @if (showCompanyInfo()) {\n <p class=\"text-sm text-muted-color mt-1\">\n {{ 'shared.company' | translate }}: {{ currentCompanyName() }}\n </p>\n }\n </div>\n <p-button\n *hasPermission=\"EMAIL_TEMPLATE_PERMISSIONS.CREATE\"\n [label]=\"'email.template.new' | translate\"\n icon=\"pi pi-plus\"\n (onClick)=\"onCreate()\"\n styleClass=\"w-full sm:w-auto\"\n />\n </div>\n\n <div class=\"overflow-x-auto -mx-4 sm:mx-0\">\n <p-table\n [value]=\"templates()\"\n [loading]=\"isLoading()\"\n [paginator]=\"totalRecords() > 0\"\n [rows]=\"pageSize()\"\n [first]=\"first()\"\n [totalRecords]=\"totalRecords()\"\n [lazy]=\"true\"\n (onLazyLoad)=\"onLazyLoad($event)\"\n [rowsPerPageOptions]=\"[10, 25, 50]\"\n styleClass=\"p-datatable-sm\"\n [tableStyle]=\"{ 'min-width': '50rem' }\"\n >\n <ng-template #header>\n <tr>\n <th>{{ 'shared.name' | translate }}</th>\n <th class=\"hidden md:table-cell\">\n {{ 'email.template.slug' | translate }}\n </th>\n <th class=\"hidden lg:table-cell\">\n {{ 'email.template.subject' | translate }}\n </th>\n <th>{{ 'shared.type' | translate }}</th>\n <th>{{ 'shared.status' | translate }}</th>\n <th class=\"hidden xl:table-cell\">\n {{ 'shared.created' | translate }}\n </th>\n <th class=\"w-[120px]\">{{ 'shared.actions' | translate }}</th>\n </tr>\n </ng-template>\n\n <ng-template #body let-template>\n <tr>\n <td>\n <i class=\"pi pi-envelope mr-2 text-muted-color\"></i>\n {{ template.name }}\n </td>\n <td class=\"hidden md:table-cell\">\n <code class=\"text-sm px-2 py-1 rounded text-text-color\">{{\n template.slug\n }}</code>\n </td>\n <td class=\"hidden lg:table-cell\">{{ template.subject }}</td>\n <td>\n <p-tag\n [value]=\"\n (template.isHtml\n ? 'email.template.html'\n : 'email.template.text'\n ) | translate\n \"\n [severity]=\"template.isHtml ? 'info' : 'secondary'\"\n />\n </td>\n <td>\n <p-tag\n [value]=\"\n (template.isActive ? 'shared.active' : 'shared.inactive')\n | translate\n \"\n [severity]=\"template.isActive ? 'success' : 'secondary'\"\n />\n </td>\n <td class=\"hidden xl:table-cell\">\n {{ template.createdAt | date: 'short' }}\n </td>\n <td>\n <div class=\"flex gap-1\">\n <p-button\n *hasPermission=\"EMAIL_TEMPLATE_PERMISSIONS.UPDATE\"\n icon=\"pi pi-send\"\n [text]=\"true\"\n size=\"small\"\n [pTooltip]=\"'email.template.test.send' | translate\"\n (onClick)=\"onTestSend(template)\"\n />\n <p-button\n *hasPermission=\"EMAIL_TEMPLATE_PERMISSIONS.UPDATE\"\n icon=\"pi pi-pencil\"\n [text]=\"true\"\n severity=\"secondary\"\n size=\"small\"\n [pTooltip]=\"'shared.edit' | translate\"\n (onClick)=\"onEdit(template.id)\"\n />\n <p-button\n *hasPermission=\"EMAIL_TEMPLATE_PERMISSIONS.DELETE\"\n icon=\"pi pi-trash\"\n [text]=\"true\"\n severity=\"danger\"\n size=\"small\"\n [pTooltip]=\"'shared.delete' | translate\"\n (onClick)=\"onDelete(template)\"\n />\n </div>\n </td>\n </tr>\n </ng-template>\n\n <ng-template #emptymessage>\n <tr>\n <td colspan=\"7\" class=\"text-center py-4 text-muted-color\">\n {{ 'email.template.empty' | translate }}\n </td>\n </tr>\n </ng-template>\n </p-table>\n </div>\n </div>\n\n <!-- Test Send Dialog -->\n <p-dialog\n [header]=\"'email.template.test.dialog.title' | translate\"\n [visible]=\"showTestDialog()\"\n (visibleChange)=\"showTestDialog.set($event)\"\n [modal]=\"true\"\n [style]=\"{ width: '95vw', maxWidth: '500px', maxHeight: '80vh' }\"\n [breakpoints]=\"{ '575px': '95vw' }\"\n >\n <div class=\"flex flex-col gap-4\">\n <div class=\"field\">\n <label class=\"block font-medium mb-2\">{{\n 'email.template.template' | translate\n }}</label>\n <input\n pInputText\n [value]=\"selectedTemplate()?.name || ''\"\n class=\"w-full\"\n [disabled]=\"true\"\n />\n </div>\n\n <div class=\"field\">\n <label class=\"block font-medium mb-2\"\n >{{ 'email.template.email.config' | translate }} *</label\n >\n <p-select\n [ngModel]=\"testSendModel.configId\"\n (ngModelChange)=\"updateTestSendModel('configId', $event)\"\n [options]=\"configOptions()\"\n optionLabel=\"label\"\n optionValue=\"value\"\n [placeholder]=\"'email.template.select.config' | translate\"\n class=\"w-full\"\n [loading]=\"isLoadingConfigs()\"\n />\n </div>\n\n <div class=\"field\">\n <label class=\"block font-medium mb-2\"\n >{{ 'email.config.recipient.email' | translate }} *</label\n >\n <input\n pInputText\n [ngModel]=\"testSendModel.recipient\"\n (ngModelChange)=\"updateTestSendModel('recipient', $event)\"\n class=\"w-full\"\n [placeholder]=\"'email.recipient.example' | translate\"\n />\n </div>\n\n <!-- Dynamic Variables -->\n @if (templateVariables().length > 0) {\n <div class=\"border-t border-surface pt-4 mt-2\">\n <h4 class=\"font-medium mb-3 flex items-center gap-2\">\n <i class=\"pi pi-code text-muted-color\"></i>\n {{ 'email.template.variables' | translate }}\n </h4>\n <div class=\"flex flex-col gap-3\">\n @for (variable of templateVariables(); track variable) {\n <div class=\"field\">\n <label class=\"block text-sm font-medium mb-1\">\n <code\n class=\"text-primary bg-surface-100 dark:bg-surface-700 px-1 rounded\"\n >{{ '{{' + variable + '}}' }}</code\n >\n </label>\n <input\n pInputText\n [ngModel]=\"variableValues[variable] || ''\"\n (ngModelChange)=\"updateVariableValue(variable, $event)\"\n class=\"w-full\"\n [placeholder]=\"\n translate('email.template.enter.value.for', {\n variable: variable,\n })\n \"\n />\n </div>\n }\n </div>\n </div>\n }\n </div>\n\n <ng-template #footer>\n <p-button\n [label]=\"'shared.cancel' | translate\"\n severity=\"secondary\"\n [outlined]=\"true\"\n (onClick)=\"showTestDialog.set(false)\"\n />\n <p-button\n [label]=\"'email.template.test.send' | translate\"\n icon=\"pi pi-send\"\n [loading]=\"isSendingTest()\"\n (onClick)=\"sendTestEmail()\"\n />\n </ng-template>\n </p-dialog>\n\n <p-confirmDialog />\n <p-toast />\n `,\n})\nexport class TemplateListComponent {\n // Permission constants for template\n readonly EMAIL_TEMPLATE_PERMISSIONS = EMAIL_TEMPLATE_PERMISSIONS;\n\n private readonly router = inject(Router);\n private readonly templateService = inject(EmailTemplateApiService);\n private readonly configService = inject(EmailConfigApiService);\n private readonly emailSendService = inject(EmailSendService);\n private readonly confirmationService = inject(ConfirmationService);\n private readonly messageService = inject(MessageService);\n private readonly appConfig = inject(APP_CONFIG);\n private readonly companyContext = inject(LAYOUT_AUTH_STATE, {\n optional: true,\n });\n private readonly translateAdapter = inject(TRANSLATE_ADAPTER, {\n optional: true,\n });\n\n readonly isLoading = signal(false);\n readonly templates = signal<IEmailTemplate[]>([]);\n readonly totalRecords = signal(0);\n readonly pageSize = signal(10);\n readonly first = signal(0);\n\n readonly showCompanyInfo = computed(\n () => this.appConfig.enableCompanyFeature && !!this.companyContext,\n );\n readonly currentCompanyName = computed(\n () => this.companyContext?.currentCompanyInfo()?.name ?? DEFAULT_APP_NAME,\n );\n // Test send dialog (signals for zoneless change detection)\n readonly showTestDialog = signal(false);\n readonly selectedTemplate = signal<IEmailTemplate | null>(null);\n readonly configs = signal<IEmailConfig[]>([]);\n readonly isLoadingConfigs = signal(false);\n readonly isSendingTest = signal(false);\n\n // Form-bound properties as signals for zoneless change detection\n private readonly _testSendModel = signal({ configId: '', recipient: '' });\n private readonly _variableValues = signal<Record<string, string>>({});\n\n get testSendModel() {\n return this._testSendModel();\n }\n\n get variableValues() {\n return this._variableValues();\n }\n\n updateTestSendModel<K extends 'configId' | 'recipient'>(\n field: K,\n value: string,\n ): void {\n this._testSendModel.update((m) => ({ ...m, [field]: value }));\n }\n\n updateVariableValue(key: string, value: string): void {\n this._variableValues.update((v) => ({ ...v, [key]: value }));\n }\n\n readonly configOptions = computed(() =>\n this.configs().map((c) => ({\n label: `${c.name} (${this.translate(`email.provider.${c.provider}`)})`,\n value: c.id,\n })),\n );\n\n /** Extract variables from template content */\n readonly templateVariables = computed(() => {\n const template = this.selectedTemplate();\n if (!template) return [];\n\n // Combine all content sources to extract variables\n const content = [\n template.subject,\n template.htmlContent,\n template.textContent || '',\n ].join(' ');\n\n // Find all {{variableName}} patterns\n const matches = content.matchAll(/\\{\\{(\\w+)\\}\\}/g);\n const variables = new Set<string>();\n\n for (const match of matches) {\n variables.add(match[1]);\n }\n\n return Array.from(variables).sort();\n });\n\n onCreate(): void {\n this.router.navigate(['/email/templates/new']);\n }\n\n onEdit(templateId: string): void {\n this.router.navigate(['/email/templates', templateId]);\n }\n\n async loadTemplates(): Promise<void> {\n this.isLoading.set(true);\n try {\n const response = await this.templateService.getAll({\n pagination: {\n currentPage: Math.floor(this.first() / this.pageSize()),\n pageSize: this.pageSize(),\n },\n filter: {},\n select: [],\n sort: {},\n });\n\n if (response.success) {\n this.templates.set(response.data ?? []);\n this.totalRecords.set(response.meta?.total ?? 0);\n }\n } catch {\n // Error toast handled by global interceptor\n } finally {\n this.isLoading.set(false);\n }\n }\n\n onLazyLoad(event: { first?: number | null; rows?: number | null }): void {\n this.first.set(event.first ?? 0);\n this.pageSize.set(event.rows ?? 10);\n this.loadTemplates();\n }\n\n async onTestSend(template: IEmailTemplate): Promise<void> {\n this.selectedTemplate.set(template);\n this._testSendModel.set({ configId: '', recipient: '' });\n this._variableValues.set({}); // Reset variable values\n this.showTestDialog.set(true);\n await this.loadConfigs();\n }\n\n async loadConfigs(): Promise<void> {\n this.isLoadingConfigs.set(true);\n try {\n const response = await this.configService.getAll({\n pagination: { currentPage: 0, pageSize: 100 },\n filter: { isActive: true },\n select: [],\n sort: {},\n });\n if (response.success) {\n this.configs.set(response.data ?? []);\n }\n } catch {\n // Error toast handled by global interceptor\n } finally {\n this.isLoadingConfigs.set(false);\n }\n }\n\n async sendTestEmail(): Promise<void> {\n const template = this.selectedTemplate();\n const model = this.testSendModel;\n if (!template || !model.configId || !model.recipient) {\n this.messageService.add({\n severity: 'warn',\n summary: this.translate('shared.validation'),\n detail: this.translate('email.template.select.config.and.recipient'),\n });\n return;\n }\n\n this.isSendingTest.set(true);\n try {\n // Build variables object (only include non-empty values)\n const variables: Record<string, string> = {};\n for (const [key, value] of Object.entries(this.variableValues)) {\n if (value) {\n variables[key] = value;\n }\n }\n\n const response = await firstValueFrom(\n this.emailSendService.sendTemplate({\n templateId: template.id,\n to: model.recipient,\n emailConfigId: model.configId,\n variables: Object.keys(variables).length > 0 ? variables : undefined,\n }),\n );\n\n if (response.data?.success) {\n this.messageService.add({\n severity: 'success',\n summary: this.translate('shared.success'),\n detail: response.messageKey\n ? this.translate(\n response.messageKey,\n response.messageVariables as Record<string, string | number>,\n )\n : response.message,\n });\n this.showTestDialog.set(false);\n } else {\n this.messageService.add({\n severity: 'error',\n summary: this.translate('shared.error'),\n detail: response.messageKey\n ? this.translate(\n response.messageKey,\n response.messageVariables as Record<string, string | number>,\n )\n : response.data?.error,\n });\n }\n } catch {\n // Error toast handled by global interceptor\n } finally {\n this.isSendingTest.set(false);\n }\n }\n\n onDelete(template: IEmailTemplate): void {\n this.confirmationService.confirm({\n message: this.translate('shared.confirm.delete.item', {\n name: template.name,\n }),\n header: this.translate('email.template.delete.title'),\n icon: 'pi pi-exclamation-triangle',\n acceptButtonStyleClass: 'p-button-danger',\n accept: async () => {\n try {\n const response = await this.templateService.delete({\n id: template.id,\n type: 'delete',\n });\n this.messageService.add({\n severity: 'success',\n summary: this.translate('shared.success'),\n detail: response?.messageKey\n ? this.translate(\n response.messageKey,\n response.messageVariables as Record<string, string | number>,\n )\n : (response?.message ?? ''),\n });\n this.loadTemplates();\n } catch {\n // Error toast handled by global interceptor\n }\n },\n });\n }\n\n /** Translate helper - public for template usage with dynamic variables */\n translate(key: string, variables?: Record<string, string | number>): string {\n return this.translateAdapter?.translate(key, variables) ?? key;\n }\n}\n"],"names":["i9"],"mappings":"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"}
|