Skip to content

Commit c460868

Browse files
authored
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.
1 parent a0a1e20 commit c460868

File tree

5 files changed

+304
-124
lines changed

5 files changed

+304
-124
lines changed

packages/payload/src/fields/hooks/beforeDuplicate/promise.ts

Lines changed: 35 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,24 @@ export const promise = async <T>({
4040
parentSchemaPath,
4141
})
4242

43+
// Handle unnamed tabs
44+
if (field.type === 'tab' && !tabHasName(field)) {
45+
await traverseFields({
46+
id,
47+
collection,
48+
context,
49+
doc,
50+
fields: field.fields,
51+
overrideAccess,
52+
path: fieldPath,
53+
req,
54+
schemaPath: fieldSchemaPath,
55+
siblingDoc,
56+
})
57+
58+
return
59+
}
60+
4361
if (fieldAffectsData(field)) {
4462
let fieldData = siblingDoc?.[field.name]
4563
const fieldIsLocalized = field.localized && localization
@@ -207,40 +225,25 @@ export const promise = async <T>({
207225
switch (field.type) {
208226
case 'tab':
209227
case 'group': {
210-
if (field.type === 'tab' && !tabHasName(field)) {
211-
await traverseFields({
212-
id,
213-
collection,
214-
context,
215-
doc,
216-
fields: field.fields,
217-
overrideAccess,
218-
path: fieldPath,
219-
req,
220-
schemaPath: fieldSchemaPath,
221-
siblingDoc,
222-
})
223-
} else {
224-
if (typeof siblingDoc[field.name] !== 'object') {
225-
siblingDoc[field.name] = {}
226-
}
227-
228-
const groupDoc = siblingDoc[field.name] as Record<string, unknown>
229-
230-
await traverseFields({
231-
id,
232-
collection,
233-
context,
234-
doc,
235-
fields: field.fields,
236-
overrideAccess,
237-
path: fieldPath,
238-
req,
239-
schemaPath: fieldSchemaPath,
240-
siblingDoc: groupDoc as JsonObject,
241-
})
228+
if (typeof siblingDoc[field.name] !== 'object') {
229+
siblingDoc[field.name] = {}
242230
}
243231

232+
const groupDoc = siblingDoc[field.name] as Record<string, unknown>
233+
234+
await traverseFields({
235+
id,
236+
collection,
237+
context,
238+
doc,
239+
fields: field.fields,
240+
overrideAccess,
241+
path: fieldPath,
242+
req,
243+
schemaPath: fieldSchemaPath,
244+
siblingDoc: groupDoc as JsonObject,
245+
})
246+
244247
break
245248
}
246249

test/localization/config.ts

Lines changed: 61 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -123,44 +123,77 @@ export default buildConfigWithDefaults({
123123
type: 'text',
124124
},
125125
{
126-
name: 'layout',
127-
blocks: [
126+
type: 'tabs',
127+
tabs: [
128128
{
129+
label: 'Main Nav',
129130
fields: [
130131
{
131-
name: 'text',
132-
type: 'text',
133-
},
134-
{
135-
name: 'nestedArray',
136-
type: 'array',
132+
name: 'nav',
133+
type: 'group',
137134
fields: [
138135
{
139-
name: 'text',
140-
type: 'text',
136+
name: 'layout',
137+
blocks: [
138+
{
139+
fields: [
140+
{
141+
name: 'text',
142+
type: 'text',
143+
},
144+
{
145+
name: 'nestedArray',
146+
type: 'array',
147+
fields: [
148+
{
149+
name: 'text',
150+
type: 'text',
151+
},
152+
{
153+
name: 'l2',
154+
type: 'array',
155+
fields: [
156+
{
157+
name: 'l3',
158+
type: 'array',
159+
fields: [
160+
{
161+
name: 'l4',
162+
type: 'array',
163+
fields: [
164+
{
165+
name: 'superNestedText',
166+
type: 'text',
167+
},
168+
],
169+
},
170+
],
171+
},
172+
],
173+
},
174+
],
175+
},
176+
],
177+
slug: 'text',
178+
},
179+
{
180+
fields: [
181+
{
182+
name: 'number',
183+
type: 'number',
184+
},
185+
],
186+
slug: 'number',
187+
},
188+
],
189+
localized: true,
190+
required: true,
191+
type: 'blocks',
141192
},
142193
],
143194
},
144195
],
145-
slug: 'text',
146196
},
147-
{
148-
fields: [
149-
{
150-
name: 'number',
151-
type: 'number',
152-
},
153-
],
154-
slug: 'number',
155-
},
156-
],
157-
localized: true,
158-
required: true,
159-
type: 'blocks',
160-
},
161-
{
162-
type: 'tabs',
163-
tabs: [
164197
{
165198
name: 'myTab',
166199
fields: [

test/localization/e2e.spec.ts

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -205,10 +205,10 @@ describe('Localization', () => {
205205
await page.goto(urlWithRequiredLocalizedFields.create)
206206
await changeLocale(page, defaultLocale)
207207
await page.locator('#field-title').fill(englishTitle)
208-
await page.locator('#field-layout .blocks-field__drawer-toggler').click()
208+
await page.locator('#field-nav__layout .blocks-field__drawer-toggler').click()
209209
await page.locator('button[title="Text"]').click()
210-
await page.fill('#field-layout__0__text', 'test')
211-
await expect(page.locator('#field-layout__0__text')).toHaveValue('test')
210+
await page.fill('#field-nav__layout__0__text', 'test')
211+
await expect(page.locator('#field-nav__layout__0__text')).toHaveValue('test')
212212
await saveDocAndAssert(page)
213213
const originalID = await page.locator('.id-label').innerText()
214214
await openDocControls(page)
@@ -256,6 +256,10 @@ describe('Localization', () => {
256256
async function fillValues(data: Partial<LocalizedPost>) {
257257
const { description: descVal, title: titleVal } = data
258258

259-
if (titleVal) {await page.locator('#field-title').fill(titleVal)}
260-
if (descVal) {await page.locator('#field-description').fill(descVal)}
259+
if (titleVal) {
260+
await page.locator('#field-title').fill(titleVal)
261+
}
262+
if (descVal) {
263+
await page.locator('#field-description').fill(descVal)
264+
}
261265
}

0 commit comments

Comments
 (0)