2
0
mirror of https://github.com/inventree/InvenTree.git synced 2025-06-18 13:05:42 +00:00

Set part category (#3134)

* Refactor function to enable / disable submit button on modal forms

* Category selection now just uses the AP

* Remove unused forms / views

* JS linting fixes

* remove outdated unit test
This commit is contained in:
Oliver
2022-06-06 13:00:30 +10:00
committed by GitHub
parent fe8f111a63
commit 2b1d8f5b79
10 changed files with 91 additions and 185 deletions

View File

@ -3,15 +3,12 @@
from django import forms
from django.utils.translation import gettext_lazy as _
from mptt.fields import TreeNodeChoiceField
from common.forms import MatchItemForm
from InvenTree.fields import RoundingDecimalFormField
from InvenTree.forms import HelperForm
from InvenTree.helpers import clean_decimal
from .models import (Part, PartCategory, PartInternalPriceBreak,
PartSellPriceBreak)
from .models import Part, PartInternalPriceBreak, PartSellPriceBreak
class PartImageDownloadForm(HelperForm):
@ -53,12 +50,6 @@ class BomMatchItemForm(MatchItemForm):
return super().get_special_field(col_guess, row, file_manager)
class SetPartCategoryForm(forms.Form):
"""Form for setting the category of multiple Part objects."""
part_category = TreeNodeChoiceField(queryset=PartCategory.objects.all(), required=True, help_text=_('Select part category'))
class PartPriceForm(forms.Form):
"""Simple form for viewing part pricing information."""

View File

@ -165,7 +165,7 @@
<div class='btn-group' role='group'>
<div class='btn-group' role='group'>
<button id='part-options' class='btn btn-primary dropdown-toggle' type='button' data-bs-toggle="dropdown">
{% trans "Options" %}
<span class='fas fa-tools' title='{% trans "Options" %}'></span>
</button>
<ul class='dropdown-menu'>
{% if roles.part.change %}
@ -378,7 +378,6 @@
{% else %}category: "null",
{% endif %}
},
buttons: ['#part-options'],
checkbox: true,
gridView: true,
},

View File

@ -1,43 +0,0 @@
{% extends "modal_form.html" %}
{% load i18n %}
{% block form %}
<form method="post" action='' class='js-modal-form' enctype="multipart/form-data">
{% load crispy_forms_tags %}
<label class='control-label'>Parts</label>
<p class='help-block'>{% trans "Set category for the following parts" %}</p>
<table class='table table-striped'>
<tr>
<th>{% trans "Part" %}</th>
<th>{% trans "Description" %}</th>
<th>{% trans "Category" %}</th>
<th>
</tr>
{% for part in parts %}
<tr id='part_row_{{ part.id }}'>
<input type='hidden' name='part_id_{{ part.id }}' value='1'/>
<td>
{% include "hover_image.html" with image=part.image hover=False %}
{{ part.full_name }}
</td>
<td>
{{ part.description }}
</td>
<td>
{{ part.category.pathstring }}
</td>
<td>
<button class='btn btn-outline-secondary btn-remove' onClick='removeRowFromModalForm()' title='{% trans "Remove part" %}' type='button'>
<span row='part_row_{{ part.id }}' class='fas fa-trash-alt icon-red'></span>
</button>
</td>
</tr>
{% endfor %}
</table>
{% crispy form %}
</form>
{% endblock %}

View File

@ -138,23 +138,3 @@ class PartQRTest(PartViewTestCase):
response = self.client.get(reverse('part-qr', args=(9999,)), HTTP_X_REQUESTED_WITH='XMLHttpRequest')
self.assertEqual(response.status_code, 200)
class CategoryTest(PartViewTestCase):
"""Tests for PartCategory related views."""
def test_set_category(self):
"""Test that the "SetCategory" view works."""
url = reverse('part-set-category')
response = self.client.get(url, {'parts[]': 1}, HTTP_X_REQUESTED_WITH='XMLHttpRequest')
self.assertEqual(response.status_code, 200)
data = {
'part_id_10': True,
'part_id_1': True,
'part_category': 5
}
response = self.client.post(url, data, HTTP_X_REQUESTED_WITH='XMLHttpRequest')
self.assertEqual(response.status_code, 200)

View File

@ -56,9 +56,6 @@ part_urls = [
# Part category
re_path(r'^category/', include(category_urls)),
# Change category for multiple parts
re_path(r'^set-category/?', views.PartSetCategory.as_view(), name='part-set-category'),
# Individual part using IPN as slug
re_path(r'^(?P<slug>[-\w]+)/', views.PartDetailFromIPN.as_view(), name='part-detail-from-ipn'),

View File

@ -8,7 +8,6 @@ from django.conf import settings
from django.contrib import messages
from django.core.exceptions import ValidationError
from django.core.files.base import ContentFile
from django.db import transaction
from django.shortcuts import HttpResponseRedirect, get_object_or_404
from django.urls import reverse
from django.utils.translation import gettext_lazy as _
@ -67,80 +66,6 @@ class PartIndex(InvenTreeRoleMixin, ListView):
return context
class PartSetCategory(AjaxUpdateView):
"""View for settings the part category for multiple parts at once."""
ajax_template_name = 'part/set_category.html'
ajax_form_title = _('Set Part Category')
form_class = part_forms.SetPartCategoryForm
role_required = 'part.change'
category = None
parts = []
def get(self, request, *args, **kwargs):
"""Respond to a GET request to this view."""
self.request = request
if 'parts[]' in request.GET:
self.parts = Part.objects.filter(id__in=request.GET.getlist('parts[]'))
else:
self.parts = []
return self.renderJsonResponse(request, form=self.get_form(), context=self.get_context_data())
def post(self, request, *args, **kwargs):
"""Respond to a POST request to this view."""
self.parts = []
for item in request.POST:
if item.startswith('part_id_'):
pk = item.replace('part_id_', '')
try:
part = Part.objects.get(pk=pk)
except (Part.DoesNotExist, ValueError):
continue
self.parts.append(part)
self.category = None
if 'part_category' in request.POST:
pk = request.POST['part_category']
try:
self.category = PartCategory.objects.get(pk=pk)
except (PartCategory.DoesNotExist, ValueError):
self.category = None
valid = self.category is not None
data = {
'form_valid': valid,
'success': _('Set category for {n} parts').format(n=len(self.parts))
}
if valid:
with transaction.atomic():
for part in self.parts:
part.category = self.category
part.save()
return self.renderJsonResponse(request, data=data, form=self.get_form(), context=self.get_context_data())
def get_context_data(self):
"""Return context data for rendering in the form."""
ctx = {}
ctx['parts'] = self.parts
ctx['categories'] = PartCategory.objects.all()
ctx['category'] = self.category
return ctx
class PartImport(FileManagementFormView):
"""Part: Upload file, match to fields and import parts(using multi-Step form)"""
permission_required = 'part.add'