feat: ability to pass uploadActions to the Upload component (#6941)

This commit is contained in:
Jarrod Flesch
2024-06-26 13:20:54 -04:00
committed by GitHub
parent f47d6cb23c
commit 35eb16bbec
5 changed files with 90 additions and 29 deletions

View File

@@ -1,5 +1,4 @@
'use client'
import { isImage } from 'payload/shared'
import React from 'react'
import { UploadActions } from '../../elements/Upload/index.js'
@@ -13,11 +12,12 @@ const baseClass = 'file-details'
import type { Data, FileSizes, SanitizedCollectionConfig } from 'payload'
export type FileDetailsProps = {
canEdit?: boolean
collectionSlug: string
customUploadActions?: React.ReactNode[]
doc: Data & {
sizes?: FileSizes
}
enableAdjustments?: boolean
handleRemove?: () => void
hasImageSizes?: boolean
imageCacheTag?: string
@@ -25,8 +25,16 @@ export type FileDetailsProps = {
}
export const FileDetails: React.FC<FileDetailsProps> = (props) => {
const { canEdit, collectionSlug, doc, handleRemove, hasImageSizes, imageCacheTag, uploadConfig } =
props
const {
collectionSlug,
customUploadActions,
doc,
enableAdjustments,
handleRemove,
hasImageSizes,
imageCacheTag,
uploadConfig,
} = props
const { id, filename, filesize, height, mimeType, thumbnailURL, url, width } = doc
@@ -52,9 +60,12 @@ export const FileDetails: React.FC<FileDetailsProps> = (props) => {
width={width as number}
/>
{isImage(mimeType as string) && mimeType !== 'image/svg+xml' && (
<UploadActions canEdit={canEdit} showSizePreviews={hasImageSizes && doc.filename} />
)}
<UploadActions
customActions={customUploadActions}
enableAdjustments={enableAdjustments}
enablePreviewSizes={hasImageSizes && doc.filename}
mimeType={mimeType}
/>
</div>
{handleRemove && (
<Button

View File

@@ -48,7 +48,7 @@
background-color: var(--theme-bg);
}
&__file-mutation {
&__upload-actions {
display: flex;
gap: calc(var(--base) / 2);
flex-wrap: wrap;

View File

@@ -33,33 +33,60 @@ const validate = (value) => {
return true
}
export const UploadActions = ({ canEdit, showSizePreviews }) => {
type UploadActionsArgs = {
customActions?: React.ReactNode[]
enableAdjustments: boolean
enablePreviewSizes: boolean
mimeType: string
}
export const UploadActions = ({
customActions,
enableAdjustments,
enablePreviewSizes,
mimeType,
}: UploadActionsArgs) => {
const { t } = useTranslation()
const fileTypeIsAdjustable = isImage(mimeType) && mimeType !== 'image/svg+xml'
if (!fileTypeIsAdjustable && (!customActions || customActions.length === 0)) return null
return (
<div className={`${baseClass}__file-mutation`}>
{showSizePreviews && (
<div className={`${baseClass}__upload-actions`}>
{fileTypeIsAdjustable && (
<React.Fragment>
{enablePreviewSizes && (
<DrawerToggler className={`${baseClass}__previewSizes`} slug={sizePreviewSlug}>
{t('upload:previewSizes')}
</DrawerToggler>
)}
{canEdit && (
{enableAdjustments && (
<DrawerToggler className={`${baseClass}__edit`} slug={editDrawerSlug}>
{t('upload:editImage')}
</DrawerToggler>
)}
</React.Fragment>
)}
{customActions &&
customActions.map((CustomAction, i) => {
return <React.Fragment key={i}>{CustomAction}</React.Fragment>
})}
</div>
)
}
export type UploadProps = {
collectionSlug: string
customActions?: React.ReactNode[]
initialState?: FormState
onChange?: (file?: File) => void
uploadConfig: SanitizedCollectionConfig['upload']
}
export const Upload: React.FC<UploadProps> = (props) => {
const { collectionSlug, initialState, onChange, uploadConfig } = props
const { collectionSlug, customActions, initialState, onChange, uploadConfig } = props
const [replacingFile, setReplacingFile] = useState(false)
const [fileSrc, setFileSrc] = useState<null | string>(null)
@@ -169,9 +196,9 @@ export const Upload: React.FC<UploadProps> = (props) => {
<FieldError message={errorMessage} showError={showError} />
{doc.filename && !replacingFile && (
<FileDetails
canEdit={showCrop || showFocalPoint}
collectionSlug={collectionSlug}
doc={doc}
enableAdjustments={showCrop || showFocalPoint}
handleRemove={canRemoveUpload ? handleFileRemoval : undefined}
hasImageSizes={hasImageSizes}
imageCacheTag={doc.updatedAt}
@@ -203,13 +230,12 @@ export const Upload: React.FC<UploadProps> = (props) => {
type="text"
value={value.name}
/>
{isImage(value.type) && value.type !== 'image/svg+xml' && (
<UploadActions
canEdit={showCrop || showFocalPoint}
showSizePreviews={hasImageSizes && doc.filename && !replacingFile}
customActions={customActions}
enableAdjustments={showCrop || showFocalPoint}
enablePreviewSizes={hasImageSizes && doc.filename && !replacingFile}
mimeType={value.type}
/>
)}
</div>
<Button
buttonStyle="icon-label"

View File

@@ -25,6 +25,7 @@ const baseClass = 'upload'
export type UploadInputProps = Omit<UploadFieldProps, 'filterOptions'> & {
api?: string
collection?: ClientCollectionConfig
customUploadActions?: React.ReactNode[]
filterOptions?: FilterOptionsResult
onChange?: (e) => void
relationTo?: UploadField['relationTo']
@@ -41,6 +42,7 @@ export const UploadInput: React.FC<UploadInputProps> = (props) => {
api = '/api',
className,
collection,
customUploadActions,
descriptionProps,
errorProps,
filterOptions,
@@ -147,6 +149,7 @@ export const UploadInput: React.FC<UploadInputProps> = (props) => {
{fileDoc && !missingFile && (
<FileDetails
collectionSlug={relationTo}
customUploadActions={customUploadActions}
doc={fileDoc}
handleRemove={
readOnly

View File

@@ -1,8 +1,28 @@
'use client'
import { Upload, useDocumentInfo } from '@payloadcms/ui'
import { Drawer, DrawerToggler, TextField, Upload, useDocumentInfo } from '@payloadcms/ui'
import React from 'react'
const customDrawerSlug = 'custom-upload-drawer'
const CustomDrawer = () => {
return (
<Drawer slug={customDrawerSlug}>
<h1>Custom Drawer</h1>
<TextField name="alt" path="alt" />
</Drawer>
)
}
const CustomDrawerToggler = () => {
return (
<React.Fragment>
<DrawerToggler slug={customDrawerSlug}>Custom Drawer</DrawerToggler>
<CustomDrawer />
</React.Fragment>
)
}
export const CustomUploadClient = () => {
const { collectionSlug, docConfig, initialState } = useDocumentInfo()
@@ -11,6 +31,7 @@ export const CustomUploadClient = () => {
<h3>This text was rendered on the client</h3>
<Upload
collectionSlug={collectionSlug}
customActions={[<CustomDrawerToggler />]}
initialState={initialState}
uploadConfig={'upload' in docConfig ? docConfig.upload : undefined}
/>