From 83d8226ad6ecba3e9f1aea3a8199ef4c92c07e55 Mon Sep 17 00:00:00 2001 From: Oliver Date: Wed, 4 Aug 2021 11:33:20 +1000 Subject: [PATCH 1/4] Refactor "CreatePartCategory" form to API (cherry picked from commit 06ff961564cdbece29ea52f4e681c079d98bcec8) --- InvenTree/part/templates/part/category.html | 65 +++++---------------- InvenTree/part/test_views.py | 13 ----- InvenTree/part/urls.py | 3 - InvenTree/part/views.py | 44 -------------- InvenTree/templates/js/translated/part.js | 31 ++++++++++ 5 files changed, 46 insertions(+), 110 deletions(-) diff --git a/InvenTree/part/templates/part/category.html b/InvenTree/part/templates/part/category.html index 0aee97a5e3..1c41092574 100644 --- a/InvenTree/part/templates/part/category.html +++ b/InvenTree/part/templates/part/category.html @@ -240,32 +240,20 @@ }); $("#cat-create").click(function() { - launchModalForm( - "{% url 'category-create' %}", - { - follow: true, - data: { - {% if category %} - category: {{ category.id }} - {% endif %} - }, - secondary: [ - { - field: 'default_location', - label: '{% trans "New Location" %}', - title: '{% trans "Create new location" %}', - url: "{% url 'stock-location-create' %}", - }, - { - field: 'parent', - label: '{% trans "New Category" %}', - title: '{% trans "Create new category" %}', - url: "{% url 'category-create' %}", - }, - ] - } - ); - }) + + var fields = categoryFields(); + + {% if category %} + fields.parent.value = {{ category.pk }}; + {% endif %} + + constructForm('{% url "api-part-category-list" %}', { + fields: fields, + method: 'POST', + title: '{% trans "Create Part Category" %}', + follow: true, + }); + }); $("#part-export").click(function() { @@ -286,12 +274,6 @@ {% endif %} }, secondary: [ - { - field: 'category', - label: '{% trans "New Category" %}', - title: '{% trans "Create new Part Category" %}', - url: "{% url 'category-create' %}", - }, { field: 'default_location', label: '{% trans "New Location" %}', @@ -307,24 +289,7 @@ {% if category %} $("#cat-edit").click(function () { - constructForm( - '{% url "api-part-category-detail" category.pk %}', - { - fields: { - name: {}, - description: {}, - parent: { - help_text: '{% trans "Select parent category" %}', - }, - default_location: {}, - default_keywords: { - icon: 'fa-key', - } - }, - title: '{% trans "Edit Part Category" %}', - reload: true - } - ); + editCategory({{ category.pk }}); }); {% if category.parent %} diff --git a/InvenTree/part/test_views.py b/InvenTree/part/test_views.py index 9779aac544..139ec20479 100644 --- a/InvenTree/part/test_views.py +++ b/InvenTree/part/test_views.py @@ -243,19 +243,6 @@ class PartQRTest(PartViewTestCase): class CategoryTest(PartViewTestCase): """ Tests for PartCategory related views """ - def test_create(self): - """ Test view for creating a new category """ - response = self.client.get(reverse('category-create'), {'category': 1}, HTTP_X_REQUESTED_WITH='XMLHttpRequest') - - self.assertEqual(response.status_code, 200) - - def test_create_invalid_parent(self): - """ test creation of a new category with an invalid parent """ - response = self.client.get(reverse('category-create'), {'category': 9999}, HTTP_X_REQUESTED_WITH='XMLHttpRequest') - - # Form should still return OK - self.assertEqual(response.status_code, 200) - def test_set_category(self): """ Test that the "SetCategory" view works """ diff --git a/InvenTree/part/urls.py b/InvenTree/part/urls.py index 2215e14785..62061f8279 100644 --- a/InvenTree/part/urls.py +++ b/InvenTree/part/urls.py @@ -65,9 +65,6 @@ category_parameter_urls = [ category_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'), diff --git a/InvenTree/part/views.py b/InvenTree/part/views.py index fb69241a10..dd79a5360b 100644 --- a/InvenTree/part/views.py +++ b/InvenTree/part/views.py @@ -12,7 +12,6 @@ from django.db.utils import IntegrityError from django.shortcuts import get_object_or_404 from django.shortcuts import HttpResponseRedirect from django.utils.translation import gettext_lazy as _ -from django.urls import reverse, reverse_lazy from django.views.generic import DetailView, ListView from django.forms.models import model_to_dict from django.forms import HiddenInput, CheckboxInput @@ -1905,49 +1904,6 @@ class CategoryDelete(AjaxDeleteView): } -class CategoryCreate(AjaxCreateView): - """ Create view to make a new PartCategory """ - model = PartCategory - ajax_form_action = reverse_lazy('category-create') - ajax_form_title = _('Create new part category') - ajax_template_name = 'modal_form.html' - form_class = part_forms.EditCategoryForm - - def get_context_data(self, **kwargs): - """ Add extra context data to template. - - - If parent category provided, pass the category details to the template - """ - context = super(CategoryCreate, self).get_context_data(**kwargs).copy() - - parent_id = self.request.GET.get('category', None) - - if parent_id: - try: - context['category'] = PartCategory.objects.get(pk=parent_id) - except PartCategory.DoesNotExist: - pass - - return context - - def get_initial(self): - """ Get initial data for new PartCategory - - - If parent provided, pre-fill the parent category - """ - initials = super(CategoryCreate, self).get_initial().copy() - - parent_id = self.request.GET.get('category', None) - - if parent_id: - try: - initials['parent'] = PartCategory.objects.get(pk=parent_id) - except PartCategory.DoesNotExist: - pass - - return initials - - class CategoryParameterTemplateCreate(AjaxCreateView): """ View for creating a new PartCategoryParameterTemplate """ diff --git a/InvenTree/templates/js/translated/part.js b/InvenTree/templates/js/translated/part.js index 169c722d79..aaee9e47a0 100644 --- a/InvenTree/templates/js/translated/part.js +++ b/InvenTree/templates/js/translated/part.js @@ -14,6 +14,37 @@ function yesNoLabel(value) { } +function categoryFields() { + return { + parent: { + help_text: '{% trans "Parent part category" %}', + }, + name: {}, + description: {}, + default_location: {}, + default_keywords: { + icon: 'fa-key', + } + }; +} + + +// Edit a PartCategory via the API +function editCategory(pk, options={}) { + + var url = `/api/part/category/${pk}/`; + + var fields = categoryFields(); + + constructForm(url, { + fields: fields, + title: '{% trans "Edit Part Category" %}', + reload: true, + }); + +} + + function editPart(pk, options={}) { var url = `/api/part/${pk}/`; From 989983bdb5ead5e35b2a7f1e7b1fee11945d342f Mon Sep 17 00:00:00 2001 From: Oliver Date: Wed, 4 Aug 2021 11:37:59 +1000 Subject: [PATCH 2/4] Fixed missing import --- InvenTree/part/views.py | 1 + 1 file changed, 1 insertion(+) diff --git a/InvenTree/part/views.py b/InvenTree/part/views.py index dd79a5360b..dd2868b72b 100644 --- a/InvenTree/part/views.py +++ b/InvenTree/part/views.py @@ -12,6 +12,7 @@ from django.db.utils import IntegrityError from django.shortcuts import get_object_or_404 from django.shortcuts import HttpResponseRedirect from django.utils.translation import gettext_lazy as _ +from django.urls import reverse from django.views.generic import DetailView, ListView from django.forms.models import model_to_dict from django.forms import HiddenInput, CheckboxInput From f95346f21458204530dc445a54d1c714ec168e63 Mon Sep 17 00:00:00 2001 From: Oliver Date: Wed, 4 Aug 2021 12:10:49 +1000 Subject: [PATCH 3/4] Make the part thumbnail selection window searchable --- InvenTree/part/api.py | 16 +++++++++++++--- InvenTree/part/templates/part/part_base.html | 10 +++++++--- InvenTree/templates/js/translated/tables.js | 2 +- 3 files changed, 21 insertions(+), 7 deletions(-) diff --git a/InvenTree/part/api.py b/InvenTree/part/api.py index c0d049ecc7..773631459c 100644 --- a/InvenTree/part/api.py +++ b/InvenTree/part/api.py @@ -338,9 +338,7 @@ class PartThumbs(generics.ListAPIView): - Images may be used for multiple parts! """ - queryset = self.get_queryset() - - # TODO - We should return the thumbnails here, not the full image! + queryset = self.filter_queryset(self.get_queryset()) # Return the most popular parts first data = queryset.values( @@ -349,6 +347,18 @@ class PartThumbs(generics.ListAPIView): return Response(data) + filter_backends = [ + filters.SearchFilter, + ] + + search_fields = [ + 'name', + 'description', + 'IPN', + 'revision', + 'keywords', + 'category__name', + ] class PartThumbsUpdate(generics.RetrieveUpdateAPIView): """ API endpoint for updating Part thumbnails""" diff --git a/InvenTree/part/templates/part/part_base.html b/InvenTree/part/templates/part/part_base.html index 5191399f0a..ec637412a8 100644 --- a/InvenTree/part/templates/part/part_base.html +++ b/InvenTree/part/templates/part/part_base.html @@ -415,13 +415,16 @@ // Callback when the image-selection modal form is displayed // Populate the form with image data (requested via AJAX) - $("#modal-form").find("#image-select-table").bootstrapTable({ - pagination: true, - pageSize: 25, + $("#modal-form").find("#image-select-table").inventreeTable({ url: "{% url 'api-part-thumbs' %}", showHeader: false, + showColumns: false, clickToSelect: true, + sidePagination: 'server', singleSelect: true, + formatNoMatches: function() { + return '{% trans "No matching images found" %}'; + }, columns: [ { checkbox: true, @@ -429,6 +432,7 @@ { field: 'image', title: 'Image', + searchable: true, formatter: function(value, row, index, field) { return "" } diff --git a/InvenTree/templates/js/translated/tables.js b/InvenTree/templates/js/translated/tables.js index afe1fefbc9..88d9a5f99a 100644 --- a/InvenTree/templates/js/translated/tables.js +++ b/InvenTree/templates/js/translated/tables.js @@ -187,7 +187,7 @@ $.fn.inventreeTable = function(options) { if (!options.disablePagination) { options.pagination = true; options.paginationVAlign = options.paginationVAlign || 'both'; - options.pageSize = inventreeLoad(varName, 25); + options.pageSize = options.pageSize || inventreeLoad(varName, 25); options.pageList = [25, 50, 100, 250, 'all']; options.totalField = 'count'; options.dataField = 'results'; From 56c0e289bd7544c1a9b3a87b79b954dca5b30f67 Mon Sep 17 00:00:00 2001 From: Oliver Date: Wed, 4 Aug 2021 12:13:24 +1000 Subject: [PATCH 4/4] Style fix --- InvenTree/part/api.py | 1 + 1 file changed, 1 insertion(+) diff --git a/InvenTree/part/api.py b/InvenTree/part/api.py index 773631459c..a01b05034f 100644 --- a/InvenTree/part/api.py +++ b/InvenTree/part/api.py @@ -360,6 +360,7 @@ class PartThumbs(generics.ListAPIView): 'category__name', ] + class PartThumbsUpdate(generics.RetrieveUpdateAPIView): """ API endpoint for updating Part thumbnails"""