b2in/dev/displays-11-05-2026/00-entwicklungskonzept.md

20 KiB
Raw Permalink Blame History

Cabinet Displays Entwicklungskonzept

Datum: 11.05.2026 Autor: Konzept-Phase Status: Freigegeben Umsetzung gestartet am 11.05.2026


1. Ausgangslage

1.1 Was es heute gibt

Im Admin-Portal unter portal.b2in.test/admin/cms/ existiert der Bereich Store Displays mit folgenden Unterseiten:

Pfad Bedeutung
cms/display-dashboard Übersicht / Einstieg
cms/display-media Mediathek (eigene Display-Mediathek, getrennt von Flux CMS)
cms/display-modules Inhalts-Module
cms/display-modules/{id}/edit Editor für ein Modul
cms/displays Physische Displays + Playlist-Zuweisung
cms/cabinet-tablet Info-Tablet (Öffnungszeiten/Status)

1.2 Aktuelles Datenmodell

displays  (5 Datensätze live)
└── 1:n display_playlists (Live/Entwurf)
        └── 1:n display_playlist_items (sort_order = Playlist-Reihenfolge)
                └── display_versions (technisch), fachlich Module
                        ├── type: video-display | b2in | offers
                        ├── settings: JSON
                        └── 1:n display_version_items
                                ├── item_type: video | footer | media | slide
                                └── content: JSON

1.3 Echte Live-Daten (Stand heute)

5 Displays:

# Name Standort Playlist (Reihenfolge)
1 Display 1 Eingang Schaufenster rechts Schaufenster Video → B2In Immobilien Dark
2 Display 2 Mitte Schaufenster Mitte Angebote Schauraum
3 Display 3 Rechts Schaufenster rechts B2In Immobilien Light → Angebote Schauraum → Schaufenster Video
4 Display 4 Innen Schauraum B2In Immobilien Dark
5 Kundenstopper Draußen Sideboard Goya → Schaufenster Video

5 Versionen:

# Name Typ Items Verwendet in
1 Schaufenster Video video-display 6 3 Displays
2 B2In Immobilien Dark b2in 3 2 Displays
3 B2In Immobilien Light b2in 3 1 Display
4 Angebote Schauraum offers 4 2 Displays
5 Sideboard Goya offers 1 1 Display

→ Dieser Bestand muss migriert, nicht verworfen werden.

1.4 Beobachtete Schwächen

  1. Begriff „Versionen" missverständlich sind faktisch wiederverwendbare Inhalts-Bausteine, nicht „Versionen" im Sinne von „Revisionen".
  2. Kein Live/Entwurfs-Trennung pro Display jede Änderung an einem Baustein wirkt sofort auf alle Displays, die ihn nutzen. Es gibt kein „in Arbeit, noch nicht veröffentlichen".
  3. Kein dediziertes Test-Display will man eine Konfiguration vorab prüfen, muss man sie produktiv ausspielen.
  4. Keine visuelle Vorschau im Editor beim Bearbeiten eines Slides sieht man nicht, wie er auf dem Display aussehen wird.
  5. Hilfetexte nur im Dashboard Listen- und Editor-Seiten haben kaum Erklärungen.
  6. Versions-Settings JSON-Wirrwarr Theme, Footer, Transition etc. werden je Typ unterschiedlich gepflegt, ohne sichtbares Schema.

2. Zielbild

„Pro Display gibt es einen klar veröffentlichten Stand (Live) und optional einen Entwurf, der gefahrlos vorbereitet und getestet werden kann. Veröffentlichen ist ein bewusster Schritt. Module sind wiederverwendbare Bausteine. Beim Bearbeiten sieht man sofort, wie es auf dem Display aussieht."

2.1 Neue Begriffswelt

