Skip to content

Commit

Permalink
feat(payload, ui): adds disableListColumn & disableListFilter to …
Browse files Browse the repository at this point in the history
…fields `admin` props (#6238)
  • Loading branch information
PatrikKozak committed May 10, 2024
1 parent 4216d69 commit ea84e82
Show file tree
Hide file tree
Showing 13 changed files with 139 additions and 17 deletions.
28 changes: 15 additions & 13 deletions docs/fields/overview.mdx
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
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
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
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
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
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
Expand Up @@ -32,6 +32,8 @@ export const reduceFieldMap = (fieldMap: Column[], i18n) =>
},
}

if (field.admin?.disableListFilter) return reduced

return [...reduced, formattedField]
}

Expand Down
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
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
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
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
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
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 {}
}
}

0 comments on commit ea84e82

Please sign in to comment.