Support upload of multiple files at once

This commit is contained in:
ekzyis 2023-10-25 21:11:23 +02:00
parent 1b7b869fdb
commit 9885f7d768

View File

@ -153,6 +153,7 @@ export function ImageUpload ({ children, className, onSelect, onSuccess, onError
const s3Upload = useCallback(file => { const s3Upload = useCallback(file => {
const img = new window.Image() const img = new window.Image()
img.src = window.URL.createObjectURL(file) img.src = window.URL.createObjectURL(file)
return new Promise((resolve, reject) => {
img.onload = async () => { img.onload = async () => {
onSelect?.(file) onSelect?.(file)
let data let data
@ -167,6 +168,7 @@ export function ImageUpload ({ children, className, onSelect, onSuccess, onError
} catch (e) { } catch (e) {
toaster.danger(e.message || e.toString?.()) toaster.danger(e.message || e.toString?.())
onError?.({ ...variables, name: file.name, file }) onError?.({ ...variables, name: file.name, file })
reject(e)
return return
} }
@ -184,8 +186,10 @@ export function ImageUpload ({ children, className, onSelect, onSuccess, onError
if (!res.ok) { if (!res.ok) {
// TODO make sure this is actually a helpful error message and does not expose anything to the user we don't want // TODO make sure this is actually a helpful error message and does not expose anything to the user we don't want
toaster.danger(res.statusText) const err = res.statusText
toaster.danger(err)
onError?.({ ...variables, name: file.name, file }) onError?.({ ...variables, name: file.name, file })
reject(err)
return return
} }
@ -193,7 +197,9 @@ export function ImageUpload ({ children, className, onSelect, onSuccess, onError
// key is upload id in database // key is upload id in database
const id = data.getSignedPOST.fields.key const id = data.getSignedPOST.fields.key
onSuccess?.({ ...variables, id, name: file.name, url, file }) onSuccess?.({ ...variables, id, name: file.name, url, file })
resolve(id)
} }
})
}, [toaster, getSignedPOST]) }, [toaster, getSignedPOST])
return ( return (
@ -201,20 +207,20 @@ export function ImageUpload ({ children, className, onSelect, onSuccess, onError
<input <input
ref={ref} ref={ref}
type='file' type='file'
multiple
className='d-none' className='d-none'
accept={UPLOAD_TYPES_ALLOW.join(', ')} accept={UPLOAD_TYPES_ALLOW.join(', ')}
onChange={(e) => { onChange={async (e) => {
if (e.target.files.length === 0) { const fileList = e.target.files
return for (const file of Array.from(fileList)) {
}
const file = e.target.files[0]
if (UPLOAD_TYPES_ALLOW.indexOf(file.type) === -1) { if (UPLOAD_TYPES_ALLOW.indexOf(file.type) === -1) {
toaster.danger(`image must be ${UPLOAD_TYPES_ALLOW.map(t => t.replace('image/', '')).join(', ')}`) toaster.danger(`image must be ${UPLOAD_TYPES_ALLOW.map(t => t.replace('image/', '')).join(', ')}`)
return continue
} }
s3Upload(file) await s3Upload(file)
// TODO find out if this is needed and if so, why (copied from components/upload.js) // TODO find out if this is needed and if so, why (copied from components/upload.js)
e.target.value = null e.target.value = null
}
}} }}
/> />
<div className={className} onClick={() => ref.current?.click()} style={{ cursor: 'pointer' }}> <div className={className} onClick={() => ref.current?.click()} style={{ cursor: 'pointer' }}>