Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Teagle ⇄ reference eXplorer (tx.helex.dev) — parity spec

Comparison of the deployed reference Terminology eXplorer (tx.helex.dev) with the current Teagle web, and specs for the missing pages to add. Per direction: hold the existing Teagle pages (Servers, Catalog, Expand playground, Authoring, Operations) and add the ones below.

Reference eXplorer — navigation (observed)

Menu: Dashboard (Landing page · Global Search) · Terminology (Code systems · Value sets · Concept maps · Structure definitions · Structure maps) · Summary (Topology). Header: logo → /landing, language, GUEST, overflow menu, global search box. Resource detail opens at /fhir/{Type}/{id} (content-negotiated: browser → UI, Accept: application/fhir+json → FHIR).

Page inventory & gap

Reference pageRouteTeagle todayAction
Landing / Ecosystem dashboard/landingServers (plain table)ADD dashboard (richer); keep Servers
Global Search(search box)Catalog search onlyADD cross-resource search page
Code systems (list)/terminology/code-systemsCatalog (unified CS/VS/CM tabs)ADD per-type pages; keep Catalog
Value sets (list)/terminology/value-setsCatalogADD per-type
Concept maps (list)/terminology/concept-mapsCatalogADD per-type
Structure definitions (list)/terminology/structure-definitions— (none)DONE
Structure maps (list)/terminology/structure-maps— (none)DONE
Topology/terminology/topology— (none)ADD graph view
Rich resource detail/fhir/{Type}/{id}Catalog row → raw JSONADD rich detail (tabs + content)
FHIR API landing / dev hub/fhir (text/html)— (none)ADD static hub (content-negotiated)
Operation Examples(from /fhir hub)Expand playground + OperationsREUSE existing (link/seed)
Health(from /fhir hub)ADD trivial status page
Expand playground✔ (Teagle-only, keep)keep
Authoring (editable server)✔ (Teagle-only, keep)keep
Operations console✔ (Teagle-only, keep)keep

Specs for the missing pages

1. Ecosystem Dashboard (Landing) — /teagle/ landing

Structure (observed): a Resources stat card row — Total Code Systems / Value Sets / Concept Maps / Structure Definitions / Structure Maps (each a link to its list page); a Server types stat row — FHIR servers / NPM package targets / IG package targets / Open (public) targets; then one card per server: name + type badge (FHIR / NPM PACKAGE / IG), FHIR versions, Supported Operations chips ($expand/$lookup/$validate-code), and per-type counts (CS/VS/CM/SD/SM). Top search box. Data: /api/catalog/stats (per-server + totals) + /api/servers (kind, ops, fhir versions). Use @helex/ui stat/AppCard + ResourceList where tabular. Keep the current Servers page as the detailed registry table; Dashboard is the overview landing.

2. Global Search — /teagle/search

A single search box that queries all catalogued resources across servers by url / id / title (and optionally concept text), returning a merged ResourceList grouped or badged by resource type + owning server, row → detail. Data: /api/catalog?text=… (extend with a cross-type ?q= if needed). Debounced; type/server facets.

3. Per-type resource lists — /teagle/terminology/{code-systems|value-sets|concept-maps|structure-definitions|structure-maps}

ResourceList per type: columns ID (link → detail) · Last version · Title · Publisher · Status · Count (concept count for CS; expansion size for VS; mapping count for CM), expandable rows (versions), title/id filter + funnel (server, status). Data: /api/catalog?type=CodeSystem etc. + /fhir/{Type}?url=. SD/SM — DONE. The catalog scan indexes both types (HttpCatalogScanner.DEFAULT_TYPES, trimmable via teagle.catalog-scan.types) and TeagleResourceController serves them, so the same generic list page covers them. Their column set differs from the reference’s only where the reference itself differs: SD adds Type (the constrained base type) and Kind, SM leads with Name instead of Title, and neither carries a Count (a StructureDefinition “count” would mean pulling the whole snapshot per row).

4. Topology — /teagle/topology

A force-directed graph of the ecosystem: nodes = resources (colored by type CS/VS/CM/…), edges = references (VS→CS via compose, CM→CS via source/target), grouped by owning server. Zoom (+/−), fit, layout toggle, filter (type/server). Use a graph lib bundled self-contained (no external CDN). Backend: DONEGET /api/topology (implemented) returns the Cytoscape shape { catalogVersion, truncated, elements: { nodes:[{data:{id,label,resourceType,server}}], edges:[{data:{id,source,target,kind}}] } }. Nodes are one-per-canonical (type,url) from the catalog; edges are derived server-side (ValueSet compose composes/imports, ConceptMap group source/target, *-scope), only between catalogued nodes (delegated-but-uncatalogued systems e.g. SNOMED are omitted), cached per catalogVersion. Node id is "{type}|{bare-url}"; the frontend just renders the elements.

