feat: relationship sortOptions property (#4301)
* feat: adds sortOptions property to relationship field * chore: fix lexical int tests * feat: simplifies logic & updates joi schema definition * feat: revert to default when searching in relationship select * fix types and joi schema * type adjustments --------- Co-authored-by: Alessio Gravili <alessio@bonfireleads.com> Co-authored-by: Jarrod Flesch <jarrodmflesch@gmail.com>
This commit is contained in:
@@ -10,6 +10,11 @@ const ArrayFields: CollectionConfig = {
|
||||
enableRichTextLink: false,
|
||||
},
|
||||
fields: [
|
||||
{
|
||||
name: 'title',
|
||||
type: 'text',
|
||||
required: false,
|
||||
},
|
||||
{
|
||||
name: 'items',
|
||||
defaultValue: arrayDefaultValue,
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import type { ArrayField } from '../../payload-types'
|
||||
|
||||
export const arrayDoc: Partial<ArrayField> = {
|
||||
title: 'array doc 1',
|
||||
items: [
|
||||
{
|
||||
text: 'first row',
|
||||
@@ -35,3 +36,31 @@ export const arrayDoc: Partial<ArrayField> = {
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
export const anotherArrayDoc: Partial<ArrayField> = {
|
||||
title: 'array doc 2',
|
||||
items: [
|
||||
{
|
||||
text: 'first row',
|
||||
},
|
||||
{
|
||||
text: 'second row',
|
||||
},
|
||||
{
|
||||
text: 'third row',
|
||||
},
|
||||
],
|
||||
collapsedArray: [
|
||||
{
|
||||
text: 'initialize collapsed',
|
||||
},
|
||||
],
|
||||
arrayWithMinRows: [
|
||||
{
|
||||
text: 'first row',
|
||||
},
|
||||
{
|
||||
text: 'second row',
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
@@ -13,12 +13,23 @@ const RelationshipFields: CollectionConfig = {
|
||||
relationTo: ['text-fields', 'array-fields'],
|
||||
required: true,
|
||||
type: 'relationship',
|
||||
admin: {
|
||||
sortOptions: {
|
||||
'text-fields': '-id',
|
||||
'array-fields': '-id',
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'relationHasManyPolymorphic',
|
||||
type: 'relationship',
|
||||
relationTo: ['text-fields', 'array-fields'],
|
||||
hasMany: true,
|
||||
admin: {
|
||||
sortOptions: {
|
||||
'text-fields': '-text',
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'relationToSelf',
|
||||
|
||||
@@ -10,6 +10,7 @@ const TextFields: CollectionConfig = {
|
||||
admin: {
|
||||
useAsTitle: 'text',
|
||||
},
|
||||
defaultSort: 'id',
|
||||
fields: [
|
||||
{
|
||||
name: 'text',
|
||||
|
||||
@@ -7,3 +7,7 @@ export const textDoc: Partial<TextField> = {
|
||||
text: 'Seeded text document',
|
||||
localizedText: 'Localized text',
|
||||
}
|
||||
|
||||
export const anotherTextDoc: Partial<TextField> = {
|
||||
text: 'Another text document',
|
||||
}
|
||||
|
||||
@@ -1666,6 +1666,30 @@ describe('fields', () => {
|
||||
await page.click('#action-save', { delay: 100 })
|
||||
await expect(page.locator('.Toastify')).toContainText('Please correct invalid fields')
|
||||
})
|
||||
|
||||
test('should sort relationship options by sortOptions property (ID in ascending order)', async () => {
|
||||
await page.goto(url.create)
|
||||
|
||||
const field = page.locator('#field-relationship')
|
||||
await field.click()
|
||||
|
||||
const firstOption = page.locator('.rs__option').first()
|
||||
await expect(firstOption).toBeVisible()
|
||||
const firstOptionText = await firstOption.textContent()
|
||||
expect(firstOptionText.trim()).toBe('Another text document')
|
||||
})
|
||||
|
||||
test('should sort relationHasManyPolymorphic options by sortOptions property: text-fields collection (items in descending order)', async () => {
|
||||
await page.goto(url.create)
|
||||
|
||||
const field = page.locator('#field-relationHasManyPolymorphic')
|
||||
await field.click()
|
||||
|
||||
const firstOption = page.locator('.rs__option').first()
|
||||
await expect(firstOption).toBeVisible()
|
||||
const firstOptionText = await firstOption.textContent()
|
||||
expect(firstOptionText.trim()).toBe('Seeded text document')
|
||||
})
|
||||
})
|
||||
|
||||
describe('upload', () => {
|
||||
|
||||
@@ -64,8 +64,8 @@ describe('Lexical', () => {
|
||||
await payload.find({
|
||||
collection: arrayFieldsSlug,
|
||||
where: {
|
||||
id: {
|
||||
exists: true,
|
||||
title: {
|
||||
equals: 'array doc 1',
|
||||
},
|
||||
},
|
||||
})
|
||||
@@ -75,8 +75,8 @@ describe('Lexical', () => {
|
||||
await payload.find({
|
||||
collection: uploadsSlug,
|
||||
where: {
|
||||
id: {
|
||||
exists: true,
|
||||
filename: {
|
||||
equals: 'payload.jpg',
|
||||
},
|
||||
},
|
||||
})
|
||||
@@ -86,8 +86,8 @@ describe('Lexical', () => {
|
||||
await payload.find({
|
||||
collection: textFieldsSlug,
|
||||
where: {
|
||||
id: {
|
||||
exists: true,
|
||||
text: {
|
||||
equals: 'Seeded text document',
|
||||
},
|
||||
},
|
||||
})
|
||||
@@ -97,8 +97,8 @@ describe('Lexical', () => {
|
||||
await payload.find({
|
||||
collection: richTextFieldsSlug,
|
||||
where: {
|
||||
id: {
|
||||
exists: true,
|
||||
title: {
|
||||
equals: 'Rich Text',
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
@@ -166,6 +166,7 @@ export interface User {
|
||||
}
|
||||
export interface ArrayField {
|
||||
id: string
|
||||
title?: string | null
|
||||
items: {
|
||||
text: string
|
||||
id?: string | null
|
||||
|
||||
@@ -4,7 +4,7 @@ import { type Payload } from '../../packages/payload/src'
|
||||
import getFileByPath from '../../packages/payload/src/uploads/getFileByPath'
|
||||
import { devUser } from '../credentials'
|
||||
import { seedDB } from '../helpers/seed'
|
||||
import { arrayDoc } from './collections/Array/shared'
|
||||
import { anotherArrayDoc, arrayDoc } from './collections/Array/shared'
|
||||
import { blocksDoc } from './collections/Blocks/shared'
|
||||
import { codeDoc } from './collections/Code/shared'
|
||||
import { collapsibleDoc } from './collections/Collapsible/shared'
|
||||
@@ -20,7 +20,7 @@ import { radiosDoc } from './collections/Radio/shared'
|
||||
import { richTextBulletsDocData, richTextDocData } from './collections/RichText/data'
|
||||
import { selectsDoc } from './collections/Select/shared'
|
||||
import { tabsDoc } from './collections/Tabs/shared'
|
||||
import { textDoc } from './collections/Text/shared'
|
||||
import { anotherTextDoc, textDoc } from './collections/Text/shared'
|
||||
import { uploadsDoc } from './collections/Upload/shared'
|
||||
import {
|
||||
arrayFieldsSlug,
|
||||
@@ -56,9 +56,17 @@ export async function clearAndSeedEverything(_payload: Payload) {
|
||||
// Get both files in parallel
|
||||
const [jpgFile, pngFile] = await Promise.all([getFileByPath(jpgPath), getFileByPath(pngPath)])
|
||||
|
||||
const [createdArrayDoc, createdTextDoc, createdPNGDoc] = await Promise.all([
|
||||
const [
|
||||
createdArrayDoc,
|
||||
createdAnotherArrayDoc,
|
||||
createdTextDoc,
|
||||
createdAnotherTextDoc,
|
||||
createdPNGDoc,
|
||||
] = await Promise.all([
|
||||
_payload.create({ collection: arrayFieldsSlug, data: arrayDoc }),
|
||||
_payload.create({ collection: arrayFieldsSlug, data: anotherArrayDoc }),
|
||||
_payload.create({ collection: textFieldsSlug, data: textDoc }),
|
||||
_payload.create({ collection: textFieldsSlug, data: anotherTextDoc }),
|
||||
_payload.create({ collection: uploadsSlug, data: {}, file: pngFile }),
|
||||
])
|
||||
|
||||
|
||||
Reference in New Issue
Block a user