@3cr/viewer-browser 0.0.220 → 0.0.246
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 +22 -13
- 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/index.html
CHANGED
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
const testVersion = (window.location.href.includes('test.') || window.location.href.includes('localhost')) && new URLSearchParams(window.location.search).get("build_version")
|
|
33
33
|
const version = testVersion ?? dynamicConfig.value["sdkVersion"] ?? "1.1.0";
|
|
34
34
|
|
|
35
|
-
await registerViewer(version);
|
|
35
|
+
await registerViewer('#app', version);
|
|
36
36
|
await loadViewer();
|
|
37
37
|
</script>
|
|
38
38
|
</body>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@3cr/viewer-browser",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.246",
|
|
4
4
|
"main": "./dist/Viewer3CR.umd.js",
|
|
5
5
|
"module": "dist/Viewer3CR.umd.js",
|
|
6
6
|
"homepage": "https://docs.3cr.singular.health",
|
|
@@ -21,8 +21,9 @@
|
|
|
21
21
|
"coverage": "vitest run --coverage"
|
|
22
22
|
},
|
|
23
23
|
"dependencies": {
|
|
24
|
-
"@3cr/sdk-browser": "^1.0.
|
|
25
|
-
"@3cr/
|
|
24
|
+
"@3cr/sdk-browser": "^1.0.17",
|
|
25
|
+
"@3cr/translations-ts": "^1.0.1",
|
|
26
|
+
"@3cr/types-ts": "^1.0.166",
|
|
26
27
|
"@kyvg/vue3-notification": "^3.2.1",
|
|
27
28
|
"@mdi/font": "^7.4.47",
|
|
28
29
|
"@mdi/js": "^7.4.47",
|
package/playground/index.html
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
<!DOCTYPE html>
|
|
2
2
|
<html lang="en">
|
|
3
|
-
|
|
4
3
|
<head>
|
|
5
4
|
<meta charset="UTF-8" />
|
|
6
5
|
<link rel="icon" href="/favicon.ico" />
|
|
@@ -14,7 +13,7 @@
|
|
|
14
13
|
<meta name="msapplication-TileColor" content="#da532c">
|
|
15
14
|
<meta name="theme-color" content="#ffffff">
|
|
16
15
|
|
|
17
|
-
<script src="https://cdn.jsdelivr.net/npm/@3cr/viewer-browser@{{version}}/dist/Viewer3CR.umd.js"
|
|
16
|
+
<script src="https://cdn.jsdelivr.net/npm/@3cr/viewer-browser@{{version}}/dist/Viewer3CR.umd.js"></script>
|
|
18
17
|
<script type="module">
|
|
19
18
|
const channel = new BroadcastChannel('GET_SERVICE_WORKER_BUILD');
|
|
20
19
|
channel.addEventListener('message', event => {
|
|
@@ -69,19 +68,15 @@
|
|
|
69
68
|
<script src="https://cdn.jsdelivr.net/npm/@statsig/js-client@latest/build/statsig-js-client+session-replay+web-analytics.min.js"></script>
|
|
70
69
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
71
70
|
<title>3CR Viewer Playground</title>
|
|
72
|
-
|
|
73
71
|
</head>
|
|
74
|
-
|
|
75
72
|
<body>
|
|
76
73
|
<div id="app"></div>
|
|
77
74
|
<script type="module">
|
|
78
|
-
|
|
79
75
|
const { StatsigClient, runStatsigAutoCapture } = window.Statsig;
|
|
80
76
|
const isTest = (window.location.href.includes('test.') || window.location.href.includes('localhost'))
|
|
81
|
-
const client = new StatsigClient(
|
|
82
|
-
"client-YaAjxOTTRbuSN3peDAwXEzErieXpI744a3OHDgonzvV",
|
|
77
|
+
const client = new StatsigClient("client-YaAjxOTTRbuSN3peDAwXEzErieXpI744a3OHDgonzvV",
|
|
83
78
|
{ userID: undefined },
|
|
84
|
-
{environment: {tier: isTest ? 'development' : 'production'}}
|
|
79
|
+
{ environment: { tier: isTest ? 'development' : 'production' } }
|
|
85
80
|
);
|
|
86
81
|
client.initializeSync()
|
|
87
82
|
runStatsigAutoCapture(client);
|
|
@@ -93,15 +88,12 @@
|
|
|
93
88
|
if (!testVersion) {
|
|
94
89
|
version = dynamicConfig.value["sdkVersion"] ?? "1.1.0";
|
|
95
90
|
}
|
|
96
|
-
// const version = testVersion || dynamicConfig.value["sdkVersion"] ?? "1.1.0";
|
|
97
91
|
|
|
98
92
|
client.initializeAsync().then(() => {
|
|
99
|
-
window.registerViewer(version).then(() => {
|
|
93
|
+
window.registerViewer('#app', version).then(() => {
|
|
100
94
|
window.loadViewer().then()
|
|
101
95
|
})
|
|
102
96
|
}).catch((err) => console.error(err));
|
|
103
|
-
|
|
104
97
|
</script>
|
|
105
98
|
</body>
|
|
106
|
-
|
|
107
99
|
</html>
|
package/src/App.vue
CHANGED
|
@@ -1,17 +1,34 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<v-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
2
|
+
<MftpWebGL3DRModal v-if="show" ref="mftpWebGL3DRModal" :payload="payload" :options="options" />
|
|
3
|
+
<DemoLicenceInfoModal v-model:modal="m_demoLicence" />
|
|
4
|
+
<DemoLicenceShareToMobileModal v-model:modal="m_demoLicenceShareToMobile" />
|
|
5
|
+
<DemoLicenceSendToPartyModal v-model:modal="m_demoLicenceSendToParty" />
|
|
6
|
+
<DemoLicenceEnableCloudStorageModal v-model:modal="m_demoLicenseEnableCloudStorage" />
|
|
7
|
+
<DemoPatientInfoModal v-model:modal="m_demoPatient" />
|
|
8
|
+
<DemoPatientShareToMobileModal v-model:modal="m_demoPatientShareToMobile" />
|
|
9
|
+
<DemoPatientSendToPartyModal v-model:modal="m_demoPatientSendToParty" />
|
|
10
|
+
<DemoPatientEnableCloudStorageModal v-model:modal="m_demoPatientEnableCloudStorage" />
|
|
11
|
+
<Notifications />
|
|
12
|
+
<update-snackbar />
|
|
7
13
|
</template>
|
|
8
14
|
|
|
9
15
|
<script setup lang="ts">
|
|
10
|
-
import {
|
|
16
|
+
import { ref } from 'vue';
|
|
11
17
|
import { Notifications } from '@kyvg/vue3-notification';
|
|
12
18
|
import { defaultLoadViewerPayload, LoadViewerPayload } from '@/models/loadViewerPayload';
|
|
13
19
|
import { defaultLoadViewerOptions, LoadViewerOptions } from '@/models/loadViewerOptions';
|
|
14
|
-
import {
|
|
20
|
+
import {
|
|
21
|
+
isDemo,
|
|
22
|
+
m_demoLicence,
|
|
23
|
+
m_demoLicenceSendToParty,
|
|
24
|
+
m_demoLicenceShareToMobile,
|
|
25
|
+
m_demoLicenseEnableCloudStorage,
|
|
26
|
+
m_demoPatient,
|
|
27
|
+
m_demoPatientEnableCloudStorage,
|
|
28
|
+
m_demoPatientSendToParty,
|
|
29
|
+
m_demoPatientShareToMobile,
|
|
30
|
+
show
|
|
31
|
+
} from '@/components/demo/options';
|
|
15
32
|
import MftpWebGL3DRModal from '@/components/modal/MftpWebGL3DRModal.vue';
|
|
16
33
|
import LogRocket from 'logrocket';
|
|
17
34
|
|
|
@@ -26,16 +43,17 @@ const mftpWebGL3DRModal = ref<typeof MftpWebGL3DRModal>();
|
|
|
26
43
|
async function loadInstance(payloadIncoming: LoadViewerPayload | undefined, optionsIncoming: LoadViewerOptions) {
|
|
27
44
|
payload.value = payloadIncoming || payload.value;
|
|
28
45
|
options.value = optionsIncoming;
|
|
29
|
-
|
|
30
|
-
await nextTick();
|
|
31
|
-
mftpWebGL3DRModal.value?.alterValue(true);
|
|
32
46
|
}
|
|
33
47
|
|
|
34
48
|
async function loadSession(url: string): Promise<void> {
|
|
35
49
|
await mftpWebGL3DRModal.value?.loadSession(url);
|
|
36
50
|
}
|
|
37
51
|
|
|
38
|
-
|
|
52
|
+
async function close(): Promise<void> {
|
|
53
|
+
await mftpWebGL3DRModal.value?.close();
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
defineExpose({ loadInstance, loadSession, close });
|
|
39
57
|
</script>
|
|
40
58
|
|
|
41
59
|
<style>
|
|
@@ -85,9 +103,6 @@ defineExpose({ loadInstance, loadSession });
|
|
|
85
103
|
.transparent {
|
|
86
104
|
background-color: transparent;
|
|
87
105
|
}
|
|
88
|
-
.v-dialog.v-overlay--active:not(.v-tooltip) {
|
|
89
|
-
backdrop-filter: blur(4px);
|
|
90
|
-
}
|
|
91
106
|
.card-bg-border {
|
|
92
107
|
border-radius: 12px !important;
|
|
93
108
|
border: 2px #ffffffaa solid;
|
|
@@ -12,22 +12,22 @@ describe('index tests', () => {
|
|
|
12
12
|
});
|
|
13
13
|
|
|
14
14
|
it('should resolve loadViewer', async () => {
|
|
15
|
-
await registerViewer('1.0.0');
|
|
15
|
+
await registerViewer(document.body, '1.0.0');
|
|
16
16
|
expect(loadViewer()).resolves.not.toThrow(errorMessage);
|
|
17
17
|
});
|
|
18
18
|
|
|
19
19
|
it('should resolve loadSession 3crds url', async () => {
|
|
20
|
-
await registerViewer('1.0.0');
|
|
20
|
+
await registerViewer(document.body, '1.0.0');
|
|
21
21
|
expect(loadSession('https://localhost/example.3crds')).resolves.not.toThrow(errorMessage);
|
|
22
22
|
});
|
|
23
23
|
|
|
24
24
|
it('should resolve loadSession 3crms url', async () => {
|
|
25
|
-
await registerViewer('1.0.0');
|
|
25
|
+
await registerViewer(document.body, '1.0.0');
|
|
26
26
|
expect(loadSession('https://localhost/example.3crms')).resolves.not.toThrow(errorMessage);
|
|
27
27
|
});
|
|
28
28
|
|
|
29
29
|
it('should resolve loadSession 3crs url', async () => {
|
|
30
|
-
await registerViewer('1.0.0');
|
|
30
|
+
await registerViewer(document.body, '1.0.0');
|
|
31
31
|
expect(loadSession('https://localhost/example.3crs')).resolves.not.toThrow(errorMessage);
|
|
32
32
|
});
|
|
33
33
|
|
package/src/assets/styles.scss
CHANGED
|
@@ -1,14 +1,18 @@
|
|
|
1
1
|
@import 'vuetify/styles';
|
|
2
2
|
@import 'intro.js/introjs.css';
|
|
3
3
|
|
|
4
|
+
.v-overlay {
|
|
5
|
+
z-index: 3400 !important;
|
|
6
|
+
}
|
|
7
|
+
|
|
4
8
|
.introjs-tooltipReferenceLayer {
|
|
5
|
-
z-index:
|
|
9
|
+
z-index: 3401;
|
|
6
10
|
}
|
|
7
11
|
|
|
8
12
|
.introjs-overlay,
|
|
9
13
|
.introjs-helperLayer {
|
|
10
14
|
pointer-events: none;
|
|
11
|
-
z-index:
|
|
15
|
+
z-index: 3401;
|
|
12
16
|
}
|
|
13
17
|
|
|
14
18
|
.introjs-dontShowAgain {
|
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
import { computed } from
|
|
3
|
-
import {PRICING_URL} from
|
|
2
|
+
import { computed } from 'vue';
|
|
3
|
+
import { PRICING_URL } from '@/components/demo/options';
|
|
4
4
|
|
|
5
5
|
export interface Props {
|
|
6
6
|
modal: boolean;
|
|
7
|
-
isModalOpen
|
|
7
|
+
isModalOpen?: boolean;
|
|
8
8
|
}
|
|
9
9
|
|
|
10
10
|
const emit = defineEmits<{
|
|
11
|
-
|
|
11
|
+
'update:modal': [value: boolean];
|
|
12
12
|
}>();
|
|
13
13
|
|
|
14
14
|
const props = withDefaults(defineProps<Props>(), {
|
|
15
15
|
modal: false,
|
|
16
|
-
isModalOpen: true
|
|
16
|
+
isModalOpen: true
|
|
17
17
|
});
|
|
18
18
|
|
|
19
19
|
const modalState = computed({
|
|
@@ -21,11 +21,11 @@ const modalState = computed({
|
|
|
21
21
|
return props.modal;
|
|
22
22
|
},
|
|
23
23
|
set(value) {
|
|
24
|
-
emit(
|
|
25
|
-
}
|
|
24
|
+
emit('update:modal', value);
|
|
25
|
+
}
|
|
26
26
|
});
|
|
27
27
|
function openUrl(url: string) {
|
|
28
|
-
window.open(url,
|
|
28
|
+
window.open(url, '_self');
|
|
29
29
|
}
|
|
30
30
|
</script>
|
|
31
31
|
|
|
@@ -35,25 +35,15 @@ function openUrl(url: string) {
|
|
|
35
35
|
<v-card-title>Purchase 3Dicom Viewer</v-card-title>
|
|
36
36
|
<v-card-text> Thank you for trying 3Dicom Online Viewer! </v-card-text>
|
|
37
37
|
<v-card-text>
|
|
38
|
-
This instance of the Online Viewer is a Demo instance. If you would like
|
|
39
|
-
|
|
38
|
+
This instance of the Online Viewer is a Demo instance. If you would like to see your scans in 3D, please choose
|
|
39
|
+
a plan for 3DICOM
|
|
40
40
|
</v-card-text>
|
|
41
41
|
<v-card-actions>
|
|
42
|
-
<v-btn
|
|
43
|
-
data-testid="close"
|
|
44
|
-
color="error"
|
|
45
|
-
@click="modalState = false"
|
|
46
|
-
:disabled="!isModalOpen"
|
|
47
|
-
>
|
|
42
|
+
<v-btn data-testid="close" color="error" @click="modalState = false" :disabled="!isModalOpen">
|
|
48
43
|
Continue with Viewer
|
|
49
44
|
</v-btn>
|
|
50
45
|
<v-spacer />
|
|
51
|
-
<v-btn
|
|
52
|
-
data-testid="select-plan"
|
|
53
|
-
variant="tonal"
|
|
54
|
-
color="success"
|
|
55
|
-
@click="openUrl(PRICING_URL)"
|
|
56
|
-
>
|
|
46
|
+
<v-btn data-testid="select-plan" variant="tonal" color="success" @click="openUrl(PRICING_URL)">
|
|
57
47
|
Select a Plan
|
|
58
48
|
</v-btn>
|
|
59
49
|
</v-card-actions>
|
|
@@ -1,23 +1,19 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
import { computed } from
|
|
3
|
-
import {
|
|
4
|
-
demoLicenceSubtitles,
|
|
5
|
-
demoLicenceTitle,
|
|
6
|
-
openUrl, SUPPORT_URL,
|
|
7
|
-
} from "@/components/demo/options";
|
|
2
|
+
import { computed } from 'vue';
|
|
3
|
+
import { demoLicenceSubtitles, demoLicenceTitle, openUrl, SUPPORT_URL } from '@/components/demo/options';
|
|
8
4
|
|
|
9
5
|
export interface Props {
|
|
10
6
|
modal: boolean;
|
|
11
|
-
isModalOpen
|
|
7
|
+
isModalOpen?: boolean;
|
|
12
8
|
}
|
|
13
9
|
|
|
14
10
|
const emit = defineEmits<{
|
|
15
|
-
|
|
11
|
+
'update:modal': [value: boolean];
|
|
16
12
|
}>();
|
|
17
13
|
|
|
18
14
|
const props = withDefaults(defineProps<Props>(), {
|
|
19
15
|
modal: false,
|
|
20
|
-
isModalOpen: true
|
|
16
|
+
isModalOpen: true
|
|
21
17
|
});
|
|
22
18
|
|
|
23
19
|
const modalState = computed({
|
|
@@ -25,25 +21,16 @@ const modalState = computed({
|
|
|
25
21
|
return props.modal;
|
|
26
22
|
},
|
|
27
23
|
set(value) {
|
|
28
|
-
emit(
|
|
29
|
-
}
|
|
24
|
+
emit('update:modal', value);
|
|
25
|
+
}
|
|
30
26
|
});
|
|
31
27
|
</script>
|
|
32
28
|
|
|
33
29
|
<template>
|
|
34
30
|
<v-dialog v-model:model-value="modalState">
|
|
35
|
-
<v-card
|
|
36
|
-
class="
|
|
37
|
-
|
|
38
|
-
max-width="680"
|
|
39
|
-
>
|
|
40
|
-
<v-card-title class="text-center mb-4 mt-2 font-weight-bold">{{
|
|
41
|
-
demoLicenceTitle
|
|
42
|
-
}}</v-card-title>
|
|
43
|
-
<v-card-text
|
|
44
|
-
class="text-justify"
|
|
45
|
-
v-for="subtitle in demoLicenceSubtitles"
|
|
46
|
-
:key="subtitle"
|
|
31
|
+
<v-card class="pa-1 ma-auto position-relative motif-background card-bg-border" theme="dark" max-width="680">
|
|
32
|
+
<v-card-title class="text-center mb-4 mt-2 font-weight-bold">{{ demoLicenceTitle }}</v-card-title>
|
|
33
|
+
<v-card-text class="text-justify" v-for="subtitle in demoLicenceSubtitles" :key="subtitle"
|
|
47
34
|
>{{ subtitle }}
|
|
48
35
|
</v-card-text>
|
|
49
36
|
<v-card-actions class="mt-4">
|
|
@@ -51,12 +38,7 @@ const modalState = computed({
|
|
|
51
38
|
Continue with Demo
|
|
52
39
|
</v-btn>
|
|
53
40
|
<v-spacer />
|
|
54
|
-
<v-btn
|
|
55
|
-
data-testid="confirm"
|
|
56
|
-
variant="flat"
|
|
57
|
-
color="success"
|
|
58
|
-
@click="openUrl(SUPPORT_URL)"
|
|
59
|
-
>
|
|
41
|
+
<v-btn data-testid="confirm" variant="flat" color="success" @click="openUrl(SUPPORT_URL)">
|
|
60
42
|
Enquire about technical integration
|
|
61
43
|
</v-btn>
|
|
62
44
|
</v-card-actions>
|
|
@@ -1,23 +1,20 @@
|
|
|
1
|
-
import { computed, ref
|
|
1
|
+
import { computed, ref } from 'vue';
|
|
2
2
|
import { LoadViewerOptions } from '@/models/loadViewerOptions';
|
|
3
3
|
import { LoadViewerPayload } from '@/models/loadViewerPayload';
|
|
4
|
+
import { useViewer3cr } from '@/composables/useViewer3cr';
|
|
5
|
+
import { mockDemoViewerStlDecimator } from '@/composables/useViewerOptions';
|
|
6
|
+
import { DemoType } from '@/types/demo-type';
|
|
4
7
|
|
|
5
8
|
export const PRICING_URL = 'https://3dicomviewer.com/pricing';
|
|
6
9
|
|
|
7
10
|
export const SUPPORT_URL = 'https://3dicomviewer.com/contact-3dicom';
|
|
8
11
|
|
|
9
|
-
export function checkIsDemo(payload: LoadViewerPayload) {
|
|
10
|
-
isDemo.value = payload.Url.startsWith('https://webgl-3dr.singular.health/demo');
|
|
11
|
-
}
|
|
12
|
-
import { useViewer3cr } from '@/composables/useViewer3cr';
|
|
13
|
-
import { mockDemoViewerStlDecimator } from '@/composables/useViewerOptions';
|
|
14
|
-
|
|
15
|
-
const viewer3cr = useViewer3cr();
|
|
16
|
-
|
|
17
12
|
const BASE_STATE_URL = 'https://webgl-3dr.singular.health/demo';
|
|
18
13
|
|
|
14
|
+
const viewer3cr = useViewer3cr();
|
|
19
15
|
export const isDemo = ref<boolean>(false);
|
|
20
|
-
export const
|
|
16
|
+
export const show = ref<boolean>(true);
|
|
17
|
+
export const m_demoLicence = ref<boolean>(false);
|
|
21
18
|
export const m_demoLicenceShareToMobile = ref<boolean>(false);
|
|
22
19
|
export const m_demoLicenceSendToParty = ref<boolean>(false);
|
|
23
20
|
export const m_demoLicenseEnableCloudStorage = ref<boolean>(false);
|
|
@@ -31,13 +28,14 @@ export const demoLicenceTitle = ref<string>('');
|
|
|
31
28
|
export const demoLicenceSubtitles = ref<Array<string>>([]);
|
|
32
29
|
|
|
33
30
|
export const demoLicenceOptions: LoadViewerOptions = {
|
|
34
|
-
OnClosePopup:
|
|
31
|
+
OnClosePopup: undefined,
|
|
35
32
|
OnExitViewer: () => {
|
|
36
33
|
demoLicenceTitle.value = 'Thank you for trying the 3Dicom Licensing Demo.';
|
|
37
34
|
demoLicenceSubtitles.value = [
|
|
38
35
|
'Should you have any further questions or enquiries, please get in touch by emailing support@singular.health'
|
|
39
36
|
];
|
|
40
|
-
|
|
37
|
+
m_demoLicence.value = true;
|
|
38
|
+
show.value = false;
|
|
41
39
|
},
|
|
42
40
|
OnLoadNewDicomSeries: () => {
|
|
43
41
|
demoLicenceTitle.value = 'Support multiple medical imaging file types';
|
|
@@ -45,26 +43,26 @@ export const demoLicenceOptions: LoadViewerOptions = {
|
|
|
45
43
|
'3Dicom’s white-labelled online 2D / 3D DICOM viewer allows the loading of X-Ray (XR), Ultrasound (US), Computed Tomography (CT), Magnetic Resonance Imaging (MRI), and Positron Emitting Tomography (PET) using the global DICOM file format.'
|
|
46
44
|
];
|
|
47
45
|
|
|
48
|
-
|
|
46
|
+
m_demoLicence.value = true;
|
|
49
47
|
},
|
|
50
48
|
OnDownloadDicomSeries: () => {
|
|
51
49
|
demoLicenceTitle.value = 'Improve interoperability with local download of DICOM series';
|
|
52
50
|
demoLicenceSubtitles.value = [
|
|
53
51
|
'Integrate 3Dicom’s white-labelled online 2D/3D viewer into your PACS and/or medical records database to pull DICOM series and allow for local download direct from the viewer. This feature can be hidden upon request.'
|
|
54
52
|
];
|
|
55
|
-
|
|
53
|
+
m_demoLicence.value = true;
|
|
56
54
|
},
|
|
57
55
|
OnLoadSavedSession: () => {
|
|
58
56
|
demoLicenceTitle.value = 'Save previous progress and share particular sessions';
|
|
59
57
|
demoLicenceSubtitles.value = [
|
|
60
58
|
'3Dicom’s viewer enables session-saving to record any changes made during the viewing of medical scans including orientation of views, editing of labels, visualisation settings, and density settings. Changes made during sessions preserve the integrity of the DICOM file and are overlaid in future sessions.'
|
|
61
59
|
];
|
|
62
|
-
|
|
60
|
+
m_demoLicence.value = true;
|
|
63
61
|
},
|
|
64
62
|
OnSaveSession: () => {
|
|
65
63
|
demoLicenceTitle.value = 'Thank you for trying the 3Dicom Licensing Demo.';
|
|
66
64
|
demoLicenceSubtitles.value = ['Each 3Dicom viewer session can be saved with your changes made for future viewing.'];
|
|
67
|
-
|
|
65
|
+
m_demoLicence.value = true;
|
|
68
66
|
},
|
|
69
67
|
OnSendTo3rdParty: () => {
|
|
70
68
|
m_demoLicenceSendToParty.value = true;
|
|
@@ -79,24 +77,20 @@ export const demoLicenceOptions: LoadViewerOptions = {
|
|
|
79
77
|
mockDemoViewerStlDecimator();
|
|
80
78
|
await viewer3cr.loadMcadObjects({ Url: `${BASE_STATE_URL}/state/TotalSegmentator_1722837421466.3crms` });
|
|
81
79
|
},
|
|
82
|
-
OnShare:
|
|
83
|
-
OnScreenshot:
|
|
84
|
-
OnErrorClose:
|
|
80
|
+
OnShare: undefined,
|
|
81
|
+
OnScreenshot: undefined,
|
|
82
|
+
OnErrorClose: undefined
|
|
85
83
|
};
|
|
86
84
|
|
|
87
85
|
export const demoPatientOptions: LoadViewerOptions = {
|
|
88
|
-
OnClosePopup:
|
|
86
|
+
OnClosePopup: undefined,
|
|
89
87
|
OnExitViewer: () => {
|
|
90
88
|
demoPatientTitle.value = 'Thank you for trying the 3Dicom Patient Demo.';
|
|
91
89
|
demoPatientSubtitles.value = [
|
|
92
90
|
'Should you have any further questions or enquiries, please get in touch by emailing support@singular.health'
|
|
93
91
|
];
|
|
94
92
|
m_demoPatient.value = true;
|
|
95
|
-
|
|
96
|
-
if (!m_demoPatient) {
|
|
97
|
-
window.close();
|
|
98
|
-
}
|
|
99
|
-
});
|
|
93
|
+
show.value = false;
|
|
100
94
|
},
|
|
101
95
|
OnLoadNewDicomSeries: () => {
|
|
102
96
|
demoPatientTitle.value = '3Dicom Patient supports multiple Medical Imaging Formats';
|
|
@@ -137,28 +131,37 @@ export const demoPatientOptions: LoadViewerOptions = {
|
|
|
137
131
|
m_demoPatientEnableCloudStorage.value = true;
|
|
138
132
|
},
|
|
139
133
|
OnAutoAnnotate: demoLicenceOptions.OnAutoAnnotate,
|
|
140
|
-
OnShare:
|
|
141
|
-
OnScreenshot:
|
|
142
|
-
OnErrorClose:
|
|
134
|
+
OnShare: undefined,
|
|
135
|
+
OnScreenshot: undefined,
|
|
136
|
+
OnErrorClose: undefined
|
|
143
137
|
};
|
|
144
138
|
|
|
145
|
-
|
|
139
|
+
export function checkIsDemo(payload: LoadViewerPayload) {
|
|
140
|
+
isDemo.value = payload.Url.startsWith('https://webgl-3dr.singular.health/demo');
|
|
141
|
+
}
|
|
146
142
|
|
|
147
143
|
export const demoType = computed(() => {
|
|
148
144
|
const urlParams = new URLSearchParams(window.location.search);
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
145
|
+
if (urlParams.has('demoType')) {
|
|
146
|
+
const demoType = urlParams.get('demoType')!.toLowerCase();
|
|
147
|
+
switch (demoType) {
|
|
148
|
+
case 'patient':
|
|
149
|
+
return DemoType.Patient;
|
|
150
|
+
case 'licence':
|
|
151
|
+
return DemoType.Licence;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
return DemoType.Patient;
|
|
153
155
|
});
|
|
154
156
|
|
|
155
157
|
export const demoOptions = computed(() => {
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
158
|
+
switch (demoType.value) {
|
|
159
|
+
case DemoType.Patient:
|
|
160
|
+
return demoPatientOptions;
|
|
161
|
+
case DemoType.Licence:
|
|
162
|
+
return demoLicenceOptions;
|
|
163
|
+
default:
|
|
164
|
+
throw new Error('Unknown demo type');
|
|
162
165
|
}
|
|
163
166
|
});
|
|
164
167
|
|
|
@@ -1,23 +1,19 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
import { computed } from
|
|
3
|
-
import {
|
|
4
|
-
demoPatientSubtitles,
|
|
5
|
-
demoPatientTitle,
|
|
6
|
-
openUrl, PRICING_URL,
|
|
7
|
-
} from "@/components/demo/options";
|
|
2
|
+
import { computed } from 'vue';
|
|
3
|
+
import { demoPatientSubtitles, demoPatientTitle, openUrl, PRICING_URL } from '@/components/demo/options';
|
|
8
4
|
|
|
9
5
|
export interface Props {
|
|
10
6
|
modal: boolean;
|
|
11
|
-
isModalOpen
|
|
7
|
+
isModalOpen?: boolean;
|
|
12
8
|
}
|
|
13
9
|
|
|
14
10
|
const emit = defineEmits<{
|
|
15
|
-
|
|
11
|
+
'update:modal': [value: boolean];
|
|
16
12
|
}>();
|
|
17
13
|
|
|
18
14
|
const props = withDefaults(defineProps<Props>(), {
|
|
19
15
|
modal: false,
|
|
20
|
-
isModalOpen: true
|
|
16
|
+
isModalOpen: true
|
|
21
17
|
});
|
|
22
18
|
|
|
23
19
|
const modalState = computed({
|
|
@@ -25,25 +21,16 @@ const modalState = computed({
|
|
|
25
21
|
return props.modal;
|
|
26
22
|
},
|
|
27
23
|
set(value) {
|
|
28
|
-
emit(
|
|
29
|
-
}
|
|
24
|
+
emit('update:modal', value);
|
|
25
|
+
}
|
|
30
26
|
});
|
|
31
27
|
</script>
|
|
32
28
|
|
|
33
29
|
<template>
|
|
34
30
|
<v-dialog v-model:model-value="modalState">
|
|
35
|
-
<v-card
|
|
36
|
-
class="
|
|
37
|
-
|
|
38
|
-
max-width="680"
|
|
39
|
-
>
|
|
40
|
-
<v-card-title class="text-center mb-4 mt-2 font-weight-bold">{{
|
|
41
|
-
demoPatientTitle
|
|
42
|
-
}}</v-card-title>
|
|
43
|
-
<v-card-text
|
|
44
|
-
class="text-justify"
|
|
45
|
-
v-for="subtitle in demoPatientSubtitles"
|
|
46
|
-
:key="subtitle"
|
|
31
|
+
<v-card class="pa-1 ma-auto position-relative motif-background card-bg-border" theme="dark" max-width="680">
|
|
32
|
+
<v-card-title class="text-center mb-4 mt-2 font-weight-bold">{{ demoPatientTitle }}</v-card-title>
|
|
33
|
+
<v-card-text class="text-justify" v-for="subtitle in demoPatientSubtitles" :key="subtitle"
|
|
47
34
|
>{{ subtitle }}
|
|
48
35
|
</v-card-text>
|
|
49
36
|
<v-card-actions class="mt-4">
|
|
@@ -51,12 +38,7 @@ const modalState = computed({
|
|
|
51
38
|
Continue with Demo
|
|
52
39
|
</v-btn>
|
|
53
40
|
<v-spacer />
|
|
54
|
-
<v-btn
|
|
55
|
-
data-testid="confirm"
|
|
56
|
-
variant="flat"
|
|
57
|
-
color="success"
|
|
58
|
-
@click="openUrl(PRICING_URL)"
|
|
59
|
-
>
|
|
41
|
+
<v-btn data-testid="confirm" variant="flat" color="success" @click="openUrl(PRICING_URL)">
|
|
60
42
|
Purchase 3Dicom Patient
|
|
61
43
|
</v-btn>
|
|
62
44
|
</v-card-actions>
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
<v-card-title class="text-center">Close Viewer?</v-card-title>
|
|
5
5
|
<v-card-text class="text-center mb-2"> Are you sure you want to close the Online Viewer? </v-card-text>
|
|
6
6
|
<v-card-actions>
|
|
7
|
-
<v-btn data-testid="cancel" variant="
|
|
7
|
+
<v-btn data-testid="cancel" variant="text" @click="modalState = false"> Cancel </v-btn>
|
|
8
8
|
<v-spacer />
|
|
9
9
|
<v-btn v-if="options?.OnSaveSession" data-testid="close" color="red" variant="flat" @click="closeModal">
|
|
10
10
|
Close without saving
|