Header: Statuszeile "Ohne Datenverlust seit n Tagen" + Kennzahlen zurückholen
Schlanke Wiederbelebung des alten Uptime-Schriftzugs aus der Python-Version, jetzt als kleine Zeile direkt unter dem Titel: Tage seit fixem Startpunkt (13.12.2025, Kontinuität) plus aktuelle Profil- und Beitragszahlen. - /stats: neuer öffentlicher Endpunkt (COUNT user / COUNT entry WHERE deleted=0) - app.js: renderStats() rechnet die Tage und füllt #stats per textContent - index.html: <p id="stats" class="tagline"> unter der h1 - app.css: kleine graue .tagline-Zeile Kein Inline-JS/CSS -> strikte CSP bleibt unangetastet. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -87,6 +87,7 @@ func routes() http.Handler {
|
|||||||
r.Get("/auth/logout", handleLogout)
|
r.Get("/auth/logout", handleLogout)
|
||||||
r.Get("/auth/sessioninfo", handleSessionInfo)
|
r.Get("/auth/sessioninfo", handleSessionInfo)
|
||||||
r.Get("/auth/headerbar", handleHeaderbar)
|
r.Get("/auth/headerbar", handleHeaderbar)
|
||||||
|
r.Get("/stats", handleStats)
|
||||||
|
|
||||||
// --- Entries ---
|
// --- Entries ---
|
||||||
r.Get("/entry/feed/{page}", handleFeed)
|
r.Get("/entry/feed/{page}", handleFeed)
|
||||||
|
|||||||
@@ -70,6 +70,18 @@ func handleUserPage(w http.ResponseWriter, r *http.Request) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// handleStats liefert die Kennzahlen für die Statuszeile unter dem Titel:
|
||||||
|
// registrierte Nutzer und nicht-gelöschte Beiträge.
|
||||||
|
func handleStats(w http.ResponseWriter, r *http.Request) {
|
||||||
|
var users, entries int64
|
||||||
|
db.QueryRow(`SELECT COUNT(*) FROM user`).Scan(&users)
|
||||||
|
db.QueryRow(`SELECT COUNT(*) FROM entry WHERE deleted = 0`).Scan(&entries)
|
||||||
|
writeJSON(w, http.StatusOK, map[string]any{
|
||||||
|
"users": users,
|
||||||
|
"entries": entries,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func handleUserInfo(w http.ResponseWriter, r *http.Request) {
|
func handleUserInfo(w http.ResponseWriter, r *http.Request) {
|
||||||
uid := uidFromContext(r.Context())
|
uid := uidFromContext(r.Context())
|
||||||
|
|
||||||
|
|||||||
@@ -80,6 +80,13 @@ h2 {
|
|||||||
padding: 0 0.3rem;
|
padding: 0 0.3rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Kleine Statuszeile direkt unter dem Titel (Tage ohne Datenverlust + Kennzahlen). */
|
||||||
|
.tagline {
|
||||||
|
margin: 0.2rem 0 0;
|
||||||
|
font-size: 0.85rem;
|
||||||
|
color: gray;
|
||||||
|
}
|
||||||
|
|
||||||
#headerbar {
|
#headerbar {
|
||||||
background-color: white;
|
background-color: white;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
<a href="/static/docs/beitragsordnung.html">Beitragsordnung</a>
|
<a href="/static/docs/beitragsordnung.html">Beitragsordnung</a>
|
||||||
</nav>
|
</nav>
|
||||||
<a href="/"><h1>Kontrollverlust</h1></a>
|
<a href="/"><h1>Kontrollverlust</h1></a>
|
||||||
|
<p id="stats" class="tagline"></p>
|
||||||
<div id="headerbar"></div>
|
<div id="headerbar"></div>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
|
|||||||
@@ -95,5 +95,26 @@ document.getElementById("entry-form").addEventListener("submit", async (e) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// --- Statuszeile unter dem Titel ---
|
||||||
|
// Tage ohne Datenverlust (fester Startpunkt, Kontinuität seit der alten
|
||||||
|
// Version) plus aktuelle Kennzahlen aus /stats.
|
||||||
|
const dataLossStart = new Date("2025-12-13T12:44:00").getTime();
|
||||||
|
|
||||||
|
function plural(n, one, many) {
|
||||||
|
return `${n} ${n === 1 ? one : many}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function renderStats() {
|
||||||
|
const el = document.getElementById("stats");
|
||||||
|
if (!el) return;
|
||||||
|
const days = Math.floor((Date.now() - dataLossStart) / 86400000);
|
||||||
|
const s = await api.get("/stats");
|
||||||
|
el.textContent =
|
||||||
|
`Ohne Datenverlust seit ${plural(days, "Tag", "Tagen")} · ` +
|
||||||
|
`${plural(s.users ?? 0, "Profil", "Profile")} · ` +
|
||||||
|
`${plural(s.entries ?? 0, "Beitrag", "Beiträge")}`;
|
||||||
|
}
|
||||||
|
|
||||||
// --- Start ---
|
// --- Start ---
|
||||||
refreshHeader();
|
refreshHeader();
|
||||||
|
renderStats();
|
||||||
|
|||||||
Reference in New Issue
Block a user