@bigbinary/neeto-email-notifications-frontend 2.2.13 → 2.2.15

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,170 +1,616 @@
1
1
  # neeto-email-notifications-nano
2
2
 
3
- The neeto-email-notifications-nano enables the management of email notifications
4
- within neeto applications. The nano exports the
5
- @bigbinary/neeto-email-notifications-frontend NPM package and
6
- neeto-email-notifications-engine Rails engine for development.
7
-
8
- ## Contents
9
-
10
- 1. [Development with Host Application](#development-with-host-application)
11
- - [Engine](#engine)
12
- - [Installation](#installation)
13
- - [Usage](#usage)
14
- - [Frontend package](#frontend-package)
15
- - [Installation](#installation-1)
16
- - [Usage](#usage-1)
17
- 2. [Instructions for Publishing](#instructions-for-publishing)
18
-
19
- ## Development with Host Application
20
-
21
- ### Engine
22
-
23
- The engine is used to manage email notifications across neeto products.
24
-
25
- #### Installation
26
-
27
- 1. Add this line to your application's Gemfile:
28
-
29
- ```ruby
30
- source "NEETO_GEM_SERVER_URL" do
31
- # Rails engine to manage email notifications
32
- gem "neeto-email-notifications-engine"
33
- end
34
- ```
35
-
36
- 2. And then execute:
37
-
38
- ```shell
39
- bundle install
40
- ```
41
-
42
- 3. Add this line to your application's `config/routes.rb` file (replace `at` to
43
- your desired route):
44
-
45
- ```ruby
46
- mount NeetoEmailNotificationsEngine::Engine, at: "/neeto_email_notifications"
47
- ```
48
-
49
- 4. Explicitly specify via initializer which all models can hold email notifications:
50
-
51
- ```ruby
52
- # config/initializers/neeto_email_notifications_engine.rb
53
- NeetoEmailNotificationsEngine.configure do |config|
54
- config.allowed_notification_holder_types = ["PaymentPlan", "SomeOtherModel"]
55
- end
56
- ```
57
-
58
- 5. Add required migrations in the `db/migrate` folder. Run the following
59
- commands to generate the migrations.
60
-
61
- ```shell
62
- rails g neeto_email_notifications_engine:install
63
- ```
64
-
65
- This will generate the migration to create the
66
- `neeto_email_notifications_engine_email_notifications` table, which holds the
67
- data for the email notifications, and have `custom_fields` column to include
68
- custom attributes
69
-
70
- 6. Run the following command to create the tables.
71
-
72
- ```shell
73
- rails db:migrate
74
- ```
75
-
76
- #### Usage
77
-
78
- 1. Create required email notification models inherited from
79
- `NeetoEmailNotificationsEngine::EmailNotification`. For example,
80
-
81
- ```ruby
82
- class PushEmailNotification < ::NeetoEmailNotificationsEngine::EmailNotification
83
- default_scope { where("custom_fields -> 'notification_type' ? :value", value: "Push") }
84
- after_initialize :set_custom_field
85
-
86
- def set_custom_field
87
- self.custom_fields ||= {}
88
- self.custom_fields[custom_field_key] = "Push"
89
- end
90
-
91
- def custom_field_key
92
- "notification_type"
93
- end
94
- end
95
- ```
96
-
97
- 2. Add the required associations to the polymorphic model. For example,
98
-
99
- ```ruby
100
- class Form < ApplicationRecord
101
- ....
102
-
103
- has_many :email_notifications, as: :notification_holder, class_name: "::NeetoEmailNotificationsEngine::EmailNotification", dependent: :destroy
104
- has_one :push_email_notification, as: :notification_holder
3
+ The `neeto-email-notifications-nano` is a comprehensive email notification management solution designed for the Neeto ecosystem. Implemented as a Ruby on Rails engine with associated React frontend components (`@bigbinary/neeto-email-notifications-frontend`), it provides a unified interface for managing email notifications across neeto applications.
4
+
5
+ # Table of Contents
6
+
7
+ 1. [Installation (Backend Engine)](#installation-backend-engine)
8
+ - [1. Add the Gem](#1-add-the-gem)
9
+ - [2. Install Gems](#2-install-gems)
10
+ - [3. Install Migrations](#3-install-migrations)
11
+ - [4. Run Migrations](#4-run-migrations)
12
+ - [5. Mount the Engine](#5-mount-the-engine)
13
+ 2. [Configuration (Backend Engine)](#configuration-backend-engine)
14
+ - [1. Initializer Setup](#1-initializer-setup)
15
+ - [2. Model Associations](#2-model-associations)
16
+ 3. [Frontend Integration](#frontend-integration)
17
+ - [1. Install Frontend Package](#1-install-frontend-package)
18
+ - [2. Install Peer Dependencies](#2-install-peer-dependencies)
19
+ - [3. Components](#3-components)
20
+ - [4. Hooks](#4-hooks)
21
+ 4. [Core Concepts](#core-concepts)
22
+ 5. [Usage Examples](#usage-examples)
23
+ - [Creating Custom Notification Models](#creating-custom-notification-models)
24
+ - [Setting Up Notification Holders](#setting-up-notification-holders)
25
+ - [Using the Email Notification Service](#using-the-email-notification-service)
26
+ 6. [API Endpoints](#api-endpoints)
27
+ 7. [Liquid Template Variables](#liquid-template-variables)
28
+ 8. [Email Validation](#email-validation)
29
+ 9. [Incineration Concern](#incineration-concern)
30
+ 10. [Development Environment Setup](#development-environment-setup)
31
+ 11. [Testing & Debugging](#testing--debugging)
32
+ 12. [Publishing](#publishing)
33
+
34
+ ## Installation (Backend Engine)
35
+
36
+ Follow these steps to integrate the `neeto-email-notifications-engine` into your host Rails application:
37
+
38
+ ### 1. Add the Gem
39
+ Add the gem to your application's `Gemfile`:
40
+ ```ruby
41
+ # Gemfile
42
+ source "NEETO_GEM_SERVER_URL" do
43
+ gem "neeto-email-notifications-engine"
44
+ end
45
+ ```
46
+
47
+ ### 2. Install Gems
48
+ Run bundler to install the gem and its dependencies:
49
+ ```bash
50
+ bundle install
51
+ ```
52
+
53
+ ### 3. Install Migrations
54
+ Add required migrations in the `db/migrate` folder. Run the following
55
+ commands to generate the migrations.
56
+
57
+ ```shell
58
+ bundle exec rails g neeto_email_notifications_engine:install
59
+ ```
60
+
61
+ This will generate the migration to create the
62
+ `neeto_email_notifications_engine_email_notifications` table, which holds the
63
+ data for the email notifications, and have `custom_fields` column to include
64
+ custom attributes.
65
+
66
+ ### 4. Run Migrations
67
+ Apply the migrations to your database:
68
+ ```bash
69
+ bundle exec rails db:migrate
70
+ ```
71
+
72
+ ### 5. Mount the Engine
73
+ Add the engine's routes to your application's `config/routes.rb`:
74
+ ```ruby
75
+ # config/routes.rb
76
+ mount NeetoEmailNotificationsEngine::Engine, at: "/neeto_email_notifications" # Or your preferred mount point
77
+ ```
78
+
79
+ > **Note:** The engine uses the [`liquid`](https://github.com/Shopify/liquid)
80
+ > gem for template rendering. This will be installed automatically as a
81
+ > dependency.
82
+
83
+ ## Configuration (Backend Engine)
84
+
85
+ ### 1. Initializer Setup
86
+ Create an initializer file `config/initializers/neeto_email_notifications_engine.rb` to configure the engine:
87
+
88
+ ```ruby
89
+ # config/initializers/neeto_email_notifications_engine.rb
90
+ NeetoEmailNotificationsEngine.configure do |config|
91
+ # IMPORTANT: Configure which model types can hold email notifications.
92
+ # This configuration is MANDATORY for the engine to work properly.
93
+ config.allowed_notification_holder_types = ["PaymentPlan", "SomeOtherModel"]
94
+ end
95
+ ```
96
+
97
+ The allowed_notification_holder_types configuration is mandatory. Failing to configure this will result in validation errors when creating email notifications.
98
+
99
+ ### 2. Models
100
+
101
+ #### `NeetoEmailNotificationsEngine::EmailNotification` ([source code](https://github.com/bigbinary/neeto-email-notifications-nano/blob/main/app/models/neeto_email_notifications_engine/email_notification.rb))
102
+
103
+ **Key Associations:**
104
+ ```ruby
105
+ belongs_to :notification_holder, polymorphic: true
106
+ has_rich_text :message
107
+ ```
108
+
109
+ **Key Validations:**
110
+ - `notification_holder_type` must be in the configured `allowed_notification_holder_types`.
111
+ - `subject`, `message` are required when `is_enabled` is true.
112
+ - `send_from` must be a valid email format when required.
113
+ - All email fields (`notify_emails`, `notify_cc_emails`, `notify_bcc_emails`) are validated for proper email format.
114
+
115
+
116
+ **Available Methods:**
117
+ - `message_body_content`: Returns HTML content of the rich text message.
118
+ - `custom_field_key`: Abstract method that subclasses must implement.
119
+ - `notification_type`: Returns the notification type from custom fields.
120
+ - `disabled_by_user?`: Checks if the notification was disabled by user action.
121
+
122
+ #### Setting Up Host Application Models
123
+
124
+ Ensure the models specified in `allowed_notification_holder_types` have the correct associations defined:
125
+
126
+ **Single Notification Per Model (Most Common)**
127
+ ```ruby
128
+ # app/models/form.rb
129
+ class Form < ApplicationRecord
130
+ # Standard single notification association
131
+ has_one :email_notification, as: :notification_holder,
132
+ class_name: "::NeetoEmailNotificationsEngine::EmailNotification", dependent: :destroy
133
+
134
+ # Optional: Create default notification after model creation
135
+ after_create :seed_email_notification
136
+
137
+ private
138
+
139
+ def seed_email_notification
140
+ self.create_email_notification!(
141
+ send_from: Rails.application.secrets.mailer[:default_from_email],
142
+ notify_emails: [],
143
+ is_enabled: false,
144
+ subject: "New {{form-name}} submission",
145
+ message: "A new submission has been received for {{form-name}}."
146
+ )
147
+ end
148
+ end
149
+ ```
150
+
151
+ **Multiple Notification Types Per Model**
152
+ ```ruby
153
+ # app/models/meeting.rb
154
+ class Meeting < ApplicationRecord
155
+ # General association for all notifications
156
+ has_many :email_notifications, as: :notification_holder,
157
+ class_name: "::NeetoEmailNotificationsEngine::EmailNotification", dependent: :destroy
158
+
159
+ # Specific notification types using custom fields
160
+ has_one :reminder_notification,
161
+ -> { where("custom_fields -> 'notification_type' ? :value", value: "reminder") },
162
+ as: :notification_holder, class_name: "::NeetoEmailNotificationsEngine::EmailNotification"
163
+
164
+ has_one :confirmation_notification,
165
+ -> { where("custom_fields -> 'notification_type' ? :value", value: "confirmation") },
166
+ as: :notification_holder, class_name: "::NeetoEmailNotificationsEngine::EmailNotification"
167
+
168
+ has_one :cancellation_notification,
169
+ -> { where("custom_fields -> 'notification_type' ? :value", value: "cancellation") },
170
+ as: :notification_holder, class_name: "::NeetoEmailNotificationsEngine::EmailNotification"
171
+
172
+ after_create :setup_default_notifications
173
+
174
+ private
175
+
176
+ def setup_default_notifications
177
+ create_reminder_notification!(
178
+ send_from: "meetings@company.com",
179
+ subject: "Reminder: {{meeting-title}} starts in 1 hour",
180
+ message: "Your meeting {{meeting-title}} is scheduled to start in 1 hour.",
181
+ custom_fields: { notification_type: "reminder" },
182
+ is_enabled: false
183
+ )
184
+
185
+ create_confirmation_notification!(
186
+ send_from: "meetings@company.com",
187
+ subject: "Meeting Confirmed: {{meeting-title}}",
188
+ message: "Your meeting {{meeting-title}} has been confirmed for {{meeting-date}}.",
189
+ custom_fields: { notification_type: "confirmation" },
190
+ is_enabled: true
191
+ )
192
+ end
193
+ end
194
+ ```
195
+
196
+ **Creating Custom Notification Models**
197
+ ```ruby
198
+ # app/models/submission_email_notification.rb
199
+ class SubmissionEmailNotification < ::NeetoEmailNotificationsEngine::EmailNotification
200
+ # Scope to only submission notifications
201
+ default_scope { where("custom_fields -> 'notification_type' ? :value", value: "submission") }
202
+
203
+ after_initialize :set_notification_type
204
+
205
+ def custom_field_key
206
+ "notification_type"
207
+ end
208
+
209
+ private
210
+
211
+ def set_notification_type
212
+ self.custom_fields ||= {}
213
+ self.custom_fields[custom_field_key] = "submission"
214
+ end
215
+ end
216
+
217
+ # Usage in host model
218
+ class Form < ApplicationRecord
219
+ has_one :submission_email_notification, as: :notification_holder, dependent: :destroy
220
+
221
+ # You can still have the general association too
222
+ has_one :email_notification, as: :notification_holder,
223
+ class_name: "::NeetoEmailNotificationsEngine::EmailNotification", dependent: :destroy
224
+ end
225
+ ```
226
+
227
+ **Database Schema Information**
228
+ The engine creates a table `neeto_email_notifications_engine_email_notifications` with these key columns:
229
+ - `notification_holder_type` & `notification_holder_id`: Polymorphic association.
230
+ - `notify_emails`: Array of recipient email addresses.
231
+ - `notify_cc_emails` & `notify_bcc_emails`: Arrays for CC and BCC recipients.
232
+ - `send_from`: Sender email address.
233
+ - `subject`: Email subject (supports Liquid templates).
234
+ - `message`: Rich text message content (supports Liquid templates).
235
+ - `is_enabled`: Boolean flag to enable/disable notifications.
236
+ - `custom_fields`: JSONB column for additional metadata.
237
+ - `reply_to_id`: Optional reference for reply-to configuration.
238
+ - `type`: String column for Single Table Inheritance (STI) support.
239
+
240
+ #### Default Attributes Class Method
241
+
242
+ **Important:** Host applications must define the `default_attributes` class method in their custom notification models that inherit from `NeetoEmailNotificationsEngine::EmailNotification`. This method is required and will receive the `notification_holder` as a parameter. This method should return a hash with the default attributes for the email notification.
243
+
244
+ Variables in the subject and message must always be wrapped like this:
245
+ ```html
246
+ <span data-variable data-label="label" data-id="key">{{key}}</span>
247
+ ```
248
+
249
+ **Example Implementation**
250
+
251
+ ```ruby
252
+ def self.default_attributes(quiz)
253
+ {
254
+ send_from: Rails.application.secrets.mailer[:default_from_email],
255
+ notify_emails: [quiz.user.email],
256
+ is_enabled: true,
257
+ subject: "A new submission has arrived for {{quiz-name}}",
258
+ message: <<~HTML.squish
259
+ <b><span data-variable data-label="Quiz name" data-id="quiz-name">{{quiz-name}}</span></b>
260
+ has a new submission.<br/><br/>
261
+ <span data-variable data-label="All answers" data-id="all-answers">{{all-answers}}</span>
262
+ HTML
263
+ }
264
+ end
265
+ ```
266
+
267
+ ## Frontend Integration
268
+
269
+ ### 1. Install Frontend Package
270
+ ```bash
271
+ yarn add @bigbinary/neeto-email-notifications-frontend
272
+ ```
273
+ This package will provide a single component `NeetoEmailNotification`, which
274
+ uses components from `neeto-molecules`.
275
+
276
+ ### 2. Install Peer Dependencies
277
+ If the host app doesn't already include these peer dependencies, install them:
278
+ ```bash
279
+ # DO NOT INSTALL THE EXACT VERSIONS MENTIONED BELOW AS THEY MIGHT BE OUTDATED.
280
+ # ALWAYS PREFER INSTALLING THE LATEST COMPATIBLE VERSIONS.
281
+ yarn add @babel/runtime@^7.26.10 @bigbinary/neeto-cist@^1.0.17 @bigbinary/neeto-commons-frontend@^4.13.43 @bigbinary/neeto-editor@^1.47.16 @bigbinary/neeto-filters-frontend@^4.3.21 @bigbinary/neeto-icons@^1.20.49 @bigbinary/neeto-molecules@^3.16.63 @bigbinary/neetoui@^8.3.9 @honeybadger-io/js@^6.10.1 @honeybadger-io/react@^6.1.25 @tailwindcss/container-queries@^0.1.1 @tanstack/react-query@^5.59.20 @tanstack/react-query-devtools@^5.59.20 antd@^5.22.0 axios@^1.8.2 buffer@^6.0.3 classnames@^2.5.1 crypto-browserify@^3.12.1 dompurify@^3.2.4 formik@^2.4.6 https-browserify@^1.0.0 i18next@^22.5.1 js-logger@^1.6.1 mixpanel-browser@^2.47.0 os-browserify@^0.3.0 path-browserify@^1.0.1 qs@^6.11.2 ramda@^0.29.0 react@^18.3.1 react-dom@^18.3.1 react-helmet@^6.1.0 react-i18next@^12.3.1 react-router-dom@^5.3.3 react-toastify@^8.0.2 source-map-loader@^4.0.1 stream-browserify@^3.0.0 stream-http@^3.2.0 tailwindcss@^3.4.14 tty-browserify@^0.0.1 url@^0.11.0 util@^0.12.5 vm-browserify@^1.1.2 yup@^0.32.11 zustand@^4.4.2
282
+ ```
283
+ *Note: Carefully manage potential version conflicts with your host application.*
284
+
285
+ ### 3. Components
286
+
287
+ #### `NeetoEmailNotificationForm` ([source code](https://github.com/bigbinary/neeto-email-notifications-nano/blob/main/app/javascript/src/components/EmailNotificationForm/index.jsx))
288
+
289
+ **Props**
290
+
291
+ | Prop | Type | Default | Description |
292
+ | ------------------------- | --------- | -------------------------------------------------------- | ---------------------------------------------------------------- |
293
+ | `emailNotificationParams` | Object | `{}` | **Required.** Parameters for fetching email notification data |
294
+ | `title` | String | `"Email notification"` | Title displayed above the notification toggle |
295
+ | `notificationToggleLabel` | String | `"Send an email notification when a new event occurred"` | The label displayed beside the notification toggle switch |
296
+ | `disabled` | Boolean | `false` | Disables the entire component |
297
+ | `onSuccess` | Function | `noop` | Callback function triggered after successful notification update |
298
+ | `breadcrumbs` | Array | `[]` | Breadcrumb navigation data |
299
+ | `children` | ReactNode | `undefined` | Additional content rendered when notifications are enabled |
300
+ | `blockNavigation` | Boolean | `false` | Shows block navigation alert for unsaved changes |
301
+ | `helpPopoverProps` | Object | `{}` | Props for the help popover component |
302
+ | `tooltipProps` | Object | `{}` | Props for tooltip shown when component is disabled |
303
+ | `emailFormProps` | Object | `{}` | Props passed to the underlying EmailForm component |
304
+ | `emailFormikProps` | Object | `{}` | Props passed to the EmailFormProvider component |
305
+ | `emailPreviewProps` | Object | `{}` | Props passed to the EmailPreview component |
306
+ | `fieldsVisibility` | Object | `{}` | Controls which fields are visible in the email form |
307
+
308
+ #### FieldsVisibility
309
+
310
+ Default visibility for each field is as follows:
311
+
312
+ ```js
313
+ {
314
+ showSendToField: true,
315
+ showReplyToField: false,
316
+ showSendToAsRadio: false,
317
+ showCcField: false,
318
+ showBccField: false,
319
+ }
320
+ ```
321
+
322
+ You can override any of these by passing a `fieldsVisibility` prop with your
323
+ desired values.
324
+
325
+ **emailNotificationParams Object Structure**
326
+ ```javascript
327
+ {
328
+ notificationHolderId: "uuid-string", // ID of the notification holder
329
+ notificationHolderType: "Form", // Type of the notification holder
330
+ customFields: { // Optional custom fields for filtering
331
+ notificationType: "submission" // Example: different notification types
332
+ }
333
+ }
334
+ ```
335
+
336
+ **Usage Example**
337
+ ```jsx
338
+ import React from "react";
339
+ import { NeetoEmailNotificationForm } from "@bigbinary/neeto-email-notifications-frontend";
340
+
341
+ const FormSettingsPage = ({ formId }) => {
342
+ const handleNotificationUpdate = () => {
343
+ console.log("Email notification updated successfully!");
344
+ };
345
+
346
+ return (
347
+ <NeetoEmailNotificationForm
348
+ title="Form Submission Notification"
349
+ notificationToggleLabel="Get notified when someone submits your form"
350
+ emailNotificationParams={{
351
+ notificationHolderId: formId,
352
+ notificationHolderType: "Form",
353
+ customFields: { notificationType: "submission" }
354
+ }}
355
+ emailPreviewProps={{
356
+ formatBody: message => replaceVariablesWithDummyValues(message, values),
357
+ }}
358
+ breadcrumbs={[
359
+ { text: "Forms", link: "/forms" },
360
+ { text: "Settings", link: `/forms/${formId}/settings` }
361
+ ]}
362
+ onSuccess={handleNotificationUpdate}
363
+ />
364
+ );
365
+ };
366
+
367
+ export default FormSettingsPage;
368
+ ```
369
+
370
+ ### 4. Hooks
371
+
372
+ #### `useFetchEmailNotifications` ([source code](https://github.com/neetozone/neeto-email-notifications-nano/blob/main/app/javascript/src/hooks/reactQuery/emailNotificationApi.js#L10))
373
+ Fetches email notification data for a specific notification holder.
374
+ ```javascript
375
+ import { useFetchEmailNotifications } from "@bigbinary/neeto-email-notifications-frontend";
376
+
377
+ const { data, isLoading, error } = useFetchEmailNotifications({
378
+ notificationHolderId: "form-uuid",
379
+ notificationHolderType: "Form",
380
+ customFields: { notificationType: "submission" }
381
+ });
382
+ ```
383
+
384
+ #### `useUpdateEmailNotification` ([source code](https://github.com/neetozone/neeto-email-notifications-nano/blob/main/app/javascript/src/hooks/reactQuery/emailNotificationApi.js#L23))
385
+ Updates email notification settings.
386
+
387
+ ```javascript
388
+ import { useUpdateEmailNotification } from "@bigbinary/neeto-email-notifications-frontend";
389
+
390
+ const { mutate: updateEmailNotification, isPending } = useUpdateEmailNotification();
391
+
392
+ const handleUpdate = (notificationData) => {
393
+ updateEmailNotification({
394
+ ...notificationData,
395
+ notificationHolderId: "form-uuid",
396
+ notificationHolderType: "Form"
397
+ });
398
+ };
399
+ ```
400
+
401
+ ## Usage Examples
402
+
403
+ ### Creating Custom Notification Models
404
+ You can create specialized notification models that inherit from the base `EmailNotification` class:
405
+
406
+ ```ruby
407
+ class SubmissionEmailNotification < ::NeetoEmailNotificationsEngine::EmailNotification
408
+ default_scope { where("custom_fields -> 'notification_type' ? :value", value: "submission") }
409
+
410
+ after_initialize :set_notification_type
411
+
412
+ def custom_field_key
413
+ "notification_type"
414
+ end
415
+
416
+ private
417
+
418
+ def set_notification_type
419
+ self.custom_fields ||= {}
420
+ self.custom_fields[custom_field_key] = "submission"
421
+ end
422
+ end
423
+ ```
424
+
425
+ ### Setting Up Notification Holders
426
+ Configure your models to support email notifications:
427
+
428
+ ```ruby
429
+ class Meeting < ApplicationRecord
430
+ has_one :reminder_notification, -> { where("custom_fields -> 'notification_type' ? :value", value: "reminder") },
431
+ as: :notification_holder, class_name: "::NeetoEmailNotificationsEngine::EmailNotification"
432
+
433
+ has_one :confirmation_notification, -> { where("custom_fields -> 'notification_type' ? :value", value: "confirmation") },
434
+ as: :notification_holder, class_name: "::NeetoEmailNotificationsEngine::EmailNotification"
435
+
436
+ after_create :setup_notifications
437
+
438
+ private
439
+
440
+ def setup_notifications
441
+ create_reminder_notification!(
442
+ send_from: "meetings@company.com",
443
+ subject: "Reminder: {{meeting-title}} in 1 hour",
444
+ message: "Your meeting {{meeting-title}} is scheduled to start in 1 hour.",
445
+ custom_fields: { notification_type: "reminder" }
446
+ )
447
+
448
+ create_confirmation_notification!(
449
+ send_from: "meetings@company.com",
450
+ subject: "Meeting Confirmed: {{meeting-title}}",
451
+ message: "Your meeting {{meeting-title}} has been confirmed for {{meeting-date}}.",
452
+ custom_fields: { notification_type: "confirmation" }
453
+ )
454
+ end
455
+ end
456
+ ```
457
+
458
+ ### Seeding Default Email Notification Content
459
+ It is recommended to automatically create a default email notification record for each instance of your model. This ensures the notification UI and API always have a record to fetch and update, preventing errors and missing functionality. You can use an `after_create` callback in your model to seed this record.
460
+
461
+ ##### Example:
462
+
463
+ ```ruby
464
+ class Quiz < ApplicationRecord
465
+ has_many :email_notifications, as: :notification_holder,
466
+ class_name: "NeetoEmailNotificationsEngine::EmailNotification", dependent: :destroy
467
+ has_one :push_email_notification, as: :notification_holder
468
+
469
+ after_create :create_default_email_notification
470
+
471
+ private
472
+
473
+ def create_default_email_notification
474
+ self.create_push_email_notification!(PushEmailNotification.default_attributes(self))
475
+ end
476
+ end
477
+ ```
478
+
479
+ ### Using the Email Notification Service
480
+ Create service classes that include the email notification functionality:
481
+
482
+ ```ruby
483
+ class MeetingReminderService
484
+ include ::NeetoEmailNotificationsEngine::EmailNotificationService
485
+
486
+ def initialize(meeting)
487
+ @meeting = meeting
488
+ @email_notification = meeting.reminder_notification
489
+ end
490
+
491
+ private
492
+
493
+ def send_emails
494
+ return unless @email_notification.is_enabled?
495
+
496
+ MeetingMailer.reminder_email(
497
+ recipients: @email_notification.notify_emails,
498
+ cc: @email_notification.notify_cc_emails,
499
+ bcc: @email_notification.notify_bcc_emails,
500
+ subject: @subject,
501
+ message: @message,
502
+ meeting: @meeting
503
+ ).deliver_now
504
+ end
505
+
506
+ def load_liquid_parameters
507
+ @liquid_parameters[:text] = {
508
+ "meeting-title" => @meeting.title,
509
+ "meeting-date" => @meeting.scheduled_at.strftime("%B %d, %Y"),
510
+ "meeting-time" => @meeting.scheduled_at.strftime("%I:%M %p")
511
+ }
512
+
513
+ @liquid_parameters[:html] = @liquid_parameters[:text]
514
+ end
515
+ end
516
+
517
+ # Usage
518
+ meeting = Meeting.find(params[:id])
519
+ MeetingReminderService.new(meeting).process
520
+ ```
521
+
522
+ ## API Endpoints
523
+
524
+ The engine exposes API endpoints under the configured mount path (default `/neeto_email_notifications`):
525
+
526
+ | Method | Path | Description | Parameters |
527
+ |--------|------|-------------|------------|
528
+ | GET | `/email_notification` | Fetch email notification settings | `notification_holder_id`, `notification_holder_type`, `custom_fields` |
529
+ | PUT | `/email_notification` | Update email notification settings | `notification_holder_id`, `notification_holder_type`, `email_notification` params |
530
+
531
+ **Example API Usage:**
532
+ ```javascript
533
+ // Fetch notification settings
534
+ axios.get('/neeto_email_notifications/email_notification', {
535
+ params: {
536
+ notification_holder_id: 'form-uuid',
537
+ notification_holder_type: 'Form',
538
+ custom_fields: { notification_type: 'submission' }
539
+ }
540
+ })
541
+
542
+ // Update notification settings
543
+ axios.put('/neeto_email_notifications/email_notification', {
544
+ notification_holder_id: 'form-uuid',
545
+ notification_holder_type: 'Form',
546
+ email_notification: {
547
+ is_enabled: true,
548
+ subject: 'New form submission',
549
+ message: 'A new submission was received.',
550
+ notify_emails: ['admin@company.com'],
551
+ send_from: 'forms@company.com'
552
+ }
553
+ })
554
+ ```
555
+
556
+ ## Liquid Template Variables
557
+
558
+ Email subjects and messages support Liquid templating for dynamic content:
559
+
560
+ ```ruby
561
+ # In your notification setup
562
+ email_notification.update!(
563
+ subject: "New {{form-name}} submission from {{user-name}}",
564
+ message: "Hello {{admin-name}}, a new submission was received for {{form-name}} on {{submission-date}}."
565
+ )
566
+
567
+ # In your service class
568
+ def load_liquid_parameters
569
+ @liquid_parameters[:text] = {
570
+ "form-name" => @form.name,
571
+ "user-name" => @submission.user.name,
572
+ "admin-name" => @form.owner.name,
573
+ "submission-date" => @submission.created_at.strftime("%B %d, %Y")
574
+ }
575
+
576
+ @liquid_parameters[:html] = @liquid_parameters[:text]
577
+ end
578
+ ```
579
+
580
+ ## Development Environment Setup
581
+
582
+ ### Instructions for Development
583
+ Check the [Frontend package development guide](https://neeto-engineering.neetokb.com/p/a-d34cb4b0) for step-by-step instructions to develop the frontend package.
105
584
 
106
- ....
107
- end
585
+ ### Backend Development
586
+ 1. **Rails Server:** Start the main application
587
+ ```bash
588
+ bundle exec rails server
108
589
  ```
109
590
 
110
- You can learn more about the setup and usage here:
111
-
112
- 1. [Models](/docs/engine/models.md)
113
- 2. [Services](/docs/engine/services.md)
114
-
115
- ### Frontend package
116
-
117
- #### Installation
118
-
119
- 1. Add the `neeto-email-notifications-frontend` package to the `package.json`
120
-
121
- ```shell
122
- yarn add @bigbinary/neeto-email-notifications-frontend
591
+ 2. **Database Setup:** Ensure migrations are run
592
+ ```bash
593
+ bundle exec rails db:migrate
123
594
  ```
124
595
 
125
- This package will provide a single component `NeetoEmailNotification`, which
126
- uses components from `neeto-molecules`.
127
-
128
- #### Instructions for development
129
-
130
- Check the [Frontend package development guide](https://neeto-engineering.neetokb.com/p/a-d34cb4b0) for step-by-step instructions to develop the frontend package.
131
-
132
- #### Usage
133
-
134
- 1. Add the component to the host application. For example,
135
- ```js
136
- <NeetoEmailNotificationForm
137
- title="Email notification"
138
- subtitle="Send an email notification when a new event occurred"
139
- emailPreviewProps={{ productName: "Product" }}
140
- emailNotificationParams={{
141
- notificationHolderType: "Form",
142
- notificationHolderId: formId,
143
- customFields: { notificationType: "Push" },
144
- }}
145
- />
596
+ 3. **Testing:** Run the test suite
597
+ ```bash
598
+ bundle exec rails test
146
599
  ```
147
600
 
148
- ##### NeetoEmailNotificationForm
149
-
150
- The component is a form-based interface for adding or editing team members.
151
-
152
- ###### Props
153
-
154
- - `title`: The title of the component.
155
- - `subtitle`: The subtitle of the component.
156
- - `onSuccess`: Function that will be called when the email notification is
157
- updated successfully.
158
- - `disabled`: Disables the component.
159
-
160
- You can learn more about the NeetoEmailNotificationForm component and usage
161
- here:
601
+ ## Testing & Debugging
162
602
 
163
- 1. [NeetoEmailNotificationForm component](./docs/frontend/neeto_email_notification_form.md)
603
+ ### Test Helpers
604
+ The engine provides factories for testing:
164
605
 
606
+ ```ruby
607
+ # Use in your tests
608
+ FactoryBot.create(:neeto_email_notification_engine_email_notification,
609
+ notification_holder: your_model_instance
610
+ )
611
+ ```
612
+ Use the ```test/dummy``` app within the engine's repository for isolated testing.
165
613
 
166
- ## Instructions for Publishing
614
+ ## Publishing
167
615
 
168
- Consult the
169
- [building and releasing packages](https://neeto-engineering.neetokb.com/articles/building-and-releasing-packages)
170
- guide for details on how to publish.
616
+ For instructions on building and releasing the `@bigbinary/neeto-email-notifications-frontend` NPM package and the `neeto-email-notifications-engine` Ruby gem, please refer to the internal guide: [Building and Releasing Packages](https://neeto-engineering.neetokb.com/articles/building-and-releasing-packages).