Add proxied full-stack e2e (docker images + nginx) and fix DISTINCT sort crash#327
Open
felixevers wants to merge 10 commits into
Open
Add proxied full-stack e2e (docker images + nginx) and fix DISTINCT sort crash#327felixevers wants to merge 10 commits into
felixevers wants to merge 10 commits into
Conversation
* feat: backend-driven CSV/XLSX exports for task and patient table views
Virtualized infinite scrolling made DOM-based printing unusable for large
lists. Table views can now be exported server-side with the complete result
set of the current view:
- POST /export/{tasks|patients}: authenticated via the existing Keycloak
context, reuses the GraphQL list resolvers (same visibility, filters,
sorts, search and scope as the UI), capped by EXPORT_MAX_ROWS
- CSV: semicolon-separated, UTF-8 BOM, CRLF, locale-aware decimals, safe
against formula injection
- XLSX (openpyxl): print-ready ward list template with title block, styled
repeated header row, zebra rows, freeze pane, auto filter, A4 landscape
fit-to-width and page footer; dates as real cells with locale formats
- German/timezone handling: UTC values converted to the requested timezone
(default Europe/Berlin), date-only due-date sentinel kept as calendar
date, localized enum/boolean labels, UI-parity aggregated cells
(assignees, ward/room/bed from position ancestors, task progress, age)
- Frontend: export menu next to the column switcher sends the visible
columns in user order with localized headers plus the current
filter/sort/search/scope state; wired into patients, my tasks and saved
task views; new translations for all six locales
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BHhpBYXJpVeACm3JMWNFyA
* feat: export refinements — exporting user, select labels, row heights, patient todos tab
- XLSX header block and print footer now include the exporting user
("Erstellt am … von <name>")
- select / multi-select property values resolve their option keys
(<definitionId>-opt-<index>) to the definition's option labels, matching
PropertyCell.tsx; multi-select values are joined inline with a comma
- taller XLSX rows: 26pt header, data rows scale with wrapped content
(minimum 22pt); print orientation remains A4 landscape by default
- the patient detail tasks tab exports the patient's todo list
(done/title/description/due date/assignee, sorted open-first by due date)
via the patientId export scope
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BHhpBYXJpVeACm3JMWNFyA
---------
Co-authored-by: Claude <noreply@anthropic.com>
#318) * Add per-field update timestamps for patient state, clinic and position Adds state_updated_at, clinic_updated_at and position_updated_at columns to patients, stamped when the respective value actually changes. The timestamps are exposed as stateUpdateDate, clinicUpdateDate and positionUpdateDate on PatientType, filterable and sortable via the queryable fields API, included in table exports, and shown as patient list columns that are hidden by default and can be enabled through the column switcher. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KTFvWu2rNPeV3Q8wXKoht1 * Add patient field update timestamps to e2e mock backend Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KTFvWu2rNPeV3Q8wXKoht1 --------- Co-authored-by: Claude <noreply@anthropic.com>
Adds a row of small preset buttons below the due date input in the task creation drawer: Now, +1/+3/+6/+12/+24 hours set a datetime due date, while Today, Tomorrow, +2/+4 days set a date-only due date (end-of-day sentinel). The due date stays empty until a preset is clicked or a value is entered manually. Presets are computed in the configured app timezone and the buttons wrap on narrow viewports. Claude-Session: https://claude.ai/code/session_011FUW7ckxf9AFki2eubR3sX Co-authored-by: Claude <noreply@anthropic.com>
E2E tests (tests/e2e): - filter-sort-patients.spec.ts: sorting (name, birthdate, text property), text/tag filters, "does not contain", server-side search - filter-sort-tasks.spec.ts: default order, sorting by patient/title/priority, text/tag filters, search (guards issue #213) - filter-sort-views.spec.ts: saved views apply stored filters/sorting, legacy serializations, save/overwrite/discard, related panels - support/queryEngine.ts + extended mockBackend.ts: the mock now honours filters/sorts/search/pagination with the same semantics as the backend query engine, serves queryable-field metadata and saved views Fixes: - "does not contain"/"not between" filters were sent as NEQ and silently behaved like "not equals": new NOT_CONTAINS/NOT_BETWEEN query operators in the backend, mapped from the table filter state (issue #227 class) - saved views: legacy searchTags-based tag filters were dropped on deserialization, silently disabling the stored filter - related panels (custom views): tag filters with the "equals" operator never matched because the selection is stored in uuidValue; assignee filters ignored the selected user id - related patients panel: sorting by "Updated" sorted by name instead of the update date (now derived from the latest related task update) - related panels: state ordering (WAIT<ADMITTED<DISCHARGED<DEAD), priority ordering (P1..P4), and due-date null ordering now match the backend; added firstname/lastname and ward/room/bed filter+sort support Claude-Session: https://claude.ai/code/session_01WCSmjBuS6NbcB6oRmKvQgT Co-authored-by: Claude <noreply@anthropic.com>
- Stop infinite re-render when opening the Tasks tab on a saved patient view: sync related table state from memoized baselines and only when the persisted view definition key changes. - Fix virtual derived singleTag equals matching to use uuidValue like hightide and reject empty selections instead of matching every row. - Harden filter/sort E2E helpers for tabbed view pages (visible toolbar controls and dialog-scoped equals tag filters). - Move Playwright config to tests/playwright.config.ts with correct paths so CI/local runs pick up baseURL, retries, and webServer settings. Co-authored-by: Cursor Agent <cursoragent@cursor.com>
…ort crash Full-stack e2e against the real backend behind the nginx proxy: - docker-compose.e2e.yml: production-like stack (proxy -> web/backend/ keycloak/postgres/redis/influxdb) with parameterized image references so CI runs the images built for the current commit; ephemeral volumes - tests/e2e/proxy-fullstack.spec.ts (gated by E2E_PROXY_TARGET=1): verifies proxy routing (/, /graphql, /keycloak), authenticates via the proxied keycloak (password grant + browser login flow), seeds patients and tasks over the proxied GraphQL API, and asserts server-side filtering/sorting from the real query engine, including sorting tasks by patient (issue #213) and the NOT_CONTAINS operator - e2e-proxy CI job in tests.yml: builds backend/web/proxy images for the commit with a shared buildx layer cache (docker-build.yml now writes the same gha cache scopes), starts the compose stack and runs the proxied tests against http://localhost; required in the CI gate Backend fix uncovered by the proxied tests: - sorting over DISTINCT base queries crashed on PostgreSQL ("for SELECT DISTINCT, ORDER BY expressions must appear in select list") whenever a sort ordered by a joined/correlated expression - tasks by patient or assignee (issue #213), patients by update date, ward/room/bed, clinic or position. The unified query engine now rewraps DISTINCT statements into a plain select over deduplicated ids before applying sorts, and clears stale join memos so sort adapters re-join the rewrapped query. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WCSmjBuS6NbcB6oRmKvQgT
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.
Full-stack e2e behind the nginx proxy + a real backend sort crash it caught
Follow-up to #319: the mock-based e2e can't see routing or database-level problems, so this adds a second e2e tier that runs against the real stack — the docker images built for the current commit, wired together exactly like production (nginx proxy in front of web, backend and Keycloak).
Proxied full-stack e2e
docker-compose.e2e.yml— production-like stack (proxy → web / backend / Keycloak / Postgres / Redis / InfluxDB) with parameterized image references (BACKEND_IMAGE/WEB_IMAGE/PROXY_IMAGE) so CI runs this commit's images; ephemeral volumes,restart: on-failureon the backend so migrations retry until Postgres accepts connections.tests/e2e/proxy-fullstack.spec.ts(gated behindE2E_PROXY_TARGET=1, skipped in the mock-based runs):/→ web,/keycloak/...→ Keycloak (issuer under the subpath),/graphql→ backend (JSON, never the frontend catch-all)/auth/callback→ app)NOT_CONTAINS, update-date sort, and sorting tasks by patient asc/desc (issue Sorting of my tasks list based on patients not possible #213)e2e-proxyCI job (tests.yml) — builds the backend/web/proxy images for the commit with Buildx (cache-from/to: type=gha, same scopes now written by the Docker Build workflow, so layers are shared with the images built earlier), starts the compose stack, waits for readiness through the proxy, runs the spec, and uploads the report + stack logs on failure. Added to the requiredCIgate.E2E_TESTING.mddocuments how to run this locally.Real bug the proxied tests caught (issue #213)
Sorting my tasks by patient crashed on PostgreSQL:
The tasks/patients base queries use
SELECT DISTINCT(location-scope joins), and every sort that orders by a joined or correlated expression — tasks by patient or assignee, patients by update date, ward/room/bed, clinic or position — produced anORDER BYoutside the select list and 500ed. This is invisible to the mock-based suite and to SQLite-backed tests; it reproduced immediately against the real Postgres backend through the proxy.Fix:
apply_unified_querynow rewraps DISTINCT statements into a plain select over deduplicated ids before applying sorts (and clears stale join memos so sort adapters re-join the rewrapped statement). This also covers the pre-existing case where a property filter (needs_distinct) was combined with a position/clinic sort.Verification
mainwith the DISTINCT crash when sorting tasks by patient).ruffclean; unit tests show no new failures.E2E_PROXY_TARGET=1, so the existing mock-based e2e job is unaffected.🤖 Generated with Claude Code
https://claude.ai/code/session_01WCSmjBuS6NbcB6oRmKvQgT
Generated by Claude Code