fix(next): custom edit view base override

This commit is contained in:
Jacob Fletcher
2024-03-14 10:05:39 -04:00
parent da1d2873d5
commit fa259aa194
5 changed files with 190 additions and 167 deletions

View File

@@ -28,6 +28,7 @@ export const getViewsFromConfig = ({
}: {
collectionConfig?: SanitizedCollectionConfig
config: SanitizedConfig
// eslint-disable-next-line @typescript-eslint/no-redundant-type-constituents
docPermissions: CollectionPermission | GlobalPermission
globalConfig?: SanitizedGlobalConfig
routeSegments: string[]
@@ -56,50 +57,46 @@ export const getViewsFromConfig = ({
config?.admin?.livePreview?.globals?.includes(globalConfig?.slug)
if (collectionConfig) {
const [collectionEntity, collectionSlug, createOrID, nestedViewSlug, segmentFive] =
routeSegments
const editConfig = collectionConfig?.admin?.components?.views?.Edit
const EditOverride = typeof editConfig === 'function' ? editConfig : null
const {
admin: { hidden },
} = collectionConfig
if (isEntityHidden({ hidden, user })) {
return null
if (EditOverride) {
CustomView = EditOverride
}
// `../:id`, or `../create`
if (!nestedViewSlug) {
switch (createOrID) {
case 'create': {
if ('create' in docPermissions && docPermissions?.create?.permission) {
CustomView = getCustomViewByKey(views, 'Default')
DefaultView = DefaultEditView
} else {
ErrorView = Unauthorized
}
break
}
if (!EditOverride) {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const [collectionEntity, collectionSlug, createOrID, nestedViewSlug, segmentFive] =
routeSegments
default: {
if (docPermissions?.read?.permission) {
CustomView = getCustomViewByKey(views, 'Default')
DefaultView = DefaultEditView
} else {
ErrorView = Unauthorized
}
}
const {
admin: { hidden },
} = collectionConfig
if (isEntityHidden({ hidden, user })) {
return null
}
}
if (nestedViewSlug) {
// `../:id/versions/:version`, etc
if (segmentFive) {
if (nestedViewSlug === 'versions') {
if (docPermissions?.readVersions?.permission) {
CustomView = getCustomViewByKey(views, 'Version')
DefaultView = DefaultVersionView
} else {
ErrorView = Unauthorized
// `../:id`, or `../create`
if (routeSegments.length === 3) {
switch (createOrID) {
case 'create': {
if ('create' in docPermissions && docPermissions?.create?.permission) {
CustomView = getCustomViewByKey(views, 'Default')
DefaultView = DefaultEditView
} else {
ErrorView = Unauthorized
}
break
}
default: {
if (docPermissions?.read?.permission) {
CustomView = getCustomViewByKey(views, 'Default')
DefaultView = DefaultEditView
} else {
ErrorView = Unauthorized
}
}
}
}
@@ -139,75 +136,101 @@ export const getViewsFromConfig = ({
}
}
}
// `../:id/versions/:version`, etc
if (routeSegments.length === 5) {
if (nestedViewSlug === 'versions') {
if (docPermissions?.readVersions?.permission) {
CustomView = getCustomViewByKey(views, 'Version')
DefaultView = DefaultVersionView
} else {
ErrorView = Unauthorized
}
}
}
}
}
if (globalConfig) {
const [globalEntity, globalSlug, nestedViewSlug] = routeSegments
const editConfig = globalConfig?.admin?.components?.views?.Edit
const EditOverride = typeof editConfig === 'function' ? editConfig : null
const {
admin: { hidden },
} = globalConfig
if (isEntityHidden({ hidden, user })) {
return null
if (EditOverride) {
CustomView = EditOverride
}
if (routeSegments?.length === 2) {
if (docPermissions?.read?.permission) {
CustomView = getCustomViewByKey(views, 'Default')
DefaultView = DefaultEditView
} else {
ErrorView = Unauthorized
if (!EditOverride) {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const [globalEntity, globalSlug, nestedViewSlug] = routeSegments
const {
admin: { hidden },
} = globalConfig
if (isEntityHidden({ hidden, user })) {
return null
}
} else if (routeSegments?.length === 3) {
// `../:slug/api`, `../:slug/preview`, `../:slug/versions`, etc
switch (nestedViewSlug) {
case 'api': {
if (globalConfig?.admin?.hideAPIURL !== true) {
CustomView = getCustomViewByKey(views, 'API')
DefaultView = DefaultAPIView
}
break
}
case 'preview': {
if (livePreviewEnabled) {
DefaultView = DefaultLivePreviewView
}
break
}
case 'versions': {
if (docPermissions?.readVersions?.permission) {
CustomView = getCustomViewByKey(views, 'Versions')
DefaultView = DefaultVersionsView
} else {
ErrorView = Unauthorized
}
break
}
default: {
if (docPermissions?.read?.permission) {
CustomView = getCustomViewByKey(views, 'Default')
DefaultView = DefaultEditView
} else {
ErrorView = Unauthorized
}
break
}
}
} else if (routeSegments?.length === 4) {
// `../:slug/versions/:version`, etc
if (nestedViewSlug === 'versions') {
if (docPermissions?.readVersions?.permission) {
CustomView = getCustomViewByKey(views, 'Version')
DefaultView = DefaultVersionView
if (routeSegments?.length === 2) {
if (docPermissions?.read?.permission) {
CustomView = getCustomViewByKey(views, 'Default')
DefaultView = DefaultEditView
} else {
ErrorView = Unauthorized
}
}
if (routeSegments?.length === 3) {
// `../:slug/api`, `../:slug/preview`, `../:slug/versions`, etc
switch (nestedViewSlug) {
case 'api': {
if (globalConfig?.admin?.hideAPIURL !== true) {
CustomView = getCustomViewByKey(views, 'API')
DefaultView = DefaultAPIView
}
break
}
case 'preview': {
if (livePreviewEnabled) {
DefaultView = DefaultLivePreviewView
}
break
}
case 'versions': {
if (docPermissions?.readVersions?.permission) {
CustomView = getCustomViewByKey(views, 'Versions')
DefaultView = DefaultVersionsView
} else {
ErrorView = Unauthorized
}
break
}
default: {
if (docPermissions?.read?.permission) {
CustomView = getCustomViewByKey(views, 'Default')
DefaultView = DefaultEditView
} else {
ErrorView = Unauthorized
}
break
}
}
}
if (routeSegments?.length === 4) {
// `../:slug/versions/:version`, etc
if (nestedViewSlug === 'versions') {
if (docPermissions?.readVersions?.permission) {
CustomView = getCustomViewByKey(views, 'Version')
DefaultView = DefaultVersionView
} else {
ErrorView = Unauthorized
}
}
}
}
}

View File

@@ -1,5 +1,6 @@
import type { EditViewComponent } from 'payload/config'
import type {
AdminViewComponent,
DocumentPreferences,
Document as DocumentType,
Field,
@@ -25,6 +26,7 @@ import React from 'react'
import type { GenerateEditViewMetadata } from './getMetaBySegment.js'
import { NotFoundClient } from '../NotFound/index.client.js'
import { NotFoundView } from '../NotFound/index.js'
import { getMetaBySegment } from './getMetaBySegment.js'
import { getViewsFromConfig } from './getViewsFromConfig.js'
@@ -62,8 +64,11 @@ export const Document: React.FC<AdminViewProps> = async ({
const isEditing = Boolean(globalSlug || (collectionSlug && !!id))
let ViewOverride: EditViewComponent
let CustomView: EditViewComponent
let DefaultView: EditViewComponent
let ErrorView: AdminViewComponent = NotFoundView
let data: DocumentType
let docPermissions: DocumentPermissions
let preferencesKey: string
@@ -92,19 +97,24 @@ export const Document: React.FC<AdminViewProps> = async ({
collectionConfig.versions?.drafts ? '&draft=true' : ''
}`
const collectionViews = getViewsFromConfig({
collectionConfig,
config,
docPermissions,
routeSegments: segments,
user,
})
const editConfig = collectionConfig?.admin?.components?.views?.Edit
ViewOverride = typeof editConfig === 'function' ? editConfig : null
CustomView = collectionViews?.CustomView
DefaultView = collectionViews?.DefaultView
if (!ViewOverride) {
const collectionViews = getViewsFromConfig({
collectionConfig,
config,
docPermissions,
routeSegments: segments,
user,
})
if (!CustomView && !DefaultView) {
const ErrorView = collectionViews?.ErrorView || NotFoundClient
CustomView = collectionViews?.CustomView
DefaultView = collectionViews?.DefaultView
ErrorView = collectionViews?.ErrorView
}
if (!CustomView && !DefaultView && !ViewOverride) {
return <ErrorView initPageResult={initPageResult} searchParams={searchParams} />
}
@@ -139,38 +149,43 @@ export const Document: React.FC<AdminViewProps> = async ({
globalConfig.versions?.drafts ? '&draft=true' : ''
}`
const globalViews = getViewsFromConfig({
config,
docPermissions,
globalConfig,
routeSegments: segments,
user,
})
const editConfig = globalConfig?.admin?.components?.views?.Edit
ViewOverride = typeof editConfig === 'function' ? editConfig : null
CustomView = globalViews?.CustomView
DefaultView = globalViews?.DefaultView
if (!CustomView && !DefaultView) {
const ErrorView = globalViews?.ErrorView || NotFoundClient
return <ErrorView initPageResult={initPageResult} searchParams={searchParams} />
}
try {
data = await payload.findGlobal({
slug: globalSlug,
depth: 0,
fallbackLocale: null,
locale: locale.code,
overrideAccess: false,
if (!ViewOverride) {
const globalViews = getViewsFromConfig({
config,
docPermissions,
globalConfig,
routeSegments: segments,
user,
})
} catch (error) {} // eslint-disable-line no-empty
if (!data) {
return <NotFoundClient />
CustomView = globalViews?.CustomView
DefaultView = globalViews?.DefaultView
ErrorView = globalViews?.ErrorView
if (!CustomView && !DefaultView && !ViewOverride) {
return <ErrorView initPageResult={initPageResult} searchParams={searchParams} />
}
try {
data = await payload.findGlobal({
slug: globalSlug,
depth: 0,
fallbackLocale: null,
locale: locale.code,
overrideAccess: false,
user,
})
} catch (error) {} // eslint-disable-line no-empty
if (!data) {
return <NotFoundClient />
}
preferencesKey = `global-${globalSlug}`
}
preferencesKey = `global-${globalSlug}`
}
const { docs: [{ value: docPreferences } = { value: null }] = [] } = (await payload.find({
@@ -222,12 +237,14 @@ export const Document: React.FC<AdminViewProps> = async ({
i18n,
})}
>
<DocumentHeader
collectionConfig={collectionConfig}
config={payload.config}
globalConfig={globalConfig}
i18n={i18n}
/>
{!ViewOverride && (
<DocumentHeader
collectionConfig={collectionConfig}
config={payload.config}
globalConfig={globalConfig}
i18n={i18n}
/>
)}
<HydrateClientUser permissions={permissions} user={user} />
<EditDepthProvider depth={1} key={`${collectionSlug || globalSlug}-${locale.code}`}>
<FormQueryParamsProvider
@@ -239,7 +256,7 @@ export const Document: React.FC<AdminViewProps> = async ({
}}
>
<RenderCustomComponent
CustomComponent={typeof CustomView === 'function' ? CustomView : undefined}
CustomComponent={ViewOverride || CustomView}
DefaultComponent={DefaultView}
componentProps={serverSideProps}
/>

View File

@@ -1,38 +1,17 @@
import type { SanitizedConfig } from 'payload/types'
import type { AdminViewComponent } from 'payload/types'
import { DefaultTemplate } from '@payloadcms/ui'
import React from 'react'
import { initPage } from '../../utilities/initPage.js'
import { NotFoundClient } from './index.client.js'
export const NotFoundView = async ({
config: configPromise,
params,
searchParams,
}: {
config: Promise<SanitizedConfig>
params: {
[key: string]: string | string[]
}
searchParams: {
[key: string]: string | string[]
}
}) => {
const config = await configPromise
const initPageResult = await initPage({
config,
route: '',
searchParams,
})
export const NotFoundView: AdminViewComponent = ({ initPageResult }) => {
return (
<DefaultTemplate
config={initPageResult.req.payload.config}
i18n={initPageResult.req.i18n}
permissions={initPageResult.permissions}
user={initPageResult.req.user}
config={initPageResult?.req?.payload.config}
i18n={initPageResult?.req?.i18n}
permissions={initPageResult?.permissions}
user={initPageResult?.req?.user}
>
<NotFoundClient />
</DefaultTemplate>

View File

@@ -27,6 +27,10 @@ export const DefaultNav: React.FC<{
}> = (props) => {
const { config, i18n, permissions, user } = props
if (!config) {
return null
}
const {
admin: {
components: { afterNavLinks, beforeNavLinks },

View File

@@ -28,7 +28,7 @@ export const DefaultTemplate: React.FC<Props> = async ({
Nav: undefined,
},
} = {},
} = config
} = config || {}
return (
<Fragment>