Skip to content

feat(ui): replace Ant Design with the Slim v2 design system - #451

Open
igoroctaviano wants to merge 130 commits into
masterfrom
feat/slim-modern-redesign
Open

igoroctaviano wants to merge 130 commits into
masterfrom
feat/slim-modern-redesign

Conversation

@igoroctaviano

@igoroctaviano igoroctaviano commented Sep 30, 2026 •

Copy link
Copy Markdown
Collaborator

DMV pairing (optional)

dmv-branch: feat/markup-measurement-labels

Context

Slim still used Ant Design 4, Less, Create React App (craco), Jest, React 18 class components and oidc-client. This PR moves the whole UI to the Slim Modern v2 design (light and dark) and updates the toolchain in the same pass. Existing viewer behavior is kept.

Changes & Results

Toolchain

  • Build: Vite 8 replaces CRA/craco. pnpm start and pnpm run build keep their names, the output still goes to build/, and REACT_APP_* variables and PUBLIC_URL still work. The dicom-microscopy-viewer workers and wasm files are copied to static/js/, the same path as before.
  • React 19.3 with the React Compiler. pnpm run check:compiler runs in CI and in the pre-commit hook and fails on bailouts. The only opt-out is WorklistTable (TanStack Table).
  • TypeScript 7 (tsc --noEmit). Vitest 5 with jsdom and Testing Library replaces Jest.
  • Playwright end-to-end tests in e2e/ (pnpm test:e2e) run against public IDC slides through the read-only proxy (public/config/e2e.js).
  • Tailwind CSS 4, configured in src/styles/globals.css (@theme). The design uses lucide-react icons and self-hosted IBM Plex Sans/Mono fonts.
  • react-router 8 and react-error-boundary 6.
  • Biome is the only linter and formatter. ESLint is gone.
  • Node 22.22 or newer (CI and Docker use Node 24) and pnpm 11.

