From 9c9b7e03bd68c834857a34ae830dda67c9b837e9 Mon Sep 17 00:00:00 2001 From: karim Date: Thu, 4 Jun 2026 12:09:10 +0200 Subject: [PATCH] =?UTF-8?q?admin:=20=C3=9Cbersicht-Dashboard,=20aufgewerte?= =?UTF-8?q?te=20Nutzerverwaltung,=20Wiki-Autoren?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Neue /api/stats (Admin, read-only): Inhalte/Nutzer/Dialog-Kennzahlen - Übersicht-View als Admin-Dashboard: Stat-Karten (klickbar) + Schnellzugriff - Nutzerverwaltung: Avatar-Initiale, angelegt/zuletzt-aktiv, Rolle beim Anlegen, Inline-Passwort (statt prompt), Filter, Rollen-Badge; API liefert last_sign_in_at - Wiki im Editor anlegbar: Typ 'Wiki-Seite' + Gruppe-Feld → content/wiki/.md; files.js klassifiziert wiki als eigene 'kind' (eigene Sidebar-Gruppe) Co-Authored-By: Claude Opus 4.8 --- cms/admin/src/App.jsx | 140 ++++++++++++++++++++++++++++-------- cms/admin/src/api.js | 3 +- cms/admin/src/styles.css | 31 ++++++++ cms/api/src/files.js | 7 +- cms/api/src/index.js | 2 + cms/api/src/routes/stats.js | 47 ++++++++++++ cms/api/src/routes/users.js | 8 ++- 7 files changed, 203 insertions(+), 35 deletions(-) create mode 100644 cms/api/src/routes/stats.js diff --git a/cms/admin/src/App.jsx b/cms/admin/src/App.jsx index 027fcf2..82a06c8 100644 --- a/cms/admin/src/App.jsx +++ b/cms/admin/src/App.jsx @@ -22,13 +22,13 @@ const hexOf = (name) => (COLORS.find((c) => c[0] === name) || [])[2] || 'transpa const LAYOUTS = ['', 'text', 'image', 'icon']; const SECTIONS = ['buerofuehrung', 'software', 'theorie']; -const KIND_LABEL = { beitrag: 'Beiträge', seite: 'Seiten', rubrik: 'Rubriken' }; +const KIND_LABEL = { beitrag: 'Beiträge', wiki: 'Wiki', seite: 'Seiten', rubrik: 'Rubriken' }; const EMPTY = { isNew: true, path: '', type: 'beitrag', section: 'software', slug: '', title: '', date: new Date().toISOString().slice(0, 10), weight: '', color: '', layout: 'text', tags: '', summary: '', description: '', - cover_image: '', external: '', authors: '', toc: false, draft: true, body: '', + cover_image: '', external: '', authors: '', group: '', toc: false, draft: true, body: '', }; export default function App() { @@ -89,7 +89,7 @@ function Dashboard({ email }) { const q = query.trim().toLowerCase(); const filtered = q ? entries.filter((e) => e.title.toLowerCase().includes(q) || (e.section || '').includes(q)) : entries; - const groups = { beitrag: [], seite: [], rubrik: [] }; + const groups = { beitrag: [], wiki: [], seite: [], rubrik: [] }; for (const e of filtered) (groups[e.kind] || groups.seite).push(e); return ( @@ -98,6 +98,7 @@ function Dashboard({ email }) { OPENBUREAU Redaktion