mirror of
https://github.com/inventree/InvenTree
synced 2024-08-30 18:33:04 +00:00
Replace "edit part category" form
This commit is contained in:
parent
c425f36a35
commit
621f47e46c
@ -10,11 +10,13 @@ from django.db import models
|
||||
from django.contrib.auth.models import User
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from django.core.exceptions import ValidationError
|
||||
|
||||
from django.db.models.signals import pre_delete
|
||||
from django.dispatch import receiver
|
||||
|
||||
from mptt.models import MPTTModel, TreeForeignKey
|
||||
from mptt.exceptions import InvalidMove
|
||||
|
||||
from .validators import validate_tree_name
|
||||
|
||||
@ -91,6 +93,15 @@ class InvenTreeTree(MPTTModel):
|
||||
parent: The item immediately above this one. An item with a null parent is a top-level item
|
||||
"""
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
|
||||
try:
|
||||
super().save(*args, **kwargs)
|
||||
except InvalidMove:
|
||||
raise ValidationError({
|
||||
'parent': _("Invalid choice"),
|
||||
})
|
||||
|
||||
class Meta:
|
||||
abstract = True
|
||||
|
||||
|
@ -110,6 +110,19 @@ class InvenTreeModelSerializer(serializers.ModelSerializer):
|
||||
|
||||
return initials
|
||||
|
||||
def save(self, **kwargs):
|
||||
"""
|
||||
Catch any django ValidationError thrown at the moment save() is called,
|
||||
and re-throw as a DRF ValidationError
|
||||
"""
|
||||
|
||||
try:
|
||||
super().save(**kwargs)
|
||||
except (ValidationError, DjangoValidationError) as exc:
|
||||
raise ValidationError(detail=serializers.as_serializer_error(exc))
|
||||
|
||||
return self.instance
|
||||
|
||||
def run_validation(self, data=empty):
|
||||
"""
|
||||
Perform serializer validation.
|
||||
|
@ -127,7 +127,10 @@ class CategoryList(generics.ListCreateAPIView):
|
||||
|
||||
|
||||
class CategoryDetail(generics.RetrieveUpdateDestroyAPIView):
|
||||
""" API endpoint for detail view of a single PartCategory object """
|
||||
"""
|
||||
API endpoint for detail view of a single PartCategory object
|
||||
"""
|
||||
|
||||
serializer_class = part_serializers.CategorySerializer
|
||||
queryset = PartCategory.objects.all()
|
||||
|
||||
|
@ -39,6 +39,7 @@ class CategorySerializer(InvenTreeModelSerializer):
|
||||
'name',
|
||||
'description',
|
||||
'default_location',
|
||||
'default_keywords',
|
||||
'pathstring',
|
||||
'url',
|
||||
'parent',
|
||||
|
@ -268,13 +268,23 @@
|
||||
|
||||
{% if category %}
|
||||
$("#cat-edit").click(function () {
|
||||
launchModalForm(
|
||||
"{% url 'category-edit' category.id %}",
|
||||
|
||||
constructForm(
|
||||
'{% url "api-part-category-detail" category.pk %}',
|
||||
{
|
||||
fields: {
|
||||
name: {},
|
||||
description: {},
|
||||
parent: {},
|
||||
default_location: {},
|
||||
default_keywords: {
|
||||
icon: 'fa-key',
|
||||
}
|
||||
},
|
||||
title: '{% trans "Edit Part Category" %}',
|
||||
reload: true
|
||||
},
|
||||
}
|
||||
);
|
||||
return false;
|
||||
});
|
||||
|
||||
{% if category.parent %}
|
||||
|
@ -294,11 +294,6 @@ class CategoryTest(PartViewTestCase):
|
||||
# Form should still return OK
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
||||
def test_edit(self):
|
||||
""" Retrieve the part category editing form """
|
||||
response = self.client.get(reverse('category-edit', args=(1,)), HTTP_X_REQUESTED_WITH='XMLHttpRequest')
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
||||
def test_set_category(self):
|
||||
""" Test that the "SetCategory" view works """
|
||||
|
||||
|
@ -104,7 +104,6 @@ category_urls = [
|
||||
|
||||
# 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)),
|
||||
|
||||
|
@ -388,8 +388,13 @@ function constructFormBody(fields, options) {
|
||||
function submitFormData(fields, options) {
|
||||
|
||||
// Form data to be uploaded to the server
|
||||
// Only used if file / image upload is required
|
||||
var form_data = new FormData();
|
||||
|
||||
var data = {};
|
||||
|
||||
var has_files = false;
|
||||
|
||||
// Extract values for each field
|
||||
options.field_names.forEach(function(name) {
|
||||
|
||||
@ -411,20 +416,31 @@ function submitFormData(fields, options) {
|
||||
var file = field_files[0];
|
||||
|
||||
form_data.append(name, file);
|
||||
|
||||
has_files = true;
|
||||
}
|
||||
} else {
|
||||
// Normal field (not a file or image)
|
||||
form_data.append(name, value);
|
||||
|
||||
data[name] = value;
|
||||
}
|
||||
} else {
|
||||
console.log(`WARNING: Could not find field matching '${name}'`);
|
||||
}
|
||||
});
|
||||
|
||||
var upload_func = inventreePut;
|
||||
|
||||
if (has_files) {
|
||||
upload_func = inventreeFormDataUpload;
|
||||
data = form_data;
|
||||
}
|
||||
|
||||
// Submit data
|
||||
inventreeFormDataUpload(
|
||||
upload_func(
|
||||
options.url,
|
||||
form_data,
|
||||
data,
|
||||
{
|
||||
method: options.method,
|
||||
success: function(response, status) {
|
||||
@ -708,6 +724,7 @@ function initializeRelatedField(name, field, options) {
|
||||
ajax: {
|
||||
url: field.api_url,
|
||||
dataType: 'json',
|
||||
placeholder: '',
|
||||
allowClear: !field.required,
|
||||
dropdownParent: $(options.modal),
|
||||
dropdownAutoWidth: false,
|
||||
|
Loading…
Reference in New Issue
Block a user