Skip to content

feat: collection-level preferences #12909

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

Merged
merged 3 commits into from
Jun 27, 2025
Merged
Show file tree
Hide file tree
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
8 changes: 4 additions & 4 deletions packages/next/src/views/List/handleServerFunction.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { ListPreferences, ListQuery, ServerFunction, VisibleEntities } from 'payload'
import type { CollectionPreferences, ListQuery, ServerFunction, VisibleEntities } from 'payload'

import { getClientConfig } from '@payloadcms/ui/utilities/getClientConfig'
import { headers as getHeaders } from 'next/headers.js'
Expand All @@ -8,7 +8,7 @@ import { renderListView } from './index.js'

type RenderListResult = {
List: React.ReactNode
preferences: ListPreferences
preferences: CollectionPreferences
}

export const renderListHandler: ServerFunction<
Expand Down Expand Up @@ -92,7 +92,7 @@ export const renderListHandler: ServerFunction<
importMap: payload.importMap,
})

const preferencesKey = `${collectionSlug}-list`
const preferencesKey = `collection-${collectionSlug}`

const preferences = await payload
.find({
Expand All @@ -119,7 +119,7 @@ export const renderListHandler: ServerFunction<
],
},
})
.then((res) => res.docs[0]?.value as ListPreferences)
.then((res) => res.docs[0]?.value as CollectionPreferences)

