@geode/opengeodeweb-front 10.29.1 → 10.30.0-rc.10

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 (82) hide show
  1. package/app/components/ClippingPlaneCard.vue +112 -0
  2. package/app/components/ClippingPlanes.vue +238 -0
  3. package/app/components/Launcher.vue +1 -1
  4. package/app/components/ObjectSelector.vue +26 -76
  5. package/app/components/ToolPanel.vue +3 -2
  6. package/app/components/ViewToolbar.vue +12 -0
  7. package/app/components/Viewer/ObjectTree/Base/TreeRow.vue +58 -20
  8. package/app/components/Viewer/ObjectTree/Views/GlobalObjects.vue +42 -40
  9. package/app/composables/clipping_planes_widget.js +262 -0
  10. package/app/composables/hover_highlight.js +6 -0
  11. package/app/composables/project_manager.js +14 -11
  12. package/app/composables/use_overlapping_picker.js +15 -2
  13. package/app/stores/app.js +56 -11
  14. package/app/stores/back.js +10 -27
  15. package/app/stores/cloud.js +7 -1
  16. package/app/stores/data.js +32 -1
  17. package/app/stores/data_style.js +11 -0
  18. package/app/stores/hybrid_viewer.js +13 -5
  19. package/app/stores/infra.js +2 -7
  20. package/app/stores/viewer.js +9 -27
  21. package/app/utils/clipping_planes.js +110 -0
  22. package/app/utils/extension.js +30 -3
  23. package/app/utils/import_workflow.js +9 -12
  24. package/app/utils/log.js +18 -0
  25. package/app/utils/stores.js +32 -0
  26. package/internal/stores/hybrid_viewer.js +8 -63
  27. package/internal/stores/hybrid_viewer_brightness.js +62 -0
  28. package/internal/utils/api_fetch.js +27 -53
  29. package/internal/utils/upload_file.js +36 -29
  30. package/internal/utils/viewer_call.js +7 -2
  31. package/nuxt.config.js +2 -1
  32. package/package.json +4 -3
  33. package/server/api/local/{project_folder_path.post.js → app/project_folder_path.post.js} +1 -1
  34. package/server/api/local/{run_back.post.js → app/run_back.post.js} +1 -1
  35. package/server/api/local/{run_viewer.post.js → app/run_viewer.post.js} +1 -1
  36. package/server/api/{microservice → local}/extensions/upload.put.js +16 -37
  37. package/server/api/microservice/app/set_app_base_url.post.js +25 -0
  38. package/server/api/microservice/app/set_back_base_url.post.js +22 -0
  39. package/server/api/microservice/app/set_viewer_base_url.post.js +22 -0
  40. package/server/api/microservice/extensions/download.post.js +32 -0
  41. package/server/api/microservice/extensions/kill.post.js +3 -3
  42. package/server/api/microservice/extensions/run.post.js +5 -4
  43. package/server/api/serverless/{run_cloud.js → run_cloud.post.js} +1 -1
  44. package/{app/utils/config.js → server/utils/app_config.js} +28 -3
  45. package/{app/utils/local → server/utils}/path.js +1 -1
  46. package/{app/utils/local → server/utils}/scripts.js +5 -2
  47. package/server/utils/server_config.js +32 -0
  48. package/shared/scripts.js +56 -0
  49. package/shared/utils/fetch_raw.js +61 -0
  50. package/shared/utils/fetch_schema.js +46 -0
  51. package/shared/utils/file.js +16 -0
  52. package/shared/utils/response_handlers/load.js +74 -0
  53. package/tests/integration/setup.js +3 -3
  54. package/tests/integration/stores/data_style/mesh/cells.nuxt.test.js +1 -1
  55. package/tests/integration/stores/data_style/mesh/edges.nuxt.test.js +1 -1
  56. package/tests/integration/stores/data_style/mesh/index.nuxt.test.js +1 -1
  57. package/tests/integration/stores/data_style/mesh/points.nuxt.test.js +1 -1
  58. package/tests/integration/stores/data_style/mesh/polygons.nuxt.test.js +1 -1
  59. package/tests/integration/stores/data_style/mesh/polyhedra.nuxt.test.js +1 -1
  60. package/tests/integration/stores/data_style/model/blocks.nuxt.test.js +1 -1
  61. package/tests/integration/stores/data_style/model/corners.nuxt.test.js +1 -1
  62. package/tests/integration/stores/data_style/model/edges.nuxt.test.js +1 -1
  63. package/tests/integration/stores/data_style/model/index.nuxt.test.js +1 -1
  64. package/tests/integration/stores/data_style/model/lines.nuxt.test.js +1 -1
  65. package/tests/integration/stores/data_style/model/points.nuxt.test.js +1 -1
  66. package/tests/integration/stores/data_style/model/surfaces.nuxt.test.js +1 -1
  67. package/tests/integration/stores/viewer.nuxt.test.js +1 -1
  68. package/tests/unit/composables/project_manager.nuxt.test.js +14 -2
  69. package/tests/unit/composables/upload_file.nuxt.test.js +2 -2
  70. package/tests/unit/stores/back.nuxt.test.js +1 -1
  71. package/tests/unit/stores/cloud.nuxt.test.js +22 -20
  72. package/tests/unit/stores/data.nuxt.test.js +35 -0
  73. package/tests/unit/stores/infra.nuxt.test.js +13 -6
  74. package/tests/unit/stores/viewer.nuxt.test.js +1 -1
  75. package/tests/unit/utils/validate_schema.nuxt.test.js +1 -1
  76. package/tests/vitest.config.js +7 -5
  77. /package/server/api/local/{kill.post.js → app/kill.post.js} +0 -0
  78. /package/{app/utils/local → server/utils}/cleanup.js +0 -0
  79. /package/{app/utils/local → server/utils}/microservices.js +0 -0
  80. /package/{app → server}/utils/server.js +0 -0
  81. /package/{app/utils/local → shared}/app_mode.js +0 -0
  82. /package/{app → shared}/utils/validate_schema.js +0 -0
