fix: separate collection docs with same ids were excluded in selectable (#6499)

This commit is contained in:
Jarrod Flesch
2024-05-24 15:20:07 -04:00
committed by GitHub
parent 6d951e6987
commit 18bc4b708c
5 changed files with 138 additions and 2 deletions

View File

@@ -495,6 +495,11 @@ const RelationshipField: React.FC<RelationshipFieldProps> = (props) => {
}} }}
disabled={readOnly || formProcessing || drawerIsOpen} disabled={readOnly || formProcessing || drawerIsOpen}
filterOption={enableWordBoundarySearch ? filterOption : undefined} filterOption={enableWordBoundarySearch ? filterOption : undefined}
getOptionValue={(option) => {
return hasMany && Array.isArray(relationTo)
? `${option.relationTo}_${option.value}`
: option.value
}}
isLoading={isLoading} isLoading={isLoading}
isMulti={hasMany} isMulti={hasMany}
isSortable={isSortable} isSortable={isSortable}

View File

@@ -9,3 +9,6 @@ export const relationWithTitleSlug = 'relation-with-title'
export const relationUpdatedExternallySlug = 'relation-updated-externally' export const relationUpdatedExternallySlug = 'relation-updated-externally'
export const collection1Slug = 'collection-1' export const collection1Slug = 'collection-1'
export const collection2Slug = 'collection-2' export const collection2Slug = 'collection-2'
export const videoCollectionSlug = 'videos'
export const podcastCollectionSlug = 'podcasts'
export const mixedMediaCollectionSlug = 'mixed-media'

View File

@@ -9,6 +9,8 @@ import { PrePopulateFieldUI } from './PrePopulateFieldUI/index.js'
import { import {
collection1Slug, collection1Slug,
collection2Slug, collection2Slug,
mixedMediaCollectionSlug,
podcastCollectionSlug,
relationFalseFilterOptionSlug, relationFalseFilterOptionSlug,
relationOneSlug, relationOneSlug,
relationRestrictedSlug, relationRestrictedSlug,
@@ -17,6 +19,7 @@ import {
relationUpdatedExternallySlug, relationUpdatedExternallySlug,
relationWithTitleSlug, relationWithTitleSlug,
slug, slug,
videoCollectionSlug,
} from './collectionSlugs.js' } from './collectionSlugs.js'
export interface FieldsRelationship { export interface FieldsRelationship {
@@ -325,6 +328,51 @@ export default buildConfigWithDefaults({
], ],
slug: collection2Slug, slug: collection2Slug,
}, },
{
slug: videoCollectionSlug,
admin: {
useAsTitle: 'title',
},
fields: [
{
name: 'id',
type: 'number',
required: true,
},
{
name: 'title',
type: 'text',
},
],
},
{
slug: podcastCollectionSlug,
admin: {
useAsTitle: 'title',
},
fields: [
{
name: 'id',
type: 'number',
required: true,
},
{
name: 'title',
type: 'text',
},
],
},
{
slug: mixedMediaCollectionSlug,
fields: [
{
type: 'relationship',
name: 'relatedMedia',
relationTo: [videoCollectionSlug, podcastCollectionSlug],
hasMany: true,
},
],
},
], ],
onInit: async (payload) => { onInit: async (payload) => {
await payload.create({ await payload.create({
@@ -461,5 +509,22 @@ export default buildConfigWithDefaults({
}, },
}) })
} }
for (let i = 0; i < 2; i++) {
await payload.create({
collection: videoCollectionSlug,
data: {
id: i,
title: `Video ${i}`,
},
})
await payload.create({
collection: podcastCollectionSlug,
data: {
id: i,
title: `Podcast ${i}`,
},
})
}
}, },
}) })

View File

