@geode/opengeodeweb-front 10.19.0 → 10.20.0-rc.1

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 (29) hide show
  1. package/app/components/ViewToolbar.vue +1 -1
  2. package/app/components/Viewer/ContextMenu/CenterButton.vue +119 -0
  3. package/app/components/Viewer/ContextMenu/CircularItems.vue +86 -0
  4. package/app/components/Viewer/{ContextMenu.vue → ContextMenu/ContextMenu.vue} +67 -71
  5. package/app/components/Viewer/{ContextMenuItem.vue → ContextMenu/ContextMenuItem.vue} +104 -4
  6. package/app/components/Viewer/ContextMenu/InfoCard.vue +184 -0
  7. package/app/components/Viewer/EdgedCurve/SpecificEdgesOptions.vue +1 -1
  8. package/app/components/Viewer/Generic/Mesh/CellsOptions.vue +1 -1
  9. package/app/components/Viewer/Generic/Mesh/EdgesOptions.vue +1 -1
  10. package/app/components/Viewer/Generic/Mesh/PointsOptions.vue +1 -1
  11. package/app/components/Viewer/Generic/Mesh/PolygonsOptions.vue +1 -1
  12. package/app/components/Viewer/Generic/Mesh/PolyhedraOptions.vue +1 -1
  13. package/app/components/Viewer/Generic/Model/EdgesOptions.vue +1 -1
  14. package/app/components/Viewer/Generic/Model/ModelStyleOptions.vue +1 -1
  15. package/app/components/Viewer/Generic/Model/PointsOptions.vue +1 -1
  16. package/app/components/Viewer/OverlappingObjectsPicker.vue +96 -0
  17. package/app/components/Viewer/PointSet/SpecificPointsOptions.vue +1 -1
  18. package/app/components/Viewer/Solid/SpecificPolyhedraOptions.vue +1 -1
  19. package/app/components/Viewer/Surface/PolygonsOptions.vue +1 -1
  20. package/app/components/Viewer/Ui.vue +38 -24
  21. package/app/composables/project_manager.js +3 -3
  22. package/app/composables/use_adaptive_styles.js +50 -3
  23. package/app/composables/use_overlapping_picker.js +153 -0
  24. package/app/stores/data.js +5 -0
  25. package/app/utils/local/microservices.js +2 -2
  26. package/app/utils/name_cleaner.js +20 -0
  27. package/internal/stores/hybrid_viewer.js +6 -0
  28. package/package.json +3 -3
  29. package/tests/unit/composables/project_manager.nuxt.test.js +0 -1
