@3cr/viewer-browser 0.0.161 → 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 (229) hide show
  1. package/.circleci/config.yml +53 -0
  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 +22734 -17747
  6. package/dist/Viewer3CR.umd.js +44 -27
  7. package/index.html +6 -8
  8. package/index.ts +9 -5
  9. package/package.json +5 -2
  10. package/playground/index.html +7 -10
  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/coverage/3cr-viewer-browser/index.html +0 -116
  187. package/coverage/3cr-viewer-browser/index.ts.html +0 -199
  188. package/coverage/3cr-viewer-browser/src/App.vue.html +0 -316
  189. package/coverage/3cr-viewer-browser/src/components/WebGL3DR.vue.html +0 -442
  190. package/coverage/3cr-viewer-browser/src/components/icons/index.html +0 -116
  191. package/coverage/3cr-viewer-browser/src/components/icons/liver.vue.html +0 -148
  192. package/coverage/3cr-viewer-browser/src/components/index.html +0 -116
  193. package/coverage/3cr-viewer-browser/src/components/loading/LoadingSpinner.vue.html +0 -622
  194. package/coverage/3cr-viewer-browser/src/components/loading/index.html +0 -116
  195. package/coverage/3cr-viewer-browser/src/components/modal/MftpWebGL3DRModal.vue.html +0 -3118
  196. package/coverage/3cr-viewer-browser/src/components/modal/index.html +0 -116
  197. package/coverage/3cr-viewer-browser/src/components/selectors/ValueSelector.vue.html +0 -358
  198. package/coverage/3cr-viewer-browser/src/components/selectors/index.html +0 -116
  199. package/coverage/3cr-viewer-browser/src/components/sliders/DoubleSliderSelector.vue.html +0 -487
  200. package/coverage/3cr-viewer-browser/src/components/sliders/VerticalSliderSelector.vue.html +0 -358
  201. package/coverage/3cr-viewer-browser/src/components/sliders/index.html +0 -131
  202. package/coverage/3cr-viewer-browser/src/dataLayer/iconData.ts.html +0 -118
  203. package/coverage/3cr-viewer-browser/src/dataLayer/index.html +0 -146
  204. package/coverage/3cr-viewer-browser/src/dataLayer/payloadHandler.ts.html +0 -463
  205. package/coverage/3cr-viewer-browser/src/dataLayer/scanState.ts.html +0 -598
  206. package/coverage/3cr-viewer-browser/src/helpers/index.html +0 -146
  207. package/coverage/3cr-viewer-browser/src/helpers/layoutOverlayStyle.ts.html +0 -406
  208. package/coverage/3cr-viewer-browser/src/helpers/modelHelper.ts.html +0 -412
  209. package/coverage/3cr-viewer-browser/src/helpers/utils.ts.html +0 -133
  210. package/coverage/3cr-viewer-browser/src/index.html +0 -131
  211. package/coverage/3cr-viewer-browser/src/main.ts.html +0 -124
  212. package/coverage/3cr-viewer-browser/src/models/LoadViewerOptions.ts.html +0 -166
  213. package/coverage/3cr-viewer-browser/src/models/index.html +0 -116
  214. package/coverage/3cr-viewer-browser/src/notifications/index.html +0 -116
  215. package/coverage/3cr-viewer-browser/src/notifications/notification.ts.html +0 -238
  216. package/coverage/3cr-viewer-browser/src/plugins/index.html +0 -131
  217. package/coverage/3cr-viewer-browser/src/plugins/index.ts.html +0 -136
  218. package/coverage/3cr-viewer-browser/src/plugins/vuetify.ts.html +0 -220
  219. package/coverage/base.css +0 -224
  220. package/coverage/block-navigation.js +0 -87
  221. package/coverage/favicon.png +0 -0
  222. package/coverage/index.html +0 -296
  223. package/coverage/prettify.css +0 -1
  224. package/coverage/prettify.js +0 -2
  225. package/coverage/sort-arrow-sprite.png +0 -0
  226. package/coverage/sorter.js +0 -196
  227. package/src/dataLayer/__tests__/payload-handler.spec.ts +0 -214
  228. package/src/dataLayer/payloadHandler.ts +0 -138
  229. /package/src/dataLayer/{iconData.ts → getIconForPreset.ts} +0 -0
