fix(ui): preserve polymorphic upload bulk select relation (#17112)
Port of https://github.com/payloadcms/payload/pull/16695 to `3.x`
This commit is contained in:
@@ -197,7 +197,7 @@ export const ListDrawerContent: React.FC<ListDrawerProps> = ({
|
||||
DocumentDrawerToggler={DocumentDrawerToggler}
|
||||
drawerSlug={drawerSlug}
|
||||
enabledCollections={collectionSlugs}
|
||||
onBulkSelect={onBulkSelect}
|
||||
onBulkSelect={(selected) => onBulkSelect?.(selected, selectedOption.value)}
|
||||
onQueryChange={onQueryChange}
|
||||
onSelect={onSelect}
|
||||
refresh={refreshSelf}
|
||||
|
||||
@@ -12,7 +12,10 @@ export type ListDrawerContextProps = {
|
||||
readonly DocumentDrawerToggler?: ReturnType<UseDocumentDrawer>[1]
|
||||
readonly drawerSlug?: string
|
||||
readonly enabledCollections?: CollectionSlug[]
|
||||
readonly onBulkSelect?: (selected: ReturnType<typeof useSelection>['selected']) => void
|
||||
readonly onBulkSelect?: (
|
||||
selected: ReturnType<typeof useSelection>['selected'],
|
||||
collectionSlug?: CollectionSlug,
|
||||
) => void
|
||||
readonly onQueryChange?: (query: ListQuery) => void
|
||||
readonly onSelect?: (args: {
|
||||
collectionSlug: CollectionSlug
|
||||
|
||||
@@ -413,8 +413,9 @@ export function UploadInput(props: UploadInputProps) {
|
||||
|
||||
// only hasMany can bulk select
|
||||
const onListBulkSelect = React.useCallback<NonNullable<ListDrawerProps['onBulkSelect']>>(
|
||||
async (docs) => {
|
||||
async (docs, collectionSlug) => {
|
||||
const isPoly = Array.isArray(relationTo)
|
||||
const relationToUse = isPoly ? collectionSlug || activeRelationTo : activeRelationTo
|
||||
const selectedDocIDs = []
|
||||
|
||||
for (const [id, isSelected] of docs) {
|
||||
@@ -424,7 +425,7 @@ export function UploadInput(props: UploadInputProps) {
|
||||
}
|
||||
|
||||
const itemsToLoad = selectedDocIDs.map((id) => ({
|
||||
relationTo: activeRelationTo,
|
||||
relationTo: relationToUse,
|
||||
value: id,
|
||||
}))
|
||||
|
||||
@@ -434,7 +435,7 @@ export function UploadInput(props: UploadInputProps) {
|
||||
}
|
||||
|
||||
const newValues = selectedDocIDs.map((id) =>
|
||||
isPoly ? { relationTo: activeRelationTo, value: id } : id,
|
||||
isPoly ? { relationTo: relationToUse, value: id } : id,
|
||||
)
|
||||
// Normalize existing values before merging
|
||||
const normalizedExisting = Array.isArray(value) ? value.map(normalizeValue) : []
|
||||
|
||||
@@ -86,6 +86,12 @@ export default buildConfigWithDefaults({
|
||||
type: 'upload',
|
||||
relationTo: hideFileInputOnCreateSlug,
|
||||
},
|
||||
{
|
||||
name: 'polymorphicUploads',
|
||||
type: 'upload',
|
||||
relationTo: ['uploads-1', 'uploads-2'],
|
||||
hasMany: true,
|
||||
},
|
||||
{
|
||||
type: 'tabs',
|
||||
tabs: [
|
||||
|
||||
@@ -276,6 +276,65 @@ describe('Uploads', () => {
|
||||
await expect(filename).toContainText('test-image.png')
|
||||
})
|
||||
|
||||
test('should preserve collection when bulk selecting polymorphic uploads', async () => {
|
||||
await page.goto(uploadsTwo.create)
|
||||
await page.locator('#field-prefix').fill('video')
|
||||
await page.locator('#field-title').fill('Polymorphic upload two')
|
||||
await page.setInputFiles('input[type="file"]', path.resolve(dirname, './image.png'))
|
||||
await saveDocAndAssert(page)
|
||||
|
||||
const uploadTwoID = page.url().split('/').pop()
|
||||
const relationDoc = await payload.create({
|
||||
collection: relationSlug,
|
||||
data: {},
|
||||
})
|
||||
|
||||
await page.goto(relationURL.edit(relationDoc.id))
|
||||
await openDocDrawer({ page, selector: '#field-polymorphicUploads .upload__listToggler' })
|
||||
|
||||
const listDrawer = page.locator('[id^=list-drawer_1_]')
|
||||
await expect(listDrawer).toBeVisible()
|
||||
|
||||
await listDrawer.locator('.list-header__select-collection').click()
|
||||
await page.getByText('Uploads 2', { exact: true }).click()
|
||||
await expect(
|
||||
listDrawer.locator('.cell-title', { hasText: 'Polymorphic upload two' }),
|
||||
).toBeVisible()
|
||||
|
||||
await listDrawer
|
||||
.locator('tr', { hasText: 'Polymorphic upload two' })
|
||||
.locator('.select-row__checkbox')
|
||||
.click()
|
||||
await listDrawer.getByRole('button', { name: 'Select 1' }).click()
|
||||
|
||||
await saveDocAndAssert(page)
|
||||
|
||||
const updatedRelationDoc = (
|
||||
await payload.find({
|
||||
collection: relationSlug,
|
||||
depth: 0,
|
||||
where: {
|
||||
id: {
|
||||
equals: relationDoc.id,
|
||||
},
|
||||
},
|
||||
})
|
||||
).docs[0] as any
|
||||
|
||||
expect(updatedRelationDoc.polymorphicUploads).toEqual([
|
||||
{
|
||||
relationTo: 'uploads-2',
|
||||
value: uploadTwoID,
|
||||
},
|
||||
])
|
||||
expect(updatedRelationDoc.polymorphicUploads).not.toEqual([
|
||||
{
|
||||
relationTo: 'uploads-1',
|
||||
value: uploadTwoID,
|
||||
},
|
||||
])
|
||||
})
|
||||
|
||||
test('should copy the file url field to the clipboard', async () => {
|
||||
const mediaDoc = (
|
||||
await payload.find({
|
||||
|
||||
@@ -246,6 +246,18 @@ export interface Relation {
|
||||
image?: (string | null) | Media;
|
||||
versionedImage?: (string | null) | Version;
|
||||
hideFileInputOnCreate?: (string | null) | HideFileInputOnCreate;
|
||||
polymorphicUploads?:
|
||||
| (
|
||||
| {
|
||||
relationTo: 'uploads-1';
|
||||
value: string | Uploads1;
|
||||
}
|
||||
| {
|
||||
relationTo: 'uploads-2';
|
||||
value: string | Uploads2;
|
||||
}
|
||||
)[]
|
||||
| null;
|
||||
blocks?:
|
||||
| {
|
||||
media: string | Media;
|
||||
@@ -2197,6 +2209,7 @@ export interface RelationSelect<T extends boolean = true> {
|
||||
image?: T;
|
||||
versionedImage?: T;
|
||||
hideFileInputOnCreate?: T;
|
||||
polymorphicUploads?: T;
|
||||
blocks?:
|
||||
| T
|
||||
| {
|
||||
|
||||
Reference in New Issue
Block a user