Skip to content

Commit

Permalink
Merge pull request #1493 from SchrodingersGat/multi-location-print
Browse files Browse the repository at this point in the history
Split "part category" view into separate pages
  • Loading branch information
SchrodingersGat committed Apr 20, 2021
2 parents 21708da + 4d1eb51 commit 9addad9
Show file tree
Hide file tree
Showing 17 changed files with 525 additions and 135 deletions.
41 changes: 28 additions & 13 deletions InvenTree/part/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,28 +60,43 @@ class CategoryList(generics.ListCreateAPIView):
queryset = PartCategory.objects.all()
serializer_class = part_serializers.CategorySerializer

def get_queryset(self):
def filter_queryset(self, queryset):
"""
Custom filtering:
- Allow filtering by "null" parent to retrieve top-level part categories
"""

cat_id = self.request.query_params.get('parent', None)
queryset = super().filter_queryset(queryset)

params = self.request.query_params

queryset = super().get_queryset()
cat_id = params.get('parent', None)

if cat_id is not None:
cascade = str2bool(params.get('cascade', False))

# Do not filter by category
if cat_id is None:
pass
# Look for top-level categories
elif isNull(cat_id):

# Look for top-level categories
if isNull(cat_id):
if not cascade:
queryset = queryset.filter(parent=None)

else:
try:
cat_id = int(cat_id)
queryset = queryset.filter(parent=cat_id)
except ValueError:
pass

else:
try:
category = PartCategory.objects.get(pk=cat_id)

if cascade:
parents = category.get_descendants(include_self=True)
parent_ids = [p.id for p in parents]

queryset = queryset.filter(parent__in=parent_ids)
else:
queryset = queryset.filter(parent=category)

except (ValueError, PartCategory.DoesNotExist):
pass

return queryset

Expand Down
28 changes: 8 additions & 20 deletions InvenTree/part/templates/part/category.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@
{% load static %}
{% load i18n %}

{% block menubar %}
{% include 'part/category_navbar.html' with tab='parts' %}
{% endblock %}

{% block content %}

<div class='panel panel-default panel-inventree'>
Expand Down Expand Up @@ -100,14 +104,10 @@ <h3>{% trans "Category Details" %}</h3>
</div>
</div>

{% if category and category.children.all|length > 0 %}
{% include "part/subcategories.html" with children=category.children.all collapse_id="categories" %}
{% elif children|length > 0 %}
{% include "part/subcategories.html" with children=children collapse_id="categories" %}
{% endif %}

</div>

{% block category_content %}

<div id='button-toolbar'>
<div class='btn-group'>
<button class='btn btn-default' id='part-export' title='{% trans "Export Part Data" %}'>
Expand Down Expand Up @@ -150,6 +150,8 @@ <h4>
</div>
</div>

{% endblock %}


{% block category_tables %}
{% endblock category_tables %}
Expand All @@ -162,24 +164,10 @@ <h4>
{% block js_ready %}
{{ block.super }}

{% if category %}
enableNavbar({
label: 'category',
toggleId: '#category-menu-toggle',
});
{% endif %}

if (inventreeLoadInt("show-part-cats") == 1) {
$("#collapse-item-categories").collapse('show');
}

$("#collapse-item-categories").on('shown.bs.collapse', function() {
inventreeSave('show-part-cats', 1);
});

$("#collapse-item-categories").on('hidden.bs.collapse', function() {
inventreeDel('show-part-cats');
});

