chore: migrates form builder example cms to examples
This commit is contained in:
4
examples/form-builder/cms/.env.example
Normal file
4
examples/form-builder/cms/.env.example
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
PAYLOAD_PUBLIC_SITE_URL=http://localhost:3000
|
||||||
|
PAYLOAD_PUBLIC_SERVER_URL=http://localhost:8000
|
||||||
|
MONGODB_URI=mongodb://localhost/form-builder-example
|
||||||
|
PAYLOAD_SECRET=ENTER-STRING-HERE
|
||||||
4
examples/form-builder/cms/.eslintrc.js
Normal file
4
examples/form-builder/cms/.eslintrc.js
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
module.exports = {
|
||||||
|
root: true,
|
||||||
|
extends: ['@payloadcms'],
|
||||||
|
}
|
||||||
5
examples/form-builder/cms/.gitignore
vendored
Normal file
5
examples/form-builder/cms/.gitignore
vendored
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
build
|
||||||
|
dist
|
||||||
|
node_modules
|
||||||
|
package-lock.json
|
||||||
|
.env
|
||||||
1
examples/form-builder/cms/.npmrc
Normal file
1
examples/form-builder/cms/.npmrc
Normal file
@@ -0,0 +1 @@
|
|||||||
|
legacy-peer-deps=true
|
||||||
8
examples/form-builder/cms/.prettierrc.js
Normal file
8
examples/form-builder/cms/.prettierrc.js
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
module.exports = {
|
||||||
|
printWidth: 100,
|
||||||
|
parser: "typescript",
|
||||||
|
semi: false,
|
||||||
|
singleQuote: true,
|
||||||
|
trailingComma: "all",
|
||||||
|
arrowParens: "avoid",
|
||||||
|
};
|
||||||
21
examples/form-builder/cms/.vscode/launch.json
vendored
Normal file
21
examples/form-builder/cms/.vscode/launch.json
vendored
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
{
|
||||||
|
// Use IntelliSense to learn about possible attributes.
|
||||||
|
// Hover to view descriptions of existing attributes.
|
||||||
|
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||||
|
"version": "0.2.0",
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"type": "node",
|
||||||
|
"request": "launch",
|
||||||
|
"name": "Debug Learn with Jason CMS",
|
||||||
|
"program": "${workspaceFolder}/src/server.ts",
|
||||||
|
"preLaunchTask": "npm: build:server",
|
||||||
|
"env": {
|
||||||
|
"PAYLOAD_CONFIG_PATH": "${workspaceFolder}/src/payload.config.ts"
|
||||||
|
},
|
||||||
|
// "outFiles": [
|
||||||
|
// "${workspaceFolder}/dist/**/*.js"
|
||||||
|
// ]
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}
|
||||||
26
examples/form-builder/cms/README.md
Normal file
26
examples/form-builder/cms/README.md
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
# Form Builder Example CMS
|
||||||
|
|
||||||
|
This is an example repo for a CMS built with [Payload](https://payloadcms.com). This repo showcases how to utilize Payload's [Form Builder Plugin](https://github.com/payloadcms/plugin-form-builder).
|
||||||
|
|
||||||
|
## Getting Started
|
||||||
|
|
||||||
|
1. Clone this repo
|
||||||
|
2. `cd` into the directory and run `yarn` or `npm install`
|
||||||
|
3. Copy (`cp`) the `.env.example` file to an `.env` file
|
||||||
|
4. Run `yarn dev` or `npm run dev` to start the development server
|
||||||
|
5. Visit `http://localhost:8000/admin` to access the admin panel
|
||||||
|
6. Login with the following credentials:
|
||||||
|
- Email: `dev@payloadcms.com`
|
||||||
|
- Password: `test`
|
||||||
|
|
||||||
|
## Frontend Development
|
||||||
|
|
||||||
|
Clone the [frontend](https://github.com/payloadcms/form-builder-example-website) and follow the instructions there to get started. You can use this repo as a backend for the frontend and see for yourself how it all works together.
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
Once booted up, a `Basic Form` will be immediately available to view on the home page along with a few other forms on their corresponding pages.
|
||||||
|
|
||||||
|
- These forms are seeded into the `forms` collection.
|
||||||
|
- A few pages have also been seeded in on start up and utilize a layout building block called `Form Block` that is wired up to use the different forms from the `forms` collection.
|
||||||
|
- This is done by adding a `relationship` field in the form-block config and setting its `relationTo` field to the `forms` collection.
|
||||||
4
examples/form-builder/cms/nodemon.json
Normal file
4
examples/form-builder/cms/nodemon.json
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"ext": "ts",
|
||||||
|
"exec": "ts-node src/server.ts"
|
||||||
|
}
|
||||||
33
examples/form-builder/cms/package.json
Normal file
33
examples/form-builder/cms/package.json
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
{
|
||||||
|
"name": "form-builder-example-cms",
|
||||||
|
"description": "The CMS that utilizes Payload's form builder plugin.",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"main": "dist/server.js",
|
||||||
|
"license": "MIT",
|
||||||
|
"scripts": {
|
||||||
|
"dev": "cross-env PAYLOAD_SEED=true PAYLOAD_DROP_DATABASE=true PAYLOAD_CONFIG_PATH=src/payload.config.ts nodemon",
|
||||||
|
"build:payload": "cross-env PAYLOAD_CONFIG_PATH=src/payload.config.ts payload build",
|
||||||
|
"build:server": "tsc",
|
||||||
|
"build": "yarn copyfiles && yarn build:payload && yarn build:server",
|
||||||
|
"serve": "cross-env PAYLOAD_CONFIG_PATH=dist/payload.config.js NODE_ENV=production node dist/server.js",
|
||||||
|
"copyfiles": "copyfiles -u 1 \"src/**/*.{html,css,scss,ttf,woff,woff2,eot,svg,jpg,png}\" dist/",
|
||||||
|
"generate:types": "cross-env PAYLOAD_CONFIG_PATH=src/payload.config.ts payload generate:types",
|
||||||
|
"generate:graphQLSchema": "PAYLOAD_CONFIG_PATH=src/payload.config.ts payload generate:graphQLSchema"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@faceless-ui/modal": "^2.0.1",
|
||||||
|
"@payloadcms/plugin-form-builder": "^1.0.12",
|
||||||
|
"@payloadcms/plugin-seo": "^1.0.8",
|
||||||
|
"dotenv": "^8.2.0",
|
||||||
|
"express": "^4.17.1",
|
||||||
|
"payload": "^1.6.19"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@types/express": "^4.17.9",
|
||||||
|
"copyfiles": "^2.4.1",
|
||||||
|
"cross-env": "^7.0.3",
|
||||||
|
"nodemon": "^2.0.6",
|
||||||
|
"ts-node": "^9.1.1",
|
||||||
|
"typescript": "^4.1.3"
|
||||||
|
}
|
||||||
|
}
|
||||||
11
examples/form-builder/cms/src/access/publishedOnly.ts
Normal file
11
examples/form-builder/cms/src/access/publishedOnly.ts
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
import { Access } from 'payload/config';
|
||||||
|
|
||||||
|
export const publishedOnly: Access = ({ req: { user } }) => {
|
||||||
|
if (user) return true;
|
||||||
|
|
||||||
|
return {
|
||||||
|
_status: {
|
||||||
|
equals: 'published',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
};
|
||||||
33
examples/form-builder/cms/src/blocks/Form/index.ts
Normal file
33
examples/form-builder/cms/src/blocks/Form/index.ts
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
import { Block } from 'payload/types';
|
||||||
|
import richText from '../../fields/richText';
|
||||||
|
|
||||||
|
export const FormBlock: Block = {
|
||||||
|
slug: 'formBlock',
|
||||||
|
labels: {
|
||||||
|
singular: 'Form Block',
|
||||||
|
plural: 'Form Blocks',
|
||||||
|
},
|
||||||
|
graphQL: {
|
||||||
|
singularName: 'FormBlock',
|
||||||
|
},
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
name: 'form',
|
||||||
|
type: 'relationship',
|
||||||
|
relationTo: 'forms',
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'enableIntro',
|
||||||
|
label: 'Enable Intro Content',
|
||||||
|
type: 'checkbox',
|
||||||
|
},
|
||||||
|
richText({
|
||||||
|
name: 'introContent',
|
||||||
|
label: 'Intro Content',
|
||||||
|
admin: {
|
||||||
|
condition: (_, { enableIntro }) => Boolean(enableIntro),
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
};
|
||||||
44
examples/form-builder/cms/src/collections/Pages.ts
Normal file
44
examples/form-builder/cms/src/collections/Pages.ts
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
import { CollectionConfig } from 'payload/types';
|
||||||
|
import { publishedOnly } from '../access/publishedOnly';
|
||||||
|
import { FormBlock } from '../blocks/Form';
|
||||||
|
import { slugField } from '../fields/slug';
|
||||||
|
|
||||||
|
export const Pages: CollectionConfig = {
|
||||||
|
slug: 'pages',
|
||||||
|
admin: {
|
||||||
|
useAsTitle: 'title',
|
||||||
|
defaultColumns: ['title', 'slug', 'updatedAt'],
|
||||||
|
},
|
||||||
|
versions: {
|
||||||
|
drafts: true,
|
||||||
|
},
|
||||||
|
access: {
|
||||||
|
read: publishedOnly,
|
||||||
|
},
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
name: 'title',
|
||||||
|
type: 'text',
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'tabs',
|
||||||
|
tabs: [
|
||||||
|
{
|
||||||
|
label: 'Content',
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
name: 'layout',
|
||||||
|
type: 'blocks',
|
||||||
|
required: true,
|
||||||
|
blocks: [
|
||||||
|
FormBlock,
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
slugField(),
|
||||||
|
],
|
||||||
|
};
|
||||||
12
examples/form-builder/cms/src/collections/Users.ts
Normal file
12
examples/form-builder/cms/src/collections/Users.ts
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
import { CollectionConfig } from 'payload/types';
|
||||||
|
|
||||||
|
export const Users: CollectionConfig = {
|
||||||
|
slug: 'users',
|
||||||
|
auth: true,
|
||||||
|
admin: {
|
||||||
|
useAsTitle: 'email',
|
||||||
|
},
|
||||||
|
fields: [
|
||||||
|
// Don't need any user fields here
|
||||||
|
],
|
||||||
|
};
|
||||||
151
examples/form-builder/cms/src/fields/link.ts
Normal file
151
examples/form-builder/cms/src/fields/link.ts
Normal file
@@ -0,0 +1,151 @@
|
|||||||
|
import { Field } from 'payload/types';
|
||||||
|
import deepMerge from '../utilities/deepMerge';
|
||||||
|
|
||||||
|
export const appearanceOptions = {
|
||||||
|
primary: {
|
||||||
|
label: 'Primary Button',
|
||||||
|
value: 'primary',
|
||||||
|
},
|
||||||
|
secondary: {
|
||||||
|
label: 'Secondary Button',
|
||||||
|
value: 'secondary',
|
||||||
|
},
|
||||||
|
default: {
|
||||||
|
label: 'Default',
|
||||||
|
value: 'default',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export type LinkAppearances = 'primary' | 'secondary' | 'default'
|
||||||
|
|
||||||
|
type LinkType = (
|
||||||
|
options?: {
|
||||||
|
appearances?: LinkAppearances[] | false
|
||||||
|
disableLabel?: boolean
|
||||||
|
overrides?: Record<string, unknown>
|
||||||
|
}
|
||||||
|
) => Field;
|
||||||
|
|
||||||
|
const link: LinkType = ({
|
||||||
|
appearances,
|
||||||
|
disableLabel = false,
|
||||||
|
overrides = {},
|
||||||
|
} = {}) => {
|
||||||
|
const linkResult: Field = {
|
||||||
|
name: 'link',
|
||||||
|
type: 'group',
|
||||||
|
admin: {
|
||||||
|
hideGutter: true,
|
||||||
|
},
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
type: 'row',
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
name: 'type',
|
||||||
|
type: 'radio',
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
label: 'Internal link',
|
||||||
|
value: 'reference',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Custom URL',
|
||||||
|
value: 'custom',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
defaultValue: 'reference',
|
||||||
|
admin: {
|
||||||
|
layout: 'horizontal',
|
||||||
|
width: '50%',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'newTab',
|
||||||
|
label: 'Open in new tab',
|
||||||
|
type: 'checkbox',
|
||||||
|
admin: {
|
||||||
|
width: '50%',
|
||||||
|
style: {
|
||||||
|
alignSelf: 'flex-end',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
const linkTypes: Field[] = [
|
||||||
|
{
|
||||||
|
name: 'reference',
|
||||||
|
label: 'Document to link to',
|
||||||
|
type: 'relationship',
|
||||||
|
relationTo: ['pages'],
|
||||||
|
required: true,
|
||||||
|
maxDepth: 1,
|
||||||
|
admin: {
|
||||||
|
condition: (_, siblingData) => siblingData?.type === 'reference',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'url',
|
||||||
|
label: 'Custom URL',
|
||||||
|
type: 'text',
|
||||||
|
required: true,
|
||||||
|
admin: {
|
||||||
|
condition: (_, siblingData) => siblingData?.type === 'custom',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
if (!disableLabel) {
|
||||||
|
linkTypes[0].admin.width = '50%';
|
||||||
|
linkTypes[1].admin.width = '50%';
|
||||||
|
|
||||||
|
linkResult.fields.push({
|
||||||
|
type: 'row',
|
||||||
|
fields: [
|
||||||
|
...linkTypes,
|
||||||
|
{
|
||||||
|
name: 'label',
|
||||||
|
label: 'Label',
|
||||||
|
type: 'text',
|
||||||
|
required: true,
|
||||||
|
admin: {
|
||||||
|
width: '50%',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
linkResult.fields = [...linkResult.fields, ...linkTypes];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (appearances !== false) {
|
||||||
|
let appearanceOptionsToUse = [
|
||||||
|
appearanceOptions.default,
|
||||||
|
appearanceOptions.primary,
|
||||||
|
appearanceOptions.secondary,
|
||||||
|
];
|
||||||
|
|
||||||
|
if (appearances) {
|
||||||
|
appearanceOptionsToUse = appearances.map((appearance) => appearanceOptions[appearance]);
|
||||||
|
}
|
||||||
|
|
||||||
|
linkResult.fields.push({
|
||||||
|
name: 'appearance',
|
||||||
|
type: 'select',
|
||||||
|
defaultValue: 'default',
|
||||||
|
options: appearanceOptionsToUse,
|
||||||
|
admin: {
|
||||||
|
description: 'Choose how the link should be rendered.',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return deepMerge(linkResult, overrides);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default link;
|
||||||
13
examples/form-builder/cms/src/fields/richText/elements.ts
Normal file
13
examples/form-builder/cms/src/fields/richText/elements.ts
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
import { RichTextElement } from 'payload/dist/fields/config/types';
|
||||||
|
|
||||||
|
const elements: RichTextElement[] = [
|
||||||
|
'blockquote',
|
||||||
|
'h2',
|
||||||
|
'h3',
|
||||||
|
'h4',
|
||||||
|
'h5',
|
||||||
|
'h6',
|
||||||
|
'link',
|
||||||
|
];
|
||||||
|
|
||||||
|
export default elements;
|
||||||
94
examples/form-builder/cms/src/fields/richText/index.ts
Normal file
94
examples/form-builder/cms/src/fields/richText/index.ts
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
import { RichTextElement, RichTextField, RichTextLeaf } from 'payload/dist/fields/config/types';
|
||||||
|
import deepMerge from '../../utilities/deepMerge';
|
||||||
|
import elements from './elements';
|
||||||
|
import leaves from './leaves';
|
||||||
|
import link from '../link';
|
||||||
|
|
||||||
|
type RichText = (
|
||||||
|
overrides?: Partial<RichTextField>,
|
||||||
|
additions?: {
|
||||||
|
elements?: RichTextElement[]
|
||||||
|
leaves?: RichTextLeaf[]
|
||||||
|
}
|
||||||
|
) => RichTextField
|
||||||
|
|
||||||
|
const richText: RichText = (
|
||||||
|
overrides,
|
||||||
|
additions = {
|
||||||
|
elements: [],
|
||||||
|
leaves: [],
|
||||||
|
},
|
||||||
|
) => deepMerge<RichTextField, Partial<RichTextField>>(
|
||||||
|
{
|
||||||
|
name: 'richText',
|
||||||
|
type: 'richText',
|
||||||
|
required: true,
|
||||||
|
admin: {
|
||||||
|
upload: {
|
||||||
|
collections: {
|
||||||
|
media: {
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
type: 'richText',
|
||||||
|
name: 'caption',
|
||||||
|
label: 'Caption',
|
||||||
|
admin: {
|
||||||
|
elements: [
|
||||||
|
...elements,
|
||||||
|
],
|
||||||
|
leaves: [
|
||||||
|
...leaves,
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'radio',
|
||||||
|
name: 'alignment',
|
||||||
|
label: 'Alignment',
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
label: 'Left',
|
||||||
|
value: 'left',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Center',
|
||||||
|
value: 'center',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Right',
|
||||||
|
value: 'right',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'enableLink',
|
||||||
|
type: 'checkbox',
|
||||||
|
label: 'Enable Link',
|
||||||
|
},
|
||||||
|
link({
|
||||||
|
appearances: false,
|
||||||
|
disableLabel: true,
|
||||||
|
overrides: {
|
||||||
|
admin: {
|
||||||
|
condition: (_, data) => Boolean(data?.enableLink),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
elements: [
|
||||||
|
...elements,
|
||||||
|
...additions.elements || [],
|
||||||
|
],
|
||||||
|
leaves: [
|
||||||
|
...leaves,
|
||||||
|
...additions.leaves || [],
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
overrides,
|
||||||
|
);
|
||||||
|
|
||||||
|
export default richText;
|
||||||
9
examples/form-builder/cms/src/fields/richText/leaves.ts
Normal file
9
examples/form-builder/cms/src/fields/richText/leaves.ts
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
import { RichTextLeaf } from 'payload/dist/fields/config/types';
|
||||||
|
|
||||||
|
const defaultLeaves: RichTextLeaf[] = [
|
||||||
|
'bold',
|
||||||
|
'italic',
|
||||||
|
'underline',
|
||||||
|
];
|
||||||
|
|
||||||
|
export default defaultLeaves;
|
||||||
23
examples/form-builder/cms/src/fields/slug.ts
Normal file
23
examples/form-builder/cms/src/fields/slug.ts
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
import { Field } from 'payload/types';
|
||||||
|
import formatSlug from '../utilities/formatSlug';
|
||||||
|
import deepMerge from '../utilities/deepMerge';
|
||||||
|
|
||||||
|
type Slug = (fieldToUse?: string, overrides?: Partial<Field>) => Field
|
||||||
|
|
||||||
|
export const slugField: Slug = (fieldToUse = 'title', overrides) => deepMerge<Field, Partial<Field>>(
|
||||||
|
{
|
||||||
|
name: 'slug',
|
||||||
|
label: 'Slug',
|
||||||
|
type: 'text',
|
||||||
|
index: true,
|
||||||
|
admin: {
|
||||||
|
position: 'sidebar',
|
||||||
|
},
|
||||||
|
hooks: {
|
||||||
|
beforeValidate: [
|
||||||
|
formatSlug(fieldToUse),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
overrides,
|
||||||
|
);
|
||||||
21
examples/form-builder/cms/src/globals/MainMenu.ts
Normal file
21
examples/form-builder/cms/src/globals/MainMenu.ts
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
import { GlobalConfig } from 'payload/types';
|
||||||
|
import link from '../fields/link';
|
||||||
|
|
||||||
|
export const MainMenu: GlobalConfig = {
|
||||||
|
slug: 'main-menu',
|
||||||
|
access: {
|
||||||
|
read: () => true,
|
||||||
|
},
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
name: 'navItems',
|
||||||
|
type: 'array',
|
||||||
|
maxRows: 6,
|
||||||
|
fields: [
|
||||||
|
link({
|
||||||
|
appearances: false,
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
202
examples/form-builder/cms/src/payload-types.ts
Normal file
202
examples/form-builder/cms/src/payload-types.ts
Normal file
@@ -0,0 +1,202 @@
|
|||||||
|
/* tslint:disable */
|
||||||
|
/**
|
||||||
|
* This file was automatically generated by Payload CMS.
|
||||||
|
* DO NOT MODIFY IT BY HAND. Instead, modify your source Payload config,
|
||||||
|
* and re-run `payload generate:types` to regenerate this file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
export interface Config {}
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
|
* via the `definition` "main-menu".
|
||||||
|
*/
|
||||||
|
export interface MainMenu {
|
||||||
|
id: string;
|
||||||
|
navItems: {
|
||||||
|
link: {
|
||||||
|
type?: 'reference' | 'custom';
|
||||||
|
newTab?: boolean;
|
||||||
|
reference: {
|
||||||
|
value: string | Page;
|
||||||
|
relationTo: 'pages';
|
||||||
|
};
|
||||||
|
url: string;
|
||||||
|
label: string;
|
||||||
|
};
|
||||||
|
id?: string;
|
||||||
|
}[];
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
|
* via the `definition` "pages".
|
||||||
|
*/
|
||||||
|
export interface Page {
|
||||||
|
id: string;
|
||||||
|
title: string;
|
||||||
|
layout: {
|
||||||
|
form: string | Form;
|
||||||
|
enableIntro?: boolean;
|
||||||
|
introContent: {
|
||||||
|
[k: string]: unknown;
|
||||||
|
}[];
|
||||||
|
id?: string;
|
||||||
|
blockName?: string;
|
||||||
|
blockType: 'formBlock';
|
||||||
|
}[];
|
||||||
|
slug?: string;
|
||||||
|
_status?: 'draft' | 'published';
|
||||||
|
createdAt: string;
|
||||||
|
updatedAt: string;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
|
* via the `definition` "forms".
|
||||||
|
*/
|
||||||
|
export interface Form {
|
||||||
|
id: string;
|
||||||
|
title: string;
|
||||||
|
fields: (
|
||||||
|
| {
|
||||||
|
name: string;
|
||||||
|
label?: string;
|
||||||
|
width?: number;
|
||||||
|
defaultValue?: string;
|
||||||
|
required?: boolean;
|
||||||
|
id?: string;
|
||||||
|
blockName?: string;
|
||||||
|
blockType: 'text';
|
||||||
|
}
|
||||||
|
| {
|
||||||
|
name: string;
|
||||||
|
label?: string;
|
||||||
|
width?: number;
|
||||||
|
defaultValue?: string;
|
||||||
|
required?: boolean;
|
||||||
|
id?: string;
|
||||||
|
blockName?: string;
|
||||||
|
blockType: 'textarea';
|
||||||
|
}
|
||||||
|
| {
|
||||||
|
name: string;
|
||||||
|
label?: string;
|
||||||
|
width?: number;
|
||||||
|
defaultValue?: string;
|
||||||
|
options: {
|
||||||
|
label: string;
|
||||||
|
value: string;
|
||||||
|
id?: string;
|
||||||
|
}[];
|
||||||
|
required?: boolean;
|
||||||
|
id?: string;
|
||||||
|
blockName?: string;
|
||||||
|
blockType: 'select';
|
||||||
|
}
|
||||||
|
| {
|
||||||
|
name: string;
|
||||||
|
label?: string;
|
||||||
|
width?: number;
|
||||||
|
required?: boolean;
|
||||||
|
id?: string;
|
||||||
|
blockName?: string;
|
||||||
|
blockType: 'email';
|
||||||
|
}
|
||||||
|
| {
|
||||||
|
name: string;
|
||||||
|
label?: string;
|
||||||
|
width?: number;
|
||||||
|
required?: boolean;
|
||||||
|
id?: string;
|
||||||
|
blockName?: string;
|
||||||
|
blockType: 'state';
|
||||||
|
}
|
||||||
|
| {
|
||||||
|
name: string;
|
||||||
|
label?: string;
|
||||||
|
width?: number;
|
||||||
|
required?: boolean;
|
||||||
|
id?: string;
|
||||||
|
blockName?: string;
|
||||||
|
blockType: 'country';
|
||||||
|
}
|
||||||
|
| {
|
||||||
|
name: string;
|
||||||
|
label?: string;
|
||||||
|
width?: number;
|
||||||
|
defaultValue?: number;
|
||||||
|
required?: boolean;
|
||||||
|
id?: string;
|
||||||
|
blockName?: string;
|
||||||
|
blockType: 'number';
|
||||||
|
}
|
||||||
|
| {
|
||||||
|
name: string;
|
||||||
|
label?: string;
|
||||||
|
width?: number;
|
||||||
|
required?: boolean;
|
||||||
|
defaultValue?: boolean;
|
||||||
|
id?: string;
|
||||||
|
blockName?: string;
|
||||||
|
blockType: 'checkbox';
|
||||||
|
}
|
||||||
|
| {
|
||||||
|
message?: {
|
||||||
|
[k: string]: unknown;
|
||||||
|
}[];
|
||||||
|
id?: string;
|
||||||
|
blockName?: string;
|
||||||
|
blockType: 'message';
|
||||||
|
}
|
||||||
|
)[];
|
||||||
|
submitButtonLabel?: string;
|
||||||
|
confirmationType?: 'message' | 'redirect';
|
||||||
|
confirmationMessage: {
|
||||||
|
[k: string]: unknown;
|
||||||
|
}[];
|
||||||
|
redirect: {
|
||||||
|
url: string;
|
||||||
|
};
|
||||||
|
emails: {
|
||||||
|
emailTo: string;
|
||||||
|
bcc?: string;
|
||||||
|
replyTo?: string;
|
||||||
|
replyToName?: string;
|
||||||
|
emailFrom?: string;
|
||||||
|
emailFromName?: string;
|
||||||
|
subject: string;
|
||||||
|
message?: {
|
||||||
|
[k: string]: unknown;
|
||||||
|
}[];
|
||||||
|
id?: string;
|
||||||
|
}[];
|
||||||
|
createdAt: string;
|
||||||
|
updatedAt: string;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
|
* via the `definition` "users".
|
||||||
|
*/
|
||||||
|
export interface User {
|
||||||
|
id: string;
|
||||||
|
email?: string;
|
||||||
|
resetPasswordToken?: string;
|
||||||
|
resetPasswordExpiration?: string;
|
||||||
|
loginAttempts?: number;
|
||||||
|
lockUntil?: string;
|
||||||
|
createdAt: string;
|
||||||
|
updatedAt: string;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
|
* via the `definition` "form-submissions".
|
||||||
|
*/
|
||||||
|
export interface FormSubmission {
|
||||||
|
id: string;
|
||||||
|
form: string | Form;
|
||||||
|
submissionData: {
|
||||||
|
field: string;
|
||||||
|
value: string;
|
||||||
|
id?: string;
|
||||||
|
}[];
|
||||||
|
createdAt: string;
|
||||||
|
updatedAt: string;
|
||||||
|
}
|
||||||
31
examples/form-builder/cms/src/payload.config.ts
Normal file
31
examples/form-builder/cms/src/payload.config.ts
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
import { buildConfig } from 'payload/config';
|
||||||
|
import path from 'path';
|
||||||
|
import FormBuilder from '@payloadcms/plugin-form-builder';
|
||||||
|
import { Users } from './collections/Users';
|
||||||
|
import { Pages } from './collections/Pages';
|
||||||
|
import { MainMenu } from './globals/MainMenu';
|
||||||
|
|
||||||
|
export default buildConfig({
|
||||||
|
collections: [
|
||||||
|
Pages,
|
||||||
|
Users,
|
||||||
|
],
|
||||||
|
globals: [
|
||||||
|
MainMenu,
|
||||||
|
],
|
||||||
|
cors: [
|
||||||
|
'http://localhost:3000',
|
||||||
|
process.env.PAYLOAD_PUBLIC_SITE_URL,
|
||||||
|
],
|
||||||
|
typescript: {
|
||||||
|
outputFile: path.resolve(__dirname, 'payload-types.ts'),
|
||||||
|
},
|
||||||
|
plugins: [
|
||||||
|
FormBuilder({
|
||||||
|
fields: {
|
||||||
|
payment: false,
|
||||||
|
},
|
||||||
|
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
});
|
||||||
23
examples/form-builder/cms/src/seed/advanced.ts
Normal file
23
examples/form-builder/cms/src/seed/advanced.ts
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
export const advanced = {
|
||||||
|
title: 'Advanced',
|
||||||
|
layout: [
|
||||||
|
{
|
||||||
|
form: '{{ADVANCED_FORM_ID}}',
|
||||||
|
enableIntro: true,
|
||||||
|
introContent: [
|
||||||
|
{
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
text: 'Advanced form:',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
type: 'h4',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
id: '63adc92568224b995af9df14',
|
||||||
|
blockType: 'formBlock',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
slug: 'advanced',
|
||||||
|
_status: 'published',
|
||||||
|
};
|
||||||
118
examples/form-builder/cms/src/seed/advancedForm.ts
Normal file
118
examples/form-builder/cms/src/seed/advancedForm.ts
Normal file
@@ -0,0 +1,118 @@
|
|||||||
|
export const advancedForm = {
|
||||||
|
id: '63c0835134d40cef85cc11a2',
|
||||||
|
title: 'Advanced Form',
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
name: 'first-name',
|
||||||
|
label: 'First Name',
|
||||||
|
width: 50,
|
||||||
|
required: true,
|
||||||
|
id: '63c081b169853127a8895312',
|
||||||
|
blockName: 'first-name',
|
||||||
|
blockType: 'text',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'last-name',
|
||||||
|
label: 'Last Name',
|
||||||
|
width: 50,
|
||||||
|
required: true,
|
||||||
|
id: '63c081c669853127a8895313',
|
||||||
|
blockName: 'last-name',
|
||||||
|
blockType: 'text',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'email',
|
||||||
|
label: 'Email',
|
||||||
|
width: 100,
|
||||||
|
required: true,
|
||||||
|
id: '63c081e869853127a8895314',
|
||||||
|
blockName: 'email',
|
||||||
|
blockType: 'email',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'street-address',
|
||||||
|
label: 'Street Address',
|
||||||
|
width: 100,
|
||||||
|
required: true,
|
||||||
|
id: '63c081fe69853127a8895315',
|
||||||
|
blockName: 'street-address',
|
||||||
|
blockType: 'text',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'street-address-two',
|
||||||
|
label: 'Street Address Line 2',
|
||||||
|
width: 100,
|
||||||
|
id: '63c0823169853127a8895316',
|
||||||
|
blockName: 'street-address-two',
|
||||||
|
blockType: 'text',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'city',
|
||||||
|
label: 'City',
|
||||||
|
width: 50,
|
||||||
|
required: true,
|
||||||
|
id: '63c0825a69853127a8895317',
|
||||||
|
blockName: 'city',
|
||||||
|
blockType: 'text',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'state',
|
||||||
|
label: 'State',
|
||||||
|
width: 50,
|
||||||
|
required: true,
|
||||||
|
id: '63c0826569853127a8895318',
|
||||||
|
blockName: 'state',
|
||||||
|
blockType: 'state',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'zip-code',
|
||||||
|
label: 'Postal / Zip Code',
|
||||||
|
width: 50,
|
||||||
|
required: true,
|
||||||
|
id: '63c082bb69853127a889531a',
|
||||||
|
blockName: 'zip-code',
|
||||||
|
blockType: 'number',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'county',
|
||||||
|
label: 'Country',
|
||||||
|
width: 50,
|
||||||
|
required: true,
|
||||||
|
id: '63c0829269853127a8895319',
|
||||||
|
blockName: 'country',
|
||||||
|
blockType: 'country',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
submitButtonLabel: 'Submit',
|
||||||
|
confirmationType: 'message',
|
||||||
|
confirmationMessage: [
|
||||||
|
{
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
text: 'Your shipping information submission was successful.',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
emails: [
|
||||||
|
{
|
||||||
|
emailTo: '{{email}}',
|
||||||
|
emailFrom: 'dev@payloadcms.com',
|
||||||
|
emailFromName: 'Payload Team',
|
||||||
|
subject: "You've received a new message.",
|
||||||
|
message: [
|
||||||
|
{
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
text: 'Your example shipping information form submission was received successfully.',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
id: '63c0831869853127a889531b',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
createdAt: '2023-01-12T22:01:53.023Z',
|
||||||
|
updatedAt: '2023-01-12T22:01:53.023Z',
|
||||||
|
redirect: {},
|
||||||
|
};
|
||||||
102
examples/form-builder/cms/src/seed/basicForm.ts
Normal file
102
examples/form-builder/cms/src/seed/basicForm.ts
Normal file
@@ -0,0 +1,102 @@
|
|||||||
|
export const basicForm = {
|
||||||
|
id: '63c0651b132c8e2783f8dcae',
|
||||||
|
updatedAt: '2023-01-12T21:25:41.113Z',
|
||||||
|
createdAt: '2022-12-28T20:48:53.181Z',
|
||||||
|
title: 'Basic Form',
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
name: 'first-name',
|
||||||
|
label: 'First name',
|
||||||
|
width: 50,
|
||||||
|
required: true,
|
||||||
|
id: '63adaaba5236fe69ca8973f8',
|
||||||
|
blockName: 'first-name',
|
||||||
|
blockType: 'text',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'last-name',
|
||||||
|
label: 'Last name',
|
||||||
|
width: 50,
|
||||||
|
required: true,
|
||||||
|
id: '63bf4b1fd69cef4f34272f9a',
|
||||||
|
blockName: 'last-name',
|
||||||
|
blockType: 'text',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'email',
|
||||||
|
label: 'Email',
|
||||||
|
width: 100,
|
||||||
|
required: true,
|
||||||
|
id: '63c0953adc1cd2c2f6c2d30b',
|
||||||
|
blockName: 'email',
|
||||||
|
blockType: 'email',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'coolest-project',
|
||||||
|
label: "What's the coolest project you've built with Payload so far?",
|
||||||
|
width: 100,
|
||||||
|
required: false,
|
||||||
|
id: '63adab96b65c28c168442316',
|
||||||
|
blockName: 'coolest-project',
|
||||||
|
blockType: 'textarea',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
message: [
|
||||||
|
{
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
text: 'Have a great rest of your day!',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
text: '',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
text: 'Sincerely, \n\nPayload Team.',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
id: '63adb90db65c28c168442322',
|
||||||
|
blockName: 'farewell',
|
||||||
|
blockType: 'message',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
submitButtonLabel: 'Submit',
|
||||||
|
confirmationType: 'message',
|
||||||
|
confirmationMessage: [
|
||||||
|
{
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
text: 'The basic form has been submitted successfully.',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
emails: [
|
||||||
|
{
|
||||||
|
emailTo: '{{email}}',
|
||||||
|
emailFrom: 'dev@payloadcms.com',
|
||||||
|
emailFromName: 'Payload',
|
||||||
|
subject: "You've received a new message.",
|
||||||
|
message: [
|
||||||
|
{
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
text: 'Your basic form submission was successfully received.',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
id: '63acab72433ea1822764c538',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
redirect: {},
|
||||||
|
};
|
||||||
23
examples/form-builder/cms/src/seed/contact.ts
Normal file
23
examples/form-builder/cms/src/seed/contact.ts
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
export const contact = {
|
||||||
|
title: 'Contact',
|
||||||
|
layout: [
|
||||||
|
{
|
||||||
|
form: '{{CONTACT_FORM_ID}}',
|
||||||
|
enableIntro: true,
|
||||||
|
introContent: [
|
||||||
|
{
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
text: 'Example contact form:',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
type: 'h4',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
id: '63adc92568224b995af9df13',
|
||||||
|
blockType: 'formBlock',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
slug: 'contact',
|
||||||
|
_status: 'published',
|
||||||
|
};
|
||||||
74
examples/form-builder/cms/src/seed/contactForm.ts
Normal file
74
examples/form-builder/cms/src/seed/contactForm.ts
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
export const contactForm = {
|
||||||
|
id: '63c07ffd4cb6b574b4977573',
|
||||||
|
title: 'Contact Form',
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
name: 'full-name',
|
||||||
|
label: 'Full Name',
|
||||||
|
width: 100,
|
||||||
|
required: true,
|
||||||
|
id: '63c07f4e69853127a889530c',
|
||||||
|
blockName: 'full-name',
|
||||||
|
blockType: 'text',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'email',
|
||||||
|
label: 'Email',
|
||||||
|
width: 50,
|
||||||
|
required: true,
|
||||||
|
id: '63c07f7069853127a889530d',
|
||||||
|
blockName: 'email',
|
||||||
|
blockType: 'email',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'phone',
|
||||||
|
label: 'Phone',
|
||||||
|
width: 50,
|
||||||
|
required: false,
|
||||||
|
id: '63c07f8169853127a889530e',
|
||||||
|
blockName: 'phone',
|
||||||
|
blockType: 'number',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'message',
|
||||||
|
label: 'Message',
|
||||||
|
width: 100,
|
||||||
|
required: true,
|
||||||
|
id: '63c07f9d69853127a8895310',
|
||||||
|
blockName: 'message',
|
||||||
|
blockType: 'textarea',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
submitButtonLabel: 'Submit',
|
||||||
|
confirmationType: 'message',
|
||||||
|
confirmationMessage: [
|
||||||
|
{
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
text: 'The contact form has been submitted successfully.',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
emails: [
|
||||||
|
{
|
||||||
|
emailTo: '{{email}}',
|
||||||
|
emailFrom: 'dev@payloadcms.com',
|
||||||
|
emailFromName: 'Payload Team',
|
||||||
|
subject: "You've received a new message.",
|
||||||
|
message: [
|
||||||
|
{
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
text: 'Your contact form submission was successfully received.',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
id: '63c07fcb69853127a8895311',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
createdAt: '2023-01-12T21:47:41.374Z',
|
||||||
|
updatedAt: '2023-01-12T21:47:41.374Z',
|
||||||
|
redirect: {},
|
||||||
|
};
|
||||||
23
examples/form-builder/cms/src/seed/home.ts
Normal file
23
examples/form-builder/cms/src/seed/home.ts
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
export const home = {
|
||||||
|
title: 'Home',
|
||||||
|
layout: [
|
||||||
|
{
|
||||||
|
form: '{{BASIC_FORM_ID}}',
|
||||||
|
enableIntro: true,
|
||||||
|
introContent: [
|
||||||
|
{
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
text: 'Example basic form:',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
type: 'h4',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
id: '63adc92568224b995af9df12',
|
||||||
|
blockType: 'formBlock',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
slug: 'home',
|
||||||
|
_status: 'published',
|
||||||
|
};
|
||||||
121
examples/form-builder/cms/src/seed/index.ts
Normal file
121
examples/form-builder/cms/src/seed/index.ts
Normal file
@@ -0,0 +1,121 @@
|
|||||||
|
import { Payload } from 'payload';
|
||||||
|
import { home } from './home';
|
||||||
|
import { contact } from './contact';
|
||||||
|
import { advanced } from './advanced';
|
||||||
|
import { signUp } from './signUp';
|
||||||
|
import { basicForm } from './basicForm';
|
||||||
|
import { contactForm } from './contactForm';
|
||||||
|
import { advancedForm } from './advancedForm';
|
||||||
|
import { signUpForm } from './signUpForm';
|
||||||
|
|
||||||
|
export const seed = async (payload: Payload) => {
|
||||||
|
await payload.create({
|
||||||
|
collection: 'users',
|
||||||
|
data: {
|
||||||
|
email: 'dev@payloadcms.com',
|
||||||
|
password: 'test',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const basicFormJSON = JSON.parse(JSON.stringify(basicForm));
|
||||||
|
|
||||||
|
const { id: basicFormID } = await payload.create({
|
||||||
|
collection: 'forms',
|
||||||
|
data: basicFormJSON,
|
||||||
|
});
|
||||||
|
|
||||||
|
const contactFormJSON = JSON.parse(JSON.stringify(contactForm));
|
||||||
|
|
||||||
|
const { id: contactFormID } = await payload.create({
|
||||||
|
collection: 'forms',
|
||||||
|
data: contactFormJSON,
|
||||||
|
});
|
||||||
|
|
||||||
|
const advancedFormJSON = JSON.parse(JSON.stringify(advancedForm));
|
||||||
|
|
||||||
|
const { id: advancedFormID } = await payload.create({
|
||||||
|
collection: 'forms',
|
||||||
|
data: advancedFormJSON,
|
||||||
|
});
|
||||||
|
|
||||||
|
const signUpFormJSON = JSON.parse(JSON.stringify(signUpForm));
|
||||||
|
|
||||||
|
const { id: signUpFormID } = await payload.create({
|
||||||
|
collection: 'forms',
|
||||||
|
data: signUpFormJSON,
|
||||||
|
});
|
||||||
|
|
||||||
|
const homePageJSON = JSON.parse(
|
||||||
|
JSON.stringify(home).replace(/{{BASIC_FORM_ID}}/g, basicFormID),
|
||||||
|
);
|
||||||
|
|
||||||
|
const contactPageJSON = JSON.parse(
|
||||||
|
JSON.stringify(contact).replace(/{{CONTACT_FORM_ID}}/g, contactFormID),
|
||||||
|
);
|
||||||
|
|
||||||
|
const advancedPageJSON = JSON.parse(
|
||||||
|
JSON.stringify(advanced).replace(/{{ADVANCED_FORM_ID}}/g, advancedFormID),
|
||||||
|
);
|
||||||
|
|
||||||
|
const signupPageJSON = JSON.parse(
|
||||||
|
JSON.stringify(signUp).replace(/{{SIGNUP_FORM_ID}}/g, signUpFormID),
|
||||||
|
);
|
||||||
|
|
||||||
|
await payload.create({
|
||||||
|
collection: 'pages',
|
||||||
|
data: homePageJSON,
|
||||||
|
});
|
||||||
|
|
||||||
|
const { id: contactPageID } = await payload.create({
|
||||||
|
collection: 'pages',
|
||||||
|
data: contactPageJSON,
|
||||||
|
});
|
||||||
|
|
||||||
|
const { id: advancedPageID } = await payload.create({
|
||||||
|
collection: 'pages',
|
||||||
|
data: advancedPageJSON,
|
||||||
|
});
|
||||||
|
|
||||||
|
const { id: signupPageID } = await payload.create({
|
||||||
|
collection: 'pages',
|
||||||
|
data: signupPageJSON,
|
||||||
|
});
|
||||||
|
|
||||||
|
await payload.updateGlobal({
|
||||||
|
slug: 'main-menu',
|
||||||
|
data: {
|
||||||
|
navItems: [
|
||||||
|
{
|
||||||
|
link: {
|
||||||
|
type: 'reference',
|
||||||
|
reference: {
|
||||||
|
relationTo: 'pages',
|
||||||
|
value: contactPageID,
|
||||||
|
},
|
||||||
|
label: 'Contact Form',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
link: {
|
||||||
|
type: 'reference',
|
||||||
|
reference: {
|
||||||
|
relationTo: 'pages',
|
||||||
|
value: advancedPageID,
|
||||||
|
},
|
||||||
|
label: 'Advanced Form',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
link: {
|
||||||
|
type: 'reference',
|
||||||
|
reference: {
|
||||||
|
relationTo: 'pages',
|
||||||
|
value: signupPageID,
|
||||||
|
},
|
||||||
|
label: 'Signup Form',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
23
examples/form-builder/cms/src/seed/signUp.ts
Normal file
23
examples/form-builder/cms/src/seed/signUp.ts
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
export const signUp = {
|
||||||
|
title: 'Sign Up',
|
||||||
|
layout: [
|
||||||
|
{
|
||||||
|
form: '{{SIGNUP_FORM_ID}}',
|
||||||
|
enableIntro: true,
|
||||||
|
introContent: [
|
||||||
|
{
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
text: 'Example sign-up form:',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
type: 'h4',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
id: '63adc92568224b995af9df15',
|
||||||
|
blockType: 'formBlock',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
slug: 'sign-up',
|
||||||
|
_status: 'published',
|
||||||
|
};
|
||||||
86
examples/form-builder/cms/src/seed/signUpForm.ts
Normal file
86
examples/form-builder/cms/src/seed/signUpForm.ts
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
export const signUpForm = {
|
||||||
|
id: '63c086c36955e39c4208aa8f',
|
||||||
|
title: 'Sign Up Form',
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
name: 'full-name',
|
||||||
|
label: 'Full Name',
|
||||||
|
width: 100,
|
||||||
|
required: true,
|
||||||
|
id: '63c085ae69853127a889531e',
|
||||||
|
blockName: 'full-name',
|
||||||
|
blockType: 'text',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'email',
|
||||||
|
label: 'Email',
|
||||||
|
width: 100,
|
||||||
|
required: true,
|
||||||
|
id: '63c085df69853127a889531f',
|
||||||
|
blockName: 'email',
|
||||||
|
blockType: 'email',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'password',
|
||||||
|
label: 'Password',
|
||||||
|
width: 100,
|
||||||
|
required: true,
|
||||||
|
id: '63c0861869853127a8895321',
|
||||||
|
blockName: 'password',
|
||||||
|
blockType: 'text',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
message: [
|
||||||
|
{
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
text: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
id: '63c0865769853127a8895324',
|
||||||
|
blockType: 'message',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'terms-and-conditions',
|
||||||
|
label: 'I agree to the terms and conditions',
|
||||||
|
required: true,
|
||||||
|
id: '63c086a469853127a8895325',
|
||||||
|
blockName: 'terms-and-conditions',
|
||||||
|
blockType: 'checkbox',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
submitButtonLabel: 'Create Account',
|
||||||
|
confirmationType: 'message',
|
||||||
|
confirmationMessage: [
|
||||||
|
{
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
text: 'Your sign up submission was successful.',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
emails: [
|
||||||
|
{
|
||||||
|
emailTo: '{{email}}',
|
||||||
|
emailFrom: 'dev@payloadcms.com',
|
||||||
|
emailFromName: 'Payload Team',
|
||||||
|
subject: "You've received a new message.",
|
||||||
|
message: [
|
||||||
|
{
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
text: 'Your sign up submissioin was received successfully.',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
id: '63c0858f69853127a889531d',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
createdAt: '2023-01-12T22:16:35.480Z',
|
||||||
|
updatedAt: '2023-01-12T22:16:35.480Z',
|
||||||
|
redirect: {},
|
||||||
|
};
|
||||||
40
examples/form-builder/cms/src/server.ts
Normal file
40
examples/form-builder/cms/src/server.ts
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
import path from 'path';
|
||||||
|
import express from 'express';
|
||||||
|
import payload from 'payload';
|
||||||
|
import { seed } from './seed';
|
||||||
|
|
||||||
|
// eslint-disable-next-line
|
||||||
|
require('dotenv').config({
|
||||||
|
path: path.resolve(__dirname, '../.env'),
|
||||||
|
});
|
||||||
|
|
||||||
|
const app = express();
|
||||||
|
|
||||||
|
app.get('/', (_, res) => {
|
||||||
|
res.redirect('/admin');
|
||||||
|
});
|
||||||
|
|
||||||
|
const start = async () => {
|
||||||
|
await payload.init({
|
||||||
|
secret: process.env.PAYLOAD_SECRET,
|
||||||
|
mongoURL: process.env.MONGODB_URI,
|
||||||
|
express: app,
|
||||||
|
email: {
|
||||||
|
fromName: 'Admin',
|
||||||
|
fromAddress: 'admin@example.com',
|
||||||
|
logMockCredentials: true,
|
||||||
|
},
|
||||||
|
onInit: () => {
|
||||||
|
payload.logger.info(`Payload Admin URL: ${payload.getAdminURL()}`);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
if (process.env.PAYLOAD_SEED === 'true') {
|
||||||
|
payload.logger.info('---- SEEDING DATABASE ----');
|
||||||
|
await seed(payload);
|
||||||
|
}
|
||||||
|
|
||||||
|
app.listen(8000);
|
||||||
|
};
|
||||||
|
|
||||||
|
start();
|
||||||
32
examples/form-builder/cms/src/utilities/deepMerge.ts
Normal file
32
examples/form-builder/cms/src/utilities/deepMerge.ts
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
/**
|
||||||
|
* Simple object check.
|
||||||
|
* @param item
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
export function isObject(item: unknown): boolean {
|
||||||
|
return (item && typeof item === 'object' && !Array.isArray(item));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deep merge two objects.
|
||||||
|
* @param target
|
||||||
|
* @param ...sources
|
||||||
|
*/
|
||||||
|
export default function deepMerge<T, R>(target: T, source: R): T {
|
||||||
|
const output = { ...target };
|
||||||
|
if (isObject(target) && isObject(source)) {
|
||||||
|
Object.keys(source).forEach((key) => {
|
||||||
|
if (isObject(source[key])) {
|
||||||
|
if (!(key in target)) {
|
||||||
|
Object.assign(output, { [key]: source[key] });
|
||||||
|
} else {
|
||||||
|
output[key] = deepMerge(target[key], source[key]);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Object.assign(output, { [key]: source[key] });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
21
examples/form-builder/cms/src/utilities/formatSlug.ts
Normal file
21
examples/form-builder/cms/src/utilities/formatSlug.ts
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
import { FieldHook } from 'payload/types';
|
||||||
|
|
||||||
|
const format = (val: string): string => val.replace(/ /g, '-').replace(/[^\w-]+/g, '').toLowerCase();
|
||||||
|
|
||||||
|
const formatSlug = (fallback: string): FieldHook => ({ operation, value, originalDoc, data }) => {
|
||||||
|
if (typeof value === 'string') {
|
||||||
|
return format(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (operation === 'create') {
|
||||||
|
const fallbackData = (data && data[fallback]) || (originalDoc && originalDoc[fallback]);
|
||||||
|
|
||||||
|
if (fallbackData && typeof fallbackData === 'string') {
|
||||||
|
return format(fallbackData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return value;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default formatSlug;
|
||||||
30
examples/form-builder/cms/tsconfig.json
Normal file
30
examples/form-builder/cms/tsconfig.json
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"target": "es5",
|
||||||
|
"lib": [
|
||||||
|
"dom",
|
||||||
|
"dom.iterable",
|
||||||
|
"esnext"
|
||||||
|
],
|
||||||
|
"allowJs": true,
|
||||||
|
"strict": false,
|
||||||
|
"esModuleInterop": true,
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"outDir": "./dist",
|
||||||
|
"rootDir": "./src",
|
||||||
|
"jsx": "react",
|
||||||
|
"sourceMap": true,
|
||||||
|
"resolveJsonModule": true
|
||||||
|
},
|
||||||
|
"include": [
|
||||||
|
"src"
|
||||||
|
],
|
||||||
|
"exclude": [
|
||||||
|
"node_modules",
|
||||||
|
"dist",
|
||||||
|
"build",
|
||||||
|
],
|
||||||
|
"ts-node": {
|
||||||
|
"transpileOnly": true
|
||||||
|
}
|
||||||
|
}
|
||||||
6012
examples/form-builder/cms/yarn.lock
Normal file
6012
examples/form-builder/cms/yarn.lock
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user