fix: separate collection docs with same ids were excluded in selectable (#6499)
This commit is contained in:
@@ -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}
|
||||||
|
|||||||
@@ -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'
|
||||||
|
|||||||
@@ -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}`,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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".
|
||||||
|
|||||||
Reference in New Issue
Block a user