diff --git a/InvenTree/InvenTree/static/script/inventree/part.js b/InvenTree/InvenTree/static/script/inventree/part.js index 05b209b9b8..927afca2e6 100644 --- a/InvenTree/InvenTree/static/script/inventree/part.js +++ b/InvenTree/InvenTree/static/script/inventree/part.js @@ -87,7 +87,7 @@ function loadPartTable(table, url, options={}) { * buttons: If provided, link buttons to selection status of this table */ - var params = options.parms || {}; + var params = options.params || {}; var filters = loadTableFilters("parts"); diff --git a/InvenTree/part/api.py b/InvenTree/part/api.py index 7d193fa1ee..629136af05 100644 --- a/InvenTree/part/api.py +++ b/InvenTree/part/api.py @@ -153,6 +153,7 @@ class PartList(generics.ListCreateAPIView): The Part object list can be filtered by: - category: Filter by PartCategory reference - cascade: If true, include parts from sub-categories + - starred: Is the part "starred" by the current user? - is_template: Is the part a template part? - variant_of: Filter by variant_of Part reference - assembly: Filter by assembly field @@ -295,31 +296,50 @@ class PartList(generics.ListCreateAPIView): def get_queryset(self): - # Does the user wish to filter by category? - cat_id = self.request.query_params.get('category', None) # Start with all objects parts_list = Part.objects.all() - cascade = str2bool(self.request.query_params.get('cascade', False)) + # Filter by 'starred' parts? + starred = str2bool(self.request.query_params.get('starred', None)) + + if starred is not None: + starred_parts = [star.part.pk for star in self.request.user.starred_parts.all()] + + if starred: + parts_list = parts_list.filter(pk__in=starred_parts) + else: + parts_list = parts_list.exclude(pk__in=starred_parts) + + cascade = str2bool(self.request.query_params.get('cascade', None)) + + # Does the user wish to filter by category? + cat_id = self.request.query_params.get('category', None) if cat_id is None: - # Top-level parts - if not cascade: - parts_list = parts_list.filter(category=None) - + # No category filtering if category is not specified + pass + else: - try: - category = PartCategory.objects.get(pk=cat_id) + # Category has been specified! + if isNull(cat_id): + # A 'null' category is the top-level category + if cascade is False: + # Do not cascade, only list parts in the top-level category + parts_list = parts_list.filter(category=None) - # If '?cascade=true' then include parts which exist in sub-categories - if cascade: - parts_list = parts_list.filter(category__in=category.getUniqueChildren()) - # Just return parts directly in the requested category - else: - parts_list = parts_list.filter(category=cat_id) - except (ValueError, PartCategory.DoesNotExist): - pass + else: + try: + category = PartCategory.objects.get(pk=cat_id) + + # If '?cascade=true' then include parts which exist in sub-categories + if cascade: + parts_list = parts_list.filter(category__in=category.getUniqueChildren()) + # Just return parts directly in the requested category + else: + parts_list = parts_list.filter(category=cat_id) + except (ValueError, PartCategory.DoesNotExist): + pass # Ensure that related models are pre-loaded to reduce DB trips parts_list = self.get_serializer_class().setup_eager_loading(parts_list) diff --git a/InvenTree/part/templates/part/category.html b/InvenTree/part/templates/part/category.html index cc663a63c4..63a60bd71e 100644 --- a/InvenTree/part/templates/part/category.html +++ b/InvenTree/part/templates/part/category.html @@ -200,11 +200,11 @@ {% if category %} $("#cat-edit").click(function () { launchModalForm( - "{% url 'category-edit' category.id %}", - { - reload: true - }, - ); + "{% url 'category-edit' category.id %}", + { + reload: true + }, + ); return false; }); @@ -227,9 +227,9 @@ "#part-table", "{% url 'api-part-list' %}", { - query: { - {% if category %} - category: {{ category.id }}, + params: { + {% if category %}category: {{ category.id }}, + {% else %}category: "null", {% endif %} }, buttons: ['#part-options'],