Rollen (Admin/Mitglied), Seite Kooperationen, Textanpassungen

- Gemeinsame Zugänge mit Rollen: Admin darf alles, Mitglied nutzt Kalender,
  Fahrtplaner, Treffpunkte und bearbeitet Mitglieder (kein Hinzufügen,
  Löschen, Import, keine Patches, keine Statistik-Korrektur)
- Server prüft die Rechte (403), Konten ohne Rolle gelten als Admin
- npm run user: add <name> [admin|mitglied], role <name> <rolle>
- Neue öffentliche Seite Kooperationen mit Titelbild, Anführer,
  Social-Media-Links und Beschreibung, Pflege durch Admin
- Kopfzeile bleibt bei mittlerer Breite einzeilig
- Texte auf Wunsch gekürzt

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
guyg1474andClaude Opus 5.5 committed 2026-10-12 19:47:03 +02:00
1 parent f46016487d
commit 819219fb2d
18 files changed
+661 -106

No files matched your search

+6 -6
View File
@@ -1,10 +1,10 @@
import { $, api, esc, showError, renderHeader, renderFooter } from './common.js';
import { $, api, esc, showError, renderHeader, renderFooter, isAdmin } from './common.js';
renderHeader('statistik');
renderFooter();
let stats = [];
let canEdit = false; // angemeldet und laufendes Jahr
let canEdit = false; // Admin und laufendes Jahr
function detail(s) {
if (!s.manual) return '';
@@ -50,12 +50,12 @@ $('#stats-list').addEventListener('click', async (e) => {
}
});
let loggedIn = false;
let admin = false;
async function load(year) {
const data = await api('GET', `/stats${year ? `?year=${year}` : ''}`);
stats = data.entries;
canEdit = loggedIn && data.live;
canEdit = admin && data.live;
$('#stats-year').innerHTML = data.years
.map((y, i) => `<option value="${y}" ${y === data.year ? 'selected' : ''}>${y}${i === 0 ? ' (laufend)' : ''}</option>`).join('');
$('#stats-info').textContent = data.live
@@ -66,6 +66,6 @@ async function load(year) {
$('#stats-year').addEventListener('change', (e) => load(e.target.value).catch(showError));
api('GET', '/me')
.then(({ user }) => { loggedIn = !!user; return load(); })
isAdmin()
.then((yes) => { admin = yes; return load(); })
.catch(showError);