fix(richtext-lexical): inline blocks did not store nested fields correctly (#10578)
Fixes https://github.com/payloadcms/payload/issues/10555 Form state with nested fields was not unflattened before saving field data to the node
This commit is contained in:
@@ -491,14 +491,13 @@ export const BlockComponent: React.FC<Props> = (props) => {
|
||||
fields={clientBlock?.fields}
|
||||
initialState={initialState}
|
||||
onChange={[onChange]}
|
||||
onSubmit={(formState) => {
|
||||
onSubmit={(formState, newData) => {
|
||||
// This is only called when form is submitted from drawer - usually only the case if the block has a custom Block component
|
||||
const newData: any = reduceFieldsToValues(formState)
|
||||
newData.blockType = formData.blockType
|
||||
editor.update(() => {
|
||||
const node = $getNodeByKey(nodeKey)
|
||||
if (node && $isBlockNode(node)) {
|
||||
node.setFields(newData, true)
|
||||
node.setFields(newData as BlockFields, true)
|
||||
}
|
||||
})
|
||||
toggleDrawer()
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
import React, { createContext, useCallback, useEffect, useMemo, useRef } from 'react'
|
||||
const baseClass = 'inline-block'
|
||||
|
||||
import type { BlocksFieldClient, FormState } from 'payload'
|
||||
import type { BlocksFieldClient, Data, FormState } from 'payload'
|
||||
|
||||
import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext'
|
||||
import { useLexicalNodeSelection } from '@lexical/react/useLexicalNodeSelection'
|
||||
@@ -33,7 +33,6 @@ import {
|
||||
KEY_BACKSPACE_COMMAND,
|
||||
KEY_DELETE_COMMAND,
|
||||
} from 'lexical'
|
||||
import { reduceFieldsToValues } from 'payload/shared'
|
||||
|
||||
import './index.scss'
|
||||
|
||||
@@ -308,13 +307,13 @@ export const InlineBlockComponent: React.FC<Props> = (props) => {
|
||||
* HANDLE FORM SUBMIT
|
||||
*/
|
||||
const onFormSubmit = useCallback(
|
||||
(formState: FormState) => {
|
||||
const newData: any = reduceFieldsToValues(formState)
|
||||
(formState: FormState, newData: Data) => {
|
||||
newData.blockType = formData.blockType
|
||||
|
||||
editor.update(() => {
|
||||
const node = $getNodeByKey(nodeKey)
|
||||
if (node && $isInlineBlockNode(node)) {
|
||||
node.setFields(newData, true)
|
||||
node.setFields(newData as InlineBlockFields, true)
|
||||
}
|
||||
})
|
||||
},
|
||||
@@ -414,8 +413,8 @@ export const InlineBlockComponent: React.FC<Props> = (props) => {
|
||||
fields={clientBlock?.fields}
|
||||
initialState={initialState || {}}
|
||||
onChange={[onChange]}
|
||||
onSubmit={(formState) => {
|
||||
onFormSubmit(formState)
|
||||
onSubmit={(formState, data) => {
|
||||
onFormSubmit(formState, data)
|
||||
toggleDrawer()
|
||||
}}
|
||||
uuid={uuid()}
|
||||
|
||||
@@ -36,7 +36,7 @@ describe('Array', () => {
|
||||
testInfo.setTimeout(TEST_TIMEOUT_LONG)
|
||||
|
||||
process.env.SEED_IN_CONFIG_ONINIT = 'false' // Makes it so the payload config onInit seed is not run. Otherwise, the seed would be run unnecessarily twice for the initial test run - once for beforeEach and once for onInit
|
||||
;({ payload, serverURL } = await initPayloadE2ENoConfig({
|
||||
;({ payload, serverURL } = await initPayloadE2ENoConfig<Config>({
|
||||
dirname,
|
||||
}))
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ describe('Collapsibles', () => {
|
||||
beforeAll(async ({ browser }, testInfo) => {
|
||||
testInfo.setTimeout(TEST_TIMEOUT_LONG)
|
||||
process.env.SEED_IN_CONFIG_ONINIT = 'false' // Makes it so the payload config onInit seed is not run. Otherwise, the seed would be run unnecessarily twice for the initial test run - once for beforeEach and once for onInit
|
||||
;({ payload, serverURL } = await initPayloadE2ENoConfig({
|
||||
;({ payload, serverURL } = await initPayloadE2ENoConfig<Config>({
|
||||
dirname,
|
||||
// prebuild,
|
||||
}))
|
||||
|
||||
@@ -45,7 +45,7 @@ describe('Conditional Logic', () => {
|
||||
beforeAll(async ({ browser }, testInfo) => {
|
||||
testInfo.setTimeout(TEST_TIMEOUT_LONG)
|
||||
process.env.SEED_IN_CONFIG_ONINIT = 'false' // Makes it so the payload config onInit seed is not run. Otherwise, the seed would be run unnecessarily twice for the initial test run - once for beforeEach and once for onInit
|
||||
;({ payload, serverURL } = await initPayloadE2ENoConfig({
|
||||
;({ payload, serverURL } = await initPayloadE2ENoConfig<Config>({
|
||||
dirname,
|
||||
// prebuild,
|
||||
}))
|
||||
|
||||
@@ -35,7 +35,7 @@ describe('Custom IDs', () => {
|
||||
beforeAll(async ({ browser }, testInfo) => {
|
||||
testInfo.setTimeout(TEST_TIMEOUT_LONG)
|
||||
process.env.SEED_IN_CONFIG_ONINIT = 'false' // Makes it so the payload config onInit seed is not run. Otherwise, the seed would be run unnecessarily twice for the initial test run - once for beforeEach and once for onInit
|
||||
;({ payload, serverURL } = await initPayloadE2ENoConfig({
|
||||
;({ payload, serverURL } = await initPayloadE2ENoConfig<Config>({
|
||||
dirname,
|
||||
// prebuild,
|
||||
}))
|
||||
|
||||
@@ -36,7 +36,7 @@ describe('Date', () => {
|
||||
beforeAll(async ({ browser }, testInfo) => {
|
||||
testInfo.setTimeout(TEST_TIMEOUT_LONG)
|
||||
process.env.SEED_IN_CONFIG_ONINIT = 'false' // Makes it so the payload config onInit seed is not run. Otherwise, the seed would be run unnecessarily twice for the initial test run - once for beforeEach and once for onInit
|
||||
;({ payload, serverURL } = await initPayloadE2ENoConfig({
|
||||
;({ payload, serverURL } = await initPayloadE2ENoConfig<Config>({
|
||||
dirname,
|
||||
// prebuild,
|
||||
}))
|
||||
|
||||
@@ -35,7 +35,7 @@ describe('Email', () => {
|
||||
beforeAll(async ({ browser }, testInfo) => {
|
||||
testInfo.setTimeout(TEST_TIMEOUT_LONG)
|
||||
process.env.SEED_IN_CONFIG_ONINIT = 'false' // Makes it so the payload config onInit seed is not run. Otherwise, the seed would be run unnecessarily twice for the initial test run - once for beforeEach and once for onInit
|
||||
;({ payload, serverURL } = await initPayloadE2ENoConfig({
|
||||
;({ payload, serverURL } = await initPayloadE2ENoConfig<Config>({
|
||||
dirname,
|
||||
// prebuild,
|
||||
}))
|
||||
|
||||
@@ -32,7 +32,7 @@ describe('Radio', () => {
|
||||
beforeAll(async ({ browser }, testInfo) => {
|
||||
testInfo.setTimeout(TEST_TIMEOUT_LONG)
|
||||
process.env.SEED_IN_CONFIG_ONINIT = 'false' // Makes it so the payload config onInit seed is not run. Otherwise, the seed would be run unnecessarily twice for the initial test run - once for beforeEach and once for onInit
|
||||
;({ payload, serverURL } = await initPayloadE2ENoConfig({
|
||||
;({ payload, serverURL } = await initPayloadE2ENoConfig<Config>({
|
||||
dirname,
|
||||
// prebuild,
|
||||
}))
|
||||
|
||||
@@ -36,7 +36,7 @@ describe('JSON', () => {
|
||||
beforeAll(async ({ browser }, testInfo) => {
|
||||
testInfo.setTimeout(TEST_TIMEOUT_LONG)
|
||||
process.env.SEED_IN_CONFIG_ONINIT = 'false' // Makes it so the payload config onInit seed is not run. Otherwise, the seed would be run unnecessarily twice for the initial test run - once for beforeEach and once for onInit
|
||||
;({ payload, serverURL } = await initPayloadE2ENoConfig({
|
||||
;({ payload, serverURL } = await initPayloadE2ENoConfig<Config>({
|
||||
dirname,
|
||||
// prebuild,
|
||||
}))
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -69,7 +69,7 @@ describe('lexicalMain', () => {
|
||||
beforeAll(async ({ browser }, testInfo) => {
|
||||
testInfo.setTimeout(TEST_TIMEOUT_LONG)
|
||||
process.env.SEED_IN_CONFIG_ONINIT = 'false' // Makes it so the payload config onInit seed is not run. Otherwise, the seed would be run unnecessarily twice for the initial test run - once for beforeEach and once for onInit
|
||||
;({ payload, serverURL } = await initPayloadE2ENoConfig({ dirname }))
|
||||
;({ payload, serverURL } = await initPayloadE2ENoConfig<Config>({ dirname }))
|
||||
|
||||
context = await browser.newContext()
|
||||
page = await context.newPage()
|
||||
|
||||
@@ -176,6 +176,25 @@ const editorConfig: ServerEditorConfig = {
|
||||
},
|
||||
],
|
||||
inlineBlocks: [
|
||||
{
|
||||
slug: 'AvatarGroup',
|
||||
interfaceName: 'AvatarGroupBlock',
|
||||
fields: [
|
||||
{
|
||||
name: 'avatars',
|
||||
type: 'array',
|
||||
minRows: 1,
|
||||
maxRows: 6,
|
||||
fields: [
|
||||
{
|
||||
name: 'image',
|
||||
type: 'upload',
|
||||
relationTo: 'uploads',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
slug: 'myInlineBlock',
|
||||
admin: {
|
||||
|
||||
@@ -38,7 +38,7 @@ describe('Number', () => {
|
||||
beforeAll(async ({ browser }, testInfo) => {
|
||||
testInfo.setTimeout(TEST_TIMEOUT_LONG)
|
||||
process.env.SEED_IN_CONFIG_ONINIT = 'false' // Makes it so the payload config onInit seed is not run. Otherwise, the seed would be run unnecessarily twice for the initial test run - once for beforeEach and once for onInit
|
||||
;({ payload, serverURL } = await initPayloadE2ENoConfig({
|
||||
;({ payload, serverURL } = await initPayloadE2ENoConfig<Config>({
|
||||
dirname,
|
||||
// prebuild,
|
||||
}))
|
||||
|
||||
@@ -37,7 +37,7 @@ describe('Point', () => {
|
||||
beforeAll(async ({ browser }, testInfo) => {
|
||||
testInfo.setTimeout(TEST_TIMEOUT_LONG)
|
||||
process.env.SEED_IN_CONFIG_ONINIT = 'false' // Makes it so the payload config onInit seed is not run. Otherwise, the seed would be run unnecessarily twice for the initial test run - once for beforeEach and once for onInit
|
||||
;({ payload, serverURL } = await initPayloadE2ENoConfig({
|
||||
;({ payload, serverURL } = await initPayloadE2ENoConfig<Config>({
|
||||
dirname,
|
||||
// prebuild,
|
||||
}))
|
||||
|
||||
@@ -31,7 +31,7 @@ describe('Radio', () => {
|
||||
beforeAll(async ({ browser }, testInfo) => {
|
||||
testInfo.setTimeout(TEST_TIMEOUT_LONG)
|
||||
process.env.SEED_IN_CONFIG_ONINIT = 'false' // Makes it so the payload config onInit seed is not run. Otherwise, the seed would be run unnecessarily twice for the initial test run - once for beforeEach and once for onInit
|
||||
;({ payload, serverURL } = await initPayloadE2ENoConfig({
|
||||
;({ payload, serverURL } = await initPayloadE2ENoConfig<Config>({
|
||||
dirname,
|
||||
// prebuild,
|
||||
}))
|
||||
|
||||
@@ -42,7 +42,7 @@ describe('relationship', () => {
|
||||
beforeAll(async ({ browser }, testInfo) => {
|
||||
testInfo.setTimeout(TEST_TIMEOUT_LONG)
|
||||
process.env.SEED_IN_CONFIG_ONINIT = 'false' // Makes it so the payload config onInit seed is not run. Otherwise, the seed would be run unnecessarily twice for the initial test run - once for beforeEach and once for onInit
|
||||
;({ payload, serverURL } = await initPayloadE2ENoConfig({
|
||||
;({ payload, serverURL } = await initPayloadE2ENoConfig<Config>({
|
||||
dirname,
|
||||
}))
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ describe('Rich Text', () => {
|
||||
beforeAll(async ({ browser }, testInfo) => {
|
||||
testInfo.setTimeout(TEST_TIMEOUT_LONG)
|
||||
process.env.SEED_IN_CONFIG_ONINIT = 'false' // Makes it so the payload config onInit seed is not run. Otherwise, the seed would be run unnecessarily twice for the initial test run - once for beforeEach and once for onInit
|
||||
;({ serverURL } = await initPayloadE2ENoConfig({
|
||||
;({ serverURL } = await initPayloadE2ENoConfig<Config>({
|
||||
dirname,
|
||||
}))
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ describe('Row', () => {
|
||||
beforeAll(async ({ browser }, testInfo) => {
|
||||
testInfo.setTimeout(TEST_TIMEOUT_LONG)
|
||||
process.env.SEED_IN_CONFIG_ONINIT = 'false' // Makes it so the payload config onInit seed is not run. Otherwise, the seed would be run unnecessarily twice for the initial test run - once for beforeEach and once for onInit
|
||||
;({ payload, serverURL } = await initPayloadE2ENoConfig({
|
||||
;({ payload, serverURL } = await initPayloadE2ENoConfig<Config>({
|
||||
dirname,
|
||||
// prebuild,
|
||||
}))
|
||||
|
||||
@@ -35,7 +35,7 @@ describe('Radio', () => {
|
||||
beforeAll(async ({ browser }, testInfo) => {
|
||||
testInfo.setTimeout(TEST_TIMEOUT_LONG)
|
||||
process.env.SEED_IN_CONFIG_ONINIT = 'false' // Makes it so the payload config onInit seed is not run. Otherwise, the seed would be run unnecessarily twice for the initial test run - once for beforeEach and once for onInit
|
||||
;({ payload, serverURL } = await initPayloadE2ENoConfig({
|
||||
;({ payload, serverURL } = await initPayloadE2ENoConfig<Config>({
|
||||
dirname,
|
||||
// prebuild,
|
||||
}))
|
||||
|
||||
@@ -39,7 +39,7 @@ describe('Tabs', () => {
|
||||
beforeAll(async ({ browser }, testInfo) => {
|
||||
testInfo.setTimeout(TEST_TIMEOUT_LONG)
|
||||
process.env.SEED_IN_CONFIG_ONINIT = 'false' // Makes it so the payload config onInit seed is not run. Otherwise, the seed would be run unnecessarily twice for the initial test run - once for beforeEach and once for onInit
|
||||
;({ payload, serverURL } = await initPayloadE2ENoConfig({
|
||||
;({ payload, serverURL } = await initPayloadE2ENoConfig<Config>({
|
||||
dirname,
|
||||
// prebuild,
|
||||
}))
|
||||
|
||||
@@ -36,7 +36,7 @@ describe('Tabs', () => {
|
||||
beforeAll(async ({ browser }, testInfo) => {
|
||||
testInfo.setTimeout(TEST_TIMEOUT_LONG)
|
||||
process.env.SEED_IN_CONFIG_ONINIT = 'false' // Makes it so the payload config onInit seed is not run. Otherwise, the seed would be run unnecessarily twice for the initial test run - once for beforeEach and once for onInit
|
||||
;({ payload, serverURL } = await initPayloadE2ENoConfig({
|
||||
;({ payload, serverURL } = await initPayloadE2ENoConfig<Config>({
|
||||
dirname,
|
||||
// prebuild,
|
||||
}))
|
||||
|
||||
@@ -43,7 +43,7 @@ describe('Text', () => {
|
||||
beforeAll(async ({ browser }, testInfo) => {
|
||||
testInfo.setTimeout(TEST_TIMEOUT_LONG)
|
||||
process.env.SEED_IN_CONFIG_ONINIT = 'false' // Makes it so the payload config onInit seed is not run. Otherwise, the seed would be run unnecessarily twice for the initial test run - once for beforeEach and once for onInit
|
||||
;({ payload, serverURL } = await initPayloadE2ENoConfig({
|
||||
;({ payload, serverURL } = await initPayloadE2ENoConfig<Config>({
|
||||
dirname,
|
||||
// prebuild,
|
||||
}))
|
||||
|
||||
@@ -31,7 +31,7 @@ describe('Radio', () => {
|
||||
beforeAll(async ({ browser }, testInfo) => {
|
||||
testInfo.setTimeout(TEST_TIMEOUT_LONG)
|
||||
process.env.SEED_IN_CONFIG_ONINIT = 'false' // Makes it so the payload config onInit seed is not run. Otherwise, the seed would be run unnecessarily twice for the initial test run - once for beforeEach and once for onInit
|
||||
;({ payload, serverURL } = await initPayloadE2ENoConfig({
|
||||
;({ payload, serverURL } = await initPayloadE2ENoConfig<Config>({
|
||||
dirname,
|
||||
// prebuild,
|
||||
}))
|
||||
|
||||
@@ -38,7 +38,7 @@ describe('Upload', () => {
|
||||
beforeAll(async ({ browser }, testInfo) => {
|
||||
testInfo.setTimeout(TEST_TIMEOUT_LONG)
|
||||
process.env.SEED_IN_CONFIG_ONINIT = 'false' // Makes it so the payload config onInit seed is not run. Otherwise, the seed would be run unnecessarily twice for the initial test run - once for beforeEach and once for onInit
|
||||
;({ payload, serverURL } = await initPayloadE2ENoConfig({
|
||||
;({ payload, serverURL } = await initPayloadE2ENoConfig<Config>({
|
||||
dirname,
|
||||
// prebuild,
|
||||
}))
|
||||
|
||||
@@ -33,7 +33,7 @@ describe('Upload with restrictions', () => {
|
||||
beforeAll(async ({ browser }, testInfo) => {
|
||||
testInfo.setTimeout(TEST_TIMEOUT_LONG)
|
||||
process.env.SEED_IN_CONFIG_ONINIT = 'false' // Makes it so the payload config onInit seed is not run. Otherwise, the seed would be run unnecessarily twice for the initial test run - once for beforeEach and once for onInit
|
||||
;({ payload, serverURL } = await initPayloadE2ENoConfig({
|
||||
;({ payload, serverURL } = await initPayloadE2ENoConfig<Config>({
|
||||
dirname,
|
||||
// prebuild,
|
||||
}))
|
||||
|
||||
@@ -3374,6 +3374,21 @@ export interface LexicalBlocksRadioButtonsBlock {
|
||||
blockName?: string | null;
|
||||
blockType: 'radioButtons';
|
||||
}
|
||||
/**
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
* via the `definition` "AvatarGroupBlock".
|
||||
*/
|
||||
export interface AvatarGroupBlock {
|
||||
avatars?:
|
||||
| {
|
||||
image?: (string | null) | Upload;
|
||||
id?: string | null;
|
||||
}[]
|
||||
| null;
|
||||
id?: string | null;
|
||||
blockName?: string | null;
|
||||
blockType: 'AvatarGroup';
|
||||
}
|
||||
/**
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
* via the `definition` "auth".
|
||||
|
||||
@@ -39,7 +39,7 @@ let serverURL: string
|
||||
describe('Locked Documents', () => {
|
||||
beforeAll(async ({ browser }, testInfo) => {
|
||||
testInfo.setTimeout(TEST_TIMEOUT_LONG)
|
||||
;({ payload, serverURL } = await initPayloadE2ENoConfig({ dirname }))
|
||||
;({ payload, serverURL } = await initPayloadE2ENoConfig<Config>({ dirname }))
|
||||
|
||||
globalUrl = new AdminUrlUtil(serverURL, 'menu')
|
||||
postsUrl = new AdminUrlUtil(serverURL, 'posts')
|
||||
|
||||
@@ -8,7 +8,7 @@ const dirname = path.dirname(filename)
|
||||
|
||||
dotenv.config({ path: path.resolve(dirname, 'test.env') })
|
||||
|
||||
let multiplier = process.env.CI ? 3 : 0.5
|
||||
let multiplier = process.env.CI ? 3 : 0.75
|
||||
let smallMultiplier = process.env.CI ? 2 : 0.75
|
||||
|
||||
export const TEST_TIMEOUT_LONG = 640000 * multiplier // 8*3 minutes - used as timeOut for the beforeAll
|
||||
|
||||
Reference in New Issue
Block a user