Compare commits

..
Author SHA1 Message Date
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
ohif-bot fe658c6392 chore(version): Update package versions [skip ci] 2025-01-28 13:59:39 +00:00
ohif-bot 70c94e8d5a chore(version): version.json [skip ci] 2025-01-28 13:59:33 +00:00
Devu-trenser 5addf51c45 feat(windowLevelActionMenu) customization support for windowLevelActionMenu (#4725) 2025-01-28 08:54:58 -05:00
ashik-trenserandashikcn 8e3e2085d4 fix: for initialImageIndex mismatch issue for loading SR after disabling prompts (#4732)
Co-authored-by: ashikcn <ashik@L1140.trenser.com>
2025-01-28 08:53:42 -05:00
ohif-bot 078a72996f chore(version): Update package versions [skip ci] 2025-01-27 16:59:04 +00:00
ohif-bot dc14a48fd9 chore(version): version.json [skip ci] 2025-01-27 16:58:57 +00:00
arul-trenser 61699d00b6 fix(context menu): Context menus for edge-proximate measurements are partially obscured. (#4727) 2025-01-27 11:54:29 -05:00
ohif-bot eb854ac2cb chore(version): Update package versions [skip ci] 2025-01-27 16:24:18 +00:00
ohif-bot 6c42f269a7 chore(version): version.json [skip ci] 2025-01-27 16:24:12 +00:00
Ibrahim ac6e674b4d feat(static-wado): add support for case-insensitive searching (#4603)
[OHI-1357]
2025-01-27 11:20:00 -05:00
ohif-bot 316cf0a7bd chore(version): Update package versions [skip ci] 2025-01-27 14:27:48 +00:00
ohif-bot c011236060 chore(version): version.json [skip ci] 2025-01-27 14:27:43 +00:00
dependabot[bot] 2ed7a1adfa chore(deps): bump store2 from 2.14.3 to 2.14.4 (#4737)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-27 09:23:38 -05:00
ohif-bot 492150478b chore(version): Update package versions [skip ci] 2025-01-24 15:27:16 +00:00
ohif-bot cb03077d37 chore(version): version.json [skip ci] 2025-01-24 15:27:10 +00:00
Alireza 28fb921089 fix(docs): image in customization (#4735) 2025-01-24 10:22:29 -05:00
ohif-bot bc175d68b6 chore(version): Update package versions [skip ci] 2025-01-24 13:46:27 +00:00
ohif-bot 884020f143 chore(version): version.json [skip ci] 2025-01-24 13:46:21 +00:00
Gas Giantandscouser d6f0092a32 feat: delete active annotation using backspace/delete key (#4722)
Co-authored-by: scouser <sharukh@Sharukhs-MacBook-Pro.local>
2025-01-24 08:42:00 -05:00
ohif-bot 01fa5d83a6 chore(version): Update package versions [skip ci] 2025-01-23 19:28:43 +00:00
ohif-bot 625919d4e4 chore(version): version.json [skip ci] 2025-01-23 19:28:36 +00:00
Alireza 55ad8efbab feat(customization): new customization service api (#4688) 2025-01-23 14:24:13 -05:00
ohif-bot fab52808cb chore(version): Update package versions [skip ci] 2025-01-23 19:18:02 +00:00
ohif-bot f5ad0de2d2 chore(version): version.json [skip ci] 2025-01-23 19:17:56 +00:00
Ibrahim d9abc3da8d feat(panels): responsive thumbnails based on panel size (#4723) 2025-01-23 14:13:44 -05:00
ohif-bot 9d07705a1f chore(version): Update package versions [skip ci] 2025-01-22 16:40:54 +00:00
ohif-bot 0966f62310 chore(version): version.json [skip ci] 2025-01-22 16:40:48 +00:00
Alireza f00d18292f fix(seg): sphere scissor on stack and cpu rendering reset properties was broken (#4721) 2025-01-22 11:36:45 -05:00
ohif-bot 3628ad84c8 chore(version): Update package versions [skip ci] 2025-01-21 16:25:19 +00:00
ohif-bot b21287e908 chore(version): version.json [skip ci] 2025-01-21 16:25:13 +00:00
Joe Boccanfuso d90a4cfb16 feat(resizable-side-panels): Make the left and right side panels (optionally) resizable. (#4672) 2025-01-21 11:20:34 -05:00
ohif-bot a518854a4c chore(version): Update package versions [skip ci] 2025-01-21 14:38:46 +00:00
ohif-bot 28f86f3cd6 chore(version): version.json [skip ci] 2025-01-21 14:38:40 +00:00
Alireza cf97fa9b7b fix(ui): Update dependencies and add missing icons (#4699) 2025-01-21 09:34:19 -05:00
ohif-bot ad7ade28ea chore(version): Update package versions [skip ci] 2025-01-21 14:12:03 +00:00
ohif-bot 9aed7b8486 chore(version): version.json [skip ci] 2025-01-21 14:11:57 +00:00
Jaseel-trenser 8aedb2ec54 fix: Inconsistent Handling of Patient Name Tag (#4703) 2025-01-21 09:07:30 -05:00
ohif-bot cbe926f52b chore(version): Update package versions [skip ci] 2025-01-20 14:17:53 +00:00
ohif-bot 855648f41f chore(version): version.json [skip ci] 2025-01-20 14:17:47 +00:00
Bez bf587070cc fix(rotation): support cycling rotateViewportCCW (#4533) 2025-01-20 09:13:43 -05:00
ohif-bot 953f36ab4c chore(version): Update package versions [skip ci] 2025-01-20 14:11:21 +00:00
ohif-bot 0911e3c0d1 chore(version): version.json [skip ci] 2025-01-20 14:11:15 +00:00
Bill Wallace 464148ece6 fix(hp): Display set should allow remembered updates (#4707) 2025-01-20 09:06:28 -05:00
ohif-bot 544dc543d9 chore(version): Update package versions [skip ci] 2025-01-17 21:48:05 +00:00
ohif-bot f5dcf25d98 chore(version): version.json [skip ci] 2025-01-17 21:47:59 +00:00
Bill Wallace 7734296d1d docs: Documentation on how to set default configuration to search for today (#4708) 2025-01-17 16:43:51 -05:00
ohif-bot 9e047784d1 chore(version): Update package versions [skip ci] 2025-01-16 16:47:32 +00:00
ohif-bot df96a4992c chore(version): version.json [skip ci] 2025-01-16 16:47:26 +00:00
Pedro H. Köhler 19931614dc fix: context menu icon (#4696) 2025-01-16 11:42:58 -05:00
ohif-bot ef477c29c5 chore(version): Update package versions [skip ci] 2025-01-16 03:33:26 +00:00
ohif-bot 6c8ebc1d5a chore(version): version.json [skip ci] 2025-01-16 03:33:19 +00:00
ec4b5a6876 fix(multiframe): handling proxies properly (#4693)
Co-authored-by: Bill Wallace <wayfarer3130@gmail.com>
Co-authored-by: Chao Sui <chao.sui@curvebeamai.com>
2025-01-15 22:29:06 -05:00
ohif-bot 9f8df95f3e chore(version): Update package versions [skip ci] 2025-01-15 20:21:31 +00:00
ohif-bot c718b20659 chore(version): version.json [skip ci] 2025-01-15 20:21:25 +00:00
Bill Wallaceandsedghi cded082617 fix: Having sop instance in a per-frame or shared attribute breaks load (#4560)
Co-authored-by: sedghi <ar.sedghi@gmail.com>
2025-01-15 15:16:50 -05:00
ohif-bot 27c040fdda chore(version): Update package versions [skip ci] 2025-01-14 14:07:59 +00:00
ohif-bot e923bf2bc5 chore(version): version.json [skip ci] 2025-01-14 14:07:53 +00:00
Pedro H. Köhler 2d611d06ed fix: cs dicom sr commands module (#4683) 2025-01-14 09:03:04 -05:00
Alireza c901a847af fix: bugs after multimonitor (#4680) 2025-01-13 18:32:54 -05:00
248 changed files with 10913 additions and 3481 deletions

No files matched your search

+2 -1
View File
@@ -18,7 +18,8 @@
},
"rules": {
// Enforce consistent brace style for all control statements for readability
"curly": "error"
"curly": "error",
"import/no-anonymous-default-export": "off"
},
"globals": {
"cy": true,
+215
View File
@@ -3,6 +3,221 @@
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.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)
### Bug Fixes
* for initialImageIndex mismatch issue for loading SR after disabling prompts ([#4732](https://github.com/OHIF/Viewers/issues/4732)) ([8e3e208](https://github.com/OHIF/Viewers/commit/8e3e2085d45eba230d0210849b65a6e609c9d81a))
# [3.10.0-beta.76](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.75...v3.10.0-beta.76) (2025-01-27)
### Bug Fixes
* **context menu:** Context menus for edge-proximate measurements are partially obscured. ([#4727](https://github.com/OHIF/Viewers/issues/4727)) ([61699d0](https://github.com/OHIF/Viewers/commit/61699d00b6ce1e53631fd8c01e783701e01a7373))
# [3.10.0-beta.75](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.74...v3.10.0-beta.75) (2025-01-27)
### Features
* **static-wado:** add support for case-insensitive searching ([#4603](https://github.com/OHIF/Viewers/issues/4603)) ([ac6e674](https://github.com/OHIF/Viewers/commit/ac6e674b4d094f942556d045178011bbf3f81796))
# [3.10.0-beta.74](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.73...v3.10.0-beta.74) (2025-01-27)
**Note:** Version bump only for package ohif-monorepo-root
# [3.10.0-beta.73](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.72...v3.10.0-beta.73) (2025-01-24)
### Bug Fixes
* **docs:** image in customization ([#4735](https://github.com/OHIF/Viewers/issues/4735)) ([28fb921](https://github.com/OHIF/Viewers/commit/28fb92108988c3304344690792947c847bad72a6))
# [3.10.0-beta.72](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.71...v3.10.0-beta.72) (2025-01-24)
### Features
* delete active annotation using backspace/delete key ([#4722](https://github.com/OHIF/Viewers/issues/4722)) ([d6f0092](https://github.com/OHIF/Viewers/commit/d6f0092a3236cecb5d04ec46c8ad01600500831e))
# [3.10.0-beta.71](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.70...v3.10.0-beta.71) (2025-01-23)
### Features
* **customization:** new customization service api ([#4688](https://github.com/OHIF/Viewers/issues/4688)) ([55ad8ef](https://github.com/OHIF/Viewers/commit/55ad8efbabc3fabd8031fc08927b2f92ae5aec69))
# [3.10.0-beta.70](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.69...v3.10.0-beta.70) (2025-01-23)
### Features
* **panels:** responsive thumbnails based on panel size ([#4723](https://github.com/OHIF/Viewers/issues/4723)) ([d9abc3d](https://github.com/OHIF/Viewers/commit/d9abc3da8d94d6c5ab0cc5af25a5f61849905a35))
# [3.10.0-beta.69](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.68...v3.10.0-beta.69) (2025-01-22)
### Bug Fixes
* **seg:** sphere scissor on stack and cpu rendering reset properties was broken ([#4721](https://github.com/OHIF/Viewers/issues/4721)) ([f00d182](https://github.com/OHIF/Viewers/commit/f00d18292f02e8910215d913edfc994850a68d88))
# [3.10.0-beta.68](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.67...v3.10.0-beta.68) (2025-01-21)
### Features
* **resizable-side-panels:** Make the left and right side panels (optionally) resizable. ([#4672](https://github.com/OHIF/Viewers/issues/4672)) ([d90a4cf](https://github.com/OHIF/Viewers/commit/d90a4cfb16cc0daed9b905de9780f44cca1323f9))
# [3.10.0-beta.67](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.66...v3.10.0-beta.67) (2025-01-21)
### Bug Fixes
* **ui:** Update dependencies and add missing icons ([#4699](https://github.com/OHIF/Viewers/issues/4699)) ([cf97fa9](https://github.com/OHIF/Viewers/commit/cf97fa9b7b9687a9b73c1cf6926bc9fbc39b6512))
# [3.10.0-beta.66](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.65...v3.10.0-beta.66) (2025-01-21)
### Bug Fixes
* Inconsistent Handling of Patient Name Tag ([#4703](https://github.com/OHIF/Viewers/issues/4703)) ([8aedb2e](https://github.com/OHIF/Viewers/commit/8aedb2ec54a0ccf2550f745fed6f0b8aa184a860))
# [3.10.0-beta.65](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.64...v3.10.0-beta.65) (2025-01-20)
### Bug Fixes
* **rotation:** support cycling rotateViewportCCW ([#4533](https://github.com/OHIF/Viewers/issues/4533)) ([bf58707](https://github.com/OHIF/Viewers/commit/bf587070cccd344f5e8817e9954ba9f2e46b81bb))
# [3.10.0-beta.64](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.63...v3.10.0-beta.64) (2025-01-20)
### Bug Fixes
* **hp:** Display set should allow remembered updates ([#4707](https://github.com/OHIF/Viewers/issues/4707)) ([464148e](https://github.com/OHIF/Viewers/commit/464148ece66b48b583dc6e998ca4d11c66746f3a))
# [3.10.0-beta.63](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.62...v3.10.0-beta.63) (2025-01-17)
**Note:** Version bump only for package ohif-monorepo-root
# [3.10.0-beta.62](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.61...v3.10.0-beta.62) (2025-01-16)
### Bug Fixes
* context menu icon ([#4696](https://github.com/OHIF/Viewers/issues/4696)) ([1993161](https://github.com/OHIF/Viewers/commit/19931614dc53da440718e512d39a87ca9118b96e))
# [3.10.0-beta.61](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.60...v3.10.0-beta.61) (2025-01-16)
### Bug Fixes
* **multiframe:** handling proxies properly ([#4693](https://github.com/OHIF/Viewers/issues/4693)) ([ec4b5a6](https://github.com/OHIF/Viewers/commit/ec4b5a6876cea77278e5cffaf4108eeeefdc57dc))
# [3.10.0-beta.60](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.59...v3.10.0-beta.60) (2025-01-15)
### Bug Fixes
* Having sop instance in a per-frame or shared attribute breaks load ([#4560](https://github.com/OHIF/Viewers/issues/4560)) ([cded082](https://github.com/OHIF/Viewers/commit/cded08261788143e0d5be57a55c927fd96aafb22))
# [3.10.0-beta.59](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.58...v3.10.0-beta.59) (2025-01-14)
### Bug Fixes
* bugs after multimonitor ([#4680](https://github.com/OHIF/Viewers/issues/4680)) ([c901a84](https://github.com/OHIF/Viewers/commit/c901a847af75d356509366c695ea46ff4f4bcdaf))
* cs dicom sr commands module ([#4683](https://github.com/OHIF/Viewers/issues/4683)) ([2d611d0](https://github.com/OHIF/Viewers/commit/2d611d06ed759bbd1e83ccfac7dceeff9eb6238e))
# [3.10.0-beta.58](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.57...v3.10.0-beta.58) (2025-01-13)
+163
View File
@@ -3,6 +3,169 @@
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.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
# [3.10.0-beta.76](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.75...v3.10.0-beta.76) (2025-01-27)
**Note:** Version bump only for package @externals/devDependencies
# [3.10.0-beta.75](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.74...v3.10.0-beta.75) (2025-01-27)
**Note:** Version bump only for package @externals/devDependencies
# [3.10.0-beta.74](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.73...v3.10.0-beta.74) (2025-01-27)
**Note:** Version bump only for package @externals/devDependencies
# [3.10.0-beta.73](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.72...v3.10.0-beta.73) (2025-01-24)
**Note:** Version bump only for package @externals/devDependencies
# [3.10.0-beta.72](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.71...v3.10.0-beta.72) (2025-01-24)
**Note:** Version bump only for package @externals/devDependencies
# [3.10.0-beta.71](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.70...v3.10.0-beta.71) (2025-01-23)
**Note:** Version bump only for package @externals/devDependencies
# [3.10.0-beta.70](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.69...v3.10.0-beta.70) (2025-01-23)
**Note:** Version bump only for package @externals/devDependencies
# [3.10.0-beta.69](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.68...v3.10.0-beta.69) (2025-01-22)
**Note:** Version bump only for package @externals/devDependencies
# [3.10.0-beta.68](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.67...v3.10.0-beta.68) (2025-01-21)
**Note:** Version bump only for package @externals/devDependencies
# [3.10.0-beta.67](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.66...v3.10.0-beta.67) (2025-01-21)
### Bug Fixes
* **ui:** Update dependencies and add missing icons ([#4699](https://github.com/OHIF/Viewers/issues/4699)) ([cf97fa9](https://github.com/OHIF/Viewers/commit/cf97fa9b7b9687a9b73c1cf6926bc9fbc39b6512))
# [3.10.0-beta.66](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.65...v3.10.0-beta.66) (2025-01-21)
**Note:** Version bump only for package @externals/devDependencies
# [3.10.0-beta.65](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.64...v3.10.0-beta.65) (2025-01-20)
**Note:** Version bump only for package @externals/devDependencies
# [3.10.0-beta.64](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.63...v3.10.0-beta.64) (2025-01-20)
**Note:** Version bump only for package @externals/devDependencies
# [3.10.0-beta.63](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.62...v3.10.0-beta.63) (2025-01-17)
**Note:** Version bump only for package @externals/devDependencies
# [3.10.0-beta.62](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.61...v3.10.0-beta.62) (2025-01-16)
**Note:** Version bump only for package @externals/devDependencies
# [3.10.0-beta.61](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.60...v3.10.0-beta.61) (2025-01-16)
**Note:** Version bump only for package @externals/devDependencies
# [3.10.0-beta.60](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.59...v3.10.0-beta.60) (2025-01-15)
**Note:** Version bump only for package @externals/devDependencies
# [3.10.0-beta.59](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.58...v3.10.0-beta.59) (2025-01-14)
**Note:** Version bump only for package @externals/devDependencies
# [3.10.0-beta.58](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.57...v3.10.0-beta.58) (2025-01-13)
**Note:** Version bump only for package @externals/devDependencies
+2 -2
View File
@@ -1,7 +1,7 @@
{
"name": "@externals/devDependencies",
"description": "External dev dependencies - put dev build dependencies here",
"version": "3.10.0-beta.58",
"version": "3.10.0-beta.78",
"license": "MIT",
"private": true,
"engines": {
@@ -72,7 +72,7 @@
"prettier-plugin-tailwindcss": "^0.5.4",
"react-refresh": "^0.14.2",
"semver": "^7.5.1",
"serve": "^14.2.0",
"serve": "^14.2.4",
"shader-loader": "^1.3.1",
"shx": "^0.3.3",
"source-map-loader": "^4.0.1",
+160
View File
@@ -3,6 +3,166 @@
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.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
# [3.10.0-beta.76](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.75...v3.10.0-beta.76) (2025-01-27)
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
# [3.10.0-beta.75](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.74...v3.10.0-beta.75) (2025-01-27)
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
# [3.10.0-beta.74](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.73...v3.10.0-beta.74) (2025-01-27)
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
# [3.10.0-beta.73](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.72...v3.10.0-beta.73) (2025-01-24)
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
# [3.10.0-beta.72](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.71...v3.10.0-beta.72) (2025-01-24)
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
# [3.10.0-beta.71](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.70...v3.10.0-beta.71) (2025-01-23)
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
# [3.10.0-beta.70](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.69...v3.10.0-beta.70) (2025-01-23)
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
# [3.10.0-beta.69](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.68...v3.10.0-beta.69) (2025-01-22)
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
# [3.10.0-beta.68](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.67...v3.10.0-beta.68) (2025-01-21)
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
# [3.10.0-beta.67](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.66...v3.10.0-beta.67) (2025-01-21)
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
# [3.10.0-beta.66](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.65...v3.10.0-beta.66) (2025-01-21)
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
# [3.10.0-beta.65](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.64...v3.10.0-beta.65) (2025-01-20)
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
# [3.10.0-beta.64](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.63...v3.10.0-beta.64) (2025-01-20)
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
# [3.10.0-beta.63](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.62...v3.10.0-beta.63) (2025-01-17)
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
# [3.10.0-beta.62](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.61...v3.10.0-beta.62) (2025-01-16)
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
# [3.10.0-beta.61](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.60...v3.10.0-beta.61) (2025-01-16)
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
# [3.10.0-beta.60](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.59...v3.10.0-beta.60) (2025-01-15)
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
# [3.10.0-beta.59](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.58...v3.10.0-beta.59) (2025-01-14)
**Note:** Version bump only for package @externals/dicom-microscopy-viewer
# [3.10.0-beta.58](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.57...v3.10.0-beta.58) (2025-01-13)
**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.58",
"version": "3.10.0-beta.78",
"license": "MIT",
"dependencies": {
"dicom-microscopy-viewer": "^0.46.1"
BIN
View File
Binary file not shown.
+1 -1
View File
@@ -1 +1 @@
07c628e689b28f831317a7c28d712509b69c6b13
6abb095b8a39c5ae4f8df8852b3ddb3249ec463f
@@ -3,6 +3,172 @@
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.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
# [3.10.0-beta.76](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.75...v3.10.0-beta.76) (2025-01-27)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
# [3.10.0-beta.75](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.74...v3.10.0-beta.75) (2025-01-27)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
# [3.10.0-beta.74](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.73...v3.10.0-beta.74) (2025-01-27)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
# [3.10.0-beta.73](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.72...v3.10.0-beta.73) (2025-01-24)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
# [3.10.0-beta.72](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.71...v3.10.0-beta.72) (2025-01-24)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
# [3.10.0-beta.71](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.70...v3.10.0-beta.71) (2025-01-23)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
# [3.10.0-beta.70](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.69...v3.10.0-beta.70) (2025-01-23)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
# [3.10.0-beta.69](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.68...v3.10.0-beta.69) (2025-01-22)
### Bug Fixes
* **seg:** sphere scissor on stack and cpu rendering reset properties was broken ([#4721](https://github.com/OHIF/Viewers/issues/4721)) ([f00d182](https://github.com/OHIF/Viewers/commit/f00d18292f02e8910215d913edfc994850a68d88))
# [3.10.0-beta.68](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.67...v3.10.0-beta.68) (2025-01-21)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
# [3.10.0-beta.67](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.66...v3.10.0-beta.67) (2025-01-21)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
# [3.10.0-beta.66](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.65...v3.10.0-beta.66) (2025-01-21)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
# [3.10.0-beta.65](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.64...v3.10.0-beta.65) (2025-01-20)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
# [3.10.0-beta.64](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.63...v3.10.0-beta.64) (2025-01-20)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
# [3.10.0-beta.63](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.62...v3.10.0-beta.63) (2025-01-17)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
# [3.10.0-beta.62](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.61...v3.10.0-beta.62) (2025-01-16)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
# [3.10.0-beta.61](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.60...v3.10.0-beta.61) (2025-01-16)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
# [3.10.0-beta.60](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.59...v3.10.0-beta.60) (2025-01-15)
### Bug Fixes
* Having sop instance in a per-frame or shared attribute breaks load ([#4560](https://github.com/OHIF/Viewers/issues/4560)) ([cded082](https://github.com/OHIF/Viewers/commit/cded08261788143e0d5be57a55c927fd96aafb22))
# [3.10.0-beta.59](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.58...v3.10.0-beta.59) (2025-01-14)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-pmap
# [3.10.0-beta.58](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.57...v3.10.0-beta.58) (2025-01-13)
**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.58",
"version": "3.10.0-beta.78",
"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.58",
"@ohif/extension-cornerstone": "3.10.0-beta.58",
"@ohif/extension-default": "3.10.0-beta.58",
"@ohif/i18n": "3.10.0-beta.58",
"@ohif/core": "3.10.0-beta.78",
"@ohif/extension-cornerstone": "3.10.0-beta.78",
"@ohif/extension-default": "3.10.0-beta.78",
"@ohif/i18n": "3.10.0-beta.78",
"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.14.7",
"@cornerstonejs/core": "^2.14.7",
"@cornerstonejs/adapters": "^2.17.2",
"@cornerstonejs/core": "^2.17.2",
"@kitware/vtk.js": "32.1.1",
"react-color": "^2.19.3"
}
@@ -3,6 +3,169 @@
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.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
# [3.10.0-beta.76](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.75...v3.10.0-beta.76) (2025-01-27)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
# [3.10.0-beta.75](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.74...v3.10.0-beta.75) (2025-01-27)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
# [3.10.0-beta.74](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.73...v3.10.0-beta.74) (2025-01-27)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
# [3.10.0-beta.73](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.72...v3.10.0-beta.73) (2025-01-24)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
# [3.10.0-beta.72](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.71...v3.10.0-beta.72) (2025-01-24)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
# [3.10.0-beta.71](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.70...v3.10.0-beta.71) (2025-01-23)
### Features
* **customization:** new customization service api ([#4688](https://github.com/OHIF/Viewers/issues/4688)) ([55ad8ef](https://github.com/OHIF/Viewers/commit/55ad8efbabc3fabd8031fc08927b2f92ae5aec69))
# [3.10.0-beta.70](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.69...v3.10.0-beta.70) (2025-01-23)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
# [3.10.0-beta.69](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.68...v3.10.0-beta.69) (2025-01-22)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
# [3.10.0-beta.68](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.67...v3.10.0-beta.68) (2025-01-21)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
# [3.10.0-beta.67](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.66...v3.10.0-beta.67) (2025-01-21)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
# [3.10.0-beta.66](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.65...v3.10.0-beta.66) (2025-01-21)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
# [3.10.0-beta.65](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.64...v3.10.0-beta.65) (2025-01-20)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
# [3.10.0-beta.64](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.63...v3.10.0-beta.64) (2025-01-20)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
# [3.10.0-beta.63](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.62...v3.10.0-beta.63) (2025-01-17)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
# [3.10.0-beta.62](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.61...v3.10.0-beta.62) (2025-01-16)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
# [3.10.0-beta.61](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.60...v3.10.0-beta.61) (2025-01-16)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
# [3.10.0-beta.60](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.59...v3.10.0-beta.60) (2025-01-15)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
# [3.10.0-beta.59](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.58...v3.10.0-beta.59) (2025-01-14)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
# [3.10.0-beta.58](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.57...v3.10.0-beta.58) (2025-01-13)
**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.58",
"version": "3.10.0-beta.78",
"description": "DICOM RT read workflow",
"author": "OHIF",
"license": "MIT",
@@ -33,10 +33,10 @@
"start": "yarn run dev"
},
"peerDependencies": {
"@ohif/core": "3.10.0-beta.58",
"@ohif/extension-cornerstone": "3.10.0-beta.58",
"@ohif/extension-default": "3.10.0-beta.58",
"@ohif/i18n": "3.10.0-beta.58",
"@ohif/core": "3.10.0-beta.78",
"@ohif/extension-cornerstone": "3.10.0-beta.78",
"@ohif/extension-default": "3.10.0-beta.78",
"@ohif/i18n": "3.10.0-beta.78",
"prop-types": "^15.6.2",
"react": "^18.3.1",
"react-dom": "^18.3.1",
@@ -1,5 +1,5 @@
function createRTToolGroupAndAddTools(ToolGroupService, customizationService, toolGroupId) {
const { tools } = customizationService.get('cornerstone.overlayViewportTools') ?? {};
const tools = customizationService.getCustomization('cornerstone.overlayViewportTools');
return ToolGroupService.createToolGroupAndAddTools(toolGroupId, tools);
}
@@ -3,6 +3,175 @@
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.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
# [3.10.0-beta.76](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.75...v3.10.0-beta.76) (2025-01-27)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
# [3.10.0-beta.75](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.74...v3.10.0-beta.75) (2025-01-27)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
# [3.10.0-beta.74](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.73...v3.10.0-beta.74) (2025-01-27)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
# [3.10.0-beta.73](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.72...v3.10.0-beta.73) (2025-01-24)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
# [3.10.0-beta.72](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.71...v3.10.0-beta.72) (2025-01-24)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
# [3.10.0-beta.71](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.70...v3.10.0-beta.71) (2025-01-23)
### Features
* **customization:** new customization service api ([#4688](https://github.com/OHIF/Viewers/issues/4688)) ([55ad8ef](https://github.com/OHIF/Viewers/commit/55ad8efbabc3fabd8031fc08927b2f92ae5aec69))
# [3.10.0-beta.70](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.69...v3.10.0-beta.70) (2025-01-23)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
# [3.10.0-beta.69](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.68...v3.10.0-beta.69) (2025-01-22)
### Bug Fixes
* **seg:** sphere scissor on stack and cpu rendering reset properties was broken ([#4721](https://github.com/OHIF/Viewers/issues/4721)) ([f00d182](https://github.com/OHIF/Viewers/commit/f00d18292f02e8910215d913edfc994850a68d88))
# [3.10.0-beta.68](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.67...v3.10.0-beta.68) (2025-01-21)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
# [3.10.0-beta.67](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.66...v3.10.0-beta.67) (2025-01-21)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
# [3.10.0-beta.66](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.65...v3.10.0-beta.66) (2025-01-21)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
# [3.10.0-beta.65](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.64...v3.10.0-beta.65) (2025-01-20)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
# [3.10.0-beta.64](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.63...v3.10.0-beta.64) (2025-01-20)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
# [3.10.0-beta.63](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.62...v3.10.0-beta.63) (2025-01-17)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
# [3.10.0-beta.62](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.61...v3.10.0-beta.62) (2025-01-16)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
# [3.10.0-beta.61](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.60...v3.10.0-beta.61) (2025-01-16)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
# [3.10.0-beta.60](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.59...v3.10.0-beta.60) (2025-01-15)
### Bug Fixes
* Having sop instance in a per-frame or shared attribute breaks load ([#4560](https://github.com/OHIF/Viewers/issues/4560)) ([cded082](https://github.com/OHIF/Viewers/commit/cded08261788143e0d5be57a55c927fd96aafb22))
# [3.10.0-beta.59](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.58...v3.10.0-beta.59) (2025-01-14)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
# [3.10.0-beta.58](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.57...v3.10.0-beta.58) (2025-01-13)
**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.58",
"version": "3.10.0-beta.78",
"description": "DICOM SEG read workflow",
"author": "OHIF",
"license": "MIT",
@@ -33,10 +33,10 @@
"start": "yarn run dev"
},
"peerDependencies": {
"@ohif/core": "3.10.0-beta.58",
"@ohif/extension-cornerstone": "3.10.0-beta.58",
"@ohif/extension-default": "3.10.0-beta.58",
"@ohif/i18n": "3.10.0-beta.58",
"@ohif/core": "3.10.0-beta.78",
"@ohif/extension-cornerstone": "3.10.0-beta.78",
"@ohif/extension-default": "3.10.0-beta.78",
"@ohif/i18n": "3.10.0-beta.78",
"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.14.7",
"@cornerstonejs/core": "^2.14.7",
"@cornerstonejs/adapters": "^2.17.2",
"@cornerstonejs/core": "^2.17.2",
"@kitware/vtk.js": "32.1.1",
"react-color": "^2.19.3"
}
@@ -1,5 +1,5 @@
function createSEGToolGroupAndAddTools(ToolGroupService, customizationService, toolGroupId) {
const { tools } = customizationService.get('cornerstone.overlayViewportTools') ?? {};
const tools = customizationService.getCustomization('cornerstone.overlayViewportTools');
return ToolGroupService.createToolGroupAndAddTools(toolGroupId, tools);
}
@@ -3,6 +3,181 @@
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.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
# [3.10.0-beta.76](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.75...v3.10.0-beta.76) (2025-01-27)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
# [3.10.0-beta.75](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.74...v3.10.0-beta.75) (2025-01-27)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
# [3.10.0-beta.74](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.73...v3.10.0-beta.74) (2025-01-27)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
# [3.10.0-beta.73](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.72...v3.10.0-beta.73) (2025-01-24)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
# [3.10.0-beta.72](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.71...v3.10.0-beta.72) (2025-01-24)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
# [3.10.0-beta.71](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.70...v3.10.0-beta.71) (2025-01-23)
### Features
* **customization:** new customization service api ([#4688](https://github.com/OHIF/Viewers/issues/4688)) ([55ad8ef](https://github.com/OHIF/Viewers/commit/55ad8efbabc3fabd8031fc08927b2f92ae5aec69))
# [3.10.0-beta.70](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.69...v3.10.0-beta.70) (2025-01-23)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
# [3.10.0-beta.69](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.68...v3.10.0-beta.69) (2025-01-22)
### Bug Fixes
* **seg:** sphere scissor on stack and cpu rendering reset properties was broken ([#4721](https://github.com/OHIF/Viewers/issues/4721)) ([f00d182](https://github.com/OHIF/Viewers/commit/f00d18292f02e8910215d913edfc994850a68d88))
# [3.10.0-beta.68](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.67...v3.10.0-beta.68) (2025-01-21)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
# [3.10.0-beta.67](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.66...v3.10.0-beta.67) (2025-01-21)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
# [3.10.0-beta.66](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.65...v3.10.0-beta.66) (2025-01-21)
### Bug Fixes
* Inconsistent Handling of Patient Name Tag ([#4703](https://github.com/OHIF/Viewers/issues/4703)) ([8aedb2e](https://github.com/OHIF/Viewers/commit/8aedb2ec54a0ccf2550f745fed6f0b8aa184a860))
# [3.10.0-beta.65](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.64...v3.10.0-beta.65) (2025-01-20)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
# [3.10.0-beta.64](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.63...v3.10.0-beta.64) (2025-01-20)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
# [3.10.0-beta.63](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.62...v3.10.0-beta.63) (2025-01-17)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
# [3.10.0-beta.62](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.61...v3.10.0-beta.62) (2025-01-16)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
# [3.10.0-beta.61](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.60...v3.10.0-beta.61) (2025-01-16)
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
# [3.10.0-beta.60](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.59...v3.10.0-beta.60) (2025-01-15)
### Bug Fixes
* Having sop instance in a per-frame or shared attribute breaks load ([#4560](https://github.com/OHIF/Viewers/issues/4560)) ([cded082](https://github.com/OHIF/Viewers/commit/cded08261788143e0d5be57a55c927fd96aafb22))
# [3.10.0-beta.59](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.58...v3.10.0-beta.59) (2025-01-14)
### Bug Fixes
* cs dicom sr commands module ([#4683](https://github.com/OHIF/Viewers/issues/4683)) ([2d611d0](https://github.com/OHIF/Viewers/commit/2d611d06ed759bbd1e83ccfac7dceeff9eb6238e))
# [3.10.0-beta.58](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.57...v3.10.0-beta.58) (2025-01-13)
**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.58",
"version": "3.10.0-beta.78",
"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.58",
"@ohif/extension-cornerstone": "3.10.0-beta.58",
"@ohif/extension-measurement-tracking": "3.10.0-beta.58",
"@ohif/ui": "3.10.0-beta.58",
"@ohif/core": "3.10.0-beta.78",
"@ohif/extension-cornerstone": "3.10.0-beta.78",
"@ohif/extension-measurement-tracking": "3.10.0-beta.78",
"@ohif/ui": "3.10.0-beta.78",
"dcmjs": "*",
"dicom-parser": "^1.8.9",
"hammerjs": "^2.0.8",
@@ -46,9 +46,9 @@
},
"dependencies": {
"@babel/runtime": "^7.20.13",
"@cornerstonejs/adapters": "^2.14.7",
"@cornerstonejs/core": "^2.14.7",
"@cornerstonejs/tools": "^2.14.7",
"@cornerstonejs/adapters": "^2.17.2",
"@cornerstonejs/core": "^2.17.2",
"@cornerstonejs/tools": "^2.17.2",
"classnames": "^2.3.2"
}
}
@@ -1,9 +1,8 @@
import { metaData, utilities } from '@cornerstonejs/core';
import OHIF, { DicomMetadataStore, utils } from '@ohif/core';
import OHIF, { DicomMetadataStore } from '@ohif/core';
import dcmjs from 'dcmjs';
import { adaptersSR } from '@cornerstonejs/adapters';
import { showLabelAnnotationPopup, colorPickerDialog } from '@ohif/extension-default';
import getFilteredCornerstoneToolState from './utils/getFilteredCornerstoneToolState';
import hydrateStructuredReport from './utils/hydrateStructuredReport';
@@ -42,9 +41,8 @@ const _generateReport = (measurementData, additionalFindingTypes, options = {})
};
const commandsModule = (props: withAppTypes) => {
const { servicesManager, extensionManager, commandsManager } = props;
const { customizationService, measurementService, viewportGridService, uiDialogService } =
servicesManager.services;
const { servicesManager, extensionManager } = props;
const { customizationService, viewportGridService, displaySetService } = servicesManager.services;
const actions = {
changeColorMeasurement: ({ uid }) => {
@@ -76,7 +74,7 @@ const commandsModule = (props: withAppTypes) => {
* that you wish to serialize.
*/
downloadReport: ({ measurementData, additionalFindingTypes, options = {} }) => {
const srDataset = actions.generateReport(measurementData, additionalFindingTypes, options);
const srDataset = _generateReport(measurementData, additionalFindingTypes, options);
const reportBlob = dcmjs.data.datasetToBlob(srDataset);
//Create a URL for the binary.
@@ -120,12 +118,11 @@ const commandsModule = (props: withAppTypes) => {
throw new Error('Invalid report, no content');
}
const onBeforeDicomStore =
customizationService.getModeCustomization('onBeforeDicomStore')?.value;
const onBeforeDicomStore = customizationService.getCustomization('onBeforeDicomStore');
let dicomDict;
if (typeof onBeforeDicomStore === 'function') {
dicomDict = onBeforeDicomStore({ measurementData, naturalizedReport });
dicomDict = onBeforeDicomStore({ dicomDict, measurementData, naturalizedReport });
}
await dataSource.store.dicom(naturalizedReport, null, dicomDict);
@@ -153,7 +150,7 @@ const commandsModule = (props: withAppTypes) => {
*/
loadSRMeasurements: ({ displaySetInstanceUID }) => {
const { SeriesInstanceUIDs } = hydrateStructuredReport(
{ servicesManager, extensionManager },
{ servicesManager, extensionManager, commandsManager },
displaySetInstanceUID
);
@@ -263,9 +263,9 @@ function _checkIfCanAddMeasurementsToDisplaySet(
for (let j = unloadedMeasurements.length - 1; j >= 0; j--) {
let measurement = unloadedMeasurements[j];
const onBeforeSRAddMeasurement = customizationService.getModeCustomization(
const onBeforeSRAddMeasurement = customizationService.getCustomization(
'onBeforeSRAddMeasurement'
)?.value;
);
if (typeof onBeforeSRAddMeasurement === 'function') {
measurement = onBeforeSRAddMeasurement({
@@ -25,7 +25,7 @@ const contentItemFormatters = {
return `${NumericValue} ${CodeValue}`;
},
PNAME: contentItem => {
const personName = contentItem.PersonName?.[0]?.Alphabetic;
const personName = contentItem.PersonName?.[0];
return personName ? utils.formatPN(personName) : undefined;
},
DATE: contentItem => {
@@ -41,22 +41,14 @@ const convertSites = (codingValues, sites) => {
*
*/
export default function hydrateStructuredReport(
{ servicesManager, extensionManager }: withAppTypes,
{ servicesManager, extensionManager, commandsManager }: withAppTypes,
displaySetInstanceUID
) {
const annotationManager = CsAnnotation.state.getAnnotationManager();
const dataSource = extensionManager.getActiveDataSource()[0];
const { measurementService, displaySetService, customizationService } = servicesManager.services;
const codingValues = customizationService.getCustomization('codingValues', {});
const { disableEditing } = customizationService.getCustomization(
'PanelMeasurement.disableEditing',
{
id: 'default.disableEditing',
disableEditing: false,
}
);
const codingValues = customizationService.getCustomization('codingValues');
const disableEditing = customizationService.getCustomization('panelMeasurement.disableEditing');
const displaySet = displaySetService.getDisplaySetByUID(displaySetInstanceUID);
@@ -107,8 +99,7 @@ export default function hydrateStructuredReport(
metaData
);
const onBeforeSRHydration =
customizationService.getModeCustomization('onBeforeSRHydration')?.value;
const onBeforeSRHydration = customizationService.getCustomization('onBeforeSRHydration')?.value;
if (typeof onBeforeSRHydration === 'function') {
storedMeasurementByAnnotationType = onBeforeSRHydration({
@@ -230,8 +221,7 @@ export default function hydrateStructuredReport(
});
if (disableEditing) {
const addedAnnotation = annotationManager.getAnnotation(newAnnotationUID);
locking.setAnnotationLocked(addedAnnotation, true);
locking.setAnnotationLocked(newAnnotationUID, true);
}
if (!imageIds.includes(imageId)) {
@@ -3,6 +3,178 @@
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.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
# [3.10.0-beta.76](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.75...v3.10.0-beta.76) (2025-01-27)
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
# [3.10.0-beta.75](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.74...v3.10.0-beta.75) (2025-01-27)
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
# [3.10.0-beta.74](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.73...v3.10.0-beta.74) (2025-01-27)
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
# [3.10.0-beta.73](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.72...v3.10.0-beta.73) (2025-01-24)
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
# [3.10.0-beta.72](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.71...v3.10.0-beta.72) (2025-01-24)
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
# [3.10.0-beta.71](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.70...v3.10.0-beta.71) (2025-01-23)
### Features
* **customization:** new customization service api ([#4688](https://github.com/OHIF/Viewers/issues/4688)) ([55ad8ef](https://github.com/OHIF/Viewers/commit/55ad8efbabc3fabd8031fc08927b2f92ae5aec69))
# [3.10.0-beta.70](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.69...v3.10.0-beta.70) (2025-01-23)
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
# [3.10.0-beta.69](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.68...v3.10.0-beta.69) (2025-01-22)
### Bug Fixes
* **seg:** sphere scissor on stack and cpu rendering reset properties was broken ([#4721](https://github.com/OHIF/Viewers/issues/4721)) ([f00d182](https://github.com/OHIF/Viewers/commit/f00d18292f02e8910215d913edfc994850a68d88))
# [3.10.0-beta.68](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.67...v3.10.0-beta.68) (2025-01-21)
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
# [3.10.0-beta.67](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.66...v3.10.0-beta.67) (2025-01-21)
### Bug Fixes
* **ui:** Update dependencies and add missing icons ([#4699](https://github.com/OHIF/Viewers/issues/4699)) ([cf97fa9](https://github.com/OHIF/Viewers/commit/cf97fa9b7b9687a9b73c1cf6926bc9fbc39b6512))
# [3.10.0-beta.66](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.65...v3.10.0-beta.66) (2025-01-21)
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
# [3.10.0-beta.65](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.64...v3.10.0-beta.65) (2025-01-20)
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
# [3.10.0-beta.64](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.63...v3.10.0-beta.64) (2025-01-20)
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
# [3.10.0-beta.63](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.62...v3.10.0-beta.63) (2025-01-17)
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
# [3.10.0-beta.62](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.61...v3.10.0-beta.62) (2025-01-16)
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
# [3.10.0-beta.61](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.60...v3.10.0-beta.61) (2025-01-16)
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
# [3.10.0-beta.60](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.59...v3.10.0-beta.60) (2025-01-15)
### Bug Fixes
* Having sop instance in a per-frame or shared attribute breaks load ([#4560](https://github.com/OHIF/Viewers/issues/4560)) ([cded082](https://github.com/OHIF/Viewers/commit/cded08261788143e0d5be57a55c927fd96aafb22))
# [3.10.0-beta.59](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.58...v3.10.0-beta.59) (2025-01-14)
**Note:** Version bump only for package @ohif/extension-cornerstone-dynamic-volume
# [3.10.0-beta.58](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.57...v3.10.0-beta.58) (2025-01-13)
**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.58",
"version": "3.10.0-beta.78",
"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.58",
"@ohif/extension-cornerstone": "3.10.0-beta.58",
"@ohif/extension-default": "3.10.0-beta.58",
"@ohif/i18n": "3.10.0-beta.58",
"@ohif/ui": "3.10.0-beta.58",
"@ohif/core": "3.10.0-beta.78",
"@ohif/extension-cornerstone": "3.10.0-beta.78",
"@ohif/extension-default": "3.10.0-beta.78",
"@ohif/i18n": "3.10.0-beta.78",
"@ohif/ui": "3.10.0-beta.78",
"dcmjs": "*",
"dicom-parser": "^1.8.21",
"hammerjs": "^2.0.8",
@@ -42,8 +42,8 @@
},
"dependencies": {
"@babel/runtime": "^7.20.13",
"@cornerstonejs/core": "^2.14.7",
"@cornerstonejs/tools": "^2.14.7",
"@cornerstonejs/core": "^2.17.2",
"@cornerstonejs/tools": "^2.17.2",
"classnames": "^2.3.2"
}
}
@@ -218,10 +218,6 @@ export default function PanelGenerateImage({ servicesManager, commandsManager }:
setTimePointsRangeToUseForGenerate(newValues);
}
if (!dynamicVolume || timePointsRange.length === 0) {
return null;
}
return (
<DynamicVolumeControls
fps={frameRate}
@@ -5,7 +5,7 @@ function WorkflowPanel({ servicesManager }: { servicesManager: ServicesManager }
const ProgressDropdownWithService =
servicesManager.services.customizationService.getCustomization(
'progressDropdownWithServiceComponent'
).component;
);
return (
<div
+184
View File
@@ -3,6 +3,190 @@
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.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)
### Bug Fixes
* for initialImageIndex mismatch issue for loading SR after disabling prompts ([#4732](https://github.com/OHIF/Viewers/issues/4732)) ([8e3e208](https://github.com/OHIF/Viewers/commit/8e3e2085d45eba230d0210849b65a6e609c9d81a))
# [3.10.0-beta.76](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.75...v3.10.0-beta.76) (2025-01-27)
**Note:** Version bump only for package @ohif/extension-cornerstone
# [3.10.0-beta.75](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.74...v3.10.0-beta.75) (2025-01-27)
**Note:** Version bump only for package @ohif/extension-cornerstone
# [3.10.0-beta.74](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.73...v3.10.0-beta.74) (2025-01-27)
**Note:** Version bump only for package @ohif/extension-cornerstone
# [3.10.0-beta.73](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.72...v3.10.0-beta.73) (2025-01-24)
**Note:** Version bump only for package @ohif/extension-cornerstone
# [3.10.0-beta.72](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.71...v3.10.0-beta.72) (2025-01-24)
### Features
* delete active annotation using backspace/delete key ([#4722](https://github.com/OHIF/Viewers/issues/4722)) ([d6f0092](https://github.com/OHIF/Viewers/commit/d6f0092a3236cecb5d04ec46c8ad01600500831e))
# [3.10.0-beta.71](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.70...v3.10.0-beta.71) (2025-01-23)
### Features
* **customization:** new customization service api ([#4688](https://github.com/OHIF/Viewers/issues/4688)) ([55ad8ef](https://github.com/OHIF/Viewers/commit/55ad8efbabc3fabd8031fc08927b2f92ae5aec69))
# [3.10.0-beta.70](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.69...v3.10.0-beta.70) (2025-01-23)
**Note:** Version bump only for package @ohif/extension-cornerstone
# [3.10.0-beta.69](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.68...v3.10.0-beta.69) (2025-01-22)
### Bug Fixes
* **seg:** sphere scissor on stack and cpu rendering reset properties was broken ([#4721](https://github.com/OHIF/Viewers/issues/4721)) ([f00d182](https://github.com/OHIF/Viewers/commit/f00d18292f02e8910215d913edfc994850a68d88))
# [3.10.0-beta.68](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.67...v3.10.0-beta.68) (2025-01-21)
**Note:** Version bump only for package @ohif/extension-cornerstone
# [3.10.0-beta.67](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.66...v3.10.0-beta.67) (2025-01-21)
### Bug Fixes
* **ui:** Update dependencies and add missing icons ([#4699](https://github.com/OHIF/Viewers/issues/4699)) ([cf97fa9](https://github.com/OHIF/Viewers/commit/cf97fa9b7b9687a9b73c1cf6926bc9fbc39b6512))
# [3.10.0-beta.66](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.65...v3.10.0-beta.66) (2025-01-21)
### Bug Fixes
* Inconsistent Handling of Patient Name Tag ([#4703](https://github.com/OHIF/Viewers/issues/4703)) ([8aedb2e](https://github.com/OHIF/Viewers/commit/8aedb2ec54a0ccf2550f745fed6f0b8aa184a860))
# [3.10.0-beta.65](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.64...v3.10.0-beta.65) (2025-01-20)
### Bug Fixes
* **rotation:** support cycling rotateViewportCCW ([#4533](https://github.com/OHIF/Viewers/issues/4533)) ([bf58707](https://github.com/OHIF/Viewers/commit/bf587070cccd344f5e8817e9954ba9f2e46b81bb))
# [3.10.0-beta.64](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.63...v3.10.0-beta.64) (2025-01-20)
**Note:** Version bump only for package @ohif/extension-cornerstone
# [3.10.0-beta.63](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.62...v3.10.0-beta.63) (2025-01-17)
**Note:** Version bump only for package @ohif/extension-cornerstone
# [3.10.0-beta.62](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.61...v3.10.0-beta.62) (2025-01-16)
**Note:** Version bump only for package @ohif/extension-cornerstone
# [3.10.0-beta.61](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.60...v3.10.0-beta.61) (2025-01-16)
**Note:** Version bump only for package @ohif/extension-cornerstone
# [3.10.0-beta.60](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.59...v3.10.0-beta.60) (2025-01-15)
### Bug Fixes
* Having sop instance in a per-frame or shared attribute breaks load ([#4560](https://github.com/OHIF/Viewers/issues/4560)) ([cded082](https://github.com/OHIF/Viewers/commit/cded08261788143e0d5be57a55c927fd96aafb22))
# [3.10.0-beta.59](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.58...v3.10.0-beta.59) (2025-01-14)
**Note:** Version bump only for package @ohif/extension-cornerstone
# [3.10.0-beta.58](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.57...v3.10.0-beta.58) (2025-01-13)
+7 -7
View File
@@ -1,6 +1,6 @@
{
"name": "@ohif/extension-cornerstone",
"version": "3.10.0-beta.58",
"version": "3.10.0-beta.78",
"description": "OHIF extension for Cornerstone",
"author": "OHIF",
"license": "MIT",
@@ -38,10 +38,10 @@
"@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.14.7",
"@cornerstonejs/dicom-image-loader": "^2.17.2",
"@icr/polyseg-wasm": "^0.4.0",
"@ohif/core": "3.10.0-beta.58",
"@ohif/ui": "3.10.0-beta.58",
"@ohif/core": "3.10.0-beta.78",
"@ohif/ui": "3.10.0-beta.78",
"dcmjs": "*",
"dicom-parser": "^1.8.21",
"hammerjs": "^2.0.8",
@@ -55,9 +55,9 @@
},
"dependencies": {
"@babel/runtime": "^7.20.13",
"@cornerstonejs/adapters": "^2.14.7",
"@cornerstonejs/core": "^2.14.7",
"@cornerstonejs/tools": "^2.14.7",
"@cornerstonejs/adapters": "^2.17.2",
"@cornerstonejs/core": "^2.17.2",
"@cornerstonejs/tools": "^2.17.2",
"@icr/polyseg-wasm": "^0.4.0",
"@kitware/vtk.js": "32.1.1",
"html2canvas": "^1.4.1",
@@ -5,12 +5,14 @@ import { metaData, Enums, utilities } from '@cornerstonejs/core';
import type { ImageSliceData } from '@cornerstonejs/core/types';
import { ViewportOverlay } from '@ohif/ui';
import type { InstanceMetadata } from '@ohif/core/src/types';
import { formatPN, formatDICOMDate, formatDICOMTime, formatNumberPrecision } from './utils';
import { formatDICOMDate, formatDICOMTime, formatNumberPrecision } from './utils';
import { utils } from '@ohif/core';
import { StackViewportData, VolumeViewportData } from '../../types/CornerstoneCacheService';
import './CustomizableViewportOverlay.css';
const EPSILON = 1e-4;
const { formatPN } = utils;
type ViewportData = StackViewportData | VolumeViewportData;
@@ -45,80 +47,6 @@ const OverlayItemComponents = {
'ohif.overlayItem.instanceNumber': InstanceNumberOverlayItem,
};
const studyDateItem = {
id: 'StudyDate',
customizationType: 'ohif.overlayItem',
label: '',
title: 'Study date',
condition: ({ referenceInstance }) => referenceInstance?.StudyDate,
contentF: ({ referenceInstance, formatters: { formatDate } }) =>
formatDate(referenceInstance.StudyDate),
};
const seriesDescriptionItem = {
id: 'SeriesDescription',
customizationType: 'ohif.overlayItem',
label: '',
title: 'Series description',
condition: ({ referenceInstance }) => {
return referenceInstance && referenceInstance.SeriesDescription;
},
contentF: ({ referenceInstance }) => referenceInstance.SeriesDescription,
};
const topLeftItems = {
id: 'cornerstoneOverlayTopLeft',
items: [studyDateItem, seriesDescriptionItem],
};
const topRightItems = { id: 'cornerstoneOverlayTopRight', items: [] };
const bottomLeftItems = {
id: 'cornerstoneOverlayBottomLeft',
items: [
{
id: 'WindowLevel',
customizationType: 'ohif.overlayItem.windowLevel',
},
{
id: 'ZoomLevel',
customizationType: 'ohif.overlayItem.zoomLevel',
condition: props => {
const activeToolName = props.toolGroupService.getActiveToolForViewport(props.viewportId);
return activeToolName === 'Zoom';
},
},
],
};
const bottomRightItems = {
id: 'cornerstoneOverlayBottomRight',
items: [
{
id: 'InstanceNumber',
customizationType: 'ohif.overlayItem.instanceNumber',
},
],
};
/**
* The @ohif/cornerstoneOverlay is a default value for a customization
* for the cornerstone overlays. The intent is to allow it to be extended
* without needing to re-write the individual overlays by using the append
* mechanism. Individual attributes can be modified individually without
* affecting the other items by using the append as well, with position
* based replacement.
* This is used as a default in the getCustomizationModule so that it
* is available early for additional customization extensions.
*/
const CornerstoneOverlay = {
id: '@ohif/cornerstoneOverlay',
topLeftItems,
topRightItems,
bottomLeftItems,
bottomRightItems,
};
/**
* Customizable Viewport Overlay
*/
@@ -141,26 +69,18 @@ function CustomizableViewportOverlay({
const [scale, setScale] = useState(1);
const { imageIndex } = imageSliceData;
// The new customization is 'cornerstoneOverlay', with an append or replace
// on the individual items rather than defining individual items.
const cornerstoneOverlay = customizationService.getCustomization('@ohif/cornerstoneOverlay');
// Historical usage defined the overlays as separate items due to lack of
// append functionality. This code enables the historical usage, but
// the recommended functionality is to append to the default values in
// cornerstoneOverlay rather than defining individual items.
const topLeftCustomization =
customizationService.getCustomization('cornerstoneOverlayTopLeft') ||
cornerstoneOverlay?.topLeftItems;
const topRightCustomization =
customizationService.getCustomization('cornerstoneOverlayTopRight') ||
cornerstoneOverlay?.topRightItems;
const bottomLeftCustomization =
customizationService.getCustomization('cornerstoneOverlayBottomLeft') ||
cornerstoneOverlay?.bottomLeftItems;
const bottomRightCustomization =
customizationService.getCustomization('cornerstoneOverlayBottomRight') ||
cornerstoneOverlay?.bottomRightItems;
const topLeftCustomization = customizationService.getCustomization('viewportOverlay.topLeft');
const topRightCustomization = customizationService.getCustomization('viewportOverlay.topRight');
const bottomLeftCustomization = customizationService.getCustomization(
'viewportOverlay.bottomLeft'
);
const bottomRightCustomization = customizationService.getCustomization(
'viewportOverlay.bottomRight'
);
const instanceNumber = useMemo(
() =>
@@ -262,8 +182,8 @@ function CustomizableViewportOverlay({
return null;
}
const { customizationType } = item;
const OverlayItemComponent = OverlayItemComponents[customizationType];
const { inheritsFrom } = item;
const OverlayItemComponent = OverlayItemComponents[inheritsFrom];
if (OverlayItemComponent) {
return <OverlayItemComponent {...overlayItemProps} />;
@@ -291,10 +211,6 @@ function CustomizableViewportOverlay({
const getContent = useCallback(
(customization, keyPrefix) => {
if (!customization?.items) {
return null;
}
const { items } = customization;
const props = {
...displaySetProps,
formatters: { formatDate: formatDICOMDate },
@@ -307,7 +223,7 @@ function CustomizableViewportOverlay({
return (
<>
{items.map((item, index) => (
{customization.map((item, index) => (
<div key={`${keyPrefix}_${index}`}>
{((!item?.condition || item.condition(props)) && _renderOverlayItem(item, props)) ||
null}
@@ -531,4 +447,4 @@ CustomizableViewportOverlay.propTypes = {
export default CustomizableViewportOverlay;
export { CustomizableViewportOverlay, CornerstoneOverlay };
export { CustomizableViewportOverlay };
@@ -52,31 +52,6 @@ export function formatDICOMTime(time, strFormat = 'HH:mm:ss') {
return moment(time, 'HH:mm:ss').format(strFormat);
}
/**
* Formats a patient name for display purposes
*
* @param {string} name
* @returns {string} formatted name.
*/
export function formatPN(name) {
if (!name) {
return '';
}
if (typeof name === 'object') {
name = name.Alphabetic;
if (!name) {
return '';
}
}
const cleaned = name
.split('^')
.filter(s => !!s)
.join(', ')
.trim();
return cleaned === ',' || cleaned === '' ? '' : cleaned;
}
/**
* Gets compression type
*
+31 -9
View File
@@ -13,6 +13,7 @@ import {
ReferenceLinesTool,
annotation,
} from '@cornerstonejs/tools';
import * as cornerstoneTools from '@cornerstonejs/tools';
import { Types as OhifTypes, utils } from '@ohif/core';
import i18n from '@ohif/i18n';
@@ -123,7 +124,11 @@ function commandsModule({
type,
});
},
updateStoredPositionPresentation: ({ viewportId, displaySetInstanceUID }) => {
updateStoredPositionPresentation: ({
viewportId,
displaySetInstanceUID,
referencedImageId,
}) => {
const presentations = cornerstoneViewportService.getPresentations(viewportId);
const { positionPresentationStore, setPositionPresentation, getPositionPresentationId } =
usePositionPresentationStore.getState();
@@ -135,10 +140,18 @@ function commandsModule({
)?.[0];
if (previousReferencedDisplaySetStoreKey) {
setPositionPresentation(
previousReferencedDisplaySetStoreKey,
presentations.positionPresentation
);
if (referencedImageId) {
setPositionPresentation(previousReferencedDisplaySetStoreKey, {
viewReference: {
referencedImageId,
},
});
} else {
setPositionPresentation(
previousReferencedDisplaySetStoreKey,
presentations.positionPresentation
);
}
return;
}
@@ -194,7 +207,7 @@ function commandsModule({
* on the measurement with a response if not cancelled.
*/
setMeasurementLabel: ({ uid }) => {
const labelConfig = customizationService.get('measurementLabels');
const labelConfig = customizationService.getCustomization('measurementLabels');
const measurement = measurementService.getMeasurement(uid);
showLabelAnnotationPopup(measurement, uiDialogService, labelConfig).then(
(val: Map<any, any>) => {
@@ -311,7 +324,7 @@ function commandsModule({
},
renameMeasurement: ({ uid }) => {
const labelConfig = customizationService.get('measurementLabels');
const labelConfig = customizationService.getCustomization('measurementLabels');
const measurement = measurementService.getMeasurement(uid);
showLabelAnnotationPopup(measurement, uiDialogService, labelConfig).then(val => {
measurementService.update(
@@ -362,7 +375,7 @@ function commandsModule({
viewportGridService.setActiveViewportId(viewportId);
},
arrowTextCallback: ({ callback, data, uid }) => {
const labelConfig = customizationService.get('measurementLabels');
const labelConfig = customizationService.getCustomization('measurementLabels');
callLabelAutocompleteDialog(uiDialogService, callback, {}, labelConfig);
},
toggleCine: () => {
@@ -569,7 +582,7 @@ function commandsModule({
} else if (viewport.getRotation !== undefined) {
const presentation = viewport.getViewPresentation();
const { rotation: currentRotation } = presentation;
const newRotation = (currentRotation + rotation) % 360;
const newRotation = (currentRotation + rotation + 360) % 360;
viewport.setViewPresentation({ rotation: newRotation });
viewport.render();
}
@@ -1298,6 +1311,12 @@ function commandsModule({
viewportGridService.getActiveViewportId()
);
},
deleteActiveAnnotation: () => {
const activeAnnotationsUID = cornerstoneTools.annotation.selection.getAnnotationsSelected();
activeAnnotationsUID.forEach(activeAnnotationUID => {
measurementService.remove(activeAnnotationUID);
});
},
};
const definitions = {
@@ -1558,6 +1577,9 @@ function commandsModule({
getRenderInactiveSegmentations: {
commandFn: actions.getRenderInactiveSegmentations,
},
deleteActiveAnnotation: {
commandFn: actions.deleteActiveAnnotation,
},
};
return {
@@ -1,5 +1,5 @@
import React, { useCallback, useEffect, useState, useRef } from 'react';
import { CinePlayer, useCine } from '@ohif/ui';
import { useCine } from '@ohif/ui';
import { Enums, eventTarget, cache } from '@cornerstonejs/core';
import { useAppConfig } from '@state';
@@ -160,8 +160,7 @@ function RenderCinePlayer({
dynamicInfo: dynamicInfoProp,
customizationService,
}) {
const { component: CinePlayerComponent = CinePlayer } =
customizationService.get('cinePlayer') ?? {};
const CinePlayerComponent = customizationService.getCustomization('cinePlayer');
const [dynamicInfo, setDynamicInfo] = useState(dynamicInfoProp);
@@ -51,7 +51,7 @@ export function WindowLevelActionMenu({
const { colorbarService, cornerstoneViewportService } = servicesManager.services;
const viewportInfo = cornerstoneViewportService.getViewportInfo(viewportId);
const viewport = cornerstoneViewportService.getCornerstoneViewport(viewportId);
const backgroundColor = viewportInfo.getViewportOptions().background;
const backgroundColor = viewportInfo?.getViewportOptions().background;
const isLight = backgroundColor ? utilities.isEqual(backgroundColor, [1, 1, 1]) : false;
const { t } = useTranslation('WindowLevelActionMenu');
@@ -2,21 +2,21 @@
// configured via the customization service.
const defaultWindowLevelPresets = {
CT: [
{ description: 'Soft tissue', window: '400', level: '40' },
{ description: 'Lung', window: '1500', level: '-600' },
{ description: 'Liver', window: '150', level: '90' },
{ description: 'Bone', window: '2500', level: '480' },
{ description: 'Brain', window: '80', level: '40' },
{ id: 'ct-soft-tissue', description: 'Soft tissue', window: '400', level: '40' },
{ id: 'ct-lung', description: 'Lung', window: '1500', level: '-600' },
{ id: 'ct-liver', description: 'Liver', window: '150', level: '90' },
{ id: 'ct-bone', description: 'Bone', window: '2500', level: '480' },
{ id: 'ct-brain', description: 'Brain', window: '80', level: '40' },
],
PT: [
{ description: 'Default', window: '5', level: '2.5' },
{ description: 'SUV', window: '0', level: '3' },
{ description: 'SUV', window: '0', level: '5' },
{ description: 'SUV', window: '0', level: '7' },
{ description: 'SUV', window: '0', level: '8' },
{ description: 'SUV', window: '0', level: '10' },
{ description: 'SUV', window: '0', level: '15' },
{ id: 'pt-default', description: 'Default', window: '5', level: '2.5' },
{ id: 'pt-suv-3', description: 'SUV', window: '0', level: '3' },
{ id: 'pt-suv-5', description: 'SUV', window: '0', level: '5' },
{ id: 'pt-suv-7', description: 'SUV', window: '0', level: '7' },
{ id: 'pt-suv-8', description: 'SUV', window: '0', level: '8' },
{ id: 'pt-suv-10', description: 'SUV', window: '0', level: '10' },
{ id: 'pt-suv-15', description: 'SUV', window: '0', level: '15' },
],
};
@@ -1,5 +1,5 @@
import React, { ReactNode } from 'react';
import { nonWLModalities, WindowLevelActionMenu } from './WindowLevelActionMenu';
import { nonWLModalities } from './WindowLevelActionMenu';
export function getWindowLevelActionMenu({
viewportId,
@@ -16,12 +16,13 @@ export function getWindowLevelActionMenu({
}>): ReactNode {
const { customizationService } = servicesManager.services;
const { presets } = customizationService.get('cornerstone.windowLevelPresets');
const colorbarProperties = customizationService.get('cornerstone.colorbar');
const { volumeRenderingPresets, volumeRenderingQualityRange } = customizationService.get(
'cornerstone.3dVolumeRendering'
const presets = customizationService.getCustomization('cornerstone.windowLevelPresets');
const colorbarProperties = customizationService.getCustomization('cornerstone.colorbar');
const { volumeRenderingPresets, volumeRenderingQualityRange } =
customizationService.getCustomization('cornerstone.3dVolumeRendering');
const WindowLevelActionMenu = customizationService.getCustomization(
'cornerstone.windowLevelActionMenu'
);
const displaySetPresets = displaySets
.filter(displaySet => presets[displaySet.Modality])
.map(displaySet => {
@@ -0,0 +1,13 @@
import { colormaps } from '../utils/colormaps';
const DefaultColormap = 'Grayscale';
export default {
'cornerstone.colorbar': {
width: '16px',
colorbarTickPosition: 'left',
colormaps,
colorbarContainerPosition: 'right',
colorbarInitialColormap: DefaultColormap,
},
};
@@ -0,0 +1,99 @@
export default {
'layoutSelector.advancedPresetGenerator': ({
servicesManager,
}: {
servicesManager: AppTypes.ServicesManager;
}) => {
const _areSelectorsValid = (
hp: AppTypes.HangingProtocol.Protocol,
displaySets: AppTypes.DisplaySet[],
hangingProtocolService: AppTypes.HangingProtocolService
) => {
if (!hp.displaySetSelectors || Object.values(hp.displaySetSelectors).length === 0) {
return true;
}
return hangingProtocolService.areRequiredSelectorsValid(
Object.values(hp.displaySetSelectors),
displaySets[0]
);
};
const generateAdvancedPresets = ({
servicesManager,
}: {
servicesManager: AppTypes.ServicesManager;
}) => {
const { hangingProtocolService, viewportGridService, displaySetService } =
servicesManager.services;
const hangingProtocols = Array.from(hangingProtocolService.protocols.values());
const viewportId = viewportGridService.getActiveViewportId();
if (!viewportId) {
return [];
}
const displaySetInsaneUIDs = viewportGridService.getDisplaySetsUIDsForViewport(viewportId);
if (!displaySetInsaneUIDs) {
return [];
}
const displaySets = displaySetInsaneUIDs.map(uid =>
displaySetService.getDisplaySetByUID(uid)
);
return hangingProtocols
.map(hp => {
if (!hp.isPreset) {
return null;
}
const areValid = _areSelectorsValid(hp, displaySets, hangingProtocolService);
return {
icon: hp.icon,
title: hp.name,
commandOptions: {
protocolId: hp.id,
},
disabled: !areValid,
};
})
.filter(preset => preset !== null);
};
return generateAdvancedPresets({ servicesManager });
},
'layoutSelector.commonPresets': [
{
icon: 'layout-common-1x1',
commandOptions: {
numRows: 1,
numCols: 1,
},
},
{
icon: 'layout-common-1x2',
commandOptions: {
numRows: 1,
numCols: 2,
},
},
{
icon: 'layout-common-2x2',
commandOptions: {
numRows: 2,
numCols: 2,
},
},
{
icon: 'layout-common-2x3',
commandOptions: {
numRows: 2,
numCols: 3,
},
},
],
};
@@ -0,0 +1,124 @@
export default {
'cornerstone.measurements': {
Angle: {
displayText: [],
report: [],
},
CobbAngle: {
displayText: [],
report: [],
},
ArrowAnnotate: {
displayText: [],
report: [],
},
RectangleROi: {
displayText: [],
report: [],
},
CircleROI: {
displayText: [],
report: [],
},
EllipticalROI: {
displayText: [],
report: [],
},
Bidirectional: {
displayText: [],
report: [],
},
Length: {
displayText: [],
report: [],
},
LivewireContour: {
displayText: [],
report: [],
},
SplineROI: {
displayText: [
{
displayName: 'Areas',
value: 'area',
type: 'value',
},
{
value: 'areaUnits',
for: ['area'],
type: 'unit',
},
],
report: [
{
displayName: 'Area',
value: 'area',
type: 'value',
},
{
displayName: 'Unit',
value: 'areaUnits',
type: 'value',
},
],
},
PlanarFreehandROI: {
displayTextOpen: [
{
displayName: 'Length',
value: 'length',
type: 'value',
},
],
displayText: [
{
displayName: 'Mean',
value: 'mean',
type: 'value',
},
{
displayName: 'Max',
value: 'max',
type: 'value',
},
{
displayName: 'Area',
value: 'area',
type: 'value',
},
{
value: 'pixelValueUnits',
for: ['mean', 'max'],
type: 'unit',
},
{
value: 'areaUnits',
for: ['area'],
type: 'unit',
},
],
report: [
{
displayName: 'Mean',
value: 'mean',
type: 'value',
},
{
displayName: 'Max',
value: 'max',
type: 'value',
},
{
displayName: 'Area',
value: 'area',
type: 'value',
},
{
displayName: 'Unit',
value: 'unit',
type: 'value',
},
],
},
},
};
@@ -0,0 +1,16 @@
import { CinePlayer } from '@ohif/ui';
import DicomUpload from '../components/DicomUpload/DicomUpload';
export default {
cinePlayer: CinePlayer,
autoCineModalities: ['OT', 'US'],
'panelMeasurement.disableEditing': false,
onBeforeSRAddMeasurement: ({ measurement, StudyInstanceUID, SeriesInstanceUID }) => {
return measurement;
},
onBeforeDicomStore: ({ dicomDict, measurementData, naturalizedReport }) => {
return dicomDict;
},
dicomUploadComponent: DicomUpload,
codingValues: {},
};
@@ -0,0 +1,95 @@
import React from 'react';
import {
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuLabel,
DropdownMenuPortal,
DropdownMenuSeparator,
DropdownMenuSub,
DropdownMenuSubContent,
DropdownMenuSubTrigger,
Icons,
} from '@ohif/ui-next';
export default function getSegmentationPanelCustomization({ commandsManager, servicesManager }) {
return {
'panelSegmentation.customDropdownMenuContent': ({
activeSegmentation,
onSegmentationAdd,
onSegmentationRemoveFromViewport,
onSegmentationEdit,
onSegmentationDelete,
allowExport,
storeSegmentation,
onSegmentationDownload,
onSegmentationDownloadRTSS,
t,
}) => (
<DropdownMenuContent align="start">
<DropdownMenuItem onClick={() => onSegmentationAdd(activeSegmentation.segmentationId)}>
<Icons.Add className="text-foreground" />
<span className="pl-2">{t('Create New Segmentation')}</span>
</DropdownMenuItem>
<DropdownMenuSeparator />
<DropdownMenuLabel>{t('Manage Current Segmentation')}</DropdownMenuLabel>
<DropdownMenuItem
onClick={() => onSegmentationRemoveFromViewport(activeSegmentation.segmentationId)}
>
<Icons.Series className="text-foreground" />
<span className="pl-2">{t('Remove from Viewport')}</span>
</DropdownMenuItem>
<DropdownMenuItem onClick={() => onSegmentationEdit(activeSegmentation.segmentationId)}>
<Icons.Rename className="text-foreground" />
<span className="pl-2">{t('Rename')}</span>
</DropdownMenuItem>
<DropdownMenuSub>
<DropdownMenuSubTrigger
disabled={!allowExport}
className="pl-1"
>
<Icons.Export className="text-foreground" />
<span className="pl-2">{t('Export & Download')}</span>
</DropdownMenuSubTrigger>
<DropdownMenuPortal>
<DropdownMenuSubContent>
<DropdownMenuItem
onClick={() => storeSegmentation(activeSegmentation.segmentationId)}
>
{t('Export DICOM SEG')}
</DropdownMenuItem>
<DropdownMenuItem
onClick={() => onSegmentationDownload(activeSegmentation.segmentationId)}
>
{t('Download DICOM SEG')}
</DropdownMenuItem>
</DropdownMenuSubContent>
</DropdownMenuPortal>
</DropdownMenuSub>
<DropdownMenuSeparator />
<DropdownMenuItem onClick={() => onSegmentationDelete(activeSegmentation.segmentationId)}>
<Icons.Delete className="text-red-600" />
<span className="pl-2 text-red-600">{t('Delete')}</span>
</DropdownMenuItem>
</DropdownMenuContent>
),
'panelSegmentation.disableEditing': false,
'panelSegmentation.showAddSegment': true,
'panelSegmentation.onSegmentationAdd': () => {
const { viewportGridService } = servicesManager.services;
const viewportId = viewportGridService.getState().activeViewportId;
commandsManager.run('createLabelmapForViewport', { viewportId });
},
'panelSegmentation.tableMode': 'collapsed',
'panelSegmentation.readableText': {
lesionStats: 'Lesion Statistics',
minValue: 'Minimum Value',
maxValue: 'Maximum Value',
meanValue: 'Mean Value',
volume: 'Volume (ml)',
suvPeak: 'SUV Peak',
suvMax: 'Maximum SUV',
suvMaxIJK: 'SUV Max IJK',
lesionGlyoclysisStats: 'Lesion Glycolysis',
},
};
}
@@ -0,0 +1,15 @@
export default {
cornerstoneViewportClickCommands: {
doubleClick: ['toggleOneUp'],
button1: ['closeContextMenu'],
button3: [
{
commandName: 'showCornerstoneContextMenu',
commandOptions: {
requireNearbyToolData: true,
menuId: 'measurementsContextMenu',
},
},
],
},
};
@@ -0,0 +1,44 @@
export default {
'viewportOverlay.topLeft': [
{
id: 'StudyDate',
inheritsFrom: 'ohif.overlayItem',
label: '',
title: 'Study date',
condition: ({ referenceInstance }) => referenceInstance?.StudyDate,
contentF: ({ referenceInstance, formatters: { formatDate } }) =>
formatDate(referenceInstance.StudyDate),
},
{
id: 'SeriesDescription',
inheritsFrom: 'ohif.overlayItem',
label: '',
title: 'Series description',
condition: ({ referenceInstance }) => {
return referenceInstance && referenceInstance.SeriesDescription;
},
contentF: ({ referenceInstance }) => referenceInstance.SeriesDescription,
},
],
'viewportOverlay.topRight': [],
'viewportOverlay.bottomLeft': [
{
id: 'WindowLevel',
inheritsFrom: 'ohif.overlayItem.windowLevel',
},
{
id: 'ZoomLevel',
inheritsFrom: 'ohif.overlayItem.zoomLevel',
condition: props => {
const activeToolName = props.toolGroupService.getActiveToolForViewport(props.viewportId);
return activeToolName === 'Zoom';
},
},
],
'viewportOverlay.bottomRight': [
{
id: 'InstanceNumber',
inheritsFrom: 'ohif.overlayItem.instanceNumber',
},
],
};
@@ -0,0 +1,33 @@
import { Enums } from '@cornerstonejs/tools';
import { toolNames } from '../initCornerstoneTools';
export default {
'cornerstone.overlayViewportTools': {
active: [
{
toolName: toolNames.WindowLevel,
bindings: [{ mouseButton: Enums.MouseBindings.Primary }],
},
{
toolName: toolNames.Pan,
bindings: [{ mouseButton: Enums.MouseBindings.Auxiliary }],
},
{
toolName: toolNames.Zoom,
bindings: [{ mouseButton: Enums.MouseBindings.Secondary }],
},
{
toolName: toolNames.StackScroll,
bindings: [{ mouseButton: Enums.MouseBindings.Wheel }],
},
],
enabled: [
{
toolName: toolNames.PlanarFreehandContourSegmentation,
configuration: {
displayOnePointAsCrosshairs: true,
},
},
],
},
};
@@ -0,0 +1,14 @@
import { CONSTANTS } from '@cornerstonejs/core';
const { VIEWPORT_PRESETS } = CONSTANTS;
export default {
'cornerstone.3dVolumeRendering': {
volumeRenderingPresets: VIEWPORT_PRESETS,
volumeRenderingQualityRange: {
min: 1,
max: 4,
step: 1,
},
},
};
@@ -0,0 +1,5 @@
import { WindowLevelActionMenu } from '../components/WindowLevelActionMenu/WindowLevelActionMenu';
export default {
'cornerstone.windowLevelActionMenu': WindowLevelActionMenu,
};
@@ -0,0 +1,5 @@
import defaultWindowLevelPresets from '../components/WindowLevelActionMenu/defaultWindowLevelPresets';
export default {
'cornerstone.windowLevelPresets': defaultWindowLevelPresets,
};
@@ -1,213 +0,0 @@
import { Enums } from '@cornerstonejs/tools';
import { toolNames } from './initCornerstoneTools';
import defaultWindowLevelPresets from './components/WindowLevelActionMenu/defaultWindowLevelPresets';
import { colormaps } from './utils/colormaps';
import { CONSTANTS } from '@cornerstonejs/core';
import { CornerstoneOverlay } from './Viewport/Overlays/CustomizableViewportOverlay';
const DefaultColormap = 'Grayscale';
const { VIEWPORT_PRESETS } = CONSTANTS;
const tools = {
active: [
{
toolName: toolNames.WindowLevel,
bindings: [{ mouseButton: Enums.MouseBindings.Primary }],
},
{
toolName: toolNames.Pan,
bindings: [{ mouseButton: Enums.MouseBindings.Auxiliary }],
},
{
toolName: toolNames.Zoom,
bindings: [{ mouseButton: Enums.MouseBindings.Secondary }],
},
{
toolName: toolNames.StackScroll,
bindings: [{ mouseButton: Enums.MouseBindings.Wheel }],
},
],
enabled: [
{
toolName: toolNames.PlanarFreehandContourSegmentation,
configuration: {
displayOnePointAsCrosshairs: true,
},
},
],
};
function getCustomizationModule() {
return [
{
name: 'default',
value: [
CornerstoneOverlay,
{
id: 'cornerstone.overlayViewportTools',
tools,
},
{
id: 'cornerstone.windowLevelPresets',
presets: defaultWindowLevelPresets,
},
{
id: 'cornerstone.colorbar',
width: '16px',
colorbarTickPosition: 'left',
colormaps,
colorbarContainerPosition: 'right',
colorbarInitialColormap: DefaultColormap,
},
{
id: 'cornerstone.3dVolumeRendering',
volumeRenderingPresets: VIEWPORT_PRESETS,
volumeRenderingQualityRange: {
min: 1,
max: 4,
step: 1,
},
},
{
id: 'cornerstone.measurements',
Angle: {
displayText: [],
report: [],
},
CobbAngle: {
displayText: [],
report: [],
},
ArrowAnnotate: {
displayText: [],
report: [],
},
RectangleROi: {
displayText: [],
report: [],
},
CircleROI: {
displayText: [],
report: [],
},
EllipticalROI: {
displayText: [],
report: [],
},
Bidirectional: {
displayText: [],
report: [],
},
Length: {
displayText: [],
report: [],
},
LivewireContour: {
displayText: [],
report: [],
},
SplineROI: {
displayText: [
{
displayName: 'Area',
value: 'area',
type: 'value',
},
{
value: 'areaUnits',
for: ['area'],
type: 'unit',
},
/**
{
displayName: 'Modality',
value: 'Modality',
type: 'value',
},
*/
],
report: [
{
displayName: 'Area',
value: 'area',
type: 'value',
},
{
displayName: 'Unit',
value: 'areaUnits',
type: 'value',
},
],
},
PlanarFreehandROI: {
displayTextOpen: [
{
displayName: 'Length',
value: 'length',
type: 'value',
},
],
displayText: [
{
displayName: 'Mean',
value: 'mean',
type: 'value',
},
{
displayName: 'Max',
value: 'max',
type: 'value',
},
{
displayName: 'Area',
value: 'area',
type: 'value',
},
{
value: 'pixelValueUnits',
for: ['mean', 'max' /** 'stdDev **/],
type: 'unit',
},
{
value: 'areaUnits',
for: ['area'],
type: 'unit',
},
/**
{
displayName: 'Std Dev',
value: 'stdDev',
type: 'value',
},
*/
],
report: [
{
displayName: 'Mean',
value: 'mean',
type: 'value',
},
{
displayName: 'Max',
value: 'max',
type: 'value',
},
{
displayName: 'Area',
value: 'area',
type: 'value',
},
{
displayName: 'Unit',
value: 'unit',
type: 'value',
},
],
},
},
],
},
];
}
export default getCustomizationModule;
@@ -0,0 +1,34 @@
import viewportOverlayCustomization from './customizations/viewportOverlayCustomization';
import getSegmentationPanelCustomization from './customizations/segmentationPanelCustomization';
import layoutSelectorCustomization from './customizations/layoutSelectorCustomization';
import viewportToolsCustomization from './customizations/viewportToolsCustomization';
import viewportClickCommandsCustomization from './customizations/viewportClickCommandsCustomization';
import measurementsCustomization from './customizations/measurementsCustomization';
import volumeRenderingCustomization from './customizations/volumeRenderingCustomization';
import colorbarCustomization from './customizations/colorbarCustomization';
import windowLevelPresetsCustomization from './customizations/windowLevelPresetsCustomization';
import miscCustomization from './customizations/miscCustomization';
import windowLevelActionMenuCustomization from './customizations/windowLevelActionMenuCustomization';
function getCustomizationModule({ commandsManager, servicesManager }) {
return [
{
name: 'default',
value: {
...viewportOverlayCustomization,
...getSegmentationPanelCustomization({ commandsManager, servicesManager }),
...layoutSelectorCustomization,
...viewportToolsCustomization,
...viewportClickCommandsCustomization,
...measurementsCustomization,
...volumeRenderingCustomization,
...colorbarCustomization,
...windowLevelPresetsCustomization,
...miscCustomization,
...windowLevelActionMenuCustomization,
},
},
];
}
export default getCustomizationModule;
@@ -12,10 +12,7 @@ function mapSegmentationToDisplay(segmentation, customizationService) {
const { label, segments } = segmentation;
// Get the readable text mapping once
const { readableText: readableTextMap } = customizationService.getCustomization(
'PanelSegmentation.readableText',
{}
);
const readableTextMap = customizationService.getCustomization('panelSegmentation.readableText');
// Helper function to recursively map cachedStats to readable display text
function mapStatsToDisplay(stats, indent = 0) {
@@ -7,10 +7,7 @@ function mapSegmentationToDisplay(segmentation, customizationService) {
const { label, segments } = segmentation;
// Get the readable text mapping once
const { readableText: readableTextMap } = customizationService.getCustomization(
'PanelSegmentation.readableText',
{}
);
const readableTextMap = customizationService.getCustomization('panelSegmentation.readableText');
// Helper function to recursively map cachedStats to readable display text
function mapStatsToDisplay(stats, indent = 0) {
+2 -4
View File
@@ -160,11 +160,9 @@ const cornerstoneExtension: Types.Extensions.Extension = {
ViewportActionCornersProvider
);
const { syncGroupService } = servicesManager.services;
const { syncGroupService, customizationService } = servicesManager.services;
syncGroupService.registerCustomSynchronizer('frameview', createFrameViewSynchronizer);
servicesManager.services.customizationService.setGlobalCustomization('dicomUploadComponent', {
component: props => <DicomUpload {...props} />,
});
return init.call(this, props);
},
getToolbarModule,
@@ -40,7 +40,7 @@ function _getSyncedViewports(servicesManager: AppTypes.ServicesManager, srcViewp
.filter(({ viewportId }) => {
const viewport = cornerstoneViewportService.getCornerstoneViewport(viewportId);
return viewportId !== srcViewportId && viewport?.hasVolumeId(srcVolumeId);
return viewportId !== srcViewportId && viewport?.hasVolumeId?.(srcVolumeId);
})
.map(({ viewportId }) => ({ viewportId }));
}
+5 -24
View File
@@ -5,27 +5,6 @@ import { findNearbyToolData } from './utils/findNearbyToolData';
const cs3DToolsEvents = Enums.Events;
const DEFAULT_CONTEXT_MENU_CLICKS = {
button1: {
commands: [
{
commandName: 'closeContextMenu',
},
],
},
button3: {
commands: [
{
commandName: 'showCornerstoneContextMenu',
commandOptions: {
requireNearbyToolData: true,
menuId: 'measurementsContextMenu',
},
},
],
},
};
/**
* Generates a name, consisting of:
* * alt when the alt key is down
@@ -60,8 +39,10 @@ function initContextMenu({
* defaults on button1 and button2
*/
const cornerstoneViewportHandleEvent = (name, evt) => {
const customizations =
customizationService.get('cornerstoneViewportClickCommands') || DEFAULT_CONTEXT_MENU_CLICKS;
const customizations = customizationService.getCustomization(
'cornerstoneViewportClickCommands'
);
const toRun = customizations[name];
if (!toRun) {
@@ -71,7 +52,7 @@ function initContextMenu({
// only find nearbyToolData if required, for the click (which closes the context menu
// we don't need to find nearbyToolData)
let nearbyToolData = null;
if (toRun.commands.some(command => command.commandOptions?.requireNearbyToolData)) {
if (toRun.some(command => command.commandOptions?.requireNearbyToolData)) {
nearbyToolData = findNearbyToolData(commandsManager, evt);
}
+4 -10
View File
@@ -1,17 +1,10 @@
import { eventTarget, EVENTS } from '@cornerstonejs/core';
import { Enums } from '@cornerstonejs/tools';
import { CommandsManager, CustomizationService, Types } from '@ohif/core';
import { CommandsManager, CustomizationService } from '@ohif/core';
import { findNearbyToolData } from './utils/findNearbyToolData';
const cs3DToolsEvents = Enums.Events;
const DEFAULT_DOUBLE_CLICK = {
doubleClick: {
commandName: 'toggleOneUp',
commandOptions: {},
},
};
/**
* Generates a double click event name, consisting of:
* * alt when the alt key is down
@@ -50,8 +43,9 @@ function initDoubleClick({ customizationService, commandsManager }: initDoubleCl
const eventName = getDoubleClickEventName(evt);
// Allows for the customization of the double click on a viewport.
const customizations =
customizationService.get('cornerstoneViewportClickCommands') || DEFAULT_DOUBLE_CLICK;
const customizations = customizationService.getCustomization(
'cornerstoneViewportClickCommands'
);
const toRun = customizations[eventName];
@@ -1,4 +1,4 @@
import React, { useEffect, useRef, useState } from 'react';
import React, { useEffect, useRef } from 'react';
import { utils } from '@ohif/core';
import { MeasurementTable } from '@ohif/ui-next';
import debounce from 'lodash.debounce';
@@ -1,16 +1,5 @@
import React from 'react';
import {
DropdownMenuLabel,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuPortal,
DropdownMenuSeparator,
DropdownMenuSub,
DropdownMenuSubContent,
Icons,
SegmentationTable,
DropdownMenuSubTrigger,
} from '@ohif/ui-next';
import { SegmentationTable } from '@ohif/ui-next';
import { useActiveViewportSegmentationRepresentations } from '../hooks/useActiveViewportSegmentationRepresentations';
import { metaData } from '@cornerstonejs/core';
@@ -19,7 +8,7 @@ export default function PanelSegmentation({
commandsManager,
children,
}: withAppTypes) {
const { customizationService, viewportGridService, displaySetService } = servicesManager.services;
const { customizationService, displaySetService } = servicesManager.services;
const { segmentationsWithRepresentations, disabled } =
useActiveViewportSegmentationRepresentations({
@@ -27,11 +16,6 @@ export default function PanelSegmentation({
});
const handlers = {
onSegmentationAdd: async () => {
const viewportId = viewportGridService.getState().activeViewportId;
commandsManager.run('createLabelmapForViewport', { viewportId });
},
onSegmentationClick: (segmentationId: string) => {
commandsManager.run('setActiveSegmentation', { segmentationId });
},
@@ -125,107 +109,19 @@ export default function PanelSegmentation({
},
};
const { mode: SegmentationTableMode } = customizationService.getCustomization(
'PanelSegmentation.tableMode',
{
id: 'default.segmentationTable.mode',
mode: 'collapsed',
}
const segmentationTableMode = customizationService.getCustomization(
'panelSegmentation.tableMode'
);
// custom onSegmentationAdd if provided
const { onSegmentationAdd } = customizationService.getCustomization(
'PanelSegmentation.onSegmentationAdd',
{
id: 'segmentation.onSegmentationAdd',
onSegmentationAdd: handlers.onSegmentationAdd,
}
const onSegmentationAdd = customizationService.getCustomization(
'panelSegmentation.onSegmentationAdd'
);
const { disableEditing } = customizationService.getCustomization(
'PanelSegmentation.disableEditing',
{
id: 'default.disableEditing',
disableEditing: false,
}
);
const { showAddSegment } = customizationService.getCustomization(
'PanelSegmentation.showAddSegment',
{
id: 'default.showAddSegment',
showAddSegment: true,
}
);
const CustomDropdownMenuContent = customizationService.getCustomComponent(
'PanelSegmentation.CustomDropdownMenuContent',
({
activeSegmentation,
onSegmentationAdd,
onSegmentationRemoveFromViewport,
onSegmentationEdit,
onSegmentationDelete,
allowExport,
storeSegmentation,
onSegmentationDownload,
onSegmentationDownloadRTSS,
t,
}) => {
return (
<DropdownMenuContent align="start">
<DropdownMenuItem onClick={() => onSegmentationAdd(activeSegmentation.segmentationId)}>
<Icons.Add className="text-foreground" />
<span className="pl-2">{t('Create New Segmentation')}</span>
</DropdownMenuItem>
<DropdownMenuSeparator />
<DropdownMenuLabel>{t('Manage Current Segmentation')}</DropdownMenuLabel>
<DropdownMenuItem
onClick={() => onSegmentationRemoveFromViewport(activeSegmentation.segmentationId)}
>
<Icons.Series className="text-foreground" />
<span className="pl-2">{t('Remove from Viewport')}</span>
</DropdownMenuItem>
<DropdownMenuItem onClick={() => onSegmentationEdit(activeSegmentation.segmentationId)}>
<Icons.Rename className="text-foreground" />
<span className="pl-2">{t('Rename')}</span>
</DropdownMenuItem>
<DropdownMenuSub>
<DropdownMenuSubTrigger
disabled={!allowExport}
className="pl-1"
>
<Icons.Export className="text-foreground" />
<span className="pl-2">{t('Export & Download')}</span>
</DropdownMenuSubTrigger>
<DropdownMenuPortal>
<DropdownMenuSubContent>
<DropdownMenuItem
onClick={() => storeSegmentation(activeSegmentation.segmentationId)}
>
{t('Export DICOM SEG')}
</DropdownMenuItem>
<DropdownMenuItem
onClick={() => onSegmentationDownload(activeSegmentation.segmentationId)}
>
{t('Download DICOM SEG')}
</DropdownMenuItem>
{/* <DropdownMenuItem
onClick={() => onSegmentationDownloadRTSS(activeSegmentation.segmentationId)}
>
{t('Download DICOM RTSTRUCT')}
</DropdownMenuItem> */}
</DropdownMenuSubContent>
</DropdownMenuPortal>
</DropdownMenuSub>
<DropdownMenuSeparator />
<DropdownMenuItem onClick={() => onSegmentationDelete(activeSegmentation.segmentationId)}>
<Icons.Delete className="text-red-600" />
<span className="pl-2 text-red-600">{t('Delete')}</span>
</DropdownMenuItem>
</DropdownMenuContent>
);
}
const disableEditing = customizationService.getCustomization('panelSegmentation.disableEditing');
const showAddSegment = customizationService.getCustomization('panelSegmentation.showAddSegment');
const CustomDropdownMenuContent = customizationService.getCustomization(
'panelSegmentation.customDropdownMenuContent'
);
const exportOptions = segmentationsWithRepresentations.map(({ segmentation }) => {
@@ -243,6 +139,14 @@ export default function PanelSegmentation({
const firstImageId = referencedImageIds[0];
const instance = metaData.get('instance', firstImageId);
if (!instance) {
return {
segmentationId,
isExportable: false,
};
}
const SOPInstanceUID = instance.SOPInstanceUID || instance.SopInstanceUID;
const SeriesInstanceUID = instance.SeriesInstanceUID;
@@ -264,7 +168,7 @@ export default function PanelSegmentation({
<SegmentationTable
disabled={disabled}
data={segmentationsWithRepresentations}
mode={SegmentationTableMode}
mode={segmentationTableMode}
title="Segmentations"
exportOptions={exportOptions}
disableEditing={disableEditing}
@@ -300,7 +204,7 @@ export default function PanelSegmentation({
<SegmentationTable.Config />
<SegmentationTable.AddSegmentationRow />
{SegmentationTableMode === 'collapsed' ? (
{segmentationTableMode === 'collapsed' ? (
<SegmentationTable.Collapsed>
<SegmentationTable.SelectorHeader>
<CustomDropdownMenuContent />
@@ -4,7 +4,7 @@ import { PositionPresentation } from '../types/Presentation';
import { addUniqueIndex, JOIN_STR } from './presentationUtils';
const PRESENTATION_TYPE_ID = 'positionPresentationId';
const DEBUG_STORE = true;
const DEBUG_STORE = false;
/**
* Represents the state and actions for managing position presentations.
@@ -1,7 +1,5 @@
import { useEffect, useState, memo } from 'react';
const MODALITIES_REQUIRING_CINE_AUTO_MOUNT = ['OT', 'US'];
const ActiveViewportBehavior = memo(
({ servicesManager, viewportId }: withAppTypes<{ viewportId: string }>) => {
const { displaySetService, cineService, viewportGridService, customizationService } =
@@ -41,13 +39,7 @@ const ActiveViewportBehavior = memo(
const modalities = displaySets.map(displaySet => displaySet?.Modality);
const isDynamicVolume = displaySets.some(displaySet => displaySet?.isDynamicVolume);
const { modalities: sourceModalities } = customizationService.getModeCustomization(
'autoCineModalities',
{
id: 'autoCineModalities',
modalities: MODALITIES_REQUIRING_CINE_AUTO_MOUNT,
}
);
const sourceModalities = customizationService.getCustomization('autoCineModalities');
const requiresCine = modalities.some(modality => sourceModalities.includes(modality));
@@ -142,7 +142,7 @@ function getMappedAnnotations(annotation, displaySetService) {
* @returns {object} Report's content.
*/
function getColumnValueReport(annotation, customizationService) {
const { PlanarFreehandROI } = customizationService.get('cornerstone.measurements');
const { PlanarFreehandROI } = customizationService.getCustomization('cornerstone.measurements');
const { report } = PlanarFreehandROI;
const columns = [];
const values = [];
@@ -145,7 +145,7 @@ function getMappedAnnotations(annotation, displaySetService) {
* @returns {object} Report's content.
*/
function getColumnValueReport(annotation, customizationService) {
const { SplineROI } = customizationService.get('cornerstone.measurements');
const { SplineROI } = customizationService.getCustomization('cornerstone.measurements');
const { report } = SplineROI;
const columns = [];
const values = [];
+196
View File
@@ -3,6 +3,202 @@
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.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
# [3.10.0-beta.76](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.75...v3.10.0-beta.76) (2025-01-27)
**Note:** Version bump only for package @ohif/extension-default
# [3.10.0-beta.75](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.74...v3.10.0-beta.75) (2025-01-27)
### Features
* **static-wado:** add support for case-insensitive searching ([#4603](https://github.com/OHIF/Viewers/issues/4603)) ([ac6e674](https://github.com/OHIF/Viewers/commit/ac6e674b4d094f942556d045178011bbf3f81796))
# [3.10.0-beta.74](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.73...v3.10.0-beta.74) (2025-01-27)
**Note:** Version bump only for package @ohif/extension-default
# [3.10.0-beta.73](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.72...v3.10.0-beta.73) (2025-01-24)
**Note:** Version bump only for package @ohif/extension-default
# [3.10.0-beta.72](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.71...v3.10.0-beta.72) (2025-01-24)
**Note:** Version bump only for package @ohif/extension-default
# [3.10.0-beta.71](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.70...v3.10.0-beta.71) (2025-01-23)
### Features
* **customization:** new customization service api ([#4688](https://github.com/OHIF/Viewers/issues/4688)) ([55ad8ef](https://github.com/OHIF/Viewers/commit/55ad8efbabc3fabd8031fc08927b2f92ae5aec69))
# [3.10.0-beta.70](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.69...v3.10.0-beta.70) (2025-01-23)
### Features
* **panels:** responsive thumbnails based on panel size ([#4723](https://github.com/OHIF/Viewers/issues/4723)) ([d9abc3d](https://github.com/OHIF/Viewers/commit/d9abc3da8d94d6c5ab0cc5af25a5f61849905a35))
# [3.10.0-beta.69](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.68...v3.10.0-beta.69) (2025-01-22)
### Bug Fixes
* **seg:** sphere scissor on stack and cpu rendering reset properties was broken ([#4721](https://github.com/OHIF/Viewers/issues/4721)) ([f00d182](https://github.com/OHIF/Viewers/commit/f00d18292f02e8910215d913edfc994850a68d88))
# [3.10.0-beta.68](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.67...v3.10.0-beta.68) (2025-01-21)
### Features
* **resizable-side-panels:** Make the left and right side panels (optionally) resizable. ([#4672](https://github.com/OHIF/Viewers/issues/4672)) ([d90a4cf](https://github.com/OHIF/Viewers/commit/d90a4cfb16cc0daed9b905de9780f44cca1323f9))
# [3.10.0-beta.67](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.66...v3.10.0-beta.67) (2025-01-21)
### Bug Fixes
* **ui:** Update dependencies and add missing icons ([#4699](https://github.com/OHIF/Viewers/issues/4699)) ([cf97fa9](https://github.com/OHIF/Viewers/commit/cf97fa9b7b9687a9b73c1cf6926bc9fbc39b6512))
# [3.10.0-beta.66](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.65...v3.10.0-beta.66) (2025-01-21)
### Bug Fixes
* Inconsistent Handling of Patient Name Tag ([#4703](https://github.com/OHIF/Viewers/issues/4703)) ([8aedb2e](https://github.com/OHIF/Viewers/commit/8aedb2ec54a0ccf2550f745fed6f0b8aa184a860))
# [3.10.0-beta.65](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.64...v3.10.0-beta.65) (2025-01-20)
**Note:** Version bump only for package @ohif/extension-default
# [3.10.0-beta.64](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.63...v3.10.0-beta.64) (2025-01-20)
### Bug Fixes
* **hp:** Display set should allow remembered updates ([#4707](https://github.com/OHIF/Viewers/issues/4707)) ([464148e](https://github.com/OHIF/Viewers/commit/464148ece66b48b583dc6e998ca4d11c66746f3a))
# [3.10.0-beta.63](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.62...v3.10.0-beta.63) (2025-01-17)
**Note:** Version bump only for package @ohif/extension-default
# [3.10.0-beta.62](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.61...v3.10.0-beta.62) (2025-01-16)
### Bug Fixes
* context menu icon ([#4696](https://github.com/OHIF/Viewers/issues/4696)) ([1993161](https://github.com/OHIF/Viewers/commit/19931614dc53da440718e512d39a87ca9118b96e))
# [3.10.0-beta.61](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.60...v3.10.0-beta.61) (2025-01-16)
### Bug Fixes
* **multiframe:** handling proxies properly ([#4693](https://github.com/OHIF/Viewers/issues/4693)) ([ec4b5a6](https://github.com/OHIF/Viewers/commit/ec4b5a6876cea77278e5cffaf4108eeeefdc57dc))
# [3.10.0-beta.60](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.59...v3.10.0-beta.60) (2025-01-15)
**Note:** Version bump only for package @ohif/extension-default
# [3.10.0-beta.59](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.58...v3.10.0-beta.59) (2025-01-14)
### Bug Fixes
* bugs after multimonitor ([#4680](https://github.com/OHIF/Viewers/issues/4680)) ([c901a84](https://github.com/OHIF/Viewers/commit/c901a847af75d356509366c695ea46ff4f4bcdaf))
# [3.10.0-beta.58](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.57...v3.10.0-beta.58) (2025-01-13)
+3 -3
View File
@@ -1,6 +1,6 @@
{
"name": "@ohif/extension-default",
"version": "3.10.0-beta.58",
"version": "3.10.0-beta.78",
"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.58",
"@ohif/i18n": "3.10.0-beta.58",
"@ohif/core": "3.10.0-beta.78",
"@ohif/i18n": "3.10.0-beta.78",
"dcmjs": "*",
"dicomweb-client": "^0.10.4",
"prop-types": "^15.6.2",
@@ -29,8 +29,9 @@ function DataSourceConfigurationComponent({
return;
}
const { factory: configurationAPIFactory } =
customizationService.get(activeDataSourceDef.configuration.configurationAPI) ?? {};
const { factory: configurationAPIFactory } = customizationService.getCustomization(
activeDataSourceDef.configuration.configurationAPI
) ?? { factory: () => null };
if (!configurationAPIFactory) {
return;
@@ -27,9 +27,9 @@ const getMenuItemsDefault = ({ commandsManager, items, servicesManager, ...props
e.preventDefault();
}}
>
{items?.map(item =>
menuContent.content({
key: item.id,
{items?.map((item, index) =>
React.createElement(menuContent.content, {
key: item.id || `menu-item-${index}`,
item,
commandsManager,
servicesManager,
@@ -56,9 +56,9 @@ export default function MoreDropdownMenu(bindProps) {
} = bindProps;
const { customizationService } = servicesManager.services;
const items = customizationService.getCustomization(menuItemsKey)?.value;
const items = customizationService.getCustomization(menuItemsKey);
if (!items) {
if (!items?.length) {
return null;
}
@@ -7,47 +7,58 @@ export type SidePanelWithServicesProps = {
side: 'left' | 'right';
className?: string;
activeTabIndex: number;
tabs: any;
tabs?: any;
expandedWidth?: number;
onClose: () => void;
onOpen: () => void;
isExpanded: boolean;
collapsedWidth?: number;
expandedInsideBorderSize?: number;
collapsedInsideBorderSize?: number;
collapsedOutsideBorderSize?: number;
};
const SidePanelWithServices = ({
servicesManager,
side,
activeTabIndex: activeTabIndexProp,
isExpanded,
tabs: tabsProp,
expandedWidth,
onOpen,
onClose,
...props
}: SidePanelWithServicesProps) => {
const panelService = servicesManager?.services?.panelService;
// Tracks whether this SidePanel has been opened at least once since this SidePanel was inserted into the DOM.
// Thus going to the Study List page and back to the viewer resets this flag for a SidePanel.
const [sidePanelOpen, setSidePanelOpen] = useState(activeTabIndexProp !== null);
const [activeTabIndex, setActiveTabIndex] = useState(activeTabIndexProp);
const [sidePanelExpanded, setSidePanelExpanded] = useState(isExpanded);
const [activeTabIndex, setActiveTabIndex] = useState(activeTabIndexProp ?? 0);
const [closedManually, setClosedManually] = useState(false);
const [tabs, setTabs] = useState(tabsProp ?? panelService.getPanels(side));
const handleActiveTabIndexChange = useCallback(({ activeTabIndex }) => {
setActiveTabIndex(activeTabIndex);
setSidePanelOpen(activeTabIndex !== null);
}, []);
const handleOpen = useCallback(() => {
setSidePanelOpen(true);
// If panel is being opened but no tab is active, set first tab as active
if (activeTabIndex === null && tabs.length > 0) {
setActiveTabIndex(0);
}
}, [activeTabIndex, tabs]);
setSidePanelExpanded(true);
onOpen?.();
}, [onOpen]);
const handleClose = useCallback(() => {
setSidePanelOpen(false);
setActiveTabIndex(null);
}, []);
setSidePanelExpanded(false);
setClosedManually(true);
onClose?.();
}, [onClose]);
useEffect(() => {
setSidePanelExpanded(isExpanded);
}, [isExpanded]);
/** update the active tab index from outside */
useEffect(() => {
setActiveTabIndex(activeTabIndexProp);
setActiveTabIndex(activeTabIndexProp ?? 0);
}, [activeTabIndexProp]);
useEffect(() => {
@@ -71,9 +82,12 @@ const SidePanelWithServices = ({
const activatePanelSubscription = panelService.subscribe(
panelService.EVENTS.ACTIVATE_PANEL,
(activatePanelEvent: Types.ActivatePanelEvent) => {
if (sidePanelOpen || activatePanelEvent.forceActive) {
if (sidePanelExpanded || activatePanelEvent.forceActive) {
const tabIndex = tabs.findIndex(tab => tab.id === activatePanelEvent.panelId);
if (tabIndex !== -1) {
if (!closedManually) {
setSidePanelExpanded(true);
}
setActiveTabIndex(tabIndex);
}
}
@@ -83,7 +97,7 @@ const SidePanelWithServices = ({
return () => {
activatePanelSubscription.unsubscribe();
};
}, [tabs, sidePanelOpen, panelService]);
}, [tabs, sidePanelExpanded, panelService, closedManually]);
return (
<SidePanel
@@ -91,10 +105,10 @@ const SidePanelWithServices = ({
side={side}
tabs={tabs}
activeTabIndex={activeTabIndex}
isExpanded={sidePanelExpanded}
onOpen={handleOpen}
onClose={handleClose}
onActiveTabIndexChange={handleActiveTabIndexChange}
expandedWidth={expandedWidth}
/>
);
};
@@ -154,7 +154,7 @@ export function adaptItem(item: MenuItem, subProps: ContextMenuProps): ContextMe
};
if (item.actionType === 'ShowSubMenu' && !newItem.iconRight) {
newItem.iconRight = 'chevron-menu';
newItem.iconRight = 'chevron-down';
}
if (!item.action) {
newItem.action = (itemRef, componentProps) => {
@@ -1,34 +0,0 @@
const defaultContextMenu = {
id: 'measurementsContextMenu',
customizationType: 'ohif.contextMenu',
menus: [
// Get the items from the UI Customization for the menu name (and have a custom name)
{
id: 'forExistingMeasurement',
selector: ({ nearbyToolData }) => !!nearbyToolData,
items: [
{
label: 'Delete measurement',
commands: [
{
commandName: 'deleteMeasurement',
// we only have support for cornerstoneTools context menu since
// they are svg based
context: 'CORNERSTONE',
},
],
},
{
label: 'Add Label',
commands: [
{
commandName: 'setMeasurementLabel',
},
],
},
],
},
],
};
export default defaultContextMenu;
@@ -1,11 +1,5 @@
import ContextMenuController from './ContextMenuController';
import * as ContextMenuItemsBuilder from './ContextMenuItemsBuilder';
import defaultContextMenu from './defaultContextMenu';
import * as CustomizableContextMenuTypes from './types';
export {
ContextMenuController,
CustomizableContextMenuTypes,
ContextMenuItemsBuilder,
defaultContextMenu,
};
export { ContextMenuController, CustomizableContextMenuTypes, ContextMenuItemsBuilder };
@@ -45,10 +45,11 @@ export type UIMenuItem = {
*/
export interface MenuItem {
id?: string;
/** The customization type is used to apply preset values to this item
/**
* The customization type is used to apply preset values to this item
* when registered with the customization service.
*/
customizationType?: string;
inheritsFrom?: string;
// The label is the value to show in the menu for this item
label?: string;
@@ -91,7 +92,7 @@ export interface Menu {
/** The customization type is used to apply preset values to this item
* when registered with the customization service.
*/
customizationType?: string;
inheritsFrom?: string;
// Choose whether this menu applies.
selector?: Types.Predicate;
@@ -142,7 +142,9 @@ function createDicomLocalApi(dicomLocalConfig) {
study.series.forEach(aSeries => {
const { SeriesInstanceUID } = aSeries;
aSeries.instances.forEach(instance => {
const isMultiframe = aSeries.instances[0].NumberOfFrames > 1;
aSeries.instances.forEach((instance, index) => {
const {
url: imageId,
StudyInstanceUID,
@@ -151,22 +153,14 @@ function createDicomLocalApi(dicomLocalConfig) {
} = instance;
instance.imageId = imageId;
const numberOfFrames = instance.NumberOfFrames || 1;
// Process all frames consistently, whether single or multiframe
for (let i = 0; i < numberOfFrames; i++) {
const frameNumber = i + 1;
const frameImageId = implementation.getImageIdsForInstance({
instance,
frame: frameNumber,
});
// Add imageId specific mapping to this data as the URL isn't necessarily WADO-URI.
metadataProvider.addImageIdToUIDs(frameImageId, {
StudyInstanceUID,
SeriesInstanceUID,
SOPInstanceUID,
frameNumber: numberOfFrames > 1 ? frameNumber : undefined,
});
}
// Add imageId specific mapping to this data as the URL isn't necessarily WADO-URI.
metadataProvider.addImageIdToUIDs(imageId, {
StudyInstanceUID,
SeriesInstanceUID,
SOPInstanceUID,
frameIndex: isMultiframe ? index : 1,
});
});
DicomMetadataStore._broadcastEvent(EVENTS.INSTANCES_ADDED, {
@@ -151,6 +151,7 @@ function createDicomWebApi(dicomWebConfig: DicomWebConfig, servicesManager) {
singlepart: dicomWebConfig.singlepart,
headers: userAuthenticationService.getAuthorizationHeader(),
errorInterceptor: errorHandler.getHTTPErrorHandler(),
supportsFuzzyMatching: dicomWebConfig.supportsFuzzyMatching,
};
wadoConfig = {
@@ -159,6 +160,7 @@ function createDicomWebApi(dicomWebConfig: DicomWebConfig, servicesManager) {
singlepart: dicomWebConfig.singlepart,
headers: userAuthenticationService.getAuthorizationHeader(),
errorInterceptor: errorHandler.getHTTPErrorHandler(),
supportsFuzzyMatching: dicomWebConfig.supportsFuzzyMatching,
};
// TODO -> Two clients sucks, but its better than 1000.
@@ -478,7 +480,6 @@ function createDicomWebApi(dicomWebConfig: DicomWebConfig, servicesManager) {
instance.wadoUri = dicomWebConfig.wadoUri;
const { StudyInstanceUID, SeriesInstanceUID, SOPInstanceUID } = instance;
const numberOfFrames = instance.NumberOfFrames || 1;
// Process all frames consistently, whether single or multiframe
for (let i = 0; i < numberOfFrames; i++) {
@@ -583,8 +584,11 @@ function createDicomWebApi(dicomWebConfig: DicomWebConfig, servicesManager) {
return dicomWebConfigCopy;
},
getStudyInstanceUIDs({ params, query }) {
const { StudyInstanceUIDs: paramsStudyInstanceUIDs } = params;
const queryStudyInstanceUIDs = utils.splitComma(query.getAll('StudyInstanceUIDs'));
const paramsStudyInstanceUIDs = params.StudyInstanceUIDs || params.studyInstanceUIDs;
const queryStudyInstanceUIDs = utils.splitComma(
query.getAll('StudyInstanceUIDs').concat(query.getAll('studyInstanceUIDs'))
);
const StudyInstanceUIDs =
(queryStudyInstanceUIDs.length && queryStudyInstanceUIDs) || paramsStudyInstanceUIDs;
@@ -156,18 +156,40 @@ export default class StaticWadoClient extends api.DICOMwebClient {
*
* @param {*} desired
* @param {*} actual
* @param {*} options - fuzzyMatching: if true, then do a sub-string match
* @returns true if the values match
*/
compareValues(desired, actual) {
compareValues(desired, actual, options) {
const { fuzzyMatching } = options;
if (Array.isArray(desired)) {
return desired.find(item => this.compareValues(item, actual));
return desired.find(item => this.compareValues(item, actual, options));
}
if (Array.isArray(actual)) {
return actual.find(actualItem => this.compareValues(desired, actualItem));
return actual.find(actualItem => this.compareValues(desired, actualItem, options));
}
if (actual?.Alphabetic) {
actual = actual.Alphabetic;
}
if (fuzzyMatching && typeof actual === 'string' && typeof desired === 'string') {
const normalizeValue = str => {
return str.toLowerCase();
};
const normalizedDesired = normalizeValue(desired);
const normalizedActual = normalizeValue(actual);
const tokenizeAndNormalize = str => str.split(/[\s^]+/).filter(Boolean);
const desiredTokens = tokenizeAndNormalize(normalizedDesired);
const actualTokens = tokenizeAndNormalize(normalizedActual);
return desiredTokens.every(desiredToken =>
actualTokens.some(actualToken => actualToken.startsWith(desiredToken))
);
}
if (typeof actual == 'string') {
if (actual.length === 0) {
return true;
@@ -194,7 +216,7 @@ export default class StaticWadoClient extends api.DICOMwebClient {
}
const dash = range.indexOf('-');
if (dash === -1) {
return this.compareValues(range, value);
return this.compareValues(range, value, {});
}
const start = range.substring(0, dash);
const end = range.substring(dash + 1);
@@ -211,6 +233,14 @@ export default class StaticWadoClient extends api.DICOMwebClient {
* @returns
*/
filterItem(key: string, queryParams, study, sourceFilterMap) {
const isName = (key: string) => key.indexOf('name') !== -1;
const { supportsFuzzyMatching = false } = this.config;
const options = {
fuzzyMatching: isName(key) && supportsFuzzyMatching,
};
const altKey = sourceFilterMap[key] || key;
if (!queryParams) {
return true;
@@ -227,7 +257,8 @@ export default class StaticWadoClient extends api.DICOMwebClient {
return this.compareDateRange(testValue, valueElem.Value[0]);
}
const value = valueElem.Value;
return this.compareValues(testValue, value);
return this.compareValues(testValue, value, options);
}
/** Converts the query parameters to lower case query parameters */
@@ -6,7 +6,7 @@ import { utils } from '@ohif/core';
import { useNavigate } from 'react-router-dom';
import { Separator } from '@ohif/ui-next';
import { PanelStudyBrowserHeader } from './PanelStudyBrowserHeader';
import { defaultActionIcons, defaultViewPresets } from './constants';
import { defaultActionIcons } from './constants';
import MoreDropdownMenu from '../../Components/MoreDropdownMenu';
const { sortStudyInstances, formatDate, createStudyBrowserTabs } = utils;
@@ -43,7 +43,7 @@ function PanelStudyBrowser({
const [thumbnailImageSrcMap, setThumbnailImageSrcMap] = useState({});
const [viewPresets, setViewPresets] = useState(
customizationService.getCustomization('studyBrowser.viewPresets')?.value || defaultViewPresets
customizationService.getCustomization('studyBrowser.viewPresets')
);
const [actionIcons, setActionIcons] = useState(defaultActionIcons);
@@ -13,7 +13,7 @@ import requestDisplaySetCreationForStudy from './requestDisplaySetCreationForStu
* @param {object} commandsManager
* @param {object} extensionManager
*/
function WrappedPanelStudyBrowser({ extensionManager, servicesManager }) {
function WrappedPanelStudyBrowser({ extensionManager, servicesManager, commandsManager }) {
// TODO: This should be made available a different way; route should have
// already determined our datasource
const [dataSource] = extensionManager.getActiveDataSource();
@@ -2,87 +2,6 @@ import React, { useEffect, useState, useCallback, useRef } from 'react';
import PropTypes from 'prop-types';
import { LayoutSelector as OHIFLayoutSelector, ToolbarButton, LayoutPreset } from '@ohif/ui';
const defaultCommonPresets = [
{
icon: 'layout-common-1x1',
commandOptions: {
numRows: 1,
numCols: 1,
},
},
{
icon: 'layout-common-1x2',
commandOptions: {
numRows: 1,
numCols: 2,
},
},
{
icon: 'layout-common-2x2',
commandOptions: {
numRows: 2,
numCols: 2,
},
},
{
icon: 'layout-common-2x3',
commandOptions: {
numRows: 2,
numCols: 3,
},
},
];
const _areSelectorsValid = (hp, displaySets, hangingProtocolService) => {
if (!hp.displaySetSelectors || Object.values(hp.displaySetSelectors).length === 0) {
return true;
}
return hangingProtocolService.areRequiredSelectorsValid(
Object.values(hp.displaySetSelectors),
displaySets[0]
);
};
const generateAdvancedPresets = ({ servicesManager }: withAppTypes) => {
const { hangingProtocolService, viewportGridService, displaySetService } =
servicesManager.services;
const hangingProtocols = Array.from(hangingProtocolService.protocols.values());
const viewportId = viewportGridService.getActiveViewportId();
if (!viewportId) {
return [];
}
const displaySetInsaneUIDs = viewportGridService.getDisplaySetsUIDsForViewport(viewportId);
if (!displaySetInsaneUIDs) {
return [];
}
const displaySets = displaySetInsaneUIDs.map(uid => displaySetService.getDisplaySetByUID(uid));
return hangingProtocols
.map(hp => {
if (!hp.isPreset) {
return null;
}
const areValid = _areSelectorsValid(hp, displaySets, hangingProtocolService);
return {
icon: hp.icon,
title: hp.name,
commandOptions: {
protocolId: hp.id,
},
disabled: !areValid,
};
})
.filter(preset => preset !== null);
};
function ToolbarLayoutSelectorWithServices({
commandsManager,
servicesManager,
@@ -138,9 +57,13 @@ function LayoutSelector({
const dropdownRef = useRef(null);
const { customizationService } = servicesManager.services;
const commonPresets = customizationService.get('commonPresets') || defaultCommonPresets;
const advancedPresets =
customizationService.get('advancedPresets') || generateAdvancedPresets({ servicesManager });
const commonPresets = customizationService.getCustomization('layoutSelector.commonPresets');
const advancedPresetsGenerator = customizationService.getCustomization(
'layoutSelector.advancedPresetGenerator'
);
const advancedPresets = advancedPresetsGenerator({ servicesManager });
const closeOnOutsideClick = event => {
if (isOpen && dropdownRef.current) {
@@ -216,7 +139,7 @@ function LayoutSelector({
</div>
</div>
<div className="bg-primary-dark flex flex-col gap-2.5 border-l-2 border-solid border-black p-2">
<div className="bg-primary-dark flex flex-col gap-2.5 border-l-2 border-solid border-black p-2">
<div className="text-aqua-pale text-xs">Custom</div>
<DropdownContent
rows={rows}
@@ -0,0 +1,316 @@
import { useState, useCallback, useLayoutEffect, useRef } from 'react';
import { getPanelElement, getPanelGroupElement } from 'react-resizable-panels';
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
* 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
* browser window. In general, the widths are always set unless the resize
* handle for either side panel is being dragged (i.e. a side panel is being resized).
*
* @param elem the element
* @param width the max and min width to set on the element
*/
const setMinMaxWidth = (elem, width?) => {
elem.style.minWidth = width === undefined ? '' : `${width}px`;
elem.style.maxWidth = elem.style.minWidth;
};
const useResizablePanels = (
leftPanelClosed,
setLeftPanelClosed,
rightPanelClosed,
setRightPanelClosed
) => {
const [leftPanelExpandedWidth, setLeftPanelExpandedWidth] = useState(
panelGroupDefinition.left.initialExpandedWidth
);
const [rightPanelExpandedWidth, setRightPanelExpandedWidth] = useState(
panelGroupDefinition.right.initialExpandedWidth
);
const [leftResizablePanelMinimumSize, setLeftResizablePanelMinimumSize] = useState(0);
const [rightResizablePanelMinimumSize, setRightResizablePanelMinimumSize] = useState(0);
const [leftResizablePanelCollapsedSize, setLeftResizePanelCollapsedSize] = useState(0);
const [rightResizePanelCollapsedSize, setRightResizePanelCollapsedSize] = useState(0);
const resizablePanelGroupElemRef = useRef(null);
const resizableLeftPanelElemRef = useRef(null);
const resizableRightPanelElemRef = useRef(null);
const resizableLeftPanelAPIRef = useRef(null);
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 leftPanelElem = getPanelElement(panelGroupDefinition.left.panelId);
resizableLeftPanelElemRef.current = leftPanelElem;
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 = getPercentageSize(
panelGroupDefinition.left.initialExpandedOffsetWidth
);
resizableLeftPanelAPIRef?.current?.expand(leftResizablePanelExpandedSize);
setMinMaxWidth(leftPanelElem, panelGroupDefinition.left.initialExpandedOffsetWidth);
}
if (!rightPanelClosed) {
const rightResizablePanelExpandedSize = getPercentageSize(
panelGroupDefinition.right.initialExpandedOffsetWidth
);
resizableRightPanelAPIRef?.current?.expand(rightResizablePanelExpandedSize);
setMinMaxWidth(rightPanelElem, panelGroupDefinition.right.initialExpandedOffsetWidth);
}
}, []); // no dependencies because this useLayoutEffect is only needed on the very first render
// This useLayoutEffect follows the pattern prescribed by the react-resizable-panels
// readme for converting between pixel values and percentages. An example of
// the pattern can be found here:
// https://github.com/bvaughn/react-resizable-panels/issues/46#issuecomment-1368108416
// This useLayoutEffect is used to...
// - Ensure that the percentage size is up-to-date with the pixel sizes
// - Add a resize observer to the resizable panel group to reset various state
// values whenever the resizable panel group is resized (e.g. whenever the
// browser window is resized).
useLayoutEffect(() => {
// 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 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 = getPercentageSize(
leftPanelExpandedWidth + panelGroupDefinition.shared.expandedInsideBorderSize
);
resizableLeftPanelAPIRef.current.resize(leftSize);
}
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 minimumLeftSize = getPercentageSize(
panelGroupDefinition.left.minimumExpandedOffsetWidth
);
const minimumRightSize = getPercentageSize(
panelGroupDefinition.right.minimumExpandedOffsetWidth
);
// Set the new minimum and collapsed resizable panel sizes.
setLeftResizablePanelMinimumSize(minimumLeftSize);
setRightResizablePanelMinimumSize(minimumRightSize);
setLeftResizePanelCollapsedSize(
getPercentageSize(panelGroupDefinition.left.collapsedOffsetWidth)
);
setRightResizePanelCollapsedSize(
getPercentageSize(panelGroupDefinition.right.collapsedOffsetWidth)
);
});
observer.observe(resizablePanelGroupElemRef.current);
return () => {
observer.disconnect();
};
}, [
leftPanelExpandedWidth,
rightPanelExpandedWidth,
leftResizablePanelMinimumSize,
rightResizablePanelMinimumSize,
]);
/**
* Handles dragging of either side panel resize handle.
*/
const onHandleDragging = useCallback(
isStartDrag => {
if (isStartDrag) {
isResizableHandleDraggingRef.current = true;
setMinMaxWidth(resizableLeftPanelElemRef.current);
setMinMaxWidth(resizableRightPanelElemRef.current);
} else {
isResizableHandleDraggingRef.current = false;
if (resizableLeftPanelAPIRef?.current?.isExpanded()) {
setMinMaxWidth(
resizableLeftPanelElemRef.current,
leftPanelExpandedWidth + panelGroupDefinition.shared.expandedInsideBorderSize
);
}
if (resizableRightPanelAPIRef?.current?.isExpanded()) {
setMinMaxWidth(
resizableRightPanelElemRef.current,
rightPanelExpandedWidth + panelGroupDefinition.shared.expandedInsideBorderSize
);
}
}
},
[leftPanelExpandedWidth, rightPanelExpandedWidth]
);
const onLeftPanelClose = useCallback(() => {
setLeftPanelClosed(true);
setMinMaxWidth(resizableLeftPanelElemRef.current);
resizableLeftPanelAPIRef?.current?.collapse();
}, [setLeftPanelClosed]);
const onLeftPanelOpen = useCallback(() => {
resizableLeftPanelAPIRef?.current?.expand(
getPercentageSize(panelGroupDefinition.left.initialExpandedOffsetWidth)
);
setLeftPanelClosed(false);
}, [setLeftPanelClosed]);
const onLeftPanelResize = useCallback(size => {
if (!resizablePanelGroupElemRef?.current || resizableLeftPanelAPIRef.current.isCollapsed()) {
return;
}
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(() => {
setRightPanelClosed(true);
setMinMaxWidth(resizableRightPanelElemRef.current);
resizableRightPanelAPIRef?.current?.collapse();
}, [setRightPanelClosed]);
const onRightPanelOpen = useCallback(() => {
resizableRightPanelAPIRef?.current?.expand(
getPercentageSize(panelGroupDefinition.right.initialExpandedOffsetWidth)
);
setRightPanelClosed(false);
}, [setRightPanelClosed]);
const onRightPanelResize = useCallback(size => {
if (!resizablePanelGroupElemRef?.current || resizableRightPanelAPIRef.current.isCollapsed()) {
return;
}
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,
collapsedWidth: panelGroupDefinition.shared.collapsedWidth,
collapsedInsideBorderSize: panelGroupDefinition.shared.collapsedInsideBorderSize,
collapsedOutsideBorderSize: panelGroupDefinition.shared.collapsedOutsideBorderSize,
expandedInsideBorderSize: panelGroupDefinition.shared.expandedInsideBorderSize,
onClose: onLeftPanelClose,
onOpen: onLeftPanelOpen,
},
{
expandedWidth: rightPanelExpandedWidth,
collapsedWidth: panelGroupDefinition.shared.collapsedWidth,
collapsedInsideBorderSize: panelGroupDefinition.shared.collapsedInsideBorderSize,
collapsedOutsideBorderSize: panelGroupDefinition.shared.collapsedOutsideBorderSize,
expandedInsideBorderSize: panelGroupDefinition.shared.expandedInsideBorderSize,
onClose: onRightPanelClose,
onOpen: onRightPanelOpen,
},
{ direction: 'horizontal', id: panelGroupDefinition.groupId },
{
defaultSize: leftResizablePanelMinimumSize,
minSize: leftResizablePanelMinimumSize,
onResize: onLeftPanelResize,
collapsible: true,
collapsedSize: leftResizablePanelCollapsedSize,
onCollapse: () => setLeftPanelClosed(true),
onExpand: () => setLeftPanelClosed(false),
ref: resizableLeftPanelAPIRef,
order: 0,
id: panelGroupDefinition.left.panelId,
},
{ order: 1, id: 'viewerLayoutResizableViewportGridPanel' },
{
defaultSize: rightResizablePanelMinimumSize,
minSize: rightResizablePanelMinimumSize,
onResize: onRightPanelResize,
collapsible: true,
collapsedSize: rightResizePanelCollapsedSize,
onCollapse: () => setRightPanelClosed(true),
onExpand: () => setRightPanelClosed(false),
ref: resizableRightPanelAPIRef,
order: 2,
id: panelGroupDefinition.right.panelId,
},
onHandleDragging,
];
};
export default useResizablePanels;
@@ -0,0 +1,38 @@
const expandedInsideBorderSize = 0;
const collapsedInsideBorderSize = 4;
const collapsedOutsideBorderSize = 4;
const collapsedWidth = 25;
const rightPanelInitialExpandedWidth = 280;
const leftPanelInitialExpandedWidth = 282;
const panelGroupDefinition = {
groupId: 'viewerLayoutResizablePanelGroup',
shared: {
expandedInsideBorderSize,
collapsedInsideBorderSize,
collapsedOutsideBorderSize,
collapsedWidth,
},
left: {
// id
panelId: 'viewerLayoutResizableLeftPanel',
// expanded width
initialExpandedWidth: leftPanelInitialExpandedWidth,
// expanded width + expanded inside border
minimumExpandedOffsetWidth: 145 + expandedInsideBorderSize,
// initial expanded width
initialExpandedOffsetWidth: leftPanelInitialExpandedWidth + expandedInsideBorderSize,
// collapsed width + collapsed inside border + collapsed outside border
collapsedOffsetWidth: collapsedWidth + collapsedInsideBorderSize + collapsedOutsideBorderSize,
},
right: {
panelId: 'viewerLayoutResizableRightPanel',
initialExpandedWidth: rightPanelInitialExpandedWidth,
minimumExpandedOffsetWidth: rightPanelInitialExpandedWidth + expandedInsideBorderSize,
initialExpandedOffsetWidth: rightPanelInitialExpandedWidth + expandedInsideBorderSize,
collapsedOffsetWidth: collapsedWidth + collapsedInsideBorderSize + collapsedOutsideBorderSize,
},
};
export { panelGroupDefinition };
+71 -26
View File
@@ -6,7 +6,10 @@ import { HangingProtocolService, CommandsManager } from '@ohif/core';
import { useAppConfig } from '@state';
import ViewerHeader from './ViewerHeader';
import SidePanelWithServices from '../Components/SidePanelWithServices';
import { Onboarding } from '@ohif/ui-next';
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
@@ -19,6 +22,8 @@ function ViewerLayout({
ViewportGridComp,
leftPanelClosed = false,
rightPanelClosed = false,
leftPanelResizable = false,
rightPanelResizable = false,
}: withAppTypes): React.FunctionComponent {
const [appConfig] = useAppConfig();
@@ -35,6 +40,21 @@ function ViewerLayout({
const [leftPanelClosedState, setLeftPanelClosed] = useState(leftPanelClosed);
const [rightPanelClosedState, setRightPanelClosed] = useState(rightPanelClosed);
const [
leftPanelProps,
rightPanelProps,
resizablePanelGroupProps,
resizableLeftPanelProps,
resizableViewportGridPanelProps,
resizableRightPanelProps,
onHandleDragging,
] = useResizablePanels(
leftPanelClosed,
setLeftPanelClosed,
rightPanelClosed,
setRightPanelClosed
);
/**
* Set body classes (tailwindcss) that don't allow vertical
* or horizontal overflow (no scrolling). Also guarantee window
@@ -123,31 +143,56 @@ function ViewerLayout({
>
<React.Fragment>
{showLoadingIndicator && <LoadingIndicatorProgress className="h-full w-full bg-black" />}
{/* LEFT SIDEPANELS */}
{hasLeftPanels ? (
<SidePanelWithServices
side="left"
activeTabIndex={leftPanelClosedState ? null : 0}
servicesManager={servicesManager}
/>
) : null}
{/* TOOLBAR + GRID */}
<div className="flex h-full flex-1 flex-col">
<div className="relative flex h-full flex-1 items-center justify-center overflow-hidden bg-black">
<ViewportGridComp
servicesManager={servicesManager}
viewportComponents={viewportComponents}
commandsManager={commandsManager}
/>
</div>
</div>
{hasRightPanels ? (
<SidePanelWithServices
side="right"
activeTabIndex={rightPanelClosedState ? null : 0}
servicesManager={servicesManager}
/>
) : null}
<ResizablePanelGroup {...resizablePanelGroupProps}>
{/* LEFT SIDEPANELS */}
{hasLeftPanels ? (
<>
<ResizablePanel {...resizableLeftPanelProps}>
<SidePanelWithServices
side="left"
isExpanded={!leftPanelClosedState}
servicesManager={servicesManager}
{...leftPanelProps}
/>
</ResizablePanel>
<ResizableHandle
onDragging={onHandleDragging}
disabled={!leftPanelResizable}
className={resizableHandleClassName}
/>
</>
) : null}
{/* TOOLBAR + GRID */}
<ResizablePanel {...resizableViewportGridPanelProps}>
<div className="flex h-full flex-1 flex-col">
<div className="relative flex h-full flex-1 items-center justify-center overflow-hidden bg-black">
<ViewportGridComp
servicesManager={servicesManager}
viewportComponents={viewportComponents}
commandsManager={commandsManager}
/>
</div>
</div>
</ResizablePanel>
{hasRightPanels ? (
<>
<ResizableHandle
onDragging={onHandleDragging}
disabled={!rightPanelResizable}
className={resizableHandleClassName}
/>
<ResizablePanel {...resizableRightPanelProps}>
<SidePanelWithServices
side="right"
isExpanded={!rightPanelClosedState}
servicesManager={servicesManager}
{...rightPanelProps}
/>
</ResizablePanel>
</>
) : null}
</ResizablePanelGroup>
</React.Fragment>
</div>
<Onboarding />
+2 -5
View File
@@ -1,6 +1,6 @@
import { Types, DicomMetadataStore } from '@ohif/core';
import { ContextMenuController, defaultContextMenu } from './CustomizableContextMenu';
import { ContextMenuController } from './CustomizableContextMenu';
import DicomTagBrowser from './DicomTagBrowser/DicomTagBrowser';
import reuseCachedLayouts from './utils/reuseCachedLayouts';
import findViewportsByPosition, {
@@ -113,10 +113,7 @@ const commandsModule = ({
const optionsToUse = { ...options };
if (menuCustomizationId) {
Object.assign(
optionsToUse,
customizationService.get(menuCustomizationId, defaultContextMenu)
);
Object.assign(optionsToUse, customizationService.getCustomization(menuCustomizationId));
}
// TODO - make the selectorProps richer by including the study metadata and display set.
@@ -0,0 +1,25 @@
import { CustomizationService } from '@ohif/core';
export default {
'ohif.contextMenu': {
$transform: function (customizationService: CustomizationService) {
/**
* Applies the inheritsFrom to all the menu items.
* This function clones the object and child objects to prevent
* changes to the original customization object.
*/
// Don't modify the children, as those are copied by reference
const clonedObject = { ...this };
clonedObject.menus = this.menus.map(menu => ({ ...menu }));
for (const menu of clonedObject.menus) {
const { items: originalItems } = menu;
menu.items = [];
for (const item of originalItems) {
menu.items.push(customizationService.transform(item));
}
}
return clonedObject;
},
},
};
@@ -0,0 +1,6 @@
export default {
'routes.customRoutes': {
routes: [],
notFoundRoute: null,
},
};
@@ -0,0 +1,19 @@
import DataSourceConfigurationComponent from '../Components/DataSourceConfigurationComponent';
import { GoogleCloudDataSourceConfigurationAPI } from '../DataSourceConfigurationAPI/GoogleCloudDataSourceConfigurationAPI';
export default function getDataSourceConfigurationCustomization({
servicesManager,
extensionManager,
}) {
return {
// the generic GUI component to configure a data source using an instance of a BaseDataSourceConfigurationAPI
'ohif.dataSourceConfigurationComponent': DataSourceConfigurationComponent.bind(null, {
servicesManager,
extensionManager,
}),
// The factory for creating an instance of a BaseDataSourceConfigurationAPI for Google Cloud Healthcare
'ohif.dataSourceConfigurationAPI.google': (dataSourceName: string) =>
new GoogleCloudDataSourceConfigurationAPI(dataSourceName, servicesManager, extensionManager),
};
}
@@ -0,0 +1,14 @@
import DataSourceSelector from '../Panels/DataSourceSelector';
export default {
'routes.customRoutes': {
routes: {
$push: [
{
path: '/datasources',
children: DataSourceSelector,
},
],
},
},
};
@@ -0,0 +1,22 @@
export default {
measurementsContextMenu: {
inheritsFrom: 'ohif.contextMenu',
menus: [
// Get the items from the UI Customization for the menu name (and have a custom name)
{
id: 'forExistingMeasurement',
selector: ({ nearbyToolData }) => !!nearbyToolData,
items: [
{
label: 'Delete measurement',
commands: 'deleteMeasurement',
},
{
label: 'Add Label',
commands: 'setMeasurementLabel',
},
],
},
],
},
};
@@ -0,0 +1,14 @@
import React from 'react';
export default {
'routes.customRoutes': {
routes: {
$push: [
{
path: '/custom',
children: () => <h1 style={{ color: 'white' }}>Hello Custom Route</h1>,
},
],
},
},
};
@@ -0,0 +1,67 @@
import React from 'react';
import {
DropdownMenuSub,
DropdownMenuSubTrigger,
DropdownMenuPortal,
DropdownMenuSubContent,
DropdownMenuItem,
Icons,
} from '@ohif/ui-next';
export default {
'ohif.menuContent': function (props) {
const { item: topLevelItem, commandsManager, servicesManager, ...rest } = props;
const content = function (subProps) {
const { item: subItem } = subProps;
// Regular menu item
const isDisabled = subItem.selector && !subItem.selector({ servicesManager });
return (
<DropdownMenuItem
disabled={isDisabled}
onSelect={() => {
commandsManager.runAsync(subItem.commands, {
...subItem.commandOptions,
...rest,
});
}}
className="gap-[6px]"
>
{subItem.iconName && (
<Icons.ByName
name={subItem.iconName}
className="-ml-1"
/>
)}
{subItem.label}
</DropdownMenuItem>
);
};
// If item has sub-items, render a submenu
if (topLevelItem.items) {
return (
<DropdownMenuSub>
<DropdownMenuSubTrigger className="gap-[6px]">
{topLevelItem.iconName && (
<Icons.ByName
name={topLevelItem.iconName}
className="-ml-1"
/>
)}
{topLevelItem.label}
</DropdownMenuSubTrigger>
<DropdownMenuPortal>
<DropdownMenuSubContent>
{topLevelItem.items.map(subItem => content({ ...props, item: subItem }))}
</DropdownMenuSubContent>
</DropdownMenuPortal>
</DropdownMenuSub>
);
}
return content({ ...props, item: topLevelItem });
},
};
@@ -0,0 +1,63 @@
export default {
'studyBrowser.studyMenuItems': {
$push: [
{
id: 'applyHangingProtocol',
label: 'Apply Hanging Protocol',
iconName: 'ViewportViews',
items: [
{
id: 'applyDefaultProtocol',
label: 'Default',
commands: [
'loadStudy',
{
commandName: 'setHangingProtocol',
commandOptions: {
protocolId: 'default',
},
},
],
},
{
id: 'applyMPRProtocol',
label: '2x2 Grid',
commands: [
'loadStudy',
{
commandName: 'setHangingProtocol',
commandOptions: {
protocolId: '@ohif/mnGrid',
},
},
],
},
],
},
{
id: 'showInOtherMonitor',
label: 'Launch On Second Monitor',
iconName: 'DicomTagBrowser',
selector: ({ servicesManager }) => {
const { multiMonitorService } = servicesManager.services;
return multiMonitorService.isMultimonitor;
},
commands: {
commandName: 'multimonitor',
commandOptions: {
hashParams: '&hangingProtocolId=@ohif/mnGrid8',
commands: [
'loadStudy',
{
commandName: 'setHangingProtocol',
commandOptions: {
protocolId: '@ohif/mnGrid8',
},
},
],
},
},
},
],
},
};
@@ -0,0 +1,31 @@
import React from 'react';
export default {
'ohif.overlayItem': function (props) {
if (this.condition && !this.condition(props)) {
return null;
}
const { instance } = props;
const value =
instance && this.attribute
? instance[this.attribute]
: this.contentF && typeof this.contentF === 'function'
? this.contentF(props)
: null;
if (!value) {
return null;
}
return (
<span
className="overlay-item flex flex-row"
style={{ color: this.color || undefined }}
title={this.title || ''}
>
{this.label && <span className="mr-1 shrink-0">{this.label}</span>}
<span className="font-light">{value}</span>
</span>
);
},
};
@@ -0,0 +1,5 @@
import { ProgressDropdownWithService } from '../Components/ProgressDropdownWithService';
export default {
progressDropdownWithServiceComponent: ProgressDropdownWithService,
};
@@ -0,0 +1,7 @@
import { utils } from '@ohif/core';
const { sortingCriteria } = utils;
export default {
sortingCriteria: sortingCriteria.seriesSortCriteria.seriesInfoSortingCriteria,
};
@@ -1,81 +0,0 @@
export const studyBrowserContextMenu = {
id: 'StudyBrowser.studyContextMenu',
customizationType: 'ohif.contextMenu',
menus: [
{
id: 'studyBrowserContextMenu',
// selector restricts context menu to when there is nearbyToolData
items: [
{
label: 'Show in Grid',
commands: {
commandName: 'loadStudy',
commandOptions: {
commands: {
commandName: 'setHangingProtocol',
commandOptions: {
protocolId: '@ohif/mnGrid8',
},
},
},
},
},
{
label: 'Show in other monitor',
selector: ({ isMultimonitor }) => isMultimonitor,
commands: {
commandName: 'multimonitor',
commandOptions: {
commands: {
commandName: 'loadStudy',
commandOptions: {
commands: {
commandName: 'setHangingProtocol',
commandOptions: {
protocolId: '@ohif/mnGrid8',
},
},
},
},
},
},
},
{
label: 'Compare All',
selector: ({ isMultimonitor }) => isMultimonitor,
commands: [
{
commandName: 'loadStudy',
commandOptions: {
commands: {
commandName: 'setHangingProtocol',
commandOptions: {
protocolId: '@ohif/mnGrid',
},
},
},
},
{
commandName: 'multimonitor',
commandOptions: {
commands: {
commandName: 'loadStudy',
commandOptions: {
commands: {
commandName: 'setHangingProtocol',
commandOptions: {
protocolId: '@ohif/mnGridMonitor2',
},
},
},
},
},
},
],
},
],
},
],
};
export default studyBrowserContextMenu;
@@ -0,0 +1,43 @@
import { utils } from '@ohif/core';
const { formatDate } = utils;
export default {
'studyBrowser.studyMenuItems': [],
'studyBrowser.thumbnailMenuItems': [
{
id: 'tagBrowser',
label: 'Tag Browser',
iconName: 'DicomTagBrowser',
commands: 'openDICOMTagViewer',
},
],
'studyBrowser.sortFunctions': [
{
label: 'Series Number',
sortFunction: (a, b) => {
return a?.SeriesNumber - b?.SeriesNumber;
},
},
{
label: 'Series Date',
sortFunction: (a, b) => {
const dateA = new Date(formatDate(a?.SeriesDate));
const dateB = new Date(formatDate(b?.SeriesDate));
return dateB.getTime() - dateA.getTime();
},
},
],
'studyBrowser.viewPresets': [
{
id: 'list',
iconName: 'ListView',
selected: false,
},
{
id: 'thumbnails',
iconName: 'ThumbnailView',
selected: true,
},
],
'studyBrowser.studyMode': 'all',
};
+26 -319
View File
@@ -1,21 +1,15 @@
import { CustomizationService } from '@ohif/core';
import React from 'react';
import DataSourceSelector from './Panels/DataSourceSelector';
import { ProgressDropdownWithService } from './Components/ProgressDropdownWithService';
import DataSourceConfigurationComponent from './Components/DataSourceConfigurationComponent';
import { GoogleCloudDataSourceConfigurationAPI } from './DataSourceConfigurationAPI/GoogleCloudDataSourceConfigurationAPI';
import { utils } from '@ohif/core';
import studyBrowserContextMenu from './customizations/studyBrowserContextMenu';
import {
DropdownMenuSub,
DropdownMenuSubTrigger,
DropdownMenuPortal,
DropdownMenuSubContent,
DropdownMenuItem,
Icons,
} from '@ohif/ui-next';
const formatDate = utils.formatDate;
import defaultContextMenuCustomization from './customizations/defaultContextMenuCustomization';
import helloPageCustomization from './customizations/helloPageCustomization';
import datasourcesCustomization from './customizations/datasourcesCustomization';
import multimonitorCustomization from './customizations/multimonitorCustomization';
import customRoutesCustomization from './customizations/customRoutesCustomization';
import studyBrowserCustomization from './customizations/studyBrowserCustomization';
import overlayItemCustomization from './customizations/overlayItemCustomization';
import contextMenuCustomization from './customizations/contextMenuCustomization';
import menuContentCustomization from './customizations/menuContentCustomization';
import getDataSourceConfigurationCustomization from './customizations/dataSourceConfigurationCustomization';
import progressDropdownCustomization from './customizations/progressDropdownCustomization';
import sortingCriteriaCustomization from './customizations/sortingCriteriaCustomization';
/**
*
@@ -30,316 +24,29 @@ export default function getCustomizationModule({ servicesManager, extensionManag
return [
{
name: 'helloPage',
merge: 'Append',
value: {
id: 'customRoutes',
routes: [
{
path: '/custom',
children: () => <h1 style={{ color: 'white' }}>Hello Custom Route</h1>,
},
],
},
value: helloPageCustomization,
},
// Example customization to list a set of datasources
{
name: 'datasources',
merge: 'Append',
value: {
id: 'customRoutes',
routes: [
{
path: '/datasources',
children: DataSourceSelector,
},
],
},
value: datasourcesCustomization,
},
{
name: 'multimonitor',
merge: 'Append',
value: {
id: 'studyBrowser.studyMenuItems',
customizationType: 'ohif.menuContent',
value: [
{
id: 'applyHangingProtocol',
label: 'Apply Hanging Protocol',
iconName: 'ViewportViews',
items: [
{
id: 'applyDefaultProtocol',
label: 'Default',
commands: [
'loadStudy',
{
commandName: 'setHangingProtocol',
commandOptions: {
protocolId: 'default',
},
},
],
},
{
id: 'applyMPRProtocol',
label: '2x2 Grid',
commands: [
'loadStudy',
{
commandName: 'setHangingProtocol',
commandOptions: {
protocolId: '@ohif/mnGrid',
},
},
],
},
],
},
{
id: 'showInOtherMonitor',
label: 'Launch On Second Monitor',
iconName: 'DicomTagBrowser',
// we should use evaluator for this, as these are basically toolbar buttons
selector: ({ servicesManager }) => {
const { multiMonitorService } = servicesManager.services;
return multiMonitorService.isMultimonitor;
},
commands: {
commandName: 'multimonitor',
commandOptions: {
hashParams: '&hangingProtocolId=@ohif/mnGrid8',
commands: [
'loadStudy',
{
commandName: 'setHangingProtocol',
commandOptions: {
protocolId: '@ohif/mnGrid8',
},
},
],
},
},
},
],
},
value: multimonitorCustomization,
},
{
name: 'default',
value: [
/**
* Customization Component Type definition for overlay items.
* Overlay items are texts (or other components) that will be displayed
* on a Viewport Overlay, which contains the information panels on the
* four corners of a viewport.
*
* @definition of a overlay item using this type
* The value to be displayed is defined by
* - setting DICOM image instance's property to this field,
* - or defining contentF()
*
* {
* id: string - unique id for the overlay item
* customizationType: string - indicates customization type definition to this
* label: string - Label, to be displayed for the item
* title: string - Tooltip, for the item
* color: string - Color of the text
* condition: ({ instance }) => boolean - decides whether to display the overlay item or not
* attribute: string - property name of the DICOM image instance
* contentF: ({ instance, formatters }) => string | component,
* }
*
* @example
* {
* id: 'PatientNameOverlay',
* customizationType: 'ohif.overlayItem',
* label: 'PN:',
* title: 'Patient Name',
* color: 'yellow',
* condition: ({ instance }) => instance && instance.PatientName && instance.PatientName.Alphabetic,
* attribute: 'PatientName',
* contentF: ({ instance, formatters: { formatPN } }) => `${formatPN(instance.PatientName.Alphabetic)} ${(instance.PatientSex ? '(' + instance.PatientSex + ')' : '')}`,
* },
*
* @see CustomizableViewportOverlay
*/
{
id: 'ohif.overlayItem',
content: function (props) {
if (this.condition && !this.condition(props)) {
return null;
}
const { instance } = props;
const value =
instance && this.attribute
? instance[this.attribute]
: this.contentF && typeof this.contentF === 'function'
? this.contentF(props)
: null;
if (!value) {
return null;
}
return (
<span
className="overlay-item flex flex-row"
style={{ color: this.color || undefined }}
title={this.title || ''}
>
{this.label && <span className="mr-1 shrink-0">{this.label}</span>}
<span className="font-light">{value}</span>
</span>
);
},
},
{
id: 'ohif.contextMenu',
/** Applies the customizationType to all the menu items.
* This function clones the object and child objects to prevent
* changes to the original customization object.
*/
transform: function (customizationService: CustomizationService) {
// Don't modify the children, as those are copied by reference
const clonedObject = { ...this };
clonedObject.menus = this.menus.map(menu => ({ ...menu }));
for (const menu of clonedObject.menus) {
const { items: originalItems } = menu;
menu.items = [];
for (const item of originalItems) {
menu.items.push(customizationService.transform(item));
}
}
return clonedObject;
},
},
studyBrowserContextMenu,
{
// the generic GUI component to configure a data source using an instance of a BaseDataSourceConfigurationAPI
id: 'ohif.dataSourceConfigurationComponent',
component: DataSourceConfigurationComponent.bind(null, {
servicesManager,
extensionManager,
}),
},
{
// The factory for creating an instance of a BaseDataSourceConfigurationAPI for Google Cloud Healthcare
id: 'ohif.dataSourceConfigurationAPI.google',
factory: (dataSourceName: string) =>
new GoogleCloudDataSourceConfigurationAPI(
dataSourceName,
servicesManager,
extensionManager
),
},
{
id: 'progressDropdownWithServiceComponent',
component: ProgressDropdownWithService,
},
{
id: 'studyBrowser.sortFunctions',
values: [
{
label: 'Series Number',
sortFunction: (a, b) => {
return a?.SeriesNumber - b?.SeriesNumber;
},
},
{
label: 'Series Date',
sortFunction: (a, b) => {
const dateA = new Date(formatDate(a?.SeriesDate));
const dateB = new Date(formatDate(b?.SeriesDate));
return dateB.getTime() - dateA.getTime();
},
},
],
},
{
id: 'studyBrowser.viewPresets',
// change your default selected preset here
value: [
{
id: 'list',
iconName: 'ListView',
selected: false,
},
{
id: 'thumbnails',
iconName: 'ThumbnailView',
selected: true,
},
],
},
{
id: 'studyBrowser.thumbnailMenuItems',
value: [
{
id: 'tagBrowser',
label: 'Tag Browser',
iconName: 'DicomTagBrowser',
commands: 'openDICOMTagViewer',
},
],
},
{
id: 'ohif.menuContent',
content: function (props) {
const { item, commandsManager, servicesManager, ...rest } = props;
// If item has sub-items, render a submenu
if (item.items) {
return (
<DropdownMenuSub>
<DropdownMenuSubTrigger className="gap-[6px]">
{item.iconName && (
<Icons.ByName
name={item.iconName}
className="-ml-1"
/>
)}
{item.label}
</DropdownMenuSubTrigger>
<DropdownMenuPortal>
<DropdownMenuSubContent>
{item.items.map(subItem => this.content({ ...props, item: subItem }))}
</DropdownMenuSubContent>
</DropdownMenuPortal>
</DropdownMenuSub>
);
}
// Regular menu item
const isDisabled = item.selector && !item.selector({ servicesManager });
return (
<DropdownMenuItem
disabled={isDisabled}
onSelect={() => {
commandsManager.runAsync(item.commands, {
...item.commandOptions,
...rest,
});
}}
className="gap-[6px]"
>
{item.iconName && (
<Icons.ByName
name={item.iconName}
className="-ml-1"
/>
)}
{item.label}
</DropdownMenuItem>
);
},
},
],
value: {
...customRoutesCustomization,
...studyBrowserCustomization,
...overlayItemCustomization,
...contextMenuCustomization,
...menuContentCustomization,
...getDataSourceConfigurationCustomization({ servicesManager, extensionManager }),
...progressDropdownCustomization,
...sortingCriteriaCustomization,
...defaultContextMenuCustomization,
},
},
];
}
@@ -1,4 +1,4 @@
import { hpMN, hpMN8, hpMNMonitor2 } from './hangingprotocols/hpMNGrid';
import { hpMN, hpMN8 } from './hangingprotocols/hpMNGrid';
import hpMNCompare from './hangingprotocols/hpCompare';
import hpMammography from './hangingprotocols/hpMammo';
import hpScale from './hangingprotocols/hpScale';
@@ -149,10 +149,6 @@ function getHangingProtocolModule() {
name: hpMN8.id,
protocol: hpMN8,
},
{
name: hpMNMonitor2.id,
protocol: hpMNMonitor2,
},
];
}
@@ -32,6 +32,7 @@ export const hpMN: Types.HangingProtocol.Protocol = {
toolGroupIds: ['default'],
displaySetSelectors: {
defaultDisplaySetId: {
allowUnmatchedView: true,
seriesMatchingRules: seriesWithImages,
},
},
@@ -39,7 +40,6 @@ export const hpMN: Types.HangingProtocol.Protocol = {
viewportOptions: {
viewportType: 'stack',
toolGroupId: 'default',
allowUnmatchedView: true,
syncGroups: [HYDRATE_SEG_SYNC_GROUP],
},
displaySets: [
@@ -393,163 +393,4 @@ export const hpMN8: Types.HangingProtocol.Protocol = {
],
};
/**
* This hanging protocol extends the default protocol with additional
* images on the second monitor. It assumes the first four images are shown
* on monitor 0
*/
export const hpMNMonitor2: Types.HangingProtocol.Protocol = {
...hpMN,
id: '@ohif/mnGridMonitor2',
description: 'Second monitor HP with 2x2 grid',
name: '2x2 Monitor 2',
stages: [
{
id: '2x2',
name: '2x2',
stageActivation: {
enabled: {
minViewportsMatched: 3,
},
},
viewportStructure: {
layoutType: 'grid',
properties: {
rows: 2,
columns: 2,
},
},
viewports: [
{
viewportOptions,
displaySets: [
{
id: 'defaultDisplaySetId',
matchedDisplaySetsIndex: 4,
},
],
},
{
viewportOptions,
displaySets: [
{
matchedDisplaySetsIndex: 5,
id: 'defaultDisplaySetId',
},
],
},
{
viewportOptions,
displaySets: [
{
matchedDisplaySetsIndex: 6,
id: 'defaultDisplaySetId',
},
],
},
{
viewportOptions,
displaySets: [
{
matchedDisplaySetsIndex: 7,
id: 'defaultDisplaySetId',
},
],
},
],
},
// A 2x1 stage
{
name: '2x1',
stageActivation: {
enabled: {
minViewportsMatched: 1,
},
},
viewportStructure: {
layoutType: 'grid',
properties: {
rows: 1,
columns: 2,
},
},
viewports: [
{
viewportOptions,
displaySets: [
{
id: 'defaultDisplaySetId',
matchedDisplaySetsIndex: 4,
},
],
},
{
viewportOptions,
displaySets: [
{
matchedDisplaySetsIndex: 5,
id: 'defaultDisplaySetId',
},
],
},
],
},
{
name: '1x1',
stageActivation: {
enabled: {
minViewportsMatched: 0,
},
},
viewportStructure: {
layoutType: 'grid',
properties: {
rows: 1,
columns: 1,
},
},
viewports: [
{
viewportOptions,
displaySets: [
{
id: 'defaultDisplaySetId',
matchedDisplaySetsIndex: 4,
},
],
},
],
},
{
name: '1x1 Base',
stageActivation: {
enabled: {
minViewportsMatched: 1,
},
},
viewportStructure: {
layoutType: 'grid',
properties: {
rows: 1,
columns: 1,
},
},
viewports: [
{
viewportOptions,
displaySets: [
{
id: 'defaultDisplaySetId',
matchedDisplaySetsIndex: 0,
},
],
},
],
},
],
};
export default hpMN;
@@ -36,9 +36,10 @@ function usePatientInfo(servicesManager: AppTypes.ServicesManager) {
if (!instance) {
return;
}
setPatientInfo({
PatientID: instance.PatientID || null,
PatientName: instance.PatientName ? formatPN(instance.PatientName.Alphabetic) : null,
PatientName: instance.PatientName ? formatPN(instance.PatientName ) : null,
PatientSex: instance.PatientSex || null,
PatientDOB: formatDate(instance.PatientBirthDate) || null,
});
@@ -2,7 +2,7 @@ import { create } from 'zustand';
import { devtools } from 'zustand/middleware';
const PRESENTATION_TYPE_ID = 'viewportsByPositionId';
const DEBUG_STORE = true;
const DEBUG_STORE = false;
/**
* Represents the state and actions for managing viewports by position.
@@ -4,7 +4,7 @@ function promptLabelAnnotation({ servicesManager }, ctx, evt) {
const { measurementService, customizationService } = servicesManager.services;
const { viewportId, StudyInstanceUID, SeriesInstanceUID, measurementId } = evt;
return new Promise(async function (resolve) {
const labelConfig = customizationService.get('measurementLabels');
const labelConfig = customizationService.getCustomization('measurementLabels');
const measurement = measurementService.getMeasurement(measurementId);
const value = await showLabelAnnotationPopup(
measurement,
+163
View File
@@ -3,6 +3,169 @@
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.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
# [3.10.0-beta.76](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.75...v3.10.0-beta.76) (2025-01-27)
**Note:** Version bump only for package @ohif/extension-dicom-microscopy
# [3.10.0-beta.75](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.74...v3.10.0-beta.75) (2025-01-27)
**Note:** Version bump only for package @ohif/extension-dicom-microscopy
# [3.10.0-beta.74](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.73...v3.10.0-beta.74) (2025-01-27)
**Note:** Version bump only for package @ohif/extension-dicom-microscopy
# [3.10.0-beta.73](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.72...v3.10.0-beta.73) (2025-01-24)
**Note:** Version bump only for package @ohif/extension-dicom-microscopy
# [3.10.0-beta.72](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.71...v3.10.0-beta.72) (2025-01-24)
**Note:** Version bump only for package @ohif/extension-dicom-microscopy
# [3.10.0-beta.71](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.70...v3.10.0-beta.71) (2025-01-23)
**Note:** Version bump only for package @ohif/extension-dicom-microscopy
# [3.10.0-beta.70](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.69...v3.10.0-beta.70) (2025-01-23)
**Note:** Version bump only for package @ohif/extension-dicom-microscopy
# [3.10.0-beta.69](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.68...v3.10.0-beta.69) (2025-01-22)
**Note:** Version bump only for package @ohif/extension-dicom-microscopy
# [3.10.0-beta.68](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.67...v3.10.0-beta.68) (2025-01-21)
**Note:** Version bump only for package @ohif/extension-dicom-microscopy
# [3.10.0-beta.67](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.66...v3.10.0-beta.67) (2025-01-21)
**Note:** Version bump only for package @ohif/extension-dicom-microscopy
# [3.10.0-beta.66](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.65...v3.10.0-beta.66) (2025-01-21)
### Bug Fixes
* Inconsistent Handling of Patient Name Tag ([#4703](https://github.com/OHIF/Viewers/issues/4703)) ([8aedb2e](https://github.com/OHIF/Viewers/commit/8aedb2ec54a0ccf2550f745fed6f0b8aa184a860))
# [3.10.0-beta.65](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.64...v3.10.0-beta.65) (2025-01-20)
**Note:** Version bump only for package @ohif/extension-dicom-microscopy
# [3.10.0-beta.64](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.63...v3.10.0-beta.64) (2025-01-20)
**Note:** Version bump only for package @ohif/extension-dicom-microscopy
# [3.10.0-beta.63](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.62...v3.10.0-beta.63) (2025-01-17)
**Note:** Version bump only for package @ohif/extension-dicom-microscopy
# [3.10.0-beta.62](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.61...v3.10.0-beta.62) (2025-01-16)
**Note:** Version bump only for package @ohif/extension-dicom-microscopy
# [3.10.0-beta.61](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.60...v3.10.0-beta.61) (2025-01-16)
**Note:** Version bump only for package @ohif/extension-dicom-microscopy
# [3.10.0-beta.60](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.59...v3.10.0-beta.60) (2025-01-15)
**Note:** Version bump only for package @ohif/extension-dicom-microscopy
# [3.10.0-beta.59](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.58...v3.10.0-beta.59) (2025-01-14)
**Note:** Version bump only for package @ohif/extension-dicom-microscopy
# [3.10.0-beta.58](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.57...v3.10.0-beta.58) (2025-01-13)
**Note:** Version bump only for package @ohif/extension-dicom-microscopy
+5 -5
View File
@@ -1,6 +1,6 @@
{
"name": "@ohif/extension-dicom-microscopy",
"version": "3.10.0-beta.58",
"version": "3.10.0-beta.78",
"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.58",
"@ohif/extension-default": "3.10.0-beta.58",
"@ohif/i18n": "3.10.0-beta.58",
"@ohif/ui": "3.10.0-beta.58",
"@ohif/core": "3.10.0-beta.78",
"@ohif/extension-default": "3.10.0-beta.78",
"@ohif/i18n": "3.10.0-beta.78",
"@ohif/ui": "3.10.0-beta.78",
"prop-types": "^15.6.2",
"react": "^18.3.1",
"react-dom": "^18.3.1",
Loaded 100 of 248 files, more files were not shown because too many files have changed in this diff. Show more