package/index.html CHANGED
@@ -18,23 +18,21 @@
18
18
  import {registerViewer, loadViewer} from './index.ts';
19
19
 
20
20
  const { StatsigClient, SessionReplay, runStatsigAutoCapture, runStatsigSessionReplay } = window.Statsig;
21
+
21
22
  const client = new StatsigClient(
22
23
  "client-YaAjxOTTRbuSN3peDAwXEzErieXpI744a3OHDgonzvV",
23
24
  { userID: undefined },
24
- {environment: {tier: 'production'}}
25
+ {environment: {tier: 'development'}}
25
26
  );
26
-
27
- const replayer = new SessionReplay(client);
28
- console.log(replayer)
27
+ client.initializeSync()
29
28
 
30
29
  runStatsigAutoCapture(client);
31
30
  window.playgroundStatsigClient = client
32
- runStatsigSessionReplay(client);
33
-
34
31
 
35
32
 
36
- const dynamicConfig = window.playgroundStatsigClient.getDynamicConfig("3cr_viewer_version");
37
- const version = dynamicConfig.value["sdkVersion"] ?? "1.0.0";
33
+ const dynamicConfig = client.getDynamicConfig("3cr_viewer_version");
34
+ const testVersion = (window.location.href.includes('test.') || window.location.href.includes('localhost')) && new URLSearchParams(window.location.search).get("build_version")
35
+ const version = testVersion ?? dynamicConfig.value["sdkVersion"] ?? "1.1.0";
38
36
 
