Files
putzliga/README.md

300 lines
9.2 KiB
Markdown

# Putzliga
Putzliga ist eine moderne, leichte Haushaltsaufgaben-Web-App mit spielerischem Charakter. Version 1 setzt auf Flask, SQLite, Jinja-Templates, responsives CSS, minimales JavaScript und eine saubere PWA-/Web-Push-Basis. Die App ist für mehrere Nutzer ausgelegt, läuft lokal sehr unkompliziert und ist so vorbereitet, dass sie auf Cloudron direkt als Container-App betrieben werden kann.
## Features
- Mehrere Nutzer mit Login, Registrierung und Profil-/Avatar-Einstellungen
- Trennung zwischen `TaskTemplate` und `TaskInstance`
- Aufgaben anlegen, bearbeiten, zuweisen und erledigen
- Wiederholungen für einmalig, alle X Tage, alle X Wochen und alle X Monate
- Saubere Erledigungslogik für fremd zugewiesene Aufgaben mit Auswahl, wer wirklich erledigt hat
- Statuslogik für offen, bald fällig, überfällig und erledigt
- `Meine Aufgaben`, `Alle Aufgaben`, `Aufgabe erstellen`, `Kalender/Liste`, `Highscoreboard`, `Optionen`
- Monats-Highscore mit Badge-Boni und Balkendarstellung
- Monatsarchiv über `MonthlyScoreSnapshot`
- PWA mit `manifest.json`, Service Worker, App-Icons und iOS-freundlicher Installationsbasis
- Echte Web-Push-Architektur mit gespeicherten `PushSubscription`s
- CLI-Kommandos für Archivierung und serverseitig triggerbare Benachrichtigungen
- Cloudron-/Container-tauglicher Start mit `start.sh`, `Dockerfile` und `CloudronManifest.json`
- Keine freie Registrierung nach dem ersten Nutzer; weitere Nutzer lassen sich kontrolliert per CLI anlegen
## Projektstruktur
```text
app/
routes/
services/
static/
css/
fonts/
icons/
images/
js/
manifest.json
service-worker.js
templates/
auth/
partials/
scoreboard/
settings/
tasks/
app.py
config.py
seed.py
start.sh
Dockerfile
CloudronManifest.json
requirements.txt
.env.example
scripts/
data/
```
## Lokale Daten vs. Cloudron-Inhalte
Die App ist jetzt so vorbereitet, dass lokale Entwicklungsdaten nicht versehentlich mit nach Cloudron wandern:
- `data/` ist in `.gitignore` ausgeschlossen und wird nicht committed
- `data/` ist zusätzlich in `.dockerignore` ausgeschlossen und landet nicht im Docker-Build-Kontext
- Uploads liegen standardmäßig ebenfalls unter `data/uploads` und bleiben damit lokal bzw. im persistenten Cloudron-Storage
- Beim ersten Cloudron-Start wird keine lokale Entwicklungsdatenbank ins Image kopiert
Damit kannst du lokal mit Seed-Daten entwickeln und online unabhängig davon echte Inhalte pflegen.
## Lokales Setup
### 1. Abhängigkeiten installieren
```bash
python3 -m venv .venv
. .venv/bin/activate
pip install -r requirements.txt
```
### 2. Umgebungsvariablen setzen
```bash
cp .env.example .env
```
Wichtige Variablen:
- `SECRET_KEY`: Flask Secret Key
- `DATA_DIR`: Persistentes Datenverzeichnis
- `DATABASE_PATH`: SQLite-Datei
- `UPLOAD_FOLDER`: Upload-Verzeichnis für Avatare
- `APP_BASE_URL`: Vollständige Basis-URL der App, wichtig für Push-Links
- `APP_TIMEZONE`: Standardmäßig `Europe/Berlin`
- `VAPID_PUBLIC_KEY` / `VAPID_PRIVATE_KEY`: Web-Push-Schlüssel
- `VAPID_CLAIMS_SUBJECT`: Kontaktadresse für VAPID
### 3. App-Icons erzeugen
Die Raster-Icons liegen als generierte Dateien im Projekt. Falls du sie neu erzeugen willst:
```bash
python scripts/generate_assets.py
```
### 4. Datenbank und Seed-Daten anlegen
```bash
flask --app app.py init-db
python seed.py
```
Demo-Logins:
- `anna@putzliga.local` / `putzliga123`
- `ben@putzliga.local` / `putzliga123`
## Nutzer anlegen
Freie Registrierung ist deaktiviert, sobald mindestens ein Nutzer existiert.
- Wenn die Datenbank noch leer ist, darf genau der erste Nutzer über `/register` angelegt werden.
- Weitere Nutzer legst du kontrolliert per CLI an:
```bash
flask --app app.py create-user
```
### 5. Entwicklungsserver starten
```bash
flask --app app.py run --debug
```
oder produktionsnah:
```bash
./start.sh
```
## Seed-Daten
Die Seed-Datei erzeugt:
- 2 Beispielnutzer
- wiederkehrende und einmalige Vorlagen
- offene, bald fällige, überfällige und erledigte Aufgaben
- Punkte im aktuellen Monat
- erledigte Aufgaben aus dem Vormonat, damit das Archiv direkt sichtbar ist
- Standard-Badges für Frühstarter, Serien und Monatsmenge
## Datenmodell
Umgesetzt sind die Kernmodelle:
- `User`
- `TaskTemplate`
- `TaskInstance`
- `MonthlyScoreSnapshot`
- `PushSubscription`
- `NotificationLog`
Zusätzlich für Version 1:
- `BadgeDefinition` für pflegbare Badge-Regeln in den Optionen
Wichtig: `TaskTemplate` beschreibt die wiederverwendbare Vorlage, `TaskInstance` die konkrete Aufgabe mit Fälligkeit, Status und tatsächlicher Erledigung.
## Monatsarchivierung
Putzliga speichert keine monatlichen Punktetotale als Live-Zähler. Stattdessen wird der Monatsstand aus erledigten `TaskInstance`s berechnet. Dadurch startet jeder neue Monat automatisch bei 0, weil nur Aufgaben des aktuellen Monats zählen.
Die Archivierung funktioniert so:
- Vor Requests wird geprüft, ob bis zum Vormonat Archive fehlen
- Fehlende Monate werden als `MonthlyScoreSnapshot` erzeugt
- Archivwerte enthalten erledigte Aufgaben und Badge-Boni des jeweiligen Monats
- Frühere Monate bleiben dauerhaft sichtbar
Zusätzlicher CLI-Trigger:
```bash
flask --app app.py archive-months
```
## Push-Benachrichtigungen
Putzliga nutzt echte Web-Push-Benachrichtigungen mit Service Worker und VAPID.
### Architektur
- Browser registriert Service Worker
- Subscription wird pro Nutzer in `PushSubscription` gespeichert
- Server versendet über `pywebpush`
- Versand ist getrennt in Prüf- und Ausführungslogik
- Logs werden in `NotificationLog` dedupliziert
### Verfügbare Trigger
```bash
flask --app app.py notify-due
flask --app app.py notify-monthly-winner
```
`notify-due`:
- prüft offene Aufgaben, die heute oder morgen fällig sind
- berücksichtigt die Nutzeroption `notification_task_due_enabled`
`notify-monthly-winner`:
- sendet am 1. des Monats ab 09:00 Uhr
- verweist auf das Scoreboard/Archiv des letzten Monats
- berücksichtigt `notification_monthly_winner_enabled`
Für iPhone/iPad muss zusätzlich sichergestellt sein, dass der Server ausgehend Apple Web Push erreichen kann. Laut WebKit sollten dafür Verbindungen zu `*.push.apple.com` möglich sein.
### Produktiver Betrieb
Auf Cloudron oder einem anderen Server solltest du diese Kommandos regelmäßig per Cronjob oder Task ausführen, zum Beispiel:
```bash
flask --app /app/app.py notify-due
flask --app /app/app.py notify-monthly-winner
```
### iPhone-/iOS-Hinweis
Web-Push auf iPhone/iPad funktioniert nur in neueren iOS-/iPadOS-Versionen, wenn die Web-App über Safari zum Home-Bildschirm hinzugefügt wurde. Innerhalb eines normalen Safari-Tabs stehen Push-Berechtigungen nicht zuverlässig zur Verfügung.
## PWA
Enthalten sind:
- `app/static/manifest.json`
- `app/static/service-worker.js`
- `app/static/images/pwa-icon-192.png`
- `app/static/images/pwa-icon-512.png`
- `app/static/images/apple-touch-icon.png`
- `app/static/images/pwa-badge.png`
Der Service Worker cached die App-Shell und Assets pragmatisch für eine stabile Basis. Für Version 1 ist das bewusst schlank gehalten.
## Branding und Assets aus `heinz.marketing`
Aus `../heinz.marketing` wurden bewusst nur verwertbare Grundlagen übernommen:
- `Inter` und `Space Grotesk` aus `css/fonts/`
- ausgewählte lokale SVG-Icons aus `css/fontawesome-pro-plus-7.0.0-web/svgs-full/chisel-regular/`
Diese Assets wurden nicht unverändert als fertiges Branding übernommen. Putzliga nutzt darauf aufbauend:
- eine eigene helle, iOS-nahe Farbwelt
- ein neues App-Logo (`app/static/images/logo.svg`)
- ein eigenes Favicon (`app/static/images/favicon.svg`)
- eigene generierte PWA-Raster-Icons (`scripts/generate_assets.py`)
## Cloudron
Cloudron-Dateien im Projekt:
- `Dockerfile`
- `start.sh`
- `CloudronManifest.json`
Die Manifest- und Docker-Struktur orientiert sich an der aktuellen Cloudron-Dokumentation für Docker-/Container-Apps:
https://docs.cloudron.io/docker/
### Wichtige Punkte für Cloudron
- App hört auf `PORT` und standardmäßig auf `8000`
- `DATA_DIR` und `UPLOAD_FOLDER` sollten im persistenten Storage liegen
- SQLite-Datei liegt standardmäßig unter `/app/data/putzliga.db`
- `start.sh` initialisiert die DB und startet Gunicorn
- `APP_BASE_URL` kann auf Cloudron über `CLOUDRON_APP_ORIGIN` gesetzt oder daraus abgeleitet werden
- Lokale Testdaten aus `data/` werden weder committed noch in das Docker-Image gepackt
### Beispielstart in Cloudron-/Container-Umgebungen
```bash
./start.sh
```
## Hilfsskripte
VAPID-Schlüssel generieren:
```bash
python scripts/generate_vapid_keys.py
```
Der ausgegebene `VAPID_PRIVATE_KEY` ist bereits `.env`-freundlich mit escaped Newlines formatiert. `config.py` wandelt `\\n` beim Start automatisch in echte Zeilenumbrüche zurück.
Icons neu generieren:
```bash
python scripts/generate_assets.py
```
## Hinweise für spätere Erweiterungen
- Maluslogik für verspätete Erledigungen kann an `compute_monthly_scores()` und `TaskInstance` ergänzt werden
- echte Admin-/Rollenrechte können ergänzt werden, aktuell dürfen bewusst alle Nutzer Aufgaben pflegen
- Scheduler kann auf Cloudron später als separater Task sauber ausgelagert werden
- Badge-Awards könnten in einer eigenen Tabelle historisiert werden, falls spätere Regeln rückwirkungsfrei versioniert werden sollen