@bongos/core 1.24.29 → 1.24.31
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.bongos-core.json +198 -108
- package/clients/bongos-client/README.md +1 -1
- package/clients/bongos-client/bongos-client.global.js +12 -0
- package/clients/bongos-client/index.cjs +12 -0
- package/clients/bongos-client/index.d.ts +12 -0
- package/clients/bongos-client/index.mjs +12 -0
- package/docs/api/openapi.json +174 -1
- package/docs/api-reference.md +12 -2
- package/docs/copy-inventory.md +226 -224
- package/docs/copy-registry.json +583 -549
- package/docs/module-api-changelog.md +2 -0
- package/docs/page-inventory.json +18 -37
- package/docs/page-readings.json +306 -361
- package/modules/copy-desk/module.json +1 -1
- package/modules/copy-desk/routes/copy-desk-studio.js +103 -0
- package/modules/copy-desk/tests/copy_no_cms.mjs +2 -2
- package/modules/government/db.js +29 -0
- package/modules/government/docket.js +61 -4
- package/modules/government/routes/government.js +2 -0
- package/modules/hall-ui/public/ai-studio.html +1 -1
- package/modules/hall-ui/public/atlas.html +1 -1
- package/modules/hall-ui/public/blockers.html +1 -1
- package/modules/hall-ui/public/board-room.html +1 -1
- package/modules/hall-ui/public/builders.js +3 -79
- package/modules/hall-ui/public/city.html +1 -1
- package/modules/hall-ui/public/collab.html +1 -1
- package/modules/hall-ui/public/commands.html +1 -1
- package/modules/hall-ui/public/copy-desk.html +1 -1
- package/modules/hall-ui/public/craft-mode.js +1 -1
- package/modules/hall-ui/public/deploy.html +1 -1
- package/modules/hall-ui/public/diagrams.html +1 -1
- package/modules/hall-ui/public/drachmae.html +1 -1
- package/modules/hall-ui/public/fleet.html +1 -1
- package/modules/hall-ui/public/gate.html +1 -1
- package/modules/hall-ui/public/goal-map.html +1 -1
- package/modules/hall-ui/public/goals.html +1 -1
- package/modules/hall-ui/public/government.html +1 -1
- package/modules/hall-ui/public/hall-render.js +68 -167
- package/modules/hall-ui/public/hall-widgets.js +4 -45
- package/modules/hall-ui/public/home-city-draw.js +583 -0
- package/modules/hall-ui/public/home-city.css +102 -0
- package/modules/hall-ui/public/home-city.js +339 -0
- package/modules/hall-ui/public/home-gallery.css +129 -0
- package/modules/hall-ui/public/home-gallery.js +349 -0
- package/modules/hall-ui/public/home-studio.css +72 -0
- package/modules/hall-ui/public/home-studio.js +203 -0
- package/modules/hall-ui/public/idea.html +1 -1
- package/modules/hall-ui/public/ideas.html +1 -1
- package/modules/hall-ui/public/index.html +9 -7
- package/modules/hall-ui/public/index.states.json +73 -8
- package/modules/hall-ui/public/market-watch-item.html +1 -1
- package/modules/hall-ui/public/market-watch-rules.html +1 -1
- package/modules/hall-ui/public/market-watch-settings.js +6 -1
- package/modules/hall-ui/public/market-watch.html +141 -54
- package/modules/hall-ui/public/market-watch.js +54 -0
- package/modules/hall-ui/public/market-watch.states.json +2 -1
- package/modules/hall-ui/public/modules.html +1 -1
- package/modules/hall-ui/public/my-agents.html +1 -1
- package/modules/hall-ui/public/primer.html +1 -1
- package/modules/hall-ui/public/profile.html +1 -1
- package/modules/hall-ui/public/project-settings.html +1 -1
- package/modules/hall-ui/public/ranks.html +1 -1
- package/modules/hall-ui/public/roadmap.html +1 -1
- package/modules/hall-ui/public/roster.html +1 -1
- package/modules/hall-ui/public/sessions.html +1 -1
- package/modules/hall-ui/public/settings.html +1 -1
- package/modules/hall-ui/public/shell.js +2 -3
- package/modules/hall-ui/public/street.html +1 -1
- package/modules/hall-ui/public/studio.html +9 -1
- package/modules/hall-ui/public/style.css +74 -27
- package/modules/hall-ui/public/task.html +1 -1
- package/modules/hall-ui/public/thinking.html +1 -1
- package/modules/hall-ui/public/tweak-editor.html +1 -1
- package/modules/hall-ui/public/watch.html +1 -1
- package/modules/hall-ui/public/work.html +1 -1
- package/modules/hall-ui/records/home-city.md +189 -0
- package/modules/hall-ui/records/loader.md +1 -1
- package/modules/hall-ui/records/market-watch-settings.md +16 -3
- package/modules/hall-ui/records/market-watch.md +3 -1
- package/modules/lifecycle/home-city.js +388 -0
- package/modules/lifecycle/home-gallery.js +320 -0
- package/modules/lifecycle/migrations/lifecycle_020_work_appreciations.sql +36 -0
- package/modules/lifecycle/module.json +2 -0
- package/modules/lifecycle/routes/home-city.js +29 -0
- package/modules/lifecycle/routes/home-gallery.js +37 -0
- package/modules/market-watch/routes/settings.js +1 -1
- package/package-lock.json +2 -2
- package/package.json +1 -1
- package/release-notes.json +38 -0
- package/scripts/bongos/leak-scan-allowlist.js +8 -0
- package/scripts/hall-preview/README.md +1 -0
- package/scripts/hall-preview/server.js +10 -0
- package/src/bongos/serve-internal.js +17 -3
- package/src/module-api.js +1 -1
- package/tests/claim_from_task_and_home.mjs +8 -43
- package/tests/hall_board_world.mjs +10 -12
- package/tests/hall_builders_page_pass.mjs +18 -27
- package/tests/hall_home_ships_bounded.mjs +4 -3
- package/tests/hall_loading.mjs +1 -1
- package/tests/hall_nav.mjs +11 -4
- package/tests/hall_page_gate_map.mjs +7 -4
- package/tests/home_bounded_reads.mjs +16 -31
- package/tests/home_city.mjs +580 -0
- package/tests/home_city_widget.mjs +260 -0
- package/tests/home_gallery.mjs +255 -0
- package/tests/home_gallery_widget.mjs +220 -0
- package/tests/home_studio.mjs +169 -0
- package/tests/home_studio_widget.mjs +157 -0
- package/tests/leaderboard_roles.mjs +3 -2
- package/tests/market_watch_pages.mjs +162 -0
- package/tests/nav_permission_atoms.mjs +2 -2
- package/modules/hall-ui/public/market-watch-settings.html +0 -115
- package/modules/hall-ui/public/market-watch-settings.states.json +0 -14
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
'use strict';
|
|
23
23
|
|
|
24
24
|
window.OTBHallRender = function createHallRender(ctx) {
|
|
25
|
-
const { API, RANK_ORDER, api, brandWorld, curLabel, emptyRow, fmtDate, getJSON,
|
|
25
|
+
const { API, RANK_ORDER, api, brandWorld, curLabel, emptyRow, fmtDate, getJSON, mins, normalizeRank, pct, postJSON, rankLabel, rankWeight, signClasses, toast, usd } = ctx;
|
|
26
26
|
const { escapeHtml, $, fmtNum, moduleOn } = window.OTB;
|
|
27
27
|
|
|
28
28
|
const RANK_UNLOCKS = {
|
|
@@ -273,69 +273,40 @@
|
|
|
273
273
|
return v === 'open' || v === 'invite_only' ? v : 'apply';
|
|
274
274
|
}
|
|
275
275
|
|
|
276
|
-
//
|
|
277
|
-
//
|
|
276
|
+
// The signed-out page is one centred card (task: sign-in redesign): the
|
|
277
|
+
// sign-in button leads in every mode, and the door below it is the only part
|
|
278
|
+
// that depends on joinability — open → nothing to do, invite_only → nothing
|
|
279
|
+
// to apply for, apply → the request form, folded behind a disclosure so the
|
|
280
|
+
// card stays a sign-in screen rather than a form.
|
|
278
281
|
function landingDoorHtml(mode) {
|
|
279
|
-
const hub = `This is the builders' hub for ${brandWorld()} — where builders claim work, earn ${curLabel()}, and see what they have accomplished.`;
|
|
280
282
|
const admitter = escapeHtml(rankLabel('archon'));
|
|
281
|
-
const signIn = `<p class="landing__cta"><a class="landing__btn" href="${API}/auth/web/start">Sign in with GitHub</a></p>`;
|
|
282
283
|
if (mode === 'open') {
|
|
283
284
|
return `
|
|
284
|
-
<p class="
|
|
285
|
-
<div class="landing__request" id="landing-request">
|
|
286
|
-
<h3 class="landing__request-h">New here — sign in to join</h3>
|
|
287
|
-
<p class="landing__request-lede">No request and no invite needed. Sign in with GitHub, and a step-by-step guide takes you the rest of the way.</p>
|
|
288
|
-
${signIn}
|
|
289
|
-
</div>`;
|
|
285
|
+
<p class="landing__door" id="landing-request">New here? Signing in creates your account.</p>`;
|
|
290
286
|
}
|
|
291
287
|
if (mode === 'invite_only') {
|
|
292
288
|
return `
|
|
293
|
-
<p class="
|
|
294
|
-
<div class="landing__request" id="landing-request">
|
|
295
|
-
<h3 class="landing__request-h">Invited? Sign in</h3>
|
|
296
|
-
<p class="landing__request-lede">If the ${admitter} has invited you, sign in with GitHub and you're in. If not, ask them for an invite — this project doesn't take requests.</p>
|
|
297
|
-
${signIn}
|
|
298
|
-
</div>`;
|
|
289
|
+
<p class="landing__door" id="landing-request">Invite-only — there is nothing to apply for here.</p>`;
|
|
299
290
|
}
|
|
300
291
|
return `
|
|
301
|
-
<
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
</label>
|
|
320
|
-
<label class="landing__field">
|
|
321
|
-
<span>Your name <span class="landing__opt">(optional)</span></span>
|
|
322
|
-
<input type="text" id="ar-name" name="display_name" autocomplete="name"
|
|
323
|
-
placeholder="So the Archon knows who you are" maxlength="100">
|
|
324
|
-
</label>
|
|
325
|
-
<label class="landing__field">
|
|
326
|
-
<span>A word on why <span class="landing__opt">(optional)</span></span>
|
|
327
|
-
<input type="text" id="ar-note" name="note"
|
|
328
|
-
placeholder="How you got here, what you'd build" maxlength="500">
|
|
329
|
-
</label>
|
|
330
|
-
<p class="landing__form-hint">
|
|
331
|
-
No GitHub account yet? Make a free one at
|
|
332
|
-
<a href="https://github.com/signup" target="_blank" rel="noopener noreferrer">github.com</a>
|
|
333
|
-
first — your username is all we need.
|
|
334
|
-
</p>
|
|
335
|
-
<button type="submit" class="landing__btn landing__btn--request" id="ar-submit">Request access</button>
|
|
336
|
-
<p class="landing__request-status" id="ar-status" aria-live="polite"></p>
|
|
337
|
-
</form>
|
|
338
|
-
</div>`;
|
|
292
|
+
<details class="landing__disclosure">
|
|
293
|
+
<summary class="landing__summary">New here? Request access</summary>
|
|
294
|
+
<div class="landing__request" id="landing-request">
|
|
295
|
+
<form class="landing__form" id="access-request-form" novalidate>
|
|
296
|
+
<label class="landing__field">
|
|
297
|
+
<span>GitHub username</span>
|
|
298
|
+
<input type="text" id="ar-login" name="github_login" autocomplete="username"
|
|
299
|
+
placeholder="e.g. octocat" maxlength="40" required>
|
|
300
|
+
</label>
|
|
301
|
+
<label class="landing__field">
|
|
302
|
+
<span>Why you'd like in <span class="landing__opt">(optional)</span></span>
|
|
303
|
+
<input type="text" id="ar-note" name="note" maxlength="500">
|
|
304
|
+
</label>
|
|
305
|
+
<button type="submit" class="landing__btn landing__btn--quiet landing__btn--block" id="ar-submit">Request access</button>
|
|
306
|
+
<p class="landing__request-status" id="ar-status" aria-live="polite"></p>
|
|
307
|
+
</form>
|
|
308
|
+
</div>
|
|
309
|
+
</details>`;
|
|
339
310
|
}
|
|
340
311
|
|
|
341
312
|
// task 1002835: a karma vote on a peer's ship was a vote on a title alone.
|
|
@@ -360,28 +331,39 @@
|
|
|
360
331
|
}
|
|
361
332
|
return `<span class="acclaim__evidence">${parts.join(' · ')}</span>`;
|
|
362
333
|
}
|
|
363
|
-
// The
|
|
364
|
-
//
|
|
365
|
-
|
|
366
|
-
// one — those modes keep the prose note alone. Only the `apply` door, whose
|
|
367
|
-
// primary control is the request FORM, left signing in as a footnote link.
|
|
368
|
-
// It gets a real button: the request button's geometry so it reads as a
|
|
369
|
-
// control, a quieter fill so the request path still leads for the strangers
|
|
370
|
-
// who are most of this page's traffic.
|
|
371
|
-
function returningDoorHtml(mode) {
|
|
372
|
-
if (mode !== 'apply') return '';
|
|
334
|
+
// The sign-in itself — the card's one primary control, in every mode, so a
|
|
335
|
+
// returning builder never hunts for it below a form (task 1002851's intent).
|
|
336
|
+
function returningDoorHtml() {
|
|
373
337
|
return `
|
|
374
|
-
<
|
|
375
|
-
<
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
338
|
+
<a class="landing__btn landing__btn--block" id="landing-signin" href="${API}/auth/web/start">
|
|
339
|
+
<svg class="landing__gh" viewBox="0 0 16 16" width="18" height="18" aria-hidden="true"><path fill="currentColor" d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0016 8c0-4.42-3.58-8-8-8z"/></svg>
|
|
340
|
+
Sign in with GitHub
|
|
341
|
+
</a>`;
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
// The project's mark, as the sidebar draws it: the pack's own logo when it has
|
|
345
|
+
// one (theme.logo, ADR 0358), otherwise the Cloud Bongos ring-and-moon.
|
|
346
|
+
function landingLogoHtml() {
|
|
347
|
+
const b = window.__BRANDING__ || {};
|
|
348
|
+
const logo = b.theme && b.theme.logo;
|
|
349
|
+
return logo
|
|
350
|
+
? `<img class="landing__logo" src="${escapeHtml(logo)}" alt="" width="56" height="56" decoding="async">`
|
|
351
|
+
: '<svg class="landing__logo" viewBox="0 0 200 200" aria-hidden="true"><path class="landing__ring" d="M137 31 A78 78 0 1 0 170 66" fill="none" stroke-width="15" stroke-linecap="round"/><circle class="landing__planet" cx="100" cy="100" r="55"/><circle cx="156" cy="46" r="12" fill="#fb9569"/></svg>';
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
// Strip the hall's chrome (rail, top bar, foot) for the signed-out card —
|
|
355
|
+
// html[data-door="out"], styled in style.css. The test vm has no
|
|
356
|
+
// documentElement, hence the guard.
|
|
357
|
+
function markSignedOut() {
|
|
358
|
+
const root = document.documentElement;
|
|
359
|
+
if (root && root.dataset) root.dataset.door = 'out';
|
|
379
360
|
}
|
|
380
361
|
|
|
381
362
|
function renderLanding() {
|
|
382
|
-
// task 1723: collapse the shell nav to the signed-out minimum
|
|
383
|
-
//
|
|
363
|
+
// task 1723: collapse the shell nav to the signed-out minimum. Cosmetic —
|
|
364
|
+
// the server gates every page regardless.
|
|
384
365
|
window.OTBShell?.applyAccess({ authed: false });
|
|
366
|
+
markSignedOut();
|
|
385
367
|
|
|
386
368
|
const welcome = $('#welcome-line');
|
|
387
369
|
if (welcome) welcome.textContent = '';
|
|
@@ -390,20 +372,12 @@
|
|
|
390
372
|
if (landing) {
|
|
391
373
|
landing.hidden = false;
|
|
392
374
|
const mode = joinabilityMode();
|
|
393
|
-
// On the apply door the sign-in is a real button above, so the note keeps
|
|
394
|
-
// only the privacy sentence — one sign-in path per landing, never two.
|
|
395
|
-
const signInNote = mode === 'apply'
|
|
396
|
-
? ''
|
|
397
|
-
: `Already a member? <a href="${API}/auth/web/start">Sign in with GitHub</a>. `;
|
|
398
375
|
landing.innerHTML = `
|
|
399
|
-
<div class="
|
|
400
|
-
|
|
401
|
-
|
|
376
|
+
<div class="landing">
|
|
377
|
+
${landingLogoHtml()}
|
|
378
|
+
<h2 class="landing__title">${brandWorld()}</h2>
|
|
402
379
|
${returningDoorHtml(mode)}
|
|
403
|
-
|
|
404
|
-
<p class="landing__signin-note">
|
|
405
|
-
${signInNote}We store only your GitHub login, avatar, and the work you ship.
|
|
406
|
-
</p>
|
|
380
|
+
${landingDoorHtml(mode)}
|
|
407
381
|
</div>
|
|
408
382
|
`;
|
|
409
383
|
wireAccessRequestForm();
|
|
@@ -419,6 +393,7 @@
|
|
|
419
393
|
// deleted. Say so, and offer the way out: sign out, then sign in again.
|
|
420
394
|
function renderSessionRefused(code) {
|
|
421
395
|
window.OTBShell?.applyAccess({ authed: false });
|
|
396
|
+
markSignedOut();
|
|
422
397
|
const landing = $('#landing-root');
|
|
423
398
|
if (!landing) return;
|
|
424
399
|
landing.hidden = false;
|
|
@@ -427,11 +402,12 @@
|
|
|
427
402
|
? `This account has been switched off, so it cannot open the hall. If that is a mistake, ask the ${admitter} to switch it back on.`
|
|
428
403
|
: 'This sign-in is no longer accepted, so the hall cannot open with it.';
|
|
429
404
|
landing.innerHTML = `
|
|
430
|
-
<div class="
|
|
431
|
-
|
|
405
|
+
<div class="landing">
|
|
406
|
+
${landingLogoHtml()}
|
|
407
|
+
<h2 class="landing__title">You can't get in with this account</h2>
|
|
432
408
|
<p class="landing__request-lede">${why}</p>
|
|
433
409
|
<p class="landing__request-lede">Sign out, then sign in with the GitHub account you use now. A new account needs the ${admitter}'s approval first.</p>
|
|
434
|
-
<
|
|
410
|
+
<button type="button" class="landing__btn landing__btn--block" id="refused-signout">Sign out</button>
|
|
435
411
|
</div>
|
|
436
412
|
`;
|
|
437
413
|
$('#refused-signout')?.addEventListener('click', () => {
|
|
@@ -603,14 +579,6 @@
|
|
|
603
579
|
const el = document.getElementById(id);
|
|
604
580
|
if (el) el.textContent = text;
|
|
605
581
|
};
|
|
606
|
-
setText('stat-credits', fmtNum(builder.total_credits));
|
|
607
|
-
setText('stat-karma', fmtNum(karmaTotal));
|
|
608
|
-
setText('stat-karma-sub', karmaTrendText);
|
|
609
|
-
const statRank = document.getElementById('stat-rank');
|
|
610
|
-
if (statRank) statRank.innerHTML = builder.rank ? renderRankBadge(normalizeRank(builder.rank), { tip: false }) : '—';
|
|
611
|
-
setText('stat-rank-sub', rollPlace ? [`#${rollPlace.place} on the leaderboard`, rolePlaceText(rollPlace)].filter(Boolean).join(' · ') : '');
|
|
612
|
-
const statsSection = document.getElementById('home-stats');
|
|
613
|
-
if (statsSection && !ctx.newcomerGated) statsSection.hidden = false;
|
|
614
582
|
|
|
615
583
|
// task 1003464: the Home card as the mock draws it — an identity LINE and a
|
|
616
584
|
// three-row fact ledger. The mock repeats Credits and the place even though
|
|
@@ -635,7 +603,7 @@
|
|
|
635
603
|
<dl class="home-facts home-facts--grid">
|
|
636
604
|
<div><dt>${escapeHtml(curLabel(true))}</dt><dd>${fmtNum(builder.total_credits)}</dd></div>
|
|
637
605
|
<div><dt>Karma</dt><dd>${fmtNum(karmaTotal)}</dd></div>
|
|
638
|
-
<div><dt>Shipped</dt><dd id="standing-shipped">${
|
|
606
|
+
<div><dt>Shipped</dt><dd id="standing-shipped">${shipState.seen ? fmtNum(shipState.total) : '—'}</dd></div>
|
|
639
607
|
<div><dt>Leaderboard place</dt><dd>${place}</dd></div>
|
|
640
608
|
</dl>
|
|
641
609
|
<dl class="home-facts">
|
|
@@ -716,39 +684,15 @@
|
|
|
716
684
|
}
|
|
717
685
|
|
|
718
686
|
// task 1003464: the greeting IS Home's one h1 (the mock opens with it).
|
|
719
|
-
// task 1004780: it has no sub-line any more
|
|
720
|
-
//
|
|
721
|
-
// repeating both was redundant (owner, 2026-10-23).
|
|
687
|
+
// task 1004780: it has no sub-line any more (owner, 2026-10-23); since task
|
|
688
|
+
// 1005054 the city under it (home-city.js) is how far the project has come.
|
|
722
689
|
const greetingWord = (hour) => (hour < 12 ? 'Good morning' : (hour < 18 ? 'Good afternoon' : 'Good evening'));
|
|
723
|
-
// The version the tab is about: the one being built with the most work in it.
|
|
724
|
-
function currentVersion(progress) {
|
|
725
|
-
const rows = progress && Array.isArray(progress.progress) ? progress.progress : [];
|
|
726
|
-
return rows.filter((r) => r && r.status === 'building')
|
|
727
|
-
.sort((a, b) => (Number(b.total_count) || 0) - (Number(a.total_count) || 0))[0] || null;
|
|
728
|
-
}
|
|
729
|
-
// task 1004774: the version tab under the Home banner, drawn as a bar.
|
|
730
|
-
// Hidden while no version is being built.
|
|
731
|
-
function renderVersionTab(v) {
|
|
732
|
-
const tab = document.getElementById('home-version');
|
|
733
|
-
if (!tab) return;
|
|
734
|
-
if (!v) { tab.hidden = true; return; }
|
|
735
|
-
const pct = Math.max(0, Math.min(100, Math.round(Number(v.percent_complete) || 0)));
|
|
736
|
-
const name = document.getElementById('home-version-name');
|
|
737
|
-
const fill = document.getElementById('home-version-fill');
|
|
738
|
-
const pctEl = document.getElementById('home-version-pct');
|
|
739
|
-
if (name) name.textContent = v.version_id;
|
|
740
|
-
if (fill) fill.style.width = `${pct}%`;
|
|
741
|
-
if (pctEl) pctEl.textContent = `${pct}% complete`;
|
|
742
|
-
tab.setAttribute('aria-label', `${v.version_id} is ${pct} percent complete`);
|
|
743
|
-
tab.hidden = false;
|
|
744
|
-
}
|
|
745
690
|
function renderGreeting() {
|
|
746
691
|
const h1 = document.getElementById('hall-h1');
|
|
747
692
|
const builder = ctx.lastMeState && ctx.lastMeState.builder;
|
|
748
693
|
if (h1 && builder) {
|
|
749
694
|
h1.textContent = `${greetingWord(new Date().getHours())}, ${builder.display_name || builder.github_login || 'builder'}`;
|
|
750
695
|
}
|
|
751
|
-
renderVersionTab(currentVersion(ctx.lastProgressState));
|
|
752
696
|
}
|
|
753
697
|
const ONBOARDING_STAGE_ORDER = [
|
|
754
698
|
'auth_complete',
|
|
@@ -1096,28 +1040,9 @@
|
|
|
1096
1040
|
const countEl = $('#ships-count');
|
|
1097
1041
|
const pagerEl = $('#ships-pager');
|
|
1098
1042
|
|
|
1099
|
-
// task
|
|
1100
|
-
// 5-row recent-work table are fed from the same feed. Guarded writes.
|
|
1101
|
-
const statShipped = document.getElementById('stat-shipped');
|
|
1102
|
-
if (statShipped) statShipped.textContent = fmtNum(shipState.total);
|
|
1103
|
-
// task 1004774: the Standing hover card carries the same count.
|
|
1043
|
+
// task 1004774: the Standing hover card carries the shipped count.
|
|
1104
1044
|
const standingShipped = document.getElementById('standing-shipped');
|
|
1105
1045
|
if (standingShipped) standingShipped.textContent = fmtNum(shipState.total);
|
|
1106
|
-
const homeRecent = document.querySelector('#home-recent-table tbody');
|
|
1107
|
-
if (homeRecent) {
|
|
1108
|
-
const latest = sortShips(shipState.recent, 'recent').slice(0, HOME_SHIPS_LIMIT);
|
|
1109
|
-
homeRecent.innerHTML = latest.length
|
|
1110
|
-
? latest.map((s) => `
|
|
1111
|
-
<tr>
|
|
1112
|
-
<td class="ledger__num">#${s.id}</td>
|
|
1113
|
-
<td>${escapeHtml(s.title)}</td>
|
|
1114
|
-
<td class="ledger__drachmae">${fmtNum(window.OTBBranding?.taskCreditValue?.(s) ?? s.credits_reward)}</td>
|
|
1115
|
-
<td class="ledger__date">${fmtDate(s.shipped_at)}</td>
|
|
1116
|
-
</tr>`).join('')
|
|
1117
|
-
: emptyRow(4, 'Nothing shipped yet. Claim a task on the Work board to get started.');
|
|
1118
|
-
}
|
|
1119
|
-
const homeRecentSection = document.getElementById('home-recent');
|
|
1120
|
-
if (homeRecentSection && !ctx.newcomerGated) homeRecentSection.hidden = false;
|
|
1121
1046
|
|
|
1122
1047
|
// The ledger waits for its own fetch (loadShipLedger); until then it keeps its placeholder.
|
|
1123
1048
|
const all = shipState.all;
|
|
@@ -1378,31 +1303,7 @@
|
|
|
1378
1303
|
return `#${p.role.place} as ${ROLE_AS[p.role.craft]}`;
|
|
1379
1304
|
}
|
|
1380
1305
|
|
|
1381
|
-
// task 1003459 — the Claim button on each Home "Next up" row, through the
|
|
1382
|
-
// hall's ONE claim action (task 1003458) rather than a third hand-rolled
|
|
1383
|
-
// POST /claims. Lives here, not builders.js, because that file is at the
|
|
1384
|
-
// 1,500-line ratchet (hall-ui/CLAUDE.md: "growth in the page half has to be
|
|
1385
|
-
// paid for; new pure helper → the lib/renderer"). refresh re-fetches the
|
|
1386
|
-
// two-row slice so a claimed task drops out of it immediately.
|
|
1387
|
-
function wireNextUpClaim() {
|
|
1388
|
-
const claimAction = window.OTBClaimAction.makeClaimAction({ postJSON, toast, API, refresh: loadNextUp });
|
|
1389
|
-
$('#home-next-list')?.addEventListener('click', (e) => {
|
|
1390
|
-
const btn = e.target.closest('.next-up__claim');
|
|
1391
|
-
if (!btn || btn.disabled) return;
|
|
1392
|
-
const taskId = btn.dataset.taskId;
|
|
1393
|
-
btn.disabled = true;
|
|
1394
|
-
btn.textContent = '…';
|
|
1395
|
-
claimAction.claim(taskId).then((out) => {
|
|
1396
|
-
// A redirect to sign-in is already navigating away; re-enabling here
|
|
1397
|
-
// would just invite a click that can't land.
|
|
1398
|
-
if (!out.ok && !out.redirected) {
|
|
1399
|
-
btn.disabled = false;
|
|
1400
|
-
btn.textContent = 'Claim';
|
|
1401
|
-
}
|
|
1402
|
-
});
|
|
1403
|
-
});
|
|
1404
|
-
}
|
|
1405
1306
|
|
|
1406
|
-
return { acclaimEvidenceHtml, analyticsState, lbState, mountHallWidgets, renderCurveBody, renderGreeting, renderLanding, renderSessionRefused, renderNav, renderOnboarding, renderProfile, renderRecentShips, renderWelcomeCore, HOME_SHIPS_LIMIT, loadShipLedger, populateShipVersionFilter, setRecentShips, shipState, shipsPager, welcomeDismissalKey
|
|
1307
|
+
return { acclaimEvidenceHtml, analyticsState, lbState, mountHallWidgets, renderCurveBody, renderGreeting, renderLanding, renderSessionRefused, renderNav, renderOnboarding, renderProfile, renderRecentShips, renderWelcomeCore, HOME_SHIPS_LIMIT, loadShipLedger, populateShipVersionFilter, setRecentShips, shipState, shipsPager, welcomeDismissalKey };
|
|
1407
1308
|
};
|
|
1408
1309
|
})();
|
|
@@ -62,29 +62,8 @@
|
|
|
62
62
|
'<p class="ledger__note" id="onboarding-status" hidden></p>',
|
|
63
63
|
{ view: 'home', zone: 'home-banner', labelledby: 'onboarding-h', hiddenByDefault: true });
|
|
64
64
|
|
|
65
|
-
//
|
|
66
|
-
//
|
|
67
|
-
// shipped count once the ships feed settles (renderRecentShips).
|
|
68
|
-
// task 2169: each tile is a LINK — the stat row doubles as the fastest
|
|
69
|
-
// navigation on the page (Credits → the economy doc, Shipped/Karma → the
|
|
70
|
-
// Standing sections that explain them, Rank → the ladder).
|
|
71
|
-
w('home-stats', 'Overview', 15,
|
|
72
|
-
'<h2 id="home-stats-h" class="sr-only">Overview</h2>' +
|
|
73
|
-
'<div class="stat-row" id="home-stats-row">' +
|
|
74
|
-
'<a class="stat-tile" href="/drachmae"><span class="stat-tile__label" data-currency-label="caps">Credits</span><span class="stat-tile__num" id="stat-credits">—</span></a>' +
|
|
75
|
-
'<a class="stat-tile" href="#accomplishments-work"><span class="stat-tile__label">Shipped</span><span class="stat-tile__num" id="stat-shipped">—</span><span class="stat-tile__sub" id="stat-shipped-sub"></span></a>' +
|
|
76
|
-
'<a class="stat-tile" href="#accomplishments-karma"><span class="stat-tile__label">Karma</span><span class="stat-tile__num" id="stat-karma">—</span><span class="stat-tile__sub" id="stat-karma-sub"></span></a>' +
|
|
77
|
-
'<a class="stat-tile" href="/ranks"><span class="stat-tile__label">Rank</span><span class="stat-tile__num stat-tile__num--badge" id="stat-rank">—</span><span class="stat-tile__sub" id="stat-rank-sub"></span></a>' +
|
|
78
|
-
'</div>' +
|
|
79
|
-
// task 1004774: the version tab under the banner — how far the version being
|
|
80
|
-
// built has come. hall-render.js renderGreeting fills it from the same
|
|
81
|
-
// progress read as the greeting's sub-line; hidden until there is a version.
|
|
82
|
-
'<a class="version-tab" id="home-version" href="/roadmap" hidden>' +
|
|
83
|
-
'<span class="version-tab__name" id="home-version-name"></span>' +
|
|
84
|
-
'<span class="version-tab__bar" aria-hidden="true"><span class="version-tab__fill" id="home-version-fill"></span></span>' +
|
|
85
|
-
'<span class="version-tab__pct" id="home-version-pct"></span>' +
|
|
86
|
-
'</a>',
|
|
87
|
-
{ view: 'home', zone: 'home-stats', sectionClass: 'scroll scroll--bare', labelledby: 'home-stats-h', hiddenByDefault: true });
|
|
65
|
+
// (task 1005054: the quick-stats strip and the version tab left Home. The
|
|
66
|
+
// zone they held, home-stats, is the project city's — home-city.js.)
|
|
88
67
|
|
|
89
68
|
// (task 1004774: the Standing summary is no longer a Home card. It is the
|
|
90
69
|
// chip at the top right of the page head — index.html #hall-standing — whose
|
|
@@ -97,28 +76,8 @@
|
|
|
97
76
|
// goal-inbox.js owns (#attention-ideas), the single landing place for every
|
|
98
77
|
// actionable item. builders.js still gates the /inbox fetch to Metic+.)
|
|
99
78
|
|
|
100
|
-
//
|
|
101
|
-
//
|
|
102
|
-
// claimable queue (builders.js loadNextUp fills it; hidden when the feed is
|
|
103
|
-
// gated or empty), then the 5-row recent-ships table below it.
|
|
104
|
-
w('home-recent', 'Your work', 28,
|
|
105
|
-
'<h2 id="home-recent-h" class="scroll__h">Your work</h2>' +
|
|
106
|
-
// task 1004774: Next up and Recently shipped sit side by side (stacking
|
|
107
|
-
// again on a phone); when Next up is hidden, shipped takes the full width.
|
|
108
|
-
'<div class="home-split">' +
|
|
109
|
-
'<div class="home-split__col" id="home-next" hidden>' +
|
|
110
|
-
'<h3 class="ginbox__sec-h">Next up — ready to claim</h3>' +
|
|
111
|
-
'<ul class="next-up" id="home-next-list"></ul>' +
|
|
112
|
-
'<p class="next-up__foot"><a href="/work" id="home-next-foot">See all ready work →</a></p>' +
|
|
113
|
-
'</div>' +
|
|
114
|
-
'<div class="home-split__col">' +
|
|
115
|
-
'<h3 class="ginbox__sec-h" id="home-recent-subh" hidden>Recently shipped</h3>' +
|
|
116
|
-
'<table class="ledger" id="home-recent-table"><thead><tr><th>№</th><th>Work</th><th data-currency-label="caps">Credits</th><th>Shipped</th></tr></thead>' +
|
|
117
|
-
'<tbody><tr><td colspan="4" class="ledger__empty"><span class="hall-loading" role="status">Loading…</span></td></tr></tbody></table>' +
|
|
118
|
-
'<p class="card-foot"><a href="#accomplishments-work">All your work →</a></p>' +
|
|
119
|
-
'</div>' +
|
|
120
|
-
'</div>',
|
|
121
|
-
{ view: 'home', zone: 'home-main', labelledby: 'home-recent-h', hiddenByDefault: true });
|
|
79
|
+
// (task 1005054: Your work — Next up and Recently shipped — left Home; ready
|
|
80
|
+
// work is the Work board's and your history is Accomplishments'.)
|
|
122
81
|
|
|
123
82
|
// 0f. The founding wall (task 1004424) — everyone who joined while the project was
|
|
124
83
|
// being founded, founder first, each with their mark. Hidden until the founding
|