@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
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { compareSelections } from "@ogw_front/utils/treeview";
|
|
2
|
+
import { useDataStore } from "@ogw_front/stores/data";
|
|
3
|
+
import { useDataStyleStore } from "@ogw_front/stores/data_style";
|
|
4
|
+
import { useHybridViewerStore } from "@ogw_front/stores/hybrid_viewer";
|
|
5
|
+
|
|
6
|
+
export function useModelCollections(viewId) {
|
|
7
|
+
const dataStore = useDataStore();
|
|
8
|
+
const dataStyleStore = useDataStyleStore();
|
|
9
|
+
const hybridViewerStore = useHybridViewerStore();
|
|
10
|
+
|
|
11
|
+
const items = dataStore.refFormatedCollectionComponents(viewId);
|
|
12
|
+
const collectionsCache = ref(undefined);
|
|
13
|
+
const localCategories = ref([]);
|
|
14
|
+
|
|
15
|
+
onMounted(async () => {
|
|
16
|
+
const data = await dataStore.fetchAllCollectionComponents(viewId);
|
|
17
|
+
collectionsCache.value = markRaw(data);
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
watch(
|
|
21
|
+
items,
|
|
22
|
+
async (newItems) => {
|
|
23
|
+
if (!newItems) {
|
|
24
|
+
localCategories.value = [];
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const data = await dataStore.fetchAllCollectionComponents(viewId);
|
|
29
|
+
collectionsCache.value = markRaw(data);
|
|
30
|
+
|
|
31
|
+
localCategories.value = newItems.map((newCategory) => {
|
|
32
|
+
const existing = localCategories.value.find((category) => category.id === newCategory.id);
|
|
33
|
+
if (existing) {
|
|
34
|
+
existing.title = newCategory.title || newCategory.id;
|
|
35
|
+
return existing;
|
|
36
|
+
}
|
|
37
|
+
return reactive({
|
|
38
|
+
...newCategory,
|
|
39
|
+
title: newCategory.title || newCategory.id,
|
|
40
|
+
});
|
|
41
|
+
});
|
|
42
|
+
},
|
|
43
|
+
{ immediate: true },
|
|
44
|
+
);
|
|
45
|
+
|
|
46
|
+
const selection = dataStyleStore.visibleMeshComponents(viewId);
|
|
47
|
+
|
|
48
|
+
async function updateVisibility(current) {
|
|
49
|
+
const previous = selection.value;
|
|
50
|
+
const { added, removed } = compareSelections(current, previous);
|
|
51
|
+
|
|
52
|
+
if (added.length === 0 && removed.length === 0) {
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
if (added.length > 0) {
|
|
57
|
+
await dataStyleStore.setModelComponentsVisibility(viewId, added, true);
|
|
58
|
+
}
|
|
59
|
+
if (removed.length > 0) {
|
|
60
|
+
await dataStyleStore.setModelComponentsVisibility(viewId, removed, false);
|
|
61
|
+
}
|
|
62
|
+
hybridViewerStore.remoteRender();
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
return {
|
|
66
|
+
items,
|
|
67
|
+
collectionsCache,
|
|
68
|
+
localCategories,
|
|
69
|
+
selection,
|
|
70
|
+
updateVisibility,
|
|
71
|
+
};
|
|
72
|
+
}
|
|
@@ -19,11 +19,15 @@ export function useModelComponents(viewId) {
|
|
|
19
19
|
|
|
20
20
|
watch(
|
|
21
21
|
items,
|
|
22
|
-
(newItems) => {
|
|
22
|
+
async (newItems) => {
|
|
23
23
|
if (!newItems) {
|
|
24
24
|
localCategories.value = [];
|
|
25
25
|
return;
|
|
26
26
|
}
|
|
27
|
+
|
|
28
|
+
const data = await dataStore.fetchAllMeshComponents(viewId);
|
|
29
|
+
componentsCache.value = markRaw(data);
|
|
30
|
+
|
|
27
31
|
localCategories.value = newItems.map((newCategory) => {
|
|
28
32
|
const existing = localCategories.value.find((category) => category.id === newCategory.id);
|
|
29
33
|
if (existing) {
|
|
@@ -5,9 +5,9 @@ import viewer_schemas from "@geode/opengeodeweb-viewer/opengeodeweb_viewer_schem
|
|
|
5
5
|
import { importWorkflowFromSnapshot } from "@ogw_front/utils/import_workflow";
|
|
6
6
|
|
|
7
7
|
import { useAppStore } from "@ogw_front/stores/app";
|
|
8
|
+
import { useBackStore } from "@ogw_front/stores/back";
|
|
8
9
|
import { useDataStore } from "@ogw_front/stores/data";
|
|
9
10
|
import { useDataStyleStore } from "@ogw_front/stores/data_style";
|
|
10
|
-
import { useGeodeStore } from "@ogw_front/stores/geode";
|
|
11
11
|
import { useHybridViewerStore } from "@ogw_front/stores/hybrid_viewer";
|
|
12
12
|
import { useTreeviewStore } from "@ogw_front/stores/treeview";
|
|
13
13
|
import { useViewerStore } from "@ogw_front/stores/viewer";
|
|
@@ -15,13 +15,13 @@ import { useViewerStore } from "@ogw_front/stores/viewer";
|
|
|
15
15
|
async function exportProject() {
|
|
16
16
|
console.log("[export triggered]");
|
|
17
17
|
const appStore = useAppStore();
|
|
18
|
-
const
|
|
18
|
+
const backStore = useBackStore();
|
|
19
19
|
const snapshot = await appStore.exportStores();
|
|
20
20
|
const schema = back_schemas.opengeodeweb_back.export_project;
|
|
21
21
|
const defaultName = "project.vease";
|
|
22
22
|
|
|
23
23
|
const result = await $fetch(schema.$id, {
|
|
24
|
-
baseURL:
|
|
24
|
+
baseURL: backStore.base_url,
|
|
25
25
|
method: schema.methods.find((method) => method !== "OPTIONS"),
|
|
26
26
|
body: { snapshot, filename: defaultName },
|
|
27
27
|
});
|
|
@@ -30,7 +30,7 @@ async function exportProject() {
|
|
|
30
30
|
}
|
|
31
31
|
|
|
32
32
|
async function importProject(file) {
|
|
33
|
-
const
|
|
33
|
+
const backStore = useBackStore();
|
|
34
34
|
const dataStyleStore = useDataStyleStore();
|
|
35
35
|
const viewerStore = useViewerStore();
|
|
36
36
|
const dataStore = useDataStore();
|
|
@@ -63,7 +63,7 @@ async function importProject(file) {
|
|
|
63
63
|
form.append("file", file, originalFileName);
|
|
64
64
|
|
|
65
65
|
const result = await $fetch(schemaImport.$id, {
|
|
66
|
-
baseURL:
|
|
66
|
+
baseURL: backStore.base_url,
|
|
67
67
|
method: "POST",
|
|
68
68
|
body: form,
|
|
69
69
|
});
|
|
@@ -30,13 +30,14 @@ export function useVirtualTree(propsIn, emit) {
|
|
|
30
30
|
emit("update:opened", [...newOpened]);
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
-
function
|
|
33
|
+
function getLeafChildrenIds(item, ids = []) {
|
|
34
34
|
const children = item[actualItemProps.value.children];
|
|
35
|
-
if (children) {
|
|
35
|
+
if (children && children.length > 0) {
|
|
36
36
|
for (const child of children) {
|
|
37
|
-
|
|
38
|
-
getAllChildrenIds(child, ids);
|
|
37
|
+
getLeafChildrenIds(child, ids);
|
|
39
38
|
}
|
|
39
|
+
} else {
|
|
40
|
+
ids.push(item[actualItemProps.value.value]);
|
|
40
41
|
}
|
|
41
42
|
return ids;
|
|
42
43
|
}
|
|
@@ -47,7 +48,7 @@ export function useVirtualTree(propsIn, emit) {
|
|
|
47
48
|
return true;
|
|
48
49
|
}
|
|
49
50
|
if (actualSelection.value.strategy === "classic") {
|
|
50
|
-
const childrenIds =
|
|
51
|
+
const childrenIds = getLeafChildrenIds(item);
|
|
51
52
|
return (
|
|
52
53
|
childrenIds.length > 0 && childrenIds.every((childId) => selectedSet.value.has(childId))
|
|
53
54
|
);
|
|
@@ -59,7 +60,7 @@ export function useVirtualTree(propsIn, emit) {
|
|
|
59
60
|
if (actualSelection.value.strategy !== "classic") {
|
|
60
61
|
return false;
|
|
61
62
|
}
|
|
62
|
-
const childrenIds =
|
|
63
|
+
const childrenIds = getLeafChildrenIds(item);
|
|
63
64
|
if (childrenIds.length === 0) {
|
|
64
65
|
return false;
|
|
65
66
|
}
|
|
@@ -75,7 +76,7 @@ export function useVirtualTree(propsIn, emit) {
|
|
|
75
76
|
const isCurrentlySelected = newSelected.has(id) || isSelected(item);
|
|
76
77
|
|
|
77
78
|
if (actualSelection.value.strategy === "classic") {
|
|
78
|
-
const childrenIds =
|
|
79
|
+
const childrenIds = getLeafChildrenIds(item);
|
|
79
80
|
if (isCurrentlySelected) {
|
|
80
81
|
newSelected.delete(id);
|
|
81
82
|
for (const childId of childrenIds) {
|
|
@@ -10,11 +10,12 @@ import { useInfraStore } from "@ogw_front/stores/infra";
|
|
|
10
10
|
const MILLISECONDS_IN_SECOND = 1000;
|
|
11
11
|
const DEFAULT_PING_INTERVAL_SECONDS = 10;
|
|
12
12
|
|
|
13
|
-
export const
|
|
13
|
+
export const useBackStore = defineStore("back", {
|
|
14
14
|
state: () => ({
|
|
15
15
|
default_local_port: "5000",
|
|
16
16
|
request_counter: 0,
|
|
17
17
|
status: Status.NOT_CONNECTED,
|
|
18
|
+
version: "0.0.0",
|
|
18
19
|
}),
|
|
19
20
|
getters: {
|
|
20
21
|
protocol() {
|
|
@@ -148,6 +149,20 @@ export const useGeodeStore = defineStore("geode", {
|
|
|
148
149
|
},
|
|
149
150
|
);
|
|
150
151
|
},
|
|
152
|
+
get_version(schema) {
|
|
153
|
+
if (!schema) {
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
return this.request(
|
|
157
|
+
schema,
|
|
158
|
+
{},
|
|
159
|
+
{
|
|
160
|
+
response_function: (response) => {
|
|
161
|
+
this.version = response.microservice_version;
|
|
162
|
+
},
|
|
163
|
+
},
|
|
164
|
+
);
|
|
165
|
+
},
|
|
151
166
|
},
|
|
152
167
|
share: {
|
|
153
168
|
omit: ["status"],
|
package/app/stores/data.js
CHANGED
|
@@ -5,6 +5,8 @@ import viewer_schemas from "@geode/opengeodeweb-viewer/opengeodeweb_viewer_schem
|
|
|
5
5
|
|
|
6
6
|
// Local imports
|
|
7
7
|
import { database } from "@ogw_internal/database/database.js";
|
|
8
|
+
import { useDataCollections } from "./data_helpers/collections.js";
|
|
9
|
+
import { useDataMesh } from "./data_helpers/mesh.js";
|
|
8
10
|
import { useViewerStore } from "@ogw_front/stores/viewer";
|
|
9
11
|
|
|
10
12
|
const viewer_generic_schemas = viewer_schemas.opengeodeweb_viewer.generic;
|
|
@@ -16,6 +18,27 @@ export const useDataStore = defineStore("data", () => {
|
|
|
16
18
|
const model_components_db = database.model_components;
|
|
17
19
|
const model_components_relation_db = database.model_components_relation;
|
|
18
20
|
|
|
21
|
+
const {
|
|
22
|
+
formatedMeshComponents,
|
|
23
|
+
refFormatedMeshComponents,
|
|
24
|
+
getMeshComponentsByType,
|
|
25
|
+
getAllMeshComponents,
|
|
26
|
+
fetchAllMeshComponents,
|
|
27
|
+
getMeshComponentGeodeIds,
|
|
28
|
+
getCornersGeodeIds,
|
|
29
|
+
getLinesGeodeIds,
|
|
30
|
+
getSurfacesGeodeIds,
|
|
31
|
+
getBlocksGeodeIds,
|
|
32
|
+
} = useDataMesh();
|
|
33
|
+
|
|
34
|
+
const {
|
|
35
|
+
hasCollectionComponents,
|
|
36
|
+
getAllCollectionComponents,
|
|
37
|
+
fetchAllCollectionComponents,
|
|
38
|
+
formatedCollectionComponents,
|
|
39
|
+
refFormatedCollectionComponents,
|
|
40
|
+
} = useDataCollections();
|
|
41
|
+
|
|
19
42
|
async function item(id) {
|
|
20
43
|
const data_item = await data_db.get(id);
|
|
21
44
|
if (!data_item) {
|
|
@@ -42,84 +65,6 @@ export const useDataStore = defineStore("data", () => {
|
|
|
42
65
|
);
|
|
43
66
|
}
|
|
44
67
|
|
|
45
|
-
async function formatedMeshComponents(modelId) {
|
|
46
|
-
const items = await model_components_db.where("id").equals(modelId).toArray();
|
|
47
|
-
const componentTitles = {
|
|
48
|
-
Corner: "Corners",
|
|
49
|
-
Line: "Lines",
|
|
50
|
-
Surface: "Surfaces",
|
|
51
|
-
Block: "Blocks",
|
|
52
|
-
};
|
|
53
|
-
|
|
54
|
-
const componentsByType = {};
|
|
55
|
-
for (const component_item of items) {
|
|
56
|
-
if (componentTitles[component_item.type]) {
|
|
57
|
-
if (!componentsByType[component_item.type]) {
|
|
58
|
-
componentsByType[component_item.type] = [];
|
|
59
|
-
}
|
|
60
|
-
componentsByType[component_item.type].push(component_item);
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
return Object.keys(componentTitles)
|
|
65
|
-
.filter((type) => componentsByType[type])
|
|
66
|
-
.map((type) => ({
|
|
67
|
-
id: type,
|
|
68
|
-
title: componentTitles[type],
|
|
69
|
-
children: componentsByType[type].map((meshComponent) => ({
|
|
70
|
-
id: meshComponent.geode_id,
|
|
71
|
-
title: meshComponent.name,
|
|
72
|
-
category: meshComponent.type,
|
|
73
|
-
viewer_id: Number(meshComponent.viewer_id),
|
|
74
|
-
is_active: meshComponent.is_active,
|
|
75
|
-
})),
|
|
76
|
-
}));
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
async function getMeshComponentsByType(modelId, type) {
|
|
80
|
-
const components = await model_components_db
|
|
81
|
-
.where("[id+type]")
|
|
82
|
-
.equals([modelId, type])
|
|
83
|
-
.toArray();
|
|
84
|
-
return components.map((meshComponent) => ({
|
|
85
|
-
id: meshComponent.geode_id,
|
|
86
|
-
title: meshComponent.name,
|
|
87
|
-
category: meshComponent.type,
|
|
88
|
-
viewer_id: Number(meshComponent.viewer_id),
|
|
89
|
-
is_active: meshComponent.is_active,
|
|
90
|
-
}));
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
async function getAllMeshComponents(modelId) {
|
|
94
|
-
const items = await model_components_db.where("id").equals(modelId).toArray();
|
|
95
|
-
return items.map((meshComponent) => ({
|
|
96
|
-
id: meshComponent.geode_id,
|
|
97
|
-
title: meshComponent.name,
|
|
98
|
-
category: meshComponent.type,
|
|
99
|
-
viewer_id: Number(meshComponent.viewer_id),
|
|
100
|
-
is_active: meshComponent.is_active,
|
|
101
|
-
}));
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
async function fetchAllMeshComponents(modelId) {
|
|
105
|
-
const components = await getAllMeshComponents(modelId);
|
|
106
|
-
const byType = {};
|
|
107
|
-
for (const component of components) {
|
|
108
|
-
if (!byType[component.category]) {
|
|
109
|
-
byType[component.category] = [];
|
|
110
|
-
}
|
|
111
|
-
byType[component.category].push(component);
|
|
112
|
-
}
|
|
113
|
-
return byType;
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
function refFormatedMeshComponents(modelId) {
|
|
117
|
-
return useObservable(
|
|
118
|
-
liveQuery(() => formatedMeshComponents(modelId)),
|
|
119
|
-
{ initialValue: undefined },
|
|
120
|
-
);
|
|
121
|
-
}
|
|
122
|
-
|
|
123
68
|
async function meshComponentType(modelId, geode_id) {
|
|
124
69
|
const component = await model_components_db
|
|
125
70
|
.where("[id+geode_id]")
|
|
@@ -227,30 +172,6 @@ export const useDataStore = defineStore("data", () => {
|
|
|
227
172
|
await database.model_components_relation.where("id").equals(modelId).delete();
|
|
228
173
|
}
|
|
229
174
|
|
|
230
|
-
async function getMeshComponentGeodeIds(modelId, type) {
|
|
231
|
-
const components = await model_components_db
|
|
232
|
-
.where("[id+type]")
|
|
233
|
-
.equals([modelId, type])
|
|
234
|
-
.toArray();
|
|
235
|
-
return components.map((component) => component.geode_id);
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
async function getCornersGeodeIds(modelId) {
|
|
239
|
-
return await getMeshComponentGeodeIds(modelId, "Corner");
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
async function getLinesGeodeIds(modelId) {
|
|
243
|
-
return await getMeshComponentGeodeIds(modelId, "Line");
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
async function getSurfacesGeodeIds(modelId) {
|
|
247
|
-
return await getMeshComponentGeodeIds(modelId, "Surface");
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
async function getBlocksGeodeIds(modelId) {
|
|
251
|
-
return await getMeshComponentGeodeIds(modelId, "Block");
|
|
252
|
-
}
|
|
253
|
-
|
|
254
175
|
async function getAllModelComponentsViewerIds(modelId) {
|
|
255
176
|
const components = await model_components_db.where("id").equals(modelId).toArray();
|
|
256
177
|
return components.map((component) => Number.parseInt(component.viewer_id, 10));
|
|
@@ -283,10 +204,6 @@ export const useDataStore = defineStore("data", () => {
|
|
|
283
204
|
allItems,
|
|
284
205
|
refItem,
|
|
285
206
|
meshComponentType,
|
|
286
|
-
formatedMeshComponents,
|
|
287
|
-
refFormatedMeshComponents,
|
|
288
|
-
getMeshComponentsByType,
|
|
289
|
-
getAllMeshComponents,
|
|
290
207
|
registerObject,
|
|
291
208
|
deregisterObject,
|
|
292
209
|
addItem,
|
|
@@ -294,18 +211,29 @@ export const useDataStore = defineStore("data", () => {
|
|
|
294
211
|
addComponentRelations,
|
|
295
212
|
deleteItem,
|
|
296
213
|
updateItem,
|
|
297
|
-
getCornersGeodeIds,
|
|
298
|
-
getLinesGeodeIds,
|
|
299
|
-
getSurfacesGeodeIds,
|
|
300
|
-
getBlocksGeodeIds,
|
|
301
214
|
getAllModelComponentsViewerIds,
|
|
302
|
-
getMeshComponentGeodeIds,
|
|
303
215
|
getMeshComponentsViewerIds,
|
|
304
216
|
getComponentByViewerId,
|
|
305
217
|
|
|
306
218
|
exportStores,
|
|
307
219
|
importStores,
|
|
308
220
|
clear,
|
|
221
|
+
|
|
222
|
+
formatedMeshComponents,
|
|
223
|
+
refFormatedMeshComponents,
|
|
224
|
+
getMeshComponentsByType,
|
|
225
|
+
getAllMeshComponents,
|
|
309
226
|
fetchAllMeshComponents,
|
|
227
|
+
getMeshComponentGeodeIds,
|
|
228
|
+
getCornersGeodeIds,
|
|
229
|
+
getLinesGeodeIds,
|
|
230
|
+
getSurfacesGeodeIds,
|
|
231
|
+
getBlocksGeodeIds,
|
|
232
|
+
|
|
233
|
+
hasCollectionComponents,
|
|
234
|
+
getAllCollectionComponents,
|
|
235
|
+
fetchAllCollectionComponents,
|
|
236
|
+
formatedCollectionComponents,
|
|
237
|
+
refFormatedCollectionComponents,
|
|
310
238
|
};
|
|
311
239
|
});
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { database } from "@ogw_internal/database/database.js";
|
|
2
|
+
import { liveQuery } from "dexie";
|
|
3
|
+
import { useDataMesh } from "./mesh.js";
|
|
4
|
+
import { useObservable } from "@vueuse/rxjs";
|
|
5
|
+
|
|
6
|
+
export function useDataCollections() {
|
|
7
|
+
const model_components_db = database.model_components;
|
|
8
|
+
const model_components_relation_db = database.model_components_relation;
|
|
9
|
+
const { getAllMeshComponents } = useDataMesh();
|
|
10
|
+
|
|
11
|
+
async function hasCollectionComponents(modelId) {
|
|
12
|
+
const count = await model_components_db
|
|
13
|
+
.where("id")
|
|
14
|
+
.equals(modelId)
|
|
15
|
+
.and((component) =>
|
|
16
|
+
["Horizon", "Fault", "FaultBlock", "StratigraphicUnit", "ModelBoundary"].includes(
|
|
17
|
+
component.type,
|
|
18
|
+
),
|
|
19
|
+
)
|
|
20
|
+
.count();
|
|
21
|
+
return count > 0;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
async function getAllCollectionComponents(modelId) {
|
|
25
|
+
const items = await model_components_db.where("id").equals(modelId).toArray();
|
|
26
|
+
return items
|
|
27
|
+
.filter((component) =>
|
|
28
|
+
["Horizon", "Fault", "FaultBlock", "StratigraphicUnit", "ModelBoundary"].includes(
|
|
29
|
+
component.type,
|
|
30
|
+
),
|
|
31
|
+
)
|
|
32
|
+
.map((component) => ({
|
|
33
|
+
id: component.geode_id,
|
|
34
|
+
title: component.name,
|
|
35
|
+
category: component.type,
|
|
36
|
+
viewer_id: Number(component.viewer_id),
|
|
37
|
+
is_active: component.is_active,
|
|
38
|
+
}));
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
async function fetchAllCollectionComponents(modelId) {
|
|
42
|
+
const components = await getAllCollectionComponents(modelId);
|
|
43
|
+
const relations = await model_components_relation_db.where("id").equals(modelId).toArray();
|
|
44
|
+
const allMeshComponents = await getAllMeshComponents(modelId);
|
|
45
|
+
const meshComponentsById = {};
|
|
46
|
+
for (const meshComponent of allMeshComponents) {
|
|
47
|
+
meshComponentsById[meshComponent.id] = meshComponent;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const byType = {};
|
|
51
|
+
for (const component of components) {
|
|
52
|
+
if (!byType[component.category]) {
|
|
53
|
+
byType[component.category] = [];
|
|
54
|
+
}
|
|
55
|
+
const itemRelations = relations.filter(
|
|
56
|
+
(relation) => relation.parent === component.id && relation.type === "collection",
|
|
57
|
+
);
|
|
58
|
+
const children = itemRelations
|
|
59
|
+
.map((relation) => meshComponentsById[relation.child])
|
|
60
|
+
.filter(Boolean);
|
|
61
|
+
byType[component.category].push({
|
|
62
|
+
...component,
|
|
63
|
+
children,
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
return byType;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
async function formatedCollectionComponents(modelId) {
|
|
70
|
+
const byType = await fetchAllCollectionComponents(modelId);
|
|
71
|
+
const collectionTitles = {
|
|
72
|
+
Horizon: "Horizons",
|
|
73
|
+
Fault: "Faults",
|
|
74
|
+
FaultBlock: "FaultBlocks",
|
|
75
|
+
StratigraphicUnit: "StratigraphicUnits",
|
|
76
|
+
ModelBoundary: "ModelBoundaries",
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
return Object.keys(collectionTitles)
|
|
80
|
+
.filter((type) => byType[type] && byType[type].length > 0)
|
|
81
|
+
.map((type) => ({
|
|
82
|
+
id: type,
|
|
83
|
+
title: collectionTitles[type],
|
|
84
|
+
children: byType[type],
|
|
85
|
+
}));
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function refFormatedCollectionComponents(modelId) {
|
|
89
|
+
return useObservable(
|
|
90
|
+
liveQuery(() => formatedCollectionComponents(modelId)),
|
|
91
|
+
{ initialValue: undefined },
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
return {
|
|
96
|
+
hasCollectionComponents,
|
|
97
|
+
getAllCollectionComponents,
|
|
98
|
+
fetchAllCollectionComponents,
|
|
99
|
+
formatedCollectionComponents,
|
|
100
|
+
refFormatedCollectionComponents,
|
|
101
|
+
};
|
|
102
|
+
}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { database } from "@ogw_internal/database/database.js";
|
|
2
|
+
import { liveQuery } from "dexie";
|
|
3
|
+
import { useObservable } from "@vueuse/rxjs";
|
|
4
|
+
|
|
5
|
+
export function useDataMesh() {
|
|
6
|
+
const model_components_db = database.model_components;
|
|
7
|
+
|
|
8
|
+
async function formatedMeshComponents(modelId) {
|
|
9
|
+
const items = await model_components_db.where("id").equals(modelId).toArray();
|
|
10
|
+
const componentTitles = {
|
|
11
|
+
Corner: "Corners",
|
|
12
|
+
Line: "Lines",
|
|
13
|
+
Surface: "Surfaces",
|
|
14
|
+
Block: "Blocks",
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
const componentsByType = {};
|
|
18
|
+
for (const component_item of items) {
|
|
19
|
+
if (componentTitles[component_item.type]) {
|
|
20
|
+
if (!componentsByType[component_item.type]) {
|
|
21
|
+
componentsByType[component_item.type] = [];
|
|
22
|
+
}
|
|
23
|
+
componentsByType[component_item.type].push(component_item);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
return Object.keys(componentTitles)
|
|
28
|
+
.filter((type) => componentsByType[type])
|
|
29
|
+
.map((type) => ({
|
|
30
|
+
id: type,
|
|
31
|
+
title: componentTitles[type],
|
|
32
|
+
children: componentsByType[type].map((meshComponent) => ({
|
|
33
|
+
id: meshComponent.geode_id,
|
|
34
|
+
title: meshComponent.name,
|
|
35
|
+
category: meshComponent.type,
|
|
36
|
+
viewer_id: Number(meshComponent.viewer_id),
|
|
37
|
+
is_active: meshComponent.is_active,
|
|
38
|
+
})),
|
|
39
|
+
}));
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function refFormatedMeshComponents(modelId) {
|
|
43
|
+
return useObservable(
|
|
44
|
+
liveQuery(() => formatedMeshComponents(modelId)),
|
|
45
|
+
{ initialValue: undefined },
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
async function getMeshComponentsByType(modelId, type) {
|
|
50
|
+
const components = await model_components_db
|
|
51
|
+
.where("[id+type]")
|
|
52
|
+
.equals([modelId, type])
|
|
53
|
+
.toArray();
|
|
54
|
+
return components.map((meshComponent) => ({
|
|
55
|
+
id: meshComponent.geode_id,
|
|
56
|
+
title: meshComponent.name,
|
|
57
|
+
category: meshComponent.type,
|
|
58
|
+
viewer_id: Number(meshComponent.viewer_id),
|
|
59
|
+
is_active: meshComponent.is_active,
|
|
60
|
+
}));
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
async function getAllMeshComponents(modelId) {
|
|
64
|
+
const items = await model_components_db.where("id").equals(modelId).toArray();
|
|
65
|
+
return items.map((meshComponent) => ({
|
|
66
|
+
id: meshComponent.geode_id,
|
|
67
|
+
title: meshComponent.name,
|
|
68
|
+
category: meshComponent.type,
|
|
69
|
+
viewer_id: Number(meshComponent.viewer_id),
|
|
70
|
+
is_active: meshComponent.is_active,
|
|
71
|
+
}));
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
async function fetchAllMeshComponents(modelId) {
|
|
75
|
+
const components = await getAllMeshComponents(modelId);
|
|
76
|
+
const byType = {};
|
|
77
|
+
for (const component of components) {
|
|
78
|
+
if (!byType[component.category]) {
|
|
79
|
+
byType[component.category] = [];
|
|
80
|
+
}
|
|
81
|
+
byType[component.category].push(component);
|
|
82
|
+
}
|
|
83
|
+
return byType;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
async function getMeshComponentGeodeIds(modelId, type) {
|
|
87
|
+
const components = await model_components_db
|
|
88
|
+
.where("[id+type]")
|
|
89
|
+
.equals([modelId, type])
|
|
90
|
+
.toArray();
|
|
91
|
+
return components.map((component) => component.geode_id);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
async function getCornersGeodeIds(modelId) {
|
|
95
|
+
return await getMeshComponentGeodeIds(modelId, "Corner");
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
async function getLinesGeodeIds(modelId) {
|
|
99
|
+
return await getMeshComponentGeodeIds(modelId, "Line");
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
async function getSurfacesGeodeIds(modelId) {
|
|
103
|
+
return await getMeshComponentGeodeIds(modelId, "Surface");
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
async function getBlocksGeodeIds(modelId) {
|
|
107
|
+
return await getMeshComponentGeodeIds(modelId, "Block");
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
return {
|
|
111
|
+
formatedMeshComponents,
|
|
112
|
+
refFormatedMeshComponents,
|
|
113
|
+
getMeshComponentsByType,
|
|
114
|
+
getAllMeshComponents,
|
|
115
|
+
fetchAllMeshComponents,
|
|
116
|
+
getMeshComponentGeodeIds,
|
|
117
|
+
getCornersGeodeIds,
|
|
118
|
+
getLinesGeodeIds,
|
|
119
|
+
getSurfacesGeodeIds,
|
|
120
|
+
getBlocksGeodeIds,
|
|
121
|
+
};
|
|
122
|
+
}
|
package/app/stores/treeview.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { defineStore } from "pinia";
|
|
2
2
|
|
|
3
|
-
import { ref,
|
|
3
|
+
import { ref, watch } from "vue";
|
|
4
4
|
import { compareSelections } from "@ogw_front/utils/treeview";
|
|
5
5
|
import { database } from "@ogw_internal/database/database";
|
|
6
6
|
|
|
@@ -45,13 +45,20 @@ export const useTreeviewStore = defineStore("treeview", () => {
|
|
|
45
45
|
watch(
|
|
46
46
|
[opened_views, panelWidth, additionalPanelWidth, selection, rowHeights],
|
|
47
47
|
() => {
|
|
48
|
+
// oxlint-disable-next-line unicorn/prefer-structured-clone
|
|
49
|
+
const clean_opened_views = JSON.parse(JSON.stringify(opened_views.value));
|
|
50
|
+
// oxlint-disable-next-line unicorn/prefer-structured-clone
|
|
51
|
+
const clean_selectionIds = JSON.parse(JSON.stringify(selection.value));
|
|
52
|
+
// oxlint-disable-next-line unicorn/prefer-structured-clone
|
|
53
|
+
const clean_rowHeights = JSON.parse(JSON.stringify(rowHeights.value));
|
|
54
|
+
|
|
48
55
|
database.treeview_config.put({
|
|
49
56
|
id: "main",
|
|
50
|
-
opened_views:
|
|
57
|
+
opened_views: clean_opened_views,
|
|
51
58
|
panelWidth: panelWidth.value,
|
|
52
59
|
additionalPanelWidth: additionalPanelWidth.value,
|
|
53
|
-
selectionIds:
|
|
54
|
-
rowHeights:
|
|
60
|
+
selectionIds: clean_selectionIds,
|
|
61
|
+
rowHeights: clean_rowHeights,
|
|
55
62
|
});
|
|
56
63
|
},
|
|
57
64
|
{ deep: true },
|
|
@@ -127,15 +134,18 @@ export const useTreeviewStore = defineStore("treeview", () => {
|
|
|
127
134
|
}
|
|
128
135
|
}
|
|
129
136
|
|
|
130
|
-
function displayAdditionalTree(id, title, geodeObjectType) {
|
|
131
|
-
const
|
|
137
|
+
function displayAdditionalTree(id, title, geodeObjectType, viewType = "model_components") {
|
|
138
|
+
const viewId = `${id}_${viewType}`;
|
|
139
|
+
const index = opened_views.value.findIndex((view) => view.id === viewId);
|
|
132
140
|
if (index !== -1) {
|
|
133
|
-
return closeView(
|
|
141
|
+
return closeView(viewId);
|
|
134
142
|
}
|
|
135
143
|
additionalPanelWidth.value = panelWidth.value;
|
|
136
144
|
opened_views.value.push({
|
|
137
145
|
type: "component",
|
|
138
|
-
id,
|
|
146
|
+
id: viewId,
|
|
147
|
+
modelId: id,
|
|
148
|
+
viewType,
|
|
139
149
|
title: title || id,
|
|
140
150
|
geode_object_type: geodeObjectType,
|
|
141
151
|
scrollTop: 0,
|