@flusys/ng-email 4.1.1 → 5.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,92 +1,19 @@
1
1
  # @flusys/ng-email
2
2
 
3
- > Email management UI library for the FLUSYS Angular platform provider configuration, visual template builder, and programmatic email sending.
3
+ Email management UI for FLUSYS visual block-based template builder, email config CRUD, and programmatic sending via `EmailSendService`.
4
4
 
5
5
  [![npm version](https://img.shields.io/npm/v/@flusys/ng-email.svg)](https://www.npmjs.com/package/@flusys/ng-email)
6
- [![Angular](https://img.shields.io/badge/Angular-21-red.svg)](https://angular.io)
7
- [![TypeScript](https://img.shields.io/badge/TypeScript-5.x-blue.svg)](https://www.typescriptlang.org)
8
- [![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](LICENSE)
9
-
10
- ---
11
-
12
- ## Table of Contents
13
-
14
- - [Overview](#overview)
15
- - [Features](#features)
16
- - [Compatibility](#compatibility)
17
- - [Installation](#installation)
18
- - [Quick Start](#quick-start)
19
- - [Email Schema](#email-schema)
20
- - [IEmailSchema](#iemailschema)
21
- - [Block Types](#block-types)
22
- - [Services](#services)
23
- - [EmailProviderApiService](#emailproviderapiservice)
24
- - [EmailTemplateApiService](#emailtemplateapiservice)
25
- - [EmailSendService](#emailsendservice)
26
- - [EmailBuilderStateService](#emailbuilderstateservice)
27
- - [Components](#components)
28
- - [EmailBuilderComponent](#emailbuildercomponent)
29
- - [EmailPreviewComponent](#emailpreviewcomponent)
30
- - [Email Provider Enum](#email-provider-enum)
31
- - [API Endpoints](#api-endpoints)
32
- - [Configuration Reference](#configuration-reference)
33
- - [Troubleshooting](#troubleshooting)
34
- - [License](#license)
35
-
36
- ---
37
-
38
- ## Overview
39
-
40
- `@flusys/ng-email` provides a complete email management UI for FLUSYS applications. Administrators can configure SMTP/SendGrid/Mailgun providers, design reusable email templates via a block-based visual builder, and developers can send emails programmatically using `EmailSendService`.
41
-
42
- Templates are stored as `IEmailSchema` JSON in the backend (`nestjs-email`) and rendered server-side with `{{variable}}` interpolation.
43
-
44
- ---
45
-
46
- ## Features
47
-
48
- - ✅ Email provider configuration UI (SMTP, SendGrid, Mailgun)
49
- - ✅ Visual block-based email template builder
50
- - ✅ `{{variable}}` interpolation with XSS protection
51
- - ✅ Email template preview (desktop + mobile viewport)
52
- - ✅ `EmailSendService` for programmatic sending from any feature
53
- - ✅ Template versioning (draft / published)
54
- - ✅ File/image insertion via `ng-storage` integration
55
-
56
- ---
57
-
58
- ## Compatibility
59
-
60
- | Package | Version |
61
- |---------|---------|
62
- | Angular | 21+ |
63
- | @flusys/ng-core | 4.x |
64
- | @flusys/ng-shared | 4.x |
6
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
65
7
 
66
8
  ---
67
9
 
68
10
  ## Installation
69
11
 
70
12
  ```bash
71
- npm install @flusys/ng-email @flusys/ng-core @flusys/ng-shared
13
+ npm install @flusys/ng-email
72
14
  ```
73
15
 
74
- ---
75
-
76
- ## Quick Start
77
-
78
- ### 1. Enable Email in Config
79
-
80
- ```typescript
81
- // environments/environment.ts
82
- export const environment = {
83
- services: {
84
- email: { enabled: true },
85
- },
86
- };
87
- ```
88
-
89
- ### 2. Add Email Routes
16
+ ## 1. Add Email Routes
90
17
 
91
18
  ```typescript
92
19
  // app.routes.ts
@@ -100,322 +27,9 @@ export const routes: Routes = [
100
27
  ];
101
28
  ```
102
29
 
103
- ### 3. Send Email Programmatically
104
-
105
- ```typescript
106
- import { EmailSendService } from '@flusys/ng-email';
107
-
108
- @Injectable({ providedIn: 'root' })
109
- export class OrderService {
110
- private emailSend = inject(EmailSendService);
111
-
112
- sendOrderConfirmation(order: Order): Observable<IMessageResponse> {
113
- return this.emailSend.send({
114
- templateKey: 'order-confirmation',
115
- to: order.customerEmail,
116
- variables: {
117
- customerName: order.customerName,
118
- orderNumber: order.id,
119
- totalAmount: order.total.toFixed(2),
120
- },
121
- });
122
- }
123
- }
124
- ```
125
-
126
- ---
127
-
128
- ## Email Schema
129
-
130
- ### IEmailSchema
131
-
132
- Complete email template definition stored as JSON:
133
-
134
- ```typescript
135
- interface IEmailSchema {
136
- id: string;
137
- name: string;
138
- key: string; // Unique identifier for programmatic sending
139
- subject: string; // Supports {{variable}} interpolation
140
- previewText?: string;
141
- blocks: IEmailBlock[];
142
- settings: IEmailSettings;
143
- isDraft: boolean;
144
- createdAt: string;
145
- updatedAt: string;
146
- }
147
-
148
- interface IEmailSettings {
149
- backgroundColor: string;
150
- contentWidth: number; // pixels (default: 600)
151
- fontFamily: string;
152
- padding: number; // px
153
- }
154
- ```
155
-
156
- ### Block Types
157
-
158
- Email templates are composed of blocks:
159
-
160
- | Block Type | Description | Key Properties |
161
- |------------|-------------|----------------|
162
- | `header` | Logo + company name header | `logoFileId`, `companyName`, `backgroundColor` |
163
- | `text` | Rich text paragraph | `content` (HTML), `fontSize`, `color`, `align` |
164
- | `heading` | H1-H4 heading | `content`, `level`, `color`, `align` |
165
- | `button` | Call-to-action button | `label`, `url`, `backgroundColor`, `textColor` |
166
- | `image` | Image block | `fileId`, `altText`, `width`, `link` |
167
- | `divider` | Horizontal rule | `color`, `thickness` |
168
- | `spacer` | Vertical whitespace | `height` |
169
- | `columns` | Two-column layout | `leftBlock`, `rightBlock` |
170
- | `footer` | Unsubscribe/legal footer | `content`, `unsubscribeUrl` |
171
-
172
- ```typescript
173
- interface IEmailBlock {
174
- id: string;
175
- type: EmailBlockType;
176
- [key: string]: unknown; // Block-specific properties
177
- }
178
- ```
179
-
180
- **Variable Interpolation:**
181
-
182
- Use `{{variableName}}` in any text content:
183
-
184
- ```
185
- Subject: "Order {{orderNumber}} Confirmed"
186
- Content: "Hi {{customerName}}, your order totaling ${{totalAmount}} is confirmed."
187
- ```
30
+ Routes included (all protected by `permissionGuard`):
188
31
 
189
- Variables are XSS-sanitized server-side before rendering.
190
-
191
- ---
192
-
193
- ## Services
194
-
195
- ### EmailProviderApiService
196
-
197
- Manages email provider configuration (SMTP, SendGrid, Mailgun):
198
-
199
- ```typescript
200
- import { EmailProviderApiService } from '@flusys/ng-email';
201
-
202
- @Injectable({ ... })
203
- export class MyService {
204
- private providerApi = inject(EmailProviderApiService);
205
-
206
- getProviders(): Observable<IListResponse<IEmailProvider>> {
207
- return this.providerApi.getAll({});
208
- }
209
-
210
- configureSmtp(config: ISmtpConfig): Observable<ISingleResponse<IEmailProvider>> {
211
- return this.providerApi.insert({
212
- type: EmailProviderEnum.SMTP,
213
- ...config,
214
- });
215
- }
216
-
217
- testProvider(id: string): Observable<IMessageResponse> {
218
- return this.providerApi.test(id);
219
- }
220
- }
221
- ```
222
-
223
- ### EmailTemplateApiService
224
-
225
- Manages email template CRUD and publishing:
226
-
227
- ```typescript
228
- import { EmailTemplateApiService } from '@flusys/ng-email';
229
-
230
- @Injectable({ ... })
231
- export class MyService {
232
- private templateApi = inject(EmailTemplateApiService);
233
-
234
- getTemplates(): Observable<IListResponse<IEmailTemplate>> {
235
- return this.templateApi.getAll({ pageSize: 50 });
236
- }
237
-
238
- getByKey(key: string): Observable<ISingleResponse<IEmailTemplate>> {
239
- return this.templateApi.getByKey(key);
240
- }
241
-
242
- publish(id: string): Observable<IMessageResponse> {
243
- return this.templateApi.publish(id);
244
- }
245
- }
246
- ```
247
-
248
- ### EmailSendService
249
-
250
- Programmatic email sending from any feature module:
251
-
252
- ```typescript
253
- import { EmailSendService } from '@flusys/ng-email';
254
-
255
- @Injectable({ providedIn: 'root' })
256
- export class NotificationBridgeService {
257
- private emailSend = inject(EmailSendService);
258
-
259
- sendWelcomeEmail(user: IUser): Observable<IMessageResponse> {
260
- return this.emailSend.send({
261
- templateKey: 'welcome',
262
- to: user.email,
263
- variables: {
264
- firstName: user.firstName,
265
- loginUrl: 'https://app.example.com/auth/login',
266
- },
267
- });
268
- }
269
-
270
- sendPasswordReset(email: string, resetToken: string): Observable<IMessageResponse> {
271
- return this.emailSend.send({
272
- templateKey: 'password-reset',
273
- to: email,
274
- variables: { resetToken, expiresIn: '24 hours' },
275
- });
276
- }
277
- }
278
- ```
279
-
280
- **EmailSendService.send() Options:**
281
-
282
- | Field | Type | Required | Description |
283
- |-------|------|----------|-------------|
284
- | `templateKey` | `string` | ✅ | Unique template key |
285
- | `to` | `string \| string[]` | ✅ | Recipient(s) |
286
- | `variables` | `Record<string, string \| number>` | — | Template variables |
287
- | `cc` | `string[]` | — | CC recipients |
288
- | `bcc` | `string[]` | — | BCC recipients |
289
- | `replyTo` | `string` | — | Reply-to address |
290
- | `attachments` | `IEmailAttachment[]` | — | File attachments |
291
-
292
- ### EmailBuilderStateService
293
-
294
- Component-scoped service managing the visual builder state:
295
-
296
- ```typescript
297
- // Component-scoped — not provided at root
298
- @Component({
299
- providers: [EmailBuilderStateService],
300
- })
301
- export class EmailBuilderComponent {
302
- private state = inject(EmailBuilderStateService);
303
-
304
- schema = this.state.schema; // Signal<IEmailSchema>
305
- selectedBlock = this.state.selectedBlock; // Signal<IEmailBlock | null>
306
- isDirty = this.state.isDirty; // Signal<boolean>
307
- previewMode = this.state.previewMode; // Signal<'desktop' | 'mobile'>
308
- }
309
- ```
310
-
311
- ---
312
-
313
- ## Components
314
-
315
- ### EmailBuilderComponent
316
-
317
- Visual block-based email template editor:
318
-
319
- ```html
320
- <flusys-email-builder
321
- [templateId]="templateId"
322
- (saved)="onTemplateSaved($event)"
323
- />
324
- ```
325
-
326
- Features:
327
- - Left panel: Block type palette
328
- - Center: Email canvas (drag to reorder blocks)
329
- - Right panel: Selected block properties
330
- - Top bar: Save draft / Publish / Preview toggle
331
-
332
- ### EmailPreviewComponent
333
-
334
- Renders an email template with mock variable values:
335
-
336
- ```html
337
- <flusys-email-preview
338
- [schema]="emailSchema"
339
- [variables]="mockVariables"
340
- [viewport]="'desktop'"
341
- />
342
- ```
343
-
344
- | Input | Type | Description |
345
- |-------|------|-------------|
346
- | `schema` | `IEmailSchema` | Template to preview |
347
- | `variables` | `Record<string, string>` | Mock values for `{{vars}}` |
348
- | `viewport` | `'desktop' \| 'mobile'` | Preview viewport width |
349
-
350
- ---
351
-
352
- ## Email Provider Enum
353
-
354
- ```typescript
355
- import { EmailProviderEnum } from '@flusys/ng-email';
356
-
357
- enum EmailProviderEnum {
358
- SMTP = 'SMTP',
359
- SENDGRID = 'SENDGRID',
360
- MAILGUN = 'MAILGUN',
361
- }
362
- ```
363
-
364
- ---
365
-
366
- ## API Endpoints
367
-
368
- | Method | Endpoint | Description |
369
- |--------|----------|-------------|
370
- | POST | `/email/provider/get-all` | List email providers |
371
- | POST | `/email/provider/get/:id` | Get provider config |
372
- | POST | `/email/provider/insert` | Add provider |
373
- | POST | `/email/provider/update` | Update provider |
374
- | POST | `/email/provider/delete` | Delete provider |
375
- | POST | `/email/provider/test/:id` | Send test email |
376
- | POST | `/email/template/get-all` | List templates |
377
- | POST | `/email/template/get/:id` | Get template |
378
- | POST | `/email/template/insert` | Create template |
379
- | POST | `/email/template/update` | Update template |
380
- | POST | `/email/template/delete` | Delete template |
381
- | POST | `/email/template/publish/:id` | Publish template |
382
- | POST | `/email/send` | Send email |
383
-
384
- ---
385
-
386
- ## Configuration Reference
387
-
388
- | Config Key | Type | Default | Description |
389
- |------------|------|---------|-------------|
390
- | `services.email.enabled` | `boolean` | `false` | Enable email module |
391
-
392
- Email provider credentials (API keys, SMTP host/port) are configured server-side in `nestjs-email`. The Angular client only calls the send API.
393
-
394
- ---
395
-
396
- ## Troubleshooting
397
-
398
- **`EmailSendService.send()` returns 404**
399
-
400
- Template with the given `key` doesn't exist or is still in draft. Publish the template first via the builder UI or `templateApi.publish(id)`.
401
-
402
- **Visual builder blocks not reordering**
403
-
404
- CDK drag-and-drop requires `@angular/cdk`. Install it and import `DragDropModule`.
405
-
406
- **Images in email not displaying for recipients**
407
-
408
- Images are referenced by file ID. The backend resolves these to absolute URLs when rendering. Ensure `ng-storage` is configured and the storage backend is publicly accessible (or uses presigned URLs).
409
-
410
- **Variables showing as `{{varName}}` in sent emails**
411
-
412
- The `variables` object key doesn't match the template placeholder. Check for exact case match: `{{customerName}}` requires `{ customerName: '...' }`.
413
-
414
- **Provider test fails with "Connection refused"**
415
-
416
- SMTP host/port is incorrect or the email provider's server is blocking the connection. Verify credentials in the Email Providers configuration page.
417
-
418
- ---
32
+ Routes require permissions (`EMAIL_TEMPLATE_PERMISSIONS`, `EMAIL_CONFIG_PERMISSIONS`) from `@flusys/ng-shared` ensure IAM is configured.
419
33
 
420
34
  ## License
421
35