Files
payloadcms/packages/richtext-lexical/src/field/features/upload/component/index.tsx
Alessio Gravili 7880fb402a chore: playwright support (#5262)
* working playwright

* chore: use zipped, local build of playwright instead of patching it

* chore: remove bloat

* chore: get playwright and lexical to work by fixing imports from cjs modules
2024-03-08 10:56:13 -05:00

194 lines
6.1 KiB
TypeScript

'use client'
import type { SanitizedCollectionConfig } from 'payload/types'
import lexicalComposerContextImport from '@lexical/react/LexicalComposerContext.js'
const { useLexicalComposerContext } = lexicalComposerContextImport
import { useLexicalNodeSelection } from '@lexical/react/useLexicalNodeSelection.js'
import { getTranslation } from '@payloadcms/translations'
import {
Button,
DrawerToggler,
FileGraphic,
useConfig,
useDocumentDrawer,
useDrawerSlug,
usePayloadAPI,
useThumbnail,
useTranslation,
} from '@payloadcms/ui'
import lexicalImport from 'lexical'
const { $getNodeByKey } = lexicalImport
import React, { useCallback, useReducer, useState } from 'react'
import type { ClientComponentProps } from '../../types.js'
import type { UploadFeaturePropsClient } from '../feature.client.js'
import type { UploadData } from '../nodes/UploadNode.js'
import { useEditorConfigContext } from '../../../lexical/config/client/EditorConfigProvider.js'
import { EnabledRelationshipsCondition } from '../../relationship/utils/EnabledRelationshipsCondition.js'
import { INSERT_UPLOAD_WITH_DRAWER_COMMAND } from '../drawer/commands.js'
import { ExtraFieldsUploadDrawer } from './ExtraFieldsDrawer/index.js'
import './index.scss'
const baseClass = 'lexical-upload'
const initialParams = {
depth: 0,
}
export type ElementProps = {
data: UploadData
nodeKey: string
//uploadProps: UploadFeatureProps
}
const Component: React.FC<ElementProps> = (props) => {
const {
data: { fields, relationTo, value },
nodeKey,
} = props
const {
collections,
routes: { api },
serverURL,
} = useConfig()
const [editor] = useLexicalComposerContext()
const [isSelected, setSelected, clearSelection] = useLexicalNodeSelection(nodeKey)
const { editorConfig, field } = useEditorConfigContext()
const { i18n, t } = useTranslation()
const [cacheBust, dispatchCacheBust] = useReducer((state) => state + 1, 0)
const [relatedCollection, setRelatedCollection] = useState<SanitizedCollectionConfig>(() =>
collections.find((coll) => coll.slug === relationTo),
)
const drawerSlug = useDrawerSlug('upload-drawer')
const [DocumentDrawer, DocumentDrawerToggler, { closeDrawer }] = useDocumentDrawer({
id: value?.id,
collectionSlug: relatedCollection.slug,
})
// Get the referenced document
const [{ data }, { setParams }] = usePayloadAPI(
`${serverURL}${api}/${relatedCollection.slug}/${value?.id}`,
{ initialParams },
)
const thumbnailSRC = useThumbnail(relatedCollection.slug, relatedCollection.upload, data)
const removeUpload = useCallback(() => {
editor.update(() => {
$getNodeByKey(nodeKey).remove()
})
}, [editor, nodeKey])
const updateUpload = useCallback(
(json) => {
setParams({
...initialParams,
cacheBust, // do this to get the usePayloadAPI to re-fetch the data even though the URL string hasn't changed
})
dispatchCacheBust()
closeDrawer()
},
[setParams, cacheBust, closeDrawer],
)
const hasExtraFields = (
editorConfig?.resolvedFeatureMap?.get('upload')
?.clientFeatureProps as ClientComponentProps<UploadFeaturePropsClient>
).collections?.[relatedCollection.slug]?.hasExtraFields
return (
<div
className={[baseClass, isSelected && `${baseClass}--selected`].filter(Boolean).join(' ')}
contentEditable={false}
>
<div className={`${baseClass}__card`}>
<div className={`${baseClass}__topRow`}>
<div className={`${baseClass}__thumbnail`}>
{thumbnailSRC ? <img alt={data?.filename} src={thumbnailSRC} /> : <FileGraphic />}
</div>
<div className={`${baseClass}__topRowRightPanel`}>
<div className={`${baseClass}__collectionLabel`}>
{getTranslation(relatedCollection.labels.singular, i18n)}
</div>
{editor.isEditable() && (
<div className={`${baseClass}__actions`}>
{hasExtraFields ? (
<DrawerToggler
className={`${baseClass}__upload-drawer-toggler`}
disabled={field?.readOnly}
slug={drawerSlug}
>
<Button
buttonStyle="icon-label"
el="div"
icon="edit"
onClick={(e) => {
e.preventDefault()
}}
round
tooltip={t('fields:editRelationship')}
/>
</DrawerToggler>
) : null}
<Button
buttonStyle="icon-label"
disabled={field?.readOnly}
el="div"
icon="swap"
onClick={() => {
editor.dispatchCommand(INSERT_UPLOAD_WITH_DRAWER_COMMAND, {
replace: { nodeKey },
})
}}
round
tooltip={t('fields:swapUpload')}
/>
<Button
buttonStyle="icon-label"
className={`${baseClass}__removeButton`}
disabled={field?.readOnly}
icon="x"
onClick={(e) => {
e.preventDefault()
removeUpload()
}}
round
tooltip={t('fields:removeUpload')}
/>
</div>
)}
</div>
</div>
<div className={`${baseClass}__bottomRow`}>
<DocumentDrawerToggler className={`${baseClass}__doc-drawer-toggler`}>
<strong>{data?.filename}</strong>
</DocumentDrawerToggler>
</div>
</div>
{value?.id && <DocumentDrawer onSave={updateUpload} />}
<ExtraFieldsUploadDrawer
drawerSlug={drawerSlug}
relatedCollection={relatedCollection}
{...props}
/>
</div>
)
}
export const UploadComponent = (props: ElementProps): React.ReactNode => {
return (
<EnabledRelationshipsCondition {...props} uploads>
<Component {...props} />
</EnabledRelationshipsCondition>
)
}