@3cr/viewer-browser 0.0.15 → 0.0.18
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/dist/Viewer3CR.js +11 -11
- package/dist/Viewer3CR.mjs +4433 -4420
- package/dist/Viewer3CR.umd.js +12 -12
- package/index.html +2 -2
- package/package.json +6 -1
- package/playground/favicon.ico +0 -0
- package/playground/index.html +21 -0
- package/scripts/modules.d.ts +2 -0
- package/scripts/postPublish.js +92 -0
- package/scripts/postPublish.ts +104 -0
- package/src/App.vue +3 -3
- package/src/components/DoubleSliderSelector.vue +9 -8
- package/src/components/MftpWebGL3DRModal.vue +73 -60
- package/src/components/SliderSelector.vue +28 -47
- package/src/components/VerticalSliderSelector.vue +8 -8
- package/src/plugins/vuetify.ts +1 -1
- package/tsconfig.build-scripts.json +22 -0
- package/vite.config.mts +1 -0
- package/.idea/git_toolbox_prj.xml +0 -15
- package/.idea/vcs.xml +0 -6
- package/.idea/workspace.xml +0 -218
package/index.html
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
|
|
4
4
|
<head>
|
|
5
5
|
<meta charset="UTF-8" />
|
|
6
|
-
<link rel="icon" href="/favicon.ico" />
|
|
6
|
+
<link rel="icon" href="/playground/favicon.ico" />
|
|
7
7
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
8
8
|
<title>Welcome to Vuetify 3</title>
|
|
9
9
|
</head>
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
<script type="module">
|
|
14
14
|
import {registerViewer, loadViewer} from './index.ts';
|
|
15
15
|
|
|
16
|
-
registerViewer('1.0.
|
|
16
|
+
registerViewer('1.0.0', '#app').then(() => {
|
|
17
17
|
loadViewer().then()
|
|
18
18
|
})
|
|
19
19
|
</script>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@3cr/viewer-browser",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.18",
|
|
4
4
|
"main": "./dist/Viewer3CR.umd.js",
|
|
5
5
|
"module": "dist/Viewer3CR.umd.js",
|
|
6
6
|
"homepage": "https://docs.3cr.singular.health",
|
|
@@ -14,6 +14,8 @@
|
|
|
14
14
|
"deploy": "npm version --no-git-tag-version patch && npm run build && npm publish",
|
|
15
15
|
"preview": "vite preview",
|
|
16
16
|
"test": "vitest",
|
|
17
|
+
"compile:scripts": "tsc --project tsconfig.build-scripts.json",
|
|
18
|
+
"deploy:playground": "npm run compile:scripts && node scripts/postPublish.js",
|
|
17
19
|
"coverage": "vitest run --coverage"
|
|
18
20
|
},
|
|
19
21
|
"dependencies": {
|
|
@@ -29,7 +31,10 @@
|
|
|
29
31
|
"@types/node": "^20.11.25",
|
|
30
32
|
"@vitejs/plugin-vue": "^5.0.4",
|
|
31
33
|
"@vue/test-utils": "^2.4.1",
|
|
34
|
+
"aws-sdk": "^2.1594.0",
|
|
32
35
|
"material-design-icons-iconfont": "^6.7.0",
|
|
36
|
+
"mime-types": "^2.1.35",
|
|
37
|
+
"randomstring": "^1.3.0",
|
|
33
38
|
"sass": "^1.71.1",
|
|
34
39
|
"typescript": "^5.4.2",
|
|
35
40
|
"unplugin-fonts": "^1.1.1",
|
|
Binary file
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
|
|
4
|
+
<head>
|
|
5
|
+
<meta charset="UTF-8" />
|
|
6
|
+
<link rel="icon" href="/favicon.ico" />
|
|
7
|
+
<script src="https://cdn.jsdelivr.net/npm/@3cr/viewer-browser"> </script>
|
|
8
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
9
|
+
<title>3CR Viewer Playground</title>
|
|
10
|
+
</head>
|
|
11
|
+
|
|
12
|
+
<body>
|
|
13
|
+
<div id="app"></div>
|
|
14
|
+
<script type="module">
|
|
15
|
+
window.registerViewer('1.0.0', '#app').then(() => {
|
|
16
|
+
window.loadViewer().then()
|
|
17
|
+
})
|
|
18
|
+
</script>
|
|
19
|
+
</body>
|
|
20
|
+
|
|
21
|
+
</html>
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
// import { CloudFront, S3 } from 'aws-sdk';
|
|
7
|
+
const randomstring_1 = require("randomstring");
|
|
8
|
+
const path_1 = require("path");
|
|
9
|
+
const mime_types_1 = require("mime-types");
|
|
10
|
+
const fs_1 = require("fs");
|
|
11
|
+
const aws_sdk_1 = __importDefault(require("aws-sdk"));
|
|
12
|
+
const { CloudFront, S3 } = aws_sdk_1.default;
|
|
13
|
+
//Note: Config is injected in CI now. (leaving this for in case we need to do a local)
|
|
14
|
+
// import dotenv from 'dotenv';
|
|
15
|
+
// dotenv.config();
|
|
16
|
+
const { DIST_NAME, AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, BUCKET_NAME } = process.env;
|
|
17
|
+
if (!AWS_ACCESS_KEY_ID || !AWS_SECRET_ACCESS_KEY)
|
|
18
|
+
throw Error('Please define environment variables for AWS');
|
|
19
|
+
if (!DIST_NAME)
|
|
20
|
+
throw Error('Please define environment variables for DIST_NAME');
|
|
21
|
+
const DistributionName = DIST_NAME;
|
|
22
|
+
const BucketName = BUCKET_NAME;
|
|
23
|
+
const s3 = new S3({
|
|
24
|
+
region: 'ap-southeast-2',
|
|
25
|
+
});
|
|
26
|
+
const cloudfront = new CloudFront();
|
|
27
|
+
async function uploadDir(s3Path) {
|
|
28
|
+
for (const name of (0, fs_1.readdirSync)(s3Path)) {
|
|
29
|
+
const filePath = (0, path_1.join)(s3Path, name);
|
|
30
|
+
const stat = (0, fs_1.statSync)(filePath);
|
|
31
|
+
if (stat.isFile()) {
|
|
32
|
+
if (!filePath.endsWith('.map'))
|
|
33
|
+
await executeUpload(s3Path, filePath);
|
|
34
|
+
}
|
|
35
|
+
else if (stat.isDirectory()) {
|
|
36
|
+
await uploadDir(filePath);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
async function executeUpload(s3Path, filePath) {
|
|
41
|
+
const parentDir = s3Path.includes('/')
|
|
42
|
+
? s3Path.substring(0, s3Path.indexOf('/'))
|
|
43
|
+
: s3Path;
|
|
44
|
+
const bucketPath = filePath.substring(parentDir.length + 1);
|
|
45
|
+
const options = {
|
|
46
|
+
Bucket: BucketName,
|
|
47
|
+
Key: `${bucketPath}`,
|
|
48
|
+
Body: (0, fs_1.readFileSync)(filePath),
|
|
49
|
+
};
|
|
50
|
+
if (typeof (0, mime_types_1.lookup)(bucketPath) === 'string') {
|
|
51
|
+
options.ContentType = (0, mime_types_1.lookup)(bucketPath);
|
|
52
|
+
}
|
|
53
|
+
await s3.putObject(options).promise();
|
|
54
|
+
}
|
|
55
|
+
async function deployToAws() {
|
|
56
|
+
const listObjectsParams = {
|
|
57
|
+
Bucket: BucketName,
|
|
58
|
+
Prefix: ``
|
|
59
|
+
};
|
|
60
|
+
const listObjectsResponse = await s3
|
|
61
|
+
.listObjectsV2(listObjectsParams)
|
|
62
|
+
.promise();
|
|
63
|
+
if (listObjectsResponse.Contents && listObjectsResponse.Contents.length > 0) {
|
|
64
|
+
const deleteParams = {
|
|
65
|
+
Bucket: BucketName,
|
|
66
|
+
Delete: {
|
|
67
|
+
Objects: listObjectsResponse.Contents?.map((x) => ({
|
|
68
|
+
Key: x.Key || '',
|
|
69
|
+
})).filter((x) => x.Key !== '') || [],
|
|
70
|
+
},
|
|
71
|
+
};
|
|
72
|
+
await s3.deleteObjects(deleteParams).promise();
|
|
73
|
+
}
|
|
74
|
+
await uploadDir('playground');
|
|
75
|
+
const reference = (0, randomstring_1.generate)(16);
|
|
76
|
+
const params = {
|
|
77
|
+
DistributionId: DistributionName,
|
|
78
|
+
InvalidationBatch: {
|
|
79
|
+
CallerReference: reference,
|
|
80
|
+
Paths: {
|
|
81
|
+
Quantity: 1,
|
|
82
|
+
Items: ['/*'],
|
|
83
|
+
},
|
|
84
|
+
},
|
|
85
|
+
};
|
|
86
|
+
console.log(`Creating Invalidation for (${DistributionName}): ${reference}`);
|
|
87
|
+
const invalidation = await cloudfront.createInvalidation(params).promise();
|
|
88
|
+
console.log(invalidation);
|
|
89
|
+
}
|
|
90
|
+
deployToAws()
|
|
91
|
+
.then((data) => console.log(data))
|
|
92
|
+
.catch((err) => console.error(err));
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
// import { CloudFront, S3 } from 'aws-sdk';
|
|
2
|
+
import { generate } from 'randomstring';
|
|
3
|
+
import { join } from 'path';
|
|
4
|
+
import { lookup } from 'mime-types';
|
|
5
|
+
import { readdirSync, statSync, readFileSync } from 'fs';
|
|
6
|
+
import pkg from 'aws-sdk';
|
|
7
|
+
const { CloudFront, S3 } = pkg;
|
|
8
|
+
|
|
9
|
+
import { CreateInvalidationRequest } from 'aws-sdk/clients/cloudfront';
|
|
10
|
+
import {DeleteObjectsRequest, ListObjectsV2Request, PutObjectRequest } from 'aws-sdk/clients/s3';
|
|
11
|
+
|
|
12
|
+
//Note: Config is injected in CI now. (leaving this for in case we need to do a local)
|
|
13
|
+
// import dotenv from 'dotenv';
|
|
14
|
+
// dotenv.config();
|
|
15
|
+
|
|
16
|
+
const { DIST_NAME, AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, BUCKET_NAME } = process.env;
|
|
17
|
+
|
|
18
|
+
if (!AWS_ACCESS_KEY_ID || !AWS_SECRET_ACCESS_KEY) throw Error('Please define environment variables for AWS');
|
|
19
|
+
if (!DIST_NAME) throw Error('Please define environment variables for DIST_NAME');
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
const DistributionName = DIST_NAME as string;
|
|
23
|
+
const BucketName = BUCKET_NAME as string;
|
|
24
|
+
const s3 = new S3({
|
|
25
|
+
region: 'ap-southeast-2',
|
|
26
|
+
});
|
|
27
|
+
const cloudfront = new CloudFront();
|
|
28
|
+
|
|
29
|
+
async function uploadDir(s3Path: string) {
|
|
30
|
+
for (const name of readdirSync(s3Path)) {
|
|
31
|
+
const filePath = join(s3Path, name);
|
|
32
|
+
const stat = statSync(filePath);
|
|
33
|
+
|
|
34
|
+
if (stat.isFile()) {
|
|
35
|
+
if (!filePath.endsWith('.map')) await executeUpload(s3Path, filePath);
|
|
36
|
+
} else if (stat.isDirectory()) {
|
|
37
|
+
await uploadDir(filePath);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
async function executeUpload(s3Path: string, filePath: string) {
|
|
42
|
+
const parentDir = s3Path.includes('/')
|
|
43
|
+
? s3Path.substring(0, s3Path.indexOf('/'))
|
|
44
|
+
: s3Path;
|
|
45
|
+
const bucketPath = filePath.substring(parentDir.length + 1);
|
|
46
|
+
const options: PutObjectRequest = {
|
|
47
|
+
Bucket: BucketName,
|
|
48
|
+
Key: `${bucketPath}`,
|
|
49
|
+
Body: readFileSync(filePath),
|
|
50
|
+
};
|
|
51
|
+
if (typeof lookup(bucketPath) === 'string') {
|
|
52
|
+
options.ContentType = lookup(bucketPath) as string;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
await s3.putObject(options).promise();
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
async function deployToAws() {
|
|
59
|
+
const listObjectsParams: ListObjectsV2Request = {
|
|
60
|
+
Bucket: BucketName,
|
|
61
|
+
Prefix: ``
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
const listObjectsResponse = await s3
|
|
65
|
+
.listObjectsV2(listObjectsParams)
|
|
66
|
+
.promise();
|
|
67
|
+
|
|
68
|
+
if (listObjectsResponse.Contents && listObjectsResponse.Contents.length > 0) {
|
|
69
|
+
const deleteParams: DeleteObjectsRequest = {
|
|
70
|
+
Bucket: BucketName,
|
|
71
|
+
Delete: {
|
|
72
|
+
Objects:
|
|
73
|
+
listObjectsResponse.Contents?.map((x) => ({
|
|
74
|
+
Key: x.Key || '',
|
|
75
|
+
})).filter((x) => x.Key !== '') || [],
|
|
76
|
+
},
|
|
77
|
+
};
|
|
78
|
+
await s3.deleteObjects(deleteParams).promise();
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
await uploadDir('playground');
|
|
82
|
+
|
|
83
|
+
const reference = generate(16);
|
|
84
|
+
const params: CreateInvalidationRequest = {
|
|
85
|
+
DistributionId: DistributionName,
|
|
86
|
+
InvalidationBatch: {
|
|
87
|
+
CallerReference: reference,
|
|
88
|
+
Paths: {
|
|
89
|
+
Quantity: 1,
|
|
90
|
+
Items: ['/*'],
|
|
91
|
+
},
|
|
92
|
+
},
|
|
93
|
+
};
|
|
94
|
+
console.log(`Creating Invalidation for (${DistributionName}): ${reference}`);
|
|
95
|
+
|
|
96
|
+
const invalidation = await cloudfront.createInvalidation(params).promise();
|
|
97
|
+
console.log(invalidation);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
deployToAws()
|
|
101
|
+
.then((data) => console.log(data))
|
|
102
|
+
.catch((err) => console.error(err));
|
|
103
|
+
|
|
104
|
+
|
package/src/App.vue
CHANGED
|
@@ -11,10 +11,10 @@ import {ref, unref} from "vue";
|
|
|
11
11
|
import {LoadViewerPayload} from "../index";
|
|
12
12
|
|
|
13
13
|
const payload = ref<LoadViewerPayload>({
|
|
14
|
-
Url:"https://webgl-3dr.singular.health/test_scans/
|
|
14
|
+
Url:"https://webgl-3dr.singular.health/test_scans/01440d4e-8b04-4b90-bb2c-698535ce16d6/CHEST.3vxl",
|
|
15
15
|
DecryptionKey:{
|
|
16
|
-
Iv:"
|
|
17
|
-
Key:"
|
|
16
|
+
Iv:"XEloSh+OcO7TG77au6HjPw==",
|
|
17
|
+
Key:"KUc722X1y4w42M+jCf9a3+6EGz66z7UMWK3m2aMqGxM="
|
|
18
18
|
}
|
|
19
19
|
});
|
|
20
20
|
const mftpWebGL3DRModal = ref<typeof MftpWebGL3DRModal | null>(null)
|
|
@@ -3,12 +3,12 @@ import {computed, defineEmits, ref, unref, watch} from 'vue';
|
|
|
3
3
|
|
|
4
4
|
export interface Props {
|
|
5
5
|
value: Array<number>;
|
|
6
|
-
loading
|
|
7
|
-
label
|
|
8
|
-
lower
|
|
9
|
-
upper
|
|
10
|
-
min
|
|
11
|
-
max
|
|
6
|
+
loading?: boolean;
|
|
7
|
+
label?: string;
|
|
8
|
+
lower?: number;
|
|
9
|
+
upper?: number;
|
|
10
|
+
min?: number;
|
|
11
|
+
max?: number;
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
const props = withDefaults(defineProps<Props>(), {
|
|
@@ -22,8 +22,9 @@ const props = withDefaults(defineProps<Props>(), {
|
|
|
22
22
|
});
|
|
23
23
|
|
|
24
24
|
const emit = defineEmits<{
|
|
25
|
-
|
|
25
|
+
'update:value': [Array<number>];
|
|
26
26
|
}>();
|
|
27
|
+
|
|
27
28
|
const prevValue = ref<Array<number>>([])
|
|
28
29
|
const showThumb = ref<"always" | boolean>(false)
|
|
29
30
|
const showThumbTimeout = ref<number>(0)
|
|
@@ -32,7 +33,7 @@ const sliderValue = computed({
|
|
|
32
33
|
return props.value
|
|
33
34
|
},
|
|
34
35
|
set(value: Array<number>) {
|
|
35
|
-
emit('
|
|
36
|
+
emit('update:value', value);
|
|
36
37
|
}
|
|
37
38
|
})
|
|
38
39
|
|
|
@@ -26,22 +26,27 @@
|
|
|
26
26
|
class="pa-0 ma-0 position-relative motif-background overflow-y-hidden rounded-0"
|
|
27
27
|
height="100vh"
|
|
28
28
|
>
|
|
29
|
-
<v-toolbar dense>
|
|
29
|
+
<v-toolbar dense height="48">
|
|
30
30
|
<v-menu :close-on-content-click="false" :close-on-click="true" open-on-hover offset-y>
|
|
31
31
|
<template #activator="{ props, isActive }">
|
|
32
32
|
<v-btn
|
|
33
33
|
v-bind="props"
|
|
34
|
+
variant="flat"
|
|
34
35
|
:color="isActive ? 'secondary' : 'primary'"
|
|
35
|
-
class="
|
|
36
|
+
class="mr-2"
|
|
36
37
|
>
|
|
37
|
-
<
|
|
38
|
+
<template #prepend>
|
|
39
|
+
<v-icon>description</v-icon>
|
|
40
|
+
</template>
|
|
41
|
+
File
|
|
38
42
|
</v-btn>
|
|
39
43
|
</template>
|
|
40
44
|
<v-card class="">
|
|
41
45
|
<v-list>
|
|
42
|
-
<v-list-item-group>
|
|
43
46
|
<v-list-item disabled>
|
|
44
|
-
<
|
|
47
|
+
<template v-slot:prepend>
|
|
48
|
+
<v-icon> upload </v-icon>
|
|
49
|
+
</template>
|
|
45
50
|
<v-list-item-title
|
|
46
51
|
>Load New DICOM Series <v-chip x-small color="success">Coming Soon</v-chip></v-list-item-title
|
|
47
52
|
>
|
|
@@ -51,51 +56,60 @@
|
|
|
51
56
|
<!-- <v-list-item-title>Download DICOM Series</v-list-item-title>-->
|
|
52
57
|
<!-- </v-list-item>-->
|
|
53
58
|
<v-list-item disabled>
|
|
54
|
-
<
|
|
59
|
+
<template v-slot:prepend>
|
|
60
|
+
<v-icon> sync </v-icon>
|
|
61
|
+
</template>
|
|
55
62
|
<v-list-item-title
|
|
56
63
|
>Load Saved Session <v-chip x-small color="success">Coming Soon</v-chip></v-list-item-title
|
|
57
64
|
>
|
|
58
65
|
</v-list-item>
|
|
59
66
|
<v-list-item disabled>
|
|
60
|
-
<
|
|
67
|
+
<template v-slot:prepend>
|
|
68
|
+
<v-icon> share </v-icon>
|
|
69
|
+
</template>
|
|
61
70
|
<v-list-item-title>Share <v-chip x-small color="success">Coming Soon</v-chip></v-list-item-title>
|
|
62
71
|
</v-list-item>
|
|
63
72
|
<v-list-item @click="alterValue(false)">
|
|
64
|
-
<
|
|
73
|
+
<template v-slot:prepend>
|
|
74
|
+
<v-icon> close </v-icon>
|
|
75
|
+
</template>
|
|
65
76
|
<v-list-item-title>Close Viewer</v-list-item-title>
|
|
66
77
|
</v-list-item>
|
|
67
|
-
</v-list-item-group>
|
|
68
78
|
</v-list>
|
|
69
79
|
</v-card>
|
|
70
80
|
</v-menu>
|
|
71
81
|
<v-menu :close-on-content-click="false" :close-on-click="true" open-on-hover offset-y>
|
|
72
82
|
<template #activator="{ props, isActive }">
|
|
73
|
-
<v-btn
|
|
74
|
-
|
|
83
|
+
<v-btn
|
|
84
|
+
variant="flat"
|
|
85
|
+
v-bind="props" :color="isActive ? 'secondary' : 'primary'">
|
|
86
|
+
<template #prepend>
|
|
87
|
+
<v-icon>settings</v-icon>
|
|
88
|
+
</template>
|
|
89
|
+
Settings
|
|
75
90
|
</v-btn>
|
|
76
91
|
</template>
|
|
77
92
|
<v-card min-width="400" class="pb-2">
|
|
78
|
-
<v-card-subtitle>Viewer Settings</v-card-subtitle>
|
|
79
93
|
<SliderSelector
|
|
80
|
-
v-model="scanState.InteractionSettings.PanSensivitity"
|
|
94
|
+
v-model:value="scanState.InteractionSettings.PanSensivitity"
|
|
81
95
|
:min="0"
|
|
82
96
|
:max="100"
|
|
83
97
|
label="Pan Sensitivity"
|
|
84
98
|
/>
|
|
85
99
|
<SliderSelector
|
|
86
|
-
v-model="scanState.InteractionSettings.ZoomSensitivity"
|
|
100
|
+
v-model:value="scanState.InteractionSettings.ZoomSensitivity"
|
|
87
101
|
:min="0"
|
|
88
102
|
:max="100"
|
|
89
103
|
label="Zoom Sensitivity"
|
|
90
104
|
/>
|
|
91
105
|
<SliderSelector
|
|
92
|
-
v-model="scanState.InteractionSettings.RotateSensitivity"
|
|
106
|
+
v-model:value="scanState.InteractionSettings.RotateSensitivity"
|
|
93
107
|
:min="0"
|
|
94
108
|
:max="100"
|
|
95
109
|
label="Rotate Sensitivity"
|
|
96
110
|
/>
|
|
97
111
|
<SliderSelector
|
|
98
|
-
v-model="scanState.InteractionSettings.CameraRotateSensitivity"
|
|
112
|
+
v-model:value="scanState.InteractionSettings.CameraRotateSensitivity"
|
|
99
113
|
:min="0"
|
|
100
114
|
:max="100"
|
|
101
115
|
label="Camera Rotate Sensitivity"
|
|
@@ -130,18 +144,18 @@
|
|
|
130
144
|
@click="layouts('lo_03')"
|
|
131
145
|
><v-icon style="rotate: -90deg">view_comfy</v-icon></v-btn
|
|
132
146
|
>
|
|
133
|
-
<v-btn class="
|
|
147
|
+
<v-btn class="" variant="flat" color="red" @click="alterValue(false)">Close Viewer</v-btn>
|
|
134
148
|
</v-toolbar>
|
|
135
149
|
<v-navigation-drawer
|
|
136
150
|
v-model="drawer"
|
|
137
151
|
permanent
|
|
138
|
-
:
|
|
139
|
-
|
|
152
|
+
:rail="drawerCollapsed"
|
|
153
|
+
rail-width="68"
|
|
140
154
|
style="opacity: 0.95; margin-top: 48px; height: calc(100vh - 40px)"
|
|
141
155
|
absolute
|
|
142
156
|
dark
|
|
143
157
|
class="rounded-0 motif-background"
|
|
144
|
-
width="
|
|
158
|
+
width="300"
|
|
145
159
|
>
|
|
146
160
|
<template v-slot:prepend>
|
|
147
161
|
<div class="d-flex align-center pb-1" :class="drawerCollapsed ? 'py-2' : 'pa-2'" @click="snap">
|
|
@@ -183,19 +197,18 @@
|
|
|
183
197
|
:disabled="!(instanceLoaded && !scanLoading)"
|
|
184
198
|
@click="item.click()"
|
|
185
199
|
>
|
|
186
|
-
<v-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
</v-list-item-content>
|
|
200
|
+
<template v-slot:prepend>
|
|
201
|
+
<div
|
|
202
|
+
:class="[drawerCollapsed && 'mx-auto']"
|
|
203
|
+
:style="drawerCollapsed && 'margin-left: 7px !important; margin-right: 7px !important;'">
|
|
204
|
+
<v-icon :large="drawerCollapsed" :color="item.color">
|
|
205
|
+
{{ item.icon || 'radio_button_checked' }}
|
|
206
|
+
</v-icon>
|
|
207
|
+
</div>
|
|
208
|
+
</template>
|
|
209
|
+
<v-list-item-title v-if="!drawerCollapsed">
|
|
210
|
+
{{ item.text }}
|
|
211
|
+
</v-list-item-title>
|
|
199
212
|
</v-list-item>
|
|
200
213
|
</template>
|
|
201
214
|
{{ item.text }}
|
|
@@ -236,12 +249,12 @@
|
|
|
236
249
|
<ExpansionHeaderMiniMenu :mini-menu="miniMenu[0]" />
|
|
237
250
|
<v-expansion-panel-text>
|
|
238
251
|
<DoubleSliderSelector
|
|
239
|
-
v-model="windowSlider"
|
|
252
|
+
v-model:value="windowSlider"
|
|
240
253
|
label="Skin to Bone"
|
|
241
254
|
:min="huMinMax.min"
|
|
242
255
|
:max="huMinMax.max"
|
|
243
256
|
/>
|
|
244
|
-
<DoubleSliderSelector v-model="thresholdSlider" label="Fine Adjustment" v-bind="huMinMax" />
|
|
257
|
+
<DoubleSliderSelector v-model:value="thresholdSlider" label="Fine Adjustment" v-bind="huMinMax" />
|
|
245
258
|
<v-card-actions class="py-1">
|
|
246
259
|
<v-select
|
|
247
260
|
:value="getCurrentGreyscalePreset()"
|
|
@@ -307,9 +320,9 @@
|
|
|
307
320
|
<v-expansion-panel class="transparent">
|
|
308
321
|
<ExpansionHeaderMiniMenu :mini-menu="miniMenu[1]" />
|
|
309
322
|
<v-expansion-panel-text>
|
|
310
|
-
<SliderSelector v-model="scanState.Display.Brightness" label="Adjust Brightness" />
|
|
311
|
-
<SliderSelector v-model="scanState.Display.Contrast" label="Adjust Contrast" />
|
|
312
|
-
<SliderSelector v-model="scanState.Display.Opacity" label="Adjust Opacity" />
|
|
323
|
+
<SliderSelector v-model:value="scanState.Display.Brightness" label="Adjust Brightness" />
|
|
324
|
+
<SliderSelector v-model:value="scanState.Display.Contrast" label="Adjust Contrast" />
|
|
325
|
+
<SliderSelector v-model:value="scanState.Display.Opacity" label="Adjust Opacity" />
|
|
313
326
|
</v-expansion-panel-text>
|
|
314
327
|
</v-expansion-panel>
|
|
315
328
|
</v-expansion-panels>
|
|
@@ -468,17 +481,17 @@
|
|
|
468
481
|
<div class="slider-in-view" v-if="isHovering">
|
|
469
482
|
<VerticalSliderSelector
|
|
470
483
|
v-if="getCurrentActiveView(layout) === ScanView.Transverse"
|
|
471
|
-
v-model="scanState.Orientations.Transverse.Slice"
|
|
484
|
+
v-model:value="scanState.Orientations.Transverse.Slice"
|
|
472
485
|
v-bind="tMinMax"
|
|
473
486
|
/>
|
|
474
487
|
<VerticalSliderSelector
|
|
475
488
|
v-if="getCurrentActiveView(layout) === ScanView.Coronal"
|
|
476
|
-
v-model="scanState.Orientations.Coronal.Slice"
|
|
489
|
+
v-model:value="scanState.Orientations.Coronal.Slice"
|
|
477
490
|
v-bind="cMinMax"
|
|
478
491
|
/>
|
|
479
492
|
<VerticalSliderSelector
|
|
480
493
|
v-if="getCurrentActiveView(layout) === ScanView.Sagittal"
|
|
481
|
-
v-model="scanState.Orientations.Sagittal.Slice"
|
|
494
|
+
v-model:value="scanState.Orientations.Sagittal.Slice"
|
|
482
495
|
v-bind="sMinMax"
|
|
483
496
|
/>
|
|
484
497
|
</div>
|
|
@@ -586,25 +599,22 @@ const footerItems = ref([
|
|
|
586
599
|
text: 'Reset Scan',
|
|
587
600
|
icon: 'refresh',
|
|
588
601
|
color: 'red',
|
|
589
|
-
click: () => {
|
|
590
|
-
|
|
591
|
-
viewSelection('vs_05');
|
|
592
|
-
|
|
593
|
-
viewSelection('vs_06');
|
|
602
|
+
click: async () => {
|
|
603
|
+
console.log('Reset Scan');
|
|
604
|
+
await viewSelection('vs_05');
|
|
605
|
+
await viewSelection('vs_06');
|
|
594
606
|
},
|
|
595
607
|
},
|
|
596
608
|
{
|
|
597
609
|
text: 'Send to 3rd Party',
|
|
598
610
|
icon: 'send',
|
|
599
611
|
color: 'blue',
|
|
600
|
-
//@ts-ignore
|
|
601
612
|
click: () => alterValue(false),
|
|
602
613
|
},
|
|
603
614
|
{
|
|
604
615
|
text: 'Share to Mobile / VR',
|
|
605
616
|
icon: 'share',
|
|
606
617
|
color: 'yellow',
|
|
607
|
-
//@ts-ignore
|
|
608
618
|
click: () => alterValue(false),
|
|
609
619
|
},
|
|
610
620
|
{
|
|
@@ -612,7 +622,6 @@ const footerItems = ref([
|
|
|
612
622
|
icon: 'screenshot_region',
|
|
613
623
|
color: 'green',
|
|
614
624
|
click: () => {
|
|
615
|
-
//@ts-ignore
|
|
616
625
|
snap();
|
|
617
626
|
},
|
|
618
627
|
},
|
|
@@ -762,18 +771,18 @@ watch(() => scanState.value.InteractionSettings.CameraRotateSensitivity, async (
|
|
|
762
771
|
})
|
|
763
772
|
|
|
764
773
|
function getIconForPreset(presetName: string): string | undefined {
|
|
765
|
-
if (presetName === 'Bone') return 'fa-solid fa-bone';
|
|
766
|
-
if (presetName === 'Brain') return 'fa-solid fa-brain';
|
|
767
|
-
if (presetName === 'Liver') return '$liver_icon';
|
|
768
|
-
if (presetName === 'Lungs') return 'fa-solid fa-lungs';
|
|
769
|
-
if (presetName === 'Muscle') return '$muscle_icon';
|
|
770
|
-
if (presetName === 'Temporal Bones') return '$temporal_bones_icon';
|
|
771
|
-
if (presetName === 'Soft Tissue') return '$torso_icon';
|
|
772
|
-
if (presetName === 'Skin') return '$skin_icon';
|
|
774
|
+
// if (presetName === 'Bone') return 'fa-solid fa-bone';
|
|
775
|
+
// if (presetName === 'Brain') return 'fa-solid fa-brain';
|
|
776
|
+
// if (presetName === 'Liver') return '$liver_icon';
|
|
777
|
+
// if (presetName === 'Lungs') return 'fa-solid fa-lungs';
|
|
778
|
+
// if (presetName === 'Muscle') return '$muscle_icon';
|
|
779
|
+
// if (presetName === 'Temporal Bones') return '$temporal_bones_icon';
|
|
780
|
+
// if (presetName === 'Soft Tissue') return '$torso_icon';
|
|
781
|
+
// if (presetName === 'Skin') return '$skin_icon';
|
|
773
782
|
return undefined
|
|
774
783
|
}
|
|
775
784
|
async function rotateByDeg(view: ScanView, deg: number) {
|
|
776
|
-
await
|
|
785
|
+
await (FrontEndInterfaces.scan_orientation, ScanOrientationActions.so01, {
|
|
777
786
|
Version: '0.0.1',
|
|
778
787
|
View: view,
|
|
779
788
|
Angle: deg,
|
|
@@ -832,11 +841,11 @@ async function load() {
|
|
|
832
841
|
await sendPayload('file_management', 'fm_01', props.payload);
|
|
833
842
|
}
|
|
834
843
|
async function viewSelection(action: string) {
|
|
835
|
-
await sendPayload(
|
|
844
|
+
await sendPayload(FrontEndInterfaces.view_selection, action, emptyPayload)
|
|
836
845
|
}
|
|
837
846
|
async function layouts(action: string) {
|
|
838
847
|
if (action !== 'lo_01') previousLayout.value = action;
|
|
839
|
-
await sendPayload(
|
|
848
|
+
await sendPayload(FrontEndInterfaces.layout, action, emptyPayload)
|
|
840
849
|
}
|
|
841
850
|
async function snap() {
|
|
842
851
|
// await unref(web_gl).snap();
|
|
@@ -1005,4 +1014,8 @@ function handleOnPayload(interfaceSet: string | FrontEndInterfaces, actionSet: s
|
|
|
1005
1014
|
.buttons-in-view > div {
|
|
1006
1015
|
display: inline-block;
|
|
1007
1016
|
}
|
|
1017
|
+
.motif-background {
|
|
1018
|
+
background: url("data:image/svg+xml,%3Csvg width='992' height='560' viewBox='15 7 992 560' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Crect x='15' y='1' width='992' height='567' fill='url(%23paint0_linear_504_579)'/%3E%3Cg filter='url(%23filter0_i_504_579)'%3E%3Cpath d='M567.029 291.5C574.21 421.339 748.15 561 825.931 561H12L12.0001 0C153.713 0 580.363 0 580.363 0C684.258 142 560.918 181 567.029 291.5Z' fill='%231B2E43' fill-opacity='0.9'/%3E%3C/g%3E%3Cg filter='url(%23filter1_i_504_579)'%3E%3Cpath d='M435.911 260.5C462.579 433.5 652.034 561 729.815 561H12L12.0001 0C233.678 0 409.954 92.1126 435.911 260.5Z' fill='%231B2E43' fill-opacity='0.9'/%3E%3C/g%3E%3Cg filter='url(%23filter2_i_504_579)'%3E%3Ccircle cx='46' cy='521' r='93' fill='%231B2E43' fill-opacity='0.3'/%3E%3C/g%3E%3Cdefs%3E%3Cfilter id='filter0_i_504_579' x='12' y='0' width='858.931' height='606' filterUnits='userSpaceOnUse' color-interpolation-filters='sRGB'%3E%3CfeFlood flood-opacity='0' result='BackgroundImageFix'/%3E%3CfeBlend mode='normal' in='SourceGraphic' in2='BackgroundImageFix' result='shape'/%3E%3CfeColorMatrix in='SourceAlpha' type='matrix' values='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0' result='hardAlpha'/%3E%3CfeOffset dx='45' dy='45'/%3E%3CfeGaussianBlur stdDeviation='50'/%3E%3CfeComposite in2='hardAlpha' operator='arithmetic' k2='-1' k3='1'/%3E%3CfeColorMatrix type='matrix' values='0 0 0 0 0.653125 0 0 0 0 0.761642 0 0 0 0 0.916667 0 0 0 0.15 0'/%3E%3CfeBlend mode='normal' in2='shape' result='effect1_innerShadow_504_579'/%3E%3C/filter%3E%3Cfilter id='filter1_i_504_579' x='12' y='0' width='762.815' height='606' filterUnits='userSpaceOnUse' color-interpolation-filters='sRGB'%3E%3CfeFlood flood-opacity='0' result='BackgroundImageFix'/%3E%3CfeBlend mode='normal' in='SourceGraphic' in2='BackgroundImageFix' result='shape'/%3E%3CfeColorMatrix in='SourceAlpha' type='matrix' values='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0' result='hardAlpha'/%3E%3CfeOffset dx='45' dy='45'/%3E%3CfeGaussianBlur stdDeviation='50'/%3E%3CfeComposite in2='hardAlpha' operator='arithmetic' k2='-1' k3='1'/%3E%3CfeColorMatrix type='matrix' values='0 0 0 0 0.653125 0 0 0 0 0.761642 0 0 0 0 0.916667 0 0 0 0.25 0'/%3E%3CfeBlend mode='normal' in2='shape' result='effect1_innerShadow_504_579'/%3E%3C/filter%3E%3Cfilter id='filter2_i_504_579' x='-47' y='428' width='231' height='231' filterUnits='userSpaceOnUse' color-interpolation-filters='sRGB'%3E%3CfeFlood flood-opacity='0' result='BackgroundImageFix'/%3E%3CfeBlend mode='normal' in='SourceGraphic' in2='BackgroundImageFix' result='shape'/%3E%3CfeColorMatrix in='SourceAlpha' type='matrix' values='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0' result='hardAlpha'/%3E%3CfeOffset dx='45' dy='45'/%3E%3CfeGaussianBlur stdDeviation='50'/%3E%3CfeComposite in2='hardAlpha' operator='arithmetic' k2='-1' k3='1'/%3E%3CfeColorMatrix type='matrix' values='0 0 0 0 0.653125 0 0 0 0 0.761642 0 0 0 0 0.916667 0 0 0 0.15 0'/%3E%3CfeBlend mode='normal' in2='shape' result='effect1_innerShadow_504_579'/%3E%3C/filter%3E%3ClinearGradient id='paint0_linear_504_579' x1='1251.04' y1='696.83' x2='21.486' y2='-10.2783' gradientUnits='userSpaceOnUse'%3E%3Cstop stop-color='%230E141D'/%3E%3Cstop offset='1' stop-color='%2323405E'/%3E%3C/linearGradient%3E%3C/defs%3E%3C/svg%3E%0A") !important;
|
|
1019
|
+
background-size: cover !important;
|
|
1020
|
+
}
|
|
1008
1021
|
</style>
|