Compare commits

..
Author SHA1 Message Date
ohif-bot 7a69c46dc0 chore(release): publish [skip ci]
- @ohif/extension-dicom-tag-browser@0.2.26
 - @ohif/extension-vtk@1.12.42
 - @ohif/ui@1.10.11
 - @ohif/viewer@4.12.51
2023-03-19 22:18:48 +00:00
Igor Octaviano 70367bad0b Merge pull request #3257 from OHIF/dependabot/npm_and_yarn/moment-2.29.4
chore(deps): bump moment from 2.24.0 to 2.29.4
2023-03-19 19:16:56 -03:00
Igor Octaviano cd347812bf Merge branch 'master' into dependabot/npm_and_yarn/moment-2.29.4 2023-03-19 19:01:02 -03:00
Igor Octaviano befd7d1b08 Merge pull request #3255 from OHIF/dependabot/npm_and_yarn/hapi/hoek-8.5.1
chore(deps): bump @hapi/hoek from 8.3.2 to 8.5.1
2023-03-19 19:00:54 -03:00
Igor Octaviano 618b0fc516 Merge branch 'master' into dependabot/npm_and_yarn/hapi/hoek-8.5.1 2023-03-19 18:48:52 -03:00
Igor Octaviano 693bfc5ac3 Merge branch 'master' into dependabot/npm_and_yarn/moment-2.29.4 2023-03-19 18:48:49 -03:00
Igor Octaviano c14daf6735 Merge pull request #3253 from OHIF/dependabot/npm_and_yarn/docs/latest/qs-6.2.4
chore(deps): bump qs from 6.2.3 to 6.2.4 in /docs/latest
2023-03-19 18:48:33 -03:00
Igor Octaviano 5e35fbb21d Merge branch 'master' into dependabot/npm_and_yarn/moment-2.29.4 2023-03-19 18:43:49 -03:00
Igor Octaviano efd02088f1 Merge branch 'master' into dependabot/npm_and_yarn/hapi/hoek-8.5.1 2023-03-19 18:41:28 -03:00
Igor Octaviano d7f2b3acaf Merge branch 'master' into dependabot/npm_and_yarn/docs/latest/qs-6.2.4 2023-03-19 18:35:48 -03:00
Igor Octaviano c609acaaad Merge pull request #2692 from OHIF/dependabot/npm_and_yarn/tar-4.4.19
chore(deps): bump tar from 4.4.13 to 4.4.19
2023-03-19 18:35:36 -03:00
Igor Octaviano 4db092f4bf Merge branch 'master' into dependabot/npm_and_yarn/tar-4.4.19 2023-03-19 18:23:22 -03:00
Igor Octaviano 994abf2a6a Merge branch 'master' into dependabot/npm_and_yarn/docs/latest/qs-6.2.4 2023-03-19 18:23:15 -03:00
Igor Octaviano c7db3fca24 Merge branch 'master' into dependabot/npm_and_yarn/hapi/hoek-8.5.1 2023-03-19 18:23:12 -03:00
Igor Octaviano ce8e00ea73 Merge branch 'master' into dependabot/npm_and_yarn/moment-2.29.4 2023-03-19 18:23:10 -03:00
Igor Octaviano 4d4356338c Merge pull request #3254 from OHIF/dependabot/npm_and_yarn/docs/latest/minimatch-3.0.8
chore(deps): bump minimatch from 3.0.4 to 3.0.8 in /docs/latest
2023-03-19 18:22:54 -03:00
dependabot[bot] 9d9e1aa4fe chore(deps): bump tar from 4.4.13 to 4.4.19
Bumps [tar](https://github.com/npm/node-tar) from 4.4.13 to 4.4.19.
- [Release notes](https://github.com/npm/node-tar/releases)
- [Changelog](https://github.com/npm/node-tar/blob/main/CHANGELOG.md)
- [Commits](https://github.com/npm/node-tar/compare/v4.4.13...v4.4.19)

---
updated-dependencies:
- dependency-name: tar
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-19 21:13:11 +00:00
dependabot[bot] 884224541b chore(deps): bump moment from 2.24.0 to 2.29.4
Bumps [moment](https://github.com/moment/moment) from 2.24.0 to 2.29.4.
- [Release notes](https://github.com/moment/moment/releases)
- [Changelog](https://github.com/moment/moment/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/moment/moment/compare/2.24.0...2.29.4)

---
updated-dependencies:
- dependency-name: moment
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-19 21:09:42 +00:00
dependabot[bot] 69a61698ae chore(deps): bump @hapi/hoek from 8.3.2 to 8.5.1
Bumps [@hapi/hoek](https://github.com/hapijs/hoek) from 8.3.2 to 8.5.1.
- [Release notes](https://github.com/hapijs/hoek/releases)
- [Commits](https://github.com/hapijs/hoek/compare/v8.3.2...v8.5.1)

---
updated-dependencies:
- dependency-name: "@hapi/hoek"
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-19 21:09:28 +00:00
dependabot[bot] 82b4f72408 chore(deps): bump minimatch from 3.0.4 to 3.0.8 in /docs/latest
Bumps [minimatch](https://github.com/isaacs/minimatch) from 3.0.4 to 3.0.8.
- [Release notes](https://github.com/isaacs/minimatch/releases)
- [Changelog](https://github.com/isaacs/minimatch/blob/main/changelog.md)
- [Commits](https://github.com/isaacs/minimatch/compare/v3.0.4...v3.0.8)

---
updated-dependencies:
- dependency-name: minimatch
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-19 21:08:49 +00:00
dependabot[bot] c87d933bbc chore(deps): bump qs from 6.2.3 to 6.2.4 in /docs/latest
Bumps [qs](https://github.com/ljharb/qs) from 6.2.3 to 6.2.4.
- [Release notes](https://github.com/ljharb/qs/releases)
- [Changelog](https://github.com/ljharb/qs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/ljharb/qs/compare/v6.2.3...v6.2.4)

---
updated-dependencies:
- dependency-name: qs
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-19 21:08:33 +00:00
Igor Octaviano b1745c5157 Merge pull request #3251 from OHIF/fix/dependabot-critical-items
Bump libs version to address dependabot [critical] security alerts
2023-03-19 18:06:18 -03:00
Igor Octaviano 096590a7e9 Bump libs version to address dependabot [critical] security alerts 2023-03-19 14:51:21 -03:00
Igor Octaviano 106b67d436 Merge pull request #3249 from OHIF/dependabot/npm_and_yarn/thenify-3.3.1
chore(deps): bump thenify from 3.3.0 to 3.3.1
2023-03-19 14:41:01 -03:00
dependabot[bot] cefe3c3cfb chore(deps): bump thenify from 3.3.0 to 3.3.1
Bumps [thenify](https://github.com/thenables/thenify) from 3.3.0 to 3.3.1.
- [Release notes](https://github.com/thenables/thenify/releases)
- [Changelog](https://github.com/thenables/thenify/blob/master/History.md)
- [Commits](https://github.com/thenables/thenify/compare/3.3.0...3.3.1)

---
updated-dependencies:
- dependency-name: thenify
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-19 17:23:49 +00:00
Igor Octaviano 2a2d5eefcb Merge pull request #3248 from OHIF/fix/dependabot-high-critical-items
dependabot security updates
2023-03-19 14:22:54 -03:00
Igor Octaviano 3f55e57056 Bump minimist version to fix prototype pollution reported by dependabot 2023-03-19 14:05:35 -03:00
ohif-bot 30515b8ab5 chore(release): publish [skip ci]
- @ohif/extension-dicom-segmentation@0.7.21
 - @ohif/viewer@4.12.50
2023-01-17 17:52:04 +00:00
Gitanjali 24bbf2b190 Re IDC #3077: Seg series thumbnail selection (#3078)
* fix: #3077 update seg tolerance popup and update seg thumbnail warning

* jump to first segment item image

* Shows warning message only once on onChange
2023-01-17 09:50:25 -08:00
Alireza cb9aa6a765 chore: update issue and PR templates (#3113)
* chore: update issue templates

* add template to PRs

* update for pr titles

* update

* update

* update description
2023-01-11 16:53:35 -05:00
ohif-bot 5d9e4c9b02 chore(release): publish [skip ci]
- @ohif/extension-dicom-segmentation@0.7.20
 - @ohif/viewer@4.12.49
2023-01-10 16:33:09 +00:00
Gitanjali dab095b6b5 Re IDC #3088: Fix seg toggle visibility logic (#3101) 2023-01-10 08:30:52 -08:00
ohif-bot cfa697aabc chore(release): publish [skip ci]
- @ohif/extension-cornerstone@2.12.16
 - @ohif/extension-dicom-html@1.3.24
 - @ohif/extension-dicom-rt@0.7.14
 - @ohif/extension-dicom-segmentation@0.7.19
 - @ohif/extension-dicom-tag-browser@0.2.25
 - @ohif/extension-vtk@1.12.41
 - @ohif/core@2.16.35
 - @ohif/viewer@4.12.48
2022-12-21 13:40:36 +00:00
Gitanjali 3350b1faa6 Re IDC #3047: update variable name for frame index (#3085) 2022-12-21 19:23:47 +05:45
ohif-bot 4ffb50c7e9 chore(release): publish [skip ci]
- @ohif/extension-dicom-segmentation@0.7.18
 - @ohif/viewer@4.12.47
2022-12-21 04:56:46 +00:00
Gitanjali 1d29554a91 Re IDC #3067: Show eye-icon when segment label name is long (#3073)
* fix: #2964 Reword message for segmentation error loading due to orientation tolerance

* fix: Show eye-icon when segment name is long

* update python version
2022-12-21 10:40:04 +05:45
ohif-bot b9d484fb2e chore(release): publish [skip ci]
- @ohif/extension-dicom-segmentation@0.7.17
 - @ohif/extension-vtk@1.12.40
 - @ohif/core@2.16.34
 - @ohif/viewer@4.12.46
2022-12-12 12:05:13 +00:00
Gitanjali 597ac11c4d fix: #2964 Reword message for segmentation error loading due to orientation tolerance (#3017) 2022-12-12 17:47:58 +05:45
ohif-bot 6007f340bf chore(release): publish [skip ci]
- @ohif/extension-vtk@1.12.39
 - @ohif/core@2.16.33
 - @ohif/viewer@4.12.45
2022-11-12 16:03:12 +00:00
Pauline Ribeyre 44738078db fix: handle missing ReferencedInstanceSequence attribute (#2786) 2022-11-12 11:01:21 -05:00
ohif-bot 686fe7d931 chore(release): publish [skip ci]
- @ohif/extension-vtk@1.12.38
 - @ohif/core@2.16.32
 - @ohif/viewer@4.12.44
2022-11-02 21:22:01 +00:00
Gitanjali 0b8facbea6 remove-unsed-code-from-SR-parsing (#2997) 2022-11-02 15:20:20 -06:00
ohif-bot 0f89aa32f9 chore(release): publish [skip ci]
- @ohif/extension-dicom-segmentation@0.7.16
 - @ohif/extension-vtk@1.12.37
 - @ohif/core@2.16.31
 - @ohif/viewer@4.12.43
2022-10-28 17:55:54 +00:00
Gitanjali 545161d5e8 fix: #2964 Update message for segmentation error loading due to orientation tolerance (#2982) 2022-10-28 11:54:19 -06:00
ohif-bot eaa423c64e chore(release): publish [skip ci]
- @ohif/extension-vtk@1.12.36
 - @ohif/core@2.16.30
 - @ohif/viewer@4.12.42
2022-10-25 14:09:04 +00:00
Gitanjali f7db74a843 fix: 2965 Correct Parsing Logic for Qualitative Instance Level SR (#2972)
* fix: 2965 Correct Parsing Logic for Qualitative Instance Level SR

* fix: 2965 Correct Parsing Logic for Qualitative Instance Level SR

* fix: 2965 Correct Parsing Logic for Qualitative Instance Level SR
2022-10-25 10:06:59 -04:00
ohif-bot 7aba01f534 chore(release): publish [skip ci]
- @ohif/extension-vtk@1.12.35
 - @ohif/viewer@4.12.41
2022-09-26 14:42:01 +00:00
GitanjaliChhetri c5ebeaa127 Re IDC #2847: Fix 2d MPR rendering issue for the sagittal view (#2960) 2022-09-26 08:39:55 -06:00
ohif-bot d7e1d2c975 chore(release): publish [skip ci]
- @ohif/extension-cornerstone@2.12.15
 - @ohif/extension-vtk@1.12.34
 - @ohif/core@2.16.29
 - @ohif/viewer@4.12.40
2022-09-20 11:26:05 +00:00
Davide Punzo eb7eb56d7e Re IDC #2934: update cornerstoneWADOImageLoader to v 4.2.1 (#2944) 2022-09-20 13:24:17 +02:00
ohif-bot c5ee092bf2 chore(release): publish [skip ci]
- @ohif/extension-dicom-segmentation@0.7.15
 - @ohif/extension-vtk@1.12.33
 - @ohif/core@2.16.28
 - @ohif/viewer@4.12.39
2022-09-19 10:32:07 +00:00
Davide Punzo e2f4f95222 Re IDC #2935: fix parsing of Instance-level qualitative annotations (#2940) 2022-09-19 12:29:28 +02:00
ohif-bot 4546ede9bb chore(release): publish [skip ci]
- @ohif/extension-dicom-segmentation@0.7.14
 - @ohif/viewer@4.12.38
2022-09-12 12:24:25 +00:00
Davide Punzo e0fb439e98 Fix IDC Re #2918: Runtime tolerance for SEGs loading (#2924) 2022-09-12 14:22:32 +02:00
ohif-bot ebbc9e0d6d chore(release): publish [skip ci]
- @ohif/extension-vtk@1.12.32
 - @ohif/core@2.16.27
 - @ohif/viewer@4.12.37
2022-09-12 08:27:33 +00:00
Davide Punzo 47a6130fd5 Re IDC #2919: fix popup notifications behavior (#2923) 2022-09-12 10:25:19 +02:00
ohif-bot 80dfdcc37c chore(release): publish [skip ci]
- @ohif/viewer@4.12.36
2022-09-08 14:48:41 +00:00
Doug Horner d74ad370e0 fix: hotkey page up/down did not work (#2910) 2022-09-08 10:46:26 -04:00
ohif-bot ddfde9279e chore(release): publish [skip ci]
- @ohif/extension-vtk@1.12.31
 - @ohif/core@2.16.26
 - @ohif/viewer@4.12.35
2022-09-02 13:49:07 +00:00
Davide Punzo aaab6d2622 Re IDC #2849: raise error if dicom request is not conforming with the UID (DICOM UI VR) character repertoire. (#2908) 2022-09-02 15:47:28 +02:00
ohif-bot d2921083e7 chore(release): publish [skip ci]
- @ohif/extension-cornerstone@2.12.14
 - @ohif/extension-dicom-html@1.3.23
 - @ohif/extension-dicom-rt@0.7.13
 - @ohif/extension-dicom-segmentation@0.7.13
 - @ohif/extension-dicom-tag-browser@0.2.24
 - @ohif/extension-vtk@1.12.30
 - @ohif/core@2.16.25
 - @ohif/viewer@4.12.34
2022-09-01 18:14:46 +00:00
Davide Punzo a6338ea266 Re IDC #2869: update dcmjs for fixing eps in nearly equal condition (#2906) 2022-09-01 20:12:30 +02:00
ohif-bot fe9551b9b1 chore(release): publish [skip ci]
- @ohif/extension-dicom-rt@0.7.12
 - @ohif/extension-dicom-segmentation@0.7.12
 - @ohif/extension-vtk@1.12.29
 - @ohif/core@2.16.24
 - @ohif/viewer@4.12.33
2022-08-31 12:59:14 +00:00
Davide Punzo ef60156a47 Fix minor issues IDC (#2903) 2022-08-31 14:57:14 +02:00
ohif-bot 850de2903a chore(release): publish [skip ci]
- @ohif/viewer@4.12.32
2022-08-25 09:50:05 +00:00
Davide Punzo f26ed5539b IDC2859 (#2891)
* Re #2859 IDC: disable jump to for measurements in MPR mode
2022-08-25 11:48:20 +02:00
ohif-bot 21aeaa63c7 chore(release): publish [skip ci]
- @ohif/extension-vtk@1.12.28
 - @ohif/core@2.16.23
 - @ohif/ui@1.10.10
 - @ohif/viewer@4.12.31
2022-08-24 10:38:46 +00:00
Davide Punzo 2ac0d3f017 Re #2852 IDC: fix parsing of qualitative slice annotation (#2888) 2022-08-24 12:37:21 +02:00
ohif-bot efdbe8e7b4 chore(release): publish [skip ci]
- @ohif/extension-cornerstone@2.12.13
 - @ohif/extension-debugging@0.3.3
 - @ohif/extension-dicom-html@1.3.22
 - @ohif/extension-vtk@1.12.27
 - @ohif/core@2.16.22
 - @ohif/viewer@4.12.30
2022-06-30 10:07:05 +00:00
Davide Punzo 67b70eaa98 IDC2797: add linking and report UI for SR displaySets (#2834) 2022-06-30 12:05:47 +02:00
ohif-bot 5150ed9427 chore(release): publish [skip ci]
- @ohif/extension-cornerstone@2.12.12
 - @ohif/extension-lesion-tracker@0.2.2
 - @ohif/extension-vtk@1.12.26
 - @ohif/core@2.16.21
 - @ohif/ui@1.10.9
 - @ohif/viewer@4.12.29
2022-06-29 02:26:24 +00:00
Davide Punzo 1bcb0acf9f IDC2797: improving UI for SR qualitative measurements and bug fixes (#2832) 2022-06-29 04:24:35 +02:00
ohif-bot 5d6cf2a609 chore(release): publish [skip ci]
- @ohif/extension-vtk@1.12.25
 - @ohif/core@2.16.20
 - @ohif/viewer@4.12.28
2022-06-28 11:18:54 +00:00
Davide Punzo 9f813e0ea0 fix: Re IDC2797, fix double parsing of SR qualitative annotations (#2830) 2022-06-28 13:17:16 +02:00
ohif-bot 49de44ba34 chore(release): publish [skip ci]
- @ohif/extension-cornerstone@2.12.11
 - @ohif/extension-vtk@1.12.24
 - @ohif/core@2.16.19
 - @ohif/viewer@4.12.27
2022-06-14 12:14:35 +00:00
Davide Punzo b04e186274 feat IDC #2797: add support for SR qualitative annotation per instance (#2822) 2022-06-14 14:12:27 +02:00
ohif-bot c59d66412f chore(release): publish [skip ci]
- @ohif/extension-vtk@1.12.23
 - @ohif/core@2.16.18
 - @ohif/viewer@4.12.26
2022-04-22 08:54:26 +00:00
Davide Punzo f8b4ccbb59 IDC: Fix undefined return in getDerivedDatasets (#2784) 2022-04-22 10:53:01 +02:00
ohif-bot 5426773ffc chore(release): publish [skip ci]
- @ohif/extension-dicom-tag-browser@0.2.23
 - @ohif/extension-vtk@1.12.22
 - @ohif/core@2.16.17
 - @ohif/ui@1.10.8
 - @ohif/viewer@4.12.25
2022-04-06 16:24:23 +00:00
Davide Punzo a507a00f59 Fix thumbnail loading bar (#2772) 2022-04-06 18:23:02 +02:00
Davide Punzo cedeb756c0 Re IDC #2762: fix thumbnail series type for unsupported SOPClassUID (#2770) 2022-04-06 17:10:00 +02:00
ohif-bot 64385485b6 chore(release): publish [skip ci]
- @ohif/extension-cornerstone@2.12.10
 - @ohif/extension-dicom-html@1.3.21
 - @ohif/extension-dicom-rt@0.7.11
 - @ohif/extension-dicom-segmentation@0.7.11
 - @ohif/extension-dicom-tag-browser@0.2.22
 - @ohif/extension-vtk@1.12.21
 - @ohif/core@2.16.16
 - @ohif/viewer@4.12.24
2022-04-05 07:40:48 +00:00
Davide Punzo 32828d9a6e Re IDC #2765: fix loading of segmentations at first startup (#2768)
Re IDC #2761: fix loading of segmentations

update dcmjs to 0.19.9
2022-04-05 09:39:22 +02:00
ohif-bot b94d4782d1 chore(release): publish [skip ci]
- @ohif/extension-cornerstone@2.12.9
 - @ohif/extension-dicom-html@1.3.20
 - @ohif/extension-dicom-rt@0.7.10
 - @ohif/extension-dicom-segmentation@0.7.10
 - @ohif/extension-dicom-tag-browser@0.2.21
 - @ohif/extension-vtk@1.12.20
 - @ohif/core@2.16.15
 - @ohif/viewer@4.12.23
2022-03-25 11:17:54 +00:00
Igor Octaviano 36b47ce3a3 Merge pull request #2750 from OHIF/igoroctaviano/dcmjs-0.19.8
Update dependency: dcmjs@0.19.8
2022-03-25 08:16:36 -03:00
igoroctaviano fe57c00577 Update dependency: dcmjs@0.19.8
dcmjs
  * @ohif/core: 0.19.7 → 0.19.8
  * @ohif/extension-cornerstone: 0.19.7 → 0.19.8
  * @ohif/extension-dicom-html: 0.19.7 → 0.19.8
  * @ohif/extension-dicom-rt: 0.19.7 → 0.19.8
  * @ohif/extension-dicom-segmentation: 0.19.7 → 0.19.8
  * @ohif/extension-dicom-tag-browser: 0.19.7 → 0.19.8
  * @ohif/extension-vtk: 0.19.7 → 0.19.8
  * @ohif/viewer: 0.19.7 → 0.19.8
2022-03-25 07:45:50 -03:00
ohif-bot 21a3bc2ded chore(release): publish [skip ci]
- @ohif/extension-cornerstone@2.12.8
 - @ohif/extension-dicom-html@1.3.19
 - @ohif/extension-dicom-rt@0.7.9
 - @ohif/extension-dicom-segmentation@0.7.9
 - @ohif/extension-dicom-tag-browser@0.2.20
 - @ohif/extension-vtk@1.12.19
 - @ohif/core@2.16.14
 - @ohif/viewer@4.12.22
2022-03-14 17:19:00 +00:00
Davide Punzo b6b09f22fc IDC2733: update dcmjs to version 0.19.7 (#2745) 2022-03-14 18:17:28 +01:00
ohif-bot 64a4d60e52 chore(release): publish [skip ci]
- @ohif/extension-vtk@1.12.18
 - @ohif/core@2.16.13
 - @ohif/viewer@4.12.21
2022-03-14 16:26:55 +00:00
0ba796c73c fix: Update fetchPaletteColorLookupTableData: LUT Entries shall be 0 if the table entries value is 2^16 (#2395)
Opened issue https://github.com/OHIF/Viewers/issues/2366. 

Following http://dicom.nema.org/medical/Dicom/2018d/output/chtml/part03/sect_C.7.6.3.html#sect_C.7.6.3.1.5, LUT Entries shall be 0 if the table entries value is 2^16.

If numLutEntries is 0, there is no for loop and return empty lut array.

Solution:

const numLutEntries = lutDescriptor[0] ? lutDescriptor[0] : 65536;

This is often used by Philips Ultrasound equipments.

Co-authored-by: Alireza <ar.sedghi@gmail.com>
Co-authored-by: Erik Ziegler <erik.sweed@gmail.com>
2022-03-14 17:25:19 +01:00
ohif-bot cb7fafb1d6 chore(release): publish [skip ci]
- @ohif/extension-vtk@1.12.17
 - @ohif/ui@1.10.7
 - @ohif/viewer@4.12.20
2022-03-14 16:20:31 +00:00
ladeirarodolfo 7164d1a654 fix: remove docz + node version fix on docker (#2743)
* fix: docz uses too outdated packages and current documentation hasnt being updated oftenly. removing it

* fix: node docker version to prevent node req "^12.13.0 || ^14.15.0 || >=16" issue
2022-03-14 17:18:26 +01:00
149 changed files with 3277 additions and 8476 deletions

No files matched your search

+9 -13
View File
@@ -27,7 +27,7 @@ executors:
- image: 'cypress/browsers:node14.15.0-chrome86-ff82'
defaults: &defaults
docker:
- image: cimg/node:14.18
- image: cimg/node:14.19
environment:
TERM: xterm # Enable colors in term
QUICK_BUILD: true
@@ -347,9 +347,8 @@ workflows:
store_artifacts: true
working_directory: platform/viewer
build:
git submodule update --init &&
npx cross-env QUICK_BUILD=true APP_CONFIG=config/e2e.js
yarn run build
git submodule update --init && npx cross-env QUICK_BUILD=true
APP_CONFIG=config/e2e.js yarn run build
start: yarn run test:e2e:serve
spec: 'cypress/integration/common/**/*,cypress/integration/pwa/**/*'
wait-on: 'http://localhost:3000'
@@ -376,9 +375,8 @@ workflows:
store_artifacts: true
working_directory: platform/viewer
build:
git submodule update --init &&
npx cross-env QUICK_BUILD=true APP_CONFIG=config/e2e.js
yarn run build:package
git submodule update --init && npx cross-env QUICK_BUILD=true
APP_CONFIG=config/e2e.js yarn run build:package
start: yarn run test:e2e:serve
spec: 'cypress/integration/common/**/*,cypress/integration/script-tag/**/*'
wait-on: 'http://localhost:3000'
@@ -410,9 +408,8 @@ workflows:
store_artifacts: false
working_directory: platform/viewer
build:
git submodule update --init &&
npx cross-env QUICK_BUILD=true APP_CONFIG=config/e2e.js
yarn run build
git submodule update --init && npx cross-env QUICK_BUILD=true
APP_CONFIG=config/e2e.js yarn run build
# start server --> verify running --> percy + chrome + cypress
command: yarn run test:e2e:dist
cache-key: 'yarn-packages-{{ checksum "yarn.lock" }}'
@@ -490,9 +487,8 @@ workflows:
store_artifacts: false
working_directory: platform/viewer
build:
git submodule update --init &&
npx cross-env QUICK_BUILD=true APP_CONFIG=config/e2e.js
yarn run build
git submodule update --init && npx cross-env QUICK_BUILD=true
APP_CONFIG=config/e2e.js yarn run build
# start server --> verify running --> percy + chrome + cypress
command: yarn run test:e2e:dist
cache-key: 'yarn-packages-{{ checksum "yarn.lock" }}'
+16 -9
View File
@@ -2,23 +2,21 @@
name: "\U0001F41B Bug report"
about: Create a report to help us improve
title: ''
labels: 'Community: Report :bug:, Awaiting Reproduction, Triage :white_flag:'
labels: 'Community: Report :bug:, Awaiting Reproduction'
assignees: ''
---
> **Before Creating an issue**
>
> - Are you running the latest version?
> - Are you reporting to the correct repository?
> - Did you search existing issues?
## Bug Report
<!-- ⚠️⚠️ Do Not Delete This! bug_report_template ⚠️⚠️ -->
<!-- Please read our Rules of Conduct: https://github.com/OHIF/Viewers/blob/master/CODE_OF_CONDUCT.md -->
<!-- 🕮 Read our guide about our process: https://v3-docs.ohif.org/development/our-process -->
<!-- 🔎 Search existing issues to avoid creating duplicates. -->
<!-- 🧪 Test using the latest version -->
### Describe the Bug
_A clear and concise description of what the bug is._
### What steps can we follow to reproduce the bug?
### Steps to Reproduce:
1. First step
2. Second step
@@ -28,6 +26,15 @@ _A clear and concise description of what the bug is._
Please use code blocks to show formatted errors or code snippets
```
### The current behavior
_A clear and concise description of what happens instead of the expected
behavior._
### The expected behavior
_A clear and concise description of what you expected to happen._
> :warning: Reports we cannot reproduce are at risk of being marked stale and
> closed. The more information you can provide, the more likely we are to look
> into and address your issue.
+14 -5
View File
@@ -2,19 +2,28 @@
name: "\U0001F680 Feature request"
about: Suggest an idea for this project
title: ''
labels: 'Community: Request :hand:, Triage :white_flag:'
labels: 'Community: Request :hand:'
assignees: ''
---
> :hand: Many people requests features. Tell us why yours is important to the
<!-- ⚠️⚠️ Do Not Delete This! feature_request_template ⚠️⚠️ -->
<!-- Please read our Rules of Conduct: https://github.com/OHIF/Viewers/blob/master/CODE_OF_CONDUCT.md -->
<!-- :hand: Many people requests features. Tell us why yours is important to the
> community. How does it add value? Why _this feature_?
>
> Is your request very specific to your needs? Consider
> [contributing it](https://docs.ohif.org/contributing.html) yourself! Or reach
> out to a community member that offers
> [contributing it](https://v3-docs.ohif.org/development/contributing) yourself!
> Or reach out to a community member that offers
> [consulting services](https://docs.ohif.org/help.html#paid--commercial).
-->
## Request
### Request
<!--
Please include as much detail as possible including possibly mock up screen shots, workflow or logic flow diagrams etc.
Discuss if and how the requested feature interacts with existing features
-->
**What feature or change would you like to see made?**
+86 -9
View File
@@ -1,14 +1,91 @@
### PR Checklist
- [ ] Brief description of changes
- [ ] Links to any relevant issues
- [ ] Required status checks are passing
- [ ] User cases if changes impact the user's experience
- [ ] `@mention` a maintainer to request a review
<!-- Do Not Delete This! pr_template -->
<!-- Please read our Rules of Conduct: https://github.com/OHIF/Viewers/blob/master/CODE_OF_CONDUCT.md -->
<!-- 🕮 Read our guide about our Contributing Guide here https://v3-docs.ohif.org/development/contributing -->
<!-- :hand: Thank you for starting this amazing contribution! -->
<!--
Links
-->
⚠️⚠️ Please make sure the checklist section below is complete before submitting your PR.
To complete the checklist, add an 'x' to each item: [] -> [x]
(PRs that do not have all the checkboxes marked will not be approved)
-->
### Context
<!--
Provide a clear explanation of the reasoning behind this change, such as:
- A link to the issue being addressed, using the format "Fixes #ISSUE_NUMBER"
- An image showing the issue or problem being addressed (if not already in the issue)
- Error logs or callStacks to help with the understanding of the problem (if not already in the issue)
-->
### Changes & Results
<!--
List all the changes that have been done, such as:
- Add new components
- Remove old components
- Update dependencies
What are the effects of this change?
- Before vs After
- Screenshots / GIFs / Videos
-->
### Testing
<!--
Describe how we can test your changes.
- open a URL
- visit a page
- click on a button
- etc.
-->
### Checklist
#### PR
<!--
https://semantic-release.gitbook.io/semantic-release/#how-does-it-work
Examples:
Please note the letter casing in the provided examples (upper or lower).
- feat(MeasurementService): add ...
- fix(Toolbar): fix ...
- docs(Readme): update ...
- style(Whitespace): fix ...
- refactor(ExtensionManager): ...
- test(HangingProtocol): Add test ...
- chore(git): update ...
- perf(VolumeLoader): ...
You don't need to have each commit within the Pull Request follow the rule,
but the PR title must comply with it, as it will be used as the commit message
after the commits are squashed.
-->
- [] My Pull Request title is descriptive, accurate and follows the
semantic-release format and guidelines.
#### Code
- [] My code has been well-documented (function documentation, inline comments,
etc.)
#### Public Documentation Updates
<!-- https://v3-docs.ohif.org/ -->
- [] The documentation page has been updated as necessary for any public API
additions or removals.
#### Tested Environment
- [] "OS: <!--[e.g. Windows 10, macOS 10.15.4]"-->
- [] "Node version: <!--[e.g. 16.14.0]"-->
- [] "Browser:
<!--[e.g. Chrome 83.0.4103.116, Firefox 77.0.1, Safari 13.1.1]"-->
<!-- prettier-ignore-start -->
[blog]: https://circleci.com/blog/triggering-trusted-ci-jobs-on-untrusted-forks/
+3 -9
View File
@@ -4,23 +4,17 @@
# Number of days of inactivity before an issue becomes stale
daysUntilStale: 180
# Number of days of inactivity before a stale issue is closed
daysUntilClose: 9000
daysUntilClose: 60
# Issues with these labels will never be considered stale
exemptLabels:
- 'Story :raised_hands:'
- 'Bug: Verified :bug:'
- 'Task: CI/Tooling :robot:'
- 'Task: Docs 📖'
- 'Task: Docs :book:'
- 'Task: Refactor :hammer_and_wrench:'
- 'Task: Tests :microscope:'
- 'PR: Awaiting Review 👀'
- 'Triage :white_flag:'
- 'Extension: Discussion'
- 'Announcement 🎉'
- 'IDC:priority'
- 'IDC:candidate'
- 'IDC:collaboration'
- 'Community: Request :hand:'
- 'Community: Report :bug:'
# Label to use when marking an issue as stale
staleLabel: 'Stale :baguette_bread:'
# Comment to post when marking an issue as stale. Set to `false` to disable
-2
View File
@@ -8,7 +8,6 @@ docs/_book
src/version.js
junit.xml
coverage/
.docz/
*.js.map
.yarn
platform/docs/.docusaurus
@@ -38,4 +37,3 @@ screenshots/
# Locize settings
.locize
-10
View File
@@ -22,16 +22,6 @@ mv platform/viewer/dist/* .netlify/www/pwa -v
# Build && Move script output
# yarn run build:package
# Build && Move Docz Output
# Using local yarn install to prevent Gatsby from needing to access
# node_modules above the platform/ui folder
cd platform/ui
yarn install
yarn run build
cd ../..
mkdir -p ./.netlify/www/ui
mv platform/ui/.docz/dist/* .netlify/www/ui -v
# Cache all of the node_module dependencies in
# extensions, modules, and platform packages
yarn run lerna:cache
+2 -2
View File
@@ -21,7 +21,7 @@
# Stage 1: Build the application
# docker build -t ohif/viewer:latest .
FROM node:15.13.0-slim as builder
FROM node:14-slim as builder
RUN mkdir /usr/src/app
WORKDIR /usr/src/app
@@ -42,7 +42,7 @@ COPY yarn.lock /usr/src/app/yarn.lock
RUN apt-get update && apt-get install -y python make g++
# Run the install before copying the rest of the files
RUN yarn config set workspaces-experimental true
RUN yarn install
RUN yarn install --verbose
ENV PATH /usr/src/app/node_modules/.bin:$PATH
ENV QUICK_BUILD true
+5
View File
@@ -40,5 +40,10 @@
},
"devDependencies": {
"gitbook-cli": "^2.3.2"
},
"resolutions": {
"underscore": "1.12.1",
"json-schema": "0.4.0",
"minimist": "1.2.8"
}
}
+31 -34
View File
@@ -1481,10 +1481,10 @@ json-schema-traverse@^0.4.1:
resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660"
integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==
json-schema@0.2.3:
version "0.2.3"
resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13"
integrity sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=
json-schema@0.2.3, json-schema@0.4.0:
version "0.4.0"
resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.4.0.tgz#f7de4cf6efab838ebaeb3236474cbba5a1930ab5"
integrity sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==
json-stable-stringify@^1.0.1:
version "1.0.1"
@@ -1729,27 +1729,24 @@ mime-types@^2.1.11, mime-types@^2.1.12, mime-types@~2.1.19, mime-types@~2.1.7:
dependencies:
mime-db "~1.38.0"
minimatch@^3.0.0, minimatch@^3.0.2, minimatch@^3.0.4, minimatch@~3.0.3:
version "3.0.4"
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083"
integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==
minimatch@^3.0.0, minimatch@^3.0.2, minimatch@^3.0.4:
version "3.1.2"
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b"
integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==
dependencies:
brace-expansion "^1.1.7"
minimist@0.0.8:
version "0.0.8"
resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d"
integrity sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=
minimatch@~3.0.3:
version "3.0.8"
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.8.tgz#5e6a59bd11e2ab0de1cfb843eb2d82e546c321c1"
integrity sha512-6FsRAQsxQ61mw+qP1ZzbL9Bc78x2p5OqNgNpnoAFLTrX8n5Kxph0CsnhmKKNXTWjXqU5L0pGPR7hYk+XWZr60Q==
dependencies:
brace-expansion "^1.1.7"
minimist@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284"
integrity sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=
minimist@~0.0.1:
version "0.0.10"
resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.10.tgz#de3f98543dbf96082be48ad1a0c7cda836301dcf"
integrity sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8=
minimist@0.0.8, minimist@1.2.8, minimist@^1.2.0, minimist@~0.0.1:
version "1.2.8"
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c"
integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==
mississippi@^1.2.0, mississippi@^1.3.0, mississippi@~1.3.0:
version "1.3.1"
@@ -2491,19 +2488,19 @@ q@1.5.0:
integrity sha1-3QG6ydBtMObyGa7LglPunr3DCPE=
qs@~6.2.0:
version "6.2.3"
resolved "https://registry.yarnpkg.com/qs/-/qs-6.2.3.tgz#1cfcb25c10a9b2b483053ff39f5dfc9233908cfe"
integrity sha1-HPyyXBCpsrSDBT/zn138kjOQjP4=
version "6.2.4"
resolved "https://registry.yarnpkg.com/qs/-/qs-6.2.4.tgz#d90821bb8537cecc140e6c34f54ec76e54b39b22"
integrity sha512-E57gmgKXqDda+qWTkUJgIwgJICK7zgMfqZZopTRKZ6mY9gzLlmJN9EpXNnDrTxXFlOM/a+I28kJkF/60rqgnYw==
qs@~6.4.0:
version "6.4.0"
resolved "https://registry.yarnpkg.com/qs/-/qs-6.4.0.tgz#13e26d28ad6b0ffaa91312cd3bf708ed351e7233"
integrity sha1-E+JtKK1rD/qpExLNO/cI7TUecjM=
version "6.4.1"
resolved "https://registry.yarnpkg.com/qs/-/qs-6.4.1.tgz#2bad97710a5b661c366b378b1e3a44a592ff45e6"
integrity sha512-LQy1Q1fcva/UsnP/6Iaa4lVeM49WiOitu2T4hZCyA/elLKu37L99qcBJk4VCCk+rdLvnMzfKyiN3SZTqdAZGSQ==
qs@~6.5.2:
version "6.5.2"
resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36"
integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==
version "6.5.3"
resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.3.tgz#3aeeffc91967ef6e35c0e488ef46fb296ab76aad"
integrity sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==
rc@^1.0.1, rc@^1.1.6:
version "1.2.8"
@@ -3175,10 +3172,10 @@ umask@~1.1.0:
resolved "https://registry.yarnpkg.com/umask/-/umask-1.1.0.tgz#f29cebf01df517912bb58ff9c4e50fde8e33320d"
integrity sha1-8pzr8B31F5ErtY/5xOUP3o4zMg0=
underscore@^1.7.0:
version "1.9.1"
resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.9.1.tgz#06dce34a0e68a7babc29b365b8e74b8925203961"
integrity sha512-5/4etnCkd9c8gwgowi5/om/mYO5ajCaOgdzj/oW+0eQV9WxKBDZw5+ycmKmeaTXjInS/W0BzpGLo2xR2aBwZdg==
underscore@1.12.1, underscore@^1.7.0:
version "1.12.1"
resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.12.1.tgz#7bb8cc9b3d397e201cf8553336d262544ead829e"
integrity sha512-hEQt0+ZLDVUMhebKxL4x1BTtDY7bavVofhZ9KZ4aI26X9SRaE+Y3m83XUL1UP2jn8ynjndwCCpEHdUG+9pP1Tw==
unique-filename@^1.1.0, unique-filename@~1.1.0:
version "1.1.1"
+72
View File
@@ -3,6 +3,78 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [2.12.16](https://github.com/OHIF/Viewers/compare/@ohif/extension-cornerstone@2.12.15...@ohif/extension-cornerstone@2.12.16) (2022-12-21)
**Note:** Version bump only for package @ohif/extension-cornerstone
## [2.12.15](https://github.com/OHIF/Viewers/compare/@ohif/extension-cornerstone@2.12.14...@ohif/extension-cornerstone@2.12.15) (2022-09-20)
**Note:** Version bump only for package @ohif/extension-cornerstone
## [2.12.14](https://github.com/OHIF/Viewers/compare/@ohif/extension-cornerstone@2.12.13...@ohif/extension-cornerstone@2.12.14) (2022-09-01)
**Note:** Version bump only for package @ohif/extension-cornerstone
## [2.12.13](https://github.com/OHIF/Viewers/compare/@ohif/extension-cornerstone@2.12.12...@ohif/extension-cornerstone@2.12.13) (2022-06-30)
**Note:** Version bump only for package @ohif/extension-cornerstone
## [2.12.12](https://github.com/OHIF/Viewers/compare/@ohif/extension-cornerstone@2.12.11...@ohif/extension-cornerstone@2.12.12) (2022-06-29)
**Note:** Version bump only for package @ohif/extension-cornerstone
## [2.12.11](https://github.com/OHIF/Viewers/compare/@ohif/extension-cornerstone@2.12.10...@ohif/extension-cornerstone@2.12.11) (2022-06-14)
**Note:** Version bump only for package @ohif/extension-cornerstone
## [2.12.10](https://github.com/OHIF/Viewers/compare/@ohif/extension-cornerstone@2.12.9...@ohif/extension-cornerstone@2.12.10) (2022-04-05)
**Note:** Version bump only for package @ohif/extension-cornerstone
## [2.12.9](https://github.com/OHIF/Viewers/compare/@ohif/extension-cornerstone@2.12.8...@ohif/extension-cornerstone@2.12.9) (2022-03-25)
**Note:** Version bump only for package @ohif/extension-cornerstone
## [2.12.8](https://github.com/OHIF/Viewers/compare/@ohif/extension-cornerstone@2.12.7...@ohif/extension-cornerstone@2.12.8) (2022-03-14)
**Note:** Version bump only for package @ohif/extension-cornerstone
## [2.12.7](https://github.com/OHIF/Viewers/compare/@ohif/extension-cornerstone@2.12.6...@ohif/extension-cornerstone@2.12.7) (2022-02-03)
**Note:** Version bump only for package @ohif/extension-cornerstone
+5 -4
View File
@@ -1,6 +1,6 @@
{
"name": "@ohif/extension-cornerstone",
"version": "2.12.7",
"version": "2.12.16",
"description": "OHIF extension for Cornerstone",
"author": "OHIF",
"license": "MIT",
@@ -35,8 +35,8 @@
"cornerstone-core": "^2.6.1",
"cornerstone-math": "^0.1.9",
"cornerstone-tools": "^6.0.6",
"cornerstone-wado-image-loader": "^4.1.0",
"dcmjs": "0.19.4",
"cornerstone-wado-image-loader": "^4.2.1",
"dcmjs": "0.29.3",
"dicom-parser": "^1.8.11",
"hammerjs": "^2.0.8",
"prop-types": "^15.6.2",
@@ -44,7 +44,8 @@
"react-dom": "^16.8.6",
"react-redux": "^6.0.0",
"react-resize-detector": "^3.4.0",
"redux": "^4.0.1"
"redux": "^4.0.1",
"styled-components": "^5.3.5"
},
"dependencies": {
"@babel/runtime": "^7.5.5",
@@ -237,11 +237,21 @@ class OHIFCornerstoneViewport extends Component {
}
};
const warningsOverlay = props => {
const overlay = props => {
const displaySet = this.props.viewportData.displaySet;
let filteredSRLabels;
if (displaySet.SRLabels && displaySet.SRLabels.length !== 0) {
filteredSRLabels = displaySet.SRLabels.filter(
SRLabel =>
SRLabel.ReferencedSOPInstanceUID === displaySet.SOPInstanceUID
);
}
return (
<OHIFCornerstoneViewportOverlay
{...props}
inconsistencyWarnings={inconsistencyWarnings}
SRLabels={filteredSRLabels}
/>
);
};
@@ -254,7 +264,7 @@ class OHIFCornerstoneViewport extends Component {
imageIdIndex={currentImageIdIndex}
onNewImageDebounced={newImageHandler}
onNewImageDebounceTime={300}
viewportOverlayComponent={warningsOverlay}
viewportOverlayComponent={overlay}
stackPrefetch={this.props.stackPrefetch}
isStackPrefetchEnabled={this.props.isStackPrefetchEnabled}
// ~~ Connected (From REDUX)
@@ -33,6 +33,10 @@
bottom: 140px;
left: 20px;
}
.OHIFCornerstoneViewportOverlay .bottom-left3 {
bottom: 110px;
left: -20px;
}
.OHIFCornerstoneViewportOverlay .bottom-right {
bottom: 20px;
right: 20px;
@@ -1,5 +1,6 @@
import { PureComponent } from 'react';
import React from 'react';
import styled from 'styled-components';
import PropTypes from 'prop-types';
import cornerstone from 'cornerstone-core';
import './OHIFCornerstoneViewportOverlay.css';
@@ -9,13 +10,27 @@ import {
formatDICOMDate,
formatDICOMTime,
formatPN,
getCompression
getCompression,
} from '../utils/formatStudy';
import classNames from 'classnames';
import { Icon } from '@ohif/ui/src/elements/Icon';
import { Tooltip } from '@ohif/ui/src/components/tooltip';
import { OverlayTrigger } from '@ohif/ui/src/components/overlayTrigger';
const Button = styled.button`
color: white;
padding: 2px 7px;
border-radius: 10px;
outline: 0;
text-transform: none;
margin: 2px 2px;
cursor: pointer;
&:disabled {
cursor: default;
opacity: 0.9;
}
`;
class OHIFCornerstoneViewportOverlay extends PureComponent {
static propTypes = {
scale: PropTypes.number.isRequired,
@@ -30,11 +45,19 @@ class OHIFCornerstoneViewportOverlay extends PureComponent {
imageId: PropTypes.string.isRequired,
imageIndex: PropTypes.number.isRequired,
stackSize: PropTypes.number.isRequired,
inconsistencyWarnings: PropTypes.array.isRequired
inconsistencyWarnings: PropTypes.array,
SRLabels: PropTypes.array,
};
render() {
const { imageId, scale, windowWidth, windowCenter, inconsistencyWarnings } = this.props;
const {
imageId,
scale,
windowWidth,
windowCenter,
inconsistencyWarnings,
SRLabels,
} = this.props;
if (!imageId) {
return null;
@@ -72,8 +95,11 @@ class OHIFCornerstoneViewportOverlay extends PureComponent {
const { imageIndex, stackSize } = this.props;
const inconsistencyWarningsOn = inconsistencyWarnings && inconsistencyWarnings.length !== 0 ? true : false;
const getWarningContent = (warningList) => {
const inconsistencyWarningsOn =
inconsistencyWarnings && inconsistencyWarnings.length !== 0
? true
: false;
const getWarningContent = warningList => {
if (Array.isArray(warningList)) {
const listedWarnings = warningList.map((warn, index) => {
return <li key={index}>{warn}</li>;
@@ -86,33 +112,100 @@ class OHIFCornerstoneViewportOverlay extends PureComponent {
};
const getWarningInfo = (seriesNumber, inconsistencyWarnings) => {
return(
return (
<React.Fragment>
{inconsistencyWarnings.length != 0 ? (
<OverlayTrigger
key={seriesNumber}
placement="left"
overlay={
<Tooltip
placement="left"
className="in tooltip-warning"
id="tooltip-left"
>
<div className="warningTitle">Series Inconsistencies</div>
<div className="warningContent">{getWarningContent(inconsistencyWarnings)}</div>
</Tooltip>
}
>
<div className={classNames('warning')}>
<span className="warning-icon">
<Icon name="exclamation-triangle" />
</span>
</div>
</OverlayTrigger>
) : (
<React.Fragment></React.Fragment>
{inconsistencyWarnings.length != 0 ? (
<OverlayTrigger
key={seriesNumber}
placement="left"
overlay={
<Tooltip
placement="left"
className="in tooltip-warning"
id="tooltip-left"
>
<div className="warningTitle">Series Inconsistencies</div>
<div className="warningContent">
{getWarningContent(inconsistencyWarnings)}
</div>
</Tooltip>
}
>
<div className={classNames('warning')}>
<span className="warning-icon">
<Icon name="exclamation-triangle" />
</span>
</div>
</OverlayTrigger>
) : (
<React.Fragment></React.Fragment>
)}
</React.Fragment>
</React.Fragment>
);
};
const SRLabelsOn = SRLabels && SRLabels.length !== 0 ? true : false;
/**/
const getSRLabelsContent = SRLabels => {
if (Array.isArray(SRLabels)) {
const listedSRLabels = SRLabels.map((SRLabel, index) => {
const color = SRLabel.labels.color;
return (
SRLabel.labels.visible && (
<OverlayTrigger
key={index}
placement="top"
overlay={
<Tooltip
placement="top"
className="in tooltip-warning"
id="tooltip-top"
>
<div className="warningTitle">
{' '}
Coding scheme designators{' '}
</div>
<div className="warningContent">
{SRLabel.labels.labelCodingSchemeDesignator +
' : ' +
SRLabel.labels.valueCodingSchemeDesignator}
</div>
</Tooltip>
}
>
<div style={{ display: 'inline-block' }}>
<Button
style={{
backgroundColor: color,
}}
disabled={true}
key={index}
>
{SRLabel.labels.label + ' : ' + SRLabel.labels.value}
</Button>
</div>
</OverlayTrigger>
)
);
});
return <ol>{listedSRLabels}</ol>;
} else {
return <React.Fragment></React.Fragment>;
}
};
const getSRLabelsInfo = SRLabels => {
return (
<React.Fragment>
{SRLabels.length != 0 ? (
getSRLabelsContent(SRLabels)
) : (
<React.Fragment></React.Fragment>
)}
</React.Fragment>
);
};
@@ -134,7 +227,14 @@ class OHIFCornerstoneViewportOverlay extends PureComponent {
<div className="compressionIndicator">{compression}</div>
</div>
<div className="bottom-left2 warning">
<div>{inconsistencyWarningsOn ? getWarningInfo(seriesNumber, inconsistencyWarnings) : ''}</div>
<div>
{inconsistencyWarningsOn
? getWarningInfo(seriesNumber, inconsistencyWarnings)
: ''}
</div>
</div>
<div className="bottom-left3 warning">
<div>{SRLabelsOn ? getSRLabelsInfo(SRLabels) : ''}</div>
</div>
<div className="bottom-left overlay-element">
<div>{seriesNumber >= 0 ? `Ser: ${seriesNumber}` : ''}</div>
@@ -97,6 +97,8 @@ export default class DICOMSRDisplayTool extends BaseTool {
const renderableDataForGraphicType = renderableData[GraphicType];
switch (GraphicType) {
case SCOORD_TYPES.TEXT:
break;
case SCOORD_TYPES.POINT:
this.renderPoint(renderableDataForGraphicType, eventData, options);
break;
@@ -167,20 +169,22 @@ export default class DICOMSRDisplayTool extends BaseTool {
return data.handles.textBox.anchorPoints;
}
draw(context, context => {
drawLinkedTextBox(
context,
element,
data.handles.textBox,
text,
data.handles,
textBoxAnchorPoints,
color,
lineWidth,
0,
true
);
});
if (data.handles.textBox.anchorPoints.length !== 0) {
draw(context, context => {
drawLinkedTextBox(
context,
element,
data.handles.textBox,
text,
data.handles,
textBoxAnchorPoints,
color,
lineWidth,
0,
true
);
});
}
}
// TOOD -> text boxes may overlap with other annotations at the moment.
@@ -230,7 +234,6 @@ export default class DICOMSRDisplayTool extends BaseTool {
const { element, image } = eventData;
const { rows, columns } = image;
const context = getNewContext(eventData.canvasContext.canvas);
const { color, lineWidth } = options;
// Find a suitable length for the image size.
@@ -332,6 +335,8 @@ function _getTextBoxAnchorPointsForRenderableData(renderableData, eventData) {
const renderableDataForGraphicType = renderableData[GraphicType];
switch (GraphicType) {
case SCOORD_TYPES.TEXT:
break;
case SCOORD_TYPES.POINT:
renderableDataForGraphicType.forEach(points => {
anchorPoints = [...anchorPoints, ...points];
@@ -405,7 +410,7 @@ function _getBoundingBoxFromAnchorPoints(anchorPoints) {
minX = x;
}
if (y > maxX) {
if (y > maxY) {
maxY = y;
} else if (y < minY) {
minY = y;
@@ -1,4 +1,5 @@
export default {
TEXT: 'TEXT',
POINT: 'POINT',
MULTIPOINT: 'MULTIPOINT',
POLYLINE: 'POLYLINE',
+8
View File
@@ -3,6 +3,14 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [0.3.3](https://github.com/OHIF/Viewers/compare/@ohif/extension-debugging@0.3.2...@ohif/extension-debugging@0.3.3) (2022-06-30)
**Note:** Version bump only for package @ohif/extension-debugging
## [0.3.2](https://github.com/OHIF/Viewers/compare/@ohif/extension-debugging@0.3.1...@ohif/extension-debugging@0.3.2) (2022-03-10)
**Note:** Version bump only for package @ohif/extension-debugging
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@ohif/extension-debugging",
"version": "0.3.2",
"version": "0.3.3",
"description": "OHIF extension for debugging.",
"author": "OHIF",
"license": "MIT",
+33 -48
View File
@@ -89,10 +89,10 @@ const DubugReportModal = ({
Object.keys(viewportSpecificData).forEach(viewportIndex => {
const displaySet = viewportSpecificData[viewportIndex];
const [
referencedDisplaySetsRef,
referencedDisplaySetsCount,
] = _getReferencedSeriesInstanceUIDsString(displaySet, 'SEG');
const [referencedDisplaySetsRef] = _getReferencedSeriesInstanceUIDsString(
displaySet,
'SEG'
);
const [row, column] = _viewportIndexToViewportPosition(
viewportIndex,
@@ -106,10 +106,27 @@ const DubugReportModal = ({
Object.keys(viewportSpecificData).forEach(viewportIndex => {
const displaySet = viewportSpecificData[viewportIndex];
const [
referencedDisplaySetsRef,
referencedDisplaySetsCount,
] = _getReferencedSeriesInstanceUIDsString(displaySet, 'RTSTRUCT');
const [referencedDisplaySetsRef] = _getReferencedSeriesInstanceUIDsString(
displaySet,
'RTSTRUCT'
);
const [row, column] = _viewportIndexToViewportPosition(
viewportIndex,
numColumns
);
body += `[${row},${column}]\t${referencedDisplaySetsRef}\n`;
});
body += '== ReferencedSRSeriesInstanceUIDs ==\n';
Object.keys(viewportSpecificData).forEach(viewportIndex => {
const displaySet = viewportSpecificData[viewportIndex];
const [referencedDisplaySetsRef] = _getReferencedSeriesInstanceUIDsString(
displaySet,
'SR'
);
const [row, column] = _viewportIndexToViewportPosition(
viewportIndex,
@@ -261,11 +278,15 @@ const getLayout = viewports => {
<tr>
<th>ReferencedSEGSeriesInstanceUIDs</th>
</tr>
{getReferencedSEGSeriesInstanceUIDsPerRow(viewports)}
{getReferencedSeriesInstanceUIDsPerRow(viewports, 'SEG')}
<tr>
<th>ReferencedRTSTRUCTSeriesInstanceUIDs</th>
</tr>
{getReferencedRTSTRUCTSeriesInstanceUIDsPerRow(viewports)}
{getReferencedSeriesInstanceUIDsPerRow(viewports, 'RTSTRUCT')}
<tr>
<th>ReferencedSRSeriesInstanceUIDs</th>
</tr>
{getReferencedSeriesInstanceUIDsPerRow(viewports, 'SR')}
</React.Fragment>
);
};
@@ -351,7 +372,7 @@ const _getReferencedSeriesInstanceUIDsString = (displaySet, Modality) => {
return [referencedDisplaySetsRef, referencedDisplaySetsCount];
};
const getReferencedSEGSeriesInstanceUIDsPerRow = viewports => {
const getReferencedSeriesInstanceUIDsPerRow = (viewports, Modality) => {
const { viewportSpecificData, numColumns } = viewports;
// NOTE viewportSpecificData is actually an object with numerical keys.
@@ -360,43 +381,7 @@ const getReferencedSEGSeriesInstanceUIDsPerRow = viewports => {
const [
referencedDisplaySetsRef,
referencedDisplaySetsCount,
] = _getReferencedSeriesInstanceUIDsString(displaySet, 'SEG');
const [row, column] = _viewportIndexToViewportPosition(
viewportIndex,
numColumns
);
if (referencedDisplaySetsCount > 1) {
return (
<tr>
<td>{`[${row},${column}]`}</td>
<td className="debug-overflowText-border">
{referencedDisplaySetsRef}
</td>
</tr>
);
} else {
return (
<tr>
<td>{`[${row},${column}]`}</td>
<td className="debug-overflowText">{referencedDisplaySetsRef}</td>
</tr>
);
}
});
};
const getReferencedRTSTRUCTSeriesInstanceUIDsPerRow = viewports => {
const { viewportSpecificData, numColumns } = viewports;
// NOTE viewportSpecificData is actually an object with numerical keys.
return Object.keys(viewportSpecificData).map(viewportIndex => {
const displaySet = viewportSpecificData[viewportIndex];
const [
referencedDisplaySetsRef,
referencedDisplaySetsCount,
] = _getReferencedSeriesInstanceUIDsString(displaySet, 'RTSTRUCT');
] = _getReferencedSeriesInstanceUIDsString(displaySet, Modality);
const [row, column] = _viewportIndexToViewportPosition(
viewportIndex,
+48
View File
@@ -3,6 +3,54 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.3.24](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-html@1.3.23...@ohif/extension-dicom-html@1.3.24) (2022-12-21)
**Note:** Version bump only for package @ohif/extension-dicom-html
## [1.3.23](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-html@1.3.22...@ohif/extension-dicom-html@1.3.23) (2022-09-01)
**Note:** Version bump only for package @ohif/extension-dicom-html
## [1.3.22](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-html@1.3.21...@ohif/extension-dicom-html@1.3.22) (2022-06-30)
**Note:** Version bump only for package @ohif/extension-dicom-html
## [1.3.21](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-html@1.3.20...@ohif/extension-dicom-html@1.3.21) (2022-04-05)
**Note:** Version bump only for package @ohif/extension-dicom-html
## [1.3.20](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-html@1.3.19...@ohif/extension-dicom-html@1.3.20) (2022-03-25)
**Note:** Version bump only for package @ohif/extension-dicom-html
## [1.3.19](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-html@1.3.18...@ohif/extension-dicom-html@1.3.19) (2022-03-14)
**Note:** Version bump only for package @ohif/extension-dicom-html
## [1.3.18](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-html@1.3.17...@ohif/extension-dicom-html@1.3.18) (2022-02-03)
**Note:** Version bump only for package @ohif/extension-dicom-html
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@ohif/extension-dicom-html",
"version": "1.3.18",
"version": "1.3.24",
"description": "OHIF extension for rendering structured reports to HTML",
"author": "OHIF",
"license": "MIT",
@@ -29,7 +29,7 @@
},
"peerDependencies": {
"@ohif/core": "^0.50.0",
"dcmjs": "0.19.4",
"dcmjs": "0.29.3",
"prop-types": "^15.6.2",
"react": "^16.8.6",
"react-dom": "^16.8.6"
@@ -1,4 +1,4 @@
import { MODULE_TYPES, utils } from '@ohif/core';
import { MODULE_TYPES, utils, metadata } from '@ohif/core';
// TODO: Should probably use dcmjs for this
const SOP_CLASS_UIDS = {
@@ -10,7 +10,7 @@ const SOP_CLASS_UIDS = {
MAMMOGRAPHY_CAD_SR: '1.2.840.10008.5.1.4.1.1.88.50',
CHEST_CAD_SR: '1.2.840.10008.5.1.4.1.1.88.65',
X_RAY_RADIATION_DOSE_SR: '1.2.840.10008.5.1.4.1.1.88.67',
ACQUISITION_CONTEXT_SR_STORAGE: '1.2.840.10008.5.1.4.1.1.88.71'
ACQUISITION_CONTEXT_SR_STORAGE: '1.2.840.10008.5.1.4.1.1.88.71',
};
const sopClassUIDs = Object.values(SOP_CLASS_UIDS);
@@ -32,7 +32,7 @@ const OHIFDicomHtmlSopClassHandler = {
SeriesTime,
} = metadata;
return {
const srDisplaySet = {
plugin: 'html',
Modality: 'SR',
displaySetInstanceUID: utils.guid(),
@@ -49,7 +49,15 @@ const OHIFDicomHtmlSopClassHandler = {
authorizationHeaders,
sopClassUids: sopClassUIDs,
images: series._instances,
isDerived: true,
referencedDisplaySets: [],
};
srDisplaySet.getSourceDisplaySet = function() {
return srDisplaySet.referencedDisplaySets;
};
return srDisplaySet;
},
};
+48
View File
@@ -3,6 +3,54 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [0.7.14](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-rt@0.7.13...@ohif/extension-dicom-rt@0.7.14) (2022-12-21)
**Note:** Version bump only for package @ohif/extension-dicom-rt
## [0.7.13](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-rt@0.7.12...@ohif/extension-dicom-rt@0.7.13) (2022-09-01)
**Note:** Version bump only for package @ohif/extension-dicom-rt
## [0.7.12](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-rt@0.7.11...@ohif/extension-dicom-rt@0.7.12) (2022-08-31)
**Note:** Version bump only for package @ohif/extension-dicom-rt
## [0.7.11](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-rt@0.7.10...@ohif/extension-dicom-rt@0.7.11) (2022-04-05)
**Note:** Version bump only for package @ohif/extension-dicom-rt
## [0.7.10](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-rt@0.7.9...@ohif/extension-dicom-rt@0.7.10) (2022-03-25)
**Note:** Version bump only for package @ohif/extension-dicom-rt
## [0.7.9](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-rt@0.7.8...@ohif/extension-dicom-rt@0.7.9) (2022-03-14)
**Note:** Version bump only for package @ohif/extension-dicom-rt
## [0.7.8](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-rt@0.7.7...@ohif/extension-dicom-rt@0.7.8) (2022-02-03)
**Note:** Version bump only for package @ohif/extension-dicom-rt
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@ohif/extension-dicom-rt",
"version": "0.7.8",
"version": "0.7.14",
"description": "OHIF extension for rendering DICOM RTSTRUCTs on top of cornerstone images.",
"author": "OHIF",
"license": "MIT",
@@ -31,7 +31,7 @@
"@ohif/core": "^0.50.0",
"cornerstone-core": "^2.6.1",
"cornerstone-tools": "^6.0.6",
"dcmjs": "0.19.4",
"dcmjs": "0.29.3",
"gl-matrix": "^3.3.0",
"prop-types": "^15.6.2",
"react": "^16.8.6",
@@ -1,4 +1,4 @@
import React, { useState, useEffect, useCallback } from 'react';
import React, { useState, useEffect } from 'react';
import PropTypes from 'prop-types';
import cornerstoneTools from 'cornerstone-tools';
import cornerstone from 'cornerstone-core';
+110
View File
@@ -3,6 +3,116 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [0.7.21](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-segmentation@0.7.20...@ohif/extension-dicom-segmentation@0.7.21) (2023-01-17)
**Note:** Version bump only for package @ohif/extension-dicom-segmentation
## [0.7.20](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-segmentation@0.7.19...@ohif/extension-dicom-segmentation@0.7.20) (2023-01-10)
**Note:** Version bump only for package @ohif/extension-dicom-segmentation
## [0.7.19](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-segmentation@0.7.18...@ohif/extension-dicom-segmentation@0.7.19) (2022-12-21)
**Note:** Version bump only for package @ohif/extension-dicom-segmentation
## [0.7.18](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-segmentation@0.7.17...@ohif/extension-dicom-segmentation@0.7.18) (2022-12-21)
**Note:** Version bump only for package @ohif/extension-dicom-segmentation
## [0.7.17](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-segmentation@0.7.16...@ohif/extension-dicom-segmentation@0.7.17) (2022-12-12)
### Bug Fixes
* [#2964](https://github.com/OHIF/Viewers/issues/2964) Reword message for segmentation error loading due to orientation tolerance ([#3017](https://github.com/OHIF/Viewers/issues/3017)) ([597ac11](https://github.com/OHIF/Viewers/commit/597ac11c4daee1b1e14148804551e20611cfef08))
## [0.7.16](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-segmentation@0.7.15...@ohif/extension-dicom-segmentation@0.7.16) (2022-10-28)
### Bug Fixes
* [#2964](https://github.com/OHIF/Viewers/issues/2964) Update message for segmentation error loading due to orientation tolerance ([#2982](https://github.com/OHIF/Viewers/issues/2982)) ([545161d](https://github.com/OHIF/Viewers/commit/545161d5e8d92bb6652f17dc24a36dac8aa7b3a4))
## [0.7.15](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-segmentation@0.7.14...@ohif/extension-dicom-segmentation@0.7.15) (2022-09-19)
**Note:** Version bump only for package @ohif/extension-dicom-segmentation
## [0.7.14](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-segmentation@0.7.13...@ohif/extension-dicom-segmentation@0.7.14) (2022-09-12)
**Note:** Version bump only for package @ohif/extension-dicom-segmentation
## [0.7.13](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-segmentation@0.7.12...@ohif/extension-dicom-segmentation@0.7.13) (2022-09-01)
**Note:** Version bump only for package @ohif/extension-dicom-segmentation
## [0.7.12](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-segmentation@0.7.11...@ohif/extension-dicom-segmentation@0.7.12) (2022-08-31)
**Note:** Version bump only for package @ohif/extension-dicom-segmentation
## [0.7.11](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-segmentation@0.7.10...@ohif/extension-dicom-segmentation@0.7.11) (2022-04-05)
**Note:** Version bump only for package @ohif/extension-dicom-segmentation
## [0.7.10](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-segmentation@0.7.9...@ohif/extension-dicom-segmentation@0.7.10) (2022-03-25)
**Note:** Version bump only for package @ohif/extension-dicom-segmentation
## [0.7.9](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-segmentation@0.7.8...@ohif/extension-dicom-segmentation@0.7.9) (2022-03-14)
**Note:** Version bump only for package @ohif/extension-dicom-segmentation
## [0.7.8](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-segmentation@0.7.7...@ohif/extension-dicom-segmentation@0.7.8) (2022-02-03)
**Note:** Version bump only for package @ohif/extension-dicom-segmentation
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@ohif/extension-dicom-segmentation",
"version": "0.7.8",
"version": "0.7.21",
"description": "OHIF extension for viewing segmentations in the 2D MPR view",
"author": "OHIF",
"license": "MIT",
@@ -31,7 +31,7 @@
"@ohif/core": "^0.50.0",
"cornerstone-core": "^2.6.1",
"cornerstone-tools": "^6.0.6",
"dcmjs": "0.19.4",
"dcmjs": "0.29.3",
"prop-types": "^15.6.2",
"react": "^16.8.6",
"react-dom": "^16.8.6"
@@ -0,0 +1,100 @@
import csTools from 'cornerstone-tools';
import cs from 'cornerstone-core';
import OHIF from '@ohif/core';
import DICOMSegTempCrosshairsTool from './tools/DICOMSegTempCrosshairsTool';
import refreshViewports from './utils/refreshViewports';
const { studyMetadataManager } = OHIF.utils;
const commandsModule = ({ commandsManager }) => {
const actions = {
jumpToFirstSegment: ({ viewports }) => {
try {
const { activeViewportIndex, viewportSpecificData } = viewports;
const viewport = viewportSpecificData[activeViewportIndex];
const { StudyInstanceUID, displaySetInstanceUID } = viewport;
const studyMetadata = studyMetadataManager.get(StudyInstanceUID);
const firstImageId = studyMetadata.getFirstImageId(
displaySetInstanceUID
);
const module = csTools.getModule('segmentation');
const brushStackState = module.state.series[firstImageId];
const { labelmaps3D, activeLabelmapIndex } = brushStackState;
const { labelmaps2D } = labelmaps3D[activeLabelmapIndex];
const firstLabelMap2D = labelmaps2D.find(value => !!value);
const firstSegment = firstLabelMap2D.segmentsOnLabelmap[0];
const segmentNumber = firstSegment;
const validIndexList = [];
labelmaps2D.forEach((labelMap2D, index) => {
if (labelMap2D.segmentsOnLabelmap.includes(segmentNumber)) {
validIndexList.push(index);
}
});
const avg = array => array.reduce((a, b) => a + b) / array.length;
const average = avg(validIndexList);
const closest = validIndexList.reduce((prev, curr) => {
return Math.abs(curr - average) < Math.abs(prev - average)
? curr
: prev;
});
const enabledElements = cs.getEnabledElements();
const element = enabledElements[activeViewportIndex].element;
const toolState = csTools.getToolState(element, 'stack');
if (!toolState) return;
const imageIds = toolState.data[0].imageIds;
const imageId = imageIds[closest];
const frameIndex = imageIds.indexOf(imageId);
const SOPInstanceUID = cs.metaData.get('SOPInstanceUID', imageId);
cs.getEnabledElements().forEach(enabledElement => {
cs.updateImage(enabledElement.element);
});
DICOMSegTempCrosshairsTool.addCrosshair(
element,
imageId,
segmentNumber
);
cs.getEnabledElements().forEach(enabledElement => {
cs.updateImage(enabledElement.element);
});
const refreshViewports = false;
commandsManager.runCommand('jumpToImage', {
StudyInstanceUID,
SOPInstanceUID,
frameIndex,
activeViewportIndex,
refreshViewports,
});
} catch (error) {
console.log('Error in moving to the first segment slice');
}
},
};
const definitions = {
jumpToFirstSegment: {
commandFn: actions.jumpToFirstSegment,
storeContexts: ['viewports'],
options: {},
},
};
return {
definitions,
defaultContext: 'VIEWER',
};
};
export default commandsModule;
@@ -62,8 +62,8 @@
}
.dcmseg-segment-item .segment-label span {
overflow-wrap: normal;
white-space: nowrap;
overflow-wrap: break-word;
white-space: normal;
overflow: hidden;
max-width: calc(100% - 40px); /* calc(100% - 50px); 20px = eye icon */
text-overflow: ellipsis;
@@ -71,6 +71,7 @@
.dcmseg-segment-item .segment-label .eye-icon {
cursor: pointer;
min-width: 20px;
color: var(--active-color);
}
@@ -1,4 +1,4 @@
import React, { useState, useEffect } from 'react';
import React, { useState, useEffect, useCallback } from 'react';
import PropTypes from 'prop-types';
import cornerstoneTools from 'cornerstone-tools';
import cornerstone from 'cornerstone-core';
@@ -36,6 +36,7 @@ const { studyMetadataManager } = utils;
* @param {Function} props.onConfigurationChange - Configuration change handler
* @param {Function} props.activeContexts - List of active application contexts
* @param {Function} props.contexts - List of available application contexts
* @param {Function} props.servicesManager - Services manager
* @returns component
*/
const SegmentationPanel = ({
@@ -50,6 +51,7 @@ const SegmentationPanel = ({
onSelectedSegmentationChange,
activeContexts = [],
contexts = {},
servicesManager,
}) => {
const isVTK = () => activeContexts.includes(contexts.VTK);
const isCornerstone = () => activeContexts.includes(contexts.CORNERSTONE);
@@ -59,6 +61,9 @@ const SegmentationPanel = ({
* store with context to make these kind of things less blurry.
*/
const { configuration } = cornerstoneTools.getModule('segmentation');
if (configuration.segsTolerance === undefined) {
configuration.segsTolerance = 1e-2;
}
const DEFAULT_BRUSH_RADIUS = configuration.radius || 10;
/*
@@ -87,6 +92,25 @@ const SegmentationPanel = ({
return studyMetadata.getFirstImageId(displaySetInstanceUID);
};
const getAllSegDisplaySets = () => {
const { StudyInstanceUID } = getActiveViewport();
const studyMetadata = studyMetadataManager.get(StudyInstanceUID);
return studyMetadata.getDerivedDatasets({
Modality: 'SEG',
});
};
const updateSegDisplaySetsTolerance = tolerance => {
const segDisplaySets = getAllSegDisplaySets();
segDisplaySets.forEach(segDisplaySet => {
// update tol value
segDisplaySet.tolerance = tolerance;
// reset load flags for allowing retry for seg parsing.
segDisplaySet.isLoaded = false;
segDisplaySet.loadError = false;
});
};
const getActiveLabelMaps3D = () => {
const { labelmaps3D, activeLabelmapIndex } = getBrushStackState();
return labelmaps3D[activeLabelmapIndex];
@@ -224,33 +248,15 @@ const SegmentationPanel = ({
)
);
};
}, [
activeIndex,
updateSegmentationComboBox,
viewports,
]);
}, [activeIndex, viewports]);
const updateSegmentationComboBox = e => {
const index = e.detail.activatedLabelmapIndex;
if (index !== -1) {
setState(state => ({ ...state, selectedSegmentation: index }));
} else {
cleanSegmentationComboBox();
}
};
const cleanSegmentationComboBox = () => {
setState(state => ({
...state,
segmentsHidden: [],
segmentNumbers: [],
labelMapList: [],
segmentList: [],
isDisabled: true,
selectedSegmentation: -1,
}));
};
const refreshSegmentations = () => {
const activeViewport = getActiveViewport();
const isDisabled = !activeViewport || !activeViewport.StudyInstanceUID;
@@ -616,31 +622,25 @@ const SegmentationPanel = ({
configuration.outlineWidth = newConfiguration.outlineWidth;
configuration.fillAlphaInactive = newConfiguration.fillAlphaInactive;
configuration.outlineAlphaInactive = newConfiguration.outlineAlphaInactive;
configuration.segsTolerance = newConfiguration.segsTolerance;
onConfigurationChange(newConfiguration);
updateSegDisplaySetsTolerance(configuration.segsTolerance);
refreshViewports();
};
const onVisibilityChangeHandler = isVisible => {
let segmentsHidden = [];
const labelmap3D = getActiveLabelMaps3D();
state.segmentNumbers.forEach(segmentNumber => {
if (isVTK()) {
onSegmentVisibilityChange(segmentNumber, isVisible);
}
/** Get all labelmaps with this segmentNumber (overlapping segments) */
const { labelmaps3D } = getBrushStackState();
const possibleLabelMaps3D = labelmaps3D.filter(({ labelmaps2D }) => {
return labelmaps2D.some(({ segmentsOnLabelmap }) =>
segmentsOnLabelmap.includes(segmentNumber)
);
});
possibleLabelMaps3D.forEach(labelmap3D => {
labelmap3D.segmentsHidden[segmentNumber] = !isVisible;
segmentsHidden = [
...new Set([...segmentsHidden, ...labelmap3D.segmentsHidden]),
];
});
labelmap3D.segmentsHidden[segmentNumber] = !isVisible;
segmentsHidden = [
...new Set([...segmentsHidden, ...labelmap3D.segmentsHidden]),
];
});
setState(state => ({ ...state, segmentsHidden }));
@@ -665,6 +665,7 @@ const SegmentationPanel = ({
configuration={configuration}
onBack={() => setState(state => ({ ...state, showSettings: false }))}
onChange={updateConfiguration}
servicesManager={servicesManager}
/>
);
} else {
@@ -709,7 +710,7 @@ const SegmentationPanel = ({
count={state.segmentList.length}
isVisible={
state.segmentsHidden.filter(isHidden => isHidden === true).length <
state.segmentNumbers.length
state.segmentNumbers.length && state.segmentNumbers.length > 0
}
onVisibilityChange={onVisibilityChangeHandler}
>
@@ -4,7 +4,7 @@ import { Range } from '@ohif/ui';
import './SegmentationSettings.css';
const SegmentationSettings = ({ configuration, onBack, onChange, disabledFields = [] }) => {
const SegmentationSettings = ({ configuration, onBack, onChange, servicesManager, disabledFields = [] }) => {
const [state, setState] = useState({
renderFill: configuration.renderFill,
renderOutline: configuration.renderOutline,
@@ -13,7 +13,8 @@ const SegmentationSettings = ({ configuration, onBack, onChange, disabledFields
outlineAlpha: configuration.outlineAlpha,
outlineWidth: configuration.outlineWidth,
fillAlphaInactive: configuration.fillAlphaInactive,
outlineAlphaInactive: configuration.outlineAlphaInactive
outlineAlphaInactive: configuration.outlineAlphaInactive,
segsTolerance: configuration.segsTolerance,
});
useEffect(() => {
@@ -28,6 +29,32 @@ const SegmentationSettings = ({ configuration, onBack, onChange, disabledFields
setState(state => ({ ...state, [field]: value }));
};
const once = fn => (...args) => {
if (!fn) return;
fn(...args);
fn = null;
};
const segTolValue = document.getElementById('segToleranceValue');
if (segTolValue) {
segTolValue.onchange = once(function() {
const { UINotificationService, LoggerService } = servicesManager.services;
const error = new Error(
'Segmentation loader tolerance changed.\
This operation can potentially generate errors in the Segmentation parsing.'
);
LoggerService.error({ error, message: error.message });
UINotificationService.show({
title: 'Segmentation panel',
message: error.message,
type: 'warning',
autoClose: true,
});
});
}
const toFloat = value => parseFloat(value / 100).toFixed(2);
return (
@@ -133,6 +160,31 @@ const SegmentationSettings = ({ configuration, onBack, onChange, disabledFields
)}
</div>
)}
<div className="settings-group" style={{ marginBottom: 15 }}>
<label style={{ margin: '0 15px' }}>
Tolerance:
<input
id="segToleranceValue"
style={{ margin: '0 15px' }}
label="Tolerance"
onKeyPress={event => {
const validate = string => {
let rgx = /[^-.e0-9]+/g;
return string.match(rgx);
};
if (validate(event.key)) {
event.preventDefault();
}
}
}
onChange={event => {
save('segsTolerance', event.target.value);
}}
value={state.segsTolerance}
/>
</label>
</div>
</div>
);
};
@@ -169,11 +221,12 @@ SegmentationSettings.propTypes = {
renderFill: PropTypes.bool.isRequired,
renderOutline: PropTypes.bool.isRequired,
shouldRenderInactiveLabelmaps: PropTypes.bool.isRequired,
fillAlpha: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired, /* TODO: why fillAlpha is string? */
outlineAlpha: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired, /* TODO: why fillAlpha is string? */
fillAlpha: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired,
outlineAlpha: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired,
outlineWidth: PropTypes.number.isRequired,
fillAlphaInactive: PropTypes.number.isRequired,
outlineAlphaInactive: PropTypes.number.isRequired,
fillAlphaInactive: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired,
outlineAlphaInactive: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired,
segsTolerance: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired,
}).isRequired,
onBack: PropTypes.func.isRequired,
onChange: PropTypes.func.isRequired,
@@ -62,6 +62,7 @@ export default function getSopClassHandlerModule({ servicesManager }) {
SeriesNumber,
SeriesDescription,
metadata,
tolerance: 1e-2,
};
segDisplaySet.getSourceDisplaySet = function(
@@ -93,7 +94,7 @@ export default function getSopClassHandlerModule({ servicesManager }) {
referencedDisplaySet.SeriesInstanceUID
);
const results = await _parseSeg(segArrayBuffer, imageIds);
const results = await _parseSeg(segArrayBuffer, imageIds, segDisplaySet.tolerance);
if (results === undefined) {
return;
}
@@ -149,10 +150,13 @@ export default function getSopClassHandlerModule({ servicesManager }) {
};
}
function _parseSeg(arrayBuffer, imageIds) {
const skipOverlapping = false;
const tolerance = 1e-2;
const cornerstoneToolsVersion = 4;
function _parseSeg(
arrayBuffer,
imageIds,
tolerance = 1e-2,
skipOverlapping = false,
cornerstoneToolsVersion = 4
) {
return dcmjs.adapters.Cornerstone.Segmentation.generateToolState(
imageIds,
arrayBuffer,
+23 -3
View File
@@ -6,6 +6,7 @@ import toolbarModule from './toolbarModule.js';
import getSopClassHandlerModule from './getOHIFDicomSegSopClassHandler.js';
import SegmentationPanel from './components/SegmentationPanel/SegmentationPanel.js';
import { version } from '../package.json';
import commandsModule from './commandsModule.js';
const { studyMetadataManager } = OHIF.utils;
export default {
@@ -32,12 +33,18 @@ export default {
const ExtendedSegmentationPanel = props => {
const { activeContexts } = api.hooks.useAppContext();
const onDisplaySetLoadFailureHandler = error => {
LoggerService.error({ error, message: error.message });
const message =
error.message.includes('orthogonal') ||
error.message.includes('oblique')
? 'The segmentation has been detected as non coplanar,\
If you really think it is coplanar,\
please adjust the tolerance in the segmentation panel settings (at your own peril!)'
: error.message;
LoggerService.error({ error, message });
UINotificationService.show({
title: 'DICOM Segmentation Loader',
message: error.message,
message,
type: 'error',
autoClose: false,
});
@@ -78,6 +85,7 @@ export default {
onConfigurationChange={onConfigurationChangeHandler}
onSelectedSegmentationChange={onSelectedSegmentationChangeHandler}
onDisplaySetLoadFailure={onDisplaySetLoadFailureHandler}
servicesManager={servicesManager}
/>
);
};
@@ -114,6 +122,15 @@ export default {
});
};
const onSegmentationsCompletelyLoaded = () => {
commandsManager.runCommand('jumpToFirstSegment');
};
document.addEventListener(
'segseriesselected',
onSegmentationsCompletelyLoaded
);
document.addEventListener(
'extensiondicomsegmentationsegloaded',
onSegmentationsLoaded
@@ -175,5 +192,8 @@ export default {
defaultContext: ['VIEWER'],
};
},
getCommandsModule({ commandsManager, servicesManager }) {
return commandsModule({ commandsManager, servicesManager });
},
getSopClassHandlerModule,
};
@@ -47,14 +47,23 @@ export default async function setActiveLabelmap(
return labelmapIndex;
}
if (!displaySet.isLoaded) {
if (!displaySet.isLoaded && !displaySet.loadError) {
try {
await displaySet.load(referencedDisplaySet, studies);
} catch (error) {
displaySet.isLoaded = false;
displaySet.loadError = true;
displaySet.segLoadErrorMessagge = error.message;
onDisplaySetLoadFailure(error);
/*
* TODO: Improve the way we notify parts of the app
* that depends on derived display sets to be loaded.
* (Implement pubsub for better tracking of derived display sets)
*/
const event = new CustomEvent('segmentationLoadingError');
document.dispatchEvent(event);
return -1;
}
}
+56
View File
@@ -3,6 +3,62 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [0.2.26](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-tag-browser@0.2.25...@ohif/extension-dicom-tag-browser@0.2.26) (2023-03-19)
**Note:** Version bump only for package @ohif/extension-dicom-tag-browser
## [0.2.25](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-tag-browser@0.2.24...@ohif/extension-dicom-tag-browser@0.2.25) (2022-12-21)
**Note:** Version bump only for package @ohif/extension-dicom-tag-browser
## [0.2.24](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-tag-browser@0.2.23...@ohif/extension-dicom-tag-browser@0.2.24) (2022-09-01)
**Note:** Version bump only for package @ohif/extension-dicom-tag-browser
## [0.2.23](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-tag-browser@0.2.22...@ohif/extension-dicom-tag-browser@0.2.23) (2022-04-06)
**Note:** Version bump only for package @ohif/extension-dicom-tag-browser
## [0.2.22](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-tag-browser@0.2.21...@ohif/extension-dicom-tag-browser@0.2.22) (2022-04-05)
**Note:** Version bump only for package @ohif/extension-dicom-tag-browser
## [0.2.21](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-tag-browser@0.2.20...@ohif/extension-dicom-tag-browser@0.2.21) (2022-03-25)
**Note:** Version bump only for package @ohif/extension-dicom-tag-browser
## [0.2.20](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-tag-browser@0.2.19...@ohif/extension-dicom-tag-browser@0.2.20) (2022-03-14)
**Note:** Version bump only for package @ohif/extension-dicom-tag-browser
## [0.2.19](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-tag-browser@0.2.18...@ohif/extension-dicom-tag-browser@0.2.19) (2022-02-03)
**Note:** Version bump only for package @ohif/extension-dicom-tag-browser
+3 -3
View File
@@ -1,6 +1,6 @@
{
"name": "@ohif/extension-dicom-tag-browser",
"version": "0.2.19",
"version": "0.2.26",
"description": "OHIF extension for checking DICOM headers.",
"author": "OHIF",
"license": "MIT",
@@ -28,13 +28,13 @@
},
"peerDependencies": {
"@ohif/core": "^2.6.0",
"dcmjs": "0.19.4",
"dcmjs": "0.29.3",
"react": "^16.8.6"
},
"dependencies": {
"@babel/runtime": "^7.5.5",
"dicomweb-client": "^0.8.3",
"moment": "2.24.0",
"moment": "2.29.4",
"react-select": "^3.0.8"
}
}
@@ -59,7 +59,7 @@ const DicomTagBrowser = ({ displaySets, displaySetInstanceUID }) => {
let metadata;
const isImageStack =
activeDisplaySet instanceof ImageSet &&
activeDisplaySet.isModalitySupported === true;
activeDisplaySet.isSOPClassUIDSupported === true;
let instanceList;
+8
View File
@@ -3,6 +3,14 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [0.2.2](https://github.com/OHIF/Viewers/compare/@ohif/extension-lesion-tracker@0.2.1...@ohif/extension-lesion-tracker@0.2.2) (2022-06-29)
**Note:** Version bump only for package @ohif/extension-lesion-tracker
## [0.2.1](https://github.com/OHIF/Viewers/compare/@ohif/extension-lesion-tracker@0.2.0...@ohif/extension-lesion-tracker@0.2.1) (2020-09-03)
**Note:** Version bump only for package @ohif/extension-lesion-tracker
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@ohif/extension-lesion-tracker",
"version": "0.2.1",
"version": "0.2.2",
"description": "OHIF extension for Lesion Tracker",
"author": "OHIF",
"license": "MIT",
@@ -76,13 +76,13 @@ const additionalFindings = [
const currentCollections = [
{
selectorAction: () => { },
selectorAction: () => {},
maxMeasurements: 3,
groupName: 'Measurements',
measurements: measurements,
},
{
selectorAction: () => { },
selectorAction: () => {},
groupName: 'Additional Findings',
measurements: additionalFindings,
},
@@ -90,13 +90,13 @@ const currentCollections = [
const comparisonColletions = [
{
selectorAction: () => { },
selectorAction: () => {},
maxMeasurements: 3,
groupName: 'Measurements',
measurements: measurements,
},
{
selectorAction: () => { },
selectorAction: () => {},
groupName: 'Additional Findings',
measurements: additionalFindings,
},
@@ -128,7 +128,7 @@ const comparisonTimepoints = [
{
key: 'Comparison',
date: '15-Jun-18',
}
},
];
const MeasurementComparisonTable = () => {
@@ -138,8 +138,8 @@ const MeasurementComparisonTable = () => {
timepoints={comparisonTimepoints}
overallWarnings={overallWarnings}
measurementCollection={comparisonCollections}
onRelabelClick={() => { }}
onEditDescriptionClick={() => { }}
onRelabelClick={() => {}}
onEditDescriptionClick={() => {}}
/>
<div className="generate-report">
<button className="btn btn-primary">Generate Report</button>
+208
View File
@@ -3,6 +3,214 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.12.42](https://github.com/OHIF/Viewers/compare/@ohif/extension-vtk@1.12.41...@ohif/extension-vtk@1.12.42) (2023-03-19)
**Note:** Version bump only for package @ohif/extension-vtk
## [1.12.41](https://github.com/OHIF/Viewers/compare/@ohif/extension-vtk@1.12.40...@ohif/extension-vtk@1.12.41) (2022-12-21)
**Note:** Version bump only for package @ohif/extension-vtk
## [1.12.40](https://github.com/OHIF/Viewers/compare/@ohif/extension-vtk@1.12.39...@ohif/extension-vtk@1.12.40) (2022-12-12)
**Note:** Version bump only for package @ohif/extension-vtk
## [1.12.39](https://github.com/OHIF/Viewers/compare/@ohif/extension-vtk@1.12.38...@ohif/extension-vtk@1.12.39) (2022-11-12)
**Note:** Version bump only for package @ohif/extension-vtk
## [1.12.38](https://github.com/OHIF/Viewers/compare/@ohif/extension-vtk@1.12.37...@ohif/extension-vtk@1.12.38) (2022-11-02)
**Note:** Version bump only for package @ohif/extension-vtk
## [1.12.37](https://github.com/OHIF/Viewers/compare/@ohif/extension-vtk@1.12.36...@ohif/extension-vtk@1.12.37) (2022-10-28)
**Note:** Version bump only for package @ohif/extension-vtk
## [1.12.36](https://github.com/OHIF/Viewers/compare/@ohif/extension-vtk@1.12.35...@ohif/extension-vtk@1.12.36) (2022-10-25)
**Note:** Version bump only for package @ohif/extension-vtk
## [1.12.35](https://github.com/OHIF/Viewers/compare/@ohif/extension-vtk@1.12.34...@ohif/extension-vtk@1.12.35) (2022-09-26)
**Note:** Version bump only for package @ohif/extension-vtk
## [1.12.34](https://github.com/OHIF/Viewers/compare/@ohif/extension-vtk@1.12.33...@ohif/extension-vtk@1.12.34) (2022-09-20)
**Note:** Version bump only for package @ohif/extension-vtk
## [1.12.33](https://github.com/OHIF/Viewers/compare/@ohif/extension-vtk@1.12.32...@ohif/extension-vtk@1.12.33) (2022-09-19)
**Note:** Version bump only for package @ohif/extension-vtk
## [1.12.32](https://github.com/OHIF/Viewers/compare/@ohif/extension-vtk@1.12.31...@ohif/extension-vtk@1.12.32) (2022-09-12)
**Note:** Version bump only for package @ohif/extension-vtk
## [1.12.31](https://github.com/OHIF/Viewers/compare/@ohif/extension-vtk@1.12.30...@ohif/extension-vtk@1.12.31) (2022-09-02)
**Note:** Version bump only for package @ohif/extension-vtk
## [1.12.30](https://github.com/OHIF/Viewers/compare/@ohif/extension-vtk@1.12.29...@ohif/extension-vtk@1.12.30) (2022-09-01)
**Note:** Version bump only for package @ohif/extension-vtk
## [1.12.29](https://github.com/OHIF/Viewers/compare/@ohif/extension-vtk@1.12.28...@ohif/extension-vtk@1.12.29) (2022-08-31)
**Note:** Version bump only for package @ohif/extension-vtk
## [1.12.28](https://github.com/OHIF/Viewers/compare/@ohif/extension-vtk@1.12.27...@ohif/extension-vtk@1.12.28) (2022-08-24)
**Note:** Version bump only for package @ohif/extension-vtk
## [1.12.27](https://github.com/OHIF/Viewers/compare/@ohif/extension-vtk@1.12.26...@ohif/extension-vtk@1.12.27) (2022-06-30)
**Note:** Version bump only for package @ohif/extension-vtk
## [1.12.26](https://github.com/OHIF/Viewers/compare/@ohif/extension-vtk@1.12.25...@ohif/extension-vtk@1.12.26) (2022-06-29)
**Note:** Version bump only for package @ohif/extension-vtk
## [1.12.25](https://github.com/OHIF/Viewers/compare/@ohif/extension-vtk@1.12.24...@ohif/extension-vtk@1.12.25) (2022-06-28)
**Note:** Version bump only for package @ohif/extension-vtk
## [1.12.24](https://github.com/OHIF/Viewers/compare/@ohif/extension-vtk@1.12.23...@ohif/extension-vtk@1.12.24) (2022-06-14)
**Note:** Version bump only for package @ohif/extension-vtk
## [1.12.23](https://github.com/OHIF/Viewers/compare/@ohif/extension-vtk@1.12.22...@ohif/extension-vtk@1.12.23) (2022-04-22)
**Note:** Version bump only for package @ohif/extension-vtk
## [1.12.22](https://github.com/OHIF/Viewers/compare/@ohif/extension-vtk@1.12.21...@ohif/extension-vtk@1.12.22) (2022-04-06)
**Note:** Version bump only for package @ohif/extension-vtk
## [1.12.21](https://github.com/OHIF/Viewers/compare/@ohif/extension-vtk@1.12.20...@ohif/extension-vtk@1.12.21) (2022-04-05)
**Note:** Version bump only for package @ohif/extension-vtk
## [1.12.20](https://github.com/OHIF/Viewers/compare/@ohif/extension-vtk@1.12.19...@ohif/extension-vtk@1.12.20) (2022-03-25)
**Note:** Version bump only for package @ohif/extension-vtk
## [1.12.19](https://github.com/OHIF/Viewers/compare/@ohif/extension-vtk@1.12.18...@ohif/extension-vtk@1.12.19) (2022-03-14)
**Note:** Version bump only for package @ohif/extension-vtk
## [1.12.18](https://github.com/OHIF/Viewers/compare/@ohif/extension-vtk@1.12.17...@ohif/extension-vtk@1.12.18) (2022-03-14)
**Note:** Version bump only for package @ohif/extension-vtk
## [1.12.17](https://github.com/OHIF/Viewers/compare/@ohif/extension-vtk@1.12.16...@ohif/extension-vtk@1.12.17) (2022-03-14)
**Note:** Version bump only for package @ohif/extension-vtk
## [1.12.16](https://github.com/OHIF/Viewers/compare/@ohif/extension-vtk@1.12.15...@ohif/extension-vtk@1.12.16) (2022-02-15)
**Note:** Version bump only for package @ohif/extension-vtk
+7 -7
View File
@@ -1,6 +1,6 @@
{
"name": "@ohif/extension-vtk",
"version": "1.12.16",
"version": "1.12.42",
"description": "OHIF extension for VTK.js",
"author": "OHIF",
"license": "MIT",
@@ -34,8 +34,8 @@
"@ohif/ui": "^0.50.0",
"cornerstone-core": "^2.6.1",
"cornerstone-tools": "^6.0.6",
"cornerstone-wado-image-loader": "^4.1.0",
"dcmjs": "0.19.4",
"cornerstone-wado-image-loader": "^4.2.1",
"dcmjs": "0.29.3",
"dicom-parser": "^1.8.11",
"i18next": "^17.0.3",
"i18next-browser-languagedetector": "^3.0.1",
@@ -50,13 +50,13 @@
"dependencies": {
"@babel/runtime": "^7.5.5",
"lodash.throttle": "^4.1.1",
"react-vtkjs-viewport": "^0.14.4"
"react-vtkjs-viewport": "^0.14.5"
},
"devDependencies": {
"@ohif/core": "^2.16.12",
"@ohif/ui": "^1.10.6",
"@ohif/core": "^2.16.35",
"@ohif/ui": "^1.10.11",
"cornerstone-tools": "^6.0.6",
"cornerstone-wado-image-loader": "^4.1.0",
"cornerstone-wado-image-loader": "^4.2.1",
"dicom-parser": "^1.8.11",
"gh-pages": "^2.0.1",
"i18next": "^17.0.3",
+9
View File
@@ -99,6 +99,7 @@
"shader-loader": "^1.3.1",
"start-server-and-test": "^1.10.0",
"style-loader": "^1.0.0",
"styled-components": "^5.3.5",
"stylelint": "^10.1.0",
"stylelint-config-recommended": "^2.2.0",
"stylus": "^0.54.5",
@@ -124,6 +125,14 @@
]
},
"resolutions": {
"handlebars": "4.7.7",
"json-schema": "0.4.0",
"ejs": "3.1.7",
"thenify": "3.3.1",
"parse-url": "8.1.0",
"loader-utils": "1.4.1",
"flat": "5.0.1",
"minimist": "1.2.8",
"**/node-gyp": "8.4.1",
"**/@babel/runtime": "7.5.5"
}
+202
View File
@@ -3,6 +3,208 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [2.16.35](https://github.com/OHIF/Viewers/compare/@ohif/core@2.16.34...@ohif/core@2.16.35) (2022-12-21)
**Note:** Version bump only for package @ohif/core
## [2.16.34](https://github.com/OHIF/Viewers/compare/@ohif/core@2.16.33...@ohif/core@2.16.34) (2022-12-12)
### Bug Fixes
* [#2964](https://github.com/OHIF/Viewers/issues/2964) Reword message for segmentation error loading due to orientation tolerance ([#3017](https://github.com/OHIF/Viewers/issues/3017)) ([597ac11](https://github.com/OHIF/Viewers/commit/597ac11c4daee1b1e14148804551e20611cfef08))
## [2.16.33](https://github.com/OHIF/Viewers/compare/@ohif/core@2.16.32...@ohif/core@2.16.33) (2022-11-12)
### Bug Fixes
* handle missing ReferencedInstanceSequence attribute ([#2786](https://github.com/OHIF/Viewers/issues/2786)) ([4473807](https://github.com/OHIF/Viewers/commit/44738078dbd8dc6b27d2d669e25417e37371f48d))
## [2.16.32](https://github.com/OHIF/Viewers/compare/@ohif/core@2.16.31...@ohif/core@2.16.32) (2022-11-02)
**Note:** Version bump only for package @ohif/core
## [2.16.31](https://github.com/OHIF/Viewers/compare/@ohif/core@2.16.30...@ohif/core@2.16.31) (2022-10-28)
### Bug Fixes
* [#2964](https://github.com/OHIF/Viewers/issues/2964) Update message for segmentation error loading due to orientation tolerance ([#2982](https://github.com/OHIF/Viewers/issues/2982)) ([545161d](https://github.com/OHIF/Viewers/commit/545161d5e8d92bb6652f17dc24a36dac8aa7b3a4))
## [2.16.30](https://github.com/OHIF/Viewers/compare/@ohif/core@2.16.29...@ohif/core@2.16.30) (2022-10-25)
### Bug Fixes
* 2965 Correct Parsing Logic for Qualitative Instance Level SR ([#2972](https://github.com/OHIF/Viewers/issues/2972)) ([f7db74a](https://github.com/OHIF/Viewers/commit/f7db74a84376598065b6fa2c00cd5735415ff651))
## [2.16.29](https://github.com/OHIF/Viewers/compare/@ohif/core@2.16.28...@ohif/core@2.16.29) (2022-09-20)
**Note:** Version bump only for package @ohif/core
## [2.16.28](https://github.com/OHIF/Viewers/compare/@ohif/core@2.16.27...@ohif/core@2.16.28) (2022-09-19)
**Note:** Version bump only for package @ohif/core
## [2.16.27](https://github.com/OHIF/Viewers/compare/@ohif/core@2.16.26...@ohif/core@2.16.27) (2022-09-12)
**Note:** Version bump only for package @ohif/core
## [2.16.26](https://github.com/OHIF/Viewers/compare/@ohif/core@2.16.25...@ohif/core@2.16.26) (2022-09-02)
**Note:** Version bump only for package @ohif/core
## [2.16.25](https://github.com/OHIF/Viewers/compare/@ohif/core@2.16.24...@ohif/core@2.16.25) (2022-09-01)
**Note:** Version bump only for package @ohif/core
## [2.16.24](https://github.com/OHIF/Viewers/compare/@ohif/core@2.16.23...@ohif/core@2.16.24) (2022-08-31)
**Note:** Version bump only for package @ohif/core
## [2.16.23](https://github.com/OHIF/Viewers/compare/@ohif/core@2.16.22...@ohif/core@2.16.23) (2022-08-24)
**Note:** Version bump only for package @ohif/core
## [2.16.22](https://github.com/OHIF/Viewers/compare/@ohif/core@2.16.21...@ohif/core@2.16.22) (2022-06-30)
**Note:** Version bump only for package @ohif/core
## [2.16.21](https://github.com/OHIF/Viewers/compare/@ohif/core@2.16.20...@ohif/core@2.16.21) (2022-06-29)
**Note:** Version bump only for package @ohif/core
## [2.16.20](https://github.com/OHIF/Viewers/compare/@ohif/core@2.16.19...@ohif/core@2.16.20) (2022-06-28)
### Bug Fixes
* Re IDC2797, fix double parsing of SR qualitative annotations ([#2830](https://github.com/OHIF/Viewers/issues/2830)) ([9f813e0](https://github.com/OHIF/Viewers/commit/9f813e0ea08f0aada8efab9ef6228ad90dd1758d))
## [2.16.19](https://github.com/OHIF/Viewers/compare/@ohif/core@2.16.18...@ohif/core@2.16.19) (2022-06-14)
**Note:** Version bump only for package @ohif/core
## [2.16.18](https://github.com/OHIF/Viewers/compare/@ohif/core@2.16.17...@ohif/core@2.16.18) (2022-04-22)
**Note:** Version bump only for package @ohif/core
## [2.16.17](https://github.com/OHIF/Viewers/compare/@ohif/core@2.16.16...@ohif/core@2.16.17) (2022-04-06)
**Note:** Version bump only for package @ohif/core
## [2.16.16](https://github.com/OHIF/Viewers/compare/@ohif/core@2.16.15...@ohif/core@2.16.16) (2022-04-05)
**Note:** Version bump only for package @ohif/core
## [2.16.15](https://github.com/OHIF/Viewers/compare/@ohif/core@2.16.14...@ohif/core@2.16.15) (2022-03-25)
**Note:** Version bump only for package @ohif/core
## [2.16.14](https://github.com/OHIF/Viewers/compare/@ohif/core@2.16.13...@ohif/core@2.16.14) (2022-03-14)
**Note:** Version bump only for package @ohif/core
## [2.16.13](https://github.com/OHIF/Viewers/compare/@ohif/core@2.16.12...@ohif/core@2.16.13) (2022-03-14)
### Bug Fixes
* Update fetchPaletteColorLookupTableData: LUT Entries shall be 0 if the table entries value is 2^16 ([#2395](https://github.com/OHIF/Viewers/issues/2395)) ([0ba796c](https://github.com/OHIF/Viewers/commit/0ba796c73c5254f1bc5ac72c58fd06abf19d7102))
## [2.16.12](https://github.com/OHIF/Viewers/compare/@ohif/core@2.16.11...@ohif/core@2.16.12) (2022-02-15)
**Note:** Version bump only for package @ohif/core
+3 -3
View File
@@ -1,6 +1,6 @@
{
"name": "@ohif/core",
"version": "2.16.12",
"version": "2.16.35",
"description": "Generic business logic for web-based medical imaging applications",
"author": "OHIF Core Team",
"license": "MIT",
@@ -33,13 +33,13 @@
"peerDependencies": {
"cornerstone-core": "^2.6.1",
"cornerstone-tools": "^6.0.6",
"cornerstone-wado-image-loader": "^4.1.0",
"cornerstone-wado-image-loader": "^4.2.1",
"dicom-parser": "^1.8.11"
},
"dependencies": {
"@babel/runtime": "^7.5.5",
"ajv": "^6.10.0",
"dcmjs": "0.19.4",
"dcmjs": "0.29.3",
"dicomweb-client": "^0.8.3",
"immer": "9.0.12",
"isomorphic-base64": "^1.0.2",
@@ -1,4 +1,5 @@
export default {
TEXT: 'TEXT',
POINT: 'POINT',
MULTIPOINT: 'MULTIPOINT',
POLYLINE: 'POLYLINE',
@@ -1,6 +1,5 @@
import { ImageSet } from '../../classes';
import getMeasurements from './utils/getMeasurements';
import getReferencedImagesList from './utils/getReferencedImagesList';
import isRehydratable from './utils/isRehydratable';
import addMeasurement from './utils/addMeasurement';
@@ -8,6 +7,16 @@ const parseSCOORD3D = ({ servicesManager, displaySets }) => {
const { MeasurementService } = servicesManager.services;
const srDisplaySets = displaySets.filter(ds => ds.Modality === 'SR');
const imageDisplaySets = displaySets.filter(
ds =>
ds.Modality !== 'SR' &&
ds.Modality !== 'SEG' &&
ds.Modality !== 'RTSTRUCT'
);
imageDisplaySets.forEach(imageDisplaySet => {
imageDisplaySet.SRLabels = [];
});
srDisplaySets.forEach(srDisplaySet => {
const firstInstance = srDisplaySet.metadata;
@@ -17,8 +26,7 @@ const parseSCOORD3D = ({ servicesManager, displaySets }) => {
const { ContentSequence } = firstInstance;
srDisplaySet.referencedImages = getReferencedImagesList(ContentSequence);
srDisplaySet.measurements = getMeasurements(ContentSequence, srDisplaySet);
srDisplaySet.measurements = getMeasurements(ContentSequence);
const mappings = MeasurementService.getSourceMappings(
'CornerstoneTools',
'4'
@@ -28,13 +36,6 @@ const parseSCOORD3D = ({ servicesManager, displaySets }) => {
srDisplaySet.isRehydratable = isRehydratable(srDisplaySet, mappings);
srDisplaySet.isLoaded = true;
const imageDisplaySets = displaySets.filter(
ds =>
ds.Modality !== 'SR' &&
ds.Modality !== 'SEG' &&
ds.Modality !== 'RTSTRUCT' &&
ds.Modality !== 'RTDOSE'
);
imageDisplaySets.forEach(imageDisplaySet => {
// Check currently added displaySets and add measurements if the sources exist.
checkIfCanAddMeasurementsToDisplaySet(srDisplaySet, imageDisplaySet);
@@ -127,10 +128,10 @@ const checkIfCanAddMeasurementsToDisplaySet = (
const imageIds = images.map(i => i.getImageId());
const SOPInstanceUIDs = images.map(i => i.SOPInstanceUID);
const colors = new Map();
measurements.forEach(measurement => {
const { coords } = measurement;
coords.forEach(coord => {
coords.forEach((coord, index) => {
if (coord.ReferencedSOPSequence !== undefined) {
const imageIndex = SOPInstanceUIDs.findIndex(
SOPInstanceUID =>
@@ -138,14 +139,50 @@ const checkIfCanAddMeasurementsToDisplaySet = (
coord.ReferencedSOPSequence.ReferencedSOPInstanceUID
);
if (imageIndex > -1) {
if (!srDisplaySet.referencedDisplaySets.includes(imageDisplaySet)) {
srDisplaySet.referencedDisplaySets.push(imageDisplaySet);
}
const imageId = imageIds[imageIndex];
const imageMetadata = images[imageIndex].getData().metadata;
addMeasurement(
measurement,
imageId,
imageMetadata,
imageDisplaySet.displaySetInstanceUID
);
if (coord.GraphicType === 'TEXT') {
const key =
measurement.labels[index].label + measurement.labels[index].value;
let color = colors.get(key);
if (!color) {
// random dark color
color =
'hsla(' + Math.floor(Math.random() * 360) + ', 70%, 30%, 1)';
colors.set(key, color);
}
measurement.labels[index].color = color;
measurement.isSRText = true;
measurement.labels[index].visible = true;
imageDisplaySet.SRLabels.push({
ReferencedSOPInstanceUID:
coord.ReferencedSOPSequence.ReferencedSOPInstanceUID,
labels: measurement.labels[index],
});
if (index === 0) {
addMeasurement(
measurement,
imageId,
imageMetadata,
imageDisplaySet.displaySetInstanceUID
);
}
} else {
addMeasurement(
measurement,
imageId,
imageMetadata,
imageDisplaySet.displaySetInstanceUID
);
}
}
}
});
@@ -26,8 +26,10 @@ export default function addMeasurement(
const measurementData = {
TrackingUniqueIdentifier: measurement.TrackingUniqueIdentifier,
TrackingIdentifier: measurement.TrackingIdentifier,
renderableData: {},
labels: measurement.labels,
isSRText: measurement.isSRText,
};
measurement.coords.forEach(coord => {
@@ -1,22 +1,14 @@
const getCoordsFromSCOORDOrSCOORD3D = (graphicItem, displaySet) => {
const { ValueType, RelationshipType, GraphicType, GraphicData } = graphicItem;
// if (RelationshipType !== RELATIONSHIP_TYPE.INFERRED_FROM) {
// console.warn(
// `Relationshiptype === ${RelationshipType}. Cannot deal with NON TID-1400 SCOORD group with RelationshipType !== "INFERRED FROM."`
// );
// return;
// }
const getCoordsFromSCOORDOrSCOORD3D = graphicItem => {
const { ValueType, GraphicType, GraphicData } = graphicItem;
const coords = { ValueType, GraphicType, GraphicData };
// ContentSequence has length of 1 as RelationshipType === 'INFERRED FROM'
if (ValueType === 'SCOORD') {
const { ReferencedSOPSequence } = graphicItem.ContentSequence;
coords.ReferencedSOPSequence = ReferencedSOPSequence;
} else if (ValueType === 'SCOORD3D') {
if (graphicItem.ReferencedFrameOfReferenceUID) {
coords.ReferencedFrameOfReferenceSequence = graphicItem.ReferencedFrameOfReferenceUID;
coords.ReferencedFrameOfReferenceSequence =
graphicItem.ReferencedFrameOfReferenceUID;
} else if (graphicItem.ContentSequence) {
const {
ReferencedFrameOfReferenceSequence,
@@ -3,10 +3,7 @@ import getSequenceAsArray from './getSequenceAsArray';
import getMergedContentSequencesByTrackingUniqueIdentifiers from './getMergedContentSequencesByTrackingUniqueIdentifiers';
import processMeasurement from './processMeasurement';
const getMeasurements = (
ImagingMeasurementReportContentSequence,
displaySet
) => {
const getMeasurements = ImagingMeasurementReportContentSequence => {
const ImagingMeasurements = ImagingMeasurementReportContentSequence.find(
item =>
item.ConceptNameCodeSequence.CodeValue ===
@@ -21,25 +18,19 @@ const getMeasurements = (
CodeNameCodeSequenceValues.MeasurementGroup
);
const mergedContentSequencesByTrackingUniqueIdentifiers = getMergedContentSequencesByTrackingUniqueIdentifiers(
/* const mergedContentSequencesByTrackingUniqueIdentifiers = getMergedContentSequencesByTrackingUniqueIdentifiers(
MeasurementGroups
);
);*/
let measurements = [];
Object.keys(mergedContentSequencesByTrackingUniqueIdentifiers).forEach(
trackingUniqueIdentifier => {
const mergedContentSequence =
mergedContentSequencesByTrackingUniqueIdentifiers[
trackingUniqueIdentifier
];
const measurement = processMeasurement(mergedContentSequence, displaySet);
if (measurement) {
measurements.push(measurement);
}
MeasurementGroups.forEach(MeasurementGroup => {
const contentSequence = MeasurementGroup.ContentSequence;
const measurement = processMeasurement(contentSequence);
if (measurement) {
measurements.push(measurement);
}
);
});
return measurements;
};
@@ -1,43 +0,0 @@
import getSequenceAsArray from './getSequenceAsArray';
import { CodeNameCodeSequenceValues } from '../enums';
const getReferencedImagesList = ImagingMeasurementReportContentSequence => {
const referencedImages = [];
const ImageLibrary = ImagingMeasurementReportContentSequence.find(
item =>
item.ConceptNameCodeSequence.CodeValue ===
CodeNameCodeSequenceValues.ImageLibrary
);
if (!ImageLibrary.ContentSequence) {
return referencedImages;
}
const ImageLibraryGroup = getSequenceAsArray(
ImageLibrary.ContentSequence
).find(
item =>
item.ConceptNameCodeSequence.CodeValue ===
CodeNameCodeSequenceValues.ImageLibraryGroup
);
getSequenceAsArray(ImageLibraryGroup.ContentSequence).forEach(item => {
const { ReferencedSOPSequence } = item;
if (ReferencedSOPSequence) {
const {
ReferencedSOPClassUID,
ReferencedSOPInstanceUID,
} = ReferencedSOPSequence;
referencedImages.push({
ReferencedSOPClassUID,
ReferencedSOPInstanceUID,
});
}
});
return referencedImages;
};
export default getReferencedImagesList;
@@ -57,6 +57,10 @@ const getRenderableData = (
// https://dicom.innolitics.com/ciods/procedure-log/sr-document-content/00700023
switch (GraphicType) {
case SCOORD_TYPES.TEXT:
renderableData = [{ x: GraphicData[0], y: GraphicData[1] }];
break;
case SCOORD_TYPES.POINT:
renderableData = [];
@@ -1,16 +1,16 @@
import processTID1410Measurement from './processTID1410Measurement';
import processNonGeometricallyDefinedMeasurement from './processNonGeometricallyDefinedMeasurement';
const processMeasurement = (mergedContentSequence, displaySet) => {
const processMeasurement = contentSequence => {
if (
mergedContentSequence.some(
contentSequence.some(
group => group.ValueType === 'SCOORD' || group.ValueType === 'SCOORD3D'
)
) {
return processTID1410Measurement(mergedContentSequence, displaySet);
return processTID1410Measurement(contentSequence);
}
return processNonGeometricallyDefinedMeasurement(mergedContentSequence);
return processNonGeometricallyDefinedMeasurement(contentSequence);
};
export default processMeasurement;
@@ -1,31 +1,40 @@
import getLabelFromMeasuredValueSequence from './getLabelFromMeasuredValueSequence';
import getCoordsFromSCOORDOrSCOORD3D from './getCoordsFromSCOORDOrSCOORD3D';
import { CodeNameCodeSequenceValues, CodingSchemeDesignators } from '../enums';
import SCOORD_TYPES from '../constants/scoordTypes';
const CORNERSTONE_FREETEXT_CODE_VALUE = 'CORNERSTONEFREETEXT';
const processNonGeometricallyDefinedMeasurement = mergedContentSequence => {
const NUMContentItems = mergedContentSequence.filter(
const processNonGeometricallyDefinedMeasurement = contentSequence => {
const NUMContentItems = contentSequence.filter(
group => group.ValueType === 'NUM'
);
const UIDREFContentItem = mergedContentSequence.find(
const CODEContentItems = contentSequence.filter(
group => group.ValueType === 'CODE'
);
const UIDREFContentItem = contentSequence.find(
group => group.ValueType === 'UIDREF'
);
const TrackingIdentifierContentItem = mergedContentSequence.find(
const IMAGEContentItem = contentSequence.find(
group => group.ValueType === 'IMAGE'
);
const TrackingIdentifierContentItem = contentSequence.find(
item =>
item.ConceptNameCodeSequence.CodeValue ===
CodeNameCodeSequenceValues.TrackingIdentifier
);
const Finding = mergedContentSequence.find(
const Finding = contentSequence.find(
item =>
item.ConceptNameCodeSequence.CodeValue ===
CodeNameCodeSequenceValues.Finding
);
const FindingSites = mergedContentSequence.filter(
const FindingSites = contentSequence.filter(
item =>
item.ConceptNameCodeSequence.CodingSchemeDesignator ===
CodingSchemeDesignators.SRT &&
@@ -111,6 +120,37 @@ const processNonGeometricallyDefinedMeasurement = mergedContentSequence => {
}
});
if (NUMContentItems.length === 0 && IMAGEContentItem) {
CODEContentItems.forEach(item => {
const { ConceptCodeSequence, ConceptNameCodeSequence } = item;
if (!ConceptCodeSequence || !ConceptNameCodeSequence) {
console.warn(`Graphic missing, skipping annotation.`);
return;
}
const GraphicData = [0, 0];
const GraphicType = SCOORD_TYPES.TEXT;
const { ValueType } = item;
const ReferencedSOPSequence = IMAGEContentItem.ReferencedSOPSequence;
const coord = {
ValueType,
GraphicType,
GraphicData,
ReferencedSOPSequence,
};
measurement.coords.push(coord);
measurement.labels.push({
label: ConceptNameCodeSequence.CodeMeaning,
labelCodingSchemeDesignator:
ConceptNameCodeSequence.CodingSchemeDesignator,
value: ConceptCodeSequence.CodeMeaning,
valueCodingSchemeDesignator: ConceptCodeSequence.CodingSchemeDesignator,
});
});
}
return measurement;
};
@@ -5,14 +5,14 @@ import { RELATIONSHIP_TYPE, CodeNameCodeSequenceValues } from '../enums';
/**
* TID 1410 Planar ROI Measurements and Qualitative Evaluations.
*
* @param {*} mergedContentSequence
* @param {*} contentSequence
* @returns
*/
const processTID1410Measurement = (mergedContentSequence, displaySet) => {
const processTID1410Measurement = contentSequence => {
// Need to deal with TID 1410 style measurements, which will have a SCOORD or SCOORD3D at the top level,
// And non-geometric representations where each NUM has "INFERRED FROM" SCOORD/SCOORD3D
const graphicItem = mergedContentSequence.find(
const graphicItem = contentSequence.find(
group => group.ValueType === 'SCOORD' || group.ValueType === 'SCOORD3D'
);
@@ -23,24 +23,24 @@ const processTID1410Measurement = (mergedContentSequence, displaySet) => {
return;
}
const UIDREFContentItem = mergedContentSequence.find(
const UIDREFContentItem = contentSequence.find(
group => group.ValueType === 'UIDREF'
);
const TrackingIdentifierContentItem = mergedContentSequence.find(
const TrackingIdentifierContentItem = contentSequence.find(
item =>
item.ConceptNameCodeSequence.CodeValue ===
CodeNameCodeSequenceValues.TrackingIdentifier
);
const NUMContentItems = mergedContentSequence.filter(
const NUMContentItems = contentSequence.filter(
group => group.ValueType === 'NUM'
);
const measurement = {
loaded: false,
labels: [],
coords: [getCoordsFromSCOORDOrSCOORD3D(graphicItem, displaySet)],
coords: [getCoordsFromSCOORDOrSCOORD3D(graphicItem)],
TrackingUniqueIdentifier: UIDREFContentItem.UID,
TrackingIdentifier: TrackingIdentifierContentItem.TextValue,
};
@@ -21,16 +21,32 @@ const parseDicomStructuredReport = (
displaySets,
external
) => {
if (external && external.servicesManager) {
parseSCOORD3D({ servicesManager: external.servicesManager, displaySets });
}
// Get the dicom data as an Object
const dicomData = dcmjs.data.DicomMessage.readFile(part10SRArrayBuffer);
const dataset = dcmjs.data.DicomMetaDictionary.naturalizeDataset(
dicomData.dict
);
const {
LoggerService,
UINotificationService,
} = external.servicesManager.services;
if (external && external.servicesManager) {
try {
parseSCOORD3D({ servicesManager: external.servicesManager, displaySets });
} catch (error) {
const seriesDescription = dataset.SeriesDescription || '';
LoggerService.error({ error, message: error.message });
UINotificationService.show({
title: `Failed to parse ${seriesDescription} SR display set`,
message: error.message,
type: 'error',
autoClose: false,
});
return;
}
}
const { MeasurementReport } = dcmjs.adapters.Cornerstone;
let storedMeasurementByToolType;
@@ -38,11 +54,12 @@ const parseDicomStructuredReport = (
storedMeasurementByToolType = MeasurementReport.generateToolState(dataset);
} catch (error) {
const seriesDescription = dataset.SeriesDescription || '';
LogManager.publish(LogManager.EVENTS.OnLog, {
LoggerService.error({ error, message: error.message });
UINotificationService.show({
title: `Failed to parse ${seriesDescription} measurement report`,
type: 'warning',
message: error.message || '',
notify: true,
message: error.message,
type: 'error',
autoClose: false,
});
return;
}
+2 -1
View File
@@ -67,12 +67,13 @@ export class HotkeysManager {
UINotificationService,
LoggerService,
} = this._servicesManager.services;
const message = 'Erro while setting hotkeys';
const message = 'Error while setting hotkeys';
LoggerService.error({ error, message });
UINotificationService.show({
title: 'Hotkeys Manager',
message,
type: 'error',
autoClose: false,
});
}
}
@@ -401,7 +401,7 @@ class StackLoadingListener extends BaseLoadingListener {
const totalFramesCount = this.stack.imageIds.length;
const loadedFramesCount = this.loadedCount;
const loadingFramesCount = totalFramesCount - loadedFramesCount;
const percentComplete = Math.round(
const percentComplete = Math.ceil(
(loadedFramesCount / totalFramesCount) * 100
);
const progressId = this._getProgressId();
@@ -469,8 +469,8 @@ class StudyLoadingListener {
// TODO: Make this work for plugins
if (!stack) {
console.warn('Skipping adding displaySet to StudyLoadingListener');
console.warn(displaySet);
//console.warn('Skipping adding displaySet to StudyLoadingListener');
//console.warn(displaySet);
return;
}
@@ -3,12 +3,12 @@ import DICOMWeb from './../../DICOMWeb';
import ImageSet from './../ImageSet';
import { InstanceMetadata } from './InstanceMetadata';
import { Metadata } from './Metadata';
import OHIFError from '../OHIFError';
import { SeriesMetadata } from './SeriesMetadata';
// - createStacks
import { api } from 'dicomweb-client';
// - createStacks
import { isImage } from '../../utils/isImage';
import { naturalizeSOPClassUID } from '../../utils/naturalizeSOPClassUID';
import {
isDisplaySetReconstructable,
isSpacingUniform,
@@ -169,8 +169,12 @@ class StudyMetadata extends Metadata {
!isImage(instance.getTagValue('SOPClassUID')) &&
!instance.getTagValue('Rows')
) {
// we set an empty display and we add a isModalitySupported variable to
// print a warning that the modality is not supported in the thumbnail.
// we set an empty display and we add a isSOPClassUIDSupported variable to
// print a warning that the series is not supported in the thumbnail.
// SOPClassUIDNaturalized is human readable name, since for non image series,
// we could have a mismatch between the SOPClassUID and the Modality.
// For example, in the Parametric map IOD Modality is expected to match
// the value for the series used to generate Parametric map, and there is no "PM" modality.
const displaySet = new ImageSet([]);
const seriesData = series.getData();
displaySet.setAttributes({
@@ -188,7 +192,10 @@ class StudyMetadata extends Metadata {
InstanceNumber: instance.getTagValue('InstanceNumber'), // Include the instance number
AcquisitionDatetime: instance.getTagValue('AcquisitionDateTime'), // Include the acquisition datetime
isReconstructable: false,
isModalitySupported: false,
isSOPClassUIDSupported: false,
SOPClassUIDNaturalized: naturalizeSOPClassUID(
instance.getTagValue('SOPClassUID')
),
metadata: instance.getData().metadata,
});
@@ -268,6 +275,8 @@ class StudyMetadata extends Metadata {
const otherDisplaySets = allDisplaySets.filter(
ds =>
ds &&
derivatedDisplaySet &&
ds.displaySetInstanceUID !== derivatedDisplaySet.displaySetInstanceUID
);
@@ -333,10 +342,38 @@ class StudyMetadata extends Metadata {
if (referencedSeriesInstanceUID) {
filteredDerivedDisplaySets = filteredDerivedDisplaySets.filter(
displaySet => {
return (
StudyMetadata.getReferencedDisplaySet(displaySet, [this])
.SeriesInstanceUID === referencedSeriesInstanceUID
const referencedDisplaySet = StudyMetadata.getReferencedDisplaySet(
displaySet,
[this]
);
if (referencedDisplaySet) {
return (
referencedDisplaySet.SeriesInstanceUID ===
referencedSeriesInstanceUID
);
} else {
if (
!displaySet.referencedDisplaySets ||
displaySet.referencedDisplaySets.length === 0
) {
return false;
}
const filteredReferencedDisplaySets = displaySet.referencedDisplaySets.filter(
referencedDisplaySet =>
referencedDisplaySet.SeriesInstanceUID ===
referencedSeriesInstanceUID
);
if (
filteredReferencedDisplaySets &&
filteredReferencedDisplaySets.length !== 0
) {
return true;
}
return false;
}
}
);
}
@@ -923,7 +960,7 @@ const makeDisplaySet = (series, instances) => {
: displayReconstructableInfo.reconstructionIssues;
}
imageSet.isModalitySupported = true;
imageSet.isSOPClassUIDSupported = true;
return imageSet;
};
@@ -6,7 +6,8 @@ export const dicomSRDisplayTool = {
options: {
measurementTable: {
displayFunction: data => {
return `(SR) ${data.lesionNamingNumber ||
return `(SR) ${data.TrackingIdentifier ||
data.lesionNamingNumber ||
data.measurementNumber ||
data.text ||
''}`;
@@ -420,6 +420,10 @@ class MeasurementService {
throw new Error('No source definition provided.');
}
if (definition == 'stack' || definition == 'stackPrefetch') {
return;
}
const sourceInfo = this._getSourceInfo(source);
if (!this._sourceHasMappings(source)) {
@@ -19,17 +19,4 @@ describe('retrieveStudyMetadata.js', () => {
expect(callWithNoStudyInstanceUID).toThrow(Error);
});
it('caches and returns the same promise for identical studyInstanceUIDs', () => {
const firstPromise = retrieveStudyMetadata(
fakeDicomWebServer,
'fake-study-instance-uid'
);
const secondPromise = retrieveStudyMetadata(
fakeDicomWebServer,
'fake-study-instance-uid'
);
expect(firstPromise).toBe(secondPromise);
});
});
@@ -21,16 +21,18 @@ const getReferencedSeriesSequence = instance => {
const referencedInstanceSequenceRaw = referencedSeries['0008114A'];
const referencedInstanceSequence = [];
referencedInstanceSequenceRaw.Value.forEach(referencedInstance => {
referencedInstanceSequence.push({
referencedSOPClassUID: DICOMWeb.getString(
referencedInstance['00081150']
),
referencedSOPInstanceUID: DICOMWeb.getString(
referencedInstance['00081155']
),
if (referencedInstanceSequenceRaw) {
referencedInstanceSequenceRaw.Value.forEach(referencedInstance => {
referencedInstanceSequence.push({
referencedSOPClassUID: DICOMWeb.getString(
referencedInstance['00081150']
),
referencedSOPInstanceUID: DICOMWeb.getString(
referencedInstance['00081155']
),
});
});
});
}
referencedSeriesSequence.push({
referencedSeriesInstanceUID,
@@ -102,6 +102,35 @@ async function makeSOPInstance(server, study, instance) {
SOPInstanceUID,
} = naturalizedInstance;
const validate = string => {
let rgx = /[^.0-9]+/g;
return string.match(rgx);
};
if (StudyInstanceUID === undefined || validate(StudyInstanceUID)) {
const error =
'makeSOPInstance: StudyInstanceUID is not conforming with the UID (DICOM UI VR) character repertoire, skipping SOPInstance.';
console.error(error);
return;
}
if (SeriesInstanceUID === undefined || validate(SeriesInstanceUID)) {
const error =
'makeSOPInstance: SeriesInstanceUID is not conforming with the UID (DICOM UI VR) character repertoire, skipping SOPInstance.';
console.error(error);
return;
}
if (SOPInstanceUID === undefined || validate(SOPInstanceUID)) {
const error =
'makeSOPInstance: SOPInstanceUID is not conforming with the UID (DICOM UI VR) character repertoire, skipping SOPInstance.';
console.error(error);
return;
}
let series = study.seriesMap[SeriesInstanceUID];
if (!series) {
+2 -2
View File
@@ -25,7 +25,7 @@ function createAndAddStack(stackMap, study, displaySet, stackUpdatedCallbacks) {
const imageIds = [];
let imageId;
displaySet.images.forEach((instance, imageIndex) => {
images.forEach((instance, imageIndex) => {
const image = instance.getData();
const metaData = {
instance: image, // in this context, instance will be the data of the InstanceMetadata object...
@@ -35,7 +35,7 @@ function createAndAddStack(stackMap, study, displaySet, stackUpdatedCallbacks) {
imageIndex: imageIndex + 1,
};
const naturalizedInstance = instance.getData().metadata;
const naturalizedInstance = image.metadata;
const NumberOfFrames = naturalizedInstance.NumberOfFrames;
if (NumberOfFrames > 1) {
@@ -49,7 +49,12 @@ import studyMetadataManager from './studyMetadataManager';
* @param {object} snackbar
* @returns void
*/
async function loadAndCacheDerivedDisplaySets(referencedDisplaySet, studies, logger, snackbar) {
async function loadAndCacheDerivedDisplaySets(
referencedDisplaySet,
studies,
logger,
snackbar
) {
const { StudyInstanceUID, SeriesInstanceUID } = referencedDisplaySet;
const promises = [];
const studyMetadata = studyMetadataManager.get(StudyInstanceUID);
@@ -80,60 +85,119 @@ async function loadAndCacheDerivedDisplaySets(referencedDisplaySet, studies, log
});
// For each type, see if any are loaded, if not load the most recent.
await Promise.all(Object.keys(displaySetsPerModality).map(async (key) => {
const displaySets = displaySetsPerModality[key];
await Promise.all(
Object.keys(displaySetsPerModality).map(async key => {
const displaySets = displaySetsPerModality[key];
const isLoaded = displaySets.some(displaySet => displaySet.isLoaded);
if (isLoaded) {
return;
}
if (displaySets.some(displaySet => displaySet.loadError)) {
return;
}
// find most recent and load it.
let recentDateTime = 0;
let recentDisplaySet = displaySets[0];
displaySets.forEach(displaySet => {
const dateTime = Number(
`${displaySet.SeriesDate}${displaySet.SeriesTime}`
);
if (dateTime > recentDateTime) {
recentDateTime = dateTime;
recentDisplaySet = displaySet;
const isLoaded = displaySets.some(displaySet => displaySet.isLoaded);
if (isLoaded) {
return;
}
});
try {
if (recentDisplaySet.hasOwnProperty('getSourceDisplaySet') &&
typeof recentDisplaySet.getSourceDisplaySet === 'function') {
await recentDisplaySet.getSourceDisplaySet(studies);
} else {
await recentDisplaySet.load(referencedDisplaySet, studies);
if (displaySets.some(displaySet => displaySet.loadError)) {
return;
}
} catch (error) {
recentDisplaySet.isLoaded = false;
recentDisplaySet.loadError = true;
logger.error({ error, message: error.message });
snackbar.show({
title: 'Error loading derived display set:',
message: error.message,
type: 'error',
error,
autoClose: false,
// find most recent and load it.
let recentDateTime = 0;
let recentDisplaySet = displaySets[0];
displaySets.forEach(displaySet => {
const dateTime = Number(
`${displaySet.SeriesDate}${displaySet.SeriesTime}`
);
if (dateTime > recentDateTime) {
recentDateTime = dateTime;
recentDisplaySet = displaySet;
}
});
}
}));
try {
if (
recentDisplaySet.hasOwnProperty('getSourceDisplaySet') &&
typeof recentDisplaySet.getSourceDisplaySet === 'function'
) {
if (recentDisplaySet.Modality === 'SEG' && logger) {
const onDisplaySetLoadFailureHandler = error => {
const message =
error.message.includes('orthogonal') ||
error.message.includes('oblique')
? 'The segmentation has been detected as non coplanar,\
If you really think it is coplanar,\
please adjust the tolerance in the segmentation panel settings (at your own peril!)'
: error.message;
logger.error({ error, message });
snackbar.show({
title: 'DICOM Segmentation Loader',
message,
type: 'error',
autoClose: false,
});
};
let activatedLabelmapIndex = -1;
while (activatedLabelmapIndex == -1) {
const {
referencedDisplaySet,
activatedLabelmapPromise,
} = await recentDisplaySet.getSourceDisplaySet(
studies,
true,
onDisplaySetLoadFailureHandler
);
activatedLabelmapIndex = await activatedLabelmapPromise;
const selectionFired = new CustomEvent(
'extensiondicomsegmentationsegselected',
{
detail: { activatedLabelmapIndex: activatedLabelmapIndex },
}
);
document.dispatchEvent(selectionFired);
const lastDateTime = Number(
`${recentDisplaySet.SeriesDate}${recentDisplaySet.SeriesTime}`
);
recentDateTime = 0;
displaySets.forEach(displaySet => {
const dateTime = Number(
`${displaySet.SeriesDate}${displaySet.SeriesTime}`
);
if (dateTime > recentDateTime && dateTime < lastDateTime) {
recentDateTime = dateTime;
recentDisplaySet = displaySet;
}
});
}
} else {
await recentDisplaySet.getSourceDisplaySet(studies);
}
} else {
await recentDisplaySet.load(referencedDisplaySet, studies);
}
} catch (error) {
recentDisplaySet.isLoaded = false;
recentDisplaySet.loadError = true;
logger.error({ error, message: error.message });
snackbar.show({
title: 'Error loading derived display set:',
message: error.message,
type: 'error',
error,
autoClose: false,
});
}
})
);
/*
* TODO: Improve the way we notify parts of the app
* that depends on derived display sets to be loaded.
* (Implement pubsub for better tracking of derived display sets)
*/
* TODO: Improve the way we notify parts of the app
* that depends on derived display sets to be loaded.
* (Implement pubsub for better tracking of derived display sets)
*/
const event = new CustomEvent('deriveddisplaysetsloadedandcached');
document.dispatchEvent(event);
};
}
export default loadAndCacheDerivedDisplaySets;
@@ -113,7 +113,7 @@ const _paletteColorCache = {
};
function _getPaletteColor(server, paletteColorLookupTableData, lutDescriptor) {
const numLutEntries = lutDescriptor[0];
const numLutEntries = lutDescriptor[0] ? lutDescriptor[0] : 65536;
const bits = lutDescriptor[2];
const arrayBufferToPaletteColorLUT = arraybuffer => {
@@ -0,0 +1,200 @@
import { sopClassDictionary } from './sopClassDictionary';
import { isImage } from './isImage';
/**
* Naturalize SOP Class UID which do not have image data
* @param {string} SOPClassUID - SOP Class UID to be converted
* @returns {string} - human readable name
*/
export const naturalizeSOPClassUID = SOPClassUID => {
let naturalizedName = '';
if (!SOPClassUID) return naturalizedName;
if (!isImage) return naturalizedName;
if (sopClassDictionary.MRSpectroscopyStorage === SOPClassUID) {
naturalizedName = 'MRSpectroscopy';
} else if (sopClassDictionary.EnhancedUSVolumeStorage === SOPClassUID) {
naturalizedName = 'EnhancedUSVolume';
} else if (sopClassDictionary.Sop12LeadECGWaveformStorage === SOPClassUID) {
naturalizedName = 'Sop12LeadECGWaveform';
} else if (sopClassDictionary.GeneralECGWaveformStorage === SOPClassUID) {
naturalizedName = 'GeneralECGWaveform';
} else if (sopClassDictionary.AmbulatoryECGWaveformStorage === SOPClassUID) {
naturalizedName = 'AECAmbulatoryECGWaveformGW';
} else if (sopClassDictionary.HemodynamicWaveformStorage === SOPClassUID) {
naturalizedName = 'HemodynamicWaveform';
} else if (
sopClassDictionary.CardiacElectrophysiologyWaveformStorage === SOPClassUID
) {
naturalizedName = 'CardiacElectrophysiologyWaveform';
} else if (
sopClassDictionary.BasicVoiceAudioWaveformStorage === SOPClassUID
) {
naturalizedName = 'BasicVoiceAudioWaveform';
} else if (sopClassDictionary.GeneralAudioWaveformStorage === SOPClassUID) {
naturalizedName = 'GGeneralAudioWaveformAW';
} else if (sopClassDictionary.ArterialPulseWaveformStorage === SOPClassUID) {
naturalizedName = 'APArterialPulseWaveformW';
} else if (sopClassDictionary.RespiratoryWaveformStorage === SOPClassUID) {
naturalizedName = 'RespiratoryWaveform';
} else if (
sopClassDictionary.GrayscaleSoftcopyPresentationStateStorage === SOPClassUID
) {
naturalizedName = 'GrayscaleSoftcopyPresentationState';
} else if (
sopClassDictionary.ColorSoftcopyPresentationStateStorage === SOPClassUID
) {
naturalizedName = 'ColorSoftcopyPresentationState';
} else if (
sopClassDictionary.PseudoColorSoftcopyPresentationStateStorage ===
SOPClassUID
) {
naturalizedName = 'PseudoColorSoftcopyPresentationState';
} else if (
sopClassDictionary.BlendingSoftcopyPresentationStateStorage === SOPClassUID
) {
naturalizedName = 'BlendingSoftcopyPresentationState';
} else if (
sopClassDictionary.XAXRFGrayscaleSoftcopyPresentationStateStorage ===
SOPClassUID
) {
naturalizedName = 'XAXRFGrayscaleSoftcopyPresentationState';
} else if (sopClassDictionary.RawDataStorage === SOPClassUID) {
naturalizedName = 'RawData';
} else if (sopClassDictionary.SpatialRegistrationStorage === SOPClassUID) {
naturalizedName = 'SpatialRegistration';
} else if (sopClassDictionary.SpatialFiducialsStorage === SOPClassUID) {
naturalizedName = 'SpatialFiducials';
} else if (
sopClassDictionary.DeformableSpatialRegistrationStorage === SOPClassUID
) {
naturalizedName = 'DeformableSpatialRegistration';
} else if (sopClassDictionary.SegmentationStorage === SOPClassUID) {
naturalizedName = 'SEG';
} else if (sopClassDictionary.SurfaceSegmentationStorage === SOPClassUID) {
naturalizedName = 'SurfaceSEG';
} else if (sopClassDictionary.RealWorldValueMappingStorage === SOPClassUID) {
naturalizedName = 'RealWorldValueMapping';
} else if (sopClassDictionary.SurfaceScanMeshStorage === SOPClassUID) {
naturalizedName = 'SurfaceScanMesh';
} else if (sopClassDictionary.SurfaceScanPointCloudStorage === SOPClassUID) {
naturalizedName = 'SurfaceScanPointCloud';
} else if (
sopClassDictionary.StereometricRelationshipStorage === SOPClassUID
) {
naturalizedName = 'StereometricRelationship';
} else if (sopClassDictionary.LensometryMeasurementsStorage === SOPClassUID) {
naturalizedName = 'LensometryMeasurements';
} else if (
sopClassDictionary.AutorefractionMeasurementsStorage === SOPClassUID
) {
naturalizedName = 'AutorefractionMeasurements';
} else if (
sopClassDictionary.KeratometryMeasurementsStorage === SOPClassUID
) {
naturalizedName = 'KeratometryMeasurements';
} else if (
sopClassDictionary.SubjectiveRefractionMeasurementsStorage === SOPClassUID
) {
naturalizedName = 'SubjectiveRefractionMeasurements';
} else if (
sopClassDictionary.VisualAcuityMeasurementsStorage === SOPClassUID
) {
naturalizedName = 'VisualAcuityMeasurements';
} else if (
sopClassDictionary.SpectaclePrescriptionReportStorage === SOPClassUID
) {
naturalizedName = 'SpectaclePrescriptionReport';
} else if (
sopClassDictionary.OphthalmicAxialMeasurementsStorage === SOPClassUID
) {
naturalizedName = 'OphthalmicAxialMeasurements';
} else if (
sopClassDictionary.IntraocularLensCalculationsStorage === SOPClassUID
) {
naturalizedName = 'IntraocularLensCalculations';
} else if (
sopClassDictionary.MacularGridThicknessandVolumeReport === SOPClassUID
) {
naturalizedName = 'MacularGridThicknessandVolume';
} else if (
sopClassDictionary.OphthalmicVisualFieldStaticPerimetryMeasurementsStorage ===
SOPClassUID
) {
naturalizedName = 'OphthalmicVisualFieldStaticPerimetryMeasurements';
} else if (sopClassDictionary.OphthalmicThicknessMapStorage === SOPClassUID) {
naturalizedName = 'OphthalmicThicknessMap';
} else if (sopClassDictionary.CornealTopographyMapStorage === SOPClassUID) {
naturalizedName = 'CornealTopographyMap';
} else if (sopClassDictionary.BasicTextSR === SOPClassUID) {
naturalizedName = 'BasicTextSR';
} else if (sopClassDictionary.EnhancedSR === SOPClassUID) {
naturalizedName = 'EnhancedSR';
} else if (sopClassDictionary.ComprehensiveSR === SOPClassUID) {
naturalizedName = 'ComprehensiveSR';
} else if (sopClassDictionary.Comprehensive3DSR === SOPClassUID) {
naturalizedName = 'Comprehensive3DSR';
} else if (sopClassDictionary.ProcedureLog === SOPClassUID) {
naturalizedName = 'ProcedureLog';
} else if (sopClassDictionary.MammographyCADSR === SOPClassUID) {
naturalizedName = 'MammographyCADSR';
} else if (sopClassDictionary.KeyObjectSelection === SOPClassUID) {
naturalizedName = 'KeyObject';
} else if (sopClassDictionary.ChestCADSR === SOPClassUID) {
naturalizedName = 'ChestCADSR';
} else if (sopClassDictionary.XRayRadiationDoseSR === SOPClassUID) {
naturalizedName = 'XRayRadiationDoseSR';
} else if (
sopClassDictionary.RadiopharmaceuticalRadiationDoseSR === SOPClassUID
) {
naturalizedName = 'RadiopharmaceuticalRadiationDoseSR';
} else if (sopClassDictionary.ColonCADSR === SOPClassUID) {
naturalizedName = 'ColonCADSR';
} else if (
sopClassDictionary.ImplantationPlanSRDocumentStorage === SOPClassUID
) {
naturalizedName = 'ImplantationPlanSRDocument';
} else if (sopClassDictionary.EncapsulatedPDFStorage === SOPClassUID) {
naturalizedName = 'EncapsulatedPDF';
} else if (sopClassDictionary.EncapsulatedCDAStorage === SOPClassUID) {
naturalizedName = 'EncapsulatedCDA';
} else if (sopClassDictionary.BasicStructuredDisplayStorage === SOPClassUID) {
naturalizedName = 'BasicStructuredDisplay';
} else if (sopClassDictionary.RTDoseStorage === SOPClassUID) {
naturalizedName = 'RTDose';
} else if (sopClassDictionary.RTStructureSetStorage === SOPClassUID) {
naturalizedName = 'RTStructureSet';
} else if (sopClassDictionary.RTBeamsTreatmentRecordStorage === SOPClassUID) {
naturalizedName = 'RTBeamsTreatmentRecord';
} else if (sopClassDictionary.RTPlanStorage === SOPClassUID) {
naturalizedName = 'RTPlan';
} else if (
sopClassDictionary.RTBrachyTreatmentRecordStorage === SOPClassUID
) {
naturalizedName = 'RTBrachyTreatmentRecord';
} else if (
sopClassDictionary.RTTreatmentSummaryRecordStorage === SOPClassUID
) {
naturalizedName = 'RTTreatmentSummaryRecord';
} else if (sopClassDictionary.RTIonPlanStorage === SOPClassUID) {
naturalizedName = 'RTIonPlan';
} else if (
sopClassDictionary.RTIonBeamsTreatmentRecordStorage === SOPClassUID
) {
naturalizedName = 'RTIonBeamsTreatmentRecord';
} else if (
sopClassDictionary.RTBeamsDeliveryInstructionStorage === SOPClassUID
) {
naturalizedName = 'RTBeamsDeliveryInstruction';
} else if (sopClassDictionary.GenericImplantTemplateStorage === SOPClassUID) {
naturalizedName = 'GenericImplantTemplate';
} else if (
sopClassDictionary.ImplantAssemblyTemplateStorage === SOPClassUID
) {
naturalizedName = 'ImplantAssemblyTemplate';
} else if (sopClassDictionary.ImplantTemplateGroupStorage === SOPClassUID) {
naturalizedName = 'ImplantTemplateGroup';
}
return naturalizedName;
};
-3
View File
@@ -1,8 +1,5 @@
####
##
## We need to pin WebPack's version for docz to work. See this issue:
## https://github.com/pedronauck/docz/issues/704#issuecomment-480295032
##
## react-scripts checks that dependency versions match before running
## Our top level webpack version causes the preflight check to fail
## This prevents that check
+43
View File
@@ -3,6 +3,49 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.10.11](https://github.com/OHIF/Viewers/compare/@ohif/ui@1.10.10...@ohif/ui@1.10.11) (2023-03-19)
**Note:** Version bump only for package @ohif/ui
## [1.10.10](https://github.com/OHIF/Viewers/compare/@ohif/ui@1.10.9...@ohif/ui@1.10.10) (2022-08-24)
**Note:** Version bump only for package @ohif/ui
## [1.10.9](https://github.com/OHIF/Viewers/compare/@ohif/ui@1.10.8...@ohif/ui@1.10.9) (2022-06-29)
**Note:** Version bump only for package @ohif/ui
## [1.10.8](https://github.com/OHIF/Viewers/compare/@ohif/ui@1.10.7...@ohif/ui@1.10.8) (2022-04-06)
**Note:** Version bump only for package @ohif/ui
## [1.10.7](https://github.com/OHIF/Viewers/compare/@ohif/ui@1.10.6...@ohif/ui@1.10.7) (2022-03-14)
### Bug Fixes
* remove docz + node version fix on docker ([#2743](https://github.com/OHIF/Viewers/issues/2743)) ([7164d1a](https://github.com/OHIF/Viewers/commit/7164d1a654571af99c22d2684e56cbdde05b2222))
## [1.10.6](https://github.com/OHIF/Viewers/compare/@ohif/ui@1.10.5...@ohif/ui@1.10.6) (2022-02-03)
**Note:** Version bump only for package @ohif/ui
-75
View File
@@ -1,75 +0,0 @@
/**
* Docz Configuration File:
* https://www.docz.site/docs/project-configuration
*/
import { css } from "docz-plugin-css";
export default {
dest: "example/build",
public: "/public",
wrapper: "src/__docs__/wrapper",
indexHtml: "src/__docs__/index.html",
// Limited support for importing `.styl` files
codeSandbox: false,
// https://github.com/pedronauck/docz/pull/849/files
// Because we re-export using `index.js` files
notUseSpecifiers: true,
menu: [
"Introduction",
"Getting Started",
{ name: "Elements", menu: ["Form / Select"] },
{
name: "Components",
menu: [
"CINE Dialog",
"Layout Button",
"Measurement Table",
"Overlay Trigger",
"Quick Switch",
"Rounded Button Group",
"Select Tree",
"Simple Dialog",
"Study Browser",
"Study List",
"Table List",
"Toolbar Section",
"About Modal",
"User Preferences Modal"
]
},
"Styling & Theming",
"Translating",
"Compatibility"
],
// Rollup Aliases?
// https://github.com/pedronauck/docz/issues/373
plugins: [
// CSS
css(),
// Stylus
css({
preprocessor: "stylus",
cssmodules: false
})
],
// `docz` uses file-loader to pull in SVGs. This kills our icons before
// They can be picked up by our `babel-plugin-inline-react-svg` dependency
// You can see where it's configured here:
// https://github.com/pedronauck/docz/blob/f72624d0aa5231dab17e1770e8d36be920f590a2/core/docz-core/src/bundler/loaders.ts#L135-L144
// How we delete our rule:
// https://github.com/neutrinojs/webpack-chain/issues/48
onCreateWebpackChain: config => {
config.module.rules.delete("svg");
},
modifyBabelRc: babelrc => {
const newBabelRc = {
...babelrc,
plugins: [
...babelrc.plugins,
require.resolve("babel-plugin-inline-react-svg")
]
};
return newBabelRc;
}
};
-25
View File
@@ -1,25 +0,0 @@
const path = require('path');
// ~~ Plugins
const PnpWebpackPlugin = require(`pnp-webpack-plugin`); // Required until Webpack@5
exports.onCreateWebpackConfig = args => {
args.actions.setWebpackConfig({
node: { fs: 'empty' },
resolve: {
plugins: [PnpWebpackPlugin],
// Note the '..' in the path because docz gatsby project lives in the '.docz' directory
modules: [
// platform/ui
path.resolve(__dirname, '../node_modules'),
// .docz
'node_modules',
],
// resolve: {
// symlinks: true,
// },
},
resolveLoader: {
plugins: [PnpWebpackPlugin.moduleLoader(module)],
},
});
};
+3 -8
View File
@@ -1,6 +1,6 @@
{
"name": "@ohif/ui",
"version": "1.10.6",
"version": "1.10.11",
"description": "A set of React components for Medical Imaging Viewers",
"author": "OHIF Contributors",
"license": "MIT",
@@ -20,9 +20,8 @@
"README.md"
],
"scripts": {
"dev": "docz dev",
"dev": "echo \"No dev script yet\" && exit 0",
"dev:ui": "yarn run dev",
"docs": "docz build",
"build": "cross-env NODE_ENV=production webpack --config .webpack/webpack.prod.js",
"build:package": "yarn run build",
"prepublishOnly": "yarn run build",
@@ -46,7 +45,7 @@
"i18next-browser-languagedetector": "^3.0.1",
"lodash.debounce": "^4.0.8",
"lodash.isequal": "4.5.0",
"moment": "2.24.0",
"moment": "2.29.4",
"prop-types": "15.6.2",
"prop-types-extra": "^1.1.1",
"react-dates": "21.2.1",
@@ -64,10 +63,6 @@
"devDependencies": {
"@mdx-js/tag": "^0.20.3",
"autoprefixer": "^9.6.0",
"docz": "1.2.0",
"docz-core": "1.2.0",
"docz-plugin-css": "0.11.0",
"docz-theme-default": "1.2.0",
"lodash.clonedeep": "^4.5.0",
"react-powerplug": "1.0.0"
}
-17
View File
@@ -1,17 +0,0 @@
import React, { Fragment } from 'react';
import { Link } from 'docz';
import PropTypes from 'prop-types';
const NameSpace = ({ name }) => (
<Fragment>
The namespace used on this component was: <pre>{name}</pre> Check the{' '}
<Link to="/translating#how-to-translate-components">translation docs</Link>{' '}
to see how to override it.
</Fragment>
);
NameSpace.propTypes = {
name: PropTypes.string.isRequired,
};
export default NameSpace;
Binary file not shown.

Before

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 61 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

@@ -1,15 +0,0 @@
---
name: Compatibility
route: /compatibility
---
# Compatibility
## Browser Support
`@ohif/ui` relies on
[browsers supported by Styled Components](https://www.styled-components.com/docs/faqs#which-browsers-are-supported)
or browsers supported by emotion.
Supported Browsers: IE11, IE 9+ (with Map + Set polyfills), Chrome, Firefox (and
derivatives), Edge, and Safari.
Whitespace-only changes.
@@ -1,13 +0,0 @@
---
name: Docs Settings
route: /docs-settings
---
import LanguageSwitcher from '../components/languageSwitcher';
# Components Language
You can change the language of the components displayed in this documentation by
choosing an option in the selector below:
<LanguageSwitcher />
@@ -1,76 +0,0 @@
---
name: Getting Started
route: /getting-started
---
# Getting Started
## Installation
> This component library is pre- v1.0. All realeases until a v1.0 have the
> possibility of introducing breaking changes. Please depend on an "exact"
> version in your projects to prevent issues caused by loose versioning.
Install `@ohif/ui` from npm:
```shell
// with npm
npm i @ohif/ui --save-exact
// with yarn
yarn add @ohif/ui --exact
```
## Usage
There is some setup required for `@ohif/ui`. We are working to eliminate these
requirements with the goal of providing ready to use components.
### External Dependencies
We have tried to keep the number of external dependencies limited to make setup
as easy as possible. You will, however, need to include either the default font
or the font you set for your theme:
```js
// Google Fonts, Roboto
'https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700&display=swap';
```
`@ohif/ui` also looks for theme CSS variabled defined on `:root`. You can find a
list of variables [on the theming page](/styling-and-theming)
### Import & Use
You can use components in your React app:
```js
import React, { Component } from 'react';
import { LayoutButton } from '@ohif/ui';
class Example extends Component {
constructor(props) {
super(props);
this.state = {
selectedCell: {
className: 'hover',
col: 1,
row: 1,
},
};
}
render() {
return (
<LayoutButton
selectedCell={this.state.selectedCell}
onChange={cell => this.setState({ selectedCell: cell })}
/>
);
}
}
```
> NOTE: It is heavily recommended that you use a CSS reset or normalize. As well
> as the following style: `* { Box-sizing: Border-box }`
-83
View File
@@ -1,83 +0,0 @@
<!DOCTYPE html>
<html lang="{{ lang }}">
<head>
<meta charset="UTF-8">
<meta name="description" content="{{ description }}">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>{{ title }}</title>
<!-- Latest compiled and minified CSS -->
<link rel="stylesheet" href="/public/docz.css">
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700&display=swap">
<style>
/* "Tide" theme */
/* TODO:
- Convert the other themes to CSS Variables
- Allow user to set default CSS theme in JS config
- Export the themes as identical JS objects
- For theme switcher, update root-level CSS properties via JS (https://medium.com/@_bengarrison/accessing-and-modifying-css-variables-with-javascript-2ccb735bbff0)
*/
:root {
/* Interface UI Colors */
--default-color: #9CCEF9;
--hover-color: #ffffff;
--active-color: #20A5D6;
--ui-border-color: #44626F;
--ui-border-color-dark: #3C5D80;
--ui-border-color-active: #00a4d9;
--primary-background-color: #000000;
--box-background-color: #3E5975;
--text-primary-color: #ffffff;
--text-secondary-color: #91B9CD;
--input-background-color: #2c363f;
--input-placeholder-color: #d3d3d3;
--table-hover-color: #2c363f;
--table-text-primary-color: #ffffff;
--table-text-secondary-color: #91b9cd;
--large-numbers-color: #6FBDE2;
--state-error: #FFCCCC;
--state-error-border: #FFCCCC;
--state-error-text: #FFCCCC;
/* Common palette */
--ui-yellow: #E29E4A;
--ui-sky-blue: #6FBDE2;
/* State palette */
--ui-state-error: #FFCCCC;
--ui-state-error-border: #993333;
--ui-state-error-text: #661111;
--ui-gray-lighter: #436270;
--ui-gray-light: #516873;
--ui-gray: #263340;
--ui-gray-dark: #16202B;
--ui-gray-darker: #151A1F;
--ui-gray-darkest: #14202A;
--calendar-day-color: #d3d3d3;
--calendar-day-border-color: #d3d3d3;
--calendar-day-active-hover-background-color: #516873;
--calendar-main-color: #263340;
--viewport-border-thickness: 1px;
}
body {
font-family: 'Roboto', sans-serif !important;
}
</style>
{{ head }}
</head>
<body>
<div id="root" />
{{ footer }}
</body>
</html>
-76
View File
@@ -1,76 +0,0 @@
---
name: Introduction
route: /
---
import { Playground, Props } from 'docz';
import { State } from 'react-powerplug';
import { TableList, TableListItem } from './../index.js';
# Introduction
**@ohif/ui is a collection of components and utilities** that power OHIF's
[zero-footprint DICOM viewer](https://github.com/OHIF/Viewers)
([demo][demo-url]). We maintain them as a separate component library to:
- Decouple presentation from business logic
- Test and develop components in isolation
- Provide well documented, reusable components
- Aid rapid application development for context specific viewers
## Quick Example
> This component library is pre- v1.0. All realeases until a v1.0 have the
> possibility of introducing breaking changes. Please depend on an "exact"
> version in your projects to prevent issues caused by loose versioning.
```js
// Add '@ohif/ui' as a dependency
yarn add @ohif/ui
// Import and use components
import { TableList } from '@ohif/ui'
```
<Playground>
<State
initial={{
selectedIndex: null,
listItems: [
{ label: 'Brain Left' },
{ label: 'Brain Right' },
{ label: 'Heart Left' },
{ label: 'Heart Right' },
],
}}
>
{({ state, setState }) => (
<TableList headerTitle="Example Table List Header">
{state.listItems.map((item, index) => {
return (
<TableListItem
key={`item_${index}`}
itemClass={state.selectedIndex === index ? 'selected' : ''}
itemIndex={index}
onItemClick={() => alert('item clicked')}
>
<label>{item.label}</label>
</TableListItem>
);
})}
</TableList>
)}
</State>
</Playground>
## FAQ
...
<!--
Links
-->
<!-- prettier-ignore-start -->
[demo-url]: https://docs.ohif.org/demo/
<!-- prettier-ignore-end -->
@@ -1,56 +0,0 @@
---
name: Styling & Theming
route: /styling-and-theming
---
# Styling & Theming
```css
:root {
/* Interface UI Colors */
--default-color: #9ccef9;
--hover-color: #ffffff;
--active-color: #20a5d6;
--ui-border-color: #44626f;
--ui-border-color-dark: #3c5d80;
--ui-border-color-active: #00a4d9;
--primary-background-color: #000000;
--box-background-color: #3e5975;
--text-primary-color: #ffffff;
--text-secondary-color: #91b9cd;
--input-background-color: #2c363f;
--input-placeholder-color: #d3d3d3;
--table-hover-color: #2c363f;
--table-text-primary-color: #ffffff;
--table-text-secondary-color: #91b9cd;
--large-numbers-color: #6fbde2;
--state-error: #ffcccc;
--state-error-border: #ffcccc;
--state-error-text: #ffcccc;
/* Common palette */
--ui-yellow: #e29e4a;
--ui-sky-blue: #6fbde2;
/* State palette */
--ui-state-error: #ffcccc;
--ui-state-error-border: #993333;
--ui-state-error-text: #661111;
--ui-gray-lighter: #436270;
--ui-gray-light: #516873;
--ui-gray: #263340;
--ui-gray-dark: #16202b;
--ui-gray-darker: #151a1f;
--ui-gray-darkest: #14202a;
--calendar-day-color: #d3d3d3;
--calendar-day-border-color: #d3d3d3;
--calendar-day-active-hover-background-color: #516873;
--calendar-main-color: #263340;
--viewport-border-thickness: 1px;
}
```
-87
View File
@@ -1,87 +0,0 @@
---
name: Translating
route: /translating
---
# Translating
**React Viewerbase** supports internationalization using
[i18next](https://www.i18next.com/) through the npm package
[@ohif/i18n](https://www.npmjs.com/package/@ohif/i18n), where is the main
instance of i18n containing several languages and tools.
## How to translate components
All you need is to use the internal custom superset of
[withTranslation HOC](https://react.i18next.com/latest/withtranslation-hoc),
available at `src/utils/LanguageProvider.js`
e.g.:
```js
import React from 'react';
import { withTranslation } from '../utils/LanguageProvider.js';
function MyComponent({ t }) {
return <p>{t('my translated text')}</p>;
}
export default withTranslation('MyNameSpace')(MyComponent);
```
---
## Namespaces
For further information about namespaces and how they work, please visit
[OHIF Namespaces docs](https://docs.ohif.org/viewer/internationalization.html#namespaces).
### How to get right the Namespace of a `@ohif/ui` component?
Check the component's page in this site, the Namespace information should be on
the bottom line.
Also, a nameSpace is defined when exporting a component, this information can be
found on exports trough the code, in case of missing in docs.
E.g.
```
export default withTranslation('TheNamespaceYouAreLookingFor')(TheComponentYouWantToUse);
```
### How to use another Namespace inside the current Namespace?
i18next provides a parsing feature able to get translations strings from any
Namespace, like this following example getting data from `InnerSpace` Namespace:
```
$t(InnerSpace:Reset)
export default withTranslation('OuterSpace')(TheComponent);
```
---
## I18next Provider
**@ohif/ui** pass down the `t` function trough the custom
[withTranslation HOC](https://github.com/OHIF/Viewers/blob/master/platform/ui/src/utils/LanguageProvider.js).
---
## Extending and Overriding languages
[How to Extend languages with @ohif/i18n](https://docs.ohif.org/viewer/internationalization.html#extending-languages-in-ohifi18n)
## Changing the language
The language choosing method is the same implemented in
[OHIF Viewers](https://docs.ohif.org/viewer/internationalization.html#changing-the-language)
> You can also change the language of the components displayed in this
> documentation by choosing an option in the
> [Docs Settings](https://react.ohif.org/docs-settings) section.
## Debugging translations
[How to Debug @ohif/i18n](https://docs.ohif.org/viewer/internationalization.html#debugging-translations)
-22
View File
@@ -1,22 +0,0 @@
import React from 'react';
import PropTypes from 'prop-types';
import LanguageSwitcher from '../components/languageSwitcher';
import './wrapper.styl';
const Wrapper = ({ children }) => (
<React.Fragment>
<div className="sidebarLanguageSwitcher">
<strong>Display components in:</strong>
<LanguageSwitcher />
</div>
{children}
</React.Fragment>
);
Wrapper.propTypes = {
children: PropTypes.node.isRequired,
};
export default Wrapper;
-15
View File
@@ -1,15 +0,0 @@
[class*="Sidebar__Menus"]
@media (min-width: 1120px)
margin-top: 80px
.sidebarLanguageSwitcher
position: fixed
top: 155px
left 0
z-index: 1049
padding: 0 24px 20px
border-bottom: 1px dotted #CED4DE
background: #F5F6F7
transition: all 200ms ease
@media (max-width: 1119px)
left -100%
@@ -1,42 +0,0 @@
---
name: Checkbox
menu: Elements
route: /components/checkbox
---
import { Playground, Props } from 'docz'
import { State } from 'react-powerplug'
import { Checkbox } from './../index'
import NameSpace from '../../../__docs__/NameSpace'
# Checkbox
## Basic usage
<Playground>
<State
initial={{
checked : false,
label : 'Sample check'
}}
>
{({ state, setState }) => (
<React.Fragment>
<div>
<pre>{JSON.stringify(state, null, 2)}</pre>
</div>
<div style={{ maxWidth: '300px', margin: '0 auto' }}>
<Checkbox {...state} />
</div>
</React.Fragment>
)}
</State>
</Playground>
## API
<Props of={Checkbox} />
## Translation Namespace
<NameSpace name="Checkbox" />
@@ -1,57 +0,0 @@
---
name: CINE Dialog
menu: Components
route: /components/cine-dialog
---
import { Playground, Props } from 'docz'
import { State } from 'react-powerplug'
import { CineDialog } from './../index'
import NameSpace from '../../../__docs__/NameSpace'
# CINE Dialog
## Basic usage
<Playground>
<State
initial={{
isPlaying: false,
cineFrameRate: 24,
isLoopEnabled: true,
lastChange: '',
}}
>
{({ state, setState }) => (
<React.Fragment>
<div>
<pre>{JSON.stringify(state, null, 2)}</pre>
</div>
<div style={{ maxWidth: '300px', margin: '0 auto' }}>
<CineDialog
{...state}
onClickSkipToStart={() =>
setState({ lastChange: 'Clicked SkipToStart' })
}
onClickSkipToEnd={() =>
setState({ lastChange: 'Clicked SkipToEnd' })
}
onClickNextButton={() => setState({ lastChange: 'Clicked Next' })}
onClickBackButton={() => setState({ lastChange: 'Clicked Back' })}
onLoopChanged={value => setState({ isLoopEnabled: value })}
onFrameRateChanged={value => setState({ cineFrameRate: value })}
onPlayPauseChanged={() => setState({ isPlaying: !state.isPlaying })}
/>
</div>
</React.Fragment>
)}
</State>
</Playground>
## API
<Props of={CineDialog} />
## Translation Namespace
<NameSpace name="CineDialog" />
@@ -1,42 +0,0 @@
---
name: About Modal
menu: Components
route: /components/about-modal
---
import { Playground, Props } from 'docz'
import { State } from 'react-powerplug'
import { AboutContent } from './../index.js'
# About Modal
## Basic usage
<Playground>
<State initial={{
isOpen: false
}}>
{({ state, setState }) => (
<React.Fragment>
<button
className="btn btn-primary"
type="button"
onClick={ () => setState({ isOpen: true }) }
>
Open about modal
</button>
<AboutContent
{...state}
onCancel={() => setState({ isOpen: false })}
/>
</React.Fragment>
)}
</State>
</Playground>
## API
<Props of={AboutContent} />
@@ -1,39 +0,0 @@
---
name: Viewport Download Form
menu: Components
route: /components/viewport-download-form
---
import { Playground, Props } from 'docz'
import { State } from 'react-powerplug'
import { ViewportDownloadForm } from './../index'
import NameSpace from '../../../__docs__/NameSpace'
# Viewport Download Form
## Basic usage
<Playground>
<State
initial={{}}
>
{({ state, setState }) => (
<React.Fragment>
<div>
<pre>{JSON.stringify(state, null, 2)}</pre>
</div>
<div style={{ maxWidth: '400px', margin: '0 auto' }}>
<ViewportDownloadForm />
</div>
</React.Fragment>
)}
</State>
</Playground>
## API
<Props of={ViewportDownloadForm} />
## Translation Namespace
<NameSpace name="ViewportDownloadForm" />
@@ -1,10 +0,0 @@
.LayoutExample {
background-color: var(--primary-background-color);
width: 160px;
height: 160px;
}
.GridLayout td {
padding: 5px;
border: 1px solid black;
}
@@ -1,49 +0,0 @@
---
name: Layout Button
menu: Components
route: /components/layout-button
---
import { Playground, Props } from 'docz'
import { State } from 'react-powerplug'
import { LayoutButton } from './../index.js'
import './layoutButton.css'
import NameSpace from '../../../__docs__/NameSpace'
# Layout Button
## Basic usage
<Playground>
<State initial={{
selectedCell: {
className: 'hover',
col: 1,
row: 1
},
}}>
{({ state, setState }) => (
<React.Fragment>
{/* STATE */}
<div><pre>{JSON.stringify(state, null, 2) }</pre></div>
{/* COMPONENT */}
<div className="LayoutExample">
<LayoutButton
{...state}
onChange={cell => setState({ selectedCell: cell })}
/>
</div>
</React.Fragment>
)}
</State>
</Playground>
## API
<Props of={LayoutButton} />
## Translation Namespace
<NameSpace name="Buttons" />
@@ -9,6 +9,14 @@ import { TableListItem } from './../tableList/TableListItem.js';
import './MeasurementTableItem.styl';
const ColoredCircle = ({ color }) => {
return <div className="item-color" style={{ backgroundColor: color }}></div>;
};
ColoredCircle.propTypes = {
color: PropTypes.string.isRequired,
};
class MeasurementTableItem extends Component {
static propTypes = {
measurementData: PropTypes.object.isRequired,
@@ -21,6 +29,14 @@ class MeasurementTableItem extends Component {
t: PropTypes.func,
};
constructor(props) {
super(props);
this.state = {
collapsed: true,
visible: true,
};
}
render() {
const {
warningTitle = '',
@@ -93,27 +109,115 @@ class MeasurementTableItem extends Component {
actionButtons.push(deleteButton);
}
return (
<TableListItem
itemKey={this.props.measurementData.measurementNumber}
itemClass={`measurementItem ${this.props.itemClass} ${hasWarningClass}`}
itemIndex={this.props.itemIndex}
onItemClick={this.onItemClick}
>
<div>
<div className="measurementLocation">
{this.props.t(this.props.measurementData.label, {
keySeparator: '>',
nsSeparator: '|',
if (
this.props.measurementData.isSRText === true &&
this.props.measurementData.labels &&
this.props.measurementData.labels.length > 0
) {
return (
<React.Fragment>
<TableListItem
key={this.props.measurementData.measurementNumber}
itemKey={this.props.measurementData.measurementNumber}
itemClass={`measurementItem ${this.props.itemClass} ${hasWarningClass}`}
itemIndex={this.props.itemIndex}
onItemClick={this.onItemClick}
>
<div>
<div className="measurementLocation">
{this.props.t(this.props.measurementData.label, {
keySeparator: '>',
nsSeparator: '|',
})}
</div>
</div>
<div className="icons">
<div className="displayTexts">{this.getDataDisplayText()}</div>
<Icon
className={`eye-icon`}
name={this.state.visible ? 'eye' : 'eye-closed'}
width="20px"
height="20px"
onClick={() => {
this.props.measurementData.labels.forEach(label => {
label.visible = !this.state.visible;
});
this.setState({
visible: !this.state.visible,
});
}}
/>
<Icon
className={`angle-double-${
this.state.collapsed ? 'down' : 'up'
}`}
name={`angle-double-${this.state.collapsed ? 'down' : 'up'}`}
width="20px"
height="20px"
onClick={() => {
this.setState({
collapsed: !this.state.collapsed,
});
}}
/>
</div>
</TableListItem>
{this.state.collapsed &&
this.props.measurementData.labels.map((SRLabel, index) => {
return (
<TableListItem
key={index}
itemKey={index}
itemMeta={<ColoredCircle color={SRLabel.color} />}
itemMetaClass="item-color-section"
onItemClick={this.onItemClick}
>
<div>
<div className="icons">
<span style={{ width: '90px' }}>
{SRLabel.label + ' : ' + SRLabel.value}
</span>
<Icon
className={`eye-icon`}
name={SRLabel.visible ? 'eye' : 'eye-closed'}
width="20px"
height="20px"
onClick={() => {
SRLabel.visible = !SRLabel.visible;
}}
/>
</div>
</div>
</TableListItem>
);
})}
</React.Fragment>
);
} else {
return (
<TableListItem
key={this.props.measurementData.measurementNumber}
itemKey={this.props.measurementData.measurementNumber}
itemClass={`measurementItem ${this.props.itemClass} ${hasWarningClass}`}
itemIndex={this.props.itemIndex}
onItemClick={this.onItemClick}
>
<div>
<div className="measurementLocation">
{this.props.t(this.props.measurementData.label, {
keySeparator: '>',
nsSeparator: '|',
})}
</div>
<div className="displayTexts">{this.getDataDisplayText()}</div>
{!this.props.measurementData.isReadOnly && (
<div className="rowActions">{actionButtons}</div>
)}
</div>
<div className="displayTexts">{this.getDataDisplayText()}</div>
{!this.props.measurementData.isReadOnly && (
<div className="rowActions">{actionButtons}</div>
)}
</div>
</TableListItem>
);
</TableListItem>
);
}
};
onItemClick = event => {
@@ -1,4 +1,16 @@
.measurementItem
.item-color-section
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
.item-color
margin-top: 8px;
border-radius: 100%;
width: 20px;
height: 20px;
.rowActions
margin-left: -1px;
background-color: var(--ui-gray-darker)
@@ -63,3 +75,16 @@
width: 22px;
height: 20px;
pointer-events: inherit;
.icons
display: flex;
align-items: center;
border-radius: 5px;
.icons .eye-icon
margin-left: 100px;
margin-right: -5px;
.icons .angle-double-down
.icons .angle-double-up
margin-left: 15px;
margin-right: -5px;
@@ -1,49 +0,0 @@
---
name: Measurement Table
menu: Components
route: /components/measurement-table
---
import { Playground, Props } from 'docz'
import { State } from 'react-powerplug'
import { MeasurementTable } from './../index.js'
import NameSpace from '../../../__docs__/NameSpace'
//
import measurements from './measurements.js'
import timepoints from './timepoints.js'
import warnings from './warnings.js'
# Measurement Table
## Basic usage
<Playground>
<State
initial={{
// Spelling error: overwallWarnings
overwallWarnings: warnings,
timepoints,
measurementCollection: measurements,
}}
>
{({ state, setState }) => (
<div style={{ height: '340px' }}>
<MeasurementTable
{...state}
onItemClick={() => alert('onItemClick')}
onRelabelClick={() => alert('onRelabelClick')}
onDeleteClick={() => alert('onDeleteClick')}
onEditDescriptionClick={() => alert('onEditDescriptionClick')}
/>
</div>
)}
</State>
</Playground>
## API
<Props of={MeasurementTable} />
## Translation Namespace
<NameSpace name="MeasurementTable" />
@@ -1,93 +0,0 @@
export default [
{
maxMeasurements: 5,
groupName: 'Targets',
measurements: [
{
measurementId: '123',
measurementNumber: '123',
itemNumber: 1,
label: 'Chest Wall Posterior',
hasWarnings: true,
warningTitle: 'Criteria nonconformities',
isSplitLesion: false,
warningList: [
'All measurements should have a location',
'Nodal lesions must be >= 15mm short axis AND >= double the acquisition slice thickness by CT and MR',
],
data: [
{
displayText: '25.7 x 12.9',
},
{
displayText: '24.7 x 11.5',
},
{},
],
},
{
measurementId: '124',
measurementNumber: '124',
itemNumber: 2,
label: 'Bone Extremity',
data: [
{
displayText: '24.7 x 11.1',
},
{
displayText: '21.2 x 10.9',
},
{},
],
},
],
},
{
maxMeasurements: 3,
groupName: 'NonTargets',
measurements: [
{
measurementId: '125',
measurementNumber: '125',
itemNumber: 1,
label: 'Chest Wall Single Site',
data: [
{
displayText: 'MD',
},
{
displayText: 'NM',
},
{},
],
},
{
measurementId: '126',
measurementNumber: '126',
itemNumber: 2,
label: 'Extremity Multiple Sites',
data: [
{
displayText: 'CR',
},
{},
{},
],
},
{
measurementId: '127',
measurementNumber: '127',
label: 'Extremity Site',
data: [
{
displayText: 'CR',
},
{},
{
displayText: 'NM',
},
],
},
],
},
];
@@ -1,14 +0,0 @@
export default [
{
label: 'Follow-up 2',
date: '20-Dec-18',
},
{
label: 'Follow-up 1',
date: '15-Jun-18',
},
{
label: 'Baseline',
date: '10-Apr-18',
},
];
Loaded 100 of 149 files, more files were not shown because too many files have changed in this diff. Show more