Skip to content

Commit 479d2f4

Browse files
committed
Complete users roles login state and DB Viewer behavior - PR_26157_013-users-roles-login-and-db-viewer-completion
1 parent 6d658a3 commit 479d2f4

37 files changed

Lines changed: 1168 additions & 369 deletions

admin/db-viewer.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ <h2>Mock DB</h2>
3434
<summary>Session User</summary>
3535
<div class="accordion-body content-stack">
3636
<div class="action-group" role="group" aria-label="Mock DB session user controls" data-session-user-controls>
37+
<button class="btn btn--compact" type="button" data-session-user-button="guest">Guest</button>
3738
<button class="btn btn--compact" type="button" data-session-user-button="user1">User 1</button>
3839
<button class="btn btn--compact" type="button" data-session-user-button="user2">User 2</button>
3940
<button class="btn btn--compact" type="button" data-session-user-button="user3">User 3</button>

admin/db-viewer.js

Lines changed: 74 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -5,22 +5,25 @@ import {
55
getAllPersistedMockDbSnapshot,
66
clearMockDbTables,
77
getMockDbSessionUser,
8-
getMockDbSessionUsers,
98
getStandaloneMockDbTables,
9+
seedMockDbTables,
1010
setMockDbSessionUser,
1111
} from "../src/engine/persistence/mock-db-store.js";
1212

1313
const AUDIT_FIELDS = ["createdAt", "updatedAt", "createdBy", "updatedBy"];
14-
const TOOL_GROUP_ORDER = ["project-journey", "palette", "asset"];
14+
const TOOL_GROUP_ORDER = ["workspace", "game-design", "game-configuration", "project-journey", "palette", "asset"];
1515
const TOOL_GROUP_LABELS = Object.freeze({
1616
asset: "Asset",
17+
"game-configuration": "Game Configuration",
18+
"game-design": "Game Design",
1719
palette: "Palette",
1820
"project-journey": "Project Journey",
21+
workspace: "Workspace",
1922
});
2023
const STANDALONE_TABLE_LABELS = Object.freeze({
21-
users: "Users",
22-
actors: "Actors",
24+
user_roles: "User Roles",
2325
});
26+
const IDENTITY_TABLE_GROUP = Object.freeze(["users", "user_roles", "roles"]);
2427

