@3cr/viewer-browser 0.0.162 → 0.0.194

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (188) hide show
  1. package/.circleci/config.yml +8 -6
  2. package/__tests__/index.spec.ts +31 -24
  3. package/components.d.ts +32 -0
  4. package/dist/Viewer3CR.js +44 -27
  5. package/dist/Viewer3CR.mjs +22731 -17742
  6. package/dist/Viewer3CR.umd.js +44 -27
  7. package/index.html +5 -8
  8. package/index.ts +7 -2
  9. package/package.json +4 -2
  10. package/playground/index.html +6 -4
  11. package/src/App.vue +12 -4
  12. package/src/__tests__/app.spec.ts +2 -13
  13. package/src/assets/magic_wand.svg +24 -0
  14. package/src/components/WebGL3DR.vue +53 -92
  15. package/src/components/__tests__/webgl3dr.spec.ts +29 -48
  16. package/src/{demo → components/demo}/DemoModal.vue +1 -1
  17. package/src/{demo → components/demo}/DemoPatientModal.vue +4 -1
  18. package/src/components/demo/__tests__/DemoModal.spec.ts +25 -0
  19. package/src/components/demo/__tests__/DemoPatientModal.spec.ts +37 -0
  20. package/src/components/demo/__tests__/options.spec.ts +25 -0
  21. package/src/components/demo/licence/DemoLicenceEnableCloudStorageModal.vue +64 -0
  22. package/src/{demo → components/demo}/licence/DemoLicenceInfoModal.vue +5 -4
  23. package/src/{demo → components/demo}/licence/DemoLicenceSendToPartyModal.vue +6 -4
  24. package/src/{demo → components/demo}/licence/DemoLicenceShareToMobileModal.vue +8 -6
  25. package/src/components/demo/licence/__tests__/DemoLicenceEnableCloudStorageModal.spec.ts +37 -0
  26. package/src/components/demo/licence/__tests__/DemoLicenceInfoModal.spec.ts +37 -0
  27. package/src/components/demo/licence/__tests__/DemoLicenceSendToPartyModal.spec.ts +36 -0
  28. package/src/components/demo/licence/__tests__/DemoLicenceShareToMobileModal.spec.ts +51 -0
  29. package/src/{demo → components/demo}/options.ts +18 -20
  30. package/src/components/demo/patient/DemoPatientEnableCloudStorageModal.vue +64 -0
  31. package/src/{demo → components/demo}/patient/DemoPatientInfoModal.vue +5 -4
  32. package/src/{demo → components/demo}/patient/DemoPatientSendToPartyModal.vue +4 -3
  33. package/src/{demo → components/demo}/patient/DemoPatientShareToMobileModal.vue +8 -6
  34. package/src/components/demo/patient/__tests__/DemoPatientEnableCloudStorageModal.spec.ts +37 -0
  35. package/src/components/demo/patient/__tests__/DemoPatientInfoModal.spec.ts +37 -0
  36. package/src/components/demo/patient/__tests__/DemoPatientSendToPartyModal.spec.ts +36 -0
  37. package/src/components/demo/patient/__tests__/DemoPatientShareToMobileModal.spec.ts +51 -0
  38. package/src/components/loading/LoadingSpinner.vue +1 -1
  39. package/src/components/modal/ActionRail.vue +96 -0
  40. package/src/components/modal/AskAI.vue +250 -0
  41. package/src/components/modal/CloseViewerModal.vue +104 -0
  42. package/src/components/modal/MftpWebGL3DRModal.vue +415 -834
  43. package/src/components/modal/ViewerActionRail.vue +123 -0
  44. package/src/components/modal/ViewerAnnotationModal.vue +115 -0
  45. package/src/components/modal/ViewerAnnotations.vue +283 -0
  46. package/src/components/modal/ViewerDisplaySettings.vue +102 -0
  47. package/src/components/modal/ViewerNavigationDrawer.vue +90 -0
  48. package/src/components/modal/ViewerNavigationDrawerContent.vue +126 -0
  49. package/src/components/modal/ViewerNavigationDrawerFooter.vue +111 -0
  50. package/src/components/modal/ViewerNavigationDrawerHeader.vue +63 -0
  51. package/src/components/modal/__tests__/CloseViewerModal.spec.ts +60 -0
  52. package/src/components/modal/__tests__/{mftp-webgl-3dr-modal.spec.ts → MftpWebGL3DRModal.spec.ts} +47 -298
  53. package/src/components/modal/__tests__/ViewerAnnotationModal.spec.ts +79 -0
  54. package/src/components/modal/__tests__/ViewerDisplaySettings.spec.ts +61 -0
  55. package/src/components/modal/__tests__/ViewerNavigationDrawer.spec.ts +32 -0
  56. package/src/components/modal/__tests__/ViewerNavigationDrawerContent.spec.ts +29 -0
  57. package/src/components/modal/__tests__/ViewerNavigationDrawerFooter.spec.ts +43 -0
  58. package/src/components/modal/__tests__/ViewerNavigationDrawerHeader.spec.ts +37 -0
  59. package/src/components/modal/actions/Action.vue +40 -0
  60. package/src/components/modal/actions/Flip3dAction.vue +79 -0
  61. package/src/components/modal/actions/FlipHorizontalAction.vue +36 -0
  62. package/src/components/modal/actions/FlipVerticalAction.vue +36 -0
  63. package/src/components/modal/actions/FullscreenAction.vue +47 -0
  64. package/src/components/modal/actions/NavigationCubeAction.vue +33 -0
  65. package/src/components/modal/actions/PanAction.vue +78 -0
  66. package/src/components/modal/actions/ResetViewAction.vue +29 -0
  67. package/src/components/modal/actions/Rotate2dAction.vue +78 -0
  68. package/src/components/modal/actions/Slice3dAction.vue +71 -0
  69. package/src/components/modal/actions/ZoomAction.vue +70 -0
  70. package/src/components/modal/actions/__tests__/Action.spec.ts +29 -0
  71. package/src/components/modal/actions/__tests__/Flip3dAction.spec.ts +48 -0
  72. package/src/components/modal/actions/__tests__/FlipHorizontalAction.spec.ts +17 -0
  73. package/src/components/modal/actions/__tests__/FlipVerticalAction.spec.ts +17 -0
  74. package/src/components/modal/actions/__tests__/FullscreenAction.spec.ts +28 -0
  75. package/src/components/modal/actions/__tests__/NavigationCubeAction.spec.ts +25 -0
  76. package/src/components/modal/actions/__tests__/PanAction.spec.ts +46 -0
  77. package/src/components/modal/actions/__tests__/ResetViewAction.spec.ts +17 -0
  78. package/src/components/modal/actions/__tests__/Rotate2dAction.spec.ts +23 -0
  79. package/src/components/modal/actions/__tests__/Slice3dAction.spec.ts +14 -0
  80. package/src/components/modal/actions/__tests__/ZoomAction.spec.ts +34 -0
  81. package/src/components/modal/composables/__tests__/useNavigationCubeObserver.spec.ts +56 -0
  82. package/src/components/modal/composables/useEventListener.ts +22 -0
  83. package/src/components/modal/composables/useNavigationCubeObserver.ts +104 -0
  84. package/src/components/selectors/ValueSelector.vue +30 -33
  85. package/src/components/selectors/__tests__/value-selector.spec.ts +1 -1
  86. package/src/components/sliders/DoubleSliderSelector.vue +79 -71
  87. package/src/components/sliders/VerticalSliderSelector.vue +12 -17
  88. package/src/components/sliders/__tests__/double-slider-selector.spec.ts +1 -1
  89. package/src/components/sliders/__tests__/vertical-slider-selector.spec.ts +1 -1
  90. package/src/dataLayer/__tests__/clamp.spec.ts +16 -0
  91. package/src/dataLayer/__tests__/eventHandlers.spec.ts +38 -0
  92. package/src/dataLayer/__tests__/getIconForPreset.spec.ts +40 -0
  93. package/src/dataLayer/__tests__/patchDataOverlay.spec.ts +88 -0
  94. package/src/dataLayer/__tests__/scanState.spec.ts +93 -0
  95. package/src/dataLayer/__tests__/useViewer3cr.spec.ts +10 -0
  96. package/src/dataLayer/__tests__/viewer3cr.spec.ts +331 -0
  97. package/src/dataLayer/clamp.ts +9 -0
  98. package/src/dataLayer/eventHandlers.ts +26 -0
  99. package/src/dataLayer/patchDataOverlay.ts +101 -0
  100. package/src/dataLayer/scanState.ts +105 -26
  101. package/src/dataLayer/useViewer3cr.ts +7 -0
  102. package/src/dataLayer/viewer3cr.ts +410 -0
  103. package/src/helpers/__tests__/layout-overlay-style.spec.ts +24 -22
  104. package/src/helpers/__tests__/model-helper.spec.ts +44 -13
  105. package/src/helpers/layoutOverlayStyle.ts +16 -27
  106. package/src/helpers/modelHelper.ts +62 -10
  107. package/src/models/Callbacks.ts +2 -2
  108. package/src/models/LoadViewerOptions.ts +2 -0
  109. package/src/models/LoadViewerPayload.ts +1 -0
  110. package/src/notifications/notification.ts +3 -4
  111. package/src/plugins/vuetify.ts +5 -0
  112. package/src/services/gpt/__tests__/gpt.service.spec.ts +27 -0
  113. package/src/services/gpt/gpt.service.ts +27 -0
  114. package/static/3cr-types-browser/index.ts +74 -0
  115. package/static/3cr-types-browser/types/Action.ts +6 -0
  116. package/static/3cr-types-browser/types/ActionData.ts +4 -0
  117. package/static/3cr-types-browser/types/AlphaKeys.ts +5 -0
  118. package/static/3cr-types-browser/types/AnchorPoint.ts +12 -0
  119. package/static/3cr-types-browser/types/CallToAction.ts +5 -0
  120. package/static/3cr-types-browser/types/ColourData.ts +7 -0
  121. package/static/3cr-types-browser/types/ColourPresetData.ts +9 -0
  122. package/static/3cr-types-browser/types/CurrentDataOverlayState.ts +6 -0
  123. package/static/3cr-types-browser/types/CurrentScanState.ts +22 -0
  124. package/static/3cr-types-browser/types/DataOverlay.ts +22 -0
  125. package/static/3cr-types-browser/types/DataOverlayActions.ts +14 -0
  126. package/static/3cr-types-browser/types/DataOverlayData.ts +8 -0
  127. package/static/3cr-types-browser/types/DataOverlayEvent.ts +8 -0
  128. package/static/3cr-types-browser/types/DecryptionKey.ts +4 -0
  129. package/static/3cr-types-browser/types/DisplaySettings.ts +10 -0
  130. package/static/3cr-types-browser/types/EmptyPayload.ts +3 -0
  131. package/static/3cr-types-browser/types/EnumPayload.ts +4 -0
  132. package/static/3cr-types-browser/types/FileManagementActions.ts +11 -0
  133. package/static/3cr-types-browser/types/FlipValue.ts +7 -0
  134. package/static/3cr-types-browser/types/FrontEndInterfaces.ts +14 -0
  135. package/static/3cr-types-browser/types/GradientKeys.ts +7 -0
  136. package/static/3cr-types-browser/types/GreyscalePresetData.ts +6 -0
  137. package/static/3cr-types-browser/types/InitialDataOverlayState.ts +6 -0
  138. package/static/3cr-types-browser/types/InitialScanState.ts +19 -0
  139. package/static/3cr-types-browser/types/InteractionType.ts +8 -0
  140. package/static/3cr-types-browser/types/InteractivityActions.ts +6 -0
  141. package/static/3cr-types-browser/types/InteractivityState.ts +4 -0
  142. package/static/3cr-types-browser/types/InvertTransformData.ts +6 -0
  143. package/static/3cr-types-browser/types/LayoutActions.ts +6 -0
  144. package/static/3cr-types-browser/types/LayoutData.ts +7 -0
  145. package/static/3cr-types-browser/types/LoadDataSet.ts +6 -0
  146. package/static/3cr-types-browser/types/LoadSessionState.ts +4 -0
  147. package/static/3cr-types-browser/types/LocalLoadDataset.ts +3 -0
  148. package/static/3cr-types-browser/types/MovementData.ts +7 -0
  149. package/static/3cr-types-browser/types/NavigationCubeActions.ts +8 -0
  150. package/static/3cr-types-browser/types/NavigationCubeData.ts +12 -0
  151. package/static/3cr-types-browser/types/NavigationCubeTransform.ts +9 -0
  152. package/static/3cr-types-browser/types/NotificationPayload.ts +7 -0
  153. package/static/3cr-types-browser/types/NotificationsActions.ts +6 -0
  154. package/static/3cr-types-browser/types/Object.ts +1 -0
  155. package/static/3cr-types-browser/types/ObjectColour.ts +7 -0
  156. package/static/3cr-types-browser/types/ObjectIcon.ts +5 -0
  157. package/static/3cr-types-browser/types/ObjectInvert.ts +7 -0
  158. package/static/3cr-types-browser/types/ObjectSize.ts +7 -0
  159. package/static/3cr-types-browser/types/ObjectSize2D.ts +7 -0
  160. package/static/3cr-types-browser/types/ObjectVisible.ts +5 -0
  161. package/static/3cr-types-browser/types/PositionData.ts +14 -0
  162. package/static/3cr-types-browser/types/PresetsActions.ts +4 -0
  163. package/static/3cr-types-browser/types/RotationValue.ts +7 -0
  164. package/static/3cr-types-browser/types/ScanMovementActions.ts +27 -0
  165. package/static/3cr-types-browser/types/ScanMovementData.ts +3 -0
  166. package/static/3cr-types-browser/types/ScanOrientationActions.ts +6 -0
  167. package/static/3cr-types-browser/types/ScanStateActions.ts +4 -0
  168. package/static/3cr-types-browser/types/ScanView.ts +6 -0
  169. package/static/3cr-types-browser/types/SettingsData.ts +12 -0
  170. package/static/3cr-types-browser/types/SlicerData.ts +9 -0
  171. package/static/3cr-types-browser/types/SliderValue.ts +4 -0
  172. package/static/3cr-types-browser/types/SlidersActions.ts +18 -0
  173. package/static/3cr-types-browser/types/Vector2Data.ts +5 -0
  174. package/static/3cr-types-browser/types/Vector3Data.ts +6 -0
  175. package/static/3cr-types-browser/types/VectorMovementData.ts +8 -0
  176. package/static/3cr-types-browser/types/ViewInteractiveMode.ts +5 -0
  177. package/static/3cr-types-browser/types/ViewOrientation.ts +8 -0
  178. package/static/3cr-types-browser/types/ViewOrientations.ts +10 -0
  179. package/static/3cr-types-browser/types/ViewSelectionActions.ts +9 -0
  180. package/static/3cr-types-browser/types/ViewToggleData.ts +7 -0
  181. package/static/3cr-types-browser/types/VolumeOrientation.ts +7 -0
  182. package/test/helper.ts +10 -1
  183. package/test/setup.ts +13 -0
  184. package/tsconfig.json +1 -0
  185. package/vite.config.mts +1 -0
  186. package/src/dataLayer/__tests__/payload-handler.spec.ts +0 -214
  187. package/src/dataLayer/payloadHandler.ts +0 -138
  188. /package/src/dataLayer/{iconData.ts → getIconForPreset.ts} +0 -0
