- Mindestbestand pro Liste/Produkt/Einheit (Tabelle stock_minimums): fällt der Vorrat darunter, füllt der Server die Einkaufsliste genau bis zur fehlenden Menge auf (nach Ändern, Aufgebraucht, Löschen, Setzen) - Laden-Kategorien (kategorien.py): automatische Zuordnung über Stichwörter (längstes Stichwort gewinnt), änderbar in der Zeile und im Vorschläge-Dialog; Einkaufsliste "A–Z" oder "Nach Laden" gruppiert; Reihenfolge der Abteilungen pro Liste - Rezeptsammlung (Tabelle recipes): "☆ Merken" beim Abgleich, "Was kann ich kochen?" sortiert gemerkte Rezepte nach vorhandenen Zutaten (Salz & Co. zählen nicht, nur sichtbare Produkte), vollständiger Abgleich per Klick - Migration Schritt 3 (Kategorien für bestehende Produkte); _add_column für Tabellen, die SCHEMA in alten Datenbanken schon neu angelegt hat - Tests in test_vorrat_extras.py Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
298 lines
16 KiB
Markdown
298 lines
16 KiB
Markdown
# P42 Dashboard
|
||
|
||
Persönliche Startseite mit Konten, universeller Sendungsverfolgung, Projekt-Artikeln,
|
||
gemeinsamer Vorrats- und Einkaufsliste (mit Rezeptabgleich), Reise-Weltkarte, Kanban-Boards,
|
||
Schnellzugriff auf Jellyfin, Audiobookshelf und Homer sowie Server-Monitoring.
|
||
Zwei umschaltbare Designs: Matrix und Blackwall.
|
||
|
||
- **Backend:** Python (FastAPI) – `backend/`
|
||
- **Frontend:** React (Vite, React Router, TipTap-Editor) – `frontend/`
|
||
|
||
## Zugehöriges Projekt: P42-S.M.
|
||
|
||
Die Server-Auslastung im Monitoring liefert der Agent **P42-S.M.** – ein eigenes Repository, das auf
|
||
dem zu überwachenden Server läuft: **https://github.com/guyg1474/p42.s-m**
|
||
Einrichtung dort in der README; danach hier im Monitoring eintragen (siehe [Monitoring](#monitoring)).
|
||
|
||
## Starten
|
||
|
||
```bash
|
||
./start.sh
|
||
```
|
||
|
||
Danach im Browser: http://localhost:3000
|
||
|
||
Das Skript legt beim ersten Mal die Python-Umgebung an, installiert die Pakete,
|
||
baut das Frontend (und baut es neu, sobald sich etwas in `frontend/src` ändert)
|
||
und startet den Server. Voraussetzungen: Python ≥ 3.11 und Node.js ≥ 20.
|
||
|
||
### Auf einem Server (Docker)
|
||
|
||
```bash
|
||
./deploy/update-docker.sh
|
||
```
|
||
|
||
Der Container öffnet nur einen internen Port (Standard `127.0.0.1:3000`), den ein nginx per HTTPS
|
||
nach außen gibt. Daten (`data/`) und Einstellungen (`config.json`) liegen außerhalb des Containers.
|
||
Einrichtung, Port-Optionen und nginx-Einstellungen: [DEPLOY.md](DEPLOY.md).
|
||
|
||
### Entwicklung (mit Live-Reload)
|
||
|
||
Zwei Terminals:
|
||
|
||
```bash
|
||
cd backend && RELOAD=1 .venv/bin/python -m app # API auf Port 3000
|
||
cd frontend && npm run dev # Oberfläche auf http://localhost:5173
|
||
```
|
||
|
||
Vite leitet `/api` und `/uploads` automatisch ans Backend weiter.
|
||
|
||
### Tests
|
||
|
||
```bash
|
||
cd backend
|
||
python3 -m pip --python .venv/bin/python install -r requirements-dev.txt # einmalig: pytest
|
||
.venv/bin/python -m pytest
|
||
```
|
||
|
||
Jeder Test bekommt eine frische, leere Datenbank. `tests/test_migrationen.py` baut ältere
|
||
Datenbank-Stände nach und prüft, dass der Start sie verlustfrei umstellt.
|
||
Die API-Dokumentation gibt es nur im Entwicklungsmodus (`RELOAD=1` oder `P42_API_DOCS=1`) unter
|
||
http://localhost:3000/api/docs – im Betrieb ist sie abgeschaltet.
|
||
|
||
## Konfiguration (`config.json`)
|
||
|
||
| Feld | Bedeutung |
|
||
|---|---|
|
||
| `port` | Port des Servers (Standard 3000) |
|
||
| `links` | Nur Startwerte für die Links des ersten Kontos (falls es keine alten Daten gibt) |
|
||
| `tracking.seventeenTrackApiKey` | API-Key von 17TRACK – universell, über 2000 Paketdienste |
|
||
| `tracking.dhlApiKey` | API-Key der DHL Shipment Tracking API (optional, für DHL-Sendungen) |
|
||
| `reisen.wikipediaKontakt` | Kontaktadresse, die bei Abrufen von Wikipedia/Wikidata mitgesendet wird (von Wikimedia verlangt). Leer = keine Wikipedia-Texte auf der Reise-Karte |
|
||
|
||
Nach Änderungen an `config.json` den Server neu starten.
|
||
|
||
## Konten
|
||
|
||
Die ganze Seite ist nur nach Anmeldung erreichbar.
|
||
|
||
- Beim allerersten Aufruf legst du das **erste Konto** an. Es wird Administrator und
|
||
übernimmt die bisherigen Projekte (als Autor) und Links.
|
||
- Weitere Konten legt ein Administrator unter **Menü → Benutzer verwalten** an
|
||
(dort auch: Passwort zurücksetzen, Admin-Rechte vergeben, Konten löschen).
|
||
- Unter **Menü → Mein Konto** ändert jeder seinen Anzeigenamen und sein Passwort.
|
||
- Pro Konto eigenständig: **Links** auf der Startseite, **Monitoring** und die **Reise-Karte**
|
||
(die Städte der anderen lassen sich auf der Karte einblenden).
|
||
- Gemeinsam für alle Konten: **Kanban**.
|
||
- **Vorrat & Einkauf** in Listen (z. B. Zuhause, Urlaub): wer eine Liste anlegt, bestimmt, ob alle
|
||
Konten sie sehen oder nur ausgewählte.
|
||
- **Artikel** sind gemeinsam: alle Konten können sie lesen und bearbeiten; angezeigt wird,
|
||
wer ihn geschrieben und wer ihn zuletzt geändert hat. Löschen dürfen nur der Autor und
|
||
Administratoren.
|
||
|
||
Passwort vergessen und kein anderer Admin vorhanden? Im Ordner `backend/`:
|
||
|
||
```bash
|
||
.venv/bin/python -m app.reset_password BENUTZERNAME
|
||
```
|
||
|
||
### Schnellzugriff-Links (Jellyfin, Audiobookshelf, Homer)
|
||
|
||
Jedes Konto hinterlegt seine eigenen Adressen auf der Startseite über
|
||
„✎ Links bearbeiten“ (oder durch Klick auf eine Kachel ohne Link).
|
||
|
||
### Monitoring
|
||
|
||
Jedes Konto pflegt seine eigene Serverliste. Geprüft wird alle 30 Sekunden:
|
||
|
||
- **Webseite (HTTP):** online, wenn die Adresse antwortet (auch mit Anmeldeseite o. Ä.).
|
||
- **Port (TCP):** online, wenn der Port Verbindungen annimmt, z. B. `192.168.0.10:22`.
|
||
- **Server-Auslastung ([P42-S.M.](https://github.com/guyg1474/p42.s-m)):** CPU, RAM, Platten, Load und Temperatur direkt auf der Karte.
|
||
Klick auf die Karte öffnet die große Ansicht mit allen Werten (alle 5 s aktualisiert) und dem Verlauf
|
||
der letzten 6 h, 24 h oder 2 Tage. Adresse `http://p42-sm:9142` (Agent auf demselben Server), dazu der
|
||
Token aus der `.env` von P42-S.M. Der Token wird nur im Backend gespeichert und nie an den Browser gegeben.
|
||
Für den Verlauf speichert das Dashboard jede Minute einen Mittelwert (Tabelle `monitor_samples`,
|
||
2 Tage lang) – auch wenn niemand die Seite offen hat.
|
||
|
||
Die Prüfung läuft vom Dashboard-Server aus – Adressen müssen also von dort erreichbar sein.
|
||
|
||
### Sendungsverfolgung
|
||
|
||
Ohne API-Key erkennt die Seite anhand des Nummernformats den wahrscheinlichen
|
||
Paketdienst und zeigt Links zur jeweiligen Tracking-Seite.
|
||
|
||
Für Live-Daten (Paketdienst, Status, voraussichtliche Ankunft, Verlauf):
|
||
|
||
- **17TRACK** (empfohlen, deckt DHL, Hermes, DPD, GLS, UPS, Post usw. ab):
|
||
Konto unter https://api.17track.net anlegen und den Key eintragen.
|
||
Der kostenlose Tarif hat ein begrenztes Kontingent an Sendungsnummern.
|
||
- **DHL** (optional, kostenlos): unter https://developer.dhl.com die API
|
||
„Shipment Tracking – Unified“ freischalten. DHL-Nummern werden dann direkt bei
|
||
DHL abgefragt, alles andere über 17TRACK.
|
||
|
||
### Projekte
|
||
|
||
Jedes Projekt ist ein Artikel mit Titelbild, Titel, Kurzbeschreibung, Status und
|
||
formatiertem Text (Überschriften, Listen, Zitate, Links, Bilder). Über „Bearbeiten“
|
||
wird der Artikel direkt auf der Seite geändert. Bilder lassen sich per Button,
|
||
Einfügen (Strg+V) oder Drag & Drop in den Text setzen.
|
||
|
||
Nicht mehr verwendete Bilder werden automatisch gelöscht. Der Artikeltext wird beim
|
||
Speichern serverseitig bereinigt; Bilder sind nur aus den eigenen Uploads erlaubt (fremde Bilder
|
||
würden beim Lesen IP-Adresse und Zeitpunkt an deren Server verraten).
|
||
|
||
Beim Hochladen entfernt der Server alle Metadaten aus Fotos (EXIF/XMP: GPS-Standort, Kamera,
|
||
Uhrzeit); die Drehung von Hochkant-Fotos bleibt erhalten. GIFs bleiben unverändert.
|
||
|
||
### Vorrat & Einkauf
|
||
|
||
Oben wählst du die **Liste**, z. B. „Zuhause“ oder „Urlaub“. Jede Liste hat zwei eigene Bereiche:
|
||
**Vorrat** (was da ist) und **Einkaufen** (was fehlt) – im Urlaub gibt es also einen eigenen Bestand
|
||
und einen eigenen Einkaufszettel.
|
||
|
||
- **Neue Liste:** „+ Neue Liste“ legt Vorrat und Einkauf zusammen neu an. Dabei festlegen, wer sie
|
||
sieht: **alle Konten** oder **nur ausgewählte**. Der Ersteller sieht seine Liste immer.
|
||
Name, Sichtbarkeit und Löschen („✎ Liste bearbeiten“) nur für den Ersteller und Administratoren –
|
||
Administratoren aber nur bei Listen, die sie sehen. Löschen entfernt Vorrat und Einkauf der Liste.
|
||
- Beim Update werden der bisherige Vorrat und die bisherige Einkaufsliste zur Liste „Zuhause“
|
||
(für alle sichtbar).
|
||
- **Mindestbestand** („⚑ Mindestbestand“ im Vorrat): pro Produkt eine Untergrenze, z. B. „Milch: immer 2“.
|
||
Fällt der Vorrat darunter (weniger, aufgebraucht, gelöscht), kommt genau die fehlende Menge auf die
|
||
Einkaufsliste. Die Zeile im Vorrat zeigt „min 2“, darunter hervorgehoben.
|
||
- **Nach Laden sortieren:** Die Einkaufsliste lässt sich nach Abteilungen gruppieren (Obst & Gemüse,
|
||
Kühlregal …). Neue Produkte bekommen ihre Kategorie automatisch (Stichwörter, `backend/app/kategorien.py`),
|
||
ändern lässt sie sich direkt in der Zeile oder unter „Vorschläge verwalten“. „⇅ Reihenfolge“ legt pro
|
||
Liste fest, in welcher Reihenfolge man durch seinen Laden geht.
|
||
- **Rezeptsammlung:** Ein abgeglichenes Rezept lässt sich mit „☆ Merken“ speichern (für alle Konten).
|
||
„Was kann ich kochen?“ zeigt die gemerkten Rezepte, sortiert danach, wie viele Zutaten im Vorrat der
|
||
gewählten Liste sind, und was noch fehlt; ein Klick gleicht das Rezept vollständig ab.
|
||
- **Vorschläge** beim Eintippen und die Zuordnung beim Rezeptabgleich kommen nur aus Listen, die man
|
||
sehen darf – Einträge privater Listen tauchen bei anderen nicht auf. „Vorschläge verwalten“ löscht
|
||
nur aus den eigenen sichtbaren Listen.
|
||
- Welche Liste gewählt ist, merkt sich der Browser. Gekauft, aufgebraucht, Nachkaufen und der
|
||
Rezeptabgleich wirken immer innerhalb der gewählten Liste.
|
||
- **Einkaufen:** Abhaken legt ein Produkt „in den Wagen“ – es rutscht nach unten, bleibt aber auf der
|
||
Einkaufsliste (für alle sichtbar, die die Liste sehen; erneut klicken nimmt den Haken zurück).
|
||
**„Einkauf beenden“** übernimmt alle abgehakten Produkte auf einmal in den Vorrat.
|
||
−‑Klick bei der letzten Einheit im Vorrat setzt ein Produkt auf die Einkaufsliste.
|
||
- **Rezept abgleichen:** Link zu einer Rezeptseite (z. B. Chefkoch) oder eine Zutatenliste
|
||
einfügen, Personenzahl angeben. Die Seite rechnet die Mengen um, vergleicht mit dem Vorrat
|
||
und setzt Fehlendes auf die Einkaufsliste. Eiweiß/Eigelb werden zu Eiern.
|
||
Abgerufen wird nur die eingefügte Seite (schema.org-Rezeptdaten); Links ins eigene Netz
|
||
werden abgelehnt.
|
||
|
||
### Reisen
|
||
|
||
Weltkarte pro Konto: Städte, in denen man war, als Punkte; besuchte Länder ausgemalt.
|
||
Klick auf Land oder Punkt zoomt hin und zeigt unten links Infos (Länderdaten lokal,
|
||
Texte aus Wikipedia, Einwohner aus Wikidata, Orte über Open-Meteo/GeoNames).
|
||
|
||
Der Schalter **Städte anderer zeigen** (über der Karte) blendet die Städte der übrigen Konten ein – je Person in einer eigenen Farbe,
|
||
einzelne Personen lassen sich über ihre Schaltfläche aus- und einblenden (gemerkt pro Browser). Fremde
|
||
Städte kann man nur ansehen, nicht ändern. Alle angemeldeten Konten können die Städte der anderen sehen.
|
||
|
||
**⤓ Karte herunterladen** speichert die eigenen Städte und besuchten Länder als Bild; Ausschnitt
|
||
„Meine Orte“ (auf die Städte gezoomt) oder ganze Welt:
|
||
|
||
- **PNG** (4000 oder 8000 px breit): gut sichtbare Punkte, beschriftet sind nur besuchte **Hauptstädte**.
|
||
- **SVG** (beliebig scharf zoombar, z. B. zum Drucken): kleine Punkte und Schrift, **alle** Städte
|
||
beschriftet – dicht liegende Orte trennen sich beim Hineinzoomen.
|
||
|
||
Beschriftungen weichen einander aus, wenn nötig mit Linie zum Punkt. Farben kommen aus dem gewählten
|
||
Design; erstellt wird das Bild im Browser. Ob eine Stadt Hauptstadt ist, liefert die Städtesuche
|
||
(GeoNames-Merkmal „PPLC“); bei älteren Einträgen trägt der Server das im Hintergrund nach.
|
||
|
||
### Kanban
|
||
|
||
Beliebig viele Projekte mit je einem Board (Offen, In Arbeit, Wartet, Erledigt). Aufgaben
|
||
haben Titel, Beschreibung, Status und Bearbeiter; verschieben per Drag & Drop oder im Dialog.
|
||
Projekte lassen sich mit Artikeln aus „P42 Projekte“ verknüpfen, abschließen, wieder öffnen
|
||
und löschen (löschen: wer angelegt hat und Administratoren).
|
||
|
||
- **Checkliste** je Aufgabe: Punkte im Aufgaben-Dialog anlegen und abhaken; die Karte zeigt den Stand (☑ 2/5).
|
||
- **Voraussetzungen:** Im Dialog unter „Setzt voraus“ andere Aufgaben desselben Projekts wählen. Solange eine
|
||
davon nicht erledigt ist, ist die Aufgabe gesperrt (🔒, bleibt in „Offen“). Kreise werden abgelehnt.
|
||
|
||
Erledigte Aufgaben räumen sich selbst auf: **2 Tage** nach „Erledigt“ verschwinden sie ins **Archiv**
|
||
(Button „Archiv (n)“ im Board, dort auch „Zurückholen“), **14 Tage** nach „Erledigt“ werden sie
|
||
automatisch gelöscht. Zurück aus „Erledigt“ hält die Uhr an; „Zurückholen“ startet beide Fristen neu.
|
||
Gelöscht wird stündlich im Hintergrund und beim Öffnen eines Boards.
|
||
|
||
### Designs
|
||
|
||
Im Menü unter **Design** umschaltbar, gespeichert pro Browser:
|
||
|
||
| Design | Stil |
|
||
|---|---|
|
||
| Matrix | rotes Retro-Terminal mit Matrix-Regen (Standard) |
|
||
| Blackwall | Cyberpunk-Netrunner: Pink-Rot mit Cyan, leuchtende Datenwand, abgeschrägte Panels |
|
||
| Fabrik | Industrie-Inventar à la Satisfactory: Stahlplatten mit Schrauben, gelb leuchtende Buttons, orange Mengen-Zähler, Warnstreifen, drehende Zahnräder |
|
||
|
||
„Animation: an/aus“ im Menü stoppt alle Hintergrund-Animationen; bei „Bewegung reduzieren“
|
||
im Betriebssystem sind sie automatisch aus. Die Designs sind von den Vorbildern inspiriert,
|
||
ohne Original-Logos; alle Schriften sind frei (OFL) und lokal eingebunden.
|
||
Quellen und Lizenzen: `docs/CREDITS.md`.
|
||
|
||
## Daten & Backup
|
||
|
||
Alles liegt im Ordner `data/`: die Datenbank `p42.db` (Konten, Projekte, Links,
|
||
Monitoring, Vorrat, Reisen, Kanban) und die Bilder in `uploads/`. Neue Tabellen und
|
||
Spalten legt der Server beim Start selbst an: nummerierte Umstellungen in `backend/app/migrations.py`,
|
||
der erreichte Stand steht in der Datenbank (`PRAGMA user_version`). Für ein Backup den Server kurz stoppen und
|
||
den Ordner `data/` sichern. Ältere `projects.json`/`links.json` werden beim ersten Start
|
||
automatisch übernommen und danach in `*.importiert` umbenannt.
|
||
|
||
## Aufbau
|
||
|
||
```
|
||
start.sh Einrichten + Starten (lokal, ohne Docker)
|
||
Dockerfile, docker-compose.yml Betrieb auf dem Server, siehe DEPLOY.md
|
||
deploy/update-docker.sh Container bauen/aktualisieren
|
||
config.json Einstellungen (nicht ins Git)
|
||
data/ Datenbank und Bilder (nicht ins Git)
|
||
|
||
backend/
|
||
requirements.txt
|
||
app/main.py FastAPI: API-Routen, Uploads, Auslieferung des Frontends
|
||
app/config.py liest config.json
|
||
app/common.py Gemeinsame Helfer: Eingabefehler, Texte prüfen, Zeitstempel, Kontenliste
|
||
app/db.py SQLite-Schema (neuester Stand), Verbindungen, Übernahme alter JSON-Daten
|
||
app/migrations.py Nummerierte Umstellungen bestehender Datenbanken (Regel steht oben in der Datei)
|
||
app/auth.py Konten, Anmeldung, Benutzerverwaltung
|
||
app/projects.py Projekte/Artikel, Bild-Uploads
|
||
app/htmlclean.py Artikel-HTML bereinigen (nur eigene Bilder)
|
||
app/bilder.py Metadaten (GPS usw.) aus hochgeladenen Bildern entfernen
|
||
app/links.py Schnellzugriff-Links pro Konto
|
||
app/monitoring.py Monitoring pro Konto (HTTP/TCP-Prüfung, P42-S.M.-Auslastung + Verlauf)
|
||
app/haushalt.py Listen (je Vorrat + Einkauf) mit Sichtbarkeit, Produktkatalog, Einheiten
|
||
app/rezept.py Rezeptabgleich (Seite abrufen, Zutaten zerlegen, zuordnen), Rezeptsammlung
|
||
app/kategorien.py Laden-Kategorien und automatische Zuordnung neuer Produkte
|
||
app/reisen.py Reise-Karte, Städtesuche, Infos aus Wikipedia/Wikidata
|
||
app/kanban.py Kanban-Projekte, Aufgaben, Artikel-Verknüpfungen, Archiv + automatisches Löschen
|
||
app/tracking/ Paketdienst-Erkennung, 17TRACK, DHL
|
||
|
||
frontend/
|
||
src/main.jsx Routen
|
||
src/api.js API-Aufrufe, Bild-Upload
|
||
src/auth.jsx Anmeldestatus
|
||
src/styles/index.css Bindet alle Styles in fester Reihenfolge ein (Kommentar dort beachten)
|
||
src/styles/base.css Tokens (Farben, Schrift, Form) und Matrix als Standard-Design
|
||
src/styles/<bereich>.css layout, components, start, projekte, monitoring, haushalt, reisen, kanban, konto
|
||
src/styles/grundschicht.css Bereichsübergreifend: einheitliche Eingabefelder, Hover, Bewegung (kommt nach den Bereichen)
|
||
src/styles/responsive.css Handy-Anpassungen, weniger Bewegung
|
||
src/styles/designs/ Blackwall und Fabrik (überschreiben vor allem Tokens)
|
||
src/theme.js, motion.js Design-Auswahl, Animations-Schalter
|
||
src/useLiveData.js Laden, regelmäßiges Nachladen und Speichern einer Seite (gemeinsamer Hook)
|
||
src/storage.js Kleine Einstellungen pro Browser (localStorage)
|
||
src/components/Layout.jsx Kopfzeile + Menü
|
||
src/components/<bereich>/ Bausteine je Bereich: haushalt, reisen, kanban, monitoring, projekte, start,
|
||
design (Hintergründe der Designs)
|
||
src/pages/ Seiten: Login, Start, Projekte, Artikel, Vorrat, Reisen, Kanban, Monitoring, …
|
||
src/data/laender.json Länderdaten (aus world-countries, ODbL)
|
||
public/maps/ Weltkarte (Natural Earth über world-atlas)
|
||
|
||
docs/ Design-Brief, Bibliotheken, Quellen & Lizenzen
|
||
```
|
||
|
||
`_alt-node/` (nur lokal, nicht im Repository) enthält die frühere Node.js-Version und kann gelöscht werden.
|