CI / test (push) Has been cancelled
Quivio (Kofferwort aus Quire + Video) ersetzt den Arbeitstitel WatchStack. Es ist origineller, frei auf PyPI/npm, und passt perfekt zur Doppelnatur der App: Buecher (Quire) + Serien (Video). Geaendert: - Python-Paket app/ -> quivio/ (+ alle Imports angepasst) - DB-File watchstack.db -> quivio.db - Docker-Image: quivio:0.5.1-beta, Container-Name quivio - Compose-Services: quivio, quivio-local - ENV-Vars: QUIVIO_VERSION, QUIVIO_PORT, Volume quivio-data - Frontend-Logo "W" -> "Q", Titel "Quivio", Footer - Favicon "Q" (Georgia serif fuer klassischen Look) - Logger-Name: watchstack -> quivio - README, NOTICE, dist/README, data/README: Quivio - CI-Workflow: testet quivio/ Pfade - build-and-push.sh: lokaler Tag "quivio:VERSION" - service-Feld in /api/health: quivio - OpenAPI title: Quivio Bugfix (gefunden beim Renaming): - seed.py hatte versteckten "from app.database import DB_PATH" — gefixt Verifiziert end-to-end: - Python-Import OK - Backend: service=quivio, version=0.5.1-beta, 8 unique items - Docker-Build OK, Push in Gitea-Registry OK (neuer sha256-Digest) - Container: Quivio 0.5.1-beta ready (logger), HTML ohne WatchStack-Rest - OpenAPI title=Quivio - 8 unique items nach cold start (Race-Fix haelt)
236 lines
9.3 KiB
HTML
236 lines
9.3 KiB
HTML
<!doctype html>
|
||
<html lang="de">
|
||
<head>
|
||
<meta charset="utf-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||
<title>Quivio – Watchlist für Bücher & Serien</title>
|
||
<link rel="icon" type="image/svg+xml" href="/static/img/favicon.svg">
|
||
<link rel="stylesheet" href="/static/css/style.css">
|
||
</head>
|
||
<body>
|
||
<!-- ===================== Header / Hero ===================== -->
|
||
<header class="hero">
|
||
<div class="hero-bg"></div>
|
||
<div class="hero-inner">
|
||
<div class="brand">
|
||
<div class="logo">Q</div>
|
||
<div class="brand-text">
|
||
<h1>Quivio <span class="version-badge">beta</span></h1>
|
||
<p>Deine Watchlist für <strong>Bücher</strong>, <strong>Serien</strong> & mehr.</p>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="hero-search">
|
||
<input id="search-input" type="search" placeholder="Titel, Autor oder Genre suchen…" autocomplete="off">
|
||
<select id="filter-kind">
|
||
<option value="">Alle Medien</option>
|
||
<option value="book">Nur Bücher</option>
|
||
<option value="series">Nur Serien</option>
|
||
</select>
|
||
<select id="filter-status">
|
||
<option value="">Alle Status</option>
|
||
<option value="plan">Geplant</option>
|
||
<option value="reading">Laufend</option>
|
||
<option value="done">Abgeschlossen</option>
|
||
<option value="hold">Pausiert</option>
|
||
<option value="dropped">Abgebrochen</option>
|
||
</select>
|
||
<select id="filter-sort">
|
||
<option value="updated_desc">Zuletzt geändert</option>
|
||
<option value="title_asc">Titel A–Z</option>
|
||
<option value="title_desc">Titel Z–A</option>
|
||
<option value="rating_desc">Beste Bewertung</option>
|
||
<option value="rating_asc">Schlechteste Bewertung</option>
|
||
<option value="year_desc">Neueste zuerst</option>
|
||
<option value="year_asc">Älteste zuerst</option>
|
||
</select>
|
||
<button id="open-stats" class="btn btn-ghost" title="Statistik anzeigen">📊</button>
|
||
<button id="open-add" class="btn btn-primary">+ Neu</button>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Status-Tabs (MAL-Style) -->
|
||
<nav class="status-tabs" id="status-tabs">
|
||
<button class="tab active" data-status="">Alle</button>
|
||
<button class="tab" data-status="plan">Geplant <span class="count" id="cnt-plan">0</span></button>
|
||
<button class="tab" data-status="reading">Laufend <span class="count" id="cnt-reading">0</span></button>
|
||
<button class="tab" data-status="done">Abgeschlossen <span class="count" id="cnt-done">0</span></button>
|
||
<button class="tab" data-status="hold">Pausiert <span class="count" id="cnt-hold">0</span></button>
|
||
<button class="tab" data-status="dropped">Abgebrochen <span class="count" id="cnt-dropped">0</span></button>
|
||
</nav>
|
||
</header>
|
||
|
||
<!-- ===================== Main ===================== -->
|
||
<main class="container">
|
||
<!-- Genre/Tag-Chips (Filter) -->
|
||
<div class="chips" id="genre-chips" aria-label="Genres">
|
||
<span class="chip-label">Genres:</span>
|
||
<!-- per JS befüllt -->
|
||
</div>
|
||
<div class="chips" id="tag-chips" aria-label="Tags">
|
||
<span class="chip-label">Tags:</span>
|
||
<!-- per JS befüllt -->
|
||
</div>
|
||
|
||
<!-- Listen-Grid -->
|
||
<section id="grid" class="grid">
|
||
<div class="grid-loading">
|
||
<div class="spinner"></div>
|
||
<span>Lade Watchlist…</span>
|
||
</div>
|
||
</section>
|
||
|
||
<div id="empty-state" class="empty hidden">
|
||
<h2>Noch nichts hier.</h2>
|
||
<p>Klick auf <strong>+ Neu</strong> und leg deinen ersten Eintrag an.</p>
|
||
</div>
|
||
</main>
|
||
|
||
<!-- ===================== Modal: Add / Edit ===================== -->
|
||
<div class="modal" id="modal-add" hidden>
|
||
<div class="modal-backdrop" data-close></div>
|
||
<div class="modal-card">
|
||
<header class="modal-header">
|
||
<h2 id="modal-title">Neuer Eintrag</h2>
|
||
<button class="icon-btn" data-close aria-label="Schließen">✕</button>
|
||
</header>
|
||
<form id="form-add" class="form">
|
||
<input type="hidden" name="id">
|
||
|
||
<div class="row">
|
||
<label class="field grow">
|
||
<span>Art</span>
|
||
<select name="kind" required>
|
||
<option value="book">📚 Buch</option>
|
||
<option value="series">📺 Serie</option>
|
||
</select>
|
||
</label>
|
||
<label class="field">
|
||
<span>Status</span>
|
||
<select name="status">
|
||
<option value="plan">Geplant</option>
|
||
<option value="reading">Laufend</option>
|
||
<option value="done">Abgeschlossen</option>
|
||
<option value="hold">Pausiert</option>
|
||
<option value="dropped">Abgebrochen</option>
|
||
</select>
|
||
</label>
|
||
</div>
|
||
|
||
<div class="row">
|
||
<label class="field grow">
|
||
<span>Titel*</span>
|
||
<input name="title" required maxlength="200">
|
||
<button type="button" id="btn-lookup" class="btn btn-ghost small" title="Online nachschlagen">🔍 Nachschlagen</button>
|
||
</label>
|
||
<label class="field">
|
||
<span>Jahr</span>
|
||
<input name="release_year" type="number" min="1800" max="2200">
|
||
</label>
|
||
</div>
|
||
|
||
<!-- Buch-Felder -->
|
||
<div class="row" data-when="book">
|
||
<label class="field grow">
|
||
<span>Autor</span>
|
||
<input name="author" maxlength="200">
|
||
</label>
|
||
<label class="field">
|
||
<span>ISBN</span>
|
||
<input name="isbn" maxlength="20" placeholder="z.B. 9783608938284">
|
||
</label>
|
||
</div>
|
||
<div class="row" data-when="book">
|
||
<label class="field"><span>Bände</span><input name="total_volumes" type="number" min="0"></label>
|
||
<label class="field"><span>Kapitel</span><input name="total_chapters" type="number" min="0"></label>
|
||
<label class="field"><span>Seiten</span><input name="total_pages" type="number" min="0"></label>
|
||
</div>
|
||
|
||
<!-- Serien-Felder -->
|
||
<div class="row" data-when="series">
|
||
<label class="field grow">
|
||
<span>Sender / Streaming</span>
|
||
<input name="network" maxlength="120" placeholder="z.B. Netflix, ARD, …">
|
||
</label>
|
||
<label class="field"><span>Staffeln</span><input name="total_seasons" type="number" min="0"></label>
|
||
<label class="field"><span>Episoden</span><input name="total_episodes" type="number" min="0"></label>
|
||
</div>
|
||
<div class="row" data-when="series">
|
||
<label class="field"><span>Start</span><input name="start_date" type="date"></label>
|
||
<label class="field"><span>Ende</span><input name="end_date" type="date"></label>
|
||
<label class="field"><span>Staffel aktuell</span><input name="season_watching" type="number" min="0"></label>
|
||
</div>
|
||
|
||
<div class="row">
|
||
<label class="field grow">
|
||
<span>Cover-URL</span>
|
||
<input name="cover_url" placeholder="https://… (oder per Nachschlagen automatisch)">
|
||
</label>
|
||
<label class="field">
|
||
<span>Bewertung (0–10)</span>
|
||
<input name="rating" type="number" step="0.1" min="0" max="10">
|
||
</label>
|
||
</div>
|
||
|
||
<label class="field">
|
||
<span>Beschreibung</span>
|
||
<textarea name="description" rows="3"></textarea>
|
||
</label>
|
||
|
||
<div class="row">
|
||
<label class="field grow">
|
||
<span>Genres (Komma-getrennt)</span>
|
||
<input name="genres" placeholder="Fantasy, Sci-Fi, Roman">
|
||
</label>
|
||
<label class="field grow">
|
||
<span>Tags (Komma-getrennt)</span>
|
||
<input name="tags" placeholder="long-runner, klassiker">
|
||
</label>
|
||
</div>
|
||
|
||
<label class="field">
|
||
<span>Notizen</span>
|
||
<textarea name="notes" rows="2"></textarea>
|
||
</label>
|
||
|
||
<footer class="modal-footer">
|
||
<button type="button" class="btn btn-ghost" data-close>Abbrechen</button>
|
||
<button type="submit" class="btn btn-primary">Speichern</button>
|
||
</footer>
|
||
</form>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- ===================== Drawer: Detail ===================== -->
|
||
<aside class="drawer" id="drawer" hidden>
|
||
<div class="drawer-backdrop" data-close-drawer></div>
|
||
<div class="drawer-card">
|
||
<button class="icon-btn drawer-close" data-close-drawer aria-label="Schließen">✕</button>
|
||
<div id="drawer-content"><!-- per JS --></div>
|
||
</div>
|
||
</aside>
|
||
|
||
<!-- ===================== Modal: Stats ===================== -->
|
||
<div class="modal" id="modal-stats" hidden>
|
||
<div class="modal-backdrop" data-close-stats></div>
|
||
<div class="modal-card stats-card">
|
||
<header class="modal-header">
|
||
<h2>Deine Statistik</h2>
|
||
<button class="icon-btn" data-close-stats aria-label="Schließen">✕</button>
|
||
</header>
|
||
<div id="stats-body"><!-- per JS --></div>
|
||
</div>
|
||
</div>
|
||
|
||
<footer class="footer">
|
||
<span>Quivio <span id="version">…</span> · Apache 2.0</span>
|
||
<span>Quire + Video — made for readers & binge-watchers</span>
|
||
</footer>
|
||
|
||
<!-- ===================== Toast ===================== -->
|
||
<div id="toast" class="toast" hidden></div>
|
||
|
||
<script src="/static/js/app.js" defer></script>
|
||
</body>
|
||
</html>
|