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.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,32 +613,63 @@ async function uploadFile() {
|
|||||||
btn.disabled = true;
|
btn.disabled = true;
|
||||||
btn.textContent = 'UPLOADING...';
|
btn.textContent = 'UPLOADING...';
|
||||||
showUploadStatus('Uploading...', '');
|
showUploadStatus('Uploading...', '');
|
||||||
try {
|
showUploadProgress(true);
|
||||||
var form = new FormData();
|
|
||||||
form.append('file', pendingUploadFile);
|
var xhr = new XMLHttpRequest();
|
||||||
var res = await fetch('/api/upload', { method: 'POST', body: form });
|
xhr.open('POST', '/api/upload');
|
||||||
var data = await res.json();
|
|
||||||
if (!data.success) {
|
xhr.upload.onprogress = function(e) {
|
||||||
showUploadStatus(data.error || 'Upload failed', 'error');
|
if (e.lengthComputable) {
|
||||||
btn.disabled = false;
|
var pct = Math.round((e.loaded / e.total) * 100);
|
||||||
btn.textContent = 'UPLOAD';
|
document.getElementById('upload-progress-bar').style.width = pct + '%';
|
||||||
return;
|
document.getElementById('upload-progress-percent').textContent = pct + '%';
|
||||||
}
|
}
|
||||||
showUploadStatus('Upload complete: ' + data.name, 'success');
|
};
|
||||||
selectedFile = data.path;
|
|
||||||
document.getElementById('btn-start').disabled = false;
|
xhr.onload = function() {
|
||||||
document.getElementById('btn-download').disabled = false;
|
showUploadProgress(false);
|
||||||
document.getElementById('btn-delete').disabled = false;
|
try {
|
||||||
document.getElementById('pending-filename').textContent = 'no file chosen';
|
var data = JSON.parse(xhr.responseText);
|
||||||
document.getElementById('pending-filename').classList.remove('has-file');
|
if (!data.success) {
|
||||||
pendingUploadFile = null;
|
showUploadStatus(data.error || 'Upload failed', 'error');
|
||||||
loadUploads();
|
btn.disabled = false;
|
||||||
loadBatchResult(data.path);
|
btn.textContent = 'UPLOAD';
|
||||||
} catch (err) {
|
return;
|
||||||
showUploadStatus('Upload error: ' + err.message, 'error');
|
}
|
||||||
}
|
showUploadStatus('Upload complete: ' + data.name, 'success');
|
||||||
btn.disabled = false;
|
selectedFile = data.path;
|
||||||
btn.textContent = 'UPLOAD';
|
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) {
|
function selectFile(path, name) {
|
||||||
|
|||||||
Reference in new issue
Block a user