fix(pct/eml): bouton 'Telecharger .eml' via delegation document-level

Bug: le handler etait attache via getElementById('pct-btn-eml') au moment du <script>
mais la modal HTML est plus bas dans le DOM -> element pas encore parse -> bind silencieux KO.

Fix: utilise document.addEventListener('click', ...) avec delegation
(closest('button') + check sur t.id). Marche meme si la modal est ajoutee/retiree.
Inclus aussi pct-btn-cancel et pct-modal-bg dans la delegation pour coherence.
This commit is contained in:
Pierre & Lumière 2026-05-07 22:40:41 +02:00
parent abfb1bec7f
commit 69ea7aa09a

View File

@ -541,41 +541,52 @@
document.addEventListener('keydown', e => {
if (e.key === 'Escape') closePctModal();
});
document.getElementById('pct-btn-cancel')?.addEventListener('click', closePctModal);
document.getElementById('pct-modal-bg')?.addEventListener('click', closePctModal);
// Bouton "Télécharger .eml" : génère un fichier mail prêt à ouvrir dans Outlook web/New
document.getElementById('pct-btn-eml')?.addEventListener('click', async () => {
const checkedAny = Array.from(tbody.querySelectorAll('input.row-cb:checked'));
const ids = checkedAny.map(cb => cb.dataset.id);
if (!ids.length) { alert('Sélection vide'); return; }
try {
const r = await fetch('/patching/import/pct-prevenance/download-eml', {
method: 'POST', headers: {'Content-Type':'application/json'},
credentials: 'same-origin',
body: JSON.stringify({row_ids: ids}),
});
if (!r.ok) {
const j = await r.json().catch(()=>({}));
alert('Erreur génération .eml : ' + (j.msg || r.status));
return;
}
// Récupère le nom de fichier depuis Content-Disposition
let filename = 'prevenance_pct.eml';
const cd = r.headers.get('Content-Disposition') || '';
const m = cd.match(/filename="?([^"]+)"?/i);
if (m) filename = m[1];
const blob = await r.blob();
// Force download
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url; a.download = filename;
document.body.appendChild(a); a.click();
document.body.removeChild(a);
setTimeout(() => URL.revokeObjectURL(url), 1000);
} catch (e) {
alert('Erreur réseau : ' + e);
// Délégation document-level pour les boutons modaux (bind robuste même si
// la modal HTML est parsée APRÈS ce script).
document.addEventListener('click', async (ev) => {
const t = ev.target.closest('button');
if (!t) return;
if (t.id === 'pct-btn-cancel' || t.id === 'pct-modal-bg') {
closePctModal();
return;
}
if (t.id === 'pct-btn-eml') {
const checkedAny = Array.from(tbody.querySelectorAll('input.row-cb:checked'));
const ids = checkedAny.map(cb => cb.dataset.id);
if (!ids.length) { alert('Sélection vide'); return; }
t.disabled = true; const orig = t.textContent; t.textContent = '⏳ Génération .eml…';
try {
const r = await fetch('/patching/import/pct-prevenance/download-eml', {
method: 'POST', headers: {'Content-Type':'application/json'},
credentials: 'same-origin',
body: JSON.stringify({row_ids: ids}),
});
if (!r.ok) {
const j = await r.json().catch(()=>({}));
alert('Erreur génération .eml : ' + (j.msg || r.status));
return;
}
let filename = 'prevenance_pct.eml';
const cd = r.headers.get('Content-Disposition') || '';
const m = cd.match(/filename="?([^"]+)"?/i);
if (m) filename = m[1];
const blob = await r.blob();
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url; a.download = filename;
document.body.appendChild(a); a.click();
document.body.removeChild(a);
setTimeout(() => URL.revokeObjectURL(url), 1000);
} catch (e) {
alert('Erreur réseau : ' + e);
} finally {
t.disabled = false; t.textContent = orig;
}
}
});
// Click hors modal sur le BG ferme la modal (delegation aussi)
document.addEventListener('click', (ev) => {
if (ev.target && ev.target.id === 'pct-modal-bg') closePctModal();
});
})();
</script>