Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
192f967
fix(LoaderComponents): Add loader and new logic for components loader
SpliiT Apr 22, 2026
4d21ae7
Apply prepare changes
SpliiT Apr 22, 2026
9c0ba90
big changes : new treeview system
SpliiT Apr 23, 2026
647292f
Apply prepare changes
SpliiT Apr 23, 2026
8cb5770
Scroll and other
SpliiT Apr 23, 2026
1f7c43e
Merge branch 'fix/AddLoaderTreeview' of https://github.com/Geode-solu…
SpliiT Apr 23, 2026
ccbcedd
remove conflit
SpliiT Apr 23, 2026
54c21cc
backgorund adaptater
SpliiT Apr 23, 2026
7d92c7e
backgorund adaptater
SpliiT Apr 23, 2026
8f5b5b8
Merge branch 'fix/AddLoaderTreeview' of https://github.com/Geode-solu…
SpliiT Apr 23, 2026
1229663
Merge branch 'next' of https://github.com/Geode-solutions/OpenGeodeWe…
SpliiT Apr 23, 2026
82f6ee7
Apply prepare changes
SpliiT Apr 23, 2026
97b623e
background colo adaptative
SpliiT Apr 23, 2026
f7ee5c6
oxlint
SpliiT Apr 23, 2026
f1bd489
Merge branch 'fix/AddLoaderTreeview' of https://github.com/Geode-solu…
SpliiT Apr 23, 2026
c675fca
Apply prepare changes
SpliiT Apr 23, 2026
aa7e4de
go for color
SpliiT Apr 23, 2026
b4a4670
Merge branch 'fix/AddLoaderTreeview' of https://github.com/Geode-solu…
SpliiT Apr 23, 2026
9c6bb4f
Apply prepare changes
SpliiT Apr 23, 2026
7fb7e27
add blur
SpliiT Apr 24, 2026
8f62f6a
Merge branch 'fix/AddLoaderTreeview' of https://github.com/Geode-solu…
SpliiT Apr 24, 2026
896f8a2
Apply prepare changes
SpliiT Apr 24, 2026
6d4e63f
rm comments
SpliiT Apr 24, 2026
ccef0ac
Merge branch 'fix/AddLoaderTreeview' of https://github.com/Geode-solu…
SpliiT Apr 24, 2026
843f9ca
Apply prepare changes
SpliiT Apr 24, 2026
5c31078
clean code
SpliiT Apr 24, 2026
402846b
Merge branch 'fix/AddLoaderTreeview' of https://github.com/Geode-solu…
SpliiT Apr 24, 2026
38575e0
Apply prepare changes
SpliiT Apr 24, 2026
fc03543
fix comments
SpliiT Apr 24, 2026
22cd805
Merge branch 'fix/AddLoaderTreeview' of https://github.com/Geode-solu…
SpliiT Apr 24, 2026
e8d771e
fix comments toref
SpliiT Apr 24, 2026
fe7a726
Apply prepare changes
SpliiT Apr 24, 2026
dcf2350
oclint
SpliiT Apr 24, 2026
96dbd10
Merge branch 'fix/AddLoaderTreeview' of https://github.com/Geode-solu…
SpliiT Apr 24, 2026
a982f96
clean code
SpliiT Apr 24, 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
142 changes: 142 additions & 0 deletions app/components/Viewer/ObjectTree/Base/CommonTreeView.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
<script setup>
import StickyHeader from "@ogw_front/components/Viewer/ObjectTree/Base/StickyHeader.vue";
import TreeRow from "@ogw_front/components/Viewer/ObjectTree/Base/TreeRow.vue";
import { useTreeScroll } from "@ogw_front/composables/use_tree_scroll";
import { useVirtualTree } from "@ogw_front/composables/use_virtual_tree";

const {
items,
opened = [],
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
opened = [],
opened,

selected = [],
scrollTop = 0,
options = {},
} = defineProps({
Comment thread
SpliiT marked this conversation as resolved.
items: { type: Array, required: true },
opened: { type: Array },
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
opened: { type: Array },
opened: { type: Array, required: false, default: [] },

Même commentaire pour les autres

selected: { type: Array },
scrollTop: { type: Number },
options: { type: Object },
});

const emit = defineEmits(["update:opened", "update:selected", "click:item", "update:scrollTop"]);

const {
actualItemProps,
actualSelection,
displayItems,
toggleOpen,
toggleSelect,
isSelected,
getIndeterminate,
} = useVirtualTree(
computed(() => ({
items,
opened,
selected,
...options,
})),
emit,
);

