2
0
mirror of https://github.com/inventree/InvenTree.git synced 2025-06-17 20:45:44 +00:00

[React] Update part parameters table (#5731)

* Implement simple "PartVariantTable" component

- Not yet nested
- More work needed for table nesting

* Fix issue rendering same image multiple times

- Use useId hook to generate random key

* Update PartParameter list API endpoint

- Allow part_detail extra field
- Add FilterSet class
- Allow filter to include variants

* Update PartParameterTable

- Display part column
- Allow returned parts to include templates of base part
- Hide actions for templated parameters

* Fix some code smells
This commit is contained in:
Oliver
2023-10-18 00:41:05 +11:00
committed by GitHub
parent 997b2ad569
commit 8c10b98fe8
10 changed files with 199 additions and 121 deletions

View File

@ -1475,14 +1475,22 @@ class PartParameterAPIMixin:
queryset = PartParameter.objects.all()
serializer_class = part_serializers.PartParameterSerializer
def get_queryset(self, *args, **kwargs):
"""Override get_queryset method to prefetch related fields"""
queryset = super().get_queryset(*args, **kwargs)
queryset = queryset.prefetch_related('part', 'template')
return queryset
def get_serializer(self, *args, **kwargs):
"""Return the serializer instance for this API endpoint.
If requested, extra detail fields are annotated to the queryset:
- part_detail
- template_detail
"""
try:
kwargs['part_detail'] = str2bool(self.request.GET.get('part_detail', False))
kwargs['template_detail'] = str2bool(self.request.GET.get('template_detail', True))
except AttributeError:
pass
@ -1490,6 +1498,35 @@ class PartParameterAPIMixin:
return self.serializer_class(*args, **kwargs)
class PartParameterFilter(rest_filters.FilterSet):
"""Custom filters for the PartParameterList API endpoint"""
class Meta:
"""Metaclass options for the filterset"""
model = PartParameter
fields = [
'template'
]
part = rest_filters.ModelChoiceFilter(queryset=Part.objects.all(), method='filter_part')
def filter_part(self, queryset, name, part):
"""Filter against the provided part.
If 'include_variants' query parameter is provided, filter against variant parts also
"""
try:
include_variants = str2bool(self.request.GET.get('include_variants', False))
except AttributeError:
include_variants = False
if include_variants:
return queryset.filter(part__in=part.get_descendants(include_self=True))
else:
return queryset.filter(part=part)
class PartParameterList(PartParameterAPIMixin, ListCreateAPI):
"""API endpoint for accessing a list of PartParameter objects.
@ -1497,11 +1534,15 @@ class PartParameterList(PartParameterAPIMixin, ListCreateAPI):
- POST: Create a new PartParameter object
"""
filterset_class = PartParameterFilter
filter_backends = SEARCH_ORDER_FILTER_ALIAS
ordering_fields = [
'name',
'data',
'part',
'template',
]
ordering_field_aliases = {
@ -1516,11 +1557,6 @@ class PartParameterList(PartParameterAPIMixin, ListCreateAPI):
'template__units',
]
filterset_fields = [
'part',
'template',
]
class PartParameterDetail(PartParameterAPIMixin, RetrieveUpdateDestroyAPI):
"""API endpoint for detail view of a single PartParameter object."""

View File

@ -240,37 +240,6 @@ class PartParameterTemplateSerializer(InvenTree.serializers.InvenTreeModelSerial
]
class PartParameterSerializer(InvenTree.serializers.InvenTreeModelSerializer):
"""JSON serializers for the PartParameter model."""
class Meta:
"""Metaclass defining serializer fields"""
model = PartParameter
fields = [
'pk',
'part',
'template',
'template_detail',
'data',
'data_numeric',
]
def __init__(self, *args, **kwargs):
"""Custom initialization method for the serializer.
Allows us to optionally include or exclude particular information
"""
template_detail = kwargs.pop('template_detail', True)
super().__init__(*args, **kwargs)
if not template_detail:
self.fields.pop('template_detail')
template_detail = PartParameterTemplateSerializer(source='template', many=False, read_only=True)
class PartBriefSerializer(InvenTree.serializers.InvenTreeModelSerializer):
"""Serializer for Part (brief detail)"""
@ -321,6 +290,43 @@ class PartBriefSerializer(InvenTree.serializers.InvenTreeModelSerializer):
pricing_max = InvenTree.serializers.InvenTreeMoneySerializer(source='pricing_data.overall_max', allow_null=True, read_only=True)
class PartParameterSerializer(InvenTree.serializers.InvenTreeModelSerializer):
"""JSON serializers for the PartParameter model."""
class Meta:
"""Metaclass defining serializer fields"""
model = PartParameter
fields = [
'pk',
'part',
'part_detail',
'template',
'template_detail',
'data',
'data_numeric',
]
def __init__(self, *args, **kwargs):
"""Custom initialization method for the serializer.
Allows us to optionally include or exclude particular information
"""
template_detail = kwargs.pop('template_detail', True)
part_detail = kwargs.pop('part_detail', False)
super().__init__(*args, **kwargs)
if not part_detail:
self.fields.pop('part_detail')
if not template_detail:
self.fields.pop('template_detail')
part_detail = PartBriefSerializer(source='part', many=False, read_only=True)
template_detail = PartParameterTemplateSerializer(source='template', many=False, read_only=True)
class PartSetCategorySerializer(serializers.Serializer):
"""Serializer for changing PartCategory for multiple Part objects"""
@ -1472,7 +1478,8 @@ class BomImportExtractSerializer(InvenTree.serializers.DataFileExtractSerializer
# At least one part column is required!
raise serializers.ValidationError(_("No part column specified"))
def process_row(self, row):
@staticmethod
def process_row(row):
"""Process a single row from the loaded BOM file"""
# Skip any rows which are at a lower "level"
level = row.get('level', None)