@geode/opengeodeweb-front 10.18.2-rc.1 → 10.19.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.
@@ -1,5 +1,6 @@
1
1
  <script setup>
2
2
  import { useFeedbackStore } from "@ogw_front/stores/feedback";
3
+
3
4
  const feedbackStore = useFeedbackStore();
4
5
 
5
6
  function reload() {
@@ -1,5 +1,6 @@
1
1
  <script setup>
2
2
  import { computed, useAttrs } from "vue";
3
+
3
4
  const { variant, rounded, padding, theme } = defineProps({
4
5
  variant: {
5
6
  type: String,
@@ -1,4 +1,5 @@
1
1
  <script setup>
2
+ import HybridViewerTooltip from "@ogw_front/components/HybridViewerTooltip";
2
3
  import ViewToolbar from "@ogw_front/components/ViewToolbar";
3
4
  import { useHybridViewerStore } from "@ogw_front/stores/hybrid_viewer";
4
5
  import { useViewerStore } from "@ogw_front/stores/viewer";
@@ -60,6 +61,7 @@ async function handleClick(event) {
60
61
  <div data-testid="hybridViewer" class="fill-height" style="position: relative; height: 100%">
61
62
  <ViewToolbar />
62
63
  <slot name="ui"></slot>
64
+ <HybridViewerTooltip :container-width="elementWidth" :container-height="elementHeight" />
63
65
  <v-col
64
66
  class="pa-0"
65
67
  ref="viewer"
@@ -0,0 +1,216 @@
1
+ <script setup>
2
+ import GlassCard from "@ogw_front/components/GlassCard";
3
+ import { useHybridViewerStore } from "@ogw_front/stores/hybrid_viewer";
4
+
5
+ const TOOLTIP_SCREEN_MARGIN = 10;
6
+
7
+ const { containerWidth, containerHeight } = defineProps({
8
+ containerWidth: {
9
+ type: Number,
10
+ required: true,
11
+ },
12
+ containerHeight: {
13
+ type: Number,
14
+ required: true,
15
+ },
16
+ });
17
+
18
+ const hybridViewerStore = useHybridViewerStore();
19
+
20
+ const tooltipRef = useTemplateRef("tooltip");
21
+ const { width: tooltipWidth, height: tooltipHeight } = useElementSize(tooltipRef);
22
+
23
+ const tooltipStyle = computed(() => {
24
+ if (!hybridViewerStore.hoverData) {
25
+ return {};
26
+ }
27
+ const mouseX = hybridViewerStore.hoverPosition.x;
28
+ const mouseY = hybridViewerStore.hoverPosition.y;
29
+ const measuredTooltipWidth = tooltipWidth.value;
30
+ const measuredTooltipHeight = tooltipHeight.value;
31
+ const tooltipOffsetGap = 20;
32
+
33
+ let left = mouseX + tooltipOffsetGap;
34
+ if (left + measuredTooltipWidth > containerWidth) {
35
+ left = mouseX - measuredTooltipWidth - tooltipOffsetGap;
36
+ }
37
+ if (left < 0) {
38
+ left = TOOLTIP_SCREEN_MARGIN;
39
+ }
40
+
41
+ let top = mouseY - measuredTooltipHeight - tooltipOffsetGap;
42
+ if (top < 0) {
43
+ top = mouseY + tooltipOffsetGap;
44
+ }
45
+ if (top + measuredTooltipHeight > containerHeight) {
46
+ top = containerHeight - measuredTooltipHeight - TOOLTIP_SCREEN_MARGIN;
47
+ }
48
+
49
+ return {
50
+ left: `${left}px`,
51
+ top: `${top}px`,
52
+ };
53
+ });
54
+
55
+ const originalIndex = computed(() => {
56
+ const attributes = hybridViewerStore.hoverData?.attributes || {};
57
+ const originalId =
58
+ attributes.vtkOriginalCellIds ??
59
+ attributes.vtkOriginalPointIds ??
60
+ hybridViewerStore.hoverData?.pickedId;
61
+ if (originalId === undefined) {
62
+ return undefined;
63
+ }
64
+ return Math.floor(Number(originalId));
65
+ });
66
+
67
+ const hasOtherAttributes = computed(() => {
68
+ const attributes = hybridViewerStore.hoverData?.attributes || {};
69
+ return Object.keys(attributes).some(
70
+ (key) => key !== "vtkOriginalCellIds" && key !== "vtkOriginalPointIds",
71
+ );
72
+ });
73
+
74
+ function capitalize(val) {
75
+ if (!val) {
76
+ return "";
77
+ }
78
+ const spaced = val.replaceAll("_", " ");
79
+ return spaced.charAt(0).toUpperCase() + spaced.slice(1);
80
+ }
81
+
82
+ function formatAttributeValue(val) {
83
+ if (Array.isArray(val)) {
84
+ const formattedValues = val.map((value) => {
85
+ if (typeof value === "number") {
86
+ if (Number.isInteger(value)) {
87
+ return String(value);
88
+ }
89
+ return Number(value).toFixed(3);
90
+ }
91
+ return value;
92
+ });
93
+ return `[ ${formattedValues.join(", ")} ]`;
94
+ }
95
+ if (typeof val === "number") {
96
+ return Number.isInteger(val) ? String(val) : Number(val).toFixed(4);
97
+ }
98
+ return val;
99
+ }
100
+ </script>
101
+
102
+ <template>
103
+ <GlassCard
104
+ v-if="hybridViewerStore.hoverData"
105
+ ref="tooltip"
106
+ variant="panel"
107
+ padding="pa-3"
108
+ rounded="lg"
109
+ class="floating-tooltip"
110
+ :style="tooltipStyle"
111
+ >
112
+ <v-container fluid class="pa-0 tooltip-container">
113
+ <v-row no-gutters class="flex-column ga-1">
114
+ <v-col>
115
+ <span class="tooltip-label">Name:</span>
116
+ <span class="tooltip-value">
117
+ {{
118
+ hybridViewerStore.hoverData.component?.name ||
119
+ hybridViewerStore.hoverData.component?.id ||
120
+ hybridViewerStore.hoverData.blockName ||
121
+ hybridViewerStore.hoverData.modelName ||
122
+ `${capitalize(hybridViewerStore.hoverData.fieldType.toLowerCase())} #${hybridViewerStore.hoverData.pickedId}`
123
+ }}
124
+ </span>
125
+ </v-col>
126
+ <v-col>
127
+ <span class="tooltip-label">Id:</span>
128
+ <span class="tooltip-value-dim font-mono">
129
+ {{ hybridViewerStore.hoverData.component?.id || hybridViewerStore.hoverData.modelId }}
130
+ </span>
131
+ </v-col>
132
+ <v-col v-if="originalIndex !== undefined">
133
+ <span class="tooltip-label">Index:</span>
134
+ <span class="tooltip-value font-mono">
135
+ {{ originalIndex }}
136
+ </span>
137
+ </v-col>
138
+ <v-col v-if="hybridViewerStore.hoverData.component?.type">
139
+ <span class="tooltip-label">Type:</span>
140
+ <span class="tooltip-value">
141
+ {{ hybridViewerStore.hoverData.component.type }}
142
+ </span>
143
+ </v-col>
144
+ </v-row>
145
+ <template v-if="hasOtherAttributes">
146
+ <v-divider class="my-2" opacity="0.15" />
147
+ <v-row no-gutters class="flex-column ga-1">
148
+ <v-col
149
+ v-if="hybridViewerStore.hoverData.attributes.coordinates"
150
+ class="d-flex justify-space-between ga-3"
151
+ >
152
+ <span class="tooltip-label">Position:</span>
153
+ <span class="tooltip-value font-mono">
154
+ [ {{ Number(hybridViewerStore.hoverData.attributes.coordinates[0]).toFixed(3) }},
155
+ {{ Number(hybridViewerStore.hoverData.attributes.coordinates[1]).toFixed(3) }},
156
+ {{ Number(hybridViewerStore.hoverData.attributes.coordinates[2]).toFixed(3) }} ]
157
+ </span>
158
+ </v-col>
159
+ <template v-for="(val, name) in hybridViewerStore.hoverData.attributes" :key="name">
160
+ <v-col
161
+ v-if="
162
+ name !== 'coordinates' &&
163
+ name !== 'vtkOriginalCellIds' &&
164
+ name !== 'vtkOriginalPointIds'
165
+ "
166
+ class="d-flex justify-space-between ga-3"
167
+ >
168
+ <span class="tooltip-label">{{ capitalize(name) }}:</span>
169
+ <span class="tooltip-value font-mono">
170
+ {{ formatAttributeValue(val) }}
171
+ </span>
172
+ </v-col>
173
+ </template>
174
+ </v-row>
175
+ </template>
176
+ </v-container>
177
+ </GlassCard>
178
+ </template>
179
+
180
+ <style scoped>
181
+ .floating-tooltip {
182
+ position: absolute;
183
+ pointer-events: none;
184
+ z-index: 10000;
185
+ min-width: 200px;
186
+ max-width: 450px;
187
+ transition: opacity 0.15s ease;
188
+ }
189
+ .font-mono {
190
+ font-family: monospace !important;
191
+ }
192
+ .tooltip-container {
193
+ min-width: 220px;
194
+ color: white;
195
+ font-size: 0.875rem;
196
+ }
197
+ .tooltip-label {
198
+ color: #bdbdbd;
199
+ font-weight: bold;
200
+ }
201
+ .tooltip-value {
202
+ color: #a7ffeb;
203
+ font-weight: 500;
204
+ }
205
+ .tooltip-value-dim {
206
+ color: #eeeeee;
207
+ font-size: 0.75rem !important;
208
+ }
209
+ .tooltip-label + .tooltip-value,
210
+ .tooltip-label + .tooltip-value-dim {
211
+ margin-left: 4px;
212
+ }
213
+ .justify-space-between > .tooltip-value {
214
+ margin-left: 0 !important;
215
+ }
216
+ </style>
@@ -1,5 +1,6 @@
1
1
  <script setup>
2
2
  import { useInfraStore } from "@ogw_front/stores/infra";
3
+
3
4
  const infraStore = useInfraStore();
4
5
  console.log("TEST", { infraStore });
5
6
  </script>
@@ -1,6 +1,7 @@
1
1
  <script setup>
2
2
  import schemas from "@geode/opengeodeweb-back/opengeodeweb_back_schemas.json";
3
3
  import { useGeodeStore } from "@ogw_front/stores/geode";
4
+
4
5
  const schema = schemas.opengeodeweb_back.inspect_file;
5
6
 
6
7
  const emit = defineEmits(["update_values", "increment_step", "decrement_step"]);
@@ -1,5 +1,6 @@
1
1
  <script setup>
2
2
  import Slider from "./Slider";
3
+
3
4
  const size = defineModel();
4
5
  </script>
5
6
 
@@ -1,5 +1,6 @@
1
1
  <script setup>
2
2
  import Slider from "./Slider";
3
+
3
4
  const width = defineModel();
4
5
  </script>
5
6
 
@@ -1,4 +1,5 @@
1
1
  import { useInfraStore } from "@ogw_front/stores/infra";
2
+
2
3
  export function run_function_when_microservices_connected(function_to_run) {
3
4
  const infraStore = useInfraStore();
4
5
  const { microservices_connected } = storeToRefs(infraStore);
@@ -1,14 +1,15 @@
1
1
  import {
2
2
  ACTOR_COLOR,
3
3
  BACKGROUND_COLOR,
4
- HOVER_THROTTLE_MS,
5
4
  WHEEL_TIME_OUT_MS,
6
5
  computeAverageBrightness,
7
6
  performAddItem,
7
+ performClear,
8
8
  performClearHoverHighlight,
9
9
  performClickPicking,
10
- performHoverHighlight,
10
+ performRemoveItem,
11
11
  performSetContainer,
12
+ performSetVisibility,
12
13
  performSetZScaling,
13
14
  } from "@ogw_internal/stores/hybrid_viewer";
14
15
  import {
@@ -19,6 +20,10 @@ import {
19
20
  performSetCamera,
20
21
  performSyncRemoteCamera,
21
22
  } from "@ogw_internal/stores/hybrid_viewer_camera";
23
+ import {
24
+ createClearHoverData,
25
+ createHoverHighlight,
26
+ } from "@ogw_internal/stores/hybrid_viewer_highlight";
22
27
  import { newInstance as vtkActor } from "@kitware/vtk.js/Rendering/Core/Actor";
23
28
  import { newInstance as vtkGenericRenderWindow } from "@kitware/vtk.js/Rendering/Misc/GenericRenderWindow";
24
29
  import { newInstance as vtkMapper } from "@kitware/vtk.js/Rendering/Core/Mapper";
@@ -30,6 +35,7 @@ import { useViewerStore } from "@ogw_front/stores/viewer";
30
35
 
31
36
  import viewer_schemas from "@geode/opengeodeweb-viewer/opengeodeweb_viewer_schemas.json";
32
37
 
38
+ // oxlint-disable max-lines-per-function max-statements
33
39
  export const useHybridViewerStore = defineStore("hybridViewer", () => {
34
40
  const dataStore = useDataStore();
35
41
  const hybridDb = reactive({});
@@ -41,6 +47,8 @@ export const useHybridViewerStore = defineStore("hybridViewer", () => {
41
47
  const is_picking = ref(false);
42
48
  const is_hover_highlight = ref(false);
43
49
  const hover_highlight_field_type = ref("CELL");
50
+ const hoverData = ref(undefined);
51
+ const hoverPosition = ref({ x: 0, y: 0 });
44
52
  const zScale = ref(1);
45
53
  let imageStyle = undefined;
46
54
  let viewStream = undefined;
@@ -106,20 +114,14 @@ export const useHybridViewerStore = defineStore("hybridViewer", () => {
106
114
  }
107
115
 
108
116
  function removeItem(id) {
109
- if (!hybridDb[id]) {
110
- return;
111
- }
112
- genericRenderWindow.value.getRenderer().removeActor(hybridDb[id].actor);
113
- genericRenderWindow.value.getRenderWindow().render();
114
- delete hybridDb[id];
117
+ performRemoveItem(id, { genericRenderWindow: genericRenderWindow.value, hybridDb });
115
118
  }
116
119
 
117
120
  function setVisibility(id, visibility) {
118
- if (!hybridDb[id]) {
119
- return;
120
- }
121
- hybridDb[id].actor.setVisibility(visibility);
122
- genericRenderWindow.value.getRenderWindow().render();
121
+ performSetVisibility(id, visibility, {
122
+ genericRenderWindow: genericRenderWindow.value,
123
+ hybridDb,
124
+ });
123
125
  }
124
126
 
125
127
  async function setZScaling(z_scale) {
@@ -184,20 +186,27 @@ export const useHybridViewerStore = defineStore("hybridViewer", () => {
184
186
  return viewerStore.request(viewer_schemas.opengeodeweb_viewer.viewer.render);
185
187
  }
186
188
 
187
- const throttledHoverHighlight = useThrottleFn(
188
- (event) =>
189
- performHoverHighlight(event, {
190
- is_hover_highlight,
191
- genericRenderWindow: genericRenderWindow.value,
192
- viewerStore,
193
- viewer_schemas,
194
- hover_highlight_field_type,
195
- hybridDb,
196
- }),
197
- HOVER_THROTTLE_MS,
198
- );
189
+ const hoverTimeoutRef = ref(undefined);
190
+ const currentHoverId = ref(undefined);
191
+
192
+ const clearHoverData = createClearHoverData(hoverTimeoutRef, hoverData, currentHoverId);
193
+
194
+ const hoverHighlight = createHoverHighlight({
195
+ genericRenderWindow,
196
+ is_hover_highlight,
197
+ viewerStore,
198
+ viewer_schemas,
199
+ hover_highlight_field_type,
200
+ hybridDb,
201
+ hoverData,
202
+ hoverPosition,
203
+ currentHoverId,
204
+ hoverTimeoutRef,
205
+ clearHoverData,
206
+ });
199
207
 
200
208
  function clearHoverHighlight() {
209
+ clearHoverData();
201
210
  performClearHoverHighlight({
202
211
  viewerStore,
203
212
  viewer_schemas,
@@ -220,7 +229,7 @@ export const useHybridViewerStore = defineStore("hybridViewer", () => {
220
229
  viewerStore,
221
230
  viewer_schemas,
222
231
  syncRemoteCamera,
223
- throttledHoverHighlight,
232
+ hoverHighlight,
224
233
  wheelTimeoutMs: WHEEL_TIME_OUT_MS,
225
234
  wheelEventEndTimeout,
226
235
  wheelTimeoutSetter: (timeout) => (wheelEventEndTimeout = timeout),
@@ -266,14 +275,7 @@ export const useHybridViewerStore = defineStore("hybridViewer", () => {
266
275
  }
267
276
 
268
277
  function clear() {
269
- const renderer = genericRenderWindow.value.getRenderer();
270
- for (const actor of renderer.getActors()) {
271
- renderer.removeActor(actor);
272
- }
273
- genericRenderWindow.value.getRenderWindow().render();
274
- for (const id of Object.keys(hybridDb)) {
275
- delete hybridDb[id];
276
- }
278
+ performClear({ genericRenderWindow: genericRenderWindow.value, hybridDb });
277
279
  }
278
280
 
279
281
  return {
@@ -297,6 +299,8 @@ export const useHybridViewerStore = defineStore("hybridViewer", () => {
297
299
  is_hover_highlight,
298
300
  hover_highlight_field_type,
299
301
  clearHoverHighlight,
302
+ hoverData,
303
+ hoverPosition,
300
304
  clear,
301
305
  exportStores,
302
306
  importStores,
@@ -3,6 +3,7 @@ import { defineStore } from "pinia";
3
3
  import { ref, toRaw, watch } from "vue";
4
4
  import { compareSelections } from "@ogw_front/utils/treeview";
5
5
  import { database } from "@ogw_internal/database/database";
6
+
6
7
  const PANEL_WIDTH = 300;
7
8
 
8
9
  export const useTreeviewStore = defineStore("treeview", () => {
@@ -14,6 +14,7 @@ const Configuration = {
14
14
  "type-empty": [0],
15
15
  "type-enum": [2, "always", ["feat", "fix", "perf"]],
16
16
  },
17
+ defaultIgnores: false,
17
18
  };
18
19
 
19
20
  export default Configuration;
@@ -16,6 +16,7 @@ const ACTOR_COLOR = [
16
16
  ];
17
17
  const WHEEL_TIME_OUT_MS = 600;
18
18
  const HOVER_THROTTLE_MS = 50;
19
+ const HOVER_TIMEOUT_MS = 500;
19
20
 
20
21
  const SAMPLE_SIZE = 10;
21
22
  const TOTAL_CHANNELS = 400;
@@ -112,7 +113,7 @@ function performHoverHighlight(event, options) {
112
113
  }
113
114
  const rect = container.getBoundingClientRect();
114
115
  viewerStore.request(
115
- viewer_schemas.opengeodeweb_viewer.viewer.hover_highlight,
116
+ viewer_schemas.opengeodeweb_viewer.viewer.highlight,
116
117
  {
117
118
  x: Math.round(event.clientX - rect.left),
118
119
  y: Math.round(rect.height - (event.clientY - rect.top)),
@@ -127,7 +128,7 @@ function performHoverHighlight(event, options) {
127
128
 
128
129
  function performClearHoverHighlight(options) {
129
130
  const { viewerStore, viewer_schemas, hover_highlight_field_type, hybridDb } = options;
130
- viewerStore.request(viewer_schemas.opengeodeweb_viewer.viewer.hover_highlight, {
131
+ viewerStore.request(viewer_schemas.opengeodeweb_viewer.viewer.highlight, {
131
132
  x: -1,
132
133
  y: -1,
133
134
  field_type: hover_highlight_field_type.value,
@@ -200,7 +201,7 @@ function performSetContainer(options) {
200
201
  viewerStore,
201
202
  viewer_schemas,
202
203
  syncRemoteCamera,
203
- throttledHoverHighlight,
204
+ hoverHighlight,
204
205
  wheelTimeoutMs,
205
206
  wheelEventEndTimeout,
206
207
  wheelTimeoutSetter,
@@ -251,7 +252,7 @@ function performSetContainer(options) {
251
252
  },
252
253
  });
253
254
 
254
- useEventListener(container, "mousemove", throttledHoverHighlight);
255
+ useEventListener(container, "mousemove", hoverHighlight);
255
256
  useEventListener(container, "wheel", () => {
256
257
  is_moving.value = true;
257
258
  if (imageStyle) {
@@ -268,11 +269,43 @@ function performSetContainer(options) {
268
269
  });
269
270
  }
270
271
 
272
+ function performRemoveItem(id, options) {
273
+ const { genericRenderWindow, hybridDb } = options;
274
+ if (!hybridDb[id]) {
275
+ return;
276
+ }
277
+ genericRenderWindow.getRenderer().removeActor(hybridDb[id].actor);
278
+ genericRenderWindow.getRenderWindow().render();
279
+ delete hybridDb[id];
280
+ }
281
+
282
+ function performSetVisibility(id, visibility, options) {
283
+ const { genericRenderWindow, hybridDb } = options;
284
+ if (!hybridDb[id]) {
285
+ return;
286
+ }
287
+ hybridDb[id].actor.setVisibility(visibility);
288
+ genericRenderWindow.getRenderWindow().render();
289
+ }
290
+
291
+ function performClear(options) {
292
+ const { genericRenderWindow, hybridDb } = options;
293
+ const renderer = genericRenderWindow.getRenderer();
294
+ for (const actor of renderer.getActors()) {
295
+ renderer.removeActor(actor);
296
+ }
297
+ genericRenderWindow.getRenderWindow().render();
298
+ for (const id of Object.keys(hybridDb)) {
299
+ delete hybridDb[id];
300
+ }
301
+ }
302
+
271
303
  export {
272
304
  BACKGROUND_COLOR,
273
305
  ACTOR_COLOR,
274
306
  WHEEL_TIME_OUT_MS,
275
307
  HOVER_THROTTLE_MS,
308
+ HOVER_TIMEOUT_MS,
276
309
  computeAverageBrightness,
277
310
  performAddItem,
278
311
  performClearHoverHighlight,
@@ -280,4 +313,7 @@ export {
280
313
  performHoverHighlight,
281
314
  performSetContainer,
282
315
  performSetZScaling,
316
+ performRemoveItem,
317
+ performSetVisibility,
318
+ performClear,
283
319
  };
@@ -0,0 +1,113 @@
1
+ import { HOVER_THROTTLE_MS, HOVER_TIMEOUT_MS, performHoverHighlight } from "./hybrid_viewer";
2
+ import { database } from "@ogw_internal/database/database.js";
3
+
4
+ function createClearHoverData(hoverTimeoutRef, hoverData, currentHoverId) {
5
+ return function clearHoverData() {
6
+ if (hoverTimeoutRef.value) {
7
+ clearTimeout(hoverTimeoutRef.value);
8
+ hoverTimeoutRef.value = undefined;
9
+ }
10
+ hoverData.value = undefined;
11
+ currentHoverId.value = undefined;
12
+ };
13
+ }
14
+
15
+ function createHoverHighlight(options) {
16
+ const {
17
+ genericRenderWindow,
18
+ is_hover_highlight,
19
+ viewerStore,
20
+ viewer_schemas,
21
+ hover_highlight_field_type,
22
+ hybridDb,
23
+ hoverData,
24
+ hoverPosition,
25
+ currentHoverId,
26
+ hoverTimeoutRef,
27
+ clearHoverData,
28
+ } = options;
29
+
30
+ return useThrottleFn((event) => {
31
+ const containerElement = genericRenderWindow.value?.getContainer();
32
+ let relativeMousePosition = { x: 0, y: 0 };
33
+ if (containerElement) {
34
+ const containerRect = containerElement.getBoundingClientRect();
35
+ relativeMousePosition = {
36
+ x: event.clientX - containerRect.left,
37
+ y: event.clientY - containerRect.top,
38
+ };
39
+ } else {
40
+ relativeMousePosition = { x: event.clientX, y: event.clientY };
41
+ }
42
+
43
+ performHoverHighlight(event, {
44
+ is_hover_highlight,
45
+ genericRenderWindow: genericRenderWindow.value,
46
+ viewerStore,
47
+ viewer_schemas,
48
+ hover_highlight_field_type,
49
+ hybridDb,
50
+ onResponse: async (response) => {
51
+ const isResponseValid =
52
+ response && response.id && response.picked_id !== undefined && response.picked_id !== -1;
53
+ if (!is_hover_highlight.value || !isResponseValid) {
54
+ clearHoverData();
55
+ return;
56
+ }
57
+
58
+ const hoverKey = `${response.id}_${response.field_type}_${response.picked_id}`;
59
+ if (currentHoverId.value === hoverKey) {
60
+ return;
61
+ }
62
+
63
+ if (hoverTimeoutRef.value) {
64
+ clearTimeout(hoverTimeoutRef.value);
65
+ hoverTimeoutRef.value = undefined;
66
+ }
67
+
68
+ hoverData.value = undefined;
69
+ currentHoverId.value = hoverKey;
70
+
71
+ let componentInfo = undefined;
72
+ let modelName = undefined;
73
+
74
+ const modelRecord = await database.data.get(response.id);
75
+ if (modelRecord) {
76
+ modelName = modelRecord.name;
77
+ }
78
+
79
+ if (response.geode_id) {
80
+ const component = await database.model_components
81
+ .where("[id+geode_id]")
82
+ .equals([response.id, response.geode_id])
83
+ .first();
84
+ if (component) {
85
+ componentInfo = {
86
+ name: component.name,
87
+ id: component.geode_id,
88
+ type: component.type,
89
+ };
90
+ }
91
+ }
92
+
93
+ const newHoverData = {
94
+ modelId: response.id,
95
+ modelName,
96
+ blockName: response.geode_id,
97
+ pickedId: response.picked_id,
98
+ fieldType: response.field_type,
99
+ component: componentInfo,
100
+ attributes: response.attributes || {},
101
+ };
102
+
103
+ hoverTimeoutRef.value = setTimeout(() => {
104
+ hoverPosition.value = relativeMousePosition;
105
+ hoverData.value = newHoverData;
106
+ hoverTimeoutRef.value = undefined;
107
+ }, HOVER_TIMEOUT_MS);
108
+ },
109
+ });
110
+ }, HOVER_THROTTLE_MS);
111
+ }
112
+
113
+ export { createClearHoverData, createHoverHighlight };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@geode/opengeodeweb-front",
3
- "version": "10.18.2-rc.1",
3
+ "version": "10.19.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": {