first commit
This commit is contained in:
285
README.md
Normal file
285
README.md
Normal file
@@ -0,0 +1,285 @@
|
||||
# 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`
|
||||
|
||||
## 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`
|
||||
|
||||
### 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`
|
||||
|
||||
### 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
|
||||
Reference in New Issue
Block a user