Skip to content

Commit

Permalink
fix!: some custom components were not handled properly if they are RS…
Browse files Browse the repository at this point in the history
…Cs (#6315)

**Breaking:** The following, exported components now need the `payload` object as a prop rather than the `config` object:
- `RenderCustomComponent` (optional)
- `Logo`
- `DefaultTemplate`
- `DefaultNav`
  • Loading branch information
AlessioGr committed May 13, 2024
1 parent 23c7ab2 commit 0d98b4b
Show file tree
Hide file tree
Showing 16 changed files with 94 additions and 38 deletions.
1 change: 1 addition & 0 deletions packages/next/src/views/Account/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ export const Account: React.FC<AdminViewProps> = ({ initPageResult, params, sear
}
DefaultComponent={EditView}
componentProps={viewComponentProps}
payload={payload}
/>
</FormQueryParamsProvider>
</DocumentInfoProvider>
Expand Down
24 changes: 19 additions & 5 deletions packages/next/src/views/Dashboard/Default/index.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import type { Permissions } from 'payload/auth'
import type { SanitizedConfig, VisibleEntities } from 'payload/types'
import type { Payload, SanitizedConfig, VisibleEntities } from 'payload/types'

import { Gutter } from '@payloadcms/ui/elements/Gutter'
import { SetStepNav } from '@payloadcms/ui/elements/StepNav'
import { WithServerSideProps } from '@payloadcms/ui/elements/WithServerSideProps'
import { SetViewActions } from '@payloadcms/ui/providers/Actions'
import React from 'react'

Expand All @@ -14,6 +15,7 @@ const baseClass = 'dashboard'
export type DashboardProps = {
Link: React.ComponentType<any>
config: SanitizedConfig
payload: Payload
permissions: Permissions
visibleEntities: VisibleEntities
}
Expand All @@ -26,24 +28,36 @@ export const DefaultDashboard: React.FC<DashboardProps> = (props) => {
components: { afterDashboard, beforeDashboard },
},
},
payload,
permissions,
visibleEntities,
} = props

const BeforeDashboards = Array.isArray(beforeDashboard)
? beforeDashboard.map((Component, i) => (
<WithServerSideProps Component={Component} key={i} payload={payload} />
))
: null

const AfterDashboards = Array.isArray(afterDashboard)
? afterDashboard.map((Component, i) => (
<WithServerSideProps Component={Component} key={i} payload={payload} />
))
: null

return (
<div className={baseClass}>
<SetStepNav nav={[]} />
<SetViewActions actions={[]} />
<Gutter className={`${baseClass}__wrap`}>
{Array.isArray(beforeDashboard) &&
beforeDashboard.map((Component, i) => <Component key={i} />)}
{Array.isArray(BeforeDashboards) && BeforeDashboards.map((Component) => Component)}

<DefaultDashboardClient
Link={Link}
permissions={permissions}
visibleEntities={visibleEntities}
/>
{Array.isArray(afterDashboard) &&
afterDashboard.map((Component, i) => <Component key={i} />)}
{Array.isArray(AfterDashboards) && AfterDashboards.map((Component) => Component)}
</Gutter>
</div>
)
Expand Down
4 changes: 3 additions & 1 deletion packages/next/src/views/Dashboard/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,15 @@ export const Dashboard: React.FC<AdminViewProps> = ({ initPageResult }) => {
permissions,
req: {
payload: { config },
payload,
user,
},
visibleEntities,
} = initPageResult

const CustomDashboardComponent = config.admin.components?.views?.Dashboard

