@geode/opengeodeweb-front 10.10.1 → 10.10.2-rc.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,106 +1,144 @@
1
1
  <script setup>
2
- import GlassCard from "@ogw_front/components/GlassCard";
2
+ import { onMounted, onUnmounted, ref } from "vue";
3
+ import DragAndDropInline from "./DragAndDropInternal/DragAndDropInline.vue";
4
+ import DragAndDropOverlay from "./DragAndDropInternal/DragAndDropOverlay.vue";
3
5
 
4
- const { multiple, accept, loading, showExtensions } = defineProps({
5
- multiple: { type: Boolean, default: false },
6
- accept: { type: String, default: "" },
7
- loading: { type: Boolean, default: false },
8
- showExtensions: { type: Boolean, default: true },
9
- });
6
+ const { multiple, accept, loading, showExtensions, fullscreen, inline, showOverlay, texts } =
7
+ defineProps({
8
+ multiple: { type: Boolean, default: false },
9
+ accept: { type: String, default: "" },
10
+ loading: { type: Boolean, default: false },
11
+ showExtensions: { type: Boolean, default: true },
12
+ fullscreen: { type: Boolean, default: false },
13
+ inline: { type: Boolean, default: true },
14
+ showOverlay: { type: Boolean, default: true },
15
+ texts: {
16
+ type: Object,
17
+ default: () => ({
18
+ idle: "Click or drag and drop",
19
+ drop: "Drop files here",
20
+ loading: "Loading...",
21
+ }),
22
+ },
23
+ });
10
24
 
11
25
  const emit = defineEmits(["files-selected"]);
12
26
 
13
27
  const isDragging = ref(false);
28
+ const isInternalDrag = ref(false);
29
+ const dragCounter = ref(0);
14
30
  const fileInput = ref(undefined);
15
31
 
16
32
  function triggerFileDialog() {
17
33
  fileInput.value?.click();
18
34
  }
19
35
 