@@ -5,6 +5,8 @@ import { flushPromises } from "@vue/test-utils";
5
5
  import { spyOn } from "@vitest/spy";
6
6
 
7
7
  describe("generateDivStyleForLayout", () => {
8
+ const canvas = { clientWidth: 0, clientHeight: 0 } as HTMLCanvasElement;
9
+
8
10
  it("should generateDivStyleForLayout AnchorPoint.TOP", () => {
9
11
  expect(
10
12
  generateDivStyleForLayout({
@@ -24,9 +26,9 @@ describe("generateDivStyleForLayout", () => {
24
26
  Y: 1,
25
27
  },
26
28
  Version: "1.0.0",
27
- })
29
+ }, canvas)
28
30
  ).toStrictEqual({
29
- height: "calc(100% - 2px)",
31
+ height: "calc(100% - 0px)",
30
32
  left: "50%",
31
33
  top: "0px",
32
34
  transform: "translateX(-50%)",
@@ -53,11 +55,11 @@ describe("generateDivStyleForLayout", () => {
53
55
  Y: 1,
54
56
  },
55
57
  Version: "1.0.0",
56
- })
58
+ }, canvas)
57
59
  ).toStrictEqual({
58
- height: "calc(100% - 2px)",
60
+ height: "calc(100% - 0px)",
59
61
  left: "50%",
60
- bottom: "4px",
62
+ bottom: "0px",
61
63
  transform: "translateX(-50%)",
62
64
  width: "calc(100% - 0px)",
63
65
  });
@@ -82,9 +84,9 @@ describe("generateDivStyleForLayout", () => {
82
84
  Y: 1,
83
85
  },
84
86
  Version: "1.0.0",
85
- })
87
+ }, canvas)
86
88
  ).toStrictEqual({
87
- height: "calc(100% - 2px)",
89
+ height: "calc(100% - 0px)",
88
90
  left: "0px",
89
91
  top: "50%",
90
92
  transform: "translateY(-50%)",
@@ -111,9 +113,9 @@ describe("generateDivStyleForLayout", () => {
111
113
  Y: 1,
112
114
  },
113
115
  Version: "1.0.0",
114
- })
116
+ }, canvas)
115
117
  ).toStrictEqual({
116
- height: "calc(100% - 2px)",
118
+ height: "calc(100% - 0px)",
117
119
  right: "0px",
118
120
  top: "50%",
119
121
  transform: "translateY(-50%)",
@@ -140,10 +142,10 @@ describe("generateDivStyleForLayout", () => {
140
142
  Y: 1,
141
143
  },
142
144
  Version: "1.0.0",
143
- })
145
+ }, canvas)
144
146
  ).toStrictEqual({
145
147
  "border-top-left-radius": "0px",
146
- height: "calc(100% - 2px)",
148
+ height: "calc(100% - 0px)",
147
149
  left: "0px",
148
150
  top: "0px",
149
151
  width: "calc(100% - 0px)",
@@ -169,22 +171,22 @@ describe("generateDivStyleForLayout", () => {
169
171
  Y: 1,
170
172
  },
171
173
  Version: "1.0.0",
172
- })
174
+ }, canvas)
173
175
  ).toStrictEqual({
174
176
  "border-bottom-left-radius": "0px",
175
177
  "border-bottom-right-radius": "0px",
176
178
  "border-top-left-radius": "0px",
177
179
  "border-top-right-radius": "0px",
178
- height: "calc(100% - 2px - 2px)",
180
+ height: "calc(100% - 0px - 0px)",
179
181
  left: "0px",
180
182
  top: "0px",
181
- width: "calc(100% - 0px - 0px)",
183
+ width: "calc(100% - 0px - 0px - 0px)",
182
184
  });
