Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
5697f22
feat(MultipleTreeview): Add a new system for objects tree, multiple t…
SpliiT Apr 13, 2026
fe6192d
import & other
SpliiT Apr 13, 2026
bc9d34f
icon dynamic
SpliiT Apr 13, 2026
60c57c7
rm comments
SpliiT Apr 13, 2026
b00bda5
Apply prepare changes
SpliiT Apr 13, 2026
706862a
rm comments
SpliiT Apr 13, 2026
ca98ca7
Merge branch 'feat/MultipleObjectTree' of https://github.com/Geode-so…
SpliiT Apr 13, 2026
66dc527
Apply prepare changes
SpliiT Apr 13, 2026
9056114
on off btn
SpliiT Apr 13, 2026
d4d27f7
Merge branch 'feat/MultipleObjectTree' of https://github.com/Geode-so…
SpliiT Apr 13, 2026
cf85f6e
Size duplicate instead of split
SpliiT Apr 13, 2026
96209e4
Apply prepare changes
SpliiT Apr 13, 2026
c47b12f
bigger smallest size
SpliiT Apr 13, 2026
e0156b5
Merge branch 'feat/MultipleObjectTree' of https://github.com/Geode-so…
SpliiT Apr 13, 2026
04abf14
oxlint fix
SpliiT Apr 13, 2026
a1708d5
Apply prepare changes
SpliiT Apr 13, 2026
0d4e3d7
oxlint
SpliiT Apr 13, 2026
4e23cdf
Merge branch 'feat/MultipleObjectTree' of https://github.com/Geode-so…
SpliiT Apr 13, 2026
3cca529
Apply prepare changes
SpliiT Apr 13, 2026
6485f65
changes comments
SpliiT Apr 14, 2026
bbf4b71
Apply prepare changes
SpliiT Apr 14, 2026
d730bed
apply changes comments
SpliiT Apr 14, 2026
9ca6438
Merge branch 'feat/MultipleObjectTree' of https://github.com/Geode-so…
SpliiT Apr 14, 2026
c7bc261
Apply prepare changes
SpliiT Apr 14, 2026
0c99945
rename, imports, and define funciton out of the return
SpliiT Apr 14, 2026
72368b1
Apply prepare changes
SpliiT Apr 14, 2026
6cc622d
state of scroll and tree
SpliiT Apr 15, 2026
b85fa23
Apply prepare changes
SpliiT Apr 15, 2026
5dfe973
oxlint
SpliiT Apr 15, 2026
f4cf4dd
Merge branch 'feat/MultipleObjectTree' of https://github.com/Geode-so…
SpliiT Apr 15, 2026
c1ae78a
oximport
SpliiT Apr 15, 2026
4c4ded8
Apply prepare changes
SpliiT Apr 15, 2026
df115ea
oxliny
SpliiT Apr 15, 2026
870b0cc
Merge branch 'feat/MultipleObjectTree' of https://github.com/Geode-so…
SpliiT Apr 15, 2026
e3cfa30
imports for tests
SpliiT Apr 15, 2026
01e1fd8
rm imports
SpliiT Apr 15, 2026
14560bc
Apply prepare changes
SpliiT Apr 15, 2026
a5d1b51
trigger
SpliiT Apr 15, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 0 additions & 49 deletions app/components/Viewer/BreadCrumb.vue

This file was deleted.

58 changes: 58 additions & 0 deletions app/components/Viewer/ObjectTree/Base/Controls.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
<script setup>
import ActionButton from "@ogw_front/components/ActionButton.vue";
import SearchBar from "@ogw_front/components/SearchBar.vue";

const { search, sortType, filterOptions, availableFilterOptions } = defineProps({
search: { type: String, required: true },
sortType: { type: String, required: true },
filterOptions: { type: Object, required: true },
availableFilterOptions: { type: Array, required: true },
});

const emit = defineEmits(["update:search", "toggle-sort"]);
</script>

<template>
<v-row dense align="center" class="pa-2">
<v-col>
<SearchBar
:model-value="search"
label="Search"
color="black"
base-color="black"
@update:model-value="emit('update:search', $event)"
/>
</v-col>
<v-col cols="auto" class="d-flex align-center">
<ActionButton
:tooltip="'Sort by ' + (sortType === 'name' ? 'ID' : 'Name')"
:icon="
sortType === 'name' ? 'mdi-sort-alphabetical-ascending' : 'mdi-sort-numeric-ascending'
"
tooltipLocation="bottom"
@click="emit('toggle-sort')"
/>
<v-menu :close-on-content-click="false">
<template #activator="{ props: menuProps }">
<ActionButton
tooltip="Filter options"
icon="mdi-filter-variant"
tooltipLocation="bottom"
class="ml-1"
v-bind="menuProps"
/>
</template>
<v-list class="mt-1">
<v-list-item v-for="category_id in availableFilterOptions" :key="category_id">
<v-checkbox
v-model="filterOptions[category_id]"
:label="category_id"
hide-details
density="compact"
/>
</v-list-item>
</v-list>
</v-menu>
</v-col>
</v-row>
</template>
49 changes: 49 additions & 0 deletions app/components/Viewer/ObjectTree/Base/ItemLabel.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<script setup>
const { item, showTooltip } = defineProps({
item: { type: Object, required: true },
showTooltip: { type: Boolean, default: false },
});

