Browse Source

docs(email-plugin): Improve docs on custom handlers

Michael Bromley 3 years ago
parent
commit
a7797d446b
2 changed files with 90 additions and 5 deletions
  1. 74 2
      packages/email-plugin/src/event-handler.ts
  2. 16 3
      packages/email-plugin/src/plugin.ts

+ 74 - 2
packages/email-plugin/src/event-handler.ts

@@ -37,11 +37,17 @@ import {
  * This example creates a handler which listens for the `OrderStateTransitionEvent` and if the Order has
  * This example creates a handler which listens for the `OrderStateTransitionEvent` and if the Order has
  * transitioned to the `'PaymentSettled'` state, it will generate and send an email.
  * transitioned to the `'PaymentSettled'` state, it will generate and send an email.
  *
  *
+ * The string argument passed into the `EmailEventListener` constructor is used to identify the handler, and
+ * also to locate the directory of the email template files. So in the example above, there should be a directory
+ * `<app root>/static/email/templates/order-confirmation` which contains a Handlebars template named `body.hbs`.
+ *
  * ## Handling other languages
  * ## Handling other languages
  *
  *
  * By default, the handler will respond to all events on all channels and use the same subject ("Order confirmation for #12345" above)
  * By default, the handler will respond to all events on all channels and use the same subject ("Order confirmation for #12345" above)
  * and body template. Where the server is intended to support multiple languages, the `.addTemplate()` method may be used
  * and body template. Where the server is intended to support multiple languages, the `.addTemplate()` method may be used
- * to defined the subject and body template for specific language and channel combinations.
+ * to define the subject and body template for specific language and channel combinations.
+ *
+ * The language is determined by looking at the `languageCode` property of the event's `ctx` ({@link RequestContext}) object.
  *
  *
  * @example
  * @example
  * ```ts
  * ```ts
@@ -54,6 +60,72 @@ import {
  *   })
  *   })
  * ```
  * ```
  *
  *
