Add live show docs and smoke tests
Some checks failed
linter / quality (push) Has been cancelled
tests / ci (push) Has been cancelled
tests / ui (push) Has been cancelled

This commit is contained in:
Codex Agent
2026-01-05 19:42:58 +01:00
parent 53eb560aa5
commit 3f3061a899
10 changed files with 230 additions and 3 deletions

View File

@@ -25,10 +25,10 @@
{"id":"fotospiel-app-55n","title":"Tenant admin onboarding: add Paddle error UX + test coverage","status":"open","priority":2,"issue_type":"task","created_at":"2026-01-01T16:08:40.463283816+01:00","created_by":"soeren","updated_at":"2026-01-01T16:08:40.463283816+01:00"}
{"id":"fotospiel-app-574","title":"Paddle catalog sync: extend PaddleClient tests/mocks for catalog endpoints","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T15:59:03.486301225+01:00","created_by":"soeren","updated_at":"2026-01-02T21:11:39.626820206+01:00","closed_at":"2026-01-02T21:11:39.626820206+01:00","close_reason":"Deprioritized"}
{"id":"fotospiel-app-576","title":"Tenant admin onboarding: legacy asset audit + component inventory","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T16:07:59.996563146+01:00","created_by":"soeren","updated_at":"2026-01-01T16:08:05.599274641+01:00","closed_at":"2026-01-01T16:08:05.599274641+01:00","close_reason":"Completed in codebase (verified)"}
{"id":"fotospiel-app-579","title":"Live Show: tests (backend + UI smoke)","status":"open","priority":2,"issue_type":"task","created_at":"2026-01-05T11:11:57.246607374+01:00","created_by":"soeren","updated_at":"2026-01-05T11:11:57.246607374+01:00","dependencies":[{"issue_id":"fotospiel-app-579","depends_on_id":"fotospiel-app-539","type":"blocks","created_at":"2026-01-05T11:13:27.729131522+01:00","created_by":"soeren"},{"issue_id":"fotospiel-app-579","depends_on_id":"fotospiel-app-xg5","type":"blocks","created_at":"2026-01-05T11:13:37.425191011+01:00","created_by":"soeren"},{"issue_id":"fotospiel-app-579","depends_on_id":"fotospiel-app-qne","type":"blocks","created_at":"2026-01-05T11:13:46.257175231+01:00","created_by":"soeren"}]}
{"id":"fotospiel-app-579","title":"Live Show: tests (backend + UI smoke)","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-05T11:11:57.246607374+01:00","created_by":"soeren","updated_at":"2026-01-05T19:37:35.590123482+01:00","closed_at":"2026-01-05T19:37:35.590123482+01:00","close_reason":"Closed","dependencies":[{"issue_id":"fotospiel-app-579","depends_on_id":"fotospiel-app-539","type":"blocks","created_at":"2026-01-05T11:13:27.729131522+01:00","created_by":"soeren"},{"issue_id":"fotospiel-app-579","depends_on_id":"fotospiel-app-xg5","type":"blocks","created_at":"2026-01-05T11:13:37.425191011+01:00","created_by":"soeren"},{"issue_id":"fotospiel-app-579","depends_on_id":"fotospiel-app-qne","type":"blocks","created_at":"2026-01-05T11:13:46.257175231+01:00","created_by":"soeren"}]}
{"id":"fotospiel-app-5dl","title":"Paddle catalog sync: PaddleCatalogService scaffold","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T16:00:24.916655836+01:00","created_by":"soeren","updated_at":"2026-01-01T16:00:30.566084195+01:00","closed_at":"2026-01-01T16:00:30.566084195+01:00","close_reason":"Completed in codebase (verified)"}
{"id":"fotospiel-app-5hk","title":"Fix staging coupon seed 500 for E2E","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-03T15:12:53.643644221+01:00","created_by":"soeren","updated_at":"2026-01-04T16:21:46.441797374+01:00","closed_at":"2026-01-04T16:21:46.441797374+01:00","close_reason":"Resolved elsewhere; staging coupon seed 500 no longer reproducible after recent backend changes."}
{"id":"fotospiel-app-5ie","title":"Help docs: Live Show how-to + recommended hardware (DE/EN)","status":"open","priority":2,"issue_type":"task","created_at":"2026-01-05T11:12:05.973844187+01:00","created_by":"soeren","updated_at":"2026-01-05T11:30:44.911207413+01:00","dependencies":[{"issue_id":"fotospiel-app-5ie","depends_on_id":"fotospiel-app-vro","type":"blocks","created_at":"2026-01-05T11:13:54.925412888+01:00","created_by":"soeren"},{"issue_id":"fotospiel-app-5ie","depends_on_id":"fotospiel-app-539","type":"blocks","created_at":"2026-01-05T11:14:03.257649076+01:00","created_by":"soeren"}]}
{"id":"fotospiel-app-5ie","title":"Help docs: Live Show how-to + recommended hardware (DE/EN)","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-05T11:12:05.973844187+01:00","created_by":"soeren","updated_at":"2026-01-05T19:42:44.39939087+01:00","closed_at":"2026-01-05T19:42:44.39939087+01:00","close_reason":"Closed","dependencies":[{"issue_id":"fotospiel-app-5ie","depends_on_id":"fotospiel-app-vro","type":"blocks","created_at":"2026-01-05T11:13:54.925412888+01:00","created_by":"soeren"},{"issue_id":"fotospiel-app-5ie","depends_on_id":"fotospiel-app-539","type":"blocks","created_at":"2026-01-05T11:14:03.257649076+01:00","created_by":"soeren"}]}
{"id":"fotospiel-app-5iy","title":"Security review: confirm env/header defaults","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T16:03:20.808188183+01:00","created_by":"soeren","updated_at":"2026-01-01T16:03:26.388002115+01:00","closed_at":"2026-01-01T16:03:26.388002115+01:00","close_reason":"Completed in codebase (verified)"}
{"id":"fotospiel-app-5s3","title":"Localized SEO: canonical/hreflang tags + localized navigation","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T16:02:03.909947355+01:00","created_by":"soeren","updated_at":"2026-01-01T16:02:09.550647107+01:00","closed_at":"2026-01-01T16:02:09.550647107+01:00","close_reason":"Completed in codebase (verified)"}
{"id":"fotospiel-app-5zl","title":"Ensure checkout step 3 requires login for Paddle checkout","description":"Problem: Paddle checkout on step 3 fails when user is not logged in. Step 3 must enforce authentication before initializing Paddle checkout.\\n\\nSuggestions:\\n- Protect step 3 route/controller with auth middleware and redirect to login with intended return URL.\\n- Gate step 3 UI/CTA on auth state; show inline login prompt and disable Paddle until authenticated.\\n- Require auth in backend endpoint that creates Paddle transaction/session; return 401 and send user to login.\\n- Optionally preflight at end of step 2 to prompt login before advancing.","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-04T12:31:43.215017311+01:00","created_by":"soeren","updated_at":"2026-01-04T12:42:45.088723058+01:00","closed_at":"2026-01-04T12:42:45.088723058+01:00","close_reason":"Closed"}

