@geode/opengeodeweb-front 10.12.0 → 10.13.0

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,132 +0,0 @@
1
- <script setup>
2
- import ViewerBreadCrumb from "@ogw_front/components/Viewer/BreadCrumb";
3
- import ViewerTreeComponent from "@ogw_front/components/Viewer/TreeComponent";
4
- import ViewerTreeObject from "@ogw_front/components/Viewer/TreeObject";
5
- import { useTreeviewStore } from "@ogw_front/stores/treeview";
6
-
7
- const WIDTH_MIN = 150;
8
-
9
- const treeviewStore = useTreeviewStore();
10
- const emit = defineEmits(["show-menu"]);
11
-
12
- function onResizeStart(event) {
13
- const startWidth = treeviewStore.panelWidth;
14
- const startX = event.clientX;
15
- function resize(move_event) {
16
- const deltaX = move_event.clientX - startX;
17
- const newWidth = Math.max(WIDTH_MIN, Math.min(startWidth + deltaX, window.innerWidth));
18
- treeviewStore.setPanelWidth(newWidth);
19
- document.body.style.userSelect = "none";
20
- }
21
- function stopResize() {
22
- document.removeEventListener("mousemove", resize);
23
- document.removeEventListener("mouseup", stopResize);
24
- document.body.style.userSelect = "";
25
- }
26
- document.addEventListener("mousemove", resize);
27
- document.addEventListener("mouseup", stopResize);
28
- }
29
- </script>
30
-
31
- <template>
32
- <v-container
33
- class="treeview-container"
34
- :style="{ width: `${treeviewStore.panelWidth}px` }"
35
- @contextmenu.prevent
36
- @mousedown.stop
37
- >
38
- <v-row class="resizable-panel" :style="{ width: `${treeviewStore.panelWidth}px` }">
39
- <div class="scrollable-wrapper">
40
- <v-sheet style="max-height: calc(85vh)" class="transparent-treeview scrollbar-hover">
41
- <v-row v-if="treeviewStore.items.length > 0">
42
- <v-col>
43
- <ViewerBreadCrumb />
44
- </v-col>
45
- </v-row>
46
- <v-row>
47
- <v-col>
48
- <ViewerTreeObject
49
- v-if="!treeviewStore.isAdditionnalTreeDisplayed"
50
- @show-menu="emit('show-menu', $event)"
51
- />
52
- <ViewerTreeComponent
53
- v-else
54
- @show-menu="emit('show-menu', $event)"
55
- :id="treeviewStore.model_id"
56
- />
57
- </v-col>
58
- </v-row>
59
- </v-sheet>
60
- </div>
61
- <div class="resizer" @mousedown="onResizeStart"></div>
62
- </v-row>
63
- </v-container>
64
- </template>
65
-
66
- <style scoped>
67
- .treeview-container {
68
- position: absolute;
69
- z-index: 2;
70
- left: 0;
71
- top: 0;
72
- background-color: transparent;
73
- border-radius: 16px;
74
- padding: 8px;
75
- display: flex;
76
- box-sizing: border-box;
77
- }
78
-
79
- .resizable-panel {
80
- display: flex;
81
- height: 100%;
82
- position: relative;
83
- box-sizing: border-box;
84
- }
85
-
86
- .scrollable-wrapper {
87
- overflow-y: auto;
88
- padding-right: 6px;
89
- flex: 1;
90
- }
91
-
92
- .resizer {
93
- position: absolute;
94
- top: 0;
95
- right: 0;
96
- width: 6px;
97
- height: 100%;
98
- cursor: ew-resize;
99
- background-color: transparent;
100
- z-index: 15;
101
- }
102
-
103
- .resizer:hover {
104
- background-color: #999;
105
- }
106
-
107
- .resizer:active {
108
- background-color: #666;
109
- }
110
-
111
- .transparent-treeview {
112
- background-color: transparent;
113
- margin: 4px 0;
114
- }
115
-
116
- .scrollbar-hover {
117
- overflow-x: hidden;
118
- }
119
-
120
- .scrollbar-hover::-webkit-scrollbar {
121
- width: 5px;
122
- }
123
-
124
- .scrollbar-hover::-webkit-scrollbar-thumb {
125
- background-color: transparent;
126
- }
127
-
128
- .scrollbar-hover:hover::-webkit-scrollbar-thumb {
129
- background-color: rgba(0, 0, 0, 0.3);
130
- border-radius: 10px;
131
- }
132
- </style>
@@ -1,170 +0,0 @@
1
- <script setup>
2
- import ActionButton from "@ogw_front/components/ActionButton.vue";
3
- import SearchBar from "@ogw_front/components/SearchBar.vue";
4
- import { compareSelections } from "@ogw_front/utils/treeview";
5
- import { useDataStore } from "@ogw_front/stores/data";
6
- import { useDataStyleStore } from "@ogw_front/stores/data_style";
7
- import { useHybridViewerStore } from "@ogw_front/stores/hybrid_viewer";
8
-
9
- const dataStyleStore = useDataStyleStore();
10
- const dataStore = useDataStore();
11
- const hybridViewerStore = useHybridViewerStore();
12
-
13
- const { id } = defineProps({ id: { type: String, required: true } });
14
- const emit = defineEmits(["show-menu"]);
15
-
16
- const items = dataStore.refFormatedMeshComponents(toRef(() => id));
17
- const mesh_components_selection = dataStyleStore.visibleMeshComponents(toRef(() => id));
18
-
19
- const search = ref("");
20
- const sortType = ref("name");
21
- const filterOptions = ref({
22
- Corner: true,
23
- Line: true,
24
- Surface: true,
25
- Block: true,
26
- });
27
-
28
- const processedItems = computed(() =>
29
- items.value
30
- .filter((category) => filterOptions.value[category.id])
31
- .map((category) => {
32
- const field = sortType.value === "name" ? "title" : "id";
33
- const children = (category.children || []).toSorted((first, second) =>
34
- first[field].localeCompare(second[field]),
35
- );
36
- return { id: category.id, title: category.title, children };
37
- }),
38
- );
39
-
40
- const availableFilterOptions = computed(() => items.value.map((category) => category.id));
41
-
42
- function toggleSort() {
43
- sortType.value = sortType.value === "name" ? "id" : "name";
44
- }
45
-
46
- function customFilter(value, searchQuery, item) {
47
- if (!searchQuery) {
48
- return true;
49
- }
50
- const query = searchQuery.toLowerCase();
51
- return (
52
- item.raw.title.toLowerCase().includes(query) ||
53
- (item.raw.id && item.raw.id.toLowerCase().includes(query))
54
- );
55
- }
56
-
57
- async function onSelectionChange(current) {
58
- const previous = mesh_components_selection.value;
59
- const { added, removed } = compareSelections(current, previous);
60
-
61
- if (added.length === 0 && removed.length === 0) {
62
- return;
63
- }
64
-
65
- if (added.length > 0) {
66
- await dataStyleStore.setModelComponentsVisibility(id, added, true);
67
- }
68
- if (removed.length > 0) {
69
- await dataStyleStore.setModelComponentsVisibility(id, removed, false);
70
- }
71
- hybridViewerStore.remoteRender();
72
- }
73
- </script>
74
-
75
- <template>
76
- <v-row dense align="center" class="mr-1 ml-3 mt-2 pa-1">
77
- <v-col>
78
- <SearchBar v-model="search" label="Search" color="black" base-color="black" />
79
- </v-col>
80
- <v-col cols="auto" class="d-flex align-center">
81
- <ActionButton
82
- :tooltip="'Sort by ' + (sortType === 'name' ? 'ID' : 'Name')"
83
- :icon="
84
- sortType === 'name' ? 'mdi-sort-alphabetical-ascending' : 'mdi-sort-numeric-ascending'
85
- "
86
- tooltipLocation="bottom"
87
- @click="toggleSort"
88
- />
89
- <v-menu :close-on-content-click="false">
90
- <template #activator="{ props }">
91
- <ActionButton
92
- tooltip="Filter options"
93
- icon="mdi-filter-variant"
94
- tooltipLocation="bottom"
95
- class="ml-1"
96
- v-bind="props"
97
- />
98
- </template>
99
- <v-list class="mt-1">
100
- <v-list-item v-for="category_id in availableFilterOptions" :key="category_id">
101
- <v-checkbox
102
- v-model="filterOptions[category_id]"
103
- :label="category_id"
104
- hide-details
105
- density="compact"
106
- />
107
- </v-list-item>
108
- </v-list>
109
- </v-menu>
110
- </v-col>
111
- </v-row>
112
- <v-treeview
113
- :selected="mesh_components_selection"
114
- :items="processedItems"
115
- :search="search"
116
- :custom-filter="customFilter"
117
- class="transparent-treeview"
118
- item-value="id"
119
- select-strategy="independent"
120
- selectable
121
- @update:selected="onSelectionChange"
122
- >
123
- <template #title="{ item }">
124
- <span
125
- class="treeview-item"
126
- :class="{ 'inactive-item': item.is_active === false }"
127
- @contextmenu.prevent.stop="
128
- emit('show-menu', {
129
- event: $event,
130
- itemId: item.id,
131
- context_type: 'model_component',
132
- modelId: id,
133
- })
134
- "
135
- >
136
- {{ item.title }}
137
- <v-tooltip v-if="item.category" activator="parent" location="right">
138
- <div class="d-flex flex-column pa-1">
139
- <span class="text-caption"><strong>ID:</strong> {{ item.id }}</span>
140
- <span v-if="item.title" class="text-caption"
141
- ><strong>Name:</strong> {{ item.title }}</span
142
- >
143
- <span class="text-caption font-italic border-t-sm d-flex align-center">
144
- <strong class="mr-1">Status:</strong> {{ item.is_active ? "Active" : "Inactive" }}
145
- </span>
146
- </div>
147
- </v-tooltip>
148
- </span>
149
- </template>
150
- </v-treeview>
151
- </template>
152
-
153
- <style scoped>
154
- .treeview-item {
155
- white-space: nowrap;
156
- overflow: hidden;
157
- text-overflow: ellipsis;
158
- max-width: 100%;
159
- display: inline-block;
160
- }
161
- .inactive-item {
162
- opacity: 0.4;
163
- font-style: italic;
164
- }
165
-
166
- .transparent-treeview {
167
- background-color: transparent;
168
- margin: 4px 0;
169
- }
170
- </style>
@@ -1,184 +0,0 @@
1
- <script setup>
2
- import ActionButton from "@ogw_front/components/ActionButton.vue";
3
- import SearchBar from "@ogw_front/components/SearchBar.vue";
4
- import { useDataStyleStore } from "@ogw_front/stores/data_style";
5
- import { useHybridViewerStore } from "@ogw_front/stores/hybrid_viewer";
6
- import { useTreeviewStore } from "@ogw_front/stores/treeview";
7
-
8
- import { compareSelections } from "@ogw_front/utils/treeview";
9
-
10
- const treeviewStore = useTreeviewStore();
11
- const dataStyleStore = useDataStyleStore();
12
- const hybridViewerStore = useHybridViewerStore();
13
-
14
- const emit = defineEmits(["show-menu"]);
15
-
16
- const search = ref("");
17
- const sortType = ref("name");
18
- const filterOptions = ref({});
19
-
20
- const processedItems = computed(() =>
21
- treeviewStore.items
22
- .filter((category) => filterOptions.value[category.title] !== false)
23
- .map((category) => {
24
- const field = sortType.value === "name" ? "title" : "id";
25
- const children = (category.children || []).toSorted((first, second) =>
26
- first[field].localeCompare(second[field], undefined, {
27
- numeric: true,
28
- sensitivity: "base",
29
- }),
30
- );
31
- return { id: category.title, title: category.title, children };
32
- }),
33
- );
34
-
35
- const availableFilterOptions = computed(() =>
36
- treeviewStore.items.map((category) => category.title),
37
- );
38
-
39
- watch(
40
- availableFilterOptions,
41
- (newOptions) => {
42
- for (const option of newOptions) {
43
- if (filterOptions.value[option] === undefined) {
44
- filterOptions.value[option] = true;
45
- }
46
- }
47
- },
48
- { immediate: true },
49
- );
50
-
51
- function toggleSort() {
52
- sortType.value = sortType.value === "name" ? "id" : "name";
53
- }
54
-
55
- function customFilter(value, searchQuery, item) {
56
- if (!searchQuery) {
57
- return true;
58
- }
59
- const query = searchQuery.toLowerCase();
60
- return (
61
- item.raw.title.toLowerCase().includes(query) ||
62
- (item.raw.id && item.raw.id.toLowerCase().includes(query))
63
- );
64
- }
65
-
66
- function isLeafNode(item) {
67
- return !item.children || item.children.length === 0;
68
- }
69
-
70
- watch(
71
- () => treeviewStore.selection,
72
- async (current, previous) => {
73
- const oldSelection = previous || [];
74
- if (current === oldSelection) {
75
- return;
76
- }
77
- const { added, removed } = compareSelections(current, previous);
78
- const updates = [
79
- ...added.map((id) => dataStyleStore.setVisibility(id, true)),
80
- ...removed.map((id) => dataStyleStore.setVisibility(id, false)),
81
- ];
82
- await Promise.all(updates);
83
- hybridViewerStore.remoteRender();
84
- },
85
- );
86
-
87
- function isModel(item) {
88
- return item.viewer_type === "model";
89
- }
90
-
91
- onMounted(() => {
92
- const savedSelection = treeviewStore.selection;
93
- if (savedSelection && savedSelection.length > 0) {
94
- treeviewStore.selection = savedSelection;
95
- }
96
- });
97
- </script>
98
-
99
- <template>
100
- <v-row v-if="treeviewStore.items.length > 0" dense align="center" class="mr-1 ml-3 mt-2 pa-1">
101
- <v-col>
102
- <SearchBar v-model="search" label="Search" color="black" base-color="black" />
103
- </v-col>
104
- <v-col cols="auto" class="d-flex align-center">
105
- <ActionButton
106
- :tooltip="'Sort by ' + (sortType === 'name' ? 'ID' : 'Name')"
107
- :icon="
108
- sortType === 'name' ? 'mdi-sort-alphabetical-ascending' : 'mdi-sort-numeric-ascending'
109
- "
110
- tooltipLocation="bottom"
111
- @click="toggleSort"
112
- />
113
- <v-menu :close-on-content-click="false">
114
- <template #activator="{ props }">
115
- <ActionButton
116
- tooltip="Filter options"
117
- icon="mdi-filter-variant"
118
- tooltipLocation="bottom"
119
- class="ml-1"
120
- v-bind="props"
121
- />
122
- </template>
123
- <v-list class="mt-1">
124
- <v-list-item v-for="category_id in availableFilterOptions" :key="category_id">
125
- <v-checkbox
126
- v-model="filterOptions[category_id]"
127
- :label="category_id"
128
- hide-details
129
- density="compact"
130
- />
131
- </v-list-item>
132
- </v-list>
133
- </v-menu>
134
- </v-col>
135
- </v-row>
136
- <v-treeview
137
- v-model:selected="treeviewStore.selection"
138
- :items="processedItems"
139
- :search="search"
140
- :custom-filter="customFilter"
141
- class="transparent-treeview"
142
- item-value="id"
143
- select-strategy="classic"
144
- selectable
145
- >
146
- <template #title="{ item }">
147
- <span
148
- class="treeview-item"
149
- @contextmenu.prevent.stop="
150
- isLeafNode(item) ? emit('show-menu', { event: $event, itemId: item.id }) : null
151
- "
152
- >
153
- {{ item.title }}
154
- </span>
155
- </template>
156
-
157
- <template #append="{ item }">
158
- <v-btn
159
- v-if="isModel(item)"
160
- icon="mdi-magnify-expand"
161
- size="medium"
162
- class="ml-8"
163
- variant="text"
164
- v-tooltip="'Model\'s mesh components'"
165
- @click.stop="treeviewStore.displayAdditionalTree(item.id)"
166
- />
167
- </template>
168
- </v-treeview>
169
- </template>
170
-
171
- <style scoped>
172
- .transparent-treeview {
173
- background-color: transparent;
174
- margin: 4px 0;
175
- }
176
-
177
- .treeview-item {
178
- white-space: nowrap;
179
- overflow: hidden;
180
- text-overflow: ellipsis;
181
- max-width: 100%;
182
- display: inline-block;
183
- }
184
- </style>