Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
10 changes: 9 additions & 1 deletion app/components/Viewer/ObjectTree/Views/GlobalObjects.vue
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,15 @@ const {
availableFilterOptions,
toggleSort,
customFilter,
applySearchFilter,
} = useTreeFilter(toRef(() => treeviewStore.items));

function onUpdateSelection(val) {
treeviewStore.selection = applySearchFilter(val, treeviewStore.selection);
}

const visibleSelection = computed(() => applySearchFilter(treeviewStore.selection, []));

watch(
() => treeviewStore.selection,
async (current, previous) => {
Expand Down Expand Up @@ -94,7 +101,7 @@ function handleHoverLeave(item) {
/>

<v-treeview
v-model:selected="treeviewStore.selection"
:selected="visibleSelection"
v-model:opened="opened"
:items="processedItems"
:search="search"
Expand All @@ -104,6 +111,7 @@ function handleHoverLeave(item) {
select-strategy="classic"
selectable
items-registration="props"
@update:selected="onUpdateSelection"
>
<template #title="{ item }">
<ObjectTreeItemLabel
Expand Down
10 changes: 7 additions & 3 deletions app/components/Viewer/ObjectTree/Views/ModelComponents.vue
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,11 @@ const {
availableFilterOptions,
toggleSort,
customFilter,
applySearchFilter,
} = useTreeFilter(items);

async function onSelectionChange(current) {
async function onSelectionChange(newSelection) {
const current = applySearchFilter(newSelection, mesh_components_selection.value);
const previous = mesh_components_selection.value;
const { added, removed } = compareSelections(current, previous);

Expand All @@ -55,6 +57,8 @@ async function onSelectionChange(current) {
hybridViewerStore.remoteRender();
}

const visibleSelection = computed(() => applySearchFilter(mesh_components_selection.value, []));

function showContextMenu(event, item) {
const actualItem = item.raw || item;
emit("show-menu", {
Expand Down Expand Up @@ -93,14 +97,14 @@ function handleHoverLeave() {

<v-treeview
v-else
:selected="mesh_components_selection"
:selected="visibleSelection"
v-model:opened="opened"
:items="processedItems"
:search="search"
:custom-filter="customFilter"
class="transparent-treeview"
item-value="id"
select-strategy="independent"
select-strategy="classic"
selectable
items-registration="props"
@update:selected="onSelectionChange"
Expand Down
49 changes: 43 additions & 6 deletions app/composables/use_tree_filter.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,8 @@ function customFilter(value, searchQuery, item) {
return true;
}
const query = searchQuery.toLowerCase();
const title = (item.raw.title || "").toLowerCase();
const idValue = String(value || "").toLowerCase();
return title.includes(query) || idValue.includes(query);
const { title = "", id = value } = item.raw || {};
return [title, id].some((field) => String(field).toLowerCase().includes(query));
}

function sortAndFormatItems(items, sortType) {
Expand All @@ -21,8 +20,6 @@ function sortAndFormatItems(items, sortType) {
});
return {
...category,
id: category.id,
title: category.title || category.id,
children,
};
});
Expand Down Expand Up @@ -56,19 +53,58 @@ function useTreeFilter(rawItems, options = {}) {
if (!rawItems.value) {
return [];
}
return sortAndFormatItems(
const sorted = sortAndFormatItems(
rawItems.value.filter((category) => {
const key = category.title || category.id;
return filterOptions.value[key] !== false;
}),
sortType.value,
);
if (!search.value) {
return sorted;
}
return sorted
.map((category) => {
category.children = (category.children || []).filter((child) =>
customFilter(child.id, search.value, { raw: child }),
);
return category;
})
.filter((category) => category.children.length > 0);
});

function toggleSort() {
sortType.value = sortType.value === "name" ? "id" : "name";
}

const allItems = computed(() => {
const map = new Map();
function traverse(items) {
for (const item of items) {
map.set(item.id, item);
if (item.children) {
traverse(item.children);
}
}
}
traverse(rawItems.value || []);
return map;
});

function applySearchFilter(newSelection, previousSelection = []) {
if (!search.value) {
return newSelection;
}
const allItemsMap = allItems.value;
function matches(id) {
const item = allItemsMap.get(id);
return item && customFilter(id, search.value, { raw: item });
}
const hidden = previousSelection.filter((id) => !matches(id));
const visible = newSelection.filter((id) => matches(id));
return [...new Set([...hidden, ...visible])];
}

return {
search,
sortType,
Expand All @@ -77,6 +113,7 @@ function useTreeFilter(rawItems, options = {}) {
availableFilterOptions,
toggleSort,
customFilter,
applySearchFilter,
};
}

Expand Down
Loading