Alt Neu Erklärung
Display-Version Modul Wiederverwendbarer Inhalts-Baustein eines Typs (Video, B2in, Offers).
Display Display (unverändert) Physischer Bildschirm im Showroom.
Display ↔ Version Pivot Bespielung (Playlist) Geordnete Liste von Modulen pro Display. Existiert pro Display in zwei Ausprägungen: Live und Entwurf.
Mediathek Display-Mediathek (unverändert) Bilder/Videos für Displays.
Info-Tablet Info-Tablet (unverändert) Eingangs-Tablet mit Öffnungszeiten.

Routen wurden entsprechend umbenannt: display-versionsdisplay-modules. Die Übergangs-Redirects wurden in Phase 7 entfernt.

2.2 Neues mentales Modell

┌──────────────────────────────────────────────────────────────┐
│  MODULE (Bausteine)                                          │
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐           │
│  │ Modul A     │  │ Modul B     │  │ Modul C     │ ...       │
│  │ Type:Video  │  │ Type:B2in   │  │ Type:Offers │           │
│  └─────────────┘  └─────────────┘  └─────────────┘           │
└────────┬─────────────────┬─────────────────┬─────────────────┘
         │                 │                 │
         ▼                 ▼                 ▼
┌──────────────────────────────────────────────────────────────┐
│  DISPLAYS                                                    │
│  ┌────────────────────┐    ┌────────────────────┐            │
│  │ Display 1          │    │ Display 2          │            │
│  │ ┌────────────────┐ │    │ ┌────────────────┐ │            │
│  │ │ ▶ Live         │ │    │ │ ▶ Live         │ │            │
│  │ │   Modul A→B    │ │    │ │   Modul C      │ │            │
│  │ ├────────────────┤ │    │ ├────────────────┤ │            │
│  │ │ ✎ Entwurf      │ │    │ │ (kein Entwurf) │ │            │
│  │ │   Modul A→B→C  │ │    │ └────────────────┘ │            │
│  │ └────────────────┘ │    │                    │            │
│  └────────────────────┘    └────────────────────┘            │
│                                                              │
│  ┌────────────────────┐                                      │
│  │ Test-Display       │  ← neu, technisch ein Display        │
│  │ Beliebig kombi-    │    mit Sonder-Flag is_test=true      │
│  │ nierbar zum Testen │                                      │
│  └────────────────────┘                                      │
└──────────────────────────────────────────────────────────────┘

2.3 Festlegungen aus Klärung

  1. Begriff: „Modul" (statt Version/Baustein).
  2. Versionierung: Pro Display-Bespielung (Live + Entwurf), nicht pro Modul.
  3. Vorlagen-Konzept: Ein eigenes Test-Display, auf dem beliebige Module/Bespielungen ausprobiert werden können.
  4. Vorschau: alle drei Varianten Inline-Thumbnail je Item, Iframe-Live-Preview neben Editor, Vollbild-Vorschau auf Knopfdruck.

3. Datenmodell Soll-Zustand

3.1 Neue Tabellen

display_playlists

Pro Display max. zwei Datensätze: eine published und eine draft.

Schema::create('display_playlists', function (Blueprint $table) {
    $table->id();
    $table->foreignId('display_id')->constrained()->cascadeOnDelete();
    $table->enum('status', ['published', 'draft']);
    $table->timestamp('published_at')->nullable();
    $table->foreignId('published_by')->nullable()->constrained('users')->nullOnDelete();
    $table->text('notes')->nullable();
    $table->timestamps();

    $table->unique(['display_id', 'status']);
});

display_playlist_items

Ersetzt funktional display_display_version.

Schema::create('display_playlist_items', function (Blueprint $table) {
    $table->id();
    $table->foreignId('display_playlist_id')->constrained()->cascadeOnDelete();
    $table->foreignId('display_version_id')->constrained()->cascadeOnDelete();
    $table->unsignedInteger('sort_order')->default(0);
    $table->timestamps();

    $table->index(['display_playlist_id', 'sort_order']);
});

3.2 Anpassungen bestehender Tabellen

