Auto-expand to the selected ID
This commit is contained in:
parent
102cbe0497
commit
1b9d44f577
|
|
@ -331,6 +331,7 @@ class CategoryTree(ListAPI):
|
|||
"""Filter the queryset, and include all ancestors of matched items when searching."""
|
||||
queryset = super().filter_queryset(queryset)
|
||||
|
||||
# If a search term is provided, include all ancestors of matched items in the results
|
||||
if self.request.query_params.get('search', '').strip():
|
||||
ancestors = PartCategory.objects.get_queryset_ancestors(
|
||||
queryset, include_self=True
|
||||
|
|
@ -338,6 +339,17 @@ class CategoryTree(ListAPI):
|
|||
queryset = (queryset | ancestors).distinct()
|
||||
queryset = part_serializers.CategoryTree.annotate_queryset(queryset)
|
||||
|
||||
# If a specific ID is provided to "expand_to", include all ancestors of that item in the results
|
||||
expand_to = self.request.query_params.get('expand_to')
|
||||
if expand_to:
|
||||
try:
|
||||
target = PartCategory.objects.get(pk=int(expand_to))
|
||||
ancestors = target.get_ancestors(include_self=True)
|
||||
queryset = (queryset | ancestors).distinct()
|
||||
queryset = part_serializers.CategoryTree.annotate_queryset(queryset)
|
||||
except (PartCategory.DoesNotExist, ValueError):
|
||||
pass
|
||||
|
||||
return queryset
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -84,36 +84,54 @@ export default function NavigationTree({
|
|||
// Data query — browse mode loads root nodes only; search mode loads all matches + ancestors
|
||||
const query = useQuery({
|
||||
enabled: opened,
|
||||
queryKey: [modelType, 'tree', opened, debouncedSearch],
|
||||
queryKey: [modelType, 'tree', opened, debouncedSearch, selectedId],
|
||||
queryFn: async () =>
|
||||
api
|
||||
.get(apiUrl(endpoint), {
|
||||
params: {
|
||||
ordering: 'level',
|
||||
search: debouncedSearch || undefined,
|
||||
max_level: debouncedSearch ? undefined : 0
|
||||
max_level: debouncedSearch ? undefined : 0,
|
||||
expand_to: debouncedSearch ? undefined : (selectedId ?? undefined)
|
||||
}
|
||||
})
|
||||
.then((response) => response.data ?? [])
|
||||
});
|
||||
|
||||
// When the browse-mode query settles, reset accumulated node list
|
||||
// When the browse-mode query settles, reset accumulated node list and expand to selected node
|
||||
useEffect(() => {
|
||||
if (!debouncedSearch && query.data && !query.isFetching) {
|
||||
setAllNodes(query.data);
|
||||
setFetchedNodes(new Set());
|
||||
|
||||
if (selectedId) {
|
||||
const nodeMap: Record<number, any> = {};
|
||||
for (const n of query.data) nodeMap[n.pk] = n;
|
||||
|
||||
// Walk from the selected node up to the root, expanding each ancestor
|
||||
let current = nodeMap[selectedId];
|
||||
while (current?.parent) {
|
||||
treeState.expand(current.parent.toString());
|
||||
current = nodeMap[current.parent];
|
||||
}
|
||||
}
|
||||
}
|
||||
}, [debouncedSearch, query.data, query.isFetching, selectedId]);
|
||||
|
||||
// Collapse all nodes when the search term changes (switching modes).
|
||||
// Intentionally omits query.data so it does NOT fire when browse results arrive —
|
||||
// that would undo the ancestor expansion done in the sync effect above.
|
||||
useEffect(() => {
|
||||
treeState.collapseAllNodes();
|
||||
}, [debouncedSearch]);
|
||||
|
||||
// Expand all nodes once search results have fully arrived
|
||||
useEffect(() => {
|
||||
if (debouncedSearch && !query.isFetching && query.data?.length) {
|
||||
treeState.expandAllNodes();
|
||||
}
|
||||
}, [debouncedSearch, query.data, query.isFetching]);
|
||||
|
||||
// Expand all nodes when a search is active so ancestors are visible
|
||||
useEffect(() => {
|
||||
if (debouncedSearch) {
|
||||
treeState.expandAllNodes();
|
||||
} else {
|
||||
treeState.collapseAllNodes();
|
||||
}
|
||||
}, [debouncedSearch, query.data]);
|
||||
|
||||
// Fetch direct children of a node (browse mode only); no-op if already fetched
|
||||
const fetchChildren = useCallback(
|
||||
async (nodeValue: string) => {
|
||||
|
|
@ -280,7 +298,7 @@ export default function NavigationTree({
|
|||
return (
|
||||
<Drawer
|
||||
opened={opened}
|
||||
size='md'
|
||||
size='lg'
|
||||
position='left'
|
||||
onClose={onClose}
|
||||
withCloseButton={true}
|
||||
|
|
|
|||
Loading…
Reference in New Issue