before refactor
This commit is contained in:
215
src/components/ScenarioFileUpload.vue
Normal file
215
src/components/ScenarioFileUpload.vue
Normal file
@@ -0,0 +1,215 @@
|
||||
<script setup>
|
||||
import { FileUploadStore } from '@/stores/FileUploadStore';
|
||||
import { useAuth } from '@websanova/vue-auth/src/v3.js';
|
||||
import { usePrimeVue } from 'primevue/config';
|
||||
import { useToast } from 'primevue/usetoast';
|
||||
import { ref, watch } from 'vue';
|
||||
|
||||
const props = defineProps({
|
||||
inputName: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
label: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
tooltipText: {
|
||||
type: String,
|
||||
default: 'Upload files'
|
||||
},
|
||||
uploadUrl: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
isMultiple: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
acceptedFormats: {
|
||||
type: String,
|
||||
default: '.docx'
|
||||
},
|
||||
folderName: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
uploadedFiles: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
}
|
||||
});
|
||||
|
||||
const emit = defineEmits(['upload', 'remove', 'update:uploadedFiles']);
|
||||
|
||||
const fileUploadStore = FileUploadStore();
|
||||
const toast = useToast();
|
||||
const auth = useAuth();
|
||||
const $primevue = usePrimeVue();
|
||||
|
||||
const localUploadedFiles = ref(props.uploadedFiles);
|
||||
|
||||
// Sync uploaded files with parent
|
||||
watch(
|
||||
localUploadedFiles,
|
||||
(newFiles) => {
|
||||
emit('update:uploadedFiles', newFiles);
|
||||
},
|
||||
{ deep: true }
|
||||
);
|
||||
|
||||
watch(
|
||||
() => props.uploadedFiles,
|
||||
(newFiles) => {
|
||||
localUploadedFiles.value = newFiles;
|
||||
},
|
||||
{ deep: true }
|
||||
);
|
||||
|
||||
const onBeforeSend = (event) => {
|
||||
const { xhr } = event;
|
||||
const token = auth.token();
|
||||
xhr.setRequestHeader('Authorization', 'Bearer ' + token);
|
||||
};
|
||||
|
||||
const handleUpload = (event) => {
|
||||
const { xhr } = event;
|
||||
|
||||
if (xhr.status === 200) {
|
||||
const uploadedFileName = event.files && event.files.length > 0 ? event.files[0].name : 'UnknownFile';
|
||||
|
||||
toast.add({
|
||||
severity: 'success',
|
||||
summary: 'Success',
|
||||
detail: 'File uploaded successfully!',
|
||||
life: 3000
|
||||
});
|
||||
|
||||
emit('upload', {
|
||||
fileName: uploadedFileName,
|
||||
response: xhr.response,
|
||||
files: event.files,
|
||||
inputName: props.inputName
|
||||
});
|
||||
} else {
|
||||
toast.add({
|
||||
severity: 'error',
|
||||
summary: 'Error',
|
||||
detail: `Failed to upload file. Status: ${xhr.status}`,
|
||||
life: 3000
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const handleRemove = async (event, removeUploadedFileCallback) => {
|
||||
const { file, index } = event;
|
||||
|
||||
try {
|
||||
const response = await fileUploadStore.deleteFile(file.name, props.folderName);
|
||||
|
||||
if (response.status === 200) {
|
||||
toast.add({
|
||||
severity: 'success',
|
||||
summary: 'Success',
|
||||
detail: 'File removed successfully!',
|
||||
life: 3000
|
||||
});
|
||||
|
||||
removeUploadedFileCallback(index);
|
||||
emit('remove', { fileName: file.name, inputName: props.inputName });
|
||||
} else {
|
||||
toast.add({
|
||||
severity: 'error',
|
||||
summary: 'Error',
|
||||
detail: `Failed to remove file. Status: ${response.statusText}`,
|
||||
life: 3000
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
toast.add({
|
||||
severity: 'error',
|
||||
summary: 'Error',
|
||||
detail: `Error while removing file: ${error.message}`,
|
||||
life: 3000
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const formatSize = (bytes) => {
|
||||
const k = 1024;
|
||||
const sizes = $primevue.config.locale.fileSizeTypes;
|
||||
|
||||
if (bytes === 0) {
|
||||
return `0 ${sizes[0]}`;
|
||||
}
|
||||
|
||||
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
||||
const truncatedSize = Math.trunc(bytes / Math.pow(k, i));
|
||||
|
||||
return `${truncatedSize} ${sizes[i]}`;
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<label :for="inputName">
|
||||
<b>{{ label }}</b>
|
||||
<i class="pi pi-info-circle text-violet-600 cursor-pointer" v-tooltip="tooltipText"></i>
|
||||
</label>
|
||||
<div>
|
||||
<FileUpload
|
||||
:name="inputName"
|
||||
:customUpload="false"
|
||||
:url="uploadUrl"
|
||||
@upload="handleUpload"
|
||||
:multiple="isMultiple"
|
||||
:accept="acceptedFormats"
|
||||
auto
|
||||
:showUploadButton="false"
|
||||
:showCancelButton="false"
|
||||
:maxFileSize="52428800"
|
||||
:invalidFileSizeMessage="'Invalid file size, file size should be smaller than 20 MB'"
|
||||
v-model:files="localUploadedFiles"
|
||||
@before-send="onBeforeSend"
|
||||
>
|
||||
<template #content="{ uploadedFiles, removeUploadedFileCallback }">
|
||||
<div class="pt-4">
|
||||
<div v-if="uploadedFiles.length > 0">
|
||||
<table class="table-auto w-full border-collapse border border-gray-200">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="border border-gray-300 p-2">Name</th>
|
||||
<th class="border border-gray-300 p-2">Dimension</th>
|
||||
<th class="border border-gray-300 p-2">Status</th>
|
||||
<th class="border border-gray-300 p-2">Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="(file, index) in uploadedFiles" :key="file.name + file.size" class="hover:bg-gray-50">
|
||||
<td class="border border-gray-300 p-2">{{ file.name }}</td>
|
||||
<td class="border border-gray-300 p-2">{{ formatSize(file.size) }}</td>
|
||||
<td class="border border-gray-300 p-2">
|
||||
<Badge value="UPLOADED" severity="success" />
|
||||
</td>
|
||||
<td class="border border-gray-300 p-2">
|
||||
<Button label="Remove" @click="handleRemove({ file, index }, removeUploadedFileCallback)" />
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template #empty>
|
||||
<div class="flex items-center justify-center flex-col">
|
||||
<div class="!border !border-violet-600 !rounded-full !w-24 !h-24 flex items-center justify-center">
|
||||
<i class="pi pi-cloud-upload !text-4xl !-violet-600"></i>
|
||||
</div>
|
||||
<p class="mt-2 mb-2 text-m">Drag and drop files here to upload.</p>
|
||||
</div>
|
||||
</template>
|
||||
</FileUpload>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
Reference in New Issue
Block a user