chore(next): wires form submissions (#4982)
This commit is contained in:
@@ -6,7 +6,7 @@ import { SanitizedConfig } from 'payload/types'
|
||||
import { createClientConfig } from '../../utilities/createClientConfig'
|
||||
import { getRequestLanguage } from '../../utilities/getRequestLanguage'
|
||||
import { deepMerge } from 'payload/utilities'
|
||||
import { buildFieldMaps } from '../../../../ui/src/forms/RenderFields/buildFieldMaps'
|
||||
import { buildFieldMaps } from '../../../../ui/src/forms/utilities/buildFieldMaps'
|
||||
|
||||
import '@payloadcms/ui/scss/app.scss'
|
||||
|
||||
|
||||
@@ -9,7 +9,6 @@ import { initPage } from '../../utilities/initPage'
|
||||
import {
|
||||
EditDepthProvider,
|
||||
RenderCustomComponent,
|
||||
fieldTypes,
|
||||
buildStateFromSchema,
|
||||
formatFields,
|
||||
FormQueryParamsProvider,
|
||||
@@ -20,11 +19,9 @@ import {
|
||||
import type { EditViewProps } from '@payloadcms/ui'
|
||||
import queryString from 'qs'
|
||||
import { notFound } from 'next/navigation'
|
||||
import { TFunction } from '@payloadcms/translations'
|
||||
import { AdminViewComponent } from 'payload/config'
|
||||
import { getViewsFromConfig } from './getViewsFromConfig'
|
||||
import type { DocumentPermissions } from 'payload/types'
|
||||
import { buildFieldMap } from '../../../../ui/src/forms/RenderFields/buildFieldMaps/buildFieldMap'
|
||||
|
||||
export const Document = async ({
|
||||
params,
|
||||
@@ -43,6 +40,7 @@ export const Document = async ({
|
||||
const globalSlug = params.global
|
||||
const isCreating = params.segments?.length === 1 && params.segments?.[0] === 'create'
|
||||
const id = (collectionSlug && !isCreating && params.segments[0]) || undefined
|
||||
|
||||
const isEditing = Boolean(globalSlug || (collectionSlug && !!id))
|
||||
|
||||
const { config, payload, permissions, user, collectionConfig, globalConfig, locale, i18n } =
|
||||
@@ -162,10 +160,6 @@ export const Document = async ({
|
||||
user,
|
||||
})
|
||||
|
||||
const fieldMap = buildFieldMap({
|
||||
fieldSchema: collectionConfig?.fields || globalConfig?.fields,
|
||||
})
|
||||
|
||||
const formQueryParams: QueryParamTypes = {
|
||||
depth: 0,
|
||||
'fallback-locale': 'null',
|
||||
@@ -189,7 +183,6 @@ export const Document = async ({
|
||||
updatedAt: data?.updatedAt?.toString(),
|
||||
user,
|
||||
locale,
|
||||
fieldMap,
|
||||
}
|
||||
|
||||
return (
|
||||
|
||||
@@ -6,7 +6,7 @@ import type { SanitizedCollectionConfig } from '../../../../collections/config/t
|
||||
import type { LivePreviewConfig } from '../../../../exports/config'
|
||||
import type { Field } from '../../../../fields/config/types'
|
||||
import type { SanitizedGlobalConfig } from '../../../../globals/config/types'
|
||||
import type { FieldTypes } from '../../forms/field-types'
|
||||
import type { FieldTypes } from '../../forms/fields'
|
||||
import type { EditViewProps } from '../types'
|
||||
|
||||
import { DocumentControls } from '../../elements/DocumentControls'
|
||||
|
||||
@@ -3,6 +3,7 @@ import {
|
||||
Email,
|
||||
Form,
|
||||
FormLoadingOverlayToggle,
|
||||
FormState,
|
||||
FormSubmit,
|
||||
Password,
|
||||
useConfig,
|
||||
@@ -25,27 +26,29 @@ export const LoginForm: React.FC<{
|
||||
routes: { admin, api },
|
||||
} = config
|
||||
|
||||
const { t } = useTranslation()
|
||||
|
||||
const prefillForm = autoLogin && autoLogin.prefillOnly
|
||||
|
||||
const { t } = useTranslation()
|
||||
const initialState: FormState = {
|
||||
email: {
|
||||
initialValue: prefillForm ? autoLogin.email : undefined,
|
||||
value: prefillForm ? autoLogin.email : undefined,
|
||||
valid: true,
|
||||
},
|
||||
password: {
|
||||
initialValue: prefillForm ? autoLogin.password : undefined,
|
||||
value: prefillForm ? autoLogin.password : undefined,
|
||||
valid: true,
|
||||
},
|
||||
}
|
||||
|
||||
return (
|
||||
<Form
|
||||
action={`${api}/${userSlug}/login`}
|
||||
className={`${baseClass}__form`}
|
||||
disableSuccessStatus
|
||||
initialState={{
|
||||
email: {
|
||||
initialValue: prefillForm ? autoLogin.email : undefined,
|
||||
value: prefillForm ? autoLogin.email : undefined,
|
||||
valid: true,
|
||||
},
|
||||
password: {
|
||||
initialValue: prefillForm ? autoLogin.password : undefined,
|
||||
value: prefillForm ? autoLogin.password : undefined,
|
||||
valid: true,
|
||||
},
|
||||
}}
|
||||
initialState={initialState}
|
||||
redirect={`${admin}${searchParams?.redirect || ''}`}
|
||||
waitForAutocomplete
|
||||
method="POST"
|
||||
|
||||
@@ -17,28 +17,39 @@ export const updateByID = async ({
|
||||
const autosave = searchParams.get('autosave') === 'true'
|
||||
const draft = searchParams.get('draft') === 'true'
|
||||
|
||||
const doc = await updateByIDOperation({
|
||||
id,
|
||||
autosave,
|
||||
collection: req.collection,
|
||||
data: req.data,
|
||||
depth: isNumber(depth) ? Number(depth) : undefined,
|
||||
draft,
|
||||
req,
|
||||
})
|
||||
try {
|
||||
const doc = await updateByIDOperation({
|
||||
id,
|
||||
autosave,
|
||||
collection: req.collection,
|
||||
data: req.data,
|
||||
depth: isNumber(depth) ? Number(depth) : undefined,
|
||||
draft,
|
||||
req,
|
||||
})
|
||||
|
||||
let message = req.t('general:updatedSuccessfully')
|
||||
let message = req.t('general:updatedSuccessfully')
|
||||
|
||||
if (draft) message = req.t('version:draftSavedSuccessfully')
|
||||
if (autosave) message = req.t('version:autosavedSuccessfully')
|
||||
if (draft) message = req.t('version:draftSavedSuccessfully')
|
||||
if (autosave) message = req.t('version:autosavedSuccessfully')
|
||||
|
||||
return Response.json(
|
||||
{
|
||||
message,
|
||||
doc,
|
||||
},
|
||||
{
|
||||
status: httpStatus.OK,
|
||||
},
|
||||
)
|
||||
return Response.json(
|
||||
{
|
||||
message,
|
||||
doc,
|
||||
},
|
||||
{
|
||||
status: httpStatus.OK,
|
||||
},
|
||||
)
|
||||
} catch (error) {
|
||||
return Response.json(
|
||||
{
|
||||
message: error.message,
|
||||
},
|
||||
{
|
||||
status: error.status || httpStatus.INTERNAL_SERVER_ERROR,
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ export const getDataAndFile: GetDataAndFile = async ({ request, collection, conf
|
||||
let data: Record<string, any> = undefined
|
||||
let file: CustomPayloadRequest['file'] = undefined
|
||||
|
||||
if (['POST', 'PUT'].includes(request.method.toUpperCase()) && request.body) {
|
||||
if (['PATCH', 'POST', 'PUT'].includes(request.method.toUpperCase()) && request.body) {
|
||||
const [contentType] = request.headers.get('Content-Type').split(';')
|
||||
|
||||
if (contentType === 'application/json') {
|
||||
|
||||
@@ -11,7 +11,7 @@ import type { DocumentDrawerProps } from './types'
|
||||
import { baseClass } from '.'
|
||||
import { getTranslation } from '@payloadcms/translations'
|
||||
import usePayloadAPI from '../../hooks/usePayloadAPI'
|
||||
import { useRelatedCollections } from '../../forms/field-types/Relationship/AddNew/useRelatedCollections'
|
||||
import { useRelatedCollections } from '../../forms/fields/Relationship/AddNew/useRelatedCollections'
|
||||
import { X } from '../../icons/X'
|
||||
import { useAuth } from '../../providers/Auth'
|
||||
import { useConfig } from '../../providers/Config'
|
||||
@@ -23,7 +23,6 @@ import { RenderCustomComponent } from '../../elements/RenderCustomComponent'
|
||||
import { formatFields } from '../../utilities/formatFields'
|
||||
import IDLabel from '../IDLabel'
|
||||
import type { EditViewProps } from '../../views/types'
|
||||
import { useFieldMaps } from '../../providers/FieldMapsProvider'
|
||||
import { DefaultEditView } from '../../views/Edit'
|
||||
import { Gutter } from '../Gutter'
|
||||
|
||||
@@ -35,9 +34,6 @@ const Content: React.FC<DocumentDrawerProps> = ({ collectionSlug, Header, drawer
|
||||
serverURL,
|
||||
} = config
|
||||
|
||||
const fieldMaps = useFieldMaps()
|
||||
const fieldMap = fieldMaps[collectionSlug]
|
||||
|
||||
const { closeModal, modalState, toggleModal } = useModal()
|
||||
const locale = useLocale()
|
||||
const { user } = useAuth()
|
||||
@@ -150,10 +146,9 @@ const Content: React.FC<DocumentDrawerProps> = ({ collectionSlug, Header, drawer
|
||||
docPermissions: docPermissions as CollectionPermission,
|
||||
docPreferences: null,
|
||||
user,
|
||||
fieldMap,
|
||||
updatedAt: data?.updatedAt,
|
||||
locale,
|
||||
formState: {},
|
||||
initializeFormState: true,
|
||||
}
|
||||
|
||||
return (
|
||||
|
||||
@@ -6,7 +6,7 @@ import { useTranslation } from '../../providers/Translation'
|
||||
import type { DocumentDrawerProps, DocumentTogglerProps, UseDocumentDrawer } from './types'
|
||||
|
||||
import { getTranslation } from '@payloadcms/translations'
|
||||
import { useRelatedCollections } from '../../forms/field-types/Relationship/AddNew/useRelatedCollections'
|
||||
import { useRelatedCollections } from '../../forms/fields/Relationship/AddNew/useRelatedCollections'
|
||||
import { useEditDepth } from '../../providers/EditDepth'
|
||||
import { Drawer, DrawerToggler } from '../Drawer'
|
||||
import { DocumentDrawerContent } from './DrawerContent'
|
||||
|
||||
@@ -8,7 +8,7 @@ import type { Locale } from 'payload/config'
|
||||
import RenderFields from '../../forms/RenderFields'
|
||||
import { Gutter } from '../Gutter'
|
||||
import { Document } from 'payload/types'
|
||||
import { FieldMap } from '../../forms/RenderFields/buildFieldMaps/types'
|
||||
import { FieldMap } from '../../forms/utilities/buildFieldMaps/types'
|
||||
|
||||
import './index.scss'
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ import Form from '../../forms/Form'
|
||||
import { useForm } from '../../forms/Form/context'
|
||||
import RenderFields from '../../forms/RenderFields'
|
||||
import FormSubmit from '../../forms/Submit'
|
||||
import { fieldTypes } from '../../forms/field-types'
|
||||
import { fieldTypes } from '../../forms/fields'
|
||||
import { X } from '../../icons/X'
|
||||
import { useAuth } from '../../providers/Auth'
|
||||
import { useConfig } from '../../providers/Config'
|
||||
|
||||
@@ -2,12 +2,12 @@ import equal from 'deep-equal'
|
||||
import { useEffect } from 'react'
|
||||
|
||||
import type { FilterOptions } from 'payload/types'
|
||||
import type { FilterOptionsResult } from '../../forms/field-types/Relationship/types'
|
||||
import type { FilterOptionsResult } from '../../forms/fields/Relationship/types'
|
||||
|
||||
import { useAllFormFields } from '../../forms/Form/context'
|
||||
import getSiblingData from '../../forms/Form/getSiblingData'
|
||||
import reduceFieldsToValues from '../../forms/Form/reduceFieldsToValues'
|
||||
import { getFilterOptionsQuery } from '../../forms/field-types/getFilterOptionsQuery'
|
||||
import { getFilterOptionsQuery } from '../../forms/fields/getFilterOptionsQuery'
|
||||
import { useAuth } from '../../providers/Auth'
|
||||
import { useDocumentInfo } from '../../providers/DocumentInfo'
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ import type React from 'react'
|
||||
import type { HTMLAttributes } from 'react'
|
||||
|
||||
import type { SanitizedCollectionConfig } from 'payload/types'
|
||||
import type { FilterOptionsResult } from '../../forms/field-types/Relationship/types'
|
||||
import type { FilterOptionsResult } from '../../forms/fields/Relationship/types'
|
||||
|
||||
export type ListDrawerProps = {
|
||||
collectionSlugs: string[]
|
||||
|
||||
@@ -25,7 +25,7 @@ export { FormLoadingOverlayToggle } from '../elements/Loading'
|
||||
export { default as CopyToClipboard } from '../elements/CopyToClipboard'
|
||||
export { Collapsible } from '../elements/Collapsible'
|
||||
export { ErrorPill } from '../elements/ErrorPill'
|
||||
export { BlocksDrawer } from '../forms/field-types/Blocks/BlocksDrawer'
|
||||
export { BlocksDrawer } from '../forms/fields/Blocks/BlocksDrawer'
|
||||
export { formatDrawerSlug, Drawer, DrawerToggler } from '../elements/Drawer'
|
||||
export { useListDrawer } from '../elements/ListDrawer'
|
||||
export { useDocumentDrawer } from '../elements/DocumentDrawer'
|
||||
|
||||
@@ -1,27 +1,28 @@
|
||||
export { fieldTypes } from '../forms/field-types'
|
||||
export { default as buildStateFromSchema } from '../forms/Form/buildStateFromSchema'
|
||||
export { fieldTypes } from '../forms/fields'
|
||||
export { default as buildStateFromSchema } from '../forms/utilities/buildStateFromSchema'
|
||||
export { buildFieldMaps } from '../forms/utilities/buildFieldMaps'
|
||||
export { default as Form } from '../forms/Form'
|
||||
export { default as FormSubmit } from '../forms/Submit'
|
||||
export { default as ConfirmPassword } from '../forms/field-types/ConfirmPassword'
|
||||
export { default as HiddenInput } from '../forms/field-types/HiddenInput'
|
||||
export { default as Password } from '../forms/field-types/Password'
|
||||
export { default as ConfirmPassword } from '../forms/fields/ConfirmPassword'
|
||||
export { default as HiddenInput } from '../forms/fields/HiddenInput'
|
||||
export { default as Password } from '../forms/fields/Password'
|
||||
export { default as RenderFields } from '../forms/RenderFields'
|
||||
export { default as Email } from '../forms/field-types/Email'
|
||||
export { fieldBaseClass } from '../forms/field-types/shared'
|
||||
export { default as Email } from '../forms/fields/Email'
|
||||
export { fieldBaseClass } from '../forms/fields/shared'
|
||||
export type { FormState } from '../forms/Form/types'
|
||||
export type { OnChange } from '../forms/field-types/RadioGroup/types'
|
||||
export { default as RadioGroupInput } from '../forms/field-types/RadioGroup'
|
||||
export type { OnChange } from '../forms/fields/RadioGroup/types'
|
||||
export { default as RadioGroupInput } from '../forms/fields/RadioGroup'
|
||||
export { default as Label } from '../forms/Label'
|
||||
export { default as Submit } from '../forms/Submit'
|
||||
export { default as Checkbox } from '../forms/field-types/Checkbox'
|
||||
export { default as CheckboxInput } from '../forms/field-types/Checkbox'
|
||||
export { default as Select } from '../forms/field-types/Select'
|
||||
export { default as SelectInput } from '../forms/field-types/Select'
|
||||
export { default as Number } from '../forms/field-types/Number'
|
||||
export { default as Checkbox } from '../forms/fields/Checkbox'
|
||||
export { default as CheckboxInput } from '../forms/fields/Checkbox'
|
||||
export { default as Select } from '../forms/fields/Select'
|
||||
export { default as SelectInput } from '../forms/fields/Select'
|
||||
export { default as Number } from '../forms/fields/Number'
|
||||
export { useAllFormFields } from '../forms/Form/context'
|
||||
export { default as reduceFieldsToValues } from '../forms/Form/reduceFieldsToValues'
|
||||
export { useFormSubmitted } from '../forms/Form/context'
|
||||
export { default as SectionTitle } from '../forms/field-types/Blocks/SectionTitle'
|
||||
export { default as SectionTitle } from '../forms/fields/Blocks/SectionTitle'
|
||||
export { createNestedFieldPath } from '../forms/Form/createNestedFieldPath'
|
||||
export { default as buildInitialState } from '../forms/Form'
|
||||
export { default as FieldDescription } from '../forms/FieldDescription'
|
||||
|
||||
@@ -65,10 +65,12 @@ export function fieldReducer(state: FormState, action: FieldAction): FormState {
|
||||
state[action.path] || ({} as FormField),
|
||||
)
|
||||
|
||||
return {
|
||||
const newState = {
|
||||
...state,
|
||||
[action.path]: newField,
|
||||
}
|
||||
|
||||
return newState
|
||||
}
|
||||
|
||||
case 'REMOVE_ROW': {
|
||||
|
||||
@@ -24,7 +24,6 @@ import { useConfig } from '../../providers/Config'
|
||||
import { useDocumentInfo } from '../../providers/DocumentInfo'
|
||||
import { useLocale } from '../../providers/Locale'
|
||||
import { useOperation } from '../../providers/OperationProvider'
|
||||
import buildStateFromSchema from './buildStateFromSchema'
|
||||
import {
|
||||
FormContext,
|
||||
FormFieldsContext,
|
||||
@@ -40,6 +39,7 @@ import getSiblingDataFunc from './getSiblingData'
|
||||
import initContextState from './initContextState'
|
||||
import reduceFieldsToValues from './reduceFieldsToValues'
|
||||
import useDebounce from '../../hooks/useDebounce'
|
||||
import { FieldPathProvider } from '../FieldPathProvider'
|
||||
|
||||
const baseClass = 'form'
|
||||
|
||||
@@ -62,6 +62,7 @@ const Form: React.FC<Props> = (props) => {
|
||||
submitted: submittedFromProps,
|
||||
waitForAutocomplete,
|
||||
onChange,
|
||||
beforeSubmit,
|
||||
} = props
|
||||
|
||||
const method = 'method' in props ? props.method : undefined
|
||||
@@ -95,7 +96,9 @@ const Form: React.FC<Props> = (props) => {
|
||||
const validateForm = useCallback(async () => {
|
||||
const validatedFieldState = {}
|
||||
let isValid = true
|
||||
const data = contextRef.current.getData()
|
||||
|
||||
const dataFromContext = contextRef.current.getData()
|
||||
let data = dataFromContext
|
||||
|
||||
const validationPromises = Object.entries(contextRef.current.fields).map(
|
||||
async ([path, field]) => {
|
||||
@@ -143,7 +146,7 @@ const Form: React.FC<Props> = (props) => {
|
||||
}
|
||||
|
||||
return isValid
|
||||
}, [contextRef, id, user, operation, t, dispatchFields, config])
|
||||
}, [id, user, operation, t, dispatchFields, config, beforeSubmit])
|
||||
|
||||
const submit = useCallback(
|
||||
async (options: SubmitOptions = {}, e): Promise<void> => {
|
||||
@@ -167,12 +170,33 @@ const Form: React.FC<Props> = (props) => {
|
||||
}
|
||||
|
||||
setProcessing(true)
|
||||
setSubmitted(true)
|
||||
|
||||
if (waitForAutocomplete) await wait(100)
|
||||
|
||||
const isValid = skipValidation ? true : await contextRef.current.validateForm()
|
||||
// Execute server side validations
|
||||
if (Array.isArray(beforeSubmit)) {
|
||||
let revalidatedFormState: FormState
|
||||
|
||||
if (!skipValidation) setSubmitted(true)
|
||||
await beforeSubmit.reduce(async (priorOnChange, beforeSubmitFn) => {
|
||||
await priorOnChange
|
||||
|
||||
const result = await beforeSubmitFn({
|
||||
formState: debouncedFormState,
|
||||
})
|
||||
|
||||
revalidatedFormState = result
|
||||
}, Promise.resolve())
|
||||
|
||||
const isValid = Object.entries(revalidatedFormState).every(([, field]) => field.valid)
|
||||
|
||||
if (!isValid) {
|
||||
setProcessing(false)
|
||||
return dispatchFields({ state: revalidatedFormState, type: 'REPLACE_STATE' })
|
||||
}
|
||||
}
|
||||
|
||||
const isValid = skipValidation ? true : await contextRef.current.validateForm()
|
||||
|
||||
// If not valid, prevent submission
|
||||
if (!isValid) {
|
||||
@@ -331,67 +355,65 @@ const Form: React.FC<Props> = (props) => {
|
||||
],
|
||||
)
|
||||
|
||||
const getFields = useCallback(() => contextRef.current.fields, [contextRef])
|
||||
const getField = useCallback((path: string) => contextRef.current.fields[path], [contextRef])
|
||||
const getData = useCallback(
|
||||
() => reduceFieldsToValues(contextRef.current.fields, true),
|
||||
[contextRef],
|
||||
)
|
||||
const getFields = useCallback(() => contextRef.current.fields, [])
|
||||
|
||||
const getField = useCallback((path: string) => contextRef.current.fields[path], [])
|
||||
|
||||
const getData = useCallback(() => reduceFieldsToValues(contextRef.current.fields, true), [])
|
||||
|
||||
const getSiblingData = useCallback(
|
||||
(path: string) => getSiblingDataFunc(contextRef.current.fields, path),
|
||||
[contextRef],
|
||||
[],
|
||||
)
|
||||
const getDataByPath = useCallback<GetDataByPath>(
|
||||
(path: string) => getDataByPathFunc(contextRef.current.fields, path),
|
||||
[contextRef],
|
||||
[],
|
||||
)
|
||||
|
||||
const createFormData = useCallback(
|
||||
(overrides: any = {}) => {
|
||||
const data = reduceFieldsToValues(contextRef.current.fields, true)
|
||||
const createFormData = useCallback((overrides: any = {}) => {
|
||||
const data = reduceFieldsToValues(contextRef.current.fields, true)
|
||||
|
||||
const file = data?.file
|
||||
const file = data?.file
|
||||
|
||||
if (file) {
|
||||
delete data.file
|
||||
}
|
||||
if (file) {
|
||||
delete data.file
|
||||
}
|
||||
|
||||
const dataWithOverrides = {
|
||||
...data,
|
||||
...overrides,
|
||||
}
|
||||
const dataWithOverrides = {
|
||||
...data,
|
||||
...overrides,
|
||||
}
|
||||
|
||||
const dataToSerialize = {
|
||||
_payload: JSON.stringify(dataWithOverrides),
|
||||
file,
|
||||
}
|
||||
const dataToSerialize = {
|
||||
_payload: JSON.stringify(dataWithOverrides),
|
||||
file,
|
||||
}
|
||||
|
||||
// nullAsUndefineds is important to allow uploads and relationship fields to clear themselves
|
||||
const formData = serialize(dataToSerialize, { indices: true, nullsAsUndefineds: false })
|
||||
return formData
|
||||
},
|
||||
[contextRef],
|
||||
)
|
||||
// nullAsUndefineds is important to allow uploads and relationship fields to clear themselves
|
||||
const formData = serialize(dataToSerialize, { indices: true, nullsAsUndefineds: false })
|
||||
|
||||
return formData
|
||||
}, [])
|
||||
|
||||
const reset = useCallback(
|
||||
async (fieldSchema: Field[], data: unknown) => {
|
||||
const preferences = await getDocPreferences()
|
||||
const state = await buildStateFromSchema({
|
||||
id,
|
||||
// TODO: fix this
|
||||
// @ts-ignore-next-line
|
||||
config,
|
||||
data,
|
||||
fieldSchema,
|
||||
locale,
|
||||
operation,
|
||||
preferences,
|
||||
t,
|
||||
user,
|
||||
})
|
||||
// const state = await buildStateFromSchema({
|
||||
// id,
|
||||
// // TODO: fix this
|
||||
// // @ts-ignore-next-line
|
||||
// config,
|
||||
// data,
|
||||
// fieldSchema,
|
||||
// locale,
|
||||
// operation,
|
||||
// preferences,
|
||||
// t,
|
||||
// user,
|
||||
// })
|
||||
contextRef.current = { ...initContextState } as FormContextType
|
||||
setModified(false)
|
||||
dispatchFields({ state, type: 'REPLACE_STATE' })
|
||||
// dispatchFields({ state, type: 'REPLACE_STATE' })
|
||||
},
|
||||
[id, user, operation, locale, t, dispatchFields, getDocPreferences, config],
|
||||
)
|
||||
@@ -492,7 +514,7 @@ const Form: React.FC<Props> = (props) => {
|
||||
<ProcessingContext.Provider value={processing}>
|
||||
<ModifiedContext.Provider value={modified}>
|
||||
<FormFieldsContext.Provider value={fieldsReducer}>
|
||||
{children}
|
||||
<FieldPathProvider path="">{children}</FieldPathProvider>
|
||||
</FormFieldsContext.Provider>
|
||||
</ModifiedContext.Provider>
|
||||
</ProcessingContext.Provider>
|
||||
|
||||
@@ -27,7 +27,6 @@ const setSubmitted: SetSubmitted = () => undefined
|
||||
const reset: Reset = () => undefined
|
||||
|
||||
const initialContextState: Context = {
|
||||
addFieldRow: () => undefined,
|
||||
buildRowErrors: () => undefined,
|
||||
createFormData,
|
||||
disabled: false,
|
||||
@@ -39,8 +38,6 @@ const initialContextState: Context = {
|
||||
getField: (): FormField => undefined,
|
||||
getFields: (): FormState => ({}),
|
||||
getSiblingData,
|
||||
removeFieldRow: () => undefined,
|
||||
replaceFieldRow: () => undefined,
|
||||
replaceState: () => undefined,
|
||||
reset,
|
||||
setModified,
|
||||
|
||||
@@ -4,16 +4,16 @@ import type { FormState } from './types'
|
||||
import { Data } from 'payload/types'
|
||||
|
||||
const reduceFieldsToValues = (fields: FormState, unflatten?: boolean): Data => {
|
||||
const data = {}
|
||||
let data = {}
|
||||
|
||||
Object.keys(fields).forEach((key) => {
|
||||
if (!fields[key].disableFormData) {
|
||||
data[key] = fields[key].value
|
||||
if (!fields[key]?.disableFormData) {
|
||||
data[key] = fields[key]?.value
|
||||
}
|
||||
})
|
||||
|
||||
if (unflatten) {
|
||||
return flatleyUnflatten(data, { safe: true })
|
||||
data = flatleyUnflatten(data, { safe: true })
|
||||
}
|
||||
|
||||
return data
|
||||
|
||||
@@ -60,7 +60,8 @@ export type Props = (
|
||||
submitted?: boolean
|
||||
validationOperation?: 'create' | 'update'
|
||||
waitForAutocomplete?: boolean
|
||||
onChange?: ((args: { formState: FormState }) => Promise<FormState | void>)[]
|
||||
onChange?: ((args: { formState: FormState }) => Promise<FormState>)[]
|
||||
beforeSubmit?: ((args: { formState: FormState }) => Promise<FormState>)[]
|
||||
}
|
||||
|
||||
export type SubmitOptions = {
|
||||
|
||||
@@ -6,7 +6,7 @@ import { Banner } from '../../elements/Banner'
|
||||
import { useConfig } from '../../providers/Config'
|
||||
import { useLocale } from '../../providers/Locale'
|
||||
import { useForm } from '../Form/context'
|
||||
import CheckboxInput from '../field-types/Checkbox'
|
||||
import CheckboxInput from '../fields/Checkbox'
|
||||
|
||||
type NullifyLocaleFieldProps = {
|
||||
fieldValue?: [] | null | number
|
||||
|
||||
@@ -30,11 +30,9 @@ const RenderFields: React.FC<Props> = (props) => {
|
||||
.filter(Boolean)
|
||||
.join(' ')}
|
||||
>
|
||||
<FieldPathProvider path="">
|
||||
{fieldMap?.map(({ Field, name }, fieldIndex) => (
|
||||
<RenderField key={fieldIndex} name={name} Field={Field} />
|
||||
))}
|
||||
</FieldPathProvider>
|
||||
{fieldMap?.map(({ Field, name }, fieldIndex) => (
|
||||
<RenderField key={fieldIndex} name={name} Field={Field} />
|
||||
))}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import type { FieldPermissions, User } from 'payload/auth'
|
||||
import type { Document, DocumentPreferences, Field } from 'payload/types'
|
||||
import { Locale } from 'payload/config'
|
||||
import { FieldMap, FieldMaps } from './buildFieldMaps/types'
|
||||
import { FieldMap, FieldMaps } from '../utilities/buildFieldMaps/types'
|
||||
|
||||
export type Props = {
|
||||
className?: string
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { FieldMap } from '../RenderFields/buildFieldMaps/types'
|
||||
import { FieldMap } from '../utilities/buildFieldMaps/types'
|
||||
|
||||
export const buildPathSegments = (parentPath: string, fieldMap: FieldMap): string[] => {
|
||||
const pathNames = fieldMap.reduce((acc, subField) => {
|
||||
|
||||
@@ -5,7 +5,7 @@ import useThrottledEffect from '../../hooks/useThrottledEffect'
|
||||
import { useAllFormFields, useFormSubmitted } from '../Form/context'
|
||||
import { getFieldStateFromPaths } from './getFieldStateFromPaths'
|
||||
import { buildPathSegments } from './buildPathSegments'
|
||||
import { FieldMap } from '../RenderFields/buildFieldMaps/types'
|
||||
import { FieldMap } from '../utilities/buildFieldMaps/types'
|
||||
|
||||
type TrackSubSchemaErrorCountProps = {
|
||||
path: string
|
||||
|
||||
@@ -14,7 +14,7 @@ import HiddenInput from '../HiddenInput'
|
||||
import { FieldPathProvider } from '../../FieldPathProvider'
|
||||
import { FieldPermissions } from 'payload/auth'
|
||||
import { getTranslation } from '@payloadcms/translations'
|
||||
import { FieldMap } from '../../RenderFields/buildFieldMaps/types'
|
||||
import { FieldMap } from '../../utilities/buildFieldMaps/types'
|
||||
|
||||
import './index.scss'
|
||||
|
||||
@@ -17,7 +17,7 @@ import SectionTitle from './SectionTitle'
|
||||
import { FieldPathProvider } from '../../FieldPathProvider'
|
||||
import { Labels } from 'payload/types'
|
||||
import { FieldPermissions } from 'payload/auth'
|
||||
import { ReducedBlock } from '../../RenderFields/buildFieldMaps/types'
|
||||
import { ReducedBlock } from '../../utilities/buildFieldMaps/types'
|
||||
|
||||
const baseClass = 'blocks-field'
|
||||
|
||||
@@ -11,7 +11,7 @@ import { Drawer } from '../../../../elements/Drawer'
|
||||
import { ThumbnailCard } from '../../../../elements/ThumbnailCard'
|
||||
import DefaultBlockImage from '../../../../graphics/DefaultBlockImage'
|
||||
import BlockSearch from './BlockSearch'
|
||||
import { ReducedBlock } from '../../../RenderFields/buildFieldMaps/types'
|
||||
import { ReducedBlock } from '../../../utilities/buildFieldMaps/types'
|
||||
|
||||
import './index.scss'
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { Labels } from 'payload/types'
|
||||
import { ReducedBlock } from '../../../RenderFields/buildFieldMaps/types'
|
||||
import { ReducedBlock } from '../../../utilities/buildFieldMaps/types'
|
||||
|
||||
export type Props = {
|
||||
addRow: (index: number, blockType?: string) => void
|
||||
@@ -7,7 +7,7 @@ import type { Labels } from 'payload/types'
|
||||
import { ArrayAction } from '../../../elements/ArrayAction'
|
||||
import { useDrawerSlug } from '../../../elements/Drawer/useDrawerSlug'
|
||||
import { BlocksDrawer } from './BlocksDrawer'
|
||||
import { FieldMap, ReducedBlock } from '../../RenderFields/buildFieldMaps/types'
|
||||
import { FieldMap, ReducedBlock } from '../../utilities/buildFieldMaps/types'
|
||||
|
||||
export const RowActions: React.FC<{
|
||||
addRow: (rowIndex: number, blockType: string) => void
|
||||
@@ -9,7 +9,7 @@ import { useCollapsible } from '../../../elements/Collapsible/provider'
|
||||
import { useRow } from '../Row/provider'
|
||||
import { useTabs } from '../Tabs/provider'
|
||||
import { fieldBaseClass } from '../shared'
|
||||
import { useFieldPath } from '../../FieldPathProvider'
|
||||
import { FieldPathProvider, useFieldPath } from '../../FieldPathProvider'
|
||||
import { WatchChildErrors } from '../../WatchChildErrors'
|
||||
import { ErrorPill } from '../../../elements/ErrorPill'
|
||||
import { useTranslation } from '../../../providers/Translation'
|
||||
@@ -57,20 +57,22 @@ const Group: React.FC<Props> = (props) => {
|
||||
width,
|
||||
}}
|
||||
>
|
||||
<GroupProvider>
|
||||
<div className={`${baseClass}__wrap`}>
|
||||
<div className={`${baseClass}__header`}>
|
||||
{(Label || Description) && (
|
||||
<header>
|
||||
{Label}
|
||||
{Description}
|
||||
</header>
|
||||
)}
|
||||
{fieldHasErrors && <ErrorPill count={errorCount} withMessage i18n={i18n} />}
|
||||
<FieldPathProvider path={path}>
|
||||
<GroupProvider>
|
||||
<div className={`${baseClass}__wrap`}>
|
||||
<div className={`${baseClass}__header`}>
|
||||
{(Label || Description) && (
|
||||
<header>
|
||||
{Label}
|
||||
{Description}
|
||||
</header>
|
||||
)}
|
||||
{fieldHasErrors && <ErrorPill count={errorCount} withMessage i18n={i18n} />}
|
||||
</div>
|
||||
<RenderFields fieldMap={fieldMap} />
|
||||
</div>
|
||||
<RenderFields fieldMap={fieldMap} />
|
||||
</div>
|
||||
</GroupProvider>
|
||||
</GroupProvider>
|
||||
</FieldPathProvider>
|
||||
</div>
|
||||
</Fragment>
|
||||
)
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user