@flusys/ng-email 1.0.0-rc

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,713 @@
1
+ import * as i0 from '@angular/core';
2
+ import { inject, computed, signal, effect, ChangeDetectionStrategy, Component } from '@angular/core';
3
+ import { toSignal } from '@angular/core/rxjs-interop';
4
+ import * as i1$1 from '@angular/router';
5
+ import { ActivatedRoute, Router } from '@angular/router';
6
+ import { APP_CONFIG, DEFAULT_APP_NAME } from '@flusys/ng-core';
7
+ import { LAYOUT_AUTH_STATE } from '@flusys/ng-layout';
8
+ import { AngularModule, PrimeModule } from '@flusys/ng-shared';
9
+ import { MessageService } from 'primeng/api';
10
+ import { EmailConfigApiService, EmailProviderEnum } from './flusys-ng-email.mjs';
11
+ import * as i1 from '@angular/forms';
12
+ import * as i2 from 'primeng/button';
13
+ import * as i4 from 'primeng/inputnumber';
14
+ import * as i5 from 'primeng/inputtext';
15
+ import * as i6 from 'primeng/password';
16
+ import * as i6$1 from 'primeng/select';
17
+ import * as i8 from 'primeng/toast';
18
+ import * as i7 from 'primeng/toggleswitch';
19
+
20
+ /**
21
+ * Email configuration form component (create/edit)
22
+ */
23
+ class EmailConfigFormComponent {
24
+ route = inject(ActivatedRoute);
25
+ router = inject(Router);
26
+ configService = inject(EmailConfigApiService);
27
+ messageService = inject(MessageService);
28
+ appConfig = inject(APP_CONFIG);
29
+ companyContext = inject(LAYOUT_AUTH_STATE, { optional: true });
30
+ // Route params as signal
31
+ routeParams = toSignal(this.route.paramMap);
32
+ providerEnum = EmailProviderEnum;
33
+ showCompanyInfo = computed(() => this.appConfig.enableCompanyFeature && !!this.companyContext, ...(ngDevMode ? [{ debugName: "showCompanyInfo" }] : []));
34
+ currentCompanyName = computed(() => this.companyContext?.currentCompanyInfo()?.name ?? DEFAULT_APP_NAME, ...(ngDevMode ? [{ debugName: "currentCompanyName" }] : []));
35
+ isLoading = signal(false, ...(ngDevMode ? [{ debugName: "isLoading" }] : []));
36
+ existingConfig = signal(null, ...(ngDevMode ? [{ debugName: "existingConfig" }] : []));
37
+ isEditMode = computed(() => !!this.existingConfig(), ...(ngDevMode ? [{ debugName: "isEditMode" }] : []));
38
+ providerOptions = [
39
+ { label: 'SMTP', value: EmailProviderEnum.SMTP },
40
+ { label: 'SendGrid', value: EmailProviderEnum.SENDGRID },
41
+ { label: 'Mailgun', value: EmailProviderEnum.MAILGUN },
42
+ ];
43
+ regionOptions = [
44
+ { label: 'US', value: 'us' },
45
+ { label: 'EU', value: 'eu' },
46
+ ];
47
+ /** Form model as signal for zoneless change detection */
48
+ _formModel = signal({
49
+ id: '',
50
+ name: '',
51
+ provider: EmailProviderEnum.SMTP,
52
+ fromEmail: '',
53
+ fromName: '',
54
+ isActive: true,
55
+ isDefault: false,
56
+ // SMTP
57
+ smtpHost: '',
58
+ smtpPort: 587,
59
+ smtpUser: '',
60
+ smtpPass: '',
61
+ smtpSecure: false,
62
+ // SendGrid
63
+ sendgridApiKey: '',
64
+ // Mailgun
65
+ mailgunApiKey: '',
66
+ mailgunDomain: '',
67
+ mailgunRegion: 'us',
68
+ }, ...(ngDevMode ? [{ debugName: "_formModel" }] : []));
69
+ /** Expose form model for template binding */
70
+ get formModel() {
71
+ return this._formModel();
72
+ }
73
+ /** Update form model field - triggers change detection */
74
+ updateFormModel(field, value) {
75
+ this._formModel.update((m) => ({ ...m, [field]: value }));
76
+ }
77
+ constructor() {
78
+ // Effect to handle route-based initialization
79
+ effect(() => {
80
+ const params = this.routeParams();
81
+ if (!params)
82
+ return;
83
+ const id = params.get('id');
84
+ if (id) {
85
+ this.loadConfig(id);
86
+ }
87
+ });
88
+ }
89
+ async loadConfig(id) {
90
+ this.isLoading.set(true);
91
+ try {
92
+ const response = await this.configService.findByIdAsync(id);
93
+ if (response.success && response.data) {
94
+ const config = response.data;
95
+ this.existingConfig.set(config);
96
+ this._formModel.set({
97
+ id: config.id,
98
+ name: config.name,
99
+ provider: config.provider,
100
+ fromEmail: config.fromEmail || '',
101
+ fromName: config.fromName || '',
102
+ isActive: config.isActive,
103
+ isDefault: config.isDefault ?? false,
104
+ // SMTP
105
+ smtpHost: config.config?.['host'] || '',
106
+ smtpPort: config.config?.['port'] || 587,
107
+ smtpUser: config.config?.['auth']?.['user'] || '',
108
+ smtpPass: config.config?.['auth']?.['pass'] || '',
109
+ smtpSecure: config.config?.['secure'] || false,
110
+ // SendGrid
111
+ sendgridApiKey: config.config?.['apiKey'] || '',
112
+ // Mailgun
113
+ mailgunApiKey: config.config?.['apiKey'] || '',
114
+ mailgunDomain: config.config?.['domain'] || '',
115
+ mailgunRegion: config.config?.['region'] || 'us',
116
+ });
117
+ }
118
+ }
119
+ finally {
120
+ this.isLoading.set(false);
121
+ }
122
+ }
123
+ async onSave() {
124
+ if (!this.formModel.name || !this.formModel.provider) {
125
+ this.messageService.add({
126
+ severity: 'warn',
127
+ summary: 'Validation',
128
+ detail: 'Please fill in all required fields.',
129
+ });
130
+ return;
131
+ }
132
+ // Build provider-specific config
133
+ let config = {};
134
+ switch (this.formModel.provider) {
135
+ case EmailProviderEnum.SMTP:
136
+ config = {
137
+ host: this.formModel.smtpHost,
138
+ port: this.formModel.smtpPort,
139
+ secure: this.formModel.smtpSecure,
140
+ auth: {
141
+ user: this.formModel.smtpUser,
142
+ pass: this.formModel.smtpPass,
143
+ },
144
+ };
145
+ break;
146
+ case EmailProviderEnum.SENDGRID:
147
+ config = {
148
+ apiKey: this.formModel.sendgridApiKey,
149
+ };
150
+ break;
151
+ case EmailProviderEnum.MAILGUN:
152
+ config = {
153
+ apiKey: this.formModel.mailgunApiKey,
154
+ domain: this.formModel.mailgunDomain,
155
+ region: this.formModel.mailgunRegion,
156
+ };
157
+ break;
158
+ }
159
+ this.isLoading.set(true);
160
+ try {
161
+ if (this.isEditMode()) {
162
+ await this.configService.updateAsync({
163
+ id: this.formModel.id,
164
+ name: this.formModel.name,
165
+ provider: this.formModel.provider,
166
+ config,
167
+ fromEmail: this.formModel.fromEmail || undefined,
168
+ fromName: this.formModel.fromName || undefined,
169
+ isActive: this.formModel.isActive,
170
+ isDefault: this.formModel.isDefault,
171
+ });
172
+ }
173
+ else {
174
+ // ApiResourceService uses UpdateDto which requires id, cast to any for insert
175
+ await this.configService.insertAsync({
176
+ name: this.formModel.name,
177
+ provider: this.formModel.provider,
178
+ config,
179
+ fromEmail: this.formModel.fromEmail || undefined,
180
+ fromName: this.formModel.fromName || undefined,
181
+ isActive: this.formModel.isActive,
182
+ isDefault: this.formModel.isDefault,
183
+ });
184
+ }
185
+ this.messageService.add({
186
+ severity: 'success',
187
+ summary: 'Success',
188
+ detail: `Configuration ${this.isEditMode() ? 'updated' : 'created'} successfully.`,
189
+ });
190
+ this.router.navigate(['../'], { relativeTo: this.route });
191
+ }
192
+ catch {
193
+ // Error toast handled by global interceptor
194
+ }
195
+ finally {
196
+ this.isLoading.set(false);
197
+ }
198
+ }
199
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: EmailConfigFormComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
200
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.3", type: EmailConfigFormComponent, isStandalone: true, selector: "lib-email-config-form", providers: [MessageService], ngImport: i0, template: `
201
+ <div class="card">
202
+ <!-- Header -->
203
+ <div class="flex flex-col sm:flex-row justify-between items-start sm:items-center gap-3 mb-4">
204
+ <div>
205
+ <h3 class="text-lg sm:text-xl font-semibold m-0">
206
+ {{ isEditMode() ? 'Edit Configuration' : 'New Configuration' }}
207
+ </h3>
208
+ @if (showCompanyInfo()) {
209
+ <p class="text-sm text-muted-color mt-1">
210
+ Company: {{ currentCompanyName() }}
211
+ </p>
212
+ }
213
+ </div>
214
+ </div>
215
+
216
+ <!-- Form Fields -->
217
+ <div class="grid grid-cols-1 md:grid-cols-2 gap-4">
218
+ <!-- Common Fields -->
219
+ <div class="field">
220
+ <label for="name" class="block font-medium mb-2"
221
+ >Configuration Name *</label
222
+ >
223
+ <input
224
+ pInputText
225
+ id="name"
226
+ [ngModel]="formModel.name"
227
+ (ngModelChange)="updateFormModel('name', $event)"
228
+ class="w-full"
229
+ placeholder="e.g., Production SMTP"
230
+ />
231
+ </div>
232
+
233
+ <div class="field">
234
+ <label for="provider" class="block font-medium mb-2"
235
+ >Email Provider *</label
236
+ >
237
+ <p-select
238
+ id="provider"
239
+ [options]="providerOptions"
240
+ [ngModel]="formModel.provider"
241
+ (ngModelChange)="updateFormModel('provider', $event)"
242
+ optionLabel="label"
243
+ optionValue="value"
244
+ placeholder="Select provider"
245
+ class="w-full"
246
+ />
247
+ </div>
248
+
249
+ <div class="field">
250
+ <label for="fromEmail" class="block font-medium mb-2"
251
+ >From Email</label
252
+ >
253
+ <input
254
+ pInputText
255
+ id="fromEmail"
256
+ [ngModel]="formModel.fromEmail"
257
+ (ngModelChange)="updateFormModel('fromEmail', $event)"
258
+ class="w-full"
259
+ placeholder="noreply@example.com"
260
+ />
261
+ </div>
262
+
263
+ <div class="field">
264
+ <label for="fromName" class="block font-medium mb-2"
265
+ >From Name</label
266
+ >
267
+ <input
268
+ pInputText
269
+ id="fromName"
270
+ [ngModel]="formModel.fromName"
271
+ (ngModelChange)="updateFormModel('fromName', $event)"
272
+ class="w-full"
273
+ placeholder="FLUSYS"
274
+ />
275
+ </div>
276
+
277
+ <div class="field flex items-center gap-2">
278
+ <p-toggleswitch [ngModel]="formModel.isActive" (ngModelChange)="updateFormModel('isActive', $event)" />
279
+ <label>Active</label>
280
+ </div>
281
+
282
+ <div class="field flex items-center gap-2">
283
+ <p-toggleswitch [ngModel]="formModel.isDefault" (ngModelChange)="updateFormModel('isDefault', $event)" />
284
+ <label>Set as Default</label>
285
+ </div>
286
+ </div>
287
+
288
+ <!-- SMTP Fields -->
289
+ @if (formModel.provider === providerEnum.SMTP) {
290
+ <div class="border-t border-surface mt-4 pt-4">
291
+ <h3 class="font-semibold mb-4">SMTP Settings</h3>
292
+ <div class="grid grid-cols-1 md:grid-cols-2 gap-4">
293
+ <div class="field">
294
+ <label for="smtpHost" class="block font-medium mb-2"
295
+ >SMTP Host *</label
296
+ >
297
+ <input
298
+ pInputText
299
+ id="smtpHost"
300
+ [ngModel]="formModel.smtpHost"
301
+ (ngModelChange)="updateFormModel('smtpHost', $event)"
302
+ class="w-full"
303
+ placeholder="smtp.gmail.com"
304
+ />
305
+ </div>
306
+ <div class="field">
307
+ <label for="smtpPort" class="block font-medium mb-2"
308
+ >Port *</label
309
+ >
310
+ <p-inputNumber
311
+ id="smtpPort"
312
+ [ngModel]="formModel.smtpPort"
313
+ (ngModelChange)="updateFormModel('smtpPort', $event)"
314
+ [useGrouping]="false"
315
+ class="w-full"
316
+ placeholder="587"
317
+ />
318
+ </div>
319
+ <div class="field">
320
+ <label for="smtpUser" class="block font-medium mb-2"
321
+ >Username *</label
322
+ >
323
+ <input
324
+ pInputText
325
+ id="smtpUser"
326
+ [ngModel]="formModel.smtpUser"
327
+ (ngModelChange)="updateFormModel('smtpUser', $event)"
328
+ class="w-full"
329
+ placeholder="user@gmail.com"
330
+ />
331
+ </div>
332
+ <div class="field">
333
+ <label for="smtpPass" class="block font-medium mb-2"
334
+ >Password *</label
335
+ >
336
+ <p-password
337
+ id="smtpPass"
338
+ [ngModel]="formModel.smtpPass"
339
+ (ngModelChange)="updateFormModel('smtpPass', $event)"
340
+ [feedback]="false"
341
+ [toggleMask]="true"
342
+ styleClass="w-full"
343
+ inputStyleClass="w-full"
344
+ placeholder="App password"
345
+ />
346
+ </div>
347
+ <div class="field flex items-center gap-2">
348
+ <p-toggleswitch [ngModel]="formModel.smtpSecure" (ngModelChange)="updateFormModel('smtpSecure', $event)" />
349
+ <label>Use SSL/TLS (Port 465)</label>
350
+ </div>
351
+ </div>
352
+ </div>
353
+ }
354
+
355
+ <!-- SendGrid Fields -->
356
+ @if (formModel.provider === providerEnum.SENDGRID) {
357
+ <div class="border-t border-surface mt-4 pt-4">
358
+ <h3 class="font-semibold mb-4">SendGrid Settings</h3>
359
+ <div class="grid grid-cols-1 gap-4">
360
+ <div class="field">
361
+ <label for="sendgridApiKey" class="block font-medium mb-2"
362
+ >API Key *</label
363
+ >
364
+ <p-password
365
+ id="sendgridApiKey"
366
+ [ngModel]="formModel.sendgridApiKey"
367
+ (ngModelChange)="updateFormModel('sendgridApiKey', $event)"
368
+ [feedback]="false"
369
+ [toggleMask]="true"
370
+ styleClass="w-full"
371
+ inputStyleClass="w-full"
372
+ placeholder="SG.xxxx..."
373
+ />
374
+ </div>
375
+ </div>
376
+ </div>
377
+ }
378
+
379
+ <!-- Mailgun Fields -->
380
+ @if (formModel.provider === providerEnum.MAILGUN) {
381
+ <div class="border-t border-surface mt-4 pt-4">
382
+ <h3 class="font-semibold mb-4">Mailgun Settings</h3>
383
+ <div class="grid grid-cols-1 md:grid-cols-2 gap-4">
384
+ <div class="field">
385
+ <label for="mailgunApiKey" class="block font-medium mb-2"
386
+ >API Key *</label
387
+ >
388
+ <p-password
389
+ id="mailgunApiKey"
390
+ [ngModel]="formModel.mailgunApiKey"
391
+ (ngModelChange)="updateFormModel('mailgunApiKey', $event)"
392
+ [feedback]="false"
393
+ [toggleMask]="true"
394
+ styleClass="w-full"
395
+ inputStyleClass="w-full"
396
+ placeholder="key-xxxx..."
397
+ />
398
+ </div>
399
+ <div class="field">
400
+ <label for="mailgunDomain" class="block font-medium mb-2"
401
+ >Domain *</label
402
+ >
403
+ <input
404
+ pInputText
405
+ id="mailgunDomain"
406
+ [ngModel]="formModel.mailgunDomain"
407
+ (ngModelChange)="updateFormModel('mailgunDomain', $event)"
408
+ class="w-full"
409
+ placeholder="mg.example.com"
410
+ />
411
+ </div>
412
+ <div class="field">
413
+ <label for="mailgunRegion" class="block font-medium mb-2"
414
+ >Region</label
415
+ >
416
+ <p-select
417
+ id="mailgunRegion"
418
+ [options]="regionOptions"
419
+ [ngModel]="formModel.mailgunRegion"
420
+ (ngModelChange)="updateFormModel('mailgunRegion', $event)"
421
+ optionLabel="label"
422
+ optionValue="value"
423
+ placeholder="Select region"
424
+ class="w-full"
425
+ />
426
+ </div>
427
+ </div>
428
+ </div>
429
+ }
430
+
431
+ <!-- Form Actions -->
432
+ <div class="flex justify-end gap-2 mt-6 pt-4 border-t border-surface">
433
+ <p-button
434
+ label="Cancel"
435
+ severity="secondary"
436
+ [outlined]="true"
437
+ routerLink="../"
438
+ />
439
+ <p-button
440
+ [label]="isEditMode() ? 'Update' : 'Create'"
441
+ icon="pi pi-save"
442
+ [loading]="isLoading()"
443
+ (onClick)="onSave()"
444
+ />
445
+ </div>
446
+ </div>
447
+
448
+ <p-toast />
449
+ `, isInline: true, dependencies: [{ kind: "ngmodule", type: AngularModule }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i1$1.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "ngmodule", type: PrimeModule }, { kind: "component", type: i2.Button, selector: "p-button", inputs: ["hostName", "type", "badge", "disabled", "raised", "rounded", "text", "plain", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "iconPos", "icon", "label", "loading", "loadingIcon", "severity", "buttonProps", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "component", type: i4.InputNumber, selector: "p-inputNumber, p-inputnumber, p-input-number", inputs: ["showButtons", "format", "buttonLayout", "inputId", "styleClass", "placeholder", "tabindex", "title", "ariaLabelledBy", "ariaDescribedBy", "ariaLabel", "ariaRequired", "autocomplete", "incrementButtonClass", "decrementButtonClass", "incrementButtonIcon", "decrementButtonIcon", "readonly", "allowEmpty", "locale", "localeMatcher", "mode", "currency", "currencyDisplay", "useGrouping", "minFractionDigits", "maxFractionDigits", "prefix", "suffix", "inputStyle", "inputStyleClass", "showClear", "autofocus"], outputs: ["onInput", "onFocus", "onBlur", "onKeyDown", "onClear"] }, { kind: "directive", type: i5.InputText, selector: "[pInputText]", inputs: ["hostName", "ptInputText", "pInputTextPT", "pInputTextUnstyled", "pSize", "variant", "fluid", "invalid"] }, { kind: "component", type: i6.Password, selector: "p-password", inputs: ["ariaLabel", "ariaLabelledBy", "label", "promptLabel", "mediumRegex", "strongRegex", "weakLabel", "mediumLabel", "maxLength", "strongLabel", "inputId", "feedback", "toggleMask", "inputStyleClass", "styleClass", "inputStyle", "showTransitionOptions", "hideTransitionOptions", "autocomplete", "placeholder", "showClear", "autofocus", "tabindex", "appendTo", "motionOptions", "overlayOptions"], outputs: ["onFocus", "onBlur", "onClear"] }, { kind: "component", type: i6$1.Select, selector: "p-select", inputs: ["id", "scrollHeight", "filter", "panelStyle", "styleClass", "panelStyleClass", "readonly", "editable", "tabindex", "placeholder", "loadingIcon", "filterPlaceholder", "filterLocale", "inputId", "dataKey", "filterBy", "filterFields", "autofocus", "resetFilterOnHide", "checkmark", "dropdownIcon", "loading", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "group", "showClear", "emptyFilterMessage", "emptyMessage", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "ariaLabel", "ariaLabelledBy", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "focusOnHover", "selectOnFocus", "autoOptionFocus", "autofocusFilter", "filterValue", "options", "appendTo", "motionOptions"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onShow", "onHide", "onClear", "onLazyLoad"] }, { kind: "component", type: i8.Toast, selector: "p-toast", inputs: ["key", "autoZIndex", "baseZIndex", "life", "styleClass", "position", "preventOpenDuplicates", "preventDuplicates", "showTransformOptions", "hideTransformOptions", "showTransitionOptions", "hideTransitionOptions", "motionOptions", "breakpoints"], outputs: ["onClose"] }, { kind: "component", type: i7.ToggleSwitch, selector: "p-toggleswitch, p-toggleSwitch, p-toggle-switch", inputs: ["styleClass", "tabindex", "inputId", "readonly", "trueValue", "falseValue", "ariaLabel", "size", "ariaLabelledBy", "autofocus"], outputs: ["onChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
450
+ }
451
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: EmailConfigFormComponent, decorators: [{
452
+ type: Component,
453
+ args: [{
454
+ selector: 'lib-email-config-form',
455
+ standalone: true,
456
+ changeDetection: ChangeDetectionStrategy.OnPush,
457
+ imports: [AngularModule, PrimeModule],
458
+ providers: [MessageService],
459
+ template: `
460
+ <div class="card">
461
+ <!-- Header -->
462
+ <div class="flex flex-col sm:flex-row justify-between items-start sm:items-center gap-3 mb-4">
463
+ <div>
464
+ <h3 class="text-lg sm:text-xl font-semibold m-0">
465
+ {{ isEditMode() ? 'Edit Configuration' : 'New Configuration' }}
466
+ </h3>
467
+ @if (showCompanyInfo()) {
468
+ <p class="text-sm text-muted-color mt-1">
469
+ Company: {{ currentCompanyName() }}
470
+ </p>
471
+ }
472
+ </div>
473
+ </div>
474
+
475
+ <!-- Form Fields -->
476
+ <div class="grid grid-cols-1 md:grid-cols-2 gap-4">
477
+ <!-- Common Fields -->
478
+ <div class="field">
479
+ <label for="name" class="block font-medium mb-2"
480
+ >Configuration Name *</label
481
+ >
482
+ <input
483
+ pInputText
484
+ id="name"
485
+ [ngModel]="formModel.name"
486
+ (ngModelChange)="updateFormModel('name', $event)"
487
+ class="w-full"
488
+ placeholder="e.g., Production SMTP"
489
+ />
490
+ </div>
491
+
492
+ <div class="field">
493
+ <label for="provider" class="block font-medium mb-2"
494
+ >Email Provider *</label
495
+ >
496
+ <p-select
497
+ id="provider"
498
+ [options]="providerOptions"
499
+ [ngModel]="formModel.provider"
500
+ (ngModelChange)="updateFormModel('provider', $event)"
501
+ optionLabel="label"
502
+ optionValue="value"
503
+ placeholder="Select provider"
504
+ class="w-full"
505
+ />
506
+ </div>
507
+
508
+ <div class="field">
509
+ <label for="fromEmail" class="block font-medium mb-2"
510
+ >From Email</label
511
+ >
512
+ <input
513
+ pInputText
514
+ id="fromEmail"
515
+ [ngModel]="formModel.fromEmail"
516
+ (ngModelChange)="updateFormModel('fromEmail', $event)"
517
+ class="w-full"
518
+ placeholder="noreply@example.com"
519
+ />
520
+ </div>
521
+
522
+ <div class="field">
523
+ <label for="fromName" class="block font-medium mb-2"
524
+ >From Name</label
525
+ >
526
+ <input
527
+ pInputText
528
+ id="fromName"
529
+ [ngModel]="formModel.fromName"
530
+ (ngModelChange)="updateFormModel('fromName', $event)"
531
+ class="w-full"
532
+ placeholder="FLUSYS"
533
+ />
534
+ </div>
535
+
536
+ <div class="field flex items-center gap-2">
537
+ <p-toggleswitch [ngModel]="formModel.isActive" (ngModelChange)="updateFormModel('isActive', $event)" />
538
+ <label>Active</label>
539
+ </div>
540
+
541
+ <div class="field flex items-center gap-2">
542
+ <p-toggleswitch [ngModel]="formModel.isDefault" (ngModelChange)="updateFormModel('isDefault', $event)" />
543
+ <label>Set as Default</label>
544
+ </div>
545
+ </div>
546
+
547
+ <!-- SMTP Fields -->
548
+ @if (formModel.provider === providerEnum.SMTP) {
549
+ <div class="border-t border-surface mt-4 pt-4">
550
+ <h3 class="font-semibold mb-4">SMTP Settings</h3>
551
+ <div class="grid grid-cols-1 md:grid-cols-2 gap-4">
552
+ <div class="field">
553
+ <label for="smtpHost" class="block font-medium mb-2"
554
+ >SMTP Host *</label
555
+ >
556
+ <input
557
+ pInputText
558
+ id="smtpHost"
559
+ [ngModel]="formModel.smtpHost"
560
+ (ngModelChange)="updateFormModel('smtpHost', $event)"
561
+ class="w-full"
562
+ placeholder="smtp.gmail.com"
563
+ />
564
+ </div>
565
+ <div class="field">
566
+ <label for="smtpPort" class="block font-medium mb-2"
567
+ >Port *</label
568
+ >
569
+ <p-inputNumber
570
+ id="smtpPort"
571
+ [ngModel]="formModel.smtpPort"
572
+ (ngModelChange)="updateFormModel('smtpPort', $event)"
573
+ [useGrouping]="false"
574
+ class="w-full"
575
+ placeholder="587"
576
+ />
577
+ </div>
578
+ <div class="field">
579
+ <label for="smtpUser" class="block font-medium mb-2"
580
+ >Username *</label
581
+ >
582
+ <input
583
+ pInputText
584
+ id="smtpUser"
585
+ [ngModel]="formModel.smtpUser"
586
+ (ngModelChange)="updateFormModel('smtpUser', $event)"
587
+ class="w-full"
588
+ placeholder="user@gmail.com"
589
+ />
590
+ </div>
591
+ <div class="field">
592
+ <label for="smtpPass" class="block font-medium mb-2"
593
+ >Password *</label
594
+ >
595
+ <p-password
596
+ id="smtpPass"
597
+ [ngModel]="formModel.smtpPass"
598
+ (ngModelChange)="updateFormModel('smtpPass', $event)"
599
+ [feedback]="false"
600
+ [toggleMask]="true"
601
+ styleClass="w-full"
602
+ inputStyleClass="w-full"
603
+ placeholder="App password"
604
+ />
605
+ </div>
606
+ <div class="field flex items-center gap-2">
607
+ <p-toggleswitch [ngModel]="formModel.smtpSecure" (ngModelChange)="updateFormModel('smtpSecure', $event)" />
608
+ <label>Use SSL/TLS (Port 465)</label>
609
+ </div>
610
+ </div>
611
+ </div>
612
+ }
613
+
614
+ <!-- SendGrid Fields -->
615
+ @if (formModel.provider === providerEnum.SENDGRID) {
616
+ <div class="border-t border-surface mt-4 pt-4">
617
+ <h3 class="font-semibold mb-4">SendGrid Settings</h3>
618
+ <div class="grid grid-cols-1 gap-4">
619
+ <div class="field">
620
+ <label for="sendgridApiKey" class="block font-medium mb-2"
621
+ >API Key *</label
622
+ >
623
+ <p-password
624
+ id="sendgridApiKey"
625
+ [ngModel]="formModel.sendgridApiKey"
626
+ (ngModelChange)="updateFormModel('sendgridApiKey', $event)"
627
+ [feedback]="false"
628
+ [toggleMask]="true"
629
+ styleClass="w-full"
630
+ inputStyleClass="w-full"
631
+ placeholder="SG.xxxx..."
632
+ />
633
+ </div>
634
+ </div>
635
+ </div>
636
+ }
637
+
638
+ <!-- Mailgun Fields -->
639
+ @if (formModel.provider === providerEnum.MAILGUN) {
640
+ <div class="border-t border-surface mt-4 pt-4">
641
+ <h3 class="font-semibold mb-4">Mailgun Settings</h3>
642
+ <div class="grid grid-cols-1 md:grid-cols-2 gap-4">
643
+ <div class="field">
644
+ <label for="mailgunApiKey" class="block font-medium mb-2"
645
+ >API Key *</label
646
+ >
647
+ <p-password
648
+ id="mailgunApiKey"
649
+ [ngModel]="formModel.mailgunApiKey"
650
+ (ngModelChange)="updateFormModel('mailgunApiKey', $event)"
651
+ [feedback]="false"
652
+ [toggleMask]="true"
653
+ styleClass="w-full"
654
+ inputStyleClass="w-full"
655
+ placeholder="key-xxxx..."
656
+ />
657
+ </div>
658
+ <div class="field">
659
+ <label for="mailgunDomain" class="block font-medium mb-2"
660
+ >Domain *</label
661
+ >
662
+ <input
663
+ pInputText
664
+ id="mailgunDomain"
665
+ [ngModel]="formModel.mailgunDomain"
666
+ (ngModelChange)="updateFormModel('mailgunDomain', $event)"
667
+ class="w-full"
668
+ placeholder="mg.example.com"
669
+ />
670
+ </div>
671
+ <div class="field">
672
+ <label for="mailgunRegion" class="block font-medium mb-2"
673
+ >Region</label
674
+ >
675
+ <p-select
676
+ id="mailgunRegion"
677
+ [options]="regionOptions"
678
+ [ngModel]="formModel.mailgunRegion"
679
+ (ngModelChange)="updateFormModel('mailgunRegion', $event)"
680
+ optionLabel="label"
681
+ optionValue="value"
682
+ placeholder="Select region"
683
+ class="w-full"
684
+ />
685
+ </div>
686
+ </div>
687
+ </div>
688
+ }
689
+
690
+ <!-- Form Actions -->
691
+ <div class="flex justify-end gap-2 mt-6 pt-4 border-t border-surface">
692
+ <p-button
693
+ label="Cancel"
694
+ severity="secondary"
695
+ [outlined]="true"
696
+ routerLink="../"
697
+ />
698
+ <p-button
699
+ [label]="isEditMode() ? 'Update' : 'Create'"
700
+ icon="pi pi-save"
701
+ [loading]="isLoading()"
702
+ (onClick)="onSave()"
703
+ />
704
+ </div>
705
+ </div>
706
+
707
+ <p-toast />
708
+ `,
709
+ }]
710
+ }], ctorParameters: () => [] });
711
+
712
+ export { EmailConfigFormComponent };
713
+ //# sourceMappingURL=flusys-ng-email-email-config-form.component-BK195yNS.mjs.map