displays

  • is_test BOOLEAN (default false) kennzeichnet das Test-Display.
  • preview_token STRING (nullable, unique) wird beim Erstellen einer Draft-Bespielung generiert; ermöglicht eine cabinet.b2in.eu/preview/{token} Adresse für Tablet-Tests ohne Login.

display_versions → begrifflich „Module"

Tabelle und Modell bleiben technisch erhalten (keine Rename-Migration → keine Risiken bei Live-Daten). Nur die UI-Bezeichnung wechselt zu „Modul".

3.3 Daten-Migration

Eine einmalige Migration überführt alle aktuellen display_display_version-Einträge in das neue Schema:

für jedes Display D:
    erstelle display_playlists (display_id=D.id, status='published', published_at=now())
    für jeden Eintrag aus display_display_version (display_id=D.id), sortiert nach sort_order:
        erstelle display_playlist_items (...)
display_display_version-Tabelle wurde in Phase 7 dropped.

Ergebnis nach Migration: Alle 5 Displays haben eine Live-Bespielung, kein Entwurf. Konsumenten-API liefert exakt das gleiche wie heute.


4. API Anpassungen

4.1 Endpunkte

Endpunkt Bedeutung Verhalten
GET /api/display/{display}/config Live-Konfiguration Liest aus display_playlists mit Status published. Unverändert für die im Showroom installierten Player.
GET /api/display/{display}/check Modifikationszeit für Polling Bezieht sich auf die Published-Playlist.
GET /api/display/preview/{token} (neu) Vorschau-Konfiguration Liefert die Draft-Playlist eines Displays. Token aus displays.preview_token. Kein Login nötig, aber Token rotierbar.

4.2 Backward Compatibility

Das Antwortschema bleibt identisch (playlist[], updated_at). Player im Showroom muss nicht angefasst werden.


5. UI / UX Neu

5.1 Navigation

Store Displays
├── Übersicht (Dashboard, klarer Workflow-Erklärung)
├── Mediathek
├── Module          ← war „Versionen"
├── Displays        ← Live + Entwurf je Display
└── Info-Tablet

5.2 Display-Liste (Hauptansicht)

Pro Display eine Karte mit zwei Spalten:

┌─────────────────────────────────────────────────────────────┐
│ ● Display 1  Eingang            Schaufenster rechts        │
│ ───────────────────────────────────────────────────────────  │
│ ▶ LIVE                              ✎ ENTWURF               │
│  [Modul Schaufenster Video]         (kein Entwurf)          │
│  [Modul B2In Immo Dark]                                     │
│  Aktualisiert: 02.05.2026          [Entwurf anlegen]        │
│  [Vorschau] [API]                                           │
│                                                             │
└─────────────────────────────────────────────────────────────┘

Wenn Entwurf existiert:

▶ LIVE                              ✎ ENTWURF
 [Modul A]                           [Modul A]
 [Modul B]                           [Modul B]
                                     [Modul C]  ← neu
 Aktualisiert: 02.05.2026            Test-URL: …xY12pq
 [Vorschau] [API]                    [Bearbeiten] [Veröffentlichen] [Verwerfen]

5.3 Entwurf-Editor

Nur ein Modal/Sub-Page, kein weiteres komplexes UI:

  • Module hinzufügen aus Bibliothek (Multi-Select)
  • Sortierung per ↑/↓
  • Sofortige Iframe-Vorschau rechts (lädt /preview/{token} aus aktuellem Entwurfsstand, auto-reload bei Änderung)
  • Veröffentlichen-Button mit Confirm
  • Verwerfen → löscht Draft

5.4 Test-Display

Eigene Top-Level-Kachel „Test-Display" im Display-Dashboard. Technisch ein normaler Display-Datensatz mit is_test=true. Eigene URL /_cabinet/display/?id=TEST_ID für lokales Vorab-Anschauen.

In der Liste ist es deutlich abgesetzt (anderes Icon, gelbe Border), damit es nicht versehentlich als Produktion-Display verwendet wird.