const emit = defineEmits(["contextmenu"]);

const actualItem = computed(() => item.raw || item);
</script>

<template>
<span
class="tree-item-label"
:class="{ 'inactive-item': actualItem.is_active === false }"
@contextmenu.prevent.stop="emit('contextmenu', $event)"
>
{{ actualItem.title }}
<v-tooltip v-if="showTooltip && actualItem.category" activator="parent" location="right">
<div class="d-flex flex-column pa-1">
<span class="text-caption"><strong>ID:</strong> {{ actualItem.id }}</span>
<span v-if="actualItem.title" class="text-caption"
><strong>Name:</strong> {{ actualItem.title }}</span
>
<span class="text-caption font-italic border-t-sm d-flex align-center">
<strong class="mr-1">Status:</strong>
{{ actualItem.is_active ? "Active" : "Inactive" }}
</span>
</div>
</v-tooltip>
</span>
</template>

<style scoped>
.tree-item-label {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
max-width: 100%;
display: inline-flex;
align-items: center;
cursor: pointer;
}

.inactive-item {
opacity: 0.4;
font-style: italic;
}
</style>
132 changes: 132 additions & 0 deletions app/components/Viewer/ObjectTree/Box.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
<script setup>
const SCROLL_SYNC_DELAY = 50;
const SCROLL_THRESHOLD = 1;
const { title, closable, icon, mdiIcon, scrollTop } = defineProps({
title: { type: String, required: true },
closable: { type: Boolean, default: false },
icon: { type: String, default: "" },
mdiIcon: { type: String, default: "" },
scrollTop: { type: Number, default: 0 },
});

const emit = defineEmits(["close", "dragstart", "update:scrollTop"]);

const scrollContainer = ref(undefined);
let isApplyingScroll = false;
let resizeObserver = undefined;

function handleScroll(event) {
if (isApplyingScroll) {
return;
}
emit("update:scrollTop", event.target.scrollTop);
}

function applyScrollTop(val) {
if (scrollContainer.value) {
isApplyingScroll = true;
scrollContainer.value.scrollTop = val;
setTimeout(() => {
isApplyingScroll = false;
}, SCROLL_SYNC_DELAY);
}
}

onMounted(() => {
if (scrollContainer.value) {
applyScrollTop(scrollTop);

resizeObserver = new ResizeObserver(() => {
if (
scrollContainer.value &&
Math.abs(scrollContainer.value.scrollTop - scrollTop) > SCROLL_THRESHOLD
) {
applyScrollTop(scrollTop);
}
});

resizeObserver.observe(scrollContainer.value);
}
});

onUnmounted(() => {
if (resizeObserver) {
resizeObserver.disconnect();
}
});

watch(
() => scrollTop,
(newVal) => {
if (
scrollContainer.value &&
Math.abs(scrollContainer.value.scrollTop - newVal) > SCROLL_THRESHOLD
) {
applyScrollTop(newVal);
}
},
);
</script>

<template>
<v-card variant="outlined" class="tree-box d-flex flex-column">
<v-card-title
class="tree-box-header d-flex align-center"
:class="{ 'cursor-grab': closable }"
:draggable="closable"
@dragstart="emit('dragstart', $event)"
>
<v-img
v-if="icon"
:src="icon"
width="24"
height="24"
max-width="24"
class="mr-2"
style="filter: brightness(0); display: flex; align-items: center"
/>
<v-icon v-else-if="mdiIcon" size="24" class="mr-2">{{ mdiIcon }}</v-icon>
<v-icon v-else-if="closable" size="24" class="mr-2">mdi-drag-variant</v-icon>
<span
class="text-subtitle-2 font-weight-bold d-inline-flex align-center"
style="height: 24px; line-height: 1"
>
{{ title }}
</span>
<v-spacer />
<v-btn
v-if="closable"
icon="mdi-close"
variant="text"
size="x-small"
@click="emit('close')"
/>
</v-card-title>
<v-divider />
<v-card-text class="pa-0 flex-grow-1 overflow-hidden d-flex flex-column">
<div
ref="scrollContainer"
class="flex-grow-1 overflow-y-auto overflow-x-hidden"
@scroll="handleScroll"
>
<slot />
</div>
</v-card-text>
</v-card>
</template>

<style scoped>
.tree-box {
height: 100%;
border-radius: 16px;
background-color: transparent !important;
backdrop-filter: blur(2px);
border: 1px solid rgba(0, 0, 0, 0.2);
}

.tree-box-header {
height: 40px !important;
padding: 0 8px !important;
background-color: rgba(255, 255, 255, 0.1);
}
</style>
Loading
Loading