Skip to content

Commit b33d32e

Browse files
committed
Back Toolbox status and votes with DB state - PR_26160_057-toolbox-db-status-vote-restore
1 parent d8c3bc6 commit b33d32e

12 files changed

Lines changed: 468 additions & 142 deletions

admin/tool-votes.html

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,15 +42,22 @@ <h1>Tool Votes</h1>
4242
<div class="kicker">Shared Toolbox Data</div>
4343
<h2>Vote Review</h2>
4444
</div>
45-
<p>Vote totals are read from the server API data source used by Toolbox tiles.</p>
45+
<p>Vote totals and order values are read from the server API data source used by Toolbox tiles.</p>
4646
<p class="status" role="status" data-toolbox-votes-status>Loading Toolbox vote totals.</p>
47+
<div class="content-cluster" aria-label="Selected Toolbox vote item">
48+
<span class="pill">Selected Order: <span data-toolbox-votes-selected-order>None</span></span>
49+
<span class="pill">Selected Group: <span data-toolbox-votes-selected-group>None</span></span>
50+
<span class="pill">Selected Path: <span data-toolbox-votes-selected-path>None</span></span>
51+
</div>
4752
<div class="table-wrapper">
4853
<table class="data-table" aria-label="Toolbox vote totals">
4954
<caption>Toolbox Vote Totals</caption>
5055
<thead>
5156
<tr>
5257
<th scope="col">Tool</th>
58+
<th scope="col">Order</th>
5359
<th scope="col">Group</th>
60+
<th scope="col">Path</th>
5461
<th scope="col">State</th>
5562
<th scope="col">Up</th>
5663
<th scope="col">Down</th>

admin/tool-votes.js

Lines changed: 78 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,16 @@
1-
import { readToolboxVoteSnapshot } from "../src/engine/api/toolbox-votes-api-client.js";
1+
import {
2+
readToolboxVoteSnapshot,
3+
updateToolboxVoteOrder,
4+
} from "../src/engine/api/toolbox-votes-api-client.js";
25

36
const status = document.querySelector("[data-toolbox-votes-status]");
47
const body = document.querySelector("[data-toolbox-votes-body]");
8+
const selectedOrder = document.querySelector("[data-toolbox-votes-selected-order]");
9+
const selectedGroup = document.querySelector("[data-toolbox-votes-selected-group]");
10+
const selectedPath = document.querySelector("[data-toolbox-votes-selected-path]");
11+
12+
let selectedToolId = "";
13+
let snapshotRows = [];
514

