@geode/opengeodeweb-front 10.2.0-rc.2 → 10.2.1-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.
- package/app/components/DragAndDrop.vue +120 -0
- package/app/components/FileSelector.vue +11 -14
- package/app/components/FileUploader.vue +69 -48
- package/app/components/Launcher.vue +1 -1
- package/app/components/Recaptcha.vue +6 -1
- package/app/components/Step.vue +60 -59
- package/app/components/Stepper.vue +24 -14
- package/app/plugins/auto_store_register.js +14 -10
- package/app/stores/data.js +1 -1
- package/internal/database/tables/model_components.js +1 -1
- package/internal/stores/model/blocks.js +6 -0
- package/internal/stores/model/corners.js +6 -0
- package/internal/stores/model/lines.js +6 -0
- package/internal/stores/model/surfaces.js +6 -0
- package/package.json +1 -1
- package/tests/integration/microservices/back/requirements.txt +1 -1
- package/tests/integration/microservices/viewer/requirements.txt +1 -1
- package/tests/unit/components/FileSelector.nuxt.test.js +5 -3
- package/tests/unit/components/FileUploader.nuxt.test.js +5 -4
- package/tests/unit/components/MissingFilesSelector.nuxt.test.js +5 -3
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<v-hover v-slot="{ isHovering, props: hoverProps }">
|
|
3
|
+
<v-card
|
|
4
|
+
v-bind="hoverProps"
|
|
5
|
+
class="text-center cursor-pointer"
|
|
6
|
+
:class="{
|
|
7
|
+
'elevation-4': isHovering || isDragging,
|
|
8
|
+
'elevation-0': !(isHovering || isDragging),
|
|
9
|
+
}"
|
|
10
|
+
:style="{
|
|
11
|
+
position: 'relative',
|
|
12
|
+
overflow: 'hidden',
|
|
13
|
+
transition: 'all 0.3s ease',
|
|
14
|
+
background:
|
|
15
|
+
isHovering || isDragging
|
|
16
|
+
? 'rgba(var(--v-theme-primary), 0.05)'
|
|
17
|
+
: 'rgba(0, 0, 0, 0.02)',
|
|
18
|
+
border: `2px dashed ${
|
|
19
|
+
isHovering || isDragging ? 'rgb(var(--v-theme-primary))' : '#e0e0e0'
|
|
20
|
+
}`,
|
|
21
|
+
transform: isHovering || isDragging ? 'translateY(-2px)' : 'none',
|
|
22
|
+
pointerEvents: loading ? 'none' : 'auto',
|
|
23
|
+
opacity: loading ? 0.6 : 1,
|
|
24
|
+
}"
|
|
25
|
+
rounded="xl"
|
|
26
|
+
@click="triggerFileDialog"
|
|
27
|
+
@dragover.prevent="isDragging = true"
|
|
28
|
+
@dragleave.prevent="isDragging = false"
|
|
29
|
+
@drop.prevent="handleDrop"
|
|
30
|
+
>
|
|
31
|
+
<v-card-text class="pa-8">
|
|
32
|
+
<v-sheet
|
|
33
|
+
class="mx-auto mb-6 d-flex align-center justify-center"
|
|
34
|
+
:color="isHovering || isDragging ? 'primary' : 'grey-lighten-2'"
|
|
35
|
+
:elevation="isHovering || isDragging ? 4 : 0"
|
|
36
|
+
rounded="circle"
|
|
37
|
+
width="80"
|
|
38
|
+
height="80"
|
|
39
|
+
style="transition: all 0.3s ease"
|
|
40
|
+
>
|
|
41
|
+
<v-icon
|
|
42
|
+
:icon="loading ? 'mdi-loading' : 'mdi-cloud-upload'"
|
|
43
|
+
size="40"
|
|
44
|
+
:color="isHovering || isDragging ? 'white' : 'grey-darken-1'"
|
|
45
|
+
:class="{ rotating: loading }"
|
|
46
|
+
/>
|
|
47
|
+
</v-sheet>
|
|
48
|
+
|
|
49
|
+
<v-card-title
|
|
50
|
+
class="text-h6 font-weight-bold justify-center pa-0 mb-1"
|
|
51
|
+
:class="
|
|
52
|
+
isHovering || isDragging ? 'text-primary' : 'text-grey-darken-2'
|
|
53
|
+
"
|
|
54
|
+
style="transition: color 0.3s ease"
|
|
55
|
+
>
|
|
56
|
+
{{ loading ? loadingText : isDragging ? dropText : idleText }}
|
|
57
|
+
</v-card-title>
|
|
58
|
+
|
|
59
|
+
<v-card-subtitle v-if="showExtensions" class="text-body-2 pa-0">
|
|
60
|
+
{{ accept ? `(${accept} files)` : "All files allowed" }}
|
|
61
|
+
</v-card-subtitle>
|
|
62
|
+
</v-card-text>
|
|
63
|
+
|
|
64
|
+
<input
|
|
65
|
+
ref="fileInput"
|
|
66
|
+
type="file"
|
|
67
|
+
class="d-none"
|
|
68
|
+
:multiple="multiple"
|
|
69
|
+
:accept="accept"
|
|
70
|
+
@change="handleFileSelect"
|
|
71
|
+
/>
|
|
72
|
+
</v-card>
|
|
73
|
+
</v-hover>
|
|
74
|
+
</template>
|
|
75
|
+
|
|
76
|
+
<script setup>
|
|
77
|
+
const props = defineProps({
|
|
78
|
+
multiple: { type: Boolean, default: false },
|
|
79
|
+
accept: { type: String, default: "" },
|
|
80
|
+
loading: { type: Boolean, default: false },
|
|
81
|
+
showExtensions: { type: Boolean, default: true },
|
|
82
|
+
idleText: { type: String, default: "Click or Drag & Drop files" },
|
|
83
|
+
dropText: { type: String, default: "Drop to upload" },
|
|
84
|
+
loadingText: { type: String, default: "Uploading..." },
|
|
85
|
+
})
|
|
86
|
+
|
|
87
|
+
const emit = defineEmits(["files-selected"])
|
|
88
|
+
|
|
89
|
+
const isDragging = ref(false)
|
|
90
|
+
const fileInput = ref(null)
|
|
91
|
+
|
|
92
|
+
const triggerFileDialog = () => fileInput.value?.click()
|
|
93
|
+
|
|
94
|
+
function handleDrop(e) {
|
|
95
|
+
isDragging.value = false
|
|
96
|
+
const files = Array.from(e.dataTransfer.files)
|
|
97
|
+
emit("files-selected", files)
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
function handleFileSelect(e) {
|
|
101
|
+
const files = Array.from(e.target.files)
|
|
102
|
+
emit("files-selected", files)
|
|
103
|
+
e.target.value = ""
|
|
104
|
+
}
|
|
105
|
+
</script>
|
|
106
|
+
|
|
107
|
+
<style scoped>
|
|
108
|
+
.rotating {
|
|
109
|
+
animation: rotate 1s linear infinite;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
@keyframes rotate {
|
|
113
|
+
from {
|
|
114
|
+
transform: rotate(0deg);
|
|
115
|
+
}
|
|
116
|
+
to {
|
|
117
|
+
transform: rotate(360deg);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
</style>
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
import { useGeodeStore } from "@ogw_front/stores/geode"
|
|
16
16
|
|
|
17
17
|
const schema = schemas.opengeodeweb_back.allowed_files
|
|
18
|
+
|
|
18
19
|
const emit = defineEmits([
|
|
19
20
|
"update_values",
|
|
20
21
|
"increment_step",
|
|
@@ -23,12 +24,10 @@
|
|
|
23
24
|
|
|
24
25
|
const props = defineProps({
|
|
25
26
|
multiple: { type: Boolean, required: true },
|
|
26
|
-
files: { type: Array,
|
|
27
|
-
auto_upload: { type: Boolean,
|
|
27
|
+
files: { type: Array, default: () => [] },
|
|
28
|
+
auto_upload: { type: Boolean, default: true },
|
|
28
29
|
})
|
|
29
30
|
|
|
30
|
-
const { multiple } = props
|
|
31
|
-
|
|
32
31
|
const internal_files = ref(props.files)
|
|
33
32
|
const auto_upload = ref(props.auto_upload)
|
|
34
33
|
const accept = ref("")
|
|
@@ -36,14 +35,13 @@
|
|
|
36
35
|
|
|
37
36
|
watch(
|
|
38
37
|
() => props.files,
|
|
39
|
-
(
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
38
|
+
(val) => (internal_files.value = val),
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
watch(
|
|
42
|
+
() => props.auto_upload,
|
|
43
|
+
(val) => (auto_upload.value = val),
|
|
43
44
|
)
|
|
44
|
-
watch(props.auto_upload, (newVal) => {
|
|
45
|
-
auto_upload.value = newVal
|
|
46
|
-
})
|
|
47
45
|
|
|
48
46
|
const toggle_loading = useToggle(loading)
|
|
49
47
|
|
|
@@ -58,10 +56,9 @@
|
|
|
58
56
|
toggle_loading()
|
|
59
57
|
const geodeStore = useGeodeStore()
|
|
60
58
|
const response = await geodeStore.request(schema, {})
|
|
61
|
-
accept.value = response.extensions
|
|
62
|
-
.map((extension) => "." + extension)
|
|
63
|
-
.join(",")
|
|
59
|
+
accept.value = response.extensions.map((e) => `.${e}`).join(",")
|
|
64
60
|
toggle_loading()
|
|
65
61
|
}
|
|
62
|
+
|
|
66
63
|
await get_allowed_files()
|
|
67
64
|
</script>
|
|
@@ -1,43 +1,65 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
2
|
+
<DragAndDrop
|
|
3
|
+
:multiple="props.multiple"
|
|
4
|
+
:accept="props.accept"
|
|
5
|
+
:loading="loading"
|
|
6
|
+
:show-extensions="false"
|
|
7
|
+
@files-selected="processSelectedFiles"
|
|
8
|
+
/>
|
|
9
|
+
|
|
10
|
+
<v-card-text v-if="internal_files.length" class="mt-4">
|
|
11
|
+
<v-sheet class="d-flex align-center mb-3" color="transparent">
|
|
12
|
+
<v-icon icon="mdi-file-check" class="mr-2" color="primary" />
|
|
13
|
+
<span class="text-subtitle-2 font-weight-bold"> Selected Files </span>
|
|
14
|
+
<v-chip size="x-small" class="ml-2" color="primary" variant="flat">
|
|
15
|
+
{{ internal_files.length }}
|
|
16
|
+
</v-chip>
|
|
17
|
+
</v-sheet>
|
|
18
|
+
|
|
19
|
+
<v-sheet class="d-flex flex-wrap gap-2" color="transparent">
|
|
20
|
+
<v-chip
|
|
21
|
+
v-for="(file, index) in internal_files"
|
|
22
|
+
:key="index"
|
|
23
|
+
closable
|
|
24
|
+
size="small"
|
|
23
25
|
color="primary"
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
26
|
+
variant="tonal"
|
|
27
|
+
class="font-weight-medium"
|
|
28
|
+
@click:close="removeFile(index)"
|
|
29
|
+
>
|
|
30
|
+
<v-icon start size="16">mdi-file-outline</v-icon>
|
|
31
|
+
{{ file.name }}
|
|
32
|
+
</v-chip>
|
|
33
|
+
</v-sheet>
|
|
34
|
+
</v-card-text>
|
|
35
|
+
|
|
36
|
+
<v-card-actions v-if="!props.auto_upload && internal_files.length">
|
|
37
|
+
<v-btn
|
|
38
|
+
color="primary"
|
|
39
|
+
variant="elevated"
|
|
40
|
+
size="large"
|
|
41
|
+
rounded="lg"
|
|
42
|
+
:loading="loading"
|
|
43
|
+
class="text-none px-3 font-weight-bold"
|
|
44
|
+
@click="upload_files"
|
|
45
|
+
>
|
|
46
|
+
<v-icon start size="20">mdi-cloud-upload-outline</v-icon>
|
|
47
|
+
Upload {{ internal_files.length }} file<span
|
|
48
|
+
v-if="internal_files.length > 1"
|
|
49
|
+
>s</span
|
|
28
50
|
>
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
</v-col>
|
|
32
|
-
</v-row>
|
|
51
|
+
</v-btn>
|
|
52
|
+
</v-card-actions>
|
|
33
53
|
</template>
|
|
34
54
|
|
|
35
55
|
<script setup>
|
|
36
56
|
import schemas from "@geode/opengeodeweb-back/opengeodeweb_back_schemas.json"
|
|
37
57
|
import { upload_file } from "@ogw_front/utils/upload_file"
|
|
58
|
+
import DragAndDrop from "@ogw_front/components/DragAndDrop"
|
|
59
|
+
|
|
38
60
|
const schema = schemas.opengeodeweb_back.upload_file
|
|
39
61
|
|
|
40
|
-
const emit = defineEmits(["files_uploaded", "decrement_step"])
|
|
62
|
+
const emit = defineEmits(["files_uploaded", "decrement_step", "reset_values"])
|
|
41
63
|
|
|
42
64
|
const props = defineProps({
|
|
43
65
|
multiple: { type: Boolean, required: true },
|
|
@@ -47,15 +69,28 @@
|
|
|
47
69
|
mini: { type: Boolean, required: false, default: false },
|
|
48
70
|
})
|
|
49
71
|
|
|
50
|
-
const label = props.multiple
|
|
51
|
-
? "Please select file(s) to import"
|
|
52
|
-
: "Please select a file to import"
|
|
53
72
|
const internal_files = ref(props.files)
|
|
54
73
|
const loading = ref(false)
|
|
55
74
|
const files_uploaded = ref(false)
|
|
56
75
|
|
|
57
76
|
const toggle_loading = useToggle(loading)
|
|
58
77
|
|
|
78
|
+
function processSelectedFiles(files) {
|
|
79
|
+
if (props.multiple) {
|
|
80
|
+
internal_files.value = [...internal_files.value, ...files]
|
|
81
|
+
} else {
|
|
82
|
+
internal_files.value = [files[0]]
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function removeFile(index) {
|
|
87
|
+
internal_files.value.splice(index, 1)
|
|
88
|
+
if (internal_files.value.length === 0) {
|
|
89
|
+
files_uploaded.value = false
|
|
90
|
+
emit("files_uploaded", [])
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
59
94
|
async function upload_files() {
|
|
60
95
|
toggle_loading()
|
|
61
96
|
var promise_array = []
|
|
@@ -92,11 +127,6 @@
|
|
|
92
127
|
}
|
|
93
128
|
}
|
|
94
129
|
|
|
95
|
-
function clear() {
|
|
96
|
-
internal_files.value = []
|
|
97
|
-
emit("files_uploaded", internal_files.value)
|
|
98
|
-
}
|
|
99
|
-
|
|
100
130
|
watch(
|
|
101
131
|
() => props.files,
|
|
102
132
|
(newVal) => {
|
|
@@ -107,17 +137,8 @@
|
|
|
107
137
|
|
|
108
138
|
watch(internal_files, (value) => {
|
|
109
139
|
files_uploaded.value = false
|
|
110
|
-
if (props.auto_upload) {
|
|
111
|
-
if (props.multiple.value == false) {
|
|
112
|
-
internal_files.value = [value]
|
|
113
|
-
}
|
|
140
|
+
if (props.auto_upload && value.length > 0) {
|
|
114
141
|
upload_files()
|
|
115
142
|
}
|
|
116
143
|
})
|
|
117
144
|
</script>
|
|
118
|
-
|
|
119
|
-
<style scoped>
|
|
120
|
-
.div.v-input__details {
|
|
121
|
-
display: none;
|
|
122
|
-
}
|
|
123
|
-
</style>
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
<VCol cols="4" class="d-flex justify-center align-center">
|
|
32
32
|
<VBtn
|
|
33
33
|
:text="props.button_label"
|
|
34
|
-
:color="props.button_color"
|
|
34
|
+
:color="props.color || props.button_color"
|
|
35
35
|
@click="submit_recaptcha"
|
|
36
36
|
/>
|
|
37
37
|
</VCol>
|
|
@@ -53,11 +53,16 @@
|
|
|
53
53
|
required: false,
|
|
54
54
|
default: "white",
|
|
55
55
|
},
|
|
56
|
+
color: {
|
|
57
|
+
type: String,
|
|
58
|
+
required: false,
|
|
59
|
+
},
|
|
56
60
|
})
|
|
57
61
|
const infraStore = useInfraStore()
|
|
58
62
|
const name = ref("")
|
|
59
63
|
const email = ref("")
|
|
60
64
|
const launch = ref(false)
|
|
65
|
+
const valid = ref(false)
|
|
61
66
|
const emailRules = [
|
|
62
67
|
(value) => {
|
|
63
68
|
if (value) {
|
package/app/components/Step.vue
CHANGED
|
@@ -1,62 +1,61 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<v-stepper-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
color="grey"
|
|
13
|
-
/>
|
|
14
|
-
<v-icon
|
|
15
|
-
v-else-if="current_step_index == step_index"
|
|
16
|
-
:icon="`mdi-numeric-${step_index + 1}-circle`"
|
|
17
|
-
color="primary"
|
|
18
|
-
/>
|
|
19
|
-
<v-icon
|
|
20
|
-
v-else
|
|
21
|
-
:icon="`mdi-numeric-${step_index + 1}-circle`"
|
|
22
|
-
color="grey"
|
|
23
|
-
/>
|
|
24
|
-
</v-col>
|
|
25
|
-
<v-col>
|
|
26
|
-
<p class="m-0 font-weight-bold">
|
|
27
|
-
{{ steps[step_index].step_title }}
|
|
28
|
-
</p>
|
|
29
|
-
</v-col>
|
|
30
|
-
<v-chip-group
|
|
31
|
-
v-if="
|
|
32
|
-
steps[step_index].chips.length && current_step_index >= step_index
|
|
33
|
-
"
|
|
34
|
-
column
|
|
35
|
-
class="d-flex flex-wrap ma-2 overflow-y-auto"
|
|
36
|
-
multiple
|
|
37
|
-
style="max-height: 150px"
|
|
2
|
+
<v-stepper-vertical-item
|
|
3
|
+
:value="step_index + 1"
|
|
4
|
+
:editable="step_index < current_step_index"
|
|
5
|
+
color="primary"
|
|
6
|
+
hide-actions
|
|
7
|
+
>
|
|
8
|
+
<template #title>
|
|
9
|
+
<v-sheet
|
|
10
|
+
color="transparent"
|
|
11
|
+
class="d-flex flex-column justify-center ps-2"
|
|
38
12
|
>
|
|
39
|
-
<v-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
class="
|
|
43
|
-
|
|
13
|
+
<v-text
|
|
14
|
+
tag="h3"
|
|
15
|
+
class="text-subtitle-1 font-weight-bold mb-0 transition-swing"
|
|
16
|
+
:class="
|
|
17
|
+
current_step_index === step_index
|
|
18
|
+
? 'text-primary'
|
|
19
|
+
: 'text-grey-darken-1'
|
|
20
|
+
"
|
|
44
21
|
>
|
|
45
|
-
{{
|
|
46
|
-
</v-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
22
|
+
{{ steps[step_index].step_title }}
|
|
23
|
+
</v-text>
|
|
24
|
+
|
|
25
|
+
<v-sheet
|
|
26
|
+
v-if="sortedChips.length && current_step_index >= step_index"
|
|
27
|
+
color="transparent"
|
|
28
|
+
class="d-flex flex-wrap mt-2"
|
|
29
|
+
>
|
|
30
|
+
<v-chip
|
|
31
|
+
v-for="(chip, chip_index) in sortedChips"
|
|
32
|
+
:key="chip_index"
|
|
33
|
+
size="small"
|
|
34
|
+
class="me-2 mb-1 font-weight-medium"
|
|
35
|
+
color="primary"
|
|
36
|
+
variant="tonal"
|
|
37
|
+
>
|
|
38
|
+
{{ truncate(chip, 30) }}
|
|
39
|
+
</v-chip>
|
|
40
|
+
</v-sheet>
|
|
41
|
+
</v-sheet>
|
|
42
|
+
</template>
|
|
43
|
+
|
|
44
|
+
<v-card-text class="pt-0">
|
|
45
|
+
<v-divider class="mb-6 opacity-10" />
|
|
46
|
+
|
|
47
|
+
<component
|
|
48
|
+
v-if="step_index === current_step_index"
|
|
49
|
+
:key="step_index"
|
|
50
|
+
:is="steps[step_index].component.component_name"
|
|
51
|
+
v-bind="steps[step_index].component.component_options"
|
|
52
|
+
@increment_step="increment_step"
|
|
53
|
+
@decrement_step="decrement_step"
|
|
54
|
+
@update_values="update_values_event"
|
|
55
|
+
@reset_values="$emit('reset_values')"
|
|
56
|
+
/>
|
|
57
|
+
</v-card-text>
|
|
58
|
+
</v-stepper-vertical-item>
|
|
60
59
|
</template>
|
|
61
60
|
|
|
62
61
|
<script setup>
|
|
@@ -74,9 +73,11 @@
|
|
|
74
73
|
const stepper_tree = inject("stepper_tree")
|
|
75
74
|
const { current_step_index, steps } = toRefs(stepper_tree)
|
|
76
75
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
76
|
+
watch(current_step_index, (newVal, oldVal) => {
|
|
77
|
+
if (newVal < oldVal) {
|
|
78
|
+
stepper_tree.navigating_back = true
|
|
79
|
+
}
|
|
80
|
+
})
|
|
80
81
|
|
|
81
82
|
function update_values_event(keys_values_object) {
|
|
82
83
|
for (const [key, value] of Object.entries(keys_values_object)) {
|
|
@@ -1,20 +1,30 @@
|
|
|
1
1
|
<template>
|
|
2
|
+
<v-card-item class="flex-shrink-0 pa-0">
|
|
3
|
+
<v-card-title
|
|
4
|
+
class="text-h4 text-primary px-8 pt-6 pb-4 font-weight-bold d-flex align-center"
|
|
5
|
+
>
|
|
6
|
+
<v-icon icon="mdi-file-upload-outline" class="mr-3" />
|
|
7
|
+
Import Data
|
|
8
|
+
</v-card-title>
|
|
9
|
+
|
|
10
|
+
<v-card-subtitle class="px-8 pb-4 text-medium">
|
|
11
|
+
Choose a file to import.
|
|
12
|
+
</v-card-subtitle>
|
|
13
|
+
</v-card-item>
|
|
14
|
+
|
|
2
15
|
<v-stepper-vertical
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
16
|
+
:model-value="current_step_index + 1"
|
|
17
|
+
@update:model-value="current_step_index = $event - 1"
|
|
18
|
+
flat
|
|
19
|
+
non-linear
|
|
20
|
+
class="pa-0 ma-0 bg-white rounded-xl overflow-hidden"
|
|
7
21
|
>
|
|
8
|
-
<
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
@reset_values="emit('reset_values')"
|
|
15
|
-
/>
|
|
16
|
-
</v-col>
|
|
17
|
-
</v-stepper-items>
|
|
22
|
+
<Step
|
|
23
|
+
v-for="(step, index) in steps"
|
|
24
|
+
:key="index"
|
|
25
|
+
:step_index="index"
|
|
26
|
+
@reset_values="emit('reset_values')"
|
|
27
|
+
/>
|
|
18
28
|
</v-stepper-vertical>
|
|
19
29
|
</template>
|
|
20
30
|
|
|
@@ -10,15 +10,19 @@ const autoStoreRegister = ({ store }) => {
|
|
|
10
10
|
console.log(`[AutoRegister] Store "${store.$id}" processed`)
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
-
export default defineNuxtPlugin(
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
13
|
+
export default defineNuxtPlugin({
|
|
14
|
+
name: "auto-store-register",
|
|
15
|
+
dependsOn: ["pinia"],
|
|
16
|
+
setup(nuxtApp) {
|
|
17
|
+
const { $pinia } = nuxtApp
|
|
18
|
+
if (!$pinia) {
|
|
19
|
+
console.warn("Pinia instance not available.")
|
|
20
|
+
return
|
|
21
|
+
}
|
|
19
22
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
23
|
+
$pinia.use(autoStoreRegister)
|
|
24
|
+
console.log(
|
|
25
|
+
"[AUTOREGISTER PLUGIN] Loaded automatically from OpenGeodeWeb-Front",
|
|
26
|
+
)
|
|
27
|
+
},
|
|
24
28
|
})
|
package/app/stores/data.js
CHANGED
|
@@ -103,7 +103,7 @@ export const useDataStore = defineStore("data", () => {
|
|
|
103
103
|
|
|
104
104
|
async function addModelComponents(values) {
|
|
105
105
|
if (!values || values.length === 0) {
|
|
106
|
-
console.
|
|
106
|
+
console.debug("[addModelComponents] No mesh components to add")
|
|
107
107
|
return
|
|
108
108
|
}
|
|
109
109
|
values.map((value) => {
|
|
@@ -32,6 +32,9 @@ export function useModelBlocksStyle() {
|
|
|
32
32
|
modelBlockStyle(id, block_id).visibility = visibility
|
|
33
33
|
}
|
|
34
34
|
async function setModelBlocksVisibility(id, block_ids, visibility) {
|
|
35
|
+
if (!block_ids || block_ids.length === 0) {
|
|
36
|
+
return
|
|
37
|
+
}
|
|
35
38
|
const blocks_viewer_ids = await dataStore.getMeshComponentsViewerIds(
|
|
36
39
|
id,
|
|
37
40
|
block_ids,
|
|
@@ -70,6 +73,9 @@ export function useModelBlocksStyle() {
|
|
|
70
73
|
}
|
|
71
74
|
|
|
72
75
|
async function setModelBlocksColor(id, block_ids, color) {
|
|
76
|
+
if (!block_ids || block_ids.length === 0) {
|
|
77
|
+
return
|
|
78
|
+
}
|
|
73
79
|
const blocks_viewer_ids = await dataStore.getMeshComponentsViewerIds(
|
|
74
80
|
id,
|
|
75
81
|
block_ids,
|
|
@@ -32,6 +32,9 @@ export function useModelCornersStyle() {
|
|
|
32
32
|
modelCornerStyle(id, corner_id).visibility = visibility
|
|
33
33
|
}
|
|
34
34
|
async function setModelCornersVisibility(id, corner_ids, visibility) {
|
|
35
|
+
if (!corner_ids || corner_ids.length === 0) {
|
|
36
|
+
return
|
|
37
|
+
}
|
|
35
38
|
const corner_viewer_ids = await dataStore.getMeshComponentsViewerIds(
|
|
36
39
|
id,
|
|
37
40
|
corner_ids,
|
|
@@ -71,6 +74,9 @@ export function useModelCornersStyle() {
|
|
|
71
74
|
}
|
|
72
75
|
|
|
73
76
|
async function setModelCornersColor(id, corner_ids, color) {
|
|
77
|
+
if (!corner_ids || corner_ids.length === 0) {
|
|
78
|
+
return
|
|
79
|
+
}
|
|
74
80
|
const corner_viewer_ids = await dataStore.getMeshComponentsViewerIds(
|
|
75
81
|
id,
|
|
76
82
|
corner_ids,
|
|
@@ -32,6 +32,9 @@ export function useModelLinesStyle() {
|
|
|
32
32
|
modelLineStyle(id, line_id).visibility = visibility
|
|
33
33
|
}
|
|
34
34
|
async function setModelLinesVisibility(id, line_ids, visibility) {
|
|
35
|
+
if (!line_ids || line_ids.length === 0) {
|
|
36
|
+
return
|
|
37
|
+
}
|
|
35
38
|
const line_viewer_ids = await dataStore.getMeshComponentsViewerIds(
|
|
36
39
|
id,
|
|
37
40
|
line_ids,
|
|
@@ -69,6 +72,9 @@ export function useModelLinesStyle() {
|
|
|
69
72
|
modelLineStyle(id, line_id).color = color
|
|
70
73
|
}
|
|
71
74
|
async function setModelLinesColor(id, line_ids, color) {
|
|
75
|
+
if (!line_ids || line_ids.length === 0) {
|
|
76
|
+
return
|
|
77
|
+
}
|
|
72
78
|
const line_viewer_ids = await dataStore.getMeshComponentsViewerIds(
|
|
73
79
|
id,
|
|
74
80
|
line_ids,
|
|
@@ -31,6 +31,9 @@ export function useModelSurfacesStyle() {
|
|
|
31
31
|
modelSurfaceStyle(id, surface_id).visibility = visibility
|
|
32
32
|
}
|
|
33
33
|
async function setModelSurfacesVisibility(id, surface_ids, visibility) {
|
|
34
|
+
if (!surface_ids || surface_ids.length === 0) {
|
|
35
|
+
return
|
|
36
|
+
}
|
|
34
37
|
const surface_viewer_ids = await dataStore.getMeshComponentsViewerIds(
|
|
35
38
|
id,
|
|
36
39
|
surface_ids,
|
|
@@ -68,6 +71,9 @@ export function useModelSurfacesStyle() {
|
|
|
68
71
|
}
|
|
69
72
|
|
|
70
73
|
async function setModelSurfacesColor(id, surface_ids, color) {
|
|
74
|
+
if (!surface_ids || surface_ids.length === 0) {
|
|
75
|
+
return
|
|
76
|
+
}
|
|
71
77
|
const surface_viewer_ids = await dataStore.getMeshComponentsViewerIds(
|
|
72
78
|
id,
|
|
73
79
|
surface_ids,
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@geode/opengeodeweb-front",
|
|
3
3
|
"description": "OpenSource Vue/Nuxt/Pinia/Vuetify framework for web applications",
|
|
4
4
|
"type": "module",
|
|
5
|
-
"version": "10.2.
|
|
5
|
+
"version": "10.2.1-rc.1",
|
|
6
6
|
"main": "./nuxt.config.js",
|
|
7
7
|
"scripts": {
|
|
8
8
|
"lint": "eslint --fix --ext .js,.vue --ignore-path .gitignore .",
|
|
@@ -46,11 +46,13 @@ describe("FileSelector", async () => {
|
|
|
46
46
|
handler: () => ({}),
|
|
47
47
|
})
|
|
48
48
|
|
|
49
|
-
const v_file_input = file_uploader.
|
|
50
|
-
await v_file_input.trigger("click")
|
|
49
|
+
const v_file_input = file_uploader.find('input[type="file"]')
|
|
51
50
|
const files = [new File(["fake_file"], "fake_file.txt")]
|
|
52
51
|
const auto_upload = false
|
|
53
|
-
|
|
52
|
+
Object.defineProperty(v_file_input.element, "files", {
|
|
53
|
+
value: files,
|
|
54
|
+
writable: true,
|
|
55
|
+
})
|
|
54
56
|
await v_file_input.trigger("change")
|
|
55
57
|
const v_btn = wrapper.findComponent(components.VBtn)
|
|
56
58
|
await v_btn.trigger("click")
|
|
@@ -43,10 +43,11 @@ describe("FileUploader", async () => {
|
|
|
43
43
|
props: { multiple: false, accept: "*.txt" },
|
|
44
44
|
})
|
|
45
45
|
|
|
46
|
-
const v_file_input = wrapper.
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
46
|
+
const v_file_input = wrapper.find('input[type="file"]')
|
|
47
|
+
Object.defineProperty(v_file_input.element, "files", {
|
|
48
|
+
value: files,
|
|
49
|
+
writable: true,
|
|
50
|
+
})
|
|
50
51
|
await v_file_input.trigger("change")
|
|
51
52
|
const v_btn = wrapper.findComponent(components.VBtn)
|
|
52
53
|
|
|
@@ -55,10 +55,12 @@ describe("MissingFilesSelector", async () => {
|
|
|
55
55
|
const file_uploader = wrapper.findComponent(FileUploader)
|
|
56
56
|
expect(file_uploader.exists()).toBe(true)
|
|
57
57
|
|
|
58
|
-
const v_file_input = file_uploader.
|
|
59
|
-
await v_file_input.trigger("click")
|
|
58
|
+
const v_file_input = file_uploader.find('input[type="file"]')
|
|
60
59
|
const files = [new File(["fake_file"], "fake_file.txt")]
|
|
61
|
-
|
|
60
|
+
Object.defineProperty(v_file_input.element, "files", {
|
|
61
|
+
value: files,
|
|
62
|
+
writable: true,
|
|
63
|
+
})
|
|
62
64
|
await v_file_input.trigger("change")
|
|
63
65
|
const v_btn = file_uploader.findComponent(components.VBtn)
|
|
64
66
|
|