Elf Abschnitte in einer Spalte waren zehn zu viel

Die Verwaltung war eine Seite mit 1786 Zeilen. Wer das Protokoll sehen
wollte, scrollte an Mediatheken, Prüfliste, Benutzern und Speicher
vorbei — und jede neue Einstellung hätte sie länger gemacht.

Jetzt hat sie eine eigene Leiste mit sieben Bereichen, jeder mit seiner
Adresse: `#/verwaltung/protokolle` lässt sich ablegen, und ein Neuladen
bleibt dort stehen. Die Leiste sieht aus wie die Hauptleiste daneben,
damit sie als Navigation gelesen wird und nicht als Knopfreihe; am
Telefon wird aus der Spalte ein Streifen zum Schieben.

**Gebaut wird nur, was offen ist.** Das ist nicht nur sparsamer: das
Abspielfenster fragt im Fünf-Sekunden-Takt nach, die Mediathekenliste
beobachtet laufende Scans. Gemessen: nach dem Wechsel in einen anderen
Bereich kommt zwölf Sekunden lang keine Anfrage mehr.

`admin.ts` ist in acht Dateien zerlegt — eine je Bereich, dazu `teile.ts`
für die gemeinsame Überschrift und `index.ts` für Leiste und Weiche.

Zwei Dinge mussten dabei nachziehen:

**Die Markierung in der Hauptleiste.** Sie verglich stur zwei Segmente;
bei `#/verwaltung/metadaten` traf das auf keinen Eintrag, und
„Verwaltung" verlor seinen Balken. Jetzt gilt auch ein Segment.

**„5 Titel warten — ansehen".** Der Knopf sprang mit `scrollIntoView` zur
Prüfliste. Die steht nicht mehr im selben Dokument — er wechselt jetzt
den Bereich. Die Hervorhebung danach entfällt damit, und mit ihr ihr CSS.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Scarriffle
2026-10-06 16:39:50 +02:00
co-authored by Claude Opus 5
parent 94c6604e8b
commit 1e4a231d1b
13 changed files with 1979 additions and 1796 deletions
+9 -3
View File
@@ -11,7 +11,7 @@ import { anmeldung } from './views/login';
import { startseite } from './views/home';
import { mediathek } from './views/library';
import { detailseite } from './views/detail';
import { verwaltung } from './views/admin';
import { verwaltung, alsBereich } from './views/verwaltung';
import { suchseite } from './views/search';
import { esc, meldung } from './util';
@@ -361,9 +361,15 @@ function zeichnen(): void {
const weg = location.hash.replace(/^#\/?/, '');
const teile = weg.split('/').filter(Boolean);
// **Zwei Segmente, sonst eines.** Eine Mediathek heisst `#/m/{id}` und
// braucht beide; die Verwaltung heisst `#/verwaltung` und hat seit der
// zweiten Leiste einen Bereich dahinter. Verglich man stur zwei Segmente,
// verlor „Verwaltung" seine Markierung, sobald man darin etwas anklickte.
const zweiTeilig = `#/${teile.slice(0, 2).join('/')}`;
const einTeilig = `#/${teile.slice(0, 1).join('/')}`;
leiste.querySelectorAll('button[data-ziel]').forEach(b => {
const ziel = (b as HTMLElement).dataset.ziel!;
b.classList.toggle('check', ziel === `#/${teile.slice(0, 2).join('/')}`);
b.classList.toggle('check', ziel === zweiTeilig || ziel === einTeilig);
});
// **Aushängen, nicht leeren.** `innerHTML = ''` zerstörte die Ansicht —
@@ -397,7 +403,7 @@ function zeichnen(): void {
} else if (teile[0] === 'verwaltung' && istAdmin()) {
// **Die Verwaltung auch nicht** — sie zeigt Laufendes. Ihr Takt hängt am
// Signal und hört auf, sobald man weggeht.
einhaengen(weg, inhalt, signal => verwaltung(bekannt => {
einhaengen(weg, inhalt, signal => verwaltung(alsBereich(teile[1]), bekannt => {
// Gemerkte Ansichten wegwerfen: der Bestand hat sich geändert.
// Die Seitenleiste bekommt neue Zahlen — die Seite selbst bleibt.
vergessen();