Skip to content

Commit a11243e

Browse files
authored
fix(ui): join field ignoring defaultSort and defaultLimit (#9766)
The join field was not respecting the defaultSort or defaultLimit of the field configuration. ### Why? This was never implemented. ### How? This fix applies these correct limit and sort properties to the query, first based on the field config and as a fallback, the collection configuration.
1 parent 19ddd3c commit a11243e

File tree

5 files changed

+77
-14
lines changed

5 files changed

+77
-14
lines changed

packages/payload/src/admin/functions/index.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import type { ImportMap } from '../../bin/generateImportMap/index.js'
22
import type { SanitizedConfig } from '../../config/types.js'
33
import type { PaginatedDocs } from '../../database/types.js'
4-
import type { PayloadRequest, Where } from '../../types/index.js'
4+
import type { PayloadRequest, Sort, Where } from '../../types/index.js'
55

66
export type DefaultServerFunctionArgs = {
77
importMap: ImportMap
@@ -43,7 +43,7 @@ export type ListQuery = {
4343
When provided, is automatically injected into the `where` object
4444
*/
4545
search?: string
46-
sort?: string
46+
sort?: Sort
4747
where?: Where
4848
}
4949

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

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1410,7 +1410,10 @@ export type JoinField = {
14101410
export type JoinFieldClient = {
14111411
admin?: AdminClient & Pick<JoinField['admin'], 'allowCreate' | 'disableBulkEdit' | 'readOnly'>
14121412
} & FieldBaseClient &
1413-
Pick<JoinField, 'collection' | 'index' | 'maxDepth' | 'on' | 'type' | 'where'>
1413+
Pick<
1414+
JoinField,
1415+
'collection' | 'defaultLimit' | 'defaultSort' | 'index' | 'maxDepth' | 'on' | 'type' | 'where'
1416+
>
14141417

14151418
export type FlattenedBlock = {
14161419
flattenedFields: FlattenedField[]

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

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ export const RelationshipTable: React.FC<RelationshipTableComponentProps> = (pro
5353
allowCreate = true,
5454
BeforeInput,
5555
disableTable = false,
56+
field,
5657
filterOptions,
5758
initialData: initialDataFromProps,
5859
initialDrawerData,
@@ -104,6 +105,8 @@ export const RelationshipTable: React.FC<RelationshipTableComponentProps> = (pro
104105
const renderTable = useCallback(
105106
async (docs?: PaginatedDocs['docs']) => {
106107
const newQuery: ListQuery = {
108+
limit: String(field.defaultLimit || collectionConfig.admin.pagination.defaultLimit),
109+
sort: field.defaultSort || collectionConfig.defaultSort,
107110
...(query || {}),
108111
where: { ...(query?.where || {}) },
109112
}
@@ -130,7 +133,16 @@ export const RelationshipTable: React.FC<RelationshipTableComponentProps> = (pro
130133
setColumnState(newColumnState)
131134
setIsLoadingTable(false)
132135
},
133-
[getTableState, relationTo, filterOptions, query],
136+
[
137+
query,
138+
field.defaultLimit,
139+
field.defaultSort,
140+
collectionConfig.admin.pagination.defaultLimit,
141+
collectionConfig.defaultSort,
142+
filterOptions,
143+
getTableState,
144+
relationTo,
145+
],
134146
)
135147

136148
useIgnoredEffect(
@@ -227,7 +239,9 @@ export const RelationshipTable: React.FC<RelationshipTableComponentProps> = (pro
227239
<ListQueryProvider
228240
collectionSlug={relationTo}
229241
data={data}
230-
defaultLimit={collectionConfig?.admin?.pagination?.defaultLimit}
242+
defaultLimit={
243+
field.defaultLimit ?? collectionConfig?.admin?.pagination?.defaultLimit
244+
}
231245
modifySearchParams={false}
232246
onQueryChange={setQuery}
233247
preferenceKey={preferenceKey}

packages/ui/src/providers/ListQuery/index.tsx

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
'use client'
2-
import type { ListQuery, PaginatedDocs, Where } from 'payload'
2+
import type { ListQuery, PaginatedDocs, Sort, Where } from 'payload'
33

44
import { useRouter, useSearchParams } from 'next/navigation.js'
55
import { isNumber } from 'payload/shared'
@@ -27,7 +27,7 @@ export type ListQueryProps = {
2727
readonly collectionSlug: string
2828
readonly data: PaginatedDocs
2929
readonly defaultLimit?: number
30-
readonly defaultSort?: string
30+
readonly defaultSort?: Sort
3131
readonly modifySearchParams?: boolean
3232
readonly onQueryChange?: (query: ListQuery) => void
3333
readonly preferenceKey?: string
@@ -36,7 +36,7 @@ export type ListQueryProps = {
3636
export type ListQueryContext = {
3737
data: PaginatedDocs
3838
defaultLimit?: number
39-
defaultSort?: string
39+
defaultSort?: Sort
4040
query: ListQuery
4141
refineListData: (args: ListQuery) => Promise<void>
4242
} & ContextHandlers
@@ -103,10 +103,13 @@ export const ListQueryProvider: React.FC<ListQueryProps> = ({
103103
}
104104

105105
const newQuery: ListQuery = {
106-
limit: 'limit' in query ? query.limit : (currentQuery?.limit as string),
106+
limit:
107+
'limit' in query
108+
? query.limit
109+
: ((currentQuery?.limit as string) ?? String(defaultLimit)),
107110
page: pageQuery as string,
108111
search: 'search' in query ? query.search : (currentQuery?.search as string),
109-
sort: 'sort' in query ? query.sort : (currentQuery?.sort as string),
112+
sort: 'sort' in query ? query.sort : ((currentQuery?.sort as string) ?? defaultSort),
110113
where: 'where' in query ? query.where : (currentQuery?.where as Where),
111114
}
112115

test/joins/e2e.spec.ts

Lines changed: 47 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@ import { reorderColumns } from 'helpers/e2e/reorderColumns.js'
55
import * as path from 'path'
66
import { fileURLToPath } from 'url'
77

8+
import type { PayloadTestSDK } from '../helpers/sdk/index.js'
9+
import type { Config } from './payload-types.js'
10+
811
import {
912
ensureCompilationIsDone,
1013
exactText,
@@ -20,6 +23,9 @@ import { categoriesSlug, postsSlug, uploadsSlug } from './shared.js'
2023
const filename = fileURLToPath(import.meta.url)
2124
const dirname = path.dirname(filename)
2225

26+
let payload: PayloadTestSDK<Config>
27+
let serverURL: string
28+
2329
test.describe('Admin Panel', () => {
2430
let page: Page
2531
let categoriesURL: AdminUrlUtil
@@ -28,8 +34,9 @@ test.describe('Admin Panel', () => {
2834

2935
test.beforeAll(async ({ browser }, testInfo) => {
3036
testInfo.setTimeout(TEST_TIMEOUT_LONG)
31-
32-
const { payload, serverURL } = await initPayloadE2ENoConfig({ dirname })
37+
;({ payload, serverURL } = await initPayloadE2ENoConfig<Config>({
38+
dirname,
39+
}))
3340
postsURL = new AdminUrlUtil(serverURL, postsSlug)
3441
categoriesURL = new AdminUrlUtil(serverURL, categoriesSlug)
3542
uploadsURL = new AdminUrlUtil(serverURL, uploadsSlug)
@@ -59,8 +66,44 @@ test.describe('Admin Panel', () => {
5966
const joinField = page.locator('#field-relatedPosts.field-type.join')
6067
await expect(joinField).toBeVisible()
6168
await expect(joinField.locator('.relationship-table table')).toBeVisible()
62-
const columns = await joinField.locator('.relationship-table tbody tr').count()
63-
expect(columns).toBe(3)
69+
const rows = joinField.locator('.relationship-table tbody tr')
70+
await expect(rows).toHaveCount(3)
71+
})
72+
73+
test('should apply defaultLimit and defaultSort on relationship table', async () => {
74+
const result = await payload.find({
75+
collection: categoriesSlug,
76+
limit: 1,
77+
})
78+
const category = result.docs[0]
79+
// seed additional posts to test defaultLimit (5)
80+
await payload.create({
81+
collection: postsSlug,
82+
data: {
83+
title: 'a',
84+
category: category.id,
85+
},
86+
})
87+
await payload.create({
88+
collection: postsSlug,
89+
data: {
90+
title: 'b',
91+
category: category.id,
92+
},
93+
})
94+
await payload.create({
95+
collection: postsSlug,
96+
data: {
97+
title: 'z',
98+
category: category.id,
99+
},
100+
})
101+
await navigateToDoc(page, categoriesURL)
102+
const joinField = page.locator('#field-relatedPosts.field-type.join')
103+
await expect(joinField.locator('.row-1 > .cell-title')).toContainText('z')
104+
await expect(joinField.locator('.paginator > .clickable-arrow--right')).toBeVisible()
105+
const rows = joinField.locator('.relationship-table tbody tr')
106+
await expect(rows).toHaveCount(5)
64107
})
65108

66109
test('should render join field for hidden posts', async () => {

0 commit comments

Comments
 (0)