Skip to content

Add qPCR + TapeStation support, table-pending transitions, and run files/report refinements - #34

Merged
wasimxyz merged 7 commits into
stagingfrom
wa/web-app-updates-20260420
Apr 21, 2026
Merged

Add qPCR + TapeStation support, table-pending transitions, and run files/report refinements#34
wasimxyz merged 7 commits into
stagingfrom
wa/web-app-updates-20260420

Conversation

@wasimxyz

@wasimxyz wasimxyz commented Apr 21, 2026

Copy link
Copy Markdown
Member

Summary

This branch adds first-class support for two new instrument types (qPCR and TapeStation), introduces a shared "stale table" pending treatment that ties every server-side query-string change to a React transition, and delivers a batch of run-detail / run-files / report-section refinements.

Changes

qPCR + TapeStation instrument support

  • New Drizzle migration web-app/drizzle/0006_qpcr_tape_station.sql extending instrument_type with qpcr and tape_station, with matching enum + VALID_INSTRUMENT_TYPES entries in web-app/lib/db/schema.ts.
  • New run-detail variants web-app/components/runs/variants/qpcr-run-detail.tsx and tape-station-run-detail.tsx, wired into the variant dispatcher in web-app/components/runs/variants/index.tsx.
  • New qPCR runs table web-app/components/instruments/runs-table/qpcr-runs-table.tsx with a filterable "Dye Channels" column backed by getQpcrFilterOptions and dye_channel search param (web-app/lib/api/instrument-runs.ts, web-app/lib/search-params.ts, filterable-column-header.tsx).
  • New qPCR / TapeStation metadata badges and hasQpcrMetadata / hasTapeStationMetadata helpers in web-app/components/runs/run-metadata-badges.tsx; dye-channel color helper in web-app/lib/instrument-colors.ts.
  • Human-readable labels for qpcr / tape_station in web-app/components/instruments/edit-instrument-dialog.tsx.

Table pending / stale treatment

  • New web-app/components/table-pending.tsx exporting TablePendingProvider, TablePendingBoundary, and useTablePending. Provides a React transition that sibling useQueryState(s) calls hook into via startTransition, with a 120 ms delay before any visible change to avoid flicker on fast fetches.
  • Applied to the dashboard (app/page.tsx + dashboard/runs-toolbar.tsx), per-instrument runs (app/instruments/[instrumentId]/page.tsx + instrument-runs-toolbar.tsx + filterable-column-header.tsx), and the watcher event log (watcher-detail-tabs.tsx + event-log-toolbar.tsx + event-log.tsx).
  • pagination-nav.tsx now reads the pending state, dims to 60% opacity, blocks pointer events, and sets aria-busy while the RSC payload streams in; Prev / Next disable themselves instantly to prevent queued double-clicks.
  • New @keyframes table-pending-slide in web-app/app/globals.css drives the thin sliding indeterminate bar.

Run files table

  • Extracted the presentational table into a new web-app/components/runs/run-files-table.tsx (status badge logic, selection column, row actions). run-files-section.tsx now owns only state + handlers.
  • Added a "Type" column (raw / processed) and a stable secondary sort that always lists raw files before processed files within each sort field.
  • Allow completed files to be reprocessed (previously only failed); reprocess action now gates on REPROCESSABLE_STATUSES = { completed, failed }.

Run report section

  • run-report-section.tsx now renders PDFs (by content type or .pdf extension) in an inline <iframe> alongside processed images, so qPCR / TapeStation exports render in-page. Count label updated to N file(s).
  • Removed unused web-app/components/runs/report-data-table.tsx.

File size fix for processed artifacts

  • lambda/src/data_hub_lambda/azure_600_gel_doc/process_file.py and spectramax_plate_reader/process_file.py now pass size_bytes=...stat().st_size when recording processed outputs, so the Total Size column accounts for derived PNG / CSV files.

Misc UX

  • Empty RunMetadata now returns null instead of the "No metadata recorded yet" placeholder, cleaning up run-detail pages when there is nothing to show.

Breaking changes

  • New Postgres migration 0006_qpcr_tape_station must be applied before deploy; it adds two values to the instrument_type enum. No existing data is altered.
  • No API / route contract changes.

Driveby changes

  • Ran the formatter across touched files (chore: Run formatter, 4fed033).
  • Tightened pagination-nav.tsx (atPrev / atNext locals, collapsed duplicated className ternaries).
  • InstrumentRunsTable / dispatcher updated to accept qpcrFilterOptions alongside the existing plate-reader / gel-doc options.
  • Edit-instrument dialog label map gained entries for qpcr and tape_station.

Testing

  • Apply migration 0006_qpcr_tape_station.sql in a clean staging DB; confirm the instrument_type enum now includes qpcr and tape_station.
  • Create a qPCR instrument via the edit dialog; verify the label renders as "qPCR".
  • Upload a qPCR run and confirm it appears in the new QpcrRunsTable with a populated "Dye Channels" column; verify the column dropdown filter round-trips via ?dye_channel=....
  • Open a qPCR run detail page; verify qPCR metadata badges render and metadata section is hidden when metadata is empty.
  • Upload a TapeStation run with a PDF report; verify the Report Data section renders the PDF in the inline viewer and "Open in new tab" works.
  • On the dashboard and instrument runs tables, apply a toolbar filter and click pagination; verify the table dims to ~60% opacity, the sliding bar appears only after fast fetches complete without flicker, and pagination is non-interactive during the transition.
  • On the watcher Event Log tab, change filters / paginate and verify the same pending treatment applies.
  • Reprocess a completed file from the files table; verify the action is offered (was previously hidden) and existing report data is cleared.
  • In the run files table, confirm the new "Type" column shows "raw" / "processed" and raw files sort before processed files regardless of the active sort field.
  • Re-run a gel doc / plate reader processing job and verify the Total Size column on the run row includes the processed artifact bytes.

Introduces a shared TablePendingProvider + TablePendingBoundary pair that ties every shallow:false nuqs write (pagination, toolbars, per-column filters) into a React transition. While the RSC refetch is in flight the stale table dims to 60%, blocks pointer events, and shows a thin sliding indeterminate bar; pagination controls disable themselves instantly to prevent queued double-clicks. A 120ms delay before the visible treatment appears keeps fast fetches from flickering.

Applied to the dashboard runs table, per-instrument runs tables (incl. column filter dropdowns), and the watcher event log.
@wasimxyz wasimxyz self-assigned this Apr 21, 2026
@vercel

vercel Bot commented Apr 21, 2026

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
data-hub Ready Ready Preview, Comment Apr 21, 2026 7:27pm

Request Review

@wasimxyz
wasimxyz merged commit c045f1c into staging Apr 21, 2026
7 checks passed
@wasimxyz
wasimxyz deleted the wa/web-app-updates-20260420 branch April 21, 2026 19:31
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.

1 participant