183
185
  });
184
186
 
185
187
  it("should generateDivStyleForLayout AspectRatio === 1", async () => {
186
188
  spyOn(document, "getElementById").mockReturnValue({
187
- id: "unity-canvas",
189
+ id: "unity",
188
190
  offsetWidth: 1,
189
191
  offsetHeight: 2,
190
192
  } as HTMLElement);
@@ -207,16 +209,16 @@ describe("generateDivStyleForLayout", () => {
207
209
  Y: 1,
208
210
  },
209
211
  Version: "1.0.0",
210
- })
212
+ }, canvas)
211
213
  ).toStrictEqual({
212
214
  "border-bottom-left-radius": "0px",
213
215
  "border-bottom-right-radius": "0px",
214
216
  "border-top-left-radius": "0px",
215
217
  "border-top-right-radius": "0px",
216
- height: "calc(1px)",
218
+ height: "calc(0px)",
217
219
  left: "0px",
218
220
  top: "0px",
219
- width: "calc(2px)",
221
+ width: "calc(0px)",
220
222
  });
221
223
  });
222
224
 
@@ -241,7 +243,7 @@ describe("generateDivStyleForLayout", () => {
241
243
  Y: 1,
242
244
  },
243
245
  Version: "1.0.0",
244
- })
246
+ }, canvas)
245
247
  ).toStrictEqual({
246
248
  "border-bottom-left-radius": "0px",
247
249
  "border-bottom-right-radius": "0px",
@@ -273,16 +275,16 @@ describe("generateDivStyleForLayout", () => {
273
275
  Y: 1,
274
276
  },
275
277
  Version: "1.0.0",
276
- })
278
+ }, canvas)
277
279
  ).toStrictEqual({
278
280
  "border-bottom-left-radius": "0px",
279
281
  "border-bottom-right-radius": "0px",
280
282
  "border-top-left-radius": "0px",
281
283
  "border-top-right-radius": "0px",
282
- height: "calc(0% - 2px - 2px)",
284
+ height: "calc(0% - 0px - 0px)",
283
285
  left: "0px",
284
286
  top: "0px",
285
- width: "calc(0% - 0px - 0px)",
287
+ width: "calc(0% - 0px - 0px - 0px)",
286
288
  });