View File

@@ -1 +1 @@
fotospiel-app-539.5
fotospiel-app-579

View File

@@ -19,6 +19,7 @@ Hier findest du alle Informationen, die du als Event-Admin für einen reibungslo
| Konto & Team | Wie lade ich Mitarbeitende ein und setze Branding auf? | `tenant-dashboard-overview` |
| Event-Vorbereitung | Welche Checkliste erledige ich vor Einlass? | `event-prep-checklist` |
| Live-Betrieb | Wie überwache ich Uploads, moderiere Inhalte und sende Hinweise? | `live-ops-control` |
| Live Show | Wie richte ich den Live-Show-Player ein und spiele ihn ab? | `live-show-setup` |
| Abschluss & Compliance | Wie funktionieren Export, Archiv und Datenschutz? | `post-event-wrapup` |
| Troubleshooting | Was tun bei Upload-Problemen, Geräteverlust oder Billing-Fragen? | `admin-issue-resolution` |

View File

@@ -13,6 +13,7 @@ owner: ops@fotospiel.app
related:
- slug: event-prep-checklist
- slug: admin-issue-resolution
- slug: live-show-setup
---
## Dashboard-Widgets

View File

@@ -0,0 +1,82 @@
---
title: "Live Show einrichten & abspielen"
locale: de
slug: live-show-setup
audience: admin
summary: "Schritt-für-Schritt-Anleitung für Live Show, Moderation, Effekte und Hardware-Setup am Beamer."
version_introduced: 2025.4
requires_app_version: "^3.2.0"
status: draft
translation_state: aligned
last_reviewed_at: 2025-02-22
owner: ops@fotospiel.app
related:
- slug: live-ops-control
- slug: admin-issue-resolution
---
> Diese Anleitung ist für Event-Admins, die eine Live Show auf einem Bildschirm oder Beamer abspielen möchten.
## Wann ist dieser Artikel relevant?
- Du willst neue Uploads live auf einer großen Leinwand zeigen.
- Du brauchst einen stabilen Ablauf mit Moderation, Effekten und klarer Hardware-Empfehlung.
## Live Show vorbereiten (Admin-App)
1. Öffne das Event und gehe zu **Live Show Einstellungen**.
2. Wähle den **Moderationsmodus**:
- **Aus**: jedes Foto erscheint sofort.
- **Manuell**: Fotos landen in der Live-Show-Warteschlange.
- **Trusted only**: nur freigegebene Quellen werden automatisch übernommen.
3. Lege **Tempo** (Auto oder feste Sekunden), **Layout** (Single/Split/Grid) und **Effekt-Preset** fest.
4. Speichere die Einstellungen.
## Live Show Link öffnen
- Öffne den Live-Show-Link im Format `/show/<token>` im Browser des Abspielgeräts.
- Teile den Link nur mit Personen, die die Show steuern dürfen.
> Tipp: Der Live-Show-Player läuft ohne Login und ist read-only.
## Moderation im Live-Betrieb
- Öffne die **Live Show Queue** im Admin und bestätige neue Fotos.
- Nutze **„Approve + Live“**, um Galerie und Live Show in einem Schritt freizugeben.
- Reagiere schnell bei sensiblen Inhalten (Policy: ≤10 Minuten).
## Effekte & Layouts (empfohlene Defaults)
- **Film Cut** + **Blur last**: ruhiger, professioneller Look.
- **Shutter Flash**: mehr Dynamik für Party- und Gala-Events.
- **Grid Burst**: ideal bei vielen Uploads und großen Leinwänden.
## Empfohlenes Setup für Beamer
**Minimal (funktioniert):**
- Laptop mit Chrome/Edge, 8GB RAM
- HDMI-Kabel (510m)
- Beamer ≥3000 ANSI Lumen, 1080p
**Empfohlen (stabil):**
- Mini-PC oder Laptop mit dedizierter Grafikeinheit
- Ethernet-Verbindung (USBC → Ethernet Adapter)
- Beamer ≥4500 ANSI Lumen, 1080p/4K, 16:9
- HDMI 2.0 + aktiver HDMI-Verlängerer (ab 10m)
**Optional:**
- HDMI-Splitter (zusätzliche Displays)
- Präsentationsklicker für schnellen Fokuswechsel
## Beamer & Bildschirm richtig einstellen
1. Auflösung auf **16:9** setzen, Skalierung 100%.
2. Vollbild aktivieren (Taste **F** im Player oder Browser-F11).
3. Energiesparmodus und Bildschirmsperre deaktivieren.
4. Benachrichtigungen im Betriebssystem ausschalten.
## Netzwerk & Stabilität
- Nutze 5GHz-WLAN oder (besser) Ethernet.
- Vermeide offene Gäste-WLANs für den Player.
- Stelle sicher, dass das Abspielgerät **dauerhaft online** bleibt.
## Häufige Probleme
- **Fotos erscheinen nicht:** Moderationsmodus prüfen, Queue leeren, Live-Show-Link neu laden.
- **Ruckler:** Effekt-Intensität reduzieren, Layout auf Single wechseln, WLAN prüfen.
- **Schwarzer Bildschirm:** HDMI-Eingang am Beamer prüfen, Browser-Fullscreen deaktivieren/neu aktivieren.
### Weitere Hilfe
Siehe `admin-issue-resolution` für Troubleshooting oder kontaktiere den Support.

