feat(ui-core): schema foreshadowing banner on Ingest and Batches (#290) - #296
Merged
Conversation
useProjectReadiness composes the three queries the project header already runs — active schema, project stats, batches — so it costs zero requests on the project screen, and it is the single spelling of "has a schema" from here on: the schema-less 404 is an answer, any other failure means the hook answers null rather than guessing. currentStep walks labels -> images -> annotate -> export; "done" is declared and waits on hasReleases and an ingest-in-flight signal, both recorded as out of v1.
A Checklist pattern — every step rendered, one active, finished ones checked — driven on the project Overview by useProjectReadiness, so the strip costs no request the header was not already paying for. It renders above the stat tiles and above the empty state alike, because a project with nothing ingested is exactly the reader the journey exists for, and it retires itself at "done". Deliberately not an extraction of the ingest stepper: that one mounts only its active step and its tests pin the choreography. An upcoming step is plain text even when a callback exists — pointing three steps ahead lands somebody on a screen that refuses everything.
The schema gate stays server-side — approval still refuses with SchemaNotFound and nothing pre-checks it. What moves earlier is the foreshadowing: one Alert on Ingest and on the batch list, rendered only when useProjectReadiness positively answers hasSchema: false, with a link to the schema tab. Promoted into one SchemaForeshadow component rather than spelled twice, and no dismiss — the banner's exit is the remedy itself.
This was referenced Aug 4, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #290. Stacked on #295 (
journey/pr2-checklist) — merge order #294 → #295 → this.What
The schema gate stays exactly where it is — server-side, refused at batch approval — and the foreshadowing moves earlier: a quiet
Alert(its first consumer as an informational banner) on the two screens a user reaches before the gate, saying "You can ingest now — you'll need labels before annotating." with a "Define your labels" link.frontend/ui-core/src/screens/SchemaForeshadow.tsx, promoted rather than copied — two screens render it and two spellings of one warning are free to drift. Driven byuseProjectReadiness(Add useProjectReadiness hook and normalize the has-schema question #288): it renders only on a positivehasSchema: false; while readiness has no answer, nothing renders. No dismiss mechanism — the banner's exit is the remedy itself.IngestScreen: banner between the header and the stepper; new optionalonOpenSchemaprop. The stepper itself is untouched.BatchesScreen: banner under the header; new optionalonOpenSchemaprop.ProjectScreen: threadsonOpenSchemainto the Batches tab asonTabChange("schema"), only when the host controls the tabs.frontend/app/src/routes.tsx: the ingest route wiresonOpenSchemato/projects/{id}?tab=schema— spelling the URL is the shell's job.No client-side pre-validation anywhere: approval still goes to the server and renders whatever it answers.
Tests
gallery.test.tsx+2 (BatchesScreen): banner present without a schema and its link fires the callback; absent once a schema exists (asserted after the readiness sources have answered, so it is a decision, not a pending query).ingest.test.tsx+2: same pair, plus the assertion that the dropzone stays live under the banner — foreshadowing, not a gate.bash scripts/check.sh frontend: All checks passed (ui-core 393 tests / 26 files).Playwright
navigation.spec.ts shell.spec.ts gallery.spec.ts: 44 passed.