5.5 Modul-Editor drei Vorschau-Stufen

Stufe A: Inline-Mini-Preview je Item

In den Listen version-editor-{video|b2in|offers}.blade.php: pro Item-Zeile ein Thumbnail/Mini-Layout neben Headline und Subline. Konkret:

  • Video-Item: Video-Thumbnail (erstes Frame oder Standbild) + Filename-Badge
  • Footer-Item: kleines Footer-Layout mit Headline+Subline+QR-Stub
  • Media-Item: Bild-Thumbnail + Headline-Overlay-Skizze
  • Slide-Item: Mini-Skizze des Slide-Layouts (Hero/Details/Impulse erkennbar)

Stufe B: Iframe-Live-Preview neben Editor

Beim Bearbeiten eines Moduls splittet sich die Ansicht:

┌────────────────────────┬──────────────────────────┐
│ Items / Form           │ 9:16 Iframe              │
│ (links, scrollbar)     │ Live-Preview aus         │
│                        │ /preview/module/{id}     │
└────────────────────────┴──────────────────────────┘

Die Iframe-URL lädt das Modul isoliert (ohne Display-Bespielung) dafür legen wir an: GET /preview/module/{module} (gerendert via vorhandene Display-Player-Templates, aber im Single-Module-Modus).

Stufe C: Vollbild-Vorschau auf Knopfdruck

Button „Vollbild-Vorschau" → öffnet /preview/module/{module} in neuem Tab in voller 9:16-Größe.

5.6 Dashboard

Bleibt strukturell wie heute, aber mit:

  • aktualisierten Bezeichnungen
  • zusätzlicher Zeile pro Display: Live/Entwurf-Stand
  • prominentem „Test-Display"-Eintrag
  • ausgebautem Workflow-Block (1. Modul anlegen → 2. Display-Entwurf bauen → 3. Testen → 4. Veröffentlichen)

6. Authentifizierung / Berechtigungen

  • Alle Admin-Routen weiterhin auth + partner.setup.
  • Vorschau-Routen /preview/{token} und /preview/module/{id} sind öffentlich, aber per Token bzw. nur auf nicht-aktiven Daten zugreifbar. Token rotierbar per Button im Display-Detail.

7. Tests (Pflicht laut Projekt-Regeln)

Test Datei
Bestehende Versions-API funktioniert weiter tests/Feature/DisplayVersionApiTest.php (anpassen)
Migration display_display_versiondisplay_playlists ist verlustfrei tests/Feature/DisplayPlaylistMigrationTest.php (neu)
Neuer Workflow: Entwurf anlegen → bearbeiten → veröffentlichen tests/Feature/DisplayPublishWorkflowTest.php (neu)
Vorschau via Token ohne Login erreichbar tests/Feature/DisplayPreviewTokenTest.php (neu)
Test-Display verhält sich korrekt tests/Feature/DisplayTestFlagTest.php (neu)
Modul-Preview-Endpoint funktioniert tests/Feature/ModulePreviewTest.php (neu)

Bestehende Tests aus DisplayListTest, DisplayVersionTest, DisplayVersionApiTest werden angepasst nicht ersetzt.


8. Phasen-Roadmap

Jede Phase liefert ein in sich getestetes, deploybares Inkrement.

Phase 1 Datenmodell (Tag 1)

  • Migration display_playlists + display_playlist_items
  • Migration: displays.is_test, displays.preview_token
  • Daten-Migration aus display_display_version
  • Modelle DisplayPlaylist, DisplayPlaylistItem
  • Relations & Factories
  • Test: Daten-Migration verlustfrei

Phase 2 API & Player (Tag 1)

  • DisplayConfigController liest aus Published-Playlist
  • Neuer DisplayPreviewController für Token-Preview
  • Neuer ModulePreviewController für Modul-Einzelvorschau
  • Tests aktualisiert + neu

Phase 3 Admin-UI: Displays-Liste (Tag 2)

  • Liste mit Live + Entwurf je Display
  • Aktionen: Entwurf anlegen / verwerfen / veröffentlichen
  • Test-Display als eigene, hervorgehobene Karte
  • Vorschau-Buttons (Live + Entwurf)

Phase 4 Admin-UI: Entwurf-Editor (Tag 2)

  • Modal/Page zum Bearbeiten der Entwurf-Playlist (Module hinzufügen, sortieren, entfernen)
  • Iframe-Vorschau rechts
  • Auto-Reload der Iframe bei Änderung

Phase 5 Modul-Editor Vorschau-Ausbau (Tag 3)

  • Stufe A: Inline-Mini-Preview je Item-Typ (Video/Footer/Media/Slide)
  • Stufe B: Iframe-Live-Preview rechts neben Modul-Editor
  • Stufe C: Vollbild-Vorschau-Button
  • Player-Templates: Single-Module-Modus

Phase 6 Umbenennung & Onboarding (Tag 3)

  • Routen: display-versionsdisplay-modules
  • Komponenten / Views umbenennen
  • Dashboard-Texte / Hilfe-Bausteine aktualisieren
  • Tooltips an Schlüsselstellen

Phase 7 Aufräumen (Tag 4)

  • display_display_version-Tabelle dropped
  • Alte Routen entfernt
  • Entwicklerdoku in dev/displays-11-05-2026 aktualisiert
  • Vollständiger Test-Run

9. Risiken & Migrationsschutz

Risiko Maßnahme
Live-Displays brechen API-Schema unverändert; Daten-Migration zuerst, Live-Tests vorher
Konflikte bei parallelen Edits Optimistic Lock per updated_at auf Playlist (vorerst nicht zwingend)
Token-Preview öffentlich Token mind. 24 Zeichen, rotierbar, nur Draft sichtbar
Verwirrung „Modul" vs „Version" 301 von alten Routen, Hinweis im Dashboard zur Umbenennung

10. Offene Fragen / Klärungsbedarf vor Phase 1

Bevor wir Phase 1 starten, sind diese Punkte zu bestätigen:

  1. „Test-Display" soll es fest „1" geben (Singleton) oder beliebig viele? (Empfehlung: genau 1 angelegt durch Seeder, weitere optional erstellbar.)
  2. Verwerfen vs. „auf Live zurücksetzen" beim Verwerfen eines Entwurfs: einfach löschen, oder soll der Entwurf auf den Stand der Live-Bespielung zurückgesetzt werden? (Empfehlung: löschen, beim Neuanlegen wird der Stand aus Live geklont.)
  3. Modul gleichzeitig in Live und Entwurf eines Displays darf vorkommen (z.B. Reihenfolge ändern). Module bleiben dabei shared zwischen Displays. Wirken Modul-Änderungen sofort auch auf Live-Displays? Ja (technisch das gleiche Datum). Falls das nicht gewünscht ist, müssten Module ebenfalls versioniert werden das ist Out-Of-Scope für diesen Konzeptstand.
  4. Player-Cache nach Veröffentlichen soll der Polling-Mechanismus (60 s) ausreichen, oder brauchen wir einen Push-Refresh? (Empfehlung: 60 s reicht.)

11. Was passiert mit dem alten Pfad cms/cabinet?

Die ursprüngliche CabinetDisplay-Komponente (mit DisplayVideo + DisplayFooterContent) ist Legacy und gehört zur alten 1-Display-Welt unter /_cabinet/index.html. Sie wird im Konzeptzeitraum nicht angefasst, aber im Anschluss empfohlen zu entfernen, sobald alle Live-Displays auf /_cabinet/display/?id=… umgeschaltet sind.


12. Nächster Schritt

→ Das Konzept wurde am 11.05.2026 freigegeben und die Umsetzung wurde gestartet. → Der laufende Fortschritt wird in 01-status.md gepflegt.