Skip to content

Conversation

@kendelljoseph
Copy link
Contributor

@kendelljoseph kendelljoseph commented Mar 10, 2025

What?

Adds the ability to add additional components to the file upload component.

export const Media: CollectionConfig = { slug: 'media', upload: { admin: { components: { controls: [ '/collections/components/Control/index.js#UploadControl', ], }, }, }, fields: [], }

image

Provider

Use the useUploadControls provider to either setUploadControlFile passing a file object, or set the file by url using setUploadControlFileUrl.

'use client' import { Button, useUploadControls } from '@payloadcms/ui' import React, { useCallback } from 'react' export const UploadControl = () => { const { setUploadControlFile, setUploadControlFileUrl } = useUploadControls() const loadFromFile = useCallback(async () => { const response = await fetch('https://payloadcms.com/images/universal-truth.jpg') const blob = await response.blob() const file = new File([blob], 'universal-truth.jpg', { type: 'image/jpeg' }) setUploadControlFile(file) }, [setUploadControlFile]) const loadFromUrl = useCallback(() => { setUploadControlFileUrl('https://payloadcms.com/images/universal-truth.jpg') }, [setUploadControlFileUrl]) return ( <div> <Button id="load-from-file-upload-button" onClick={loadFromFile}> Load from File </Button> <br /> <Button id="load-from-url-upload-button" onClick={loadFromUrl}> Load from URL </Button> </div> ) }

Why?

Add the ability to use a custom component to select a document to upload.

@kendelljoseph kendelljoseph self-assigned this Mar 10, 2025
@kendelljoseph kendelljoseph marked this pull request as ready for review March 10, 2025 19:39
@rilrom
Copy link
Contributor

rilrom commented Mar 11, 2025

This makes me very happy. I'll no longer need a custom upload component for my image search plugin, thank you!

@PatrikKozak PatrikKozak self-requested a review March 12, 2025 14:03
Copy link
Contributor

@PatrikKozak PatrikKozak left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kendelljoseph Can we update the styling of the Select a file & Paste url buttons or / it's parent wrappers so that the buttons do not stretch (like shown in your image above) if the parent height changes due to the custom components?

@kendelljoseph
Copy link
Contributor Author

@PatrikKozak yep, will do!

@kendelljoseph kendelljoseph force-pushed the feat/upload-controls branch 2 times, most recently from 7b98279 to 3c1ca0f Compare March 31, 2025 19:35
@kendelljoseph kendelljoseph force-pushed the feat/upload-controls branch 2 times, most recently from 2d2d4e8 to 1c8e823 Compare May 19, 2025 15:03
updateUploadEdits={updateUploadEdits}
uploadEdits={uploadEdits}
/>
<UploadControlsProvider>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this provider should wrap these lines https://github.com/payloadcms/payload/pull/11615/files#diff-1bff65262fbaf801a00a575c6b3ced6b40325c0e5cadcdfdc88c8590a256bdbdR592-R598

and can be removed from this file. This way if they define a CustomUpload it will have access to the context.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm -- It's not clear by the link which lines or file you mean. It's not zooming to it correctly or something?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Got it!

Comment on lines +354 to +373
useEffect(() => {
const handleControlFileUrl = async () => {
if (uploadControlFileUrl) {
setFileUrl(uploadControlFileUrl)
await handleUrlSubmit()
}
}

void handleControlFileUrl()
}, [uploadControlFileUrl, handleUrlSubmit])

useEffect(() => {
const handleControlFile = () => {
if (uploadControlFile) {
handleFileChange(uploadControlFile)
}
}

void handleControlFile()
}, [uploadControlFile, handleFileChange])
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need effects here? Or could we just make functions that get called in the onClick handlers below?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since the uploadControlFileUrl and uploadControlFile can be modified by a custom component that is the useUploadControls(), we want to look for changes here and then run the internal handleFileChange or handleUrlSubmit the same way.

So I think we do need the effect here to watch for changes.

@JarrodMFlesch
Copy link
Contributor

We need a way to get UploadControls into the BulkUpload view as well. Currently they do not show up.

@kendelljoseph
Copy link
Contributor Author

@JarrodMFlesch I think we can add the BulkUploadControl as a separate PR.

  • I am able to thread the UploadControl through, but it has to be a different control, since it is referencing a different file input.
  • This will require wrapping a provider around bulk upload to connect the URL or File object that the BulkUploadControl would be touching.
    Example:
image

The Add File button also seems to reset the state of the control I shimmied in using getDocumentSlots, so that would have to be resolved.

image

After clicking add file
image

Also canceling the target file to upload would need to have a control added:

Before canceling:
image

After canceling:
image

Given the amount of adaptations needed I'm proposing grouping that effort into a different PR, feat: admin bulk upload controls so that we can ship this feat.

@kendelljoseph kendelljoseph merged commit f2e0422 into main Jun 13, 2025
80 checks passed
@kendelljoseph kendelljoseph deleted the feat/upload-controls branch June 13, 2025 16:47
@github-actions
Copy link
Contributor

🚀 This is included in version v3.43.0

@rilrom
Copy link
Contributor

rilrom commented Jun 27, 2025

This worked amazingly in my image search plugin, no longer need to keep track of any changes that happen to the default upload component.

Thanks again for your work on this! Looking forward to seeing the equivalent for the bulk upload feature in the near future.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment