chore: adjusts endpoint for buildFormState
This commit is contained in:
@@ -8,4 +8,5 @@ export default ({ params, searchParams }) =>
|
|||||||
collectionSlug: params.collection,
|
collectionSlug: params.collection,
|
||||||
searchParams,
|
searchParams,
|
||||||
config,
|
config,
|
||||||
|
route: `/${params.collection + '/' + params.segments?.join('/')}`,
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -3,4 +3,4 @@
|
|||||||
import { Dashboard } from '@payloadcms/next/pages/Dashboard'
|
import { Dashboard } from '@payloadcms/next/pages/Dashboard'
|
||||||
import config from 'payload-config'
|
import config from 'payload-config'
|
||||||
|
|
||||||
export default async () => Dashboard({ config })
|
export default async ({ searchParams }) => Dashboard({ config, searchParams })
|
||||||
|
|||||||
@@ -22,6 +22,8 @@ export const Account = async ({
|
|||||||
const { config, payload, permissions, user, i18n, locale } = await initPage({
|
const { config, payload, permissions, user, i18n, locale } = await initPage({
|
||||||
config: configPromise,
|
config: configPromise,
|
||||||
redirectUnauthenticatedUser: true,
|
redirectUnauthenticatedUser: true,
|
||||||
|
searchParams,
|
||||||
|
route: `/account`,
|
||||||
})
|
})
|
||||||
|
|
||||||
const {
|
const {
|
||||||
|
|||||||
@@ -15,15 +15,19 @@ export const CollectionList = async ({
|
|||||||
collectionSlug,
|
collectionSlug,
|
||||||
config: configPromise,
|
config: configPromise,
|
||||||
searchParams,
|
searchParams,
|
||||||
|
route,
|
||||||
}: {
|
}: {
|
||||||
collectionSlug: string
|
collectionSlug: string
|
||||||
config: Promise<SanitizedConfig>
|
config: Promise<SanitizedConfig>
|
||||||
searchParams: { [key: string]: string | string[] | undefined }
|
searchParams: { [key: string]: string | string[] | undefined }
|
||||||
|
route
|
||||||
}) => {
|
}) => {
|
||||||
const { config, payload, permissions, user, collectionConfig } = await initPage({
|
const { config, payload, permissions, user, collectionConfig } = await initPage({
|
||||||
config: configPromise,
|
config: configPromise,
|
||||||
redirectUnauthenticatedUser: true,
|
redirectUnauthenticatedUser: true,
|
||||||
collectionSlug,
|
collectionSlug,
|
||||||
|
route,
|
||||||
|
searchParams,
|
||||||
})
|
})
|
||||||
|
|
||||||
let listPreferences: ListPreferences
|
let listPreferences: ListPreferences
|
||||||
|
|||||||
@@ -7,12 +7,16 @@ import { DefaultDashboard } from './Default'
|
|||||||
|
|
||||||
export const Dashboard = async ({
|
export const Dashboard = async ({
|
||||||
config: configPromise,
|
config: configPromise,
|
||||||
|
searchParams,
|
||||||
}: {
|
}: {
|
||||||
config: Promise<SanitizedConfig>
|
config: Promise<SanitizedConfig>
|
||||||
|
searchParams: { [key: string]: string | string[] | undefined }
|
||||||
}) => {
|
}) => {
|
||||||
const { config, user, permissions } = await initPage({
|
const { config, user, permissions } = await initPage({
|
||||||
config: configPromise,
|
config: configPromise,
|
||||||
redirectUnauthenticatedUser: true,
|
redirectUnauthenticatedUser: true,
|
||||||
|
route: '',
|
||||||
|
searchParams,
|
||||||
})
|
})
|
||||||
|
|
||||||
const CustomDashboardComponent = config.admin.components?.views?.Dashboard
|
const CustomDashboardComponent = config.admin.components?.views?.Dashboard
|
||||||
|
|||||||
@@ -43,12 +43,16 @@ export const Document = async ({
|
|||||||
|
|
||||||
const isEditing = Boolean(globalSlug || (collectionSlug && !!id))
|
const isEditing = Boolean(globalSlug || (collectionSlug && !!id))
|
||||||
|
|
||||||
|
const route = `/${collectionSlug || globalSlug + '/' + params.segments.join('/')}`
|
||||||
|
|
||||||
const { config, payload, permissions, user, collectionConfig, globalConfig, locale, i18n } =
|
const { config, payload, permissions, user, collectionConfig, globalConfig, locale, i18n } =
|
||||||
await initPage({
|
await initPage({
|
||||||
config: configPromise,
|
config: configPromise,
|
||||||
redirectUnauthenticatedUser: true,
|
redirectUnauthenticatedUser: true,
|
||||||
collectionSlug,
|
collectionSlug,
|
||||||
globalSlug,
|
globalSlug,
|
||||||
|
searchParams,
|
||||||
|
route,
|
||||||
})
|
})
|
||||||
|
|
||||||
if (!collectionConfig && !globalConfig) {
|
if (!collectionConfig && !globalConfig) {
|
||||||
@@ -149,7 +153,7 @@ export const Document = async ({
|
|||||||
limit: 1,
|
limit: 1,
|
||||||
})) as any as { docs: { value: DocumentPreferences }[] }
|
})) as any as { docs: { value: DocumentPreferences }[] }
|
||||||
|
|
||||||
const formState = await buildStateFromSchema({
|
const initialState = await buildStateFromSchema({
|
||||||
id,
|
id,
|
||||||
data: data || {},
|
data: data || {},
|
||||||
fieldSchema: formatFields(fields, isEditing),
|
fieldSchema: formatFields(fields, isEditing),
|
||||||
@@ -176,13 +180,11 @@ export const Document = async ({
|
|||||||
globalSlug,
|
globalSlug,
|
||||||
data,
|
data,
|
||||||
hasSavePermission,
|
hasSavePermission,
|
||||||
formState,
|
initialState,
|
||||||
isEditing,
|
isEditing,
|
||||||
docPermissions,
|
docPermissions,
|
||||||
docPreferences,
|
|
||||||
updatedAt: data?.updatedAt?.toString(),
|
updatedAt: data?.updatedAt?.toString(),
|
||||||
user,
|
user,
|
||||||
locale,
|
|
||||||
payload,
|
payload,
|
||||||
config,
|
config,
|
||||||
searchParams,
|
searchParams,
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ export const Login: React.FC<{
|
|||||||
config: Promise<SanitizedConfig>
|
config: Promise<SanitizedConfig>
|
||||||
searchParams: { [key: string]: string | string[] | undefined }
|
searchParams: { [key: string]: string | string[] | undefined }
|
||||||
}> = async ({ config: configPromise, searchParams }) => {
|
}> = async ({ config: configPromise, searchParams }) => {
|
||||||
const { config, user } = await initPage({ config: configPromise })
|
const { config, user } = await initPage({ config: configPromise, searchParams, route: '/login' })
|
||||||
|
|
||||||
const {
|
const {
|
||||||
admin: { components: { afterLogin, beforeLogin } = {}, user: userSlug },
|
admin: { components: { afterLogin, beforeLogin } = {}, user: userSlug },
|
||||||
|
|||||||
67
packages/next/src/routes/rest/buildFormState.ts
Normal file
67
packages/next/src/routes/rest/buildFormState.ts
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
import httpStatus from 'http-status'
|
||||||
|
|
||||||
|
import {
|
||||||
|
BuildFormStateArgs,
|
||||||
|
FieldSchemaMap,
|
||||||
|
buildFieldSchemaMap,
|
||||||
|
buildStateFromSchema,
|
||||||
|
reduceFieldsToValues,
|
||||||
|
} from '@payloadcms/ui'
|
||||||
|
import { Field, PayloadRequest, SanitizedConfig } from 'payload/types'
|
||||||
|
|
||||||
|
let cached = global._payload_fieldSchemaMap
|
||||||
|
|
||||||
|
if (!cached) {
|
||||||
|
// eslint-disable-next-line no-multi-assign
|
||||||
|
cached = global._payload_fieldSchemaMap = null
|
||||||
|
}
|
||||||
|
|
||||||
|
export const getFieldSchemaMap = (config: SanitizedConfig): FieldSchemaMap => {
|
||||||
|
if (cached) {
|
||||||
|
return cached
|
||||||
|
}
|
||||||
|
|
||||||
|
cached = buildFieldSchemaMap(config)
|
||||||
|
|
||||||
|
return cached
|
||||||
|
}
|
||||||
|
|
||||||
|
export const buildFormState = async ({ req }: { req: PayloadRequest }) => {
|
||||||
|
const { data: reqData, user, t, locale } = req
|
||||||
|
|
||||||
|
// TODO: run ADMIN access control for user
|
||||||
|
|
||||||
|
const fieldSchemaMap = getFieldSchemaMap(req.payload.config)
|
||||||
|
|
||||||
|
const { id, operation, docPreferences, formState, schemaPath } = reqData as BuildFormStateArgs
|
||||||
|
const schemaPathSegments = schemaPath.split('.')
|
||||||
|
|
||||||
|
let fieldSchema: Field[]
|
||||||
|
|
||||||
|
if (schemaPathSegments.length === 1) {
|
||||||
|
if (req.payload.collections[schemaPath]) {
|
||||||
|
fieldSchema = req.payload.collections[schemaPath].config.fields
|
||||||
|
} else if (req.payload.globals[schemaPath]) {
|
||||||
|
fieldSchema = req.payload.globals[schemaPath].config.fields
|
||||||
|
}
|
||||||
|
} else if (fieldSchemaMap.has(schemaPath)) {
|
||||||
|
fieldSchema = fieldSchemaMap.get(schemaPath)
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = reduceFieldsToValues(formState, true)
|
||||||
|
|
||||||
|
const result = await buildStateFromSchema({
|
||||||
|
id,
|
||||||
|
data,
|
||||||
|
fieldSchema,
|
||||||
|
locale,
|
||||||
|
operation,
|
||||||
|
preferences: docPreferences,
|
||||||
|
t,
|
||||||
|
user,
|
||||||
|
})
|
||||||
|
|
||||||
|
return Response.json(result, {
|
||||||
|
status: httpStatus.OK,
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -12,6 +12,7 @@ import {
|
|||||||
} from './types'
|
} from './types'
|
||||||
|
|
||||||
import { RouteError } from './RouteError'
|
import { RouteError } from './RouteError'
|
||||||
|
import { buildFormState } from './buildFormState'
|
||||||
import { endpointsAreDisabled } from './checkEndpoints'
|
import { endpointsAreDisabled } from './checkEndpoints'
|
||||||
|
|
||||||
import { me } from './auth/me'
|
import { me } from './auth/me'
|
||||||
@@ -50,6 +51,9 @@ const endpoints = {
|
|||||||
GET: {
|
GET: {
|
||||||
access,
|
access,
|
||||||
},
|
},
|
||||||
|
POST: {
|
||||||
|
'form-state': buildFormState,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
collection: {
|
collection: {
|
||||||
GET: {
|
GET: {
|
||||||
@@ -295,6 +299,7 @@ export const POST =
|
|||||||
config,
|
config,
|
||||||
params: { collection: slug1 },
|
params: { collection: slug1 },
|
||||||
})
|
})
|
||||||
|
|
||||||
collection = req.payload.collections?.[slug1]
|
collection = req.payload.collections?.[slug1]
|
||||||
|
|
||||||
const disableEndpoints = endpointsAreDisabled({
|
const disableEndpoints = endpointsAreDisabled({
|
||||||
@@ -315,6 +320,7 @@ export const POST =
|
|||||||
payloadRequest: req,
|
payloadRequest: req,
|
||||||
endpoints: collection.config.endpoints,
|
endpoints: collection.config.endpoints,
|
||||||
})
|
})
|
||||||
|
|
||||||
if (customEndpointResponse) return customEndpointResponse
|
if (customEndpointResponse) return customEndpointResponse
|
||||||
|
|
||||||
switch (slug.length) {
|
switch (slug.length) {
|
||||||
@@ -324,6 +330,7 @@ export const POST =
|
|||||||
break
|
break
|
||||||
case 2:
|
case 2:
|
||||||
if (slug2 in endpoints.collection.POST) {
|
if (slug2 in endpoints.collection.POST) {
|
||||||
|
// /:collection/form-state
|
||||||
// /:collection/login
|
// /:collection/login
|
||||||
// /:collection/logout
|
// /:collection/logout
|
||||||
// /:collection/unlock
|
// /:collection/unlock
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { headers as getHeaders } from 'next/headers'
|
import { headers as getHeaders } from 'next/headers'
|
||||||
|
import qs from 'qs'
|
||||||
|
|
||||||
import { auth } from './auth'
|
import { auth } from './auth'
|
||||||
|
|
||||||
@@ -22,12 +23,16 @@ export const initPage = async ({
|
|||||||
collectionSlug,
|
collectionSlug,
|
||||||
globalSlug,
|
globalSlug,
|
||||||
localeParam,
|
localeParam,
|
||||||
|
searchParams,
|
||||||
|
route,
|
||||||
}: {
|
}: {
|
||||||
config: SanitizedConfig | Promise<SanitizedConfig>
|
config: SanitizedConfig | Promise<SanitizedConfig>
|
||||||
redirectUnauthenticatedUser?: boolean
|
redirectUnauthenticatedUser?: boolean
|
||||||
collectionSlug?: string
|
collectionSlug?: string
|
||||||
globalSlug?: string
|
globalSlug?: string
|
||||||
localeParam?: string
|
localeParam?: string
|
||||||
|
searchParams?: { [key: string]: string | string[] | undefined }
|
||||||
|
route?: string
|
||||||
}): Promise<{
|
}): Promise<{
|
||||||
payload: Awaited<ReturnType<typeof getPayload>>
|
payload: Awaited<ReturnType<typeof getPayload>>
|
||||||
permissions: Awaited<ReturnType<typeof auth>>['permissions']
|
permissions: Awaited<ReturnType<typeof auth>>['permissions']
|
||||||
@@ -46,15 +51,18 @@ export const initPage = async ({
|
|||||||
config: configPromise,
|
config: configPromise,
|
||||||
cookies,
|
cookies,
|
||||||
})
|
})
|
||||||
|
|
||||||
const language = getRequestLanguage({ cookies, headers })
|
const language = getRequestLanguage({ cookies, headers })
|
||||||
|
|
||||||
const config = await configPromise
|
const config = await configPromise
|
||||||
|
|
||||||
const { localization, routes, collections, globals } = config
|
const { localization, routes, collections, globals } = config
|
||||||
|
|
||||||
if (redirectUnauthenticatedUser && !user) {
|
if (redirectUnauthenticatedUser && !user && route !== '/login') {
|
||||||
// `redirect(`${payload.config.routes.admin}/unauthorized`)` is not built yet
|
const stringifiedSearchParams = Object.keys(searchParams ?? {}).length
|
||||||
redirect(`${routes.admin}/login`)
|
? `?${qs.stringify(searchParams)}`
|
||||||
|
: ''
|
||||||
|
redirect(`${routes.admin}/login?redirect=${routes.admin + route + stringifiedSearchParams}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
const payload = await getPayload({
|
const payload = await getPayload({
|
||||||
|
|||||||
@@ -25,6 +25,9 @@ import IDLabel from '../IDLabel'
|
|||||||
import type { EditViewProps } from '../../views/types'
|
import type { EditViewProps } from '../../views/types'
|
||||||
import { DefaultEditView } from '../../views/Edit'
|
import { DefaultEditView } from '../../views/Edit'
|
||||||
import { Gutter } from '../Gutter'
|
import { Gutter } from '../Gutter'
|
||||||
|
import { LoadingOverlay } from '../Loading'
|
||||||
|
import { getFormState } from '../../views/Edit/getFormState'
|
||||||
|
import { useFieldPath } from '../../forms/FieldPathProvider'
|
||||||
|
|
||||||
const Content: React.FC<DocumentDrawerProps> = ({ collectionSlug, Header, drawerSlug, onSave }) => {
|
const Content: React.FC<DocumentDrawerProps> = ({ collectionSlug, Header, drawerSlug, onSave }) => {
|
||||||
const config = useConfig()
|
const config = useConfig()
|
||||||
@@ -37,7 +40,7 @@ const Content: React.FC<DocumentDrawerProps> = ({ collectionSlug, Header, drawer
|
|||||||
const { closeModal, modalState, toggleModal } = useModal()
|
const { closeModal, modalState, toggleModal } = useModal()
|
||||||
const locale = useLocale()
|
const locale = useLocale()
|
||||||
const { user } = useAuth()
|
const { user } = useAuth()
|
||||||
const [internalState, setInternalState] = useState<FormState>()
|
const [initialState, setInitialState] = useState<FormState>()
|
||||||
const { i18n, t } = useTranslation()
|
const { i18n, t } = useTranslation()
|
||||||
const hasInitializedState = useRef(false)
|
const hasInitializedState = useRef(false)
|
||||||
const [isOpen, setIsOpen] = useState(false)
|
const [isOpen, setIsOpen] = useState(false)
|
||||||
@@ -48,6 +51,7 @@ const Content: React.FC<DocumentDrawerProps> = ({ collectionSlug, Header, drawer
|
|||||||
const { admin: { components: { views: { Edit } = {} } = {} } = {}, fields: fieldsFromConfig } =
|
const { admin: { components: { views: { Edit } = {} } = {} } = {}, fields: fieldsFromConfig } =
|
||||||
collectionConfig
|
collectionConfig
|
||||||
|
|
||||||
|
const { schemaPath } = useFieldPath()
|
||||||
const { id, docPermissions } = useDocumentInfo()
|
const { id, docPermissions } = useDocumentInfo()
|
||||||
|
|
||||||
// The component definition could come from multiple places in the config
|
// The component definition could come from multiple places in the config
|
||||||
@@ -105,7 +109,33 @@ const Content: React.FC<DocumentDrawerProps> = ({ collectionSlug, Header, drawer
|
|||||||
(isEditing && docPermissions?.update?.permission) ||
|
(isEditing && docPermissions?.update?.permission) ||
|
||||||
(!isEditing && (docPermissions as CollectionPermission)?.create?.permission)
|
(!isEditing && (docPermissions as CollectionPermission)?.create?.permission)
|
||||||
|
|
||||||
const isLoading = !internalState || !docPermissions || isLoadingDocument
|
useEffect(() => {
|
||||||
|
if (!hasInitializedState.current && data) {
|
||||||
|
const getInitialState = async () => {
|
||||||
|
const result = await getFormState({
|
||||||
|
serverURL,
|
||||||
|
apiRoute: api,
|
||||||
|
body: {
|
||||||
|
id,
|
||||||
|
operation: isEditing ? 'update' : 'create',
|
||||||
|
formState: data,
|
||||||
|
docPreferences: null, // TODO: get this
|
||||||
|
schemaPath,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
setInitialState(result)
|
||||||
|
}
|
||||||
|
|
||||||
|
getInitialState()
|
||||||
|
}
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
const isLoading = !initialState || !docPermissions || isLoadingDocument
|
||||||
|
|
||||||
|
if (isLoading) {
|
||||||
|
return <LoadingOverlay />
|
||||||
|
}
|
||||||
|
|
||||||
const componentProps: EditViewProps = {
|
const componentProps: EditViewProps = {
|
||||||
id,
|
id,
|
||||||
@@ -144,11 +174,10 @@ const Content: React.FC<DocumentDrawerProps> = ({ collectionSlug, Header, drawer
|
|||||||
onSave,
|
onSave,
|
||||||
collectionSlug: collectionConfig.slug,
|
collectionSlug: collectionConfig.slug,
|
||||||
docPermissions: docPermissions as CollectionPermission,
|
docPermissions: docPermissions as CollectionPermission,
|
||||||
docPreferences: null,
|
docPreferences: null, // TODO: get this
|
||||||
user,
|
user,
|
||||||
updatedAt: data?.updatedAt,
|
updatedAt: data?.updatedAt,
|
||||||
locale,
|
initialState,
|
||||||
initializeFormState: true,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -28,3 +28,4 @@ export { default as buildInitialState } from '../forms/Form'
|
|||||||
export { default as FieldDescription } from '../forms/FieldDescription'
|
export { default as FieldDescription } from '../forms/FieldDescription'
|
||||||
export { default as useField } from '../forms/useField'
|
export { default as useField } from '../forms/useField'
|
||||||
export { default as Error } from '../forms/Error'
|
export { default as Error } from '../forms/Error'
|
||||||
|
export type { BuildFormStateArgs } from '../forms/utilities/buildStateFromSchema'
|
||||||
|
|||||||
@@ -5,3 +5,5 @@ export type { EntityToGroup, Group } from '../utilities/groupNavItems'
|
|||||||
export { EntityType, groupNavItems } from '../utilities/groupNavItems'
|
export { EntityType, groupNavItems } from '../utilities/groupNavItems'
|
||||||
export { withMergedProps } from '../utilities/withMergedProps'
|
export { withMergedProps } from '../utilities/withMergedProps'
|
||||||
export type { FieldMap, MappedField } from '../utilities/buildComponentMap/types'
|
export type { FieldMap, MappedField } from '../utilities/buildComponentMap/types'
|
||||||
|
export { buildFieldSchemaMap } from '../utilities/buildFieldSchemaMap'
|
||||||
|
export type { FieldSchemaMap } from '../utilities/buildFieldSchemaMap/types'
|
||||||
|
|||||||
@@ -16,7 +16,6 @@ export const FieldPathProvider: React.FC<{
|
|||||||
children: React.ReactNode
|
children: React.ReactNode
|
||||||
}> = (props) => {
|
}> = (props) => {
|
||||||
const { children, path, schemaPath } = props
|
const { children, path, schemaPath } = props
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<FieldPathContext.Provider
|
<FieldPathContext.Provider
|
||||||
value={{
|
value={{
|
||||||
|
|||||||
@@ -39,7 +39,6 @@ import getSiblingDataFunc from './getSiblingData'
|
|||||||
import initContextState from './initContextState'
|
import initContextState from './initContextState'
|
||||||
import reduceFieldsToValues from './reduceFieldsToValues'
|
import reduceFieldsToValues from './reduceFieldsToValues'
|
||||||
import useDebounce from '../../hooks/useDebounce'
|
import useDebounce from '../../hooks/useDebounce'
|
||||||
import { FieldPathProvider } from '../FieldPathProvider'
|
|
||||||
|
|
||||||
const baseClass = 'form'
|
const baseClass = 'form'
|
||||||
|
|
||||||
@@ -514,7 +513,7 @@ const Form: React.FC<Props> = (props) => {
|
|||||||
<ProcessingContext.Provider value={processing}>
|
<ProcessingContext.Provider value={processing}>
|
||||||
<ModifiedContext.Provider value={modified}>
|
<ModifiedContext.Provider value={modified}>
|
||||||
<FormFieldsContext.Provider value={fieldsReducer}>
|
<FormFieldsContext.Provider value={fieldsReducer}>
|
||||||
<FieldPathProvider path="">{children}</FieldPathProvider>
|
{children}
|
||||||
</FormFieldsContext.Provider>
|
</FormFieldsContext.Provider>
|
||||||
</ModifiedContext.Provider>
|
</ModifiedContext.Provider>
|
||||||
</ProcessingContext.Provider>
|
</ProcessingContext.Provider>
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ type BlockFieldProps = UseDraggableSortableReturn & {
|
|||||||
path: string
|
path: string
|
||||||
labels: Labels
|
labels: Labels
|
||||||
permissions: FieldPermissions
|
permissions: FieldPermissions
|
||||||
|
schemaPath: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export const BlockRow: React.FC<BlockFieldProps> = ({
|
export const BlockRow: React.FC<BlockFieldProps> = ({
|
||||||
@@ -54,6 +55,7 @@ export const BlockRow: React.FC<BlockFieldProps> = ({
|
|||||||
listeners,
|
listeners,
|
||||||
moveRow,
|
moveRow,
|
||||||
path: parentPath,
|
path: parentPath,
|
||||||
|
schemaPath,
|
||||||
permissions,
|
permissions,
|
||||||
readOnly,
|
readOnly,
|
||||||
removeRow,
|
removeRow,
|
||||||
@@ -132,7 +134,7 @@ export const BlockRow: React.FC<BlockFieldProps> = ({
|
|||||||
onToggle={(collapsed) => setCollapse(row.id, collapsed)}
|
onToggle={(collapsed) => setCollapse(row.id, collapsed)}
|
||||||
>
|
>
|
||||||
<HiddenInput name={`${path}.id`} value={row.id} />
|
<HiddenInput name={`${path}.id`} value={row.id} />
|
||||||
<FieldPathProvider path={path} schemaPath={`${parentPath}.${block.slug}`}>
|
<FieldPathProvider path={path} schemaPath={`${schemaPath}.${block.slug}`}>
|
||||||
<RenderFields
|
<RenderFields
|
||||||
className={`${baseClass}__fields`}
|
className={`${baseClass}__fields`}
|
||||||
fieldMap={block.subfields}
|
fieldMap={block.subfields}
|
||||||
|
|||||||
@@ -96,6 +96,7 @@ const BlocksField: React.FC<Props> = (props) => {
|
|||||||
valid,
|
valid,
|
||||||
value,
|
value,
|
||||||
path,
|
path,
|
||||||
|
schemaPath,
|
||||||
} = useField<number>({
|
} = useField<number>({
|
||||||
hasRows: true,
|
hasRows: true,
|
||||||
path: pathFromProps || name,
|
path: pathFromProps || name,
|
||||||
@@ -248,6 +249,7 @@ const BlocksField: React.FC<Props> = (props) => {
|
|||||||
labels={labels}
|
labels={labels}
|
||||||
moveRow={moveRow}
|
moveRow={moveRow}
|
||||||
path={path}
|
path={path}
|
||||||
|
schemaPath={schemaPath}
|
||||||
permissions={permissions}
|
permissions={permissions}
|
||||||
readOnly={readOnly}
|
readOnly={readOnly}
|
||||||
removeRow={removeRow}
|
removeRow={removeRow}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import type { TFunction } from '@payloadcms/translations'
|
import type { TFunction } from '@payloadcms/translations'
|
||||||
|
|
||||||
import type { User } from 'payload/auth'
|
import type { User } from 'payload/auth'
|
||||||
import type { Field as FieldSchema, Data } from 'payload/types'
|
import type { Field as FieldSchema, Data, DocumentPreferences } from 'payload/types'
|
||||||
import type { FormState } from '../../Form/types'
|
import type { FormState } from '../../Form/types'
|
||||||
|
|
||||||
import { iterateFields } from './iterateFields'
|
import { iterateFields } from './iterateFields'
|
||||||
@@ -21,6 +21,14 @@ type Args = {
|
|||||||
user?: User | null
|
user?: User | null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type BuildFormStateArgs = {
|
||||||
|
id?: string | number
|
||||||
|
operation?: 'create' | 'update'
|
||||||
|
docPreferences: DocumentPreferences
|
||||||
|
formState?: FormState
|
||||||
|
schemaPath: string
|
||||||
|
}
|
||||||
|
|
||||||
const buildStateFromSchema = async (args: Args): Promise<FormState> => {
|
const buildStateFromSchema = async (args: Args): Promise<FormState> => {
|
||||||
const { id, data: fullData = {}, fieldSchema, locale, operation, preferences, t, user } = args
|
const { id, data: fullData = {}, fieldSchema, locale, operation, preferences, t, user } = args
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import type { AuthContext } from './types'
|
|||||||
import { requests } from '../../utilities/api'
|
import { requests } from '../../utilities/api'
|
||||||
import useDebounce from '../../hooks/useDebounce'
|
import useDebounce from '../../hooks/useDebounce'
|
||||||
import { useConfig } from '../Config'
|
import { useConfig } from '../Config'
|
||||||
import { usePathname, useRouter } from 'next/navigation'
|
import { usePathname, useRouter, useSearchParams } from 'next/navigation'
|
||||||
// import { useLocale } from '../Locale'
|
// import { useLocale } from '../Locale'
|
||||||
|
|
||||||
const Context = createContext({} as AuthContext)
|
const Context = createContext({} as AuthContext)
|
||||||
@@ -19,6 +19,7 @@ const Context = createContext({} as AuthContext)
|
|||||||
const maxTimeoutTime = 2147483647
|
const maxTimeoutTime = 2147483647
|
||||||
|
|
||||||
export const AuthProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => {
|
export const AuthProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => {
|
||||||
|
const searchParams = useSearchParams()
|
||||||
const [user, setUser] = useState<User | null>()
|
const [user, setUser] = useState<User | null>()
|
||||||
const [tokenInMemory, setTokenInMemory] = useState<string>()
|
const [tokenInMemory, setTokenInMemory] = useState<string>()
|
||||||
const [tokenExpiration, setTokenExpiration] = useState<number>()
|
const [tokenExpiration, setTokenExpiration] = useState<number>()
|
||||||
@@ -209,6 +210,7 @@ export const AuthProvider: React.FC<{ children: React.ReactNode }> = ({ children
|
|||||||
if (autoLoginJson?.token) {
|
if (autoLoginJson?.token) {
|
||||||
setTokenAndExpiration(autoLoginJson)
|
setTokenAndExpiration(autoLoginJson)
|
||||||
}
|
}
|
||||||
|
push(searchParams.get('redirect') || admin)
|
||||||
} else {
|
} else {
|
||||||
setUser(null)
|
setUser(null)
|
||||||
revokeTokenAndExpire()
|
revokeTokenAndExpire()
|
||||||
|
|||||||
25
packages/ui/src/utilities/buildFieldSchemaMap/index.ts
Normal file
25
packages/ui/src/utilities/buildFieldSchemaMap/index.ts
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
import type { SanitizedConfig } from 'payload/types'
|
||||||
|
import { FieldSchemaMap } from './types'
|
||||||
|
import { traverseFields } from './traverseFields'
|
||||||
|
|
||||||
|
export const buildFieldSchemaMap = (config: SanitizedConfig): FieldSchemaMap => {
|
||||||
|
const result: FieldSchemaMap = new Map()
|
||||||
|
|
||||||
|
config.collections.forEach((collection) => {
|
||||||
|
traverseFields({
|
||||||
|
schemaPath: collection.slug,
|
||||||
|
fields: collection.fields,
|
||||||
|
schemaMap: result,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
config.globals.forEach((global) => {
|
||||||
|
traverseFields({
|
||||||
|
schemaPath: global.slug,
|
||||||
|
fields: global.fields,
|
||||||
|
schemaMap: result,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
import { Field, tabHasName } from 'payload/types'
|
||||||
|
import { FieldSchemaMap } from './types'
|
||||||
|
|
||||||
|
type Args = {
|
||||||
|
fields: Field[]
|
||||||
|
schemaMap: FieldSchemaMap
|
||||||
|
schemaPath: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export const traverseFields = ({ fields, schemaMap, schemaPath }: Args) => {
|
||||||
|
fields.map((field) => {
|
||||||
|
switch (field.type) {
|
||||||
|
case 'group':
|
||||||
|
case 'array':
|
||||||
|
traverseFields({
|
||||||
|
fields: field.fields,
|
||||||
|
schemaMap,
|
||||||
|
schemaPath: `${schemaPath}.${field.name}`,
|
||||||
|
})
|
||||||
|
break
|
||||||
|
|
||||||
|
case 'collapsible':
|
||||||
|
case 'row':
|
||||||
|
traverseFields({
|
||||||
|
fields: field.fields,
|
||||||
|
schemaMap,
|
||||||
|
schemaPath,
|
||||||
|
})
|
||||||
|
break
|
||||||
|
|
||||||
|
case 'blocks':
|
||||||
|
field.blocks.map((block) => {
|
||||||
|
traverseFields({
|
||||||
|
fields: block.fields,
|
||||||
|
schemaMap,
|
||||||
|
schemaPath: `${schemaPath}.${field.name}.${block.slug}`,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
break
|
||||||
|
|
||||||
|
case 'tabs':
|
||||||
|
field.tabs.map((tab) => {
|
||||||
|
const tabSchemaPath = tabHasName(tab) ? `${schemaPath}.${tab.name}` : schemaPath
|
||||||
|
traverseFields({
|
||||||
|
fields: tab.fields,
|
||||||
|
schemaMap,
|
||||||
|
schemaPath: tabSchemaPath,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
break
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
3
packages/ui/src/utilities/buildFieldSchemaMap/types.ts
Normal file
3
packages/ui/src/utilities/buildFieldSchemaMap/types.ts
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
import { Field } from 'payload/types'
|
||||||
|
|
||||||
|
export type FieldSchemaMap = Map<string, Field[]>
|
||||||
@@ -1,63 +0,0 @@
|
|||||||
'use server'
|
|
||||||
|
|
||||||
import { getPayload } from 'payload'
|
|
||||||
import { FormState } from '../../forms/Form/types'
|
|
||||||
import configPromise from 'payload-config'
|
|
||||||
import buildStateFromSchema from '../../forms/utilities/buildStateFromSchema'
|
|
||||||
import { reduceFieldsToValues } from '../..'
|
|
||||||
import { DocumentPreferences } from 'payload/types'
|
|
||||||
import { Locale } from 'payload/config'
|
|
||||||
import { User } from 'payload/auth'
|
|
||||||
import { initI18n } from '@payloadcms/translations'
|
|
||||||
import { translations } from '@payloadcms/translations/api'
|
|
||||||
|
|
||||||
export const getFormStateFromServer = async (
|
|
||||||
args: {
|
|
||||||
collectionSlug: string
|
|
||||||
docPreferences: DocumentPreferences
|
|
||||||
locale: Locale
|
|
||||||
id?: string
|
|
||||||
operation: 'create' | 'update'
|
|
||||||
user: User
|
|
||||||
language: string
|
|
||||||
},
|
|
||||||
{
|
|
||||||
formState,
|
|
||||||
}: {
|
|
||||||
formState: FormState
|
|
||||||
},
|
|
||||||
) => {
|
|
||||||
const { collectionSlug, docPreferences, locale, id, operation, user, language } = args
|
|
||||||
|
|
||||||
const payload = await getPayload({
|
|
||||||
config: configPromise,
|
|
||||||
})
|
|
||||||
|
|
||||||
const collectionConfig = payload.collections[collectionSlug]?.config
|
|
||||||
|
|
||||||
if (!collectionConfig) {
|
|
||||||
throw new Error(`Collection with slug "${collectionSlug}" not found`)
|
|
||||||
}
|
|
||||||
|
|
||||||
const data = reduceFieldsToValues(formState, true)
|
|
||||||
|
|
||||||
const { t } = await initI18n({
|
|
||||||
translations,
|
|
||||||
language: language,
|
|
||||||
config: payload.config.i18n,
|
|
||||||
context: 'api',
|
|
||||||
})
|
|
||||||
|
|
||||||
const result = await buildStateFromSchema({
|
|
||||||
id,
|
|
||||||
data,
|
|
||||||
fieldSchema: collectionConfig.fields,
|
|
||||||
locale: locale.code,
|
|
||||||
operation,
|
|
||||||
preferences: docPreferences,
|
|
||||||
t,
|
|
||||||
user,
|
|
||||||
})
|
|
||||||
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
26
packages/ui/src/views/Edit/getFormState.ts
Normal file
26
packages/ui/src/views/Edit/getFormState.ts
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
import { SanitizedConfig } from 'payload/types'
|
||||||
|
import { FormState } from '../../forms/Form/types'
|
||||||
|
import { BuildFormStateArgs } from '../..'
|
||||||
|
|
||||||
|
export const getFormState = async (args: {
|
||||||
|
serverURL: SanitizedConfig['serverURL']
|
||||||
|
apiRoute: SanitizedConfig['routes']['api']
|
||||||
|
body: BuildFormStateArgs
|
||||||
|
}): Promise<FormState> => {
|
||||||
|
const { serverURL, apiRoute, body } = args
|
||||||
|
|
||||||
|
const res = await fetch(`${serverURL}${apiRoute}/form-state`, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
body: JSON.stringify(body),
|
||||||
|
})
|
||||||
|
|
||||||
|
if (res.ok) {
|
||||||
|
const json = (await res.json()) as FormState
|
||||||
|
return json
|
||||||
|
}
|
||||||
|
|
||||||
|
return body?.formState
|
||||||
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
'use client'
|
'use client'
|
||||||
import React, { Fragment, useCallback, useState } from 'react'
|
import React, { Fragment, useCallback } from 'react'
|
||||||
|
|
||||||
import { FormLoadingOverlayToggle } from '../../elements/Loading'
|
import { FormLoadingOverlayToggle } from '../../elements/Loading'
|
||||||
import Form from '../../forms/Form'
|
import Form from '../../forms/Form'
|
||||||
@@ -9,18 +9,19 @@ import { OperationProvider } from '../../providers/OperationProvider'
|
|||||||
import { DocumentControls } from '../../elements/DocumentControls'
|
import { DocumentControls } from '../../elements/DocumentControls'
|
||||||
import { DocumentFields } from '../../elements/DocumentFields'
|
import { DocumentFields } from '../../elements/DocumentFields'
|
||||||
import { LeaveWithoutSaving } from '../../elements/LeaveWithoutSaving'
|
import { LeaveWithoutSaving } from '../../elements/LeaveWithoutSaving'
|
||||||
// import Meta from '../../../../utilities/Meta'
|
|
||||||
import Auth from './Auth'
|
import Auth from './Auth'
|
||||||
import { SetStepNav } from './SetStepNav'
|
import { SetStepNav } from './SetStepNav'
|
||||||
import { EditViewProps } from '../types'
|
import { EditViewProps } from '../types'
|
||||||
import { getFormStateFromServer } from './action'
|
|
||||||
import { Upload } from './Upload'
|
import { Upload } from './Upload'
|
||||||
import { useConfig } from '../../providers/Config'
|
import { useConfig } from '../../providers/Config'
|
||||||
import { useTranslation } from '../../providers/Translation'
|
|
||||||
import { useComponentMap } from '../../providers/ComponentMapProvider'
|
import { useComponentMap } from '../../providers/ComponentMapProvider'
|
||||||
import { SetDocumentTitle } from './SetDocumentTitle'
|
import { SetDocumentTitle } from './SetDocumentTitle'
|
||||||
|
import { Props as FormProps, FormState } from '../../forms/Form/types'
|
||||||
|
|
||||||
import './index.scss'
|
import './index.scss'
|
||||||
|
import { BuildFormStateArgs } from '../..'
|
||||||
|
import { getFormState } from './getFormState'
|
||||||
|
import { FieldPathProvider } from '../../forms/FieldPathProvider'
|
||||||
|
|
||||||
const baseClass = 'collection-edit'
|
const baseClass = 'collection-edit'
|
||||||
|
|
||||||
@@ -32,20 +33,22 @@ export const DefaultEditView: React.FC<EditViewProps> = (props) => {
|
|||||||
AfterDocument,
|
AfterDocument,
|
||||||
AfterFields,
|
AfterFields,
|
||||||
data,
|
data,
|
||||||
formState: initialStateFromProps,
|
initialState,
|
||||||
initializeFormState,
|
|
||||||
// isLoading,
|
// isLoading,
|
||||||
onSave: onSaveFromProps,
|
onSave: onSaveFromProps,
|
||||||
docPreferences,
|
|
||||||
docPermissions,
|
docPermissions,
|
||||||
|
docPreferences,
|
||||||
user,
|
user,
|
||||||
locale,
|
|
||||||
} = props
|
} = props
|
||||||
|
|
||||||
const config = useConfig()
|
const config = useConfig()
|
||||||
const { collections, globals } = config
|
const {
|
||||||
|
serverURL,
|
||||||
|
collections,
|
||||||
|
globals,
|
||||||
|
routes: { api: apiRoute },
|
||||||
|
} = config
|
||||||
|
|
||||||
const { i18n } = useTranslation()
|
|
||||||
const { getFieldMap } = useComponentMap()
|
const { getFieldMap } = useComponentMap()
|
||||||
|
|
||||||
const collectionConfig =
|
const collectionConfig =
|
||||||
@@ -55,6 +58,8 @@ export const DefaultEditView: React.FC<EditViewProps> = (props) => {
|
|||||||
const globalConfig =
|
const globalConfig =
|
||||||
'globalSlug' in props && globals.find((global) => global.slug === props.globalSlug)
|
'globalSlug' in props && globals.find((global) => global.slug === props.globalSlug)
|
||||||
|
|
||||||
|
const [schemaPath] = React.useState(collectionConfig?.slug || globalConfig?.slug)
|
||||||
|
|
||||||
const fieldMap = getFieldMap({
|
const fieldMap = getFieldMap({
|
||||||
collectionSlug: collectionConfig?.slug,
|
collectionSlug: collectionConfig?.slug,
|
||||||
globalSlug: globalConfig?.slug,
|
globalSlug: globalConfig?.slug,
|
||||||
@@ -64,22 +69,6 @@ export const DefaultEditView: React.FC<EditViewProps> = (props) => {
|
|||||||
const isEditing = 'isEditing' in props ? props.isEditing : undefined
|
const isEditing = 'isEditing' in props ? props.isEditing : undefined
|
||||||
const operation = isEditing ? 'update' : 'create'
|
const operation = isEditing ? 'update' : 'create'
|
||||||
|
|
||||||
const [initialState] = useState(() => {
|
|
||||||
if (initializeFormState) {
|
|
||||||
const initializedState = getFormStateFromServer.bind(null, {
|
|
||||||
collectionSlug: collectionConfig?.slug,
|
|
||||||
id: id || undefined,
|
|
||||||
locale,
|
|
||||||
language: i18n.language,
|
|
||||||
operation,
|
|
||||||
docPreferences,
|
|
||||||
user,
|
|
||||||
})({ formState: {} })
|
|
||||||
|
|
||||||
return initializedState
|
|
||||||
} else return initialStateFromProps
|
|
||||||
})
|
|
||||||
|
|
||||||
const auth = collectionConfig ? collectionConfig.auth : undefined
|
const auth = collectionConfig ? collectionConfig.auth : undefined
|
||||||
const upload = collectionConfig ? collectionConfig.upload : undefined
|
const upload = collectionConfig ? collectionConfig.upload : undefined
|
||||||
const hasSavePermission = 'hasSavePermission' in props ? props.hasSavePermission : undefined
|
const hasSavePermission = 'hasSavePermission' in props ? props.hasSavePermission : undefined
|
||||||
@@ -137,41 +126,56 @@ export const DefaultEditView: React.FC<EditViewProps> = (props) => {
|
|||||||
// setViewActions(defaultActions)
|
// setViewActions(defaultActions)
|
||||||
// }, [id, location.pathname, collectionConfig?.admin?.components?.views?.Edit, setViewActions])
|
// }, [id, location.pathname, collectionConfig?.admin?.components?.views?.Edit, setViewActions])
|
||||||
|
|
||||||
const rebuildFormState = getFormStateFromServer.bind(null, {
|
const onChange: FormProps['onChange'][0] = useCallback(
|
||||||
collectionSlug: collectionConfig?.slug,
|
async ({ formState: prevFormState }) =>
|
||||||
id: id || undefined,
|
getFormState({
|
||||||
locale,
|
serverURL,
|
||||||
language: i18n.language,
|
apiRoute,
|
||||||
operation,
|
body: {
|
||||||
docPreferences,
|
id,
|
||||||
user,
|
operation,
|
||||||
})
|
formState: prevFormState,
|
||||||
|
docPreferences,
|
||||||
|
schemaPath,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
[
|
||||||
|
serverURL,
|
||||||
|
apiRoute,
|
||||||
|
collectionConfig,
|
||||||
|
globalConfig,
|
||||||
|
id,
|
||||||
|
operation,
|
||||||
|
docPreferences,
|
||||||
|
schemaPath,
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<main className={classes}>
|
<main className={classes}>
|
||||||
<OperationProvider operation={operation}>
|
<FieldPathProvider path="" schemaPath={schemaPath}>
|
||||||
<Form
|
<OperationProvider operation={operation}>
|
||||||
action={action}
|
<Form
|
||||||
className={`${baseClass}__form`}
|
action={action}
|
||||||
disabled={!hasSavePermission}
|
className={`${baseClass}__form`}
|
||||||
initialState={initialState}
|
disabled={!hasSavePermission}
|
||||||
method={id ? 'PATCH' : 'POST'}
|
initialState={initialState}
|
||||||
beforeSubmit={[rebuildFormState]}
|
method={id ? 'PATCH' : 'POST'}
|
||||||
onChange={[rebuildFormState]}
|
onChange={[onChange]}
|
||||||
onSuccess={onSave}
|
onSuccess={onSave}
|
||||||
>
|
>
|
||||||
<FormLoadingOverlayToggle
|
<FormLoadingOverlayToggle
|
||||||
action={operation}
|
action={operation}
|
||||||
// formIsLoading={isLoading}
|
// formIsLoading={isLoading}
|
||||||
// loadingSuffix={getTranslation(collectionConfig.labels.singular, i18n)}
|
// loadingSuffix={getTranslation(collectionConfig.labels.singular, i18n)}
|
||||||
name={`collection-edit--${
|
name={`collection-edit--${
|
||||||
typeof collectionConfig?.labels?.singular === 'string'
|
typeof collectionConfig?.labels?.singular === 'string'
|
||||||
? collectionConfig.labels.singular
|
? collectionConfig.labels.singular
|
||||||
: 'document'
|
: 'document'
|
||||||
}`}
|
}`}
|
||||||
type="withoutNav"
|
type="withoutNav"
|
||||||
/>
|
/>
|
||||||
{/* <Meta
|
{/* <Meta
|
||||||
description={`${isEditing ? t('general:editing') : t('general:creating')} - ${getTranslation(
|
description={`${isEditing ? t('general:editing') : t('general:creating')} - ${getTranslation(
|
||||||
collection.labels.singular,
|
collection.labels.singular,
|
||||||
i18n,
|
i18n,
|
||||||
@@ -182,61 +186,62 @@ export const DefaultEditView: React.FC<EditViewProps> = (props) => {
|
|||||||
i18n,
|
i18n,
|
||||||
)}`}
|
)}`}
|
||||||
/> */}
|
/> */}
|
||||||
{BeforeDocument}
|
{BeforeDocument}
|
||||||
{preventLeaveWithoutSaving && <LeaveWithoutSaving />}
|
{preventLeaveWithoutSaving && <LeaveWithoutSaving />}
|
||||||
<SetStepNav
|
<SetStepNav
|
||||||
collectionSlug={collectionConfig?.slug}
|
collectionSlug={collectionConfig?.slug}
|
||||||
globalSlug={globalConfig?.slug}
|
globalSlug={globalConfig?.slug}
|
||||||
useAsTitle={collectionConfig?.admin?.useAsTitle}
|
useAsTitle={collectionConfig?.admin?.useAsTitle}
|
||||||
id={id}
|
id={id}
|
||||||
isEditing={isEditing || false}
|
isEditing={isEditing || false}
|
||||||
pluralLabel={collectionConfig?.labels?.plural}
|
pluralLabel={collectionConfig?.labels?.plural}
|
||||||
/>
|
/>
|
||||||
<SetDocumentTitle
|
<SetDocumentTitle
|
||||||
config={config}
|
config={config}
|
||||||
collectionConfig={collectionConfig}
|
collectionConfig={collectionConfig}
|
||||||
globalConfig={globalConfig}
|
globalConfig={globalConfig}
|
||||||
/>
|
/>
|
||||||
<DocumentControls
|
<DocumentControls
|
||||||
apiURL={apiURL}
|
apiURL={apiURL}
|
||||||
slug={collectionConfig?.slug}
|
slug={collectionConfig?.slug}
|
||||||
data={data}
|
data={data}
|
||||||
disableActions={disableActions}
|
disableActions={disableActions}
|
||||||
hasSavePermission={hasSavePermission}
|
hasSavePermission={hasSavePermission}
|
||||||
id={id}
|
id={id}
|
||||||
isEditing={isEditing}
|
isEditing={isEditing}
|
||||||
permissions={docPermissions}
|
permissions={docPermissions}
|
||||||
/>
|
/>
|
||||||
<DocumentFields
|
<DocumentFields
|
||||||
BeforeFields={
|
BeforeFields={
|
||||||
<Fragment>
|
<Fragment>
|
||||||
{auth && (
|
{auth && (
|
||||||
<Auth
|
<Auth
|
||||||
className={`${baseClass}__auth`}
|
className={`${baseClass}__auth`}
|
||||||
collectionSlug={collectionConfig.slug}
|
collectionSlug={collectionConfig.slug}
|
||||||
email={data?.email}
|
email={data?.email}
|
||||||
operation={operation}
|
operation={operation}
|
||||||
readOnly={!hasSavePermission}
|
readOnly={!hasSavePermission}
|
||||||
requirePassword={!isEditing}
|
requirePassword={!isEditing}
|
||||||
useAPIKey={auth.useAPIKey}
|
useAPIKey={auth.useAPIKey}
|
||||||
verify={auth.verify}
|
verify={auth.verify}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{upload && (
|
{upload && (
|
||||||
<Upload
|
<Upload
|
||||||
uploadConfig={upload}
|
uploadConfig={upload}
|
||||||
collectionSlug={collectionConfig.slug}
|
collectionSlug={collectionConfig.slug}
|
||||||
initialState={initialState}
|
initialState={initialState}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</Fragment>
|
</Fragment>
|
||||||
}
|
}
|
||||||
fieldMap={fieldMap}
|
fieldMap={fieldMap}
|
||||||
AfterFields={AfterFields}
|
AfterFields={AfterFields}
|
||||||
/>
|
/>
|
||||||
{AfterDocument}
|
{AfterDocument}
|
||||||
</Form>
|
</Form>
|
||||||
</OperationProvider>
|
</OperationProvider>
|
||||||
|
</FieldPathProvider>
|
||||||
</main>
|
</main>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import type { CollectionPermission, GlobalPermission, Permissions, User } from 'payload/auth'
|
import type { CollectionPermission, GlobalPermission, Permissions, User } from 'payload/auth'
|
||||||
import type { Document, DocumentPreferences, Payload, SanitizedConfig } from 'payload/types'
|
import type { Document, DocumentPreferences, Payload, SanitizedConfig } from 'payload/types'
|
||||||
import type { FormState } from '../forms/Form/types'
|
import type { FormState } from '../forms/Form/types'
|
||||||
import type { Locale } from 'payload/config'
|
|
||||||
import { I18n } from '@payloadcms/translations'
|
import { I18n } from '@payloadcms/translations'
|
||||||
|
|
||||||
export type EditViewProps = (
|
export type EditViewProps = (
|
||||||
@@ -22,15 +21,13 @@ export type EditViewProps = (
|
|||||||
action?: string
|
action?: string
|
||||||
apiURL: string
|
apiURL: string
|
||||||
canAccessAdmin?: boolean
|
canAccessAdmin?: boolean
|
||||||
data: Document
|
|
||||||
docPreferences: DocumentPreferences
|
docPreferences: DocumentPreferences
|
||||||
|
data: Document
|
||||||
// isLoading: boolean
|
// isLoading: boolean
|
||||||
onSave?: (json: any) => void
|
onSave?: (json: any) => void
|
||||||
updatedAt: string
|
updatedAt: string
|
||||||
user: User | null | undefined
|
user: User | null | undefined
|
||||||
locale: Locale
|
initialState?: FormState
|
||||||
formState?: FormState
|
|
||||||
initializeFormState?: boolean
|
|
||||||
BeforeDocument?: React.ReactNode
|
BeforeDocument?: React.ReactNode
|
||||||
AfterDocument?: React.ReactNode
|
AfterDocument?: React.ReactNode
|
||||||
AfterFields?: React.ReactNode
|
AfterFields?: React.ReactNode
|
||||||
|
|||||||
Reference in New Issue
Block a user