Accept multiple files when uploading
This commit is contained in:
parent
f200d1d754
commit
8bef969908
@ -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
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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,
|
||||
];
|
||||
|
||||
Loading…
Reference in New Issue
Block a user