diff --git a/packages/payload/src/fields/config/client.ts b/packages/payload/src/fields/config/client.ts index bdf14622f4..b9a9529e26 100644 --- a/packages/payload/src/fields/config/client.ts +++ b/packages/payload/src/fields/config/client.ts @@ -1,7 +1,10 @@ +/* eslint-disable perfectionist/sort-switch-case */ +// Keep perfectionist/sort-switch-case disabled - it incorrectly messes up the ordering of the switch cases, causing it to break import type { I18nClient } from '@payloadcms/translations' import type { AdminClient, + ArrayFieldClient, BlockJSX, BlocksFieldClient, ClientBlock, @@ -144,7 +147,27 @@ export const createClientField = ({ } switch (incomingField.type) { - case 'array': + case 'array': { + if (incomingField.labels) { + const field = clientField as unknown as ArrayFieldClient + + field.labels = {} as unknown as LabelsClient + + if (incomingField.labels.singular) { + if (typeof incomingField.labels.singular === 'function') { + field.labels.singular = incomingField.labels.singular({ t: i18n.t }) + } else { + field.labels.singular = incomingField.labels.singular + } + if (typeof incomingField.labels.plural === 'function') { + field.labels.plural = incomingField.labels.plural({ t: i18n.t }) + } else { + field.labels.plural = incomingField.labels.plural + } + } + } + } + // falls through case 'collapsible': case 'group': case 'row': { @@ -168,6 +191,23 @@ export const createClientField = ({ case 'blocks': { const field = clientField as unknown as BlocksFieldClient + if (incomingField.labels) { + field.labels = {} as unknown as LabelsClient + + if (incomingField.labels.singular) { + if (typeof incomingField.labels.singular === 'function') { + field.labels.singular = incomingField.labels.singular({ t: i18n.t }) + } else { + field.labels.singular = incomingField.labels.singular + } + if (typeof incomingField.labels.plural === 'function') { + field.labels.plural = incomingField.labels.plural({ t: i18n.t }) + } else { + field.labels.plural = incomingField.labels.plural + } + } + } + if (incomingField.blocks?.length) { for (let i = 0; i < incomingField.blocks.length; i++) { const block = incomingField.blocks[i] diff --git a/test/_community/payload-types.ts b/test/_community/payload-types.ts index 22f8b49173..27942bd6d6 100644 --- a/test/_community/payload-types.ts +++ b/test/_community/payload-types.ts @@ -13,6 +13,7 @@ export interface Config { collections: { posts: Post; media: Media; + test: Test; users: User; 'payload-locked-documents': PayloadLockedDocument; 'payload-preferences': PayloadPreference; @@ -22,6 +23,7 @@ export interface Config { collectionsSelect: { posts: PostsSelect | PostsSelect; media: MediaSelect | MediaSelect; + test: TestSelect | TestSelect; users: UsersSelect | UsersSelect; 'payload-locked-documents': PayloadLockedDocumentsSelect | PayloadLockedDocumentsSelect; 'payload-preferences': PayloadPreferencesSelect | PayloadPreferencesSelect; @@ -133,6 +135,28 @@ export interface Media { }; }; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "test". + */ +export interface Test { + id: string; + test_array?: + | { + test_text?: + | { + text?: string | null; + id?: string | null; + blockName?: string | null; + blockType: 'test_text'; + }[] + | null; + id?: string | null; + }[] + | null; + updatedAt: string; + createdAt: string; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "users". @@ -165,6 +189,10 @@ export interface PayloadLockedDocument { relationTo: 'media'; value: string | Media; } | null) + | ({ + relationTo: 'test'; + value: string | Test; + } | null) | ({ relationTo: 'users'; value: string | User; @@ -273,6 +301,30 @@ export interface MediaSelect { }; }; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "test_select". + */ +export interface TestSelect { + test_array?: + | T + | { + test_text?: + | T + | { + test_text?: + | T + | { + text?: T; + id?: T; + blockName?: T; + }; + }; + id?: T; + }; + updatedAt?: T; + createdAt?: T; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "users_select". diff --git a/test/fields/collections/Array/e2e.spec.ts b/test/fields/collections/Array/e2e.spec.ts index 35eb19547d..2db8a5ebd8 100644 --- a/test/fields/collections/Array/e2e.spec.ts +++ b/test/fields/collections/Array/e2e.spec.ts @@ -133,6 +133,13 @@ describe('Array', () => { await expect(page.locator('#field-items #items-row-0 .row-label')).toContainText('Item 01') }) + test('ensure functions passed to array field labels property are respected', async () => { + await page.goto(url.create) + + const arrayWithLabelsField = page.locator('#field-arrayWithLabels') + await expect(arrayWithLabelsField.locator('.array-field__add-row')).toHaveText('Add Account') + }) + describe('row manipulation', () => { test('should add, remove and duplicate rows', async () => { const assertText0 = 'array row 1' diff --git a/test/fields/collections/Array/index.ts b/test/fields/collections/Array/index.ts index 869f3a92f6..3e819094e9 100644 --- a/test/fields/collections/Array/index.ts +++ b/test/fields/collections/Array/index.ts @@ -246,6 +246,20 @@ const ArrayFields: CollectionConfig = { }, }, }, + { + name: 'arrayWithLabels', + type: 'array', + labels: { + singular: ({ t }) => t('authentication:account'), + plural: ({ t }) => t('authentication:generate'), + }, + fields: [ + { + name: 'text', + type: 'text', + }, + ], + }, ], slug: arrayFieldsSlug, versions: true, diff --git a/test/fields/collections/Blocks/e2e.spec.ts b/test/fields/collections/Blocks/e2e.spec.ts index 0f76d71de5..050f5aeac9 100644 --- a/test/fields/collections/Blocks/e2e.spec.ts +++ b/test/fields/collections/Blocks/e2e.spec.ts @@ -212,7 +212,7 @@ describe('Block fields', () => { .click() await expect( - await page.locator('#field-blocks .blocks-field__row .blocks-field__block-header', { + page.locator('#field-blocks .blocks-field__row .blocks-field__block-header', { hasText: 'Custom Block Label', }), ).toBeVisible() @@ -292,6 +292,16 @@ describe('Block fields', () => { ) }) + test('ensure functions passed to blocks field labels property are respected', async () => { + await page.goto(url.create) + + const blocksFieldWithLabels = page.locator('#field-blockWithLabels') + + await expect(blocksFieldWithLabels.locator('.blocks-field__drawer-toggler')).toHaveText( + 'Add Account', + ) + }) + describe('row manipulation', () => { describe('react hooks', () => { test('should add 2 new block rows', async () => { diff --git a/test/fields/collections/Blocks/index.ts b/test/fields/collections/Blocks/index.ts index 867b13a1f6..3936cb80fd 100644 --- a/test/fields/collections/Blocks/index.ts +++ b/test/fields/collections/Blocks/index.ts @@ -373,6 +373,29 @@ const BlockFields: CollectionConfig = { }, ], }, + { + name: 'blockWithLabels', + type: 'blocks', + labels: { + singular: ({ t }) => t('authentication:account'), + plural: ({ t }) => t('authentication:generate'), + }, + blocks: [ + { + labels: { + singular: ({ t }) => t('authentication:account'), + plural: ({ t }) => t('authentication:generate'), + }, + slug: 'text', + fields: [ + { + name: 'text', + type: 'text', + }, + ], + }, + ], + }, ], } diff --git a/test/fields/payload-types.ts b/test/fields/payload-types.ts index a9c08c8c4c..1ecc7f44ec 100644 --- a/test/fields/payload-types.ts +++ b/test/fields/payload-types.ts @@ -595,6 +595,12 @@ export interface ArrayField { id?: string | null; }[] | null; + arrayWithLabels?: + | { + text?: string | null; + id?: string | null; + }[] + | null; updatedAt: string; createdAt: string; } @@ -727,6 +733,14 @@ export interface BlockField { blockType: 'relationships'; }[] | null; + blockWithLabels?: + | { + text?: string | null; + id?: string | null; + blockName?: string | null; + blockType: 'text'; + }[] + | null; updatedAt: string; createdAt: string; } @@ -2265,6 +2279,12 @@ export interface ArrayFieldsSelect { text?: T; id?: T; }; + arrayWithLabels?: + | T + | { + text?: T; + id?: T; + }; updatedAt?: T; createdAt?: T; } @@ -2446,6 +2466,17 @@ export interface BlockFieldsSelect { blockName?: T; }; }; + blockWithLabels?: + | T + | { + text?: + | T + | { + text?: T; + id?: T; + blockName?: T; + }; + }; updatedAt?: T; createdAt?: T; }