@@ -1,5 +1,4 @@
import type { Page } from '@playwright/test' import type { Page } from '@playwright/test'
import type { Payload } from 'payload'
import { expect, test } from '@playwright/test' import { expect, test } from '@playwright/test'
import path from 'path' import path from 'path'
@@ -22,12 +21,12 @@ import {
openDocControls, openDocControls,
openDocDrawer, openDocDrawer,
saveDocAndAssert, saveDocAndAssert,
throttleTest,
} from '../helpers.js' } from '../helpers.js'
import { AdminUrlUtil } from '../helpers/adminUrlUtil.js' import { AdminUrlUtil } from '../helpers/adminUrlUtil.js'
import { initPayloadE2ENoConfig } from '../helpers/initPayloadE2ENoConfig.js' import { initPayloadE2ENoConfig } from '../helpers/initPayloadE2ENoConfig.js'
import { POLL_TOPASS_TIMEOUT, TEST_TIMEOUT_LONG } from '../playwright.config.js' import { POLL_TOPASS_TIMEOUT, TEST_TIMEOUT_LONG } from '../playwright.config.js'
import { import {
mixedMediaCollectionSlug,
relationFalseFilterOptionSlug, relationFalseFilterOptionSlug,
relationOneSlug, relationOneSlug,
relationRestrictedSlug, relationRestrictedSlug,
@@ -397,6 +396,26 @@ describe('fields - relationship', () => {
await expect(options).toContainText('truth') await expect(options).toContainText('truth')
}) })
test('should allow docs with same ID but different collections to be selectable', async () => {
const mixedMedia = new AdminUrlUtil(serverURL, mixedMediaCollectionSlug)
await page.goto(mixedMedia.create)
// wait for relationship options to load
const podcastsFilterOptionsReq = page.waitForResponse(/api\/podcasts/)
const videosFilterOptionsReq = page.waitForResponse(/api\/videos/)
// select relationshipMany field that relies on siblingData field above
await page.locator('#field-relatedMedia .rs__control').click()
await podcastsFilterOptionsReq
await videosFilterOptionsReq
const options = page.locator('.rs__option')
await expect(options).toHaveCount(4) // 4 docs
await options.locator(`text=Video 0`).click()
await page.locator('#field-relatedMedia .rs__control').click()
const remainingOptions = page.locator('.rs__option')
await expect(remainingOptions).toHaveCount(3) // 3 docs
})
// TODO: Flaky test in CI - fix. // TODO: Flaky test in CI - fix.
test.skip('should open document drawer from read-only relationships', async () => { test.skip('should open document drawer from read-only relationships', async () => {
const editURL = url.edit(docWithExistingRelations.id) const editURL = url.edit(docWithExistingRelations.id)

View File

@@ -18,6 +18,9 @@ export interface Config {
'relation-updated-externally': RelationUpdatedExternally; 'relation-updated-externally': RelationUpdatedExternally;
'collection-1': Collection1; 'collection-1': Collection1;
'collection-2': Collection2; 'collection-2': Collection2;
videos: Video;
podcasts: Podcast;
mixedMedia: MixedMedia;
users: User; users: User;
'payload-preferences': PayloadPreference; 'payload-preferences': PayloadPreference;
'payload-migrations': PayloadMigration; 'payload-migrations': PayloadMigration;
@@ -192,6 +195,47 @@ export interface Collection2 {
updatedAt: string; updatedAt: string;
createdAt: string; createdAt: string;
} }
/**
* This interface was referenced by `Config`'s JSON-Schema
* via the `definition` "videos".
*/
export interface Video {
id: number;
title?: string | null;
updatedAt: string;
createdAt: string;
}
/**
* This interface was referenced by `Config`'s JSON-Schema
* via the `definition` "podcasts".
*/
export interface Podcast {
id: number;
title?: string | null;
updatedAt: string;
createdAt: string;
}
/**
* This interface was referenced by `Config`'s JSON-Schema
* via the `definition` "mixedMedia".
*/
export interface MixedMedia {
id: string;
relatedMedia?:
| (
| {
relationTo: 'videos';
value: number | Video;
}
| {
relationTo: 'podcasts';
value: number | Podcast;
}
)[]
| null;
updatedAt: string;
createdAt: string;
}
/** /**
* This interface was referenced by `Config`'s JSON-Schema * This interface was referenced by `Config`'s JSON-Schema
* via the `definition` "users". * via the `definition` "users".