Skip to content

Commit 4e2e4d2

Browse files
authored
feat(next): version view overhaul (#12027)
#11769 improved the lexical version view diff component. This PR improves the rest of the version view. ## What changed - Column layout when selecting a version: - Previously: Selected version on the left, latest version on the left - Now: Previous version on the left, previous version on the right (mimics behavior of GitHub) - Locale selector now displayed in pill selector, rather than react-select - Smoother, more reliable locale, modifiedOnly and version selection. Now uses clean event callbacks rather than useEffects - React-diff-viewer-continued has been replaced with the html differ we use in lexical - Updated Design for all field diffs - Version columns now have a clearly defined separator line - Fixed collapsibles showing in version view despite having no modified fields if modifiedOnly is true - New, redesigned header ## Screenshots ### Before ![CleanShot 2025-04-11 at 20 10 03@2x](https://github.com/user-attachments/assets/a93a500a-3cdd-4cf0-84dd-cf5481aac2b3) ![CleanShot 2025-04-11 at 20 10 28@2x](https://github.com/user-attachments/assets/59bc5885-cbaf-49ea-8d1d-8d145463fd80) ### After ![Screenshot 2025-06-09 at 17 43 49@2x](https://github.com/user-attachments/assets/f6ff0369-76c9-4c1c-9aa7-cbd88806ddc1) ![Screenshot 2025-06-09 at 17 44 50@2x](https://github.com/user-attachments/assets/db93a3db-48d6-4e5d-b080-86a34fff5d22) ![Screenshot 2025-06-09 at 17 45 19@2x](https://github.com/user-attachments/assets/27b6c720-05fe-4957-85af-1305d6b65cfd) ![Screenshot 2025-06-09 at 17 45 34@2x](https://github.com/user-attachments/assets/6d42f458-515a-4611-b27a-f4d6bafbf555)
1 parent 9943b35 commit 4e2e4d2

File tree

182 files changed

+4779
-2195
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

182 files changed

+4779
-2195
lines changed

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@
6464
"clean:build": "node ./scripts/delete-recursively.js 'media/' '**/dist/' '**/.cache/' '**/.next/' '**/.turbo/' '**/tsconfig.tsbuildinfo' '**/payload*.tgz' '**/meta_*.json'",
6565
"clean:build:allowtgz": "node ./scripts/delete-recursively.js 'media/' '**/dist/' '**/.cache/' '**/.next/' '**/.turbo/' '**/tsconfig.tsbuildinfo' '**/meta_*.json'",
6666
"clean:cache": "node ./scripts/delete-recursively.js node_modules/.cache! packages/payload/node_modules/.cache! .next/*",
67-
"dev": "cross-env NODE_OPTIONS=--no-deprecation tsx ./test/dev.ts",
67+
"dev": "cross-env NODE_OPTIONS=\"--no-deprecation --max-old-space-size=16384\" tsx ./test/dev.ts",
6868
"dev:generate-db-schema": "pnpm runts ./test/generateDatabaseSchema.ts",
6969
"dev:generate-graphql-schema": "pnpm runts ./test/generateGraphQLSchema.ts",
7070
"dev:generate-importmap": "pnpm runts ./test/generateImportMap.ts",
@@ -111,7 +111,7 @@
111111
"test:int:sqlite": "cross-env NODE_OPTIONS=\"--no-deprecation --no-experimental-strip-types\" NODE_NO_WARNINGS=1 PAYLOAD_DATABASE=sqlite DISABLE_LOGGING=true jest --forceExit --detectOpenHandles --config=test/jest.config.js --runInBand",
112112
"test:types": "tstyche",
113113
"test:unit": "cross-env NODE_OPTIONS=\"--no-deprecation --no-experimental-strip-types\" NODE_NO_WARNINGS=1 DISABLE_LOGGING=true jest --forceExit --detectOpenHandles --config=jest.config.js --runInBand",
114-
"translateNewKeys": "pnpm --filter translations run translateNewKeys"
114+
"translateNewKeys": "pnpm --filter @tools/scripts run generateTranslations:core"
115115
},
116116
"lint-staged": {
117117
"**/package.json": "sort-package-json",

packages/next/package.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,6 @@
103103
"http-status": "2.1.0",
104104
"path-to-regexp": "6.3.0",
105105
"qs-esm": "7.0.2",
106-
"react-diff-viewer-continued": "4.0.5",
107106
"sass": "1.77.4",
108107
"uuid": "10.0.0"
109108
},