const { virtualScrollRef, stickyHeader, handleScroll } = useTreeScroll(
computed(() => ({ scrollTop })),
emit,
displayItems,
actualItemProps,
);

function handleItemClick(item) {
if (item.isLeaf) {
toggleSelect(item.raw);
emit("click:item", item.raw);
} else {
toggleOpen(item.raw);
}
}
</script>

<template>
<div class="common-tree-view-wrapper">
<StickyHeader
v-if="stickyHeader"
:item="stickyHeader"
:item-props="actualItemProps"
:selection="actualSelection"
:is-selected="isSelected"
:get-indeterminate="getIndeterminate"
@toggle-open="toggleOpen"
@toggle-select="toggleSelect"
>
<template #title="slotProps">
<slot name="title" v-bind="slotProps" />
</template>
</StickyHeader>

<v-virtual-scroll
ref="virtualScrollRef"
:items="displayItems"
:item-height="actualItemProps.height"
class="common-tree-view"
@scroll="handleScroll"
>
<template #default="{ item }">
<v-list-item
:class="['tree-row-wrapper', { 'leaf-row': item.isLeaf }]"
class="pa-0"
@click="handleItemClick(item)"
>
<TreeRow
:item="item"
:item-props="actualItemProps"
:selection="actualSelection"
:is-selected="isSelected"
:get-indeterminate="getIndeterminate"
@toggle-open="toggleOpen"
@toggle-select="toggleSelect"
>
<template #title="slotProps">
<slot name="title" v-bind="slotProps" />
</template>
<template #append="slotProps">
<slot name="append" v-bind="slotProps" />
</template>
</TreeRow>
</v-list-item>
</template>
</v-virtual-scroll>
</div>
</template>

<style scoped>
.common-tree-view-wrapper {
height: 100%;
position: relative;
display: flex;
flex-direction: column;
min-height: 0;
}

.common-tree-view {
flex-grow: 1;
min-height: 0;
overflow-y: auto !important;
}

.tree-row-wrapper {
min-height: 44px !important;
cursor: pointer;
}

:deep(.v-list-item__content) {
padding: 0 !important;
display: block !important;
}

:deep(.v-list-item__overlay) {
display: none !important;
}

.v-list-item:hover {
background-color: rgba(0, 0, 0, 0.04);
}
</style>
9 changes: 8 additions & 1 deletion app/components/Viewer/ObjectTree/Base/Controls.vue
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ const { search, sortType, filterOptions, availableFilterOptions } = defineProps(
availableFilterOptions: { type: Array, required: true },
});

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

