From 8fb504406281a9dcb3b24e66138cae6a4050ea1a Mon Sep 17 00:00:00 2001 From: tleininger Date: Thu, 1 Oct 2026 11:37:04 +0200 Subject: [PATCH] Align the FAQ docs with the faq_topics collection --- Elternbeirat.Contracts/FaqTopic.cs | 2 +- docs/architektur.md | 4 +-- docs/entwicklung.md | 2 +- docs/redaktion.md | 55 ++++++++++++++++++++++-------- 4 files changed, 44 insertions(+), 19 deletions(-) diff --git a/Elternbeirat.Contracts/FaqTopic.cs b/Elternbeirat.Contracts/FaqTopic.cs index 9f585c8..15f22c3 100644 --- a/Elternbeirat.Contracts/FaqTopic.cs +++ b/Elternbeirat.Contracts/FaqTopic.cs @@ -85,7 +85,7 @@ public record FaqTopic /// /// Convenience over : questions name their topic, so /// PocketBase returns them under the back-relation key when the query expands it - /// (faqs_via_topic). The topic detail page reads them from here. They + /// (faqs_via_topic). The FAQ page reads them from here. They /// arrive unsorted, so this orders them by for a stable /// render. Drafts are dropped: PocketBase does not apply the topic query's /// public filter to the expanded children, so this keeps diff --git a/docs/architektur.md b/docs/architektur.md index f16b13a..c0a00d0 100644 --- a/docs/architektur.md +++ b/docs/architektur.md @@ -28,8 +28,8 @@ architecture. Never global. ## AE-2: Content in PocketBase, read per request (revised) **Decision:** All visible content lives in **PocketBase** (collections `pages`, -`posts`, `events`, `faqs`); the app reads it over the REST API per request via a -typed `PocketBaseClient`. Documents remain PDFs under `wwwroot`. +`posts`, `events`, `faq_topics`, `faqs`); the app reads it over the REST API per +request via a typed `PocketBaseClient`. Documents remain PDFs under `wwwroot`. **Original decision (stage 1):** Content as files in the repo — Markdown with YAML frontmatter, events as `Content/events.yml`. The rationale then was: no DB backup, diff --git a/docs/entwicklung.md b/docs/entwicklung.md index e2455e5..fac8547 100644 --- a/docs/entwicklung.md +++ b/docs/entwicklung.md @@ -108,7 +108,7 @@ and the dev overlay mounts that folder into PocketBase (`./pb/pb_migrations:/pb_ | File | Role | |---|---| -| `collections_schema.json` | The four content collections (`pages`, `posts`, `events`, `faqs`) as PocketBase exports them. **The single source of truth for the schema** — the test fixture imports this same file. | +| `collections_schema.json` | The five content collections (`pages`, `posts`, `events`, `faq_topics`, `faqs`) as PocketBase exports them. **The single source of truth for the schema** — the test fixture imports this same file. | | `_dev_seed.js` | The PocketBase migration. Reads the schema file, creates any missing collection, then inserts the example records. | Both steps are **idempotent**: a collection is created only if it is missing, and diff --git a/docs/redaktion.md b/docs/redaktion.md index 2cda244..cad1052 100644 --- a/docs/redaktion.md +++ b/docs/redaktion.md @@ -41,7 +41,8 @@ der passenden Collection (Button *New record*). | `pages` | Feste Seiten (Vorstand, Impressum, Kontakt …) | Slug, z. B. `/board` | | `posts` | Neuigkeiten / Beiträge | `/posts`, neueste zuerst | | `events` | Termine (Kalender) | `/events` und der `.ics`-Feed | -| `faqs` | Häufige Fragen | Werden auf der FAQ-Seite gruppiert angezeigt | +| `faq_topics` | Themen der häufigen Fragen (z. B. „Mensa und Mittagessen") | Als aufklappbare Gruppen auf `/faqs` | +| `faqs` | Häufige Fragen | Auf `/faqs`, in der Gruppe ihres Themas | Jede Collection hat als **letztes Feld `public`** (ja/nein). Nur Records mit `public = true` erscheinen auf der Website — so lässt sich ein Entwurf anlegen, @@ -54,8 +55,9 @@ Redaktion arbeitet mit **Daten**, nicht mit Struktur. Konkret: | Was du willst | Geht redaktionell? | Wie | |---|---|---| | Beitrag / Termin / Frage hinzufügen | **Ja** | Neuer Record in `posts` / `events` / `faqs` — erscheint sofort in der jeweiligen Liste | +| Neues FAQ-Thema (neue Gruppe auf `/faqs`) | **Ja** | Neuer Record in `faq_topics` (siehe *Häufige Fragen*) | | Neue Textseite | **Ja** | Neuer Record in `pages` (siehe unten) | -| Eine Seite mit einer Liste anteasern | **Ja** | Feld `embed` der Seite (`posts`/`events`/`faqs`) | +| Eine Seite mit einer Liste anteasern | **Ja** | Feld `embed` der Seite (`posts`/`events`) | | **Neue Art von Liste** (eigene Seite mit eigener Sortierung/Gruppierung und eigener Adresse, z. B. „Protokolle") | **Nein** | Braucht Entwicklung: neue Collection **plus** Code | Das heißt: **Bestehende Listen lassen sich beliebig erweitern**, aber eine *neue* @@ -98,9 +100,10 @@ sofort live, ohne Code und ohne Rebuild: `location` (`header` oder `footer`) und `order` (Reihenfolge, ab 1). Die App baut Kopf- und Fußnavigation daraus; nichts wird im Markup angefasst. - **Eingebettete Blöcke:** Das Feld `embed` (Mehrfachauswahl aus - `faqs`/`posts`/`events`) hängt unter den Text der Seite dynamische Blöcke. So - ist die Startseite (`home`) eine normale Seite mit `embed = [posts, events]`, - und `/faqs` eine Seite mit `embed = [faqs]`. Leeres `embed` = reine Textseite. + `posts`/`events`) hängt unter den Text der Seite dynamische Blöcke. So ist die + Startseite (`home`) eine normale Seite mit `embed = [posts, events]`. Leeres + `embed` = reine Textseite. Die FAQ-Liste ist kein `embed`: `/faqs` ist eine + feste Ansicht (siehe *Häufige Fragen*). > **Impressum und Datenschutz** hängen an ihren Slugs (`imprint`, `privacy`). > Diese Slugs nicht ändern — sonst laufen die rechtlich verlinkten Adressen ins @@ -162,16 +165,38 @@ ihrer Kalender-App abonnieren — der Feed entsteht aus denselben Records. --- -## Häufige Fragen (`faqs`) +## Häufige Fragen (`faq_topics` und `faqs`) -Eine Frage hat `question`, `answer` (Markdown), `topic` und `public`. Die App -baut die FAQ-Seite generiert: sie gruppiert die Fragen nach `topic` und zeigt den -`topic`-Text unverändert als Gruppen-Überschrift. `topic` ist also **keine feste -Auswahl**, sondern der Überschriftentext selbst (z. B. `Mensa und Mittagessen`) — -eine neue Gruppe entsteht einfach, indem eine Frage einen neuen `topic`-Text -bekommt; Fragen mit gleichem `topic` landen in derselben Gruppe. Auf Groß-/ -Kleinschreibung und Leerzeichen achten, sonst entstehen versehentlich zwei -Gruppen. Der Rahmentext oben auf `/faqs` ist eine eigene Seite in `pages` +Die FAQ-Seite `/faqs` besteht aus zwei Collections: **Themen** (`faq_topics`) und +**Fragen** (`faqs`). Jedes Thema erscheint als aufklappbare Gruppe, darin seine +Fragen. Eine Frage gehört zu genau einem Thema, das du aus einer Liste +**auswählst** — du tippst es nicht als Text ein. + +### Themen (`faq_topics`) + +Ein Thema hat `title`, `slug`, `intro` (optional), `order` und `public`. + +- `title` ist die Überschrift der Gruppe (z. B. `Mensa und Mittagessen`). +- `intro` ist ein kurzer Einleitungstext (Markdown), der beim Aufklappen über den + Fragen steht. +- `order` legt die Reihenfolge der Gruppen fest (kleinere Zahl zuerst). +- `slug` ist englisch, klein, ohne Umlaute (z. B. `lunch`) — dieselbe Regel wie + bei Seiten. Er wird derzeit nicht angezeigt, ist aber Pflicht. +- **Eine neue Gruppe** = ein neuer Record in `faq_topics`. Danach steht das Thema + bei den Fragen zur Auswahl. + +### Fragen (`faqs`) + +Eine Frage hat `question`, `answer` (Markdown), `topic`, `order` und `public`. + +- `topic`: das Thema aus `faq_topics` auswählen. +- `order` legt die Reihenfolge innerhalb des Themas fest (kleinere Zahl zuerst). + +> **Stolpersteine.** Eine Frage **ohne** `topic` erscheint nirgends auf der +> Website. Ist ein Thema nicht `public`, verschwinden auch alle seine Fragen — +> egal, ob diese selbst `public` sind. + +Überschrift und Rahmentext oben auf `/faqs` sind eine eigene Seite in `pages` (Slug `faqs`). --- @@ -180,7 +205,7 @@ Gruppen. Der Rahmentext oben auf `/faqs` ist eine eigene Seite in `pages` - **Nach dem Ändern einer Zugriffsregel** immer den Haupt-*Save* der Collection drücken, sonst greift die Änderung nicht. -- Die vier Collections sind öffentlich **lesbar** (List/View offen), aber nur +- Die fünf Collections sind öffentlich **lesbar** (List/View offen), aber nur eingeloggt **schreibbar** — ein Schreibversuch ohne Login wird abgewiesen. Das ist Absicht; nicht „vereinfachen". - **Backup:** Der gesamte Inhalt liegt in `pb_data`. Ein Backup dieses -- 2.54.0