@geode/opengeodeweb-front 9.12.1 → 9.12.2-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.
Files changed (40) hide show
  1. package/components/Viewer/TreeComponent.vue +28 -8
  2. package/internal_stores/data_style_state.js +6 -1
  3. package/internal_stores/mesh/edges.js +18 -8
  4. package/internal_stores/mesh/index.js +21 -20
  5. package/internal_stores/mesh/points.js +22 -9
  6. package/internal_stores/mesh/polygons.js +26 -8
  7. package/internal_stores/mesh/polyhedra.js +19 -8
  8. package/internal_stores/model/blocks.js +71 -31
  9. package/internal_stores/model/corners.js +69 -32
  10. package/internal_stores/model/edges.js +16 -10
  11. package/internal_stores/model/index.js +117 -77
  12. package/internal_stores/model/lines.js +53 -36
  13. package/internal_stores/model/points.js +23 -16
  14. package/internal_stores/model/surfaces.js +63 -29
  15. package/package.json +3 -3
  16. package/stores/data_base.js +18 -32
  17. package/stores/data_style.js +18 -30
  18. package/stores/hybrid_viewer.js +12 -6
  19. package/stores/treeview.js +2 -3
  20. package/tests/integration/data/uploads/test.og_brep +0 -0
  21. package/tests/integration/microservices/back/requirements.txt +1 -1
  22. package/tests/integration/microservices/viewer/requirements.txt +1 -1
  23. package/tests/integration/setup.js +22 -41
  24. package/tests/integration/stores/data_style/mesh/edges.nuxt.test.js +27 -13
  25. package/tests/integration/stores/data_style/mesh/index.nuxt.test.js +66 -0
  26. package/tests/integration/stores/data_style/mesh/points.nuxt.test.js +47 -13
  27. package/tests/integration/stores/data_style/mesh/polygons.nuxt.test.js +27 -13
  28. package/tests/integration/stores/data_style/mesh/polyhedra.nuxt.test.js +26 -13
  29. package/tests/integration/stores/data_style/model/blocks.nuxt.test.js +92 -0
  30. package/tests/integration/stores/data_style/model/corners.nuxt.test.js +92 -0
  31. package/tests/integration/stores/data_style/model/edges.nuxt.test.js +57 -0
  32. package/tests/integration/stores/data_style/model/index.nuxt.test.js +57 -0
  33. package/tests/integration/stores/data_style/model/lines.nuxt.test.js +83 -0
  34. package/tests/integration/stores/data_style/model/points.nuxt.test.js +73 -0
  35. package/tests/integration/stores/data_style/model/surfaces.nuxt.test.js +96 -0
  36. package/tests/vitest.config.js +2 -1
  37. package/utils/default_styles.js +19 -7
  38. package/utils/file_import_workflow.js +82 -0
  39. package/utils/local.js +51 -15
  40. package/tests/integration/utils.js +0 -35
