@3cr/viewer-browser 0.0.220 → 0.0.247
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.
- package/components.d.ts +6 -2
- package/dist/Viewer3CR.js +32 -32
- package/dist/Viewer3CR.mjs +17808 -14315
- package/dist/Viewer3CR.umd.js +32 -32
- package/index.html +1 -1
- package/package.json +4 -3
- package/playground/index.html +4 -12
- package/src/App.vue +29 -14
- package/src/__tests__/main.spec.ts +4 -4
- package/src/assets/styles.scss +6 -2
- package/src/components/demo/DemoPatientModal.vue +12 -22
- package/src/components/demo/licence/DemoLicenceInfoModal.vue +11 -29
- package/src/components/demo/options.ts +42 -39
- package/src/components/demo/patient/DemoPatientInfoModal.vue +11 -29
- package/src/components/modal/CloseViewerModal.vue +1 -1
- package/src/components/modal/MftpWebGL3DRModal.vue +133 -120
- package/src/components/modal/ViewerActionRail.vue +0 -6
- package/src/components/modal/ViewerNavigationDrawerContent.vue +25 -16
- package/src/components/modal/ViewerNavigationDrawerFooter.vue +32 -9
- package/src/components/modal/ViewerNavigationDrawerHeader.vue +6 -1
- package/src/components/modal/WebGL3DR.vue +7 -0
- package/src/components/modal/__tests__/ViewerNavigationDrawerHeader.spec.ts +3 -2
- package/src/components/modal/buttons/AutoAnnotateBtn.vue +181 -13
- package/src/components/modal/menus/FileMenu.vue +2 -9
- package/src/components/modal/menus/SettingsMenu.vue +2 -7
- package/src/components/navigation/mcad/McadGlobalActions.vue +20 -0
- package/src/components/navigation/mcad/McadGlobalOpacitySlider.vue +103 -0
- package/src/components/navigation/mcad/McadGlobalScanViewBtn.vue +28 -0
- package/src/components/navigation/mcad/McadGlobalVisibilityBtn.vue +38 -0
- package/src/components/shared/LoadingSpinner.vue +27 -36
- package/src/components/views/AnnotationTreeView.vue +3 -1
- package/src/components/views/MarkupTreeView.vue +3 -1
- package/src/components/views/McadObjectTreeView.vue +46 -36
- package/src/components/views/modals/DataOverlayGeneralModal.vue +71 -0
- package/src/components/views/modals/DataOverlayMarkupModal.vue +60 -0
- package/src/components/views/modals/DataOverlayModal.vue +54 -55
- package/src/components/views/shared/Opacity.vue +0 -1
- package/src/composables/useDebounce.ts +11 -0
- package/src/composables/useIntroJs.ts +23 -6
- package/src/composables/useViewerOptions.ts +1 -0
- package/src/functions/guards/isDataOverlayAngle.ts +6 -0
- package/src/functions/guards/isDataOverlayLength.ts +6 -0
- package/src/functions/guards/isDataOverlayPolygon.ts +6 -0
- package/src/functions/modelHelper.ts +2 -0
- package/src/functions/notification.ts +63 -29
- package/src/main.ts +23 -15
- package/src/models/loadViewerOptions.ts +39 -0
- package/src/models/loadViewerPayload.ts +0 -7
- package/src/services/viewer-3cr.service.ts +13 -1
- package/src/tools/data-overlay.tool.ts +71 -0
- package/src/types/data-overlay-event.ts +5 -0
- package/src/types/data-overlay-info.ts +4 -0
- package/src/types/demo-type.ts +4 -0
- package/src/components/modal/actions/HideViewAction.vue +0 -38
- package/src/components/views/modals/DataOverlayModalManager.vue +0 -104
- package/src/components/views/modals/__tests__/DataOverlayModal.spec.ts +0 -33
- package/src/components/views/modals/__tests__/DataOverlayModalManager.spec.ts +0 -93
package/src/main.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { registerVersion } from '@3cr/sdk-browser';
|
|
1
|
+
import { registerVersion, quit } from '@3cr/sdk-browser';
|
|
2
2
|
import { ComponentPublicInstance, createApp } from 'vue';
|
|
3
3
|
import { usePlugins } from '@/plugins/usePlugins';
|
|
4
4
|
import { defaultLoadViewerOptions, LoadViewerOptions } from '@/models/loadViewerOptions';
|
|
@@ -6,22 +6,24 @@ import { LoadViewerPayload } from '@/models/loadViewerPayload';
|
|
|
6
6
|
import { injectedStyleId } from './config';
|
|
7
7
|
import { useVersion3cr } from '@/composables/useVersion3cr';
|
|
8
8
|
import App from '@/App.vue';
|
|
9
|
+
import { getAvailableLanguages, setLanguage } from '@3cr/translations-ts';
|
|
9
10
|
|
|
10
11
|
let mountedApp: ComponentPublicInstance | undefined = undefined;
|
|
11
12
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
export async function registerViewer(version: string) {
|
|
15
|
-
const newElement = document.createElement('div');
|
|
16
|
-
newElement.style.width = '0';
|
|
17
|
-
newElement.style.height = '0';
|
|
18
|
-
newElement.id = modalId;
|
|
19
|
-
document.body.appendChild(newElement);
|
|
20
|
-
|
|
13
|
+
export async function registerViewer(host: Element | string, version: string, language?: string): Promise<void> {
|
|
14
|
+
await registerVersion(version);
|
|
21
15
|
const app = createApp(App);
|
|
22
16
|
usePlugins(app);
|
|
23
|
-
mountedApp = app.mount(
|
|
24
|
-
|
|
17
|
+
mountedApp = app.mount(host);
|
|
18
|
+
|
|
19
|
+
const languages = await getAvailableLanguages();
|
|
20
|
+
if (language && languages.includes(language)) {
|
|
21
|
+
await setLanguage(language);
|
|
22
|
+
} else {
|
|
23
|
+
const documentLanguage = document.querySelector('html')?.getAttribute('lang');
|
|
24
|
+
const defaultLanguage = documentLanguage ?? languages[0];
|
|
25
|
+
await setLanguage(defaultLanguage);
|
|
26
|
+
}
|
|
25
27
|
|
|
26
28
|
const version3cr = useVersion3cr();
|
|
27
29
|
version3cr.value = version;
|
|
@@ -44,9 +46,15 @@ export async function loadSession(url: string): Promise<void> {
|
|
|
44
46
|
await (mountedApp as any).loadSession(url);
|
|
45
47
|
}
|
|
46
48
|
|
|
47
|
-
export async function ejectViewer() {
|
|
48
|
-
const modal = document.getElementById(modalId);
|
|
49
|
+
export async function ejectViewer(): Promise<void> {
|
|
49
50
|
const styleSheet = document.getElementById(injectedStyleId);
|
|
50
|
-
modal?.remove();
|
|
51
51
|
styleSheet?.remove();
|
|
52
|
+
await quit();
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export async function closeViewer(): Promise<void> {
|
|
56
|
+
if (!mountedApp) {
|
|
57
|
+
throw new Error('Please call `registerViewer(version: string)` first');
|
|
58
|
+
}
|
|
59
|
+
await (mountedApp as any).close();
|
|
52
60
|
}
|
|
@@ -1,7 +1,33 @@
|
|
|
1
1
|
import { ViewerCallback } from '@/models/callbacks';
|
|
2
2
|
import { CurrentDataOverlayState, CurrentMcadState, CurrentScanState } from '@3cr/types-ts';
|
|
3
|
+
import { Viewer3crService } from '@/services/viewer-3cr.service';
|
|
3
4
|
|
|
4
5
|
export interface LoadViewerOptions {
|
|
6
|
+
ViewerTitle?: string;
|
|
7
|
+
DisplaySettings?: {
|
|
8
|
+
Show?: boolean;
|
|
9
|
+
Title?: string;
|
|
10
|
+
Tooltip?: string;
|
|
11
|
+
Icon?: string;
|
|
12
|
+
};
|
|
13
|
+
Annotations?: {
|
|
14
|
+
Show?: boolean;
|
|
15
|
+
Title?: string;
|
|
16
|
+
Tooltip?: string;
|
|
17
|
+
Icon?: string;
|
|
18
|
+
};
|
|
19
|
+
Markups?: {
|
|
20
|
+
Show?: boolean;
|
|
21
|
+
Title?: string;
|
|
22
|
+
Tooltip?: string;
|
|
23
|
+
Icon?: string;
|
|
24
|
+
};
|
|
25
|
+
Mcad?: {
|
|
26
|
+
Show?: boolean;
|
|
27
|
+
Title?: string;
|
|
28
|
+
Tooltip?: string;
|
|
29
|
+
Icon?: string;
|
|
30
|
+
};
|
|
5
31
|
OnAutoAnnotate?: ViewerCallback;
|
|
6
32
|
OnClosePopup?: ViewerCallback;
|
|
7
33
|
OnDownloadDicomSeries?: ViewerCallback;
|
|
@@ -18,6 +44,19 @@ export interface LoadViewerOptions {
|
|
|
18
44
|
OnSendTo3rdParty?: ViewerCallback;
|
|
19
45
|
OnShare?: ViewerCallback;
|
|
20
46
|
OnShareToMobile?: ViewerCallback;
|
|
47
|
+
OnInteractionReady?: ViewerCallback;
|
|
48
|
+
OnViewerLoaded?: ViewerCallback<void, [Viewer3crService]>;
|
|
49
|
+
ShowFileMenu?: boolean;
|
|
50
|
+
ShowSettingsMenu?: boolean;
|
|
51
|
+
ShowAiMenu?: boolean;
|
|
52
|
+
Show2x2Layout?: boolean;
|
|
53
|
+
Show1x3Layout?: boolean;
|
|
54
|
+
ShowTutorial?: boolean;
|
|
55
|
+
ShowResetScan?: boolean;
|
|
56
|
+
ShowEnableCloudStorage?: boolean;
|
|
57
|
+
ShowSendTo3rdParty?: boolean;
|
|
58
|
+
ShowShareToMobile?: boolean;
|
|
59
|
+
ShowScreenshot?: boolean;
|
|
21
60
|
}
|
|
22
61
|
|
|
23
62
|
export const defaultLoadViewerOptions: LoadViewerOptions = {
|
|
@@ -8,13 +8,6 @@ export interface MftpDecryptionKey {
|
|
|
8
8
|
Iv: string;
|
|
9
9
|
}
|
|
10
10
|
|
|
11
|
-
export const defaultLoadViewerPayload_old: LoadViewerPayload = {
|
|
12
|
-
Url: 'https://webgl-3dr.singular.health/demo/scans/chest.3vxl',
|
|
13
|
-
DecryptionKey: {
|
|
14
|
-
Iv: 'XEloSh+OcO7TG77au6HjPw==',
|
|
15
|
-
Key: 'KUc722X1y4w42M+jCf9a3+6EGz66z7UMWK3m2aMqGxM='
|
|
16
|
-
}
|
|
17
|
-
};
|
|
18
11
|
export const defaultLoadViewerPayload: LoadViewerPayload = {
|
|
19
12
|
Url: 'https://webgl-3dr.singular.health/demo/scans/chest_v6.3vxl',
|
|
20
13
|
DecryptionKey: {
|
|
@@ -22,7 +22,8 @@ import {
|
|
|
22
22
|
ObjectColour,
|
|
23
23
|
ObjectInvert,
|
|
24
24
|
ObjectVisibility,
|
|
25
|
-
ViewToggleData
|
|
25
|
+
ViewToggleData,
|
|
26
|
+
GraphicType
|
|
26
27
|
} from '@3cr/types-ts';
|
|
27
28
|
import { LoadViewerPayload } from '@/models/loadViewerPayload';
|
|
28
29
|
import { currentColourPreset, previousLayout, transactionStarted } from '@/models/scanState';
|
|
@@ -338,6 +339,17 @@ export class Viewer3crService {
|
|
|
338
339
|
});
|
|
339
340
|
}
|
|
340
341
|
|
|
342
|
+
/**
|
|
343
|
+
* NC-08: Set Navigation Cube Face Graphics.
|
|
344
|
+
* @param type Face type of cube.
|
|
345
|
+
*/
|
|
346
|
+
async setNavCubeGraphics(type: GraphicType): Promise<void> {
|
|
347
|
+
await this.sendPayload(FrontEndInterfaces.navigation_cube, NavigationCubeActions.nc08, {
|
|
348
|
+
Version: '0.0.1',
|
|
349
|
+
Value: type
|
|
350
|
+
});
|
|
351
|
+
}
|
|
352
|
+
|
|
341
353
|
/**
|
|
342
354
|
* SM-13: Pan the selected view to the left.
|
|
343
355
|
* @param view The view.
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { McadObjectInteraction } from '@/types/mcad-object-interaction';
|
|
2
|
+
import { Interactiontype } from '@3cr/types-ts';
|
|
3
|
+
import { DataOverlay } from '@/types/data-overlay';
|
|
4
|
+
import { ref, watch, WatchStopHandle } from 'vue';
|
|
5
|
+
import { useAnnotations } from '@/composables/useAnnotations';
|
|
6
|
+
import { useMarkups } from '@/composables/useMarkups';
|
|
7
|
+
import { useMcadObjects } from '@/composables/useMcadObjects';
|
|
8
|
+
import { DataOverlayInteraction } from '@/types/data-overlay-interaction';
|
|
9
|
+
|
|
10
|
+
export function useDataOverlayTool() {
|
|
11
|
+
let _flag = false;
|
|
12
|
+
let _focused: DataOverlay | null = null;
|
|
13
|
+
let _handles: WatchStopHandle[] = [];
|
|
14
|
+
|
|
15
|
+
const { annotationEvent } = useAnnotations();
|
|
16
|
+
const { markupEvent } = useMarkups();
|
|
17
|
+
const { mcadObjectEvent } = useMcadObjects();
|
|
18
|
+
const selected = ref<DataOverlay | null>(null);
|
|
19
|
+
|
|
20
|
+
function activate(): void {
|
|
21
|
+
document.addEventListener('mousedown', onMouseDown);
|
|
22
|
+
document.addEventListener('mousemove', onMouseMove);
|
|
23
|
+
document.addEventListener('mouseup', onMouseUp);
|
|
24
|
+
_handles.push(
|
|
25
|
+
watch(annotationEvent, onInteraction),
|
|
26
|
+
watch(markupEvent, onInteraction),
|
|
27
|
+
watch(mcadObjectEvent, onMcadInteraction)
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function deactivate(): void {
|
|
32
|
+
document.removeEventListener('mousedown', onMouseDown);
|
|
33
|
+
document.removeEventListener('mousemove', onMouseMove);
|
|
34
|
+
document.removeEventListener('mouseup', onMouseUp);
|
|
35
|
+
_handles.forEach((handle) => handle());
|
|
36
|
+
_handles = [];
|
|
37
|
+
selected.value = null;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function onMouseDown(): void {
|
|
41
|
+
_flag = true;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function onMouseMove(): void {
|
|
45
|
+
_flag = false;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function onMouseUp(): void {
|
|
49
|
+
if (_flag) {
|
|
50
|
+
selected.value = _focused;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function onInteraction(event: DataOverlayInteraction<DataOverlay> | null): void {
|
|
55
|
+
if (event?.Interaction === Interactiontype.HOVER_START) {
|
|
56
|
+
_focused = event.DataOverlay;
|
|
57
|
+
} else if (event?.Interaction === Interactiontype.HOVER_END) {
|
|
58
|
+
_focused = null;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function onMcadInteraction(event: McadObjectInteraction | null): void {
|
|
63
|
+
if (event?.Interaction === Interactiontype.HOVER_START) {
|
|
64
|
+
_focused = event.Mcad;
|
|
65
|
+
} else if (event?.Interaction === Interactiontype.HOVER_END) {
|
|
66
|
+
_focused = null;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
return { selected, activate, deactivate };
|
|
71
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { DataOverlay } from '@/types/data-overlay';
|
|
2
|
+
import { DataOverlayData } from '@/types/data-overlay-data';
|
|
3
|
+
import { DataOverlayInteraction } from '@/types/data-overlay-interaction';
|
|
4
|
+
|
|
5
|
+
export type DataOverlayEvent<T extends DataOverlay> = DataOverlayData<DataOverlayInteraction<T>>;
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<Action :text="text" :icon="icon" :variant="variant" @click="hide" />
|
|
3
|
-
</template>
|
|
4
|
-
|
|
5
|
-
<script setup lang="ts">
|
|
6
|
-
import { ScanView } from '@3cr/types-ts';
|
|
7
|
-
import { useViewer3cr } from '@/composables/useViewer3cr';
|
|
8
|
-
import { computed, ref } from 'vue';
|
|
9
|
-
import { getViewName } from '@/models/scanState';
|
|
10
|
-
|
|
11
|
-
interface Props {
|
|
12
|
-
view: ScanView;
|
|
13
|
-
variant?: 'button' | 'menu-item';
|
|
14
|
-
}
|
|
15
|
-
const isHidden = ref<boolean>(false);
|
|
16
|
-
|
|
17
|
-
const props = withDefaults(defineProps<Props>(), {
|
|
18
|
-
variant: 'button'
|
|
19
|
-
});
|
|
20
|
-
|
|
21
|
-
const icon = computed(() => {
|
|
22
|
-
return isHidden.value ? 'visibility' : 'visibility_off';
|
|
23
|
-
});
|
|
24
|
-
|
|
25
|
-
const text = computed(() => {
|
|
26
|
-
return isHidden.value ? `Show the ${getViewName(props.view)} view.` : `Hide the ${getViewName(props.view)} view.`;
|
|
27
|
-
});
|
|
28
|
-
|
|
29
|
-
const viewer3cr = useViewer3cr();
|
|
30
|
-
|
|
31
|
-
async function hide(): Promise<void> {
|
|
32
|
-
await viewer3cr.viewSelectionToggleView({
|
|
33
|
-
View: props.view,
|
|
34
|
-
Visibility: isHidden.value
|
|
35
|
-
});
|
|
36
|
-
isHidden.value = !isHidden.value;
|
|
37
|
-
}
|
|
38
|
-
</script>
|
|
@@ -1,104 +0,0 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<template v-for="[item, modal] of modals" :key="item">
|
|
3
|
-
<data-overlay-modal :modal="modal" :item="item" />
|
|
4
|
-
</template>
|
|
5
|
-
</template>
|
|
6
|
-
|
|
7
|
-
<script setup lang="ts">
|
|
8
|
-
import { ref, watch } from 'vue';
|
|
9
|
-
import { Interactiontype } from '@3cr/types-ts';
|
|
10
|
-
import { DataOverlayInfo } from '@/types/data-overlay-info';
|
|
11
|
-
import { DataOverlay } from '@/types/data-overlay';
|
|
12
|
-
import { useMouse } from '@/composables/useMouse';
|
|
13
|
-
import { useAnnotations } from '@/composables/useAnnotations';
|
|
14
|
-
import { useMarkups } from '@/composables/useMarkups';
|
|
15
|
-
import { useMcadObjects } from '@/composables/useMcadObjects';
|
|
16
|
-
import { useEventListener } from '@/composables/useEventListener';
|
|
17
|
-
import { GptService } from '@/services/gpt.service';
|
|
18
|
-
import { GptResponsePayload } from '@/types/gpt-response-payload';
|
|
19
|
-
|
|
20
|
-
useEventListener(document, 'mousedown', onMouseDown);
|
|
21
|
-
const { x, y } = useMouse(document);
|
|
22
|
-
const { annotationEvent } = useAnnotations();
|
|
23
|
-
const { markupEvent } = useMarkups();
|
|
24
|
-
const { mcadObjectEvent } = useMcadObjects();
|
|
25
|
-
|
|
26
|
-
const modals = ref<Map<DataOverlayInfo, boolean>>(new Map<DataOverlayInfo, boolean>());
|
|
27
|
-
const smartDescriptions = ref<Record<string, GptResponsePayload>>({});
|
|
28
|
-
|
|
29
|
-
watch(
|
|
30
|
-
annotationEvent,
|
|
31
|
-
async (event) => {
|
|
32
|
-
if (event?.Interaction === Interactiontype.POINTER_UP) {
|
|
33
|
-
await generateSmartDescriptions(event.DataOverlay);
|
|
34
|
-
const item = mapToDataOverlayModal(event.DataOverlay);
|
|
35
|
-
modals.value.set(item, true);
|
|
36
|
-
}
|
|
37
|
-
},
|
|
38
|
-
{ immediate: true }
|
|
39
|
-
);
|
|
40
|
-
|
|
41
|
-
watch(
|
|
42
|
-
markupEvent,
|
|
43
|
-
async (event) => {
|
|
44
|
-
if (event?.Interaction === Interactiontype.POINTER_UP) {
|
|
45
|
-
await generateSmartDescriptions(event.DataOverlay);
|
|
46
|
-
const item = mapToDataOverlayModal(event.DataOverlay);
|
|
47
|
-
modals.value.set(item, true);
|
|
48
|
-
}
|
|
49
|
-
},
|
|
50
|
-
{ immediate: true }
|
|
51
|
-
);
|
|
52
|
-
|
|
53
|
-
watch(
|
|
54
|
-
mcadObjectEvent,
|
|
55
|
-
async (event) => {
|
|
56
|
-
if (event?.Interaction === Interactiontype.POINTER_UP) {
|
|
57
|
-
await generateSmartDescriptions(event.Mcad as any);
|
|
58
|
-
const item = mapToDataOverlayModal(event.Mcad as any);
|
|
59
|
-
modals.value.set(item, true);
|
|
60
|
-
}
|
|
61
|
-
},
|
|
62
|
-
{ immediate: true }
|
|
63
|
-
);
|
|
64
|
-
|
|
65
|
-
function onMouseDown(): void {
|
|
66
|
-
for (const [key, value] of modals.value.entries()) {
|
|
67
|
-
if (value) {
|
|
68
|
-
modals.value.set(key, false);
|
|
69
|
-
setTimeout(() => modals.value.delete(key), 500); // wait for animation
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
async function generateSmartDescriptions(overlay: DataOverlay): Promise<void> {
|
|
75
|
-
const key = overlay.Title;
|
|
76
|
-
if (!(key in smartDescriptions.value)) {
|
|
77
|
-
const response = await GptService.Instantiate().GenerateAnnotations(key);
|
|
78
|
-
smartDescriptions.value[key] = response.data;
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
function mapToDataOverlayModal(overlay: DataOverlay): DataOverlayInfo {
|
|
83
|
-
return {
|
|
84
|
-
id: overlay.Id,
|
|
85
|
-
title: overlay.Title,
|
|
86
|
-
target: [x.value, y.value],
|
|
87
|
-
data: [
|
|
88
|
-
{
|
|
89
|
-
icon: overlay.Description ? 'description' : 'psychology',
|
|
90
|
-
title: overlay.Description ? 'Description' : 'Smart Description',
|
|
91
|
-
subtitle: overlay.Description || smartDescriptions.value[overlay.Title].GptResponse
|
|
92
|
-
},
|
|
93
|
-
{
|
|
94
|
-
icon: 'help',
|
|
95
|
-
title: 'Resources',
|
|
96
|
-
actions: overlay.CallToAction?.Actions.map((action) => ({
|
|
97
|
-
url: action.ActionData.Url,
|
|
98
|
-
description: action.ActionData.Description
|
|
99
|
-
}))
|
|
100
|
-
}
|
|
101
|
-
]
|
|
102
|
-
};
|
|
103
|
-
}
|
|
104
|
-
</script>
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
import DataOverlayModal from '@/components/views/modals/DataOverlayModal.vue';
|
|
2
|
-
import { DataOverlayInfoFaker } from '@test/fakers/data-overlay-info.faker';
|
|
3
|
-
import { mount } from '@vue/test-utils';
|
|
4
|
-
import { VCard, VMenu } from 'vuetify/components';
|
|
5
|
-
|
|
6
|
-
describe('DataOverlayInfo tests', () => {
|
|
7
|
-
it('should mount', () => {
|
|
8
|
-
const item = DataOverlayInfoFaker.random();
|
|
9
|
-
const props = { item, modal: true };
|
|
10
|
-
const wrapper = mount(DataOverlayModal, { props });
|
|
11
|
-
expect(wrapper).toBeTruthy();
|
|
12
|
-
});
|
|
13
|
-
|
|
14
|
-
it('should open and close menu', async () => {
|
|
15
|
-
const item = DataOverlayInfoFaker.random();
|
|
16
|
-
const props = { item, modal: true };
|
|
17
|
-
const wrapper = mount(DataOverlayModal, { props });
|
|
18
|
-
const menu = wrapper.findComponent(VMenu);
|
|
19
|
-
await menu.setValue(false);
|
|
20
|
-
await wrapper.setProps({ modal: false });
|
|
21
|
-
expect(wrapper.findComponent(VCard).isVisible()).toBeFalsy();
|
|
22
|
-
});
|
|
23
|
-
|
|
24
|
-
it('should open link', async () => {
|
|
25
|
-
const item = DataOverlayInfoFaker.random(1);
|
|
26
|
-
const props = { item, modal: true };
|
|
27
|
-
const wrapper = mount(DataOverlayModal, { props });
|
|
28
|
-
const card = wrapper.findComponent(VCard);
|
|
29
|
-
const anchor = card.find('a');
|
|
30
|
-
await anchor.trigger('click');
|
|
31
|
-
expect(anchor.attributes('href')).toBe(item.data[0].actions![0].url);
|
|
32
|
-
});
|
|
33
|
-
});
|
|
@@ -1,93 +0,0 @@
|
|
|
1
|
-
import { GptService } from '@/services/gpt.service';
|
|
2
|
-
import { DOMWrapper, flushPromises, mount } from '@vue/test-utils';
|
|
3
|
-
import { useAnnotations } from '@/composables/useAnnotations';
|
|
4
|
-
import { DataOverlayInteractionFaker } from '@test/fakers/data-overlay-interaction.faker';
|
|
5
|
-
import { Interactiontype } from '@3cr/types-ts';
|
|
6
|
-
import { useMarkups } from '@/composables/useMarkups';
|
|
7
|
-
import { McadObjectInteractionFaker } from '@test/fakers/mcad-object-interaction.faker';
|
|
8
|
-
import { useMcadObjects } from '@/composables/useMcadObjects';
|
|
9
|
-
import { VCard } from 'vuetify/components';
|
|
10
|
-
import { GptResponsePayload } from '@/types/gpt-response-payload';
|
|
11
|
-
import DataOverlayModalManager from '@/components/views/modals/DataOverlayModalManager.vue';
|
|
12
|
-
import DataOverlayModal from '@/components/views/modals/DataOverlayModal.vue';
|
|
13
|
-
|
|
14
|
-
const gpt: GptResponsePayload = {
|
|
15
|
-
GptResponse: 'Example',
|
|
16
|
-
FollowupQuestions: []
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
describe('DataOverlayModalManager tests', () => {
|
|
20
|
-
beforeEach(() => {
|
|
21
|
-
vi.spyOn(GptService.prototype, 'GenerateAnnotations').mockResolvedValue({ data: gpt } as any);
|
|
22
|
-
});
|
|
23
|
-
|
|
24
|
-
it('should mount', () => {
|
|
25
|
-
const wrapper = mount(DataOverlayModalManager);
|
|
26
|
-
expect(wrapper).toBeTruthy();
|
|
27
|
-
});
|
|
28
|
-
|
|
29
|
-
it('should display annotation on pointer up', async () => {
|
|
30
|
-
const event = DataOverlayInteractionFaker.annotation(Interactiontype.POINTER_UP);
|
|
31
|
-
const { annotationEvent } = useAnnotations();
|
|
32
|
-
vi.spyOn(annotationEvent, 'value', 'get').mockReturnValue(event);
|
|
33
|
-
|
|
34
|
-
const wrapper = mount(DataOverlayModalManager);
|
|
35
|
-
await flushPromises();
|
|
36
|
-
expect(wrapper.findComponent(DataOverlayModal).exists()).toBeTruthy();
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
it('should display markup on pointer up', async () => {
|
|
40
|
-
const event = DataOverlayInteractionFaker.polygon(Interactiontype.POINTER_UP);
|
|
41
|
-
const { markupEvent } = useMarkups();
|
|
42
|
-
vi.spyOn(markupEvent, 'value', 'get').mockReturnValue(event);
|
|
43
|
-
|
|
44
|
-
const wrapper = mount(DataOverlayModalManager);
|
|
45
|
-
await flushPromises();
|
|
46
|
-
expect(wrapper.findComponent(DataOverlayModal).exists()).toBeTruthy();
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
it('should display mcad on pointer up', async () => {
|
|
50
|
-
const event = McadObjectInteractionFaker.random(Interactiontype.POINTER_UP);
|
|
51
|
-
const { mcadObjectEvent } = useMcadObjects();
|
|
52
|
-
vi.spyOn(mcadObjectEvent, 'value', 'get').mockReturnValue(event);
|
|
53
|
-
|
|
54
|
-
const wrapper = mount(DataOverlayModalManager);
|
|
55
|
-
await flushPromises();
|
|
56
|
-
expect(wrapper.findComponent(DataOverlayModal).exists()).toBeTruthy();
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
it('should generate smart description if none provided', async () => {
|
|
60
|
-
const event = DataOverlayInteractionFaker.annotation(Interactiontype.POINTER_UP);
|
|
61
|
-
event.DataOverlay.Description = '';
|
|
62
|
-
const { annotationEvent } = useAnnotations();
|
|
63
|
-
vi.spyOn(annotationEvent, 'value', 'get').mockReturnValue(event);
|
|
64
|
-
|
|
65
|
-
const wrapper = mount(DataOverlayModalManager);
|
|
66
|
-
await flushPromises();
|
|
67
|
-
expect(wrapper.findComponent(VCard).text()).toContain('Smart Description');
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
describe('timed tests', () => {
|
|
71
|
-
beforeEach(() => {
|
|
72
|
-
vi.useFakeTimers();
|
|
73
|
-
});
|
|
74
|
-
|
|
75
|
-
afterEach(() => {
|
|
76
|
-
vi.useRealTimers();
|
|
77
|
-
});
|
|
78
|
-
|
|
79
|
-
it('should dismiss modal on mousedown', async () => {
|
|
80
|
-
const event = DataOverlayInteractionFaker.annotation(Interactiontype.POINTER_UP);
|
|
81
|
-
const { annotationEvent } = useAnnotations();
|
|
82
|
-
vi.spyOn(annotationEvent, 'value', 'get').mockReturnValue(event);
|
|
83
|
-
|
|
84
|
-
const wrapper = mount(DataOverlayModalManager);
|
|
85
|
-
await flushPromises();
|
|
86
|
-
|
|
87
|
-
await new DOMWrapper(document).trigger('mousedown');
|
|
88
|
-
vi.advanceTimersByTime(500);
|
|
89
|
-
await flushPromises();
|
|
90
|
-
expect(wrapper.findComponent(DataOverlayModal).exists()).toBeFalsy();
|
|
91
|
-
});
|
|
92
|
-
});
|
|
93
|
-
});
|