feat: join field admin.defaultColumns (#9982)
Add the ability to specify which columns should appear in the relationship table of a join fields The new property is in the Join field `admin.defaultColumns` and can be set to an array of strings containing the field names in the desired order.
This commit is contained in:
@@ -145,10 +145,11 @@ _\* 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:
|
You can control the user experience of the join field using the `admin` config properties. The following options are supported:
|
||||||
|
|
||||||
| Option | Description |
|
| Option | Description |
|
||||||
|------------------------|----------------------------------------------------------------------------------------|
|
|------------------------|---------------------------------------------------------------------------------------------------------------------------|
|
||||||
| **`allowCreate`** | Set to `false` to remove the controls for making new related documents from this field. |
|
| **`defaultColumns`** | Array of field names that correspond to which columns to show in the relationship table. Default is the collection config. |
|
||||||
| **`components.Label`** | Override the default Label of the Field Component. [More details](../admin/fields#label) |
|
| **`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](../admin/fields#label) |
|
||||||
|
|
||||||
## Join Field Data
|
## Join Field Data
|
||||||
|
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ export type ListQuery = {
|
|||||||
|
|
||||||
export type BuildTableStateArgs = {
|
export type BuildTableStateArgs = {
|
||||||
collectionSlug: string
|
collectionSlug: string
|
||||||
columns?: any[] // TODO: type this (comes from ui pkg)
|
columns?: { accessor: string; active: boolean }[]
|
||||||
docs?: PaginatedDocs['docs']
|
docs?: PaginatedDocs['docs']
|
||||||
enableRowSelections?: boolean
|
enableRowSelections?: boolean
|
||||||
query?: ListQuery
|
query?: ListQuery
|
||||||
|
|||||||
@@ -1390,6 +1390,7 @@ export type JoinField = {
|
|||||||
Error?: CustomComponent<JoinFieldErrorClientComponent | JoinFieldErrorServerComponent>
|
Error?: CustomComponent<JoinFieldErrorClientComponent | JoinFieldErrorServerComponent>
|
||||||
Label?: CustomComponent<JoinFieldLabelClientComponent | JoinFieldLabelServerComponent>
|
Label?: CustomComponent<JoinFieldLabelClientComponent | JoinFieldLabelServerComponent>
|
||||||
} & Admin['components']
|
} & Admin['components']
|
||||||
|
defaultColumns?: string[]
|
||||||
disableBulkEdit?: never
|
disableBulkEdit?: never
|
||||||
readOnly?: never
|
readOnly?: never
|
||||||
} & Admin
|
} & Admin
|
||||||
@@ -1422,7 +1423,8 @@ export type JoinField = {
|
|||||||
FieldGraphQLType
|
FieldGraphQLType
|
||||||
|
|
||||||
export type JoinFieldClient = {
|
export type JoinFieldClient = {
|
||||||
admin?: AdminClient & Pick<JoinField['admin'], 'allowCreate' | 'disableBulkEdit' | 'readOnly'>
|
admin?: AdminClient &
|
||||||
|
Pick<JoinField['admin'], 'allowCreate' | 'defaultColumns' | 'disableBulkEdit' | 'readOnly'>
|
||||||
} & FieldBaseClient &
|
} & FieldBaseClient &
|
||||||
Pick<
|
Pick<
|
||||||
JoinField,
|
JoinField,
|
||||||
|
|||||||
@@ -115,12 +115,21 @@ export const RelationshipTable: React.FC<RelationshipTableComponentProps> = (pro
|
|||||||
newQuery.where = hoistQueryParamsToAnd(newQuery.where, filterOptions)
|
newQuery.where = hoistQueryParamsToAnd(newQuery.where, filterOptions)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// map columns from string[] to ColumnPreferences
|
||||||
|
const defaultColumns = field.admin.defaultColumns
|
||||||
|
? field.admin.defaultColumns.map((accessor) => ({
|
||||||
|
accessor,
|
||||||
|
active: true,
|
||||||
|
}))
|
||||||
|
: undefined
|
||||||
|
|
||||||
const {
|
const {
|
||||||
data: newData,
|
data: newData,
|
||||||
state: newColumnState,
|
state: newColumnState,
|
||||||
Table: NewTable,
|
Table: NewTable,
|
||||||
} = await getTableState({
|
} = await getTableState({
|
||||||
collectionSlug: relationTo,
|
collectionSlug: relationTo,
|
||||||
|
columns: defaultColumns,
|
||||||
docs,
|
docs,
|
||||||
enableRowSelections: false,
|
enableRowSelections: false,
|
||||||
query: newQuery,
|
query: newQuery,
|
||||||
@@ -134,11 +143,12 @@ export const RelationshipTable: React.FC<RelationshipTableComponentProps> = (pro
|
|||||||
setIsLoadingTable(false)
|
setIsLoadingTable(false)
|
||||||
},
|
},
|
||||||
[
|
[
|
||||||
query,
|
|
||||||
field.defaultLimit,
|
field.defaultLimit,
|
||||||
field.defaultSort,
|
field.defaultSort,
|
||||||
|
field.admin.defaultColumns,
|
||||||
collectionConfig.admin.pagination.defaultLimit,
|
collectionConfig.admin.pagination.defaultLimit,
|
||||||
collectionConfig.defaultSort,
|
collectionConfig.defaultSort,
|
||||||
|
query,
|
||||||
filterOptions,
|
filterOptions,
|
||||||
getTableState,
|
getTableState,
|
||||||
relationTo,
|
relationTo,
|
||||||
|
|||||||
@@ -91,6 +91,9 @@ export const Categories: CollectionConfig = {
|
|||||||
type: 'join',
|
type: 'join',
|
||||||
collection: postsSlug,
|
collection: postsSlug,
|
||||||
on: 'group.category',
|
on: 'group.category',
|
||||||
|
admin: {
|
||||||
|
defaultColumns: ['id', 'createdAt', 'title'],
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'camelCasePosts',
|
name: 'camelCasePosts',
|
||||||
|
|||||||
@@ -218,16 +218,28 @@ test.describe('Join Field', () => {
|
|||||||
const titleAscButton = titleColumn.locator('button.sort-column__asc')
|
const titleAscButton = titleColumn.locator('button.sort-column__asc')
|
||||||
await expect(titleAscButton).toBeVisible()
|
await expect(titleAscButton).toBeVisible()
|
||||||
await titleAscButton.click()
|
await titleAscButton.click()
|
||||||
await expect(joinField.locator('tbody tr:first-child td:nth-child(2)')).toHaveText(
|
await expect(joinField.locator('tbody .row-1')).toContainText('Test Post 1')
|
||||||
'Test Post 1',
|
|
||||||
)
|
|
||||||
|
|
||||||
const titleDescButton = titleColumn.locator('button.sort-column__desc')
|
const titleDescButton = titleColumn.locator('button.sort-column__desc')
|
||||||
await expect(titleDescButton).toBeVisible()
|
await expect(titleDescButton).toBeVisible()
|
||||||
await titleDescButton.click()
|
await titleDescButton.click()
|
||||||
await expect(joinField.locator('tbody tr:first-child td:nth-child(2)')).toHaveText(
|
await expect(joinField.locator('tbody .row-1')).toContainText('Test Post 3')
|
||||||
'Test Post 3',
|
})
|
||||||
)
|
|
||||||
|
test('should display relationship table with columns from admin.defaultColumns', async () => {
|
||||||
|
await page.goto(categoriesURL.edit(categoryID))
|
||||||
|
const joinField = page.locator('#field-group__relatedPosts.field-type.join')
|
||||||
|
const thead = joinField.locator('.relationship-table thead')
|
||||||
|
await expect(thead).toContainText('ID')
|
||||||
|
await expect(thead).toContainText('Created At')
|
||||||
|
await expect(thead).toContainText('Title')
|
||||||
|
const innerText = await thead.innerText()
|
||||||
|
|
||||||
|
// expect the order of columns to be 'ID', 'Created At', 'Title'
|
||||||
|
// eslint-disable-next-line payload/no-flaky-assertions
|
||||||
|
expect(innerText.indexOf('ID')).toBeLessThan(innerText.indexOf('Created At'))
|
||||||
|
// eslint-disable-next-line payload/no-flaky-assertions
|
||||||
|
expect(innerText.indexOf('Created At')).toBeLessThan(innerText.indexOf('Title'))
|
||||||
})
|
})
|
||||||
|
|
||||||
test('should update relationship table when new document is created', async () => {
|
test('should update relationship table when new document is created', async () => {
|
||||||
@@ -276,9 +288,7 @@ test.describe('Join Field', () => {
|
|||||||
await titleField.fill('Test Post 1 Updated')
|
await titleField.fill('Test Post 1 Updated')
|
||||||
await drawer.locator('button[id="action-save"]').click()
|
await drawer.locator('button[id="action-save"]').click()
|
||||||
await expect(drawer).toBeHidden()
|
await expect(drawer).toBeHidden()
|
||||||
await expect(joinField.locator('tbody tr:first-child td:nth-child(2)')).toHaveText(
|
await expect(joinField.locator('tbody .row-1')).toContainText('Test Post 1 Updated')
|
||||||
'Test Post 1 Updated',
|
|
||||||
)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
test('should render empty relationship table when creating new document', async () => {
|
test('should render empty relationship table when creating new document', async () => {
|
||||||
|
|||||||
Reference in New Issue
Block a user