Compare commits

...
Author SHA1 Message Date
ohif-bot 6b0bb9402f chore(version): Update package versions [skip ci] 2025-02-28 17:30:34 +00:00
ohif-bot 9cbf82167e chore(version): version.json [skip ci] 2025-02-28 17:30:27 +00:00
Sofien-Sellami 7f0cc0f60e feat: separate checks for addWindowLevelActionMenu and addSegmentationOverlay (#4813) 2025-02-28 12:25:52 -05:00
ohif-bot 7d67834159 chore(version): Update package versions [skip ci] 2025-02-26 17:19:13 +00:00
ohif-bot 51f9407d93 chore(version): version.json [skip ci] 2025-02-26 17:19:07 +00:00
Sofien-Sellami fdb073c216 fix: broken activateViewportBeforeInteraction behavior (#4810) 2025-02-26 12:14:56 -05:00
ohif-bot d319d20b0d chore(version): Update package versions [skip ci] 2025-02-26 16:28:51 +00:00
ohif-bot 8a977bb70c chore(version): version.json [skip ci] 2025-02-26 16:28:42 +00:00
Alireza 9233143b9d fix(sr): sr hydration and load was not working, Screenshot Comparison, and Testing (#4814) 2025-02-26 11:23:40 -05:00
ohif-bot 1f5c60bbda chore(version): Update package versions [skip ci] 2025-02-25 22:26:27 +00:00
ohif-bot ca22bac851 chore(version): version.json [skip ci] 2025-02-25 22:26:21 +00:00
Alireza 32fc6f0d4b chore: upgrade cornerstone3D version (#4809) 2025-02-25 17:21:57 -05:00
ohif-bot e2491daff7 chore(version): Update package versions [skip ci] 2025-02-25 21:30:04 +00:00
ohif-bot 7dd0260f86 chore(version): version.json [skip ci] 2025-02-25 21:29:58 +00:00
Yiannis Theocharakis 4b63d48518 feat(Segments Looping) : Fixed looping through Segments of SEG (#4793) 2025-02-25 16:25:52 -05:00
ohif-bot 4ecffe89cb chore(version): Update package versions [skip ci] 2025-02-25 21:24:41 +00:00
ohif-bot 9fb3653281 chore(version): version.json [skip ci] 2025-02-25 21:24:35 +00:00
Rafael Osipov 06660be7c4 docs: Fix broken link to viewer internationalization docs (#4808) 2025-02-25 16:20:19 -05:00
ohif-bot 5d5eafb0f5 chore(version): Update package versions [skip ci] 2025-02-25 18:36:49 +00:00
ohif-bot 0abb62167a chore(version): version.json [skip ci] 2025-02-25 18:36:43 +00:00
Alireza 3e6913b097 feat(hotkeys): Migrate hotkeys to customization service and fix issues with overrides (#4777) 2025-02-25 13:32:30 -05:00
ohif-bot 4559d39a91 chore(version): Update package versions [skip ci] 2025-02-25 16:55:42 +00:00
ohif-bot b7ddbccdff chore(version): version.json [skip ci] 2025-02-25 16:55:37 +00:00
Bill Wallace e480e841bb fix: Changes to address hang/crash on jump to instance (#4679) 2025-02-25 11:51:44 -05:00
Ibrahim afd528b8d7 fix(rt): jump to segment discards the configured width (#4799) 2025-02-25 11:49:16 -05:00
ohif-bot 76da2d86a9 chore(version): Update package versions [skip ci] 2025-02-25 14:20:31 +00:00
ohif-bot 5527c0e8ea chore(version): version.json [skip ci] 2025-02-25 14:20:25 +00:00
Bill Wallace bda98b0bee fix: Delay for all series thumbnails on fetching thumbnail (#4802) 2025-02-25 09:15:45 -05:00
ohif-bot 74d96d378d chore(version): Update package versions [skip ci] 2025-02-23 20:49:40 +00:00
ohif-bot 94496f72b9 chore(version): version.json [skip ci] 2025-02-23 20:49:34 +00:00
Dan Rukas 338e386948 ui(icons): Added New Segmentation Tool Art (#4797) 2025-02-23 15:44:53 -05:00
ohif-bot 0531bee83b chore(version): Update package versions [skip ci] 2025-02-20 14:26:22 +00:00
ohif-bot 6411488cd1 chore(version): version.json [skip ci] 2025-02-20 14:26:16 +00:00
Pedro H. Köhler 55f0b54db1 fix: combine frame instance (#4792) 2025-02-20 09:21:44 -05:00
ohif-bot 2e70f0ffa1 chore(version): Update package versions [skip ci] 2025-02-20 14:01:47 +00:00
ohif-bot 0931356f68 chore(version): version.json [skip ci] 2025-02-20 14:01:41 +00:00
Pedro H. Köhler b7cd0c6027 fix: icon is not defined (#4794) 2025-02-20 08:57:29 -05:00
ohif-bot 8d83c117cf chore(version): Update package versions [skip ci] 2025-02-19 14:21:08 +00:00
ohif-bot bd93a6f428 chore(version): version.json [skip ci] 2025-02-19 14:21:01 +00:00
Ceciliadrc 125f11fc73 fix(button): fix for className (#4604) 2025-02-19 09:16:22 -05:00
ohif-bot ce3bc8962d chore(version): Update package versions [skip ci] 2025-02-18 23:24:46 +00:00
ohif-bot 0d8820d941 chore(version): version.json [skip ci] 2025-02-18 23:24:39 +00:00
Yiannis Theocharakis c61dbba8d0 fix(Segments Looping) : Fixed looping through Segments of RTSTRUCT using Left/Right viewport buttons (#4783) 2025-02-18 18:20:26 -05:00
Bill Wallace 2410c6a509 fix: cache thumbnail in display set (#4782) 2025-02-18 18:19:09 -05:00
ohif-bot d26c9551b6 chore(version): Update package versions [skip ci] 2025-02-18 16:41:10 +00:00
ohif-bot b6afba12a5 chore(version): version.json [skip ci] 2025-02-18 16:41:04 +00:00
Pedro H. Köhler 4e16099ad3 fix: lodash dependencies (#4791) 2025-02-18 11:36:26 -05:00
ohif-bot 887a892a5b chore(version): Update package versions [skip ci] 2025-02-18 15:34:40 +00:00
ohif-bot db4d94c3fe chore(version): version.json [skip ci] 2025-02-18 15:34:31 +00:00
Pedro H. Köhler 0b5836ca1a feat: improve dicom tag browser with nested rows (#4451) 2025-02-18 10:29:53 -05:00
ohif-bot 8b969eb1e9 chore(version): Update package versions [skip ci] 2025-02-18 14:12:35 +00:00
ohif-bot ac30be6038 chore(version): version.json [skip ci] 2025-02-18 14:12:28 +00:00
Alireza d8a6e79df0 fix: depandabot (#4786) 2025-02-18 09:08:10 -05:00
Pedro H. Köhler 5712e91ca1 fix: right panel for the create mode cli command (#4788) 2025-02-18 09:07:17 -05:00
Pedro H. Köhler a3b1251386 docs: fix yarn version (#4790) 2025-02-18 09:04:35 -05:00
ohif-bot 2fbaa11cf1 chore(version): Update package versions [skip ci] 2025-02-13 17:31:17 +00:00
ohif-bot 8fe7b78e54 chore(version): version.json [skip ci] 2025-02-13 17:31:11 +00:00
Yiannis Theocharakis d9a3ba7990 fix(Frame View) : Fixed synchronization for Frame View Hanging Protocol (#4780) 2025-02-13 12:27:01 -05:00
ohif-bot 2ca9f2b0cc chore(version): Update package versions [skip ci] 2025-02-11 17:44:43 +00:00
ohif-bot 559f248d1f chore(version): version.json [skip ci] 2025-02-11 17:44:37 +00:00
Pedro H. Köhler 084a10f783 feat: add viewport overlays to microscopy mode (#4776) 2025-02-11 12:39:45 -05:00
ohif-bot 5043ea3260 chore(version): Update package versions [skip ci] 2025-02-04 23:37:42 +00:00
ohif-bot e0ec1011cf chore(version): version.json [skip ci] 2025-02-04 23:37:36 +00:00
devin-ai-integration[bot]andAlireza Sedghi bbf1a19676 fix: add commandsManager to MoreDropdownMenu onClick props (#4765)
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: Alireza Sedghi <ar.sedghi@gmail.com>
2025-02-04 18:33:45 -05:00
ohif-bot 9a3d832cc2 chore(version): Update package versions [skip ci] 2025-02-04 17:29:26 +00:00
ohif-bot e373e22481 chore(version): version.json [skip ci] 2025-02-04 17:29:19 +00:00
Alireza 149d6d049c fix(core): Address 3D reconstruction and Android compatibility issues and clean up 4D data mode (#4762) 2025-02-04 12:25:10 -05:00
ohif-bot 4d06a7d286 chore(version): Update package versions [skip ci] 2025-02-04 14:10:16 +00:00
ohif-bot a7e4204cea chore(version): version.json [skip ci] 2025-02-04 14:10:10 +00:00
Joost van Griethuysen 8996df80e4 fix: changing colormap for second volume in fusion viewport (#4746) 2025-02-04 09:05:55 -05:00
ohif-bot d5dbe20256 chore(version): Update package versions [skip ci] 2025-02-04 13:55:40 +00:00
ohif-bot 105fd7a468 chore(version): version.json [skip ci] 2025-02-04 13:55:34 +00:00
Abhijith Sb 2c183aa4a7 feat(ui): Add support for Custom Modal component in Modal Service (#4752) 2025-02-04 08:51:23 -05:00
ohif-bot 8788dae6a4 chore(version): Update package versions [skip ci] 2025-02-04 13:50:59 +00:00
ohif-bot 6937129991 chore(version): version.json [skip ci] 2025-02-04 13:50:54 +00:00
nithin-trenser 8acbd760d8 feat(ui): customization option for viewport notification (#4638) 2025-02-04 08:46:39 -05:00
ohif-bot c65e7f57cc chore(version): Update package versions [skip ci] 2025-02-04 13:36:09 +00:00
ohif-bot 5e09b405f4 chore(version): version.json [skip ci] 2025-02-04 13:36:04 +00:00
Joe Boccanfuso 12d3db2dbc fix(context-menu): Fixing regression introduced by PR #4727 (#4760) 2025-02-04 08:31:40 -05:00
ohif-bot ae9a238289 chore(version): Update package versions [skip ci] 2025-02-03 15:35:58 +00:00
ohif-bot 691accacd9 chore(version): version.json [skip ci] 2025-02-03 15:35:53 +00:00
arul-trenser e035ef1dcc fix(measurement label auto-completion): Customization of measurement label auto-completion fails for measurements following arrow annotations. (#4739) 2025-02-03 10:31:41 -05:00
ohif-bot 43aa20c372 chore(version): Update package versions [skip ci] 2025-02-03 14:33:26 +00:00
ohif-bot 860f76586a chore(version): version.json [skip ci] 2025-02-03 14:33:20 +00:00
Ibrahim 9b8e5cfd1a fix(store-segmentation): storing segmentations was hitting the wrong command resulting in an undefined datasource (#4755)
[OHI-1445]
2025-02-03 09:28:58 -05:00
ohif-bot 613401e043 chore(version): Update package versions [skip ci] 2025-02-03 14:22:28 +00:00
ohif-bot 47b9a06f74 chore(version): version.json [skip ci] 2025-02-03 14:22:22 +00:00
f15eb44b4c feat: Add customization support for more UI components (#4634)
Co-authored-by: ashikcn <ashik@L1140.trenser.com>
Co-authored-by: Devu Jayalekshmi <devu.jayalekshmi@trenser.com>
Co-authored-by: Arul Mozhi <arul.mozhi@trenser.com>
2025-02-03 09:18:00 -05:00
ohif-bot 8f79ebafd9 chore(version): Update package versions [skip ci] 2025-01-31 15:12:46 +00:00
ohif-bot a3c7c2c3da chore(version): version.json [skip ci] 2025-01-31 15:12:40 +00:00
Celian-abd 32017d15a4 fix: Remove non-functional Tailwind class for SegmentationPanel (#4745) 2025-01-31 10:07:55 -05:00
ohif-bot e3967e62f2 chore(version): Update package versions [skip ci] 2025-01-31 14:47:57 +00:00
ohif-bot 09f9024728 chore(version): version.json [skip ci] 2025-01-31 14:47:51 +00:00
Alireza 0cb6106d0f fix: publish dependency (#4753) 2025-01-31 09:43:35 -05:00
ohif-bot 4dc26ae603 chore(version): Update package versions [skip ci] 2025-01-31 13:58:58 +00:00
ohif-bot 9850f92b8a chore(version): version.json [skip ci] 2025-01-31 13:58:52 +00:00
Gas Giantandscouser f10683c667 fix: typo in pet_series_module (#4748)
Co-authored-by: scouser <sharukh@Sharukhs-MacBook-Pro.local>
2025-01-31 08:54:45 -05:00
ohif-bot 2bfc790870 chore(version): Update package versions [skip ci] 2025-01-29 18:41:36 +00:00
ohif-bot 3f08a76aac chore(version): version.json [skip ci] 2025-01-29 18:41:29 +00:00
Dan Rukasandsedghi a8d84443a9 ui(components): migrates to new toolbar ui components and Numeric for Input InputRange and InputDoubleRange (#4728)
Co-authored-by: sedghi <ar.sedghi@gmail.com>
2025-01-29 13:36:52 -05:00
ohif-bot ac5ae4a29e chore(version): Update package versions [skip ci] 2025-01-29 14:19:36 +00:00
ohif-bot 6d9c701fa9 chore(version): version.json [skip ci] 2025-01-29 14:19:30 +00:00
Jaseel-trenser 054b262e9c feat(customization): enable custom onDropHandler for viewportGrid (#4641) 2025-01-29 09:14:50 -05:00
ohif-bot 3dac0f9e73 chore(version): Update package versions [skip ci] 2025-01-28 20:04:13 +00:00
ohif-bot d62c32c898 chore(version): version.json [skip ci] 2025-01-28 20:04:07 +00:00
Alireza d554f02f7c fix(dependencies): Update dcmjs library and improve documentation links (#4741) 2025-01-28 14:59:59 -05:00
ohif-bot ff6dd3a152 chore(version): Update package versions [skip ci] 2025-01-28 16:38:07 +00:00
ohif-bot a22818c1f4 chore(version): version.json [skip ci] 2025-01-28 16:38:01 +00:00
Joe Boccanfuso 6abb095b8a feat(side-panels): Added resize handle interactive feedback for side panels (#4734) 2025-01-28 11:33:53 -05:00
354 changed files with 24596 additions and 4630 deletions

No files matched your search

+7 -7
View File
@@ -2,7 +2,7 @@ version: 2.1
orbs:
codecov: codecov/codecov@1.0.5
cypress: cypress-io/cypress@3.3.1
cypress: cypress-io/cypress@3.4.2
defaults: &defaults
docker:
@@ -341,8 +341,10 @@ jobs:
steps:
- install_bun
- run:
name: Install Xvfb
command: sudo apt-get update && sudo apt-get install -y xvfb
name: Install System Dependencies
command: |
sudo apt-get update
sudo apt-get install -y xvfb libgtk2.0-0 libgtk-3-0 libgbm-dev libnotify-dev libgconf-2-4 libnss3 libxss1 libasound2 libxtst6
- run:
name: Start Xvfb
command: Xvfb :99 -screen 0 1920x1080x24 &
@@ -351,13 +353,11 @@ jobs:
name: Export Display Variable
command: export DISPLAY=:99
- cypress/install:
install-browsers: true
install-command: bun install --no-save
package-manager: yarn
- cypress/run-tests:
cypress-command:
npx wait-on@latest http://localhost:3000 && cd platform/app && npx cypress run --record
--browser chrome --parallel
cypress-command: |
npx wait-on@latest http://localhost:3000 && cd platform/app && npx cypress run --record --parallel
start-command: bun run test:data && bun run test:e2e:serve
DOCKER_MULTIARCH_MANIFEST:
+1 -1
View File
@@ -9,7 +9,7 @@ jobs:
timeout-minutes: 60
runs-on: ubuntu-latest
container:
image: mcr.microsoft.com/playwright:v1.49.0-noble
image: mcr.microsoft.com/playwright:v1.50.0-noble
strategy:
fail-fast: false
matrix:
+369
View File
@@ -3,6 +3,375 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
# [3.10.0-beta.112](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.111...v3.10.0-beta.112) (2025-02-28)
### Features
* separate checks for addWindowLevelActionMenu and addSegmentationOverlay ([#4813](https://github.com/OHIF/Viewers/issues/4813)) ([7f0cc0f](https://github.com/OHIF/Viewers/commit/7f0cc0f60e74a2e0ac2aea1fe6a786582b495c4e))
# [3.10.0-beta.111](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.110...v3.10.0-beta.111) (2025-02-26)
### Bug Fixes
* broken activateViewportBeforeInteraction behavior ([#4810](https://github.com/OHIF/Viewers/issues/4810)) ([fdb073c](https://github.com/OHIF/Viewers/commit/fdb073c216013477c8545db34d254a9ad328fe48))
# [3.10.0-beta.110](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.109...v3.10.0-beta.110) (2025-02-26)
### Bug Fixes
* **sr:** sr hydration and load was not working, Screenshot Comparison, and Testing ([#4814](https://github.com/OHIF/Viewers/issues/4814)) ([9233143](https://github.com/OHIF/Viewers/commit/9233143b9da5850080365e1526e24b44e9910075))
# [3.10.0-beta.109](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.108...v3.10.0-beta.109) (2025-02-25)
**Note:** Version bump only for package ohif-monorepo-root
# [3.10.0-beta.108](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.107...v3.10.0-beta.108) (2025-02-25)
**Note:** Version bump only for package ohif-monorepo-root
# [3.10.0-beta.107](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.106...v3.10.0-beta.107) (2025-02-25)
**Note:** Version bump only for package ohif-monorepo-root
# [3.10.0-beta.106](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.105...v3.10.0-beta.106) (2025-02-25)
### Features
* **hotkeys:** Migrate hotkeys to customization service and fix issues with overrides ([#4777](https://github.com/OHIF/Viewers/issues/4777)) ([3e6913b](https://github.com/OHIF/Viewers/commit/3e6913b097569280a5cc2fa5bbe4add52f149305))
# [3.10.0-beta.105](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.104...v3.10.0-beta.105) (2025-02-25)
### Bug Fixes
* Changes to address hang/crash on jump to instance ([#4679](https://github.com/OHIF/Viewers/issues/4679)) ([e480e84](https://github.com/OHIF/Viewers/commit/e480e841bb5da5281a7c4624a60d5964d690ebb8))
* **rt:** jump to segment discards the configured width ([#4799](https://github.com/OHIF/Viewers/issues/4799)) ([afd528b](https://github.com/OHIF/Viewers/commit/afd528b8d72c3d8360b54bb52604758e83ada863))
# [3.10.0-beta.104](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.103...v3.10.0-beta.104) (2025-02-25)
### Bug Fixes
* Delay for all series thumbnails on fetching thumbnail ([#4802](https://github.com/OHIF/Viewers/issues/4802)) ([bda98b0](https://github.com/OHIF/Viewers/commit/bda98b0beebde6294a522b5c7e0ca76724020a2f))
# [3.10.0-beta.103](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.102...v3.10.0-beta.103) (2025-02-23)
**Note:** Version bump only for package ohif-monorepo-root
# [3.10.0-beta.102](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.101...v3.10.0-beta.102) (2025-02-20)
### Bug Fixes
* combine frame instance ([#4792](https://github.com/OHIF/Viewers/issues/4792)) ([55f0b54](https://github.com/OHIF/Viewers/commit/55f0b54db1e81a99f9e2d92b1d6d78dfb02762f0))
# [3.10.0-beta.101](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.100...v3.10.0-beta.101) (2025-02-20)
### Bug Fixes
* icon is not defined ([#4794](https://github.com/OHIF/Viewers/issues/4794)) ([b7cd0c6](https://github.com/OHIF/Viewers/commit/b7cd0c6027debcbfa573bc8068bc2e87928af9a5))
# [3.10.0-beta.100](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.99...v3.10.0-beta.100) (2025-02-19)
### Bug Fixes
* **button:** fix for className ([#4604](https://github.com/OHIF/Viewers/issues/4604)) ([125f11f](https://github.com/OHIF/Viewers/commit/125f11fc737f70ec9324798245787f44198e3bd4))
# [3.10.0-beta.99](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.98...v3.10.0-beta.99) (2025-02-18)
### Bug Fixes
* cache thumbnail in display set ([#4782](https://github.com/OHIF/Viewers/issues/4782)) ([2410c6a](https://github.com/OHIF/Viewers/commit/2410c6a50904c1235993900e837876cc26af019b))
# [3.10.0-beta.98](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.97...v3.10.0-beta.98) (2025-02-18)
### Bug Fixes
* lodash dependencies ([#4791](https://github.com/OHIF/Viewers/issues/4791)) ([4e16099](https://github.com/OHIF/Viewers/commit/4e16099ad3ab777b09f6ac8f181025cfd656ab6b))
# [3.10.0-beta.97](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.96...v3.10.0-beta.97) (2025-02-18)
### Features
* improve dicom tag browser with nested rows ([#4451](https://github.com/OHIF/Viewers/issues/4451)) ([0b5836c](https://github.com/OHIF/Viewers/commit/0b5836ca1a908e152336752672b196f0d533f4f9))
# [3.10.0-beta.96](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.95...v3.10.0-beta.96) (2025-02-18)
### Bug Fixes
* depandabot ([#4786](https://github.com/OHIF/Viewers/issues/4786)) ([d8a6e79](https://github.com/OHIF/Viewers/commit/d8a6e79df008139f7f2f45054b73baf8cd52fb40))
* right panel for the create mode cli command ([#4788](https://github.com/OHIF/Viewers/issues/4788)) ([5712e91](https://github.com/OHIF/Viewers/commit/5712e91ca1d939ff3c36615d3cf1a1f6f0051c4f))
# [3.10.0-beta.95](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.94...v3.10.0-beta.95) (2025-02-13)
**Note:** Version bump only for package ohif-monorepo-root
# [3.10.0-beta.94](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.93...v3.10.0-beta.94) (2025-02-11)
### Features
* add viewport overlays to microscopy mode ([#4776](https://github.com/OHIF/Viewers/issues/4776)) ([084a10f](https://github.com/OHIF/Viewers/commit/084a10f7835acab6a851922850c474bc9c7b864b))
# [3.10.0-beta.93](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.92...v3.10.0-beta.93) (2025-02-04)
### Bug Fixes
* add commandsManager to MoreDropdownMenu onClick props ([#4765](https://github.com/OHIF/Viewers/issues/4765)) ([bbf1a19](https://github.com/OHIF/Viewers/commit/bbf1a19676b2b345a0f911dde319e5ffefe29fa6))
# [3.10.0-beta.92](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.91...v3.10.0-beta.92) (2025-02-04)
### Bug Fixes
* **core:** Address 3D reconstruction and Android compatibility issues and clean up 4D data mode ([#4762](https://github.com/OHIF/Viewers/issues/4762)) ([149d6d0](https://github.com/OHIF/Viewers/commit/149d6d049cd333b9e5846576b403ff387558a66f))
# [3.10.0-beta.91](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.90...v3.10.0-beta.91) (2025-02-04)
### Bug Fixes
* changing colormap for second volume in fusion viewport ([#4746](https://github.com/OHIF/Viewers/issues/4746)) ([8996df8](https://github.com/OHIF/Viewers/commit/8996df80e45c97ad5847ebbd19291cd772a2163d))
# [3.10.0-beta.90](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.89...v3.10.0-beta.90) (2025-02-04)
### Features
* **ui:** Add support for Custom Modal component in Modal Service ([#4752](https://github.com/OHIF/Viewers/issues/4752)) ([2c183aa](https://github.com/OHIF/Viewers/commit/2c183aa4a777d7b5a0417ebcc8576a0fc2631ad2))
# [3.10.0-beta.89](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.88...v3.10.0-beta.89) (2025-02-04)
### Features
* **ui:** customization option for viewport notification ([#4638](https://github.com/OHIF/Viewers/issues/4638)) ([8acbd76](https://github.com/OHIF/Viewers/commit/8acbd760d801dcaf624c5d9fb636a029201b91e1))
# [3.10.0-beta.88](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.87...v3.10.0-beta.88) (2025-02-04)
### Bug Fixes
* **context-menu:** Fixing regression introduced by PR [#4727](https://github.com/OHIF/Viewers/issues/4727) ([#4760](https://github.com/OHIF/Viewers/issues/4760)) ([12d3db2](https://github.com/OHIF/Viewers/commit/12d3db2dbc80438df60139c67e9bcf0a610532d6))
# [3.10.0-beta.87](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.86...v3.10.0-beta.87) (2025-02-03)
### Bug Fixes
* **measurement label auto-completion:** Customization of measurement label auto-completion fails for measurements following arrow annotations. ([#4739](https://github.com/OHIF/Viewers/issues/4739)) ([e035ef1](https://github.com/OHIF/Viewers/commit/e035ef1dcc72ecbe2a757e3b814551d768d7e610))
# [3.10.0-beta.86](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.85...v3.10.0-beta.86) (2025-02-03)
### Bug Fixes
* **store-segmentation:** storing segmentations was hitting the wrong command resulting in an undefined datasource ([#4755](https://github.com/OHIF/Viewers/issues/4755)) ([9b8e5cf](https://github.com/OHIF/Viewers/commit/9b8e5cfd1a6121a58991c0f75660a2fd9913a4e7))
# [3.10.0-beta.85](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.84...v3.10.0-beta.85) (2025-02-03)
### Features
* Add customization support for more UI components ([#4634](https://github.com/OHIF/Viewers/issues/4634)) ([f15eb44](https://github.com/OHIF/Viewers/commit/f15eb44b4cf49de1b73a22512571cec02effaef3))
# [3.10.0-beta.84](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.83...v3.10.0-beta.84) (2025-01-31)
### Bug Fixes
* Remove non-functional Tailwind class for SegmentationPanel ([#4745](https://github.com/OHIF/Viewers/issues/4745)) ([32017d1](https://github.com/OHIF/Viewers/commit/32017d15a4c11e0cb7717c13da022a01ee152ba5))
# [3.10.0-beta.83](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.82...v3.10.0-beta.83) (2025-01-31)
### Bug Fixes
* publish dependency ([#4753](https://github.com/OHIF/Viewers/issues/4753)) ([0cb6106](https://github.com/OHIF/Viewers/commit/0cb6106d0fa576348ca3324685d5768b6ec80572))
# [3.10.0-beta.82](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.81...v3.10.0-beta.82) (2025-01-31)
### Bug Fixes
* typo in pet_series_module ([#4748](https://github.com/OHIF/Viewers/issues/4748)) ([f10683c](https://github.com/OHIF/Viewers/commit/f10683c667ea8f20c8d3e99ee0fb206522757b71))
# [3.10.0-beta.81](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.80...v3.10.0-beta.81) (2025-01-29)
**Note:** Version bump only for package ohif-monorepo-root
# [3.10.0-beta.80](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.79...v3.10.0-beta.80) (2025-01-29)
### Features
* **customization:** enable custom onDropHandler for viewportGrid ([#4641](https://github.com/OHIF/Viewers/issues/4641)) ([054b262](https://github.com/OHIF/Viewers/commit/054b262e9cbeb0f44de65d05641efe1e8944a4f5))
# [3.10.0-beta.79](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.78...v3.10.0-beta.79) (2025-01-28)
### Bug Fixes
* **dependencies:** Update dcmjs library and improve documentation links ([#4741](https://github.com/OHIF/Viewers/issues/4741)) ([d554f02](https://github.com/OHIF/Viewers/commit/d554f02f7cdb876e4132fb94e3b3df8d11b7bb5c))
# [3.10.0-beta.78](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.77...v3.10.0-beta.78) (2025-01-28)
### Features
* **side-panels:** Added resize handle interactive feedback for side panels ([#4734](https://github.com/OHIF/Viewers/issues/4734)) ([6abb095](https://github.com/OHIF/Viewers/commit/6abb095b8a39c5ae4f8df8852b3ddb3249ec463f))
# [3.10.0-beta.77](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.76...v3.10.0-beta.77) (2025-01-28)
+1 -1
View File
@@ -135,7 +135,7 @@ Here is a schematic representation of our development workflow:
### Requirements
- [Yarn 1.17.3+](https://yarnpkg.com/en/docs/install)
- [Yarn 1.20.0+](https://yarnpkg.com/en/docs/install)
- [Node 18+](https://nodejs.org/en/)
- Yarn Workspaces should be enabled on your machine:
- `yarn config set workspaces-experimental true`
+280
View File
@@ -3,6 +3,286 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
# [3.10.0-beta.112](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.111...v3.10.0-beta.112) (2025-02-28)
**Note:** Version bump only for package @externals/devDependencies
# [3.10.0-beta.111](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.110...v3.10.0-beta.111) (2025-02-26)
**Note:** Version bump only for package @externals/devDependencies
# [3.10.0-beta.110](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.109...v3.10.0-beta.110) (2025-02-26)
**Note:** Version bump only for package @externals/devDependencies
# [3.10.0-beta.109](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.108...v3.10.0-beta.109) (2025-02-25)
**Note:** Version bump only for package @externals/devDependencies
# [3.10.0-beta.108](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.107...v3.10.0-beta.108) (2025-02-25)
**Note:** Version bump only for package @externals/devDependencies
# [3.10.0-beta.107](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.106...v3.10.0-beta.107) (2025-02-25)
**Note:** Version bump only for package @externals/devDependencies
# [3.10.0-beta.106](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.105...v3.10.0-beta.106) (2025-02-25)
**Note:** Version bump only for package @externals/devDependencies
# [3.10.0-beta.105](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.104...v3.10.0-beta.105) (2025-02-25)
**Note:** Version bump only for package @externals/devDependencies
# [3.10.0-beta.104](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.103...v3.10.0-beta.104) (2025-02-25)
**Note:** Version bump only for package @externals/devDependencies
# [3.10.0-beta.103](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.102...v3.10.0-beta.103) (2025-02-23)
**Note:** Version bump only for package @externals/devDependencies
# [3.10.0-beta.102](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.101...v3.10.0-beta.102) (2025-02-20)
**Note:** Version bump only for package @externals/devDependencies
# [3.10.0-beta.101](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.100...v3.10.0-beta.101) (2025-02-20)
**Note:** Version bump only for package @externals/devDependencies
# [3.10.0-beta.100](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.99...v3.10.0-beta.100) (2025-02-19)
**Note:** Version bump only for package @externals/devDependencies
# [3.10.0-beta.99](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.98...v3.10.0-beta.99) (2025-02-18)
**Note:** Version bump only for package @externals/devDependencies
# [3.10.0-beta.98](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.97...v3.10.0-beta.98) (2025-02-18)
**Note:** Version bump only for package @externals/devDependencies
# [3.10.0-beta.97](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.96...v3.10.0-beta.97) (2025-02-18)
**Note:** Version bump only for package @externals/devDependencies
# [3.10.0-beta.96](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.95...v3.10.0-beta.96) (2025-02-18)
**Note:** Version bump only for package @externals/devDependencies
# [3.10.0-beta.95](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.94...v3.10.0-beta.95) (2025-02-13)
**Note:** Version bump only for package @externals/devDependencies
# [3.10.0-beta.94](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.93...v3.10.0-beta.94) (2025-02-11)
**Note:** Version bump only for package @externals/devDependencies
# [3.10.0-beta.93](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.92...v3.10.0-beta.93) (2025-02-04)
**Note:** Version bump only for package @externals/devDependencies
# [3.10.0-beta.92](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.91...v3.10.0-beta.92) (2025-02-04)
**Note:** Version bump only for package @externals/devDependencies
# [3.10.0-beta.91](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.90...v3.10.0-beta.91) (2025-02-04)
**Note:** Version bump only for package @externals/devDependencies
# [3.10.0-beta.90](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.89...v3.10.0-beta.90) (2025-02-04)
**Note:** Version bump only for package @externals/devDependencies
# [3.10.0-beta.89](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.88...v3.10.0-beta.89) (2025-02-04)
**Note:** Version bump only for package @externals/devDependencies
# [3.10.0-beta.88](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.87...v3.10.0-beta.88) (2025-02-04)
**Note:** Version bump only for package @externals/devDependencies
# [3.10.0-beta.87](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.86...v3.10.0-beta.87) (2025-02-03)
**Note:** Version bump only for package @externals/devDependencies
# [3.10.0-beta.86](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.85...v3.10.0-beta.86) (2025-02-03)
**Note:** Version bump only for package @externals/devDependencies
# [3.10.0-beta.85](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.84...v3.10.0-beta.85) (2025-02-03)
**Note:** Version bump only for package @externals/devDependencies
# [3.10.0-beta.84](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.83...v3.10.0-beta.84) (2025-01-31)
**Note:** Version bump only for package @externals/devDependencies
# [3.10.0-beta.83](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.82...v3.10.0-beta.83) (2025-01-31)
**Note:** Version bump only for package @externals/devDependencies
# [3.10.0-beta.82](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.81...v3.10.0-beta.82) (2025-01-31)
**Note:** Version bump only for package @externals/devDependencies
# [3.10.0-beta.81](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.80...v3.10.0-beta.81) (2025-01-29)
**Note:** Version bump only for package @externals/devDependencies
# [3.10.0-beta.80](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.79...v3.10.0-beta.80) (2025-01-29)
**Note:** Version bump only for package @externals/devDependencies
# [3.10.0-beta.79](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.78...v3.10.0-beta.79) (2025-01-28)
**Note:** Version bump only for package @externals/devDependencies
# [3.10.0-beta.78](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.77...v3.10.0-beta.78) (2025-01-28)
**Note:** Version bump only for package @externals/devDependencies
# [3.10.0-beta.77](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.76...v3.10.0-beta.77) (2025-01-28)
**Note:** Version bump only for package @externals/devDependencies
+1 -1
View File
@@ -1,7 +1,7 @@
{
"name": "@externals/devDependencies",
"description": "External dev dependencies - put dev build dependencies here",
"version": "3.10.0-beta.77",
"version": "3.10.0-beta.112",
"license": "MIT",
"private": true,
"engines": {
+280
View File
@@ -3,6 +3,286 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
# [3.10.0-beta.112](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.111...v3.10.0-beta.112) (2025-02-28)
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
# [3.10.0-beta.111](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.110...v3.10.0-beta.111) (2025-02-26)
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
# [3.10.0-beta.110](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.109...v3.10.0-beta.110) (2025-02-26)
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
# [3.10.0-beta.109](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.108...v3.10.0-beta.109) (2025-02-25)
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
# [3.10.0-beta.108](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.107...v3.10.0-beta.108) (2025-02-25)
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
# [3.10.0-beta.107](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.106...v3.10.0-beta.107) (2025-02-25)
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
# [3.10.0-beta.106](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.105...v3.10.0-beta.106) (2025-02-25)
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
# [3.10.0-beta.105](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.104...v3.10.0-beta.105) (2025-02-25)
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
# [3.10.0-beta.104](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.103...v3.10.0-beta.104) (2025-02-25)
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
# [3.10.0-beta.103](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.102...v3.10.0-beta.103) (2025-02-23)
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
# [3.10.0-beta.102](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.101...v3.10.0-beta.102) (2025-02-20)
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
# [3.10.0-beta.101](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.100...v3.10.0-beta.101) (2025-02-20)
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
# [3.10.0-beta.100](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.99...v3.10.0-beta.100) (2025-02-19)
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
# [3.10.0-beta.99](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.98...v3.10.0-beta.99) (2025-02-18)
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
# [3.10.0-beta.98](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.97...v3.10.0-beta.98) (2025-02-18)
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
# [3.10.0-beta.97](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.96...v3.10.0-beta.97) (2025-02-18)
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
# [3.10.0-beta.96](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.95...v3.10.0-beta.96) (2025-02-18)
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
# [3.10.0-beta.95](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.94...v3.10.0-beta.95) (2025-02-13)
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
# [3.10.0-beta.94](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.93...v3.10.0-beta.94) (2025-02-11)
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
# [3.10.0-beta.93](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.92...v3.10.0-beta.93) (2025-02-04)
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
# [3.10.0-beta.92](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.91...v3.10.0-beta.92) (2025-02-04)
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
# [3.10.0-beta.91](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.90...v3.10.0-beta.91) (2025-02-04)
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
# [3.10.0-beta.90](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.89...v3.10.0-beta.90) (2025-02-04)
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
# [3.10.0-beta.89](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.88...v3.10.0-beta.89) (2025-02-04)
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
# [3.10.0-beta.88](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.87...v3.10.0-beta.88) (2025-02-04)
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
# [3.10.0-beta.87](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.86...v3.10.0-beta.87) (2025-02-03)
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
# [3.10.0-beta.86](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.85...v3.10.0-beta.86) (2025-02-03)
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
# [3.10.0-beta.85](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.84...v3.10.0-beta.85) (2025-02-03)
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
# [3.10.0-beta.84](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.83...v3.10.0-beta.84) (2025-01-31)
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
# [3.10.0-beta.83](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.82...v3.10.0-beta.83) (2025-01-31)
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
# [3.10.0-beta.82](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.81...v3.10.0-beta.82) (2025-01-31)
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
# [3.10.0-beta.81](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.80...v3.10.0-beta.81) (2025-01-29)
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
# [3.10.0-beta.80](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.79...v3.10.0-beta.80) (2025-01-29)
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
# [3.10.0-beta.79](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.78...v3.10.0-beta.79) (2025-01-28)
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
# [3.10.0-beta.78](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.77...v3.10.0-beta.78) (2025-01-28)
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
# [3.10.0-beta.77](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.76...v3.10.0-beta.77) (2025-01-28)
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
+1 -1
View File
@@ -1,7 +1,7 @@
{
"name": "@externals/dicom-microscopy-viewer",
"description": "External reference to dicom-microscopy-viewer",
"version": "3.10.0-beta.77",
"version": "3.10.0-beta.112",
"license": "MIT",
"dependencies": {
"dicom-microscopy-viewer": "^0.46.1"
+1 -1
View File
@@ -38,7 +38,7 @@
"resolutions": {
"**/@babel/runtime": "^7.20.13",
"commander": "8.3.0",
"dcmjs": ">=0.33.0",
"dcmjs": "0.38.0",
"dicomweb-client": ">=0.10.4",
"nth-check": "^2.1.1",
"trim-newlines": "^5.0.0",
+7767
View File
File diff suppressed because it is too large. Load diff
BIN
View File
Binary file not shown.
+1 -1
View File
@@ -1 +1 @@
5addf51c459cd7371da028d68d8ce8d3e795334d
7f0cc0f60e74a2e0ac2aea1fe6a786582b495c4e
@@ -3,6 +3,292 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
# [3.10.0-beta.112](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.111...v3.10.0-beta.112) (2025-02-28)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
# [3.10.0-beta.111](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.110...v3.10.0-beta.111) (2025-02-26)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
# [3.10.0-beta.110](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.109...v3.10.0-beta.110) (2025-02-26)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
# [3.10.0-beta.109](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.108...v3.10.0-beta.109) (2025-02-25)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
# [3.10.0-beta.108](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.107...v3.10.0-beta.108) (2025-02-25)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
# [3.10.0-beta.107](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.106...v3.10.0-beta.107) (2025-02-25)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
# [3.10.0-beta.106](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.105...v3.10.0-beta.106) (2025-02-25)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
# [3.10.0-beta.105](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.104...v3.10.0-beta.105) (2025-02-25)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
# [3.10.0-beta.104](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.103...v3.10.0-beta.104) (2025-02-25)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
# [3.10.0-beta.103](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.102...v3.10.0-beta.103) (2025-02-23)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
# [3.10.0-beta.102](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.101...v3.10.0-beta.102) (2025-02-20)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
# [3.10.0-beta.101](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.100...v3.10.0-beta.101) (2025-02-20)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
# [3.10.0-beta.100](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.99...v3.10.0-beta.100) (2025-02-19)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
# [3.10.0-beta.99](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.98...v3.10.0-beta.99) (2025-02-18)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
# [3.10.0-beta.98](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.97...v3.10.0-beta.98) (2025-02-18)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
# [3.10.0-beta.97](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.96...v3.10.0-beta.97) (2025-02-18)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
# [3.10.0-beta.96](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.95...v3.10.0-beta.96) (2025-02-18)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
# [3.10.0-beta.95](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.94...v3.10.0-beta.95) (2025-02-13)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
# [3.10.0-beta.94](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.93...v3.10.0-beta.94) (2025-02-11)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
# [3.10.0-beta.93](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.92...v3.10.0-beta.93) (2025-02-04)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
# [3.10.0-beta.92](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.91...v3.10.0-beta.92) (2025-02-04)
### Bug Fixes
* **core:** Address 3D reconstruction and Android compatibility issues and clean up 4D data mode ([#4762](https://github.com/OHIF/Viewers/issues/4762)) ([149d6d0](https://github.com/OHIF/Viewers/commit/149d6d049cd333b9e5846576b403ff387558a66f))
# [3.10.0-beta.91](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.90...v3.10.0-beta.91) (2025-02-04)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
# [3.10.0-beta.90](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.89...v3.10.0-beta.90) (2025-02-04)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
# [3.10.0-beta.89](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.88...v3.10.0-beta.89) (2025-02-04)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
# [3.10.0-beta.88](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.87...v3.10.0-beta.88) (2025-02-04)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
# [3.10.0-beta.87](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.86...v3.10.0-beta.87) (2025-02-03)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
# [3.10.0-beta.86](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.85...v3.10.0-beta.86) (2025-02-03)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
# [3.10.0-beta.85](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.84...v3.10.0-beta.85) (2025-02-03)
### Features
* Add customization support for more UI components ([#4634](https://github.com/OHIF/Viewers/issues/4634)) ([f15eb44](https://github.com/OHIF/Viewers/commit/f15eb44b4cf49de1b73a22512571cec02effaef3))
# [3.10.0-beta.84](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.83...v3.10.0-beta.84) (2025-01-31)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
# [3.10.0-beta.83](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.82...v3.10.0-beta.83) (2025-01-31)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
# [3.10.0-beta.82](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.81...v3.10.0-beta.82) (2025-01-31)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
# [3.10.0-beta.81](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.80...v3.10.0-beta.81) (2025-01-29)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
# [3.10.0-beta.80](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.79...v3.10.0-beta.80) (2025-01-29)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
# [3.10.0-beta.79](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.78...v3.10.0-beta.79) (2025-01-28)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
# [3.10.0-beta.78](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.77...v3.10.0-beta.78) (2025-01-28)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
# [3.10.0-beta.77](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.76...v3.10.0-beta.77) (2025-01-28)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
@@ -1,6 +1,6 @@
{
"name": "@ohif/extension-cornerstone-dicom-pmap",
"version": "3.10.0-beta.77",
"version": "3.10.0-beta.112",
"description": "DICOM Parametric Map read workflow",
"author": "OHIF",
"license": "MIT",
@@ -33,10 +33,10 @@
"start": "yarn run dev"
},
"peerDependencies": {
"@ohif/core": "3.10.0-beta.77",
"@ohif/extension-cornerstone": "3.10.0-beta.77",
"@ohif/extension-default": "3.10.0-beta.77",
"@ohif/i18n": "3.10.0-beta.77",
"@ohif/core": "3.10.0-beta.112",
"@ohif/extension-cornerstone": "3.10.0-beta.112",
"@ohif/extension-default": "3.10.0-beta.112",
"@ohif/i18n": "3.10.0-beta.112",
"prop-types": "^15.6.2",
"react": "^18.3.1",
"react-dom": "^18.3.1",
@@ -46,8 +46,8 @@
},
"dependencies": {
"@babel/runtime": "^7.20.13",
"@cornerstonejs/adapters": "^2.17.2",
"@cornerstonejs/core": "^2.17.2",
"@cornerstonejs/adapters": "^2.19.14",
"@cornerstonejs/core": "^2.19.14",
"@kitware/vtk.js": "32.1.1",
"react-color": "^2.19.3"
}
@@ -1,6 +1,5 @@
import PropTypes from 'prop-types';
import React, { useCallback, useEffect, useRef, useState } from 'react';
import { LoadingIndicatorTotalPercent } from '@ohif/ui';
import { useViewportGrid } from '@ohif/ui-next';
function OHIFCornerstonePMAPViewport(props: withAppTypes) {
@@ -13,7 +12,7 @@ function OHIFCornerstonePMAPViewport(props: withAppTypes) {
extensionManager,
} = props;
const viewportId = viewportOptions.viewportId;
const { displaySetService, segmentationService, uiNotificationService } =
const { displaySetService, segmentationService, uiNotificationService, customizationService } =
servicesManager.services;
// PMAP viewport will always have a single display set
@@ -21,6 +20,10 @@ function OHIFCornerstonePMAPViewport(props: withAppTypes) {
throw new Error('PMAP viewport must have a single display set');
}
const LoadingIndicatorTotalPercent = customizationService.getCustomization(
'ui.loadingIndicatorTotalPercent'
);
const pmapDisplaySet = displaySets[0];
const [viewportGrid, viewportGridService] = useViewportGrid();
const referencedDisplaySetRef = useRef(null);
@@ -3,6 +3,289 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
# [3.10.0-beta.112](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.111...v3.10.0-beta.112) (2025-02-28)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
# [3.10.0-beta.111](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.110...v3.10.0-beta.111) (2025-02-26)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
# [3.10.0-beta.110](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.109...v3.10.0-beta.110) (2025-02-26)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
# [3.10.0-beta.109](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.108...v3.10.0-beta.109) (2025-02-25)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
# [3.10.0-beta.108](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.107...v3.10.0-beta.108) (2025-02-25)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
# [3.10.0-beta.107](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.106...v3.10.0-beta.107) (2025-02-25)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
# [3.10.0-beta.106](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.105...v3.10.0-beta.106) (2025-02-25)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
# [3.10.0-beta.105](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.104...v3.10.0-beta.105) (2025-02-25)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
# [3.10.0-beta.104](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.103...v3.10.0-beta.104) (2025-02-25)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
# [3.10.0-beta.103](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.102...v3.10.0-beta.103) (2025-02-23)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
# [3.10.0-beta.102](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.101...v3.10.0-beta.102) (2025-02-20)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
# [3.10.0-beta.101](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.100...v3.10.0-beta.101) (2025-02-20)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
# [3.10.0-beta.100](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.99...v3.10.0-beta.100) (2025-02-19)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
# [3.10.0-beta.99](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.98...v3.10.0-beta.99) (2025-02-18)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
# [3.10.0-beta.98](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.97...v3.10.0-beta.98) (2025-02-18)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
# [3.10.0-beta.97](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.96...v3.10.0-beta.97) (2025-02-18)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
# [3.10.0-beta.96](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.95...v3.10.0-beta.96) (2025-02-18)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
# [3.10.0-beta.95](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.94...v3.10.0-beta.95) (2025-02-13)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
# [3.10.0-beta.94](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.93...v3.10.0-beta.94) (2025-02-11)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
# [3.10.0-beta.93](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.92...v3.10.0-beta.93) (2025-02-04)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
# [3.10.0-beta.92](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.91...v3.10.0-beta.92) (2025-02-04)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
# [3.10.0-beta.91](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.90...v3.10.0-beta.91) (2025-02-04)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
# [3.10.0-beta.90](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.89...v3.10.0-beta.90) (2025-02-04)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
# [3.10.0-beta.89](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.88...v3.10.0-beta.89) (2025-02-04)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
# [3.10.0-beta.88](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.87...v3.10.0-beta.88) (2025-02-04)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
# [3.10.0-beta.87](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.86...v3.10.0-beta.87) (2025-02-03)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
# [3.10.0-beta.86](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.85...v3.10.0-beta.86) (2025-02-03)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
# [3.10.0-beta.85](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.84...v3.10.0-beta.85) (2025-02-03)
### Features
* Add customization support for more UI components ([#4634](https://github.com/OHIF/Viewers/issues/4634)) ([f15eb44](https://github.com/OHIF/Viewers/commit/f15eb44b4cf49de1b73a22512571cec02effaef3))
# [3.10.0-beta.84](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.83...v3.10.0-beta.84) (2025-01-31)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
# [3.10.0-beta.83](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.82...v3.10.0-beta.83) (2025-01-31)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
# [3.10.0-beta.82](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.81...v3.10.0-beta.82) (2025-01-31)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
# [3.10.0-beta.81](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.80...v3.10.0-beta.81) (2025-01-29)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
# [3.10.0-beta.80](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.79...v3.10.0-beta.80) (2025-01-29)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
# [3.10.0-beta.79](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.78...v3.10.0-beta.79) (2025-01-28)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
# [3.10.0-beta.78](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.77...v3.10.0-beta.78) (2025-01-28)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
# [3.10.0-beta.77](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.76...v3.10.0-beta.77) (2025-01-28)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
+5 -5
View File
@@ -1,6 +1,6 @@
{
"name": "@ohif/extension-cornerstone-dicom-rt",
"version": "3.10.0-beta.77",
"version": "3.10.0-beta.112",
"description": "DICOM RT read workflow",
"author": "OHIF",
"license": "MIT",
@@ -33,10 +33,10 @@
"start": "yarn run dev"
},
"peerDependencies": {
"@ohif/core": "3.10.0-beta.77",
"@ohif/extension-cornerstone": "3.10.0-beta.77",
"@ohif/extension-default": "3.10.0-beta.77",
"@ohif/i18n": "3.10.0-beta.77",
"@ohif/core": "3.10.0-beta.112",
"@ohif/extension-cornerstone": "3.10.0-beta.112",
"@ohif/extension-default": "3.10.0-beta.112",
"@ohif/i18n": "3.10.0-beta.112",
"prop-types": "^15.6.2",
"react": "^18.3.1",
"react-dom": "^18.3.1",
@@ -1,7 +1,8 @@
import React, { useCallback, useEffect, useRef, useState } from 'react';
import PropTypes from 'prop-types';
import { LoadingIndicatorTotalPercent, ViewportActionArrows } from '@ohif/ui';
import { ViewportActionArrows } from '@ohif/ui';
import { useViewportGrid } from '@ohif/ui-next';
import { utils } from '@ohif/extension-cornerstone';
import promptHydrateRT from '../utils/promptHydrateRT';
import _getStatusComponent from './_getStatusComponent';
@@ -39,12 +40,16 @@ function OHIFCornerstoneRTViewport(props: withAppTypes) {
throw new Error('RT viewport should only have a single display set');
}
const LoadingIndicatorTotalPercent = customizationService.getCustomization(
'ui.loadingIndicatorTotalPercent'
);
const rtDisplaySet = displaySets[0];
const [viewportGrid, viewportGridService] = useViewportGrid();
// States
const [selectedSegment, setSelectedSegment] = useState(1);
const selectedSegmentObjectIndex: number = 0;
const { setPositionPresentation } = usePositionPresentationStore();
// Hydration means that the RT is opened and segments are loaded into the
@@ -137,26 +142,15 @@ function OHIFCornerstoneRTViewport(props: withAppTypes) {
const onSegmentChange = useCallback(
direction => {
const segmentationId = rtDisplaySet.displaySetInstanceUID;
const segmentation = segmentationService.getSegmentation(segmentationId);
const { segments } = segmentation;
const numberOfSegments = Object.keys(segments).length;
let newSelectedSegmentIndex = selectedSegment + direction;
// Segment 0 is always background
if (newSelectedSegmentIndex >= numberOfSegments - 1) {
newSelectedSegmentIndex = 1;
} else if (newSelectedSegmentIndex === 0) {
newSelectedSegmentIndex = numberOfSegments - 1;
}
segmentationService.jumpToSegmentCenter(segmentationId, newSelectedSegmentIndex, viewportId);
setSelectedSegment(newSelectedSegmentIndex);
utils.handleSegmentChange({
direction,
segDisplaySet: rtDisplaySet,
viewportId,
selectedSegmentObjectIndex,
segmentationService,
});
},
[selectedSegment, segmentationService]
[selectedSegmentObjectIndex]
);
useEffect(() => {
@@ -3,6 +3,295 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
# [3.10.0-beta.112](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.111...v3.10.0-beta.112) (2025-02-28)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
# [3.10.0-beta.111](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.110...v3.10.0-beta.111) (2025-02-26)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
# [3.10.0-beta.110](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.109...v3.10.0-beta.110) (2025-02-26)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
# [3.10.0-beta.109](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.108...v3.10.0-beta.109) (2025-02-25)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
# [3.10.0-beta.108](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.107...v3.10.0-beta.108) (2025-02-25)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
# [3.10.0-beta.107](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.106...v3.10.0-beta.107) (2025-02-25)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
# [3.10.0-beta.106](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.105...v3.10.0-beta.106) (2025-02-25)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
# [3.10.0-beta.105](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.104...v3.10.0-beta.105) (2025-02-25)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
# [3.10.0-beta.104](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.103...v3.10.0-beta.104) (2025-02-25)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
# [3.10.0-beta.103](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.102...v3.10.0-beta.103) (2025-02-23)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
# [3.10.0-beta.102](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.101...v3.10.0-beta.102) (2025-02-20)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
# [3.10.0-beta.101](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.100...v3.10.0-beta.101) (2025-02-20)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
# [3.10.0-beta.100](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.99...v3.10.0-beta.100) (2025-02-19)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
# [3.10.0-beta.99](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.98...v3.10.0-beta.99) (2025-02-18)
### Bug Fixes
* cache thumbnail in display set ([#4782](https://github.com/OHIF/Viewers/issues/4782)) ([2410c6a](https://github.com/OHIF/Viewers/commit/2410c6a50904c1235993900e837876cc26af019b))
# [3.10.0-beta.98](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.97...v3.10.0-beta.98) (2025-02-18)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
# [3.10.0-beta.97](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.96...v3.10.0-beta.97) (2025-02-18)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
# [3.10.0-beta.96](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.95...v3.10.0-beta.96) (2025-02-18)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
# [3.10.0-beta.95](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.94...v3.10.0-beta.95) (2025-02-13)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
# [3.10.0-beta.94](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.93...v3.10.0-beta.94) (2025-02-11)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
# [3.10.0-beta.93](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.92...v3.10.0-beta.93) (2025-02-04)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
# [3.10.0-beta.92](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.91...v3.10.0-beta.92) (2025-02-04)
### Bug Fixes
* **core:** Address 3D reconstruction and Android compatibility issues and clean up 4D data mode ([#4762](https://github.com/OHIF/Viewers/issues/4762)) ([149d6d0](https://github.com/OHIF/Viewers/commit/149d6d049cd333b9e5846576b403ff387558a66f))
# [3.10.0-beta.91](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.90...v3.10.0-beta.91) (2025-02-04)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
# [3.10.0-beta.90](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.89...v3.10.0-beta.90) (2025-02-04)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
# [3.10.0-beta.89](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.88...v3.10.0-beta.89) (2025-02-04)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
# [3.10.0-beta.88](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.87...v3.10.0-beta.88) (2025-02-04)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
# [3.10.0-beta.87](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.86...v3.10.0-beta.87) (2025-02-03)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
# [3.10.0-beta.86](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.85...v3.10.0-beta.86) (2025-02-03)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
# [3.10.0-beta.85](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.84...v3.10.0-beta.85) (2025-02-03)
### Features
* Add customization support for more UI components ([#4634](https://github.com/OHIF/Viewers/issues/4634)) ([f15eb44](https://github.com/OHIF/Viewers/commit/f15eb44b4cf49de1b73a22512571cec02effaef3))
# [3.10.0-beta.84](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.83...v3.10.0-beta.84) (2025-01-31)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
# [3.10.0-beta.83](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.82...v3.10.0-beta.83) (2025-01-31)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
# [3.10.0-beta.82](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.81...v3.10.0-beta.82) (2025-01-31)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
# [3.10.0-beta.81](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.80...v3.10.0-beta.81) (2025-01-29)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
# [3.10.0-beta.80](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.79...v3.10.0-beta.80) (2025-01-29)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
# [3.10.0-beta.79](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.78...v3.10.0-beta.79) (2025-01-28)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
# [3.10.0-beta.78](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.77...v3.10.0-beta.78) (2025-01-28)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
# [3.10.0-beta.77](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.76...v3.10.0-beta.77) (2025-01-28)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
@@ -1,6 +1,6 @@
{
"name": "@ohif/extension-cornerstone-dicom-seg",
"version": "3.10.0-beta.77",
"version": "3.10.0-beta.112",
"description": "DICOM SEG read workflow",
"author": "OHIF",
"license": "MIT",
@@ -33,10 +33,10 @@
"start": "yarn run dev"
},
"peerDependencies": {
"@ohif/core": "3.10.0-beta.77",
"@ohif/extension-cornerstone": "3.10.0-beta.77",
"@ohif/extension-default": "3.10.0-beta.77",
"@ohif/i18n": "3.10.0-beta.77",
"@ohif/core": "3.10.0-beta.112",
"@ohif/extension-cornerstone": "3.10.0-beta.112",
"@ohif/extension-default": "3.10.0-beta.112",
"@ohif/i18n": "3.10.0-beta.112",
"prop-types": "^15.6.2",
"react": "^18.3.1",
"react-dom": "^18.3.1",
@@ -46,8 +46,8 @@
},
"dependencies": {
"@babel/runtime": "^7.20.13",
"@cornerstonejs/adapters": "^2.17.2",
"@cornerstonejs/core": "^2.17.2",
"@cornerstonejs/adapters": "^2.19.14",
"@cornerstonejs/core": "^2.19.14",
"@kitware/vtk.js": "32.1.1",
"react-color": "^2.19.3"
}
@@ -1,6 +1,15 @@
export function getToolbarModule({ servicesManager }: withAppTypes) {
const { segmentationService, toolbarService, toolGroupService } = servicesManager.services;
return [
{
name: 'evaluate.cornerstone.hasSegmentation',
evaluate: ({ viewportId }) => {
const segmentations = segmentationService.getSegmentationRepresentations(viewportId);
return {
disabled: !segmentations?.length,
};
},
},
{
name: 'evaluate.cornerstone.segmentation',
evaluate: ({ viewportId, button, toolNames, disabledText }) => {
@@ -12,17 +21,23 @@ export function getToolbarModule({ servicesManager }: withAppTypes) {
if (!segmentations?.length) {
return {
disabled: true,
className: '!text-common-bright !bg-black opacity-50',
disabledText: disabledText ?? 'No segmentations available',
};
}
const activeSegmentation = segmentationService.getActiveSegmentation(viewportId);
if (!Object.keys(activeSegmentation.segments).length) {
return {
disabled: true,
disabledText: 'Add segment to enable this tool',
};
}
const toolGroup = toolGroupService.getToolGroupForViewport(viewportId);
if (!toolGroup) {
return {
disabled: true,
className: '!text-common-bright ohif-disabled',
disabledText: disabledText ?? 'Not available on the current viewport',
};
}
@@ -32,7 +47,6 @@ export function getToolbarModule({ servicesManager }: withAppTypes) {
if (!toolGroup.hasTool(toolName) && !toolNames) {
return {
disabled: true,
className: '!text-common-bright ohif-disabled',
disabledText: disabledText ?? 'Not available on the current viewport',
};
}
@@ -43,12 +57,6 @@ export function getToolbarModule({ servicesManager }: withAppTypes) {
return {
disabled: false,
className: isPrimaryActive
? '!text-black !bg-primary-light hover:bg-primary-light hover-text-black hover:cursor-pointer'
: '!text-common-bright !bg-black hover:bg-primary-light hover:cursor-pointer hover:text-black',
// Todo: isActive right now is used for nested buttons where the primary
// button needs to be fully rounded (vs partial rounded) when active
// otherwise it does not have any other use
isActive: isPrimaryActive,
};
},
@@ -1,12 +1,13 @@
import React, { useCallback, useEffect, useRef, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { LoadingIndicatorTotalPercent, ViewportActionArrows } from '@ohif/ui';
import { ViewportActionArrows } from '@ohif/ui';
import { useViewportGrid } from '@ohif/ui-next';
import createSEGToolGroupAndAddTools from '../utils/initSEGToolGroup';
import promptHydrateSEG from '../utils/promptHydrateSEG';
import _getStatusComponent from './_getStatusComponent';
import { usePositionPresentationStore } from '@ohif/extension-cornerstone';
import { SegmentationRepresentations } from '@cornerstonejs/tools/enums';
import { utils } from '@ohif/extension-cornerstone';
const SEG_TOOLGROUP_BASE_NAME = 'SEGToolGroup';
@@ -31,6 +32,10 @@ function OHIFCornerstoneSEGViewport(props: withAppTypes) {
viewportActionCornersService,
} = servicesManager.services;
const LoadingIndicatorTotalPercent = customizationService.getCustomization(
'ui.loadingIndicatorTotalPercent'
);
const toolGroupId = `${SEG_TOOLGROUP_BASE_NAME}-${viewportId}`;
// SEG viewport will always have a single display set
@@ -42,7 +47,7 @@ function OHIFCornerstoneSEGViewport(props: withAppTypes) {
const [viewportGrid, viewportGridService] = useViewportGrid();
// States
const [selectedSegment, setSelectedSegment] = useState(1);
let selectedSegmentObjectIndex: number = 0;
const { setPositionPresentation } = usePositionPresentationStore();
// Hydration means that the SEG is opened and segments are loaded into the
@@ -127,27 +132,15 @@ function OHIFCornerstoneSEGViewport(props: withAppTypes) {
const onSegmentChange = useCallback(
direction => {
const segmentationId = segDisplaySet.displaySetInstanceUID;
const segmentation = segmentationService.getSegmentation(segmentationId);
const { segments } = segmentation;
const numberOfSegments = Object.keys(segments).length;
let newSelectedSegmentIndex = selectedSegment + direction;
// Segment 0 is always background
if (newSelectedSegmentIndex > numberOfSegments - 1) {
newSelectedSegmentIndex = 1;
} else if (newSelectedSegmentIndex === 0) {
newSelectedSegmentIndex = numberOfSegments - 1;
}
segmentationService.jumpToSegmentCenter(segmentationId, newSelectedSegmentIndex, viewportId);
setSelectedSegment(newSelectedSegmentIndex);
utils.handleSegmentChange({
direction,
segDisplaySet: segDisplaySet,
viewportId,
selectedSegmentObjectIndex,
segmentationService,
});
},
[selectedSegment]
[selectedSegmentObjectIndex]
);
const hydrateSEG = useCallback(() => {
@@ -3,6 +3,289 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
# [3.10.0-beta.112](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.111...v3.10.0-beta.112) (2025-02-28)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
# [3.10.0-beta.111](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.110...v3.10.0-beta.111) (2025-02-26)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
# [3.10.0-beta.110](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.109...v3.10.0-beta.110) (2025-02-26)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
# [3.10.0-beta.109](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.108...v3.10.0-beta.109) (2025-02-25)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
# [3.10.0-beta.108](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.107...v3.10.0-beta.108) (2025-02-25)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
# [3.10.0-beta.107](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.106...v3.10.0-beta.107) (2025-02-25)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
# [3.10.0-beta.106](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.105...v3.10.0-beta.106) (2025-02-25)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
# [3.10.0-beta.105](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.104...v3.10.0-beta.105) (2025-02-25)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
# [3.10.0-beta.104](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.103...v3.10.0-beta.104) (2025-02-25)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
# [3.10.0-beta.103](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.102...v3.10.0-beta.103) (2025-02-23)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
# [3.10.0-beta.102](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.101...v3.10.0-beta.102) (2025-02-20)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
# [3.10.0-beta.101](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.100...v3.10.0-beta.101) (2025-02-20)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
# [3.10.0-beta.100](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.99...v3.10.0-beta.100) (2025-02-19)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
# [3.10.0-beta.99](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.98...v3.10.0-beta.99) (2025-02-18)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
# [3.10.0-beta.98](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.97...v3.10.0-beta.98) (2025-02-18)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
# [3.10.0-beta.97](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.96...v3.10.0-beta.97) (2025-02-18)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
# [3.10.0-beta.96](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.95...v3.10.0-beta.96) (2025-02-18)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
# [3.10.0-beta.95](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.94...v3.10.0-beta.95) (2025-02-13)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
# [3.10.0-beta.94](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.93...v3.10.0-beta.94) (2025-02-11)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
# [3.10.0-beta.93](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.92...v3.10.0-beta.93) (2025-02-04)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
# [3.10.0-beta.92](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.91...v3.10.0-beta.92) (2025-02-04)
### Bug Fixes
* **core:** Address 3D reconstruction and Android compatibility issues and clean up 4D data mode ([#4762](https://github.com/OHIF/Viewers/issues/4762)) ([149d6d0](https://github.com/OHIF/Viewers/commit/149d6d049cd333b9e5846576b403ff387558a66f))
# [3.10.0-beta.91](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.90...v3.10.0-beta.91) (2025-02-04)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
# [3.10.0-beta.90](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.89...v3.10.0-beta.90) (2025-02-04)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
# [3.10.0-beta.89](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.88...v3.10.0-beta.89) (2025-02-04)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
# [3.10.0-beta.88](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.87...v3.10.0-beta.88) (2025-02-04)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
# [3.10.0-beta.87](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.86...v3.10.0-beta.87) (2025-02-03)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
# [3.10.0-beta.86](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.85...v3.10.0-beta.86) (2025-02-03)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
# [3.10.0-beta.85](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.84...v3.10.0-beta.85) (2025-02-03)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
# [3.10.0-beta.84](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.83...v3.10.0-beta.84) (2025-01-31)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
# [3.10.0-beta.83](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.82...v3.10.0-beta.83) (2025-01-31)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
# [3.10.0-beta.82](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.81...v3.10.0-beta.82) (2025-01-31)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
# [3.10.0-beta.81](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.80...v3.10.0-beta.81) (2025-01-29)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
# [3.10.0-beta.80](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.79...v3.10.0-beta.80) (2025-01-29)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
# [3.10.0-beta.79](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.78...v3.10.0-beta.79) (2025-01-28)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
# [3.10.0-beta.78](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.77...v3.10.0-beta.78) (2025-01-28)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
# [3.10.0-beta.77](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.76...v3.10.0-beta.77) (2025-01-28)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
+8 -8
View File
@@ -1,6 +1,6 @@
{
"name": "@ohif/extension-cornerstone-dicom-sr",
"version": "3.10.0-beta.77",
"version": "3.10.0-beta.112",
"description": "OHIF extension for an SR Cornerstone Viewport",
"author": "OHIF",
"license": "MIT",
@@ -34,10 +34,10 @@
"test:unit:ci": "jest --ci --runInBand --collectCoverage --passWithNoTests"
},
"peerDependencies": {
"@ohif/core": "3.10.0-beta.77",
"@ohif/extension-cornerstone": "3.10.0-beta.77",
"@ohif/extension-measurement-tracking": "3.10.0-beta.77",
"@ohif/ui": "3.10.0-beta.77",
"@ohif/core": "3.10.0-beta.112",
"@ohif/extension-cornerstone": "3.10.0-beta.112",
"@ohif/extension-measurement-tracking": "3.10.0-beta.112",
"@ohif/ui": "3.10.0-beta.112",
"dcmjs": "*",
"dicom-parser": "^1.8.9",
"hammerjs": "^2.0.8",
@@ -46,9 +46,9 @@
},
"dependencies": {
"@babel/runtime": "^7.20.13",
"@cornerstonejs/adapters": "^2.17.2",
"@cornerstonejs/core": "^2.17.2",
"@cornerstonejs/tools": "^2.17.2",
"@cornerstonejs/adapters": "^2.19.14",
"@cornerstonejs/core": "^2.19.14",
"@cornerstonejs/tools": "^2.19.14",
"classnames": "^2.3.2"
}
}
@@ -3,6 +3,289 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
# [3.10.0-beta.112](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.111...v3.10.0-beta.112) (2025-02-28)
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
# [3.10.0-beta.111](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.110...v3.10.0-beta.111) (2025-02-26)
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
# [3.10.0-beta.110](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.109...v3.10.0-beta.110) (2025-02-26)
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
# [3.10.0-beta.109](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.108...v3.10.0-beta.109) (2025-02-25)
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
# [3.10.0-beta.108](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.107...v3.10.0-beta.108) (2025-02-25)
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
# [3.10.0-beta.107](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.106...v3.10.0-beta.107) (2025-02-25)
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
# [3.10.0-beta.106](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.105...v3.10.0-beta.106) (2025-02-25)
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
# [3.10.0-beta.105](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.104...v3.10.0-beta.105) (2025-02-25)
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
# [3.10.0-beta.104](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.103...v3.10.0-beta.104) (2025-02-25)
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
# [3.10.0-beta.103](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.102...v3.10.0-beta.103) (2025-02-23)
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
# [3.10.0-beta.102](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.101...v3.10.0-beta.102) (2025-02-20)
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
# [3.10.0-beta.101](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.100...v3.10.0-beta.101) (2025-02-20)
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
# [3.10.0-beta.100](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.99...v3.10.0-beta.100) (2025-02-19)
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
# [3.10.0-beta.99](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.98...v3.10.0-beta.99) (2025-02-18)
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
# [3.10.0-beta.98](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.97...v3.10.0-beta.98) (2025-02-18)
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
# [3.10.0-beta.97](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.96...v3.10.0-beta.97) (2025-02-18)
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
# [3.10.0-beta.96](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.95...v3.10.0-beta.96) (2025-02-18)
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
# [3.10.0-beta.95](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.94...v3.10.0-beta.95) (2025-02-13)
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
# [3.10.0-beta.94](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.93...v3.10.0-beta.94) (2025-02-11)
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
# [3.10.0-beta.93](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.92...v3.10.0-beta.93) (2025-02-04)
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
# [3.10.0-beta.92](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.91...v3.10.0-beta.92) (2025-02-04)
### Bug Fixes
* **core:** Address 3D reconstruction and Android compatibility issues and clean up 4D data mode ([#4762](https://github.com/OHIF/Viewers/issues/4762)) ([149d6d0](https://github.com/OHIF/Viewers/commit/149d6d049cd333b9e5846576b403ff387558a66f))
# [3.10.0-beta.91](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.90...v3.10.0-beta.91) (2025-02-04)
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
# [3.10.0-beta.90](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.89...v3.10.0-beta.90) (2025-02-04)
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
# [3.10.0-beta.89](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.88...v3.10.0-beta.89) (2025-02-04)
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
# [3.10.0-beta.88](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.87...v3.10.0-beta.88) (2025-02-04)
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
# [3.10.0-beta.87](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.86...v3.10.0-beta.87) (2025-02-03)
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
# [3.10.0-beta.86](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.85...v3.10.0-beta.86) (2025-02-03)
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
# [3.10.0-beta.85](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.84...v3.10.0-beta.85) (2025-02-03)
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
# [3.10.0-beta.84](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.83...v3.10.0-beta.84) (2025-01-31)
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
# [3.10.0-beta.83](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.82...v3.10.0-beta.83) (2025-01-31)
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
# [3.10.0-beta.82](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.81...v3.10.0-beta.82) (2025-01-31)
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
# [3.10.0-beta.81](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.80...v3.10.0-beta.81) (2025-01-29)
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
# [3.10.0-beta.80](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.79...v3.10.0-beta.80) (2025-01-29)
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
# [3.10.0-beta.79](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.78...v3.10.0-beta.79) (2025-01-28)
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
# [3.10.0-beta.78](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.77...v3.10.0-beta.78) (2025-01-28)
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
# [3.10.0-beta.77](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.76...v3.10.0-beta.77) (2025-01-28)
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
@@ -1,6 +1,6 @@
{
"name": "@ohif/extension-cornerstone-dynamic-volume",
"version": "3.10.0-beta.77",
"version": "3.10.0-beta.112",
"description": "OHIF extension for 4D volumes data",
"author": "OHIF",
"license": "MIT",
@@ -29,11 +29,11 @@
"test:unit:ci": "jest --ci --runInBand --collectCoverage --passWithNoTests"
},
"peerDependencies": {
"@ohif/core": "3.10.0-beta.77",
"@ohif/extension-cornerstone": "3.10.0-beta.77",
"@ohif/extension-default": "3.10.0-beta.77",
"@ohif/i18n": "3.10.0-beta.77",
"@ohif/ui": "3.10.0-beta.77",
"@ohif/core": "3.10.0-beta.112",
"@ohif/extension-cornerstone": "3.10.0-beta.112",
"@ohif/extension-default": "3.10.0-beta.112",
"@ohif/i18n": "3.10.0-beta.112",
"@ohif/ui": "3.10.0-beta.112",
"dcmjs": "*",
"dicom-parser": "^1.8.21",
"hammerjs": "^2.0.8",
@@ -42,8 +42,8 @@
},
"dependencies": {
"@babel/runtime": "^7.20.13",
"@cornerstonejs/core": "^2.17.2",
"@cornerstonejs/tools": "^2.17.2",
"@cornerstonejs/core": "^2.19.14",
"@cornerstonejs/tools": "^2.19.14",
"classnames": "^2.3.2"
}
}
@@ -1,6 +1,6 @@
import React, { useState } from 'react';
import { Button, PanelSection, ButtonGroup, IconButton, InputNumber } from '@ohif/ui';
import { DoubleSlider, Icons, Tooltip, TooltipTrigger, TooltipContent } from '@ohif/ui-next';
import { Icons, Tooltip, TooltipTrigger, TooltipContent, Numeric } from '@ohif/ui-next';
import { Enums } from '@cornerstonejs/core';
const controlClassNames = {
@@ -20,7 +20,10 @@ const Header = ({ title, tooltip }) => (
/>
</span>
</TooltipTrigger>
<TooltipContent sideOffset={4} className="max-w-xs p-2 bg-primary-dark text-white">
<TooltipContent
sideOffset={4}
className="bg-primary-dark max-w-xs p-2 text-white"
>
<div>{tooltip}</div>
</TooltipContent>
</Tooltip>
@@ -37,23 +40,16 @@ const DynamicVolumeControls = ({
minFps,
maxFps,
// Frames
currentFrameIndex,
onFrameChange,
framesLength,
currentDimensionGroupNumber,
onDimensionGroupChange,
numDimensionGroups,
onGenerate,
onDoubleRangeChange,
rangeValues,
onDynamicClick,
}) => {
const [computedView, setComputedView] = useState(false);
const [computeViewMode, setComputeViewMode] = useState(Enums.DynamicOperatorType.SUM);
const [sliderRangeValues, setSliderRangeValues] = useState([0, framesLength - 1]);
const handleSliderChange = newValues => {
onDoubleRangeChange(newValues);
setSliderRangeValues(newValues);
};
const formatLabel = value => Math.round(value);
return (
<div className="flex select-none flex-col">
@@ -89,7 +85,7 @@ const DynamicVolumeControls = ({
</ButtonGroup>
</div>
<div>
<FrameControls
<DimensionGroupControls
onPlayPauseChange={onPlayPauseChange}
isPlaying={isPlaying}
computedView={computedView}
@@ -99,9 +95,9 @@ const DynamicVolumeControls = ({
minFps={minFps}
maxFps={maxFps}
//
framesLength={framesLength}
onFrameChange={onFrameChange}
currentFrameIndex={currentFrameIndex}
numDimensionGroups={numDimensionGroups}
onDimensionGroupChange={onDimensionGroupChange}
currentDimensionGroupNumber={currentDimensionGroupNumber}
/>
</div>
<div className={`mt-6 flex flex-col ${computedView ? '' : 'ohif-disabled'}`}>
@@ -111,9 +107,10 @@ const DynamicVolumeControls = ({
<div>
Operation Buttons (SUM, AVERAGE, SUBTRACT): Select the mathematical operation to be
applied to the data set.
<br /> Range Slider: Choose the numeric range within which the operation will be
performed.
<br />Generate Button: Execute the chosen operation on the specified range of data.
<br /> Range Slider: Choose the numeric range of dimension groups within which the
operation will be performed.
<br />
Generate Button: Execute the chosen operation on the specified range of data.
</div>
}
/>
@@ -141,15 +138,15 @@ const DynamicVolumeControls = ({
</button>
</ButtonGroup>
<div className="mt-2 w-full">
<DoubleSlider
min={0}
max={framesLength - 1}
step={1}
defaultValue={sliderRangeValues}
onValueChange={handleSliderChange}
formatLabel={formatLabel}
className="w-full"
/>
<Numeric.Container
mode="doubleRange"
min={1}
max={numDimensionGroups}
values={rangeValues}
onChange={onDoubleRangeChange}
>
<Numeric.DoubleRange showNumberInputs />
</Numeric.Container>
</div>
<Button
className="mt-2 !h-[26px] !w-[115px] self-start !p-0"
@@ -167,16 +164,16 @@ const DynamicVolumeControls = ({
export default DynamicVolumeControls;
function FrameControls({
function DimensionGroupControls({
isPlaying,
onPlayPauseChange,
fps,
minFps,
maxFps,
onFpsChange,
framesLength,
onFrameChange,
currentFrameIndex,
numDimensionGroups,
onDimensionGroupChange,
currentDimensionGroupNumber,
computedView,
}) {
const getPlayPauseIconName = () => (isPlaying ? 'icon-pause' : 'icon-play');
@@ -187,14 +184,16 @@ function FrameControls({
title="4D Controls"
tooltip={
<div>
Play/Pause Button: Begin or pause the animation of the 4D visualization. <br /> Frame
Selector: Navigate through individual frames of the 4D data. <br /> FPS (Frames Per
Second) Selector: Adjust the playback speed of the animation.
Play/Pause Button: Begin or pause the animation of the 4D visualization. <br />
Dimension Group Selector: Navigate through individual dimension groups of the 4D data.{' '}
<br />
FPS (Frames Per Second) Selector: Adjust the playback speed of the animation.
</div>
}
/>
<div className="mt-3 flex justify-between">
<IconButton
id="play-pause-button"
className="bg-customblue-30 h-[26px] w-[58px] rounded-[4px]"
onClick={() => onPlayPauseChange(!isPlaying)}
>
@@ -204,11 +203,11 @@ function FrameControls({
/>
</IconButton>
<InputNumber
value={currentFrameIndex}
onChange={onFrameChange}
minValue={0}
maxValue={framesLength - 1}
label="Frame"
value={currentDimensionGroupNumber}
onChange={onDimensionGroupChange}
minValue={1}
maxValue={numDimensionGroups}
label="Group"
{...controlClassNames}
/>
<InputNumber
@@ -222,4 +221,4 @@ function FrameControls({
</div>
</div>
);
}
}
@@ -15,13 +15,12 @@ export default function PanelGenerateImage({ servicesManager, commandsManager }:
const [{ activeViewportId }] = useViewportGrid();
//
const [timePointsRange, setTimePointsRange] = useState([0, 0]);
const [timePointsRangeToUseForGenerate, setTimePointsRangeToUseForGenerate] = useState([0, 0]);
const [dimensionGroupRange, setDimensionGroupRange] = useState([1, 1]);
const [computedDisplaySet, setComputedDisplaySet] = useState(null);
const [dynamicVolume, setDynamicVolume] = useState(null);
const [frameRate, setFrameRate] = useState(20);
const [isPlaying, setIsPlaying] = useState(isCineEnabled);
const [timePointRendered, setTimePointRendered] = useState(null);
const [dimensionGroupNumberRendered, setDimensionGroupNumberRendered] = useState(null);
const [displayingComputed, setDisplayingComputed] = useState(false);
//
@@ -38,9 +37,8 @@ export default function PanelGenerateImage({ servicesManager, commandsManager }:
if (volumeData.volume?.isDynamicVolume()) {
setDynamicVolume(volumeData.volume);
uuidDynamicVolume.current = volumeData.displaySetInstanceUID;
const newRange = [1, volumeData.volume.numTimePoints];
setTimePointsRange(newRange);
setTimePointsRangeToUseForGenerate(newRange);
const newRange = [1, volumeData.volume.numDimensionGroups];
setDimensionGroupRange(newRange);
}
});
};
@@ -65,10 +63,10 @@ export default function PanelGenerateImage({ servicesManager, commandsManager }:
}, [cornerstoneViewportService, cineService, servicesManager.services.cineService]);
useEffect(() => {
const evt = Enums.Events.DYNAMIC_VOLUME_TIME_POINT_INDEX_CHANGED;
const evt = Enums.Events.DYNAMIC_VOLUME_DIMENSION_GROUP_CHANGED;
const callback = evt => {
setTimePointRendered(evt.detail.timePointIndex);
setDimensionGroupNumberRendered(evt.detail.dimensionGroupNumber);
};
eventTarget.addEventListener(evt, callback);
@@ -76,7 +74,7 @@ export default function PanelGenerateImage({ servicesManager, commandsManager }:
return () => {
eventTarget.removeEventListener(evt, callback);
};
}, [cornerstoneViewportService]);
}, []);
useEffect(() => {
const displaySetUIDs = viewportGridService.getDisplaySetsUIDsForViewport(activeViewportId);
@@ -102,9 +100,7 @@ export default function PanelGenerateImage({ servicesManager, commandsManager }:
setDynamicVolume(dynamicVolume);
uuidDynamicVolume.current = dynamicVolumeDisplaySet.displaySetInstanceUID;
const newRange = [1, dynamicVolume.numTimePoints];
setTimePointsRange(newRange);
setTimePointsRangeToUseForGenerate(newRange);
setDimensionGroupRange([1, dynamicVolume.numDimensionGroups]);
}, [
activeViewportId,
viewportGridService,
@@ -141,11 +137,12 @@ export default function PanelGenerateImage({ servicesManager, commandsManager }:
volumeId: computedVolumeId,
});
}
const [start, end] = timePointsRangeToUseForGenerate;
const frameNumbers = Array.from({ length: end - start + 1 }, (_, i) => i + start - 1);
const [start, end] = dimensionGroupRange;
// from start to end, with steps of 1
const frameNumbers = Array.from({ length: end - start + 1 }, (_, i) => start + i);
const options = {
frameNumbers: operationName === 'SUBTRACT' ? [start, end - 1] : frameNumbers,
dimensionGroupNumbers: operationName === 'SUBTRACT' ? [start, end] : frameNumbers,
targetVolume: computedVolume,
};
@@ -207,17 +204,6 @@ export default function PanelGenerateImage({ servicesManager, commandsManager }:
handlePlay();
};
function handleSliderChange(newValues) {
if (
newValues[0] === timePointsRangeToUseForGenerate[0] &&
newValues[1] === timePointsRangeToUseForGenerate[1]
) {
return;
}
setTimePointsRangeToUseForGenerate(newValues);
}
return (
<DynamicVolumeControls
fps={frameRate}
@@ -225,16 +211,16 @@ export default function PanelGenerateImage({ servicesManager, commandsManager }:
onPlayPauseChange={onPlayPauseChange}
minFps={1}
maxFps={50}
currentFrameIndex={timePointRendered}
onFpsChange={handleSetFrameRate}
framesLength={timePointsRange[1]}
onFrameChange={timePointIndex => {
dynamicVolume.timePointIndex = timePointIndex;
currentDimensionGroupNumber={dimensionGroupNumberRendered}
numDimensionGroups={dynamicVolume?.numDimensionGroups || 1}
onDimensionGroupChange={dimensionGroupNumber => {
dynamicVolume.dimensionGroupNumber = dimensionGroupNumber;
}}
onGenerate={onGenerateImage}
onDynamicClick={displayingComputed ? () => renderDynamicImage(computedDisplaySet) : null}
onDoubleRangeChange={handleSliderChange}
initialRangeValues={timePointsRangeToUseForGenerate}
onDoubleRangeChange={setDimensionGroupRange}
rangeValues={dimensionGroupRange}
/>
);
}
+317
View File
@@ -3,6 +3,323 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
# [3.10.0-beta.112](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.111...v3.10.0-beta.112) (2025-02-28)
### Features
* separate checks for addWindowLevelActionMenu and addSegmentationOverlay ([#4813](https://github.com/OHIF/Viewers/issues/4813)) ([7f0cc0f](https://github.com/OHIF/Viewers/commit/7f0cc0f60e74a2e0ac2aea1fe6a786582b495c4e))
# [3.10.0-beta.111](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.110...v3.10.0-beta.111) (2025-02-26)
**Note:** Version bump only for package @ohif/extension-cornerstone
# [3.10.0-beta.110](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.109...v3.10.0-beta.110) (2025-02-26)
### Bug Fixes
* **sr:** sr hydration and load was not working, Screenshot Comparison, and Testing ([#4814](https://github.com/OHIF/Viewers/issues/4814)) ([9233143](https://github.com/OHIF/Viewers/commit/9233143b9da5850080365e1526e24b44e9910075))
# [3.10.0-beta.109](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.108...v3.10.0-beta.109) (2025-02-25)
**Note:** Version bump only for package @ohif/extension-cornerstone
# [3.10.0-beta.108](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.107...v3.10.0-beta.108) (2025-02-25)
**Note:** Version bump only for package @ohif/extension-cornerstone
# [3.10.0-beta.107](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.106...v3.10.0-beta.107) (2025-02-25)
**Note:** Version bump only for package @ohif/extension-cornerstone
# [3.10.0-beta.106](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.105...v3.10.0-beta.106) (2025-02-25)
### Features
* **hotkeys:** Migrate hotkeys to customization service and fix issues with overrides ([#4777](https://github.com/OHIF/Viewers/issues/4777)) ([3e6913b](https://github.com/OHIF/Viewers/commit/3e6913b097569280a5cc2fa5bbe4add52f149305))
# [3.10.0-beta.105](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.104...v3.10.0-beta.105) (2025-02-25)
### Bug Fixes
* Changes to address hang/crash on jump to instance ([#4679](https://github.com/OHIF/Viewers/issues/4679)) ([e480e84](https://github.com/OHIF/Viewers/commit/e480e841bb5da5281a7c4624a60d5964d690ebb8))
* **rt:** jump to segment discards the configured width ([#4799](https://github.com/OHIF/Viewers/issues/4799)) ([afd528b](https://github.com/OHIF/Viewers/commit/afd528b8d72c3d8360b54bb52604758e83ada863))
# [3.10.0-beta.104](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.103...v3.10.0-beta.104) (2025-02-25)
**Note:** Version bump only for package @ohif/extension-cornerstone
# [3.10.0-beta.103](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.102...v3.10.0-beta.103) (2025-02-23)
**Note:** Version bump only for package @ohif/extension-cornerstone
# [3.10.0-beta.102](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.101...v3.10.0-beta.102) (2025-02-20)
**Note:** Version bump only for package @ohif/extension-cornerstone
# [3.10.0-beta.101](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.100...v3.10.0-beta.101) (2025-02-20)
**Note:** Version bump only for package @ohif/extension-cornerstone
# [3.10.0-beta.100](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.99...v3.10.0-beta.100) (2025-02-19)
**Note:** Version bump only for package @ohif/extension-cornerstone
# [3.10.0-beta.99](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.98...v3.10.0-beta.99) (2025-02-18)
### Bug Fixes
* cache thumbnail in display set ([#4782](https://github.com/OHIF/Viewers/issues/4782)) ([2410c6a](https://github.com/OHIF/Viewers/commit/2410c6a50904c1235993900e837876cc26af019b))
# [3.10.0-beta.98](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.97...v3.10.0-beta.98) (2025-02-18)
### Bug Fixes
* lodash dependencies ([#4791](https://github.com/OHIF/Viewers/issues/4791)) ([4e16099](https://github.com/OHIF/Viewers/commit/4e16099ad3ab777b09f6ac8f181025cfd656ab6b))
# [3.10.0-beta.97](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.96...v3.10.0-beta.97) (2025-02-18)
**Note:** Version bump only for package @ohif/extension-cornerstone
# [3.10.0-beta.96](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.95...v3.10.0-beta.96) (2025-02-18)
**Note:** Version bump only for package @ohif/extension-cornerstone
# [3.10.0-beta.95](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.94...v3.10.0-beta.95) (2025-02-13)
**Note:** Version bump only for package @ohif/extension-cornerstone
# [3.10.0-beta.94](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.93...v3.10.0-beta.94) (2025-02-11)
**Note:** Version bump only for package @ohif/extension-cornerstone
# [3.10.0-beta.93](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.92...v3.10.0-beta.93) (2025-02-04)
**Note:** Version bump only for package @ohif/extension-cornerstone
# [3.10.0-beta.92](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.91...v3.10.0-beta.92) (2025-02-04)
### Bug Fixes
* **core:** Address 3D reconstruction and Android compatibility issues and clean up 4D data mode ([#4762](https://github.com/OHIF/Viewers/issues/4762)) ([149d6d0](https://github.com/OHIF/Viewers/commit/149d6d049cd333b9e5846576b403ff387558a66f))
# [3.10.0-beta.91](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.90...v3.10.0-beta.91) (2025-02-04)
### Bug Fixes
* changing colormap for second volume in fusion viewport ([#4746](https://github.com/OHIF/Viewers/issues/4746)) ([8996df8](https://github.com/OHIF/Viewers/commit/8996df80e45c97ad5847ebbd19291cd772a2163d))
# [3.10.0-beta.90](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.89...v3.10.0-beta.90) (2025-02-04)
**Note:** Version bump only for package @ohif/extension-cornerstone
# [3.10.0-beta.89](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.88...v3.10.0-beta.89) (2025-02-04)
### Features
* **ui:** customization option for viewport notification ([#4638](https://github.com/OHIF/Viewers/issues/4638)) ([8acbd76](https://github.com/OHIF/Viewers/commit/8acbd760d801dcaf624c5d9fb636a029201b91e1))
# [3.10.0-beta.88](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.87...v3.10.0-beta.88) (2025-02-04)
**Note:** Version bump only for package @ohif/extension-cornerstone
# [3.10.0-beta.87](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.86...v3.10.0-beta.87) (2025-02-03)
**Note:** Version bump only for package @ohif/extension-cornerstone
# [3.10.0-beta.86](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.85...v3.10.0-beta.86) (2025-02-03)
### Bug Fixes
* **store-segmentation:** storing segmentations was hitting the wrong command resulting in an undefined datasource ([#4755](https://github.com/OHIF/Viewers/issues/4755)) ([9b8e5cf](https://github.com/OHIF/Viewers/commit/9b8e5cfd1a6121a58991c0f75660a2fd9913a4e7))
# [3.10.0-beta.85](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.84...v3.10.0-beta.85) (2025-02-03)
### Features
* Add customization support for more UI components ([#4634](https://github.com/OHIF/Viewers/issues/4634)) ([f15eb44](https://github.com/OHIF/Viewers/commit/f15eb44b4cf49de1b73a22512571cec02effaef3))
# [3.10.0-beta.84](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.83...v3.10.0-beta.84) (2025-01-31)
**Note:** Version bump only for package @ohif/extension-cornerstone
# [3.10.0-beta.83](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.82...v3.10.0-beta.83) (2025-01-31)
### Bug Fixes
* publish dependency ([#4753](https://github.com/OHIF/Viewers/issues/4753)) ([0cb6106](https://github.com/OHIF/Viewers/commit/0cb6106d0fa576348ca3324685d5768b6ec80572))
# [3.10.0-beta.82](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.81...v3.10.0-beta.82) (2025-01-31)
**Note:** Version bump only for package @ohif/extension-cornerstone
# [3.10.0-beta.81](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.80...v3.10.0-beta.81) (2025-01-29)
**Note:** Version bump only for package @ohif/extension-cornerstone
# [3.10.0-beta.80](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.79...v3.10.0-beta.80) (2025-01-29)
**Note:** Version bump only for package @ohif/extension-cornerstone
# [3.10.0-beta.79](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.78...v3.10.0-beta.79) (2025-01-28)
**Note:** Version bump only for package @ohif/extension-cornerstone
# [3.10.0-beta.78](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.77...v3.10.0-beta.78) (2025-01-28)
**Note:** Version bump only for package @ohif/extension-cornerstone
# [3.10.0-beta.77](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.76...v3.10.0-beta.77) (2025-01-28)
+11 -11
View File
@@ -1,6 +1,6 @@
{
"name": "@ohif/extension-cornerstone",
"version": "3.10.0-beta.77",
"version": "3.10.0-beta.112",
"description": "OHIF extension for Cornerstone",
"author": "OHIF",
"license": "MIT",
@@ -38,10 +38,9 @@
"@cornerstonejs/codec-libjpeg-turbo-8bit": "^1.2.2",
"@cornerstonejs/codec-openjpeg": "^1.2.4",
"@cornerstonejs/codec-openjph": "^2.4.5",
"@cornerstonejs/dicom-image-loader": "^2.17.2",
"@icr/polyseg-wasm": "^0.4.0",
"@ohif/core": "3.10.0-beta.77",
"@ohif/ui": "3.10.0-beta.77",
"@cornerstonejs/dicom-image-loader": "^2.19.14",
"@ohif/core": "3.10.0-beta.112",
"@ohif/ui": "3.10.0-beta.112",
"dcmjs": "*",
"dicom-parser": "^1.8.21",
"hammerjs": "^2.0.8",
@@ -50,19 +49,20 @@
"react-dom": "^18.3.1",
"react-resize-detector": "^10.0.1"
},
"devDependencies": {
"lodash": "^4.17.21"
},
"dependencies": {
"@babel/runtime": "^7.20.13",
"@cornerstonejs/adapters": "^2.17.2",
"@cornerstonejs/core": "^2.17.2",
"@cornerstonejs/tools": "^2.17.2",
"@cornerstonejs/adapters": "^2.19.14",
"@cornerstonejs/core": "^2.19.14",
"@cornerstonejs/tools": "^2.19.14",
"@icr/polyseg-wasm": "^0.4.0",
"@itk-wasm/morphological-contour-interpolation": "1.1.0",
"@kitware/vtk.js": "32.1.1",
"html2canvas": "^1.4.1",
"lodash.compact": "^3.0.1",
"lodash.debounce": "^4.0.8",
"lodash.flatten": "^4.4.0",
"lodash.merge": "^4.6.2",
"lodash.zip": "^4.2.0",
"shader-loader": "^1.3.1",
"worker-loader": "^3.0.8"
}
@@ -3,7 +3,7 @@ import { useResizeDetector } from 'react-resize-detector';
import * as cs3DTools from '@cornerstonejs/tools';
import { Enums, eventTarget, getEnabledElement } from '@cornerstonejs/core';
import { MeasurementService } from '@ohif/core';
import { AllInOneMenu, Notification, useViewportDialog } from '@ohif/ui';
import { AllInOneMenu, useViewportDialog } from '@ohif/ui';
import type { Types as csTypes } from '@cornerstonejs/core';
import { setEnabledElement } from '../state';
@@ -15,11 +15,11 @@ import type { Types } from '@ohif/core';
import OHIFViewportActionCorners from '../components/OHIFViewportActionCorners';
import { getWindowLevelActionMenu } from '../components/WindowLevelActionMenu/getWindowLevelActionMenu';
import { useAppConfig } from '@state';
import { getViewportDataOverlaySettingsMenu } from '../components/ViewportDataOverlaySettingMenu';
import { getViewportPresentations } from '../utils/presentations/getViewportPresentations';
import { useSynchronizersStore } from '../stores/useSynchronizersStore';
import ActiveViewportBehavior from '../utils/ActiveViewportBehavior';
import { WITH_NAVIGATION } from '../services/ViewportService/CornerstoneViewportService';
const STACK = 'stack';
@@ -88,7 +88,6 @@ const OHIFCornerstoneViewport = React.memo(
const [scrollbarHeight, setScrollbarHeight] = useState('100px');
const [enabledVPElement, setEnabledVPElement] = useState(null);
const elementRef = useRef() as React.MutableRefObject<HTMLDivElement>;
const [appConfig] = useAppConfig();
const {
displaySetService,
@@ -99,6 +98,7 @@ const OHIFCornerstoneViewport = React.memo(
segmentationService,
cornerstoneCacheService,
viewportActionCornersService,
customizationService,
} = servicesManager.services;
const [viewportDialogState] = useViewportDialog();
@@ -322,57 +322,60 @@ const OHIFCornerstoneViewport = React.memo(
// Set up the window level action menu in the viewport action corners.
useEffect(() => {
// Doing an === check here because the default config value when not set is true
if (appConfig.addWindowLevelActionMenu === false) {
return;
const windowLevelActionMenu = customizationService.getCustomization(
'viewportActionMenu.windowLevelActionMenu'
);
const segmentationOverlay = customizationService.getCustomization(
'viewportActionMenu.segmentationOverlay'
);
if (windowLevelActionMenu?.enabled) {
viewportActionCornersService.addComponent({
viewportId,
id: 'windowLevelActionMenu',
component: getWindowLevelActionMenu({
viewportId,
element: elementRef.current,
displaySets,
servicesManager,
commandsManager,
location: windowLevelActionMenu.location,
verticalDirection: AllInOneMenu.VerticalDirection.TopToBottom,
horizontalDirection: AllInOneMenu.HorizontalDirection.RightToLeft,
}),
location: windowLevelActionMenu.location,
});
}
const location = viewportActionCornersService.LOCATIONS.topRight;
// TODO: In the future we should consider using the customization service
// to determine if and in which corner various action components should go.
viewportActionCornersService.addComponent({
viewportId,
id: 'windowLevelActionMenu',
component: getWindowLevelActionMenu({
if (segmentationOverlay?.enabled) {
viewportActionCornersService.addComponent({
viewportId,
element: elementRef.current,
displaySets,
servicesManager,
commandsManager,
location,
verticalDirection: AllInOneMenu.VerticalDirection.TopToBottom,
horizontalDirection: AllInOneMenu.HorizontalDirection.RightToLeft,
}),
location,
});
viewportActionCornersService.addComponent({
viewportId,
id: 'segmentation',
component: getViewportDataOverlaySettingsMenu({
viewportId,
element: elementRef.current,
displaySets,
servicesManager,
commandsManager,
location,
}),
location,
});
id: 'segmentation',
component: getViewportDataOverlaySettingsMenu({
viewportId,
element: elementRef.current,
displaySets,
servicesManager,
commandsManager,
location: segmentationOverlay.location,
}),
location: segmentationOverlay.location,
});
}
}, [
displaySets,
viewportId,
viewportActionCornersService,
servicesManager,
commandsManager,
appConfig,
]);
const { ref: resizeRef } = useResizeDetector({
onResize,
});
const Notification = customizationService.getCustomization('ui.notificationComponent');
return (
<React.Fragment>
<div className="viewport-wrapper">
@@ -502,12 +505,16 @@ function _jumpToMeasurement(measurement, targetElementRef, viewportId, servicesM
const viewport = enabledElement.viewport as csTypes.IStackViewport | csTypes.IVolumeViewport;
const { metadata } = measurement;
if (!viewport.isReferenceViewable(metadata, { withNavigation: true, withOrientation: true })) {
if (!viewport.isReferenceViewable(metadata, WITH_NAVIGATION)) {
console.log("Reference isn't viewable, postponing until updated");
return;
}
viewport.setViewReference(metadata);
try {
viewport.setViewReference(metadata);
} catch (e) {
console.warn('Unable to apply', metadata, e);
}
cs3DTools.annotation.selection.setAnnotationSelected(measurement.uid);
// Jump to measurement consumed, remove.
+74 -25
View File
@@ -25,7 +25,6 @@ import {
colorPickerDialog,
} from '@ohif/extension-default';
import { vec3, mat4 } from 'gl-matrix';
import CornerstoneViewportDownloadForm from './utils/CornerstoneViewportDownloadForm';
import toggleImageSliceSync from './utils/imageSliceSync/toggleImageSliceSync';
import { getFirstAnnotationSelected } from './utils/measurementServiceMappings/utils/selection';
@@ -34,6 +33,7 @@ import toggleVOISliceSync from './utils/toggleVOISliceSync';
import { usePositionPresentationStore, useSegmentationPresentationStore } from './stores';
import { toolNames } from './initCornerstoneTools';
const { DefaultHistoryMemo } = csUtils.HistoryMemo;
const toggleSyncFunctions = {
imageSlice: toggleImageSliceSync,
voi: toggleVOISliceSync,
@@ -140,19 +140,16 @@ function commandsModule({
)?.[0];
if (previousReferencedDisplaySetStoreKey) {
if (referencedImageId) {
setPositionPresentation(previousReferencedDisplaySetStoreKey, {
viewReference: {
referencedImageId,
},
});
} else {
setPositionPresentation(
previousReferencedDisplaySetStoreKey,
presentations.positionPresentation
);
}
const presentationData = referencedImageId
? {
...presentations.positionPresentation,
viewReference: {
referencedImageId,
},
}
: presentations.positionPresentation;
setPositionPresentation(previousReferencedDisplaySetStoreKey, presentationData);
return;
}
@@ -208,8 +205,9 @@ function commandsModule({
*/
setMeasurementLabel: ({ uid }) => {
const labelConfig = customizationService.getCustomization('measurementLabels');
const renderContent = customizationService.getCustomization('ui.labellingComponent');
const measurement = measurementService.getMeasurement(uid);
showLabelAnnotationPopup(measurement, uiDialogService, labelConfig).then(
showLabelAnnotationPopup(measurement, uiDialogService, labelConfig, renderContent).then(
(val: Map<any, any>) => {
measurementService.update(
uid,
@@ -325,16 +323,19 @@ function commandsModule({
renameMeasurement: ({ uid }) => {
const labelConfig = customizationService.getCustomization('measurementLabels');
const renderContent = customizationService.getCustomization('ui.labellingComponent');
const measurement = measurementService.getMeasurement(uid);
showLabelAnnotationPopup(measurement, uiDialogService, labelConfig).then(val => {
measurementService.update(
uid,
{
...val,
},
true
);
});
showLabelAnnotationPopup(measurement, uiDialogService, labelConfig, renderContent).then(
val => {
measurementService.update(
uid,
{
...val,
},
true
);
}
);
},
toggleLockMeasurement: ({ uid }) => {
@@ -376,7 +377,8 @@ function commandsModule({
},
arrowTextCallback: ({ callback, data, uid }) => {
const labelConfig = customizationService.getCustomization('measurementLabels');
callLabelAutocompleteDialog(uiDialogService, callback, {}, labelConfig);
const renderContent = customizationService.getCustomization('ui.labellingComponent');
callLabelAutocompleteDialog(uiDialogService, callback, {}, labelConfig, renderContent);
},
toggleCine: () => {
const { viewports } = viewportGridService.getState();
@@ -425,6 +427,37 @@ function commandsModule({
actions.setViewportWindowLevel({ ...props, viewportId });
},
setWindowLevelPreset: ({ presetName, presetIndex }) => {
const windowLevelPresets = customizationService.getCustomization(
'cornerstone.windowLevelPresets'
);
const activeViewport = viewportGridService.getActiveViewportId();
const viewport = cornerstoneViewportService.getCornerstoneViewport(activeViewport);
const metadata = viewport.getImageData().metadata;
const modality = metadata.Modality;
if (!modality) {
return;
}
const windowLevelPresetForModality = windowLevelPresets[modality];
if (!windowLevelPresetForModality) {
return;
}
const windowLevelPreset =
windowLevelPresetForModality[presetName] ??
Object.values(windowLevelPresetForModality)[presetIndex];
actions.setViewportWindowLevel({
viewportId: activeViewport,
window: windowLevelPreset.window,
level: windowLevelPreset.level,
});
},
setToolEnabled: ({ toolName, toggle, toolGroupId }) => {
const { viewports } = viewportGridService.getState();
@@ -751,7 +784,12 @@ function commandsModule({
displaySetInstanceUID = viewports.get(viewportId)?.displaySetInstanceUIDs[0];
}
const volumeId = viewport.getVolumeId();
// ToDo: Find a better way of obtaining the volumeId that corresponds to the displaySetInstanceUID
const volumeId =
viewport
.getAllVolumeIds()
.find((_volumeId: string) => _volumeId.includes(displaySetInstanceUID)) ??
viewport.getVolumeId();
viewport.setProperties({ colormap }, volumeId);
}
@@ -1317,6 +1355,12 @@ function commandsModule({
measurementService.remove(activeAnnotationUID);
});
},
undo: () => {
DefaultHistoryMemo.undo();
},
redo: () => {
DefaultHistoryMemo.redo();
},
};
const definitions = {
@@ -1381,6 +1425,9 @@ function commandsModule({
setWindowLevel: {
commandFn: actions.setWindowLevel,
},
setWindowLevelPreset: {
commandFn: actions.setWindowLevelPreset,
},
setToolActive: {
commandFn: actions.setToolActive,
},
@@ -1580,6 +1627,8 @@ function commandsModule({
deleteActiveAnnotation: {
commandFn: actions.deleteActiveAnnotation,
},
undo: actions.undo,
redo: actions.redo,
};
return {
@@ -53,13 +53,13 @@ function WrappedCinePlayer({
// check if the displaySet is dynamic and set the dynamic info
if (displaySet.isDynamicVolume) {
const { dynamicVolumeInfo } = displaySet;
const numTimePoints = dynamicVolumeInfo.timePoints.length;
const numDimensionGroups = dynamicVolumeInfo.timePoints.length;
const label = dynamicVolumeInfo.splittingTag;
const timePointIndex = dynamicVolumeInfo.timePointIndex || 0;
const dimensionGroupNumber = dynamicVolumeInfo.dimensionGroupNumber || 1;
setDynamicInfo({
volumeId: displaySet.displaySetInstanceUID,
timePointIndex,
numTimePoints,
dimensionGroupNumber,
numDimensionGroups,
label,
});
} else {
@@ -176,20 +176,20 @@ function RenderCinePlayer({
return;
}
const handleTimePointIndexChange = evt => {
const { volumeId, timePointIndex, numTimePoints, splittingTag } = evt.detail;
setDynamicInfo({ volumeId, timePointIndex, numTimePoints, label: splittingTag });
const handleDimensionGroupChange = evt => {
const { volumeId, dimensionGroupNumber, numDimensionGroups, splittingTag } = evt.detail;
setDynamicInfo({ volumeId, dimensionGroupNumber, numDimensionGroups, label: splittingTag });
};
eventTarget.addEventListener(
Enums.Events.DYNAMIC_VOLUME_TIME_POINT_INDEX_CHANGED,
handleTimePointIndexChange
Enums.Events.DYNAMIC_VOLUME_DIMENSION_GROUP_CHANGED,
handleDimensionGroupChange
);
return () => {
eventTarget.removeEventListener(
Enums.Events.DYNAMIC_VOLUME_TIME_POINT_INDEX_CHANGED,
handleTimePointIndexChange
Enums.Events.DYNAMIC_VOLUME_DIMENSION_GROUP_CHANGED,
handleDimensionGroupChange
);
};
}, [dynamicInfo]);
@@ -199,17 +199,17 @@ function RenderCinePlayer({
return;
}
const { volumeId, timePointIndex, numTimePoints, splittingTag } = dynamicInfo || {};
const { volumeId, dimensionGroupNumber, numDimensionGroups, splittingTag } = dynamicInfo || {};
const volume = cache.getVolume(volumeId, true);
volume.timePointIndex = timePointIndex;
volume.dimensionGroupNumber = dimensionGroupNumber;
setDynamicInfo({ volumeId, timePointIndex, numTimePoints, label: splittingTag });
setDynamicInfo({ volumeId, dimensionGroupNumber, numDimensionGroups, label: splittingTag });
}, []);
const updateDynamicInfo = useCallback(props => {
const { volumeId, timePointIndex } = props;
const { volumeId, dimensionGroupNumber } = props;
const volume = cache.getVolume(volumeId, true);
volume.timePointIndex = timePointIndex;
volume.dimensionGroupNumber = dimensionGroupNumber;
}, []);
return (
@@ -1,6 +1,7 @@
import React, { useCallback, useEffect, useRef, useState, ReactElement } from 'react';
import PropTypes from 'prop-types';
import { Button, ProgressLoadingBar } from '@ohif/ui';
import { useSystem } from '@ohif/core';
import { Button } from '@ohif/ui';
import { Icons } from '@ohif/ui-next';
import DicomFileUploader, {
EVENTS,
@@ -40,6 +41,11 @@ function DicomUploadProgress({
dicomFileUploaderArr,
onComplete,
}: DicomUploadProgressProps): ReactElement {
const { servicesManager } = useSystem();
const ProgressLoadingBar =
servicesManager.services.customizationService.getCustomization('ui.progressLoadingBar');
const [totalUploadSize] = useState(
dicomFileUploaderArr.reduce((acc, fileUploader) => acc + fileUploader.getFileSize(), 0)
);
@@ -1,14 +1,16 @@
import React from 'react';
import { useViewportActionCornersContext } from '../contextProviders/ViewportActionCornersProvider';
import { ViewportActionCorners } from '@ohif/ui';
import { useSystem } from '@ohif/core';
export type OHIFViewportActionCornersProps = {
viewportId: string;
};
function OHIFViewportActionCorners({ viewportId }: OHIFViewportActionCornersProps) {
const { servicesManager } = useSystem();
const [viewportActionCornersState] = useViewportActionCornersContext();
const ViewportActionCorners =
servicesManager.services.customizationService.getCustomization('ui.viewportActionCorner');
if (!viewportActionCornersState[viewportId]) {
return null;
}
@@ -0,0 +1,12 @@
import viewportActionCornersService from '../services/ViewportActionCornersService/ViewportActionCornersService';
export default {
'viewportActionMenu.windowLevelActionMenu': {
enabled: true,
location: viewportActionCornersService.LOCATIONS.topRight,
},
'viewportActionMenu.segmentationOverlay': {
enabled: true,
location: viewportActionCornersService.LOCATIONS.topRight,
},
};
@@ -9,6 +9,7 @@ import colorbarCustomization from './customizations/colorbarCustomization';
import windowLevelPresetsCustomization from './customizations/windowLevelPresetsCustomization';
import miscCustomization from './customizations/miscCustomization';
import windowLevelActionMenuCustomization from './customizations/windowLevelActionMenuCustomization';
import viewportActionMenuCustomizations from './customizations/viewportActionMenuCustomizations';
function getCustomizationModule({ commandsManager, servicesManager }) {
return [
@@ -26,6 +27,7 @@ function getCustomizationModule({ commandsManager, servicesManager }) {
...windowLevelPresetsCustomization,
...miscCustomization,
...windowLevelActionMenuCustomization,
...viewportActionMenuCustomizations,
},
},
];
@@ -1,14 +1,8 @@
import { Enums } from '@cornerstonejs/tools';
const getToggledClassName = (isToggled: boolean) => {
return isToggled
? '!text-primary-active'
: '!text-common-bright hover:!bg-primary-dark hover:text-primary-light';
};
import { utils } from '@ohif/ui-next';
const getDisabledState = (disabledText?: string) => ({
disabled: true,
className: '!text-common-bright ohif-disabled',
disabledText: disabledText ?? 'Not available on the current viewport',
});
@@ -93,9 +87,6 @@ export default function getToolbarModule({ commandsManager, servicesManager }: w
return {
disabled: false,
className: isPrimaryActive
? '!text-black bg-primary-light rounded'
: '!text-common-bright hover:!bg-primary-dark hover:!text-primary-light rounded',
// Todo: isActive right now is used for nested buttons where the primary
// button needs to be fully rounded (vs partial rounded) when active
// otherwise it does not have any other use
@@ -153,9 +144,9 @@ export default function getToolbarModule({ commandsManager, servicesManager }: w
},
{
name: 'evaluate.action',
evaluate: ({ viewportId, button }) => {
evaluate: () => {
return {
className: '!text-common-bright hover:!bg-primary-dark hover:text-primary-light',
disabled: false,
};
},
},
@@ -190,7 +181,7 @@ export default function getToolbarModule({ commandsManager, servicesManager }: w
if (!synchronizers?.length) {
return {
className: getToggledClassName(false),
className: utils.getToggledClassName(false),
};
}
@@ -204,7 +195,7 @@ export default function getToolbarModule({ commandsManager, servicesManager }: w
if (!synchronizers?.length) {
return {
className: getToggledClassName(false),
className: utils.getToggledClassName(false),
};
}
@@ -216,7 +207,7 @@ export default function getToolbarModule({ commandsManager, servicesManager }: w
const isEnabled = synchronizer?._enabled;
return {
className: getToggledClassName(isEnabled),
className: utils.getToggledClassName(isEnabled),
};
},
},
@@ -239,14 +230,13 @@ export default function getToolbarModule({ commandsManager, servicesManager }: w
if (!prop) {
return {
disabled: false,
className: '!text-common-bright hover:!bg-primary-dark hover:text-primary-light',
};
}
const isToggled = prop;
return {
className: getToggledClassName(isToggled),
className: utils.getToggledClassName(isToggled),
};
},
},
@@ -275,7 +265,7 @@ export default function getToolbarModule({ commandsManager, servicesManager }: w
return {
disabled: false,
className: getToggledClassName(isMpr),
className: utils.getToggledClassName(isMpr),
};
},
},
@@ -304,6 +294,6 @@ function _evaluateToggle({
const isOff = offModes.includes(toolGroup.getToolOptions(toolName).mode);
return {
className: getToggledClassName(!isOff),
className: utils.getToggledClassName(!isOff),
};
}
+6 -33
View File
@@ -1,3 +1,5 @@
import { HYDRATE_SEG_SYNC_GROUP, VOI_SYNC_GROUP } from './mpr';
export const fourUp = {
id: 'fourUp',
locked: true,
@@ -46,17 +48,7 @@ export const fourUp = {
initialImageOptions: {
preset: 'middle',
},
syncGroups: [
{
type: 'voi',
id: 'mpr',
source: true,
target: true,
options: {
syncColormap: true,
},
},
],
syncGroups: [VOI_SYNC_GROUP, HYDRATE_SEG_SYNC_GROUP],
},
displaySets: [
{
@@ -72,6 +64,7 @@ export const fourUp = {
customViewportProps: {
hideOverlays: true,
},
syncGroups: [VOI_SYNC_GROUP, HYDRATE_SEG_SYNC_GROUP],
},
displaySets: [
{
@@ -94,17 +87,7 @@ export const fourUp = {
initialImageOptions: {
preset: 'middle',
},
syncGroups: [
{
type: 'voi',
id: 'mpr',
source: true,
target: true,
options: {
syncColormap: true,
},
},
],
syncGroups: [VOI_SYNC_GROUP, HYDRATE_SEG_SYNC_GROUP],
},
displaySets: [
{
@@ -120,17 +103,7 @@ export const fourUp = {
initialImageOptions: {
preset: 'middle',
},
syncGroups: [
{
type: 'voi',
id: 'mpr',
source: true,
target: true,
options: {
syncColormap: true,
},
},
],
syncGroups: [VOI_SYNC_GROUP, HYDRATE_SEG_SYNC_GROUP],
},
displaySets: [
{
@@ -55,6 +55,7 @@ const frameView: Types.HangingProtocol.Protocol = {
viewports: [
{
viewportOptions: {
viewportId: 'custom_R0_C0',
toolGroupId: 'default',
syncGroups: [
{
@@ -91,6 +92,7 @@ const frameView: Types.HangingProtocol.Protocol = {
},
{
viewportOptions: {
viewportId: 'custom_R0_C1',
toolGroupId: 'default',
syncGroups: [
{
@@ -127,6 +129,7 @@ const frameView: Types.HangingProtocol.Protocol = {
},
{
viewportOptions: {
viewportId: 'custom_R0_C2',
toolGroupId: 'default',
syncGroups: [
{
@@ -163,6 +166,7 @@ const frameView: Types.HangingProtocol.Protocol = {
},
{
viewportOptions: {
viewportId: 'custom_R0_C3',
toolGroupId: 'default',
syncGroups: [
{
@@ -199,6 +203,7 @@ const frameView: Types.HangingProtocol.Protocol = {
},
{
viewportOptions: {
viewportId: 'custom_R1_C0',
toolGroupId: 'default',
syncGroups: [
{
@@ -235,6 +240,7 @@ const frameView: Types.HangingProtocol.Protocol = {
},
{
viewportOptions: {
viewportId: 'custom_R1_C1',
toolGroupId: 'default',
syncGroups: [
{
@@ -271,6 +277,7 @@ const frameView: Types.HangingProtocol.Protocol = {
},
{
viewportOptions: {
viewportId: 'custom_R1_C2',
toolGroupId: 'default',
syncGroups: [
{
@@ -307,6 +314,7 @@ const frameView: Types.HangingProtocol.Protocol = {
},
{
viewportOptions: {
viewportId: 'custom_R1_C3',
toolGroupId: 'default',
syncGroups: [
{
@@ -343,6 +351,7 @@ const frameView: Types.HangingProtocol.Protocol = {
},
{
viewportOptions: {
viewportId: 'custom_R2_C0',
toolGroupId: 'default',
syncGroups: [
{
@@ -379,6 +388,7 @@ const frameView: Types.HangingProtocol.Protocol = {
},
{
viewportOptions: {
viewportId: 'custom_R2_C1',
toolGroupId: 'default',
syncGroups: [
{
@@ -415,6 +425,7 @@ const frameView: Types.HangingProtocol.Protocol = {
},
{
viewportOptions: {
viewportId: 'custom_R2_C2',
toolGroupId: 'default',
syncGroups: [
{
@@ -451,6 +462,7 @@ const frameView: Types.HangingProtocol.Protocol = {
},
{
viewportOptions: {
viewportId: 'custom_R2_C3',
toolGroupId: 'default',
syncGroups: [
{
@@ -487,6 +499,7 @@ const frameView: Types.HangingProtocol.Protocol = {
},
{
viewportOptions: {
viewportId: 'custom_R3_C0',
toolGroupId: 'default',
syncGroups: [
{
@@ -523,6 +536,7 @@ const frameView: Types.HangingProtocol.Protocol = {
},
{
viewportOptions: {
viewportId: 'custom_R3_C1',
toolGroupId: 'default',
syncGroups: [
{
@@ -559,6 +573,7 @@ const frameView: Types.HangingProtocol.Protocol = {
},
{
viewportOptions: {
viewportId: 'custom_R3_C2',
toolGroupId: 'default',
syncGroups: [
{
@@ -595,6 +610,7 @@ const frameView: Types.HangingProtocol.Protocol = {
},
{
viewportOptions: {
viewportId: 'custom_R3_C3',
toolGroupId: 'default',
syncGroups: [
{
+5 -33
View File
@@ -1,3 +1,5 @@
import { HYDRATE_SEG_SYNC_GROUP, VOI_SYNC_GROUP } from './mpr';
export const main3D = {
id: 'main3D',
locked: true,
@@ -94,17 +96,7 @@ export const main3D = {
initialImageOptions: {
preset: 'middle',
},
syncGroups: [
{
type: 'voi',
id: 'mpr',
source: true,
target: true,
options: {
syncColormap: true,
},
},
],
syncGroups: [VOI_SYNC_GROUP, HYDRATE_SEG_SYNC_GROUP],
},
displaySets: [
{
@@ -120,17 +112,7 @@ export const main3D = {
initialImageOptions: {
preset: 'middle',
},
syncGroups: [
{
type: 'voi',
id: 'mpr',
source: true,
target: true,
options: {
syncColormap: true,
},
},
],
syncGroups: [VOI_SYNC_GROUP, HYDRATE_SEG_SYNC_GROUP],
},
displaySets: [
{
@@ -146,17 +128,7 @@ export const main3D = {
initialImageOptions: {
preset: 'middle',
},
syncGroups: [
{
type: 'voi',
id: 'mpr',
source: true,
target: true,
options: {
syncColormap: true,
},
},
],
syncGroups: [VOI_SYNC_GROUP, HYDRATE_SEG_SYNC_GROUP],
},
displaySets: [
{
+2 -2
View File
@@ -1,6 +1,6 @@
import { Types } from '@ohif/core';
const VOI_SYNC_GROUP = {
export const VOI_SYNC_GROUP = {
type: 'voi',
id: 'mpr',
source: true,
@@ -10,7 +10,7 @@ const VOI_SYNC_GROUP = {
},
};
const HYDRATE_SEG_SYNC_GROUP = {
export const HYDRATE_SEG_SYNC_GROUP = {
type: 'hydrateseg',
id: 'sameFORId',
source: true,
@@ -1,3 +1,5 @@
import { HYDRATE_SEG_SYNC_GROUP, VOI_SYNC_GROUP } from './mpr';
export const mprAnd3DVolumeViewport = {
id: 'mprAnd3DVolumeViewport',
locked: true,
@@ -53,17 +55,7 @@ export const mprAnd3DVolumeViewport = {
initialImageOptions: {
preset: 'middle',
},
syncGroups: [
{
type: 'voi',
id: 'mpr',
source: true,
target: true,
options: {
syncColormap: true,
},
},
],
syncGroups: [VOI_SYNC_GROUP, HYDRATE_SEG_SYNC_GROUP],
},
displaySets: [
{
@@ -79,6 +71,7 @@ export const mprAnd3DVolumeViewport = {
customViewportProps: {
hideOverlays: true,
},
syncGroups: [VOI_SYNC_GROUP, HYDRATE_SEG_SYNC_GROUP],
},
displaySets: [
{
@@ -101,17 +94,7 @@ export const mprAnd3DVolumeViewport = {
initialImageOptions: {
preset: 'middle',
},
syncGroups: [
{
type: 'voi',
id: 'mpr',
source: true,
target: true,
options: {
syncColormap: true,
},
},
],
syncGroups: [VOI_SYNC_GROUP, HYDRATE_SEG_SYNC_GROUP],
},
displaySets: [
{
@@ -127,17 +110,7 @@ export const mprAnd3DVolumeViewport = {
initialImageOptions: {
preset: 'middle',
},
syncGroups: [
{
type: 'voi',
id: 'mpr',
source: true,
target: true,
options: {
syncColormap: true,
},
},
],
syncGroups: [VOI_SYNC_GROUP, HYDRATE_SEG_SYNC_GROUP],
},
displaySets: [
{
+3
View File
@@ -1,3 +1,5 @@
import { HYDRATE_SEG_SYNC_GROUP, VOI_SYNC_GROUP } from './mpr';
export const only3D = {
id: 'only3D',
locked: true,
@@ -45,6 +47,7 @@ export const only3D = {
orientation: 'coronal',
customViewportProps: {
hideOverlays: true,
syncGroups: [VOI_SYNC_GROUP, HYDRATE_SEG_SYNC_GROUP],
},
},
displaySets: [
+5 -33
View File
@@ -1,3 +1,5 @@
import { HYDRATE_SEG_SYNC_GROUP, VOI_SYNC_GROUP } from './mpr';
export const primary3D = {
id: 'primary3D',
locked: true,
@@ -94,17 +96,7 @@ export const primary3D = {
initialImageOptions: {
preset: 'middle',
},
syncGroups: [
{
type: 'voi',
id: 'mpr',
source: true,
target: true,
options: {
syncColormap: true,
},
},
],
syncGroups: [VOI_SYNC_GROUP, HYDRATE_SEG_SYNC_GROUP],
},
displaySets: [
{
@@ -120,17 +112,7 @@ export const primary3D = {
initialImageOptions: {
preset: 'middle',
},
syncGroups: [
{
type: 'voi',
id: 'mpr',
source: true,
target: true,
options: {
syncColormap: true,
},
},
],
syncGroups: [VOI_SYNC_GROUP, HYDRATE_SEG_SYNC_GROUP],
},
displaySets: [
{
@@ -146,17 +128,7 @@ export const primary3D = {
initialImageOptions: {
preset: 'middle',
},
syncGroups: [
{
type: 'voi',
id: 'mpr',
source: true,
target: true,
options: {
syncColormap: true,
},
},
],
syncGroups: [VOI_SYNC_GROUP, HYDRATE_SEG_SYNC_GROUP],
},
displaySets: [
{
+5 -33
View File
@@ -1,3 +1,5 @@
import { HYDRATE_SEG_SYNC_GROUP, VOI_SYNC_GROUP } from './mpr';
export const primaryAxial = {
id: 'primaryAxial',
locked: true,
@@ -66,17 +68,7 @@ export const primaryAxial = {
initialImageOptions: {
preset: 'middle',
},
syncGroups: [
{
type: 'voi',
id: 'mpr',
source: true,
target: true,
options: {
syncColormap: true,
},
},
],
syncGroups: [VOI_SYNC_GROUP, HYDRATE_SEG_SYNC_GROUP],
},
displaySets: [
{
@@ -92,17 +84,7 @@ export const primaryAxial = {
initialImageOptions: {
preset: 'middle',
},
syncGroups: [
{
type: 'voi',
id: 'mpr',
source: true,
target: true,
options: {
syncColormap: true,
},
},
],
syncGroups: [VOI_SYNC_GROUP, HYDRATE_SEG_SYNC_GROUP],
},
displaySets: [
{
@@ -118,17 +100,7 @@ export const primaryAxial = {
initialImageOptions: {
preset: 'middle',
},
syncGroups: [
{
type: 'voi',
id: 'mpr',
source: true,
target: true,
options: {
syncColormap: true,
},
},
],
syncGroups: [VOI_SYNC_GROUP, HYDRATE_SEG_SYNC_GROUP],
},
displaySets: [
{
+3 -1
View File
@@ -54,6 +54,7 @@ import PanelMeasurement from './panels/PanelMeasurement';
import DicomUpload from './components/DicomUpload/DicomUpload';
import { useSegmentations } from './hooks/useSegmentations';
import { StudySummaryFromMetadata } from './components/StudySummaryFromMetadata';
import utils from './utils';
const { imageRetrieveMetadataProvider } = cornerstone.utilities;
@@ -160,7 +161,7 @@ const cornerstoneExtension: Types.Extensions.Extension = {
ViewportActionCornersProvider
);
const { syncGroupService, customizationService } = servicesManager.services;
const { syncGroupService } = servicesManager.services;
syncGroupService.registerCustomSynchronizer('frameview', createFrameViewSynchronizer);
return init.call(this, props);
@@ -254,5 +255,6 @@ export {
PanelMeasurement,
DicomUpload,
StudySummaryFromMetadata,
utils,
};
export default cornerstoneExtension;
@@ -61,7 +61,11 @@ export default function PanelSegmentation({
},
storeSegmentation: async segmentationId => {
commandsManager.run('storeSegmentation', { segmentationId });
commandsManager.run({
commandName: 'storeSegmentation',
commandOptions: { segmentationId },
context: 'CORNERSTONE',
});
},
onSegmentationDownloadRTSS: segmentationId => {
@@ -16,7 +16,7 @@ import {
} from '@cornerstonejs/tools';
import { PubSubService, Types as OHIFTypes } from '@ohif/core';
import i18n from '@ohif/i18n';
import { easeInOutBell, reverseEaseInOutBell } from '../../utils/transitions';
import { easeInOutBell, easeInOutBellRelative } from '../../utils/transitions';
import { mapROIContoursToRTStructData } from './RTSTRUCT/mapROIContoursToRTStructData';
import { SegmentationRepresentations } from '@cornerstonejs/tools/enums';
import { addColorLUT } from '@cornerstonejs/tools/segmentation/addColorLUT';
@@ -809,7 +809,8 @@ class SegmentationService extends PubSubService {
if (!segmentIndex) {
// grab the next available segment index based on the object keys,
// so basically get the highest segment index value + 1
segmentIndex = Math.max(...Object.keys(csSegmentation.segments).map(Number)) + 1;
const segmentKeys = Object.keys(csSegmentation.segments);
segmentIndex = segmentKeys.length === 0 ? 1 : Math.max(...segmentKeys.map(Number)) + 1;
}
// update the segmentation
@@ -1636,10 +1637,7 @@ class SegmentationService extends PubSubService {
const startTime = performance.now();
const prevStyle = cstSegmentation.config.style.getStyle({
viewportId,
segmentationId,
type: CONTOUR,
segmentIndex,
}) as ContourStyle;
const prevOutlineWidth = prevStyle.outlineWidth;
@@ -1649,18 +1647,11 @@ class SegmentationService extends PubSubService {
const animate = (currentTime: number) => {
const progress = (currentTime - startTime) / animationLength;
if (progress >= 1) {
cstSegmentation.config.style.setStyle(
{
segmentationId,
segmentIndex,
type: CONTOUR,
},
{}
);
cstSegmentation.config.style.resetToGlobalStyle();
return;
}
const reversedProgress = reverseEaseInOutBell(progress, baseline);
const reversedProgress = easeInOutBellRelative(progress, baseline, prevOutlineWidth);
cstSegmentation.config.style.setStyle(
{
@@ -38,6 +38,8 @@ const EVENTS = {
VIEWPORT_VOLUMES_CHANGED: 'event::cornerstoneViewportService:viewportVolumesChanged',
};
export const WITH_NAVIGATION = { withNavigation: true, withOrientation: true };
/**
* Handles cornerstone viewport logic including enabling, disabling, and
* updating the viewport.
@@ -1141,7 +1143,11 @@ class CornerstoneViewportService extends PubSubService implements IViewportServi
): void {
const viewRef = positionPresentation?.viewReference;
if (viewRef) {
viewport.setViewReference(viewRef);
if (viewport.isReferenceViewable(viewRef, WITH_NAVIGATION)) {
viewport.setViewReference(viewRef);
} else {
console.warn('Unable to apply reference viewable', viewRef);
}
}
const viewPresentation = positionPresentation?.viewPresentation;
@@ -1,22 +1,18 @@
import { useEffect, useState, memo } from 'react';
import { useEffect, useState, memo, useCallback } from 'react';
const ActiveViewportBehavior = memo(
({ servicesManager, viewportId }: withAppTypes<{ viewportId: string }>) => {
const { displaySetService, cineService, viewportGridService, customizationService } =
servicesManager.services;
const {
displaySetService,
cineService,
viewportGridService,
customizationService,
cornerstoneViewportService,
} = servicesManager.services;
const [activeViewportId, setActiveViewportId] = useState(viewportId);
useEffect(() => {
const subscription = viewportGridService.subscribe(
viewportGridService.EVENTS.ACTIVE_VIEWPORT_ID_CHANGED,
({ viewportId }) => setActiveViewportId(viewportId)
);
return () => subscription.unsubscribe();
}, [viewportId, viewportGridService]);
useEffect(() => {
const handleCineEnable = useCallback(() => {
if (cineService.isViewportCineClosed(activeViewportId)) {
return;
}
@@ -54,6 +50,32 @@ const ActiveViewportBehavior = memo(
customizationService,
]);
useEffect(() => {
const subscription = viewportGridService.subscribe(
viewportGridService.EVENTS.ACTIVE_VIEWPORT_ID_CHANGED,
({ viewportId }) => setActiveViewportId(viewportId)
);
return () => subscription.unsubscribe();
}, [viewportId, viewportGridService]);
useEffect(() => {
const subscription = cornerstoneViewportService.subscribe(
cornerstoneViewportService.EVENTS.VIEWPORT_DATA_CHANGED,
() => {
const activeViewportId = viewportGridService.getActiveViewportId();
setActiveViewportId(activeViewportId);
handleCineEnable();
}
);
return () => subscription.unsubscribe();
}, [viewportId, cornerstoneViewportService, viewportGridService, handleCineEnable]);
useEffect(() => {
handleCineEnable();
}, [handleCineEnable]);
return null;
},
arePropsEqual
@@ -0,0 +1,7 @@
import { handleSegmentChange } from './segmentUtils';
const utils = {
handleSegmentChange,
};
export default utils;
@@ -1,6 +1,8 @@
import { cache, imageLoadPoolManager, Enums } from '@cornerstonejs/core';
import getInterleavedFrames from './getInterleavedFrames';
import { compact, flatten, zip } from 'lodash';
import zip from 'lodash.zip';
import compact from 'lodash.compact';
import flatten from 'lodash.flatten';
// Map of volumeId and SeriesInstanceId
const volumeIdMapsToLoad = new Map<string, string>();
@@ -1,5 +1,7 @@
import { cache, imageLoadPoolManager, Enums } from '@cornerstonejs/core';
import { compact, flatten, zip } from 'lodash';
import zip from 'lodash.zip';
import compact from 'lodash.compact';
import flatten from 'lodash.flatten';
// Map of volumeId and SeriesInstanceId
const volumeIdMapsToLoad = new Map<string, string>();
@@ -0,0 +1,47 @@
import SegmentationServiceType from '../services/SegmentationService';
export const handleSegmentChange = ({
direction,
segDisplaySet,
viewportId,
selectedSegmentObjectIndex,
segmentationService,
}: {
direction: number;
segDisplaySet: AppTypes.DisplaySet;
viewportId: string;
selectedSegmentObjectIndex: number;
segmentationService: SegmentationServiceType;
}) => {
const segmentationId = segDisplaySet.displaySetInstanceUID;
const segmentation = segmentationService.getSegmentation(segmentationId);
const { segments } = segmentation;
const numberOfSegments = Object.keys(segments).length;
// Get activeSegment each time because the user can select any segment from the list and thus the index should be updated
const activeSegment = segmentationService.getActiveSegment(viewportId);
if (activeSegment) {
// from the activeSegment get the actual object array index to be used
selectedSegmentObjectIndex = Object.values(segments).findIndex(
segment => segment.segmentIndex === activeSegment.segmentIndex
);
}
let newSelectedSegmentIndex = selectedSegmentObjectIndex + direction;
// Handle looping through list of segments
if (newSelectedSegmentIndex > numberOfSegments - 1) {
newSelectedSegmentIndex = 0;
} else if (newSelectedSegmentIndex < 0) {
newSelectedSegmentIndex = numberOfSegments - 1;
}
// Convert segmentationId from object array index to property value of type Segment
// Functions below use the segmentIndex object attribute so we have to do the conversion
const segmentIndex = Object.values(segments)[newSelectedSegmentIndex]?.segmentIndex;
segmentationService.setActiveSegment(segmentationId, segmentIndex);
segmentationService.jumpToSegmentCenter(segmentationId, segmentIndex, viewportId);
selectedSegmentObjectIndex = newSelectedSegmentIndex;
};
@@ -34,3 +34,30 @@ export function reverseEaseInOutBell(x: number, baseline: number): number {
const y = easeInOutBell(x, baseline);
return -y + 1 + baseline;
}
export function easeInOutBellRelative(
x: number,
baseline: number,
prevOutlineWidth: number
): number {
const range = baseline - prevOutlineWidth;
if (x < 1 / 4) {
return prevOutlineWidth + 4 * Math.pow(2 * x, 3) * range;
} else if (x < 1 / 2) {
return prevOutlineWidth + (1 - Math.pow(-4 * x + 2, 3) / 2) * range;
} else if (x < 3 / 4) {
return prevOutlineWidth + (1 - Math.pow(4 * x - 2, 3) / 2) * range;
} else {
return prevOutlineWidth + -4 * Math.pow(2 * x - 2, 3) * range;
}
}
export function reverseEaseInOutBellRelative(
x: number,
baseline: number,
prevOutlineWidth: number
): number {
const y = easeInOutBellRelative(x, baseline, prevOutlineWidth);
return y;
}
+319
View File
@@ -3,6 +3,325 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
# [3.10.0-beta.112](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.111...v3.10.0-beta.112) (2025-02-28)
**Note:** Version bump only for package @ohif/extension-default
# [3.10.0-beta.111](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.110...v3.10.0-beta.111) (2025-02-26)
**Note:** Version bump only for package @ohif/extension-default
# [3.10.0-beta.110](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.109...v3.10.0-beta.110) (2025-02-26)
### Bug Fixes
* **sr:** sr hydration and load was not working, Screenshot Comparison, and Testing ([#4814](https://github.com/OHIF/Viewers/issues/4814)) ([9233143](https://github.com/OHIF/Viewers/commit/9233143b9da5850080365e1526e24b44e9910075))
# [3.10.0-beta.109](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.108...v3.10.0-beta.109) (2025-02-25)
**Note:** Version bump only for package @ohif/extension-default
# [3.10.0-beta.108](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.107...v3.10.0-beta.108) (2025-02-25)
**Note:** Version bump only for package @ohif/extension-default
# [3.10.0-beta.107](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.106...v3.10.0-beta.107) (2025-02-25)
**Note:** Version bump only for package @ohif/extension-default
# [3.10.0-beta.106](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.105...v3.10.0-beta.106) (2025-02-25)
### Features
* **hotkeys:** Migrate hotkeys to customization service and fix issues with overrides ([#4777](https://github.com/OHIF/Viewers/issues/4777)) ([3e6913b](https://github.com/OHIF/Viewers/commit/3e6913b097569280a5cc2fa5bbe4add52f149305))
# [3.10.0-beta.105](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.104...v3.10.0-beta.105) (2025-02-25)
**Note:** Version bump only for package @ohif/extension-default
# [3.10.0-beta.104](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.103...v3.10.0-beta.104) (2025-02-25)
**Note:** Version bump only for package @ohif/extension-default
# [3.10.0-beta.103](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.102...v3.10.0-beta.103) (2025-02-23)
**Note:** Version bump only for package @ohif/extension-default
# [3.10.0-beta.102](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.101...v3.10.0-beta.102) (2025-02-20)
**Note:** Version bump only for package @ohif/extension-default
# [3.10.0-beta.101](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.100...v3.10.0-beta.101) (2025-02-20)
**Note:** Version bump only for package @ohif/extension-default
# [3.10.0-beta.100](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.99...v3.10.0-beta.100) (2025-02-19)
**Note:** Version bump only for package @ohif/extension-default
# [3.10.0-beta.99](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.98...v3.10.0-beta.99) (2025-02-18)
### Bug Fixes
* cache thumbnail in display set ([#4782](https://github.com/OHIF/Viewers/issues/4782)) ([2410c6a](https://github.com/OHIF/Viewers/commit/2410c6a50904c1235993900e837876cc26af019b))
# [3.10.0-beta.98](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.97...v3.10.0-beta.98) (2025-02-18)
### Bug Fixes
* lodash dependencies ([#4791](https://github.com/OHIF/Viewers/issues/4791)) ([4e16099](https://github.com/OHIF/Viewers/commit/4e16099ad3ab777b09f6ac8f181025cfd656ab6b))
# [3.10.0-beta.97](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.96...v3.10.0-beta.97) (2025-02-18)
### Features
* improve dicom tag browser with nested rows ([#4451](https://github.com/OHIF/Viewers/issues/4451)) ([0b5836c](https://github.com/OHIF/Viewers/commit/0b5836ca1a908e152336752672b196f0d533f4f9))
# [3.10.0-beta.96](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.95...v3.10.0-beta.96) (2025-02-18)
**Note:** Version bump only for package @ohif/extension-default
# [3.10.0-beta.95](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.94...v3.10.0-beta.95) (2025-02-13)
**Note:** Version bump only for package @ohif/extension-default
# [3.10.0-beta.94](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.93...v3.10.0-beta.94) (2025-02-11)
**Note:** Version bump only for package @ohif/extension-default
# [3.10.0-beta.93](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.92...v3.10.0-beta.93) (2025-02-04)
### Bug Fixes
* add commandsManager to MoreDropdownMenu onClick props ([#4765](https://github.com/OHIF/Viewers/issues/4765)) ([bbf1a19](https://github.com/OHIF/Viewers/commit/bbf1a19676b2b345a0f911dde319e5ffefe29fa6))
# [3.10.0-beta.92](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.91...v3.10.0-beta.92) (2025-02-04)
**Note:** Version bump only for package @ohif/extension-default
# [3.10.0-beta.91](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.90...v3.10.0-beta.91) (2025-02-04)
**Note:** Version bump only for package @ohif/extension-default
# [3.10.0-beta.90](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.89...v3.10.0-beta.90) (2025-02-04)
**Note:** Version bump only for package @ohif/extension-default
# [3.10.0-beta.89](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.88...v3.10.0-beta.89) (2025-02-04)
### Features
* **ui:** customization option for viewport notification ([#4638](https://github.com/OHIF/Viewers/issues/4638)) ([8acbd76](https://github.com/OHIF/Viewers/commit/8acbd760d801dcaf624c5d9fb636a029201b91e1))
# [3.10.0-beta.88](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.87...v3.10.0-beta.88) (2025-02-04)
**Note:** Version bump only for package @ohif/extension-default
# [3.10.0-beta.87](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.86...v3.10.0-beta.87) (2025-02-03)
### Bug Fixes
* **measurement label auto-completion:** Customization of measurement label auto-completion fails for measurements following arrow annotations. ([#4739](https://github.com/OHIF/Viewers/issues/4739)) ([e035ef1](https://github.com/OHIF/Viewers/commit/e035ef1dcc72ecbe2a757e3b814551d768d7e610))
# [3.10.0-beta.86](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.85...v3.10.0-beta.86) (2025-02-03)
### Bug Fixes
* **store-segmentation:** storing segmentations was hitting the wrong command resulting in an undefined datasource ([#4755](https://github.com/OHIF/Viewers/issues/4755)) ([9b8e5cf](https://github.com/OHIF/Viewers/commit/9b8e5cfd1a6121a58991c0f75660a2fd9913a4e7))
# [3.10.0-beta.85](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.84...v3.10.0-beta.85) (2025-02-03)
### Features
* Add customization support for more UI components ([#4634](https://github.com/OHIF/Viewers/issues/4634)) ([f15eb44](https://github.com/OHIF/Viewers/commit/f15eb44b4cf49de1b73a22512571cec02effaef3))
# [3.10.0-beta.84](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.83...v3.10.0-beta.84) (2025-01-31)
**Note:** Version bump only for package @ohif/extension-default
# [3.10.0-beta.83](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.82...v3.10.0-beta.83) (2025-01-31)
**Note:** Version bump only for package @ohif/extension-default
# [3.10.0-beta.82](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.81...v3.10.0-beta.82) (2025-01-31)
**Note:** Version bump only for package @ohif/extension-default
# [3.10.0-beta.81](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.80...v3.10.0-beta.81) (2025-01-29)
**Note:** Version bump only for package @ohif/extension-default
# [3.10.0-beta.80](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.79...v3.10.0-beta.80) (2025-01-29)
### Features
* **customization:** enable custom onDropHandler for viewportGrid ([#4641](https://github.com/OHIF/Viewers/issues/4641)) ([054b262](https://github.com/OHIF/Viewers/commit/054b262e9cbeb0f44de65d05641efe1e8944a4f5))
# [3.10.0-beta.79](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.78...v3.10.0-beta.79) (2025-01-28)
### Bug Fixes
* **dependencies:** Update dcmjs library and improve documentation links ([#4741](https://github.com/OHIF/Viewers/issues/4741)) ([d554f02](https://github.com/OHIF/Viewers/commit/d554f02f7cdb876e4132fb94e3b3df8d11b7bb5c))
# [3.10.0-beta.78](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.77...v3.10.0-beta.78) (2025-01-28)
### Features
* **side-panels:** Added resize handle interactive feedback for side panels ([#4734](https://github.com/OHIF/Viewers/issues/4734)) ([6abb095](https://github.com/OHIF/Viewers/commit/6abb095b8a39c5ae4f8df8852b3ddb3249ec463f))
# [3.10.0-beta.77](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.76...v3.10.0-beta.77) (2025-01-28)
**Note:** Version bump only for package @ohif/extension-default
+6 -4
View File
@@ -1,6 +1,6 @@
{
"name": "@ohif/extension-default",
"version": "3.10.0-beta.77",
"version": "3.10.0-beta.112",
"description": "Common/default features and functionality for basic image viewing",
"author": "OHIF Core Team",
"license": "MIT",
@@ -32,8 +32,8 @@
"start": "yarn run dev"
},
"peerDependencies": {
"@ohif/core": "3.10.0-beta.77",
"@ohif/i18n": "3.10.0-beta.77",
"@ohif/core": "3.10.0-beta.112",
"@ohif/i18n": "3.10.0-beta.112",
"dcmjs": "*",
"dicomweb-client": "^0.10.4",
"prop-types": "^15.6.2",
@@ -46,6 +46,8 @@
},
"dependencies": {
"@babel/runtime": "^7.20.13",
"@cornerstonejs/calculate-suv": "^1.1.0"
"@cornerstonejs/calculate-suv": "^1.1.0",
"lodash.get": "^4.4.2",
"lodash.uniqby": "^4.7.0"
}
}
@@ -1,7 +1,8 @@
import classNames from 'classnames';
import React, { ReactElement, useEffect, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { Button, InputFilterText, LoadingIndicatorProgress } from '@ohif/ui';
import { useSystem } from '@ohif/core';
import { Button, InputFilterText } from '@ohif/ui';
import { Icons } from '@ohif/ui-next';
import { Types } from '@ohif/core';
@@ -16,6 +17,7 @@ function ItemListComponent({
itemList,
onItemClicked,
}: ItemListComponentProps): ReactElement {
const { servicesManager } = useSystem();
const { t } = useTranslation('DataSourceConfiguration');
const [filterValue, setFilterValue] = useState('');
@@ -23,6 +25,10 @@ function ItemListComponent({
setFilterValue('');
}, [itemList]);
const LoadingIndicatorProgress = servicesManager.services.customizationService.getCustomization(
'ui.loadingIndicatorProgress'
);
return (
<div className="flex min-h-[1px] grow flex-col gap-4">
<div className="flex items-center justify-between">
@@ -3,6 +3,7 @@ import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuTrigger,
DropdownMenuItem,
Icons,
Button,
} from '@ohif/ui-next';
@@ -11,13 +12,40 @@ import {
* The default sub-menu appearance and setup is defined here, but this can be
* replaced by
*/
const getMenuItemsDefault = ({ commandsManager, items, servicesManager, ...props }) => {
const getMenuItemsDefault = ({
commandsManager,
items,
servicesManager,
...props
}: withAppTypes) => {
const { customizationService } = servicesManager.services;
// This allows replacing the default child item for menus, whereas the entire
// getMenuItems can also be replaced by providing it to the MoreDropdownMenu
const menuContent = customizationService.getCustomization('ohif.menuContent');
// Default menu item component if none is provided through customization
const DefaultMenuItem = ({
item,
}: {
item: {
id: string;
label: string;
iconName: string;
onClick: ({ commandsManager, ...props }: withAppTypes) => () => void;
};
}) => (
<DropdownMenuItem onClick={() => item.onClick({ commandsManager, ...props })}>
<div className="flex items-center gap-2">
{item.iconName && <Icons.ByName name={item.iconName} />}
<span>{item.label}</span>
</div>
</DropdownMenuItem>
);
const MenuItemComponent = menuContent?.content || DefaultMenuItem;
return (
<DropdownMenuContent
hideWhenDetached
@@ -27,15 +55,15 @@ const getMenuItemsDefault = ({ commandsManager, items, servicesManager, ...props
e.preventDefault();
}}
>
{items?.map((item, index) =>
React.createElement(menuContent.content, {
key: item.id || `menu-item-${index}`,
item,
commandsManager,
servicesManager,
...props,
})
)}
{items?.map((item, index) => (
<MenuItemComponent
key={item.id || `menu-item-${index}`}
item={item}
commandsManager={commandsManager}
servicesManager={servicesManager}
{...props}
/>
))}
</DropdownMenuContent>
);
};
@@ -1,5 +1,4 @@
import * as ContextMenuItemsBuilder from './ContextMenuItemsBuilder';
import ContextMenu from '../../../../platform/ui/src/components/ContextMenu/ContextMenu';
import { CommandsManager } from '@ohif/core';
import { annotation as CsAnnotation } from '@cornerstonejs/tools';
import { Menu, MenuItem, Point, ContextMenuProps } from './types';
@@ -72,6 +71,8 @@ export default class ContextMenuController {
menuId
);
const ContextMenu = this.services.customizationService.getCustomization('ui.contextMenu');
this.services.uiDialogService.dismiss({ id: 'context-menu' });
this.services.uiDialogService.create({
id: 'context-menu',
@@ -1,30 +1,44 @@
import dcmjs from 'dcmjs';
import moment from 'moment';
import React, { useState, useMemo, useEffect } from 'react';
import { classes } from '@ohif/core';
import React, { useState, useMemo, useCallback } from 'react';
import { classes, Types } from '@ohif/core';
import { InputFilterText } from '@ohif/ui';
import debounce from 'lodash.debounce';
import { Select, SelectTrigger, SelectContent, SelectItem, Slider } from '@ohif/ui-next';
import DicomTagTable from './DicomTagTable';
import './DicomTagBrowser.css';
export type Row = {
uid: string;
tag: string;
valueRepresentation: string;
keyword: string;
value: string;
isVisible: boolean;
depth: number;
parents?: string[];
children?: string[];
areChildrenVisible?: true;
};
let rowCounter = 0;
const generateRowId = () => `row_${++rowCounter}`;
const { ImageSet } = classes;
const { DicomMetaDictionary } = dcmjs.data;
const { nameMap } = DicomMetaDictionary;
const DicomTagBrowser = ({ displaySets, displaySetInstanceUID }) => {
// The column indices that are to be excluded during a filter of the table.
// At present the column indices are:
// 0: DICOM tag
// 1: VR
// 2: Keyword
// 3: Value
const excludedColumnIndicesForFilter: Set<number> = new Set([1]);
const DicomTagBrowser = ({
displaySets,
displaySetInstanceUID,
}: {
displaySets: Types.DisplaySet[];
displaySetInstanceUID: string;
}) => {
const [selectedDisplaySetInstanceUID, setSelectedDisplaySetInstanceUID] =
useState(displaySetInstanceUID);
const [instanceNumber, setInstanceNumber] = useState(1);
const [shouldShowInstanceList, setShouldShowInstanceList] = useState(false);
const [filterValue, setFilterValue] = useState('');
const onSelectChange = value => {
@@ -36,9 +50,6 @@ const DicomTagBrowser = ({ displaySets, displaySetInstanceUID }) => {
ds => ds.displaySetInstanceUID === selectedDisplaySetInstanceUID
);
const isImageStack = _isImageStack(activeDisplaySet);
const showInstanceList = isImageStack && activeDisplaySet.images.length > 1;
const displaySetList = useMemo(() => {
displaySets.sort((a, b) => a.SeriesNumber - b.SeriesNumber);
return displaySets.map(displaySet => {
@@ -64,48 +75,53 @@ const DicomTagBrowser = ({ displaySets, displaySetInstanceUID }) => {
});
}, [displaySets]);
const getMetadata = useCallback(
isImageStack => {
if (isImageStack) {
return activeDisplaySet.images[instanceNumber - 1];
}
return activeDisplaySet.instance || activeDisplaySet;
},
[activeDisplaySet, instanceNumber]
);
const rows = useMemo(() => {
let metadata;
if (isImageStack) {
metadata = activeDisplaySet.images[instanceNumber - 1];
} else {
metadata = activeDisplaySet.instance || activeDisplaySet;
}
const isImageStack = activeDisplaySet instanceof ImageSet;
const metadata = getMetadata(isImageStack);
setShouldShowInstanceList(isImageStack && activeDisplaySet.images.length > 1);
const tags = getSortedTags(metadata);
return getFormattedRowsFromTags(tags, metadata);
}, [instanceNumber, selectedDisplaySetInstanceUID]);
const rows = getFormattedRowsFromTags({ tags, metadata, depth: 0 });
return rows;
}, [getMetadata, activeDisplaySet]);
const filteredRows = useMemo(() => {
if (!filterValue) {
return rows;
}
const filterValueLowerCase = filterValue.toLowerCase();
return rows.filter(row => {
return row.reduce((keepRow, col, colIndex) => {
if (keepRow) {
// We are already keeping the row, why do more work so return now.
return keepRow;
}
const matchedRowIds = new Set();
if (excludedColumnIndicesForFilter.has(colIndex)) {
return keepRow;
}
const propertiesToCheck = ['tag', 'valueRepresentation', 'keyword', 'value'];
return keepRow || col.toLowerCase().includes(filterValueLowerCase);
}, false);
});
}, [rows, filterValue]);
const setIsMatched = row => {
const isDirectMatch = propertiesToCheck.some(propertyName =>
row[propertyName]?.toLowerCase().includes(filterValueLowerCase)
);
const debouncedSetFilterValue = useMemo(() => {
return debounce(setFilterValue, 200);
}, []);
if (!isDirectMatch) {
return;
}
useEffect(() => {
return () => {
debouncedSetFilterValue?.cancel();
matchedRowIds.add(row.uid);
[...(row.parents ?? []), ...(row.children ?? [])].forEach(uid => matchedRowIds.add(uid));
};
}, []);
const filterValueLowerCase = filterValue.toLowerCase();
rows.forEach(setIsMatched);
return rows.filter(row => matchedRowIds.has(row.uid));
}, [rows, filterValue]);
return (
<div className="dicom-tag-browser-content bg-muted">
@@ -136,10 +152,10 @@ const DicomTagBrowser = ({ displaySets, displaySetInstanceUID }) => {
</SelectContent>
</Select>
</div>
{showInstanceList && (
{shouldShowInstanceList && (
<div className="mx-auto flex w-1/5 flex-col">
<span className="text-muted-foreground flex h-6 items-center text-xs">
Instance Number ({instanceNumber} of {activeDisplaySet.images.length})
Instance Number ({instanceNumber} of {activeDisplaySet?.images?.length})
</span>
<Slider
value={[instanceNumber]}
@@ -147,7 +163,7 @@ const DicomTagBrowser = ({ displaySets, displaySetInstanceUID }) => {
setInstanceNumber(value);
}}
min={1}
max={activeDisplaySet.images.length}
max={activeDisplaySet?.images?.length}
step={1}
className="pt-4"
/>
@@ -169,22 +185,33 @@ const DicomTagBrowser = ({ displaySets, displaySetInstanceUID }) => {
);
};
function getFormattedRowsFromTags(tags, metadata) {
const rows = [];
function getFormattedRowsFromTags({ tags, metadata, depth, parents }) {
const rows: Row[] = [];
tags.forEach(tagInfo => {
const uid = generateRowId();
if (tagInfo.vr === 'SQ') {
rows.push([`${tagInfo.tagIndent}${tagInfo.tag}`, tagInfo.vr, tagInfo.keyword, '']);
const { values } = tagInfo;
values.forEach((item, index) => {
const formatedRowsFromTags = getFormattedRowsFromTags(item, metadata);
rows.push([`${item[0].tagIndent}(FFFE,E000)`, '', `Item #${index}`, '']);
rows.push(...formatedRowsFromTags);
});
const children = tagInfo.values.flatMap(value =>
getFormattedRowsFromTags({
tags: value,
metadata,
depth: depth + 1,
parents: parents ? [...parents, uid] : [uid],
})
);
const row: Row = {
uid,
tag: tagInfo.tag,
valueRepresentation: tagInfo.vr,
keyword: tagInfo.keyword,
value: '',
depth,
isVisible: true,
areChildrenVisible: true,
children: children.map(child => child.uid),
parents,
};
rows.push(row, ...children);
} else {
if (tagInfo.vr === 'xs') {
try {
@@ -192,10 +219,20 @@ function getFormattedRowsFromTags(tags, metadata) {
const originalTagInfo = metadata[tag];
tagInfo.vr = originalTagInfo.vr;
} catch (error) {
console.error(`Failed to parse value representation for tag '${tagInfo.keyword}'`);
console.warn(`Failed to parse value representation for tag '${tagInfo.keyword}'`);
}
}
rows.push([`${tagInfo.tagIndent}${tagInfo.tag}`, tagInfo.vr, tagInfo.keyword, tagInfo.value]);
const row: Row = {
uid,
tag: tagInfo.tag,
valueRepresentation: tagInfo.vr,
keyword: tagInfo.keyword,
value: tagInfo.value,
depth,
isVisible: true,
parents,
};
rows.push(row);
}
});
@@ -216,16 +253,6 @@ function getRows(metadata, depth = 0) {
const keywords = Object.keys(metadata);
let tagIndent = '';
for (let i = 0; i < depth; i++) {
tagIndent += '>';
}
if (depth > 0) {
tagIndent += ' '; // If indented, add a space after the indents.
}
const rows = [];
for (let i = 0; i < keywords.length; i++) {
let keyword = keywords[i];
@@ -245,7 +272,6 @@ function getRows(metadata, depth = 0) {
const sequence = {
tag: tagInfo.tag,
tagIndent,
vr: tagInfo.vr,
keyword,
values: [],
@@ -311,7 +337,6 @@ function getRows(metadata, depth = 0) {
if (tagInfo) {
rows.push({
tag: tagInfo.tag,
tagIndent,
vr: tagInfo.vr,
keyword,
value,
@@ -323,7 +348,6 @@ function getRows(metadata, depth = 0) {
const tag = `(${keyword.substring(0, 4)},${keyword.substring(4, 8)})`;
rows.push({
tag,
tagIndent,
vr: '',
keyword: 'Private Tag',
value,
@@ -335,10 +359,6 @@ function getRows(metadata, depth = 0) {
return rows;
}
function _isImageStack(displaySet) {
return displaySet instanceof ImageSet;
}
function toArray(objectOrArray) {
return Array.isArray(objectOrArray) ? objectOrArray : [objectOrArray];
}
@@ -1,7 +1,9 @@
import React, { useCallback, useEffect, useRef, useState } from 'react';
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { VariableSizeList as List } from 'react-window';
import classNames from 'classnames';
import debounce from 'lodash.debounce';
import { Row } from './DicomTagBrowser';
import { Icons } from '@ohif/ui-next';
const lineHeightPx = 20;
const lineHeightClassName = `leading-[${lineHeightPx}px]`;
@@ -12,6 +14,62 @@ const rowStyle = {
borderBottomWidth: `${rowBottomBorderPx}px`,
...rowVerticalPaddingStyle,
};
const indentationPadding = 8;
const RowComponent = ({
row,
style,
keyPrefix,
onToggle,
}: {
row: Row;
style: any;
keyPrefix: string;
onToggle?: (areChildrenVisible: boolean) => void;
}) => {
const handleToggle = useCallback(() => {
onToggle(!row.areChildrenVisible);
}, [row.areChildrenVisible, onToggle]);
const hasChildren = row.children && row.children.length > 0;
const isChildOrParent = hasChildren || row.depth > 0;
const padding = indentationPadding * (1 + 2 * row.depth);
return (
<div
style={{ ...style, ...rowStyle }}
className={classNames(
'hover:bg-secondary-main border-secondary-light flex w-full flex-row items-center break-all bg-black text-base transition duration-300',
lineHeightClassName
)}
key={keyPrefix}
>
{isChildOrParent && (
<div style={{ paddingLeft: `${padding}px`, opacity: onToggle ? 1 : 0 }}>
{row.areChildrenVisible ? (
<div
className="cursor-pointer p-1"
onClick={handleToggle}
>
<Icons.ChevronDown />
</div>
) : (
<div
className="cursor-pointer p-1"
onClick={handleToggle}
>
<Icons.ChevronRight />
</div>
)}
</div>
)}
<div className="w-4/24 px-3">{row.tag}</div>
<div className="w-2/24 px-3">{row.valueRepresentation}</div>
<div className="w-6/24 px-3">{row.keyword}</div>
<div className="w-5/24 grow px-3">{row.value}</div>
</div>
);
};
function ColumnHeaders({ tagRef, vrRef, keywordRef, valueRef }) {
return (
@@ -56,8 +114,7 @@ function ColumnHeaders({ tagRef, vrRef, keywordRef, valueRef }) {
</div>
);
}
function DicomTagTable({ rows }) {
function DicomTagTable({ rows }: { rows: Row[] }) {
const listRef = useRef();
const canvasRef = useRef();
@@ -65,6 +122,7 @@ function DicomTagTable({ rows }) {
const [vrHeaderElem, setVrHeaderElem] = useState(null);
const [keywordHeaderElem, setKeywordHeaderElem] = useState(null);
const [valueHeaderElem, setValueHeaderElem] = useState(null);
const [internalRows, setInternalRows] = useState(rows);
// Here the refs are inturn stored in state to trigger a render of the table.
// This virtualized table does NOT render until the header is rendered because the header column widths are used to determine the row heights in the table.
@@ -90,6 +148,14 @@ function DicomTagTable({ rows }) {
}
};
useEffect(() => {
setInternalRows(rows);
}, [rows]);
const visibleRows = useMemo(() => {
return internalRows.filter(row => row.isVisible);
}, [internalRows]);
/**
* When new rows are set, scroll to the top and reset the virtualization.
*/
@@ -116,42 +182,8 @@ function DicomTagTable({ rows }) {
};
}, []);
const Row = useCallback(
({ index, style }) => {
const row = rows[index];
return (
<div
style={{ ...style, ...rowStyle }}
className={classNames(
'hover:bg-secondary-main border-secondary-light flex w-full flex-row items-center break-all bg-black text-base transition duration-300',
lineHeightClassName
)}
key={`DICOMTagRow-${index}`}
>
<div className="w-4/24 px-3">{row[0]}</div>
<div className="w-2/24 px-3">{row[1]}</div>
<div className="w-6/24 px-3">{row[2]}</div>
<div className="w-5/24 grow px-3">{row[3]}</div>
</div>
);
},
[rows]
);
/**
* Whenever any one of the column headers is set, then the header is rendered.
* Here we chose the tag header.
*/
const isHeaderRendered = useCallback(() => tagHeaderElem !== null, [tagHeaderElem]);
/**
* Get the item/row size. We use the header column widths to calculate the various row heights.
* @param index the row index
* @returns the row height
*/
const getItemSize = useCallback(
index => {
const getOneRowHeight = useCallback(
row => {
const headerWidths = [
tagHeaderElem.offsetWidth,
vrHeaderElem.offsetWidth,
@@ -162,17 +194,79 @@ function DicomTagTable({ rows }) {
const context = canvasRef.current.getContext('2d');
context.font = getComputedStyle(canvasRef.current).font;
return rows[index]
.map((colText, index) => {
const propertiesToCheck = ['tag', 'valueRepresentation', 'keyword', 'value'];
return Object.entries(row)
.filter(([key]) => propertiesToCheck.includes(key))
.map(([, colText], index) => {
const colOneLineWidth = context.measureText(colText).width;
const numLines = Math.ceil(colOneLineWidth / headerWidths[index]);
return numLines * lineHeightPx + 2 * rowVerticalPaddingPx + rowBottomBorderPx;
})
.reduce((maxHeight, colHeight) => Math.max(maxHeight, colHeight));
.reduce((maxHeight, colHeight) => Math.max(maxHeight, colHeight), 0);
},
[rows, keywordHeaderElem, tagHeaderElem, valueHeaderElem, vrHeaderElem]
[keywordHeaderElem, tagHeaderElem, valueHeaderElem, vrHeaderElem]
);
/**
* Get the item/row size. We use the header column widths to calculate the various row heights.
* @param index the row index
* @returns the row height
*/
const getItemSize = useCallback(
rows => index => {
const row = rows[index];
const height = getOneRowHeight(row);
return height;
},
[getOneRowHeight]
);
const onToggle = useCallback(
sourceRow => {
if (!sourceRow.children) {
return undefined;
}
return areChildrenVisible => {
const newInternalRows = internalRows.map(internalRow => {
if (sourceRow.uid === internalRow.uid) {
return { ...internalRow, areChildrenVisible };
}
if (sourceRow.children.includes(internalRow.uid)) {
return { ...internalRow, isVisible: areChildrenVisible, areChildrenVisible };
}
return internalRow;
});
setInternalRows(newInternalRows);
};
},
[internalRows]
);
const getRowComponent = useCallback(
({ rows }: { rows: Row[] }) =>
function RowList({ index, style }) {
const row = useMemo(() => rows[index], [index]);
return (
<RowComponent
style={style}
row={row}
keyPrefix={`DICOMTagRow-${index}`}
onToggle={onToggle(row)}
/>
);
},
[onToggle]
);
/**
* Whenever any one of the column headers is set, then the header is rendered.
* Here we chose the tag header.
*/
const isHeaderRendered = useCallback(() => tagHeaderElem !== null, [tagHeaderElem]);
return (
<div>
<canvas
@@ -194,12 +288,12 @@ function DicomTagTable({ rows }) {
<List
ref={listRef}
height={500}
itemCount={rows.length}
itemSize={getItemSize}
itemCount={visibleRows.length}
itemSize={getItemSize(visibleRows)}
width={'100%'}
className="ohif-scrollbar"
>
{Row}
{getRowComponent({ rows: visibleRows })}
</List>
)}
</div>
@@ -207,4 +301,4 @@ function DicomTagTable({ rows }) {
);
}
export default DicomTagTable;
export default React.memo(DicomTagTable);
@@ -1,5 +1,6 @@
import { DicomMetadataStore, IWebApiDataSource } from '@ohif/core';
import { get, uniqBy } from 'lodash';
import get from 'lodash.get';
import uniqBy from 'lodash.uniqby';
import {
MergeConfig,
CallForAllDataSourcesAsyncOptions,
@@ -2,7 +2,7 @@ import React, { useState, useEffect } from 'react';
import { useImageViewer } from '@ohif/ui';
import { useViewportGrid } from '@ohif/ui-next';
import { StudyBrowser } from '@ohif/ui-next';
import { utils } from '@ohif/core';
import { useSystem, utils } from '@ohif/core';
import { useNavigate } from 'react-router-dom';
import { Separator } from '@ohif/ui-next';
import { PanelStudyBrowserHeader } from './PanelStudyBrowserHeader';
@@ -16,13 +16,12 @@ const { sortStudyInstances, formatDate, createStudyBrowserTabs } = utils;
* @param {*} param0
*/
function PanelStudyBrowser({
servicesManager,
getImageSrc,
getStudiesForPatientByMRN,
requestDisplaySetCreationForStudy,
dataSource,
commandsManager,
}: withAppTypes) {
}) {
const { servicesManager, commandsManager } = useSystem();
const { hangingProtocolService, displaySetService, uiNotificationService, customizationService } =
servicesManager.services;
const navigate = useNavigate();
@@ -5,6 +5,7 @@ import PanelStudyBrowser from './StudyBrowser/PanelStudyBrowser';
import getImageSrcFromImageId from './getImageSrcFromImageId';
import getStudiesForPatientByMRN from './getStudiesForPatientByMRN';
import requestDisplaySetCreationForStudy from './requestDisplaySetCreationForStudy';
import { useSystem } from '@ohif/core';
/**
* Wraps the PanelStudyBrowser and provides features afforded by managers/services
@@ -13,7 +14,8 @@ import requestDisplaySetCreationForStudy from './requestDisplaySetCreationForStu
* @param {object} commandsManager
* @param {object} extensionManager
*/
function WrappedPanelStudyBrowser({ extensionManager, servicesManager, commandsManager }) {
function WrappedPanelStudyBrowser() {
const { extensionManager } = useSystem();
// TODO: This should be made available a different way; route should have
// already determined our datasource
const [dataSource] = extensionManager.getActiveDataSource();
@@ -29,8 +31,6 @@ function WrappedPanelStudyBrowser({ extensionManager, servicesManager, commandsM
return (
<PanelStudyBrowser
servicesManager={servicesManager}
commandsManager={commandsManager}
dataSource={dataSource}
getImageSrc={_getImageSrcFromImageId}
getStudiesForPatientByMRN={_getStudiesForPatientByMRN}
@@ -61,10 +61,4 @@ function _createGetImageSrcFromImageIdFn(extensionManager) {
}
}
WrappedPanelStudyBrowser.propTypes = {
commandsManager: PropTypes.object.isRequired,
extensionManager: PropTypes.object.isRequired,
servicesManager: PropTypes.object.isRequired,
};
export default WrappedPanelStudyBrowser;
@@ -0,0 +1,44 @@
import React from 'react';
import classNames from 'classnames';
import { ToolButton } from '@ohif/ui-next';
/**
* Wraps the ToolButtonList component to handle the OHIF toolbar button structure
* @param props - Component props
* @returns Component
*/
export function ToolBoxButtonGroupWrapper({ groupId, items, onInteraction, ...props }) {
if (!items || !groupId) {
return null;
}
return (
<div className="bg-popover flex flex-row space-x-1 rounded-md px-0 py-0">
{items.map(item => (
<ToolButton
{...item}
key={item.id}
size="small"
className={props.disabled && 'text-primary'}
onInteraction={() =>
onInteraction?.({ groupId, itemId: item.id, commands: item.commands })
}
/>
))}
</div>
);
}
export function ToolBoxButtonWrapper({ onInteraction, ...props }) {
return (
<div className="bg-popover flex flex-row rounded-md px-0 py-0">
<ToolButton
{...props}
id={props.id}
size="small"
className={classNames(props.disabled && 'text-primary')}
onInteraction={() => onInteraction?.({ itemId: props.id, commands: props.commands })}
/>
</div>
);
}
@@ -0,0 +1,84 @@
import React from 'react';
import {
ToolButtonList,
ToolButton,
ToolButtonListDefault,
ToolButtonListDropDown,
ToolButtonListItem,
ToolButtonListDivider,
} from '@ohif/ui-next';
interface ButtonItem {
id: string;
icon?: string;
label?: string;
tooltip?: string;
isActive?: boolean;
disabledText?: string;
commands?: Record<string, unknown>;
disabled?: boolean;
className?: string;
}
interface ToolButtonListWrapperProps {
groupId: string;
primary: ButtonItem;
items: ButtonItem[];
onInteraction?: (details: {
groupId: string;
itemId: string;
commands?: Record<string, unknown>;
}) => void;
}
/**
* Wraps the ToolButtonList component to handle the OHIF toolbar button structure
* @param props - Component props
* @returns Component
* // test
*/
export default function ToolButtonListWrapper({
groupId,
primary,
items,
onInteraction,
}: ToolButtonListWrapperProps) {
return (
<ToolButtonList>
<ToolButtonListDefault>
<div
data-cy={`${groupId}-split-button-primary`}
data-tool={primary.id}
data-active={primary.isActive}
>
<ToolButton
{...primary}
onInteraction={({ itemId }) =>
onInteraction?.({ groupId, itemId, commands: primary.commands })
}
className={primary.className}
/>
</div>
</ToolButtonListDefault>
<ToolButtonListDivider className={primary.isActive ? 'opacity-0' : 'opacity-100'} />
<div data-cy={`${groupId}-split-button-secondary`}>
<ToolButtonListDropDown>
{items.map(item => (
<ToolButtonListItem
key={item.id}
{...item}
data-cy={item.id}
data-tool={item.id}
data-active={item.isActive}
onSelect={() =>
onInteraction?.({ groupId, itemId: item.id, commands: item.commands })
}
>
<span className="pl-1">{item.label || item.tooltip || item.id}</span>
</ToolButtonListItem>
))}
</ToolButtonListDropDown>
</div>
</ToolButtonList>
);
}
+1 -3
View File
@@ -1,6 +1,4 @@
import React from 'react';
import { Tooltip } from '@ohif/ui';
import classnames from 'classnames';
import { useToolbar } from '@ohif/core';
export function Toolbar({ servicesManager, buttonSection = 'primary' }) {
@@ -15,7 +13,7 @@ export function Toolbar({ servicesManager, buttonSection = 'primary' }) {
return (
<>
{toolbarButtons.map(toolDef => {
{toolbarButtons?.map(toolDef => {
if (!toolDef) {
return null;
}
@@ -1,5 +1,5 @@
import { ToolbarButton, ButtonGroup } from '@ohif/ui';
import React, { useCallback } from 'react';
import { ToolbarButton, ButtonGroup } from '@ohif/ui';
function ToolbarButtonGroupWithServices({ groupId, items, onInteraction, size }) {
const getSplitButtonItems = useCallback(
@@ -5,7 +5,7 @@ import { panelGroupDefinition } from './constants/panels';
/**
* Set the minimum and maximum css style width attributes for the given element.
* The two style attributes are cleared whenever the width
* arguments is undefined.
* argument is undefined.
* <p>
* This utility is used as part of a HACK throughout the ViewerLayout component as
* the means of restricting the side panel widths during the resizing of the
@@ -34,7 +34,7 @@ const useResizablePanels = (
);
const [leftResizablePanelMinimumSize, setLeftResizablePanelMinimumSize] = useState(0);
const [rightResizablePanelMinimumSize, setRightResizablePanelMinimumSize] = useState(0);
const [leftResizeablePanelCollapsedSize, setLeftResizePanelCollapsedSize] = useState(0);
const [leftResizablePanelCollapsedSize, setLeftResizePanelCollapsedSize] = useState(0);
const [rightResizePanelCollapsedSize, setRightResizePanelCollapsedSize] = useState(0);
const resizablePanelGroupElemRef = useRef(null);
@@ -44,15 +44,16 @@ const useResizablePanels = (
const resizableRightPanelAPIRef = useRef(null);
const isResizableHandleDraggingRef = useRef(false);
// The total width of both handles.
const resizableHandlesWidth = useRef(null);
// This useLayoutEffect is used to...
// - Grab a reference to the various resizable panel elements needed for
// converting between percentages and pixels in various callbacks.
// - Expand those panels that are initially expanded.
useLayoutEffect(() => {
const panelGroupElem = getPanelGroupElement(panelGroupDefinition.groupId);
resizablePanelGroupElemRef.current = panelGroupElem;
const { width: panelGroupWidth } = panelGroupElem.getBoundingClientRect();
const leftPanelElem = getPanelElement(panelGroupDefinition.left.panelId);
resizableLeftPanelElemRef.current = leftPanelElem;
@@ -60,20 +61,29 @@ const useResizablePanels = (
const rightPanelElem = getPanelElement(panelGroupDefinition.right.panelId);
resizableRightPanelElemRef.current = rightPanelElem;
// Calculate and set the width of both handles combined.
const resizeHandles = document.querySelectorAll('[data-panel-resize-handle-id]');
resizableHandlesWidth.current = 0;
resizeHandles.forEach(resizeHandle => {
resizableHandlesWidth.current += resizeHandle.offsetWidth;
});
// Since both resizable panels are collapsed by default (i.e. their default size is zero),
// on the very first render check if either/both side panels should be expanded.
// we use the initialExpandedOffsetWidth on the first render incase the panel has min width but we want the initial state to be larger than that
if (!leftPanelClosed) {
const leftResizablePanelExpandedSize =
(panelGroupDefinition.left.initialExpandedOffsetWidth / panelGroupWidth) * 100;
const leftResizablePanelExpandedSize = getPercentageSize(
panelGroupDefinition.left.initialExpandedOffsetWidth
);
resizableLeftPanelAPIRef?.current?.expand(leftResizablePanelExpandedSize);
setMinMaxWidth(leftPanelElem, panelGroupDefinition.left.initialExpandedOffsetWidth);
}
if (!rightPanelClosed) {
const rightResizablePanelExpandedSize =
(panelGroupDefinition.right.initialExpandedOffsetWidth / panelGroupWidth) * 100;
const rightResizablePanelExpandedSize = getPercentageSize(
panelGroupDefinition.right.initialExpandedOffsetWidth
);
resizableRightPanelAPIRef?.current?.expand(rightResizablePanelExpandedSize);
setMinMaxWidth(rightPanelElem, panelGroupDefinition.right.initialExpandedOffsetWidth);
}
@@ -89,103 +99,47 @@ const useResizablePanels = (
// values whenever the resizable panel group is resized (e.g. whenever the
// browser window is resized).
useLayoutEffect(() => {
const { width: panelGroupWidth } = resizablePanelGroupElemRef.current.getBoundingClientRect();
// Ensure the side panels' percentage size is in synch with the pixel width of the
// expanded side panels. In general the two get out-of-sync during a browser
// window resize. Note that this code is here and NOT in the ResizeObserver
// because it has to be done AFTER the minimum percentage size for a panel is
// updated which occurs only AFTER the render following a resize. And by virtue
// of the dependency on the `resizablePanelDefaultSize` state, this code
// is executed on the render following an update of the minimum percentage size
// updated which occurs only AFTER the render following a browser window resize.
// And by virtue of the dependency on the minimum size state variables, this code
// is executed on the render following an update of the minimum percentage sizes
// for a panel.
if (!resizableLeftPanelAPIRef.current.isCollapsed()) {
const leftSize =
((leftPanelExpandedWidth + panelGroupDefinition.shared.expandedInsideBorderSize) /
panelGroupWidth) *
100;
resizableLeftPanelAPIRef.current.resize(leftSize);
if (!resizableLeftPanelAPIRef.current?.isCollapsed()) {
const leftSize = getPercentageSize(
leftPanelExpandedWidth + panelGroupDefinition.shared.expandedInsideBorderSize
);
resizableLeftPanelAPIRef.current?.resize(leftSize);
}
if (!resizableRightPanelAPIRef.current.isCollapsed()) {
const rightSize =
((rightPanelExpandedWidth + panelGroupDefinition.shared.expandedInsideBorderSize) /
panelGroupWidth) *
100;
resizableRightPanelAPIRef.current.resize(rightSize);
if (!resizableRightPanelAPIRef?.current?.isCollapsed()) {
const rightSize = getPercentageSize(
rightPanelExpandedWidth + panelGroupDefinition.shared.expandedInsideBorderSize
);
resizableRightPanelAPIRef?.current?.resize(rightSize);
}
// This observer kicks in when the ViewportLayout resizable panel group
// component is resized. This typically occurs when the browser window resizes.
const observer = new ResizeObserver(() => {
const { width: panelGroupWidth } = resizablePanelGroupElemRef.current.getBoundingClientRect();
const minimumLeftSize =
(panelGroupDefinition.left.minimumExpandedOffsetWidth / panelGroupWidth) * 100;
const minimumRightSize =
(panelGroupDefinition.right.minimumExpandedOffsetWidth / panelGroupWidth) * 100;
const minimumLeftSize = getPercentageSize(
panelGroupDefinition.left.minimumExpandedOffsetWidth
);
const minimumRightSize = getPercentageSize(
panelGroupDefinition.right.minimumExpandedOffsetWidth
);
// Set the new default and collapsed resizable panel sizes.
setLeftResizablePanelMinimumSize(Math.min(50, minimumLeftSize));
setRightResizablePanelMinimumSize(Math.min(50, minimumRightSize));
// Set the new minimum and collapsed resizable panel sizes.
setLeftResizablePanelMinimumSize(minimumLeftSize);
setRightResizablePanelMinimumSize(minimumRightSize);
setLeftResizePanelCollapsedSize(
(panelGroupDefinition.left.collapsedOffsetWidth / panelGroupWidth) * 100
getPercentageSize(panelGroupDefinition.left.collapsedOffsetWidth)
);
setRightResizePanelCollapsedSize(
(panelGroupDefinition.right.collapsedOffsetWidth / panelGroupWidth) * 100
getPercentageSize(panelGroupDefinition.right.collapsedOffsetWidth)
);
if (
resizableLeftPanelAPIRef.current.isCollapsed() &&
resizableRightPanelAPIRef.current.isCollapsed()
) {
return;
}
// The code that follows is to handle cases when the group panel is resized to be
// too small to display either side panel at its current width.
// Determine the current widths of the two side panels.
let leftPanelOffsetWidth = resizableLeftPanelAPIRef.current.isCollapsed()
? panelGroupDefinition.left.collapsedOffsetWidth
: leftPanelExpandedWidth + panelGroupDefinition.shared.expandedInsideBorderSize;
let rightPanelOffsetWidth = resizableRightPanelAPIRef.current.isCollapsed()
? panelGroupDefinition.right.collapsedOffsetWidth
: rightPanelExpandedWidth + panelGroupDefinition.shared.expandedInsideBorderSize;
if (
!resizableLeftPanelAPIRef.current.isCollapsed() &&
leftPanelOffsetWidth + rightPanelOffsetWidth > panelGroupWidth
) {
// There is not enough space to show both panels at their pre-resize widths.
// Note that at this point, the viewport grid component is zero width.
// Reduce the left panel width so that both panels might fit.
leftPanelOffsetWidth = Math.max(
panelGroupWidth - rightPanelOffsetWidth,
panelGroupDefinition.left.minimumExpandedOffsetWidth
);
setLeftPanelExpandedWidth(
leftPanelOffsetWidth - panelGroupDefinition.shared.expandedInsideBorderSize
);
setMinMaxWidth(resizableLeftPanelElemRef.current, leftPanelOffsetWidth);
}
if (
!resizableRightPanelAPIRef.current.isCollapsed() &&
rightPanelOffsetWidth + leftPanelOffsetWidth > panelGroupWidth
) {
// There is not enough space to show both panels at their pre-resize widths.
// Note that at this point, the viewport grid component is zero width.
// Reduce the right panel width so that both panels might fit.
rightPanelOffsetWidth = Math.max(
panelGroupWidth - leftPanelOffsetWidth,
panelGroupDefinition.right.minimumExpandedOffsetWidth
);
setRightPanelExpandedWidth(
rightPanelOffsetWidth - panelGroupDefinition.shared.expandedInsideBorderSize
);
setMinMaxWidth(resizableRightPanelElemRef.current, rightPanelOffsetWidth);
}
});
observer.observe(resizablePanelGroupElemRef.current);
@@ -238,23 +192,26 @@ const useResizablePanels = (
}, [setLeftPanelClosed]);
const onLeftPanelOpen = useCallback(() => {
const { width: panelGroupWidth } = resizablePanelGroupElemRef.current.getBoundingClientRect();
resizableLeftPanelAPIRef?.current?.expand(
(panelGroupDefinition.left.initialExpandedOffsetWidth / panelGroupWidth) * 100
getPercentageSize(panelGroupDefinition.left.initialExpandedOffsetWidth)
);
setLeftPanelClosed(false);
}, [setLeftPanelClosed]);
const onLeftPanelResize = useCallback(size => {
if (resizableLeftPanelAPIRef.current.isCollapsed()) {
if (!resizablePanelGroupElemRef?.current || resizableLeftPanelAPIRef.current?.isCollapsed()) {
return;
}
const { width: panelGroupWidth } = resizablePanelGroupElemRef.current.getBoundingClientRect();
const newExpandedWidth =
(size / 100) * panelGroupWidth - panelGroupDefinition.shared.expandedInsideBorderSize;
const newExpandedWidth = getExpandedPixelWidth(size);
setLeftPanelExpandedWidth(newExpandedWidth);
if (!isResizableHandleDraggingRef.current) {
// This typically gets executed when the left panel is expanded via one of the UI
// buttons. It is done here instead of in the onLeftPanelOpen method
// because here we know the size of the expanded panel.
setMinMaxWidth(resizableLeftPanelElemRef.current, newExpandedWidth);
}
}, []);
const onRightPanelClose = useCallback(() => {
@@ -264,25 +221,49 @@ const useResizablePanels = (
}, [setRightPanelClosed]);
const onRightPanelOpen = useCallback(() => {
const { width: panelGroupWidth } = resizablePanelGroupElemRef.current.getBoundingClientRect();
resizableRightPanelAPIRef?.current?.expand(
(panelGroupDefinition.right.initialExpandedOffsetWidth / panelGroupWidth) * 100
getPercentageSize(panelGroupDefinition.right.initialExpandedOffsetWidth)
);
setRightPanelClosed(false);
}, [setRightPanelClosed]);
const onRightPanelResize = useCallback(size => {
if (resizableRightPanelAPIRef?.current?.isCollapsed()) {
if (!resizablePanelGroupElemRef?.current || resizableRightPanelAPIRef?.current?.isCollapsed()) {
return;
}
const { width: panelGroupWidth } = resizablePanelGroupElemRef.current.getBoundingClientRect();
const newExpandedWidth =
(size / 100) * panelGroupWidth - panelGroupDefinition.shared.expandedInsideBorderSize;
const newExpandedWidth = getExpandedPixelWidth(size);
setRightPanelExpandedWidth(newExpandedWidth);
if (!isResizableHandleDraggingRef.current) {
// This typically gets executed when the right panel is expanded via one of the UI
// buttons. It is done here instead of in the onRightPanelOpen method
// because here we know the size of the expanded panel.
setMinMaxWidth(resizableRightPanelElemRef.current, newExpandedWidth);
}
}, []);
/**
* Gets the percentage size corresponding to the given pixel size.
* Note that the width attributed to the handles must be taken into account.
*/
const getPercentageSize = pixelSize => {
const { width: panelGroupWidth } = resizablePanelGroupElemRef.current?.getBoundingClientRect();
return (pixelSize / (panelGroupWidth - resizableHandlesWidth.current)) * 100;
};
/**
* Gets the width in pixels for an expanded panel given its percentage size/width.
* Note that the width attributed to the handles must be taken into account.
*/
const getExpandedPixelWidth = percentageSize => {
const { width: panelGroupWidth } = resizablePanelGroupElemRef.current?.getBoundingClientRect();
const expandedWidth =
(percentageSize / 100) * (panelGroupWidth - resizableHandlesWidth.current) -
panelGroupDefinition.shared.expandedInsideBorderSize;
return expandedWidth;
};
return [
{
expandedWidth: leftPanelExpandedWidth,
@@ -308,7 +289,7 @@ const useResizablePanels = (
minSize: leftResizablePanelMinimumSize,
onResize: onLeftPanelResize,
collapsible: true,
collapsedSize: leftResizeablePanelCollapsedSize,
collapsedSize: leftResizablePanelCollapsedSize,
onCollapse: () => setLeftPanelClosed(true),
onExpand: () => setLeftPanelClosed(false),
ref: resizableLeftPanelAPIRef,
@@ -1,6 +1,6 @@
const expandedInsideBorderSize = 4;
const expandedInsideBorderSize = 0;
const collapsedInsideBorderSize = 4;
const collapsedOutsideBorderSize = 8;
const collapsedOutsideBorderSize = 4;
const collapsedWidth = 25;
const rightPanelInitialExpandedWidth = 280;
+11 -5
View File
@@ -1,7 +1,7 @@
import React, { useEffect, useState, useCallback } from 'react';
import PropTypes from 'prop-types';
import { LoadingIndicatorProgress, InvestigationalUseDialog } from '@ohif/ui';
import { InvestigationalUseDialog } from '@ohif/ui';
import { HangingProtocolService, CommandsManager } from '@ohif/core';
import { useAppConfig } from '@state';
import ViewerHeader from './ViewerHeader';
@@ -9,6 +9,8 @@ import SidePanelWithServices from '../Components/SidePanelWithServices';
import { Onboarding, ResizablePanelGroup, ResizablePanel, ResizableHandle } from '@ohif/ui-next';
import useResizablePanels from './ResizablePanelsHook';
const resizableHandleClassName = 'mt-[1px] bg-black';
function ViewerLayout({
// From Extension Module Params
extensionManager,
@@ -25,7 +27,7 @@ function ViewerLayout({
}: withAppTypes): React.FunctionComponent {
const [appConfig] = useAppConfig();
const { panelService, hangingProtocolService } = servicesManager.services;
const { panelService, hangingProtocolService, customizationService } = servicesManager.services;
const [showLoadingIndicator, setShowLoadingIndicator] = useState(appConfig.showLoadingIndicator);
const hasPanels = useCallback(
@@ -53,6 +55,10 @@ function ViewerLayout({
setRightPanelClosed
);
const LoadingIndicatorProgress = customizationService.getCustomization(
'ui.loadingIndicatorProgress'
);
/**
* Set body classes (tailwindcss) that don't allow vertical
* or horizontal overflow (no scrolling). Also guarantee window
@@ -157,7 +163,7 @@ function ViewerLayout({
<ResizableHandle
onDragging={onHandleDragging}
disabled={!leftPanelResizable}
className="!w-0"
className={resizableHandleClassName}
/>
</>
) : null}
@@ -178,7 +184,7 @@ function ViewerLayout({
<ResizableHandle
onDragging={onHandleDragging}
disabled={!rightPanelResizable}
className="!w-0"
className={resizableHandleClassName}
/>
<ResizablePanel {...resizableRightPanelProps}>
<SidePanelWithServices
@@ -193,7 +199,7 @@ function ViewerLayout({
</ResizablePanelGroup>
</React.Fragment>
</div>
<Onboarding />
<Onboarding tours={customizationService.getCustomization('ohif.tours')} />
<InvestigationalUseDialog dialogConfiguration={appConfig?.investigationalUseDialog} />
</div>
);
@@ -0,0 +1,5 @@
import { ContextMenu } from '@ohif/ui';
export default {
'ui.contextMenu': ContextMenu,
};
@@ -0,0 +1,5 @@
import { defaults } from '@ohif/core';
export default {
'ohif.hotkeyBindings': defaults.hotkeyBindings,
};
@@ -0,0 +1,5 @@
import { LabellingFlow } from '@ohif/ui';
export default {
'ui.labellingComponent': LabellingFlow,
};
@@ -0,0 +1,5 @@
import { LoadingIndicatorProgress } from '@ohif/ui';
export default {
'ui.loadingIndicatorProgress': LoadingIndicatorProgress,
};
@@ -0,0 +1,5 @@
import { LoadingIndicatorTotalPercent } from '@ohif/ui';
export default {
'ui.loadingIndicatorTotalPercent': LoadingIndicatorTotalPercent,
};
@@ -0,0 +1,5 @@
import { Notification } from '@ohif/ui';
export default {
'ui.notificationComponent': Notification,
};
@@ -0,0 +1,5 @@
export default {
customOnDropHandler: () => {
return Promise.resolve({ handled: false });
},
};
@@ -0,0 +1,210 @@
function waitForElement(selector, maxAttempts = 20, interval = 25) {
return new Promise(resolve => {
let attempts = 0;
const checkForElement = setInterval(() => {
const element = document.querySelector(selector);
if (element || attempts >= maxAttempts) {
clearInterval(checkForElement);
resolve();
}
attempts++;
}, interval);
});
}
export default {
'ohif.tours': [
{
id: 'basicViewerTour',
route: '/viewer',
steps: [
{
id: 'scroll',
title: 'Scrolling Through Images',
text: 'You can scroll through the images using the mouse wheel or scrollbar.',
attachTo: {
element: '.viewport-element',
on: 'top',
},
advanceOn: {
selector: '.cornerstone-viewport-element',
event: 'CORNERSTONE_TOOLS_MOUSE_WHEEL',
},
beforeShowPromise: () => waitForElement('.viewport-element'),
},
{
id: 'zoom',
title: 'Zooming In and Out',
text: 'You can zoom the images using the right click.',
attachTo: {
element: '.viewport-element',
on: 'left',
},
advanceOn: {
selector: '.cornerstone-viewport-element',
event: 'CORNERSTONE_TOOLS_MOUSE_UP',
},
beforeShowPromise: () => waitForElement('.viewport-element'),
},
{
id: 'pan',
title: 'Panning the Image',
text: 'You can pan the images using the middle click.',
attachTo: {
element: '.viewport-element',
on: 'top',
},
advanceOn: {
selector: '.cornerstone-viewport-element',
event: 'CORNERSTONE_TOOLS_MOUSE_UP',
},
beforeShowPromise: () => waitForElement('.viewport-element'),
},
{
id: 'windowing',
title: 'Adjusting Window Level',
text: 'You can modify the window level using the left click.',
attachTo: {
element: '.viewport-element',
on: 'left',
},
advanceOn: {
selector: '.cornerstone-viewport-element',
event: 'CORNERSTONE_TOOLS_MOUSE_UP',
},
beforeShowPromise: () => waitForElement('.viewport-element'),
},
{
id: 'length',
title: 'Using the Measurement Tools',
text: 'You can measure the length of a region using the Length tool.',
attachTo: {
element: '[data-cy="MeasurementTools-split-button-primary"]',
on: 'bottom',
},
advanceOn: {
selector: '[data-cy="MeasurementTools-split-button-primary"]',
event: 'click',
},
beforeShowPromise: () =>
waitForElement('[data-cy="MeasurementTools-split-button-primary]'),
},
{
id: 'drawAnnotation',
title: 'Drawing Length Annotations',
text: 'Use the length tool on the viewport to measure the length of a region.',
attachTo: {
element: '.viewport-element',
on: 'right',
},
advanceOn: {
selector: 'body',
event: 'event::measurement_added',
},
beforeShowPromise: () => waitForElement('.viewport-element'),
},
{
id: 'trackMeasurement',
title: 'Tracking Measurements in the Panel',
text: 'Click yes to track the measurements in the measurement panel.',
attachTo: {
element: '[data-cy="prompt-begin-tracking-yes-btn"]',
on: 'bottom',
},
advanceOn: {
selector: '[data-cy="prompt-begin-tracking-yes-btn"]',
event: 'click',
},
beforeShowPromise: () => waitForElement('[data-cy="prompt-begin-tracking-yes-btn"]'),
},
{
id: 'openMeasurementPanel',
title: 'Opening the Measurements Panel',
text: 'Click the measurements button to open the measurements panel.',
attachTo: {
element: '#trackedMeasurements-btn',
on: 'left-start',
},
advanceOn: {
selector: '#trackedMeasurements-btn',
event: 'click',
},
beforeShowPromise: () => waitForElement('#trackedMeasurements-btn'),
},
{
id: 'scrollAwayFromMeasurement',
title: 'Scrolling Away from a Measurement',
text: 'Scroll the images using the mouse wheel away from the measurement.',
attachTo: {
element: '.viewport-element',
on: 'left',
},
advanceOn: {
selector: '.cornerstone-viewport-element',
event: 'CORNERSTONE_TOOLS_MOUSE_WHEEL',
},
beforeShowPromise: () => waitForElement('.viewport-element'),
},
{
id: 'jumpToMeasurement',
title: 'Jumping to Measurements in the Panel',
text: 'Click the measurement in the measurement panel to jump to it.',
attachTo: {
element: '[data-cy="data-row"]',
on: 'left-start',
},
advanceOn: {
selector: '[data-cy="data-row"]',
event: 'click',
},
beforeShowPromise: () => waitForElement('[data-cy="data-row"]'),
},
{
id: 'changeLayout',
title: 'Changing Layout',
text: 'You can change the layout of the viewer using the layout button.',
attachTo: {
element: '[data-cy="Layout"]',
on: 'bottom',
},
advanceOn: {
selector: '[data-cy="Layout"]',
event: 'click',
},
beforeShowPromise: () => waitForElement('[data-cy="Layout"]'),
},
{
id: 'selectLayout',
title: 'Selecting the MPR Layout',
text: 'Select the MPR layout to view the images in MPR mode.',
attachTo: {
element: '[data-cy="MPR"]',
on: 'left-start',
},
advanceOn: {
selector: '[data-cy="MPR"]',
event: 'click',
},
beforeShowPromise: () => waitForElement('[data-cy="MPR"]'),
},
],
tourOptions: {
useModalOverlay: true,
defaultStepOptions: {
buttons: [
{
text: 'Skip all',
action() {
this.complete();
},
secondary: true,
},
],
},
},
},
],
};
@@ -0,0 +1,5 @@
import { ProgressLoadingBar } from '@ohif/ui';
export default {
'ui.progressLoadingBar': ProgressLoadingBar,
};
@@ -8,7 +8,11 @@ export default {
id: 'tagBrowser',
label: 'Tag Browser',
iconName: 'DicomTagBrowser',
commands: 'openDICOMTagViewer',
onClick: ({ commandsManager, displaySetInstanceUID }: withAppTypes) => {
commandsManager.runCommand('openDICOMTagViewer', {
displaySetInstanceUID,
});
},
},
],
'studyBrowser.sortFunctions': [
@@ -0,0 +1,5 @@
import { ViewportActionCorners } from '@ohif/ui';
export default {
'ui.viewportActionCorner': ViewportActionCorners,
};
@@ -6,11 +6,20 @@ import customRoutesCustomization from './customizations/customRoutesCustomizatio
import studyBrowserCustomization from './customizations/studyBrowserCustomization';
import overlayItemCustomization from './customizations/overlayItemCustomization';
import contextMenuCustomization from './customizations/contextMenuCustomization';
import contextMenuUICustomization from './customizations/contextMenuUICustomization';
import menuContentCustomization from './customizations/menuContentCustomization';
import getDataSourceConfigurationCustomization from './customizations/dataSourceConfigurationCustomization';
import progressDropdownCustomization from './customizations/progressDropdownCustomization';
import sortingCriteriaCustomization from './customizations/sortingCriteriaCustomization';
import onDropHandlerCustomization from './customizations/onDropHandlerCustomization';
import loadingIndicatorProgressCustomization from './customizations/loadingIndicatorProgressCustomization';
import loadingIndicatorTotalPercentCustomization from './customizations/loadingIndicatorTotalPercentCustomization';
import progressLoadingBarCustomization from './customizations/progressLoadingBarCustomization';
import viewportActionCornersCustomization from './customizations/viewportActionCornersCustomization';
import labellingFlowCustomization from './customizations/labellingFlowCustomization';
import viewportNotificationCustomization from './customizations/notificationCustomization';
import hotkeyBindingsCustomization from './customizations/hotkeyBindingsCustomization';
import onboardingCustomization from './customizations/onboardingCustomization';
/**
*
* Note: this is an example of how the customization module can be used
@@ -46,6 +55,16 @@ export default function getCustomizationModule({ servicesManager, extensionManag
...progressDropdownCustomization,
...sortingCriteriaCustomization,
...defaultContextMenuCustomization,
...onDropHandlerCustomization,
...loadingIndicatorProgressCustomization,
...loadingIndicatorTotalPercentCustomization,
...progressLoadingBarCustomization,
...viewportActionCornersCustomization,
...labellingFlowCustomization,
...contextMenuUICustomization,
...viewportNotificationCustomization,
...hotkeyBindingsCustomization,
...onboardingCustomization,
},
},
];
+40 -19
View File
@@ -1,42 +1,61 @@
import ToolbarDivider from './Toolbar/ToolbarDivider';
import { ToolbarButton as ToolbarButtonLegacy } from '@ohif/ui';
import { ToolButton, utils } from '@ohif/ui-next';
import ToolbarLayoutSelectorWithServices from './Toolbar/ToolbarLayoutSelector';
import ToolbarSplitButtonWithServices from './Toolbar/ToolbarSplitButtonWithServices';
import ToolbarButtonGroupWithServices from './Toolbar/ToolbarButtonGroupWithServices';
import { ToolbarButton } from '@ohif/ui';
// legacy
import ToolbarDividerLegacy from './Toolbar/ToolbarDivider';
import ToolbarSplitButtonWithServicesLegacy from './Toolbar/ToolbarSplitButtonWithServices';
import ToolbarButtonGroupWithServicesLegacy from './Toolbar/ToolbarButtonGroupWithServices';
import { ProgressDropdownWithService } from './Components/ProgressDropdownWithService';
const getClassName = isToggled => {
return {
className: isToggled
? '!text-primary-active'
: '!text-common-bright hover:!bg-primary-dark hover:text-primary-light',
};
};
// new
import ToolButtonListWrapper from './Toolbar/ToolButtonListWrapper';
import { ToolBoxButtonGroupWrapper, ToolBoxButtonWrapper } from './Toolbar/ToolBoxWrapper';
export default function getToolbarModule({ commandsManager, servicesManager }: withAppTypes) {
const { cineService } = servicesManager.services;
return [
// new
{
name: 'ohif.toolButton',
defaultComponent: ToolButton,
},
{
name: 'ohif.toolButtonList',
defaultComponent: ToolButtonListWrapper,
},
{
name: 'ohif.toolBoxButtonGroup',
defaultComponent: ToolBoxButtonGroupWrapper,
},
{
name: 'ohif.toolBoxButton',
defaultComponent: ToolBoxButtonWrapper,
},
// legacy
{
name: 'ohif.radioGroup',
defaultComponent: ToolbarButton,
defaultComponent: ToolbarButtonLegacy,
},
{
name: 'ohif.buttonGroup',
defaultComponent: ToolbarButtonGroupWithServicesLegacy,
},
{
name: 'ohif.divider',
defaultComponent: ToolbarDivider,
defaultComponent: ToolbarDividerLegacy,
},
{
name: 'ohif.splitButton',
defaultComponent: ToolbarSplitButtonWithServices,
defaultComponent: ToolbarSplitButtonWithServicesLegacy,
},
// others
{
name: 'ohif.layoutSelector',
defaultComponent: props =>
ToolbarLayoutSelectorWithServices({ ...props, commandsManager, servicesManager }),
},
{
name: 'ohif.buttonGroup',
defaultComponent: ToolbarButtonGroupWithServices,
},
{
name: 'ohif.progressDropdown',
defaultComponent: ProgressDropdownWithService,
@@ -66,7 +85,9 @@ export default function getToolbarModule({ commandsManager, servicesManager }: w
name: 'evaluate.cine',
evaluate: () => {
const isToggled = cineService.getState().isCineEnabled;
return getClassName(isToggled);
return {
className: utils.getToggledClassName(isToggled),
};
},
},
];
@@ -13,9 +13,8 @@ function usePatientInfo(servicesManager: AppTypes.ServicesManager) {
PatientDOB: '',
});
const [isMixedPatients, setIsMixedPatients] = useState(false);
const displaySets = displaySetService.getActiveDisplaySets();
const checkMixedPatients = PatientID => {
const checkMixedPatients = (PatientID: string) => {
const displaySets = displaySetService.getActiveDisplaySets();
let isMixedPatients = false;
displaySets.forEach(displaySet => {
@@ -30,8 +29,11 @@ function usePatientInfo(servicesManager: AppTypes.ServicesManager) {
setIsMixedPatients(isMixedPatients);
};
const updatePatientInfo = () => {
const displaySet = displaySets[0];
const updatePatientInfo = ({ displaySetsAdded }) => {
if (!displaySetsAdded.length) {
return;
}
const displaySet = displaySetsAdded[0];
const instance = displaySet?.instances?.[0] || displaySet?.instance;
if (!instance) {
return;
@@ -39,7 +41,7 @@ function usePatientInfo(servicesManager: AppTypes.ServicesManager) {
setPatientInfo({
PatientID: instance.PatientID || null,
PatientName: instance.PatientName ? formatPN(instance.PatientName ) : null,
PatientName: instance.PatientName ? formatPN(instance.PatientName) : null,
PatientSex: instance.PatientSex || null,
PatientDOB: formatDate(instance.PatientBirthDate) || null,
});
@@ -49,15 +51,11 @@ function usePatientInfo(servicesManager: AppTypes.ServicesManager) {
useEffect(() => {
const subscription = displaySetService.subscribe(
displaySetService.EVENTS.DISPLAY_SETS_ADDED,
() => updatePatientInfo()
props => updatePatientInfo(props)
);
return () => subscription.unsubscribe();
}, []);
useEffect(() => {
updatePatientInfo();
}, [displaySets]);
return { patientInfo, isMixedPatients };
}
-1
View File
@@ -39,7 +39,6 @@ import { PanelStudyBrowserHeader } from './Panels/StudyBrowser/PanelStudyBrowser
import * as utils from './utils';
import MoreDropdownMenu from './Components/MoreDropdownMenu';
import requestDisplaySetCreationForStudy from './Panels/requestDisplaySetCreationForStudy';
const defaultExtension: Types.Extensions.Extension = {
/**
* Only required property. Should be a unique value across all extensions.
@@ -89,7 +89,13 @@ export function callInputDialog(
}
}
export function callLabelAutocompleteDialog(uiDialogService, callback, dialogConfig, labelConfig) {
export function callLabelAutocompleteDialog(
uiDialogService,
callback,
dialogConfig,
labelConfig,
renderContent = LabellingFlow
) {
const exclusive = labelConfig ? labelConfig.exclusive : false;
const dropDownItems = labelConfig ? labelConfig.items : [];
@@ -112,7 +118,7 @@ export function callLabelAutocompleteDialog(uiDialogService, callback, dialogCon
centralize: true,
isDraggable: false,
showOverlay: true,
content: LabellingFlow,
content: renderContent,
contentProps: {
labellingDoneCallback: labellingDoneCallback,
measurementData: { label: '' },
@@ -123,7 +129,12 @@ export function callLabelAutocompleteDialog(uiDialogService, callback, dialogCon
});
}
export function showLabelAnnotationPopup(measurement, uiDialogService, labelConfig) {
export function showLabelAnnotationPopup(
measurement,
uiDialogService,
labelConfig,
renderContent = LabellingFlow
) {
const exclusive = labelConfig ? labelConfig.exclusive : false;
const dropDownItems = labelConfig ? labelConfig.items : [];
return new Promise<Map<any, any>>((resolve, reject) => {
@@ -139,7 +150,7 @@ export function showLabelAnnotationPopup(measurement, uiDialogService, labelConf
id: 'select-annotation',
isDraggable: false,
showOverlay: true,
content: LabellingFlow,
content: renderContent,
defaultPosition: {
x: window.innerWidth / 2,
y: window.innerHeight / 2,
@@ -1,30 +1,42 @@
import { showLabelAnnotationPopup } from './callInputDialog';
function promptLabelAnnotation({ servicesManager }, ctx, evt) {
const { measurementService, customizationService } = servicesManager.services;
const { viewportId, StudyInstanceUID, SeriesInstanceUID, measurementId } = evt;
const { measurementService, customizationService, toolGroupService } = servicesManager.services;
const { viewportId, StudyInstanceUID, SeriesInstanceUID, measurementId, toolName } = evt;
return new Promise(async function (resolve) {
const labelConfig = customizationService.getCustomization('measurementLabels');
const measurement = measurementService.getMeasurement(measurementId);
const value = await showLabelAnnotationPopup(
measurement,
servicesManager.services.uiDialogService,
labelConfig
);
const toolGroup = toolGroupService.getToolGroupForViewport(viewportId);
const activeToolOptions = toolGroup.getToolConfiguration(toolName);
if(activeToolOptions.getTextCallback) {
resolve({
StudyInstanceUID,
SeriesInstanceUID,
viewportId,
})
} else {
const labelConfig = customizationService.getCustomization('measurementLabels');
const measurement = measurementService.getMeasurement(measurementId);
const renderContent = customizationService.getCustomization('ui.labellingComponent');
const value = await showLabelAnnotationPopup(
measurement,
servicesManager.services.uiDialogService,
labelConfig,
renderContent
);
measurementService.update(
measurementId,
{
...value,
},
true
);
measurementService.update(
measurementId,
{
...value,
},
true
);
resolve({
StudyInstanceUID,
SeriesInstanceUID,
viewportId,
});
resolve({
StudyInstanceUID,
SeriesInstanceUID,
viewportId,
});
}
});
}
@@ -45,6 +45,10 @@ export default function areAllImagePositionsEqual(instances: Array<any>): boolea
const firstImagePositionPatient = toNumber(instances[0].ImagePositionPatient);
const lastIpp = toNumber(instances[instances.length - 1].ImagePositionPatient);
if (!firstImagePositionPatient || !lastIpp) {
return false;
}
const averageSpacingBetweenFrames =
_getPerpendicularDistance(firstImagePositionPatient, lastIpp) / (instances.length - 1);
+292
View File
@@ -3,6 +3,298 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
# [3.10.0-beta.112](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.111...v3.10.0-beta.112) (2025-02-28)
**Note:** Version bump only for package @ohif/extension-dicom-microscopy
# [3.10.0-beta.111](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.110...v3.10.0-beta.111) (2025-02-26)
**Note:** Version bump only for package @ohif/extension-dicom-microscopy
# [3.10.0-beta.110](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.109...v3.10.0-beta.110) (2025-02-26)
**Note:** Version bump only for package @ohif/extension-dicom-microscopy
# [3.10.0-beta.109](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.108...v3.10.0-beta.109) (2025-02-25)
**Note:** Version bump only for package @ohif/extension-dicom-microscopy
# [3.10.0-beta.108](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.107...v3.10.0-beta.108) (2025-02-25)
**Note:** Version bump only for package @ohif/extension-dicom-microscopy
# [3.10.0-beta.107](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.106...v3.10.0-beta.107) (2025-02-25)
**Note:** Version bump only for package @ohif/extension-dicom-microscopy
# [3.10.0-beta.106](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.105...v3.10.0-beta.106) (2025-02-25)
**Note:** Version bump only for package @ohif/extension-dicom-microscopy
# [3.10.0-beta.105](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.104...v3.10.0-beta.105) (2025-02-25)
**Note:** Version bump only for package @ohif/extension-dicom-microscopy
# [3.10.0-beta.104](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.103...v3.10.0-beta.104) (2025-02-25)
**Note:** Version bump only for package @ohif/extension-dicom-microscopy
# [3.10.0-beta.103](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.102...v3.10.0-beta.103) (2025-02-23)
**Note:** Version bump only for package @ohif/extension-dicom-microscopy
# [3.10.0-beta.102](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.101...v3.10.0-beta.102) (2025-02-20)
**Note:** Version bump only for package @ohif/extension-dicom-microscopy
# [3.10.0-beta.101](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.100...v3.10.0-beta.101) (2025-02-20)
**Note:** Version bump only for package @ohif/extension-dicom-microscopy
# [3.10.0-beta.100](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.99...v3.10.0-beta.100) (2025-02-19)
**Note:** Version bump only for package @ohif/extension-dicom-microscopy
# [3.10.0-beta.99](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.98...v3.10.0-beta.99) (2025-02-18)
**Note:** Version bump only for package @ohif/extension-dicom-microscopy
# [3.10.0-beta.98](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.97...v3.10.0-beta.98) (2025-02-18)
### Bug Fixes
* lodash dependencies ([#4791](https://github.com/OHIF/Viewers/issues/4791)) ([4e16099](https://github.com/OHIF/Viewers/commit/4e16099ad3ab777b09f6ac8f181025cfd656ab6b))
# [3.10.0-beta.97](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.96...v3.10.0-beta.97) (2025-02-18)
**Note:** Version bump only for package @ohif/extension-dicom-microscopy
# [3.10.0-beta.96](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.95...v3.10.0-beta.96) (2025-02-18)
**Note:** Version bump only for package @ohif/extension-dicom-microscopy
# [3.10.0-beta.95](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.94...v3.10.0-beta.95) (2025-02-13)
**Note:** Version bump only for package @ohif/extension-dicom-microscopy
# [3.10.0-beta.94](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.93...v3.10.0-beta.94) (2025-02-11)
### Features
* add viewport overlays to microscopy mode ([#4776](https://github.com/OHIF/Viewers/issues/4776)) ([084a10f](https://github.com/OHIF/Viewers/commit/084a10f7835acab6a851922850c474bc9c7b864b))
# [3.10.0-beta.93](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.92...v3.10.0-beta.93) (2025-02-04)
**Note:** Version bump only for package @ohif/extension-dicom-microscopy
# [3.10.0-beta.92](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.91...v3.10.0-beta.92) (2025-02-04)
### Bug Fixes
* **core:** Address 3D reconstruction and Android compatibility issues and clean up 4D data mode ([#4762](https://github.com/OHIF/Viewers/issues/4762)) ([149d6d0](https://github.com/OHIF/Viewers/commit/149d6d049cd333b9e5846576b403ff387558a66f))
# [3.10.0-beta.91](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.90...v3.10.0-beta.91) (2025-02-04)
**Note:** Version bump only for package @ohif/extension-dicom-microscopy
# [3.10.0-beta.90](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.89...v3.10.0-beta.90) (2025-02-04)
**Note:** Version bump only for package @ohif/extension-dicom-microscopy
# [3.10.0-beta.89](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.88...v3.10.0-beta.89) (2025-02-04)
**Note:** Version bump only for package @ohif/extension-dicom-microscopy
# [3.10.0-beta.88](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.87...v3.10.0-beta.88) (2025-02-04)
**Note:** Version bump only for package @ohif/extension-dicom-microscopy
# [3.10.0-beta.87](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.86...v3.10.0-beta.87) (2025-02-03)
**Note:** Version bump only for package @ohif/extension-dicom-microscopy
# [3.10.0-beta.86](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.85...v3.10.0-beta.86) (2025-02-03)
**Note:** Version bump only for package @ohif/extension-dicom-microscopy
# [3.10.0-beta.85](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.84...v3.10.0-beta.85) (2025-02-03)
### Features
* Add customization support for more UI components ([#4634](https://github.com/OHIF/Viewers/issues/4634)) ([f15eb44](https://github.com/OHIF/Viewers/commit/f15eb44b4cf49de1b73a22512571cec02effaef3))
# [3.10.0-beta.84](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.83...v3.10.0-beta.84) (2025-01-31)
**Note:** Version bump only for package @ohif/extension-dicom-microscopy
# [3.10.0-beta.83](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.82...v3.10.0-beta.83) (2025-01-31)
**Note:** Version bump only for package @ohif/extension-dicom-microscopy
# [3.10.0-beta.82](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.81...v3.10.0-beta.82) (2025-01-31)
**Note:** Version bump only for package @ohif/extension-dicom-microscopy
# [3.10.0-beta.81](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.80...v3.10.0-beta.81) (2025-01-29)
**Note:** Version bump only for package @ohif/extension-dicom-microscopy
# [3.10.0-beta.80](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.79...v3.10.0-beta.80) (2025-01-29)
**Note:** Version bump only for package @ohif/extension-dicom-microscopy
# [3.10.0-beta.79](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.78...v3.10.0-beta.79) (2025-01-28)
**Note:** Version bump only for package @ohif/extension-dicom-microscopy
# [3.10.0-beta.78](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.77...v3.10.0-beta.78) (2025-01-28)
**Note:** Version bump only for package @ohif/extension-dicom-microscopy
# [3.10.0-beta.77](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.76...v3.10.0-beta.77) (2025-01-28)
**Note:** Version bump only for package @ohif/extension-dicom-microscopy
+6 -5
View File
@@ -1,6 +1,6 @@
{
"name": "@ohif/extension-dicom-microscopy",
"version": "3.10.0-beta.77",
"version": "3.10.0-beta.112",
"description": "OHIF extension for DICOM microscopy",
"author": "Bill Wallace, md-prog",
"license": "MIT",
@@ -30,10 +30,10 @@
"start": "yarn run dev"
},
"peerDependencies": {
"@ohif/core": "3.10.0-beta.77",
"@ohif/extension-default": "3.10.0-beta.77",
"@ohif/i18n": "3.10.0-beta.77",
"@ohif/ui": "3.10.0-beta.77",
"@ohif/core": "3.10.0-beta.112",
"@ohif/extension-default": "3.10.0-beta.112",
"@ohif/i18n": "3.10.0-beta.112",
"@ohif/ui": "3.10.0-beta.112",
"prop-types": "^15.6.2",
"react": "^18.3.1",
"react-dom": "^18.3.1",
@@ -47,6 +47,7 @@
"@cornerstonejs/codec-libjpeg-turbo-8bit": "^1.2.2",
"@cornerstonejs/codec-openjpeg": "^1.2.4",
"colormap": "^2.3",
"lodash.debounce": "^4.0.8",
"mathjs": "^12.4.2"
}
}
@@ -1,314 +1,258 @@
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { LoadingIndicatorProgress } from '@ohif/ui';
import React, { useCallback, useEffect, useRef, useState } from 'react';
import { cleanDenaturalizedDataset } from '@ohif/extension-default';
import './DicomMicroscopyViewport.css';
import ViewportOverlay from './components/ViewportOverlay';
import getDicomWebClient from './utils/dicomWebClient';
import dcmjs from 'dcmjs';
import MicroscopyService from './services/MicroscopyService';
import { useSystem } from '@ohif/core';
class DicomMicroscopyViewport extends Component {
state = {
error: null as any,
isLoaded: false,
};
function DicomMicroscopyViewport({
activeViewportId,
setViewportActive,
displaySets,
viewportId,
dataSource,
resizeRef,
}: {
activeViewportId: string;
setViewportActive: Function;
displaySets: any[];
viewportId: string;
dataSource: any;
resizeRef: any;
}) {
const { servicesManager, extensionManager } = useSystem();
const [isLoaded, setIsLoaded] = useState(false);
const [viewer, setViewer] = useState(null);
const [managedViewer, setManagedViewer] = useState(null);
const overlayElement = useRef();
const container = useRef();
const { microscopyService, customizationService } = servicesManager.services;
microscopyService: MicroscopyService;
viewer: any = null; // dicom-microscopy-viewer instance
managedViewer: any = null; // managed wrapper of microscopy-dicom extension
container = React.createRef();
overlayElement = React.createRef();
constructor(props: any) {
super(props);
const { microscopyService } = this.props.servicesManager.services;
this.microscopyService = microscopyService;
}
static propTypes = {
viewportData: PropTypes.object,
activeViewportId: PropTypes.string,
setViewportActive: PropTypes.func,
// props from OHIF Viewport Grid
displaySets: PropTypes.array,
viewportId: PropTypes.string,
viewportLabel: PropTypes.string,
dataSource: PropTypes.object,
viewportOptions: PropTypes.object,
displaySetOptions: PropTypes.array,
// other props from wrapping component
servicesManager: PropTypes.object,
extensionManager: PropTypes.object,
commandsManager: PropTypes.object,
resizeRef: PropTypes.oneOfType([PropTypes.func, PropTypes.shape({ current: PropTypes.any })]),
};
/**
* Get the nearest ROI from the mouse click point
*
* @param event
* @param autoselect
* @returns
*/
getNearbyROI(event: Event, autoselect = true) {
const symbols = Object.getOwnPropertySymbols(this.viewer);
const _drawingSource = symbols.find(p => p.description === 'drawingSource');
const _pyramid = symbols.find(p => p.description === 'pyramid');
const _map = symbols.find(p => p.description === 'map');
const _affine = symbols.find(p => p.description === 'affine');
const feature = this.viewer[_drawingSource].getClosestFeatureToCoordinate(
this.viewer[_map].getEventCoordinate(event)
);
if (!feature) {
return null;
}
const roiAnnotation = this.viewer._getROIFromFeature(
feature,
this.viewer[_pyramid].metadata,
this.viewer[_affine]
);
if (roiAnnotation && autoselect) {
this.microscopyService.selectAnnotation(roiAnnotation);
}
return roiAnnotation;
}
const overlayData = customizationService.getCustomization('microscopyViewport.overlay');
// install the microscopy renderer into the web page.
// you should only do this once.
async installOpenLayersRenderer(container, displaySet) {
const loadViewer = async metadata => {
const dicomMicroscopyModule = await this.microscopyService.importDicomMicroscopyViewer();
const { viewer: DicomMicroscopyViewer, metadata: metadataUtils } = dicomMicroscopyModule;
const installOpenLayersRenderer = useCallback(
async (container, displaySet) => {
const loadViewer = async metadata => {
const dicomMicroscopyModule = await microscopyService.importDicomMicroscopyViewer();
const { viewer: DicomMicroscopyViewer, metadata: metadataUtils } = dicomMicroscopyModule;
const microscopyViewer = DicomMicroscopyViewer.VolumeImageViewer;
const microscopyViewer = DicomMicroscopyViewer.VolumeImageViewer;
const client = getDicomWebClient({
extensionManager: this.props.extensionManager,
servicesManager: this.props.servicesManager,
});
// Parse, format, and filter metadata
const volumeImages: any[] = [];
/**
* This block of code is the original way of loading DICOM into dicom-microscopy-viewer
* as in their documentation.
* But we have the metadata already loaded by our loaders.
* As the metadata for microscopy DIOM files tends to be big and we don't
* want to double load it, below we have the mechanism to reconstruct the
* DICOM JSON structure (denaturalized) from naturalized metadata.
* (NOTE: Our loaders cache only naturalized metadata, not the denaturalized.)
*/
// {
// const retrieveOptions = {
// studyInstanceUID: metadata[0].StudyInstanceUID,
// seriesInstanceUID: metadata[0].SeriesInstanceUID,
// };
// metadata = await client.retrieveSeriesMetadata(retrieveOptions);
// // Parse, format, and filter metadata
// metadata.forEach(m => {
// if (
// volumeImages.length > 0 &&
// m['00200052'].Value[0] != volumeImages[0].FrameOfReferenceUID
// ) {
// console.warn(
// 'Expected FrameOfReferenceUID of difference instances within a series to be the same, found multiple different values',
// m['00200052'].Value[0]
// );
// m['00200052'].Value[0] = volumeImages[0].FrameOfReferenceUID;
// }
// NOTE: depending on different data source, image.ImageType sometimes
// is a string, not a string array.
// m['00080008'] = transformImageTypeUnnaturalized(m['00080008']);
// const image = new metadataUtils.VLWholeSlideMicroscopyImage({
// metadata: m,
// });
// const imageFlavor = image.ImageType[2];
// if (imageFlavor === 'VOLUME' || imageFlavor === 'THUMBNAIL') {
// volumeImages.push(image);
// }
// });
// }
metadata.forEach(m => {
// NOTE: depending on different data source, image.ImageType sometimes
// is a string, not a string array.
m.ImageType = typeof m.ImageType === 'string' ? m.ImageType.split('\\') : m.ImageType;
const inst = cleanDenaturalizedDataset(
dcmjs.data.DicomMetaDictionary.denaturalizeDataset(m),
{
StudyInstanceUID: m.StudyInstanceUID,
SeriesInstanceUID: m.SeriesInstanceUID,
dataSourceConfig: this.props.dataSource.getConfig(),
}
);
if (!inst['00480105']) {
// Optical Path Sequence, no OpticalPathIdentifier?
// NOTE: this is actually a not-well formatted DICOM VL Whole Slide Microscopy Image.
inst['00480105'] = {
vr: 'SQ',
Value: [
{
'00480106': {
vr: 'SH',
Value: ['1'],
},
},
],
};
}
const image = new metadataUtils.VLWholeSlideMicroscopyImage({
metadata: inst,
const client = getDicomWebClient({
extensionManager,
servicesManager,
});
const imageFlavor = image.ImageType[2];
if (imageFlavor === 'VOLUME' || imageFlavor === 'THUMBNAIL') {
volumeImages.push(image);
}
});
// Parse, format, and filter metadata
const volumeImages: any[] = [];
// format metadata for microscopy-viewer
const options = {
client,
metadata: volumeImages,
retrieveRendered: false,
controls: ['overview', 'position'],
/**
* This block of code is the original way of loading DICOM into dicom-microscopy-viewer
* as in their documentation.
* But we have the metadata already loaded by our loaders.
* As the metadata for microscopy DIOM files tends to be big and we don't
* want to double load it, below we have the mechanism to reconstruct the
* DICOM JSON structure (denaturalized) from naturalized metadata.
* (NOTE: Our loaders cache only naturalized metadata, not the denaturalized.)
*/
// {
// const retrieveOptions = {
// studyInstanceUID: metadata[0].StudyInstanceUID,
// seriesInstanceUID: metadata[0].SeriesInstanceUID,
// };
// metadata = await client.retrieveSeriesMetadata(retrieveOptions);
// // Parse, format, and filter metadata
// metadata.forEach(m => {
// if (
// volumeImages.length > 0 &&
// m['00200052'].Value[0] != volumeImages[0].FrameOfReferenceUID
// ) {
// console.warn(
// 'Expected FrameOfReferenceUID of difference instances within a series to be the same, found multiple different values',
// m['00200052'].Value[0]
// );
// m['00200052'].Value[0] = volumeImages[0].FrameOfReferenceUID;
// }
// NOTE: depending on different data source, image.ImageType sometimes
// is a string, not a string array.
// m['00080008'] = transformImageTypeUnnaturalized(m['00080008']);
// const image = new metadataUtils.VLWholeSlideMicroscopyImage({
// metadata: m,
// });
// const imageFlavor = image.ImageType[2];
// if (imageFlavor === 'VOLUME' || imageFlavor === 'THUMBNAIL') {
// volumeImages.push(image);
// }
// });
// }
metadata.forEach(m => {
// NOTE: depending on different data source, image.ImageType sometimes
// is a string, not a string array.
m.ImageType = typeof m.ImageType === 'string' ? m.ImageType.split('\\') : m.ImageType;
const inst = cleanDenaturalizedDataset(
dcmjs.data.DicomMetaDictionary.denaturalizeDataset(m),
{
StudyInstanceUID: m.StudyInstanceUID,
SeriesInstanceUID: m.SeriesInstanceUID,
dataSourceConfig: dataSource.getConfig(),
}
);
if (!inst['00480105']) {
// Optical Path Sequence, no OpticalPathIdentifier?
// NOTE: this is actually a not-well formatted DICOM VL Whole Slide Microscopy Image.
inst['00480105'] = {
vr: 'SQ',
Value: [
{
'00480106': {
vr: 'SH',
Value: ['1'],
},
},
],
};
}
const image = new metadataUtils.VLWholeSlideMicroscopyImage({
metadata: inst,
});
const imageFlavor = image.ImageType[2];
if (imageFlavor === 'VOLUME' || imageFlavor === 'THUMBNAIL') {
volumeImages.push(image);
}
});
// format metadata for microscopy-viewer
const options = {
client,
metadata: volumeImages,
retrieveRendered: false,
controls: ['overview', 'position'],
};
const viewer = new microscopyViewer(options);
if (overlayElement && overlayElement.current && viewer.addViewportOverlay) {
viewer.addViewportOverlay({
element: overlayElement.current,
coordinates: [0, 0], // TODO: dicom-microscopy-viewer documentation says this can be false to be automatically, but it is not.
navigate: true,
className: 'OpenLayersOverlay',
});
}
viewer.render({ container });
const { StudyInstanceUID, SeriesInstanceUID } = displaySet;
const managedViewer = microscopyService.addViewer(
viewer,
viewportId,
container,
StudyInstanceUID,
SeriesInstanceUID
);
managedViewer.addContextMenuCallback((event: Event) => {
// TODO: refactor this after Bill's changes on ContextMenu feature get merged
// const roiAnnotationNearBy = this.getNearbyROI(event);
});
setViewer(viewer);
setManagedViewer(managedViewer);
};
this.viewer = new microscopyViewer(options);
microscopyService.clearAnnotations();
if (this.overlayElement && this.overlayElement.current && this.viewer.addViewportOverlay) {
this.viewer.addViewportOverlay({
element: this.overlayElement.current,
coordinates: [0, 0], // TODO: dicom-microscopy-viewer documentation says this can be false to be automatically, but it is not.
navigate: true,
className: 'OpenLayersOverlay',
});
}
this.viewer.render({ container });
const { StudyInstanceUID, SeriesInstanceUID } = displaySet;
this.managedViewer = this.microscopyService.addViewer(
this.viewer,
this.props.viewportId,
container,
StudyInstanceUID,
SeriesInstanceUID
);
this.managedViewer.addContextMenuCallback((event: Event) => {
// TODO: refactor this after Bill's changes on ContextMenu feature get merged
// const roiAnnotationNearBy = this.getNearbyROI(event);
});
};
this.microscopyService.clearAnnotations();
let smDisplaySet = displaySet;
if (displaySet.Modality === 'SR') {
// for SR displaySet, let's load the actual image displaySet
smDisplaySet = displaySet.getSourceDisplaySet();
}
console.log('Loading viewer metadata', smDisplaySet);
await loadViewer(smDisplaySet.others);
if (displaySet.Modality === 'SR') {
displaySet.load(smDisplaySet);
}
}
componentDidMount() {
const { displaySets, viewportOptions } = this.props;
// Todo-rename: this is always getting the 0
const displaySet = displaySets[0];
this.installOpenLayersRenderer(this.container.current, displaySet).then(() => {
this.setState({ isLoaded: true });
});
}
componentDidUpdate(prevProps: Readonly<{}>, prevState: Readonly<{}>, snapshot?: any): void {
if (this.managedViewer && prevProps.displaySets !== this.props.displaySets) {
const { displaySets } = this.props;
const displaySet = displaySets[0];
this.microscopyService.clearAnnotations();
// loading SR
let smDisplaySet = displaySet;
if (displaySet.Modality === 'SR') {
const referencedDisplaySet = displaySet.getSourceDisplaySet();
displaySet.load(referencedDisplaySet);
// for SR displaySet, let's load the actual image displaySet
smDisplaySet = displaySet.getSourceDisplaySet();
}
console.log('Loading viewer metadata', smDisplaySet);
await loadViewer(smDisplaySet.others);
if (displaySet.Modality === 'SR') {
displaySet.load(smDisplaySet);
}
},
[dataSource, extensionManager, microscopyService, servicesManager, viewportId]
);
useEffect(() => {
const displaySet = displaySets[0];
installOpenLayersRenderer(container.current, displaySet).then(() => {
setIsLoaded(true);
});
return () => {
if (viewer) {
microscopyService.removeViewer(viewer);
}
};
}, []);
useEffect(() => {
const displaySet = displaySets[0];
microscopyService.clearAnnotations();
// loading SR
if (displaySet.Modality === 'SR') {
const referencedDisplaySet = displaySet.getSourceDisplaySet();
displaySet.load(referencedDisplaySet);
}
}
}, [managedViewer, displaySets, microscopyService]);
componentWillUnmount() {
this.microscopyService.removeViewer(this.viewer);
}
const style = { width: '100%', height: '100%' };
const displaySet = displaySets[0];
const firstInstance = displaySet.firstInstance || displaySet.instance;
const LoadingIndicatorProgress = customizationService.getCustomization(
'ui.loadingIndicatorProgress'
);
setViewportActiveHandler = () => {
const { setViewportActive, viewportId, activeViewportId } = this.props;
if (viewportId !== activeViewportId) {
setViewportActive(viewportId);
}
};
render() {
const style = { width: '100%', height: '100%' };
const displaySet = this.props.displaySets[0];
const firstInstance = displaySet.firstInstance || displaySet.instance;
return (
<div
className={'DicomMicroscopyViewer'}
style={style}
onClick={this.setViewportActiveHandler}
>
<div style={{ ...style, display: 'none' }}>
<div style={{ ...style }} ref={this.overlayElement}>
<div style={{ position: 'relative', height: '100%', width: '100%' }}>
{displaySet && firstInstance.imageId && (
<ViewportOverlay
displaySet={displaySet}
instance={displaySet.instance}
metadata={displaySet.metadata}
/>
)}
</div>
return (
<div
className={'DicomMicroscopyViewer'}
style={style}
onClick={() => {
if (viewportId !== activeViewportId) {
setViewportActive(viewportId);
}
}}
>
<div style={{ ...style, display: 'none' }}>
<div style={{ ...style }} ref={overlayElement}>
<div style={{ position: 'relative', height: '100%', width: '100%' }}>
{displaySet && firstInstance.imageId && (
<ViewportOverlay
overlayData={overlayData}
displaySet={displaySet}
instance={displaySet.instance}
metadata={displaySet.metadata}
/>
)}
</div>
</div>
{this.state.error ? (
<h2>{JSON.stringify(this.state.error)}</h2>
) : (
<div
style={style}
ref={(ref: any) => {
this.container.current = ref;
this.props.resizeRef.current = ref;
}}
/>
)}
{this.state.isLoaded ? null : (
<LoadingIndicatorProgress className={'h-full w-full bg-black'} />
)}
</div>
);
}
<div
style={style}
ref={(ref: any) => {
container.current = ref;
resizeRef.current = ref;
}}
/>
{isLoaded ? null : <LoadingIndicatorProgress className={'h-full w-full bg-black'} />}
</div>
);
}
export default DicomMicroscopyViewport;
@@ -24,72 +24,66 @@ interface OverlayItem {
* @param {*} extensionManager is used to load the image data.
* @returns
*/
export const generateFromConfig = ({
topLeft = [],
topRight = [],
bottomLeft = [],
bottomRight = [],
itemGenerator = () => {},
}: {
topLeft?: OverlayItem[];
topRight?: OverlayItem[];
bottomLeft?: OverlayItem[];
bottomRight?: OverlayItem[];
itemGenerator?: (props: any) => any;
}) => {
return (props: any) => {
const topLeftClass = 'top-viewport left-viewport text-primary-light';
const topRightClass = 'top-viewport right-viewport-scrollbar text-primary-light';
const bottomRightClass = 'bottom-viewport right-viewport-scrollbar text-primary-light';
const bottomLeftClass = 'bottom-viewport left-viewport text-primary-light';
const overlay = 'absolute pointer-events-none microscopy-viewport-overlay';
export const generateFromConfig = ({ config, overlayData, ...props }) => {
const {
topLeft = [],
topRight = [],
bottomLeft = [],
bottomRight = [],
}: {
topLeft?: OverlayItem[];
topRight?: OverlayItem[];
bottomLeft?: OverlayItem[];
bottomRight?: OverlayItem[];
} = overlayData ?? {};
const topLeftClass = 'top-viewport left-viewport text-primary-light';
const topRightClass = 'top-viewport right-viewport-scrollbar text-primary-light';
const bottomRightClass = 'bottom-viewport right-viewport-scrollbar text-primary-light';
const bottomLeftClass = 'bottom-viewport left-viewport text-primary-light';
const overlay = 'absolute pointer-events-none microscopy-viewport-overlay';
return (
<>
{topLeft && topLeft.length > 0 && (
<div data-cy={'viewport-overlay-top-left'} className={classnames(overlay, topLeftClass)}>
{listComponentGenerator({ ...props, list: topLeft, itemGenerator })}
</div>
)}
{topRight && topRight.length > 0 && (
<div
data-cy={'viewport-overlay-top-right'}
className={classnames(overlay, topRightClass)}
>
{listComponentGenerator({
...props,
list: topRight,
itemGenerator,
})}
</div>
)}
{bottomRight && bottomRight.length > 0 && (
<div
data-cy={'viewport-overlay-bottom-right'}
className={classnames(overlay, bottomRightClass)}
>
{listComponentGenerator({
...props,
list: bottomRight,
itemGenerator,
})}
</div>
)}
{bottomLeft && bottomLeft.length > 0 && (
<div
data-cy={'viewport-overlay-bottom-left'}
className={classnames(overlay, bottomLeftClass)}
>
{listComponentGenerator({
...props,
list: bottomLeft,
itemGenerator,
})}
</div>
)}
</>
);
};
return (
<>
{topLeft && topLeft.length > 0 && (
<div data-cy={'viewport-overlay-top-left'} className={classnames(overlay, topLeftClass)}>
{listComponentGenerator({ ...props, list: topLeft, itemGenerator })}
</div>
)}
{topRight && topRight.length > 0 && (
<div data-cy={'viewport-overlay-top-right'} className={classnames(overlay, topRightClass)}>
{listComponentGenerator({
...props,
list: topRight,
itemGenerator,
})}
</div>
)}
{bottomRight && bottomRight.length > 0 && (
<div
data-cy={'viewport-overlay-bottom-right'}
className={classnames(overlay, bottomRightClass)}
>
{listComponentGenerator({
...props,
list: bottomRight,
itemGenerator,
})}
</div>
)}
{bottomLeft && bottomLeft.length > 0 && (
<div
data-cy={'viewport-overlay-bottom-left'}
className={classnames(overlay, bottomLeftClass)}
>
{listComponentGenerator({
...props,
list: bottomLeft,
itemGenerator,
})}
</div>
)}
</>
);
};
const itemGenerator = (props: any) => {
@@ -123,4 +117,4 @@ const itemGenerator = (props: any) => {
);
};
export default generateFromConfig({});
export default generateFromConfig;
@@ -0,0 +1,5 @@
import { MeasurementItem } from '@ohif/ui';
export default {
'microscopyPanel.measurementItem': MeasurementItem,
};
@@ -0,0 +1,12 @@
import panelMeasurementItem from './customizations/panelMeasurementItem';
export default function getCustomizationModule() {
return [
{
name: 'default',
value: {
...panelMeasurementItem,
},
},
];
}
+3 -3
View File
@@ -2,6 +2,7 @@ import { id } from './id';
import React, { Suspense, useMemo } from 'react';
import getPanelModule from './getPanelModule';
import getCommandsModule from './getCommandsModule';
import getCustomizationModule from './getCustomizationModule';
import { Types } from '@ohif/core';
import { useViewportGrid } from '@ohif/ui-next';
@@ -82,9 +83,6 @@ const extension: Types.Extensions.Extension = {
return (
<MicroscopyViewport
key={displaySetsKey}
servicesManager={servicesManager}
extensionManager={extensionManager}
commandsManager={commandsManager}
activeViewportId={activeViewportId}
setViewportActive={(viewportId: string) => {
viewportGridService.setActiveViewportId(viewportId);
@@ -158,6 +156,8 @@ const extension: Types.Extensions.Extension = {
getPanelModule,
getCommandsModule,
getCustomizationModule,
};
export default extension;
+280
View File
@@ -3,6 +3,286 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
# [3.10.0-beta.112](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.111...v3.10.0-beta.112) (2025-02-28)
**Note:** Version bump only for package @ohif/extension-dicom-pdf
# [3.10.0-beta.111](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.110...v3.10.0-beta.111) (2025-02-26)
**Note:** Version bump only for package @ohif/extension-dicom-pdf
# [3.10.0-beta.110](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.109...v3.10.0-beta.110) (2025-02-26)
**Note:** Version bump only for package @ohif/extension-dicom-pdf
# [3.10.0-beta.109](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.108...v3.10.0-beta.109) (2025-02-25)
**Note:** Version bump only for package @ohif/extension-dicom-pdf
# [3.10.0-beta.108](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.107...v3.10.0-beta.108) (2025-02-25)
**Note:** Version bump only for package @ohif/extension-dicom-pdf
# [3.10.0-beta.107](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.106...v3.10.0-beta.107) (2025-02-25)
**Note:** Version bump only for package @ohif/extension-dicom-pdf
# [3.10.0-beta.106](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.105...v3.10.0-beta.106) (2025-02-25)
**Note:** Version bump only for package @ohif/extension-dicom-pdf
# [3.10.0-beta.105](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.104...v3.10.0-beta.105) (2025-02-25)
**Note:** Version bump only for package @ohif/extension-dicom-pdf
# [3.10.0-beta.104](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.103...v3.10.0-beta.104) (2025-02-25)
**Note:** Version bump only for package @ohif/extension-dicom-pdf
# [3.10.0-beta.103](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.102...v3.10.0-beta.103) (2025-02-23)
**Note:** Version bump only for package @ohif/extension-dicom-pdf
# [3.10.0-beta.102](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.101...v3.10.0-beta.102) (2025-02-20)
**Note:** Version bump only for package @ohif/extension-dicom-pdf
# [3.10.0-beta.101](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.100...v3.10.0-beta.101) (2025-02-20)
**Note:** Version bump only for package @ohif/extension-dicom-pdf
# [3.10.0-beta.100](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.99...v3.10.0-beta.100) (2025-02-19)
**Note:** Version bump only for package @ohif/extension-dicom-pdf
# [3.10.0-beta.99](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.98...v3.10.0-beta.99) (2025-02-18)
**Note:** Version bump only for package @ohif/extension-dicom-pdf
# [3.10.0-beta.98](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.97...v3.10.0-beta.98) (2025-02-18)
**Note:** Version bump only for package @ohif/extension-dicom-pdf
# [3.10.0-beta.97](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.96...v3.10.0-beta.97) (2025-02-18)
**Note:** Version bump only for package @ohif/extension-dicom-pdf
# [3.10.0-beta.96](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.95...v3.10.0-beta.96) (2025-02-18)
**Note:** Version bump only for package @ohif/extension-dicom-pdf
# [3.10.0-beta.95](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.94...v3.10.0-beta.95) (2025-02-13)
**Note:** Version bump only for package @ohif/extension-dicom-pdf
# [3.10.0-beta.94](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.93...v3.10.0-beta.94) (2025-02-11)
**Note:** Version bump only for package @ohif/extension-dicom-pdf
# [3.10.0-beta.93](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.92...v3.10.0-beta.93) (2025-02-04)
**Note:** Version bump only for package @ohif/extension-dicom-pdf
# [3.10.0-beta.92](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.91...v3.10.0-beta.92) (2025-02-04)
**Note:** Version bump only for package @ohif/extension-dicom-pdf
# [3.10.0-beta.91](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.90...v3.10.0-beta.91) (2025-02-04)
**Note:** Version bump only for package @ohif/extension-dicom-pdf
# [3.10.0-beta.90](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.89...v3.10.0-beta.90) (2025-02-04)
**Note:** Version bump only for package @ohif/extension-dicom-pdf
# [3.10.0-beta.89](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.88...v3.10.0-beta.89) (2025-02-04)
**Note:** Version bump only for package @ohif/extension-dicom-pdf
# [3.10.0-beta.88](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.87...v3.10.0-beta.88) (2025-02-04)
**Note:** Version bump only for package @ohif/extension-dicom-pdf
# [3.10.0-beta.87](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.86...v3.10.0-beta.87) (2025-02-03)
**Note:** Version bump only for package @ohif/extension-dicom-pdf
# [3.10.0-beta.86](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.85...v3.10.0-beta.86) (2025-02-03)
**Note:** Version bump only for package @ohif/extension-dicom-pdf
# [3.10.0-beta.85](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.84...v3.10.0-beta.85) (2025-02-03)
**Note:** Version bump only for package @ohif/extension-dicom-pdf
# [3.10.0-beta.84](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.83...v3.10.0-beta.84) (2025-01-31)
**Note:** Version bump only for package @ohif/extension-dicom-pdf
# [3.10.0-beta.83](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.82...v3.10.0-beta.83) (2025-01-31)
**Note:** Version bump only for package @ohif/extension-dicom-pdf
# [3.10.0-beta.82](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.81...v3.10.0-beta.82) (2025-01-31)
**Note:** Version bump only for package @ohif/extension-dicom-pdf
# [3.10.0-beta.81](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.80...v3.10.0-beta.81) (2025-01-29)
**Note:** Version bump only for package @ohif/extension-dicom-pdf
# [3.10.0-beta.80](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.79...v3.10.0-beta.80) (2025-01-29)
**Note:** Version bump only for package @ohif/extension-dicom-pdf
# [3.10.0-beta.79](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.78...v3.10.0-beta.79) (2025-01-28)
**Note:** Version bump only for package @ohif/extension-dicom-pdf
# [3.10.0-beta.78](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.77...v3.10.0-beta.78) (2025-01-28)
**Note:** Version bump only for package @ohif/extension-dicom-pdf
# [3.10.0-beta.77](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.76...v3.10.0-beta.77) (2025-01-28)
**Note:** Version bump only for package @ohif/extension-dicom-pdf
+3 -3
View File
@@ -1,6 +1,6 @@
{
"name": "@ohif/extension-dicom-pdf",
"version": "3.10.0-beta.77",
"version": "3.10.0-beta.112",
"description": "OHIF extension for PDF display",
"author": "OHIF",
"license": "MIT",
@@ -30,8 +30,8 @@
"test:unit:ci": "jest --ci --runInBand --collectCoverage --passWithNoTests"
},
"peerDependencies": {
"@ohif/core": "3.10.0-beta.77",
"@ohif/ui": "3.10.0-beta.77",
"@ohif/core": "3.10.0-beta.112",
"@ohif/ui": "3.10.0-beta.112",
"dcmjs": "*",
"dicom-parser": "^1.8.9",
"hammerjs": "^2.0.8",
Loaded 100 of 354 files, more files were not shown because too many files have changed in this diff. Show more