create PM v0.5
This commit is contained in:
parent
9b47296cea
commit
d2ba22c0cf
25 changed files with 2155 additions and 72 deletions
|
|
@ -219,6 +219,14 @@ aber:
|
|||
> Die hub-flux-Roadmap ist mit Phase 6 **vollständig** abgeschlossen.
|
||||
> Alle weiteren Themen sind eigene Initiativen.
|
||||
|
||||
**🟡 In Planung — Phase 7 (Press-Release-Form-Refactor):**
|
||||
Mockup `User Neue Mitteilung presseportale.html` wird auf den
|
||||
Customer-Create/Edit-Flow übertragen. Plan-Doc:
|
||||
`19-PHASE-7-PRESS-RELEASE-FORM.md`.
|
||||
Päckchen 7A (Migrations) → 7B (flux:editor + Sanitizer) →
|
||||
7C (Customer-Create-UI) → 7D (Customer-Edit-UI) →
|
||||
7E (Anhänge-Manager) → 7F (Scheduling/Embargo, optional).
|
||||
|
||||
1. **Manueller Dark-Mode Smoke-Test**: Im Browser User-Menü →
|
||||
Erscheinung → „Dunkel" und durch die Hauptseiten klicken
|
||||
(Dashboard, Listen, Detail, Security mit QR, Tokens). Erwartung:
|
||||
|
|
|
|||
240
dev/frontend/hub-flux/19-PHASE-7-PRESS-RELEASE-FORM.md
Normal file
240
dev/frontend/hub-flux/19-PHASE-7-PRESS-RELEASE-FORM.md
Normal file
|
|
@ -0,0 +1,240 @@
|
|||
# Phase 7 — Press-Release-Form-Refactor
|
||||
|
||||
> Großes Modul-Refactor: das zentrale „Neue Pressemitteilung"-Form
|
||||
> wird auf das Mockup `User Neue Mitteilung presseportale.html` gehoben.
|
||||
> Bekommt deshalb eine eigene Phase außerhalb der bisherigen
|
||||
> `hub-flux`-Roadmap (Phase 0–6 sind dort abgeschlossen).
|
||||
|
||||
**Status**: 🟡 in Planung · **Aufwand**: 2–3 Tage · **Risiko**: mittel
|
||||
(Datenmodell-Erweiterung, Editor-Format-Migration, Composer-Dependency)
|
||||
|
||||
---
|
||||
|
||||
## Ausgangslage
|
||||
|
||||
| Datei | Status |
|
||||
|---|---|
|
||||
| `resources/views/livewire/customer/press-releases/create.blade.php` | nur 1-Spalter, `<flux:textarea>`, fehlende Felder |
|
||||
| `resources/views/livewire/customer/press-releases/edit.blade.php` | gleicher Stand, plus Image-Manager |
|
||||
| `resources/views/livewire/admin/press-releases/create.blade.php` | Admin-Variante, dünner |
|
||||
| `resources/views/livewire/admin/press-releases/edit.blade.php` | Admin-Variante |
|
||||
|
||||
Das Mockup verlangt einen 2-Spalter mit eigener
|
||||
Settings-Sidebar (Status & Submit, Portal, Pressekontakt, Tags,
|
||||
Veröffentlichung, SEO). Linke Spalte: Firma-Selector, Titel,
|
||||
Untertitel, Editor, Medien, Anhänge, Boilerplate.
|
||||
|
||||
---
|
||||
|
||||
## Entscheidungen (vom User abgesegnet)
|
||||
|
||||
| Frage | Entscheidung |
|
||||
|---|---|
|
||||
| Scope | **full** — Anhänge-Tabelle + Schema-Vorbereitung für Scheduling/Embargo |
|
||||
| Portal-Auswahl | **read-only** — Portal kommt immer aus der Firma; UI zeigt nur Badge |
|
||||
| HTML-Sanitizer | **`mews/purifier`** — explizit approved, wird in 7B installiert |
|
||||
| Pressekontakt | **genau 1 pro PM**, Single-Select aus Firmen-Kontakten; Datenmodell bleibt n:m-Pivot, Validation erzwingt `count == 1` |
|
||||
| Admin-Forms | **mitziehen** in 7C+7D, gleiches Layout + Admin-only Felder |
|
||||
| Default-Kontakt | **erster Firmen-Kontakt alphabetisch** (keine Schema-Änderung) |
|
||||
|
||||
---
|
||||
|
||||
## Päckchen-Aufteilung
|
||||
|
||||
### 7A — Migrations + Models
|
||||
|
||||
**Scope:**
|
||||
- `press_releases.subtitle` (string 255, nullable)
|
||||
- `press_releases.boilerplate_override` (text, nullable) — pro PM überschreibbare Firmen-Boilerplate
|
||||
- `press_releases.scheduled_at` (timestamp, nullable) — Schema da, UI „bald"
|
||||
- `press_releases.embargo_at` (timestamp, nullable) — Schema da, UI „bald"
|
||||
- `companies.boilerplate` (text, nullable) — Firmenprofil-Boilerplate
|
||||
- Neue Tabelle `press_release_attachments` analog `press_release_images`
|
||||
(`disk`, `path`, `original_name`, `mime`, `size`, `sort_order`,
|
||||
`title`, `description`, `legacy_portal`, `legacy_id`, soft-deletes,
|
||||
timestamps).
|
||||
- Models: `PressRelease`, `Company`, neues `PressReleaseAttachment`
|
||||
+ Factory + Relationen + Casts.
|
||||
- Bestehende Tests müssen grün bleiben (alle Felder nullable,
|
||||
keine Verhaltensänderung).
|
||||
|
||||
**Akzeptanz**
|
||||
- [ ] Migration up/down sauber
|
||||
- [ ] `php artisan test --compact` grün (Baseline)
|
||||
- [ ] `php artisan db:show press_releases / companies / press_release_attachments` zeigt neue Spalten
|
||||
|
||||
### 7B — Editor-Integration
|
||||
|
||||
**Scope:**
|
||||
- `composer require mews/purifier` (explizite Approval einholen)
|
||||
- Service `App\Services\PressRelease\PressReleaseHtmlSanitizer`
|
||||
(Allowlist: `p,br,h2,h3,strong,em,u,ul,ol,li,blockquote,a[href|rel|target]`)
|
||||
- Create/Edit-Form: `<flux:textarea>` → `<flux:editor>` mit
|
||||
reduzierter Toolbar:
|
||||
```
|
||||
toolbar="heading | bold italic | bullet ordered blockquote | link | undo redo"
|
||||
```
|
||||
- Save-Pfad: `$this->text = $sanitizer->clean($this->text)`
|
||||
- Display-Pfad (`show.blade.php`, Portal-Detail-Seiten,
|
||||
`PressReleaseResource`):
|
||||
- Wenn `text` HTML-Tags enthält → `{!! $clean !!}` (sanitized)
|
||||
- Wenn nicht (legacy) → `{!! nl2br(e($text)) !!}`
|
||||
- Helper `PressRelease::renderedText(): HtmlString`
|
||||
- API: `PressReleaseResource` liefert weiterhin String (HTML),
|
||||
Doku-Update `_docs/api/v1.yml` und `dev/migration 2026/07-API-MIGRATION.md`.
|
||||
|
||||
**Akzeptanz**
|
||||
- [ ] `mews/purifier` in `composer.json`
|
||||
- [ ] Alle bestehenden Plain-Text-PMs werden korrekt angezeigt
|
||||
- [ ] Neue HTML-PMs werden korrekt sanitized gespeichert
|
||||
- [ ] Pest-Test: `<script>`-Tag wird bei Save gestrippt
|
||||
- [ ] Pest-Test: legacy plain text → `<p>`/`<br>` Rendering
|
||||
|
||||
### 7C — Customer-Create-Form (UI)
|
||||
|
||||
**Scope:**
|
||||
- Page-Header wie Mockup (Crumb-Trail + Topbar mit Autosave-Status,
|
||||
„Speichern", „Vorschau-bald")
|
||||
- 2-Spalter `grid-cols-[1fr,360px]`
|
||||
- Linke Spalte (Schreibfläche):
|
||||
1. **Firma-Selector** als kompakte Inline-Pille (`flux:dropdown`)
|
||||
mit „Neue Firma anlegen"-Link
|
||||
2. **Titel** (`<flux:input>` mit Title-Font, Counter-Pille
|
||||
`meter good/warn` 40–90 Zeichen empfohlen)
|
||||
3. **Untertitel** (optional, Counter-Pille 0/200)
|
||||
4. **Fließtext** (`<flux:editor>` mit reduzierter Toolbar,
|
||||
Counter-Pille 600–3500 Z., KI-Lektorat-bald-Hint)
|
||||
5. **Medien** (bestehende `press-release-images-manager`-Komponente
|
||||
im neuen Tile-Style anpassen — Titelbild-Flag,
|
||||
Caption/Alt-Text Pflicht-Hint)
|
||||
6. **Anhänge** (neue Livewire-Komponente in 7E)
|
||||
7. **Boilerplate** (Read-only-Box mit Toggle „Für diese PM
|
||||
überschreiben" → öffnet `<flux:textarea>`)
|
||||
- Rechte Spalte (Settings-Sidebar, sticky):
|
||||
1. **Status & Absenden** (Pre-Submit-Checkliste aus
|
||||
Pflichtfeldern, primärer Submit „Zur Prüfung senden")
|
||||
2. **Portal** (read-only-Badge aus Firma)
|
||||
3. **Pressekontakt** (Single-Select aus Firmen-Kontakten,
|
||||
Pflichtfeld, Warn-Hint falls Telefon fehlt)
|
||||
4. **Themen-Tags** (Chip-Eingabe, parst `keywords` als
|
||||
Komma-getrennt, max 5 Tags, Vorschläge aus Firma)
|
||||
5. **Veröffentlichung** (RadioGroup: „Sofort nach Freigabe"
|
||||
aktiv, „Geplanter Termin" als `bald`-Badge)
|
||||
6. **SEO** (Collapsed, „automatisch aus Titel" als `bald`-Hint)
|
||||
7. **Phase-2-Footer-Card** wie im Mockup
|
||||
- Validation:
|
||||
- `title`: required, 5–255
|
||||
- `subtitle`: nullable, max 255
|
||||
- `text`: required, min 50 (HTML-stripped)
|
||||
- `company_id`: required, muss zur User-Firma gehören
|
||||
- `category_id`: required
|
||||
- `contact_id`: required, muss zur Firma gehören
|
||||
- `keywords`: nullable, max 5 Tags
|
||||
- `boilerplate_override`: nullable
|
||||
- Pre-Submit-Check (Read-only-Anzeige, blockiert nicht):
|
||||
- Titel vorhanden + Länge ok → ok
|
||||
- Fließtext min 600 Z. → ok / sonst warn
|
||||
- Firma gewählt → ok
|
||||
- Mind. 1 Bild + Titelbild gesetzt → ok / sonst warn
|
||||
- Mind. 1 Tag → ok / sonst warn
|
||||
- Pressekontakt mit Telefon → ok / sonst warn
|
||||
|
||||
**Was NICHT ins 7C kommt:**
|
||||
- Anhänge-Manager UI (kommt in 7E)
|
||||
- Scheduling/Embargo-Logik (kommt in 7F)
|
||||
- Autosave („alle paar Sek.") — erstmal nur Status-Anzeige
|
||||
(„Manuell gespeichert vor X") via Livewire-Event nach `save()`;
|
||||
echtes Autosave optional in 7F
|
||||
|
||||
**Akzeptanz**
|
||||
- [ ] Bestehender Test `CustomerCompanyContextTest > customer press releases create …` grün
|
||||
- [ ] Neuer Test: Create mit allen Pflichtfeldern → PR persistiert
|
||||
- [ ] Neuer Test: Create ohne Pressekontakt → Validation-Fehler
|
||||
- [ ] Pint + Build grün
|
||||
|
||||
### 7D — Customer-Edit-Form
|
||||
|
||||
**Scope:**
|
||||
- Gleiches Layout wie 7C
|
||||
- Submit-Sektion zeigt aktuellen Status (Entwurf/Abgelehnt) +
|
||||
ggf. letzten Reject-Grund
|
||||
- Image-Manager und Attachments-Manager weiterhin verfügbar
|
||||
- Form ist nur editierbar, wenn `status in [draft, rejected]`
|
||||
(bestehende Policy bleibt)
|
||||
|
||||
**Akzeptanz**
|
||||
- [ ] Edit-Test (Update aller neuen Felder) grün
|
||||
- [ ] Reject-Reason-Anzeige bleibt sichtbar
|
||||
- [ ] Bestehende Tests bleiben grün
|
||||
|
||||
### 7E — Anhänge-Manager
|
||||
|
||||
**Scope:**
|
||||
- Neue Volt-Komponente
|
||||
`resources/views/livewire/components/press-release-attachments-manager.blade.php`
|
||||
analog `press-release-images-manager.blade.php`
|
||||
- Methoden: `upload`, `remove`, `moveUp`, `moveDown`
|
||||
- Storage via `Storage::disk('public')` unter
|
||||
`press-release-attachments/{press_release_id}/`
|
||||
- Validation: PDF/DOCX/XLSX/PPTX, max. 25 MB pro Datei
|
||||
- Tile-Layout wie im Mockup (PDF-Badge + Filename + Größe + Aktionen)
|
||||
- Berechtigung wie beim Image-Manager (Policy `update` auf PR
|
||||
+ Status `draft|rejected` für Customer)
|
||||
|
||||
**Akzeptanz**
|
||||
- [ ] Upload-Test
|
||||
- [ ] Remove-Test
|
||||
- [ ] Reorder-Test
|
||||
- [ ] Datei-Type-Validation grün
|
||||
|
||||
### 7F — Scheduling + Embargo (Schema vorhanden, UI aktivieren)
|
||||
|
||||
**Scope:**
|
||||
- UI-Elemente aus 7C (Veröffentlichung-RadioGroup,
|
||||
Embargo-Checkbox + Date-Picker) aktivieren
|
||||
- `bald`-Badges entfernen
|
||||
- Service-Logik in `PressReleaseService`:
|
||||
- bei `submitForReview` mit `scheduled_at` → Status bleibt
|
||||
`review`, beim `publish` durch Admin/Job wird `published_at`
|
||||
auf `scheduled_at` gesetzt
|
||||
- bei `embargo_at` → öffentliche Anzeige erst ab `embargo_at`
|
||||
- Background-Job (`PublishScheduledPressReleases`) für die
|
||||
Veröffentlichung um `scheduled_at`
|
||||
- Test: Geplante PM wird nicht vor Termin öffentlich
|
||||
- Test: Embargo-Filter im Portal-Index
|
||||
|
||||
**Hinweis:** 7F ist optional und kann nach 7C/D/E in eine eigene
|
||||
kleine Sub-Phase ausgelagert werden, weil es einen Background-Job
|
||||
einführt und der Test-Umfang separat sauber bleibt.
|
||||
|
||||
---
|
||||
|
||||
## Risiken & Mitigation
|
||||
|
||||
| Risiko | Mitigation |
|
||||
|---|---|
|
||||
| Editor-HTML bricht alte Anzeigen | Helper `renderedText()` mit Fallback auf `nl2br(e(…))` |
|
||||
| Composer-Dependency `mews/purifier` ungeprüft | Vor Install explizite User-Approval; alternative `decide_later` möglich |
|
||||
| Pressekontakt-Pivot mit > 1 Eintrag in DB | Migrations-Skript prüft & loggt; Validation in Save erzwingt 1 |
|
||||
| Test-Suite-Regression | Jedes Päckchen einzeln + `php artisan test --compact` zwischen den Päckchen |
|
||||
|
||||
## Out of Scope (bewusst nicht in Phase 7)
|
||||
|
||||
- KI-Titel-Optimierung (Phase 8)
|
||||
- KI-Lektorat (Phase 8)
|
||||
- KI-Bildgenerierung (Phase 8)
|
||||
- Mehrfach-Portal-Publishing (Phase 2 laut Mockup-Disclaimer)
|
||||
- Versionshistorie (Phase 2 laut Mockup-Disclaimer)
|
||||
- Portal-Vorschau (Phase 2)
|
||||
- Echtes Autosave alle paar Sekunden (Polish, in 7F optional)
|
||||
|
||||
## Reihenfolge
|
||||
|
||||
1. **7A** Migrations + Models
|
||||
2. **7B** Editor + Sanitizer
|
||||
3. **7C** Customer-Create-Form
|
||||
4. **7D** Customer-Edit-Form
|
||||
5. **7E** Anhänge-Manager
|
||||
6. **7F** Scheduling/Embargo (optional, eigene Sub-Phase)
|
||||
|
||||
Nach jedem Päckchen: User-Approval + Test-Run + Build + Pint + PROGRESS-Update.
|
||||
Loading…
Add table
Add a link
Reference in a new issue