Dashboard: boutons restart services, JH-Photomaton et reboot Pi
🚀 Deploy — JH Photomaton / 🔍 Vérification (push) Has been cancelled
🚀 Deploy — JH Photomaton / 🍓 Deploy sur le Pi (push) Has been cancelled

This commit is contained in:
2026-07-18 10:35:43 +02:00
parent 3522d2d996
commit fb35533b37
3 changed files with 148 additions and 4 deletions
+69 -1
View File
@@ -142,12 +142,19 @@
<div class="card-title">Services</div>
<div class="card">
<table class="table">
<thead><tr><th>Service</th><th>Statut</th></tr></thead>
<thead><tr><th>Service</th><th>Statut</th><th>Action</th></tr></thead>
<tbody id="services-tbody">
{% for svc in services %}
<tr>
<td>{{ svc.label }}</td>
<td><span class="badge {{ 'badge-success' if svc.active else 'badge-error' }}">{{ 'Actif' if svc.active else 'Arrêté' }}</span></td>
<td>
{% if svc.name == 'jh-photomaton' %}
<button class="btn btn-ghost btn-sm" onclick="restartSelf()">🔄 Restart</button>
{% else %}
<button class="btn btn-ghost btn-sm" onclick="restartService('{{ svc.name }}', '{{ svc.label }}')">🔄 Restart</button>
{% endif %}
</td>
</tr>
{% endfor %}
</tbody>
@@ -155,7 +162,24 @@
</div>
</div>
<!-- Actions système -->
<div class="section">
<div class="card-title">Actions système</div>
<div class="card flex gap-2" style="flex-wrap:wrap;align-items:center">
<button class="btn btn-primary btn-sm" onclick="restartSelf()">🔄 Redémarrer JH-Photomaton</button>
<button class="btn btn-danger btn-sm" onclick="rebootPi()">⚡ Redémarrer le Raspberry Pi</button>
</div>
</div>
</div>
<!-- Overlay reconnexion -->
<div id="reconnect-overlay" style="display:none;position:fixed;inset:0;background:rgba(0,0,0,.75);z-index:9999;display:none;align-items:center;justify-content:center;flex-direction:column;gap:1rem">
<div style="color:#fff;font-size:1.2rem;font-weight:600" id="reconnect-msg">Redémarrage en cours…</div>
<div style="color:#aaa;font-size:.9rem">Reconnexion automatique dans quelques secondes…</div>
<div class="spinner" style="width:40px;height:40px;border:4px solid #444;border-top-color:#4f9cf9;border-radius:50%;animation:spin 1s linear infinite"></div>
</div>
<style>@keyframes spin{to{transform:rotate(360deg)}}</style>
{% endblock %}
{% block scripts %}
@@ -324,6 +348,50 @@ async function saveEvent(isNew) {
} catch(err) { showToast('Erreur sauvegarde événement', 'error'); }
}
// ── Restart services ─────────────────────────────────────────────────────────
async function restartService(name, label) {
if (!confirm(`Redémarrer ${label} ?\nLe service sera temporairement indisponible.`)) return;
try {
await api('POST', `/api/system/service/${name}/restart`);
showToast(`🔄 ${label} redémarre…`, 'info');
} catch(e) { showToast('Erreur restart ' + name, 'error'); }
}
async function restartSelf() {
if (!confirm('Redémarrer JH-Photomaton ?\nVous serez déconnecté quelques secondes.')) return;
try {
await api('POST', '/api/system/restart-self');
showReconnectOverlay('Redémarrage de JH-Photomaton…');
} catch(e) { showToast('Erreur restart', 'error'); }
}
async function rebootPi() {
if (!confirm('⚡ ATTENTION : Redémarrer le Raspberry Pi ?\n\nTout sera arrêté (photobooth, WiFi, impression).\nLe démarrage prend environ 30 secondes.\n\nConfirmer le redémarrage ?')) return;
try {
await api('POST', '/api/system/reboot');
showReconnectOverlay('Redémarrage du Raspberry Pi…');
} catch(e) { showToast('Erreur reboot', 'error'); }
}
function showReconnectOverlay(msg) {
const overlay = document.getElementById('reconnect-overlay');
document.getElementById('reconnect-msg').textContent = msg;
overlay.style.display = 'flex';
// Attendre 5s puis commencer à sonder /api/system/ping
setTimeout(pollReconnect, 5000);
}
async function pollReconnect() {
try {
const r = await fetch('/api/system/ping');
if (r.ok) {
window.location.reload();
return;
}
} catch(e) { /* serveur pas encore là */ }
setTimeout(pollReconnect, 2000);
}
// ── Init ──────────────────────────────────────────────────────────────────────
loadQueue();
loadEvent();