- Mediathek: Video-Vorschaubilder statt Icons (FFmpeg-Thumbnails + Backfill-Command), Kategorie "Sonstiges" - B2in Media-Picker zeigt alle Medientypen, Typ wird automatisch erkannt; Thumbnail-Preview vor allen Medien-URL-Feldern - B2in Marke/Footer: Footer ein/aus, Logo+Claim frei positionierbar (Ecken) mit Constraints, separate Anzeige-Schalter - Angebote-Modul dynamisch: kein Slide-Typ mehr, einheitliches Detail-Layout mit ein-/ausblendbaren Bloecken, Logo/Brand pro Slide, Streichpreis-Option - Player: leere Module stoppen Endlosschleife, dynamische Layout-Anpassung bei verstecktem Footer/Header - Fix: Script-Ladereihenfolge (Livewire vor Flux), entfernte stale public/flux/flux.js, Modal-Crash beim Aktualisieren behoben Co-authored-by: Cursor <cursoragent@cursor.com>
375 lines
23 KiB
Markdown
375 lines
23 KiB
Markdown
# Cabinet Displays – Implementierungs-Status
|
||
|
||
> Konzept: siehe `00-entwicklungskonzept.md`. Diese Datei wird je Phase fortgeschrieben.
|
||
|
||
## Übersicht
|
||
|
||
| Phase | Inhalt | Status |
|
||
|---|---|---|
|
||
| **0** | Konzept-Freigabe | ✅ 11.05.2026 |
|
||
| **1** | Datenmodell + Daten-Migration | ✅ 11.05.2026 |
|
||
| **2** | API & Player (config + preview + module preview) | ✅ 12.05.2026 |
|
||
| **3** | Admin-UI: Displays-Liste mit Live/Entwurf | ✅ 12.05.2026 |
|
||
| **4** | Admin-UI: Entwurf-Editor (Iframe-Vorschau) | ✅ 12.05.2026 |
|
||
| **5** | Modul-Editor: 3-stufige Vorschau | ✅ 12.05.2026 |
|
||
| **6** | Umbenennung Versionen → Module + Onboarding | ✅ 12.05.2026 |
|
||
| **7** | Aufräumen + alte Pivot-Tabelle entfernen | ✅ 13.05.2026 |
|
||
| **8** | Review: Fehler / Optimierungen / Erweiterungen | 🟡 29.05.2026 (Befundaufnahme) |
|
||
|
||
Legende: ✅ fertig · 🟡 in Arbeit · ⏳ offen · ⛔ blockiert
|
||
|
||
---
|
||
|
||
## Defaults aus §10 (Konzept-Freigabe vom 11.05.2026)
|
||
|
||
Der User hat das Konzept freigegeben. Da keine abweichende Wahl getroffen wurde, gelten die im Konzept empfohlenen Defaults:
|
||
|
||
1. **Test-Display:** genau 1 Datensatz per Seeder angelegt, weitere können bei Bedarf erstellt werden.
|
||
2. **Entwurf verwerfen:** löscht die Draft-Playlist. Beim erneuten Anlegen wird die Reihenfolge aus Live kopiert.
|
||
3. **Module bleiben *shared*:** Modul-Änderungen wirken sofort auf alle Displays, die das Modul live einsetzen. Modul-eigene Versionierung ist *out of scope*.
|
||
4. **Polling-Mechanismus** der Player (alle 60 s) reicht; kein Push-Refresh.
|
||
|
||
---
|
||
|
||
## Live-Roll-out Hinweise
|
||
|
||
Auf dem Live-Server reicht für jede Phase:
|
||
|
||
```bash
|
||
git pull
|
||
composer install --no-dev --optimize-autoloader # falls neue Composer-Deps
|
||
php artisan migrate --force # bringt neue Migrations ein
|
||
php artisan config:cache # Caches frisch
|
||
php artisan view:clear
|
||
```
|
||
|
||
Alle strukturellen Änderungen liegen **ausschließlich** in `database/migrations/` als datierte Dateien vor – auf der Live-DB reicht `php artisan migrate --force`. Datenverlust gibt es nicht: bestehende Pivot-Daten aus `display_display_version` werden in die neue Struktur überführt.
|
||
|
||
---
|
||
|
||
## Phase 1 – Datenmodell
|
||
|
||
**Ziel:** neue Tabellen `display_playlists` + `display_playlist_items`, erweiterte `displays`-Spalten (`is_test`, `preview_token`), vollständige verlustfreie Migration der heutigen Pivot-Daten.
|
||
|
||
**Dateien:**
|
||
- `database/migrations/2026_05_11_*_create_display_playlists_table.php`
|
||
- `database/migrations/2026_05_11_*_create_display_playlist_items_table.php`
|
||
- `database/migrations/2026_05_11_*_add_test_flag_and_preview_token_to_displays_table.php`
|
||
- `database/migrations/2026_05_11_*_migrate_pivot_to_display_playlists.php`
|
||
- `app/Models/DisplayPlaylist.php`
|
||
- `app/Models/DisplayPlaylistItem.php`
|
||
- `app/Models/Display.php` (neue Relations, alte `versions()` bleibt kompatibel)
|
||
- `database/factories/DisplayPlaylistFactory.php`
|
||
- `database/factories/DisplayPlaylistItemFactory.php`
|
||
- `tests/Feature/DisplayPlaylistMigrationTest.php`
|
||
|
||
**Wichtig:** Die alte Tabelle `display_display_version` und die Relation `Display::versions()` bleiben in dieser Phase **erhalten** (Removal erst in Phase 7), damit keine bestehenden Funktionen brechen.
|
||
|
||
### Stand 11.05.2026 – ✅ abgeschlossen
|
||
|
||
#### Gelieferte Migrationen (Live-Reihenfolge)
|
||
|
||
| Reihenfolge | Datei | Zweck |
|
||
|---|---|---|
|
||
| 1 | `2026_05_11_113300_add_test_flag_and_preview_token_to_displays_table.php` | `displays.is_test` + `displays.preview_token` (unique) |
|
||
| 2 | `2026_05_11_113310_create_display_playlists_table.php` | Neue Tabelle für Live/Entwurfs-Bespielung pro Display |
|
||
| 3 | `2026_05_11_113320_create_display_playlist_items_table.php` | Geordnete Module pro Bespielung |
|
||
| 4 | `2026_05_11_113330_migrate_pivot_to_display_playlists.php` | Übernimmt bestehende Pivot-Daten als Published-Playlists (idempotent) |
|
||
|
||
Die Daten-Migration ist **idempotent** – wenn pro Display bereits eine Published-Playlist existiert, wird sie übersprungen. Die alte Pivot-Tabelle `display_display_version` bleibt erhalten.
|
||
|
||
#### Neue Modelle & Relations
|
||
|
||
- `App\Models\DisplayPlaylist` mit Scopes `published()`/`draft()`, Relation `modules()` (geordnet)
|
||
- `App\Models\DisplayPlaylistItem`
|
||
- `App\Models\Display` erweitert um `playlists()`, `livePlaylist()`, `draftPlaylist()`, `liveModules()`, `ensurePreviewToken()`
|
||
- `Display::versions()` ist als `@deprecated` markiert, bleibt aber funktional
|
||
|
||
#### Tests
|
||
|
||
```text
|
||
tests/Feature/DisplayPlaylistMigrationTest.php – 11 passed
|
||
tests/Feature/DisplayListTest.php – ok
|
||
tests/Feature/DisplayVersionTest.php – ok
|
||
tests/Feature/DisplayVersionApiTest.php – ok
|
||
tests/Feature/DisplayMediaTest.php – ok
|
||
```
|
||
|
||
Insgesamt 67 grüne Tests rund um Displays (11 neu + 56 bestand). Keine Linter-Warnungen, Pint clean.
|
||
|
||
#### Roll-out auf Live
|
||
|
||
```bash
|
||
git pull
|
||
php artisan migrate --force
|
||
```
|
||
|
||
Reihenfolge stimmt durch die Timestamps automatisch. Daten-Migration ist idempotent, kann beliebig oft laufen.
|
||
|
||
---
|
||
|
||
## Phase 2 – API & Player
|
||
|
||
**Ziel:** bestehende Player-Konfiguration liest künftig aus der Published-Playlist. Zusätzlich gibt es öffentliche Vorschau-Endpunkte für Display-Entwürfe per Token und einzelne Module. Das JSON-Schema bleibt rückwärtskompatibel (`playlist[]`, `updated_at`).
|
||
|
||
### Stand 12.05.2026 – ✅ abgeschlossen
|
||
|
||
Geplante/aktuelle Dateien:
|
||
- `app/Services/DisplayPlaylistConfigBuilder.php`
|
||
- `app/Http/Controllers/Api/DisplayVersionApiController.php`
|
||
- `app/Http/Controllers/Api/DisplayPreviewController.php`
|
||
- `app/Http/Controllers/Api/ModulePreviewController.php`
|
||
- `routes/domains.php`
|
||
- `public/_cabinet/display/index.html`
|
||
- `tests/Feature/DisplayVersionApiTest.php`
|
||
|
||
Umsetzung:
|
||
- Live-Config: `GET /api/display/{display}/config` liest `livePlaylist`
|
||
- Live-Check: `GET /api/display/{display}/check` bezieht sich auf die Published-Playlist
|
||
- Draft-Preview: `GET /api/display/preview/{token}` liefert die Draft-Playlist
|
||
- Modul-Preview: `GET /api/display/module/{module}/preview` liefert ein Einzelmodul im Player-Schema
|
||
- Player-Preview-Seiten: `/preview/{token}` und `/preview/module/{module}`
|
||
|
||
#### Tests
|
||
|
||
```text
|
||
tests/Feature/DisplayVersionApiTest.php – 13 passed
|
||
tests/Feature/DisplayPlaylistMigrationTest.php – ok
|
||
```
|
||
|
||
Insgesamt 24 grüne Tests für Phase 2 und die Playlist-Grundlage. Pint clean.
|
||
|
||
#### Hinweis
|
||
|
||
In der lokalen Umgebung musste der alte Route-Cache einmal mit `php artisan route:clear` geleert werden, damit die neuen Preview-Routen sichtbar wurden. Für Live bleibt beim Roll-out `php artisan config:cache` bzw. ein frischer Route-/Config-Cache relevant.
|
||
|
||
---
|
||
|
||
## Phase 3 – Admin-UI: Displays-Liste mit Live/Entwurf
|
||
|
||
**Ziel:** Die Display-Liste zeigt pro physischem Display den Live-Stand und optionalen Entwurf nebeneinander. Entwürfe können aus Live angelegt, verworfen und veröffentlicht werden. Das Test-Display ist sichtbar hervorgehoben.
|
||
|
||
### Stand 12.05.2026 – ✅ abgeschlossen
|
||
|
||
Dateien:
|
||
- `app/Livewire/Admin/Cms/DisplayList.php`
|
||
- `resources/views/livewire/admin/cms/display-list.blade.php`
|
||
- `tests/Feature/DisplayListTest.php`
|
||
|
||
Umsetzung:
|
||
- Display-Karten zeigen `Live` und `Entwurf` als zwei getrennte Spalten
|
||
- Der globale Bearbeiten-Button im Display-Kopf wurde entfernt; Live und Entwurf haben jeweils eigene Bearbeiten-Buttons
|
||
- Die Live-Card zeigt die Player-URL direkt als kopierbares Feld; der API-Link ist weniger prominent unten rechts platziert
|
||
- Live-Spalte nutzt `livePlaylist.modules`
|
||
- Entwurf-Spalte nutzt `draftPlaylist.modules`
|
||
- Live-Bearbeitung speichert nur die Published-Playlist
|
||
- Entwurfs-Bearbeitung speichert nur die Draft-Playlist und erzeugt bei Bedarf den Preview-Token
|
||
- Die Modul-Auswahl im Bearbeiten-Dialog zeigt nur noch Module, die in der aktuell bearbeiteten Bespielung noch nicht enthalten sind
|
||
- Der Plus-Button fügt auch dann das erste verfügbare Modul hinzu, wenn der Select-Wert wegen des Platzhalters noch nicht explizit gesetzt wurde
|
||
- Aktion `Entwurf anlegen` kopiert den aktuellen Live-Stand und erzeugt bei Bedarf den Preview-Token
|
||
- Aktion `Veröffentlichen` ersetzt die Published-Playlist durch den Draft und synchronisiert die alte Pivot-Tabelle weiterhin kompatibel
|
||
- Aktion `Verwerfen` löscht die Draft-Playlist
|
||
- Test-Displays (`is_test`) werden in der Liste hervorgehoben
|
||
- Der bestehende Bearbeiten-Dialog pflegt die Live-Bespielung weiter und synchronisiert bis Phase 7 zusätzlich `display_display_version`
|
||
|
||
#### Tests
|
||
|
||
```text
|
||
tests/Feature/DisplayListTest.php – 14 passed
|
||
```
|
||
|
||
Die neuen Tests decken Draft anlegen, verwerfen, veröffentlichen, getrennte Live-/Entwurfs-Bearbeitung, gefilterte Modul-Auswahl sowie die Darstellung von Live-/Entwurf-Modulen ab.
|
||
|
||
---
|
||
|
||
## Phase 4 – Admin-UI: Entwurf-Editor mit Iframe-Vorschau
|
||
|
||
**Ziel:** Beim Bearbeiten eines Entwurfs ist die Player-Vorschau direkt sichtbar. Moduländerungen im Entwurf werden sofort in die Draft-Playlist geschrieben und laden die Vorschau neu.
|
||
|
||
### Stand 12.05.2026 – ✅ abgeschlossen
|
||
|
||
Dateien:
|
||
- `app/Livewire/Admin/Cms/DisplayList.php`
|
||
- `resources/views/livewire/admin/cms/display-list.blade.php`
|
||
- `tests/Feature/DisplayListTest.php`
|
||
|
||
Umsetzung:
|
||
- Der Entwurfs-Editor zeigt rechts eine 9:16-Iframe-Vorschau
|
||
- Die Iframe-Vorschau sitzt dauerhaft unterhalb der Aktualisieren-Aktion, damit sie im Desktop-Modal nicht mit dem Formular überlappt
|
||
- Die Vorschau lädt `/preview/{token}` mit Cache-Bust-Parameter
|
||
- Hinzufügen, Entfernen und Sortieren von Modulen persistiert bei Draft-Bearbeitung sofort in `display_playlist_items`
|
||
- Nach jeder Moduländerung wird die Iframe-Vorschau per `wire:key` neu aufgebaut
|
||
- Vollbild-Vorschau ist aus dem Editor heraus verlinkt
|
||
|
||
#### Tests
|
||
|
||
```text
|
||
tests/Feature/DisplayListTest.php – 21 passed
|
||
```
|
||
|
||
Die Tests decken das Rendern der Vorschau-URL und das sofortige Persistieren von Draft-Änderungen für Preview-Reloads ab.
|
||
|
||
---
|
||
|
||
## Phase 5 – Modul-Editor: 3-stufige Vorschau
|
||
|
||
**Ziel:** Module können beim Bearbeiten visuell geprüft werden: kleine Vorschau je Item, eingebettete Player-Vorschau und Vollbild-Vorschau.
|
||
|
||
### Stand 12.05.2026 – ✅ abgeschlossen
|
||
|
||
Dateien:
|
||
- `app/Livewire/Admin/Cms/DisplayVersionEditor.php`
|
||
- `resources/views/livewire/admin/cms/display-version-editor.blade.php`
|
||
- `resources/views/livewire/admin/cms/partials/version-editor-video.blade.php`
|
||
- `resources/views/livewire/admin/cms/partials/version-editor-b2in.blade.php`
|
||
- `resources/views/livewire/admin/cms/partials/version-editor-offers.blade.php`
|
||
- `tests/Feature/DisplayVersionTest.php`
|
||
|
||
Umsetzung:
|
||
- Modul-Editor zeigt eine 9:16-Iframe-Vorschau über `/preview/module/{module}`
|
||
- Vollbild-Vorschau ist direkt aus dem Editor verlinkt
|
||
- Das Item-Bearbeiten-Modal ist breiter und zeigt unterhalb der Aktualisieren-Aktion ebenfalls eine 9:16-Iframe-Vorschau
|
||
- `Aktualisieren` im Item-Bearbeiten-Modal schließt das Modal nicht mehr, sondern speichert den Inhalt und lädt die Iframe-Vorschau neu
|
||
- Die Modal-Aktionen stehen unterhalb der Iframe-Vorschau und bieten `Aktualisieren`, `Abbrechen` und `Schließen`
|
||
- Die Vorschau im Item-Bearbeiten-Modal nutzt eine eigene Item-Preview und zeigt nur den aktuell bearbeiteten Slide statt das komplette Modul
|
||
- Der Display-Player rendert seinen Viewport strikt als 9:16-Fläche und skaliert Slide-, Footer- und QR-Elemente proportional zur Player-Fläche
|
||
- Harte Player-Elemente wie B2in-Headerlogo/Claim/Footer/QR, Offers-Logo/Brandtext/QR-Labels und Video-Footer-QR-Label sind jetzt als Modul-Einstellungen im CMS pflegbar
|
||
- Die Modul-Meta-Einstellungen sind als sichtbarer Block unterhalb der Media-/Slide-Liste editierbar; Angebote vererben Footer-Claim und Web/QR-URL automatisch an alle Slides
|
||
- Logo-Alt-Text-Felder wurden aus den Modul-Meta-Einstellungen entfernt; Player nutzen weiterhin feste Fallback-Alt-Texte
|
||
- Video-Display unterstützt Mediathek-Upload-URLs wie `/storage/...` ohne Legacy-`assets/`-Prefix
|
||
- Die Display-Mediathek und der schnelle Media-Picker akzeptieren SVG-Dateien als Bild-Uploads
|
||
- Änderungen an Name, Einstellungen, Items, Reihenfolge und Aktiv-Status laden die Modul-Vorschau neu
|
||
- Video/Footer/Media/Slide-Listen zeigen Inline-Mini-Previews je Item; Slide-Previews sind größer dargestellt
|
||
- Einzelmodul-Vorschau nutzt weiterhin den Player aus Phase 2
|
||
|
||
---
|
||
|
||
## Phase 6 – Umbenennung Versionen → Module + Onboarding
|
||
|
||
**Ziel:** Die Admin-UI verwendet den fachlich korrekten Begriff „Module“. Alte URLs wurden während der Übergangsphase per 301 weitergeleitet und in Phase 7 entfernt.
|
||
|
||
### Stand 12.05.2026 – ✅ abgeschlossen
|
||
|
||
Dateien:
|
||
- `routes/admin.php`
|
||
- `app/Livewire/Admin/Cms/DisplayVersionList.php`
|
||
- `resources/views/livewire/admin/cms/display-version-list.blade.php`
|
||
- `resources/views/livewire/admin/cms/display-version-editor.blade.php`
|
||
- `resources/views/livewire/admin/cms/display-dashboard.blade.php`
|
||
- `resources/views/components/layouts/app/sidebar.blade.php`
|
||
- `tests/Feature/DisplayVersionTest.php`
|
||
|
||
Umsetzung:
|
||
- Neue Routen: `admin/cms/display-modules` und `admin/cms/display-modules/{displayVersion}/edit`
|
||
- Neue Routennamen: `admin.cms.display-modules` und `admin.cms.display-module-edit`
|
||
- Alte `display-versions`-Routen waren während der Übergangsphase als 301-Redirects aktiv und wurden in Phase 7 entfernt
|
||
- Sidebar, Dashboard, Listen- und Editor-Texte verwenden „Module“
|
||
- Technische Modell-/Klassennamen bleiben bei `DisplayVersion`, da sie fachlich weiterhin die wiederverwendbaren Module abbilden
|
||
|
||
#### Tests
|
||
|
||
```text
|
||
tests/Feature/DisplayVersionTest.php – ok
|
||
tests/Feature/DisplayVersionApiTest.php – ok
|
||
tests/Feature/DisplayListTest.php – ok
|
||
tests/Feature/DisplayPlaylistMigrationTest.php – ok
|
||
```
|
||
|
||
Insgesamt 64 grüne Tests für Phasen 5/6 und die angrenzenden Display-Flows. Pint clean.
|
||
|
||
---
|
||
|
||
## Phase 7 – Technisches Aufräumen & Optimierung
|
||
|
||
**Ziel:** Nach Stabilisierung des neuen Playlist-Flows wird die alte Pivot-Kompatibilität entfernt und der Modul-Editor weiter vereinheitlicht.
|
||
|
||
### Stand 13.05.2026 – ✅ umgesetzt
|
||
|
||
Dateien:
|
||
- `app/Models/Display.php`
|
||
- `app/Models/DisplayVersion.php`
|
||
- `app/Livewire/Admin/Cms/DisplayList.php`
|
||
- `app/Console/Commands/MigrateLegacyDisplays.php`
|
||
- `app/Support/DisplayModuleSettings.php`
|
||
- `app/Services/DisplayPlaylistConfigBuilder.php`
|
||
- `app/Livewire/Admin/Cms/DisplayVersionEditor.php`
|
||
- `app/Livewire/Admin/Cms/DisplayVersionList.php`
|
||
- `routes/admin.php`
|
||
- `database/migrations/2026_05_13_103600_drop_display_display_version_table.php`
|
||
- `resources/views/livewire/admin/cms/display-list.blade.php`
|
||
- `resources/views/livewire/admin/cms/display-version-editor.blade.php`
|
||
- `resources/views/livewire/admin/cms/partials/version-editor-video.blade.php`
|
||
|
||
Umsetzung:
|
||
- Alte Pivot-Tabelle `display_display_version` wird per Migration entfernt
|
||
- Legacy-Relationen `Display::versions()` und `DisplayVersion::displays()` wurden entfernt
|
||
- Display-Bearbeitung, Draft-Veröffentlichung und Legacy-Migrations-Command schreiben ausschließlich in `display_playlists` und `display_playlist_items`
|
||
- Alte `display-versions`-Redirect-Routen wurden entfernt; die Admin-UI nutzt nur noch `display-modules`
|
||
- Modul-Settings-Defaults liegen zentral in `App\Support\DisplayModuleSettings` und werden von Editor, Listen-Erstellung und API-Config-Builder gemeinsam genutzt
|
||
- Admin-Iframes laden per `loading="lazy"` verzögert, um die parallelen Player-Vorschauen leichter zu halten
|
||
- Video-Display-Items zeigen im Editor sichtbar an, ob die Quelle aus der Mediathek oder aus einem Legacy-Dateinamen kommt
|
||
|
||
---
|
||
|
||
## Phase 8 – Review 29.05.2026 (Befundaufnahme)
|
||
|
||
Geprüft wurden die drei Navigationspunkte:
|
||
- `admin/cms/display-media` → Volt `admin.cms.display-media-library`
|
||
- `admin/cms/display-modules` → `App\Livewire\Admin\Cms\DisplayVersionList` (+ Editor `DisplayVersionEditor`)
|
||
- `admin/cms/displays` → `App\Livewire\Admin\Cms\DisplayList`
|
||
|
||
**Vorgehen:** Code-Review der Komponenten/Views/Services/Player + Laravel-Logs + DB-Stand. Eine Browser-Sichtprüfung war in dieser Session nicht möglich (Browser-MCP nicht verfügbar). **Alle Befunde (#1–#11) wurden inzwischen umgesetzt** (Details je Punkt unten).
|
||
|
||
**Aktueller Datenstand (DB):** 5 Displays (davon **0** Test-Displays), 6 Module, 7 Playlists (5 Live + 2 Entwürfe), 13 Medien.
|
||
|
||
**Tests:** `DisplayListTest`, `DisplayMediaTest`, `DisplayVersionTest`, `DisplayVersionApiTest`, `DisplayPlaylistMigrationTest` → **95 passed** (276 Assertions). Keine CMS-Fehler in `storage/logs` (vorhandene Log-Fehler betreffen unrelated `immobilien-azizi`-Routen).
|
||
|
||
### 🔴 Fehler (sollten behoben werden)
|
||
|
||
1. **Mediathek-Suche hebelt alle Filter aus.** ✅ **behoben 29.05.2026**
|
||
In `display-media-library.blade.php` (`$media`-Computed) und in `DisplayMediaPicker::resolveMediaItems()` wurde die Suche als `->where('filename','like',…)->orWhere('title','like',…)` ohne Gruppierung an die vorherigen `when()`-Filter gehängt. Durch SQL-Präzedenz (`AND` bindet stärker als `OR`) wurde die Query zu `… AND filename LIKE … OR title LIKE …`. Sobald gesucht wurde, wurden **Typ-, Quelle-, Sammlungs- und (beim Picker) der `active()`-Filter ignoriert**, sobald ein Treffer über `title` zustande kam.
|
||
*Behebung:* Neuer gekapselter Scope `DisplayMedia::scopeSearch()` (Closure um `filename`/`title`), den Library und Picker gemeinsam nutzen. Tests: `keeps preceding filters when combined with the search scope`, `search scope respects the active filter on the media picker` in `DisplayMediaTest.php`.
|
||
|
||
2. **Inhalt-Bearbeiten reaktiviert deaktivierte Items.** ✅ **behoben 29.05.2026**
|
||
In `DisplayVersionEditor` übergab `loadItemContent()` nur das `content`-Array an `loadVideoContent()/loadFooterContent()/loadMediaContent()/loadSlideContent()`. Alle vier setzten `…IsActive = true` fest – das tatsächliche `is_active` des Items wurde nie geladen. Wer ein zuvor per Auge-Icon deaktiviertes Item öffnete und „Aktualisieren" klickte, hat es über `getActiveFlag()` **ungewollt wieder aktiviert**.
|
||
*Behebung:* `loadItemContent()` reicht `(bool) $item->is_active` an die Loader durch, die es in die jeweilige `…IsActive`-Property schreiben. Test: `editing an inactive item keeps it inactive` in `DisplayVersionTest.php`.
|
||
|
||
### 🟡 Optimierungen / Aufräumen
|
||
|
||
3. **Toter Code im Video-Editor.** ✅ **behoben 29.05.2026** `DisplayVersionEditor::loadAvailableVideos()`, Property `$availableVideos`, der `mount()`-Aufruf und der ungenutzte `Illuminate\Support\Facades\File`-Import wurden entfernt (im aktiven Editor-Blade ungenutzt; das einzige Blade mit `availableVideos` gehört zur Legacy-`CabinetDisplay`). Spart den Dateisystem-Scan von `public/_cabinet/assets` bei jedem Editor-Aufruf.
|
||
|
||
4. **Modul-Löschen ohne Schutz.** ✅ **behoben 29.05.2026** `DisplayVersionList::deleteVersion()` ermittelt jetzt den `displays_count` (distinct Displays über Playlists) und **blockiert** das Löschen, solange das Modul in irgendeiner Bespielung (Live oder Entwurf) genutzt wird; es erscheint ein roter Flash-Hinweis mit Anzahl. Module ohne Nutzung lassen sich weiterhin löschen. Test: `cannot delete a display version that is used by a playlist` in `DisplayVersionTest.php`.
|
||
|
||
5. **Doppelte Such-Logik** zwischen Library und Picker (siehe #1) → ein gemeinsamer Query-Scope `DisplayMedia::scopeSearch(string $term)` verhindert künftige Divergenz. ✅ **erledigt 29.05.2026** (im Zuge von #1).
|
||
|
||
6. **Preview-Token bleibt nach Veröffentlichen bestehen.** ✅ **behoben 29.05.2026**
|
||
`DisplayList::publishDraft()`/`discardDraft()` ließen `displays.preview_token` gesetzt, obwohl `/preview/{token}` danach 404 lieferte (kein Draft mehr); ein Rotations-Button fehlte ganz.
|
||
*Behebung:* Neue Model-Methoden `Display::rotatePreviewToken()` und `Display::clearPreviewToken()`. `publishDraft()` und `discardDraft()` setzen den Token jetzt zurück (alter Link wird ungültig). Im Entwurf gibt es einen „Link erneuern"-Button (`rotatePreviewToken()` mit `wire:confirm`), der bei offenem Entwurf zugleich die Iframe-Vorschau aktualisiert. Tests: `publishing a draft clears the preview token`, `can discard a draft playlist` (erweitert) und `can rotate the preview token of a draft` in `DisplayListTest.php`.
|
||
|
||
### 🟠 Konfiguration / Dev-Umgebung
|
||
|
||
7. **Live-Vorschau zeigt im lokalen Dev auf die Produktion.** ✅ **behoben 29.05.2026**
|
||
`config/display.php` `player_url` defaultete auf `https://cabinet.b2in.eu/display`, und `DISPLAY_PLAYER_URL` war in `.env` nicht gesetzt. In `display-list.blade.php` nutzten „Vorschau", „Live-URL zum Kopieren" und „Display-Übersicht öffnen" diese Produktions-URL, während die Entwurfs-„Test-URL" über `url('/preview/…')` lokal lief. Lokal sah man Live also den Produktionsstand, Entwurf aber lokale Daten – inkonsistent und irreführend.
|
||
*Behebung:* Player-Seite (`public/_cabinet/display/`) **und** die Display-API liegen auf der Portal-Domain, daher ist der Player lokal unter `https://portal.b2in.test/_cabinet/display` erreichbar (der Player ermittelt `BASE_URL` aus `window.location.origin` und ruft die API auf derselben Domain auf).
|
||
- `.env`: `DISPLAY_PLAYER_URL=https://portal.b2in.test/_cabinet/display` gesetzt (Config-Cache geleert).
|
||
- `.env.example`: dokumentiert (Live-Wert als Kommentar).
|
||
- `phpunit.xml`: `DISPLAY_PLAYER_URL=https://cabinet.b2in.eu/display` gepinnt, damit die bestehenden URL-Tests (`DisplayListTest`, `DisplayVersionApiTest`) deterministisch gegen den Produktionswert prüfen, unabhängig von der lokalen `.env`.
|
||
- Der Produktions-Fallback in `config/display.php` (und damit das Live-Verhalten) bleibt unverändert.
|
||
|
||
### 🟢 Erweiterungen / Verbesserungen (UX)
|
||
|
||
8. **Test-Display existiert nicht.** ✅ **behoben 29.05.2026** Neuer idempotenter `Database\Seeders\TestDisplaySeeder` legt genau **ein** Test-Display an (überspringt, falls schon vorhanden) und ist im `DatabaseSeeder` registriert. In der Dev-DB wurde das Test-Display angelegt. Tests: `seeds exactly one test display`, `is idempotent and does not create a second test display` in `TestDisplaySeederTest.php`.
|
||
|
||
9. **Externe Bilder ohne Thumbnail.** ✅ **behoben 29.05.2026** Grid, Listenansicht und Detail-Sidebar (`display-media-library.blade.php`) rendern externe Bilder jetzt direkt via `<img src="{{ external_url }}">` (gemeinsame `$thumbSrc`-Logik: Upload-Thumbnail → sonst `external_url`). Nicht-Bild-Externe behalten das Link-Icon. Test: `renders external image media with an inline thumbnail` in `DisplayMediaTest.php`.
|
||
|
||
10. **Mediathek-Pagination ohne `resetPage`.** ✅ **behoben 29.05.2026** Die Volt-Komponente nutzt jetzt `WithPagination` und Update-Hooks (`updatedSearch/updatedFilterType/updatedFilterSource/updatedFilterCollection`), die bei jeder Filter-/Suchänderung `resetPage()` aufrufen. Test: `resets pagination to page one when a filter changes` in `DisplayMediaTest.php`.
|
||
|
||
11. **Modul-Hinzufügen nur einzeln.** ✅ **behoben 29.05.2026** Der Bespielungs-Dialog (`display-list.blade.php`) nutzt jetzt einen durchsuchbaren Flux-Listbox-Multi-Select (`versionsToAdd`) plus „Hinzufügen"-Button (`addSelectedVersions()`), der alle ausgewählten Module auf einmal übernimmt (Duplikate werden übersprungen). Die programmatische `addVersion()`-Methode bleibt für Einzel-Adds/Tests erhalten. Test: `can add multiple modules to a playlist at once` in `DisplayListTest.php`.
|
||
|
||
### Empfohlene Reihenfolge
|
||
|
||
1. #1 + #2 (echte Fehler, klein, mit Tests) → 2. #7 (Dev-Konfiguration, blockiert lokales Testen) → 3. #3/#4/#5/#6 (Aufräumen/Robustheit) → 4. #8–#11 (UX-Erweiterungen). Jeder Punkt wird gemäß Projekt-Regeln mit Test abgesichert und mit Pint formatiert.
|
||
|
||
**Stand 29.05.2026:** Alle Befunde (#1–#11) sind umgesetzt, getestet und mit Pint formatiert.
|
||
|
||
|