diff --git a/docs/custom-components/edit-view.mdx b/docs/custom-components/edit-view.mdx index 92a4e3a778..af7f371ce5 100644 --- a/docs/custom-components/edit-view.mdx +++ b/docs/custom-components/edit-view.mdx @@ -293,7 +293,6 @@ Here's an example of a custom `editMenuItems` component: ```tsx import React from 'react' -import { PopupList } from '@payloadcms/ui' import type { EditMenuItemsServerProps } from 'payload' @@ -301,12 +300,12 @@ export const EditMenuItems = async (props: EditMenuItemsServerProps) => { const href = `/custom-action?id=${props.id}` return ( - - Custom Edit Menu Item - + <> + Custom Edit Menu Item + Another Custom Edit Menu Item - add as many as you need! - - + + ) } ``` diff --git a/packages/next/src/views/Document/renderDocumentSlots.tsx b/packages/next/src/views/Document/renderDocumentSlots.tsx index 8d5f7dbcc5..7b81e3daef 100644 --- a/packages/next/src/views/Document/renderDocumentSlots.tsx +++ b/packages/next/src/views/Document/renderDocumentSlots.tsx @@ -1,6 +1,5 @@ import type { BeforeDocumentControlsServerPropsOnly, - DefaultServerFunctionArgs, DocumentSlots, EditMenuItemsServerPropsOnly, PayloadRequest, @@ -39,6 +38,7 @@ export const renderDocumentSlots: (args: { const isPreviewEnabled = collectionConfig?.admin?.preview || globalConfig?.admin?.preview const serverProps: ServerProps = { + id: req.routeParams.id as number | string, i18n: req.i18n, payload: req.payload, user: req.user, diff --git a/packages/payload/src/config/types.ts b/packages/payload/src/config/types.ts index fdd2e460f6..82c6f132c9 100644 --- a/packages/payload/src/config/types.ts +++ b/packages/payload/src/config/types.ts @@ -402,6 +402,7 @@ export type Params = { [key: string]: string | string[] | undefined } export type ServerProps = { readonly documentSubViewType?: DocumentSubViewTypes readonly i18n: I18nClient + readonly id?: number | string readonly locale?: Locale readonly params?: Params readonly payload: Payload diff --git a/test/admin/collections/editMenuItems.ts b/test/admin/collections/editMenuItems.ts index f08f303528..278318c0d8 100644 --- a/test/admin/collections/editMenuItems.ts +++ b/test/admin/collections/editMenuItems.ts @@ -1,6 +1,6 @@ import type { CollectionConfig } from 'payload' -import { editMenuItemsSlug, postsCollectionSlug, uploadCollectionSlug } from '../slugs.js' +import { editMenuItemsSlug } from '../slugs.js' export const EditMenuItems: CollectionConfig = { slug: editMenuItemsSlug, @@ -11,6 +11,9 @@ export const EditMenuItems: CollectionConfig = { { path: '/components/EditMenuItems/index.js#EditMenuItems', }, + { + path: '/components/EditMenuItemsServer/index.js#EditMenuItemsServer', + }, ], }, }, diff --git a/test/admin/components/EditMenuItemsServer/index.tsx b/test/admin/components/EditMenuItemsServer/index.tsx new file mode 100644 index 0000000000..3bd5aaa334 --- /dev/null +++ b/test/admin/components/EditMenuItemsServer/index.tsx @@ -0,0 +1,13 @@ +import type { EditMenuItemsServerProps } from 'payload' + +import React from 'react' + +export const EditMenuItemsServer = (props: EditMenuItemsServerProps) => { + const href = `/custom-action?id=${props.id}` + + return ( +
+ Custom Edit Menu Item (Server) +
+ ) +} diff --git a/test/admin/e2e/document-view/e2e.spec.ts b/test/admin/e2e/document-view/e2e.spec.ts index a4705ae0ed..f793332a86 100644 --- a/test/admin/e2e/document-view/e2e.spec.ts +++ b/test/admin/e2e/document-view/e2e.spec.ts @@ -731,7 +731,7 @@ describe('Document View', () => { }) describe('custom editMenuItem components', () => { - test('should render custom editMenuItems component', async () => { + test('should render custom editMenuItems client component', async () => { await page.goto(editMenuItemsURL.create) await page.locator('#field-title')?.fill(title) await saveDocAndAssert(page) @@ -746,6 +746,51 @@ describe('Document View', () => { await expect(customEditMenuItem).toBeVisible() }) + + test('should render custom editMenuItems server component', async () => { + await page.goto(editMenuItemsURL.create) + await page.locator('#field-title')?.fill(title) + await saveDocAndAssert(page) + + const threeDotMenu = page.getByRole('main').locator('.doc-controls__popup') + await expect(threeDotMenu).toBeVisible() + await threeDotMenu.click() + + const popup = page.locator('.popup--active .popup__content') + await expect(popup).toBeVisible() + + const customEditMenuItem = popup.getByRole('link', { + name: 'Custom Edit Menu Item (Server)', + }) + + await expect(customEditMenuItem).toBeVisible() + }) + + test('should render doc id in href of custom editMenuItems server component link', async () => { + await page.goto(editMenuItemsURL.create) + await page.locator('#field-title')?.fill(title) + await saveDocAndAssert(page) + + const threeDotMenu = page.getByRole('main').locator('.doc-controls__popup') + await expect(threeDotMenu).toBeVisible() + await threeDotMenu.click() + + const popup = page.locator('.popup--active .popup__content') + await expect(popup).toBeVisible() + + const customEditMenuItem = popup.getByRole('link', { + name: 'Custom Edit Menu Item (Server)', + }) + + await expect(customEditMenuItem).toBeVisible() + + // Extract the document id from the edit page URL (last path segment) + const editPath = new URL(page.url()).pathname + const docId = editPath.split('/').filter(Boolean).pop()! + + // Assert the href contains the same id + await expect(customEditMenuItem).toHaveAttribute('href', `/custom-action?id=${docId}`) + }) }) })