20
- function handleDrop(event) {
36
+ function onDragEnter(event) {
37
+ if (!isInternalDrag.value && event.dataTransfer.types.includes("Files")) {
38
+ dragCounter.value += 1;
39
+ isDragging.value = true;
40
+ }
41
+ }
42
+
43
+ function onDragLeave() {
44
+ dragCounter.value -= 1;
45
+ if (dragCounter.value <= 0) {
46
+ isDragging.value = false;
47
+ dragCounter.value = 0;
48
+ }
49
+ }
50
+
51
+ function onDragOver(event) {
52
+ if (!isInternalDrag.value && event.dataTransfer.types.includes("Files")) {
53
+ event.preventDefault();
54
+ }
55
+ }
56
+
57
+ function onDrop(event) {
58
+ event.preventDefault();
59
+ dragCounter.value = 0;
21
60
  isDragging.value = false;
22
61
  const files = [...event.dataTransfer.files];
23
- emit("files-selected", files);
62
+ if (files.length > 0) {
63
+ emit("files-selected", files);
64
+ }
65
+ }
66
+
67
+ function onKeyDown(event) {
68
+ if (event.key === "Escape") {
69
+ event.preventDefault();
70
+ event.stopPropagation();
71
+ isDragging.value = false;
72
+ dragCounter.value = 0;
73
+ }
24
74
  }
25
75
 
26
76
  function handleFileSelect(event) {
27
77
  const files = [...event.target.files];
28
- emit("files-selected", files);
78
+ if (files.length > 0) {
79
+ emit("files-selected", files);
80
+ }
29
81
  event.target.value = "";
30
82
  }
83
+
84
+ function onInternalDragStart() {
85
+ isInternalDrag.value = true;
86
+ }
87
+
88
+ function onInternalDragEnd() {
89
+ isInternalDrag.value = false;
90
+ }
91
+
92
+ onMounted(() => {
93
+ globalThis.addEventListener("dragstart", onInternalDragStart);
94
+ globalThis.addEventListener("dragend", onInternalDragEnd);
95
+ globalThis.addEventListener("dragenter", onDragEnter);
96
+ globalThis.addEventListener("dragover", onDragOver);
97
+ globalThis.addEventListener("dragleave", onDragLeave);
98
+ globalThis.addEventListener("drop", onDrop);
99
+ globalThis.addEventListener("keydown", onKeyDown);
100
+ });
101
+
102
+ onUnmounted(() => {
103
+ globalThis.removeEventListener("dragstart", onInternalDragStart);
104
+ globalThis.removeEventListener("dragend", onInternalDragEnd);
105
+ globalThis.removeEventListener("dragenter", onDragEnter);
106
+ globalThis.removeEventListener("dragover", onDragOver);
107
+ globalThis.removeEventListener("dragleave", onDragLeave);
108
+ globalThis.removeEventListener("drop", onDrop);
109
+ globalThis.removeEventListener("keydown", onKeyDown);
110
+ });
111
+
112
+ defineExpose({ triggerFileDialog });
31
113
  </script>
32
114
 
33
115
  <template>
34
- <v-hover v-slot="{ isHovering, props: hoverProps }">
35
- <GlassCard
36
- v-bind="hoverProps"
37
- class="text-center cursor-pointer overflow-hidden border-opacity-10 border-white"
38
- :class="{
39
- 'elevation-4': isHovering || isDragging,
40
- 'elevation-0': !(isHovering || isDragging),
41
- }"
42
- :style="{
43
- position: 'relative',
44
- transition: 'all 0.3s cubic-bezier(0.4, 0, 0.2, 1)',
45
- background:
46
- isHovering || isDragging
47
- ? 'rgba(255, 255, 255, 0.08) !important'
48
- : 'rgba(255, 255, 255, 0.03) !important',
49
- transform: isHovering || isDragging ? 'translateY(-2px)' : 'none',
50
- pointerEvents: loading ? 'none' : 'auto',
51
- opacity: loading ? 0.6 : 1,
52
- }"
53
- variant="panel"
54
- padding="pa-0"
55
- @click="triggerFileDialog"
56
- @dragover.prevent="isDragging = true"
57
- @dragleave.prevent="isDragging = false"
58
- @drop.prevent="handleDrop"
59
- >
60
- <v-card-text class="pa-8">
61
- <v-sheet
62
- class="mx-auto mb-6 d-flex align-center justify-center"
63
- :color="isHovering || isDragging ? 'white' : 'rgba(255, 255, 255, 0.1)'"
64
- rounded="circle"
65
- width="80"
66
- height="80"
67
- style="transition: all 0.3s ease"
68
- >
69
- <v-icon
70
- :icon="loading ? 'mdi-loading' : 'mdi-cloud-upload'"
71
- size="40"
72
- :color="isHovering || isDragging ? 'primary' : 'white'"
73
- :class="{ rotating: loading }"
74
- />
75
- </v-sheet>
76
-
77
- <v-card-title
78
- class="text-h6 font-weight-bold justify-center pa-0 mb-1 text-white"
79
- style="transition: color 0.3s ease"
80
- >
81
- {{
82
- loading ? "Uploading..." : isDragging ? "Drop to upload" : "Click or Drag & Drop files"
83
- }}
84
- </v-card-title>
85
-
86
- <v-card-subtitle v-if="showExtensions" class="text-body-2 pa-0">
87
- {{ accept ? `(${accept} files)` : "All files allowed" }}
88
- </v-card-subtitle>
89
- </v-card-text>
90
-
91
- <input
92
- ref="fileInput"
93
- type="file"
94
- class="d-none"
95
- :multiple="multiple"
96
- :accept="accept"
97
- @change="handleFileSelect"
98
- />
99
- </GlassCard>
100
- </v-hover>
116
+ <DragAndDropInline
117
+ v-if="inline"
118
+ :is-dragging
119
+ :loading
120
+ :texts
121
+ :accept
122
+ :show-extensions
123
+ @click="triggerFileDialog"
124
+ />
125
+
126
+ <DragAndDropOverlay
127
+ v-if="isDragging && showOverlay"
128
+ :is-dragging
129
+ :show-overlay
130
+ :fullscreen
131
+ :loading
132
+ :texts
133
+ :multiple
134
+ :accept
135
+ :show-extensions
136
+ />
137
+
138
+ <input ref="fileInput" type="file" class="d-none" :multiple :accept @change="handleFileSelect" />
101
139
  </template>
102
140
 
103
- <style scoped>
141
+ <style>
104
142
  .rotating {
105
143
  animation: rotate 1s linear infinite;
106
144
  }
