Feature: Tagebuch Cover-Bild (Favorit-Funktion) für diary_media
- Migration: diary_media.is_cover (INTEGER DEFAULT 0)
- Upload: erstes Item eines Eintrags automatisch is_cover=1
- Neuer Endpoint: PATCH /diary/{id}/media/{mid}/cover
- GET-Endpoints geben is_cover + cover_url zurück
- Frontend: Stern-Button (⭐) in Gallery-Detail und Edit-Formular
- Timeline-Karte verwendet cover_url als Vorschaubild
- SW by-v212, APP_VER 186
This commit is contained in:
parent
63ab092f5e
commit
fa0fcbf8c9
7 changed files with 196 additions and 21 deletions
|
|
@ -6,18 +6,27 @@ SQLite mit WAL-Modus (bewährt von akku-werkstatt).
|
|||
import sqlite3
|
||||
import os
|
||||
import logging
|
||||
import unicodedata
|
||||
from contextlib import contextmanager
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
DB_PATH = os.getenv("DB_PATH", "/data/banyaro.db")
|
||||
|
||||
|
||||
def _norm(s):
|
||||
"""Diakritika entfernen + lowercase — für akzentunabhängige Suche."""
|
||||
if not s:
|
||||
return ''
|
||||
return unicodedata.normalize('NFKD', str(s)).encode('ascii', 'ignore').decode('ascii').lower()
|
||||
|
||||
|
||||
def get_connection() -> sqlite3.Connection:
|
||||
conn = sqlite3.connect(DB_PATH, check_same_thread=False)
|
||||
conn.row_factory = sqlite3.Row
|
||||
conn.execute("PRAGMA journal_mode=WAL")
|
||||
conn.execute("PRAGMA foreign_keys=ON")
|
||||
conn.execute("PRAGMA busy_timeout=5000")
|
||||
conn.create_function('norm', 1, _norm)
|
||||
return conn
|
||||
|
||||
|
||||
|
|
@ -471,6 +480,8 @@ def _migrate(conn_factory):
|
|||
("walks", "anz_bewertungen", "INTEGER DEFAULT 0"),
|
||||
("sitters", "bewertung", "REAL DEFAULT 0"),
|
||||
("sitters", "anz_bewertungen", "INTEGER DEFAULT 0"),
|
||||
# Tagebuch-Medien: Cover-Bild markieren
|
||||
("diary_media", "is_cover", "INTEGER NOT NULL DEFAULT 0"),
|
||||
]
|
||||
with conn_factory() as conn:
|
||||
for table, column, col_type in migrations:
|
||||
|
|
@ -774,6 +785,20 @@ def _migrate(conn_factory):
|
|||
""")
|
||||
logger.info("Migration: diary_media Tabelle bereit.")
|
||||
|
||||
# Gesundheit: mehrere Mediendateien pro Eintrag
|
||||
conn.executescript("""
|
||||
CREATE TABLE IF NOT EXISTS health_media (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
health_id INTEGER NOT NULL REFERENCES health(id) ON DELETE CASCADE,
|
||||
url TEXT NOT NULL,
|
||||
media_type TEXT NOT NULL DEFAULT 'image',
|
||||
sort_order INTEGER NOT NULL DEFAULT 0,
|
||||
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS idx_health_media_entry ON health_media(health_id, sort_order);
|
||||
""")
|
||||
logger.info("Migration: health_media Tabelle bereit.")
|
||||
|
||||
# Walk-Einladungen (RSVP)
|
||||
conn.executescript("""
|
||||
CREATE TABLE IF NOT EXISTS walk_invitations (
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue