feat(presets): Bearbeitungs-Profile — YAML-Export/Import, Schritt-Checkboxen, Batch-Anwendung#9
Conversation
…-Checkboxen, Batch-Anwendung)
Erweitert das Preset-System um:
- YAML-Export/Import (Client-seitig, Pydantic bleibt Validierungs-Autoritaet)
- 8 logische Schritt-Gruppen als Checkboxen beim Anwenden (geteilte
infra/profiles/edit-groups.json als Single Source fuer FE+BE)
- nicht-destruktive Batch-Anwendung auf mehrere Bilder via neuem
atomaren POST /presets/{id}/apply
- Migration 009: nullable geometry-Spalte (Crop/Straighten/Lens)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…-Geo-Test, Cleanups) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Fix A: applyProfileGroups faellt bei null-Crop/-Lens im Profil auf defaultCropRect()/defaultLensCorrection() zurueck statt den aktuellen Bild-Wert zu behalten. Fix B: Zwei Store-Level-Tests fuer die null-Fallback-Faelle. Fix C: Array-Guard in parseProfileYaml fuer adjustments-Shape-Check. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
PresetDialog: Per-Preset-Button 'Laden' -> 'Anwenden' (oeffnet Schritt- Panel, merged via store.applyProfileGroups), YAML-Export je Preset und YAML-Import (parseProfileYaml -> api.createPreset), Geometry beim Speichern/Aktualisieren erfasst. Bestehende Tests + Screenshot-E2E auf den neuen Flow (preset-apply-* + apply-confirm) angepasst. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Playwright-Spec fuer den Library-Batch-Apply-Flow: zwei Bilder per API-Helper seeden, beide selektieren, Modal oeffnen, Default-Preset waehlen, bestaetigen, Toast 'N von N' verifizieren. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Schluessel-Dateien-Tabelle um edit-groups.json, profile_groups.py, profileGroups.ts, profileYaml.ts, StepCheckboxes.tsx, BatchApplyModal.tsx erweitert. Alembic-Versions-Eintrag um Migration 009 ergaenzt. Neues Gotcha fuer die Single-Source-JSON-Platzierung in backend/schemas/. Roadmap-Eintrag Phase P (Bearbeitungs-Profile) hinzugefuegt. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Der Vite-Build importiert backend/schemas/edit-groups.json, aber der Frontend-Docker-Build (context=Repo-Root) hatte sie nicht: Root-.dockerignore schloss backend/schemas aus und das Dockerfile kopierte nur infra/. Lokal/CI (pnpm build von der Platte) gruen, aber der Prod-Docker-Build waere gebrochen. - .dockerignore: backend/schemas/* aus, Ausnahme !backend/schemas/edit-groups.json - frontend/Dockerfile: COPY der Datei nach /app/backend/schemas/ vor pnpm build - CLAUDE.md-Gotcha korrigiert (Docker-Falle dokumentiert) Verifiziert via 'docker build --target build -f frontend/Dockerfile .' (gruen). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…bei 0 Gruppen Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
✅ End-to-end verifiziert (laufender Stack)Gegen einen komplett hochgefahrenen Stack getestet — Postgres + Keycloak + MinIO (Docker) + FastAPI-Backend (:8000) + Vite-Frontend (:5173), Migration auf GUI (echter Browser, Playwright/Chromium): Registrieren → 2 Bilder hochladen → beide selektieren → „Profil anwenden" → Preset wählen → anwenden → Toast „2 von 2 angewendet", Auswahl danach geleert. ✓ Merge-Semantik (Live-API, der Kern des Features):
Caveat: YAML-Export/Import wurde nicht im Live-Browser geklickt — abgedeckt durch Unit- (Serialize/Parse-Roundtrip) + Component-Tests (File-Input → Voller Gate ebenfalls grün: backend pytest 156, frontend tsc/lint/vitest (356)/build, plus Prod-Frontend-Docker-Build ( 🤖 Verifiziert mit Claude Code |
CI installiert Pillow nicht (keine Backend-Dep) -> Collection-Error 'No module named PIL'. Lokal lief es nur durch, weil Pillow zufaellig im venv lag. Auf das etablierte Muster aus test_images_api.py umgestellt: JPEG-Magic-Byte-Literal + urllib-PUT (Backend prueft nur Magic-Bytes, dekodiert nie). Kein neuer Dependency. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Summary
Erweitert das bestehende Preset-System (kein neues Entity, Marketplace unberührt) um drei Fähigkeiten:
.yamlherunterladen und wieder hochladen. Import läuft client-seitig (yaml-npm) und geht durchPOST /presets; Pydantic (extra="forbid", Ranges, Mask-Caps) bleibt Validierungs-Autorität. Versioniertes Format (lumenProfile: 1).backend/schemas/edit-groups.json), von Backend (Laufzeit) und Frontend (Vite-Build) gelesen — kein Drift.POST /presets/{id}/apply. Angehakte Gruppen überschreiben nur ihren Teil im gespeicherten Edit-State jedes Bildes, der Rest bleibt. Ownership/Ready wird vorab geprüft → all-or-nothing, ein Commit. UI: Mehrfachauswahl in der Bibliothek + Modal.Datenmodell: Migration 009 fügt eine nullable
geometryJSONB-Spalte zupresets(Crop/Straighten/Lens). Marketplace gibt Geometrie nie öffentlich aus.Implementierung
profile_groups.merge_edit_state(nicht-destruktiver Merge),PresetGeometry+BatchApplyIn/Out, Geometry im Preset-CRUD, Batch-Endpoint (rate-limited,ValidationError→400-Guard).profileGroups/mergeGroups,profileYaml,store.applyProfileGroups(gruppenweises Merge, ein Undo-Snapshot, geklemmte Geometrie),StepCheckboxes, PresetDialog (Anwenden-Panel + YAML + Geometry beim Speichern),BatchApplyModal+ Library-Mehrfachauswahl..dockerignore/frontend/Dockerfileso angepasst, dass der cross-repo JSON-Import auch im Prod-Docker-Build des Frontends auflöst (lokal/CI lief grün, der Docker-Build hätte sonst gebrochen).Test Plan
pytest -q— 156 passed (testcontainers; inkl. Merge-Logik, Geometry-Round-Trip, Batch-Apply: Ownership/400-ohne-Mutation, unknown-group/422, crop-ohne-Geometrie-cleart)tsc -b --noEmit·lint·vitest(356 passed, inkl. mergeGroups-Vollständigkeit, YAML-Round-Trip, applyProfileGroups inkl. Clamp & null-Crop/Lens) ·builddocker build --target build -f frontend/Dockerfile .) — grün (JSON-Import auflösbar)frontend/e2e/preset-profile.spec.tsgeschrieben (parst via--list; voller Lauf braucht laufenden Stack, nicht in PR-Pipeline)🤖 Generated with Claude Code