Skip to content
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

feat(payload, ui): adds disableListColumn & disableListFilter to fields admin props #6238

Merged
merged 8 commits into from
May 10, 2024
28 changes: 15 additions & 13 deletions docs/fields/overview.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -163,19 +163,21 @@ Example:

In addition to each field's base configuration, you can define specific traits and properties for fields that only have effect on how they are rendered in the Admin panel. The following properties are available for all fields within the `admin` property:

| Option | Description |
| ----------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `condition` | You can programmatically show / hide fields based on what other fields are doing. [Click here](#conditional-logic) for more info. |
| `components` | All field components can be completely and easily swapped out for custom components that you define. [Click here](#custom-components) for more info. |
| `description` | Helper text to display with the field to provide more information for the editor user. [Click here](#description) for more info. |
| `position` | Specify if the field should be rendered in the sidebar by defining `position: 'sidebar'`. |
| `width` | Restrict the width of a field. you can pass any string-based value here, be it pixels, percentages, etc. This property is especially useful when fields are nested within a `Row` type where they can be organized horizontally. |
| `style` | Attach raw CSS style properties to the root DOM element of a field. |
| `className` | Attach a CSS class name to the root DOM element of a field. |
| `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. |
| `disableBulkEdit` | Set `disableBulkEdit` to `true` to prevent fields from appearing in the select options when making edits for multiple documents. |
| `hidden` | Setting a field's `hidden` property on its `admin` config will transform it into a `hidden` input type. Its value will still submit with the Admin panel's requests, but the field itself will not be visible to editors. |
| Option | Description |
| ------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `condition` | You can programmatically show / hide fields based on what other fields are doing. [Click here](#conditional-logic) for more info. |
| `components` | All field components can be completely and easily swapped out for custom components that you define. [Click here](#custom-components) for more info. |
| `description` | Helper text to display with the field to provide more information for the editor user. [Click here](#description) for more info. |
| `position` | Specify if the field should be rendered in the sidebar by defining `position: 'sidebar'`. |
| `width` | Restrict the width of a field. you can pass any string-based value here, be it pixels, percentages, etc. This property is especially useful when fields are nested within a `Row` type where they can be organized horizontally. |
| `style` | Attach raw CSS style properties to the root DOM element of a field. |
| `className` | Attach a CSS class name to the root DOM element of a field. |
| `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. |
| `disableBulkEdit` | Set `disableBulkEdit` to `true` to prevent fields from appearing in the select options when making edits for multiple documents. |
| `disableListColumn` | Set `disableListColumn` to `true` to prevent fields from appearing in the list view column selector. |
| `disableListFilter` | Set `disableListFilter` to `true` to prevent fields from appearing in the list view filter options. |
| `hidden` | Setting a field's `hidden` property on its `admin` config will transform it into a `hidden` input type. Its value will still submit with the Admin panel's requests, but the field itself will not be visible to editors. |

### Custom components

Expand Down
2 changes: 2 additions & 0 deletions packages/payload/src/fields/config/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ export const baseAdminFields = joi.object().keys({
.alternatives()
.try(joi.string(), joi.object().pattern(joi.string(), [joi.string()]), joi.function()),
disableBulkEdit: joi.boolean().default(false),
disableListColumn: joi.boolean().default(false),
disableListFilter: joi.boolean().default(false),
disabled: joi.boolean().default(false),
hidden: joi.boolean().default(false),
initCollapsed: joi.boolean().default(false),
Expand Down
20 changes: 20 additions & 0 deletions packages/payload/src/fields/config/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,16 @@ type Admin = {
custom?: Record<string, any>
description?: Description
disableBulkEdit?: boolean
/**
* Shows / hides fields from appearing in the list view column selector.
* @type boolean
*/
disableListColumn?: boolean
/**
* Shows / hides fields from appearing in the list view filter options.
* @type boolean
*/
disableListFilter?: boolean
disabled?: boolean
hidden?: boolean
position?: 'sidebar'
Expand Down Expand Up @@ -443,6 +453,16 @@ export type UIField = {
/** Extension point to add your custom data. Available in server and client. */
custom?: Record<string, any>
disableBulkEdit?: boolean
/**
* Shows / hides fields from appearing in the list view column selector.
* @type boolean
*/
disableListColumn?: boolean
/**
* Shows / hides fields from appearing in the list view filter options.
* @type boolean
*/
disableListFilter?: boolean
position?: string
width?: string
}
Expand Down
14 changes: 12 additions & 2 deletions packages/ui/src/elements/ColumnSelector/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import type { SanitizedCollectionConfig } from 'payload/types'

import React, { useId } from 'react'

import type { Column } from '../Table/index.js'

import { Plus } from '../../icons/Plus/index.js'
import { X } from '../../icons/X/index.js'
import { useEditDepth } from '../../providers/EditDepth/index.js'
Expand All @@ -17,6 +19,12 @@ export type Props = {
collectionSlug: SanitizedCollectionConfig['slug']
}

const filterColumnFields = (fields: Column[]): Column[] => {
return fields.filter((field) => {
return !field.admin?.disableListColumn
})
}

export const ColumnSelector: React.FC<Props> = ({ collectionSlug }) => {
const { columns, moveColumn, toggleColumn } = useTableColumns()

Expand All @@ -27,18 +35,20 @@ export const ColumnSelector: React.FC<Props> = ({ collectionSlug }) => {
return null
}

const filteredColumns = filterColumnFields(columns)

return (
<DraggableSortable
className={baseClass}
ids={columns.map((col) => col?.accessor)}
ids={filteredColumns.map((col) => col?.accessor)}
onDragEnd={({ moveFromIndex, moveToIndex }) => {
moveColumn({
fromIndex: moveFromIndex,
toIndex: moveToIndex,
})
}}
>
{columns.map((col, i) => {
{filteredColumns.map((col, i) => {
if (!col) return null

const { Label, accessor, active } = col
Expand Down
1 change: 1 addition & 0 deletions packages/ui/src/elements/Table/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export type Column = {
Label: React.ReactNode
accessor: string
active: boolean
admin?: FieldBase['admin']
cellProps?: Partial<CellComponentProps>
components: {
Cell: React.ReactNode
Expand Down
4 changes: 4 additions & 0 deletions packages/ui/src/elements/TableColumns/buildColumnState.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,10 @@ export const buildColumnState = (args: Args): Column[] => {
Label,
accessor: name,
active,
admin: {
disableListColumn: field.disableListColumn,
disableListFilter: field.disableListFilter,
},
cellProps: {
...field.cellComponentProps,
...cellProps?.[index],
Expand Down
2 changes: 2 additions & 0 deletions packages/ui/src/elements/WhereBuilder/reduceFieldMap.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ export const reduceFieldMap = (fieldMap: Column[], i18n) =>
},
}

if (field.admin?.disableListFilter) return reduced

return [...reduced, formattedField]
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -755,6 +755,10 @@ export const mapFields = (args: {
custom: field?.admin?.custom,
disableBulkEdit:
'admin' in field && 'disableBulkEdit' in field.admin && field.admin.disableBulkEdit,
disableListColumn:
'admin' in field && 'disableListColumn' in field.admin && field.admin.disableListColumn,
disableListFilter:
'admin' in field && 'disableListFilter' in field.admin && field.admin.disableListFilter,
fieldComponentProps,
fieldIsPresentational,
isFieldAffectingData,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@ export type MappedField = {
cellComponentProps: CellComponentProps
custom?: Record<any, string>
disableBulkEdit?: boolean
disableListColumn?: boolean
disableListFilter?: boolean
disabled?: boolean
fieldComponentProps: FieldComponentProps
fieldIsPresentational: boolean
Expand Down
16 changes: 16 additions & 0 deletions test/fields/collections/Text/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,22 @@ const TextFields: CollectionConfig = {
hasMany: true,
maxRows: 4,
},
{
name: 'disableListColumnText',
type: 'text',
admin: {
disableListColumn: true,
disableListFilter: false,
},
},
{
name: 'disableListFilterText',
type: 'text',
admin: {
disableListColumn: false,
disableListFilter: true,
},
},
],
}

Expand Down
2 changes: 2 additions & 0 deletions test/fields/collections/Text/shared.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ export const textFieldsSlug = 'text-fields'
export const textDoc: Partial<TextField> = {
text: 'Seeded text document',
localizedText: 'Localized text',
disableListColumnText: 'Disable List Column Text',
disableListFilterText: 'Disable List Filter Text',
}

export const anotherTextDoc: Partial<TextField> = {
Expand Down
55 changes: 55 additions & 0 deletions test/fields/e2e.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import type { Config } from './payload-types.js'

import {
ensureAutoLoginAndCompilationIsDone,
exactText,
initPageConsoleErrorCatch,
navigateToListCellLink,
openDocDrawer,
Expand Down Expand Up @@ -89,6 +90,60 @@ describe('fields', () => {
await expect(textCell).toHaveText(textDoc.text)
})

test('should hide field in column selector when admin.disableListColumn', async () => {
await page.goto(url.list)
await page.locator('.list-controls__toggle-columns').click()

await expect(page.locator('.column-selector')).toBeVisible()

// Check if "Disable List Column Text" is not present in the column options
await expect(
page.locator(`.column-selector .column-selector__column`, {
hasText: exactText('Disable List Column Text'),
}),
).toBeHidden()
})

test('should show field in filter when admin.disableListColumn is true', async () => {
await page.goto(url.list)
await page.locator('.list-controls__toggle-where').click()
await page.locator('.where-builder__add-first-filter').click()

const initialField = page.locator('.condition__field')
await initialField.click()

await expect(
initialField.locator(`.rs__menu-list:has-text("Disable List Column Text")`),
).toBeVisible()
})

test('should display field in list view column selector if admin.disableListColumn is false and admin.disableListFilter is true', async () => {
await page.goto(url.list)
await page.locator('.list-controls__toggle-columns').click()

await expect(page.locator('.column-selector')).toBeVisible()

// Check if "Disable List Filter Text" is present in the column options
await expect(
page.locator(`.column-selector .column-selector__column`, {
hasText: exactText('Disable List Filter Text'),
}),
).toBeVisible()
})

test('should hide field in filter when admin.disableListFilter is true', async () => {
await page.goto(url.list)
await page.locator('.list-controls__toggle-where').click()
await page.locator('.where-builder__add-first-filter').click()

const initialField = page.locator('.condition__field')
await initialField.click()

await expect(
initialField.locator(`.rs__option :has-text("Disable List Filter Text")`),
).toBeHidden()
})

test('should display i18n label in cells when missing field data', async () => {
await page.goto(url.list)
const textCell = page.locator('.row-1 .cell-i18nText')
Expand Down
6 changes: 4 additions & 2 deletions test/fields/payload-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -698,6 +698,8 @@ export interface TextField {
localizedHasMany?: string[] | null;
withMinRows?: string[] | null;
withMaxRows?: string[] | null;
disableListColumnText?: string | null;
disableListFilterText?: string | null;
updatedAt: string;
createdAt: string;
}
Expand Down Expand Up @@ -1411,6 +1413,6 @@ export interface LexicalBlocksRadioButtonsBlock {


declare module 'payload' {
// @ts-ignore
// @ts-ignore
export interface GeneratedTypes extends Config {}
}
}
Loading