Skip to content

Commit

Permalink
chore(ui): renders live document title (#5115)
Browse files Browse the repository at this point in the history
  • Loading branch information
jacobsfletch authored and DanRibbens committed Feb 27, 2024
1 parent ad24900 commit 1bbbcb3
Show file tree
Hide file tree
Showing 11 changed files with 96 additions and 101 deletions.
2 changes: 2 additions & 0 deletions packages/payload/src/admin/providers/DocumentInfo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,9 @@ export type DocumentInfoContext = {
versionsConfig: SanitizedCollectionConfig['versions'] | SanitizedGlobalConfig['versions']
}>,
) => void
setDocumentTitle: (title: string) => void
slug?: string
title?: string
unpublishedVersions?: PaginatedDocs<TypeWithVersion<any>>
versions?: PaginatedDocs<TypeWithVersion<any>>
versionsConfig?: SanitizedCollectionConfig['versions'] | SanitizedGlobalConfig['versions']
Expand Down
9 changes: 4 additions & 5 deletions packages/ui/src/elements/DeleteDocument/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,17 @@ import type { Props } from './types'

import { getTranslation } from '@payloadcms/translations'
// import { requests } from '../../../api'
import useTitle from '../../hooks/useTitle'
import { useForm } from '../../forms/Form/context'
import { MinimalTemplate } from '../../templates/Minimal'
import { useTranslation } from '../../providers/Translation'
import { useConfig } from '../../providers/Config'
import { Button } from '../Button'
import * as PopupList from '../Popup/PopupButtonList'
import './index.scss'
import { useRouter } from 'next/navigation'
import { Translation } from '../Translation'
import { useDocumentInfo } from '../../providers/DocumentInfo'

import './index.scss'

const baseClass = 'delete-document'

