Compare commits
25
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ff6dd3a152 | ||
|
|
a22818c1f4 | ||
|
|
6abb095b8a | ||
|
|
fe658c6392 | ||
|
|
70c94e8d5a | ||
|
|
5addf51c45 | ||
|
|
8e3e2085d4 | ||
|
|
078a72996f | ||
|
|
dc14a48fd9 | ||
|
|
61699d00b6 | ||
|
|
eb854ac2cb | ||
|
|
6c42f269a7 | ||
|
|
ac6e674b4d | ||
|
|
316cf0a7bd | ||
|
|
c011236060 | ||
|
|
2ed7a1adfa | ||
|
|
492150478b | ||
|
|
cb03077d37 | ||
|
|
28fb921089 | ||
|
|
bc175d68b6 | ||
|
|
884020f143 | ||
|
|
d6f0092a32 | ||
|
|
01fa5d83a6 | ||
|
|
625919d4e4 | ||
|
|
55ad8efbab |
No files matched your search
+2
-1
@@ -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,
|
||||
|
||||
@@ -3,6 +3,91 @@
|
||||
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)
|
||||
|
||||
|
||||
|
||||
+64
@@ -3,6 +3,70 @@
|
||||
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
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@externals/devDependencies",
|
||||
"description": "External dev dependencies - put dev build dependencies here",
|
||||
"version": "3.10.0-beta.70",
|
||||
"version": "3.10.0-beta.78",
|
||||
"license": "MIT",
|
||||
"private": true,
|
||||
"engines": {
|
||||
|
||||
@@ -3,6 +3,70 @@
|
||||
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
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@externals/dicom-microscopy-viewer",
|
||||
"description": "External reference to dicom-microscopy-viewer",
|
||||
"version": "3.10.0-beta.70",
|
||||
"version": "3.10.0-beta.78",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"dicom-microscopy-viewer": "^0.46.1"
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
d9abc3da8d94d6c5ab0cc5af25a5f61849905a35
|
||||
6abb095b8a39c5ae4f8df8852b3ddb3249ec463f
|
||||
@@ -3,6 +3,70 @@
|
||||
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
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ohif/extension-cornerstone-dicom-pmap",
|
||||
"version": "3.10.0-beta.70",
|
||||
"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.70",
|
||||
"@ohif/extension-cornerstone": "3.10.0-beta.70",
|
||||
"@ohif/extension-default": "3.10.0-beta.70",
|
||||
"@ohif/i18n": "3.10.0-beta.70",
|
||||
"@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",
|
||||
|
||||
@@ -3,6 +3,73 @@
|
||||
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
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ohif/extension-cornerstone-dicom-rt",
|
||||
"version": "3.10.0-beta.70",
|
||||
"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.70",
|
||||
"@ohif/extension-cornerstone": "3.10.0-beta.70",
|
||||
"@ohif/extension-default": "3.10.0-beta.70",
|
||||
"@ohif/i18n": "3.10.0-beta.70",
|
||||
"@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,73 @@
|
||||
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
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ohif/extension-cornerstone-dicom-seg",
|
||||
"version": "3.10.0-beta.70",
|
||||
"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.70",
|
||||
"@ohif/extension-cornerstone": "3.10.0-beta.70",
|
||||
"@ohif/extension-default": "3.10.0-beta.70",
|
||||
"@ohif/i18n": "3.10.0-beta.70",
|
||||
"@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 createSEGToolGroupAndAddTools(ToolGroupService, customizationService, toolGroupId) {
|
||||
const { tools } = customizationService.get('cornerstone.overlayViewportTools') ?? {};
|
||||
const tools = customizationService.getCustomization('cornerstone.overlayViewportTools');
|
||||
|
||||
return ToolGroupService.createToolGroupAndAddTools(toolGroupId, tools);
|
||||
}
|
||||
|
||||
@@ -3,6 +3,73 @@
|
||||
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
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ohif/extension-cornerstone-dicom-sr",
|
||||
"version": "3.10.0-beta.70",
|
||||
"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.70",
|
||||
"@ohif/extension-cornerstone": "3.10.0-beta.70",
|
||||
"@ohif/extension-measurement-tracking": "3.10.0-beta.70",
|
||||
"@ohif/ui": "3.10.0-beta.70",
|
||||
"@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",
|
||||
|
||||
@@ -118,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);
|
||||
@@ -151,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({
|
||||
|
||||
@@ -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,73 @@
|
||||
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
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ohif/extension-cornerstone-dynamic-volume",
|
||||
"version": "3.10.0-beta.70",
|
||||
"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.70",
|
||||
"@ohif/extension-cornerstone": "3.10.0-beta.70",
|
||||
"@ohif/extension-default": "3.10.0-beta.70",
|
||||
"@ohif/i18n": "3.10.0-beta.70",
|
||||
"@ohif/ui": "3.10.0-beta.70",
|
||||
"@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",
|
||||
|
||||
@@ -5,7 +5,7 @@ function WorkflowPanel({ servicesManager }: { servicesManager: ServicesManager }
|
||||
const ProgressDropdownWithService =
|
||||
servicesManager.services.customizationService.getCustomization(
|
||||
'progressDropdownWithServiceComponent'
|
||||
).component;
|
||||
);
|
||||
|
||||
return (
|
||||
<div
|
||||
|
||||
@@ -3,6 +3,79 @@
|
||||
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
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ohif/extension-cornerstone",
|
||||
"version": "3.10.0-beta.70",
|
||||
"version": "3.10.0-beta.78",
|
||||
"description": "OHIF extension for Cornerstone",
|
||||
"author": "OHIF",
|
||||
"license": "MIT",
|
||||
@@ -40,8 +40,8 @@
|
||||
"@cornerstonejs/codec-openjph": "^2.4.5",
|
||||
"@cornerstonejs/dicom-image-loader": "^2.17.2",
|
||||
"@icr/polyseg-wasm": "^0.4.0",
|
||||
"@ohif/core": "3.10.0-beta.70",
|
||||
"@ohif/ui": "3.10.0-beta.70",
|
||||
"@ohif/core": "3.10.0-beta.78",
|
||||
"@ohif/ui": "3.10.0-beta.78",
|
||||
"dcmjs": "*",
|
||||
"dicom-parser": "^1.8.21",
|
||||
"hammerjs": "^2.0.8",
|
||||
|
||||
@@ -47,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
|
||||
*/
|
||||
@@ -143,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(
|
||||
() =>
|
||||
@@ -264,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} />;
|
||||
@@ -293,10 +211,6 @@ function CustomizableViewportOverlay({
|
||||
|
||||
const getContent = useCallback(
|
||||
(customization, keyPrefix) => {
|
||||
if (!customization?.items) {
|
||||
return null;
|
||||
}
|
||||
const { items } = customization;
|
||||
const props = {
|
||||
...displaySetProps,
|
||||
formatters: { formatDate: formatDICOMDate },
|
||||
@@ -309,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}
|
||||
@@ -533,4 +447,4 @@ CustomizableViewportOverlay.propTypes = {
|
||||
|
||||
export default CustomizableViewportOverlay;
|
||||
|
||||
export { CustomizableViewportOverlay, CornerstoneOverlay };
|
||||
export { CustomizableViewportOverlay };
|
||||
@@ -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: () => {
|
||||
@@ -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);
|
||||
|
||||
|
||||
+1
-1
@@ -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');
|
||||
|
||||
+12
-12
@@ -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' },
|
||||
],
|
||||
};
|
||||
|
||||
|
||||
+7
-6
@@ -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) {
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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 }) => {
|
||||
@@ -272,7 +168,7 @@ export default function PanelSegmentation({
|
||||
<SegmentationTable
|
||||
disabled={disabled}
|
||||
data={segmentationsWithRepresentations}
|
||||
mode={SegmentationTableMode}
|
||||
mode={segmentationTableMode}
|
||||
title="Segmentations"
|
||||
exportOptions={exportOptions}
|
||||
disableEditing={disableEditing}
|
||||
@@ -308,7 +204,7 @@ export default function PanelSegmentation({
|
||||
<SegmentationTable.Config />
|
||||
<SegmentationTable.AddSegmentationRow />
|
||||
|
||||
{SegmentationTableMode === 'collapsed' ? (
|
||||
{segmentationTableMode === 'collapsed' ? (
|
||||
<SegmentationTable.Collapsed>
|
||||
<SegmentationTable.SelectorHeader>
|
||||
<CustomDropdownMenuContent />
|
||||
|
||||
@@ -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 = [];
|
||||
|
||||
@@ -3,6 +3,79 @@
|
||||
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)
|
||||
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ohif/extension-default",
|
||||
"version": "3.10.0-beta.70",
|
||||
"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.70",
|
||||
"@ohif/i18n": "3.10.0-beta.70",
|
||||
"@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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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.
|
||||
@@ -582,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);
|
||||
|
||||
@@ -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}
|
||||
|
||||
@@ -5,7 +5,7 @@ import { panelGroupDefinition } from './constants/panels';
|
||||
/**
|
||||
* Set the minimum and maximum css style width attributes for the given element.
|
||||
* The two style attributes are cleared whenever the width
|
||||
* arguments is undefined.
|
||||
* argument is undefined.
|
||||
* <p>
|
||||
* This utility is used as part of a HACK throughout the ViewerLayout component as
|
||||
* the means of restricting the side panel widths during the resizing of the
|
||||
@@ -34,7 +34,7 @@ const useResizablePanels = (
|
||||
);
|
||||
const [leftResizablePanelMinimumSize, setLeftResizablePanelMinimumSize] = useState(0);
|
||||
const [rightResizablePanelMinimumSize, setRightResizablePanelMinimumSize] = useState(0);
|
||||
const [leftResizeablePanelCollapsedSize, setLeftResizePanelCollapsedSize] = useState(0);
|
||||
const [leftResizablePanelCollapsedSize, setLeftResizePanelCollapsedSize] = useState(0);
|
||||
const [rightResizePanelCollapsedSize, setRightResizePanelCollapsedSize] = useState(0);
|
||||
|
||||
const resizablePanelGroupElemRef = useRef(null);
|
||||
@@ -44,15 +44,16 @@ const useResizablePanels = (
|
||||
const resizableRightPanelAPIRef = useRef(null);
|
||||
const isResizableHandleDraggingRef = useRef(false);
|
||||
|
||||
// The total width of both handles.
|
||||
const resizableHandlesWidth = useRef(null);
|
||||
|
||||
// This useLayoutEffect is used to...
|
||||
// - Grab a reference to the various resizable panel elements needed for
|
||||
// converting between percentages and pixels in various callbacks.
|
||||
// - Expand those panels that are initially expanded.
|
||||
useLayoutEffect(() => {
|
||||
const panelGroupElem = getPanelGroupElement(panelGroupDefinition.groupId);
|
||||
|
||||
resizablePanelGroupElemRef.current = panelGroupElem;
|
||||
const { width: panelGroupWidth } = panelGroupElem.getBoundingClientRect();
|
||||
|
||||
const leftPanelElem = getPanelElement(panelGroupDefinition.left.panelId);
|
||||
resizableLeftPanelElemRef.current = leftPanelElem;
|
||||
@@ -60,20 +61,29 @@ const useResizablePanels = (
|
||||
const rightPanelElem = getPanelElement(panelGroupDefinition.right.panelId);
|
||||
resizableRightPanelElemRef.current = rightPanelElem;
|
||||
|
||||
// Calculate and set the width of both handles combined.
|
||||
const resizeHandles = document.querySelectorAll('[data-panel-resize-handle-id]');
|
||||
resizableHandlesWidth.current = 0;
|
||||
resizeHandles.forEach(resizeHandle => {
|
||||
resizableHandlesWidth.current += resizeHandle.offsetWidth;
|
||||
});
|
||||
|
||||
// Since both resizable panels are collapsed by default (i.e. their default size is zero),
|
||||
// on the very first render check if either/both side panels should be expanded.
|
||||
// we use the initialExpandedOffsetWidth on the first render incase the panel has min width but we want the initial state to be larger than that
|
||||
|
||||
if (!leftPanelClosed) {
|
||||
const leftResizablePanelExpandedSize =
|
||||
(panelGroupDefinition.left.initialExpandedOffsetWidth / panelGroupWidth) * 100;
|
||||
const leftResizablePanelExpandedSize = getPercentageSize(
|
||||
panelGroupDefinition.left.initialExpandedOffsetWidth
|
||||
);
|
||||
resizableLeftPanelAPIRef?.current?.expand(leftResizablePanelExpandedSize);
|
||||
setMinMaxWidth(leftPanelElem, panelGroupDefinition.left.initialExpandedOffsetWidth);
|
||||
}
|
||||
|
||||
if (!rightPanelClosed) {
|
||||
const rightResizablePanelExpandedSize =
|
||||
(panelGroupDefinition.right.initialExpandedOffsetWidth / panelGroupWidth) * 100;
|
||||
const rightResizablePanelExpandedSize = getPercentageSize(
|
||||
panelGroupDefinition.right.initialExpandedOffsetWidth
|
||||
);
|
||||
resizableRightPanelAPIRef?.current?.expand(rightResizablePanelExpandedSize);
|
||||
setMinMaxWidth(rightPanelElem, panelGroupDefinition.right.initialExpandedOffsetWidth);
|
||||
}
|
||||
@@ -89,103 +99,47 @@ const useResizablePanels = (
|
||||
// values whenever the resizable panel group is resized (e.g. whenever the
|
||||
// browser window is resized).
|
||||
useLayoutEffect(() => {
|
||||
const { width: panelGroupWidth } = resizablePanelGroupElemRef.current.getBoundingClientRect();
|
||||
|
||||
// Ensure the side panels' percentage size is in synch with the pixel width of the
|
||||
// expanded side panels. In general the two get out-of-sync during a browser
|
||||
// window resize. Note that this code is here and NOT in the ResizeObserver
|
||||
// because it has to be done AFTER the minimum percentage size for a panel is
|
||||
// updated which occurs only AFTER the render following a resize. And by virtue
|
||||
// of the dependency on the `resizablePanelDefaultSize` state, this code
|
||||
// is executed on the render following an update of the minimum percentage size
|
||||
// updated which occurs only AFTER the render following a browser window resize.
|
||||
// And by virtue of the dependency on the minimum size state variables, this code
|
||||
// is executed on the render following an update of the minimum percentage sizes
|
||||
// for a panel.
|
||||
if (!resizableLeftPanelAPIRef.current.isCollapsed()) {
|
||||
const leftSize =
|
||||
((leftPanelExpandedWidth + panelGroupDefinition.shared.expandedInsideBorderSize) /
|
||||
panelGroupWidth) *
|
||||
100;
|
||||
const leftSize = getPercentageSize(
|
||||
leftPanelExpandedWidth + panelGroupDefinition.shared.expandedInsideBorderSize
|
||||
);
|
||||
resizableLeftPanelAPIRef.current.resize(leftSize);
|
||||
}
|
||||
|
||||
if (!resizableRightPanelAPIRef.current.isCollapsed()) {
|
||||
const rightSize =
|
||||
((rightPanelExpandedWidth + panelGroupDefinition.shared.expandedInsideBorderSize) /
|
||||
panelGroupWidth) *
|
||||
100;
|
||||
const rightSize = getPercentageSize(
|
||||
rightPanelExpandedWidth + panelGroupDefinition.shared.expandedInsideBorderSize
|
||||
);
|
||||
resizableRightPanelAPIRef.current.resize(rightSize);
|
||||
}
|
||||
|
||||
// This observer kicks in when the ViewportLayout resizable panel group
|
||||
// component is resized. This typically occurs when the browser window resizes.
|
||||
const observer = new ResizeObserver(() => {
|
||||
const { width: panelGroupWidth } = resizablePanelGroupElemRef.current.getBoundingClientRect();
|
||||
const minimumLeftSize =
|
||||
(panelGroupDefinition.left.minimumExpandedOffsetWidth / panelGroupWidth) * 100;
|
||||
const minimumRightSize =
|
||||
(panelGroupDefinition.right.minimumExpandedOffsetWidth / panelGroupWidth) * 100;
|
||||
const minimumLeftSize = getPercentageSize(
|
||||
panelGroupDefinition.left.minimumExpandedOffsetWidth
|
||||
);
|
||||
const minimumRightSize = getPercentageSize(
|
||||
panelGroupDefinition.right.minimumExpandedOffsetWidth
|
||||
);
|
||||
|
||||
// Set the new default and collapsed resizable panel sizes.
|
||||
setLeftResizablePanelMinimumSize(Math.min(50, minimumLeftSize));
|
||||
setRightResizablePanelMinimumSize(Math.min(50, minimumRightSize));
|
||||
// Set the new minimum and collapsed resizable panel sizes.
|
||||
setLeftResizablePanelMinimumSize(minimumLeftSize);
|
||||
setRightResizablePanelMinimumSize(minimumRightSize);
|
||||
setLeftResizePanelCollapsedSize(
|
||||
(panelGroupDefinition.left.collapsedOffsetWidth / panelGroupWidth) * 100
|
||||
getPercentageSize(panelGroupDefinition.left.collapsedOffsetWidth)
|
||||
);
|
||||
setRightResizePanelCollapsedSize(
|
||||
(panelGroupDefinition.right.collapsedOffsetWidth / panelGroupWidth) * 100
|
||||
getPercentageSize(panelGroupDefinition.right.collapsedOffsetWidth)
|
||||
);
|
||||
|
||||
if (
|
||||
resizableLeftPanelAPIRef.current.isCollapsed() &&
|
||||
resizableRightPanelAPIRef.current.isCollapsed()
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
// The code that follows is to handle cases when the group panel is resized to be
|
||||
// too small to display either side panel at its current width.
|
||||
|
||||
// Determine the current widths of the two side panels.
|
||||
let leftPanelOffsetWidth = resizableLeftPanelAPIRef.current.isCollapsed()
|
||||
? panelGroupDefinition.left.collapsedOffsetWidth
|
||||
: leftPanelExpandedWidth + panelGroupDefinition.shared.expandedInsideBorderSize;
|
||||
|
||||
let rightPanelOffsetWidth = resizableRightPanelAPIRef.current.isCollapsed()
|
||||
? panelGroupDefinition.right.collapsedOffsetWidth
|
||||
: rightPanelExpandedWidth + panelGroupDefinition.shared.expandedInsideBorderSize;
|
||||
|
||||
if (
|
||||
!resizableLeftPanelAPIRef.current.isCollapsed() &&
|
||||
leftPanelOffsetWidth + rightPanelOffsetWidth > panelGroupWidth
|
||||
) {
|
||||
// There is not enough space to show both panels at their pre-resize widths.
|
||||
// Note that at this point, the viewport grid component is zero width.
|
||||
// Reduce the left panel width so that both panels might fit.
|
||||
leftPanelOffsetWidth = Math.max(
|
||||
panelGroupWidth - rightPanelOffsetWidth,
|
||||
panelGroupDefinition.left.minimumExpandedOffsetWidth
|
||||
);
|
||||
setLeftPanelExpandedWidth(
|
||||
leftPanelOffsetWidth - panelGroupDefinition.shared.expandedInsideBorderSize
|
||||
);
|
||||
setMinMaxWidth(resizableLeftPanelElemRef.current, leftPanelOffsetWidth);
|
||||
}
|
||||
|
||||
if (
|
||||
!resizableRightPanelAPIRef.current.isCollapsed() &&
|
||||
rightPanelOffsetWidth + leftPanelOffsetWidth > panelGroupWidth
|
||||
) {
|
||||
// There is not enough space to show both panels at their pre-resize widths.
|
||||
// Note that at this point, the viewport grid component is zero width.
|
||||
// Reduce the right panel width so that both panels might fit.
|
||||
rightPanelOffsetWidth = Math.max(
|
||||
panelGroupWidth - leftPanelOffsetWidth,
|
||||
panelGroupDefinition.right.minimumExpandedOffsetWidth
|
||||
);
|
||||
setRightPanelExpandedWidth(
|
||||
rightPanelOffsetWidth - panelGroupDefinition.shared.expandedInsideBorderSize
|
||||
);
|
||||
setMinMaxWidth(resizableRightPanelElemRef.current, rightPanelOffsetWidth);
|
||||
}
|
||||
});
|
||||
|
||||
observer.observe(resizablePanelGroupElemRef.current);
|
||||
@@ -238,23 +192,26 @@ const useResizablePanels = (
|
||||
}, [setLeftPanelClosed]);
|
||||
|
||||
const onLeftPanelOpen = useCallback(() => {
|
||||
const { width: panelGroupWidth } = resizablePanelGroupElemRef.current.getBoundingClientRect();
|
||||
resizableLeftPanelAPIRef?.current?.expand(
|
||||
(panelGroupDefinition.left.initialExpandedOffsetWidth / panelGroupWidth) * 100
|
||||
getPercentageSize(panelGroupDefinition.left.initialExpandedOffsetWidth)
|
||||
);
|
||||
setLeftPanelClosed(false);
|
||||
}, [setLeftPanelClosed]);
|
||||
|
||||
const onLeftPanelResize = useCallback(size => {
|
||||
if (resizableLeftPanelAPIRef.current.isCollapsed()) {
|
||||
if (!resizablePanelGroupElemRef?.current || resizableLeftPanelAPIRef.current.isCollapsed()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const { width: panelGroupWidth } = resizablePanelGroupElemRef.current.getBoundingClientRect();
|
||||
const newExpandedWidth =
|
||||
(size / 100) * panelGroupWidth - panelGroupDefinition.shared.expandedInsideBorderSize;
|
||||
|
||||
const newExpandedWidth = getExpandedPixelWidth(size);
|
||||
setLeftPanelExpandedWidth(newExpandedWidth);
|
||||
|
||||
if (!isResizableHandleDraggingRef.current) {
|
||||
// This typically gets executed when the left panel is expanded via one of the UI
|
||||
// buttons. It is done here instead of in the onLeftPanelOpen method
|
||||
// because here we know the size of the expanded panel.
|
||||
setMinMaxWidth(resizableLeftPanelElemRef.current, newExpandedWidth);
|
||||
}
|
||||
}, []);
|
||||
|
||||
const onRightPanelClose = useCallback(() => {
|
||||
@@ -264,25 +221,49 @@ const useResizablePanels = (
|
||||
}, [setRightPanelClosed]);
|
||||
|
||||
const onRightPanelOpen = useCallback(() => {
|
||||
const { width: panelGroupWidth } = resizablePanelGroupElemRef.current.getBoundingClientRect();
|
||||
resizableRightPanelAPIRef?.current?.expand(
|
||||
(panelGroupDefinition.right.initialExpandedOffsetWidth / panelGroupWidth) * 100
|
||||
getPercentageSize(panelGroupDefinition.right.initialExpandedOffsetWidth)
|
||||
);
|
||||
setRightPanelClosed(false);
|
||||
}, [setRightPanelClosed]);
|
||||
|
||||
const onRightPanelResize = useCallback(size => {
|
||||
if (resizableRightPanelAPIRef?.current?.isCollapsed()) {
|
||||
if (!resizablePanelGroupElemRef?.current || resizableRightPanelAPIRef.current.isCollapsed()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const { width: panelGroupWidth } = resizablePanelGroupElemRef.current.getBoundingClientRect();
|
||||
const newExpandedWidth =
|
||||
(size / 100) * panelGroupWidth - panelGroupDefinition.shared.expandedInsideBorderSize;
|
||||
|
||||
const newExpandedWidth = getExpandedPixelWidth(size);
|
||||
setRightPanelExpandedWidth(newExpandedWidth);
|
||||
|
||||
if (!isResizableHandleDraggingRef.current) {
|
||||
// This typically gets executed when the right panel is expanded via one of the UI
|
||||
// buttons. It is done here instead of in the onRightPanelOpen method
|
||||
// because here we know the size of the expanded panel.
|
||||
setMinMaxWidth(resizableRightPanelElemRef.current, newExpandedWidth);
|
||||
}
|
||||
}, []);
|
||||
|
||||
/**
|
||||
* Gets the percentage size corresponding to the given pixel size.
|
||||
* Note that the width attributed to the handles must be taken into account.
|
||||
*/
|
||||
const getPercentageSize = pixelSize => {
|
||||
const { width: panelGroupWidth } = resizablePanelGroupElemRef.current.getBoundingClientRect();
|
||||
return (pixelSize / (panelGroupWidth - resizableHandlesWidth.current)) * 100;
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets the width in pixels for an expanded panel given its percentage size/width.
|
||||
* Note that the width attributed to the handles must be taken into account.
|
||||
*/
|
||||
const getExpandedPixelWidth = percentageSize => {
|
||||
const { width: panelGroupWidth } = resizablePanelGroupElemRef.current.getBoundingClientRect();
|
||||
const expandedWidth =
|
||||
(percentageSize / 100) * (panelGroupWidth - resizableHandlesWidth.current) -
|
||||
panelGroupDefinition.shared.expandedInsideBorderSize;
|
||||
return expandedWidth;
|
||||
};
|
||||
|
||||
return [
|
||||
{
|
||||
expandedWidth: leftPanelExpandedWidth,
|
||||
@@ -308,7 +289,7 @@ const useResizablePanels = (
|
||||
minSize: leftResizablePanelMinimumSize,
|
||||
onResize: onLeftPanelResize,
|
||||
collapsible: true,
|
||||
collapsedSize: leftResizeablePanelCollapsedSize,
|
||||
collapsedSize: leftResizablePanelCollapsedSize,
|
||||
onCollapse: () => setLeftPanelClosed(true),
|
||||
onExpand: () => setLeftPanelClosed(false),
|
||||
ref: resizableLeftPanelAPIRef,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
const expandedInsideBorderSize = 4;
|
||||
const expandedInsideBorderSize = 0;
|
||||
const collapsedInsideBorderSize = 4;
|
||||
const collapsedOutsideBorderSize = 8;
|
||||
const collapsedOutsideBorderSize = 4;
|
||||
const collapsedWidth = 25;
|
||||
|
||||
const rightPanelInitialExpandedWidth = 280;
|
||||
|
||||
@@ -9,6 +9,8 @@ import SidePanelWithServices from '../Components/SidePanelWithServices';
|
||||
import { Onboarding, ResizablePanelGroup, ResizablePanel, ResizableHandle } from '@ohif/ui-next';
|
||||
import useResizablePanels from './ResizablePanelsHook';
|
||||
|
||||
const resizableHandleClassName = 'mt-[1px] bg-black';
|
||||
|
||||
function ViewerLayout({
|
||||
// From Extension Module Params
|
||||
extensionManager,
|
||||
@@ -157,7 +159,7 @@ function ViewerLayout({
|
||||
<ResizableHandle
|
||||
onDragging={onHandleDragging}
|
||||
disabled={!leftPanelResizable}
|
||||
className="!w-0"
|
||||
className={resizableHandleClassName}
|
||||
/>
|
||||
</>
|
||||
) : null}
|
||||
@@ -178,7 +180,7 @@ function ViewerLayout({
|
||||
<ResizableHandle
|
||||
onDragging={onHandleDragging}
|
||||
disabled={!rightPanelResizable}
|
||||
className="!w-0"
|
||||
className={resizableHandleClassName}
|
||||
/>
|
||||
<ResizablePanel {...resizableRightPanelProps}>
|
||||
<SidePanelWithServices
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
@@ -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',
|
||||
};
|
||||
@@ -1,20 +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 {
|
||||
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';
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -29,315 +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;
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
// 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,
|
||||
},
|
||||
},
|
||||
];
|
||||
}
|
||||
@@ -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,
|
||||
|
||||
@@ -3,6 +3,70 @@
|
||||
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
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ohif/extension-dicom-microscopy",
|
||||
"version": "3.10.0-beta.70",
|
||||
"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.70",
|
||||
"@ohif/extension-default": "3.10.0-beta.70",
|
||||
"@ohif/i18n": "3.10.0-beta.70",
|
||||
"@ohif/ui": "3.10.0-beta.70",
|
||||
"@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",
|
||||
|
||||
@@ -3,6 +3,70 @@
|
||||
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-pdf
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.10.0-beta.77](https://github.com/OHIF/Viewers/compare/v3.10.0-beta.76...v3.10.0-beta.77) (2025-01-28)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-dicom-pdf
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.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-pdf
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [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-pdf
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [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-pdf
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [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-pdf
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [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-pdf
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [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-pdf
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [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-pdf
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ohif/extension-dicom-pdf",
|
||||
"version": "3.10.0-beta.70",
|
||||
"version": "3.10.0-beta.78",
|
||||
"description": "OHIF extension for PDF display",
|
||||
"author": "OHIF",
|
||||
"license": "MIT",
|
||||
@@ -30,8 +30,8 @@
|
||||
"test:unit:ci": "jest --ci --runInBand --collectCoverage --passWithNoTests"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@ohif/core": "3.10.0-beta.70",
|
||||
"@ohif/ui": "3.10.0-beta.70",
|
||||
"@ohif/core": "3.10.0-beta.78",
|
||||
"@ohif/ui": "3.10.0-beta.78",
|
||||
"dcmjs": "*",
|
||||
"dicom-parser": "^1.8.9",
|
||||
"hammerjs": "^2.0.8",
|
||||
|
||||
@@ -3,6 +3,70 @@
|
||||
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-video
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [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-video
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [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-video
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [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-video
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [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-video
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [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-video
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [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-video
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [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-video
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [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-video
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ohif/extension-dicom-video",
|
||||
"version": "3.10.0-beta.70",
|
||||
"version": "3.10.0-beta.78",
|
||||
"description": "OHIF extension for video display",
|
||||
"author": "OHIF",
|
||||
"license": "MIT",
|
||||
@@ -30,8 +30,8 @@
|
||||
"test:unit:ci": "jest --ci --runInBand --collectCoverage --passWithNoTests"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@ohif/core": "3.10.0-beta.70",
|
||||
"@ohif/ui": "3.10.0-beta.70",
|
||||
"@ohif/core": "3.10.0-beta.78",
|
||||
"@ohif/ui": "3.10.0-beta.78",
|
||||
"dcmjs": "*",
|
||||
"dicom-parser": "^1.8.9",
|
||||
"hammerjs": "^2.0.8",
|
||||
|
||||
@@ -3,6 +3,76 @@
|
||||
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-measurement-tracking
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [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-measurement-tracking
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [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-measurement-tracking
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [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-measurement-tracking
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [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-measurement-tracking
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [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-measurement-tracking
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [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-measurement-tracking
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ohif/extension-measurement-tracking",
|
||||
"version": "3.10.0-beta.70",
|
||||
"version": "3.10.0-beta.78",
|
||||
"description": "Tracking features and functionality for basic image viewing",
|
||||
"author": "OHIF Core Team",
|
||||
"license": "MIT",
|
||||
@@ -34,10 +34,10 @@
|
||||
"peerDependencies": {
|
||||
"@cornerstonejs/core": "^2.17.2",
|
||||
"@cornerstonejs/tools": "^2.17.2",
|
||||
"@ohif/core": "3.10.0-beta.70",
|
||||
"@ohif/extension-cornerstone-dicom-sr": "3.10.0-beta.70",
|
||||
"@ohif/extension-default": "3.10.0-beta.70",
|
||||
"@ohif/ui": "3.10.0-beta.70",
|
||||
"@ohif/core": "3.10.0-beta.78",
|
||||
"@ohif/extension-cornerstone-dicom-sr": "3.10.0-beta.78",
|
||||
"@ohif/extension-default": "3.10.0-beta.78",
|
||||
"@ohif/ui": "3.10.0-beta.78",
|
||||
"classnames": "^2.3.2",
|
||||
"dcmjs": "*",
|
||||
"lodash.debounce": "^4.0.8",
|
||||
@@ -49,7 +49,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.20.13",
|
||||
"@ohif/ui": "3.10.0-beta.70",
|
||||
"@ohif/ui": "3.10.0-beta.78",
|
||||
"@xstate/react": "^3.2.2",
|
||||
"xstate": "^4.10.0"
|
||||
}
|
||||
|
||||
+4
-2
@@ -97,6 +97,7 @@ function TrackedMeasurementsContextProvider(
|
||||
commandsManager.runCommand('updateStoredPositionPresentation', {
|
||||
viewportId: activeViewportId,
|
||||
displaySetInstanceUID: referencedDisplaySetUID,
|
||||
referencedImageId: trackedMeasurement.referencedImageId,
|
||||
});
|
||||
|
||||
viewportGridService.setDisplaySetsForViewport({
|
||||
@@ -159,6 +160,7 @@ function TrackedMeasurementsContextProvider(
|
||||
promptHydrateStructuredReport: promptHydrateStructuredReport.bind(null, {
|
||||
servicesManager,
|
||||
extensionManager,
|
||||
commandsManager,
|
||||
appConfig,
|
||||
}),
|
||||
hydrateStructuredReport: hydrateStructuredReport.bind(null, {
|
||||
@@ -173,11 +175,11 @@ function TrackedMeasurementsContextProvider(
|
||||
});
|
||||
machineOptions.guards = Object.assign({}, machineOptions.guards, {
|
||||
isLabelOnMeasure: (ctx, evt, condMeta) => {
|
||||
const labelConfig = customizationService.get('measurementLabels');
|
||||
const labelConfig = customizationService.getCustomization('measurementLabels');
|
||||
return labelConfig?.labelOnMeasure;
|
||||
},
|
||||
isLabelOnMeasureAndShouldKillMachine: (ctx, evt, condMeta) => {
|
||||
const labelConfig = customizationService.get('measurementLabels');
|
||||
const labelConfig = customizationService.getCustomization('measurementLabels');
|
||||
return evt.data && evt.data.userResponse === RESPONSE.NO_NEVER && labelConfig?.labelOnMeasure;
|
||||
},
|
||||
});
|
||||
|
||||
+2
-2
@@ -1,7 +1,7 @@
|
||||
import { hydrateStructuredReport as baseHydrateStructuredReport } from '@ohif/extension-cornerstone-dicom-sr';
|
||||
|
||||
function hydrateStructuredReport(
|
||||
{ servicesManager, extensionManager, appConfig }: withAppTypes,
|
||||
{ servicesManager, extensionManager, commandsManager, appConfig }: withAppTypes,
|
||||
ctx,
|
||||
evt
|
||||
) {
|
||||
@@ -11,7 +11,7 @@ function hydrateStructuredReport(
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
const hydrationResult = baseHydrateStructuredReport(
|
||||
{ servicesManager, extensionManager, appConfig },
|
||||
{ servicesManager, extensionManager, commandsManager, appConfig },
|
||||
displaySetInstanceUID
|
||||
);
|
||||
|
||||
|
||||
+6
-2
@@ -11,7 +11,11 @@ const RESPONSE = {
|
||||
HYDRATE_REPORT: 5,
|
||||
};
|
||||
|
||||
function promptHydrateStructuredReport({ servicesManager, extensionManager, appConfig }, ctx, evt) {
|
||||
function promptHydrateStructuredReport(
|
||||
{ servicesManager, extensionManager, commandsManager, appConfig },
|
||||
ctx,
|
||||
evt
|
||||
) {
|
||||
const { uiViewportDialogService, displaySetService } = servicesManager.services;
|
||||
const { viewportId, displaySetInstanceUID } = evt;
|
||||
const srDisplaySet = displaySetService.getDisplaySetByUID(displaySetInstanceUID);
|
||||
@@ -26,7 +30,7 @@ function promptHydrateStructuredReport({ servicesManager, extensionManager, appC
|
||||
if (promptResult === RESPONSE.HYDRATE_REPORT) {
|
||||
console.warn('!! HYDRATING STRUCTURED REPORT');
|
||||
const hydrationResult = hydrateStructuredReport(
|
||||
{ servicesManager, extensionManager, appConfig },
|
||||
{ servicesManager, extensionManager, commandsManager, appConfig },
|
||||
displaySetInstanceUID
|
||||
);
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ import { Button, Icons } from '@ohif/ui-next';
|
||||
import { PanelMeasurement, StudySummaryFromMetadata } from '@ohif/extension-cornerstone';
|
||||
import { useTrackedMeasurements } from '../getContextModule';
|
||||
|
||||
const { filterAnd, filterPlanarMeasurement, filterAny, filterMeasurementsBySeriesUID } =
|
||||
const { filterAnd, filterPlanarMeasurement, filterMeasurementsBySeriesUID } =
|
||||
utils.MeasurementFilters;
|
||||
|
||||
function PanelMeasurementTableTracking({
|
||||
@@ -21,13 +21,7 @@ function PanelMeasurementTableTracking({
|
||||
? filterAnd(filterPlanarMeasurement, filterMeasurementsBySeriesUID(trackedSeries))
|
||||
: filterPlanarMeasurement;
|
||||
|
||||
const { disableEditing } = customizationService.getCustomization(
|
||||
'PanelMeasurement.disableEditing',
|
||||
{
|
||||
id: 'default.disableEditing',
|
||||
disableEditing: false,
|
||||
}
|
||||
);
|
||||
const disableEditing = customizationService.getCustomization('panelMeasurement.disableEditing');
|
||||
|
||||
return (
|
||||
<>
|
||||
|
||||
+6
-8
@@ -4,14 +4,15 @@ import { useTranslation } from 'react-i18next';
|
||||
import PropTypes from 'prop-types';
|
||||
import { utils } from '@ohif/core';
|
||||
import { useImageViewer, Dialog, ButtonEnums } from '@ohif/ui';
|
||||
import { useViewportGrid, DropdownMenu, DropdownMenuTrigger, Icons, Button } from '@ohif/ui-next';
|
||||
import { useViewportGrid } from '@ohif/ui-next';
|
||||
import { StudyBrowser } from '@ohif/ui-next';
|
||||
|
||||
import { useTrackedMeasurements } from '../../getContextModule';
|
||||
import { Separator } from '@ohif/ui-next';
|
||||
import { PanelStudyBrowserHeader, MoreDropdownMenu } from '@ohif/extension-default';
|
||||
import { defaultActionIcons, defaultViewPresets } from './constants';
|
||||
import { MoreDropdownMenu, PanelStudyBrowserHeader } from '@ohif/extension-default';
|
||||
import { defaultActionIcons } from './constants';
|
||||
const { formatDate, createStudyBrowserTabs } = utils;
|
||||
|
||||
const thumbnailNoImageModalities = [
|
||||
'SR',
|
||||
'SEG',
|
||||
@@ -46,10 +47,7 @@ export default function PanelStudyBrowserTracking({
|
||||
customizationService,
|
||||
} = servicesManager.services;
|
||||
const navigate = useNavigate();
|
||||
const { mode: studyMode } = customizationService.getCustomization('PanelStudyBrowser.studyMode', {
|
||||
id: 'default',
|
||||
mode: 'all',
|
||||
});
|
||||
const studyMode = customizationService.getCustomization('studyBrowser.studyMode');
|
||||
|
||||
const { t } = useTranslation('Common');
|
||||
|
||||
@@ -73,7 +71,7 @@ export default function PanelStudyBrowserTracking({
|
||||
const [jumpToDisplaySet, setJumpToDisplaySet] = useState(null);
|
||||
|
||||
const [viewPresets, setViewPresets] = useState(
|
||||
customizationService.getCustomization('studyBrowser.viewPresets')?.value || defaultViewPresets
|
||||
customizationService.getCustomization('studyBrowser.viewPresets')
|
||||
);
|
||||
|
||||
const [actionIcons, setActionIcons] = useState(defaultActionIcons);
|
||||
|
||||
@@ -3,6 +3,73 @@
|
||||
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-test
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [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-test
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [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-test
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [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-test
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [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-test
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [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-test
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [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-test
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [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-test
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ohif/extension-test",
|
||||
"version": "3.10.0-beta.70",
|
||||
"version": "3.10.0-beta.78",
|
||||
"description": "OHIF extension used inside e2e testing",
|
||||
"author": "OHIF",
|
||||
"license": "MIT",
|
||||
@@ -30,8 +30,8 @@
|
||||
"test:unit:ci": "jest --ci --runInBand --collectCoverage --passWithNoTests"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@ohif/core": "3.10.0-beta.70",
|
||||
"@ohif/ui": "3.10.0-beta.70",
|
||||
"@ohif/core": "3.10.0-beta.78",
|
||||
"@ohif/ui": "3.10.0-beta.78",
|
||||
"dcmjs": "0.29.11",
|
||||
"dicom-parser": "^1.8.9",
|
||||
"hammerjs": "^2.0.8",
|
||||
|
||||
@@ -16,81 +16,79 @@
|
||||
* See https://dicom.nema.org/medical/dicom/current/output/html/part16.html
|
||||
* for definitions of SCT and other code values.
|
||||
*/
|
||||
const codingValues = {
|
||||
id: 'codingValues',
|
||||
export default {
|
||||
codingValues: {
|
||||
// Sites
|
||||
'SCT:69536005': {
|
||||
text: 'Head',
|
||||
type: 'site',
|
||||
style: {
|
||||
color: 'red',
|
||||
},
|
||||
},
|
||||
'SCT:45048000': {
|
||||
text: 'Neck',
|
||||
type: 'site',
|
||||
style: {
|
||||
color: 'blue',
|
||||
},
|
||||
},
|
||||
'SCT:818981001': {
|
||||
text: 'Abdomen',
|
||||
type: 'site',
|
||||
style: {
|
||||
color: 'orange',
|
||||
},
|
||||
},
|
||||
'SCT:816092008': {
|
||||
text: 'Pelvis',
|
||||
type: 'site',
|
||||
style: {
|
||||
color: 'cyan',
|
||||
},
|
||||
},
|
||||
|
||||
// Sites
|
||||
'SCT:69536005': {
|
||||
text: 'Head',
|
||||
type: 'site',
|
||||
style: {
|
||||
color: 'red',
|
||||
// Findings
|
||||
'SCT:371861004': {
|
||||
text: 'Mild intimal coronary irregularities',
|
||||
style: {
|
||||
color: 'green',
|
||||
},
|
||||
},
|
||||
},
|
||||
'SCT:45048000': {
|
||||
text: 'Neck',
|
||||
type: 'site',
|
||||
style: {
|
||||
color: 'blue',
|
||||
'SCT:194983005': {
|
||||
text: 'Aortic insufficiency',
|
||||
style: {
|
||||
color: 'darkred',
|
||||
},
|
||||
},
|
||||
},
|
||||
'SCT:818981001': {
|
||||
text: 'Abdomen',
|
||||
type: 'site',
|
||||
style: {
|
||||
color: 'orange',
|
||||
'SCT:399232001': {
|
||||
text: '2-chamber',
|
||||
},
|
||||
},
|
||||
'SCT:816092008': {
|
||||
text: 'Pelvis',
|
||||
type: 'site',
|
||||
style: {
|
||||
color: 'cyan',
|
||||
'SCT:103340004': {
|
||||
text: 'SAX',
|
||||
},
|
||||
'SCT:91134007': {
|
||||
text: 'MV',
|
||||
},
|
||||
'SCT:122972007': {
|
||||
text: 'PV',
|
||||
},
|
||||
},
|
||||
|
||||
// Findings
|
||||
'SCT:371861004': {
|
||||
text: 'Mild intimal coronary irregularities',
|
||||
style: {
|
||||
color: 'green',
|
||||
// Orientations
|
||||
'SCT:24422004': {
|
||||
text: 'Axial',
|
||||
color: '#000000',
|
||||
type: 'orientation',
|
||||
},
|
||||
},
|
||||
'SCT:194983005': {
|
||||
text: 'Aortic insufficiency',
|
||||
style: {
|
||||
color: 'darkred',
|
||||
'SCT:81654009': {
|
||||
text: 'Coronal',
|
||||
color: '#000000',
|
||||
type: 'orientation',
|
||||
},
|
||||
'SCT:30730003': {
|
||||
text: 'Sagittal',
|
||||
color: '#000000',
|
||||
type: 'orientation',
|
||||
},
|
||||
},
|
||||
'SCT:399232001': {
|
||||
text: '2-chamber',
|
||||
},
|
||||
'SCT:103340004': {
|
||||
text: 'SAX',
|
||||
},
|
||||
'SCT:91134007': {
|
||||
text: 'MV',
|
||||
},
|
||||
'SCT:122972007': {
|
||||
text: 'PV',
|
||||
},
|
||||
|
||||
// Orientations
|
||||
'SCT:24422004': {
|
||||
text: 'Axial',
|
||||
color: '#000000',
|
||||
type: 'orientation',
|
||||
},
|
||||
'SCT:81654009': {
|
||||
text: 'Coronal',
|
||||
color: '#000000',
|
||||
type: 'orientation',
|
||||
},
|
||||
'SCT:30730003': {
|
||||
text: 'Sagittal',
|
||||
color: '#000000',
|
||||
type: 'orientation',
|
||||
},
|
||||
};
|
||||
|
||||
export default codingValues;
|
||||
Loaded 100 of 199 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user