From 2325661df408a69c3e93f127e8d0b0807c53c176 Mon Sep 17 00:00:00 2001 From: retoor Date: Mon, 10 Nov 2025 17:59:40 +0100 Subject: [PATCH] Fixed bread crumbs. --- static/js/components/file-upload-view.js | 75 ++++++++++++++++++------ 1 file changed, 58 insertions(+), 17 deletions(-) diff --git a/static/js/components/file-upload-view.js b/static/js/components/file-upload-view.js index 42de0de..8fd1cf6 100644 --- a/static/js/components/file-upload-view.js +++ b/static/js/components/file-upload-view.js @@ -5,6 +5,7 @@ export class FileUploadView extends HTMLElement { super(); this.folderId = null; this.handleEscape = this.handleEscape.bind(this); + this.uploadItems = new Map(); } connectedCallback() { @@ -94,6 +95,8 @@ export class FileUploadView extends HTMLElement { const uploadList = this.querySelector('#upload-list'); if (!uploadList) return; + const uploadPromises = []; + for (const file of files) { const itemId = `upload-${Date.now()}-${Math.random()}`; const item = document.createElement('div'); @@ -113,22 +116,31 @@ export class FileUploadView extends HTMLElement { `; uploadList.appendChild(item); - try { - await this.uploadFile(file, itemId); - const statusEl = item.querySelector('.upload-item-status'); - if (statusEl) { - statusEl.textContent = 'Complete'; - statusEl.classList.add('success'); - } - } catch (error) { - const statusEl = item.querySelector('.upload-item-status'); - if (statusEl) { - statusEl.textContent = 'Failed: ' + error.message; - statusEl.classList.add('error'); - } - } + this.uploadItems.set(itemId, { + element: item, + progress: 0 + }); + + const promise = this.uploadFile(file, itemId) + .then(() => { + setTimeout(() => { + this.uploadItems.delete(itemId); + item.remove(); + }, 500); + }) + .catch(error => { + const statusEl = item.querySelector('.upload-item-status'); + if (statusEl) { + statusEl.textContent = 'Failed: ' + error.message; + statusEl.classList.add('error'); + } + }); + + uploadPromises.push(promise); } + await Promise.all(uploadPromises); + this.dispatchEvent(new CustomEvent('upload-complete', { bubbles: true })); setTimeout(() => { @@ -136,6 +148,19 @@ export class FileUploadView extends HTMLElement { }, 1500); } + sortUploadList() { + const uploadList = this.querySelector('#upload-list'); + if (!uploadList) return; + + const items = Array.from(this.uploadItems.entries()) + .sort((a, b) => b[1].progress - a[1].progress); + + uploadList.innerHTML = ''; + items.forEach(([itemId, data]) => { + uploadList.appendChild(data.element); + }); + } + async uploadFile(file, itemId) { const formData = new FormData(); formData.append('file', file); @@ -149,18 +174,34 @@ export class FileUploadView extends HTMLElement { xhr.upload.addEventListener('progress', (e) => { if (e.lengthComputable) { const percentComplete = (e.loaded / e.total) * 100; - const item = this.querySelector(`#${itemId}`); - if (item) { - const progressFill = item.querySelector('.progress-fill'); + const itemData = this.uploadItems.get(itemId); + if (itemData) { + itemData.progress = percentComplete; + const progressFill = itemData.element.querySelector('.progress-fill'); if (progressFill) { progressFill.style.width = percentComplete + '%'; } + this.sortUploadList(); } } }); xhr.addEventListener('load', () => { if (xhr.status >= 200 && xhr.status < 300) { + const itemData = this.uploadItems.get(itemId); + if (itemData) { + itemData.progress = 100; + const progressFill = itemData.element.querySelector('.progress-fill'); + const statusEl = itemData.element.querySelector('.upload-item-status'); + if (progressFill) { + progressFill.style.width = '100%'; + } + if (statusEl) { + statusEl.textContent = 'Complete'; + statusEl.classList.add('success'); + } + this.sortUploadList(); // Sort after completion to move completed items to top + } resolve(JSON.parse(xhr.responseText)); } else { reject(new Error(xhr.statusText));