Upload dialog hotfixed + clear button

This commit is contained in:
Georges-Antoine Assi
2024-08-26 12:58:38 -04:00
parent e55401fa95
commit 3e9f59c546
6 changed files with 90 additions and 42 deletions

2
.gitignore vendored
View File

@@ -19,6 +19,8 @@ coverage
# Editor directories and files
.vscode
.zed
pyrightconfig.json
!.vscode/extensions.json
!.vscode/settings.json
!.vscode/tasks.json

View File

@@ -50,7 +50,14 @@ async def add_rom(request: Request):
detail="No platform ID or filename provided",
) from None
platform_fs_slug = db_platform_handler.get_platform(int(platform_id)).fs_slug
db_platform = db_platform_handler.get_platform(int(platform_id))
if not db_platform:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="Platform not found",
) from None
platform_fs_slug = db_platform.fs_slug
roms_path = fs_rom_handler.build_upload_file_path(platform_fs_slug)
log.info(f"Uploading file to {platform_fs_slug}")

View File

@@ -52,9 +52,7 @@ emitter?.on("showUploadRomDialog", (platformWhereUpload) => {
})
.catch(({ response, message }) => {
emitter?.emit("snackbarShow", {
msg: `Unable to upload roms: ${
response?.data?.detail || response?.statusText || message
}`,
msg: `Unable to upload roms: ${response?.data?.detail || response?.statusText || message}`,
icon: "mdi-close-circle",
color: "red",
timeout: 4000,
@@ -101,13 +99,15 @@ async function uploadRoms() {
platformId: platformId,
})
.then((responses: PromiseSettledResult<unknown>[]) => {
uploadStore.clear();
const successfulUploads = responses.filter(
(d) => d.status == "fulfilled"
(d) => d.status == "fulfilled",
);
const failedUploads = responses.filter((d) => d.status == "rejected");
if (failedUploads.length == 0) {
uploadStore.clearAll();
}
if (successfulUploads.length == 0) {
return emitter?.emit("snackbarShow", {
msg: `All files skipped, nothing to upload.`,
@@ -137,9 +137,7 @@ async function uploadRoms() {
})
.catch(({ response, message }) => {
emitter?.emit("snackbarShow", {
msg: `Unable to upload roms: ${
response?.data?.detail || response?.statusText || message
}`,
msg: `Unable to upload roms: ${response?.data?.detail || response?.statusText || message}`,
icon: "mdi-close-circle",
color: "red",
timeout: 4000,
@@ -156,7 +154,7 @@ function triggerFileInput() {
function removeRomFromList(romName: string) {
filesToUpload.value = filesToUpload.value.filter(
(rom) => rom.name !== romName
(rom) => rom.name !== romName,
);
}

View File

@@ -10,6 +10,10 @@ const uploadStore = storeUpload();
const { files } = storeToRefs(uploadStore);
const show = ref(false);
function clearFinished() {
uploadStore.clearFinished();
}
watch(files, (newList) => {
show.value = newList.length > 0;
});
@@ -30,41 +34,64 @@ watch(files, (newList) => {
<v-list-item
v-for="file in files"
class="py-2 px-4"
:disabled="file.finished"
:disabled="file.finished && !file.failed"
>
<v-list-item-title class="d-flex justify-space-between">
{{ file.filename }}
<v-icon
:icon="file.finished ? `mdi-check` : `mdi-loading mdi-spin`"
:color="file.finished ? `green` : `white`"
class="mx-2"
/>
</v-list-item-title>
<template v-if="file.progress > 0 && !file.finished">
<v-progress-linear
v-model="file.progress"
height="4"
color="white"
class="mt-1"
/>
<div class="upload-speeds d-flex justify-space-between mt-1">
<div>{{ formatBytes(file.rate) }}/s</div>
<div>
{{ formatBytes(file.loaded) }} /
{{ formatBytes(file.total) }}
</div>
</div>
<template v-if="file.failed">
<v-list-item-title class="d-flex justify-space-between">
{{ file.filename }}
<v-icon :icon="`mdi-close`" :color="`red`" class="mx-2" />
</v-list-item-title>
<v-list-item-subtitle class="text-red mt-1">
{{ file.failureReason }}
</v-list-item-subtitle>
</template>
<template v-if="file.finished">
<div class="upload-speeds d-flex justify-space-between mt-1">
<div />
<div>
{{ formatBytes(file.total) }}
<template v-else>
<v-list-item-title class="d-flex justify-space-between">
{{ file.filename }}
<v-icon
:icon="file.finished ? `mdi-check` : `mdi-loading mdi-spin`"
:color="file.finished ? `green` : `white`"
class="mx-2"
/>
</v-list-item-title>
<template v-if="file.progress > 0 && !file.finished">
<v-progress-linear
v-model="file.progress"
height="4"
color="white"
class="mt-1"
/>
<div class="upload-speeds d-flex justify-space-between mt-1">
<div>{{ formatBytes(file.rate) }}/s</div>
<div>
{{ formatBytes(file.loaded) }} /
{{ formatBytes(file.total) }}
</div>
</div>
</div>
</template>
<template v-if="file.finished">
<div class="upload-speeds d-flex justify-space-between mt-1">
<div />
<div>
{{ formatBytes(file.total) }}
</div>
</div>
</template>
</template>
</v-list-item>
</v-list>
<div class="text-center">
<v-btn
size="small"
variant="tonal"
class="my-2"
color="romm-accent-1"
:disabled="!files.some((f) => f.finished || f.failed)"
@click="clearFinished"
>
Clear finished
</v-btn>
</div>
</v-snackbar>
</template>

View File

@@ -39,7 +39,7 @@ async function uploadRoms({
})
.then(resolve)
.catch((error) => {
console.error("Failed to upload file", file.name, error);
uploadStore.fail(file.name, error.response?.data?.detail);
reject(error);
});
});

View File

@@ -8,6 +8,8 @@ class UploadingFile {
loaded: number;
rate: number;
finished: boolean;
failed: boolean;
failureReason: string;
constructor(filename: string) {
this.filename = filename;
@@ -16,6 +18,8 @@ class UploadingFile {
this.loaded = 0;
this.rate = 0;
this.finished = false;
this.failed = false;
this.failureReason = "";
}
}
@@ -39,7 +43,17 @@ export default defineStore("upload", {
file.rate = progressEvent.rate || file.rate;
file.finished = progressEvent.loaded === progressEvent.total;
},
clear() {
fail(filename: string, reason: string) {
const file = this.files.find((f) => f.filename === filename);
if (!file) return;
file.failed = true;
file.failureReason = reason;
},
clearFinished() {
this.files = this.files.filter((f) => !f.finished && !f.failed);
},
clearAll() {
this.files = [];
},
},