Files
payload/packages/ui/src/elements/DocumentDrawer/DrawerContent.tsx
Patrik 00771b1f2a fix(ui): uploading from drawer & focal point positioning (#7117)
Fixes #7101
Fixes #7006

Drawers were sending duplicate query params. This new approach modeled after the fix in V2, ensures that each drawer has its own action url created per document and the query params will be created when that is generated.

Also fixes the following:
- incorrect focal point cropping
- generated filenames for animated image names used incorrect heights
2024-07-18 13:43:53 -04:00

118 lines
3.6 KiB
TypeScript

'use client'
import { useModal } from '@faceless-ui/modal'
import React, { useCallback, useEffect, useState } from 'react'
import { toast } from 'sonner'
import type { DocumentDrawerProps } from './types.js'
import { useRelatedCollections } from '../../fields/Relationship/AddNew/useRelatedCollections.js'
import { XIcon } from '../../icons/X/index.js'
import { useComponentMap } from '../../providers/ComponentMap/index.js'
import { useConfig } from '../../providers/Config/index.js'
import { DocumentInfoProvider, useDocumentInfo } from '../../providers/DocumentInfo/index.js'
import { useLocale } from '../../providers/Locale/index.js'
import { useTranslation } from '../../providers/Translation/index.js'
import { Gutter } from '../Gutter/index.js'
import { IDLabel } from '../IDLabel/index.js'
import { RenderTitle } from '../RenderTitle/index.js'
import { baseClass } from './index.js'
export const DocumentDrawerContent: React.FC<DocumentDrawerProps> = ({
id: existingDocID,
Header,
collectionSlug,
drawerSlug,
onSave: onSaveFromProps,
}) => {
const config = useConfig()
const {
routes: { api: apiRoute },
serverURL,
} = config
const { closeModal, modalState, toggleModal } = useModal()
const locale = useLocale()
const { t } = useTranslation()
const [docID, setDocID] = useState(existingDocID)
const [isOpen, setIsOpen] = useState(false)
const [collectionConfig] = useRelatedCollections(collectionSlug)
const { componentMap } = useComponentMap()
const { Edit } = componentMap[`${collectionSlug ? 'collections' : 'globals'}`][collectionSlug]
const isEditing = Boolean(docID)
const apiURL = docID
? `${serverURL}${apiRoute}/${collectionSlug}/${docID}${locale?.code ? `?locale=${locale.code}` : ''}`
: null
useEffect(() => {
setIsOpen(Boolean(modalState[drawerSlug]?.isOpen))
}, [modalState, drawerSlug])
const onLoadError = React.useCallback(
(data) => {
if (isOpen) {
closeModal(drawerSlug)
toast.error(data.errors?.[0].message || t('error:unspecific'))
}
},
[closeModal, drawerSlug, isOpen, t],
)
const onSave = useCallback<DocumentDrawerProps['onSave']>(
(args) => {
setDocID(args.doc.id)
if (typeof onSaveFromProps === 'function') {
void onSaveFromProps({
...args,
collectionConfig,
})
}
},
[onSaveFromProps, collectionConfig],
)
return (
<DocumentInfoProvider
BeforeDocument={
<Gutter className={`${baseClass}__header`}>
<div className={`${baseClass}__header-content`}>
<h2 className={`${baseClass}__header-text`}>
{Header || <RenderTitle element="span" />}
</h2>
{/* TODO: the `button` HTML element breaks CSS transitions on the drawer for some reason...
i.e. changing to a `div` element will fix the animation issue but will break accessibility
*/}
<button
aria-label={t('general:close')}
className={`${baseClass}__header-close`}
onClick={() => toggleModal(drawerSlug)}
type="button"
>
<XIcon />
</button>
</div>
<DocumentTitle />
</Gutter>
}
apiURL={apiURL}
collectionSlug={collectionConfig.slug}
disableActions
disableLeaveWithoutSaving
id={docID}
isEditing={isEditing}
onLoadError={onLoadError}
onSave={onSave}
>
{Edit}
</DocumentInfoProvider>
)
}
const DocumentTitle: React.FC = () => {
const { id, title } = useDocumentInfo()
return id && id !== title ? <IDLabel id={id.toString()} /> : null
}