Compare commits

...

2 Commits

Author SHA1 Message Date
Jacob Fletcher
e75b0e5aad threads through upload field 2025-04-29 10:45:44 -04:00
Jacob Fletcher
a0caab4e6f perf: supports admin.select on relationship and upload fields 2025-04-29 10:31:44 -04:00
8 changed files with 65 additions and 7 deletions

View File

@@ -129,6 +129,11 @@ export const sanitizeFields = async ({
})
}
// If `admin.select` is present, ensure that it includes `id`
if (field.admin?.select && !field.admin.select.id) {
field.admin.select.id = true
}
if (field.min && !field.minRows) {
console.warn(
`(payload): The "min" property is deprecated for the Relationship field "${field.name}" and will be removed in a future version. Please use "minRows" instead.`,

View File

@@ -141,6 +141,7 @@ import type {
JsonObject,
Operation,
PayloadRequest,
SelectType,
Where,
} from '../../types/index.js'
import type {
@@ -969,9 +970,17 @@ type UploadAdmin = {
>
} & Admin['components']
isSortable?: boolean
/**
* Specify the fields to be queried when populating the relationship.
* If not provided, all fields will be selected.
* This is useful for performance optimization, especially in large collections.
* The `id` field will be automatically included in the selection.
* @example { select: { title: true, slug: true } }
*/
select?: SelectType
} & Admin
type UploadAdminClient = AdminClient & Pick<UploadAdmin, 'allowCreate' | 'isSortable'>
type UploadAdminClient = AdminClient & Pick<UploadAdmin, 'allowCreate' | 'isSortable' | 'select'>
export type PolymorphicUploadField = {
admin?: {
@@ -1160,10 +1169,18 @@ type RelationshipAdmin = {
>
} & Admin['components']
isSortable?: boolean
/**
* Specify the fields to be queried when populating the relationship.
* If not provided, all fields will be selected.
* This is useful for performance optimization, especially in large collections.
* The `id` field will be automatically included in the selection.
* @example { select: { title: true, slug: true } }
*/
select?: SelectType
} & Admin
type RelationshipAdminClient = AdminClient &
Pick<RelationshipAdmin, 'allowCreate' | 'allowEdit' | 'appearance' | 'isSortable'>
Pick<RelationshipAdmin, 'allowCreate' | 'allowEdit' | 'appearance' | 'isSortable' | 'select'>
export type PolymorphicRelationshipField = {
admin?: {

View File

@@ -56,6 +56,7 @@ const RelationshipFieldComponent: RelationshipFieldClientComponent = (props) =>
className,
description,
isSortable = true,
select,
sortOptions,
} = {},
hasMany,
@@ -271,6 +272,7 @@ const RelationshipFieldComponent: RelationshipFieldClientComponent = (props) =>
limit: maxResultsPerRequest,
locale,
page: lastLoadedPageToUse,
select,
sort: fieldToSort,
where: {
and: [
@@ -367,6 +369,7 @@ const RelationshipFieldComponent: RelationshipFieldClientComponent = (props) =>
i18n,
config,
t,
select,
],
)

View File

@@ -5,6 +5,7 @@ import type {
FieldLabelClientProps,
FilterOptionsResult,
JsonObject,
SelectType,
StaticDescription,
StaticLabel,
UploadFieldClient,
@@ -71,6 +72,7 @@ export type UploadInputProps = {
readonly readOnly?: boolean
readonly relationTo: UploadFieldType['relationTo']
readonly required?: boolean
readonly select?: SelectType
readonly serverURL?: string
readonly showError?: boolean
readonly style?: React.CSSProperties
@@ -100,6 +102,7 @@ export function UploadInput(props: UploadInputProps) {
readOnly,
relationTo,
required,
select,
serverURL,
showError,
style,
@@ -201,6 +204,7 @@ export function UploadInput(props: UploadInputProps) {
draft: true,
limit: ids.length,
locale: code,
select,
where: {
and: [
{
@@ -308,6 +312,7 @@ export function UploadInput(props: UploadInputProps) {
setMaxFiles,
path,
setCurrentActivePath,
select,
],
)

View File

@@ -20,7 +20,7 @@ export function UploadComponent(props: UploadFieldClientProps) {
const {
field,
field: {
admin: { allowCreate, className, description, isSortable } = {},
admin: { allowCreate, className, description, isSortable, select } = {},
hasMany,
label,
localized,
@@ -84,6 +84,7 @@ export function UploadComponent(props: UploadFieldClientProps) {
readOnly={readOnly || disabled}
relationTo={relationTo}
required={required}
select={select}
serverURL={config.serverURL}
showError={showError}
style={styles}

View File

@@ -1,7 +1,10 @@
import type { Page } from '@playwright/test'
import type { SelectType } from 'payload'
import { expect, test } from '@playwright/test'
import { addListFilter } from 'helpers/e2e/addListFilter.js'
import { assertRequestBody } from 'helpers/e2e/assertRequestBody.js'
import { assertResponseBody } from 'helpers/e2e/assertResponseBody.js'
import { navigateToDoc } from 'helpers/e2e/navigateToDoc.js'
import { openDocControls } from 'helpers/e2e/openDocControls.js'
import { openCreateDocDrawer, openDocDrawer } from 'helpers/e2e/toggleDocDrawer.js'
@@ -651,6 +654,20 @@ describe('relationship', () => {
await expect(page.locator(tableRowLocator)).toHaveCount(1)
})
test('should populate only selected fields', async () => {
await page.goto(url.create)
await assertRequestBody<{ select: SelectType }>(page, {
action: async () => {
await page.locator('#field-relationshipWithSelect').click()
},
url: `/api/${textFieldsSlug}`,
expect: (body) => {
return Boolean(body.select.title === true && body.select.id === true)
},
})
})
test('should be able to select relationship with drawer appearance', async () => {
await page.goto(url.create)
@@ -703,7 +720,7 @@ describe('relationship', () => {
test('should handle polymorphic relationship when `appearance: "drawer"`', async () => {
await page.goto(url.create)
const relationshipField = page.locator('#field-polymorphicRelationshipDrawer')
const relationshipField = page.locator('#field-relationshipDrawerPolymorphic')
await relationshipField.click()
const listDrawerContent = page.locator('.list-drawer').locator('.drawer__content')
await expect(listDrawerContent).toBeVisible()
@@ -818,7 +835,7 @@ describe('relationship', () => {
test('should filter out existing values from polymorphic relationship list drawer', async () => {
await page.goto(url.create)
const relationshipField = page.locator('#field-polymorphicRelationshipDrawer')
const relationshipField = page.locator('#field-relationshipDrawerPolymorphic')
await relationshipField.click()
const listDrawerContent = page.locator('.list-drawer').locator('.drawer__content')
await expect(listDrawerContent).toBeVisible()

View File

@@ -126,6 +126,16 @@ const RelationshipFields: CollectionConfig = {
type: 'relationship',
hasMany: true,
},
{
name: 'relationshipWithSelect',
relationTo: 'text-fields',
type: 'relationship',
admin: {
select: {
text: true,
},
},
},
{
name: 'relationshipDrawer',
relationTo: 'text-fields',
@@ -142,7 +152,7 @@ const RelationshipFields: CollectionConfig = {
type: 'relationship',
},
{
name: 'polymorphicRelationshipDrawer',
name: 'relationshipDrawerPolymorphic',
admin: { appearance: 'drawer' },
type: 'relationship',
relationTo: ['text-fields', 'array-fields'],

View File

@@ -31,7 +31,7 @@
}
],
"paths": {
"@payload-config": ["./test/query-presets/config.ts"],
"@payload-config": ["./test/fields/config.ts"],
"@payloadcms/admin-bar": ["./packages/admin-bar/src"],
"@payloadcms/live-preview": ["./packages/live-preview/src"],
"@payloadcms/live-preview-react": ["./packages/live-preview-react/src/index.ts"],