@geode/opengeodeweb-front 10.18.1 → 10.18.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.
@@ -1,6 +1,6 @@
1
1
  <script setup>
2
2
  import ToolPanel from "@ogw_front/components/ToolPanel";
3
- import { applyCameraOptions } from "@ogw_internal/stores/hybrid_viewer";
3
+ import { applyCameraOptions } from "@ogw_internal/stores/hybrid_viewer_camera";
4
4
  import { useHybridViewerStore } from "@ogw_front/stores/hybrid_viewer";
5
5
  import { newInstance as vtkAnnotatedCubeActor } from "@kitware/vtk.js/Rendering/Core/AnnotatedCubeActor";
6
6
  import { newInstance as vtkGenericRenderWindow } from "@kitware/vtk.js/Rendering/Misc/GenericRenderWindow";
@@ -30,7 +30,7 @@ async function handleZScalingClose() {
30
30
  showZScaling.value = false;
31
31
  }
32
32
 
33
- const camera_options = [
33
+ const camera_options = computed(() => [
34
34
  {
35
35
  tooltip: "Reset camera",
36
36
  icon: "mdi-cube-scan",
@@ -41,10 +41,50 @@ const camera_options = [
41
41
  {
42
42
  tooltip: "Center on click",
43
43
  icon: "mdi-crosshairs-question",
44
+ color: hybridViewerStore.is_picking ? "primary" : undefined,
44
45
  action: () => {
45
46
  hybridViewerStore.is_picking = !hybridViewerStore.is_picking;
46
47
  },
47
48
  },
49
+ {
50
+ tooltip: "Highlight on hover",
51
+ icon: "mdi-cursor-default-click",
52
+ color: hybridViewerStore.is_hover_highlight ? "primary" : undefined,
53
+ menu: [
54
+ {
55
+ title: "Cells",
56
+ icon: "mdi-select-all",
57
+ action: () => {
58
+ if (
59
+ hybridViewerStore.is_hover_highlight &&
60
+ hybridViewerStore.hover_highlight_field_type === "CELL"
61
+ ) {
62
+ hybridViewerStore.is_hover_highlight = false;
63
+ hybridViewerStore.clearHoverHighlight();
64
+ } else {
65
+ hybridViewerStore.is_hover_highlight = true;
66
+ hybridViewerStore.hover_highlight_field_type = "CELL";
67
+ }
68
+ },
69
+ },
70
+ {
71
+ title: "Points",
72
+ icon: "mdi-select-drag",
73
+ action: () => {
74
+ if (
75
+ hybridViewerStore.is_hover_highlight &&
76
+ hybridViewerStore.hover_highlight_field_type === "POINT"
77
+ ) {
78
+ hybridViewerStore.is_hover_highlight = false;
79
+ hybridViewerStore.clearHoverHighlight();
80
+ } else {
81
+ hybridViewerStore.is_hover_highlight = true;
82
+ hybridViewerStore.hover_highlight_field_type = "POINT";
83
+ }
84
+ },
85
+ },
86
+ ],
87
+ },
48
88
  {
49
89
  tooltip: "Camera orientation",
50
90
  icon: "mdi-rotate-3d",
@@ -70,6 +110,7 @@ const camera_options = [
70
110
  {
71
111
  tooltip: "Toggle grid scale",
72
112
  icon: "mdi-ruler-square",
113
+ color: grid_scale.value ? "primary" : undefined,
73
114
  action: () => {
74
115
  viewerStore.request(
75
116
  schemas.opengeodeweb_viewer.viewer.grid_scale,
@@ -90,19 +131,54 @@ const camera_options = [
90
131
  showZScaling.value = !showZScaling.value;
91
132
  },
92
133
  },
93
- ];
134
+ ]);
94
135
  </script>
95
136
 
96
137
  <template>
97
138
  <v-container :class="[$style.floatToolbar, 'pa-0']" width="auto">
98
139
  <v-row v-for="camera_option in camera_options" :key="camera_option.icon" dense>
99
140
  <v-col>
141
+ <v-menu v-if="camera_option.menu" location="start" :close-on-content-click="false">
142
+ <template #activator="{ props }">
143
+ <ActionButton
144
+ v-bind="props"
145
+ :icon="
146
+ typeof camera_option.icon === 'function' ? camera_option.icon() : camera_option.icon
147
+ "
148
+ :tooltip="camera_option.tooltip"
149
+ :color="camera_option.color"
150
+ :icon-size="camera_option.iconSize"
151
+ tooltip-location="left"
152
+ />
153
+ </template>
154
+ <v-card class="pa-1 mr-2" elevation="4" rounded="pill">
155
+ <v-row dense>
156
+ <v-col v-for="item in camera_option.menu" :key="item.title">
157
+ <ActionButton
158
+ :icon="item.icon"
159
+ :tooltip="item.title"
160
+ :color="
161
+ hybridViewerStore.is_hover_highlight &&
162
+ hybridViewerStore.hover_highlight_field_type ===
163
+ item.title.toUpperCase().slice(0, -1)
164
+ ? 'primary'
165
+ : undefined
166
+ "
167
+ tooltip-location="top"
168
+ @click="item.action"
169
+ />
170
+ </v-col>
171
+ </v-row>
172
+ </v-card>
173
+ </v-menu>
100
174
  <ActionButton
175
+ v-else
101
176
  :icon="camera_option.icon"
102
177
  :tooltip="camera_option.tooltip"
178
+ :color="camera_option.color"
103
179
  :icon-size="camera_option.iconSize"
104
180
  tooltip-location="left"
105
- @click.stop="camera_option.action"
181
+ @click.stop="camera_option.action?.()"
106
182
  />
107
183
  </v-col>
108
184
  </v-row>
@@ -1,5 +1,5 @@
1
1
  <script setup>
2
- import { getRGBPointsFromPreset, scientificPresets } from "@ogw_front/utils/colormap";
2
+ import { colormaps, getRGBPointsFromPreset } from "@ogw_front/utils/colormap";
3
3
  import ColorMapList from "./ColorMapList.vue";
4
4
  import { newInstance } from "@kitware/vtk.js/Rendering/Core/ColorTransferFunction";
5
5
 
@@ -18,13 +18,13 @@ const lutCanvas = ref();
18
18
 
19
19
  const presets = computed(() => {
20
20
  let currentPreset = undefined;
21
- for (const category of scientificPresets) {
21
+ for (const category of colormaps) {
22
22
  currentPreset = category.Children.find((preset) => preset.Name === selectedPresetName.value);
23
23
  if (currentPreset) {
24
24
  break;
25
25
  }
26
26
  }
27
- return [currentPreset, ...scientificPresets].filter(Boolean);
27
+ return [currentPreset, ...colormaps].filter(Boolean);
28
28
  });
29
29
 
30
30
  function drawLutCanvas() {
@@ -12,89 +12,87 @@ 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";
14
14
 
15
- export function useProjectManager() {
16
- async function exportProject() {
17
- console.log("[export triggered]");
18
- const appStore = useAppStore();
19
- const geodeStore = useGeodeStore();
20
- const snapshot = await appStore.exportStores();
21
- const schema = back_schemas.opengeodeweb_back.export_project;
22
- const defaultName = "project.vease";
23
-
24
- const result = await $fetch(schema.$id, {
25
- baseURL: geodeStore.base_url,
26
- method: schema.methods.find((method) => method !== "OPTIONS"),
27
- body: { snapshot, filename: defaultName },
28
- });
29
- fileDownload(result, defaultName);
30
- return { result };
15
+ async function exportProject() {
16
+ console.log("[export triggered]");
17
+ const appStore = useAppStore();
18
+ const geodeStore = useGeodeStore();
19
+ const snapshot = await appStore.exportStores();
20
+ const schema = back_schemas.opengeodeweb_back.export_project;
21
+ const defaultName = "project.vease";
22
+
23
+ const result = await $fetch(schema.$id, {
24
+ baseURL: geodeStore.base_url,
25
+ method: schema.methods.find((method) => method !== "OPTIONS"),
26
+ body: { snapshot, filename: defaultName },
27
+ });
28
+ fileDownload(result, defaultName);
29
+ return { result };
30
+ }
31
+
32
+ async function importProject(project) {
33
+ const geodeStore = useGeodeStore();
34
+ const dataStyleStore = useDataStyleStore();
35
+ const viewerStore = useViewerStore();
36
+ const dataStore = useDataStore();
37
+ const treeviewStore = useTreeviewStore();
38
+ const hybridViewerStore = useHybridViewerStore();
39
+
40
+ await viewerStore.ws_connect();
41
+
42
+ const { client } = viewerStore;
43
+ if (client && client.getConnection && client.getConnection().getSession) {
44
+ await client.getConnection().getSession().call("opengeodeweb_viewer.release_database", [{}]);
45
+ }
46
+
47
+ await viewerStore.request(
48
+ viewer_schemas.opengeodeweb_viewer.viewer.reset_visualization,
49
+ {},
50
+ undefined,
51
+ );
52
+
53
+ treeviewStore.clear();
54
+ dataStore.clear();
55
+ hybridViewerStore.clear();
56
+
57
+ const schemaImport = back_schemas.opengeodeweb_back.import_project;
58
+ const form = new FormData();
59
+ const originalFileName = project && project.name ? project.name : "project.vease";
60
+ if (!originalFileName.toLowerCase().endsWith(".vease")) {
61
+ throw new Error("Uploaded file must be a .vease");
62
+ }
63
+ form.append("file", project, originalFileName);
64
+
65
+ const result = await $fetch(schemaImport.$id, {
66
+ baseURL: geodeStore.base_url,
67
+ method: "POST",
68
+ body: form,
69
+ });
70
+ const snapshot = result && result.snapshot ? result.snapshot : {};
71
+
72
+ treeviewStore.isImporting = true;
73
+
74
+ const { client: client2 } = viewerStore;
75
+ if (client2 && client2.getConnection && client2.getConnection().getSession) {
76
+ await client2.getConnection().getSession().call("opengeodeweb_viewer.import_project", [{}]);
31
77
  }
32
78
 
33
- async function importProjectFile(file) {
34
- const geodeStore = useGeodeStore();
35
- const dataStyleStore = useDataStyleStore();
36
- const viewerStore = useViewerStore();
37
- const dataStore = useDataStore();
38
- const treeviewStore = useTreeviewStore();
39
- const hybridViewerStore = useHybridViewerStore();
40
-
41
- await viewerStore.ws_connect();
42
-
43
- const { client } = viewerStore;
44
- if (client && client.getConnection && client.getConnection().getSession) {
45
- await client.getConnection().getSession().call("opengeodeweb_viewer.release_database", [{}]);
46
- }
47
-
48
- await viewerStore.request(
49
- viewer_schemas.opengeodeweb_viewer.viewer.reset_visualization,
50
- {},
51
- undefined,
52
- );
53
-
54
- treeviewStore.clear();
55
- dataStore.clear();
56
- hybridViewerStore.clear();
57
-
58
- const schemaImport = back_schemas.opengeodeweb_back.import_project;
59
- const form = new FormData();
60
- const originalFileName = file && file.name ? file.name : "project.vease";
61
- if (!originalFileName.toLowerCase().endsWith(".vease")) {
62
- throw new Error("Uploaded file must be a .vease");
63
- }
64
- form.append("file", file, originalFileName);
65
-
66
- const result = await $fetch(schemaImport.$id, {
67
- baseURL: geodeStore.base_url,
68
- method: "POST",
69
- body: form,
70
- });
71
- const snapshot = result && result.snapshot ? result.snapshot : {};
72
-
73
- treeviewStore.isImporting = true;
74
-
75
- const { client: client2 } = viewerStore;
76
- if (client2 && client2.getConnection && client2.getConnection().getSession) {
77
- await client2.getConnection().getSession().call("opengeodeweb_viewer.import_project", [{}]);
78
- }
79
-
80
- await treeviewStore.importStores(snapshot.treeview || {});
81
- await hybridViewerStore.initHybridViewer();
82
- await hybridViewerStore.importStores(snapshot.hybridViewer || {});
83
-
84
- const items = snapshot?.data?.items || [];
85
-
86
- await importWorkflowFromSnapshot(items);
87
- await hybridViewerStore.importStores(snapshot.hybridViewer || {});
88
- {
89
- await dataStyleStore.importStores(snapshot.dataStyle || {});
90
- }
91
- {
92
- await dataStyleStore.applyAllStylesFromState();
93
- }
94
-
95
- treeviewStore.finalizeImportSelection();
96
- treeviewStore.isImporting = false;
79
+ await treeviewStore.importStores(snapshot.treeview || {});
80
+ await hybridViewerStore.initHybridViewer();
81
+ await hybridViewerStore.importStores(snapshot.hybridViewer || {});
82
+
83
+ const items = snapshot?.data?.items || [];
84
+
85
+ await importWorkflowFromSnapshot(items);
86
+ await hybridViewerStore.importStores(snapshot.hybridViewer || {});
87
+ {
88
+ await dataStyleStore.importStores(snapshot.dataStyle || {});
89
+ }
90
+ {
91
+ await dataStyleStore.applyAllStylesFromState();
97
92
  }
98
93
 
99
- return { exportProject, importProjectFile };
94
+ treeviewStore.finalizeImportSelection();
95
+ treeviewStore.isImporting = false;
100
96
  }
97
+
98
+ export { exportProject, importProject };
@@ -9,27 +9,28 @@ import { useViewerStore } from "@ogw_front/stores/viewer";
9
9
 
10
10
  export const useCameraManagerStore = defineStore("camera_manager", () => {
11
11
  const viewerStore = useViewerStore();
12
+ const camera_positions_db = database.camera_positions;
12
13
 
13
14
  function refAllCameraPositions() {
14
15
  return useObservable(
15
- liveQuery(() => database.camera_positions.toArray()),
16
+ liveQuery(() => camera_positions_db.toArray()),
16
17
  { initialValue: [] },
17
18
  );
18
19
  }
19
20
 
20
21
  async function getCameraPosition(id) {
21
- return await database.camera_positions.get(id);
22
+ return await camera_positions_db.get(id);
22
23
  }
23
24
 
24
25
  async function saveCameraPosition(name, camera_options) {
25
- await database.camera_positions.put({
26
+ await camera_positions_db.put({
26
27
  name,
27
28
  camera_options,
28
29
  });
29
30
  }
30
31
 
31
32
  async function restoreCameraPosition(id) {
32
- const position = await database.camera_positions.get(id);
33
+ const position = await camera_positions_db.get(id);
33
34
  if (position) {
34
35
  await viewerStore.request(viewer_schemas.opengeodeweb_viewer.viewer.update_camera, {
35
36
  camera_options: position.camera_options,
@@ -38,11 +39,11 @@ export const useCameraManagerStore = defineStore("camera_manager", () => {
38
39
  }
39
40
 
40
41
  async function deleteCameraPosition(id) {
41
- await database.camera_positions.delete(id);
42
+ await camera_positions_db.delete(id);
42
43
  }
43
44
 
44
45
  async function renameCameraPosition(id, newName) {
45
- await database.camera_positions.update(id, { name: newName });
46
+ await camera_positions_db.update(id, { name: newName });
46
47
  }
47
48
 
48
49
  return {
@@ -12,9 +12,12 @@ const viewer_generic_schemas = viewer_schemas.opengeodeweb_viewer.generic;
12
12
  // oxlint-disable-next-line max-lines-per-function, max-statements
13
13
  export const useDataStore = defineStore("data", () => {
14
14
  const viewerStore = useViewerStore();
15
+ const data_db = database.data;
16
+ const model_components_db = database.model_components;
17
+ const model_components_relation_db = database.model_components_relation;
15
18
 
16
19
  async function item(id) {
17
- const data_item = await database.data.get(id);
20
+ const data_item = await data_db.get(id);
18
21
  if (!data_item) {
19
22
  throw new Error(`Item not found: ${id}`);
20
23
  }
@@ -23,20 +26,20 @@ export const useDataStore = defineStore("data", () => {
23
26
 
24
27
  function refItem(id) {
25
28
  return useObservable(
26
- liveQuery(() => database.data.get(id)),
29
+ liveQuery(() => data_db.get(id)),
27
30
  { initialValue: {} },
28
31
  );
29
32
  }
30
33
 
31
34
  function refAllItems() {
32
35
  return useObservable(
33
- liveQuery(() => database.data.toArray()),
36
+ liveQuery(() => data_db.toArray()),
34
37
  { initialValue: [] },
35
38
  );
36
39
  }
37
40
 
38
41
  async function formatedMeshComponents(modelId) {
39
- const items = await database.model_components.where("id").equals(modelId).toArray();
42
+ const items = await model_components_db.where("id").equals(modelId).toArray();
40
43
  const componentTitles = {
41
44
  Corner: "Corners",
42
45
  Line: "Lines",
@@ -70,7 +73,7 @@ export const useDataStore = defineStore("data", () => {
70
73
  }
71
74
 
72
75
  async function getMeshComponentsByType(modelId, type) {
73
- const components = await database.model_components
76
+ const components = await model_components_db
74
77
  .where("[id+type]")
75
78
  .equals([modelId, type])
76
79
  .toArray();
@@ -84,7 +87,7 @@ export const useDataStore = defineStore("data", () => {
84
87
  }
85
88
 
86
89
  async function getAllMeshComponents(modelId) {
87
- const items = await database.model_components.where("id").equals(modelId).toArray();
90
+ const items = await model_components_db.where("id").equals(modelId).toArray();
88
91
  return items.map((meshComponent) => ({
89
92
  id: meshComponent.geode_id,
90
93
  title: meshComponent.name,
@@ -114,7 +117,7 @@ export const useDataStore = defineStore("data", () => {
114
117
  }
115
118
 
116
119
  async function meshComponentType(modelId, geode_id) {
117
- const component = await database.model_components
120
+ const component = await model_components_db
118
121
  .where("[id+geode_id]")
119
122
  .equals([modelId, geode_id])
120
123
  .first();
@@ -139,7 +142,7 @@ export const useDataStore = defineStore("data", () => {
139
142
  created_at: new Date().toISOString(),
140
143
  binary_light_viewable: new_item.binary_light_viewable,
141
144
  };
142
- return database.data.put(itemData);
145
+ return data_db.put(itemData);
143
146
  }
144
147
 
145
148
  function addComponents(new_item) {
@@ -162,7 +165,7 @@ export const useDataStore = defineStore("data", () => {
162
165
  if (new_item.collection_components) {
163
166
  addModelComponents(new_item.collection_components);
164
167
  }
165
- return database.model_components.bulkPut(allComponents);
168
+ return model_components_db.bulkPut(allComponents);
166
169
  }
167
170
 
168
171
  function addComponentRelations(new_item) {
@@ -194,11 +197,11 @@ export const useDataStore = defineStore("data", () => {
194
197
  }
195
198
  }
196
199
  }
197
- return database.model_components_relation.bulkPut(relations);
200
+ return model_components_relation_db.bulkPut(relations);
198
201
  }
199
202
 
200
203
  async function getComponentByViewerId(modelId, viewer_id) {
201
- const component = await database.model_components
204
+ const component = await model_components_db
202
205
  .where("viewer_id")
203
206
  .equals(Number(viewer_id))
204
207
  .and((model_component) => model_component.id === modelId)
@@ -207,21 +210,21 @@ export const useDataStore = defineStore("data", () => {
207
210
  }
208
211
 
209
212
  async function deleteItem(id) {
210
- await database.data.delete(id);
213
+ await data_db.delete(id);
211
214
  await deleteModelComponents(id);
212
215
  }
213
216
 
214
217
  async function updateItem(id, changes) {
215
- await database.data.update(id, changes);
218
+ await data_db.update(id, changes);
216
219
  }
217
220
 
218
221
  async function deleteModelComponents(modelId) {
219
- await database.model_components.where("id").equals(modelId).delete();
222
+ await model_components_db.where("id").equals(modelId).delete();
220
223
  await database.model_components_relation.where("id").equals(modelId).delete();
221
224
  }
222
225
 
223
226
  async function getMeshComponentGeodeIds(modelId, type) {
224
- const components = await database.model_components
227
+ const components = await model_components_db
225
228
  .where("[id+type]")
226
229
  .equals([modelId, type])
227
230
  .toArray();
@@ -245,12 +248,12 @@ export const useDataStore = defineStore("data", () => {
245
248
  }
246
249
 
247
250
  async function getAllModelComponentsViewerIds(modelId) {
248
- const components = await database.model_components.where("id").equals(modelId).toArray();
251
+ const components = await model_components_db.where("id").equals(modelId).toArray();
249
252
  return components.map((component) => Number.parseInt(component.viewer_id, 10));
250
253
  }
251
254
 
252
255
  async function getMeshComponentsViewerIds(modelId, meshComponentGeodeIds) {
253
- const components = await database.model_components
256
+ const components = await model_components_db
254
257
  .where("[id+geode_id]")
255
258
  .anyOf(meshComponentGeodeIds.map((geode_id) => [modelId, geode_id]))
256
259
  .toArray();
@@ -258,7 +261,7 @@ export const useDataStore = defineStore("data", () => {
258
261
  }
259
262
 
260
263
  async function exportStores() {
261
- const items = await database.data.toArray();
264
+ const items = await data_db.toArray();
262
265
  return { items };
263
266
  }
264
267
 
@@ -267,7 +270,7 @@ export const useDataStore = defineStore("data", () => {
267
270
  }
268
271
 
269
272
  async function clear() {
270
- await database.data.clear();
273
+ await data_db.clear();
271
274
  }
272
275
 
273
276
  return {
@@ -5,14 +5,18 @@ import { useDataStyleState } from "@ogw_internal/stores/data_style/state";
5
5
  import { useMeshStyle } from "@ogw_internal/stores/data_style/mesh/index";
6
6
  import { useModelStyle } from "@ogw_internal/stores/data_style/model/index";
7
7
 
8
+ // oxlint-disable-next-line max-lines-per-function
8
9
  export const useDataStyleStore = defineStore("dataStyle", () => {
9
10
  const dataStyleState = useDataStyleState();
10
11
  const meshStyleStore = useMeshStyle();
11
12
  const modelStyleStore = useModelStyle();
12
13
  const dataStore = useDataStore();
14
+ const data_style_db = database.data_style;
15
+ const model_component_type_datastyle_db = database.model_component_type_datastyle;
16
+ const component_datastyle_db = database.component_datastyle;
13
17
 
14
18
  async function addDataStyle(id, geode_object) {
15
- await database.data_style.put(structuredClone({ id, ...getDefaultStyle(geode_object) }));
19
+ await data_style_db.put(structuredClone({ id, ...getDefaultStyle(geode_object) }));
16
20
  }
17
21
 
18
22
  async function setVisibility(id, visibility) {
@@ -57,13 +61,13 @@ export const useDataStyleStore = defineStore("dataStyle", () => {
57
61
  await dataStyleState.clear();
58
62
 
59
63
  const style_promises = Object.entries(stylesSnapshot).map(([id, style]) =>
60
- database.data_style.put(structuredClone({ id, ...style })),
64
+ data_style_db.put(structuredClone({ id, ...style })),
61
65
  );
62
66
  const component_style_promises = Object.values(componentStylesSnapshot).map((style) =>
63
- database.model_component_datastyle.put(structuredClone(style)),
67
+ component_datastyle_db.put(structuredClone(style)),
64
68
  );
65
69
  const model_component_type_style_promises = Object.values(modelComponentTypeStylesSnapshot).map(
66
- (style) => database.model_component_type_datastyle.put(structuredClone(style)),
70
+ (style) => model_component_type_datastyle_db.put(structuredClone(style)),
67
71
  );
68
72
 
69
73
  await Promise.all([