feat(webui): quality of life improvements for upload dialog
ci/woodpecker/push/woodpecker Pipeline was successful
Details
ci/woodpecker/push/woodpecker Pipeline was successful
Details
- when uploading, warn before closing tab - allow cancelling in progress uploads - when uploading multiple files, scroll to the current filefeat/users
parent
669b348160
commit
1f270d6dc7
|
@ -21,10 +21,13 @@
|
||||||
let files: File[] = [];
|
let files: File[] = [];
|
||||||
let URLs: string[] = [];
|
let URLs: string[] = [];
|
||||||
let uploading = false;
|
let uploading = false;
|
||||||
|
let abortController: AbortController | undefined;
|
||||||
|
|
||||||
let progress: Record<string, number> = {};
|
let progress: Record<string, number> = {};
|
||||||
let totalProgress: number | undefined;
|
let totalProgress: number | undefined;
|
||||||
|
|
||||||
|
let filesElement: HTMLDivElement;
|
||||||
|
|
||||||
$: visible = files.length + URLs.length > 0;
|
$: visible = files.length + URLs.length > 0;
|
||||||
|
|
||||||
addEmitter.on('files', (ev) => {
|
addEmitter.on('files', (ev) => {
|
||||||
|
@ -40,9 +43,15 @@
|
||||||
uploading = true;
|
uploading = true;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
abortController = new AbortController();
|
||||||
const addresses: string[] = [];
|
const addresses: string[] = [];
|
||||||
for (const file of files) {
|
for (const [idx, file] of files.entries()) {
|
||||||
|
filesElement
|
||||||
|
?.querySelectorAll('.entry')
|
||||||
|
[idx]?.scrollIntoView({ behavior: 'smooth', block: 'center' });
|
||||||
|
|
||||||
const address = await api.putBlob(file, {
|
const address = await api.putBlob(file, {
|
||||||
|
abortController,
|
||||||
onProgress: (p) => {
|
onProgress: (p) => {
|
||||||
progress[file.name] = (p.loaded / p.total) * 100;
|
progress[file.name] = (p.loaded / p.total) * 100;
|
||||||
totalProgress = Object.values(progress).reduce((a, b) => a + b, 0) / files.length;
|
totalProgress = Object.values(progress).reduce((a, b) => a + b, 0) / files.length;
|
||||||
|
@ -50,6 +59,10 @@
|
||||||
timeout: -1
|
timeout: -1
|
||||||
});
|
});
|
||||||
addresses.push(address);
|
addresses.push(address);
|
||||||
|
|
||||||
|
if (!uploading) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (addresses.length == 1) {
|
if (addresses.length == 1) {
|
||||||
|
@ -67,11 +80,16 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
function reset() {
|
function reset() {
|
||||||
if (!uploading) {
|
if (uploading) {
|
||||||
files = [];
|
const msg = $i18n.t('Are you sure you want to cancel the upload?');
|
||||||
URLs = [];
|
if (!confirm(msg)) return;
|
||||||
progress = {};
|
|
||||||
}
|
}
|
||||||
|
abortController?.abort();
|
||||||
|
|
||||||
|
files = [];
|
||||||
|
URLs = [];
|
||||||
|
progress = {};
|
||||||
|
uploading = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
function onKeydown(event: KeyboardEvent) {
|
function onKeydown(event: KeyboardEvent) {
|
||||||
|
@ -84,14 +102,22 @@
|
||||||
reset();
|
reset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function onBeforeUnload(ev: BeforeUnloadEvent) {
|
||||||
|
if (files.length || uploading) {
|
||||||
|
ev.preventDefault();
|
||||||
|
ev.returnValue = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<svelte:window on:beforeunload={onBeforeUnload} />
|
||||||
<svelte:body on:keydown={onKeydown} />
|
<svelte:body on:keydown={onKeydown} />
|
||||||
|
|
||||||
<!-- svelte-ignore a11y-click-events-have-key-events a11y-no-static-element-interactions -->
|
<!-- svelte-ignore a11y-click-events-have-key-events a11y-no-static-element-interactions -->
|
||||||
<div class="addmodal-container" class:visible class:uploading on:click={reset}>
|
<div class="addmodal-container" class:visible class:uploading on:click={reset}>
|
||||||
<div class="addmodal" on:click|stopPropagation>
|
<div class="addmodal" on:click|stopPropagation>
|
||||||
<div class="files">
|
<div class="files" bind:this={filesElement}>
|
||||||
{#each files as file}
|
{#each files as file}
|
||||||
<div class="entry">
|
<div class="entry">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
|
|
Loading…
Reference in New Issue