Skip to content

Commit 39e9519

Browse files
authored
fix(next): prevent errors in globals version view (#12920)
### What? This PR fixes a runtime error that occurs when opening the "More versions..." drawer while browsing the versions for a global. It also fixes a minor runtime error when navigating to a global version view where an optional chaining operator was missing as the collection variable would be undefined as we are viewing a global. This PR also adds an e2e test to ensure the versions drawer is accessible and renders the appropriate number of versions for globals. ### Why? To properly render global version views without errors. ### How? By threading the global slug to the versions drawer and adjusting some properties of the `renderDocument` server function call there. This PR also adds an optional chaining operator the `versionUseAsTitle` in the original view to prevent an error in globals. Notes: - This was brought to my attention in Discord by a handful of users Before: (Missing optional chaining error) [error1-verions-Editing---Menu---Payload.webm](https://github.com/user-attachments/assets/3dc4dbe4-ee5a-43df-8d25-05128b05e063) Before: (Versions drawer error) [error2-versions-Editing---Menu---Payload.webm](https://github.com/user-attachments/assets/98c3e1da-cb0b-4a36-bafd-240f641e8814) After: [versions-globals-Dashboard---Payload.webm](https://github.com/user-attachments/assets/c778d3f0-a8fe-4e31-92cb-62da8e6d8cb4)
1 parent 886c07e commit 39e9519

File tree

6 files changed

+89
-18
lines changed

6 files changed

+89
-18
lines changed

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,7 @@ export const DefaultVersionView: React.FC<DefaultVersionsViewProps> = ({
238238
<SelectComparison
239239
collectionSlug={collectionSlug}
240240
docID={originalDocID}
241+
globalSlug={globalSlug}
241242
onChange={onChangeVersionFrom}
242243
versionFromID={versionFromID}
243244
versionFromOptions={versionFromOptions}

packages/next/src/views/Version/SelectComparison/VersionDrawer/index.tsx

Lines changed: 36 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,12 @@ export const formatVersionDrawerSlug = ({
2424
}) => `version-drawer_${depth}_${uuid}`
2525

2626
export const VersionDrawerContent: React.FC<{
27-
collectionSlug: string
28-
docID: number | string
27+
collectionSlug?: string
28+
docID?: number | string
2929
drawerSlug: string
30+
globalSlug?: string
3031
}> = (props) => {
31-
const { collectionSlug, docID, drawerSlug } = props
32+
const { collectionSlug, docID, drawerSlug, globalSlug } = props
3233
const { closeModal } = useModal()
3334
const searchParams = useSearchParams()
3435
const prevSearchParams = useRef(searchParams)
@@ -46,12 +47,20 @@ export const VersionDrawerContent: React.FC<{
4647
setIsLoading(true)
4748

4849
try {
50+
const isGlobal = Boolean(globalSlug)
51+
const entitySlug = collectionSlug ?? globalSlug
52+
4953
const result = await renderDocument({
50-
collectionSlug,
54+
collectionSlug: entitySlug,
5155
docID,
5256
drawerSlug,
5357
paramsOverride: {
54-
segments: ['collections', collectionSlug, String(docID), 'versions'],
58+
segments: [
59+
isGlobal ? 'globals' : 'collections',
60+
entitySlug,
61+
isGlobal ? undefined : String(docID),
62+
'versions',
63+
].filter(Boolean),
5564
},
5665
redirectAfterDelete: false,
5766
redirectAfterDuplicate: false,
@@ -75,7 +84,7 @@ export const VersionDrawerContent: React.FC<{
7584

7685
void fetchDocumentView()
7786
},
78-
[closeModal, collectionSlug, drawerSlug, renderDocument, searchParams, t],
87+
[closeModal, collectionSlug, globalSlug, drawerSlug, renderDocument, searchParams, t],
7988
)
8089

8190
useEffect(() => {
@@ -93,11 +102,12 @@ export const VersionDrawerContent: React.FC<{
93102
return DocumentView
94103
}
95104
export const VersionDrawer: React.FC<{
96-
collectionSlug: string
97-
docID: number | string
105+
collectionSlug?: string
106+
docID?: number | string
98107
drawerSlug: string
108+
globalSlug?: string
99109
}> = (props) => {
100-
const { collectionSlug, docID, drawerSlug } = props
110+
const { collectionSlug, docID, drawerSlug, globalSlug } = props
101111
const { t } = useTranslation()
102112

103113
return (
@@ -107,17 +117,24 @@ export const VersionDrawer: React.FC<{
107117
slug={drawerSlug}
108118
title={t('version:selectVersionToCompare')}
109119
>
110-
<VersionDrawerContent collectionSlug={collectionSlug} docID={docID} drawerSlug={drawerSlug} />
120+
<VersionDrawerContent
121+
collectionSlug={collectionSlug}
122+
docID={docID}
123+
drawerSlug={drawerSlug}
124+
globalSlug={globalSlug}
125+
/>
111126
</Drawer>
112127
)
113128
}
114129

115130
export const useVersionDrawer = ({
116131
collectionSlug,
117132
docID,
133+
globalSlug,
118134
}: {
119-
collectionSlug: string
120-
docID: number | string
135+
collectionSlug?: string
136+
docID?: number | string
137+
globalSlug?: string
121138
}) => {
122139
const drawerDepth = useEditDepth()
123140
const uuid = useId()
@@ -147,9 +164,14 @@ export const useVersionDrawer = ({
147164

148165
const MemoizedDrawer = useMemo(() => {
149166
return () => (
150-
<VersionDrawer collectionSlug={collectionSlug} docID={docID} drawerSlug={drawerSlug} />
167+
<VersionDrawer
168+
collectionSlug={collectionSlug}
169+
docID={docID}
170+
drawerSlug={drawerSlug}
171+
globalSlug={globalSlug}
172+
/>
151173
)
152-
}, [collectionSlug, docID, drawerSlug])
174+
}, [collectionSlug, docID, drawerSlug, globalSlug])
153175

154176
return useMemo(
155177
() => ({

packages/next/src/views/Version/SelectComparison/index.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,14 @@ export const SelectComparison: React.FC<Props> = memo((props) => {
1717
const {
1818
collectionSlug,
1919
docID,
20+
globalSlug,
2021
onChange: onChangeFromProps,
2122
versionFromID,
2223
versionFromOptions,
2324
} = props
2425
const { t } = useTranslation()
2526

26-
const { Drawer, openDrawer } = useVersionDrawer({ collectionSlug, docID })
27+
const { Drawer, openDrawer } = useVersionDrawer({ collectionSlug, docID, globalSlug })
2728

2829
const options = useMemo(() => {
2930
return [

packages/next/src/views/Version/SelectComparison/types.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,9 @@ import type { PaginatedDocs, SanitizedCollectionConfig } from 'payload'
33
import type { CompareOption } from '../Default/types.js'
44

55
export type Props = {
6-
collectionSlug: string
7-
docID: number | string
6+
collectionSlug?: string
7+
docID?: number | string
8+
globalSlug?: string
89
onChange: (val: CompareOption) => void
910
versionFromID?: string
1011
versionFromOptions: CompareOption[]

packages/next/src/views/Version/index.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -425,7 +425,7 @@ export async function VersionView(props: DocumentViewServerProps) {
425425
VersionToCreatedAtLabel={formatPill({ doc: versionTo, labelStyle: 'pill' })}
426426
versionToID={versionTo.id}
427427
versionToStatus={versionTo.version?._status}
428-
versionToUseAsTitle={versionTo[collectionConfig.admin?.useAsTitle || 'id']}
428+
versionToUseAsTitle={versionTo[collectionConfig?.admin?.useAsTitle || 'id']}
429429
/>
430430
)
431431
}

test/versions/e2e.spec.ts

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,7 @@ describe('Versions', () => {
205205
const fieldValue = autosaveRelationField.locator('.value-container')
206206
await expect(fieldValue).toContainText('test')
207207
})
208+
208209
test('should show collection versions view level action in collection versions view', async () => {
209210
await page.goto(url.list)
210211
await page.locator('tbody tr .cell-title a').first().click()
@@ -839,6 +840,51 @@ describe('Versions', () => {
839840
await page.goto(url.global(disablePublishGlobalSlug))
840841
await expect(page.locator('#action-save')).not.toBeAttached()
841842
})
843+
844+
test('global — should show versions drawer when SelectComparison more option is clicked', async () => {
845+
await payload.updateGlobal({
846+
slug: draftGlobalSlug,
847+
data: {
848+
title: 'initial title',
849+
},
850+
})
851+
await payload.updateGlobal({
852+
slug: draftGlobalSlug,
853+
data: {
854+
title: 'initial title 2',
855+
},
856+
})
857+
858+
const url = new AdminUrlUtil(serverURL, draftGlobalSlug)
859+
await page.goto(`${url.global(draftGlobalSlug)}/versions`)
860+
861+
const versionsTable = page.locator('.table table')
862+
await expect(versionsTable).toBeVisible()
863+
864+
const versionAnchor = versionsTable.locator('tbody tr.row-1 td.cell-updatedAt a')
865+
await expect(versionAnchor).toBeVisible()
866+
await versionAnchor.click()
867+
868+
const compareFromContainer = page.locator(
869+
'.view-version__version-from .field-type.compare-version',
870+
)
871+
await expect(compareFromContainer).toBeVisible()
872+
873+
const fromSelect = compareFromContainer.locator('.react-select .rs__control')
874+
await expect(fromSelect).toBeVisible()
875+
await fromSelect.click()
876+
877+
const moreVersions = compareFromContainer.locator('.rs__option:has-text("More versions...")')
878+
await expect(moreVersions).toBeVisible()
879+
await moreVersions.click()
880+
881+
const versionDrawer = page.locator('dialog.version-drawer')
882+
await expect(versionDrawer).toBeVisible()
883+
884+
const versionsDrawerTableBody = versionDrawer.locator('main.versions table tbody')
885+
await expect(versionsDrawerTableBody).toBeVisible()
886+
await expect(versionsDrawerTableBody.locator('tr')).toHaveCount(2)
887+
})
842888
})
843889

844890
describe('Scheduled publish', () => {

0 commit comments

Comments
 (0)