const visibleEntities: VisibleEntities = {
collections: payload.config.collections
Expand Down
22 changes: 11 additions & 11 deletions packages/next/src/views/List/index.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import type {
AdminViewServerProps,
CollectionPreferences,
ColumnPreference,
DefaultDocumentIDType,
ListPreferences,
ListQuery,
ListViewClientProps,
ListViewServerPropsOnly,
Expand Down Expand Up @@ -98,8 +98,8 @@ export const renderListView = async (
* This will ensure that prefs are only updated when explicitly set by the user
* This could potentially be done by injecting a `sessionID` into the params and comparing it against a session cookie
*/
const listPreferences = await upsertPreferences<ListPreferences>({
key: `${collectionSlug}-list`,
const collectionPreferences = await upsertPreferences<CollectionPreferences>({
key: `collection-${collectionSlug}`,
req,
value: {
columns,
Expand All @@ -120,10 +120,10 @@ export const renderListView = async (

const page = isNumber(query?.page) ? Number(query.page) : 0

const limit = listPreferences?.limit || collectionConfig.admin.pagination.defaultLimit
const limit = collectionPreferences?.limit || collectionConfig.admin.pagination.defaultLimit

const sort =
listPreferences?.sort ||
collectionPreferences?.sort ||
(typeof collectionConfig.defaultSort === 'string' ? collectionConfig.defaultSort : undefined)

let where = mergeListSearchAndWhere({
Expand All @@ -150,10 +150,10 @@ export const renderListView = async (
let queryPreset: QueryPreset | undefined
let queryPresetPermissions: SanitizedCollectionPermission | undefined

if (listPreferences?.preset) {
if (collectionPreferences?.preset) {
try {
queryPreset = (await payload.findByID({
id: listPreferences?.preset,
id: collectionPreferences?.preset,
collection: 'payload-query-presets',
depth: 0,
overrideAccess: false,
Expand Down Expand Up @@ -194,7 +194,7 @@ export const renderListView = async (
const { columnState, Table } = renderTable({
clientCollectionConfig,
collectionConfig,
columnPreferences: listPreferences?.columns,
columnPreferences: collectionPreferences?.columns,
columns,
customCellProps,
docs: data.docs,
Expand Down Expand Up @@ -230,7 +230,7 @@ export const renderListView = async (
data,
i18n,
limit,
listPreferences,
listPreferences: collectionPreferences,
listSearchableFields: collectionConfig.admin.listSearchableFields,
locale: fullLocale,
params,
Expand Down Expand Up @@ -264,7 +264,7 @@ export const renderListView = async (
data={data}
defaultLimit={limit}
defaultSort={sort}
listPreferences={listPreferences}
listPreferences={collectionPreferences}
modifySearchParams={!isInDrawer}
orderableFieldName={collectionConfig.orderable === true ? '_order' : undefined}
>
Expand All @@ -278,7 +278,7 @@ export const renderListView = async (
disableQueryPresets,
enableRowSelections,
hasCreatePermission,
listPreferences,
listPreferences: collectionPreferences,
newDocumentURL,
queryPreset,
queryPresetPermissions,
Expand Down
6 changes: 3 additions & 3 deletions packages/payload/src/admin/views/list.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import type {
SanitizedCollectionConfig,
} from '../../collections/config/types.js'
import type { ServerProps } from '../../config/types.js'
import type { ListPreferences } from '../../preferences/types.js'
import type { CollectionPreferences } from '../../preferences/types.js'
import type { QueryPreset } from '../../query-presets/types.js'
import type { ResolvedFilterOptions } from '../../types/index.js'
import type { Column } from '../elements/Table.js'
Expand All @@ -30,7 +30,7 @@ export type ListViewServerPropsOnly = {
collectionConfig: SanitizedCollectionConfig
data: Data
limit: number
listPreferences: ListPreferences
listPreferences: CollectionPreferences
listSearchableFields: CollectionAdminOptions['listSearchableFields']
} & ServerProps

Expand All @@ -48,7 +48,7 @@ export type ListViewClientProps = {
/**
* @deprecated
*/
listPreferences?: ListPreferences
listPreferences?: CollectionPreferences
newDocumentURL: string
/**
* @deprecated
Expand Down
6 changes: 5 additions & 1 deletion packages/payload/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1475,11 +1475,15 @@ export { restoreVersionOperation as restoreVersionOperationGlobal } from './glob
export { updateOperation as updateOperationGlobal } from './globals/operations/update.js'
export type {
CollapsedPreferences,
CollectionPreferences,
/**
* @deprecated Use `CollectionPreferences` instead.
*/
CollectionPreferences as ListPreferences,
ColumnPreference,
DocumentPreferences,
FieldsPreferences,
InsideFieldsPreferences,
ListPreferences,
PreferenceRequest,
PreferenceUpdateRequest,
TabsPreferences,
Expand Down
2 changes: 1 addition & 1 deletion packages/payload/src/preferences/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ export type ColumnPreference = {
active: boolean
}

export type ListPreferences = {
export type CollectionPreferences = {
columns?: ColumnPreference[]
limit?: number
preset?: DefaultDocumentIDType
Expand Down
4 changes: 2 additions & 2 deletions packages/payload/src/query-presets/types.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { Field } from '../fields/config/types.js'
import type { Access, CollectionSlug } from '../index.js'
import type { ListPreferences } from '../preferences/types.js'
import type { CollectionPreferences } from '../preferences/types.js'
import type { Where } from '../types/index.js'

// Note: order matters here as it will change the rendered order in the UI
Expand All @@ -19,7 +19,7 @@ export type QueryPreset = {
users?: string[]
}
}
columns: ListPreferences['columns']
columns: CollectionPreferences['columns']
id: number | string
isShared: boolean
relatedCollection: CollectionSlug
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
'use client'

import type { ListPreferences, SelectFieldClientComponent } from 'payload'
import type { CollectionPreferences, SelectFieldClientComponent } from 'payload'
import type { ReactNode } from 'react'

import {
Expand Down Expand Up @@ -51,10 +51,11 @@ export const FieldsToExport: SelectFieldClientComponent = (props) => {
if (id || !collectionSlug) {
return
}

const doAsync = async () => {
const currentPreferences = await getPreference<{
columns: ListPreferences['columns']
}>(`${collectionSlug}-list`)
columns: CollectionPreferences['columns']
}>(`collection-${collectionSlug}`)

const columns = currentPreferences?.columns?.filter((a) => a.active).map((b) => b.accessor)
setValue(columns ?? collectionConfig?.admin?.defaultColumns ?? [])
Expand Down
2 changes: 1 addition & 1 deletion packages/ui/src/elements/RelationshipTable/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ export const RelationshipTable: React.FC<RelationshipTableComponentProps> = (pro
newQuery.where = hoistQueryParamsToAnd(newQuery.where, filterOptions)
}

// map columns from string[] to ListPreferences['columns']
// map columns from string[] to CollectionPreferences['columns']
const defaultColumns = field.admin.defaultColumns
? field.admin.defaultColumns.map((accessor) => ({
accessor,
Expand Down
2 changes: 1 addition & 1 deletion packages/ui/src/exports/client/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -385,7 +385,7 @@ export type {
/**
* @deprecated
* This export will be removed in the next major version.
* Use `import type { ListPreferences } from 'payload'` instead.
* Use `import type { CollectionPreferences } from 'payload'` instead.
*/
ListPreferences,
} from 'payload'
Expand Down
4 changes: 2 additions & 2 deletions packages/ui/src/providers/ListQuery/types.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type {
ClientCollectionConfig,
CollectionPreferences,
ColumnPreference,
ListPreferences,
ListQuery,
PaginatedDocs,
Sort,
Expand All @@ -25,7 +25,7 @@ export type ListQueryProps = {
readonly data: PaginatedDocs
readonly defaultLimit?: number
readonly defaultSort?: Sort
readonly listPreferences?: ListPreferences
readonly listPreferences?: CollectionPreferences
readonly modifySearchParams?: boolean
readonly onQueryChange?: OnListQueryChange
readonly orderableFieldName?: string
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@ import type { I18nClient } from '@payloadcms/translations'
import type {
ClientComponentProps,
ClientField,
CollectionPreferences,
CollectionSlug,
Column,
DefaultCellComponentProps,
Document,
Field,
ListPreferences,
PaginatedDocs,
Payload,
SanitizedCollectionConfig,
Expand Down Expand Up @@ -38,8 +38,8 @@ import { sortFieldMap } from './sortFieldMap.js'
export type BuildColumnStateArgs = {
beforeRows?: Column[]
clientFields: ClientField[]
columnPreferences: ListPreferences['columns']
columns?: ListPreferences['columns']
columnPreferences: CollectionPreferences['columns']
columns?: CollectionPreferences['columns']
customCellProps: DefaultCellComponentProps['customCellProps']
enableLinkedCell?: boolean
enableRowSelections: boolean
Expand Down
6 changes: 3 additions & 3 deletions packages/ui/src/providers/TableColumns/getInitialColumns.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import type { ClientField, CollectionConfig, Field, ListPreferences } from 'payload'
import type { ClientField, CollectionConfig, CollectionPreferences, Field } from 'payload'

import { fieldAffectsData } from 'payload/shared'

const getRemainingColumns = <T extends ClientField[] | Field[]>(
fields: T,
useAsTitle: string,
): ListPreferences['columns'] =>
): CollectionPreferences['columns'] =>
fields?.reduce((remaining, field) => {
if (fieldAffectsData(field) && field.name === useAsTitle) {
return remaining
Expand Down Expand Up @@ -40,7 +40,7 @@ export const getInitialColumns = <T extends ClientField[] | Field[]>(
fields: T,
useAsTitle: CollectionConfig['admin']['useAsTitle'],
defaultColumns: CollectionConfig['admin']['defaultColumns'],
): ListPreferences['columns'] => {
): CollectionPreferences['columns'] => {
let initialColumns = []

if (Array.isArray(defaultColumns) && defaultColumns.length >= 1) {
Expand Down
4 changes: 2 additions & 2 deletions packages/ui/src/providers/TableColumns/types.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { Column, ListPreferences } from 'payload'
import type { CollectionPreferences, Column } from 'payload'

import type { SortColumnProps } from '../../elements/SortColumn/index.js'

Expand Down Expand Up @@ -27,7 +27,7 @@ export type TableColumnsProviderProps = {
/**
* @deprecated
*/
readonly listPreferences?: ListPreferences
readonly listPreferences?: CollectionPreferences
/**
* @deprecated
*/
Expand Down
12 changes: 6 additions & 6 deletions packages/ui/src/utilities/buildTableState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ import type {
BuildTableStateArgs,
ClientCollectionConfig,
ClientConfig,
CollectionPreferences,
Column,
ErrorResult,
ListPreferences,
PaginatedDocs,
SanitizedCollectionConfig,
ServerFunction,
Expand All @@ -22,7 +22,7 @@ type BuildTableStateSuccessResult = {
clientConfig?: ClientConfig
data: PaginatedDocs
errors?: never
preferences: ListPreferences
preferences: CollectionPreferences
renderedFilters: Map<string, React.ReactNode>
state: Column[]
Table: React.ReactNode
Expand Down Expand Up @@ -142,10 +142,10 @@ const buildTableState = async (
}
}

const listPreferences = await upsertPreferences<ListPreferences>({
const collectionPreferences = await upsertPreferences<CollectionPreferences>({
key: Array.isArray(collectionSlug)
? `${parent.collectionSlug}-${parent.joinPath}`
: `${collectionSlug}-list`,
: `collection-${collectionSlug}`,
req,
value: {
columns,
Expand Down Expand Up @@ -231,7 +231,7 @@ const buildTableState = async (
clientConfig,
collectionConfig,
collections: Array.isArray(collectionSlug) ? collectionSlug : undefined,
columnPreferences: Array.isArray(collectionSlug) ? listPreferences?.columns : undefined, // TODO, might not be neededcolumns,
columnPreferences: Array.isArray(collectionSlug) ? collectionPreferences?.columns : undefined, // TODO, might not be neededcolumns,
columns,
docs,
enableRowSelections,
Expand All @@ -253,7 +253,7 @@ const buildTableState = async (

return {
data,
preferences: listPreferences,
preferences: collectionPreferences,
renderedFilters,
state: columnState,
Table,
Expand Down
6 changes: 3 additions & 3 deletions packages/ui/src/utilities/renderTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@ import type {
ClientConfig,
ClientField,
CollectionConfig,
CollectionPreferences,
Column,
ColumnPreference,
Field,
ImportMap,
ListPreferences,
PaginatedDocs,
Payload,
SanitizedCollectionConfig,
Expand Down Expand Up @@ -80,8 +80,8 @@ export const renderTable = ({
clientConfig?: ClientConfig
collectionConfig?: SanitizedCollectionConfig
collections?: string[]
columnPreferences: ListPreferences['columns']
columns?: ListPreferences['columns']
columnPreferences: CollectionPreferences['columns']
columns?: CollectionPreferences['columns']
customCellProps?: Record<string, unknown>
docs: PaginatedDocs['docs']
drawerSlug?: string
Expand Down
Loading
Loading