Accept multiple files when uploading

This commit is contained in:
Sam Becker 2023-11-10 12:14:07 -06:00
parent f200d1d754
commit 8bef969908
3 changed files with 98 additions and 61 deletions

View File

@ -19,7 +19,12 @@ export default function ImageInput({
debug,
}: {
onStart?: () => void
onBlobReady?: (blob: Blob, extension?: string) => void
onBlobReady?: (args: {
blob: Blob,
extension?: string,
hasMultipleUploads?: boolean,
isLastBlob?: boolean,
}) => Promise<any>
maxSize?: number
quality?: number
loading?: boolean
@ -27,7 +32,7 @@ export default function ImageInput({
}) {
const ref = useRef<HTMLCanvasElement>(null);
const [fileName, setFileName] = useState<string>();
const [statusText, setStatusText] = useState<string>();
const [image, setImage] = useState<HTMLImageElement>();
return (
@ -63,16 +68,33 @@ export default function ImageInput({
className="!hidden"
accept={ACCEPTED_PHOTO_FILE_TYPES.join(',')}
disabled={loading}
multiple
onChange={async e => {
onStart?.();
const file = e.currentTarget.files?.[0];
setFileName(file?.name);
const extension = file?.name.split('.').pop()?.toLowerCase();
const canvas = ref.current;
const { files } = e.currentTarget;
if (files && files.length > 0) {
for (let i = 0; i < files?.length; i++) {
const file = files[i];
if (file) {
const callbackArgs = {
extension: file.name.split('.').pop()?.toLowerCase(),
hasMultipleUploads: files.length > 1,
isLastBlob: i === files.length - 1,
};
if (files.length > 1) {
setStatusText(
`Uploading ${i + 1} of ${files.length}: ${file.name}`
);
} else {
setStatusText(`Uploading ${file.name}`);
}
const canvas = ref.current;
if (!(maxSize && canvas)) {
// No need to process
onBlobReady?.(file);
await onBlobReady?.({
...callbackArgs,
blob: file,
});
} else {
// Process images that need resizing
const image = await blobToImage(file);
@ -105,7 +127,10 @@ export default function ImageInput({
async blob => {
if (blob) {
const blobWithExif = await CopyExif(file, blob);
onBlobReady?.(blobWithExif, extension);
await onBlobReady?.({
...callbackArgs,
blob: blobWithExif,
});
}
},
'image/jpeg',
@ -113,12 +138,14 @@ export default function ImageInput({
);
}
}
}
}
}}
/>
</label>
{fileName &&
{statusText &&
<div className="max-w-full truncate text-ellipsis">
{fileName}
{statusText}
</div>}
</div>
<canvas

View File

@ -3,7 +3,7 @@
import { useState } from 'react';
import { uploadPhotoFromClient } from '@/services/blob';
import { useRouter } from 'next/navigation';
import { pathForAdminUploadUrl } from '@/site/paths';
import { PATH_ADMIN_UPLOADS, pathForAdminUploadUrl } from '@/site/paths';
import ImageInput from '../components/ImageInput';
import { MAX_IMAGE_SIZE } from '@/utility/image';
import { cc } from '@/utility/css';
@ -38,7 +38,12 @@ export default function PhotoUpload({
setIsUploading(true);
setUploadError('');
}}
onBlobReady={(blob, extension) => {
onBlobReady={async ({
blob,
extension,
hasMultipleUploads,
isLastBlob,
}) => {
if (debug) {
setDebugDownload({
href: URL.createObjectURL(blob),
@ -47,16 +52,23 @@ export default function PhotoUpload({
setIsUploading(false);
setUploadError('');
} else {
uploadPhotoFromClient(
return uploadPhotoFromClient(
blob,
extension,
)
.then(({ url }) => {
if (isLastBlob) {
// Refresh page to update upload list,
// relevant only when a photo isn't added
// relevant to upload count in nav
router.refresh();
if (hasMultipleUploads) {
// Redirect to view multiple uploads
router.push(PATH_ADMIN_UPLOADS);
} else {
// Redirect to photo detail page
router.push(pathForAdminUploadUrl(url));
}
}
})
.catch(error => {
setIsUploading(false);

View File

@ -31,8 +31,7 @@ const PATH_CAMERA_DYNAMIC = `${PREFIX_CAMERA}/:camera`;
export const PATH_ADMIN_PHOTOS = `${PATH_ADMIN}/photos`;
export const PATH_ADMIN_UPLOADS = `${PATH_ADMIN}/uploads`;
export const PATH_ADMIN_TAGS = `${PATH_ADMIN}/tags`;
export const PATH_ADMIN_UPLOAD = `${PATH_ADMIN}/uploads`;
export const PATH_ADMIN_UPLOAD_BLOB = `${PATH_ADMIN_UPLOAD}/blob`;
export const PATH_ADMIN_UPLOAD_BLOB = `${PATH_ADMIN_UPLOADS}/blob`;
export const PATH_ADMIN_CONFIGURATION = `${PATH_ADMIN}/configuration`;
// Modifiers
@ -45,7 +44,6 @@ export const PATHS_ADMIN = [
PATH_ADMIN_PHOTOS,
PATH_ADMIN_UPLOADS,
PATH_ADMIN_TAGS,
PATH_ADMIN_UPLOAD,
PATH_ADMIN_UPLOAD_BLOB,
PATH_ADMIN_CONFIGURATION,
];