Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: passes field permissions to custom fields #10024

Merged
merged 4 commits into from
Dec 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
3 changes: 1 addition & 2 deletions packages/payload/src/admin/fields/Array.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,7 @@ type ArrayFieldClientWithoutType = MarkOptional<ArrayFieldClient, 'type'>

type ArrayFieldBaseClientProps = {
readonly validate?: ArrayFieldValidation
} & FieldPaths &
Pick<ServerFieldBase, 'permissions'>
} & FieldPaths

export type ArrayFieldClientProps = ArrayFieldBaseClientProps &
ClientFieldBase<ArrayFieldClientWithoutType>
Expand Down
3 changes: 1 addition & 2 deletions packages/payload/src/admin/fields/Blocks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,7 @@ type BlocksFieldClientWithoutType = MarkOptional<BlocksFieldClient, 'type'>

type BlocksFieldBaseClientProps = {
readonly validate?: BlocksFieldValidation
} & FieldPaths &
Pick<ServerFieldBase, 'permissions'>
} & FieldPaths

export type BlocksFieldClientProps = BlocksFieldBaseClientProps &
ClientFieldBase<BlocksFieldClientWithoutType>
Expand Down
2 changes: 1 addition & 1 deletion packages/payload/src/admin/fields/Collapsible.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import type {
FieldLabelServerComponent,
} from '../types.js'

type CollapsibleFieldBaseClientProps = FieldPaths & Pick<ServerFieldBase, 'permissions'>
type CollapsibleFieldBaseClientProps = FieldPaths

type CollapsibleFieldClientWithoutType = MarkOptional<CollapsibleFieldClient, 'type'>

Expand Down
2 changes: 1 addition & 1 deletion packages/payload/src/admin/fields/Group.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import type {

type GroupFieldClientWithoutType = MarkOptional<GroupFieldClient, 'type'>

export type GroupFieldBaseClientProps = FieldPaths & Pick<ServerFieldBase, 'permissions'>
export type GroupFieldBaseClientProps = FieldPaths

export type GroupFieldClientProps = ClientFieldBase<GroupFieldClientWithoutType> &
GroupFieldBaseClientProps
Expand Down
3 changes: 1 addition & 2 deletions packages/payload/src/admin/fields/Row.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,7 @@ type RowFieldClientWithoutType = MarkOptional<RowFieldClient, 'type'>

type RowFieldBaseClientProps = {
readonly forceRender?: boolean
} & Omit<FieldPaths, 'path'> &
Pick<ServerFieldBase, 'permissions'>
} & Omit<FieldPaths, 'path'>

export type RowFieldClientProps = Omit<ClientFieldBase<RowFieldClientWithoutType>, 'path'> &
RowFieldBaseClientProps
Expand Down
2 changes: 1 addition & 1 deletion packages/payload/src/admin/fields/Tabs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export type ClientTab =
| ({ fields: ClientField[]; readonly path?: string } & Omit<NamedTab, 'fields'>)
| ({ fields: ClientField[] } & Omit<UnnamedTab, 'fields'>)

type TabsFieldBaseClientProps = FieldPaths & Pick<ServerFieldBase, 'permissions'>
type TabsFieldBaseClientProps = FieldPaths

type TabsFieldClientWithoutType = MarkOptional<TabsFieldClient, 'type'>

Expand Down
1 change: 1 addition & 0 deletions packages/payload/src/admin/forms/Field.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export type ClientComponentProps = {
customComponents: FormField['customComponents']
field: ClientBlock | ClientField | ClientTab
forceRender?: boolean
permissions?: SanitizedFieldPermissions
readOnly?: boolean
renderedBlocks?: RenderedField[]
/**
Expand Down
7 changes: 5 additions & 2 deletions packages/ui/src/forms/RenderFields/RenderField.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,12 @@ export function RenderField({
return CustomField || null
}

const baseFieldProps: Pick<ClientComponentProps, 'forceRender' | 'readOnly' | 'schemaPath'> = {
const baseFieldProps: Pick<
ClientComponentProps,
'forceRender' | 'permissions' | 'readOnly' | 'schemaPath'
> = {
forceRender,
permissions,
readOnly,
schemaPath,
}
Expand All @@ -68,7 +72,6 @@ export function RenderField({
indexPath,
parentPath,
parentSchemaPath,
permissions,
}

if (clientFieldConfig.admin?.hidden) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ export const renderField: RenderFieldMethod = ({
customComponents: fieldState?.customComponents || {},
field: clientField,
path,
permissions,
readOnly: typeof permissions === 'boolean' ? !permissions : !permissions?.[operation],
schemaPath,
}
Expand Down
12 changes: 12 additions & 0 deletions test/fields/collections/Array/CustomArrayField.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
'use client'
import type { ArrayFieldClientComponent } from 'payload'

import { ArrayField } from '@payloadcms/ui'

export const CustomArrayField: ArrayFieldClientComponent = (props) => {
return (
<div id="custom-array-field">
<ArrayField {...props} />
</div>
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ import type { TextFieldServerComponent } from 'payload'

import { TextField } from '@payloadcms/ui'

export const CustomField: TextFieldServerComponent = ({ clientField, path }) => {
export const CustomTextField: TextFieldServerComponent = ({ clientField, path }) => {
return (
<div id="custom-field">
<div id="custom-text-field">
<TextField field={clientField} path={path as string} />
</div>
)
Expand Down
8 changes: 7 additions & 1 deletion test/fields/collections/Array/e2e.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,12 @@ describe('Array', () => {
await expect(customRowLabel).toHaveCSS('text-transform', 'uppercase')
})

test('should render default array field within custom component', async () => {
await page.goto(url.create)
await page.locator('#field-customArrayField >> .array-field__add-row').click()
await expect(page.locator('#field-customArrayField__0__text')).toBeVisible()
})

// eslint-disable-next-line playwright/expect-expect
test('should bypass min rows validation when no rows present and field is not required', async () => {
await page.goto(url.create)
Expand Down Expand Up @@ -313,7 +319,7 @@ describe('Array', () => {
test('should externally update array rows and render custom fields', async () => {
await page.goto(url.create)
await page.locator('#updateArrayExternally').click()
await expect(page.locator('#custom-field')).toBeVisible()
await expect(page.locator('#custom-text-field')).toBeVisible()
})

test('should not re-close initCollapsed true array rows on input in create new view', async () => {
Expand Down
19 changes: 17 additions & 2 deletions test/fields/collections/Array/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -194,16 +194,31 @@ const ArrayFields: CollectionConfig = {
type: 'array',
fields: [
{
name: 'customField',
name: 'customTextField',
type: 'ui',
admin: {
components: {
Field: '/collections/Array/CustomField.js#CustomField',
Field: '/collections/Array/CustomTextField.js#CustomTextField',
},
},
},
],
},
{
name: 'customArrayField',
type: 'array',
admin: {
components: {
Field: '/collections/Array/CustomArrayField.js#CustomArrayField',
},
},
fields: [
{
name: 'text',
type: 'text',
},
],
},
{
name: 'ui',
type: 'ui',
Expand Down
Loading