diff --git a/InvenTree/part/test_api.py b/InvenTree/part/test_api.py index 6644a6cea7..4862750ae8 100644 --- a/InvenTree/part/test_api.py +++ b/InvenTree/part/test_api.py @@ -472,6 +472,34 @@ class PartCategoryAPITest(InvenTreeAPITestCase): self.assertEqual(path[1]['name'], 'IC') self.assertEqual(path[2]['name'], 'MCU') + def test_part_category_tree(self): + """Test the PartCategoryTree API endpoint.""" + # Create a number of new part categories + loc = None + + for idx in range(50): + loc = PartCategory.objects.create( + name=f'Test Category {idx}', + description=f'Test category {idx}', + parent=loc, + ) + + PartCategory.objects.rebuild() + + with self.assertNumQueriesLessThan(10): + response = self.get(reverse('api-part-category-tree'), expected_code=200) + + self.assertEqual(len(response.data), PartCategory.objects.count()) + + for item in response.data: + category = PartCategory.objects.get(pk=item['pk']) + parent = category.parent.pk if category.parent else None + subcategories = category.get_descendants(include_self=False).count() + + self.assertEqual(item['name'], category.name) + self.assertEqual(item['parent'], parent) + self.assertEqual(item['subcategories'], subcategories) + class PartOptionsAPITest(InvenTreeAPITestCase): """Tests for the various OPTIONS endpoints in the /part/ API. diff --git a/InvenTree/stock/serializers.py b/InvenTree/stock/serializers.py index 4574c7728d..cae8460a41 100644 --- a/InvenTree/stock/serializers.py +++ b/InvenTree/stock/serializers.py @@ -865,7 +865,7 @@ class LocationTreeSerializer(InvenTree.serializers.InvenTreeModelSerializer): @staticmethod def annotate_queryset(queryset): """Annotate the queryset with the number of sublocations.""" - return queryset.annotate(sublocations=Count('children')) + return queryset.annotate(sublocations=stock.filters.annotate_sub_locations()) class LocationSerializer(InvenTree.serializers.InvenTreeTagModelSerializer): diff --git a/InvenTree/stock/test_api.py b/InvenTree/stock/test_api.py index ca237d2029..42de5d7b8f 100644 --- a/InvenTree/stock/test_api.py +++ b/InvenTree/stock/test_api.py @@ -434,6 +434,32 @@ class StockLocationTest(StockAPITestCase): self.assertEqual(len(res), 1) + def test_stock_location_tree(self): + """Test the StockLocationTree API endpoint.""" + # Create a number of new locations + loc = None + + for idx in range(50): + loc = StockLocation.objects.create( + name=f'Location {idx}', description=f'Test location {idx}', parent=loc + ) + + StockLocation.objects.rebuild() + + with self.assertNumQueriesLessThan(10): + response = self.get(reverse('api-location-tree'), expected_code=200) + + self.assertEqual(len(response.data), StockLocation.objects.count()) + + for item in response.data: + location = StockLocation.objects.get(pk=item['pk']) + parent = location.parent.pk if location.parent else None + sublocations = location.get_descendants(include_self=False).count() + + self.assertEqual(item['name'], location.name) + self.assertEqual(item['parent'], parent) + self.assertEqual(item['sublocations'], sublocations) + class StockLocationTypeTest(StockAPITestCase): """Tests for the StockLocationType API endpoints.""" diff --git a/src/frontend/src/components/nav/BreadcrumbList.tsx b/src/frontend/src/components/nav/BreadcrumbList.tsx index b76c20be21..ef45cc7b6a 100644 --- a/src/frontend/src/components/nav/BreadcrumbList.tsx +++ b/src/frontend/src/components/nav/BreadcrumbList.tsx @@ -7,6 +7,7 @@ import { Text } from '@mantine/core'; import { IconMenu2 } from '@tabler/icons-react'; +import { useMemo } from 'react'; import { useNavigate } from 'react-router-dom'; export type Breadcrumb = { @@ -26,6 +27,19 @@ export function BreadcrumbList({ }) { const navigate = useNavigate(); + const elements = useMemo(() => { + // Limit to 7 active elements + if (breadcrumbs.length > 7) { + return [ + ...breadcrumbs.slice(0, 3), + { name: '...', url: '#' }, + ...breadcrumbs.slice(-3) + ]; + } else { + return breadcrumbs; + } + }, [breadcrumbs]); + return ( @@ -35,7 +49,7 @@ export function BreadcrumbList({ )} - {breadcrumbs.map((breadcrumb, index) => { + {elements.map((breadcrumb, index) => { return (