287
289
  });
288
290
  });
@@ -9,6 +9,9 @@ describe("inflateScanState", () => {
9
9
  it("should inflateScanState", () => {
10
10
  expect(inflateScanState()).toStrictEqual({
11
11
  Version: "1.0.0",
12
+ ScanMovement: {
13
+ Version: '1.1.0',
14
+ },
12
15
  Display: {
13
16
  Version: "1.0.0",
14
17
  Brightness: 50,
@@ -19,6 +22,7 @@ describe("inflateScanState", () => {
19
22
  ThresholdLower: 0,
20
23
  ThresholdUpper: 100,
21
24
  },
25
+ Colour: null,
22
26
  CurrentView: ScanView.Volume,
23
27
  Slice: {
24
28
  Version: "1.0.0",
@@ -40,31 +44,41 @@ describe("inflateScanState", () => {
40
44
  InteractionMode: ViewInteractiveMode.STATIC,
41
45
  },
42
46
  Orientations: {
43
- Version: "1.0.0",
47
+ Version: '1.0.0',
44
48
  Transverse: {
45
- Version: "1.0.0",
46
- View: ScanView.Transverse,
47
- VFlip: false,
48
- HFlip: false,
49
+ Version: '1.0.0',
50
+ Visibility: true,
51
+ VerticalFlip: false,
52
+ HorizontalFlip: false,
49
53
  Rotation: 0,
50
54
  Slice: 0,
51
55
  },
52
56
  Sagittal: {
53
- Version: "1.0.0",
54
- View: ScanView.Transverse,
55
- VFlip: false,
56
- HFlip: false,
57
+ Version: '1.0.0',
58
+ Visibility: true,
59
+ VerticalFlip: false,
60
+ HorizontalFlip: false,
57
61
  Rotation: 0,
58
62
  Slice: 0,
59
63
  },
60
64
  Coronal: {
61
- Version: "1.0.0",
62
- View: ScanView.Transverse,
63
- VFlip: false,
64
- HFlip: false,
65
+ Version: '1.0.0',
66
+ Visibility: true,
67
+ VerticalFlip: false,
68
+ HorizontalFlip: false,
65
69
  Rotation: 0,
66
70
  Slice: 0,
67
71
  },
72
+ Volume: {
73
+ Version: '1.1.0',
74
+ Visibility: true,
75
+ Inverted: {
76
+ Version: '1.1.0',
77
+ InvertedSagittal: false,
78
+ InvertedCoronal: false,
79
+ InvertedTransverse: false
80
+ }
81
+ }
68
82
  },
69
83
  Layout: {
70
84
  Version: "1.0.0",
@@ -95,6 +109,20 @@ describe("inflateScanState", () => {
95
109
  Version: "1.0.0",
96
110
  Value: false,
97
111
  },
112
+ Colour: {
113
+ Version: '1.1.0',
114
+ R: 0.75,
115
+ G: 0.75,
116
+ B: 0.75,
117
+ A: 1.0
118
+ },
119
+ HighlightColour: {
120
+ Version: '1.1.0',
121
+ R: 0.8,
122
+ G: 0.8,
123
+ B: 0.8,
124
+ A: 1.0
125
+ }
98
126
  },
99
127
  });
100
128
  });
@@ -107,6 +135,9 @@ describe("inflateInitialScanState", () => {
107
135
  XSlices: 0,
108
136
  YSlices: 0,
109
137
  ZSlices: 0,
138
+ XSpacing: 0,
139
+ YSpacing: 0,
140
+ ZSpacing: 0,
110
141
  Modality: "CT",
111
142
  HuUpper: 0,
112
143
  HuLower: 0,
@@ -1,29 +1,24 @@
1
1
  import { AnchorPoint, PositionData } from "@3cr/types-ts";
2
+ import { isFullscreen } from "@/dataLayer/scanState";
2
3
 
3
- import { toNumber } from "@/helpers/utils";
4
-
5
- export function generateDivStyleForLayout(layout: PositionData) {
6
- const padding = "0px";
7
- const canvas = document.getElementById("unity-canvas");
8
-
9
- const props = {} as any;
4
+ export function generateDivStyleForLayout(layout: PositionData, canvas: HTMLCanvasElement) {
5
+ const padding: string = "0px";
6
+ const props: Record<string, any> = {} as any;
10
7
 
11
8
  if (layout.Anchor === AnchorPoint.TOP) {
12
9
  props["left"] = "50%";
13
10
  props["transform"] = "translateX(-50%)";
14
- }
15
- if (layout.Anchor === AnchorPoint.BOTTOM) {
11
+ } else if (layout.Anchor === AnchorPoint.BOTTOM) {
16
12
  props["left"] = "50%";
17
13
  props["transform"] = "translateX(-50%)";
18
- }
19
- if (layout.Anchor === AnchorPoint.LEFT) {
14
+ } else if (layout.Anchor === AnchorPoint.LEFT) {
20
15
  props["top"] = "50%";
21
16
  props["transform"] = "translateY(-50%)";
22
- }
23
- if (layout.Anchor === AnchorPoint.RIGHT) {
17
+ } else if (layout.Anchor === AnchorPoint.RIGHT) {
24
18
  props["top"] = "50%";
25
19
  props["transform"] = "translateY(-50%)";
26
20
  }
21
+
27
22
  if (
28
23
  layout.Anchor === AnchorPoint.TOP_LEFT ||
29
24
  layout.Anchor === AnchorPoint.TOP ||
@@ -52,7 +47,7 @@ export function generateDivStyleForLayout(layout: PositionData) {
52
47
  layout.Anchor === AnchorPoint.BOTTOM_LEFT ||
53
48
  layout.Anchor === AnchorPoint.BOTTOM_RIGHT
54
49
  ) {
55
- props["bottom"] = "4px";
50
+ props["bottom"] = padding;
56
51
  }
57
52
  if (
58
53
  layout.Anchor === AnchorPoint.TOP_LEFT ||
@@ -80,26 +75,20 @@ export function generateDivStyleForLayout(layout: PositionData) {
80
75
  }
81
76
 
82
77
  props["width"] = `calc(${layout.MaxSize.X * 100}% - ${padding})`;
83
- props["height"] = `calc(${layout.MaxSize.Y * 100}% - ${"2px"})`;
78
+ props["height"] = `calc(${layout.MaxSize.Y * 100}% - ${padding})`;
79
+
84
80
  if (layout.Anchor === AnchorPoint.CENTER) {
85
- props["width"] = `calc(${
86
- layout.MaxSize.X * 100
87
- }% - ${padding} - ${padding})`;
88
- props["height"] = `calc(${
89
- layout.MaxSize.Y * 100
90
- }% - ${"2px"} - ${"2px"})`;
81
+ const adjustment = !isFullscreen.value ? canvas.clientHeight / 3 : 0;
82
+ props["width"] = `calc(${ layout.MaxSize.X * 100 }% - ${adjustment}px - ${padding} - ${padding})`;
83
+ props["height"] = `calc(${ layout.MaxSize.Y * 100 }% - ${padding} - ${padding})`;
91
84
  }
92
85
 
93
86
  if (layout.AspectRatio === 1) {
94
87
  if (layout.MaxSize.X === 1) {
95
- props["width"] = `calc(${
96
- layout.MaxSize.Y * toNumber(canvas?.offsetHeight)
97
- }px)`;
88
+ props["width"] = `calc(${layout.MaxSize.Y * canvas.clientHeight}px)`;
98
89
  }
99
90
  if (layout.MaxSize.Y === 1) {
100
- props["height"] = `calc(${
101
- layout.MaxSize.X * toNumber(canvas?.offsetWidth)
102
- }px)`;
91
+ props["height"] = `calc(${layout.MaxSize.X * canvas.clientWidth}px)`;
103
92
  }
104
93
  }
105
94
 
@@ -1,8 +1,18 @@
1
- import {AnchorPoint, CurrentScanState, InitialScanState, ScanView, ViewInteractiveMode,} from '@3cr/types-ts';
1
+ import {
2
+ AnchorPoint, CurrentDataOverlayState,
3
+ CurrentScanState,
4
+ InitialDataOverlayState,
5
+ InitialScanState,
6
+ ScanView,
7
+ ViewInteractiveMode,
8
+ } from '@3cr/types-ts';
2
9
 
3
10
  export function inflateScanState(): CurrentScanState {
4
11
  return {
5
12
  Version: '1.0.0',
13
+ ScanMovement: {
14
+ Version: '1.1.0',
15
+ },
6
16
  Display: {
7
17
  Version: '1.0.0',
8
18
  Brightness: 50,
@@ -37,34 +47,45 @@ export function inflateScanState(): CurrentScanState {
37
47
  Version: '1.0.0',
38
48
  Transverse: {
39
49
  Version: '1.0.0',
40
- View: ScanView.Transverse,
41
- VFlip: false,
42
- HFlip: false,
50
+ Visibility: true,
51
+ VerticalFlip: false,
52
+ HorizontalFlip: false,
43
53
  Rotation: 0,
44
54
  Slice: 0,
45
55
  },
46
56
  Sagittal: {
47
57
  Version: '1.0.0',
48
- View: ScanView.Transverse,
49
- VFlip: false,
50
- HFlip: false,
58
+ Visibility: true,
59
+ VerticalFlip: false,
60
+ HorizontalFlip: false,
51
61
  Rotation: 0,
52
62
  Slice: 0,
53
63
  },
54
64
  Coronal: {
55
65
  Version: '1.0.0',
56
- View: ScanView.Transverse,
57
- VFlip: false,
58
- HFlip: false,
66
+ Visibility: true,
67
+ VerticalFlip: false,
68
+ HorizontalFlip: false,
59
69
  Rotation: 0,
60
70
  Slice: 0,
61
71
  },
72
+ Volume: {
73
+ Version: '1.1.0',
74
+ Visibility: true,
75
+ Inverted: {
76
+ Version: '1.1.0',
77
+ InvertedSagittal: false,
78
+ InvertedCoronal: false,
79
+ InvertedTransverse: false
80
+ }
81
+ }
62
82
  },
63
83
  Layout: {
64
84
  Version: '1.0.0',
65
85
  SwitchOnViewChange: false,
66
86
  PositionData: [],
67
87
  },
88
+ Colour: null,
68
89
  NavigationCube: {
69
90
  Version: '1.0.0',
70
91
  Transform: {
@@ -89,6 +110,20 @@ export function inflateScanState(): CurrentScanState {
89
110
  Version: '1.0.0',
90
111
  Value: false,
91
112
  },
113
+ Colour: {
114
+ Version: '1.1.0',
115
+ R: 0.75,
116
+ G: 0.75,
117
+ B: 0.75,
118
+ A: 1.0
119
+ },
120
+ HighlightColour: {
121
+ Version: '1.1.0',
122
+ R: 0.8,
123
+ G: 0.8,
124
+ B: 0.8,
125
+ A: 1.0
126
+ }
92
127
  },
93
128
  };
94
129
  }
@@ -99,6 +134,9 @@ export function inflateInitialScanState(): InitialScanState {
99
134
  XSlices: 0,
100
135
  YSlices: 0,
101
136
  ZSlices: 0,
137
+ XSpacing: 0,
138
+ YSpacing: 0,
139
+ ZSpacing: 0,
102
140
  Modality: 'CT',
103
141
  HuUpper: 0,
104
142
  HuLower: 0,
@@ -107,3 +145,17 @@ export function inflateInitialScanState(): InitialScanState {
107
145
  ColourPresets: [],
108
146
  };
109
147
  }
148
+
149
+ export function inflateDataOverlayState(): CurrentDataOverlayState {
150
+ return {
151
+ Version: '1.1.0',
152
+ DataOverlay: []
153
+ };
154
+ }
155
+
156
+ export function inflateInitialDataOverlayState(): InitialDataOverlayState {
157
+ return {
158
+ Version: '1.1.0',
159
+ DataOverlay: inflateDataOverlayState()
160
+ };
161
+ }
@@ -1,2 +1,2 @@
1
- export type ViewerCallback = () => void;
2
- export type ViewerAsyncCallback = () => Promise<void>;
1
+ export type ViewerCallback = (...args: any[]) => void;
2
+ export type ViewerAsyncCallback = (...args: any[]) => Promise<void>;
@@ -8,6 +8,7 @@ export interface LoadViewerOptions {
8
8
  OnLoadSavedSession?: ViewerCallback | ViewerAsyncCallback | undefined;
9
9
  OnShareToMobile?: ViewerCallback | ViewerAsyncCallback | undefined;
10
10
  OnSendTo3rdParty?: ViewerCallback | ViewerAsyncCallback | undefined;
11
+ OnEnableCloudStorage?: ViewerCallback | ViewerAsyncCallback | undefined;
11
12
  OnSaveSession?: ViewerCallback | ViewerAsyncCallback | undefined;
12
13
  OnClosePopup?: ViewerCallback | ViewerAsyncCallback | undefined;
13
14
  OnExitViewer?: ViewerCallback | ViewerAsyncCallback | undefined;
@@ -23,6 +24,7 @@ export const defaultLoadViewerOptions: LoadViewerOptions = {
23
24
  OnSaveSession: () => Promise.resolve(),
24
25
  OnSendTo3rdParty: () => Promise.resolve(),
25
26
  OnShareToMobile: () => Promise.resolve(),
27
+ OnEnableCloudStorage: () => Promise.resolve(),
26
28
  OnShare: () => Promise.resolve(),
27
29
  OnScreenshot: () => Promise.resolve(),
28
30
  OnErrorClose: () => Promise.resolve(),
@@ -2,6 +2,7 @@ export interface LoadViewerPayload {
2
2
  Url: string;
3
3
  DecryptionKey: MftpDecryptionKey;
4
4
  }
5
+
5
6
  export interface MftpDecryptionKey {
6
7
  Key: string;
7
8
  Iv: string;
@@ -1,15 +1,13 @@
1
1
  import {
2
2
  InteractivityActions,
3
+ NavigationCubeActions,
3
4
  NotificationPayload,
4
5
  NotificationsActions,
5
6
  } from "@3cr/types-ts";
6
7
  import { useNotification } from "@kyvg/vue3-notification";
7
8
  const { notify } = useNotification();
8
9
 
9
- export async function handleNotification(
10
- action: NotificationsActions,
11
- message: string
12
- ) {
10
+ export async function handleNotification(action: NotificationsActions, message: string) {
13
11
  const notification = JSON.parse(message) as NotificationPayload;
14
12
 
15
13
  switch (notification.Action) {
@@ -17,6 +15,7 @@ export async function handleNotification(
17
15
  case InteractivityActions.in02:
18
16
  case InteractivityActions.in03:
19
17
  case InteractivityActions.in04:
18
+ case NavigationCubeActions.nc01:
20
19
  return;
21
20
  default:
22
21
  }
@@ -14,6 +14,7 @@ import { mdi } from "vuetify/iconsets/mdi";
14
14
  import { fa } from "vuetify/iconsets/fa";
15
15
  import { h, ref } from "vue";
16
16
  import liver from "@/components/icons/liver.vue";
17
+ import { VTreeview, VTreeviewItem } from 'vuetify/labs/components';
17
18
 
18
19
  const customComponents: any = {
19
20
  liver,
@@ -22,6 +23,10 @@ export const disableTheme = ref<boolean>(false);
22
23
  // https://vuetifyjs.com/en/introduction/why-vuetify/#feature-guides
23
24
  /* istanbul ignore next -- @preserve */
24
25
  export default createVuetify({
26
+ components: {
27
+ VTreeview,
28
+ VTreeviewItem
29
+ },
25
30
  theme: disableTheme.value
26
31
  ? false
27
32
  : {
@@ -0,0 +1,27 @@
1
+ import {describe, expect, it, vi} from "vitest";
2
+ import {GptResponsePayload, GptService} from "@/services/gpt/gpt.service";
3
+
4
+ vi.mock('axios', async (importOriginal) => {
5
+ return {
6
+ ...(await importOriginal<typeof import('axios')>()),
7
+ create: () => ({
8
+ post: vi.fn()
9
+ })
10
+ };
11
+ });
12
+
13
+ describe('GptService tests', () => {
14
+ it('should instantiate', () => {
15
+ expect(GptService.Instantiate()).toBeTruthy();
16
+ });
17
+
18
+ it('should generate response', async () => {
19
+ const data: GptResponsePayload = { GptResponse: 'test', FollowupQuestions: [] };
20
+ const service = GptService.Instantiate();
21
+ vi.spyOn(service.client, 'post').mockResolvedValue({ data });
22
+
23
+ const response = await service.GenerateAnnotations('test', 0);
24
+ expect(response).toBeDefined();
25
+ expect(response).toStrictEqual({ data });
26
+ });
27
+ });
@@ -0,0 +1,27 @@
1
+ import axios, { AxiosInstance, AxiosResponse } from "axios";
2
+
3
+ export class GptService {
4
+ static Instantiate() {
5
+ return new GptService();
6
+ }
7
+
8
+ client: AxiosInstance = axios.create();
9
+
10
+ async GenerateAnnotations(title: string, question: number = 0): Promise<AxiosResponse<GptResponsePayload>> {
11
+ return this.client.post(
12
+ "https://test.api.singular.health/api/GPT/Smart/Annotation",
13
+ null,
14
+ { params: { annotationTitle: title, question } }
15
+ );
16
+ }
17
+ }
18
+
19
+ export interface GptResponsePayload {
20
+ GptResponse: string;
21
+ FollowupQuestions: GptQuestion[];
22
+ }
23
+
24
+ export interface GptQuestion {
25
+ Question: string;
26
+ ApiPreFilledRequestKey: number;
27
+ }
@@ -0,0 +1,74 @@
1
+ // Interfaces
2
+ export { FrontEndInterfaces } from './types/FrontEndInterfaces';
3
+
4
+ // Actions
5
+ export { FileManagementActions } from './types/FileManagementActions';
6
+ export { SlidersActions } from './types/SlidersActions';
7
+ export { ScanStateActions } from './types/ScanStateActions';
8
+ export { ViewSelectionActions } from './types/ViewSelectionActions';
9
+ export { ScanOrientationActions } from './types/ScanOrientationActions';
10
+ export { InteractivityActions } from './types/InteractivityActions';
11
+ export { NotificationsActions } from './types/NotificationsActions';
12
+ export { PresetsActions } from './types/PresetsActions';
13
+ export { ScanMovementActions } from './types/ScanMovementActions';
14
+ export { NavigationCubeActions } from './types/NavigationCubeActions';
15
+ export { LayoutActions } from './types/LayoutActions';
16
+ export { DataOverlayActions } from './types/DataOverlayActions';
17
+
18
+ // Type Definitions
19
+ export type { Action } from './types/Action';
20
+ export type { ActionData } from './types/ActionData';
21
+ export type { CallToAction } from './types/CallToAction';
22
+ export type { DecryptionKey } from './types/DecryptionKey';
23
+ export type { LoadDataSet } from './types/LoadDataSet';
24
+ export type { DataOverlay } from './types/DataOverlay';
25
+ export type { DataOverlayEvent } from './types/DataOverlayEvent';
26
+ export type { DisplaySettings } from './types/DisplaySettings';
27
+ export type { SlicerData } from './types/SlicerData';
28
+ export type { SettingsData } from './types/SettingsData';
29
+ export type { ViewOrientation } from './types/ViewOrientation';
30
+ export type { InvertTransformData } from './types/InvertTransformData';
31
+ export type { VolumeOrientation } from './types/VolumeOrientation';
32
+ export type { ViewOrientations } from './types/ViewOrientations';
33
+ export type { Vector2Data } from './types/Vector2Data';
34
+ export type { PositionData } from './types/PositionData';
35
+ export type { LayoutData } from './types/LayoutData';
36
+ export type { GradientKeys } from './types/GradientKeys';
37
+ export type { AlphaKeys } from './types/AlphaKeys';
38
+ export type { ColourPresetData } from './types/ColourPresetData';
39
+ export type { NavigationCubeTransform } from './types/NavigationCubeTransform';
40
+ export type { InteractivityState } from './types/InteractivityState';
41
+ export type { ColourData } from './types/ColourData';
42
+ export type { NavigationCubeData } from './types/NavigationCubeData';
43
+ export type { ScanMovementData } from './types/ScanMovementData';
44
+ export type { CurrentScanState } from './types/CurrentScanState';
45
+ export type { GreyscalePresetData } from './types/GreyscalePresetData';
46
+ export type { InitialScanState } from './types/InitialScanState';
47
+ export type { LoadSessionState } from './types/LoadSessionState';
48
+ export type { LocalLoadDataset } from './types/LocalLoadDataset';
49
+ export type { SliderValue } from './types/SliderValue';
50
+ export type { Object } from './types/Object';
51
+ export type { DataOverlayData } from './types/DataOverlayData';
52
+ export type { CurrentDataOverlayState } from './types/CurrentDataOverlayState';
53
+ export type { EmptyPayload } from './types/EmptyPayload';
54
+ export type { ViewToggleData } from './types/ViewToggleData';
55
+ export type { RotationValue } from './types/RotationValue';
56
+ export type { FlipValue } from './types/FlipValue';
57
+ export type { EnumPayload } from './types/EnumPayload';
58
+ export type { NotificationPayload } from './types/NotificationPayload';
59
+ export type { MovementData } from './types/MovementData';
60
+ export type { Vector3Data } from './types/Vector3Data';
61
+ export type { VectorMovementData } from './types/VectorMovementData';
62
+ export type { InitialDataOverlayState } from './types/InitialDataOverlayState';
63
+ export type { ObjectVisible } from './types/ObjectVisible';
64
+ export type { ObjectSize2D } from './types/ObjectSize2D';
65
+ export type { ObjectColour } from './types/ObjectColour';
66
+ export type { ObjectIcon } from './types/ObjectIcon';
67
+ export type { ObjectSize } from './types/ObjectSize';
68
+ export type { ObjectInvert } from './types/ObjectInvert';
69
+
70
+ // Enum Definitions
71
+ export { ScanView } from './types/ScanView';
72
+ export { AnchorPoint } from './types/AnchorPoint';
73
+ export { ViewInteractiveMode } from './types/ViewInteractiveMode';
74
+ export { InteractionType } from './types/InteractionType';
@@ -0,0 +1,6 @@
1
+ import {ActionData} from "./ActionData";
2
+
3
+ export interface Action {
4
+ ActionType: number;
5
+ ActionData: ActionData
6
+ }
@@ -0,0 +1,4 @@
1
+ export interface ActionData {
2
+ Description: string;
3
+ Url: string;
4
+ }
@@ -0,0 +1,5 @@
1
+ export interface AlphaKeys {
2
+ Version: string,
3
+ Alpha: number,
4
+ Time: number
5
+ }