Add multi-player and remote bridge support

This commit is contained in:
2026-08-07 02:58:18 +01:00
parent a4f8a807ff
commit 74318eb34e
58 changed files with 3785 additions and 432 deletions
+18 -15
View File
@@ -34,8 +34,8 @@
{{/if}}
{{#if (hasPermission currentUser "clients.read")}}
<div class="dashboard-hero-stat">
<span class="dashboard-hero-stat-value">{{connectedClientsCount}}</span>
<span class="dashboard-hero-stat-label">clients</span>
<span id="dashboard-player-count" class="dashboard-hero-stat-value">{{connectedPlayersCount}}</span>
<span class="dashboard-hero-stat-label">players</span>
</div>
{{/if}}
</div>
@@ -157,12 +157,25 @@
</div>
<p class="mb-0 mt-2 text-muted small">Check this box to enable the Windows and Linux downloads.</p>
</div>
<div class="d-grid gap-2">
<select class="form-select" id="dashboard-kiosk-launcher-player-select" data-kiosk-launcher-player-select>
<option value="">Select a player</option>
{{#each kioskPlayers}}
{{#if player_identifier}}
{{#if player_url}}
<option value="{{player_url}}" data-player-identifier="{{player_identifier}}">{{player_identifier}} - {{player_url}}</option>
{{/if}}
{{/if}}
{{/each}}
</select>
<p class="mb-0 text-muted small">The download will open the selected player's public URL when the kiosk starts.</p>
</div>
<div class="d-flex flex-column flex-sm-row gap-2">
<a class="btn btn-outline-primary btn-lg flex-fill disabled dashboard-kiosk-launcher-download" href="/downloads/kiosk/pulse-signage-kiosk.bat" data-kiosk-launcher-download aria-disabled="true" tabindex="-1">
<a class="btn btn-outline-primary btn-lg flex-fill disabled dashboard-kiosk-launcher-download" data-kiosk-launcher-download data-kiosk-launcher-download-base="/downloads/kiosk/pulse-signage-kiosk.bat" aria-disabled="true" tabindex="-1">
<i class="bi bi-windows me-2" aria-hidden="true"></i>
<span>Download for Windows</span>
</a>
<a class="btn btn-outline-secondary btn-lg flex-fill disabled dashboard-kiosk-launcher-download" href="/downloads/kiosk/pulse-signage-kiosk.sh" data-kiosk-launcher-download aria-disabled="true" tabindex="-1">
<a class="btn btn-outline-secondary btn-lg flex-fill disabled dashboard-kiosk-launcher-download" data-kiosk-launcher-download data-kiosk-launcher-download-base="/downloads/kiosk/pulse-signage-kiosk.sh" aria-disabled="true" tabindex="-1">
<i class="bi bi-terminal me-2" aria-hidden="true"></i>
<span>Download for Linux</span>
</a>
@@ -178,8 +191,7 @@
<div class="card-header dashboard-screen-card-header">
<div class="dashboard-card-heading">
<h3 class="card-title">Screen group snapshot</h3>
<p class="dashboard-card-subtitle">Player URL, playlist assignment,
and live connection count without the spreadsheet feel.</p>
<p class="dashboard-card-subtitle">Playlist assignment and live connection state without the spreadsheet feel.</p>
</div>
<a class="btn btn-sm btn-primary" href="/screens">Manage screen groups</a>
</div>
@@ -191,11 +203,6 @@
<div class="dashboard-screen-tile-top">
<div class="dashboard-screen-tile-text">
<h4 class="dashboard-screen-name">{{name}}</h4>
{{#if player_url}}
<a class="dashboard-screen-link" href="{{player_url}}" target="_blank">{{player_url}}</a>
{{else}}
<span class="dashboard-screen-link empty">Not available</span>
{{/if}}
</div>
<span class="dashboard-screen-pill {{#if player_connection_count}}is-live{{else}}is-idle{{/if}}">
{{#if player_connection_count}}
@@ -210,10 +217,6 @@
<dt>Playlist</dt>
<dd>{{#if playlist_name}}{{playlist_name}}{{else}}Unassigned{{/if}}</dd>
</div>
<div>
<dt>Connections</dt>
<dd>{{#if player_connection_count}}{{player_connection_count}} connected{{else}}No clients connected{{/if}}</dd>
</div>
</dl>
</article>
{{/each}}
+31 -6
View File
@@ -6,7 +6,7 @@
</div>
<div class="row g-4">
<div class="col-12 col-xl-8">
<div class="col-12 col-xl-6">
<div class="card card-outline card-primary admin-form-card h-100">
<div class="card-header">
<h3 class="card-title">Screen group details</h3>
@@ -40,16 +40,41 @@
</div>
</div>
<div class="col-12 col-xl-4">
<div class="col-12 col-xl-6">
<div class="card card-outline card-secondary admin-form-card h-100">
<div class="card-header">
<h3 class="card-title">Player URL</h3>
<h3 class="card-title">Player URLs</h3>
</div>
<div class="card-body">
{{#if screen.player_url}}
<p class="mb-0"><a href="{{screen.player_url}}" target="_blank">{{screen.player_url}}</a></p>
{{#if screen.player_urls.length}}
<div class="table-responsive">
<table class="table table-sm align-middle mb-0">
<thead>
<tr>
<th>Player</th>
<th>URL</th>
</tr>
</thead>
<tbody>
{{#each screen.player_urls}}
<tr>
<td>
<div class="fw-semibold">{{identifier}}</div>
</td>
<td>
{{#if player_url}}
<a href="{{player_url}}" target="_blank" rel="noreferrer">{{player_url}}</a>
{{else}}
<span class="text-muted">Not available</span>
{{/if}}
</td>
</tr>
{{/each}}
</tbody>
</table>
</div>
{{else}}
<p class="mb-0 text-muted">No player URL is available yet.</p>
<p class="mb-0 text-muted">No player URLs are available yet.</p>
{{/if}}
</div>
</div>
+1 -9
View File
@@ -23,7 +23,6 @@
<thead>
<tr>
<th data-table-sort-key="name">Name</th>
<th data-table-sort-key="url">Player URL</th>
<th data-table-sort-key="playlist">Playlist</th>
<th data-table-sort-key="player_connection_count">Connected</th>
<th>Actions</th>
@@ -34,13 +33,6 @@
{{#each screens}}
<tr data-table-search-row>
<td data-label="Name">{{name}}</td>
<td data-label="Player URL">
{{#if player_url}}
<a href="{{player_url}}" target="_blank">{{player_url}}</a>
{{else}}
<span class="empty">Not available</span>
{{/if}}
</td>
<td data-label="Playlist">{{playlist_name}}</td>
<td data-label="Connected clients">
{{#if (gt player_connection_count 0)}}
@@ -72,7 +64,7 @@
</tr>
{{/each}}
{{else}}
<tr data-table-search-empty-default><td colspan="5" class="empty">No screen groups yet.</td></tr>
<tr data-table-search-empty-default><td colspan="4" class="empty">No screen groups yet.</td></tr>
{{/if}}
</tbody>
</table>
@@ -58,6 +58,12 @@
<div class="slide-preview-popup-canvas" id="popup-preview-canvas"></div>
</div>
{{#if popupPreviewPayloadJson}}
<script>
window.__pulsePopupPreviewPayload = {{{popupPreviewPayloadJson}}};
</script>
{{/if}}
<script>
(function () {
function startPreviewVideoPlayback(root) {
@@ -127,6 +133,10 @@
var canvas = document.getElementById('popup-preview-canvas');
function readPayload() {
if (window.__pulsePopupPreviewPayload) {
return window.__pulsePopupPreviewPayload;
}
var hash = String(window.location.hash || '').replace(/^#/, '');
if (!hash) {
return null;