Lexical tests comprise almost half of the collections in the fields suite, and are starting to become complex to manage. They are sometimes related to other auxiliary collections, so refactoring one test sometimes breaks another, seemingly unrelated one. In addition, the fields suite is very large, taking a long time to compile. This will make it faster. Some ideas for future refactorings: - 3 main collections: defaultFeatures, fully featured, and legacy. Legacy is the current one that has multiple editors and could later be migrated to the first two. - Avoid collections with more than 1 editor. - Create reseed buttons to restore the editor to certain states, to avoid a proliferation of collections and documents. - Reduce the complexity of the three auxiliary collections (text, array, upload), which are rarely or never used and have many fields designed for tests in the fields suite.
447 lines
8.9 KiB
TypeScript
447 lines
8.9 KiB
TypeScript
import type { ArrayField, Block, TextFieldSingleValidation } from 'payload'
|
|
|
|
import { BlocksFeature, FixedToolbarFeature, lexicalEditor } from '@payloadcms/richtext-lexical'
|
|
|
|
import { textFieldsSlug } from '../../slugs.js'
|
|
|
|
async function asyncFunction(param: string) {
|
|
return new Promise((resolve) => {
|
|
setTimeout(() => {
|
|
resolve(param?.toUpperCase())
|
|
}, 1000)
|
|
})
|
|
}
|
|
|
|
export const FilterOptionsBlock: Block = {
|
|
slug: 'filterOptionsBlock',
|
|
fields: [
|
|
{
|
|
name: 'text',
|
|
type: 'text',
|
|
},
|
|
{
|
|
name: 'group',
|
|
type: 'group',
|
|
fields: [
|
|
{
|
|
name: 'groupText',
|
|
type: 'text',
|
|
},
|
|
{
|
|
name: 'dependsOnDocData',
|
|
type: 'relationship',
|
|
relationTo: 'text-fields',
|
|
filterOptions: ({ data }) => {
|
|
if (!data.title) {
|
|
return true
|
|
}
|
|
return {
|
|
text: {
|
|
equals: data.title,
|
|
},
|
|
}
|
|
},
|
|
},
|
|
{
|
|
name: 'dependsOnSiblingData',
|
|
type: 'relationship',
|
|
relationTo: 'text-fields',
|
|
filterOptions: ({ siblingData }) => {
|
|
// @ts-expect-error
|
|
if (!siblingData?.groupText) {
|
|
return true
|
|
}
|
|
return {
|
|
text: {
|
|
equals: (siblingData as any)?.groupText,
|
|
},
|
|
}
|
|
},
|
|
},
|
|
{
|
|
name: 'dependsOnBlockData',
|
|
type: 'relationship',
|
|
relationTo: 'text-fields',
|
|
filterOptions: ({ blockData }) => {
|
|
if (!blockData?.text) {
|
|
return true
|
|
}
|
|
return {
|
|
text: {
|
|
equals: blockData?.text,
|
|
},
|
|
}
|
|
},
|
|
},
|
|
],
|
|
},
|
|
],
|
|
}
|
|
|
|
export const ValidationBlock: Block = {
|
|
slug: 'validationBlock',
|
|
fields: [
|
|
{
|
|
name: 'text',
|
|
type: 'text',
|
|
},
|
|
{
|
|
name: 'group',
|
|
type: 'group',
|
|
fields: [
|
|
{
|
|
name: 'groupText',
|
|
type: 'text',
|
|
},
|
|
{
|
|
name: 'textDependsOnDocData',
|
|
type: 'text',
|
|
validate: ((value, { data }) => {
|
|
if ((data as any)?.title === 'invalid') {
|
|
return 'doc title cannot be invalid'
|
|
}
|
|
return true
|
|
}) as TextFieldSingleValidation,
|
|
},
|
|
{
|
|
name: 'textDependsOnSiblingData',
|
|
type: 'text',
|
|
validate: ((value, { siblingData }) => {
|
|
if ((siblingData as any)?.groupText === 'invalid') {
|
|
return 'textDependsOnSiblingData sibling field cannot be invalid'
|
|
}
|
|
}) as TextFieldSingleValidation,
|
|
},
|
|
{
|
|
name: 'textDependsOnBlockData',
|
|
type: 'text',
|
|
validate: ((value, { blockData }) => {
|
|
if ((blockData as any)?.text === 'invalid') {
|
|
return 'textDependsOnBlockData sibling field cannot be invalid'
|
|
}
|
|
}) as TextFieldSingleValidation,
|
|
},
|
|
],
|
|
},
|
|
],
|
|
}
|
|
|
|
export const AsyncHooksBlock: Block = {
|
|
slug: 'asyncHooksBlock',
|
|
fields: [
|
|
{
|
|
name: 'test1',
|
|
label: 'Text',
|
|
type: 'text',
|
|
hooks: {
|
|
afterRead: [
|
|
({ value }) => {
|
|
return value?.toUpperCase()
|
|
},
|
|
],
|
|
},
|
|
},
|
|
{
|
|
name: 'test2',
|
|
label: 'Text',
|
|
type: 'text',
|
|
hooks: {
|
|
afterRead: [
|
|
async ({ value }) => {
|
|
const valuenew = await asyncFunction(value)
|
|
return valuenew
|
|
},
|
|
],
|
|
},
|
|
},
|
|
],
|
|
}
|
|
|
|
export const BlockColumns = ({ name }: { name: string }): ArrayField => ({
|
|
type: 'array',
|
|
name,
|
|
interfaceName: 'BlockColumns',
|
|
admin: {
|
|
initCollapsed: true,
|
|
},
|
|
fields: [
|
|
{
|
|
name: 'text',
|
|
type: 'text',
|
|
},
|
|
{
|
|
name: 'subArray',
|
|
type: 'array',
|
|
fields: [
|
|
{
|
|
name: 'requiredText',
|
|
type: 'text',
|
|
required: true,
|
|
},
|
|
],
|
|
},
|
|
],
|
|
})
|
|
export const ConditionalLayoutBlock: Block = {
|
|
fields: [
|
|
{
|
|
label: 'Layout',
|
|
name: 'layout',
|
|
type: 'select',
|
|
options: ['1', '2', '3'],
|
|
defaultValue: '1',
|
|
required: true,
|
|
},
|
|
{
|
|
...BlockColumns({ name: 'columns' }),
|
|
admin: {
|
|
condition: (data, siblingData) => {
|
|
return ['1'].includes(siblingData.layout)
|
|
},
|
|
},
|
|
minRows: 1,
|
|
maxRows: 1,
|
|
},
|
|
{
|
|
...BlockColumns({ name: 'columns2' }),
|
|
admin: {
|
|
condition: (data, siblingData) => {
|
|
return ['2'].includes(siblingData.layout)
|
|
},
|
|
},
|
|
minRows: 2,
|
|
maxRows: 2,
|
|
},
|
|
{
|
|
...BlockColumns({ name: 'columns3' }),
|
|
admin: {
|
|
condition: (data, siblingData) => {
|
|
return ['3'].includes(siblingData.layout)
|
|
},
|
|
},
|
|
minRows: 3,
|
|
maxRows: 3,
|
|
},
|
|
],
|
|
slug: 'conditionalLayout',
|
|
}
|
|
|
|
export const TextBlock: Block = {
|
|
fields: [
|
|
{
|
|
name: 'text',
|
|
type: 'text',
|
|
required: true,
|
|
},
|
|
],
|
|
slug: 'textRequired',
|
|
}
|
|
|
|
export const RadioButtonsBlock: Block = {
|
|
interfaceName: 'LexicalBlocksRadioButtonsBlock',
|
|
fields: [
|
|
{
|
|
name: 'radioButtons',
|
|
type: 'radio',
|
|
options: [
|
|
{
|
|
label: 'Option 1',
|
|
value: 'option1',
|
|
},
|
|
{
|
|
label: 'Option 2',
|
|
value: 'option2',
|
|
},
|
|
{
|
|
label: 'Option 3',
|
|
value: 'option3',
|
|
},
|
|
],
|
|
},
|
|
],
|
|
slug: 'radioButtons',
|
|
}
|
|
|
|
export const RichTextBlock: Block = {
|
|
fields: [
|
|
{
|
|
name: 'richTextField',
|
|
type: 'richText',
|
|
editor: lexicalEditor({
|
|
features: ({ defaultFeatures }) => [
|
|
...defaultFeatures,
|
|
FixedToolbarFeature(),
|
|
BlocksFeature({
|
|
blocks: [
|
|
{
|
|
fields: [
|
|
{
|
|
name: 'subRichTextField',
|
|
type: 'richText',
|
|
editor: lexicalEditor({}),
|
|
},
|
|
{
|
|
name: 'subUploadField',
|
|
type: 'upload',
|
|
relationTo: 'uploads',
|
|
},
|
|
],
|
|
slug: 'lexicalAndUploadBlock',
|
|
},
|
|
],
|
|
}),
|
|
],
|
|
}),
|
|
},
|
|
],
|
|
slug: 'richTextBlock',
|
|
}
|
|
|
|
export const UploadAndRichTextBlock: Block = {
|
|
fields: [
|
|
{
|
|
name: 'upload',
|
|
type: 'upload',
|
|
relationTo: 'uploads',
|
|
required: true,
|
|
},
|
|
{
|
|
name: 'richText',
|
|
type: 'richText',
|
|
editor: lexicalEditor(),
|
|
},
|
|
],
|
|
slug: 'uploadAndRichText',
|
|
}
|
|
|
|
export const RelationshipHasManyBlock: Block = {
|
|
fields: [
|
|
{
|
|
name: 'rel',
|
|
type: 'relationship',
|
|
hasMany: true,
|
|
relationTo: [textFieldsSlug, 'uploads'],
|
|
required: true,
|
|
},
|
|
],
|
|
slug: 'relationshipHasManyBlock',
|
|
}
|
|
export const RelationshipBlock: Block = {
|
|
fields: [
|
|
{
|
|
name: 'rel',
|
|
type: 'relationship',
|
|
relationTo: 'uploads',
|
|
required: true,
|
|
},
|
|
],
|
|
slug: 'relationshipBlock',
|
|
}
|
|
|
|
export const SelectFieldBlock: Block = {
|
|
fields: [
|
|
{
|
|
name: 'select',
|
|
type: 'select',
|
|
options: [
|
|
{
|
|
label: 'Option 1',
|
|
value: 'option1',
|
|
},
|
|
{
|
|
label: 'Option 2',
|
|
value: 'option2',
|
|
},
|
|
{
|
|
label: 'Option 3',
|
|
value: 'option3',
|
|
},
|
|
{
|
|
label: 'Option 4',
|
|
value: 'option4',
|
|
},
|
|
{
|
|
label: 'Option 5',
|
|
value: 'option5',
|
|
},
|
|
],
|
|
},
|
|
],
|
|
slug: 'select',
|
|
}
|
|
|
|
export const SubBlockBlock: Block = {
|
|
slug: 'subBlockLexical',
|
|
fields: [
|
|
{
|
|
name: 'subBlocksLexical',
|
|
type: 'blocks',
|
|
blocks: [
|
|
{
|
|
slug: 'contentBlock',
|
|
fields: [
|
|
{
|
|
name: 'richText',
|
|
type: 'richText',
|
|
required: true,
|
|
editor: lexicalEditor(),
|
|
},
|
|
],
|
|
},
|
|
{
|
|
slug: 'textArea',
|
|
fields: [
|
|
{
|
|
name: 'content',
|
|
type: 'textarea',
|
|
required: true,
|
|
},
|
|
],
|
|
},
|
|
SelectFieldBlock,
|
|
],
|
|
},
|
|
],
|
|
}
|
|
|
|
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',
|
|
},
|
|
],
|
|
},
|
|
],
|
|
},
|
|
],
|
|
}
|
|
|
|
export const CodeBlock: Block = {
|
|
fields: [
|
|
{
|
|
name: 'code',
|
|
type: 'code',
|
|
},
|
|
],
|
|
slug: 'code',
|
|
}
|