130 lines
5.5 KiB
HTML
130 lines
5.5 KiB
HTML
<!doctype html>
|
||||
|
|
<html lang="en">
|
|||
|
|
<head>
|
|||
|
|
<meta charset="utf-8">
|
|||
|
|
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
|
|||
|
|
<meta name="theme-color" content="#0b0d12">
|
|||
|
|
<meta name="color-scheme" content="dark">
|
|||
|
|
<title>Translation — Operator</title>
|
|||
|
|
<link rel="stylesheet" href="/operator.css">
|
|||
|
|
</head>
|
|||
|
|
<body>
|
|||
|
|
|
|||
|
|
<!-- PIN gate ------------------------------------------------------------- -->
|
|||
|
|
<section id="gate" class="gate is-active">
|
|||
|
|
<form id="gateForm" class="gate-card">
|
|||
|
|
<h1>Operator</h1>
|
|||
|
|
<p class="muted">Enter the PIN for this church's translation system.</p>
|
|||
|
|
<input id="pin" type="password" inputmode="numeric" autocomplete="current-password"
|
|||
|
|
placeholder="PIN" aria-label="Operator PIN" required>
|
|||
|
|
<button type="submit" class="btn btn-primary">Unlock</button>
|
|||
|
|
<p id="gateErr" class="err" hidden></p>
|
|||
|
|
<p class="muted tiny">The PIN is in <code>data/OPERATOR-PIN.txt</code> on the NAS.</p>
|
|||
|
|
</form>
|
|||
|
|
</section>
|
|||
|
|
|
|||
|
|
<!-- Console -------------------------------------------------------------- -->
|
|||
|
|
<main id="console" class="wrap">
|
|||
|
|
|
|||
|
|
<header class="top">
|
|||
|
|
<div>
|
|||
|
|
<div class="eyebrow">Live Translation</div>
|
|||
|
|
<h1 id="svcName">—</h1>
|
|||
|
|
</div>
|
|||
|
|
<a class="ghost" href="/" target="_blank" rel="noopener">Listener view ↗</a>
|
|||
|
|
</header>
|
|||
|
|
|
|||
|
|
<!-- The one control that matters on a Sunday morning. -->
|
|||
|
|
<section class="card control">
|
|||
|
|
<button id="bigBtn" class="big" data-live="false">
|
|||
|
|
<span class="big-label">START TRANSLATING</span>
|
|||
|
|
<span class="big-sub" id="bigSub">Ready</span>
|
|||
|
|
</button>
|
|||
|
|
<p class="op-health" id="opHealth" hidden></p>
|
|||
|
|
<div class="stats">
|
|||
|
|
<div class="stat"><b id="stListeners">0</b><span>listening</span></div>
|
|||
|
|
<div class="stat"><b id="stLangs">0</b><span>languages</span></div>
|
|||
|
|
<div class="stat"><b id="stElapsed">—</b><span>elapsed</span></div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<!-- Who is actually reading, and in what. The total alone does not tell you
|
|||
|
|
whether a language is worth keeping. -->
|
|||
|
|
<div id="whoList" class="wholist" hidden></div>
|
|||
|
|
|
|||
|
|
<div id="engineWarn" class="warn" hidden>
|
|||
|
|
<strong>The Mac engine is not connected.</strong>
|
|||
|
|
<span>Open <em>Church Translate Engine</em> on the backstage Mac Studio. Nothing will translate until it is running.</span>
|
|||
|
|
</div>
|
|||
|
|
<div id="engineInfo" class="enginebar" hidden></div>
|
|||
|
|
</section>
|
|||
|
|
|
|||
|
|
<!-- Languages ---------------------------------------------------------- -->
|
|||
|
|
<section class="card">
|
|||
|
|
<h2>Languages on the front page</h2>
|
|||
|
|
<p class="muted">These show as big buttons before anyone searches. Everything else
|
|||
|
|
is still reachable through search — all <b id="totalLangs">0</b> of them.</p>
|
|||
|
|
<div id="featuredList" class="chips"></div>
|
|||
|
|
<input id="langSearch" type="search" placeholder="Add a language…" autocomplete="off">
|
|||
|
|
<div id="langResults" class="results"></div>
|
|||
|
|
|
|||
|
|
<h2 class="mt">Always translate</h2>
|
|||
|
|
<p class="muted">Normally a language is only translated while someone is actually
|
|||
|
|
listening to it. Pin one here to have it ready before the first person arrives.</p>
|
|||
|
|
<div id="pinnedList" class="chips"></div>
|
|||
|
|
</section>
|
|||
|
|
|
|||
|
|
<!-- Glossary ----------------------------------------------------------- -->
|
|||
|
|
<section class="card">
|
|||
|
|
<h2>Corrections</h2>
|
|||
|
|
<p class="muted">One per line, in the form
|
|||
|
|
<code>what it heard => what it should say</code>. This is how “have a cook”
|
|||
|
|
becomes “Habakkuk” and your pastor’s name stops being a different word every
|
|||
|
|
week. Matching ignores capitals and only hits whole words.</p>
|
|||
|
|
<textarea id="bias" rows="7" spellcheck="false"></textarea>
|
|||
|
|
<button id="saveGlossary" class="btn">Save corrections</button>
|
|||
|
|
</section>
|
|||
|
|
|
|||
|
|
<!-- Setup -------------------------------------------------------------- -->
|
|||
|
|
<section class="card">
|
|||
|
|
<h2>The QR code</h2>
|
|||
|
|
<div class="qrrow">
|
|||
|
|
<img id="qr" class="qr" alt="QR code to the listener page">
|
|||
|
|
<div class="qrside">
|
|||
|
|
<label>Public address
|
|||
|
|
<input id="publicUrl" type="url" placeholder="https://translate.yourchurch.org" spellcheck="false">
|
|||
|
|
</label>
|
|||
|
|
<p class="muted tiny">Leave blank to use whatever address this page was opened at.
|
|||
|
|
Set it once the Cloudflare tunnel is up so the QR code always points at the public name.</p>
|
|||
|
|
<div class="row">
|
|||
|
|
<button id="savePublic" class="btn">Save</button>
|
|||
|
|
<a id="posterLink" class="btn" href="/poster" target="_blank" rel="noopener">Printable poster ↗</a>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</section>
|
|||
|
|
|
|||
|
|
<section class="card">
|
|||
|
|
<h2>Stream Deck / Companion</h2>
|
|||
|
|
<p class="muted">Add a <b>Generic HTTP</b> action in Companion. Method GET, and one of:</p>
|
|||
|
|
<div class="codeblock"><code id="urlToggle">—</code><button class="copy" data-copy="urlToggle">Copy</button></div>
|
|||
|
|
<div class="codeblock"><code id="urlStart">—</code><button class="copy" data-copy="urlStart">Copy</button></div>
|
|||
|
|
<div class="codeblock"><code id="urlStop">—</code><button class="copy" data-copy="urlStop">Copy</button></div>
|
|||
|
|
<p class="muted tiny">Keep this key off the projector — anyone with it can start and stop translation.</p>
|
|||
|
|
</section>
|
|||
|
|
|
|||
|
|
<section class="card">
|
|||
|
|
<h2>Change the PIN</h2>
|
|||
|
|
<div class="row">
|
|||
|
|
<input id="newPin" type="password" placeholder="New PIN (4+ characters)" autocomplete="new-password">
|
|||
|
|
<button id="savePin" class="btn">Update PIN</button>
|
|||
|
|
</div>
|
|||
|
|
</section>
|
|||
|
|
|
|||
|
|
<div id="toast" class="toast" hidden></div>
|
|||
|
|
</main>
|
|||
|
|
|
|||
|
|
<script src="/languages.js"></script>
|
|||
|
|
<script src="/operator.js"></script>
|
|||
|
|
</body>
|
|||
|
|
</html>
|