diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index e2aa53db03..2cb9cfc6c7 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -246,7 +246,7 @@ jobs:
suite:
- _community
- access-control
- # - admin
+ - admin
- auth
- field-error-states
- fields-relationship
diff --git a/packages/next/src/views/List/Default/index.tsx b/packages/next/src/views/List/Default/index.tsx
index 51dbad6435..28c1d93ef1 100644
--- a/packages/next/src/views/List/Default/index.tsx
+++ b/packages/next/src/views/List/Default/index.tsx
@@ -37,7 +37,7 @@ const baseClass = 'collection-list'
const Link = (LinkImport.default || LinkImport) as unknown as typeof LinkImport.default
export const DefaultListView: React.FC = () => {
- const { Header, collectionSlug, hasCreatePermission, newDocumentURL, titleField } = useListInfo()
+ const { Header, collectionSlug, hasCreatePermission, newDocumentURL } = useListInfo()
const { data, defaultLimit, handlePageChange, handlePerPageChange } = useListQuery()
const { searchParams } = useSearchParams()
@@ -47,8 +47,15 @@ export const DefaultListView: React.FC = () => {
const componentMap = getComponentMap({ collectionSlug }) as CollectionComponentMap
- const { AfterList, AfterListTable, BeforeList, BeforeListTable, actionsMap, fieldMap } =
- componentMap || {}
+ const {
+ AfterList,
+ AfterListTable,
+ BeforeList,
+ BeforeListTable,
+ Description,
+ actionsMap,
+ fieldMap,
+ } = componentMap || {}
const collectionConfig = config.collections.find(
(collection) => collection.slug === collectionSlug,
@@ -106,19 +113,11 @@ export const DefaultListView: React.FC = () => {
{!smallBreak && (
)}
- {/* {description && (
-
-
-
- )} */}
+ {Description && {Description}
}
)}
-
+
{BeforeListTable}
{!data.docs && (
+
+export type EntityDescriptionFunction = () => string
+
export type EntityDescription =
- | (() => string)
- | React.ComponentType
+ | EntityDescriptionComponent
+ | EntityDescriptionFunction
| Record
| string
diff --git a/packages/payload/src/exports/types.ts b/packages/payload/src/exports/types.ts
index eebb5b64a4..ff5f9f9911 100644
--- a/packages/payload/src/exports/types.ts
+++ b/packages/payload/src/exports/types.ts
@@ -39,7 +39,15 @@ export type {
} from './../collections/config/types.js'
export type { ClientConfig } from './../config/client.js'
-export type { Access, AccessArgs, EditViewComponent, SanitizedConfig } from './../config/types.js'
+export type {
+ Access,
+ AccessArgs,
+ EditViewComponent,
+ EntityDescription,
+ EntityDescriptionComponent,
+ EntityDescriptionFunction,
+ SanitizedConfig,
+} from './../config/types.js'
export type { ClientFieldConfig } from './../fields/config/client.js'
export type {
ArrayField,
diff --git a/packages/ui/src/elements/ListControls/index.tsx b/packages/ui/src/elements/ListControls/index.tsx
index c15751d032..59c73db1ad 100644
--- a/packages/ui/src/elements/ListControls/index.tsx
+++ b/packages/ui/src/elements/ListControls/index.tsx
@@ -3,13 +3,14 @@ import type { ClientCollectionConfig, FieldAffectingData, Where } from 'payload/
import * as facelessUIImport from '@faceless-ui/window-info'
import { getTranslation } from '@payloadcms/translations'
-import { fieldAffectsData } from 'payload/types'
import React, { useState } from 'react'
import AnimateHeightImport from 'react-animate-height'
const AnimateHeight = (AnimateHeightImport.default ||
AnimateHeightImport) as typeof AnimateHeightImport.default
+import { useUseTitleField } from '@payloadcms/ui/hooks/useUseAsTitle'
+
import type { FieldMap } from '../../utilities/buildComponentMap.js'
import { Chevron } from '../../icons/Chevron/index.js'
@@ -38,7 +39,6 @@ export type ListControlsProps = {
handleSortChange?: (sort: string) => void
handleWhereChange?: (where: Where) => void
textFieldsToBeSearched?: FieldAffectingData[]
- titleField: FieldAffectingData
}
/**
@@ -53,31 +53,39 @@ export const ListControls: React.FC = (props) => {
enableSort = false,
fieldMap,
textFieldsToBeSearched,
- titleField,
} = props
const { useWindowInfo } = facelessUIImport
+
const { handleSearchChange } = useListQuery()
-
const { searchParams } = useSearchParams()
- const shouldInitializeWhereOpened = validateWhereQuery(searchParams?.where)
-
- const [visibleDrawer, setVisibleDrawer] = useState<'columns' | 'sort' | 'where'>(
- shouldInitializeWhereOpened ? 'where' : undefined,
- )
+ const titleField = useUseTitleField(collectionConfig, fieldMap)
const { i18n, t } = useTranslation()
const {
breakpoints: { s: smallBreak },
} = useWindowInfo()
+ const shouldInitializeWhereOpened = validateWhereQuery(searchParams?.where)
+ const [visibleDrawer, setVisibleDrawer] = useState<'columns' | 'sort' | 'where'>(
+ shouldInitializeWhereOpened ? 'where' : undefined,
+ )
+
return (
diff --git a/packages/ui/src/elements/ListDrawer/DrawerContent.tsx b/packages/ui/src/elements/ListDrawer/DrawerContent.tsx
index f0b7053d48..06ca787921 100644
--- a/packages/ui/src/elements/ListDrawer/DrawerContent.tsx
+++ b/packages/ui/src/elements/ListDrawer/DrawerContent.tsx
@@ -10,7 +10,6 @@ import type { ListDrawerProps } from './types.js'
import { FieldLabel } from '../../forms/FieldLabel/index.js'
import usePayloadAPI from '../../hooks/usePayloadAPI.js'
-import { useUseTitleField } from '../../hooks/useUseAsTitle.js'
import { X } from '../../icons/X/index.js'
import { useAuth } from '../../providers/Auth/index.js'
import { useComponentMap } from '../../providers/ComponentMap/index.js'
@@ -55,7 +54,7 @@ export const ListDrawerContent: React.FC
= ({
const { i18n, t } = useTranslation()
const { permissions } = useAuth()
- const { getPreference, setPreference } = usePreferences()
+ const { setPreference } = usePreferences()
const { closeModal, isModalOpen } = useModal()
const [limit, setLimit] = useState()
const [sort, setSort] = useState(null)
@@ -97,8 +96,6 @@ export const ListDrawerContent: React.FC = ({
// const [fields, setFields] = useState(() => formatFields(selectedCollectionConfig))
- const titleField = useUseTitleField(selectedCollectionConfig)
-
useEffect(() => {
// setFields(formatFields(selectedCollectionConfig))
}, [selectedCollectionConfig])
@@ -141,7 +138,11 @@ export const ListDrawerContent: React.FC = ({
const moreThanOneAvailableCollection = enabledCollectionConfigs.length > 1
useEffect(() => {
- const { slug, admin: { listSearchableFields } = {}, versions } = selectedCollectionConfig
+ const {
+ slug,
+ admin: { listSearchableFields, useAsTitle } = {},
+ versions,
+ } = selectedCollectionConfig
const params: {
cacheBust?: number
draft?: string
@@ -160,7 +161,7 @@ export const ListDrawerContent: React.FC = ({
}
if (search) {
- const searchAsConditions = (listSearchableFields || [titleField?.name]).map((fieldName) => {
+ const searchAsConditions = (listSearchableFields || [useAsTitle]).map((fieldName) => {
return {
[fieldName]: {
like: search,
@@ -184,18 +185,7 @@ export const ListDrawerContent: React.FC = ({
if (versions?.drafts) params.draft = 'true'
setParams(params)
- }, [
- page,
- sort,
- where,
- search,
- cacheBust,
- filterOptions,
- selectedCollectionConfig,
- t,
- setParams,
- titleField?.name,
- ])
+ }, [page, sort, where, search, cacheBust, filterOptions, selectedCollectionConfig, t, setParams])
useEffect(() => {
const newPreferences = {
@@ -282,7 +272,6 @@ export const ListDrawerContent: React.FC = ({
collectionSlug={selectedCollectionConfig.slug}
hasCreatePermission={hasCreatePermission}
newDocumentURL={null}
- titleField={titleField}
>
{
cellProps: {
...cellProps?.[index],
link: isFirstActiveColumn,
+ relationTo:
+ field.type === 'relationship' && 'relationTo' in field.fieldComponentProps
+ ? field.fieldComponentProps.relationTo
+ : undefined,
},
components: {
Cell,
diff --git a/packages/ui/src/elements/WhereBuilder/Condition/index.tsx b/packages/ui/src/elements/WhereBuilder/Condition/index.tsx
index d4bc62087e..394007b60a 100644
--- a/packages/ui/src/elements/WhereBuilder/Condition/index.tsx
+++ b/packages/ui/src/elements/WhereBuilder/Condition/index.tsx
@@ -161,11 +161,10 @@ export const Condition: React.FC = (props) => {
options: valueOptions,
relationTo:
internalField?.props?.type === 'relationship' &&
- 'components' in internalField.props
- ? (
- (internalField?.props?.components as any)?.Cell
- ?.props as RelationshipFieldProps
- )?.relationTo
+ 'cellProps' in internalField.props &&
+ typeof internalField.props.cellProps === 'object' &&
+ 'relationTo' in internalField.props.cellProps
+ ? internalField.props.cellProps?.relationTo
: undefined,
value: internalQueryValue ?? '',
}}
diff --git a/packages/ui/src/elements/WhereBuilder/reduceFieldMap.tsx b/packages/ui/src/elements/WhereBuilder/reduceFieldMap.tsx
index 9b9bcdc845..c32196cab9 100644
--- a/packages/ui/src/elements/WhereBuilder/reduceFieldMap.tsx
+++ b/packages/ui/src/elements/WhereBuilder/reduceFieldMap.tsx
@@ -28,6 +28,7 @@ export const reduceFieldMap = (fieldMap: Column[], i18n) =>
operators,
props: {
...field,
+ ...(field?.cellProps || {}),
},
}
diff --git a/packages/ui/src/hooks/useUseAsTitle.ts b/packages/ui/src/hooks/useUseAsTitle.ts
index 9a7c362674..db35865efc 100644
--- a/packages/ui/src/hooks/useUseAsTitle.ts
+++ b/packages/ui/src/hooks/useUseAsTitle.ts
@@ -1,16 +1,17 @@
import type { ClientCollectionConfig, FieldAffectingData } from 'payload/types'
-import { fieldAffectsData } from 'payload/types'
-import { flattenTopLevelFields } from 'payload/utilities'
+import type { FieldMap, MappedField } from '../utilities/buildComponentMap.js'
-export const useUseTitleField = (collection: ClientCollectionConfig): FieldAffectingData => {
+import { flattenFieldMap } from '../utilities/flattenFieldMap.js'
+
+export const useUseTitleField = (
+ collection: ClientCollectionConfig,
+ fieldMap: FieldMap,
+): MappedField => {
const {
admin: { useAsTitle },
- fields,
} = collection
- const topLevelFields = flattenTopLevelFields(fields)
- return topLevelFields.find(
- (field) => fieldAffectsData(field) && field.name === useAsTitle,
- ) as FieldAffectingData
+ const topLevelFields = flattenFieldMap(fieldMap)
+ return topLevelFields.find((field) => field.name === useAsTitle)
}
diff --git a/packages/ui/src/providers/ComponentMap/buildComponentMap/mapActions.tsx b/packages/ui/src/providers/ComponentMap/buildComponentMap/actions.tsx
similarity index 100%
rename from packages/ui/src/providers/ComponentMap/buildComponentMap/mapActions.tsx
rename to packages/ui/src/providers/ComponentMap/buildComponentMap/actions.tsx
diff --git a/packages/ui/src/providers/ComponentMap/buildComponentMap/collections.tsx b/packages/ui/src/providers/ComponentMap/buildComponentMap/collections.tsx
new file mode 100644
index 0000000000..be6a71a86c
--- /dev/null
+++ b/packages/ui/src/providers/ComponentMap/buildComponentMap/collections.tsx
@@ -0,0 +1,164 @@
+import type { ViewDescriptionProps } from '@payloadcms/ui/elements/ViewDescription'
+import type {
+ AdminViewProps,
+ EditViewProps,
+ EntityDescriptionComponent,
+ EntityDescriptionFunction,
+ SanitizedCollectionConfig,
+ SanitizedConfig,
+} from 'payload/types'
+
+import { ViewDescription } from '@payloadcms/ui/elements/ViewDescription'
+import { isPlainFunction, isReactComponent } from 'payload/utilities'
+import React from 'react'
+
+import type { CollectionComponentMap } from './types.js'
+
+import { mapActions } from './actions.js'
+import { mapFields } from './fields.js'
+
+export const mapCollections = ({
+ DefaultEditView,
+ DefaultListView,
+ collections,
+ config,
+ readOnly: readOnlyOverride,
+}: {
+ DefaultEditView: React.FC
+ DefaultListView: React.FC
+ collections: SanitizedCollectionConfig[]
+ config: SanitizedConfig
+ readOnly?: boolean
+}): {
+ [key: SanitizedCollectionConfig['slug']]: CollectionComponentMap
+} =>
+ collections.reduce((acc, collectionConfig) => {
+ const { slug, fields } = collectionConfig
+
+ const internalCollections = ['payload-preferences', 'payload-migrations']
+
+ if (internalCollections.includes(slug)) {
+ return acc
+ }
+
+ const editViewFromConfig = collectionConfig?.admin?.components?.views?.Edit
+
+ const listViewFromConfig = collectionConfig?.admin?.components?.views?.List
+
+ const CustomEditView =
+ typeof editViewFromConfig === 'function'
+ ? editViewFromConfig
+ : typeof editViewFromConfig === 'object' && typeof editViewFromConfig.Default === 'function'
+ ? editViewFromConfig.Default
+ : typeof editViewFromConfig?.Default === 'object' &&
+ 'Component' in editViewFromConfig.Default &&
+ typeof editViewFromConfig.Default.Component === 'function'
+ ? (editViewFromConfig.Default.Component as React.FC)
+ : undefined
+
+ const CustomListView =
+ typeof listViewFromConfig === 'function'
+ ? listViewFromConfig
+ : typeof listViewFromConfig === 'object' &&
+ typeof listViewFromConfig.Component === 'function'
+ ? listViewFromConfig.Component
+ : undefined
+
+ const Edit = (CustomEditView as React.FC) || DefaultEditView
+
+ const List = CustomListView || DefaultListView
+
+ const beforeList = collectionConfig?.admin?.components?.BeforeList
+
+ const beforeListTable = collectionConfig?.admin?.components?.BeforeListTable
+
+ const afterList = collectionConfig?.admin?.components?.AfterList
+
+ const afterListTable = collectionConfig?.admin?.components?.AfterListTable
+
+ const SaveButtonComponent = collectionConfig?.admin?.components?.edit?.SaveButton
+ const SaveButton = SaveButtonComponent ? : undefined
+
+ const SaveDraftButtonComponent = collectionConfig?.admin?.components?.edit?.SaveDraftButton
+ const SaveDraftButton = SaveDraftButtonComponent ? : undefined
+
+ const PreviewButtonComponent = collectionConfig?.admin?.components?.edit?.PreviewButton
+ const PreviewButton = PreviewButtonComponent ? : undefined
+
+ const PublishButtonComponent = collectionConfig?.admin?.components?.edit?.PublishButton
+ const PublishButton = PublishButtonComponent ? : undefined
+
+ const BeforeList =
+ (beforeList && Array.isArray(beforeList) && beforeList?.map((Component) => )) ||
+ null
+
+ const BeforeListTable =
+ (beforeListTable &&
+ Array.isArray(beforeListTable) &&
+ beforeListTable?.map((Component) => )) ||
+ null
+
+ const AfterList =
+ (afterList && Array.isArray(afterList) && afterList?.map((Component) => )) ||
+ null
+
+ const AfterListTable =
+ (afterListTable &&
+ Array.isArray(afterListTable) &&
+ afterListTable?.map((Component) => )) ||
+ null
+
+ const descriptionProps: ViewDescriptionProps = {
+ description:
+ (collectionConfig.admin &&
+ 'description' in collectionConfig.admin &&
+ (((typeof collectionConfig.admin?.description === 'string' ||
+ typeof collectionConfig.admin?.description === 'object') &&
+ collectionConfig.admin.description) ||
+ (typeof collectionConfig.admin?.description === 'function' &&
+ isPlainFunction(collectionConfig.admin?.description) &&
+ collectionConfig.admin?.description()))) ||
+ undefined,
+ }
+
+ const DescriptionComponent =
+ (collectionConfig.admin &&
+ 'description' in collectionConfig.admin &&
+ ((isReactComponent(collectionConfig.admin.description) &&
+ collectionConfig.admin.description) ||
+ (collectionConfig.admin.description && ViewDescription))) ||
+ undefined
+
+ const Description =
+ DescriptionComponent !== undefined ? (
+
+ ) : undefined
+
+ const componentMap: CollectionComponentMap = {
+ AfterList,
+ AfterListTable,
+ BeforeList,
+ BeforeListTable,
+ Description,
+ Edit: ,
+ List:
,
+ PreviewButton,
+ PublishButton,
+ SaveButton,
+ SaveDraftButton,
+ actionsMap: mapActions({
+ collectionConfig,
+ }),
+ fieldMap: mapFields({
+ config,
+ fieldSchema: fields,
+ readOnly: readOnlyOverride,
+ }),
+ isPreviewEnabled: !!collectionConfig?.admin?.preview,
+ }
+
+ return {
+ ...acc,
+ [slug]: componentMap,
+ }
+ }, {})
diff --git a/packages/ui/src/providers/ComponentMap/buildComponentMap/mapFields.tsx b/packages/ui/src/providers/ComponentMap/buildComponentMap/fields.tsx
similarity index 99%
rename from packages/ui/src/providers/ComponentMap/buildComponentMap/mapFields.tsx
rename to packages/ui/src/providers/ComponentMap/buildComponentMap/fields.tsx
index 7947bd1e8f..5bd1765461 100644
--- a/packages/ui/src/providers/ComponentMap/buildComponentMap/mapFields.tsx
+++ b/packages/ui/src/providers/ComponentMap/buildComponentMap/fields.tsx
@@ -154,7 +154,7 @@ export const mapFields = (args: {
'description' in field.admin &&
((isReactComponent(field.admin.description) &&
field.admin.description) ||
- (isPlainFunction(field.admin.description) && FieldDescription))) ||
+ (field.admin.description && FieldDescription))) ||
undefined
const CustomDescription =
diff --git a/packages/ui/src/providers/ComponentMap/buildComponentMap/globals.tsx b/packages/ui/src/providers/ComponentMap/buildComponentMap/globals.tsx
new file mode 100644
index 0000000000..544c6b3f3b
--- /dev/null
+++ b/packages/ui/src/providers/ComponentMap/buildComponentMap/globals.tsx
@@ -0,0 +1,109 @@
+import type {
+ EditViewProps,
+ EntityDescriptionComponent,
+ EntityDescriptionFunction,
+ SanitizedConfig,
+ SanitizedGlobalConfig,
+} from 'payload/types'
+
+import { ViewDescription, type ViewDescriptionProps } from '@payloadcms/ui/elements/ViewDescription'
+import { isPlainFunction, isReactComponent } from 'payload/utilities'
+import React from 'react'
+
+import type { GlobalComponentMap } from './types.js'
+
+import { mapActions } from './actions.js'
+import { mapFields } from './fields.js'
+
+export const mapGlobals = ({
+ DefaultEditView,
+ config,
+ globals,
+ readOnly: readOnlyOverride,
+}: {
+ DefaultEditView: React.FC
+ config: SanitizedConfig
+ globals: SanitizedGlobalConfig[]
+ readOnly?: boolean
+}): {
+ [key: SanitizedGlobalConfig['slug']]: GlobalComponentMap
+} =>
+ globals.reduce((acc, globalConfig) => {
+ const { slug, fields } = globalConfig
+
+ const editViewFromConfig = globalConfig?.admin?.components?.views?.Edit
+
+ const SaveButton = globalConfig?.admin?.components?.elements?.SaveButton
+ const SaveButtonComponent = SaveButton ? : undefined
+
+ const SaveDraftButton = globalConfig?.admin?.components?.elements?.SaveDraftButton
+ const SaveDraftButtonComponent = SaveDraftButton ? : undefined
+
+ const PreviewButton = globalConfig?.admin?.components?.elements?.PreviewButton
+ const PreviewButtonComponent = PreviewButton ? : undefined
+
+ const PublishButton = globalConfig?.admin?.components?.elements?.PublishButton
+ const PublishButtonComponent = PublishButton ? : undefined
+
+ const CustomEditView =
+ typeof editViewFromConfig === 'function'
+ ? editViewFromConfig
+ : typeof editViewFromConfig === 'object' && typeof editViewFromConfig.Default === 'function'
+ ? editViewFromConfig.Default
+ : typeof editViewFromConfig?.Default === 'object' &&
+ 'Component' in editViewFromConfig.Default &&
+ typeof editViewFromConfig.Default.Component === 'function'
+ ? editViewFromConfig.Default.Component
+ : undefined
+
+ const Edit = (CustomEditView as React.FC) || DefaultEditView
+
+ const descriptionProps: ViewDescriptionProps = {
+ description:
+ (globalConfig.admin &&
+ 'description' in globalConfig.admin &&
+ (((typeof globalConfig.admin?.description === 'string' ||
+ typeof globalConfig.admin?.description === 'object') &&
+ globalConfig.admin.description) ||
+ (typeof globalConfig.admin?.description === 'function' &&
+ isPlainFunction(globalConfig.admin?.description) &&
+ globalConfig.admin?.description()))) ||
+ undefined,
+ }
+
+ const DescriptionComponent =
+ (globalConfig.admin &&
+ 'description' in globalConfig.admin &&
+ ((isReactComponent(globalConfig.admin.description) &&
+ globalConfig.admin.description) ||
+ (globalConfig.admin.description && ViewDescription))) ||
+ undefined
+
+ const Description =
+ DescriptionComponent !== undefined ? (
+
+ ) : undefined
+
+ const componentMap: GlobalComponentMap = {
+ Description,
+ Edit: ,
+ PreviewButton: PreviewButtonComponent,
+ PublishButton: PublishButtonComponent,
+ SaveButton: SaveButtonComponent,
+ SaveDraftButton: SaveDraftButtonComponent,
+ actionsMap: mapActions({
+ globalConfig,
+ }),
+ fieldMap: mapFields({
+ config,
+ fieldSchema: fields,
+ readOnly: readOnlyOverride,
+ }),
+ isPreviewEnabled: !!globalConfig?.admin?.preview,
+ }
+
+ return {
+ ...acc,
+ [slug]: componentMap,
+ }
+ }, {})
diff --git a/packages/ui/src/providers/ComponentMap/buildComponentMap/index.tsx b/packages/ui/src/providers/ComponentMap/buildComponentMap/index.tsx
index 1d4c623f64..f9f669aa63 100644
--- a/packages/ui/src/providers/ComponentMap/buildComponentMap/index.tsx
+++ b/packages/ui/src/providers/ComponentMap/buildComponentMap/index.tsx
@@ -1,15 +1,15 @@
-import type { EditViewProps, SanitizedConfig } from 'payload/types'
+import type { AdminViewProps, EditViewProps, SanitizedConfig } from 'payload/types'
import React from 'react'
-import type { CollectionComponentMap, ComponentMap, GlobalComponentMap } from './types.js'
+import type { ComponentMap } from './types.js'
-import { mapActions } from './mapActions.js'
-import { mapFields } from './mapFields.js'
+import { mapCollections } from './collections.js'
+import { mapGlobals } from './globals.js'
export const buildComponentMap = (args: {
DefaultEditView: React.FC
- DefaultListView: React.FC
+ DefaultListView: React.FC
children: React.ReactNode
config: SanitizedConfig
readOnly?: boolean
@@ -17,166 +17,22 @@ export const buildComponentMap = (args: {
componentMap: ComponentMap
wrappedChildren: React.ReactNode
} => {
- const { DefaultEditView, DefaultListView, children, config, readOnly: readOnlyOverride } = args
+ const { DefaultEditView, DefaultListView, children, config, readOnly } = args
- // Collections
- const collections = config.collections.reduce((acc, collectionConfig) => {
- const { slug, fields } = collectionConfig
+ const collections = mapCollections({
+ DefaultEditView,
+ DefaultListView,
+ collections: config.collections,
+ config,
+ readOnly,
+ })
- const internalCollections = ['payload-preferences', 'payload-migrations']
-
- if (internalCollections.includes(slug)) {
- return acc
- }
-
- const editViewFromConfig = collectionConfig?.admin?.components?.views?.Edit
-
- const listViewFromConfig = collectionConfig?.admin?.components?.views?.List
-
- const CustomEditView =
- typeof editViewFromConfig === 'function'
- ? editViewFromConfig
- : typeof editViewFromConfig === 'object' && typeof editViewFromConfig.Default === 'function'
- ? editViewFromConfig.Default
- : typeof editViewFromConfig?.Default === 'object' &&
- 'Component' in editViewFromConfig.Default &&
- typeof editViewFromConfig.Default.Component === 'function'
- ? (editViewFromConfig.Default.Component as React.FC)
- : undefined
-
- const CustomListView =
- typeof listViewFromConfig === 'function'
- ? listViewFromConfig
- : typeof listViewFromConfig === 'object' &&
- typeof listViewFromConfig.Component === 'function'
- ? listViewFromConfig.Component
- : undefined
-
- const Edit = (CustomEditView as React.FC) || DefaultEditView
-
- const List = CustomListView || DefaultListView
-
- const beforeList = collectionConfig?.admin?.components?.BeforeList
-
- const beforeListTable = collectionConfig?.admin?.components?.BeforeListTable
-
- const afterList = collectionConfig?.admin?.components?.AfterList
-
- const afterListTable = collectionConfig?.admin?.components?.AfterListTable
-
- const SaveButtonComponent = collectionConfig?.admin?.components?.edit?.SaveButton
- const SaveButton = SaveButtonComponent ? : undefined
-
- const SaveDraftButtonComponent = collectionConfig?.admin?.components?.edit?.SaveDraftButton
- const SaveDraftButton = SaveDraftButtonComponent ? : undefined
-
- const PreviewButtonComponent = collectionConfig?.admin?.components?.edit?.PreviewButton
- const PreviewButton = PreviewButtonComponent ? : undefined
-
- const PublishButtonComponent = collectionConfig?.admin?.components?.edit?.PublishButton
- const PublishButton = PublishButtonComponent ? : undefined
-
- const BeforeList =
- (beforeList && Array.isArray(beforeList) && beforeList?.map((Component) => )) ||
- null
-
- const BeforeListTable =
- (beforeListTable &&
- Array.isArray(beforeListTable) &&
- beforeListTable?.map((Component) => )) ||
- null
-
- const AfterList =
- (afterList && Array.isArray(afterList) && afterList?.map((Component) => )) ||
- null
-
- const AfterListTable =
- (afterListTable &&
- Array.isArray(afterListTable) &&
- afterListTable?.map((Component) => )) ||
- null
-
- const componentMap: CollectionComponentMap = {
- AfterList,
- AfterListTable,
- BeforeList,
- BeforeListTable,
- Edit: ,
- List:
,
- PreviewButton,
- PublishButton,
- SaveButton,
- SaveDraftButton,
- actionsMap: mapActions({
- collectionConfig,
- }),
- fieldMap: mapFields({
- config,
- fieldSchema: fields,
- readOnly: readOnlyOverride,
- }),
- isPreviewEnabled: !!collectionConfig?.admin?.preview,
- }
-
- return {
- ...acc,
- [slug]: componentMap,
- }
- }, {})
-
- // Globals
- const globals = config.globals.reduce((acc, globalConfig) => {
- const { slug, fields } = globalConfig
-
- const editViewFromConfig = globalConfig?.admin?.components?.views?.Edit
-
- const SaveButton = globalConfig?.admin?.components?.elements?.SaveButton
- const SaveButtonComponent = SaveButton ? : undefined
-
- const SaveDraftButton = globalConfig?.admin?.components?.elements?.SaveDraftButton
- const SaveDraftButtonComponent = SaveDraftButton ? : undefined
-
- const PreviewButton = globalConfig?.admin?.components?.elements?.PreviewButton
- const PreviewButtonComponent = PreviewButton ? : undefined
-
- const PublishButton = globalConfig?.admin?.components?.elements?.PublishButton
- const PublishButtonComponent = PublishButton ? : undefined
-
- const CustomEditView =
- typeof editViewFromConfig === 'function'
- ? editViewFromConfig
- : typeof editViewFromConfig === 'object' && typeof editViewFromConfig.Default === 'function'
- ? editViewFromConfig.Default
- : typeof editViewFromConfig?.Default === 'object' &&
- 'Component' in editViewFromConfig.Default &&
- typeof editViewFromConfig.Default.Component === 'function'
- ? editViewFromConfig.Default.Component
- : undefined
-
- const Edit = (CustomEditView as React.FC) || DefaultEditView
-
- const componentMap: GlobalComponentMap = {
- Edit: ,
- PreviewButton: PreviewButtonComponent,
- PublishButton: PublishButtonComponent,
- SaveButton: SaveButtonComponent,
- SaveDraftButton: SaveDraftButtonComponent,
- actionsMap: mapActions({
- globalConfig,
- }),
- fieldMap: mapFields({
- config,
- fieldSchema: fields,
- readOnly: readOnlyOverride,
- }),
- isPreviewEnabled: !!globalConfig?.admin?.preview,
- }
-
- return {
- ...acc,
- [slug]: componentMap,
- }
- }, {})
+ const globals = mapGlobals({
+ DefaultEditView,
+ config,
+ globals: config.globals,
+ readOnly,
+ })
const NestProviders = ({ children, providers }) => {
const Component = providers[0]
diff --git a/packages/ui/src/providers/ComponentMap/buildComponentMap/types.ts b/packages/ui/src/providers/ComponentMap/buildComponentMap/types.ts
index 34483d05b1..0383274540 100644
--- a/packages/ui/src/providers/ComponentMap/buildComponentMap/types.ts
+++ b/packages/ui/src/providers/ComponentMap/buildComponentMap/types.ts
@@ -101,6 +101,7 @@ export type CollectionComponentMap = ConfigComponentMapBase & {
export type GlobalComponentMap = ConfigComponentMapBase
export type ConfigComponentMapBase = {
+ Description: React.ReactNode
Edit: React.ReactNode
PreviewButton: React.ReactNode
PublishButton: React.ReactNode
diff --git a/packages/ui/src/providers/ListInfo/index.tsx b/packages/ui/src/providers/ListInfo/index.tsx
index 3aef0d67fe..696cb3461b 100644
--- a/packages/ui/src/providers/ListInfo/index.tsx
+++ b/packages/ui/src/providers/ListInfo/index.tsx
@@ -21,7 +21,6 @@ export type ListInfoContext = {
collectionSlug: string
hasCreatePermission: boolean
newDocumentURL: string
- titleField?: FieldAffectingData
}
const Context = createContext({} as ListInfoContext)
diff --git a/packages/ui/src/utilities/buildComponentMap.ts b/packages/ui/src/utilities/buildComponentMap.ts
index 0205acb97a..b4dd74d0d5 100644
--- a/packages/ui/src/utilities/buildComponentMap.ts
+++ b/packages/ui/src/utilities/buildComponentMap.ts
@@ -1,3 +1,3 @@
+export { mapFields } from '../providers/ComponentMap/buildComponentMap/fields.js'
export { buildComponentMap } from '../providers/ComponentMap/buildComponentMap/index.js'
-export { mapFields } from '../providers/ComponentMap/buildComponentMap/mapFields.js'
export type * from '../providers/ComponentMap/buildComponentMap/types.js'
diff --git a/test/admin/e2e.spec.ts b/test/admin/e2e.spec.ts
index b4335c6b11..12337a7dd0 100644
--- a/test/admin/e2e.spec.ts
+++ b/test/admin/e2e.spec.ts
@@ -679,7 +679,7 @@ describe('admin', () => {
// delete all posts created by the seed
await deleteAllPosts()
await page.goto(postsUrl.list)
- await page.waitForURL(postsUrl.list)
+ await page.waitForURL((url) => url.toString().startsWith(postsUrl.list))
await expect(page.locator(tableRowLocator)).toBeHidden()
await createPost({ title: 'post1' })
@@ -695,6 +695,7 @@ describe('admin', () => {
// prefill search with "a" from the query param
await page.goto(`${postsUrl.list}?search=dennis`)
+ await page.waitForURL(`${postsUrl.list}?search=dennis`)
// input should be filled out, list should filter
await expect(page.locator('.search-filter__input')).toHaveValue('dennis')
@@ -1264,7 +1265,7 @@ describe('admin', () => {
})
describe('i18n', () => {
- test.skip('should display translated collections and globals config options', async () => {
+ test('should display translated collections and globals config options', async () => {
await page.goto(postsUrl.list)
// collection label
@@ -1277,7 +1278,7 @@ describe('admin', () => {
await expect(page.locator('.view-description')).toContainText('Description')
})
- test.skip('should display translated field titles', async () => {
+ test('should display translated field titles', async () => {
await createPost()
// column controls