Commit Graph

10 Commits

Author SHA1 Message Date
Experiments DB Dev 9b3d52d89b fix(export): default group-by to None when unset/stale; polish
Final code review of the configurable-data-export feature: ExperimentDetail
was forwarding its on-page groupField state (defaults to '__name__') into
ExportDataModal, leaking a clustering default into the default (untouched)
export. Now passes the raw saved localStorage value, defaulting to
'__none__'. The modal also now validates the incoming groupField against
'__none__'/'__name__'/'__id__'/active subjectTemplate fields and coerces to
'__none__' otherwise, guarding against stale/deleted subject_info fields.
Plus a stale module comment fix and optional-chaining consistency fix in
listSubjectMembers.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-19 13:59:48 -04:00
Experiments DB Dev e65de8892a feat(export): pass subjectTemplate + saved group field to export modal 2026-07-19 13:41:15 -04:00
Experiments DB Dev ea1a7f39f2 feat(frontend): Export data button + modal on experiment page 2026-07-06 15:48:02 -04:00
Experiments DB Dev 9a9b5dfae8 feat(frontend): hydrate + debounced-persist cross-subject plot config
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-01 10:26:33 -04:00
Experiments DB Dev d2c8d69718 perf: server-side caching + remove bulk status fetch from experiment page
- Add backend/src/lib/cache.js — in-process TTL Map cache with
  prefix-based invalidation; no external dependencies

- Cache /experiments/:id/calendar?field=X per (experimentId, field).
  Invalidated immediately on any DailyStatus write.

- Cache /experiments/:id/daily-statuses per (experimentId, date, analysisOnly).
  Invalidated immediately on any DailyStatus write (create/update/delete
  and analysis-summary saves all clear the relevant prefix).

- Add ?analysisOnly=true to /daily-statuses: filters rows where
  analysis_summary IS NOT NULL. Charts are the only consumer and already
  discard rows without analysis data; pre-filtering server-side avoids
  sending the full status payload (71 rows → 1 for this experiment).

- ExperimentCalendar: remove allStatuses prop, fetch calendar data
  directly via API. The component now issues one small GET per field
  selection change instead of the parent loading thousands of rows upfront.

- ExperimentDetail: pass analysisOnly:true to getDailyStatuses;
  drop allStatuses prop from ExperimentCalendar. Cold experiment page
  load no longer fetches every daily status record.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-23 14:03:59 -04:00
Experiments DB Dev c8f0c5f298 feat: replace calendar day modal with dedicated day-view page
Calendar day clicks now navigate to /experiments/:id/day/:date
(with ?field= param). ExperimentDayView shows a sticky-column table
of all subjects with data that day, inline edit via modal, and a
session-metrics bar chart from analysis_summary. Subject name links
to /daily-statuses/:id. Backend adds ?date= filtering to
GET /experiments/:id/daily-statuses.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-23 12:46:35 -04:00
Experiments DB Dev 755caca09e feat: permanent calendar below analytics, editable day modal, per-subject bar chart 2026-04-23 15:24:00 +00:00
Experiments DB Dev 9535f86970 feat: add experiment calendar view with per-day subject counts
New ExperimentCalendar component added as a third view mode (List / Group / Calendar)
on the Experiment Detail page.

Backend:
- GET /api/experiments/:id/calendar?field=<fieldIdOrBuiltinKey>
  Returns { field, days: { "YYYY-MM-DD": count } } where count = number of
  subjects with a non-null/non-empty value for the chosen field on that date.
  Supports both builtin fields (vitals, treatment, notes, experiment_description)
  and custom fields addressed by fieldId UUID.

Frontend:
- ExperimentCalendar component: navigable monthly grid, field selector
  (defaults to first field with "weight" in label, else first active field),
  blue badges showing subject count per day, click to open modal with all
  subjects' data for that day.
- Integrated into ExperimentDetail as displayMode "calendar", persisted
  in localStorage alongside the existing list/group modes.
- experimentsApi.getCalendar() added to API client.

Tests:
- backend/tests/calendar.test.js: 8 unit tests (404, empty days, builtin
  count, custom field count, whitespace ignored, multi-month, field echo,
  missing param).
- frontend/tests/ExperimentCalendar.test.jsx: 13 RTL tests covering
  rendering, default field selection, count badges, month navigation,
  field-change re-fetch, day click modal, and multi-subject display.

All 47 backend + 13 calendar frontend tests passing.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-23 09:26:35 -04:00
Experiments DB Dev 86a56427b7 feat(template): per-experiment daily record template — rename/add/hide fields, custom_fields JSONB 2026-04-15 13:56:17 -04:00
Experiments DB Dev c32a5d200d feat(frontend): React UI — pages, forms, audit log section, Tailwind, Vite build 2026-04-15 13:18:31 -04:00