Compare commits
24 Commits
chore/lice
...
perf/optim
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e5801528ae | ||
|
|
42c8f15161 | ||
|
|
7d9fbafe5f | ||
|
|
4e7266e927 | ||
|
|
7653386552 | ||
|
|
63eb41617e | ||
|
|
8c68ea9677 | ||
|
|
2a199d7724 | ||
|
|
475fd5be92 | ||
|
|
35e9c27286 | ||
|
|
618491d694 | ||
|
|
2c8701b89d | ||
|
|
88f3ec562e | ||
|
|
869461b0ad | ||
|
|
63e07ff481 | ||
|
|
603418fe83 | ||
|
|
ae2b3bb984 | ||
|
|
6d9972ee8f | ||
|
|
a61431e9d8 | ||
|
|
b17520dac6 | ||
|
|
cffe888e84 | ||
|
|
505db12ff3 | ||
|
|
209b9ad291 | ||
|
|
41353f2d94 |
1
.github/workflows/main.yml
vendored
1
.github/workflows/main.yml
vendored
@@ -313,7 +313,6 @@ jobs:
|
||||
- i18n
|
||||
- plugin-cloud-storage
|
||||
- plugin-form-builder
|
||||
- plugin-import-export
|
||||
- plugin-nested-docs
|
||||
- plugin-seo
|
||||
- versions
|
||||
|
||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -318,5 +318,3 @@ test/databaseAdapter.js
|
||||
/media-with-relation-preview
|
||||
/media-without-relation-preview
|
||||
/media-without-cache-tags
|
||||
|
||||
licenses.csv
|
||||
|
||||
@@ -1,32 +1,32 @@
|
||||
---
|
||||
title: Swap in your own React components
|
||||
label: Overview
|
||||
order: 10
|
||||
label: Custom Components
|
||||
order: 20
|
||||
desc: Fully customize your Admin Panel by swapping in your own React components. Add fields, remove views, update routes and change functions to sculpt your perfect Dashboard.
|
||||
keywords: admin, components, custom, documentation, Content Management System, cms, headless, javascript, node, react, nextjs
|
||||
---
|
||||
|
||||
The Payload [Admin Panel](../admin/overview) is designed to be as minimal and straightforward as possible to allow for 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).
|
||||
The Payload [Admin Panel](./overview) is designed to be as minimal and straightforward as possible to allow for 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. 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.
|
||||
|
||||
<Banner type="success">
|
||||
**Note:**
|
||||
Client Components continue to be fully supported. To use Client Components in your app, simply include the `'use client'` directive. Payload will automatically detect and remove all [non-serializable](https://react.dev/reference/rsc/use-client#serializable-types) default props before rendering your component. [More details](#client-components).
|
||||
Client Components continue to be fully supported. To use Client Components in your app, simply include the `use client` directive. Payload will automatically detect and remove all default, [non-serializable props](https://react.dev/reference/rsc/use-client#serializable-types) before rendering your component. [More details](#client-components).
|
||||
</Banner>
|
||||
|
||||
There are four main types of Custom Components in Payload:
|
||||
|
||||
- [Root Components](./root-components)
|
||||
- [Collection Components](../configuration/collections#custom-components)
|
||||
- [Root Components](#root-components)
|
||||
- [Collection Components](../configuration/collections/#custom-components)
|
||||
- [Global Components](../configuration/globals#custom-components)
|
||||
- [Field Components](../fields/overview#custom-components)
|
||||
|
||||
To swap in your own Custom Component, first determine the scope that corresponds to what you are trying to accomplish, consult the list of available components, then [author your React component(s)](#building-custom-components) accordingly.
|
||||
To swap in your own Custom Component, first consult the list of available components, determine the scope that corresponds to what you are trying to accomplish, then [author your React component(s)](#building-custom-components) accordingly.
|
||||
|
||||
## Defining Custom Components
|
||||
|
||||
As Payload compiles the Admin Panel, it checks your config for Custom Components. When detected, Payload either replaces its own default component with yours, or if none exists by default, renders yours outright. While there are many places where Custom Components are supported in Payload, each is defined in the same way using [Component Paths](#component-paths).
|
||||
As Payload compiles the Admin Panel, it checks your config for Custom Components. When detected, Payload either replaces its own default component with yours, or if none exists by default, renders yours outright. While are many places where Custom Components are supported in Payload, each is defined in the same way using [Component Paths](#component-paths).
|
||||
|
||||
To add a Custom Component, point to its file path in your Payload Config:
|
||||
|
||||
@@ -47,7 +47,7 @@ const config = buildConfig({
|
||||
|
||||
<Banner type="success">
|
||||
**Note:**
|
||||
All Custom Components can be either Server Components or Client Components, depending on the presence of the `'use client'` directive at the top of the file.
|
||||
All Custom Components can be either Server Components or Client Components, depending on the presence of the `use client` directive at the top of the file.
|
||||
</Banner>
|
||||
|
||||
### Component Paths
|
||||
@@ -82,7 +82,7 @@ const config = buildConfig({
|
||||
|
||||
In this example, we set the base directory to the `src` directory, and omit the `/src/` part of our component path string.
|
||||
|
||||
### Component Config
|
||||
### Config Options
|
||||
|
||||
While Custom Components are usually defined as a string, you can also pass in an object with additional options:
|
||||
|
||||
@@ -110,12 +110,12 @@ The following options are available:
|
||||
|
||||
| Property | Description |
|
||||
|---------------|-------------------------------------------------------------------------------------------------------------------------------|
|
||||
| `clientProps` | Props to be passed to the Custom Components if it's a Client Component. [More details](#custom-props). |
|
||||
| `exportName` | Instead of declaring named exports using `#` in the component path, you can also omit them from `path` and pass them in here. |
|
||||
| `path` | File path to the Custom Component. Named exports can be appended to the end of the path, separated by a `#`. |
|
||||
| `serverProps` | Props to be passed to the Custom Component if it's a Server Component. [More details](#custom-props). |
|
||||
| **`clientProps`** | Props to be passed to the Custom Components if it's a Client Component. [More details](#custom-props). |
|
||||
| **`exportName`** | Instead of declaring named exports using `#` in the component path, you can also omit them from `path` and pass them in here. |
|
||||
| **`path`** | File path to the Custom Component. Named exports can be appended to the end of the path, separated by a `#`. |
|
||||
| **`serverProps`** | Props to be passed to the Custom Component if it's a Server Component. [More details](#custom-props). |
|
||||
|
||||
For details on how to build Custom Components, see [Building Custom Components](#building-custom-components).
|
||||
For more details on how to build Custom Components, see [Building Custom Components](#building-custom-components).
|
||||
|
||||
### Import Map
|
||||
|
||||
@@ -161,13 +161,10 @@ Here is an example:
|
||||
|
||||
```tsx
|
||||
import React from 'react'
|
||||
import type { Payload } from 'payload'
|
||||
|
||||
async function MyServerComponent({
|
||||
const MyServerComponent = async ({
|
||||
payload // highlight-line
|
||||
}: {
|
||||
payload: Payload
|
||||
}) {
|
||||
}) => {
|
||||
const page = await payload.findByID({
|
||||
collection: 'pages',
|
||||
id: '123',
|
||||
@@ -188,12 +185,12 @@ Each Custom Component receives the following props by default:
|
||||
|
||||
<Banner type="warning">
|
||||
**Reminder:**
|
||||
All Custom Components also receive various other props that are specific to the component being rendered. See [Root Components](#root-components), [Collection Components](../configuration/collections#custom-components), [Global Components](../configuration/globals#custom-components), or [Field Components](../fields/overview#custom-components) for a complete list of all default props per component.
|
||||
All Custom Components also receive various other props that are specific component being rendered. See [Root Components](#root-components), [Collection Components](../configuration/collections#custom-components), [Global Components](../configuration/globals#custom-components), or [Field Components](../fields/overview#custom-components) for a complete list of all default props per component.
|
||||
</Banner>
|
||||
|
||||
### Custom Props
|
||||
|
||||
It is also possible to pass custom props to your Custom Components. To do this, you can use either the `clientProps` or `serverProps` properties depending on whether your prop is [serializable](https://react.dev/reference/rsc/use-client#serializable-types), and whether your component is a Server or Client Component.
|
||||
To pass in custom props from the config, you can use either the `clientProps` or `serverProps` properties depending on whether your prop is [serializable](https://react.dev/reference/rsc/use-client#serializable-types), and whether your component is a Server or Client Component.
|
||||
|
||||
```ts
|
||||
import { buildConfig } from 'payload'
|
||||
@@ -215,30 +212,26 @@ const config = buildConfig({
|
||||
})
|
||||
```
|
||||
|
||||
Here is how your component might receive this prop:
|
||||
|
||||
```tsx
|
||||
'use client'
|
||||
import React from 'react'
|
||||
import { Link } from '@payloadcms/ui'
|
||||
|
||||
export function MyComponent({ myCustomProp }: { myCustomProp: string }) {
|
||||
export const MyComponent = ({ myCustomProp }: { myCustomProp: string }) => {
|
||||
return (
|
||||
<Link href="/admin/logout">{myCustomProp}</Link>
|
||||
<button>{myCustomProp}</button>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### Client Components
|
||||
|
||||
All Custom Components in Payload are [React Server Components](https://react.dev/reference/rsc/server-components) by default, however, it is possible to use [Client Components](https://react.dev/reference/rsc/use-client) by simply adding the `'use client'` directive at the top of your file. Payload will automatically detect and remove all [non-serializable](https://react.dev/reference/rsc/use-client#serializable-types) default props before rendering your component.
|
||||
When [Building Custom Components](#building-custom-components), it's still possible to use client-side code such as `useState` or the `window` object. To do this, simply add the `use client` directive at the top of your file. Payload will automatically detect and remove all default, [non-serializable props](https://react.dev/reference/rsc/use-client#serializable-types) before rendering your component.
|
||||
|
||||
```tsx
|
||||
// highlight-start
|
||||
'use client'
|
||||
// highlight-end
|
||||
'use client' // highlight-line
|
||||
import React, { useState } from 'react'
|
||||
|
||||
export function MyClientComponent() {
|
||||
export const MyClientComponent: React.FC = () => {
|
||||
const [count, setCount] = useState(0)
|
||||
|
||||
return (
|
||||
@@ -274,19 +267,17 @@ export default async function MyServerComponent({
|
||||
}
|
||||
```
|
||||
|
||||
But, the Payload Config is [non-serializable](https://react.dev/reference/rsc/use-client#serializable-types) by design. It is full of custom validation functions and more. This means that the Payload Config, in its entirety, cannot be passed directly to Client Components.
|
||||
But, the Payload Config is [non-serializable](https://react.dev/reference/rsc/use-client#serializable-types) by design. It is full of custom validation functions, React components, etc. This means that the Payload Config, in its entirety, cannot be passed directly to Client Components.
|
||||
|
||||
For this reason, Payload creates a Client Config and passes it into the Config Provider. This is a serializable version of the Payload Config that can be accessed from any Client Component via the [`useConfig`](../admin/hooks#useconfig) hook:
|
||||
For this reason, Payload creates a Client Config and passes it into the Config Provider. This is a serializable version of the Payload Config that can be accessed from any Client Component via the [`useConfig`](./hooks#useconfig) hook:
|
||||
|
||||
```tsx
|
||||
'use client'
|
||||
import React from 'react'
|
||||
import { useConfig } from '@payloadcms/ui'
|
||||
|
||||
export function MyClientComponent() {
|
||||
// highlight-start
|
||||
const { config: { serverURL } } = useConfig()
|
||||
// highlight-end
|
||||
export const MyClientComponent: React.FC = () => {
|
||||
const { config: { serverURL } } = useConfig() // highlight-line
|
||||
|
||||
return (
|
||||
<Link href={serverURL}>
|
||||
@@ -300,9 +291,7 @@ export function MyClientComponent() {
|
||||
See [Using Hooks](#using-hooks) for more details.
|
||||
</Banner>
|
||||
|
||||
Similarly, all [Field Components](../fields/overview#custom-components) automatically receive their respective Field Config through props.
|
||||
|
||||
Within Server Components, this prop is named `field`:
|
||||
All [Field Components](../fields/overview#custom-components) automatically receive their respective Field Config through props.
|
||||
|
||||
```tsx
|
||||
import React from 'react'
|
||||
@@ -317,29 +306,11 @@ export const MyClientFieldComponent: TextFieldServerComponent = ({ field: { name
|
||||
}
|
||||
```
|
||||
|
||||
Within Client Components, this prop is named `clientField` because its non-serializable props have been removed:
|
||||
|
||||
```tsx
|
||||
'use client'
|
||||
import React from 'react'
|
||||
import type { TextFieldClientComponent } from 'payload'
|
||||
|
||||
export const MyClientFieldComponent: TextFieldClientComponent = ({ clientField: { name } }) => {
|
||||
return (
|
||||
<p>
|
||||
{`This field's name is ${name}`}
|
||||
</p>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### Getting the Current Language
|
||||
|
||||
All Custom Components can support language translations to be consistent with Payload's [I18n](../configuration/i18n). This will allow your Custom Components to display the correct language based on the user's preferences.
|
||||
All Custom Components can support multiple languages to be consistent with Payload's [Internationalization](../configuration/i18n). To do this, first add your translation resources to the [I18n Config](../configuration/i18n).
|
||||
|
||||
To do this, first add your translation resources to the [I18n Config](../configuration/i18n). Then from any Server Component, you can translate resources using the `getTranslation` function from `@payloadcms/translations`.
|
||||
|
||||
All Server Components automatically receive the `i18n` object as a prop by default:
|
||||
From any Server Component, you can translate resources using the `getTranslation` function from `@payloadcms/translations`. All Server Components automatically receive the `i18n` object as a prop by default.
|
||||
|
||||
```tsx
|
||||
import React from 'react'
|
||||
@@ -361,7 +332,7 @@ The best way to do this within a Client Component is to import the `useTranslati
|
||||
import React from 'react'
|
||||
import { useTranslation } from '@payloadcms/ui'
|
||||
|
||||
export function MyClientComponent() {
|
||||
export const MyClientComponent: React.FC = () => {
|
||||
const { t, i18n } = useTranslation() // highlight-line
|
||||
|
||||
return (
|
||||
@@ -375,14 +346,12 @@ export function MyClientComponent() {
|
||||
```
|
||||
|
||||
<Banner type="success">
|
||||
See the [Hooks](../admin/hooks) documentation for a full list of available hooks.
|
||||
See the [Hooks](./hooks) documentation for a full list of available hooks.
|
||||
</Banner>
|
||||
|
||||
### Getting the Current Locale
|
||||
|
||||
All [Custom Views](./custom-views) can support multiple locales to be consistent with Payload's [Localization](../configuration/localization) feature. This can be used to scope API requests, etc.
|
||||
|
||||
All Server Components automatically receive the `locale` object as a prop by default:
|
||||
All [Custom Views](./views) can support multiple locales to be consistent with Payload's [Localization](../configuration/localization). They automatically receive the `locale` object as a prop by default. This can be used to scope API requests, etc.:
|
||||
|
||||
```tsx
|
||||
import React from 'react'
|
||||
@@ -407,7 +376,7 @@ The best way to do this within a Client Component is to import the `useLocale` h
|
||||
import React from 'react'
|
||||
import { useLocale } from '@payloadcms/ui'
|
||||
|
||||
function Greeting() {
|
||||
const Greeting: React.FC = () => {
|
||||
const locale = useLocale() // highlight-line
|
||||
|
||||
const trans = {
|
||||
@@ -422,19 +391,19 @@ function Greeting() {
|
||||
```
|
||||
|
||||
<Banner type="success">
|
||||
See the [Hooks](../admin/hooks) documentation for a full list of available hooks.
|
||||
See the [Hooks](./hooks) documentation for a full list of available hooks.
|
||||
</Banner>
|
||||
|
||||
### Using Hooks
|
||||
|
||||
To make it easier to [build your Custom Components](#building-custom-components), you can use [Payload's built-in React Hooks](../admin/hooks) in any Client Component. For example, you might want to interact with one of Payload's many React Contexts. To do this, you can use one of the many hooks available depending on your needs.
|
||||
To make it easier to [build your Custom Components](#building-custom-components), you can use [Payload's built-in React Hooks](./hooks) in any Client Component. For example, you might want to interact with one of Payload's many React Contexts. To do this, you can one of the many hooks available depending on your needs.
|
||||
|
||||
```tsx
|
||||
'use client'
|
||||
import React from 'react'
|
||||
import { useDocumentInfo } from '@payloadcms/ui'
|
||||
|
||||
export function MyClientComponent() {
|
||||
export const MyClientComponent: React.FC = () => {
|
||||
const { slug } = useDocumentInfo() // highlight-line
|
||||
|
||||
return (
|
||||
@@ -444,19 +413,19 @@ export function MyClientComponent() {
|
||||
```
|
||||
|
||||
<Banner type="success">
|
||||
See the [Hooks](../admin/hooks) documentation for a full list of available hooks.
|
||||
See the [Hooks](./hooks) documentation for a full list of available hooks.
|
||||
</Banner>
|
||||
|
||||
### Adding Styles
|
||||
|
||||
Payload has a robust [CSS Library](../admin/customizing-css) that you can use to style your Custom Components to match to Payload's built-in styling. This will ensure that your Custom Components integrate well into the existing design system. This will make it so they automatically adapt to any theme changes that might occur.
|
||||
Payload has a robust [CSS Library](./customizing-css) that you can use to style your Custom Components similarly to Payload's built-in styling. This will ensure that your Custom Components match the existing design system, and so that they automatically adapt to any theme changes that might occur.
|
||||
|
||||
To apply custom styles, simply import your own `.css` or `.scss` file into your Custom Component:
|
||||
|
||||
```tsx
|
||||
import './index.scss'
|
||||
|
||||
export function MyComponent() {
|
||||
export const MyComponent: React.FC = () => {
|
||||
return (
|
||||
<div className="my-component">
|
||||
My Custom Component
|
||||
@@ -487,5 +456,95 @@ Payload also exports its [SCSS](https://sass-lang.com) library for reuse which i
|
||||
|
||||
<Banner type="success">
|
||||
**Note:**
|
||||
You can also drill into Payload's own component styles, or easily apply global, app-wide CSS. More on that [here](../admin/customizing-css).
|
||||
You can also drill into Payload's own component styles, or easily apply global, app-wide CSS. More on that [here](./customizing-css).
|
||||
</Banner>
|
||||
|
||||
|
||||
## Root Components
|
||||
|
||||
Root Components are those that affect the [Admin Panel](./overview) generally, such as the logo or the main nav.
|
||||
|
||||
To override Root Components, use the `admin.components` property in your [Payload Config](../configuration/overview):
|
||||
|
||||
```ts
|
||||
import { buildConfig } from 'payload'
|
||||
|
||||
export default buildConfig({
|
||||
// ...
|
||||
admin: {
|
||||
// highlight-start
|
||||
components: {
|
||||
// ...
|
||||
},
|
||||
// highlight-end
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
_For details on how to build Custom Components, see [Building Custom Components](#building-custom-components)._
|
||||
|
||||
The following options are available:
|
||||
|
||||
| Path | Description |
|
||||
|-----------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| **`Nav`** | Contains the sidebar / mobile menu in its entirety. |
|
||||
| **`beforeNavLinks`** | An array of Custom Components to inject into the built-in Nav, _before_ the links themselves. |
|
||||
| **`afterNavLinks`** | An array of Custom Components to inject into the built-in Nav, _after_ the links. |
|
||||
| **`beforeDashboard`** | An array of Custom Components to inject into the built-in Dashboard, _before_ the default dashboard contents. |
|
||||
| **`afterDashboard`** | An array of Custom Components to inject into the built-in Dashboard, _after_ the default dashboard contents. |
|
||||
| **`beforeLogin`** | An array of Custom Components to inject into the built-in Login, _before_ the default login form. |
|
||||
| **`afterLogin`** | An array of Custom Components to inject into the built-in Login, _after_ the default login form. |
|
||||
| **`logout.Button`** | The button displayed in the sidebar that logs the user out. |
|
||||
| **`graphics.Icon`** | The simplified logo used in contexts like the the `Nav` component. |
|
||||
| **`graphics.Logo`** | The full logo used in contexts like the `Login` view. |
|
||||
| **`providers`** | Custom [React Context](https://react.dev/learn/scaling-up-with-reducer-and-context) providers that will wrap the entire Admin Panel. [More details](#custom-providers). |
|
||||
| **`actions`** | An array of Custom Components to be rendered _within_ the header of the Admin Panel, providing additional interactivity and functionality. |
|
||||
| **`header`** | An array of Custom Components to be injected above the Payload header. |
|
||||
| **`views`** | Override or create new views within the Admin Panel. [More details](./views). |
|
||||
|
||||
<Banner type="success">
|
||||
**Note:**
|
||||
You can also use set [Collection Components](../configuration/collections#custom-components) and [Global Components](../configuration/globals#custom-components) in their respective configs.
|
||||
</Banner>
|
||||
|
||||
### Custom Providers
|
||||
|
||||
As you add more and more Custom Components to your [Admin Panel](./overview), you may find it helpful to add additional [React Context](https://react.dev/learn/scaling-up-with-reducer-and-context)(s). Payload allows you to inject your own context providers in your app so you can export your own custom hooks, etc.
|
||||
|
||||
To add a Custom Provider, use the `admin.components.providers` property in your [Payload Config](../configuration/overview):
|
||||
|
||||
```ts
|
||||
import { buildConfig } from 'payload'
|
||||
|
||||
export default buildConfig({
|
||||
// ...
|
||||
admin: {
|
||||
components: {
|
||||
providers: ['/path/to/MyProvider'], // highlight-line
|
||||
},
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
Then build your Custom Provider as follows:
|
||||
|
||||
```tsx
|
||||
'use client'
|
||||
import React, { createContext, useContext } from 'react'
|
||||
|
||||
const MyCustomContext = React.createContext(myCustomValue)
|
||||
|
||||
export const MyProvider: React.FC = ({ children }) => {
|
||||
return (
|
||||
<MyCustomContext.Provider value={myCustomValue}>
|
||||
{children}
|
||||
</MyCustomContext.Provider>
|
||||
)
|
||||
}
|
||||
|
||||
export const useMyCustomContext = () => useContext(MyCustomContext)
|
||||
```
|
||||
|
||||
<Banner type="warning">
|
||||
**Reminder:** React Context exists only within Client Components. This means they must include the `use client` directive at the top of their files and cannot contain server-only code. To use a Server Component here, simply _wrap_ your Client Component with it.
|
||||
</Banner>
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
title: Customizing CSS & SCSS
|
||||
label: Customizing CSS
|
||||
order: 50
|
||||
order: 80
|
||||
desc: Customize the Payload Admin Panel further by adding your own CSS or SCSS style sheet to the configuration, powerful theme and design options are waiting for you.
|
||||
keywords: admin, css, scss, documentation, Content Management System, cms, headless, javascript, node, react, nextjs
|
||||
---
|
||||
@@ -30,7 +30,7 @@ Here is an example of how you might target the Dashboard View and change the bac
|
||||
|
||||
<Banner type="warning">
|
||||
**Note:**
|
||||
If you are building [Custom Components](../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.
|
||||
If you are building [Custom Components](./components), 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
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
---
|
||||
title: React Hooks
|
||||
label: React Hooks
|
||||
order: 50
|
||||
order: 40
|
||||
desc: Make use of all of the powerful React hooks that Payload provides.
|
||||
keywords: admin, components, custom, documentation, Content Management System, cms, headless, javascript, node, react, nextjs
|
||||
---
|
||||
|
||||
Payload provides a variety of powerful [React Hooks](https://react.dev/reference/react-dom/hooks) that can be used within your own [Custom Components](../custom-components/overview), such as [Custom Fields](../fields/overview#custom-components). With them, you can interface with Payload itself to build just about any type of complex customization you can think of.
|
||||
Payload provides a variety of powerful [React Hooks](https://react.dev/reference/react-dom/hooks) that can be used within your own [Custom Components](./components), such as [Custom Fields](../fields/overview#custom-components). With them, you can interface with Payload itself to build just about any type of complex customization you can think of.
|
||||
|
||||
<Banner type="warning">
|
||||
**Reminder:**
|
||||
All Custom Components are [React Server Components](https://react.dev/reference/rsc/server-components) by default. Hooks, on the other hand, are only available in client-side environments. To use hooks, [ensure your component is a client component](../custom-components/overview#client-components).
|
||||
All Custom Components are [React Server Components](https://react.dev/reference/rsc/server-components) by default. Hooks, on the other hand, are only available in client-side environments. To use hooks, [ensure your component is a client component](./components#client-components).
|
||||
</Banner>
|
||||
|
||||
## useField
|
||||
@@ -875,7 +875,7 @@ const Greeting: React.FC = () => {
|
||||
|
||||
## useConfig
|
||||
|
||||
Used to retrieve the Payload [Client Config](../custom-components/overview#accessing-the-payload-config).
|
||||
Used to retrieve the Payload [Client Config](./components#accessing-the-payload-config).
|
||||
|
||||
```tsx
|
||||
'use client'
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
title: Document Locking
|
||||
label: Document Locking
|
||||
order: 40
|
||||
order: 90
|
||||
desc: Ensure your documents are locked during editing to prevent concurrent changes from multiple users and maintain data integrity.
|
||||
keywords: locking, document locking, edit locking, document, concurrency, Payload, headless, Content Management System, cms, javascript, react, node, nextjs
|
||||
---
|
||||
|
||||
@@ -194,7 +194,7 @@ The Global Meta config has the same options as the [Root Metadata](#root-metadat
|
||||
|
||||
## View Metadata
|
||||
|
||||
View Metadata is the metadata that is applied to specific [Views](../custom-components/custom-views) within the Admin Panel. This metadata is used to customize the title and description of a specific view, overriding any metadata set at the [Root](#root-metadata), [Collection](#collection-metadata), or [Global](#global-metadata) level.
|
||||
View Metadata is the metadata that is applied to specific [Views](./views) within the Admin Panel. This metadata is used to customize the title and description of a specific view, overriding any metadata set at the [Root](#root-metadata), [Collection](#collection-metadata), or [Global](#global-metadata) level.
|
||||
|
||||
To customize View Metadata, use the `meta` key within your View Config:
|
||||
|
||||
|
||||
@@ -8,12 +8,12 @@ keywords: admin, components, custom, customize, documentation, Content Managemen
|
||||
|
||||
Payload dynamically generates a beautiful, [fully type-safe](../typescript/overview) Admin Panel to manage your users and data. It is highly performant, even with 100+ fields, and is translated in over 30 languages. Within the Admin Panel you can manage content, [render your site](../live-preview/overview), [preview drafts](./preview), [diff versions](../versions/overview), and so much more.
|
||||
|
||||
The Admin Panel is designed to [white-label your brand](https://payloadcms.com/blog/white-label-admin-ui). You can endlessly customize and extend the Admin UI by swapping in your own [Custom Components](../custom-components/overview)—everything from simple field labels to entire views can be modified or replaced to perfectly tailor the interface for your editors.
|
||||
The Admin Panel is designed to [white-label your brand](https://payloadcms.com/blog/white-label-admin-ui). You can endlessly customize and extend the Admin UI by swapping in your own [Custom Components](./components)—everything from simple field labels to entire views can be modified or replaced to perfectly tailor the interface for your editors.
|
||||
|
||||
The Admin Panel is written in [TypeScript](https://www.typescriptlang.org) and built with [React](https://react.dev) using the [Next.js App Router](https://nextjs.org/docs/app). It supports [React Server Components](https://react.dev/reference/rsc/server-components), enabling the use of the [Local API](/docs/local-api/overview) on the front-end. You can install Payload into any [existing Next.js app in just one line](../getting-started/installation) and [deploy it anywhere](../production/deployment).
|
||||
|
||||
<Banner type="success">
|
||||
The Payload Admin Panel is designed to be as minimal and straightforward as possible to allow easy customization and control. [Learn more](../custom-components/overview).
|
||||
The Payload Admin Panel is designed to be as minimal and straightforward as possible to allow easy customization and control. [Learn more](./components).
|
||||
</Banner>
|
||||
|
||||
<LightDarkImage
|
||||
@@ -91,7 +91,7 @@ The following options are available:
|
||||
| **`avatar`** | Set account profile picture. Options: `gravatar`, `default` or a custom React component. |
|
||||
| **`autoLogin`** | Used to automate log-in for dev and demonstration convenience. [More details](../authentication/overview). |
|
||||
| **`buildPath`** | Specify an absolute path for where to store the built Admin bundle used in production. Defaults to `path.resolve(process.cwd(), 'build')`. |
|
||||
| **`components`** | Component overrides that affect the entirety of the Admin Panel. [More details](../custom-components/overview). |
|
||||
| **`components`** | Component overrides that affect the entirety of the Admin Panel. [More details](./components). |
|
||||
| **`custom`** | Any custom properties you wish to pass to the Admin Panel. |
|
||||
| **`dateFormat`** | The date format that will be used for all dates within the Admin Panel. Any valid [date-fns](https://date-fns.org/) format pattern can be used. |
|
||||
| **`livePreview`** | Enable real-time editing for instant visual feedback of your front-end application. [More details](../live-preview/overview). |
|
||||
@@ -178,7 +178,7 @@ The following options are available:
|
||||
|
||||
<Banner type="success">
|
||||
**Tip:**
|
||||
You can easily add _new_ routes to the Admin Panel through [Custom Endpoints](../rest-api/overview#custom-endpoints) and [Custom Views](../custom-components/custom-views).
|
||||
You can easily add _new_ routes to the Admin Panel through [Custom Endpoints](../rest-api/overview#custom-endpoints) and [Custom Views](./views).
|
||||
</Banner>
|
||||
|
||||
#### Customizing Root-level Routes
|
||||
@@ -233,7 +233,7 @@ The following options are available:
|
||||
|
||||
<Banner type="success">
|
||||
**Note:**
|
||||
You can also swap out entire _views_ out for your own, using the `admin.views` property of the Payload Config. See [Custom Views](../custom-components/custom-views) for more information.
|
||||
You can also swap out entire _views_ out for your own, using the `admin.views` property of the Payload Config. See [Custom Views](./views) for more information.
|
||||
</Banner>
|
||||
|
||||
## I18n
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
title: Managing User Preferences
|
||||
label: Preferences
|
||||
order: 60
|
||||
order: 70
|
||||
desc: Store the preferences of your users as they interact with the Admin Panel.
|
||||
keywords: admin, preferences, custom, customize, documentation, Content Management System, cms, headless, javascript, node, react, nextjs
|
||||
---
|
||||
@@ -81,7 +81,7 @@ import { usePreferences } from '@payloadcms/ui'
|
||||
|
||||
const lastUsedColorsPreferenceKey = 'last-used-colors';
|
||||
|
||||
export function CustomComponent() {
|
||||
const CustomComponent = (props) => {
|
||||
const { getPreference, setPreference } = usePreferences();
|
||||
|
||||
// Store the last used colors in local state
|
||||
@@ -154,6 +154,8 @@ export function CustomComponent() {
|
||||
</Fragment>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
export default CustomComponent;
|
||||
```
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
title: Preview
|
||||
label: Preview
|
||||
order: 30
|
||||
order: 50
|
||||
desc: Enable links to your front-end to preview published or draft content.
|
||||
keywords: admin, components, preview, documentation, Content Management System, cms, headless, javascript, node, react, nextjs
|
||||
---
|
||||
|
||||
375
docs/admin/views.mdx
Normal file
375
docs/admin/views.mdx
Normal file
@@ -0,0 +1,375 @@
|
||||
---
|
||||
title: Customizing Views
|
||||
label: Customizing Views
|
||||
order: 30
|
||||
desc:
|
||||
keywords:
|
||||
---
|
||||
|
||||
Views are the individual pages that make up the [Admin Panel](./overview), such as the Dashboard, List, and Edit views. One of the most powerful ways to customize the Admin Panel is to create Custom Views. These are [Custom Components](./components) that can either replace built-in views or can be entirely new.
|
||||
|
||||
There are four types of views within the Admin Panel:
|
||||
|
||||
- [Root Views](#root-views)
|
||||
- [Collection Views](#collection-views)
|
||||
- [Global Views](#global-views)
|
||||
- [Document Views](#document-views)
|
||||
|
||||
To swap in your own Custom View, first consult the list of available components, determine the scope that corresponds to what you are trying to accomplish, then [author your React component(s)](#building-custom-views) accordingly.
|
||||
|
||||
## Root Views
|
||||
|
||||
Root Views are the main views of the [Admin Panel](./overview). These are views that are scoped directly under the `/admin` route, such as the Dashboard or Account views.
|
||||
|
||||
To swap Root Views with your own, or to [create entirely new ones](#adding-new-views), use the `admin.components.views` property of your root [Payload Config](../configuration/overview):
|
||||
|
||||
```ts
|
||||
import { buildConfig } from 'payload'
|
||||
|
||||
const config = buildConfig({
|
||||
// ...
|
||||
admin: {
|
||||
components: {
|
||||
views: {
|
||||
customView: {
|
||||
Component: '/path/to/MyCustomView#MyCustomView', // highlight-line
|
||||
path: '/my-custom-view',
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
Your Custom Root Views can optionally use one of the templates that Payload provides. The most common of these is the Default Template which provides the basic layout and navigation. Here is an example of what that might look like:
|
||||
|
||||
```tsx
|
||||
import type { AdminViewProps } from 'payload'
|
||||
|
||||
import { DefaultTemplate } from '@payloadcms/next/templates'
|
||||
import { Gutter } from '@payloadcms/ui'
|
||||
import React from 'react'
|
||||
|
||||
export const MyCustomView: React.FC<AdminViewProps> = ({
|
||||
initPageResult,
|
||||
params,
|
||||
searchParams,
|
||||
}) => {
|
||||
return (
|
||||
<DefaultTemplate
|
||||
i18n={initPageResult.req.i18n}
|
||||
locale={initPageResult.locale}
|
||||
params={params}
|
||||
payload={initPageResult.req.payload}
|
||||
permissions={initPageResult.permissions}
|
||||
searchParams={searchParams}
|
||||
user={initPageResult.req.user || undefined}
|
||||
visibleEntities={initPageResult.visibleEntities}
|
||||
>
|
||||
<Gutter>
|
||||
<h1>Custom Default Root View</h1>
|
||||
|
||||
<p>This view uses the Default Template.</p>
|
||||
</Gutter>
|
||||
</DefaultTemplate>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
_For details on how to build Custom Views, including all available props, see [Building Custom Views](#building-custom-views)._
|
||||
|
||||
The following options are available:
|
||||
|
||||
| Property | Description |
|
||||
| --------------- | ----------------------------------------------------------------------------- |
|
||||
| **`account`** | The Account view is used to show the currently logged in user's Account page. |
|
||||
| **`dashboard`** | The main landing page of the [Admin Panel](./overview). |
|
||||
|
||||
For more granular control, pass a configuration object instead. Payload exposes the following properties for each view:
|
||||
|
||||
| Property | Description |
|
||||
| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
||||
| **`Component`** * | Pass in the component path that should be rendered when a user navigates to this route. |
|
||||
| **`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.|
|
||||
| **`meta`** | Page metadata overrides to apply to this view within the Admin Panel. [More details](./metadata). |
|
||||
|
||||
_* An asterisk denotes that a property is required._
|
||||
|
||||
### Adding New Views
|
||||
|
||||
To add a _new_ views to the [Admin Panel](./overview), simply add your own key to the `views` object with at least a `path` and `Component` property. For example:
|
||||
|
||||
```ts
|
||||
import { buildConfig } from 'payload'
|
||||
|
||||
const config = buildConfig({
|
||||
// ...
|
||||
admin: {
|
||||
components: {
|
||||
views: {
|
||||
// highlight-start
|
||||
myCustomView: {
|
||||
// highlight-end
|
||||
Component: '/path/to/MyCustomView#MyCustomViewComponent',
|
||||
path: '/my-custom-view',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
The above example shows how to add a new [Root View](#root-views), but the pattern is the same for [Collection Views](#collection-views), [Global Views](#global-views), and [Document Views](#document-views). For help on how to build your own Custom Views, see [Building Custom Views](#building-custom-views).
|
||||
|
||||
<Banner type="warning">
|
||||
**Note:**
|
||||
|
||||
Routes are cascading, so unless explicitly given the `exact` property, they will
|
||||
match on URLs that simply _start_ with the route's path. This is helpful when creating catch-all
|
||||
routes in your application. Alternatively, define your nested route _before_ your parent
|
||||
route.
|
||||
</Banner>
|
||||
|
||||
<Banner type="warning">
|
||||
**Custom views are public**
|
||||
|
||||
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.
|
||||
|
||||
To swap out Collection Views with your own, or to [create entirely new ones](#adding-new-views), use the `admin.components.views` property of your [Collection Config](../configuration/collections):
|
||||
|
||||
```ts
|
||||
import type { SanitizedCollectionConfig } from 'payload'
|
||||
|
||||
export const MyCollectionConfig: SanitizedCollectionConfig = {
|
||||
// ...
|
||||
admin: {
|
||||
components: {
|
||||
views: {
|
||||
edit: {
|
||||
root: {
|
||||
Component: '/path/to/MyCustomEditView', // highlight-line
|
||||
}
|
||||
// other options include:
|
||||
// default
|
||||
// versions
|
||||
// version
|
||||
// api
|
||||
// livePreview
|
||||
// [key: string]
|
||||
// See "Document Views" for more details
|
||||
},
|
||||
list: {
|
||||
Component: '/path/to/MyCustomListView',
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
_For details on how to build Custom Views, including all available props, see [Building Custom Views](#building-custom-views)._
|
||||
|
||||
<Banner type="warning">
|
||||
**Note:**
|
||||
The `root` property will replace the _entire_ Edit View, including the title, tabs, etc., _as well as all nested [Document Views](#document-views)_, such as the API, Live Preview, and Version views. To replace only the Edit View precisely, use the `edit.default` key instead.
|
||||
</Banner>
|
||||
|
||||
The following options are available:
|
||||
|
||||
| Property | Description |
|
||||
| ---------- | ----------------------------------------------------------------------------------------------------------------- |
|
||||
| **`edit`** | The Edit View is used to edit a single document for any given Collection. [More details](#document-views). |
|
||||
| **`list`** | The List View is used to show a list of documents for any given Collection. |
|
||||
|
||||
<Banner type="success">
|
||||
**Note:**
|
||||
You can also add _new_ Collection Views to the config by adding a new key to the `views` object with at least a `path` and `Component` property. See [Adding New Views](#adding-new-views) for more information.
|
||||
</Banner>
|
||||
|
||||
## Global Views
|
||||
|
||||
Global Views are views that are scoped under the `/globals` route, such as the Document Edit View.
|
||||
|
||||
To swap out Global Views with your own or [create entirely new ones](#adding-new-views), use the `admin.components.views` property in your [Global Config](../configuration/globals):
|
||||
|
||||
```ts
|
||||
import type { SanitizedGlobalConfig } from 'payload'
|
||||
|
||||
export const MyGlobalConfig: SanitizedGlobalConfig = {
|
||||
// ...
|
||||
admin: {
|
||||
components: {
|
||||
views: {
|
||||
edit: {
|
||||
root: {
|
||||
Component: '/path/to/MyCustomEditView', // highlight-line
|
||||
}
|
||||
// other options include:
|
||||
// default
|
||||
// versions
|
||||
// version
|
||||
// api
|
||||
// livePreview
|
||||
// [key: string]
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
_For details on how to build Custom Views, including all available props, see [Building Custom Views](#building-custom-views)._
|
||||
|
||||
<Banner type="warning">
|
||||
**Note:**
|
||||
The `root` property will replace the _entire_ Edit View, including the title, tabs, etc., _as well as all nested [Document Views](#document-views)_, such as the API, Live Preview, and Version views. To replace only the Edit View precisely, use the `edit.default` key instead.
|
||||
</Banner>
|
||||
|
||||
The following options are available:
|
||||
|
||||
| Property | Description |
|
||||
| ---------- | ------------------------------------------------------------------- |
|
||||
| **`edit`** | The Edit View is used to edit a single document for any given Global. [More details](#document-views). |
|
||||
|
||||
<Banner type="success">
|
||||
**Note:**
|
||||
You can also add _new_ Global Views to the config by adding a new key to the `views` object with at least a `path` and `Component` property. See [Adding New Views](#adding-new-views) for more information.
|
||||
</Banner>
|
||||
|
||||
## Document Views
|
||||
|
||||
Document Views are views that are scoped under the `/collections/:collectionSlug/:id` or the `/globals/:globalSlug` route, such as the Edit View or the API View. All Document Views keep their overall structure across navigation changes, such as their title and tabs, and replace only the content below.
|
||||
|
||||
To swap out Document Views with your own, or to [create entirely new ones](#adding-new-views), use the `admin.components.views.Edit[key]` property in your [Collection Config](../configuration/collections) or [Global Config](../configuration/globals):
|
||||
|
||||
```ts
|
||||
import type { SanitizedCollectionConfig } from 'payload'
|
||||
|
||||
export const MyCollectionOrGlobalConfig: SanitizedCollectionConfig = {
|
||||
// ...
|
||||
admin: {
|
||||
components: {
|
||||
views: {
|
||||
edit: {
|
||||
api: {
|
||||
Component: '/path/to/MyCustomAPIViewComponent', // highlight-line
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
_For details on how to build Custom Views, including all available props, see [Building Custom Views](#building-custom-views)._
|
||||
|
||||
<Banner type="warning">
|
||||
**Note:**
|
||||
If you need to replace the _entire_ Edit View, including _all_ nested Document Views, use the `root` key. See [Custom Collection Views](#collection-views) or [Custom Global Views](#global-views) for more information.
|
||||
</Banner>
|
||||
|
||||
The following options are available:
|
||||
|
||||
| Property | Description |
|
||||
| ----------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| **`root`** | The Root View overrides all other nested views and routes. No document controls or tabs are rendered when this key is set. |
|
||||
| **`default`** | The Default View is the primary view in which your document is edited. It is rendered within the "Edit" tab. |
|
||||
| **`versions`** | The Versions View is used to navigate the version history of a single document. It is rendered within the "Versions" tab. [More details](../versions/overview). |
|
||||
| **`version`** | The Version View is used to edit a single version of a document. It is rendered within the "Version" tab. [More details](../versions/overview). |
|
||||
| **`api`** | The API View is used to display the REST API JSON response for a given document. It is rendered within the "API" tab. |
|
||||
| **`livePreview`** | The LivePreview view is used to display the Live Preview interface. It is rendered within the "Live Preview" tab. [More details](../live-preview/overview). |
|
||||
|
||||
### Document Tabs
|
||||
|
||||
Each Custom View can be given a new tab in the Edit View, if desired. Tabs are highly configurable, from as simple as changing the label to swapping out the entire component, they can be modified in any way. To add or customize tabs in the Edit View, use the `tab` key:
|
||||
|
||||
```ts
|
||||
import type { SanitizedCollectionConfig } from 'payload'
|
||||
|
||||
export const MyCollection: SanitizedCollectionConfig = {
|
||||
slug: 'my-collection',
|
||||
admin: {
|
||||
components: {
|
||||
views: {
|
||||
edit: {
|
||||
myCustomTab: {
|
||||
Component: '/path/to/MyCustomTab',
|
||||
path: '/my-custom-tab',
|
||||
tab: {
|
||||
Component: '/path/to/MyCustomTabComponent' // highlight-line
|
||||
}
|
||||
},
|
||||
anotherCustomTab: {
|
||||
Component: '/path/to/AnotherCustomView',
|
||||
path: '/another-custom-view',
|
||||
// highlight-start
|
||||
tab: {
|
||||
label: 'Another Custom View',
|
||||
href: '/another-custom-view',
|
||||
}
|
||||
// highlight-end
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
<Banner type="warning">
|
||||
**Note:**
|
||||
This applies to _both_ Collections _and_ Globals.
|
||||
</Banner>
|
||||
|
||||
## Building Custom Views
|
||||
|
||||
Custom Views are just [Custom Components](./components) rendered at the page-level. To understand how to build Custom Views, first review the [Building Custom Components](./components#building-custom-components) guide. Once you have a Custom Component ready, you can use it as a Custom View.
|
||||
|
||||
```ts
|
||||
import type { SanitizedCollectionConfig } from 'payload'
|
||||
|
||||
export const MyCollectionConfig: SanitizedCollectionConfig = {
|
||||
// ...
|
||||
admin: {
|
||||
components: {
|
||||
views: {
|
||||
edit: {
|
||||
Component: '/path/to/MyCustomView' // highlight-line
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
### Default Props
|
||||
|
||||
Your Custom Views will be provided with the following props:
|
||||
|
||||
| Prop | Description |
|
||||
| ------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| **`initPageResult`** | An object containing `req`, `payload`, `permissions`, etc. |
|
||||
| **`clientConfig`** | The Client Config object. [More details](../admin/components#accessing-the-payload-config). |
|
||||
| **`importMap`** | The import map object. |
|
||||
| **`params`** | An object containing the [Dynamic Route Parameters](https://nextjs.org/docs/app/building-your-application/routing/dynamic-routes). |
|
||||
| **`searchParams`** | An object containing the [Search Parameters](https://developer.mozilla.org/docs/Learn/Common_questions/What_is_a_URL#parameters). |
|
||||
| **`doc`** | The document being edited. Only available in Document Views. [More details](#document-views). |
|
||||
|
||||
<Banner type="success">
|
||||
**Reminder:**
|
||||
All [Custom Server Components](./components) receive `payload` and `i18n` by default. See [Building Custom Components](./components#building-custom-components) for more details.
|
||||
</Banner>
|
||||
|
||||
<Banner type="warning">
|
||||
**Important:**
|
||||
It's up to you to secure your custom views. 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>
|
||||
@@ -59,25 +59,25 @@ The following options are available:
|
||||
|
||||
| Option | Description |
|
||||
| ---------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `admin` | The configuration options for the Admin Panel. [More details](#admin-options). |
|
||||
| `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` | Manage GraphQL-related properties for this collection. [More](#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). |
|
||||
| **`admin`** | The configuration options for the Admin Panel. [More details](#admin-options). |
|
||||
| **`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`** | Manage GraphQL-related properties for this collection. [More](#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). |
|
||||
|
||||
_* An asterisk denotes that a property is required._
|
||||
|
||||
@@ -95,7 +95,7 @@ Fields define the schema of the Documents within a Collection. To learn more, go
|
||||
|
||||
## Admin Options
|
||||
|
||||
The behavior of Collections within the [Admin Panel](../admin/overview) can be fully customized to fit the needs of your application. This includes grouping or hiding their navigation links, adding [Custom Components](../custom-components/overview), selecting which fields to display in the List View, and more.
|
||||
The behavior of Collections within the [Admin Panel](../admin/overview) can be fully customized to fit the needs of your application. This includes grouping or hiding their navigation links, adding [Custom Components](../admin/components), selecting which fields to display in the List View, and more.
|
||||
|
||||
To configure Admin Options for Collections, use the `admin` property in your Collection Config:
|
||||
|
||||
@@ -114,33 +114,33 @@ The following options are available:
|
||||
|
||||
| Option | Description |
|
||||
| -------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `group` | Text or localization object used to group Collection and Global links in the admin navigation. Set to `false` to hide the link from the navigation while keeping its routes accessible. |
|
||||
| `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. |
|
||||
| `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](#custom-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](../admin/metadata). |
|
||||
| `preview` | Function to generate preview URLs within the Admin Panel that can point to your app. [More details](../admin/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](#custom-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). |
|
||||
| `baseListFilter` | You can define a default base filter for this collection's List view, which will be merged into any filters that the user performs. |
|
||||
| **`group`** | Text or localization object used to group Collection and Global links in the admin navigation. Set to `false` to hide the link from the navigation while keeping its routes accessible. |
|
||||
| **`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. |
|
||||
| **`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](#custom-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](../admin/metadata). |
|
||||
| **`preview`** | Function to generate preview URLs within the Admin Panel that can point to your app. [More details](../admin/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](#custom-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). |
|
||||
| **`baseListFilter`** | You can define a default base filter for this collection's List view, which will be merged into any filters that the user performs. |
|
||||
|
||||
### Custom Components
|
||||
|
||||
Collections can set their own [Custom Components](../custom-components/overview) which only apply to Collection-specific UI within the [Admin Panel](../admin/overview). This includes elements such as the Save Button, or entire layouts such as the Edit View.
|
||||
Collections can set their own [Custom Components](../admin/components) which only apply to Collection-specific UI within the [Admin Panel](../admin/overview). This includes elements such as the Save Button, or entire layouts such as the Edit View.
|
||||
|
||||
To override Collection Components, use the `admin.components` property in your Collection Config:
|
||||
|
||||
```ts
|
||||
import type { CollectionConfig } from 'payload'
|
||||
import type { SanitizedCollectionConfig } from 'payload'
|
||||
|
||||
export const MyCollection: CollectionConfig = {
|
||||
export const MyCollection: SanitizedCollectionConfig = {
|
||||
// ...
|
||||
admin: {
|
||||
components: { // highlight-line
|
||||
@@ -152,47 +152,23 @@ export const MyCollection: CollectionConfig = {
|
||||
|
||||
The following options are available:
|
||||
|
||||
| Option | Description |
|
||||
| --------------------- |------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| `afterList` | An array of components to inject _after_ the built-in List View. [More details](../custom-components/list-view#afterlist). |
|
||||
| `afterListTable` | An array of components to inject _after_ the built-in List View's table. [More details](../custom-components/list-view#afterlisttable). |
|
||||
| `beforeList` | An array of components to inject _before_ the built-in List View. [More details](../custom-components/list-view#beforelist). |
|
||||
| `beforeListTable` | An array of components to inject _before_ the built-in List View's table. [More details](../custom-components/list-view#beforelisttable). |
|
||||
| `listMenuItems` | An array of components to render within a menu next to the List Controls (after the Columns and Filters options) |
|
||||
| `Description` | A component to render below the Collection label in the List View. An alternative to the `admin.description` property. [More details](../custom-components/list-view#description). |
|
||||
| `edit` | Override specific components within the Edit View. [More details](#edit-view-options). |
|
||||
| `views` | Override or create new views within the Admin Panel. [More details](../custom-components/custom-views). |
|
||||
|
||||
#### Edit View Options
|
||||
|
||||
```ts
|
||||
import type { CollectionCOnfig } from 'payload'
|
||||
|
||||
export const MyCollection: CollectionCOnfig = {
|
||||
// ...
|
||||
admin: {
|
||||
components: {
|
||||
edit: { // highlight-line
|
||||
// ...
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
The following options are available:
|
||||
|
||||
| Option | Description |
|
||||
| ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------ |
|
||||
| `SaveButton` | Replace the default Save Button within the Edit View. [Drafts](../versions/drafts) must be disabled. [More details](../custom-components/edit-view#save-button). |
|
||||
| `SaveDraftButton` | Replace the default Save Draft Button within the Edit View. [Drafts](../versions/drafts) must be enabled and autosave must be disabled. [More details](../custom-components/edit-view#save-draft-button). |
|
||||
| `PublishButton` | Replace the default Publish Button within the Edit View. [Drafts](../versions/drafts) must be enabled. [More details](../custom-components/edit-view#publish-button). |
|
||||
| `PreviewButton` | Replace the default Preview Button within the Edit View. [Preview](../admin/preview) must be enabled. [More details](../custom-components/edit-view#preview-button). |
|
||||
| `Upload` | Replace the default Upload component within the Edit View. [Upload](../upload/overview) must be enabled. [More details](../custom-components/edit-view#upload). |
|
||||
| Path | Description |
|
||||
| -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------ |
|
||||
| **`beforeList`** | An array of components to inject _before_ the built-in List View |
|
||||
| **`beforeListTable`** | An array of components to inject _before_ the built-in List View's table |
|
||||
| **`afterList`** | An array of components to inject _after_ the built-in List View |
|
||||
| **`afterListTable`** | An array of components to inject _after_ the built-in List View's table |
|
||||
| **`Description`** | A component to render below the Collection label in the List View. An alternative to the `admin.description` property. |
|
||||
| **`edit.SaveButton`** | Replace the default Save Button with a Custom Component. [Drafts](../versions/drafts) must be disabled. |
|
||||
| **`edit.SaveDraftButton`** | Replace the default Save Draft Button with a Custom Component. [Drafts](../versions/drafts) must be enabled and autosave must be disabled. |
|
||||
| **`edit.PublishButton`** | Replace the default Publish Button with a Custom Component. [Drafts](../versions/drafts) must be enabled. |
|
||||
| **`edit.PreviewButton`** | Replace the default Preview Button with a Custom Component. [Preview](../admin/preview) must be enabled. |
|
||||
| **`edit.Upload`** | Replace the default Upload component with a Custom Component. [Upload](../upload/overview) must be enabled. |
|
||||
| **`views`** | Override or create new views within the Admin Panel. [More details](../admin/views). |
|
||||
|
||||
<Banner type="success">
|
||||
**Note:**
|
||||
For details on how to build Custom Components, see [Building Custom Components](../custom-components/overview#building-custom-components).
|
||||
For details on how to build Custom Components, see [Building Custom Components](../admin/components#building-custom-components).
|
||||
</Banner>
|
||||
|
||||
### Pagination
|
||||
@@ -256,10 +232,10 @@ You can also pass an object to the collection's `graphQL` property, which allows
|
||||
|
||||
| Option | Description |
|
||||
| ---------------------- | ----------------------------------------------------------------------------------- |
|
||||
| `singularName` | Override the "singular" name that will be used in GraphQL schema generation. |
|
||||
| `pluralName` | Override the "plural" name that will be used in GraphQL schema generation. |
|
||||
| `disableQueries` | Disable all GraphQL queries that correspond to this collection by passing `true`. |
|
||||
| `disableMutations` | Disable all GraphQL mutations that correspond to this collection by passing `true`. |
|
||||
| **`singularName`** | Override the "singular" name that will be used in GraphQL schema generation. |
|
||||
| **`pluralName`** | Override the "plural" name that will be used in GraphQL schema generation. |
|
||||
| **`disableQueries`** | Disable all GraphQL queries that correspond to this collection by passing `true`. |
|
||||
| **`disableMutations`** | Disable all GraphQL mutations that correspond to this collection by passing `true`. |
|
||||
|
||||
## TypeScript
|
||||
|
||||
|
||||
@@ -42,7 +42,7 @@ export default buildConfig({
|
||||
|
||||
For security and safety reasons, the [Admin Panel](../admin/overview) does **not** include Environment Variables in its _client-side_ bundle by default. But, Next.js provides a mechanism to expose Environment Variables to the client-side bundle when needed.
|
||||
|
||||
If you are building a [Custom Component](../custom-components/overview) and need to access Environment Variables from the client-side, you can do so by prefixing them with `NEXT_PUBLIC_`.
|
||||
If you are building a [Custom Component](../admin/components) and need to access Environment Variables from the client-side, you can do so by prefixing them with `NEXT_PUBLIC_`.
|
||||
|
||||
<Banner type="warning">
|
||||
**Important:**
|
||||
|
||||
@@ -67,20 +67,20 @@ The following options are available:
|
||||
|
||||
| Option | Description |
|
||||
| ------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `access` | Provide Access Control functions to define exactly who should be able to do what with this Global. [More details](../access-control/globals). |
|
||||
| `admin` | The configuration options for the Admin Panel. [More details](#admin-options). |
|
||||
| `custom` | Extension point for adding custom data (e.g. for plugins) |
|
||||
| `dbName` | Custom table or collection name for this Global depending on the Database Adapter. Auto-generated from slug if not defined. |
|
||||
| `description` | Text or React component to display below the Global header to give editors more information. |
|
||||
| `endpoints` | Add custom routes to the REST API. [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 Global. [More details](../fields/overview). |
|
||||
| `graphQL` | Manage GraphQL-related properties related to this global. [More details](#graphql) |
|
||||
| `hooks` | Entry point for Hooks. [More details](../hooks/overview#global-hooks). |
|
||||
| `label` | Text for the name in the Admin Panel or an object with keys for each language. 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 Global. |
|
||||
| `typescript` | An object with property `interface` as the text used in schema generation. Auto-generated from slug if not defined. |
|
||||
| `versions` | Set to true to enable default options, or configure with object properties. [More details](../versions/overview#global-config). |
|
||||
| **`access`** | Provide Access Control functions to define exactly who should be able to do what with this Global. [More details](../access-control/globals). |
|
||||
| **`admin`** | The configuration options for the Admin Panel. [More details](#admin-options). |
|
||||
| **`custom`** | Extension point for adding custom data (e.g. for plugins) |
|
||||
| **`dbName`** | Custom table or collection name for this Global depending on the Database Adapter. Auto-generated from slug if not defined. |
|
||||
| **`description`** | Text or React component to display below the Global header to give editors more information. |
|
||||
| **`endpoints`** | Add custom routes to the REST API. [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 Global. [More details](../fields/overview). |
|
||||
| **`graphQL`** | Manage GraphQL-related properties related to this global. [More details](#graphql) |
|
||||
| **`hooks`** | Entry point for Hooks. [More details](../hooks/overview#global-hooks). |
|
||||
| **`label`** | Text for the name in the Admin Panel or an object with keys for each language. 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 Global. |
|
||||
| **`typescript`** | An object with property `interface` as the text used in schema generation. Auto-generated from slug if not defined. |
|
||||
| **`versions`** | Set to true to enable default options, or configure with object properties. [More details](../versions/overview#global-config). |
|
||||
|
||||
_* An asterisk denotes that a property is required._
|
||||
|
||||
@@ -98,7 +98,7 @@ Fields define the schema of the Global. To learn more, go to the [Fields](../fie
|
||||
|
||||
## Admin Options
|
||||
|
||||
The behavior of Globals within the [Admin Panel](../admin/overview) can be fully customized to fit the needs of your application. This includes grouping or hiding their navigation links, adding [Custom Components](../custom-components/overview), setting page metadata, and more.
|
||||
The behavior of Globals within the [Admin Panel](../admin/overview) can be fully customized to fit the needs of your application. This includes grouping or hiding their navigation links, adding [Custom Components](../admin/components), setting page metadata, and more.
|
||||
|
||||
To configure Admin Options for Globals, use the `admin` property in your Global Config:
|
||||
|
||||
@@ -117,17 +117,17 @@ The following options are available:
|
||||
|
||||
| Option | Description |
|
||||
| ----------------- | --------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `group` | Text or localization object used to group Collection and Global links in the admin navigation. Set to `false` to hide the link from the navigation while keeping its routes accessible. |
|
||||
| `hidden` | Set to true or a function, called with the current user, returning true to exclude this Global from navigation and admin routing. |
|
||||
| `components` | Swap in your own React components to be used within this Global. [More details](#custom-components). |
|
||||
| `preview` | Function to generate a preview URL within the Admin Panel for this Global that can point to your app. [More details](../admin/preview). |
|
||||
| `livePreview` | Enable real-time editing for instant visual feedback of your front-end application. [More details](../live-preview/overview). |
|
||||
| `hideAPIURL` | Hides the "API URL" meta field while editing documents within this collection. |
|
||||
| `meta` | Page metadata overrides to apply to this Global within the Admin Panel. [More details](../admin/metadata). |
|
||||
| **`group`** | Text or localization object used to group Collection and Global links in the admin navigation. Set to `false` to hide the link from the navigation while keeping its routes accessible. |
|
||||
| **`hidden`** | Set to true or a function, called with the current user, returning true to exclude this Global from navigation and admin routing. |
|
||||
| **`components`** | Swap in your own React components to be used within this Global. [More details](#custom-components). |
|
||||
| **`preview`** | Function to generate a preview URL within the Admin Panel for this Global that can point to your app. [More details](../admin/preview). |
|
||||
| **`livePreview`** | Enable real-time editing for instant visual feedback of your front-end application. [More details](../live-preview/overview). |
|
||||
| **`hideAPIURL`** | Hides the "API URL" meta field while editing documents within this collection. |
|
||||
| **`meta`** | Page metadata overrides to apply to this Global within the Admin Panel. [More details](../admin/metadata). |
|
||||
|
||||
### Custom Components
|
||||
|
||||
Globals can set their own [Custom Components](../custom-components/overview) which only apply to Global-specific UI within the [Admin Panel](../admin/overview). This includes elements such as the Save Button, or entire layouts such as the Edit View.
|
||||
Globals can set their own [Custom Components](../admin/components) which only apply to Global-specific UI within the [Admin Panel](../admin/overview). This includes elements such as the Save Button, or entire layouts such as the Edit View.
|
||||
|
||||
To override Global Components, use the `admin.components` property in your Global Config:
|
||||
|
||||
@@ -146,42 +146,17 @@ export const MyGlobal: SanitizedGlobalConfig = {
|
||||
|
||||
The following options are available:
|
||||
|
||||
#### General
|
||||
|
||||
| Option | Description |
|
||||
| Path | Description |
|
||||
| ------------------------------ | ---------------------------------------------------------------------------------------------------------------------- |
|
||||
| `elements` | Override or create new elements within the Edit View. [More details](#edit-view-options). |
|
||||
| `views` | Override or create new views within the Admin Panel. [More details](../custom-components/custom-views). |
|
||||
|
||||
#### Edit View Options
|
||||
|
||||
```ts
|
||||
import type { SanitizedGlobalConfig } from 'payload'
|
||||
|
||||
export const MyGlobal: SanitizedGlobalConfig = {
|
||||
// ...
|
||||
admin: {
|
||||
components: {
|
||||
elements: { // highlight-line
|
||||
// ...
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
The following options are available:
|
||||
|
||||
| Option | Description |
|
||||
| ------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `SaveButton` | Replace the default Save Button with a Custom Component. [Drafts](../versions/drafts) must be disabled. [More details](../custom-components/edit-view#save-button). |
|
||||
| `SaveDraftButton` | Replace the default Save Draft Button with a Custom Component. [Drafts](../versions/drafts) must be enabled and autosave must be disabled. [More details](../custom-components/edit-view#save-draft-button). |
|
||||
| `PublishButton` | Replace the default Publish Button with a Custom Component. [Drafts](../versions/drafts) must be enabled. [More details](../custom-components/edit-view#publish-button). |
|
||||
| `PreviewButton` | Replace the default Preview Button with a Custom Component. [Preview](../admin/preview) must be enabled. [More details](../custom-components/edit-view#preview-button). |
|
||||
| **`elements.SaveButton`** | Replace the default Save Button with a Custom Component. [Drafts](../versions/drafts) must be disabled. |
|
||||
| **`elements.SaveDraftButton`** | Replace the default Save Draft Button with a Custom Component. [Drafts](../versions/drafts) must be enabled and autosave must be disabled. |
|
||||
| **`elements.PublishButton`** | Replace the default Publish Button with a Custom Component. [Drafts](../versions/drafts) must be enabled. |
|
||||
| **`elements.PreviewButton`** | Replace the default Preview Button with a Custom Component. [Preview](../admin/preview) must be enabled. |
|
||||
| **`views`** | Override or create new views within the Admin Panel. [More details](../admin/views). |
|
||||
|
||||
<Banner type="success">
|
||||
**Note:**
|
||||
For details on how to build Custom Components, see [Building Custom Components](../custom-components/overview#building-custom-components).
|
||||
For details on how to build Custom Components, see [Building Custom Components](../admin/components#building-custom-components).
|
||||
</Banner>
|
||||
|
||||
## GraphQL
|
||||
@@ -192,9 +167,9 @@ You can also pass an object to the global's `graphQL` property, which allows you
|
||||
|
||||
| Option | Description |
|
||||
| ---------------------- | ----------------------------------------------------------------------------------- |
|
||||
| `name` | Override the name that will be used in GraphQL schema generation. |
|
||||
| `disableQueries` | Disable all GraphQL queries that correspond to this global by passing `true`. |
|
||||
| `disableMutations` | Disable all GraphQL mutations that correspond to this global by passing `true`. |
|
||||
| **`name`** | Override the name that will be used in GraphQL schema generation. |
|
||||
| **`disableQueries`** | Disable all GraphQL queries that correspond to this global by passing `true`. |
|
||||
| **`disableMutations`** | Disable all GraphQL mutations that correspond to this global by passing `true`. |
|
||||
|
||||
## TypeScript
|
||||
|
||||
|
||||
@@ -55,9 +55,9 @@ 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'`. |
|
||||
| `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. |
|
||||
| **`fallbackLanguage`** | The language to fall back to if the user's preferred language is not supported. Default is `'en'`. |
|
||||
| **`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. |
|
||||
|
||||
## Adding Languages
|
||||
|
||||
@@ -227,7 +227,7 @@ export default buildConfig({
|
||||
})
|
||||
```
|
||||
|
||||
Import the shared translation types to use in your [Custom Component](../custom-components/overview):
|
||||
Import the shared translation types to use in your [Custom Component](../admin/components):
|
||||
|
||||
```ts
|
||||
// <rootDir>/components/MyComponent.tsx
|
||||
|
||||
@@ -104,7 +104,7 @@ _* An asterisk denotes that a property is required._
|
||||
|
||||
<Banner type="warning">
|
||||
**Note:**
|
||||
Some properties are removed from the client-side bundle. [More details](../custom-components/overview#accessing-the-payload-config).
|
||||
Some properties are removed from the client-side bundle. [More details](../admin/components#accessing-the-payload-config).
|
||||
</Banner>
|
||||
|
||||
### Typescript Config
|
||||
|
||||
@@ -1,49 +0,0 @@
|
||||
---
|
||||
title: Swap in your own React Context providers
|
||||
label: Custom Providers
|
||||
order: 30
|
||||
desc:
|
||||
keywords: admin, components, custom, documentation, Content Management System, cms, headless, javascript, node, react, nextjs
|
||||
---
|
||||
|
||||
As you add more and more [Custom Components](./overview) to your [Admin Panel](../admin/overview), you may find it helpful to add additional [React Context](https://react.dev/learn/scaling-up-with-reducer-and-context)(s) to your app. Payload allows you to inject your own context providers where you can export your own custom hooks, etc.
|
||||
|
||||
To add a Custom Provider, use the `admin.components.providers` property in your [Payload Config](../configuration/overview):
|
||||
|
||||
```ts
|
||||
import { buildConfig } from 'payload'
|
||||
|
||||
export default buildConfig({
|
||||
// ...
|
||||
admin: {
|
||||
components: {
|
||||
providers: ['/path/to/MyProvider'], // highlight-line
|
||||
},
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
Then build your Custom Provider as follows:
|
||||
|
||||
```tsx
|
||||
'use client'
|
||||
import React, { createContext, useContext } from 'react'
|
||||
|
||||
const MyCustomContext = React.createContext(myCustomValue)
|
||||
|
||||
export function MyProvider({ children }: { children: React.ReactNode }) {
|
||||
return (
|
||||
<MyCustomContext.Provider value={myCustomValue}>
|
||||
{children}
|
||||
</MyCustomContext.Provider>
|
||||
)
|
||||
}
|
||||
|
||||
export const useMyCustomContext = () => useContext(MyCustomContext)
|
||||
```
|
||||
|
||||
_For details on how to build Custom Components, see [Building Custom Components](./overview#building-custom-components)._
|
||||
|
||||
<Banner type="warning">
|
||||
**Reminder:** React Context exists only within Client Components. This means they must include the `use client` directive at the top of their files and cannot contain server-only code. To use a Server Component here, simply _wrap_ your Client Component with it.
|
||||
</Banner>
|
||||
@@ -1,364 +0,0 @@
|
||||
---
|
||||
title: Customizing Views
|
||||
label: Customizing Views
|
||||
order: 40
|
||||
desc:
|
||||
keywords:
|
||||
---
|
||||
|
||||
Views are the individual pages that make up the [Admin Panel](../admin/overview), such as the Dashboard, [List View](./list-view), and [Edit View](./edit-view). One of the most powerful ways to customize the Admin Panel is to create Custom Views. These are [Custom Components](./overview) that can either replace built-in views or be entirely new.
|
||||
|
||||
There are four types of views within the Admin Panel:
|
||||
|
||||
- [Root Views](#root-views)
|
||||
- [Collection Views](#collection-views)
|
||||
- [Global Views](#global-views)
|
||||
- [Document Views](./document-views)
|
||||
|
||||
To swap in your own Custom View, first determine the scope that corresponds to what you are trying to accomplish, consult the list of available components, then [author your React component(s)](#building-custom-views) accordingly.
|
||||
|
||||
## Configuration
|
||||
|
||||
### Replacing Views
|
||||
|
||||
To customize views, use the `admin.components.views` property in your [Payload Config](../configuration/overview). This is an object with keys for each view you want to customize. Each key corresponds to the view you want to customize.
|
||||
|
||||
The exact list of available keys depends on the scope of the view you are customizing, depending on whether it's a [Root View](#root-views), [Collection View](#collection-views), or [Global View](#global-views). Regardless of the scope, the principles are the same.
|
||||
|
||||
Here is an example of how to swap out a built-in view:
|
||||
|
||||
```ts
|
||||
import { buildConfig } from 'payload'
|
||||
|
||||
const config = buildConfig({
|
||||
// ...
|
||||
admin: {
|
||||
components: {
|
||||
views: {
|
||||
// highlight-start
|
||||
dashboard: {
|
||||
Component: '/path/to/MyCustomDashboard',
|
||||
}
|
||||
// highlight-end
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
For more granular control, pass a configuration object instead. Payload exposes the following properties for each view:
|
||||
|
||||
| Property | Description |
|
||||
| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
||||
| `Component` * | Pass in the component path that should be rendered when a user navigates to this route. |
|
||||
| `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.|
|
||||
| `meta` | Page metadata overrides to apply to this view within the Admin Panel. [More details](./metadata). |
|
||||
|
||||
_* An asterisk denotes that a property is required._
|
||||
|
||||
### Adding New Views
|
||||
|
||||
To add a _new_ view to the [Admin Panel](../admin/overview), simply add your own key to the `views` object. This is true for all view scopes.
|
||||
|
||||
New views require at least the `Component` and `path` properties:
|
||||
|
||||
```ts
|
||||
import { buildConfig } from 'payload'
|
||||
|
||||
const config = buildConfig({
|
||||
// ...
|
||||
admin: {
|
||||
components: {
|
||||
views: {
|
||||
// highlight-start
|
||||
myCustomView: {
|
||||
Component: '/path/to/MyCustomView#MyCustomViewComponent',
|
||||
path: '/my-custom-view',
|
||||
},
|
||||
// highlight-end
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
<Banner type="warning">
|
||||
**Note:**
|
||||
Routes are cascading, so unless explicitly given the `exact` property, they will
|
||||
match on URLs that simply _start_ with the route's path. This is helpful when creating catch-all
|
||||
routes in your application. Alternatively, define your nested route _before_ your parent
|
||||
route.
|
||||
</Banner>
|
||||
|
||||
|
||||
## Building Custom Views
|
||||
|
||||
Custom Views are simply [Custom Components](./overview) rendered at the page-level. Custom Views can either [replace existing views](#replacing-views) or [add entirely new ones](#adding-new-views). The process is generally the same regardless of the type of view you are customizing.
|
||||
|
||||
To understand how to build Custom Views, first review the [Building Custom Components](./overview#building-custom-components) guide. Once you have a Custom Component ready, you can use it as a Custom View.
|
||||
|
||||
```ts
|
||||
import type { CollectionConfig } from 'payload'
|
||||
|
||||
export const MyCollectionConfig: CollectionConfig = {
|
||||
// ...
|
||||
admin: {
|
||||
components: {
|
||||
views: {
|
||||
// highlight-start
|
||||
edit: {
|
||||
Component: '/path/to/MyCustomView' // highlight-line
|
||||
}
|
||||
// highlight-end
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
### Default Props
|
||||
|
||||
Your Custom Views will be provided with the following props:
|
||||
|
||||
| Prop | Description |
|
||||
| ------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `initPageResult` | An object containing `req`, `payload`, `permissions`, etc. |
|
||||
| `clientConfig` | The Client Config object. [More details](./overview#accessing-the-payload-config). |
|
||||
| `importMap` | The import map object. |
|
||||
| `params` | An object containing the [Dynamic Route Parameters](https://nextjs.org/docs/app/building-your-application/routing/dynamic-routes). |
|
||||
| `searchParams` | An object containing the [Search Parameters](https://developer.mozilla.org/docs/Learn/Common_questions/What_is_a_URL#parameters). |
|
||||
| `doc` | The document being edited. Only available in Document Views. [More details](./document-views). |
|
||||
| `i18n` | The [i18n](../configuration/i18n) object. |
|
||||
| `payload` | The [Payload](../local-api/overview) class. |
|
||||
|
||||
<Banner type="warning">
|
||||
**Note:**
|
||||
Some views may receive additional props, such as [Collection Views](#collection-views) and [Global Views](#global-views). See the relevant section for more details.
|
||||
</Banner>
|
||||
|
||||
Here is an example of a Custom View component:
|
||||
|
||||
```tsx
|
||||
import type { AdminViewServerProps } from 'payload'
|
||||
|
||||
import { Gutter } from '@payloadcms/ui'
|
||||
import React from 'react'
|
||||
|
||||
export function MyCustomView(props: AdminViewServerProps) {
|
||||
return (
|
||||
<Gutter>
|
||||
<h1>Custom Default Root View</h1>
|
||||
<p>This view uses the Default Template.</p>
|
||||
</Gutter>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
<Banner type="success">
|
||||
**Tip:**
|
||||
For consistent layout and navigation, you may want to wrap your Custom View with one of the built-in [Template](./overview#templates).
|
||||
</Banner>
|
||||
|
||||
### View Templates
|
||||
|
||||
Your Custom Root Views can optionally use one of the templates that Payload provides. The most common of these is the Default Template which provides the basic layout and navigation.
|
||||
|
||||
Here is an example of how to use the Default Template in your Custom View:
|
||||
|
||||
```tsx
|
||||
import type { AdminViewServerProps } from 'payload'
|
||||
|
||||
import { DefaultTemplate } from '@payloadcms/next/templates'
|
||||
import { Gutter } from '@payloadcms/ui'
|
||||
import React from 'react'
|
||||
|
||||
export function MyCustomView({
|
||||
initPageResult,
|
||||
params,
|
||||
searchParams,
|
||||
}: AdminViewServerProps) {
|
||||
return (
|
||||
<DefaultTemplate
|
||||
i18n={initPageResult.req.i18n}
|
||||
locale={initPageResult.locale}
|
||||
params={params}
|
||||
payload={initPageResult.req.payload}
|
||||
permissions={initPageResult.permissions}
|
||||
searchParams={searchParams}
|
||||
user={initPageResult.req.user || undefined}
|
||||
visibleEntities={initPageResult.visibleEntities}
|
||||
>
|
||||
<Gutter>
|
||||
<h1>Custom Default Root View</h1>
|
||||
<p>This view uses the Default Template.</p>
|
||||
</Gutter>
|
||||
</DefaultTemplate>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### Securing Custom Views
|
||||
|
||||
All Custom Views are public by default. It's up to you to secure your custom views. 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.
|
||||
|
||||
Here is how you might secure a Custom View:
|
||||
|
||||
```tsx
|
||||
import type { AdminViewServerProps } from 'payload'
|
||||
|
||||
import { Gutter } from '@payloadcms/ui'
|
||||
import React from 'react'
|
||||
|
||||
export function MyCustomView({
|
||||
initPageResult
|
||||
}: AdminViewServerProps) {
|
||||
const {
|
||||
req: {
|
||||
user
|
||||
}
|
||||
} = initPageResult
|
||||
|
||||
if (!user) {
|
||||
return <p>You must be logged in to view this page.</p>
|
||||
}
|
||||
|
||||
return (
|
||||
<Gutter>
|
||||
<h1>Custom Default Root View</h1>
|
||||
<p>This view uses the Default Template.</p>
|
||||
</Gutter>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
## Root Views
|
||||
|
||||
Root Views are the main views of the [Admin Panel](../admin/overview). These are views that are scoped directly under the `/admin` route, such as the Dashboard or Account views.
|
||||
|
||||
To [swap out](#replacing-views) Root Views with your own, or to [create entirely new ones](#adding-new-views), use the `admin.components.views` property at the root of your [Payload Config](../configuration/overview):
|
||||
|
||||
```ts
|
||||
import { buildConfig } from 'payload'
|
||||
|
||||
const config = buildConfig({
|
||||
// ...
|
||||
admin: {
|
||||
components: {
|
||||
views: {
|
||||
// highlight-start
|
||||
dashboard: {
|
||||
Component: '/path/to/Dashboard',
|
||||
}
|
||||
// highlight-end
|
||||
// Other options include:
|
||||
// - account
|
||||
// - [key: string]
|
||||
// See below for more details
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
_For details on how to build Custom Views, including all available props, see [Building Custom Views](#building-custom-views)._
|
||||
|
||||
The following options are available:
|
||||
|
||||
| Property | Description |
|
||||
| --------------- | ----------------------------------------------------------------------------- |
|
||||
| `account` | The Account view is used to show the currently logged in user's Account page. |
|
||||
| `dashboard` | The main landing page of the Admin Panel. |
|
||||
| `[key]` | Any other key can be used to add a completely new Root View. [More details](#adding-new-views). |
|
||||
|
||||
## Collection Views
|
||||
|
||||
Collection Views are views that are scoped under the `/collections` route, such as the Collection List and Document Edit views.
|
||||
|
||||
To [swap out](#replacing-views) Collection Views with your own, or to [create entirely new ones](#adding-new-views), use the `admin.components.views` property of your [Collection Config](../configuration/collections):
|
||||
|
||||
```ts
|
||||
import type { CollectionConfig } from 'payload'
|
||||
|
||||
export const MyCollectionConfig: CollectionConfig = {
|
||||
// ...
|
||||
admin: {
|
||||
components: {
|
||||
views: {
|
||||
// highlight-start
|
||||
edit: {
|
||||
default: {
|
||||
Component: '/path/to/MyCustomCollectionView',
|
||||
}
|
||||
}
|
||||
// highlight-end
|
||||
// Other options include:
|
||||
// - list
|
||||
// - [key: string]
|
||||
// See below for more details
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
<Banner type="success">
|
||||
**Reminder:**
|
||||
The `edit` key is comprised of various nested views, known as Document Views, that relate to the same Collection Document. [More details](./document-views).
|
||||
</Banner>
|
||||
|
||||
The following options are available:
|
||||
|
||||
| Property | Description |
|
||||
| ---------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `edit` | The Edit View corresponds to a single Document for any given Collection and consists of various nested views. [More details](./document-views). |
|
||||
| `list` | The List View is used to show a list of Documents for any given Collection. [More details](#list-view). |
|
||||
| `[key]` | Any other key can be used to add a completely new Collection View. [More details](#adding-new-views). |
|
||||
|
||||
_For details on how to build Custom Views, including all available props, see [Building Custom Views](#building-custom-views)._
|
||||
|
||||
## Global Views
|
||||
|
||||
Global Views are views that are scoped under the `/globals` route, such as the Edit View.
|
||||
|
||||
To [swap out](#replacing-views) Global Views with your own or [create entirely new ones](#adding-new-views), use the `admin.components.views` property in your [Global Config](../configuration/globals):
|
||||
|
||||
```ts
|
||||
import type { SanitizedGlobalConfig } from 'payload'
|
||||
|
||||
export const MyGlobalConfig: SanitizedGlobalConfig = {
|
||||
// ...
|
||||
admin: {
|
||||
components: {
|
||||
views: {
|
||||
// highlight-start
|
||||
edit: {
|
||||
default: {
|
||||
Component: '/path/to/MyCustomGlobalView',
|
||||
}
|
||||
}
|
||||
// highlight-end
|
||||
// Other options include:
|
||||
// - [key: string]
|
||||
// See below for more details
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
<Banner type="success">
|
||||
**Reminder:**
|
||||
The `edit` key is comprised of various nested views, known as Document Views, that relate to the same Global Document. [More details](./document-views).
|
||||
</Banner>
|
||||
|
||||
The following options are available:
|
||||
|
||||
| Property | Description |
|
||||
| ---------- | ----------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `edit` | The Edit View represents a single Document for any given Global and consists of various nested views. [More details](./document-views). |
|
||||
| `[key]` | Any other key can be used to add a completely new Global View. [More details](#adding-new-views). |
|
||||
|
||||
_For details on how to build Custom Views, including all available props, see [Building Custom Views](#building-custom-views)._
|
||||
@@ -1,186 +0,0 @@
|
||||
---
|
||||
title: Document Views
|
||||
label: Document Views
|
||||
order: 50
|
||||
desc:
|
||||
keywords:
|
||||
---
|
||||
|
||||
Document Views consist of multiple, individual views that together represent any single [Collection](../configuration/collections) or [Global](../configuration/globals) Document. All Document Views and are scoped under the `/collections/:collectionSlug/:id` or the `/globals/:globalSlug` route, respectively.
|
||||
|
||||
There are a number of default Document Views, such as the [Edit View](./edit-view) and API View, but you can also create [entirely new views](./custom-views#adding-new-views) as needed. All Document Views share a layout and can be given their own tab-based navigation, if desired.
|
||||
|
||||
To customize Document Views, use the `admin.components.views.edit[key]` property in your [Collection Config](../configuration/collections) or [Global Config](../configuration/globals):
|
||||
|
||||
```ts
|
||||
import type { CollectionConfig } from 'payload'
|
||||
|
||||
export const MyCollectionOrGlobalConfig: CollectionConfig = {
|
||||
// ...
|
||||
admin: {
|
||||
components: {
|
||||
views: {
|
||||
// highlight-start
|
||||
edit: {
|
||||
default: {
|
||||
Component: '/path/to/MyCustomEditView',
|
||||
},
|
||||
// Other options include:
|
||||
// - root
|
||||
// - api
|
||||
// - versions
|
||||
// - version
|
||||
// - livePreview
|
||||
// - [key: string]
|
||||
// See below for more details
|
||||
},
|
||||
// highlight-end
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
## Config Options
|
||||
|
||||
The following options are available:
|
||||
|
||||
| Property | Description |
|
||||
| ----------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `root` | The Root View overrides all other nested views and routes. No document controls or tabs are rendered when this key is set. [More details](#document-root). |
|
||||
| `default` | The Default View is the primary view in which your document is edited. It is rendered within the "Edit" tab. [More details](./edit-view). |
|
||||
| `versions` | The Versions View is used to navigate the version history of a single document. It is rendered within the "Versions" tab. [More details](../versions/overview). |
|
||||
| `version` | The Version View is used to edit a single version of a document. It is rendered within the "Version" tab. [More details](../versions/overview). |
|
||||
| `api` | The API View is used to display the REST API JSON response for a given document. It is rendered within the "API" tab. |
|
||||
| `livePreview` | The LivePreview view is used to display the Live Preview interface. It is rendered within the "Live Preview" tab. [More details](../live-preview/overview). |
|
||||
| `[key]` | Any other key can be used to add a completely new Document View. |
|
||||
|
||||
_For details on how to build Custom Views, including all available props, see [Building Custom Views](./custom-views#building-custom-views)._
|
||||
|
||||
### Document Root
|
||||
|
||||
The Document Root is mounted on the top-level route for a Document. Setting this property will completely take over the entire Document View layout, including the title, [Document Tabs](#ocument-tabs), _and all other nested Document Views_ including the [Edit View](./edit-view), API View, etc.
|
||||
|
||||
When setting a Document Root, you are responsible for rendering all necessary components and controls, as no document controls or tabs would be rendered. To replace only the Edit View precisely, use the `edit.default` key instead.
|
||||
|
||||
To override the Document Root, use the `views.edit.root` property in your [Collection Config](../configuration/collections) or [Global Config](../configuration/globals):
|
||||
|
||||
```ts
|
||||
import type { CollectionConfig } from 'payload'
|
||||
|
||||
export const MyCollection: CollectionConfig = {
|
||||
slug: 'my-collection',
|
||||
admin: {
|
||||
components: {
|
||||
views: {
|
||||
edit: {
|
||||
// highlight-start
|
||||
root: {
|
||||
Component: '/path/to/MyCustomRootComponent', // highlight-line
|
||||
},
|
||||
// highlight-end
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
### Edit View
|
||||
|
||||
The Edit View is where users interact with individual Collection and Global Documents. This is where they can view, edit, and save their content. the Edit View is keyed under the `default` property in the `views.edit` object.
|
||||
|
||||
For more information on customizing the Edit View, see the [Edit View](./edit-view) documentation.
|
||||
|
||||
## Document Tabs
|
||||
|
||||
Each Document View can be given a tab for navigation, if desired. Tabs are highly configurable, from as simple as changing the label to swapping out the entire component, they can be modified in any way.
|
||||
|
||||
To add or customize tabs in the Document View, use the `views.edit.[key].tab` property in your [Collection Config](../configuration/collections) or [Global Config](../configuration/globals):
|
||||
|
||||
```ts
|
||||
import type { CollectionConfig } from 'payload'
|
||||
|
||||
export const MyCollection: CollectionConfig = {
|
||||
slug: 'my-collection',
|
||||
admin: {
|
||||
components: {
|
||||
views: {
|
||||
edit: {
|
||||
myCustomTab: {
|
||||
Component: '/path/to/MyCustomTab',
|
||||
path: '/my-custom-tab',
|
||||
// highlight-start
|
||||
tab: {
|
||||
Component: '/path/to/MyCustomTabComponent'
|
||||
}
|
||||
// highlight-end
|
||||
},
|
||||
anotherCustomTab: {
|
||||
Component: '/path/to/AnotherCustomView',
|
||||
path: '/another-custom-view',
|
||||
// highlight-start
|
||||
tab: {
|
||||
label: 'Another Custom View',
|
||||
href: '/another-custom-view',
|
||||
}
|
||||
// highlight-end
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
<Banner type="warning">
|
||||
**Note:**
|
||||
This applies to _both_ Collections _and_ Globals.
|
||||
</Banner>
|
||||
|
||||
The following options are available for tabs:
|
||||
|
||||
| Property | Description |
|
||||
| ----------- | ----------------------------------------------------------------------------------------------------- |
|
||||
| `label` | The label to display in the tab. |
|
||||
| `href` | The URL to navigate to when the tab is clicked. This is optional and defaults to the tab's `path`. |
|
||||
| `Component` | The component to render in the tab. This can be a Server or Client component. [More details](#tab-components) |
|
||||
|
||||
### Tab Components
|
||||
|
||||
If changing the label or href is not enough, you can also replace the entire tab component with your own custom component. This can be done by setting the `tab.Component` property to the path of your custom component.
|
||||
|
||||
Here is an example of how to scaffold a custom Document Tab:
|
||||
|
||||
#### Server Component
|
||||
|
||||
```tsx
|
||||
import React from 'react'
|
||||
import type { DocumentTabServerProps } from 'payload'
|
||||
import { Link } from '@payloadcms/ui'
|
||||
|
||||
export function MyCustomTabComponent(props: DocumentTabServerProps) {
|
||||
return (
|
||||
<Link href="/my-custom-tab">
|
||||
This is a custom Document Tab (Server)
|
||||
</Link>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
#### Client Component
|
||||
|
||||
```tsx
|
||||
'use client'
|
||||
import React from 'react'
|
||||
import type { DocumentTabClientProps } from 'payload'
|
||||
import { Link } from '@payloadcms/ui'
|
||||
|
||||
export function MyCustomTabComponent(props: DocumentTabClientProps) {
|
||||
return (
|
||||
<Link href="/my-custom-tab">
|
||||
This is a custom Document Tab (Client)
|
||||
</Link>
|
||||
)
|
||||
}
|
||||
```
|
||||
@@ -1,463 +0,0 @@
|
||||
---
|
||||
title: Edit View
|
||||
label: Edit View
|
||||
order: 60
|
||||
desc:
|
||||
keywords: admin, components, custom, documentation, Content Management System, cms, headless, javascript, node, react, nextjs
|
||||
---
|
||||
|
||||
The Edit View is where users interact with individual [Collection](../collections/overview) and [Global](../globals/overview) Documents within the [Admin Panel](../admin/overview). The Edit View contains the actual form in which submits the data to the server. This is where they can view, edit, and save their content. It contains controls for saving, publishing, and previewing the document, all of which can be customized to a high degree.
|
||||
|
||||
The Edit View can be swapped out in its entirety for a Custom View, or it can be injected with a number of Custom Components to add additional functionality or presentational elements without replacing the entire view.
|
||||
|
||||
<Banner type="warning">
|
||||
**Note:**
|
||||
The Edit View is one of many [Document Views](./document-views) in the Payload Admin Panel. Each Document View is responsible for a different aspect of the interacting with a single Document.
|
||||
</Banner>
|
||||
|
||||
## Custom Edit View
|
||||
|
||||
To swap out the entire Edit View with a [Custom View](./custom-views), use the `views.edit.default` property in your [Collection Config](../configuration/collections) or [Global Config](../configuration/globals):
|
||||
|
||||
```tsx
|
||||
import { buildConfig } from 'payload'
|
||||
|
||||
const config = buildConfig({
|
||||
// ...
|
||||
admin: {
|
||||
components: {
|
||||
views: {
|
||||
edit: {
|
||||
// highlight-start
|
||||
default: {
|
||||
Component: '/path/to/MyCustomEditViewComponent',
|
||||
},
|
||||
// highlight-end
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
Here is an example of a custom Edit View:
|
||||
|
||||
#### Server Component
|
||||
|
||||
```tsx
|
||||
import React from 'react'
|
||||
import type { DocumentViewServerProps } from 'payload'
|
||||
|
||||
export function MyCustomServerEditView(props: DocumentViewServerProps) {
|
||||
return (
|
||||
<div>
|
||||
This is a custom Edit View (Server)
|
||||
</div>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
#### Client Component
|
||||
|
||||
```tsx
|
||||
'use client'
|
||||
import React from 'react'
|
||||
import type { DocumentViewClientProps } from 'payload'
|
||||
|
||||
export function MyCustomClientEditView(props: DocumentViewClientProps) {
|
||||
return (
|
||||
<div>
|
||||
This is a custom Edit View (Client)
|
||||
</div>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
_For details on how to build Custom Views, including all available props, see [Building Custom Views](./custom-views#building-custom-views)._
|
||||
|
||||
## Custom Components
|
||||
|
||||
In addition to swapping out the entire Edit View with a [Custom View](./custom-views), you can also override individual components. This allows you to customize specific parts of the Edit View without swapping out the entire view.
|
||||
|
||||
<Banner type="warning">
|
||||
**Important:**
|
||||
Collection and Globals are keyed to a different property in the `admin.components` object have slightly different options. Be sure to use the correct key for the entity you are working with.
|
||||
</Banner>
|
||||
|
||||
#### Collections
|
||||
|
||||
To override Edit View components for a Collection, use the `admin.components.edit` property in your [Collection Config](../configuration/collections):
|
||||
|
||||
```ts
|
||||
import type { CollectionConfig } from 'payload'
|
||||
|
||||
export const MyCollection: CollectionConfig = {
|
||||
// ...
|
||||
admin: {
|
||||
components: {
|
||||
// highlight-start
|
||||
edit: {
|
||||
// ...
|
||||
},
|
||||
// highlight-end
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
The following options are available:
|
||||
|
||||
| Path | Description |
|
||||
|-----------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `SaveButton` | A button that saves the current document. [More details](#SaveButton). |
|
||||
| `SaveDraftButton` | A button that saves the current document as a draft. [More details](#SaveDraftButton). |
|
||||
| `PublishButton` | A button that publishes the current document. [More details](#PublishButton). |
|
||||
| `PreviewButton` | A button that previews the current document. [More details](#PreviewButton). |
|
||||
| `Description` | A description of the Collection. [More details](#Description). |
|
||||
| `Upload` | A file upload component. [More details](#Upload). |
|
||||
|
||||
#### Globals
|
||||
|
||||
To override Edit View components for Globals, use the `admin.components.elements` property in your [Global Config](../configuration/globals):
|
||||
|
||||
```ts
|
||||
import type { GlobalConfig } from 'payload'
|
||||
|
||||
export const MyGlobal: GlobalConfig = {
|
||||
// ...
|
||||
admin: {
|
||||
components: {
|
||||
// highlight-start
|
||||
elements: {
|
||||
// ...
|
||||
},
|
||||
// highlight-end
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
The following options are available:
|
||||
|
||||
| Path | Description |
|
||||
|-----------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `SaveButton` | A button that saves the current document. [More details](#SaveButton). |
|
||||
| `SaveDraftButton` | A button that saves the current document as a draft. [More details](#SaveDraftButton). |
|
||||
| `PublishButton` | A button that publishes the current document. [More details](#PublishButton). |
|
||||
| `PreviewButton` | A button that previews the current document. [More details](#PreviewButton). |
|
||||
| `Description` | A description of the Global. [More details](#Description). |
|
||||
|
||||
### SaveButton
|
||||
|
||||
The `SaveButton` property allows you to render a custom Save Button in the Edit View.
|
||||
|
||||
To add a `SaveButton` component, use the `components.edit.SaveButton` property in your [Collection Config](../configuration/collections) or `components.elements.SaveButton` in your [Global Config](../configuration/globals):
|
||||
|
||||
```ts
|
||||
import type { CollectionConfig } from 'payload'
|
||||
|
||||
export const MyCollection: CollectionConfig = {
|
||||
// ...
|
||||
admin: {
|
||||
components: {
|
||||
edit: {
|
||||
// highlight-start
|
||||
SaveButton: '/path/to/MySaveButton',
|
||||
// highlight-end
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
Here's an example of a custom `SaveButton` component:
|
||||
|
||||
#### Server Component
|
||||
|
||||
```tsx
|
||||
import React from 'react'
|
||||
import { SaveButton } from '@payloadcms/ui'
|
||||
import type { SaveButtonServerProps } from 'payload'
|
||||
|
||||
export function MySaveButton(props: SaveButtonServerProps) {
|
||||
return (
|
||||
<SaveButton label="Save" />
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
#### Client Component
|
||||
|
||||
```tsx
|
||||
'use client'
|
||||
import React from 'react'
|
||||
import { SaveButton } from '@payloadcms/ui'
|
||||
import type { SaveButtonClientProps } from 'payload'
|
||||
|
||||
export function MySaveButton(props: SaveButtonClientProps) {
|
||||
return (
|
||||
<SaveButton label="Save" />
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### SaveDraftButton
|
||||
|
||||
The `SaveDraftButton` property allows you to render a custom Save Draft Button in the Edit View.
|
||||
|
||||
To add a `SaveDraftButton` component, use the `components.edit.SaveDraftButton` property in your [Collection Config](../configuration/collections) or `components.elements.SaveDraftButton` in your [Global Config](../configuration/globals):
|
||||
|
||||
```ts
|
||||
import type { CollectionConfig } from 'payload'
|
||||
|
||||
export const MyCollection: CollectionConfig = {
|
||||
// ...
|
||||
admin: {
|
||||
components: {
|
||||
edit: {
|
||||
// highlight-start
|
||||
SaveDraftButton: '/path/to/MySaveDraftButton',
|
||||
// highlight-end
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
Here's an example of a custom `SaveDraftButton` component:
|
||||
|
||||
#### Server Component
|
||||
|
||||
```tsx
|
||||
import React from 'react'
|
||||
import { SaveDraftButton } from '@payloadcms/ui'
|
||||
import type { SaveDraftButtonServerProps } from 'payload'
|
||||
|
||||
export function MySaveDraftButton(props: SaveDraftButtonServerProps) {
|
||||
return (
|
||||
<SaveDraftButton />
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
#### Client Component
|
||||
|
||||
```tsx
|
||||
'use client'
|
||||
import React from 'react'
|
||||
import { SaveDraftButton } from '@payloadcms/ui'
|
||||
import type { SaveDraftButtonClientProps } from 'payload'
|
||||
|
||||
export function MySaveDraftButton(props: SaveDraftButtonClientProps) {
|
||||
return (
|
||||
<SaveDraftButton />
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### PublishButton
|
||||
|
||||
The `PublishButton` property allows you to render a custom Publish Button in the Edit View.
|
||||
|
||||
To add a `PublishButton` component, use the `components.edit.PublishButton` property in your [Collection Config](../configuration/collections) or `components.elements.PublishButton` in your [Global Config](../configuration/globals):
|
||||
|
||||
```ts
|
||||
import type { CollectionConfig } from 'payload'
|
||||
|
||||
export const MyCollection: CollectionConfig = {
|
||||
// ...
|
||||
admin: {
|
||||
components: {
|
||||
edit: {
|
||||
// highlight-start
|
||||
PublishButton: '/path/to/MyPublishButton',
|
||||
// highlight-end
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
Here's an example of a custom `PublishButton` component:
|
||||
|
||||
#### Server Component
|
||||
|
||||
```tsx
|
||||
import React from 'react'
|
||||
import { PublishButton } from '@payloadcms/ui'
|
||||
import type { PublishButtonClientProps } from 'payload'
|
||||
|
||||
export function MyPublishButton(props: PublishButtonServerProps) {
|
||||
return (
|
||||
<PublishButton label="Publish" />
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
#### Client Component
|
||||
|
||||
```tsx
|
||||
'use client'
|
||||
import React from 'react'
|
||||
import { PublishButton } from '@payloadcms/ui'
|
||||
import type { PublishButtonClientProps } from 'payload'
|
||||
|
||||
export function MyPublishButton(props: PublishButtonClientProps) {
|
||||
return (
|
||||
<PublishButton label="Publish" />
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### PreviewButton
|
||||
|
||||
The `PreviewButton` property allows you to render a custom Preview Button in the Edit View.
|
||||
|
||||
To add a `PreviewButton` component, use the `components.edit.PreviewButton` property in your [Collection Config](../configuration/collections) or `components.elements.PreviewButton` in your [Global Config](../configuration/globals):
|
||||
|
||||
```ts
|
||||
import type { CollectionConfig } from 'payload'
|
||||
|
||||
export const MyCollection: CollectionConfig = {
|
||||
// ...
|
||||
admin: {
|
||||
components: {
|
||||
edit: {
|
||||
// highlight-start
|
||||
PreviewButton: '/path/to/MyPreviewButton',
|
||||
// highlight-end
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
Here's an example of a custom `PreviewButton` component:
|
||||
|
||||
#### Server Component
|
||||
|
||||
```tsx
|
||||
import React from 'react'
|
||||
import { PreviewButton } from '@payloadcms/ui'
|
||||
import type { PreviewButtonServerProps } from 'payload'
|
||||
|
||||
export function MyPreviewButton(props: PreviewButtonServerProps) {
|
||||
return (
|
||||
<PreviewButton />
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
#### Client Component
|
||||
|
||||
```tsx
|
||||
'use client'
|
||||
import React from 'react'
|
||||
import { PreviewButton } from '@payloadcms/ui'
|
||||
import type { PreviewButtonClientProps } from 'payload'
|
||||
|
||||
export function MyPreviewButton(props: PreviewButtonClientProps) {
|
||||
return (
|
||||
<PreviewButton />
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### Description
|
||||
|
||||
The `Description` property allows you to render a custom description of the Collection or Global in the Edit View.
|
||||
|
||||
To add a `Description` component, use the `components.edit.Description` property in your [Collection Config](../configuration/collections) or `components.elements.Description` in your [Global Config](../configuration/globals):
|
||||
|
||||
```ts
|
||||
import type { CollectionConfig } from 'payload'
|
||||
|
||||
export const MyCollection: CollectionConfig = {
|
||||
// ...
|
||||
admin: {
|
||||
components: {
|
||||
// highlight-start
|
||||
Description: '/path/to/MyDescriptionComponent',
|
||||
// highlight-end
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
<Banner type="warning">
|
||||
**Note:**
|
||||
The `Description` component is shared between the Edit View and the [List View](./list-view).
|
||||
</Banner>
|
||||
|
||||
Here's an example of a custom `Description` component:
|
||||
|
||||
#### Server Component
|
||||
|
||||
```tsx
|
||||
import React from 'react'
|
||||
import type { ViewDescriptionServerProps } from 'payload'
|
||||
|
||||
export function MyDescriptionComponent(props: ViewDescriptionServerProps) {
|
||||
return (
|
||||
<div>
|
||||
This is a custom description component (Server)
|
||||
</div>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
#### Client Component
|
||||
|
||||
```tsx
|
||||
'use client'
|
||||
import React from 'react'
|
||||
import type { ViewDescriptionClientProps } from 'payload'
|
||||
|
||||
export function MyDescriptionComponent(props: ViewDescriptionClientProps) {
|
||||
return (
|
||||
<div>
|
||||
This is a custom description component (Client)
|
||||
</div>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### Upload
|
||||
|
||||
The `Upload` property allows you to render a custom file upload component in the Edit View.
|
||||
|
||||
To add an `Upload` component, use the `components.edit.Upload` property in your [Collection Config](../configuration/collections):
|
||||
|
||||
```ts
|
||||
import type { CollectionConfig } from 'payload'
|
||||
|
||||
export const MyCollection: CollectionConfig = {
|
||||
// ...
|
||||
admin: {
|
||||
components: {
|
||||
edit: {
|
||||
// highlight-start
|
||||
Upload: '/path/to/MyUploadComponent',
|
||||
// highlight-end
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
<Banner type="warning">
|
||||
**Note:**
|
||||
The Upload component is only available for Collections.
|
||||
</Banner>
|
||||
|
||||
Here's an example of a custom `Upload` component:
|
||||
|
||||
```tsx
|
||||
import React from 'react'
|
||||
|
||||
export function MyUploadComponent() {
|
||||
return (
|
||||
<input type="file" />
|
||||
)
|
||||
}
|
||||
```
|
||||
@@ -1,387 +0,0 @@
|
||||
---
|
||||
title: List View
|
||||
label: List View
|
||||
order: 70
|
||||
desc:
|
||||
keywords: admin, components, custom, documentation, Content Management System, cms, headless, javascript, node, react, nextjs
|
||||
---
|
||||
|
||||
The List View is where users interact with a list of [Collection](../collections/overview) Documents within the [Admin Panel](../admin/overview). This is where they can view, sort, filter, and paginate their documents to find exactly what they're looking for. This is also where users can perform bulk operations on multiple documents at once, such as deleting, editing, or publishing many.
|
||||
|
||||
The List View can be swapped out in its entirety for a Custom View, or it can be injected with a number of Custom Components to add additional functionality or presentational elements without replacing the entire view.
|
||||
|
||||
<Banner type="info">
|
||||
**Note:**
|
||||
Only [Collections](../collections/overview) have a List View. [Globals](../globals/overview) do not have a List View as they are single documents.
|
||||
</Banner>
|
||||
|
||||
## Custom List View
|
||||
|
||||
To swap out the entire List View with a [Custom View](./custom-views), use the `admin.components.views.list` property in your [Payload Config](../configuration/overview):
|
||||
|
||||
```tsx
|
||||
import { buildConfig } from 'payload'
|
||||
|
||||
const config = buildConfig({
|
||||
// ...
|
||||
admin: {
|
||||
components: {
|
||||
views: {
|
||||
// highlight-start
|
||||
list: '/path/to/MyCustomListView',
|
||||
// highlight-end
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
Here is an example of a custom List View:
|
||||
|
||||
#### Server Component
|
||||
|
||||
```tsx
|
||||
import React from 'react'
|
||||
import type { ListViewServerProps } from 'payload'
|
||||
import { DefaultListView } from '@payloadcms/ui'
|
||||
|
||||
export function MyCustomServerListView(props: ListViewServerProps) {
|
||||
return (
|
||||
<div>
|
||||
This is a custom List View (Server)
|
||||
</div>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
#### Client Component
|
||||
|
||||
```tsx
|
||||
'use client'
|
||||
import React from 'react'
|
||||
import type { ListViewClientProps } from 'payload'
|
||||
|
||||
export function MyCustomClientListView(props: ListViewClientProps) {
|
||||
return (
|
||||
<div>
|
||||
This is a custom List View (Client)
|
||||
</div>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
_For details on how to build Custom Views, including all available props, see [Building Custom Views](./custom-views#building-custom-views)._
|
||||
|
||||
## Custom Components
|
||||
|
||||
In addition to swapping out the entire List View with a [Custom View](./custom-views), you can also override individual components. This allows you to customize specific parts of the List View without swapping out the entire view for your own.
|
||||
|
||||
To override List View components for a Collection, use the `admin.components` property in your [Collection Config](../configuration/collections):
|
||||
|
||||
```ts
|
||||
import type { CollectionConfig } from 'payload'
|
||||
|
||||
export const MyCollection: CollectionConfig = {
|
||||
// ...
|
||||
admin: {
|
||||
// highlight-start
|
||||
components: {
|
||||
// ...
|
||||
},
|
||||
// highlight-end
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
The following options are available:
|
||||
|
||||
| Path | Description |
|
||||
|-----------------------|----------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `beforeList` | An array of custom components to inject before the list of documents in the List View. [More details](#beforeList). |
|
||||
| `beforeListTable` | An array of custom components to inject before the table of documents in the List View. [More details](#beforeListTable). |
|
||||
| `afterList` | An array of custom components to inject after the list of documents in the List View. [More details](#afterList). |
|
||||
| `afterListTable` | An array of custom components to inject after the table of documents in the List View. [More details](#afterListTable). |
|
||||
| `Description` | A component to render a description of the Collection. [More details](#Description). |
|
||||
|
||||
### beforeList
|
||||
|
||||
The `beforeList` property allows you to inject custom components before the list of documents in the List View.
|
||||
|
||||
To add `beforeList` components, use the `components.beforeList` property in your [Collection Config](../configuration/collections):
|
||||
|
||||
```ts
|
||||
import type { CollectionConfig } from 'payload'
|
||||
|
||||
export const MyCollection: CollectionConfig = {
|
||||
// ...
|
||||
admin: {
|
||||
components: {
|
||||
// highlight-start
|
||||
beforeList: [
|
||||
'/path/to/MyBeforeListComponent',
|
||||
],
|
||||
// highlight-end
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
Here's an example of a custom `beforeList` component:
|
||||
|
||||
#### Server Component
|
||||
|
||||
```tsx
|
||||
import React from 'react'
|
||||
import type { BeforeListServerProps } from 'payload'
|
||||
|
||||
export function MyBeforeListComponent(props: BeforeListServerProps) {
|
||||
return (
|
||||
<div>
|
||||
This is a custom beforeList component (Server)
|
||||
</div>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
#### Client Component
|
||||
|
||||
```tsx
|
||||
'use client'
|
||||
import React from 'react'
|
||||
import type { BeforeListClientProps } from 'payload'
|
||||
|
||||
export function MyBeforeListComponent(props: BeforeListClientProps) {
|
||||
return (
|
||||
<div>
|
||||
This is a custom beforeList component (Client)
|
||||
</div>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### beforeListTable
|
||||
|
||||
The `beforeListTable` property allows you to inject custom components before the table of documents in the List View.
|
||||
|
||||
To add `beforeListTable` components, use the `components.beforeListTable` property in your [Collection Config](../configuration/collections):
|
||||
|
||||
```ts
|
||||
import type { CollectionConfig } from 'payload'
|
||||
|
||||
export const MyCollection: CollectionConfig = {
|
||||
// ...
|
||||
admin: {
|
||||
components: {
|
||||
// highlight-start
|
||||
beforeListTable: [
|
||||
'/path/to/MyBeforeListTableComponent',
|
||||
],
|
||||
// highlight-end
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
Here's an example of a custom `beforeListTable` component:
|
||||
|
||||
#### Server Component
|
||||
|
||||
```tsx
|
||||
import React from 'react'
|
||||
import type { BeforeListTableServerProps } from 'payload'
|
||||
|
||||
export function MyBeforeListTableComponent(props: BeforeListTableServerProps) {
|
||||
return (
|
||||
<div>
|
||||
This is a custom beforeListTable component (Server)
|
||||
</div>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
#### Client Component
|
||||
|
||||
```tsx
|
||||
'use client'
|
||||
import React from 'react'
|
||||
import type { BeforeListTableClientProps } from 'payload'
|
||||
|
||||
export function MyBeforeListTableComponent(props: BeforeListTableClientProps) {
|
||||
return (
|
||||
<div>
|
||||
This is a custom beforeListTable component (Client)
|
||||
</div>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### afterList
|
||||
|
||||
The `afterList` property allows you to inject custom components after the list of documents in the List View.
|
||||
|
||||
To add `afterList` components, use the `components.afterList` property in your [Collection Config](../configuration/collections):
|
||||
|
||||
```ts
|
||||
import type { CollectionConfig } from 'payload'
|
||||
|
||||
export const MyCollection: CollectionConfig = {
|
||||
// ...
|
||||
admin: {
|
||||
components: {
|
||||
// highlight-start
|
||||
afterList: [
|
||||
'/path/to/MyAfterListComponent',
|
||||
],
|
||||
// highlight-end
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
Here's an example of a custom `afterList` component:
|
||||
|
||||
#### Server Component
|
||||
|
||||
```tsx
|
||||
import React from 'react'
|
||||
import type { AfterListServerProps } from 'payload'
|
||||
|
||||
export function MyAfterListComponent(props: AfterListServerProps) {
|
||||
return (
|
||||
<div>
|
||||
This is a custom afterList component (Server)
|
||||
</div>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
#### Client Component
|
||||
|
||||
```tsx
|
||||
'use client'
|
||||
import React from 'react'
|
||||
import type { AfterListClientProps } from 'payload'
|
||||
|
||||
export function MyAfterListComponent(props: AfterListClientProps) {
|
||||
return (
|
||||
<div>
|
||||
This is a custom afterList component (Client)
|
||||
</div>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### afterListTable
|
||||
|
||||
The `afterListTable` property allows you to inject custom components after the table of documents in the List View.
|
||||
|
||||
To add `afterListTable` components, use the `components.afterListTable` property in your [Collection Config](../configuration/collections):
|
||||
|
||||
```ts
|
||||
import type { CollectionConfig } from 'payload'
|
||||
|
||||
export const MyCollection: CollectionConfig = {
|
||||
// ...
|
||||
admin: {
|
||||
components: {
|
||||
// highlight-start
|
||||
afterListTable: [
|
||||
'/path/to/MyAfterListTableComponent',
|
||||
],
|
||||
// highlight-end
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
Here's an example of a custom `afterListTable` component:
|
||||
|
||||
#### Server Component
|
||||
|
||||
```tsx
|
||||
import React from 'react'
|
||||
import type { AfterListTableServerProps } from 'payload'
|
||||
|
||||
export function MyAfterListTableComponent(props: AfterListTableServerProps) {
|
||||
return (
|
||||
<div>
|
||||
This is a custom afterListTable component (Server)
|
||||
</div>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
#### Client Component
|
||||
|
||||
```tsx
|
||||
'use client'
|
||||
import React from 'react'
|
||||
import type { AfterListTableClientProps } from 'payload'
|
||||
|
||||
export function MyAfterListTableComponent(props: AfterListTableClientProps) {
|
||||
return (
|
||||
<div>
|
||||
This is a custom afterListTable component (Client)
|
||||
</div>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### Description
|
||||
|
||||
The `Description` property allows you to render a custom description of the Collection in the List View.
|
||||
|
||||
To add a `Description` component, use the `components.Description` property in your [Collection Config](../configuration/collections):
|
||||
|
||||
```ts
|
||||
import type { CollectionConfig } from 'payload'
|
||||
|
||||
export const MyCollection: CollectionConfig = {
|
||||
// ...
|
||||
admin: {
|
||||
components: {
|
||||
// highlight-start
|
||||
Description: '/path/to/MyDescriptionComponent',
|
||||
// highlight-end
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
<Banner type="warning">
|
||||
**Note:**
|
||||
The `Description` component is shared between the List View and the [Edit View](./edit-view).
|
||||
</Banner>
|
||||
|
||||
Here's an example of a custom `Description` component:
|
||||
|
||||
#### Server Component
|
||||
|
||||
```tsx
|
||||
import React from 'react'
|
||||
import type { ViewDescriptionServerProps } from 'payload'
|
||||
|
||||
export function MyDescriptionComponent(props: ViewDescriptionServerProps) {
|
||||
return (
|
||||
<div>
|
||||
This is a custom Collection description component (Server)
|
||||
</div>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
#### Client Component
|
||||
|
||||
```tsx
|
||||
'use client'
|
||||
import React from 'react'
|
||||
import type { ViewDescriptionClientProps } from 'payload'
|
||||
|
||||
export function MyDescriptionComponent(props: ViewDescriptionClientProps) {
|
||||
return (
|
||||
<div>
|
||||
This is a custom Collection description component (Client)
|
||||
</div>
|
||||
)
|
||||
}
|
||||
```
|
||||
@@ -1,485 +0,0 @@
|
||||
---
|
||||
title: Root Components
|
||||
label: Root Components
|
||||
order: 20
|
||||
desc:
|
||||
keywords: admin, components, custom, documentation, Content Management System, cms, headless, javascript, node, react, nextjs
|
||||
---
|
||||
|
||||
Root Components are those that affect the [Admin Panel](../admin/overview) at a high-level, such as the logo or the main nav. You can swap out these components with your own [Custom Components](./overview) to create a completely custom look and feel.
|
||||
|
||||
When combined with [Custom CSS](../admin/customizing-css), you can create a truly unique experience for your users, such as white-labeling the Admin Panel to match your brand.
|
||||
|
||||
To override Root Components, use the `admin.components` property at the root of your [Payload Config](../configuration/overview):
|
||||
|
||||
```ts
|
||||
import { buildConfig } from 'payload'
|
||||
|
||||
export default buildConfig({
|
||||
// ...
|
||||
admin: {
|
||||
// highlight-start
|
||||
components: {
|
||||
// ...
|
||||
},
|
||||
// highlight-end
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
## Config Options
|
||||
|
||||
The following options are available:
|
||||
|
||||
| Path | Description |
|
||||
|-----------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `actions` | An array of Custom Components to be rendered _within_ the header of the Admin Panel, providing additional interactivity and functionality. [More details](#actions). |
|
||||
| `afterDashboard` | An array of Custom Components to inject into the built-in Dashboard, _after_ the default dashboard contents. [More details](#afterdashboard). |
|
||||
| `afterLogin` | An array of Custom Components to inject into the built-in Login, _after_ the default login form. [More details](#afterlogin). |
|
||||
| `afterNavLinks` | An array of Custom Components to inject into the built-in Nav, _after_ the links. [More details](#afternavlinks). |
|
||||
| `beforeDashboard` | An array of Custom Components to inject into the built-in Dashboard, _before_ the default dashboard contents. [More details](#beforedashboard). |
|
||||
| `beforeLogin` | An array of Custom Components to inject into the built-in Login, _before_ the default login form. [More details](#beforelogin). |
|
||||
| `beforeNavLinks` | An array of Custom Components to inject into the built-in Nav, _before_ the links themselves. [More details](#beforenavlinks). |
|
||||
| `graphics.Icon` | The simplified logo used in contexts like the the `Nav` component. [More details](#graphicsicon). |
|
||||
| `graphics.Logo` | The full logo used in contexts like the `Login` view. [More details](#graphicslogo). |
|
||||
| `header` | An array of Custom Components to be injected above the Payload header. [More details](#header). |
|
||||
| `logout.Button` | The button displayed in the sidebar that logs the user out. [More details](#logoutbutton). |
|
||||
| `Nav` | Contains the sidebar / mobile menu in its entirety. [More details](#nav). |
|
||||
| `providers` | Custom [React Context](https://react.dev/learn/scaling-up-with-reducer-and-context) providers that will wrap the entire Admin Panel. [More details](./custom-providers). |
|
||||
| `views` | Override or create new views within the Admin Panel. [More details](./custom-views). |
|
||||
|
||||
_For details on how to build Custom Components, see [Building Custom Components](./overview#building-custom-components)._
|
||||
|
||||
<Banner type="success">
|
||||
**Note:**
|
||||
You can also use set [Collection Components](../configuration/collections#custom-components) and [Global Components](../configuration/globals#custom-components) in their respective configs.
|
||||
</Banner>
|
||||
|
||||
## Components
|
||||
|
||||
### actions
|
||||
|
||||
Actions are rendered within the header of the Admin Panel. Actions are typically used to display buttons that add additional interactivity and functionality, although they can be anything you'd like.
|
||||
|
||||
To add an action, use the `actions` property in your `admin.components` config:
|
||||
|
||||
```ts
|
||||
import { buildConfig } from 'payload'
|
||||
|
||||
export default buildConfig({
|
||||
// ...
|
||||
admin: {
|
||||
// highlight-start
|
||||
components: {
|
||||
actions: [
|
||||
'/path/to/your/component',
|
||||
],
|
||||
},
|
||||
// highlight-end
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
Here is an example of a simple Action component:
|
||||
|
||||
```tsx
|
||||
export default function MyCustomAction() {
|
||||
return (
|
||||
<button onClick={() => alert('Hello, world!')}>
|
||||
This is a custom action component
|
||||
</button>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
<Banner type="success">
|
||||
**Note:**
|
||||
You can also use add Actions to the [Edit View](./edit-view) and [List View](./list-view) in their respective configs.
|
||||
</Banner>
|
||||
|
||||
### beforeDashboard
|
||||
|
||||
The `beforeDashboard` property allows you to inject Custom Components into the built-in Dashboard, before the default dashboard contents.
|
||||
|
||||
To add `beforeDashboard` components, use the `admin.components.beforeDashboard` property in your Payload Config:
|
||||
|
||||
```ts
|
||||
import { buildConfig } from 'payload'
|
||||
|
||||
export default buildConfig({
|
||||
// ...
|
||||
admin: {
|
||||
// highlight-start
|
||||
components: {
|
||||
beforeDashboard: [
|
||||
'/path/to/your/component',
|
||||
],
|
||||
},
|
||||
// highlight-end
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
Here is an example of a simple `beforeDashboard` component:
|
||||
|
||||
```tsx
|
||||
export default function MyBeforeDashboardComponent() {
|
||||
return (
|
||||
<div>
|
||||
This is a custom component injected before the Dashboard.
|
||||
</div>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### afterDashboard
|
||||
|
||||
Similar to `beforeDashboard`, the `afterDashboard` property allows you to inject Custom Components into the built-in Dashboard, _after_ the default dashboard contents.
|
||||
|
||||
To add `afterDashboard` components, use the `admin.components.afterDashboard` property in your Payload Config:
|
||||
|
||||
```ts
|
||||
import { buildConfig } from 'payload'
|
||||
|
||||
export default buildConfig({
|
||||
// ...
|
||||
admin: {
|
||||
// highlight-start
|
||||
components: {
|
||||
afterDashboard: [
|
||||
'/path/to/your/component',
|
||||
],
|
||||
},
|
||||
// highlight-end
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
Here is an example of a simple `afterDashboard` component:
|
||||
|
||||
```tsx
|
||||
export default function MyAfterDashboardComponent() {
|
||||
return (
|
||||
<div>
|
||||
This is a custom component injected after the Dashboard.
|
||||
</div>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### beforeLogin
|
||||
|
||||
The `beforeLogin` property allows you to inject Custom Components into the built-in Login view, _before_ the default login form.
|
||||
|
||||
To add `beforeLogin` components, use the `admin.components.beforeLogin` property in your Payload Config:
|
||||
|
||||
```ts
|
||||
import { buildConfig } from 'payload'
|
||||
|
||||
export default buildConfig({
|
||||
// ...
|
||||
admin: {
|
||||
// highlight-start
|
||||
components: {
|
||||
beforeLogin: [
|
||||
'/path/to/your/component',
|
||||
],
|
||||
},
|
||||
// highlight-end
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
Here is an example of a simple `beforeLogin` component:
|
||||
|
||||
```tsx
|
||||
export default function MyBeforeLoginComponent() {
|
||||
return (
|
||||
<div>
|
||||
This is a custom component injected before the Login form.
|
||||
</div>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### afterLogin
|
||||
|
||||
Similar to `beforeLogin`, the `afterLogin` property allows you to inject Custom Components into the built-in Login view, _after_ the default login form.
|
||||
|
||||
To add `afterLogin` components, use the `admin.components.afterLogin` property in your Payload Config:
|
||||
|
||||
```ts
|
||||
import { buildConfig } from 'payload'
|
||||
|
||||
export default buildConfig({
|
||||
// ...
|
||||
admin: {
|
||||
// highlight-start
|
||||
components: {
|
||||
afterLogin: [
|
||||
'/path/to/your/component',
|
||||
],
|
||||
},
|
||||
// highlight-end
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
Here is an example of a simple `afterLogin` component:
|
||||
|
||||
```tsx
|
||||
export default function MyAfterLoginComponent() {
|
||||
return (
|
||||
<div>
|
||||
This is a custom component injected after the Login form.
|
||||
</div>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### beforeNavLinks
|
||||
|
||||
The `beforeNavLinks` property allows you to inject Custom Components into the built-in [Nav Component](#nav), _before_ the nav links themselves.
|
||||
|
||||
To add `beforeNavLinks` components, use the `admin.components.beforeNavLinks` property in your Payload Config:
|
||||
|
||||
```ts
|
||||
import { buildConfig } from 'payload'
|
||||
|
||||
export default buildConfig({
|
||||
// ...
|
||||
admin: {
|
||||
// highlight-start
|
||||
components: {
|
||||
beforeNavLinks: [
|
||||
'/path/to/your/component',
|
||||
],
|
||||
},
|
||||
// highlight-end
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
Here is an example of a simple `beforeNavLinks` component:
|
||||
|
||||
```tsx
|
||||
export default function MyBeforeNavLinksComponent() {
|
||||
return (
|
||||
<div>
|
||||
This is a custom component injected before the Nav links.
|
||||
</div>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### afterNavLinks
|
||||
|
||||
Similar to `beforeNavLinks`, the `afterNavLinks` property allows you to inject Custom Components into the built-in Nav, _after_ the nav links.
|
||||
|
||||
To add `afterNavLinks` components, use the `admin.components.afterNavLinks` property in your Payload Config:
|
||||
|
||||
```ts
|
||||
import { buildConfig } from 'payload'
|
||||
|
||||
export default buildConfig({
|
||||
// ...
|
||||
admin: {
|
||||
// highlight-start
|
||||
components: {
|
||||
afterNavLinks: [
|
||||
'/path/to/your/component',
|
||||
],
|
||||
},
|
||||
// highlight-end
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
Here is an example of a simple `afterNavLinks` component:
|
||||
|
||||
```tsx
|
||||
export default function MyAfterNavLinksComponent() {
|
||||
return (
|
||||
<p>This is a custom component injected after the Nav links.</p>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### Nav
|
||||
|
||||
The `Nav` property contains the sidebar / mobile menu in its entirety. Use this property to completely replace the built-in Nav with your own custom navigation.
|
||||
|
||||
To add a custom nav, use the `admin.components.Nav` property in your Payload Config:
|
||||
|
||||
```ts
|
||||
import { buildConfig } from 'payload'
|
||||
|
||||
export default buildConfig({
|
||||
// ...
|
||||
admin: {
|
||||
// highlight-start
|
||||
components: {
|
||||
Nav: '/path/to/your/component',
|
||||
},
|
||||
// highlight-end
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
Here is an example of a simple `Nav` component:
|
||||
|
||||
```tsx
|
||||
import { Link } from '@payloadcms/ui'
|
||||
|
||||
export default function MyCustomNav() {
|
||||
return (
|
||||
<nav>
|
||||
<ul>
|
||||
<li>
|
||||
<Link href="/dashboard">
|
||||
Dashboard
|
||||
</Link>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### graphics.Icon
|
||||
|
||||
The `Icon` property is the simplified logo used in contexts like the `Nav` component. This is typically a small, square icon that represents your brand.
|
||||
|
||||
To add a custom icon, use the `admin.components.graphics.Icon` property in your Payload Config:
|
||||
|
||||
```ts
|
||||
import { buildConfig } from 'payload'
|
||||
|
||||
export default buildConfig({
|
||||
// ...
|
||||
admin: {
|
||||
// highlight-start
|
||||
components: {
|
||||
graphics: {
|
||||
Icon: '/path/to/your/component',
|
||||
},
|
||||
},
|
||||
// highlight-end
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
Here is an example of a simple `Icon` component:
|
||||
|
||||
```tsx
|
||||
export default function MyCustomIcon() {
|
||||
return (
|
||||
<img src="/path/to/your/icon.png" alt="My Custom Icon" />
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### graphics.Logo
|
||||
|
||||
The `Logo` property is the full logo used in contexts like the `Login` view. This is typically a larger, more detailed representation of your brand.
|
||||
|
||||
To add a custom logo, use the `admin.components.graphic.Logo` property in your Payload Config:
|
||||
|
||||
```ts
|
||||
import { buildConfig } from 'payload'
|
||||
|
||||
export default buildConfig({
|
||||
// ...
|
||||
admin: {
|
||||
// highlight-start
|
||||
components: {
|
||||
graphics: {
|
||||
Logo: '/path/to/your/component',
|
||||
},
|
||||
},
|
||||
// highlight-end
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
Here is an example of a simple `Logo` component:
|
||||
|
||||
```tsx
|
||||
export default function MyCustomLogo() {
|
||||
return (
|
||||
<img src="/path/to/your/logo.png" alt="My Custom Logo" />
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### Header
|
||||
|
||||
The `Header` property allows you to inject Custom Components above the Payload header.
|
||||
|
||||
Examples of a custom header components might include an announcements banner, a notifications bar, or anything else you'd like to display at the top of the Admin Panel in a prominent location.
|
||||
|
||||
To add `Header` components, use the `admin.components.header` property in your Payload Config:
|
||||
|
||||
```ts
|
||||
import { buildConfig } from 'payload'
|
||||
|
||||
export default buildConfig({
|
||||
// ...
|
||||
admin: {
|
||||
// highlight-start
|
||||
components: {
|
||||
Header: [
|
||||
'/path/to/your/component'
|
||||
],
|
||||
},
|
||||
// highlight-end
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
Here is an example of a simple `Header` component:
|
||||
|
||||
```tsx
|
||||
export default function MyCustomHeader() {
|
||||
return (
|
||||
<header>
|
||||
<h1>My Custom Header</h1>
|
||||
</header>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### logout.Button
|
||||
|
||||
The `logout.Button` property is the button displayed in the sidebar that should log the user out when clicked.
|
||||
|
||||
To add a custom logout button, use the `admin.components.logout.Button` property in your Payload Config:
|
||||
|
||||
```ts
|
||||
import { buildConfig } from 'payload'
|
||||
|
||||
export default buildConfig({
|
||||
// ...
|
||||
admin: {
|
||||
// highlight-start
|
||||
components: {
|
||||
logout: {
|
||||
Button: '/path/to/your/component',
|
||||
}
|
||||
},
|
||||
// highlight-end
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
Here is an example of a simple `logout.Button` component:
|
||||
|
||||
```tsx
|
||||
export default function MyCustomLogoutButton() {
|
||||
return (
|
||||
<button onClick={() => alert('Logging out!')}>
|
||||
Log Out
|
||||
</button>
|
||||
)
|
||||
}
|
||||
```
|
||||
@@ -104,7 +104,7 @@ Here are the available Virtual Fields:
|
||||
- [Join](../fields/join) - achieves two-way data binding between fields
|
||||
|
||||
<Banner type="success">
|
||||
**Tip:** Don't see a built-in field type that you need? Build it! Using a combination of [Field Validations](#validation) and [Custom Components](../custom-components/overview), you can override the entirety of how a component functions within the [Admin Panel](../admin/overview) to effectively create your own field type.
|
||||
**Tip:** Don't see a built-in field type that you need? Build it! Using a combination of [Field Validations](#validation) and [Custom Components](../admin/components), you can override the entirety of how a component functions within the [Admin Panel](../admin/overview) to effectively create your own field type.
|
||||
</Banner>
|
||||
|
||||
## Field Options
|
||||
@@ -429,7 +429,7 @@ The following options are available:
|
||||
| Option | Description |
|
||||
| --- | --- |
|
||||
| **`condition`** | Programmatically show / hide fields based on other fields. [More details](#conditional-logic). |
|
||||
| **`components`** | All Field Components can be swapped out for [Custom Components](../custom-components/overview) that you define. |
|
||||
| **`components`** | All Field Components can be swapped out for [Custom Components](../admin/components) that you define. |
|
||||
| **`description`** | Helper text to display alongside the field to provide more information for the editor. [More details](#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. |
|
||||
@@ -455,9 +455,9 @@ A description can be configured in three ways:
|
||||
To add a Custom Description to a field, use the `admin.description` property in your Field Config:
|
||||
|
||||
```ts
|
||||
import type { CollectionConfig } from 'payload'
|
||||
import type { SanitizedCollectionConfig } from 'payload'
|
||||
|
||||
export const MyCollectionConfig: CollectionConfig = {
|
||||
export const MyCollectionConfig: SanitizedCollectionConfig = {
|
||||
// ...
|
||||
fields: [
|
||||
// ...
|
||||
@@ -473,7 +473,7 @@ export const MyCollectionConfig: CollectionConfig = {
|
||||
```
|
||||
|
||||
<Banner type="warning">
|
||||
**Reminder:** To replace the Field Description with a [Custom Component](../custom-components/overview), use the `admin.components.Description` property. [More details](#description).
|
||||
**Reminder:** To replace the Field Description with a [Custom Component](../admin/components), use the `admin.components.Description` property. [More details](#description).
|
||||
</Banner>
|
||||
|
||||
#### Description Functions
|
||||
@@ -483,9 +483,9 @@ Custom Descriptions can also be defined as a function. Description Functions are
|
||||
To add a Description Function to a field, set the `admin.description` property to a *function* in your Field Config:
|
||||
|
||||
```ts
|
||||
import type { CollectionConfig } from 'payload'
|
||||
import type { SanitizedCollectionConfig } from 'payload'
|
||||
|
||||
export const MyCollectionConfig: CollectionConfig = {
|
||||
export const MyCollectionConfig: SanitizedCollectionConfig = {
|
||||
// ...
|
||||
fields: [
|
||||
// ...
|
||||
@@ -618,7 +618,7 @@ export const CollectionConfig: CollectionConfig = {
|
||||
}
|
||||
```
|
||||
|
||||
*For details on how to build Custom Components, see [Building Custom Components](../custom-components/overview#building-custom-components).*
|
||||
*For details on how to build Custom Components, see [Building Custom Components](../admin/components#building-custom-components).*
|
||||
|
||||
<Banner type="warning">
|
||||
Instead of replacing the entire Field Component, you can alternately replace or slot-in only specific parts by using the [`Label`](#label), [`Error`](#error), [`beforeInput`](#afterinput-and-beforinput), and [`afterInput`](#afterinput-and-beforinput) properties.
|
||||
@@ -677,7 +677,7 @@ export const CustomTextField: React.FC = () => {
|
||||
```
|
||||
|
||||
<Banner type="success">
|
||||
For a complete list of all available React hooks, see the [Payload React Hooks](../admin/hooks) documentation. For additional help, see [Building Custom Components](../custom-components/overview#building-custom-components).
|
||||
For a complete list of all available React hooks, see the [Payload React Hooks](../admin/hooks) documentation. For additional help, see [Building Custom Components](../admin/components#building-custom-components).
|
||||
</Banner>
|
||||
|
||||
##### TypeScript#field-component-types
|
||||
@@ -723,7 +723,7 @@ All Cell Components receive the same [Default Field Component Props](#field), pl
|
||||
| **`link`** | A boolean representing whether this cell should be wrapped in a link. |
|
||||
| **`onClick`** | A function that is called when the cell is clicked. |
|
||||
|
||||
For details on how to build Custom Components themselves, see [Building Custom Components](../custom-components/overview#building-custom-components).
|
||||
For details on how to build Custom Components themselves, see [Building Custom Components](../admin/components#building-custom-components).
|
||||
|
||||
#### Filter
|
||||
|
||||
@@ -747,7 +747,7 @@ export const myField: Field = {
|
||||
|
||||
All Custom Filter Components receive the same [Default Field Component Props](#field).
|
||||
|
||||
For details on how to build Custom Components themselves, see [Building Custom Components](../custom-components/overview#building-custom-components).
|
||||
For details on how to build Custom Components themselves, see [Building Custom Components](../admin/components#building-custom-components).
|
||||
|
||||
#### Label
|
||||
|
||||
@@ -771,7 +771,7 @@ export const myField: Field = {
|
||||
|
||||
All Custom Label Components receive the same [Default Field Component Props](#field).
|
||||
|
||||
For details on how to build Custom Components themselves, see [Building Custom Components](../custom-components/overview#building-custom-components).
|
||||
For details on how to build Custom Components themselves, see [Building Custom Components](../admin/components#building-custom-components).
|
||||
|
||||
##### TypeScript#label-component-types
|
||||
|
||||
@@ -787,14 +787,14 @@ import type {
|
||||
|
||||
#### Description
|
||||
|
||||
Alternatively to the [Description Property](#field-descriptions), you can also use a [Custom Component](../custom-components/overview) as the Field Description. This can be useful when you need to provide more complex feedback to the user, such as rendering dynamic field values or other interactive elements.
|
||||
Alternatively to the [Description Property](#field-descriptions), you can also use a [Custom Component](../admin/components) as the Field Description. This can be useful when you need to provide more complex feedback to the user, such as rendering dynamic field values or other interactive elements.
|
||||
|
||||
To add a Description Component to a field, use the `admin.components.Description` property in your Field Config:
|
||||
|
||||
```ts
|
||||
import type { CollectionConfig } from 'payload'
|
||||
import type { SanitizedCollectionConfig } from 'payload'
|
||||
|
||||
export const MyCollectionConfig: CollectionConfig = {
|
||||
export const MyCollectionConfig: SanitizedCollectionConfig = {
|
||||
// ...
|
||||
fields: [
|
||||
// ...
|
||||
@@ -813,7 +813,7 @@ export const MyCollectionConfig: CollectionConfig = {
|
||||
|
||||
All Custom Description Components receive the same [Default Field Component Props](#field).
|
||||
|
||||
For details on how to build a Custom Components themselves, see [Building Custom Components](../custom-components/overview#building-custom-components).
|
||||
For details on how to build a Custom Components themselves, see [Building Custom Components](../admin/components#building-custom-components).
|
||||
|
||||
##### TypeScript#description-component-types
|
||||
|
||||
@@ -849,7 +849,7 @@ export const myField: Field = {
|
||||
|
||||
All Error Components receive the [Default Field Component Props](#field).
|
||||
|
||||
For details on how to build Custom Components themselves, see [Building Custom Components](../custom-components/overview#building-custom-components).
|
||||
For details on how to build Custom Components themselves, see [Building Custom Components](../admin/components#building-custom-components).
|
||||
|
||||
##### TypeScript#error-component-types
|
||||
|
||||
@@ -885,7 +885,7 @@ export const myField: Field = {
|
||||
|
||||
All Error Components receive the [Default Field Component Props](#field).
|
||||
|
||||
For details on how to build Custom Components themselves, see [Building Custom Components](../custom-components/overview#building-custom-components).
|
||||
For details on how to build Custom Components themselves, see [Building Custom Components](../admin/components#building-custom-components).
|
||||
|
||||
##### TypeScript#diff-component-types
|
||||
|
||||
@@ -906,9 +906,9 @@ With these properties you can add multiple components *before* and *after* the i
|
||||
To add components before and after the input element, use the `admin.components.beforeInput` and `admin.components.afterInput` properties in your Field Config:
|
||||
|
||||
```ts
|
||||
import type { CollectionConfig } from 'payload'
|
||||
import type { SanitizedCollectionConfig } from 'payload'
|
||||
|
||||
export const MyCollectionConfig: CollectionConfig = {
|
||||
export const MyCollectionConfig: SanitizedCollectionConfig = {
|
||||
// ...
|
||||
fields: [
|
||||
// ...
|
||||
@@ -930,7 +930,7 @@ export const MyCollectionConfig: CollectionConfig = {
|
||||
|
||||
All `afterInput` and `beforeInput` Components receive the same [Default Field Component Props](#field).
|
||||
|
||||
For details on how to build Custom Components, see [Building Custom Components](../custom-components/overview#building-custom-components).
|
||||
For details on how to build Custom Components, see [Building Custom Components](../admin/components#building-custom-components).
|
||||
|
||||
## TypeScript
|
||||
|
||||
@@ -938,4 +938,4 @@ You can import the Payload `Field` type as well as other common types from the `
|
||||
|
||||
```ts
|
||||
import type { Field } from 'payload'
|
||||
```
|
||||
```
|
||||
@@ -443,7 +443,7 @@ For more details, see the [Documentation](https://payloadcms.com/docs/getting-st
|
||||
})
|
||||
```
|
||||
|
||||
For more details, see the [Documentation](https://payloadcms.com/docs/custom-components/overview#component-paths).
|
||||
For more details, see the [Documentation](https://payloadcms.com/docs/admin/components#component-paths).
|
||||
|
||||
1. All Custom Components are now server-rendered by default, and therefore, cannot use state or hooks directly. If you’re using Custom Components in your app that requires state or hooks, add the `'use client'` directive at the top of the file.
|
||||
|
||||
@@ -463,7 +463,7 @@ For more details, see the [Documentation](https://payloadcms.com/docs/getting-st
|
||||
}
|
||||
```
|
||||
|
||||
For more details, see the [Documentation](https://payloadcms.com/docs/custom-components/overview#client-components).
|
||||
For more details, see the [Documentation](https://payloadcms.com/docs/admin/components#client-components).
|
||||
|
||||
1. The `admin.description` property within Collection, Globals, and Fields no longer accepts a React Component. Instead, you must define it as a Custom Component.
|
||||
|
||||
@@ -854,7 +854,7 @@ For more details, see the [Documentation](https://payloadcms.com/docs/getting-st
|
||||
}
|
||||
```
|
||||
|
||||
For more details, see the [Documentation](https://payloadcms.com/docs/admin/custom-components/overview#accessing-the-payload-config).
|
||||
For more details, see the [Documentation](https://payloadcms.com/docs/admin/components#accessing-the-payload-config).
|
||||
|
||||
1. The `useCollapsible` hook has had slight changes to its property names. `collapsed` is now `isCollapsed` and `withinCollapsible` is now `isWithinCollapsible`.
|
||||
|
||||
|
||||
@@ -409,7 +409,7 @@ Explore the APIs available through ClientFeature to add the specific functionali
|
||||
|
||||
### Adding a client feature to the server feature
|
||||
|
||||
Inside of your server feature, you can provide an [import path](/docs/admin/custom-components/overview#component-paths) to the client feature like this:
|
||||
Inside of your server feature, you can provide an [import path](/docs/admin/components#component-paths) to the client feature like this:
|
||||
|
||||
```ts
|
||||
import { createServerFeature } from '@payloadcms/richtext-lexical';
|
||||
|
||||
@@ -6,7 +6,7 @@ desc: Generate your own TypeScript interfaces based on your collections and glob
|
||||
keywords: headless cms, typescript, documentation, Content Management System, cms, headless, javascript, node, react, nextjs
|
||||
---
|
||||
|
||||
While building your own custom functionality into Payload, like [Plugins](../plugins/overview), [Hooks](../hooks/overview), [Access Control](../access-control/overview) functions, [Custom Views](../custom-components/custom-views), [GraphQL queries / mutations](../graphql/overview), or anything else, you may benefit from generating your own TypeScript types dynamically from your Payload Config itself.
|
||||
While building your own custom functionality into Payload, like [Plugins](../plugins/overview), [Hooks](../hooks/overview), [Access Control](../access-control/overview) functions, [Custom Views](../admin/views), [GraphQL queries / mutations](../graphql/overview), or anything else, you may benefit from generating your own TypeScript types dynamically from your Payload Config itself.
|
||||
|
||||
## Types generation script
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ It's also possible to set up a TypeScript project from scratch. We plan to write
|
||||
|
||||
## Using Payload's Exported Types
|
||||
|
||||
Payload exports a number of types that you may find useful while writing your own custom functionality like [Plugins](../plugins/overview), [Hooks](../hooks/overview), [Access Control](../access-control/overview) functions, [Custom Views](../custom-components/custom-views), [GraphQL queries / mutations](../graphql/overview) or anything else.
|
||||
Payload exports a number of types that you may find useful while writing your own custom functionality like [Plugins](../plugins/overview), [Hooks](../hooks/overview), [Access Control](../access-control/overview) functions, [Custom Views](../admin/views), [GraphQL queries / mutations](../graphql/overview) or anything else.
|
||||
|
||||
## Config Types
|
||||
|
||||
|
||||
@@ -88,29 +88,27 @@ export const Media: CollectionConfig = {
|
||||
|
||||
_An asterisk denotes that an option is required._
|
||||
|
||||
| Option | Description |
|
||||
|--------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| **`adminThumbnail`** | Set the way that the [Admin Panel](../admin/overview) will display thumbnails for this Collection. [More](#admin-thumbnails) |
|
||||
| **`bulkUpload`** | Allow users to upload in bulk from the list view, default is true |
|
||||
| **`cacheTags`** | Set to `false` to disable the cache tag set in the UI for the admin thumbnail component. Useful for when CDNs don't allow certain cache queries. |
|
||||
| **`crop`** | Set to `false` to disable the cropping tool in the [Admin Panel](../admin/overview). Crop is enabled by default. [More](#crop-and-focal-point-selector) |
|
||||
| **`disableLocalStorage`** | Completely disable uploading files to disk locally. [More](#disabling-local-upload-storage) |
|
||||
| **`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. |
|
||||
| **`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. |
|
||||
| **`imageSizes`** | If specified, image uploads will be automatically resized in accordance to these image sizes. [More](#image-sizes) |
|
||||
| **`mimeTypes`** | Restrict mimeTypes in the file picker. Array of valid mimetypes or mimetype wildcards [More](#mimetypes) |
|
||||
| Option | Description |
|
||||
| ------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| **`adminThumbnail`** | Set the way that the [Admin Panel](../admin/overview) will display thumbnails for this Collection. [More](#admin-thumbnails) |
|
||||
| **`bulkUpload`** | Allow users to upload in bulk from the list view, default is true |
|
||||
| **`cacheTags`** | Set to `false` to disable the cache tag set in the UI for the admin thumbnail component. Useful for when CDNs don't allow certain cache queries. |
|
||||
| **`crop`** | Set to `false` to disable the cropping tool in the [Admin Panel](../admin/overview). Crop is enabled by default. [More](#crop-and-focal-point-selector) |
|
||||
| **`disableLocalStorage`** | Completely disable uploading files to disk locally. [More](#disabling-local-upload-storage) |
|
||||
| **`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. |
|
||||
| **`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. |
|
||||
| **`imageSizes`** | If specified, image uploads will be automatically resized in accordance to these image sizes. [More](#image-sizes) |
|
||||
| **`mimeTypes`** | Restrict mimeTypes in the file picker. Array of valid mimetypes or mimetype wildcards [More](#mimetypes) |
|
||||
| **`pasteURL`** | Controls whether files can be uploaded from remote URLs by pasting them into the Upload field. **Enabled by default.** Accepts `false` to disable or an object with an `allowList` of valid remote URLs. [More](#uploading-files-from-remote-urls) |
|
||||
| **`resizeOptions`** | An object passed to the the Sharp image library to resize the uploaded file. [More](https://sharp.pixelplumbing.com/api-resize) |
|
||||
| **`staticDir`** | The folder directory to use to store media in. Can be either an absolute path or relative to the directory that contains your config. Defaults to your collection slug |
|
||||
| **`trimOptions`** | An object passed to the the Sharp image library to trim the uploaded file. [More](https://sharp.pixelplumbing.com/api-resize#trim) |
|
||||
| **`withMetadata`** | If specified, appends metadata to the output image file. Accepts a boolean or a function that receives `metadata` and `req`, returning a boolean. |
|
||||
| **`hideFileInputOnCreate`** | Set to `true` to prevent the admin UI from showing file inputs during document creation, useful for programmatic file generation. |
|
||||
| **`hideRemoveFile`** | Set to `true` to prevent the admin UI having a way to remove an existing file while editing. |
|
||||
| **`resizeOptions`** | An object passed to the the Sharp image library to resize the uploaded file. [More](https://sharp.pixelplumbing.com/api-resize) |
|
||||
| **`staticDir`** | The folder directory to use to store media in. Can be either an absolute path or relative to the directory that contains your config. Defaults to your collection slug |
|
||||
| **`trimOptions`** | An object passed to the the Sharp image library to trim the uploaded file. [More](https://sharp.pixelplumbing.com/api-resize#trim) |
|
||||
| **`withMetadata`** | If specified, appends metadata to the output image file. Accepts a boolean or a function that receives `metadata` and `req`, returning a boolean. |
|
||||
|
||||
|
||||
### Payload-wide Upload Options
|
||||
|
||||
@@ -13,7 +13,7 @@ export interface Props {
|
||||
onLoad?: () => void
|
||||
priority?: boolean // for NextImage only
|
||||
ref?: Ref<HTMLImageElement | HTMLVideoElement | null>
|
||||
resource?: MediaType | string | number | null // for Payload media
|
||||
resource?: MediaType | string | number // for Payload media
|
||||
size?: string // for NextImage only
|
||||
src?: StaticImageData // for static media
|
||||
videoClassName?: string
|
||||
|
||||
@@ -33,7 +33,6 @@
|
||||
"build:payload-cloud": "turbo build --filter \"@payloadcms/payload-cloud\"",
|
||||
"build:plugin-cloud-storage": "turbo build --filter \"@payloadcms/plugin-cloud-storage\"",
|
||||
"build:plugin-form-builder": "turbo build --filter \"@payloadcms/plugin-form-builder\"",
|
||||
"build:plugin-import-export": "turbo build --filter \"@payloadcms/plugin-import-export\"",
|
||||
"build:plugin-multi-tenant": "turbo build --filter \"@payloadcms/plugin-multi-tenant\"",
|
||||
"build:plugin-nested-docs": "turbo build --filter \"@payloadcms/plugin-nested-docs\"",
|
||||
"build:plugin-redirects": "turbo build --filter \"@payloadcms/plugin-redirects\"",
|
||||
@@ -87,7 +86,6 @@
|
||||
"runts": "cross-env NODE_OPTIONS=--no-deprecation node --no-deprecation --import @swc-node/register/esm-register",
|
||||
"script:build-template-with-local-pkgs": "pnpm --filter scripts build-template-with-local-pkgs",
|
||||
"script:gen-templates": "pnpm --filter scripts gen-templates",
|
||||
"script:license-check": "pnpm runts tools/scripts/src/license-check.ts",
|
||||
"script:list-published": "pnpm --filter releaser list-published",
|
||||
"script:pack": "pnpm --filter scripts pack-all-to-dest",
|
||||
"pretest": "pnpm build",
|
||||
@@ -142,7 +140,6 @@
|
||||
"copyfiles": "2.4.1",
|
||||
"create-payload-app": "workspace:*",
|
||||
"cross-env": "7.0.3",
|
||||
"csv-stringify": "^6.5.2",
|
||||
"dotenv": "16.4.7",
|
||||
"drizzle-kit": "0.28.0",
|
||||
"drizzle-orm": "0.36.1",
|
||||
@@ -153,7 +150,6 @@
|
||||
"globby": "11.1.0",
|
||||
"husky": "9.0.11",
|
||||
"jest": "29.7.0",
|
||||
"license-checker": "25.0.1",
|
||||
"lint-staged": "15.2.7",
|
||||
"minimist": "1.2.8",
|
||||
"mongodb-memory-server": "^10",
|
||||
|
||||
@@ -45,6 +45,7 @@ export const find: Find = async function find(
|
||||
config: this.payload.config,
|
||||
fields: collectionConfig.flattenedFields,
|
||||
locale,
|
||||
parentIsLocalized: false,
|
||||
sort: sortArg || collectionConfig.defaultSort,
|
||||
timestamps: true,
|
||||
})
|
||||
|
||||
@@ -41,6 +41,7 @@ export const findGlobalVersions: FindGlobalVersions = async function findGlobalV
|
||||
config: this.payload.config,
|
||||
fields: versionFields,
|
||||
locale,
|
||||
parentIsLocalized: false,
|
||||
sort: sortArg || '-updatedAt',
|
||||
timestamps: true,
|
||||
})
|
||||
|
||||
@@ -36,6 +36,7 @@ export const findVersions: FindVersions = async function findVersions(
|
||||
config: this.payload.config,
|
||||
fields: collectionConfig.flattenedFields,
|
||||
locale,
|
||||
parentIsLocalized: false,
|
||||
sort: sortArg || '-updatedAt',
|
||||
timestamps: true,
|
||||
})
|
||||
|
||||
@@ -38,6 +38,7 @@ export const init: Init = function init(this: MongooseAdapter) {
|
||||
...schemaOptions,
|
||||
},
|
||||
configFields: versionCollectionFields,
|
||||
parentIsLocalized: false,
|
||||
payload: this.payload,
|
||||
})
|
||||
|
||||
@@ -92,6 +93,7 @@ export const init: Init = function init(this: MongooseAdapter) {
|
||||
},
|
||||
},
|
||||
configFields: versionGlobalFields,
|
||||
parentIsLocalized: false,
|
||||
payload: this.payload,
|
||||
})
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@ export const buildCollectionSchema = (
|
||||
},
|
||||
},
|
||||
configFields: collection.fields,
|
||||
parentIsLocalized: false,
|
||||
payload,
|
||||
})
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@ export const buildGlobalModel = (payload: Payload): GlobalModel | null => {
|
||||
},
|
||||
},
|
||||
configFields: globalConfig.fields,
|
||||
parentIsLocalized: false,
|
||||
payload,
|
||||
})
|
||||
Globals.discriminator(globalConfig.slug, globalSchema)
|
||||
|
||||
@@ -7,7 +7,7 @@ type Args = {
|
||||
config: SanitizedConfig
|
||||
fields: FlattenedField[]
|
||||
locale: string
|
||||
parentIsLocalized?: boolean
|
||||
parentIsLocalized: boolean
|
||||
sort: Sort
|
||||
timestamps: boolean
|
||||
}
|
||||
|
||||
@@ -34,6 +34,7 @@ export const queryDrafts: QueryDrafts = async function queryDrafts(
|
||||
config: this.payload.config,
|
||||
fields: collectionConfig.flattenedFields,
|
||||
locale,
|
||||
parentIsLocalized: false,
|
||||
sort: sortArg || collectionConfig.defaultSort,
|
||||
timestamps: true,
|
||||
})
|
||||
|
||||
@@ -70,7 +70,6 @@ export const buildJoinAggregation = async ({
|
||||
|
||||
const {
|
||||
limit: limitJoin = join.field.defaultLimit ?? 10,
|
||||
page,
|
||||
sort: sortJoin = join.field.defaultSort || collectionConfig.defaultSort,
|
||||
where: whereJoin,
|
||||
} = joins?.[join.joinPath] || {}
|
||||
@@ -79,6 +78,7 @@ export const buildJoinAggregation = async ({
|
||||
config: adapter.payload.config,
|
||||
fields: adapter.payload.collections[slug].config.flattenedFields,
|
||||
locale,
|
||||
parentIsLocalized: false,
|
||||
sort: sortJoin,
|
||||
timestamps: true,
|
||||
})
|
||||
@@ -98,12 +98,6 @@ export const buildJoinAggregation = async ({
|
||||
},
|
||||
]
|
||||
|
||||
if (page) {
|
||||
pipeline.push({
|
||||
$skip: (page - 1) * limitJoin,
|
||||
})
|
||||
}
|
||||
|
||||
if (limitJoin > 0) {
|
||||
pipeline.push({
|
||||
$limit: limitJoin + 1,
|
||||
|
||||
@@ -65,6 +65,7 @@ export const deleteOne: DeleteOne = async function deleteOne(
|
||||
data: docToDelete,
|
||||
fields: collection.flattenedFields,
|
||||
joinQuery: false,
|
||||
parentIsLocalized: false,
|
||||
})
|
||||
|
||||
await this.deleteWhere({
|
||||
|
||||
@@ -165,6 +165,7 @@ export const findMany = async function find({
|
||||
data,
|
||||
fields,
|
||||
joinQuery,
|
||||
parentIsLocalized: false,
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
@@ -348,7 +348,6 @@ export const traverseFields = ({
|
||||
|
||||
const {
|
||||
limit: limitArg = field.defaultLimit ?? 10,
|
||||
page,
|
||||
sort = field.defaultSort,
|
||||
where,
|
||||
} = joinQuery[joinSchemaPath] || {}
|
||||
@@ -438,16 +437,6 @@ export const traverseFields = ({
|
||||
})
|
||||
}
|
||||
|
||||
if (page && limit !== 0) {
|
||||
const offset = (page - 1) * limit - 1
|
||||
if (offset > 0) {
|
||||
chainedMethods.push({
|
||||
args: [offset],
|
||||
method: 'offset',
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const db = adapter.drizzle as LibSQLDatabase
|
||||
|
||||
for (let key in selectFields) {
|
||||
|
||||
@@ -14,7 +14,7 @@ type TransformArgs = {
|
||||
fields: FlattenedField[]
|
||||
joinQuery?: JoinQuery
|
||||
locale?: string
|
||||
parentIsLocalized?: boolean
|
||||
parentIsLocalized: boolean
|
||||
}
|
||||
|
||||
// This is the entry point to transform Drizzle output data
|
||||
|
||||
@@ -9,7 +9,7 @@ type Args = {
|
||||
adapter: DrizzleAdapter
|
||||
data: Record<string, unknown>
|
||||
fields: FlattenedField[]
|
||||
parentIsLocalized?: boolean
|
||||
parentIsLocalized: boolean
|
||||
path?: string
|
||||
tableName: string
|
||||
}
|
||||
|
||||
@@ -38,6 +38,7 @@ export const upsertRow = async <T extends Record<string, unknown> | TypeWithID>(
|
||||
adapter,
|
||||
data,
|
||||
fields,
|
||||
parentIsLocalized: false,
|
||||
path,
|
||||
tableName,
|
||||
})
|
||||
@@ -459,6 +460,7 @@ export const upsertRow = async <T extends Record<string, unknown> | TypeWithID>(
|
||||
data: doc,
|
||||
fields,
|
||||
joinQuery: false,
|
||||
parentIsLocalized: false,
|
||||
})
|
||||
|
||||
return result
|
||||
|
||||
@@ -263,9 +263,6 @@ export function buildObjectType({
|
||||
limit: {
|
||||
type: GraphQLInt,
|
||||
},
|
||||
page: {
|
||||
type: GraphQLInt,
|
||||
},
|
||||
sort: {
|
||||
type: GraphQLString,
|
||||
},
|
||||
@@ -279,7 +276,7 @@ export function buildObjectType({
|
||||
},
|
||||
async resolve(parent, args, context: Context) {
|
||||
const { collection } = field
|
||||
const { limit, page, sort, where } = args
|
||||
const { limit, sort, where } = args
|
||||
const { req } = context
|
||||
|
||||
const fullWhere = combineQueries(where, {
|
||||
@@ -293,7 +290,6 @@ export function buildObjectType({
|
||||
limit,
|
||||
locale: req.locale,
|
||||
overrideAccess: false,
|
||||
page,
|
||||
req,
|
||||
sort,
|
||||
where: fullWhere,
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
import type { DocumentTabConfig, DocumentTabServerProps, ServerProps } from 'payload'
|
||||
import type { DocumentTabConfig, DocumentTabProps } from 'payload'
|
||||
import type React from 'react'
|
||||
|
||||
import { RenderServerComponent } from '@payloadcms/ui/elements/RenderServerComponent'
|
||||
import { Fragment } from 'react'
|
||||
|
||||
import { DocumentTabLink } from './TabLink.js'
|
||||
import './index.scss'
|
||||
import { DocumentTabLink } from './TabLink.js'
|
||||
|
||||
export const baseClass = 'doc-tab'
|
||||
|
||||
export const DocumentTab: React.FC<
|
||||
{ readonly Pill_Component?: React.FC } & DocumentTabConfig & DocumentTabServerProps
|
||||
{ readonly Pill_Component?: React.FC } & DocumentTabConfig & DocumentTabProps
|
||||
> = (props) => {
|
||||
const {
|
||||
apiURL,
|
||||
@@ -27,7 +27,6 @@ export const DocumentTab: React.FC<
|
||||
Pill,
|
||||
Pill_Component,
|
||||
} = props
|
||||
|
||||
const { config } = payload
|
||||
const { routes } = config
|
||||
|
||||
@@ -84,7 +83,7 @@ export const DocumentTab: React.FC<
|
||||
i18n,
|
||||
payload,
|
||||
permissions,
|
||||
} satisfies ServerProps,
|
||||
},
|
||||
})}
|
||||
</Fragment>
|
||||
) : null}
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
import type { I18n } from '@payloadcms/translations'
|
||||
import type {
|
||||
DocumentTabClientProps,
|
||||
DocumentTabServerPropsOnly,
|
||||
Payload,
|
||||
SanitizedCollectionConfig,
|
||||
SanitizedGlobalConfig,
|
||||
@@ -66,7 +64,6 @@ export const DocumentTabs: React.FC<{
|
||||
return (
|
||||
<DocumentTab
|
||||
key={`tab-${index}`}
|
||||
path={viewConfig && 'path' in viewConfig ? viewConfig.path : ''}
|
||||
{...{
|
||||
...props,
|
||||
...(tab || {}),
|
||||
@@ -86,7 +83,7 @@ export const DocumentTabs: React.FC<{
|
||||
return RenderServerComponent({
|
||||
clientProps: {
|
||||
path,
|
||||
} satisfies DocumentTabClientProps,
|
||||
},
|
||||
Component: tab.Component,
|
||||
importMap: payload.importMap,
|
||||
key: `tab-custom-${index}`,
|
||||
@@ -96,14 +93,13 @@ export const DocumentTabs: React.FC<{
|
||||
i18n,
|
||||
payload,
|
||||
permissions,
|
||||
} satisfies DocumentTabServerPropsOnly,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
return (
|
||||
<DocumentTab
|
||||
key={`tab-custom-${index}`}
|
||||
path={path}
|
||||
{...{
|
||||
...props,
|
||||
...tab,
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import type { DocumentViewServerProps } from 'payload'
|
||||
import type { EditViewComponent, PayloadServerReactComponent } from 'payload'
|
||||
|
||||
import React from 'react'
|
||||
|
||||
import { APIViewClient } from './index.client.js'
|
||||
|
||||
export function APIView(props: DocumentViewServerProps) {
|
||||
export const APIView: PayloadServerReactComponent<EditViewComponent> = () => {
|
||||
return <APIViewClient />
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { AdminViewServerProps, DocumentViewServerPropsOnly } from 'payload'
|
||||
import type { AdminViewProps } from 'payload'
|
||||
|
||||
import { DocumentInfoProvider, EditDepthProvider, HydrateAuthProvider } from '@payloadcms/ui'
|
||||
import { RenderServerComponent } from '@payloadcms/ui/elements/RenderServerComponent'
|
||||
@@ -18,7 +18,11 @@ import { Settings } from './Settings/index.js'
|
||||
|
||||
export { generateAccountMetadata } from './meta.js'
|
||||
|
||||
export async function Account({ initPageResult, params, searchParams }: AdminViewServerProps) {
|
||||
export const Account: React.FC<AdminViewProps> = async ({
|
||||
initPageResult,
|
||||
params,
|
||||
searchParams,
|
||||
}) => {
|
||||
const {
|
||||
languageOptions,
|
||||
locale,
|
||||
@@ -149,7 +153,6 @@ export async function Account({ initPageResult, params, searchParams }: AdminVie
|
||||
Fallback: EditView,
|
||||
importMap: payload.importMap,
|
||||
serverProps: {
|
||||
doc: data,
|
||||
i18n,
|
||||
initPageResult,
|
||||
locale,
|
||||
@@ -159,7 +162,7 @@ export async function Account({ initPageResult, params, searchParams }: AdminVie
|
||||
routeSegments: [],
|
||||
searchParams,
|
||||
user,
|
||||
} satisfies DocumentViewServerPropsOnly,
|
||||
},
|
||||
})}
|
||||
<AccountClient />
|
||||
</EditDepthProvider>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { AdminViewServerProps } from 'payload'
|
||||
import type { AdminViewProps } from 'payload'
|
||||
|
||||
import { buildFormState } from '@payloadcms/ui/utilities/buildFormState'
|
||||
import React from 'react'
|
||||
@@ -11,7 +11,7 @@ import './index.scss'
|
||||
|
||||
export { generateCreateFirstUserMetadata } from './meta.js'
|
||||
|
||||
export async function CreateFirstUserView({ initPageResult }: AdminViewServerProps) {
|
||||
export const CreateFirstUserView: React.FC<AdminViewProps> = async ({ initPageResult }) => {
|
||||
const {
|
||||
locale,
|
||||
req,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { groupNavItems } from '@payloadcms/ui/shared'
|
||||
import type { ClientUser, Locale, ServerProps } from 'payload'
|
||||
import type { ClientUser, SanitizedPermissions, ServerProps, VisibleEntities } from 'payload'
|
||||
|
||||
import { getTranslation } from '@payloadcms/translations'
|
||||
import { Button, Card, Gutter, Locked } from '@payloadcms/ui'
|
||||
@@ -11,11 +11,7 @@ import './index.scss'
|
||||
|
||||
const baseClass = 'dashboard'
|
||||
|
||||
export type DashboardViewClientProps = {
|
||||
locale: Locale
|
||||
}
|
||||
|
||||
export type DashboardViewServerPropsOnly = {
|
||||
export type DashboardProps = {
|
||||
globalData: Array<{
|
||||
data: { _isLocked: boolean; _lastEditedAt: string; _userEditing: ClientUser | number | string }
|
||||
lockDuration?: number
|
||||
@@ -28,11 +24,11 @@ export type DashboardViewServerPropsOnly = {
|
||||
*/
|
||||
Link?: React.ComponentType
|
||||
navGroups?: ReturnType<typeof groupNavItems>
|
||||
permissions: SanitizedPermissions
|
||||
visibleEntities: VisibleEntities
|
||||
} & ServerProps
|
||||
|
||||
export type DashboardViewServerProps = DashboardViewClientProps & DashboardViewServerPropsOnly
|
||||
|
||||
export function DefaultDashboard(props: DashboardViewServerProps) {
|
||||
export const DefaultDashboard: React.FC<DashboardProps> = (props) => {
|
||||
const {
|
||||
globalData,
|
||||
i18n,
|
||||
@@ -69,7 +65,7 @@ export function DefaultDashboard(props: DashboardViewServerProps) {
|
||||
permissions,
|
||||
searchParams,
|
||||
user,
|
||||
} satisfies ServerProps,
|
||||
},
|
||||
})}
|
||||
|
||||
<Fragment>
|
||||
@@ -186,7 +182,7 @@ export function DefaultDashboard(props: DashboardViewServerProps) {
|
||||
permissions,
|
||||
searchParams,
|
||||
user,
|
||||
} satisfies ServerProps,
|
||||
},
|
||||
})}
|
||||
</Gutter>
|
||||
</div>
|
||||
|
||||
@@ -1,18 +1,20 @@
|
||||
import type { EntityToGroup } from '@payloadcms/ui/shared'
|
||||
import type { AdminViewServerProps } from 'payload'
|
||||
import type { AdminViewProps } from 'payload'
|
||||
|
||||
import { HydrateAuthProvider, SetStepNav } from '@payloadcms/ui'
|
||||
import { RenderServerComponent } from '@payloadcms/ui/elements/RenderServerComponent'
|
||||
import { EntityType, groupNavItems } from '@payloadcms/ui/shared'
|
||||
import React, { Fragment } from 'react'
|
||||
|
||||
import type { DashboardViewClientProps, DashboardViewServerPropsOnly } from './Default/index.js'
|
||||
|
||||
import { DefaultDashboard } from './Default/index.js'
|
||||
|
||||
export { generateDashboardMetadata } from './meta.js'
|
||||
|
||||
export async function Dashboard({ initPageResult, params, searchParams }: AdminViewServerProps) {
|
||||
export const Dashboard: React.FC<AdminViewProps> = async ({
|
||||
initPageResult,
|
||||
params,
|
||||
searchParams,
|
||||
}) => {
|
||||
const {
|
||||
locale,
|
||||
permissions,
|
||||
@@ -106,7 +108,7 @@ export async function Dashboard({ initPageResult, params, searchParams }: AdminV
|
||||
{RenderServerComponent({
|
||||
clientProps: {
|
||||
locale,
|
||||
} satisfies DashboardViewClientProps,
|
||||
},
|
||||
Component: config.admin?.components?.views?.dashboard?.Component,
|
||||
Fallback: DefaultDashboard,
|
||||
importMap: payload.importMap,
|
||||
@@ -121,7 +123,7 @@ export async function Dashboard({ initPageResult, params, searchParams }: AdminV
|
||||
searchParams,
|
||||
user,
|
||||
visibleEntities,
|
||||
} satisfies DashboardViewServerPropsOnly,
|
||||
},
|
||||
})}
|
||||
</Fragment>
|
||||
)
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import type {
|
||||
AdminViewServerProps,
|
||||
DocumentViewServerProps,
|
||||
AdminViewProps,
|
||||
PayloadComponent,
|
||||
SanitizedCollectionConfig,
|
||||
SanitizedCollectionPermission,
|
||||
SanitizedConfig,
|
||||
SanitizedGlobalConfig,
|
||||
SanitizedGlobalPermission,
|
||||
ServerSideEditViewProps,
|
||||
} from 'payload'
|
||||
import type React from 'react'
|
||||
|
||||
@@ -46,18 +46,18 @@ export const getViewsFromConfig = ({
|
||||
overrideDocPermissions: true
|
||||
}
|
||||
)): {
|
||||
CustomView: ViewFromConfig<DocumentViewServerProps>
|
||||
DefaultView: ViewFromConfig<DocumentViewServerProps>
|
||||
CustomView: ViewFromConfig<ServerSideEditViewProps>
|
||||
DefaultView: ViewFromConfig<ServerSideEditViewProps>
|
||||
/**
|
||||
* The error view to display if CustomView or DefaultView do not exist (could be either due to not found, or unauthorized). Can be null
|
||||
*/
|
||||
ErrorView: ViewFromConfig<AdminViewServerProps>
|
||||
ErrorView: ViewFromConfig<AdminViewProps>
|
||||
viewKey: string
|
||||
} | null => {
|
||||
// Conditionally import and lazy load the default view
|
||||
let DefaultView: ViewFromConfig<DocumentViewServerProps> = null
|
||||
let CustomView: ViewFromConfig<DocumentViewServerProps> = null
|
||||
let ErrorView: ViewFromConfig<AdminViewServerProps> = null
|
||||
let DefaultView: ViewFromConfig<ServerSideEditViewProps> = null
|
||||
let CustomView: ViewFromConfig<ServerSideEditViewProps> = null
|
||||
let ErrorView: ViewFromConfig<AdminViewProps> = null
|
||||
let viewKey: string
|
||||
|
||||
const {
|
||||
|
||||
@@ -145,7 +145,6 @@ export const renderDocumentHandler = async (args: {
|
||||
disableActions,
|
||||
documentSubViewType: 'default',
|
||||
drawerSlug,
|
||||
i18n,
|
||||
importMap: payload.importMap,
|
||||
initialData,
|
||||
initPageResult: {
|
||||
@@ -164,7 +163,6 @@ export const renderDocumentHandler = async (args: {
|
||||
params: {
|
||||
segments: ['collections', collectionSlug, docID],
|
||||
},
|
||||
payload,
|
||||
redirectAfterDelete,
|
||||
redirectAfterDuplicate,
|
||||
searchParams: {},
|
||||
|
||||
@@ -1,11 +1,4 @@
|
||||
import type {
|
||||
AdminViewServerProps,
|
||||
Data,
|
||||
DocumentViewClientProps,
|
||||
DocumentViewServerProps,
|
||||
DocumentViewServerPropsOnly,
|
||||
PayloadComponent,
|
||||
} from 'payload'
|
||||
import type { AdminViewProps, Data, PayloadComponent, ServerSideEditViewProps } from 'payload'
|
||||
|
||||
import { DocumentInfoProvider, EditDepthProvider, HydrateAuthProvider } from '@payloadcms/ui'
|
||||
import { RenderServerComponent } from '@payloadcms/ui/elements/RenderServerComponent'
|
||||
@@ -48,9 +41,8 @@ export const renderDocument = async ({
|
||||
searchParams,
|
||||
viewType,
|
||||
}: {
|
||||
drawerSlug?: string
|
||||
overrideEntityVisibility?: boolean
|
||||
} & AdminViewServerProps): Promise<{
|
||||
} & AdminViewProps): Promise<{
|
||||
data: Data
|
||||
Document: React.ReactNode
|
||||
}> => {
|
||||
@@ -82,9 +74,9 @@ export const renderDocument = async ({
|
||||
let isEditing = getIsEditing({ id: idFromArgs, collectionSlug, globalSlug })
|
||||
|
||||
let RootViewOverride: PayloadComponent
|
||||
let CustomView: ViewFromConfig<DocumentViewServerProps>
|
||||
let DefaultView: ViewFromConfig<DocumentViewServerProps>
|
||||
let ErrorView: ViewFromConfig<AdminViewServerProps>
|
||||
let CustomView: ViewFromConfig<ServerSideEditViewProps>
|
||||
let DefaultView: ViewFromConfig<ServerSideEditViewProps>
|
||||
let ErrorView: ViewFromConfig<AdminViewProps>
|
||||
|
||||
let apiURL: string
|
||||
|
||||
@@ -169,7 +161,7 @@ export const renderDocument = async ({
|
||||
}),
|
||||
])
|
||||
|
||||
const documentViewServerProps: DocumentViewServerPropsOnly = {
|
||||
const serverProps: ServerSideEditViewProps = {
|
||||
doc,
|
||||
i18n,
|
||||
initPageResult,
|
||||
@@ -191,11 +183,9 @@ export const renderDocument = async ({
|
||||
}
|
||||
|
||||
const params = new URLSearchParams()
|
||||
|
||||
if (collectionConfig.versions?.drafts) {
|
||||
params.append('draft', 'true')
|
||||
}
|
||||
|
||||
if (locale?.code) {
|
||||
params.append('locale', locale.code)
|
||||
}
|
||||
@@ -329,12 +319,7 @@ export const renderDocument = async ({
|
||||
req,
|
||||
})
|
||||
|
||||
const clientProps: DocumentViewClientProps = {
|
||||
formState,
|
||||
...documentSlots,
|
||||
documentSubViewType,
|
||||
viewType,
|
||||
}
|
||||
const clientProps = { formState, ...documentSlots, documentSubViewType, viewType }
|
||||
|
||||
return {
|
||||
data: doc,
|
||||
@@ -378,7 +363,7 @@ export const renderDocument = async ({
|
||||
clientProps,
|
||||
Component: ErrorView.ComponentConfig || ErrorView.Component,
|
||||
importMap,
|
||||
serverProps: documentViewServerProps,
|
||||
serverProps,
|
||||
})
|
||||
: RenderServerComponent({
|
||||
clientProps,
|
||||
@@ -388,7 +373,7 @@ export const renderDocument = async ({
|
||||
? CustomView?.ComponentConfig || CustomView?.Component
|
||||
: DefaultView?.ComponentConfig || DefaultView?.Component,
|
||||
importMap,
|
||||
serverProps: documentViewServerProps,
|
||||
serverProps,
|
||||
})}
|
||||
</EditDepthProvider>
|
||||
</DocumentInfoProvider>
|
||||
@@ -396,16 +381,16 @@ export const renderDocument = async ({
|
||||
}
|
||||
}
|
||||
|
||||
export async function Document(props: AdminViewServerProps) {
|
||||
export const Document: React.FC<AdminViewProps> = async (args) => {
|
||||
try {
|
||||
const { Document: RenderedDocument } = await renderDocument(props)
|
||||
const { Document: RenderedDocument } = await renderDocument(args)
|
||||
return RenderedDocument
|
||||
} catch (error) {
|
||||
if (error?.message === 'NEXT_REDIRECT') {
|
||||
throw error
|
||||
}
|
||||
|
||||
logError({ err: error, payload: props.initPageResult.req.payload })
|
||||
logError({ err: error, payload: args.initPageResult.req.payload })
|
||||
|
||||
if (error.message === 'not-found') {
|
||||
notFound()
|
||||
|
||||
@@ -2,17 +2,11 @@ import type {
|
||||
DefaultServerFunctionArgs,
|
||||
DocumentSlots,
|
||||
PayloadRequest,
|
||||
PreviewButtonServerPropsOnly,
|
||||
PublishButtonServerPropsOnly,
|
||||
SanitizedCollectionConfig,
|
||||
SanitizedDocumentPermissions,
|
||||
SanitizedGlobalConfig,
|
||||
SaveButtonServerPropsOnly,
|
||||
SaveDraftButtonServerPropsOnly,
|
||||
ServerProps,
|
||||
StaticDescription,
|
||||
ViewDescriptionClientProps,
|
||||
ViewDescriptionServerPropsOnly,
|
||||
} from 'payload'
|
||||
|
||||
import { ViewDescription } from '@payloadcms/ui'
|
||||
@@ -50,7 +44,7 @@ export const renderDocumentSlots: (args: {
|
||||
components.PreviewButton = RenderServerComponent({
|
||||
Component: CustomPreviewButton,
|
||||
importMap: req.payload.importMap,
|
||||
serverProps: serverProps satisfies PreviewButtonServerPropsOnly,
|
||||
serverProps,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -70,14 +64,11 @@ export const renderDocumentSlots: (args: {
|
||||
|
||||
if (hasDescription) {
|
||||
components.Description = RenderServerComponent({
|
||||
clientProps: {
|
||||
collectionSlug: collectionConfig?.slug,
|
||||
description: staticDescription,
|
||||
} satisfies ViewDescriptionClientProps,
|
||||
clientProps: { description: staticDescription },
|
||||
Component: CustomDescription,
|
||||
Fallback: ViewDescription,
|
||||
importMap: req.payload.importMap,
|
||||
serverProps: serverProps satisfies ViewDescriptionServerPropsOnly,
|
||||
serverProps,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -91,10 +82,9 @@ export const renderDocumentSlots: (args: {
|
||||
components.PublishButton = RenderServerComponent({
|
||||
Component: CustomPublishButton,
|
||||
importMap: req.payload.importMap,
|
||||
serverProps: serverProps satisfies PublishButtonServerPropsOnly,
|
||||
serverProps,
|
||||
})
|
||||
}
|
||||
|
||||
const CustomSaveDraftButton =
|
||||
collectionConfig?.admin?.components?.edit?.SaveDraftButton ||
|
||||
globalConfig?.admin?.components?.elements?.SaveDraftButton
|
||||
@@ -107,7 +97,7 @@ export const renderDocumentSlots: (args: {
|
||||
components.SaveDraftButton = RenderServerComponent({
|
||||
Component: CustomSaveDraftButton,
|
||||
importMap: req.payload.importMap,
|
||||
serverProps: serverProps satisfies SaveDraftButtonServerPropsOnly,
|
||||
serverProps,
|
||||
})
|
||||
}
|
||||
} else {
|
||||
@@ -119,7 +109,7 @@ export const renderDocumentSlots: (args: {
|
||||
components.SaveButton = RenderServerComponent({
|
||||
Component: CustomSaveButton,
|
||||
importMap: req.payload.importMap,
|
||||
serverProps: serverProps satisfies SaveButtonServerPropsOnly,
|
||||
serverProps,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
'use client'
|
||||
|
||||
import type { DocumentViewClientProps } from 'payload'
|
||||
import type { ClientSideEditViewProps } from 'payload'
|
||||
|
||||
import { DefaultEditView } from '@payloadcms/ui'
|
||||
import React from 'react'
|
||||
|
||||
export const EditView: React.FC<DocumentViewClientProps> = (props) => {
|
||||
export const EditView: React.FC<ClientSideEditViewProps> = (props) => {
|
||||
return <DefaultEditView {...props} />
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { AdminViewServerProps } from 'payload'
|
||||
import type { AdminViewProps } from 'payload'
|
||||
|
||||
import { Button, Link } from '@payloadcms/ui'
|
||||
import { formatAdminURL, Translation } from '@payloadcms/ui/shared'
|
||||
@@ -11,7 +11,7 @@ export { generateForgotPasswordMetadata } from './meta.js'
|
||||
|
||||
export const forgotPasswordBaseClass = 'forgot-password'
|
||||
|
||||
export function ForgotPasswordView({ initPageResult }: AdminViewServerProps) {
|
||||
export const ForgotPasswordView: React.FC<AdminViewProps> = ({ initPageResult }) => {
|
||||
const {
|
||||
req: {
|
||||
i18n,
|
||||
|
||||
@@ -137,7 +137,6 @@ export const renderListHandler = async (args: {
|
||||
disableBulkEdit,
|
||||
drawerSlug,
|
||||
enableRowSelections,
|
||||
i18n,
|
||||
importMap: payload.importMap,
|
||||
initPageResult: {
|
||||
collectionConfig: payload?.collections?.[collectionSlug]?.config,
|
||||
@@ -153,7 +152,6 @@ export const renderListHandler = async (args: {
|
||||
params: {
|
||||
segments: ['collections', collectionSlug],
|
||||
},
|
||||
payload,
|
||||
query,
|
||||
redirectAfterDelete,
|
||||
redirectAfterDuplicate,
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
import type {
|
||||
AdminViewServerProps,
|
||||
ListComponentClientProps,
|
||||
ListComponentServerProps,
|
||||
ListPreferences,
|
||||
ListQuery,
|
||||
ListViewClientProps,
|
||||
ListViewServerPropsOnly,
|
||||
Where,
|
||||
} from 'payload'
|
||||
} from '@payloadcms/ui'
|
||||
import type { AdminViewProps, ListQuery, Where } from 'payload'
|
||||
|
||||
import { DefaultListView, HydrateAuthProvider, ListQueryProvider } from '@payloadcms/ui'
|
||||
import { RenderServerComponent } from '@payloadcms/ui/elements/RenderServerComponent'
|
||||
@@ -20,18 +19,17 @@ import { resolveAllFilterOptions } from './resolveAllFilterOptions.js'
|
||||
|
||||
export { generateListMetadata } from './meta.js'
|
||||
|
||||
type RenderListViewArgs = {
|
||||
type ListViewArgs = {
|
||||
customCellProps?: Record<string, any>
|
||||
disableBulkDelete?: boolean
|
||||
disableBulkEdit?: boolean
|
||||
drawerSlug?: string
|
||||
enableRowSelections: boolean
|
||||
overrideEntityVisibility?: boolean
|
||||
query: ListQuery
|
||||
} & AdminViewServerProps
|
||||
} & AdminViewProps
|
||||
|
||||
export const renderListView = async (
|
||||
args: RenderListViewArgs,
|
||||
args: ListViewArgs,
|
||||
): Promise<{
|
||||
List: React.ReactNode
|
||||
}> => {
|
||||
@@ -162,20 +160,19 @@ export const renderListView = async (
|
||||
? collectionConfig.admin.description({ t: i18n.t })
|
||||
: collectionConfig.admin.description
|
||||
|
||||
const newDocumentURL = formatAdminURL({
|
||||
adminRoute,
|
||||
path: `/collections/${collectionSlug}/create`,
|
||||
})
|
||||
const sharedClientProps: ListComponentClientProps = {
|
||||
collectionSlug,
|
||||
hasCreatePermission: permissions?.collections?.[collectionSlug]?.create,
|
||||
newDocumentURL: formatAdminURL({
|
||||
adminRoute,
|
||||
path: `/collections/${collectionSlug}/create`,
|
||||
}),
|
||||
}
|
||||
|
||||
const hasCreatePermission = permissions?.collections?.[collectionSlug]?.create
|
||||
|
||||
const serverProps: ListViewServerPropsOnly = {
|
||||
const sharedServerProps: ListComponentServerProps = {
|
||||
collectionConfig,
|
||||
data,
|
||||
i18n,
|
||||
limit,
|
||||
listPreferences,
|
||||
listSearchableFields: collectionConfig.admin.listSearchableFields,
|
||||
locale: fullLocale,
|
||||
params,
|
||||
payload,
|
||||
@@ -185,17 +182,26 @@ export const renderListView = async (
|
||||
}
|
||||
|
||||
const listViewSlots = renderListViewSlots({
|
||||
clientProps: {
|
||||
collectionSlug,
|
||||
hasCreatePermission,
|
||||
newDocumentURL,
|
||||
},
|
||||
clientProps: sharedClientProps,
|
||||
collectionConfig,
|
||||
description: staticDescription,
|
||||
payload,
|
||||
serverProps,
|
||||
serverProps: sharedServerProps,
|
||||
})
|
||||
|
||||
const clientProps: ListViewClientProps = {
|
||||
...listViewSlots,
|
||||
...sharedClientProps,
|
||||
columnState,
|
||||
disableBulkDelete,
|
||||
disableBulkEdit,
|
||||
enableRowSelections,
|
||||
listPreferences,
|
||||
renderedFilters,
|
||||
resolvedFilterOptions,
|
||||
Table,
|
||||
}
|
||||
|
||||
const isInDrawer = Boolean(drawerSlug)
|
||||
|
||||
return {
|
||||
@@ -209,24 +215,16 @@ export const renderListView = async (
|
||||
modifySearchParams={!isInDrawer}
|
||||
>
|
||||
{RenderServerComponent({
|
||||
clientProps: {
|
||||
...listViewSlots,
|
||||
collectionSlug,
|
||||
columnState,
|
||||
disableBulkDelete,
|
||||
disableBulkEdit,
|
||||
enableRowSelections,
|
||||
hasCreatePermission,
|
||||
listPreferences,
|
||||
newDocumentURL,
|
||||
renderedFilters,
|
||||
resolvedFilterOptions,
|
||||
Table,
|
||||
} satisfies ListViewClientProps,
|
||||
clientProps,
|
||||
Component: collectionConfig?.admin?.components?.views?.list?.Component,
|
||||
Fallback: DefaultListView,
|
||||
importMap: payload.importMap,
|
||||
serverProps,
|
||||
serverProps: {
|
||||
...sharedServerProps,
|
||||
data,
|
||||
listPreferences,
|
||||
listSearchableFields: collectionConfig.admin.listSearchableFields,
|
||||
},
|
||||
})}
|
||||
</ListQueryProvider>
|
||||
</Fragment>
|
||||
@@ -237,7 +235,7 @@ export const renderListView = async (
|
||||
throw new Error('not-found')
|
||||
}
|
||||
|
||||
export const ListView: React.FC<RenderListViewArgs> = async (args) => {
|
||||
export const ListView: React.FC<ListViewArgs> = async (args) => {
|
||||
try {
|
||||
const { List: RenderedList } = await renderListView({ ...args, enableRowSelections: true })
|
||||
return RenderedList
|
||||
|
||||
@@ -1,29 +1,18 @@
|
||||
import type {
|
||||
AfterListClientProps,
|
||||
AfterListTableClientProps,
|
||||
AfterListTableServerPropsOnly,
|
||||
BeforeListClientProps,
|
||||
BeforeListServerPropsOnly,
|
||||
BeforeListTableClientProps,
|
||||
BeforeListTableServerPropsOnly,
|
||||
ListViewServerPropsOnly,
|
||||
ListComponentClientProps,
|
||||
ListComponentServerProps,
|
||||
ListViewSlots,
|
||||
ListViewSlotSharedClientProps,
|
||||
Payload,
|
||||
SanitizedCollectionConfig,
|
||||
StaticDescription,
|
||||
ViewDescriptionClientProps,
|
||||
ViewDescriptionServerPropsOnly,
|
||||
} from 'payload'
|
||||
} from '@payloadcms/ui'
|
||||
import type { Payload, SanitizedCollectionConfig, StaticDescription } from 'payload'
|
||||
|
||||
import { RenderServerComponent } from '@payloadcms/ui/elements/RenderServerComponent'
|
||||
|
||||
type Args = {
|
||||
clientProps: ListViewSlotSharedClientProps
|
||||
clientProps: ListComponentClientProps
|
||||
collectionConfig: SanitizedCollectionConfig
|
||||
description?: StaticDescription
|
||||
payload: Payload
|
||||
serverProps: ListViewServerPropsOnly
|
||||
serverProps: ListComponentServerProps
|
||||
}
|
||||
|
||||
export const renderListViewSlots = ({
|
||||
@@ -37,61 +26,49 @@ export const renderListViewSlots = ({
|
||||
|
||||
if (collectionConfig.admin.components?.afterList) {
|
||||
result.AfterList = RenderServerComponent({
|
||||
clientProps: clientProps satisfies AfterListClientProps,
|
||||
clientProps,
|
||||
Component: collectionConfig.admin.components.afterList,
|
||||
importMap: payload.importMap,
|
||||
serverProps: serverProps satisfies AfterListTableServerPropsOnly,
|
||||
serverProps,
|
||||
})
|
||||
}
|
||||
|
||||
const listMenuItems = collectionConfig.admin.components?.listMenuItems
|
||||
if (Array.isArray(listMenuItems)) {
|
||||
result.listMenuItems = [
|
||||
RenderServerComponent({
|
||||
clientProps,
|
||||
Component: listMenuItems,
|
||||
importMap: payload.importMap,
|
||||
serverProps,
|
||||
}),
|
||||
]
|
||||
}
|
||||
|
||||
if (collectionConfig.admin.components?.afterListTable) {
|
||||
result.AfterListTable = RenderServerComponent({
|
||||
clientProps: clientProps satisfies AfterListTableClientProps,
|
||||
clientProps,
|
||||
Component: collectionConfig.admin.components.afterListTable,
|
||||
importMap: payload.importMap,
|
||||
serverProps: serverProps satisfies AfterListTableServerPropsOnly,
|
||||
serverProps,
|
||||
})
|
||||
}
|
||||
|
||||
if (collectionConfig.admin.components?.beforeList) {
|
||||
result.BeforeList = RenderServerComponent({
|
||||
clientProps: clientProps satisfies BeforeListClientProps,
|
||||
clientProps,
|
||||
Component: collectionConfig.admin.components.beforeList,
|
||||
importMap: payload.importMap,
|
||||
serverProps: serverProps satisfies BeforeListServerPropsOnly,
|
||||
serverProps,
|
||||
})
|
||||
}
|
||||
|
||||
if (collectionConfig.admin.components?.beforeListTable) {
|
||||
result.BeforeListTable = RenderServerComponent({
|
||||
clientProps: clientProps satisfies BeforeListTableClientProps,
|
||||
clientProps,
|
||||
Component: collectionConfig.admin.components.beforeListTable,
|
||||
importMap: payload.importMap,
|
||||
serverProps: serverProps satisfies BeforeListTableServerPropsOnly,
|
||||
serverProps,
|
||||
})
|
||||
}
|
||||
|
||||
if (collectionConfig.admin.components?.Description) {
|
||||
result.Description = RenderServerComponent({
|
||||
clientProps: {
|
||||
collectionSlug: collectionConfig.slug,
|
||||
description,
|
||||
} satisfies ViewDescriptionClientProps,
|
||||
...clientProps,
|
||||
},
|
||||
Component: collectionConfig.admin.components.Description,
|
||||
importMap: payload.importMap,
|
||||
serverProps: serverProps satisfies ViewDescriptionServerPropsOnly,
|
||||
serverProps,
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import type { DocumentViewServerProps, LivePreviewConfig } from 'payload'
|
||||
import type { EditViewComponent, LivePreviewConfig, PayloadServerReactComponent } from 'payload'
|
||||
|
||||
import React from 'react'
|
||||
|
||||
import './index.scss'
|
||||
import { LivePreviewClient } from './index.client.js'
|
||||
|
||||
export async function LivePreviewView(props: DocumentViewServerProps) {
|
||||
export const LivePreviewView: PayloadServerReactComponent<EditViewComponent> = async (props) => {
|
||||
const { doc, initPageResult } = props
|
||||
|
||||
const { collectionConfig, globalConfig, locale, req } = initPageResult
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { AdminViewServerProps, ServerProps } from 'payload'
|
||||
import type { AdminViewProps } from 'payload'
|
||||
|
||||
import { RenderServerComponent } from '@payloadcms/ui/elements/RenderServerComponent'
|
||||
import { redirect } from 'next/navigation.js'
|
||||
@@ -12,7 +12,7 @@ export { generateLoginMetadata } from './meta.js'
|
||||
|
||||
export const loginBaseClass = 'login'
|
||||
|
||||
export function LoginView({ initPageResult, params, searchParams }: AdminViewServerProps) {
|
||||
export const LoginView: React.FC<AdminViewProps> = ({ initPageResult, params, searchParams }) => {
|
||||
const { locale, permissions, req } = initPageResult
|
||||
|
||||
const {
|
||||
@@ -24,6 +24,7 @@ export function LoginView({ initPageResult, params, searchParams }: AdminViewSer
|
||||
|
||||
const {
|
||||
admin: { components: { afterLogin, beforeLogin } = {}, user: userSlug },
|
||||
collections,
|
||||
routes: { admin },
|
||||
} = config
|
||||
|
||||
@@ -75,8 +76,9 @@ export function LoginView({ initPageResult, params, searchParams }: AdminViewSer
|
||||
permissions,
|
||||
searchParams,
|
||||
user,
|
||||
} satisfies ServerProps,
|
||||
},
|
||||
})}
|
||||
|
||||
{!collectionConfig?.auth?.disableLocalStrategy && (
|
||||
<LoginForm
|
||||
prefillEmail={prefillEmail}
|
||||
@@ -96,7 +98,7 @@ export function LoginView({ initPageResult, params, searchParams }: AdminViewSer
|
||||
permissions,
|
||||
searchParams,
|
||||
user,
|
||||
} satisfies ServerProps,
|
||||
},
|
||||
})}
|
||||
</Fragment>
|
||||
)
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import type { AdminViewServerProps } from 'payload'
|
||||
import type { AdminViewProps } from 'payload'
|
||||
|
||||
import React from 'react'
|
||||
|
||||
import { LogoutClient } from './LogoutClient.js'
|
||||
import './index.scss'
|
||||
import { LogoutClient } from './LogoutClient.js'
|
||||
|
||||
const baseClass = 'logout'
|
||||
|
||||
@@ -12,7 +12,7 @@ export { generateLogoutMetadata } from './meta.js'
|
||||
export const LogoutView: React.FC<
|
||||
{
|
||||
inactivity?: boolean
|
||||
} & AdminViewServerProps
|
||||
} & AdminViewProps
|
||||
> = ({ inactivity, initPageResult, searchParams }) => {
|
||||
const {
|
||||
req: {
|
||||
@@ -35,6 +35,6 @@ export const LogoutView: React.FC<
|
||||
)
|
||||
}
|
||||
|
||||
export function LogoutInactivity(props: AdminViewServerProps) {
|
||||
export const LogoutInactivity: React.FC<AdminViewProps> = (props) => {
|
||||
return <LogoutView inactivity {...props} />
|
||||
}
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
import type { I18n } from '@payloadcms/translations'
|
||||
import type { Metadata } from 'next'
|
||||
import type { AdminViewServerProps, ImportMap, SanitizedConfig } from 'payload'
|
||||
import type {
|
||||
AdminViewComponent,
|
||||
ImportMap,
|
||||
PayloadServerReactComponent,
|
||||
SanitizedConfig,
|
||||
} from 'payload'
|
||||
|
||||
import { formatAdminURL } from '@payloadcms/ui/shared'
|
||||
import React from 'react'
|
||||
@@ -82,6 +87,6 @@ export const NotFoundPage = async ({
|
||||
)
|
||||
}
|
||||
|
||||
export function NotFoundView(props: AdminViewServerProps) {
|
||||
export const NotFoundView: PayloadServerReactComponent<AdminViewComponent> = () => {
|
||||
return <NotFoundClient marginTop="large" />
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { AdminViewServerProps } from 'payload'
|
||||
import type { AdminViewProps } from 'payload'
|
||||
|
||||
import { Button, Link } from '@payloadcms/ui'
|
||||
import { formatAdminURL, Translation } from '@payloadcms/ui/shared'
|
||||
@@ -12,7 +12,7 @@ export const resetPasswordBaseClass = 'reset-password'
|
||||
|
||||
export { generateResetPasswordMetadata } from './meta.js'
|
||||
|
||||
export function ResetPassword({ initPageResult, params }: AdminViewServerProps) {
|
||||
export const ResetPassword: React.FC<AdminViewProps> = ({ initPageResult, params }) => {
|
||||
const { req } = initPageResult
|
||||
|
||||
const {
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import type {
|
||||
AdminViewServerProps,
|
||||
AdminViewComponent,
|
||||
AdminViewProps,
|
||||
DocumentSubViewTypes,
|
||||
ImportMap,
|
||||
PayloadComponent,
|
||||
SanitizedConfig,
|
||||
ServerPropsFromView,
|
||||
ViewTypes,
|
||||
@@ -38,12 +38,12 @@ const baseClasses = {
|
||||
}
|
||||
|
||||
type OneSegmentViews = {
|
||||
[K in Exclude<keyof SanitizedConfig['admin']['routes'], 'reset'>]: React.FC<AdminViewServerProps>
|
||||
[K in Exclude<keyof SanitizedConfig['admin']['routes'], 'reset'>]: React.FC<AdminViewProps>
|
||||
}
|
||||
|
||||
export type ViewFromConfig = {
|
||||
Component?: React.FC<AdminViewServerProps>
|
||||
payloadComponent?: PayloadComponent<AdminViewServerProps>
|
||||
Component?: React.FC<AdminViewProps>
|
||||
payloadComponent?: AdminViewComponent
|
||||
}
|
||||
|
||||
const oneSegmentViews: OneSegmentViews = {
|
||||
|
||||
@@ -1,11 +1,6 @@
|
||||
import type { I18nClient } from '@payloadcms/translations'
|
||||
import type { Metadata } from 'next'
|
||||
import type {
|
||||
AdminViewClientProps,
|
||||
AdminViewServerPropsOnly,
|
||||
ImportMap,
|
||||
SanitizedConfig,
|
||||
} from 'payload'
|
||||
import type { ImportMap, SanitizedConfig } from 'payload'
|
||||
|
||||
import { RenderServerComponent } from '@payloadcms/ui/elements/RenderServerComponent'
|
||||
import { formatAdminURL } from '@payloadcms/ui/shared'
|
||||
@@ -135,7 +130,7 @@ export const RootPage = async ({
|
||||
})
|
||||
|
||||
const RenderedView = RenderServerComponent({
|
||||
clientProps: { clientConfig, documentSubViewType, viewType } satisfies AdminViewClientProps,
|
||||
clientProps: { clientConfig, documentSubViewType, viewType },
|
||||
Component: DefaultView.payloadComponent,
|
||||
Fallback: DefaultView.Component,
|
||||
importMap,
|
||||
@@ -149,7 +144,7 @@ export const RootPage = async ({
|
||||
params,
|
||||
payload: initPageResult?.req.payload,
|
||||
searchParams,
|
||||
} satisfies AdminViewServerPropsOnly,
|
||||
},
|
||||
})
|
||||
|
||||
return (
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { AdminViewServerProps } from 'payload'
|
||||
import type { AdminViewComponent, PayloadServerReactComponent } from 'payload'
|
||||
|
||||
import { Button } from '@payloadcms/ui'
|
||||
import { formatAdminURL } from '@payloadcms/ui/shared'
|
||||
@@ -11,7 +11,9 @@ export { generateUnauthorizedMetadata } from './meta.js'
|
||||
|
||||
const baseClass = 'unauthorized'
|
||||
|
||||
export function UnauthorizedView({ initPageResult }: AdminViewServerProps) {
|
||||
export const UnauthorizedView: PayloadServerReactComponent<AdminViewComponent> = ({
|
||||
initPageResult,
|
||||
}) => {
|
||||
const {
|
||||
permissions,
|
||||
req: {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { AdminViewServerProps } from 'payload'
|
||||
import type { AdminViewProps } from 'payload'
|
||||
|
||||
import { formatAdminURL } from '@payloadcms/ui/shared'
|
||||
import React from 'react'
|
||||
@@ -11,10 +11,14 @@ export const verifyBaseClass = 'verify'
|
||||
|
||||
export { generateVerifyMetadata } from './meta.js'
|
||||
|
||||
export async function Verify({ initPageResult, params, searchParams }: AdminViewServerProps) {
|
||||
export const Verify: React.FC<AdminViewProps> = async ({
|
||||
initPageResult,
|
||||
params,
|
||||
searchParams,
|
||||
}) => {
|
||||
// /:collectionSlug/verify/:token
|
||||
|
||||
const [collectionSlug, token] = params.segments
|
||||
const [collectionSlug, verify, token] = params.segments
|
||||
const { locale, permissions, req } = initPageResult
|
||||
|
||||
const {
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import type {
|
||||
Document,
|
||||
DocumentViewServerProps,
|
||||
EditViewComponent,
|
||||
OptionObject,
|
||||
PayloadServerReactComponent,
|
||||
SanitizedCollectionPermission,
|
||||
SanitizedGlobalPermission,
|
||||
} from 'payload'
|
||||
@@ -16,7 +17,7 @@ import { getLatestVersion } from '../Versions/getLatestVersion.js'
|
||||
import { DefaultVersionView } from './Default/index.js'
|
||||
import { RenderDiff } from './RenderFieldsToDiff/index.js'
|
||||
|
||||
export async function VersionView(props: DocumentViewServerProps) {
|
||||
export const VersionView: PayloadServerReactComponent<EditViewComponent> = async (props) => {
|
||||
const { i18n, initPageResult, routeSegments, searchParams } = props
|
||||
|
||||
const {
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import type { I18n } from '@payloadcms/translations'
|
||||
import type {
|
||||
Column,
|
||||
PaginatedDocs,
|
||||
SanitizedCollectionConfig,
|
||||
SanitizedConfig,
|
||||
@@ -8,7 +7,7 @@ import type {
|
||||
TypeWithVersion,
|
||||
} from 'payload'
|
||||
|
||||
import { SortColumn } from '@payloadcms/ui'
|
||||
import { type Column, SortColumn } from '@payloadcms/ui'
|
||||
import React from 'react'
|
||||
|
||||
import { AutosaveCell } from './cells/AutosaveCell/index.js'
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
'use client'
|
||||
import type { Column, SanitizedCollectionConfig } from 'payload'
|
||||
import type { SanitizedCollectionConfig } from 'payload'
|
||||
|
||||
import {
|
||||
type Column,
|
||||
LoadingOverlayToggle,
|
||||
Pagination,
|
||||
PerPage,
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
import { Gutter, ListQueryProvider, SetDocumentStepNav } from '@payloadcms/ui'
|
||||
import { notFound } from 'next/navigation.js'
|
||||
import { type DocumentViewServerProps, logError, type PaginatedDocs } from 'payload'
|
||||
import {
|
||||
type EditViewComponent,
|
||||
logError,
|
||||
type PaginatedDocs,
|
||||
type PayloadServerReactComponent,
|
||||
} from 'payload'
|
||||
import { isNumber } from 'payload/shared'
|
||||
import React from 'react'
|
||||
|
||||
@@ -11,7 +16,7 @@ import './index.scss'
|
||||
|
||||
export const baseClass = 'versions'
|
||||
|
||||
export async function VersionsView(props: DocumentViewServerProps) {
|
||||
export const VersionsView: PayloadServerReactComponent<EditViewComponent> = async (props) => {
|
||||
const { initPageResult, searchParams } = props
|
||||
|
||||
const {
|
||||
|
||||
@@ -1,7 +1,3 @@
|
||||
import type { ServerProps } from '../../config/types.js'
|
||||
import type { CustomComponent } from '../../config/types.js'
|
||||
|
||||
export type PreviewButtonClientProps = {}
|
||||
|
||||
export type PreviewButtonServerPropsOnly = {} & ServerProps
|
||||
|
||||
export type PreviewButtonServerProps = PreviewButtonClientProps & PreviewButtonServerPropsOnly
|
||||
export type CustomPreviewButton = CustomComponent
|
||||
|
||||
@@ -1,9 +1,3 @@
|
||||
import type { ServerProps } from '../../config/types.js'
|
||||
import type { CustomComponent } from '../../config/types.js'
|
||||
|
||||
export type PublishButtonClientProps = {
|
||||
label?: string
|
||||
}
|
||||
|
||||
export type PublishButtonServerPropsOnly = {} & ServerProps
|
||||
|
||||
export type PublishButtonServerProps = PublishButtonClientProps & PublishButtonServerPropsOnly
|
||||
export type CustomPublishButton = CustomComponent
|
||||
|
||||
@@ -1,9 +1,3 @@
|
||||
import type { ServerProps } from '../../config/types.js'
|
||||
import type { CustomComponent } from '../../config/types.js'
|
||||
|
||||
export type SaveButtonClientProps = {
|
||||
label?: string
|
||||
}
|
||||
|
||||
export type SaveButtonServerPropsOnly = {} & ServerProps
|
||||
|
||||
export type SaveButtonServerProps = SaveButtonClientProps & SaveButtonServerPropsOnly
|
||||
export type CustomSaveButton = CustomComponent
|
||||
|
||||
@@ -1,7 +1,3 @@
|
||||
import type { ServerProps } from '../../config/types.js'
|
||||
import type { CustomComponent } from '../../config/types.js'
|
||||
|
||||
export type SaveDraftButtonClientProps = {}
|
||||
|
||||
export type SaveDraftButtonServerPropsOnly = {} & ServerProps
|
||||
|
||||
export type SaveDraftButtonServerProps = SaveDraftButtonClientProps & SaveDraftButtonServerPropsOnly
|
||||
export type CustomSaveDraftButton = CustomComponent
|
||||
|
||||
@@ -1,45 +1,18 @@
|
||||
import type { I18n } from '@payloadcms/translations'
|
||||
|
||||
import type { SanitizedPermissions } from '../../auth/types.js'
|
||||
import type { SanitizedCollectionConfig } from '../../collections/config/types.js'
|
||||
import type { PayloadComponent, SanitizedConfig, ServerProps } from '../../config/types.js'
|
||||
import type { PayloadComponent, SanitizedConfig } from '../../config/types.js'
|
||||
import type { SanitizedGlobalConfig } from '../../globals/config/types.js'
|
||||
import type { Data, DocumentSlots, FormState } from '../types.js'
|
||||
import type { InitPageResult, ViewTypes } from './index.js'
|
||||
import type { Payload } from '../../index.js'
|
||||
|
||||
export type EditViewProps = {
|
||||
readonly collectionSlug?: string
|
||||
readonly globalSlug?: string
|
||||
}
|
||||
|
||||
export type DocumentViewServerPropsOnly = {
|
||||
readonly doc: Data
|
||||
readonly initPageResult: InitPageResult
|
||||
readonly routeSegments: string[]
|
||||
} & ServerProps
|
||||
|
||||
export type DocumentViewServerProps = DocumentViewClientProps & DocumentViewServerPropsOnly
|
||||
|
||||
export type DocumentViewClientProps = {
|
||||
documentSubViewType: DocumentSubViewTypes
|
||||
formState: FormState
|
||||
viewType: ViewTypes
|
||||
} & DocumentSlots
|
||||
|
||||
/**
|
||||
* @todo: This should be renamed to `DocumentSubViewType` (singular)
|
||||
*/
|
||||
export type DocumentSubViewTypes = 'api' | 'default' | 'livePreview' | 'version' | 'versions'
|
||||
|
||||
export type DocumentTabServerPropsOnly = {
|
||||
export type DocumentTabProps = {
|
||||
readonly apiURL?: string
|
||||
readonly collectionConfig?: SanitizedCollectionConfig
|
||||
readonly globalConfig?: SanitizedGlobalConfig
|
||||
readonly i18n: I18n
|
||||
readonly payload: Payload
|
||||
readonly permissions: SanitizedPermissions
|
||||
} & ServerProps
|
||||
|
||||
export type DocumentTabServerProps = DocumentTabClientProps & DocumentTabServerPropsOnly
|
||||
|
||||
export type DocumentTabClientProps = {
|
||||
path: string
|
||||
}
|
||||
|
||||
export type DocumentTabCondition = (args: {
|
||||
@@ -69,9 +42,6 @@ export type DocumentTabConfig = {
|
||||
readonly Pill?: PayloadComponent
|
||||
}
|
||||
|
||||
/**
|
||||
* @todo: Remove this type as it's only used internally for the config (above)
|
||||
*/
|
||||
export type DocumentTabComponent = PayloadComponent<{
|
||||
path: string
|
||||
}>
|
||||
@@ -1,10 +0,0 @@
|
||||
import type { ClientField } from '../../fields/config/types.js'
|
||||
|
||||
export type Column = {
|
||||
readonly accessor: string
|
||||
readonly active: boolean
|
||||
readonly CustomLabel?: React.ReactNode
|
||||
readonly field: ClientField
|
||||
readonly Heading: React.ReactNode
|
||||
readonly renderedCells: React.ReactNode[]
|
||||
}
|
||||
@@ -24,58 +24,20 @@ import type {
|
||||
Row,
|
||||
} from './forms/Form.js'
|
||||
|
||||
export type {
|
||||
/**
|
||||
* @deprecated
|
||||
* The `CustomPreviewButton` type is deprecated and will be removed in the next major version.
|
||||
* This type is only used for the Payload Config. Use `PreviewButtonClientProps` instead.
|
||||
*/
|
||||
CustomComponent as CustomPreviewButton,
|
||||
/**
|
||||
* @deprecated
|
||||
* The `CustomPublishButton` type is deprecated and will be removed in the next major version.
|
||||
* This type is only used for the Payload Config. Use `PreviewButtonClientProps` instead.
|
||||
*/
|
||||
CustomComponent as CustomPublishButton,
|
||||
/**
|
||||
* @deprecated
|
||||
* The `CustomSaveButton` type is deprecated and will be removed in the next major version.
|
||||
* This type is only used for the Payload Config. Use `PreviewButtonClientProps` instead.
|
||||
*/
|
||||
CustomComponent as CustomSaveButton,
|
||||
/**
|
||||
* @deprecated
|
||||
* The `CustomSaveDraftButton` type is deprecated and will be removed in the next major version.
|
||||
* This type is only used for the Payload Config. Use `PreviewButtonClientProps` instead.
|
||||
*/
|
||||
CustomComponent as CustomSaveDraftButton,
|
||||
} from '../config/types.js'
|
||||
export type { DefaultCellComponentProps, DefaultServerCellComponentProps } from './elements/Cell.js'
|
||||
export type { ConditionalDateProps } from './elements/DatePicker.js'
|
||||
export type { DayPickerProps, SharedProps, TimePickerProps } from './elements/DatePicker.js'
|
||||
export type { NavGroupPreferences, NavPreferences } from './elements/Nav.js'
|
||||
export type { CustomPreviewButton } from './elements/PreviewButton.js'
|
||||
export type { CustomPublishButton } from './elements/PublishButton.js'
|
||||
export type { CustomSaveButton } from './elements/SaveButton.js'
|
||||
export type { CustomSaveDraftButton } from './elements/SaveDraftButton.js'
|
||||
export type {
|
||||
PreviewButtonClientProps,
|
||||
PreviewButtonServerProps,
|
||||
PreviewButtonServerPropsOnly,
|
||||
} from './elements/PreviewButton.js'
|
||||
export type {
|
||||
PublishButtonClientProps,
|
||||
PublishButtonServerProps,
|
||||
PublishButtonServerPropsOnly,
|
||||
} from './elements/PublishButton.js'
|
||||
export type {
|
||||
SaveButtonClientProps,
|
||||
SaveButtonServerProps,
|
||||
SaveButtonServerPropsOnly,
|
||||
} from './elements/SaveButton.js'
|
||||
export type {
|
||||
SaveDraftButtonClientProps,
|
||||
SaveDraftButtonServerProps,
|
||||
SaveDraftButtonServerPropsOnly,
|
||||
} from './elements/SaveDraftButton.js'
|
||||
|
||||
export type { Column } from './elements/Table.js'
|
||||
DocumentTabComponent,
|
||||
DocumentTabCondition,
|
||||
DocumentTabConfig,
|
||||
DocumentTabProps,
|
||||
} from './elements/Tab.js'
|
||||
|
||||
export type { CustomUpload } from './elements/Upload.js'
|
||||
|
||||
@@ -435,6 +397,14 @@ export type {
|
||||
VersionTab,
|
||||
} from './forms/Diff.js'
|
||||
|
||||
export type {
|
||||
FieldErrorClientComponent,
|
||||
FieldErrorClientProps,
|
||||
FieldErrorServerComponent,
|
||||
FieldErrorServerProps,
|
||||
GenericErrorProps,
|
||||
} from './forms/Error.js'
|
||||
|
||||
export type {
|
||||
BuildFormStateArgs,
|
||||
Data,
|
||||
@@ -446,14 +416,6 @@ export type {
|
||||
Row,
|
||||
}
|
||||
|
||||
export type {
|
||||
FieldErrorClientComponent,
|
||||
FieldErrorClientProps,
|
||||
FieldErrorServerComponent,
|
||||
FieldErrorServerProps,
|
||||
GenericErrorProps,
|
||||
} from './forms/Error.js'
|
||||
|
||||
export type {
|
||||
ClientComponentProps,
|
||||
ClientFieldBase,
|
||||
@@ -476,6 +438,18 @@ export type {
|
||||
|
||||
export type { RowLabel, RowLabelComponent } from './forms/RowLabel.js'
|
||||
|
||||
export type {
|
||||
BuildTableStateArgs,
|
||||
DefaultServerFunctionArgs,
|
||||
ListQuery,
|
||||
ServerFunction,
|
||||
ServerFunctionArgs,
|
||||
ServerFunctionClient,
|
||||
ServerFunctionClientArgs,
|
||||
ServerFunctionConfig,
|
||||
ServerFunctionHandler,
|
||||
} from './functions/index.js'
|
||||
|
||||
export type MappedServerComponent<TComponentClientProps extends JsonObject = JsonObject> = {
|
||||
Component?: React.ComponentType<TComponentClientProps>
|
||||
props?: Partial<any>
|
||||
@@ -561,104 +535,20 @@ export type DocumentSlots = {
|
||||
Upload?: React.ReactNode
|
||||
}
|
||||
|
||||
export type {
|
||||
BuildTableStateArgs,
|
||||
DefaultServerFunctionArgs,
|
||||
ListQuery,
|
||||
ServerFunction,
|
||||
ServerFunctionArgs,
|
||||
ServerFunctionClient,
|
||||
ServerFunctionClientArgs,
|
||||
ServerFunctionConfig,
|
||||
ServerFunctionHandler,
|
||||
} from './functions/index.js'
|
||||
|
||||
export type { LanguageOptions } from './LanguageOptions.js'
|
||||
|
||||
export type { RichTextAdapter, RichTextAdapterProvider, RichTextHooks } from './RichText.js'
|
||||
|
||||
export type {
|
||||
DocumentSubViewTypes,
|
||||
DocumentTabClientProps,
|
||||
/**
|
||||
* @deprecated
|
||||
* The `DocumentTabComponent` type is deprecated and will be removed in the next major version.
|
||||
* Use `DocumentTabServerProps`or `DocumentTabClientProps` instead.
|
||||
*/
|
||||
DocumentTabComponent,
|
||||
DocumentTabCondition,
|
||||
DocumentTabConfig,
|
||||
/**
|
||||
* @deprecated
|
||||
* The `DocumentTabProps` type is deprecated and will be removed in the next major version.
|
||||
* Use `DocumentTabServerProps` instead.
|
||||
*/
|
||||
DocumentTabServerProps as DocumentTabProps,
|
||||
DocumentTabServerProps,
|
||||
DocumentTabServerPropsOnly,
|
||||
/**
|
||||
* @deprecated
|
||||
* The `ClientSideEditViewProps` type is deprecated and will be removed in the next major version.
|
||||
* Use `DocumentViewClientProps` instead.
|
||||
*/
|
||||
DocumentViewClientProps as ClientSideEditViewProps,
|
||||
DocumentViewClientProps,
|
||||
/**
|
||||
* @deprecated
|
||||
* The `ServerSideEditViewProps` is deprecated and will be removed in the next major version.
|
||||
* Use `DocumentViewServerProps` instead.
|
||||
*/
|
||||
DocumentViewServerProps as ServerSideEditViewProps,
|
||||
DocumentViewServerProps,
|
||||
DocumentViewServerPropsOnly,
|
||||
EditViewProps,
|
||||
} from './views/document.js'
|
||||
|
||||
export type {
|
||||
AdminViewClientProps,
|
||||
/**
|
||||
* @deprecated
|
||||
* The `AdminViewComponent` type is deprecated and will be removed in the next major version.
|
||||
* Type your component props directly instead.
|
||||
*/
|
||||
AdminViewComponent,
|
||||
AdminViewConfig,
|
||||
/**
|
||||
* @deprecated
|
||||
* The `AdminViewProps` type is deprecated and will be removed in the next major version.
|
||||
* Use `AdminViewServerProps` instead.
|
||||
*/
|
||||
AdminViewServerProps as AdminViewProps,
|
||||
AdminViewServerProps,
|
||||
AdminViewServerPropsOnly,
|
||||
AdminViewProps,
|
||||
ClientSideEditViewProps,
|
||||
EditViewProps,
|
||||
InitPageResult,
|
||||
ServerPropsFromView,
|
||||
ViewDescriptionClientProps,
|
||||
ViewDescriptionServerProps,
|
||||
ViewDescriptionServerPropsOnly,
|
||||
ViewTypes,
|
||||
ServerSideEditViewProps,
|
||||
VisibleEntities,
|
||||
} from './views/index.js'
|
||||
|
||||
export type {
|
||||
AfterListClientProps,
|
||||
AfterListServerProps,
|
||||
AfterListServerPropsOnly,
|
||||
AfterListTableClientProps,
|
||||
AfterListTableServerProps,
|
||||
AfterListTableServerPropsOnly,
|
||||
BeforeListClientProps,
|
||||
BeforeListServerProps,
|
||||
BeforeListServerPropsOnly,
|
||||
BeforeListTableClientProps,
|
||||
BeforeListTableServerProps,
|
||||
BeforeListTableServerPropsOnly,
|
||||
ListViewClientProps,
|
||||
ListViewServerProps,
|
||||
ListViewServerPropsOnly,
|
||||
ListViewSlots,
|
||||
ListViewSlotSharedClientProps,
|
||||
} from './views/list.js'
|
||||
} from './views/types.js'
|
||||
|
||||
type SchemaPath = {} & string
|
||||
export type FieldSchemaMap = Map<
|
||||
|
||||
@@ -1,76 +0,0 @@
|
||||
import type {
|
||||
CollectionAdminOptions,
|
||||
SanitizedCollectionConfig,
|
||||
} from '../../collections/config/types.js'
|
||||
import type { ServerProps } from '../../config/types.js'
|
||||
import type { ListPreferences } from '../../preferences/types.js'
|
||||
import type { ResolvedFilterOptions } from '../../types/index.js'
|
||||
import type { Column } from '../elements/Table.js'
|
||||
import type { Data } from '../types.js'
|
||||
|
||||
export type ListViewSlots = {
|
||||
AfterList?: React.ReactNode
|
||||
AfterListTable?: React.ReactNode
|
||||
BeforeList?: React.ReactNode
|
||||
BeforeListTable?: React.ReactNode
|
||||
Description?: React.ReactNode
|
||||
listMenuItems?: React.ReactNode[]
|
||||
Table: React.ReactNode
|
||||
}
|
||||
|
||||
/**
|
||||
* The `ListViewServerPropsOnly` approach is needed to ensure type strictness when injecting component props
|
||||
* There is no way to do something like `Omit<ListViewServerProps, keyof ListViewClientProps>`
|
||||
* This is because `ListViewClientProps` is a union which is impossible to exclude from
|
||||
* Exporting explicitly defined `ListViewServerPropsOnly`, etc. allows for the strictest typing
|
||||
*/
|
||||
export type ListViewServerPropsOnly = {
|
||||
collectionConfig: SanitizedCollectionConfig
|
||||
data: Data
|
||||
limit: number
|
||||
listPreferences: ListPreferences
|
||||
listSearchableFields: CollectionAdminOptions['listSearchableFields']
|
||||
} & ServerProps
|
||||
|
||||
export type ListViewServerProps = ListViewClientProps & ListViewServerPropsOnly
|
||||
|
||||
export type ListViewClientProps = {
|
||||
beforeActions?: React.ReactNode[]
|
||||
collectionSlug: SanitizedCollectionConfig['slug']
|
||||
columnState: Column[]
|
||||
disableBulkDelete?: boolean
|
||||
disableBulkEdit?: boolean
|
||||
enableRowSelections?: boolean
|
||||
hasCreatePermission: boolean
|
||||
listPreferences?: ListPreferences
|
||||
newDocumentURL: string
|
||||
preferenceKey?: string
|
||||
renderedFilters?: Map<string, React.ReactNode>
|
||||
resolvedFilterOptions?: Map<string, ResolvedFilterOptions>
|
||||
} & ListViewSlots
|
||||
|
||||
export type ListViewSlotSharedClientProps = {
|
||||
collectionSlug: SanitizedCollectionConfig['slug']
|
||||
hasCreatePermission: boolean
|
||||
newDocumentURL: string
|
||||
}
|
||||
|
||||
// BeforeList
|
||||
export type BeforeListClientProps = ListViewSlotSharedClientProps
|
||||
export type BeforeListServerPropsOnly = {} & ListViewServerPropsOnly
|
||||
export type BeforeListServerProps = BeforeListClientProps & BeforeListServerPropsOnly
|
||||
|
||||
// BeforeListTable
|
||||
export type BeforeListTableClientProps = ListViewSlotSharedClientProps
|
||||
export type BeforeListTableServerPropsOnly = {} & ListViewServerPropsOnly
|
||||
export type BeforeListTableServerProps = BeforeListTableClientProps & BeforeListTableServerPropsOnly
|
||||
|
||||
// AfterList
|
||||
export type AfterListClientProps = ListViewSlotSharedClientProps
|
||||
export type AfterListServerPropsOnly = {} & ListViewServerPropsOnly
|
||||
export type AfterListServerProps = AfterListClientProps & AfterListServerPropsOnly
|
||||
|
||||
// AfterListTable
|
||||
export type AfterListTableClientProps = ListViewSlotSharedClientProps
|
||||
export type AfterListTableServerPropsOnly = {} & ListViewServerPropsOnly
|
||||
export type AfterListTableServerProps = AfterListTableClientProps & AfterListTableServerPropsOnly
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { ClientTranslationsObject, I18n } from '@payloadcms/translations'
|
||||
import type { ClientTranslationsObject } from '@payloadcms/translations'
|
||||
|
||||
import type { SanitizedPermissions } from '../../auth/index.js'
|
||||
import type { ImportMap } from '../../bin/generateImportMap/index.js'
|
||||
@@ -8,19 +8,17 @@ import type {
|
||||
CustomComponent,
|
||||
Locale,
|
||||
MetaConfig,
|
||||
Params,
|
||||
PayloadComponent,
|
||||
SanitizedConfig,
|
||||
ServerProps,
|
||||
} from '../../config/types.js'
|
||||
import type { SanitizedGlobalConfig } from '../../globals/config/types.js'
|
||||
import type { Payload, PayloadRequest } from '../../types/index.js'
|
||||
import type { PayloadRequest } from '../../types/index.js'
|
||||
import type { LanguageOptions } from '../LanguageOptions.js'
|
||||
import type { Data, StaticDescription } from '../types.js'
|
||||
import type { DocumentSubViewTypes } from './document.js'
|
||||
import type { Data, DocumentSlots } from '../types.js'
|
||||
|
||||
export type AdminViewConfig = {
|
||||
Component: PayloadComponent
|
||||
Component: AdminViewComponent
|
||||
/** Whether the path should be matched exactly or as a prefix */
|
||||
exact?: boolean
|
||||
meta?: MetaConfig
|
||||
@@ -29,32 +27,27 @@ export type AdminViewConfig = {
|
||||
strict?: boolean
|
||||
}
|
||||
|
||||
export type AdminViewClientProps = {
|
||||
clientConfig: ClientConfig
|
||||
documentSubViewType?: DocumentSubViewTypes
|
||||
viewType: ViewTypes
|
||||
}
|
||||
|
||||
export type AdminViewServerPropsOnly = {
|
||||
export type AdminViewProps = {
|
||||
readonly clientConfig: ClientConfig
|
||||
readonly disableActions?: boolean
|
||||
/**
|
||||
* @todo remove `docID` here as it is already contained in `initPageResult`
|
||||
*/
|
||||
readonly docID?: number | string
|
||||
readonly documentSubViewType?: DocumentSubViewTypes
|
||||
readonly drawerSlug?: string
|
||||
readonly importMap: ImportMap
|
||||
readonly initialData?: Data
|
||||
readonly initPageResult: InitPageResult
|
||||
readonly params?: { [key: string]: string | string[] | undefined }
|
||||
readonly redirectAfterDelete?: boolean
|
||||
readonly redirectAfterDuplicate?: boolean
|
||||
} & ServerProps
|
||||
readonly searchParams: { [key: string]: string | string[] | undefined }
|
||||
readonly viewType: ViewTypes
|
||||
}
|
||||
|
||||
export type AdminViewServerProps = AdminViewClientProps & AdminViewServerPropsOnly
|
||||
export type AdminViewComponent = PayloadComponent<AdminViewProps>
|
||||
|
||||
/**
|
||||
* @deprecated This should be removed in favor of direct props
|
||||
*/
|
||||
export type AdminViewComponent = PayloadComponent<AdminViewServerProps>
|
||||
export type EditViewProps = {
|
||||
readonly collectionSlug?: string
|
||||
readonly globalSlug?: string
|
||||
}
|
||||
|
||||
export type VisibleEntities = {
|
||||
collections: SanitizedCollectionConfig['slug'][]
|
||||
@@ -75,9 +68,15 @@ export type InitPageResult = {
|
||||
visibleEntities: VisibleEntities
|
||||
}
|
||||
|
||||
/**
|
||||
* @todo This should be renamed to `ViewType` (singular)
|
||||
*/
|
||||
export type ServerSideEditViewProps = {
|
||||
readonly doc: Data
|
||||
readonly initPageResult: InitPageResult
|
||||
readonly routeSegments: string[]
|
||||
} & ClientSideEditViewProps &
|
||||
ServerProps
|
||||
|
||||
export type ClientSideEditViewProps = {} & DocumentSlots
|
||||
|
||||
export type ViewTypes =
|
||||
| 'account'
|
||||
| 'dashboard'
|
||||
@@ -86,19 +85,10 @@ export type ViewTypes =
|
||||
| 'reset'
|
||||
| 'verify'
|
||||
| 'version'
|
||||
export type DocumentSubViewTypes = 'api' | 'default' | 'livePreview' | 'version' | 'versions'
|
||||
|
||||
export type ServerPropsFromView = {
|
||||
collectionConfig?: SanitizedConfig['collections'][number]
|
||||
globalConfig?: SanitizedConfig['globals'][number]
|
||||
viewActions: CustomComponent[]
|
||||
}
|
||||
|
||||
// Description
|
||||
export type ViewDescriptionClientProps = {
|
||||
collectionSlug?: SanitizedCollectionConfig['slug']
|
||||
description: StaticDescription
|
||||
}
|
||||
|
||||
export type ViewDescriptionServerPropsOnly = {} & ServerProps
|
||||
|
||||
export type ViewDescriptionServerProps = ViewDescriptionClientProps & ViewDescriptionServerPropsOnly
|
||||
@@ -30,7 +30,6 @@ export function iterateCollections({
|
||||
})
|
||||
|
||||
addToImportMap(collection.admin?.components?.afterList)
|
||||
addToImportMap(collection.admin?.components?.listMenuItems)
|
||||
addToImportMap(collection.admin?.components?.afterListTable)
|
||||
addToImportMap(collection.admin?.components?.beforeList)
|
||||
addToImportMap(collection.admin?.components?.beforeListTable)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// @ts-strict-ignore
|
||||
|
||||
import type { AdminViewConfig } from '../../admin/views/index.js'
|
||||
import type { AdminViewConfig } from '../../admin/views/types.js'
|
||||
import type { SanitizedConfig } from '../../config/types.js'
|
||||
import type { AddToImportMap, Imports, InternalImportMap } from './index.js'
|
||||
|
||||
|
||||
@@ -3,13 +3,11 @@ import type { LoginWithUsernameOptions } from '../../auth/types.js'
|
||||
import type { Config, SanitizedConfig } from '../../config/types.js'
|
||||
import type { CollectionConfig, SanitizedCollectionConfig, SanitizedJoins } from './types.js'
|
||||
|
||||
import { authCollectionEndpoints } from '../../auth/endpoints/index.js'
|
||||
import { getBaseAuthFields } from '../../auth/getAuthFields.js'
|
||||
import { TimestampsRequired } from '../../errors/TimestampsRequired.js'
|
||||
import { sanitizeFields } from '../../fields/config/sanitize.js'
|
||||
import { fieldAffectsData } from '../../fields/config/types.js'
|
||||
import mergeBaseFields from '../../fields/mergeBaseFields.js'
|
||||
import { uploadCollectionEndpoints } from '../../uploads/endpoints/index.js'
|
||||
import { getBaseUploadFields } from '../../uploads/getBaseFields.js'
|
||||
import { deepMergeWithReactComponents } from '../../utilities/deepMerge.js'
|
||||
import { flattenAllFields } from '../../utilities/flattenAllFields.js'
|
||||
@@ -60,18 +58,6 @@ export const sanitizeCollection = async (
|
||||
sanitized.endpoints = []
|
||||
}
|
||||
|
||||
if (sanitized.auth) {
|
||||
for (const endpoint of authCollectionEndpoints) {
|
||||
sanitized.endpoints.push(endpoint)
|
||||
}
|
||||
}
|
||||
|
||||
if (sanitized.upload) {
|
||||
for (const endpoint of uploadCollectionEndpoints) {
|
||||
sanitized.endpoints.push(endpoint)
|
||||
}
|
||||
}
|
||||
|
||||
for (const endpoint of defaultCollectionEndpoints) {
|
||||
sanitized.endpoints.push(endpoint)
|
||||
}
|
||||
|
||||
@@ -1,7 +1,13 @@
|
||||
import type { GraphQLInputObjectType, GraphQLNonNull, GraphQLObjectType } from 'graphql'
|
||||
import type { DeepRequired, IsAny, MarkOptional } from 'ts-essentials'
|
||||
|
||||
import type { CustomUpload } from '../../admin/types.js'
|
||||
import type {
|
||||
CustomPreviewButton,
|
||||
CustomPublishButton,
|
||||
CustomSaveButton,
|
||||
CustomSaveDraftButton,
|
||||
CustomUpload,
|
||||
} from '../../admin/types.js'
|
||||
import type { Arguments as MeArguments } from '../../auth/operations/me.js'
|
||||
import type {
|
||||
Arguments as RefreshArguments,
|
||||
@@ -281,30 +287,29 @@ export type CollectionAdminOptions = {
|
||||
/**
|
||||
* Replaces the "Preview" button
|
||||
*/
|
||||
PreviewButton?: CustomComponent
|
||||
PreviewButton?: CustomPreviewButton
|
||||
/**
|
||||
* Replaces the "Publish" button
|
||||
* + drafts must be enabled
|
||||
*/
|
||||
PublishButton?: CustomComponent
|
||||
PublishButton?: CustomPublishButton
|
||||
/**
|
||||
* Replaces the "Save" button
|
||||
* + drafts must be disabled
|
||||
*/
|
||||
SaveButton?: CustomComponent
|
||||
SaveButton?: CustomSaveButton
|
||||
/**
|
||||
* Replaces the "Save Draft" button
|
||||
* + drafts must be enabled
|
||||
* + autosave must be disabled
|
||||
*/
|
||||
SaveDraftButton?: CustomComponent
|
||||
SaveDraftButton?: CustomSaveDraftButton
|
||||
/**
|
||||
* Replaces the "Upload" section
|
||||
* + upload must be enabled
|
||||
*/
|
||||
Upload?: CustomUpload
|
||||
}
|
||||
listMenuItems?: CustomComponent[]
|
||||
views?: {
|
||||
/**
|
||||
* Set to a React component to replace the entire Edit View, including all nested routes.
|
||||
|
||||
@@ -3,7 +3,7 @@ import type { BatchLoadFn } from 'dataloader'
|
||||
|
||||
import DataLoader from 'dataloader'
|
||||
|
||||
import type { PayloadRequest, PopulateType, SelectType } from '../types/index.js'
|
||||
import type { PayloadRequest, SelectType } from '../types/index.js'
|
||||
import type { TypeWithID } from './config/types.js'
|
||||
|
||||
import { isValidID } from '../utilities/isValidID.js'
|
||||
@@ -57,7 +57,6 @@ const batchAndLoadDocs =
|
||||
showHiddenFields,
|
||||
draft,
|
||||
select,
|
||||
populate,
|
||||
] = JSON.parse(key)
|
||||
|
||||
const batchKeyArray = [
|
||||
@@ -71,7 +70,6 @@ const batchAndLoadDocs =
|
||||
showHiddenFields,
|
||||
draft,
|
||||
select,
|
||||
populate,
|
||||
]
|
||||
|
||||
const batchKey = JSON.stringify(batchKeyArray)
|
||||
@@ -109,7 +107,6 @@ const batchAndLoadDocs =
|
||||
showHiddenFields,
|
||||
draft,
|
||||
select,
|
||||
populate,
|
||||
] = JSON.parse(batchKey)
|
||||
|
||||
req.transactionID = transactionID
|
||||
@@ -124,7 +121,6 @@ const batchAndLoadDocs =
|
||||
locale,
|
||||
overrideAccess: Boolean(overrideAccess),
|
||||
pagination: false,
|
||||
populate,
|
||||
req,
|
||||
select,
|
||||
showHiddenFields: Boolean(showHiddenFields),
|
||||
@@ -148,7 +144,6 @@ const batchAndLoadDocs =
|
||||
fallbackLocale,
|
||||
locale,
|
||||
overrideAccess,
|
||||
populate,
|
||||
select,
|
||||
showHiddenFields,
|
||||
transactionID: req.transactionID,
|
||||
@@ -178,7 +173,6 @@ type CreateCacheKeyArgs = {
|
||||
fallbackLocale: string
|
||||
locale: string
|
||||
overrideAccess: boolean
|
||||
populate?: PopulateType
|
||||
select?: SelectType
|
||||
showHiddenFields: boolean
|
||||
transactionID: number | Promise<number | string> | string
|
||||
@@ -192,7 +186,6 @@ export const createDataloaderCacheKey = ({
|
||||
fallbackLocale,
|
||||
locale,
|
||||
overrideAccess,
|
||||
populate,
|
||||
select,
|
||||
showHiddenFields,
|
||||
transactionID,
|
||||
@@ -209,5 +202,4 @@ export const createDataloaderCacheKey = ({
|
||||
showHiddenFields,
|
||||
draft,
|
||||
select,
|
||||
populate,
|
||||
])
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import type { Endpoint } from '../../config/types.js'
|
||||
|
||||
import { authCollectionEndpoints } from '../../auth/endpoints/index.js'
|
||||
import { wrapInternalEndpoints } from '../../utilities/wrapInternalEndpoints.js'
|
||||
import { countHandler } from './count.js'
|
||||
import { createHandler } from './create.js'
|
||||
@@ -11,12 +12,15 @@ import { findHandler } from './find.js'
|
||||
import { findByIDHandler } from './findByID.js'
|
||||
import { findVersionByIDHandler } from './findVersionByID.js'
|
||||
import { findVersionsHandler } from './findVersions.js'
|
||||
import { getFileHandler } from './getFile.js'
|
||||
import { getFileFromURLHandler } from './getFileFromURL.js'
|
||||
import { previewHandler } from './preview.js'
|
||||
import { restoreVersionHandler } from './restoreVersion.js'
|
||||
import { updateHandler } from './update.js'
|
||||
import { updateByIDHandler } from './updateByID.js'
|
||||
|
||||
export const defaultCollectionEndpoints: Endpoint[] = [
|
||||
...authCollectionEndpoints,
|
||||
...wrapInternalEndpoints([
|
||||
{
|
||||
handler: countHandler,
|
||||
@@ -43,6 +47,11 @@ export const defaultCollectionEndpoints: Endpoint[] = [
|
||||
method: 'post',
|
||||
path: '/access/:id?',
|
||||
},
|
||||
{
|
||||
handler: getFileFromURLHandler,
|
||||
method: 'get',
|
||||
path: '/paste-url/:id?',
|
||||
},
|
||||
{
|
||||
handler: findVersionsHandler,
|
||||
method: 'get',
|
||||
@@ -68,6 +77,11 @@ export const defaultCollectionEndpoints: Endpoint[] = [
|
||||
method: 'get',
|
||||
path: '/versions/:id',
|
||||
},
|
||||
{
|
||||
handler: getFileHandler,
|
||||
method: 'get',
|
||||
path: '/file/:filename',
|
||||
},
|
||||
{
|
||||
handler: previewHandler,
|
||||
method: 'get',
|
||||
|
||||
@@ -14,16 +14,18 @@ import type { JSONSchema4 } from 'json-schema'
|
||||
import type { DestinationStream, Level, pino } from 'pino'
|
||||
import type React from 'react'
|
||||
import type { default as sharp } from 'sharp'
|
||||
import type { DeepRequired } from 'ts-essentials'
|
||||
import type { DeepRequired, MarkOptional } from 'ts-essentials'
|
||||
|
||||
import type { RichTextAdapterProvider } from '../admin/RichText.js'
|
||||
import type { DocumentTabConfig, RichTextAdapter } from '../admin/types.js'
|
||||
import type {
|
||||
AdminViewConfig,
|
||||
DocumentSubViewTypes,
|
||||
DocumentTabConfig,
|
||||
DocumentViewServerProps,
|
||||
RichTextAdapter,
|
||||
} from '../admin/types.js'
|
||||
import type { AdminViewConfig, ViewTypes, VisibleEntities } from '../admin/views/index.js'
|
||||
ServerPropsFromView,
|
||||
ServerSideEditViewProps,
|
||||
ViewTypes,
|
||||
VisibleEntities,
|
||||
} from '../admin/views/types.js'
|
||||
import type { SanitizedPermissions } from '../auth/index.js'
|
||||
import type {
|
||||
AddToImportMap,
|
||||
@@ -381,7 +383,7 @@ export type Endpoint = {
|
||||
root?: never
|
||||
}
|
||||
|
||||
export type EditViewComponent = PayloadComponent<DocumentViewServerProps>
|
||||
export type EditViewComponent = PayloadComponent<ServerSideEditViewProps>
|
||||
|
||||
export type EditViewConfig = {
|
||||
meta?: MetaConfig
|
||||
@@ -405,20 +407,22 @@ export type EditViewConfig = {
|
||||
}
|
||||
)
|
||||
|
||||
export type Params = { [key: string]: string | string[] | undefined }
|
||||
type ClientProps = {
|
||||
readonly [key: string]: unknown
|
||||
}
|
||||
|
||||
export type ServerProps = {
|
||||
readonly documentSubViewType?: DocumentSubViewTypes
|
||||
readonly i18n: I18nClient
|
||||
readonly locale?: Locale
|
||||
readonly params?: Params
|
||||
readonly params?: { [key: string]: string | string[] | undefined }
|
||||
readonly payload: Payload
|
||||
readonly permissions?: SanitizedPermissions
|
||||
readonly searchParams?: Params
|
||||
readonly searchParams?: { [key: string]: string | string[] | undefined }
|
||||
readonly user?: TypedUser
|
||||
readonly viewType?: ViewTypes
|
||||
readonly visibleEntities?: VisibleEntities
|
||||
}
|
||||
} & ClientProps
|
||||
|
||||
export const serverProps: (keyof ServerProps)[] = [
|
||||
'payload',
|
||||
@@ -761,7 +765,7 @@ export type Config = {
|
||||
/**
|
||||
* Add extra and/or replace built-in components with custom components
|
||||
*
|
||||
* @see https://payloadcms.com/docs/admin/custom-components/overview
|
||||
* @see https://payloadcms.com/docs/admin/components
|
||||
*/
|
||||
components?: {
|
||||
/**
|
||||
@@ -1270,3 +1274,5 @@ export type EntityDescriptionFunction = ({ t }: { t: TFunction }) => string
|
||||
export type EntityDescription = EntityDescriptionFunction | Record<string, string> | string
|
||||
|
||||
export type { EmailAdapter, SendEmailOptions }
|
||||
|
||||
export type { DocumentSubViewTypes, ServerPropsFromView, ViewTypes }
|
||||
|
||||
@@ -4,6 +4,7 @@ import type { JoinQuery, PayloadRequest } from '../types/index.js'
|
||||
|
||||
import executeAccess from '../auth/executeAccess.js'
|
||||
import { QueryError } from '../errors/QueryError.js'
|
||||
import { deepCopyObjectSimple } from '../utilities/deepCopyObject.js'
|
||||
import { combineQueries } from './combineQueries.js'
|
||||
import { validateQueryPaths } from './queryValidation/validateQueryPaths.js'
|
||||
|
||||
|
||||
@@ -72,7 +72,6 @@ const populate = async ({
|
||||
fallbackLocale,
|
||||
locale,
|
||||
overrideAccess,
|
||||
populate: populateArg,
|
||||
select:
|
||||
populateArg?.[relatedCollection.config.slug] ??
|
||||
relatedCollection.config.defaultPopulate,
|
||||
|
||||
@@ -146,7 +146,6 @@ export type JoinQuery<TSlug extends CollectionSlug = string> =
|
||||
[K in keyof TypedCollectionJoins[TSlug]]:
|
||||
| {
|
||||
limit?: number
|
||||
page?: number
|
||||
sort?: string
|
||||
where?: Where
|
||||
}
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
import type { Endpoint } from '../../config/types.js'
|
||||
|
||||
import { wrapInternalEndpoints } from '../../utilities/wrapInternalEndpoints.js'
|
||||
import { getFileHandler } from './getFile.js'
|
||||
import { getFileFromURLHandler } from './getFileFromURL.js'
|
||||
|
||||
export const uploadCollectionEndpoints: Endpoint[] = wrapInternalEndpoints([
|
||||
{
|
||||
handler: getFileFromURLHandler,
|
||||
method: 'get',
|
||||
path: '/paste-url/:id?',
|
||||
},
|
||||
{
|
||||
handler: getFileHandler,
|
||||
method: 'get',
|
||||
path: '/file/:filename',
|
||||
},
|
||||
])
|
||||
@@ -181,14 +181,6 @@ export type UploadConfig = {
|
||||
params: { collection: string; filename: string }
|
||||
},
|
||||
) => Promise<Response> | Promise<void> | Response | void)[]
|
||||
/**
|
||||
* Set to `true` to prevent the admin UI from showing file inputs during document creation, useful for programmatic file generation.
|
||||
*/
|
||||
hideFileInputOnCreate?: boolean
|
||||
/**
|
||||
* Set to `true` to prevent the admin UI having a way to remove an existing file while editing.
|
||||
*/
|
||||
hideRemoveFile?: boolean
|
||||
imageSizes?: ImageSize[]
|
||||
/**
|
||||
* Restrict mimeTypes in the file picker. Array of valid mime types or mimetype wildcards
|
||||
|
||||
@@ -28,7 +28,6 @@ export const sanitizeJoinParams = (
|
||||
} else {
|
||||
joinQuery[schemaPath] = {
|
||||
limit: isNumber(joins[schemaPath]?.limit) ? Number(joins[schemaPath].limit) : undefined,
|
||||
page: isNumber(joins[schemaPath]?.page) ? Number(joins[schemaPath].page) : undefined,
|
||||
sort: joins[schemaPath]?.sort ? joins[schemaPath].sort : undefined,
|
||||
where: joins[schemaPath]?.where ? joins[schemaPath].where : undefined,
|
||||
}
|
||||
|
||||
@@ -92,7 +92,7 @@ const traverseArrayOrBlocksField = ({
|
||||
}
|
||||
}
|
||||
|
||||
export type TraverseFieldsCallback<T = unknown> = (args: {
|
||||
export type TraverseFieldsCallback = (args: {
|
||||
/**
|
||||
* The current field
|
||||
*/
|
||||
@@ -105,11 +105,11 @@ export type TraverseFieldsCallback<T = unknown> = (args: {
|
||||
/**
|
||||
* The parent reference object
|
||||
*/
|
||||
parentRef: Record<string, T> | T
|
||||
parentRef?: Record<string, unknown> | unknown
|
||||
/**
|
||||
* The current reference object
|
||||
*/
|
||||
ref: Record<string, T> | T
|
||||
ref?: Record<string, unknown> | unknown
|
||||
}) => boolean | void
|
||||
|
||||
type TraverseFieldsArgs = {
|
||||
@@ -140,7 +140,7 @@ type TraverseFieldsArgs = {
|
||||
* @param ref the data or any artifacts assigned in the callback during field recursion
|
||||
* @param parentRef the data or any artifacts assigned in the callback during field recursion one level up
|
||||
*/
|
||||
export const traverseFields = <T = unknown>({
|
||||
export const traverseFields = ({
|
||||
callback,
|
||||
callbackStack: _callbackStack = [],
|
||||
config,
|
||||
@@ -151,7 +151,7 @@ export const traverseFields = <T = unknown>({
|
||||
parentIsLocalized,
|
||||
parentRef = {},
|
||||
ref = {},
|
||||
}: TraverseFieldsArgs<T>): void => {
|
||||
}: TraverseFieldsArgs): void => {
|
||||
fields.some((field) => {
|
||||
let callbackStack: (() => ReturnType<TraverseFieldsCallback>)[] = []
|
||||
if (!isTopLevel) {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user