mirror of
https://github.com/inventree/InvenTree.git
synced 2025-04-28 19:46:46 +00:00
Tree fix (#6583)
* PartCategoryTree - add "subcategories" field * Fix rendering of PartCategoryTree * Implement similar fixes for StockLocationTree * Bump API version * Breadcrumb list tweak - Limit to 7 items * Fix bug for stock tree serializer * Add unit tests
This commit is contained in:
parent
de23023277
commit
bb105d8c08
@ -472,6 +472,34 @@ class PartCategoryAPITest(InvenTreeAPITestCase):
|
|||||||
self.assertEqual(path[1]['name'], 'IC')
|
self.assertEqual(path[1]['name'], 'IC')
|
||||||
self.assertEqual(path[2]['name'], 'MCU')
|
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):
|
class PartOptionsAPITest(InvenTreeAPITestCase):
|
||||||
"""Tests for the various OPTIONS endpoints in the /part/ API.
|
"""Tests for the various OPTIONS endpoints in the /part/ API.
|
||||||
|
@ -865,7 +865,7 @@ class LocationTreeSerializer(InvenTree.serializers.InvenTreeModelSerializer):
|
|||||||
@staticmethod
|
@staticmethod
|
||||||
def annotate_queryset(queryset):
|
def annotate_queryset(queryset):
|
||||||
"""Annotate the queryset with the number of sublocations."""
|
"""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):
|
class LocationSerializer(InvenTree.serializers.InvenTreeTagModelSerializer):
|
||||||
|
@ -434,6 +434,32 @@ class StockLocationTest(StockAPITestCase):
|
|||||||
|
|
||||||
self.assertEqual(len(res), 1)
|
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):
|
class StockLocationTypeTest(StockAPITestCase):
|
||||||
"""Tests for the StockLocationType API endpoints."""
|
"""Tests for the StockLocationType API endpoints."""
|
||||||
|
@ -7,6 +7,7 @@ import {
|
|||||||
Text
|
Text
|
||||||
} from '@mantine/core';
|
} from '@mantine/core';
|
||||||
import { IconMenu2 } from '@tabler/icons-react';
|
import { IconMenu2 } from '@tabler/icons-react';
|
||||||
|
import { useMemo } from 'react';
|
||||||
import { useNavigate } from 'react-router-dom';
|
import { useNavigate } from 'react-router-dom';
|
||||||
|
|
||||||
export type Breadcrumb = {
|
export type Breadcrumb = {
|
||||||
@ -26,6 +27,19 @@ export function BreadcrumbList({
|
|||||||
}) {
|
}) {
|
||||||
const navigate = useNavigate();
|
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 (
|
return (
|
||||||
<Paper p="3" radius="xs">
|
<Paper p="3" radius="xs">
|
||||||
<Group spacing="xs">
|
<Group spacing="xs">
|
||||||
@ -35,7 +49,7 @@ export function BreadcrumbList({
|
|||||||
</ActionIcon>
|
</ActionIcon>
|
||||||
)}
|
)}
|
||||||
<Breadcrumbs key="breadcrumbs" separator=">">
|
<Breadcrumbs key="breadcrumbs" separator=">">
|
||||||
{breadcrumbs.map((breadcrumb, index) => {
|
{elements.map((breadcrumb, index) => {
|
||||||
return (
|
return (
|
||||||
<Anchor
|
<Anchor
|
||||||
key={index}
|
key={index}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user