fix(ui): upload.displayPreview should affect all previews in the admin panel (#11496)

### What?
We have the option to set `displayPreview: true || false` on upload
collections / upload fields - with the **field** option taking
precedence.

Currently, `displayPreview` is only affecting the list view for the
**_related_** collection.

i.e. if you go to a collection that has an upload field - the preview
will be hidden/shown correctly according to the `displayPreview` option.
<img width="620" alt="Screenshot 2025-03-03 at 12 38 18 PM"
src="https://github.com/user-attachments/assets/c11c2a84-0f64-4a08-940e-8c3f9096484b"
/>

However, when you go directly to the upload collection and look at the
list view - the preview is always shown, not affected by the
`displayPreview` option.
<img width="446" alt="Screenshot 2025-03-03 at 12 39 24 PM"
src="https://github.com/user-attachments/assets/f5e1267a-d98a-4c8c-8d54-93dea6cd2e31"
/>

Also, we have previews within the file field itself - also not being
affected by the `displayPreview` option.
<img width="528" alt="Screenshot 2025-03-03 at 12 40 06 PM"
src="https://github.com/user-attachments/assets/3dd04c9a-3d9f-4823-90f8-b538f3d420f9"
/>

All the upload related previews (excluding preview sizes and upload
editing options) should be affected by the `displayPreview` option.

### How?
Checks for `collection.displayPreview` and `field.displayPreview` in all
places where previews are displayed.

Closes #11404
This commit is contained in:
Jessica Chowdhury
2025-03-07 12:49:20 +00:00
committed by GitHub
parent 6699844d7b
commit 6f90d62fc2
9 changed files with 83 additions and 37 deletions

View File

@@ -38,17 +38,21 @@ export const StaticFileDetails: React.FC<StaticFileDetailsProps> = (props) => {
const { filename, filesize, height, mimeType, thumbnailURL, url, width } = doc const { filename, filesize, height, mimeType, thumbnailURL, url, width } = doc
const previewAllowed = uploadConfig.displayPreview ?? true
return ( return (
<div className={baseClass}> <div className={baseClass}>
<header> <header>
<Thumbnail {previewAllowed && (
// size="small" <Thumbnail
className={`${baseClass}__thumbnail`} // size="small"
doc={doc} className={`${baseClass}__thumbnail`}
fileSrc={thumbnailURL || url} doc={doc}
imageCacheTag={imageCacheTag} fileSrc={thumbnailURL || url}
uploadConfig={uploadConfig} imageCacheTag={imageCacheTag}
/> uploadConfig={uploadConfig}
/>
)}
<div className={`${baseClass}__main-detail`}> <div className={`${baseClass}__main-detail`}>
<FileMeta <FileMeta
filename={filename as string} filename={filename as string}

View File

@@ -21,22 +21,30 @@ export interface FileCellProps
export const FileCell: React.FC<FileCellProps> = ({ export const FileCell: React.FC<FileCellProps> = ({
cellData: filename, cellData: filename,
collectionConfig, collectionConfig,
field,
rowData, rowData,
}) => { }) => {
return ( const fieldPreviewAllowed = 'displayPreview' in field ? field.displayPreview : undefined
<div className={baseClass}> const previewAllowed = fieldPreviewAllowed ?? collectionConfig.upload?.displayPreview ?? true
<Thumbnail
className={`${baseClass}__thumbnail`} if (previewAllowed) {
collectionSlug={collectionConfig?.slug} return (
doc={{ <div className={baseClass}>
...rowData, <Thumbnail
filename, className={`${baseClass}__thumbnail`}
}} collectionSlug={collectionConfig?.slug}
fileSrc={rowData?.thumbnailURL || rowData?.url} doc={{
size="small" ...rowData,
uploadConfig={collectionConfig?.upload} filename,
/> }}
<span className={`${baseClass}__filename`}>{String(filename)}</span> fileSrc={rowData?.thumbnailURL || rowData?.url}
</div> size="small"
) uploadConfig={collectionConfig?.upload}
/>
<span className={`${baseClass}__filename`}>{String(filename)}</span>
</div>
)
} else {
return <>{String(filename)}</>
}
} }

View File

@@ -110,9 +110,9 @@ export const RelationshipCell: React.FC<RelationshipCellProps> = ({
let fileField = null let fileField = null
if (field.type === 'upload') { if (field.type === 'upload') {
const relatedCollectionPreview = !!relatedCollection.upload.displayPreview const fieldPreviewAllowed = 'displayPreview' in field ? field.displayPreview : undefined
const previewAllowed = const previewAllowed =
field.displayPreview || (relatedCollectionPreview && field.displayPreview !== false) fieldPreviewAllowed ?? relatedCollection.upload?.displayPreview ?? true
if (previewAllowed && document) { if (previewAllowed && document) {
fileField = ( fileField = (

View File

@@ -17,6 +17,7 @@ import './index.scss'
type Props = { type Props = {
readonly className?: string readonly className?: string
readonly displayPreview?: boolean
readonly fileDocs: { readonly fileDocs: {
relationTo: string relationTo: string
value: JsonObject value: JsonObject
@@ -30,8 +31,17 @@ type Props = {
} }
export function UploadComponentHasMany(props: Props) { export function UploadComponentHasMany(props: Props) {
const { className, fileDocs, isSortable, onRemove, onReorder, readonly, reloadDoc, serverURL } = const {
props className,
displayPreview,
fileDocs,
isSortable,
onRemove,
onReorder,
readonly,
reloadDoc,
serverURL,
} = props
const moveRow = React.useCallback( const moveRow = React.useCallback(
(moveFromIndex: number, moveToIndex: number) => { (moveFromIndex: number, moveToIndex: number) => {
@@ -120,6 +130,7 @@ export function UploadComponentHasMany(props: Props) {
alt={(value?.alt || value?.filename) as string} alt={(value?.alt || value?.filename) as string}
byteSize={value.filesize as number} byteSize={value.filesize as number}
collectionSlug={relationTo} collectionSlug={relationTo}
displayPreview={displayPreview}
filename={value.filename as string} filename={value.filename as string}
id={id} id={id}
mimeType={value?.mimeType as string} mimeType={value?.mimeType as string}

View File

@@ -14,6 +14,7 @@ const baseClass = 'upload upload--has-one'
type Props = { type Props = {
readonly className?: string readonly className?: string
readonly displayPreview?: boolean
readonly fileDoc: { readonly fileDoc: {
relationTo: string relationTo: string
value: JsonObject value: JsonObject
@@ -25,7 +26,7 @@ type Props = {
} }
export function UploadComponentHasOne(props: Props) { export function UploadComponentHasOne(props: Props) {
const { className, fileDoc, onRemove, readonly, reloadDoc, serverURL } = props const { className, displayPreview, fileDoc, onRemove, readonly, reloadDoc, serverURL } = props
const { relationTo, value } = fileDoc const { relationTo, value } = fileDoc
const id = String(value?.id) const id = String(value?.id)
@@ -56,6 +57,7 @@ export function UploadComponentHasOne(props: Props) {
alt={(value?.alt || value?.filename) as string} alt={(value?.alt || value?.filename) as string}
byteSize={value.filesize as number} byteSize={value.filesize as number}
collectionSlug={relationTo} collectionSlug={relationTo}
displayPreview={displayPreview}
filename={value.filename as string} filename={value.filename as string}
id={id} id={id}
mimeType={value?.mimeType as string} mimeType={value?.mimeType as string}

View File

@@ -55,6 +55,7 @@ export type UploadInputProps = {
readonly customUploadActions?: React.ReactNode[] readonly customUploadActions?: React.ReactNode[]
readonly Description?: React.ReactNode readonly Description?: React.ReactNode
readonly description?: StaticDescription readonly description?: StaticDescription
readonly displayPreview?: boolean
readonly Error?: React.ReactNode readonly Error?: React.ReactNode
readonly filterOptions?: FilterOptionsResult readonly filterOptions?: FilterOptionsResult
readonly hasMany?: boolean readonly hasMany?: boolean
@@ -85,6 +86,7 @@ export function UploadInput(props: UploadInputProps) {
className, className,
Description, Description,
description, description,
displayPreview,
Error, Error,
filterOptions: filterOptionsFromProps, filterOptions: filterOptionsFromProps,
hasMany, hasMany,
@@ -495,6 +497,7 @@ export function UploadInput(props: UploadInputProps) {
<> <>
{populatedDocs && populatedDocs?.length > 0 ? ( {populatedDocs && populatedDocs?.length > 0 ? (
<UploadComponentHasMany <UploadComponentHasMany
displayPreview={displayPreview}
fileDocs={populatedDocs} fileDocs={populatedDocs}
isSortable={isSortable && !readOnly} isSortable={isSortable && !readOnly}
onRemove={onRemove} onRemove={onRemove}
@@ -516,6 +519,7 @@ export function UploadInput(props: UploadInputProps) {
<> <>
{populatedDocs && populatedDocs?.length > 0 && populatedDocs[0].value ? ( {populatedDocs && populatedDocs?.length > 0 && populatedDocs[0].value ? (
<UploadComponentHasOne <UploadComponentHasOne
displayPreview={displayPreview}
fileDoc={populatedDocs[0]} fileDoc={populatedDocs[0]}
onRemove={onRemove} onRemove={onRemove}
readonly={readOnly} readonly={readOnly}

View File

@@ -10,6 +10,7 @@ import type { ReloadDoc } from '../types.js'
import { Button } from '../../../elements/Button/index.js' import { Button } from '../../../elements/Button/index.js'
import { useDocumentDrawer } from '../../../elements/DocumentDrawer/index.js' import { useDocumentDrawer } from '../../../elements/DocumentDrawer/index.js'
import { ThumbnailComponent } from '../../../elements/Thumbnail/index.js' import { ThumbnailComponent } from '../../../elements/Thumbnail/index.js'
import { useConfig } from '../../../providers/Config/index.js'
import './index.scss' import './index.scss'
const baseClass = 'upload-relationship-details' const baseClass = 'upload-relationship-details'
@@ -21,6 +22,7 @@ type Props = {
readonly byteSize: number readonly byteSize: number
readonly className?: string readonly className?: string
readonly collectionSlug: string readonly collectionSlug: string
readonly displayPreview?: boolean
readonly filename: string readonly filename: string
readonly id?: number | string readonly id?: number | string
readonly mimeType: string readonly mimeType: string
@@ -41,6 +43,7 @@ export function RelationshipContent(props: Props) {
byteSize, byteSize,
className, className,
collectionSlug, collectionSlug,
displayPreview,
filename, filename,
mimeType, mimeType,
onRemove, onRemove,
@@ -52,6 +55,12 @@ export function RelationshipContent(props: Props) {
y, y,
} = props } = props
const { config } = useConfig()
const collectionConfig =
'collections' in config
? config.collections.find((collection) => collection.slug === collectionSlug)
: undefined
const [DocumentDrawer, _, { openDrawer }] = useDocumentDrawer({ const [DocumentDrawer, _, { openDrawer }] = useDocumentDrawer({
id: src ? id : undefined, id: src ? id : undefined,
collectionSlug, collectionSlug,
@@ -80,17 +89,20 @@ export function RelationshipContent(props: Props) {
} }
const metaText = withMeta ? generateMetaText(mimeType, byteSize) : '' const metaText = withMeta ? generateMetaText(mimeType, byteSize) : ''
const previewAllowed = displayPreview ?? collectionConfig.upload?.displayPreview ?? true
return ( return (
<div className={[baseClass, className].filter(Boolean).join(' ')}> <div className={[baseClass, className].filter(Boolean).join(' ')}>
<div className={`${baseClass}__imageAndDetails`}> <div className={`${baseClass}__imageAndDetails`}>
<ThumbnailComponent {previewAllowed && (
alt={alt} <ThumbnailComponent
className={`${baseClass}__thumbnail`} alt={alt}
filename={filename} className={`${baseClass}__thumbnail`}
fileSrc={thumbnailSrc} filename={filename}
size="small" fileSrc={thumbnailSrc}
/> size="small"
/>
)}
<div className={`${baseClass}__details`}> <div className={`${baseClass}__details`}>
<p className={`${baseClass}__filename`}> <p className={`${baseClass}__filename`}>
{src ? ( {src ? (

View File

@@ -35,6 +35,8 @@ export function UploadComponent(props: UploadFieldClientProps) {
const { config } = useConfig() const { config } = useConfig()
const displayPreview = field.displayPreview
const memoizedValidate = React.useCallback( const memoizedValidate = React.useCallback(
(value, options) => { (value, options) => {
if (typeof validate === 'function') { if (typeof validate === 'function') {
@@ -66,6 +68,7 @@ export function UploadComponent(props: UploadFieldClientProps) {
className={className} className={className}
Description={Description} Description={Description}
description={description} description={description}
displayPreview={displayPreview}
Error={Error} Error={Error}
filterOptions={filterOptions} filterOptions={filterOptions}
hasMany={hasMany} hasMany={hasMany}

View File

@@ -658,7 +658,9 @@ export default buildConfigWithDefaults({
type: 'text', type: 'text',
}, },
], ],
upload: true, upload: {
displayPreview: false,
},
}, },
{ {
slug: relationPreviewSlug, slug: relationPreviewSlug,