Skip to content

Commit 8d2c07b

Browse files
committed
Polish Project Journey key SSoT search and user item creation - PR_26157_008-project-journey-key-search-additem-polish
1 parent 8b674eb commit 8d2c07b

9 files changed

Lines changed: 617 additions & 344 deletions

admin/db-viewer.js

Lines changed: 35 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,16 @@ class AdminDbViewer {
3535
}
3636

3737
recordId(record) {
38-
return record.itemId || record.templateId || record.id || record.name || "record";
38+
return record.key || record.name || "record";
3939
}
4040

41-
shortKey(record) {
42-
const key = String(this.recordId(record));
43-
return key.length > 8 ? key.slice(-8) : key;
41+
isUlidKey(value) {
42+
return /^[0-9A-HJKMNP-TV-Z]{26}$/.test(String(value || ""));
43+
}
44+
45+
formatKeyValue(value) {
46+
const key = String(value);
47+
return key.slice(0, 10);
4448
}
4549

4650
formatValue(value) {
@@ -92,7 +96,6 @@ class AdminDbViewer {
9296
const fields = this.tableFields(records);
9397
const head = this.createElement("thead");
9498
const headerRow = this.createElement("tr");
95-
headerRow.append(this.createElement("th", { text: "Key" }));
9699
fields.forEach((field) => {
97100
headerRow.append(this.createElement("th", { text: field }));
98101
});
@@ -102,11 +105,15 @@ class AdminDbViewer {
102105
records.forEach((record) => {
103106
const row = this.createElement("tr");
104107
row.dataset.adminDbRecord = this.recordId(record);
105-
const keyCell = this.createElement("td", { text: this.shortKey(record) });
106-
keyCell.title = this.recordId(record);
107-
row.append(keyCell);
108108
fields.forEach((field) => {
109-
row.append(this.createElement("td", { text: this.formatValue(record[field]) }));
109+
const value = record[field];
110+
const cell = this.createElement("td", {
111+
text: this.isUlidKey(value) ? this.formatKeyValue(value) : this.formatValue(value),
112+
});
113+
if (this.isUlidKey(value)) {
114+
cell.title = String(value);
115+
}
116+
row.append(cell);
110117
});
111118
tableBody.append(row);
112119
});
@@ -142,52 +149,52 @@ class AdminDbViewer {
142149
}
143150

144151
relationshipsForTables(tables) {
145-
const noteTypeIds = new Set(tables.project_journey_note_types.map((type) => type.id));
146-
const noteIds = new Set(tables.project_journey_notes.map((note) => note.id));
147-
const activeTemplateIds = new Set(
152+
const noteTypeKeys = new Set(tables.project_journey_note_types.map((type) => type.key));
153+
const noteKeys = new Set(tables.project_journey_notes.map((note) => note.key));
154+
const activeTemplateKeys = new Set(
148155
tables.project_journey_templates
149156
.filter((template) => template.isActive)
150-
.map((template) => template.templateId),
157+
.map((template) => template.key),
151158
);
152159
return [
153160
{
154-
name: "project_journey_notes.typeId -> project_journey_note_types.id",
161+
name: "project_journey_notes.typeKey -> project_journey_note_types.key",
155162
checked: tables.project_journey_notes.length,
156-
missing: tables.project_journey_notes.filter((note) => !noteTypeIds.has(note.typeId)),
163+
missing: tables.project_journey_notes.filter((note) => !noteTypeKeys.has(note.typeKey)),
157164
},
158165
{
159-
name: "project_journey_items.noteId -> project_journey_notes.id",
166+
name: "project_journey_items.noteKey -> project_journey_notes.key",
160167
checked: tables.project_journey_items.length,
161-
missing: tables.project_journey_items.filter((item) => !noteIds.has(item.noteId)),
168+
missing: tables.project_journey_items.filter((item) => !noteKeys.has(item.noteKey)),
162169
},
163170
{
164-
name: "system project_journey_items.templateId -> active project_journey_templates.templateId",
171+
name: "system project_journey_items.templateKey -> active project_journey_templates.key",
165172
checked: tables.project_journey_items.filter((item) => item.createdByType === "system").length,
166173
missing: tables.project_journey_items.filter(
167-
(item) => item.createdByType === "system" && !activeTemplateIds.has(item.templateId),
174+
(item) => item.createdByType === "system" && !activeTemplateKeys.has(item.templateKey),
168175
),
169176
},
170177
{
171-
name: "project_journey_activity.noteId -> project_journey_notes.id",
178+
name: "project_journey_activity.noteKey -> project_journey_notes.key",
172179
checked: tables.project_journey_activity.length,
173-
missing: tables.project_journey_activity.filter((activity) => !noteIds.has(activity.noteId)),
180+
missing: tables.project_journey_activity.filter((activity) => !noteKeys.has(activity.noteKey)),
174181
},
175182
];
176183
}
177184

178185
tableBleedFindings(tables) {
179-
const notesById = new Map(tables.project_journey_notes.map((note) => [note.id, note]));
186+
const notesByKey = new Map(tables.project_journey_notes.map((note) => [note.key, note]));
180187
const findings = [];
181188
tables.project_journey_items.forEach((item) => {
182-
const note = notesById.get(item.noteId);
183-
if (note && note.projectId !== item.projectId) {
184-
findings.push(`${item.itemId} projectId ${item.projectId} does not match note ${note.id} projectId ${note.projectId}.`);
189+
const note = notesByKey.get(item.noteKey);
190+
if (note && note.projectKey !== item.projectKey) {
191+
findings.push(`${item.key} projectKey ${item.projectKey} does not match note ${note.key} projectKey ${note.projectKey}.`);
185192
}
186193
});
187194
tables.project_journey_activity.forEach((activity) => {
188-
const note = notesById.get(activity.noteId);
189-
if (note && note.projectId !== activity.projectId) {
190-
findings.push(`${activity.id} projectId ${activity.projectId} does not match note ${note.id} projectId ${note.projectId}.`);
195+
const note = notesByKey.get(activity.noteKey);
196+
if (note && note.projectKey !== activity.projectKey) {
197+
findings.push(`${activity.key} projectKey ${activity.projectKey} does not match note ${note.key} projectKey ${note.projectKey}.`);
191198
}
192199
});
193200
return findings;

docs_build/dev/reports/playwright_v8_coverage_report.txt

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@ Exercised tool entry points detected:
1717
(74%) Theme V2 Shared JS - exercised 2 runtime JS files
1818

1919
Changed runtime JS files covered:
20-
(95%) toolbox/project-journey/project-journey-mock-repository.js - executed lines 960/960; executed functions 76/80
21-
(96%) toolbox/project-journey/project-journey.js - executed lines 805/805; executed functions 79/82
20+
(95%) toolbox/project-journey/project-journey-mock-repository.js - executed lines 961/961; executed functions 76/80
21+
(96%) toolbox/project-journey/project-journey.js - executed lines 950/950; executed functions 100/104
2222

2323
Files with executed line/function counts where available:
2424
(67%) assets/theme-v2/js/tool-display-mode.js - executed lines 201/201; executed functions 10/15
@@ -27,17 +27,15 @@ Files with executed line/function counts where available:
2727
(76%) toolbox/project-workspace/project-workspace-mock-repository.js - executed lines 402/402; executed functions 26/34
2828
(80%) assets/theme-v2/js/gamefoundry-partials.js - executed lines 207/207; executed functions 16/20
2929
(86%) toolbox/toolRegistry.js - executed lines 1788/1788; executed functions 32/37
30-
(95%) toolbox/project-journey/project-journey-mock-repository.js - executed lines 960/960; executed functions 76/80
31-
(96%) toolbox/project-journey/project-journey.js - executed lines 805/805; executed functions 79/82
32-
(98%) admin/db-viewer.js - executed lines 221/221; executed functions 40/41
30+
(95%) toolbox/project-journey/project-journey-mock-repository.js - executed lines 961/961; executed functions 76/80
31+
(96%) toolbox/project-journey/project-journey.js - executed lines 950/950; executed functions 100/104
32+
(98%) admin/db-viewer.js - executed lines 227/227; executed functions 41/42
3333

3434
Uncovered or low-coverage changed JS files:
3535
(100%) none - no low-coverage changed runtime JS files
3636

3737
Changed JS files considered:
38-
(0%) admin/notes.js - changed JS file not collected as browser runtime coverage
3938
(0%) tests/playwright/tools/AdminDbViewer.spec.mjs - changed JS file not collected as browser runtime coverage
40-
(0%) tests/playwright/tools/AdminNotesViewer.spec.mjs - changed JS file not collected as browser runtime coverage
4139
(0%) tests/playwright/tools/ProjectJourneyTool.spec.mjs - changed JS file not collected as browser runtime coverage
4240
(95%) toolbox/project-journey/project-journey-mock-repository.js - changed JS file with browser V8 coverage
4341
(96%) toolbox/project-journey/project-journey.js - changed JS file with browser V8 coverage
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# Project Journey Key Search Add Item Polish Report
2+
3+
PR: PR_26157_008-project-journey-key-search-additem-polish
4+
5+
## Summary
6+
- Migrated Project Journey mock DB records to use `key` as the only ULID primary key SSoT.
7+
- Updated note, item, template, type, activity, and repository relationships to use `projectKey`, `ownerKey`, `noteKey`, `typeKey`, and `templateKey`.
8+
- Updated the Admin DB Viewer to display actual table field names, shorten ULID values to their first 10 characters, and expose the full key through hover/title text.
9+
- Added Project Journey search across note names, note types, item titles, item details, system guidance, status labels/icons, linked tool contexts, and suggested tool text.
10+
- Polished Add Item so user-created items can be titled before creation, default to Not Started unless a different status is selected, become selected immediately, and never create disabled system-owned blank rows.
11+
12+
## Validation Notes
13+
- DB Viewer relationship checks now report key-based relationships and continue to show no missing-link or table-bleed diagnostics for valid seed data.
14+
- Search filters the Summary Table and the selected Note Tree where applicable, and visible Statistics counts are recomputed from the filtered item set.
15+
- Search clear restores the prior navigation/filter state, including a navigation-click state where no Summary Table row was selected.
16+
- System-created titles and template guidance remain protected; system-created items remain non-deletable.
17+
- User-created titles and Item Details remain editable, and user-created delete confirmation behavior is preserved.
18+
19+
## Constraints Checked
20+
- No page-local CSS, tool-local CSS, inline styles, style blocks, inline script blocks, or inline event handlers were added.
21+
- No archived V1/V2 files were modified.
22+
- No `start_of_day` folders were modified.
23+
- Full samples smoke was not run.

docs_build/dev/reports/testing_lane_execution_report.md

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Testing Lane Execution Report
22

3-
PR: PR_26157_007-project-journey-ulid-db-table-polish
3+
PR: PR_26157_008-project-journey-key-search-additem-polish
44

55
## Lanes Run
66
- Project Journey runtime/UI lane.
@@ -15,21 +15,26 @@ PR: PR_26157_007-project-journey-ulid-db-table-polish
1515
- `node --check tests/playwright/tools/ProjectJourneyTool.spec.mjs`
1616
- `node --check tests/playwright/tools/AdminDbViewer.spec.mjs`
1717
- `npx playwright test tests/playwright/tools/ProjectJourneyTool.spec.mjs tests/playwright/tools/AdminDbViewer.spec.mjs --reporter=list --workers=1`
18-
- `npm run test:playwright:static -- --static-report docs_build/dev/reports/static_validation_report.md`
18+
- `npm run test:playwright:static`
19+
- `git diff --check`
20+
- `rg -n "<style|style=|on(click|change|input|submit)=" admin/db-viewer.js toolbox/project-journey/index.html toolbox/project-journey/project-journey.js toolbox/project-journey/project-journey-mock-repository.js tests/playwright/tools/AdminDbViewer.spec.mjs tests/playwright/tools/ProjectJourneyTool.spec.mjs`
21+
- `rg -n "<script" toolbox/project-journey/index.html admin/db-viewer.js`
22+
- `git diff --name-only | rg -n "(^|/)(start_of_day|archived|archive)(/|$)"`
1923

2024
## Results
2125
- Syntax checks: PASS.
22-
- Targeted Playwright: PASS, 12 passed.
26+
- Targeted Playwright: PASS, 13 passed.
2327
- Static validation: PASS.
28+
- Changed-file scans: PASS. No forbidden inline styles, style blocks, inline event handlers, inline script blocks, archived paths, or `start_of_day` paths were introduced. Existing external script tags remain unchanged.
29+
- `git diff --check`: PASS with line-ending warnings only.
2430
- V8 coverage report: generated at `docs_build/dev/reports/playwright_v8_coverage_report.txt`.
2531

2632
## Behavior Covered
27-
- Project Journey Statistics mini-stat value/label inline layout.
28-
- Project Journey Status Legend removal.
29-
- Summary Table sorting, Skipped status, Open/Total formulas, System Generated filter, system template SSoT, and ownership fields.
30-
- User-created generated note/type/item IDs remain ULID-style and editable/deletable as scoped.
31-
- System-created items remain template-backed and non-deletable.
32-
- DB Viewer field casing, Key column, full-key hover titles, read-only behavior, relationship summaries, and no table bleed diagnostics.
33+
- Project Journey `key`-based mock DB SSoT and key-based relationships across notes, note types, items, templates, and activity.
34+
- DB Viewer actual field casing, 10-character ULID display, full-key hover titles, read-only behavior, relationship summaries, and no table bleed diagnostics.
35+
- Project Journey Search filters Summary Table and Note Tree content, recomputes visible counts, and restores the prior navigation/filter state on clear.
36+
- Add Item creates immediately editable user-created items with pre-entered titles, default Not Started status, and no disabled blank system-created rows.
37+
- System-created title/guidance protections, no-delete behavior, user-created edit/delete behavior, Summary Table sorting, Skipped status, Open/Total formulas, System Generated filter, and template SSoT behavior remain covered.
3338

3439
## Skipped Lanes
3540
- Full samples smoke: SKIP. Samples are not in scope and the PR does not modify sample manifests or game runtime.

tests/playwright/tools/AdminDbViewer.spec.mjs

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { expect, test } from "@playwright/test";
2-
import { PROJECT_JOURNEY_IDS } from "../../../toolbox/project-journey/project-journey-mock-repository.js";
2+
import { PROJECT_JOURNEY_KEYS } from "../../../toolbox/project-journey/project-journey-mock-repository.js";
33
import { startRepoServer } from "../../helpers/playwrightRepoServer.mjs";
44
import { clearPlaywrightStorage, installPlaywrightStorageIsolation } from "../../helpers/playwrightStorageIsolation.mjs";
55
import { workspaceV2CoverageReporter } from "../../helpers/workspaceV2CoverageReporter.mjs";
@@ -82,35 +82,37 @@ test("Admin DB Viewer shows read-only mock DB tables and diagnostics", async ({
8282
"project_journey_notes",
8383
"project_journey_templates",
8484
]) {
85-
await expect(page.locator(`[data-admin-db-table="${tableName}"] thead th`).first()).toHaveText("Key");
85+
await expect(page.locator(`[data-admin-db-table="${tableName}"] thead th`).first()).toHaveText("key");
8686
const keyCell = page.locator(`[data-admin-db-table="${tableName}"] tbody tr`).first().locator("td").first();
87-
await expect(keyCell).toHaveText(/^[0-9A-HJKMNP-TV-Z]{6,8}$/);
87+
await expect(keyCell).toHaveText(/^[0-9A-HJKMNP-TV-Z]{10}$/);
8888
await expect(keyCell).toHaveAttribute("title", ULID_PATTERN);
8989
}
9090

9191
const itemHeaders = await page.locator("[data-admin-db-table='project_journey_items'] thead th").allTextContents();
92-
expect(itemHeaders[0]).toBe("Key");
92+
expect(itemHeaders[0]).toBe("key");
9393
expect(itemHeaders).toEqual(expect.arrayContaining([
94-
"itemId",
95-
"projectId",
96-
"noteId",
94+
"key",
95+
"projectKey",
96+
"noteKey",
9797
"status",
9898
"title",
9999
"userDetails",
100100
"createdAt",
101101
"updatedAt",
102102
"createdByType",
103103
"updatedByType",
104-
"templateId",
104+
"templateKey",
105105
]));
106+
expect(itemHeaders).not.toEqual(expect.arrayContaining(["id", "itemId", "projectId", "noteId", "templateId"]));
106107
expect(itemHeaders).not.toEqual(expect.arrayContaining(["CREATEDAT", "UPDATEDAT", "CREATEDBYTYPE", "UPDATEDBYTYPE"]));
107108
const createdAtHeader = page.locator("[data-admin-db-table='project_journey_items'] thead th", { hasText: "createdAt" });
108109
await expect(createdAtHeader).toHaveCSS("text-transform", "none");
109-
const designItemRow = page.locator(`[data-admin-db-record="${PROJECT_JOURNEY_IDS.items.designAffordance}"]`);
110-
await expect(designItemRow.locator("td").first()).toHaveText(PROJECT_JOURNEY_IDS.items.designAffordance.slice(-8));
111-
await expect(designItemRow.locator("td").first()).toHaveAttribute("title", PROJECT_JOURNEY_IDS.items.designAffordance);
112-
await expect(page.locator("[data-admin-db-table='project_journey_items']")).toContainText(PROJECT_JOURNEY_IDS.items.designAffordance);
113-
await expect(page.locator("[data-admin-db-table='project_journey_templates']")).toContainText(PROJECT_JOURNEY_IDS.templates.paletteAffordance);
110+
const designItemRow = page.locator(`[data-admin-db-record="${PROJECT_JOURNEY_KEYS.items.designAffordance}"]`);
111+
await expect(designItemRow.locator("td").first()).toHaveText(PROJECT_JOURNEY_KEYS.items.designAffordance.slice(0, 10));
112+
await expect(designItemRow.locator("td").first()).toHaveAttribute("title", PROJECT_JOURNEY_KEYS.items.designAffordance);
113+
await expect(page.locator("[data-admin-db-table='project_journey_items']")).toContainText(PROJECT_JOURNEY_KEYS.items.designAffordance.slice(0, 10));
114+
await expect(page.locator("[data-admin-db-table='project_journey_items']")).not.toContainText(PROJECT_JOURNEY_KEYS.items.designAffordance);
115+
await expect(page.locator("[data-admin-db-table='project_journey_templates']")).toContainText(PROJECT_JOURNEY_KEYS.templates.paletteAffordance.slice(0, 10));
114116
await expect(page.locator("[data-admin-db-table='project_journey_note_types']")).toContainText("Design");
115117
await expect(page.locator("[data-admin-db-table='project_journey_activity']")).toContainText("Palette and Input Density updated by Designer");
116118

@@ -119,10 +121,10 @@ test("Admin DB Viewer shows read-only mock DB tables and diagnostics", async ({
119121
);
120122
await expect(page.locator("[data-admin-db-bleed-findings]")).toContainText("No table bleed detected.");
121123
await expect(page.locator("[data-admin-db-relationship-summary]")).toContainText(
122-
"project_journey_items.noteId -> project_journey_notes.id: 9/9 records linked."
124+
"project_journey_items.noteKey -> project_journey_notes.key: 9/9 records linked."
123125
);
124126
await expect(page.locator("[data-admin-db-relationship-summary]")).toContainText(
125-
"system project_journey_items.templateId -> active project_journey_templates.templateId: 9/9 records linked."
127+
"system project_journey_items.templateKey -> active project_journey_templates.key: 9/9 records linked."
126128
);
127129
await expect(page.locator("[data-admin-db-missing-links]")).toContainText("No missing links detected.");
128130
await expect(page.locator("[data-admin-db-viewer] input, [data-admin-db-viewer] textarea, [data-admin-db-viewer] select, [data-admin-db-viewer] button")).toHaveCount(0);

0 commit comments

Comments
 (0)