chore(next): properly instantiates table columns
This commit is contained in:
@@ -23,13 +23,13 @@ export default buildConfig({
|
||||
globals: [Settings],
|
||||
editor: lexicalEditor({}),
|
||||
onInit: async (payload) => {
|
||||
await payload.create({
|
||||
collection: 'users',
|
||||
data: {
|
||||
email: 'dev@payloadcms.com',
|
||||
password: 'test',
|
||||
},
|
||||
})
|
||||
// await payload.create({
|
||||
// collection: 'users',
|
||||
// data: {
|
||||
// email: 'dev@payloadcms.com',
|
||||
// password: 'test',
|
||||
// },
|
||||
// })
|
||||
// const page = await payload.create({
|
||||
// collection: 'pages',
|
||||
// data: {
|
||||
|
||||
@@ -9,6 +9,7 @@ import {
|
||||
} from '@payloadcms/ui'
|
||||
import { initPage } from '../../utilities/initPage'
|
||||
import { notFound } from 'next/navigation'
|
||||
import { ListPreferences } from '../../../../ui/src/views/List/types'
|
||||
|
||||
export const CollectionList = async ({
|
||||
collectionSlug,
|
||||
@@ -25,6 +26,23 @@ export const CollectionList = async ({
|
||||
collectionSlug,
|
||||
})
|
||||
|
||||
let listPreferences: ListPreferences
|
||||
|
||||
try {
|
||||
listPreferences = (await payload
|
||||
.find({
|
||||
collection: 'payload-preferences',
|
||||
where: {
|
||||
key: {
|
||||
equals: `${collectionSlug}-list`,
|
||||
},
|
||||
},
|
||||
limit: 1,
|
||||
depth: 0,
|
||||
})
|
||||
?.then((res) => res?.docs?.[0]?.value)) as unknown as ListPreferences
|
||||
} catch (error) {}
|
||||
|
||||
const {
|
||||
routes: { admin },
|
||||
} = config
|
||||
@@ -62,7 +80,7 @@ export const CollectionList = async ({
|
||||
return (
|
||||
<Fragment>
|
||||
<HydrateClientUser user={user} permissions={permissions} />
|
||||
<TableColumnsProvider collectionSlug={collectionSlug}>
|
||||
<TableColumnsProvider collectionSlug={collectionSlug} listPreferences={listPreferences}>
|
||||
<RenderCustomComponent
|
||||
CustomComponent={ListToRender}
|
||||
DefaultComponent={DefaultList}
|
||||
|
||||
@@ -1,21 +1,41 @@
|
||||
import { CellProps } from 'payload/types'
|
||||
import { useComponentMap } from '../../providers/ComponentMapProvider'
|
||||
import { CellProps, SanitizedCollectionConfig } from 'payload/types'
|
||||
import { Column } from '../../elements/Table/types'
|
||||
import { FieldMap } from '../../utilities/buildComponentMap/types'
|
||||
import { ListPreferences } from '../../views/List/types'
|
||||
|
||||
export const buildColumns = (args: {
|
||||
columns: Pick<Column, 'accessor' | 'active'>[]
|
||||
getMappedFieldByPath: ReturnType<typeof useComponentMap>['getMappedFieldByPath']
|
||||
collectionSlug: string
|
||||
useAsTitle: SanitizedCollectionConfig['admin']['useAsTitle']
|
||||
fieldMap: FieldMap
|
||||
cellProps: Partial<CellProps>[]
|
||||
defaultColumns?: string[]
|
||||
columnPreferences: ListPreferences['columns']
|
||||
}): Column[] => {
|
||||
const { columns, getMappedFieldByPath, collectionSlug, cellProps } = args
|
||||
const { fieldMap, cellProps, defaultColumns, columnPreferences, useAsTitle } = args
|
||||
|
||||
let numberOfActiveColumns = 0
|
||||
|
||||
return fieldMap.reduce((acc, field, index) => {
|
||||
const columnPreference = columnPreferences?.find(
|
||||
(preference) => preference.accessor === field.name,
|
||||
)
|
||||
|
||||
let active = false
|
||||
|
||||
if (columnPreference) {
|
||||
active = columnPreference.active
|
||||
} else if (defaultColumns && Array.isArray(defaultColumns) && defaultColumns.length > 0) {
|
||||
active = defaultColumns.includes(field.name)
|
||||
} else if (numberOfActiveColumns < 4) {
|
||||
active = true
|
||||
}
|
||||
|
||||
if (active) {
|
||||
numberOfActiveColumns += 1
|
||||
}
|
||||
|
||||
return columns.map(({ accessor, active }, index) => {
|
||||
const field = getMappedFieldByPath({ path: accessor, collectionSlug })
|
||||
if (!field) console.warn(`No field found for ${accessor} in ${collectionSlug}`)
|
||||
if (field) {
|
||||
const column: Column = {
|
||||
accessor,
|
||||
accessor: field.name,
|
||||
active,
|
||||
label: field.label,
|
||||
name: field.name,
|
||||
@@ -26,7 +46,9 @@ export const buildColumns = (args: {
|
||||
cellProps: cellProps?.[index],
|
||||
}
|
||||
|
||||
return column
|
||||
acc.push(column)
|
||||
}
|
||||
})
|
||||
|
||||
return acc
|
||||
}, [])
|
||||
}
|
||||
|
||||
@@ -29,12 +29,13 @@ export const TableColumnsProvider: React.FC<{
|
||||
cellProps?: Partial<CellProps>[]
|
||||
children: React.ReactNode
|
||||
collectionSlug: string
|
||||
}> = ({ cellProps, children, collectionSlug }) => {
|
||||
listPreferences: ListPreferences
|
||||
}> = ({ cellProps, children, collectionSlug, listPreferences }) => {
|
||||
const config = useConfig()
|
||||
|
||||
const { componentMap, getMappedFieldByPath } = useComponentMap()
|
||||
const { componentMap } = useComponentMap()
|
||||
|
||||
const { initialColumns } = componentMap.collections[collectionSlug]
|
||||
const { fieldMap } = componentMap.collections[collectionSlug]
|
||||
|
||||
const collectionConfig = config.collections.find(
|
||||
(collectionConfig) => collectionConfig.slug === collectionSlug,
|
||||
@@ -45,60 +46,69 @@ export const TableColumnsProvider: React.FC<{
|
||||
} = collectionConfig
|
||||
|
||||
const preferenceKey = `${collectionSlug}-list`
|
||||
const prevCollection = useRef<SanitizedCollectionConfig['slug']>()
|
||||
const prevCollection = useRef<SanitizedCollectionConfig['slug']>(collectionSlug)
|
||||
const hasInitialized = useRef(false)
|
||||
const { getPreference, setPreference } = usePreferences()
|
||||
|
||||
const [tableColumns, dispatchTableColumns] = useReducer(columnReducer, {}, () => {
|
||||
return buildColumns({
|
||||
columns: initialColumns,
|
||||
getMappedFieldByPath,
|
||||
collectionSlug,
|
||||
useAsTitle,
|
||||
defaultColumns,
|
||||
columnPreferences: listPreferences?.columns,
|
||||
fieldMap,
|
||||
cellProps,
|
||||
})
|
||||
})
|
||||
|
||||
// // /////////////////////////////////////
|
||||
// // Sync preferences on collectionConfig change
|
||||
// // /////////////////////////////////////
|
||||
// /////////////////////////////////////
|
||||
// Get preferences on collection change
|
||||
// /////////////////////////////////////
|
||||
|
||||
useEffect(() => {
|
||||
const sync = async () => {
|
||||
const collectionHasChanged = prevCollection.current !== collectionSlug
|
||||
|
||||
if (collectionHasChanged) {
|
||||
hasInitialized.current = false
|
||||
|
||||
const currentPreferences = await getPreference<ListPreferences>(preferenceKey)
|
||||
prevCollection.current = collectionSlug
|
||||
|
||||
const newCols = currentPreferences?.columns || initialColumns
|
||||
|
||||
dispatchTableColumns({
|
||||
payload: {
|
||||
columns: buildColumns({
|
||||
columns: newCols,
|
||||
getMappedFieldByPath,
|
||||
collectionSlug,
|
||||
cellProps,
|
||||
}),
|
||||
},
|
||||
type: 'set',
|
||||
})
|
||||
|
||||
hasInitialized.current = true
|
||||
if (currentPreferences.columns) {
|
||||
dispatchTableColumns({
|
||||
payload: {
|
||||
columns: buildColumns({
|
||||
useAsTitle,
|
||||
columnPreferences: currentPreferences?.columns,
|
||||
defaultColumns,
|
||||
fieldMap,
|
||||
cellProps,
|
||||
}),
|
||||
},
|
||||
type: 'set',
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sync()
|
||||
}, [preferenceKey, getPreference, collectionSlug, initialColumns, cellProps])
|
||||
}, [
|
||||
preferenceKey,
|
||||
getPreference,
|
||||
collectionSlug,
|
||||
fieldMap,
|
||||
cellProps,
|
||||
defaultColumns,
|
||||
useAsTitle,
|
||||
])
|
||||
|
||||
// // /////////////////////////////////////
|
||||
// // Set preferences on column change
|
||||
// // /////////////////////////////////////
|
||||
// /////////////////////////////////////
|
||||
// Set preferences on column change
|
||||
// /////////////////////////////////////
|
||||
|
||||
useEffect(() => {
|
||||
if (!hasInitialized.current) return
|
||||
if (!hasInitialized.current) {
|
||||
hasInitialized.current = true
|
||||
return
|
||||
}
|
||||
|
||||
const columns = tableColumns.map((c) => ({
|
||||
accessor: c?.accessor,
|
||||
|
||||
@@ -1,48 +0,0 @@
|
||||
import type { Field } from 'payload/types'
|
||||
|
||||
import { fieldAffectsData, fieldHasSubFields, tabHasName } from 'payload/types'
|
||||
import { Column } from '../../elements/Table/types'
|
||||
|
||||
export const getInitialColumns = (
|
||||
fields: Field[],
|
||||
useAsTitle: string,
|
||||
defaultColumns: string[],
|
||||
): Pick<Column, 'accessor' | 'active'>[] => {
|
||||
return fields.reduce((remaining, field, index) => {
|
||||
if (
|
||||
fieldAffectsData(field) &&
|
||||
(field.name === useAsTitle ||
|
||||
(defaultColumns && defaultColumns.includes(field.name)) ||
|
||||
index < 4)
|
||||
) {
|
||||
return [...remaining, { accessor: field.name, active: true }]
|
||||
}
|
||||
|
||||
if (!fieldAffectsData(field) && fieldHasSubFields(field)) {
|
||||
return [...remaining, ...getInitialColumns(field.fields, useAsTitle, defaultColumns)]
|
||||
}
|
||||
|
||||
if (field.type === 'tabs') {
|
||||
return [
|
||||
...remaining,
|
||||
...field.tabs.reduce(
|
||||
(tabFieldColumns, tab) => [
|
||||
...tabFieldColumns,
|
||||
...(tabHasName(tab)
|
||||
? [tab.name]
|
||||
: getInitialColumns(tab.fields, useAsTitle, defaultColumns)),
|
||||
],
|
||||
[],
|
||||
),
|
||||
]
|
||||
}
|
||||
|
||||
return [
|
||||
...remaining,
|
||||
{
|
||||
accessor: field.name,
|
||||
active: false,
|
||||
},
|
||||
]
|
||||
}, [])
|
||||
}
|
||||
@@ -3,7 +3,6 @@ import type { FieldPermissions } from 'payload/auth'
|
||||
import type { SanitizedConfig } from 'payload/types'
|
||||
import { mapFields } from './mapFields'
|
||||
import { CollectionComponentMap, ComponentMap, GlobalComponentMap } from './types'
|
||||
import { getInitialColumns } from './getInitialColumns'
|
||||
|
||||
export const buildComponentMap = (args: {
|
||||
config: SanitizedConfig
|
||||
@@ -56,15 +55,12 @@ export const buildComponentMap = (args: {
|
||||
readOnly: readOnlyOverride,
|
||||
})
|
||||
|
||||
const initialColumns = getInitialColumns(fields, useAsTitle, defaultColumns)
|
||||
|
||||
const componentMap: CollectionComponentMap = {
|
||||
BeforeList,
|
||||
AfterList,
|
||||
BeforeListTable,
|
||||
AfterListTable,
|
||||
fieldMap: mappedFields,
|
||||
initialColumns,
|
||||
}
|
||||
|
||||
return {
|
||||
|
||||
@@ -7,7 +7,6 @@ import {
|
||||
TabsField,
|
||||
} from 'payload/types'
|
||||
import { fieldTypes } from '../../forms/fields'
|
||||
import { Column } from '../../elements/Table/types'
|
||||
|
||||
export type MappedTab = {
|
||||
name?: string
|
||||
@@ -54,7 +53,6 @@ export type CollectionComponentMap = {
|
||||
BeforeListTable: React.ReactNode
|
||||
AfterListTable: React.ReactNode
|
||||
fieldMap: FieldMap
|
||||
initialColumns: Pick<Column, 'accessor' | 'active'>[]
|
||||
}
|
||||
|
||||
export type GlobalComponentMap = {
|
||||
|
||||
@@ -16,12 +16,12 @@ export const BlocksCell: React.FC<BlocksCellProps> = ({ cellData, blocks, labels
|
||||
|
||||
const selectedBlocks = cellData ? cellData.map(({ blockType }) => blockType) : []
|
||||
|
||||
const translatedBlockLabels = blocks.map((b) => ({
|
||||
const translatedBlockLabels = blocks?.map((b) => ({
|
||||
label: getTranslation(b.labels.singular, i18n),
|
||||
slug: b.slug,
|
||||
}))
|
||||
|
||||
let label = `0 ${getTranslation(labels.plural, i18n)}`
|
||||
let label = `0 ${getTranslation(labels?.plural, i18n)}`
|
||||
|
||||
const formatBlockList = (blocks) =>
|
||||
blocks
|
||||
@@ -35,13 +35,13 @@ export const BlocksCell: React.FC<BlocksCellProps> = ({ cellData, blocks, labels
|
||||
|
||||
if (selectedBlocks.length > itemsToShow) {
|
||||
const more = selectedBlocks.length - itemsToShow
|
||||
label = `${selectedBlocks.length} ${getTranslation(labels.plural, i18n)} - ${i18n.t(
|
||||
label = `${selectedBlocks.length} ${getTranslation(labels?.plural, i18n)} - ${i18n.t(
|
||||
'fields:itemsAndMore',
|
||||
{ count: more, items: formatBlockList(selectedBlocks.slice(0, itemsToShow)) },
|
||||
)}`
|
||||
} else if (selectedBlocks.length > 0) {
|
||||
label = `${selectedBlocks.length} ${getTranslation(
|
||||
selectedBlocks.length === 1 ? labels.singular : labels.plural,
|
||||
selectedBlocks.length === 1 ? labels?.singular : labels?.plural,
|
||||
i18n,
|
||||
)} - ${formatBlockList(selectedBlocks)}`
|
||||
}
|
||||
|
||||
@@ -15,9 +15,9 @@ import { useConfig } from '../../providers/Config'
|
||||
import { useTranslation } from '../../providers/Translation'
|
||||
import { useComponentMap } from '../../providers/ComponentMapProvider'
|
||||
import { Table } from '../../elements/Table'
|
||||
import { ListControls } from '../../elements/ListControls'
|
||||
|
||||
import './index.scss'
|
||||
import { ListControls } from '../../elements/ListControls'
|
||||
|
||||
const baseClass = 'collection-list'
|
||||
|
||||
|
||||
Reference in New Issue
Block a user