Merge branch 'main' into feat/folders
This commit is contained in:
@@ -10,6 +10,7 @@ import type { Config } from '../../payload-types.js'
|
||||
import {
|
||||
ensureCompilationIsDone,
|
||||
initPageConsoleErrorCatch,
|
||||
saveDocAndAssert,
|
||||
// throttleTest,
|
||||
} from '../../../helpers.js'
|
||||
import { AdminUrlUtil } from '../../../helpers/adminUrlUtil.js'
|
||||
@@ -225,4 +226,19 @@ describe('Conditional Logic', () => {
|
||||
|
||||
await expect(numberField).toBeVisible()
|
||||
})
|
||||
|
||||
test('should render field based on operation argument', async () => {
|
||||
await page.goto(url.create)
|
||||
|
||||
const textField = page.locator('#field-text')
|
||||
const fieldWithOperationCondition = page.locator('#field-fieldWithOperationCondition')
|
||||
|
||||
await textField.fill('some text')
|
||||
|
||||
await expect(fieldWithOperationCondition).toBeVisible()
|
||||
|
||||
await saveDocAndAssert(page)
|
||||
|
||||
await expect(fieldWithOperationCondition).toBeHidden()
|
||||
})
|
||||
})
|
||||
|
||||
@@ -24,6 +24,19 @@ const ConditionalLogic: CollectionConfig = {
|
||||
condition: ({ toggleField }) => Boolean(toggleField),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'fieldWithOperationCondition',
|
||||
type: 'text',
|
||||
admin: {
|
||||
condition: (data, siblingData, { operation }) => {
|
||||
if (operation === 'create') {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'customFieldWithField',
|
||||
type: 'text',
|
||||
@@ -217,7 +230,7 @@ const ConditionalLogic: CollectionConfig = {
|
||||
name: 'numberField',
|
||||
type: 'number',
|
||||
admin: {
|
||||
condition: (data, siblingData, { path, user }) => {
|
||||
condition: (data, siblingData, { path }) => {
|
||||
// Ensure path has enough depth
|
||||
if (path.length < 5) {
|
||||
return false
|
||||
|
||||
@@ -650,6 +650,163 @@ describe('relationship', () => {
|
||||
|
||||
await expect(page.locator(tableRowLocator)).toHaveCount(1)
|
||||
})
|
||||
|
||||
test('should be able to select relationship with drawer appearance', async () => {
|
||||
await page.goto(url.create)
|
||||
|
||||
const relationshipField = page.locator('#field-relationshipDrawer')
|
||||
await relationshipField.click()
|
||||
const listDrawerContent = page.locator('.list-drawer').locator('.drawer__content')
|
||||
await expect(listDrawerContent).toBeVisible()
|
||||
|
||||
const firstRow = listDrawerContent.locator('table tbody tr').first()
|
||||
const button = firstRow.locator('button')
|
||||
await button.click()
|
||||
await expect(listDrawerContent).toBeHidden()
|
||||
|
||||
const selectedValue = relationshipField.locator('.relationship--single-value__text')
|
||||
await expect(selectedValue).toBeVisible()
|
||||
|
||||
// Fill required field
|
||||
await page.locator('#field-relationship').click()
|
||||
await page.locator('.rs__option:has-text("Seeded text document")').click()
|
||||
|
||||
await saveDocAndAssert(page)
|
||||
})
|
||||
|
||||
test('should be able to search within relationship list drawer', async () => {
|
||||
await page.goto(url.create)
|
||||
|
||||
const relationshipField = page.locator('#field-relationshipDrawer')
|
||||
await relationshipField.click()
|
||||
const searchField = page.locator('.list-drawer .search-filter')
|
||||
await expect(searchField).toBeVisible()
|
||||
|
||||
const searchInput = searchField.locator('input')
|
||||
await searchInput.fill('seeded')
|
||||
const rows = page.locator('.list-drawer table tbody tr')
|
||||
|
||||
await expect(rows).toHaveCount(1)
|
||||
const closeButton = page.locator('.list-drawer__header-close')
|
||||
await closeButton.click()
|
||||
|
||||
await expect(page.locator('.list-drawer')).toBeHidden()
|
||||
})
|
||||
|
||||
test('should handle read-only relationship field when `appearance: "drawer"`', async () => {
|
||||
await page.goto(url.create)
|
||||
const readOnlyField = page.locator(
|
||||
'#field-relationshipDrawerReadOnly .rs__control--is-disabled',
|
||||
)
|
||||
await expect(readOnlyField).toBeVisible()
|
||||
})
|
||||
|
||||
test('should handle polymorphic relationship when `appearance: "drawer"`', async () => {
|
||||
await page.goto(url.create)
|
||||
const relationshipField = page.locator('#field-polymorphicRelationshipDrawer')
|
||||
await relationshipField.click()
|
||||
const listDrawerContent = page.locator('.list-drawer').locator('.drawer__content')
|
||||
await expect(listDrawerContent).toBeVisible()
|
||||
|
||||
const relationToSelector = page.locator('.list-header__select-collection')
|
||||
await expect(relationToSelector).toBeVisible()
|
||||
|
||||
await relationToSelector.locator('.rs__control').click()
|
||||
const option = relationToSelector.locator('.rs__option').nth(1)
|
||||
await option.click()
|
||||
const firstRow = listDrawerContent.locator('table tbody tr').first()
|
||||
const button = firstRow.locator('button')
|
||||
await button.click()
|
||||
await expect(listDrawerContent).toBeHidden()
|
||||
|
||||
const selectedValue = relationshipField.locator('.relationship--single-value__text')
|
||||
await expect(selectedValue).toBeVisible()
|
||||
|
||||
// Fill required field
|
||||
await page.locator('#field-relationship').click()
|
||||
await page.locator('.rs__option:has-text("Seeded text document")').click()
|
||||
|
||||
await saveDocAndAssert(page)
|
||||
})
|
||||
|
||||
test('should handle `hasMany` relationship when `appearance: "drawer"`', async () => {
|
||||
await page.goto(url.create)
|
||||
const relationshipField = page.locator('#field-relationshipDrawerHasMany')
|
||||
await relationshipField.click()
|
||||
const listDrawerContent = page.locator('.list-drawer').locator('.drawer__content')
|
||||
await expect(listDrawerContent).toBeVisible()
|
||||
|
||||
const firstRow = listDrawerContent.locator('table tbody tr').first()
|
||||
const button = firstRow.locator('button')
|
||||
await button.click()
|
||||
await expect(listDrawerContent).toBeHidden()
|
||||
|
||||
const selectedValue = relationshipField.locator('.relationship--multi-value-label__text')
|
||||
await expect(selectedValue).toBeVisible()
|
||||
})
|
||||
|
||||
test('should handle `hasMany` polymorphic relationship when `appearance: "drawer"`', async () => {
|
||||
await page.goto(url.create)
|
||||
const relationshipField = page.locator('#field-relationshipDrawerHasManyPolymorphic')
|
||||
await relationshipField.click()
|
||||
const listDrawerContent = page.locator('.list-drawer').locator('.drawer__content')
|
||||
await expect(listDrawerContent).toBeVisible()
|
||||
|
||||
const firstRow = listDrawerContent.locator('table tbody tr').first()
|
||||
const button = firstRow.locator('button')
|
||||
await button.click()
|
||||
await expect(listDrawerContent).toBeHidden()
|
||||
|
||||
const selectedValue = relationshipField.locator('.relationship--multi-value-label__text')
|
||||
await expect(selectedValue).toBeVisible()
|
||||
})
|
||||
|
||||
test('should not be allowed to create in relationship list drawer when `allowCreate` is `false`', async () => {
|
||||
await page.goto(url.create)
|
||||
const relationshipField = page.locator('#field-relationshipDrawerWithAllowCreateFalse')
|
||||
await relationshipField.click()
|
||||
const listDrawerContent = page.locator('.list-drawer').locator('.drawer__content')
|
||||
await expect(listDrawerContent).toBeVisible()
|
||||
|
||||
const createNewButton = listDrawerContent.locator('list-drawer__create-new-button')
|
||||
await expect(createNewButton).toBeHidden()
|
||||
})
|
||||
|
||||
test('should respect `filterOptions` in the relationship list drawer for filtered relationship', async () => {
|
||||
// Create test documents
|
||||
await createTextFieldDoc({ text: 'list drawer test' })
|
||||
await createTextFieldDoc({ text: 'not test' })
|
||||
await page.goto(url.create)
|
||||
|
||||
const relationshipField = page.locator('#field-relationshipDrawerWithFilterOptions')
|
||||
await relationshipField.click()
|
||||
const listDrawerContent = page.locator('.list-drawer').locator('.drawer__content')
|
||||
await expect(listDrawerContent).toBeVisible()
|
||||
|
||||
const rows = page.locator('.list-drawer table tbody tr')
|
||||
await expect(rows).toHaveCount(1)
|
||||
})
|
||||
|
||||
test('should filter out existing values from relationship list drawer', async () => {
|
||||
await page.goto(url.create)
|
||||
|
||||
await page.locator('#field-relationshipDrawer').click()
|
||||
const listDrawerContent = page.locator('.list-drawer').locator('.drawer__content')
|
||||
await expect(listDrawerContent).toBeVisible()
|
||||
const rows = listDrawerContent.locator('table tbody tr')
|
||||
await expect(rows).toHaveCount(2)
|
||||
await listDrawerContent.getByText('Seeded text document', { exact: true }).click()
|
||||
|
||||
const selectedValue = page.locator(
|
||||
'#field-relationshipDrawer .relationship--single-value__text',
|
||||
)
|
||||
|
||||
await expect(selectedValue).toHaveText('Seeded text document')
|
||||
await page.locator('#field-relationshipDrawer').click()
|
||||
const newRows = listDrawerContent.locator('table tbody tr')
|
||||
await expect(newRows).toHaveCount(1)
|
||||
await expect(listDrawerContent.getByText('Seeded text document')).toHaveCount(0)
|
||||
})
|
||||
})
|
||||
|
||||
async function createTextFieldDoc(overrides?: Partial<TextField>): Promise<TextField> {
|
||||
|
||||
@@ -126,6 +126,71 @@ const RelationshipFields: CollectionConfig = {
|
||||
type: 'relationship',
|
||||
hasMany: true,
|
||||
},
|
||||
{
|
||||
name: 'relationshipDrawer',
|
||||
relationTo: 'text-fields',
|
||||
admin: { appearance: 'drawer' },
|
||||
type: 'relationship',
|
||||
},
|
||||
{
|
||||
name: 'relationshipDrawerReadOnly',
|
||||
relationTo: 'text-fields',
|
||||
admin: {
|
||||
readOnly: true,
|
||||
appearance: 'drawer',
|
||||
},
|
||||
type: 'relationship',
|
||||
},
|
||||
{
|
||||
name: 'polymorphicRelationshipDrawer',
|
||||
admin: { appearance: 'drawer' },
|
||||
type: 'relationship',
|
||||
relationTo: ['text-fields', 'array-fields'],
|
||||
},
|
||||
{
|
||||
name: 'relationshipDrawerHasMany',
|
||||
relationTo: 'text-fields',
|
||||
admin: {
|
||||
appearance: 'drawer',
|
||||
},
|
||||
hasMany: true,
|
||||
type: 'relationship',
|
||||
},
|
||||
{
|
||||
name: 'relationshipDrawerHasManyPolymorphic',
|
||||
relationTo: ['text-fields'],
|
||||
admin: {
|
||||
appearance: 'drawer',
|
||||
},
|
||||
hasMany: true,
|
||||
type: 'relationship',
|
||||
},
|
||||
{
|
||||
name: 'relationshipDrawerWithAllowCreateFalse',
|
||||
admin: {
|
||||
allowCreate: false,
|
||||
appearance: 'drawer',
|
||||
},
|
||||
type: 'relationship',
|
||||
relationTo: 'text-fields',
|
||||
},
|
||||
{
|
||||
name: 'relationshipDrawerWithFilterOptions',
|
||||
admin: { appearance: 'drawer' },
|
||||
type: 'relationship',
|
||||
relationTo: ['text-fields'],
|
||||
filterOptions: ({ relationTo }) => {
|
||||
if (relationTo === 'text-fields') {
|
||||
return {
|
||||
text: {
|
||||
equals: 'list drawer test',
|
||||
},
|
||||
}
|
||||
} else {
|
||||
return true
|
||||
}
|
||||
},
|
||||
},
|
||||
],
|
||||
slug: relationshipFieldsSlug,
|
||||
}
|
||||
|
||||
@@ -790,6 +790,7 @@ export interface ConditionalLogic {
|
||||
text: string;
|
||||
toggleField?: boolean | null;
|
||||
fieldWithCondition?: string | null;
|
||||
fieldWithOperationCondition?: string | null;
|
||||
customFieldWithField?: string | null;
|
||||
customFieldWithHOC?: string | null;
|
||||
customClientFieldWithCondition?: string | null;
|
||||
@@ -1312,6 +1313,29 @@ export interface RelationshipField {
|
||||
| null;
|
||||
relationToRow?: (string | null) | RowField;
|
||||
relationToRowMany?: (string | RowField)[] | null;
|
||||
relationshipDrawer?: (string | null) | TextField;
|
||||
relationshipDrawerReadOnly?: (string | null) | TextField;
|
||||
polymorphicRelationshipDrawer?:
|
||||
| ({
|
||||
relationTo: 'text-fields';
|
||||
value: string | TextField;
|
||||
} | null)
|
||||
| ({
|
||||
relationTo: 'array-fields';
|
||||
value: string | ArrayField;
|
||||
} | null);
|
||||
relationshipDrawerHasMany?: (string | TextField)[] | null;
|
||||
relationshipDrawerHasManyPolymorphic?:
|
||||
| {
|
||||
relationTo: 'text-fields';
|
||||
value: string | TextField;
|
||||
}[]
|
||||
| null;
|
||||
relationshipDrawerWithAllowCreateFalse?: (string | null) | TextField;
|
||||
relationshipDrawerWithFilterOptions?: {
|
||||
relationTo: 'text-fields';
|
||||
value: string | TextField;
|
||||
} | null;
|
||||
updatedAt: string;
|
||||
createdAt: string;
|
||||
}
|
||||
@@ -2341,6 +2365,7 @@ export interface ConditionalLogicSelect<T extends boolean = true> {
|
||||
text?: T;
|
||||
toggleField?: T;
|
||||
fieldWithCondition?: T;
|
||||
fieldWithOperationCondition?: T;
|
||||
customFieldWithField?: T;
|
||||
customFieldWithHOC?: T;
|
||||
customClientFieldWithCondition?: T;
|
||||
@@ -2786,6 +2811,13 @@ export interface RelationshipFieldsSelect<T extends boolean = true> {
|
||||
relationshipWithMinRows?: T;
|
||||
relationToRow?: T;
|
||||
relationToRowMany?: T;
|
||||
relationshipDrawer?: T;
|
||||
relationshipDrawerReadOnly?: T;
|
||||
polymorphicRelationshipDrawer?: T;
|
||||
relationshipDrawerHasMany?: T;
|
||||
relationshipDrawerHasManyPolymorphic?: T;
|
||||
relationshipDrawerWithAllowCreateFalse?: T;
|
||||
relationshipDrawerWithFilterOptions?: T;
|
||||
updatedAt?: T;
|
||||
createdAt?: T;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user