diff --git a/backend/api/system_api.py b/backend/api/system_api.py
index b50884d..bb01483 100644
--- a/backend/api/system_api.py
+++ b/backend/api/system_api.py
@@ -1,5 +1,6 @@
"""API de surveillance des ressources système."""
+import asyncio
import logging
from typing import Optional
from fastapi import APIRouter, Request, Body
@@ -9,6 +10,16 @@ from pydantic import BaseModel
logger = logging.getLogger(__name__)
router = APIRouter()
+# Services autorisés pour le restart individuel (jh-photomaton a son propre endpoint)
+_ALLOWED_SERVICES = {
+ "photobooth-app",
+ "photobooth-kiosk",
+ "zoraxy",
+ "hostapd",
+ "dnsmasq",
+ "cups",
+}
+
@router.get("/system/stats")
async def system_stats(request: Request):
@@ -90,7 +101,15 @@ async def _restart_photobooth():
stderr=asyncio.subprocess.DEVNULL,
)
await proc.wait()
- logger.info("photobooth-app redémarré après changement CSS")
+ logger.info("photobooth-app redémarré")
+
+
+@router.post("/system/restart-photobooth")
+async def restart_photobooth(request: Request):
+ """Redémarre photobooth-app.service pour recharger la config (actions, etc.)."""
+ import asyncio
+ asyncio.create_task(_restart_photobooth())
+ return {"ok": True, "message": "Redémarrage de photobooth-app en cours…"}
@router.post("/system/screen/refresh")
diff --git a/frontend/templates/admin/actions.html b/frontend/templates/admin/actions.html
index 2f94b2e..ea1bc76 100644
--- a/frontend/templates/admin/actions.html
+++ b/frontend/templates/admin/actions.html
@@ -121,7 +121,12 @@
Gestion des actions
-
+
+
+
+
@@ -385,6 +390,7 @@ async function saveAction(idx) {
try {
await api('PUT', `/api/actions/photobooth/${realIdx}`, updates);
showToast('✅ Action sauvegardée', 'success');
+ showRestartBtn();
await loadAll();
} catch(e) {
showToast(`❌ Erreur: ${e.message}`, 'error');
@@ -397,6 +403,7 @@ async function cloneAction(idx) {
try {
await api('POST', `/api/actions/photobooth/${realIdx}/clone`);
showToast('⧉ Action dupliquée', 'success');
+ showRestartBtn();
await loadAll();
} catch(e) { showToast(`❌ ${e.message}`, 'error'); }
}
@@ -408,6 +415,7 @@ async function deleteAction(idx) {
try {
await api('DELETE', `/api/actions/photobooth/${realIdx}`);
showToast(`🗑 « ${name} » supprimée`, 'info');
+ showRestartBtn();
await loadAll();
} catch(e) { showToast(`❌ ${e.message}`, 'error'); }
}
@@ -418,6 +426,7 @@ async function newAction() {
try {
await api('POST', '/api/actions/photobooth', { name: name.trim() || 'Nouvelle action' });
showToast('✅ Action créée', 'success');
+ showRestartBtn();
await loadAll();
} catch(e) { showToast(`❌ ${e.message}`, 'error'); }
}
@@ -481,7 +490,8 @@ async function saveOrder() {
const order = actions.map(a => a._index);
try {
await api('PUT', '/api/actions/photobooth/reorder', order);
- showToast('✅ Ordre sauvegardé — redémarrez photobooth-app pour appliquer', 'success', 7000);
+ showToast('✅ Ordre sauvegardé', 'success');
+ showRestartBtn();
await loadAll();
} catch(e) { showToast(`❌ ${e.message}`, 'error'); }
}
@@ -581,7 +591,8 @@ async function restorePreset(name, label) {
if (!confirm(`Restaurer le preset « ${label} » ?\nLes actions actuelles seront remplacées.`)) return;
try {
const r = await api('POST', `/api/actions/presets/${encodeURIComponent(name)}/restore`);
- showToast(`✅ Preset « ${label} » restauré (${r.action_count} actions) — redémarrez photobooth-app`, 'success', 8000);
+ showToast(`✅ Preset « ${label} » restauré (${r.action_count} actions)`, 'success');
+ showRestartBtn();
await loadAll();
} catch(e) { showToast(`❌ ${e.message}`, 'error'); }
}
@@ -603,6 +614,27 @@ function esc(s) {
.replace(/"/g,'"').replace(/'/g,''');
}
+// ── Restart photobooth-app ────────────────────────────────────────────────────
+function showRestartBtn() {
+ document.getElementById('restart-btn').style.display = '';
+}
+
+async function restartPhotobooth() {
+ const btn = document.getElementById('restart-btn');
+ btn.disabled = true;
+ btn.textContent = '⏳ Redémarrage…';
+ try {
+ await api('POST', '/api/system/restart-photobooth');
+ showToast('🔄 photobooth-app redémarre — patientez ~10s', 'info', 8000);
+ btn.style.display = 'none';
+ } catch(e) {
+ showToast('❌ Erreur redémarrage: ' + e.message, 'error');
+ } finally {
+ btn.disabled = false;
+ btn.textContent = '🔄 Redémarrer photobooth-app';
+ }
+}
+
// ── Init ──────────────────────────────────────────────────────────────────────
loadAll();