Files
ProdDash/public/admin/index.html
T
Waters ChurchandClaude Fable 5.1 ac1f17b9ed Shell 1.10.0: a packaged ProdDash carries no modules
The macOS app and the Windows bundle shipped every module in the repo, on
by default, and a shell update silently added whatever new module had
landed on main — Band Lineup appeared on AB that way. A module was also
only as fresh as the last shell update. Now a packaged install (no .git —
the same test the updater uses to choose the archive over git pull)
carries no modules at all: every one arrives from the admin page's catalog
into the data directory, and the shell's own update never writes modules/.
A git checkout keeps running the modules in its tree.

Existing installs move over by themselves: at the first start, the bundled
modules that are switched on are copied into the data directory as
installed copies (a compiled helper keeps its mode), an uninstalled one is
dropped, and the app folder's modules/ is removed. Settings are keyed by
module id, so nothing changes for the operator.

Around it: the dashboard's empty state says "No modules yet — open Admin"
when the registry is empty; the admin page says "Nothing installed yet",
puts a checkbox on every compatible catalog entry and an Install selected
button (POST /api/admin/modules/install {ids}) that fetches them in one go.
The Mac build stops copying modules/ and no longer compiles or signs Swift
helpers — those ship prebuilt inside a module, per the guide.

tools/unbundled.test.js drives a packaged copy of the shell through the
move, an archive update that must not bring modules back, and a multi-install.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-30 09:34:10 -04:00

108 lines
4.4 KiB
HTML

<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>ProdDash Admin</title>
<meta name="theme-color" content="#0b0e12">
<link rel="icon" href="/icons/icon-192.png">
<link rel="stylesheet" href="/style.css">
<link rel="stylesheet" href="/admin/admin.css">
</head>
<body>
<header id="topbar">
<span id="brand">Prod<span class="accent">Dash</span> <span class="admin-tag">Admin</span> <span class="admin-version" id="shell-version"></span></span>
<span class="spacer"></span>
<a class="tb-btn" href="/">← Dashboard</a>
</header>
<main id="admin-main">
<section class="admin-card" id="login-card" hidden>
<h2>Admin PIN</h2>
<p class="admin-copy">This page changes the server-wide configuration for every dashboard in the building.</p>
<div class="login-row">
<input type="password" id="passcode" class="pin-input" inputmode="numeric" autocomplete="off"
maxlength="6" placeholder="••••••" aria-label="Admin PIN">
<button class="btn primary" id="login-btn">Unlock</button>
</div>
<div class="admin-status" id="login-status"></div>
</section>
<section class="admin-card update-card" id="update-card" hidden>
<div class="update-head">
<span class="dot connecting"></span>
<strong id="update-title">Update available</strong>
<span class="spacer"></span>
<a class="btn small" id="update-changes" href="#" target="_blank" rel="noopener">What changed</a>
<button class="btn small primary" id="update-btn">Update now</button>
</div>
<p class="admin-copy" id="update-copy"></p>
<div class="admin-status" id="update-status"></div>
</section>
<section id="theme-section" hidden>
<details class="admin-fold">
<summary class="admin-h1 admin-fold-title">Theme</summary>
<div class="theme-swatches" id="theme-swatches" role="radiogroup" aria-label="Theme"></div>
<div class="admin-status" id="theme-status"></div>
</details>
</section>
<section id="modules-section" hidden>
<h1 class="admin-h1">Modules</h1>
<p class="admin-copy admin-storage" id="storage-note" hidden>Saved on the server at
<code id="storage-path"></code> — outside the app folder, so updating ProdDash keeps them.</p>
<div id="modules-list"></div>
</section>
<section id="available-section" hidden>
<h1 class="admin-h1">Available modules</h1>
<div class="catalog-toolbar">
<button class="btn small primary" id="install-selected" hidden>Install selected</button>
<button class="btn small" id="catalog-refresh">Check again</button>
<span class="admin-status" id="catalog-status"></span>
</div>
<div id="available-list"></div>
</section>
<section id="layouts-section" hidden>
<h1 class="admin-h1">Saved layouts</h1>
<div id="layouts-list"></div>
</section>
<section id="security-section" hidden>
<h1 class="admin-h1">Admin PIN</h1>
<p class="admin-copy" id="pin-state"></p>
<div class="admin-card">
<div class="pin-form">
<label class="pin-field" id="pin-current-field" hidden>
<span>Current PIN</span>
<input type="password" id="pin-current" class="pin-input" inputmode="numeric"
autocomplete="off" maxlength="6" placeholder="••••••">
</label>
<label class="pin-field">
<span id="pin-new-label">New PIN</span>
<input type="password" id="pin-new" class="pin-input" inputmode="numeric"
autocomplete="off" maxlength="6" placeholder="6 digits">
</label>
<label class="pin-field">
<span>Repeat</span>
<input type="password" id="pin-repeat" class="pin-input" inputmode="numeric"
autocomplete="off" maxlength="6" placeholder="6 digits">
</label>
<div class="pin-actions">
<button class="btn primary" id="pin-save">Set PIN</button>
<button class="btn" id="pin-clear" hidden>Turn off</button>
</div>
</div>
<div class="admin-status" id="pin-status"></div>
</div>
</section>
</main>
<div id="toast" hidden></div>
<script type="module" src="/admin/admin.js"></script>
</body>
</html>