5. Rich resource detail — /teagle/fhir/{Type}/{id} (replaces the raw-JSON view)

Tabs Description | Concepts/Expansion/Mappings/Elements | JSON | XML (content-negotiated fetches). The header shows the title in the UI language (resolved over the _title translation extensions). Description stacks, in this order (same for every resource type): the other titles the resource carries, one ET / EN-chipped line each → a metadata card (Official URL, Version, status/date, Computable Name, Flags, Server source badge — which registry server served it) → Definition (the localized description) → Properties (CS property declarations: Code / Description / Type with its ValueSet-or-CodeSystem binding / URI) → Relations (CS “used in value sets”; VS “includes systems”; CM source/target; SD base definition + the profiles its differential references; SM its structure[] and import[]) → the sanitized Narrative (text.div) last, since it only restates the above. The content tab holds — for CS: a concept table (Code / Display with multi-language designations / Properties) with search + total; for VS: the merged expansion (reuse the Expand playground’s source-colored ResourceList); for CM: the mappings table (source → target, relationship); for SD: the element tree (FhirStructureDefinitionViewer from @helex/fhir — the same viewer TEDY uses: merged snapshot + differential, slices as children, Σ/?!/C flags, cardinality, types with their target profiles, binding links, and its own diff/hybrid/snap control). SM has no content tab — its groups and rules are the body, which the JSON tab already shows, and the reference renders nothing for maps either. Data: /fhir/{Type}/{id} (+ ?_format), and the ops the resource supports.

6. FHIR API landing / developer hub — /teagle/fhir (static GET /fhir as text/html)

The reference serves a developer-facing docs page at /fhir (content-negotiated: browser → this HTML hub, Accept: application/fhir+json → the FHIR endpoint itself). It is the API entry point, structured as:

  • Intro — “FHIR R5 terminology endpoint with content negotiation”; the Base URL for clients (…/fhir) shown as a copyable code span; one-line “use as the base URL for CodeSystem, ValueSet, $lookup, $expand, $validate-code”.
  • Content Negotiation table — Accept header → result (text/html→Web UI, application/fhir+json / application/json→FHIR JSON, application/fhir+xml / application/xml→FHIR XML, none→FHIR JSON).
  • URL Patterns table — read (/fhir/ValueSet/foo), versioned (…/foo|1.0.0), formatted views (…/foo.json, …/foo.xml), concept lookup (/fhir/CodeSystem/foo/active), …/foo/$expand, /fhir/CodeSystem/$lookup (POST), /fhir/metadata.
  • Browse Resources links → Global Concept Search · CodeSystems · ValueSets · ConceptMaps · StructureDefinitions · StructureMaps (the per-type lists above).
  • Examples & Info links → Operation Examples ($lookup, $validate-code, $expand, batch Bundle) · Ecosystem (dashboard) · Topology · API documentation · Health.

For Teagle: serve a static FHIR API hub page at GET /fhir when Accept: text/html (mirrors the content-negotiation the reference uses), linking to the Teagle pages above. Two net-new leaf pages it references:

  • Operation Examples — a small page of ready-to-run $lookup/$validate-code/$expand/batch-Bundle request examples (Teagle already has the Expand playground + Operations console — this can link to them / seed them with the examples rather than a new page).
  • Health — a plain status page (/actuator/health or /api/health).

