feat(plugin-form-builder): pass beforeChange params into beforeEmail hook and add types to it (#7626)

Form Builder Plugin BeforeEmail hook now takes a generic for your
generated types and it has the full hook params available to it.

```ts
import type { BeforeEmail } from '@payloadcms/plugin-form-builder'
// Your generated FormSubmission type
import type {FormSubmission} from '@payload-types'

// Pass it through and 'data' or 'originalDoc' will now be typed
const beforeEmail: BeforeEmail<FormSubmission> = (emailsToSend, beforeChangeParams) => {
  // modify the emails in any way before they are sent
  return emails.map((email) => ({
    ...email,
    html: email.html, // transform the html in any way you'd like (maybe wrap it in an html template?)
  }))
}
```
This commit is contained in:
Paul
2024-08-12 12:22:52 -06:00
committed by GitHub
parent a063b81460
commit 78dd6a2d5b
4 changed files with 48 additions and 12 deletions

View File

@@ -109,7 +109,7 @@ The `beforeEmail` property is a [beforeChange](<[beforeChange](https://payloadcm
// payload.config.ts // payload.config.ts
formBuilder({ formBuilder({
// ... // ...
beforeEmail: (emailsToSend) => { beforeEmail: (emailsToSend, beforeChangeParams) => {
// modify the emails in any way before they are sent // modify the emails in any way before they are sent
return emails.map((email) => ({ return emails.map((email) => ({
...email, ...email,
@@ -119,6 +119,23 @@ formBuilder({
}) })
``` ```
For full types with `beforeChangeParams`, you can import the types from the plugin:
```ts
import type { BeforeEmail } from '@payloadcms/plugin-form-builder'
// Your generated FormSubmission type
import type {FormSubmission} from '@payload-types'
// Pass it through and 'data' or 'originalDoc' will now be typed
const beforeEmail: BeforeEmail<FormSubmission> = (emailsToSend, beforeChangeParams) => {
// modify the emails in any way before they are sent
return emails.map((email) => ({
...email,
html: email.html, // transform the html in any way you'd like (maybe wrap it in an html template?)
}))
}
```
### `formOverrides` ### `formOverrides`
Override anything on the `forms` collection by sending a [Payload Collection Config](https://payloadcms.com/docs/configuration/collections) to the `formOverrides` property. Override anything on the `forms` collection by sending a [Payload Collection Config](https://payloadcms.com/docs/configuration/collections) to the `formOverrides` property.

View File

@@ -1,20 +1,24 @@
import type { CollectionBeforeChangeHook } from 'payload'
import type { Email, FormBuilderPluginConfig, FormattedEmail } from '../../../types.js' import type { Email, FormBuilderPluginConfig, FormattedEmail } from '../../../types.js'
import { serializeLexical } from '../../../utilities/lexical/serializeLexical.js' import { serializeLexical } from '../../../utilities/lexical/serializeLexical.js'
import { replaceDoubleCurlys } from '../../../utilities/replaceDoubleCurlys.js' import { replaceDoubleCurlys } from '../../../utilities/replaceDoubleCurlys.js'
import { serializeSlate } from '../../../utilities/slate/serializeSlate.js' import { serializeSlate } from '../../../utilities/slate/serializeSlate.js'
type BeforeChangeParams = Parameters<CollectionBeforeChangeHook>[0]
export const sendEmail = async ( export const sendEmail = async (
beforeChangeData: any, beforeChangeParameters: BeforeChangeParams,
formConfig: FormBuilderPluginConfig, formConfig: FormBuilderPluginConfig,
): Promise<any> => { ): Promise<BeforeChangeParams['data']> => {
const { data, operation, req } = beforeChangeData const { data, operation, req } = beforeChangeParameters
if (operation === 'create') { if (operation === 'create') {
const { const {
data: { id: formSubmissionID }, data: { id: formSubmissionID },
req: { locale, payload }, req: { locale, payload },
} = beforeChangeData } = beforeChangeParameters
const { form: formID, submissionData } = data || {} const { form: formID, submissionData } = data || {}
@@ -28,7 +32,7 @@ export const sendEmail = async (
req, req,
}) })
const { emails } = form const emails = form.emails as Email[]
if (emails && emails.length) { if (emails && emails.length) {
const formattedEmails: FormattedEmail[] = await Promise.all( const formattedEmails: FormattedEmail[] = await Promise.all(
@@ -70,11 +74,9 @@ export const sendEmail = async (
let emailsToSend = formattedEmails let emailsToSend = formattedEmails
if (typeof beforeEmail === 'function') { if (typeof beforeEmail === 'function') {
emailsToSend = await beforeEmail(formattedEmails) emailsToSend = await beforeEmail(formattedEmails, beforeChangeParameters)
} }
// const log = emailsToSend.map(({ html, ...rest }) => ({ ...rest }))
await Promise.all( await Promise.all(
emailsToSend.map(async (email) => { emailsToSend.map(async (email) => {
const { to } = email const { to } = email

View File

@@ -1,4 +1,10 @@
import type { Block, CollectionConfig, Field } from 'payload' import type {
Block,
CollectionBeforeChangeHook,
CollectionConfig,
Field,
TypeWithID,
} from 'payload'
export interface BlockConfig { export interface BlockConfig {
block: Block block: Block
@@ -37,7 +43,11 @@ export interface FieldsConfig {
textarea?: FieldConfig | boolean textarea?: FieldConfig | boolean
} }
export type BeforeEmail = (emails: FormattedEmail[]) => FormattedEmail[] | Promise<FormattedEmail[]> type BeforeChangeParams<T extends TypeWithID = any> = Parameters<CollectionBeforeChangeHook<T>>[0]
export type BeforeEmail<T extends TypeWithID = any> = (
emails: FormattedEmail[],
beforeChangeParams: BeforeChangeParams<T>,
) => FormattedEmail[] | Promise<FormattedEmail[]>
export type HandlePayment = (data: any) => void export type HandlePayment = (data: any) => void
export type FieldsOverride = (args: { defaultFields: Field[] }) => Field[] export type FieldsOverride = (args: { defaultFields: Field[] }) => Field[]

View File

@@ -2,11 +2,14 @@ import { fileURLToPath } from 'node:url'
import path from 'path' import path from 'path'
const filename = fileURLToPath(import.meta.url) const filename = fileURLToPath(import.meta.url)
const dirname = path.dirname(filename) const dirname = path.dirname(filename)
import type { BeforeEmail } from '@payloadcms/plugin-form-builder/types'
import type { Block } from 'payload' import type { Block } from 'payload'
import { formBuilderPlugin, fields as formFields } from '@payloadcms/plugin-form-builder' import { formBuilderPlugin, fields as formFields } from '@payloadcms/plugin-form-builder'
import { slateEditor } from '@payloadcms/richtext-slate' import { slateEditor } from '@payloadcms/richtext-slate'
import type { FormSubmission } from './payload-types.js'
import { buildConfigWithDefaults } from '../buildConfigWithDefaults.js' import { buildConfigWithDefaults } from '../buildConfigWithDefaults.js'
import { devUser } from '../credentials.js' import { devUser } from '../credentials.js'
import { Pages } from './collections/Pages.js' import { Pages } from './collections/Pages.js'
@@ -27,6 +30,10 @@ const colorField: Block = {
}, },
} }
const beforeEmail: BeforeEmail<FormSubmission> = (emails, { req: { payload }, originalDoc }) => {
return emails
}
export default buildConfigWithDefaults({ export default buildConfigWithDefaults({
collections: [Pages, Users], collections: [Pages, Users],
editor: slateEditor({}), editor: slateEditor({}),
@@ -49,7 +56,6 @@ export default buildConfigWithDefaults({
plugins: [ plugins: [
formBuilderPlugin({ formBuilderPlugin({
// handlePayment: handleFormPayments, // handlePayment: handleFormPayments,
// beforeEmail: prepareFormEmails,
fields: { fields: {
colorField, colorField,
payment: true, payment: true,
@@ -72,6 +78,7 @@ export default buildConfigWithDefaults({
// }, // },
// }, // },
}, },
beforeEmail,
formOverrides: { formOverrides: {
// labels: { // labels: {
// singular: 'Contact Form', // singular: 'Contact Form',