Files
xamxam/app/public/assets/js/upload-progress.js

170 lines
6.4 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* upload-progress.js
*
* Intercepts admin form submissions with files and submits via XMLHttpRequest.
* Polls GET /admin/actions/upload-progress.php?token=xxx for server-side
* processing progress (PeerTube uploads, file moves).
*
* Progress display:
* 0%25% : browser → server upload (XHR upload.progress)
* 25%99% : server processing (polled from progress endpoint)
* 100% : response received — "Téléversé avec succès", then redirect
*/
(() => {
'use strict';
const FORMS = document.querySelectorAll('form[data-upload-progress]');
if (!FORMS.length) return;
const POLL_INTERVAL = 400;
const UPLOAD_CAP = 25;
const PROCESSING_MAX = 99;
const SUCCESS_DELAY = 800;
for (const form of FORMS) {
const progressWrap = form.querySelector('#upload-progress-wrap');
const progressBar = form.querySelector('#upload-progress-bar');
const progressLabel = form.querySelector('#upload-progress-label');
const progressFile = form.querySelector('#upload-progress-file');
const submitBtn = form.querySelector('button[type="submit"]');
const tokenInput = form.querySelector('input[name="progress_token"]');
if (!progressBar || !progressWrap) continue;
function collectFileNames() {
const names = [];
const inputs = form.querySelectorAll('input[type="file"]');
for (const fi of inputs) {
if (fi.files) {
for (const f of fi.files) {
if (f.name) names.push(f.name);
}
}
}
return names;
}
form.addEventListener('submit', function (e) {
const fileNames = collectFileNames();
if (!fileNames.length) return;
e.preventDefault();
const token = tokenInput ? tokenInput.value : '';
progressWrap.style.display = '';
progressBar.value = 0;
progressBar.removeAttribute('data-complete');
progressLabel.textContent = 'Téléversement en cours…';
progressFile.textContent = fileNames.length === 1
? fileNames[0]
: fileNames.length + ' fichiers';
if (submitBtn) submitBtn.disabled = true;
const fd = new FormData(form);
const xhr = new XMLHttpRequest();
let uploadDone = false;
let lastUploadPct = 0;
let pollingTimer = null;
/** Poll server-side progress */
function startPolling() {
if (pollingTimer || !token) return;
progressLabel.textContent = 'Traitement en cours…';
pollingTimer = setInterval(function () {
fetch('/admin/actions/upload-progress.php?token=' + encodeURIComponent(token))
.then(function (r) { return r.json(); })
.then(function (data) {
if (data && data.stage && data.stage !== 'upload') {
const pct = Math.min(PROCESSING_MAX, Math.max(UPLOAD_CAP, data.pct || UPLOAD_CAP));
progressBar.value = pct;
if (data.file) {
progressFile.textContent = data.file;
}
}
})
.catch(function () { /* ignore poll errors */ });
}, POLL_INTERVAL);
}
function stopPolling() {
if (pollingTimer) {
clearInterval(pollingTimer);
pollingTimer = null;
}
}
function finishSuccess() {
stopPolling();
progressBar.value = 100;
progressBar.setAttribute('data-complete', '');
progressLabel.textContent = 'Téléversé avec succès';
progressFile.textContent = '';
}
// ── Upload phase (0% → UPLOAD_CAP) ──
xhr.upload.addEventListener('progress', function (evt) {
if (evt.lengthComputable) {
const rawPct = Math.round((evt.loaded / evt.total) * 100);
const scaled = Math.round((rawPct / 100) * UPLOAD_CAP);
if (scaled > lastUploadPct) {
lastUploadPct = scaled;
progressBar.value = scaled;
}
}
});
xhr.upload.addEventListener('loadend', function () {
uploadDone = true;
progressBar.value = UPLOAD_CAP;
startPolling();
});
// ── Response handling ──
xhr.addEventListener('readystatechange', function () {
if (xhr.readyState !== XMLHttpRequest.DONE) return;
stopPolling();
if (xhr.status >= 200 && xhr.status < 300) {
finishSuccess();
setTimeout(function () {
const finalUrl = xhr.responseURL || '';
if (finalUrl && finalUrl !== form.action) {
window.location.href = finalUrl;
} else {
document.open();
document.write(xhr.responseText);
document.close();
}
}, SUCCESS_DELAY);
} else {
progressLabel.textContent = 'Erreur';
progressFile.textContent = 'Échec du téléversement';
document.open();
document.write(xhr.responseText);
document.close();
}
});
xhr.addEventListener('error', function () {
stopPolling();
progressLabel.textContent = 'Erreur réseau';
progressFile.textContent = '';
if (submitBtn) submitBtn.disabled = false;
});
xhr.addEventListener('abort', function () {
stopPolling();
progressWrap.style.display = 'none';
if (submitBtn) submitBtn.disabled = false;
});
xhr.open('POST', form.action, true);
xhr.send(fd);
});
}
})();