feat: impression galerie utilisateur (enable/quota/max_copies)
This commit is contained in:
@@ -4,7 +4,7 @@ import asyncio
|
|||||||
import logging
|
import logging
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
from fastapi import APIRouter, Request, Query
|
from fastapi import APIRouter, Request, Query, Body
|
||||||
from fastapi.responses import JSONResponse
|
from fastapi.responses import JSONResponse
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
@@ -125,6 +125,29 @@ async def set_print_mode(request: Request, mode: str = Query(...)):
|
|||||||
return {"ok": True, "mode": mode}
|
return {"ok": True, "mode": mode}
|
||||||
|
|
||||||
|
|
||||||
|
@router.post("/print/user-print-config")
|
||||||
|
async def set_user_print_config(request: Request, body: dict = Body(...)):
|
||||||
|
"""Configure l'impression depuis la galerie utilisateur."""
|
||||||
|
enabled = bool(body.get("user_print_enabled", False))
|
||||||
|
quota = max(0, int(body.get("user_print_quota", 0)))
|
||||||
|
max_copies = max(1, min(10, int(body.get("user_print_max_copies", 1))))
|
||||||
|
config_svc = request.app.state.config_service
|
||||||
|
config_svc.save_user_print_config(enabled, quota, max_copies)
|
||||||
|
logger.info("User print config: enabled=%s quota=%d max_copies=%d", enabled, quota, max_copies)
|
||||||
|
return {"ok": True, "user_print_enabled": enabled, "user_print_quota": quota, "user_print_max_copies": max_copies}
|
||||||
|
|
||||||
|
|
||||||
|
@router.get("/print/user-print-config")
|
||||||
|
async def get_user_print_config(request: Request):
|
||||||
|
"""Retourne la config impression galerie utilisateur."""
|
||||||
|
cfg = request.app.state.config.print
|
||||||
|
return {
|
||||||
|
"user_print_enabled": cfg.user_print_enabled,
|
||||||
|
"user_print_quota": cfg.user_print_quota,
|
||||||
|
"user_print_max_copies": cfg.user_print_max_copies,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
# ── Gestion avancée des imprimantes CUPS ──────────────────────────────────────
|
# ── Gestion avancée des imprimantes CUPS ──────────────────────────────────────
|
||||||
|
|
||||||
@router.post("/print/printers/{printer_name}/enable")
|
@router.post("/print/printers/{printer_name}/enable")
|
||||||
|
|||||||
@@ -83,6 +83,10 @@ class PrintConfig:
|
|||||||
script_path: str = "/home/pi/photobooth-data/script/script_print.sh"
|
script_path: str = "/home/pi/photobooth-data/script/script_print.sh"
|
||||||
default_copies: int = 1
|
default_copies: int = 1
|
||||||
printers: list = field(default_factory=list)
|
printers: list = field(default_factory=list)
|
||||||
|
# Impression depuis la galerie utilisateur
|
||||||
|
user_print_enabled: bool = False
|
||||||
|
user_print_quota: int = 0 # 0 = illimité
|
||||||
|
user_print_max_copies: int = 1 # copies max par demande
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
@@ -209,6 +213,21 @@ class ConfigService:
|
|||||||
self._config.event.slug = slug
|
self._config.event.slug = slug
|
||||||
self._config.event.started_at = started_at
|
self._config.event.started_at = started_at
|
||||||
|
|
||||||
|
def save_user_print_config(self, enabled: bool, quota: int, max_copies: int):
|
||||||
|
with open(self.path, encoding="utf-8") as f:
|
||||||
|
raw = yaml.safe_load(f) or {}
|
||||||
|
raw.setdefault("print", {}).update({
|
||||||
|
"user_print_enabled": enabled,
|
||||||
|
"user_print_quota": quota,
|
||||||
|
"user_print_max_copies": max_copies,
|
||||||
|
})
|
||||||
|
with open(self.path, "w", encoding="utf-8") as f:
|
||||||
|
yaml.dump(raw, f, allow_unicode=True, default_flow_style=False)
|
||||||
|
if self._config:
|
||||||
|
self._config.print.user_print_enabled = enabled
|
||||||
|
self._config.print.user_print_quota = quota
|
||||||
|
self._config.print.user_print_max_copies = max_copies
|
||||||
|
|
||||||
def save_print_mode(self, mode: str):
|
def save_print_mode(self, mode: str):
|
||||||
with open(self.path, encoding="utf-8") as f:
|
with open(self.path, encoding="utf-8") as f:
|
||||||
raw = yaml.safe_load(f) or {}
|
raw = yaml.safe_load(f) or {}
|
||||||
|
|||||||
@@ -256,6 +256,51 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- ── IMPRESSION GALERIE UTILISATEUR ───────────────────────────────── -->
|
||||||
|
<div>
|
||||||
|
<div class="section-title">👥 Impression galerie utilisateur</div>
|
||||||
|
<div class="mode-card">
|
||||||
|
<p class="mode-hint" style="margin-bottom:.85rem">
|
||||||
|
Autorise (ou non) les visiteurs de la galerie publique à demander l'impression d'une photo,
|
||||||
|
avec un quota et un nombre de copies maximum par demande.
|
||||||
|
</p>
|
||||||
|
<div style="display:flex;flex-direction:column;gap:.75rem">
|
||||||
|
|
||||||
|
<label style="display:flex;align-items:center;gap:.65rem;cursor:pointer;font-size:.95rem">
|
||||||
|
<input type="checkbox" id="uprint-enabled"
|
||||||
|
{% if config.print.user_print_enabled %}checked{% endif %}
|
||||||
|
style="accent-color:var(--primary);width:1.1rem;height:1.1rem">
|
||||||
|
Permettre aux utilisateurs de demander une impression
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<div style="display:flex;gap:1.5rem;flex-wrap:wrap;align-items:flex-end">
|
||||||
|
<div class="form-group" style="margin:0">
|
||||||
|
<label class="mode-hint" style="display:block;margin-bottom:.3rem;font-weight:600">
|
||||||
|
Quota d'impressions par session
|
||||||
|
</label>
|
||||||
|
<div style="display:flex;align-items:center;gap:.5rem">
|
||||||
|
<input type="number" id="uprint-quota" class="copies-input"
|
||||||
|
value="{{ config.print.user_print_quota }}" min="0" max="99" style="width:70px">
|
||||||
|
<span class="mode-hint">0 = illimité</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group" style="margin:0">
|
||||||
|
<label class="mode-hint" style="display:block;margin-bottom:.3rem;font-weight:600">
|
||||||
|
Copies max par demande
|
||||||
|
</label>
|
||||||
|
<input type="number" id="uprint-max-copies" class="copies-input"
|
||||||
|
value="{{ config.print.user_print_max_copies }}" min="1" max="10" style="width:70px">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<button class="btn-sm btn-print" style="margin-top:.85rem" onclick="saveUserPrintConfig()">
|
||||||
|
💾 Sauvegarder
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- ── FILE D'ATTENTE ─────────────────────────────────────────────────── -->
|
<!-- ── FILE D'ATTENTE ─────────────────────────────────────────────────── -->
|
||||||
<div>
|
<div>
|
||||||
<div class="queue-card">
|
<div class="queue-card">
|
||||||
@@ -486,6 +531,19 @@ async function cancelPrint(id) {
|
|||||||
} catch(err) { showToast('Erreur', 'error'); }
|
} catch(err) { showToast('Erreur', 'error'); }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ── Config impression utilisateur ─────────────────────────────────────────────
|
||||||
|
async function saveUserPrintConfig() {
|
||||||
|
const payload = {
|
||||||
|
user_print_enabled: document.getElementById('uprint-enabled').checked,
|
||||||
|
user_print_quota: parseInt(document.getElementById('uprint-quota').value) || 0,
|
||||||
|
user_print_max_copies: parseInt(document.getElementById('uprint-max-copies').value) || 1,
|
||||||
|
};
|
||||||
|
try {
|
||||||
|
await api('POST', '/api/print/user-print-config', payload);
|
||||||
|
showToast('✅ Configuration sauvegardée', 'success');
|
||||||
|
} catch(e) { showToast('❌ Erreur : ' + e.message, 'error'); }
|
||||||
|
}
|
||||||
|
|
||||||
// ── WebSocket + auto-refresh ───────────────────────────────────────────────────
|
// ── WebSocket + auto-refresh ───────────────────────────────────────────────────
|
||||||
function onWsMessage(msg) {
|
function onWsMessage(msg) {
|
||||||
if (['print_request','print_result','print_cancelled'].includes(msg.type)) {
|
if (['print_request','print_result','print_cancelled'].includes(msg.type)) {
|
||||||
|
|||||||
Reference in New Issue
Block a user