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