Expand All @@ -33,9 +34,7 @@ const DeleteDocument: React.FC<Props> = (props) => {
const { toggleModal } = useModal()
const history = useRouter()
const { i18n, t } = useTranslation()
const title = useTitle({
useAsTitle,
})
const { title } = useDocumentInfo()

const titleToRender = titleFromProps || title || id

Expand Down
3 changes: 0 additions & 3 deletions packages/ui/src/elements/DocumentHeader/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,6 @@ export const DocumentHeader: React.FC<{
<Fragment>
<RenderTitle
className={`${baseClass}__title`}
useAsTitle={collectionConfig?.admin?.useAsTitle}
globalLabel={globalConfig?.label}
globalSlug={globalConfig?.slug}
isDate={titleFieldConfig?.type === 'date'}
dateFormat={
titleFieldConfig && 'date' in titleFieldConfig?.admin
Expand Down
28 changes: 5 additions & 23 deletions packages/ui/src/elements/RenderTitle/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,36 +3,18 @@ import React from 'react'

import type { Props } from './types'

import useTitle from '../../hooks/useTitle'
import IDLabel from '../IDLabel'
import { useDocumentInfo } from '../../providers/DocumentInfo'
import './index.scss'

const baseClass = 'render-title'

const RenderTitle: React.FC<Props> = (props) => {
const {
className,
useAsTitle,
globalLabel,
globalSlug,
element = 'h1',
fallback = '[untitled]',
title: titleFromProps,
} = props

const { id } = useDocumentInfo()

const titleFromForm = useTitle({
useAsTitle: useAsTitle,
globalLabel: globalLabel,
globalSlug: globalSlug,
})

let title = titleFromForm
if (!title) title = id?.toString()
if (!title) title = fallback
title = titleFromProps || title
const { className, element = 'h1', title: titleFromProps } = props

const { title: titleFromContext, id } = useDocumentInfo()

const title = titleFromProps || titleFromContext

const idAsTitle = title === id

Expand Down
3 changes: 0 additions & 3 deletions packages/ui/src/elements/RenderTitle/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,6 @@ import type { SanitizedCollectionConfig, SanitizedGlobalConfig } from 'payload/t

export type Props = {
className?: string
useAsTitle?: SanitizedCollectionConfig['admin']['useAsTitle']
globalLabel?: SanitizedGlobalConfig['label']
globalSlug?: SanitizedGlobalConfig['slug']
element?: React.ElementType
fallback?: string
title?: string
Expand Down
41 changes: 0 additions & 41 deletions packages/ui/src/hooks/useTitle.tsx

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,6 @@ export const SetDocumentInfo: React.FC<{

useEffect(() => {
setDocumentInfo({ collectionSlug, globalSlug, id, versionsConfig })

return () => {
// reset on navigation away
setDocumentInfo({})
}
}, [collectionSlug, globalSlug, id, setDocumentInfo, versionsConfig])

return null
Expand Down
12 changes: 12 additions & 0 deletions packages/ui/src/providers/DocumentInfo/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ export const DocumentInfoProvider: React.FC<Props> = ({ children, ...rest }) =>
routes: { api },
serverURL,
} = useConfig()

const { getPreference, setPreference } = usePreferences()
const { i18n } = useTranslation()
const { permissions } = useAuth()
Expand All @@ -42,6 +43,8 @@ export const DocumentInfoProvider: React.FC<Props> = ({ children, ...rest }) =>
...rest,
})

const [title, setTitle] = useState<string>('')

const { globalSlug, collectionSlug, id, versionsConfig } = propsToUse

const baseURL = `${serverURL}${api}`
Expand Down Expand Up @@ -257,6 +260,13 @@ export const DocumentInfoProvider: React.FC<Props> = ({ children, ...rest }) =>
getDocPermissions()
}, [getDocPermissions])

const setDocumentTitle = useCallback<DocumentInfoContext['setDocumentTitle']>(
(title) => {
setTitle(title || id?.toString() || '[untitled]')
},
[setPropsToUse, id],
)

const value: DocumentInfoContext = {
id,
collectionSlug,
Expand All @@ -272,6 +282,8 @@ export const DocumentInfoProvider: React.FC<Props> = ({ children, ...rest }) =>
versionsConfig,
versions,
setDocumentInfo: setPropsToUse,
setDocumentTitle,
title,
}

return <Context.Provider value={value}>{children}</Context.Provider>
Expand Down
56 changes: 56 additions & 0 deletions packages/ui/src/views/Edit/SetDocumentTitle/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
'use client'
import { useEffect } from 'react'
import { useDocumentInfo } from '../../../providers/DocumentInfo'
import { useTranslation } from '../../../providers/Translation'
import { ClientConfig } from 'payload/types'
import { useFormFields } from '../../../forms/Form/context'
import { formatDate } from '../../..'
import { getTranslation } from '@payloadcms/translations'

export const SetDocumentTitle: React.FC<{
config?: ClientConfig
globalConfig?: ClientConfig['globals'][0]
collectionConfig?: ClientConfig['collections'][0]
}> = (props) => {
const { config, globalConfig, collectionConfig } = props

const dateFormatFromConfig = config?.admin?.dateFormat

const useAsTitle = collectionConfig?.admin?.useAsTitle

const field = useFormFields(([fields]) => (useAsTitle && fields && fields?.[useAsTitle]) || null)

const { i18n } = useTranslation()

const { setDocumentTitle } = useDocumentInfo()

let title: string

if (typeof field === 'string') {
title = field
} else if (typeof field === 'number') {
title = String(field)
} else {
title = field?.value as string
}

if (collectionConfig && useAsTitle) {
const fieldConfig = collectionConfig.fields.find((f) => 'name' in f && f.name === useAsTitle)
const isDate = fieldConfig?.type === 'date'

if (title && isDate) {
const dateFormat = fieldConfig?.admin?.date?.displayFormat || dateFormatFromConfig
title = formatDate(title, dateFormat, i18n.language)
}
}

if (globalConfig) {
title = getTranslation(globalConfig?.label, i18n) || globalConfig?.slug
}

useEffect(() => {
setDocumentTitle(title)
}, [setDocumentTitle, title])

return null
}
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
'use client'
import { useEffect } from 'react'
import { useTranslation } from '../../providers/Translation'
import { useTranslation } from '../../../providers/Translation'

import type { SanitizedCollectionConfig, SanitizedGlobalConfig } from 'payload/types'
import type { StepNavItem } from '../../elements/StepNav/types'
import type { StepNavItem } from '../../../elements/StepNav/types'

import { getTranslation } from '@payloadcms/translations'
import { useStepNav } from '../../elements/StepNav'
import { useConfig } from '../../providers/Config'
import { useEditDepth } from '../../providers/EditDepth'
import useTitle from '../../hooks/useTitle'
import { useStepNav } from '../../../elements/StepNav'
import { useConfig } from '../../../providers/Config'
import { useEditDepth } from '../../../providers/EditDepth'
import { useDocumentInfo } from '../../../providers/DocumentInfo'

export const SetStepNav: React.FC<{
collectionSlug?: SanitizedCollectionConfig['slug']
Expand All @@ -21,23 +21,11 @@ export const SetStepNav: React.FC<{
isEditing?: boolean
view?: string
}> = (props) => {
const {
collectionSlug,
globalSlug,
pluralLabel,
useAsTitle,
id,
isEditing = true,
globalLabel,
} = props
const { collectionSlug, globalSlug, pluralLabel, useAsTitle, id, isEditing = true } = props

const view: string | undefined = props?.view || undefined

const title = useTitle({
useAsTitle,
globalLabel,
globalSlug,
})
const { title } = useDocumentInfo()

const { setStepNav } = useStepNav()

Expand Down
10 changes: 9 additions & 1 deletion packages/ui/src/views/Edit/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import { Upload } from './Upload'
import { useConfig } from '../../providers/Config'
import { useTranslation } from '../../providers/Translation'
import { useComponentMap } from '../../providers/ComponentMapProvider'
import { SetDocumentTitle } from './SetDocumentTitle'

import './index.scss'

Expand All @@ -41,7 +42,9 @@ export const DefaultEditView: React.FC<EditViewProps> = (props) => {
locale,
} = props

const { collections, globals } = useConfig()
const config = useConfig()
const { collections, globals } = config

const { i18n } = useTranslation()
const { getFieldMap } = useComponentMap()

Expand Down Expand Up @@ -189,6 +192,11 @@ export const DefaultEditView: React.FC<EditViewProps> = (props) => {
isEditing={isEditing || false}
pluralLabel={collectionConfig?.labels?.plural}
/>
<SetDocumentTitle
config={config}
collectionConfig={collectionConfig}
globalConfig={globalConfig}
/>
<DocumentControls
apiURL={apiURL}
slug={collectionConfig?.slug}
Expand Down

0 comments on commit 1bbbcb3

Please sign in to comment.