<template>
Expand Down Expand Up @@ -53,6 +53,13 @@ const emit = defineEmits(["update:search", "toggle-sort"]);
</v-list-item>
</v-list>
</v-menu>
<ActionButton
tooltip="Collapse All"
icon="mdi-collapse-all-outline"
tooltipLocation="bottom"
class="ml-1"
@click="emit('collapse-all')"
/>
</v-col>
</v-row>
</template>
61 changes: 43 additions & 18 deletions app/components/Viewer/ObjectTree/Base/ItemLabel.vue
Original file line number Diff line number Diff line change
@@ -1,37 +1,62 @@
<script setup>
const { item, showTooltip } = defineProps({
const { item, isLeaf = undefined } = defineProps({
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
const { item, isLeaf = undefined } = defineProps({
const { item, isLeaf } = defineProps({

item: { type: Object, required: true },
showTooltip: { type: Boolean, default: false },
isLeaf: { type: Boolean },
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
isLeaf: { type: Boolean },
isLeaf: { type: Boolean, required: false: default: undefined },

});

const emit = defineEmits(["contextmenu"]);
const emit = defineEmits(["contextmenu", "mouseenter", "mouseleave"]);

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

const tooltipDisabled = computed(() => {
if (isLeaf !== undefined) {
return !isLeaf;
}
return actualItem.value.children && actualItem.value.children.length > 0;
});
</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
<div class="tree-item-label-container w-100">
<v-tooltip :disabled="tooltipDisabled" location="right" open-delay="400">
<template #activator="{ props: tooltipProps }">
<span
v-bind="tooltipProps"
class="tree-item-label"
:class="{ 'inactive-item': actualItem.is_active === false }"
@contextmenu.prevent.stop="emit('contextmenu', $event)"
@mouseenter="emit('mouseenter')"
@mouseleave="emit('mouseleave')"
>
<span class="text-caption font-italic border-t-sm d-flex align-center">
<strong class="mr-1">Status:</strong>
{{ actualItem.is_active ? "Active" : "Inactive" }}
{{ actualItem.title }}
</span>
</template>

<div class="d-flex flex-column ga-1">
<span class="text-caption">
<strong class="text-white">ID:</strong> {{ actualItem.id }}
</span>
<span v-if="actualItem.title" class="text-caption">
<strong class="text-white">Name:</strong> {{ actualItem.title }}
</span>
<span class="text-caption">
<strong class="text-white">Status:</strong>
<i class="ml-1">{{ actualItem.is_active ? "Active" : "Inactive" }}</i>
</span>
</div>
</v-tooltip>
</span>
</div>
</template>

<style scoped>
.tree-item-label-container {
display: flex;
align-items: center;
min-width: 0;
height: 100%;
width: 100%;
}

.tree-item-label {
white-space: nowrap;
overflow: hidden;
Expand Down
46 changes: 46 additions & 0 deletions app/components/Viewer/ObjectTree/Base/StickyHeader.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<script setup>
import TreeRow from "@ogw_front/components/Viewer/ObjectTree/Base/TreeRow.vue";

const { item, itemProps, selection, isSelected, getIndeterminate } = defineProps({
item: { type: Object, required: true },
itemProps: { type: Object, required: true },
selection: { type: Object, required: true },
isSelected: { type: Function, required: true },
getIndeterminate: { type: Function, required: true },
});

defineEmits(["toggle-open", "toggle-select"]);
</script>

<template>
<div class="sticky-tree-header tree-row" @click="$emit('toggle-open', item.raw)">
<TreeRow
:item="item"
:item-props="itemProps"
:selection="selection"
:is-selected="isSelected"
:get-indeterminate="getIndeterminate"
@toggle-open="$emit('toggle-open', $event)"
@toggle-select="$emit('toggle-select', $event)"
>
<template #title="slotProps">
<slot name="title" v-bind="slotProps" />
</template>
</TreeRow>
</div>
</template>

<style scoped>
.sticky-tree-header {
flex-shrink: 0;
background-color: transparent;
border-bottom: 2px solid rgba(0, 0, 0, 0.05);
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
cursor: pointer;
z-index: 20;
}

.sticky-tree-header:hover {
background-color: rgba(0, 0, 0, 0.04);
}
</style>
75 changes: 75 additions & 0 deletions app/components/Viewer/ObjectTree/Base/TreeRow.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
<script setup>
const { item, itemProps, selection, isSelected, getIndeterminate } = defineProps({
item: { type: Object, required: true },
itemProps: { type: Object, required: true },
selection: { type: Object, required: true },
isSelected: { type: Function, required: true },
getIndeterminate: { type: Function, required: true },
});

defineEmits(["toggle-open", "toggle-select"]);

const INDENT_STEP = 16;
</script>

<template>
<div class="tree-row-content d-flex align-center px-4 ps-3 w-100">
<div
v-if="item.depth > 0"
class="flex-shrink-0"
:style="{ width: `${item.depth * INDENT_STEP}px` }"
/>

<div class="d-flex align-center flex-shrink-0">
<v-icon
v-if="!item.isLeaf"
:icon="item.isOpen ? 'mdi-menu-down' : 'mdi-menu-right'"
class="me-1"
color="black"
@click.stop="$emit('toggle-open', item.raw)"
/>
<div v-else class="icon-placeholder" />

<v-checkbox-btn
v-if="selection.selectable"
:model-value="isSelected(item.raw)"
:indeterminate="getIndeterminate(item.raw)"
density="compact"
hide-details
color="black"
@click.stop="$emit('toggle-select', item.raw)"
@mousedown.stop
/>
</div>

<div class="tree-title flex-grow-1 overflow-hidden d-flex align-center ms-1 pt-1">
<slot name="title" :item="item.raw" :is-leaf="item.isLeaf">
<v-list-item-title :class="{ 'font-weight-bold': !item.isLeaf }" class="text-black">
{{ item.raw[itemProps.title] || item.id }}
</v-list-item-title>
</slot>
</div>

<div class="ms-auto d-flex align-center">
<slot name="append" :item="item.raw" />
</div>
</div>
</template>

<style scoped>
.tree-row-content {
min-height: 44px;
}

.icon-placeholder {
width: 24px;
}

.tree-title {
min-height: 24px;
}

:deep(.v-checkbox-btn .v-selection-control__input .v-icon) {
color: #000 !important;
}
</style>
Loading
Loading