Add upload progress bar to recounting upload dashboard
This commit is contained in:
1 parent
bcceaae626
commit
79656cd661
1 file changed
+95
-26
@@ -349,6 +349,32 @@
|
||||
.upload-status.success { color: var(--accent4); }
|
||||
.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 {
|
||||
font-family: 'Orbitron', sans-serif; font-size: 10px; letter-spacing: 2px;
|
||||
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>
|
||||
</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>
|
||||
|
||||
<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('upload-status').textContent = '';
|
||||
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) {
|
||||
@@ -566,7 +604,7 @@ function showUploadStatus(msg, cls) {
|
||||
el.className = 'upload-status ' + (cls || '');
|
||||
}
|
||||
|
||||
async function uploadFile() {
|
||||
function uploadFile() {
|
||||
if (!pendingUploadFile) {
|
||||
showUploadStatus('Pick a file first', 'error');
|
||||
return;
|
||||
@@ -575,32 +613,63 @@ async function uploadFile() {
|
||||
btn.disabled = true;
|
||||
btn.textContent = 'UPLOADING...';
|
||||
showUploadStatus('Uploading...', '');
|
||||
try {
|
||||
var form = new FormData();
|
||||
form.append('file', pendingUploadFile);
|
||||
var res = await fetch('/api/upload', { method: 'POST', body: form });
|
||||
var data = await res.json();
|
||||
if (!data.success) {
|
||||
showUploadStatus(data.error || 'Upload failed', 'error');
|
||||
btn.disabled = false;
|
||||
btn.textContent = 'UPLOAD';
|
||||
return;
|
||||
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 + '%';
|
||||
}
|
||||
showUploadStatus('Upload complete: ' + data.name, 'success');
|
||||
selectedFile = data.path;
|
||||
document.getElementById('btn-start').disabled = false;
|
||||
document.getElementById('btn-download').disabled = false;
|
||||
document.getElementById('btn-delete').disabled = false;
|
||||
document.getElementById('pending-filename').textContent = 'no file chosen';
|
||||
document.getElementById('pending-filename').classList.remove('has-file');
|
||||
pendingUploadFile = null;
|
||||
loadUploads();
|
||||
loadBatchResult(data.path);
|
||||
} catch (err) {
|
||||
showUploadStatus('Upload error: ' + err.message, 'error');
|
||||
}
|
||||
btn.disabled = false;
|
||||
btn.textContent = 'UPLOAD';
|
||||
};
|
||||
|
||||
xhr.onload = function() {
|
||||
showUploadProgress(false);
|
||||
try {
|
||||
var data = JSON.parse(xhr.responseText);
|
||||
if (!data.success) {
|
||||
showUploadStatus(data.error || 'Upload failed', 'error');
|
||||
btn.disabled = false;
|
||||
btn.textContent = 'UPLOAD';
|
||||
return;
|
||||
}
|
||||
showUploadStatus('Upload complete: ' + data.name, 'success');
|
||||
selectedFile = data.path;
|
||||
document.getElementById('btn-start').disabled = false;
|
||||
document.getElementById('btn-download').disabled = false;
|
||||
document.getElementById('btn-delete').disabled = false;
|
||||
document.getElementById('pending-filename').textContent = 'no file chosen';
|
||||
document.getElementById('pending-filename').classList.remove('has-file');
|
||||
pendingUploadFile = null;
|
||||
loadUploads();
|
||||
loadBatchResult(data.path);
|
||||
} catch (err) {
|
||||
showUploadStatus('Upload error: ' + err.message, 'error');
|
||||
}
|
||||
btn.disabled = false;
|
||||
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) {
|
||||
|
||||
Reference in new issue
Block a user