Add upload progress bar to recounting upload dashboard

This commit is contained in:
proitlab committed 2026-08-05 00:39:47 +07:00
1 parent bcceaae626
commit 79656cd661
1 file changed
+74 -5
+74 -5
View File
@@ -349,6 +349,32 @@
.upload-status.success { color: var(--accent4); } .upload-status.success { color: var(--accent4); }
.upload-status.error { color: var(--accent3); } .upload-status.error { color: var(--accent3); }
.upload-progress {
display: none;
width: 100%;
height: 6px;
background: var(--cell-bg);
border: 1px solid var(--cell-border);
border-radius: 3px;
margin-top: 10px;
overflow: hidden;
}
.upload-progress .upload-progress-bar {
height: 100%;
width: 0%;
background: linear-gradient(90deg, var(--accent), var(--accent2));
border-radius: 3px;
transition: width 0.15s ease;
}
.upload-progress-percent {
display: none;
font-size: 8px;
color: var(--text-secondary);
letter-spacing: 1px;
text-align: center;
margin-top: 4px;
}
.btn { .btn {
font-family: 'Orbitron', sans-serif; font-size: 10px; letter-spacing: 2px; font-family: 'Orbitron', sans-serif; font-size: 10px; letter-spacing: 2px;
padding: 8px 16px; border-radius: 7px; cursor: pointer; font-weight: 600; padding: 8px 16px; border-radius: 7px; cursor: pointer; font-weight: 600;
@@ -482,6 +508,10 @@
<button class="btn btn-ghost" id="btn-upload" onclick="uploadFile()">UPLOAD</button> <button class="btn btn-ghost" id="btn-upload" onclick="uploadFile()">UPLOAD</button>
</div> </div>
<div class="upload-progress" id="upload-progress">
<div class="upload-progress-bar" id="upload-progress-bar"></div>
</div>
<div class="upload-progress-percent" id="upload-progress-percent"></div>
<div class="upload-status" id="upload-status"></div> <div class="upload-status" id="upload-status"></div>
<input type="file" id="upload-file-input" accept=".mp4" style="display:none" <input type="file" id="upload-file-input" accept=".mp4" style="display:none"
@@ -558,6 +588,14 @@ function setPendingFile(file) {
document.getElementById('pending-filename').classList.add('has-file'); document.getElementById('pending-filename').classList.add('has-file');
document.getElementById('upload-status').textContent = ''; document.getElementById('upload-status').textContent = '';
document.getElementById('upload-status').className = 'upload-status'; document.getElementById('upload-status').className = 'upload-status';
showUploadProgress(false);
}
function showUploadProgress(show) {
document.getElementById('upload-progress').style.display = show ? 'block' : 'none';
document.getElementById('upload-progress-percent').style.display = show ? 'block' : 'none';
document.getElementById('upload-progress-bar').style.width = '0%';
document.getElementById('upload-progress-percent').textContent = '';
} }
function showUploadStatus(msg, cls) { function showUploadStatus(msg, cls) {
@@ -566,7 +604,7 @@ function showUploadStatus(msg, cls) {
el.className = 'upload-status ' + (cls || ''); el.className = 'upload-status ' + (cls || '');
} }
async function uploadFile() { function uploadFile() {
if (!pendingUploadFile) { if (!pendingUploadFile) {
showUploadStatus('Pick a file first', 'error'); showUploadStatus('Pick a file first', 'error');
return; return;
@@ -575,11 +613,23 @@ async function uploadFile() {
btn.disabled = true; btn.disabled = true;
btn.textContent = 'UPLOADING...'; btn.textContent = 'UPLOADING...';
showUploadStatus('Uploading...', ''); showUploadStatus('Uploading...', '');
showUploadProgress(true);
var xhr = new XMLHttpRequest();
xhr.open('POST', '/api/upload');
xhr.upload.onprogress = function(e) {
if (e.lengthComputable) {
var pct = Math.round((e.loaded / e.total) * 100);
document.getElementById('upload-progress-bar').style.width = pct + '%';
document.getElementById('upload-progress-percent').textContent = pct + '%';
}
};
xhr.onload = function() {
showUploadProgress(false);
try { try {
var form = new FormData(); var data = JSON.parse(xhr.responseText);
form.append('file', pendingUploadFile);
var res = await fetch('/api/upload', { method: 'POST', body: form });
var data = await res.json();
if (!data.success) { if (!data.success) {
showUploadStatus(data.error || 'Upload failed', 'error'); showUploadStatus(data.error || 'Upload failed', 'error');
btn.disabled = false; btn.disabled = false;
@@ -601,6 +651,25 @@ async function uploadFile() {
} }
btn.disabled = false; btn.disabled = false;
btn.textContent = 'UPLOAD'; btn.textContent = 'UPLOAD';
};
xhr.onerror = function() {
showUploadProgress(false);
showUploadStatus('Upload error: network error', 'error');
btn.disabled = false;
btn.textContent = 'UPLOAD';
};
xhr.onabort = function() {
showUploadProgress(false);
showUploadStatus('Upload aborted', '');
btn.disabled = false;
btn.textContent = 'UPLOAD';
};
var form = new FormData();
form.append('file', pendingUploadFile);
xhr.send(form);
} }
function selectFile(path, name) { function selectFile(path, name) {