Skip to content

feat(ui): add support for disabling join field row types #12738

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 6 additions & 5 deletions docs/fields/join.mdx
Original file line number Diff line number Diff line change
@@ -157,11 +157,12 @@ _\* An asterisk denotes that a property is required._

You can control the user experience of the join field using the `admin` config properties. The following options are supported:

| Option | Description |
| ---------------------- | -------------------------------------------------------------------------------------------------------------------------- |
| **`defaultColumns`** | Array of field names that correspond to which columns to show in the relationship table. Default is the collection config. |
| **`allowCreate`** | Set to `false` to remove the controls for making new related documents from this field. |
| **`components.Label`** | Override the default Label of the Field Component. [More details](./overview#label) |
| Option | Description |
| ---------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **`defaultColumns`** | Array of field names that correspond to which columns to show in the relationship table. Default is the collection config. |
| **`allowCreate`** | Set to `false` to remove the controls for making new related documents from this field. |
| **`components.Label`** | Override the default Label of the Field Component. [More details](./overview#label) |
| **`disableRowTypes`** | Set to `false` to render row types, and `true` to hide them. Defaults to `false` for join fields with a singular `relationTo`, and `true` for join fields where `relationTo` is an array. |

## Join Field Data

8 changes: 6 additions & 2 deletions packages/payload/src/fields/config/types.ts
Original file line number Diff line number Diff line change
@@ -1578,6 +1578,7 @@ export type JoinField = {
} & Admin['components']
defaultColumns?: string[]
disableBulkEdit?: never
disableRowTypes?: boolean
readOnly?: never
} & Admin
/**
@@ -1629,8 +1630,11 @@ export type JoinField = {

export type JoinFieldClient = {
admin?: AdminClient &
// @ts-expect-error - vestiges of when tsconfig was not strict. Feel free to improve
Pick<JoinField['admin'], 'allowCreate' | 'defaultColumns' | 'disableBulkEdit' | 'readOnly'>
Pick<
JoinField['admin'],
// @ts-expect-error - vestiges of when tsconfig was not strict. Feel free to improve
'allowCreate' | 'defaultColumns' | 'disableBulkEdit' | 'disableRowTypes' | 'readOnly'
>
} & { targetField: Pick<RelationshipFieldClient, 'relationTo'> } & FieldBaseClient &
Pick<
JoinField,
8 changes: 7 additions & 1 deletion packages/ui/src/elements/RelationshipTable/index.tsx
Original file line number Diff line number Diff line change
@@ -130,6 +130,11 @@ export const RelationshipTable: React.FC<RelationshipTableComponentProps> = (pro
}))
: undefined

const renderRowTypes =
typeof field.admin.disableRowTypes === 'boolean'
? !field.admin.disableRowTypes
: Array.isArray(relationTo)

const {
data: newData,
state: newColumnState,
@@ -145,7 +150,7 @@ export const RelationshipTable: React.FC<RelationshipTableComponentProps> = (pro
: `_${field.collection}_${field.name}_order`,
parent,
query: newQuery,
renderRowTypes: true,
renderRowTypes,
tableAppearance: 'condensed',
})

@@ -158,6 +163,7 @@ export const RelationshipTable: React.FC<RelationshipTableComponentProps> = (pro
field.defaultLimit,
field.defaultSort,
field.admin.defaultColumns,
field.admin.disableRowTypes,
field.collection,
field.name,
field.orderable,
26 changes: 26 additions & 0 deletions test/joins/collections/Categories.ts
Original file line number Diff line number Diff line change
@@ -4,6 +4,7 @@ import { ValidationError } from 'payload'

import { categoriesSlug, hiddenPostsSlug, postsSlug } from '../shared.js'
import { singularSlug } from './Singular.js'
import { versionsSlug } from './Versions.js'

export const Categories: CollectionConfig = {
slug: categoriesSlug,
@@ -55,13 +56,22 @@ export const Categories: CollectionConfig = {
beforeInput: ['/components/BeforeInput.js#BeforeInput'],
Description: '/components/CustomDescription/index.js#FieldDescriptionComponent',
},
disableRowTypes: false,
},
collection: postsSlug,
defaultSort: '-title',
defaultLimit: 5,
on: 'category',
maxDepth: 1,
},
{
name: 'noRowTypes',
type: 'join',
collection: postsSlug,
defaultLimit: 5,
on: 'category',
maxDepth: 1,
},
{
name: 'hasManyPosts',
type: 'join',
@@ -95,6 +105,7 @@ export const Categories: CollectionConfig = {
on: 'group.category',
admin: {
defaultColumns: ['id', 'createdAt', 'title'],
disableRowTypes: false,
},
},
{
@@ -123,6 +134,21 @@ export const Categories: CollectionConfig = {
collection: 'posts',
on: 'blocks.category',
},
{
name: 'polymorphicJoin',
type: 'join',
collection: [postsSlug, versionsSlug],
on: 'category',
},
{
name: 'polymorphicJoinNoRowTypes',
type: 'join',
collection: [postsSlug, versionsSlug],
on: 'category',
admin: {
disableRowTypes: true,
},
},
{
name: 'polymorphic',
type: 'join',
3 changes: 3 additions & 0 deletions test/joins/collections/Uploads.ts
Original file line number Diff line number Diff line change
@@ -15,6 +15,9 @@ export const Uploads: CollectionConfig = {
type: 'join',
collection: 'posts',
on: 'upload',
admin: {
disableRowTypes: false,
},
},
],
upload: {
1 change: 0 additions & 1 deletion test/joins/config.ts
Original file line number Diff line number Diff line change
@@ -277,7 +277,6 @@ export default buildConfigWithDefaults({
},
],
},

{
slug: 'folders',
fields: [
48 changes: 46 additions & 2 deletions test/joins/e2e.spec.ts
Original file line number Diff line number Diff line change
@@ -199,7 +199,7 @@ describe('Join Field', () => {
await saveDocAndAssert(page)
})

test('should render collection type in first column of relationship table', async () => {
test('should render collection type in first column of relationship table when disableRowTypes false', async () => {
await page.goto(categoriesURL.edit(categoryID))
const joinField = page.locator('#field-relatedPosts.field-type.join')
await expect(joinField).toBeVisible()
@@ -217,7 +217,51 @@ describe('Join Field', () => {
}
})

test('should render drawer toggler without document link in second column of relationship table', async () => {
test('should hide collection type column of monomorphic relationship table by default', async () => {
await page.goto(categoriesURL.edit(categoryID))
const joinField = page.locator('#field-noRowTypes.field-type.join')
const tableHeaderRow = joinField.locator('.table thead > tr')
const firstColumnHeader = tableHeaderRow.locator('th').first()
await expect(firstColumnHeader).toHaveId('heading-title')
})

test('should render collection type in first column of polymorphic relationship table by default', async () => {
await page.goto(categoriesURL.edit(categoryID))
const joinField = page.locator('#field-polymorphicJoin.field-type.join')
await expect(joinField).toBeVisible()
const text = joinField.locator('thead tr th#heading-collection:first-child')
await expect(text).toHaveText('Type')
const cells = joinField.locator('.relationship-table tbody tr td:first-child .pill__label')

const count = await cells.count()

for (let i = 0; i < count; i++) {
const element = cells.nth(i)
// Perform actions on each element
await expect(element).toBeVisible()
await expect(element).toHaveText('Post')
}
})

test('should not render collection type in polymorphic relationship table with disableRowTypes true', async () => {
await page.goto(categoriesURL.edit(categoryID))
const joinField = page.locator('#field-polymorphicJoinNoRowTypes.field-type.join')
await expect(joinField).toBeVisible()
const text = joinField.locator('thead tr th#heading-title:first-child')
await expect(text).toHaveText('Title')
const cells = joinField.locator('.relationship-table tbody tr td:first-child .pill__label')

const count = await cells.count()

for (let i = 0; i < count; i++) {
const element = cells.nth(i)
// Perform actions on each element
await expect(element).toBeVisible()
await expect(element).toHaveText(/Test Post \d+/)
}
})

test('should render drawer toggler without document link in second column of relationship table with row types', async () => {
await page.goto(categoriesURL.edit(categoryID))
const joinField = page.locator('#field-relatedPosts.field-type.join')
await expect(joinField).toBeVisible()
Loading