39
37
  client.initializeAsync().then(() => {
40
38
  registerViewer(version).then(() => {
package/index.ts CHANGED
@@ -43,6 +43,7 @@ export async function registerViewer(
43
43
  registerPlugins(app);
44
44
 
45
45
  mountedApp = app.mount(newElement);
46
+
46
47
  await registerVersion(version);
47
48
  }
48
49
 
@@ -51,18 +52,21 @@ export async function loadViewer(
51
52
  options: LoadViewerOptions = defaultLoadViewerOptions
52
53
  ): Promise<void> {
53
54
  if (!mountedApp) {
54
- throw new Error(
55
- "Please call `registerViewer(version: string, idSelector: string)` first"
56
- );
55
+ throw new Error("Please call `registerViewer(version: string)` first");
57
56
  }
58
57
  await (mountedApp as any).loadInstance(payload, options);
59
58
  }
60
59
 
60
+ export async function loadSession(url: string): Promise<void> {
61
+ if (!mountedApp) {
62
+ throw new Error("Please call `registerViewer(version: string)` first");
63
+ }
64
+ await (mountedApp as any).loadSession(url);
65
+ }
66
+
61
67
  export async function ejectViewer() {
62
- console.log("Ejected Viewer");
63
68
  const modal = document.getElementById(modalId);
64
69
  const styleSheet = document.getElementById(injectedStyleId);
65
-
66
70
  modal?.remove();
67
71
  styleSheet?.remove();
68
72
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@3cr/viewer-browser",
3
- "version": "0.0.161",
3
+ "version": "0.0.194",
4
4
  "main": "./dist/Viewer3CR.umd.js",
5
5
  "module": "dist/Viewer3CR.umd.js",
6
6
  "homepage": "https://docs.3cr.singular.health",
@@ -12,6 +12,7 @@
12
12
  "dev": "vite",
13
13
  "build": "vue-tsc --noEmit && vite build",
14
14
  "deploy": "npm version --no-git-tag-version patch && npm run build && npm publish",
15
+ "deploy:ci": "npm run build && npm publish --access=public",
15
16
  "preview": "vite preview",
16
17
  "test": "vitest",
17
18
  "test:ui": "vitest --ui",
@@ -21,10 +22,12 @@
21
22
  },
22
23
  "dependencies": {
23
24
  "@3cr/sdk-browser": "^1.0.13",
24
- "@3cr/types-ts": "^1.0.9",
25
+ "@3cr/types-ts": "file:static/3cr-types-browser",
25
26
  "@kyvg/vue3-notification": "^3.2.1",
26
27
  "@mdi/font": "6.2.95",
27
28
  "@mdi/js": "^7.4.47",
29
+ "axios": "^1.7.2",
30
+ "intro.js": "^7.2.0",
28
31
  "logrocket": "^8.1.0",
29
32
  "roboto-fontface": "*",
30
33
  "vue": "^3.4.21",
@@ -79,23 +79,20 @@
79
79
  <div id="app"></div>
80
80
  <script type="module">
81
81
 
82
- const { StatsigClient, SessionReplay, runStatsigAutoCapture, runStatsigSessionReplay } = window.Statsig;
82
+ const { StatsigClient, runStatsigAutoCapture } = window.Statsig;
83
+ const isTest = (window.location.href.includes('test.') || window.location.href.includes('localhost'))
83
84
  const client = new StatsigClient(
84
85
  "client-YaAjxOTTRbuSN3peDAwXEzErieXpI744a3OHDgonzvV",
85
86
  { userID: undefined },
86
- {environment: {tier: 'production'}}
87
+ {environment: {tier: isTest ? 'development' : 'production'}}
87
88
  );
88
- const replayer = new SessionReplay(client);
89
- console.log(replayer)
89
+ client.initializeSync()
90
90
  runStatsigAutoCapture(client);
91
91
  window.playgroundStatsigClient = client
92
- runStatsigSessionReplay(client);
93
-
94
- const dynamicConfig = window.playgroundStatsigClient.getDynamicConfig("3cr_viewer_version");
95
- const version = dynamicConfig.value["sdkVersion"] ?? "1.0.0_381";
96
-
97
-
98
92
 
93
+ const dynamicConfig = client.getDynamicConfig("3cr_viewer_version");
94
+ const testVersion = (isTest) && new URLSearchParams(window.location.search).get("build_version")
95
+ const version = testVersion ?? dynamicConfig.value["sdkVersion"] ?? "1.1.0";
99
96
 
100
97
  client.initializeAsync().then(() => {
101
98
  window.registerViewer(version).then(() => {
package/src/App.vue CHANGED
@@ -20,7 +20,7 @@ import {
20
20
  defaultLoadViewerOptions,
21
21
  LoadViewerOptions,
22
22
  } from "@/models/LoadViewerOptions";
23
- import { isDemo } from "@/demo/options";
23
+ import { isDemo } from "@/components/demo/options";
24
24
  import LogRocket from "logrocket";
25
25
 
26
26
  if (isDemo.value) {
@@ -34,12 +34,10 @@ const payload = ref<LoadViewerPayload>({
34
34
  Key: "KUc722X1y4w42M+jCf9a3+6EGz66z7UMWK3m2aMqGxM=",
35
35
  },
36
36
  });
37
+
37
38
  const options = ref<LoadViewerOptions>(defaultLoadViewerOptions);
38
39
 
39
40
  const mftpWebGL3DRModal = ref<typeof MftpWebGL3DRModal | null>(null);
40
- defineExpose({
41
- loadInstance,
42
- });
43
41
 
44
42
  async function loadInstance(
45
43
  payloadIncoming: LoadViewerPayload | undefined,
@@ -51,7 +49,17 @@ async function loadInstance(
51
49
  await nextTick();
52
50
  unref(mftpWebGL3DRModal)?.alterValue(true);
53
51
  }
52
+
53
+ async function loadSession(url: string): Promise<void> {
54
+ await unref(mftpWebGL3DRModal)?.loadSession(url);
55
+ }
56
+
57
+ defineExpose({
58
+ loadInstance,
59
+ loadSession,
60
+ });
54
61
  </script>
62
+
55
63
  <style>
56
64
  .material-icons-outlined,
57
65
  .material-symbols-outlined {
@@ -1,25 +1,14 @@
1
- import { expect, describe, it, vi } from "vitest";
1
+ import { expect, describe, it } from "vitest";
2
2
  import { shallowMountVuetify } from "~/helper";
3
3
  import App from "@/App.vue";
4
4
 
5
5
  const wrapper = shallowMountVuetify(App);
6
6
 
7
- vi.mock("@3cr/sdk-browser", async (importOriginal) => {
8
- const mod = (await importOriginal()) as object;
9
- return {
10
- ...mod,
11
- // replace some exports
12
- registerVersion: vi.fn(),
13
- createInstance: vi.fn(),
14
- executePayload: vi.fn(),
15
- registerOnPayloadHandler: vi.fn(),
16
- };
17
- });
18
-
19
7
  describe("App.vue", () => {
20
8
  it("should inflate component", () => {
21
9
  expect(wrapper).toBeTruthy();
22
10
  });
11
+
23
12
  it("should loadScan", async () => {
24
13
  await wrapper.vm.loadInstance(undefined, {});
25
14
  expect(wrapper).toBeTruthy();
@@ -0,0 +1,24 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+
3
+ <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
4
+ <!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
5
+ <svg width="800px" height="800px" viewBox="-3 0 32 32" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
6
+ <g id="icomoon-ignore">
7
+ </g>
8
+ <path d="M-0.007 28.236l13.916-13.916 0.754 0.754-13.916 13.916-0.754-0.754z" fill="#000000">
9
+
10
+ <path d="M9.973 10.453h4.267v1.067h-4.267v-1.067z" fill="#000000">
11
+
12
+ <path d="M21.707 10.453h4.267v1.067h-4.267v-1.067z" fill="#000000">
13
+
14
+ <path d="M17.44 14.72h1.067v4.267h-1.067v-4.267z" fill="#000000">
15
+
16
+ <path d="M17.44 2.987h1.067v4.267h-1.067v-4.267z" fill="#000000">
17
+
18
+ <path d="M23.991 5.717l-3.017 3.017-0.754-0.754 3.017-3.017 0.754 0.754z" fill="#000000">
19
+
20
+ <path d="M23.246 17.042l-3.017-3.017 0.754-0.754 3.017 3.017-0.754 0.754z" fill="#000000">
21
+
22
+ <path d="M14.986 8.741l-3.017-3.017 0.754-0.754 3.017 3.017-0.754 0.754z" fill="#000000">
23
+
24
+ </svg>
@@ -1,82 +1,46 @@
1
1
  <template>
2
- <div
3
- id="screenshotWindow"
4
- class=""
5
- @mouseover="emit('hover', true)"
6
- @mouseout="emit('hover', false)"
7
- >
2
+ <div id="webgl-container">
8
3
  <canvas
9
- id="unity-canvas"
4
+ id="canvas"
5
+ ref="canvas"
10
6
  width="100%"
11
- height="calc(100vh - 48px)"
7
+ height="100%"
12
8
  tabindex="-1"
13
- style="
14
- width: 100%;
15
- height: calc(100vh - 50px);
16
- background-size: cover !important;
17
- "
18
9
  >
19
10
  </canvas>
20
- <div id="parent-canvas" ref="parent_canvas">
11
+ <div id="overlay" ref="overlay">
21
12
  <slot></slot>
22
13
  </div>
23
14
  </div>
24
15
  </template>
25
- <script setup lang="ts">
26
- import { defineEmits, nextTick, onMounted, ref } from "vue";
27
16
 
28
- import {
29
- createInstance,
30
- executePayload,
31
- registerOnPayloadHandler,
32
- } from "@3cr/sdk-browser";
33
- import {
34
- FrontEndInterfaces,
35
- FrontEndPayload,
36
- } from "@3cr/sdk-browser/types/payload";
17
+ <script setup lang="ts">
18
+ import { onMounted, ref } from "vue";
19
+ import { useViewer3cr } from '@/dataLayer/useViewer3cr';
37
20
 
38
- const unityInstance = ref<any>(null);
21
+ const viewer3cr = useViewer3cr();
22
+ const canvas = ref<HTMLCanvasElement>();
23
+ const overlay = ref<HTMLDivElement>();
39
24
 
40
25
  const emit = defineEmits<{
41
26
  instance_loaded: [void];
42
- on_payload: [FrontEndInterfaces, string, string];
43
- hover: [boolean];
44
27
  }>();
45
28
 
46
- defineExpose({
47
- sendPayload,
48
- receiveMessageFromUnity,
49
- });
50
-
51
29
  onMounted(async () => {
52
- await nextTick();
53
- const canvas = document.querySelector("#unity-canvas") as HTMLCanvasElement;
54
-
55
- await registerOnPayloadHandler(receiveMessageFromUnity);
30
+ if (!canvas.value || !overlay.value) {
31
+ throw new Error('One or more canvases failed to load');
32
+ }
56
33
 
57
34
  /* c8 ignore start */
58
35
  if (/iPhone|iPad|iPod|Android/i.test(navigator.userAgent)) {
59
36
  // Mobile device style: fill the whole browser client area with the game canvas:
60
37
  const meta = document.createElement("meta");
61
38
  meta.name = "viewport";
62
- meta.content =
63
- "width=device-width, height=device-height, initial-scale=1.0, user-scalable=no, shrink-to-fit=yes";
39
+ meta.content = "width=device-width, height=device-height, initial-scale=1.0, user-scalable=no, shrink-to-fit=yes";
64
40
  document.getElementsByTagName("head")[0].appendChild(meta);
65
-
66
- canvas.style.width = "100%";
67
- canvas.style.height = "80vh";
68
- canvas.style.position = "fixed";
69
-
70
- document.body.style.textAlign = "left";
71
41
  }
72
- /* c8 ignore stop */
73
- await nextTick();
74
- unityInstance.value = await createInstance(canvas);
75
-
76
- await nextTick();
77
42
 
78
- /* c8 ignore start */
79
- if (navigator.storage) {
43
+ if (navigator.storage && navigator.storage.estimate) {
80
44
  const quota = await navigator.storage.estimate();
81
45
  if (quota) {
82
46
  const percentageUsed = (quota.usage! / quota.quota!) * 100;
@@ -87,55 +51,52 @@ onMounted(async () => {
87
51
  }
88
52
  /* c8 ignore stop */
89
53
 
90
- emit("instance_loaded");
91
54
  // Overlay scroll events to the container instance
92
- const fixedDiv = document.getElementById("parent-canvas");
93
55
  /* c8 ignore start */
94
- fixedDiv?.addEventListener("wheel", function (e: WheelEvent) {
95
- e.preventDefault();
96
- const evt = new WheelEvent("wheel", {
97
- ...e,
98
- deltaY: e.deltaY,
99
- });
100
- canvas.dispatchEvent(evt);
101
- });
102
- function injectEventListener(eventType: keyof HTMLElementEventMap) {
103
- fixedDiv?.addEventListener(eventType, function (e: Event) {
56
+ function injectEventListener(type: keyof HTMLElementEventMap) {
57
+ overlay.value!.addEventListener(type, (e: Event) => {
104
58
  e.preventDefault();
105
- const evt = new MouseEvent(eventType, {
106
- ...e,
107
- });
108
- canvas.dispatchEvent(evt);
59
+ canvas.value!.dispatchEvent(new MouseEvent(type, e));
109
60
  });
110
61
  }
111
- injectEventListener("mousedown");
112
- injectEventListener("mouseup");
113
- injectEventListener("mouseout");
114
- injectEventListener("mouseover");
115
- injectEventListener("mouseenter");
116
- injectEventListener("mouseleave");
117
- injectEventListener("mousemove");
118
- injectEventListener("contextmenu");
119
- injectEventListener("dblclick");
120
62
 
121
- fixedDiv?.addEventListener(
122
- "*",
123
- function (ev) {
124
- console.log(`${ev.type}`);
125
- ev.preventDefault();
126
- const evt = new Event(ev.type, { ...ev });
127
- canvas.dispatchEvent(evt);
128
- }
129
- // false
130
- );
63
+ overlay.value!.addEventListener("wheel", (e: WheelEvent) => {
64
+ e.preventDefault();
65
+ canvas.value!.dispatchEvent(new WheelEvent(e.type, e));
66
+ });
67
+
68
+ injectEventListener('click');
69
+ injectEventListener('dblclick');
70
+ injectEventListener('auxclick');
71
+ injectEventListener('mousedown');
72
+ injectEventListener('mousemove');
73
+ injectEventListener('mouseup');
74
+ injectEventListener('mouseout');
75
+ injectEventListener('mouseover');
76
+ injectEventListener('mouseenter');
77
+ injectEventListener('mouseleave');
78
+ injectEventListener('contextmenu');
79
+
80
+ await viewer3cr.register(canvas.value);
81
+ emit("instance_loaded");
131
82
 
132
83
  /* c8 ignore stop */
133
84
  });
134
85
 
135
- async function sendPayload(payload: string) {
136
- await executePayload(JSON.parse(payload));
86
+ defineExpose({ canvas });
87
+ </script>
88
+
89
+ <style scoped lang="scss">
90
+ #webgl-container {
91
+ position: relative;
92
+ width: 100%;
93
+ height: 100%;
137
94
  }
138
- function receiveMessageFromUnity(json: FrontEndPayload) {
139
- emit("on_payload", json.Interface, json.Action, json.Message);
95
+
96
+ #canvas, #overlay {
97
+ position: absolute;
98
+ inset: 0;
99
+ width: 100%;
100
+ height: 100%;
140
101
  }
141
- </script>
102
+ </style>
@@ -1,56 +1,37 @@
1
- import { expect, test, vi } from "vitest";
2
- import WebGL3DR from "../WebGL3DR.vue";
1
+ import { expect, describe, it } from "vitest";
3
2
  import { registerOnPayloadHandler, createInstance } from "@3cr/sdk-browser";
4
3
  import { mountVuetify } from "~/helper";
5
- import { FileManagementActions, FrontEndInterfaces } from "@3cr/types-ts";
6
-
7
- vi.mock("@3cr/sdk-browser", async (importOriginal) => {
8
- const mod = (await importOriginal()) as object;
9
- return {
10
- ...mod,
11
- registerVersion: vi.fn(),
12
- createInstance: vi.fn(),
13
- executePayload: vi.fn(),
14
- registerOnPayloadHandler: vi.fn(),
15
- };
16
- });
17
-
18
- const wrapper = mountVuetify(WebGL3DR);
4
+ import { nextTick } from "vue";
5
+ import WebGL3DR from "../WebGL3DR.vue";
19
6
 
20
- test("registers payload handler", () => {
21
- expect(registerOnPayloadHandler).toHaveBeenCalled();
22
- });
23
- test("creates instance", () => {
24
- expect(createInstance).toHaveBeenCalled();
25
- });
26
- test("creates instance", () => {
27
- wrapper.vm.receiveMessageFromUnity({
28
- Action: FileManagementActions.fm01 as any,
29
- Message: "testing message",
30
- Interface: FrontEndInterfaces.file_management as any,
7
+ describe('WebGL3DR spec', () => {
8
+ it("creates instance", async () => {
9
+ mountVuetify(WebGL3DR);
10
+ await nextTick();
11
+ expect(createInstance).toHaveBeenCalled();
12
+ expect(registerOnPayloadHandler).toHaveBeenCalled();
31
13
  });
32
14
 
33
- expect(wrapper.emitted()["on_payload"]).toStrictEqual([
34
- ["file_management", "fm_01", "testing message"],
35
- ]);
36
- });
37
-
38
- test("scrolling", () => {
39
- const parentCanvas = wrapper.find("#parent-canvas");
40
- parentCanvas.trigger("wheel");
41
- });
42
-
43
- test("mouseover", () => {
44
- const parentCanvas = wrapper.find("#screenshotWindow");
45
- parentCanvas.trigger("mouseover");
46
-
47
- expect(wrapper.emitted()["hover"]).toStrictEqual([[true]]);
48
- });
15
+ it("should emit wheel event", () => {
16
+ const wrapper = mountVuetify(WebGL3DR);
17
+ const overlay = wrapper.find("#overlay");
18
+ overlay.trigger("wheel");
19
+ expect(wrapper.emitted()["wheel"]).toBeTruthy();
20
+ });
49
21
 
50
- test("mouseout", () => {
51
- const parentCanvas = wrapper.find("#screenshotWindow");
52
- parentCanvas.trigger("mouseover");
53
- parentCanvas.trigger("mouseout");
22
+ it("should emit mouseover event", () => {
23
+ const wrapper = mountVuetify(WebGL3DR);
24
+ const overlay = wrapper.find("#overlay");
25
+ overlay.trigger("mouseover");
26
+ expect(wrapper.emitted()["mouseover"]).toBeTruthy();
27
+ });
54
28
 
55
- expect(wrapper.emitted()["hover"]).toStrictEqual([[true], [true], [false]]);
29
+ it("should emit mouseout event", () => {
30
+ const wrapper = mountVuetify(WebGL3DR);
31
+ const overlay = wrapper.find("#overlay");
32
+ overlay.trigger("mouseover");
33
+ overlay.trigger("mouseout");
34
+ expect(wrapper.emitted()["mouseover"]).toBeTruthy();
35
+ expect(wrapper.emitted()["mouseout"]).toBeTruthy();
36
+ });
56
37
  });
@@ -37,7 +37,7 @@ const modalState = computed({
37
37
  <v-card-text> support@singular.health </v-card-text>
38
38
  <v-card-actions>
39
39
  <v-spacer />
40
- <v-btn color="primary" @click="modalState = false"> Thanks! </v-btn>
40
+ <v-btn data-testid="close" color="primary" @click="modalState = false"> Thanks! </v-btn>
41
41
  </v-card-actions>
42
42
  </v-card>
43
43
  </v-dialog>
@@ -1,5 +1,6 @@
1
1
  <script setup lang="ts">
2
2
  import { computed } from "vue";
3
+ import {PRICING_URL} from "@/components/demo/options";
3
4
 
4
5
  export interface Props {
5
6
  modal: boolean;
@@ -39,6 +40,7 @@ function openUrl(url: string) {
39
40
  </v-card-text>
40
41
  <v-card-actions>
41
42
  <v-btn
43
+ data-testid="close"
42
44
  color="error"
43
45
  @click="modalState = false"
44
46
  :disabled="!isModalOpen"
@@ -47,9 +49,10 @@ function openUrl(url: string) {
47
49
  </v-btn>
48
50
  <v-spacer />
49
51
  <v-btn
52
+ data-testid="select-plan"
50
53
  variant="tonal"
51
54
  color="success"
52
- @click="openUrl('https://3dicomviewer.com/pricing')"
55
+ @click="openUrl(PRICING_URL)"
53
56
  >
54
57
  Select a Plan
55
58
  </v-btn>
@@ -0,0 +1,25 @@
1
+ import { describe, it, expect } from "vitest";
2
+ import {mountVuetify, openAllModals} from "~/helper";
3
+ import DemoModal from "@/components/demo/DemoModal.vue";
4
+
5
+ describe('DemoModal tests', () => {
6
+ it('should mount', () => {
7
+ const props = { modal: true };
8
+ const wrapper = mountVuetify(DemoModal, props);
9
+ expect(wrapper).toBeTruthy();
10
+ });
11
+
12
+ it('should close', async () => {
13
+ const props = { modal: true };
14
+ const wrapper = mountVuetify(DemoModal, props);
15
+ const button = wrapper.findComponent('[data-testid="close"]');
16
+ await button.trigger('click');
17
+ expect(wrapper.emitted()['update:modal']).toBeTruthy();
18
+ });
19
+
20
+ it('should open via input', async () => {
21
+ const props = { modal: false };
22
+ const wrapper = mountVuetify(DemoModal, props);
23
+ await openAllModals(wrapper);
24
+ });
25
+ });
@@ -0,0 +1,37 @@
1
+ import { describe, it, expect, vi } from "vitest";
2
+ import { mountVuetify, openAllModals } from "~/helper";
3
+ import { PRICING_URL } from "@/components/demo/options";
4
+ import DemoPatientModal from "@/components/demo/DemoPatientModal.vue";
5
+
6
+ describe('DemoPatientModal tests', () => {
7
+ it('should mount', () => {
8
+ const props = { modal: true, isModalOpen: true };
9
+ const wrapper = mountVuetify(DemoPatientModal, props);
10
+ expect(wrapper).toBeTruthy();
11
+ });
12
+
13
+ it('should close', async () => {
14
+ const props = { modal: true, isModalOpen: true };
15
+ const wrapper = mountVuetify(DemoPatientModal, props);
16
+ const button = wrapper.findComponent('[data-testid="close"]');
17
+ await button.trigger('click');
18
+ expect(wrapper.emitted()['update:modal']).toBeTruthy();
19
+ });
20
+
21
+ it('should open pricing url', async () => {
22
+ vi.stubGlobal('open', vi.fn());
23
+ const spy = vi.spyOn(window, 'open');
24
+ const props = { modal: true, isModalOpen: true };
25
+ const wrapper = mountVuetify(DemoPatientModal, props);
26
+ const button = wrapper.findComponent('[data-testid="select-plan"]');
27
+ await button.trigger('click');
28
+ expect(spy).toHaveBeenCalledWith(PRICING_URL, '_self');
29
+ vi.restoreAllMocks();
30
+ });
31
+
32
+ it('should open via input', async () => {
33
+ const props = { modal: false, isModalOpen: true };
34
+ const wrapper = mountVuetify(DemoPatientModal, props);
35
+ await openAllModals(wrapper);
36
+ });
37
+ });
@@ -0,0 +1,25 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { demoLicenceOptions, demoPatientOptions } from "@/components/demo/options";
3
+ import { LoadViewerOptions } from "@/models/LoadViewerOptions";
4
+
5
+ describe('options tests', () => {
6
+ it('should call demo license options', () => {
7
+ Object.keys(demoLicenceOptions).forEach(key => {
8
+ const k = key as keyof LoadViewerOptions;
9
+ const fn = demoLicenceOptions[k];
10
+ if (fn) {
11
+ expect(fn).not.toThrow();
12
+ }
13
+ });
14
+ });
15
+
16
+ it('should call demo patient options', () => {
17
+ Object.keys(demoPatientOptions).forEach(key => {
18
+ const k = key as keyof LoadViewerOptions;
19
+ const fn = demoPatientOptions[k];
20
+ if (fn) {
21
+ expect(fn).not.toThrow();
22
+ }
23
+ });
24
+ });
25
+ });