const viewComponentProps: DashboardProps = {
const viewComponentProps: Omit<DashboardProps, 'payload'> = {
Link,
config,
permissions,
Expand All @@ -41,6 +42,7 @@ export const Dashboard: React.FC<AdminViewProps> = ({ initPageResult }) => {
}
DefaultComponent={DefaultDashboard}
componentProps={viewComponentProps}
payload={payload}
/>
</Fragment>
)
Expand Down
1 change: 1 addition & 0 deletions packages/next/src/views/Document/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,7 @@ export const Document: React.FC<AdminViewProps> = async ({
CustomComponent={ViewOverride || CustomView}
DefaultComponent={DefaultView}
componentProps={viewComponentProps}
payload={payload}
/>
)}
</FormQueryParamsProvider>
Expand Down
1 change: 1 addition & 0 deletions packages/next/src/views/List/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ export const ListView: React.FC<AdminViewProps> = async ({ initPageResult, searc
CustomComponent={CustomListView}
DefaultComponent={DefaultListView}
componentProps={viewComponentProps}
payload={payload}
/>
</TableColumnsProvider>
</ListQueryProvider>
Expand Down
2 changes: 1 addition & 1 deletion packages/next/src/views/Login/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ export const LoginView: React.FC<AdminViewProps> = ({ initPageResult, searchPara
return (
<Fragment>
<div className={`${loginBaseClass}__brand`}>
<Logo config={config} />
<Logo payload={payload} />
</div>
{Array.isArray(BeforeLogins) && BeforeLogins.map((Component) => Component)}
{!collectionConfig?.auth?.disableLocalStrategy && <LoginForm searchParams={searchParams} />}
Expand Down
2 changes: 1 addition & 1 deletion packages/next/src/views/NotFound/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ export const NotFoundPage = async ({
<Fragment>
<HydrateClientUser permissions={initPageResult.permissions} user={initPageResult.req.user} />
<DefaultTemplate
config={initPageResult.req.payload.config}
payload={initPageResult.req.payload}
visibleEntities={initPageResult.visibleEntities}
>
<NotFoundClient />
Expand Down
5 changes: 4 additions & 1 deletion packages/next/src/views/Root/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,10 @@ export const RootPage = async ({
<MinimalTemplate className={templateClassName}>{RenderedView}</MinimalTemplate>
)}
{templateType === 'default' && (
<DefaultTemplate config={config} visibleEntities={initPageResult.visibleEntities}>
<DefaultTemplate
payload={initPageResult?.req.payload}
visibleEntities={initPageResult.visibleEntities}
>
{RenderedView}
</DefaultTemplate>
)}
Expand Down
3 changes: 2 additions & 1 deletion packages/next/src/views/Verify/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export const Verify: React.FC<AdminViewProps> = async ({ initPageResult, params

const {
payload: { config },
payload,
} = req

const {
Expand All @@ -42,7 +43,7 @@ export const Verify: React.FC<AdminViewProps> = async ({ initPageResult, params
return (
<React.Fragment>
<div className={`${verifyBaseClass}__brand`}>
<Logo config={config} />
<Logo payload={payload} />
</div>
<h2>{textToRender}</h2>
</React.Fragment>
Expand Down
6 changes: 6 additions & 0 deletions packages/payload/src/fields/config/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,9 @@ type Admin = {
Cell?: CustomComponent
Description?: DescriptionComponent
Field?: CustomComponent
/**
* The Filter component has to be a client component
*/
Filter?: React.ComponentType<any>
}
/**
Expand Down Expand Up @@ -447,6 +450,9 @@ export type UIField = {
components?: {
Cell?: CustomComponent
Field: CustomComponent
/**
* The Filter component has to be a client component
*/
Filter?: React.ComponentType<any>
}
condition?: Condition
Expand Down
31 changes: 23 additions & 8 deletions packages/ui/src/elements/Nav/index.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { SanitizedConfig } from 'payload/types'
import type { Payload } from 'payload/types'

import React from 'react'

Expand All @@ -9,32 +9,47 @@ import './index.scss'

const baseClass = 'nav'

import { WithServerSideProps } from '@payloadcms/ui/elements/WithServerSideProps'

import { DefaultNavClient } from './index.client.js'

export type NavProps = {
config: SanitizedConfig
payload: Payload
}

export const DefaultNav: React.FC<NavProps> = (props) => {
const { config } = props
const { payload } = props

if (!config) {
if (!payload?.config) {
return null
}

const {
admin: {
components: { afterNavLinks, beforeNavLinks },
},
} = config
} = payload.config

const BeforeNavLinks = Array.isArray(beforeNavLinks)
? beforeNavLinks.map((Component, i) => (
<WithServerSideProps Component={Component} key={i} payload={payload} />
))
: null

const AfterNavLinks = Array.isArray(afterNavLinks)
? afterNavLinks.map((Component, i) => (
<WithServerSideProps Component={Component} key={i} payload={payload} />
))
: null

return (
<NavWrapper baseClass={baseClass}>
<nav className={`${baseClass}__wrap`}>
{Array.isArray(beforeNavLinks) &&
beforeNavLinks.map((Component, i) => <Component key={i} />)}
{Array.isArray(BeforeNavLinks) && BeforeNavLinks.map((Component) => Component)}

<DefaultNavClient />
{Array.isArray(afterNavLinks) && afterNavLinks.map((Component, i) => <Component key={i} />)}
{Array.isArray(AfterNavLinks) && AfterNavLinks.map((Component) => Component)}

<div className={`${baseClass}__controls`}>
<Logout />
</div>
Expand Down
11 changes: 9 additions & 2 deletions packages/ui/src/elements/RenderCustomComponent/index.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,27 @@
import type { Payload } from 'payload'

import { WithServerSideProps } from '@payloadcms/ui/elements/WithServerSideProps'
import React from 'react'

export type RenderCustomComponentProps = {
CustomComponent?: React.ComponentType<any>
DefaultComponent: React.ComponentType<any>
componentProps?: Record<string, any>
/**
* Payload automatically gets added to the component if it's an RSC
*/
payload?: Payload
}

export const RenderCustomComponent: React.FC<RenderCustomComponentProps> = (props) => {
const { CustomComponent, DefaultComponent, componentProps = {} } = props

if (CustomComponent) {
return <CustomComponent {...componentProps} />
return <WithServerSideProps Component={CustomComponent} payload={null} {...componentProps} />
}

if (DefaultComponent) {
return <DefaultComponent {...componentProps} />
return <WithServerSideProps Component={DefaultComponent} payload={null} {...componentProps} />
}

return null
Expand Down
2 changes: 0 additions & 2 deletions packages/ui/src/elements/WhereBuilder/Condition/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,6 @@ export type Props = {
}) => void
}

import type { RelationshipFieldProps } from '@payloadcms/ui/fields/Relationship'

import { RenderCustomComponent } from '../../../elements/RenderCustomComponent/index.js'
import { useDebounce } from '../../../hooks/useDebounce.js'
import { Button } from '../../Button/index.js'
Expand Down
16 changes: 11 additions & 5 deletions packages/ui/src/graphics/Logo/index.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { SanitizedConfig } from 'payload/config'
import type { Payload } from 'payload'

import React from 'react'

Expand Down Expand Up @@ -33,9 +33,9 @@ const PayloadLogo: React.FC = () => (
)

export const Logo: React.FC<{
config: SanitizedConfig
payload: Payload
}> = (props) => {
const { config } = props
const { payload } = props

const {
admin: {
Expand All @@ -45,7 +45,13 @@ export const Logo: React.FC<{
},
} = {},
} = {},
} = config
} = payload.config

return <RenderCustomComponent CustomComponent={CustomLogo} DefaultComponent={PayloadLogo} />
return (
<RenderCustomComponent
CustomComponent={CustomLogo}
DefaultComponent={PayloadLogo}
payload={payload}
/>
)
}
15 changes: 7 additions & 8 deletions packages/ui/src/templates/Default/index.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { SanitizedConfig, VisibleEntities } from 'payload/types'
import type { Payload, SanitizedConfig, VisibleEntities } from 'payload/types'

import { EntityVisibilityProvider } from '@payloadcms/ui/providers/EntityVisibility'
import React from 'react'
Expand All @@ -18,28 +18,26 @@ const baseClass = 'template-default'
export type DefaultTemplateProps = {
children?: React.ReactNode
className?: string
config: Promise<SanitizedConfig> | SanitizedConfig
payload: Payload
visibleEntities?: VisibleEntities
}

export const DefaultTemplate: React.FC<DefaultTemplateProps> = async ({
export const DefaultTemplate: React.FC<DefaultTemplateProps> = ({
children,
className,
config: configPromise,
payload,
visibleEntities,
}) => {
const config = await configPromise

const {
admin: {
components: { Nav: CustomNav } = {
Nav: undefined,
},
} = {},
} = config || {}
} = payload.config || {}

const navProps: NavProps = {
config,
payload,
}

return (
Expand All @@ -55,6 +53,7 @@ export const DefaultTemplate: React.FC<DefaultTemplateProps> = async ({
CustomComponent={CustomNav}
DefaultComponent={DefaultNav}
componentProps={navProps}
payload={payload}
/>
<div className={`${baseClass}__wrap`}>
<AppHeader />
Expand Down
8 changes: 5 additions & 3 deletions test/admin/components/views/CustomDefault/index.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import type { AdminViewProps } from 'payload/types'

import { DefaultTemplate } from '@payloadcms/ui/templates/Default'
import LinkImport from 'next/link.js'
import { redirect } from 'next/navigation.js'
Expand All @@ -18,15 +20,15 @@ export const CustomDefaultView: React.FC<AdminViewProps> = ({ initPageResult })
const {
permissions,
req: {
i18n,
payload,
payload: {
config,
config: {
routes: { admin: adminRoute },
},
},
user,
},
visibleEntities,
} = initPageResult

// If an unauthorized user tries to navigate straight to this page,
Expand All @@ -36,7 +38,7 @@ export const CustomDefaultView: React.FC<AdminViewProps> = ({ initPageResult })
}

return (
<DefaultTemplate config={config} i18n={i18n} permissions={permissions} user={user}>
<DefaultTemplate payload={payload} visibleEntities={visibleEntities}>
<SetStepNav
nav={[
{
Expand Down

0 comments on commit 0d98b4b

Please sign in to comment.