feat: adds disableGroupBy to fields admin props (#14017)

### What?

Adds a new `disableGroupBy` admin config property for fields to control
their visibility in the list view GroupBy dropdown.

### Why

Previously, the GroupByBuilder was incorrectly using `disableListFilter`
to determine which fields to show in the group-by dropdown.

### How

- Added new `disableGroupBy` property to the field admin config types.
- Updated `GroupByBuilder` to filter fields based on `disableGroupBy`
instead of `disableListFilter`

---
- To see the specific tasks where the Asana app for GitHub is being
used, see below:
  - https://app.asana.com/0/0/1211511898438807
This commit is contained in:
Patrik
2025-10-02 09:22:32 -04:00
committed by GitHub
parent ef57d24200
commit 537f58b4bc
11 changed files with 62 additions and 9 deletions

View File

@@ -616,8 +616,9 @@ The following options are available:
| **`readOnly`** | Setting a field to `readOnly` has no effect on the API whatsoever but disables the admin component's editability to prevent editors from modifying the field's value. | | **`readOnly`** | Setting a field to `readOnly` has no effect on the API whatsoever but disables the admin component's editability to prevent editors from modifying the field's value. |
| **`disabled`** | If a field is `disabled`, it is completely omitted from the [Admin Panel](../admin/overview) entirely. | | **`disabled`** | If a field is `disabled`, it is completely omitted from the [Admin Panel](../admin/overview) entirely. |
| **`disableBulkEdit`** | Set `disableBulkEdit` to `true` to prevent fields from appearing in the select options when making edits for multiple documents. Defaults to `true` for UI fields. | | **`disableBulkEdit`** | Set `disableBulkEdit` to `true` to prevent fields from appearing in the select options when making edits for multiple documents. Defaults to `true` for UI fields. |
| **`disableListColumn`** | Set `disableListColumn` to `true` to prevent fields from appearing in the list view column selector. | | **`disableGroupBy`** | Set `disableGroupBy` to `true` to prevent fields from appearing in the list view groupBy options. Defaults to `false`. |
| **`disableListFilter`** | Set `disableListFilter` to `true` to prevent fields from appearing in the list view filter options. | | **`disableListColumn`** | Set `disableListColumn` to `true` to prevent fields from appearing in the list view column selector. Defaults to `false`. |
| **`disableListFilter`** | Set `disableListFilter` to `true` to prevent fields from appearing in the list view filter options. Defaults to `false`. |
| **`hidden`** | Will transform the field into a `hidden` input type. Its value will still submit with requests in the Admin Panel, but the field itself will not be visible to editors. | | **`hidden`** | Will transform the field into a `hidden` input type. Its value will still submit with requests in the Admin Panel, but the field itself will not be visible to editors. |
### Field Descriptions ### Field Descriptions

View File

@@ -202,6 +202,7 @@ Each image size also supports `admin` options to control whether it appears in t
width: 400, width: 400,
height: 300, height: 300,
admin: { admin: {
disableGroupBy: true, // hide from list view groupBy options
disableListColumn: true, // hide from list view columns disableListColumn: true, // hide from list view columns
disableListFilter: true, // hide from list view filters disableListFilter: true, // hide from list view filters
}, },
@@ -209,7 +210,8 @@ Each image size also supports `admin` options to control whether it appears in t
``` ```
| Option | Description | | Option | Description |
| ----------------------- | -------------------------------------------------------------------------------------------------------------------------------- | | ----------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
| **`disableGroupBy`** | If set to `true`, this image size will not be available as a selectable groupBy option in the collection list view. Defaults to `false`. |
| **`disableListColumn`** | If set to `true`, this image size will not be available as a selectable column in the collection list view. Defaults to `false`. | | **`disableListColumn`** | If set to `true`, this image size will not be available as a selectable column in the collection list view. Defaults to `false`. |
| **`disableListFilter`** | If set to `true`, this image size will not be available as a filter option in the collection list view. Defaults to `false`. | | **`disableListFilter`** | If set to `true`, this image size will not be available as a filter option in the collection list view. Defaults to `false`. |

View File

@@ -89,6 +89,7 @@ export const addOrderableFieldsAndHook = (
admin: { admin: {
disableBulkEdit: true, disableBulkEdit: true,
disabled: true, disabled: true,
disableGroupBy: true,
disableListColumn: true, disableListColumn: true,
disableListFilter: true, disableListFilter: true,
hidden: true, hidden: true,

View File

@@ -366,6 +366,11 @@ type Admin = {
description?: Description description?: Description
disableBulkEdit?: boolean disableBulkEdit?: boolean
disabled?: boolean disabled?: boolean
/**
* Shows / hides fields from appearing in the list view groupBy options.
* @type boolean
*/
disableGroupBy?: boolean
/** /**
* Shows / hides fields from appearing in the list view column selector. * Shows / hides fields from appearing in the list view column selector.
* @type boolean * @type boolean
@@ -390,6 +395,11 @@ export type AdminClient = {
description?: StaticDescription description?: StaticDescription
disableBulkEdit?: boolean disableBulkEdit?: boolean
disabled?: boolean disabled?: boolean
/**
* Shows / hides fields from appearing in the list view groupBy options.
* @type boolean
*/
disableGroupBy?: boolean
/** /**
* Shows / hides fields from appearing in the list view column selector. * Shows / hides fields from appearing in the list view column selector.
* @type boolean * @type boolean

View File

@@ -170,6 +170,7 @@ export const getBaseUploadFields = ({ collection, config }: Options): Field[] =>
name, name,
type: 'number', type: 'number',
admin: { admin: {
disableGroupBy: true,
disableListColumn: true, disableListColumn: true,
disableListFilter: true, disableListFilter: true,
hidden: true, hidden: true,
@@ -184,7 +185,7 @@ export const getBaseUploadFields = ({ collection, config }: Options): Field[] =>
} }
// In Payload v4, image size subfields (`url`, `width`, `height`, etc.) should // In Payload v4, image size subfields (`url`, `width`, `height`, etc.) should
// default to `disableListColumn: true` and `disableListFilter: true` // default to `disableGroupBy: true`, `disableListColumn: true` and `disableListFilter: true`
// to avoid cluttering the collection list view and filters by default. // to avoid cluttering the collection list view and filters by default.
if (uploadOptions.imageSizes) { if (uploadOptions.imageSizes) {
uploadFields = uploadFields.concat([ uploadFields = uploadFields.concat([
@@ -199,6 +200,7 @@ export const getBaseUploadFields = ({ collection, config }: Options): Field[] =>
type: 'group', type: 'group',
admin: { admin: {
hidden: true, hidden: true,
...(size.admin?.disableGroupBy && { disableGroupBy: true }),
...(size.admin?.disableListColumn && { disableListColumn: true }), ...(size.admin?.disableListColumn && { disableListColumn: true }),
...(size.admin?.disableListFilter && { disableListFilter: true }), ...(size.admin?.disableListFilter && { disableListFilter: true }),
}, },
@@ -207,6 +209,7 @@ export const getBaseUploadFields = ({ collection, config }: Options): Field[] =>
...url, ...url,
admin: { admin: {
...url.admin, ...url.admin,
...(size.admin?.disableGroupBy && { disableGroupBy: true }),
...(size.admin?.disableListColumn && { disableListColumn: true }), ...(size.admin?.disableListColumn && { disableListColumn: true }),
...(size.admin?.disableListFilter && { disableListFilter: true }), ...(size.admin?.disableListFilter && { disableListFilter: true }),
}, },
@@ -232,6 +235,7 @@ export const getBaseUploadFields = ({ collection, config }: Options): Field[] =>
...width, ...width,
admin: { admin: {
...width.admin, ...width.admin,
...(size.admin?.disableGroupBy && { disableGroupBy: true }),
...(size.admin?.disableListColumn && { disableListColumn: true }), ...(size.admin?.disableListColumn && { disableListColumn: true }),
...(size.admin?.disableListFilter && { disableListFilter: true }), ...(size.admin?.disableListFilter && { disableListFilter: true }),
}, },
@@ -240,6 +244,7 @@ export const getBaseUploadFields = ({ collection, config }: Options): Field[] =>
...height, ...height,
admin: { admin: {
...height.admin, ...height.admin,
...(size.admin?.disableGroupBy && { disableGroupBy: true }),
...(size.admin?.disableListColumn && { disableListColumn: true }), ...(size.admin?.disableListColumn && { disableListColumn: true }),
...(size.admin?.disableListFilter && { disableListFilter: true }), ...(size.admin?.disableListFilter && { disableListFilter: true }),
}, },
@@ -248,6 +253,7 @@ export const getBaseUploadFields = ({ collection, config }: Options): Field[] =>
...mimeType, ...mimeType,
admin: { admin: {
...mimeType.admin, ...mimeType.admin,
...(size.admin?.disableGroupBy && { disableGroupBy: true }),
...(size.admin?.disableListColumn && { disableListColumn: true }), ...(size.admin?.disableListColumn && { disableListColumn: true }),
...(size.admin?.disableListFilter && { disableListFilter: true }), ...(size.admin?.disableListFilter && { disableListFilter: true }),
}, },
@@ -256,6 +262,7 @@ export const getBaseUploadFields = ({ collection, config }: Options): Field[] =>
...filesize, ...filesize,
admin: { admin: {
...filesize.admin, ...filesize.admin,
...(size.admin?.disableGroupBy && { disableGroupBy: true }),
...(size.admin?.disableListColumn && { disableListColumn: true }), ...(size.admin?.disableListColumn && { disableListColumn: true }),
...(size.admin?.disableListFilter && { disableListFilter: true }), ...(size.admin?.disableListFilter && { disableListFilter: true }),
}, },
@@ -264,6 +271,7 @@ export const getBaseUploadFields = ({ collection, config }: Options): Field[] =>
...filename, ...filename,
admin: { admin: {
...filename.admin, ...filename.admin,
...(size.admin?.disableGroupBy && { disableGroupBy: true }),
...(size.admin?.disableListColumn && { disableListColumn: true }), ...(size.admin?.disableListColumn && { disableListColumn: true }),
...(size.admin?.disableListFilter && { disableListFilter: true }), ...(size.admin?.disableListFilter && { disableListFilter: true }),
}, },

View File

@@ -72,11 +72,17 @@ export type ImageSize = {
/** /**
* Admin UI options that control how this image size appears in list views. * Admin UI options that control how this image size appears in list views.
* *
* NOTE: In Payload v4, these options (`disableListColumn`, `disableListFilter`) * NOTE: In Payload v4, these options (`disableGroupBy`, `disableListColumn` and `disableListFilter`)
* should default to `true` so image size subfields are hidden from list columns * should default to `true` so image size subfields are hidden from list columns
* and filters by default, reducing noise in the admin UI. * and filters by default, reducing noise in the admin UI.
*/ */
admin?: { admin?: {
/**
* If set to true, this image size will not be available
* as a selectable groupBy option in the collection list view.
* @default false
*/
disableGroupBy?: boolean
/** /**
* If set to true, this image size will not be available * If set to true, this image size will not be available
* as a selectable column in the collection list view. * as a selectable column in the collection list view.

View File

@@ -51,6 +51,7 @@ export const tenantField = ({
admin: { admin: {
allowCreate: false, allowCreate: false,
allowEdit: false, allowEdit: false,
disableGroupBy: true,
disableListColumn: true, disableListColumn: true,
disableListFilter: true, disableListFilter: true,
position: 'sidebar', position: 'sidebar',

View File

@@ -101,7 +101,7 @@ export const GroupByBuilder: React.FC<Props> = ({ collectionSlug, fields }) => {
}} }}
options={reducedFields.filter( options={reducedFields.filter(
(field) => (field) =>
!field.field.admin.disableListFilter && !field.field.admin.disableGroupBy &&
field.value !== 'id' && field.value !== 'id' &&
supportedFieldTypes.includes(field.field.type), supportedFieldTypes.includes(field.field.type),
)} )}

View File

@@ -22,6 +22,14 @@ export const PostsCollection: CollectionConfig = {
type: 'relationship', type: 'relationship',
relationTo: categoriesSlug, relationTo: categoriesSlug,
}, },
{
name: 'virtualTitleFromCategory',
type: 'text',
virtual: 'category.title',
admin: {
disableGroupBy: true,
},
},
{ {
name: 'checkbox', name: 'checkbox',
type: 'checkbox', type: 'checkbox',

View File

@@ -804,6 +804,20 @@ test.describe('Group By', () => {
).toBeVisible() ).toBeVisible()
}) })
test('should hide field from groupBy options when admin.disableGroupBy is true', async () => {
await page.goto(url.list)
const { groupByContainer } = await openGroupBy(page)
const field = groupByContainer.locator('#group-by--field-select')
await field.click()
await expect(
field.locator('.rs__option', {
hasText: exactText('Virtual Title From Category'),
}),
).toBeHidden()
})
test.describe('Trash', () => { test.describe('Trash', () => {
test('should show trashed docs in trash view when group-by is active', async () => { test('should show trashed docs in trash view when group-by is active', async () => {
await page.goto(url.list) await page.goto(url.list)

View File

@@ -127,6 +127,7 @@ export interface Post {
id: string; id: string;
title?: string | null; title?: string | null;
category?: (string | null) | Category; category?: (string | null) | Category;
virtualTitleFromCategory?: string | null;
checkbox?: boolean | null; checkbox?: boolean | null;
date?: string | null; date?: string | null;
tab1Field?: string | null; tab1Field?: string | null;
@@ -321,6 +322,7 @@ export interface PayloadMigration {
export interface PostsSelect<T extends boolean = true> { export interface PostsSelect<T extends boolean = true> {
title?: T; title?: T;
category?: T; category?: T;
virtualTitleFromCategory?: T;
checkbox?: T; checkbox?: T;
date?: T; date?: T;
tab1Field?: T; tab1Field?: T;