@@ -1,4 +1,6 @@
1
1
  import { Status } from "@ogw_front/utils/status";
2
+ import { fetchSchema } from "@ogw_shared/utils/fetch_schema";
3
+ import { setAppBaseUrl } from "@ogw_shared/scripts";
2
4
  import { useAppStore } from "./app";
3
5
  import { useFeedbackStore } from "./feedback";
4
6
  import { useInfraStore } from "./infra";
@@ -25,7 +27,7 @@ export const useCloudStore = defineStore("cloud", {
25
27
  console.log("[CLOUD] params", params);
26
28
  const appStore = useAppStore();
27
29
  const feedbackStore = useFeedbackStore();
28
- return appStore.request(
30
+ return fetchSchema(
29
31
  { schema, params },
30
32
  {
31
33
  request_error_function: () => {
@@ -40,6 +42,10 @@ export const useCloudStore = defineStore("cloud", {
40
42
  infraStore.$patch({
41
43
  domain_name: response.url,
42
44
  });
45
+ setAppBaseUrl(appStore.base_url);
46
+ appStore.$patch({
47
+ projectFolderPath: "/project",
48
+ });
43
49
  },
44
50
  response_error_function: () => {
45
51
  feedbackStore.$patch({ server_error: true });
@@ -11,6 +11,33 @@ import { useViewerStore } from "@ogw_front/stores/viewer";
11
11
 
12
12
  const viewer_generic_schemas = viewer_schemas.opengeodeweb_viewer.generic;
13
13
 
14
+ function checkItemViewable(item) {
15
+ if (!item || typeof item !== "object") {
16
+ return false;
17
+ }
18
+ if (item.is_viewable !== undefined) {
19
+ return Boolean(item.is_viewable);
20
+ }
21
+ if (item.binary_light_viewable !== undefined) {
22
+ return item.binary_light_viewable !== "not_viewable";
23
+ }
24
+ if (
25
+ item.geode_object_type === "HorizonStack3D" ||
26
+ item.id === "HorizonStack3D" ||
27
+ item.title === "HorizonStack3D"
28
+ ) {
29
+ return false;
30
+ }
31
+ return true;
32
+ }
33
+
34
+ function isItemViewable(itemOrId) {
35
+ if (typeof itemOrId === "string") {
36
+ return database.data.get(itemOrId).then(checkItemViewable);
37
+ }
38
+ return checkItemViewable(itemOrId);
39
+ }
40
+
14
41
  // oxlint-disable-next-line max-lines-per-function, max-statements
15
42
  export const useDataStore = defineStore("data", () => {
16
43
  const viewerStore = useViewerStore();
@@ -93,8 +120,11 @@ export const useDataStore = defineStore("data", () => {
93
120
  geode_object_type: new_item.geode_object_type,
94
121
  visible: true,
95
122
  created_at: new Date().toISOString(),
96
- binary_light_viewable: new_item.binary_light_viewable,
123
+ is_viewable: new_item.is_viewable,
97
124
  };
125
+ if (new_item.binary_light_viewable !== undefined && new_item.binary_light_viewable !== null) {
126
+ itemData.binary_light_viewable = new_item.binary_light_viewable;
127
+ }
98
128
  return data_db.put(itemData);
99
129
  }
100
130
 
@@ -213,6 +243,7 @@ export const useDataStore = defineStore("data", () => {
213
243
  item,
214
244
  allItems,
215
245
  refItem,
246
+ isItemViewable,
216
247
  meshComponentType,
217
248
  registerObject,
218
249
  deregisterObject,
@@ -21,6 +21,10 @@ export const useDataStyleStore = defineStore("dataStyle", () => {
21
21
 
22
22
  async function setVisibility(id, visibility) {
23
23
  const item = await dataStore.item(id);
24
+ if (!(await dataStore.isItemViewable(item))) {
25
+ return dataStyleState.mutateStyle(id, { visibility });
26
+ }
27
+
24
28
  const { viewer_type } = item;
25
29
 
26
30
  if (viewer_type === "mesh") {
@@ -34,6 +38,10 @@ export const useDataStyleStore = defineStore("dataStyle", () => {
34
38
 
35
39
  async function applyDefaultStyle(id) {
36
40
  const item = await dataStore.item(id);
41
+ if (!(await dataStore.isItemViewable(item))) {
42
+ throw new Error(`applyDefaultStyle called for non-viewable item: ${id}`);
43
+ }
44
+
37
45
  const { viewer_type } = item;
38
46
 
39
47
  if (viewer_type === "mesh") {
@@ -81,6 +89,9 @@ export const useDataStyleStore = defineStore("dataStyle", () => {
81
89
  const ids = Object.keys(dataStyleState.styles.value);
82
90
  const promises = ids.map(async (id) => {
83
91
  const meta = await dataStore.item(id);
92
+ if (!(await dataStore.isItemViewable(meta))) {
93
+ return;
94
+ }
84
95
  const viewerType = meta.viewer_type;
85
96
  if (viewerType === "mesh") {
86
97
  return meshStyleStore.applyMeshStyle(id);
@@ -12,7 +12,10 @@ import {
12
12
  performSyncRemoteCamera,
13
13
  } from "@ogw_internal/stores/hybrid_viewer_camera";
14
14
  import {
15
- computeAverageBrightness,
15
+ createClearHoverData,
16
+ createHoverHighlight,
17
+ } from "@ogw_internal/stores/hybrid_viewer_highlight";
18
+ import {
16
19
  performAddItem,
17
20
  performClear,
18
21
  performClearHoverHighlight,
@@ -22,10 +25,7 @@ import {
22
25
  performSetVisibility,
23
26
  performSetZScaling,
24
27
  } from "@ogw_internal/stores/hybrid_viewer";
25
- import {
26
- createClearHoverData,
27
- createHoverHighlight,
28
- } from "@ogw_internal/stores/hybrid_viewer_highlight";
28
+ import { computeAverageBrightness } from "@ogw_internal/stores/hybrid_viewer_brightness";
29
29
  import { newInstance as vtkActor } from "@kitware/vtk.js/Rendering/Core/Actor";
30
30
  import { newInstance as vtkGenericRenderWindow } from "@kitware/vtk.js/Rendering/Misc/GenericRenderWindow";
31
31
  import { newInstance as vtkMapper } from "@kitware/vtk.js/Rendering/Core/Mapper";
@@ -137,6 +137,13 @@ export const useHybridViewerStore = defineStore("hybridViewer", () => {
137
137
  });
138
138
  }
139
139
 
140
+ async function setClippingPlanes(ids, planes) {
141
+ const schema = viewer_schemas.opengeodeweb_viewer.viewer.clipping_planes;
142
+ const params = { ids, planes };
143
+ await viewerStore.request({ schema, params });
144
+ await remoteRender();
145
+ }
146
+
140
147
  function resetCamera() {
141
148
  genericRenderWindow.value.getRenderer().resetCamera();
142
149
  genericRenderWindow.value.getRenderWindow().render();
@@ -307,6 +314,7 @@ export const useHybridViewerStore = defineStore("hybridViewer", () => {
307
314
  removeItem,
308
315
  setVisibility,
309
316
  setZScaling,
317
+ setClippingPlanes,
310
318
  syncRemoteCamera,
311
319
  setCamera,
312
320
  initHybridViewer,
@@ -1,5 +1,5 @@
1
1
  import { Status } from "@ogw_front/utils/status";
2
- import { appMode } from "@ogw_front/utils/local/app_mode";
2
+ import { appMode } from "@ogw_shared/app_mode";
3
3
  import { registerRunningExtensions } from "@ogw_front/utils/extension";
4
4
  import { useAppStore } from "@ogw_front/stores/app";
5
5
  import { useCloudStore } from "@ogw_front/stores/cloud";
@@ -9,7 +9,7 @@ export const useInfraStore = defineStore("infra", {
9
9
  app_mode: useRuntimeConfig().public.MODE,
10
10
  status: Status.NOT_CREATED,
11
11
  microservices: [],
12
- domain_name: "localhost",
12
+ domain_name: globalThis.location.hostname,
13
13
  }),
14
14
  getters: {
15
15
  microservices_connected() {
@@ -77,11 +77,6 @@ export const useInfraStore = defineStore("infra", {
77
77
  },
78
78
  async create_connection() {
79
79
  console.log("[INFRA] Starting create_connection");
80
- console.log(
81
- "[INFRA] Connecting microservices:",
82
- this.microservices.map((store) => store.$id),
83
- );
84
-
85
80
  await Promise.all(
86
81
  this.microservices.map(async (store) => {
87
82
  console.log("[INFRA] Connecting to microservice:", store.$id);
@@ -8,8 +8,12 @@ import { connectImageStream } from "@kitware/vtk.js/Rendering/Misc/RemoteView";
8
8
  import schemas from "@geode/opengeodeweb-viewer/opengeodeweb_viewer_schemas.json";
9
9
 
10
10
  // Local imports
11
+ import {
12
+ getWebsocketApiPort,
13
+ getWebsocketApiProtocol,
14
+ isCloudMode,
15
+ } from "@ogw_front/utils/stores.js";
11
16
  import { Status } from "@ogw_front/utils/status";
12
- import { appMode } from "@ogw_front/utils/local/app_mode";
13
17
  import { useAppStore } from "@ogw_front/stores/app";
14
18
  import { useInfraStore } from "@ogw_front/stores/infra";
15
19
  import { viewer_call } from "@ogw_internal/utils/viewer_call";
@@ -33,23 +37,13 @@ export const useViewerStore = defineStore(
33
37
  const version = ref("0.0.0");
34
38
  const busy = ref(0);
35
39
 
36
- const protocol = computed(() => {
37
- if (infraStore.app_mode === appMode.CLOUD) {
38
- return "wss";
39
- }
40
- return "ws";
41
- });
40
+ const protocol = computed(() => getWebsocketApiProtocol());
42
41
 
43
- const port = computed(() => {
44
- if (infraStore.app_mode === appMode.CLOUD) {
45
- return "443";
46
- }
47
- return default_local_port.value;
48
- });
42
+ const port = computed(() => getWebsocketApiPort(default_local_port.value));
49
43
 
50
44
  const base_url = computed(() => {
51
45
  let viewer_url = `${protocol.value}://${infraStore.domain_name}:${port.value}`;
52
- if (infraStore.app_mode === appMode.CLOUD) {
46
+ if (isCloudMode()) {
53
47
  viewer_url += `/viewer`;
54
48
  }
55
49
  viewer_url += "/ws";
@@ -133,7 +127,7 @@ export const useViewerStore = defineStore(
133
127
 
134
128
  const { COMMAND_VIEWER, NUXT_ROOT_PATH } = useRuntimeConfig().public;
135
129
  const schema = {
136
- $id: "/api/local/run_viewer",
130
+ $id: "/api/local/app/run_viewer",
137
131
  methods: ["POST"],
138
132
  type: "object",
139
133
  properties: { COMMAND_VIEWER: { type: "string" }, NUXT_ROOT_PATH: { type: "string" } },
@@ -162,25 +156,13 @@ export const useViewerStore = defineStore(
162
156
  }
163
157
 
164
158
  function request({ schema, params = {}, timeout = request_timeout }, callbacks = {}) {
165
- console.log("[VIEWER] Request:", schema.$id);
166
- const start = Date.now();
167
-
168
- // Get current store instance to pass to viewer_call
169
159
  const store = useViewerStore();
170
-
171
160
  return viewer_call(
172
161
  store,
173
162
  { schema, params, timeout },
174
163
  {
175
164
  ...callbacks,
176
165
  response_function: async (response) => {
177
- console.log(
178
- "[VIEWER] Request completed:",
179
- schema.$id,
180
- "in",
181
- (Date.now() - start) / MS_PER_SECOND,
182
- "s",
183
- );
184
166
  if (callbacks.response_function) {
185
167
  await callbacks.response_function(response);
186
168
  }
@@ -0,0 +1,110 @@
1
+ const AXIS_SCALE = 0.45;
2
+ const SIZE_RATIO = 0.1;
3
+ const DEBOUNCE_DELAY = 200;
4
+ const CHANGE_THRESHOLD = 1e-4;
5
+ // oxlint-disable no-magic-numbers
6
+ const COLOR_BLUE = [0.12, 0.53, 0.9];
7
+ const COLOR_GREEN = [0.26, 0.63, 0.28];
8
+ const COLOR_ORANGE = [0.98, 0.55, 0];
9
+ const COLOR_PURPLE = [0.55, 0.14, 0.67];
10
+ const COLOR_RED = [0.9, 0.22, 0.21];
11
+ // oxlint-enable no-magic-numbers
12
+ const PLANE_COLORS = [COLOR_BLUE, COLOR_GREEN, COLOR_ORANGE, COLOR_PURPLE, COLOR_RED];
13
+ const NORMAL_X = [1, 0, 0];
14
+ const NORMAL_Y = [0, 1, 0];
15
+ const NORMAL_Z = [0, 0, 1];
16
+ const DEFAULT_NORMALS = [NORMAL_X, NORMAL_Y, NORMAL_Z];
17
+ const RGB_MAX_VALUE = 255;
18
+
19
+ function getPlaneCssColor(index) {
20
+ const rgb = PLANE_COLORS[index % PLANE_COLORS.length];
21
+ return `rgb(${rgb.map((channel) => Math.round(channel * RGB_MAX_VALUE)).join(",")})`;
22
+ }
23
+
24
+ function hasPlaneChanged(origin, normal, currentOrigin, currentNormal) {
25
+ if (!currentOrigin) {
26
+ return true;
27
+ }
28
+ return (
29
+ origin.some((val, idx) => Math.abs(val - currentOrigin[idx]) > CHANGE_THRESHOLD) ||
30
+ normal.some((val, idx) => Math.abs(val - currentNormal[idx]) > CHANGE_THRESHOLD)
31
+ );
32
+ }
33
+
34
+ function getPlaneStyle(rgb) {
35
+ return {
36
+ active: {
37
+ plane: { opacity: 1, color: rgb },
38
+ normal: { opacity: 1, color: rgb },
39
+ origin: { opacity: 1, color: rgb },
40
+ },
41
+ inactive: {
42
+ plane: { opacity: 0.5, color: rgb },
43
+ normal: { opacity: 1, color: rgb },
44
+ origin: { opacity: 1, color: rgb },
45
+ },
46
+ static: {
47
+ display2D: { representation: 0 },
48
+ outline: { color: [1, 1, 1], opacity: 1, representation: 1, interpolation: 0 },
49
+ },
50
+ };
51
+ }
52
+
53
+ function computeSceneBounds(actors) {
54
+ let bounds = [Infinity, -Infinity, Infinity, -Infinity, Infinity, -Infinity];
55
+ for (const actor of actors) {
56
+ const boundsOfActor = actor.getBounds();
57
+ bounds = [
58
+ Math.min(bounds[0], boundsOfActor[0]),
59
+ Math.max(bounds[1], boundsOfActor[1]),
60
+ Math.min(bounds[2], boundsOfActor[2]),
61
+ Math.max(bounds[3], boundsOfActor[3]),
62
+ Math.min(bounds[4], boundsOfActor[4]),
63
+ Math.max(bounds[5], boundsOfActor[5]),
64
+ ];
65
+ }
66
+ return bounds;
67
+ }
68
+
69
+ function computeSceneBoundsInfo(actors) {
70
+ if (!actors || actors.length === 0) {
71
+ return { center: [0, 0, 0], cubicBounds: [-1, 1, -1, 1, -1, 1] };
72
+ }
73
+ const [xmin, xmax, ymin, ymax, zmin, zmax] = computeSceneBounds(actors);
74
+ const center = [
75
+ Number(((xmin + xmax) / 2).toFixed(4)),
76
+ Number(((ymin + ymax) / 2).toFixed(4)),
77
+ Number(((zmin + zmax) / 2).toFixed(4)),
78
+ ];
79
+
80
+ const maxActorExtent = Math.max(
81
+ ...actors.map((actor) => {
82
+ const bounds = actor.getBounds();
83
+ return Math.max(bounds[1] - bounds[0], bounds[3] - bounds[2], bounds[5] - bounds[4]);
84
+ }),
85
+ );
86
+ const halfExtent = maxActorExtent / 2;
87
+ const cubicBounds = [
88
+ center[0] - halfExtent,
89
+ center[0] + halfExtent,
90
+ center[1] - halfExtent,
91
+ center[1] + halfExtent,
92
+ center[2] - halfExtent,
93
+ center[2] + halfExtent,
94
+ ];
95
+ return { center, cubicBounds };
96
+ }
97
+
98
+ export {
99
+ AXIS_SCALE,
100
+ SIZE_RATIO,
101
+ DEBOUNCE_DELAY,
102
+ CHANGE_THRESHOLD,
103
+ PLANE_COLORS,
104
+ DEFAULT_NORMALS,
105
+ getPlaneCssColor,
106
+ hasPlaneChanged,
107
+ getPlaneStyle,
108
+ computeSceneBounds,
109
+ computeSceneBoundsInfo,
110
+ };
@@ -12,6 +12,11 @@ async function importExtensionFile(file) {
12
12
  return registerRunningExtensions();
13
13
  }
14
14
 
15
+ async function importExtensionURL(url) {
16
+ await downloadExtension(url);
17
+ return registerRunningExtensions();
18
+ }
19
+
15
20
  async function registerRunningExtensions() {
16
21
  const appStore = useAppStore();
17
22
  const infraStore = useInfraStore();
@@ -74,6 +79,27 @@ async function uploadExtension(file) {
74
79
  await appStore.upload(file);
75
80
  }
76
81
 
82
+ function downloadExtension({ url, extensionFileName }) {
83
+ const appStore = useAppStore();
84
+ const { PROJECT: projectName } = useRuntimeConfig().public;
85
+ const params = { projectName, url, extensionFileName };
86
+
87
+ const schema = {
88
+ $id: "/api/microservice/extensions/download",
89
+ methods: ["POST"],
90
+ type: "object",
91
+ properties: {
92
+ extensionFileName: { type: "string" },
93
+ projectName: { type: "string" },
94
+ url: { type: "string" },
95
+ },
96
+ required: ["extensionFileName", "projectName", "url"],
97
+ additionalProperties: false,
98
+ };
99
+
100
+ return appStore.request({ schema, params });
101
+ }
102
+
77
103
  function runExtensions() {
78
104
  const appStore = useAppStore();
79
105
  const { projectFolderPath } = appStore;
@@ -121,9 +147,10 @@ function killExtension(extensionId) {
121
147
 
122
148
  export {
123
149
  importExtensionFile,
124
- unloadExtension,
125
- uploadExtension,
150
+ importExtensionURL,
151
+ killExtension,
126
152
  registerRunningExtensions,
127
153
  runExtensions,
128
- killExtension,
154
+ unloadExtension,
155
+ uploadExtension,
129
156
  };
@@ -35,13 +35,6 @@ async function importWorkflow(files) {
35
35
  return results;
36
36
  }
37
37
 
38
- function buildImportItemFromPayloadApi(value, geode_object_type) {
39
- return {
40
- geode_object_type,
41
- ...value,
42
- };
43
- }
44
-
45
38
  async function importItem(item) {
46
39
  const dataStore = useDataStore();
47
40
  const dataStyleStore = useDataStyleStore();
@@ -61,14 +54,19 @@ async function importItem(item) {
61
54
  item.viewer_type === "model" ? dataStore.addComponentRelations(item) : Promise.resolve();
62
55
  treeviewStore.addItem(item.geode_object_type, item.name, item.id, item.viewer_type);
63
56
  const addDataStyleTask = dataStyleStore.addDataStyle(item.id, item.geode_object_type);
64
- const addViewerTask = addDataTask.then(() => {
65
- if (item.nb_vertices === 0) {
57
+ const addViewerTask = addDataTask.then(async () => {
58
+ if (!(await dataStore.isItemViewable(item))) {
66
59
  return;
67
60
  }
68
61
  return hybridViewerStore.addItem(item.id);
69
62
  });
70
63
  const applyStyleTask = Promise.all([registerTask, addDataComponentsTask, addDataStyleTask]).then(
71
- () => dataStyleStore.applyDefaultStyle(item.id),
64
+ async () => {
65
+ if (await dataStore.isItemViewable(item)) {
66
+ return dataStyleStore.applyDefaultStyle(item.id);
67
+ }
68
+ return undefined;
69
+ },
72
70
  );
73
71
  await Promise.all([
74
72
  registerTask,
@@ -89,8 +87,7 @@ async function importFile(filename, geode_object_type) {
89
87
  filename,
90
88
  };
91
89
  const response = await backStore.request({ schema, params });
92
- const item = buildImportItemFromPayloadApi(response, geode_object_type);
93
- return importItem(item);
90
+ return importItem(response);
94
91
  }
95
92
 
96
93
  async function importWorkflowFromSnapshot(items) {
@@ -0,0 +1,18 @@
1
+ function startRequestLog(microservice, schema) {
2
+ console.log(`[${microservice.$id}] Request:`, schema.$id);
3
+ const requestStartingTime = new Date(Date.now());
4
+ return requestStartingTime;
5
+ }
6
+
7
+ function endRequestLog(microservice, schema, requestStartingTime) {
8
+ const requestEndingTime = new Date(Date.now());
9
+ console.log(
10
+ `[${microservice.$id}] Request completed:`,
11
+ schema.$id,
12
+ "in",
13
+ requestEndingTime.getSeconds() - requestStartingTime.getSeconds(),
14
+ "s",
15
+ );
16
+ }
17
+
18
+ export { startRequestLog, endRequestLog };
@@ -0,0 +1,32 @@
1
+ import { appMode } from "@ogw_shared/app_mode";
2
+ import { useInfraStore } from "@ogw_front/stores/infra";
3
+
4
+ function isCloudMode() {
5
+ const infraStore = useInfraStore();
6
+ return infraStore.app_mode === appMode.CLOUD;
7
+ }
8
+
9
+ function getRestApiProtocol() {
10
+ const protocol = isCloudMode() ? "https" : "http";
11
+ return protocol;
12
+ }
13
+ function getRestApiPort(defaultLocalPort) {
14
+ const port = isCloudMode() ? "443" : defaultLocalPort;
15
+ return port;
16
+ }
17
+ function getWebsocketApiProtocol() {
18
+ const protocol = isCloudMode() ? "wss" : "ws";
19
+ return protocol;
20
+ }
21
+ function getWebsocketApiPort(defaultLocalPort) {
22
+ const port = isCloudMode() ? "443" : defaultLocalPort;
23
+ return port;
24
+ }
25
+
26
+ export {
27
+ isCloudMode,
28
+ getRestApiPort,
29
+ getRestApiProtocol,
30
+ getWebsocketApiProtocol,
31
+ getWebsocketApiPort,
32
+ };
@@ -1,65 +1,5 @@
1
- import { BACKGROUND_GREY_VALUE, RGB_MAX } from "./hybrid_viewer_constants";
2
1
  import { centerCameraOnPosition } from "./hybrid_viewer_camera";
3
2
 
4
- const RGBA_CHANNELS = 4;
5
- const SAMPLE_SIZE = 10;
6
- const TOTAL_CHANNELS = 400;
7
-
8
- function mapRect(rect, latestImage, canvasRect) {
9
- const scaleX = latestImage.width / canvasRect.width;
10
- const scaleY = latestImage.height / canvasRect.height;
11
- return {
12
- relX: (rect.x - canvasRect.left) * scaleX,
13
- relY: (rect.y - canvasRect.top) * scaleY,
14
- relW: rect.width * scaleX,
15
- relH: rect.height * scaleY,
16
- };
17
- }
18
-
19
- function computeAverageBrightness(rect, options) {
20
- const { latestImage, offscreenCtx, offscreenCanvas, genericRenderWindow } = options;
21
- if (!latestImage || !offscreenCtx || !offscreenCanvas || !genericRenderWindow) {
22
- return BACKGROUND_GREY_VALUE / RGB_MAX;
23
- }
24
- const canvas = genericRenderWindow.getApiSpecificRenderWindow().getCanvas();
25
- if (!canvas) {
26
- return BACKGROUND_GREY_VALUE / RGB_MAX;
27
- }
28
- if (rect.width <= 0 || rect.height <= 0) {
29
- return BACKGROUND_GREY_VALUE / RGB_MAX;
30
- }
31
- const { relX, relY, relW, relH } = mapRect(rect, latestImage, canvas.getBoundingClientRect());
32
- if (relW <= 0 || relH <= 0) {
33
- return BACKGROUND_GREY_VALUE / RGB_MAX;
34
- }
35
- offscreenCanvas.width = SAMPLE_SIZE;
36
- offscreenCanvas.height = SAMPLE_SIZE;
37
- try {
38
- offscreenCtx.drawImage(
39
- latestImage,
40
- Math.max(0, relX),
41
- Math.max(0, relY),
42
- Math.min(latestImage.width, relW),
43
- Math.min(latestImage.height, relH),
44
- 0,
45
- 0,
46
- SAMPLE_SIZE,
47
- SAMPLE_SIZE,
48
- );
49
- const { data } = offscreenCtx.getImageData(0, 0, SAMPLE_SIZE, SAMPLE_SIZE);
50
- let minBrightness = 1;
51
- for (let i = 0; i < TOTAL_CHANNELS; i += RGBA_CHANNELS) {
52
- const brightness = (data[i] + data[i + 1] + data[i + 2]) / (3 * RGB_MAX);
53
- if (brightness < minBrightness) {
54
- minBrightness = brightness;
55
- }
56
- }
57
- return minBrightness;
58
- } catch {
59
- return BACKGROUND_GREY_VALUE / RGB_MAX;
60
- }
61
- }
62
-
63
3
  function performClickPicking(event, options) {
64
4
  const { container, viewerStore, viewer_schemas, genericRenderWindow, syncRemoteCamera } = options;
65
5
  const rect = container.getBoundingClientRect();
@@ -148,8 +88,11 @@ async function performAddItem(id, options) {
148
88
  if (!genericRenderWindow) {
149
89
  return;
150
90
  }
151
- const reader = vtkXMLPolyDataReader(),
152
- value = await dataStore.item(id);
91
+ const value = await dataStore.item(id);
92
+ if (value && !dataStore.isItemViewable(value)) {
93
+ return;
94
+ }
95
+ const reader = vtkXMLPolyDataReader();
153
96
  await reader.parseAsArrayBuffer(new TextEncoder().encode(value.binary_light_viewable));
154
97
  const actor = vtkActor(),
155
98
  mapper = vtkMapper(),
@@ -158,6 +101,9 @@ async function performAddItem(id, options) {
158
101
  actor.getProperty().setColor(actorColor);
159
102
  actor.setMapper(mapper);
160
103
  const renderer = genericRenderWindow.getRenderer();
104
+ if (hybridDb[id] && hybridDb[id].actor) {
105
+ renderer.removeActor(hybridDb[id].actor);
106
+ }
161
107
  const isFirst = renderer.getActors().length === 0;
162
108
  renderer.addActor(actor);
163
109
  if (isFirst) {
@@ -307,7 +253,6 @@ function performClear(options) {
307
253
  }
308
254
 
309
255
  export {
310
- computeAverageBrightness,
311
256
  performAddItem,
312
257
  performClearHoverHighlight,
313
258
  performClickPicking,
@@ -0,0 +1,62 @@
1
+ import { BACKGROUND_GREY_VALUE, RGB_MAX } from "./hybrid_viewer_constants";
2
+
3
+ const RGBA_CHANNELS = 4;
4
+ const SAMPLE_SIZE = 10;
5
+ const TOTAL_CHANNELS = 400;
6
+
7
+ function mapRect(rect, latestImage, canvasRect) {
8
+ const scaleX = latestImage.width / canvasRect.width;
9
+ const scaleY = latestImage.height / canvasRect.height;
10
+ return {
11
+ relX: (rect.x - canvasRect.left) * scaleX,
12
+ relY: (rect.y - canvasRect.top) * scaleY,
13
+ relW: rect.width * scaleX,
14
+ relH: rect.height * scaleY,
15
+ };
16
+ }
17
+
18
+ function computeAverageBrightness(rect, options) {
19
+ const { latestImage, offscreenCtx, offscreenCanvas, genericRenderWindow } = options;
20
+ if (!latestImage || !offscreenCtx || !offscreenCanvas || !genericRenderWindow) {
21
+ return BACKGROUND_GREY_VALUE / RGB_MAX;
22
+ }
23
+ const canvas = genericRenderWindow.getApiSpecificRenderWindow().getCanvas();
24
+ if (!canvas) {
25
+ return BACKGROUND_GREY_VALUE / RGB_MAX;
26
+ }
27
+ if (rect.width <= 0 || rect.height <= 0) {
28
+ return BACKGROUND_GREY_VALUE / RGB_MAX;
29
+ }
30
+ const { relX, relY, relW, relH } = mapRect(rect, latestImage, canvas.getBoundingClientRect());
31
+ if (relW <= 0 || relH <= 0) {
32
+ return BACKGROUND_GREY_VALUE / RGB_MAX;
33
+ }
34
+ offscreenCanvas.width = SAMPLE_SIZE;
35
+ offscreenCanvas.height = SAMPLE_SIZE;
36
+ try {
37
+ offscreenCtx.drawImage(
38
+ latestImage,
39
+ Math.max(0, relX),
40
+ Math.max(0, relY),
41
+ Math.min(latestImage.width, relW),
42
+ Math.min(latestImage.height, relH),
43
+ 0,
44
+ 0,
45
+ SAMPLE_SIZE,
46
+ SAMPLE_SIZE,
47
+ );
48
+ const { data } = offscreenCtx.getImageData(0, 0, SAMPLE_SIZE, SAMPLE_SIZE);
49
+ let minBrightness = 1;
50
+ for (let i = 0; i < TOTAL_CHANNELS; i += RGBA_CHANNELS) {
51
+ const brightness = (data[i] + data[i + 1] + data[i + 2]) / (3 * RGB_MAX);
52
+ if (brightness < minBrightness) {
53
+ minBrightness = brightness;
54
+ }
55
+ }
56
+ return minBrightness;
57
+ } catch {
58
+ return BACKGROUND_GREY_VALUE / RGB_MAX;
59
+ }
60
+ }
61
+
62
+ export { computeAverageBrightness };