@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
@@ -0,0 +1,126 @@
1
+ <template>
2
+ <v-expansion-panels
3
+ :model-value="expanded"
4
+ class="bg-transparent text-white"
5
+ variant="accordion"
6
+ flat
7
+ tile
8
+ @update:model-value="onUpdate"
9
+ >
10
+ <template v-for="(item, index) in items" :key="item">
11
+ <v-expansion-panel v-if="item.visible()" :data-testid="`panel-${index}`" class="bg-transparent text-white px-0">
12
+ <v-expansion-panel-title :hide-actions="!drawer" class="font-weight-bold">
13
+ <v-icon :start="drawer" :icon="item.icon" />
14
+ <span v-show="drawer">{{ item.text }}</span>
15
+ <v-tooltip location="right" activator="parent">
16
+ {{ item.tooltip }}
17
+ </v-tooltip>
18
+ </v-expansion-panel-title>
19
+ <v-expansion-panel-text class="px-0">
20
+ <Component v-bind="item.props" :is="item.component" />
21
+ </v-expansion-panel-text>
22
+ </v-expansion-panel>
23
+ </template>
24
+ </v-expansion-panels>
25
+ </template>
26
+
27
+ <script setup lang="ts">
28
+ import { ComponentInstance, computed, ref, shallowRef, watch } from "vue";
29
+ import { LoadViewerOptions } from "@/models/LoadViewerOptions";
30
+ import { isSessionLoaded } from "@/dataLayer/scanState";
31
+ import ViewerDisplaySettings from "@/components/modal/ViewerDisplaySettings.vue";
32
+ import ViewerAnnotations from "@/components/modal/ViewerAnnotations.vue";
33
+
34
+ interface Props {
35
+ drawer?: boolean;
36
+ options: LoadViewerOptions
37
+ }
38
+
39
+ type Emits = {
40
+ 'update:drawer': [boolean];
41
+ 'update:expanded': [number | undefined];
42
+ };
43
+
44
+ interface SettingsItem {
45
+ icon: string;
46
+ text: string;
47
+ tooltip: string;
48
+ component: ComponentInstance<any>;
49
+ visible: () => boolean;
50
+ props: Record<string, any>;
51
+ }
52
+
53
+ const props = withDefaults(defineProps<Props>(), {
54
+ drawer: false
55
+ });
56
+
57
+ const emit = defineEmits<Emits>();
58
+
59
+ const previous = ref<number | undefined>(0);
60
+ const expanded = ref<number | undefined>(0);
61
+
62
+ const items = shallowRef<SettingsItem[]>([
63
+ {
64
+ icon: "display_settings",
65
+ text: "Display Settings",
66
+ tooltip: "Change the range of visible anatomy in the scan by only showing areas with certain density of tissue",
67
+ component: ViewerDisplaySettings,
68
+ visible: () => true,
69
+ props: {}
70
+ },
71
+ {
72
+ icon: "draw",
73
+ text: "Annotations",
74
+ tooltip: "Display annotations on your scans",
75
+ component: ViewerAnnotations,
76
+ visible: () => !!showAnnotations.value,
77
+ props: {}
78
+ },
79
+ ]);
80
+
81
+ const showAnnotations = computed(() => {
82
+ return props.options.OnLoadSavedSession && isSessionLoaded.value;
83
+ });
84
+
85
+ watch(() => props.drawer, (value: boolean) => {
86
+ if (value) {
87
+ expanded.value = previous.value;
88
+ emit('update:expanded', expanded.value);
89
+ } else {
90
+ previous.value = expanded.value;
91
+ expanded.value = undefined;
92
+ emit('update:expanded', expanded.value);
93
+ }
94
+ }, { immediate: true });
95
+
96
+ function onUpdate(event: unknown): void {
97
+ const value = event as number | undefined;
98
+ previous.value = value;
99
+ expanded.value = value;
100
+ emit('update:expanded', expanded.value);
101
+ if (!props.drawer && value !== undefined) {
102
+ emit('update:drawer', true)
103
+ }
104
+ }
105
+ </script>
106
+
107
+ <style scoped>
108
+ .v-expansion-panel-content__wrap {
109
+ padding: 0 8px 4px;
110
+ flex: 1 1 auto;
111
+ max-width: 100%;
112
+ }
113
+
114
+ .v-expansion-panel--active > .v-expansion-panel-header {
115
+ min-height: 48px;
116
+ }
117
+
118
+ .v-expansion-panel--active:not(:first-child),
119
+ .v-expansion-panel--active + .v-expansion-panel {
120
+ margin-top: 0;
121
+ }
122
+
123
+ .v-expansion-panel-text__wrapper {
124
+ padding: 8px 8px 16px;
125
+ }
126
+ </style>
@@ -0,0 +1,111 @@
1
+ <template>
2
+ <v-list>
3
+ <template v-for="(item, index) of footerItems" :key="item">
4
+ <v-tooltip location="right">
5
+ <template #activator="{ props }">
6
+ <v-list-item
7
+ v-if="item.visible()"
8
+ v-bind="props"
9
+ :data-testid="`footer-${index}`"
10
+ class="px-6"
11
+ target="_blank"
12
+ :disabled="disabled"
13
+ @click="item.click()"
14
+ >
15
+ <template v-slot:prepend>
16
+ <v-icon v-bind="item.iconProps" />
17
+ </template>
18
+ <v-list-item-title v-if="drawer" class="text-white">
19
+ <span>{{ item.text }}</span>
20
+ </v-list-item-title>
21
+ </v-list-item>
22
+ </template>
23
+ <span>{{ item.tooltip }}</span>
24
+ </v-tooltip>
25
+ </template>
26
+ </v-list>
27
+ </template>
28
+
29
+ <script setup lang="ts">
30
+ import { ref } from "vue";
31
+ import { currentColourPreset, initialScanState } from "@/dataLayer/scanState";
32
+ import { ViewSelectionActions } from "@3cr/types-ts";
33
+ import { LoadViewerOptions } from "@/models/LoadViewerOptions";
34
+ import { useViewer3cr } from "@/dataLayer/useViewer3cr";
35
+
36
+ interface Props {
37
+ options: LoadViewerOptions;
38
+ drawer?: boolean;
39
+ disabled?: boolean;
40
+ }
41
+
42
+ interface FooterItem {
43
+ text: string;
44
+ tooltip: string;
45
+ iconProps: Record<string, any>;
46
+ visible: () => boolean;
47
+ click: () => void | Promise<void>;
48
+ }
49
+
50
+ const props = withDefaults(defineProps<Props>(), {
51
+ drawer: false,
52
+ disabled: false
53
+ });
54
+
55
+ const viewer3cr = useViewer3cr();
56
+ const footerItems = ref<FooterItem[]>([
57
+ {
58
+ text: "Reset Scan",
59
+ tooltip: "Resets your scan to original position and settings in all views",
60
+ iconProps: { icon: "refresh", color: "red" },
61
+ visible: () => true,
62
+ click: async () => {
63
+ currentColourPreset.value = initialScanState.value.ColourPresets[0];
64
+ await viewer3cr.viewSelection(ViewSelectionActions.vs05);
65
+ await viewer3cr.viewSelection(ViewSelectionActions.vs06);
66
+ },
67
+ },
68
+ {
69
+ text: "Enable Cloud Storage",
70
+ tooltip: "Securely store your medical records in the cloud",
71
+ iconProps: { icon: "cloud", color: "blue" },
72
+ visible: () => !!props.options.OnEnableCloudStorage,
73
+ click: async () => {
74
+ await props.options.OnEnableCloudStorage!();
75
+ }
76
+ },
77
+ {
78
+ text: "Send to 3rd Party",
79
+ tooltip: "Securely share your loaded scan with 3rd parties via email with option to anonymise",
80
+ iconProps: { icon: "send", color: "green" },
81
+ visible: () => !!props.options.OnSendTo3rdParty,
82
+ click: async () => {
83
+ await props.options.OnSendTo3rdParty!();
84
+ }
85
+ },
86
+ {
87
+ text: "Share to Mobile / VR",
88
+ tooltip: "Share your loaded scan with the 3Dicom Mobile and VR applications to download within 7 days",
89
+ iconProps: { icon: "share", color: "yellow" },
90
+ visible: () => !!props.options.OnShareToMobile,
91
+ click: async () => {
92
+ await props.options.OnShareToMobile!();
93
+ }
94
+ },
95
+ {
96
+ text: "Screenshot View",
97
+ tooltip: 'Take a screenshot',
98
+ iconProps: { icon: "screenshot_region", color: "green" },
99
+ visible: () => !!props.options.OnScreenshot,
100
+ click: async () => {
101
+ await props.options.OnScreenshot!();
102
+ }
103
+ },
104
+ ]);
105
+ </script>
106
+
107
+ <style scoped>
108
+ .v-icon {
109
+ opacity: 1;
110
+ }
111
+ </style>
@@ -0,0 +1,63 @@
1
+ <template>
2
+ <div
3
+ v-if="!isDemo || demoType === 'patient'"
4
+ class="d-flex align-center pb-1"
5
+ :class="!drawer ? 'py-2' : 'pa-2'"
6
+ >
7
+ <v-img
8
+ v-if="drawer"
9
+ src="../../assets/images/dark/3dicom-logo.svg"
10
+ height="64"
11
+ alt="logo"
12
+ style="opacity: 0.9"
13
+ />
14
+ <v-img
15
+ v-else
16
+ src="../../assets/images/dark/3DICOM.png"
17
+ height="48"
18
+ alt="logo"
19
+ style="opacity: 0.9"
20
+ />
21
+ </div>
22
+ <div
23
+ v-else
24
+ class="d-flex align-center pb-1"
25
+ :class="!drawer ? 'py-2' : 'pa-2'"
26
+ >
27
+ <!-- TODO: Image probably needs to be cropped (1500 x 1500) -->
28
+ <v-img
29
+ v-if="drawer"
30
+ src="../../assets/images/dark/demo-logo.svg"
31
+ width="100%"
32
+ height="64"
33
+ :cover="true"
34
+ alt="logo"
35
+ style="opacity: 0.9"
36
+ />
37
+ <v-img
38
+ v-else
39
+ src="../../assets/images/dark/demo-icon-small.png"
40
+ height="48"
41
+ alt="logo"
42
+ style="opacity: 0.9"
43
+ />
44
+ </div>
45
+ <div
46
+ class="text-center mx-auto text-white sub-type"
47
+ :style="!drawer ? 'font-size: 100%' : 'font-size: 140%'"
48
+ >
49
+ Online Viewer
50
+ </div>
51
+ </template>
52
+
53
+ <script setup lang="ts">
54
+ import { demoType, isDemo } from "@/components/demo/options";
55
+
56
+ interface Props {
57
+ drawer?: boolean;
58
+ }
59
+
60
+ withDefaults(defineProps<Props>(), {
61
+ drawer: false
62
+ });
63
+ </script>
@@ -0,0 +1,60 @@
1
+ import { describe, expect, it, vi } from "vitest";
2
+ import { DOMWrapper, flushPromises } from "@vue/test-utils";
3
+ import { mountVuetify } from "~/helper";
4
+ import { defaultLoadViewerOptions } from "@/models/LoadViewerOptions";
5
+ import CloseViewerModal from "@/components/modal/CloseViewerModal.vue";
6
+
7
+ class CloseViewerModalHarness {
8
+ dialog(): DOMWrapper<Element> {
9
+ return new DOMWrapper(document.querySelector('[data-testid="dialog"]'));
10
+ }
11
+
12
+ close() {
13
+ return this.dialog().findComponent('[data-testid="close"]');
14
+ }
15
+
16
+ save() {
17
+ return this.dialog().findComponent('[data-testid="save"]');
18
+ }
19
+ }
20
+
21
+ describe('CloseViewerModal tests', () => {
22
+ const harness = new CloseViewerModalHarness();
23
+
24
+ it("should open modal", () => {
25
+ const props = { modal: true, options: defaultLoadViewerOptions };
26
+ const wrapper = mountVuetify(CloseViewerModal, props);
27
+ expect(wrapper.exists()).toBeTruthy();
28
+ });
29
+
30
+ it('should close modal', async () => {
31
+ const props = { modal: true, options: defaultLoadViewerOptions };
32
+ const wrapper = mountVuetify(CloseViewerModal, props);
33
+ expect(wrapper.exists()).toBeTruthy();
34
+ await wrapper.setProps({ modal: false });
35
+ // expect(wrapper.isVisible()).toBeFalsy();
36
+ });
37
+
38
+ it('should close modal without saving', async () => {
39
+ const props = { modal: true, options: defaultLoadViewerOptions };
40
+ const wrapper = mountVuetify(CloseViewerModal, props);
41
+ const onExitViewerSpy = vi.spyOn(defaultLoadViewerOptions, 'OnExitViewer');
42
+ expect(wrapper.exists()).toBeTruthy();
43
+ await harness.close().trigger('click');
44
+ expect(onExitViewerSpy).toHaveBeenCalled();
45
+ // expect(wrapper.isVisible()).toBeFalsy();
46
+ });
47
+
48
+ it('should close modal and save session', async () => {
49
+ const props = { modal: true, options: defaultLoadViewerOptions };
50
+ const wrapper = mountVuetify(CloseViewerModal, props);
51
+ const onExitViewerSpy = vi.spyOn(defaultLoadViewerOptions, 'OnExitViewer');
52
+ const onSaveSessionSpy = vi.spyOn(defaultLoadViewerOptions, 'OnSaveSession');
53
+ expect(wrapper.exists()).toBeTruthy();
54
+ await harness.save().trigger('click');
55
+ await flushPromises();
56
+ expect(onExitViewerSpy).toHaveBeenCalled();
57
+ expect(onSaveSessionSpy).toHaveBeenCalled();
58
+ // expect(wrapper.isVisible()).toBeFalsy();
59
+ })
60
+ });