View File

@@ -19,6 +19,7 @@ This portal collects everything event admins need to configure customer accounts
| Account Setup | How do I invite staff and configure branding? | `tenant-dashboard-overview` |
| Event Preparation | What checklists should I complete before doors open? | `event-prep-checklist` |
| Live Operations | How do I monitor uploads, moderate content, and trigger announcements? | `live-ops-control` |
| Live Show | How do I set up and run the Live Show player? | `live-show-setup` |
| Wrap-up & Compliance | How are exports, archives, and privacy handled? | `post-event-wrapup` |
| Troubleshooting | How to handle upload issues, device loss, billing, etc. | `admin-issue-resolution` |

View File

@@ -13,6 +13,7 @@ owner: ops@fotospiel.app
related:
- slug: event-prep-checklist
- slug: admin-issue-resolution
- slug: live-show-setup
---
## Dashboard widgets

View File

@@ -0,0 +1,82 @@
---
title: "Set up & run Live Show"
locale: en
slug: live-show-setup
audience: admin
summary: "Step-by-step guide for Live Show, moderation, effects, and recommended projector hardware."
version_introduced: 2025.4
requires_app_version: "^3.2.0"
status: draft
translation_state: aligned
last_reviewed_at: 2025-02-22
owner: ops@fotospiel.app
related:
- slug: live-ops-control
- slug: admin-issue-resolution
---
> This guide is for event admins who want to run Live Show on a big screen or projector.
## When is this relevant?
- You want new uploads to appear live on a large display.
- You need a stable flow with moderation, effects, and hardware guidance.
## Prepare Live Show (Admin app)
1. Open the event and go to **Live Show settings**.
2. Choose a **moderation mode**:
- **Off**: every photo appears immediately.
- **Manual**: photos are held in the Live Show queue.
- **Trusted only**: only approved sources are auto-added.
3. Set the **pace** (auto or fixed seconds), **layout** (single/split/grid), and **effect preset**.
4. Save the settings.
## Open the Live Show link
- Open the Live Show URL in the format `/show/<token>` on the playback device.
- Share the link only with staff who should control the show.
> Tip: The Live Show player is read-only and works without login.
## Moderation during the event
- Open the **Live Show queue** in the admin app and approve new photos.
- Use **"Approve + Live"** to publish to gallery and Live Show in one step.
- Act quickly on sensitive content (policy: ≤10 minutes).
## Effects & layouts (recommended defaults)
- **Film Cut** + **Blur last**: calm, professional look.
- **Shutter Flash**: more energy for party and gala moments.
- **Grid Burst**: best for high-volume uploads and big screens.
## Recommended projector setup
**Minimum (works):**
- Laptop with Chrome/Edge, 8 GB RAM
- HDMI cable (510 m)
- Projector ≥3000 ANSI lumens, 1080p
**Recommended (stable):**
- Mini PC or laptop with dedicated GPU
- Ethernet connection (USBC → Ethernet adapter)
- Projector ≥4500 ANSI lumens, 1080p/4K, 16:9
- HDMI 2.0 + active HDMI extender (10 m or more)
**Optional:**
- HDMI splitter (additional displays)
- Presentation clicker for quick focus switching
## Screen & projector tuning
1. Set resolution to **16:9**, scaling 100%.
2. Enable fullscreen (press **F** in the player or browser F11).
3. Disable sleep mode and screen lock.
4. Disable OS notifications.
## Network & stability
- Use 5 GHz WiFi or (better) Ethernet.
- Avoid guest WiFi for the player device.
- Keep the playback device **online at all times**.
## Common issues
- **Photos not showing:** check moderation mode, clear the queue, reload the Live Show link.
- **Stutter:** reduce effect intensity, switch to Single layout, check WiFi.
- **Black screen:** verify projector input, toggle browser fullscreen off/on.
### Further help
See `admin-issue-resolution` for troubleshooting or contact support.

