fix: mtime index dans processed_full, print 404, galerie full-width
This commit is contained in:
@@ -22,20 +22,49 @@ def _get_id(item: dict) -> str:
|
|||||||
|
|
||||||
|
|
||||||
def _find_file(media_dir: str, photo_id: str) -> Path | None:
|
def _find_file(media_dir: str, photo_id: str) -> Path | None:
|
||||||
"""Cherche un fichier image correspondant à l'identifiant dans le répertoire media."""
|
"""Cherche un fichier image correspondant à l'identifiant.
|
||||||
|
|
||||||
|
Cherche dans media_dir, processed_full/ et les chemins photobooth standard.
|
||||||
|
"""
|
||||||
base = Path(media_dir)
|
base = Path(media_dir)
|
||||||
if not base.exists():
|
candidates = [
|
||||||
return None
|
base,
|
||||||
|
base / "processed_full",
|
||||||
|
Path("/home/pi/photobooth-data/media/processed_full"),
|
||||||
|
Path("/home/pi/photobooth-data/media"),
|
||||||
|
]
|
||||||
|
for d in candidates:
|
||||||
|
if not d.exists():
|
||||||
|
continue
|
||||||
for ext in (".jpg", ".jpeg", ".png"):
|
for ext in (".jpg", ".jpeg", ".png"):
|
||||||
f = base / f"{photo_id}{ext}"
|
f = d / f"{photo_id}{ext}"
|
||||||
if f.exists():
|
if f.exists():
|
||||||
return f
|
return f
|
||||||
matches = list(base.rglob(f"{photo_id}{ext}"))
|
|
||||||
if matches:
|
|
||||||
return matches[0]
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def _build_mtime_index(media_dir: Path) -> dict[str, float]:
|
||||||
|
"""Construit un index {stem: mtime, name: mtime} en cherchant dans les dossiers connus."""
|
||||||
|
index: dict[str, float] = {}
|
||||||
|
checked: set[Path] = set()
|
||||||
|
candidates = [
|
||||||
|
media_dir,
|
||||||
|
media_dir / "processed_full",
|
||||||
|
Path("/home/pi/photobooth-data/media/processed_full"),
|
||||||
|
Path("/home/pi/photobooth-data/media"),
|
||||||
|
]
|
||||||
|
for d in candidates:
|
||||||
|
if not d.exists() or d in checked:
|
||||||
|
continue
|
||||||
|
checked.add(d)
|
||||||
|
for f in d.iterdir():
|
||||||
|
if f.is_file() and f.suffix.lower() in (".jpg", ".jpeg", ".png"):
|
||||||
|
mt = f.stat().st_mtime
|
||||||
|
index[f.name] = mt
|
||||||
|
index[f.stem] = mt
|
||||||
|
return index
|
||||||
|
|
||||||
|
|
||||||
def _require_auth(request: Request):
|
def _require_auth(request: Request):
|
||||||
return request.session.get("authenticated") is True
|
return request.session.get("authenticated") is True
|
||||||
|
|
||||||
@@ -66,20 +95,7 @@ async def admin_get_photos(
|
|||||||
photos = [p for p in all_photos if _is_image(p)]
|
photos = [p for p in all_photos if _is_image(p)]
|
||||||
|
|
||||||
# Enrichit chaque photo avec mtime depuis le disque
|
# Enrichit chaque photo avec mtime depuis le disque
|
||||||
# Indexe par stem ET par nom complet pour couvrir les deux formats d'id
|
mtime_index = _build_mtime_index(media_dir)
|
||||||
mtime_index: dict[str, float] = {}
|
|
||||||
for media_dir_candidate in [
|
|
||||||
media_dir,
|
|
||||||
Path("/home/pi/photobooth-data/media/processed_full"),
|
|
||||||
Path("/home/pi/photobooth-data/media"),
|
|
||||||
]:
|
|
||||||
if media_dir_candidate.exists():
|
|
||||||
for f in media_dir_candidate.iterdir():
|
|
||||||
if f.is_file():
|
|
||||||
mt = f.stat().st_mtime
|
|
||||||
mtime_index[f.name] = mt # uuid.jpg
|
|
||||||
mtime_index[f.stem] = mt # uuid
|
|
||||||
break
|
|
||||||
|
|
||||||
for p in photos:
|
for p in photos:
|
||||||
pid = _get_id(p)
|
pid = _get_id(p)
|
||||||
|
|||||||
+13
-9
@@ -50,20 +50,24 @@ async def api_gallery_photos(
|
|||||||
if ev:
|
if ev:
|
||||||
started_at = ev["started_at"] or 0.0
|
started_at = ev["started_at"] or 0.0
|
||||||
ended_at = ev["ended_at"] or datetime.now().timestamp()
|
ended_at = ev["ended_at"] or datetime.now().timestamp()
|
||||||
# Construire un index mtime par stem ET par nom complet
|
# Construire un index mtime : cherche dans media_dir et ses sous-dossiers connus
|
||||||
mtime_index: dict[str, float] = {}
|
mtime_index: dict[str, float] = {}
|
||||||
for media_dir_candidate in [
|
base = Path(cfg.photobooth.media_dir)
|
||||||
Path(cfg.photobooth.media_dir),
|
checked: set = set()
|
||||||
|
for candidate in [
|
||||||
|
base,
|
||||||
|
base / "processed_full",
|
||||||
Path("/home/pi/photobooth-data/media/processed_full"),
|
Path("/home/pi/photobooth-data/media/processed_full"),
|
||||||
Path("/home/pi/photobooth-data/media"),
|
Path("/home/pi/photobooth-data/media"),
|
||||||
]:
|
]:
|
||||||
if media_dir_candidate.exists():
|
if not candidate.exists() or candidate in checked:
|
||||||
for f in media_dir_candidate.iterdir():
|
continue
|
||||||
if f.is_file():
|
checked.add(candidate)
|
||||||
|
for f in candidate.iterdir():
|
||||||
|
if f.is_file() and f.suffix.lower() in (".jpg", ".jpeg", ".png"):
|
||||||
mt = f.stat().st_mtime
|
mt = f.stat().st_mtime
|
||||||
mtime_index[f.name] = mt # uuid.jpg
|
mtime_index[f.name] = mt
|
||||||
mtime_index[f.stem] = mt # uuid
|
mtime_index[f.stem] = mt
|
||||||
break
|
|
||||||
|
|
||||||
def _in_event(p: dict) -> bool:
|
def _in_event(p: dict) -> bool:
|
||||||
pid = _get_id(p)
|
pid = _get_id(p)
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
{% block head %}
|
{% block head %}
|
||||||
<style>
|
<style>
|
||||||
/* ── Layout ───────────────────────────────────────────────────────────────── */
|
/* ── Layout ───────────────────────────────────────────────────────────────── */
|
||||||
.gallery-wrap { max-width: 1300px; margin: 0 auto; padding: 1rem; }
|
.gallery-wrap { max-width: 100%; margin: 0; padding: 1rem 1.5rem; }
|
||||||
|
|
||||||
/* ── Barre de filtres ─────────────────────────────────────────────────────── */
|
/* ── Barre de filtres ─────────────────────────────────────────────────────── */
|
||||||
.filter-bar {
|
.filter-bar {
|
||||||
@@ -53,7 +53,7 @@
|
|||||||
.copies-wrap input { width: 52px; background: var(--bg); border: 1px solid var(--border); color: var(--text); border-radius: 6px; padding: .3rem .5rem; text-align: center; }
|
.copies-wrap input { width: 52px; background: var(--bg); border: 1px solid var(--border); color: var(--text); border-radius: 6px; padding: .3rem .5rem; text-align: center; }
|
||||||
|
|
||||||
/* ── Grille photos ────────────────────────────────────────────────────────── */
|
/* ── Grille photos ────────────────────────────────────────────────────────── */
|
||||||
.photo-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(160px, 1fr)); gap: .75rem; }
|
.photo-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: .85rem; }
|
||||||
.photo-card {
|
.photo-card {
|
||||||
position: relative; aspect-ratio: 3/2; border-radius: 8px; overflow: hidden;
|
position: relative; aspect-ratio: 3/2; border-radius: 8px; overflow: hidden;
|
||||||
cursor: pointer; background: var(--surface); border: 2px solid transparent;
|
cursor: pointer; background: var(--surface); border: 2px solid transparent;
|
||||||
@@ -123,7 +123,7 @@
|
|||||||
.lb-modal {
|
.lb-modal {
|
||||||
background: var(--surface); border: 1px solid var(--border);
|
background: var(--surface); border: 1px solid var(--border);
|
||||||
border-radius: 16px; overflow: hidden;
|
border-radius: 16px; overflow: hidden;
|
||||||
max-width: min(860px, calc(95vw - 110px)); width: 100%;
|
max-width: min(1100px, calc(95vw - 110px)); width: 100%;
|
||||||
display: flex; flex-direction: column; max-height: 95vh;
|
display: flex; flex-direction: column; max-height: 95vh;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -148,7 +148,7 @@
|
|||||||
flex: 1; overflow: hidden; display: flex; align-items: center; justify-content: center;
|
flex: 1; overflow: hidden; display: flex; align-items: center; justify-content: center;
|
||||||
background: #111; min-height: 200px;
|
background: #111; min-height: 200px;
|
||||||
}
|
}
|
||||||
.lb-img-wrap img { max-width: 100%; max-height: 55vh; object-fit: contain; display: block; }
|
.lb-img-wrap img { max-width: 100%; max-height: 72vh; object-fit: contain; display: block; }
|
||||||
|
|
||||||
/* Bloc demandes impression */
|
/* Bloc demandes impression */
|
||||||
.lb-print-panel {
|
.lb-print-panel {
|
||||||
|
|||||||
Reference in New Issue
Block a user