Skip to content

feat(presets): Bearbeitungs-Profile — YAML-Export/Import, Schritt-Checkboxen, Batch-Anwendung#9

Merged
phash merged 23 commits into
mainfrom
feat/preset-profile-export-batch
Jun 6, 2026
Merged

feat(presets): Bearbeitungs-Profile — YAML-Export/Import, Schritt-Checkboxen, Batch-Anwendung#9
phash merged 23 commits into
mainfrom
feat/preset-profile-export-batch

Conversation

@phash
Copy link
Copy Markdown
Owner

@phash phash commented Jun 6, 2026

Summary

Erweitert das bestehende Preset-System (kein neues Entity, Marketplace unberührt) um drei Fähigkeiten:

  • YAML-Export/Import — Profile als .yaml herunterladen und wieder hochladen. Import läuft client-seitig (yaml-npm) und geht durch POST /presets; Pydantic (extra="forbid", Ranges, Mask-Caps) bleibt Validierungs-Autorität. Versioniertes Format (lumenProfile: 1).
  • Schritt-Checkboxen beim Anwenden — 8 logische Gruppen (Belichtung&Ton / Farbe&WB / HSL / Tonkurve / Detail / Masken / Crop&Geometrie / Objektiv) einzeln de-/aktivierbar. Crop & Objektiv default aus (bildspezifisch). Gruppen→Feld-Mapping als Single-Source-JSON (backend/schemas/edit-groups.json), von Backend (Laufzeit) und Frontend (Vite-Build) gelesen — kein Drift.
  • Nicht-destruktive Batch-Anwendung — ein Profil auf 1..N Bilder anwenden via neuem atomarem 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 geometry JSONB-Spalte zu presets (Crop/Straighten/Lens). Marketplace gibt Geometrie nie öffentlich aus.

Implementierung

  • Backend: profile_groups.merge_edit_state (nicht-destruktiver Merge), PresetGeometry + BatchApplyIn/Out, Geometry im Preset-CRUD, Batch-Endpoint (rate-limited, ValidationError→400-Guard).
  • Frontend: profileGroups/mergeGroups, profileYaml, store.applyProfileGroups (gruppenweises Merge, ein Undo-Snapshot, geklemmte Geometrie), StepCheckboxes, PresetDialog (Anwenden-Panel + YAML + Geometry beim Speichern), BatchApplyModal + Library-Mehrfachauswahl.
  • Infra: .dockerignore/frontend/Dockerfile so 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

  • Backend pytest -q — 156 passed (testcontainers; inkl. Merge-Logik, Geometry-Round-Trip, Batch-Apply: Ownership/400-ohne-Mutation, unknown-group/422, crop-ohne-Geometrie-cleart)
  • Frontend tsc -b --noEmit · lint · vitest (356 passed, inkl. mergeGroups-Vollständigkeit, YAML-Round-Trip, applyProfileGroups inkl. Clamp & null-Crop/Lens) · build
  • Prod-Frontend-Docker-Build (docker build --target build -f frontend/Dockerfile .) — grün (JSON-Import auflösbar)
  • E2E-Spec frontend/e2e/preset-profile.spec.ts geschrieben (parst via --list; voller Lauf braucht laufenden Stack, nicht in PR-Pipeline)
  • Manuell: Profil mit Geometrie speichern → YAML-Export → Re-Import → auf mehrere Bilder mit Teil-Gruppen anwenden

🤖 Generated with Claude Code

Manuel Rödig and others added 22 commits June 5, 2026 18:01
…-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>
@phash
Copy link
Copy Markdown
Owner Author

phash commented Jun 6, 2026

✅ End-to-end verifiziert (laufender Stack)

Gegen einen komplett hochgefahrenen Stack getestet — Postgres + Keycloak + MinIO (Docker) + FastAPI-Backend (:8000) + Vite-Frontend (:5173), Migration auf 009_preset_geometry (head).

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):

  • Bild mit temperature=0.7 vorbelegt; Preset contrast=0.6 (tone) + temperature=-0.9 (color). apply groups=["tone"]contrast==0.6 angewendet und temperature bleibt 0.7 → nicht-destruktiv + selektiv. ✓
  • danach apply groups=["color"]temperature==-0.9, contrast bleibt 0.6 → Gruppen mergen unabhängig, frühere Edits überleben. ✓
  • Geometrie: Preset mit Crop, apply groups=["crop"] → Crop landet im Edit-State des Bildes. ✓
  • Unbekannte Gruppe "voodoo"422 (kein stilles Akzeptieren). ✓
  • Atomar: Antwort {applied:1, total:1}.

Caveat: YAML-Export/Import wurde nicht im Live-Browser geklickt — abgedeckt durch Unit- (Serialize/Parse-Roundtrip) + Component-Tests (File-Input → parseProfileYamlapi.createPreset, inkl. 409-Pfad); der zugrundeliegende createPreset-Pfad wurde live mitgeprüft.

Voller Gate ebenfalls grün: backend pytest 156, frontend tsc/lint/vitest (356)/build, plus Prod-Frontend-Docker-Build (docker build --target 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>
@phash phash merged commit 6ccd671 into main Jun 6, 2026
3 checks passed
@phash phash deleted the feat/preset-profile-export-batch branch June 6, 2026 20:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant