@mobilizehub/payload-plugin 0.3.2 → 0.4.0

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
@@ -11,6 +11,7 @@ A comprehensive email advocacy and contact management plugin for [Payload CMS](h
11
11
 
12
12
  - Contact database with tag-based segmentation and opt-in management
13
13
  - Email broadcast campaigns with draft-to-sent workflow and audience targeting
14
+ - Forms and form submissions for collecting and managing user responses
14
15
  - Background task processing for scalable email delivery
15
16
  - Webhook integration for delivery status tracking (delivered, bounced, opened, clicked)
16
17
  - Secure unsubscribe tokens with HMAC-SHA256 signing
@@ -99,6 +99,20 @@ import { authenticated } from '../../access/authenticated.js';
99
99
  }
100
100
  ],
101
101
  label: 'Location'
102
+ },
103
+ {
104
+ fields: [
105
+ {
106
+ name: 'formSubmissions',
107
+ type: 'join',
108
+ admin: {
109
+ description: 'Form submissions made by this contact'
110
+ },
111
+ collection: 'formSubmissions',
112
+ on: 'contact'
113
+ }
114
+ ],
115
+ label: 'Submissions'
102
116
  }
103
117
  ]
104
118
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/collections/contacts/generateContactsCollection.ts"],"sourcesContent":["import type { CollectionConfig, Field } from 'payload'\n\nimport iso from 'i18n-iso-countries'\n\nimport type { MobilizehubPluginConfig } from '../../types/index.js'\n\nimport { authenticated } from '../../access/authenticated.js'\n\n/**\n * Generates country options for the country select field.\n */\nconst countryOptions = Object.entries(iso.getNames('en', { select: 'official' })).map(\n ([code, name]) => ({\n label: name,\n value: code,\n }),\n)\n\n/**\n * Generates the contacts collection configuration.\n * @param contactsConfig\n * @returns CollectionConfig\n *\n * @example\n * ```ts\n * import { generateContactsCollection } from 'path/to/generateContactsCollection';\n *\n * const contactsCollection = generateContactsCollection({\n * contactsOverrides: {\n * slug: 'my-contacts',\n * admin: {\n * useAsTitle: 'firstName',\n * },\n * },\n * });\n * ```\n */\nexport const generateContactsCollection = (\n contactsConfig: Pick<MobilizehubPluginConfig, 'contactsOverrides'>,\n): CollectionConfig => {\n const defaultFields: Field[] = [\n {\n name: 'tags',\n type: 'relationship',\n admin: {\n position: 'sidebar',\n },\n hasMany: true,\n relationTo: 'tags',\n },\n {\n type: 'tabs',\n tabs: [\n {\n fields: [\n {\n name: 'email',\n type: 'email',\n required: true,\n },\n {\n name: 'emailOptIn',\n type: 'checkbox',\n defaultValue: false,\n label: 'Receive emails',\n },\n {\n name: 'firstName',\n type: 'text',\n },\n {\n name: 'lastName',\n type: 'text',\n },\n {\n name: 'mobileNumber',\n type: 'text',\n },\n {\n name: 'mobileOptIn',\n type: 'checkbox',\n defaultValue: false,\n label: 'Receive sms',\n },\n ],\n label: 'Details',\n },\n {\n fields: [\n {\n name: 'address',\n type: 'text',\n },\n {\n name: 'city',\n type: 'text',\n },\n {\n name: 'state',\n type: 'text',\n },\n {\n name: 'zip',\n type: 'text',\n },\n {\n name: 'country',\n type: 'select',\n options: countryOptions,\n },\n ],\n label: 'Location',\n },\n /**\n * @todo Enable form submissions relationship when form submissions collection is available.\n */\n // {\n // fields: [\n // {\n // name: 'formSubmissions',\n // type: 'join',\n // admin: {\n // description: 'Form submissions made by this contact',\n // },\n // collection: 'formSubmissions',\n // on: 'contact',\n // },\n // ],\n // label: 'Submissions',\n // },\n /**\n * @todo Enable transactions relationship when transactions collection is available.\n */\n // {\n // fields: [\n // {\n // name: 'transactions',\n // type: 'join',\n // admin: {\n // description: 'Transactions made by this contact',\n // },\n // collection: 'transactions',\n // on: 'contact',\n // },\n // ],\n // label: 'Transactions',\n // },\n ],\n },\n ]\n\n const config: CollectionConfig = {\n ...(contactsConfig?.contactsOverrides || {}),\n slug: contactsConfig.contactsOverrides?.slug || 'contacts',\n access: {\n read: authenticated,\n ...(contactsConfig?.contactsOverrides?.access || {}),\n },\n admin: {\n useAsTitle: contactsConfig?.contactsOverrides?.admin?.useAsTitle || 'email',\n ...(contactsConfig?.contactsOverrides?.admin || {}),\n },\n fields: contactsConfig.contactsOverrides?.fields\n ? contactsConfig.contactsOverrides.fields({ defaultFields })\n : defaultFields,\n }\n return config\n}\n"],"names":["iso","authenticated","countryOptions","Object","entries","getNames","select","map","code","name","label","value","generateContactsCollection","contactsConfig","defaultFields","type","admin","position","hasMany","relationTo","tabs","fields","required","defaultValue","options","config","contactsOverrides","slug","access","read","useAsTitle"],"mappings":"AAEA,OAAOA,SAAS,qBAAoB;AAIpC,SAASC,aAAa,QAAQ,gCAA+B;AAE7D;;CAEC,GACD,MAAMC,iBAAiBC,OAAOC,OAAO,CAACJ,IAAIK,QAAQ,CAAC,MAAM;IAAEC,QAAQ;AAAW,IAAIC,GAAG,CACnF,CAAC,CAACC,MAAMC,KAAK,GAAM,CAAA;QACjBC,OAAOD;QACPE,OAAOH;IACT,CAAA;AAGF;;;;;;;;;;;;;;;;;;CAkBC,GACD,OAAO,MAAMI,6BAA6B,CACxCC;IAEA,MAAMC,gBAAyB;QAC7B;YACEL,MAAM;YACNM,MAAM;YACNC,OAAO;gBACLC,UAAU;YACZ;YACAC,SAAS;YACTC,YAAY;QACd;QACA;YACEJ,MAAM;YACNK,MAAM;gBACJ;oBACEC,QAAQ;wBACN;4BACEZ,MAAM;4BACNM,MAAM;4BACNO,UAAU;wBACZ;wBACA;4BACEb,MAAM;4BACNM,MAAM;4BACNQ,cAAc;4BACdb,OAAO;wBACT;wBACA;4BACED,MAAM;4BACNM,MAAM;wBACR;wBACA;4BACEN,MAAM;4BACNM,MAAM;wBACR;wBACA;4BACEN,MAAM;4BACNM,MAAM;wBACR;wBACA;4BACEN,MAAM;4BACNM,MAAM;4BACNQ,cAAc;4BACdb,OAAO;wBACT;qBACD;oBACDA,OAAO;gBACT;gBACA;oBACEW,QAAQ;wBACN;4BACEZ,MAAM;4BACNM,MAAM;wBACR;wBACA;4BACEN,MAAM;4BACNM,MAAM;wBACR;wBACA;4BACEN,MAAM;4BACNM,MAAM;wBACR;wBACA;4BACEN,MAAM;4BACNM,MAAM;wBACR;wBACA;4BACEN,MAAM;4BACNM,MAAM;4BACNS,SAAStB;wBACX;qBACD;oBACDQ,OAAO;gBACT;aAmCD;QACH;KACD;IAED,MAAMe,SAA2B;QAC/B,GAAIZ,gBAAgBa,qBAAqB,CAAC,CAAC;QAC3CC,MAAMd,eAAea,iBAAiB,EAAEC,QAAQ;QAChDC,QAAQ;YACNC,MAAM5B;YACN,GAAIY,gBAAgBa,mBAAmBE,UAAU,CAAC,CAAC;QACrD;QACAZ,OAAO;YACLc,YAAYjB,gBAAgBa,mBAAmBV,OAAOc,cAAc;YACpE,GAAIjB,gBAAgBa,mBAAmBV,SAAS,CAAC,CAAC;QACpD;QACAK,QAAQR,eAAea,iBAAiB,EAAEL,SACtCR,eAAea,iBAAiB,CAACL,MAAM,CAAC;YAAEP;QAAc,KACxDA;IACN;IACA,OAAOW;AACT,EAAC"}
1
+ {"version":3,"sources":["../../../src/collections/contacts/generateContactsCollection.ts"],"sourcesContent":["import type { CollectionConfig, Field } from 'payload'\n\nimport iso from 'i18n-iso-countries'\n\nimport type { MobilizehubPluginConfig } from '../../types/index.js'\n\nimport { authenticated } from '../../access/authenticated.js'\n\n/**\n * Generates country options for the country select field.\n */\nconst countryOptions = Object.entries(iso.getNames('en', { select: 'official' })).map(\n ([code, name]) => ({\n label: name,\n value: code,\n }),\n)\n\n/**\n * Generates the contacts collection configuration.\n * @param contactsConfig\n * @returns CollectionConfig\n *\n * @example\n * ```ts\n * import { generateContactsCollection } from 'path/to/generateContactsCollection';\n *\n * const contactsCollection = generateContactsCollection({\n * contactsOverrides: {\n * slug: 'my-contacts',\n * admin: {\n * useAsTitle: 'firstName',\n * },\n * },\n * });\n * ```\n */\nexport const generateContactsCollection = (\n contactsConfig: Pick<MobilizehubPluginConfig, 'contactsOverrides'>,\n): CollectionConfig => {\n const defaultFields: Field[] = [\n {\n name: 'tags',\n type: 'relationship',\n admin: {\n position: 'sidebar',\n },\n hasMany: true,\n relationTo: 'tags',\n },\n {\n type: 'tabs',\n tabs: [\n {\n fields: [\n {\n name: 'email',\n type: 'email',\n required: true,\n },\n {\n name: 'emailOptIn',\n type: 'checkbox',\n defaultValue: false,\n label: 'Receive emails',\n },\n {\n name: 'firstName',\n type: 'text',\n },\n {\n name: 'lastName',\n type: 'text',\n },\n {\n name: 'mobileNumber',\n type: 'text',\n },\n {\n name: 'mobileOptIn',\n type: 'checkbox',\n defaultValue: false,\n label: 'Receive sms',\n },\n ],\n label: 'Details',\n },\n {\n fields: [\n {\n name: 'address',\n type: 'text',\n },\n {\n name: 'city',\n type: 'text',\n },\n {\n name: 'state',\n type: 'text',\n },\n {\n name: 'zip',\n type: 'text',\n },\n {\n name: 'country',\n type: 'select',\n options: countryOptions,\n },\n ],\n label: 'Location',\n },\n {\n fields: [\n {\n name: 'formSubmissions',\n type: 'join',\n admin: {\n description: 'Form submissions made by this contact',\n },\n collection: 'formSubmissions',\n on: 'contact',\n },\n ],\n label: 'Submissions',\n },\n /**\n * @todo Enable transactions relationship when transactions collection is available.\n */\n // {\n // fields: [\n // {\n // name: 'transactions',\n // type: 'join',\n // admin: {\n // description: 'Transactions made by this contact',\n // },\n // collection: 'transactions',\n // on: 'contact',\n // },\n // ],\n // label: 'Transactions',\n // },\n ],\n },\n ]\n\n const config: CollectionConfig = {\n ...(contactsConfig?.contactsOverrides || {}),\n slug: contactsConfig.contactsOverrides?.slug || 'contacts',\n access: {\n read: authenticated,\n ...(contactsConfig?.contactsOverrides?.access || {}),\n },\n admin: {\n useAsTitle: contactsConfig?.contactsOverrides?.admin?.useAsTitle || 'email',\n ...(contactsConfig?.contactsOverrides?.admin || {}),\n },\n fields: contactsConfig.contactsOverrides?.fields\n ? contactsConfig.contactsOverrides.fields({ defaultFields })\n : defaultFields,\n }\n return config\n}\n"],"names":["iso","authenticated","countryOptions","Object","entries","getNames","select","map","code","name","label","value","generateContactsCollection","contactsConfig","defaultFields","type","admin","position","hasMany","relationTo","tabs","fields","required","defaultValue","options","description","collection","on","config","contactsOverrides","slug","access","read","useAsTitle"],"mappings":"AAEA,OAAOA,SAAS,qBAAoB;AAIpC,SAASC,aAAa,QAAQ,gCAA+B;AAE7D;;CAEC,GACD,MAAMC,iBAAiBC,OAAOC,OAAO,CAACJ,IAAIK,QAAQ,CAAC,MAAM;IAAEC,QAAQ;AAAW,IAAIC,GAAG,CACnF,CAAC,CAACC,MAAMC,KAAK,GAAM,CAAA;QACjBC,OAAOD;QACPE,OAAOH;IACT,CAAA;AAGF;;;;;;;;;;;;;;;;;;CAkBC,GACD,OAAO,MAAMI,6BAA6B,CACxCC;IAEA,MAAMC,gBAAyB;QAC7B;YACEL,MAAM;YACNM,MAAM;YACNC,OAAO;gBACLC,UAAU;YACZ;YACAC,SAAS;YACTC,YAAY;QACd;QACA;YACEJ,MAAM;YACNK,MAAM;gBACJ;oBACEC,QAAQ;wBACN;4BACEZ,MAAM;4BACNM,MAAM;4BACNO,UAAU;wBACZ;wBACA;4BACEb,MAAM;4BACNM,MAAM;4BACNQ,cAAc;4BACdb,OAAO;wBACT;wBACA;4BACED,MAAM;4BACNM,MAAM;wBACR;wBACA;4BACEN,MAAM;4BACNM,MAAM;wBACR;wBACA;4BACEN,MAAM;4BACNM,MAAM;wBACR;wBACA;4BACEN,MAAM;4BACNM,MAAM;4BACNQ,cAAc;4BACdb,OAAO;wBACT;qBACD;oBACDA,OAAO;gBACT;gBACA;oBACEW,QAAQ;wBACN;4BACEZ,MAAM;4BACNM,MAAM;wBACR;wBACA;4BACEN,MAAM;4BACNM,MAAM;wBACR;wBACA;4BACEN,MAAM;4BACNM,MAAM;wBACR;wBACA;4BACEN,MAAM;4BACNM,MAAM;wBACR;wBACA;4BACEN,MAAM;4BACNM,MAAM;4BACNS,SAAStB;wBACX;qBACD;oBACDQ,OAAO;gBACT;gBACA;oBACEW,QAAQ;wBACN;4BACEZ,MAAM;4BACNM,MAAM;4BACNC,OAAO;gCACLS,aAAa;4BACf;4BACAC,YAAY;4BACZC,IAAI;wBACN;qBACD;oBACDjB,OAAO;gBACT;aAkBD;QACH;KACD;IAED,MAAMkB,SAA2B;QAC/B,GAAIf,gBAAgBgB,qBAAqB,CAAC,CAAC;QAC3CC,MAAMjB,eAAegB,iBAAiB,EAAEC,QAAQ;QAChDC,QAAQ;YACNC,MAAM/B;YACN,GAAIY,gBAAgBgB,mBAAmBE,UAAU,CAAC,CAAC;QACrD;QACAf,OAAO;YACLiB,YAAYpB,gBAAgBgB,mBAAmBb,OAAOiB,cAAc;YACpE,GAAIpB,gBAAgBgB,mBAAmBb,SAAS,CAAC,CAAC;QACpD;QACAK,QAAQR,eAAegB,iBAAiB,EAAER,SACtCR,eAAegB,iBAAiB,CAACR,MAAM,CAAC;YAAEP;QAAc,KACxDA;IACN;IACA,OAAOc;AACT,EAAC"}
@@ -0,0 +1,3 @@
1
+ import type { CollectionConfig } from 'payload';
2
+ import type { MobilizehubPluginConfig } from '../../types/index.js';
3
+ export declare const generateFormSubmissionsCollection: (formSubmissionsConfig: MobilizehubPluginConfig) => CollectionConfig;
@@ -0,0 +1,63 @@
1
+ import { authenticated } from '../../access/authenticated.js';
2
+ export const generateFormSubmissionsCollection = (formSubmissionsConfig)=>{
3
+ const defaultFields = [
4
+ {
5
+ name: 'form',
6
+ type: 'relationship',
7
+ admin: {
8
+ position: 'sidebar',
9
+ readOnly: true
10
+ },
11
+ relationTo: 'forms',
12
+ required: true
13
+ },
14
+ {
15
+ name: 'contact',
16
+ type: 'relationship',
17
+ admin: {
18
+ position: 'sidebar',
19
+ readOnly: true
20
+ },
21
+ relationTo: 'contacts'
22
+ },
23
+ {
24
+ name: 'createdAt',
25
+ type: 'date',
26
+ admin: {
27
+ position: 'sidebar',
28
+ readOnly: true
29
+ }
30
+ },
31
+ {
32
+ name: 'data',
33
+ type: 'json',
34
+ label: 'Data'
35
+ }
36
+ ];
37
+ const config = {
38
+ ...formSubmissionsConfig.formSubmissionsOverrides = {},
39
+ slug: formSubmissionsConfig.formSubmissionsOverrides?.slug || 'formSubmissions',
40
+ access: {
41
+ create: ()=>false,
42
+ read: authenticated,
43
+ update: ()=>false,
44
+ ...formSubmissionsConfig.formSubmissionsOverrides?.access || {}
45
+ },
46
+ admin: {
47
+ ...formSubmissionsConfig.formSubmissionsOverrides?.admin || {},
48
+ hidden: formSubmissionsConfig.formSubmissionsOverrides?.admin?.hidden || true
49
+ },
50
+ fields: formSubmissionsConfig.formSubmissionsOverrides?.fields ? formSubmissionsConfig.formSubmissionsOverrides.fields({
51
+ defaultFields
52
+ }) : defaultFields,
53
+ hooks: {
54
+ ...formSubmissionsConfig.formSubmissionsOverrides?.hooks || {},
55
+ afterChange: [
56
+ ...formSubmissionsConfig.formSubmissionsOverrides?.hooks?.afterChange || []
57
+ ]
58
+ }
59
+ };
60
+ return config;
61
+ };
62
+
63
+ //# sourceMappingURL=generateFormSubmissionsCollection.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/collections/form-submissions/generateFormSubmissionsCollection.ts"],"sourcesContent":["import type { CollectionConfig, Field } from 'payload'\n\nimport type { MobilizehubPluginConfig } from '../../types/index.js'\n\nimport { authenticated } from '../../access/authenticated.js'\n\nexport const generateFormSubmissionsCollection = (\n formSubmissionsConfig: MobilizehubPluginConfig,\n) => {\n const defaultFields: Field[] = [\n {\n name: 'form',\n type: 'relationship',\n admin: {\n position: 'sidebar',\n readOnly: true,\n },\n relationTo: 'forms',\n required: true,\n },\n {\n name: 'contact',\n type: 'relationship',\n admin: {\n position: 'sidebar',\n readOnly: true,\n },\n relationTo: 'contacts',\n },\n {\n name: 'createdAt',\n type: 'date',\n admin: {\n position: 'sidebar',\n readOnly: true,\n },\n },\n {\n name: 'data',\n type: 'json',\n label: 'Data',\n },\n ]\n\n const config: CollectionConfig = {\n ...(formSubmissionsConfig.formSubmissionsOverrides = {}),\n slug: formSubmissionsConfig.formSubmissionsOverrides?.slug || 'formSubmissions',\n access: {\n create: () => false,\n read: authenticated,\n update: () => false,\n ...(formSubmissionsConfig.formSubmissionsOverrides?.access || {}),\n },\n admin: {\n ...(formSubmissionsConfig.formSubmissionsOverrides?.admin || {}),\n hidden: formSubmissionsConfig.formSubmissionsOverrides?.admin?.hidden || true,\n },\n fields: formSubmissionsConfig.formSubmissionsOverrides?.fields\n ? formSubmissionsConfig.formSubmissionsOverrides.fields({ defaultFields })\n : defaultFields,\n hooks: {\n ...(formSubmissionsConfig.formSubmissionsOverrides?.hooks || {}),\n afterChange: [...(formSubmissionsConfig.formSubmissionsOverrides?.hooks?.afterChange || [])],\n },\n }\n\n return config\n}\n"],"names":["authenticated","generateFormSubmissionsCollection","formSubmissionsConfig","defaultFields","name","type","admin","position","readOnly","relationTo","required","label","config","formSubmissionsOverrides","slug","access","create","read","update","hidden","fields","hooks","afterChange"],"mappings":"AAIA,SAASA,aAAa,QAAQ,gCAA+B;AAE7D,OAAO,MAAMC,oCAAoC,CAC/CC;IAEA,MAAMC,gBAAyB;QAC7B;YACEC,MAAM;YACNC,MAAM;YACNC,OAAO;gBACLC,UAAU;gBACVC,UAAU;YACZ;YACAC,YAAY;YACZC,UAAU;QACZ;QACA;YACEN,MAAM;YACNC,MAAM;YACNC,OAAO;gBACLC,UAAU;gBACVC,UAAU;YACZ;YACAC,YAAY;QACd;QACA;YACEL,MAAM;YACNC,MAAM;YACNC,OAAO;gBACLC,UAAU;gBACVC,UAAU;YACZ;QACF;QACA;YACEJ,MAAM;YACNC,MAAM;YACNM,OAAO;QACT;KACD;IAED,MAAMC,SAA2B;QAC/B,GAAIV,sBAAsBW,wBAAwB,GAAG,CAAC,CAAC;QACvDC,MAAMZ,sBAAsBW,wBAAwB,EAAEC,QAAQ;QAC9DC,QAAQ;YACNC,QAAQ,IAAM;YACdC,MAAMjB;YACNkB,QAAQ,IAAM;YACd,GAAIhB,sBAAsBW,wBAAwB,EAAEE,UAAU,CAAC,CAAC;QAClE;QACAT,OAAO;YACL,GAAIJ,sBAAsBW,wBAAwB,EAAEP,SAAS,CAAC,CAAC;YAC/Da,QAAQjB,sBAAsBW,wBAAwB,EAAEP,OAAOa,UAAU;QAC3E;QACAC,QAAQlB,sBAAsBW,wBAAwB,EAAEO,SACpDlB,sBAAsBW,wBAAwB,CAACO,MAAM,CAAC;YAAEjB;QAAc,KACtEA;QACJkB,OAAO;YACL,GAAInB,sBAAsBW,wBAAwB,EAAEQ,SAAS,CAAC,CAAC;YAC/DC,aAAa;mBAAKpB,sBAAsBW,wBAAwB,EAAEQ,OAAOC,eAAe,EAAE;aAAE;QAC9F;IACF;IAEA,OAAOV;AACT,EAAC"}
@@ -0,0 +1,3 @@
1
+ import type { CollectionConfig } from 'payload';
2
+ import type { MobilizehubPluginConfig } from '../../types/index.js';
3
+ export declare const generateFormsCollection: (formsConfig: MobilizehubPluginConfig) => CollectionConfig;
@@ -0,0 +1,226 @@
1
+ import { createContactFieldsConfig } from '../../fields/contact-fields.js';
2
+ import { createNameField } from '../../fields/name.js';
3
+ import { createPublishedAtField } from '../../fields/publishedAt.js';
4
+ import { createSlugField } from '../../fields/slug.js';
5
+ import { createStatusField } from '../../fields/status.js';
6
+ export const generateFormsCollection = (formsConfig)=>{
7
+ const defaultFields = [
8
+ createStatusField(),
9
+ {
10
+ type: 'tabs',
11
+ tabs: [
12
+ {
13
+ fields: [
14
+ createNameField(),
15
+ createSlugField(),
16
+ createPublishedAtField()
17
+ ],
18
+ label: 'Settings'
19
+ },
20
+ {
21
+ fields: [
22
+ {
23
+ name: 'headline',
24
+ type: 'text',
25
+ label: 'Headline'
26
+ },
27
+ {
28
+ name: 'content',
29
+ type: 'richText',
30
+ label: 'Content'
31
+ }
32
+ ],
33
+ label: 'Content'
34
+ },
35
+ {
36
+ fields: [
37
+ {
38
+ name: 'legend',
39
+ type: 'text',
40
+ localized: true
41
+ },
42
+ createContactFieldsConfig(),
43
+ {
44
+ name: 'submitButtonLabel',
45
+ type: 'text',
46
+ localized: true
47
+ },
48
+ {
49
+ name: 'confirmationType',
50
+ type: 'radio',
51
+ admin: {
52
+ description: 'Choose whether to display an on-page message or redirect to a different page after they submit the form.',
53
+ layout: 'horizontal'
54
+ },
55
+ defaultValue: 'message',
56
+ options: [
57
+ {
58
+ label: 'Message',
59
+ value: 'message'
60
+ },
61
+ {
62
+ label: 'Redirect',
63
+ value: 'redirect'
64
+ }
65
+ ]
66
+ },
67
+ {
68
+ name: 'confirmationMessage',
69
+ type: 'richText',
70
+ admin: {
71
+ condition: (_, siblingData)=>siblingData?.confirmationType === 'message'
72
+ },
73
+ localized: true
74
+ },
75
+ {
76
+ name: 'type',
77
+ type: 'radio',
78
+ admin: {
79
+ condition: (_, siblingData)=>siblingData?.confirmationType === 'redirect',
80
+ layout: 'horizontal'
81
+ },
82
+ defaultValue: 'reference',
83
+ options: [
84
+ {
85
+ label: 'Internal link',
86
+ value: 'reference'
87
+ },
88
+ {
89
+ label: 'Custom URL',
90
+ value: 'custom'
91
+ }
92
+ ]
93
+ },
94
+ {
95
+ name: 'reference',
96
+ type: 'relationship',
97
+ admin: {
98
+ condition: (_, siblingData)=>siblingData?.confirmationType === 'redirect' && siblingData?.type === 'reference'
99
+ },
100
+ label: 'Document to link to',
101
+ maxDepth: 2,
102
+ relationTo: [
103
+ 'pages',
104
+ 'forms'
105
+ ],
106
+ required: true
107
+ },
108
+ {
109
+ name: 'url',
110
+ type: 'text',
111
+ admin: {
112
+ condition: (_, siblingData)=>siblingData?.confirmationType === 'redirect' && siblingData?.type === 'custom'
113
+ },
114
+ label: 'URL to redirect to',
115
+ required: true
116
+ },
117
+ {
118
+ name: 'tags',
119
+ type: 'relationship',
120
+ admin: {
121
+ description: 'Tag all contacts submitted via this form with these tags.'
122
+ },
123
+ hasMany: true,
124
+ relationTo: 'tags'
125
+ },
126
+ {
127
+ name: 'autoresponse',
128
+ type: 'group',
129
+ fields: [
130
+ {
131
+ name: 'enabled',
132
+ type: 'checkbox',
133
+ admin: {
134
+ style: {
135
+ marginTop: '1.5rem'
136
+ }
137
+ },
138
+ defaultValue: false,
139
+ label: 'Automatically send an autoresponse email to the submitter'
140
+ },
141
+ {
142
+ name: 'fromName',
143
+ type: 'text',
144
+ defaultValue: ({ req })=>formsConfig.email(req).defaultFromName || '',
145
+ label: 'Name',
146
+ required: true
147
+ },
148
+ {
149
+ name: 'fromAddress',
150
+ type: 'text',
151
+ admin: {
152
+ description: 'The from address is set in the email configuration.',
153
+ readOnly: true
154
+ },
155
+ defaultValue: ({ req })=>formsConfig.email(req).defaultFromAddress || '',
156
+ label: 'Address',
157
+ required: true
158
+ },
159
+ {
160
+ name: 'replyTo',
161
+ type: 'text',
162
+ localized: true
163
+ },
164
+ {
165
+ name: 'subject',
166
+ type: 'text',
167
+ localized: true
168
+ },
169
+ {
170
+ name: 'previewText',
171
+ type: 'text',
172
+ localized: true
173
+ },
174
+ {
175
+ name: 'content',
176
+ type: 'richText',
177
+ localized: true
178
+ }
179
+ ]
180
+ }
181
+ ],
182
+ label: 'Form'
183
+ },
184
+ {
185
+ fields: [
186
+ {
187
+ name: 'formSubmissions',
188
+ type: 'join',
189
+ collection: 'formSubmissions',
190
+ on: 'form'
191
+ }
192
+ ],
193
+ label: 'Submissions'
194
+ }
195
+ ]
196
+ }
197
+ ];
198
+ const config = {
199
+ ...formsConfig.formsOverrides = {},
200
+ slug: formsConfig.formsOverrides?.slug || 'forms',
201
+ access: {
202
+ read: ()=>true,
203
+ ...formsConfig.formsOverrides?.access || {}
204
+ },
205
+ admin: {
206
+ ...formsConfig.formsOverrides?.admin || {},
207
+ defaultColumns: formsConfig.formsOverrides?.admin?.defaultColumns || [
208
+ 'id',
209
+ 'name',
210
+ 'slug',
211
+ 'status'
212
+ ],
213
+ hidden: formsConfig.formsOverrides?.admin?.hidden || false,
214
+ useAsTitle: formsConfig.formsOverrides?.admin?.useAsTitle || 'name'
215
+ },
216
+ fields: formsConfig.formsOverrides?.fields ? formsConfig.formsOverrides.fields({
217
+ defaultFields
218
+ }) : defaultFields,
219
+ hooks: {
220
+ ...formsConfig.formsOverrides?.hooks || {}
221
+ }
222
+ };
223
+ return config;
224
+ };
225
+
226
+ //# sourceMappingURL=generateFormsCollection.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/collections/forms/generateFormsCollection.ts"],"sourcesContent":["import type { CollectionConfig, Field } from 'payload'\n\nimport type { MobilizehubPluginConfig } from '../../types/index.js'\n\nimport { createContactFieldsConfig } from '../../fields/contact-fields.js'\nimport { createNameField } from '../../fields/name.js'\nimport { createPublishedAtField } from '../../fields/publishedAt.js'\nimport { createSlugField } from '../../fields/slug.js'\nimport { createStatusField } from '../../fields/status.js'\n\nexport const generateFormsCollection = (formsConfig: MobilizehubPluginConfig) => {\n const defaultFields: Field[] = [\n createStatusField(),\n {\n type: 'tabs',\n tabs: [\n {\n fields: [createNameField(), createSlugField(), createPublishedAtField()],\n label: 'Settings',\n },\n {\n fields: [\n {\n name: 'headline',\n type: 'text',\n label: 'Headline',\n },\n {\n name: 'content',\n type: 'richText',\n label: 'Content',\n },\n ],\n label: 'Content',\n },\n {\n fields: [\n {\n name: 'legend',\n type: 'text',\n localized: true,\n },\n createContactFieldsConfig(),\n {\n name: 'submitButtonLabel',\n type: 'text',\n localized: true,\n },\n {\n name: 'confirmationType',\n type: 'radio',\n admin: {\n description:\n 'Choose whether to display an on-page message or redirect to a different page after they submit the form.',\n layout: 'horizontal',\n },\n defaultValue: 'message',\n options: [\n {\n label: 'Message',\n value: 'message',\n },\n {\n label: 'Redirect',\n value: 'redirect',\n },\n ],\n },\n {\n name: 'confirmationMessage',\n type: 'richText',\n admin: {\n condition: (_, siblingData) => siblingData?.confirmationType === 'message',\n },\n localized: true,\n },\n {\n name: 'type',\n type: 'radio',\n admin: {\n condition: (_, siblingData) => siblingData?.confirmationType === 'redirect',\n layout: 'horizontal',\n },\n defaultValue: 'reference',\n options: [\n {\n label: 'Internal link',\n value: 'reference',\n },\n {\n label: 'Custom URL',\n value: 'custom',\n },\n ],\n },\n {\n name: 'reference',\n type: 'relationship',\n admin: {\n condition: (_, siblingData) =>\n siblingData?.confirmationType === 'redirect' && siblingData?.type === 'reference',\n },\n label: 'Document to link to',\n maxDepth: 2,\n relationTo: ['pages', 'forms'],\n required: true,\n },\n {\n name: 'url',\n type: 'text',\n admin: {\n condition: (_, siblingData) =>\n siblingData?.confirmationType === 'redirect' && siblingData?.type === 'custom',\n },\n label: 'URL to redirect to',\n required: true,\n },\n {\n name: 'tags',\n type: 'relationship',\n admin: {\n description: 'Tag all contacts submitted via this form with these tags.',\n },\n hasMany: true,\n relationTo: 'tags',\n },\n {\n name: 'autoresponse',\n type: 'group',\n fields: [\n {\n name: 'enabled',\n type: 'checkbox',\n admin: {\n style: {\n marginTop: '1.5rem',\n },\n },\n defaultValue: false,\n label: 'Automatically send an autoresponse email to the submitter',\n },\n {\n name: 'fromName',\n type: 'text',\n defaultValue: ({ req }) => formsConfig.email(req).defaultFromName || '',\n label: 'Name',\n required: true,\n },\n {\n name: 'fromAddress',\n type: 'text',\n admin: {\n description: 'The from address is set in the email configuration.',\n readOnly: true,\n },\n defaultValue: ({ req }) => formsConfig.email(req).defaultFromAddress || '',\n label: 'Address',\n required: true,\n },\n {\n name: 'replyTo',\n type: 'text',\n localized: true,\n },\n {\n name: 'subject',\n type: 'text',\n localized: true,\n },\n {\n name: 'previewText',\n type: 'text',\n localized: true,\n },\n {\n name: 'content',\n type: 'richText',\n localized: true,\n },\n ],\n },\n ],\n label: 'Form',\n },\n {\n fields: [\n {\n name: 'formSubmissions',\n type: 'join',\n collection: 'formSubmissions',\n on: 'form',\n },\n ],\n label: 'Submissions',\n },\n ],\n },\n ]\n\n const config: CollectionConfig = {\n ...(formsConfig.formsOverrides = {}),\n slug: formsConfig.formsOverrides?.slug || 'forms',\n access: {\n read: () => true,\n ...(formsConfig.formsOverrides?.access || {}),\n },\n admin: {\n ...(formsConfig.formsOverrides?.admin || {}),\n defaultColumns: formsConfig.formsOverrides?.admin?.defaultColumns || [\n 'id',\n 'name',\n 'slug',\n 'status',\n ],\n hidden: formsConfig.formsOverrides?.admin?.hidden || false,\n useAsTitle: formsConfig.formsOverrides?.admin?.useAsTitle || 'name',\n },\n fields: formsConfig.formsOverrides?.fields\n ? formsConfig.formsOverrides.fields({ defaultFields })\n : defaultFields,\n hooks: {\n ...(formsConfig.formsOverrides?.hooks || {}),\n },\n }\n\n return config\n}\n"],"names":["createContactFieldsConfig","createNameField","createPublishedAtField","createSlugField","createStatusField","generateFormsCollection","formsConfig","defaultFields","type","tabs","fields","label","name","localized","admin","description","layout","defaultValue","options","value","condition","_","siblingData","confirmationType","maxDepth","relationTo","required","hasMany","style","marginTop","req","email","defaultFromName","readOnly","defaultFromAddress","collection","on","config","formsOverrides","slug","access","read","defaultColumns","hidden","useAsTitle","hooks"],"mappings":"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"}
@@ -0,0 +1,65 @@
1
+ import type { Field } from 'payload';
2
+ /**
3
+ * Definitions for each contact field, including default required status and label.
4
+ */
5
+ export declare const CONTACT_FIELD_DEFINITIONS: readonly [{
6
+ readonly name: "email";
7
+ readonly defaultLabel: "Email";
8
+ readonly defaultRequired: true;
9
+ readonly label: "Email";
10
+ }, {
11
+ readonly name: "emailOptIn";
12
+ readonly defaultLabel: "Receive emails";
13
+ readonly defaultRequired: false;
14
+ readonly label: "Email Opt-In";
15
+ }, {
16
+ readonly name: "firstName";
17
+ readonly defaultLabel: "First Name";
18
+ readonly defaultRequired: false;
19
+ readonly label: "First Name";
20
+ }, {
21
+ readonly name: "lastName";
22
+ readonly defaultLabel: "Last Name";
23
+ readonly defaultRequired: false;
24
+ readonly label: "Last Name";
25
+ }, {
26
+ readonly name: "mobileNumber";
27
+ readonly defaultLabel: "Mobile Number";
28
+ readonly defaultRequired: false;
29
+ readonly label: "Mobile Number";
30
+ }, {
31
+ readonly name: "mobileOptIn";
32
+ readonly defaultLabel: "Receive SMS";
33
+ readonly defaultRequired: false;
34
+ readonly label: "Mobile Opt-In";
35
+ }, {
36
+ readonly name: "address";
37
+ readonly defaultLabel: "Address";
38
+ readonly defaultRequired: false;
39
+ readonly label: "Address";
40
+ }, {
41
+ readonly name: "city";
42
+ readonly defaultLabel: "City";
43
+ readonly defaultRequired: false;
44
+ readonly label: "City";
45
+ }, {
46
+ readonly name: "state";
47
+ readonly defaultLabel: "State";
48
+ readonly defaultRequired: false;
49
+ readonly label: "State";
50
+ }, {
51
+ readonly name: "zip";
52
+ readonly defaultLabel: "Zip Code";
53
+ readonly defaultRequired: false;
54
+ readonly label: "Zip Code";
55
+ }, {
56
+ readonly name: "country";
57
+ readonly defaultLabel: "Country";
58
+ readonly defaultRequired: false;
59
+ readonly label: "Country";
60
+ }];
61
+ /**
62
+ * Creates the contact fields configuration for a Payload CMS collection.
63
+ * Each field can be customized with a label and whether it is required.
64
+ */
65
+ export declare const createContactFieldsConfig: () => Field;
@@ -0,0 +1,122 @@
1
+ /**
2
+ * Definitions for each contact field, including default required status and label.
3
+ */ export const CONTACT_FIELD_DEFINITIONS = [
4
+ {
5
+ name: 'email',
6
+ defaultLabel: 'Email',
7
+ defaultRequired: true,
8
+ label: 'Email'
9
+ },
10
+ {
11
+ name: 'emailOptIn',
12
+ defaultLabel: 'Receive emails',
13
+ defaultRequired: false,
14
+ label: 'Email Opt-In'
15
+ },
16
+ {
17
+ name: 'firstName',
18
+ defaultLabel: 'First Name',
19
+ defaultRequired: false,
20
+ label: 'First Name'
21
+ },
22
+ {
23
+ name: 'lastName',
24
+ defaultLabel: 'Last Name',
25
+ defaultRequired: false,
26
+ label: 'Last Name'
27
+ },
28
+ {
29
+ name: 'mobileNumber',
30
+ defaultLabel: 'Mobile Number',
31
+ defaultRequired: false,
32
+ label: 'Mobile Number'
33
+ },
34
+ {
35
+ name: 'mobileOptIn',
36
+ defaultLabel: 'Receive SMS',
37
+ defaultRequired: false,
38
+ label: 'Mobile Opt-In'
39
+ },
40
+ {
41
+ name: 'address',
42
+ defaultLabel: 'Address',
43
+ defaultRequired: false,
44
+ label: 'Address'
45
+ },
46
+ {
47
+ name: 'city',
48
+ defaultLabel: 'City',
49
+ defaultRequired: false,
50
+ label: 'City'
51
+ },
52
+ {
53
+ name: 'state',
54
+ defaultLabel: 'State',
55
+ defaultRequired: false,
56
+ label: 'State'
57
+ },
58
+ {
59
+ name: 'zip',
60
+ defaultLabel: 'Zip Code',
61
+ defaultRequired: false,
62
+ label: 'Zip Code'
63
+ },
64
+ {
65
+ name: 'country',
66
+ defaultLabel: 'Country',
67
+ defaultRequired: false,
68
+ label: 'Country'
69
+ }
70
+ ];
71
+ /**
72
+ * Creates the contact fields configuration for a Payload CMS collection.
73
+ * Each field can be customized with a label and whether it is required.
74
+ */ export const createContactFieldsConfig = ()=>{
75
+ return {
76
+ name: 'contactFields',
77
+ type: 'blocks',
78
+ admin: {
79
+ description: 'Configure the fields to be included in the contact form.'
80
+ },
81
+ blocks: CONTACT_FIELD_DEFINITIONS.map((def)=>({
82
+ slug: def.name,
83
+ fields: [
84
+ {
85
+ name: 'label',
86
+ type: 'text',
87
+ admin: {
88
+ placeholder: def.label
89
+ },
90
+ defaultValue: def.defaultLabel
91
+ },
92
+ {
93
+ name: 'required',
94
+ type: 'checkbox',
95
+ defaultValue: def.defaultRequired
96
+ }
97
+ ]
98
+ })),
99
+ defaultValue: [
100
+ {
101
+ blockType: 'email',
102
+ label: 'Email',
103
+ required: true
104
+ }
105
+ ],
106
+ filterOptions: ({ siblingData })=>{
107
+ const blocks = siblingData?.contactFields;
108
+ if (!blocks || blocks.length === 0) {
109
+ return CONTACT_FIELD_DEFINITIONS.map((def)=>def.name);
110
+ }
111
+ const usedSlugs = blocks?.map((block)=>block.blockType) || [];
112
+ return CONTACT_FIELD_DEFINITIONS.map((def)=>def.name).filter((slug)=>!usedSlugs.includes(slug));
113
+ },
114
+ label: 'Fields',
115
+ labels: {
116
+ plural: 'Fields',
117
+ singular: 'Field'
118
+ }
119
+ };
120
+ };
121
+
122
+ //# sourceMappingURL=contact-fields.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/fields/contact-fields.ts"],"sourcesContent":["import type { Field } from 'payload'\n\n/**\n * Definitions for each contact field, including default required status and label.\n */\nexport const CONTACT_FIELD_DEFINITIONS = [\n { name: 'email', defaultLabel: 'Email', defaultRequired: true, label: 'Email' },\n {\n name: 'emailOptIn',\n defaultLabel: 'Receive emails',\n defaultRequired: false,\n label: 'Email Opt-In',\n },\n { name: 'firstName', defaultLabel: 'First Name', defaultRequired: false, label: 'First Name' },\n { name: 'lastName', defaultLabel: 'Last Name', defaultRequired: false, label: 'Last Name' },\n {\n name: 'mobileNumber',\n defaultLabel: 'Mobile Number',\n defaultRequired: false,\n label: 'Mobile Number',\n },\n {\n name: 'mobileOptIn',\n defaultLabel: 'Receive SMS',\n defaultRequired: false,\n label: 'Mobile Opt-In',\n },\n { name: 'address', defaultLabel: 'Address', defaultRequired: false, label: 'Address' },\n { name: 'city', defaultLabel: 'City', defaultRequired: false, label: 'City' },\n { name: 'state', defaultLabel: 'State', defaultRequired: false, label: 'State' },\n { name: 'zip', defaultLabel: 'Zip Code', defaultRequired: false, label: 'Zip Code' },\n { name: 'country', defaultLabel: 'Country', defaultRequired: false, label: 'Country' },\n] as const\n\n/**\n * Creates the contact fields configuration for a Payload CMS collection.\n * Each field can be customized with a label and whether it is required.\n */\nexport const createContactFieldsConfig = (): Field => {\n return {\n name: 'contactFields',\n type: 'blocks',\n admin: {\n description: 'Configure the fields to be included in the contact form.',\n },\n blocks: CONTACT_FIELD_DEFINITIONS.map((def) => ({\n slug: def.name,\n fields: [\n {\n name: 'label',\n type: 'text',\n admin: {\n placeholder: def.label,\n },\n defaultValue: def.defaultLabel,\n },\n {\n name: 'required',\n type: 'checkbox',\n defaultValue: def.defaultRequired,\n },\n ],\n })),\n defaultValue: [\n {\n blockType: 'email',\n label: 'Email',\n required: true,\n },\n ],\n filterOptions: ({ siblingData }) => {\n const blocks = (siblingData as any)?.contactFields as { blockType: string }[] | undefined\n if (!blocks || blocks.length === 0) {\n return CONTACT_FIELD_DEFINITIONS.map((def) => def.name)\n }\n const usedSlugs = blocks?.map((block) => block.blockType) || []\n return CONTACT_FIELD_DEFINITIONS.map((def) => def.name).filter(\n (slug) => !usedSlugs.includes(slug),\n )\n },\n label: 'Fields',\n labels: {\n plural: 'Fields',\n singular: 'Field',\n },\n }\n}\n"],"names":["CONTACT_FIELD_DEFINITIONS","name","defaultLabel","defaultRequired","label","createContactFieldsConfig","type","admin","description","blocks","map","def","slug","fields","placeholder","defaultValue","blockType","required","filterOptions","siblingData","contactFields","length","usedSlugs","block","filter","includes","labels","plural","singular"],"mappings":"AAEA;;CAEC,GACD,OAAO,MAAMA,4BAA4B;IACvC;QAAEC,MAAM;QAASC,cAAc;QAASC,iBAAiB;QAAMC,OAAO;IAAQ;IAC9E;QACEH,MAAM;QACNC,cAAc;QACdC,iBAAiB;QACjBC,OAAO;IACT;IACA;QAAEH,MAAM;QAAaC,cAAc;QAAcC,iBAAiB;QAAOC,OAAO;IAAa;IAC7F;QAAEH,MAAM;QAAYC,cAAc;QAAaC,iBAAiB;QAAOC,OAAO;IAAY;IAC1F;QACEH,MAAM;QACNC,cAAc;QACdC,iBAAiB;QACjBC,OAAO;IACT;IACA;QACEH,MAAM;QACNC,cAAc;QACdC,iBAAiB;QACjBC,OAAO;IACT;IACA;QAAEH,MAAM;QAAWC,cAAc;QAAWC,iBAAiB;QAAOC,OAAO;IAAU;IACrF;QAAEH,MAAM;QAAQC,cAAc;QAAQC,iBAAiB;QAAOC,OAAO;IAAO;IAC5E;QAAEH,MAAM;QAASC,cAAc;QAASC,iBAAiB;QAAOC,OAAO;IAAQ;IAC/E;QAAEH,MAAM;QAAOC,cAAc;QAAYC,iBAAiB;QAAOC,OAAO;IAAW;IACnF;QAAEH,MAAM;QAAWC,cAAc;QAAWC,iBAAiB;QAAOC,OAAO;IAAU;CACtF,CAAS;AAEV;;;CAGC,GACD,OAAO,MAAMC,4BAA4B;IACvC,OAAO;QACLJ,MAAM;QACNK,MAAM;QACNC,OAAO;YACLC,aAAa;QACf;QACAC,QAAQT,0BAA0BU,GAAG,CAAC,CAACC,MAAS,CAAA;gBAC9CC,MAAMD,IAAIV,IAAI;gBACdY,QAAQ;oBACN;wBACEZ,MAAM;wBACNK,MAAM;wBACNC,OAAO;4BACLO,aAAaH,IAAIP,KAAK;wBACxB;wBACAW,cAAcJ,IAAIT,YAAY;oBAChC;oBACA;wBACED,MAAM;wBACNK,MAAM;wBACNS,cAAcJ,IAAIR,eAAe;oBACnC;iBACD;YACH,CAAA;QACAY,cAAc;YACZ;gBACEC,WAAW;gBACXZ,OAAO;gBACPa,UAAU;YACZ;SACD;QACDC,eAAe,CAAC,EAAEC,WAAW,EAAE;YAC7B,MAAMV,SAAUU,aAAqBC;YACrC,IAAI,CAACX,UAAUA,OAAOY,MAAM,KAAK,GAAG;gBAClC,OAAOrB,0BAA0BU,GAAG,CAAC,CAACC,MAAQA,IAAIV,IAAI;YACxD;YACA,MAAMqB,YAAYb,QAAQC,IAAI,CAACa,QAAUA,MAAMP,SAAS,KAAK,EAAE;YAC/D,OAAOhB,0BAA0BU,GAAG,CAAC,CAACC,MAAQA,IAAIV,IAAI,EAAEuB,MAAM,CAC5D,CAACZ,OAAS,CAACU,UAAUG,QAAQ,CAACb;QAElC;QACAR,OAAO;QACPsB,QAAQ;YACNC,QAAQ;YACRC,UAAU;QACZ;IACF;AACF,EAAC"}
package/dist/index.js CHANGED
@@ -1,6 +1,8 @@
1
1
  import { generateBroadcastsCollection } from './collections/broadcasts/generateBroadcastsCollection.js';
2
2
  import { generateContactsCollection } from './collections/contacts/generateContactsCollection.js';
3
3
  import { generateEmailsCollection } from './collections/emails/generateEmailsCollection.js';
4
+ import { generateFormSubmissionsCollection } from './collections/form-submissions/generateFormSubmissionsCollection.js';
5
+ import { generateFormsCollection } from './collections/forms/generateFormsCollection.js';
4
6
  import { generatePagesCollection } from './collections/pages/generatePagesCollection.js';
5
7
  import { generateTagsCollection } from './collections/tags/generateTagsCollection.js';
6
8
  import { generateUnsubscribeTokensCollection } from './collections/unsubscribe-tokens/generateUnsubscribeTokens.js';
@@ -11,13 +13,13 @@ import { createSendBroadcastsTask } from './tasks/sendBroadcastsTask.js';
11
13
  import { createSendEmailTask } from './tasks/sendEmailTask.js';
12
14
  export * from './types/index.js';
13
15
  export const mobilizehubPlugin = (pluginOptions)=>(config)=>{
14
- if (pluginOptions.disabled) {
15
- return config;
16
- }
17
16
  if (!config.collections) {
18
17
  config.collections = [];
19
18
  }
20
- config.collections.push(generateTagsCollection(pluginOptions), generateContactsCollection(pluginOptions), generateBroadcastsCollection(pluginOptions), generateEmailsCollection(pluginOptions), generatePagesCollection(pluginOptions), generateUnsubscribeTokensCollection());
19
+ config.collections.push(generateTagsCollection(pluginOptions), generateContactsCollection(pluginOptions), generateBroadcastsCollection(pluginOptions), generateEmailsCollection(pluginOptions), generatePagesCollection(pluginOptions), generateUnsubscribeTokensCollection(), generateFormSubmissionsCollection(pluginOptions), generateFormsCollection(pluginOptions));
20
+ if (pluginOptions.disabled) {
21
+ return config;
22
+ }
21
23
  if (!config.endpoints) {
22
24
  config.endpoints = [];
23
25
  }
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"sourcesContent":["import type { Config, Endpoint, TaskConfig } from 'payload'\n\nimport type { MobilizehubPluginConfig } from './types/index.js'\n\nimport { generateBroadcastsCollection } from './collections/broadcasts/generateBroadcastsCollection.js'\nimport { generateContactsCollection } from './collections/contacts/generateContactsCollection.js'\nimport { generateEmailsCollection } from './collections/emails/generateEmailsCollection.js'\nimport { generatePagesCollection } from './collections/pages/generatePagesCollection.js'\nimport { generateTagsCollection } from './collections/tags/generateTagsCollection.js'\nimport { generateUnsubscribeTokensCollection } from './collections/unsubscribe-tokens/generateUnsubscribeTokens.js'\nimport { sendBroadcastHandler } from './endpoints/sendBroadcastHandler.js'\nimport { sendTestEmailHandler } from './endpoints/sendTestBroadcastHandler.js'\nimport { unsubscribeHandler } from './endpoints/unsubscribeHandler.js'\nimport { createSendBroadcastsTask } from './tasks/sendBroadcastsTask.js'\nimport { createSendEmailTask } from './tasks/sendEmailTask.js'\n\nexport * from './types/index.js'\n\nexport const mobilizehubPlugin =\n (pluginOptions: MobilizehubPluginConfig) =>\n (config: Config): Config => {\n if (pluginOptions.disabled) {\n return config\n }\n\n if (!config.collections) {\n config.collections = []\n }\n\n config.collections.push(\n generateTagsCollection(pluginOptions),\n generateContactsCollection(pluginOptions),\n generateBroadcastsCollection(pluginOptions),\n generateEmailsCollection(pluginOptions),\n generatePagesCollection(pluginOptions),\n generateUnsubscribeTokensCollection(),\n )\n\n if (!config.endpoints) {\n config.endpoints = []\n }\n\n const endpoints: Endpoint[] = [\n {\n handler: sendBroadcastHandler(),\n method: 'post',\n path: '/send-broadcast',\n },\n {\n handler: sendTestEmailHandler(pluginOptions),\n method: 'post',\n path: '/send-test-email',\n },\n {\n handler: unsubscribeHandler(),\n method: 'post',\n path: '/unsubscribe',\n },\n ]\n\n config.endpoints = [...config.endpoints, ...endpoints]\n\n if (!config.jobs) {\n config.jobs = {\n tasks: [],\n }\n }\n\n const tasks: TaskConfig[] = [\n createSendBroadcastsTask(pluginOptions),\n createSendEmailTask(pluginOptions),\n ]\n\n config.jobs.tasks = [...(config.jobs.tasks ?? []), ...tasks]\n\n const incomingOnInit = config.onInit\n\n config.onInit = async (payload) => {\n if (incomingOnInit) {\n await incomingOnInit(payload)\n }\n }\n\n return config\n }\n"],"names":["generateBroadcastsCollection","generateContactsCollection","generateEmailsCollection","generatePagesCollection","generateTagsCollection","generateUnsubscribeTokensCollection","sendBroadcastHandler","sendTestEmailHandler","unsubscribeHandler","createSendBroadcastsTask","createSendEmailTask","mobilizehubPlugin","pluginOptions","config","disabled","collections","push","endpoints","handler","method","path","jobs","tasks","incomingOnInit","onInit","payload"],"mappings":"AAIA,SAASA,4BAA4B,QAAQ,2DAA0D;AACvG,SAASC,0BAA0B,QAAQ,uDAAsD;AACjG,SAASC,wBAAwB,QAAQ,mDAAkD;AAC3F,SAASC,uBAAuB,QAAQ,iDAAgD;AACxF,SAASC,sBAAsB,QAAQ,+CAA8C;AACrF,SAASC,mCAAmC,QAAQ,gEAA+D;AACnH,SAASC,oBAAoB,QAAQ,sCAAqC;AAC1E,SAASC,oBAAoB,QAAQ,0CAAyC;AAC9E,SAASC,kBAAkB,QAAQ,oCAAmC;AACtE,SAASC,wBAAwB,QAAQ,gCAA+B;AACxE,SAASC,mBAAmB,QAAQ,2BAA0B;AAE9D,cAAc,mBAAkB;AAEhC,OAAO,MAAMC,oBACX,CAACC,gBACD,CAACC;QACC,IAAID,cAAcE,QAAQ,EAAE;YAC1B,OAAOD;QACT;QAEA,IAAI,CAACA,OAAOE,WAAW,EAAE;YACvBF,OAAOE,WAAW,GAAG,EAAE;QACzB;QAEAF,OAAOE,WAAW,CAACC,IAAI,CACrBZ,uBAAuBQ,gBACvBX,2BAA2BW,gBAC3BZ,6BAA6BY,gBAC7BV,yBAAyBU,gBACzBT,wBAAwBS,gBACxBP;QAGF,IAAI,CAACQ,OAAOI,SAAS,EAAE;YACrBJ,OAAOI,SAAS,GAAG,EAAE;QACvB;QAEA,MAAMA,YAAwB;YAC5B;gBACEC,SAASZ;gBACTa,QAAQ;gBACRC,MAAM;YACR;YACA;gBACEF,SAASX,qBAAqBK;gBAC9BO,QAAQ;gBACRC,MAAM;YACR;YACA;gBACEF,SAASV;gBACTW,QAAQ;gBACRC,MAAM;YACR;SACD;QAEDP,OAAOI,SAAS,GAAG;eAAIJ,OAAOI,SAAS;eAAKA;SAAU;QAEtD,IAAI,CAACJ,OAAOQ,IAAI,EAAE;YAChBR,OAAOQ,IAAI,GAAG;gBACZC,OAAO,EAAE;YACX;QACF;QAEA,MAAMA,QAAsB;YAC1Bb,yBAAyBG;YACzBF,oBAAoBE;SACrB;QAEDC,OAAOQ,IAAI,CAACC,KAAK,GAAG;eAAKT,OAAOQ,IAAI,CAACC,KAAK,IAAI,EAAE;eAAMA;SAAM;QAE5D,MAAMC,iBAAiBV,OAAOW,MAAM;QAEpCX,OAAOW,MAAM,GAAG,OAAOC;YACrB,IAAIF,gBAAgB;gBAClB,MAAMA,eAAeE;YACvB;QACF;QAEA,OAAOZ;IACT,EAAC"}
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["import type { Config, Endpoint, TaskConfig } from 'payload'\n\nimport type { MobilizehubPluginConfig } from './types/index.js'\n\nimport { generateBroadcastsCollection } from './collections/broadcasts/generateBroadcastsCollection.js'\nimport { generateContactsCollection } from './collections/contacts/generateContactsCollection.js'\nimport { generateEmailsCollection } from './collections/emails/generateEmailsCollection.js'\nimport { generateFormSubmissionsCollection } from './collections/form-submissions/generateFormSubmissionsCollection.js'\nimport { generateFormsCollection } from './collections/forms/generateFormsCollection.js'\nimport { generatePagesCollection } from './collections/pages/generatePagesCollection.js'\nimport { generateTagsCollection } from './collections/tags/generateTagsCollection.js'\nimport { generateUnsubscribeTokensCollection } from './collections/unsubscribe-tokens/generateUnsubscribeTokens.js'\nimport { sendBroadcastHandler } from './endpoints/sendBroadcastHandler.js'\nimport { sendTestEmailHandler } from './endpoints/sendTestBroadcastHandler.js'\nimport { unsubscribeHandler } from './endpoints/unsubscribeHandler.js'\nimport { createSendBroadcastsTask } from './tasks/sendBroadcastsTask.js'\nimport { createSendEmailTask } from './tasks/sendEmailTask.js'\n\nexport * from './types/index.js'\n\nexport const mobilizehubPlugin =\n (pluginOptions: MobilizehubPluginConfig) =>\n (config: Config): Config => {\n if (!config.collections) {\n config.collections = []\n }\n\n config.collections.push(\n generateTagsCollection(pluginOptions),\n generateContactsCollection(pluginOptions),\n generateBroadcastsCollection(pluginOptions),\n generateEmailsCollection(pluginOptions),\n generatePagesCollection(pluginOptions),\n generateUnsubscribeTokensCollection(),\n generateFormSubmissionsCollection(pluginOptions),\n generateFormsCollection(pluginOptions),\n )\n\n if (pluginOptions.disabled) {\n return config\n }\n\n if (!config.endpoints) {\n config.endpoints = []\n }\n\n const endpoints: Endpoint[] = [\n {\n handler: sendBroadcastHandler(),\n method: 'post',\n path: '/send-broadcast',\n },\n {\n handler: sendTestEmailHandler(pluginOptions),\n method: 'post',\n path: '/send-test-email',\n },\n {\n handler: unsubscribeHandler(),\n method: 'post',\n path: '/unsubscribe',\n },\n ]\n\n config.endpoints = [...config.endpoints, ...endpoints]\n\n if (!config.jobs) {\n config.jobs = {\n tasks: [],\n }\n }\n\n const tasks: TaskConfig[] = [\n createSendBroadcastsTask(pluginOptions),\n createSendEmailTask(pluginOptions),\n ]\n\n config.jobs.tasks = [...(config.jobs.tasks ?? []), ...tasks]\n\n const incomingOnInit = config.onInit\n\n config.onInit = async (payload) => {\n if (incomingOnInit) {\n await incomingOnInit(payload)\n }\n }\n\n return config\n }\n"],"names":["generateBroadcastsCollection","generateContactsCollection","generateEmailsCollection","generateFormSubmissionsCollection","generateFormsCollection","generatePagesCollection","generateTagsCollection","generateUnsubscribeTokensCollection","sendBroadcastHandler","sendTestEmailHandler","unsubscribeHandler","createSendBroadcastsTask","createSendEmailTask","mobilizehubPlugin","pluginOptions","config","collections","push","disabled","endpoints","handler","method","path","jobs","tasks","incomingOnInit","onInit","payload"],"mappings":"AAIA,SAASA,4BAA4B,QAAQ,2DAA0D;AACvG,SAASC,0BAA0B,QAAQ,uDAAsD;AACjG,SAASC,wBAAwB,QAAQ,mDAAkD;AAC3F,SAASC,iCAAiC,QAAQ,sEAAqE;AACvH,SAASC,uBAAuB,QAAQ,iDAAgD;AACxF,SAASC,uBAAuB,QAAQ,iDAAgD;AACxF,SAASC,sBAAsB,QAAQ,+CAA8C;AACrF,SAASC,mCAAmC,QAAQ,gEAA+D;AACnH,SAASC,oBAAoB,QAAQ,sCAAqC;AAC1E,SAASC,oBAAoB,QAAQ,0CAAyC;AAC9E,SAASC,kBAAkB,QAAQ,oCAAmC;AACtE,SAASC,wBAAwB,QAAQ,gCAA+B;AACxE,SAASC,mBAAmB,QAAQ,2BAA0B;AAE9D,cAAc,mBAAkB;AAEhC,OAAO,MAAMC,oBACX,CAACC,gBACD,CAACC;QACC,IAAI,CAACA,OAAOC,WAAW,EAAE;YACvBD,OAAOC,WAAW,GAAG,EAAE;QACzB;QAEAD,OAAOC,WAAW,CAACC,IAAI,CACrBX,uBAAuBQ,gBACvBb,2BAA2Ba,gBAC3Bd,6BAA6Bc,gBAC7BZ,yBAAyBY,gBACzBT,wBAAwBS,gBACxBP,uCACAJ,kCAAkCW,gBAClCV,wBAAwBU;QAG1B,IAAIA,cAAcI,QAAQ,EAAE;YAC1B,OAAOH;QACT;QAEA,IAAI,CAACA,OAAOI,SAAS,EAAE;YACrBJ,OAAOI,SAAS,GAAG,EAAE;QACvB;QAEA,MAAMA,YAAwB;YAC5B;gBACEC,SAASZ;gBACTa,QAAQ;gBACRC,MAAM;YACR;YACA;gBACEF,SAASX,qBAAqBK;gBAC9BO,QAAQ;gBACRC,MAAM;YACR;YACA;gBACEF,SAASV;gBACTW,QAAQ;gBACRC,MAAM;YACR;SACD;QAEDP,OAAOI,SAAS,GAAG;eAAIJ,OAAOI,SAAS;eAAKA;SAAU;QAEtD,IAAI,CAACJ,OAAOQ,IAAI,EAAE;YAChBR,OAAOQ,IAAI,GAAG;gBACZC,OAAO,EAAE;YACX;QACF;QAEA,MAAMA,QAAsB;YAC1Bb,yBAAyBG;YACzBF,oBAAoBE;SACrB;QAEDC,OAAOQ,IAAI,CAACC,KAAK,GAAG;eAAKT,OAAOQ,IAAI,CAACC,KAAK,IAAI,EAAE;eAAMA;SAAM;QAE5D,MAAMC,iBAAiBV,OAAOW,MAAM;QAEpCX,OAAOW,MAAM,GAAG,OAAOC;YACrB,IAAIF,gBAAgB;gBAClB,MAAMA,eAAeE;YACvB;QACF;QAEA,OAAOZ;IACT,EAAC"}
@@ -87,6 +87,9 @@ export type EmailAdapter = ({ payload }: {
87
87
  webhookHandler?: (req: PayloadRequest) => Promise<void | WebhookResult>;
88
88
  };
89
89
  export type MobilizehubPluginConfig = {
90
+ /**
91
+ * Broadcasts task configuration
92
+ */
90
93
  broadcastConfig?: {
91
94
  /**
92
95
  * Batch size for processing contacts in the broadcasts task.
@@ -131,6 +134,14 @@ export type MobilizehubPluginConfig = {
131
134
  * Overrides for the emails collection
132
135
  */
133
136
  emailsOverrides?: CollectionOverride;
137
+ /**
138
+ * Overrides for the forms collection
139
+ */
140
+ formsOverrides?: CollectionOverride;
141
+ /**
142
+ * Overrides for the form submissions collection
143
+ */
144
+ formSubmissionsOverrides?: CollectionOverride;
134
145
  /**
135
146
  * Overrides for the pages collection
136
147
  */
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/types/index.ts"],"sourcesContent":["import type { BasePayload, Block, CollectionConfig, Field, PayloadRequest } from 'payload'\n\nexport type FieldsOverride = (args: { defaultFields: Field[] }) => Field[]\n\nexport type CollectionOverride = { fields?: FieldsOverride } & Partial<\n Omit<CollectionConfig, 'fields'>\n>\n\nexport type BlocksOverride = (args: { defaultBlocks: Block[] }) => Block[]\n\n/**\n * Contact type\n */\nexport type Contact = {\n createdAt?: string\n email?: string\n emailOptIn: boolean\n firstName?: string\n id: number | string\n lastName?: string\n tags?: {\n createdAt?: string\n id: number | string\n name?: string\n updatedAt?: string\n }[]\n updatedAt?: string\n}\n\n/**\n * Unsubscribe token input structure\n */\nexport interface UnsubscribeTokenInput {\n timestamp: number\n tokenId: string\n}\n\n/**\n * Unsubscribe token record structure\n */\nexport type UnsubscribeTokenRecord = {\n emailId?: number | string\n expiresAt?: string\n id: string\n}\n\n/**\n * Email activity types\n */\nexport type EmailStatus =\n | 'bounced'\n | 'complained'\n | 'delivered'\n | 'failed'\n | 'queued'\n | 'sent'\n | 'unsubscribed'\n\n/**\n * Email activity types from providers\n */\nexport type EmailActivityType =\n | 'bounced'\n | 'clicked'\n | 'complained'\n | 'delivered'\n | 'delivery_delayed'\n | 'failed'\n | 'opened'\n | 'received'\n | 'sent'\n\n/**\n * Email message structure\n */\nexport type EmailMessage = {\n from: string\n html: string\n idempotencyKey?: string\n markdown?: string\n plainText?: string\n previewText?: string\n replyTo?: string\n subject: string\n to: string\n token?: string\n}\n\n/**\n * Result of a webhook call\n */\nexport type WebhookResult = {\n body?: unknown\n status: number\n}\n\n/**\n * Email adapter interface for sending emails\n */\nexport type EmailAdapter = ({ payload }: { payload: BasePayload }) => {\n defaultFromAddress: string\n defaultFromName: string\n name: string\n render: (args: EmailMessage) => string\n sendEmail: (args: EmailMessage) => Promise<{ providerId: string } | void>\n webhookHandler?: (req: PayloadRequest) => Promise<void | WebhookResult>\n}\n\nexport type MobilizehubPluginConfig = {\n broadcastConfig?: {\n /**\n * Batch size for processing contacts in the broadcasts task.\n * Higher values process faster but use more memory.\n * @default 100\n */\n batchSize?: number\n /**\n * Optional custom queue name for the broadcasts task\n * @default 'send-broadcasts'\n */\n broadcastQueueName?: string\n /**\n * Optional custom queue name for the email sending task\n * @default 'send-email'\n */\n emailQueueName?: string\n /**\n * Cron schedule for the broadcasts task\n * On schedule the task will run to process and send pending broadcasts\n * @default '5 * * * *' (every 5 minutes)\n */\n taskSchedule?: string\n }\n /**\n * Overrides for the broadcasts collection\n */\n broadcastsOverrides?: CollectionOverride\n\n /**\n * Overrides for the contacts collection\n */\n contactsOverrides?: CollectionOverride\n /**\n * Disable the plugin\n */\n disabled?: boolean\n /**\n * Email adapter for sending emails\n */\n email: EmailAdapter\n /**\n * Overrides for the emails collection\n */\n emailsOverrides?: CollectionOverride\n /**\n * Overrides for the pages collection\n */\n pagesOverrides?: { blocks?: BlocksOverride } & CollectionOverride\n /**\n * Overrides for the tags collection\n */\n tagsOverrides?: CollectionOverride\n /**\n *\n */\n}\n"],"names":[],"mappings":"AA4GA,WAyDC"}
1
+ {"version":3,"sources":["../../src/types/index.ts"],"sourcesContent":["import type { BasePayload, Block, CollectionConfig, Field, PayloadRequest } from 'payload'\n\nexport type FieldsOverride = (args: { defaultFields: Field[] }) => Field[]\n\nexport type CollectionOverride = { fields?: FieldsOverride } & Partial<\n Omit<CollectionConfig, 'fields'>\n>\n\nexport type BlocksOverride = (args: { defaultBlocks: Block[] }) => Block[]\n\n/**\n * Contact type\n */\nexport type Contact = {\n createdAt?: string\n email?: string\n emailOptIn: boolean\n firstName?: string\n id: number | string\n lastName?: string\n tags?: {\n createdAt?: string\n id: number | string\n name?: string\n updatedAt?: string\n }[]\n updatedAt?: string\n}\n\n/**\n * Unsubscribe token input structure\n */\nexport interface UnsubscribeTokenInput {\n timestamp: number\n tokenId: string\n}\n\n/**\n * Unsubscribe token record structure\n */\nexport type UnsubscribeTokenRecord = {\n emailId?: number | string\n expiresAt?: string\n id: string\n}\n\n/**\n * Email activity types\n */\nexport type EmailStatus =\n | 'bounced'\n | 'complained'\n | 'delivered'\n | 'failed'\n | 'queued'\n | 'sent'\n | 'unsubscribed'\n\n/**\n * Email activity types from providers\n */\nexport type EmailActivityType =\n | 'bounced'\n | 'clicked'\n | 'complained'\n | 'delivered'\n | 'delivery_delayed'\n | 'failed'\n | 'opened'\n | 'received'\n | 'sent'\n\n/**\n * Email message structure\n */\nexport type EmailMessage = {\n from: string\n html: string\n idempotencyKey?: string\n markdown?: string\n plainText?: string\n previewText?: string\n replyTo?: string\n subject: string\n to: string\n token?: string\n}\n\n/**\n * Result of a webhook call\n */\nexport type WebhookResult = {\n body?: unknown\n status: number\n}\n\n/**\n * Email adapter interface for sending emails\n */\nexport type EmailAdapter = ({ payload }: { payload: BasePayload }) => {\n defaultFromAddress: string\n defaultFromName: string\n name: string\n render: (args: EmailMessage) => string\n sendEmail: (args: EmailMessage) => Promise<{ providerId: string } | void>\n webhookHandler?: (req: PayloadRequest) => Promise<void | WebhookResult>\n}\n\nexport type MobilizehubPluginConfig = {\n /**\n * Broadcasts task configuration\n */\n broadcastConfig?: {\n /**\n * Batch size for processing contacts in the broadcasts task.\n * Higher values process faster but use more memory.\n * @default 100\n */\n batchSize?: number\n /**\n * Optional custom queue name for the broadcasts task\n * @default 'send-broadcasts'\n */\n broadcastQueueName?: string\n /**\n * Optional custom queue name for the email sending task\n * @default 'send-email'\n */\n emailQueueName?: string\n /**\n * Cron schedule for the broadcasts task\n * On schedule the task will run to process and send pending broadcasts\n * @default '5 * * * *' (every 5 minutes)\n */\n taskSchedule?: string\n }\n /**\n * Overrides for the broadcasts collection\n */\n broadcastsOverrides?: CollectionOverride\n /**\n * Overrides for the contacts collection\n */\n contactsOverrides?: CollectionOverride\n /**\n * Disable the plugin\n */\n disabled?: boolean\n /**\n * Email adapter for sending emails\n */\n email: EmailAdapter\n /**\n * Overrides for the emails collection\n */\n emailsOverrides?: CollectionOverride\n /**\n * Overrides for the forms collection\n */\n formsOverrides?: CollectionOverride\n /**\n * Overrides for the form submissions collection\n */\n formSubmissionsOverrides?: CollectionOverride\n /**\n * Overrides for the pages collection\n */\n pagesOverrides?: { blocks?: BlocksOverride } & CollectionOverride\n /**\n * Overrides for the tags collection\n */\n tagsOverrides?: CollectionOverride\n}\n"],"names":[],"mappings":"AA4GA,WAgEC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mobilizehub/payload-plugin",
3
- "version": "0.3.2",
3
+ "version": "0.4.0",
4
4
  "description": "Edvocacy plugin for Payload",
5
5
  "license": "MIT",
6
6
  "private": false,