feat(ui): SearchParameter viewer (#238) + Compartment viewer & route tester (#237) — read halves#252
Open
angela-helios wants to merge 5 commits into
Open
feat(ui): SearchParameter viewer (#238) + Compartment viewer & route tester (#237) — read halves#252angela-helios wants to merge 5 commits into
angela-helios wants to merge 5 commits into
Conversation
Implements the read halves of #238 and #237 in helios-ui, following the docs/237-238-mockups designs on the existing design system. /ui/search-parameters (#238): read-only viewer over the same snapshot the storage backends seed their registries from (embedded fallback + the spec bundle in HFS_DATA_DIR, first canonical URL wins). Resource Filter rail with live counts and a Recently-used group (localStorage enhancement; everything else is links + GET forms, so the page works without JavaScript), type/source facet rows scoped to the current base, pagination instead of a render cap, and a detail panel with (base, code) slot chips per the #242 precedence semantics - cross-source shadows are informational overrides, same-source collisions are the blocking DuplicateCode conflict - plus empty-expression / missing- target warnings and the choice-type rewrite note. A missing spec bundle renders a visible warning instead of under-reporting silently. Write paths stay off pending #235, and the page says so. /ui/compartments (#237): definition rail with member counts, read-only Definition tab, Members tab with member/excluded chips and per-type linking params, and the tester. Everything membership-shaped resolves through helios_fhir::compartment_params() - the codegen'd table the REST compartment handler consults - so the tester's member / 404 + OperationOutcome / *-fan-out / {def} answers are the answers the API gives. Definition metadata comes from the spec CompartmentDefinition JSONs vendored under crates/ui/data/ (include_str! across crates would break cargo package); a parity test asserts every (compartment, type) slot matches the codegen table for every enabled version, so the vendored copies cannot drift silently. The questionnaire.json oddity (no code, zero resources) is not vendored, per issue open question 4. helios-ui grows R4/R4B/R5/R6 features forwarded from hfs (helios-ui?/…) so the version pill covers exactly the versions the server is built with; mount() takes the data dir. Semantic --ok/--warn/--danger tokens join app.css for both themes, held off the accent hue. Sidebar's Compartments entry goes live and Search Parameters joins the Server section; strings in en/es/de. Verified end to end against a running hfs: both pages serve the real R4 registry (1377 definitions; Patient 66/145 members), the tester round-trips member, 404, and fan-out cases, and the ES locale renders.
…es) into feat/237-238-registry-compartment-ui # Conflicts: # crates/ui/assets/app.css # locales/de/main.ftl # locales/en/main.ftl # locales/es/main.ftl
…results
Grows the queries page's Search Builder to the rest of the hi-fi console
design, on top of the featured GET URL:
- Visual rows in two-way sync with the URL: Conditions (parameter /
modifier / value, add and remove), Includes (_include/_revinclude with
:iterate), and Result controls (_count/_sort/_total/_summary/_elements).
Colon modifiers rejoin onto the key, comparator prefixes (ge, le, ...)
onto the value, matching how FHIR search actually spells them. Editing
the URL re-derives the rows; editing a row rewrites the URL.
- Parameter suggestions come from the server's SearchParameter registry:
GET /ui/queries/params?type=X returns a datalist fragment (options
labeled with the parameter type) rendered from the same snapshot the
SearchParameter viewer reads, swapped per resource type as the URL's
type changes. Server-rendered hypermedia, not a UI-facing JSON API.
- Run now executes in-page against the FHIR REST API itself and renders
the Bundle: total (with an included-resources count when _include is in
play), a table whose columns honor _elements with compact formatting
for common shapes (HumanName, CodeableConcept, Reference, Quantity),
row links to the resource, OperationOutcome diagnostics on errors, and
paging over Bundle.link. Explicit runs still record to recentSearches;
paging does not. An Open-in-new-tab link keeps the old behavior a click
away, and /ui/queries?url=... deep-links straight into a loaded builder
and executed search.
- Global [hidden] { display: none !important } so script-toggled regions
(pager buttons, builder sections, the rail's recents group) cannot be
un-hidden by their class display values.
Verified against a running hfs with seeded Patients: the deep link
renders condition and control rows from the URL, the datalist swaps to
the Patient catalog (birthdate et al.), and the search renders '2
results' with name/gender/birthDate columns and formatted HumanNames.
Contributor
Author
|
Verified against a running hfs with seeded Patients (screenshots below reflect |
Adds the hi-fi Search screen's remaining FHIR-applicable piece: a left
rail listing every resource type of the version, sourced from the spec
CompartmentDefinitions already vendored for the compartment viewer (each
enumerates the full set - 145 in R4), so no new dependency. Picking a
type re-keys the builder to GET /{Type} and runs the browse; a filter
box narrows the list client-side; the active type tracks the URL.
Counts hydrate client-side through the standard count-only search,
_summary=count, a few requests at a time so 145 types don't stampede
the server. _total=accurate rides along because this server only
computes Bundle.total when asked explicitly, even under _summary=count
- that gap is worth fixing server-side, at which point the extra
parameter is harmless.
The page goes content-wide with the rail | builder+results layout of
the design. The hi-fi's AI search panel is deliberately not included:
natural-language-to-URL translation is not a FHIR capability and needs
a backend HFS does not have; it stays a follow-up.
Verified against a running hfs with seeded data: counts render per type
(including real zeros), clicking a type browses it in-page, and the
deep-linked builder + results still work.
This was referenced Jul 14, 2026
…-compartment-ui # Conflicts: # Cargo.lock # crates/hfs/src/main.rs # crates/ui/src/lib.rs # crates/ui/templates/layouts/base.html # crates/ui/tests/router_http.rs
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.
Implements the read halves of #238 (SearchParameter viewer) and #237 (Compartment viewer + route tester) in
helios-ui, following the interactive mockups from #247, the standalone hi-fi console design, and Brett's Figma file (CcLtq79cH2aHv4Ii9aNQTP). Stacked on #241 (feat/234-saved-queries); retarget/rebase once that merges.Scope: the slice both issues said to ship first
sp-writes-pending).GET /ui/search-parameters(#238)load_embedded()fallback first, thenload_from_spec_file()fromHFS_DATA_DIR(default./data), first canonical URL wins — mirroringSearchParameterRegistry::register. A missing spec bundle renders a visible warning instead of silently under-reporting. Lazily loaded per FHIR version, cached for the process lifetime.base → code → paramouter map. Recents are a progressive enhancement (resource-filter.js, localStorage); everything else is links + a GET form, so the page works with JavaScript disabled.(base, code)shadow renders as informationaloverrides spec/shadowed; a same-source collision is the blockingconflict(DuplicateCode). Warnings for empty expressions (extractor indexes zero rows) and reference params without targets; informational note for choice-type expressions (rewrite_choice_types()).helios-uigrew version features, forwarded fromhfsviahelios-ui?/…).GET /ui/compartments(#237)members / totalcounts (Patient 66/145 etc.), Definition tab (canonical URL, status,search/experimental, publisher, description — read-only, stated as such), Members tab withmember/excludedchips, per-type linking params, and the Members · All types · Excluded filter.*). Resolves throughhelios_fhir::compartment_params()— the same codegen'd table the REST compartment handler consults — so the answer here is the answer the API gives:subject=Patient/example OR performer=Patient/example),*→ fan-out across member types, with the skipped-not-failed note matching the handler'sfilter_map,{def}(e.g. Encounter in its own compartment) → explained as the compartment resource itself.CompartmentDefinitionJSONs vendored undercrates/ui/data/compartments/(the same filesfhir-gencompiles; the crate can'tinclude_str!across crate boundaries without breakingcargo package). A parity test asserts every(compartment, type)slot in the vendored copies matches the codegen table, for every enabled version — the vendored data cannot drift silently. Thequestionnaire.jsonoddity (nocode, zero resources) is not vendored, per issue open question 4.Design
Both pages implement the #247 mockups on the existing design system:
app.csstokens, Figtree, the card/radius/shadow scale from the Figma Dashboard frames, and the Search screen's table styling. New semantic tokens--ok/--warn/--danger(+ soft variants) are held off the accent hue, defined for both themes. The pages reuse the crate's htmx-first conventions: server-rendered pages at real URLs,hx-boostfor swaps, anhx-selectlive rail filter — no client-side state beyond the recents enhancement.The sidebar's Compartments entry goes live, and a Search Parameters entry joins the Server section; strings added to en/es/de.
Tests
get_compartment_params()output, all versions.{def}cases against real R4 data (Patient 66 members,subject OR performer, etc.).overrides/shadowed, same-source →conflict.mount(), including the tester round-trip and detail-panel selection.Notes / follow-ups
mount()now takes the data dir:helios_ui::mount(app, version, config.data_dir.clone()).load_custom_from_directory,Configsource) aren't in the snapshot yet — worth folding in together with Store SearchParameters in storage; make the in-memory registry a TTL cache over it #235's storage-backed registry, which is also when the editor's create/override/delete lands.Groupcompartment.Closes nothing yet — read halves only; #238 and #237 stay open to track the write paths.