Skip to content

app: the annotator is unreachable from the UI — gallery tiles are disabled and nothing routes to /jobs/:jobId #160

Description

@JArmandoAnaya

Found by manual testing of the shipped 0.0.1b1 wheel.

What happens

There is no way to reach the annotator from inside the app. The whole point of the product — open an asset and label it — is reachable only by typing a URL.

Three facts, each verified in the running app:

  1. Every tile in the batch gallery renders disabled, so clicking one does nothing.
  2. The annotator's own "Open the gallery" button in the top bar is disabled.
  3. Nothing anywhere navigates to /jobs/:jobId. Grepping the frontend for navigation to that path returns only API calls in frontend/ui-core/src/annotator/jobQueries.ts.

I reached the annotator during testing only by pasting /ui/jobs/{jobId} into the address bar, having read the job id out of the REST API. A user has no way to discover it.

Root cause

frontend/app/src/routes.tsx:129-133:

function Gallery(): JSX.Element {
  const { projectId, batchId } = useParams();
  if (projectId === undefined || batchId === undefined) return <NotFound />;
  return <GalleryScreen projectId={projectId} batchId={batchId} />;   // no onOpenAsset
}

GalleryScreen takes an optional onOpenAsset (frontend/ui-core/src/screens/GalleryScreen.tsx:54) and renders each Tile disabled when it is absent (line 134):

{...(onOpenAsset === undefined ? {} : { onOpen: () => onOpenAsset(asset) })}

Every sibling route wires its callbacks — Projects passes onOpenProject (line 111), Project passes onIngest / onOpenBatch / onOpenDataset (lines 122-124). Gallery passing none looks like an omission rather than a decision, and the ui-core-takes-navigation-as-a-callback contract documented at lines 101-108 is exactly what makes it a one-line class of fix.

The design question that has to be answered first

It is not purely a missing callback, because the two screens are keyed on different things:

  • the gallery lists assets in a batch (/projects/:projectId/batches/:batchId)
  • the annotator is keyed on a job (/jobs/:jobId)

A batch is partitioned into jobs at approval, so an asset belongs to exactly one job — but the gallery's BatchAsset rows carry job_id only once the batch leaves draft (this is #29's deliberate shape: job_id/progress are null exactly while the batch is a draft). So:

  • For a draft batch there is no job to open, and tiles being inert is arguably correct — but they should say so rather than look broken.
  • For an approved batch, asset.job_id is present and the navigation is available without a new endpoint.

Recommended: navigate to the annotator positioned on the clicked asset, not merely to its job — otherwise clicking the fifth tile opens the job at its first asset, which reads as the click being ignored. That needs the annotator to accept an initial asset, e.g. /jobs/:jobId?asset={assetId} read through useSearchParams (already imported in routes.tsx:52). Confirm against AnnotationPage's current props before assuming it can be told where to start.

The reverse direction ("Open the gallery") needs the annotator to know its batch — GET /jobs/{job_id} returns batch_id, which is exactly what JobService.batch() was added for in #29 — and the project id to build the path.

Acceptance criteria

  1. Clicking a gallery tile in an approved batch opens the annotator on that asset.
  2. "Open the gallery" in the annotator returns to that batch's gallery, enabled whenever the job resolves.
  3. Tiles in a draft batch are inert and explain why (tooltip or disabled reason), rather than looking like a broken control.
  4. A Playwright spec walks project → batch → tile → annotate → back to the gallery entirely by clicking, with no direct navigation to a /jobs/ URL anywhere in the spec — that is the assertion that this cannot regress.
  5. Deep-linking straight to /ui/jobs/{jobId} still works.

Scope notes

Metadata

Metadata

Assignees

No one assigned

    Labels

    beta20.0.1-beta.2 — beta defect fixesbugSomething isn't workingfrontendannotator / ui-core / app packages

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions