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:
committed by
GitHub
parent
6699844d7b
commit
6f90d62fc2
@@ -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}
|
||||||
|
|||||||
@@ -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)}</>
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 = (
|
||||||
|
|||||||
@@ -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}
|
||||||
|
|||||||
@@ -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}
|
||||||
|
|||||||
@@ -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}
|
||||||
|
|||||||
@@ -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 ? (
|
||||||
|
|||||||
@@ -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}
|
||||||
|
|||||||
@@ -658,7 +658,9 @@ export default buildConfigWithDefaults({
|
|||||||
type: 'text',
|
type: 'text',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
upload: true,
|
upload: {
|
||||||
|
displayPreview: false,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
slug: relationPreviewSlug,
|
slug: relationPreviewSlug,
|
||||||
|
|||||||
Reference in New Issue
Block a user