@geode/opengeodeweb-front 0.0.0
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/.github/workflows/Branch-protection.yml +11 -0
- package/.github/workflows/CD.yml +23 -0
- package/.releaserc +11 -0
- package/LICENSE +21 -0
- package/README.md +2 -0
- package/assets/geode_objects.js +110 -0
- package/assets/img/geode_objects/BRep.svg +102 -0
- package/assets/img/geode_objects/cross_section.svg +95 -0
- package/assets/img/geode_objects/edged_curve.svg +67 -0
- package/assets/img/geode_objects/edged_curve2d.svg +78 -0
- package/assets/img/geode_objects/edged_curve3d.svg +78 -0
- package/assets/img/geode_objects/hybrid_solid.svg +128 -0
- package/assets/img/geode_objects/point_set2d.svg +97 -0
- package/assets/img/geode_objects/point_set3d.svg +97 -0
- package/assets/img/geode_objects/polygonal_surface2d.svg +90 -0
- package/assets/img/geode_objects/polygonal_surface3d.svg +90 -0
- package/assets/img/geode_objects/polyhedral_solid.svg +148 -0
- package/assets/img/geode_objects/raster_image2d.svg +109 -0
- package/assets/img/geode_objects/raster_image3d.svg +108 -0
- package/assets/img/geode_objects/regular_grid.svg +107 -0
- package/assets/img/geode_objects/regular_grid2d.svg +107 -0
- package/assets/img/geode_objects/regular_grid3d.svg +193 -0
- package/assets/img/geode_objects/section.svg +87 -0
- package/assets/img/geode_objects/structural_model.svg +95 -0
- package/assets/img/geode_objects/tetrahedral_solid.svg +82 -0
- package/assets/img/geode_objects/triangulated_surface2d.svg +84 -0
- package/assets/img/geode_objects/triangulated_surface3d.svg +84 -0
- package/assets/img/geode_objects/vertex_set.svg +86 -0
- package/components/CrsSelector.vue +78 -0
- package/components/Errors/Banner.vue +48 -0
- package/components/Errors/Snackers.vue +49 -0
- package/components/ExtensionSelector.vue +53 -0
- package/components/FileSelector.vue +46 -0
- package/components/Header.vue +30 -0
- package/components/Launcher.vue +55 -0
- package/components/Loading.vue +24 -0
- package/components/ObjectSelector.vue +66 -0
- package/components/PackagesVersions.vue +54 -0
- package/components/RemoteRenderingView.client.vue +88 -0
- package/components/Step.vue +74 -0
- package/components/Stepper.vue +13 -0
- package/components/ViewToolbar.vue +30 -0
- package/components/Wrapper.vue +33 -0
- package/composables/api_fetch.js +32 -0
- package/nuxt.config.js +5 -0
- package/package.json +53 -0
- package/protocols/index.js +5 -0
- package/protocols/vtk.js +20 -0
- package/stores/cloud.js +89 -0
- package/stores/errors.js +20 -0
- package/stores/viewer.js +139 -0
- package/stores/websocket.js +94 -0
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<v-card class="pa-5 card" elevation="5">
|
|
3
|
+
<v-row align="center" @click="set_current_step(step_index)">
|
|
4
|
+
<v-col cols="auto">
|
|
5
|
+
<v-icon v-if="current_step_index > step_index" icon="mdi-check-circle" color="grey" />
|
|
6
|
+
<v-icon v-else-if="current_step_index == step_index" :icon="`mdi-numeric-${step_index + 1}-circle`"
|
|
7
|
+
color="primary" />
|
|
8
|
+
<v-icon v-else :icon="`mdi-numeric-${step_index + 1}-circle`" color="grey" />
|
|
9
|
+
</v-col>
|
|
10
|
+
<v-col cols="auto">
|
|
11
|
+
<p class="font-weight-bold">
|
|
12
|
+
{{ steps[step_index].step_title }}
|
|
13
|
+
</p>
|
|
14
|
+
</v-col>
|
|
15
|
+
<v-col v-if="steps[step_index].chips.length && (current_step_index >= step_index)">
|
|
16
|
+
<v-chip v-for="(chip, chip_index) in steps[step_index].chips" :key="chip_index">
|
|
17
|
+
{{ chip }}
|
|
18
|
+
</v-chip>
|
|
19
|
+
</v-col>
|
|
20
|
+
</v-row>
|
|
21
|
+
<Transition name="slide-fade">
|
|
22
|
+
<v-col v-if="step_index == current_step_index">
|
|
23
|
+
<component :is="steps[step_index].component.component_name"
|
|
24
|
+
v-bind="steps[step_index].component.component_options" />
|
|
25
|
+
<v-btn v-if="skippable()" @click="skipStep()" color="primary">Skip step</v-btn>
|
|
26
|
+
</v-col>
|
|
27
|
+
</Transition>
|
|
28
|
+
</v-card>
|
|
29
|
+
</template>
|
|
30
|
+
|
|
31
|
+
<script setup>
|
|
32
|
+
const props = defineProps({
|
|
33
|
+
step_index: { type: Number, required: true }
|
|
34
|
+
})
|
|
35
|
+
const { step_index } = props
|
|
36
|
+
const stepper_tree = inject('stepper_tree')
|
|
37
|
+
const { current_step_index, steps } = toRefs(stepper_tree)
|
|
38
|
+
|
|
39
|
+
function skippable () {
|
|
40
|
+
if (stepper_tree.steps[step_index].component.skippable !== undefined) {
|
|
41
|
+
return(stepper_tree.steps[step_index].component.skippable)
|
|
42
|
+
} else {
|
|
43
|
+
return(false)
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function skipStep() {
|
|
48
|
+
stepper_tree.current_step_index++
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function set_current_step (step_index) {
|
|
52
|
+
stepper_tree.current_step_index = step_index
|
|
53
|
+
}
|
|
54
|
+
</script>
|
|
55
|
+
|
|
56
|
+
<style>
|
|
57
|
+
.card {
|
|
58
|
+
border-radius: 15px;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
.slide-fade-enter-active {
|
|
62
|
+
transition: all 0.5s ease-out;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
.slide-fade-leave-active {
|
|
66
|
+
transition: all 0.5s ease-in;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
.slide-fade-enter-from,
|
|
70
|
+
.slide-fade-leave-to {
|
|
71
|
+
transform: translateX(50px);
|
|
72
|
+
opacity: 0;
|
|
73
|
+
}
|
|
74
|
+
</style>
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<v-card class="card">
|
|
3
|
+
<div v-for="(step, index) in steps" :key="index" class="pa-3">
|
|
4
|
+
<Step :step_index="index" />
|
|
5
|
+
</div>
|
|
6
|
+
</v-card>
|
|
7
|
+
</template>
|
|
8
|
+
|
|
9
|
+
<script setup>
|
|
10
|
+
const stepper_tree = inject('stepper_tree')
|
|
11
|
+
const { steps } = stepper_tree
|
|
12
|
+
|
|
13
|
+
</script>
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<v-row dense :class="[$style.floatToolbar, 'flex-column']">
|
|
3
|
+
<v-col>
|
|
4
|
+
<v-tooltip location="left">
|
|
5
|
+
Reset camera
|
|
6
|
+
<template #activator="{ props }">
|
|
7
|
+
<v-btn @click.stop=reset_camera icon="mdi-crop-free" density="comfortable" v-bind="props" />
|
|
8
|
+
</template>
|
|
9
|
+
</v-tooltip>
|
|
10
|
+
</v-col>
|
|
11
|
+
</v-row>
|
|
12
|
+
</template>
|
|
13
|
+
|
|
14
|
+
<script setup>
|
|
15
|
+
const viewer_store = use_viewer_store()
|
|
16
|
+
function reset_camera() {
|
|
17
|
+
viewer_store.reset_camera()
|
|
18
|
+
}
|
|
19
|
+
</script>
|
|
20
|
+
|
|
21
|
+
<style module>
|
|
22
|
+
.floatToolbar {
|
|
23
|
+
position: absolute;
|
|
24
|
+
z-index: 2;
|
|
25
|
+
right: 20px;
|
|
26
|
+
top: 20px;
|
|
27
|
+
background-color: rgba(0, 0, 0, 0.4);
|
|
28
|
+
border-radius: 16px;
|
|
29
|
+
}
|
|
30
|
+
</style>
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<v-container>
|
|
3
|
+
<v-row class="flex-column">
|
|
4
|
+
<v-col>
|
|
5
|
+
<Header :tool_name="tool_name" :cards_list="cards_list" />
|
|
6
|
+
</v-col>
|
|
7
|
+
<v-col v-if="!is_cloud_running">
|
|
8
|
+
<Launcher :site_key="site_key" />
|
|
9
|
+
</v-col>
|
|
10
|
+
<v-col v-if="is_cloud_running">
|
|
11
|
+
<Stepper />
|
|
12
|
+
</v-col>
|
|
13
|
+
<v-col v-if="is_cloud_running">
|
|
14
|
+
<PackagesVersions :route_prefix="route_prefix" />
|
|
15
|
+
</v-col>
|
|
16
|
+
</v-row>
|
|
17
|
+
</v-container>
|
|
18
|
+
</template>
|
|
19
|
+
|
|
20
|
+
<script setup>
|
|
21
|
+
const cloud_store = use_cloud_store()
|
|
22
|
+
const { is_cloud_running } = storeToRefs(cloud_store)
|
|
23
|
+
|
|
24
|
+
const props = defineProps({
|
|
25
|
+
cards_list: { type: Array, required: true },
|
|
26
|
+
site_key: { type: String, required: true }
|
|
27
|
+
})
|
|
28
|
+
const { cards_list, site_key } = props
|
|
29
|
+
|
|
30
|
+
const stepper_tree = inject('stepper_tree')
|
|
31
|
+
const { tool_name, route_prefix } = stepper_tree
|
|
32
|
+
|
|
33
|
+
</script>
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
export async function api_fetch (request_url, request_options, { request_error_function, response_function, response_error_function } = {}) {
|
|
2
|
+
const errors_store = use_errors_store()
|
|
3
|
+
const cloud_store = use_cloud_store()
|
|
4
|
+
|
|
5
|
+
return useFetch(request_url,
|
|
6
|
+
{
|
|
7
|
+
baseURL: cloud_store.geode_url,
|
|
8
|
+
...request_options,
|
|
9
|
+
onRequestError ({ error }) {
|
|
10
|
+
// MUST STAY HERE FOR EASIER DEBUG
|
|
11
|
+
// console.log('onRequestError', error)
|
|
12
|
+
errors_store.add_error({ "code": '', "route": request_url, 'name': error.message, 'description': error.stack })
|
|
13
|
+
if (request_error_function) { request_error_function(error) }
|
|
14
|
+
},
|
|
15
|
+
onResponse ({ response }) {
|
|
16
|
+
if (response.ok) {
|
|
17
|
+
// MUST STAY HERE FOR EASIER DEBUG
|
|
18
|
+
// console.log('onResponse', response)
|
|
19
|
+
if (response_function) { response_function(response) }
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
onResponseError ({ response }) {
|
|
23
|
+
// MUST STAY HERE FOR EASIER DEBUG
|
|
24
|
+
// console.log('onResponseError', response)
|
|
25
|
+
errors_store.add_error({ "code": response.status, "route": request_url, 'name': response._data.name, 'description': response._data.description })
|
|
26
|
+
if (response_error_function) { response_error_function(response) }
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
)
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export default api_fetch
|
package/nuxt.config.js
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@geode/opengeodeweb-front",
|
|
3
|
+
"private": false,
|
|
4
|
+
"scripts": {
|
|
5
|
+
"lint": "eslint --fix --ext .js,.vue --ignore-path .gitignore ."
|
|
6
|
+
},
|
|
7
|
+
"devDependencies": {
|
|
8
|
+
"eslint": "^8.47.0",
|
|
9
|
+
"eslint-plugin-import": "^2.28.1",
|
|
10
|
+
"eslint-plugin-nuxt": "^4.0.0",
|
|
11
|
+
"eslint-plugin-prettier": "^5.0.0",
|
|
12
|
+
"eslint-plugin-prettier-vue": "^4.2.0",
|
|
13
|
+
"eslint-plugin-vue": "^9.17.0",
|
|
14
|
+
"eslint-plugin-vuetify": "^2.0.5",
|
|
15
|
+
"nuxt": "^3.6.5"
|
|
16
|
+
},
|
|
17
|
+
"overrides": {
|
|
18
|
+
"vue": "latest"
|
|
19
|
+
},
|
|
20
|
+
"description": "OpenSource Vue/Vuetify framework for web applications",
|
|
21
|
+
"type": "module",
|
|
22
|
+
"version": "0.0.0",
|
|
23
|
+
"main": "./nuxt.config.js",
|
|
24
|
+
"dependencies": {
|
|
25
|
+
"@kitware/vtk.js": "^28.8.0",
|
|
26
|
+
"@mdi/font": "^7.2.96",
|
|
27
|
+
"@pinia/nuxt": "^0.4.11",
|
|
28
|
+
"@types/node": "^20.5.3",
|
|
29
|
+
"@vueuse/components": "^10.3.0",
|
|
30
|
+
"@vueuse/core": "^10.3.0",
|
|
31
|
+
"lodash": "^4.17.21",
|
|
32
|
+
"pinia": "^2.1.6",
|
|
33
|
+
"sass": "^1.66.1",
|
|
34
|
+
"semver": "^7.5.4",
|
|
35
|
+
"vue-recaptcha": "^2.0.3",
|
|
36
|
+
"vuetify": "^3.3.14",
|
|
37
|
+
"wslink": "^1.11.0"
|
|
38
|
+
},
|
|
39
|
+
"repository": {
|
|
40
|
+
"type": "git",
|
|
41
|
+
"url": "git+https://github.com/Geode-solutions/OpenGeodeWeb-Front.git"
|
|
42
|
+
},
|
|
43
|
+
"keywords": [
|
|
44
|
+
"vue",
|
|
45
|
+
"vuetify"
|
|
46
|
+
],
|
|
47
|
+
"author": "@geode",
|
|
48
|
+
"license": "MIT",
|
|
49
|
+
"bugs": {
|
|
50
|
+
"url": "https://github.com/Geode-solutions/OpenGeodeWeb-Front/issues"
|
|
51
|
+
},
|
|
52
|
+
"homepage": "https://github.com/Geode-solutions/OpenGeodeWeb-Front#readme"
|
|
53
|
+
}
|
package/protocols/vtk.js
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/* eslint-disable arrow-body-style */
|
|
2
|
+
function createMethods (session) {
|
|
3
|
+
return {
|
|
4
|
+
create_object_pipeline: (params) => session.call('create_object_pipeline', [params]),
|
|
5
|
+
create_visualization: () => session.call('create_visualization', []),
|
|
6
|
+
reset: () => session.call('reset'),
|
|
7
|
+
reset_camera: () => session.call('reset_camera', []),
|
|
8
|
+
toggle_object_visibility: (params) => session.call('toggle_object_visibility', [params]),
|
|
9
|
+
toggle_edge_visibility: (params) => session.call('toggle_edge_visibility', [params]),
|
|
10
|
+
toggle_point_visibility: (params) => session.call('toggle_point_visibility', [params]),
|
|
11
|
+
set_color: (params) => session.call('set_color', [params]),
|
|
12
|
+
set_vertex_attribute: (params) => session.call('set_vertex_attribute', [params]),
|
|
13
|
+
point_size: (params) => session.call('point_size', [params]),
|
|
14
|
+
apply_textures: (params) => session.call('apply_textures', [params]),
|
|
15
|
+
get_point_position: (params) => session.call('get_point_position', [params]),
|
|
16
|
+
update_data: (params) => session.call('update_data', [params])
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export default createMethods
|
package/stores/cloud.js
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { defineStore } from 'pinia'
|
|
2
|
+
|
|
3
|
+
export const use_cloud_store = defineStore('cloud', {
|
|
4
|
+
state: () => ({
|
|
5
|
+
ID: '',
|
|
6
|
+
is_captcha_validated: false,
|
|
7
|
+
is_cloud_running: false,
|
|
8
|
+
is_connexion_launched: false,
|
|
9
|
+
request_counter: 0
|
|
10
|
+
}),
|
|
11
|
+
getters: {
|
|
12
|
+
geode_url: (state) => {
|
|
13
|
+
const public_runtime_config = useRuntimeConfig().public
|
|
14
|
+
var geode_url = `${public_runtime_config.GEODE_PROTOCOL}://${public_runtime_config.API_URL}:${public_runtime_config.GEODE_PORT}`
|
|
15
|
+
if (process.env.NODE_ENV == 'production') {
|
|
16
|
+
geode_url = geode_url + `/${state.ID}/geode`
|
|
17
|
+
}
|
|
18
|
+
console.log("geode_url",geode_url)
|
|
19
|
+
return geode_url
|
|
20
|
+
},
|
|
21
|
+
viewer_url: (state) => {
|
|
22
|
+
const public_runtime_config = useRuntimeConfig().public
|
|
23
|
+
var viewer_url = `${public_runtime_config.VIEWER_PROTOCOL}://${public_runtime_config.API_URL}:${public_runtime_config.VIEWER_PORT}`
|
|
24
|
+
if (process.env.NODE_ENV == 'production') {
|
|
25
|
+
viewer_url = viewer_url + `/${state.ID}/viewer`
|
|
26
|
+
}
|
|
27
|
+
viewer_url = viewer_url + '/ws'
|
|
28
|
+
return viewer_url
|
|
29
|
+
},
|
|
30
|
+
},
|
|
31
|
+
actions: {
|
|
32
|
+
async create_connexion () {
|
|
33
|
+
if (this.is_connexion_launched) { return }
|
|
34
|
+
this.is_connexion_launched = true
|
|
35
|
+
const ID = localStorage.getItem('ID')
|
|
36
|
+
if (ID === null || typeof ID === 'undefined') {
|
|
37
|
+
return this.create_backend()
|
|
38
|
+
} else {
|
|
39
|
+
const { data, error } = await useFetch(`${this.geode_url}/ping`, { method: 'POST' })
|
|
40
|
+
console.log("error", error)
|
|
41
|
+
if (data.value !== null) {
|
|
42
|
+
this.ID = ID
|
|
43
|
+
this.is_cloud_running = true
|
|
44
|
+
return this.ping_task()
|
|
45
|
+
} else {
|
|
46
|
+
return this.create_backend()
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
async create_backend () {
|
|
51
|
+
const errors_store = use_errors_store()
|
|
52
|
+
const config = useRuntimeConfig()
|
|
53
|
+
const public_runtime_config = config.public
|
|
54
|
+
const { data, error } = await useFetch(`${public_runtime_config.GEODE_PROTOCOL}://${public_runtime_config.API_URL}:${public_runtime_config.GEODE_PORT}${public_runtime_config.SITE_BRANCH}/tools/createbackend`, { method: 'POST' })
|
|
55
|
+
if (data.value !== null) {
|
|
56
|
+
this.ID = data.value.ID
|
|
57
|
+
localStorage.setItem('ID', data.value.ID)
|
|
58
|
+
this.is_cloud_running = true
|
|
59
|
+
return this.ping_task()
|
|
60
|
+
} else {
|
|
61
|
+
console.log("error : ", error)
|
|
62
|
+
errors_store.server_error = true
|
|
63
|
+
}
|
|
64
|
+
},
|
|
65
|
+
|
|
66
|
+
ping_task () {
|
|
67
|
+
setInterval(() => this.do_ping(), 10 * 1000)
|
|
68
|
+
},
|
|
69
|
+
async do_ping () {
|
|
70
|
+
const errors_store = use_errors_store()
|
|
71
|
+
const { data, error } = await useFetch(`${this.geode_url}/ping`, { method: 'POST' })
|
|
72
|
+
if (data.value !== null) {
|
|
73
|
+
this.is_cloud_running = true
|
|
74
|
+
} else {
|
|
75
|
+
errors_store.server_error = true
|
|
76
|
+
console.log("error : ", error)
|
|
77
|
+
}
|
|
78
|
+
},
|
|
79
|
+
|
|
80
|
+
mutations: {
|
|
81
|
+
start_request (state) {
|
|
82
|
+
state.request_counter++
|
|
83
|
+
},
|
|
84
|
+
stop_request (state) {
|
|
85
|
+
state.request_counter--
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
})
|
package/stores/errors.js
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { defineStore } from 'pinia'
|
|
2
|
+
|
|
3
|
+
export const use_errors_store = defineStore('errors', {
|
|
4
|
+
state: () => ({
|
|
5
|
+
errors: [],
|
|
6
|
+
server_error: false,
|
|
7
|
+
}),
|
|
8
|
+
actions: {
|
|
9
|
+
add_error (error_object) {
|
|
10
|
+
this.errors.push(error_object)
|
|
11
|
+
console.log(this.errors)
|
|
12
|
+
},
|
|
13
|
+
delete_error (error_index) {
|
|
14
|
+
this.errors.splice(error_index, 1)
|
|
15
|
+
},
|
|
16
|
+
delete_server_error () {
|
|
17
|
+
this.server_error = false
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
})
|
package/stores/viewer.js
ADDED
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import { defineStore } from 'pinia'
|
|
2
|
+
|
|
3
|
+
export const use_viewer_store = defineStore('viewer', {
|
|
4
|
+
state: () => ({
|
|
5
|
+
picking_mode: false,
|
|
6
|
+
picked_point: { x: null, y: null }
|
|
7
|
+
}),
|
|
8
|
+
actions: {
|
|
9
|
+
toggle_picking_mode(value) {
|
|
10
|
+
this.picking_mode = value
|
|
11
|
+
},
|
|
12
|
+
async set_picked_point(x, y) {
|
|
13
|
+
const response = await get_point_position({ x, y })
|
|
14
|
+
const { x: world_x, y: world_y } = response
|
|
15
|
+
this.picked_point.x = world_x
|
|
16
|
+
this.picked_point.y = world_y
|
|
17
|
+
this.picking_mode = false
|
|
18
|
+
},
|
|
19
|
+
async create_object_pipeline(params) {
|
|
20
|
+
const websocket_store = use_websocket_store()
|
|
21
|
+
if (websocket_store.client) {
|
|
22
|
+
use_websocket_store().client
|
|
23
|
+
.getRemote()
|
|
24
|
+
.vtk.create_object_pipeline(params)
|
|
25
|
+
.catch(console.error);
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
async reset_camera() {
|
|
29
|
+
const websocket_store = use_websocket_store()
|
|
30
|
+
if (websocket_store.client) {
|
|
31
|
+
use_websocket_store().client
|
|
32
|
+
.getRemote()
|
|
33
|
+
.vtk.reset_camera()
|
|
34
|
+
.catch(console.error);
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
async toggle_object_visibility(params) {
|
|
38
|
+
const websocket_store = use_websocket_store()
|
|
39
|
+
if (websocket_store.client) {
|
|
40
|
+
use_websocket_store().client
|
|
41
|
+
.getRemote()
|
|
42
|
+
.vtk.toggle_object_visibility(params)
|
|
43
|
+
.catch(console.error);
|
|
44
|
+
}
|
|
45
|
+
},
|
|
46
|
+
async toggle_edge_visibility(params) {
|
|
47
|
+
const websocket_store = use_websocket_store()
|
|
48
|
+
if (websocket_store.client) {
|
|
49
|
+
use_websocket_store().client
|
|
50
|
+
.getRemote()
|
|
51
|
+
.vtk.toggle_edge_visibility(params)
|
|
52
|
+
.catch(console.error);
|
|
53
|
+
}
|
|
54
|
+
},
|
|
55
|
+
async toggle_point_visibility(params) {
|
|
56
|
+
const websocket_store = use_websocket_store()
|
|
57
|
+
if (websocket_store.client) {
|
|
58
|
+
use_websocket_store().client
|
|
59
|
+
.getRemote()
|
|
60
|
+
.vtk.toggle_point_visibility(params)
|
|
61
|
+
.catch(console.error);
|
|
62
|
+
}
|
|
63
|
+
},
|
|
64
|
+
async point_size(params) {
|
|
65
|
+
const websocket_store = use_websocket_store()
|
|
66
|
+
if (websocket_store.client) {
|
|
67
|
+
use_websocket_store().client
|
|
68
|
+
.getRemote()
|
|
69
|
+
.vtk.point_size(params)
|
|
70
|
+
.catch(console.error);
|
|
71
|
+
}
|
|
72
|
+
},
|
|
73
|
+
async set_color(params) {
|
|
74
|
+
const websocket_store = use_websocket_store()
|
|
75
|
+
if (websocket_store.client) {
|
|
76
|
+
use_websocket_store().client
|
|
77
|
+
.getRemote()
|
|
78
|
+
.vtk.set_color(params)
|
|
79
|
+
.catch(console.error);
|
|
80
|
+
}
|
|
81
|
+
},
|
|
82
|
+
async set_vertex_attribute(params) {
|
|
83
|
+
const websocket_store = use_websocket_store()
|
|
84
|
+
if (websocket_store.client) {
|
|
85
|
+
use_websocket_store().client
|
|
86
|
+
.getRemote()
|
|
87
|
+
.vtk.set_vertex_attribute(params)
|
|
88
|
+
.catch(console.error);
|
|
89
|
+
}
|
|
90
|
+
},
|
|
91
|
+
async apply_textures(params) {
|
|
92
|
+
const websocket_store = use_websocket_store()
|
|
93
|
+
if (websocket_store.client) {
|
|
94
|
+
websocket_store.$patch({ busy: true })
|
|
95
|
+
use_websocket_store().client
|
|
96
|
+
.getRemote()
|
|
97
|
+
.vtk.apply_textures(params)
|
|
98
|
+
.catch(console.error);
|
|
99
|
+
websocket_store.$patch({ busy: false })
|
|
100
|
+
}
|
|
101
|
+
},
|
|
102
|
+
async get_point_position(params) {
|
|
103
|
+
const websocket_store = use_websocket_store()
|
|
104
|
+
if (websocket_store.client) {
|
|
105
|
+
websocket_store.$patch({ busy: true })
|
|
106
|
+
const response = await use_websocket_store().client
|
|
107
|
+
.getRemote()
|
|
108
|
+
.vtk.get_point_position(params)
|
|
109
|
+
.catch(console.error);
|
|
110
|
+
websocket_store.$patch({ busy: false })
|
|
111
|
+
return response
|
|
112
|
+
}
|
|
113
|
+
},
|
|
114
|
+
async update_data(params) {
|
|
115
|
+
const websocket_store = use_websocket_store()
|
|
116
|
+
if (websocket_store.client) {
|
|
117
|
+
websocket_store.$patch({ busy: true })
|
|
118
|
+
const response = await use_websocket_store().client
|
|
119
|
+
.getRemote()
|
|
120
|
+
.vtk.update_data(params)
|
|
121
|
+
.catch(console.error);
|
|
122
|
+
websocket_store.$patch({ busy: false })
|
|
123
|
+
return response
|
|
124
|
+
}
|
|
125
|
+
},
|
|
126
|
+
async reset() {
|
|
127
|
+
const websocket_store = use_websocket_store()
|
|
128
|
+
if (websocket_store.client) {
|
|
129
|
+
websocket_store.$patch({ busy: true })
|
|
130
|
+
const response = await use_websocket_store().client
|
|
131
|
+
.getRemote()
|
|
132
|
+
.vtk.reset()
|
|
133
|
+
.catch(console.error);
|
|
134
|
+
websocket_store.$patch({ busy: false })
|
|
135
|
+
return response
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
})
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { defineStore } from 'pinia'
|
|
2
|
+
import _ from 'lodash'
|
|
3
|
+
|
|
4
|
+
import vtkWSLinkClient from '@kitware/vtk.js/IO/Core/WSLinkClient'
|
|
5
|
+
import SmartConnect from 'wslink/src/SmartConnect'
|
|
6
|
+
|
|
7
|
+
import '@kitware/vtk.js/Rendering/OpenGL/Profiles/Geometry'
|
|
8
|
+
import { connectImageStream } from '@kitware/vtk.js/Rendering/Misc/RemoteView'
|
|
9
|
+
import protocols from '@/protocols'
|
|
10
|
+
|
|
11
|
+
// Bind vtkWSLinkClient to our SmartConnect
|
|
12
|
+
vtkWSLinkClient.setSmartConnectClass(SmartConnect);
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
export const use_websocket_store = defineStore('websocket', {
|
|
16
|
+
state: () => ({
|
|
17
|
+
client: {},
|
|
18
|
+
config: null,
|
|
19
|
+
busy: false,
|
|
20
|
+
is_client_created: false
|
|
21
|
+
}),
|
|
22
|
+
actions: {
|
|
23
|
+
ws_connect () {
|
|
24
|
+
const config = { application: 'cone' };
|
|
25
|
+
const cloud_store = use_cloud_store()
|
|
26
|
+
config.sessionURL = cloud_store.viewer_url
|
|
27
|
+
|
|
28
|
+
const { client } = this
|
|
29
|
+
if (this.is_client_created && client.isConnected()) {
|
|
30
|
+
client.disconnect(-1);
|
|
31
|
+
this.is_client_created = false;
|
|
32
|
+
}
|
|
33
|
+
let clientToConnect = client;
|
|
34
|
+
if (_.isEmpty(clientToConnect)) {
|
|
35
|
+
clientToConnect = vtkWSLinkClient.newInstance({ protocols });
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// Connect to busy store
|
|
39
|
+
clientToConnect.onBusyChange((count) => {
|
|
40
|
+
this.buzy = count
|
|
41
|
+
});
|
|
42
|
+
clientToConnect.beginBusy();
|
|
43
|
+
|
|
44
|
+
// Error
|
|
45
|
+
clientToConnect.onConnectionError((httpReq) => {
|
|
46
|
+
const message =
|
|
47
|
+
(httpReq && httpReq.response && httpReq.response.error) ||
|
|
48
|
+
`Connection error`;
|
|
49
|
+
console.error(message);
|
|
50
|
+
console.log(httpReq);
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
// Close
|
|
54
|
+
clientToConnect.onConnectionClose((httpReq) => {
|
|
55
|
+
const message =
|
|
56
|
+
(httpReq && httpReq.response && httpReq.response.error) ||
|
|
57
|
+
`Connection close`;
|
|
58
|
+
console.error(message);
|
|
59
|
+
console.log(httpReq);
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
// Connect
|
|
63
|
+
clientToConnect
|
|
64
|
+
.connect(config)
|
|
65
|
+
.then((validClient) => {
|
|
66
|
+
connectImageStream(validClient.getConnection().getSession());
|
|
67
|
+
this.client = validClient
|
|
68
|
+
clientToConnect.endBusy();
|
|
69
|
+
|
|
70
|
+
// Now that the client is ready let's setup the server for us
|
|
71
|
+
this.ws_initialize_server()
|
|
72
|
+
this.client.getRemote().vtk.reset().catch(console.error);
|
|
73
|
+
this.is_client_created = true;
|
|
74
|
+
})
|
|
75
|
+
.catch((error) => {
|
|
76
|
+
console.error(error);
|
|
77
|
+
});
|
|
78
|
+
},
|
|
79
|
+
ws_initialize_server () {
|
|
80
|
+
|
|
81
|
+
if (!_.isEmpty(this.client)) {
|
|
82
|
+
this.client
|
|
83
|
+
.getRemote()
|
|
84
|
+
.vtk.create_visualization()
|
|
85
|
+
.catch(console.error);
|
|
86
|
+
}
|
|
87
|
+
},
|
|
88
|
+
reset_camera () {
|
|
89
|
+
if (!_.isEmpty(this.client)) {
|
|
90
|
+
this.client.getRemote().vtk.reset_camera().catch(console.error);
|
|
91
|
+
}
|
|
92
|
+
},
|
|
93
|
+
},
|
|
94
|
+
})
|