chore: beta release v0.5.0-beta
- Bump version to 0.5.0-beta - Add Apache-2.0 LICENSE (official text) + NOTICE - Add Docker support: multi-stage Dockerfile + docker-compose * non-root user, tini PID 1, gunicorn + uvicorn workers * healthcheck, OCI labels, persistent /data volume - Add GitHub Actions CI (lint/import-check + Docker smoke-test) - Backend polish: * modern lifespan handler (replaces deprecated on_event) * explicit sort validation (400 instead of 500) * title min_length=1 schema validation * configurable data dir + http timeout via env * avg_rating helper extracted (DRY) - Frontend polish: * beta badge in title, footer with live version * loading spinner on initial fetch * updated README, badges, config table, roadmap
This commit is contained in:
@@ -96,6 +96,22 @@ a { color: var(--accent-2); text-decoration: none; }
|
||||
}
|
||||
.brand-text p { margin: 2px 0 0; color: var(--text-dim); font-size: 14px; }
|
||||
|
||||
.version-badge {
|
||||
display: inline-block;
|
||||
margin-left: 8px;
|
||||
vertical-align: middle;
|
||||
font-size: 10px;
|
||||
font-weight: 800;
|
||||
letter-spacing: .1em;
|
||||
text-transform: uppercase;
|
||||
padding: 3px 7px;
|
||||
border-radius: 999px;
|
||||
background: linear-gradient(135deg, rgba(245,158,11,.25), rgba(239,68,68,.25));
|
||||
color: #fbbf24;
|
||||
border: 1px solid rgba(245,158,11,.4);
|
||||
-webkit-text-fill-color: #fbbf24;
|
||||
}
|
||||
|
||||
.hero-search {
|
||||
display: flex; gap: 10px; flex-wrap: wrap;
|
||||
align-items: center;
|
||||
@@ -224,6 +240,22 @@ a { color: var(--accent-2); text-decoration: none; }
|
||||
margin-top: 14px;
|
||||
}
|
||||
|
||||
.grid-loading {
|
||||
grid-column: 1 / -1;
|
||||
display: flex; align-items: center; justify-content: center;
|
||||
gap: 12px;
|
||||
padding: 60px 20px;
|
||||
color: var(--text-dim);
|
||||
}
|
||||
.spinner {
|
||||
width: 22px; height: 22px;
|
||||
border: 2px solid var(--border);
|
||||
border-top-color: var(--accent);
|
||||
border-radius: 50%;
|
||||
animation: spin .8s linear infinite;
|
||||
}
|
||||
@keyframes spin { to { transform: rotate(360deg); } }
|
||||
|
||||
.card {
|
||||
background: var(--bg-elev);
|
||||
border: 1px solid var(--border);
|
||||
@@ -541,3 +573,16 @@ body.kind-series .row[data-when="series"] { display: flex; }
|
||||
.status-tabs { padding: 4px 12px 0; }
|
||||
.tab { padding: 10px 10px; font-size: 13px; }
|
||||
}
|
||||
|
||||
/* ===================== Footer ===================== */
|
||||
.footer {
|
||||
max-width: var(--container);
|
||||
margin: 0 auto;
|
||||
padding: 24px 24px 40px;
|
||||
display: flex; justify-content: space-between; align-items: center;
|
||||
color: var(--text-muted);
|
||||
font-size: 12px;
|
||||
border-top: 1px solid var(--border);
|
||||
margin-top: 40px;
|
||||
}
|
||||
.footer span:last-child { color: var(--text-dim); }
|
||||
|
||||
+10
-2
@@ -15,7 +15,7 @@
|
||||
<div class="brand">
|
||||
<div class="logo">W</div>
|
||||
<div class="brand-text">
|
||||
<h1>WatchStack</h1>
|
||||
<h1>WatchStack <span class="version-badge">beta</span></h1>
|
||||
<p>Deine Watchlist für <strong>Bücher</strong>, <strong>Serien</strong> & mehr.</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -74,7 +74,10 @@
|
||||
|
||||
<!-- Listen-Grid -->
|
||||
<section id="grid" class="grid">
|
||||
<!-- Cards per JS -->
|
||||
<div class="grid-loading">
|
||||
<div class="spinner"></div>
|
||||
<span>Lade Watchlist…</span>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<div id="empty-state" class="empty hidden">
|
||||
@@ -219,6 +222,11 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<footer class="footer">
|
||||
<span>WatchStack <span id="version">…</span> · Apache 2.0</span>
|
||||
<span>Made for readers & binge-watchers</span>
|
||||
</footer>
|
||||
|
||||
<!-- ===================== Toast ===================== -->
|
||||
<div id="toast" class="toast" hidden></div>
|
||||
|
||||
|
||||
@@ -510,6 +510,15 @@
|
||||
$$('[data-close-stats]').forEach(b => b.addEventListener('click', () => { $('#modal-stats').hidden = true; }));
|
||||
}
|
||||
|
||||
// Version aus /api/health in den Footer schreiben
|
||||
(async () => {
|
||||
try {
|
||||
const h = await api.get('/api/health');
|
||||
const el = $('#version');
|
||||
if (el && h.version) el.textContent = 'v' + h.version;
|
||||
} catch (_) { /* silent */ }
|
||||
})();
|
||||
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
wire();
|
||||
loadAll();
|
||||
|
||||
Reference in New Issue
Block a user