@bongos/core 1.19.440 → 1.19.442
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 +71 -31
- package/clients/bongos-client/index.d.ts +1 -2
- package/docs/api/openapi.json +3 -20
- package/docs/api-reference.md +1 -1
- package/docs/copy-inventory.md +180 -173
- package/docs/copy-registry.json +300 -226
- package/docs/design/mocks/hub/mine.html +89 -1
- package/docs/design/projects-hub-direction-v2.md +59 -0
- package/docs/module-api-changelog.md +4 -0
- package/modules/platform-identity/routes/projects.js +2 -1
- package/modules/provisioning/provisioning.js +11 -2
- package/modules/provisioning/routes/provisioning.js +10 -5
- package/modules/ui-design/kit/fixtures/featured-hub.json +1 -1
- package/modules/ui-design/kit/serve.js +29 -4
- package/package-lock.json +2 -2
- package/package.json +1 -1
- package/public-landing/assets/cosmos.css +89 -65
- package/public-landing/assets/world/r4-card-chrome.jpg +0 -0
- package/public-landing/assets/world/r4-card-chrome.jpg.json +14 -0
- package/public-landing/assets/world/r4-card-deepfield.jpg +0 -0
- package/public-landing/assets/world/r4-card-deepfield.jpg.json +14 -0
- package/public-landing/assets/world/r4-card-dust.jpg +0 -0
- package/public-landing/assets/world/r4-card-dust.jpg.json +14 -0
- package/public-landing/assets/world/r4-card-nebula.jpg +0 -0
- package/public-landing/assets/world/r4-card-nebula.jpg.json +14 -0
- package/public-landing/projects-floor.states.json +28 -1
- package/public-landing/projects.html +201 -69
- package/public-landing/projects.probes.json +16 -2
- package/public-landing/projects.states.json +3 -1
- package/src/module-api.js +1 -1
- package/tests/projects_hub.mjs +173 -65
- package/tests/projects_hub_pre_uat.mjs +11 -9
- package/tests/provisioning_settings.mjs +49 -4
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"kind": "card-band",
|
|
3
|
+
"model": "soul_location (Higgsfield) — nano_banana_pro was asked first; its queue had not started a job after 25 minutes, so the round moved to the model that answered",
|
|
4
|
+
"job_id": "a9e4cb59-7436-4f8f-9289-aba9b1fd567e",
|
|
5
|
+
"aspect_ratio": "5:2",
|
|
6
|
+
"source_aspect_ratio": "21:9",
|
|
7
|
+
"generated": "2026-08-30T17:09Z",
|
|
8
|
+
"round": 4,
|
|
9
|
+
"task": 1003352,
|
|
10
|
+
"prompt": "Ultra-wide studio photograph on a pure black ground: a single sweeping ribbon of liquid chrome, polished mirror metal with soft neutral specular highlights and a faint cool blue and warm bronze reflection, curving gently through the centre-right of the frame and fading into black at both ends. Abstract material study, not an object, no recognisable shape, no product. The left third and both lower corners stay almost pure black and empty. No text, no watermark, no logo, no border, no reflection of a studio or a person. Pure black dominates the frame.",
|
|
11
|
+
"source": ".impeccable/mocks/world-assets/r4-card-chrome-src.jpg",
|
|
12
|
+
"encoded": "ffmpeg crop=2560:1024:0:24 (21:9 → 5:2, centred), JPEG -q:v 4",
|
|
13
|
+
"use": "the poster card's backdrop on /projects, chosen by an owner as card_backdrop=\"chrome\": a sweeping ribbon of liquid chrome — the world's own material with no object in it. Dark only (ADR 0204); composed so the left third and the lower corners stay near-black, where the card puts its disc, its name and its two figure callouts."
|
|
14
|
+
}
|
|
Binary file
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"kind": "card-band",
|
|
3
|
+
"model": "soul_location (Higgsfield) — nano_banana_pro was asked first; its queue had not started a job after 25 minutes, so the round moved to the model that answered",
|
|
4
|
+
"job_id": "debaaba3-6094-4670-9b08-c578fc6e8bb9",
|
|
5
|
+
"aspect_ratio": "5:2",
|
|
6
|
+
"source_aspect_ratio": "21:9",
|
|
7
|
+
"generated": "2026-08-30T17:09Z",
|
|
8
|
+
"round": 4,
|
|
9
|
+
"task": 1003352,
|
|
10
|
+
"prompt": "Ultra-wide deep-field astronomical photograph on a pure black ground: many very small, very distant galaxies and faint stars scattered sparsely across an almost entirely black frame, a few with the faintest cool blue or warm amber tint, no bright object anywhere, extremely quiet and even. No planets, no moons, no large nebula, no ground plane, no horizon, no lens flare, no text, no watermark, no logo, no border. Pure black dominates the frame.",
|
|
11
|
+
"source": ".impeccable/mocks/world-assets/r4-card-deepfield-src.jpg",
|
|
12
|
+
"encoded": "ffmpeg crop=2560:1024:0:24 (21:9 → 5:2, centred), JPEG -q:v 4",
|
|
13
|
+
"use": "the poster card's backdrop on /projects, chosen by an owner as card_backdrop=\"deepfield\": a deep field of very distant galaxies on near-black; the quietest of the four. Dark only (ADR 0204); composed so the left third and the lower corners stay near-black, where the card puts its disc, its name and its two figure callouts."
|
|
14
|
+
}
|
|
Binary file
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"kind": "card-band",
|
|
3
|
+
"model": "soul_location (Higgsfield) — nano_banana_pro was asked first; its queue had not started a job after 25 minutes, so the round moved to the model that answered",
|
|
4
|
+
"job_id": "7ec35328-3943-4765-8dd7-8392fb8c48c3",
|
|
5
|
+
"aspect_ratio": "5:2",
|
|
6
|
+
"source_aspect_ratio": "21:9",
|
|
7
|
+
"generated": "2026-08-30T17:09Z",
|
|
8
|
+
"round": 4,
|
|
9
|
+
"task": 1003352,
|
|
10
|
+
"prompt": "Ultra-wide cinematic deep-space photograph on a pure black ground: soft interstellar dust lanes in warm bronze and dark amber sweeping diagonally across the centre-right, very low contrast, a haze rather than a shape, a scatter of tiny faint stars. The left third and both lower corners stay almost pure black and empty. No planets, no moons, no nebula pillars, no ground plane, no horizon, no lens flare, no text, no watermark, no logo, no border. Pure black dominates the frame.",
|
|
11
|
+
"source": ".impeccable/mocks/world-assets/r4-card-dust-src.jpg",
|
|
12
|
+
"encoded": "ffmpeg crop=2560:1024:0:24 (21:9 → 5:2, centred), eq=gamma=1.20, JPEG -q:v 4",
|
|
13
|
+
"use": "the poster card's backdrop on /projects, chosen by an owner as card_backdrop=\"dust\": warm bronze dust lanes, very low contrast; a haze rather than a shape. Dark only (ADR 0204); composed so the left third and the lower corners stay near-black, where the card puts its disc, its name and its two figure callouts."
|
|
14
|
+
}
|
|
Binary file
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"kind": "card-band",
|
|
3
|
+
"model": "soul_location (Higgsfield) — nano_banana_pro was asked first; its queue had not started a job after 25 minutes, so the round moved to the model that answered",
|
|
4
|
+
"job_id": "35ad2c18-aaa3-413c-9fd8-958e5017d77c",
|
|
5
|
+
"aspect_ratio": "5:2",
|
|
6
|
+
"source_aspect_ratio": "21:9",
|
|
7
|
+
"generated": "2026-08-30T17:09Z",
|
|
8
|
+
"round": 4,
|
|
9
|
+
"task": 1003352,
|
|
10
|
+
"prompt": "Ultra-wide cinematic deep-space photograph on a pure black ground: a faint nebula wash in muted violet and deep blue with a soft bronze warmth drifting through the centre-right of the frame, very sparse pin-sharp stars of varied brightness, gentle depth. The left third and both lower corners stay almost pure black and empty. No planets, no moons, no ground plane, no horizon, no lens flare, no text, no watermark, no logo, no border. Pure black dominates the frame.",
|
|
11
|
+
"source": ".impeccable/mocks/world-assets/r4-card-nebula-src.jpg",
|
|
12
|
+
"encoded": "ffmpeg crop=2560:1024:0:24 (21:9 → 5:2, centred), eq=gamma=1.75:saturation=1.30, JPEG -q:v 4 — the render was too dark to read at the card's 560px; a gamma lift raises the wash without crushing the black the disc and the name sit on (contrast would have)",
|
|
13
|
+
"use": "the poster card's backdrop on /projects, chosen by an owner as card_backdrop=\"nebula\": a violet-and-bronze nebula wash, sparse stars — the field's own language in the card's shape. Dark only (ADR 0204); composed so the left third and the lower corners stay near-black, where the card puts its disc, its name and its two figure callouts."
|
|
14
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"_": "The all-null floor card (task 1003301) on the hub's own catalog (task 1003345): the same page, the same stub, the catalog aliased to featured-hub.json — the landing's three plus Tidewater, a null row nobody owns. Demo, the landing catalog's floor row, is owned by the signed-in stub, and an owned orb's plain click opens its manage view, never its card. Rendered by name: node modules/ui-design/kit/render.js --states public-landing/projects-floor.states.json",
|
|
2
|
+
"_": "The all-null floor card (task 1003301) on the hub's own catalog (task 1003345): the same page, the same stub, the catalog aliased to featured-hub.json — the landing's three plus Tidewater, a null row nobody owns. Demo, the landing catalog's floor row, is owned by the signed-in stub, and an owned orb's plain click opens its manage view, never its card. Since task 1003352 it also carries the card BACKDROP state: featured-hub gives Off the Boats a card_backdrop, so the owner's plate can be seen standing in front of the project's own picture. Rendered by name: node modules/ui-design/kit/render.js --states public-landing/projects-floor.states.json",
|
|
3
3
|
"page": "/projects",
|
|
4
4
|
"surface": "public-landing",
|
|
5
5
|
"modes": [
|
|
@@ -58,6 +58,33 @@
|
|
|
58
58
|
"#cardListed"
|
|
59
59
|
]
|
|
60
60
|
}
|
|
61
|
+
},
|
|
62
|
+
"card-backdrop": {
|
|
63
|
+
"auth": true,
|
|
64
|
+
"actions": [
|
|
65
|
+
[
|
|
66
|
+
"dispatchClick",
|
|
67
|
+
"#orbField a.worldOrb[data-origin=\"https://amazonprimea.com\"]"
|
|
68
|
+
],
|
|
69
|
+
[
|
|
70
|
+
"wait",
|
|
71
|
+
600
|
|
72
|
+
]
|
|
73
|
+
],
|
|
74
|
+
"expect": {
|
|
75
|
+
"dialog": true,
|
|
76
|
+
"visible": [
|
|
77
|
+
"#cardArt",
|
|
78
|
+
"#cardOpen"
|
|
79
|
+
],
|
|
80
|
+
"attr": [
|
|
81
|
+
[
|
|
82
|
+
"#cardArt",
|
|
83
|
+
"src",
|
|
84
|
+
"/assets/world/r4-card-nebula.jpg"
|
|
85
|
+
]
|
|
86
|
+
]
|
|
87
|
+
}
|
|
61
88
|
}
|
|
62
89
|
}
|
|
63
90
|
}
|
|
@@ -492,37 +492,32 @@ summary{min-height:24px;padding:3px 0;}
|
|
|
492
492
|
<h2 class="tblTitle">every project</h2>
|
|
493
493
|
<span class="mastObj" aria-hidden="true"></span>
|
|
494
494
|
</div>
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
<
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
</tr>
|
|
522
|
-
<!--apex-only:end-->
|
|
523
|
-
</tbody>
|
|
524
|
-
</table>
|
|
525
|
-
<p class="finePrint" style="text-align:center">Sort by Project or Builders.</p>
|
|
495
|
+
<!-- The sort left the column head with the header row (task 1003356): a
|
|
496
|
+
ledger row has no columns to head, so the two orders are hairline
|
|
497
|
+
pills in the mine view's own grammar — real buttons, aria-pressed, the
|
|
498
|
+
live order stated under the list where a screen reader hears it. -->
|
|
499
|
+
<div class="tblSort" role="group" aria-label="Sort the projects">
|
|
500
|
+
<span class="sortLbl">sort</span>
|
|
501
|
+
<button type="button" class="sortPill" data-sort="name" aria-pressed="true">name <span class="dir">a to z</span></button>
|
|
502
|
+
<button type="button" class="sortPill" data-sort="builders" aria-pressed="false">builders</button>
|
|
503
|
+
</div>
|
|
504
|
+
<ul class="tbl" id="mapRows">
|
|
505
|
+
<!-- The platform's own row. Static and apex-only for exactly the reason
|
|
506
|
+
the orb above is (stripApexOnly() is a string transform that cannot
|
|
507
|
+
reach anything a script renders later), and preserved across
|
|
508
|
+
re-renders by the same data-generated contract renderOrbs uses. -->
|
|
509
|
+
<!--apex-only:start-->
|
|
510
|
+
<li class="tblRow" id="selfRow">
|
|
511
|
+
<span class="worldOrb" data-shape="pair" data-style="chrome" data-template="pair-chrome" style="--acc:var(--accent);--d:64px" aria-hidden="true"><span class="disc"></span></span>
|
|
512
|
+
<div class="tWho"><span class="ptitle" data-brand-product-inline>Cloud Bongos</span><span id="selfPill"></span><span class="chip calm"><span class="cdot"></span>not checked</span></div>
|
|
513
|
+
<div class="facts"><span class="fact" id="selfBuilders">builders not known</span><span class="fact" id="selfShipped" hidden></span></div>
|
|
514
|
+
<p class="ptag">this platform</p>
|
|
515
|
+
<div class="runs"><span class="rLbl">runs</span><span id="selfTags">—</span></div>
|
|
516
|
+
<div class="rowDoors"><a class="rowGo" href="/">view</a><a class="rowHall" id="selfHall" href="{{buildersOrigin}}" aria-label="Builders' hall" title="Builders' hall" hidden><svg viewBox="0 0 20 20" aria-hidden="true"><path d="M2.8 7.4 10 3.5l7.2 3.9"/><path d="M5.2 8.8v5.6M10 8.8v5.6M14.8 8.8v5.6"/><path d="M3.4 16.3h13.2"/></svg></a></div>
|
|
517
|
+
</li>
|
|
518
|
+
<!--apex-only:end-->
|
|
519
|
+
</ul>
|
|
520
|
+
<p class="finePrint" id="mapSorted" role="status" aria-live="polite">Sorted by name, A to Z.</p>
|
|
526
521
|
</div>
|
|
527
522
|
|
|
528
523
|
<!-- The project card. An OVERLAY inside the map, not a fourth view: opening
|
|
@@ -774,6 +769,18 @@ summary{min-height:24px;padding:3px 0;}
|
|
|
774
769
|
</details>
|
|
775
770
|
</div>
|
|
776
771
|
|
|
772
|
+
<!-- its card (task 1003352): the poster card's backdrop, a plate the
|
|
773
|
+
platform drew. Beside the planet, on the same settings channel, and
|
|
774
|
+
like it: nothing is pushed to the project and nothing restarts. -->
|
|
775
|
+
<div class="card mSec" id="mCard">
|
|
776
|
+
<h2>Its card</h2>
|
|
777
|
+
<div id="mCardPick"><p class="finePrint">Reading the project…</p></div>
|
|
778
|
+
<details class="finePrint" id="mCardWhat">
|
|
779
|
+
<summary>What the choice changes</summary>
|
|
780
|
+
<p>The backdrop behind this project’s name on its card — the panel that opens when someone picks it out of the map. Four plates the platform drew, or the project’s own picture if you have given it one. Saving here changes nothing on the project itself: no restart, nothing to apply.</p>
|
|
781
|
+
</details>
|
|
782
|
+
</div>
|
|
783
|
+
|
|
777
784
|
<!-- live since task 1003042: the teardown control, for a project in ANY
|
|
778
785
|
state that still holds something. The server used to refuse a
|
|
779
786
|
'requested' or an 'error' project outright — and force-teardown reused
|
|
@@ -1471,7 +1478,9 @@ summary{min-height:24px;padding:3px 0;}
|
|
|
1471
1478
|
}
|
|
1472
1479
|
function typeHtml(t) {
|
|
1473
1480
|
var l = typeLabel(t);
|
|
1474
|
-
|
|
1481
|
+
/* a ledger row's fact is a self-describing line, so "not declared" is said
|
|
1482
|
+
in words where the table's Type cell used to print a dash (task 1003356) */
|
|
1483
|
+
return l ? '<span class="typeTag">' + l + '</span>' : 'type not declared';
|
|
1475
1484
|
}
|
|
1476
1485
|
function matchesMapQuery(p, q) {
|
|
1477
1486
|
if (!q) return true;
|
|
@@ -1545,44 +1554,63 @@ summary{min-height:24px;padding:3px 0;}
|
|
|
1545
1554
|
});
|
|
1546
1555
|
}
|
|
1547
1556
|
|
|
1557
|
+
/* ── the row's facts, the ledger grammar (task 1003356) ──
|
|
1558
|
+
Each fact is one self-describing label-face line, the shape the Your-projects
|
|
1559
|
+
row uses, so the two views read as one ledger. The distinction the columns
|
|
1560
|
+
drew survives the move: "we could not ask" (null) and "we asked, the answer
|
|
1561
|
+
is none" (0) are two different sentences, not a dash and a zero. A figure
|
|
1562
|
+
that was never a column — shipped in 30 days, the Listed date — takes no
|
|
1563
|
+
space when it has no answer, the poster card's own rule. */
|
|
1564
|
+
function factLines(p) {
|
|
1565
|
+
var out = ['<span class="fact">' + typeHtml(p.type) + '</span>'];
|
|
1566
|
+
out.push('<span class="fact">' + (p.builders == null ? 'builders not known'
|
|
1567
|
+
: esc(String(p.builders)) + (p.builders === 1 ? ' builder' : ' builders')) + '</span>');
|
|
1568
|
+
var shipped = shippedFigure(p);
|
|
1569
|
+
if (shipped) out.push('<span class="fact">' + esc(shipped) + ' shipped in 30 days</span>');
|
|
1570
|
+
if (p.created_at) out.push('<span class="fact">listed ' + esc(listedDate(p.created_at)) + '</span>');
|
|
1571
|
+
return out.join('');
|
|
1572
|
+
}
|
|
1573
|
+
|
|
1548
1574
|
function renderRows(list) {
|
|
1549
1575
|
var body = $('mapRows');
|
|
1550
1576
|
/* replace only the generated rows — the platform's own row is static
|
|
1551
1577
|
apex-only markup and must survive every re-render, for the same reason
|
|
1552
1578
|
#selfOrb does in the sky. It stays pinned first: it is "this platform",
|
|
1553
1579
|
not a peer in the catalog's sort order. */
|
|
1554
|
-
body.querySelectorAll('
|
|
1580
|
+
body.querySelectorAll('li[data-generated]').forEach(function (n) { n.remove(); });
|
|
1555
1581
|
body.insertAdjacentHTML('beforeend', list.map(function (p) {
|
|
1556
1582
|
var rel = relOf(p);
|
|
1557
|
-
var pill = rel === 'owner' ? '
|
|
1558
|
-
: rel === 'builder' ? '
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1583
|
+
var pill = rel === 'owner' ? '<span class="pill">yours</span>'
|
|
1584
|
+
: rel === 'builder' ? '<span class="pill">you build here</span>' : '';
|
|
1585
|
+
/* the project's own planet, the object the sky and the Your-projects row
|
|
1586
|
+
already draw — the owner's chosen template and colour first (task
|
|
1587
|
+
1003347), the slug walk otherwise. Decorative here: the name beside it
|
|
1588
|
+
is the row's accessible door. */
|
|
1589
|
+
var planet = '<span class="worldOrb"' + planetAttrs({ tpl: templateOf(p) }) +
|
|
1590
|
+
' style="--acc:' + accentOf(p) + ';--d:64px" aria-hidden="true"><span class="disc"></span></span>';
|
|
1591
|
+
return '<li class="tblRow" data-generated ' + (p._inst ? 'data-manage="' + esc(String(p._inst.id)) + '" ' : '') +
|
|
1592
|
+
'data-origin="' + esc(String(p.origin || '')) + '">' + planet +
|
|
1593
|
+
'<div class="tWho">' + (p._inst
|
|
1564
1594
|
? '<a class="ptitle" data-manage="' + esc(String(p._inst.id)) + '" href="?view=manage&id=' + esc(String(p._inst.id)) + '">' + esc(p.name) + '</a>'
|
|
1565
|
-
: '<span class="ptitle">' + esc(p.name) + '</span>') + pill +
|
|
1566
|
-
'<span class="ptag">' + esc(p.tagline || '') + '</span></span></span></td>' +
|
|
1567
|
-
/* Builders and Runs come from the project's OWN public API, enriched
|
|
1568
|
-
server-side (task 1002771). null is unknown — the project was
|
|
1569
|
-
unreachable — and an em dash says exactly that. 0 is a real answer and
|
|
1570
|
-
renders as 0, because "nobody has joined yet" is a different fact from
|
|
1571
|
-
"we could not ask". */
|
|
1572
|
-
'<td class="colType">' + typeHtml(p.type) + '</td>' +
|
|
1573
|
-
'<td class="right num">' + (p.builders == null ? '—' : esc(String(p.builders))) + '</td>' +
|
|
1574
|
-
'<td class="colTags">' + tagsHtml(p.tags) + '</td>' +
|
|
1595
|
+
: '<span class="ptitle">' + esc(p.name) + '</span>') + pill +
|
|
1575
1596
|
/* liveness on a CATALOG row is NOT probed by this surface — a chip
|
|
1576
1597
|
saying "live" there would claim more than anything verified (C6).
|
|
1577
1598
|
An OWNED row is different: the own-scoped feed answers for it, so
|
|
1578
1599
|
it carries chipFor()'s truth, the same chip its orb and its manage
|
|
1579
1600
|
card show (task 1002744). */
|
|
1580
|
-
|
|
1581
|
-
: '<span class="chip calm"><span class="cdot"></span
|
|
1582
|
-
'<
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1601
|
+
(p._inst ? chipFor(p._inst)
|
|
1602
|
+
: '<span class="chip calm"><span class="cdot"></span>not checked</span>') + '</div>' +
|
|
1603
|
+
'<div class="facts">' + factLines(p) + '</div>' +
|
|
1604
|
+
'<p class="ptag">' + esc(p.tagline || '') + '</p>' +
|
|
1605
|
+
/* Runs stays the module list here, where the poster card's Runs is the
|
|
1606
|
+
address (direction §7): null is "we could not ask", [] is "core" */
|
|
1607
|
+
'<div class="runs"><span class="rLbl">runs</span>' + tagsHtml(p.tags) + '</div>' +
|
|
1608
|
+
/* at most two doors (task 1003356): the site, and the hall where the
|
|
1609
|
+
viewer builds there and the hall answers at a different address */
|
|
1610
|
+
'<div class="rowDoors">' + (safeHttpUrl(p.origin)
|
|
1611
|
+
? '<a class="rowGo" href="' + esc(safeHttpUrl(p.origin)) + '" target="_blank" rel="noopener">view</a>'
|
|
1612
|
+
: '') + hallGlyphHtml(p, rel) + '</div>' +
|
|
1613
|
+
'</li>';
|
|
1586
1614
|
}).join(''));
|
|
1587
1615
|
}
|
|
1588
1616
|
|
|
@@ -1665,7 +1693,7 @@ summary{min-height:24px;padding:3px 0;}
|
|
|
1665
1693
|
}
|
|
1666
1694
|
if (row) {
|
|
1667
1695
|
row.hidden = !selfShown;
|
|
1668
|
-
$('selfPill').innerHTML = badge ? '
|
|
1696
|
+
$('selfPill').innerHTML = badge ? '<span class="pill">' + badge + '</span>' : '';
|
|
1669
1697
|
/* the hall glyph: member-gated (the badge says so) and address-gated */
|
|
1670
1698
|
var sh = $('selfHall');
|
|
1671
1699
|
if (sh) sh.hidden = !badge || !hallUrlOf(SELF_PROJECT);
|
|
@@ -1804,7 +1832,7 @@ summary{min-height:24px;padding:3px 0;}
|
|
|
1804
1832
|
var href = p.isSelf ? '/' : safeHttpUrl(p.origin);
|
|
1805
1833
|
/* the art: catalog text an Archon typed, scheme-checked server-side and
|
|
1806
1834
|
again here before it becomes a src */
|
|
1807
|
-
cardArt(p.isSelf ? '' : safeHttpUrl(p.art_url));
|
|
1835
|
+
cardArt(p.isSelf ? '' : (backdropPlate(p.card_backdrop) || safeHttpUrl(p.art_url)));
|
|
1808
1836
|
$('cardDot').style.setProperty('--acc', p.isSelf ? 'var(--accent)' : accentOf(p));
|
|
1809
1837
|
$('cardName').textContent = p.name || '';
|
|
1810
1838
|
$('cardTag').textContent = p.tagline || '';
|
|
@@ -1911,7 +1939,7 @@ summary{min-height:24px;padding:3px 0;}
|
|
|
1911
1939
|
}
|
|
1912
1940
|
/* the row's own "Open →" keeps its job — the card is for the rest of the row */
|
|
1913
1941
|
if (ev.target.closest && ev.target.closest('a')) return;
|
|
1914
|
-
var tr = ev.target.closest && ev.target.closest('
|
|
1942
|
+
var tr = ev.target.closest && ev.target.closest('li');
|
|
1915
1943
|
if (!tr || !isPlainClick(ev)) return;
|
|
1916
1944
|
if (tr.id === 'selfRow') return openCard(SELF_PROJECT, selfRel(), null);
|
|
1917
1945
|
/* an owned row goes to MANAGE, exactly like its orb — two views, one job */
|
|
@@ -2030,7 +2058,7 @@ summary{min-height:24px;padding:3px 0;}
|
|
|
2030
2058
|
var rows = (d && d.leaderboard) || [];
|
|
2031
2059
|
if (!rows.length) return;
|
|
2032
2060
|
var real = rows.filter(function (b) { return !/-system$/.test(String(b.github_login || '')); });
|
|
2033
|
-
$('selfBuilders').textContent =
|
|
2061
|
+
$('selfBuilders').textContent = real.length === 1 ? '1 builder' : real.length + ' builders';
|
|
2034
2062
|
/* the card reads these too: the same payload answers the platform's
|
|
2035
2063
|
builder count and its owner — the archon row — by the same rule the
|
|
2036
2064
|
server-side enrichment applies to every other project */
|
|
@@ -2056,6 +2084,10 @@ summary{min-height:24px;padding:3px 0;}
|
|
|
2056
2084
|
var n = d.tasks.filter(function (t) { return Date.parse(t && t.shipped_at) >= since; }).length;
|
|
2057
2085
|
SELF_PROJECT.shipped_30d = n;
|
|
2058
2086
|
SELF_PROJECT.shipped_30d_capped = d.tasks.length >= 200 && n === d.tasks.length;
|
|
2087
|
+
/* the row's own fact, by the same rule every other row's is written */
|
|
2088
|
+
var sf = $('selfShipped');
|
|
2089
|
+
sf.textContent = shippedFigure(SELF_PROJECT) + ' shipped in 30 days';
|
|
2090
|
+
sf.hidden = false;
|
|
2059
2091
|
})
|
|
2060
2092
|
.catch(function () { /* unknown stays unknown: the figure hides */ });
|
|
2061
2093
|
}
|
|
@@ -2113,21 +2145,33 @@ summary{min-height:24px;padding:3px 0;}
|
|
|
2113
2145
|
|
|
2114
2146
|
$('onlyMine').addEventListener('change', applyMapFilter);
|
|
2115
2147
|
$('mapQ').addEventListener('input', applyMapFilter);
|
|
2116
|
-
/* the sort
|
|
2117
|
-
|
|
2118
|
-
|
|
2119
|
-
|
|
2120
|
-
|
|
2121
|
-
|
|
2148
|
+
/* ── the sort, off the column head (task 1003356) ──
|
|
2149
|
+
A ledger row has no columns to head, so aria-sort has no host: the two
|
|
2150
|
+
orders are toggle buttons in a group, pressed = the live order, and the
|
|
2151
|
+
sentence under the list states it for a screen reader that never saw the
|
|
2152
|
+
press. Pressing the pressed one reverses, exactly as the header did. */
|
|
2153
|
+
var SORT_WORDS = { name: ['a to z', 'z to a'], builders: ['fewest first', 'most first'] };
|
|
2154
|
+
function paintSort() {
|
|
2155
|
+
document.querySelectorAll('.tblSort button[data-sort]').forEach(function (b) {
|
|
2156
|
+
var on = b.getAttribute('data-sort') === mapSort.key;
|
|
2157
|
+
b.setAttribute('aria-pressed', on ? 'true' : 'false');
|
|
2158
|
+
var dir = b.querySelector('.dir');
|
|
2159
|
+
if (on && !dir) { dir = document.createElement('span'); dir.className = 'dir'; b.appendChild(document.createTextNode(' ')); b.appendChild(dir); }
|
|
2160
|
+
if (dir) { dir.hidden = !on; dir.textContent = on ? SORT_WORDS[mapSort.key][mapSort.dir === 1 ? 0 : 1] : ''; }
|
|
2161
|
+
});
|
|
2162
|
+
$('mapSorted').textContent = 'Sorted by ' + mapSort.key + ', ' +
|
|
2163
|
+
SORT_WORDS[mapSort.key][mapSort.dir === 1 ? 0 : 1] + '.';
|
|
2164
|
+
}
|
|
2165
|
+
document.querySelectorAll('.tblSort button[data-sort]').forEach(function (btn) {
|
|
2122
2166
|
btn.addEventListener('click', function () {
|
|
2123
|
-
var k =
|
|
2167
|
+
var k = btn.getAttribute('data-sort');
|
|
2124
2168
|
mapSort.dir = (mapSort.key === k) ? -mapSort.dir : 1;
|
|
2125
2169
|
mapSort.key = k;
|
|
2126
|
-
|
|
2127
|
-
th.setAttribute('aria-sort', mapSort.dir === 1 ? 'ascending' : 'descending');
|
|
2170
|
+
paintSort();
|
|
2128
2171
|
applyMapFilter();
|
|
2129
2172
|
});
|
|
2130
2173
|
});
|
|
2174
|
+
paintSort();
|
|
2131
2175
|
|
|
2132
2176
|
/* ══ THE LIVING SKY (task 1002762) ═════════════════════════════════════════
|
|
2133
2177
|
The retired gate's cluster, rewritten for the hub. Physics is the gate's
|
|
@@ -4819,6 +4863,7 @@ summary{min-height:24px;padding:3px 0;}
|
|
|
4819
4863
|
/* its planet (task 1003347) reads off the row — fetch-free too; a pick in
|
|
4820
4864
|
progress survives the tick because only a different project re-renders it */
|
|
4821
4865
|
renderPick(inst);
|
|
4866
|
+
renderCardPick(inst);
|
|
4822
4867
|
/* the page names its project — the heading holds #mName; and in the tab */
|
|
4823
4868
|
document.title = (inst.slug ? inst.slug + ' — ' : '') + BASE_TITLE;
|
|
4824
4869
|
/* the card's own story, on the project's own page (task 1003232): the
|
|
@@ -5400,6 +5445,20 @@ summary{min-height:24px;padding:3px 0;}
|
|
|
5400
5445
|
var PICK_STYLES = [['tint', 'tinted'], ['wash', 'washed'], ['plain', 'plain']];
|
|
5401
5446
|
var PICK_ACCENTS = [['sea', 'sea'], ['terracotta', 'terracotta'], ['gold-soft', 'soft gold'], ['sun-lit', 'sunlit'], ['accent', 'the accent']];
|
|
5402
5447
|
var PICK_FIELDS = { mPickShape: 'shape', mPickMaterial: 'material', mPickStyle: 'style', mPickAccent: 'accent' };
|
|
5448
|
+
/* ── the card's backdrop (task 1003352): the same KIND of key as the planet —
|
|
5449
|
+
a closed list of platform-drawn plates, saved on the same settings channel,
|
|
5450
|
+
pushed to no instance and restarting nothing. '' is "its own picture": the
|
|
5451
|
+
card falls back to the project's art_url, which is all it read before. The
|
|
5452
|
+
plates are the world's own material (DESIGN.md, round 4), dark only. ── */
|
|
5453
|
+
var CARD_BACKDROPS = [['', 'its own picture'], ['nebula', 'nebula'], ['dust', 'dust'], ['deepfield', 'deep field'], ['chrome', 'chrome']];
|
|
5454
|
+
var CARD_PLATES = { nebula: 'r4-card-nebula.jpg', dust: 'r4-card-dust.jpg', deepfield: 'r4-card-deepfield.jpg', chrome: 'r4-card-chrome.jpg' };
|
|
5455
|
+
var CARD_WORDS = { nebula: 'a violet and bronze nebula wash', dust: 'warm bronze dust lanes',
|
|
5456
|
+
deepfield: 'a deep field of distant galaxies', chrome: 'a sweep of liquid chrome' };
|
|
5457
|
+
/* a key → the plate's path, or '' for anything this platform does not draw
|
|
5458
|
+
(an unknown key from an older row must never become a broken src) */
|
|
5459
|
+
function backdropPlate(key) {
|
|
5460
|
+
return CARD_PLATES[key] ? '/assets/world/' + CARD_PLATES[key] : '';
|
|
5461
|
+
}
|
|
5403
5462
|
var mPick = null; /* the pending choice: { shape, material, style, accent } */
|
|
5404
5463
|
var mPickFor = null; /* which project it belongs to — a different one starts afresh */
|
|
5405
5464
|
var mPickTouched = false; /* the owner changed something since the seed — a late catalog must not undo it */
|
|
@@ -5508,6 +5567,79 @@ summary{min-height:24px;padding:3px 0;}
|
|
|
5508
5567
|
});
|
|
5509
5568
|
}
|
|
5510
5569
|
|
|
5570
|
+
/* ── its card (task 1003352; the owner's ask on the planet round: "this could
|
|
5571
|
+
also house project card backdrop customization"). Its own section BESIDE the
|
|
5572
|
+
planet rather than inside it, so each heading stays true — one is how the
|
|
5573
|
+
project is drawn everywhere, the other is one surface's backdrop. Same
|
|
5574
|
+
mechanics as the planet, key for key: reads off the row, saves on the
|
|
5575
|
+
settings PATCH, and the reply is a receipt the card repaints from. ── */
|
|
5576
|
+
var mCard = null; /* the pending choice: the backdrop key, or '' */
|
|
5577
|
+
var mCardFor = null; /* which project it belongs to */
|
|
5578
|
+
function renderCardPick(inst) {
|
|
5579
|
+
if (mCard === null || mCardFor !== inst.id) { mCard = inst.card_backdrop || ''; mCardFor = inst.id; }
|
|
5580
|
+
var plate = backdropPlate(mCard);
|
|
5581
|
+
$('mCardPick').innerHTML =
|
|
5582
|
+
'<div class="pick">' +
|
|
5583
|
+
'<div class="pickPreview"><span class="cardBand"' +
|
|
5584
|
+
(plate ? ' style="background-image:url(' + esc(plate) + ')"' : ' data-own') + ' aria-hidden="true"></span>' +
|
|
5585
|
+
/* the line speaks for the ROW, so a pick that is ahead of the row says
|
|
5586
|
+
so — the preview above it is already showing the plate */
|
|
5587
|
+
'<p class="pickWords">' + esc(CARD_WORDS[mCard] || 'the project’s own picture, when it has one') +
|
|
5588
|
+
'<small>' + (mCard !== (inst.card_backdrop || '') ? 'not saved yet'
|
|
5589
|
+
: inst.card_backdrop ? 'your choice' : 'nothing chosen') + '</small></p></div>' +
|
|
5590
|
+
'<div class="pickBands">' + pickBand('Backdrop', 'mCardBackdrop', CARD_BACKDROPS, mCard) + '</div>' +
|
|
5591
|
+
'</div>' +
|
|
5592
|
+
'<div class="actions"><button type="button" class="btn small" data-card-save>Save its card</button></div>' +
|
|
5593
|
+
'<div class="projMsg" id="mCardMsg" role="status" aria-live="polite"></div>';
|
|
5594
|
+
}
|
|
5595
|
+
$('mCardPick').addEventListener('change', function (ev) {
|
|
5596
|
+
var t = ev.target;
|
|
5597
|
+
if (!t || t.type !== 'radio' || t.name !== 'mCardBackdrop' || !manageInst) return;
|
|
5598
|
+
mCard = t.value;
|
|
5599
|
+
renderCardPick(manageInst); /* the preview follows the pick, keeping the cell's focus */
|
|
5600
|
+
var again = document.querySelector('#mCardPick input[value="' + t.value + '"]');
|
|
5601
|
+
if (again) again.focus({ preventScroll: true });
|
|
5602
|
+
});
|
|
5603
|
+
$('mCardPick').addEventListener('click', function (ev) {
|
|
5604
|
+
var t = ev.target.closest && ev.target.closest('button');
|
|
5605
|
+
if (t && t.hasAttribute('data-card-save')) doCardSave();
|
|
5606
|
+
});
|
|
5607
|
+
function doCardSave() {
|
|
5608
|
+
if (!manageInst || mCard === null) return;
|
|
5609
|
+
var box = $('mCardMsg');
|
|
5610
|
+
document.querySelectorAll('#mCardPick .actions button').forEach(function (b) { b.disabled = true; });
|
|
5611
|
+
box.className = 'projMsg'; box.textContent = 'Saving…';
|
|
5612
|
+
fetch(API + '/provisioning/instances/' + encodeURIComponent(manageId) + '/settings', {
|
|
5613
|
+
method: 'PATCH', credentials: 'same-origin', headers: { 'Content-Type': 'application/json' },
|
|
5614
|
+
body: JSON.stringify({ card_backdrop: mCard || null })
|
|
5615
|
+
}).then(function (res) {
|
|
5616
|
+
return jsonOrEmpty(res).then(function (data) {
|
|
5617
|
+
if (res.ok) {
|
|
5618
|
+
/* the row now holds the choice; the card reads it from there */
|
|
5619
|
+
manageInst.card_backdrop = (data.planet || {}).card_backdrop || null;
|
|
5620
|
+
var row = byId[manageInst.id];
|
|
5621
|
+
if (row) row.card_backdrop = manageInst.card_backdrop;
|
|
5622
|
+
mCard = null;
|
|
5623
|
+
renderCardPick(manageInst);
|
|
5624
|
+
var done = $('mCardMsg');
|
|
5625
|
+
done.className = 'projMsg ok';
|
|
5626
|
+
done.textContent = (data.push && data.push.message) || 'Saved.';
|
|
5627
|
+
loadCatalog();
|
|
5628
|
+
return;
|
|
5629
|
+
}
|
|
5630
|
+
var e = apiError(data, res.status);
|
|
5631
|
+
if (res.status === 401) { box.className = 'projMsg err'; box.innerHTML = signInAgain(); return; }
|
|
5632
|
+
box.className = 'projMsg err';
|
|
5633
|
+
box.textContent = e.message || 'The choice could not be saved — try again in a moment.';
|
|
5634
|
+
});
|
|
5635
|
+
}).catch(function () {
|
|
5636
|
+
box.className = 'projMsg err';
|
|
5637
|
+
box.textContent = 'Couldn’t reach the platform — check your connection and try again.';
|
|
5638
|
+
}).then(function () {
|
|
5639
|
+
document.querySelectorAll('#mCardPick .actions button').forEach(function (b) { b.disabled = false; });
|
|
5640
|
+
});
|
|
5641
|
+
}
|
|
5642
|
+
|
|
5511
5643
|
/* ── how people join (task 1003044): the joinability toggle — the visibility
|
|
5512
5644
|
section's shape, key for key: the CHOICE from the platform's settings row,
|
|
5513
5645
|
what the project RUNS from its own manifest (brand.project.joinability),
|
|
@@ -75,8 +75,16 @@
|
|
|
75
75
|
"text": [["#cardRel", "yours"]], "href": [["#cardOpen", "/"]] } },
|
|
76
76
|
{ "name": "the table: the hall glyph rides the door cell on the one member row whose hall is elsewhere, and on the platform's row", "continue": true,
|
|
77
77
|
"steps": [["press", "Escape"], ["wait", 150], ["click", "#projTrig"], ["wait", 120], ["click", "a[data-sub=\"table\"]"], ["wait", 300]],
|
|
78
|
-
"expect": { "dialog": false, "visible": ["#selfHall"], "count": [["#mapRows
|
|
79
|
-
"href": [["#mapRows
|
|
78
|
+
"expect": { "dialog": false, "visible": ["#selfHall"], "count": [["#mapRows li[data-generated] .rowHall", 1], ["#mapRows li[data-generated] .facts", 7], ["#mapRows li[data-generated] .runs", 7], ["#mapRows li[data-generated] .rowDoors", 7]],
|
|
79
|
+
"href": [["#mapRows li[data-generated] .rowHall", "https://builders.amazonprimea.com/"]] } },
|
|
80
|
+
{ "name": "the table: the sort left the column head — the pills carry the order, and the sentence under the list states it (task 1003356)", "continue": true,
|
|
81
|
+
"steps": [["click", ".tblSort button[data-sort=\"builders\"]"], ["wait", 200]],
|
|
82
|
+
"expect": { "attr": [[".tblSort button[data-sort=\"builders\"]", "aria-pressed", "true"], [".tblSort button[data-sort=\"name\"]", "aria-pressed", "false"]],
|
|
83
|
+
"text": [["#mapSorted", "Sorted by builders, fewest first."]] } },
|
|
84
|
+
{ "name": "the table: pressing the pressed sort reverses it, exactly as the column header did", "continue": true,
|
|
85
|
+
"steps": [["click", ".tblSort button[data-sort=\"builders\"]"], ["wait", 200]],
|
|
86
|
+
"expect": { "attr": [[".tblSort button[data-sort=\"builders\"]", "aria-pressed", "true"]],
|
|
87
|
+
"text": [["#mapSorted", "Sorted by builders, most first."]] } },
|
|
80
88
|
{ "name": "back to the sky for the rest of the sequence", "continue": true,
|
|
81
89
|
"steps": [["click", "#projTrig"], ["wait", 120], ["click", "a[data-sub=\"sky\"]"], ["wait", 300]],
|
|
82
90
|
"expect": { "hidden": ["#sub-table-body"] } },
|
|
@@ -123,6 +131,12 @@
|
|
|
123
131
|
{ "name": "manage flows: try again from the snagged project's own page re-files it too", "auth": true, "width": 1440, "url": "/projects?view=manage&id=103",
|
|
124
132
|
"steps": [["wait",900],["click","[data-m-retry]"],["wait",900]],
|
|
125
133
|
"expect": {"text":[["#mMsg","Queued. The platform picks it up from here."]],"hasClass":[["#mMsg","ok",true]],"hidden":["#mAddress"]} },
|
|
134
|
+
{ "name": "manage flows: its card (task 1003352) — pick the nebula plate; save; the receipt lands and the preview takes the plate", "auth": true, "width": 1440, "url": "/projects?view=manage&id=101",
|
|
135
|
+
"steps": [["wait",900],["check","#mCardPick input[name=\"mCardBackdrop\"][value=\"nebula\"]"],["wait",150],["click","[data-card-save]"],["wait",700]],
|
|
136
|
+
"expect": {"text":[["#mCardMsg","Saved. The sky, your list and the card draw it this way from here; nothing on your project restarts for it."]],"hasClass":[["#mCardMsg","ok",true]],"count":[["#mCardPick .cardBand[data-own]",0]]} },
|
|
137
|
+
{ "name": "manage flows: its card — handing it back to the platform restores the project's own picture", "continue": true,
|
|
138
|
+
"steps": [["check","#mCardPick input[name=\"mCardBackdrop\"][value=\"\"]"],["wait",150],["click","[data-card-save]"],["wait",700]],
|
|
139
|
+
"expect": {"hasClass":[["#mCardMsg","ok",true]],"count":[["#mCardPick .cardBand[data-own]",1]]} },
|
|
126
140
|
{ "name": "manage flows: how people join — pick a cell, save, the receipt lands under the choice", "auth": true, "width": 1440, "url": "/projects?view=manage&id=101",
|
|
127
141
|
"steps": [["wait",900],["check","input[name=\"mJoinPick\"][value=\"apply\"]"],["click","[data-join-save]"],["wait",600]],
|
|
128
142
|
"expect": {"text":[["#mJoinMsg","Saved. The project restarts to apply it."],["#mName","demo"]],"checked":"input[name=\"mJoinPick\"][value=\"apply\"]","visible":["#mOrb .worldOrb","#mFacts .ledger .k"]} },
|
|
@@ -15,11 +15,13 @@
|
|
|
15
15
|
"in-map-kbd": { "auth": true, "actions": [["focus", "#projTrig"], ["press", "Enter"], ["wait", 350], ["press", "ArrowDown"], ["wait", 120]], "expect": { "expanded": true, "activeText": "Table" } },
|
|
16
16
|
"in-map-search": { "auth": true, "actions": [["clickIfVisible", "#qToggle"], ["wait", 200], ["fill", "#mapQ", "emer"], ["wait", 300]], "expect": { "value": [["#mapQ", "emer"]] } },
|
|
17
17
|
"in-map-mine-on": { "auth": true, "actions": [["check", "#onlyMine"], ["wait", 300]], "expect": { "checked": "#onlyMine" } },
|
|
18
|
-
"in-table": { "auth": true, "actions": [["click", "#projTrig"], ["wait", 250], ["click", "a[data-sub=\"table\"]"], ["wait", 400]], "expect": { "visible": ["#sub-table-body", ".tblMast", ".mastObj", "#selfHall"], "closed": "#menuProjects", "count": [["#mapRows
|
|
18
|
+
"in-table": { "auth": true, "actions": [["click", "#projTrig"], ["wait", 250], ["click", "a[data-sub=\"table\"]"], ["wait", 400]], "expect": { "visible": ["#sub-table-body", ".tblMast", ".mastObj", "#selfHall"], "closed": "#menuProjects", "count": [["#mapRows li[data-generated] .rowHall", 1], ["#mapRows .tblRow .facts", 7], ["#mapRows .tblRow .rowDoors", 7]], "text": [["#mapSorted", "Sorted by name, a to z."]] } },
|
|
19
|
+
"in-table-by-builders": { "auth": true, "actions": [["click", "#projTrig"], ["wait", 250], ["click", "a[data-sub=\"table\"]"], ["wait", 400], ["click", ".tblSort button[data-sort=\"builders\"]"], ["wait", 200]], "expect": { "visible": ["#sub-table-body"], "attr": [[".tblSort button[data-sort=\"builders\"]", "aria-pressed", "true"], [".tblSort button[data-sort=\"name\"]", "aria-pressed", "false"]], "text": [["#mapSorted", "Sorted by builders, fewest first."]] } },
|
|
19
20
|
"in-mine": { "auth": true, "url": "/projects?view=mine", "expect": { "hidden": ["#qWrap", "#empty"], "visible": ["#mineBar", "#projectsList", "#projectsList .proj .worldOrb .disc"], "count": [["#projectsList .proj", 5], ["#projectsList .proj.gone", 1], ["#projectsList .proj .worldOrb[data-shape][data-material][data-style]", 5], ["#projectsList .proj .worldOrb[data-template=\"blob-frost-tint\"]", 1], ["#projectsList .proj .strip", 1], ["#projectsList .proj .worldOrb.ashen", 2], ["#projectsList .proj .actions a", 7], ["#projectsList .proj .actions button", 0]] } },
|
|
20
21
|
"in-manage": { "auth": true, "url": "/projects?view=manage&id=101", "expect": { "visible": ["#mMain", "#mChip .chip", "#mOrb .worldOrb", "#mFacts .ledger .k", "#mActs", "#mAddress"], "hidden": ["#qWrap", "#mGate", "#mMissing", "#mErr"], "text": [["#mName", "demo"], ["#mTitle", "demo"]] } },
|
|
21
22
|
"in-manage-address": { "auth": true, "url": "/projects?view=manage&id=101", "expect": { "visible": ["#mAddress", "#mAddress h2", "#mDom .plain", "#mDomName", "#mDom [data-m-attach]", "#mDomWhat summary"], "count": [["#mDom .attach input[type=text]", 1], ["#mDom .attach button", 1]] } },
|
|
22
23
|
"in-manage-planet": { "auth": true, "url": "/projects?view=manage&id=101", "expect": { "visible": ["#mPlanetPick", "#mPick .pick .pickPreview .worldOrb .disc", "#mPick [data-pick-save]", "#mPick [data-pick-reset]", "#mPickWhat summary"], "count": [["#mPick .pickCells[role=\"radiogroup\"]", 3], ["#mPick .pickCell", 10], ["#mPick .pickCell.on", 3], ["#mPick .pickSw", 5], ["#mPick .pickSw.on", 1]], "attr": [["#mPick .pickPreview .worldOrb", "data-template", "pair-obsidian-tint"], ["#mOrb .worldOrb", "data-template", "pair-obsidian-tint"]], "checked": "#mPick input[name=\"mPickAccent\"][value=\"sea\"]", "text": [["#mPlanet .v small", "your choice."]] } },
|
|
24
|
+
"in-manage-card": { "auth": true, "url": "/projects?view=manage&id=101", "expect": { "visible": ["#mCard", "#mCardPick .pick .pickPreview .cardBand", "#mCardPick [data-card-save]", "#mCardWhat summary"], "count": [["#mCardPick .pickCells[role=\"radiogroup\"]", 1], ["#mCardPick .pickCell", 5], ["#mCardPick .pickCell.on", 1]], "checked": "#mCardPick input[name=\"mCardBackdrop\"][value=\"\"]", "attr": [["#mCardPick .cardBand", "data-own", ""]] } },
|
|
23
25
|
"in-manage-snag": { "auth": true, "url": "/projects?view=manage&id=103", "expect": { "visible": ["#mMain", "#mErr", "#mActs"], "hidden": ["#mAddress"], "text": [["#mName", "tidepool"]] } },
|
|
24
26
|
"in-manage-gone": { "auth": true, "url": "/projects?view=manage&id=104", "expect": { "visible": ["#mMain", "#mActs"], "hidden": ["#mErr", "#mAddress"], "text": [["#mName", "old-lantern"]] } },
|
|
25
27
|
"in-manage-missing": { "auth": true, "url": "/projects?view=manage&id=999", "expect": { "visible": ["#mMissing"], "hidden": ["#mMain", "#mGate"] } },
|
package/src/module-api.js
CHANGED
|
@@ -33,7 +33,7 @@ const { validateOrRespond, LIMITS, parseId, asyncHandler, corsPublicGet, parsePa
|
|
|
33
33
|
// there. scripts/gds/bump-version.js still rewrites the literal below; it appends
|
|
34
34
|
// the entry to that file. Look for a version's history there, not here.
|
|
35
35
|
// ---------------------------------------------------------------------------
|
|
36
|
-
const CORE_VERSION = '1.19.
|
|
36
|
+
const CORE_VERSION = '1.19.442'; // CI auto-patch carrier (ADR 0161); changelog: docs/module-api-changelog.md
|
|
37
37
|
|
|
38
38
|
// A namespaced logger so a module's log lines are attributable + consistent.
|
|
39
39
|
// Usage: const log = api.logger('dev-box'); log.info('mounted');
|