@bongos/core 1.20.73 → 1.20.75
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 +66 -46
- package/clients/bongos-client/README.md +1 -1
- package/clients/bongos-client/bongos-client.global.js +4 -0
- package/clients/bongos-client/index.cjs +4 -0
- package/clients/bongos-client/index.d.ts +8 -0
- package/clients/bongos-client/index.mjs +4 -0
- package/docs/adr/0359-nobody-sets-a-module-score-by-hand-metic-can-ask-for-a-re-check.md +40 -0
- package/docs/adr/README.md +1 -0
- package/docs/api/openapi.json +185 -3
- package/docs/api-reference.md +5 -3
- package/docs/architecture.md +1 -1
- package/docs/copy-inventory.md +447 -373
- package/docs/copy-registry.json +1157 -468
- package/docs/module-api-changelog.md +4 -0
- package/docs/page-inventory.json +6 -1
- package/docs/page-readings.json +1044 -650
- package/modules/government/catalog.js +3 -0
- package/modules/government/migrations/government_021_module_assessment_rerun.sql +36 -0
- package/modules/provisioning/routes/provisioning.js +35 -0
- package/modules/public-landing/public/assets/cosmos.css +1 -1
- package/modules/public-landing/public/projects.html +589 -63
- package/modules/public-landing/public/projects.probes.json +8 -5
- package/modules/public-landing/public/projects.states.json +19 -14
- package/modules/ui-design/kit/lib.js +4 -2
- package/modules/ui-design/kit/serve.js +5 -0
- package/package-lock.json +2 -2
- package/package.json +1 -1
- package/release-notes.json +12 -0
- package/src/bongos/route-rank-check.js +3 -0
- package/src/bongos/routes/modules.js +27 -0
- package/src/module-api.js +1 -1
- package/tests/module_store_reassess.mjs +120 -0
- package/tests/projects_hub.mjs +9 -5
- package/tests/projects_hub_app_status.mjs +1 -1
- package/tests/projects_hub_app_step.mjs +10 -10
- package/tests/projects_hub_look.mjs +7 -7
- package/tests/projects_hub_module_picker.mjs +9 -9
- package/tests/projects_hub_pre_uat.mjs +2 -1
- package/tests/wizard_demo.mjs +1 -1
- package/tests/wizard_draft_resume.mjs +1 -1
- package/tests/wizard_front_door.mjs +11 -7
- package/tests/wizard_intent_resume.mjs +9 -9
- package/tests/wizard_physics.mjs +264 -0
|
@@ -167,6 +167,54 @@ h1[tabindex="-1"]:focus:not(:focus-visible){outline:none;}
|
|
|
167
167
|
.forkStage{max-width:300px;}
|
|
168
168
|
.forkRoutes{margin-top:32px;}
|
|
169
169
|
}
|
|
170
|
+
/* planet physics (task 1004418, BV2.PS07): the fork's layout, its stage forming a
|
|
171
|
+
planet as the answers come in. The canvas's seven-question rail is a quiet
|
|
172
|
+
label-face row inside the panel; the wizard's own rail stays above it. Choices
|
|
173
|
+
are the wizard's hairline pills; the planet grows by a step size per answer. */
|
|
174
|
+
.physCrumb{font-family:var(--label-face);font-size:var(--label-size);letter-spacing:var(--label-space);text-transform:uppercase;color:var(--ink-faint);margin:0 0 10px;}
|
|
175
|
+
.physRail{list-style:none;display:flex;flex-wrap:wrap;gap:4px 16px;margin:0 0 22px;padding:0;font-family:var(--label-face);font-size:var(--label-size);letter-spacing:var(--label-space);text-transform:uppercase;color:var(--ink-faint);}
|
|
176
|
+
.physRail li.now{color:var(--ink);}
|
|
177
|
+
.physRail li.done{color:var(--ink-soft);}
|
|
178
|
+
.physRail li.now::before{content:"";display:inline-block;width:6px;height:6px;margin-right:6px;border-radius:50%;background:var(--accent);vertical-align:2px;}
|
|
179
|
+
.physQ h1 em{font-style:italic;}
|
|
180
|
+
.physCells .tpill small{display:block;font-size:13.5px;font-weight:400;color:var(--ink-soft);line-height:1.4;}
|
|
181
|
+
.physCells .tpill[disabled]{opacity:.45;cursor:default;}
|
|
182
|
+
.physWhy{font-size:14px;line-height:1.5;color:var(--ink-soft);max-width:60ch;margin:0 0 14px;}
|
|
183
|
+
.physExisting{margin:4px 0 14px;padding:0;border:0;}
|
|
184
|
+
.physExisting legend{font-size:15px;color:var(--ink);margin:0 0 6px;padding:0;}
|
|
185
|
+
.physCheck{display:flex;align-items:flex-start;gap:12px;min-height:24px;padding:10px 0;border-top:1px solid var(--rule-soft);font-size:15px;color:var(--ink);cursor:pointer;}
|
|
186
|
+
.physCheck input[type=checkbox]{width:18px;height:18px;margin:2px 0 0;flex:none;accent-color:var(--accent);}
|
|
187
|
+
.physCheck small{display:block;font-size:13.5px;color:var(--ink-soft);}
|
|
188
|
+
.physMain{margin-left:auto;display:inline-flex;align-items:center;gap:6px;font-family:var(--label-face);font-size:var(--label-size);letter-spacing:var(--label-space);text-transform:uppercase;color:var(--ink-faint);}
|
|
189
|
+
.physMain input{width:16px;height:16px;margin:0;accent-color:var(--accent);}
|
|
190
|
+
/* the two pickers in the renderSetup field grammar: a hairline under, 44px tall */
|
|
191
|
+
.physRow2 select{display:block;width:100%;min-height:44px;font-family:var(--font-body);font-size:16px;color:var(--ink);background:none;border:0;border-bottom:1px solid var(--rule);border-radius:0;padding:8px 0;outline:none;}
|
|
192
|
+
.physRow2 select:focus{border-bottom-color:var(--ink);}
|
|
193
|
+
.physRow2 select option{background:var(--bg);color:var(--ink);}
|
|
194
|
+
.physRow2{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:0 16px;}
|
|
195
|
+
.physNote{margin:6px 0 14px;padding:14px 0 0;border-top:1px solid var(--rule);max-width:62ch;}
|
|
196
|
+
.physNoteH{font-size:15px;color:var(--ink);margin:0 0 8px;}
|
|
197
|
+
.physTiers{display:grid;grid-template-columns:120px minmax(0,1fr);gap:8px 16px;margin:0 0 10px;font-size:14.5px;line-height:1.45;}
|
|
198
|
+
.physTiers dt{font-family:var(--label-face);font-size:var(--label-size);letter-spacing:var(--label-space);text-transform:uppercase;color:var(--ink-faint);padding-top:2px;}
|
|
199
|
+
.physTiers dd{margin:0;color:var(--ink);}
|
|
200
|
+
.physGrp{font-family:var(--label-face);font-size:var(--label-size);letter-spacing:var(--label-space);text-transform:uppercase;color:var(--ink-faint);margin:12px 0 4px;}
|
|
201
|
+
.physLink{background:none;border:0;padding:3px 0;min-height:24px;font:inherit;font-size:14px;color:var(--ink);text-decoration:underline;text-underline-offset:3px;cursor:pointer;}
|
|
202
|
+
.physStage .physPlanet{transition:width .6s ease;}
|
|
203
|
+
.physStage .physPlanet[data-size="1"]{width:22%;}
|
|
204
|
+
.physStage .physPlanet[data-size="2"]{width:28%;}
|
|
205
|
+
.physStage .physPlanet[data-size="3"]{width:34%;}
|
|
206
|
+
.physStage .physPlanet[data-size="4"]{width:40%;}
|
|
207
|
+
.physStage .physPlanet[data-size="5"]{width:46%;}
|
|
208
|
+
.physStage .physPlanet[data-size="6"]{width:50%;}
|
|
209
|
+
.physGuard{position:absolute;inset:14%;border:1px solid color-mix(in srgb,var(--accent) 55%,transparent);border-radius:50%;outline:1px dashed color-mix(in srgb,var(--accent) 30%,transparent);outline-offset:6px;}
|
|
210
|
+
.physStage.physStopped{opacity:.6;}
|
|
211
|
+
.physCap,.physFoot{position:absolute;left:16px;right:16px;margin:0;}
|
|
212
|
+
.physFoot{bottom:14px;display:grid;gap:6px;}
|
|
213
|
+
.physCap,.physCallout,.physCoords{margin:0;font-family:var(--label-face);font-size:var(--label-size);letter-spacing:var(--label-space);text-transform:uppercase;color:var(--ink-soft);}
|
|
214
|
+
.physCap{top:14px;}
|
|
215
|
+
.physCallout{color:var(--ink);text-transform:none;letter-spacing:0;font-family:var(--font-body);font-size:13px;}
|
|
216
|
+
.physCoords{color:var(--ink-faint);}
|
|
217
|
+
@media (max-width:840px){ .physRow2{grid-template-columns:1fr;} }
|
|
170
218
|
/* under 520 the two doors cannot sit side by side at 48px, so they stack —
|
|
171
219
|
still two equal doors in one object */
|
|
172
220
|
@media (max-width:520px){
|
|
@@ -1243,15 +1291,16 @@ summary{min-height:24px;padding:3px 0;}
|
|
|
1243
1291
|
<div class="wrap viewWrap">
|
|
1244
1292
|
<div class="card wizFront">
|
|
1245
1293
|
<ol class="steps" aria-label="Creation steps">
|
|
1246
|
-
<li class="now" data-step="3" aria-current="step"><span class="snum">1</span><span class="slbl">
|
|
1247
|
-
<li data-step="4"><span class="snum">2</span><span class="slbl">
|
|
1248
|
-
<li data-step="5"><span class="snum">3</span><span class="slbl">
|
|
1249
|
-
<li data-step="6"><span class="snum">4</span><span class="slbl">
|
|
1250
|
-
<li data-step="7"><span class="snum">5</span><span class="slbl">
|
|
1251
|
-
<li data-step="8"><span class="snum">6</span><span class="slbl">
|
|
1252
|
-
<li data-step="9"><span class="snum">7</span><span class="slbl">
|
|
1253
|
-
<li data-step="10"><span class="snum">8</span><span class="slbl">
|
|
1254
|
-
<li data-step="11"><span class="snum">9</span><span class="slbl">
|
|
1294
|
+
<li class="now" data-step="3" aria-current="step"><span class="snum">1</span><span class="slbl">Physics</span></li>
|
|
1295
|
+
<li data-step="4"><span class="snum">2</span><span class="slbl">Name</span></li>
|
|
1296
|
+
<li data-step="5"><span class="snum">3</span><span class="slbl">Type</span></li>
|
|
1297
|
+
<li data-step="6"><span class="snum">4</span><span class="slbl">About</span></li>
|
|
1298
|
+
<li data-step="7"><span class="snum">5</span><span class="slbl">Modules</span></li>
|
|
1299
|
+
<li data-step="8"><span class="snum">6</span><span class="slbl">Home</span></li>
|
|
1300
|
+
<li data-step="9"><span class="snum">7</span><span class="slbl">Address</span></li>
|
|
1301
|
+
<li data-step="10"><span class="snum">8</span><span class="slbl">App</span></li>
|
|
1302
|
+
<li data-step="11"><span class="snum">9</span><span class="slbl">Look</span></li>
|
|
1303
|
+
<li data-step="12"><span class="snum">10</span><span class="slbl">Create</span></li>
|
|
1255
1304
|
</ol>
|
|
1256
1305
|
|
|
1257
1306
|
<div class="createSplit">
|
|
@@ -1433,12 +1482,156 @@ summary{min-height:24px;padding:3px 0;}
|
|
|
1433
1482
|
</div>
|
|
1434
1483
|
</section>
|
|
1435
1484
|
|
|
1436
|
-
<!-- step 3 ·
|
|
1485
|
+
<!-- step 3 · planet physics, questions 1 to 4 (task 1004418, BV2.PS07; the canvas's
|
|
1486
|
+
Autofill, State, StateExisting, NotPossible, Geography, Ages, Entity and
|
|
1487
|
+
EntityExisting frames, docs/design/project-startup-direction.md). ONE rail step
|
|
1488
|
+
with its own inner sequence, so the wizard's numbering moved by one and the
|
|
1489
|
+
canvas's seven-question rail lives inside the panel (questions 5 to 7 join it in
|
|
1490
|
+
BV2.PS11). Left: the question, its choices and the doors. Right: the field plate
|
|
1491
|
+
with the planet forming from the world's own plates as the answers come in.
|
|
1492
|
+
Every answer rides the create request's `detail` (planet-physics.js); the stop
|
|
1493
|
+
screen and the soft-limit table come from POST /provisioning/physics-check, the
|
|
1494
|
+
same screen and table the create runs. The age tiers are described, never
|
|
1495
|
+
claimed as enforced (spec D6). -->
|
|
1496
|
+
<section class="panel" id="panel-physics" aria-labelledby="phys-h0">
|
|
1497
|
+
<div class="forkBody physBody">
|
|
1498
|
+
<div>
|
|
1499
|
+
<p class="physCrumb">planet creation · part 1 of 2 · planet physics</p>
|
|
1500
|
+
<ol class="physRail" id="physRail" aria-label="Planet physics questions">
|
|
1501
|
+
<li data-q="1">state</li><li data-q="2">geography</li><li data-q="3">ages</li><li data-q="4">entity</li><li>builders</li><li>rewards</li><li>framing</li>
|
|
1502
|
+
</ol>
|
|
1503
|
+
<form data-next="4" id="physForm">
|
|
1504
|
+
<div class="physQ" data-q="0">
|
|
1505
|
+
<h1 id="phys-h0">Start from your account, <em>or from scratch?</em></h1>
|
|
1506
|
+
<p class="lede">Seven questions set your planet’s physics: the rules it will live by. We can fill in what your account already knows from your last project, and you check every answer before it counts.</p>
|
|
1507
|
+
<div class="typeCards physCells" role="group" aria-label="How to start">
|
|
1508
|
+
<button type="button" class="tpill" data-phys-start="account" aria-pressed="false" id="physFromAccount">Auto-fill from my account</button>
|
|
1509
|
+
<button type="button" class="tpill" data-phys-start="scratch" aria-pressed="false">Fill it in myself</button>
|
|
1510
|
+
</div>
|
|
1511
|
+
<p class="physWhy" id="physAccountWhy" hidden></p>
|
|
1512
|
+
</div>
|
|
1513
|
+
|
|
1514
|
+
<div class="physQ" data-q="1" hidden>
|
|
1515
|
+
<h1 id="phys-h1">Is your planet new, <em>or already started?</em></h1>
|
|
1516
|
+
<div class="typeCards physCells" role="group" aria-label="Your project’s state">
|
|
1517
|
+
<button type="button" class="tpill" data-phys="project_state" data-val="new" aria-pressed="false">New <small>Starting from zero.</small></button>
|
|
1518
|
+
<button type="button" class="tpill" data-phys="project_state" data-val="existing" aria-pressed="false">Existing <small>My project has already been started.</small></button>
|
|
1519
|
+
</div>
|
|
1520
|
+
<fieldset class="physExisting" id="physExisting" data-limit="existing_work" hidden>
|
|
1521
|
+
<legend>What already exists? Pick all that apply, then your main one.</legend>
|
|
1522
|
+
<label class="physCheck"><input type="checkbox" data-work="code"> <span>Code files</span> <span class="physMain"><input type="radio" name="physMain" value="code" aria-label="Code files is the main one"> main</span></label>
|
|
1523
|
+
<label class="physCheck"><input type="checkbox" data-work="digital-files"> <span>Digital files <small>Word documents, spreadsheets, other software.</small></span> <span class="physMain"><input type="radio" name="physMain" value="digital-files" aria-label="Digital files is the main one"> main</span></label>
|
|
1524
|
+
<label class="physCheck"><input type="checkbox" data-work="physical-work"> <span>Physical files or work <small>You’ll describe it in words, or upload a document, during genesis.</small></span> <span class="physMain"><input type="radio" name="physMain" value="physical-work" aria-label="Physical files or work is the main one"> main</span></label>
|
|
1525
|
+
</fieldset>
|
|
1526
|
+
<p class="physWhy" data-why="existing_work" hidden></p>
|
|
1527
|
+
<label class="wizField"><span>What is your project, and what do you want <span data-brand-product-inline>Cloud Bongos</span> to do for you?</span>
|
|
1528
|
+
<textarea id="physDesc" rows="3" maxlength="600" placeholder="A co-op farming game where the seasons never repeat."></textarea>
|
|
1529
|
+
</label>
|
|
1530
|
+
</div>
|
|
1531
|
+
|
|
1532
|
+
<div class="physQ" data-q="2" hidden>
|
|
1533
|
+
<h1 id="phys-h2">Where is <em>everyone?</em></h1>
|
|
1534
|
+
<p class="lede">Where you are, and where your builders will be, decides which payout and legal options we can offer. You can change it later.</p>
|
|
1535
|
+
<div class="physRow2">
|
|
1536
|
+
<label class="wizField"><span>Your country</span><select id="physCountry"><option value="">Choose…</option></select></label>
|
|
1537
|
+
<label class="wizField" id="physRegionField" hidden><span>State or province</span><select id="physRegion"><option value="">Choose…</option></select></label>
|
|
1538
|
+
</div>
|
|
1539
|
+
<div class="wizField"><span id="physGeoLbl">Where do you expect builders to be?</span>
|
|
1540
|
+
<div class="typeCards physCells" role="group" aria-labelledby="physGeoLbl">
|
|
1541
|
+
<button type="button" class="tpill" data-phys="builder_geography" data-val="us-only" aria-pressed="false">US only</button>
|
|
1542
|
+
<button type="button" class="tpill" data-phys="builder_geography" data-val="us-eu" aria-pressed="false">US and EU</button>
|
|
1543
|
+
<button type="button" class="tpill" data-phys="builder_geography" data-val="global" aria-pressed="false">Global</button>
|
|
1544
|
+
<button type="button" class="tpill" data-phys="builder_geography" data-val="not-sure" aria-pressed="false">Not sure yet</button>
|
|
1545
|
+
</div>
|
|
1546
|
+
</div>
|
|
1547
|
+
</div>
|
|
1548
|
+
|
|
1549
|
+
<div class="physQ" data-q="3" hidden>
|
|
1550
|
+
<h1 id="phys-h3">Will anyone under 18 <em>be building?</em></h1>
|
|
1551
|
+
<div class="typeCards physCells" role="group" aria-label="Builders under 18">
|
|
1552
|
+
<button type="button" class="tpill" data-phys="minors_on_board" data-val="false" aria-pressed="false">No <small>Everyone building is an adult.</small></button>
|
|
1553
|
+
<button type="button" class="tpill" data-phys="minors_on_board" data-val="true" aria-pressed="false">Yes <small>Some builders are under 18.</small></button>
|
|
1554
|
+
</div>
|
|
1555
|
+
<div class="physNote" id="physAges" hidden>
|
|
1556
|
+
<p class="physNoteH">The age tiers young builders work under</p>
|
|
1557
|
+
<dl class="physTiers">
|
|
1558
|
+
<dt>13 to 15</dt><dd>Non-monetary tracks only</dd>
|
|
1559
|
+
<dt>16 to 17</dt><dd>Paid work, with a guardian’s co-signature and a work-permit attestation</dd>
|
|
1560
|
+
<dt>18 and over</dt><dd>Full access</dd>
|
|
1561
|
+
</dl>
|
|
1562
|
+
<p class="finePrint">Each young builder’s guardian signs for them, and their payouts go to an account the guardian controls. These are the rules your project is set up to follow; the platform does not check ages for you yet.</p>
|
|
1563
|
+
</div>
|
|
1564
|
+
</div>
|
|
1565
|
+
|
|
1566
|
+
<div class="physQ" data-q="4" hidden>
|
|
1567
|
+
<h1 id="phys-h4">What <em>are you?</em></h1>
|
|
1568
|
+
<div id="physIntent">
|
|
1569
|
+
<p class="lede">Your planet is new, so there’s nothing to sign yet. Tell us roughly where you’re heading. You’ll make the binding choice later, once you know what you’re building.</p>
|
|
1570
|
+
<div class="typeCards physCells" role="group" aria-label="Where you are heading">
|
|
1571
|
+
<button type="button" class="tpill" data-phys="entity" data-val="intent-company" aria-pressed="false">Probably a company</button>
|
|
1572
|
+
<button type="button" class="tpill" data-phys="entity" data-val="intent-nonprofit" aria-pressed="false">Probably a nonprofit</button>
|
|
1573
|
+
<button type="button" class="tpill" data-phys="entity" data-val="intent-solo" aria-pressed="false">Just me for now</button>
|
|
1574
|
+
<button type="button" class="tpill" data-phys="entity" data-val="intent-unsure" aria-pressed="false">Don’t know yet</button>
|
|
1575
|
+
</div>
|
|
1576
|
+
<button type="button" class="physLink" id="physHaveEntity">I already have a legal entity</button>
|
|
1577
|
+
</div>
|
|
1578
|
+
<div id="physForms" hidden>
|
|
1579
|
+
<p class="lede">Pick the legal entity behind your project. The laws that apply, and the ways you can reward builders, depend on it.</p>
|
|
1580
|
+
<p class="physGrp">Organization</p>
|
|
1581
|
+
<div class="typeCards physCells" role="group" aria-label="Organization">
|
|
1582
|
+
<button type="button" class="tpill" data-phys="entity" data-val="nonprofit" aria-pressed="false">Nonprofit</button>
|
|
1583
|
+
<button type="button" class="tpill" data-phys="entity" data-val="for-profit" aria-pressed="false">For-profit company</button>
|
|
1584
|
+
<button type="button" class="tpill" data-phys="entity" data-val="corporate-division" aria-pressed="false">Division of a corporation</button>
|
|
1585
|
+
<button type="button" class="tpill" data-phys="entity" data-val="research" aria-pressed="false">Research entity</button>
|
|
1586
|
+
</div>
|
|
1587
|
+
<p class="physGrp">Group</p>
|
|
1588
|
+
<div class="typeCards physCells" role="group" aria-label="Group">
|
|
1589
|
+
<button type="button" class="tpill" data-phys="entity" data-val="university-project" aria-pressed="false">University project</button>
|
|
1590
|
+
<button type="button" class="tpill" data-phys="entity" data-val="social-group" aria-pressed="false">Social group</button>
|
|
1591
|
+
</div>
|
|
1592
|
+
<p class="physGrp">Individual</p>
|
|
1593
|
+
<div class="typeCards physCells" role="group" aria-label="Individual">
|
|
1594
|
+
<button type="button" class="tpill" data-phys="entity" data-val="single-owner-llc" aria-pressed="false">Single-owner LLC</button>
|
|
1595
|
+
<button type="button" class="tpill" data-phys="entity" data-val="private-individual" aria-pressed="false">Private individual</button>
|
|
1596
|
+
</div>
|
|
1597
|
+
<button type="button" class="physLink" id="physNoEntity">We don’t have one yet</button>
|
|
1598
|
+
</div>
|
|
1599
|
+
</div>
|
|
1600
|
+
|
|
1601
|
+
<div class="physQ" data-q="stop" hidden>
|
|
1602
|
+
<h1 id="phys-hstop">This can’t be built <em>on <span data-brand-product-inline>Cloud Bongos</span></em></h1>
|
|
1603
|
+
<p class="lede" id="physStopMsg"></p>
|
|
1604
|
+
<div class="nav">
|
|
1605
|
+
<button type="button" class="btn ghost" id="physStartOver">Start over</button>
|
|
1606
|
+
<a class="btn" href="/contact">Contact us</a>
|
|
1607
|
+
</div>
|
|
1608
|
+
</div>
|
|
1609
|
+
|
|
1610
|
+
<div class="hint" id="h-phys"> </div>
|
|
1611
|
+
<div class="nav" id="physNav">
|
|
1612
|
+
<button type="button" class="btn ghost" id="physBack">← Back</button>
|
|
1613
|
+
<button type="submit" class="btn" id="physNext">Continue →</button>
|
|
1614
|
+
</div>
|
|
1615
|
+
</form>
|
|
1616
|
+
</div>
|
|
1617
|
+
<div class="forkStage physStage" id="physStage" aria-hidden="true">
|
|
1618
|
+
<span class="forkOrbit"></span>
|
|
1619
|
+
<span class="forkOrbit forkOrbitDash"></span>
|
|
1620
|
+
<span class="physGuard" id="physGuard" hidden></span>
|
|
1621
|
+
<img class="forkSeed physPlanet" id="physPlanet" src="/assets/world/r2-chrome-blob-one-cut.webp" alt="">
|
|
1622
|
+
<p class="physCap"><span id="physCapLbl">planet physics</span> · <span id="physCapN">0 of 7</span></p>
|
|
1623
|
+
<div class="physFoot"><p class="physCallout" id="physCallout">physics · the rules it lives by · each answer shapes your planet here</p>
|
|
1624
|
+
<p class="physCoords" id="physCoords"></p></div>
|
|
1625
|
+
</div>
|
|
1626
|
+
</div>
|
|
1627
|
+
</section>
|
|
1628
|
+
|
|
1629
|
+
<!-- step 4 · name (the hub's original step-1 form, now the wizard's) -->
|
|
1437
1630
|
<section class="panel" id="panel-name" aria-labelledby="name-h">
|
|
1438
1631
|
<h1 id="name-h">Start a project</h1>
|
|
1439
1632
|
<p class="lede">Your own project: its own repository, its own home on the web, and a hall of AI builders
|
|
1440
1633
|
who do the building. You set the direction; agents lay down the code.</p>
|
|
1441
|
-
<form id="newForm" data-next="
|
|
1634
|
+
<form id="newForm" data-next="5">
|
|
1442
1635
|
<label class="wizField"><span>Project name</span>
|
|
1443
1636
|
<input type="text" id="newName" placeholder="What should it be called?" autocomplete="off" maxlength="80" aria-label="Project name">
|
|
1444
1637
|
<div class="hint" id="h-name"> </div>
|
|
@@ -1462,7 +1655,7 @@ summary{min-height:24px;padding:3px 0;}
|
|
|
1462
1655
|
<section class="panel" id="panel-type" aria-labelledby="type-h">
|
|
1463
1656
|
<h1 id="type-h">What kind of project is it?</h1>
|
|
1464
1657
|
<p class="lede">Pick the shape that fits best — it’s how the project is listed on the map, and you can change it later from the project’s own page. Not sure is a fine answer.</p>
|
|
1465
|
-
<form data-next="
|
|
1658
|
+
<form data-next="6">
|
|
1466
1659
|
<div class="typeCards" id="typeCards" role="group" aria-label="Project type">
|
|
1467
1660
|
<button type="button" class="tpill" data-type="game" aria-pressed="false">Game</button>
|
|
1468
1661
|
<button type="button" class="tpill" data-type="research" aria-pressed="false">Research</button>
|
|
@@ -1476,7 +1669,7 @@ summary{min-height:24px;padding:3px 0;}
|
|
|
1476
1669
|
</div>
|
|
1477
1670
|
<div class="hint" id="h-projtype"> </div>
|
|
1478
1671
|
<div class="nav">
|
|
1479
|
-
<button type="button" class="btn ghost" data-back="
|
|
1672
|
+
<button type="button" class="btn ghost" data-back="4">← Back</button>
|
|
1480
1673
|
<button type="submit" class="btn">Next →</button>
|
|
1481
1674
|
</div>
|
|
1482
1675
|
</form>
|
|
@@ -1494,7 +1687,7 @@ summary{min-height:24px;padding:3px 0;}
|
|
|
1494
1687
|
<section class="panel" id="panel-detail" aria-labelledby="detail-h">
|
|
1495
1688
|
<h1 id="detail-h">Tell us about it</h1>
|
|
1496
1689
|
<p class="lede">Optional — skip it and nothing about your project changes. Answering shapes what we set up for you, and a description is what puts the project on the public map.</p>
|
|
1497
|
-
<form data-next="
|
|
1690
|
+
<form data-next="7">
|
|
1498
1691
|
<label class="wizField"><span>What are you building? <small>(a sentence or two)</small></span>
|
|
1499
1692
|
<textarea id="f-desc" rows="3" maxlength="600" placeholder="A co-op farming game where the seasons never repeat."></textarea>
|
|
1500
1693
|
</label>
|
|
@@ -1507,7 +1700,7 @@ summary{min-height:24px;padding:3px 0;}
|
|
|
1507
1700
|
</div>
|
|
1508
1701
|
<div class="reassure" id="detailSkipNote"></div>
|
|
1509
1702
|
<div class="nav">
|
|
1510
|
-
<button type="button" class="btn ghost" data-back="
|
|
1703
|
+
<button type="button" class="btn ghost" data-back="5">← Back</button>
|
|
1511
1704
|
<span class="navPair">
|
|
1512
1705
|
<button type="button" class="btn ghost" id="skipDetail">Skip for now</button>
|
|
1513
1706
|
<button type="submit" class="btn">Next →</button>
|
|
@@ -1530,7 +1723,7 @@ summary{min-height:24px;padding:3px 0;}
|
|
|
1530
1723
|
<section class="panel" id="panel-modules" aria-labelledby="mod-h">
|
|
1531
1724
|
<h1 id="mod-h">What it comes with</h1>
|
|
1532
1725
|
<p class="lede">Optional — skip it and you get the suggested set below, shaped by what you just told us. These are extras on top of everything every project already has, and you can switch any of them on or off later.</p>
|
|
1533
|
-
<form data-next="
|
|
1726
|
+
<form data-next="8">
|
|
1534
1727
|
<div class="wizField"><span id="modLbl">Extras for this project</span>
|
|
1535
1728
|
<!-- the catalog search (task 1002340, BV1.R21). The wizard's own
|
|
1536
1729
|
search idiom (#ghSearch): a plain field on one hairline, no
|
|
@@ -1546,7 +1739,7 @@ summary{min-height:24px;padding:3px 0;}
|
|
|
1546
1739
|
<div class="reassure" id="modCoreNote"></div>
|
|
1547
1740
|
<div class="hint" id="h-modules"> </div>
|
|
1548
1741
|
<div class="nav">
|
|
1549
|
-
<button type="button" class="btn ghost" data-back="
|
|
1742
|
+
<button type="button" class="btn ghost" data-back="6">← Back</button>
|
|
1550
1743
|
<span class="navPair">
|
|
1551
1744
|
<button type="button" class="btn ghost" id="skipModules">Skip for now</button>
|
|
1552
1745
|
<button type="submit" class="btn">Next →</button>
|
|
@@ -1559,7 +1752,7 @@ summary{min-height:24px;padding:3px 0;}
|
|
|
1559
1752
|
<section class="panel" id="panel-home" aria-labelledby="home-h">
|
|
1560
1753
|
<h1 id="home-h">Where the code lives</h1>
|
|
1561
1754
|
<p class="lede">Every project is a real GitHub repository that you own. Start from a clean slate, or bring a repo you already have.</p>
|
|
1562
|
-
<form data-next="
|
|
1755
|
+
<form data-next="9">
|
|
1563
1756
|
<div class="choices" role="group" aria-label="Starting point">
|
|
1564
1757
|
<button type="button" class="choice" id="c-green" aria-pressed="true">
|
|
1565
1758
|
<!-- token-built, not platform orange — public-landing/ ships wholesale to
|
|
@@ -1625,7 +1818,7 @@ summary{min-height:24px;padding:3px 0;}
|
|
|
1625
1818
|
</div>
|
|
1626
1819
|
<div class="hint" id="h-home"> </div>
|
|
1627
1820
|
<div class="nav">
|
|
1628
|
-
<button type="button" class="btn ghost" data-back="
|
|
1821
|
+
<button type="button" class="btn ghost" data-back="7">← Back</button>
|
|
1629
1822
|
<button type="submit" class="btn">Next →</button>
|
|
1630
1823
|
</div>
|
|
1631
1824
|
</form>
|
|
@@ -1643,7 +1836,7 @@ summary{min-height:24px;padding:3px 0;}
|
|
|
1643
1836
|
<section class="panel" id="panel-address" aria-labelledby="addr-h">
|
|
1644
1837
|
<h1 id="addr-h">Its address in the sky</h1>
|
|
1645
1838
|
<p class="lede">The handle names your project on the platform — and its address comes with it. Once it stands up, a few GitHub steps (the next screen walks you through them) switch sign-in on.</p>
|
|
1646
|
-
<form data-next="
|
|
1839
|
+
<form data-next="10">
|
|
1647
1840
|
<label class="wizField"><span>Project handle</span>
|
|
1648
1841
|
<input type="text" id="f-slug" placeholder="mercury" autocomplete="off" maxlength="40" spellcheck="false">
|
|
1649
1842
|
<div class="hint" id="h-slug"> </div>
|
|
@@ -1665,7 +1858,7 @@ summary{min-height:24px;padding:3px 0;}
|
|
|
1665
1858
|
</label>
|
|
1666
1859
|
</div>
|
|
1667
1860
|
<div class="nav">
|
|
1668
|
-
<button type="button" class="btn ghost" data-back="
|
|
1861
|
+
<button type="button" class="btn ghost" data-back="8">← Back</button>
|
|
1669
1862
|
<button type="submit" class="btn">Next →</button>
|
|
1670
1863
|
</div>
|
|
1671
1864
|
</form>
|
|
@@ -1682,7 +1875,7 @@ summary{min-height:24px;padding:3px 0;}
|
|
|
1682
1875
|
<h1 id="app-h">Where your app will run</h1>
|
|
1683
1876
|
<p class="appHall"><b>We host your Builders' hall</b> — the place where the project gets built — at the address you just chose. There is nothing for you to set up.</p>
|
|
1684
1877
|
<p class="lede">Your app is the thing the project builds. Choose where it should run, or decide later.</p>
|
|
1685
|
-
<form data-next="
|
|
1878
|
+
<form data-next="11">
|
|
1686
1879
|
<fieldset class="appOpts" id="appOpts">
|
|
1687
1880
|
<legend>Where your app runs</legend>
|
|
1688
1881
|
<label class="appOpt" id="appOptRender">
|
|
@@ -1741,7 +1934,7 @@ summary{min-height:24px;padding:3px 0;}
|
|
|
1741
1934
|
<div class="hint" id="h-render" role="status"> </div>
|
|
1742
1935
|
</div>
|
|
1743
1936
|
<div class="nav">
|
|
1744
|
-
<button type="button" class="btn ghost" data-back="
|
|
1937
|
+
<button type="button" class="btn ghost" data-back="9">← Back</button>
|
|
1745
1938
|
<button type="submit" class="btn">Next →</button>
|
|
1746
1939
|
</div>
|
|
1747
1940
|
</form>
|
|
@@ -1754,10 +1947,10 @@ summary{min-height:24px;padding:3px 0;}
|
|
|
1754
1947
|
<section class="panel" id="panel-look" aria-labelledby="look-h">
|
|
1755
1948
|
<h1 id="look-h">Give it a look</h1>
|
|
1756
1949
|
<p class="lede">Colours for light and dark mode, and a logo, so builders who work in several projects always know which hall they’re in.</p>
|
|
1757
|
-
<form data-next="
|
|
1950
|
+
<form data-next="12">
|
|
1758
1951
|
<div class="lookPick" id="wizLook"></div>
|
|
1759
1952
|
<div class="nav">
|
|
1760
|
-
<button type="button" class="btn ghost" data-back="
|
|
1953
|
+
<button type="button" class="btn ghost" data-back="10">← Back</button>
|
|
1761
1954
|
<button type="submit" class="btn">Next →</button>
|
|
1762
1955
|
</div>
|
|
1763
1956
|
</form>
|
|
@@ -1770,7 +1963,7 @@ summary{min-height:24px;padding:3px 0;}
|
|
|
1770
1963
|
<ul class="review" id="reviewList"></ul>
|
|
1771
1964
|
<div class="alert" id="createAlert" role="alert"></div>
|
|
1772
1965
|
<div class="nav">
|
|
1773
|
-
<button type="button" class="btn ghost" data-back="
|
|
1966
|
+
<button type="button" class="btn ghost" data-back="11">← Back</button>
|
|
1774
1967
|
<button type="button" class="btn big" id="doCreate">Create my project</button>
|
|
1775
1968
|
</div>
|
|
1776
1969
|
<p class="finePrint">This files the request; the control plane does the real standup and nothing touches servers from this page. You'll get the few steps only you can do right after.</p>
|
|
@@ -4424,7 +4617,7 @@ summary{min-height:24px;padding:3px 0;}
|
|
|
4424
4617
|
/* `termsAck` is the front door's one tick (task 1004417). It is the founder's
|
|
4425
4618
|
own answer, so it lives in the draft like every other one and survives the
|
|
4426
4619
|
GitHub round-trip; the server, not this page, names the terms version. */
|
|
4427
|
-
var DRAFT_KEY = 'cb-create-draft-
|
|
4620
|
+
var DRAFT_KEY = 'cb-create-draft-v8';
|
|
4428
4621
|
var CREATED_KEY = 'cb-created-instance';
|
|
4429
4622
|
/* `description` + `teamShape` are the optional About step (task 1002334) —
|
|
4430
4623
|
both legitimately stay empty, and empty is what the create request omits. */
|
|
@@ -4433,7 +4626,7 @@ summary{min-height:24px;padding:3px 0;}
|
|
|
4433
4626
|
request omits the field), [] = the owner switched them all off, [...] =
|
|
4434
4627
|
what they picked. Never seed it with the preselect — that would store an
|
|
4435
4628
|
answer nobody gave. */
|
|
4436
|
-
var state = { step: 0, name: '', projType: null, description: '', teamShape: null, modules: null, mode: 'greenfield', owner: '', ownerTouched: false, repo: '', repoTouched: false, slug: '', slugTouched: false, domain: '', noAddress: false, appPlatform: 'later', demo: null, look: null, termsAck: false };
|
|
4629
|
+
var state = { step: 0, name: '', projType: null, description: '', teamShape: null, modules: null, mode: 'greenfield', owner: '', ownerTouched: false, repo: '', repoTouched: false, slug: '', slugTouched: false, domain: '', noAddress: false, appPlatform: 'later', physics: null, demo: null, look: null, termsAck: false };
|
|
4437
4630
|
try { Object.assign(state, JSON.parse(sessionStorage.getItem(DRAFT_KEY) || '{}')); } catch (e) {}
|
|
4438
4631
|
var authKnown = false; /* flips true when the boot's /me settles, either way */
|
|
4439
4632
|
|
|
@@ -4447,7 +4640,7 @@ summary{min-height:24px;padding:3px 0;}
|
|
|
4447
4640
|
state.name = handedName.trim().slice(0, 80);
|
|
4448
4641
|
state.slug = deriveSlug(state.name); state.slugTouched = false;
|
|
4449
4642
|
state.repo = deriveRepo(state.name); state.repoTouched = false;
|
|
4450
|
-
state.step = state.step >= 1 && state.step <=
|
|
4643
|
+
state.step = state.step >= 1 && state.step <= 12 ? state.step : 1;
|
|
4451
4644
|
try { sessionStorage.setItem(DRAFT_KEY, JSON.stringify(state)); } catch (e) {}
|
|
4452
4645
|
}
|
|
4453
4646
|
} catch (e) {}
|
|
@@ -4644,14 +4837,14 @@ summary{min-height:24px;padding:3px 0;}
|
|
|
4644
4837
|
review 11 · done 12 (the Look step joined at 10, task 1004421). The rail numbers
|
|
4645
4838
|
3-11 as its 1-9 and steps aside on 1 and 2; done marks it all. About, Modules and
|
|
4646
4839
|
Look are the steps Next can pass with nothing changed — Look has a default. */
|
|
4647
|
-
var panels = { 0: 'panel-gate', 1: 'panel-terms', 2: 'panel-fork', 3: 'panel-
|
|
4840
|
+
var panels = { 0: 'panel-gate', 1: 'panel-terms', 2: 'panel-fork', 3: 'panel-physics', 4: 'panel-name', 5: 'panel-type', 6: 'panel-detail', 7: 'panel-modules', 8: 'panel-home', 9: 'panel-address', 10: 'panel-app', 11: 'panel-look', 12: 'panel-review', 13: 'panel-done' };
|
|
4648
4841
|
/* the rail at the done panel (task 1003244): "done" is the Create step
|
|
4649
4842
|
still running — the marker stays on 5 until the project actually
|
|
4650
4843
|
answers, and only then does the whole rail read finished. aria-current
|
|
4651
4844
|
tells a screen reader the same thing. */
|
|
4652
4845
|
function paintRail(step) {
|
|
4653
|
-
var landed = step ===
|
|
4654
|
-
var cur = step ===
|
|
4846
|
+
var landed = step === 13 && !!(live && live.instStatus === 'active');
|
|
4847
|
+
var cur = step === 13 ? 12 : step;
|
|
4655
4848
|
root.querySelectorAll('.steps li').forEach(function (li) {
|
|
4656
4849
|
var n = Number(li.getAttribute('data-step'));
|
|
4657
4850
|
var now = !landed && n === cur;
|
|
@@ -4662,7 +4855,7 @@ summary{min-height:24px;padding:3px 0;}
|
|
|
4662
4855
|
the button role, the tab stop and the data-goto the delegated handler
|
|
4663
4856
|
below reads. The done panel offers none — the project is filed, and
|
|
4664
4857
|
there is nothing behind it to change. */
|
|
4665
|
-
if (step <
|
|
4858
|
+
if (step < 13 && n < cur) {
|
|
4666
4859
|
li.setAttribute('role', 'button');
|
|
4667
4860
|
li.setAttribute('tabindex', '0');
|
|
4668
4861
|
li.setAttribute('data-goto', String(n));
|
|
@@ -4681,11 +4874,11 @@ summary{min-height:24px;padding:3px 0;}
|
|
|
4681
4874
|
paintRail(step);
|
|
4682
4875
|
saveDraft();
|
|
4683
4876
|
/* the done step takes the whole card — the bongo pair steps aside */
|
|
4684
|
-
root.querySelector('.createSplit').classList.toggle('wizDone', step ===
|
|
4877
|
+
root.querySelector('.createSplit').classList.toggle('wizDone', step === 13);
|
|
4685
4878
|
/* the front door (task 1004417): no rail on its two screens, and the fork
|
|
4686
4879
|
takes the whole card for the seed on its plate */
|
|
4687
4880
|
root.querySelector('.card').classList.toggle('wizFront', step === 1 || step === 2);
|
|
4688
|
-
root.querySelector('.createSplit').classList.toggle('wizFork', step === 2);
|
|
4881
|
+
root.querySelector('.createSplit').classList.toggle('wizFork', step === 2 || step === 3);
|
|
4689
4882
|
/* focus moves ONLY on a deliberate step (the hub rule setView already
|
|
4690
4883
|
applies to this view: never on boot, never on a background settle) */
|
|
4691
4884
|
if (moveFocus) {
|
|
@@ -4697,18 +4890,19 @@ summary{min-height:24px;padding:3px 0;}
|
|
|
4697
4890
|
draft's owner with myLogin()'s placeholder) */
|
|
4698
4891
|
/* the picker repaints on entry, not once at boot: the owner can walk back
|
|
4699
4892
|
to the Type step and change the answer the preselect is keyed to */
|
|
4700
|
-
if (step ===
|
|
4701
|
-
if (step === 7)
|
|
4893
|
+
if (step === 3) paintPhysics();
|
|
4894
|
+
if (step === 7) renderModules();
|
|
4895
|
+
if (step === 8) { syncHome(); if (authKnown) ensureRepoAccess(); }
|
|
4702
4896
|
/* a resumed draft can land PAST the Home step with the probe never run —
|
|
4703
4897
|
Create would then file a repo it promised to make but never did */
|
|
4704
|
-
else if (step >
|
|
4898
|
+
else if (step > 8 && step < 13 && authKnown && repoAccess === null) ensureRepoAccess();
|
|
4705
4899
|
/* re-check on every entry, not just on typing: a resumed draft arrives here with
|
|
4706
4900
|
a handle nobody has asked the server about, and a handle free ten minutes ago
|
|
4707
4901
|
may not be now (task 1002898 N10) */
|
|
4708
|
-
if (step ===
|
|
4709
|
-
if (step ===
|
|
4710
|
-
if (step ===
|
|
4711
|
-
if (step ===
|
|
4902
|
+
if (step === 9) { checkSlugAvailable(); renderAddrPanel(); }
|
|
4903
|
+
if (step === 10) { syncAppStep(); syncRenderSetup(); }
|
|
4904
|
+
if (step === 11) renderLook();
|
|
4905
|
+
if (step === 12) renderReview();
|
|
4712
4906
|
}
|
|
4713
4907
|
|
|
4714
4908
|
/* One delegated pair on the rail, so paintRail can add and drop data-goto
|
|
@@ -4821,7 +5015,8 @@ summary{min-height:24px;padding:3px 0;}
|
|
|
4821
5015
|
}
|
|
4822
5016
|
state.teamShape = demoDraft.people > 1 ? 'small-team' : 'solo';
|
|
4823
5017
|
saveDraft();
|
|
4824
|
-
|
|
5018
|
+
/* the name step: a demo skips planet physics (task 1004418) */
|
|
5019
|
+
show(4, true);
|
|
4825
5020
|
});
|
|
4826
5021
|
/* the done panel's invite step names the demo's teammates (task 1004420): the hub
|
|
4827
5022
|
holds no invite of its own, so the founder sends each from the project's own box */
|
|
@@ -4963,7 +5158,7 @@ summary{min-height:24px;padding:3px 0;}
|
|
|
4963
5158
|
/* Skip = go on with whatever is (or isn't) filled in. It deliberately does
|
|
4964
5159
|
NOT erase an answer already given: a visitor who typed a description and
|
|
4965
5160
|
then pressed Skip meant "I'm done here", not "throw that away". */
|
|
4966
|
-
$('skipDetail').addEventListener('click', function () { show(
|
|
5161
|
+
$('skipDetail').addEventListener('click', function () { show(7, true); });
|
|
4967
5162
|
|
|
4968
5163
|
/* ── the module picker (task 1002339, BV1.R20) ──
|
|
4969
5164
|
ONE public read gives the panel both halves it needs: `optional` is the
|
|
@@ -5006,8 +5201,8 @@ summary{min-height:24px;padding:3px 0;}
|
|
|
5006
5201
|
exact dishonesty the About row's "off the public map" clause exists to
|
|
5007
5202
|
prevent, one screen before Create. */
|
|
5008
5203
|
function repaintForBundles() {
|
|
5009
|
-
if (state.step ===
|
|
5010
|
-
else if (state.step ===
|
|
5204
|
+
if (state.step === 7) renderModules();
|
|
5205
|
+
else if (state.step === 12) renderReview();
|
|
5011
5206
|
}
|
|
5012
5207
|
/* The row for the declared type, or null before the read lands / for a type
|
|
5013
5208
|
the table has no row for (including no type at all). */
|
|
@@ -5222,7 +5417,7 @@ summary{min-height:24px;padding:3px 0;}
|
|
|
5222
5417
|
/* Skip = walk past without answering. It does NOT erase a toggle already
|
|
5223
5418
|
made (the About step's rule), and with nothing said it leaves state.modules
|
|
5224
5419
|
null so the server applies the bundle this panel was showing. */
|
|
5225
|
-
$('skipModules').addEventListener('click', function () { show(
|
|
5420
|
+
$('skipModules').addEventListener('click', function () { show(8, true); });
|
|
5226
5421
|
|
|
5227
5422
|
/* ── GitHub-integrated repo picker (adopt) + auto-create (fresh) — task 1002099 / ADR 0143.
|
|
5228
5423
|
Progressive enhancement: probe GET /github/repos once we reach the Home step.
|
|
@@ -5410,9 +5605,340 @@ summary{min-height:24px;padding:3px 0;}
|
|
|
5410
5605
|
saveDraft();
|
|
5411
5606
|
});
|
|
5412
5607
|
|
|
5608
|
+
/* ── planet physics, questions 1 to 4 (task 1004418, BV2.PS07) ──
|
|
5609
|
+
One wizard step with its own inner sequence: 0 account-or-scratch, 1 state,
|
|
5610
|
+
2 geography, 3 ages, 4 entity, and the stop screen. The answers live in
|
|
5611
|
+
state.physics.answers under planet-physics.js's own keys, so the create sends
|
|
5612
|
+
them as `detail` untouched. The vocabularies below are COPIES of that file's
|
|
5613
|
+
(a page cannot require a module), held equal by tests/wizard_physics.mjs. */
|
|
5614
|
+
var PHYS_COUNTRIES = ('AD AE AF AG AI AL AM AO AQ AR AS AT AU AW AX AZ BA BB BD BE BF BG BH BI BJ BL BM BN BO BQ ' +
|
|
5615
|
+
'BR BS BT BV BW BY BZ CA CC CD CF CG CH CI CK CL CM CN CO CR CU CV CW CX CY CZ DE DJ DK DM ' +
|
|
5616
|
+
'DO DZ EC EE EG EH ER ES ET FI FJ FK FM FO FR GA GB GD GE GF GG GH GI GL GM GN GP GQ GR GS ' +
|
|
5617
|
+
'GT GU GW GY HK HM HN HR HT HU ID IE IL IM IN IO IQ IR IS IT JE JM JO JP KE KG KH KI KM KN ' +
|
|
5618
|
+
'KP KR KW KY KZ LA LB LC LI LK LR LS LT LU LV LY MA MC MD ME MF MG MH MK ML MM MN MO MP MQ ' +
|
|
5619
|
+
'MR MS MT MU MV MW MX MY MZ NA NC NE NF NG NI NL NO NP NR NU NZ OM PA PE PF PG PH PK PL PM ' +
|
|
5620
|
+
'PN PR PS PT PW PY QA RE RO RS RU RW SA SB SC SD SE SG SH SI SJ SK SL SM SN SO SR SS ST SV ' +
|
|
5621
|
+
'SX SY SZ TC TD TF TG TH TJ TK TL TM TN TO TR TT TV TW TZ UA UG UM US UY UZ VA VC VE VG VI ' +
|
|
5622
|
+
'VN VU WF WS YE YT ZA ZM ZW').split(' ');
|
|
5623
|
+
var PHYS_REGIONS = {
|
|
5624
|
+
'US-AL': 'Alabama', 'US-AK': 'Alaska', 'US-AZ': 'Arizona', 'US-AR': 'Arkansas', 'US-CA': 'California',
|
|
5625
|
+
'US-CO': 'Colorado', 'US-CT': 'Connecticut', 'US-DE': 'Delaware', 'US-FL': 'Florida', 'US-GA': 'Georgia',
|
|
5626
|
+
'US-HI': 'Hawaii', 'US-ID': 'Idaho', 'US-IL': 'Illinois', 'US-IN': 'Indiana', 'US-IA': 'Iowa',
|
|
5627
|
+
'US-KS': 'Kansas', 'US-KY': 'Kentucky', 'US-LA': 'Louisiana', 'US-ME': 'Maine', 'US-MD': 'Maryland',
|
|
5628
|
+
'US-MA': 'Massachusetts', 'US-MI': 'Michigan', 'US-MN': 'Minnesota', 'US-MS': 'Mississippi', 'US-MO': 'Missouri',
|
|
5629
|
+
'US-MT': 'Montana', 'US-NE': 'Nebraska', 'US-NV': 'Nevada', 'US-NH': 'New Hampshire', 'US-NJ': 'New Jersey',
|
|
5630
|
+
'US-NM': 'New Mexico', 'US-NY': 'New York', 'US-NC': 'North Carolina', 'US-ND': 'North Dakota', 'US-OH': 'Ohio',
|
|
5631
|
+
'US-OK': 'Oklahoma', 'US-OR': 'Oregon', 'US-PA': 'Pennsylvania', 'US-RI': 'Rhode Island', 'US-SC': 'South Carolina',
|
|
5632
|
+
'US-SD': 'South Dakota', 'US-TN': 'Tennessee', 'US-TX': 'Texas', 'US-UT': 'Utah', 'US-VT': 'Vermont',
|
|
5633
|
+
'US-VA': 'Virginia', 'US-WA': 'Washington', 'US-WV': 'West Virginia', 'US-WI': 'Wisconsin', 'US-WY': 'Wyoming',
|
|
5634
|
+
'US-DC': 'District of Columbia', 'US-AS': 'American Samoa', 'US-GU': 'Guam', 'US-MP': 'Northern Mariana Islands',
|
|
5635
|
+
'US-PR': 'Puerto Rico', 'US-UM': 'U.S. Minor Outlying Islands', 'US-VI': 'U.S. Virgin Islands',
|
|
5636
|
+
'CA-AB': 'Alberta', 'CA-BC': 'British Columbia', 'CA-MB': 'Manitoba', 'CA-NB': 'New Brunswick',
|
|
5637
|
+
'CA-NL': 'Newfoundland and Labrador', 'CA-NS': 'Nova Scotia', 'CA-NT': 'Northwest Territories', 'CA-NU': 'Nunavut',
|
|
5638
|
+
'CA-ON': 'Ontario', 'CA-PE': 'Prince Edward Island', 'CA-QC': 'Quebec', 'CA-SK': 'Saskatchewan', 'CA-YT': 'Yukon'
|
|
5639
|
+
};
|
|
5640
|
+
var PHYS_ENTITY_FORMS = ['nonprofit', 'for-profit', 'corporate-division', 'research', 'university-project', 'social-group', 'single-owner-llc', 'private-individual'];
|
|
5641
|
+
/* The core material the entity gives the planet (the direction doc's placeholder
|
|
5642
|
+
art direction): frost for one person, chrome for a group, gold for an
|
|
5643
|
+
organization, obsidian for a nonprofit. */
|
|
5644
|
+
var PHYS_MATERIAL = {
|
|
5645
|
+
'intent-solo': 'frost', 'single-owner-llc': 'frost', 'private-individual': 'frost',
|
|
5646
|
+
'university-project': 'chrome', 'social-group': 'chrome', 'intent-unsure': 'chrome',
|
|
5647
|
+
'intent-company': 'gold', 'for-profit': 'gold', 'corporate-division': 'gold', 'research': 'gold',
|
|
5648
|
+
'intent-nonprofit': 'obsidian', 'nonprofit': 'obsidian'
|
|
5649
|
+
};
|
|
5650
|
+
var PHYS_CORE_WORD = { frost: 'individual', chrome: 'group', gold: 'organization', obsidian: 'nonprofit' };
|
|
5651
|
+
var PHYS_GEO_WORD = { 'us-only': 'us only', 'us-eu': 'us + eu', 'global': 'global', 'not-sure': 'not sure yet' };
|
|
5652
|
+
var PHYS_LAST = 4;
|
|
5653
|
+
var physLimits = [];
|
|
5654
|
+
|
|
5655
|
+
function phys() {
|
|
5656
|
+
if (!state.physics || typeof state.physics !== 'object') state.physics = { q: 0, start: null, answers: {} };
|
|
5657
|
+
if (!state.physics.answers || typeof state.physics.answers !== 'object') state.physics.answers = {};
|
|
5658
|
+
return state.physics;
|
|
5659
|
+
}
|
|
5660
|
+
/* The answers as the create sends them: only what was answered, and the existing
|
|
5661
|
+
work only for an existing planet (the soft-limit table hides it for a new one). */
|
|
5662
|
+
function physDetail() {
|
|
5663
|
+
var a = phys().answers, out = {};
|
|
5664
|
+
['project_state', 'home_country', 'home_region', 'builder_geography', 'minors_on_board', 'entity'].forEach(function (k) {
|
|
5665
|
+
if (a[k] !== undefined && a[k] !== null && a[k] !== '') out[k] = a[k];
|
|
5666
|
+
});
|
|
5667
|
+
if (a.project_state === 'existing' && Array.isArray(a.existing_work) && a.existing_work.length) {
|
|
5668
|
+
out.existing_work = a.existing_work.slice();
|
|
5669
|
+
if (a.main_work && a.existing_work.indexOf(a.main_work) !== -1) out.main_work = a.main_work;
|
|
5670
|
+
}
|
|
5671
|
+
return out;
|
|
5672
|
+
}
|
|
5673
|
+
function createDetail() {
|
|
5674
|
+
var d = physDetail();
|
|
5675
|
+
if (state.teamShape) d.team_shape = state.teamShape;
|
|
5676
|
+
return Object.keys(d).length ? d : undefined;
|
|
5677
|
+
}
|
|
5678
|
+
|
|
5679
|
+
function physFillSelects() {
|
|
5680
|
+
var c = $('physCountry'), r = $('physRegion');
|
|
5681
|
+
if (c.options.length === 1) {
|
|
5682
|
+
var names = null;
|
|
5683
|
+
try { names = new Intl.DisplayNames(['en'], { type: 'region' }); } catch (e) {}
|
|
5684
|
+
PHYS_COUNTRIES.map(function (code) { return { code: code, name: (names && names.of(code)) || code }; })
|
|
5685
|
+
.sort(function (x, y) { return x.name.localeCompare(y.name); })
|
|
5686
|
+
.forEach(function (o) { var opt = document.createElement('option'); opt.value = o.code; opt.textContent = o.name; c.appendChild(opt); });
|
|
5687
|
+
}
|
|
5688
|
+
var a = phys().answers, country = a.home_country || '';
|
|
5689
|
+
c.value = country;
|
|
5690
|
+
while (r.options.length > 1) r.removeChild(r.lastChild);
|
|
5691
|
+
Object.keys(PHYS_REGIONS).filter(function (k) { return k.indexOf(country + '-') === 0; }).forEach(function (k) {
|
|
5692
|
+
var opt = document.createElement('option'); opt.value = k; opt.textContent = PHYS_REGIONS[k]; r.appendChild(opt);
|
|
5693
|
+
});
|
|
5694
|
+
$('physRegionField').hidden = r.options.length === 1;
|
|
5695
|
+
r.value = a.home_region || '';
|
|
5696
|
+
}
|
|
5697
|
+
|
|
5698
|
+
/* The stage: the planet forming from the world's own plates. A seed for a new
|
|
5699
|
+
planet, a formed one for an existing; the core material once the entity is
|
|
5700
|
+
known; a protective ring when young builders are on board. */
|
|
5701
|
+
function physPaintStage() {
|
|
5702
|
+
var p = phys(), a = p.answers;
|
|
5703
|
+
var mat = PHYS_MATERIAL[a.entity] || null;
|
|
5704
|
+
var src = mat && mat !== 'chrome' ? '/assets/world/r3-' + mat + '-blob-cut.webp'
|
|
5705
|
+
: a.project_state === 'existing' ? '/assets/world/r2-chrome-blobs-set-cut.webp'
|
|
5706
|
+
: '/assets/world/r2-chrome-blob-one-cut.webp';
|
|
5707
|
+
var img = $('physPlanet');
|
|
5708
|
+
if (img.getAttribute('src') !== src) img.setAttribute('src', src);
|
|
5709
|
+
img.setAttribute('data-size', String(p.q === 'stop' ? 0 : Math.max(1, Math.min(p.q, PHYS_LAST) + (a.project_state === 'existing' ? 2 : 1))));
|
|
5710
|
+
img.hidden = p.q === 'stop';
|
|
5711
|
+
$('physGuard').hidden = a.minors_on_board !== true;
|
|
5712
|
+
$('physStage').classList.toggle('physStopped', p.q === 'stop');
|
|
5713
|
+
$('physCapN').textContent = p.q === 'stop' ? 'stopped' : (typeof p.q === 'number' ? p.q : 0) + ' of 7';
|
|
5714
|
+
var call = 'physics · the rules it lives by · each answer shapes your planet here';
|
|
5715
|
+
if (p.q === 'stop') call = 'no planet forms · stopped at state · nothing was created';
|
|
5716
|
+
else if (p.q === 4 && mat) call = 'core · ' + PHYS_CORE_WORD[mat] + ' · a ' + mat + ' core';
|
|
5717
|
+
else if (p.q === 3 && a.minors_on_board === true) call = 'protective ring · under 18s on board · the age tiers apply';
|
|
5718
|
+
else if (p.q === 2 && a.home_country) call = 'coordinates · ' + (a.home_region || a.home_country).toLowerCase() + (a.builder_geography ? ' · builders ' + PHYS_GEO_WORD[a.builder_geography] : '');
|
|
5719
|
+
else if (p.q === 1 && a.project_state) call = a.project_state === 'existing' ? 'state · existing · terrain already formed' : 'state · new · a seed: nothing built yet';
|
|
5720
|
+
$('physCallout').textContent = call;
|
|
5721
|
+
var coords = [];
|
|
5722
|
+
if (a.project_state) coords.push('state ' + a.project_state);
|
|
5723
|
+
if (a.home_country) coords.push('home ' + (a.home_region || a.home_country).toLowerCase());
|
|
5724
|
+
if (a.builder_geography) coords.push('builders ' + PHYS_GEO_WORD[a.builder_geography]);
|
|
5725
|
+
if (a.minors_on_board !== undefined && a.minors_on_board !== null) coords.push(a.minors_on_board ? 'ages 13+' : 'ages 18+');
|
|
5726
|
+
if (mat) coords.push('core ' + PHYS_CORE_WORD[mat]);
|
|
5727
|
+
$('physCoords').textContent = coords.join(' · ');
|
|
5728
|
+
}
|
|
5729
|
+
|
|
5730
|
+
/* The soft-limit table's verdicts (spec D6): an option it hides is hidden and
|
|
5731
|
+
one it greys is disabled, each with its reason beside it. */
|
|
5732
|
+
function physApplyLimits() {
|
|
5733
|
+
root.querySelectorAll('#panel-physics [data-why]').forEach(function (el) { el.hidden = true; el.textContent = ''; });
|
|
5734
|
+
root.querySelectorAll('#panel-physics [data-limit-grey]').forEach(function (el) { el.removeAttribute('data-limit-grey'); el.disabled = false; });
|
|
5735
|
+
physLimits.forEach(function (l) {
|
|
5736
|
+
var key = String(l.option || '');
|
|
5737
|
+
var why = root.querySelector('#panel-physics [data-why="' + key + '"]');
|
|
5738
|
+
if (why && l.reason) { why.textContent = l.reason; why.hidden = false; }
|
|
5739
|
+
if (l.effect === 'grey') {
|
|
5740
|
+
var parts = key.split(':');
|
|
5741
|
+
root.querySelectorAll('#panel-physics [data-phys="' + parts[0] + '"][data-val="' + (parts[1] || '') + '"]').forEach(function (b) {
|
|
5742
|
+
b.disabled = true; b.setAttribute('data-limit-grey', '1'); b.title = l.reason || '';
|
|
5743
|
+
});
|
|
5744
|
+
}
|
|
5745
|
+
});
|
|
5746
|
+
}
|
|
5747
|
+
|
|
5748
|
+
function paintPhysics() {
|
|
5749
|
+
var p = phys(), a = p.answers;
|
|
5750
|
+
root.querySelectorAll('#panel-physics .physQ').forEach(function (el) {
|
|
5751
|
+
el.hidden = String(el.getAttribute('data-q')) !== String(p.q);
|
|
5752
|
+
});
|
|
5753
|
+
root.querySelectorAll('#physRail li').forEach(function (li) {
|
|
5754
|
+
var n = Number(li.getAttribute('data-q'));
|
|
5755
|
+
li.classList.toggle('now', n === p.q);
|
|
5756
|
+
li.classList.toggle('done', !!n && typeof p.q === 'number' && n < p.q);
|
|
5757
|
+
});
|
|
5758
|
+
$('physRail').hidden = p.q === 'stop' || p.q === 0;
|
|
5759
|
+
$('physNav').hidden = p.q === 'stop';
|
|
5760
|
+
root.querySelectorAll('[data-phys-start]').forEach(function (b) { b.setAttribute('aria-pressed', String(b.getAttribute('data-phys-start') === p.start)); });
|
|
5761
|
+
root.querySelectorAll('#panel-physics [data-phys]').forEach(function (b) {
|
|
5762
|
+
var v = a[b.getAttribute('data-phys')];
|
|
5763
|
+
b.setAttribute('aria-pressed', String(v !== undefined && v !== null && String(v) === b.getAttribute('data-val')));
|
|
5764
|
+
});
|
|
5765
|
+
var existing = a.project_state === 'existing';
|
|
5766
|
+
$('physExisting').hidden = !existing;
|
|
5767
|
+
var works = Array.isArray(a.existing_work) ? a.existing_work : [];
|
|
5768
|
+
root.querySelectorAll('#physExisting [data-work]').forEach(function (cb) { cb.checked = works.indexOf(cb.getAttribute('data-work')) !== -1; });
|
|
5769
|
+
root.querySelectorAll('#physExisting input[name="physMain"]').forEach(function (r) {
|
|
5770
|
+
r.checked = a.main_work === r.value;
|
|
5771
|
+
r.disabled = works.indexOf(r.value) === -1;
|
|
5772
|
+
});
|
|
5773
|
+
$('physDesc').value = state.description || '';
|
|
5774
|
+
$('physAges').hidden = a.minors_on_board !== true;
|
|
5775
|
+
var forms = existing || PHYS_ENTITY_FORMS.indexOf(a.entity) !== -1 || p.entityForms === true;
|
|
5776
|
+
$('physForms').hidden = !forms;
|
|
5777
|
+
$('physIntent').hidden = forms;
|
|
5778
|
+
if (p.q === 0 && !physAccountLoaded) { physAccountLoaded = true; physLoadAccount(); }
|
|
5779
|
+
physFillSelects();
|
|
5780
|
+
physApplyLimits();
|
|
5781
|
+
physPaintStage();
|
|
5782
|
+
}
|
|
5783
|
+
|
|
5784
|
+
function physHint(msg) {
|
|
5785
|
+
$('h-phys').textContent = msg || ' ';
|
|
5786
|
+
$('h-phys').className = msg ? 'hint err' : 'hint';
|
|
5787
|
+
}
|
|
5788
|
+
function physCheck() {
|
|
5789
|
+
return fetch(API + '/provisioning/physics-check', {
|
|
5790
|
+
method: 'POST', credentials: 'same-origin', headers: { 'Content-Type': 'application/json' },
|
|
5791
|
+
body: JSON.stringify({ description: String(state.description || '').trim() || undefined, detail: physDetail() })
|
|
5792
|
+
}).then(function (r) { return r.ok ? r.json() : null; }).catch(function () { return null; });
|
|
5793
|
+
}
|
|
5794
|
+
function physGo(q) {
|
|
5795
|
+
phys().q = q;
|
|
5796
|
+
saveDraft();
|
|
5797
|
+
paintPhysics();
|
|
5798
|
+
var h = root.querySelector('#panel-physics .physQ[data-q="' + q + '"] h1');
|
|
5799
|
+
if (h) { h.setAttribute('tabindex', '-1'); h.focus({ preventScroll: false }); }
|
|
5800
|
+
}
|
|
5801
|
+
|
|
5802
|
+
/* Continue: check this question, then move on. Question 1 asks the server's
|
|
5803
|
+
screen first — a description it stops ends here, before anything exists. */
|
|
5804
|
+
var physBusy = false;
|
|
5805
|
+
function physAdvance() {
|
|
5806
|
+
var p = phys(), a = p.answers;
|
|
5807
|
+
physHint('');
|
|
5808
|
+
if (p.q === 0) { if (!p.start) p.start = 'scratch'; physGo(1); return false; }
|
|
5809
|
+
if (p.q === 1) {
|
|
5810
|
+
if (!a.project_state) { physHint('Pick new or existing to go on.'); return false; }
|
|
5811
|
+
if (a.project_state === 'existing') {
|
|
5812
|
+
var works = Array.isArray(a.existing_work) ? a.existing_work : [];
|
|
5813
|
+
if (!works.length) { physHint('Pick what already exists, then your main one.'); return false; }
|
|
5814
|
+
if (works.indexOf(a.main_work) === -1) { physHint('Mark which of them is your main one.'); return false; }
|
|
5815
|
+
}
|
|
5816
|
+
if (physBusy) return false;
|
|
5817
|
+
physBusy = true;
|
|
5818
|
+
physCheck().then(function (res) {
|
|
5819
|
+
physBusy = false;
|
|
5820
|
+
if (res && res.stop) { $('physStopMsg').textContent = res.message || ''; physGo('stop'); return; }
|
|
5821
|
+
physLimits = (res && res.soft_limits && res.soft_limits.limits) || [];
|
|
5822
|
+
physGo(2);
|
|
5823
|
+
});
|
|
5824
|
+
return false;
|
|
5825
|
+
}
|
|
5826
|
+
if (p.q === 2) {
|
|
5827
|
+
if (!a.home_country) { physHint('Pick your country.'); return false; }
|
|
5828
|
+
if (!a.builder_geography) { physHint('Say where you expect builders to be. Not sure yet is a fine answer.'); return false; }
|
|
5829
|
+
physGo(3); return false;
|
|
5830
|
+
}
|
|
5831
|
+
if (p.q === 3) {
|
|
5832
|
+
if (a.minors_on_board !== true && a.minors_on_board !== false) { physHint('Answer yes or no to go on.'); return false; }
|
|
5833
|
+
physGo(4); return false;
|
|
5834
|
+
}
|
|
5835
|
+
if (p.q === 4) {
|
|
5836
|
+
if (!a.entity) { physHint('Pick the one that fits best. Don’t know yet is a fine answer.'); return false; }
|
|
5837
|
+
physCheck().then(function (res) { physLimits = (res && res.soft_limits && res.soft_limits.limits) || []; });
|
|
5838
|
+
show(4, true);
|
|
5839
|
+
return false;
|
|
5840
|
+
}
|
|
5841
|
+
return false;
|
|
5842
|
+
}
|
|
5843
|
+
|
|
5844
|
+
$('physBack').addEventListener('click', function () {
|
|
5845
|
+
var p = phys();
|
|
5846
|
+
physHint('');
|
|
5847
|
+
if (typeof p.q === 'number' && p.q > 0) physGo(p.q - 1); else show(2, true);
|
|
5848
|
+
});
|
|
5849
|
+
$('physStartOver').addEventListener('click', function () {
|
|
5850
|
+
state.description = '';
|
|
5851
|
+
if ($('f-desc')) $('f-desc').value = '';
|
|
5852
|
+
phys().answers = {};
|
|
5853
|
+
physGo(1);
|
|
5854
|
+
});
|
|
5855
|
+
root.querySelectorAll('[data-phys-start]').forEach(function (b) {
|
|
5856
|
+
b.addEventListener('click', function () {
|
|
5857
|
+
var p = phys();
|
|
5858
|
+
p.start = b.getAttribute('data-phys-start');
|
|
5859
|
+
if (p.start === 'account' && physAccountAnswers) {
|
|
5860
|
+
Object.keys(physAccountAnswers).forEach(function (k) { p.answers[k] = physAccountAnswers[k]; });
|
|
5861
|
+
}
|
|
5862
|
+
saveDraft(); paintPhysics();
|
|
5863
|
+
});
|
|
5864
|
+
});
|
|
5865
|
+
root.querySelectorAll('#panel-physics [data-phys]').forEach(function (b) {
|
|
5866
|
+
b.addEventListener('click', function () {
|
|
5867
|
+
var k = b.getAttribute('data-phys'), raw = b.getAttribute('data-val');
|
|
5868
|
+
var v = raw === 'true' ? true : raw === 'false' ? false : raw;
|
|
5869
|
+
var a = phys().answers;
|
|
5870
|
+
a[k] = a[k] === v ? null : v; /* a second click un-says it, like the team pills */
|
|
5871
|
+
if (k === 'project_state' && a[k] !== 'existing') { delete a.existing_work; delete a.main_work; }
|
|
5872
|
+
physHint(''); saveDraft(); paintPhysics();
|
|
5873
|
+
});
|
|
5874
|
+
});
|
|
5875
|
+
root.querySelectorAll('#physExisting [data-work]').forEach(function (cb) {
|
|
5876
|
+
cb.addEventListener('change', function () {
|
|
5877
|
+
var a = phys().answers, w = cb.getAttribute('data-work');
|
|
5878
|
+
var list = Array.isArray(a.existing_work) ? a.existing_work.slice() : [];
|
|
5879
|
+
if (cb.checked && list.indexOf(w) === -1) list.push(w);
|
|
5880
|
+
if (!cb.checked) list = list.filter(function (x) { return x !== w; });
|
|
5881
|
+
a.existing_work = list;
|
|
5882
|
+
if (list.length === 1) a.main_work = list[0];
|
|
5883
|
+
if (list.indexOf(a.main_work) === -1) a.main_work = list.length ? list[0] : null;
|
|
5884
|
+
saveDraft(); paintPhysics();
|
|
5885
|
+
});
|
|
5886
|
+
});
|
|
5887
|
+
root.querySelectorAll('#physExisting input[name="physMain"]').forEach(function (r) {
|
|
5888
|
+
r.addEventListener('change', function () { if (r.checked) { phys().answers.main_work = r.value; saveDraft(); paintPhysics(); } });
|
|
5889
|
+
});
|
|
5890
|
+
$('physDesc').addEventListener('input', function () {
|
|
5891
|
+
state.description = $('physDesc').value;
|
|
5892
|
+
if ($('f-desc')) $('f-desc').value = state.description;
|
|
5893
|
+
saveDraft();
|
|
5894
|
+
});
|
|
5895
|
+
$('physCountry').addEventListener('change', function () {
|
|
5896
|
+
var a = phys().answers;
|
|
5897
|
+
a.home_country = $('physCountry').value || null;
|
|
5898
|
+
if (a.home_region && a.home_region.indexOf((a.home_country || '') + '-') !== 0) a.home_region = null;
|
|
5899
|
+
saveDraft(); paintPhysics();
|
|
5900
|
+
});
|
|
5901
|
+
$('physRegion').addEventListener('change', function () { phys().answers.home_region = $('physRegion').value || null; saveDraft(); physPaintStage(); });
|
|
5902
|
+
$('physHaveEntity').addEventListener('click', function () { phys().entityForms = true; saveDraft(); paintPhysics(); });
|
|
5903
|
+
$('physNoEntity').addEventListener('click', function () {
|
|
5904
|
+
var p = phys();
|
|
5905
|
+
p.entityForms = false;
|
|
5906
|
+
if (PHYS_ENTITY_FORMS.indexOf(p.answers.entity) !== -1) p.answers.entity = null;
|
|
5907
|
+
saveDraft(); paintPhysics();
|
|
5908
|
+
});
|
|
5909
|
+
|
|
5910
|
+
/* Auto-fill: the answers this account already gave on its most recent project —
|
|
5911
|
+
the only details the platform holds about a founder. With none, the door says so
|
|
5912
|
+
and stays shut. The state of the planet is never copied: it is this project's. */
|
|
5913
|
+
var physAccountAnswers = null;
|
|
5914
|
+
var physAccountLoaded = false;
|
|
5915
|
+
function physLoadAccount() {
|
|
5916
|
+
return fetch(API + '/provisioning/instances', { credentials: 'same-origin' })
|
|
5917
|
+
.then(function (r) { return r.ok ? r.json() : null; })
|
|
5918
|
+
.then(function (d) {
|
|
5919
|
+
var list = (d && (d.instances || d)) || [];
|
|
5920
|
+
if (!Array.isArray(list)) list = [];
|
|
5921
|
+
var withDetail = list.filter(function (i) { return i && i.detail && typeof i.detail === 'object'; })
|
|
5922
|
+
.sort(function (x, y) { return String(y.created_at || '').localeCompare(String(x.created_at || '')); })[0];
|
|
5923
|
+
var pick = {};
|
|
5924
|
+
if (withDetail) ['home_country', 'home_region', 'builder_geography', 'minors_on_board', 'entity'].forEach(function (k) {
|
|
5925
|
+
if (withDetail.detail[k] !== undefined && withDetail.detail[k] !== null) pick[k] = withDetail.detail[k];
|
|
5926
|
+
});
|
|
5927
|
+
physAccountAnswers = Object.keys(pick).length ? pick : null;
|
|
5928
|
+
$('physFromAccount').disabled = !physAccountAnswers;
|
|
5929
|
+
var why = $('physAccountWhy');
|
|
5930
|
+
why.hidden = !!physAccountAnswers;
|
|
5931
|
+
why.textContent = physAccountAnswers ? '' : 'Nothing to fill from yet: your account has no other project with these answers.';
|
|
5932
|
+
})
|
|
5933
|
+
.catch(function () {});
|
|
5934
|
+
}
|
|
5935
|
+
|
|
5413
5936
|
/* per-panel validation on Next */
|
|
5414
5937
|
function validateStep(step) {
|
|
5415
|
-
if (step ===
|
|
5938
|
+
if (step === 10) return validateRender();
|
|
5939
|
+
/* planet physics (task 1004418): Continue walks the questions inside the step,
|
|
5940
|
+
and only the last one moves the wizard on, so this never says yes itself */
|
|
5941
|
+
if (step === 3) return physAdvance();
|
|
5416
5942
|
/* the fork's own door is "Begin planet creation": a real project, not the demo */
|
|
5417
5943
|
if (step === 2) { state.demo = null; return true; }
|
|
5418
5944
|
/* the front door's one tick (task 1004417): nothing past it until it is given */
|
|
@@ -5424,11 +5950,11 @@ summary{min-height:24px;padding:3px 0;}
|
|
|
5424
5950
|
}
|
|
5425
5951
|
return true;
|
|
5426
5952
|
}
|
|
5427
|
-
if (step ===
|
|
5953
|
+
if (step === 4) {
|
|
5428
5954
|
if (!state.name.trim()) { $('h-name').textContent = 'Give it a name to start.'; $('h-name').className = 'hint err'; return false; }
|
|
5429
5955
|
return true;
|
|
5430
5956
|
}
|
|
5431
|
-
if (step ===
|
|
5957
|
+
if (step === 5) {
|
|
5432
5958
|
if (!state.projType) {
|
|
5433
5959
|
$('h-projtype').textContent = 'Pick one — Not Sure is a fine answer.';
|
|
5434
5960
|
$('h-projtype').className = 'hint err';
|
|
@@ -5436,10 +5962,10 @@ summary{min-height:24px;padding:3px 0;}
|
|
|
5436
5962
|
}
|
|
5437
5963
|
return true;
|
|
5438
5964
|
}
|
|
5439
|
-
/* steps
|
|
5965
|
+
/* steps 6 (About) and 7 (Modules) have no clause: they are the optional
|
|
5440
5966
|
ones, and Next past an empty answer is the whole point (tasks 1002334,
|
|
5441
5967
|
1002339). Step 2 (the fork) has none either: its doors are the answer. */
|
|
5442
|
-
if (step ===
|
|
5968
|
+
if (step === 8) {
|
|
5443
5969
|
var homeErr = function (msg) { $('h-home').textContent = msg; $('h-home').className = 'hint err'; return false; };
|
|
5444
5970
|
if (repoAccess === 'need-connect') return homeErr('Allow GitHub repo access to pick or create your repository — or choose “enter it manually”.');
|
|
5445
5971
|
if (repoAccess === true && state.mode !== 'adopt') {
|
|
@@ -5454,7 +5980,7 @@ summary{min-height:24px;padding:3px 0;}
|
|
|
5454
5980
|
$('h-home').innerHTML = ' '; $('h-home').className = 'hint';
|
|
5455
5981
|
return true;
|
|
5456
5982
|
}
|
|
5457
|
-
if (step ===
|
|
5983
|
+
if (step === 9) {
|
|
5458
5984
|
if (!validSlug(state.slug)) {
|
|
5459
5985
|
$('h-slug').textContent = '2–40 lowercase letters, numbers, or dashes; no leading/trailing/double dash.';
|
|
5460
5986
|
$('h-slug').className = 'hint err'; $('f-slug').classList.add('bad');
|
|
@@ -5591,7 +6117,7 @@ summary{min-height:24px;padding:3px 0;}
|
|
|
5591
6117
|
: 'Once the project is up, we create your app on your Render account. Your key is used once, then thrown away.';
|
|
5592
6118
|
/* then the app's own progress, from the same read the project's page uses (task 1004353) */
|
|
5593
6119
|
var box = $('doneApp');
|
|
5594
|
-
if (box) watchApp(instanceId, box, function () { return state.step ===
|
|
6120
|
+
if (box) watchApp(instanceId, box, function () { return state.step === 13; }, 5000);
|
|
5595
6121
|
});
|
|
5596
6122
|
}).catch(function (err) {
|
|
5597
6123
|
note.className = 'hint err';
|
|
@@ -5766,7 +6292,7 @@ summary{min-height:24px;padding:3px 0;}
|
|
|
5766
6292
|
because absent means SKIPPED and an empty string would read as an
|
|
5767
6293
|
answered-but-blank description to the publish gate */
|
|
5768
6294
|
description: String(state.description || '').trim() || undefined,
|
|
5769
|
-
detail:
|
|
6295
|
+
detail: createDetail(),
|
|
5770
6296
|
/* the picker's answer (task 1002339) — omitted while unanswered, and
|
|
5771
6297
|
the server then applies the SAME starter bundle the panel showed,
|
|
5772
6298
|
so a skip and an accept land the same modules */
|
|
@@ -5820,7 +6346,7 @@ summary{min-height:24px;padding:3px 0;}
|
|
|
5820
6346
|
sessionStorage.removeItem(DRAFT_KEY);
|
|
5821
6347
|
} catch (e) {}
|
|
5822
6348
|
renderDone();
|
|
5823
|
-
show(
|
|
6349
|
+
show(13, true);
|
|
5824
6350
|
sendRenderSetup(data.instance && data.instance.id); // the key rides the new project's own setup run (task 1004352)
|
|
5825
6351
|
sendLookSetup(data.instance && data.instance.id); // the look + logo, like the Render key: right after Create (task 1004421)
|
|
5826
6352
|
startProgress(data.instance && data.instance.id);
|
|
@@ -5830,7 +6356,7 @@ summary{min-height:24px;padding:3px 0;}
|
|
|
5830
6356
|
if (err && err.gotoHome) {
|
|
5831
6357
|
/* A repo-creation problem (name taken / reconnect) — bounce back to the Home
|
|
5832
6358
|
step with the reason, so the user fixes it where the repo is chosen. */
|
|
5833
|
-
show(
|
|
6359
|
+
show(8, true);
|
|
5834
6360
|
$('h-home').textContent = err.homeMsg || 'Please revisit the repository step.';
|
|
5835
6361
|
$('h-home').className = 'hint err';
|
|
5836
6362
|
return;
|
|
@@ -6398,7 +6924,7 @@ summary{min-height:24px;padding:3px 0;}
|
|
|
6398
6924
|
5s tick never clobbers an open dropdown or mid-flight button) */
|
|
6399
6925
|
if (inst && inst.status !== live.instStatus) {
|
|
6400
6926
|
live.instStatus = inst.status; renderSteps();
|
|
6401
|
-
if (state.step ===
|
|
6927
|
+
if (state.step === 13) paintRail(13); /* the rail finishes only when the project answers */
|
|
6402
6928
|
}
|
|
6403
6929
|
var terminal = renderProgress(inst);
|
|
6404
6930
|
if (!terminal) pollTimer = setTimeout(tick, 5000);
|
|
@@ -6438,7 +6964,7 @@ summary{min-height:24px;padding:3px 0;}
|
|
|
6438
6964
|
is three-valued and null is its "nothing said" sentinel; leaving the key out
|
|
6439
6965
|
left it UNDEFINED, which is not null — so pickedModules() reached .slice()
|
|
6440
6966
|
on it and the second project's Modules step threw. */
|
|
6441
|
-
state = { step: 1, name: '', projType: null, description: '', teamShape: null, modules: null, mode: 'greenfield', owner: '', ownerTouched: false, repo: '', repoTouched: false, slug: '', slugTouched: false, domain: '', noAddress: false, appPlatform: 'later', demo: null, look: null, termsAck: false };
|
|
6967
|
+
state = { step: 1, name: '', projType: null, description: '', teamShape: null, modules: null, mode: 'greenfield', owner: '', ownerTouched: false, repo: '', repoTouched: false, slug: '', slugTouched: false, domain: '', noAddress: false, appPlatform: 'later', physics: null, demo: null, look: null, termsAck: false };
|
|
6442
6968
|
$('newName').value = ''; $('f-owner').value = ''; $('f-repo').value = ''; $('f-slug').value = ''; $('f-domain').value = '';
|
|
6443
6969
|
$('f-noaddr').checked = false; $('f-desc').value = '';
|
|
6444
6970
|
/* Re-seed the owner from the signed-in account for the next project. */
|
|
@@ -6517,7 +7043,7 @@ summary{min-height:24px;padding:3px 0;}
|
|
|
6517
7043
|
if (focus && !resumeIntent) {
|
|
6518
7044
|
var draft = null;
|
|
6519
7045
|
try { draft = JSON.parse(sessionStorage.getItem(DRAFT_KEY) || 'null'); } catch (e) {}
|
|
6520
|
-
var at = draft && draft.step >= 1 && draft.step <=
|
|
7046
|
+
var at = draft && draft.step >= 1 && draft.step <= 12 ? draft.step : 0;
|
|
6521
7047
|
if (!at) { resetForNewProject(); at = 1; }
|
|
6522
7048
|
paintResumeOffer(created);
|
|
6523
7049
|
/* step 1's own focus target is its one control, the terms tick, not the
|
|
@@ -6541,7 +7067,7 @@ summary{min-height:24px;padding:3px 0;}
|
|
|
6541
7067
|
manifestState = created.manifest_state; manifestPending = true;
|
|
6542
7068
|
}
|
|
6543
7069
|
renderDone();
|
|
6544
|
-
show(
|
|
7070
|
+
show(13, !!focus);
|
|
6545
7071
|
startProgress(created.id);
|
|
6546
7072
|
resumePolls();
|
|
6547
7073
|
}
|
|
@@ -6558,7 +7084,7 @@ summary{min-height:24px;padding:3px 0;}
|
|
|
6558
7084
|
/* before identity settles, never render past step 1 (the terms, since task
|
|
6559
7085
|
1004417): deeper steps carry authenticated side effects (the Home-step repo
|
|
6560
7086
|
probe), and onAuth() re-enters to the real draft step the moment /me answers */
|
|
6561
|
-
var step = authKnown && state.step >= 1 && state.step <=
|
|
7087
|
+
var step = authKnown && state.step >= 1 && state.step <= 12 ? state.step : 1;
|
|
6562
7088
|
if (step === 1) {
|
|
6563
7089
|
/* Pre-auth, step 1 is a PLACEHOLDER, not where the visitor is — but show()
|
|
6564
7090
|
persists whatever step it renders, so it used to overwrite the draft's real
|
|
@@ -6567,7 +7093,7 @@ summary{min-height:24px;padding:3px 0;}
|
|
|
6567
7093
|
step back after rendering the placeholder, in memory AND in the draft. */
|
|
6568
7094
|
var resumeStep = state.step;
|
|
6569
7095
|
show(1, false);
|
|
6570
|
-
if (!authKnown && resumeStep >= 1 && resumeStep <=
|
|
7096
|
+
if (!authKnown && resumeStep >= 1 && resumeStep <= 12) { state.step = resumeStep; saveDraft(); }
|
|
6571
7097
|
if (focus) $('termsAck').focus();
|
|
6572
7098
|
} else {
|
|
6573
7099
|
show(step, !!focus);
|