From c0a8e05e78294d330d35d5304130870cb92a4d84 Mon Sep 17 00:00:00 2001 From: JB Date: Sat, 25 Jul 2026 21:27:28 -0400 Subject: [PATCH] Show oversight queue counts --- docs/DESIGN_SYSTEM.md | 7 +++++++ src/routes/isac/+layout.server.ts | 14 ++++++++++++-- src/routes/isac/+layout.svelte | 11 +++++++---- 3 files changed, 26 insertions(+), 6 deletions(-) diff --git a/docs/DESIGN_SYSTEM.md b/docs/DESIGN_SYSTEM.md index f0522c3..0829314 100644 --- a/docs/DESIGN_SYSTEM.md +++ b/docs/DESIGN_SYSTEM.md @@ -735,6 +735,13 @@ grid, because the arrow will wrap to another row. The count includes textual assistive labeling and strengthens its border and contrast on link hover or active state. +The same compact count cell identifies actionable work in System Oversight +navigation. Show it only for queues with unresolved items, such as pending data +proposals or avatar reviews, and calculate it within the viewer's permissions. +Do not add zero badges or counts to informational registries such as Audit +History and System Metrics. Badge text must expose an `awaiting review` label to +assistive technology; color supplements that meaning rather than replacing it. + Pending records may be used as dependencies in later proposals by any contributor. Render these choices in the ordinary assignment control with a restrained orange border/background and the explicit text `PENDING` plus the diff --git a/src/routes/isac/+layout.server.ts b/src/routes/isac/+layout.server.ts index ccb3b5a..fd3e860 100644 --- a/src/routes/isac/+layout.server.ts +++ b/src/routes/isac/+layout.server.ts @@ -12,14 +12,24 @@ export const load: LayoutServerLoad = async ({ cookies }) => { const canSeeData = permissions.includes('*') || ['data.view','data.manage','data.propose','data.approve'].some((permission) => permissions.includes(permission)); const canManageData = permissions.includes('*') || permissions.includes('data.manage'); const canProposeData = permissions.includes('*') || permissions.includes('data.propose'); + const canApproveData = permissions.includes('*') || permissions.includes('data.approve'); + const canReviewAvatars = permissions.includes('*') || permissions.includes('avatars.review'); const contributorMode = !canManageData && canProposeData ? await getContributorMode(user.id) : null; + const database = canSeeData || canReviewAvatars ? await getDatabase() : null; const pendingRows = canSeeData - ? await (await (await getDatabase()).prepare("SELECT module,COUNT(*) AS count FROM data_change_proposals WHERE status='pending' GROUP BY module")).all() + ? await (await database!.prepare("SELECT module,COUNT(*) AS count FROM data_change_proposals WHERE status='pending' GROUP BY module")).all() : []; + const pendingProposalTotal = pendingRows.reduce((total, row) => total + Number(row.count), 0); + const pendingAvatarReviews = canReviewAvatars + ? Number((await (await database!.prepare("SELECT COUNT(*) AS count FROM avatar_reviews WHERE status='pending'")).get())?.count ?? 0) + : 0; return { permissions, contributorMode, pendingProposals: Object.fromEntries(pendingRows.map((row) => [String(row.module), Number(row.count)])), - pendingProposalTotal: pendingRows.reduce((total, row) => total + Number(row.count), 0) + oversightReviewCounts: { + data: canApproveData ? pendingProposalTotal : 0, + avatars: pendingAvatarReviews + } }; }; diff --git a/src/routes/isac/+layout.svelte b/src/routes/isac/+layout.svelte index 2346007..d3db40c 100644 --- a/src/routes/isac/+layout.svelte +++ b/src/routes/isac/+layout.svelte @@ -23,9 +23,9 @@ { href: '/isac/roles', label: 'Roles', code: 'ROLE', permission: 'users.roles' } ]; const visibleUserSections = $derived(userSections.filter((section) => can(section.permission))); - const oversightSections = [ - { href: '/isac/data-moderation', label: 'Data Oversight', code: 'OVST', permission: 'data.approve' }, - { href: '/isac/avatar-oversight', label: 'Avatar Oversight', code: 'AVTR', permission: 'avatars.review' }, + const oversightSections: Array<{ href: string; label: string; code: string; permission: string; reviewKey?: 'data' | 'avatars' }> = [ + { href: '/isac/data-moderation', label: 'Data Oversight', code: 'OVST', permission: 'data.approve', reviewKey: 'data' }, + { href: '/isac/avatar-oversight', label: 'Avatar Oversight', code: 'AVTR', permission: 'avatars.review', reviewKey: 'avatars' }, { href: '/isac/audit', label: 'Audit history', code: 'AUDT', permission: 'audit.view' }, { href: '/isac/metrics', label: 'System metrics', code: 'MTRX', permission: 'metrics.view' } ]; @@ -55,7 +55,10 @@ {/if} {#if visibleOversightSections.length} - + {/if}