@geode/opengeodeweb-front 10.26.4-rc.1 → 10.27.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.
@@ -23,7 +23,7 @@ function calc_margin(index) {
23
23
  transition="slide-x-reverse-transition"
24
24
  max-width="200px"
25
25
  height="20px"
26
- timeout="10000"
26
+ timeout="-1"
27
27
  z-index="4"
28
28
  >
29
29
  <v-row dense class="flex-nowrap">
@@ -32,6 +32,7 @@ watch(
32
32
  :class="{ 'is-expanded': showSearch }"
33
33
  >
34
34
  <ActionButton
35
+ data-testid="searchObjectsButton"
35
36
  :tooltip="showSearch ? 'Hide search' : 'Show search'"
36
37
  icon="mdi-magnify"
37
38
  tooltipLocation="bottom"
@@ -43,6 +44,7 @@ watch(
43
44
  <v-expand-x-transition>
44
45
  <div v-if="showSearch" class="flex-grow-1 ms-1 text-no-wrap overflow-hidden">
45
46
  <SearchBar
47
+ data-testid="searchObjectsInput"
46
48
  :model-value="search"
47
49
  placeholder="Search objects..."
48
50
  color="black"
@@ -67,6 +69,7 @@ watch(
67
69
  />
68
70
  </v-fade-transition>
69
71
  <ActionButton
72
+ data-testid="sortObjectsButton"
70
73
  :tooltip="'Sort by ' + (sortType === 'name' ? 'ID' : 'Name')"
71
74
  :icon="
72
75
  sortType === 'name' ? 'mdi-sort-alphabetical-ascending' : 'mdi-sort-numeric-ascending'
@@ -79,6 +82,7 @@ watch(
79
82
  <v-menu :close-on-content-click="false">
80
83
  <template #activator="{ props: menuProps }">
81
84
  <ActionButton
85
+ data-testid="filterObjectsButton"
82
86
  tooltip="Filter options"
83
87
  icon="mdi-filter-variant"
84
88
  variant="text"
@@ -94,6 +98,7 @@ watch(
94
98
  :label="category_id"
95
99
  hide-details
96
100
  density="compact"
101
+ :data-testid="'filterCheckbox-' + category_id"
97
102
  />
98
103
  </v-list-item>
99
104
  </v-list>
@@ -50,7 +50,11 @@ const tooltipDisabled = computed(() => {
50
50
  </script>
51
51
 
52
52
  <template>
53
- <div ref="label-container" class="tree-item-label-container w-100">
53
+ <div
54
+ ref="label-container"
55
+ :data-testid="'treeRow-' + actualItem.id"
56
+ class="tree-item-label-container w-100"
57
+ >
54
58
  <v-tooltip :disabled="tooltipDisabled" location="right" open-delay="400">
55
59
  <template #activator="{ props: tooltipProps }">
56
60
  <span
@@ -52,6 +52,7 @@ watch(pressed, (value) => {
52
52
  flat
53
53
  canvas-height="75"
54
54
  hide-inputs
55
+ hide-eye-dropper
55
56
  width="220"
56
57
  mode="rgba"
57
58
  class="mx-auto"
@@ -8,6 +8,7 @@ import { useAppStore } from "@ogw_front/stores/app";
8
8
  import { useBackStore } from "@ogw_front/stores/back";
9
9
  import { useDataStore } from "@ogw_front/stores/data";
10
10
  import { useDataStyleStore } from "@ogw_front/stores/data_style";
11
+ import { useFeedbackStore } from "@ogw_front/stores/feedback";
11
12
  import { useHybridViewerStore } from "@ogw_front/stores/hybrid_viewer";
12
13
  import { useTreeviewStore } from "@ogw_front/stores/treeview";
13
14
  import { useViewerStore } from "@ogw_front/stores/viewer";
@@ -16,6 +17,7 @@ async function exportProject() {
16
17
  console.log("[export triggered]");
17
18
  const appStore = useAppStore();
18
19
  const backStore = useBackStore();
20
+ const feedbackStore = useFeedbackStore();
19
21
  const snapshot = await appStore.exportStores();
20
22
  const schema = back_schemas.opengeodeweb_back.export_project;
21
23
  const defaultName = "project.vease";
@@ -26,6 +28,7 @@ async function exportProject() {
26
28
  body: { snapshot, filename: defaultName },
27
29
  });
28
30
  fileDownload(result, defaultName);
31
+ feedbackStore.add_success("Project exported successfully");
29
32
  return { result };
30
33
  }
31
34
 
@@ -73,23 +76,20 @@ async function importProject(file) {
73
76
  await client2.getConnection().getSession().call("opengeodeweb_viewer.import_project", [{}]);
74
77
  }
75
78
 
76
- await treeviewStore.importStores(snapshot.treeview || {});
79
+ await treeviewStore.importStores(snapshot.treeview);
80
+ await dataStore.importStores(snapshot.data);
77
81
  await hybridViewerStore.initHybridViewer();
78
- await hybridViewerStore.importStores(snapshot.hybridViewer || {});
79
82
 
80
83
  const items = snapshot?.data?.items || [];
81
-
82
84
  await importWorkflowFromSnapshot(items);
83
- await hybridViewerStore.importStores(snapshot.hybridViewer || {});
84
- {
85
- await dataStyleStore.importStores(snapshot.dataStyle || {});
86
- }
87
- {
88
- await dataStyleStore.applyAllStylesFromState();
89
- }
85
+ await hybridViewerStore.importStores(snapshot.hybridViewer);
86
+ await dataStyleStore.importStores(snapshot.dataStyle);
87
+ await dataStyleStore.applyAllStylesFromState();
90
88
 
91
89
  treeviewStore.finalizeImportSelection();
92
90
  treeviewStore.isImporting = false;
91
+ const feedbackStore = useFeedbackStore();
92
+ feedbackStore.add_success("Project imported successfully");
93
93
  }
94
94
 
95
95
  export { exportProject, importProject };
@@ -191,15 +191,21 @@ export const useDataStore = defineStore("data", () => {
191
191
 
192
192
  async function exportStores() {
193
193
  const items = await data_db.toArray();
194
- return { items };
194
+ const modelComponents = await model_components_db.toArray();
195
+ const modelComponentsRelations = await model_components_relation_db.toArray();
196
+ return { items, modelComponents, modelComponentsRelations };
195
197
  }
196
198
 
197
- async function importStores(_snapshot) {
199
+ async function importStores(snapshot) {
198
200
  await clear();
201
+ await model_components_db.bulkPut(snapshot.modelComponents);
202
+ await model_components_relation_db.bulkPut(snapshot.modelComponentsRelations);
199
203
  }
200
204
 
201
205
  async function clear() {
202
206
  await data_db.clear();
207
+ await model_components_db.clear();
208
+ await model_components_relation_db.clear();
203
209
  }
204
210
 
205
211
  return {
@@ -13,7 +13,7 @@ export const useDataStyleStore = defineStore("dataStyle", () => {
13
13
  const dataStore = useDataStore();
14
14
  const data_style_db = database.data_style;
15
15
  const model_component_type_datastyle_db = database.model_component_type_datastyle;
16
- const component_datastyle_db = database.component_datastyle;
16
+ const component_datastyle_db = database.model_component_datastyle;
17
17
 
18
18
  async function addDataStyle(id, geode_object) {
19
19
  await data_style_db.put(structuredClone({ id, ...getDefaultStyle(geode_object) }));
@@ -47,9 +47,9 @@ export const useDataStyleStore = defineStore("dataStyle", () => {
47
47
 
48
48
  function exportStores() {
49
49
  return {
50
- styles: dataStyleState.styles,
51
- componentStyles: dataStyleState.componentStyles,
52
- modelComponentTypeStyles: dataStyleState.modelComponentTypeStyles,
50
+ styles: dataStyleState.styles.value,
51
+ componentStyles: dataStyleState.componentStyles.value,
52
+ modelComponentTypeStyles: dataStyleState.modelComponentTypeStyles.value,
53
53
  };
54
54
  }
55
55
 
@@ -40,11 +40,22 @@ export function useMeshCellsStyle() {
40
40
  }
41
41
  if (type === "vertex") {
42
42
  const name = meshCellsVertexAttributeStyle.meshCellsVertexAttributeName(id);
43
- return meshCellsVertexAttributeStyle.setMeshCellsVertexAttributeName(id, name);
43
+ const { colorMap } = meshCellsVertexAttributeStyle.meshCellsVertexAttributeStoredConfig(
44
+ id,
45
+ name,
46
+ );
47
+ return Promise.all([
48
+ meshCellsVertexAttributeStyle.setMeshCellsVertexAttributeName(id, name),
49
+ meshCellsVertexAttributeStyle.setMeshCellsVertexAttributeColorMap(id, colorMap),
50
+ ]);
44
51
  }
45
52
  if (type === "cell") {
46
53
  const name = meshCellsCellAttributeStyle.meshCellsCellAttributeName(id);
47
- return meshCellsCellAttributeStyle.setMeshCellsCellAttributeName(id, name);
54
+ const { colorMap } = meshCellsCellAttributeStyle.meshCellsCellAttributeStoredConfig(id, name);
55
+ return Promise.all([
56
+ meshCellsCellAttributeStyle.setMeshCellsCellAttributeName(id, name),
57
+ meshCellsCellAttributeStyle.setMeshCellsCellAttributeColorMap(id, colorMap),
58
+ ]);
48
59
  }
49
60
  throw new Error(`Unknown mesh cells coloring type: ${type}`);
50
61
  }
@@ -35,11 +35,22 @@ export function useMeshEdgesStyle() {
35
35
  }
36
36
  if (type === "vertex") {
37
37
  const name = meshEdgesVertexAttributeStyle.meshEdgesVertexAttributeName(id);
38
- return meshEdgesVertexAttributeStyle.setMeshEdgesVertexAttributeName(id, name);
38
+ const { colorMap } = meshEdgesVertexAttributeStyle.meshEdgesVertexAttributeStoredConfig(
39
+ id,
40
+ name,
41
+ );
42
+ return Promise.all([
43
+ meshEdgesVertexAttributeStyle.setMeshEdgesVertexAttributeName(id, name),
44
+ meshEdgesVertexAttributeStyle.setMeshEdgesVertexAttributeColorMap(id, colorMap),
45
+ ]);
39
46
  }
40
47
  if (type === "edge") {
41
48
  const name = meshEdgesEdgeAttributeStyle.meshEdgesEdgeAttributeName(id);
42
- return meshEdgesEdgeAttributeStyle.setMeshEdgesEdgeAttributeName(id, name);
49
+ const { colorMap } = meshEdgesEdgeAttributeStyle.meshEdgesEdgeAttributeStoredConfig(id, name);
50
+ return Promise.all([
51
+ meshEdgesEdgeAttributeStyle.setMeshEdgesEdgeAttributeName(id, name),
52
+ meshEdgesEdgeAttributeStyle.setMeshEdgesEdgeAttributeColorMap(id, colorMap),
53
+ ]);
43
54
  }
44
55
  throw new Error(`Unknown mesh edges coloring type: ${type}`);
45
56
  }
@@ -28,9 +28,17 @@ function useMeshPointsColoringStyle() {
28
28
  });
29
29
  if (type === "constant") {
30
30
  return meshPointsColorStyle.setMeshPointsColor(id, meshPointsColorStyle.meshPointsColor(id));
31
- } else if (type === "vertex") {
31
+ }
32
+ if (type === "vertex") {
32
33
  const name = meshPointsVertexAttributeStyle.meshPointsVertexAttributeName(id);
33
- return meshPointsVertexAttributeStyle.setMeshPointsVertexAttributeName(id, name);
34
+ const { colorMap } = meshPointsVertexAttributeStyle.meshPointsVertexAttributeStoredConfig(
35
+ id,
36
+ name,
37
+ );
38
+ return Promise.all([
39
+ meshPointsVertexAttributeStyle.setMeshPointsVertexAttributeName(id, name),
40
+ meshPointsVertexAttributeStyle.setMeshPointsVertexAttributeColorMap(id, colorMap),
41
+ ]);
34
42
  }
35
43
  throw new Error(`Unknown mesh points coloring type: ${type}`);
36
44
  }
@@ -34,15 +34,30 @@ function useMeshPolygonsColoringStyle() {
34
34
  id,
35
35
  meshPolygonsColorStyle.meshPolygonsColor(id),
36
36
  );
37
- } else if (type === "textures") {
37
+ }
38
+ if (type === "textures") {
38
39
  const textures = meshPolygonsTexturesStyle.meshPolygonsTextures(id);
39
40
  return meshPolygonsTexturesStyle.setMeshPolygonsTextures(id, textures);
40
- } else if (type === "vertex") {
41
+ }
42
+ if (type === "vertex") {
41
43
  const name = meshPolygonsVertexAttributeStyle.meshPolygonsVertexAttributeName(id);
42
- return meshPolygonsVertexAttributeStyle.setMeshPolygonsVertexAttributeName(id, name);
43
- } else if (type === "polygon") {
44
+ const { colorMap } = meshPolygonsVertexAttributeStyle.meshPolygonsVertexAttributeStoredConfig(
45
+ id,
46
+ name,
47
+ );
48
+ return Promise.all([
49
+ meshPolygonsVertexAttributeStyle.setMeshPolygonsVertexAttributeName(id, name),
50
+ meshPolygonsVertexAttributeStyle.setMeshPolygonsVertexAttributeColorMap(id, colorMap),
51
+ ]);
52
+ }
53
+ if (type === "polygon") {
44
54
  const name = meshPolygonsPolygonAttributeStyle.meshPolygonsPolygonAttributeName(id);
45
- return meshPolygonsPolygonAttributeStyle.setMeshPolygonsPolygonAttributeName(id, name);
55
+ const { colorMap } =
56
+ meshPolygonsPolygonAttributeStyle.meshPolygonsPolygonAttributeStoredConfig(id, name);
57
+ return Promise.all([
58
+ meshPolygonsPolygonAttributeStyle.setMeshPolygonsPolygonAttributeName(id, name),
59
+ meshPolygonsPolygonAttributeStyle.setMeshPolygonsPolygonAttributeColorMap(id, colorMap),
60
+ ]);
46
61
  }
47
62
  throw new Error(`Unknown mesh polygons coloring type: ${type}`);
48
63
  }
@@ -38,14 +38,27 @@ export function useMeshPolyhedraStyle() {
38
38
  }
39
39
  if (type === "vertex") {
40
40
  const name = meshPolyhedraVertexAttributeStyle.meshPolyhedraVertexAttributeName(id);
41
- return meshPolyhedraVertexAttributeStyle.setMeshPolyhedraVertexAttributeName(id, name);
41
+ const { colorMap } =
42
+ meshPolyhedraVertexAttributeStyle.meshPolyhedraVertexAttributeStoredConfig(id, name);
43
+ return Promise.all([
44
+ meshPolyhedraVertexAttributeStyle.setMeshPolyhedraVertexAttributeName(id, name),
45
+ meshPolyhedraVertexAttributeStyle.setMeshPolyhedraVertexAttributeColorMap(id, colorMap),
46
+ ]);
42
47
  }
43
48
  if (type === "polyhedron") {
44
49
  const name = meshPolyhedraPolyhedronAttributeStyle.meshPolyhedraPolyhedronAttributeName(id);
45
- return meshPolyhedraPolyhedronAttributeStyle.setMeshPolyhedraPolyhedronAttributeName(
46
- id,
47
- name,
48
- );
50
+ const { colorMap } =
51
+ meshPolyhedraPolyhedronAttributeStyle.meshPolyhedraPolyhedronAttributeStoredConfig(
52
+ id,
53
+ name,
54
+ );
55
+ return Promise.all([
56
+ meshPolyhedraPolyhedronAttributeStyle.setMeshPolyhedraPolyhedronAttributeName(id, name),
57
+ meshPolyhedraPolyhedronAttributeStyle.setMeshPolyhedraPolyhedronAttributeColorMap(
58
+ id,
59
+ colorMap,
60
+ ),
61
+ ]);
49
62
  }
50
63
  throw new Error(`Unknown mesh polyhedra coloring type: ${type}`);
51
64
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@geode/opengeodeweb-front",
3
- "version": "10.26.4-rc.1",
3
+ "version": "10.27.0-rc.2",
4
4
  "description": "OpenSource Vue/Nuxt/Pinia/Vuetify framework for web applications",
5
5
  "homepage": "https://github.com/Geode-solutions/OpenGeodeWeb-Front",
6
6
  "bugs": {
@@ -28,7 +28,7 @@ const CLIPPING_RANGE1 = 0.1;
28
28
  const CLIPPING_RANGE2 = 1000;
29
29
  const CLIPPING_RANGE = [CLIPPING_RANGE1, CLIPPING_RANGE2];
30
30
  const POINT_SIZE = 2;
31
- const VIEWER_CALL_COUNT = 2;
31
+ const VIEWER_CALL_COUNT = 1;
32
32
 
33
33
  // Snapshot
34
34
  const snapshotMock = {
@@ -104,6 +104,7 @@ const dataStoreMock = {
104
104
  clear: vi.fn(),
105
105
  registerObject: vi.fn().mockResolvedValue(),
106
106
  addItem: vi.fn().mockResolvedValue(),
107
+ importStores: vi.fn().mockResolvedValue(),
107
108
  };
108
109
  const dataStyleStoreMock = {
109
110
  importStores: vi.fn().mockResolvedValue(),
@@ -111,6 +112,10 @@ const dataStyleStoreMock = {
111
112
  addDataStyle: vi.fn().mockResolvedValue(),
112
113
  applyDefaultStyle: vi.fn().mockResolvedValue(),
113
114
  };
115
+ const feedbackStoreMock = {
116
+ add_success: vi.fn(),
117
+ add_error: vi.fn(),
118
+ };
114
119
 
115
120
  const viewer_call_mock_fn = vi.fn().mockResolvedValue();
116
121
 
@@ -176,6 +181,9 @@ vi.mock(import("@ogw_front/stores/hybrid_viewer"), () => ({
176
181
  vi.mock(import("@ogw_front/stores/back"), () => ({
177
182
  useBackStore: () => backStoreMock,
178
183
  }));
184
+ vi.mock(import("@ogw_front/stores/feedback"), () => ({
185
+ useFeedbackStore: () => feedbackStoreMock,
186
+ }));
179
187
  vi.mock(import("@ogw_front/stores/app"), () => ({
180
188
  useAppStore: () => ({
181
189
  exportStores: vi.fn(() => ({ projectName: "mockedProject" })),
@@ -202,6 +210,7 @@ function verifyViewerCalls() {
202
210
 
203
211
  function verifyStoreImports() {
204
212
  expect(treeviewStoreMock.importStores).toHaveBeenCalledWith(snapshotMock.treeview);
213
+ expect(dataStoreMock.importStores).toHaveBeenCalledWith(snapshotMock.data);
205
214
  expect(hybridViewerStoreMock.initHybridViewer).toHaveBeenCalledWith();
206
215
  expect(hybridViewerStoreMock.importStores).toHaveBeenCalledWith(snapshotMock.hybridViewer);
207
216
  expect(hybridViewerStoreMock.setZScaling).toHaveBeenCalledWith(Z_SCALE);
@@ -220,6 +229,7 @@ function verifyRemaining() {
220
229
  expect(dataStyleStoreMock.addDataStyle).toHaveBeenCalledWith("abc123", "PointSet2D");
221
230
  expect(dataStyleStoreMock.applyDefaultStyle).toHaveBeenCalledWith("abc123");
222
231
  expect(hybridViewerStoreMock.remoteRender).toHaveBeenCalledWith();
232
+ expect(feedbackStoreMock.add_success).toHaveBeenCalledWith("Project imported successfully");
223
233
  }
224
234
 
225
235
  describe("projectManager composable (compact)", () => {
@@ -231,6 +241,7 @@ describe("projectManager composable (compact)", () => {
231
241
  dataStoreMock,
232
242
  dataStyleStoreMock,
233
243
  hybridViewerStoreMock,
244
+ feedbackStoreMock,
234
245
  ];
235
246
  for (const store of storesList) {
236
247
  const values = Object.values(store);
@@ -249,6 +260,7 @@ describe("projectManager composable (compact)", () => {
249
260
  await exportProject();
250
261
 
251
262
  expect(fileDownload).toHaveBeenCalledWith({ snapshot: snapshotMock }, "project.vease");
263
+ expect(feedbackStoreMock.add_success).toHaveBeenCalledWith("Project exported successfully");
252
264
  });
253
265
 
254
266
  test("importProjectFile with snapshot - Viewer and Stores", async () => {