+ * ## Defining a custom handler
+ *
+ * Let's say you have a plugin which defines a new event type, `QuoteRequestedEvent`. In your plugin you have defined a mutation
+ * which is executed when the customer requests a quote in your storefront, and in your resolver, you use the {@link EventBus} to publish a
+ * new `QuoteRequestedEvent`.
+ *
+ * You now want to email the customer with their quote. Here are the steps you would take to set this up:
+ *
+ * ### 1. Create a new handler
+ *
+ * ```TypeScript
+ * import { EmailEventListener } from `\@vendure/email-plugin`;
+ * import { QuoteRequestedEvent } from `./events`;
+ *
+ * const quoteRequestedHandler = new EmailEventListener('quote-requested')
+ *   .on(QuoteRequestedEvent)
+ *   .setRecipient(event => event.customer.emailAddress)
+ *   .setSubject(`Here's the quote you requested`)
+ *   .setTemplateVars(event => ({ details: event.details }));
+ * ```
+ *
+ * ### 2. Create the email template
+ *
+ * Next you need to make sure there is a template defined at `<app root>/static/email/templates/quote-requested/body.hbs`. The template
+ * would look something like this:
+ *
+ * ```handlebars
+ * {{> header title="Here's the quote you requested" }}
+ *
+ * <mj-section background-color="#fafafa">
+ *     <mj-column>
+ *         <mj-text color="#525252">
+ *             Thank you for your interest in our products! Here's the details
+ *             of the quote you recently requested:
+ *         </mj-text>
+ *
+ *         <--! your custom email layout goes here -->
+ *     </mj-column>
+ * </mj-section>
+ *
+ *
+ * {{> footer }}
+ * ```
+ *
+ * You can find pre-made templates on the [MJML website](https://mjml.io/templates/).
+ *
+ * ### 3. Register the handler
+ *
+ * Finally, you need to register the handler with the EmailPlugin:
+ *
+ * ```TypeScript {hl_lines=[8]}
+ * import { defaultEmailHandlers, EmailPlugin } from '\@vendure/email-plugin';
+ * import { quoteRequestedHandler } from './plugins/quote-plugin';
+ *
+ * const config: VendureConfig = {
+ *   // Add an instance of the plugin to the plugins array
+ *   plugins: [
+ *     EmailPlugin.init({
+ *       handlers: [...defaultEmailHandlers, quoteRequestedHandler],
+ *       templatePath: path.join(__dirname, 'vendure/email/templates'),
+ *       // ... etc
+ *     }),
+ *   ],
+ * };
+ * ```
+ *
  * @docsCategory EmailPlugin
  * @docsCategory EmailPlugin
  */
  */
 export class EmailEventHandler<T extends string = string, Event extends EventWithContext = EventWithContext> {
 export class EmailEventHandler<T extends string = string, Event extends EventWithContext = EventWithContext> {
@@ -348,7 +420,7 @@ export class EmailEventHandlerWithAsyncData<
     Data,
     Data,
     T extends string = string,
     T extends string = string,
     InputEvent extends EventWithContext = EventWithContext,
     InputEvent extends EventWithContext = EventWithContext,
-    Event extends EventWithAsyncData<InputEvent, Data> = EventWithAsyncData<InputEvent, Data>
+    Event extends EventWithAsyncData<InputEvent, Data> = EventWithAsyncData<InputEvent, Data>,
 > extends EmailEventHandler<T, Event> {
 > extends EmailEventHandler<T, Event> {
     constructor(
     constructor(
         public _loadDataFn: LoadDataFn<InputEvent, Data>,
         public _loadDataFn: LoadDataFn<InputEvent, Data>,

+ 16 - 3
packages/email-plugin/src/plugin.ts

@@ -27,9 +27,22 @@ import {
 
 
 /**
 /**
  * @description
  * @description
- * The EmailPlugin creates and sends transactional emails based on Vendure events. By default it uses an [MJML](https://mjml.io/)-based
+ * The EmailPlugin creates and sends transactional emails based on Vendure events. By default, it uses an [MJML](https://mjml.io/)-based
  * email generator to generate the email body and [Nodemailer](https://nodemailer.com/about/) to send the emails.
  * email generator to generate the email body and [Nodemailer](https://nodemailer.com/about/) to send the emails.
  *
  *
+ * ## High-level description
+ * Vendure has an internal events system (see {@link EventBus}) that allows plugins to subscribe to events. The EmailPlugin is configured with
+ * {@link EmailEventHandler}s that listen for a specific event and when it is published, the handler defines which template to use to generate
+ * the resulting email.
+ *
+ * The plugin comes with a set of default handlers for the following events:
+ * - Order confirmation
+ * - New customer email address verification
+ * - Password reset request
+ * - Email address change request
+ *
+ * You can also create your own handlers and register them with the plugin - see the {@link EmailEventHandler} docs for more details.
+ *
  * ## Installation
  * ## Installation
  *
  *
  * `yarn add \@vendure/email-plugin`
  * `yarn add \@vendure/email-plugin`
@@ -47,7 +60,7 @@ import {
  *   plugins: [
  *   plugins: [
  *     EmailPlugin.init({
  *     EmailPlugin.init({
  *       handlers: defaultEmailHandlers,
  *       handlers: defaultEmailHandlers,
- *       templatePath: path.join(__dirname, 'vendure/email/templates'),
+ *       templatePath: path.join(__dirname, 'static/email/templates'),
  *       transport: {
  *       transport: {
  *         type: 'smtp',
  *         type: 'smtp',
  *         host: 'smtp.example.com',
  *         host: 'smtp.example.com',
@@ -64,7 +77,7 @@ import {
  *
  *
  * ## Email templates
  * ## Email templates
  *
  *
- * In the example above, the plugin has been configured to look in `<app-root>/vendure/email/templates`
+ * In the example above, the plugin has been configured to look in `<app-root>/static/email/templates`
  * for the email template files. If you used `\@vendure/create` to create your application, the templates will have
  * for the email template files. If you used `\@vendure/create` to create your application, the templates will have
  * been copied to that location during setup.
  * been copied to that location during setup.
  *
  *