feat(v2-ui): integrate v2 schema/review pages into the app shell#232
Merged
Conversation
…ot the hook GetSchemasUseCase and GetReferenceReviewUseCase were typed as `typeof useXxx` and called `this.storage()`, but ts-injecty resolves a hook dependency by *calling* it and injecting the returned store object (same contract as v1's GetWorkspacesUseCase). At runtime `this.storage()` threw "this.schemasStorage is not a function", which the empty catch swallowed and surfaced as "Could not load schemas." on a 200 response. Use the injected value as an object (drop the `()`) and type it as ReturnType<typeof useXxx>. The unit tests passed the raw hook function — bypassing the DI contract — so they missed this; update them to pass the resolved store (useXxx()) as DI does. Verified live: the seeded e2e_v2_slice schema now renders in the table. Surfaced by the first end-to-end run of the v2 frontend e2e.
…badges in records table
…rumb strict-mode collision
- BaseButton `to` prop was declared `type: String | Object` (bitwise-OR evaluates to 0),
a malformed prop type that threw 'Right-hand side of instanceof is not an object' during
Vue dev-mode prop validation whenever a :to value was passed. This broke the schema-detail
page render (stuck spinner, no records) and was latent in DatasetCard/UserSettingsHeader/
QuestionsForm. Fixed to [String, Object].
- Reference-review breadcrumb rendered the bare reference, colliding with the page <h1>
'Review — {reference}' so getByText(reference) matched two nodes (e2e strict-mode
violation). Leaf is now the static 'Review' label; the <h1> still carries the reference.
Unblocks e2e/v2 auth-smoke + slashed-reference (both green).
v2 record bulk-upsert reads the pandera schema body from S3 via FileObjectResponse.response, which was annotated urllib3.HTTPResponse (from the old minio client, PR #149). aiobotocore returns the body as a StreamingChecksumBody, so pydantic's is_instance_of check rejected it and every v2 upsert 422'd. Relax the annotation to Any (consumers only stream the body via .read(); the existing validator still guards None) and add a regression test. Surfaced by the first end-to-end run of the v2 frontend e2e seed.
… search Combining an FTS query with a scalar filter called AsyncFTSQuery.where(clause, prefilter=True), but async LanceDB (0.34) where() takes only the predicate — the sync-only prefilter= kwarg raised TypeError, so every text+filter search 500'd. Scalar filters over an FTS match set apply as a postfilter, correct for the materialize-then-page model. Add a regression test covering FTS+filter narrowing and the non-matching-token empty case. Surfaced by the v2 search-roundtrip e2e (status filter + query).
…rops fill()
BaseInput debounces its update:modelValue emit (lazyEventEmitter, 100ms) while
re-rendering a controlled :value, so the DOM value resets to the stale model on
each keystroke — losing characters under fast typing and dropping Playwright
fill() entirely (the emitted value arrives as ''). A tokenized native input with
v-model + @keyup.enter is immediate and lossless, and matches the search-roundtrip
spec's fill + press('Enter') contract. Styled with design tokens for visual parity.
The HANDOVER.md file has been deleted as it contained outdated information regarding PR #214 and its verification results. This cleanup helps maintain the repository's documentation relevance.
|
The latest updates on your projects. Learn more about Vercel for GitHub. 1 Skipped Deployment
|
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.
What & why
Integrates the v2 vertical-slice pages (schemas list, schema detail, schema settings, reference review — merged in #230) into the app shell:
InternalPage+AppHeader+ workspace-aware breadcrumbs, design-system components (BaseButton, status badges, tokenized controls) replacing ad-hoc primitives, and consistent empty/error states. Executesdocs/superpowers/plans/2026-07-19-v2-ui-shell-integration.md.The plan was presentation-only, but getting the v2 e2e suite green surfaced three real bugs (one frontend regression, two backend) plus one prerequisite that had to be brought in — all included here and called out below.
Changes
Frontend — shell integration (presentation)
useEnsureWorkspaces(hydrates the workspace store on direct URL load of v2 routes — fixes the "empty schemas on hard reload" state) anduseV2Breadcrumbs(Home › workspace › Schemas trail). TDD, 4 tests.V2Empty+V2StatusBadgeshared components. TDD.e2e/v2selectors ([data-question],[data-reference],[data-record],[data-test=...]) preserved.Fixes required to pass the e2e gate
BaseButtontoprop type (3ac16521d): wastype: String | Object— a JS bitwise-OR that evaluates to0, a malformed prop type. Vue dev-mode validation then throws "Right-hand side of 'instanceof' is not an object" whenever:tois passed, which broke the schema-detail render and was latent app-wide (DatasetCard, UserSettingsHeader, QuestionsForm). Fixed to[String, Object].prefilterkwarg (4fa777343): FTS + scalar-filter search calledAsyncFTSQuery.where(clause, prefilter=True), but async LanceDB 0.34where()has noprefilterkwarg →TypeError→ 500 on every text+filter search. Fixed toquery.where(clause)(postfilter) + regression test.fa5dd96f1):BaseSearchBar→BaseInputdebounces itsupdate:modelValueemit while re-rendering a controlled:value, dropping characters under fast typing and losing Playwrightfill()entirely. Replaced with a tokenized native<input v-model @keyup.enter>on the detail page.<h1>DOI); dead#c00token fallback removed.Prerequisite cherry-pick (⚠️ see note)
cefe95e42cherry-picks551d0bd9f(FileObjectResponse.response: HTTPResponse → Any) fromfix/v2-fileobjectresponse-streaming-body. The plan names it as a required base, but this branch wasn't cut from that branch. It is unmerged with no open PR, so bundling it here is how it reachesdevelop. If it later gets its own PR, expect a duplicate/empty patch — reconcile before merging that one.Test evidence
npx vitest run)npx nuxi typecheckexit 0npm run lintclean (only pre-existing i18n false-positive warnings)ruffclean;test_fts_search_with_scalar_filter+test_filesregression tests passnpx playwright test --project=v2 --workers=1) — the CI-intended config (playwright.configsetsworkers: CI ? 1 : undefined).Reviewer notes / risk
BaseButtonprop-type fix touches a shared base component — low risk (strictly more permissive), but it changes behavior for all:toconsumers, so worth a glance.prefilterfix + theFileObjectResponsecherry-pick).extralit-server.yml(pytest) will exercise them in CI.