fix(ui,richtext-*): path from context should always have precedence over path from props, even if it's an empty string (#6782)

This commit is contained in:
Alessio Gravili
2024-06-15 01:42:16 -04:00
committed by GitHub
parent 628749573e
commit e7159c033e
29 changed files with 163 additions and 44 deletions

View File

@@ -1,7 +1,6 @@
import type { ArrayField, Block } from 'payload/types'
import { BlocksFeature, FixedToolbarFeature } from '@payloadcms/richtext-lexical'
import { lexicalEditor } from '@payloadcms/richtext-lexical'
import { BlocksFeature, FixedToolbarFeature, lexicalEditor } from '@payloadcms/richtext-lexical'
import { textFieldsSlug } from '../Text/shared.js'
@@ -251,3 +250,34 @@ export const SubBlockBlock: Block = {
},
],
}
export const TabBlock: Block = {
slug: 'tabBlock',
fields: [
{
type: 'tabs',
tabs: [
{
label: 'Tab1',
name: 'tab1',
fields: [
{
name: 'text1',
type: 'text',
},
],
},
{
label: 'Tab2',
name: 'tab2',
fields: [
{
name: 'text2',
type: 'text',
},
],
},
],
},
],
}

View File

@@ -500,7 +500,7 @@ describe('lexicalBlocks', () => {
const newRichTextBlock = richTextField
.locator('.lexical-block:not(.lexical-block .lexical-block)')
.last() // The :not(.lexical-block .lexical-block) makes sure this does not select sub-blocks
.nth(8) // The :not(.lexical-block .lexical-block) makes sure this does not select sub-blocks
await newRichTextBlock.scrollIntoViewIfNeeded()
await expect(newRichTextBlock).toBeVisible()
@@ -888,13 +888,9 @@ describe('lexicalBlocks', () => {
test('should respect required error state in deeply nested text field', async () => {
await navigateToLexicalFields()
await wait(300)
const richTextField = page.locator('.rich-text-lexical').nth(1) // second
await wait(300)
await richTextField.scrollIntoViewIfNeeded()
await wait(300)
await expect(richTextField).toBeVisible()
await wait(300)
@@ -937,5 +933,80 @@ describe('lexicalBlocks', () => {
await expect(requiredTooltip).toBeInViewport() // toBeVisible() doesn't work for some reason
})
// Reproduces https://github.com/payloadcms/payload/issues/6631
test('ensure tabs field within lexical block correctly loads and saves data', async () => {
await navigateToLexicalFields()
const richTextField = page.locator('.rich-text-lexical').nth(1) // second
await richTextField.scrollIntoViewIfNeeded()
await expect(richTextField).toBeVisible()
const tabsBlock = richTextField.locator('.lexical-block').nth(8)
await wait(300)
await tabsBlock.scrollIntoViewIfNeeded()
await wait(300)
await expect(tabsBlock).toBeVisible()
await wait(300)
const tab1Text1Field = tabsBlock.locator('#field-tab1__text1')
await tab1Text1Field.scrollIntoViewIfNeeded()
await expect(tab1Text1Field).toBeVisible()
await expect(tab1Text1Field).toHaveValue('Some text1')
// change text to 'Some text1 changed'
await tab1Text1Field.fill('Some text1 changed')
const tab1Button = tabsBlock.locator('.tabs-field__tab-button', { hasText: 'Tab1' })
const tab2Button = tabsBlock.locator('.tabs-field__tab-button', { hasText: 'Tab2' })
await tab2Button.click()
await wait(300)
const tab2Text1Field = tabsBlock.locator('#field-tab2__text2')
await tab2Text1Field.scrollIntoViewIfNeeded()
await expect(tab2Text1Field).toBeVisible()
await expect(tab2Text1Field).toHaveValue('Some text2')
// change text to 'Some text2 changed'
await tab2Text1Field.fill('Some text2 changed')
await wait(300)
await saveDocAndAssert(page)
await wait(300)
await tabsBlock.scrollIntoViewIfNeeded()
await wait(300)
await expect(tabsBlock).toBeVisible()
await wait(300)
await tab1Button.click()
await expect(tab1Text1Field).toHaveValue('Some text1 changed')
await tab2Button.click()
await expect(tab2Text1Field).toHaveValue('Some text2 changed')
await expect(async () => {
const lexicalDoc: LexicalField = (
await payload.find({
collection: lexicalFieldsSlug,
depth: 0,
overrideAccess: true,
where: {
title: {
equals: lexicalDocData.title,
},
},
})
).docs[0] as never
const lexicalField: SerializedEditorState = lexicalDoc.lexicalWithBlocks
const tabBlockData: SerializedBlockNode = lexicalField.root
.children[13] as SerializedBlockNode
expect(tabBlockData.fields.tab1.text1).toBe('Some text1 changed')
expect(tabBlockData.fields.tab2.text2).toBe('Some text2 changed')
}).toPass({
timeout: POLL_TOPASS_TIMEOUT,
})
})
})
})

View File

@@ -273,6 +273,22 @@ export function generateLexicalRichText() {
type: 'paragraph',
version: 1,
},
{
format: '',
type: 'block',
version: 2,
fields: {
id: '666c9dfd189d72626ea301f9',
blockName: '',
tab1: {
text1: 'Some text1',
},
tab2: {
text2: 'Some text2',
},
blockType: 'tabBlock',
},
},
],
direction: 'ltr',
},

View File

@@ -4,8 +4,6 @@ import type { CollectionConfig } from 'payload/types'
import { createHeadlessEditor } from '@lexical/headless'
import { $convertToMarkdownString } from '@lexical/markdown'
import { getEnabledNodes } from '@payloadcms/richtext-lexical'
import { sanitizeServerEditorConfig } from '@payloadcms/richtext-lexical'
import {
BlocksFeature,
FixedToolbarFeature,
@@ -14,7 +12,9 @@ import {
TreeViewFeature,
UploadFeature,
defaultEditorFeatures,
getEnabledNodes,
lexicalEditor,
sanitizeServerEditorConfig,
} from '@payloadcms/richtext-lexical'
import { lexicalFieldsSlug } from '../../slugs.js'
@@ -26,6 +26,7 @@ import {
RichTextBlock,
SelectFieldBlock,
SubBlockBlock,
TabBlock,
TextBlock,
UploadAndRichTextBlock,
} from './blocks.js'
@@ -77,6 +78,7 @@ const editorConfig: ServerEditorConfig = {
SubBlockBlock,
RadioButtonsBlock,
ConditionalLayoutBlock,
TabBlock,
],
}),
],

View File

@@ -3,8 +3,11 @@
import { useFieldProps } from '@payloadcms/ui/forms/FieldPropsProvider'
import React from 'react'
const CustomLabel = () => {
const { path } = useFieldProps()
const CustomLabel = ({ schemaPath }) => {
const { path: pathFromContext } = useFieldProps()
const path = pathFromContext ?? schemaPath // pathFromContext will be undefined in list view
return (
<label className="custom-label" htmlFor={`field-${path.replace(/\./g, '__')}`}>
#label