diff --git a/packages/ui/src/providers/TableColumns/buildColumnState/index.tsx b/packages/ui/src/providers/TableColumns/buildColumnState/index.tsx index bcf28624e3..779b2fc62f 100644 --- a/packages/ui/src/providers/TableColumns/buildColumnState/index.tsx +++ b/packages/ui/src/providers/TableColumns/buildColumnState/index.tsx @@ -85,8 +85,17 @@ export const buildColumnState = (args: BuildColumnStateArgs): Column[] => { } = args // clientFields contains the fake `id` column - let sortedFieldMap = flattenTopLevelFields(filterFields(clientFields), true) as ClientField[] - let _sortedFieldMap = flattenTopLevelFields(filterFields(serverFields), true) as Field[] // TODO: think of a way to avoid this additional flatten + let sortedFieldMap = flattenTopLevelFields(filterFields(clientFields), { + i18n, + keepPresentationalFields: true, + moveSubFieldsToTop: true, + }) as ClientField[] + + let _sortedFieldMap = flattenTopLevelFields(filterFields(serverFields), { + i18n, + keepPresentationalFields: true, + moveSubFieldsToTop: true, + }) as Field[] // TODO: think of a way to avoid this additional flatten // place the `ID` field first, if it exists // do the same for the `useAsTitle` field with precedence over the `ID` field @@ -122,13 +131,16 @@ export const buildColumnState = (args: BuildColumnStateArgs): Column[] => { return acc } - const serverField = _sortedFieldMap.find( - (f) => 'name' in clientField && 'name' in f && f.name === clientField.name, - ) + const accessor = + (clientField as any).accessor ?? ('name' in clientField ? clientField.name : undefined) + + const serverField = _sortedFieldMap.find((f) => { + const fAccessor = (f as any).accessor ?? ('name' in f ? f.name : undefined) + return fAccessor === accessor + }) const columnPreference = columnPreferences?.find( - (preference) => - clientField && 'name' in clientField && preference.accessor === clientField.name, + (preference) => clientField && 'name' in clientField && preference.accessor === accessor, ) const isActive = isColumnActive({ @@ -187,20 +199,28 @@ export const buildColumnState = (args: BuildColumnStateArgs): Column[] => { clientField.type === 'group' || clientField.type === 'blocks') + const label = + clientField && 'labelWithPrefix' in clientField && clientField.labelWithPrefix !== undefined + ? clientField.labelWithPrefix + : 'label' in clientField + ? clientField.label + : undefined + + // Convert accessor to dot notation specifically for SortColumn sorting behavior + const dotAccessor = accessor?.replace(/-/g, '.') + const Heading = ( ) const column: Column = { - accessor: 'name' in clientField ? clientField.name : undefined, + accessor, active: isActive, CustomLabel, field: clientField, diff --git a/packages/ui/src/providers/TableColumns/buildColumnState/isColumnActive.ts b/packages/ui/src/providers/TableColumns/buildColumnState/isColumnActive.ts index 9512b2aeaa..c8b57da67c 100644 --- a/packages/ui/src/providers/TableColumns/buildColumnState/isColumnActive.ts +++ b/packages/ui/src/providers/TableColumns/buildColumnState/isColumnActive.ts @@ -14,9 +14,8 @@ export function isColumnActive({ if (columnPreference) { return columnPreference.active } else if (columns && Array.isArray(columns) && columns.length > 0) { - return Boolean( - columns.find((column) => field && 'name' in field && column.accessor === field.name)?.active, - ) + const accessor = (field as any).accessor ?? ('name' in field ? field.name : undefined) + return Boolean(columns.find((column) => column.accessor === accessor)?.active) } else if (activeColumnsIndices.length < 4) { return true } diff --git a/packages/ui/src/providers/TableColumns/buildColumnState/renderCell.tsx b/packages/ui/src/providers/TableColumns/buildColumnState/renderCell.tsx index 1beb45b0ff..ab955df582 100644 --- a/packages/ui/src/providers/TableColumns/buildColumnState/renderCell.tsx +++ b/packages/ui/src/providers/TableColumns/buildColumnState/renderCell.tsx @@ -18,6 +18,7 @@ import { // eslint-disable-next-line payload/no-imports-from-exports-dir -- MUST reference the exports dir: https://github.com/payloadcms/payload/issues/12002#issuecomment-2791493587 } from '../../../exports/client/index.js' import { hasOptionLabelJSXElement } from '../../../utilities/hasOptionLabelJSXElement.js' +import { findValueInDoc } from '../findValueInDoc.js' type RenderCellArgs = { readonly clientField: ClientField @@ -55,7 +56,7 @@ export function renderCell({ const cellClientProps: DefaultCellComponentProps = { ...baseCellClientProps, - cellData: 'name' in clientField ? doc[clientField.name] : undefined, + cellData: 'name' in clientField ? findValueInDoc(doc, clientField.name) : undefined, link: isLinkedColumn, rowData: doc, } diff --git a/packages/ui/src/providers/TableColumns/buildColumnState/sortFieldMap.ts b/packages/ui/src/providers/TableColumns/buildColumnState/sortFieldMap.ts index 9ad1139ddd..d549011cff 100644 --- a/packages/ui/src/providers/TableColumns/buildColumnState/sortFieldMap.ts +++ b/packages/ui/src/providers/TableColumns/buildColumnState/sortFieldMap.ts @@ -5,8 +5,9 @@ export function sortFieldMap( sortTo: ColumnPreference[], ): T[] { return fieldMap?.sort((a, b) => { - const aIndex = sortTo.findIndex((column) => 'name' in a && column.accessor === a.name) - const bIndex = sortTo.findIndex((column) => 'name' in b && column.accessor === b.name) + const getAccessor = (field) => field.accessor ?? ('name' in field ? field.name : undefined) + const aIndex = sortTo.findIndex((column) => 'name' in a && column.accessor === getAccessor(a)) + const bIndex = sortTo.findIndex((column) => 'name' in b && column.accessor === getAccessor(b)) if (aIndex === -1 && bIndex === -1) { return 0 diff --git a/packages/ui/src/utilities/renderTable.tsx b/packages/ui/src/utilities/renderTable.tsx index 0774dedb2c..8c00dab882 100644 --- a/packages/ui/src/utilities/renderTable.tsx +++ b/packages/ui/src/utilities/renderTable.tsx @@ -135,9 +135,15 @@ export const renderTable = ({ const columnPreferences2: ColumnPreference[] = columnsFromArgs ? columnsFromArgs?.filter((column) => - flattenTopLevelFields(clientFields, true)?.some( - (field) => 'name' in field && field.name === column.accessor, - ), + flattenTopLevelFields(clientFields, { + i18n, + keepPresentationalFields: true, + moveSubFieldsToTop: true, + })?.some((field) => { + const accessor = + 'accessor' in field ? field.accessor : 'name' in field ? field.name : undefined + return accessor === column.accessor + }), ) : getInitialColumns( isPolymorphic ? clientFields : filterFields(clientFields),