Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3530167cc3 | ||
|
|
8fb5044062 |
No files matched your search
@@ -85,7 +85,7 @@ public record FaqTopic
|
|||||||
/// <remarks>
|
/// <remarks>
|
||||||
/// Convenience over <see cref="Expand"/>: questions name their topic, so
|
/// Convenience over <see cref="Expand"/>: questions name their topic, so
|
||||||
/// PocketBase returns them under the back-relation key when the query expands it
|
/// PocketBase returns them under the back-relation key when the query expands it
|
||||||
/// (<c>faqs_via_topic</c>). The topic detail page reads them from here. They
|
/// (<c>faqs_via_topic</c>). The FAQ page reads them from here. They
|
||||||
/// arrive unsorted, so this orders them by <see cref="Faq.Order"/> for a stable
|
/// arrive unsorted, so this orders them by <see cref="Faq.Order"/> for a stable
|
||||||
/// render. Drafts are dropped: PocketBase does not apply the topic query's
|
/// render. Drafts are dropped: PocketBase does not apply the topic query's
|
||||||
/// <c>public</c> filter to the expanded children, so this keeps
|
/// <c>public</c> filter to the expanded children, so this keeps
|
||||||
|
|||||||
+2
-2
@@ -28,8 +28,8 @@ architecture. Never global.
|
|||||||
## AE-2: Content in PocketBase, read per request (revised)
|
## AE-2: Content in PocketBase, read per request (revised)
|
||||||
|
|
||||||
**Decision:** All visible content lives in **PocketBase** (collections `pages`,
|
**Decision:** All visible content lives in **PocketBase** (collections `pages`,
|
||||||
`posts`, `events`, `faqs`); the app reads it over the REST API per request via a
|
`posts`, `events`, `faq_topics`, `faqs`); the app reads it over the REST API per
|
||||||
typed `PocketBaseClient`. Documents remain PDFs under `wwwroot`.
|
request via a typed `PocketBaseClient`. Documents remain PDFs under `wwwroot`.
|
||||||
|
|
||||||
**Original decision (stage 1):** Content as files in the repo — Markdown with YAML
|
**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,
|
frontmatter, events as `Content/events.yml`. The rationale then was: no DB backup,
|
||||||
|
|||||||
+1
-1
@@ -108,7 +108,7 @@ and the dev overlay mounts that folder into PocketBase (`./pb/pb_migrations:/pb_
|
|||||||
|
|
||||||
| File | Role |
|
| 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. |
|
||||||
| `<timestamp>_dev_seed.js` | The PocketBase migration. Reads the schema file, creates any missing collection, then inserts the example records. |
|
| `<timestamp>_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
|
Both steps are **idempotent**: a collection is created only if it is missing, and
|
||||||
|
|||||||
+40
-15
@@ -41,7 +41,8 @@ der passenden Collection (Button *New record*).
|
|||||||
| `pages` | Feste Seiten (Vorstand, Impressum, Kontakt …) | Slug, z. B. `/board` |
|
| `pages` | Feste Seiten (Vorstand, Impressum, Kontakt …) | Slug, z. B. `/board` |
|
||||||
| `posts` | Neuigkeiten / Beiträge | `/posts`, neueste zuerst |
|
| `posts` | Neuigkeiten / Beiträge | `/posts`, neueste zuerst |
|
||||||
| `events` | Termine (Kalender) | `/events` und der `.ics`-Feed |
|
| `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
|
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,
|
`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 |
|
| Was du willst | Geht redaktionell? | Wie |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| Beitrag / Termin / Frage hinzufügen | **Ja** | Neuer Record in `posts` / `events` / `faqs` — erscheint sofort in der jeweiligen Liste |
|
| 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) |
|
| 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 |
|
| **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*
|
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
|
`location` (`header` oder `footer`) und `order` (Reihenfolge, ab 1). Die App
|
||||||
baut Kopf- und Fußnavigation daraus; nichts wird im Markup angefasst.
|
baut Kopf- und Fußnavigation daraus; nichts wird im Markup angefasst.
|
||||||
- **Eingebettete Blöcke:** Das Feld `embed` (Mehrfachauswahl aus
|
- **Eingebettete Blöcke:** Das Feld `embed` (Mehrfachauswahl aus
|
||||||
`faqs`/`posts`/`events`) hängt unter den Text der Seite dynamische Blöcke. So
|
`posts`/`events`) hängt unter den Text der Seite dynamische Blöcke. So ist die
|
||||||
ist die Startseite (`home`) eine normale Seite mit `embed = [posts, events]`,
|
Startseite (`home`) eine normale Seite mit `embed = [posts, events]`. Leeres
|
||||||
und `/faqs` eine Seite mit `embed = [faqs]`. Leeres `embed` = reine Textseite.
|
`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`).
|
> **Impressum und Datenschutz** hängen an ihren Slugs (`imprint`, `privacy`).
|
||||||
> Diese Slugs nicht ändern — sonst laufen die rechtlich verlinkten Adressen ins
|
> 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
|
Die FAQ-Seite `/faqs` besteht aus zwei Collections: **Themen** (`faq_topics`) und
|
||||||
baut die FAQ-Seite generiert: sie gruppiert die Fragen nach `topic` und zeigt den
|
**Fragen** (`faqs`). Jedes Thema erscheint als aufklappbare Gruppe, darin seine
|
||||||
`topic`-Text unverändert als Gruppen-Überschrift. `topic` ist also **keine feste
|
Fragen. Eine Frage gehört zu genau einem Thema, das du aus einer Liste
|
||||||
Auswahl**, sondern der Überschriftentext selbst (z. B. `Mensa und Mittagessen`) —
|
**auswählst** — du tippst es nicht als Text ein.
|
||||||
eine neue Gruppe entsteht einfach, indem eine Frage einen neuen `topic`-Text
|
|
||||||
bekommt; Fragen mit gleichem `topic` landen in derselben Gruppe. Auf Groß-/
|
### Themen (`faq_topics`)
|
||||||
Kleinschreibung und Leerzeichen achten, sonst entstehen versehentlich zwei
|
|
||||||
Gruppen. Der Rahmentext oben auf `/faqs` ist eine eigene Seite in `pages`
|
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`).
|
(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
|
- **Nach dem Ändern einer Zugriffsregel** immer den Haupt-*Save* der Collection
|
||||||
drücken, sonst greift die Änderung nicht.
|
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
|
eingeloggt **schreibbar** — ein Schreibversuch ohne Login wird abgewiesen. Das
|
||||||
ist Absicht; nicht „vereinfachen".
|
ist Absicht; nicht „vereinfachen".
|
||||||
- **Backup:** Der gesamte Inhalt liegt in `pb_data`. Ein Backup dieses
|
- **Backup:** Der gesamte Inhalt liegt in `pb_data`. Ein Backup dieses
|
||||||
|
|||||||
Reference in new issue
Block a user