From 3522d2d996beb21cf1eeeef59c5a2f41ed1ebeb6 Mon Sep 17 00:00:00 2001 From: jbperrin Date: Sat, 18 Jul 2026 10:33:57 +0200 Subject: [PATCH] =?UTF-8?q?feat:=20bouton=20restart=20photobooth-app=20apr?= =?UTF-8?q?=C3=A8s=20modification=20des=20actions?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/api/system_api.py | 21 ++++++++++++++- frontend/templates/admin/actions.html | 38 ++++++++++++++++++++++++--- 2 files changed, 55 insertions(+), 4 deletions(-) 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();