@@ -0,0 +1,153 @@
1
+ import { ref } from "vue";
2
+ import { useDataStore } from "@ogw_front/stores/data";
3
+ import { useDataStyleStore } from "@ogw_front/stores/data_style";
4
+ import { useViewerStore } from "@ogw_front/stores/viewer";
5
+ import viewer_schemas from "@geode/opengeodeweb-viewer/opengeodeweb_viewer_schemas.json";
6
+
7
+ export function useOverlappingPicker() {
8
+ const dataStore = useDataStore();
9
+ const dataStyleStore = useDataStyleStore();
10
+ const viewerStore = useViewerStore();
11
+ const dataItems = dataStore.refAllItems();
12
+
13
+ const displayIntermediate = ref(false);
14
+ const intermediateItems = ref([]);
15
+ const intermediateMenuX = ref(0);
16
+ const intermediateMenuY = ref(0);
17
+ let resolveIntermediate = undefined;
18
+
19
+ function fetchProposedItems(pickedList) {
20
+ return Promise.all(
21
+ pickedList.map(async (pick) => {
22
+ try {
23
+ const item = await dataStore.item(pick.id);
24
+ return {
25
+ id: pick.id,
26
+ viewer_id: pick.viewer_id,
27
+ name: item.name || "Unnamed Object",
28
+ viewer_type: item.viewer_type,
29
+ geode_object_type: item.geode_object_type,
30
+ };
31
+ } catch {
32
+ return {
33
+ id: pick.id,
34
+ viewer_id: pick.viewer_id,
35
+ name: "Unnamed Object",
36
+ viewer_type: undefined,
37
+ geode_object_type: undefined,
38
+ };
39
+ }
40
+ }),
41
+ );
42
+ }
43
+
44
+ function getIntermediateMenuStyle() {
45
+ return {
46
+ position: "fixed",
47
+ left: `${intermediateMenuX.value}px`,
48
+ top: `${intermediateMenuY.value}px`,
49
+ };
50
+ }
51
+
52
+ function selectIntermediateItem(item) {
53
+ if (resolveIntermediate) {
54
+ resolveIntermediate(item);
55
+ resolveIntermediate = undefined;
56
+ }
57
+ }
58
+
59
+ function handleIntermediateMenuUpdate(val) {
60
+ if (!val && resolveIntermediate) {
61
+ resolveIntermediate(undefined);
62
+ resolveIntermediate = undefined;
63
+ }
64
+ }
65
+
66
+ async function get_viewer_id({ x, y, containerWidth, containerHeight, containerRect }) {
67
+ const activeIds = new Set(dataItems.value.map((item) => item.id));
68
+ const ids = Object.keys(dataStyleStore.styles).filter((styleId) => activeIds.has(styleId));
69
+
70
+ const result = { id: undefined, viewer_id: undefined };
71
+ let pickedResponse = undefined;
72
+
73
+ await viewerStore.request(
74
+ viewer_schemas.opengeodeweb_viewer.viewer.picked_ids,
75
+ { x, y, ids },
76
+ {
77
+ response_function: (response) => {
78
+ pickedResponse = response;
79
+ },
80
+ },
81
+ );
82
+
83
+ if (!pickedResponse || !pickedResponse.array_ids || pickedResponse.array_ids.length === 0) {
84
+ return result;
85
+ }
86
+
87
+ const { array_ids, viewer_id, picked_data } = pickedResponse;
88
+
89
+ const pickedList = [];
90
+ if (picked_data && picked_data.length > 0) {
91
+ pickedList.push(...picked_data);
92
+ } else {
93
+ for (const pickId of array_ids) {
94
+ pickedList.push({ id: pickId, viewer_id });
95
+ }
96
+ }
97
+
98
+ if (pickedList.length <= 1) {
99
+ return { id: pickedList[0]?.id, viewer_id: pickedList[0]?.viewer_id };
100
+ }
101
+
102
+ const proposedItems = await fetchProposedItems(pickedList);
103
+ intermediateItems.value = proposedItems;
104
+
105
+ const yUI = containerHeight - y;
106
+ const MENU_WIDTH = 340;
107
+ const MENU_BASE_HEIGHT = 55;
108
+ const MENU_ITEM_HEIGHT = 48;
109
+ const MENU_HEIGHT = MENU_BASE_HEIGHT + proposedItems.length * MENU_ITEM_HEIGHT;
110
+ const CLAMP_MARGIN = 10;
111
+ const clampedX = Math.min(
112
+ Math.max(x, CLAMP_MARGIN),
113
+ containerWidth - MENU_WIDTH - CLAMP_MARGIN,
114
+ );
115
+ let clampedY = yUI;
116
+ if (yUI + MENU_HEIGHT > containerHeight - CLAMP_MARGIN) {
117
+ clampedY = Math.max(yUI - MENU_HEIGHT, CLAMP_MARGIN);
118
+ } else {
119
+ clampedY = Math.max(yUI, CLAMP_MARGIN);
120
+ }
121
+ clampedY = Math.min(
122
+ Math.max(clampedY, CLAMP_MARGIN),
123
+ containerHeight - MENU_HEIGHT - CLAMP_MARGIN,
124
+ );
125
+
126
+ intermediateMenuX.value = containerRect.left + clampedX;
127
+ intermediateMenuY.value = containerRect.top + clampedY;
128
+ displayIntermediate.value = true;
129
+
130
+ /* eslint-disable-next-line promise/avoid-new */
131
+ return new Promise((resolve) => {
132
+ resolveIntermediate = (chosenResult) => {
133
+ displayIntermediate.value = false;
134
+ resolve(
135
+ chosenResult
136
+ ? { id: chosenResult.id, viewer_id: chosenResult.viewer_id }
137
+ : { id: undefined, viewer_id: undefined },
138
+ );
139
+ };
140
+ });
141
+ }
142
+
143
+ return {
144
+ displayIntermediate,
145
+ intermediateItems,
146
+ intermediateMenuX,
147
+ intermediateMenuY,
148
+ getIntermediateMenuStyle,
149
+ selectIntermediateItem,
150
+ handleIntermediateMenuUpdate,
151
+ get_viewer_id,
152
+ };
153
+ }
@@ -24,6 +24,10 @@ export const useDataStore = defineStore("data", () => {
24
24
  return data_item;
25
25
  }
26
26
 
27
+ async function allItems() {
28
+ return await data_db.toArray();
29
+ }
30
+
27
31
  function refItem(id) {
28
32
  return useObservable(
29
33
  liveQuery(() => data_db.get(id)),
@@ -276,6 +280,7 @@ export const useDataStore = defineStore("data", () => {
276
280
  return {
277
281
  refAllItems,
278
282
  item,
283
+ allItems,
279
284
  refItem,
280
285
  meshComponentType,
281
286
  formatedMeshComponents,
@@ -37,11 +37,11 @@ async function runScript(
37
37
  command = path.join(executablePath(execPath), executableName(execName));
38
38
  }
39
39
  console.log("runScript", command, args);
40
- const child = child_process.spawn(command, args, {
40
+
41
+ const child = child_process.spawn(process.platform === "win32" ? command : `"${command}"`, args, {
41
42
  encoding: "utf8",
42
43
  shell: true,
43
44
  });
44
-
45
45
  child.stdout.on("data", (data) => console.log(`[${execName}] ${data.toString()}`));
46
46
  child.stderr.on("data", (data) => console.log(`[${execName}] ${data.toString()}`));
47
47
 
@@ -0,0 +1,20 @@
1
+ const DEFAULT_MAX_LENGTH = 16;
2
+ const DEFAULT_SLICE_START = 8;
3
+ const DEFAULT_SLICE_END_OFFSET = 8;
4
+
5
+ function formatListId(
6
+ id,
7
+ maxLength = DEFAULT_MAX_LENGTH,
8
+ sliceStart = DEFAULT_SLICE_START,
9
+ sliceEndOffset = DEFAULT_SLICE_END_OFFSET,
10
+ ) {
11
+ if (!id) {
12
+ return "";
13
+ }
14
+ if (id.length <= maxLength) {
15
+ return id;
16
+ }
17
+ return `${id.slice(0, sliceStart)}...${id.slice(id.length - sliceEndOffset)}`;
18
+ }
19
+
20
+ export { formatListId };
@@ -42,7 +42,13 @@ function computeAverageBrightness(rect, options) {
42
42
  if (!canvas) {
43
43
  return BACKGROUND_GREY_VALUE / RGB_MAX;
44
44
  }
45
+ if (rect.width <= 0 || rect.height <= 0) {
46
+ return BACKGROUND_GREY_VALUE / RGB_MAX;
47
+ }
45
48
  const { relX, relY, relW, relH } = mapRect(rect, latestImage, canvas.getBoundingClientRect());
49
+ if (relW <= 0 || relH <= 0) {
50
+ return BACKGROUND_GREY_VALUE / RGB_MAX;
51
+ }
46
52
  offscreenCanvas.width = SAMPLE_SIZE;
47
53
  offscreenCanvas.height = SAMPLE_SIZE;
48
54
  try {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@geode/opengeodeweb-front",
3
- "version": "10.19.0",
3
+ "version": "10.20.0-rc.1",
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": {
@@ -34,8 +34,8 @@
34
34
  "build": ""
35
35
  },
36
36
  "dependencies": {
37
- "@geode/opengeodeweb-back": "latest",
38
- "@geode/opengeodeweb-viewer": "latest",
37
+ "@geode/opengeodeweb-back": "next",
38
+ "@geode/opengeodeweb-viewer": "next",
39
39
  "@google-cloud/run": "3.2.0",
40
40
  "@kitware/vtk.js": "33.3.0",
41
41
  "@mdi/font": "7.4.47",
@@ -4,7 +4,6 @@
4
4
  // Third party imports
5
5
  import { beforeEach, describe, expect, test, vi } from "vitest";
6
6
 
7
- // Local imports
8
7
  import { exportProject, importProject } from "@ogw_front/composables/project_manager";
9
8
  import { appMode } from "@ogw_front/utils/local/app_mode";
10
9
  import { setupActivePinia } from "@ogw_tests/utils";