From 1720f05269d87e393a1b207962048be0cb02b8b3 Mon Sep 17 00:00:00 2001 From: larssand Date: Sun, 15 Mar 2026 10:41:43 +0100 Subject: [PATCH] Refine overview panel and compact overlay header --- src/app.js | 162 ++++++++++++++++++++++++++++++++++--------------- src/styles.css | 75 +++++++++++++++++++++-- 2 files changed, 183 insertions(+), 54 deletions(-) diff --git a/src/app.js b/src/app.js index 25cf731..59e7170 100644 --- a/src/app.js +++ b/src/app.js @@ -65,6 +65,11 @@ const TRANSLATIONS = { "dashboard.recent_sessions": "Senaste sessioner", "dashboard.free_practice": "Fri träning", "dashboard.open_practice": "Open Practice", + "dashboard.live_board": "Live Board", + "dashboard.decoder_feed": "Decoder-feed", + "dashboard.backend_link": "Backend-länk", + "dashboard.audio_profile": "Ljudprofil", + "dashboard.live_note": "Snabb driftpanel för anslutning, overlay och ljud. Djupare konfig ligger kvar under Inställningar.", "session.none_yet": "Inga sessioner ännu.", "classes.create": "Skapa klass", "classes.placeholder": "Klassnamn (t.ex. 2WD Buggy)", @@ -542,6 +547,11 @@ const TRANSLATIONS = { "dashboard.recent_sessions": "Recent Sessions", "dashboard.free_practice": "Free Practice", "dashboard.open_practice": "Open Practice", + "dashboard.live_board": "Live Board", + "dashboard.decoder_feed": "Decoder feed", + "dashboard.backend_link": "Backend link", + "dashboard.audio_profile": "Audio profile", + "dashboard.live_note": "Quick operations panel for connection, overlay and audio. Deeper configuration remains under Settings.", "session.none_yet": "No sessions yet.", "classes.create": "Create Class", "classes.placeholder": "Class name (e.g. 2WD Buggy)", @@ -1961,6 +1971,14 @@ function renderDashboard() { (sum, x) => sum + (x.passings?.length || 0), 0 ); + const backendUrl = getBackendUrl(); + const decoderUrl = state.settings.wsUrl || "-"; + const audioProfile = + state.settings.passingSoundMode === "name" + ? t("settings.passing_sound_name") + : state.settings.passingSoundMode === "beep" + ? t("settings.passing_sound_beep") + : t("settings.passing_sound_off"); dom.view.innerHTML = `
@@ -1989,12 +2007,35 @@ function renderDashboard() {
-

${t("dashboard.quick_actions")}

+

${t("dashboard.live_board")}

-
- - - +
+

${t("dashboard.live_note")}

+
+
+ ${t("dashboard.decoder_feed")} + ${state.decoder.connected ? t("timing.connected") : t("timing.disconnected")} + ${escapeHtml(decoderUrl)} +
+
+ ${t("dashboard.backend_link")} + ${backend.available ? t("settings.online") : t("settings.offline")} + ${escapeHtml(backendUrl)} +
+
+ ${t("dashboard.audio_profile")} + ${state.settings.audioEnabled ? audioProfile : t("settings.passing_sound_off")} + ${state.settings.finishVoiceEnabled ? t("settings.finish_voice") : "-"} +
+
+
+ + + + + + +
@@ -2022,6 +2063,15 @@ function renderDashboard() { }); document.getElementById("connectNow")?.addEventListener("click", connectDecoder); + document.getElementById("disconnectNow")?.addEventListener("click", disconnectDecoder); + document.getElementById("openDashboardOverlay")?.addEventListener("click", openOverlayWindow); + document.getElementById("dashboardTestAudio")?.addEventListener("click", () => { + ensureAudioContext(); + playPassingBeep(); + if (state.settings.finishVoiceEnabled) { + setTimeout(playFinishSiren, 220); + } + }); } function statCard(label, value, note) { @@ -3984,11 +4034,18 @@ function renderOverlay() { active ? `
-
+
${branding.logoDataUrl ? `` : ""} -

${escapeHtml(getEventName(active.eventId))}

-

${escapeHtml(active.name)} • ${escapeHtml(getSessionTypeLabel(active.type))}

-

${escapeHtml(branding.brandName)} • ${escapeHtml(getStartModeLabel(active.startMode))} • ${escapeHtml(modeLabel)}

+
+
+

${escapeHtml(getEventName(active.eventId))}

+ ${escapeHtml(getSessionTypeLabel(active.type))} + ${escapeHtml(getStartModeLabel(active.startMode))} + ${escapeHtml(modeLabel)} +
+

${escapeHtml(active.name)}

+

${escapeHtml(branding.brandName || "JMK RB Live Event")}

+
@@ -4414,7 +4471,7 @@ function renderSettings() { dom.view.innerHTML = `

${t("settings.decoder")}

-
+ ${t("settings.auto_reconnect")} - - - - - - - - -

${t("settings.expected_json")}: {"msg":"PASSING", "transponder":232323, "rtc_time":"..."}

-

${t("settings.audio_note")}

+

${t("dashboard.live_note")}

+
+
+ +
+

${t("settings.audio")}

+
+ + + + + + + + + +
+
+

${t("settings.audio_note")}

diff --git a/src/styles.css b/src/styles.css index 01ed8b3..7db64f5 100644 --- a/src/styles.css +++ b/src/styles.css @@ -450,6 +450,37 @@ select:focus { justify-content: flex-end; } +.dashboard-live-stack { + display: grid; + gap: 14px; +} + +.dashboard-live-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); + gap: 12px; +} + +.dashboard-live-card { + border: 1px solid var(--line); + border-radius: 14px; + padding: 14px 16px; + background: rgba(255, 255, 255, 0.03); +} + +.dashboard-live-card span, +.dashboard-live-card small { + display: block; + color: var(--muted); +} + +.dashboard-live-card strong { + display: block; + margin: 8px 0 4px; + font-family: Orbitron, sans-serif; + font-size: 1.1rem; +} + .quick-add-spacer { display: flex; align-items: center; @@ -628,14 +659,34 @@ select:focus { display: flex; justify-content: space-between; gap: 16px; - align-items: flex-end; - margin-bottom: 18px; + align-items: center; + margin-bottom: 14px; +} + +.overlay-header-main { + display: flex; + align-items: center; + gap: 14px; + min-width: 0; +} + +.overlay-header-copy { + min-width: 0; +} + +.overlay-kicker-row { + display: flex; + align-items: center; + gap: 8px; + flex-wrap: wrap; + margin-bottom: 4px; } .overlay-header h1 { - margin: 4px 0; + margin: 0; font-family: Orbitron, sans-serif; - font-size: clamp(2rem, 4vw, 3.8rem); + font-size: clamp(1.35rem, 2.4vw, 2.3rem); + line-height: 1.05; } .overlay-kicker { @@ -643,18 +694,25 @@ select:focus { color: var(--muted); text-transform: uppercase; letter-spacing: 0.1em; + font-size: 0.72rem; +} + +.overlay-header-sub { + margin: 6px 0 0; + color: var(--muted); + font-size: 0.9rem; } .overlay-meta { text-align: right; display: grid; justify-items: end; - gap: 10px; + gap: 6px; } .overlay-clock { font-family: Orbitron, sans-serif; - font-size: clamp(2.6rem, 5vw, 4.8rem); + font-size: clamp(1.8rem, 3vw, 3rem); font-weight: 800; } @@ -666,6 +724,7 @@ select:focus { color: var(--muted); text-transform: uppercase; letter-spacing: 0.08em; + font-size: 0.74rem; } .overlay-board { @@ -1091,6 +1150,10 @@ select:focus { flex-direction: column; } + .overlay-header-main { + align-items: flex-start; + } + .modal-overlay { padding: 12px; }