From 9612372bc93265c7ee7c23572ca65ff811e4acd5 Mon Sep 17 00:00:00 2001 From: Patrik Kozak Date: Thu, 3 Apr 2025 13:28:50 -0400 Subject: [PATCH 1/4] fix: bulk upload edits progress --- packages/ui/src/elements/Upload/index.tsx | 32 +++++--- .../ui/src/providers/DocumentInfo/index.tsx | 8 +- .../ui/src/providers/UploadEdits/index.tsx | 73 +++++++++++++++---- packages/ui/src/views/Edit/index.tsx | 1 + 4 files changed, 87 insertions(+), 27 deletions(-) diff --git a/packages/ui/src/elements/Upload/index.tsx b/packages/ui/src/elements/Upload/index.tsx index 9316ff3ba4f..564921a933e 100644 --- a/packages/ui/src/elements/Upload/index.tsx +++ b/packages/ui/src/elements/Upload/index.tsx @@ -14,12 +14,13 @@ import { useDocumentInfo } from '../../providers/DocumentInfo/index.js' import { EditDepthProvider } from '../../providers/EditDepth/index.js' import { useTranslation } from '../../providers/Translation/index.js' import { useUploadEdits } from '../../providers/UploadEdits/index.js' +import { useFormsManager } from '../BulkUpload/FormsManager/index.js' import { Button } from '../Button/index.js' import { Drawer, DrawerToggler } from '../Drawer/index.js' import { Dropzone } from '../Dropzone/index.js' import { EditUpload } from '../EditUpload/index.js' -import { FileDetails } from '../FileDetails/index.js' import './index.scss' +import { FileDetails } from '../FileDetails/index.js' import { PreviewSizes } from '../PreviewSizes/index.js' import { Thumbnail } from '../Thumbnail/index.js' @@ -102,7 +103,8 @@ export const Upload: React.FC = (props) => { const { t } = useTranslation() const { setModified } = useForm() - const { resetUploadEdits, updateUploadEdits, uploadEdits } = useUploadEdits() + const { activeIndex } = useFormsManager?.() || {} + const { getUploadEdits, resetUploadEdits, updateUploadEdits } = useUploadEdits() const { id, docPermissions, savedDocumentData, setUploadStatus } = useDocumentInfo() const isFormSubmitting = useFormProcessing() const { errorMessage, setValue, showError, value } = useField({ @@ -110,6 +112,14 @@ export const Upload: React.FC = (props) => { validate, }) + const isBulkUpload = typeof activeIndex === 'number' + + const currentUploadEdits = getUploadEdits(isBulkUpload ? activeIndex : undefined) + + console.log('Upload edits: ', getUploadEdits(activeIndex)) + + console.log('Saved document data: ', savedDocumentData) + const [fileSrc, setFileSrc] = useState(null) const [removedFile, setRemovedFile] = useState(false) const [filename, setFilename] = useState(value?.name || '') @@ -172,16 +182,16 @@ export const Upload: React.FC = (props) => { handleFileChange(null) setFileSrc('') setFileUrl('') - resetUploadEdits() + resetUploadEdits(isBulkUpload ? activeIndex : undefined) setShowUrlInput(false) - }, [handleFileChange, resetUploadEdits]) + }, [activeIndex, isBulkUpload, handleFileChange, resetUploadEdits]) const onEditsSave = useCallback( (args: UploadEdits) => { setModified(true) - updateUploadEdits(args) + updateUploadEdits(args, isBulkUpload ? activeIndex : undefined) }, - [setModified, updateUploadEdits], + [activeIndex, isBulkUpload, setModified, updateUploadEdits], ) const handleUrlSubmit = async () => { @@ -274,6 +284,10 @@ export const Upload: React.FC = (props) => { return null } + console.log('Current upload edits: ', currentUploadEdits) + + console.log('Saved document data: ', savedDocumentData) + return (
@@ -423,10 +437,10 @@ export const Upload: React.FC = (props) => { fileName={value?.name || savedDocumentData?.filename} fileSrc={savedDocumentData?.url || fileSrc} imageCacheTag={imageCacheTag} - initialCrop={uploadEdits?.crop ?? undefined} + initialCrop={currentUploadEdits?.crop ?? undefined} initialFocalPoint={{ - x: uploadEdits?.focalPoint?.x || savedDocumentData?.focalX || 50, - y: uploadEdits?.focalPoint?.y || savedDocumentData?.focalY || 50, + x: currentUploadEdits?.focalPoint?.x || savedDocumentData?.focalX || 50, + y: currentUploadEdits?.focalPoint?.y || savedDocumentData?.focalY || 50, }} onSave={onEditsSave} showCrop={showCrop} diff --git a/packages/ui/src/providers/DocumentInfo/index.tsx b/packages/ui/src/providers/DocumentInfo/index.tsx index 7ce902301b9..47e7c4c77d2 100644 --- a/packages/ui/src/providers/DocumentInfo/index.tsx +++ b/packages/ui/src/providers/DocumentInfo/index.tsx @@ -73,7 +73,7 @@ const DocumentInfo: React.FC< const { i18n } = useTranslation() - const { uploadEdits } = useUploadEdits() + const { getUploadEdits } = useUploadEdits() const [documentTitle, setDocumentTitle] = useState(() => formatDocTitle({ @@ -300,19 +300,21 @@ const DocumentInfo: React.FC< } }, []) + console.log('Get upload edits: ', getUploadEdits()) + const action: string = React.useMemo(() => { const docURL = `${baseURL}${pluralType === 'globals' ? `/globals` : ''}/${slug}${id ? `/${id}` : ''}` const params = { depth: 0, 'fallback-locale': 'null', locale, - uploadEdits: uploadEdits || undefined, + uploadEdits: getUploadEdits() || undefined, // Single upload = no index } return `${docURL}${qs.stringify(params, { addQueryPrefix: true, })}` - }, [baseURL, locale, pluralType, id, slug, uploadEdits]) + }, [baseURL, locale, pluralType, id, slug, getUploadEdits]) const value: DocumentInfoContext = { ...props, diff --git a/packages/ui/src/providers/UploadEdits/index.tsx b/packages/ui/src/providers/UploadEdits/index.tsx index 3f45a0dc373..4559f0092ee 100644 --- a/packages/ui/src/providers/UploadEdits/index.tsx +++ b/packages/ui/src/providers/UploadEdits/index.tsx @@ -3,33 +3,76 @@ import type { UploadEdits } from 'payload' import React from 'react' +export type UploadEditsState = { + byIndex: Record + global?: UploadEdits +} + export type UploadEditsContext = { - resetUploadEdits: () => void - updateUploadEdits: (edits: UploadEdits) => void - uploadEdits: UploadEdits + getUploadEdits: (index?: number) => UploadEdits + resetUploadEdits: (index?: number) => void + updateUploadEdits: (edits: UploadEdits, index?: number) => void } const Context = React.createContext({ - resetUploadEdits: undefined, - updateUploadEdits: undefined, - uploadEdits: undefined, + getUploadEdits: () => ({}), + resetUploadEdits: () => {}, + updateUploadEdits: () => {}, }) export const UploadEditsProvider = ({ children }) => { - const [uploadEdits, setUploadEdits] = React.useState(undefined) + const [edits, setEdits] = React.useState({ + byIndex: {}, + global: {}, + }) + + const resetUploadEdits = (index?: number) => { + setEdits((prev) => { + if (typeof index === 'number') { + const { [index]: _, ...rest } = prev.byIndex + return { + ...prev, + byIndex: rest, + } + } + return { + ...prev, + global: {}, + } + }) + } - const resetUploadEdits = () => { - setUploadEdits({}) + const getUploadEdits = (index?: number): UploadEdits => { + return typeof index === 'number' ? edits.byIndex[index] || {} : edits.global || {} } - const updateUploadEdits = (edits: UploadEdits) => { - setUploadEdits((prevEdits) => ({ - ...(prevEdits || {}), - ...(edits || {}), - })) + const updateUploadEdits = (newEdits: UploadEdits, index?: number) => { + setEdits((prev) => { + if (typeof index === 'number') { + return { + ...prev, + byIndex: { + ...prev.byIndex, + [index]: { + ...(prev.byIndex[index] || {}), + ...newEdits, + }, + }, + } + } + return { + ...prev, + global: { + ...(prev.global || {}), + ...newEdits, + }, + } + }) } - return {children} + return ( + {children} + ) } export const useUploadEdits = (): UploadEditsContext => React.use(Context) diff --git a/packages/ui/src/views/Edit/index.tsx b/packages/ui/src/views/Edit/index.tsx index 78a054cb396..3abe9f8cbfd 100644 --- a/packages/ui/src/views/Edit/index.tsx +++ b/packages/ui/src/views/Edit/index.tsx @@ -325,6 +325,7 @@ export function DefaultEditView({ isLockingEnabled, setDocumentIsLocked, startRouteTransition, + redirectAfterCreate, ], ) From d260839151440d335241d333a8294ee9a8c7922b Mon Sep 17 00:00:00 2001 From: Patrik Kozak Date: Fri, 4 Apr 2025 15:01:25 -0400 Subject: [PATCH 2/4] fix: properly save upload edits in bulk uploads --- .../elements/BulkUpload/EditForm/index.tsx | 8 +- .../BulkUpload/FormsManager/index.tsx | 30 ++++++- .../BulkUpload/FormsManager/reducer.ts | 5 +- packages/ui/src/elements/Upload/index.tsx | 28 +++---- .../ui/src/providers/DocumentInfo/index.tsx | 23 ++++-- .../ui/src/providers/UploadEdits/index.tsx | 79 ++++++------------- 6 files changed, 87 insertions(+), 86 deletions(-) diff --git a/packages/ui/src/elements/BulkUpload/EditForm/index.tsx b/packages/ui/src/elements/BulkUpload/EditForm/index.tsx index 7c186d498bf..4e9d23475ba 100644 --- a/packages/ui/src/elements/BulkUpload/EditForm/index.tsx +++ b/packages/ui/src/elements/BulkUpload/EditForm/index.tsx @@ -183,11 +183,13 @@ export function EditForm({ submitted }: EditFormProps) { function GetFieldProxy() { const { getFields } = useForm() - const { getFormDataRef } = useFormsManager() + const { getFormDataRef, getUploadEditsRef } = useFormsManager() + const { getUploadEdits } = useUploadEdits() - React.useEffect(() => { + useEffect(() => { getFormDataRef.current = getFields - }, [getFields, getFormDataRef]) + getUploadEditsRef.current = getUploadEdits + }, [getFields, getFormDataRef, getUploadEdits, getUploadEditsRef]) return null } diff --git a/packages/ui/src/elements/BulkUpload/FormsManager/index.tsx b/packages/ui/src/elements/BulkUpload/FormsManager/index.tsx index 713e25d98da..330ab8a620f 100644 --- a/packages/ui/src/elements/BulkUpload/FormsManager/index.tsx +++ b/packages/ui/src/elements/BulkUpload/FormsManager/index.tsx @@ -1,6 +1,12 @@ 'use client' -import type { Data, DocumentSlots, FormState, SanitizedDocumentPermissions } from 'payload' +import type { + Data, + DocumentSlots, + FormState, + SanitizedDocumentPermissions, + UploadEdits, +} from 'payload' import { useModal } from '@faceless-ui/modal' import { isImage } from 'payload/shared' @@ -36,9 +42,11 @@ type FormsManagerContext = { readonly documentSlots: DocumentSlots readonly forms: State['forms'] getFormDataRef: React.RefObject<() => Data> + getUploadEditsRef: React.RefObject<() => UploadEdits> readonly hasPublishPermission: boolean readonly hasSavePermission: boolean readonly hasSubmitted: boolean + readonly isInBulkUploadContext: boolean readonly isInitializing: boolean readonly removeFile: (index: number) => void readonly saveAllDocs: ({ overrides }?: { overrides?: Record }) => Promise @@ -63,9 +71,11 @@ const Context = React.createContext({ documentSlots: {}, forms: [], getFormDataRef: { current: () => ({}) }, + getUploadEditsRef: { current: () => ({}) }, hasPublishPermission: false, hasSavePermission: false, hasSubmitted: false, + isInBulkUploadContext: false, isInitializing: false, removeFile: () => {}, saveAllDocs: () => Promise.resolve(), @@ -152,6 +162,7 @@ export function FormsManagerProvider({ children }: FormsManagerProps) { const hasInitializedWithFiles = React.useRef(false) const initialStateRef = React.useRef(null) const getFormDataRef = React.useRef<() => Data>(() => ({})) + const getUploadEditsRef = React.useRef<() => UploadEdits>(() => ({})) const actionURL = `${api}/${collectionSlug}` @@ -233,6 +244,7 @@ export function FormsManagerProvider({ children }: FormsManagerProps) { const setActiveIndex: FormsManagerContext['setActiveIndex'] = React.useCallback( (index: number) => { const currentFormsData = getFormDataRef.current() + const currentUploadEdits = getUploadEditsRef.current() dispatch({ type: 'REPLACE', state: { @@ -242,6 +254,7 @@ export function FormsManagerProvider({ children }: FormsManagerProps) { return { errorCount: form.errorCount, formState: currentFormsData, + uploadEdits: currentUploadEdits, } } return form @@ -291,10 +304,12 @@ export function FormsManagerProvider({ children }: FormsManagerProps) { const saveAllDocs: FormsManagerContext['saveAllDocs'] = React.useCallback( async ({ overrides } = {}) => { const currentFormsData = getFormDataRef.current() + const currentUploadEdits = getUploadEditsRef.current() const currentForms = [...forms] currentForms[activeIndex] = { errorCount: currentForms[activeIndex].errorCount, formState: currentFormsData, + uploadEdits: currentUploadEdits, } const newDocs = [] @@ -306,7 +321,15 @@ export function FormsManagerProvider({ children }: FormsManagerProps) { setLoadingText(t('general:uploadingBulk', { current: i + 1, total: currentForms.length })) - const req = await fetch(actionURL, { + const params = { + uploadEdits: form?.uploadEdits || undefined, + } + + const actionURLWithParams = `${actionURL}${qs.stringify(params, { + addQueryPrefix: true, + })}` + + const req = await fetch(actionURLWithParams, { body: await createFormData( form.formState, overrides, @@ -443,6 +466,7 @@ export function FormsManagerProvider({ children }: FormsManagerProps) { errorCount: forms[i].errorCount, formState: forms[i].formState, index: i, + uploadEdits: forms[i].uploadEdits, }) } }) @@ -524,9 +548,11 @@ export function FormsManagerProvider({ children }: FormsManagerProps) { documentSlots, forms, getFormDataRef, + getUploadEditsRef, hasPublishPermission, hasSavePermission, hasSubmitted, + isInBulkUploadContext: true, isInitializing, removeFile, saveAllDocs, diff --git a/packages/ui/src/elements/BulkUpload/FormsManager/reducer.ts b/packages/ui/src/elements/BulkUpload/FormsManager/reducer.ts index 8d2662709f1..3a2299d8900 100644 --- a/packages/ui/src/elements/BulkUpload/FormsManager/reducer.ts +++ b/packages/ui/src/elements/BulkUpload/FormsManager/reducer.ts @@ -1,10 +1,11 @@ -import type { FormState } from 'payload' +import type { FormState, UploadEdits } from 'payload' export type State = { activeIndex: number forms: { errorCount: number formState: FormState + uploadEdits?: UploadEdits }[] totalErrorCount: number } @@ -21,6 +22,7 @@ type Action = index: number type: 'UPDATE_FORM' updatedFields?: Record + uploadEdits?: UploadEdits } | { files: FileList @@ -55,6 +57,7 @@ export function formsManagementReducer(state: State, action: Action): State { value: action.files[i], }, }, + uploadEdits: {}, } } diff --git a/packages/ui/src/elements/Upload/index.tsx b/packages/ui/src/elements/Upload/index.tsx index 564921a933e..d90d06c0b92 100644 --- a/packages/ui/src/elements/Upload/index.tsx +++ b/packages/ui/src/elements/Upload/index.tsx @@ -18,8 +18,8 @@ import { useFormsManager } from '../BulkUpload/FormsManager/index.js' import { Button } from '../Button/index.js' import { Drawer, DrawerToggler } from '../Drawer/index.js' import { Dropzone } from '../Dropzone/index.js' -import { EditUpload } from '../EditUpload/index.js' import './index.scss' +import { EditUpload } from '../EditUpload/index.js' import { FileDetails } from '../FileDetails/index.js' import { PreviewSizes } from '../PreviewSizes/index.js' import { Thumbnail } from '../Thumbnail/index.js' @@ -103,8 +103,8 @@ export const Upload: React.FC = (props) => { const { t } = useTranslation() const { setModified } = useForm() - const { activeIndex } = useFormsManager?.() || {} - const { getUploadEdits, resetUploadEdits, updateUploadEdits } = useUploadEdits() + const { resetUploadEdits, updateUploadEdits, uploadEdits } = useUploadEdits() + const { activeIndex, forms, getUploadEditsRef, isInBulkUploadContext } = useFormsManager() const { id, docPermissions, savedDocumentData, setUploadStatus } = useDocumentInfo() const isFormSubmitting = useFormProcessing() const { errorMessage, setValue, showError, value } = useField({ @@ -112,13 +112,9 @@ export const Upload: React.FC = (props) => { validate, }) - const isBulkUpload = typeof activeIndex === 'number' - - const currentUploadEdits = getUploadEdits(isBulkUpload ? activeIndex : undefined) - - console.log('Upload edits: ', getUploadEdits(activeIndex)) - - console.log('Saved document data: ', savedDocumentData) + const currentUploadEdits = isInBulkUploadContext + ? getUploadEditsRef.current?.() || forms[activeIndex]?.uploadEdits + : uploadEdits const [fileSrc, setFileSrc] = useState(null) const [removedFile, setRemovedFile] = useState(false) @@ -182,16 +178,16 @@ export const Upload: React.FC = (props) => { handleFileChange(null) setFileSrc('') setFileUrl('') - resetUploadEdits(isBulkUpload ? activeIndex : undefined) + resetUploadEdits() setShowUrlInput(false) - }, [activeIndex, isBulkUpload, handleFileChange, resetUploadEdits]) + }, [handleFileChange, resetUploadEdits]) const onEditsSave = useCallback( (args: UploadEdits) => { setModified(true) - updateUploadEdits(args, isBulkUpload ? activeIndex : undefined) + updateUploadEdits(args) }, - [activeIndex, isBulkUpload, setModified, updateUploadEdits], + [setModified, updateUploadEdits], ) const handleUrlSubmit = async () => { @@ -284,10 +280,6 @@ export const Upload: React.FC = (props) => { return null } - console.log('Current upload edits: ', currentUploadEdits) - - console.log('Saved document data: ', savedDocumentData) - return (
diff --git a/packages/ui/src/providers/DocumentInfo/index.tsx b/packages/ui/src/providers/DocumentInfo/index.tsx index 47e7c4c77d2..a989c221194 100644 --- a/packages/ui/src/providers/DocumentInfo/index.tsx +++ b/packages/ui/src/providers/DocumentInfo/index.tsx @@ -1,11 +1,17 @@ 'use client' -import type { ClientUser, DocumentPreferences, SanitizedDocumentPermissions } from 'payload' +import type { + ClientUser, + DocumentPreferences, + SanitizedDocumentPermissions, + UploadEdits, +} from 'payload' import * as qs from 'qs-esm' import React, { createContext, use, useCallback, useEffect, useMemo, useRef, useState } from 'react' import type { DocumentInfoContext, DocumentInfoProps } from './types.js' +import { useFormsManager } from '../../elements/BulkUpload/FormsManager/index.js' import { useAuth } from '../../providers/Auth/index.js' import { requests } from '../../utilities/api.js' import { formatDocTitle } from '../../utilities/formatDocTitle/index.js' @@ -73,7 +79,7 @@ const DocumentInfo: React.FC< const { i18n } = useTranslation() - const { getUploadEdits } = useUploadEdits() + const { uploadEdits } = useUploadEdits() const [documentTitle, setDocumentTitle] = useState(() => formatDocTitle({ @@ -300,21 +306,19 @@ const DocumentInfo: React.FC< } }, []) - console.log('Get upload edits: ', getUploadEdits()) - const action: string = React.useMemo(() => { const docURL = `${baseURL}${pluralType === 'globals' ? `/globals` : ''}/${slug}${id ? `/${id}` : ''}` const params = { depth: 0, 'fallback-locale': 'null', locale, - uploadEdits: getUploadEdits() || undefined, // Single upload = no index + uploadEdits: uploadEdits || undefined, } return `${docURL}${qs.stringify(params, { addQueryPrefix: true, })}` - }, [baseURL, locale, pluralType, id, slug, getUploadEdits]) + }, [baseURL, locale, pluralType, id, slug, uploadEdits]) const value: DocumentInfoContext = { ...props, @@ -360,10 +364,15 @@ const DocumentInfo: React.FC< export const DocumentInfoProvider: React.FC< { readonly children: React.ReactNode + initialUploadEdits?: UploadEdits } & DocumentInfoProps > = (props) => { + const { activeIndex, forms } = useFormsManager() + + const initialUploadEdits = forms?.[activeIndex]?.uploadEdits + return ( - + ) diff --git a/packages/ui/src/providers/UploadEdits/index.tsx b/packages/ui/src/providers/UploadEdits/index.tsx index 4559f0092ee..610b83223c2 100644 --- a/packages/ui/src/providers/UploadEdits/index.tsx +++ b/packages/ui/src/providers/UploadEdits/index.tsx @@ -3,75 +3,44 @@ import type { UploadEdits } from 'payload' import React from 'react' -export type UploadEditsState = { - byIndex: Record - global?: UploadEdits +export type UploadEditsProviderProps = { + children: React.ReactNode + initialUploadEdits?: UploadEdits } - export type UploadEditsContext = { - getUploadEdits: (index?: number) => UploadEdits - resetUploadEdits: (index?: number) => void - updateUploadEdits: (edits: UploadEdits, index?: number) => void + getUploadEdits: () => UploadEdits + resetUploadEdits: () => void + updateUploadEdits: (edits: UploadEdits) => void + uploadEdits: UploadEdits } const Context = React.createContext({ - getUploadEdits: () => ({}), - resetUploadEdits: () => {}, - updateUploadEdits: () => {}, + getUploadEdits: () => undefined, + resetUploadEdits: undefined, + updateUploadEdits: undefined, + uploadEdits: undefined, }) -export const UploadEditsProvider = ({ children }) => { - const [edits, setEdits] = React.useState({ - byIndex: {}, - global: {}, - }) +export const UploadEditsProvider = ({ children, initialUploadEdits }: UploadEditsProviderProps) => { + const [uploadEdits, setUploadEdits] = React.useState(initialUploadEdits || {}) - const resetUploadEdits = (index?: number) => { - setEdits((prev) => { - if (typeof index === 'number') { - const { [index]: _, ...rest } = prev.byIndex - return { - ...prev, - byIndex: rest, - } - } - return { - ...prev, - global: {}, - } - }) + const resetUploadEdits = () => { + setUploadEdits({}) } - const getUploadEdits = (index?: number): UploadEdits => { - return typeof index === 'number' ? edits.byIndex[index] || {} : edits.global || {} + const updateUploadEdits = (edits: UploadEdits) => { + setUploadEdits((prevEdits) => ({ + ...(prevEdits || {}), + ...(edits || {}), + })) } - const updateUploadEdits = (newEdits: UploadEdits, index?: number) => { - setEdits((prev) => { - if (typeof index === 'number') { - return { - ...prev, - byIndex: { - ...prev.byIndex, - [index]: { - ...(prev.byIndex[index] || {}), - ...newEdits, - }, - }, - } - } - return { - ...prev, - global: { - ...(prev.global || {}), - ...newEdits, - }, - } - }) - } + const getUploadEdits = () => uploadEdits return ( - {children} + + {children} + ) } From 36612695a7e072463b4167ba742772b1c2ce27c4 Mon Sep 17 00:00:00 2001 From: Patrik Kozak Date: Mon, 7 Apr 2025 13:28:33 -0400 Subject: [PATCH 3/4] fix: removes need for forms manager context for Upload element --- .../BulkUpload/AddingFilesView/index.tsx | 9 ++- .../elements/BulkUpload/EditForm/index.tsx | 22 +++++--- .../src/elements/BulkUpload/EditForm/types.ts | 4 +- .../BulkUpload/FormsManager/index.tsx | 56 +++++++++++++------ .../BulkUpload/FormsManager/reducer.ts | 4 ++ packages/ui/src/elements/Upload/index.tsx | 44 +++++++++++---- .../ui/src/providers/DocumentInfo/index.tsx | 15 +---- 7 files changed, 102 insertions(+), 52 deletions(-) diff --git a/packages/ui/src/elements/BulkUpload/AddingFilesView/index.tsx b/packages/ui/src/elements/BulkUpload/AddingFilesView/index.tsx index db59591822a..20a1952aca4 100644 --- a/packages/ui/src/elements/BulkUpload/AddingFilesView/index.tsx +++ b/packages/ui/src/elements/BulkUpload/AddingFilesView/index.tsx @@ -29,6 +29,8 @@ export function AddingFilesView() { hasPublishPermission, hasSavePermission, hasSubmitted, + resetUploadEdits, + updateUploadEdits, } = useFormsManager() const activeForm = forms[activeIndex] const { getEntityConfig } = useConfig() @@ -67,7 +69,12 @@ export function AddingFilesView() { versionCount={0} > - + ) : null}
diff --git a/packages/ui/src/elements/BulkUpload/EditForm/index.tsx b/packages/ui/src/elements/BulkUpload/EditForm/index.tsx index 4e9d23475ba..f1c4da6c28a 100644 --- a/packages/ui/src/elements/BulkUpload/EditForm/index.tsx +++ b/packages/ui/src/elements/BulkUpload/EditForm/index.tsx @@ -16,11 +16,10 @@ import { useEditDepth } from '../../../providers/EditDepth/index.js' import { OperationProvider } from '../../../providers/Operation/index.js' import { useRouteTransition } from '../../../providers/RouteTransition/index.js' import { useServerFunctions } from '../../../providers/ServerFunctions/index.js' -import { useUploadEdits } from '../../../providers/UploadEdits/index.js' import { abortAndIgnore, handleAbortRef } from '../../../utilities/abortAndIgnore.js' import { useDocumentDrawerContext } from '../../DocumentDrawer/Provider.js' import { DocumentFields } from '../../DocumentFields/index.js' -import { Upload } from '../../Upload/index.js' +import { Upload_v4 } from '../../Upload/index.js' import { useFormsManager } from '../FormsManager/index.js' import { BulkUploadProvider } from '../index.js' import './index.scss' @@ -31,7 +30,12 @@ const baseClass = 'collection-edit' // When rendered within a drawer, props are empty // This is solely to support custom edit views which get server-rendered -export function EditForm({ submitted }: EditFormProps) { +export function EditForm({ + resetUploadEdits, + submitted, + updateUploadEdits, + uploadEdits, +}: EditFormProps) { const { action, collectionSlug: docSlug, @@ -62,7 +66,6 @@ export function EditForm({ submitted }: EditFormProps) { const depth = useEditDepth() const params = useSearchParams() const { reportUpdate } = useDocumentEvents() - const { resetUploadEdits } = useUploadEdits() const { startRouteTransition } = useRouteTransition() const locale = params.get('locale') @@ -161,10 +164,13 @@ export function EditForm({ submitted }: EditFormProps) { BeforeFields={ {CustomUpload || ( - )} @@ -183,13 +189,11 @@ export function EditForm({ submitted }: EditFormProps) { function GetFieldProxy() { const { getFields } = useForm() - const { getFormDataRef, getUploadEditsRef } = useFormsManager() - const { getUploadEdits } = useUploadEdits() + const { getFormDataRef } = useFormsManager() useEffect(() => { getFormDataRef.current = getFields - getUploadEditsRef.current = getUploadEdits - }, [getFields, getFormDataRef, getUploadEdits, getUploadEditsRef]) + }, [getFields, getFormDataRef]) return null } diff --git a/packages/ui/src/elements/BulkUpload/EditForm/types.ts b/packages/ui/src/elements/BulkUpload/EditForm/types.ts index 19083a07103..d975483a955 100644 --- a/packages/ui/src/elements/BulkUpload/EditForm/types.ts +++ b/packages/ui/src/elements/BulkUpload/EditForm/types.ts @@ -1,3 +1,5 @@ +import type { UploadProps_v4 } from '../../Upload/index.js' + export type EditFormProps = { readonly submitted?: boolean -} +} & Pick diff --git a/packages/ui/src/elements/BulkUpload/FormsManager/index.tsx b/packages/ui/src/elements/BulkUpload/FormsManager/index.tsx index 330ab8a620f..7c7364b35d1 100644 --- a/packages/ui/src/elements/BulkUpload/FormsManager/index.tsx +++ b/packages/ui/src/elements/BulkUpload/FormsManager/index.tsx @@ -42,13 +42,13 @@ type FormsManagerContext = { readonly documentSlots: DocumentSlots readonly forms: State['forms'] getFormDataRef: React.RefObject<() => Data> - getUploadEditsRef: React.RefObject<() => UploadEdits> readonly hasPublishPermission: boolean readonly hasSavePermission: boolean readonly hasSubmitted: boolean readonly isInBulkUploadContext: boolean readonly isInitializing: boolean readonly removeFile: (index: number) => void + readonly resetUploadEdits?: () => void readonly saveAllDocs: ({ overrides }?: { overrides?: Record }) => Promise readonly setActiveIndex: (index: number) => void readonly setFormTotalErrorCount: ({ @@ -60,6 +60,7 @@ type FormsManagerContext = { }) => void readonly thumbnailUrls: string[] readonly totalErrorCount?: number + readonly updateUploadEdits: (args: UploadEdits) => void } const Context = React.createContext({ @@ -71,7 +72,6 @@ const Context = React.createContext({ documentSlots: {}, forms: [], getFormDataRef: { current: () => ({}) }, - getUploadEditsRef: { current: () => ({}) }, hasPublishPermission: false, hasSavePermission: false, hasSubmitted: false, @@ -83,6 +83,7 @@ const Context = React.createContext({ setFormTotalErrorCount: () => {}, thumbnailUrls: [], totalErrorCount: 0, + updateUploadEdits: () => {}, }) const initialState: State = { @@ -162,7 +163,6 @@ export function FormsManagerProvider({ children }: FormsManagerProps) { const hasInitializedWithFiles = React.useRef(false) const initialStateRef = React.useRef(null) const getFormDataRef = React.useRef<() => Data>(() => ({})) - const getUploadEditsRef = React.useRef<() => UploadEdits>(() => ({})) const actionURL = `${api}/${collectionSlug}` @@ -244,7 +244,6 @@ export function FormsManagerProvider({ children }: FormsManagerProps) { const setActiveIndex: FormsManagerContext['setActiveIndex'] = React.useCallback( (index: number) => { const currentFormsData = getFormDataRef.current() - const currentUploadEdits = getUploadEditsRef.current() dispatch({ type: 'REPLACE', state: { @@ -254,7 +253,7 @@ export function FormsManagerProvider({ children }: FormsManagerProps) { return { errorCount: form.errorCount, formState: currentFormsData, - uploadEdits: currentUploadEdits, + uploadEdits: form.uploadEdits, } } return form @@ -304,12 +303,11 @@ export function FormsManagerProvider({ children }: FormsManagerProps) { const saveAllDocs: FormsManagerContext['saveAllDocs'] = React.useCallback( async ({ overrides } = {}) => { const currentFormsData = getFormDataRef.current() - const currentUploadEdits = getUploadEditsRef.current() const currentForms = [...forms] currentForms[activeIndex] = { errorCount: currentForms[activeIndex].errorCount, formState: currentFormsData, - uploadEdits: currentUploadEdits, + uploadEdits: currentForms[activeIndex].uploadEdits, } const newDocs = [] @@ -321,13 +319,14 @@ export function FormsManagerProvider({ children }: FormsManagerProps) { setLoadingText(t('general:uploadingBulk', { current: i + 1, total: currentForms.length })) - const params = { - uploadEdits: form?.uploadEdits || undefined, - } - - const actionURLWithParams = `${actionURL}${qs.stringify(params, { - addQueryPrefix: true, - })}` + const actionURLWithParams = `${actionURL}${qs.stringify( + { + uploadEdits: form?.uploadEdits || undefined, + }, + { + addQueryPrefix: true, + }, + )}` const req = await fetch(actionURLWithParams, { body: await createFormData( @@ -466,7 +465,6 @@ export function FormsManagerProvider({ children }: FormsManagerProps) { errorCount: forms[i].errorCount, formState: forms[i].formState, index: i, - uploadEdits: forms[i].uploadEdits, }) } }) @@ -502,6 +500,31 @@ export function FormsManagerProvider({ children }: FormsManagerProps) { [collectionSlug, docPermissions, forms, getFormState, hasSubmitted], ) + const updateUploadEdits = React.useCallback( + (uploadEdits) => { + dispatch({ + type: 'UPDATE_FORM', + errorCount: forms[activeIndex].errorCount, + formState: forms[activeIndex].formState, + index: activeIndex, + uploadEdits, + }) + }, + [activeIndex, forms], + ) + + const resetUploadEdits = React.useCallback(() => { + dispatch({ + type: 'REPLACE', + state: { + forms: forms.map((form) => ({ + ...form, + uploadEdits: {}, + })), + }, + }) + }, [forms]) + React.useEffect(() => { if (!collectionSlug) { return @@ -548,18 +571,19 @@ export function FormsManagerProvider({ children }: FormsManagerProps) { documentSlots, forms, getFormDataRef, - getUploadEditsRef, hasPublishPermission, hasSavePermission, hasSubmitted, isInBulkUploadContext: true, isInitializing, removeFile, + resetUploadEdits, saveAllDocs, setActiveIndex, setFormTotalErrorCount, thumbnailUrls: renderedThumbnails, totalErrorCount, + updateUploadEdits, }} > {isUploading && ( diff --git a/packages/ui/src/elements/BulkUpload/FormsManager/reducer.ts b/packages/ui/src/elements/BulkUpload/FormsManager/reducer.ts index 3a2299d8900..cbbe28a9f75 100644 --- a/packages/ui/src/elements/BulkUpload/FormsManager/reducer.ts +++ b/packages/ui/src/elements/BulkUpload/FormsManager/reducer.ts @@ -120,6 +120,10 @@ export function formsManagementReducer(state: State, action: Action): State { ...updatedForms[action.index].formState, ...action.formState, }, + uploadEdits: { + ...updatedForms[action.index].uploadEdits, + ...action.uploadEdits, + }, } return { diff --git a/packages/ui/src/elements/Upload/index.tsx b/packages/ui/src/elements/Upload/index.tsx index d90d06c0b92..1796d4d3b5c 100644 --- a/packages/ui/src/elements/Upload/index.tsx +++ b/packages/ui/src/elements/Upload/index.tsx @@ -14,15 +14,14 @@ import { useDocumentInfo } from '../../providers/DocumentInfo/index.js' import { EditDepthProvider } from '../../providers/EditDepth/index.js' import { useTranslation } from '../../providers/Translation/index.js' import { useUploadEdits } from '../../providers/UploadEdits/index.js' -import { useFormsManager } from '../BulkUpload/FormsManager/index.js' import { Button } from '../Button/index.js' import { Drawer, DrawerToggler } from '../Drawer/index.js' import { Dropzone } from '../Dropzone/index.js' -import './index.scss' import { EditUpload } from '../EditUpload/index.js' import { FileDetails } from '../FileDetails/index.js' import { PreviewSizes } from '../PreviewSizes/index.js' import { Thumbnail } from '../Thumbnail/index.js' +import './index.scss' const baseClass = 'file-field' export const editDrawerSlug = 'edit-upload' @@ -92,7 +91,34 @@ export type UploadProps = { } export const Upload: React.FC = (props) => { - const { collectionSlug, customActions, initialState, onChange, uploadConfig } = props + const { resetUploadEdits, updateUploadEdits, uploadEdits } = useUploadEdits() + return ( + + ) +} + +export type UploadProps_v4 = { + readonly resetUploadEdits?: () => void + readonly updateUploadEdits?: (args: UploadEdits) => void + readonly uploadEdits?: UploadEdits +} & UploadProps + +export const Upload_v4: React.FC = (props) => { + const { + collectionSlug, + customActions, + initialState, + onChange, + resetUploadEdits, + updateUploadEdits, + uploadConfig, + uploadEdits, + } = props const { config: { @@ -103,8 +129,6 @@ export const Upload: React.FC = (props) => { const { t } = useTranslation() const { setModified } = useForm() - const { resetUploadEdits, updateUploadEdits, uploadEdits } = useUploadEdits() - const { activeIndex, forms, getUploadEditsRef, isInBulkUploadContext } = useFormsManager() const { id, docPermissions, savedDocumentData, setUploadStatus } = useDocumentInfo() const isFormSubmitting = useFormProcessing() const { errorMessage, setValue, showError, value } = useField({ @@ -112,10 +136,6 @@ export const Upload: React.FC = (props) => { validate, }) - const currentUploadEdits = isInBulkUploadContext - ? getUploadEditsRef.current?.() || forms[activeIndex]?.uploadEdits - : uploadEdits - const [fileSrc, setFileSrc] = useState(null) const [removedFile, setRemovedFile] = useState(false) const [filename, setFilename] = useState(value?.name || '') @@ -429,10 +449,10 @@ export const Upload: React.FC = (props) => { fileName={value?.name || savedDocumentData?.filename} fileSrc={savedDocumentData?.url || fileSrc} imageCacheTag={imageCacheTag} - initialCrop={currentUploadEdits?.crop ?? undefined} + initialCrop={uploadEdits?.crop ?? undefined} initialFocalPoint={{ - x: currentUploadEdits?.focalPoint?.x || savedDocumentData?.focalX || 50, - y: currentUploadEdits?.focalPoint?.y || savedDocumentData?.focalY || 50, + x: uploadEdits?.focalPoint?.x || savedDocumentData?.focalX || 50, + y: uploadEdits?.focalPoint?.y || savedDocumentData?.focalY || 50, }} onSave={onEditsSave} showCrop={showCrop} diff --git a/packages/ui/src/providers/DocumentInfo/index.tsx b/packages/ui/src/providers/DocumentInfo/index.tsx index a989c221194..7ce902301b9 100644 --- a/packages/ui/src/providers/DocumentInfo/index.tsx +++ b/packages/ui/src/providers/DocumentInfo/index.tsx @@ -1,17 +1,11 @@ 'use client' -import type { - ClientUser, - DocumentPreferences, - SanitizedDocumentPermissions, - UploadEdits, -} from 'payload' +import type { ClientUser, DocumentPreferences, SanitizedDocumentPermissions } from 'payload' import * as qs from 'qs-esm' import React, { createContext, use, useCallback, useEffect, useMemo, useRef, useState } from 'react' import type { DocumentInfoContext, DocumentInfoProps } from './types.js' -import { useFormsManager } from '../../elements/BulkUpload/FormsManager/index.js' import { useAuth } from '../../providers/Auth/index.js' import { requests } from '../../utilities/api.js' import { formatDocTitle } from '../../utilities/formatDocTitle/index.js' @@ -364,15 +358,10 @@ const DocumentInfo: React.FC< export const DocumentInfoProvider: React.FC< { readonly children: React.ReactNode - initialUploadEdits?: UploadEdits } & DocumentInfoProps > = (props) => { - const { activeIndex, forms } = useFormsManager() - - const initialUploadEdits = forms?.[activeIndex]?.uploadEdits - return ( - + ) From 33161e4cdcc88b13e8b6cb6d10810b4382273d59 Mon Sep 17 00:00:00 2001 From: Patrik Kozak Date: Mon, 7 Apr 2025 13:34:50 -0400 Subject: [PATCH 4/4] fix: removes isInBulkUploadContext prop from FormsManaerContext --- packages/ui/src/elements/BulkUpload/FormsManager/index.tsx | 3 --- 1 file changed, 3 deletions(-) diff --git a/packages/ui/src/elements/BulkUpload/FormsManager/index.tsx b/packages/ui/src/elements/BulkUpload/FormsManager/index.tsx index 7c7364b35d1..21159e87665 100644 --- a/packages/ui/src/elements/BulkUpload/FormsManager/index.tsx +++ b/packages/ui/src/elements/BulkUpload/FormsManager/index.tsx @@ -45,7 +45,6 @@ type FormsManagerContext = { readonly hasPublishPermission: boolean readonly hasSavePermission: boolean readonly hasSubmitted: boolean - readonly isInBulkUploadContext: boolean readonly isInitializing: boolean readonly removeFile: (index: number) => void readonly resetUploadEdits?: () => void @@ -75,7 +74,6 @@ const Context = React.createContext({ hasPublishPermission: false, hasSavePermission: false, hasSubmitted: false, - isInBulkUploadContext: false, isInitializing: false, removeFile: () => {}, saveAllDocs: () => Promise.resolve(), @@ -574,7 +572,6 @@ export function FormsManagerProvider({ children }: FormsManagerProps) { hasPublishPermission, hasSavePermission, hasSubmitted, - isInBulkUploadContext: true, isInitializing, removeFile, resetUploadEdits,