feat: admin gallery - lightbox with icons, filters by date/event/status; fix: event badges - only current slug shows En cours; fix: archive_all_open on new event; fix: mtime_index uses stem for event photo filter
🚀 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-17 15:59:51 +02:00
parent 223d71883e
commit c89924ea18
6 changed files with 508 additions and 288 deletions
+38 -3
View File
@@ -1,6 +1,7 @@
"""API galerie admin — impression et suppression de photos."""
import logging
from datetime import datetime
from pathlib import Path
from fastapi import APIRouter, Request, Query
from fastapi.responses import JSONResponse
@@ -46,6 +47,9 @@ async def admin_get_photos(
request: Request,
page: int = Query(default=1, ge=1),
limit: int = Query(default=24, ge=1, le=100),
event_slug: str = Query(default=None),
date_from: float = Query(default=None),
date_to: float = Query(default=None),
):
"""Liste des photos pour la galerie admin, annotées avec leurs demandes d'impression."""
if not _require_auth(request):
@@ -53,23 +57,54 @@ async def admin_get_photos(
pb = request.app.state.photobooth_service
printer_svc = request.app.state.printer_service
cfg = request.app.state.config
event_svc = getattr(request.app.state, "event_service", None)
media_dir = Path(cfg.photobooth.media_dir)
# Récupère toutes les photos
all_photos = await pb.get_media_collection(limit=500)
photos = [p for p in all_photos if _is_image(p)]
# Enrichit chaque photo avec mtime depuis le disque
mtime_index: dict[str, float] = {}
if media_dir.exists():
for f in media_dir.iterdir():
mtime_index[f.stem] = f.stat().st_mtime
for p in photos:
pid = _get_id(p)
p["photo_id"] = pid
mt = mtime_index.get(pid, 0.0)
p["mtime"] = mt
p["date_iso"] = datetime.fromtimestamp(mt).strftime("%Y-%m-%d") if mt else ""
p["date_label"] = datetime.fromtimestamp(mt).strftime("%d/%m/%Y %H:%M") if mt else ""
# Filtre par événement
if event_slug and event_svc:
ev = await event_svc.get_event_by_slug(event_slug)
if ev:
t0 = ev["started_at"] or 0.0
t1 = ev["ended_at"] or datetime.now().timestamp()
photos = [p for p in photos if t0 <= p["mtime"] <= t1]
# Filtre par plage de dates
if date_from is not None:
photos = [p for p in photos if p["mtime"] >= date_from]
if date_to is not None:
photos = [p for p in photos if p["mtime"] <= date_to]
total = len(photos)
start = (page - 1) * limit
page_photos = photos[start:start + limit]
# Construit les URLs
for p in page_photos:
pid = _get_id(p)
p["photo_id"] = pid
pid = p["photo_id"]
p["full_url"] = pb.media_url(pid)
p["thumb_url"] = pb.thumbnail_url(pid)
p["download_url"] = f"/api/gallery/download/{pid}"
# Croise avec la file d'impression en attente (une seule requête SQLite)
# Croise avec la file d'impression en attente
try:
pending_map = await printer_svc.get_pending_by_photo_id()
for p in page_photos: