Skip to content

Commit cb9b80a

Browse files
authored
fix!: handles custom collection description components (#7789)
## Description Closes #7784 by properly handling custom collection description components via `admin.components.Description`. This component was incorrectly added to the `admin.components.edit` key, and also was never handled on the front-end. This was especially misleading because the client-side config had a duplicative key in the proper position. ## Breaking Changes This PR is only labeled as a breaking change because the key has changed position within the config. If you were previously defining a custom description component on a collection, simply move it into the correct position: Old: ```ts { admin: { components: { edit: { Description: '' } } } } ``` New: ```ts { admin: { components: { Description: '' } } } ``` - [x] I have read and understand the [CONTRIBUTING.md](https://github.com/payloadcms/payload/blob/main/CONTRIBUTING.md) document in this repository. ## Type of change - [x] Bug fix (non-breaking change which fixes an issue) - [x] This change requires a documentation update ## Checklist: - [x] I have added tests that prove my fix is effective or that my feature works - [x] Existing test suite passes locally with my changes - [x] I have made corresponding changes to the documentation
1 parent cad1906 commit cb9b80a

File tree

14 files changed

+59
-37
lines changed

14 files changed

+59
-37
lines changed

docs/admin/collections.mdx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ The following options are available:
3131
| **`hidden`** | Set to true or a function, called with the current user, returning true to exclude this Collection from navigation and admin routing. |
3232
| **`hooks`** | Admin-specific hooks for this Collection. [More details](../hooks/collections). |
3333
| **`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. |
34-
| **`description`** | Text or React component to display below the Collection label in the List View to give editors more information. |
34+
| **`description`** | Text to display below the Collection label in the List View to give editors more information. Alternatively, you can use the `admin.components.Description` to render a React component. [More details](#components). |
3535
| **`defaultColumns`** | Array of field names that correspond to which columns to show by default in this Collection's List View. |
3636
| **`hideAPIURL`** | Hides the "API URL" meta field while editing documents within this Collection. |
3737
| **`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. |
@@ -69,7 +69,8 @@ The following options are available:
6969
| **`beforeList`** | An array of components to inject _before_ the built-in List View |
7070
| **`beforeListTable`** | An array of components to inject _before_ the built-in List View's table |
7171
| **`afterList`** | An array of components to inject _after_ the built-in List View |
72-
| **`afterListTable`** | An array of components to inject _after_ the built-in List View's table |
72+
| **`afterListTable`** | An array of components to inject _after_ the built-in List View's table
73+
| **`Description`** | A component to render below the Collection label in the List View. An alternative to the `admin.description` property. |
7374
| **`edit.SaveButton`** | Replace the default Save Button with a Custom Component. [Drafts](../versions/drafts) must be disabled. |
7475
| **`edit.SaveDraftButton`** | Replace the default Save Draft Button with a Custom Component. [Drafts](../versions/drafts) must be enabled and autosave must be disabled. |
7576
| **`edit.PublishButton`** | Replace the default Publish Button with a Custom Component. [Drafts](../versions/drafts) must be enabled. |

packages/next/src/views/List/Default/index.tsx

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ import {
1313
ListSelection,
1414
Pagination,
1515
PerPage,
16-
PopupList,
1716
PublishMany,
1817
RelationshipProvider,
1918
RenderComponent,
@@ -124,13 +123,9 @@ export const DefaultListView: React.FC = () => {
124123
{!smallBreak && (
125124
<ListSelection label={getTranslation(collectionConfig.labels.plural, i18n)} />
126125
)}
127-
{description && (
126+
{(description || Description) && (
128127
<div className={`${baseClass}__sub-header`}>
129-
<RenderComponent
130-
Component={ViewDescription}
131-
clientProps={{ description }}
132-
mappedComponent={Description}
133-
/>
128+
<ViewDescription Description={Description} description={description} />
134129
</div>
135130
)}
136131
</ListHeader>

packages/payload/src/bin/generateImportMap/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ export async function generateImportMap(
8585
if (shouldLog) {
8686
console.log('Generating import map')
8787
}
88+
8889
const importMap: InternalImportMap = {}
8990
const imports: Imports = {}
9091

packages/payload/src/bin/generateImportMap/iterateCollections.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,8 @@ export function iterateCollections({
3333
addToImportMap(collection.admin?.components?.afterListTable)
3434
addToImportMap(collection.admin?.components?.beforeList)
3535
addToImportMap(collection.admin?.components?.beforeListTable)
36+
addToImportMap(collection.admin?.components?.Description)
3637

37-
addToImportMap(collection.admin?.components?.edit?.Description)
3838
addToImportMap(collection.admin?.components?.edit?.PreviewButton)
3939
addToImportMap(collection.admin?.components?.edit?.PublishButton)
4040
addToImportMap(collection.admin?.components?.edit?.SaveButton)

packages/payload/src/collections/config/client.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ export type ClientCollectionConfig = {
2424
beforeList: MappedComponent[]
2525
beforeListTable: MappedComponent[]
2626
edit: {
27-
Description: MappedComponent
2827
PreviewButton: MappedComponent
2928
PublishButton: MappedComponent
3029
SaveButton: MappedComponent

packages/payload/src/collections/config/types.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,7 @@ export type CollectionAdminOptions = {
250250
* Custom admin components
251251
*/
252252
components?: {
253+
Description?: EntityDescriptionComponent
253254
afterList?: CustomComponent[]
254255
afterListTable?: CustomComponent[]
255256
beforeList?: CustomComponent[]
@@ -258,8 +259,6 @@ export type CollectionAdminOptions = {
258259
* Components within the edit view
259260
*/
260261
edit?: {
261-
Description?: EntityDescriptionComponent
262-
263262
/**
264263
* Replaces the "Preview" button
265264
*/

packages/ui/src/elements/ListDrawer/DrawerContent.tsx

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -251,9 +251,13 @@ export const ListDrawerContent: React.FC<ListDrawerProps> = ({
251251
<XIcon />
252252
</button>
253253
</div>
254-
{selectedCollectionConfig?.admin?.description && (
254+
{(selectedCollectionConfig?.admin?.description ||
255+
selectedCollectionConfig?.admin?.components?.Description) && (
255256
<div className={`${baseClass}__sub-header`}>
256-
<ViewDescription description={selectedCollectionConfig.admin.description} />
257+
<ViewDescription
258+
Description={selectedCollectionConfig.admin?.components?.Description}
259+
description={selectedCollectionConfig.admin?.description}
260+
/>
257261
</div>
258262
)}
259263
{moreThanOneAvailableCollection && (

packages/ui/src/elements/ViewDescription/index.tsx

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
'use client'
2-
import type { DescriptionFunction, StaticDescription } from 'payload'
2+
import type { DescriptionFunction, MappedComponent, StaticDescription } from 'payload'
33

44
import { getTranslation } from '@payloadcms/translations'
55
import React from 'react'
66

7+
import { RenderComponent } from '../../providers/Config/RenderComponent.js'
78
import { useTranslation } from '../../providers/Translation/index.js'
89
import './index.scss'
910

@@ -12,7 +13,8 @@ export type ViewDescriptionComponent = React.ComponentType<any>
1213
type Description = DescriptionFunction | StaticDescription | ViewDescriptionComponent | string
1314

1415
export type ViewDescriptionProps = {
15-
readonly description?: Description
16+
readonly Description?: MappedComponent
17+
readonly description?: StaticDescription
1618
}
1719

1820
export function isComponent(description: Description): description is ViewDescriptionComponent {
@@ -21,11 +23,10 @@ export function isComponent(description: Description): description is ViewDescri
2123

2224
export const ViewDescription: React.FC<ViewDescriptionProps> = (props) => {
2325
const { i18n } = useTranslation()
24-
const { description } = props
26+
const { Description, description, ...rest } = props
2527

26-
if (isComponent(description)) {
27-
const Description = description
28-
return <Description />
28+
if (Description) {
29+
return <RenderComponent clientProps={{ description, ...rest }} mappedComponent={Description} />
2930
}
3031

3132
if (description) {

packages/ui/src/providers/Config/createClientConfig/collections.tsx

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -224,21 +224,19 @@ export const createClientCollectionConfig = ({
224224

225225
clientCollection.admin.description = description
226226

227-
if (collection.admin.components.edit?.Description) {
228-
clientCollection.admin.components.edit.Description = createMappedComponent(
229-
collection.admin.components.edit.Description,
227+
if (collection.admin.components?.Description) {
228+
clientCollection.admin.components.Description = createMappedComponent(
229+
collection.admin.components.Description,
230230
{
231231
clientProps: {
232232
description,
233233
},
234234
},
235235
undefined,
236-
'collection.admin.components.edit.Description',
236+
'collection.admin.components.Description',
237237
)
238238
}
239239

240-
clientCollection.admin.description = description
241-
242240
clientCollection.admin.components.views = (
243241
collection?.admin?.components?.views
244242
? deepCopyObjectSimple(collection?.admin?.components?.views)

test/admin/collections/CustomViews1.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ export const CustomViews1: CollectionConfig = {
66
slug: customViews1CollectionSlug,
77
admin: {
88
components: {
9+
Description: '/components/ViewDescription/index.js#ViewDescription',
910
views: {
1011
// This will override the entire Edit View including all nested views, i.e. `/edit/:id/*`
1112
// To override one specific nested view, use the nested view's slug as the key

0 commit comments

Comments
 (0)