View File

@@ -88,4 +88,49 @@ class LiveShowRealtimeTest extends TestCase
$response->assertNotFound();
}
public function test_live_show_updates_returns_settings_when_version_changes(): void
{
$event = Event::factory()->create([
'live_show_token' => str_repeat('c', 64),
'settings' => [
'live_show' => [
'effect_preset' => 'film_cut',
],
],
]);
$state = $this->getJson("/api/v1/live-show/{$event->live_show_token}");
$state->assertOk();
$version = $state->json('settings_version');
$updates = $this->getJson("/api/v1/live-show/{$event->live_show_token}/updates?settings_version={$version}");
$updates->assertOk();
$updates->assertJsonPath('settings', null);
$event->forceFill([
'settings' => [
'live_show' => [
'effect_preset' => 'shutter_flash',
],
],
])->save();
$updates = $this->getJson("/api/v1/live-show/{$event->live_show_token}/updates?settings_version={$version}");
$updates->assertOk();
$updates->assertJsonMissing(['settings' => null]);
$updates->assertJsonPath('settings.effect_preset', 'shutter_flash');
}
public function test_live_show_updates_rejects_invalid_cursor(): void
{
$event = Event::factory()->create([
'live_show_token' => str_repeat('d', 64),
]);
$response = $this->getJson("/api/v1/live-show/{$event->live_show_token}/updates?after_approved_at=invalid&after_id=1");
$response->assertStatus(422);
$response->assertJsonPath('error', 'invalid_cursor');
}
}

View File

@@ -0,0 +1,14 @@
import { test, expectFixture as expect, dismissConsentBanner } from '../helpers/test-fixtures';
const liveShowToken = process.env.E2E_LIVE_SHOW_TOKEN;
test.describe('Live Show Player', () => {
test('loads the player shell', async ({ page }) => {
test.skip(!liveShowToken, 'Set E2E_LIVE_SHOW_TOKEN to a valid live show token.');
await page.goto(`/show/${liveShowToken}`);
await dismissConsentBanner(page);
await expect(page.getByRole('button', { name: /Pause|Play|Weiter/i })).toBeVisible();
});
});