Workspace: Wissens-Bibliothek -- 20 Kategorien, Suche, Filter, Pflege
Wichtigster Befund vorab: Es gab noch KEINEN PDF-Bereich. Weder auf der Website (28 Seiten, keine davon Anleitungen) noch auf dem Server (null PDFs). Es wurde also nichts umstrukturiert, sondern neu gebaut -- und damit war die erste Frage nicht "wie sieht es aus", sondern "wie kommen die PDFs spaeter rein". Eine feste Liste im Code waere nach drei Monaten unbrauchbar gewesen. Filipe hat entschieden: eigener Pflegebereich, und alles nur fuer das Team. Die Bibliothek liegt deshalb komplett im Workspace hinter dem Login, nicht auf der oeffentlichen Seite. GLIEDERUNG Zwanzig Kategorien woertlich nach Vorgabe, gebuendelt in sechs Welten: TikTok, Streaming einrichten, Bild & Ton, Uebertragung & Aussehen, Inhalt & Menschen, Hilfe & Schnellstart. Zwanzig gleich aussehende Kacheln untereinander findet niemand -- gebuendelt sucht man erst die Welt, und darin stehen nur noch drei bis vier. Jede Welt hat ihre eigene Farbe, jede Kategorie ihr eigenes Symbol (20 verschiedene, keins doppelt). Die Kategorietexte sind Filipes Beschreibungen -- sie beantworten beim Einsortieren die einzige Frage, die man wirklich hat. Die Gliederung steht im Code, nicht in der Datenbank: Sie ist eine bewusste Ordnung, keine Nutzdaten. JEDE PDF HAT GENAU EINE HAUPTKATEGORIE, alles Weitere laeuft ueber Tags -- so gibt es jede Anleitung nur einmal, sie ist aber ueber mehrere Begriffe auffindbar. Genau wie gefordert. SUCHE UND FILTER Suche ueber Titel, Beschreibung, Tags und Dateiname. Filter nach Stufe (Einsteiger / Fortgeschritten / Profi), Geraet und Tag. Zwei Details: - "PC" zeigt auch die Anleitungen, die fuer BEIDE Geraete gelten -- sonst filtert man sich versehentlich die Haelfte weg. - Der Tag-Filter sucht mit Kommas drumherum, sonst wuerde "pc" auch bei "pc-spiele" anschlagen. Sobald gesucht oder gefiltert wird, verschwinden die Kacheln und es erscheinen Treffer. Wer sucht, will nicht erst noch klicken. Der Zustand steht in der Adresse (?k=obs&tag=...). Damit funktionieren Zurueck-Taste, Neuladen und Weiterschicken. Eine Kategorie, die man niemandem verlinken kann, ist keine Seite. Geprueft. SICHERHEIT Hochgeladen wird nur, was WIRKLICH eine PDF ist -- geprueft an den ersten Bytes (%PDF-), nicht an der Dateiendung. Die kann jeder umbenennen. Geprueft mit einer als .pdf getarnten HTML-Datei mit Skript: abgewiesen. Nur weil diese Pruefung existiert, darf die Datei ueberhaupt im Browser angezeigt werden statt bloss heruntergeladen -- und selbst dann mit strenger CSP und nosniff. Lesen darf jeder Angemeldete, pflegen nur DogFather. Geprueft: Creator und Scout bekommen 403 beim Hochladen und sehen keine Bearbeiten-Knoepfe. Ohne Anmeldung ist auch die Datei selbst nicht erreichbar (401). Bricht das Anlegen nach dem Schreiben ab, wird die Datei wieder geloescht -- sonst laege sie fuer immer verwaist auf der Platte. Beim Bearbeiten wird die Datei bewusst NICHT ersetzt. Wer eine neue Fassung hat, stellt sie neu ein. So bleibt nachvollziehbar, was wann galt. Geprueft: 20 Kacheln, 20 verschiedene Symbole, Kategorie oeffnen, Suche, Tag-Klick, Browser-Zurueck, Handy ohne Ueberlauf, 0 Konsolenfehler.
This commit is contained in:
@@ -237,6 +237,32 @@ export function db() {
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS idx_eintraege_bereich ON eintraege (bereich, creator_id);
|
||||
|
||||
/* Wissens-Bibliothek: Anleitungen als PDF, hinter dem Login.
|
||||
Jede PDF hat GENAU EINE Hauptkategorie -- so gibt es sie nur
|
||||
einmal. Zusaetzliche Themen laufen ueber Tags, damit dieselbe
|
||||
Anleitung trotzdem ueber mehrere Suchbegriffe auffindbar ist.
|
||||
Die Kategorien selbst stehen im Code (workspace-wissen.js),
|
||||
nicht hier: Sie sind eine bewusste Gliederung, keine Nutzdaten. */
|
||||
CREATE TABLE IF NOT EXISTS wissen (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
titel TEXT NOT NULL,
|
||||
beschreibung TEXT,
|
||||
kategorie TEXT NOT NULL,
|
||||
stufe TEXT NOT NULL DEFAULT 'einsteiger'
|
||||
CHECK (stufe IN ('einsteiger','fortgeschritten','profi')),
|
||||
geraet TEXT NOT NULL DEFAULT 'egal'
|
||||
CHECK (geraet IN ('pc','handy','beide','egal')),
|
||||
tags TEXT,
|
||||
name_original TEXT NOT NULL,
|
||||
name_datei TEXT NOT NULL,
|
||||
groesse INTEGER NOT NULL,
|
||||
wichtig INTEGER NOT NULL DEFAULT 0,
|
||||
veroeffentlicht TEXT NOT NULL,
|
||||
aktualisiert TEXT,
|
||||
erstellt_von INTEGER REFERENCES personen(id) ON DELETE SET NULL
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS idx_wissen_kat ON wissen (kategorie);
|
||||
|
||||
/* Start-Check / Erstanalyse (Konzept, Seite 5). Eine Zeile je
|
||||
geprueftem Punkt -- ungeprueft heisst: gar keine Zeile. So sieht
|
||||
man am Bestand sofort, wie weit die Analyse ist, ohne leere
|
||||
@@ -462,6 +488,7 @@ const GESCHUETZT = {
|
||||
"/workspace/scouting.html": ["admin", "scout"],
|
||||
"/workspace/calls.html": null,
|
||||
"/workspace/startcheck.html": null,
|
||||
"/workspace/wissen.html": null,
|
||||
};
|
||||
|
||||
workspaceRouter.use((req, res, next) => {
|
||||
|
||||
Reference in New Issue
Block a user