fix(ui): filters out upload specific fields for bulk editing (#10726)

### What

This PR adds a filtering mechanism to exclude certain reserved fields
from being displayed in the `Edit Many` drawer for bulk uploads. This
ensures that only relevant fields are available for bulk editing.

### Why

Fields like `filename`, `mimeType`, and `filesize` are not intended to
be edited in bulk. Filtering these fields streamlines the interface and
focuses on fields that are meaningful for bulk operations.

### How

- Introduced a `filterOutUploadFields` utility to exclude reserved
fields from the field selection in bulk uploads.
- Applied this filter to the `Edit Many` drawer, ensuring a more
relevant and user-friendly experience.
- Reserved fields include properties like `file`, `mimeType`, `url`,
`width`, `height`, and others that are not applicable for bulk editing.
This commit is contained in:
Patrik
2025-01-22 16:44:17 -05:00
committed by GitHub
parent 0c5321e6f8
commit f181f97d4e
3 changed files with 28 additions and 3 deletions

View File

@@ -15,6 +15,7 @@ import { RenderFields } from '../../../forms/RenderFields/index.js'
import { XIcon } from '../../../icons/X/index.js' import { XIcon } from '../../../icons/X/index.js'
import { useAuth } from '../../../providers/Auth/index.js' import { useAuth } from '../../../providers/Auth/index.js'
import { useTranslation } from '../../../providers/Translation/index.js' import { useTranslation } from '../../../providers/Translation/index.js'
import { filterOutUploadFields } from '../../../utilities/filterOutUploadFields.js'
import { FieldSelect } from '../../FieldSelect/index.js' import { FieldSelect } from '../../FieldSelect/index.js'
import { useFormsManager } from '../FormsManager/index.js' import { useFormsManager } from '../FormsManager/index.js'
import { baseClass, type EditManyBulkUploadsProps } from './index.js' import { baseClass, type EditManyBulkUploadsProps } from './index.js'
@@ -36,6 +37,7 @@ export const EditManyBulkUploadsDrawerContent: React.FC<
const [selectedFields, setSelectedFields] = useState<FieldWithPathClient[]>([]) const [selectedFields, setSelectedFields] = useState<FieldWithPathClient[]>([])
const collectionPermissions = permissions?.collections?.[slug] const collectionPermissions = permissions?.collections?.[slug]
const filteredFields = filterOutUploadFields(fields)
const handleSubmit: FormProps['onSubmit'] = useCallback( const handleSubmit: FormProps['onSubmit'] = useCallback(
(formState) => { (formState) => {
@@ -72,7 +74,7 @@ export const EditManyBulkUploadsDrawerContent: React.FC<
</button> </button>
</div> </div>
<Form className={`${baseClass}__form`} initialState={{}} onSubmit={handleSubmit}> <Form className={`${baseClass}__form`} initialState={{}} onSubmit={handleSubmit}>
<FieldSelect fields={fields} setSelected={setSelectedFields} /> <FieldSelect fields={filteredFields} setSelected={setSelectedFields} />
{selectedFields.length === 0 ? null : ( {selectedFields.length === 0 ? null : (
<RenderFields <RenderFields
fields={selectedFields} fields={selectedFields}

View File

@@ -24,11 +24,12 @@ import { SelectAllStatus, useSelection } from '../../providers/Selection/index.j
import { useServerFunctions } from '../../providers/ServerFunctions/index.js' import { useServerFunctions } from '../../providers/ServerFunctions/index.js'
import { useTranslation } from '../../providers/Translation/index.js' import { useTranslation } from '../../providers/Translation/index.js'
import { abortAndIgnore, handleAbortRef } from '../../utilities/abortAndIgnore.js' import { abortAndIgnore, handleAbortRef } from '../../utilities/abortAndIgnore.js'
import { filterOutUploadFields } from '../../utilities/filterOutUploadFields.js'
import { mergeListSearchAndWhere } from '../../utilities/mergeListSearchAndWhere.js' import { mergeListSearchAndWhere } from '../../utilities/mergeListSearchAndWhere.js'
import { parseSearchParams } from '../../utilities/parseSearchParams.js' import { parseSearchParams } from '../../utilities/parseSearchParams.js'
import './index.scss'
import { FieldSelect } from '../FieldSelect/index.js' import { FieldSelect } from '../FieldSelect/index.js'
import { baseClass, type EditManyProps } from './index.js' import { baseClass, type EditManyProps } from './index.js'
import './index.scss'
const sanitizeUnselectedFields = (formState: FormState, selected: FieldWithPathClient[]) => { const sanitizeUnselectedFields = (formState: FormState, selected: FieldWithPathClient[]) => {
const filteredData = selected.reduce((acc, field) => { const filteredData = selected.reduce((acc, field) => {
@@ -169,6 +170,8 @@ export const EditManyDrawerContent: React.FC<
const collectionPermissions = permissions?.collections?.[slug] const collectionPermissions = permissions?.collections?.[slug]
const searchParams = useSearchParams() const searchParams = useSearchParams()
const filteredFields = filterOutUploadFields(fields)
React.useEffect(() => { React.useEffect(() => {
const controller = new AbortController() const controller = new AbortController()
@@ -284,7 +287,7 @@ export const EditManyDrawerContent: React.FC<
onChange={[onChange]} onChange={[onChange]}
onSuccess={onSuccess} onSuccess={onSuccess}
> >
<FieldSelect fields={fields} setSelected={setSelected} /> <FieldSelect fields={filteredFields} setSelected={setSelected} />
{selected.length === 0 ? null : ( {selected.length === 0 ? null : (
<RenderFields <RenderFields
fields={selected} fields={selected}

View File

@@ -0,0 +1,20 @@
import type { FieldWithPathClient } from 'payload'
export const filterOutUploadFields = (fields: FieldWithPathClient[]): FieldWithPathClient[] => {
// List of reserved upload field names
const baseUploadFieldNames = [
'file',
'mimeType',
'thumbnailURL',
'width',
'height',
'filesize',
'filename',
'url',
'focalX',
'focalY',
'sizes',
]
return fields.filter((field) => !baseUploadFieldNames.includes('name' in field && field.name))
}