2
0
mirror of https://github.com/inventree/InvenTree.git synced 2025-06-18 04:55:44 +00:00

Table custom buttons (#5075)

* Add generic implementation for barcode actions

- Commonize code against tables
- Cleaner UI
- Better code
- Will make future react refactor easier

* Add permissions.js

- Separate .js file for dynamically checking permissions

* Update stock table to use client-side actions

* API endpoint for bulk category adjustment

* Bug fix for purchase_order.js

- Prevent some really strange API calls

* Refactor actions for part table

- Now done dynamically

* Refactor actions for the attachment tables

* Refactor actions for build output table

* Increment API version

* Cleanup janky button

* Refactor supplier part table

* Refactor manufacturer part table

* Remove linkButtonsToSelection

- no longer needed
- Cleanup, yay!

* Cleanup purchase order line table

* Refactor BOM table buttons

* JS linting

* Further cleanup

* Template cleanup

- remove extra div elements

* js linting

* js fix
This commit is contained in:
Oliver
2023-06-20 07:45:35 +10:00
committed by GitHub
parent 13389845b1
commit 4c9d4add2c
43 changed files with 837 additions and 905 deletions

View File

@ -1271,6 +1271,13 @@ class PartList(PartMixin, APIDownloadMixin, ListCreateAPI):
]
class PartChangeCategory(CreateAPI):
"""API endpoint to change the location of multiple parts in bulk"""
serializer_class = part_serializers.PartSetCategorySerializer
queryset = Part.objects.none()
class PartDetail(PartMixin, RetrieveUpdateDestroyAPI):
"""API endpoint for detail view of a single Part object."""
@ -2020,6 +2027,8 @@ part_api_urls = [
re_path(r'^.*$', PartDetail.as_view(), name='api-part-detail'),
])),
re_path(r'^change_category/', PartChangeCategory.as_view(), name='api-part-change-category'),
re_path(r'^.*$', PartList.as_view(), name='api-part-list'),
]

View File

