Skip to content
Merged
Show file tree
Hide file tree
Changes from 24 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
b187da4
adds standalone test suite for field paths and adds failing test for …
jacobsfletch Jan 28, 2025
0d49752
fixes field schema map, deprecates modified getFieldPaths fn
jacobsfletch Jan 28, 2025
e8604bd
fix build errors
jacobsfletch Jan 28, 2025
340089f
migrates fieldSchemasToFormState
jacobsfletch Jan 28, 2025
035c6fc
Merge branch 'main' into fix/field-schema-map
jacobsfletch Jan 6, 2026
7efcae9
regen hooks test types
jacobsfletch Jan 6, 2026
baf6346
revert auto formatting
jacobsfletch Jan 6, 2026
1357ab1
fix schema paths and cleanup
jacobsfletch Jan 7, 2026
c992ce8
fix build
jacobsfletch Jan 7, 2026
4b26e6c
fix schema paths within hooks
jacobsfletch Jan 7, 2026
0acc42a
fix tab component paths
jacobsfletch Jan 7, 2026
a3380f4
properly handle named tabs when traversing in form state
jacobsfletch Jan 8, 2026
45ce58b
fix for nested unnamed fields
jacobsfletch Jan 8, 2026
be4dc17
fix hooks int test
jacobsfletch Jan 8, 2026
1b84e6f
fix array paths within rows
jacobsfletch Jan 8, 2026
ecc4aeb
fix int
jacobsfletch Jan 8, 2026
fd5d4b0
fix unnamed group schema paths
jacobsfletch Jan 8, 2026
7c2ee5c
fix unnamed group schema paths in client schema map
jacobsfletch Jan 8, 2026
8f3ffe6
fix versions diff view paths
jacobsfletch Jan 9, 2026
a5be7dd
fix int
jacobsfletch Jan 9, 2026
cc08805
add basic e2e
jacobsfletch Jan 9, 2026
47af11d
fix form state select api for tabs
jacobsfletch Jan 9, 2026
2af1ae8
rm uneeded parent paths from schema mapping
jacobsfletch Jan 9, 2026
9621a70
fix build
jacobsfletch Jan 9, 2026
6161072
optional parent path
jacobsfletch Jan 9, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,7 @@ jobs:
- dashboard
- joins
- field-error-states
- field-paths
- fields-relationship
- fields__collections__Array
- fields__collections__Blocks
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -304,8 +304,8 @@ const buildVersionField = ({
field: tabAsField,
index: tabIndex,
parentIndexPath: indexPath,
parentPath,
parentSchemaPath,
parentPath: path,
parentSchemaPath: schemaPath,
})