@@ -0,0 +1,73 @@
1
+ // Third party imports
2
+ import { afterEach, beforeEach, describe, expect, test, vi } from "vitest"
3
+ import viewer_schemas from "@geode/opengeodeweb-viewer/opengeodeweb_viewer_schemas.json" with { type: "json" }
4
+
5
+ // Local imports
6
+ import Status from "~/utils/status"
7
+ import * as composables from "~/composables/viewer_call"
8
+ import { useDataStyleStore } from "~/stores/data_style"
9
+ import { useViewerStore } from "~/stores/viewer"
10
+ import { delete_folder_recursive, kill_back, kill_viewer } from "~/utils/local"
11
+ import { setupIntegrationTests } from "../../../setup.js"
12
+
13
+ // Local constants
14
+ const model_points_schemas = viewer_schemas.opengeodeweb_viewer.model.points
15
+ const file_name = "test.og_brep"
16
+ const geode_object = "BRep"
17
+
18
+ let id, back_port, viewer_port, project_folder_path
19
+
20
+ beforeEach(async () => {
21
+ ;({ id, back_port, viewer_port, project_folder_path } =
22
+ await setupIntegrationTests(file_name, geode_object))
23
+ }, 20000)
24
+
25
+ afterEach(async () => {
26
+ console.log("afterEach model points kill", back_port, viewer_port)
27
+ await Promise.all([kill_back(back_port), kill_viewer(viewer_port)])
28
+ delete_folder_recursive(project_folder_path)
29
+ })
30
+
31
+ describe("Model points", () => {
32
+ describe("Points visibility", () => {
33
+ test("Visibility true", async () => {
34
+ const dataStyleStore = useDataStyleStore()
35
+ const viewerStore = useViewerStore()
36
+ const visibility = true
37
+ const spy = vi.spyOn(composables, "viewer_call")
38
+ await dataStyleStore.setModelPointsVisibility(id, visibility)
39
+ expect(spy).toHaveBeenCalledWith(
40
+ {
41
+ schema: model_points_schemas.visibility,
42
+ params: { id, visibility },
43
+ },
44
+ {
45
+ response_function: expect.any(Function),
46
+ },
47
+ )
48
+ expect(dataStyleStore.modelPointsVisibility(id)).toBe(visibility)
49
+ expect(viewerStore.status).toBe(Status.CONNECTED)
50
+ })
51
+ })
52
+
53
+ describe("Points size", () => {
54
+ test("Size 20", async () => {
55
+ const dataStyleStore = useDataStyleStore()
56
+ const viewerStore = useViewerStore()
57
+ const size = 20
58
+ const spy = vi.spyOn(composables, "viewer_call")
59
+ await dataStyleStore.setModelPointsSize(id, size)
60
+ expect(spy).toHaveBeenCalledWith(
61
+ {
62
+ schema: model_points_schemas.size,
63
+ params: { id, size },
64
+ },
65
+ {
66
+ response_function: expect.any(Function),
67
+ },
68
+ )
69
+ expect(dataStyleStore.modelPointsSize(id)).toBe(size)
70
+ expect(viewerStore.status).toBe(Status.CONNECTED)
71
+ })
72
+ })
73
+ })
@@ -0,0 +1,96 @@
1
+ // Third party imports
2
+ import { afterEach, beforeEach, describe, expect, test, vi } from "vitest"
3
+ import viewer_schemas from "@geode/opengeodeweb-viewer/opengeodeweb_viewer_schemas.json" with { type: "json" }
4
+
5
+ // Local imports
6
+ import Status from "~/utils/status"
7
+ import * as composables from "~/composables/viewer_call"
8
+ import { useDataStyleStore } from "~/stores/data_style"
9
+ import { useViewerStore } from "~/stores/viewer"
10
+ import { delete_folder_recursive, kill_back, kill_viewer } from "~/utils/local"
11
+ import { setupIntegrationTests } from "../../../setup.js"
12
+
13
+ // Local constants
14
+ const model_surfaces_schemas = viewer_schemas.opengeodeweb_viewer.model.surfaces
15
+ const file_name = "test.og_brep"
16
+ const geode_object = "BRep"
17
+
18
+ let id, back_port, viewer_port, project_folder_path
19
+
20
+ beforeEach(async () => {
21
+ ;({ id, back_port, viewer_port, project_folder_path } =
22
+ await setupIntegrationTests(file_name, geode_object))
23
+ }, 20000)
24
+
25
+ afterEach(async () => {
26
+ console.log(
27
+ "afterEach model surfaces kill",
28
+ back_port,
29
+ viewer_port,
30
+ project_folder_path,
31
+ )
32
+ await Promise.all([kill_back(back_port), kill_viewer(viewer_port)])
33
+ delete_folder_recursive(project_folder_path)
34
+ })
35
+
36
+ describe("Model surfaces", () => {
37
+ describe("Surfaces visibility", () => {
38
+ test("Visibility true", async () => {
39
+ const dataStyleStore = useDataStyleStore()
40
+ const viewerStore = useViewerStore()
41
+ const dataBaseStore = useDataBaseStore()
42
+ const surface_ids = dataBaseStore.getSurfacesUuids(id)
43
+ const surface_flat_indexes = dataBaseStore.getFlatIndexes(id, surface_ids)
44
+ const visibility = true
45
+ const spy = vi.spyOn(composables, "viewer_call")
46
+ await dataStyleStore.setModelSurfacesVisibility(
47
+ id,
48
+ surface_ids,
49
+ visibility,
50
+ )
51
+ expect(spy).toHaveBeenCalledWith(
52
+ {
53
+ schema: model_surfaces_schemas.visibility,
54
+ params: { id, block_ids: surface_flat_indexes, visibility },
55
+ },
56
+ {
57
+ response_function: expect.any(Function),
58
+ },
59
+ )
60
+ for (const surface_id of surface_ids) {
61
+ expect(dataStyleStore.modelSurfaceVisibility(id, surface_id)).toBe(
62
+ visibility,
63
+ )
64
+ }
65
+ expect(viewerStore.status).toBe(Status.CONNECTED)
66
+ })
67
+ })
68
+
69
+ describe("Surfaces color", () => {
70
+ test("Color red", async () => {
71
+ const dataStyleStore = useDataStyleStore()
72
+ const viewerStore = useViewerStore()
73
+ const dataBaseStore = useDataBaseStore()
74
+ const surface_ids = dataBaseStore.getSurfacesUuids(id)
75
+ const surface_flat_indexes = dataBaseStore.getFlatIndexes(id, surface_ids)
76
+ const color = { r: 255, g: 0, b: 0 }
77
+ const spy = vi.spyOn(composables, "viewer_call")
78
+ await dataStyleStore.setModelSurfacesColor(id, surface_ids, color)
79
+ expect(spy).toHaveBeenCalledWith(
80
+ {
81
+ schema: model_surfaces_schemas.color,
82
+ params: { id, block_ids: surface_flat_indexes, color },
83
+ },
84
+ {
85
+ response_function: expect.any(Function),
86
+ },
87
+ )
88
+ for (const surface_id of surface_ids) {
89
+ expect(dataStyleStore.modelSurfaceColor(id, surface_id)).toStrictEqual(
90
+ color,
91
+ )
92
+ }
93
+ expect(viewerStore.status).toBe(Status.CONNECTED)
94
+ })
95
+ })
96
+ })
@@ -20,8 +20,9 @@ export default defineConfig({
20
20
  test: {
21
21
  name: "integration",
22
22
  include: ["tests/integration/**/*.test.js"],
23
- setupFiles: ["tests/integration/setup.js"],
24
23
  environment: "nuxt",
24
+ fileParallelism: false,
25
+ setupFiles: ["tests/integration/setup.js"],
25
26
  server: {
26
27
  deps: {
27
28
  inline: ["vuetify"],
@@ -12,10 +12,13 @@ const polygons_defaultColor = { r: 255, g: 255, b: 255 }
12
12
  const polyhedra_defaultColor = { r: 255, g: 255, b: 255 }
13
13
 
14
14
  const corners_defaultVisibility = true
15
+ const corners_defaultColor = { r: 20, g: 20, b: 20 }
15
16
  const lines_defaultVisibility = true
17
+ const lines_defaultColor = { r: 20, g: 20, b: 20 }
16
18
  const surfaces_defaultVisibility = true
19
+ const surfaces_defaultColor = { r: 20, g: 20, b: 20 }
17
20
  const blocks_defaultVisibility = true
18
- const lines_defaultColor = { r: 20, g: 20, b: 20 }
21
+ const blocks_defaultColor = { r: 20, g: 20, b: 20 }
19
22
 
20
23
  // Mesh functions
21
24
  const meshPointsDefaultStyle = (
@@ -115,8 +118,11 @@ const solid_defaultStyle = () => {
115
118
  }
116
119
 
117
120
  // Model functions
118
- const modelCornersDefaultStyle = (visibility = corners_defaultVisibility) => {
119
- return { visibility }
121
+ const modelCornersDefaultStyle = (
122
+ visibility = corners_defaultVisibility,
123
+ color = corners_defaultColor,
124
+ ) => {
125
+ return { visibility, color }
120
126
  }
121
127
  const modelLinesDefaultStyle = (
122
128
  visibility = lines_defaultVisibility,
@@ -124,11 +130,17 @@ const modelLinesDefaultStyle = (
124
130
  ) => {
125
131
  return { visibility, color }
126
132
  }
127
- const modelSurfacesDefaultStyle = (visibility = surfaces_defaultVisibility) => {
128
- return { visibility }
133
+ const modelSurfacesDefaultStyle = (
134
+ visibility = surfaces_defaultVisibility,
135
+ color = surfaces_defaultColor,
136
+ ) => {
137
+ return { visibility, color }
129
138
  }
130
- const modelBlocksDefaultStyle = (visibility = blocks_defaultVisibility) => {
131
- return { visibility }
139
+ const modelBlocksDefaultStyle = (
140
+ visibility = blocks_defaultVisibility,
141
+ color = blocks_defaultColor,
142
+ ) => {
143
+ return { visibility, color }
132
144
  }
133
145
  const modelPointsDefaultStyle = (
134
146
  visibility = points_defaultVisibility,
@@ -0,0 +1,82 @@
1
+ // Third party imports
2
+ import back_schemas from "@geode/opengeodeweb-back/opengeodeweb_back_schemas.json"
3
+ import { useHybridViewerStore } from "../stores/hybrid_viewer"
4
+
5
+ // Local imports
6
+
7
+ async function importWorkflow(files) {
8
+ console.log("importWorkflow", { files })
9
+ const promise_array = []
10
+ for (const file of files) {
11
+ const { filename, geode_object } = file
12
+ console.log({ filename }, { geode_object })
13
+ promise_array.push(importFile(filename, geode_object))
14
+ }
15
+ return Promise.all(promise_array)
16
+ }
17
+
18
+ async function importFile(filename, geode_object) {
19
+ const dataBaseStore = useDataBaseStore()
20
+ const dataStyleStore = useDataStyleStore()
21
+ const hybridViewerStore = useHybridViewerStore()
22
+ const treeviewStore = useTreeviewStore()
23
+ const { data } = await api_fetch({
24
+ schema: back_schemas.opengeodeweb_back.save_viewable_file,
25
+ params: {
26
+ input_geode_object: geode_object,
27
+ filename: filename,
28
+ },
29
+ })
30
+
31
+ const {
32
+ id,
33
+ native_file_name,
34
+ viewable_file_name,
35
+ name,
36
+ object_type,
37
+ binary_light_viewable,
38
+ } = data._value
39
+
40
+ console.log("data._value", data._value)
41
+
42
+ console.log("data._value.id", data._value.id)
43
+ await dataBaseStore.registerObject(data._value.id)
44
+ console.log("after dataBaseStore.registerObject")
45
+ await dataBaseStore.addItem(id, {
46
+ object_type: object_type,
47
+ geode_object: geode_object,
48
+ native_filename: native_file_name,
49
+ viewable_filename: viewable_file_name,
50
+ displayed_name: name,
51
+ vtk_js: {
52
+ binary_light_viewable,
53
+ },
54
+ })
55
+
56
+ await treeviewStore.addItem(geode_object, name, id, object_type)
57
+
58
+ console.log("after treeviewStore.addItem")
59
+
60
+ await hybridViewerStore.addItem(id)
61
+ console.log("after dataBaseStore.addItem")
62
+
63
+ await dataStyleStore.addDataStyle(
64
+ data._value.id,
65
+ data._value.geode_object,
66
+ data._value.object_type,
67
+ )
68
+ console.log("after dataStyleStore.addDataStyle")
69
+ if (data._value.object_type === "model") {
70
+ await Promise.all([
71
+ dataBaseStore.fetchMeshComponents(id),
72
+ dataBaseStore.fetchUuidToFlatIndexDict(id),
73
+ ])
74
+ console.log("after dataBaseStore.fetchMeshComponents")
75
+ console.log("after dataBaseStore.fetchUuidToFlatIndexDict")
76
+ }
77
+ await dataStyleStore.applyDefaultStyle(id)
78
+ console.log("after dataStyleStore.applyDefaultStyle")
79
+ return data._value.id
80
+ }
81
+
82
+ export { importFile, importWorkflow }
package/utils/local.js CHANGED
@@ -57,8 +57,17 @@ function get_available_port() {
57
57
  })
58
58
  }
59
59
 
60
+ function commandExistsSync(executable_name) {
61
+ const envPath = process.env.PATH || ""
62
+ return envPath.split(path.delimiter).some((dir) => {
63
+ const filePath = path.join(dir, executable_name)
64
+ return fs.existsSync(filePath) && fs.statSync(filePath).isFile()
65
+ })
66
+ }
67
+
60
68
  async function run_script(
61
- command,
69
+ executable_name,
70
+ executable_path,
62
71
  args,
63
72
  expected_response,
64
73
  timeout_seconds = 30,
@@ -68,6 +77,10 @@ async function run_script(
68
77
  reject("Timed out after " + timeout_seconds + " seconds")
69
78
  }, timeout_seconds * 1000)
70
79
 
80
+ const command = commandExistsSync(executable_name)
81
+ ? executable_name
82
+ : path.join(executable_path, executable_name)
83
+ console.log("run_script", command, args)
71
84
  const child = child_process.spawn(command, args, {
72
85
  encoding: "utf8",
73
86
  shell: true,
@@ -109,7 +122,8 @@ async function run_script(
109
122
  }
110
123
 
111
124
  async function run_back(
112
- command,
125
+ executable_name,
126
+ executable_path,
113
127
  args = {
114
128
  project_folder_path,
115
129
  upload_folder_path: undefined,
@@ -128,13 +142,22 @@ async function run_back(
128
142
  "--allowed_origin http://localhost:*",
129
143
  "--timeout " + 0,
130
144
  ]
131
- console.log("run_back", command, back_args)
132
- await run_script(command, back_args, "Serving Flask app")
145
+ console.log("run_back", executable_name, executable_path, back_args)
146
+ await run_script(
147
+ executable_name,
148
+ executable_path,
149
+ back_args,
150
+ "Serving Flask app",
151
+ )
133
152
  resolve(port)
134
153
  })
135
154
  }
136
155
 
137
- async function run_viewer(command, args = { project_folder_path }) {
156
+ async function run_viewer(
157
+ executable_name,
158
+ executable_path,
159
+ args = { project_folder_path },
160
+ ) {
138
161
  return new Promise(async (resolve, reject) => {
139
162
  const port = await get_available_port()
140
163
  const viewer_args = [
@@ -142,8 +165,13 @@ async function run_viewer(command, args = { project_folder_path }) {
142
165
  "--data_folder_path " + args.project_folder_path,
143
166
  "--timeout " + 0,
144
167
  ]
145
- console.log("run_viewer", command, viewer_args)
146
- await run_script(command, viewer_args, "Starting factory")
168
+ console.log("run_viewer", executable_name, executable_path, viewer_args)
169
+ await run_script(
170
+ executable_name,
171
+ executable_path,
172
+ viewer_args,
173
+ "Starting factory",
174
+ )
147
175
  resolve(port)
148
176
  })
149
177
  }
@@ -224,19 +252,27 @@ function kill_viewer(viewer_port) {
224
252
  async function run_browser(
225
253
  script_name,
226
254
  microservices_options = {
227
- back: { command, args: { project_folder_path } },
228
- viewer: { command, args: { project_folder_path } },
255
+ back: { executable_name, executable_path, args: { project_folder_path } },
256
+ viewer: { executable_name, executable_path, args: { project_folder_path } },
229
257
  },
230
258
  ) {
231
259
  console.log("microservices_options", microservices_options)
232
- const back_promise = run_back(microservices_options.back.command, {
233
- ...microservices_options.back.args,
234
- })
260
+ const back_promise = run_back(
261
+ microservices_options.back.executable_name,
262
+ microservices_options.back.executable_path,
263
+ {
264
+ ...microservices_options.back.args,
265
+ },
266
+ )
235
267
  console.log("back_promise", back_promise)
236
268
 
237
- const viewer_promise = run_viewer(microservices_options.viewer.command, {
238
- ...microservices_options.viewer.args,
239
- })
269
+ const viewer_promise = run_viewer(
270
+ microservices_options.viewer.executable_name,
271
+ microservices_options.viewer.executable_path,
272
+ {
273
+ ...microservices_options.viewer.args,
274
+ },
275
+ )
240
276
  console.log("viewer_promise", viewer_promise)
241
277
 
242
278
  const [back_port, viewer_port] = await Promise.all([
@@ -1,35 +0,0 @@
1
- // Node.js imports
2
- import fs from "fs"
3
- import path from "path"
4
-
5
- function getCurrentFolders(dataFolderPath) {
6
- if (!fs.existsSync(dataFolderPath)) {
7
- return new Set()
8
- }
9
- const entries = fs.readdirSync(dataFolderPath)
10
- const folders = new Set()
11
- for (const entry of entries) {
12
- const entryPath = path.join(dataFolderPath, entry)
13
- if (fs.statSync(entryPath).isDirectory()) {
14
- folders.add(entry)
15
- }
16
- }
17
- return folders
18
- }
19
-
20
- function cleanupCreatedFolders(dataFolderPath, foldersBeforeTests) {
21
- if (!fs.existsSync(dataFolderPath)) {
22
- return
23
- }
24
- const currentFolders = getCurrentFolders(dataFolderPath)
25
- console.log("getCurrentFolders currentFolders", currentFolders)
26
- for (const folder of currentFolders) {
27
- if (!foldersBeforeTests.has(folder)) {
28
- const folderPath = path.join(dataFolderPath, folder)
29
- fs.rmSync(folderPath, { recursive: true, force: true })
30
- console.log(`Deleted folder: ${folderPath}`)
31
- }
32
- }
33
- }
34
-
35
- export { getCurrentFolders, cleanupCreatedFolders }