Pin the contracts the next round of work meets at
Four pieces of work are about to run in parallel — the shell, the admin page, the Timers module and the PCO Plan module — and three of them meet at things that didn't exist yet. This writes those down first, so they are built once, the same way. - **Offering timers to the Timers module.** A module declares `"provides": ["timers"]` and serves `GET /timers` (a cheap snapshot with startedAt/elapsedMs/targetMs, an optional status line, optionally an SSE stream). The consumer extrapolates locally, so no fast polling. Modules meet over loopback through each other's routes, as PCO Plan already does to follow ProPresenter. - **Admin group controls.** `configGroups[name].help` becomes an ⓘ beside the group title rather than a paragraph under it; `configGroups[name].toggle` names a switch that renders in the title row as the group's on/off. - **Switches, labelled with nouns.** On means shown or enabled; the label shouldn't say so twice. - **Themes** swap the shell variables; a tile's own configured colour is set closer and wins. Two shell hooks make it real: `/api/modules` forwards `provides`, and module servers get `shell.port` in init/routes/tiles instead of guessing it from proddash.json. Clock: descriptions gone, "Show seconds" is "Seconds" (1.0.1). Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5.1
parent
7b353cf7f8
commit
a6dc2ddb85
@@ -373,14 +373,17 @@ function mountModule(id) {
|
||||
// Re-require fresh config on every (re)mount; the module code itself stays cached.
|
||||
const mod = require(serverPath);
|
||||
const config = effectiveConfig(id);
|
||||
// What a module needs to reach the rest of ProdDash — another module's
|
||||
// routes over loopback, chiefly — without guessing.
|
||||
const shell = { port: PORT };
|
||||
if (typeof mod.init === 'function') {
|
||||
entry.handle = mod.init({ config, log }) || null;
|
||||
entry.handle = mod.init({ config, log, shell }) || null;
|
||||
}
|
||||
if (typeof mod.routes === 'function') {
|
||||
entry.routes = parseRouteTable(mod.routes({ config, log }));
|
||||
entry.routes = parseRouteTable(mod.routes({ config, log, shell }));
|
||||
}
|
||||
if (typeof mod.tiles === 'function') {
|
||||
entry.tiles = () => mod.tiles({ config, log });
|
||||
entry.tiles = () => mod.tiles({ config, log, shell });
|
||||
}
|
||||
log('mounted' + (entry.routes.length ? ` (${entry.routes.length} routes)` : ''));
|
||||
} catch (err) {
|
||||
@@ -510,6 +513,8 @@ async function clientManifest(id) {
|
||||
instanceSchema: man.instanceSchema || {},
|
||||
instanceGroups: man.instanceGroups && typeof man.instanceGroups === 'object' ? man.instanceGroups : {},
|
||||
hasServer: Boolean(man.server),
|
||||
// capabilities other modules consume ("timers") — see the module guide
|
||||
provides: Array.isArray(man.provides) ? man.provides.map(String) : [],
|
||||
config: clientConfig(id),
|
||||
tiles: await moduleTiles(id),
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user