@flusys/ng-email 4.1.0 → 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.
@@ -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.findByIdAsync(id);
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('common.validation'),
181
- detail: this.translate('common.fill.required.fields'),
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
- if (this.isEditMode()) {
208
- await this.templateService.updateAsync({ id: model.id, ...data });
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('common.success'),
216
- detail: this.translate(this.isEditMode()
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
- {{ 'common.company' | translate }}: {{ currentCompanyName() }}
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
- 'common.description' | translate
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>{{ 'common.active' | translate }}</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]="'common.cancel' | translate"
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() ? 'common.update' : 'common.create') | translate
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
- {{ 'common.company' | translate }}: {{ currentCompanyName() }}
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
- 'common.description' | translate
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>{{ 'common.active' | translate }}</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]="'common.cancel' | translate"
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() ? 'common.update' : 'common.create') | translate
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-B2vIO6ow.mjs.map
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.providers.${c.provider}`)})`,
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 firstValueFrom(this.templateService.getAll('', {
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 firstValueFrom(this.configService.getAll('', {
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('common.validation'),
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('common.success'),
184
- detail: this.translate('email.template.test.sent.success', {
185
- messageId: response.data.messageId ?? '',
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('common.error'),
194
- detail: response.data?.error ||
195
- this.translate('email.template.test.sent.failed'),
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('email.template.delete.confirm', {
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.deleteAsync({
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('common.success'),
223
- detail: this.translate('email.template.deleted'),
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
- {{ 'common.company' | translate }}: {{ currentCompanyName() }}
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>{{ 'common.name' | translate }}</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>{{ 'common.type' | translate }}</th>
286
- <th>{{ 'common.status' | translate }}</th>
288
+ <th>{{ 'shared.type' | translate }}</th>
289
+ <th>{{ 'shared.status' | translate }}</th>
287
290
  <th class="hidden xl:table-cell">
288
- {{ 'common.created' | translate }}
291
+ {{ 'shared.created' | translate }}
289
292
  </th>
290
- <th class="w-[120px]">{{ 'common.actions' | translate }}</th>
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 ? 'common.active' : 'common.inactive')
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]="'common.edit' | translate"
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]="'common.delete' | translate"
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]="'common.cancel' | translate"
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.test' | translate"
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
- {{ 'common.company' | translate }}: {{ currentCompanyName() }}
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>{{ 'common.name' | translate }}</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>{{ 'common.type' | translate }}</th>
532
- <th>{{ 'common.status' | translate }}</th>
534
+ <th>{{ 'shared.type' | translate }}</th>
535
+ <th>{{ 'shared.status' | translate }}</th>
533
536
  <th class="hidden xl:table-cell">
534
- {{ 'common.created' | translate }}
537
+ {{ 'shared.created' | translate }}
535
538
  </th>
536
- <th class="w-[120px]">{{ 'common.actions' | translate }}</th>
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 ? 'common.active' : 'common.inactive')
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]="'common.edit' | translate"
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]="'common.delete' | translate"
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]="'common.cancel' | translate"
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.test' | translate"
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-0PJxS33a.mjs.map
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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"}