feat(richtext-lexical): new FieldsDrawer utility, improve blocks feature performance (#6967)
This commit is contained in:
@@ -123,3 +123,5 @@ export {
|
||||
$isBlockNode,
|
||||
BlockNode,
|
||||
} from '../../features/blocks/nodes/BlocksNode.js'
|
||||
|
||||
export { FieldsDrawer } from '../../utilities/fieldsDrawer/Drawer.js'
|
||||
|
||||
@@ -72,7 +72,7 @@ export const BlockComponent: React.FC<Props> = (props) => {
|
||||
apiRoute: config.routes.api,
|
||||
body: {
|
||||
id,
|
||||
data: JSON.parse(JSON.stringify(formData)),
|
||||
data: formData,
|
||||
operation: 'update',
|
||||
schemaPath: schemaFieldsPath,
|
||||
},
|
||||
|
||||
@@ -1,50 +0,0 @@
|
||||
@import '../../../scss/styles.scss';
|
||||
|
||||
.lexical-link-edit-drawer {
|
||||
&__template {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
padding-top: var(--base);
|
||||
padding-bottom: calc(var(--base) * 2);
|
||||
}
|
||||
|
||||
&__header {
|
||||
width: 100%;
|
||||
margin-bottom: var(--base);
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin-top: calc(var(--base) * 2.5);
|
||||
margin-bottom: var(--base);
|
||||
|
||||
@include mid-break {
|
||||
margin-top: calc(var(--base) * 1.5);
|
||||
}
|
||||
}
|
||||
|
||||
&__header-text {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
&__header-close {
|
||||
border: 0;
|
||||
background-color: transparent;
|
||||
padding: 0;
|
||||
cursor: pointer;
|
||||
overflow: hidden;
|
||||
width: var(--base);
|
||||
height: var(--base);
|
||||
|
||||
svg {
|
||||
width: calc(var(--base) * 2.75);
|
||||
height: calc(var(--base) * 2.75);
|
||||
position: relative;
|
||||
left: calc(var(--base) * -0.825);
|
||||
top: calc(var(--base) * -0.825);
|
||||
|
||||
.stroke {
|
||||
stroke-width: 2px;
|
||||
vector-effect: non-scaling-stroke;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
import type { FormState } from 'payload'
|
||||
|
||||
import type { LinkFields } from '../nodes/types.js'
|
||||
|
||||
export interface Props {
|
||||
drawerSlug: string
|
||||
handleModalSubmit: (fields: FormState, data: Record<string, unknown>) => void
|
||||
stateData: {} | (LinkFields & { text: string })
|
||||
}
|
||||
@@ -24,7 +24,7 @@ import type { LinkPayload } from '../types.js'
|
||||
import { useEditorConfigContext } from '../../../../../lexical/config/client/EditorConfigProvider.js'
|
||||
import { getSelectedNode } from '../../../../../lexical/utils/getSelectedNode.js'
|
||||
import { setFloatingElemPositionForLinkEditor } from '../../../../../lexical/utils/setFloatingElemPositionForLinkEditor.js'
|
||||
import { LinkDrawer } from '../../../drawer/index.js'
|
||||
import { FieldsDrawer } from '../../../../../utilities/fieldsDrawer/Drawer.js'
|
||||
import { $isAutoLinkNode } from '../../../nodes/AutoLinkNode.js'
|
||||
import { $createLinkNode, $isLinkNode, TOGGLE_LINK_COMMAND } from '../../../nodes/LinkNode.js'
|
||||
import { TOGGLE_LINK_WITH_MODAL_COMMAND } from './commands.js'
|
||||
@@ -44,7 +44,7 @@ export function LinkEditor({ anchorElem }: { anchorElem: HTMLElement }): React.R
|
||||
|
||||
const [stateData, setStateData] = useState<{} | (LinkFields & { id?: string; text: string })>({})
|
||||
|
||||
const { closeModal, isModalOpen, toggleModal } = useModal()
|
||||
const { closeModal, toggleModal } = useModal()
|
||||
const editDepth = useEditDepth()
|
||||
const [isLink, setIsLink] = useState(false)
|
||||
const [selectedNodes, setSelectedNodes] = useState<LexicalNode[]>([])
|
||||
@@ -312,50 +312,52 @@ export function LinkEditor({ anchorElem }: { anchorElem: HTMLElement }): React.R
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
{isModalOpen(drawerSlug) && (
|
||||
<LinkDrawer
|
||||
drawerSlug={drawerSlug}
|
||||
handleModalSubmit={(fields: FormState, data: Data) => {
|
||||
closeModal(drawerSlug)
|
||||
<FieldsDrawer
|
||||
className="lexical-link-edit-drawer"
|
||||
data={stateData}
|
||||
drawerSlug={drawerSlug}
|
||||
drawerTitle={t('fields:editLink')}
|
||||
featureKey="link"
|
||||
handleDrawerSubmit={(fields: FormState, data: Data) => {
|
||||
closeModal(drawerSlug)
|
||||
|
||||
const newLinkPayload = data as LinkFields & { text: string }
|
||||
const newLinkPayload = data as LinkFields & { text: string }
|
||||
|
||||
const bareLinkFields: LinkFields = {
|
||||
...newLinkPayload,
|
||||
const bareLinkFields: LinkFields = {
|
||||
...newLinkPayload,
|
||||
}
|
||||
delete bareLinkFields.text
|
||||
|
||||
// See: https://github.com/facebook/lexical/pull/5536. This updates autolink nodes to link nodes whenever a change was made (which is good!).
|
||||
editor.update(() => {
|
||||
const selection = $getSelection()
|
||||
let linkParent = null
|
||||
if ($isRangeSelection(selection)) {
|
||||
linkParent = getSelectedNode(selection).getParent()
|
||||
} else {
|
||||
if (selectedNodes.length) {
|
||||
linkParent = selectedNodes[0].getParent()
|
||||
}
|
||||
}
|
||||
delete bareLinkFields.text
|
||||
|
||||
// See: https://github.com/facebook/lexical/pull/5536. This updates autolink nodes to link nodes whenever a change was made (which is good!).
|
||||
editor.update(() => {
|
||||
const selection = $getSelection()
|
||||
let linkParent = null
|
||||
if ($isRangeSelection(selection)) {
|
||||
linkParent = getSelectedNode(selection).getParent()
|
||||
} else {
|
||||
if (selectedNodes.length) {
|
||||
linkParent = selectedNodes[0].getParent()
|
||||
}
|
||||
}
|
||||
if (linkParent && $isAutoLinkNode(linkParent)) {
|
||||
const linkNode = $createLinkNode({
|
||||
fields: bareLinkFields,
|
||||
})
|
||||
linkParent.replace(linkNode, true)
|
||||
}
|
||||
})
|
||||
|
||||
if (linkParent && $isAutoLinkNode(linkParent)) {
|
||||
const linkNode = $createLinkNode({
|
||||
fields: bareLinkFields,
|
||||
})
|
||||
linkParent.replace(linkNode, true)
|
||||
}
|
||||
})
|
||||
|
||||
// Needs to happen AFTER a potential auto link => link node conversion, as otherwise, the updated text to display may be lost due to
|
||||
// it being applied to the auto link node instead of the link node.
|
||||
editor.dispatchCommand(TOGGLE_LINK_COMMAND, {
|
||||
fields: bareLinkFields,
|
||||
selectedNodes,
|
||||
text: newLinkPayload.text,
|
||||
})
|
||||
}}
|
||||
stateData={stateData}
|
||||
/>
|
||||
)}
|
||||
// Needs to happen AFTER a potential auto link => link node conversion, as otherwise, the updated text to display may be lost due to
|
||||
// it being applied to the auto link node instead of the link node.
|
||||
editor.dispatchCommand(TOGGLE_LINK_COMMAND, {
|
||||
fields: bareLinkFields,
|
||||
selectedNodes,
|
||||
text: newLinkPayload.text,
|
||||
})
|
||||
}}
|
||||
schemaPathSuffix="fields"
|
||||
/>
|
||||
</React.Fragment>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,149 +0,0 @@
|
||||
'use client'
|
||||
import type { FormProps } from '@payloadcms/ui'
|
||||
import type { ClientCollectionConfig, FormState } from 'payload'
|
||||
|
||||
import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext.js'
|
||||
import { getTranslation } from '@payloadcms/translations'
|
||||
import {
|
||||
Drawer,
|
||||
Form,
|
||||
FormSubmit,
|
||||
RenderFields,
|
||||
useConfig,
|
||||
useDocumentInfo,
|
||||
useFieldProps,
|
||||
useModal,
|
||||
useTranslation,
|
||||
} from '@payloadcms/ui'
|
||||
import { getFormState } from '@payloadcms/ui/shared'
|
||||
import { $getNodeByKey } from 'lexical'
|
||||
import { deepCopyObject } from 'payload/shared'
|
||||
import React, { useCallback, useEffect, useState } from 'react'
|
||||
import { v4 as uuid } from 'uuid'
|
||||
|
||||
import type { UploadData, UploadNode } from '../../nodes/UploadNode.js'
|
||||
import type { ElementProps } from '../index.js'
|
||||
|
||||
import { useEditorConfigContext } from '../../../../lexical/config/client/EditorConfigProvider.js'
|
||||
|
||||
/**
|
||||
* This handles the extra fields, e.g. captions or alt text, which are
|
||||
* potentially added to the upload feature.
|
||||
*/
|
||||
export const ExtraFieldsUploadDrawer: React.FC<
|
||||
ElementProps & {
|
||||
drawerSlug: string
|
||||
relatedCollection: ClientCollectionConfig
|
||||
}
|
||||
> = (props) => {
|
||||
const {
|
||||
data: { fields, relationTo, value },
|
||||
drawerSlug,
|
||||
nodeKey,
|
||||
relatedCollection,
|
||||
} = props
|
||||
|
||||
const [editor] = useLexicalComposerContext()
|
||||
|
||||
const { closeModal } = useModal()
|
||||
|
||||
const { i18n, t } = useTranslation()
|
||||
const { id } = useDocumentInfo()
|
||||
const { schemaPath } = useFieldProps()
|
||||
const config = useConfig()
|
||||
const [initialState, setInitialState] = useState<FormState | false>(false)
|
||||
const {
|
||||
field: { richTextComponentMap },
|
||||
} = useEditorConfigContext()
|
||||
|
||||
const componentMapRenderedFieldsPath = `feature.upload.fields.${relatedCollection.slug}`
|
||||
const schemaFieldsPath = `${schemaPath}.feature.upload.${relatedCollection.slug}`
|
||||
|
||||
const fieldMap = richTextComponentMap.get(componentMapRenderedFieldsPath) // Field Schema
|
||||
|
||||
useEffect(() => {
|
||||
const awaitInitialState = async () => {
|
||||
const state = await getFormState({
|
||||
apiRoute: config.routes.api,
|
||||
body: {
|
||||
id,
|
||||
data: deepCopyObject(fields || {}),
|
||||
operation: 'update',
|
||||
schemaPath: schemaFieldsPath,
|
||||
},
|
||||
serverURL: config.serverURL,
|
||||
}) // Form State
|
||||
|
||||
setInitialState(state)
|
||||
}
|
||||
|
||||
void awaitInitialState()
|
||||
}, [config.routes.api, config.serverURL, schemaFieldsPath, id, fields])
|
||||
|
||||
const onChange: FormProps['onChange'][0] = useCallback(
|
||||
async ({ formState: prevFormState }) => {
|
||||
return await getFormState({
|
||||
apiRoute: config.routes.api,
|
||||
body: {
|
||||
id,
|
||||
formState: prevFormState,
|
||||
operation: 'update',
|
||||
schemaPath: schemaFieldsPath,
|
||||
},
|
||||
serverURL: config.serverURL,
|
||||
})
|
||||
},
|
||||
|
||||
[config.routes.api, config.serverURL, schemaFieldsPath, id],
|
||||
)
|
||||
|
||||
const handleUpdateEditData = useCallback(
|
||||
(_, data) => {
|
||||
// Update lexical node (with key nodeKey) with new data
|
||||
editor.update(() => {
|
||||
const uploadNode: UploadNode | null = $getNodeByKey(nodeKey)
|
||||
if (uploadNode) {
|
||||
const newData: UploadData = {
|
||||
...uploadNode.getData(),
|
||||
fields: data,
|
||||
}
|
||||
uploadNode.setData(newData)
|
||||
}
|
||||
})
|
||||
|
||||
closeModal(drawerSlug)
|
||||
},
|
||||
[closeModal, editor, drawerSlug, nodeKey],
|
||||
)
|
||||
|
||||
return (
|
||||
<Drawer
|
||||
slug={drawerSlug}
|
||||
title={t('general:editLabel', {
|
||||
label: getTranslation(relatedCollection.labels.singular, i18n),
|
||||
})}
|
||||
>
|
||||
{initialState !== false && (
|
||||
<Form
|
||||
beforeSubmit={[onChange]}
|
||||
disableValidationOnSubmit
|
||||
// @ts-expect-error TODO: Fix this
|
||||
fields={fieldMap}
|
||||
initialState={initialState}
|
||||
onChange={[onChange]}
|
||||
onSubmit={handleUpdateEditData}
|
||||
uuid={uuid()}
|
||||
>
|
||||
<RenderFields
|
||||
fieldMap={Array.isArray(fieldMap) ? fieldMap : []}
|
||||
forceRender
|
||||
path="" // See Blocks feature path for details as for why this is empty
|
||||
readOnly={false}
|
||||
schemaPath={schemaFieldsPath}
|
||||
/>
|
||||
<FormSubmit>{t('fields:saveChanges')}</FormSubmit>
|
||||
</Form>
|
||||
)}
|
||||
</Drawer>
|
||||
)
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
'use client'
|
||||
import type { ClientCollectionConfig } from 'payload'
|
||||
import type { ClientCollectionConfig, Data } from 'payload'
|
||||
|
||||
import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext.js'
|
||||
import { useLexicalNodeSelection } from '@lexical/react/useLexicalNodeSelection.js'
|
||||
@@ -12,6 +12,7 @@ import {
|
||||
useConfig,
|
||||
useDocumentDrawer,
|
||||
useDrawerSlug,
|
||||
useModal,
|
||||
usePayloadAPI,
|
||||
useTranslation,
|
||||
} from '@payloadcms/ui'
|
||||
@@ -28,13 +29,13 @@ import React, { useCallback, useEffect, useReducer, useRef, useState } from 'rea
|
||||
|
||||
import type { ClientComponentProps } from '../../typesClient.js'
|
||||
import type { UploadFeaturePropsClient } from '../feature.client.js'
|
||||
import type { UploadData } from '../nodes/UploadNode.js'
|
||||
import type { UploadData, UploadNode } from '../nodes/UploadNode.js'
|
||||
|
||||
import { useEditorConfigContext } from '../../../lexical/config/client/EditorConfigProvider.js'
|
||||
import { FieldsDrawer } from '../../../utilities/fieldsDrawer/Drawer.js'
|
||||
import { EnabledRelationshipsCondition } from '../../relationship/utils/EnabledRelationshipsCondition.js'
|
||||
import { INSERT_UPLOAD_WITH_DRAWER_COMMAND } from '../drawer/commands.js'
|
||||
import { $isUploadNode } from '../nodes/UploadNode.js'
|
||||
import { ExtraFieldsUploadDrawer } from './ExtraFieldsDrawer/index.js'
|
||||
import './index.scss'
|
||||
|
||||
const baseClass = 'lexical-upload'
|
||||
@@ -60,6 +61,7 @@ const Component: React.FC<ElementProps> = (props) => {
|
||||
serverURL,
|
||||
} = useConfig()
|
||||
const uploadRef = useRef<HTMLDivElement | null>(null)
|
||||
const { closeModal } = useModal()
|
||||
|
||||
const [editor] = useLexicalComposerContext()
|
||||
const [isSelected, setSelected, clearSelection] = useLexicalNodeSelection(nodeKey)
|
||||
@@ -68,7 +70,7 @@ const Component: React.FC<ElementProps> = (props) => {
|
||||
|
||||
const { i18n, t } = useTranslation()
|
||||
const [cacheBust, dispatchCacheBust] = useReducer((state) => state + 1, 0)
|
||||
const [relatedCollection, setRelatedCollection] = useState<ClientCollectionConfig>(() =>
|
||||
const [relatedCollection] = useState<ClientCollectionConfig>(() =>
|
||||
collections.find((coll) => coll.slug === relationTo),
|
||||
)
|
||||
|
||||
@@ -94,7 +96,7 @@ const Component: React.FC<ElementProps> = (props) => {
|
||||
}, [editor, nodeKey])
|
||||
|
||||
const updateUpload = useCallback(
|
||||
(json) => {
|
||||
(data: Data) => {
|
||||
setParams({
|
||||
...initialParams,
|
||||
cacheBust, // do this to get the usePayloadAPI to re-fetch the data even though the URL string hasn't changed
|
||||
@@ -107,9 +109,8 @@ const Component: React.FC<ElementProps> = (props) => {
|
||||
)
|
||||
|
||||
const $onDelete = useCallback(
|
||||
(payload: KeyboardEvent) => {
|
||||
(event: KeyboardEvent) => {
|
||||
if (isSelected && $isNodeSelection($getSelection())) {
|
||||
const event: KeyboardEvent = payload
|
||||
event.preventDefault()
|
||||
const node = $getNodeByKey(nodeKey)
|
||||
if ($isUploadNode(node)) {
|
||||
@@ -122,8 +123,7 @@ const Component: React.FC<ElementProps> = (props) => {
|
||||
[isSelected, nodeKey],
|
||||
)
|
||||
const onClick = useCallback(
|
||||
(payload: MouseEvent) => {
|
||||
const event = payload
|
||||
(event: MouseEvent) => {
|
||||
// Check if uploadRef.target or anything WITHIN uploadRef.target was clicked
|
||||
if (event.target === uploadRef.current || uploadRef.current?.contains(event.target as Node)) {
|
||||
if (event.shiftKey) {
|
||||
@@ -156,6 +156,25 @@ const Component: React.FC<ElementProps> = (props) => {
|
||||
?.sanitizedClientFeatureProps as ClientComponentProps<UploadFeaturePropsClient>
|
||||
).collections?.[relatedCollection.slug]?.hasExtraFields
|
||||
|
||||
const onExtraFieldsDrawerSubmit = useCallback(
|
||||
(_, data) => {
|
||||
// Update lexical node (with key nodeKey) with new data
|
||||
editor.update(() => {
|
||||
const uploadNode: UploadNode | null = $getNodeByKey(nodeKey)
|
||||
if (uploadNode) {
|
||||
const newData: UploadData = {
|
||||
...uploadNode.getData(),
|
||||
fields: data,
|
||||
}
|
||||
uploadNode.setData(newData)
|
||||
}
|
||||
})
|
||||
|
||||
closeModal(drawerSlug)
|
||||
},
|
||||
[closeModal, editor, drawerSlug, nodeKey],
|
||||
)
|
||||
|
||||
return (
|
||||
<div
|
||||
className={[baseClass, isSelected && `${baseClass}--selected`].filter(Boolean).join(' ')}
|
||||
@@ -239,10 +258,15 @@ const Component: React.FC<ElementProps> = (props) => {
|
||||
</div>
|
||||
{value && <DocumentDrawer onSave={updateUpload} />}
|
||||
{hasExtraFields ? (
|
||||
<ExtraFieldsUploadDrawer
|
||||
<FieldsDrawer
|
||||
data={fields}
|
||||
drawerSlug={drawerSlug}
|
||||
relatedCollection={relatedCollection}
|
||||
{...props}
|
||||
drawerTitle={t('general:editLabel', {
|
||||
label: getTranslation(relatedCollection.labels.singular, i18n),
|
||||
})}
|
||||
featureKey="upload"
|
||||
handleDrawerSubmit={onExtraFieldsDrawerSubmit}
|
||||
schemaPathSuffix={relatedCollection.slug}
|
||||
/>
|
||||
) : null}
|
||||
</div>
|
||||
|
||||
@@ -981,3 +981,5 @@ export { migrateSlateToLexical } from './utilities/migrateSlateToLexical/index.j
|
||||
export { upgradeLexicalData } from './utilities/upgradeLexicalData/index.js'
|
||||
|
||||
export * from './nodeTypes.js'
|
||||
|
||||
export type { FieldsDrawerProps } from './utilities/fieldsDrawer/Drawer.js'
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
'use client'
|
||||
import type { FormState } from 'payload'
|
||||
|
||||
import { Drawer } from '@payloadcms/ui'
|
||||
import React from 'react'
|
||||
|
||||
import { DrawerContent } from './DrawerContent.js'
|
||||
|
||||
export type FieldsDrawerProps = {
|
||||
className?: string
|
||||
data: any
|
||||
drawerSlug: string
|
||||
drawerTitle?: string
|
||||
featureKey: string
|
||||
handleDrawerSubmit: (fields: FormState, data: Record<string, unknown>) => void
|
||||
schemaPathSuffix?: string
|
||||
}
|
||||
|
||||
/**
|
||||
* This FieldsDrawer component can be used to easily create a Drawer that contains a form with fields within your feature.
|
||||
* The fields are taken directly from the schema map based on your `featureKey` and `schemaPathSuffix`. Thus, this can only
|
||||
* be used if you provide your field schema inside the `generateSchemaMap` prop of your feature.server.ts.
|
||||
*/
|
||||
export const FieldsDrawer: React.FC<FieldsDrawerProps> = ({
|
||||
className,
|
||||
data,
|
||||
drawerSlug,
|
||||
drawerTitle,
|
||||
featureKey,
|
||||
handleDrawerSubmit,
|
||||
schemaPathSuffix,
|
||||
}) => {
|
||||
// The Drawer only renders its children (and itself) if it's open. Thus, by extracting the main content
|
||||
// to DrawerContent, this should be faster
|
||||
return (
|
||||
<Drawer className={className} slug={drawerSlug} title={drawerTitle ?? ''}>
|
||||
<DrawerContent
|
||||
data={data}
|
||||
featureKey={featureKey}
|
||||
handleDrawerSubmit={handleDrawerSubmit}
|
||||
schemaPathSuffix={schemaPathSuffix}
|
||||
/>
|
||||
</Drawer>
|
||||
)
|
||||
}
|
||||
@@ -1,8 +1,8 @@
|
||||
'use client'
|
||||
import type { FormProps } from '@payloadcms/ui'
|
||||
import type { FormState } from 'payload'
|
||||
|
||||
import {
|
||||
Drawer,
|
||||
Form,
|
||||
FormSubmit,
|
||||
RenderFields,
|
||||
@@ -15,13 +15,16 @@ import { getFormState } from '@payloadcms/ui/shared'
|
||||
import React, { useCallback, useEffect, useState } from 'react'
|
||||
import { v4 as uuid } from 'uuid'
|
||||
|
||||
import { useEditorConfigContext } from '../../../lexical/config/client/EditorConfigProvider.js'
|
||||
import './index.scss'
|
||||
import { type Props } from './types.js'
|
||||
import type { FieldsDrawerProps } from './Drawer.js'
|
||||
|
||||
const baseClass = 'lexical-link-edit-drawer'
|
||||
import { useEditorConfigContext } from '../../lexical/config/client/EditorConfigProvider.js'
|
||||
|
||||
export const LinkDrawer: React.FC<Props> = ({ drawerSlug, handleModalSubmit, stateData }) => {
|
||||
export const DrawerContent: React.FC<Omit<FieldsDrawerProps, 'drawerSlug' | 'drawerTitle'>> = ({
|
||||
data,
|
||||
featureKey,
|
||||
handleDrawerSubmit,
|
||||
schemaPathSuffix,
|
||||
}) => {
|
||||
const { t } = useTranslation()
|
||||
const { id } = useDocumentInfo()
|
||||
const { schemaPath } = useFieldProps()
|
||||
@@ -31,8 +34,8 @@ export const LinkDrawer: React.FC<Props> = ({ drawerSlug, handleModalSubmit, sta
|
||||
field: { richTextComponentMap },
|
||||
} = useEditorConfigContext()
|
||||
|
||||
const componentMapRenderedFieldsPath = `feature.link.fields.fields`
|
||||
const schemaFieldsPath = `${schemaPath}.feature.link.fields`
|
||||
const componentMapRenderedFieldsPath = `feature.${featureKey}.fields${schemaPathSuffix ? `.${schemaPathSuffix}` : ''}`
|
||||
const schemaFieldsPath = `${schemaPath}.feature.${featureKey}${schemaPathSuffix ? `.${schemaPathSuffix}` : ''}`
|
||||
|
||||
const fieldMap = richTextComponentMap.get(componentMapRenderedFieldsPath) // Field Schema
|
||||
|
||||
@@ -42,7 +45,7 @@ export const LinkDrawer: React.FC<Props> = ({ drawerSlug, handleModalSubmit, sta
|
||||
apiRoute: config.routes.api,
|
||||
body: {
|
||||
id,
|
||||
data: stateData,
|
||||
data,
|
||||
operation: 'update',
|
||||
schemaPath: schemaFieldsPath,
|
||||
},
|
||||
@@ -52,10 +55,10 @@ export const LinkDrawer: React.FC<Props> = ({ drawerSlug, handleModalSubmit, sta
|
||||
setInitialState(state)
|
||||
}
|
||||
|
||||
if (stateData) {
|
||||
if (data) {
|
||||
void awaitInitialState()
|
||||
}
|
||||
}, [config.routes.api, config.serverURL, schemaFieldsPath, id, stateData])
|
||||
}, [config.routes.api, config.serverURL, schemaFieldsPath, id, data])
|
||||
|
||||
const onChange: FormProps['onChange'][0] = useCallback(
|
||||
async ({ formState: prevFormState }) => {
|
||||
@@ -74,29 +77,29 @@ export const LinkDrawer: React.FC<Props> = ({ drawerSlug, handleModalSubmit, sta
|
||||
[config.routes.api, config.serverURL, schemaFieldsPath, id],
|
||||
)
|
||||
|
||||
return (
|
||||
<Drawer className={baseClass} slug={drawerSlug} title={t('fields:editLink') ?? ''}>
|
||||
{initialState !== false && (
|
||||
<Form
|
||||
beforeSubmit={[onChange]}
|
||||
disableValidationOnSubmit
|
||||
fields={Array.isArray(fieldMap) ? fieldMap : []}
|
||||
initialState={initialState}
|
||||
onChange={[onChange]}
|
||||
onSubmit={handleModalSubmit}
|
||||
uuid={uuid()}
|
||||
>
|
||||
<RenderFields
|
||||
fieldMap={Array.isArray(fieldMap) ? fieldMap : []}
|
||||
forceRender
|
||||
path="" // See Blocks feature path for details as for why this is empty
|
||||
readOnly={false}
|
||||
schemaPath={schemaFieldsPath}
|
||||
/>
|
||||
if (initialState === false) {
|
||||
return null
|
||||
}
|
||||
|
||||
<FormSubmit>{t('general:submit')}</FormSubmit>
|
||||
</Form>
|
||||
)}
|
||||
</Drawer>
|
||||
return (
|
||||
<Form
|
||||
beforeSubmit={[onChange]}
|
||||
disableValidationOnSubmit
|
||||
fields={Array.isArray(fieldMap) ? fieldMap : []}
|
||||
initialState={initialState}
|
||||
onChange={[onChange]}
|
||||
onSubmit={handleDrawerSubmit}
|
||||
uuid={uuid()}
|
||||
>
|
||||
<RenderFields
|
||||
fieldMap={Array.isArray(fieldMap) ? fieldMap : []}
|
||||
forceRender
|
||||
path="" // See Blocks feature path for details as for why this is empty
|
||||
readOnly={false}
|
||||
schemaPath={schemaFieldsPath}
|
||||
/>
|
||||
|
||||
<FormSubmit>{t('fields:saveChanges')}</FormSubmit>
|
||||
</Form>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user