Stapel-Import und automatischer Titel
Beim Erstbestand sind viele Teile auf einmal zu erfassen. Der Aufwand
steckt nicht im Fotografieren, sondern im Rundlauf pro Stück. Darum:
- Stapel-Import: erst alles mit der Kamera-App fotografieren, dann alle
Fotos auf einmal hochladen. Pro Foto entsteht ein Entwurf, die Details
kommen später. Bewusst ohne capture="environment" - das erzwingt ein
Foto pro Vorgang und schliesst multiple aus.
- Titel wird optional und sonst aus Kategorie und Grösse gebildet
("Hose 98/104"). Erzeugt beim Anzeigen, nicht beim Speichern, damit er
einer späteren Korrektur der Grösse folgt.
Daraus folgt ein neuer Status "draft" im Datenmodell; title und size
müssen NULL erlauben. Entwürfe erscheinen nicht in der Galerie.
Ausserdem HEIC in Phase 2 aufgenommen: iPhones nehmen so auf, und beim
Stapel-Import fiele ein nicht lesbares Bild sonst still hinten runter.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GR4bNaj9GtRu57J4Niii8o
This commit is contained in:
@@ -76,7 +76,7 @@ getarntes Skript ebenfalls.
|
||||
|
||||
## Datenmodell – Abweichungen von `projekt.md`
|
||||
|
||||
Das Schema wird grundsätzlich übernommen. Vier Ergänzungen:
|
||||
Das Schema wird grundsätzlich übernommen. Fünf Ergänzungen:
|
||||
|
||||
1. **Feste Wertelisten statt freier VARCHAR.** `gender`, `season`, `condition`
|
||||
und `status` bekommen ein Python-Enum plus `CHECK`-Bedingung in der
|
||||
@@ -97,12 +97,65 @@ Das Schema wird grundsätzlich übernommen. Vier Ergänzungen:
|
||||
4. **`updated_at`** wird in der Anwendung gesetzt, nicht per DB-Trigger –
|
||||
bleibt so unabhängig von SQLite-Eigenheiten.
|
||||
|
||||
5. **Status `draft` (neu).** `projekt.md` kennt nur `available`, `reserved`
|
||||
und `given_away`. Der Stapel-Import (siehe unten) legt Einträge an, die
|
||||
noch keinen Titel und keine Grösse haben – die dürfen nicht in der
|
||||
öffentlichen Galerie erscheinen. `title` und `size` müssen dafür
|
||||
`NULL` erlauben; gefüllt sein müssen sie erst beim Wechsel auf
|
||||
`available`.
|
||||
|
||||
Ausserdem: beim Löschen eines Eintrags müssen die **Bilddateien mitgelöscht**
|
||||
werden, sonst wächst das Upload-Verzeichnis unbegrenzt mit verwaisten Dateien.
|
||||
`ON DELETE CASCADE` räumt nur die Datenbankzeilen weg, nicht die Dateien.
|
||||
|
||||
---
|
||||
|
||||
## Schnelles Erfassen
|
||||
|
||||
Beim Erstbestand sind auf einen Schlag viele Teile zu erfassen. Der Aufwand
|
||||
steckt dabei nicht im Fotografieren, sondern im Rundlauf pro Stück: Formular
|
||||
öffnen, fotografieren, Felder ausfüllen, speichern, von vorn. Zwei Massnahmen
|
||||
dagegen.
|
||||
|
||||
### Stapel-Import
|
||||
|
||||
Zuerst wird alles mit der gewohnten Kamera-App fotografiert – die ist fürs
|
||||
schnelle Knipsen gebaut, ohne Umweg über den Browser. Danach **einmal** ins
|
||||
Formular, alle Fotos auf einmal auswählen:
|
||||
|
||||
```html
|
||||
<input type="file" name="fotos" accept="image/*" multiple>
|
||||
```
|
||||
|
||||
Pro Foto entsteht ein Eintrag mit Status `draft`. Die Details werden später
|
||||
nachgetragen – in Ruhe, auch am Rechner mit richtiger Tastatur. Damit ist
|
||||
Fotografieren vom Erfassen entkoppelt.
|
||||
|
||||
Bewusst **ohne** `capture="environment"`: das springt zwar direkt in die
|
||||
Rückkamera, erzwingt aber ein Foto pro Vorgang und schliesst `multiple` aus.
|
||||
Für einzelne Nachträge im Alltag ist es passend – dann als zweiter, kleiner
|
||||
Knopf „Direkt fotografieren" neben dem regulären Feld.
|
||||
|
||||
Nötig dafür:
|
||||
- Ansicht „Unfertige Einträge (12)", nur für angemeldete Benutzer
|
||||
- Entwürfe erscheinen nicht in der Galerie und nicht in `GET /api/v1/items`,
|
||||
solange dort nicht ausdrücklich `status=draft` angefragt wird
|
||||
- Ein Entwurf wird erst zu `available`, wenn Grösse und Kategorie gesetzt sind
|
||||
|
||||
### Titel ist freiwillig
|
||||
|
||||
`title` wird optional. Bleibt das Feld leer, setzt die Anwendung ihn aus
|
||||
Kategorie und Grösse zusammen – „Hose 98/104", „Winterjacke 116". Das ist
|
||||
genau die Angabe, nach der man in einer Galerie ohnehin sucht, und spart beim
|
||||
Erfassen das mit Abstand lästigste Feld, weil es als einziges freien Text
|
||||
verlangt.
|
||||
|
||||
Erzeugt wird der Titel **beim Anzeigen**, nicht beim Speichern: sonst bliebe
|
||||
ein automatisch gesetzter Titel stehen, wenn später die Grösse korrigiert
|
||||
wird. In der Datenbank bleibt `title` dann schlicht `NULL`.
|
||||
|
||||
---
|
||||
|
||||
## Absicherung
|
||||
|
||||
Die App ist aus dem Internet erreichbar, also gelten hier andere Massstäbe als
|
||||
@@ -181,9 +234,15 @@ Die Phasen aus `projekt.md`, ergänzt um Tests und die Absicherung.
|
||||
**Phase 2 – Bilder**
|
||||
- Upload per `multipart/form-data`, mehrere Bilder pro Eintrag
|
||||
- Prüfung und WebP-Konvertierung (max. 1200 px Breite) nach Abschnitt 1 oben
|
||||
- **HEIC unterstützen** (`pillow-heif`): iPhones nehmen in diesem Format auf.
|
||||
Safari wandelt beim Hochladen über ein Datei-Feld meist selbst nach JPEG
|
||||
um – aber nicht zuverlässig, und beim Stapel-Import fällt ein einzelnes
|
||||
nicht lesbares Bild sonst still hinten runter. Pillow allein kann HEIC
|
||||
nicht öffnen.
|
||||
- Ausliefer-Route, `is_primary`-Logik, Aufräumen beim Löschen
|
||||
- Prüfpunkt: bewusst fehlerhafte Uploads (zu gross, falscher Typ, riesige
|
||||
Pixelmasse, `.php` als `.jpg` getarnt) werden alle abgewiesen
|
||||
Pixelmasse, `.php` als `.jpg` getarnt) werden alle abgewiesen; ein
|
||||
HEIC-Bild wird angenommen
|
||||
|
||||
**Phase 3 – Absicherung**
|
||||
- Anmeldung, Sitzung, CSRF, Rate-Limits, Sicherheits-Header
|
||||
@@ -192,10 +251,12 @@ Die Phasen aus `projekt.md`, ergänzt um Tests und die Absicherung.
|
||||
|
||||
**Phase 4 – Oberfläche**
|
||||
- Mobile-First-Layout, Galerie mit Filterleiste (HTMX)
|
||||
- Detailseite, Erfassungsformular mit Kamera-Aufnahme
|
||||
(`<input type="file" accept="image/*" capture="environment">`)
|
||||
- Detailseite und Erfassungsformular
|
||||
- **Stapel-Import** mit Entwurfsliste zum Nachtragen (siehe „Schnelles
|
||||
Erfassen"), dazu der automatische Titel aus Kategorie und Grösse
|
||||
- Reservierungs-Ablauf inklusive Selbst-Freigabe
|
||||
- Prüfpunkt: der ganze Weg auf einem echten Smartphone
|
||||
- Prüfpunkt: der ganze Weg auf einem echten Smartphone – 20 Fotos in einem
|
||||
Rutsch hochladen, danach die Entwürfe abarbeiten
|
||||
|
||||
**Phase 5 – Betrieb**
|
||||
- `Dockerfile` (Tailwind-Build inbegriffen), `docker-compose.yml`, Volumes
|
||||
|
||||
Reference in New Issue
Block a user