Compare commits
1 Commits
v3.0.0-bet
...
fix/tab-la
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2e80b38ab6 |
@@ -1,11 +1,11 @@
|
||||
name: v2 Bug Report
|
||||
description: Report a bug for Payload v2. ONLY CRITICAL bugs will be fixed in v2.
|
||||
labels: ['status: needs-triage', 'v2']
|
||||
name: Bug Report
|
||||
description: Create a bug report for Payload
|
||||
labels: ['[possible-bug]']
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
ONLY CRITICAL bugs will be fixed in v2.
|
||||
*Note:* Feature requests should be opened as [discussions](https://github.com/payloadcms/payload/discussions/new?category=feature-requests-ideas).
|
||||
- type: input
|
||||
id: reproduction-link
|
||||
attributes:
|
||||
76
.github/ISSUE_TEMPLATE/1.bug_report_v3.yml
vendored
76
.github/ISSUE_TEMPLATE/1.bug_report_v3.yml
vendored
@@ -1,76 +0,0 @@
|
||||
name: Functionality Bug
|
||||
description: '[REPRODUCTION REQUIRED] - Create a bug report'
|
||||
labels: ['status: needs-triage', 'v3', 'validate-reproduction']
|
||||
body:
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Describe the Bug
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: input
|
||||
id: reproduction-link
|
||||
attributes:
|
||||
label: Link to the code that reproduces this issue
|
||||
description: >-
|
||||
_REQUIRED_: Please provide a link to your reproduction. Note, if the URL is invalid (404 or a private repository), we may close the issue.
|
||||
Either use `npx create-payload-app@beta -t blank` then push to a repo or follow the [reproduction-guide](https://github.com/payloadcms/payload/blob/main/.github/reproduction-guide.md) for more information.
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Reproduction Steps
|
||||
description: Steps to reproduce the behavior, please provide a clear description of how to reproduce the issue, based on the linked minimal reproduction. Screenshots can be provided in the issue body below. If using code blocks, make sure that [syntax highlighting is correct](https://docs.github.com/en/get-started/writing-on-github/working-with-advanced-formatting/creating-and-highlighting-code-blocks#syntax-highlighting) and double check that the rendered preview is not broken.
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: dropdown
|
||||
attributes:
|
||||
label: Which area(s) are affected? (Select all that apply)
|
||||
multiple: true
|
||||
options:
|
||||
- 'Not sure'
|
||||
- 'area: core'
|
||||
- 'area: docs'
|
||||
- 'area: templates'
|
||||
- 'area: ui'
|
||||
- 'db-mongodb'
|
||||
- 'db-postgres'
|
||||
- 'db-sqlite'
|
||||
- 'db-vercel-postgres'
|
||||
- 'plugin: cloud'
|
||||
- 'plugin: cloud-storage'
|
||||
- 'plugin: form-builder'
|
||||
- 'plugin: nested-docs'
|
||||
- 'plugin: richtext-lexical'
|
||||
- 'plugin: richtext-slate'
|
||||
- 'plugin: search'
|
||||
- 'plugin: sentry'
|
||||
- 'plugin: seo'
|
||||
- 'plugin: stripe'
|
||||
- 'plugin: other'
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Environment Info
|
||||
description: Paste output from `pnpm payload info` (>= beta.92) _or_ Payload, Node.js, and Next.js versions.
|
||||
render: text
|
||||
placeholder: |
|
||||
Payload:
|
||||
Node.js:
|
||||
Next.js:
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: Before submitting the issue, go through the steps you've written down to make sure the steps provided are detailed and clear.
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: Contributors should be able to follow the steps provided in order to reproduce the bug.
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: These steps are used to add integration tests to ensure the same issue does not happen again. Thanks in advance!
|
||||
40
.github/ISSUE_TEMPLATE/2.design_issue.yml
vendored
40
.github/ISSUE_TEMPLATE/2.design_issue.yml
vendored
@@ -1,40 +0,0 @@
|
||||
name: Design Issue
|
||||
description: '[SCREENSHOT REQUIRED] - Create a design issue report'
|
||||
labels: ['status: needs-triage', 'v3', 'area: ui']
|
||||
body:
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Describe the Bug.
|
||||
description: >-
|
||||
_REQUIRED:_ Please a screenshot/video of the issue along with a detailed description of the problem.
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Reproduction Steps
|
||||
description: Steps to reproduce the behavior, please provide a clear description of how to reproduce the issue, based on the linked minimal reproduction. Screenshots can be provided in the issue body below. If using code blocks, make sure that [syntax highlighting is correct](https://docs.github.com/en/get-started/writing-on-github/working-with-advanced-formatting/creating-and-highlighting-code-blocks#syntax-highlighting) and double check that the rendered preview is not broken.
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Environment Info
|
||||
description: Paste output from `pnpm payload info` (>= beta.92) _or_ Payload, Node.js, and Next.js versions.
|
||||
render: text
|
||||
placeholder: |
|
||||
Payload:
|
||||
Node.js:
|
||||
Next.js:
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: Before submitting the issue, go through the steps you've written down to make sure the steps provided are detailed and clear.
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: Contributors should be able to follow the steps provided in order to reproduce the bug.
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: These steps are used to add integration tests to ensure the same issue does not happen again. Thanks in advance!
|
||||
32
.github/PULL_REQUEST_TEMPLATE.md
vendored
32
.github/PULL_REQUEST_TEMPLATE.md
vendored
@@ -1,23 +1,23 @@
|
||||
<!--
|
||||
## Description
|
||||
|
||||
Thank you for the PR! Please go through the checklist below and make sure you've completed all the steps.
|
||||
<!-- Please include a summary of the pull request and any related issues it fixes. Please also include relevant motivation and context. -->
|
||||
|
||||
Please review the [CONTRIBUTING.md](https://github.com/payloadcms/payload/blob/main/CONTRIBUTING.md) document in this repository if you haven't already.
|
||||
- [ ] I have read and understand the [CONTRIBUTING.md](https://github.com/payloadcms/payload/blob/main/CONTRIBUTING.md) document in this repository.
|
||||
|
||||
The following items will ensure that your PR is handled as smoothly as possible:
|
||||
## Type of change
|
||||
|
||||
- PR Title must follow conventional commits format. For example, `feat: my new feature`, `fix(plugin-seo): my fix`.
|
||||
- Minimal description explained as if explained to someone not immediately familiar with the code.
|
||||
- Provide before/after screenshots or code diffs if applicable.
|
||||
- Link any related issues/discussions from GitHub or Discord.
|
||||
- Add review comments if necessary to explain to the reviewer the logic behind a change
|
||||
<!-- Please delete options that are not relevant. -->
|
||||
|
||||
### What?
|
||||
- [ ] Chore (non-breaking change which does not add functionality)
|
||||
- [ ] Bug fix (non-breaking change which fixes an issue)
|
||||
- [ ] New feature (non-breaking change which adds functionality)
|
||||
- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)
|
||||
- [ ] Change to the [templates](https://github.com/payloadcms/payload/tree/main/templates) directory (does not affect core functionality)
|
||||
- [ ] Change to the [examples](https://github.com/payloadcms/payload/tree/main/examples) directory (does not affect core functionality)
|
||||
- [ ] This change requires a documentation update
|
||||
|
||||
### Why?
|
||||
## Checklist:
|
||||
|
||||
### How?
|
||||
|
||||
Fixes #
|
||||
|
||||
-->
|
||||
- [ ] I have added tests that prove my fix is effective or that my feature works
|
||||
- [ ] Existing test suite passes locally with my changes
|
||||
- [ ] I have made corresponding changes to the documentation
|
||||
|
||||
22
.github/actions/triage/LICENSE
vendored
22
.github/actions/triage/LICENSE
vendored
@@ -1,22 +0,0 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2024 Payload <info@payloadcms.com>. All modification and additions are copyright of Payload.
|
||||
|
||||
---
|
||||
|
||||
Original license:
|
||||
ISC License
|
||||
|
||||
Copyright (c) 2023, Balázs Orbán
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
21
.github/actions/triage/README.md
vendored
21
.github/actions/triage/README.md
vendored
@@ -1,21 +0,0 @@
|
||||
# Triage
|
||||
|
||||
Modified version of https://github.com/balazsorban44/nissuer
|
||||
|
||||
## Modifications
|
||||
|
||||
- Port to TypeScript
|
||||
- Remove issue locking
|
||||
- Remove reproduction blocklist
|
||||
- Uses `@vercel/ncc` for packaging
|
||||
|
||||
## Development
|
||||
|
||||
> [!IMPORTANT]
|
||||
> Whenever a modification is made to the action, the action built to `dist` must be committed to the repository.
|
||||
|
||||
This is done by running:
|
||||
|
||||
```sh
|
||||
pnpm build
|
||||
```
|
||||
40
.github/actions/triage/action.yml
vendored
40
.github/actions/triage/action.yml
vendored
@@ -1,40 +0,0 @@
|
||||
name: Triage
|
||||
description: Initial triage for issues
|
||||
|
||||
inputs:
|
||||
reproduction-comment:
|
||||
description: 'Either a string or a path to a .md file inside the repository. Example: ".github/invalid-reproduction.md"'
|
||||
default: '.github/invalid-reproduction.md'
|
||||
reproduction-hosts:
|
||||
description: 'Comma-separated list of hostnames that are allowed for reproductions. Example: "github.com,codesandbox.io"'
|
||||
default: github.com
|
||||
reproduction-invalid-label:
|
||||
description: 'Label to apply to issues without a valid reproduction. Example: "invalid-reproduction"'
|
||||
default: 'invalid-reproduction'
|
||||
reproduction-issue-labels:
|
||||
description: 'Comma-separated list of issue labels. If configured, only verify reproduction URLs of issues with one of these labels present. Adding a comma at the end will handle non-labeled issues as invalid. Example: "bug,", will consider issues with the label "bug" or no label.'
|
||||
default: ''
|
||||
reproduction-link-section:
|
||||
description: 'A regular expression string with "(.*)" matching a valid URL in the issue body. The result is trimmed. Example: "### Link to reproduction(.*)### To reproduce"'
|
||||
default: '### Link to reproduction(.*)### To reproduce'
|
||||
tag-only:
|
||||
description: Log and tag only. Do not perform closing or commenting actions.
|
||||
default: false
|
||||
|
||||
runs:
|
||||
using: 'composite'
|
||||
steps:
|
||||
- name: Checkout code
|
||||
if: ${{ github.event_name != 'pull_request' }}
|
||||
uses: actions/checkout@v4
|
||||
- name: Run action
|
||||
run: node ${{ github.action_path }}/dist/index.js
|
||||
shell: sh
|
||||
# https://github.com/actions/runner/issues/665#issuecomment-676581170
|
||||
env:
|
||||
'INPUT_REPRODUCTION_COMMENT': ${{inputs.reproduction-comment}}
|
||||
'INPUT_REPRODUCTION_HOSTS': ${{inputs.reproduction-hosts}}
|
||||
'INPUT_REPRODUCTION_INVALID_LABEL': ${{inputs.reproduction-invalid-label}}
|
||||
'INPUT_REPRODUCTION_ISSUE_LABELS': ${{inputs.reproduction-issue-labels}}
|
||||
'INPUT_REPRODUCTION_LINK_SECTION': ${{inputs.reproduction-link-section}}
|
||||
'INPUT_TAG_ONLY': ${{inputs.tag-only}}
|
||||
7
.github/actions/triage/jest.config.js
vendored
7
.github/actions/triage/jest.config.js
vendored
@@ -1,7 +0,0 @@
|
||||
module.exports = {
|
||||
testEnvironment: 'node',
|
||||
testPathIgnorePatterns: ['/node_modules/', '<rootDir>/dist/'],
|
||||
transform: {
|
||||
'^.+\\.(t|j)sx?$': ['@swc/jest'],
|
||||
},
|
||||
}
|
||||
34
.github/actions/triage/package.json
vendored
34
.github/actions/triage/package.json
vendored
@@ -1,34 +0,0 @@
|
||||
{
|
||||
"name": "triage",
|
||||
"version": "0.0.0",
|
||||
"private": true,
|
||||
"description": "GitHub Action to triage new issues",
|
||||
"license": "MIT",
|
||||
"main": "dist/index.js",
|
||||
"scripts": {
|
||||
"build": "pnpm build:typecheck && pnpm build:ncc",
|
||||
"build:ncc": "ncc build src/index.ts -t -o dist",
|
||||
"build:typecheck": "tsc",
|
||||
"clean": "rimraf dist",
|
||||
"test": "jest"
|
||||
},
|
||||
"dependencies": {
|
||||
"@actions/core": "^1.3.0",
|
||||
"@actions/github": "^5.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@octokit/webhooks-types": "^7.5.1",
|
||||
"@swc/jest": "^0.2.36",
|
||||
"@types/jest": "^27.5.2",
|
||||
"@types/node": "^20.16.5",
|
||||
"@typescript-eslint/eslint-plugin": "^4.33.0",
|
||||
"@typescript-eslint/parser": "^4.33.0",
|
||||
"@vercel/ncc": "0.38.1",
|
||||
"concurrently": "^8.2.2",
|
||||
"eslint": "^7.32.0",
|
||||
"jest": "^29.7.0",
|
||||
"prettier": "^3.3.3",
|
||||
"ts-jest": "^26.5.6",
|
||||
"typescript": "^4.9.5"
|
||||
}
|
||||
}
|
||||
5419
.github/actions/triage/pnpm-lock.yaml
generated
vendored
5419
.github/actions/triage/pnpm-lock.yaml
generated
vendored
File diff suppressed because it is too large
Load Diff
195
.github/actions/triage/src/index.ts
vendored
195
.github/actions/triage/src/index.ts
vendored
@@ -1,195 +0,0 @@
|
||||
import { debug, error, getBooleanInput, getInput, info, setFailed } from '@actions/core'
|
||||
|
||||
import { context, getOctokit } from '@actions/github'
|
||||
import { readFile, access } from 'node:fs/promises'
|
||||
import { join } from 'node:path'
|
||||
|
||||
// Ensure GITHUB_TOKEN and GITHUB_WORKSPACE are present
|
||||
if (!process.env.GITHUB_TOKEN) throw new TypeError('No GITHUB_TOKEN provided')
|
||||
if (!process.env.GITHUB_WORKSPACE) throw new TypeError('Not a GitHub workspace')
|
||||
|
||||
// Define the configuration object
|
||||
interface Config {
|
||||
invalidLink: {
|
||||
comment: string
|
||||
bugLabels: string[]
|
||||
hosts: string[]
|
||||
label: string
|
||||
linkSection: string
|
||||
}
|
||||
tagOnly: boolean
|
||||
token: string
|
||||
workspace: string
|
||||
}
|
||||
|
||||
const config: Config = {
|
||||
invalidLink: {
|
||||
comment: getInput('reproduction_comment') || '.github/invalid-reproduction.md',
|
||||
bugLabels: getInput('reproduction_issue_labels')
|
||||
.split(',')
|
||||
.map((l) => l.trim()),
|
||||
hosts: (getInput('reproduction_hosts') || 'github.com').split(',').map((h) => h.trim()),
|
||||
label: getInput('reproduction_invalid_label') || 'invalid-reproduction',
|
||||
linkSection:
|
||||
getInput('reproduction_link_section') || '### Link to reproduction(.*)### To reproduce',
|
||||
},
|
||||
tagOnly: getBooleanOrUndefined('tag_only') || false,
|
||||
token: process.env.GITHUB_TOKEN,
|
||||
workspace: process.env.GITHUB_WORKSPACE,
|
||||
}
|
||||
|
||||
// Attempt to parse JSON, return parsed object or error
|
||||
function tryParse(json: string): Record<string, unknown> {
|
||||
try {
|
||||
return JSON.parse(json)
|
||||
} catch (e) {
|
||||
setFailed(`Could not parse JSON: ${e instanceof Error ? e.message : e}`)
|
||||
return {}
|
||||
}
|
||||
}
|
||||
|
||||
// Retrieves a boolean input or undefined based on environment variables
|
||||
function getBooleanOrUndefined(value: string): boolean | undefined {
|
||||
const variable = process.env[`INPUT_${value.toUpperCase()}`]
|
||||
return variable === undefined || variable === '' ? undefined : getBooleanInput(value)
|
||||
}
|
||||
|
||||
// Returns the appropriate label match type
|
||||
function getLabelMatch(value: string | undefined): 'name' | 'description' {
|
||||
return value === 'name' ? 'name' : 'description'
|
||||
}
|
||||
|
||||
// Function to check if an issue contains a valid reproduction link
|
||||
async function checkValidReproduction(): Promise<void> {
|
||||
const { issue, action } = context.payload as {
|
||||
issue: { number: number; body: string; labels: { name: string }[] } | undefined
|
||||
action: string
|
||||
}
|
||||
|
||||
if (action !== 'opened' || !issue?.body) return
|
||||
|
||||
const labels = issue.labels.map((l) => l.name)
|
||||
|
||||
const issueMatchingLabel =
|
||||
labels.length &&
|
||||
config.invalidLink.bugLabels.length &&
|
||||
labels.some((l) => config.invalidLink.bugLabels.includes(l))
|
||||
|
||||
if (!issueMatchingLabel) {
|
||||
info(
|
||||
`Issue #${issue.number} does not match required labels: ${config.invalidLink.bugLabels.join(', ')}`,
|
||||
)
|
||||
info(`Issue labels: ${labels.join(', ')}`)
|
||||
return
|
||||
}
|
||||
|
||||
info(`Issue #${issue.number} labels: ${labels.join(', ')}`)
|
||||
|
||||
const { rest: client } = getOctokit(config.token)
|
||||
const common = { ...context.repo, issue_number: issue.number }
|
||||
|
||||
const labelsToRemove = labels.filter((l) => config.invalidLink.bugLabels.includes(l))
|
||||
|
||||
if (await isValidReproduction(issue.body)) {
|
||||
await Promise.all(
|
||||
labelsToRemove.map((label) => client.issues.removeLabel({ ...common, name: label })),
|
||||
)
|
||||
|
||||
return info(`Issue #${issue.number} contains a valid reproduction 💚`)
|
||||
}
|
||||
|
||||
info(`Invalid reproduction, issue will be closed/labeled/commented...`)
|
||||
|
||||
// Adjust labels
|
||||
await Promise.all(
|
||||
labelsToRemove.map((label) => client.issues.removeLabel({ ...common, name: label })),
|
||||
)
|
||||
info(`Issue #${issue.number} - validate label removed`)
|
||||
await client.issues.addLabels({ ...common, labels: [config.invalidLink.label] })
|
||||
info(`Issue #${issue.number} - labeled`)
|
||||
|
||||
// If tagOnly, do not close or comment
|
||||
if (config.tagOnly) {
|
||||
info('Tag-only enabled, no closing/commenting actions taken')
|
||||
return
|
||||
}
|
||||
|
||||
// Perform closing and commenting actions
|
||||
await client.issues.update({ ...common, state: 'closed' })
|
||||
info(`Issue #${issue.number} - closed`)
|
||||
|
||||
const comment = join(config.workspace, config.invalidLink.comment)
|
||||
await client.issues.createComment({ ...common, body: await getCommentBody(comment) })
|
||||
info(`Issue #${issue.number} - commented`)
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if an issue contains a valid/accessible link to a reproduction.
|
||||
*
|
||||
* Returns `true` if the link is valid.
|
||||
* @param body - The body content of the issue
|
||||
*/
|
||||
async function isValidReproduction(body: string): Promise<boolean> {
|
||||
const linkSectionRe = new RegExp(config.invalidLink.linkSection, 'is')
|
||||
const link = body.match(linkSectionRe)?.[1]?.trim()
|
||||
|
||||
if (!link) {
|
||||
info('Missing link')
|
||||
info(`Link section regex: ${linkSectionRe}`)
|
||||
info(`Link section: ${body}`)
|
||||
return false
|
||||
}
|
||||
|
||||
info(`Checking validity of link: ${link}`)
|
||||
|
||||
if (!URL.canParse(link)) {
|
||||
info(`Invalid URL: ${link}`)
|
||||
return false
|
||||
}
|
||||
|
||||
const url = new URL(link)
|
||||
|
||||
if (!config.invalidLink.hosts.includes(url.hostname)) {
|
||||
info('Link did not match allowed reproduction hosts')
|
||||
return false
|
||||
}
|
||||
|
||||
try {
|
||||
// Verify that the link can be accessed
|
||||
const response = await fetch(link)
|
||||
const isOk = response.status < 400 || response.status >= 500
|
||||
|
||||
info(`Link status: ${response.status}`)
|
||||
if (!isOk) {
|
||||
info(`Link returned status ${response.status}`)
|
||||
}
|
||||
return isOk
|
||||
} catch (error) {
|
||||
info(`Error fetching link: ${(error as Error).message}`)
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return either a file's content or a string
|
||||
* @param {string} pathOrComment
|
||||
*/
|
||||
async function getCommentBody(pathOrComment: string) {
|
||||
try {
|
||||
await access(pathOrComment)
|
||||
return await readFile(pathOrComment, 'utf8')
|
||||
} catch (error: any) {
|
||||
if (error.code === 'ENOENT') return pathOrComment
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
async function run() {
|
||||
const { token, workspace, ...safeConfig } = config
|
||||
info('Configuration:')
|
||||
info(JSON.stringify(safeConfig, null, 2))
|
||||
|
||||
await checkValidReproduction()
|
||||
}
|
||||
|
||||
run().catch(setFailed)
|
||||
15
.github/actions/triage/tsconfig.json
vendored
15
.github/actions/triage/tsconfig.json
vendored
@@ -1,15 +0,0 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "es5",
|
||||
"lib": ["es2020.string"],
|
||||
"noEmit": true,
|
||||
"strict": true,
|
||||
"noUnusedLocals": false, // Undo this
|
||||
"noImplicitReturns": true,
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"downlevelIteration": true,
|
||||
"skipLibCheck": true,
|
||||
},
|
||||
"exclude": ["src/**/*.test.ts"]
|
||||
}
|
||||
18
.github/comments/invalid-reproduction.md
vendored
18
.github/comments/invalid-reproduction.md
vendored
@@ -1,18 +0,0 @@
|
||||
We cannot recreate the issue with the provided information. **Please add a reproduction in order for us to be able to investigate.**
|
||||
|
||||
### Why was this issue marked with the `invalid-reproduction` label?
|
||||
|
||||
To be able to investigate, we need access to a reproduction to identify what triggered the issue. We prefer a link to a public GitHub repository created with `create-payload-app@beta -t blank` or a forked/branched version of this repository with tests added (more info in the [reproduction-guide](https://github.com/payloadcms/payload/blob/main/.github/reproduction-guide.md)).
|
||||
|
||||
To make sure the issue is resolved as quickly as possible, please make sure that the reproduction is as **minimal** as possible. This means that you should **remove unnecessary code, files, and dependencies** that do not contribute to the issue. Ensure your reproduction does not depend on secrets, 3rd party registries, private dependencies, or any other data that cannot be made public. Avoid a reproduction including a whole monorepo (unless relevant to the issue). The easier it is to reproduce the issue, the quicker we can help.
|
||||
|
||||
Please test your reproduction against the latest version of Payload to make sure your issue has not already been fixed.
|
||||
|
||||
### I added a link, why was it still marked?
|
||||
|
||||
Ensure the link is pointing to a codebase that is accessible (e.g. not a private repository). "[example.com](http://example.com/)", "n/a", "will add later", etc. are not acceptable links -- we need to see a public codebase. See the above section for accepted links.
|
||||
|
||||
### Useful Resources
|
||||
|
||||
- [Reproduction Guide](https://github.com/payloadcms/payload/blob/main/.github/reproduction-guide.md)
|
||||
- [Contributing to Payload](https://www.youtube.com/watch?v=08Qa3ggR9rw)
|
||||
74
.github/dependabot.yml
vendored
74
.github/dependabot.yml
vendored
@@ -1,74 +0,0 @@
|
||||
# docs: https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
|
||||
|
||||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: github-actions
|
||||
directories:
|
||||
- /
|
||||
- /.github/workflows
|
||||
- /.github/actions/* # Not working until resolved: https://github.com/dependabot/dependabot-core/issues/6345
|
||||
- /.github/actions/setup
|
||||
target-branch: beta
|
||||
schedule:
|
||||
interval: monthly
|
||||
timezone: America/Detroit
|
||||
time: '06:00'
|
||||
groups:
|
||||
github_actions:
|
||||
patterns:
|
||||
- '*'
|
||||
|
||||
- package-ecosystem: npm
|
||||
directory: /
|
||||
target-branch: beta
|
||||
schedule:
|
||||
interval: weekly
|
||||
day: sunday
|
||||
timezone: America/Detroit
|
||||
time: '06:00'
|
||||
commit-message:
|
||||
prefix: 'chore(deps)'
|
||||
labels:
|
||||
- dependencies
|
||||
groups:
|
||||
production-deps:
|
||||
dependency-type: production
|
||||
update-types:
|
||||
- minor
|
||||
- patch
|
||||
patterns:
|
||||
- '*'
|
||||
exclude-patterns:
|
||||
- 'drizzle*'
|
||||
dev-deps:
|
||||
dependency-type: development
|
||||
update-types:
|
||||
- minor
|
||||
- patch
|
||||
patterns:
|
||||
- '*'
|
||||
exclude-patterns:
|
||||
- 'drizzle*'
|
||||
|
||||
# Only bump patch versions for 2.x
|
||||
- package-ecosystem: npm
|
||||
directory: /
|
||||
target-branch: main
|
||||
schedule:
|
||||
interval: weekly
|
||||
day: sunday
|
||||
timezone: America/Detroit
|
||||
time: '06:00'
|
||||
commit-message:
|
||||
prefix: 'chore(deps)'
|
||||
labels:
|
||||
- dependencies
|
||||
groups:
|
||||
production-deps:
|
||||
dependency-type: production
|
||||
update-types:
|
||||
- patch
|
||||
patterns:
|
||||
- '*'
|
||||
exclude-patterns:
|
||||
- 'drizzle*'
|
||||
49
.github/pnpm-lock.yaml
generated
vendored
49
.github/pnpm-lock.yaml
generated
vendored
@@ -55,55 +55,6 @@ importers:
|
||||
specifier: ^4.9.5
|
||||
version: 4.9.5
|
||||
|
||||
actions/triage:
|
||||
dependencies:
|
||||
'@actions/core':
|
||||
specifier: ^1.3.0
|
||||
version: 1.10.1
|
||||
'@actions/github':
|
||||
specifier: ^5.0.0
|
||||
version: 5.1.1
|
||||
devDependencies:
|
||||
'@octokit/webhooks-types':
|
||||
specifier: ^7.5.1
|
||||
version: 7.5.1
|
||||
'@swc/jest':
|
||||
specifier: ^0.2.36
|
||||
version: 0.2.36(@swc/core@1.7.26)
|
||||
'@types/jest':
|
||||
specifier: ^27.5.2
|
||||
version: 27.5.2
|
||||
'@types/node':
|
||||
specifier: ^20.16.5
|
||||
version: 20.16.5
|
||||
'@typescript-eslint/eslint-plugin':
|
||||
specifier: ^4.33.0
|
||||
version: 4.33.0(@typescript-eslint/parser@4.33.0(eslint@7.32.0)(typescript@4.9.5))(eslint@7.32.0)(typescript@4.9.5)
|
||||
'@typescript-eslint/parser':
|
||||
specifier: ^4.33.0
|
||||
version: 4.33.0(eslint@7.32.0)(typescript@4.9.5)
|
||||
'@vercel/ncc':
|
||||
specifier: 0.38.1
|
||||
version: 0.38.1
|
||||
concurrently:
|
||||
specifier: ^8.2.2
|
||||
version: 8.2.2
|
||||
eslint:
|
||||
specifier: ^7.32.0
|
||||
version: 7.32.0
|
||||
jest:
|
||||
specifier: ^29.7.0
|
||||
version: 29.7.0(@types/node@20.16.5)
|
||||
prettier:
|
||||
specifier: ^3.3.3
|
||||
version: 3.3.3
|
||||
ts-jest:
|
||||
specifier: ^26.5.6
|
||||
version: 26.5.6(jest@29.7.0(@types/node@20.16.5))(typescript@4.9.5)
|
||||
typescript:
|
||||
specifier: ^4.9.5
|
||||
version: 4.9.5
|
||||
|
||||
packages:
|
||||
|
||||
'@actions/core@1.10.1':
|
||||
|
||||
68
.github/workflows/label-author.yml
vendored
Normal file
68
.github/workflows/label-author.yml
vendored
Normal file
@@ -0,0 +1,68 @@
|
||||
name: label-author
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [opened]
|
||||
issues:
|
||||
types: [opened]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
issues: write
|
||||
|
||||
jobs:
|
||||
debug-context:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: View context attributes
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: console.log(context)
|
||||
|
||||
label-created-by:
|
||||
name: Label pr/issue on opening
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Tag with 'created-by'
|
||||
uses: actions/github-script@v7
|
||||
if: github.event.action == 'opened'
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
script: |
|
||||
const type = context.payload.pull_request ? 'pull_request' : 'issue';
|
||||
const association = context.payload[type].author_association;
|
||||
let label = '';
|
||||
if (
|
||||
association === 'MEMBER' ||
|
||||
association === 'OWNER' ||
|
||||
[
|
||||
'denolfe',
|
||||
'jmikrut',
|
||||
'danribbens',
|
||||
|
||||
'alessiogr',
|
||||
'jacobsfletch',
|
||||
'jarrodmflesch',
|
||||
'jesschowdhury',
|
||||
'kendelljoseph',
|
||||
'patrikkozak',
|
||||
'paulpopus',
|
||||
'r1tsuu',
|
||||
'tylandavis',
|
||||
].includes(context.actor.toLowerCase())
|
||||
) {
|
||||
label = 'created-by: Payload team';
|
||||
} else if (association === 'CONTRIBUTOR') {
|
||||
label = 'created-by: Contributor';
|
||||
}
|
||||
|
||||
if (!label) return;
|
||||
|
||||
github.rest.issues.addLabels({
|
||||
issue_number: context.issue.number,
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
labels: [label],
|
||||
});
|
||||
console.log(`Added '${label}' label`);
|
||||
116
.github/workflows/label-on-change.yml
vendored
116
.github/workflows/label-on-change.yml
vendored
@@ -1,116 +0,0 @@
|
||||
name: label-on-change
|
||||
|
||||
on:
|
||||
# https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#pull_request_target
|
||||
issues:
|
||||
types:
|
||||
- assigned
|
||||
- closed
|
||||
- labeled
|
||||
- reopened
|
||||
|
||||
# TODO: Handle labeling on comment
|
||||
|
||||
jobs:
|
||||
on-labeled-ensure-one-status:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
issues: write
|
||||
# Only run on issue labeled and if label starts with 'status:'
|
||||
if: github.event.action == 'labeled' && startsWith(github.event.label.name, 'status:')
|
||||
steps:
|
||||
- name: Ensure only one status label
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
script: |
|
||||
// Get all labels that start with 'status:' and are not the incoming label
|
||||
const incomingLabelName = context.payload.label.name;
|
||||
const labelNamesToRemove = context.payload.issue.labels
|
||||
.filter(label => label.name.startsWith('status:') && label.name !== incomingLabelName)
|
||||
.map(label => label.name);
|
||||
|
||||
if (!labelNamesToRemove.length) {
|
||||
console.log('No labels to remove');
|
||||
return;
|
||||
}
|
||||
|
||||
console.log(`Labels to remove: '${labelNamesToRemove}'`);
|
||||
|
||||
// If there is more than one status label, remove all but the incoming label
|
||||
for (const labelName of labelNamesToRemove) {
|
||||
await github.rest.issues.removeLabel({
|
||||
issue_number: context.issue.number,
|
||||
name: labelName,
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
});
|
||||
console.log(`Removed '${labelName}' label`);
|
||||
}
|
||||
|
||||
on-issue-close:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
issues: write
|
||||
if: github.event.action == 'closed'
|
||||
steps:
|
||||
- name: Remove all labels on issue close
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
script: |
|
||||
// Get all labels that start with 'status:' and 'stale'
|
||||
const labelNamesToRemove = context.payload.issue.labels
|
||||
.filter(label => label.name.startsWith('status:') || label.name === 'stale')
|
||||
.map(label => label.name);
|
||||
|
||||
if (!labelNamesToRemove.length) {
|
||||
console.log('No labels to remove');
|
||||
return;
|
||||
}
|
||||
|
||||
console.log(`Labels to remove: '${labelNamesToRemove}'`);
|
||||
|
||||
for (const labelName of labelNamesToRemove) {
|
||||
await github.rest.issues.removeLabel({
|
||||
issue_number: context.issue.number,
|
||||
name: labelName,
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
});
|
||||
console.log(`Removed '${labelName}' label`);
|
||||
}
|
||||
|
||||
on-issue-reopen:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
issues: write
|
||||
if: github.event.action == 'reopened'
|
||||
steps:
|
||||
- name: Add needs-triage label on issue reopen
|
||||
uses: actions-ecosystem/action-add-labels@v1
|
||||
with:
|
||||
labels: 'status: needs-triage'
|
||||
|
||||
on-issue-assigned:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
issues: write
|
||||
if: >
|
||||
github.event.action == 'assigned' &&
|
||||
contains(github.event.issue.labels.*.name, 'status: needs-triage')
|
||||
steps:
|
||||
- name: Remove needs-triage label on issue assign
|
||||
uses: actions-ecosystem/action-remove-labels@v1
|
||||
with:
|
||||
labels: 'status: needs-triage'
|
||||
|
||||
# on-pr-merge:
|
||||
# runs-on: ubuntu-latest
|
||||
# if: github.event.pull_request.merged == true
|
||||
# steps:
|
||||
|
||||
# on-pr-close:
|
||||
# runs-on: ubuntu-latest
|
||||
# if: github.event_name == 'pull_request_target' && github.event.pull_request.merged == false
|
||||
# steps:
|
||||
26
.github/workflows/lock-issues.yml
vendored
26
.github/workflows/lock-issues.yml
vendored
@@ -1,26 +0,0 @@
|
||||
name: lock-issues
|
||||
|
||||
on:
|
||||
schedule:
|
||||
# Run nightly at 12am EST
|
||||
- cron: '0 4 * * *'
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
issues: write
|
||||
|
||||
jobs:
|
||||
lock_issues:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Lock issues
|
||||
uses: dessant/lock-threads@v5
|
||||
with:
|
||||
process-only: 'issues'
|
||||
issue-inactive-days: '1'
|
||||
exclude-any-issue-labels: 'status: awaiting-reply'
|
||||
log-output: true
|
||||
issue-comment: >
|
||||
This issue has been automatically locked.
|
||||
|
||||
Please open a new issue if this issue persists with any additional detail.
|
||||
3
.github/workflows/pr-title.yml
vendored
3
.github/workflows/pr-title.yml
vendored
@@ -5,6 +5,7 @@ on:
|
||||
types:
|
||||
- opened
|
||||
- edited
|
||||
- synchronize
|
||||
|
||||
permissions:
|
||||
pull-requests: write
|
||||
@@ -46,7 +47,7 @@ jobs:
|
||||
live-preview
|
||||
live-preview-react
|
||||
next
|
||||
payload-cloud
|
||||
payload
|
||||
plugin-cloud
|
||||
plugin-cloud-storage
|
||||
plugin-form-builder
|
||||
|
||||
42
.github/workflows/stale.yml
vendored
42
.github/workflows/stale.yml
vendored
@@ -1,42 +0,0 @@
|
||||
name: stale
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
stale:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
issues: write
|
||||
pull-requests: write
|
||||
steps:
|
||||
- uses: actions/stale@v9
|
||||
id: stale
|
||||
with:
|
||||
debug-only: true
|
||||
days-before-stale: 90
|
||||
days-before-close: 7
|
||||
ascending: true
|
||||
operations-per-run: 300
|
||||
|
||||
# Ignore all assigned
|
||||
exempt-all-assignees: false
|
||||
|
||||
# Issues
|
||||
stale-issue-label: 'stale'
|
||||
exempt-issue-labels: 'blocked,must,should,keep,created-by: Payload team,created-by: Contributor'
|
||||
stale-issue-message: >
|
||||
This issue has been marked as stale due to lack of activity. To keep the ticket open, please indicate that it is still relevant in a comment below.
|
||||
close-issue-message: >
|
||||
This issue was automatically closed due to lack of activity.
|
||||
|
||||
# Pull Requests
|
||||
stale-pr-label: 'stale'
|
||||
exempt-pr-labels: 'blocked,must,should,keep,created-by: Payload team,created-by: Contributor'
|
||||
stale-pr-message: >
|
||||
This PR is stale due to lack of activity. To keep the PR open, please indicate that it is still relevant in a comment below.
|
||||
close-pr-message: >
|
||||
This pull request was automatically closed due to lack of activity.
|
||||
|
||||
- name: Print outputs
|
||||
run: echo ${{ format('{0},{1}', toJSON(steps.stale.outputs.staled-issues-prs), toJSON(steps.stale.outputs.closed-issues-prs)) }}
|
||||
102
.github/workflows/triage.yml
vendored
102
.github/workflows/triage.yml
vendored
@@ -1,102 +0,0 @@
|
||||
name: triage
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types:
|
||||
- opened
|
||||
issues:
|
||||
types:
|
||||
- opened
|
||||
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
issues: write
|
||||
pull-requests: write
|
||||
|
||||
jobs:
|
||||
debug-context:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: View context attributes
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: console.log({ context })
|
||||
|
||||
label-created-by:
|
||||
name: label-on-open
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Tag with 'created-by'
|
||||
uses: actions/github-script@v7
|
||||
if: github.event.action == 'opened'
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
script: |
|
||||
const payloadTeamUsernames = [
|
||||
'denolfe',
|
||||
'jmikrut',
|
||||
'DanRibbens',
|
||||
'jacobsfletch',
|
||||
'JarrodMFlesch',
|
||||
'AlessioGr',
|
||||
'JessChowdhury',
|
||||
'kendelljoseph',
|
||||
'PatrikKozak',
|
||||
'tylandavis',
|
||||
'paulpopus',
|
||||
'r1tsuu',
|
||||
'GermanJablo',
|
||||
];
|
||||
|
||||
const type = context.payload.pull_request ? 'pull_request' : 'issue';
|
||||
|
||||
const isTeamMember = payloadTeamUsernames
|
||||
.map(n => n.toLowerCase())
|
||||
.includes(context.payload[type].user.login.toLowerCase());
|
||||
|
||||
if (isTeamMember) {
|
||||
github.rest.issues.addLabels({
|
||||
issue_number: context.issue.number,
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
labels: ['created-by: Payload team'],
|
||||
});
|
||||
console.log(`Added 'created-by: Payload team' label`);
|
||||
return;
|
||||
}
|
||||
|
||||
const association = context.payload[type].author_association;
|
||||
let label = ''
|
||||
if (association === 'MEMBER' || association === 'OWNER') {
|
||||
label = 'created-by: Payload team';
|
||||
} else if (association === 'CONTRIBUTOR') {
|
||||
label = 'created-by: Contributor';
|
||||
}
|
||||
|
||||
if (!label) return;
|
||||
|
||||
github.rest.issues.addLabels({
|
||||
issue_number: context.issue.number,
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
labels: [label],
|
||||
});
|
||||
console.log(`Added '${label}' label.`);
|
||||
|
||||
triage:
|
||||
name: initial-triage
|
||||
if: github.event_name == 'issues'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
- uses: ./.github/actions/triage
|
||||
with:
|
||||
reproduction-comment: '.github/comments/invalid-reproduction.md'
|
||||
reproduction-link-section: '### Link to the code that reproduces this issue(.*)### Reproduction Steps'
|
||||
reproduction-issue-labels: 'validate-reproduction'
|
||||
tag-only: 'true'
|
||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -314,6 +314,3 @@ test/app/(payload)/admin/importMap.js
|
||||
/test/app/(payload)/admin/importMap.js
|
||||
test/pnpm-lock.yaml
|
||||
test/databaseAdapter.js
|
||||
/filename-compound-index
|
||||
/media-with-relation-preview
|
||||
/media-without-relation-preview
|
||||
|
||||
30
.vscode/launch.json
vendored
30
.vscode/launch.json
vendored
@@ -10,14 +10,14 @@
|
||||
"cwd": "${workspaceFolder}"
|
||||
},
|
||||
{
|
||||
"command": "pnpm tsx --no-deprecation test/dev.ts _community",
|
||||
"command": "node --no-deprecation test/dev.js _community",
|
||||
"cwd": "${workspaceFolder}",
|
||||
"name": "Run Dev Community",
|
||||
"request": "launch",
|
||||
"type": "node-terminal"
|
||||
},
|
||||
{
|
||||
"command": "pnpm tsx --no-deprecation test/dev.ts storage-uploadthing",
|
||||
"command": "node --no-deprecation test/dev.js storage-uploadthing",
|
||||
"cwd": "${workspaceFolder}",
|
||||
"name": "Uploadthing",
|
||||
"request": "launch",
|
||||
@@ -25,7 +25,7 @@
|
||||
"envFile": "${workspaceFolder}/test/storage-uploadthing/.env"
|
||||
},
|
||||
{
|
||||
"command": "pnpm tsx --no-deprecation test/dev.ts live-preview",
|
||||
"command": "node --no-deprecation test/dev.js live-preview",
|
||||
"cwd": "${workspaceFolder}",
|
||||
"name": "Run Dev Live Preview",
|
||||
"request": "launch",
|
||||
@@ -43,28 +43,28 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"command": "pnpm tsx --no-deprecation test/dev.ts admin",
|
||||
"command": "node --no-deprecation test/dev.js admin",
|
||||
"cwd": "${workspaceFolder}",
|
||||
"name": "Run Dev Admin",
|
||||
"request": "launch",
|
||||
"type": "node-terminal"
|
||||
},
|
||||
{
|
||||
"command": "pnpm tsx --no-deprecation test/dev.ts auth",
|
||||
"command": "node --no-deprecation test/dev.js auth",
|
||||
"cwd": "${workspaceFolder}",
|
||||
"name": "Run Dev Auth",
|
||||
"request": "launch",
|
||||
"type": "node-terminal"
|
||||
},
|
||||
{
|
||||
"command": "pnpm tsx --no-deprecation test/dev.ts fields-relationship",
|
||||
"command": "node --no-deprecation test/dev.js fields-relationship",
|
||||
"cwd": "${workspaceFolder}",
|
||||
"name": "Run Dev Fields-Relationship",
|
||||
"request": "launch",
|
||||
"type": "node-terminal"
|
||||
},
|
||||
{
|
||||
"command": "pnpm tsx --no-deprecation test/dev.ts login-with-username",
|
||||
"command": "node --no-deprecation test/dev.js login-with-username",
|
||||
"cwd": "${workspaceFolder}",
|
||||
"name": "Run Dev Login-With-Username",
|
||||
"request": "launch",
|
||||
@@ -81,21 +81,21 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"command": "pnpm tsx --no-deprecation test/dev.ts collections-graphql",
|
||||
"command": "node --no-deprecation test/dev.js collections-graphql",
|
||||
"cwd": "${workspaceFolder}",
|
||||
"name": "Run Dev GraphQL",
|
||||
"request": "launch",
|
||||
"type": "node-terminal"
|
||||
},
|
||||
{
|
||||
"command": "pnpm tsx --no-deprecation test/dev.ts fields",
|
||||
"command": "node --no-deprecation test/dev.js fields",
|
||||
"cwd": "${workspaceFolder}",
|
||||
"name": "Run Dev Fields",
|
||||
"request": "launch",
|
||||
"type": "node-terminal"
|
||||
},
|
||||
{
|
||||
"command": "pnpm tsx --no-deprecation test/dev.ts versions",
|
||||
"command": "node --no-deprecation test/dev.js versions",
|
||||
"cwd": "${workspaceFolder}",
|
||||
"name": "Run Dev Postgres",
|
||||
"request": "launch",
|
||||
@@ -105,35 +105,35 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"command": "pnpm tsx --no-deprecation test/dev.ts versions",
|
||||
"command": "node --no-deprecation test/dev.js versions",
|
||||
"cwd": "${workspaceFolder}",
|
||||
"name": "Run Dev Versions",
|
||||
"request": "launch",
|
||||
"type": "node-terminal"
|
||||
},
|
||||
{
|
||||
"command": "pnpm tsx --no-deprecation test/dev.ts localization",
|
||||
"command": "node --no-deprecation test/dev.js localization",
|
||||
"cwd": "${workspaceFolder}",
|
||||
"name": "Run Dev Localization",
|
||||
"request": "launch",
|
||||
"type": "node-terminal"
|
||||
},
|
||||
{
|
||||
"command": "pnpm tsx --no-deprecation test/dev.ts locked-documents",
|
||||
"command": "node --no-deprecation test/dev.js locked-documents",
|
||||
"cwd": "${workspaceFolder}",
|
||||
"name": "Run Dev Locked Documents",
|
||||
"request": "launch",
|
||||
"type": "node-terminal"
|
||||
},
|
||||
{
|
||||
"command": "pnpm tsx --no-deprecation test/dev.ts uploads",
|
||||
"command": "node --no-deprecation test/dev.js uploads",
|
||||
"cwd": "${workspaceFolder}",
|
||||
"name": "Run Dev Uploads",
|
||||
"request": "launch",
|
||||
"type": "node-terminal"
|
||||
},
|
||||
{
|
||||
"command": "pnpm tsx --no-deprecation test/dev.ts field-error-states",
|
||||
"command": "node --no-deprecation test/dev.js field-error-states",
|
||||
"cwd": "${workspaceFolder}",
|
||||
"name": "Run Dev Field Error States",
|
||||
"request": "launch",
|
||||
|
||||
@@ -122,19 +122,3 @@ This is how you can preview changes you made locally to the docs:
|
||||
4. Add a `DOCS_DIR` environment variable to the `.env` file which points to the absolute path of your modified docs folder. For example `DOCS_DIR=/Users/yourname/Documents/GitHub/payload/docs`
|
||||
5. Run `yarn run fetchDocs:local`. If this was successful, you should see no error messages and the following output: _Docs successfully written to /.../website/src/app/docs.json_. There could be error messages if you have incorrect markdown in your local docs folder. In this case, it will tell you how you can fix it
|
||||
6. You're done! Now you can start the website locally using `yarn run dev` and preview the docs under [http://localhost:3000/docs/](http://localhost:3000/docs/)
|
||||
|
||||
## Internationalization (i18n)
|
||||
|
||||
If your PR adds a string to the UI, we need to make sure to translate it into all the languages that Payload supports. To do that:
|
||||
|
||||
- Find the appropriate internationalization file for your package. These are typically located in `packages/translations/src/languages`, although some packages (e.g., richtext-lexical) have separate i18n files for each feature.
|
||||
- Add the string to the English locale "en".
|
||||
- Translate it to other languages. You can use the `translateNewKeys` script if you have an OpenAI API key in your `.env` (under `OPENAI_KEY`), or you can use ChatGPT or Google translate - whatever is easier for you. For payload core translations (in packages/translations) you can run the `translateNewKeys` script using `cd packages/translations && pnpm translateNewKeys`. For lexical translations, you can run it using `cd packages/richtext-lexical && pnpm translateNewKeys`. External contributors can skip this step and leave it to us.
|
||||
|
||||
To display translation strings in the UI, make sure to use the `t` utility of the `useTranslation` hook:
|
||||
|
||||
```ts
|
||||
const { t } = useTranslation()
|
||||
// ...
|
||||
t('yourStringKey')
|
||||
```
|
||||
|
||||
@@ -100,10 +100,6 @@ If you want to add contributions to this repository, please follow the instructi
|
||||
|
||||
The [Examples Directory](./examples) is a great resource for learning how to setup Payload in a variety of different ways, but you can also find great examples in our blog and throughout our social media.
|
||||
|
||||
If you'd like to run the examples, you can either copy them to a folder outside this repo or run them directly by (1) navigating to the example's subfolder (`cd examples/your-example-folder`) and (2) using the `--ignore-workspace` flag to bypass workspace restrictions (e.g., `pnpm --ignore-workspace install` or `pnpm --ignore-workspace dev`).
|
||||
|
||||
You can see more examples at:
|
||||
|
||||
- [Examples Directory](./examples)
|
||||
- [Payload Blog](https://payloadcms.com/blog)
|
||||
- [Payload YouTube](https://www.youtube.com/@payloadcms)
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
/* THIS FILE WAS GENERATED AUTOMATICALLY BY PAYLOAD. */
|
||||
/* DO NOT MODIFY IT BECAUSE IT COULD BE REWRITTEN AT ANY TIME. */
|
||||
import type { Metadata } from 'next'
|
||||
|
||||
import config from '@payload-config'
|
||||
import { generatePageMetadata, NotFoundPage } from '@payloadcms/next/views'
|
||||
/* DO NOT MODIFY IT BECAUSE IT COULD BE REWRITTEN AT ANY TIME. */
|
||||
import { NotFoundPage, generatePageMetadata } from '@payloadcms/next/views'
|
||||
|
||||
import { importMap } from '../importMap.js'
|
||||
|
||||
type Args = {
|
||||
params: Promise<{
|
||||
params: {
|
||||
segments: string[]
|
||||
}>
|
||||
searchParams: Promise<{
|
||||
}
|
||||
searchParams: {
|
||||
[key: string]: string | string[]
|
||||
}>
|
||||
}
|
||||
}
|
||||
|
||||
export const generateMetadata = ({ params, searchParams }: Args): Promise<Metadata> =>
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
/* THIS FILE WAS GENERATED AUTOMATICALLY BY PAYLOAD. */
|
||||
/* DO NOT MODIFY IT BECAUSE IT COULD BE REWRITTEN AT ANY TIME. */
|
||||
import type { Metadata } from 'next'
|
||||
|
||||
import config from '@payload-config'
|
||||
import { generatePageMetadata, RootPage } from '@payloadcms/next/views'
|
||||
/* DO NOT MODIFY IT BECAUSE IT COULD BE REWRITTEN AT ANY TIME. */
|
||||
import { RootPage, generatePageMetadata } from '@payloadcms/next/views'
|
||||
|
||||
import { importMap } from '../importMap.js'
|
||||
|
||||
type Args = {
|
||||
params: Promise<{
|
||||
params: {
|
||||
segments: string[]
|
||||
}>
|
||||
searchParams: Promise<{
|
||||
}
|
||||
searchParams: {
|
||||
[key: string]: string | string[]
|
||||
}>
|
||||
}
|
||||
}
|
||||
|
||||
export const generateMetadata = ({ params, searchParams }: Args): Promise<Metadata> =>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* THIS FILE WAS GENERATED AUTOMATICALLY BY PAYLOAD. */
|
||||
/* DO NOT MODIFY IT BECAUSE IT COULD BE REWRITTEN AT ANY TIME. */
|
||||
/* DO NOT MODIFY it because it could be re-written at any time. */
|
||||
import config from '@payload-config'
|
||||
import { REST_DELETE, REST_GET, REST_OPTIONS, REST_PATCH, REST_POST } from '@payloadcms/next/routes'
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* THIS FILE WAS GENERATED AUTOMATICALLY BY PAYLOAD. */
|
||||
/* DO NOT MODIFY IT BECAUSE IT COULD BE REWRITTEN AT ANY TIME. */
|
||||
/* DO NOT MODIFY it because it could be re-written at any time. */
|
||||
import config from '@payload-config'
|
||||
import { GRAPHQL_PLAYGROUND_GET } from '@payloadcms/next/routes'
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* THIS FILE WAS GENERATED AUTOMATICALLY BY PAYLOAD. */
|
||||
/* DO NOT MODIFY IT BECAUSE IT COULD BE REWRITTEN AT ANY TIME. */
|
||||
/* DO NOT MODIFY it because it could be re-written at any time. */
|
||||
import config from '@payload-config'
|
||||
import { GRAPHQL_POST } from '@payloadcms/next/routes'
|
||||
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
/* THIS FILE WAS GENERATED AUTOMATICALLY BY PAYLOAD. */
|
||||
/* DO NOT MODIFY IT BECAUSE IT COULD BE REWRITTEN AT ANY TIME. */
|
||||
import configPromise from '@payload-config'
|
||||
import { RootLayout } from '@payloadcms/next/layouts'
|
||||
// import '@payloadcms/ui/styles.css' // Uncomment this line if `@payloadcms/ui` in `tsconfig.json` points to `/ui/dist` instead of `/ui/src`
|
||||
import React from 'react'
|
||||
|
||||
import { importMap } from './admin/importMap.js'
|
||||
|
||||
// import '@payloadcms/ui/styles.css' // Uncomment this line if `@payloadcms/ui` in `tsconfig.json` points to `/ui/dist` instead of `/ui/src`
|
||||
/* DO NOT MODIFY IT BECAUSE IT COULD BE REWRITTEN AT ANY TIME. */
|
||||
import React from 'react'
|
||||
|
||||
import './custom.scss'
|
||||
|
||||
type Args = {
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
/* eslint-disable no-restricted-exports */
|
||||
'use client'
|
||||
|
||||
import * as Sentry from '@sentry/nextjs'
|
||||
import NextError from 'next/error.js'
|
||||
import { useEffect } from 'react'
|
||||
|
||||
export default function GlobalError({ error }: { error: { digest?: string } & Error }) {
|
||||
useEffect(() => {
|
||||
if (process.env.NEXT_PUBLIC_SENTRY_DSN) {
|
||||
Sentry.captureException(error)
|
||||
}
|
||||
}, [error])
|
||||
|
||||
return (
|
||||
<html lang="en-US">
|
||||
<body>
|
||||
{/* `NextError` is the default Next.js error page component. Its type
|
||||
definition requires a `statusCode` prop. However, since the App Router
|
||||
does not expose status codes for errors, we simply pass 0 to render a
|
||||
generic error message. */}
|
||||
{/* @ts-expect-error types repo */}
|
||||
<NextError statusCode={0} />
|
||||
</body>
|
||||
</html>
|
||||
)
|
||||
}
|
||||
@@ -79,7 +79,7 @@ Returns a boolean which allows/denies access to the `create` request.
|
||||
To add create Access Control to a Collection, use the `create` property in the [Collection Config](../collections/overview):
|
||||
|
||||
```ts
|
||||
import type { CollectionConfig } from 'payload'
|
||||
import { CollectionConfig } from 'payload'
|
||||
|
||||
export const CollectionWithCreateAccess: CollectionConfig = {
|
||||
// ...
|
||||
|
||||
@@ -33,7 +33,7 @@ Access Control is specific to the operation of the request.
|
||||
To add Access Control to a Field, use the `access` property in the [Field Config](../fields/overview):
|
||||
|
||||
```ts
|
||||
import type { CollectionConfig } from 'payload';
|
||||
import { CollectionConfig } from 'payload';
|
||||
|
||||
export const Posts: CollectionConfig = {
|
||||
slug: 'posts',
|
||||
|
||||
@@ -18,7 +18,7 @@ There are many use cases for Access Control, including:
|
||||
- Only allowing public access to posts where a `status` field is equal to `published`
|
||||
- Giving only users with a `role` field equal to `admin` the ability to delete posts
|
||||
- Allowing anyone to submit contact forms, but only logged in users to `read`, `update` or `delete` them
|
||||
- Restricting a user to only be able to see their own orders, but no-one else's
|
||||
- Restricting a user to only be able to see their own orders, but noone else's
|
||||
- Allowing users that belong to a certain organization to access only that organization's resources
|
||||
|
||||
There are three main types of Access Control in Payload:
|
||||
|
||||
@@ -11,7 +11,7 @@ The behavior of [Collections](../configuration/collections) within the [Admin Pa
|
||||
To configure Admin Options for Collections, use the `admin` property in your Collection Config:
|
||||
|
||||
```ts
|
||||
import type { CollectionConfig } from 'payload'
|
||||
import { CollectionConfig } from 'payload'
|
||||
|
||||
export const MyCollection: CollectionConfig = {
|
||||
// ...
|
||||
@@ -25,23 +25,23 @@ export const MyCollection: CollectionConfig = {
|
||||
|
||||
The following options are available:
|
||||
|
||||
| Option | Description |
|
||||
| -------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| **`group`** | Text used as a label for grouping Collection and Global links together in the navigation. |
|
||||
| **`hidden`** | Set to true or a function, called with the current user, returning true to exclude this Collection from navigation and admin routing. |
|
||||
| **`hooks`** | Admin-specific hooks for this Collection. [More details](../hooks/collections). |
|
||||
| **`useAsTitle`** | Specify a top-level field to use for a document title throughout the Admin Panel. If no field is defined, the ID of the document is used as the title. A field with `virtual: true` cannot be used as the title. |
|
||||
| Option | Description |
|
||||
| ---------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| **`group`** | Text used as a label for grouping Collection and Global links together in the navigation. |
|
||||
| **`hidden`** | Set to true or a function, called with the current user, returning true to exclude this Collection from navigation and admin routing. |
|
||||
| **`hooks`** | Admin-specific hooks for this Collection. [More details](../hooks/collections). |
|
||||
| **`useAsTitle`** | Specify a top-level field to use for a document title throughout the Admin Panel. If no field is defined, the ID of the document is used as the title. |
|
||||
| **`description`** | Text to display below the Collection label in the List View to give editors more information. Alternatively, you can use the `admin.components.Description` to render a React component. [More details](#components). |
|
||||
| **`defaultColumns`** | Array of field names that correspond to which columns to show by default in this Collection's List View. |
|
||||
| **`hideAPIURL`** | Hides the "API URL" meta field while editing documents within this Collection. |
|
||||
| **`enableRichTextLink`** | The [Rich Text](../fields/rich-text) field features a `Link` element which allows for users to automatically reference related documents within their rich text. Set to `true` by default. |
|
||||
| **`enableRichTextRelationship`** | The [Rich Text](../fields/rich-text) field features a `Relationship` element which allows for users to automatically reference related documents within their rich text. Set to `true` by default. |
|
||||
| **`meta`** | Page metadata overrides to apply to this Collection within the Admin Panel. [More details](./metadata). |
|
||||
| **`preview`** | Function to generate preview URLs within the Admin Panel that can point to your app. [More details](#preview). |
|
||||
| **`livePreview`** | Enable real-time editing for instant visual feedback of your front-end application. [More details](../live-preview/overview). |
|
||||
| **`components`** | Swap in your own React components to be used within this Collection. [More details](#components). |
|
||||
| **`listSearchableFields`** | Specify which fields should be searched in the List search view. [More details](#list-searchable-fields). |
|
||||
| **`pagination`** | Set pagination-specific options for this Collection. [More details](#pagination). |
|
||||
| **`defaultColumns`** | Array of field names that correspond to which columns to show by default in this Collection's List View. |
|
||||
| **`hideAPIURL`** | Hides the "API URL" meta field while editing documents within this Collection. |
|
||||
| **`enableRichTextLink`** | The [Rich Text](../fields/rich-text) field features a `Link` element which allows for users to automatically reference related documents within their rich text. Set to `true` by default. |
|
||||
| **`enableRichTextRelationship`** | The [Rich Text](../fields/rich-text) field features a `Relationship` element which allows for users to automatically reference related documents within their rich text. Set to `true` by default. |
|
||||
| **`meta`** | Page metadata overrides to apply to this Collection within the Admin Panel. [More details](./metadata). |
|
||||
| **`preview`** | Function to generate preview URLs within the Admin Panel that can point to your app. [More details](#preview). |
|
||||
| **`livePreview`** | Enable real-time editing for instant visual feedback of your front-end application. [More details](../live-preview/overview). |
|
||||
| **`components`** | Swap in your own React components to be used within this Collection. [More details](#components). |
|
||||
| **`listSearchableFields`** | Specify which fields should be searched in the List search view. [More details](#list-searchable-fields). |
|
||||
| **`pagination`** | Set pagination-specific options for this Collection. [More details](#pagination). |
|
||||
|
||||
### Components
|
||||
|
||||
@@ -89,7 +89,7 @@ It is possible to display a Preview Button within the Edit View of the Admin Pan
|
||||
To configure the Preview Button, set the `admin.preview` property to a function in your [Collection Config](../configuration/collections):
|
||||
|
||||
```ts
|
||||
import type { CollectionConfig } from 'payload'
|
||||
import { CollectionConfig } from 'payload'
|
||||
|
||||
export const Posts: CollectionConfig = {
|
||||
// ...
|
||||
@@ -126,7 +126,7 @@ All Collections receive their own List View which displays a paginated list of d
|
||||
To configure pagination options, use the `admin.pagination` property in your [Collection Config](../configuration/collections):
|
||||
|
||||
```ts
|
||||
import type { CollectionConfig } from 'payload'
|
||||
import { CollectionConfig } from 'payload'
|
||||
|
||||
export const Posts: CollectionConfig = {
|
||||
// ...
|
||||
@@ -155,7 +155,7 @@ In the List View, there is a "search" box that allows you to quickly find a docu
|
||||
To define which fields should be searched, use the `admin.listSearchableFields` property in your [Collection Config](../configuration/collections):
|
||||
|
||||
```ts
|
||||
import type { CollectionConfig } from 'payload'
|
||||
import { CollectionConfig } from 'payload'
|
||||
|
||||
export const Posts: CollectionConfig = {
|
||||
// ...
|
||||
|
||||
@@ -8,7 +8,7 @@ keywords: admin, components, custom, documentation, Content Management System, c
|
||||
|
||||
The Payload [Admin Panel](./overview) is designed to be as minimal and straightforward as possible to allow for both easy customization and full control over the UI. In order for Payload to support this level of customization, Payload provides a pattern for you to supply your own React components through your [Payload Config](../configuration/overview).
|
||||
|
||||
All Custom Components in Payload are [React Server Components](https://react.dev/reference/rsc/server-components) by default, with the exception of [Custom Providers](#custom-providers). This enables the use of the [Local API](../local-api/overview) directly on the front-end. Custom Components are available for nearly every part of the Admin Panel for extreme granularity and control.
|
||||
All Custom Components in Payload are [React Server Components](https://react.dev/reference/rsc/server-components) by default, with the exception of [Custom Providers](#custom-providers). This enables the use of the [Local API](../local-api) directly on the front-end. Custom Components are available for nearly every part of the Admin Panel for extreme granularity and control.
|
||||
|
||||
<Banner type="success">
|
||||
<strong>Note:</strong>
|
||||
@@ -145,7 +145,7 @@ Instead, we utilize component paths to reference React Components. This method e
|
||||
|
||||
When constructing the `ClientConfig`, Payload uses the component paths as keys to fetch the corresponding React Component imports from the Import Map. It then substitutes the `PayloadComponent` with a `MappedComponent`. A `MappedComponent` includes the React Component and additional metadata, such as whether it's a server or a client component and which props it should receive. These components are then rendered through the `<RenderComponent />` component within the Payload Admin Panel.
|
||||
|
||||
Import maps are regenerated whenever you modify any element related to component paths. This regeneration occurs at startup and whenever Hot Module Replacement (HMR) runs. If the import maps fail to regenerate during HMR, you can restart your application and execute the `payload generate:importmap` command to manually create a new import map. If you encounter any errors running this command, see the [Troubleshooting](../local-api/outside-nextjs#troubleshooting) section.
|
||||
Import maps are regenerated whenever you modify any element related to component paths. This regeneration occurs at startup and whenever Hot Module Replacement (HMR) runs. If the import maps fail to regenerate during HMR, you can restart your application and execute the `payload generate:importmap` command to manually create a new import map. If you encounter any errors running this command, see the [Troubleshooting](/docs/beta/local-api/outside-nextjs#troubleshooting) section.
|
||||
|
||||
### Component paths in external packages
|
||||
|
||||
@@ -329,7 +329,7 @@ export const useMyCustomContext = () => useContext(MyCustomContext)
|
||||
|
||||
## Building Custom Components
|
||||
|
||||
All Custom Components in Payload are [React Server Components](https://react.dev/reference/rsc/server-components) by default, with the exception of [Custom Providers](#custom-providers). This enables the use of the [Local API](../local-api/overview) directly on the front-end, among other things.
|
||||
All Custom Components in Payload are [React Server Components](https://react.dev/reference/rsc/server-components) by default, with the exception of [Custom Providers](#custom-providers). This enables the use of the [Local API](../local-api) directly on the front-end, among other things.
|
||||
|
||||
To make building Custom Components as easy as possible, Payload automatically provides common props, such as the [`payload`](../local-api/overview) class and the [`i18n`](../configuration/i18n) object. This means that when building Custom Components within the Admin Panel, you do not have to get these yourself.
|
||||
|
||||
|
||||
@@ -33,19 +33,6 @@ Here is an example of how you might target the Dashboard View and change the bac
|
||||
If you are building [Custom Components](./overview), it is best to import your own stylesheets directly into your components, rather than using the global stylesheet. You can continue to use the [CSS library](#css-library) as needed.
|
||||
</Banner>
|
||||
|
||||
### Specificity rules
|
||||
|
||||
All Payload CSS is encapsulated inside CSS layers under `@layer payload-default`. Any custom css will now have the highest possible specificity.
|
||||
|
||||
We have also provided a layer `@layer payload` if you want to use layers and ensure that your styles are applied after payload.
|
||||
|
||||
To override existing styles in a way that the previous rules of specificity would be respected you can use the default layer like so
|
||||
```css
|
||||
@layer payload-default {
|
||||
// my styles within the payload specificity
|
||||
}
|
||||
```
|
||||
|
||||
## Re-using Payload SCSS variables and utilities
|
||||
|
||||
You can re-use Payload's SCSS variables and utilities in your own stylesheets by importing it from the UI package.
|
||||
|
||||
@@ -40,21 +40,21 @@ export const CollectionConfig: CollectionConfig = {
|
||||
|
||||
The following options are available:
|
||||
|
||||
| Option | Description |
|
||||
| ----------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| **`condition`** | Programmatically show / hide fields based on other fields. [More details](../admin/fields#conditional-logic). |
|
||||
| **`components`** | All Field Components can be swapped out for [Custom Components](../admin/components) that you define. [More details](../admin/fields). |
|
||||
| **`description`** | Helper text to display alongside the field to provide more information for the editor. [More details](../admin/fields#description). |
|
||||
| Option | Description |
|
||||
| ------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| **`condition`** | Programmatically show / hide fields based on other fields. [More details](../admin/fields#conditional-logic). |
|
||||
| **`components`** | All Field Components can be swapped out for [Custom Components](../admin/components) that you define. [More details](../admin/fields). |
|
||||
| **`description`** | Helper text to display alongside the field to provide more information for the editor. [More details](../admin/fields#description). |
|
||||
| **`position`** | Specify if the field should be rendered in the sidebar by defining `position: 'sidebar'`. |
|
||||
| **`width`** | Restrict the width of a field. You can pass any string-based value here, be it pixels, percentages, etc. This property is especially useful when fields are nested within a `Row` type where they can be organized horizontally. |
|
||||
| **`style`** | [CSS Properties](https://developer.mozilla.org/en-US/docs/Web/CSS) to inject into the root element of the field. |
|
||||
| **`className`** | Attach a [CSS class attribute](https://developer.mozilla.org/en-US/docs/Web/CSS/Class_selectors) to the root DOM element of a field. |
|
||||
| **`style`** | [CSS Properties](https://developer.mozilla.org/en-US/docs/Web/CSS) to inject into the root element of the field. |
|
||||
| **`className`** | Attach a [CSS class attribute](https://developer.mozilla.org/en-US/docs/Web/CSS/Class_selectors) to the root DOM element of a field. |
|
||||
| **`readOnly`** | Setting a field to `readOnly` has no effect on the API whatsoever but disables the admin component's editability to prevent editors from modifying the field's value. |
|
||||
| **`disabled`** | If a field is `disabled`, it is completely omitted from the [Admin Panel](../admin/overview). |
|
||||
| **`disableBulkEdit`** | Set `disableBulkEdit` to `true` to prevent fields from appearing in the select options when making edits for multiple documents. Defaults to `true` for UI fields. |
|
||||
| **`disabled`** | If a field is `disabled`, it is completely omitted from the [Admin Panel](../admin/overview). |
|
||||
| **`disableBulkEdit`** | Set `disableBulkEdit` to `true` to prevent fields from appearing in the select options when making edits for multiple documents. |
|
||||
| **`disableListColumn`** | Set `disableListColumn` to `true` to prevent fields from appearing in the list view column selector. |
|
||||
| **`disableListFilter`** | Set `disableListFilter` to `true` to prevent fields from appearing in the list view filter options. |
|
||||
| **`hidden`** | Will transform the field into a `hidden` input type. Its value will still submit with requests in the Admin Panel, but the field itself will not be visible to editors. |
|
||||
| **`hidden`** | Will transform the field into a `hidden` input type. Its value will still submit with requests in the Admin Panel, but the field itself will not be visible to editors. |
|
||||
|
||||
## Field Components
|
||||
|
||||
@@ -217,7 +217,6 @@ Client Component:
|
||||
'use client'
|
||||
import React from 'react'
|
||||
import type { TextFieldClientComponent } from 'payload'
|
||||
import { TextField } from '@payloadcms/ui'
|
||||
|
||||
export const MyTextField: TextFieldClientComponent = ({ field }) => {
|
||||
return <TextField field={field} />
|
||||
|
||||
@@ -760,7 +760,7 @@ const LinkFromCategoryToPosts: React.FC = () => {
|
||||
|
||||
## useLocale
|
||||
|
||||
In any Custom Component you can get the selected locale object with the `useLocale` hook. `useLocale` gives you the full locale object, consisting of a `label`, `rtl`(right-to-left) property, and then `code`. Here is a simple example:
|
||||
In any Custom Component you can get the selected locale object with the `useLocale` hook. `useLocale`gives you the full locale object, consisting of a `label`, `rtl`(right-to-left) property, and then `code`. Here is a simple example:
|
||||
|
||||
```tsx
|
||||
'use client'
|
||||
|
||||
@@ -29,7 +29,7 @@ The lockDocuments property exists on both the Collection Config and the Global C
|
||||
Here’s an example configuration for document locking:
|
||||
|
||||
```ts
|
||||
import type { CollectionConfig } from 'payload'
|
||||
import { CollectionConfig } from 'payload'
|
||||
|
||||
export const Posts: CollectionConfig = {
|
||||
slug: 'posts',
|
||||
|
||||
@@ -36,7 +36,7 @@ To customize Root Metadata, use the `admin.meta` key in your Payload Config:
|
||||
{
|
||||
rel: 'icon',
|
||||
type: 'image/png',
|
||||
url: '/favicon.png',
|
||||
href: '/favicon.png',
|
||||
},
|
||||
],
|
||||
},
|
||||
@@ -80,12 +80,12 @@ To customize icons, use the `icons` key within the `admin.meta` object in your P
|
||||
{
|
||||
rel: 'icon',
|
||||
type: 'image/png',
|
||||
url: '/favicon.png',
|
||||
href: '/favicon.png',
|
||||
},
|
||||
{
|
||||
rel: 'apple-touch-icon',
|
||||
type: 'image/png',
|
||||
url: '/apple-touch-icon.png',
|
||||
href: '/apple-touch-icon.png',
|
||||
},
|
||||
],
|
||||
},
|
||||
@@ -140,7 +140,7 @@ The following options are available for Open Graph Metadata:
|
||||
| Key | Type | Description |
|
||||
| --- | --- | --- |
|
||||
| **`description`** | `string` | The description of the Admin Panel. |
|
||||
| **`images`** | `OGImageConfig` or `OGImageConfig[]` | An array of image objects. |
|
||||
| **`images`** | `OGImageConfig | OGImageConfig[]` | An array of image objects. |
|
||||
| **`siteName`** | `string` | The name of the site. |
|
||||
| **`title`** | `string` | The title of the Admin Panel. |
|
||||
|
||||
@@ -151,7 +151,7 @@ Collection Metadata is the metadata that is applied to all pages within any give
|
||||
To customize Collection Metadata, use the `admin.meta` key within your Collection Config:
|
||||
|
||||
```ts
|
||||
import type { CollectionConfig } from 'payload'
|
||||
import { CollectionConfig } from 'payload'
|
||||
|
||||
export const MyCollection: CollectionConfig = {
|
||||
// ...
|
||||
|
||||
@@ -98,7 +98,6 @@ The following options are available:
|
||||
| **`livePreview`** | Enable real-time editing for instant visual feedback of your front-end application. [More details](../live-preview/overview). |
|
||||
| **`meta`** | Base metadata to use for the Admin Panel. [More details](./metadata). |
|
||||
| **`routes`** | Replace built-in Admin Panel routes with your own custom routes. [More details](#customizing-routes). |
|
||||
| **`theme`** | Restrict the Admin Panel theme to use only one of your choice. Default is `all`.
|
||||
| **`user`** | The `slug` of the Collection that you want to allow to login to the Admin Panel. [More details](#the-admin-user-collection). |
|
||||
|
||||
<Banner type="success">
|
||||
|
||||
@@ -93,7 +93,7 @@ For more granular control, pass a configuration object instead. Payload exposes
|
||||
| **`path`** \* | Any valid URL path or array of paths that [`path-to-regexp`](https://www.npmjs.com/package/path-to-regex) understands. |
|
||||
| **`exact`** | Boolean. When true, will only match if the path matches the `usePathname()` exactly. |
|
||||
| **`strict`** | When true, a path that has a trailing slash will only match a `location.pathname` with a trailing slash. This has no effect when there are additional URL segments in the pathname. |
|
||||
| **`sensitive`** | When true, will match if the path is case sensitive.|
|
||||
| **`sensitive`** | When true, will match if the path is case sensitive.
|
||||
| **`meta`** | Page metadata overrides to apply to this view within the Admin Panel. [More details](./metadata). |
|
||||
|
||||
_\* An asterisk denotes that a property is required._
|
||||
@@ -133,12 +133,6 @@ The above example shows how to add a new [Root View](#root-views), but the patte
|
||||
route.
|
||||
</Banner>
|
||||
|
||||
<Banner type="warning">
|
||||
<strong>Custom views are public</strong>
|
||||
<br />
|
||||
Custom views are public by default. If your view requires a user to be logged in or to have certain access rights, you should handle that within your view component yourself.
|
||||
</Banner>
|
||||
|
||||
## Collection Views
|
||||
|
||||
Collection Views are views that are scoped under the `/collections` route, such as the Collection List and Document Edit views.
|
||||
|
||||
@@ -97,7 +97,7 @@ Cookies can cross subdomains without being considered third party cookies, for e
|
||||
|
||||
##### 2. Configure cookies
|
||||
|
||||
If option 1 isn't possible, then you can get around this limitation by [configuring your cookies](./overview#config-options) on your authentication collection to achieve the following setup:
|
||||
If option 1 isn't possible, then you can get around this limitation by [configuring your cookies](https://payloadcms.com/docs/beta/authentication/overview#config-options) on your authentication collection to achieve the following setup:
|
||||
|
||||
```
|
||||
SameSite: None // allows the cookie to cross domains
|
||||
@@ -122,7 +122,7 @@ Configuration example:
|
||||
},
|
||||
```
|
||||
|
||||
If you're configuring [cors](../production/preventing-abuse#cross-origin-resource-sharing-cors) in your Payload config, you won't be able to use a wildcard anymore, you'll need to specify the list of allowed domains.
|
||||
If you're configuring [cors](https://payloadcms.com/docs/beta/production/preventing-abuse#cross-origin-resource-sharing-cors) in your Payload config, you won't be able to use a wildcard anymore, you'll need to specify the list of allowed domains.
|
||||
|
||||
|
||||
<Banner type="success">
|
||||
|
||||
@@ -38,7 +38,7 @@ At its core a strategy simply takes information from the incoming request and re
|
||||
Your `authenticate` method should return an object containing a Payload user document and any optional headers that you'd like Payload to set for you when we return a response.
|
||||
|
||||
```ts
|
||||
import type { CollectionConfig } from 'payload'
|
||||
import { CollectionConfig } from 'payload'
|
||||
|
||||
export const Users: CollectionConfig = {
|
||||
slug: 'users',
|
||||
|
||||
@@ -15,7 +15,7 @@ Email Verification forces users to prove they have access to the email address t
|
||||
To enable Email Verification, use the `auth.verify` property on your [Collection Config](../configuration/collections):
|
||||
|
||||
```ts
|
||||
import type { CollectionConfig } from 'payload'
|
||||
import { CollectionConfig } from 'payload'
|
||||
|
||||
export const Customers: CollectionConfig = {
|
||||
// ...
|
||||
@@ -42,7 +42,7 @@ The following options are available:
|
||||
Function that accepts one argument, containing `{ req, token, user }`, that allows for overriding the HTML within emails that are sent to users indicating how to validate their account. The function should return a string that supports HTML, which can optionally be a full HTML email.
|
||||
|
||||
```ts
|
||||
import type { CollectionConfig } from 'payload'
|
||||
import { CollectionConfig } from 'payload'
|
||||
|
||||
export const Customers: CollectionConfig = {
|
||||
// ...
|
||||
@@ -74,7 +74,7 @@ export const Customers: CollectionConfig = {
|
||||
Similarly to the above `generateEmailHTML`, you can also customize the subject of the email. The function argument are the same but you can only return a string - not HTML.
|
||||
|
||||
```ts
|
||||
import type { CollectionConfig } from 'payload'
|
||||
import { CollectionConfig } from 'payload'
|
||||
|
||||
export const Customers: CollectionConfig = {
|
||||
// ...
|
||||
@@ -95,7 +95,7 @@ export const Customers: CollectionConfig = {
|
||||
You can customize how the Forgot Password workflow operates with the following options on the `auth.forgotPassword` property:
|
||||
|
||||
```ts
|
||||
import type { CollectionConfig } from 'payload'
|
||||
import { CollectionConfig } from 'payload'
|
||||
|
||||
export const Customers: CollectionConfig = {
|
||||
// ...
|
||||
@@ -119,7 +119,7 @@ The following options are available:
|
||||
This function allows for overriding the HTML within emails that are sent to users attempting to reset their password. The function should return a string that supports HTML, which can be a full HTML email.
|
||||
|
||||
```ts
|
||||
import type { CollectionConfig } from 'payload'
|
||||
import { CollectionConfig } from 'payload'
|
||||
|
||||
export const Customers: CollectionConfig = {
|
||||
// ...
|
||||
@@ -179,7 +179,7 @@ The following arguments are passed to the `generateEmailHTML` function:
|
||||
Similarly to the above `generateEmailHTML`, you can also customize the subject of the email. The function argument are the same but you can only return a string - not HTML.
|
||||
|
||||
```ts
|
||||
import type { CollectionConfig } from 'payload'
|
||||
import { CollectionConfig } from 'payload'
|
||||
|
||||
export const Customers: CollectionConfig = {
|
||||
// ...
|
||||
|
||||
@@ -25,7 +25,7 @@ When Authentication is enabled on a [Collection](../configuration/collections),
|
||||
To enable Authentication on a Collection, use the `auth` property in the [Collection Config](../configuration/collection#auth):
|
||||
|
||||
```ts
|
||||
import type { CollectionConfig } from 'payload'
|
||||
import { CollectionConfig } from 'payload'
|
||||
|
||||
export const Users: CollectionConfig = {
|
||||
// ...
|
||||
@@ -48,7 +48,7 @@ Any [Collection](../configuration/collections) can opt-in to supporting Authenti
|
||||
To enable Authentication on a Collection, use the `auth` property in the [Collection Config](../configuration/collections):
|
||||
|
||||
```ts
|
||||
import type { CollectionConfig } from 'payload'
|
||||
import { CollectionConfig } from 'payload'
|
||||
|
||||
export const Admins: CollectionConfig = {
|
||||
// ...
|
||||
@@ -86,7 +86,7 @@ The following options are available:
|
||||
| **`loginWithUsername`** | Ability to allow users to login with username/password. [More](/docs/authentication/overview#login-with-username) |
|
||||
| **`maxLoginAttempts`** | Only allow a user to attempt logging in X amount of times. Automatically locks out a user from authenticating if this limit is passed. Set to `0` to disable. |
|
||||
| **`removeTokenFromResponses`** | Set to true if you want to remove the token from the returned authentication API responses such as login or refresh. |
|
||||
| **`strategies`** | Advanced - an array of custom authentication strategies to extend this collection's authentication with. [More details](./custom-strategies). |
|
||||
| **`strategies`** | Advanced - an array of custom authentification strategies to extend this collection's authentication with. [More details](./custom-strategies). |
|
||||
| **`tokenExpiration`** | How long (in seconds) to keep the user logged in. JWTs and HTTP-only cookies will both expire at the same time. |
|
||||
| **`useAPIKey`** | Payload Authentication provides for API keys to be set on each user within an Authentication-enabled Collection. [More details](./api-keys). |
|
||||
| **`verify`** | Set to `true` or pass an object with verification options to require users to verify by email before they are allowed to log into your app. [More details](./email#email-verification). |
|
||||
|
||||
@@ -6,7 +6,7 @@ desc: Storing data for read on the request object.
|
||||
keywords: authentication, config, configuration, documentation, Content Management System, cms, headless, javascript, node, react, nextjs
|
||||
---
|
||||
|
||||
During the lifecycle of a request you will be able to access the data you have configured to be stored in the JWT by accessing `req.user`. The user object is automatically appended to the request for you.
|
||||
During the lifecycle of a request you will be able to access the data you have configured to be stored in the JWT by accessing `req.user`. The user object is automatically appeneded to the request for you.
|
||||
|
||||
### Definining Token Data
|
||||
|
||||
|
||||
@@ -84,7 +84,7 @@ export default buildConfig({
|
||||
|
||||
## Email
|
||||
|
||||
Powered by [Resend](https://resend.com), Payload Cloud comes with integrated email support out of the box. No configuration is needed, and you can use `payload.sendEmail()` to send email right from your Payload app. To learn more about sending email with Payload, checkout the [Email Configuration](../email/overview) overview.
|
||||
Powered by [Resend](https://resend.com), Payload Cloud comes with integrated email support out of the box. No configuration is needed, and you can use `payload.sendEmail()` to send email right from your Payload app. To learn more about sending email with Payload, checkout the [Email Configuration](https://payloadcms.com/docs/email/overview) overview.
|
||||
|
||||
If you are on the Pro or Enterprise plan, you can add your own custom Email domain name. From the Email page of your project’s Settings, add the domain you wish to use for email delivery. This will generate a set of DNS records. Add these records to your DNS provider and click verify to check that your records are resolving properly. Once verified, your emails will now be sent from your custom domain name.
|
||||
|
||||
@@ -98,14 +98,14 @@ From there, you are ready to make updates to your project. When you are ready to
|
||||
|
||||
Projects generated from a template will come pre-configured with the official Cloud Plugin, but if you are using your own repository you will need to add this into your project. To do so, add the plugin to your Payload Config:
|
||||
|
||||
`yarn add @payloadcms/payload-cloud`
|
||||
`yarn add @payloadcms/plugin-cloud`
|
||||
|
||||
```js
|
||||
import { payloadCloudPlugin } from '@payloadcms/payload-cloud'
|
||||
import { payloadCloud } from '@payloadcms/plugin-cloud'
|
||||
import { buildConfig } from 'payload'
|
||||
|
||||
export default buildConfig({
|
||||
plugins: [payloadCloudPlugin()],
|
||||
plugins: [payloadCloud()],
|
||||
// rest of config
|
||||
})
|
||||
```
|
||||
@@ -115,11 +115,6 @@ export default buildConfig({
|
||||
over Payload Cloud's email service.
|
||||
</Banner>
|
||||
|
||||
<Banner type="info">
|
||||
Good to know: the Payload Cloud Plugin was previously named `@payloadcms/plugin-cloud`. If you are
|
||||
using this plugin, you should update to the new package name.
|
||||
</Banner>
|
||||
|
||||
#### **Optional configuration**
|
||||
|
||||
If you wish to opt-out of any Payload cloud features, the plugin also accepts options to do so.
|
||||
|
||||
@@ -37,7 +37,7 @@ It's often best practice to write your Collections in separate files and then im
|
||||
Here is what a simple Collection Config might look like:
|
||||
|
||||
```ts
|
||||
import type { CollectionConfig } from 'payload'
|
||||
import { CollectionConfig } from 'payload'
|
||||
|
||||
export const Posts: CollectionConfig = {
|
||||
slug: 'posts',
|
||||
@@ -57,27 +57,26 @@ export const Posts: CollectionConfig = {
|
||||
|
||||
The following options are available:
|
||||
|
||||
| Option | Description |
|
||||
| ---------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| **`admin`** | The configuration options for the Admin Panel. [More details](../admin/collections). |
|
||||
| **`access`** | Provide Access Control functions to define exactly who should be able to do what with Documents in this Collection. [More details](../access-control/collections). |
|
||||
| **`auth`** | Specify options if you would like this Collection to feature authentication. [More details](../authentication/overview). |
|
||||
| **`custom`** | Extension point for adding custom data (e.g. for plugins) |
|
||||
| **`disableDuplicate`** | When true, do not show the "Duplicate" button while editing documents within this Collection and prevent `duplicate` from all APIs. |
|
||||
| **`defaultSort`** | Pass a top-level field to sort by default in the Collection List View. Prefix the name of the field with a minus symbol ("-") to sort in descending order. Multiple fields can be specified by using a string array. |
|
||||
| **`dbName`** | Custom table or Collection name depending on the Database Adapter. Auto-generated from slug if not defined. |
|
||||
| **`endpoints`** | Add custom routes to the REST API. Set to `false` to disable routes. [More details](../rest-api/overview#custom-endpoints). |
|
||||
| **`fields`** \* | Array of field types that will determine the structure and functionality of the data stored within this Collection. [More details](../fields/overview). |
|
||||
| **`graphQL`** | An object with `singularName` and `pluralName` strings used in schema generation. Auto-generated from slug if not defined. Set to `false` to disable GraphQL. |
|
||||
| **`hooks`** | Entry point for Hooks. [More details](../hooks/overview#collection-hooks). |
|
||||
| **`labels`** | Singular and plural labels for use in identifying this Collection throughout Payload. Auto-generated from slug if not defined. |
|
||||
| **`lockDocuments`** | Enables or disables document locking. By default, document locking is enabled. Set to an object to configure, or set to `false` to disable locking. [More details](../admin/locked-documents). |
|
||||
| **`slug`** \* | Unique, URL-friendly string that will act as an identifier for this Collection. |
|
||||
| **`timestamps`** | Set to false to disable documents' automatically generated `createdAt` and `updatedAt` timestamps. |
|
||||
| **`typescript`** | An object with property `interface` as the text used in schema generation. Auto-generated from slug if not defined. |
|
||||
| **`upload`** | Specify options if you would like this Collection to support file uploads. For more, consult the [Uploads](../upload/overview) documentation. |
|
||||
| **`versions`** | Set to true to enable default options, or configure with object properties. [More details](../versions/overview#collection-config). |
|
||||
| **`defaultPopulate`** | Specify which fields to select when this Collection is populated from another document. [More Details](../queries/select#defaultpopulate-collection-config-property). |
|
||||
| Option | Description |
|
||||
|------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| **`admin`** | The configuration options for the Admin Panel. [More details](../admin/collections). |
|
||||
| **`access`** | Provide Access Control functions to define exactly who should be able to do what with Documents in this Collection. [More details](../access-control/collections). |
|
||||
| **`auth`** | Specify options if you would like this Collection to feature authentication. [More details](../authentication/overview). |
|
||||
| **`custom`** | Extension point for adding custom data (e.g. for plugins) |
|
||||
| **`disableDuplicate`** | When true, do not show the "Duplicate" button while editing documents within this Collection and prevent `duplicate` from all APIs. |
|
||||
| **`defaultSort`** | Pass a top-level field to sort by default in the Collection List View. Prefix the name of the field with a minus symbol ("-") to sort in descending order. |
|
||||
| **`dbName`** | Custom table or Collection name depending on the Database Adapter. Auto-generated from slug if not defined. |
|
||||
| **`endpoints`** | Add custom routes to the REST API. Set to `false` to disable routes. [More details](../rest-api/overview#custom-endpoints). |
|
||||
| **`fields`** \* | Array of field types that will determine the structure and functionality of the data stored within this Collection. [More details](../fields/overview). |
|
||||
| **`graphQL`** | An object with `singularName` and `pluralName` strings used in schema generation. Auto-generated from slug if not defined. Set to `false` to disable GraphQL. |
|
||||
| **`hooks`** | Entry point for Hooks. [More details](../hooks/overview#collection-hooks). |
|
||||
| **`labels`** | Singular and plural labels for use in identifying this Collection throughout Payload. Auto-generated from slug if not defined. |
|
||||
| **`lockDocuments`** | Enables or disables document locking. By default, document locking is enabled. Set to an object to configure, or set to `false` to disable locking. [More details](../admin/locked-documents). |
|
||||
| **`slug`** \* | Unique, URL-friendly string that will act as an identifier for this Collection. |
|
||||
| **`timestamps`** | Set to false to disable documents' automatically generated `createdAt` and `updatedAt` timestamps. |
|
||||
| **`typescript`** | An object with property `interface` as the text used in schema generation. Auto-generated from slug if not defined. |
|
||||
| **`upload`** | Specify options if you would like this Collection to support file uploads. For more, consult the [Uploads](../upload/overview) documentation. |
|
||||
| **`versions`** | Set to true to enable default options, or configure with object properties. [More details](../versions/overview#collection-config). |
|
||||
|
||||
_\* An asterisk denotes that a property is required._
|
||||
|
||||
|
||||
@@ -40,6 +40,7 @@ export default buildConfig({
|
||||
// highlight-start
|
||||
i18n: {
|
||||
fallbackLanguage: 'en', // default
|
||||
debug: false, // default
|
||||
}
|
||||
// highlight-end
|
||||
})
|
||||
@@ -50,6 +51,7 @@ The following options are available:
|
||||
| Option | Description |
|
||||
| --------------------- | --------------------------------|
|
||||
| **`fallbackLanguage`** | The language to fall back to if the user's preferred language is not supported. Default is `'en'`. |
|
||||
| **`debug`** | Whether to log debug information to the console. Default is `false`. |
|
||||
| **`translations`** | An object containing the translations. The keys are the language codes and the values are the translations. |
|
||||
| **`supportedLanguages`** | An object containing the supported languages. The keys are the language codes and the values are the translations. |
|
||||
|
||||
@@ -117,7 +119,7 @@ While Payload's built-in features come fully translated, you may also want to tr
|
||||
To do this, provide the translations wherever applicable, keyed to the language code:
|
||||
|
||||
```ts
|
||||
import type { CollectionConfig } from 'payload'
|
||||
import { CollectionConfig } from 'payload'
|
||||
|
||||
export const Articles: CollectionConfig = {
|
||||
slug: 'articles',
|
||||
@@ -176,80 +178,60 @@ Anywhere in your Payload app that you have access to the `req` object, you can a
|
||||
|
||||
In order to use custom translations in your project, you need to provide the types for the translations.
|
||||
|
||||
Here we create a shareable translations object. We will import this in both our custom components and in our Payload config.
|
||||
Here is an example of how you can define the types for the custom translations in a [Custom Component](../admin/components):
|
||||
|
||||
```ts
|
||||
// <rootDir>/custom-translations.ts
|
||||
|
||||
import type { Config } from 'payload'
|
||||
'use client'
|
||||
import type { NestedKeysStripped } from '@payloadcms/translations'
|
||||
import type React from 'react'
|
||||
|
||||
export const customTranslations: Config['i18n']['translations'] = {
|
||||
import { useTranslation } from '@payloadcms/ui/providers/Translation'
|
||||
|
||||
const customTranslations = {
|
||||
en: {
|
||||
general: {
|
||||
myCustomKey: 'My custom english translation',
|
||||
test: 'Custom Translation',
|
||||
},
|
||||
fields: {
|
||||
addLabel: 'Add!',
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
export type CustomTranslationsObject = typeof customTranslations.en
|
||||
export type CustomTranslationsKeys = NestedKeysStripped<CustomTranslationsObject>
|
||||
```
|
||||
|
||||
Import the shared translations object into our Payload config so they are available for use:
|
||||
|
||||
```ts
|
||||
// <rootDir>/payload.config.ts
|
||||
|
||||
import { buildConfig } from 'payload'
|
||||
|
||||
import { customTranslations } from './custom-translations'
|
||||
|
||||
export default buildConfig({
|
||||
//...
|
||||
i18n: {
|
||||
translations: customTranslations,
|
||||
},
|
||||
//...
|
||||
})
|
||||
```
|
||||
|
||||
Import the shared translation types to use in your [Custom Component](../admin/components):
|
||||
|
||||
```ts
|
||||
// <rootDir>/components/MyComponent.tsx
|
||||
|
||||
'use client'
|
||||
import type React from 'react'
|
||||
import { useTranslation } from '@payloadcms/ui'
|
||||
|
||||
import type { CustomTranslationsObject, CustomTranslationsKeys } from '../custom-translations'
|
||||
type CustomTranslationObject = typeof customTranslations.en
|
||||
type CustomTranslationKeys = NestedKeysStripped<CustomTranslationObject>
|
||||
|
||||
export const MyComponent: React.FC = () => {
|
||||
const { i18n, t } = useTranslation<CustomTranslationsObject, CustomTranslationsKeys>() // These generics merge your custom translations with the default client translations
|
||||
const { i18n, t } = useTranslation<CustomTranslationObject, CustomTranslationKeys>() // These generics merge your custom translations with the default client translations
|
||||
|
||||
return t('general:myCustomKey')
|
||||
return t('general:test')
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
Additionally, Payload exposes the `t` function in various places, for example in labels. Here is how you would type those:
|
||||
|
||||
```ts
|
||||
// <rootDir>/fields/myField.ts
|
||||
|
||||
import type { DefaultTranslationKeys, TFunction } from '@payloadcms/translations'
|
||||
import type {
|
||||
DefaultTranslationKeys,
|
||||
NestedKeysStripped,
|
||||
TFunction,
|
||||
} from '@payloadcms/translations'
|
||||
import type { Field } from 'payload'
|
||||
|
||||
import { CustomTranslationsKeys } from '../custom-translations'
|
||||
const customTranslations = {
|
||||
en: {
|
||||
general: {
|
||||
test: 'Custom Translation',
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
type CustomTranslationObject = typeof customTranslations.en
|
||||
type CustomTranslationKeys = NestedKeysStripped<CustomTranslationObject>
|
||||
|
||||
const field: Field = {
|
||||
name: 'myField',
|
||||
type: 'text',
|
||||
label: (
|
||||
{ t }: { t: TFunction<CustomTranslationsKeys | DefaultTranslationKeys> }, // The generic passed to TFunction does not automatically merge the custom translations with the default translations. We need to merge them ourselves here
|
||||
{ t }: { t: TFunction<CustomTranslationKeys | DefaultTranslationKeys> }, // The generic passed to TFunction does not automatically merge the custom translations with the default translations. We need to merge them ourselves here
|
||||
) => t('fields:addLabel'),
|
||||
}
|
||||
```
|
||||
|
||||
@@ -35,8 +35,7 @@ import { buildConfig } from 'payload'
|
||||
export default buildConfig({
|
||||
// ...
|
||||
localization: {
|
||||
locales: ['en', 'es', 'de'] // required
|
||||
defaultLocale: 'en', // required
|
||||
locales: ['en', 'es', 'de'] // highlight-line
|
||||
},
|
||||
})
|
||||
```
|
||||
@@ -64,7 +63,7 @@ export default buildConfig({
|
||||
rtl: true,
|
||||
},
|
||||
],
|
||||
defaultLocale: 'en', // required
|
||||
defaultLocale: 'en',
|
||||
fallback: true,
|
||||
},
|
||||
})
|
||||
|
||||
@@ -163,7 +163,7 @@ In development mode, if the configuration file is not found at the root, Payload
|
||||
|
||||
**Production Mode**
|
||||
|
||||
In production mode, Payload will first attempt to find the config file in the `outDir` of your `tsconfig.json`, and if not found, will fallback to the `rootDir` directory:
|
||||
In production mode, Payload will first attempt to find the config file in the `outDir` of your `tsconfig.json`, and if not found, will fallback to the `rootDor` directory:
|
||||
|
||||
```json
|
||||
{
|
||||
@@ -216,7 +216,7 @@ Cross-origin resource sharing (CORS) can be configured with either a whitelist a
|
||||
Here's an example showing how to allow incoming requests from any domain:
|
||||
|
||||
```ts
|
||||
import { buildConfig } from 'payload'
|
||||
import { buildConfig } from 'payload/config'
|
||||
|
||||
export default buildConfig({
|
||||
// ...
|
||||
@@ -227,7 +227,7 @@ export default buildConfig({
|
||||
Here's an example showing how to append a new header (`x-custom-header`) in `Access-Control-Allow-Headers`:
|
||||
|
||||
```ts
|
||||
import { buildConfig } from 'payload'
|
||||
import { buildConfig } from 'payload/config'
|
||||
|
||||
export default buildConfig({
|
||||
// ...
|
||||
|
||||
@@ -157,7 +157,7 @@ You can disable this setting and solely use migrations to manage your local deve
|
||||
|
||||
For this reason, we suggest that you leave `push` as its default setting and treat your local dev database as a sandbox.
|
||||
|
||||
For more information about push mode and prototyping in development, [click here](./postgres#prototyping-in-dev-mode).
|
||||
For more information about push mode and prototyping in development, [click here](/docs/beta/database/postgres#prototyping-in-dev-mode).
|
||||
|
||||
The typical workflow in Payload is to build out your Payload configs, install plugins, and make progress in development mode - allowing Drizzle to push your changes to your local database for you. Once you're finished, you can create a migration.
|
||||
|
||||
|
||||
@@ -60,7 +60,6 @@ export default buildConfig({
|
||||
| `schemaName` (experimental) | A string for the postgres schema to use, defaults to 'public'. |
|
||||
| `idType` | A string of 'serial', or 'uuid' that is used for the data type given to id columns. |
|
||||
| `transactionOptions` | A PgTransactionConfig object for transactions, or set to `false` to disable using transactions. [More details](https://orm.drizzle.team/docs/transactions) |
|
||||
| `disableCreateDatabase` | Pass `true` to disale auto database creation if it doesn't exist. Defaults to `false`. |
|
||||
| `localesSuffix` | A string appended to the end of table names for storing localized fields. Default is '_locales'. |
|
||||
| `relationshipsSuffix` | A string appended to the end of table names for storing relationships. Default is '_rels'. |
|
||||
| `versionsSuffix` | A string appended to the end of table names for storing versions. Defaults to '_v'. |
|
||||
@@ -99,7 +98,7 @@ Alternatively, you can disable `push` and rely solely on migrations to keep your
|
||||
|
||||
In Postgres, migrations are a fundamental aspect of working with Payload and you should become familiar with how they work.
|
||||
|
||||
For more information about migrations, [click here](./migrations#when-to-run-migrations).
|
||||
For more information about migrations, [click here](/docs/beta/database/migrations#when-to-run-migrations).
|
||||
|
||||
## Drizzle schema hooks
|
||||
|
||||
|
||||
@@ -78,7 +78,7 @@ Alternatively, you can disable `push` and rely solely on migrations to keep your
|
||||
|
||||
In SQLite, migrations are a fundamental aspect of working with Payload and you should become familiar with how they work.
|
||||
|
||||
For more information about migrations, [click here](./migrations#when-to-run-migrations).
|
||||
For more information about migrations, [click here](/docs/beta/database/migrations#when-to-run-migrations).
|
||||
|
||||
## Drizzle schema hooks
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ desc: Database transactions are fully supported within Payload.
|
||||
|
||||
Database transactions allow your application to make a series of database changes in an all-or-nothing commit. Consider an HTTP request that creates a new **Order** and has an `afterChange` hook to update the stock count of related **Items**. If an error occurs when updating an **Item** and an HTTP error is returned to the user, you would not want the new **Order** to be persisted or any other items to be changed either. This kind of interaction with the database is handled seamlessly with transactions.
|
||||
|
||||
By default, Payload will use transactions for all data changing operations, as long as it is supported by the configured database. Database changes are contained within all Payload operations and any errors thrown will result in all changes being rolled back without being committed. When transactions are not supported by the database, Payload will continue to operate as expected without them.
|
||||
By default, Payload will use transactions for all operations, as long as it is supported by the configured database. Database changes are contained within all Payload operations and any errors thrown will result in all changes being rolled back without being committed. When transactions are not supported by the database, Payload will continue to operate as expected without them.
|
||||
|
||||
<Banner type="info">
|
||||
<strong>Note:</strong>
|
||||
@@ -114,18 +114,3 @@ standalonePayloadScript()
|
||||
## Disabling Transactions
|
||||
|
||||
If you wish to disable transactions entirely, you can do so by passing `false` as the `transactionOptions` in your database adapter configuration. All the official Payload database adapters support this option.
|
||||
|
||||
In addition to allowing database transactions to be disabled at the adapter level. You can prevent Payload from using a transaction in direct calls to the local API by adding `disableTransaction: true` to the args. For example:
|
||||
|
||||
```ts
|
||||
await payload.update({
|
||||
collection: 'posts',
|
||||
data: {
|
||||
some: 'data',
|
||||
},
|
||||
where: {
|
||||
slug: { equals: 'my-slug' }
|
||||
},
|
||||
disableTransaction: true,
|
||||
})
|
||||
```
|
||||
|
||||
@@ -24,7 +24,7 @@ Arrays are useful for many different types of content from simple to complex, su
|
||||
To create an Array Field, set the `type` to `array` in your [Field Config](./overview):
|
||||
|
||||
```ts
|
||||
import type { Field } from 'payload'
|
||||
import type { Field } from 'payload/types'
|
||||
|
||||
export const MyArrayField: Field = {
|
||||
// ...
|
||||
@@ -66,10 +66,10 @@ _\* An asterisk denotes that a property is required._
|
||||
|
||||
## Admin Options
|
||||
|
||||
To customize the appearance and behavior of the Array Field in the [Admin Panel](../admin/overview), you can use the `admin` option:
|
||||
The customize the appearance and behavior of the Array Field in the [Admin Panel](../admin/overview), you can use the `admin` option:
|
||||
|
||||
```ts
|
||||
import type { Field } from 'payload'
|
||||
import type { Field } from 'payload/types'
|
||||
|
||||
export const MyArrayField: Field = {
|
||||
// ...
|
||||
@@ -81,18 +81,18 @@ export const MyArrayField: Field = {
|
||||
|
||||
The Array Field inherits all of the default options from the base [Field Admin Config](../admin/fields#admin-options), plus the following additional options:
|
||||
|
||||
| Option | Description |
|
||||
| ------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| **`initCollapsed`** | Set the initial collapsed state |
|
||||
| **`components.RowLabel`** | React component to be rendered as the label on the array row. [Example](#example-of-a-custom-rowlabel-component) |
|
||||
| **`isSortable`** | Disable order sorting by setting this value to `false` |
|
||||
| Option | Description |
|
||||
| ------------------------- | -------------------------------------------------------------------------------------------------------------------- |
|
||||
| **`initCollapsed`** | Set the initial collapsed state |
|
||||
| **`components.RowLabel`** | Function or React component to be rendered as the label on the array row. Receives `({ data, index, path })` as args |
|
||||
| **`isSortable`** | Disable order sorting by setting this value to `false` |
|
||||
|
||||
## Example
|
||||
|
||||
In this example, we have an Array Field called `slider` that contains a set of fields for a simple image slider. Each row in the array has a `title`, `image`, and `caption`. We also customize the row label to display the title if it exists, or a default label if it doesn't.
|
||||
|
||||
```ts
|
||||
import type { CollectionConfig } from 'payload'
|
||||
import { CollectionConfig } from 'payload'
|
||||
|
||||
export const ExampleCollection: CollectionConfig = {
|
||||
slug: 'example-collection',
|
||||
@@ -127,27 +127,12 @@ export const ExampleCollection: CollectionConfig = {
|
||||
],
|
||||
admin: {
|
||||
components: {
|
||||
RowLabel: '/path/to/ArrayRowLabel#ArrayRowLabel',
|
||||
RowLabel: ({ data, index }) => {
|
||||
return data?.title || `Slide ${String(index).padStart(2, '0')}`
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
}
|
||||
```
|
||||
|
||||
### Example of a custom RowLabel component
|
||||
|
||||
|
||||
```tsx
|
||||
'use client'
|
||||
|
||||
import { useRowLabel } from '@payloadcms/ui'
|
||||
|
||||
export const ArrayRowLabel = () => {
|
||||
const { data, rowNumber } = useRowLabel<{ title?: string }>()
|
||||
|
||||
const customLabel = `${data.title || 'Slide'} ${String(rowNumber).padStart(2, '0')} `
|
||||
|
||||
return <div>Custom Label: {customLabel}</div>
|
||||
}
|
||||
```
|
||||
|
||||
@@ -24,7 +24,7 @@ Blocks are a great way to create a flexible content model that can be used to bu
|
||||
To add a Blocks Field, set the `type` to `blocks` in your [Field Config](./overview):
|
||||
|
||||
```ts
|
||||
import type { Field } from 'payload'
|
||||
import type { Field } from 'payload/types'
|
||||
|
||||
export const MyBlocksField: Field = {
|
||||
// ...
|
||||
@@ -67,7 +67,7 @@ _\* An asterisk denotes that a property is required._
|
||||
The customize the appearance and behavior of the Blocks Field in the [Admin Panel](../admin/overview), you can use the `admin` option:
|
||||
|
||||
```ts
|
||||
import type { Field } from 'payload'
|
||||
import type { Field } from 'payload/types'
|
||||
|
||||
export const MyBlocksField: Field = {
|
||||
// ...
|
||||
|
||||
@@ -18,7 +18,7 @@ The Checkbox Field saves a boolean in the database.
|
||||
To add a Checkbox Field, set the `type` to `checkbox` in your [Field Config](./overview):
|
||||
|
||||
```ts
|
||||
import type { Field } from 'payload'
|
||||
import type { Field } from 'payload/types'
|
||||
|
||||
export const MyCheckboxField: Field = {
|
||||
// ...
|
||||
@@ -53,7 +53,7 @@ _\* An asterisk denotes that a property is required._
|
||||
Here is an example of a Checkbox Field in a Collection:
|
||||
|
||||
```ts
|
||||
import type { CollectionConfig } from 'payload'
|
||||
import { CollectionConfig } from 'payload'
|
||||
|
||||
export const ExampleCollection: CollectionConfig = {
|
||||
slug: 'example-collection',
|
||||
|
||||
@@ -19,7 +19,7 @@ The Code Field saves a string in the database, but provides the [Admin Panel](..
|
||||
To add a Code Field, set the `type` to `code` in your [Field Config](./overview):
|
||||
|
||||
```ts
|
||||
import type { Field } from 'payload'
|
||||
import type { Field } from 'payload/types'
|
||||
|
||||
export const MyBlocksField: Field = {
|
||||
// ...
|
||||
@@ -57,7 +57,7 @@ _\* An asterisk denotes that a property is required._
|
||||
The customize the appearance and behavior of the Code Field in the [Admin Panel](../admin/overview), you can use the `admin` option:
|
||||
|
||||
```ts
|
||||
import type { Field } from 'payload'
|
||||
import type { Field } from 'payload/types'
|
||||
|
||||
export const MyCodeField: Field = {
|
||||
// ...
|
||||
@@ -79,7 +79,7 @@ The Code Field inherits all of the default options from the base [Field Admin Co
|
||||
`collections/ExampleCollection.ts
|
||||
|
||||
```ts
|
||||
import type { CollectionConfig } from 'payload'
|
||||
import { CollectionConfig } from 'payload'
|
||||
|
||||
export const ExampleCollection: CollectionConfig = {
|
||||
slug: 'example-collection',
|
||||
|
||||
@@ -18,7 +18,7 @@ The Collapsible Field is presentational-only and only affects the Admin Panel. B
|
||||
To add a Collapsible Field, set the `type` to `collapsible` in your [Field Config](./overview):
|
||||
|
||||
```ts
|
||||
import type { Field } from 'payload'
|
||||
import type { Field } from 'payload/types'
|
||||
|
||||
export const MyCollapsibleField: Field = {
|
||||
// ...
|
||||
@@ -47,7 +47,7 @@ _\* An asterisk denotes that a property is required._
|
||||
The customize the appearance and behavior of the Collapsible Field in the [Admin Panel](../admin/overview), you can use the `admin` option:
|
||||
|
||||
```ts
|
||||
import type { Field } from 'payload'
|
||||
import type { Field } from 'payload/types'
|
||||
|
||||
export const MyCollapsibleField: Field = {
|
||||
// ...
|
||||
@@ -68,7 +68,7 @@ The Collapsible Field inherits all of the default options from the base [Field A
|
||||
`collections/ExampleCollection.ts`
|
||||
|
||||
```ts
|
||||
import type { CollectionConfig } from 'payload'
|
||||
import { CollectionConfig } from 'payload'
|
||||
|
||||
export const ExampleCollection: CollectionConfig = {
|
||||
slug: 'example-collection',
|
||||
|
||||
@@ -18,7 +18,7 @@ The Date Field saves a Date in the database and provides the [Admin Panel](../ad
|
||||
To add a Date Field, set the `type` to `date` in your [Field Config](./overview):
|
||||
|
||||
```ts
|
||||
import type { Field } from 'payload'
|
||||
import type { Field } from 'payload/types'
|
||||
|
||||
export const MyDateField: Field = {
|
||||
// ...
|
||||
@@ -53,7 +53,7 @@ _\* An asterisk denotes that a property is required._
|
||||
The customize the appearance and behavior of the Date Field in the [Admin Panel](../admin/overview), you can use the `admin` option:
|
||||
|
||||
```ts
|
||||
import type { Field } from 'payload'
|
||||
import type { Field } from 'payload/types'
|
||||
|
||||
export const MyDateField: Field = {
|
||||
// ...
|
||||
@@ -97,7 +97,7 @@ When only `pickerAppearance` is set, an equivalent format will be rendered in th
|
||||
`collections/ExampleCollection.ts`
|
||||
|
||||
```ts
|
||||
import type { CollectionConfig } from 'payload'
|
||||
import { CollectionConfig } from 'payload'
|
||||
|
||||
export const ExampleCollection: CollectionConfig = {
|
||||
slug: 'example-collection',
|
||||
|
||||
@@ -18,7 +18,7 @@ The Email Field enforces that the value provided is a valid email address.
|
||||
To create an Email Field, set the `type` to `email` in your [Field Config](./overview):
|
||||
|
||||
```ts
|
||||
import type { Field } from 'payload'
|
||||
import type { Field } from 'payload/types'
|
||||
|
||||
export const MyEmailField: Field = {
|
||||
// ...
|
||||
@@ -54,7 +54,7 @@ _\* An asterisk denotes that a property is required._
|
||||
The customize the appearance and behavior of the Email Field in the [Admin Panel](../admin/overview), you can use the `admin` option:
|
||||
|
||||
```ts
|
||||
import type { Field } from 'payload'
|
||||
import type { Field } from 'payload/types'
|
||||
|
||||
export const MyEmailField: Field = {
|
||||
// ...
|
||||
@@ -76,7 +76,7 @@ The Email Field inherits all of the default options from the base [Field Admin C
|
||||
`collections/ExampleCollection.ts`
|
||||
|
||||
```ts
|
||||
import type { CollectionConfig } from 'payload'
|
||||
import { CollectionConfig } from 'payload'
|
||||
|
||||
export const ExampleCollection: CollectionConfig = {
|
||||
slug: 'example-collection',
|
||||
|
||||
@@ -18,7 +18,7 @@ The Group Field allows [Fields](./overview) to be nested under a common property
|
||||
To add a Group Field, set the `type` to `group` in your [Field Config](./overview):
|
||||
|
||||
```ts
|
||||
import type { Field } from 'payload'
|
||||
import type { Field } from 'payload/types'
|
||||
|
||||
export const MyGroupField: Field = {
|
||||
// ...
|
||||
@@ -58,7 +58,7 @@ _\* An asterisk denotes that a property is required._
|
||||
The customize the appearance and behavior of the Group Field in the [Admin Panel](../admin/overview), you can use the `admin` option:
|
||||
|
||||
```ts
|
||||
import type { Field } from 'payload'
|
||||
import type { Field } from 'payload/types'
|
||||
|
||||
export const MyGroupField: Field = {
|
||||
// ...
|
||||
@@ -79,7 +79,7 @@ The Group Field inherits all of the default options from the base [Field Admin C
|
||||
`collections/ExampleCollection.ts`
|
||||
|
||||
```ts
|
||||
import type { CollectionConfig } from 'payload'
|
||||
import { CollectionConfig } from 'payload'
|
||||
|
||||
export const ExampleCollection: CollectionConfig = {
|
||||
slug: 'example-collection',
|
||||
|
||||
@@ -6,10 +6,8 @@ desc: The Join field provides the ability to work on related documents. Learn ho
|
||||
keywords: join, relationship, junction, fields, config, configuration, documentation, Content Management System, cms, headless, javascript, node, react, nextjs
|
||||
---
|
||||
|
||||
The Join Field is used to make Relationship and Upload fields available in the opposite direction. With a Join you can
|
||||
edit and view collections
|
||||
having reference to a specific collection document. The field itself acts as a virtual field, in that no new data is
|
||||
stored on the collection with a Join
|
||||
The Join Field is used to make Relationship fields in the opposite direction. It is used to show the relationship from
|
||||
the other side. The field itself acts as a virtual field, in that no new data is stored on the collection with a Join
|
||||
field. Instead, the Admin UI surfaces the related documents for a better editing experience and is surfaced by Payload's
|
||||
APIs.
|
||||
|
||||
@@ -18,21 +16,20 @@ The Join field is useful in scenarios including:
|
||||
- To surface `Order`s for a given `Product`
|
||||
- To view and edit `Posts` belonging to a `Category`
|
||||
- To work with any bi-directional relationship data
|
||||
- Displaying where a document or upload is used in other documents
|
||||
|
||||
<LightDarkImage
|
||||
srcLight="https://payloadcms.com/images/docs/fields/join.png"
|
||||
srcDark="https://payloadcms.com/images/docs/fields/join-dark.png"
|
||||
alt="Shows Join field in the Payload Admin Panel"
|
||||
caption="Admin Panel screenshot of Join field"
|
||||
srcLight="https://payloadcms.com/images/docs/fields/join.png"
|
||||
srcDark="https://payloadcms.com/images/docs/fields/join-dark.png"
|
||||
alt="Shows Join field in the Payload Admin Panel"
|
||||
caption="Admin Panel screenshot of Join field"
|
||||
/>
|
||||
|
||||
For the Join field to work, you must have an existing [relationship](./relationship) or [upload](./upload) field in the
|
||||
collection you are joining. This will reference the collection and path of the field of the related documents.
|
||||
For the Join field to work, you must have an existing [relationship](./relationship) field in the collection you are
|
||||
joining. This will reference the collection and path of the field of the related documents.
|
||||
To add a Relationship Field, set the `type` to `join` in your [Field Config](./overview):
|
||||
|
||||
```ts
|
||||
import type { Field } from 'payload'
|
||||
import type { Field } from 'payload/types'
|
||||
|
||||
export const MyJoinField: Field = {
|
||||
// highlight-start
|
||||
@@ -52,7 +49,8 @@ export const MyRelationshipField: Field = {
|
||||
```
|
||||
|
||||
In this example, the field is defined to show the related `posts` when added to a `category` collection. The `on`
|
||||
property is used to specify the relationship field name of the field that relates to the collection document.
|
||||
property is used to
|
||||
specify the relationship field name of the field that relates to the collection document.
|
||||
|
||||
With this example, if you navigate to a Category in the Admin UI or an API response, you'll now see that the Posts which
|
||||
are related to the Category are populated for you. This is extremely powerful and can be used to define a wide variety
|
||||
@@ -113,41 +111,30 @@ related docs from a new pseudo-junction collection called `categories_posts`. No
|
||||
third junction collection, and can be surfaced on both Posts and Categories. But, importantly, you could add
|
||||
additional "context" fields to this shared junction collection.
|
||||
|
||||
For example, on this `categories_posts` collection, in addition to having the `category` and `post` fields, we could add
|
||||
custom "context" fields like `featured` or `spotlight`,
|
||||
which would allow you to store additional information directly on relationships.
|
||||
The `join` field gives you complete control over any type of relational architecture in Payload, all wrapped up in a
|
||||
powerful Admin UI.
|
||||
For example, on this `categories_posts` collection, in addition to having the `category` and
|
||||
post` fields, we could add custom "context" fields like `featured` or `
|
||||
spotlight`, which would allow you to store additional information directly on relationships. The `join` field gives you
|
||||
complete control over any type of relational architecture in Payload, all wrapped up in a powerful Admin UI.
|
||||
|
||||
## Config Options
|
||||
|
||||
| Option | Description |
|
||||
|------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| **`name`** \* | To be used as the property name when retrieved from the database. [More](/docs/fields/overview#field-names) |
|
||||
| **`collection`** \* | The `slug`s having the relationship field. |
|
||||
| **`on`** \* | The name of the relationship or upload field that relates to the collection document. Use dot notation for nested paths, like 'myGroup.relationName'. |
|
||||
| **`maxDepth`** | Default is 1, Sets a maximum population depth for this field, regardless of the remaining depth when this field is reached. [Max Depth](/docs/getting-started/concepts#field-level-max-depth). |
|
||||
| **`label`** | Text used as a field label in the Admin Panel or an object with keys for each language. |
|
||||
| **`hooks`** | Provide Field Hooks to control logic for this field. [More details](../hooks/fields). |
|
||||
| **`access`** | Provide Field Access Control to denote what users can see and do with this field's data. [More details](../access-control/fields). |
|
||||
| **`defaultLimit`** | The number of documents to return. Set to 0 to return all related documents. |
|
||||
| **`defaultSort`** | The field name used to specify the order the joined documents are returned. |
|
||||
| **`admin`** | Admin-specific configuration. [More details](#admin-config-options). |
|
||||
| **`custom`** | Extension point for adding custom data (e.g. for plugins). |
|
||||
| **`typescriptSchema`** | Override field type generation with providing a JSON schema. |
|
||||
| Option | Description |
|
||||
|------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| **`name`** \* | To be used as the property name when retrieved from the database. [More](/docs/fields/overview#field-names) |
|
||||
| **`collection`** \* | The `slug`s having the relationship field. |
|
||||
| **`on`** \* | The relationship field name of the field that relates to collection document. Use dot notation for nested paths, like 'myGroup.relationName'. |
|
||||
| **`maxDepth`** | Default is 1, Sets a maximum population depth for this field, regardless of the remaining depth when this field is reached. [Max Depth](/docs/getting-started/concepts#field-level-max-depth) |
|
||||
| **`label`** | Text used as a field label in the Admin Panel or an object with keys for each language. |
|
||||
| **`hooks`** | Provide Field Hooks to control logic for this field. [More details](../hooks/fields). |
|
||||
| **`access`** | Provide Field Access Control to denote what users can see and do with this field's data. [More details](../access-control/fields). |
|
||||
| **`localized`** | Enable localization for this field. Requires [localization to be enabled](/docs/configuration/localization) in the Base config. |
|
||||
| **`required`** | Require this field to have a value. |
|
||||
| **`admin`** | Admin-specific configuration. |
|
||||
| **`custom`** | Extension point for adding custom data (e.g. for plugins) |
|
||||
| **`typescriptSchema`** | Override field type generation with providing a JSON schema |
|
||||
|
||||
_\* An asterisk denotes that a property is required._
|
||||
|
||||
|
||||
## Admin Config Options
|
||||
|
||||
You can control the user experience of the join field using the `admin` config properties. The following options are supported:
|
||||
|
||||
| Option | Description |
|
||||
|------------------------|----------------------------------------------------------------------------------------|
|
||||
| **`allowCreate`** | Set to `false` to remove the controls for making new related documents from this field. |
|
||||
| **`components.Label`** | Override the default Label of the Field Component. [More details](#the-label-component). |
|
||||
|
||||
## Join Field Data
|
||||
|
||||
When a document is returned that for a Join field is populated with related documents. The structure returned is an
|
||||
@@ -164,12 +151,12 @@ object with:
|
||||
{
|
||||
"id": "66e3431a3f23e684075aaeb9",
|
||||
// other fields...
|
||||
"category": "66e3431a3f23e684075aae9c"
|
||||
}
|
||||
"category": "66e3431a3f23e684075aae9c",
|
||||
},
|
||||
// { ... }
|
||||
],
|
||||
"hasNextPage": false
|
||||
}
|
||||
},
|
||||
// other fields...
|
||||
}
|
||||
```
|
||||
@@ -227,8 +214,7 @@ You can specify as many `joins` parameters as needed for the same or different j
|
||||
|
||||
### GraphQL
|
||||
|
||||
The GraphQL API supports the same query options as the local and REST APIs. You can specify the query options for each
|
||||
join field in your query.
|
||||
The GraphQL API supports the same query options as the local and REST APIs. You can specify the query options for each join field in your query.
|
||||
|
||||
Example:
|
||||
|
||||
@@ -241,9 +227,9 @@ query {
|
||||
limit: 5
|
||||
where: {
|
||||
author: {
|
||||
equals: "66e3431a3f23e684075aaeb9"
|
||||
equals: "66e3431a3f23e684075aaeb9"
|
||||
}
|
||||
}
|
||||
}
|
||||
) {
|
||||
docs {
|
||||
title
|
||||
|
||||
@@ -19,7 +19,7 @@ The JSON Field saves actual JSON in the database, which differs from the Code fi
|
||||
To add a JSON Field, set the `type` to `json` in your [Field Config](./overview):
|
||||
|
||||
```ts
|
||||
import type { Field } from 'payload'
|
||||
import type { Field } from 'payload/types'
|
||||
|
||||
export const MyJSONField: Field = {
|
||||
// ...
|
||||
@@ -56,7 +56,7 @@ _\* An asterisk denotes that a property is required._
|
||||
The customize the appearance and behavior of the JSON Field in the [Admin Panel](../admin/overview), you can use the `admin` option:
|
||||
|
||||
```ts
|
||||
import type { Field } from 'payload'
|
||||
import type { Field } from 'payload/types'
|
||||
|
||||
export const MyJSONField: Field = {
|
||||
// ...
|
||||
@@ -77,7 +77,7 @@ The JSON Field inherits all of the default options from the base [Field Admin Co
|
||||
`collections/ExampleCollection.ts`
|
||||
|
||||
```ts
|
||||
import type { CollectionConfig } from 'payload'
|
||||
import { CollectionConfig } from 'payload'
|
||||
|
||||
export const ExampleCollection: CollectionConfig = {
|
||||
slug: 'example-collection',
|
||||
@@ -102,7 +102,7 @@ If you only provide a URL to a schema, Payload will fetch the desired schema if
|
||||
`collections/ExampleCollection.ts`
|
||||
|
||||
```ts
|
||||
import type { CollectionConfig } from 'payload'
|
||||
import { CollectionConfig } from 'payload'
|
||||
|
||||
export const ExampleCollection: CollectionConfig = {
|
||||
slug: 'example-collection',
|
||||
@@ -135,7 +135,7 @@ export const ExampleCollection: CollectionConfig = {
|
||||
`collections/ExampleCollection.ts`
|
||||
|
||||
```ts
|
||||
import type { CollectionConfig } from 'payload'
|
||||
import { CollectionConfig } from 'payload'
|
||||
|
||||
export const ExampleCollection: CollectionConfig = {
|
||||
slug: 'example-collection',
|
||||
|
||||
@@ -18,7 +18,7 @@ The Number Field stores and validates numeric entry and supports additional nume
|
||||
To add a Number Field, set the `type` to `number` in your [Field Config](./overview):
|
||||
|
||||
```ts
|
||||
import type { Field } from 'payload'
|
||||
import type { Field } from 'payload/types'
|
||||
|
||||
export const MyNumberField: Field = {
|
||||
// ...
|
||||
@@ -59,7 +59,7 @@ _\* An asterisk denotes that a property is required._
|
||||
The customize the appearance and behavior of the Number Field in the [Admin Panel](../admin/overview), you can use the `admin` option:
|
||||
|
||||
```ts
|
||||
import type { Field } from 'payload'
|
||||
import type { Field } from 'payload/types'
|
||||
|
||||
export const MyNumberField: Field = {
|
||||
// ...
|
||||
@@ -82,7 +82,7 @@ The Number Field inherits all of the default options from the base [Field Admin
|
||||
`collections/ExampleCollection.ts`
|
||||
|
||||
```ts
|
||||
import type { CollectionConfig } from 'payload'
|
||||
import { CollectionConfig } from 'payload'
|
||||
|
||||
export const ExampleCollection: CollectionConfig = {
|
||||
slug: 'example-collection',
|
||||
|
||||
@@ -18,7 +18,7 @@ The Point Field saves a pair of coordinates in the database and assigns an index
|
||||
To add a Point Field, set the `type` to `point` in your [Field Config](./overview):
|
||||
|
||||
```ts
|
||||
import type { Field } from 'payload'
|
||||
import type { Field } from 'payload/types'
|
||||
|
||||
export const MyPointField: Field = {
|
||||
// ...
|
||||
@@ -59,7 +59,7 @@ _\* An asterisk denotes that a property is required._
|
||||
`collections/ExampleCollection.ts`
|
||||
|
||||
```ts
|
||||
import type { CollectionConfig } from 'payload'
|
||||
import { CollectionConfig } from 'payload'
|
||||
|
||||
export const ExampleCollection: CollectionConfig = {
|
||||
slug: 'example-collection',
|
||||
|
||||
@@ -18,7 +18,7 @@ The Radio Field allows for the selection of one value from a predefined set of p
|
||||
To add a Radio Field, set the `type` to `radio` in your [Field Config](./overview):
|
||||
|
||||
```ts
|
||||
import type { Field } from 'payload'
|
||||
import type { Field } from 'payload/types'
|
||||
|
||||
export const MyRadioField: Field = {
|
||||
// ...
|
||||
@@ -69,7 +69,7 @@ _\* An asterisk denotes that a property is required._
|
||||
The customize the appearance and behavior of the Radio Field in the [Admin Panel](../admin/overview), you can use the `admin` option:
|
||||
|
||||
```ts
|
||||
import type { Field } from 'payload'
|
||||
import type { Field } from 'payload/types'
|
||||
|
||||
export const MyRadioField: Field = {
|
||||
// ...
|
||||
@@ -83,14 +83,14 @@ The Radio Field inherits all of the default options from the base [Field Admin C
|
||||
|
||||
| Property | Description |
|
||||
| ------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| **`layout`** | Allows for the radio group to be styled as a horizontally or vertically distributed list. The default value is `horizontal`. |
|
||||
| **`layout`** | Allows for the radio group to be styled as a horizonally or vertically distributed list. The default value is `horizontal`. |
|
||||
|
||||
## Example
|
||||
|
||||
`collections/ExampleCollection.ts`
|
||||
|
||||
```ts
|
||||
import type { CollectionConfig } from 'payload'
|
||||
import { CollectionConfig } from 'payload'
|
||||
|
||||
export const ExampleCollection: CollectionConfig = {
|
||||
slug: 'example-collection',
|
||||
|
||||
@@ -24,7 +24,7 @@ The Relationship field is used in a variety of ways, including:
|
||||
To add a Relationship Field, set the `type` to `relationship` in your [Field Config](./overview):
|
||||
|
||||
```ts
|
||||
import type { Field } from 'payload'
|
||||
import type { Field } from 'payload/types'
|
||||
|
||||
export const MyRelationshipField: Field = {
|
||||
// ...
|
||||
@@ -74,7 +74,7 @@ _\* An asterisk denotes that a property is required._
|
||||
The customize the appearance and behavior of the Relationship Field in the [Admin Panel](../admin/overview), you can use the `admin` option:
|
||||
|
||||
```ts
|
||||
import type { Field } from 'payload'
|
||||
import type { Field } from 'payload/types'
|
||||
|
||||
export const MyRelationshipField: Field = {
|
||||
// ...
|
||||
@@ -90,7 +90,6 @@ The Relationship Field inherits all of the default options from the base [Field
|
||||
| ------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| **`isSortable`** | Set to `true` if you'd like this field to be sortable within the Admin UI using drag and drop (only works when `hasMany` is set to `true`). |
|
||||
| **`allowCreate`** | Set to `false` if you'd like to disable the ability to create new documents from within the relationship field. |
|
||||
| **`allowEdit`** | Set to `false` if you'd like to disable the ability to edit documents from within the relationship field. |
|
||||
| **`sortOptions`** | Define a default sorting order for the options within a Relationship field's dropdown. [More](#sortOptions) |
|
||||
|
||||
### Sort Options
|
||||
@@ -159,7 +158,7 @@ called with an argument object with the following properties:
|
||||
## Example
|
||||
|
||||
```ts
|
||||
import type { CollectionConfig } from 'payload'
|
||||
import { CollectionConfig } from 'payload'
|
||||
|
||||
export const ExampleCollection: CollectionConfig = {
|
||||
slug: 'example-collection',
|
||||
|
||||
@@ -25,7 +25,11 @@ Right now, Payload is officially supporting two rich text editors:
|
||||
<Banner type="success">
|
||||
<strong>
|
||||
Consistent with Payload's goal of making you learn as little of Payload as possible, customizing
|
||||
and using the Rich Text Editor does not involve learning how to develop for a{' '}<em>Payload</em>{' '}rich text editor.
|
||||
and using the Rich Text Editor does not involve learning how to develop for a
|
||||
{' '}
|
||||
<em>Payload</em>
|
||||
{' '}
|
||||
rich text editor.
|
||||
</strong>
|
||||
|
||||
Instead, you can invest your time and effort into learning the underlying open-source tools that
|
||||
@@ -59,7 +63,7 @@ _\* An asterisk denotes that a property is required._
|
||||
The customize the appearance and behavior of the Rich Text Field in the [Admin Panel](../admin/overview), you can use the `admin` option:
|
||||
|
||||
```ts
|
||||
import type { Field } from 'payload'
|
||||
import type { Field } from 'payload/types'
|
||||
|
||||
export const MyRichTextField: Field = {
|
||||
// ...
|
||||
|
||||
@@ -18,7 +18,7 @@ The Row Field is presentational-only and only affects the [Admin Panel](../admin
|
||||
To add a Row Field, set the `type` to `row` in your [Field Config](./overview):
|
||||
|
||||
```ts
|
||||
import type { Field } from 'payload'
|
||||
import type { Field } from 'payload/types'
|
||||
|
||||
export const MyRowField: Field = {
|
||||
// ...
|
||||
@@ -46,7 +46,7 @@ _\* An asterisk denotes that a property is required._
|
||||
`collections/ExampleCollection.ts`
|
||||
|
||||
```ts
|
||||
import type { CollectionConfig } from 'payload'
|
||||
import { CollectionConfig } from 'payload'
|
||||
|
||||
export const ExampleCollection: CollectionConfig = {
|
||||
slug: 'example-collection',
|
||||
|
||||
@@ -18,7 +18,7 @@ The Select Field provides a dropdown-style interface for choosing options from a
|
||||
To add a Select Field, set the `type` to `select` in your [Field Config](./overview):
|
||||
|
||||
```ts
|
||||
import type { Field } from 'payload'
|
||||
import type { Field } from 'payload/types'
|
||||
|
||||
export const MySelectField: Field = {
|
||||
// ...
|
||||
@@ -71,7 +71,7 @@ _\* An asterisk denotes that a property is required._
|
||||
The customize the appearance and behavior of the Select Field in the [Admin Panel](../admin/overview), you can use the `admin` option:
|
||||
|
||||
```ts
|
||||
import type { Field } from 'payload'
|
||||
import type { Field } from 'payload/types'
|
||||
|
||||
export const MySelectField: Field = {
|
||||
// ...
|
||||
@@ -93,7 +93,7 @@ The Select Field inherits all of the default options from the base [Field Admin
|
||||
`collections/ExampleCollection.ts`
|
||||
|
||||
```ts
|
||||
import type { CollectionConfig } from 'payload'
|
||||
import { CollectionConfig } from 'payload'
|
||||
|
||||
export const ExampleCollection: CollectionConfig = {
|
||||
slug: 'example-collection',
|
||||
@@ -156,7 +156,8 @@ You can import the existing Select component directly from Payload, then extend
|
||||
|
||||
```ts
|
||||
import * as React from 'react';
|
||||
import { SelectInput, useAuth, useField } from '@payloadcms/ui';
|
||||
import { SelectInput, useField } from 'payload/components/forms';
|
||||
import { useAuth } from 'payload/components/utilities';
|
||||
|
||||
type CustomSelectProps = {
|
||||
path: string;
|
||||
|
||||
@@ -18,7 +18,7 @@ The Tabs Field is presentational-only and only affects the [Admin Panel](../admi
|
||||
To add a Tabs Field, set the `type` to `tabs` in your [Field Config](./overview):
|
||||
|
||||
```ts
|
||||
import type { Field } from 'payload'
|
||||
import type { Field } from 'payload/types'
|
||||
|
||||
export const MyTabsField: Field = {
|
||||
// ...
|
||||
@@ -59,7 +59,7 @@ _\* An asterisk denotes that a property is required._
|
||||
`collections/ExampleCollection.ts`
|
||||
|
||||
```ts
|
||||
import type { CollectionConfig } from 'payload'
|
||||
import { CollectionConfig } from 'payload'
|
||||
|
||||
export const ExampleCollection: CollectionConfig = {
|
||||
slug: 'example-collection',
|
||||
|
||||
@@ -18,7 +18,7 @@ The Text Field is one of the most commonly used fields. It saves a string to the
|
||||
To add a Text Field, set the `type` to `text` in your [Field Config](./overview):
|
||||
|
||||
```ts
|
||||
import type { Field } from 'payload'
|
||||
import type { Field } from 'payload/types'
|
||||
|
||||
export const MyTextField: Field = {
|
||||
// ...
|
||||
@@ -59,7 +59,7 @@ _\* An asterisk denotes that a property is required._
|
||||
The customize the appearance and behavior of the Text Field in the [Admin Panel](../admin/overview), you can use the `admin` option:
|
||||
|
||||
```ts
|
||||
import type { Field } from 'payload'
|
||||
import type { Field } from 'payload/types'
|
||||
|
||||
export const MyTextField: Field = {
|
||||
// ...
|
||||
@@ -82,7 +82,7 @@ The Text Field inherits all of the default options from the base [Field Admin Co
|
||||
`collections/ExampleCollection.ts`
|
||||
|
||||
```ts
|
||||
import type { CollectionConfig } from 'payload'
|
||||
import { CollectionConfig } from 'payload'
|
||||
|
||||
export const ExampleCollection: CollectionConfig = {
|
||||
slug: 'example-collection',
|
||||
|
||||
@@ -18,7 +18,7 @@ The Textarea Field is nearly identical to the [Text Field](./text) but it featur
|
||||
To add a Textarea Field, set the `type` to `textarea` in your [Field Config](./overview):
|
||||
|
||||
```ts
|
||||
import type { Field } from 'payload'
|
||||
import type { Field } from 'payload/types'
|
||||
|
||||
export const MyTextareaField: Field = {
|
||||
// ...
|
||||
@@ -56,7 +56,7 @@ _\* An asterisk denotes that a property is required._
|
||||
The customize the appearance and behavior of the Textarea Field in the [Admin Panel](../admin/overview), you can use the `admin` option:
|
||||
|
||||
```ts
|
||||
import type { Field } from 'payload'
|
||||
import type { Field } from 'payload/types'
|
||||
|
||||
export const MyTextareaField: Field = {
|
||||
// ...
|
||||
@@ -79,7 +79,7 @@ The Textarea Field inherits all of the default options from the base [Field Admi
|
||||
`collections/ExampleCollection.ts`
|
||||
|
||||
```ts
|
||||
import type { CollectionConfig } from 'payload'
|
||||
import { CollectionConfig } from 'payload'
|
||||
|
||||
export const ExampleCollection: CollectionConfig = {
|
||||
slug: 'example-collection',
|
||||
|
||||
@@ -18,7 +18,7 @@ With the UI Field, you can:
|
||||
To add a UI Field, set the `type` to `ui` in your [Field Config](./overview):
|
||||
|
||||
```ts
|
||||
import type { Field } from 'payload'
|
||||
import type { Field } from 'payload/types'
|
||||
|
||||
export const MyUIField: Field = {
|
||||
// ...
|
||||
@@ -28,14 +28,14 @@ export const MyUIField: Field = {
|
||||
|
||||
## Config Options
|
||||
|
||||
| Option | Description |
|
||||
| ------------------------------- | ------------------------------------------------------------------------------------------------------------------- |
|
||||
| **`name`** \* | A unique identifier for this field. |
|
||||
| **`label`** | Human-readable label for this UI field. |
|
||||
| Option | Description |
|
||||
| ------------------------------- | ---------------------------------------------------------------------------------------------------------------------- |
|
||||
| **`name`** \* | A unique identifier for this field. |
|
||||
| **`label`** | Human-readable label for this UI field. |
|
||||
| **`admin.components.Field`** \* | React component to be rendered for this field within the Edit View. [More](../admin/components/#field-component) |
|
||||
| **`admin.components.Cell`** | React component to be rendered as a Cell within collection List views. [More](../admin/components/#field-component) |
|
||||
| **`admin.disableListColumn`** | Set `disableListColumn` to `true` to prevent the UI field from appearing in the list view column selector. |
|
||||
| **`custom`** | Extension point for adding custom data (e.g. for plugins) |
|
||||
| **`admin.disableListColumn`** | Set `disableListColumn` to `true` to prevent the UI field from appearing in the list view column selector. |
|
||||
| **`custom`** | Extension point for adding custom data (e.g. for plugins) |
|
||||
|
||||
_\* An asterisk denotes that a property is required._
|
||||
|
||||
@@ -44,7 +44,7 @@ _\* An asterisk denotes that a property is required._
|
||||
`collections/ExampleCollection.ts`
|
||||
|
||||
```ts
|
||||
import type { CollectionConfig } from 'payload'
|
||||
import { CollectionConfig } from 'payload'
|
||||
|
||||
export const ExampleCollection: CollectionConfig = {
|
||||
slug: 'example-collection',
|
||||
|
||||
@@ -6,8 +6,7 @@ desc: Upload fields will allow a file to be uploaded, only from a collection sup
|
||||
keywords: upload, images media, fields, config, configuration, documentation, Content Management System, cms, headless, javascript, node, react, nextjs
|
||||
---
|
||||
|
||||
The Upload Field allows for the selection of a Document from a Collection supporting [Uploads](../upload/overview), and
|
||||
formats the selection as a thumbnail in the Admin Panel.
|
||||
The Upload Field allows for the selection of a Document from a Collection supporting [Uploads](../upload/overview), and formats the selection as a thumbnail in the Admin Panel.
|
||||
|
||||
Upload fields are useful for a variety of use cases, such as:
|
||||
|
||||
@@ -16,16 +15,16 @@ Upload fields are useful for a variety of use cases, such as:
|
||||
- To give a layout building block the ability to feature a background image
|
||||
|
||||
<LightDarkImage
|
||||
srcLight="https://payloadcms.com/images/docs/fields/upload.png"
|
||||
srcDark="https://payloadcms.com/images/docs/fields/upload-dark.png"
|
||||
alt="Shows an upload field in the Payload Admin Panel"
|
||||
caption="Admin Panel screenshot of an Upload field"
|
||||
srcLight="https://payloadcms.com/images/docs/fields/upload.png"
|
||||
srcDark="https://payloadcms.com/images/docs/fields/upload-dark.png"
|
||||
alt="Shows an upload field in the Payload Admin Panel"
|
||||
caption="Admin Panel screenshot of an Upload field"
|
||||
/>
|
||||
|
||||
To create an Upload Field, set the `type` to `upload` in your [Field Config](./overview):
|
||||
|
||||
```ts
|
||||
import type { Field } from 'payload'
|
||||
import type { Field } from 'payload/types'
|
||||
|
||||
export const MyUploadField: Field = {
|
||||
// ...
|
||||
@@ -44,9 +43,9 @@ export const MyUploadField: Field = {
|
||||
## Config Options
|
||||
|
||||
| Option | Description |
|
||||
|------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| ---------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| **`name`** \* | To be used as the property name when stored and retrieved from the database. [More](/docs/fields/overview#field-names) |
|
||||
| **`relationTo`** \* | Provide a single collection `slug` to allow this field to accept a relation to. <strong>Note: the related collection must be configured to support Uploads.</strong> |
|
||||
| **`*relationTo`** \* | Provide a single collection `slug` to allow this field to accept a relation to. <strong>Note: the related collection must be configured to support Uploads.</strong> |
|
||||
| **`filterOptions`** | A query to filter which options appear in the UI and validate against. [More](#filtering-upload-options). |
|
||||
| **`maxDepth`** | Sets a number limit on iterations of related documents to populate when queried. [Depth](../queries/depth) |
|
||||
| **`label`** | Text used as a field label in the Admin Panel or an object with keys for each language. |
|
||||
@@ -73,7 +72,7 @@ _\* An asterisk denotes that a property is required._
|
||||
`collections/ExampleCollection.ts`
|
||||
|
||||
```ts
|
||||
import type { CollectionConfig } from 'payload'
|
||||
import { CollectionConfig } from 'payload'
|
||||
|
||||
export const ExampleCollection: CollectionConfig = {
|
||||
slug: 'example-collection',
|
||||
@@ -98,7 +97,7 @@ prevent all, or a `Where` query. When using a function, it will be
|
||||
called with an argument object with the following properties:
|
||||
|
||||
| Property | Description |
|
||||
|---------------|-------------------------------------------------------------------------------------------------------|
|
||||
| ------------- | ----------------------------------------------------------------------------------------------------- |
|
||||
| `relationTo` | The collection `slug` to filter against, limited to this field's `relationTo` property |
|
||||
| `data` | An object containing the full collection or global document currently being edited |
|
||||
| `siblingData` | An object containing document data that is scoped to only fields within the same parent of this field |
|
||||
@@ -128,10 +127,3 @@ You can learn more about writing queries [here](/docs/queries/overview).
|
||||
unless you call the default upload field validation function imported from{' '}
|
||||
<strong>payload/shared</strong> in your validate function.
|
||||
</Banner>
|
||||
|
||||
## Bi-directional relationships
|
||||
|
||||
The `upload` field on its own is used to reference documents in an upload collection. This can be considered a "one-way"
|
||||
relationship. If you wish to allow an editor to visit the upload document and see where it is being used, you may use
|
||||
the `join` field in the upload enabled collection. Read more about bi-directional relationships using
|
||||
the [Join field](./join)
|
||||
|
||||
@@ -54,12 +54,12 @@ To install a Database Adapter, you can run **one** of the following commands:
|
||||
|
||||
- To install the [MongoDB Adapter](../database/mongodb), run:
|
||||
```bash
|
||||
pnpm i @payloadcms/db-mongodb@beta
|
||||
pnpm i @payloadcms/db-mongodb
|
||||
```
|
||||
|
||||
- To install the [Postgres Adapter](../database/postgres), run:
|
||||
```bash
|
||||
pnpm i @payloadcms/db-postgres@beta
|
||||
pnpm i @payloadcms/db-postgres
|
||||
```
|
||||
|
||||
<Banner type="success">
|
||||
|
||||
@@ -13,7 +13,7 @@ In Payload the schema is controlled by your collections and globals. All you nee
|
||||
Install `@payloadcms/graphql` as a dev dependency:
|
||||
|
||||
```bash
|
||||
pnpm add @payloadcms/graphql@beta -D
|
||||
pnpm add @payloadcms/graphql --save-dev
|
||||
```
|
||||
|
||||
Run the following command to generate the schema:
|
||||
|
||||
@@ -139,4 +139,4 @@ declare module 'payload' {
|
||||
}
|
||||
```
|
||||
|
||||
This will add the property `myObject` with a type of string to every context object. Make sure to follow this example correctly, as type augmentation can mess up your types if you do it wrong.
|
||||
This will add a the property `myObject` with a type of string to every context object. Make sure to follow this example correctly, as type augmentation can mess up your types if you do it wrong.
|
||||
|
||||
@@ -1,382 +0,0 @@
|
||||
---
|
||||
title: Jobs Queue
|
||||
label: Jobs Queue
|
||||
order: 10
|
||||
desc: Payload provides all you need to run job queues, which are helpful to offload long-running processes into separate workers.
|
||||
keywords: jobs queue, application framework, typescript, node, react, nextjs
|
||||
---
|
||||
|
||||
## Defining tasks
|
||||
|
||||
A task is a simple function that can be executed directly or within a workflow. The difference between tasks and functions is that tasks can be run in the background, and can be retried if they fail.
|
||||
|
||||
Tasks can either be defined within the `jobs.tasks` array in your payload config, or they can be run inline within a workflow.
|
||||
|
||||
### Defining tasks in the config
|
||||
|
||||
Simply add a task to the `jobs.tasks` array in your Payload config. A task consists of the following fields:
|
||||
|
||||
| Option | Description |
|
||||
| --------------------------- | -------------------------------------------------------------------------------- |
|
||||
| `slug` | Define a slug-based name for this job. This slug needs to be unique among both tasks and workflows.|
|
||||
| `handler` | The function that should be responsible for running the job. You can either pass a string-based path to the job function file, or the job function itself. If you are using large dependencies within your job, you might prefer to pass the string path because that will avoid bundling large dependencies in your Next.js app. |
|
||||
| `inputSchema` | Define the input field schema - payload will generate a type for this schema. |
|
||||
| `interfaceName` | You can use interfaceName to change the name of the interface that is generated for this task. By default, this is "Task" + the capitalized task slug. |
|
||||
| `outputSchema` | Define the output field schema - payload will generate a type for this schema. |
|
||||
| `label` | Define a human-friendly label for this task. |
|
||||
| `onFail` | Function to be executed if the task fails. |
|
||||
| `onSuccess` | Function to be executed if the task fails. |
|
||||
| `retries` | Specify the number of times that this step should be retried if it fails. |
|
||||
|
||||
The handler is the function, or a path to the function, that will run once the job picks up this task. The handler function should return an object with an `output` key, which should contain the output of the task.
|
||||
|
||||
Example:
|
||||
|
||||
```ts
|
||||
export default buildConfig({
|
||||
// ...
|
||||
jobs: {
|
||||
tasks: [
|
||||
{
|
||||
retries: 2,
|
||||
slug: 'createPost',
|
||||
inputSchema: [
|
||||
{
|
||||
name: 'title',
|
||||
type: 'text',
|
||||
required: true,
|
||||
},
|
||||
],
|
||||
outputSchema: [
|
||||
{
|
||||
name: 'postID',
|
||||
type: 'text',
|
||||
required: true,
|
||||
},
|
||||
],
|
||||
handler: async ({ input, job, req }) => {
|
||||
const newPost = await req.payload.create({
|
||||
collection: 'post',
|
||||
req,
|
||||
data: {
|
||||
title: input.title,
|
||||
},
|
||||
})
|
||||
return {
|
||||
output: {
|
||||
postID: newPost.id,
|
||||
},
|
||||
}
|
||||
},
|
||||
} as TaskConfig<'createPost'>,
|
||||
]
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
### Example: defining external tasks
|
||||
|
||||
payload.config.ts:
|
||||
|
||||
```ts
|
||||
import { fileURLToPath } from 'node:url'
|
||||
import path from 'path'
|
||||
|
||||
const filename = fileURLToPath(import.meta.url)
|
||||
const dirname = path.dirname(filename)
|
||||
|
||||
export default buildConfig({
|
||||
// ...
|
||||
jobs: {
|
||||
tasks: [
|
||||
{
|
||||
retries: 2,
|
||||
slug: 'createPost',
|
||||
inputSchema: [
|
||||
{
|
||||
name: 'title',
|
||||
type: 'text',
|
||||
required: true,
|
||||
},
|
||||
],
|
||||
outputSchema: [
|
||||
{
|
||||
name: 'postID',
|
||||
type: 'text',
|
||||
required: true,
|
||||
},
|
||||
],
|
||||
handler: path.resolve(dirname, 'src/tasks/createPost.ts') + '#createPostHandler',
|
||||
}
|
||||
]
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
src/tasks/createPost.ts:
|
||||
|
||||
```ts
|
||||
import type { TaskHandler } from 'payload'
|
||||
|
||||
export const createPostHandler: TaskHandler<'createPost'> = async ({ input, job, req }) => {
|
||||
const newPost = await req.payload.create({
|
||||
collection: 'post',
|
||||
req,
|
||||
data: {
|
||||
title: input.title,
|
||||
},
|
||||
})
|
||||
return {
|
||||
output: {
|
||||
postID: newPost.id,
|
||||
},
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
## Defining workflows
|
||||
|
||||
There are two types of workflows - JS-based workflows and JSON-based workflows.
|
||||
|
||||
### Defining JS-based workflows
|
||||
|
||||
A JS-based function is a function in which you decide yourself when the tasks should run, by simply calling the `runTask` function. If the job, or any task within the job, fails, the entire function will re-run.
|
||||
|
||||
Tasks that have successfully been completed will simply re-return the cached output without running again, and failed tasks will be re-run.
|
||||
|
||||
Simply add a workflow to the `jobs.wokflows` array in your Payload config. A wokflow consists of the following fields:
|
||||
|
||||
| Option | Description |
|
||||
| --------------------------- | -------------------------------------------------------------------------------- |
|
||||
| `slug` | Define a slug-based name for this workflow. This slug needs to be unique among both tasks and workflows.|
|
||||
| `handler` | The function that should be responsible for running the workflow. You can either pass a string-based path to the workflow function file, or workflow job function itself. If you are using large dependencies within your workflow, you might prefer to pass the string path because that will avoid bundling large dependencies in your Next.js app. |
|
||||
| `inputSchema` | Define the input field schema - payload will generate a type for this schema. |
|
||||
| `interfaceName` | You can use interfaceName to change the name of the interface that is generated for this workflow. By default, this is "Workflow" + the capitalized workflow slug. |
|
||||
| `label` | Define a human-friendly label for this workflow. |
|
||||
| `queue` | Optionally, define the queue name that this workflow should be tied to. Defaults to "default". |
|
||||
|
||||
Example:
|
||||
|
||||
```ts
|
||||
export default buildConfig({
|
||||
// ...
|
||||
jobs: {
|
||||
tasks: [
|
||||
// ...
|
||||
]
|
||||
workflows: [
|
||||
{
|
||||
slug: 'createPostAndUpdate',
|
||||
inputSchema: [
|
||||
{
|
||||
name: 'title',
|
||||
type: 'text',
|
||||
required: true,
|
||||
},
|
||||
],
|
||||
handler: async ({ job, runTask }) => {
|
||||
const output = await runTask({
|
||||
task: 'createPost',
|
||||
id: '1',
|
||||
input: {
|
||||
title: job.input.title,
|
||||
},
|
||||
})
|
||||
|
||||
await runTask({
|
||||
task: 'updatePost',
|
||||
id: '2',
|
||||
input: {
|
||||
post: job.taskStatus.createPost['1'].output.postID, // or output.postID
|
||||
title: job.input.title + '2',
|
||||
},
|
||||
})
|
||||
},
|
||||
} as WorkflowConfig<'updatePost'>
|
||||
]
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
#### Running tasks inline
|
||||
|
||||
In order to run tasks inline without predefining them, you can use the `runTaskInline` function.
|
||||
|
||||
The drawbacks of this approach are that tasks cannot be re-used as easily, and the **task data stored in the job** will not be typed. In the following example, the inline task data will be stored on the job under `job.taskStatus.inline['2']` but completely untyped, as types for dynamic tasks like these cannot be generated beforehand.
|
||||
|
||||
Example:
|
||||
|
||||
```ts
|
||||
export default buildConfig({
|
||||
// ...
|
||||
jobs: {
|
||||
tasks: [
|
||||
// ...
|
||||
]
|
||||
workflows: [
|
||||
{
|
||||
slug: 'createPostAndUpdate',
|
||||
inputSchema: [
|
||||
{
|
||||
name: 'title',
|
||||
type: 'text',
|
||||
required: true,
|
||||
},
|
||||
],
|
||||
handler: async ({ job, runTask }) => {
|
||||
const output = await runTask({
|
||||
task: 'createPost',
|
||||
id: '1',
|
||||
input: {
|
||||
title: job.input.title,
|
||||
},
|
||||
})
|
||||
|
||||
const { newPost } = await runTaskInline({
|
||||
task: async ({ req }) => {
|
||||
const newPost = await req.payload.update({
|
||||
collection: 'post',
|
||||
id: output.postID,
|
||||
req,
|
||||
retries: 3,
|
||||
data: {
|
||||
title: 'updated!',
|
||||
},
|
||||
})
|
||||
return {
|
||||
output: {
|
||||
newPost
|
||||
},
|
||||
}
|
||||
},
|
||||
id: '2',
|
||||
})
|
||||
},
|
||||
} as WorkflowConfig<'updatePost'>
|
||||
]
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
### Defining JSON-based workflows
|
||||
|
||||
JSON-based workflows are a way to define the tasks the workflow should run in an array. The relationships between the tasks, their run order and their conditions are defined in the JSON object, which allows payload to statically analyze the workflow and will generate more helpful graphs.
|
||||
|
||||
This functionality is not available yet, but it will be available in the future.
|
||||
|
||||
## Queueing workflows and tasks
|
||||
|
||||
In order to queue a workflow or a task (= create them and add them to the queue), you can use the `payload.jobs.queue` function.
|
||||
|
||||
Example: queueing workflows:
|
||||
|
||||
```ts
|
||||
const createdJob = await payload.jobs.queue({
|
||||
workflows: 'createPostAndUpdate',
|
||||
input: {
|
||||
title: 'my title',
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
Example: queueing tasks:
|
||||
|
||||
```ts
|
||||
const createdJob = await payload.jobs.queue({
|
||||
task: 'createPost',
|
||||
input: {
|
||||
title: 'my title',
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
## Running workflows and tasks
|
||||
|
||||
Workflows and tasks added to the queue will not run unless a worker picks it up and runs it. This can be done in two ways:
|
||||
|
||||
### Endpoint
|
||||
|
||||
Make a fetch request to the `api/payload-jobs/run` endpoint:
|
||||
|
||||
```ts
|
||||
await fetch('/api/payload-jobs/run', {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Authorization': `JWT ${token}`,
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
### Local API
|
||||
|
||||
Run the payload.jobs.run function:
|
||||
|
||||
```ts
|
||||
const results = await payload.jobs.run()
|
||||
|
||||
// You can customize the queue name by passing it as an argument
|
||||
await payload.jobs.run({ queue: 'posts' })
|
||||
```
|
||||
|
||||
### Script
|
||||
|
||||
You can run the jobs:run script from the command line:
|
||||
|
||||
```sh
|
||||
npx payload jobs:run --queue default --limit 10
|
||||
```
|
||||
|
||||
#### Triggering jobs as cronjob
|
||||
|
||||
You can pass the --cron flag to the jobs:run script to run the jobs in a cronjob:
|
||||
|
||||
```sh
|
||||
npx payload jobs:run --cron "*/5 * * * *"
|
||||
```
|
||||
|
||||
### Vercel Cron
|
||||
|
||||
Vercel Cron allows scheduled tasks to be executed automatically by triggering specific endpoints. Below is a step-by-step guide to configuring Vercel Cron for running queued jobs on apps hosted on Vercel:
|
||||
|
||||
1. Add Vercel Cron Configuration: Place a vercel.json file at the root of your project with the following content:
|
||||
|
||||
```json
|
||||
{
|
||||
"crons": [
|
||||
{
|
||||
"path": "/api/payload-jobs/run",
|
||||
"schedule": "*/5 * * * *"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
This configuration schedules the endpoint `/api/payload-jobs/run` to be triggered every 5 minutes. This endpoint is added automatically by payload and is responsible for running the queued jobs.
|
||||
|
||||
2. Environment Variable Setup: By default, the endpoint may require a JWT token for authorization. However, Vercel Cron jobs cannot pass JWT tokens. Instead, you can use an environment variable to secure the endpoint:
|
||||
|
||||
Add a new environment variable named `CRON_SECRET` to your Vercel project settings. This should be a random string, ideally 16 characters or longer.
|
||||
|
||||
3. Modify Authentication for Job Running: Adjust the job running authorization logic in your project to accept the `CRON_SECRET` as a valid token. Modify your `payload.config.ts` file as follows:
|
||||
|
||||
```ts
|
||||
export default buildConfig({
|
||||
// Other configurations...
|
||||
jobs: {
|
||||
access: {
|
||||
run: ({ req }: { req: PayloadRequest }): boolean => {
|
||||
const authHeader = req.headers.get('authorization');
|
||||
return authHeader === `Bearer ${process.env.CRON_SECRET}`;
|
||||
},
|
||||
},
|
||||
// Other job configurations...
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
This code snippet ensures that the jobs can only be triggered if the correct `CRON_SECRET` is provided in the authorization header.
|
||||
|
||||
Vercel will automatically make the `CRON_SECRET` environment variable available to the endpoint when triggered by the Vercel Cron, ensuring that the jobs can be run securely.
|
||||
|
||||
After the project is deployed to Vercel, the Vercel Cron job will automatically trigger the `/api/payload-jobs/run` endpoint in the specified schedule, running the queued jobs in the background.
|
||||
@@ -52,7 +52,7 @@ const Pages: CollectionConfig = {
|
||||
}
|
||||
```
|
||||
|
||||
and done! Now, every time this lexical editor is initialized, it converts the slate date to lexical on-the-fly. If the data is already in lexical format, it will just pass it through.
|
||||
and done! Now, everytime this lexical editor is initialized, it converts the slate date to lexical on-the-fly. If the data is already in lexical format, it will just pass it through.
|
||||
|
||||
This is by far the easiest way to migrate from Slate to Lexical, although it does come with a few caveats:
|
||||
|
||||
|
||||
@@ -178,7 +178,7 @@ Notice how even the toolbars are features? That's how extensible our lexical edi
|
||||
|
||||
## Creating your own, custom Feature
|
||||
|
||||
You can find more information about creating your own feature in our [building custom feature docs](/docs/lexical/building-custom-features).
|
||||
You can find more information about creating your own feature in our [building custom feature docs](lexical/building-custom-features).
|
||||
|
||||
## TypeScript
|
||||
|
||||
|
||||
@@ -71,28 +71,26 @@ import config from '@payload-config'
|
||||
const payload = await getPayload({ config })
|
||||
```
|
||||
|
||||
Both options function in exactly the same way outside of one having HMR support and the other not. For more information about using Payload outside of Next.js, [click here](./outside-nextjs).
|
||||
Both options function in exactly the same way outside of one having HMR support and the other not. For more information about using Payload outside of Next.js, [click here](/docs/beta/local-api/outside-nextjs).
|
||||
|
||||
## Local options available
|
||||
|
||||
You can specify more options within the Local API vs. REST or GraphQL due to the server-only context that they are executed in.
|
||||
|
||||
| Local Option | Description |
|
||||
| -------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `collection` | Required for Collection operations. Specifies the Collection slug to operate against. |
|
||||
| `data` | The data to use within the operation. Required for `create`, `update`. |
|
||||
| `depth` | [Control auto-population](../queries/depth) of nested relationship and upload fields. |
|
||||
| `locale` | Specify [locale](/docs/configuration/localization) for any returned documents. |
|
||||
| `select` | Specify [select](../queries/select) to control which fields to include to the result. |
|
||||
| `fallbackLocale` | Specify a [fallback locale](/docs/configuration/localization) to use for any returned documents. |
|
||||
| `overrideAccess` | Skip access control. By default, this property is set to true within all Local API operations. |
|
||||
| `overrideLock` | By default, document locks are ignored (`true`). Set to `false` to enforce locks and prevent operations when a document is locked by another user. [More details](../admin/locked-documents). |
|
||||
| `user` | If you set `overrideAccess` to `false`, you can pass a user to use against the access control checks. |
|
||||
| `showHiddenFields` | Opt-in to receiving hidden fields. By default, they are hidden from returned documents in accordance to your config. |
|
||||
| `pagination` | Set to false to return all documents and avoid querying for document counts. |
|
||||
| `context` | [Context](/docs/hooks/context), which will then be passed to `context` and `req.context`, which can be read by hooks. Useful if you want to pass additional information to the hooks which shouldn't be necessarily part of the document, for example a `triggerBeforeChange` option which can be read by the BeforeChange hook to determine if it should run or not. |
|
||||
| `disableErrors` | When set to `true`, errors will not be thrown. Instead, the `findByID` operation will return `null`, and the `find` operation will return an empty documents array. |
|
||||
| `disableTransaction` | When set to `true`, a [database transactions](../database/transactions) will not be initialized. |
|
||||
| Local Option | Description |
|
||||
| ------------------ | ------------ |
|
||||
| `collection` | Required for Collection operations. Specifies the Collection slug to operate against. |
|
||||
| `data` | The data to use within the operation. Required for `create`, `update`. |
|
||||
| `depth` | [Control auto-population](../queries/depth) of nested relationship and upload fields. |
|
||||
| `locale` | Specify [locale](/docs/configuration/localization) for any returned documents. |
|
||||
| `fallbackLocale` | Specify a [fallback locale](/docs/configuration/localization) to use for any returned documents. |
|
||||
| `overrideAccess` | Skip access control. By default, this property is set to true within all Local API operations. |
|
||||
| `overrideLock` | By default, document locks are ignored (`true`). Set to `false` to enforce locks and prevent operations when a document is locked by another user. [More details](../admin/locked-documents).|
|
||||
| `user` | If you set `overrideAccess` to `false`, you can pass a user to use against the access control checks. |
|
||||
| `showHiddenFields` | Opt-in to receiving hidden fields. By default, they are hidden from returned documents in accordance to your config. |
|
||||
| `pagination` | Set to false to return all documents and avoid querying for document counts. |
|
||||
| `context` | [Context](/docs/hooks/context), which will then be passed to `context` and `req.context`, which can be read by hooks. Useful if you want to pass additional information to the hooks which shouldn't be necessarily part of the document, for example a `triggerBeforeChange` option which can be read by the BeforeChange hook to determine if it should run or not. |
|
||||
| `disableErrors` | When set to `true`, errors will not be thrown. Instead, the `findByID` operation will return `null`, and the `find` operation will return an empty documents array. |
|
||||
|
||||
_There are more options available on an operation by operation basis outlined below._
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ Forms can be as simple or complex as you need, from a basic contact form, to a m
|
||||
Install the plugin using any JavaScript package manager like [Yarn](https://yarnpkg.com), [NPM](https://npmjs.com), or [PNPM](https://pnpm.io):
|
||||
|
||||
```bash
|
||||
pnpm add @payloadcms/plugin-form-builder@beta
|
||||
pnpm add @payloadcms/plugin-form-builder
|
||||
```
|
||||
|
||||
## Basic Usage
|
||||
@@ -138,7 +138,7 @@ const beforeEmail: BeforeEmail<FormSubmission> = (emailsToSend, beforeChangePara
|
||||
|
||||
### `defaultToEmail`
|
||||
|
||||
Provide a fallback for the email address to send form submissions to. If the email in form configuration does not have a to email set, this email address will be used. If this is not provided then it falls back to the `defaultFromAddress` in your [email configuration](../email/overview).
|
||||
Provide a fallback for the email address to send form submissions to. If the email in form configuration does not have a to email set, this email address will be used. If this is not provided then it falls back to the `defaultFromAddress` in your [email configuration](https://payloadcms.com/docs/beta/email/overview).
|
||||
|
||||
```ts
|
||||
// payload.config.ts
|
||||
@@ -343,12 +343,12 @@ Maps to a `checkbox` input on your front-end. Used to collect a boolean value.
|
||||
Maps to a `number` input on your front-end. Used to collect a number.
|
||||
|
||||
| Property | Type | Description |
|
||||
| -------------- | -------- | ---------------------------------------------------- |
|
||||
| -------------- | -------- | ---------------------------------------------------- | --- | -------------- | ------ | ------------------------------- |
|
||||
| `name` | string | The name of the field. |
|
||||
| `label` | string | The label of the field. |
|
||||
| `defaultValue` | number | The default value of the field. |
|
||||
| `defaultValue` | string | The default value of the field. |
|
||||
| `width` | string | The width of the field on the front-end. |
|
||||
| `required` | checkbox | Whether or not the field is required when submitted. |
|
||||
| `required` | checkbox | Whether or not the field is required when submitted. | | `defaultValue` | number | The default value of the field. |
|
||||
|
||||
### Message
|
||||
|
||||
@@ -412,11 +412,11 @@ formBuilder({
|
||||
|
||||
## Email
|
||||
|
||||
This plugin relies on the [email configuration](../email/overview) defined in your payload configuration. It will read from your config and attempt to send your emails using the credentials provided.
|
||||
This plugin relies on the [email configuration](https://payloadcms.com/docs/beta/email/overview) defined in your payload configuration. It will read from your config and attempt to send your emails using the credentials provided.
|
||||
|
||||
### Email formatting
|
||||
|
||||
The email contents supports rich text which will be serialized to HTML on the server before being sent. By default it reads the global configuration of your rich text editor.
|
||||
The email contents supports rich text which will be serialised to HTML on the server before being sent. By default it reads the global configuration of your rich text editor.
|
||||
|
||||
The email subject and body supports inserting dynamic fields from the form submission data using the `{{field_name}}` syntax. For example, if you have a field called `name` in your form, you can include this in the email body like so:
|
||||
|
||||
|
||||
@@ -48,7 +48,7 @@ Install the plugin using any JavaScript package manager like [Yarn](https://yarn
|
||||
or [PNPM](https://pnpm.io):
|
||||
|
||||
```bash
|
||||
pnpm add @payloadcms/plugin-nested-docs@beta
|
||||
pnpm add @payloadcms/plugin-nested-docs
|
||||
```
|
||||
|
||||
## Basic Usage
|
||||
@@ -177,7 +177,7 @@ You can also extend the built-in `parent` and `breadcrumbs` fields per collectio
|
||||
and `createBreadcrumbField` methods. They will merge your customizations overtop the plugin's base field configurations.
|
||||
|
||||
```ts
|
||||
import type { CollectionConfig } from 'payload'
|
||||
import { CollectionConfig } from 'payload'
|
||||
import { createParentField } from '@payloadcms/plugin-nested-docs/fields'
|
||||
import { createBreadcrumbsField } from '@payloadcms/plugin-nested-docs/fields'
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ For example, if you have a page at `/about` and you want to change it to `/about
|
||||
Install the plugin using any JavaScript package manager like [Yarn](https://yarnpkg.com), [NPM](https://npmjs.com), or [PNPM](https://pnpm.io):
|
||||
|
||||
```bash
|
||||
pnpm add @payloadcms/plugin-redirects@beta
|
||||
pnpm add @payloadcms/plugin-redirects
|
||||
```
|
||||
|
||||
## Basic Usage
|
||||
|
||||
@@ -39,7 +39,7 @@ This plugin is a great way to implement a fast, immersive search experience such
|
||||
Install the plugin using any JavaScript package manager like [Yarn](https://yarnpkg.com), [NPM](https://npmjs.com), or [PNPM](https://pnpm.io):
|
||||
|
||||
```bash
|
||||
pnpm add @payloadcms/plugin-search@beta
|
||||
pnpm add @payloadcms/plugin-search
|
||||
```
|
||||
|
||||
## Basic Usage
|
||||
@@ -81,10 +81,6 @@ export default config
|
||||
|
||||
The `collections` property is an array of collection slugs to enable syncing to search. Enabled collections receive a `beforeChange` and `afterDelete` hook that creates, updates, and deletes its respective search record as it changes over time.
|
||||
|
||||
### `localize`
|
||||
|
||||
By default, the search plugin will add `localization: true` to the `title` field of the newly added `search` collection if you have localization enabled. If you would like to disable this behavior, you can set this to `false`.
|
||||
|
||||
#### `defaultPriorities`
|
||||
|
||||
This plugin automatically adds a `priority` field to the `search` collection that can be used as the `?sort=` parameter in your queries. For example, you may want to list blog posts before pages. Or you may want one specific post to always take appear first.
|
||||
@@ -143,8 +139,7 @@ Before creating or updating a search record, the `beforeSync` function runs. Thi
|
||||
searchPlugin({
|
||||
beforeSync: ({ originalDoc, searchDoc }) => ({
|
||||
...searchDoc,
|
||||
// - Modify your docs in any way here, this can be async
|
||||
// - You also need to add the `excerpt` field in the `searchOverrides` config
|
||||
// Modify your docs in any way here, this can be async
|
||||
excerpt: originalDoc?.excerpt || 'This is a fallback excerpt',
|
||||
}),
|
||||
}),
|
||||
|
||||
@@ -31,7 +31,7 @@ This multi-faceted software offers a range of features that will help you manage
|
||||
- **Integrations**: Connects with various tools and services for enhanced workflow and issue management
|
||||
|
||||
<Banner type="info">
|
||||
This plugin is completely open-source and the [source code can be found here](https://github.com/payloadcms/payload/tree/beta/packages/plugin-sentry). If you need help, check out our [Community Help](https://payloadcms.com/community-help). If you think you've found a bug, please [open a new issue](https://github.com/payloadcms/payload/issues/new?assignees=&labels=plugin%3A%20seo&template=bug_report.md&title=plugin-sentry%3A) with as much detail as possible.
|
||||
This plugin is completely open-source and the [source code can be found here](https://github.com/payloadcms/payload/tree/main/packages/plugin-sentry). If you need help, check out our [Community Help](https://payloadcms.com/community-help). If you think you've found a bug, please [open a new issue](https://github.com/payloadcms/payload/issues/new?assignees=&labels=plugin%3A%20seo&template=bug_report.md&title=plugin-seo%3A) with as much detail as possible.
|
||||
</Banner>
|
||||
|
||||
## Installation
|
||||
@@ -39,18 +39,9 @@ This multi-faceted software offers a range of features that will help you manage
|
||||
Install the plugin using any JavaScript package manager like [Yarn](https://yarnpkg.com), [NPM](https://npmjs.com), or [PNPM](https://pnpm.io):
|
||||
|
||||
```bash
|
||||
pnpm add @payloadcms/plugin-sentry@beta
|
||||
pnpm add @payloadcms/plugin-sentry
|
||||
```
|
||||
|
||||
## Sentry for Next.js setup
|
||||
This plugin requires to complete the [Sentry + Next.js setup](https://docs.sentry.io/platforms/javascript/guides/nextjs/) before.
|
||||
|
||||
You can use either the [automatic setup](https://docs.sentry.io/platforms/javascript/guides/nextjs/#install) with the installation wizard:
|
||||
```sh
|
||||
npx @sentry/wizard@latest -i nextjs
|
||||
```
|
||||
Or the [Manual Setup](https://docs.sentry.io/platforms/javascript/guides/nextjs/manual-setup/)
|
||||
|
||||
## Basic Usage
|
||||
|
||||
In the `plugins` array of your [Payload Config](https://payloadcms.com/docs/configuration/overview), call the plugin and pass in your Sentry DSN as an option.
|
||||
@@ -60,13 +51,11 @@ import { buildConfig } from 'payload'
|
||||
import { sentryPlugin } from '@payloadcms/plugin-sentry'
|
||||
import { Pages, Media } from './collections'
|
||||
|
||||
import * as Sentry from '@sentry/nextjs'
|
||||
|
||||
const config = buildConfig({
|
||||
collections: [Pages, Media],
|
||||
plugins: [
|
||||
sentryPlugin({
|
||||
Sentry,
|
||||
dsn: 'https://61edebas776889984d323d777@o4505289711681536.ingest.sentry.io/4505357433352176',
|
||||
}),
|
||||
],
|
||||
})
|
||||
@@ -76,55 +65,58 @@ export default config
|
||||
|
||||
## Options
|
||||
|
||||
- `Sentry` : Sentry | **required**
|
||||
- `dsn` : string | **required**
|
||||
|
||||
The `Sentry` instance
|
||||
Sentry automatically assigns a DSN when you create a project, the unique DSN informs Sentry where to send events so they are associated with the correct project.
|
||||
|
||||
<Banner type="warning">
|
||||
Make sure to complete the [Sentry for Next.js Setup](#sentry-for-nextjs-setup) before.
|
||||
You can find your project DSN (Data Source Name) by visiting [sentry.io](sentry.io) and navigating to your [Project] > Settings > Client Keys (DSN).
|
||||
</Banner>
|
||||
|
||||
- `enabled`: boolean | optional
|
||||
|
||||
Set to false to disable the plugin. Defaults to `true`.
|
||||
Set to false to disable the plugin. Defaults to true.
|
||||
|
||||
- `context`: `(args: ContextArgs) => Partial<ScopeContext> | Promise<Partial<ScopeContext>>`
|
||||
- `init` : ClientOptions | optional
|
||||
|
||||
Pass additional [contextual data](https://docs.sentry.io/platforms/javascript/enriching-events/context/#passing-context-directly) to Sentry
|
||||
Sentry allows a variety of options to be passed into the Sentry.init() function, see the full list of options [here](https://docs.sentry.io/platforms/node/guides/express/configuration/options).
|
||||
|
||||
- `requestHandler` : RequestHandlerOptions | optional
|
||||
|
||||
Accepts options that let you decide what data should be included in the event sent to Sentry, checkout the options [here](https://docs.sentry.io/platforms/node/guides/express/configuration/options).
|
||||
|
||||
- `captureErrors`: number[] | optional
|
||||
|
||||
By default, `Sentry.errorHandler` will capture only errors with a status code of 500 or higher. To capture additional error codes, pass the values as numbers in an array.
|
||||
|
||||
To see all options available, visit the [Sentry Docs](https://docs.sentry.io/platforms/node/guides/express/configuration/options).
|
||||
|
||||
### Example
|
||||
|
||||
Configure any of these options by passing them to the plugin:
|
||||
|
||||
```ts
|
||||
import { buildConfig } from 'payload'
|
||||
import { sentryPlugin } from '@payloadcms/plugin-sentry'
|
||||
|
||||
import * as Sentry from '@sentry/nextjs'
|
||||
|
||||
import { sentry } from '@payloadcms/plugin-sentry'
|
||||
import { Pages, Media } from './collections'
|
||||
|
||||
const config = buildConfig({
|
||||
collections: [Pages, Media],
|
||||
plugins: [
|
||||
sentryPlugin({
|
||||
sentry({
|
||||
dsn: 'https://61edebas777689984d323d777@o4505289711681536.ingest.sentry.io/4505357433352176',
|
||||
options: {
|
||||
captureErrors: [400, 403],
|
||||
context: ({ defaultContext, req }) => {
|
||||
return {
|
||||
...defaultContext,
|
||||
tags: {
|
||||
locale: req.locale,
|
||||
},
|
||||
}
|
||||
init: {
|
||||
debug: true,
|
||||
environment: 'development',
|
||||
tracesSampleRate: 1.0,
|
||||
},
|
||||
debug: true,
|
||||
requestHandler: {
|
||||
serverName: false,
|
||||
user: ['email'],
|
||||
},
|
||||
captureErrors: [400, 403, 404],
|
||||
},
|
||||
Sentry,
|
||||
}),
|
||||
],
|
||||
})
|
||||
|
||||
@@ -37,7 +37,7 @@ To help you visualize what your page might look like in a search engine, a previ
|
||||
Install the plugin using any JavaScript package manager like [Yarn](https://yarnpkg.com), [NPM](https://npmjs.com), or [PNPM](https://pnpm.io):
|
||||
|
||||
```bash
|
||||
pnpm add @payloadcms/plugin-seo@beta
|
||||
pnpm add @payloadcms/plugin-seo
|
||||
```
|
||||
|
||||
## Basic Usage
|
||||
@@ -89,23 +89,12 @@ An array of global slugs to enable SEO. Enabled globals receive a `meta` field w
|
||||
|
||||
##### `fields`
|
||||
|
||||
A function that takes in the default fields via an object and expects an array of fields in return. You can use this to modify existing fields or add new ones.
|
||||
An array of fields that allows you to inject your own custom fields onto the `meta` field group. The following fields are provided by default:
|
||||
|
||||
```ts
|
||||
// payload.config.ts
|
||||
{
|
||||
// ...
|
||||
seoPlugin({
|
||||
fields: ({ defaultFields }) => [
|
||||
...defaultFields,
|
||||
{
|
||||
name: 'customField',
|
||||
type: 'text',
|
||||
}
|
||||
]
|
||||
})
|
||||
}
|
||||
```
|
||||
- `title`: text
|
||||
- `description`: textarea
|
||||
- `image`: upload (if an `uploadsCollection` is provided)
|
||||
- `preview`: ui
|
||||
|
||||
##### `uploadsCollection`
|
||||
|
||||
@@ -220,6 +209,25 @@ Rename the meta group interface name that is generated for TypeScript and GraphQ
|
||||
}
|
||||
```
|
||||
|
||||
#### `fieldOverrides`
|
||||
|
||||
Pass any valid field props to the base fields: Title, Description or Image.
|
||||
|
||||
```ts
|
||||
// payload.config.ts
|
||||
seoPlugin({
|
||||
// ...
|
||||
fieldOverrides: {
|
||||
title: {
|
||||
required: true,
|
||||
},
|
||||
description: {
|
||||
localized: true,
|
||||
},
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
## Direct use of fields
|
||||
|
||||
There is the option to directly import any of the fields from the plugin so that you can include them anywhere as needed.
|
||||
@@ -268,10 +276,6 @@ OverviewField({
|
||||
})
|
||||
```
|
||||
|
||||
<Banner type="info">
|
||||
Tip: You can override the length rules by changing the minLength and maxLength props on the fields. In the case of the OverviewField you can use `titleOverrides` and `descriptionOverrides` to override the length rules.
|
||||
</Banner>
|
||||
|
||||
## TypeScript
|
||||
|
||||
All types can be directly imported:
|
||||
|
||||
@@ -39,7 +39,7 @@ The beauty of this plugin is the entirety of your application's content and busi
|
||||
Install the plugin using any JavaScript package manager like [Yarn](https://yarnpkg.com), [NPM](https://npmjs.com), or [PNPM](https://pnpm.io):
|
||||
|
||||
```bash
|
||||
pnpm add @payloadcms/plugin-stripe@beta
|
||||
pnpm add @payloadcms/plugin-stripe
|
||||
```
|
||||
|
||||
## Basic Usage
|
||||
|
||||
@@ -1,130 +0,0 @@
|
||||
---
|
||||
title: Select
|
||||
label: Select
|
||||
order: 30
|
||||
desc: Payload select determines which fields are selected to the result.
|
||||
keywords: query, documents, pagination, documentation, Content Management System, cms, headless, javascript, node, react, nextjs
|
||||
---
|
||||
|
||||
You may not need the full data from your Local API / REST queries, but only some specific fields. The select fields API can help you to optimize those cases.
|
||||
|
||||
## Local API
|
||||
|
||||
To specify select in the [Local API](../local-api/overview), you can use the `select` option in your query:
|
||||
|
||||
```ts
|
||||
// Include mode
|
||||
const getPosts = async () => {
|
||||
const posts = await payload.find({
|
||||
collection: 'posts',
|
||||
select: {
|
||||
text: true,
|
||||
// select a specific field from group
|
||||
group: {
|
||||
number: true
|
||||
},
|
||||
// select all fields from array
|
||||
array: true,
|
||||
}, // highlight-line
|
||||
})
|
||||
|
||||
return posts
|
||||
}
|
||||
|
||||
// Exclude mode
|
||||
const getPosts = async () => {
|
||||
const posts = await payload.find({
|
||||
collection: 'posts',
|
||||
// Select everything except for array and group.number
|
||||
select: {
|
||||
array: false,
|
||||
group: {
|
||||
number: false
|
||||
}
|
||||
}, // highlight-line
|
||||
})
|
||||
|
||||
return posts
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
<Banner type="warning">
|
||||
<strong>Important:</strong>
|
||||
To perform querying with `select` efficiently, it works on the database level. Because of that, your `beforeRead` and `afterRead` hooks may not receive the full `doc`.
|
||||
</Banner>
|
||||
|
||||
|
||||
## REST API
|
||||
|
||||
To specify select in the [REST API](../rest-api/overview), you can use the `select` parameter in your query:
|
||||
|
||||
```ts
|
||||
fetch('https://localhost:3000/api/posts?select[color]=true&select[group][number]=true') // highlight-line
|
||||
.then((res) => res.json())
|
||||
.then((data) => console.log(data))
|
||||
```
|
||||
|
||||
To understand the syntax, you need to understand that complex URL search strings are parsed into a JSON object. This one isn't too bad, but more complex queries get unavoidably more difficult to write.
|
||||
|
||||
For this reason, we recommend to use the extremely helpful and ubiquitous [`qs`](https://www.npmjs.com/package/qs) package to parse your JSON / object-formatted queries into query strings:
|
||||
|
||||
```ts
|
||||
import { stringify } from 'qs-esm'
|
||||
|
||||
const select = {
|
||||
text: true,
|
||||
group: {
|
||||
number: true
|
||||
}
|
||||
// This query could be much more complex
|
||||
// and QS would handle it beautifully
|
||||
}
|
||||
|
||||
const getPosts = async () => {
|
||||
const stringifiedQuery = stringify(
|
||||
{
|
||||
select, // ensure that `qs` adds the `select` property, too!
|
||||
},
|
||||
{ addQueryPrefix: true },
|
||||
)
|
||||
|
||||
const response = await fetch(`http://localhost:3000/api/posts${stringifiedQuery}`)
|
||||
// Continue to handle the response below...
|
||||
}
|
||||
```
|
||||
|
||||
<Banner type="info">
|
||||
<strong>Reminder:</strong>
|
||||
This is the same for [Globals](../configuration/globals) using the `/api/globals` endpoint.
|
||||
</Banner>
|
||||
|
||||
|
||||
## `defaultPopulate` collection config property
|
||||
|
||||
The `defaultPopulate` property allows you specify which fields to select when populating the collection from another document.
|
||||
This is especially useful for links where only the `slug` is needed instead of the entire document.
|
||||
|
||||
```ts
|
||||
import type { CollectionConfig } from 'payload'
|
||||
|
||||
import { lexicalEditor, LinkFeature } from '@payloadcms/richtext-lexical'
|
||||
import { slateEditor } from '@payloadcms/richtext-slate'
|
||||
|
||||
// The TSlug generic can be passed to have type safety for `defaultPopulate`.
|
||||
// If avoided, the `defaultPopulate` type resolves to `SelectType`.
|
||||
export const Pages: CollectionConfig<'pages'> = {
|
||||
slug: 'pages',
|
||||
// Specify `select`.
|
||||
defaultPopulate: {
|
||||
slug: true,
|
||||
},
|
||||
fields: [
|
||||
{
|
||||
name: 'slug',
|
||||
type: 'text',
|
||||
required: true,
|
||||
},
|
||||
],
|
||||
}
|
||||
```
|
||||
@@ -6,7 +6,7 @@ desc: Payload sort allows you to order your documents by a field in ascending or
|
||||
keywords: query, documents, pagination, documentation, Content Management System, cms, headless, javascript, node, react, nextjs
|
||||
---
|
||||
|
||||
Documents in Payload can be easily sorted by a specific [Field](../fields/overview). When querying Documents, you can pass the name of any top-level field, and the response will sort the Documents by that field in _ascending_ order. If prefixed with a minus symbol ("-"), they will be sorted in _descending_ order. In Local API multiple fields can be specified by using an array of strings. In REST API multiple fields can be specified by separating fields with comma. The minus symbol can be in front of individual fields.
|
||||
Documents in Payload can be easily sorted by a specific [Field](../fields/overview). When querying Documents, you can pass the name of any top-level field, and the response will sort the Documents by that field in _ascending_ order. If prefixed with a minus symbol ("-"), they will be sorted in _descending_ order.
|
||||
|
||||
Because sorting is handled by the database, the field cannot be a [Virtual Field](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges). It must be stored in the database to be searchable.
|
||||
|
||||
@@ -30,19 +30,6 @@ const getPosts = async () => {
|
||||
}
|
||||
```
|
||||
|
||||
To sort by multiple fields, you can use the `sort` option with fields in an array:
|
||||
|
||||
```ts
|
||||
const getPosts = async () => {
|
||||
const posts = await payload.find({
|
||||
collection: 'posts',
|
||||
sort: ['priority', '-createdAt'], // highlight-line
|
||||
})
|
||||
|
||||
return posts
|
||||
}
|
||||
```
|
||||
|
||||
## REST API
|
||||
|
||||
To sort in the [REST API](../rest-api/overview), you can use the `sort` parameter in your query:
|
||||
@@ -53,14 +40,6 @@ fetch('https://localhost:3000/api/posts?sort=-createdAt') // highlight-line
|
||||
.then((data) => console.log(data))
|
||||
```
|
||||
|
||||
To sort by multiple fields, you can use the `sort` parameter with fields separated by comma:
|
||||
|
||||
```ts
|
||||
fetch('https://localhost:3000/api/posts?sort=priority,-createdAt') // highlight-line
|
||||
.then((response) => response.json())
|
||||
.then((data) => console.log(data))
|
||||
```
|
||||
|
||||
## GraphQL API
|
||||
|
||||
To sort in the [GraphQL API](../graphql/overview), you can use the `sort` parameter in your query:
|
||||
|
||||
@@ -18,7 +18,6 @@ All Payload API routes are mounted and prefixed to your config's `routes.api` UR
|
||||
- [depth](../queries/depth) - automatically populates relationships and uploads
|
||||
- [locale](/docs/configuration/localization#retrieving-localized-docs) - retrieves document(s) in a specific locale
|
||||
- [fallback-locale](/docs/configuration/localization#retrieving-localized-docs) - specifies a fallback locale if no locale value exists
|
||||
- [select](../queries/select) - specifies which fields to include to the result
|
||||
|
||||
## Collections
|
||||
|
||||
@@ -592,7 +591,7 @@ Each endpoint object needs to have:
|
||||
Example:
|
||||
|
||||
```ts
|
||||
import type { CollectionConfig } from 'payload'
|
||||
import { CollectionConfig } from 'payload'
|
||||
|
||||
// a collection of 'orders' with an additional route for tracking details, reachable at /api/orders/:id/tracking
|
||||
export const Orders: CollectionConfig = {
|
||||
@@ -606,7 +605,7 @@ export const Orders: CollectionConfig = {
|
||||
path: '/:id/tracking',
|
||||
method: 'get',
|
||||
handler: async (req) => {
|
||||
const tracking = await getTrackingInfo(req.routeParams.id)
|
||||
const tracking = await getTrackingInfo(req.params.id)
|
||||
|
||||
if (!tracking) {
|
||||
return Response.json({ error: 'not found' }, { status: 404})
|
||||
|
||||
@@ -34,7 +34,7 @@ export default buildConfig({
|
||||
And here's an example for how to install the Slate editor on a field-by-field basis, while customizing its options:
|
||||
|
||||
```ts
|
||||
import type { CollectionConfig } from 'payload'
|
||||
import { CollectionConfig } from 'payload'
|
||||
import { slateEditor } from '@payloadcms/richtext-slate'
|
||||
|
||||
export const Pages: CollectionConfig = {
|
||||
|
||||
@@ -43,7 +43,7 @@ Every Payload Collection can opt-in to supporting Uploads by specifying the `upl
|
||||
</Banner>
|
||||
|
||||
```ts
|
||||
import type { CollectionConfig } from 'payload'
|
||||
import { CollectionConfig } from 'payload'
|
||||
|
||||
export const Media: CollectionConfig = {
|
||||
slug: 'media',
|
||||
@@ -98,7 +98,7 @@ _An asterisk denotes that an option is required._
|
||||
| **`displayPreview`** | Enable displaying preview of the uploaded file in Upload fields related to this Collection. Can be locally overridden by `displayPreview` option in Upload field. [More](/docs/fields/upload#config-options). |
|
||||
| **`externalFileHeaderFilter`** | Accepts existing headers and returns the headers after filtering or modifying. |
|
||||
| **`filesRequiredOnCreate`** | Mandate file data on creation, default is true. |
|
||||
| **`filenameCompoundIndex`** | Field slugs to use for a compound index instead of the default filename index.
|
||||
| **`filenameCompoundIndex`** | Field slugs to use for a compount index instead of the default filename index.
|
||||
| **`focalPoint`** | Set to `false` to disable the focal point selection tool in the [Admin Panel](../admin/overview). The focal point selector is only available when `imageSizes` or `resizeOptions` are defined. [More](#crop-and-focal-point-selector) |
|
||||
| **`formatOptions`** | An object with `format` and `options` that are used with the Sharp image library to format the upload file. [More](https://sharp.pixelplumbing.com/api-output#toformat) |
|
||||
| **`handlers`** | Array of Request handlers to execute when fetching a file, if a handler returns a Response it will be sent to the client. Otherwise Payload will retrieve and send back the file. |
|
||||
@@ -144,7 +144,7 @@ export default buildConfig({
|
||||
|
||||
If you specify an array of `imageSizes` to your `upload` config, Payload will automatically crop and resize your uploads to fit each of the sizes specified by your config.
|
||||
|
||||
The [Admin Panel](../admin/overview) will also automatically display all available files, including width, height, and file size, for each of your uploaded files.
|
||||
The [Admin Panel](../admin/overview) will also automatically display all available files, including width, height, and filesize, for each of your uploaded files.
|
||||
|
||||
Behind the scenes, Payload relies on [`sharp`](https://sharp.pixelplumbing.com/api-resize#resize) to perform its image resizing. You can specify additional options for `sharp` to use while resizing your images.
|
||||
|
||||
@@ -217,7 +217,7 @@ You can specify how Payload retrieves admin thumbnails for your upload-enabled C
|
||||
1. `adminThumbnail` as a **string**, equal to one of your provided image size names.
|
||||
|
||||
```ts
|
||||
import type { CollectionConfig } from 'payload'
|
||||
import { CollectionConfig } from 'payload'
|
||||
|
||||
export const Media: CollectionConfig = {
|
||||
slug: 'media',
|
||||
@@ -246,7 +246,7 @@ export const Media: CollectionConfig = {
|
||||
2. `adminThumbnail` as a **function** that takes the document's data and sends back a full URL to load the thumbnail.
|
||||
|
||||
```ts
|
||||
import type { CollectionConfig } from 'payload'
|
||||
import { CollectionConfig } from 'payload'
|
||||
|
||||
export const Media: CollectionConfig = {
|
||||
slug: 'media',
|
||||
@@ -267,7 +267,7 @@ Some example values are: `image/*`, `audio/*`, `video/*`, `image/png`, `applicat
|
||||
**Example mimeTypes usage:**
|
||||
|
||||
```ts
|
||||
import type { CollectionConfig } from 'payload'
|
||||
import { CollectionConfig } from 'payload'
|
||||
|
||||
export const Media: CollectionConfig = {
|
||||
slug: 'media',
|
||||
|
||||
@@ -22,7 +22,7 @@ Payload offers additional storage adapters to handle file uploads. These adapter
|
||||
### Installation
|
||||
|
||||
```sh
|
||||
pnpm add @payloadcms/storage-vercel-blob@beta
|
||||
pnpm add @payloadcms/storage-vercel-blob
|
||||
```
|
||||
|
||||
### Usage
|
||||
@@ -71,12 +71,12 @@ export default buildConfig({
|
||||
### Installation
|
||||
|
||||
```sh
|
||||
pnpm add @payloadcms/storage-s3@beta
|
||||
pnpm add @payloadcms/storage-s3
|
||||
```
|
||||
|
||||
### Usage
|
||||
|
||||
- Configure the `collections` object to specify which collections should use the S3 Storage adapter. The slug _must_ match one of your existing collection slugs.
|
||||
- Configure the `collections` object to specify which collections should use the Vercel Blob adapter. The slug _must_ match one of your existing collection slugs.
|
||||
- The `config` object can be any [`S3ClientConfig`](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/client/s3) object (from [`@aws-sdk/client-s3`](https://github.com/aws/aws-sdk-js-v3)). _This is highly dependent on your AWS setup_. Check the AWS documentation for more information.
|
||||
- When enabled, this package will automatically set `disableLocalStorage` to `true` for each collection.
|
||||
|
||||
@@ -119,12 +119,12 @@ See the the [AWS SDK Package](https://github.com/aws/aws-sdk-js-v3) and [`S3Clie
|
||||
### Installation
|
||||
|
||||
```sh
|
||||
pnpm add @payloadcms/storage-azure@beta
|
||||
pnpm add @payloadcms/storage-azure
|
||||
```
|
||||
|
||||
### Usage
|
||||
|
||||
- Configure the `collections` object to specify which collections should use the Azure Blob adapter. The slug _must_ match one of your existing collection slugs.
|
||||
- Configure the `collections` object to specify which collections should use the Vercel Blob adapter. The slug _must_ match one of your existing collection slugs.
|
||||
- When enabled, this package will automatically set `disableLocalStorage` to `true` for each collection.
|
||||
|
||||
```ts
|
||||
@@ -168,12 +168,12 @@ export default buildConfig({
|
||||
### Installation
|
||||
|
||||
```sh
|
||||
pnpm add @payloadcms/storage-gcs@beta
|
||||
pnpm add @payloadcms/storage-gcs
|
||||
```
|
||||
|
||||
### Usage
|
||||
|
||||
- Configure the `collections` object to specify which collections should use the Google Cloud Storage adapter. The slug _must_ match one of your existing collection slugs.
|
||||
- Configure the `collections` object to specify which collections should use the Vercel Blob adapter. The slug _must_ match one of your existing collection slugs.
|
||||
- When enabled, this package will automatically set `disableLocalStorage` to `true` for each collection.
|
||||
|
||||
```ts
|
||||
@@ -218,7 +218,7 @@ export default buildConfig({
|
||||
### Installation
|
||||
|
||||
```sh
|
||||
pnpm add @payloadcms/storage-uploadthing@beta
|
||||
pnpm add @payloadcms/storage-uploadthing
|
||||
```
|
||||
|
||||
### Usage
|
||||
@@ -261,7 +261,7 @@ If you need to create a custom storage adapter, you can use the [`@payloadcms/pl
|
||||
|
||||
### Installation
|
||||
|
||||
`pnpm add @payloadcms/plugin-cloud-storage@beta`
|
||||
`pnpm add @payloadcms/plugin-cloud-storage`
|
||||
|
||||
### Usage
|
||||
|
||||
@@ -310,7 +310,7 @@ This plugin is configurable to work across many different Payload collections. A
|
||||
| Option | Type | Description |
|
||||
| ---------------- | ----------------------------------- | --------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `collections` \* | `Record<string, CollectionOptions>` | Object with keys set to the slug of collections you want to enable the plugin for, and values set to collection-specific options. |
|
||||
| `enabled` | `boolean` | To conditionally enable/disable plugin. Default: `true`. |
|
||||
| `enabled` | | `boolean` to conditionally enable/disable plugin. Default: true. |
|
||||
|
||||
## Collection-specific options
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user