feat(patching/import): boutons d'action toujours cliquables + alerte si aucune selection

Avant: les boutons (+ Ajouter, Reporter, Annuler, Pré-patching) etaient grises (disabled)
quand aucune row n'etait selectionnee, et le clic ne provoquait rien -> confusion.

Apres:
- Boutons toujours cliquables (HTML disabled retire)
- Atténuation visuelle (opacity-50) quand selection vide pour feedback
- Au clic sans selection: alerte 'Veuillez selectionner au moins un serveur.'
- Btn Pre-patching: si selection mais aucun eligible, alerte indiquant
  d'utiliser '+ Ajouter au patching' d'abord
This commit is contained in:
Pierre & Lumière 2026-05-07 19:51:32 +02:00
parent e448d8885b
commit 040448696b

View File

@ -124,17 +124,17 @@
<span class="text-xs text-gray-400" id="selection-count">0 sélectionné(s)</span>
<div class="flex-1"></div>
{% if can_import %}
<button id="btn-add-eligible" class="btn-sm bg-cyber-green/20 text-cyber-green px-3 py-1 text-xs" disabled title="Marque les lignes comme éligibles au patching">
<button id="btn-add-eligible" class="btn-sm bg-cyber-green/20 text-cyber-green px-3 py-1 text-xs" title="Marque les lignes sélectionnées comme éligibles au patching">
+ Ajouter au patching
</button>
<button id="btn-report" class="btn-sm bg-cyber-blue/20 text-cyber-blue px-3 py-1 text-xs" disabled title="Reporter à une autre semaine">
<button id="btn-report" class="btn-sm bg-cyber-blue/20 text-cyber-blue px-3 py-1 text-xs" title="Reporter les lignes sélectionnées à une autre semaine">
⤳ Reporter
</button>
<button id="btn-unset" class="btn-sm bg-cyber-border text-gray-400 px-3 py-1 text-xs" disabled title="Annuler éligibilité / report">
<button id="btn-unset" class="btn-sm bg-cyber-border text-gray-400 px-3 py-1 text-xs" title="Annuler éligibilité / report sur les lignes sélectionnées">
Annuler
</button>
{% endif %}
<button id="btn-prepatch" class="btn-sm bg-cyber-yellow/20 text-cyber-yellow px-3 py-1 text-xs" disabled title="Lancer le pré-patching (rows éligibles uniquement)">
<button id="btn-prepatch" class="btn-sm bg-cyber-yellow/20 text-cyber-yellow px-3 py-1 text-xs" title="Lancer le pré-patching (rows éligibles uniquement)">
Pré-patching →
</button>
</div>
@ -239,12 +239,18 @@
const allVisibleChecked = visibleCb.length > 0 && Array.from(visibleCb).every(cb => cb.checked);
selAll.checked = allVisibleChecked;
selAllHead.checked = allVisibleChecked;
// Boutons toujours cliquables : si rien de sélectionné on alerte au clic
// (au lieu de griser un bouton qu'on ne peut pas atteindre).
// Atténuation visuelle quand pas de sélection pour donner un feedback :
const hasSel = checked > 0;
if (btnAddElig) btnAddElig.disabled = !hasSel;
if (btnReport) btnReport.disabled = !hasSel;
if (btnUnset) btnUnset.disabled = !hasSel;
// Pré-patching : actif uniquement si au moins 1 row éligible sélectionnée
btnPre.disabled = eligibleSelected === 0;
const dimIfEmpty = (btn, active) => {
if (!btn) return;
btn.classList.toggle('opacity-50', !active);
};
dimIfEmpty(btnAddElig, hasSel);
dimIfEmpty(btnReport, hasSel);
dimIfEmpty(btnUnset, hasSel);
dimIfEmpty(btnPre, eligibleSelected > 0);
}
function getSelectedRowIds(){
@ -410,13 +416,13 @@
if (btnAddElig) btnAddElig.addEventListener('click', async () => {
const ids = getSelectedRowIds();
if (!ids.length) return;
if (!ids.length) { alert('Veuillez sélectionner au moins un serveur.'); return; }
if (!confirm('Marquer ' + ids.length + ' ligne(s) comme éligibles au patching ?')) return;
if (await postAction({row_ids: ids, action: 'eligible'})) await reloadCurrentSheet();
});
if (btnReport) btnReport.addEventListener('click', async () => {
const ids = getSelectedRowIds();
if (!ids.length) return;
if (!ids.length) { alert('Veuillez sélectionner au moins un serveur.'); return; }
const target = (prompt('Reporter vers quelle semaine ? (ex: S23)') || '').trim();
if (!target) return;
if (!/^S\d{1,2}$/i.test(target)) { alert('Format attendu : Sxx (ex S23)'); return; }
@ -425,7 +431,7 @@
});
if (btnUnset) btnUnset.addEventListener('click', async () => {
const ids = getSelectedRowIds();
if (!ids.length) return;
if (!ids.length) { alert('Veuillez sélectionner au moins un serveur.'); return; }
if (!confirm('Annuler éligibilité ET report sur ' + ids.length + ' ligne(s) ?')) return;
if (await postAction({row_ids: ids, action: 'unset_eligible'})) {
await postAction({row_ids: ids, action: 'unset_report'});
@ -433,11 +439,15 @@
}
});
btnPre.addEventListener('click', () => {
const ids = Array.from(tbody.querySelectorAll('input.row-cb:checked'))
const checkedAny = Array.from(tbody.querySelectorAll('input.row-cb:checked'));
if (!checkedAny.length) { alert('Veuillez sélectionner au moins un serveur.'); return; }
const ids = checkedAny
.filter(cb => cb.dataset.eligible === '1')
.map(cb => cb.dataset.id);
if (!ids.length) { alert('Aucune ligne éligible sélectionnée.'); return; }
// Étape B : workflow iexec à brancher
if (!ids.length) {
alert('Aucun serveur sélectionné n\'est éligible. Marque-les d\'abord avec "+ Ajouter au patching".');
return;
}
window.location.href = '/patching/iexec?row_ids=' + ids.join(',');
});
})();