@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.
- package/app/components/Viewer/ObjectTree/Base/Controls.vue +58 -0
- package/app/components/Viewer/ObjectTree/Base/ItemLabel.vue +49 -0
- package/app/components/Viewer/ObjectTree/Box.vue +132 -0
- package/app/components/Viewer/ObjectTree/Layout.vue +320 -0
- package/app/components/Viewer/ObjectTree/Views/GlobalObjects.vue +129 -0
- package/app/components/Viewer/ObjectTree/Views/ModelComponents.vue +113 -0
- package/app/components/Viewer/Ui.vue +2 -2
- package/app/composables/use_tree_filter.js +77 -0
- package/app/stores/treeview.js +175 -98
- package/internal/database/base_database.js +1 -0
- package/package.json +1 -1
- package/app/components/Viewer/BreadCrumb.vue +0 -49
- package/app/components/Viewer/Tree/ObjectTree.vue +0 -132
- package/app/components/Viewer/TreeComponent.vue +0 -170
- package/app/components/Viewer/TreeObject.vue +0 -184
|
@@ -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>
|