fix: duplication with localized arrays in unnamed tabs (#8236)

Fixes a case where in relational DBs, you can't duplicate documents if
you have localized arrays within unnamed tabs.

The `beforeDuplicate` hooks were not being run for fields within unnamed
tabs.
This commit is contained in:
James Mikrut
2024-09-16 11:43:36 -04:00
committed by GitHub
parent a0a1e20193
commit c460868e52
5 changed files with 304 additions and 124 deletions

View File

@@ -123,44 +123,77 @@ export default buildConfigWithDefaults({
type: 'text',
},
{
name: 'layout',
blocks: [
type: 'tabs',
tabs: [
{
label: 'Main Nav',
fields: [
{
name: 'text',
type: 'text',
},
{
name: 'nestedArray',
type: 'array',
name: 'nav',
type: 'group',
fields: [
{
name: 'text',
type: 'text',
name: 'layout',
blocks: [
{
fields: [
{
name: 'text',
type: 'text',
},
{
name: 'nestedArray',
type: 'array',
fields: [
{
name: 'text',
type: 'text',
},
{
name: 'l2',
type: 'array',
fields: [
{
name: 'l3',
type: 'array',
fields: [
{
name: 'l4',
type: 'array',
fields: [
{
name: 'superNestedText',
type: 'text',
},
],
},
],
},
],
},
],
},
],
slug: 'text',
},
{
fields: [
{
name: 'number',
type: 'number',
},
],
slug: 'number',
},
],
localized: true,
required: true,
type: 'blocks',
},
],
},
],
slug: 'text',
},
{
fields: [
{
name: 'number',
type: 'number',
},
],
slug: 'number',
},
],
localized: true,
required: true,
type: 'blocks',
},
{
type: 'tabs',
tabs: [
{
name: 'myTab',
fields: [

View File

@@ -205,10 +205,10 @@ describe('Localization', () => {
await page.goto(urlWithRequiredLocalizedFields.create)
await changeLocale(page, defaultLocale)
await page.locator('#field-title').fill(englishTitle)
await page.locator('#field-layout .blocks-field__drawer-toggler').click()
await page.locator('#field-nav__layout .blocks-field__drawer-toggler').click()
await page.locator('button[title="Text"]').click()
await page.fill('#field-layout__0__text', 'test')
await expect(page.locator('#field-layout__0__text')).toHaveValue('test')
await page.fill('#field-nav__layout__0__text', 'test')
await expect(page.locator('#field-nav__layout__0__text')).toHaveValue('test')
await saveDocAndAssert(page)
const originalID = await page.locator('.id-label').innerText()
await openDocControls(page)
@@ -256,6 +256,10 @@ describe('Localization', () => {
async function fillValues(data: Partial<LocalizedPost>) {
const { description: descVal, title: titleVal } = data
if (titleVal) {await page.locator('#field-title').fill(titleVal)}
if (descVal) {await page.locator('#field-description').fill(descVal)}
if (titleVal) {
await page.locator('#field-title').fill(titleVal)
}
if (descVal) {
await page.locator('#field-description').fill(descVal)
}
}

View File

@@ -709,12 +709,14 @@ describe('Localization', () => {
const newDoc = await payload.create({
collection: withRequiredLocalizedFields,
data: {
layout: [
{
blockType: 'text',
text: 'laiwejfilwaje',
},
],
nav: {
layout: [
{
blockType: 'text',
text: 'laiwejfilwaje',
},
],
},
title: 'hello',
},
})
@@ -723,12 +725,14 @@ describe('Localization', () => {
id: newDoc.id,
collection: withRequiredLocalizedFields,
data: {
layout: [
{
blockType: 'number',
number: 12,
},
],
nav: {
layout: [
{
blockType: 'number',
number: 12,
},
],
},
title: 'en espanol, big bird',
},
locale: spanishLocale,
@@ -742,7 +746,7 @@ describe('Localization', () => {
},
})
expect(updatedDoc.layout[0].blockType).toStrictEqual('text')
expect(updatedDoc.nav.layout[0].blockType).toStrictEqual('text')
const spanishDoc = await payload.findByID({
id: newDoc.id,
@@ -750,7 +754,7 @@ describe('Localization', () => {
locale: spanishLocale,
})
expect(spanishDoc.layout[0].blockType).toStrictEqual('number')
expect(spanishDoc.nav.layout[0].blockType).toStrictEqual('number')
})
})
@@ -1126,26 +1130,56 @@ describe('Localization', () => {
// - and this needs to be done recursively for all block / array fields
// 2. make sure localized arrays / blocks work inside of localized groups / tabs
// - this is covered with myTab.group.nestedArray2
// 3. the field schema for `nav` is within an unnamed tab, which tests that we
// properly recursively loop through all field structures / types
const englishText = 'english'
const spanishText = 'spanish'
const doc = await payload.create({
collection: withRequiredLocalizedFields,
data: {
layout: [
{
blockType: 'text',
text: englishText,
nestedArray: [
{
text: 'hello',
},
{
text: 'goodbye',
},
],
},
],
nav: {
layout: [
{
blockType: 'text',
text: englishText,
nestedArray: [
{
text: 'hello',
l2: [
{
l3: [
{
l4: [
{
superNestedText: 'hello',
},
],
},
],
},
],
},
{
text: 'goodbye',
l2: [
{
l3: [
{
l4: [
{
superNestedText: 'goodbye',
},
],
},
],
},
],
},
],
},
],
},
myTab: {
text: 'hello',
group: {
@@ -1169,20 +1203,48 @@ describe('Localization', () => {
id: doc.id,
collection: withRequiredLocalizedFields,
data: {
layout: [
{
blockType: 'text',
text: spanishText,
nestedArray: [
{
text: 'hola',
},
{
text: 'adios',
},
],
},
],
nav: {
layout: [
{
blockType: 'text',
text: spanishText,
nestedArray: [
{
text: 'hola',
l2: [
{
l3: [
{
l4: [
{
superNestedText: 'hola',
},
],
},
],
},
],
},
{
text: 'adios',
l2: [
{
l3: [
{
l4: [
{
superNestedText: 'adios',
},
],
},
],
},
],
},
],
},
],
},
title: 'hello',
myTab: {
text: 'hola',
@@ -1215,10 +1277,10 @@ describe('Localization', () => {
})
// check fields
expect(result.layout[0].text).toStrictEqual(englishText)
expect(result.nav.layout[0].text).toStrictEqual(englishText)
expect(allLocales.layout.en[0].text).toStrictEqual(englishText)
expect(allLocales.layout.es[0].text).toStrictEqual(spanishText)
expect(allLocales.nav.layout.en[0].text).toStrictEqual(englishText)
expect(allLocales.nav.layout.es[0].text).toStrictEqual(spanishText)
expect(allLocales.myTab.group.en.nestedText).toStrictEqual('hello')
expect(allLocales.myTab.group.en.nestedArray2[0].nestedText).toStrictEqual('hello')

View File

@@ -26,6 +26,7 @@ export interface Config {
tabs: Tab;
'localized-sort': LocalizedSort;
'blocks-same-name': BlocksSameName;
'localized-within-localized': LocalizedWithinLocalized;
'payload-preferences': PayloadPreference;
'payload-migrations': PayloadMigration;
};
@@ -74,6 +75,14 @@ export interface BlocksField {
blockType: 'textBlock';
}[]
| null;
array?:
| {
link?: {
label?: string | null;
};
id?: string | null;
}[]
| null;
id?: string | null;
blockName?: string | null;
blockType: 'blockInsideBlock';
@@ -93,6 +102,9 @@ export interface NestedArray {
blocksWithinArray?:
| {
relationWithinBlock?: (string | null) | LocalizedPost;
myGroup?: {
text?: string | null;
};
id?: string | null;
blockName?: string | null;
blockType: 'someBlock';
@@ -109,6 +121,7 @@ export interface NestedArray {
| null;
updatedAt: string;
createdAt: string;
_status?: ('draft' | 'published') | null;
}
/**
* This interface was referenced by `Config`'s JSON-Schema
@@ -195,20 +208,56 @@ export interface ArrayField {
export interface LocalizedRequired {
id: string;
title: string;
layout: (
| {
text?: string | null;
id?: string | null;
blockName?: string | null;
blockType: 'text';
}
| {
number?: number | null;
id?: string | null;
blockName?: string | null;
blockType: 'number';
}
)[];
nav: {
layout: (
| {
text?: string | null;
nestedArray?:
| {
text?: string | null;
l2?:
| {
l3?:
| {
l4?:
| {
superNestedText?: string | null;
id?: string | null;
}[]
| null;
id?: string | null;
}[]
| null;
id?: string | null;
}[]
| null;
id?: string | null;
}[]
| null;
id?: string | null;
blockName?: string | null;
blockType: 'text';
}
| {
number?: number | null;
id?: string | null;
blockName?: string | null;
blockType: 'number';
}
)[];
};
myTab?: {
text?: string | null;
group?: {
nestedArray2?:
| {
nestedText?: string | null;
id?: string | null;
}[]
| null;
nestedText?: string | null;
};
};
updatedAt: string;
createdAt: string;
}
@@ -413,6 +462,35 @@ export interface BlocksSameName {
updatedAt: string;
createdAt: string;
}
/**
* This interface was referenced by `Config`'s JSON-Schema
* via the `definition` "localized-within-localized".
*/
export interface LocalizedWithinLocalized {
id: string;
myTab?: {
shouldNotBeLocalized?: string | null;
};
myArray?:
| {
shouldNotBeLocalized?: string | null;
id?: string | null;
}[]
| null;
myBlocks?:
| {
shouldNotBeLocalized?: string | null;
id?: string | null;
blockName?: string | null;
blockType: 'myBlock';
}[]
| null;
myGroup?: {
shouldNotBeLocalized?: string | null;
};
updatedAt: string;
createdAt: string;
}
/**
* This interface was referenced by `Config`'s JSON-Schema
* via the `definition` "payload-preferences".