2528
class AdminDbViewer {
2629
constructor(documentRef = document) {
@@ -60,12 +63,21 @@ class AdminDbViewer {
6063
if (!button) {
6164
return;
6265
}
63-
setMockDbSessionUser(button.dataset.sessionUserButton || "user1");
66+
setMockDbSessionUser(button.dataset.sessionUserButton || "guest");
6467
this.createRepositories();
6568
this.projectJourneyRepository.openProject("demo-project");
6669
this.render();
6770
});
6871
this.clearButton?.addEventListener("click", () => {
72+
const snapshot = getAllPersistedMockDbSnapshot();
73+
if (snapshot.cleared) {
74+
seedMockDbTables();
75+
this.createRepositories();
76+
this.projectJourneyRepository.openProject("demo-project");
77+
this.activeFilter = "all";
78+
this.render();
79+
return;
80+
}
6981
if (!window.confirm("Clear all shared Mock DB records?")) {
7082
return;
7183
}
@@ -77,6 +89,14 @@ class AdminDbViewer {
7789
});
7890
}
7991

92+
renderClearSeedButton(cleared) {
93+
if (!this.clearButton) {
94+
return;
95+
}
96+
this.clearButton.textContent = cleared ? "Seed Mock DB" : "Clear Mock DB";
97+
this.clearButton.dataset.adminDbClearMode = cleared ? "seed" : "clear";
98+
}
99+
80100
createElement(tagName, options = {}) {
81101
const element = this.document.createElement(tagName);
82102
if (options.className) {
@@ -134,6 +154,8 @@ class AdminDbViewer {
134154
const snapshot = getAllPersistedMockDbSnapshot();
135155
const tables = snapshot.tables;
136156
const owners = snapshot.owners || {};
157+
const schemas = snapshot.schemas || {};
158+
const toolGroups = snapshot.toolGroups || {};
137159
const tableNamesForOwner = (ownerId) => Object.keys(tables)
138160
.filter((tableName) => owners[tableName] === ownerId)
139161
.sort();
@@ -142,9 +164,9 @@ class AdminDbViewer {
142164
const unownedTableNames = Object.keys(tables)
143165
.filter((tableName) => !toolOwnedTables.has(tableName));
144166
const standaloneTableNames = [
145-
...Object.keys(STANDALONE_TABLE_LABELS).filter((tableName) => unownedTableNames.includes(tableName)),
146-
...unownedTableNames.filter((tableName) => !Object.hasOwn(STANDALONE_TABLE_LABELS, tableName)).sort(),
167+
...unownedTableNames.filter((tableName) => !IDENTITY_TABLE_GROUP.includes(tableName)).sort(),
147168
];
169+
const identityTables = IDENTITY_TABLE_GROUP.filter((tableName) => unownedTableNames.includes(tableName));
148170
const groups = [
149171
{
150172
id: "all",
@@ -154,10 +176,16 @@ class AdminDbViewer {
154176
},
155177
...toolGroupIds.map((id) => ({
156178
id,
157-
label: TOOL_GROUP_LABELS[id],
158-
tableNames: tableNamesForOwner(id),
159-
type: "tool",
160-
})),
179+
label: toolGroups[id]?.label || TOOL_GROUP_LABELS[id] || id,
180+
tableNames: tableNamesForOwner(id),
181+
type: "tool",
182+
})),
183+
...(identityTables.length ? [{
184+
id: "user_roles",
185+
label: STANDALONE_TABLE_LABELS.user_roles,
186+
tableNames: identityTables,
187+
type: "table",
188+
}] : []),
161189
...standaloneTableNames.map((tableName) => ({
162190
id: tableName,
163191
label: STANDALONE_TABLE_LABELS[tableName] || tableName,
@@ -166,7 +194,9 @@ class AdminDbViewer {
166194
})),
167195
];
168196
return {
197+
cleared: Boolean(snapshot.cleared),
169198
groups,
199+
schemas,
170200
tables,
171201
};
172202
}
@@ -175,7 +205,7 @@ class AdminDbViewer {
175205
return groups.find((group) => group.id === this.activeFilter) || groups[0];
176206
}
177207

178-
renderTable(tableName, records) {
208+
renderTable(tableName, records, schemaFields = []) {
179209
const details = this.createElement("details", {
180210
className: "vertical-accordion",
181211
});
@@ -196,7 +226,10 @@ class AdminDbViewer {
196226
});
197227
table.setAttribute("aria-label", `${tableName} records`);
198228

199-
const fields = this.tableFields(records).filter((field) => field !== "key");
229+
const fields = [
230+
...schemaFields,
231+
...this.tableFields(records),
232+
].filter((field, index, allFields) => field !== "key" && allFields.indexOf(field) === index);
200233
const head = this.createElement("thead");
201234
const headerRow = this.createElement("tr");
202235
headerRow.append(this.createElement("th", { text: "Key" }));
@@ -209,7 +242,7 @@ class AdminDbViewer {
209242
if (!records.length) {
210243
const row = this.createElement("tr");
211244
const cell = this.createElement("td", {
212-
text: "No records in this table. Add records from its tool or clear browser mock DB storage to reseed defaults.",
245+
text: "No records in this table. Add records from its tool or use Seed Mock DB to restore baseline mock records.",
213246
});
214247
cell.colSpan = Math.max(1, fields.length + 1);
215248
row.append(cell);
@@ -245,12 +278,11 @@ class AdminDbViewer {
245278
return details;
246279
}
247280

248-
renderTables(tables) {
281+
renderTables(tables, schemas = {}) {
249282
this.tablesRoot.replaceChildren();
250283
Object.keys(tables)
251-
.sort()
252284
.forEach((tableName) => {
253-
this.tablesRoot.append(this.renderTable(tableName, tables[tableName]));
285+
this.tablesRoot.append(this.renderTable(tableName, tables[tableName], schemas[tableName] || []));
254286
});
255287
}
256288

@@ -309,8 +341,17 @@ class AdminDbViewer {
309341
const noteTypeKeys = new Set((tables.project_journey_note_types || []).map((type) => type.key));
310342
const noteKeys = new Set((tables.project_journey_notes || []).map((note) => note.key));
311343
const userKeys = new Set((tables.users || []).map((user) => user.key));
312-
const actorKeys = new Set((tables.actors || []).map((actor) => actor.key));
313-
const actorUserKeys = new Set((tables.actors || []).map((actor) => actor.userKey));
344+
const roleKeys = new Set((tables.roles || []).map((role) => role.key));
345+
const systemRoleKeys = new Set(
346+
(tables.roles || [])
347+
.filter((role) => role.roleSlug === "system" || role.name === "system")
348+
.map((role) => role.key),
349+
);
350+
const systemUserKeys = new Set(
351+
(tables.user_roles || [])
352+
.filter((row) => systemRoleKeys.has(row.roleKey))
353+
.map((row) => row.userKey),
354+
);
314355
const activeTemplateKeys = new Set(
315356
(tables.project_journey_templates || [])
316357
.filter((template) => template.isActive)
@@ -328,14 +369,14 @@ class AdminDbViewer {
328369
);
329370
return [
330371
{
331-
name: "*.createdBy -> actors.key",
372+
name: "*.createdBy -> users.key",
332373
checked: allRecords.length,
333-
missing: allRecords.filter((record) => !actorKeys.has(record.createdBy)),
374+
missing: allRecords.filter((record) => !userKeys.has(record.createdBy)),
334375
},
335376
{
336-
name: "*.updatedBy -> actors.key",
377+
name: "*.updatedBy -> users.key",
337378
checked: allRecords.length,
338-
missing: allRecords.filter((record) => !actorKeys.has(record.updatedBy)),
379+
missing: allRecords.filter((record) => !userKeys.has(record.updatedBy)),
339380
},
340381
{
341382
name: "project_journey_notes.typeKey -> project_journey_note_types.key",
@@ -354,9 +395,9 @@ class AdminDbViewer {
354395
},
355396
{
356397
name: "system project_journey_items.templateKey -> active project_journey_templates.key",
357-
checked: (tables.project_journey_items || []).filter((item) => item.createdByType === "system").length,
398+
checked: (tables.project_journey_items || []).filter((item) => systemUserKeys.has(item.createdBy)).length,
358399
missing: (tables.project_journey_items || []).filter(
359-
(item) => item.createdByType === "system" && !activeTemplateKeys.has(item.templateKey),
400+
(item) => systemUserKeys.has(item.createdBy) && !activeTemplateKeys.has(item.templateKey),
360401
),
361402
},
362403
{
@@ -365,14 +406,14 @@ class AdminDbViewer {
365406
missing: (tables.project_journey_activity || []).filter((activity) => !noteKeys.has(activity.noteKey)),
366407
},
367408
{
368-
name: "actors.userKey -> users.key",
369-
checked: (tables.actors || []).length,
370-
missing: (tables.actors || []).filter((actor) => !userKeys.has(actor.userKey)),
409+
name: "user_roles.userKey -> users.key",
410+
checked: (tables.user_roles || []).length,
411+
missing: (tables.user_roles || []).filter((row) => !userKeys.has(row.userKey)),
371412
},
372413
{
373-
name: "users.key -> actors.userKey",
374-
checked: (tables.users || []).length,
375-
missing: (tables.users || []).filter((user) => !actorUserKeys.has(user.key)),
414+
name: "user_roles.roleKey -> roles.key",
415+
checked: (tables.user_roles || []).length,
416+
missing: (tables.user_roles || []).filter((row) => !roleKeys.has(row.roleKey)),
376417
},
377418
{
378419
name: "palette_colors.projectId -> project_workspace_palette_globals.projectId",
@@ -486,9 +527,10 @@ class AdminDbViewer {
486527
);
487528
this.renderFilters(snapshot.groups);
488529
this.renderSessionUser();
530+
this.renderClearSeedButton(snapshot.cleared);
489531
this.renderDiagnostics(snapshot.tables, snapshot.groups);
490532
this.renderRelationships(snapshot.tables);
491-
this.renderTables(visibleTables);
533+
this.renderTables(visibleTables, snapshot.schemas);
492534
if (this.status) {
493535
const recordCount = Object.values(visibleTables).reduce((total, rows) => total + rows.length, 0);
494536
this.status.textContent = `Mock DB loaded ${Object.keys(visibleTables).length} table${Object.keys(visibleTables).length === 1 ? "" : "s"} and ${recordCount} record${recordCount === 1 ? "" : "s"} for ${group.label}.`;

assets/theme-v2/css/layout.css

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@ body {
1212
margin: var(--space-0)
1313
}
1414

15+
[hidden] {
16+
display: none !important
17+
}
18+
1519
img,
1620
video,
1721
audio,

0 commit comments

Comments
 (0)