diff --git a/packages/payload/src/admin/components/elements/DocumentControls/index.tsx b/packages/payload/src/admin/components/elements/DocumentControls/index.tsx index 8323155fe..ceafd0116 100644 --- a/packages/payload/src/admin/components/elements/DocumentControls/index.tsx +++ b/packages/payload/src/admin/components/elements/DocumentControls/index.tsx @@ -32,7 +32,7 @@ export const DocumentControls: React.FC<{ id?: string isAccountView?: boolean isEditing?: boolean - permissions?: CollectionPermission | GlobalPermission + permissions?: CollectionPermission | GlobalPermission | null }> = (props) => { const { id, diff --git a/packages/payload/src/admin/components/elements/DocumentDrawer/DrawerContent.tsx b/packages/payload/src/admin/components/elements/DocumentDrawer/DrawerContent.tsx index 87e4991dd..523ab86e7 100644 --- a/packages/payload/src/admin/components/elements/DocumentDrawer/DrawerContent.tsx +++ b/packages/payload/src/admin/components/elements/DocumentDrawer/DrawerContent.tsx @@ -97,7 +97,7 @@ const Content: React.FC = ({ awaitInitialState() hasInitializedState.current = true - }, [data, fields, id, user, locale, isLoadingDocument, t, getDocPreferences]) + }, [data, fields, id, user, locale, isLoadingDocument, t, getDocPreferences, config]) useEffect(() => { setIsOpen(Boolean(modalState[drawerSlug]?.isOpen)) diff --git a/packages/payload/src/admin/components/forms/Form/buildStateFromSchema/index.ts b/packages/payload/src/admin/components/forms/Form/buildStateFromSchema/index.ts index 5090e9103..fc6a13d4d 100644 --- a/packages/payload/src/admin/components/forms/Form/buildStateFromSchema/index.ts +++ b/packages/payload/src/admin/components/forms/Form/buildStateFromSchema/index.ts @@ -10,7 +10,7 @@ import { iterateFields } from './iterateFields' type Args = { config: SanitizedConfig data?: Data - fieldSchema: FieldSchema[] + fieldSchema: FieldSchema[] | undefined id?: number | string locale: string operation?: 'create' | 'update' @@ -19,7 +19,7 @@ type Args = { } siblingData?: Data t: TFunction - user?: User + user?: User | null } const buildStateFromSchema = async (args: Args): Promise => { diff --git a/packages/payload/src/admin/components/utilities/Locale/index.tsx b/packages/payload/src/admin/components/utilities/Locale/index.tsx index b7348119f..de47c20a0 100644 --- a/packages/payload/src/admin/components/utilities/Locale/index.tsx +++ b/packages/payload/src/admin/components/utilities/Locale/index.tsx @@ -8,7 +8,7 @@ import { useConfig } from '../Config' import { usePreferences } from '../Preferences' import { useSearchParams } from '../SearchParams' -const LocaleContext = createContext(null) +const LocaleContext = createContext({} as Locale) export const LocaleProvider: React.FC<{ children?: React.ReactNode }> = ({ children }) => { const { localization } = useConfig() @@ -65,5 +65,6 @@ export const LocaleProvider: React.FC<{ children?: React.ReactNode }> = ({ child /** * A hook that returns the current locale object. */ -export const useLocale = (): Locale | null => useContext(LocaleContext) +export const useLocale = (): Locale => useContext(LocaleContext) + export default LocaleContext diff --git a/packages/payload/src/admin/components/utilities/OperationProvider/index.tsx b/packages/payload/src/admin/components/utilities/OperationProvider/index.tsx index fb26c01e8..72d719225 100644 --- a/packages/payload/src/admin/components/utilities/OperationProvider/index.tsx +++ b/packages/payload/src/admin/components/utilities/OperationProvider/index.tsx @@ -1,6 +1,6 @@ import { createContext, useContext } from 'react' -export const OperationContext = createContext(undefined) +export const OperationContext = createContext('' as Operation) export type Operation = 'create' | 'update' diff --git a/packages/payload/src/admin/components/utilities/RenderCustomComponent/types.ts b/packages/payload/src/admin/components/utilities/RenderCustomComponent/types.ts index 0cdd3d693..645f18af4 100644 --- a/packages/payload/src/admin/components/utilities/RenderCustomComponent/types.ts +++ b/packages/payload/src/admin/components/utilities/RenderCustomComponent/types.ts @@ -1,7 +1,7 @@ import type React from 'react' export type Props = { - CustomComponent: React.ComponentType + CustomComponent?: React.ComponentType DefaultComponent: React.ComponentType componentProps?: Record } diff --git a/packages/payload/src/admin/components/views/Account/Default.tsx b/packages/payload/src/admin/components/views/Account/Default.tsx index ffb780073..7cb447f96 100644 --- a/packages/payload/src/admin/components/views/Account/Default.tsx +++ b/packages/payload/src/admin/components/views/Account/Default.tsx @@ -41,10 +41,12 @@ const DefaultAccount: React.FC = (props) => { const { refreshCookieAsync } = useAuth() const { i18n, t } = useTranslation('authentication') - const languageOptions = Object.entries(i18n.options.resources).map(([language, resource]) => ({ - label: (resource as Translation).general.thisLanguage, - value: language, - })) + const languageOptions = Object.entries(i18n.options.resources || {}).map( + ([language, resource]) => ({ + label: (resource as Translation).general.thisLanguage, + value: language, + }), + ) const onSave = useCallback(async () => { await refreshCookieAsync() @@ -101,7 +103,7 @@ const DefaultAccount: React.FC = (props) => { fieldSchema={fields} fieldTypes={fieldTypes} filter={(field) => field?.admin?.position !== 'sidebar'} - permissions={permissions.fields} + permissions={permissions?.fields} readOnly={!hasSavePermission} /> @@ -128,7 +130,7 @@ const DefaultAccount: React.FC = (props) => { fieldSchema={fields} fieldTypes={fieldTypes} filter={(field) => field?.admin?.position === 'sidebar'} - permissions={permissions.fields} + permissions={permissions?.fields} readOnly={!hasSavePermission} /> diff --git a/packages/payload/src/admin/components/views/Account/index.tsx b/packages/payload/src/admin/components/views/Account/index.tsx index 62b4a9ca8..f9f184c32 100644 --- a/packages/payload/src/admin/components/views/Account/index.tsx +++ b/packages/payload/src/admin/components/views/Account/index.tsx @@ -25,6 +25,7 @@ const AccountView: React.FC = () => { const { id, docPermissions, getDocPermissions, getDocPreferences, preferencesKey, slug } = useDocumentInfo() const { getPreference } = usePreferences() + const config = useConfig() const { @@ -44,7 +45,7 @@ const AccountView: React.FC = () => { const collection = collections.find((coll) => coll.slug === slug) - const { fields } = collection + const { fields } = collection || {} const [{ data, isLoading: isLoadingData }] = usePayloadAPI(`${serverURL}${api}/${slug}/${id}`, { initialData: null, @@ -63,12 +64,14 @@ const AccountView: React.FC = () => { const onSave = React.useCallback( async (json: any) => { getDocPermissions() + const preferences = await getDocPreferences() + const state = await buildStateFromSchema({ id, config, data: json.doc, - fieldSchema: collection.fields, + fieldSchema: collection?.fields, locale, operation: 'update', preferences, @@ -77,7 +80,7 @@ const AccountView: React.FC = () => { }) setInternalState(state) }, - [collection, user, id, t, locale, getDocPermissions, getDocPreferences], + [collection, user, id, t, locale, getDocPermissions, getDocPreferences, config], ) useEffect(() => { @@ -106,12 +109,25 @@ const AccountView: React.FC = () => { user: userRef.current, }) - await getPreference(preferencesKey) + if (preferencesKey) { + await getPreference(preferencesKey) + } + setInternalState(state) } if (dataToRender) awaitInternalState() - }, [dataToRender, fields, id, locale, preferencesKey, getPreference, t, getDocPreferences]) + }, [ + dataToRender, + fields, + id, + locale, + preferencesKey, + getPreference, + t, + getDocPreferences, + config, + ]) const isLoading = !internalState || !docPermissions || isLoadingData diff --git a/packages/payload/src/admin/components/views/Dashboard/index.tsx b/packages/payload/src/admin/components/views/Dashboard/index.tsx index 1bec2722c..47c3a91e6 100644 --- a/packages/payload/src/admin/components/views/Dashboard/index.tsx +++ b/packages/payload/src/admin/components/views/Dashboard/index.tsx @@ -1,5 +1,7 @@ import React, { useEffect, useState } from 'react' +import type { SanitizedGlobalConfig } from '../../../../exports/types' + import { useStepNav } from '../../elements/StepNav' import { useAuth } from '../../utilities/Auth' import { useConfig } from '../../utilities/Config' @@ -9,7 +11,7 @@ import DefaultDashboard from './Default' const Dashboard: React.FC = () => { const { permissions, user } = useAuth() const { setStepNav } = useStepNav() - const [filteredGlobals, setFilteredGlobals] = useState([]) + const [filteredGlobals, setFilteredGlobals] = useState([]) const { admin: { diff --git a/packages/payload/src/admin/components/views/Global/index.tsx b/packages/payload/src/admin/components/views/Global/index.tsx index c98225f2b..c220d8b84 100644 --- a/packages/payload/src/admin/components/views/Global/index.tsx +++ b/packages/payload/src/admin/components/views/Global/index.tsx @@ -43,7 +43,9 @@ const GlobalView: React.FC = (props) => { getVersions() getDocPermissions() setUpdatedAt(json?.result?.updatedAt) + const preferences = await getDocPreferences() + const state = await buildStateFromSchema({ config, data: json.result, @@ -56,7 +58,7 @@ const GlobalView: React.FC = (props) => { }) setInitialState(state) }, - [getVersions, fields, user, locale, t, getDocPermissions, getDocPreferences], + [getVersions, fields, user, locale, t, getDocPermissions, getDocPreferences, config], ) const [{ data, isLoading: isLoadingData }] = usePayloadAPI(`${serverURL}${api}/globals/${slug}`, { @@ -79,12 +81,26 @@ const GlobalView: React.FC = (props) => { t, user, }) - await getPreference(preferencesKey) + + if (preferencesKey) { + await getPreference(preferencesKey) + } + setInitialState(state) } if (dataToRender) awaitInitialState() - }, [dataToRender, fields, user, locale, getPreference, preferencesKey, t, getDocPreferences]) + }, [ + dataToRender, + fields, + user, + locale, + getPreference, + preferencesKey, + t, + getDocPreferences, + config, + ]) const isLoading = !initialState || !docPermissions || isLoadingData diff --git a/packages/payload/src/admin/components/views/LivePreview/DeviceContainer/index.tsx b/packages/payload/src/admin/components/views/LivePreview/DeviceContainer/index.tsx index f8ee6b5ec..302b16797 100644 --- a/packages/payload/src/admin/components/views/LivePreview/DeviceContainer/index.tsx +++ b/packages/payload/src/admin/components/views/LivePreview/DeviceContainer/index.tsx @@ -9,7 +9,7 @@ export const DeviceContainer: React.FC<{ const { breakpoint, breakpoints, deviceFrameRef, size, zoom } = useLivePreviewContext() - const foundBreakpoint = breakpoint && breakpoints.find((bp) => bp.name === breakpoint) + const foundBreakpoint = breakpoint && breakpoints?.find((bp) => bp.name === breakpoint) let x = '0' let margin = '0' diff --git a/packages/payload/src/admin/components/views/Login/index.tsx b/packages/payload/src/admin/components/views/Login/index.tsx index 1e14d097c..44dc0745b 100644 --- a/packages/payload/src/admin/components/views/Login/index.tsx +++ b/packages/payload/src/admin/components/views/Login/index.tsx @@ -70,7 +70,7 @@ const Login: React.FC = () => { {Array.isArray(beforeLogin) && beforeLogin.map((Component, i) => )} - {!collection.auth.disableLocalStrategy && ( + {!collection?.auth?.disableLocalStrategy && (
import('../collections/Edit')) - // @ts-expect-error Just TypeScript being broken // TODO: Open TypeScript issue const Unauthorized = lazy(() => import('../Unauthorized')) diff --git a/packages/payload/src/admin/components/views/Routes/custom.tsx b/packages/payload/src/admin/components/views/Routes/custom.tsx index b489f422d..f663c1883 100644 --- a/packages/payload/src/admin/components/views/Routes/custom.tsx +++ b/packages/payload/src/admin/components/views/Routes/custom.tsx @@ -5,10 +5,10 @@ import type { User } from '../../../../auth' import type { SanitizedConfig } from '../../../../exports/config' export const customRoutes = (props: { - canAccessAdmin: boolean - customRoutes: SanitizedConfig['admin']['components']['routes'] + canAccessAdmin?: boolean + customRoutes?: SanitizedConfig['admin']['components']['routes'] match: { url: string } - user: User + user: User | null | undefined }) => { const { canAccessAdmin, customRoutes, match, user } = props diff --git a/packages/payload/src/admin/components/views/Routes/globals.tsx b/packages/payload/src/admin/components/views/Routes/globals.tsx index b4618a859..f0436552c 100644 --- a/packages/payload/src/admin/components/views/Routes/globals.tsx +++ b/packages/payload/src/admin/components/views/Routes/globals.tsx @@ -11,7 +11,6 @@ import { DocumentInfoProvider } from '../../utilities/DocumentInfo' // @ts-expect-error Just TypeScript being broken // TODO: Open TypeScript issue const EditGlobal = lazy(() => import('../Global')) - // @ts-expect-error Just TypeScript being broken // TODO: Open TypeScript issue const Unauthorized = lazy(() => import('../Unauthorized')) diff --git a/packages/payload/src/admin/components/views/Routes/index.tsx b/packages/payload/src/admin/components/views/Routes/index.tsx index 89b74b28b..549423c9f 100644 --- a/packages/payload/src/admin/components/views/Routes/index.tsx +++ b/packages/payload/src/admin/components/views/Routes/index.tsx @@ -34,7 +34,7 @@ const ResetPassword = lazy(() => import('../ResetPassword')) const Account = lazy(() => import('../Account')) export const Routes: React.FC = () => { - const [initialized, setInitialized] = useState(null) + const [initialized, setInitialized] = useState(null) const { permissions, refreshCookie, user } = useAuth() const { i18n } = useTranslation() const { code: locale } = useLocale() @@ -62,9 +62,9 @@ export const Routes: React.FC = () => { const userCollection = collections.find(({ slug }) => slug === userSlug) useEffect(() => { - const { slug } = userCollection + if (userCollection && !userCollection?.auth?.disableLocalStrategy) { + const { slug } = userCollection - if (!userCollection.auth.disableLocalStrategy) { requests .get(`${routes.api}/${slug}/init`, { headers: { @@ -123,12 +123,12 @@ export const Routes: React.FC = () => { - {!userCollection.auth.disableLocalStrategy && ( + {!userCollection?.auth?.disableLocalStrategy && ( )} - {!userCollection.auth.disableLocalStrategy && ( + {!userCollection?.auth?.disableLocalStrategy && ( diff --git a/packages/payload/src/admin/components/views/Verify/index.tsx b/packages/payload/src/admin/components/views/Verify/index.tsx index 109554913..c1f6274e6 100644 --- a/packages/payload/src/admin/components/views/Verify/index.tsx +++ b/packages/payload/src/admin/components/views/Verify/index.tsx @@ -28,7 +28,7 @@ const Verify: React.FC<{ collection: SanitizedCollectionConfig }> = ({ collectio const { i18n, t } = useTranslation('authentication') const isAdminUser = collectionSlug === adminUser - const [verifyResult, setVerifyResult] = useState(null) + const [verifyResult, setVerifyResult] = useState(null) useEffect(() => { async function verifyToken() { diff --git a/packages/payload/src/admin/components/views/collections/Edit/formatFields.tsx b/packages/payload/src/admin/components/views/collections/Edit/formatFields.tsx index d5b16c19f..ac8ed3d65 100644 --- a/packages/payload/src/admin/components/views/collections/Edit/formatFields.tsx +++ b/packages/payload/src/admin/components/views/collections/Edit/formatFields.tsx @@ -3,7 +3,7 @@ import type { Field } from '../../../../../fields/config/types' import { fieldAffectsData } from '../../../../../fields/config/types' -const formatFields = (collection: SanitizedCollectionConfig, isEditing: boolean): Field[] => +const formatFields = (collection: SanitizedCollectionConfig, isEditing?: boolean): Field[] => isEditing ? collection.fields.filter((field) => (fieldAffectsData(field) && field.name !== 'id') || true) : collection.fields diff --git a/packages/payload/src/admin/components/views/collections/Edit/index.tsx b/packages/payload/src/admin/components/views/collections/Edit/index.tsx index de0c6ade2..029a7db6d 100644 --- a/packages/payload/src/admin/components/views/collections/Edit/index.tsx +++ b/packages/payload/src/admin/components/views/collections/Edit/index.tsx @@ -47,7 +47,7 @@ const EditView: React.FC = (props) => { const { t } = useTranslation('general') const [{ data, isError, isLoading: isLoadingData }] = usePayloadAPI( - isEditing ? `${serverURL}${api}/${collectionSlug}/${id}` : null, + isEditing ? `${serverURL}${api}/${collectionSlug}/${id}` : '', { initialData: null, initialParams: { depth: 0, draft: 'true', 'fallback-locale': 'null' } }, ) @@ -59,7 +59,7 @@ const EditView: React.FC = (props) => { id, config, data: doc || {}, - fieldSchema: overrides.fieldSchema, + fieldSchema: overrides?.fieldSchema, locale, operation: 'update', preferences, @@ -70,7 +70,7 @@ const EditView: React.FC = (props) => { setInternalState(state) }, - [getDocPreferences, id, locale, t], + [getDocPreferences, id, locale, t, config], ) const onSave = useCallback( diff --git a/packages/payload/src/admin/components/views/types.ts b/packages/payload/src/admin/components/views/types.ts index f9e2a8d87..8547310df 100644 --- a/packages/payload/src/admin/components/views/types.ts +++ b/packages/payload/src/admin/components/views/types.ts @@ -9,29 +9,29 @@ export type CollectionEditViewProps = BaseEditViewProps & { collection: SanitizedCollectionConfig disableActions?: boolean disableLeaveWithoutSaving?: boolean - hasSavePermission: boolean + hasSavePermission?: boolean id: string initialState?: Fields - internalState: Fields - isEditing: boolean - permissions: CollectionPermission + internalState?: Fields + isEditing?: boolean + permissions: CollectionPermission | null } export type GlobalEditViewProps = BaseEditViewProps & { global: SanitizedGlobalConfig - initialState: Fields - permissions: GlobalPermission + initialState?: Fields + permissions: GlobalPermission | null } export type BaseEditViewProps = { action: string apiURL: string - canAccessAdmin: boolean + canAccessAdmin?: boolean data: any isLoading: boolean onSave: (json: any) => void updatedAt: string - user: User + user: User | null | undefined } export type EditViewProps = CollectionEditViewProps | GlobalEditViewProps diff --git a/packages/payload/src/config/types.ts b/packages/payload/src/config/types.ts index 8c162c203..37d6f6f52 100644 --- a/packages/payload/src/config/types.ts +++ b/packages/payload/src/config/types.ts @@ -7,9 +7,9 @@ import type SMTPConnection from 'nodemailer/lib/smtp-connection' import type { DestinationStream, LoggerOptions } from 'pino' import type React from 'react' import type { DeepRequired } from 'ts-essentials' -import type { Configuration } from 'webpack' // @ts-expect-error import type { InlineConfig } from 'vite' +import type { Configuration } from 'webpack' import type { DocumentTab } from '../admin/components/elements/DocumentHeader/Tabs/types' import type { RichTextAdapter } from '../admin/components/forms/field-types/RichText/types' @@ -114,16 +114,16 @@ export type InitOptions = { */ config?: Promise - /** - * Disable running of the `onInit` function - */ - disableOnInit?: boolean - /** * Disable connect to the database on init */ disableDBConnect?: boolean + /** + * Disable running of the `onInit` function + */ + disableOnInit?: boolean + /** * Configuration for Payload's email functionality * @@ -230,10 +230,10 @@ export type Endpoint = { } export type CustomAdminView = React.ComponentType<{ - canAccessAdmin: boolean + canAccessAdmin?: boolean collection?: SanitizedCollectionConfig global?: SanitizedGlobalConfig - user: User + user: User | null | undefined }> export type EditViewConfig = { @@ -460,10 +460,10 @@ export type Config = { } /** The slug of a Collection that you want be used to log in to the Admin dashboard. */ user?: string - /** Customize the Webpack config that's used to generate the Admin panel. */ - webpack?: (config: Configuration) => Configuration /** Customize the Vite config that's used to generate the Admin panel. */ vite?: (config: InlineConfig) => InlineConfig + /** Customize the Webpack config that's used to generate the Admin panel. */ + webpack?: (config: Configuration) => Configuration } /** * Manage the datamodel of your application diff --git a/packages/richtext-lexical/src/field/features/Link/plugins/floatingLinkEditor/LinkEditor/index.tsx b/packages/richtext-lexical/src/field/features/Link/plugins/floatingLinkEditor/LinkEditor/index.tsx index e605f302b..f1b65c4f7 100644 --- a/packages/richtext-lexical/src/field/features/Link/plugins/floatingLinkEditor/LinkEditor/index.tsx +++ b/packages/richtext-lexical/src/field/features/Link/plugins/floatingLinkEditor/LinkEditor/index.tsx @@ -189,7 +189,7 @@ export function LinkEditor({ } return true - }, [anchorElem, editor, fieldSchema]) + }, [anchorElem, editor, fieldSchema, config, getDocPreferences, locale, t, user, i18n]) useEffect(() => { return mergeRegister( diff --git a/packages/richtext-slate/src/field/elements/link/Element/index.tsx b/packages/richtext-slate/src/field/elements/link/Element/index.tsx index 5d5a631df..ebab0dcab 100644 --- a/packages/richtext-slate/src/field/elements/link/Element/index.tsx +++ b/packages/richtext-slate/src/field/elements/link/Element/index.tsx @@ -124,7 +124,7 @@ export const LinkElement: React.FC<{ } awaitInitialState() - }, [renderModal, element, fieldSchema, user, locale, t, getDocPreferences]) + }, [renderModal, element, fieldSchema, user, locale, t, getDocPreferences, config]) return (