feat(review): open Needs review from the System Overview review row

Review metadata on the Overview's review row now opens #/review, the
concept's go-review, instead of staying aria-disabled.
This commit is contained in:
Vito Sansevero
2026-10-23 07:20:59 -07:00
parent 59cdb00f67
commit 49b5552340
4 changed files with 12 additions and 14 deletions
+2 -2
View File
@@ -2060,8 +2060,8 @@ Recorded deviations (plan D60–D64 renumbered D92–D96; D121, D122 and D123 as
integrity" is "Not checked" until a check ran this session, then "N issues" (checks
that found issues, even beside a check that could not run), "Passed" or "Incomplete".
The review row is "N ambiguous image links" (the Needs review queue's pending count,
`needs_review.pending`) with the concept's line; its Review metadata action is
`aria-disabled` (CSS under D93) until the Needs review page ships (#288). A count
`needs_review.pending`) with the concept's line; its Review metadata action opens
`#/review` (the concept's `go-review`). A count
that is not an integer reads "Ambiguous image links" / "Not available yet." (Q6).
"Backup status" reads "No retained backup record." until verified backups exist (S8).
The thumbnail row is "Checking thumbnails…" until its own read answers, then "No
+3 -5
View File
@@ -169,10 +169,9 @@ function mapOverviewConcept(reference, overview) {
const relabel = { 'Database integrity': 'Not checked', 'Positive prompts': number(overview.library.positive_prompts),
'Negative variants': number(overview.library.negative_variants), Images: number(overview.images.indexed) };
const rows = {
// D93: the real pending count; the action is unavailable (dimmed, as the Save row's D92) until the review page.
// D93: the real pending count; Review metadata opens Needs review (the concept's go-review).
'3 ambiguous image links': row => ({ ...row,
title: `${number(overview.needs_review.pending)} ambiguous image link${overview.needs_review.pending === 1 ? '' : 's'}`,
action: { ...row.action, opacity: '0.55', cursor: 'not-allowed' } }),
title: `${number(overview.needs_review.pending)} ambiguous image link${overview.needs_review.pending === 1 ? '' : 's'}` }),
// D93: no backup has been recorded (verified backups arrive with S8).
'Backup status': row => ({ ...row, description: 'No retained backup record.' }),
// D93: there is no paging, so the shared settings are grid and density.
@@ -231,11 +230,10 @@ for (const theme of THEMES) for (const [width, height] of SIZES) {
});
}
// The recorded differences, by path: D93 the review row (its real count, dimmed action), the backup row, the
// The recorded differences, by path: D93 the review row (its real count), the backup row, the
// preferences row and the sources row, and metric 4; D96 the statistics row; D92 the chip, the status and the dimmed
// Save; D122 the nav label. (The fixture's first three metrics are the concept's own counts.)
const UNMAPPED_PATHS = [
'columns.surfaces.0.rows.0.action.cursor', 'columns.surfaces.0.rows.0.action.opacity',
'columns.surfaces.0.rows.0.title', 'columns.surfaces.0.rows.1.description',
'columns.surfaces.1.rows.0.description', 'columns.surfaces.1.rows.1.title', 'columns.surfaces.1.rows.2.description',
'heading.actions.0', 'heading.actions.length', 'metrics.items.3.value', 'nav.label',
+6 -4
View File
@@ -168,15 +168,17 @@ test('a failed thumbnail read is unavailable, never zero', async ({ page }) => {
await expect(layout.locator('.metric').nth(2).locator('strong')).toHaveText('24');
});
test('ambiguous row reads the pending count; its action waits for the review page', async ({ page }) => {
test('ambiguous row reads the pending count and Review metadata opens Needs review', async ({ page }) => {
const layout = await openOverview(page);
const row = layout.locator('.operation').filter({ hasText: 'ambiguous image links' });
await expect(row.locator('h3')).toHaveText('0 ambiguous image links');
await expect(row.locator('p')).toHaveText('Review metadata before assigning a positive / negative pair.');
const review = row.getByRole('button', { name: 'Review metadata', exact: true });
await expect(review).toHaveAttribute('aria-disabled', 'true');
await review.click({ force: true });
await expect(page).toHaveURL(`${workspace}#/system/overview`);
await expect(review).not.toHaveAttribute('aria-disabled');
await review.click();
// The concept's go-review: the Needs review page.
await expect(page).toHaveURL(`${workspace}#/review`);
await expect(page.getByRole('heading', { name: 'Metadata review', exact: true })).toBeVisible();
});
test('View backups / Appearance / Manage sources switch sections', async ({ page }) => {
+1 -3
View File
@@ -322,9 +322,7 @@ function overviewNodes(overview, { scope, navigate, openStatistics }) {
const review = operationRow({ scope, title: ambiguousTitle(overview.needs_review),
description: Number.isSafeInteger(overview.needs_review?.pending)
? 'Review metadata before assigning a positive / negative pair.' : NOT_AVAILABLE,
label: 'Review metadata', onClick: () => {} });
// D93: the row reads the queue's pending count; its action waits for the Needs review page (#288).
review.querySelector('button').setAttribute('aria-disabled', 'true');
label: 'Review metadata', onClick: () => navigate('#/review') });
const [sourcesTitle, sourcesDescription] = sourcesCopy(overview.sources);
const thumbnails = operationRow({ scope, title: THUMBNAILS_LOADING, description: 'Generate only missing previews when necessary.',
label: 'Review thumbnails', onClick: go('sources') });