Skip to content

Commit 8911dec

Browse files
committed
feat: enhance image upload functionality with loading state and file size validation
1 parent 976c06e commit 8911dec

File tree

2 files changed

+24
-22
lines changed

2 files changed

+24
-22
lines changed

custom/imageGenerator.vue

Lines changed: 22 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -64,9 +64,10 @@
6464
@change="handleAddFile"
6565
accept="image/*"
6666
/>
67-
<button @click="fileInput?.click()" type="button" class="group hover:border-gray-500 transition border-gray-300 flex items-center justify-center w-20 h-20 border-2 border-dashed rounded-md">
67+
<button v-if="!uploading" @click="fileInput?.click()" type="button" class="group hover:border-gray-500 transition border-gray-300 flex items-center justify-center w-20 h-20 border-2 border-dashed rounded-md">
6868
<IconCloseOutline class="group-hover:text-gray-500 transition rotate-45 w-10 h-10 text-gray-300 hover:text-gray-300" />
6969
</button>
70+
<Skeleton v-else type="image" class="w-20 h-20" />
7071
</div>
7172

7273
<!-- Fullscreen Modal -->
@@ -208,7 +209,7 @@ import adminforth from '@/adminforth';
208209
import { ProgressBar } from '@/afcl';
209210
import * as Handlebars from 'handlebars';
210211
import { IconCloseOutline } from '@iconify-prerendered/vue-flowbite';
211-
import { Tooltip } from '@/afcl'
212+
import { Tooltip, Skeleton } from '@/afcl'
212213
import { useRoute } from 'vue-router';
213214
214215
const { t: $t, t } = useI18n();
@@ -220,6 +221,7 @@ const emit = defineEmits(['close', 'uploadImage']);
220221
const props = defineProps({
221222
meta: Object,
222223
record: Object,
224+
humanifySize: Function,
223225
});
224226
const images = ref([]);
225227
const loading = ref(false);
@@ -498,8 +500,9 @@ async function handleAddFile(event) {
498500
continue;
499501
}
500502
const file = files[i];
501-
requestAttachmentFiles.value!.push(file);
502503
const fileUrl = await uploadFile(file);
504+
if (!fileUrl) continue;
505+
requestAttachmentFiles.value!.push(file);
503506
requestAttachmentFilesUrls.value.push(fileUrl);
504507
}
505508
fileInput.value!.value = '';
@@ -510,26 +513,29 @@ function removeFileFromList(index: number) {
510513
requestAttachmentFilesUrls.value.splice(index, 1);
511514
}
512515
513-
const uploaded = ref(false);
514-
const progress = ref(0);
516+
const uploading = ref(false);
515517
516518
async function uploadFile(file: any): Promise<string> {
517519
const { name, size, type } = file;
520+
518521
let imgPreview = '';
519522
520523
const extension = name.split('.').pop();
521524
const nameNoExtension = name.replace(`.${extension}`, '');
522525
526+
if (props.meta.maxFileSize && size > props.meta.maxFileSize) {
527+
adminforth.alert({
528+
message: t('Sorry but the file size {size} is too large. Please upload a file with a maximum size of {maxFileSize}', {
529+
size: props.humanifySize(size),
530+
maxFileSize: props.humanifySize(props.meta.maxFileSize),
531+
}),
532+
variant: 'danger'
533+
});
534+
return;
535+
}
536+
523537
try {
524-
// supports preview
525-
if (type.startsWith('image/')) {
526-
const reader = new FileReader();
527-
reader.onload = (e) => {
528-
imgPreview = e.target.result as string;
529-
}
530-
reader.readAsDataURL(file);
531-
}
532-
538+
uploading.value = true;
533539
const { uploadUrl, uploadExtraParams, filePath, error, previewUrl } = await callAdminForthApi({
534540
path: `/plugin/${props.meta.pluginInstanceId}/get_file_upload_url`,
535541
method: 'POST',
@@ -547,18 +553,11 @@ async function uploadFile(file: any): Promise<string> {
547553
variant: 'danger'
548554
});
549555
imgPreview = null;
550-
uploaded.value = false;
551-
progress.value = 0;
552556
return;
553557
}
554558
555559
const xhr = new XMLHttpRequest();
556560
const success = await new Promise((resolve) => {
557-
xhr.upload.onprogress = (e) => {
558-
if (e.lengthComputable) {
559-
progress.value = Math.round((e.loaded / e.total) * 100);
560-
}
561-
};
562561
xhr.addEventListener('loadend', () => {
563562
const success = xhr.readyState === 4 && xhr.status === 200;
564563
// try to read response
@@ -578,8 +577,10 @@ async function uploadFile(file: any): Promise<string> {
578577
throw new Error('File upload failed');
579578
}
580579
} catch (err) {
580+
uploading.value = false;
581581
console.error('File upload failed', err);
582582
}
583+
uploading.value = false;
583584
return imgPreview;
584585
}
585586
</script>

custom/uploader.vue

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
<template>
22
<div class="relative w-full">
33
<ImageGenerator v-if="showImageGen" @close="showImageGen = false" :record="record" :meta="meta"
4-
@uploadImage="uploadGeneratedImage"
4+
@uploadImage="uploadGeneratedImage"
5+
:humanifySize="humanifySize"
56
></ImageGenerator>
67

78
<button v-if="meta.generateImages"

0 commit comments

Comments
 (0)