Skip to content

feat(kiosk): rotate dashboards unattended on a lobby screen from a playlist an administrator manages - #733

Merged
rubenvdlinde merged 10 commits into
developmentfrom
feat/sharing-kiosk-screens
Sep 30, 2026
Merged

rubenvdlinde merged 10 commits into
developmentfrom
feat/sharing-kiosk-screens

Conversation

@rubenvdlinde

Copy link
Copy Markdown
Contributor

What this does

Change sharing-kiosk-screens (archived in this PR). Kiosk mode was advertised and had a backend, but no page rendered it and no screen created a playlist. Now:

  • Administration has a "Kiosk" tab (src/components/admin/tabs/KioskTab.vue): list playlists, create or edit one (src/dialogs/KioskPlaylistDialog.vue, using the service's dwell and length limits), copy its public link, revoke it after a confirmation (src/dialogs/RevokeKioskPlaylistDialog.vue).
  • GET /apps/launchpad/kiosk/{token} serves a full-screen player page to a browser (Accept asks for HTML, not JSON) and keeps the JSON for the player itself. A revoked or unknown token answers 404 on both and counts toward the same brute-force bucket.
  • The player (src/kiosk.js, src/views/KioskPlayerView.vue) rotates the dashboards by their dwell time, re-reads the playlist on an interval, and keeps the last playlist on a network failure while it retries.
  • Each playlist entry now carries its dashboard's widget placements, as the public share render does. The share page's grid moved into src/components/PublicDashboardGrid.vue so the share page and the player render the same way.

Row moved to built: s-kiosk (built.change = openspec/changes/archive/2026-09-29-sharing-kiosk-screens). REQ-KIOSKUI-001..002 are folded into openspec/specs/dashboard-kiosk-mode/spec.md.

Also in this PR: the archive helper used for this lane emptied tasks.md in every change it archived. The task lists of sharing-kiosk-screens, dashboard-edit-lock-ui and dashboard-version-history-ui are restored; their Playwright tasks stay open with a note.

Scenarios and tests (red first)

Scenario Test
Create a lobby playlist KioskPlaylistDialog.spec.js "creates a lobby playlist with two dashboards"; KioskTab.spec.js "saving a new playlist posts it", "lists playlists with a copyable public link"
Dwell below the minimum KioskPlaylistDialog.spec.js "a dwell below the minimum is named and not saved"
Rotation KioskPlayerView.spec.js "rotates through the playlist and starts over"; KioskServiceTest::testRenderPlaylistIncludesEachDashboardsPlacements; KioskControllerTest::testRenderServesThePlayerPageToABrowser, testRenderKeepsJsonForTheJsonAccept
Revoked link KioskPlayerView.spec.js "a revoked link shows that the playlist is gone"; KioskControllerTest::testRenderServesA404PlayerPageForARevokedToken; KioskTab.spec.js "revoking after confirmation deletes the playlist"
Network blip KioskPlayerView.spec.js "a network blip keeps the last playlist and tries again"

The Playwright task is not written; the spec carries @e2e exclude naming these files.

Verified

Branch head 55b2c0b, development 4ff0361 merged in.

  • composer check:strict: lint, lint:initial-state, lint:spec-annotations, lint:licenses, phpcs, psalm 0; PHPUnit 1795 tests OK (12 skipped). phpstan found 1 NEW finding (a dead catch (Exception) in KioskController::renderPlayer), fixed in 00d3475; phpmd found 2 NEW CouplingBetweenObjects (KioskController 14, KioskService 13), given the repo's reasoned suppression in 55b2c0b. Re-run: composer phpstan 0, composer phpmd 0.
  • composer phpmetrics 0. npm run build 0 (new kiosk entry).
  • npm run lint, format, check:manifest, check:schema-l10n, check:l10n-parity 0.
  • Vitest: 801 of 803 pass. The two failures are inherited: Views.loadingState.spec.js times out on development too, and GroupDashboardsTab.spec.js "opens the create modal" failed under full-suite load and passes on its own (5 of 5).
  • Hydra gates (hydra-gates@main, full scope, --require-full-coverage): 83 of 83 applicable gates pass.

Inherited, not touched: check:schema-l10n reports 1 fewer uncovered string than its baseline.

Live check

As an administrator: Administration settings, Launchpad, "Kiosk" tab, create a playlist with two dashboards at 10 seconds each, copy the link. Open it in a private window: the first dashboard fills the screen, the second follows after 10 seconds. Revoke the playlist; within one refresh the screen says the playlist is gone, and curl -H 'Accept: application/json' <link> answers 404.

🤖 Generated with Claude Code

…and survives a network blip

The public share page's read-only grid moves into PublicDashboardGrid so the
player renders dashboards the same anonymous-safe way.
…lic link

Beheer gets a Kiosk tab: list playlists with their link, create and edit
them with a dwell time per dashboard inside the service limits, and revoke
one after a confirmation.
…ptied

The archive step opened tasks.md for writing before reading it, so the
kiosk, edit-lock and version-history archives kept an empty tasks.md.
Playwright tasks stay open with a note: the specs carry @e2e exclude.
…er page

phpstan found the generic Exception catch dead: renderPlaylist only declares
PlaylistNotFoundException.
…llaborators

phpmd CouplingBetweenObjects, with the repo's reasoned suppression.
@github-actions

Copy link
Copy Markdown
Contributor

Quality Report — ConductionNL/launchpad @ 21029ce

Check PHP Vue Security License Tests
lint ✅
phpcs ✅
phpmd ✅
psalm ✅
phpstan ✅
phpmetrics ✅
eslint ✅
stylelint ✅
build ✅
check-manifest ✅
format ✅
check-schema-l10n ✅
composer ✅ ✅ 104/104
npm ✅ ✅ 636/636
app:check-code ⏭️
info.xml ✅
REUSE ❌
lockfile sync ✅
PHPUnit ✅
Newman ✅
Playwright ⏭️ deferred: E2E runs locally and on the promotion path only. This pull request targets development, so the suite is asked once per promotion into beta and main rather than once per push per open pull request. Run it on any branch from the Actions tab, or locally with npx playwright test.
Hydra gates ✅

Quality workflow — 2026-09-30 02:57 UTC

Download the full PDF report from the workflow artifacts.

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