packages/next/src/utilities/handleServerFunctions.ts

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,17 @@ import { renderDocumentSlotsHandler } from '../views/Document/renderDocumentSlot
1111
import { renderListHandler } from '../views/List/handleServerFunction.js'
1212
import { initReq } from './initReq.js'
1313

14+
const serverFunctions: Record<string, ServerFunction> = {
15+
'copy-data-from-locale': copyDataFromLocaleHandler,
16+
'form-state': buildFormStateHandler,
17+
'get-folder-results-component-and-data': getFolderResultsComponentAndDataHandler,
18+
'render-document': renderDocumentHandler,
19+
'render-document-slots': renderDocumentSlotsHandler,
20+
'render-list': renderListHandler,
21+
'schedule-publish': schedulePublishHandler,
22+
'table-state': buildTableStateHandler,
23+
}
24+
1425
export const handleServerFunctions: ServerFunctionHandler = async (args) => {
1526
const { name: fnKey, args: fnArgs, config: configPromise, importMap } = args
1627

@@ -26,18 +37,6 @@ export const handleServerFunctions: ServerFunctionHandler = async (args) => {
2637
req,
2738
}
2839

29-
const serverFunctions = {
30-
'copy-data-from-locale': copyDataFromLocaleHandler as any as ServerFunction,
31-
'form-state': buildFormStateHandler as any as ServerFunction,
32-
'get-folder-results-component-and-data':
33-
getFolderResultsComponentAndDataHandler as any as ServerFunction,
34-
'render-document': renderDocumentHandler as any as ServerFunction,
35-
'render-document-slots': renderDocumentSlotsHandler as any as ServerFunction,
36-
'render-list': renderListHandler as any as ServerFunction,
37-
'schedule-publish': schedulePublishHandler as any as ServerFunction,
38-
'table-state': buildTableStateHandler as any as ServerFunction,
39-
}
40-
4140
const fn = serverFunctions[fnKey]
4241

4342
if (!fn) {

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,7 @@ export async function Account({ initPageResult, params, searchParams }: AdminVie
148148
importMap: payload.importMap,
149149
serverProps: {
150150
doc: data,
151+
hasPublishedDoc,
151152
i18n,
152153
initPageResult,
153154
locale,

packages/next/src/views/Document/handleServerFunction.tsx

Lines changed: 10 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,13 @@
1-
import type {
2-
Data,
3-
DocumentPreferences,
4-
FormState,
5-
Locale,
6-
PayloadRequest,
7-
VisibleEntities,
8-
} from 'payload'
1+
import type { RenderDocumentServerFunction } from '@payloadcms/ui'
2+
import type { DocumentPreferences, VisibleEntities } from 'payload'
93

104
import { getClientConfig } from '@payloadcms/ui/utilities/getClientConfig'
115
import { headers as getHeaders } from 'next/headers.js'
126
import { getAccessResults, isEntityHidden, parseCookies } from 'payload'
137

148
import { renderDocument } from './index.js'
159

16-
type RenderDocumentResult = {
17-
data: any
18-
Document: React.ReactNode
19-
preferences: DocumentPreferences
20-
}
21-
22-
export const renderDocumentHandler = async (args: {
23-
collectionSlug: string
24-
disableActions?: boolean
25-
docID: string
26-
drawerSlug?: string
27-
initialData?: Data
28-
initialState?: FormState
29-
locale?: Locale
30-
overrideEntityVisibility?: boolean
31-
redirectAfterCreate?: boolean
32-
redirectAfterDelete: boolean
33-
redirectAfterDuplicate: boolean
34-
req: PayloadRequest
35-
}): Promise<RenderDocumentResult> => {
10+
export const renderDocumentHandler: RenderDocumentServerFunction = async (args) => {
3611
const {
3712
collectionSlug,
3813
disableActions,
@@ -41,6 +16,7 @@ export const renderDocumentHandler = async (args: {
4116
initialData,
4217
locale,
4318
overrideEntityVisibility,
19+
paramsOverride,
4420
redirectAfterCreate,
4521
redirectAfterDelete,
4622
redirectAfterDuplicate,
@@ -51,6 +27,8 @@ export const renderDocumentHandler = async (args: {
5127
payload: { config },
5228
user,
5329
},
30+
searchParams = {},
31+
versions,
5432
} = args
5533

5634
const headers = await getHeaders()
@@ -163,14 +141,15 @@ export const renderDocumentHandler = async (args: {
163141
visibleEntities,
164142
},
165143
overrideEntityVisibility,
166-
params: {
167-
segments: ['collections', collectionSlug, docID],
144+
params: paramsOverride ?? {
145+
segments: ['collections', collectionSlug, String(docID)],
168146
},
169147
payload,
170148
redirectAfterCreate,
171149
redirectAfterDelete,
172150
redirectAfterDuplicate,
173-
searchParams: {},
151+
searchParams,
152+
versions,
174153
viewType: 'document',
175154
})
176155

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import type {
66
DocumentViewServerPropsOnly,
77
EditViewComponent,
88
PayloadComponent,
9+
RenderDocumentVersionsProperties,
910
} from 'payload'
1011

1112
import { DocumentInfoProvider, EditDepthProvider, HydrateAuthProvider } from '@payloadcms/ui'
@@ -57,13 +58,15 @@ export const renderDocument = async ({
5758
redirectAfterDelete,
5859
redirectAfterDuplicate,
5960
searchParams,
61+
versions,
6062
viewType,
6163
}: {
6264
drawerSlug?: string
6365
overrideEntityVisibility?: boolean
6466
readonly redirectAfterCreate?: boolean
6567
readonly redirectAfterDelete?: boolean
6668
readonly redirectAfterDuplicate?: boolean
69+
versions?: RenderDocumentVersionsProperties
6770
} & AdminViewServerProps): Promise<{
6871
data: Data
6972
Document: React.ReactNode
@@ -178,6 +181,7 @@ export const renderDocument = async ({
178181

179182
const documentViewServerProps: DocumentViewServerPropsOnly = {
180183
doc,
184+
hasPublishedDoc,
181185
i18n,
182186
initPageResult,
183187
locale,
@@ -187,6 +191,7 @@ export const renderDocument = async ({
187191
routeSegments: segments,
188192
searchParams,
189193
user,
194+
versions,
190195
}
191196

192197
if (

packages/next/src/views/Document/renderDocumentSlots.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import type {
1111
SanitizedGlobalConfig,
1212
SaveButtonServerPropsOnly,
1313
SaveDraftButtonServerPropsOnly,
14+
ServerFunction,
1415
ServerProps,
1516
StaticDescription,
1617
ViewDescriptionClientProps,
@@ -168,8 +169,8 @@ export const renderDocumentSlots: (args: {
168169
return components
169170
}
170171

171-
export const renderDocumentSlotsHandler = async (
172-
args: { collectionSlug: string } & DefaultServerFunctionArgs,
172+
export const renderDocumentSlotsHandler: ServerFunction<{ collectionSlug: string }> = async (
173+
args,
173174
) => {
174175
const { collectionSlug, req } = args
175176

packages/next/src/views/List/handleServerFunction.tsx

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { ListPreferences, ListQuery, PayloadRequest, VisibleEntities } from 'payload'
1+
import type { ListPreferences, ListQuery, ServerFunction, VisibleEntities } from 'payload'
22

33
import { getClientConfig } from '@payloadcms/ui/utilities/getClientConfig'
44
import { headers as getHeaders } from 'next/headers.js'
@@ -11,21 +11,23 @@ type RenderListResult = {
1111
preferences: ListPreferences
1212
}
1313

14-
export const renderListHandler = async (args: {
15-
collectionSlug: string
16-
disableActions?: boolean
17-
disableBulkDelete?: boolean
18-
disableBulkEdit?: boolean
19-
disableQueryPresets?: boolean
20-
documentDrawerSlug: string
21-
drawerSlug?: string
22-
enableRowSelections: boolean
23-
overrideEntityVisibility?: boolean
24-
query: ListQuery
25-
redirectAfterDelete: boolean
26-
redirectAfterDuplicate: boolean
27-
req: PayloadRequest
28-
}): Promise<RenderListResult> => {
14+
export const renderListHandler: ServerFunction<
15+
{
16+
collectionSlug: string
17+
disableActions?: boolean
18+
disableBulkDelete?: boolean
19+
disableBulkEdit?: boolean
20+
disableQueryPresets?: boolean
21+
documentDrawerSlug: string
22+
drawerSlug?: string
23+
enableRowSelections: boolean
24+
overrideEntityVisibility?: boolean
25+
query: ListQuery
26+
redirectAfterDelete: boolean
27+
redirectAfterDuplicate: boolean
28+
},
29+
Promise<RenderListResult>
30+
> = async (args) => {
2931
const {
3032
collectionSlug,
3133
disableActions,

0 commit comments

Comments
 (0)