615
function setStatus(message) {
716
if (status) {
@@ -11,47 +20,110 @@ function setStatus(message) {
1120

1221
function tableCell(value) {
1322
const cell = document.createElement("td");
14-
cell.textContent = String(value || "");
23+
cell.textContent = value === null || value === undefined ? "" : String(value);
24+
return cell;
25+
}
26+
27+
function setSelectedDetails(voteRow) {
28+
if (selectedOrder) {
29+
selectedOrder.textContent = voteRow ? String(voteRow.order) : "None";
30+
}
31+
if (selectedGroup) {
32+
selectedGroup.textContent = voteRow?.group || "None";
33+
}
34+
if (selectedPath) {
35+
selectedPath.textContent = voteRow?.path || "None";
36+
}
37+
}
38+
39+
function selectRow(toolId) {
40+
selectedToolId = String(toolId || "");
41+
const selectedRow = snapshotRows.find((row) => row.toolId === selectedToolId);
42+
setSelectedDetails(selectedRow);
43+
body?.querySelectorAll("tr[data-toolbox-votes-tool-id]").forEach((row) => {
44+
row.setAttribute("aria-selected", String(row.dataset.toolboxVotesToolId === selectedToolId));
45+
});
46+
}
47+
48+
function orderCell(voteRow) {
49+
const cell = document.createElement("td");
50+
const input = document.createElement("input");
51+
input.type = "number";
52+
input.min = "0";
53+
input.step = "1";
54+
input.value = String(voteRow.order);
55+
input.dataset.toolboxVotesOrderInput = voteRow.toolId;
56+
input.setAttribute("aria-label", `Order for ${voteRow.toolName}`);
57+
input.addEventListener("change", () => {
58+
updateOrder(voteRow, input.value);
59+
});
60+
input.addEventListener("focus", () => {
61+
selectRow(voteRow.toolId);
62+
});
63+
cell.append(input);
1564
return cell;
1665
}
1766

1867
function renderRows(rows) {
1968
if (!body) {
2069
return;
2170
}
71+
snapshotRows = rows;
2272
if (!rows.length) {
2373
const row = document.createElement("tr");
2474
const cell = document.createElement("td");
25-
cell.colSpan = 6;
75+
cell.colSpan = 8;
2676
cell.textContent = "No Toolbox vote rows are available.";
2777
row.append(cell);
2878
body.replaceChildren(row);
79+
setSelectedDetails(null);
2980
return;
3081
}
3182

3283
body.replaceChildren(...rows.map((voteRow) => {
3384
const row = document.createElement("tr");
3485
row.dataset.toolboxVotesToolId = voteRow.toolId;
86+
row.addEventListener("click", () => {
87+
selectRow(voteRow.toolId);
88+
});
3589
row.append(
3690
tableCell(voteRow.toolName),
91+
orderCell(voteRow),
3792
tableCell(voteRow.group),
93+
tableCell(voteRow.path),
3894
tableCell(voteRow.releaseChannelLabel),
3995
tableCell(voteRow.up),
4096
tableCell(voteRow.down),
4197
tableCell(voteRow.currentUserVote || "None"),
4298
);
4399
return row;
44100
}));
101+
102+
selectRow(selectedToolId || rows[0].toolId);
103+
}
104+
105+
function renderSnapshot(snapshot, message) {
106+
renderRows(snapshot.rows || []);
107+
setStatus(message || `Showing Toolbox vote totals for ${snapshot.currentUserName || "current session"}.`);
108+
}
109+
110+
function updateOrder(voteRow, value) {
111+
try {
112+
const snapshot = updateToolboxVoteOrder(voteRow.toolId, Number(value));
113+
renderSnapshot(snapshot, `${voteRow.toolName} order updated to ${Number(value)}.`);
114+
selectRow(voteRow.toolId);
115+
} catch (error) {
116+
const message = error instanceof Error ? error.message : String(error || "Toolbox vote order unavailable.");
117+
setStatus(`Toolbox vote order could not be updated. ${message}`);
118+
}
45119
}
46120

47121
function renderToolboxVotes() {
48122
if (window.GameFoundrySessionGuard?.blocked) {
49123
return;
50124
}
51125
try {
52-
const snapshot = readToolboxVoteSnapshot();
53-
renderRows(snapshot.rows || []);
54-
setStatus(`Showing Toolbox vote totals for ${snapshot.currentUserName || "current session"}.`);
126+
renderSnapshot(readToolboxVoteSnapshot());
55127
} catch (error) {
56128
const message = error instanceof Error ? error.message : String(error || "Toolbox votes unavailable.");
57129
renderRows([]);
@@ -60,4 +132,3 @@ function renderToolboxVotes() {
60132
}
61133

62134
renderToolboxVotes();
63-

docs_build/dev/reports/coverage_changed_js_guardrail.txt

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,17 @@ Missing changed runtime JS files are WARN, not FAIL.
66
Source: Playwright/Chromium built-in V8 coverage from the active Playwright run.
77

88
Changed runtime JS files considered:
9+
(0%) src/dev-runtime/guest-seeds/tool-state-samples.js - WARNING: changed runtime JS file was not collected by Playwright V8 coverage; advisory only
10+
(0%) src/dev-runtime/persistence/mock-db-store.js - WARNING: changed runtime JS file was not collected by Playwright V8 coverage; advisory only
911
(0%) src/dev-runtime/server/mock-api-router.mjs - WARNING: changed runtime JS file was not collected by Playwright V8 coverage; advisory only
1012
(0%) toolbox/toolRegistry.js - WARNING: changed runtime JS file was not collected by Playwright V8 coverage; advisory only
11-
(65%) assets/theme-v2/js/gamefoundry-partials.js - executed lines 547/547; executed functions 30/46
12-
(67%) src/engine/api/toolbox-votes-api-client.js - executed lines 19/19; executed functions 2/3
13-
(75%) toolbox/tools-page-accordions.js - executed lines 1067/1067; executed functions 78/104
14-
(93%) assets/theme-v2/js/tool-display-mode.js - executed lines 209/209; executed functions 13/14
13+
(77%) assets/theme-v2/js/gamefoundry-partials.js - executed lines 547/547; executed functions 37/48
14+
(96%) toolbox/tools-page-accordions.js - executed lines 1033/1033; executed functions 108/113
15+
(100%) admin/tool-votes.js - executed lines 120/120; executed functions 16/16
16+
(100%) src/engine/api/toolbox-votes-api-client.js - executed lines 28/28; executed functions 4/4
1517

1618
Guardrail warnings:
19+
(0%) src/dev-runtime/guest-seeds/tool-state-samples.js - WARNING: changed runtime JS file missing from coverage; advisory only
20+
(0%) src/dev-runtime/persistence/mock-db-store.js - WARNING: changed runtime JS file missing from coverage; advisory only
1721
(0%) src/dev-runtime/server/mock-api-router.mjs - WARNING: changed runtime JS file missing from coverage; advisory only
1822
(0%) toolbox/toolRegistry.js - WARNING: changed runtime JS file missing from coverage; advisory only

docs_build/dev/reports/playwright_v8_coverage_report.txt

Lines changed: 30 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -12,43 +12,51 @@ Note: entry percentages use function coverage when available, otherwise line cov
1212
Note: coverage entries are aggregated across every page/tool where coverageReporter.start(page) and coverageReporter.stop(page) ran.
1313

1414
Exercised tool entry points detected:
15-
(80%) Toolbox Index - exercised 8 runtime JS files
15+
(68%) Toolbox Index - exercised 9 runtime JS files
1616
(0%) Tool Template V2 - not exercised by this Playwright run
17-
(72%) Theme V2 Shared JS - exercised 2 runtime JS files
17+
(74%) Theme V2 Shared JS - exercised 2 runtime JS files
1818

1919
Changed runtime JS files covered:
20+
(0%) src/dev-runtime/guest-seeds/tool-state-samples.js - WARNING: changed runtime JS file was not collected by Playwright V8 coverage; advisory only
21+
(0%) src/dev-runtime/persistence/mock-db-store.js - WARNING: changed runtime JS file was not collected by Playwright V8 coverage; advisory only
2022
(0%) src/dev-runtime/server/mock-api-router.mjs - WARNING: changed runtime JS file was not collected by Playwright V8 coverage; advisory only
2123
(0%) toolbox/toolRegistry.js - WARNING: changed runtime JS file was not collected by Playwright V8 coverage; advisory only
22-
(65%) assets/theme-v2/js/gamefoundry-partials.js - executed lines 547/547; executed functions 30/46
23-
(67%) src/engine/api/toolbox-votes-api-client.js - executed lines 19/19; executed functions 2/3
24-
(75%) toolbox/tools-page-accordions.js - executed lines 1067/1067; executed functions 78/104
25-
(93%) assets/theme-v2/js/tool-display-mode.js - executed lines 209/209; executed functions 13/14
24+
(77%) assets/theme-v2/js/gamefoundry-partials.js - executed lines 547/547; executed functions 37/48
25+
(96%) toolbox/tools-page-accordions.js - executed lines 1033/1033; executed functions 108/113
26+
(100%) admin/tool-votes.js - executed lines 120/120; executed functions 16/16
27+
(100%) src/engine/api/toolbox-votes-api-client.js - executed lines 28/28; executed functions 4/4
2628

2729
Files with executed line/function counts where available:
2830
(38%) src/engine/api/session-api-client.js - executed lines 34/34; executed functions 3/8
29-
(53%) src/engine/api/server-api-client.js - executed lines 159/159; executed functions 10/19
30-
(65%) assets/theme-v2/js/gamefoundry-partials.js - executed lines 547/547; executed functions 30/46
31-
(67%) src/engine/api/toolbox-votes-api-client.js - executed lines 19/19; executed functions 2/3
32-
(71%) toolbox/project-workspace/project-workspace.js - executed lines 264/264; executed functions 17/24
33-
(75%) toolbox/tools-page-accordions.js - executed lines 1067/1067; executed functions 78/104
34-
(78%) toolbox/game-configuration/game-configuration.js - executed lines 169/169; executed functions 14/18
35-
(91%) toolbox/game-design/game-design.js - executed lines 242/242; executed functions 20/22
36-
(93%) assets/theme-v2/js/tool-display-mode.js - executed lines 209/209; executed functions 13/14
37-
(96%) toolbox/tool-registry-api-client.js - executed lines 148/148; executed functions 26/27
38-
(100%) toolbox/game-configuration/game-configuration-api-client.js - executed lines 10/10; executed functions 2/2
39-
(100%) toolbox/game-design/game-design-api-client.js - executed lines 12/12; executed functions 2/2
31+
(55%) toolbox/colors/colors.js - executed lines 2147/2147; executed functions 114/206
32+
(55%) toolbox/project-journey/project-journey.js - executed lines 1003/1003; executed functions 54/99
33+
(58%) src/engine/api/server-api-client.js - executed lines 159/159; executed functions 11/19
34+
(64%) assets/theme-v2/js/tool-display-mode.js - executed lines 209/209; executed functions 9/14
35+
(71%) toolbox/assets/assets.js - executed lines 519/519; executed functions 42/59
36+
(77%) assets/theme-v2/js/gamefoundry-partials.js - executed lines 547/547; executed functions 37/48
37+
(85%) toolbox/tool-registry-api-client.js - executed lines 148/148; executed functions 23/27
38+
(96%) toolbox/tools-page-accordions.js - executed lines 1033/1033; executed functions 108/113
39+
(100%) admin/tool-votes.js - executed lines 120/120; executed functions 16/16
40+
(100%) src/engine/api/toolbox-votes-api-client.js - executed lines 28/28; executed functions 4/4
41+
(100%) toolbox/assets/assets-api-client.js - executed lines 17/17; executed functions 3/3
42+
(100%) toolbox/colors/palette-api-client.js - executed lines 19/19; executed functions 4/4
43+
(100%) toolbox/project-journey/project-journey-api-client.js - executed lines 12/12; executed functions 2/2
4044
(100%) toolbox/project-workspace/project-workspace-api-client.js - executed lines 12/12; executed functions 2/2
4145

4246
Uncovered or low-coverage changed JS files:
47+
(0%) src/dev-runtime/guest-seeds/tool-state-samples.js - WARNING: uncovered changed runtime JS file; advisory only
48+
(0%) src/dev-runtime/persistence/mock-db-store.js - WARNING: uncovered changed runtime JS file; advisory only
4349
(0%) src/dev-runtime/server/mock-api-router.mjs - WARNING: uncovered changed runtime JS file; advisory only
4450
(0%) toolbox/toolRegistry.js - WARNING: uncovered changed runtime JS file; advisory only
4551

4652
Changed JS files considered:
47-
(0%) admin/tool-votes.js - changed JS file not collected as browser runtime coverage
53+
(0%) src/dev-runtime/guest-seeds/tool-state-samples.js - changed JS file not collected as browser runtime coverage
54+
(0%) src/dev-runtime/persistence/mock-db-store.js - changed JS file not collected as browser runtime coverage
4855
(0%) src/dev-runtime/server/mock-api-router.mjs - changed JS file not collected as browser runtime coverage
56+
(0%) tests/helpers/playwrightV8CoverageReporter.mjs - changed JS file not collected as browser runtime coverage
4957
(0%) tests/playwright/tools/ToolboxRoutePages.spec.mjs - changed JS file not collected as browser runtime coverage
5058
(0%) toolbox/toolRegistry.js - changed JS file not collected as browser runtime coverage
51-
(65%) assets/theme-v2/js/gamefoundry-partials.js - changed JS file with browser V8 coverage
52-
(67%) src/engine/api/toolbox-votes-api-client.js - changed JS file with browser V8 coverage
53-
(75%) toolbox/tools-page-accordions.js - changed JS file with browser V8 coverage
54-
(93%) assets/theme-v2/js/tool-display-mode.js - changed JS file with browser V8 coverage
59+
(77%) assets/theme-v2/js/gamefoundry-partials.js - changed JS file with browser V8 coverage
60+
(96%) toolbox/tools-page-accordions.js - changed JS file with browser V8 coverage
61+
(100%) admin/tool-votes.js - changed JS file with browser V8 coverage
62+
(100%) src/engine/api/toolbox-votes-api-client.js - changed JS file with browser V8 coverage
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
# PR_26160_057 Toolbox DB Status Vote Restore Report
2+
3+
## Branch Validation
4+
5+
| Check | Result | Evidence |
6+
| --- | --- | --- |
7+
| Current branch is `main` | PASS | `git branch --show-current` returned `main`. |
8+
| Local branches reported | PASS | `git branch --list` returned only `* main`. |
9+
10+
## Requirement Checklist
11+
12+
| Requirement | Status | Evidence |
13+
| --- | --- | --- |
14+
| Build Path reads tool Status from shared DB/tool registry data source | PASS | `toolbox/tools-page-accordions.js` now renders Build Path status from each tool release channel populated by the server-backed registry API client. |
15+
| Remove Build Path Complete column | PASS | `createBuildPathTable()` now renders `Order`, `Tool`, and `Status` only; Playwright asserts these headers. |
16+
| Build Path supports planned/wireframe/beta/complete filters | PASS | Shared release-channel filter controls are active in Build Path mode and filter Build Path rows. |
17+
| Default Build Path filter state shows only Complete active | PASS | `applyReleaseFilterDefaults("build-path")` sets only `complete`; Playwright asserts planned/wireframe/beta false and complete true after opening Build Path. |
18+
| Filter counts show Planned includes remaining planned tools | PASS | Counts now use all visible registry tools rather than role-filtered tiles; Playwright asserts `Planned (28)`, `Wireframe (4)`, `Beta (5)`, `Complete (1)`. |
19+
| Persist each user vote in shared DB-backed state | PASS | Added `toolbox_votes` shared table schema/seed plus server writes through `/api/toolbox/votes/cast`; Playwright verifies `/api/mock-db/snapshot` contains vote rows. |
20+
| Vote Up/Down counts show all users' votes | PASS | Server snapshot aggregates all rows in `toolbox_votes`; Playwright verifies two users voting Up produces `Up 2`, `Down 0`. |
21+
| Current user's selected vote is visually identified and can switch direction | PASS | Vote buttons retain `aria-pressed`; Playwright verifies restore and switching from Down to Up updates counts and pressed state. |
22+
| Add admin ability to change order number for each tool | PASS | Added `/api/toolbox/votes/order`, `updateToolboxVoteOrder()`, and editable order inputs on `admin/tool-votes.html`; Playwright edits Build Game order to `7`. |
23+
| Make selected Order, Group, and Path visible in admin vote viewer | PASS | `admin/tool-votes.html` shows selected detail pills; Playwright selects Build Game and verifies Order, Group, and Path. |
24+
| Preserve one-vote-per-user-per-tool behavior | PASS | Server stores one `toolbox_votes` row per `toolId` + `userKey`; changing direction mutates the existing row. |
25+
| No inline script/style/event handlers | PASS | Static `rg --pcre2` scan returned no matches for inline scripts, styles, or inline event handlers in touched HTML pages. |
26+
27+
## Validation Performed
28+
29+
| Lane | Command | Result |
30+
| --- | --- | --- |
31+
| Branch guard | `git branch --show-current`; `git branch --list` | PASS |
32+
| Changed-file syntax | `node --check` on changed JS/MJS files | PASS |
33+
| Static diff check | `git diff --check` | PASS |
34+
| Inline HTML guard | `rg --pcre2 -n "<script(?![^>]+src=)|<style[\\s>]|\\son(?:click|change|input|submit|keydown|keyup|load)=" toolbox/index.html admin/tool-votes.html` | PASS, no matches |
35+
| Targeted Toolbox/page Playwright | `npx playwright test tests/playwright/tools/ToolboxRoutePages.spec.mjs --reporter=line` | PASS, 5 passed |
36+
| Playwright V8 coverage | Generated by `ToolboxRoutePages.spec.mjs` via `workspaceV2CoverageReporter` | PASS, report written to `docs_build/dev/reports/playwright_v8_coverage_report.txt` |
37+
38+
## Impacted Lane
39+
40+
Targeted Toolbox/page lane only: Toolbox index Build Path filters, Toolbox tile voting, admin Tool Votes viewer, and supporting server/API vote endpoints.
41+
42+
## Artifacts
43+
44+
- Codex review diff: `docs_build/dev/reports/codex_review.diff`
45+
- Changed files: `docs_build/dev/reports/codex_changed_files.txt`
46+
- V8 coverage: `docs_build/dev/reports/playwright_v8_coverage_report.txt`
47+
- Repo-structured ZIP: `tmp/PR_26160_057-toolbox-db-status-vote-restore_20260609_001_delta.zip`
48+
49+
## Skipped Lanes
50+
51+
| Lane | Decision | Reason |
52+
| --- | --- | --- |
53+
| Full samples validation | SKIPPED | Samples were not changed and no shared sample loader/framework was touched. |
54+
| Broad Project Workspace lane | SKIPPED | Project Workspace runtime files were not changed; Toolbox only reads existing registry/project summary context. |
55+
| Full app Playwright suite | SKIPPED | PR scope is targeted Toolbox/page behavior and the affected file was validated directly. |
56+
57+
## Manual Test Notes
58+
59+
1. Open `http://127.0.0.1:5501/toolbox/index.html`.
60+
2. Select `Build Path`; verify only Complete is active and the table has `Order`, `Tool`, `Status`.
61+
3. Vote on a planned or wireframe tile as User 1, navigate away/back, and verify the selected vote is restored.
62+
4. Switch to another user, vote the other direction, and verify aggregate counts include both users.
63+
5. Log in as DavidQ/Admin, open `admin/tool-votes.html`, select a row, and edit its Order value.
64+
65+
## Coverage Notes
66+
67+
V8 coverage reports browser-collected files. Server-side dev-runtime changes are listed as advisory warnings because they execute in Node behind the API boundary rather than Chromium coverage.

0 commit comments

Comments
 (0)