Fix: Media-Symlinks beim Start, Sitter-Datenschutztext, Recalls Dark-Mode, Ausweis neuer Tab, SW by-v600

This commit is contained in:
rene 2026-05-02 10:09:06 +02:00
parent 2677cff882
commit b47a54db39
6 changed files with 47 additions and 24 deletions

View file

@ -48,6 +48,7 @@ async def lifespan(app: FastAPI):
init_db()
from routes.movies import seed_movies
seed_movies()
_link_prod_media()
logger.info(f"KI-Modus: {ki.KI_MODE}")
sched.start()
yield
@ -280,25 +281,25 @@ app.mount("/img", StaticFiles(directory=f"{STATIC_DIR}/img"), name="img")
# User-generierte Medien (Fotos aus Tagebuch, Giftköder-Alarm, etc.)
MEDIA_DIR = os.getenv("MEDIA_DIR", "/data/media")
PROD_MEDIA_DIR = os.getenv("PROD_MEDIA_DIR", "") # Staging-only: Fallback auf Prod-Media
PROD_MEDIA_DIR = os.getenv("PROD_MEDIA_DIR", "") # Staging-only: Production-Media einlinken
os.makedirs(MEDIA_DIR, exist_ok=True)
app.mount("/media", StaticFiles(directory=MEDIA_DIR), name="media")
if PROD_MEDIA_DIR:
# Staging: erst eigenes media-Verzeichnis, dann Prod-Fallback
from pathlib import Path as _Path
from starlette.responses import FileResponse as _FileResponse
@app.get("/media/{path:path}")
async def serve_media(path: str):
p = _Path(MEDIA_DIR) / path
if p.is_file():
return _FileResponse(str(p))
pp = _Path(PROD_MEDIA_DIR) / path
if pp.is_file():
return _FileResponse(str(pp))
raise HTTPException(404, "Media not found")
else:
app.mount("/media", StaticFiles(directory=MEDIA_DIR), name="media")
def _link_prod_media():
"""Staging: symlinkt Production-Media-Verzeichnisse in das Staging-Media-Verzeichnis."""
if not PROD_MEDIA_DIR or not os.path.isdir(PROD_MEDIA_DIR):
return
import pathlib
staging = pathlib.Path(MEDIA_DIR)
for item in pathlib.Path(PROD_MEDIA_DIR).iterdir():
link = staging / item.name
if not link.exists() and not link.is_symlink():
try:
link.symlink_to(item)
logger.info(f"Prod-Media verlinkt: {link}{item}")
except OSError as e:
logger.warning(f"Symlink fehlgeschlagen {link}: {e}")
@app.get("/robots.txt")
async def robots():

View file

@ -6924,3 +6924,26 @@ svg.empty-state-icon {
margin-top: var(--space-1);
line-height: 1.4;
}
/* Rückrufe — Warnbanner (Dark-Mode-sicher) */
.recalls-warning-banner {
background: var(--c-danger-subtle);
border: 1px solid var(--c-danger);
border-radius: var(--radius-md);
padding: var(--space-3) var(--space-4);
margin-bottom: var(--space-4);
display: flex;
align-items: flex-start;
gap: var(--space-2);
}
.recalls-warning-icon {
color: var(--c-danger);
flex-shrink: 0;
margin-top: 2px;
}
.recalls-warning-text {
margin: 0;
font-size: var(--text-sm);
color: var(--c-text);
line-height: 1.5;
}

View file

@ -3,7 +3,7 @@
Router, State-Management, Navigation, Initialisierung.
============================================================ */
const APP_VER = '599'; // ← bei jedem Deploy mit Frontend-Änderungen erhöhen
const APP_VER = '600'; // ← bei jedem Deploy mit Frontend-Änderungen erhöhen
const APP_VERSION = '1.2.1'; // ← semantische Version, wird bei make release gesetzt
const IS_STAGING = location.hostname === 'staging.banyaro.app';

View file

@ -213,7 +213,8 @@ window.Page_dog_profile = (() => {
<div style="padding:var(--space-4);border-bottom:1px solid var(--c-border)">
<div style="font-weight:600">Sitter-Zugang</div>
<div style="font-size:var(--text-xs);color:var(--c-text-secondary)">
Gib einem Freund temporären Schreibzugang für diesen Hund
Gib einem Freund temporären Schreibzugang für diesen Hund.
Deine bestehenden Daten und Medien bleiben unsichtbar und privat der Sitter kann nur neue Einträge anlegen.
</div>
</div>
<div id="dp-sitting-access" style="padding:var(--space-4)">Lade</div>

View file

@ -38,13 +38,11 @@ window.Page_recalls = (() => {
async function _render() {
_container.innerHTML = `
<!-- Warnbanner -->
<div style="background:#fef2f2;border:1px solid #fca5a5;border-radius:var(--radius-md);
padding:var(--space-3) var(--space-4);margin-bottom:var(--space-4);
display:flex;align-items:flex-start;gap:var(--space-2)">
<svg class="ph-icon" aria-hidden="true" style="color:#dc2626;flex-shrink:0;margin-top:2px">
<div class="recalls-warning-banner">
<svg class="ph-icon recalls-warning-icon" aria-hidden="true">
<use href="/icons/phosphor.svg#warning"></use>
</svg>
<p style="margin:0;font-size:var(--text-sm);color:#991b1b;line-height:1.5">
<p class="recalls-warning-text">
<strong>Hinweis:</strong> Prüfe immer das Mindesthaltbarkeitsdatum und die Chargen-Nummer
bevor du ein gemeldetes Produkt entsorgst oder zurückgibst.
</p>

View file

@ -3,7 +3,7 @@
Offline-Cache + Push Notifications + Tile-Cache
============================================================ */
const CACHE_VERSION = 'by-v599';
const CACHE_VERSION = 'by-v600';
const CACHE_STATIC = `${CACHE_VERSION}-static`;
const CACHE_TILES = 'ban-yaro-tiles-v1'; // bleibt über SW-Updates erhalten
const CACHE_API = 'ban-yaro-api-v1'; // API-Response-Cache