@geode/opengeodeweb-front 10.20.1 → 10.21.0-rc.2
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/app/components/CrsSelector.vue +3 -3
- package/app/components/ExtensionSelector.vue +3 -3
- package/app/components/FileSelector.vue +3 -3
- package/app/components/FileUploader.vue +4 -4
- package/app/components/Inspector/InspectionButton.vue +3 -3
- package/app/components/Loading.vue +27 -0
- package/app/components/MissingFilesSelector.vue +3 -3
- package/app/components/ObjectSelector.vue +3 -3
- package/app/components/PackagesVersions.vue +4 -4
- package/app/components/Viewer/ObjectTree/Layout.vue +6 -3
- package/app/components/Viewer/ObjectTree/Views/GlobalObjects.vue +47 -1
- package/app/components/Viewer/ObjectTree/Views/ModelCollections.vue +222 -0
- package/app/components/Viewer/ObjectTree/Views/ModelComponents.vue +10 -4
- package/app/components/Viewer/Options/AttributeSelector.vue +3 -3
- package/app/components/Viewer/Options/TextureItem.vue +4 -4
- package/app/composables/model_collections.js +72 -0
- package/app/composables/model_components.js +5 -1
- package/app/composables/project_manager.js +5 -5
- package/app/composables/virtual_tree.js +8 -7
- package/app/stores/{geode.js → back.js} +16 -1
- package/app/stores/data.js +39 -111
- package/app/stores/data_helpers/collections.js +102 -0
- package/app/stores/data_helpers/mesh.js +122 -0
- package/app/stores/treeview.js +18 -8
- package/app/stores/viewer.js +18 -0
- package/app/utils/extension.js +0 -2
- package/app/utils/import_workflow.js +3 -3
- package/internal/stores/hybrid_viewer_camera_animation.js +24 -2
- package/package.json +3 -3
- package/tests/integration/setup.js +3 -3
- package/tests/unit/components/CrsSelector.nuxt.test.js +6 -6
- package/tests/unit/components/ExtensionSelector.nuxt.test.js +4 -4
- package/tests/unit/components/FileSelector.nuxt.test.js +3 -3
- package/tests/unit/components/FileUploader.nuxt.test.js +3 -3
- package/tests/unit/components/Inspector/InspectionButton.nuxt.test.js +4 -4
- package/tests/unit/components/MissingFilesSelector.nuxt.test.js +4 -4
- package/tests/unit/components/ObjectSelector.nuxt.test.js +3 -3
- package/tests/unit/components/PackagesVersions.nuxt.test.js +3 -3
- package/tests/unit/composables/api_fetch.nuxt.test.js +9 -9
- package/tests/unit/composables/project_manager.nuxt.test.js +3 -3
- package/tests/unit/composables/run_function_when_microservices_connected.nuxt.test.js +7 -7
- package/tests/unit/composables/upload_file.nuxt.test.js +7 -7
- package/tests/unit/stores/app.nuxt.test.js +9 -9
- package/tests/unit/stores/{geode.nuxt.test.js → back.nuxt.test.js} +43 -43
- package/tests/unit/stores/infra.nuxt.test.js +34 -34
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<script setup>
|
|
2
2
|
import schemas from "@geode/opengeodeweb-back/opengeodeweb_back_schemas.json";
|
|
3
|
-
import {
|
|
3
|
+
import { useBackStore } from "@ogw_front/stores/back";
|
|
4
4
|
|
|
5
5
|
const schema = schemas.opengeodeweb_back.geographic_coordinate_systems;
|
|
6
6
|
|
|
@@ -16,7 +16,7 @@ const data_table_loading = ref(false);
|
|
|
16
16
|
const crs_list = ref([]);
|
|
17
17
|
const selected_crs = ref([]);
|
|
18
18
|
const toggle_loading = useToggle(data_table_loading);
|
|
19
|
-
const
|
|
19
|
+
const backStore = useBackStore();
|
|
20
20
|
|
|
21
21
|
watch(selected_crs, (new_value) => {
|
|
22
22
|
const crs = get_selected_crs(new_value[0]);
|
|
@@ -38,7 +38,7 @@ function get_selected_crs(crs_code) {
|
|
|
38
38
|
async function get_crs_table() {
|
|
39
39
|
const params = { geode_object_type };
|
|
40
40
|
toggle_loading();
|
|
41
|
-
await
|
|
41
|
+
await backStore.request(schema, params, {
|
|
42
42
|
response_function: (response) => {
|
|
43
43
|
crs_list.value = response.crs_list;
|
|
44
44
|
},
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import schemas from "@geode/opengeodeweb-back/opengeodeweb_back_schemas.json";
|
|
3
3
|
|
|
4
4
|
import FetchingData from "@ogw_front/components/FetchingData";
|
|
5
|
-
import {
|
|
5
|
+
import { useBackStore } from "@ogw_front/stores/back";
|
|
6
6
|
|
|
7
7
|
const schema = schemas.opengeodeweb_back.geode_objects_and_output_extensions;
|
|
8
8
|
const emit = defineEmits(["update_values", "increment_step", "decrement_step"]);
|
|
@@ -19,10 +19,10 @@ const toggle_loading = useToggle(loading);
|
|
|
19
19
|
async function get_output_file_extensions() {
|
|
20
20
|
toggle_loading();
|
|
21
21
|
geode_objects_and_output_extensions.value = {};
|
|
22
|
-
const
|
|
22
|
+
const backStore = useBackStore();
|
|
23
23
|
const values = await Promise.all(
|
|
24
24
|
filenames.map(async (filename) => {
|
|
25
|
-
const response = await
|
|
25
|
+
const response = await backStore.request(schema, {
|
|
26
26
|
geode_object_type,
|
|
27
27
|
filename,
|
|
28
28
|
});
|
|
@@ -3,7 +3,7 @@ import schemas from "@geode/opengeodeweb-back/opengeodeweb_back_schemas.json";
|
|
|
3
3
|
|
|
4
4
|
import FetchingData from "@ogw_front/components/FetchingData";
|
|
5
5
|
import FileUploader from "@ogw_front/components/FileUploader";
|
|
6
|
-
import {
|
|
6
|
+
import { useBackStore } from "@ogw_front/stores/back";
|
|
7
7
|
|
|
8
8
|
const schema = schemas.opengeodeweb_back.allowed_files;
|
|
9
9
|
|
|
@@ -46,8 +46,8 @@ function files_uploaded_event(value) {
|
|
|
46
46
|
|
|
47
47
|
async function get_allowed_files() {
|
|
48
48
|
toggle_loading();
|
|
49
|
-
const
|
|
50
|
-
const response = await
|
|
49
|
+
const backStore = useBackStore();
|
|
50
|
+
const response = await backStore.request(schema, {});
|
|
51
51
|
accept.value = response.extensions.map((extension) => `.${extension}`).join(",");
|
|
52
52
|
toggle_loading();
|
|
53
53
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<script setup>
|
|
2
|
-
import {
|
|
2
|
+
import { useBackStore } from "@ogw_front/stores/back";
|
|
3
3
|
|
|
4
4
|
import CsvPreviewer from "@ogw_front/components/csv-preview/CsvPreviewer";
|
|
5
5
|
import DragAndDrop from "@ogw_front/components/DragAndDrop";
|
|
@@ -15,7 +15,7 @@ const { multiple, accept, files, auto_upload, showOverlay, mini } = defineProps(
|
|
|
15
15
|
mini: { type: Boolean, default: false },
|
|
16
16
|
});
|
|
17
17
|
|
|
18
|
-
const
|
|
18
|
+
const backStore = useBackStore();
|
|
19
19
|
const internal_files = ref(files);
|
|
20
20
|
const dragAndDropRef = useTemplateRef("dragAndDropRef");
|
|
21
21
|
const csv_dialog = ref(false);
|
|
@@ -49,7 +49,7 @@ async function onCsvConfirm(result) {
|
|
|
49
49
|
});
|
|
50
50
|
|
|
51
51
|
current_csv_file.value.isConfigured = true;
|
|
52
|
-
await
|
|
52
|
+
await backStore.upload(json_file);
|
|
53
53
|
internal_files.value = [...internal_files.value];
|
|
54
54
|
csv_dialog.value = false;
|
|
55
55
|
}
|
|
@@ -72,7 +72,7 @@ function removeFile(index) {
|
|
|
72
72
|
|
|
73
73
|
async function upload_files() {
|
|
74
74
|
toggle_loading();
|
|
75
|
-
const promise_array = internal_files.value.map((file) =>
|
|
75
|
+
const promise_array = internal_files.value.map((file) => backStore.upload(file));
|
|
76
76
|
await Promise.all(promise_array);
|
|
77
77
|
files_uploaded.value = true;
|
|
78
78
|
toggle_loading();
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<script setup>
|
|
2
2
|
import schemas from "@geode/opengeodeweb-back/opengeodeweb_back_schemas.json";
|
|
3
|
-
import {
|
|
3
|
+
import { useBackStore } from "@ogw_front/stores/back";
|
|
4
4
|
|
|
5
5
|
const schema = schemas.opengeodeweb_back.inspect_file;
|
|
6
6
|
|
|
@@ -18,9 +18,9 @@ async function get_inspection_results() {
|
|
|
18
18
|
geode_object_type,
|
|
19
19
|
filename,
|
|
20
20
|
};
|
|
21
|
-
const
|
|
21
|
+
const backStore = useBackStore();
|
|
22
22
|
|
|
23
|
-
await
|
|
23
|
+
await backStore.request(schema, params, {
|
|
24
24
|
response_function: (response) => {
|
|
25
25
|
emit("update_values", {
|
|
26
26
|
inspection_result: [response.inspection_result],
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
<script setup>
|
|
2
|
+
import { Status } from "@ogw_front/utils/status";
|
|
3
|
+
import { useInfraStore } from "@ogw_front/stores/infra";
|
|
4
|
+
|
|
2
5
|
const { logo, appName } = defineProps({
|
|
3
6
|
logo: {
|
|
4
7
|
type: String,
|
|
@@ -10,6 +13,12 @@ const { logo, appName } = defineProps({
|
|
|
10
13
|
},
|
|
11
14
|
});
|
|
12
15
|
|
|
16
|
+
const infraStore = useInfraStore();
|
|
17
|
+
|
|
18
|
+
const extensionStores = computed(() =>
|
|
19
|
+
infraStore.microservices.filter((store) => store.$id !== "back" && store.$id !== "viewer"),
|
|
20
|
+
);
|
|
21
|
+
|
|
13
22
|
const show = ref(false);
|
|
14
23
|
const progress = ref(0);
|
|
15
24
|
|
|
@@ -76,6 +85,24 @@ onUnmounted(() => {
|
|
|
76
85
|
<LoadingHeader :logo="logo" />
|
|
77
86
|
<LoadingEcoMessages :app-name="appName" />
|
|
78
87
|
<LoadingProgress :progress="progress" />
|
|
88
|
+
|
|
89
|
+
<div class="d-flex flex-wrap justify-center gap-4 w-100 mt-4">
|
|
90
|
+
<v-chip
|
|
91
|
+
v-for="store in extensionStores"
|
|
92
|
+
:key="store.$id"
|
|
93
|
+
:color="store.status === Status.CONNECTED ? 'success' : 'primary'"
|
|
94
|
+
variant="flat"
|
|
95
|
+
>
|
|
96
|
+
<v-icon
|
|
97
|
+
start
|
|
98
|
+
:icon="
|
|
99
|
+
store.status === Status.CONNECTED ? 'mdi-check-circle' : 'mdi-loading mdi-spin'
|
|
100
|
+
"
|
|
101
|
+
/>
|
|
102
|
+
{{ store.$id.charAt(0).toUpperCase() + store.$id.slice(1) }}
|
|
103
|
+
</v-chip>
|
|
104
|
+
</div>
|
|
105
|
+
|
|
79
106
|
<LoadingFooter />
|
|
80
107
|
</div>
|
|
81
108
|
</div>
|
|
@@ -3,7 +3,7 @@ import schemas from "@geode/opengeodeweb-back/opengeodeweb_back_schemas.json";
|
|
|
3
3
|
|
|
4
4
|
import FetchingData from "@ogw_front/components/FetchingData";
|
|
5
5
|
import FileUploader from "@ogw_front/components/FileUploader";
|
|
6
|
-
import {
|
|
6
|
+
import { useBackStore } from "@ogw_front/stores/back";
|
|
7
7
|
|
|
8
8
|
const schema = schemas.opengeodeweb_back.missing_files;
|
|
9
9
|
|
|
@@ -33,7 +33,7 @@ async function missing_files() {
|
|
|
33
33
|
has_missing_files.value = false;
|
|
34
34
|
mandatory_files.value = [];
|
|
35
35
|
additional_files.value = [];
|
|
36
|
-
const
|
|
36
|
+
const backStore = useBackStore();
|
|
37
37
|
|
|
38
38
|
const promise_array = filenames.map((filename) => {
|
|
39
39
|
const isCsvFile =
|
|
@@ -45,7 +45,7 @@ async function missing_files() {
|
|
|
45
45
|
additional_files: [],
|
|
46
46
|
});
|
|
47
47
|
}
|
|
48
|
-
return
|
|
48
|
+
return backStore.request(schema, { geode_object_type, filename });
|
|
49
49
|
});
|
|
50
50
|
const values = await Promise.all(promise_array);
|
|
51
51
|
for (const value of values) {
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import FetchingData from "@ogw_front/components/FetchingData.vue";
|
|
3
3
|
import { geode_objects } from "@ogw_front/assets/geode_objects";
|
|
4
4
|
import schemas from "@geode/opengeodeweb-back/opengeodeweb_back_schemas.json";
|
|
5
|
-
import {
|
|
5
|
+
import { useBackStore } from "@ogw_front/stores/back";
|
|
6
6
|
|
|
7
7
|
const schema = schemas.opengeodeweb_back.allowed_objects;
|
|
8
8
|
|
|
@@ -12,7 +12,7 @@ const { filenames } = defineProps({
|
|
|
12
12
|
filenames: { type: Array, required: true },
|
|
13
13
|
});
|
|
14
14
|
|
|
15
|
-
const
|
|
15
|
+
const backStore = useBackStore();
|
|
16
16
|
|
|
17
17
|
const loading = ref(false);
|
|
18
18
|
const allowed_objects = ref({});
|
|
@@ -52,7 +52,7 @@ async function get_allowed_objects() {
|
|
|
52
52
|
toggle_loading();
|
|
53
53
|
allowed_objects.value = {};
|
|
54
54
|
|
|
55
|
-
const promise_array = filenames.map((filename) =>
|
|
55
|
+
const promise_array = filenames.map((filename) => backStore.request(schema, { filename }));
|
|
56
56
|
const responses = await Promise.all(promise_array);
|
|
57
57
|
const allowed_objects_list = responses.map((response) => response.allowed_objects);
|
|
58
58
|
const all_keys = [...new Set(allowed_objects_list.flatMap((obj) => Object.keys(obj)))];
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
<script setup>
|
|
2
2
|
import { Status } from "@ogw_front/utils/status";
|
|
3
|
-
import {
|
|
3
|
+
import { useBackStore } from "@ogw_front/stores/back";
|
|
4
4
|
|
|
5
5
|
const { schema } = defineProps({
|
|
6
6
|
schema: { type: Object, required: true },
|
|
7
7
|
});
|
|
8
8
|
|
|
9
|
-
const
|
|
9
|
+
const backStore = useBackStore();
|
|
10
10
|
const packages_versions = ref([]);
|
|
11
11
|
|
|
12
12
|
async function get_packages_versions() {
|
|
13
|
-
await
|
|
13
|
+
await backStore.request(
|
|
14
14
|
schema,
|
|
15
15
|
{},
|
|
16
16
|
{
|
|
@@ -22,7 +22,7 @@ async function get_packages_versions() {
|
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
watch(
|
|
25
|
-
() =>
|
|
25
|
+
() => backStore.status,
|
|
26
26
|
(value) => {
|
|
27
27
|
if (value === Status.CONNECTED) {
|
|
28
28
|
get_packages_versions();
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
<script setup>
|
|
2
2
|
import GlobalObjects from "@ogw_front/components/Viewer/ObjectTree/Views/GlobalObjects.vue";
|
|
3
|
+
import ModelCollections from "@ogw_front/components/Viewer/ObjectTree/Views/ModelCollections.vue";
|
|
3
4
|
import ModelComponents from "@ogw_front/components/Viewer/ObjectTree/Views/ModelComponents.vue";
|
|
4
5
|
import ViewerObjectTreeBox from "@ogw_front/components/Viewer/ObjectTree/Box.vue";
|
|
5
6
|
import { geode_objects } from "@ogw_front/assets/geode_objects";
|
|
@@ -263,15 +264,17 @@ function onVerticalResizeStart(event, index) {
|
|
|
263
264
|
:icon="geode_objects[view.geode_object_type]?.image"
|
|
264
265
|
:scroll-top="view.scrollTop"
|
|
265
266
|
closable
|
|
266
|
-
:border-radius="index === additionalViews.length - 1 ? '
|
|
267
|
+
:border-radius="`0 ${index === 0 ? '16px' : '0'} ${index === additionalViews.length - 1 ? '16px' : '0'} 0`"
|
|
267
268
|
:border-left="false"
|
|
268
269
|
@close="treeviewStore.closeView(view.id)"
|
|
269
270
|
@dragstart="onDragStart(index + 1)"
|
|
270
271
|
@update:scroll-top="treeviewStore.setScrollTop(view.id, $event)"
|
|
271
272
|
>
|
|
272
|
-
<
|
|
273
|
+
<component
|
|
274
|
+
:is="view.viewType === 'model_collections' ? ModelCollections : ModelComponents"
|
|
273
275
|
data-testid="modelComponentsObjectTree"
|
|
274
|
-
:id="view.id"
|
|
276
|
+
:id="view.modelId || view.id"
|
|
277
|
+
:view-id="view.id"
|
|
275
278
|
@show-menu="emit('show-menu', $event)"
|
|
276
279
|
/>
|
|
277
280
|
</ViewerObjectTreeBox>
|
|
@@ -75,6 +75,31 @@ function isModel(item) {
|
|
|
75
75
|
);
|
|
76
76
|
}
|
|
77
77
|
|
|
78
|
+
const hasCollectionsMap = reactive({});
|
|
79
|
+
|
|
80
|
+
watch(
|
|
81
|
+
() => treeviewStore.items,
|
|
82
|
+
async (newItems) => {
|
|
83
|
+
const models = newItems
|
|
84
|
+
.flatMap((group) => group.children || [])
|
|
85
|
+
.filter((item) => isModel(item));
|
|
86
|
+
const fetchPromises = models.map(async (model) => {
|
|
87
|
+
if (hasCollectionsMap[model.id] === undefined) {
|
|
88
|
+
hasCollectionsMap[model.id] = false;
|
|
89
|
+
try {
|
|
90
|
+
const hasCollections = await dataStore.hasCollectionComponents(model.id);
|
|
91
|
+
hasCollectionsMap[model.id] = hasCollections;
|
|
92
|
+
} catch (error) {
|
|
93
|
+
console.error("Failed to check collections", error);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
await Promise.all(fetchPromises);
|
|
99
|
+
},
|
|
100
|
+
{ immediate: true, deep: true },
|
|
101
|
+
);
|
|
102
|
+
|
|
78
103
|
function handleHoverEnter({ item, immediate = false }) {
|
|
79
104
|
const actualItem = item.raw || item;
|
|
80
105
|
|
|
@@ -169,7 +194,28 @@ function expandAll() {
|
|
|
169
194
|
variant="text"
|
|
170
195
|
v-tooltip="'Model\'s mesh components'"
|
|
171
196
|
@click.stop="
|
|
172
|
-
treeviewStore.displayAdditionalTree(
|
|
197
|
+
treeviewStore.displayAdditionalTree(
|
|
198
|
+
item.id,
|
|
199
|
+
item.title,
|
|
200
|
+
item.geode_object_type,
|
|
201
|
+
'model_components',
|
|
202
|
+
)
|
|
203
|
+
"
|
|
204
|
+
/>
|
|
205
|
+
<v-btn
|
|
206
|
+
v-if="isModel(item) && hasCollectionsMap[item.id]"
|
|
207
|
+
icon="mdi-format-list-group"
|
|
208
|
+
size="medium"
|
|
209
|
+
class="ml-2"
|
|
210
|
+
variant="text"
|
|
211
|
+
v-tooltip="'Model\'s collections'"
|
|
212
|
+
@click.stop="
|
|
213
|
+
treeviewStore.displayAdditionalTree(
|
|
214
|
+
item.id,
|
|
215
|
+
item.title,
|
|
216
|
+
item.geode_object_type,
|
|
217
|
+
'model_collections',
|
|
218
|
+
)
|
|
173
219
|
"
|
|
174
220
|
/>
|
|
175
221
|
</template>
|
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
<script setup>
|
|
2
|
+
import { sortAndFormatItems, useTreeFilter } from "@ogw_front/composables/tree_filter";
|
|
3
|
+
import CommonTreeView from "@ogw_front/components/Viewer/ObjectTree/Base/CommonTreeView.vue";
|
|
4
|
+
import FetchingData from "@ogw_front/components/FetchingData.vue";
|
|
5
|
+
import ObjectTreeControls from "@ogw_front/components/Viewer/ObjectTree/Base/Controls.vue";
|
|
6
|
+
import ObjectTreeItemLabel from "@ogw_front/components/Viewer/ObjectTree/Base/ItemLabel.vue";
|
|
7
|
+
import { useHoverhighlight } from "@ogw_front/composables/hover_highlight";
|
|
8
|
+
import { useHybridViewerStore } from "@ogw_front/stores/hybrid_viewer";
|
|
9
|
+
import { useModelCollections } from "@ogw_front/composables/model_collections";
|
|
10
|
+
import { useTreeviewStore } from "@ogw_front/stores/treeview";
|
|
11
|
+
|
|
12
|
+
const { id, viewId } = defineProps({
|
|
13
|
+
id: { type: String, required: true },
|
|
14
|
+
viewId: { type: String, required: false },
|
|
15
|
+
});
|
|
16
|
+
const actualViewId = viewId || id;
|
|
17
|
+
const { onHoverEnter, onHoverLeave } = useHoverhighlight();
|
|
18
|
+
const hybridViewerStore = useHybridViewerStore();
|
|
19
|
+
const emit = defineEmits(["show-menu"]);
|
|
20
|
+
|
|
21
|
+
const treeviewStore = useTreeviewStore();
|
|
22
|
+
const {
|
|
23
|
+
items: rawItems,
|
|
24
|
+
collectionsCache: componentsCache,
|
|
25
|
+
localCategories,
|
|
26
|
+
selection: visibleComponents,
|
|
27
|
+
updateVisibility,
|
|
28
|
+
} = useModelCollections(id);
|
|
29
|
+
|
|
30
|
+
const currentView = computed(() =>
|
|
31
|
+
treeviewStore.opened_views.find((view) => view.id === actualViewId),
|
|
32
|
+
);
|
|
33
|
+
|
|
34
|
+
const opened = computed({
|
|
35
|
+
get: () => currentView.value?.opened || [],
|
|
36
|
+
set: (val) => treeviewStore.setOpened(actualViewId, val),
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
const {
|
|
40
|
+
search,
|
|
41
|
+
sortType,
|
|
42
|
+
filterOptions,
|
|
43
|
+
processedItems: filteredCategories,
|
|
44
|
+
availableFilterOptions,
|
|
45
|
+
toggleSort,
|
|
46
|
+
customFilter,
|
|
47
|
+
applySearchFilter,
|
|
48
|
+
} = useTreeFilter(localCategories);
|
|
49
|
+
|
|
50
|
+
function onUpdateSelection(newSelection) {
|
|
51
|
+
const finalSelection = applySearchFilter(newSelection, visibleComponents.value);
|
|
52
|
+
updateVisibility(finalSelection);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const visibleSelection = computed(() => applySearchFilter(visibleComponents.value, []));
|
|
56
|
+
|
|
57
|
+
const itemsForTreeView = computed(() => {
|
|
58
|
+
if (search.value && componentsCache.value) {
|
|
59
|
+
const query = search.value.toLowerCase();
|
|
60
|
+
const result = [];
|
|
61
|
+
for (const type of Object.keys(componentsCache.value)) {
|
|
62
|
+
const matches = componentsCache.value[type].filter(
|
|
63
|
+
(component) =>
|
|
64
|
+
component.title.toLowerCase().includes(query) ||
|
|
65
|
+
component.id.toLowerCase().includes(query),
|
|
66
|
+
);
|
|
67
|
+
if (matches.length > 0) {
|
|
68
|
+
result.push({
|
|
69
|
+
id: type,
|
|
70
|
+
title: `${type}s (${matches.length})`,
|
|
71
|
+
children: sortAndFormatItems(matches, sortType.value),
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
return result;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const result = [];
|
|
79
|
+
for (const category of filteredCategories.value) {
|
|
80
|
+
result.push({
|
|
81
|
+
...category,
|
|
82
|
+
children: sortAndFormatItems(componentsCache.value?.[category.id], sortType.value),
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
return result;
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
function showContextMenu(event, item) {
|
|
89
|
+
const actualItem = item.raw || item;
|
|
90
|
+
emit("show-menu", {
|
|
91
|
+
event,
|
|
92
|
+
itemId: actualItem.category ? actualItem.id : id,
|
|
93
|
+
context_type: actualItem.category ? "model_component" : "model_component_type",
|
|
94
|
+
modelId: id,
|
|
95
|
+
modelComponentType: actualItem.category ? undefined : actualItem.id,
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
function handleHoverEnter({ item, immediate = false }) {
|
|
100
|
+
const actualItem = item.raw || item;
|
|
101
|
+
|
|
102
|
+
if (!actualItem.category && (!actualItem.children || actualItem.children.length === 0)) {
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
const viewerIdsToHover = extractIds(actualItem);
|
|
107
|
+
|
|
108
|
+
onHoverEnter(id, () => viewerIdsToHover, "model", immediate);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
function handleHoverLeave() {
|
|
112
|
+
onHoverLeave(id);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function expandAll() {
|
|
116
|
+
const allIds = [];
|
|
117
|
+
function traverse(itemsList) {
|
|
118
|
+
for (const item of itemsList) {
|
|
119
|
+
if (item.children && item.children.length > 0) {
|
|
120
|
+
allIds.push(item.id);
|
|
121
|
+
traverse(item.children);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
traverse(itemsForTreeView.value);
|
|
126
|
+
opened.value = allIds;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
function extractIds(node) {
|
|
130
|
+
if (node.children && node.children.length > 0) {
|
|
131
|
+
return node.children.flatMap((child) => extractIds(child));
|
|
132
|
+
}
|
|
133
|
+
if (node.viewer_id !== undefined && node.viewer_id !== null) {
|
|
134
|
+
return [node.viewer_id];
|
|
135
|
+
}
|
|
136
|
+
return [];
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
function getLeafViewerIds(item) {
|
|
140
|
+
const actualItem = item.raw || item;
|
|
141
|
+
return extractIds(actualItem);
|
|
142
|
+
}
|
|
143
|
+
</script>
|
|
144
|
+
|
|
145
|
+
<template>
|
|
146
|
+
<div class="tree-view-container">
|
|
147
|
+
<ObjectTreeControls
|
|
148
|
+
v-model:search="search"
|
|
149
|
+
:sort-type="sortType"
|
|
150
|
+
:filter-options="filterOptions"
|
|
151
|
+
:available-filter-options="availableFilterOptions"
|
|
152
|
+
:is-collapsed="opened.length === 0"
|
|
153
|
+
@toggle-sort="toggleSort"
|
|
154
|
+
@collapse-all="opened = []"
|
|
155
|
+
@expand-all="expandAll"
|
|
156
|
+
/>
|
|
157
|
+
|
|
158
|
+
<FetchingData v-if="rawItems === undefined" :size="48" :width="4" text="" />
|
|
159
|
+
|
|
160
|
+
<CommonTreeView
|
|
161
|
+
:selected="visibleSelection"
|
|
162
|
+
v-model:opened="opened"
|
|
163
|
+
:items="itemsForTreeView"
|
|
164
|
+
:options="{
|
|
165
|
+
selection: { selectable: true, strategy: 'classic' },
|
|
166
|
+
search,
|
|
167
|
+
customFilter,
|
|
168
|
+
}"
|
|
169
|
+
:scroll-top="currentView?.scrollTop || 0"
|
|
170
|
+
class="transparent-treeview virtual-tree-height"
|
|
171
|
+
@update:selected="onUpdateSelection"
|
|
172
|
+
@click:item="onUpdateSelection([$event.id, ...visibleComponents])"
|
|
173
|
+
@update:scroll-top="treeviewStore.setScrollTop(actualViewId, $event)"
|
|
174
|
+
@hover:enter="handleHoverEnter"
|
|
175
|
+
@hover:leave="handleHoverLeave"
|
|
176
|
+
>
|
|
177
|
+
<template #title="{ item, isLeaf }">
|
|
178
|
+
<ObjectTreeItemLabel
|
|
179
|
+
:item="item"
|
|
180
|
+
:is-leaf="isLeaf"
|
|
181
|
+
show-tooltip
|
|
182
|
+
class="text-body-1"
|
|
183
|
+
@contextmenu.prevent.stop="showContextMenu($event, item)"
|
|
184
|
+
/>
|
|
185
|
+
</template>
|
|
186
|
+
|
|
187
|
+
<template #append="{ item }">
|
|
188
|
+
<v-btn
|
|
189
|
+
v-if="item.category || (item.children && item.children.length > 0)"
|
|
190
|
+
icon="mdi-target"
|
|
191
|
+
size="medium"
|
|
192
|
+
variant="text"
|
|
193
|
+
v-tooltip="'Focus camera on object'"
|
|
194
|
+
@click.stop="hybridViewerStore.focusCameraOnObject(id, getLeafViewerIds(item))"
|
|
195
|
+
/>
|
|
196
|
+
</template>
|
|
197
|
+
</CommonTreeView>
|
|
198
|
+
</div>
|
|
199
|
+
</template>
|
|
200
|
+
|
|
201
|
+
<style scoped>
|
|
202
|
+
.tree-view-container {
|
|
203
|
+
height: 100%;
|
|
204
|
+
display: flex;
|
|
205
|
+
flex-direction: column;
|
|
206
|
+
overflow: hidden;
|
|
207
|
+
min-height: 0;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
.virtual-tree-height {
|
|
211
|
+
flex-grow: 1;
|
|
212
|
+
min-height: 0;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
.transparent-treeview {
|
|
216
|
+
background-color: transparent;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
:deep(.v-list-item__overlay) {
|
|
220
|
+
display: none !important;
|
|
221
|
+
}
|
|
222
|
+
</style>
|
|
@@ -9,7 +9,11 @@ import { useHybridViewerStore } from "@ogw_front/stores/hybrid_viewer";
|
|
|
9
9
|
import { useModelComponents } from "@ogw_front/composables/model_components";
|
|
10
10
|
import { useTreeviewStore } from "@ogw_front/stores/treeview";
|
|
11
11
|
|
|
12
|
-
const { id } = defineProps({
|
|
12
|
+
const { id, viewId } = defineProps({
|
|
13
|
+
id: { type: String, required: true },
|
|
14
|
+
viewId: { type: String, required: false },
|
|
15
|
+
});
|
|
16
|
+
const actualViewId = viewId || id;
|
|
13
17
|
const { onHoverEnter, onHoverLeave } = useHoverhighlight();
|
|
14
18
|
const hybridViewerStore = useHybridViewerStore();
|
|
15
19
|
const emit = defineEmits(["show-menu"]);
|
|
@@ -23,11 +27,13 @@ const {
|
|
|
23
27
|
updateVisibility,
|
|
24
28
|
} = useModelComponents(id);
|
|
25
29
|
|
|
26
|
-
const currentView = computed(() =>
|
|
30
|
+
const currentView = computed(() =>
|
|
31
|
+
treeviewStore.opened_views.find((view) => view.id === actualViewId),
|
|
32
|
+
);
|
|
27
33
|
|
|
28
34
|
const opened = computed({
|
|
29
35
|
get: () => currentView.value?.opened || [],
|
|
30
|
-
set: (val) => treeviewStore.setOpened(
|
|
36
|
+
set: (val) => treeviewStore.setOpened(actualViewId, val),
|
|
31
37
|
});
|
|
32
38
|
|
|
33
39
|
const {
|
|
@@ -155,7 +161,7 @@ function expandAll() {
|
|
|
155
161
|
class="transparent-treeview virtual-tree-height"
|
|
156
162
|
@update:selected="onUpdateSelection"
|
|
157
163
|
@click:item="onUpdateSelection([$event.id, ...visibleComponents])"
|
|
158
|
-
@update:scroll-top="treeviewStore.setScrollTop(
|
|
164
|
+
@update:scroll-top="treeviewStore.setScrollTop(actualViewId, $event)"
|
|
159
165
|
@hover:enter="handleHoverEnter"
|
|
160
166
|
@hover:leave="handleHoverLeave"
|
|
161
167
|
>
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
<script setup>
|
|
2
2
|
import ViewerOptionsAttributeColorBar from "@ogw_front/components/Viewer/Options/AttributeColorBar.vue";
|
|
3
|
-
import {
|
|
3
|
+
import { useBackStore } from "@ogw_front/stores/back";
|
|
4
4
|
|
|
5
|
-
const
|
|
5
|
+
const backStore = useBackStore();
|
|
6
6
|
|
|
7
7
|
const name = defineModel("name", { type: String });
|
|
8
8
|
const range = defineModel("range", { type: Array });
|
|
@@ -49,7 +49,7 @@ function resetRange() {
|
|
|
49
49
|
}
|
|
50
50
|
|
|
51
51
|
function getAttributes() {
|
|
52
|
-
|
|
52
|
+
backStore.request(
|
|
53
53
|
schema,
|
|
54
54
|
{ id },
|
|
55
55
|
{
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<script setup>
|
|
2
2
|
import FileUploader from "@ogw_front/components/FileUploader";
|
|
3
3
|
import back_schemas from "@geode/opengeodeweb-back/opengeodeweb_back_schemas.json";
|
|
4
|
-
import {
|
|
4
|
+
import { useBackStore } from "@ogw_front/stores/back";
|
|
5
5
|
|
|
6
6
|
const emit = defineEmits(["update_value"]);
|
|
7
7
|
|
|
@@ -18,14 +18,14 @@ const texture_id = ref("");
|
|
|
18
18
|
texture_id.value = texture_id;
|
|
19
19
|
|
|
20
20
|
const texture_coordinates = ref([]);
|
|
21
|
-
const
|
|
21
|
+
const backStore = useBackStore();
|
|
22
22
|
|
|
23
23
|
onMounted(() => {
|
|
24
24
|
getTextureCoordinates();
|
|
25
25
|
});
|
|
26
26
|
|
|
27
27
|
function getTextureCoordinates() {
|
|
28
|
-
|
|
28
|
+
backStore.request(
|
|
29
29
|
back_schemas.opengeodeweb_back.texture_coordinates,
|
|
30
30
|
{ id },
|
|
31
31
|
{
|
|
@@ -38,7 +38,7 @@ function getTextureCoordinates() {
|
|
|
38
38
|
|
|
39
39
|
async function files_uploaded_event(value) {
|
|
40
40
|
if (value.length > 0) {
|
|
41
|
-
await
|
|
41
|
+
await backStore.request(
|
|
42
42
|
back_schemas.opengeodeweb_back.save_viewable_file,
|
|
43
43
|
{
|
|
44
44
|
schema: back_schemas.opengeodeweb_back.save_viewable_file,
|