Skip to content

Commit ebf3cee

Browse files
authored
fix(ui): prevent many upload fields overwriting bulkUpload onSuccess (#10189)
<!-- Thank you for the PR! Please go through the checklist below and make sure you've completed all the steps. Please review the [CONTRIBUTING.md](https://github.com/payloadcms/payload/blob/main/CONTRIBUTING.md) document in this repository if you haven't already. The following items will ensure that your PR is handled as smoothly as possible: - PR Title must follow conventional commits format. For example, `feat: my new feature`, `fix(plugin-seo): my fix`. - Minimal description explained as if explained to someone not immediately familiar with the code. - Provide before/after screenshots or code diffs if applicable. - Link any related issues/discussions from GitHub or Discord. - Add review comments if necessary to explain to the reviewer the logic behind a change ### What? ### Why? ### How? Fixes # --> ### What? This PR fixes an issue where multiple `upload` fields would sequentially overwrite the `BulkUpload` internal `onSuccess` function causing new uploads to populate the incorrect field from which the interaction started. ### Why? Sequential `upload` fields use a `useEffect` to set the success function of the `BulkUpload` provider component, however this did not take into account many `upload` fields in a single document. This PR prevents many `upload` fields from overriding their sibling's `onSuccess` function in order to populate those fields correctly. ### How? By changing the way the bulk upload component handles success functions from a singular function to a map of functions based on a string path of the field, or if necessary, using a collection slug in the case of a bulk upload on an `upload` collection list view. Fixes #10177 Before (One hasMany, one single): [Editing-hasmany-single--Post-before--Payload.webm](https://github.com/user-attachments/assets/01aeaa64-a065-4e66-8ab4-6bb9d4fa8556) Before (Many hasMany): [Editing-hasmany-two--Post-before--Payload.webm](https://github.com/user-attachments/assets/a65c58aa-9a15-4cca-b2c4-17484c020ddc) After (One hasMany, one single): [Editing-hasmany-single--Post-after--Payload.webm](https://github.com/user-attachments/assets/7206f94e-4ce2-41b3-8b45-625f4974d28d) After (Many hasMany): [Editing-hasmany-two--Post-after--Payload.webm](https://github.com/user-attachments/assets/72dbbdee-d4a5-4488-8ef0-3dd3918115a9)
1 parent d8a62b7 commit ebf3cee

File tree

3 files changed

+43
-13
lines changed

3 files changed

+43
-13
lines changed

packages/ui/src/elements/BulkUpload/index.tsx

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -83,51 +83,61 @@ export function BulkUploadDrawer() {
8383

8484
type BulkUploadContext = {
8585
collectionSlug: string
86+
currentActivePath: string
8687
drawerSlug: string
8788
initialFiles: FileList
8889
maxFiles: number
8990
onCancel: () => void
9091
onSuccess: (newDocs: JsonObject[], errorCount: number) => void
9192
setCollectionSlug: (slug: string) => void
93+
setCurrentActivePath: (path: string) => void
9294
setInitialFiles: (files: FileList) => void
9395
setMaxFiles: (maxFiles: number) => void
9496
setOnCancel: (onCancel: BulkUploadContext['onCancel']) => void
95-
setOnSuccess: (onSuccess: BulkUploadContext['onSuccess']) => void
97+
setOnSuccess: (path: string, onSuccess: BulkUploadContext['onSuccess']) => void
9698
}
9799

98100
const Context = React.createContext<BulkUploadContext>({
99101
collectionSlug: '',
102+
currentActivePath: undefined,
100103
drawerSlug: '',
101104
initialFiles: undefined,
102105
maxFiles: undefined,
103106
onCancel: () => null,
104107
onSuccess: () => null,
105108
setCollectionSlug: () => null,
109+
setCurrentActivePath: () => null,
106110
setInitialFiles: () => null,
107111
setMaxFiles: () => null,
108112
setOnCancel: () => null,
109113
setOnSuccess: () => null,
110114
})
111115
export function BulkUploadProvider({ children }: { readonly children: React.ReactNode }) {
112116
const [collection, setCollection] = React.useState<string>()
113-
const [onSuccessFunction, setOnSuccessFunction] = React.useState<BulkUploadContext['onSuccess']>()
117+
const [onSuccessFunctionMap, setOnSuccessFunctionMap] =
118+
React.useState<Record<string, BulkUploadContext['onSuccess']>>()
114119
const [onCancelFunction, setOnCancelFunction] = React.useState<BulkUploadContext['onCancel']>()
115120
const [initialFiles, setInitialFiles] = React.useState<FileList>(undefined)
116121
const [maxFiles, setMaxFiles] = React.useState<number>(undefined)
122+
const [currentActivePath, setCurrentActivePath] = React.useState<string>(undefined)
117123
const drawerSlug = useBulkUploadDrawerSlug()
118124

119125
const setCollectionSlug: BulkUploadContext['setCollectionSlug'] = (slug) => {
120126
setCollection(slug)
121127
}
122128

123-
const setOnSuccess: BulkUploadContext['setOnSuccess'] = (onSuccess) => {
124-
setOnSuccessFunction(() => onSuccess)
125-
}
129+
const setOnSuccess: BulkUploadContext['setOnSuccess'] = React.useCallback((path, onSuccess) => {
130+
setOnSuccessFunctionMap((prev) => ({
131+
...prev,
132+
[path]: onSuccess,
133+
}))
134+
}, [])
126135

127136
return (
128137
<Context.Provider
129138
value={{
130139
collectionSlug: collection,
140+
currentActivePath,
131141
drawerSlug,
132142
initialFiles,
133143
maxFiles,
@@ -137,11 +147,13 @@ export function BulkUploadProvider({ children }: { readonly children: React.Reac
137147
}
138148
},
139149
onSuccess: (docIDs, errorCount) => {
140-
if (typeof onSuccessFunction === 'function') {
150+
if (onSuccessFunctionMap && Object.hasOwn(onSuccessFunctionMap, currentActivePath)) {
151+
const onSuccessFunction = onSuccessFunctionMap[currentActivePath]
141152
onSuccessFunction(docIDs, errorCount)
142153
}
143154
},
144155
setCollectionSlug,
156+
setCurrentActivePath,
145157
setInitialFiles,
146158
setMaxFiles,
147159
setOnCancel: setOnCancelFunction,

packages/ui/src/fields/Upload/Input.tsx

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -115,8 +115,14 @@ export function UploadInput(props: UploadInputProps) {
115115
)
116116

117117
const { openModal } = useModal()
118-
const { drawerSlug, setCollectionSlug, setInitialFiles, setMaxFiles, setOnSuccess } =
119-
useBulkUpload()
118+
const {
119+
drawerSlug,
120+
setCollectionSlug,
121+
setCurrentActivePath,
122+
setInitialFiles,
123+
setMaxFiles,
124+
setOnSuccess,
125+
} = useBulkUpload()
120126
const { permissions } = useAuth()
121127
const { code } = useLocale()
122128
const { i18n, t } = useTranslation()
@@ -269,6 +275,7 @@ export function UploadInput(props: UploadInputProps) {
269275
if (typeof maxRows === 'number') {
270276
setMaxFiles(maxRows)
271277
}
278+
setCurrentActivePath(path)
272279
openModal(drawerSlug)
273280
},
274281
[
@@ -280,6 +287,8 @@ export function UploadInput(props: UploadInputProps) {
280287
setInitialFiles,
281288
maxRows,
282289
setMaxFiles,
290+
path,
291+
setCurrentActivePath,
283292
],
284293
)
285294

@@ -426,8 +435,8 @@ export function UploadInput(props: UploadInputProps) {
426435
}, [populateDocs, activeRelationTo, value])
427436

428437
useEffect(() => {
429-
setOnSuccess(onUploadSuccess)
430-
}, [value, onUploadSuccess, setOnSuccess])
438+
setOnSuccess(path, onUploadSuccess)
439+
}, [value, path, onUploadSuccess, setOnSuccess])
431440

432441
const showDropzone =
433442
!value ||

packages/ui/src/views/List/index.tsx

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ export const DefaultListView: React.FC<ListViewClientProps> = (props) => {
110110
query,
111111
} = useListQuery()
112112
const { openModal } = useModal()
113-
const { setCollectionSlug, setOnSuccess } = useBulkUpload()
113+
const { setCollectionSlug, setCurrentActivePath, setOnSuccess } = useBulkUpload()
114114
const { drawerSlug: bulkUploadDrawerSlug } = useBulkUpload()
115115

116116
const collectionConfig = getEntityConfig({ collectionSlug }) as ClientCollectionConfig
@@ -148,9 +148,18 @@ export const DefaultListView: React.FC<ListViewClientProps> = (props) => {
148148

149149
const openBulkUpload = React.useCallback(() => {
150150
setCollectionSlug(collectionSlug)
151+
setCurrentActivePath(collectionSlug)
151152
openModal(bulkUploadDrawerSlug)
152-
setOnSuccess(() => router.refresh())
153-
}, [router, collectionSlug, bulkUploadDrawerSlug, openModal, setCollectionSlug, setOnSuccess])
153+
setOnSuccess(collectionSlug, () => router.refresh())
154+
}, [
155+
router,
156+
collectionSlug,
157+
bulkUploadDrawerSlug,
158+
openModal,
159+
setCollectionSlug,
160+
setCurrentActivePath,
161+
setOnSuccess,
162+
])
154163

155164
useEffect(() => {
156165
if (drawerDepth <= 1) {

0 commit comments

Comments
 (0)