@ -291,6 +291,56 @@ class PartBriefSerializer(InvenTree.serializers.InvenTreeModelSerializer):
pricing_max = InvenTree.serializers.InvenTreeMoneySerializer(source='pricing_data.overall_max', allow_null=True, read_only=True)
class PartSetCategorySerializer(serializers.Serializer):
"""Serializer for changing PartCategory for multiple Part objects"""
class Meta:
"""Metaclass options"""
fields = [
'parts',
'category',
]
parts = serializers.PrimaryKeyRelatedField(
queryset=Part.objects.all(),
many=True, required=True, allow_null=False,
label=_('Parts'),
)
def validate_parts(self, parts):
"""Validate the selected parts"""
if len(parts) == 0:
raise serializers.ValidationError(_("No parts selected"))
return parts
category = serializers.PrimaryKeyRelatedField(
queryset=PartCategory.objects.filter(structural=False),
many=False, required=True, allow_null=False,
label=_('Category'),
help_text=_('Select category',)
)
@transaction.atomic
def save(self):
"""Save the serializer to change the location of the selected parts"""
data = self.validated_data
parts = data['parts']
category = data['category']
parts_to_save = []
for p in parts:
if p.category == category:
continue
p.category = category
parts_to_save.append(p)
Part.objects.bulk_update(parts_to_save, ['category'])
class DuplicatePartSerializer(serializers.Serializer):
"""Serializer for specifying options when duplicating a Part.

View File

@ -23,20 +23,7 @@
{% endif %}
<div id='bom-button-toolbar'>
<div class="btn-group" role="group" aria-label="...">
{% if roles.part.change %}
<!-- Action menu -->
<div class='btn-group'>
<button id='bom-actions' title='{% trans "BOM actions" %}' class='btn btn-outline-secondary dropdown-toggle' type='button' data-bs-toggle='dropdown'>
<span class='fas fa-tools'></span> <span class='caret'></span>
</button>
<ul class='dropdown-menu' role='menu'>
<li><a class='dropdown-item' href='#' id='bom-item-delete'><span class='fas fa-trash-alt icon-red'></span> {% trans "Delete Items" %}</a></li>
</ul>
</div>
{% endif %}
{% include "filter_list.html" with id="bom" %}
</div>
{% include "filter_list.html" with id="bom" %}
</div>
<table class='table table-bom table-condensed' data-toolbar="#bom-button-toolbar" id='bom-table'>

View File

@ -169,24 +169,7 @@
</div>
</div>
<div id='part-button-toolbar'>
<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">
<span class='fas fa-tools' title='{% trans "Options" %}'></span>
</button>
<ul class='dropdown-menu'>
{% if roles.part.change %}
<li><a class='dropdown-item' href='#' id='multi-part-category' title='{% trans "Set category" %}'>
<span class='fas fa-sitemap'></span> {% trans "Set Category" %}
</a></li>
{% endif %}
<li><a class='dropdown-item' href='#' id='multi-part-order' title='{% trans "Order parts" %}'>
<span class='fas fa-shopping-cart'></span> {% trans "Order Parts" %}
</a></li>
</ul>
</div>
{% include "filter_list.html" with id="parts" %}
</div>
{% include "filter_list.html" with id="parts" %}
</div>
<div class='panel-content'>
<table class='table table-striped table-condensed' data-toolbar='#part-button-toolbar' id='part-table'>
@ -209,9 +192,7 @@
</div>
<div class='panel-content'>
<div id='param-button-toolbar'>
<div class='btn-group' role='group'>
{% include "filter_list.html" with id="parameters" %}
</div>
{% include "filter_list.html" with id="parameters" %}
</div>
<table class='table table-striped table-condensed' data-toolbar='#param-button-toolbar' id='parametric-part-table'>
@ -235,9 +216,7 @@
</div>
<div class='panel-content'>
<div id='subcategory-button-toolbar'>
<div class='btn-group' role='group'>
{% include "filter_list.html" with id="category" %}
</div>
{% include "filter_list.html" with id="category" %}
</div>
<table class='table table-striped table-condensed' id='subcategory-table' data-toolbar='#subcategory-button-toolbar'></table>

View File

@ -93,9 +93,7 @@
</div>
<div class='panel-content'>
<div id='test-button-toolbar'>
<div class='btn-group' role='group'>
{% include "filter_list.html" with id="parttests" %}
</div>
{% include "filter_list.html" with id="parttests" %}
</div>
<table class='table table-striped table-condensed' data-toolbar='#test-button-toolbar' id='test-template-table'></table>
@ -116,9 +114,7 @@
</div>
<div class='panel-content'>
<div id='po-button-bar'>
<div class='button-toolbar container-fluid' style='float: right;'>
{% include "filter_list.html" with id="partpurchaseorders" %}
</div>
{% include "filter_list.html" with id="partpurchaseorders" %}
</div>
<table class='table table-striped table-condensed po-table' id='purchase-order-table' data-toolbar='#po-button-bar'>
@ -132,9 +128,7 @@
</div>
<div class='panel-content'>
<div id='so-button-bar'>
<div class='btn-group' role='group'>
{% include "filter_list.html" with id="salesorder" %}
</div>
{% include "filter_list.html" with id="salesorder" %}
</div>
<table class='table table-striped table-condensed po-table' id='sales-order-table' data-toolbar='#so-button-bar'>
@ -145,11 +139,8 @@
<h4>{% trans "Sales Order Allocations" %}</h4>
</div>
<div class='panel-content'>
<div id='sales-order-allocation-button-toolbar'>
<div class='btn-group' role='group'>
{% include "filter_list.html" with id="salesorderallocation" %}
</div>
{% include "filter_list.html" with id="salesorderallocation" %}
</div>
<table class='table table-striped table-condensed' id='sales-order-allocation-table' data-toolbar='#sales-order-allocation-button-toolbar'></table>
</div>
@ -190,11 +181,7 @@
</div>
<div class='panel-content'>
<div id='variant-button-toolbar'>
<div class='button-toolbar container-fluid'>
<div class='btn-group' role='group'>
{% include "filter_list.html" with id="variants" %}
</div>
</div>
{% include "filter_list.html" with id="variants" %}
</div>
<table class='table table-striped table-condensed' id='variants-table' data-toolbar='#variant-button-toolbar'>
@ -218,11 +205,7 @@
</div>
<div class='panel-content'>
<div id='param-button-toolbar'>
<div class='button-toolbar container-fluid'>
<div class='btn-group' role='group'>
{% include "filter_list.html" with id="parameters" %}
</div>
</div>
{% include "filter_list.html" with id="parameters" %}
</div>
<table id='parameter-table' class='table table-condensed table-striped' data-toolbar="#param-button-toolbar"></table>
</div>
@ -259,9 +242,7 @@
</div>
<div class='panel-content'>
<div id='related-button-toolbar'>
<div class='btn-group' role='group'>
{% include "filter_list.html" with id="related" %}
</div>
{% include "filter_list.html" with id="related" %}
</div>
<table id='related-parts-table' class='table table-striped table-condensed' data-toolbar='#related-button-toolbar'></table>
@ -317,9 +298,7 @@
</div>
<div class='panel-content'>
<div id='assembly-button-toolbar'>
<div class='btn-group' role='group'>
{% include "filter_list.html" with id="usedin" %}
</div>
{% include "filter_list.html" with id="usedin" %}
</div>
<table class="table table-striped table-condensed" id='used-table' data-toolbar='#assembly-button-toolbar'>
@ -346,9 +325,7 @@
</div>
<div class='panel-content'>
<div id='build-button-toolbar'>
<div class='btn-group' role='group'>
{% include "filter_list.html" with id="build" %}
</div>
{% include "filter_list.html" with id="build" %}
</div>
<table class='table table-striped table-condensed' data-toolbar='#build-button-toolbar' id='build-table'>
@ -362,9 +339,7 @@
</div>
<div class='panel-content'>
<div id='build-allocation-button-toolbar'>
<div class='btn-group' role='group'>
{% include "filter_list.html" with id="buildorderallocation" %}
</div>
{% include "filter_list.html" with id="buildorderallocation" %}
</div>
<table class='table table-striped table-condensed' id='build-order-allocation-table' data-toolbar='#build-allocation-button-toolbar'></table>
</div>
@ -385,17 +360,7 @@
</div>
<div class='panel-content'>
<div id='supplier-button-toolbar'>
<div class='btn-group'>
<div id='opt-dropdown' class="btn-group">
<button id='supplier-part-options' class="btn btn-primary dropdown-toggle" type="button" data-bs-toggle="dropdown">{% trans "Options" %} <span class="caret"></span></button>
<ul class="dropdown-menu">
<li><a class='dropdown-item' href='#' id='supplier-part-delete' title='{% trans "Delete supplier parts" %}'>
<span class='fas fa-trash-alt icon-red'></span> {% trans "Delete" %}
</a></li>
</ul>
</div>
{% include "filter_list.html" with id="supplier-part" %}
</div>
{% include "filter_list.html" with id="supplier-part" %}
</div>
<table class="table table-striped table-condensed" id='supplier-part-table' data-toolbar='#supplier-button-toolbar'>
@ -416,15 +381,7 @@
<div class='panel-content'>
<div class='panel-content'>
<div id='manufacturer-button-toolbar'>
<div class='btn-group'>
<div id='opt-dropdown' class="btn-group">
<button id='manufacturer-part-options' class="btn btn-primary dropdown-toggle" type="button" data-bs-toggle="dropdown">{% trans "Options" %} <span class="caret"></span></button>
<ul class="dropdown-menu">
<li><a class='dropdown-item' href='#' id='manufacturer-part-delete' title='{% trans "Delete manufacturer parts" %}'><span class='fas fa-trash-alt icon-red'></span> {% trans "Delete" %}</a></li>
</ul>
{% include "filter_list.html" with id="manufacturer-part" %}
</div>
</div>
{% include "filter_list.html" with id="manufacturer-part" %}
</div>
<table class='table table-condensed table-striped' id='manufacturer-part-table' data-toolbar='#manufacturer-button-toolbar'></table>
</div>
@ -526,8 +483,6 @@
}
);
linkButtonsToSelection($("#supplier-part-table"), ['#supplier-part-options']);
loadManufacturerPartTable(
'#manufacturer-part-table',
"{% url 'api-manufacturer-part-list' %}",
@ -540,8 +495,6 @@
}
);
linkButtonsToSelection($("#manufacturer-part-table"), ['#manufacturer-part-options']);
$("#manufacturer-part-delete").click(function() {
var selectionss = getTableData('#manufacturer-part-table');
@ -625,12 +578,6 @@
sub_part_detail: true,
});
linkButtonsToSelection($("#bom-table"),
[
"#bom-item-delete",
]
);
$('#bom-item-delete').click(function() {
// Get a list of the selected BOM items