Skip to content

feat(ui): success-filled batch bars, and a one-job batch drawn flat - #794

Merged
JArmandoAnaya merged 4 commits into
mainfrom
feat/batch-surfaces-single-job
Aug 26, 2026
Merged

feat(ui): success-filled batch bars, and a one-job batch drawn flat#794
JArmandoAnaya merged 4 commits into
mainfrom
feat/batch-surfaces-single-job

Conversation

@JArmandoAnaya

Copy link
Copy Markdown
Contributor

Closes #789

What changed

The annotation progress bar. Progress gains a success variant beside its primary default and takes its ref as a prop rather than through forwardRef. BatchProgressBar draws the batch's annotation as an 8 px success fill on a muted track with a border hairline, so an empty bar reads as an empty track; the batches list and the gallery header share it, and a draft row says "Not approved yet" instead of counting work it has no jobs for. The job header's bar takes the same variant. Ingest and model-download bars keep primary, and the styleguide shows the new variant beside the old.

A one-job batch draws its job flat. With exactly one job the gallery renders no accordion and no job-level bar: the job's door (Annotate, Continue or View), Pre-label and the assignee sit under the batch header, followed by that job's filter, order, timeline and frames in one bordered panel, and the batch bar is the page's one bar. The assignee reads as a line — Assigned to ‹name›, or Unassigned — with the name itself as the control. From two jobs the accordion stays as it was, each header naming its assignee (Unassigned when nobody has it) and keeping Assign as a button in the open panel.

The accordion's leftovers. The pieces both the screen and the accordion mount — the toolbar, the timeline, the door, the assignee editor and the panel body — move to screens/GalleryControls.tsx, so JobPanels no longer imports GalleryScreen while GalleryScreen imports it; the import graph is a tree. A closed panel's header carries no aria-controls, since its panel is unmounted and an id pointing at nothing is a broken reference rather than a closed one. Each job's filter, order and selection are kept by job id, so reopening a panel restores them and the other job starts from All. The view is patched per field at write time: the grid reports its selection from an effect that can run after a filter change, and a whole-view write from it put the old filter back.

The wire reads what it publishes. BatchOut.of took None for pre_label_run by default, so a route that forgot the read published a batch nobody had pre-labeled. The parameter is now required, as JobOut.of already had it, and every projection does the read — including the membership projection and the page of batches holding an asset. openapi.json and the generated client are unchanged.

Rules and docs. The information-architecture skill's two rules on the gallery are rewritten (one job flat under the header, an accordion from two; the door is the job's and the header carries the transition; the filled control is the header's step while the batch has one and the navigation column's Annotate once it is open). docs/content/ui.md's accordion section, its The way in and the pre-label sentence describe both shapes. The sitemap block itself is unchanged: no route, tab or entry point moved, and the open panel is still not in the URL.

Revoked guards

No test was deleted or skipped. These asserted the old shape and now assert the same property against the new one:

Test Was Now
jobPanels.test "falls back to the default when the open job is no longer in the batch" one job left reopens its panel one job left renders flat, no accordion
jobPanels.test "says an unassigned job has nobody rather than nothing" Unassigned
gallery.test "the job panel's way into the annotator" (whole suite) waits for job-panels waits for job-workspace; the header holds neither trigger
gallery.test "the jobs accordion" assignee suite Assign button in the open panel Unassigned line in the flat workspace (the two-job case keeps the button)
cycle.spec "the job panel is the way in" walks job-panels walks the flat workspace of the one job approval created

New guards: the flat single-job structure (vitest and e2e), one progress bar on the page, the filled-control invariant in both directions (none on in_annotation, exactly the header's step on approved), aria-controls only while a panel exists, a job's filter and order restored on reopen, BatchProgressBar's fill, hairline and draft readout, the Progress variant and ref, and the batches-list bar's fill and track colours read back in a real browser.

Test plan

  • scripts/check.sh in full on c276150: frontend build; annotator 1071, ui-core 1343, app 11 tests; frontend lint; openapi, generated-client and MCP tool-reference drift; version sync; annotator + app e2e (chromium) 281 passed; browser cycle, real server (chromium) 1 passed. The docs site, which check.sh skipped, built by hand: 48 pages, 4422 internal links resolve; docs_links, design_tokens and wire_rosters gates 25/25.
  • The python tests step was red on its first run and green on the re-run — see below.
  • Visual pass against a live workspace on this commit: batches list at 100 % and at 31 of 48, a one-job in_annotation gallery, and a two-job approved gallery with one assigned job.

A baseline flake, not this branch's

The first check.sh run failed two tests in tests/scripts/test_cooldown_lockfile.pytest_an_interrupted_first_pass_changes_nothing and test_an_interruption_during_the_snapshot_changes_nothing — with assert 0 == 130: the simulated kill landed after the wrapper had finished, on worker popen-gw18. Nothing in this diff touches scripts/cooldown.sh or tests/scripts/. Both tests pass in isolation on unmodified main at 9399430 (2 passed in 0.34s) and on this branch (2 passed in 0.10s); the file passes under the configured parallelism four times in a row on each tree (49 passed); and the python step re-run exactly as check.sh runs it answers 4479 passed, 33 skipped in 44.16s. The two tests time a signal against a live uv add, and lost the race under the full corpus's load.

Also fixed

Nothing beyond the scope above. The three items PR #783 recorded as found but not fixed are all in this change, as is the forwardRef in Feedback.tsx.

The Progress primitive gains a success variant beside its primary default and
takes its ref as a prop. BatchProgressBar draws the batch's annotation as an
8px success fill on a muted track with a border hairline, in the list and the
gallery header alike, and a draft row says it is not approved yet rather than
counting work it has no jobs for. The job header's bar takes the same variant;
ingest and model-download bars keep primary.
The constructor took None for pre_label_run by default, so a route that forgot
the read published a batch nobody had pre-labeled. The parameter is now
required, as JobOut.of already has it, and every projection does the read.
With exactly one job the gallery renders no accordion and no job-level bar:
the job's door, Pre-label and assignee sit under the batch header, followed
by the filter, the order, the strip and the grid, and the batch bar is the
page's one bar. The assignee reads as a line — Assigned to <name>, or
Unassigned — with the name as the control. From two jobs the accordion stays,
each header naming its assignee.

The pieces both the screen and the accordion mount move to GalleryControls,
so JobPanels no longer imports GalleryScreen while GalleryScreen imports it.
A closed panel's header carries no aria-controls, since its panel is
unmounted, and each job's filter, order and selection are kept by job id so
reopening a panel restores them. The view is patched per field at write time:
the grid reports its selection from an effect that can run after a filter
change, and a whole-view write from it put the old filter back.
The cycle scenario and the gallery specs walk a one-job batch as the flat
workspace it now is, and a single-job scenario sits beside the two-job one.
The information-architecture rule and the UI reference describe both shapes:
one job flat under the header, an accordion from two.
@JArmandoAnaya
JArmandoAnaya merged commit 51943f7 into main Aug 26, 2026
15 checks passed
@JArmandoAnaya
JArmandoAnaya deleted the feat/batch-surfaces-single-job branch August 26, 2026 11:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Batch surfaces: success-filled list bar, and a single-job batch detail without the job layer

1 participant