@@ -0,0 +1,73 @@
1
+ <script setup>
2
+ import GlassCard from "@ogw_front/components/GlassCard";
3
+
4
+ const { isDragging, loading, texts, accept, showExtensions } = defineProps({
5
+ isDragging: { type: Boolean, required: true },
6
+ loading: { type: Boolean, required: true },
7
+ texts: {
8
+ type: Object,
9
+ default: () => ({
10
+ idle: "Click or drag and drop",
11
+ drop: "Drop files here",
12
+ loading: "Loading...",
13
+ }),
14
+ },
15
+ accept: { type: String, default: "" },
16
+ showExtensions: { type: Boolean, required: true },
17
+ });
18
+
19
+ const emit = defineEmits(["click"]);
20
+ </script>
21
+
22
+ <template>
23
+ <v-hover v-slot="{ isHovering, props: hoverProps }">
24
+ <GlassCard
25
+ v-bind="hoverProps"
26
+ class="drag-card-inline text-center cursor-pointer transition-swing"
27
+ :class="{ 'dragging-active': isDragging, 'elevation-8': isHovering }"
28
+ variant="ui"
29
+ @click="emit('click')"
30
+ >
31
+ <v-sheet
32
+ class="mx-auto mb-4 d-flex align-center justify-center transition-swing"
33
+ :color="isHovering || isDragging ? 'primary' : 'rgba(255,255,255,0.05)'"
34
+ rounded="circle"
35
+ width="64"
36
+ height="64"
37
+ >
38
+ <v-icon
39
+ :icon="loading ? 'mdi-loading' : 'mdi-cloud-upload'"
40
+ size="32"
41
+ :color="isHovering || isDragging ? 'white' : 'primary'"
42
+ :class="{ rotating: loading }"
43
+ />
44
+ </v-sheet>
45
+
46
+ <v-card-text class="pa-0">
47
+ <v-sheet class="text-h6 font-weight-bold text-white d-block mb-1 bg-transparent">
48
+ {{ loading ? texts.loading : isDragging ? texts.drop : texts.idle }}
49
+ </v-sheet>
50
+ <v-sheet
51
+ v-if="accept && showExtensions"
52
+ class="text-body-2 text-white opacity-60 bg-transparent"
53
+ >
54
+ {{ accept }}
55
+ </v-sheet>
56
+ </v-card-text>
57
+ </GlassCard>
58
+ </v-hover>
59
+ </template>
60
+
61
+ <style scoped>
62
+ .drag-card-inline {
63
+ border: 2px dashed rgba(255, 255, 255, 0.1) !important;
64
+ background: rgba(255, 255, 255, 0.03) !important;
65
+ transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
66
+ }
67
+
68
+ .drag-card-inline:hover,
69
+ .drag-card-inline.dragging-active {
70
+ border-color: rgba(var(--v-theme-primary), 0.4) !important;
71
+ background: rgba(var(--v-theme-primary), 0.05) !important;
72
+ }
73
+ </style>
@@ -0,0 +1,162 @@
1
+ <script setup>
2
+ const { isDragging, showOverlay, fullscreen, loading, texts, multiple, accept, showExtensions } =
3
+ defineProps({
4
+ isDragging: { type: Boolean, required: true },
5
+ showOverlay: { type: Boolean, required: true },
6
+ fullscreen: { type: Boolean, required: true },
7
+ loading: { type: Boolean, required: true },
8
+ texts: {
9
+ type: Object,
10
+ default: () => ({
11
+ idle: "Click or drag and drop",
12
+ drop: "Drop files here",
13
+ loading: "Loading...",
14
+ }),
15
+ },
16
+ multiple: { type: Boolean, required: true },
17
+ accept: { type: String, default: "" },
18
+ showExtensions: { type: Boolean, required: true },
19
+ });
20
+ </script>
21
+
22
+ <template>
23
+ <Teleport to="body">
24
+ <v-fade-transition>
25
+ <v-overlay
26
+ v-if="isDragging && showOverlay"
27
+ :model-value="true"
28
+ :scrim="false"
29
+ class="drag-overlay"
30
+ content-class="w-100 h-100"
31
+ persistent
32
+ >
33
+ <v-container class="fill-height" :fluid="fullscreen">
34
+ <v-row align="center" justify="center">
35
+ <v-col
36
+ cols="12"
37
+ :md="fullscreen ? 12 : 8"
38
+ :lg="fullscreen ? 12 : 6"
39
+ class="text-center"
40
+ >
41
+ <v-sheet
42
+ class="mx-auto mb-8 pulse-animation d-flex align-center justify-center"
43
+ color="primary"
44
+ rounded="circle"
45
+ :width="fullscreen ? 140 : 120"
46
+ :height="fullscreen ? 140 : 120"
47
+ >
48
+ <v-icon icon="mdi-cloud-upload" :size="fullscreen ? 80 : 64" color="white" />
49
+ </v-sheet>
50
+
51
+ <v-sheet
52
+ class="font-weight-black mb-6 text-white text-glow d-block bg-transparent"
53
+ :class="fullscreen ? 'text-h2' : 'text-h3'"
54
+ >
55
+ {{
56
+ loading ? texts.loading : fullscreen ? "Drop your files here" : "Drop your files"
57
+ }}
58
+ </v-sheet>
59
+
60
+ <v-sheet
61
+ class="text-white opacity-70 d-block mb-8 mx-auto bg-transparent"
62
+ :class="fullscreen ? 'text-h5' : 'text-h6'"
63
+ :style="fullscreen ? 'max-width:700px' : 'max-width:500px'"
64
+ >
65
+ {{
66
+ multiple
67
+ ? "Drag your files anywhere on the screen to import them."
68
+ : "Drag your file anywhere on the screen to import it."
69
+ }}
70
+ </v-sheet>
71
+
72
+ <v-chip
73
+ v-if="accept && showExtensions"
74
+ color="white"
75
+ variant="outlined"
76
+ :size="fullscreen ? 'x-large' : 'large'"
77
+ class="px-8 glow-chip"
78
+ >
79
+ Accepted formats: {{ accept }}
80
+ </v-chip>
81
+
82
+ <v-sheet
83
+ class="text-white opacity-40 d-block mt-12 bg-transparent"
84
+ :class="fullscreen ? 'text-h6' : 'text-body-2'"
85
+ >
86
+ Press
87
+ <v-kbd class="escape-kbd mx-1">Esc</v-kbd>
88
+ to cancel
89
+ </v-sheet>
90
+ </v-col>
91
+ </v-row>
92
+ </v-container>
93
+
94
+ <v-sheet v-if="fullscreen" class="drag-frame-border" color="transparent" />
95
+ </v-overlay>
96
+ </v-fade-transition>
97
+ </Teleport>
98
+ </template>
99
+
100
+ <style scoped>
101
+ .drag-overlay :deep(.v-overlay__content) {
102
+ background: rgba(0, 0, 0, 0.6);
103
+ backdrop-filter: blur(24px);
104
+ }
105
+
106
+ .drag-frame-border {
107
+ position: absolute;
108
+ inset: 32px;
109
+ border: 4px dashed rgba(255, 255, 255, 0.3);
110
+ border-radius: 32px;
111
+ pointer-events: none;
112
+ animation: border-glimmer 4s infinite ease-in-out;
113
+ }
114
+
115
+ .glow-chip {
116
+ background: rgba(255, 255, 255, 0.1) !important;
117
+ border-color: rgba(255, 255, 255, 0.4) !important;
118
+ box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
119
+ }
120
+
121
+ .escape-kbd {
122
+ padding: 6px 12px;
123
+ border-radius: 8px;
124
+ background: rgba(255, 255, 255, 0.2);
125
+ font-weight: bold;
126
+ border: 1px solid rgba(255, 255, 255, 0.4);
127
+ box-shadow: 0 4px 8px rgba(0, 0, 0, 0.3);
128
+ }
129
+
130
+ .text-glow {
131
+ text-shadow: 0 0 30px rgba(255, 255, 255, 0.3);
132
+ }
133
+
134
+ .pulse-animation {
135
+ animation: pulse 2s infinite;
136
+ }
137
+
138
+ @keyframes pulse {
139
+ 0% {
140
+ transform: scale(1);
141
+ box-shadow: 0 0 0 0px rgba(var(--v-theme-primary), 0.4);
142
+ }
143
+ 70% {
144
+ transform: scale(1.05);
145
+ box-shadow: 0 0 0 20px rgba(var(--v-theme-primary), 0);
146
+ }
147
+ 100% {
148
+ transform: scale(1);
149
+ box-shadow: 0 0 0 0px rgba(var(--v-theme-primary), 0);
150
+ }
151
+ }
152
+
153
+ @keyframes border-glimmer {
154
+ 0%,
155
+ 100% {
156
+ border-color: rgba(255, 255, 255, 0.2);
157
+ }
158
+ 50% {
159
+ border-color: rgba(var(--v-theme-primary), 0.4);
160
+ }
161
+ }
162
+ </style>
@@ -9,10 +9,11 @@ const schema = schemas.opengeodeweb_back.allowed_files;
9
9
 
