fix: shows labels of parent fields in validation error and adds test
This commit is contained in:
@@ -13,6 +13,7 @@ import { getLabelFromPath } from '../../../utilities/getLabelFromPath.js'
|
||||
import { getTranslatedLabel } from '../../../utilities/getTranslatedLabel.js'
|
||||
import { fieldAffectsData, fieldShouldBeLocalized, tabHasName } from '../../config/types.js'
|
||||
import { getFieldPathsModified as getFieldPaths } from '../../getFieldPaths.js'
|
||||
import { getParentLabels } from '../../utilities/getParentLabels.js'
|
||||
import { getExistingRowDoc } from './getExistingRowDoc.js'
|
||||
import { traverseFields } from './traverseFields.js'
|
||||
|
||||
@@ -174,35 +175,13 @@ export const promise = async ({
|
||||
})
|
||||
if (typeof validationResult === 'string') {
|
||||
const label = getTranslatedLabel(field?.label || field?.name, req.i18n)
|
||||
const parentPathSegments = parentPath ? parentPath.split('.') : []
|
||||
const parentLabels = getParentLabels(parentPathSegments, collection.fields)
|
||||
|
||||
const findLabelInFields = (fields, pathSegments) => {
|
||||
if (pathSegments.length === 0) {return undefined}
|
||||
|
||||
const [currentSegment, ...remainingSegments] = pathSegments
|
||||
|
||||
for (const field of fields) {
|
||||
if (field.name === currentSegment) {
|
||||
if (remainingSegments.length === 0) {
|
||||
return field.label
|
||||
}
|
||||
|
||||
if (field.fields && field.fields.length > 0) {
|
||||
return findLabelInFields(field.fields, remainingSegments)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const parentLabels = parentPath.split('.').map((segment, index, array) => {
|
||||
const fullPath = array.slice(0, index + 1).join('.')
|
||||
const pathSegments = fullPath.split('.')
|
||||
|
||||
const parentLabel = findLabelInFields(collection.flattenedFields, pathSegments) || segment
|
||||
|
||||
return getTranslatedLabel(parentLabel, req.i18n)
|
||||
})
|
||||
|
||||
const fieldLabel = parentLabels.length > 0 ? [...parentLabels, label].join(' > ') : label
|
||||
const fieldLabel =
|
||||
Array.isArray(parentLabels) && parentLabels.length > 0
|
||||
? getLabelFromPath(parentLabels.concat(label))
|
||||
: label
|
||||
|
||||
errors.push({
|
||||
label: fieldLabel,
|
||||
|
||||
37
packages/payload/src/fields/utilities/getParentLabels.ts
Normal file
37
packages/payload/src/fields/utilities/getParentLabels.ts
Normal file
@@ -0,0 +1,37 @@
|
||||
export function getParentLabels(
|
||||
parentPathSegments: (number | string)[],
|
||||
collectionFields: any[],
|
||||
): (number | string)[] {
|
||||
let currentFields = collectionFields
|
||||
const labels: (number | string)[] = []
|
||||
|
||||
for (const segment of parentPathSegments) {
|
||||
// If it is a number, it's an index and should be returned
|
||||
if (!isNaN(Number(segment))) {
|
||||
labels.push(segment)
|
||||
continue
|
||||
}
|
||||
|
||||
// Find the field that matches the current path segment
|
||||
const field = currentFields.find((f) => f.name === segment)
|
||||
if (!field) {
|
||||
break
|
||||
}
|
||||
|
||||
let fieldLabel = field.label ?? field.name
|
||||
if (field.labels && typeof field.labels === 'object' && field.labels.singular) {
|
||||
fieldLabel = field.labels.singular
|
||||
}
|
||||
|
||||
labels.push(fieldLabel)
|
||||
|
||||
// Loop the nested fields if they exist
|
||||
if (field.fields) {
|
||||
currentFields = field.fields
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return labels
|
||||
}
|
||||
@@ -134,6 +134,34 @@ describe('Array', () => {
|
||||
await expect(page.locator('#field-items #items-row-0 .row-label')).toContainText('Item 01')
|
||||
})
|
||||
|
||||
test('should show correct labels for array rows in toast error', async () => {
|
||||
await page.goto(url.create)
|
||||
const nestedArrayField = page.locator('#field-nestedArrayWithLabels >> .array-field__add-row')
|
||||
await nestedArrayField.click()
|
||||
const firstChildArrayField = page.locator(
|
||||
'#field-nestedArrayWithLabels__0__firstChildArray >> .array-field__add-row',
|
||||
)
|
||||
await firstChildArrayField.click()
|
||||
const secondChildArrayField = page.locator(
|
||||
'#field-nestedArrayWithLabels__0__firstChildArray__0__secondChildArray >> .array-field__add-row',
|
||||
)
|
||||
await secondChildArrayField.click()
|
||||
const childWithoutLabelField = page.locator(
|
||||
'#field-nestedArrayWithLabels__0__firstChildArray__0__secondChildArray__0__childWithoutLabel >> .array-field__add-row',
|
||||
)
|
||||
await childWithoutLabelField.click()
|
||||
|
||||
const customTextLabel = page.locator(
|
||||
'#field-nestedArrayWithLabels__0__firstChildArray__0__secondChildArray__0__childWithoutLabel__0__text',
|
||||
)
|
||||
await customTextLabel.fill('')
|
||||
|
||||
await page.click('#action-save')
|
||||
await expect(page.locator('.payload-toast-container')).toContainText(
|
||||
'The following field is invalid: Nested Array With Labels 1 > First Child Array 1 > Second Child Array 1 > Child Without Label 1 > Custom Text Label',
|
||||
)
|
||||
})
|
||||
|
||||
test('ensure functions passed to array field labels property are respected', async () => {
|
||||
await page.goto(url.create)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user