Architecture

  • App and SlideViewer are now function components. Viewer state and side effects live in hooks under src/features/viewer/hooks, and DMV wiring lives in services under src/features/viewer/services.
  • UI components only render. DICOM parsing, formatting, filtering, persistence and viewer math are in pure modules under src/utils and src/features/*/utils, each with unit tests.
  • Auth: oidc-client-ts replaces the unmaintained oidc-client. The implicit flow, which oidc-client-ts dropped, has its own small module (src/auth/implicitGrant.ts). It validates state, nonce, at_hash, aud/azp, the issuer and expiry, and checks that the response matches the request type (redirect or silent).
  • After the redirect to the first series, the URL keeps its query string and hash.

UI

  • App shell and header: logo, study breadcrumb, server pill, debug, DICOM tag browser, server selection and user menu. The theme follows the system or the user's choice.
  • Worklist: title and count, search (which also queries the server, so it finds studies beyond the first 100), a Contains filter for derived data (annotations, SR, segmentations, parametric maps and presentation states), sortable columns and pagination. Compact rows are set in Preferences.
  • Viewer layout: collapsible left and right panels; a centered tool pill (Draw, Modify, Translate, Remove, Hide, Save, Go to) that compacts under 720px; overlays for the slide chip, zoom buttons, scale bar, magnification and cursor position; an overview card; and a footer showing tile progress and memory use.
  • Left panel: Patient, Study and Clinical trial, plus slide cards with thumbnails.
  • Right panel: Slide label, Specimens, Equipment, Optical paths, Presentation states, Annotations, Annotation groups and categories, Segmentations and Parametric maps. The old settings drawer is gone. ICC, gamma, clustering and interpolation toggles are now under "Display options" in the section they affect.
  • Dialogs: Preferences, Debug, Server, Tag browser and all viewer modals share one header and footer.

Removed: antd, react-icons, craco, craco-less, all Less files, Jest, ESLint, oidc-client, Material Symbols and the Ant Design profiling script.

Follow-up refactor on this branch (pre-doctor)

  • CaseViewer route → slide / derived-series resolution extracted to tested utils + useRouteSlideResolution.
  • derivedDataLoaders split by IOD (ANN / SEG / PM / SR) with a thin loadDerivedData facade.
  • useSlideViewerModel owns SlideViewer hook orchestration; JSX is render-only.
  • ROI / annotation-tool pure helpers (drawnRoi, roiSelectionStyles, annotationToolModes) with thinner hooks.
  • Panel rows thinned (AnnotationChip, optical-path limits util).
  • DICOM tag browser utils split (tagRows / tagTree / seriesDisplay).
  • Implicit grant split (implicitAuthorize, idToken, silentFrame).
  • React 19 polish: useEffectEvent in useDmvEvents, startTransition for bulk visibility.
  • verify-slim skill rewritten for Vite + Slim v2 selectors; full pstack journey suite green on this branch.
  • D7/D8/D9 automated: all draw geometries + modify/translate/measure/Esc on IDC (pnpm test:e2e); Save→reload against docker-compose dcm4chee via pnpm seed:local-archive + pnpm test:e2e:local-archive.

Fixes found in review

  • Annotation group measurement codes that contain a hyphen (LOINC) are no longer truncated.
  • The clustering threshold accepts decimals.
  • Annotation modal fields stay in sync after reopening, and evaluations can be cleared.
  • The worklist no longer jumps back to page 1 while modalities load.
  • Free-text search is no longer saved to localStorage.
  • Preferences apply immediately, and the stroke style and confirm-before-remove settings reach the viewer.
  • Tile counts only include the active slide, and failed tiles are counted separately.
  • The cursor readout shows slide coordinates in mm.
  • Save, remove and ICC messages show as toasts.
  • Show/hide all, the partial category state and optical path stains are back.
  • Parametric Maps panel now has Show all / Hide all toggle (matching Segmentations and Annotation Groups).
  • Worklist search sends QIDO queries again (Patient ID, Patient Name, Accession Number, Study ID), so patients outside the loaded list are found. Exact and *wildcard* values are both sent: Google Healthcare ignores wildcards and dcm4chee needs them.
  • Save ROIs works again. dcmjs (0.52.0 and its latest release) rejects every valid TrackingIdentifier when building a measurement group, so patches/dcmjs@0.52.0.patch fixes that check until upstream does. Failed saves now show a toast instead of only logging to the console.
  • The worklist looks up missing modalities only for the rows on the current page and remembers them. IDC never returns ModalitiesInStudy, so this cuts the series requests on load from about 100 to 20.
  • The ICC profiles switch no longer stays disabled ("This slide has no ICC profiles.") when DMV fetches the profiles after the panels first read the viewer.
  • Switching slides no longer carries over the active tool and hidden ROIs. Each new slide starts in select mode.
  • ROI shortcuts (Alt+D and others) no longer work when disableAnnotationTools is set. Escape and Go to still do.
  • An unknown ?state= in the URL shows the Default display instead of a blank presentation state picker.
  • Text meets WCAG AA contrast in both themes. Dark theme primary is lighter (#6a9cf7) with dark button labels; white on the old blue reached 3.5:1. Light theme muted text is darker.

The Slides column in the worklist needs NumberOfStudyRelatedSeries. The IDC proxy does not return it, so the column shows "—" there; dcm4chee and Orthanc do return it.

Testing

Pre-doctor automated gate (2026-10-16, 125b773)

  • pnpm run typecheck
  • pnpm test — 195 files, 1495 tests
  • pnpm run check:compiler — 208 components/hooks, WorklistTable only opt-out, no bailouts
  • pnpm test:e2e — 103 passed (includes D7/D8)
  • pnpm test:e2e:local-archive — D9 Save→reload on compose dcm4chee (passed)
  • verify-slim (pstack) — all journeys green: worklist, slide, segmentation, annotation-groups, sr-annotations, tag-browser, draw-roi
  • pnpm run build — DMV workers/wasm present under build/static/js

Manual (optional before inviting doctors)

  • D9 Save ROIs on local writable archive — automated via pnpm seed:local-archive + pnpm test:e2e:local-archive
  • C3 OIDC sign-in / name in menu / sign-out (if you have a server)
  • D7 / D8 all geometries, Modify, Translate, Measure, Esc — covered by pnpm test:e2e
  • A4 ANN color-by-measurement + hyphenated LOINC if private data exists
  • Spot-check Display options discoverability (ICC, gamma, clustering) and dark/light themes

Shared master quirks (do not block doctor invite unless they ask): SEG deep-link slide highlight, PR Back, "Unknown Series" tooltip, tag-browser copy, memory warning toast-only-in-Debug.

Manual checklist with IDC study links for each feature: e2e/TEST-PLAN.md

Checklist

PR

  • PR title is descriptive and follows semantic-release style
  • Linked related issues / DMV PRs when applicable (dmv#298)

Code

  • Code follows project style (pnpm run lint, pnpm run fmt)
  • Non-obvious logic is documented (JSDoc where appropriate)

Docs

  • README / CONFIGURATION / CONTRIBUTING updated when behavior changes

Tested environment

  • OS: macOS 15.7
  • Node version: 24.16.0
  • Browser: Chromium (Cursor browser / Playwright)

Move the whole app from Ant Design and Less to Tailwind, Radix primitives
and Material Symbols, following the Slim Modern v2 mockups in light and
dark mode.

- Header with study breadcrumb, server pill, debug, tag browser and user menu
- Worklist with search, date filter, grid table and pagination footer
- Viewer with collapsible side panels, centered tool pill, zoom, scale and
  overview overlays, and a status footer with tile and memory usage
- Right panel sections for label, specimens, equipment, optical paths,
  presentation states, annotations, groups, categories, segmentations and
  parametric maps, with per-section display options replacing the settings
  drawer
- Dialogs rebuilt on a shared header and footer
- Jest now uses the automatic JSX runtime, matching tsconfig and the build
@deepsource-io

deepsource-io Bot commented Sep 30, 2026 •

Copy link
Copy Markdown

DeepSource Code Review

We reviewed changes in f10a6bc...d3ed274 on this pull request. Below is the summary for the review, and you can see the individual issues we found as inline review comments.

See full review on DeepSource ↗

PR Report Card

Overall Grade   Security  

Reliability  

Complexity  

Hygiene  

Code Review Summary

Analyzer Status Updated (UTC) Details
JavaScript Oct 21, 2026 12:14a.m. Review ↗

Important

AI Review is run only on demand for your team. We're only showing results of static analysis review right now. To trigger AI Review, comment @deepsourcebot review on this thread.

…ndings

Pure, unit-tested modules now hold the DICOM parsing, formatting,
filtering, persistence and viewer math that lived inside components.
Components render props and call callbacks.

Fixes:
- annotation group measurement codes containing hyphens were truncated
- clustering settings moved to annotation groups; threshold accepts decimals
- annotation modal fields are controlled and evaluations can be cleared
- worklist no longer jumps to page 1 during modality enrichment
- free-text search is no longer persisted (may contain patient data)
- preferences apply live; stroke style and confirm-before-remove are wired
- config masking covers authorization/bearer/credential keys
- tile counts are scoped to the active volume and count failures
- cursor readout shows slide coordinates in mm, matching Go to
- save/remove/ICC messages surface as toasts instead of console logs
- restored show/hide all, partial category state and optical path stains
- slider thumbs, preference controls and pagination have accessible names
- Draw new ROIs with the user's stroke color and width, store styles per
  ROI so finding styles and re-renders no longer override them
- Convert lengths and areas to the preferred unit in the annotation list
  and ROI details
- Remove the keydown listener on unmount
- Show the viewer layout with skeletons while the study loads and a
  centered indicator until the first slide tiles arrive
- Replace the worklist spinner with skeleton rows, drop the patient
  name icon and align the page padding with the header
- Move measurement units to the Annotations tab and drop the unsupported
  ROI label option
- Widen the configuration search, highlight matches and show a count
- Redesign the About tab with links and copyable build information
- Show the full server URL on hover and add a copy button to the server
  dialog
- Hide the Worklist button on the worklist
- Open dialogs from the center instead of sliding from the corner
- Replace the S tile with the microscope mark and regenerate favicons
Port #438 into the redesigned UI instead of picking a side:
- Server dialog: optional OIDC config section with validation; the
  OIDC logic lives in useServerSelection (covered by hook tests)
- Viewer: Tailwind ViewerMessage for load errors (with retry),
  "No slides found" and "Series not found"; study loading keeps the
  skeleton layout and series loading uses the viewport indicator
- Segments: absent segments get an "Absent" badge with zoom, color,
  visibility and opacity controls disabled
@github-actions

github-actions Bot commented Oct 1, 2026 •

Copy link
Copy Markdown

📦 Firebase Preview - Using Published DMV

This preview is using the published dicom-microscopy-viewer from package.json:

Version ^0.49.3

To link a DMV branch for testing (requires an open PR in DMV):

  • Add dmv-branch: <branch-name> to the PR description, OR
  • Use the same branch name in both repos (automatic matching)

@github-actions

github-actions Bot commented Oct 1, 2026 •

Copy link
Copy Markdown

Visit the preview URL for this PR (updated for commit d3ed274):

https://idc-external-006--pr451-feat-slim-modern-red-qeu2j1mu.web.app

(expires Wed, 28 Oct 2026 00:15:02 GMT)

🔥 via Firebase Hosting GitHub Action 🌎

Sign: 88aacecd98ba54d2f9c8d201a9444e43d1ad8307

- typescript 6.0 (the last release with the JS API that CRA's type checker
  needs), ES2022 target, explicit types list, ignoreDeprecations for the
  moduleResolution CRA forces
- copy the tailwind/postcss/babel configs into the Docker image so the build
  runs Tailwind; the container test now fails on unprocessed CSS
- drop unused deps (classnames, react-test-renderer, user-event v7,
  sonarqube-scanner, @types/react-router-dom, three Radix primitives) and
  their dead ui wrappers; build tools move to devDependencies
- add lucide-react
- remove the PostCSS block craco ignores, CRA's duplicate ESLint pass, the
  duplicate .npmrc and two type files for removed libraries
- lint test files with Biome, run tests in UTC, target current Node in Babel
- browserslist targets WebGL2-capable browsers, which DMV requires
- restore the comments documenting the token-disclosure policy (configured
  origins, consent gate, insecure-origin refusal, sibling-manager grants,
  unforwarded token on server switch, GH-320 mapping, auth recovery remount)
- a server URL stored before the mode key existed is applied as custom, as
  on master; App reads it through loadServerSelection so the dialog and the
  active client agree
- drop eslint suppressions for rules no configured linter runs
- preferences dialog, hooks and utils move to features/preferences with a
  public index; SlideViewer, AnnotationItem and the worklist no longer reach
  into the header feature
- delete the components/Header and components/Worklist shims, the unused
  ui and slim barrels; move the worklist test next to its component
- SlimCollapsibleSection uses the ui/collapsible wrapper
- drop eslint suppressions for rules no configured linter runs
- Icon renders typed lucide-react SVGs (IconName union); the Google Fonts
  Material Symbols and IBM Plex requests are gone, so icons work offline
- shared CopyButton and SearchInput; Button gains xs/page sizes and a
  selected variant; Slider forwards onValueCommit; SlimDialogHeader gains a
  tone; visible focus rings on dialog close buttons
- Tailwind tokens for the recurring arbitrary sizes and radii; cn() merges
  the custom tokens; unused tokens/keyframes and CSS utilities removed
- preferences dialog split into one component per tab with the WAI-ARIA
  tabs pattern, runtime info injected, config view memoized; usePreferences
  caches its snapshot
- DICOM tag browser selects by series UID and derives display sets with a
  pure buildDisplaySets, so metadata events no longer reset the selection
- worklist: "Last 7 days" covers 7 days, legacy dotted dates parse, page
  index is clamped, empty state reflects filters, deferred search, table
  roles, patient name is a link
- OIDC config storage goes through the safe storage helpers; notifications
  keep the original error object; one keyboard shortcut table
- every sidebar panel is a function component; Item folds into SpecimenItem
- components/panel holds the shared layer controls: visibility toggle,
  settings popover, inline opacity row, useLayerStyle, useLimitWindow,
  useResettableState and a frame-throttled callback
- sliders preview locally and commit on release, except optical path
  windowing, which streams to the viewer once per animation frame
- report parsing, measurement lookups, colour, swatch, visibility summary,
  display option binding and style equality move to tested pure utils
- shared layer style types in types/layerStyles
- toasts publish through a small store rendered by ToastHost, so
  NotificationMiddleware TOAST messages and config.messages show again
- ROI styling restored: selected finding colours, measurement styles
- DMV and DOM listeners are registered through subscribe helpers and torn
  down on unmount; debounced handlers are cancelled
- SlideViewer render is split into section components; go-to, ROI removal,
  pixel statistics, ICC profile, presentation state, hovered ROIs and
  referenced slide logic move to tested utils
- typed dicom-microscopy-viewer events and styles; fewer unsafe casts
- AppInfo is built once; reports encode through encodeDicomDataset
- App renders through a single renderPage helper; the viewport no longer
  forces a minimum width
- DICOM date/time, person name and coded concept helpers live under
  utils/dicom; displayFormat reuses them; values.ts, formatDicomDate.ts and
  the old dicomDate/personName modules are gone
- magnification prefers Objective Lens Power and otherwise uses geometric
  midpoints between objectives, so 0.25-0.26 um/px slides read 40x, not 20x
- study description is filled from the first instance when empty (the
  check was inverted)
- impossible DICOM dates are returned as-is instead of rolling over
- mapWithConcurrency runs serially for NaN or sub-1 limits
- memory warning thresholds have one source in memoryWarning.ts
- display option descriptors are generic over their ids; the unused
  segment clustering branch is removed
- colour conversions live in color.ts; segment colour helpers take narrow
  object params; sr.tsx becomes sr.ts without duplicate helpers;
  CustomError is TypeScript
- tests for viewerUtils, overview clamping, cn(), study metadata,
  overlay colormaps, SR helpers and CustomError
- viewer shortcut hints are built from KEYBOARD_SHORTCUTS and shown with
  formatShortcutHint
- CaseViewer redirects a bare study URL to its first series, replacing
  SlideList's mount-only effect and its lint suppression
- bulk visibility and category recolouring update SlideViewer once through
  batch handlers; default ROI and panel style maps keep their identity
  while unchanged
- StyleOptions is replaced by AnnotationStyle
- series path, series label, optical path order, ROI selection and
  visibility change logic move to tested utils
- dcmjs naturalize/denaturalize are typed, removing casts at call sites
- icon props use IconName; a global ResizeObserver stub replaces the
  per-test ones; remaining line comments use block style
- CONTRIBUTING covers lucide icons, Tailwind token registration, the panel
  kit and publishToast
- README: toasts stack bottom-centre unless messages.top is set; test
  script description is accurate; typecheck script listed
- CONFIGURATION: legacy stored server URLs stay custom; read-only pill
- toasts default to 5 seconds again, as documented
- App is a small function component; session setup, client mapping,
  token disclosure, routes and pages live in src/app with tests. The auth
  rationale comments move next to the code they describe
- oidc-client 1.x is replaced by oidc-client-ts 3. Authorization code with
  PKCE stays the default; the implicit grant that Google Cloud Healthcare
  clients need is implemented in auth/implicitGrant, verifying the ID token
  signature, at_hash, issuer, audience/azp, nonce and expiry, with
  single-use state per flow. OIDC sign-in now needs a secure context
- silent renew must return the same subject; sign-out revokes only when
  the provider has a revocation endpoint
- the bare study URL redirect keeps the query and hash (?gcp=,
  ?access_token)
- SlideViewer is a thin function component over focused hooks: viewer
  session lifecycle, DMV/keyboard subscriptions with latest handlers,
  slide population, optical paths, presentation states, ROIs, annotation
  draft and tools, reports, annotation groups, segmentations and
  parametric maps
- viewers are created in an effect and always torn down; results that
  arrive after teardown are dropped instead of leaking into the next slide
- segment palettes rebuild only when segments, colours or gamma change
- finding keys use codedConceptKey (SCHEME:VALUE); buildKey is removed
- unread class state (config measurements, duplicate clustering
  handlers, an unreachable pixel statistics branch) is dropped
- reducers, style registry and session services are pure and tested; a
  SlideViewer smoke test and hook tests cover lifecycle and cleanup
- Vite replaces CRA/craco: root index.html, CRA placeholders
  (%PUBLIC_URL%, %REACT_APP_CONFIG%) filled by a small plugin, base from
  PUBLIC_URL, REACT_APP_* still exposed, output stays in build/
- dicom-microscopy-viewer's dynamic-import bundle is pre-bundled and its
  worker and codec files are served from static/js in dev and build;
  linked DMV checkouts re-optimize when their bundle changes
- Vitest replaces Jest with the same jsdom setup and mock reset semantics
- React 19.3 with the React Compiler (babel-plugin-react-compiler 1.0);
  check:compiler fails on any component or hook the compiler skips and runs
  in CI and pre-commit; WorklistTable opts out because TanStack Table is
  an incompatible library
- react-router 8, react-error-boundary 6, Testing Library 16, TypeScript 7
- IBM Plex fonts are bundled with @fontsource
- CRA, craco, Babel presets, ESLint and overrides that only applied to
  CRA's dependency tree are removed; Biome is the only linter
- Dockerfile, CI and docs follow the new toolchain; .env now controls
  REACT_APP_CONFIG (default local)
- @tailwindcss/vite compiles a CSS-first @theme in src/styles/globals.css;
  tailwind.config.js, postcss.config.js and PostCSS are gone
- dark mode is a class-based custom variant; tw-animate-css replaces
  tailwindcss-animate
- v4 renames applied (outline-hidden, shadow-xs, rounded-sm, important
  suffix, linear gradients kept in sRGB, data-/has- shorthands); bare
  arbitrary sizes become the existing tokens
- base styles keep v3 behaviour the UI relied on: pointer cursor on
  buttons, 1px table cell padding; OpenLayers CSS sits in the base layer
- tailwind-merge knows the custom shadow, sidebar and bar-height tokens
- computed styles of the worklist, viewer and dialogs match the v3
  build in light and dark themes
- CI rejects unprocessed Tailwind at-rules in the built CSS
scripts/profile-bulk-annotations.mjs drove Ant Design selectors that no longer exist and imported Playwright, which is not a dependency. Block comment style in inject-slim-env.mjs.
Comment thread src/features/viewer/testing/fixtures.ts Fixed
Memory formatting and warning levels move to utils/memoryWarning with
tests, and the unused MemoryMonitor status helpers are removed. Also
replaces for-in loops, dedupes the Pyramid UID errors (fixing a missing
space in one message) and tidies the implicit grant helpers.
Check the configuration before mounting and show which server lacks a URL
and which setting to change. The crash fallback is now a full page with
the message, a reload button and the details dialog.

The dev server serves config/env.js from its own environment, so starting
another server or a build with a different config no longer breaks it.
…ctable

With enableServerSelection the default server may ship without url or path,
as master allowed, so the app mounts and the header's Select server stays
reachable instead of a blocking configuration page.
A failing Microscopy Bulk Simple Annotations instance is skipped and
reported once; the remaining instances of the series are still added and
styled, and the panel refreshes.
A default presentation state that arrives after the user changed optical
paths, or picked or reset a state, is listed but no longer applied; a state
named in the URL still applies. Slider drags restyle the slide without
rebuilding the viewer snapshot each frame, so the snapshot no longer
resets the slider mid-drag; the commit refreshes it once.
The tag browser's active series were recomputed from every DMV group,
segment and mapping on each render; the effect now runs on slide, viewer
generation and visibility changes.
@igoroctaviano igoroctaviano added run-e2e Reviewer-triggered: run the Playwright e2e suite against IDC and removed run-e2e Reviewer-triggered: run the Playwright e2e suite against IDC labels Oct 20, 2026
The SR loader settles at the first suitable report again, so derived-data
auto-show no longer waits on a slow or hung retrieve. When an SR link
showed every ROI, ROIs of reports retrieved afterwards are shown as each
report is added, and ROIs the user hid meanwhile stay hidden.
@igoroctaviano igoroctaviano added run-e2e Reviewer-triggered: run the Playwright e2e suite against IDC and removed run-e2e Reviewer-triggered: run the Playwright e2e suite against IDC labels Oct 20, 2026
Window sliders spanned 0 to 2^BitsAllocated - 1, so presentation states
with narrow windows (IMC channels windowed 2-33 out of 0-65535) drew both
thumbs at zero. Once a channel's first frame is sampled the slider spans its
observed pixel range, with room above an upper limit past it, and narrow
ranges use a fractional step so dragging does not round the window.
@igoroctaviano igoroctaviano added run-e2e Reviewer-triggered: run the Playwright e2e suite against IDC and removed run-e2e Reviewer-triggered: run the Playwright e2e suite against IDC labels Oct 20, 2026
On Linux runners --use-angle=swiftshader stalled frame production while
WebGL was busy, so OpenLayers' requestAnimationFrame redraws arrived
seconds late and the viewport kept a stale frame: R2 saw ROIs still drawn
after Hide all and VS5 differed. --enable-unsafe-swiftshader alone still
renders the tiles in software. O3, O4 and O9 now wait for the presentation
state options to stop changing before clicking one.
@igoroctaviano igoroctaviano added run-e2e Reviewer-triggered: run the Playwright e2e suite against IDC and removed run-e2e Reviewer-triggered: run the Playwright e2e suite against IDC labels Oct 20, 2026
The development console.error interpolated the error category into its
first argument, which a console treats as a format string. Pass the
category as a value instead (CodeQL js/tainted-format-string).
The default state was the study's first search result, which on studies
with several slides usually belongs to another slide, so nothing applied.
The loader now names the slide's first state once every earlier result
settled, and the picker lists states in study order. A state named in the
URL still wins, and a late default never replaces user changes. O7 checks
opacity relative to the channel's contribution, and the shared multiplexed
slide resets the default state before its tests.
@igoroctaviano igoroctaviano added run-e2e Reviewer-triggered: run the Playwright e2e suite against IDC and removed run-e2e Reviewer-triggered: run the Playwright e2e suite against IDC labels Oct 20, 2026
…Contains chip

The Slides column and card label showed NumberOfStudyRelatedSeries, which
counts every series (SEG, ANN, SR, PR too), so they now say Series. A
Contains entry with no server to search keeps its chip and clear button
and says it cannot be searched, instead of filtering invisibly.
…g state

Study thumbnails and the label viewer publish frame events on the same
document, so their small frames ended the first-image wait and could set a
channel's window statistics. Only frames of the slide's volume images count.
…ys back on

Hiding the last visible overlay from the in-viewport legend removed the
legend, so the overlay could only come back from the side panel. Viewport
pixel checks in e2e leave the legend out of their captures.
Finding, evaluation and geometry selects are named by their visible label
plus their value. The DICOM tag table restates its ARIA roles because its
display overrides drop native table semantics in Safari/VoiceOver.
… drags cheaply

The annotation group measurement choice lives in useAnnotationGroups, so it
survives panel remounts and a flat color clears it. Group, segment and map
slider drags restyle the slide without rebuilding the snapshot each frame,
and segment and map Show all / Hide all apply in one pass.
…nts per session

The Configuration tab, copy and download hide user:password@ and secret
query parameters in URL values. A configured origin's token grant is kept
for the session instead of being stored, so an origin removed from the
config stops receiving the token.
A malformed SEG or PM instance is skipped instead of dropping its series,
and display failures are no longer reported as retrieval failures. A derived
deep link is resolved once and its dataset is dropped on the image series.
Retrying slides refreshes every consumer of the study, and presentation
states without a usable UID are not offered.
…cross redirects

The warning hook no longer throws on circular or BigInt arguments, and
Debug warnings reset per study rather than on the viewer's own redirects.
@igoroctaviano igoroctaviano added run-e2e Reviewer-triggered: run the Playwright e2e suite against IDC and removed run-e2e Reviewer-triggered: run the Playwright e2e suite against IDC labels Oct 21, 2026
@sonarqubecloud

Copy link
Copy Markdown

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Redesign run-e2e Reviewer-triggered: run the Playwright e2e suite against IDC v2

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants