feat(aether): initial commit – self-hosted Cloud, Phasen 1–7
Go-Backend (chi, pgx, golang-migrate) + React/TS-Frontend als PWA. Enthalten: Auth inkl. OIDC, Dateien mit Versionen und Papierkorb, Freigaben (Links + intern), WebDAV, Gruppenordner, Admin/Theming, Volltextsuche mit OCR, eigener PDF-Betrachter und WOPI-Office (Collabora/OnlyOffice). Nicht im Repo: deploy/.env (Sitzungsschlüssel, DB- und Admin-Passwort) sowie alle Daten- und Build-Verzeichnisse – siehe .gitignore. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
commit
31a027c93a
225 files changed
+38042
No files matched your search
@@ -0,0 +1,54 @@
|
||||
import { useState, useEffect } from 'react'
|
||||
import { adminApi, type AdminUser } from '../api/client'
|
||||
import PageHeader from '../components/PageHeader'
|
||||
import Tabs from '../components/Tabs'
|
||||
type Tab = 'users' | 'groups' | 'theming' | 'audit'
|
||||
|
||||
import UsersTab from './admin/UsersTab'
|
||||
import GroupsTab from './admin/GroupsTab'
|
||||
import ThemingTab from './admin/ThemingTab'
|
||||
import AuditTab from './admin/AuditTab'
|
||||
|
||||
export default function AdminPage() {
|
||||
const [tab, setTab] = useState<Tab>('users')
|
||||
const [allUsers, setAllUsers] = useState<AdminUser[]>([])
|
||||
|
||||
useEffect(() => {
|
||||
adminApi.listUsers().then(data => setAllUsers(data ?? [])).catch(() => {})
|
||||
}, [])
|
||||
|
||||
const tabs: { id: Tab; label: string }[] = [
|
||||
{ id: 'users', label: 'Users' },
|
||||
{ id: 'groups', label: 'Groups' },
|
||||
{ id: 'theming', label: 'Theming' },
|
||||
// „Activity" statt „Audit log": Der Reiter zeigt nicht mehr nur das
|
||||
// Protokoll, sondern davor auch den Stand der Texterkennung und die
|
||||
// Speicherbereinigung – alles, was im Hintergrund läuft. Die Kennung
|
||||
// bleibt 'audit', sie steht in keiner Adresse und muss nicht wandern.
|
||||
{ id: 'audit', label: 'Activity' },
|
||||
]
|
||||
|
||||
return (
|
||||
<div style={{ flex: 1, display: 'flex', flexDirection: 'column', overflow: 'hidden' }}>
|
||||
<PageHeader
|
||||
icon={
|
||||
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
||||
<path d="M12 2l8 4v6c0 5-3.5 8.5-8 10-4.5-1.5-8-5-8-10V6z" />
|
||||
<path d="M9.5 12.5l1.8 1.8 3.4-3.6" />
|
||||
</svg>
|
||||
}
|
||||
title="Admin panel"
|
||||
meta="Users, groups, appearance and activity"
|
||||
/>
|
||||
|
||||
<div style={{ flex: 1, overflowY: 'auto', padding: 20 }}>
|
||||
<Tabs tabs={tabs} active={tab} onChange={setTab} />
|
||||
|
||||
{tab === 'users' && <UsersTab />}
|
||||
{tab === 'groups' && <GroupsTab allUsers={allUsers} />}
|
||||
{tab === 'theming' && <ThemingTab />}
|
||||
{tab === 'audit' && <AuditTab />}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
Reference in new issue
Block a user