Skip to content

UI/wire: the orphan dialog counts the annotations that block a class removal but cannot link to them #699

Description

@JArmandoAnaya

The terminal dialog that refuses a class removal states how many annotations block it and across
how many assets, and then leaves the person holding a number with no way to reach the thing it
counts. The class-removal flow work (#588) asks for that link explicitly — the dialog should state
the fact, state the way out, and link to the annotations filtered to that class — and it is the one
requirement of that issue which cannot be built in the browser today, because nothing on the wire
can express the filter.

All citations are at 2e4346d.

What the dialog does now

OrphanBlockersDialog in frontend/ui-core/src/screens/SchemaEditor.tsx renders one line per
blocking class from the preview's typed report — the class name, its annotation count, its asset
count — and a single Close button. That is correct as far as it goes: the refusal has no override,
so a second button would be a lie. The counts come from POST .../schema/preview, so they agree
with what the publish would refuse over.

The remedy sentence is "Keep the class or remove the annotations first." Removing them means
finding them, and the product currently offers no way to do that for one class.

Why this is not a frontend task

No endpoint accepts a label-class filter. The three asset-listing routes are the whole surface, and
each takes pagination and nothing else:

GET /batches/{batch_id}/assets    ['limit', 'offset']
GET /datasets/{dataset_id}/assets ['limit', 'offset']
GET /projects/{project_id}/assets ['limit', 'offset']

A scan of openapi.json for any query parameter naming a class or a label returns nothing at all.
So a client cannot ask "which assets carry an annotation of class lane" without reading every
asset and filtering in the browser, which is the hand-mirroring the ui-capabilities contract
exists to forbid: the frontend never decides what is legal or derives a projection the wire declines
to make, and where a capability is missing the fix belongs in the wire rather than in a client-side
workaround.

There is a second, independent question underneath the first. Even given a filter, there is no
screen for the result. The gallery is scoped to a batch and the dataset view to a dataset, while the
count in this dialog is project-wide — it comes from a walk over every asset in the project. Sending
somebody to a batch gallery would show them a subset of what the dialog just counted, which is worse
than sending them nowhere, because the two numbers would disagree with no explanation for why.

What settling this looks like

  1. A wire filter. One of the asset-listing routes learns to narrow by label class, or a new
    route answers the question directly. Whichever shape is chosen, the scope it walks has to be the
    same scope SchemaService counts over, so the dialog's number and the list's length agree. Two
    independently written walks that agree by coincidence is the defect the typed preview report was
    introduced to end.
  2. A destination. The sitemap in the information-architecture skill gains an entry for
    wherever the filtered result lives, and the entry is added in the same change that creates it.
    A project-wide scope is what the count implies; if the answer is that no project-wide asset view
    should exist, then the dialog's remedy sentence has to change instead, and that is a legitimate
    outcome of this issue rather than a failure of it.
  3. The link. OrphanBlockersDialog gains one link per blocking class. ui-core is router-free,
    so it arrives as a callback prop from the app package the way other cross-screen navigation does,
    not as an imported router.

Acceptance criteria

  • Either the wire declares a label-class filter over a project-wide asset scope and the sitemap
    names where its result is shown, or a written decision records that it will not and the dialog's
    remedy copy is rewritten to match what the product can actually offer.
  • If the filter ships: the count in OrphanBlockersDialog and the number of results behind the link
    are the same number, and a test ties them together rather than asserting each separately.
  • No client-side reconstruction of the filter. A browser-side walk over every asset does not satisfy
    this issue.
  • The dialog gains no second button. The refusal still has no override, and this issue does not
    change that.

Notes

The counted report the dialog renders arrived with the typed narrowing refusals, and the dialog
itself was rebuilt in the pull request that gave the narrowing confirmation its blast radius
(#698). Neither touched the link, and both left the remedy sentence as it stands.

Metadata

Metadata

Assignees

No one assigned

    Labels

    apivisionset.server — REST API and OpenAPI contractenhancementNew feature or requestfrontendannotator / ui-core / app packagesuxUser experience / interaction design

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions