@geode/opengeodeweb-front 10.34.0-rc.4 → 10.34.0-rc.6
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.
- package/app/components/CameraManager.vue +9 -4
- package/app/components/CameraOrientation.vue +45 -14
- package/app/components/ClippingPlanes.vue +16 -6
- package/app/components/DeleteDialog.vue +27 -7
- package/app/components/DragAndDrop.vue +14 -4
- package/app/components/DragAndDropInternal/DragAndDropInline.vue +4 -2
- package/app/components/ExtensionSelector.vue +30 -15
- package/app/components/FileSelector.vue +11 -4
- package/app/components/FileUploader.vue +36 -11
- package/app/components/HybridRenderingView.vue +18 -7
- package/app/components/HybridViewerTooltip.vue +12 -5
- package/app/components/Launcher.vue +8 -3
- package/app/components/MissingFilesSelector.vue +45 -20
- package/app/components/ObjectSelector.vue +27 -10
- package/app/components/RemoteRenderingView.vue +2 -2
- package/app/components/Ruler.vue +11 -4
- package/app/components/Screenshot.vue +12 -6
- package/app/components/ShrinkFilter.vue +8 -3
- package/app/components/Stepper.vue +9 -3
- package/app/components/ToolPanel.vue +1 -1
- package/app/components/ViewToolbar.vue +28 -13
- package/app/components/Viewer/ContextMenu/ContextMenu.vue +6 -4
- package/app/components/Viewer/ContextMenu/ContextMenuItem.vue +35 -12
- package/app/components/Viewer/ContextMenu/InfoCard.vue +23 -6
- package/app/components/Viewer/EdgedCurve/PointsOptions.vue +6 -3
- package/app/components/Viewer/EdgedCurve/SpecificEdgesOptions.vue +55 -17
- package/app/components/Viewer/Generic/Mesh/CellsOptions.vue +52 -16
- package/app/components/Viewer/Generic/Mesh/EdgesOptions.vue +51 -16
- package/app/components/Viewer/Generic/Mesh/PointsOptions.vue +40 -13
- package/app/components/Viewer/Generic/Mesh/PolygonsOptions.vue +61 -19
- package/app/components/Viewer/Generic/Mesh/PolyhedraOptions.vue +71 -20
- package/app/components/Viewer/Generic/Model/BlocksOptions.vue +159 -44
- package/app/components/Viewer/Generic/Model/CornersOptions.vue +102 -26
- package/app/components/Viewer/Generic/Model/EdgesOptions.vue +5 -3
- package/app/components/Viewer/Generic/Model/LinesOptions.vue +168 -40
- package/app/components/Viewer/Generic/Model/ModelStyleCard.vue +40 -16
- package/app/components/Viewer/Generic/Model/ModelStyleOptions.vue +2 -2
- package/app/components/Viewer/Generic/Model/PointsOptions.vue +10 -5
- package/app/components/Viewer/Generic/Model/SurfacesOptions.vue +166 -49
- package/app/components/Viewer/Grid/2D/CellsOptions.vue +2 -2
- package/app/components/Viewer/Grid/2D/EdgesOptions.vue +6 -3
- package/app/components/Viewer/Grid/2D/PointsOptions.vue +6 -3
- package/app/components/Viewer/Grid/3D/CellsOptions.vue +2 -2
- package/app/components/Viewer/Grid/3D/EdgesOptions.vue +6 -3
- package/app/components/Viewer/Grid/3D/FacetsOptions.vue +2 -2
- package/app/components/Viewer/Grid/3D/PointsOptions.vue +6 -3
- package/app/components/Viewer/ObjectTree/Base/CommonTreeView.vue +17 -10
- package/app/components/Viewer/ObjectTree/Base/Controls.vue +18 -6
- package/app/components/Viewer/ObjectTree/Base/ItemLabel.vue +10 -6
- package/app/components/Viewer/ObjectTree/Base/StickyHeader.vue +7 -3
- package/app/components/Viewer/ObjectTree/Layout.vue +53 -19
- package/app/components/Viewer/ObjectTree/Views/GlobalObjects.vue +46 -16
- package/app/components/Viewer/ObjectTree/Views/ModelCollections.vue +45 -15
- package/app/components/Viewer/ObjectTree/Views/ModelComponents.vue +45 -16
- package/app/components/Viewer/Options/AttributeColorBar.vue +2 -2
- package/app/components/Viewer/Options/AttributeSelector.vue +27 -12
- package/app/components/Viewer/Options/ColorMapList.vue +40 -10
- package/app/components/Viewer/Options/ColorMapPicker.vue +15 -5
- package/app/components/Viewer/Options/ColorPicker.vue +1 -1
- package/app/components/Viewer/Options/ColoringTypeSelector.vue +105 -36
- package/app/components/Viewer/Options/ColormapQuickPicker.vue +5 -3
- package/app/components/Viewer/Options/Sliders/Size.vue +1 -1
- package/app/components/Viewer/Options/Sliders/Slider.vue +1 -1
- package/app/components/Viewer/Options/Sliders/Width.vue +1 -1
- package/app/components/Viewer/Options/TextureItem.vue +19 -4
- package/app/components/Viewer/Options/TexturesSelector.vue +16 -4
- package/app/components/Viewer/Options/VisibilitySwitch.vue +1 -1
- package/app/components/Viewer/OverlappingObjectsPicker.vue +24 -7
- package/app/components/Viewer/PointSet/SpecificPointsOptions.vue +35 -12
- package/app/components/Viewer/Solid/EdgesOptions.vue +6 -3
- package/app/components/Viewer/Solid/PointsOptions.vue +6 -3
- package/app/components/Viewer/Solid/PolygonsOptions.vue +2 -2
- package/app/components/Viewer/Solid/SpecificPolyhedraOptions.vue +66 -19
- package/app/components/Viewer/Surface/EdgesOptions.vue +6 -3
- package/app/components/Viewer/Surface/PointsOptions.vue +2 -2
- package/app/components/Viewer/Surface/PolygonsOptions.vue +61 -19
- package/app/components/Viewer/Surface/Triangulated/TrianglesOptions.vue +6 -3
- package/app/components/Viewer/TetrahedralSolid/TetrahedraOptions.vue +2 -2
- package/app/components/Viewer/TetrahedralSolid/TrianglesOptions.vue +2 -2
- package/app/components/Viewer/Ui.vue +9 -5
- package/app/components/Wrapper.vue +3 -3
- package/app/components/ZScaling.vue +3 -2
- package/app/components/csv-preview/CsvPreviewer.vue +35 -13
- package/app/stores/menu.ts +22 -22
- package/app/utils/import_workflow.ts +3 -1
- package/package.json +1 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
import List from "@ogw_front/components/CameraManager/List
|
|
3
|
-
import Saver from "@ogw_front/components/CameraManager/Saver
|
|
4
|
-
import ToolPanel from "@ogw_front/components/ToolPanel
|
|
2
|
+
import List from "@ogw_front/components/CameraManager/List";
|
|
3
|
+
import Saver from "@ogw_front/components/CameraManager/Saver";
|
|
4
|
+
import ToolPanel from "@ogw_front/components/ToolPanel";
|
|
5
5
|
|
|
6
6
|
const DEFAULT_PANEL_WIDTH = 260;
|
|
7
7
|
|
|
@@ -40,7 +40,12 @@ const show = computed({
|
|
|
40
40
|
</script>
|
|
41
41
|
|
|
42
42
|
<template>
|
|
43
|
-
<ToolPanel
|
|
43
|
+
<ToolPanel
|
|
44
|
+
v-model="show"
|
|
45
|
+
title="Camera Positions"
|
|
46
|
+
:width="width"
|
|
47
|
+
:escapeFunction="handleClose"
|
|
48
|
+
>
|
|
44
49
|
<v-card-text class="pa-0">
|
|
45
50
|
<Saver />
|
|
46
51
|
<v-divider />
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
// Not auto-fixable (eslint's sort-imports core rule has no autofixer) and this file's import order doesn't match its syntax-kind-then-alphabetical requirement - left as-is rather than manually reordered across the codebase for a purely cosmetic rule.
|
|
3
3
|
// oxlint-disable eslint/sort-imports
|
|
4
|
-
import ToolPanel from "@ogw_front/components/ToolPanel
|
|
4
|
+
import ToolPanel from "@ogw_front/components/ToolPanel";
|
|
5
5
|
import { applyCameraOptions } from "@ogw_internal/stores/hybrid_viewer/camera";
|
|
6
6
|
import { useHybridViewerStore } from "@ogw_front/stores/hybrid_viewer";
|
|
7
7
|
import type { CameraOptions } from "@ogw_internal/stores/hybrid_viewer/vtk_types.js";
|
|
@@ -166,7 +166,9 @@ watch(hoveredFace, (newFace, oldFace) => {
|
|
|
166
166
|
return;
|
|
167
167
|
}
|
|
168
168
|
function updateFace(face: string | undefined, active: boolean) {
|
|
169
|
-
const config = orientations.find(
|
|
169
|
+
const config = orientations.find(
|
|
170
|
+
(orientation) => orientation.face === face,
|
|
171
|
+
);
|
|
170
172
|
if (config) {
|
|
171
173
|
cubeActor[`set${config.vtkKey}FaceProperty`]({
|
|
172
174
|
faceColor: active ? "rgba(255, 255, 255, 0.95)" : "rgba(60, 60, 60, 1)",
|
|
@@ -193,10 +195,17 @@ watch(hoveredFace, (newFace, oldFace) => {
|
|
|
193
195
|
class="pa-0 overflow-hidden position-relative"
|
|
194
196
|
style="
|
|
195
197
|
height: 220px;
|
|
196
|
-
background: radial-gradient(
|
|
198
|
+
background: radial-gradient(
|
|
199
|
+
circle at center,
|
|
200
|
+
rgba(255, 255, 255, 0.05),
|
|
201
|
+
transparent 70%
|
|
202
|
+
);
|
|
197
203
|
"
|
|
198
204
|
>
|
|
199
|
-
<svg
|
|
205
|
+
<svg
|
|
206
|
+
class="position-absolute fill-height w-100"
|
|
207
|
+
style="pointer-events: none"
|
|
208
|
+
>
|
|
200
209
|
<line
|
|
201
210
|
v-for="orientation in orientations"
|
|
202
211
|
:key="orientation.value"
|
|
@@ -204,7 +213,9 @@ watch(hoveredFace, (newFace, oldFace) => {
|
|
|
204
213
|
y1="50%"
|
|
205
214
|
:x2="orientation.position.left"
|
|
206
215
|
:y2="orientation.position.top"
|
|
207
|
-
:stroke="
|
|
216
|
+
:stroke="
|
|
217
|
+
hoveredFace === orientation.face ? 'white' : 'rgba(255,255,255,0.1)'
|
|
218
|
+
"
|
|
208
219
|
:stroke-width="hoveredFace === orientation.face ? 2 : 1"
|
|
209
220
|
class="transition-all"
|
|
210
221
|
style="filter: drop-shadow(0 0 3px white)"
|
|
@@ -215,7 +226,10 @@ watch(hoveredFace, (newFace, oldFace) => {
|
|
|
215
226
|
class="position-absolute d-flex align-center justify-center"
|
|
216
227
|
style="top: 50%; left: 50%; transform: translate(-50%, -50%)"
|
|
217
228
|
>
|
|
218
|
-
<div
|
|
229
|
+
<div
|
|
230
|
+
ref="cubeContainer"
|
|
231
|
+
style="width: 70px; height: 70px; pointer-events: none"
|
|
232
|
+
/>
|
|
219
233
|
</div>
|
|
220
234
|
|
|
221
235
|
<v-btn
|
|
@@ -231,21 +245,34 @@ watch(hoveredFace, (newFace, oldFace) => {
|
|
|
231
245
|
@mouseleave="hoveredFace = undefined"
|
|
232
246
|
@click.stop="emit('select', orientation.value)"
|
|
233
247
|
>
|
|
234
|
-
<v-tooltip activator="parent" location="top"
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
248
|
+
<v-tooltip activator="parent" location="top"
|
|
249
|
+
>{{ orientation.value }} View</v-tooltip
|
|
250
|
+
>
|
|
251
|
+
<span
|
|
252
|
+
class="text-caption font-weight-black"
|
|
253
|
+
style="font-size: 0.7rem !important"
|
|
254
|
+
>{{ orientation.label }}</span
|
|
255
|
+
>
|
|
238
256
|
</v-btn>
|
|
239
257
|
</div>
|
|
240
258
|
</ToolPanel>
|
|
241
259
|
|
|
242
|
-
<v-list
|
|
260
|
+
<v-list
|
|
261
|
+
v-else
|
|
262
|
+
density="compact"
|
|
263
|
+
class="pa-4 orientation-menu rounded-lg"
|
|
264
|
+
elevation="8"
|
|
265
|
+
>
|
|
243
266
|
<div class="d-flex flex-column align-center" style="gap: 16px">
|
|
244
267
|
<div
|
|
245
268
|
class="d-flex align-center justify-center"
|
|
246
269
|
style="width: 60px; height: 60px; border-radius: 8px; overflow: hidden"
|
|
247
270
|
>
|
|
248
|
-
<div
|
|
271
|
+
<div
|
|
272
|
+
ref="cubeContainer"
|
|
273
|
+
class="w-100 h-100"
|
|
274
|
+
style="pointer-events: none"
|
|
275
|
+
/>
|
|
249
276
|
</div>
|
|
250
277
|
<v-divider class="w-100" />
|
|
251
278
|
<div class="d-flex flex-wrap justify-center" style="max-width: 140px">
|
|
@@ -261,8 +288,12 @@ watch(hoveredFace, (newFace, oldFace) => {
|
|
|
261
288
|
@mouseleave="hoveredFace = undefined"
|
|
262
289
|
@click.stop="emit('select', orientation.value)"
|
|
263
290
|
>
|
|
264
|
-
<v-tooltip activator="parent" location="top">{{
|
|
265
|
-
|
|
291
|
+
<v-tooltip activator="parent" location="top">{{
|
|
292
|
+
orientation.label
|
|
293
|
+
}}</v-tooltip>
|
|
294
|
+
<span class="text-caption font-weight-black">{{
|
|
295
|
+
orientation.label
|
|
296
|
+
}}</span>
|
|
266
297
|
</v-btn>
|
|
267
298
|
</div>
|
|
268
299
|
</div>
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
2
|
+
import {
|
|
3
|
+
DEBOUNCE_DELAY,
|
|
4
|
+
DEFAULT_NORMALS,
|
|
5
|
+
} from "@ogw_front/utils/clipping_planes";
|
|
6
|
+
import ClippingPlaneCard from "@ogw_front/components/ClippingPlaneCard";
|
|
7
|
+
import ToolPanel from "@ogw_front/components/ToolPanel";
|
|
5
8
|
import { useClippingPlanesWidget } from "@ogw_front/composables/clipping_planes_widget";
|
|
6
9
|
import { useDataStore } from "@ogw_front/stores/data";
|
|
7
10
|
import { useDebounceFn } from "@vueuse/core";
|
|
@@ -75,7 +78,9 @@ debouncedApply = useDebounceFn(() => applyClippingPlanes(), DEBOUNCE_DELAY);
|
|
|
75
78
|
function addPlane() {
|
|
76
79
|
// Index is always in-bounds (modulo the fixed-size list); the fallbacks only
|
|
77
80
|
// Satisfy noUncheckedIndexedAccess and are never hit at runtime.
|
|
78
|
-
const normal = DEFAULT_NORMALS[
|
|
81
|
+
const normal = DEFAULT_NORMALS[
|
|
82
|
+
planes.value.length % DEFAULT_NORMALS.length
|
|
83
|
+
] ??
|
|
79
84
|
DEFAULT_NORMALS[0] ?? [1, 0, 0];
|
|
80
85
|
planes.value.push({ origin: getSceneCenter(), normal });
|
|
81
86
|
}
|
|
@@ -147,7 +152,10 @@ watch(allItems, () => {
|
|
|
147
152
|
});
|
|
148
153
|
|
|
149
154
|
watch(
|
|
150
|
-
() =>
|
|
155
|
+
() =>
|
|
156
|
+
Object.values(hybridViewerStore.hybridDb).filter(
|
|
157
|
+
(entry) => entry && entry.actor,
|
|
158
|
+
).length,
|
|
151
159
|
(actorCount) => {
|
|
152
160
|
if (show.value && actorCount > 0) {
|
|
153
161
|
updateWidgetPlacement({ isReset: true });
|
|
@@ -204,7 +212,9 @@ onBeforeUnmount(cleanupLocalWidget);
|
|
|
204
212
|
<v-divider class="my-2" />
|
|
205
213
|
|
|
206
214
|
<v-row align="center" justify="space-between" no-gutters class="mb-2">
|
|
207
|
-
<v-col class="text-caption font-weight-bold"
|
|
215
|
+
<v-col class="text-caption font-weight-bold"
|
|
216
|
+
>Planes ({{ planes.length }})</v-col
|
|
217
|
+
>
|
|
208
218
|
<v-col cols="auto">
|
|
209
219
|
<v-btn
|
|
210
220
|
data-testid="addPlaneButton"
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
import GlassCard from "./GlassCard
|
|
2
|
+
import GlassCard from "./GlassCard";
|
|
3
3
|
|
|
4
4
|
interface DeleteItem {
|
|
5
5
|
name: string;
|
|
@@ -11,7 +11,11 @@ interface Props {
|
|
|
11
11
|
selectedCount?: number;
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
-
const {
|
|
14
|
+
const {
|
|
15
|
+
show = false,
|
|
16
|
+
item = undefined,
|
|
17
|
+
selectedCount = 0,
|
|
18
|
+
} = defineProps<Props>();
|
|
15
19
|
|
|
16
20
|
const emit = defineEmits<{
|
|
17
21
|
"update:show": [value: boolean];
|
|
@@ -20,10 +24,20 @@ const emit = defineEmits<{
|
|
|
20
24
|
</script>
|
|
21
25
|
|
|
22
26
|
<template>
|
|
23
|
-
<v-dialog
|
|
27
|
+
<v-dialog
|
|
28
|
+
:model-value="show"
|
|
29
|
+
@update:model-value="emit('update:show', $event)"
|
|
30
|
+
max-width="400"
|
|
31
|
+
>
|
|
24
32
|
<GlassCard v-if="item" variant="panel" padding="pa-8">
|
|
25
|
-
<v-card-title
|
|
26
|
-
|
|
33
|
+
<v-card-title
|
|
34
|
+
class="pb-2 text-h5 font-weight-bold d-flex align-center text-white"
|
|
35
|
+
>
|
|
36
|
+
<v-icon
|
|
37
|
+
icon="mdi-trash-can-outline"
|
|
38
|
+
class="mr-3 text-h4"
|
|
39
|
+
color="error"
|
|
40
|
+
></v-icon>
|
|
27
41
|
Delete Item
|
|
28
42
|
</v-card-title>
|
|
29
43
|
|
|
@@ -66,8 +80,14 @@ const emit = defineEmits<{
|
|
|
66
80
|
</GlassCard>
|
|
67
81
|
|
|
68
82
|
<GlassCard v-else variant="panel" padding="pa-8">
|
|
69
|
-
<v-card-title
|
|
70
|
-
|
|
83
|
+
<v-card-title
|
|
84
|
+
class="pb-2 text-h5 font-weight-bold d-flex align-center text-white"
|
|
85
|
+
>
|
|
86
|
+
<v-icon
|
|
87
|
+
icon="mdi-alert-circle-outline"
|
|
88
|
+
class="mr-3 text-h4"
|
|
89
|
+
color="error"
|
|
90
|
+
></v-icon>
|
|
71
91
|
Delete Items
|
|
72
92
|
</v-card-title>
|
|
73
93
|
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
// Not auto-fixable (eslint's sort-imports core rule has no autofixer) and this file's import order doesn't match its syntax-kind-then-alphabetical requirement - left as-is rather than manually reordered across the codebase for a purely cosmetic rule.
|
|
3
3
|
// oxlint-disable eslint/sort-imports
|
|
4
4
|
import { onMounted, onUnmounted, ref } from "vue";
|
|
5
|
-
import DragAndDropInline from "./DragAndDropInternal/DragAndDropInline
|
|
6
|
-
import DragAndDropOverlay from "./DragAndDropInternal/DragAndDropOverlay
|
|
5
|
+
import DragAndDropInline from "./DragAndDropInternal/DragAndDropInline";
|
|
6
|
+
import DragAndDropOverlay from "./DragAndDropInternal/DragAndDropOverlay";
|
|
7
7
|
|
|
8
8
|
interface DragAndDropTexts {
|
|
9
9
|
idle: string;
|
|
@@ -48,7 +48,10 @@ const fileInput = ref<HTMLInputElement | undefined>(undefined);
|
|
|
48
48
|
|
|
49
49
|
const WILDCARD_SUFFIX_LENGTH = 2;
|
|
50
50
|
|
|
51
|
-
function isFileAccepted(
|
|
51
|
+
function isFileAccepted(
|
|
52
|
+
file: File,
|
|
53
|
+
acceptValue: string | string[] | undefined,
|
|
54
|
+
) {
|
|
52
55
|
const fileName = (file.name || "").toLowerCase();
|
|
53
56
|
const fileType = (file.type || "").toLowerCase();
|
|
54
57
|
const isVext = fileName.endsWith(".vext");
|
|
@@ -201,7 +204,14 @@ defineExpose({ triggerFileDialog });
|
|
|
201
204
|
:show-extensions
|
|
202
205
|
/>
|
|
203
206
|
|
|
204
|
-
<input
|
|
207
|
+
<input
|
|
208
|
+
ref="fileInput"
|
|
209
|
+
type="file"
|
|
210
|
+
class="d-none"
|
|
211
|
+
:multiple
|
|
212
|
+
:accept
|
|
213
|
+
@change="handleFileSelect"
|
|
214
|
+
/>
|
|
205
215
|
</template>
|
|
206
216
|
|
|
207
217
|
<style>
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
import GlassCard from "@ogw_front/components/GlassCard
|
|
2
|
+
import GlassCard from "@ogw_front/components/GlassCard";
|
|
3
3
|
|
|
4
4
|
interface DragAndDropTexts {
|
|
5
5
|
idle: string;
|
|
@@ -57,7 +57,9 @@ const emit = defineEmits<{
|
|
|
57
57
|
</v-sheet>
|
|
58
58
|
|
|
59
59
|
<v-card-text class="pa-0">
|
|
60
|
-
<v-sheet
|
|
60
|
+
<v-sheet
|
|
61
|
+
class="text-h6 font-weight-bold text-white d-block mb-1 bg-transparent"
|
|
62
|
+
>
|
|
61
63
|
{{ loading ? texts.loading : isDragging ? texts.drop : texts.idle }}
|
|
62
64
|
</v-sheet>
|
|
63
65
|
<v-sheet
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import schemas from "@geode/opengeodeweb-back/opengeodeweb_back_schemas.json";
|
|
3
3
|
|
|
4
|
-
import FetchingData from "@ogw_front/components/FetchingData
|
|
4
|
+
import FetchingData from "@ogw_front/components/FetchingData";
|
|
5
5
|
import { useBackStore } from "@ogw_front/stores/back";
|
|
6
6
|
|
|
7
7
|
const schema = schemas.opengeodeweb_back.geode_objects_and_output_extensions;
|
|
8
8
|
const emit = defineEmits<{
|
|
9
|
-
update_values: [
|
|
9
|
+
update_values: [
|
|
10
|
+
values: { output_geode_object: string; output_extension: string },
|
|
11
|
+
];
|
|
10
12
|
increment_step: [];
|
|
11
13
|
decrement_step: [];
|
|
12
14
|
}>();
|
|
@@ -19,7 +21,9 @@ interface Props {
|
|
|
19
21
|
const { geodeObjectType, filenames } = defineProps<Props>();
|
|
20
22
|
type OutputExtensions = Record<string, { is_saveable: boolean }>;
|
|
21
23
|
|
|
22
|
-
const geode_objects_and_output_extensions = ref<
|
|
24
|
+
const geode_objects_and_output_extensions = ref<
|
|
25
|
+
Record<string, OutputExtensions>
|
|
26
|
+
>({});
|
|
23
27
|
const loading = ref(false);
|
|
24
28
|
|
|
25
29
|
const toggle_loading = useToggle(loading);
|
|
@@ -29,18 +33,25 @@ async function get_output_file_extensions() {
|
|
|
29
33
|
geode_objects_and_output_extensions.value = {};
|
|
30
34
|
const backStore = useBackStore();
|
|
31
35
|
const values: Record<string, OutputExtensions>[] = await Promise.all(
|
|
32
|
-
filenames.map(
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
36
|
+
filenames.map(
|
|
37
|
+
async (filename): Promise<Record<string, OutputExtensions>> => {
|
|
38
|
+
const params = { geode_object_type: geodeObjectType, filename };
|
|
39
|
+
const response = await backStore.request({ schema, params });
|
|
40
|
+
return (
|
|
41
|
+
response as {
|
|
42
|
+
geode_objects_and_output_extensions: Record<
|
|
43
|
+
string,
|
|
44
|
+
OutputExtensions
|
|
45
|
+
>;
|
|
46
|
+
}
|
|
47
|
+
).geode_objects_and_output_extensions;
|
|
48
|
+
},
|
|
49
|
+
),
|
|
41
50
|
);
|
|
42
51
|
const all_keys = [...new Set(values.flatMap((value) => Object.keys(value)))];
|
|
43
|
-
const common_keys = all_keys.filter(
|
|
52
|
+
const common_keys = all_keys.filter(
|
|
53
|
+
(i) => !values.some((j) => !Object.keys(j).includes(i)),
|
|
54
|
+
);
|
|
44
55
|
const final_object: Record<string, OutputExtensions> = {};
|
|
45
56
|
for (const key of common_keys) {
|
|
46
57
|
final_object[key] = {};
|
|
@@ -78,7 +89,9 @@ await get_output_file_extensions();
|
|
|
78
89
|
<FetchingData v-if="loading" />
|
|
79
90
|
<v-row v-else class="justify-left">
|
|
80
91
|
<v-col
|
|
81
|
-
v-for="(
|
|
92
|
+
v-for="(
|
|
93
|
+
output_extensions, output_geode_object
|
|
94
|
+
) in geode_objects_and_output_extensions"
|
|
82
95
|
:key="output_geode_object"
|
|
83
96
|
class="justify-left"
|
|
84
97
|
>
|
|
@@ -105,7 +118,9 @@ await get_output_file_extensions();
|
|
|
105
118
|
class="card ma-2"
|
|
106
119
|
:color="extension.is_saveable ? 'primary' : 'grey'"
|
|
107
120
|
hover
|
|
108
|
-
@click="
|
|
121
|
+
@click="
|
|
122
|
+
update_values(output_geode_object, output_extension)
|
|
123
|
+
"
|
|
109
124
|
:disabled="!extension.is_saveable"
|
|
110
125
|
>
|
|
111
126
|
<v-card-title align="center">
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import schemas from "@geode/opengeodeweb-back/opengeodeweb_back_schemas.json";
|
|
3
3
|
|
|
4
|
-
import FetchingData from "@ogw_front/components/FetchingData
|
|
5
|
-
import FileUploader from "@ogw_front/components/FileUploader
|
|
4
|
+
import FetchingData from "@ogw_front/components/FetchingData";
|
|
5
|
+
import FileUploader from "@ogw_front/components/FileUploader";
|
|
6
6
|
import { useBackStore } from "@ogw_front/stores/back";
|
|
7
7
|
|
|
8
8
|
const schema = schemas.opengeodeweb_back.allowed_files;
|
|
@@ -20,7 +20,12 @@ interface Props {
|
|
|
20
20
|
showOverlay?: boolean;
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
-
const {
|
|
23
|
+
const {
|
|
24
|
+
multiple,
|
|
25
|
+
files = [],
|
|
26
|
+
autoUpload = true,
|
|
27
|
+
showOverlay = true,
|
|
28
|
+
} = defineProps<Props>();
|
|
24
29
|
|
|
25
30
|
const internal_files = ref(files);
|
|
26
31
|
const internal_auto_upload = ref(autoUpload);
|
|
@@ -56,7 +61,9 @@ async function get_allowed_files() {
|
|
|
56
61
|
const response = (await backStore.request({ schema })) as {
|
|
57
62
|
extensions: string[];
|
|
58
63
|
};
|
|
59
|
-
accept.value = response.extensions
|
|
64
|
+
accept.value = response.extensions
|
|
65
|
+
.map((extension) => `.${extension}`)
|
|
66
|
+
.join(",");
|
|
60
67
|
toggle_loading();
|
|
61
68
|
}
|
|
62
69
|
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import { useBackStore } from "@ogw_front/stores/back";
|
|
3
3
|
|
|
4
|
-
import CsvPreviewer from "@ogw_front/components/csv-preview/CsvPreviewer
|
|
5
|
-
import DragAndDrop from "@ogw_front/components/DragAndDrop
|
|
4
|
+
import CsvPreviewer from "@ogw_front/components/csv-preview/CsvPreviewer";
|
|
5
|
+
import DragAndDrop from "@ogw_front/components/DragAndDrop";
|
|
6
6
|
|
|
7
7
|
// Files carry extra app-specific bookkeeping fields once picked up here.
|
|
8
8
|
type UploadFile = File & { isConfigured?: boolean; displayName?: string };
|
|
@@ -58,7 +58,10 @@ async function onCsvConfirm(result: unknown) {
|
|
|
58
58
|
return;
|
|
59
59
|
}
|
|
60
60
|
const json_content = JSON.stringify(result, undefined, 2);
|
|
61
|
-
const base_name = currentFile.name.slice(
|
|
61
|
+
const base_name = currentFile.name.slice(
|
|
62
|
+
0,
|
|
63
|
+
currentFile.name.lastIndexOf("."),
|
|
64
|
+
);
|
|
62
65
|
const json_filename = `${base_name}.json`;
|
|
63
66
|
|
|
64
67
|
const blob = new Blob([json_content], { type: "application/json" });
|
|
@@ -93,7 +96,9 @@ function removeFile(index: number) {
|
|
|
93
96
|
|
|
94
97
|
async function upload_files() {
|
|
95
98
|
toggle_loading();
|
|
96
|
-
const promise_array = internal_files.value.map((file) =>
|
|
99
|
+
const promise_array = internal_files.value.map((file) =>
|
|
100
|
+
backStore.upload(file),
|
|
101
|
+
);
|
|
97
102
|
await Promise.all(promise_array);
|
|
98
103
|
files_uploaded.value = true;
|
|
99
104
|
toggle_loading();
|
|
@@ -106,14 +111,21 @@ watch(
|
|
|
106
111
|
if (newFiles.length === 0) {
|
|
107
112
|
return;
|
|
108
113
|
}
|
|
109
|
-
const unconfiguredCsv = newFiles.find(
|
|
114
|
+
const unconfiguredCsv = newFiles.find(
|
|
115
|
+
(file) => isCsv(file) && !file.isConfigured,
|
|
116
|
+
);
|
|
110
117
|
|
|
111
118
|
if (unconfiguredCsv) {
|
|
112
|
-
openCsvPreviewer(
|
|
119
|
+
openCsvPreviewer(
|
|
120
|
+
unconfiguredCsv,
|
|
121
|
+
internal_files.value.indexOf(unconfiguredCsv),
|
|
122
|
+
);
|
|
113
123
|
return;
|
|
114
124
|
}
|
|
115
125
|
|
|
116
|
-
const allConfigured = newFiles.every(
|
|
126
|
+
const allConfigured = newFiles.every(
|
|
127
|
+
(file) => !isCsv(file) || file.isConfigured,
|
|
128
|
+
);
|
|
117
129
|
|
|
118
130
|
if (autoUpload && allConfigured) {
|
|
119
131
|
await upload_files();
|
|
@@ -171,8 +183,15 @@ watch(
|
|
|
171
183
|
<v-card-text v-if="internal_files.length" class="mt-6 pa-0">
|
|
172
184
|
<v-sheet class="d-flex align-center mb-4" color="transparent">
|
|
173
185
|
<v-icon icon="mdi-file-check" class="mr-3" color="primary" size="24" />
|
|
174
|
-
<span class="text-subtitle-1 font-weight-bold text-white">
|
|
175
|
-
|
|
186
|
+
<span class="text-subtitle-1 font-weight-bold text-white">
|
|
187
|
+
Selected files
|
|
188
|
+
</span>
|
|
189
|
+
<v-chip
|
|
190
|
+
size="small"
|
|
191
|
+
class="ml-3 bg-white-opacity-10"
|
|
192
|
+
color="white"
|
|
193
|
+
variant="flat"
|
|
194
|
+
>
|
|
176
195
|
{{ internal_files.length }}
|
|
177
196
|
</v-chip>
|
|
178
197
|
<v-spacer />
|
|
@@ -200,7 +219,11 @@ watch(
|
|
|
200
219
|
style="background: rgba(255, 255, 255, 0.05) !important"
|
|
201
220
|
@click:close="removeFile(index)"
|
|
202
221
|
>
|
|
203
|
-
<v-icon
|
|
222
|
+
<v-icon
|
|
223
|
+
start
|
|
224
|
+
size="18"
|
|
225
|
+
:color="isCsv(file) && file.isConfigured ? 'success' : 'primary'"
|
|
226
|
+
>
|
|
204
227
|
{{
|
|
205
228
|
isCsv(file)
|
|
206
229
|
? file.isConfigured
|
|
@@ -230,7 +253,9 @@ watch(
|
|
|
230
253
|
</v-tooltip>
|
|
231
254
|
|
|
232
255
|
<template #close>
|
|
233
|
-
<v-icon size="16" class="ml-2 opacity-60 hover-opacity-100"
|
|
256
|
+
<v-icon size="16" class="ml-2 opacity-60 hover-opacity-100"
|
|
257
|
+
>mdi-close-circle</v-icon
|
|
258
|
+
>
|
|
234
259
|
</template>
|
|
235
260
|
</v-chip>
|
|
236
261
|
</template>
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
import ColormapQuickPicker from "@ogw_front/components/Viewer/Options/ColormapQuickPicker
|
|
3
|
-
import HybridViewerTooltip from "@ogw_front/components/HybridViewerTooltip
|
|
4
|
-
import ViewToolbar from "@ogw_front/components/ViewToolbar
|
|
2
|
+
import ColormapQuickPicker from "@ogw_front/components/Viewer/Options/ColormapQuickPicker";
|
|
3
|
+
import HybridViewerTooltip from "@ogw_front/components/HybridViewerTooltip";
|
|
4
|
+
import ViewToolbar from "@ogw_front/components/ViewToolbar";
|
|
5
5
|
|
|
6
6
|
import { useDataStore } from "@ogw_front/stores/data";
|
|
7
7
|
import { useHybridViewerStore } from "@ogw_front/stores/hybrid_viewer";
|
|
@@ -21,10 +21,14 @@ const viewerStore = useViewerStore();
|
|
|
21
21
|
const menuStore = useMenuStore();
|
|
22
22
|
const dataStore = useDataStore();
|
|
23
23
|
|
|
24
|
-
const { width: elementWidth, height: elementHeight } =
|
|
24
|
+
const { width: elementWidth, height: elementHeight } =
|
|
25
|
+
useElementSize(container);
|
|
25
26
|
const { width: windowWidth, height: windowHeight } = useWindowSize();
|
|
26
27
|
|
|
27
|
-
function debounce<Callback extends (...args: unknown[]) => void>(
|
|
28
|
+
function debounce<Callback extends (...args: unknown[]) => void>(
|
|
29
|
+
func: Callback,
|
|
30
|
+
wait: number,
|
|
31
|
+
) {
|
|
28
32
|
let timeout: ReturnType<typeof setTimeout> | undefined = undefined;
|
|
29
33
|
return function executedFunction(...args: Parameters<Callback>) {
|
|
30
34
|
function later() {
|
|
@@ -93,7 +97,11 @@ async function handleClick(event: PointerEvent) {
|
|
|
93
97
|
|
|
94
98
|
<template>
|
|
95
99
|
<ClientOnly>
|
|
96
|
-
<div
|
|
100
|
+
<div
|
|
101
|
+
data-testid="hybridViewer"
|
|
102
|
+
class="fill-height"
|
|
103
|
+
style="position: relative; height: 100%"
|
|
104
|
+
>
|
|
97
105
|
<ColormapQuickPicker
|
|
98
106
|
v-model:show="quickColormap.show"
|
|
99
107
|
:x="quickColormap.x"
|
|
@@ -102,7 +110,10 @@ async function handleClick(event: PointerEvent) {
|
|
|
102
110
|
/>
|
|
103
111
|
<ViewToolbar />
|
|
104
112
|
<slot name="ui"></slot>
|
|
105
|
-
<HybridViewerTooltip
|
|
113
|
+
<HybridViewerTooltip
|
|
114
|
+
:container-width="elementWidth"
|
|
115
|
+
:container-height="elementHeight"
|
|
116
|
+
/>
|
|
106
117
|
<v-col
|
|
107
118
|
class="pa-0"
|
|
108
119
|
ref="viewer"
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
import GlassCard from "@ogw_front/components/GlassCard
|
|
2
|
+
import GlassCard from "@ogw_front/components/GlassCard";
|
|
3
3
|
import { useHybridViewerStore } from "@ogw_front/stores/hybrid_viewer";
|
|
4
4
|
|
|
5
5
|
const TOOLTIP_SCREEN_MARGIN = 10;
|
|
@@ -14,7 +14,8 @@ const { containerWidth, containerHeight } = defineProps<Props>();
|
|
|
14
14
|
const hybridViewerStore = useHybridViewerStore();
|
|
15
15
|
|
|
16
16
|
const tooltipRef = useTemplateRef("tooltip");
|
|
17
|
-
const { width: tooltipWidth, height: tooltipHeight } =
|
|
17
|
+
const { width: tooltipWidth, height: tooltipHeight } =
|
|
18
|
+
useElementSize(tooltipRef);
|
|
18
19
|
|
|
19
20
|
const tooltipStyle = computed(() => {
|
|
20
21
|
if (!hybridViewerStore.hoverData) {
|
|
@@ -92,7 +93,9 @@ function capitalize(val: string) {
|
|
|
92
93
|
|
|
93
94
|
const fieldTypeLabel = computed(() => {
|
|
94
95
|
const fieldType = hybridViewerStore.hoverData?.fieldType;
|
|
95
|
-
return typeof fieldType === "string"
|
|
96
|
+
return typeof fieldType === "string"
|
|
97
|
+
? capitalize(fieldType.toLowerCase())
|
|
98
|
+
: "";
|
|
96
99
|
});
|
|
97
100
|
|
|
98
101
|
const coordinates = computed<number[] | undefined>(() => {
|
|
@@ -147,7 +150,10 @@ function formatAttributeValue(val: unknown) {
|
|
|
147
150
|
<v-col>
|
|
148
151
|
<span class="tooltip-label">Id:</span>
|
|
149
152
|
<span class="tooltip-value-dim font-mono">
|
|
150
|
-
{{
|
|
153
|
+
{{
|
|
154
|
+
hybridViewerStore.hoverData.component?.id ||
|
|
155
|
+
hybridViewerStore.hoverData.modelId
|
|
156
|
+
}}
|
|
151
157
|
</span>
|
|
152
158
|
</v-col>
|
|
153
159
|
<v-col v-if="originalIndex !== undefined">
|
|
@@ -169,7 +175,8 @@ function formatAttributeValue(val: unknown) {
|
|
|
169
175
|
<v-col v-if="coordinates" class="d-flex justify-space-between ga-3">
|
|
170
176
|
<span class="tooltip-label">Position:</span>
|
|
171
177
|
<span class="tooltip-value font-mono">
|
|
172
|
-
[ {{ Number(coordinates[0]).toFixed(3) }},
|
|
178
|
+
[ {{ Number(coordinates[0]).toFixed(3) }},
|
|
179
|
+
{{ Number(coordinates[1]).toFixed(3) }},
|
|
173
180
|
{{ Number(coordinates[2]).toFixed(3) }} ]
|
|
174
181
|
</span>
|
|
175
182
|
</v-col>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
import Loading from "@ogw_front/components/Loading
|
|
3
|
-
import Recaptcha from "@ogw_front/components/Recaptcha
|
|
2
|
+
import Loading from "@ogw_front/components/Loading";
|
|
3
|
+
import Recaptcha from "@ogw_front/components/Recaptcha";
|
|
4
4
|
import { Status } from "@ogw_front/utils/status";
|
|
5
5
|
import { appMode } from "@ogw_shared/app_mode";
|
|
6
6
|
import { useInfraStore } from "@ogw_front/stores/infra";
|
|
@@ -12,7 +12,12 @@ interface Props {
|
|
|
12
12
|
logo?: string;
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
-
const {
|
|
15
|
+
const {
|
|
16
|
+
appName,
|
|
17
|
+
email = undefined,
|
|
18
|
+
isUserAuthenticated = false,
|
|
19
|
+
logo = "",
|
|
20
|
+
} = defineProps<Props>();
|
|
16
21
|
|
|
17
22
|
const infraStore = useInfraStore();
|
|
18
23
|
if (infraStore.app_mode !== appMode.CLOUD) {
|