$("#cat-create").click(function() {
launchModalForm(
Expand Down
17 changes: 17 additions & 0 deletions InvenTree/part/templates/part/category_navbar.html
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,34 @@
</a>
</li>

<li class='list-group-item {% if tab == "subcategories" %}active{% endif %}' title='{% trans "Subcategories" %}'>
{% if category %}
<a href='{% url "category-subcategory" category.id %}'>
{% else %}
<a href='{% url "category-index-subcategory" %}'>
{% endif %}
<span class='fas fa-sitemap'></span>
{% trans "Subcategories" %}
</a>
</li>

<li class='list-group-item {% if tab == "parts" %}active{% endif %}' title='{% trans "Parts" %}'>
{% if category %}
<a href='{% url "category-detail" category.id %}'>
{% else %}
<a href='{% url "part-index" %}'>
{% endif %}
<span class='fas fa-shapes'></span>
{% trans "Parts" %}
</a>
</li>

{% if category %}
<li class='list-group-item {% if tab == "parameters" %}active{% endif %}' title='{% trans "Parameters" %}'>
<a href='{% url "category-parametric" category.id %}'>
<span class='fas fa-tasks'></span>
{% trans "Parameters" %}
</a>
</li>
{% endif %}
</ul>
22 changes: 0 additions & 22 deletions InvenTree/part/templates/part/subcategories.html

This file was deleted.

51 changes: 51 additions & 0 deletions InvenTree/part/templates/part/subcategory.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
{% extends "part/category.html" %}

{% load i18n %}
{% load inventree_extras %}
{% load static %}

{% block menubar %}
{% include 'part/category_navbar.html' with tab='subcategories' %}
{% endblock %}

{% block category_content %}

<div class='panel panel-default panel-inventree'>

<div class='panel-heading'>
<h4>{% trans "Subcategories" %}</h4>
</div>

<div id='button-toolbar'>
<div class='button-toolbar container-fluid' style='float: right;'>

<div class='filter-list' id='filter-list-category'>
<!-- An empty div in which the filter list will be constructed -->
</div>
</div>
</div>

<table class='table table-striped table-condensed' id='subcategory-table' data-toolbar='#button-toolbar'></table>

</div>
{% endblock %}

{% block js_ready %}
{{ block.super }}

enableNavbar({
label: 'category',
toggleId: '#category-menu-toggle',
});

loadPartCategoryTable($('#subcategory-table'), {
params: {
{% if category %}
parent: {{ category.pk }}
{% else %}
parent: 'null'
{% endif %}
}
});

{% endblock %}
44 changes: 43 additions & 1 deletion InvenTree/part/test_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,54 @@ def setUp(self):
super().setUp()

def test_get_categories(self):
""" Test that we can retrieve list of part categories """
"""
Test that we can retrieve list of part categories,
with various filtering options.
"""

url = reverse('api-part-category-list')

# Request *all* part categories
response = self.client.get(url, format='json')

self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(len(response.data), 8)

# Request top-level part categories only
response = self.client.get(
url,
{
'parent': 'null',
},
format='json'
)

self.assertEqual(len(response.data), 2)

# Children of PartCategory<1>, cascade
response = self.client.get(
url,
{
'parent': 1,
'cascade': 'true',
},
format='json',
)

self.assertEqual(len(response.data), 5)

# Children of PartCategory<1>, do not cascade
response = self.client.get(
url,
{
'parent': 1,
'cascade': 'false',
},
format='json',
)

self.assertEqual(len(response.data), 3)

def test_add_categories(self):
""" Check that we can add categories """
data = {
Expand Down
29 changes: 19 additions & 10 deletions InvenTree/part/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,14 +88,26 @@
url(r'^(?P<pid>\d+)/delete/', views.CategoryParameterTemplateDelete.as_view(), name='category-param-template-delete'),
]

part_category_urls = [
url(r'^edit/?', views.CategoryEdit.as_view(), name='category-edit'),
url(r'^delete/?', views.CategoryDelete.as_view(), name='category-delete'),
category_urls = [

url(r'^parameters/', include(category_parameter_urls)),
# Create a new category
url(r'^new/', views.CategoryCreate.as_view(), name='category-create'),

# Top level subcategory display
url(r'^subcategory/', views.PartIndex.as_view(template_name='part/subcategory.html'), name='category-index-subcategory'),

# Category detail views
url(r'(?P<pk>\d+)/', include([
url(r'^edit/', views.CategoryEdit.as_view(), name='category-edit'),
url(r'^delete/', views.CategoryDelete.as_view(), name='category-delete'),
url(r'^parameters/', include(category_parameter_urls)),

url(r'^parametric/?', views.CategoryParametric.as_view(), name='category-parametric'),
url(r'^.*$', views.CategoryDetail.as_view(), name='category-detail'),
url(r'^subcategory/', views.CategoryDetail.as_view(template_name='part/subcategory.html'), name='category-subcategory'),
url(r'^parametric/', views.CategoryParametric.as_view(), name='category-parametric'),

# Anything else
url(r'^.*$', views.CategoryDetail.as_view(), name='category-detail'),
]))
]

part_bom_urls = [
Expand All @@ -106,9 +118,6 @@
# URL list for part web interface
part_urls = [

# Create a new category
url(r'^category/new/?', views.CategoryCreate.as_view(), name='category-create'),

# Create a new part
url(r'^new/?', views.PartCreate.as_view(), name='part-create'),

Expand All @@ -125,7 +134,7 @@
url(r'^(?P<pk>\d+)/', include(part_detail_urls)),

# Part category
url(r'^category/(?P<pk>\d+)/', include(part_category_urls)),
url(r'^category/', include(category_urls)),

# Part related
url(r'^related-parts/', include(part_related_urls)),
Expand Down

0 comments on commit 9addad9

Please sign in to comment.