Skip to content

Commit 9691e42

Browse files
authored
fix(ui): preserve polymorphic upload bulk select relation (#17112)
Port of #16695 to `3.x`
1 parent ac000e5 commit 9691e42

6 files changed

Lines changed: 87 additions & 5 deletions

File tree

packages/ui/src/elements/ListDrawer/DrawerContent.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,7 @@ export const ListDrawerContent: React.FC<ListDrawerProps> = ({
197197
DocumentDrawerToggler={DocumentDrawerToggler}
198198
drawerSlug={drawerSlug}
199199
enabledCollections={collectionSlugs}
200-
onBulkSelect={onBulkSelect}
200+
onBulkSelect={(selected) => onBulkSelect?.(selected, selectedOption.value)}
201201
onQueryChange={onQueryChange}
202202
onSelect={onSelect}
203203
refresh={refreshSelf}

packages/ui/src/elements/ListDrawer/Provider.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,10 @@ export type ListDrawerContextProps = {
1212
readonly DocumentDrawerToggler?: ReturnType<UseDocumentDrawer>[1]
1313
readonly drawerSlug?: string
1414
readonly enabledCollections?: CollectionSlug[]
15-
readonly onBulkSelect?: (selected: ReturnType<typeof useSelection>['selected']) => void
15+
readonly onBulkSelect?: (
16+
selected: ReturnType<typeof useSelection>['selected'],
17+
collectionSlug?: CollectionSlug,
18+
) => void
1619
readonly onQueryChange?: (query: ListQuery) => void
1720
readonly onSelect?: (args: {
1821
collectionSlug: CollectionSlug

packages/ui/src/fields/Upload/Input.tsx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -413,8 +413,9 @@ export function UploadInput(props: UploadInputProps) {
413413

414414
// only hasMany can bulk select
415415
const onListBulkSelect = React.useCallback<NonNullable<ListDrawerProps['onBulkSelect']>>(
416-
async (docs) => {
416+
async (docs, collectionSlug) => {
417417
const isPoly = Array.isArray(relationTo)
418+
const relationToUse = isPoly ? collectionSlug || activeRelationTo : activeRelationTo
418419
const selectedDocIDs = []
419420

420421
for (const [id, isSelected] of docs) {
@@ -424,7 +425,7 @@ export function UploadInput(props: UploadInputProps) {
424425
}
425426

426427
const itemsToLoad = selectedDocIDs.map((id) => ({
427-
relationTo: activeRelationTo,
428+
relationTo: relationToUse,
428429
value: id,
429430
}))
430431

@@ -434,7 +435,7 @@ export function UploadInput(props: UploadInputProps) {
434435
}
435436

436437
const newValues = selectedDocIDs.map((id) =>
437-
isPoly ? { relationTo: activeRelationTo, value: id } : id,
438+
isPoly ? { relationTo: relationToUse, value: id } : id,
438439
)
439440
// Normalize existing values before merging
440441
const normalizedExisting = Array.isArray(value) ? value.map(normalizeValue) : []

test/uploads/config.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,12 @@ export default buildConfigWithDefaults({
8686
type: 'upload',
8787
relationTo: hideFileInputOnCreateSlug,
8888
},
89+
{
90+
name: 'polymorphicUploads',
91+
type: 'upload',
92+
relationTo: ['uploads-1', 'uploads-2'],
93+
hasMany: true,
94+
},
8995
{
9096
type: 'tabs',
9197
tabs: [

test/uploads/e2e.spec.ts

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,65 @@ describe('Uploads', () => {
276276
await expect(filename).toContainText('test-image.png')
277277
})
278278

279+
test('should preserve collection when bulk selecting polymorphic uploads', async () => {
280+
await page.goto(uploadsTwo.create)
281+
await page.locator('#field-prefix').fill('video')
282+
await page.locator('#field-title').fill('Polymorphic upload two')
283+
await page.setInputFiles('input[type="file"]', path.resolve(dirname, './image.png'))
284+
await saveDocAndAssert(page)
285+
286+
const uploadTwoID = page.url().split('/').pop()
287+
const relationDoc = await payload.create({
288+
collection: relationSlug,
289+
data: {},
290+
})
291+
292+
await page.goto(relationURL.edit(relationDoc.id))
293+
await openDocDrawer({ page, selector: '#field-polymorphicUploads .upload__listToggler' })
294+
295+
const listDrawer = page.locator('[id^=list-drawer_1_]')
296+
await expect(listDrawer).toBeVisible()
297+
298+
await listDrawer.locator('.list-header__select-collection').click()
299+
await page.getByText('Uploads 2', { exact: true }).click()
300+
await expect(
301+
listDrawer.locator('.cell-title', { hasText: 'Polymorphic upload two' }),
302+
).toBeVisible()
303+
304+
await listDrawer
305+
.locator('tr', { hasText: 'Polymorphic upload two' })
306+
.locator('.select-row__checkbox')
307+
.click()
308+
await listDrawer.getByRole('button', { name: 'Select 1' }).click()
309+
310+
await saveDocAndAssert(page)
311+
312+
const updatedRelationDoc = (
313+
await payload.find({
314+
collection: relationSlug,
315+
depth: 0,
316+
where: {
317+
id: {
318+
equals: relationDoc.id,
319+
},
320+
},
321+
})
322+
).docs[0] as any
323+
324+
expect(updatedRelationDoc.polymorphicUploads).toEqual([
325+
{
326+
relationTo: 'uploads-2',
327+
value: uploadTwoID,
328+
},
329+
])
330+
expect(updatedRelationDoc.polymorphicUploads).not.toEqual([
331+
{
332+
relationTo: 'uploads-1',
333+
value: uploadTwoID,
334+
},
335+
])
336+
})
337+
279338
test('should copy the file url field to the clipboard', async () => {
280339
const mediaDoc = (
281340
await payload.find({

test/uploads/payload-types.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,18 @@ export interface Relation {
246246
image?: (string | null) | Media;
247247
versionedImage?: (string | null) | Version;
248248
hideFileInputOnCreate?: (string | null) | HideFileInputOnCreate;
249+
polymorphicUploads?:
250+
| (
251+
| {
252+
relationTo: 'uploads-1';
253+
value: string | Uploads1;
254+
}
255+
| {
256+
relationTo: 'uploads-2';
257+
value: string | Uploads2;
258+
}
259+
)[]
260+
| null;
249261
blocks?:
250262
| {
251263
media: string | Media;
@@ -2197,6 +2209,7 @@ export interface RelationSelect<T extends boolean = true> {
21972209
image?: T;
21982210
versionedImage?: T;
21992211
hideFileInputOnCreate?: T;
2212+
polymorphicUploads?: T;
22002213
blocks?:
22012214
| T
22022215
| {

0 commit comments

Comments
 (0)