Backend touch-points (flag for the backend, mostly config/read-through)

  • SD/SM: catalog indexing + read-through for StructureDefinition/StructureMap (Flint routes, doesn’t own) — DONE (scan types + the resource/batch controller type sets). Topology emits SD/SM nodes but no baseDefinition/structure edges yet: deriving those means fetching profile bodies, which is only affordable once the fetch asks for _summary=true.
  • /api/topology graph endpoint — DONE (TopologyController; see spec #4 for the shape).
  • Global concept-search / concept-detail cross-references (/concept-search/{quick,harvest,cross-references}) — still needed.
  • /api/catalog/stats already exists (dashboard); /api/servers already exists.

Note

The reference eXplorer’s /fhir/{Type}/{id} content-negotiation (browser UI vs FHIR JSON on the same URL) is a routing nicety; Teagle can keep UI routes under /teagle/ and fetch FHIR from the backend /fhir/*.


Appendix A — source review of the reference frontend (tx-viewer)

Read of terminology-explorer/frontend/projects/tx-viewer/src/app (routes in app.routes.tsterminology/routes.ts + fhir/routes.ts; docs in docs/features/*). Corrections and additions to the above:

  • No ETag / conditional-request / IndexedDB anywhere in the reference. Its only caching is RxJS shareReplay(1), an in-memory ComponentStateStore, and sessionStorage. A stale-while-revalidate / ETag layer would be net-new for Teagle, not a port.
  • Concept-detail page is a distinct route we missed: /fhir/{Type}/{id}/{code}HlxTerminologyConceptDescriptionComponent. Header (code, display+lang, system uri, version), designations table, properties table (with binding-resolved codings), and parents / children / associations (cross-references) tables — each navigable. Add as a 7th missing page (net-new). Data: CodeSystem/$lookup (+ hierarchy properties) and a cross-references lookup (new backend endpoint).
  • Formatted .json / .xml view (/fhir/{Type}/{id}.json|.xml, FhirFormattedViewComponent) — pretty-print via Accept negotiation, copy/download. Folds into the Rich-detail JSON/XML tabs (spec #5).
  • /fhir/examples (FhirExamplesComponent) — server-rendered operation examples; the FHIR-hub (spec #6) Operation-Examples link can point at Teagle’s Expand playground / Operations console instead of a new page.
  • Resource detail two-step load (resource.component.ts): render the shell from ?_summary=true, then stream the full body — a real perf pattern worth adopting in spec #5.

Appendix B — ideas & optimisations to fold into Teagle (prioritised)

Backend support key: have = Teagle’s /api/{servers,catalog,catalog/stats,resolve} + /fhir/* already cover it; new = needs a backend addition.

Tier 1 (high value, backend already there):

  1. _summary=true on all list/detail reads — list views never need concept[]/expansion; seconds → tens of ms on LOINC/SNOMED-sized resources. (have)
  2. Two-step resource load — summary shell first, full body streamed after (spec #5). (have)
  3. Ecosystem dashboard stat-cards + server-type breakdown + per-server counts from catalog/stats + servers (spec #1). (have)
  4. Versioned-id |-- request rewrite in the teagleApi interceptor (Tomcat rejects %7C; java.net.URI rejects raw |) — Teagle already parses -- server-side. (have)
  5. Structured FHIR-error toasts — parse OperationOutcome in its several shapes; special-case the multi-server routing-conflict 500 into a sticky, actionable notice naming the conflicting servers (directly relevant to Teagle’s aggregation). (have)

Tier 2 (strong UX): 6. CDK-style virtual scrolling for concept lists/trees (flatten to visible rows) — 5k concepts 3000 ms→80 ms in the reference; use @tanstack/react-virtual for the CS/VS concept viewers + Expand playground. (n/a) 7. Size-adaptive metadata filter default — preselect all <2000, common-only 2000–5000, none >5000. (n/a) 8. Property-filter table — per-property tags input, AND across / OR within, client-side over the loaded concept list. (n/a) 9. List state + scroll restoration on back-nav (TanStack Query keepPreviousData + a scroll store). (n/a) 10. Debounced search standardised (reference: 250–500 ms per surface). (have) 11. Accept-Language + displayLanguage threaded into $expand/$lookup, showing the resolved-language chip. (have)

Tier 3 (larger / net-new): 12. Topology graph — Cytoscape + cose, type-colored nodes, client-side .filtered-out filtering, fullscreen; 503 + Retry-After retry while the graph builds. Needs a /api/topology endpoint (spec #4). 13. Concept-detail relations page (parents/children/associations) — $lookup (have) + a cross-references endpoint (new). 14. Global concept text-search + $lookup harvest/concept-search/{quick,harvest,cross-references} are new backend endpoints; $lookup/$validate-code exist. 15. 503 “backend warming up” banner + poll until ready — fits Teagle’s reloadable in-memory registry; needs a ready flag on an ecosystem/health endpoint.

Reference files worth lifting from: resource/resource.component.ts, resource/concept-description/concept-description.component.ts, resource/concepts-tree-view/*, resource/concepts-paginated-list/*, terminology/topology/*, terminology/global-search/*, landing/landing.component.*, core/http/* (interceptors: pipe-encoding, error-handling, lang, readiness).