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:
Patrik
2023-11-29 16:22:47 -05:00
committed by GitHub
parent 3502ce720b
commit 224cddd045
15 changed files with 176 additions and 27 deletions

View File

@@ -10,6 +10,11 @@ const ArrayFields: CollectionConfig = {
enableRichTextLink: false,
},
fields: [
{
name: 'title',
type: 'text',
required: false,
},
{
name: 'items',
defaultValue: arrayDefaultValue,

View File

@@ -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',
},
],
}

View File

@@ -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',

View File

@@ -10,6 +10,7 @@ const TextFields: CollectionConfig = {
admin: {
useAsTitle: 'text',
},
defaultSort: 'id',
fields: [
{
name: 'text',

View File

@@ -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',
}

View File

@@ -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', () => {

View File

@@ -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',
},
},
})

View File

@@ -166,6 +166,7 @@ export interface User {
}
export interface ArrayField {
id: string
title?: string | null
items: {
text: string
id?: string | null

View File

@@ -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 }),
])