Skip to content

feat(ui): make the View Definitions page a live playground (#752) - #878

Merged
smunini merged 2 commits into
mainfrom
feat/752-vd-playground
Sep 2, 2026
Merged

feat(ui): make the View Definitions page a live playground (#752)#878
smunini merged 2 commits into
mainfrom
feat/752-vd-playground

Conversation

@andyguz17

Copy link
Copy Markdown
Contributor

Summary

The View Definitions page (/ui/sql/view-definitions) becomes a playground: the CodeMirror editor sits in a plain card with a "Runs as you type" hint, and a results card below follows whatever the editor currently holds, saved or not. Opening a view shows its rows without a click; each pause while typing refreshes the table half a second later. The Run link (?run=1, which reloaded the page and executed the saved definition) and the <details> JSON fold are gone.

When the JSON is broken or $sql-run rejects the document, a warning appears above the table, the editor is left untouched, and the previous table stays with its meta relabelled "last successful run". Save and Duplicate remain plain forms.

Scope note

Point 4 of #752 (reusing the Edit Resource highlighted JSON view) was superseded by #753 / #820: the page already runs CodeMirror 6 with FHIRPath highlighting and server-side lint, so json_view is not reintroduced. The no-JavaScript path is "Save shows results" (same choice as #839 for SQL Query/View), not a <noscript> Run button.

Changes

  • POST /ui/sql/view-definitions/run (commit 1): an htmx fragment endpoint that runs the posted document inline through $sql-run (capped at 50 rows), measures the call, and returns the results card with its N rows · T ms meta. Invalid JSON and failed runs also answer 200 so htmx swaps the notice in; the failure response ships only the #vd-run-notice warning plus an out-of-band #vd-results-meta relabel, leaving the client's table alone. A body without json is rejected by the form extractor (422). The document is never logged (constants may carry PHI). No REST or $sql-run changes.
  • Shared results partial partials/sql_run_results.html: one markup for the page's initial render and the fragment, ready for ui: SQL Query & SQL View — editor-first layout with live results #839 to reuse. I18n::t_arg2 mirrors the HTS helper for the two-placeable meta string.
  • Playground page (commit 2): editor card with hint, textarea wired with hx-post on input changed delay:500ms, a load-triggered first run when a selection opens, ?saved=1 rendering the saved definition's table server-side (and suppressing the load trigger so scripted pages never request results twice), fallback textarea bounded to the editor's 320px/70vh through a page-scoped rule. No new JavaScript: the existing CodeMirror mount already syncs keystrokes into the textarea.
  • An empty, classless #vd-results placeholder is rendered while no table exists — htmx drops an out-of-band swap whose target is missing, so the very first successful run would otherwise never paint its card.
  • details.json-fold and the vd-run key stay: sql-library.html, capability-statement.html and editor-body.html still use them (ui: SQL Query & SQL View — editor-first layout with live results #839 owns their removal). The design-system guard now exempts CodeMirror's runtime classes (cm-*, ͼN style-mod hashes), which surface whenever the page opens with a restored selection.
  • Docs (crates/ui/README.md), i18n keys vd-run-hint, vd-results-meta, vd-results-stale in en/es/de.

Test plan

  • cargo test -p helios-ui: six HTTP tests over /run (success, empty, invalid JSON, failed run, missing field, page composition), the ?saved=1 round trip, and the load-trigger contract.
  • Playwright chromium: live edit updates the header without reload, broken JSON keeps the table and relabels the meta, ?vd=new runs the starter document; design-system guard green with a restored selection. nojs: with JavaScript disabled the results region only fills after Save.
  • Manual pass over the six UI scenarios (create, live edit + undo, break/fix JSON, save, no-JS save, SQL Query/View pages untouched).

Closes #752.

… partial (#752)

Add `POST /ui/sql/view-definitions/run`, an htmx fragment endpoint that
previews whatever document the editor currently holds: it runs the posted
ViewDefinition inline through `$sql-run` (capped at `sql_views::RUN_LIMIT`,
50 rows), measures the call, and answers with the results card and its
`N rows · T ms` meta. Invalid JSON and failed runs also answer 200, so
htmx swaps the notice in instead of leaving the page mute; the failure
response ships only the `#vd-run-notice` warning plus an out-of-band
`#vd-results-meta` relabelled "last successful run", leaving the previous
table untouched. A body without the `json` field is rejected by the form
extractor (422). The document is never logged (constants may carry PHI).

The results card now lives in one place, `partials/sql_run_results.html`,
rendered both by the page's own initial render and by the fragment, and
ready for the SQL Query/View pages to reuse. `I18n::t_arg2` mirrors the
HTS helper for the two-placeable meta string; `vd-results-meta` and
`vd-results-stale` land in all three catalogs. Six HTTP tests cover the
success, empty, invalid-JSON, failed-run and missing-field paths.
Drop the Run link and the JSON fold: the editor now sits in a plain card
with a "Runs as you type" hint, and the results card follows the current
document, saved or not. The wiring is htmx only — the textarea posts to
the `/run` fragment on `input changed delay:500ms`, and the empty notice
region fires one `load` request when a selection opens, so opening a view
shows its rows without a click. No new JavaScript: the CodeMirror mount
already syncs every keystroke into the textarea.

Without JavaScript the page keeps working through Save: the `?saved=1`
round trip renders the saved definition's table server-side, and when
that happened the load trigger is not emitted, so scripted pages never
request the results twice. `?run=1` no longer executes anything. The
fallback textarea loses `rows="18"` and takes the editor's 320px/70vh
bounds through a page-scoped rule, leaving `.json-editor` untouched.

The page renders an empty, classless `#vd-results` placeholder while no
table exists: htmx drops an out-of-band swap whose target is missing, and
the very first successful run would otherwise never paint its card.

`details.json-fold` and the `vd-run` key stay: `sql-library.html`,
`capability-statement.html` and `editor-body.html` still use them (#839
owns their removal). The design-system guard now exempts CodeMirror's
runtime classes (`cm-*`, `ͼN` style-mod hashes), which surface whenever
the page opens with a restored selection. Rust tests cover the saved
round trip and the load trigger; Playwright covers the live edit,
broken-JSON recovery, `?vd=new`, and the no-JavaScript Save path.
@codecov

codecov Bot commented Sep 2, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@smunini
smunini merged commit 45729bb into main Sep 2, 2026
26 checks passed
@smunini
smunini deleted the feat/752-vd-playground branch September 2, 2026 12:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

ui: make the View Definitions page a live playground — drop Run, drop the JSON fold, reuse the editor's highlighted JSON view

2 participants