10
10
  const emit = defineEmits(["update_values", "increment_step", "decrement_step"]);
11
11
 
12
- const { multiple, files, auto_upload } = defineProps({
12
+ const { multiple, files, auto_upload, show_overlay } = defineProps({
13
13
  multiple: { type: Boolean, required: true },
14
14
  files: { type: Array, default: () => [] },
15
15
  auto_upload: { type: Boolean, default: true },
16
+ show_overlay: { type: Boolean, default: true },
16
17
  });
17
18
 
18
19
  const internal_files = ref(files);
@@ -63,6 +64,7 @@ await get_allowed_files();
63
64
  accept,
64
65
  files: internal_files,
65
66
  auto_upload: internal_auto_upload,
67
+ show_overlay,
66
68
  }"
67
69
  @files_uploaded="files_uploaded_event"
68
70
  />
@@ -1,15 +1,25 @@
1
1
  <script setup>
2
- import DragAndDrop from "@ogw_front/components/DragAndDrop";
3
2
  import { useGeodeStore } from "@ogw_front/stores/geode";
3
+ import { useTemplateRef } from "vue";
4
+
5
+ import DragAndDrop from "@ogw_front/components/DragAndDrop";
4
6
 
5
7
  const emit = defineEmits(["files_uploaded", "decrement_step", "reset_values"]);
6
8
 
7
- const { multiple, accept, files, auto_upload, mini } = defineProps({
9
+ const {
10
+ multiple,
11
+ accept,
12
+ files,
13
+ auto_upload,
14
+ mini,
15
+ show_overlay: showOverlay,
16
+ } = defineProps({
8
17
  multiple: { type: Boolean, required: true },
9
18
  accept: { type: String, required: true },
10
19
  files: { type: Array, required: false, default: [] },
11
20
  auto_upload: { type: Boolean, required: false, default: false },
12
21
  mini: { type: Boolean, required: false, default: false },
22
+ show_overlay: { type: Boolean, required: false, default: true },
13
23
  });
14
24
 
15
25
  const geodeStore = useGeodeStore();
@@ -17,6 +27,7 @@ const geodeStore = useGeodeStore();
17
27
  const internal_files = ref(files);
18
28
  const loading = ref(false);
19
29
  const files_uploaded = ref(false);
30
+ const dragAndDropRef = useTemplateRef("dragAndDropRef");
20
31
 
21
32
  const toggle_loading = useToggle(loading);
22
33
 
@@ -71,20 +82,53 @@ watch(internal_files, (value) => {
71
82
 
72
83
  <template>
73
84
  <DragAndDrop
74
- :multiple="multiple"
75
- :accept="accept"
76
- :loading="loading"
85
+ v-if="!internal_files.length"
86
+ ref="dragAndDropRef"
87
+ :multiple
88
+ :accept
89
+ :loading
90
+ :show-extensions="false"
91
+ :inline="true"
92
+ :show-overlay="showOverlay"
93
+ :texts="{
94
+ idle: 'Select files',
95
+ drop: 'Drop files here',
96
+ loading: 'Loading...',
97
+ }"
98
+ @files-selected="processSelectedFiles"
99
+ />
100
+
101
+ <DragAndDrop
102
+ v-else
103
+ ref="dragAndDropRef"
104
+ :multiple
105
+ :accept
106
+ :loading
77
107
  :show-extensions="false"
108
+ :inline="false"
109
+ :show-overlay="showOverlay"
78
110
  @files-selected="processSelectedFiles"
79
111
  />
80
112
 
81
- <v-card-text v-if="internal_files.length" class="mt-6">
113
+ <v-card-text v-if="internal_files.length" class="mt-6 pa-0">
82
114
  <v-sheet class="d-flex align-center mb-4" color="transparent">
83
115
  <v-icon icon="mdi-file-check" class="mr-3" color="primary" size="24" />
84
- <span class="text-subtitle-1 font-weight-bold text-white"> Selected Files </span>
116
+ <span class="text-subtitle-1 font-weight-bold text-white"> Selected files </span>
85
117
  <v-chip size="small" class="ml-3 bg-white-opacity-10" color="white" variant="flat">
86
118
  {{ internal_files.length }}
87
119
  </v-chip>
120
+ <v-spacer />
121
+ <v-btn
122
+ v-if="multiple"
123
+ variant="text"
124
+ color="white"
125
+ size="small"
126
+ class="text-none opacity-60"
127
+ prepend-icon="mdi-plus"
128
+ @click="dragAndDropRef?.triggerFileDialog"
129
+ >
130
+ Add
131
+ </v-btn>
88
132
  </v-sheet>
89
133
 
90
134
  <v-sheet class="d-flex flex-wrap ga-2" color="transparent">
@@ -108,7 +152,7 @@ watch(internal_files, (value) => {
108
152
  </v-sheet>
109
153
  </v-card-text>
110
154
 
111
- <v-card-actions v-if="!auto_upload && internal_files.length" class="mt-6 pa-0">
155
+ <v-card-actions v-if="!auto_upload && internal_files.length" class="mt-8 pa-0">
112
156
  <v-btn
113
157
  color="primary"
114
158
  variant="flat"
@@ -124,3 +168,20 @@ watch(internal_files, (value) => {
124
168
  </v-btn>
125
169
  </v-card-actions>
126
170
  </template>
171
+
172
+ <style scoped>
173
+ .border-dashed {
174
+ border: 2px dashed rgba(255, 255, 255, 0.1) !important;
175
+ transition: all 0.3s ease;
176
+ }
177
+
178
+ .border-dashed:hover {
179
+ border-color: rgba(var(--v-theme-primary), 0.4) !important;
180
+ background: rgba(var(--v-theme-primary), 0.02) !important;
181
+ }
182
+
183
+ .custom-upload-btn {
184
+ letter-spacing: 0.5px;
185
+ box-shadow: 0 4px 15px rgba(var(--v-theme-primary), 0.3);
186
+ }
187
+ </style>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@geode/opengeodeweb-front",
3
- "version": "10.10.1",
3
+ "version": "10.10.2-rc.2",
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
  "@kitware/vtk.js": "33.3.0",
40
40
  "@mdi/font": "7.4.47",
41
41
  "@pinia/nuxt": "0.11.3",
@@ -1,5 +1,5 @@
1
1
  // Third party imports
2
- import { afterEach, beforeEach, describe, expect, test, vi } from "vitest";
2
+ import { afterAll, beforeAll, describe, expect, test, vi } from "vitest";
3
3
  import viewer_schemas from "@geode/opengeodeweb-viewer/opengeodeweb_viewer_schemas.json" with { type: "json" };
4
4
 
5
5
  // Local imports
@@ -20,14 +20,14 @@ const cell_attribute = { name: "RGB_data" };
20
20
  let id = "",
21
21
  projectFolderPath = "";
22
22
 
23
- beforeEach(async () => {
23
+ beforeAll(async () => {
24
24
  id = "";
25
25
  projectFolderPath = "";
26
26
  ({ id, projectFolderPath } = await setupIntegrationTests(file_name, geode_object));
27
27
  }, INTERVAL_TIMEOUT);
28
28
 
29
- afterEach(async () => {
30
- console.log("afterEach mesh cells kill", projectFolderPath);
29
+ afterAll(async () => {
30
+ console.log("afterAll mesh cells kill", projectFolderPath);
31
31
  await cleanupBackend(projectFolderPath);
32
32
  });
33
33
 
@@ -1,5 +1,5 @@
1
1
  // Third party imports
2
- import { afterEach, beforeEach, describe, expect, test, vi } from "vitest";
2
+ import { afterAll, beforeAll, describe, expect, test, vi } from "vitest";
3
3
  import viewer_schemas from "@geode/opengeodeweb-viewer/opengeodeweb_viewer_schemas.json" with { type: "json" };
4
4
 
5
5
  // Local imports
@@ -20,12 +20,12 @@ const edge_attribute = { name: "edge_attribute" };
20
20
  let id = "",
21
21
  projectFolderPath = "";
22
22
 
23
- beforeEach(async () => {
23
+ beforeAll(async () => {
24
24
  ({ id, projectFolderPath } = await setupIntegrationTests(file_name, geode_object));
25
25
  }, INTERVAL_TIMEOUT);
26
26
 
27
- afterEach(async () => {
28
- console.log("afterEach mesh edges kill", projectFolderPath);
27
+ afterAll(async () => {
28
+ console.log("afterAll mesh edges kill", projectFolderPath);
29
29
  await cleanupBackend(projectFolderPath);
30
30
  });
31
31
 
@@ -1,5 +1,5 @@
1
1
  // Third party imports
2
- import { afterEach, beforeEach, describe, expect, test, vi } from "vitest";
2
+ import { afterAll, beforeAll, describe, expect, test, vi } from "vitest";
3
3
  import viewer_schemas from "@geode/opengeodeweb-viewer/opengeodeweb_viewer_schemas.json" with { type: "json" };
4
4
 
5
5
  // Local imports
@@ -18,12 +18,12 @@ const geode_object = "RegularGrid3D";
18
18
  let id = "",
19
19
  projectFolderPath = "";
20
20
 
21
- beforeEach(async () => {
21
+ beforeAll(async () => {
22
22
  ({ id, projectFolderPath } = await setupIntegrationTests(file_name, geode_object));
23
23
  }, INTERVAL_TIMEOUT);
24
24
 
25
- afterEach(async () => {
26
- console.log("afterEach mesh index kill", projectFolderPath);
25
+ afterAll(async () => {
26
+ console.log("afterAll mesh index kill", projectFolderPath);
27
27
  await cleanupBackend(projectFolderPath);
28
28
  });
29
29
 
@@ -1,5 +1,5 @@
1
1
  // Third party imports
2
- import { afterEach, beforeEach, describe, expect, test, vi } from "vitest";
2
+ import { afterAll, beforeAll, describe, expect, test, vi } from "vitest";
3
3
  import viewer_schemas from "@geode/opengeodeweb-viewer/opengeodeweb_viewer_schemas.json" with { type: "json" };
4
4
 
5
5
  // Local imports
@@ -19,12 +19,12 @@ const vertex_attribute = { name: "points" };
19
19
  let id = "",
20
20
  projectFolderPath = "";
21
21
 
22
- beforeEach(async () => {
22
+ beforeAll(async () => {
23
23
  ({ id, projectFolderPath } = await setupIntegrationTests(file_name, geode_object));
24
24
  }, INTERVAL_TIMEOUT);
25
25
 
26
- afterEach(async () => {
27
- console.log("afterEach mesh points kill", projectFolderPath);
26
+ afterAll(async () => {
27
+ console.log("afterAll mesh points kill", projectFolderPath);
28
28
  await cleanupBackend(projectFolderPath);
29
29
  });
30
30
 
@@ -1,5 +1,5 @@
1
1
  // Third party imports
2
- import { afterEach, beforeEach, describe, expect, test, vi } from "vitest";
2
+ import { afterAll, beforeAll, describe, expect, test, vi } from "vitest";
3
3
  import viewer_schemas from "@geode/opengeodeweb-viewer/opengeodeweb_viewer_schemas.json" with { type: "json" };
4
4
 
5
5
  // Local imports
@@ -20,12 +20,12 @@ const polygon_attribute = { name: "test_attribute" };
20
20
  let id = "",
21
21
  projectFolderPath = "";
22
22
 
23
- beforeEach(async () => {
23
+ beforeAll(async () => {
24
24
  ({ id, projectFolderPath } = await setupIntegrationTests(file_name, geode_object));
25
25
  }, INTERVAL_TIMEOUT);
26
26
 
27
- afterEach(async () => {
28
- console.log("afterEach mesh polygons kill", projectFolderPath);
27
+ afterAll(async () => {
28
+ console.log("afterAll mesh polygons kill", projectFolderPath);
29
29
  await cleanupBackend(projectFolderPath);
30
30
  });
31
31
 
@@ -1,5 +1,5 @@
1
1
  // Third party imports
2
- import { afterEach, beforeEach, describe, expect, test, vi } from "vitest";
2
+ import { afterAll, beforeAll, describe, expect, test, vi } from "vitest";
3
3
  import viewer_schemas from "@geode/opengeodeweb-viewer/opengeodeweb_viewer_schemas.json" with { type: "json" };
4
4
 
5
5
  // Local imports
@@ -20,12 +20,12 @@ const polyhedron_attribute = { name: "toto_on_polyhedra" };
20
20
  let id = "",
21
21
  projectFolderPath = "";
22
22
 
23
- beforeEach(async () => {
23
+ beforeAll(async () => {
24
24
  ({ id, projectFolderPath } = await setupIntegrationTests(file_name, geode_object));
25
25
  }, INTERVAL_TIMEOUT);
26
26
 
27
- afterEach(async () => {
28
- console.log("afterEach mesh cells kill", projectFolderPath);
27
+ afterAll(async () => {
28
+ console.log("afterAll mesh cells kill", projectFolderPath);
29
29
  await cleanupBackend(projectFolderPath);
30
30
  });
31
31
 
@@ -1,5 +1,5 @@
1
1
  // Third party imports
2
- import { afterEach, beforeEach, describe, expect, test, vi } from "vitest";
2
+ import { afterAll, beforeAll, describe, expect, test, vi } from "vitest";
3
3
  import viewer_schemas from "@geode/opengeodeweb-viewer/opengeodeweb_viewer_schemas.json" with { type: "json" };
4
4
 
5
5
  // Local imports
@@ -27,12 +27,12 @@ function sleep(milliseconds) {
27
27
  let id = "",
28
28
  projectFolderPath = "";
29
29
 
30
- beforeEach(async () => {
30
+ beforeAll(async () => {
31
31
  ({ id, projectFolderPath } = await setupIntegrationTests(file_name, geode_object));
32
32
  }, INTERVAL_TIMEOUT);
33
33
 
34
- afterEach(async () => {
35
- console.log("afterEach model blocks kill", projectFolderPath);
34
+ afterAll(async () => {
35
+ console.log("afterAll model blocks kill", projectFolderPath);
36
36
  await cleanupBackend(projectFolderPath);
37
37
  });
38
38
 
@@ -1,5 +1,5 @@
1
1
  // Third party imports
2
- import { afterEach, beforeEach, describe, expect, test, vi } from "vitest";
2
+ import { afterAll, beforeAll, describe, expect, test, vi } from "vitest";
3
3
  import viewer_schemas from "@geode/opengeodeweb-viewer/opengeodeweb_viewer_schemas.json" with { type: "json" };
4
4
 
5
5
  // Local imports
@@ -27,12 +27,12 @@ function sleep(milliseconds) {
27
27
  let id = "",
28
28
  projectFolderPath = "";
29
29
 
30
- beforeEach(async () => {
30
+ beforeAll(async () => {
31
31
  ({ id, projectFolderPath } = await setupIntegrationTests(file_name, geode_object));
32
32
  }, INTERVAL_TIMEOUT);
33
33
 
34
- afterEach(async () => {
35
- console.log("afterEach model corners kill", projectFolderPath);
34
+ afterAll(async () => {
35
+ console.log("afterAll model corners kill", projectFolderPath);
36
36
  await cleanupBackend(projectFolderPath);
37
37
  });
38
38
 
@@ -1,5 +1,5 @@
1
1
  // Third party imports
2
- import { afterEach, beforeEach, describe, expect, test, vi } from "vitest";
2
+ import { afterAll, beforeAll, describe, expect, test, vi } from "vitest";
3
3
  import viewer_schemas from "@geode/opengeodeweb-viewer/opengeodeweb_viewer_schemas.json" with { type: "json" };
4
4
 
5
5
  // Local imports
@@ -26,12 +26,12 @@ function sleep(milliseconds) {
26
26
  let id = "",
27
27
  projectFolderPath = "";
28
28
 
29
- beforeEach(async () => {
29
+ beforeAll(async () => {
30
30
  ({ id, projectFolderPath } = await setupIntegrationTests(file_name, geode_object));
31
31
  }, INTERVAL_TIMEOUT);
32
32
 
33
- afterEach(async () => {
34
- console.log("afterEach model edges kill", projectFolderPath);
33
+ afterAll(async () => {
34
+ console.log("afterAll model edges kill", projectFolderPath);
35
35
  await cleanupBackend(projectFolderPath);
36
36
  });
37
37
 
@@ -1,5 +1,5 @@
1
1
  // Third party imports
2
- import { afterEach, beforeEach, describe, expect, test, vi } from "vitest";
2
+ import { afterAll, beforeAll, describe, expect, test, vi } from "vitest";
3
3
  import viewer_schemas from "@geode/opengeodeweb-viewer/opengeodeweb_viewer_schemas.json" with { type: "json" };
4
4
 
5
5
  // Local imports
@@ -26,12 +26,12 @@ function sleep(milliseconds) {
26
26
  let id = "",
27
27
  projectFolderPath = "";
28
28
 
29
- beforeEach(async () => {
29
+ beforeAll(async () => {
30
30
  ({ id, projectFolderPath } = await setupIntegrationTests(file_name, geode_object));
31
31
  }, INTERVAL_TIMEOUT);
32
32
 
33
- afterEach(async () => {
34
- console.log("afterEach model kill", projectFolderPath);
33
+ afterAll(async () => {
34
+ console.log("afterAll model kill", projectFolderPath);
35
35
  await cleanupBackend(projectFolderPath);
36
36
  });
37
37
 
@@ -1,5 +1,5 @@
1
1
  // Third party imports
2
- import { afterEach, beforeEach, describe, expect, test, vi } from "vitest";
2
+ import { afterAll, beforeAll, describe, expect, test, vi } from "vitest";
3
3
  import viewer_schemas from "@geode/opengeodeweb-viewer/opengeodeweb_viewer_schemas.json" with { type: "json" };
4
4
 
5
5
  // Local imports
@@ -27,11 +27,11 @@ function sleep(milliseconds) {
27
27
  let id = "",
28
28
  projectFolderPath = "";
29
29
 
30
- beforeEach(async () => {
30
+ beforeAll(async () => {
31
31
  ({ id, projectFolderPath } = await setupIntegrationTests(file_name, geode_object));
32
32
  }, INTERVAL_TIMEOUT);
33
- afterEach(async () => {
34
- console.log("afterEach model lines kill", projectFolderPath);
33
+ afterAll(async () => {
34
+ console.log("afterAll model lines kill", projectFolderPath);
35
35
  await cleanupBackend(projectFolderPath);
36
36
  });
37
37
 
@@ -1,5 +1,5 @@
1
1
  // Third party imports
2
- import { afterEach, beforeEach, describe, expect, test, vi } from "vitest";
2
+ import { afterAll, beforeAll, describe, expect, test, vi } from "vitest";
3
3
  import viewer_schemas from "@geode/opengeodeweb-viewer/opengeodeweb_viewer_schemas.json" with { type: "json" };
4
4
 
5
5
  // Local imports
@@ -26,12 +26,12 @@ function sleep(milliseconds) {
26
26
  let id = "",
27
27
  projectFolderPath = "";
28
28
 
29
- beforeEach(async () => {
29
+ beforeAll(async () => {
30
30
  ({ id, projectFolderPath } = await setupIntegrationTests(file_name, geode_object));
31
31
  }, INTERVAL_TIMEOUT);
32
32
 
33
- afterEach(async () => {
34
- console.log("afterEach model points kill", projectFolderPath);
33
+ afterAll(async () => {
34
+ console.log("afterAll model points kill", projectFolderPath);
35
35
  await cleanupBackend(projectFolderPath);
36
36
  });
37
37
 
@@ -1,5 +1,5 @@
1
1
  // Third party imports
2
- import { afterEach, beforeEach, describe, expect, test, vi } from "vitest";
2
+ import { afterAll, beforeAll, describe, expect, test, vi } from "vitest";
3
3
  import viewer_schemas from "@geode/opengeodeweb-viewer/opengeodeweb_viewer_schemas.json" with { type: "json" };
4
4
 
5
5
  // Local imports
@@ -27,12 +27,12 @@ function sleep(milliseconds) {
27
27
  let id = "",
28
28
  projectFolderPath = "";
29
29
 
30
- beforeEach(async () => {
30
+ beforeAll(async () => {
31
31
  ({ id, projectFolderPath } = await setupIntegrationTests(file_name, geode_object));
32
32
  }, INTERVAL_TIMEOUT);
33
33
 
34
- afterEach(async () => {
35
- console.log("afterEach model surfaces kill", projectFolderPath);
34
+ afterAll(async () => {
35
+ console.log("afterAll model surfaces kill", projectFolderPath);
36
36
  await cleanupBackend(projectFolderPath);
37
37
  });
38
38
  describe("model surfaces", () => {
@@ -1,7 +1,7 @@
1
1
  // Global imports
2
2
 
3
3
  // Third party imports
4
- import { afterEach, beforeEach, describe, expect, test } from "vitest";
4
+ import { afterAll, beforeAll, describe, expect, test } from "vitest";
5
5
  import opengeodeweb_viewer_schemas from "@geode/opengeodeweb-viewer/opengeodeweb_viewer_schemas.json";
6
6
 
7
7
  // Local imports
@@ -15,12 +15,12 @@ const CONNECT_TIMEOUT = 25_000;
15
15
 
16
16
  let projectFolderPath = "";
17
17
 
18
- beforeEach(async () => {
18
+ beforeAll(async () => {
19
19
  setupActivePinia();
20
20
  ({ projectFolderPath } = await runMicroservices());
21
21
  });
22
22
 
23
- afterEach(async () => {
23
+ afterAll(async () => {
24
24
  await cleanupBackend(projectFolderPath);
25
25
  });
26
26