let tabFieldsPermissions: SanitizedFieldsPermissions = undefined
Expand Down Expand Up @@ -340,11 +340,7 @@ const buildVersionField = ({
parentIndexPath: isNamedTab ? '' : tabIndexPath,
parentIsLocalized: parentIsLocalized || tab.localized,
parentPath: isNamedTab ? tabPath : 'name' in field ? path : parentPath,
parentSchemaPath: isNamedTab
? tabSchemaPath
: 'name' in field
? schemaPath
: parentSchemaPath,
parentSchemaPath: tabSchemaPath,
req,
selectedLocales,
versionFromSiblingData: 'name' in tab ? valueFrom?.[tab.name] : valueFrom,
Expand Down Expand Up @@ -396,7 +392,7 @@ const buildVersionField = ({
parentIndexPath: 'name' in field ? '' : indexPath,
parentIsLocalized: parentIsLocalized || field.localized,
parentPath: ('name' in field ? path : parentPath) + '.' + i,
parentSchemaPath: 'name' in field ? schemaPath : parentSchemaPath,
parentSchemaPath: schemaPath,
req,
selectedLocales,
versionFromSiblingData: fromRow,
Expand Down Expand Up @@ -424,7 +420,7 @@ const buildVersionField = ({
parentIndexPath: 'name' in field ? '' : indexPath,
parentIsLocalized: parentIsLocalized || ('localized' in field && field.localized),
parentPath: 'name' in field ? path : parentPath,
parentSchemaPath: 'name' in field ? schemaPath : parentSchemaPath,
parentSchemaPath: schemaPath,
req,
selectedLocales,
versionFromSiblingData: valueFrom as object,
Expand Down Expand Up @@ -502,7 +498,7 @@ const buildVersionField = ({
parentIndexPath: 'name' in field ? '' : indexPath,
parentIsLocalized: parentIsLocalized || ('localized' in field && field.localized),
parentPath: ('name' in field ? path : parentPath) + '.' + i,
parentSchemaPath: ('name' in field ? schemaPath : parentSchemaPath) + '.' + toBlock.slug,
parentSchemaPath: schemaPath + '.' + toBlock.slug,
req,
selectedLocales,
versionFromSiblingData: fromRow,
Expand Down

This file was deleted.

4 changes: 2 additions & 2 deletions packages/payload/src/admin/forms/Form.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { type SupportedLanguages } from '@payloadcms/translations'

import type { SanitizedDocumentPermissions } from '../../auth/types.js'
import type { Field, Option, Validate } from '../../fields/config/types.js'
import type { Field, Option, TabAsField, Validate } from '../../fields/config/types.js'
import type { TypedLocale } from '../../index.js'
import type { DocumentPreferences } from '../../preferences/types.js'
import type { PayloadRequest, SelectType, Where } from '../../types/index.js'
Expand Down Expand Up @@ -60,7 +60,7 @@ export type FieldState = {
* The fieldSchema may be part of the form state if `includeSchema: true` is passed to buildFormState.
* This will never be in the form state of the client.
*/
fieldSchema?: Field
fieldSchema?: Field | TabAsField
filterOptions?: FilterOptionsResult
initialValue?: unknown
/**
Expand Down
2 changes: 1 addition & 1 deletion packages/payload/src/fields/config/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1951,7 +1951,7 @@ export type FieldWithManyClient = RelationshipFieldClient | SelectFieldClient
export type FieldWithMaxDepth = RelationshipField | UploadField
export type FieldWithMaxDepthClient = JoinFieldClient | RelationshipFieldClient | UploadFieldClient

export function fieldHasSubFields<TField extends ClientField | Field>(
export function fieldHasSubFields<TField extends ClientField | Field | TabAsField>(
field: TField,
): field is TField & (TField extends ClientField ? FieldWithSubFieldsClient : FieldWithSubFields) {
return (
Expand Down
46 changes: 14 additions & 32 deletions packages/payload/src/fields/getFieldPaths.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import type { ClientTab } from '../admin/types.js'
import type { ClientField, Field, Tab, TabAsFieldClient } from './config/types.js'

type Args = {
field: ClientField | Field | Tab | TabAsFieldClient
field: ClientField | ClientTab | Field | Tab | TabAsFieldClient
index: number
parentIndexPath: string
parentPath: string
Expand Down Expand Up @@ -31,43 +32,17 @@ export function getFieldPaths({
parentIndexPath,
parentPath,
parentSchemaPath,
}: Args): FieldPaths {
if ('name' in field) {
return {
indexPath: `${parentIndexPath ? parentIndexPath + '-' : ''}${index}`,
path: `${parentPath ? parentPath + '.' : ''}${field.name}`,
schemaPath: `${parentSchemaPath ? parentSchemaPath + '.' : ''}${field.name}`,
}
}

const indexSuffix = `_index-${`${parentIndexPath ? parentIndexPath + '-' : ''}${index}`}`

return {
indexPath: `${parentIndexPath ? parentIndexPath + '-' : ''}${index}`,
path: `${parentPath ? parentPath + '.' : ''}${indexSuffix}`,
schemaPath: `${parentSchemaPath ? parentSchemaPath + '.' : ''}${indexSuffix}`,
}
}

/**
* @deprecated - will be removed in 4.0. Use `getFieldPaths` instead.
*/
export function getFieldPathsModified({
field,
index,
parentIndexPath,
parentPath,
parentSchemaPath,
}: Args): FieldPaths {
const parentPathSegments = parentPath.split('.')

const parentIsUnnamed = parentPathSegments[parentPathSegments.length - 1]!.startsWith('_index-')
const parentPathIsUnnamed =
parentPathSegments?.[parentPathSegments.length - 1]?.startsWith('_index-')

const parentWithoutIndex = parentIsUnnamed
const parentWithoutIndex = parentPathIsUnnamed
? parentPathSegments.slice(0, -1).join('.')
: parentPath

const parentPathToUse = parentIsUnnamed ? parentWithoutIndex : parentPath
const parentPathToUse = parentPathIsUnnamed ? parentWithoutIndex : parentPath

if ('name' in field) {
return {
Expand All @@ -79,9 +54,16 @@ export function getFieldPathsModified({

const indexSuffix = `_index-${`${parentIndexPath ? parentIndexPath + '-' : ''}${index}`}`

const parentSchemaPathSegments = parentSchemaPath.split('.')

const parentSchemaPathIsUnnamed =
parentSchemaPathSegments?.[parentSchemaPathSegments.length - 1]?.startsWith('_index-')

return {
indexPath: `${parentIndexPath ? parentIndexPath + '-' : ''}${index}`,
path: `${parentPathToUse ? parentPathToUse + '.' : ''}${indexSuffix}`,
schemaPath: `${!parentIsUnnamed && parentSchemaPath ? parentSchemaPath + '.' : ''}${indexSuffix}`,
schemaPath: parentSchemaPathIsUnnamed
? `${parentSchemaPath}-${index}`
: `${parentSchemaPath ? parentSchemaPath + '.' : ''}${indexSuffix}`,
}
}
2 changes: 1 addition & 1 deletion packages/payload/src/fields/hooks/afterChange/promise.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import type { Block, Field, TabAsField } from '../../config/types.js'

import { MissingEditorProp } from '../../../errors/index.js'
import { fieldAffectsData, tabHasName } from '../../config/types.js'
import { getFieldPathsModified as getFieldPaths } from '../../getFieldPaths.js'
import { getFieldPaths } from '../../getFieldPaths.js'
import { traverseFields } from './traverseFields.js'

type Args = {
Expand Down
2 changes: 1 addition & 1 deletion packages/payload/src/fields/hooks/afterRead/promise.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import { getBlockSelect } from '../../../utilities/getBlockSelect.js'
import { stripUnselectedFields } from '../../../utilities/stripUnselectedFields.js'
import { fieldAffectsData, fieldShouldBeLocalized, tabHasName } from '../../config/types.js'
import { getDefaultValue } from '../../getDefaultValue.js'
import { getFieldPathsModified as getFieldPaths } from '../../getFieldPaths.js'
import { getFieldPaths } from '../../getFieldPaths.js'
import { relationshipPopulationPromise } from './relationshipPopulationPromise.js'
import { traverseFields } from './traverseFields.js'
import { virtualFieldPopulationPromise } from './virtualFieldPopulationPromise.js'
Expand Down
2 changes: 1 addition & 1 deletion packages/payload/src/fields/hooks/beforeChange/promise.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { type RequestContext, validateBlocksFilterOptions } from '../../../index
import { deepMergeWithSourceArrays } from '../../../utilities/deepMerge.js'
import { getTranslatedLabel } from '../../../utilities/getTranslatedLabel.js'
import { fieldAffectsData, fieldShouldBeLocalized, tabHasName } from '../../config/types.js'
import { getFieldPathsModified as getFieldPaths } from '../../getFieldPaths.js'
import { getFieldPaths } from '../../getFieldPaths.js'
import { getExistingRowDoc } from './getExistingRowDoc.js'
import { traverseFields } from './traverseFields.js'

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import type { JsonObject, PayloadRequest } from '../../../types/index.js'
import type { Block, Field, FieldHookArgs, TabAsField } from '../../config/types.js'

import { fieldAffectsData, fieldShouldBeLocalized } from '../../config/types.js'
import { getFieldPathsModified as getFieldPaths } from '../../getFieldPaths.js'
import { getFieldPaths } from '../../getFieldPaths.js'
import { traverseFields } from './traverseFields.js'

type Args<T> = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import type { Block, Field, TabAsField } from '../../config/types.js'

import { MissingEditorProp } from '../../../errors/index.js'
import { fieldAffectsData, tabHasName, valueIsValueWithRelation } from '../../config/types.js'
import { getFieldPathsModified as getFieldPaths } from '../../getFieldPaths.js'
import { getFieldPaths } from '../../getFieldPaths.js'
import { getExistingRowDoc } from '../beforeChange/getExistingRowDoc.js'
import { getFallbackValue } from './getFallbackValue.js'
import { traverseFields } from './traverseFields.js'
Expand Down
Loading
Loading