@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.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flusys-ng-email-email-config-form.component-M0g9fxU1.mjs","sources":["../../../projects/ng-email/pages/config/email-config-form.component.ts"],"sourcesContent":["import { Component, computed, effect, inject, signal } from '@angular/core';\nimport { toSignal } from '@angular/core/rxjs-interop';\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 { EmailProviderEnum } from '../../enums/email-provider.enum';\nimport {\n EmailProviderConfig,\n IEmailConfig,\n IMailgunConfig,\n ISendGridConfig,\n ISmtpConfig,\n} from '../../interfaces/email-config.interface';\nimport { EmailConfigApiService } from '../../services/email-config-api.service';\n\n/**\n * Email configuration form component (create/edit)\n */\n@Component({\n selector: 'lib-email-config-form',\n imports: [AngularModule, PrimeModule, TranslatePipe],\n providers: [MessageService],\n template: `\n <div class=\"card\">\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.config.edit.title'\n : 'email.config.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 <!-- Common Fields -->\n <div class=\"field\">\n <label for=\"name\" class=\"block font-medium mb-2\"\n >{{ 'email.config.name' | translate }} *</label\n >\n <input\n pInputText\n id=\"name\"\n [ngModel]=\"formModel.name\"\n (ngModelChange)=\"updateFormModel('name', $event)\"\n class=\"w-full\"\n [placeholder]=\"'email.config.name.example' | translate\"\n />\n </div>\n\n <div class=\"field\">\n <label for=\"provider\" class=\"block font-medium mb-2\"\n >{{ 'email.config.provider' | translate }} *</label\n >\n <p-select\n id=\"provider\"\n [options]=\"providerOptions()\"\n [ngModel]=\"formModel.provider\"\n (ngModelChange)=\"updateFormModel('provider', $event)\"\n optionLabel=\"label\"\n optionValue=\"value\"\n [placeholder]=\"'email.config.select.provider' | translate\"\n class=\"w-full\"\n />\n </div>\n\n <div class=\"field\">\n <label for=\"fromEmail\" class=\"block font-medium mb-2\">{{\n 'email.config.from.email' | translate\n }}</label>\n <input\n pInputText\n id=\"fromEmail\"\n [ngModel]=\"formModel.fromEmail\"\n (ngModelChange)=\"updateFormModel('fromEmail', $event)\"\n class=\"w-full\"\n [placeholder]=\"'email.config.from.email.example' | translate\"\n />\n </div>\n\n <div class=\"field\">\n <label for=\"fromName\" class=\"block font-medium mb-2\">{{\n 'email.config.from.name' | translate\n }}</label>\n <input\n pInputText\n id=\"fromName\"\n [ngModel]=\"formModel.fromName\"\n (ngModelChange)=\"updateFormModel('fromName', $event)\"\n class=\"w-full\"\n [placeholder]=\"'email.config.from.name.example' | translate\"\n />\n </div>\n\n <div class=\"field flex items-center gap-2\">\n <p-toggleswitch\n [ngModel]=\"formModel.isActive\"\n (ngModelChange)=\"updateFormModel('isActive', $event)\"\n />\n <label>{{ 'shared.active' | translate }}</label>\n </div>\n\n <div class=\"field flex items-center gap-2\">\n <p-toggleswitch\n [ngModel]=\"formModel.isDefault\"\n (ngModelChange)=\"updateFormModel('isDefault', $event)\"\n />\n <label>{{ 'email.config.set.as.default' | translate }}</label>\n </div>\n </div>\n\n <!-- SMTP Fields -->\n @if (formModel.provider === providerEnum.SMTP) {\n <div class=\"border-t border-surface mt-4 pt-4\">\n <h3 class=\"font-semibold mb-4\">\n {{ 'email.config.smtp.settings' | translate }}\n </h3>\n <div class=\"grid grid-cols-1 md:grid-cols-2 gap-4\">\n <div class=\"field\">\n <label for=\"smtpHost\" class=\"block font-medium mb-2\"\n >{{ 'email.config.smtp.host' | translate }} *</label\n >\n <input\n pInputText\n id=\"smtpHost\"\n [ngModel]=\"formModel.smtpHost\"\n (ngModelChange)=\"updateFormModel('smtpHost', $event)\"\n class=\"w-full\"\n [placeholder]=\"'email.config.smtp.host.example' | translate\"\n />\n </div>\n <div class=\"field\">\n <label for=\"smtpPort\" class=\"block font-medium mb-2\"\n >{{ 'email.config.port' | translate }} *</label\n >\n <p-inputNumber\n id=\"smtpPort\"\n [ngModel]=\"formModel.smtpPort\"\n (ngModelChange)=\"updateFormModel('smtpPort', $event)\"\n [useGrouping]=\"false\"\n class=\"w-full\"\n [placeholder]=\"'email.config.smtp.port.example' | translate\"\n />\n </div>\n <div class=\"field\">\n <label for=\"smtpUser\" class=\"block font-medium mb-2\"\n >{{ 'email.config.username' | translate }} *</label\n >\n <input\n pInputText\n id=\"smtpUser\"\n [ngModel]=\"formModel.smtpUser\"\n (ngModelChange)=\"updateFormModel('smtpUser', $event)\"\n class=\"w-full\"\n [placeholder]=\"'email.config.smtp.user.example' | translate\"\n />\n </div>\n <div class=\"field\">\n <label for=\"smtpPass\" class=\"block font-medium mb-2\"\n >{{ 'email.config.password' | translate }} *</label\n >\n <p-password\n id=\"smtpPass\"\n [ngModel]=\"formModel.smtpPass\"\n (ngModelChange)=\"updateFormModel('smtpPass', $event)\"\n [feedback]=\"false\"\n [toggleMask]=\"true\"\n styleClass=\"w-full\"\n inputStyleClass=\"w-full\"\n [placeholder]=\"'email.config.smtp.password.example' | translate\"\n />\n </div>\n <div class=\"field flex items-center gap-2\">\n <p-toggleswitch\n [ngModel]=\"formModel.smtpSecure\"\n (ngModelChange)=\"updateFormModel('smtpSecure', $event)\"\n />\n <label>{{ 'email.config.use.ssl.tls' | translate }}</label>\n </div>\n </div>\n </div>\n }\n\n <!-- SendGrid Fields -->\n @if (formModel.provider === providerEnum.SENDGRID) {\n <div class=\"border-t border-surface mt-4 pt-4\">\n <h3 class=\"font-semibold mb-4\">\n {{ 'email.config.sendgrid.settings' | translate }}\n </h3>\n <div class=\"grid grid-cols-1 gap-4\">\n <div class=\"field\">\n <label for=\"sendgridApiKey\" class=\"block font-medium mb-2\"\n >{{ 'email.config.api.key' | translate }} *</label\n >\n <p-password\n id=\"sendgridApiKey\"\n [ngModel]=\"formModel.sendgridApiKey\"\n (ngModelChange)=\"updateFormModel('sendgridApiKey', $event)\"\n [feedback]=\"false\"\n [toggleMask]=\"true\"\n styleClass=\"w-full\"\n inputStyleClass=\"w-full\"\n [placeholder]=\"'email.config.api.key.example' | translate\"\n />\n </div>\n </div>\n </div>\n }\n\n <!-- Mailgun Fields -->\n @if (formModel.provider === providerEnum.MAILGUN) {\n <div class=\"border-t border-surface mt-4 pt-4\">\n <h3 class=\"font-semibold mb-4\">\n {{ 'email.config.mailgun.settings' | translate }}\n </h3>\n <div class=\"grid grid-cols-1 md:grid-cols-2 gap-4\">\n <div class=\"field\">\n <label for=\"mailgunApiKey\" class=\"block font-medium mb-2\"\n >{{ 'email.config.api.key' | translate }} *</label\n >\n <p-password\n id=\"mailgunApiKey\"\n [ngModel]=\"formModel.mailgunApiKey\"\n (ngModelChange)=\"updateFormModel('mailgunApiKey', $event)\"\n [feedback]=\"false\"\n [toggleMask]=\"true\"\n styleClass=\"w-full\"\n inputStyleClass=\"w-full\"\n [placeholder]=\"'email.config.api.key.example' | translate\"\n />\n </div>\n <div class=\"field\">\n <label for=\"mailgunDomain\" class=\"block font-medium mb-2\"\n >{{ 'email.config.domain' | translate }} *</label\n >\n <input\n pInputText\n id=\"mailgunDomain\"\n [ngModel]=\"formModel.mailgunDomain\"\n (ngModelChange)=\"updateFormModel('mailgunDomain', $event)\"\n class=\"w-full\"\n [placeholder]=\"'email.config.domain.example' | translate\"\n />\n </div>\n <div class=\"field\">\n <label for=\"mailgunRegion\" class=\"block font-medium mb-2\">{{\n 'email.config.region' | translate\n }}</label>\n <p-select\n id=\"mailgunRegion\"\n [options]=\"regionOptions()\"\n [ngModel]=\"formModel.mailgunRegion\"\n (ngModelChange)=\"updateFormModel('mailgunRegion', $event)\"\n optionLabel=\"label\"\n optionValue=\"value\"\n [placeholder]=\"'email.config.select.region' | translate\"\n class=\"w-full\"\n />\n </div>\n </div>\n </div>\n }\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 (onClick)=\"onSave()\"\n />\n </div>\n </div>\n\n <p-toast />\n `,\n})\nexport class EmailConfigFormComponent {\n private readonly route = inject(ActivatedRoute);\n private readonly router = inject(Router);\n private readonly configService = inject(EmailConfigApiService);\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 // Route params as signal\n private readonly routeParams = toSignal(this.route.paramMap);\n\n readonly providerEnum = EmailProviderEnum;\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 readonly isLoading = signal(false);\n readonly existingConfig = signal<IEmailConfig | null>(null);\n readonly isEditMode = computed(() => !!this.existingConfig());\n\n readonly providerOptions = computed(() => [\n {\n label: this.translate('email.provider.smtp'),\n value: EmailProviderEnum.SMTP,\n },\n {\n label: this.translate('email.provider.sendgrid'),\n value: EmailProviderEnum.SENDGRID,\n },\n {\n label: this.translate('email.provider.mailgun'),\n value: EmailProviderEnum.MAILGUN,\n },\n ]);\n\n readonly regionOptions = computed(() => [\n { label: this.translate('email.region.us'), value: 'us' },\n { label: this.translate('email.region.eu'), value: 'eu' },\n ]);\n\n /** Form model as signal for zoneless change detection */\n private readonly _formModel = signal({\n id: '',\n name: '',\n provider: EmailProviderEnum.SMTP as EmailProviderEnum,\n fromEmail: '',\n fromName: '',\n isActive: true,\n isDefault: false,\n // SMTP\n smtpHost: '',\n smtpPort: 587,\n smtpUser: '',\n smtpPass: '',\n smtpSecure: false,\n // SendGrid\n sendgridApiKey: '',\n // Mailgun\n mailgunApiKey: '',\n mailgunDomain: '',\n mailgunRegion: 'us',\n });\n\n /** Expose form model for template binding */\n get formModel() {\n return this._formModel();\n }\n\n /** Update form model field - triggers change detection */\n updateFormModel<K extends keyof ReturnType<typeof this._formModel>>(\n field: K,\n value: ReturnType<typeof this._formModel>[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.loadConfig(id);\n }\n });\n }\n\n async loadConfig(id: string): Promise<void> {\n this.isLoading.set(true);\n try {\n const response = await this.configService.findById(id);\n if (response.success && response.data) {\n const emailConfig = response.data;\n this.existingConfig.set(emailConfig);\n this._formModel.set(this.mapConfigToFormModel(emailConfig));\n }\n } catch {\n // Error toast handled by global interceptor\n } finally {\n this.isLoading.set(false);\n }\n }\n\n private mapConfigToFormModel(emailConfig: IEmailConfig) {\n const providerConfig = emailConfig.config;\n\n return {\n id: emailConfig.id,\n name: emailConfig.name,\n provider: emailConfig.provider,\n fromEmail: emailConfig.fromEmail || '',\n fromName: emailConfig.fromName || '',\n isActive: emailConfig.isActive,\n isDefault: emailConfig.isDefault ?? false,\n // SMTP fields\n smtpHost: this.isSmtpConfig(providerConfig) ? providerConfig.host : '',\n smtpPort: this.isSmtpConfig(providerConfig) ? providerConfig.port : 587,\n smtpUser: this.isSmtpConfig(providerConfig)\n ? providerConfig.auth.user\n : '',\n smtpPass: this.isSmtpConfig(providerConfig)\n ? providerConfig.auth.pass\n : '',\n smtpSecure: this.isSmtpConfig(providerConfig)\n ? (providerConfig.secure ?? false)\n : false,\n // SendGrid fields\n sendgridApiKey: this.isSendGridConfig(providerConfig)\n ? providerConfig.apiKey\n : '',\n // Mailgun fields\n mailgunApiKey: this.isMailgunConfig(providerConfig)\n ? providerConfig.apiKey\n : '',\n mailgunDomain: this.isMailgunConfig(providerConfig)\n ? providerConfig.domain\n : '',\n mailgunRegion: this.isMailgunConfig(providerConfig)\n ? (providerConfig.region ?? 'us')\n : 'us',\n };\n }\n\n private isSmtpConfig(config: EmailProviderConfig): config is ISmtpConfig {\n return 'host' in config && 'auth' in config;\n }\n\n private isSendGridConfig(\n config: EmailProviderConfig,\n ): config is ISendGridConfig {\n return 'apiKey' in config && !('domain' in config);\n }\n\n private isMailgunConfig(\n config: EmailProviderConfig,\n ): config is IMailgunConfig {\n return 'apiKey' in config && 'domain' in config;\n }\n\n private buildProviderConfig(): EmailProviderConfig {\n const form = this.formModel;\n\n switch (form.provider) {\n case EmailProviderEnum.SMTP:\n return {\n host: form.smtpHost,\n port: form.smtpPort,\n secure: form.smtpSecure,\n auth: { user: form.smtpUser, pass: form.smtpPass },\n } satisfies ISmtpConfig;\n\n case EmailProviderEnum.SENDGRID:\n return { apiKey: form.sendgridApiKey } satisfies ISendGridConfig;\n\n case EmailProviderEnum.MAILGUN:\n return {\n apiKey: form.mailgunApiKey,\n domain: form.mailgunDomain,\n region: form.mailgunRegion as 'us' | 'eu',\n } satisfies IMailgunConfig;\n }\n }\n\n async onSave(): Promise<void> {\n if (!this.formModel.name || !this.formModel.provider) {\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 dto = this.buildSaveDto();\n\n const response = this.isEditMode()\n ? await this.configService.update({ id: this.formModel.id, ...dto })\n : await this.configService.insert(dto);\n\n const r = response as unknown as {\n messageKey?: string;\n messageVariables?: Record<string, string | number>;\n message?: string;\n };\n this.messageService.add({\n severity: 'success',\n summary: this.translate('shared.success'),\n detail: r?.messageKey\n ? this.translate(r.messageKey, r.messageVariables)\n : (r?.message ?? ''),\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(\n key: string,\n variables?: Record<string, string | number>,\n ): string {\n return this.translateAdapter?.translate(key, variables) ?? key;\n }\n\n private buildSaveDto() {\n return {\n name: this.formModel.name,\n provider: this.formModel.provider,\n config: this.buildProviderConfig(),\n fromEmail: this.formModel.fromEmail || undefined,\n fromName: this.formModel.fromName || undefined,\n isActive: this.formModel.isActive,\n isDefault: this.formModel.isDefault,\n };\n }\n}\n"],"names":["i3","i7","i9"],"mappings":"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"}
@@ -1,11 +1,11 @@
1
1
  import * as i0 from '@angular/core';
2
2
  import { inject, signal, computed, Component } from '@angular/core';
3
3
  import { Router } from '@angular/router';
4
- import { firstValueFrom } from 'rxjs';
5
4
  import { APP_CONFIG, TRANSLATE_ADAPTER, DEFAULT_APP_NAME } from '@flusys/ng-core';
6
5
  import { LAYOUT_AUTH_STATE } from '@flusys/ng-layout';
7
6
  import { EMAIL_CONFIG_PERMISSIONS, AngularModule, PrimeModule, HasPermissionDirective, TranslatePipe } from '@flusys/ng-shared';
8
7
  import { ConfirmationService, MessageService } from 'primeng/api';
8
+ import { firstValueFrom } from 'rxjs';
9
9
  import { EmailConfigApiService, EmailProviderEnum } from './flusys-ng-email.mjs';
10
10
  import * as i1 from '@angular/forms';
11
11
  import * as i2 from 'primeng/button';
@@ -29,8 +29,12 @@ class EmailConfigListComponent {
29
29
  confirmationService = inject(ConfirmationService);
30
30
  messageService = inject(MessageService);
31
31
  appConfig = inject(APP_CONFIG);
32
- companyContext = inject(LAYOUT_AUTH_STATE, { optional: true });
33
- translateAdapter = inject(TRANSLATE_ADAPTER, { optional: true });
32
+ companyContext = inject(LAYOUT_AUTH_STATE, {
33
+ optional: true,
34
+ });
35
+ translateAdapter = inject(TRANSLATE_ADAPTER, {
36
+ optional: true,
37
+ });
34
38
  isLoading = signal(false, ...(ngDevMode ? [{ debugName: "isLoading" }] : []));
35
39
  configs = signal([], ...(ngDevMode ? [{ debugName: "configs" }] : []));
36
40
  totalRecords = signal(0, ...(ngDevMode ? [{ debugName: "totalRecords" }] : []));
@@ -52,7 +56,7 @@ class EmailConfigListComponent {
52
56
  async loadConfigs() {
53
57
  this.isLoading.set(true);
54
58
  try {
55
- const response = await firstValueFrom(this.configService.getAll('', {
59
+ const response = await this.configService.getAll({
56
60
  pagination: {
57
61
  currentPage: Math.floor(this.first() / this.pageSize()),
58
62
  pageSize: this.pageSize(),
@@ -60,7 +64,7 @@ class EmailConfigListComponent {
60
64
  filter: {},
61
65
  select: [],
62
66
  sort: {},
63
- }));
67
+ });
64
68
  if (response.success) {
65
69
  this.configs.set(response.data ?? []);
66
70
  this.totalRecords.set(response.meta?.total ?? 0);
@@ -79,11 +83,27 @@ class EmailConfigListComponent {
79
83
  this.loadConfigs();
80
84
  }
81
85
  providerMeta = {
82
- [EmailProviderEnum.SMTP]: { icon: 'pi pi-server', labelKey: 'email.providers.smtp', severity: 'info' },
83
- [EmailProviderEnum.SENDGRID]: { icon: 'pi pi-cloud', labelKey: 'email.providers.sendgrid', severity: 'success' },
84
- [EmailProviderEnum.MAILGUN]: { icon: 'pi pi-cloud', labelKey: 'email.providers.mailgun', severity: 'warn' },
86
+ [EmailProviderEnum.SMTP]: {
87
+ icon: 'pi pi-server',
88
+ labelKey: 'email.provider.smtp',
89
+ severity: 'info',
90
+ },
91
+ [EmailProviderEnum.SENDGRID]: {
92
+ icon: 'pi pi-cloud',
93
+ labelKey: 'email.provider.sendgrid',
94
+ severity: 'success',
95
+ },
96
+ [EmailProviderEnum.MAILGUN]: {
97
+ icon: 'pi pi-cloud',
98
+ labelKey: 'email.provider.mailgun',
99
+ severity: 'warn',
100
+ },
101
+ };
102
+ defaultProviderMeta = {
103
+ icon: 'pi pi-envelope',
104
+ labelKey: '',
105
+ severity: 'secondary',
85
106
  };
86
- defaultProviderMeta = { icon: 'pi pi-envelope', labelKey: '', severity: 'secondary' };
87
107
  getProviderIcon(provider) {
88
108
  return this.providerMeta[provider]?.icon ?? this.defaultProviderMeta.icon;
89
109
  }
@@ -93,10 +113,10 @@ class EmailConfigListComponent {
93
113
  return this.translate(labelKey);
94
114
  }
95
115
  // Fallback to dynamic key for unknown providers
96
- return provider ? this.translate(`email.providers.${provider}`) : '';
116
+ return provider ? this.translate(`email.provider.${provider}`) : '';
97
117
  }
98
118
  getProviderSeverity(provider) {
99
- return this.providerMeta[provider]?.severity ?? this.defaultProviderMeta.severity;
119
+ return (this.providerMeta[provider]?.severity ?? this.defaultProviderMeta.severity);
100
120
  }
101
121
  onTest(config) {
102
122
  this.selectedConfig.set(config);
@@ -109,7 +129,7 @@ class EmailConfigListComponent {
109
129
  if (!config || !recipient) {
110
130
  this.messageService.add({
111
131
  severity: 'warn',
112
- summary: this.translate('common.validation'),
132
+ summary: this.translate('shared.validation'),
113
133
  detail: this.translate('email.config.enter.recipient'),
114
134
  });
115
135
  return;
@@ -117,21 +137,15 @@ class EmailConfigListComponent {
117
137
  this.isSendingTest.set(true);
118
138
  try {
119
139
  const response = await firstValueFrom(this.configService.sendTest(config.id, recipient));
120
- if (response.data?.success) {
121
- this.messageService.add({
122
- severity: 'success',
123
- summary: this.translate('common.success'),
124
- detail: this.translate('email.config.test.sent.success', { messageId: response.data.messageId ?? '' }),
125
- });
126
- this.showTestDialog.set(false);
127
- }
128
- else {
129
- this.messageService.add({
130
- severity: 'error',
131
- summary: this.translate('common.error'),
132
- detail: response.data?.error || this.translate('email.config.test.sent.failed'),
133
- });
134
- }
140
+ const r = response;
141
+ this.messageService.add({
142
+ severity: 'success',
143
+ summary: this.translate('shared.success'),
144
+ detail: r?.messageKey
145
+ ? this.translate(r.messageKey, r.messageVariables)
146
+ : (r?.message ?? ''),
147
+ });
148
+ this.showTestDialog.set(false);
135
149
  }
136
150
  catch {
137
151
  // Error toast handled by global interceptor
@@ -142,17 +156,24 @@ class EmailConfigListComponent {
142
156
  }
143
157
  onDelete(config) {
144
158
  this.confirmationService.confirm({
145
- message: this.translate('email.config.delete.confirm', { name: config.name }),
159
+ message: this.translate('shared.confirm.delete.item', {
160
+ name: config.name,
161
+ }),
146
162
  header: this.translate('email.config.delete.title'),
147
163
  icon: 'pi pi-exclamation-triangle',
148
164
  acceptButtonStyleClass: 'p-button-danger',
149
165
  accept: async () => {
150
166
  try {
151
- await this.configService.deleteAsync({ id: config.id, type: 'delete' });
167
+ const response = await this.configService.delete({
168
+ id: config.id,
169
+ type: 'delete',
170
+ });
152
171
  this.messageService.add({
153
172
  severity: 'success',
154
- summary: this.translate('common.success'),
155
- detail: this.translate('email.config.deleted'),
173
+ summary: this.translate('shared.success'),
174
+ detail: response?.messageKey
175
+ ? this.translate(response.messageKey, response.messageVariables)
176
+ : (response?.message ?? ''),
156
177
  });
157
178
  this.loadConfigs();
158
179
  }
@@ -168,12 +189,16 @@ class EmailConfigListComponent {
168
189
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: EmailConfigListComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
169
190
  static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.5", type: EmailConfigListComponent, isStandalone: true, selector: "lib-email-config-list", providers: [ConfirmationService, MessageService], ngImport: i0, template: `
170
191
  <div class="card">
171
- <div class="flex flex-col sm:flex-row justify-between items-start sm:items-center gap-3 mb-4">
192
+ <div
193
+ class="flex flex-col sm:flex-row justify-between items-start sm:items-center gap-3 mb-4"
194
+ >
172
195
  <div>
173
- <h3 class="text-lg sm:text-xl font-semibold m-0">{{ 'email.config.title' | translate }}</h3>
196
+ <h3 class="text-lg sm:text-xl font-semibold m-0">
197
+ {{ 'email.config.title' | translate }}
198
+ </h3>
174
199
  @if (showCompanyInfo()) {
175
200
  <p class="text-sm text-muted-color mt-1">
176
- {{ 'common.company' | translate }}: {{ currentCompanyName() }}
201
+ {{ 'shared.company' | translate }}: {{ currentCompanyName() }}
177
202
  </p>
178
203
  }
179
204
  </div>
@@ -202,22 +227,33 @@ class EmailConfigListComponent {
202
227
  >
203
228
  <ng-template #header>
204
229
  <tr>
205
- <th>{{ 'common.name' | translate }}</th>
230
+ <th>{{ 'shared.name' | translate }}</th>
206
231
  <th>{{ 'email.config.provider' | translate }}</th>
207
- <th class="hidden md:table-cell">{{ 'email.config.from.email' | translate }}</th>
208
- <th>{{ 'common.status' | translate }}</th>
209
- <th class="hidden lg:table-cell">{{ 'common.created' | translate }}</th>
210
- <th class="w-[120px]">{{ 'common.actions' | translate }}</th>
232
+ <th class="hidden md:table-cell">
233
+ {{ 'email.config.from.email' | translate }}
234
+ </th>
235
+ <th>{{ 'shared.status' | translate }}</th>
236
+ <th class="hidden lg:table-cell">
237
+ {{ 'shared.created' | translate }}
238
+ </th>
239
+ <th class="w-[120px]">{{ 'shared.actions' | translate }}</th>
211
240
  </tr>
212
241
  </ng-template>
213
242
 
214
243
  <ng-template #body let-config>
215
244
  <tr>
216
245
  <td>
217
- <i [class]="getProviderIcon(config.provider)" class="mr-2 text-muted-color"></i>
246
+ <i
247
+ [class]="getProviderIcon(config.provider)"
248
+ class="mr-2 text-muted-color"
249
+ ></i>
218
250
  {{ config.name }}
219
251
  @if (config.isDefault) {
220
- <p-tag [value]="'common.default' | translate" severity="contrast" class="ml-2" />
252
+ <p-tag
253
+ [value]="'shared.default' | translate"
254
+ severity="contrast"
255
+ class="ml-2"
256
+ />
221
257
  }
222
258
  </td>
223
259
  <td>
@@ -226,14 +262,21 @@ class EmailConfigListComponent {
226
262
  [severity]="getProviderSeverity(config.provider)"
227
263
  />
228
264
  </td>
229
- <td class="hidden md:table-cell">{{ config.fromEmail || ('shared.na' | translate) }}</td>
265
+ <td class="hidden md:table-cell">
266
+ {{ config.fromEmail || ('shared.na' | translate) }}
267
+ </td>
230
268
  <td>
231
269
  <p-tag
232
- [value]="(config.isActive ? 'common.active' : 'common.inactive') | translate"
270
+ [value]="
271
+ (config.isActive ? 'shared.active' : 'shared.inactive')
272
+ | translate
273
+ "
233
274
  [severity]="config.isActive ? 'success' : 'secondary'"
234
275
  />
235
276
  </td>
236
- <td class="hidden lg:table-cell">{{ config.createdAt | date: 'short' }}</td>
277
+ <td class="hidden lg:table-cell">
278
+ {{ config.createdAt | date: 'short' }}
279
+ </td>
237
280
  <td>
238
281
  <div class="flex gap-1">
239
282
  <p-button
@@ -241,7 +284,7 @@ class EmailConfigListComponent {
241
284
  icon="pi pi-send"
242
285
  [text]="true"
243
286
  size="small"
244
- [pTooltip]="'common.test' | translate"
287
+ [pTooltip]="'email.config.test' | translate"
245
288
  (onClick)="onTest(config)"
246
289
  />
247
290
  <p-button
@@ -250,7 +293,7 @@ class EmailConfigListComponent {
250
293
  [text]="true"
251
294
  severity="secondary"
252
295
  size="small"
253
- [pTooltip]="'common.edit' | translate"
296
+ [pTooltip]="'shared.edit' | translate"
254
297
  (onClick)="onEdit(config.id)"
255
298
  />
256
299
  <p-button
@@ -259,7 +302,7 @@ class EmailConfigListComponent {
259
302
  [text]="true"
260
303
  severity="danger"
261
304
  size="small"
262
- [pTooltip]="'common.delete' | translate"
305
+ [pTooltip]="'shared.delete' | translate"
263
306
  (onClick)="onDelete(config)"
264
307
  />
265
308
  </div>
@@ -289,7 +332,9 @@ class EmailConfigListComponent {
289
332
  >
290
333
  <div class="grid gap-4">
291
334
  <div class="field">
292
- <label class="block font-medium mb-2">{{ 'email.config.configuration' | translate }}</label>
335
+ <label class="block font-medium mb-2">{{
336
+ 'email.config.configuration' | translate
337
+ }}</label>
293
338
  <input
294
339
  pInputText
295
340
  [value]="selectedConfig()?.name || ''"
@@ -299,7 +344,9 @@ class EmailConfigListComponent {
299
344
  </div>
300
345
 
301
346
  <div class="field">
302
- <label class="block font-medium mb-2">{{ 'email.config.provider' | translate }}</label>
347
+ <label class="block font-medium mb-2">{{
348
+ 'email.config.provider' | translate
349
+ }}</label>
303
350
  <p-tag
304
351
  [value]="getProviderLabel(selectedConfig()?.provider || '')"
305
352
  [severity]="getProviderSeverity(selectedConfig()?.provider || '')"
@@ -307,7 +354,9 @@ class EmailConfigListComponent {
307
354
  </div>
308
355
 
309
356
  <div class="field">
310
- <label class="block font-medium mb-2">{{ 'email.config.recipient.email' | translate }} *</label>
357
+ <label class="block font-medium mb-2"
358
+ >{{ 'email.config.recipient.email' | translate }} *</label
359
+ >
311
360
  <input
312
361
  pInputText
313
362
  [ngModel]="testRecipient()"
@@ -324,7 +373,7 @@ class EmailConfigListComponent {
324
373
 
325
374
  <ng-template #footer>
326
375
  <p-button
327
- [label]="'common.cancel' | translate"
376
+ [label]="'shared.cancel' | translate"
328
377
  severity="secondary"
329
378
  [outlined]="true"
330
379
  (onClick)="showTestDialog.set(false)"
@@ -350,12 +399,16 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImpor
350
399
  providers: [ConfirmationService, MessageService],
351
400
  template: `
352
401
  <div class="card">
353
- <div class="flex flex-col sm:flex-row justify-between items-start sm:items-center gap-3 mb-4">
402
+ <div
403
+ class="flex flex-col sm:flex-row justify-between items-start sm:items-center gap-3 mb-4"
404
+ >
354
405
  <div>
355
- <h3 class="text-lg sm:text-xl font-semibold m-0">{{ 'email.config.title' | translate }}</h3>
406
+ <h3 class="text-lg sm:text-xl font-semibold m-0">
407
+ {{ 'email.config.title' | translate }}
408
+ </h3>
356
409
  @if (showCompanyInfo()) {
357
410
  <p class="text-sm text-muted-color mt-1">
358
- {{ 'common.company' | translate }}: {{ currentCompanyName() }}
411
+ {{ 'shared.company' | translate }}: {{ currentCompanyName() }}
359
412
  </p>
360
413
  }
361
414
  </div>
@@ -384,22 +437,33 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImpor
384
437
  >
385
438
  <ng-template #header>
386
439
  <tr>
387
- <th>{{ 'common.name' | translate }}</th>
440
+ <th>{{ 'shared.name' | translate }}</th>
388
441
  <th>{{ 'email.config.provider' | translate }}</th>
389
- <th class="hidden md:table-cell">{{ 'email.config.from.email' | translate }}</th>
390
- <th>{{ 'common.status' | translate }}</th>
391
- <th class="hidden lg:table-cell">{{ 'common.created' | translate }}</th>
392
- <th class="w-[120px]">{{ 'common.actions' | translate }}</th>
442
+ <th class="hidden md:table-cell">
443
+ {{ 'email.config.from.email' | translate }}
444
+ </th>
445
+ <th>{{ 'shared.status' | translate }}</th>
446
+ <th class="hidden lg:table-cell">
447
+ {{ 'shared.created' | translate }}
448
+ </th>
449
+ <th class="w-[120px]">{{ 'shared.actions' | translate }}</th>
393
450
  </tr>
394
451
  </ng-template>
395
452
 
396
453
  <ng-template #body let-config>
397
454
  <tr>
398
455
  <td>
399
- <i [class]="getProviderIcon(config.provider)" class="mr-2 text-muted-color"></i>
456
+ <i
457
+ [class]="getProviderIcon(config.provider)"
458
+ class="mr-2 text-muted-color"
459
+ ></i>
400
460
  {{ config.name }}
401
461
  @if (config.isDefault) {
402
- <p-tag [value]="'common.default' | translate" severity="contrast" class="ml-2" />
462
+ <p-tag
463
+ [value]="'shared.default' | translate"
464
+ severity="contrast"
465
+ class="ml-2"
466
+ />
403
467
  }
404
468
  </td>
405
469
  <td>
@@ -408,14 +472,21 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImpor
408
472
  [severity]="getProviderSeverity(config.provider)"
409
473
  />
410
474
  </td>
411
- <td class="hidden md:table-cell">{{ config.fromEmail || ('shared.na' | translate) }}</td>
475
+ <td class="hidden md:table-cell">
476
+ {{ config.fromEmail || ('shared.na' | translate) }}
477
+ </td>
412
478
  <td>
413
479
  <p-tag
414
- [value]="(config.isActive ? 'common.active' : 'common.inactive') | translate"
480
+ [value]="
481
+ (config.isActive ? 'shared.active' : 'shared.inactive')
482
+ | translate
483
+ "
415
484
  [severity]="config.isActive ? 'success' : 'secondary'"
416
485
  />
417
486
  </td>
418
- <td class="hidden lg:table-cell">{{ config.createdAt | date: 'short' }}</td>
487
+ <td class="hidden lg:table-cell">
488
+ {{ config.createdAt | date: 'short' }}
489
+ </td>
419
490
  <td>
420
491
  <div class="flex gap-1">
421
492
  <p-button
@@ -423,7 +494,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImpor
423
494
  icon="pi pi-send"
424
495
  [text]="true"
425
496
  size="small"
426
- [pTooltip]="'common.test' | translate"
497
+ [pTooltip]="'email.config.test' | translate"
427
498
  (onClick)="onTest(config)"
428
499
  />
429
500
  <p-button
@@ -432,7 +503,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImpor
432
503
  [text]="true"
433
504
  severity="secondary"
434
505
  size="small"
435
- [pTooltip]="'common.edit' | translate"
506
+ [pTooltip]="'shared.edit' | translate"
436
507
  (onClick)="onEdit(config.id)"
437
508
  />
438
509
  <p-button
@@ -441,7 +512,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImpor
441
512
  [text]="true"
442
513
  severity="danger"
443
514
  size="small"
444
- [pTooltip]="'common.delete' | translate"
515
+ [pTooltip]="'shared.delete' | translate"
445
516
  (onClick)="onDelete(config)"
446
517
  />
447
518
  </div>
@@ -471,7 +542,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImpor
471
542
  >
472
543
  <div class="grid gap-4">
473
544
  <div class="field">
474
- <label class="block font-medium mb-2">{{ 'email.config.configuration' | translate }}</label>
545
+ <label class="block font-medium mb-2">{{
546
+ 'email.config.configuration' | translate
547
+ }}</label>
475
548
  <input
476
549
  pInputText
477
550
  [value]="selectedConfig()?.name || ''"
@@ -481,7 +554,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImpor
481
554
  </div>
482
555
 
483
556
  <div class="field">
484
- <label class="block font-medium mb-2">{{ 'email.config.provider' | translate }}</label>
557
+ <label class="block font-medium mb-2">{{
558
+ 'email.config.provider' | translate
559
+ }}</label>
485
560
  <p-tag
486
561
  [value]="getProviderLabel(selectedConfig()?.provider || '')"
487
562
  [severity]="getProviderSeverity(selectedConfig()?.provider || '')"
@@ -489,7 +564,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImpor
489
564
  </div>
490
565
 
491
566
  <div class="field">
492
- <label class="block font-medium mb-2">{{ 'email.config.recipient.email' | translate }} *</label>
567
+ <label class="block font-medium mb-2"
568
+ >{{ 'email.config.recipient.email' | translate }} *</label
569
+ >
493
570
  <input
494
571
  pInputText
495
572
  [ngModel]="testRecipient()"
@@ -506,7 +583,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImpor
506
583
 
507
584
  <ng-template #footer>
508
585
  <p-button
509
- [label]="'common.cancel' | translate"
586
+ [label]="'shared.cancel' | translate"
510
587
  severity="secondary"
511
588
  [outlined]="true"
512
589
  (onClick)="showTestDialog.set(false)"
@@ -527,4 +604,4 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImpor
527
604
  }] });
528
605
 
529
606
  export { EmailConfigListComponent };
530
- //# sourceMappingURL=flusys-ng-email-email-config-list.component-oznfQvxo.mjs.map
607
+ //# sourceMappingURL=flusys-ng-email-email-config-list.component-DorIeenX.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flusys-ng-email-email-config-list.component-DorIeenX.mjs","sources":["../../../projects/ng-email/pages/config/email-config-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_CONFIG_PERMISSIONS,\n HasPermissionDirective,\n PrimeModule,\n TranslatePipe,\n} from '@flusys/ng-shared';\nimport { ConfirmationService, MessageService } from 'primeng/api';\nimport { firstValueFrom } from 'rxjs';\nimport { EmailProviderEnum } from '../../enums/email-provider.enum';\nimport { IEmailConfig } from '../../interfaces/email-config.interface';\nimport { EmailConfigApiService } from '../../services/email-config-api.service';\n\n/**\n * Email configuration list component\n */\n@Component({\n selector: 'lib-email-config-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.config.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_CONFIG_PERMISSIONS.CREATE\"\n [label]=\"'email.config.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]=\"configs()\"\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>{{ 'email.config.provider' | translate }}</th>\n <th class=\"hidden md:table-cell\">\n {{ 'email.config.from.email' | translate }}\n </th>\n <th>{{ 'shared.status' | translate }}</th>\n <th class=\"hidden lg: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-config>\n <tr>\n <td>\n <i\n [class]=\"getProviderIcon(config.provider)\"\n class=\"mr-2 text-muted-color\"\n ></i>\n {{ config.name }}\n @if (config.isDefault) {\n <p-tag\n [value]=\"'shared.default' | translate\"\n severity=\"contrast\"\n class=\"ml-2\"\n />\n }\n </td>\n <td>\n <p-tag\n [value]=\"getProviderLabel(config.provider)\"\n [severity]=\"getProviderSeverity(config.provider)\"\n />\n </td>\n <td class=\"hidden md:table-cell\">\n {{ config.fromEmail || ('shared.na' | translate) }}\n </td>\n <td>\n <p-tag\n [value]=\"\n (config.isActive ? 'shared.active' : 'shared.inactive')\n | translate\n \"\n [severity]=\"config.isActive ? 'success' : 'secondary'\"\n />\n </td>\n <td class=\"hidden lg:table-cell\">\n {{ config.createdAt | date: 'short' }}\n </td>\n <td>\n <div class=\"flex gap-1\">\n <p-button\n *hasPermission=\"EMAIL_CONFIG_PERMISSIONS.UPDATE\"\n icon=\"pi pi-send\"\n [text]=\"true\"\n size=\"small\"\n [pTooltip]=\"'email.config.test' | translate\"\n (onClick)=\"onTest(config)\"\n />\n <p-button\n *hasPermission=\"EMAIL_CONFIG_PERMISSIONS.UPDATE\"\n icon=\"pi pi-pencil\"\n [text]=\"true\"\n severity=\"secondary\"\n size=\"small\"\n [pTooltip]=\"'shared.edit' | translate\"\n (onClick)=\"onEdit(config.id)\"\n />\n <p-button\n *hasPermission=\"EMAIL_CONFIG_PERMISSIONS.DELETE\"\n icon=\"pi pi-trash\"\n [text]=\"true\"\n severity=\"danger\"\n size=\"small\"\n [pTooltip]=\"'shared.delete' | translate\"\n (onClick)=\"onDelete(config)\"\n />\n </div>\n </td>\n </tr>\n </ng-template>\n\n <ng-template #emptymessage>\n <tr>\n <td colspan=\"6\" class=\"text-center py-4 text-muted-color\">\n {{ 'email.config.empty' | translate }}\n </td>\n </tr>\n </ng-template>\n </p-table>\n </div>\n </div>\n\n <!-- Test Email Dialog -->\n <p-dialog\n [header]=\"'email.config.test.dialog.title' | translate\"\n [visible]=\"showTestDialog()\"\n (visibleChange)=\"showTestDialog.set($event)\"\n [modal]=\"true\"\n [style]=\"{ width: '95vw', maxWidth: '400px' }\"\n [breakpoints]=\"{ '575px': '95vw' }\"\n >\n <div class=\"grid gap-4\">\n <div class=\"field\">\n <label class=\"block font-medium mb-2\">{{\n 'email.config.configuration' | translate\n }}</label>\n <input\n pInputText\n [value]=\"selectedConfig()?.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.config.provider' | translate\n }}</label>\n <p-tag\n [value]=\"getProviderLabel(selectedConfig()?.provider || '')\"\n [severity]=\"getProviderSeverity(selectedConfig()?.provider || '')\"\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]=\"testRecipient()\"\n (ngModelChange)=\"testRecipient.set($event)\"\n class=\"w-full\"\n [placeholder]=\"'email.recipient.example' | translate\"\n type=\"email\"\n />\n <small class=\"text-muted-color mt-1 block\">\n {{ 'email.config.test.dialog.hint' | translate }}\n </small>\n </div>\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.config.send.test' | 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 EmailConfigListComponent {\n // Permission constants for template\n readonly EMAIL_CONFIG_PERMISSIONS = EMAIL_CONFIG_PERMISSIONS;\n\n private readonly router = inject(Router);\n private readonly configService = inject(EmailConfigApiService);\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 configs = signal<IEmailConfig[]>([]);\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 dialog state (signals for zoneless change detection)\n readonly showTestDialog = signal(false);\n readonly selectedConfig = signal<IEmailConfig | null>(null);\n readonly isSendingTest = signal(false);\n readonly testRecipient = signal('');\n\n onCreate(): void {\n this.router.navigate(['/email/configs/new']);\n }\n\n onEdit(configId: string): void {\n this.router.navigate(['/email/configs', configId]);\n }\n\n async loadConfigs(): Promise<void> {\n this.isLoading.set(true);\n try {\n const response = await this.configService.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.configs.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.loadConfigs();\n }\n\n private readonly providerMeta: Record<\n string,\n {\n icon: string;\n labelKey: string;\n severity:\n | 'success'\n | 'secondary'\n | 'info'\n | 'warn'\n | 'danger'\n | 'contrast';\n }\n > = {\n [EmailProviderEnum.SMTP]: {\n icon: 'pi pi-server',\n labelKey: 'email.provider.smtp',\n severity: 'info',\n },\n [EmailProviderEnum.SENDGRID]: {\n icon: 'pi pi-cloud',\n labelKey: 'email.provider.sendgrid',\n severity: 'success',\n },\n [EmailProviderEnum.MAILGUN]: {\n icon: 'pi pi-cloud',\n labelKey: 'email.provider.mailgun',\n severity: 'warn',\n },\n };\n\n private readonly defaultProviderMeta = {\n icon: 'pi pi-envelope',\n labelKey: '',\n severity: 'secondary' as const,\n };\n\n getProviderIcon(provider: EmailProviderEnum): string {\n return this.providerMeta[provider]?.icon ?? this.defaultProviderMeta.icon;\n }\n\n getProviderLabel(provider: EmailProviderEnum | string): string {\n const labelKey = this.providerMeta[provider]?.labelKey;\n if (labelKey) {\n return this.translate(labelKey);\n }\n // Fallback to dynamic key for unknown providers\n return provider ? this.translate(`email.provider.${provider}`) : '';\n }\n\n getProviderSeverity(provider: EmailProviderEnum | string) {\n return (\n this.providerMeta[provider]?.severity ?? this.defaultProviderMeta.severity\n );\n }\n\n onTest(config: IEmailConfig): void {\n this.selectedConfig.set(config);\n this.testRecipient.set('');\n this.showTestDialog.set(true);\n }\n\n async sendTestEmail(): Promise<void> {\n const config = this.selectedConfig();\n const recipient = this.testRecipient();\n if (!config || !recipient) {\n this.messageService.add({\n severity: 'warn',\n summary: this.translate('shared.validation'),\n detail: this.translate('email.config.enter.recipient'),\n });\n return;\n }\n\n this.isSendingTest.set(true);\n try {\n const response = await firstValueFrom(\n this.configService.sendTest(config.id, recipient),\n );\n\n const r = response as unknown as {\n messageKey?: string;\n messageVariables?: Record<string, string | number>;\n message?: string;\n };\n this.messageService.add({\n severity: 'success',\n summary: this.translate('shared.success'),\n detail: r?.messageKey\n ? this.translate(r.messageKey, r.messageVariables)\n : (r?.message ?? ''),\n });\n this.showTestDialog.set(false);\n } catch {\n // Error toast handled by global interceptor\n } finally {\n this.isSendingTest.set(false);\n }\n }\n\n onDelete(config: IEmailConfig): void {\n this.confirmationService.confirm({\n message: this.translate('shared.confirm.delete.item', {\n name: config.name,\n }),\n header: this.translate('email.config.delete.title'),\n icon: 'pi pi-exclamation-triangle',\n acceptButtonStyleClass: 'p-button-danger',\n accept: async () => {\n try {\n const response = await this.configService.delete({\n id: config.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.loadConfigs();\n } catch {\n // Error toast handled by global interceptor\n }\n },\n });\n }\n\n private translate(\n key: string,\n variables?: Record<string, string | number>,\n ): string {\n return this.translateAdapter?.translate(key, variables) ?? key;\n }\n}\n"],"names":["i6","i7","i8","i9"],"mappings":";;;;;;;;;;;;;;;;;;;;AAqBA;;AAEG;MAiNU,wBAAwB,CAAA;;IAE1B,wBAAwB,GAAG,wBAAwB;AAE3C,IAAA,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;AACvB,IAAA,aAAa,GAAG,MAAM,CAAC,qBAAqB,CAAC;AAC7C,IAAA,mBAAmB,GAAG,MAAM,CAAC,mBAAmB,CAAC;AACjD,IAAA,cAAc,GAAG,MAAM,CAAC,cAAc,CAAC;AACvC,IAAA,SAAS,GAAG,MAAM,CAAC,UAAU,CAAC;AAC9B,IAAA,cAAc,GAAG,MAAM,CAAC,iBAAiB,EAAE;AAC1D,QAAA,QAAQ,EAAE,IAAI;AACf,KAAA,CAAC;AACe,IAAA,gBAAgB,GAAG,MAAM,CAAC,iBAAiB,EAAE;AAC5D,QAAA,QAAQ,EAAE,IAAI;AACf,KAAA,CAAC;AAEO,IAAA,SAAS,GAAG,MAAM,CAAC,KAAK,qDAAC;AACzB,IAAA,OAAO,GAAG,MAAM,CAAiB,EAAE,mDAAC;AACpC,IAAA,YAAY,GAAG,MAAM,CAAC,CAAC,wDAAC;AACxB,IAAA,QAAQ,GAAG,MAAM,CAAC,EAAE,oDAAC;AACrB,IAAA,KAAK,GAAG,MAAM,CAAC,CAAC,iDAAC;AAEjB,IAAA,eAAe,GAAG,QAAQ,CACjC,MAAM,IAAI,CAAC,SAAS,CAAC,oBAAoB,IAAI,CAAC,CAAC,IAAI,CAAC,cAAc,2DACnE;AACQ,IAAA,kBAAkB,GAAG,QAAQ,CACpC,MAAM,IAAI,CAAC,cAAc,EAAE,kBAAkB,EAAE,EAAE,IAAI,IAAI,gBAAgB,8DAC1E;;AAEQ,IAAA,cAAc,GAAG,MAAM,CAAC,KAAK,0DAAC;AAC9B,IAAA,cAAc,GAAG,MAAM,CAAsB,IAAI,0DAAC;AAClD,IAAA,aAAa,GAAG,MAAM,CAAC,KAAK,yDAAC;AAC7B,IAAA,aAAa,GAAG,MAAM,CAAC,EAAE,yDAAC;IAEnC,QAAQ,GAAA;QACN,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,oBAAoB,CAAC,CAAC;IAC9C;AAEA,IAAA,MAAM,CAAC,QAAgB,EAAA;QACrB,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,gBAAgB,EAAE,QAAQ,CAAC,CAAC;IACpD;AAEA,IAAA,MAAM,WAAW,GAAA;AACf,QAAA,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC;AACxB,QAAA,IAAI;YACF,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC;AAC/C,gBAAA,UAAU,EAAE;AACV,oBAAA,WAAW,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,EAAE,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAC;AACvD,oBAAA,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE;AAC1B,iBAAA;AACD,gBAAA,MAAM,EAAE,EAAE;AACV,gBAAA,MAAM,EAAE,EAAE;AACV,gBAAA,IAAI,EAAE,EAAE;AACT,aAAA,CAAC;AAEF,YAAA,IAAI,QAAQ,CAAC,OAAO,EAAE;gBACpB,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,IAAI,EAAE,CAAC;AACrC,gBAAA,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,EAAE,KAAK,IAAI,CAAC,CAAC;YAClD;QACF;AAAE,QAAA,MAAM;;QAER;gBAAU;AACR,YAAA,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC;QAC3B;IACF;AAEA,IAAA,UAAU,CAAC,KAAsD,EAAA;QAC/D,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,IAAI,CAAC,CAAC;QAChC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,IAAI,EAAE,CAAC;QACnC,IAAI,CAAC,WAAW,EAAE;IACpB;AAEiB,IAAA,YAAY,GAazB;AACF,QAAA,CAAC,iBAAiB,CAAC,IAAI,GAAG;AACxB,YAAA,IAAI,EAAE,cAAc;AACpB,YAAA,QAAQ,EAAE,qBAAqB;AAC/B,YAAA,QAAQ,EAAE,MAAM;AACjB,SAAA;AACD,QAAA,CAAC,iBAAiB,CAAC,QAAQ,GAAG;AAC5B,YAAA,IAAI,EAAE,aAAa;AACnB,YAAA,QAAQ,EAAE,yBAAyB;AACnC,YAAA,QAAQ,EAAE,SAAS;AACpB,SAAA;AACD,QAAA,CAAC,iBAAiB,CAAC,OAAO,GAAG;AAC3B,YAAA,IAAI,EAAE,aAAa;AACnB,YAAA,QAAQ,EAAE,wBAAwB;AAClC,YAAA,QAAQ,EAAE,MAAM;AACjB,SAAA;KACF;AAEgB,IAAA,mBAAmB,GAAG;AACrC,QAAA,IAAI,EAAE,gBAAgB;AACtB,QAAA,QAAQ,EAAE,EAAE;AACZ,QAAA,QAAQ,EAAE,WAAoB;KAC/B;AAED,IAAA,eAAe,CAAC,QAA2B,EAAA;AACzC,QAAA,OAAO,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,EAAE,IAAI,IAAI,IAAI,CAAC,mBAAmB,CAAC,IAAI;IAC3E;AAEA,IAAA,gBAAgB,CAAC,QAAoC,EAAA;QACnD,MAAM,QAAQ,GAAG,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,EAAE,QAAQ;QACtD,IAAI,QAAQ,EAAE;AACZ,YAAA,OAAO,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC;QACjC;;AAEA,QAAA,OAAO,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC,CAAA,eAAA,EAAkB,QAAQ,EAAE,CAAC,GAAG,EAAE;IACrE;AAEA,IAAA,mBAAmB,CAAC,QAAoC,EAAA;AACtD,QAAA,QACE,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,EAAE,QAAQ,IAAI,IAAI,CAAC,mBAAmB,CAAC,QAAQ;IAE9E;AAEA,IAAA,MAAM,CAAC,MAAoB,EAAA;AACzB,QAAA,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,MAAM,CAAC;AAC/B,QAAA,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,EAAE,CAAC;AAC1B,QAAA,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,IAAI,CAAC;IAC/B;AAEA,IAAA,MAAM,aAAa,GAAA;AACjB,QAAA,MAAM,MAAM,GAAG,IAAI,CAAC,cAAc,EAAE;AACpC,QAAA,MAAM,SAAS,GAAG,IAAI,CAAC,aAAa,EAAE;AACtC,QAAA,IAAI,CAAC,MAAM,IAAI,CAAC,SAAS,EAAE;AACzB,YAAA,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC;AACtB,gBAAA,QAAQ,EAAE,MAAM;AAChB,gBAAA,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,mBAAmB,CAAC;AAC5C,gBAAA,MAAM,EAAE,IAAI,CAAC,SAAS,CAAC,8BAA8B,CAAC;AACvD,aAAA,CAAC;YACF;QACF;AAEA,QAAA,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,IAAI,CAAC;AAC5B,QAAA,IAAI;AACF,YAAA,MAAM,QAAQ,GAAG,MAAM,cAAc,CACnC,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,EAAE,SAAS,CAAC,CAClD;YAED,MAAM,CAAC,GAAG,QAIT;AACD,YAAA,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC;AACtB,gBAAA,QAAQ,EAAE,SAAS;AACnB,gBAAA,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,gBAAgB,CAAC;gBACzC,MAAM,EAAE,CAAC,EAAE;AACT,sBAAE,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,UAAU,EAAE,CAAC,CAAC,gBAAgB;AACjD,uBAAG,CAAC,EAAE,OAAO,IAAI,EAAE,CAAC;AACvB,aAAA,CAAC;AACF,YAAA,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,KAAK,CAAC;QAChC;AAAE,QAAA,MAAM;;QAER;gBAAU;AACR,YAAA,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,KAAK,CAAC;QAC/B;IACF;AAEA,IAAA,QAAQ,CAAC,MAAoB,EAAA;AAC3B,QAAA,IAAI,CAAC,mBAAmB,CAAC,OAAO,CAAC;AAC/B,YAAA,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,4BAA4B,EAAE;gBACpD,IAAI,EAAE,MAAM,CAAC,IAAI;aAClB,CAAC;AACF,YAAA,MAAM,EAAE,IAAI,CAAC,SAAS,CAAC,2BAA2B,CAAC;AACnD,YAAA,IAAI,EAAE,4BAA4B;AAClC,YAAA,sBAAsB,EAAE,iBAAiB;YACzC,MAAM,EAAE,YAAW;AACjB,gBAAA,IAAI;oBACF,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC;wBAC/C,EAAE,EAAE,MAAM,CAAC,EAAE;AACb,wBAAA,IAAI,EAAE,QAAQ;AACf,qBAAA,CAAC;AACF,oBAAA,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC;AACtB,wBAAA,QAAQ,EAAE,SAAS;AACnB,wBAAA,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,gBAAgB,CAAC;wBACzC,MAAM,EAAE,QAAQ,EAAE;AAChB,8BAAE,IAAI,CAAC,SAAS,CACZ,QAAQ,CAAC,UAAU,EACnB,QAAQ,CAAC,gBAAmD;AAEhE,+BAAG,QAAQ,EAAE,OAAO,IAAI,EAAE,CAAC;AAC9B,qBAAA,CAAC;oBACF,IAAI,CAAC,WAAW,EAAE;gBACpB;AAAE,gBAAA,MAAM;;gBAER;YACF,CAAC;AACF,SAAA,CAAC;IACJ;IAEQ,SAAS,CACf,GAAW,EACX,SAA2C,EAAA;AAE3C,QAAA,OAAO,IAAI,CAAC,gBAAgB,EAAE,SAAS,CAAC,GAAG,EAAE,SAAS,CAAC,IAAI,GAAG;IAChE;uGAjNW,wBAAwB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAxB,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,wBAAwB,oEA7MxB,CAAC,mBAAmB,EAAE,cAAc,CAAC,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EACtC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA0MT,EAAA,CAAA,EAAA,QAAA,EAAA,IAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EA5MS,aAAa,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,oBAAA,EAAA,QAAA,EAAA,8MAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,eAAA,EAAA,QAAA,EAAA,2CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,OAAA,EAAA,QAAA,EAAA,qDAAA,EAAA,MAAA,EAAA,CAAA,MAAA,EAAA,UAAA,EAAA,SAAA,EAAA,gBAAA,CAAA,EAAA,OAAA,EAAA,CAAA,eAAA,CAAA,EAAA,QAAA,EAAA,CAAA,SAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EAAE,WAAW,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,MAAA,EAAA,QAAA,EAAA,UAAA,EAAA,MAAA,EAAA,CAAA,UAAA,EAAA,MAAA,EAAA,OAAA,EAAA,UAAA,EAAA,QAAA,EAAA,SAAA,EAAA,MAAA,EAAA,OAAA,EAAA,UAAA,EAAA,MAAA,EAAA,UAAA,EAAA,MAAA,EAAA,SAAA,EAAA,OAAA,EAAA,YAAA,EAAA,YAAA,EAAA,eAAA,EAAA,WAAA,EAAA,WAAA,EAAA,SAAA,EAAA,MAAA,EAAA,OAAA,EAAA,SAAA,EAAA,aAAA,EAAA,UAAA,EAAA,aAAA,EAAA,OAAA,CAAA,EAAA,OAAA,EAAA,CAAA,SAAA,EAAA,SAAA,EAAA,QAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,aAAA,EAAA,QAAA,EAAA,oDAAA,EAAA,MAAA,EAAA,CAAA,QAAA,EAAA,MAAA,EAAA,SAAA,EAAA,OAAA,EAAA,YAAA,EAAA,gBAAA,EAAA,YAAA,EAAA,aAAA,EAAA,gBAAA,EAAA,iBAAA,EAAA,eAAA,EAAA,YAAA,EAAA,aAAA,EAAA,iBAAA,EAAA,eAAA,EAAA,wBAAA,EAAA,wBAAA,EAAA,eAAA,EAAA,iBAAA,EAAA,aAAA,EAAA,KAAA,EAAA,UAAA,EAAA,UAAA,EAAA,KAAA,EAAA,YAAA,EAAA,YAAA,EAAA,mBAAA,EAAA,WAAA,EAAA,cAAA,EAAA,aAAA,EAAA,OAAA,EAAA,SAAA,EAAA,UAAA,EAAA,WAAA,CAAA,EAAA,OAAA,EAAA,CAAA,QAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,MAAA,EAAA,QAAA,EAAA,UAAA,EAAA,MAAA,EAAA,CAAA,UAAA,EAAA,QAAA,EAAA,WAAA,EAAA,WAAA,EAAA,cAAA,EAAA,mBAAA,EAAA,OAAA,EAAA,eAAA,EAAA,iBAAA,EAAA,KAAA,EAAA,UAAA,EAAA,aAAA,EAAA,YAAA,EAAA,gBAAA,EAAA,WAAA,EAAA,YAAA,EAAA,aAAA,EAAA,YAAA,EAAA,YAAA,EAAA,MAAA,EAAA,MAAA,EAAA,aAAA,EAAA,aAAA,EAAA,gBAAA,EAAA,WAAA,EAAA,mBAAA,EAAA,mBAAA,EAAA,eAAA,EAAA,WAAA,EAAA,gBAAA,EAAA,eAAA,EAAA,cAAA,EAAA,cAAA,EAAA,kBAAA,EAAA,qBAAA,EAAA,SAAA,EAAA,OAAA,EAAA,UAAA,EAAA,MAAA,EAAA,UAAA,EAAA,SAAA,EAAA,iBAAA,EAAA,gBAAA,EAAA,mBAAA,EAAA,sBAAA,EAAA,sBAAA,EAAA,kBAAA,CAAA,EAAA,OAAA,EAAA,CAAA,QAAA,EAAA,QAAA,EAAA,eAAA,EAAA,cAAA,EAAA,aAAA,EAAA,WAAA,EAAA,YAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,SAAA,EAAA,QAAA,EAAA,cAAA,EAAA,MAAA,EAAA,CAAA,UAAA,EAAA,aAAA,EAAA,cAAA,EAAA,oBAAA,EAAA,OAAA,EAAA,SAAA,EAAA,OAAA,EAAA,SAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAAA,EAAA,CAAA,KAAA,EAAA,QAAA,EAAA,SAAA,EAAA,MAAA,EAAA,CAAA,eAAA,EAAA,aAAA,EAAA,YAAA,EAAA,YAAA,EAAA,iBAAA,EAAA,WAAA,EAAA,WAAA,EAAA,oBAAA,EAAA,qBAAA,EAAA,mBAAA,EAAA,qBAAA,EAAA,2BAAA,EAAA,+BAAA,EAAA,2BAAA,EAAA,uBAAA,EAAA,wBAAA,EAAA,qBAAA,EAAA,mBAAA,EAAA,eAAA,EAAA,kBAAA,EAAA,UAAA,EAAA,iBAAA,EAAA,eAAA,EAAA,mBAAA,EAAA,sBAAA,EAAA,0BAAA,EAAA,SAAA,EAAA,kBAAA,EAAA,eAAA,EAAA,YAAA,EAAA,MAAA,EAAA,gBAAA,EAAA,oBAAA,EAAA,cAAA,EAAA,gBAAA,EAAA,SAAA,EAAA,oBAAA,EAAA,aAAA,EAAA,cAAA,EAAA,iBAAA,EAAA,gBAAA,EAAA,eAAA,EAAA,YAAA,EAAA,cAAA,EAAA,cAAA,EAAA,eAAA,EAAA,uBAAA,EAAA,sBAAA,EAAA,oBAAA,EAAA,aAAA,EAAA,aAAA,EAAA,kBAAA,EAAA,kBAAA,EAAA,oBAAA,EAAA,SAAA,EAAA,aAAA,EAAA,YAAA,EAAA,UAAA,EAAA,YAAA,EAAA,sBAAA,EAAA,gBAAA,EAAA,cAAA,EAAA,UAAA,EAAA,cAAA,EAAA,UAAA,EAAA,aAAA,EAAA,MAAA,EAAA,eAAA,EAAA,aAAA,EAAA,kBAAA,EAAA,kBAAA,EAAA,YAAA,EAAA,iBAAA,EAAA,OAAA,EAAA,SAAA,EAAA,OAAA,EAAA,MAAA,EAAA,cAAA,EAAA,WAAA,EAAA,WAAA,EAAA,eAAA,EAAA,WAAA,EAAA,WAAA,CAAA,EAAA,OAAA,EAAA,CAAA,4BAAA,EAAA,iBAAA,EAAA,iBAAA,EAAA,aAAA,EAAA,eAAA,EAAA,QAAA,EAAA,QAAA,EAAA,UAAA,EAAA,YAAA,EAAA,aAAA,EAAA,eAAA,EAAA,qBAAA,EAAA,aAAA,EAAA,cAAA,EAAA,cAAA,EAAA,YAAA,EAAA,gBAAA,EAAA,cAAA,EAAA,wBAAA,EAAA,cAAA,EAAA,aAAA,EAAA,YAAA,EAAA,aAAA,EAAA,gBAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAAC,EAAA,CAAA,GAAA,EAAA,QAAA,EAAA,OAAA,EAAA,MAAA,EAAA,CAAA,YAAA,EAAA,UAAA,EAAA,OAAA,EAAA,MAAA,EAAA,SAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAAC,IAAA,CAAA,KAAA,EAAA,QAAA,EAAA,SAAA,EAAA,MAAA,EAAA,CAAA,KAAA,EAAA,YAAA,EAAA,YAAA,EAAA,MAAA,EAAA,YAAA,EAAA,UAAA,EAAA,uBAAA,EAAA,mBAAA,EAAA,sBAAA,EAAA,sBAAA,EAAA,uBAAA,EAAA,uBAAA,EAAA,eAAA,EAAA,aAAA,CAAA,EAAA,OAAA,EAAA,CAAA,SAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAAC,GAAA,CAAA,OAAA,EAAA,QAAA,EAAA,YAAA,EAAA,MAAA,EAAA,CAAA,iBAAA,EAAA,cAAA,EAAA,eAAA,EAAA,mBAAA,EAAA,eAAA,EAAA,QAAA,EAAA,WAAA,EAAA,WAAA,EAAA,MAAA,EAAA,aAAA,EAAA,cAAA,EAAA,UAAA,EAAA,YAAA,EAAA,cAAA,EAAA,gBAAA,EAAA,UAAA,EAAA,iBAAA,EAAA,gBAAA,EAAA,UAAA,EAAA,WAAA,EAAA,YAAA,EAAA,kBAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAE,sBAAsB,sIAAE,aAAa,EAAA,IAAA,EAAA,WAAA,EAAA,CAAA,EAAA,CAAA;;2FA8MhE,wBAAwB,EAAA,UAAA,EAAA,CAAA;kBAhNpC,SAAS;AAAC,YAAA,IAAA,EAAA,CAAA;AACT,oBAAA,QAAQ,EAAE,uBAAuB;oBACjC,OAAO,EAAE,CAAC,aAAa,EAAE,WAAW,EAAE,sBAAsB,EAAE,aAAa,CAAC;AAC5E,oBAAA,SAAS,EAAE,CAAC,mBAAmB,EAAE,cAAc,CAAC;AAChD,oBAAA,QAAQ,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA0MT,EAAA,CAAA;AACF,iBAAA;;;;;"}