mirror of
https://github.com/inventree/InvenTree
synced 2024-08-30 18:33:04 +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:
parent
13389845b1
commit
4c9d4add2c
@ -2,11 +2,14 @@
|
||||
|
||||
|
||||
# InvenTree API version
|
||||
INVENTREE_API_VERSION = 125
|
||||
INVENTREE_API_VERSION = 126
|
||||
|
||||
"""
|
||||
Increment this API version number whenever there is a significant change to the API that any clients need to know about
|
||||
|
||||
v126 -> 2023-06-19 : https://github.com/inventree/InvenTree/pull/5075
|
||||
- Adds API endpoint for setting the "category" for multiple parts simultaneously
|
||||
|
||||
v125 -> 2023-06-17 : https://github.com/inventree/InvenTree/pull/5064
|
||||
- Adds API endpoint for setting the "status" field for multiple stock items simultaneously
|
||||
|
||||
|
@ -269,10 +269,6 @@ main {
|
||||
}
|
||||
|
||||
/* Styles for table buttons and filtering */
|
||||
.button-toolbar .btn {
|
||||
margin-left: 1px;
|
||||
margin-right: 1px;
|
||||
}
|
||||
|
||||
.filter-list {
|
||||
display: inline-block;
|
||||
|
@ -95,6 +95,7 @@ notifications_urls = [
|
||||
dynamic_javascript_urls = [
|
||||
re_path(r'^calendar.js', DynamicJsView.as_view(template_name='js/dynamic/calendar.js'), name='calendar.js'),
|
||||
re_path(r'^nav.js', DynamicJsView.as_view(template_name='js/dynamic/nav.js'), name='nav.js'),
|
||||
re_path(r'^permissions.js', DynamicJsView.as_view(template_name='js/dynamic/permissions.js'), name='permissions.js'),
|
||||
re_path(r'^settings.js', DynamicJsView.as_view(template_name='js/dynamic/settings.js'), name='settings.js'),
|
||||
]
|
||||
|
||||
|
@ -165,9 +165,7 @@
|
||||
</div>
|
||||
<div class='panel-content'>
|
||||
<div id='child-button-toolbar'>
|
||||
<div class='button-toolbar container-fluid float-right'>
|
||||
{% include "filter_list.html" with id='sub-build' %}
|
||||
</div>
|
||||
{% include "filter_list.html" with id='sub-build' %}
|
||||
</div>
|
||||
<table class='table table-striped table-condensed' id='sub-build-table' data-toolbar='#child-button-toolbar'></table>
|
||||
</div>
|
||||
@ -199,26 +197,8 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class='panel-content'>
|
||||
{% if build.active %}
|
||||
{% if build.is_fully_allocated %}
|
||||
<div class='alert alert-block alert-success'>
|
||||
{% trans "Untracked stock has been fully allocated for this Build Order" %}
|
||||
</div>
|
||||
{% else %}
|
||||
<div class='alert alert-block alert-danger'>
|
||||
{% trans "Untracked stock has not been fully allocated for this Build Order" %}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
<div id='build-lines-toolbar'>
|
||||
<div class='button-toolbar container-fluid' style='float: right;'>
|
||||
<div class='btn-group'>
|
||||
<button id='allocate-selected-items' class='btn btn-success' title='{% trans "Allocate selected items" %}'>
|
||||
<span class='fas fa-sign-in-alt'></span>
|
||||
</button>
|
||||
{% include "filter_list.html" with id='buildlines' %}
|
||||
</div>
|
||||
</div>
|
||||
{% include "filter_list.html" with id='buildlines' %}
|
||||
</div>
|
||||
<table class='table table-striped table-condensed' id='build-lines-table' data-toolbar='#build-lines-toolbar'></table>
|
||||
</div>
|
||||
@ -240,37 +220,7 @@
|
||||
</div>
|
||||
<div class='panel-content'>
|
||||
<div id='build-output-toolbar'>
|
||||
<div class='button-toolbar container-fluid'>
|
||||
{% if build.active %}
|
||||
<div class='btn-group'>
|
||||
|
||||
<!-- Build output actions -->
|
||||
<div class='btn-group'>
|
||||
<button id='output-options' class='btn btn-primary dropdown-toggle' type='button' data-bs-toggle='dropdown' title='{% trans "Output Actions" %}'>
|
||||
<span class='fas fa-tools'></span> <span class='caret'></span>
|
||||
</button>
|
||||
<ul class='dropdown-menu'>
|
||||
{% if roles.build.add %}
|
||||
<li><a class='dropdown-item' href='#' id='multi-output-complete' title='{% trans "Complete selected build outputs" %}'>
|
||||
<span class='fas fa-check-circle icon-green'></span> {% trans "Complete outputs" %}
|
||||
</a></li>
|
||||
{% endif %}
|
||||
{% if roles.build.change %}
|
||||
<li><a class='dropdown-item' href='#' id='multi-output-scrap' title='{% trans "Scrap selected build outputs" %}'>
|
||||
<span class='fas fa-times-circle icon-red'></span> {% trans "Scrap outputs" %}
|
||||
</a></li>
|
||||
{% endif %}
|
||||
{% if roles.build.delete %}
|
||||
<li><a class='dropdown-item' href='#' id='multi-output-delete' title='{% trans "Delete selected build outputs" %}'>
|
||||
<span class='fas fa-trash-alt icon-red'></span> {% trans "Delete outputs" %}
|
||||
</a></li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
</div>
|
||||
{% include "filter_list.html" with id='incompletebuilditems' %}
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% include "filter_list.html" with id='incompletebuilditems' %}
|
||||
</div>
|
||||
<table class='table table-striped table-condensed' id='build-output-table' data-toolbar='#build-output-toolbar'></table>
|
||||
</div>
|
||||
@ -501,10 +451,6 @@ $('#btn-unallocate').on('click', function() {
|
||||
});
|
||||
});
|
||||
|
||||
$('#allocate-selected-items').click(function() {
|
||||
allocateSelectedLines();
|
||||
});
|
||||
|
||||
$("#btn-allocate").on('click', function() {
|
||||
allocateSelectedLines();
|
||||
});
|
||||
|
@ -24,11 +24,7 @@
|
||||
|
||||
<div class='panel-content'>
|
||||
<div id='button-toolbar'>
|
||||
<div class='button-toolbar container-fluid' style='float: right;'>
|
||||
<div class='btn-group' role='group'>
|
||||
{% include "filter_list.html" with id="build" %}
|
||||
</div>
|
||||
</div>
|
||||
{% include "filter_list.html" with id="build" %}
|
||||
</div>
|
||||
|
||||
<table class='table table-striped table-condensed' id='build-table' data-toolbar='#button-toolbar'>
|
||||
|
@ -26,28 +26,7 @@
|
||||
<div class='panel-content'>
|
||||
{% if roles.purchase_order.change %}
|
||||
<div id='supplier-part-button-toolbar'>
|
||||
<div class='button-toolbar container-fluid'>
|
||||
<div class='btn-group' role='group'>
|
||||
<div class='btn-group'>
|
||||
<button class="btn btn-primary dropdown-toggle" id='supplier-table-options' type="button" data-bs-toggle="dropdown">
|
||||
<span class='fas fa-tools'></span> <span class="caret"></span>
|
||||
</button>
|
||||
<ul class="dropdown-menu">
|
||||
{% if roles.purchase_order.add %}
|
||||
<li><a class='dropdown-item' href='#' id='multi-supplier-part-order' title='{% trans "Order parts" %}'>
|
||||
<span class='fas fa-shopping-cart'></span> {% trans "Order Parts" %}
|
||||
</a></li>
|
||||
{% endif %}
|
||||
{% if roles.purchase_order.delete %}
|
||||
<li><a class='dropdown-item' href='#' id='multi-supplier-part-delete' title='{% trans "Delete parts" %}'>
|
||||
<span class='fas fa-trash-alt icon-red'></span> {% trans "Delete Parts" %}
|
||||
</a></li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
</div>
|
||||
{% include "filter_list.html" with id="supplier-part" %}
|
||||
</div>
|
||||
</div>
|
||||
{% include "filter_list.html" with id="supplier-part" %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
@ -73,29 +52,7 @@
|
||||
<div class='panel-content'>
|
||||
{% if roles.purchase_order.change %}
|
||||
<div id='manufacturer-part-button-toolbar'>
|
||||
<div class='button-toolbar container-fluid'>
|
||||
<div class='btn-group' role='group'>
|
||||
<div class='btn-group' role='group'>
|
||||
<button class="btn btn-primary dropdown-toggle" id='manufacturer-table-options' type="button" data-bs-toggle="dropdown">
|
||||
<span class='fas fa-tools'></span>
|
||||
<span class="caret"></span>
|
||||
</button>
|
||||
<ul class="dropdown-menu">
|
||||
{% if roles.purchase_order.add %}
|
||||
<li><a class='dropdown-item' href='#' id='multi-manufacturer-part-order' title='{% trans "Order parts" %}'>
|
||||
<span class='fas fa-shopping-cart'></span> {% trans "Order Parts" %}
|
||||
</a></li>
|
||||
{% endif %}
|
||||
{% if roles.purchase_order.delete %}
|
||||
<li><a class='dropdown-item' href='#' id='multi-manufacturer-part-delete' title='{% trans "Delete parts" %}'>
|
||||
<span class='fas fa-trash-alt icon-red'></span> {% trans "Delete Parts" %}
|
||||
</a></li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
</div>
|
||||
{% include "filter_list.html" with id="manufacturer-part" %}
|
||||
</div>
|
||||
</div>
|
||||
{% include "filter_list.html" with id="manufacturer-part" %}
|
||||
</div>
|
||||
{% endif %}
|
||||
<table class='table table-striped table-condensed' id='manufacturer-part-table' data-toolbar='#manufacturer-part-button-toolbar'>
|
||||
@ -128,9 +85,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="purchaseorder" %}
|
||||
</div>
|
||||
{% include "filter_list.html" with id="purchaseorder" %}
|
||||
</div>
|
||||
|
||||
<table class='table table-striped table-condensed po-table' id='purchase-order-table' data-toolbar='#po-button-bar'>
|
||||
@ -156,9 +111,7 @@
|
||||
</div>
|
||||
<div class='panel-content'>
|
||||
<div id='so-button-bar'>
|
||||
<div class='button-toolbar container-fluid' style='float: right;'>
|
||||
{% 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'>
|
||||
@ -174,9 +127,7 @@
|
||||
</div>
|
||||
<div class='panel-content'>
|
||||
<div id='assigned-stock-button-toolbar'>
|
||||
<div class='btn-group' role='group'>
|
||||
{% include "filter_list.html" with id="customerstock" %}
|
||||
</div>
|
||||
{% include "filter_list.html" with id="customerstock" %}
|
||||
</div>
|
||||
|
||||
<table class='table table-striped table-condensed' id='assigned-stock-table' data-toolbar='#assigned-stock-button-toolbar'></table>
|
||||
@ -201,11 +152,7 @@
|
||||
</div>
|
||||
<div class='panel-content'>
|
||||
<div id='table-buttons'>
|
||||
<div class='button-toolbar container-fluid' style='float: right;'>
|
||||
<div class='btn-group'>
|
||||
{% include "filter_list.html" with id="returnorder" %}
|
||||
</div>
|
||||
</div>
|
||||
{% include "filter_list.html" with id="returnorder" %}
|
||||
</div>
|
||||
<table class='table table-striped table-condensed' data-toolbar='#table-buttons' id='return-order-table'>
|
||||
</table>
|
||||
@ -246,9 +193,7 @@
|
||||
</div>
|
||||
<div class='panel-content'>
|
||||
<div id='contacts-button-toolbar'>
|
||||
<div class='btn-group' role='group'>
|
||||
{% include "filter_list.html" with id="contacts" %}
|
||||
</div>
|
||||
{% include "filter_list.html" with id="contacts" %}
|
||||
</div>
|
||||
|
||||
<table class='table table-striped table-condensed' id='contacts-table' data-toolbar='#contacts-button-toolbar'></table>
|
||||
@ -271,9 +216,7 @@
|
||||
</div>
|
||||
<div class='panel-content'>
|
||||
<div id='addresses-button-toolbar'>
|
||||
<div class='btn-group' role='group'>
|
||||
{% include "filter_list.html" with id="addresses" %}
|
||||
</div>
|
||||
{% include "filter_list.html" with id="addresses" %}
|
||||
</div>
|
||||
|
||||
<table class='table table-striped table-condensed' id='addresses-table' data-toolbar='#addresses-button-toolbar'></table>
|
||||
@ -498,32 +441,6 @@
|
||||
}
|
||||
);
|
||||
|
||||
$("#multi-manufacturer-part-delete").click(function() {
|
||||
var selections = getTableData('#manufacturer-part-table');
|
||||
|
||||
deleteManufacturerParts(selections, {
|
||||
success: function() {
|
||||
$("#manufacturer-part-table").bootstrapTable('refresh');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
$("#multi-manufacturer-part-order").click(function() {
|
||||
var selections = getTableData('#manufacturer-part-table');
|
||||
|
||||
var parts = [];
|
||||
|
||||
selections.forEach(function(item) {
|
||||
var part = item.part_detail;
|
||||
part.manufacturer_part = item.pk;
|
||||
parts.push(part);
|
||||
});
|
||||
|
||||
orderParts(
|
||||
parts,
|
||||
);
|
||||
});
|
||||
|
||||
{% endif %}
|
||||
|
||||
{% if company.is_supplier %}
|
||||
@ -552,37 +469,6 @@
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
$("#multi-supplier-part-delete").click(function() {
|
||||
|
||||
var selections = getTableData("#supplier-part-table");
|
||||
|
||||
deleteSupplierParts(selections, {
|
||||
success: function() {
|
||||
$('#supplier-part-table').bootstrapTable('refresh');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
$("#multi-supplier-part-order").click(function() {
|
||||
|
||||
var selections = getTableData('#supplier-part-table');
|
||||
|
||||
var parts = [];
|
||||
|
||||
selections.forEach(function(item) {
|
||||
var part = item.part_detail;
|
||||
parts.push(part);
|
||||
});
|
||||
|
||||
orderParts(
|
||||
parts,
|
||||
{
|
||||
supplier: {{ company.pk }},
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
{% endif %}
|
||||
|
||||
enableSidebar('company');
|
||||
|
@ -24,11 +24,11 @@
|
||||
|
||||
<div class='panel-content'>
|
||||
|
||||
<div id='button-toolbar'>
|
||||
<div id='company-button-toolbar'>
|
||||
{% include "filter_list.html" with id='company' %}
|
||||
</div>
|
||||
|
||||
<table class='table table-striped table-condensed' id='company-table' data-toolbar='#button-toolbar'>
|
||||
<table class='table table-striped table-condensed' id='company-table' data-toolbar='#company-button-toolbar'>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
|
@ -127,17 +127,7 @@ src="{% static 'img/blank_image.png' %}"
|
||||
</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">
|
||||
<span class='fas fa-tools'></span> <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-table' data-toolbar='#supplier-button-toolbar'>
|
||||
@ -174,17 +164,7 @@ src="{% static 'img/blank_image.png' %}"
|
||||
</div>
|
||||
<div class='panel-content'>
|
||||
<div id='parameter-toolbar'>
|
||||
<div class='btn-group'>
|
||||
<div id='opt-dropdown' class="btn-group">
|
||||
<button id='parameter-options' class="btn btn-primary dropdown-toggle" type="button" data-bs-toggle="dropdown">
|
||||
<span class='fas fa-tools'></span> <span class="caret"></span>
|
||||
</button>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a class='dropdown-item' href='#' id='multi-parameter-delete' title='{% trans "Delete parameters" %}'><span class='fas fa-trash-alt icon-red'></span> {% trans "Delete" %}</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
{% include "filter_list.html" with id="manufacturer-part-parameters" %}
|
||||
</div>
|
||||
{% include "filter_list.html" with id="manufacturer-part-parameters" %}
|
||||
</div>
|
||||
|
||||
<table class='table table-striped table-condensed' id='parameter-table' data-toolbar='#parameter-toolbar'></table>
|
||||
@ -240,26 +220,6 @@ $('#supplier-create').click(function () {
|
||||
});
|
||||
});
|
||||
|
||||
$("#supplier-part-delete").click(function() {
|
||||
|
||||
var selections = getTableData('#supplier-table');
|
||||
|
||||
deleteSupplierParts(selections, {
|
||||
success: reloadSupplierPartTable,
|
||||
});
|
||||
});
|
||||
|
||||
$("#multi-parameter-delete").click(function() {
|
||||
|
||||
var selections = getTableData('#parameter-table');
|
||||
|
||||
deleteManufacturerPartParameters(selections, {
|
||||
success: function() {
|
||||
$('#parameter-table').bootstrapTable('refresh');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
loadSupplierPartTable(
|
||||
"#supplier-table",
|
||||
"{% url 'api-supplier-part-list' %}",
|
||||
|
@ -234,9 +234,7 @@ src="{% static 'img/blank_image.png' %}"
|
||||
</div>
|
||||
<div class='panel-content'>
|
||||
<div id='button-bar'>
|
||||
<div class='btn-group' role='group'>
|
||||
{% include "filter_list.html" with id='purchaseorder' %}
|
||||
</div>
|
||||
{% include "filter_list.html" with id='purchaseorder' %}
|
||||
</div>
|
||||
<table class='table table-striped table-condensed po-table' id='purchase-order-table' data-toolbar='#button-bar'>
|
||||
</table>
|
||||
@ -258,10 +256,8 @@ src="{% static 'img/blank_image.png' %}"
|
||||
</div>
|
||||
</div>
|
||||
<div class='panel-content'>
|
||||
<div id='price-break-toolbar' class='btn-group'>
|
||||
<div class='btn-group' role='group'>
|
||||
{% include "filter_list.html" with id='supplierpricebreak' %}
|
||||
</div>
|
||||
<div id='price-break-toolbar'>
|
||||
{% include "filter_list.html" with id='supplierpricebreak' %}
|
||||
</div>
|
||||
|
||||
<table class='table table-striped table-condensed' id='price-break-table' data-toolbar='#price-break-toolbar'>
|
||||
|
@ -37,23 +37,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class='panel-content'>
|
||||
<div id='order-toolbar-buttons' class='btn-group' style='float: right;'>
|
||||
{% if roles.purchase_order.change %}
|
||||
{% if order.is_open or allow_extra_editing %}
|
||||
<div class='btn-group' role='group'>
|
||||
<!-- Multiple-select actions -->
|
||||
<button id='multi-select-options' class='btn btn-primary dropdown-toggle' data-bs-toggle='dropdown'>
|
||||
<span class='fas fa-tools'></span> <span class='caret'></span>
|
||||
</button>
|
||||
<ul class='dropdown-menu'>
|
||||
<li><a class='dropdown-item' href='#' id='po-lines-bulk-delete' title='{% trans "Delete Line Items" %}'>
|
||||
<span class='fas fa-trash-alt icon-red'></span> {% trans "Delete Line Items" %}
|
||||
</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
<div id='order-toolbar-buttons'>
|
||||
{% include "filter_list.html" with id="purchase-order-lines" %}
|
||||
</div>
|
||||
|
||||
@ -77,10 +61,8 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class='panel-content'>
|
||||
<div id='order-extra-toolbar-buttons' class='btn-group' style='float: right;'>
|
||||
<div class='btn-group'>
|
||||
{% include "filter_list.html" with id="purchase-order-extra-lines" %}
|
||||
</div>
|
||||
<div id='order-extra-toolbar-buttons'>
|
||||
{% include "filter_list.html" with id="purchase-order-extra-lines" %}
|
||||
</div>
|
||||
<table class='table table-striped table-condensed' id='po-extra-lines-table' data-toolbar='#order-extra-toolbar-buttons'>
|
||||
</table>
|
||||
|
@ -24,11 +24,7 @@
|
||||
|
||||
<div class='panel-content'>
|
||||
<div id='table-buttons'>
|
||||
<div class='button-toolbar container-fluid' style='float: right;'>
|
||||
<div class='btn-group' role='group'>
|
||||
{% include "filter_list.html" with id="purchaseorder" %}
|
||||
</div>
|
||||
</div>
|
||||
{% include "filter_list.html" with id="purchaseorder" %}
|
||||
</div>
|
||||
|
||||
<table class='table table-striped table-condensed po-table' data-toolbar='#table-buttons' id='purchase-order-table'>
|
||||
|
@ -34,10 +34,8 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class='panel-content'>
|
||||
<div id='order-toolbar-buttons' class='btn-group' style='float: right;'>
|
||||
<div class='btn-group'>
|
||||
{% include "filter_list.html" with id="returnorderlines" %}
|
||||
</div>
|
||||
<div id='order-toolbar-buttons'>
|
||||
{% include "filter_list.html" with id="returnorderlines" %}
|
||||
</div>
|
||||
<table class='table table-striped table-condensed' id='return-order-lines-table' data-toolbar='#order-toolbar-buttons'>
|
||||
</table>
|
||||
@ -58,10 +56,8 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class='panel-content'>
|
||||
<div id='order-extra-toolbar-buttons' class='btn-group' style='float: right;'>
|
||||
<div class='btn-group'>
|
||||
{% include "filter_list.html" with id="return-order-extra-lines" %}
|
||||
</div>
|
||||
<div id='order-extra-toolbar-buttons'>
|
||||
{% include "filter_list.html" with id="return-order-extra-lines" %}
|
||||
</div>
|
||||
<table class='table table-striped table-condensed' id='return-order-extra-lines-table' data-toolbar='#order-extra-toolbar-buttons'>
|
||||
</table>
|
||||
|
@ -26,15 +26,11 @@
|
||||
{% block page_info %}
|
||||
|
||||
<div class='panel-content'>
|
||||
<div id='table-buttons'>
|
||||
<div class='button-toolbar container-fluid' style='float: right;'>
|
||||
<div class='btn-group'>
|
||||
{% include "filter_list.html" with id="returnorder" %}
|
||||
</div>
|
||||
</div>
|
||||
<div id='return-order-table-buttons'>
|
||||
{% include "filter_list.html" with id="returnorder" %}
|
||||
</div>
|
||||
|
||||
<table class='table table-striped table-condensed' data-toolbar='#table-buttons' id='return-order-table'>
|
||||
<table class='table table-striped table-condensed' data-toolbar='#return-order-table-buttons' id='return-order-table'>
|
||||
</table>
|
||||
|
||||
<div id='return-order-calendar'></div>
|
||||
|
@ -29,10 +29,8 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class='panel-content'>
|
||||
<div id='order-toolbar-buttons' class='btn-group' style='float: right;'>
|
||||
<div class='btn-group'>
|
||||
{% include "filter_list.html" with id="sales-order-lines" %}
|
||||
</div>
|
||||
<div id='order-toolbar-buttons'>
|
||||
{% include "filter_list.html" with id="sales-order-lines" %}
|
||||
</div>
|
||||
<table class='table table-striped table-condensed' id='so-lines-table' data-toolbar='#order-toolbar-buttons'>
|
||||
</table>
|
||||
@ -54,10 +52,8 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class='panel-content'>
|
||||
<div id='order-extra-toolbar-buttons' class='btn-group' style='float: right;'>
|
||||
<div class='btn-group'>
|
||||
{% include "filter_list.html" with id="sales-order-extra-lines" %}
|
||||
</div>
|
||||
<div id='order-extra-toolbar-buttons'>
|
||||
{% include "filter_list.html" with id="sales-order-extra-lines" %}
|
||||
</div>
|
||||
<table class='table table-striped table-condensed' id='so-extra-lines-table' data-toolbar='#order-extra-toolbar-buttons'>
|
||||
</table>
|
||||
@ -89,10 +85,8 @@
|
||||
</div>
|
||||
<div class='panel-content'>
|
||||
{% if roles.sales_order.change %}
|
||||
<div id='pending-shipment-toolbar' class='btn-group' style='float: right;'>
|
||||
<div class='btn-group' role='group'>
|
||||
{% include "filter_list.html" with id="pending-shipments" %}
|
||||
</div>
|
||||
<div id='pending-shipment-toolbar'>
|
||||
{% include "filter_list.html" with id="pending-shipments" %}
|
||||
</div>
|
||||
{% endif %}
|
||||
<table class='table table-striped table-condensed' id='pending-shipments-table' data-toolbar='#pending-shipment-toolbar'></table>
|
||||
@ -105,10 +99,8 @@
|
||||
<h4>{% trans "Completed Shipments" %}</h4>
|
||||
</div>
|
||||
<div class='panel-content'>
|
||||
<div id='completed-shipment-toolbar' class='btn-group' style='float: right;'>
|
||||
<div class='btn-group' role='group'>
|
||||
{% include "filter_list.html" with id="completed-shipments" %}
|
||||
</div>
|
||||
<div id='completed-shipment-toolbar'>
|
||||
{% include "filter_list.html" with id="completed-shipments" %}
|
||||
</div>
|
||||
<table class='table table-striped table-condensed' id='completed-shipments-table' data-toolbar='#completed-shipment-toolbar'></table>
|
||||
</div>
|
||||
@ -119,10 +111,8 @@
|
||||
<h4>{% trans "Build Orders" %}</h4>
|
||||
</div>
|
||||
<div class='panel-content'>
|
||||
<div id='builds-toolbar' class='btn-group' style='float: right;'>
|
||||
<div class='btn-group' role='group'>
|
||||
{% include "filter_list.html" with id='build' %}
|
||||
</div>
|
||||
<div id='builds-toolbar'>
|
||||
{% include "filter_list.html" with id='build' %}
|
||||
</div>
|
||||
<table class='table table-striped table-condensed' id='builds-table' data-toolbar='#builds-toolbar'></table>
|
||||
</div>
|
||||
|
@ -27,10 +27,8 @@
|
||||
|
||||
<div class='panel-content'>
|
||||
<div id='table-buttons'>
|
||||
<div class='button-toolbar container-fluid' style='float: right;'>
|
||||
<div class='btn-group'>
|
||||
{% include "filter_list.html" with id="salesorder" %}
|
||||
</div>
|
||||
<div class='button-toolbar'>
|
||||
{% include "filter_list.html" with id="salesorder" %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@ -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'),
|
||||
]
|
||||
|
||||
|
@ -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.
|
||||
|
||||
|
@ -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'>
|
||||
|
@ -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>
|
||||
|
@ -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
|
||||
|
@ -22,9 +22,7 @@
|
||||
</div>
|
||||
<div class='panel-content'>
|
||||
<div id='tracking-table-toolbar'>
|
||||
<div class='btn-group'>
|
||||
{% include "filter_list.html" with id="stocktracking" %}
|
||||
</div>
|
||||
{% include "filter_list.html" with id="stocktracking" %}
|
||||
</div>
|
||||
<table class='table table-condensed table-striped' id='track-table' data-toolbar='#tracking-table-toolbar'>
|
||||
</table>
|
||||
@ -40,9 +38,7 @@
|
||||
</div>
|
||||
<div class='panel-content'>
|
||||
<div id='build-order-allocations-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' data-toolbar='#build-order-allocations-toolbar' id='build-order-allocation-table'></table>
|
||||
</div>
|
||||
@ -55,9 +51,7 @@
|
||||
</div>
|
||||
<div class='panel-content'>
|
||||
<div id='sales-order-allocations-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' data-toolbar='#sales-order-allocations-toolbar' id='sales-order-allocation-table'></table>
|
||||
</div>
|
||||
@ -102,9 +96,7 @@
|
||||
</div>
|
||||
<div class='panel-content'>
|
||||
<div id='test-button-toolbar'>
|
||||
<div class='btn-group' role='group'>
|
||||
{% include "filter_list.html" with id="stocktests" %}
|
||||
</div>
|
||||
{% include "filter_list.html" with id="stocktests" %}
|
||||
</div>
|
||||
|
||||
<table class='table table-striped table-condensed' data-toolbar='#test-button-toolbar' id='test-result-table'></table>
|
||||
@ -157,9 +149,7 @@
|
||||
</div>
|
||||
<div class='panel-content'>
|
||||
<div id='installed-table-toolbar'>
|
||||
<div class='btn-group' role='group'>
|
||||
{% include "filter_list.html" with id='installed-items' %}
|
||||
</div>
|
||||
{% include "filter_list.html" with id='installed-items' %}
|
||||
</div>
|
||||
<table class='table table-striped table-condensed' id='installed-table' data-toolbar='#installed-table-toolbar'></table>
|
||||
</div>
|
||||
|
@ -221,9 +221,7 @@
|
||||
</div>
|
||||
<div class='panel-content'>
|
||||
<div id='sublocation-button-toolbar'>
|
||||
<div class='btn-group' role='group'>
|
||||
{% include "filter_list.html" with id="location" %}
|
||||
</div>
|
||||
{% include "filter_list.html" with id="location" %}
|
||||
</div>
|
||||
|
||||
<table class='table table-striped table-condensed' data-toolbar='#sublocation-button-toolbar' id='sublocation-table'></table>
|
||||
@ -270,13 +268,6 @@
|
||||
});
|
||||
});
|
||||
|
||||
linkButtonsToSelection(
|
||||
$('#sublocation-table'),
|
||||
[
|
||||
'#location-print-options',
|
||||
]
|
||||
);
|
||||
|
||||
{% if labels_enabled %}
|
||||
$('#print-label').click(function() {
|
||||
|
||||
|
@ -18,9 +18,7 @@
|
||||
{% block content %}
|
||||
|
||||
<div id='history-buttons'>
|
||||
<div class='btn-group' role='group'>
|
||||
{% include "filter_list.html" with id="notifications-history" %}
|
||||
</div>
|
||||
{% include "filter_list.html" with id="notifications-history" %}
|
||||
</div>
|
||||
|
||||
<div class='row'>
|
||||
|
@ -18,9 +18,7 @@
|
||||
{% block content %}
|
||||
|
||||
<div id='inbox-buttons'>
|
||||
<div class='btn-group' role='group'>
|
||||
{% include "filter_list.html" with id="notifications-inbox" %}
|
||||
</div>
|
||||
{% include "filter_list.html" with id="notifications-inbox" %}
|
||||
</div>
|
||||
|
||||
<div class='row'>
|
||||
|
@ -35,9 +35,7 @@
|
||||
|
||||
<div class='panel-content'>
|
||||
<div id='part-stocktake-report-toolbar'>
|
||||
<div class='btn-group' role='group'>
|
||||
{% include "filter_list.html" with id="stocktakereport" %}
|
||||
</div>
|
||||
{% include "filter_list.html" with id="stocktakereport" %}
|
||||
</div>
|
||||
<table class='table table-striped table-condensed' id='stocktake-report-table' data-toolbar='#part-stocktake-report-toolbar'></table>
|
||||
</div>
|
||||
|
@ -51,11 +51,7 @@
|
||||
{% endif %}
|
||||
|
||||
<div id='plugin-button-toolbar'>
|
||||
<div class='button-toolbar container-fluid'>
|
||||
<div class='btn-group' role='group'>
|
||||
{% include "filter_list.html" with id="plugins" %}
|
||||
</div>
|
||||
</div>
|
||||
{% include "filter_list.html" with id="plugins" %}
|
||||
</div>
|
||||
<div class='table-responsive'>
|
||||
<table class='table table-striped table-condensed' id='plugin-table' data-toolbar='#plugin-button-toolbar'></table>
|
||||
|
@ -1,21 +1,7 @@
|
||||
{% load i18n %}
|
||||
|
||||
<div id='attachment-buttons'>
|
||||
<div class='btn-group' role='group'>
|
||||
<div class='btn-group' id='multi-attachment-actions'>
|
||||
<button class='btn btn-primary dropdown-toggle' type='button' data-bs-toggle='dropdown' title='{% trans "Actions" %}'>
|
||||
<span class='fas fa-tools'></span> <span class='caret'></span>
|
||||
</button>
|
||||
<ul class='dropdown-menu'>
|
||||
<li>
|
||||
<a class='dropdown-item' href='#' id='multi-attachment-delete' title='{% trans "Delete selected attachments" %}'>
|
||||
<span class='fas fa-trash-alt icon-red'></span> {% trans "Delete Attachments" %}
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
{% include "filter_list.html" with id="attachments" %}
|
||||
</div>
|
||||
{% include "filter_list.html" with id="attachments" %}
|
||||
</div>
|
||||
|
||||
<div class='dropzone' id='attachment-dropzone'>
|
||||
|
@ -147,6 +147,7 @@
|
||||
<!-- dynamic javascript templates -->
|
||||
<script defer type='text/javascript' src="{% url 'calendar.js' %}"></script>
|
||||
<script defer type='text/javascript' src="{% url 'nav.js' %}"></script>
|
||||
<script defer type='text/javascript' src="{% url 'permissions.js' %}"></script>
|
||||
<script defer type='text/javascript' src="{% url 'settings.js' %}"></script>
|
||||
|
||||
<!-- translated javascript templates-->
|
||||
|
@ -1 +1,3 @@
|
||||
<div class='filter-list d-flex flex-row form-row' id='filter-list-{% if prefix %}{{ prefix }}{% endif %}{{ id }}'><!-- Empty div for table filters --></div>
|
||||
<div class='filter-list d-flex flex-row form-row' id='filter-list-{% if prefix %}{{ prefix }}{% endif %}{{ id }}'>
|
||||
<!-- Empty div for table filters -->
|
||||
</div>
|
||||
|
59
InvenTree/templates/js/dynamic/permissions.js
Normal file
59
InvenTree/templates/js/dynamic/permissions.js
Normal file
@ -0,0 +1,59 @@
|
||||
/*
|
||||
* globals
|
||||
inventreeGet,
|
||||
|
||||
/* exported
|
||||
checkPermission,
|
||||
*/
|
||||
|
||||
// Keep track of the current user permissions
|
||||
var user_roles = null;
|
||||
|
||||
|
||||
/*
|
||||
* Check if the user has the specified role and permission
|
||||
*/
|
||||
function checkPermission(role, permission='view') {
|
||||
|
||||
// Allow permission to be specified in dotted notation, e.g. 'part.add'
|
||||
if (role.indexOf('.') > 0) {
|
||||
let parts = role.split('.');
|
||||
role = parts[0];
|
||||
permission = parts[1];
|
||||
}
|
||||
|
||||
// Request user roles if we do not have them
|
||||
if (user_roles == null) {
|
||||
inventreeGet('{% url "api-user-roles" %}', {}, {
|
||||
async: false,
|
||||
success: function(response) {
|
||||
user_roles = response.roles || {};
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (user_roles == null) {
|
||||
console.error("Failed to fetch user roles");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!(role in user_roles)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
let roles = user_roles[role];
|
||||
|
||||
if (!roles) {
|
||||
return false;
|
||||
}
|
||||
|
||||
let found = false;
|
||||
|
||||
user_roles[role].forEach(function(p) {
|
||||
if (String(p).valueOf() == String(permission).valueOf()) {
|
||||
found = true;
|
||||
}
|
||||
});
|
||||
|
||||
return found;
|
||||
}
|
@ -187,7 +187,27 @@ function attachmentLink(filename) {
|
||||
let html = makeIcon(icon) + ` ${fn}`;
|
||||
|
||||
return renderLink(html, filename, {download: true});
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Construct a set of actions for an attachment table,
|
||||
* with the provided permission set
|
||||
*/
|
||||
function makeAttachmentActions(permissions, options) {
|
||||
|
||||
let actions = [];
|
||||
|
||||
if (permissions.delete) {
|
||||
actions.push({
|
||||
label: 'delete',
|
||||
icon: 'fa-trash-alt icon-red',
|
||||
title: '{% trans "Delete attachments" %}',
|
||||
callback: options.callback,
|
||||
});
|
||||
}
|
||||
|
||||
return actions;
|
||||
}
|
||||
|
||||
|
||||
@ -225,7 +245,20 @@ function loadAttachmentTable(url, options) {
|
||||
}
|
||||
});
|
||||
|
||||
setupFilterList('attachments', $(table), '#filter-list-attachments');
|
||||
setupFilterList('attachments', $(table), '#filter-list-attachments', {
|
||||
custom_actions: [
|
||||
{
|
||||
label: 'attachments',
|
||||
icon: 'fa-tools',
|
||||
title: '{% trans "Attachment actions" %}',
|
||||
actions: makeAttachmentActions(permissions, {
|
||||
callback: function(attachments) {
|
||||
deleteAttachments(attachments, url, options);
|
||||
}
|
||||
}),
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
if (permissions.add) {
|
||||
addAttachmentButtonCallbacks(url, options.fields || {});
|
||||
@ -235,19 +268,6 @@ function loadAttachmentTable(url, options) {
|
||||
$('#new-attachment-link').hide();
|
||||
}
|
||||
|
||||
if (permissions.delete) {
|
||||
// Add callback for the 'multi delete' button
|
||||
$('#multi-attachment-delete').click(function() {
|
||||
var attachments = getTableData(table);
|
||||
|
||||
if (attachments.length > 0) {
|
||||
deleteAttachments(attachments, url, options);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
$('#multi-attachment-actions').hide();
|
||||
}
|
||||
|
||||
$(table).inventreeTable({
|
||||
url: url,
|
||||
name: options.name || 'attachments',
|
||||
@ -286,16 +306,6 @@ function loadAttachmentTable(url, options) {
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
if (permissions.delete) {
|
||||
// Add callback for 'delete' button
|
||||
$(table).find('.button-attachment-delete').click(function() {
|
||||
var pk = $(this).attr('pk');
|
||||
|
||||
var attachment = $(table).bootstrapTable('getRowByUniqueId', pk);
|
||||
deleteAttachments([attachment], url, options);
|
||||
});
|
||||
}
|
||||
},
|
||||
columns: [
|
||||
{
|
||||
|
@ -763,7 +763,7 @@ function scanItemsIntoLocation(item_list, options={}) {
|
||||
// Extra form fields
|
||||
var extra = makeNotesField();
|
||||
|
||||
// Header contentfor
|
||||
// Header content
|
||||
var header = `
|
||||
<div id='header-div'>
|
||||
</div>
|
||||
|
@ -33,6 +33,7 @@
|
||||
modalSetContent,
|
||||
partFields,
|
||||
partGroups,
|
||||
reloadBootstrapTable,
|
||||
renderLink,
|
||||
setupFilterList,
|
||||
shortenString,
|
||||
@ -817,7 +818,24 @@ function loadBomTable(table, options={}) {
|
||||
|
||||
Object.assign(filters, params);
|
||||
|
||||
setupFilterList('bom', $(table));
|
||||
setupFilterList('bom', $(table), '#filter-list-bom', {
|
||||
custom_actions: [{
|
||||
label: 'actions',
|
||||
actions: [{
|
||||
label: 'delete',
|
||||
title: '{% trans "Delete items" %}',
|
||||
icon: 'fa-trash-alt icon-red',
|
||||
permission: 'part.change',
|
||||
callback: function(data) {
|
||||
deleteBomItems(data, {
|
||||
success: function() {
|
||||
reloadBootstrapTable('#bom-table');
|
||||
}
|
||||
});
|
||||
}
|
||||
}]
|
||||
}]
|
||||
});
|
||||
|
||||
function availableQuantity(row) {
|
||||
|
||||
|
@ -23,7 +23,6 @@
|
||||
inventreeLoad,
|
||||
inventreePut,
|
||||
launchModalForm,
|
||||
linkButtonsToSelection,
|
||||
loadTableFilters,
|
||||
locationDetail,
|
||||
makeDeleteButton,
|
||||
@ -34,6 +33,7 @@
|
||||
makePartIcons,
|
||||
makeProgressBar,
|
||||
orderParts,
|
||||
reloadBootstrapTable,
|
||||
renderDate,
|
||||
renderLink,
|
||||
setupFilterList,
|
||||
@ -387,7 +387,7 @@ function createBuildOutput(build_id, options) {
|
||||
fields: fields,
|
||||
preFormContent: html,
|
||||
onSuccess: function(response) {
|
||||
location.reload();
|
||||
reloadBootstrapTable(options.table || '#build-output-table');
|
||||
},
|
||||
});
|
||||
|
||||
@ -995,6 +995,70 @@ function loadBuildOrderAllocationTable(table, options={}) {
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Construct a set of actions for the build output table
|
||||
*/
|
||||
function makeBuildOutputActions(build_info) {
|
||||
|
||||
return [
|
||||
{
|
||||
label: 'complete',
|
||||
title: '{% trans "Complete outputs" %}',
|
||||
icon: 'fa-check-circle icon-green',
|
||||
permission: 'build.add',
|
||||
callback: function(data) {
|
||||
completeBuildOutputs(
|
||||
build_info.pk,
|
||||
data,
|
||||
{
|
||||
success: function() {
|
||||
$('#build-output-table').bootstrapTable('refresh'); // Reload the "in progress" table
|
||||
$('#build-stock-table').bootstrapTable('refresh'); // Reload the "completed" table
|
||||
}
|
||||
}
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
label: 'scrap',
|
||||
title: '{% trans "Scrap outputs" %}',
|
||||
icon: 'fa-times-circle icon-red',
|
||||
permission: 'build.change',
|
||||
callback: function(data) {
|
||||
scrapBuildOutputs(
|
||||
build_info.pk,
|
||||
data,
|
||||
{
|
||||
success: function() {
|
||||
$('#build-output-table').bootstrapTable('refresh'); // Reload the "in progress" table
|
||||
$('#build-stock-table').bootstrapTable('refresh'); // Reload the "completed" table
|
||||
}
|
||||
}
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
label: 'delete',
|
||||
title: '{% trans "Delete outputs" %}',
|
||||
icon: 'fa-trash-alt icon-red',
|
||||
permission: 'build.delete',
|
||||
callback: function(data) {
|
||||
deleteBuildOutputs(
|
||||
build_info.pk,
|
||||
data,
|
||||
{
|
||||
success: function() {
|
||||
$('#build-output-table').bootstrapTable('refresh'); // Reload the "in progress" table
|
||||
$('#build-stock-table').bootstrapTable('refresh'); // Reload the "completed" table
|
||||
}
|
||||
}
|
||||
)
|
||||
},
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Display a "build output" table for a particular build.
|
||||
*
|
||||
@ -1035,6 +1099,12 @@ function loadBuildOutputTable(build_info, options={}) {
|
||||
},
|
||||
singular_name: '{% trans "build output" %}',
|
||||
plural_name: '{% trans "build outputs" %}',
|
||||
custom_actions: [{
|
||||
label: 'buildoutput',
|
||||
icon: 'fa-tools',
|
||||
title: '{% trans "Build output actions" %}',
|
||||
actions: makeBuildOutputActions(build_info),
|
||||
}]
|
||||
});
|
||||
|
||||
// Request list of required tests for the part being assembled
|
||||
@ -1383,25 +1453,6 @@ function loadBuildOutputTable(build_info, options={}) {
|
||||
);
|
||||
});
|
||||
|
||||
// Complete multiple outputs
|
||||
$('#multi-output-complete').click(function() {
|
||||
var outputs = getTableData(table);
|
||||
|
||||
completeBuildOutputs(
|
||||
build_info.pk,
|
||||
outputs,
|
||||
{
|
||||
success: function() {
|
||||
// Reload the "in progress" table
|
||||
$('#build-output-table').bootstrapTable('refresh');
|
||||
|
||||
// Reload the "completed" table
|
||||
$('#build-stock-table').bootstrapTable('refresh');
|
||||
}
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
// Delete multiple build outputs
|
||||
$('#multi-output-delete').click(function() {
|
||||
var outputs = getTableData(table);
|
||||
@ -1421,25 +1472,6 @@ function loadBuildOutputTable(build_info, options={}) {
|
||||
);
|
||||
});
|
||||
|
||||
// Scrap multiple outputs
|
||||
$('#multi-output-scrap').click(function() {
|
||||
var outputs = getTableData(table);
|
||||
|
||||
scrapBuildOutputs(
|
||||
build_info.pk,
|
||||
outputs,
|
||||
{
|
||||
success: function() {
|
||||
// Reload the "in progress" table
|
||||
$('#build-output-table').bootstrapTable('refresh');
|
||||
|
||||
// Reload the "completed" table
|
||||
$('#build-stock-table').bootstrapTable('refresh');
|
||||
}
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
$('#outputs-expand').click(function() {
|
||||
$(table).bootstrapTable('expandAllRows');
|
||||
});
|
||||
@ -2180,13 +2212,6 @@ function loadBuildTable(table, options) {
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
linkButtonsToSelection(
|
||||
table,
|
||||
[
|
||||
'#build-print-options',
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
@ -18,6 +18,7 @@
|
||||
makeDeleteButton,
|
||||
makeEditButton,
|
||||
makeIconBadge,
|
||||
orderParts,
|
||||
renderClipboard,
|
||||
renderDate,
|
||||
renderLink,
|
||||
@ -1213,6 +1214,43 @@ function deleteManufacturerPartParameters(selections, options={}) {
|
||||
}
|
||||
|
||||
|
||||
// Construct a set of actions for the manufacturer part table
|
||||
function makeManufacturerPartActions(options={}) {
|
||||
return [
|
||||
{
|
||||
label: 'order',
|
||||
title: '{% trans "Order parts" %}',
|
||||
icon: 'fa-shopping-cart',
|
||||
permission: 'purchase_order.add',
|
||||
callback: function(data) {
|
||||
let parts = [];
|
||||
|
||||
data.forEach(function(item) {
|
||||
let part = item.part_detail;
|
||||
part.manufacturer_part = item.pk;
|
||||
parts.push(part);
|
||||
});
|
||||
|
||||
orderParts(parts);
|
||||
},
|
||||
},
|
||||
{
|
||||
label: 'delete',
|
||||
title: '{% trans "Delete manufacturer parts" %}',
|
||||
icon: 'fa-trash-alt icon-red',
|
||||
permission: 'purchase_order.delete',
|
||||
callback: function(data) {
|
||||
deleteManufacturerParts(data, {
|
||||
success: function() {
|
||||
$('#manufacturer-part-table').bootstrapTable('refresh');
|
||||
}
|
||||
});
|
||||
},
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Load manufacturer part table
|
||||
*/
|
||||
@ -1226,7 +1264,18 @@ function loadManufacturerPartTable(table, url, options) {
|
||||
|
||||
var filterTarget = options.filterTarget || '#filter-list-manufacturer-part';
|
||||
|
||||
setupFilterList('manufacturer-part', $(table), filterTarget);
|
||||
setupFilterList('manufacturer-part', $(table), filterTarget, {
|
||||
custom_actions: [
|
||||
{
|
||||
label: 'manufacturer-part',
|
||||
title: '{% trans "Manufacturer part actions" %}',
|
||||
icon: 'fa-tools',
|
||||
actions: makeManufacturerPartActions({
|
||||
manufacturer_id: options.params.manufacturer,
|
||||
})
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
$(table).inventreeTable({
|
||||
url: url,
|
||||
@ -1453,6 +1502,43 @@ function loadManufacturerPartParameterTable(table, url, options) {
|
||||
}
|
||||
|
||||
|
||||
// Construct a set of actions for the supplier part table
|
||||
function makeSupplierPartActions(options={}) {
|
||||
return [
|
||||
{
|
||||
label: 'order',
|
||||
title: '{% trans "Order parts" %}',
|
||||
icon: 'fa-shopping-cart',
|
||||
permission: 'purchase_order.add',
|
||||
callback: function(data) {
|
||||
let parts = []
|
||||
|
||||
data.forEach(function(entry) {
|
||||
parts.push(entry.part_detail);
|
||||
});
|
||||
|
||||
orderParts(parts, {
|
||||
supplier: options.supplier_id,
|
||||
});
|
||||
},
|
||||
},
|
||||
{
|
||||
label: 'delete',
|
||||
title: '{% trans "Delete supplier parts" %}',
|
||||
icon: 'fa-trash-alt icon-red',
|
||||
permission: 'purchase_order.delete',
|
||||
callback: function(data) {
|
||||
deleteSupplierParts(data, {
|
||||
success: function() {
|
||||
$('#supplier-part-table').bootstrapTable('refresh');
|
||||
}
|
||||
});
|
||||
},
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Load supplier part table
|
||||
*/
|
||||
@ -1464,7 +1550,18 @@ function loadSupplierPartTable(table, url, options) {
|
||||
// Load filters
|
||||
var filters = loadTableFilters('supplierpart', params);
|
||||
|
||||
setupFilterList('supplierpart', $(table));
|
||||
setupFilterList('supplierpart', $(table), '#filter-list-supplier-part', {
|
||||
custom_actions: [
|
||||
{
|
||||
label: 'supplier-part',
|
||||
title: '{% trans "Supplier part actions" %}',
|
||||
icon: 'fa-tools',
|
||||
actions: makeSupplierPartActions({
|
||||
supplier_id: options.params.supplier,
|
||||
}),
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
$(table).inventreeTable({
|
||||
url: url,
|
||||
|
@ -1,6 +1,7 @@
|
||||
{% load i18n %}
|
||||
|
||||
/* globals
|
||||
checkPermission,
|
||||
downloadTableData,
|
||||
getAvailableTableFilters,
|
||||
getTableData,
|
||||
@ -266,6 +267,102 @@ function generateFilterInput(tableKey, filterKey) {
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Construct a single action button based on the provided definition
|
||||
*/
|
||||
function makeFilterActionButton(button, options={}) {
|
||||
let prefix = options.prefix || 'action';
|
||||
|
||||
// Check for required permission (if specified)
|
||||
if (button.permission) {
|
||||
if (!checkPermission(button.permission)) {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
return `
|
||||
<li><a class='dropdown-item' href='#' id='action-${prefix}-${button.label}'>
|
||||
<span class='fas ${button.icon}'></span> ${button.title}
|
||||
</a></li>`;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Construct a set of custom actions for a given table
|
||||
*/
|
||||
function makeCustomActionGroup(action_group, table) {
|
||||
|
||||
let buttons = [];
|
||||
let label = action_group.label || 'actions';
|
||||
let title = action_group.title || '{% trans "Actions" %}';
|
||||
let icon = action_group.icon || 'fa-tools';
|
||||
|
||||
// Construct the HTML for each button
|
||||
action_group.actions.forEach(function(action) {
|
||||
buttons.push(makeFilterActionButton(action, {prefix: label}));
|
||||
});
|
||||
|
||||
if (buttons.length == 0) {
|
||||
// Don't display anything if there are no buttons to show
|
||||
return '';
|
||||
}
|
||||
|
||||
let html = `
|
||||
<div class='btn-group' role='group'>
|
||||
<button id='${label}-actions' title='${title}' class='btn btn-outline-secondary dropdown-toggle' type='button' data-bs-toggle='dropdown'>
|
||||
<span class='fas ${icon}'></span>
|
||||
</button>
|
||||
<ul class='dropdown-menu' role='menu'>
|
||||
`;
|
||||
|
||||
buttons.forEach(function(button) {
|
||||
html += button;
|
||||
});
|
||||
|
||||
html += `</ul></div>`;
|
||||
return html;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Construct a set of custom barcode actions for a given table
|
||||
*
|
||||
* To define barcode actions for a data table, use options.barcode_actions
|
||||
*/
|
||||
function makeBarcodeActions(barcode_actions, table) {
|
||||
|
||||
let html = `
|
||||
<div class='btn-group' role='group'>
|
||||
<button id='barcode-actions' title='{% trans "Barcode actions" %}' class='btn btn-outline-secondary dropdown-toggle' type='button' data-bs-toggle='dropdown'>
|
||||
<span class='fas fa-qrcode'></span>
|
||||
</button>
|
||||
<ul class='dropdown-menu' role='menu'>
|
||||
`;
|
||||
|
||||
barcode_actions.forEach(function(action) {
|
||||
html += makeFilterActionButton(action, {prefix: 'barcode'});
|
||||
});
|
||||
|
||||
html += `</ul></div>`;
|
||||
|
||||
return html;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Add callbacks for custom actions
|
||||
*/
|
||||
function addFilterActionCallbacks(element, label, table, actions) {
|
||||
actions.forEach(function(action) {
|
||||
let id = `action-${label}-${action.label}`;
|
||||
element.find(`#${id}`).click(function() {
|
||||
let data = getTableData(table);
|
||||
action.callback(data);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Helper function to make a 'filter' style button
|
||||
*/
|
||||
@ -315,6 +412,19 @@ function setupFilterList(tableKey, table, target, options={}) {
|
||||
|
||||
let report_button = options.report && global_settings.REPORT_ENABLE;
|
||||
let labels_button = options.labels && global_settings.LABEL_ENABLE;
|
||||
let barcode_actions = options.barcode_actions && global_settings.BARCODE_ENABLE;
|
||||
|
||||
// Add in "custom" actions first (to the left of the table buttons)
|
||||
if (options.custom_actions) {
|
||||
options.custom_actions.forEach(function(action_group) {
|
||||
buttons += makeCustomActionGroup(action_group, table);
|
||||
});
|
||||
}
|
||||
|
||||
// Add in button for custom barcode actions
|
||||
if (barcode_actions) {
|
||||
buttons += makeBarcodeActions(options.barcode_actions, table);
|
||||
}
|
||||
|
||||
if (report_button || labels_button) {
|
||||
let print_buttons = `
|
||||
@ -394,6 +504,19 @@ function setupFilterList(tableKey, table, target, options={}) {
|
||||
element.append(filter_tag);
|
||||
}
|
||||
|
||||
// Callback for custom actions
|
||||
if (options.custom_actions) {
|
||||
options.custom_actions.forEach(function(action_group) {
|
||||
let label = action_group.label || 'actions';
|
||||
addFilterActionCallbacks(element, label, table, action_group.actions);
|
||||
});
|
||||
}
|
||||
|
||||
// Callback for barcode actions
|
||||
if (barcode_actions) {
|
||||
addFilterActionCallbacks(element, 'barcode', table, options.barcode_actions);
|
||||
}
|
||||
|
||||
// Callback for printing reports
|
||||
if (options.report && global_settings.REPORT_ENABLE) {
|
||||
element.find(`#print-report-${tableKey}`).click(function() {
|
||||
|
@ -23,7 +23,6 @@
|
||||
inventreeLoad,
|
||||
inventreePut,
|
||||
inventreeSave,
|
||||
linkButtonsToSelection,
|
||||
loadTableFilters,
|
||||
makeDeleteButton,
|
||||
makeEditButton,
|
||||
@ -2159,6 +2158,69 @@ function partGridTile(part) {
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Update the category for a set of parts
|
||||
*/
|
||||
function setPartCategory(data, options={}) {
|
||||
|
||||
let parts = [];
|
||||
|
||||
data.forEach(function(item) {
|
||||
parts.push(item.pk);
|
||||
});
|
||||
|
||||
var html = `
|
||||
<div class='alert alert-block alert-info'>
|
||||
{% trans "Set the part category for the selected parts" %}
|
||||
</div>
|
||||
`;
|
||||
|
||||
constructForm('{% url "api-part-change-category" %}',{
|
||||
title: '{% trans "Set Part Category" %}',
|
||||
method: 'POST',
|
||||
preFormContent: html,
|
||||
fields: {
|
||||
category: {},
|
||||
},
|
||||
processBeforeUpload: function(data) {
|
||||
data.parts = parts;
|
||||
return data;
|
||||
},
|
||||
onSuccess: function() {
|
||||
$(options.table).bootstrapTable('refresh');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Construct a set of custom actions for the part table
|
||||
*/
|
||||
function makePartActions(table) {
|
||||
|
||||
return [
|
||||
{
|
||||
label: 'set-category',
|
||||
title: '{% trans "Set category" %}',
|
||||
icon: 'fa-sitemap',
|
||||
permission: 'part.change',
|
||||
callback: function(data) {
|
||||
setPartCategory(data, {table: table});
|
||||
}
|
||||
},
|
||||
{
|
||||
label: 'order',
|
||||
title: '{% trans "Order parts" %}',
|
||||
icon: 'fa-shopping-cart',
|
||||
permission: 'purchase_order.add',
|
||||
callback: function(data) {
|
||||
orderParts(data);
|
||||
},
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
/* Load part listing data into specified table.
|
||||
*
|
||||
* Args:
|
||||
@ -2190,6 +2252,14 @@ function loadPartTable(table, url, options={}) {
|
||||
},
|
||||
singular_name: '{% trans "part" %}',
|
||||
plural_name: '{% trans "parts" %}',
|
||||
custom_actions: [
|
||||
{
|
||||
label: 'parts',
|
||||
icon: 'fa-tools',
|
||||
title: '{% trans "Part actions" %}',
|
||||
actions: makePartActions(table),
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
var columns = [
|
||||
@ -2438,97 +2508,6 @@ function loadPartTable(table, url, options={}) {
|
||||
return html;
|
||||
}
|
||||
});
|
||||
|
||||
if (options.buttons) {
|
||||
linkButtonsToSelection($(table), options.buttons);
|
||||
}
|
||||
|
||||
/* Button callbacks for part table buttons */
|
||||
|
||||
// Callback function for the "order parts" button
|
||||
$('#multi-part-order').click(function() {
|
||||
var selections = getTableData(table);
|
||||
|
||||
var parts = [];
|
||||
|
||||
selections.forEach(function(part) {
|
||||
parts.push(part);
|
||||
});
|
||||
|
||||
orderParts(parts, {});
|
||||
});
|
||||
|
||||
// Callback function for the "set category" button
|
||||
$('#multi-part-category').click(function() {
|
||||
var selections = getTableData(table);
|
||||
var parts = [];
|
||||
|
||||
selections.forEach(function(item) {
|
||||
parts.push(item.pk);
|
||||
});
|
||||
|
||||
var html = `
|
||||
<div class='alert alert-block alert-info'>
|
||||
{% trans "Set the part category for the selected parts" %}
|
||||
</div>
|
||||
`;
|
||||
|
||||
constructFormBody({}, {
|
||||
title: '{% trans "Set Part Category" %}',
|
||||
preFormContent: html,
|
||||
fields: {
|
||||
category: {
|
||||
label: '{% trans "Category" %}',
|
||||
help_text: '{% trans "Select Part Category" %}',
|
||||
required: true,
|
||||
type: 'related field',
|
||||
model: 'partcategory',
|
||||
api_url: '{% url "api-part-category-list" %}',
|
||||
}
|
||||
},
|
||||
onSubmit: function(fields, opts) {
|
||||
var category = getFormFieldValue('category', fields['category'], opts);
|
||||
|
||||
if (category == null) {
|
||||
handleFormErrors(
|
||||
{
|
||||
'category': ['{% trans "Category is required" %}']
|
||||
},
|
||||
opts.fields,
|
||||
opts
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
// Set the category for each part in sequence
|
||||
function setCategory() {
|
||||
if (parts.length > 0) {
|
||||
var part = parts.shift();
|
||||
|
||||
inventreePut(
|
||||
`{% url "api-part-list" %}${part}/`,
|
||||
{
|
||||
category: category,
|
||||
},
|
||||
{
|
||||
method: 'PATCH',
|
||||
complete: setCategory,
|
||||
}
|
||||
);
|
||||
} else {
|
||||
// We are done!
|
||||
$(opts.modal).modal('hide');
|
||||
|
||||
$(table).bootstrapTable('refresh');
|
||||
}
|
||||
}
|
||||
|
||||
// Start the ball rolling
|
||||
showModalSpinner(opts.modal);
|
||||
setCategory();
|
||||
},
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
@ -31,7 +31,6 @@
|
||||
inventreeLoad,
|
||||
inventreePut,
|
||||
launchModalForm,
|
||||
linkButtonsToSelection,
|
||||
loadTableFilters,
|
||||
makeCopyButton,
|
||||
makeDeleteButton,
|
||||
@ -606,7 +605,7 @@ function newSupplierPartFromOrderWizard(e) {
|
||||
/*
|
||||
* Create a new form to order parts based on the list of provided parts.
|
||||
*/
|
||||
function orderParts(parts_list, options) {
|
||||
function orderParts(parts_list, options={}) {
|
||||
|
||||
var parts = [];
|
||||
|
||||
@ -786,7 +785,7 @@ function orderParts(parts_list, options) {
|
||||
supplier_part_filters.manufacturer_part = options.manufacturer_part;
|
||||
}
|
||||
|
||||
// Construct API filtres for the PurchaseOrder field
|
||||
// Construct API filters for the PurchaseOrder field
|
||||
var order_filters = {
|
||||
status: {{ PurchaseOrderStatus.PENDING }},
|
||||
supplier_detail: true,
|
||||
@ -822,6 +821,10 @@ function orderParts(parts_list, options) {
|
||||
|
||||
$(opts.modal).find(`#info-pack-size-${pk}`).remove();
|
||||
|
||||
if (typeof value === 'object') {
|
||||
value = value.pk;
|
||||
}
|
||||
|
||||
if (value != null) {
|
||||
inventreeGet(
|
||||
`/api/company/part/${value}/`,
|
||||
@ -1866,14 +1869,9 @@ function loadPurchaseOrderLineItemTable(table, options={}) {
|
||||
|
||||
var filters = loadTableFilters('purchaseorderlineitem', options.params);
|
||||
|
||||
setupFilterList(
|
||||
'purchaseorderlineitem',
|
||||
$(table),
|
||||
options.filter_target || '#filter-list-purchase-order-lines',
|
||||
{
|
||||
download: true
|
||||
}
|
||||
);
|
||||
setupFilterList('purchaseorderlineitem', $(table), options.filter_target || '#filter-list-purchase-order-lines', {
|
||||
download: true,
|
||||
});
|
||||
|
||||
function setupCallbacks() {
|
||||
if (options.allow_edit) {
|
||||
@ -2211,12 +2209,4 @@ function loadPurchaseOrderLineItemTable(table, options={}) {
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
linkButtonsToSelection(
|
||||
table,
|
||||
[
|
||||
'#multi-select-options',
|
||||
]
|
||||
);
|
||||
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
{% load i18n %}
|
||||
|
||||
/* globals
|
||||
checkPermission,
|
||||
getModelRenderer,
|
||||
inventreeGet,
|
||||
inventreePut,
|
||||
@ -22,40 +23,6 @@ function closeSearchPanel() {
|
||||
}
|
||||
|
||||
|
||||
// Keep track of the roles / permissions available to the current user
|
||||
var search_user_roles = null;
|
||||
|
||||
|
||||
/*
|
||||
* Check if the user has the specified role and permission
|
||||
*/
|
||||
function checkPermission(role, permission='view') {
|
||||
|
||||
if (!search_user_roles) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!(role in search_user_roles)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var roles = search_user_roles[role];
|
||||
|
||||
if (!roles) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var found = false;
|
||||
|
||||
search_user_roles[role].forEach(function(p) {
|
||||
if (String(p).valueOf() == String(permission).valueOf()) {
|
||||
found = true;
|
||||
}
|
||||
});
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Callback when the search panel is opened.
|
||||
@ -71,15 +38,6 @@ function openSearchPanel() {
|
||||
|
||||
clearSearchResults();
|
||||
|
||||
// Request user roles if we do not have them
|
||||
if (search_user_roles == null) {
|
||||
inventreeGet('{% url "api-user-roles" %}', {}, {
|
||||
success: function(response) {
|
||||
search_user_roles = response.roles || {};
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Callback for text input changed
|
||||
search_input.on('keyup change', searchTextChanged);
|
||||
|
||||
|
@ -30,7 +30,6 @@
|
||||
inventreePut,
|
||||
inventreeSave,
|
||||
launchModalForm,
|
||||
linkButtonsToSelection,
|
||||
loadTableFilters,
|
||||
makeDeleteButton,
|
||||
makeEditButton,
|
||||
@ -1707,6 +1706,121 @@ function locationDetail(row, showLink=true) {
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Construct a set of custom actions for the stock table
|
||||
*/
|
||||
function makeStockActions(table) {
|
||||
let actions = [
|
||||
{
|
||||
label: 'add',
|
||||
icon: 'fa-plus-circle icon-green',
|
||||
title: '{% trans "Add stock" %}',
|
||||
permission: 'stock.change',
|
||||
callback: function(data) {
|
||||
stockAdjustment('add', data, table);
|
||||
}
|
||||
},
|
||||
{
|
||||
label: 'remove',
|
||||
icon: 'fa-minus-circle icon-red',
|
||||
title: '{% trans "Remove stock" %}',
|
||||
permission: 'stock.change',
|
||||
callback: function(data) {
|
||||
stockAdjustment('take', data, table);
|
||||
},
|
||||
},
|
||||
{
|
||||
label: 'stocktake',
|
||||
icon: 'fa-check-circle icon-blue',
|
||||
title: '{% trans "Count stock" %}',
|
||||
permission: 'stock.change',
|
||||
callback: function(data) {
|
||||
stockAdjustment('count', data, table);
|
||||
},
|
||||
},
|
||||
{
|
||||
label: 'move',
|
||||
icon: 'fa-exchange-alt icon-blue',
|
||||
title: '{% trans "Transfer stock" %}',
|
||||
permission: 'stock.change',
|
||||
callback: function(data) {
|
||||
stockAdjustment('move', data, table);
|
||||
}
|
||||
},
|
||||
{
|
||||
label: 'status',
|
||||
icon: 'fa-info-circle icon-blue',
|
||||
title: '{% trans "Change stock status" %}',
|
||||
permission: 'stock.change',
|
||||
callback: function(data) {
|
||||
setStockStatus(data, {table: table});
|
||||
},
|
||||
},
|
||||
{
|
||||
label: 'merge',
|
||||
icon: 'fa-object-group',
|
||||
title: '{% trans "Merge stock" %}',
|
||||
permission: 'stock.change',
|
||||
callback: function(data) {
|
||||
mergeStockItems(data, {
|
||||
success: function(response) {
|
||||
$(table).bootstrapTable('refresh');
|
||||
|
||||
showMessage('{% trans "Merged stock items" %}', {
|
||||
style: 'success',
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
},
|
||||
{
|
||||
label: 'order',
|
||||
icon: 'fa-shopping-cart',
|
||||
title: '{% trans "Order stock" %}',
|
||||
permission: 'stock.change',
|
||||
callback: function(data) {
|
||||
let parts = [];
|
||||
|
||||
data.forEach(function(item) {
|
||||
var part = item.part_detail;
|
||||
|
||||
if (part) {
|
||||
parts.push(part);
|
||||
}
|
||||
});
|
||||
|
||||
orderParts(parts, {});
|
||||
},
|
||||
},
|
||||
{
|
||||
label: 'assign',
|
||||
icon: 'fa-user-tie',
|
||||
title: '{% trans "Assign to customer" %}',
|
||||
permission: 'stock.change',
|
||||
callback: function(data) {
|
||||
assignStockToCustomer(data, {
|
||||
success: function() {
|
||||
$(table).bootstrapTable('refresh');
|
||||
}
|
||||
});
|
||||
},
|
||||
},
|
||||
{
|
||||
label: 'delete',
|
||||
icon: 'fa-trash-alt icon-red',
|
||||
title: '{% trans "Delete stock" %}',
|
||||
permission: 'stock.delete',
|
||||
callback: function(data) {
|
||||
stockAdjustment('delete', data, table);
|
||||
},
|
||||
}
|
||||
];
|
||||
|
||||
return actions;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* Load data into a stock table with adjustable options.
|
||||
* Fetches data (via AJAX) and loads into a bootstrap table.
|
||||
* Also links in default button callbacks.
|
||||
@ -1746,7 +1860,26 @@ function loadStockTable(table, options) {
|
||||
key: 'item',
|
||||
},
|
||||
singular_name: '{% trans "stock item" %}',
|
||||
plural_name: '{% trans "stock items" %}'
|
||||
plural_name: '{% trans "stock items" %}',
|
||||
barcode_actions: [
|
||||
{
|
||||
icon: 'fa-sitemap',
|
||||
label: 'scantolocation',
|
||||
title: '{% trans "Scan to location" %}',
|
||||
permission: 'stock.change',
|
||||
callback: function(items) {
|
||||
scanItemsIntoLocation(items);
|
||||
}
|
||||
}
|
||||
],
|
||||
custom_actions: [
|
||||
{
|
||||
actions: makeStockActions(table),
|
||||
icon: 'fa-boxes',
|
||||
title: '{% trans "Stock Actions" %}',
|
||||
label: 'stock',
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
// Override the default values, or add new ones
|
||||
@ -2267,114 +2400,6 @@ function loadStockTable(table, options) {
|
||||
buttons.push('#stock-barcode-options');
|
||||
}
|
||||
|
||||
linkButtonsToSelection(
|
||||
table,
|
||||
buttons,
|
||||
);
|
||||
|
||||
function stockAdjustment(action) {
|
||||
var items = getTableData(table);
|
||||
|
||||
adjustStock(action, items, {
|
||||
success: function() {
|
||||
$(table).bootstrapTable('refresh');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Automatically link button callbacks
|
||||
if (global_settings.BARCODE_ENABLE) {
|
||||
$('#multi-item-barcode-scan-into-location').click(function() {
|
||||
var selections = getTableData(table);
|
||||
|
||||
var items = [];
|
||||
|
||||
selections.forEach(function(item) {
|
||||
items.push(item);
|
||||
});
|
||||
|
||||
scanItemsIntoLocation(items);
|
||||
});
|
||||
}
|
||||
|
||||
// Callback for 'stocktake' button
|
||||
$('#multi-item-stocktake').click(function() {
|
||||
stockAdjustment('count');
|
||||
});
|
||||
|
||||
// Callback for 'remove stock' button
|
||||
$('#multi-item-remove').click(function() {
|
||||
stockAdjustment('take');
|
||||
});
|
||||
|
||||
// Callback for 'add stock' button
|
||||
$('#multi-item-add').click(function() {
|
||||
stockAdjustment('add');
|
||||
});
|
||||
|
||||
// Callback for 'move stock' button
|
||||
$('#multi-item-move').click(function() {
|
||||
stockAdjustment('move');
|
||||
});
|
||||
|
||||
// Callback for 'merge stock' button
|
||||
$('#multi-item-merge').click(function() {
|
||||
var items = getTableData(table);
|
||||
|
||||
mergeStockItems(items, {
|
||||
success: function(response) {
|
||||
$(table).bootstrapTable('refresh');
|
||||
|
||||
showMessage('{% trans "Merged stock items" %}', {
|
||||
style: 'success',
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Callback for 'assign stock' button
|
||||
$('#multi-item-assign').click(function() {
|
||||
|
||||
var items = getTableData(table);
|
||||
|
||||
assignStockToCustomer(items, {
|
||||
success: function() {
|
||||
$(table).bootstrapTable('refresh');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Callback for 'un-assign stock' button
|
||||
$('#multi-item-order').click(function() {
|
||||
|
||||
var selections = getTableData(table);
|
||||
|
||||
var parts = [];
|
||||
|
||||
selections.forEach(function(item) {
|
||||
var part = item.part_detail;
|
||||
|
||||
if (part) {
|
||||
parts.push(part);
|
||||
}
|
||||
});
|
||||
|
||||
orderParts(parts, {});
|
||||
});
|
||||
|
||||
// Callback for 'delete stock' button
|
||||
$('#multi-item-delete').click(function() {
|
||||
var selections = getTableData(table);
|
||||
|
||||
var stock = [];
|
||||
|
||||
selections.forEach(function(item) {
|
||||
stock.push(item.pk);
|
||||
});
|
||||
|
||||
stockAdjustment('delete');
|
||||
});
|
||||
|
||||
// Callback for 'change status' button
|
||||
$('#multi-item-status').click(function() {
|
||||
let selections = getTableData(table);
|
||||
@ -2384,35 +2409,9 @@ function loadStockTable(table, options) {
|
||||
items.push(item.pk);
|
||||
});
|
||||
|
||||
if (items.length == 0) {
|
||||
showAlertDialog(
|
||||
'{% trans "Select Stock Items" %}',
|
||||
'{% trans "Select one or more stock items" %}'
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
let html = `
|
||||
<div class='alert alert-info alert-block>
|
||||
{% trans "Selected stock items" %}: ${items.length}
|
||||
</div>`;
|
||||
|
||||
constructForm('{% url "api-stock-change-status" %}', {
|
||||
title: '{% trans "Change Stock Status" %}',
|
||||
method: 'POST',
|
||||
preFormContent: html,
|
||||
fields: {
|
||||
status: {},
|
||||
note: {},
|
||||
},
|
||||
processBeforeUpload: function(data) {
|
||||
data.items = items;
|
||||
return data;
|
||||
},
|
||||
onSuccess: function() {
|
||||
$(table).bootstrapTable('refresh');
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
@ -2917,10 +2916,6 @@ function loadStockTrackingTable(table, options) {
|
||||
url: options.url,
|
||||
});
|
||||
|
||||
if (options.buttons) {
|
||||
linkButtonsToSelection(table, options.buttons);
|
||||
}
|
||||
|
||||
table.on('click', '.btn-entry-edit', function() {
|
||||
var button = $(this);
|
||||
|
||||
@ -3131,3 +3126,55 @@ function installStockItem(stock_item_id, part_id, options={}) {
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
// Perform the specified stock adjustment action against the selected items
|
||||
function stockAdjustment(action, items, table) {
|
||||
adjustStock(action, items, {
|
||||
success: function() {
|
||||
$(table).bootstrapTable('refresh');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Set the status of the selected stock items
|
||||
*/
|
||||
function setStockStatus(items, options={}) {
|
||||
|
||||
if (items.length == 0) {
|
||||
showAlertDialog(
|
||||
'{% trans "Select Stock Items" %}',
|
||||
'{% trans "Select one or more stock items" %}'
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
let id_values = [];
|
||||
|
||||
items.forEach(function(item) {
|
||||
id_values.push(item.pk)
|
||||
});
|
||||
|
||||
let html = `
|
||||
<div class='alert alert-info alert-block>
|
||||
{% trans "Selected stock items" %}: ${items.length}
|
||||
</div>`;
|
||||
|
||||
constructForm('{% url "api-stock-change-status" %}', {
|
||||
title: '{% trans "Change Stock Status" %}',
|
||||
method: 'POST',
|
||||
preFormContent: html,
|
||||
fields: {
|
||||
status: {},
|
||||
note: {},
|
||||
},
|
||||
processBeforeUpload: function(data) {
|
||||
data.items = items;
|
||||
return data;
|
||||
},
|
||||
onSuccess: function() {
|
||||
$(options.table).bootstrapTable('refresh');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -52,6 +52,12 @@ function constructHasProjectCodeFilter() {
|
||||
}
|
||||
|
||||
|
||||
// Reset a dictionary of filters for the attachment table
|
||||
function getAttachmentFilters() {
|
||||
return {};
|
||||
}
|
||||
|
||||
|
||||
// Return a dictionary of filters for the return order table
|
||||
function getReturnOrderFilters() {
|
||||
var filters = {
|
||||
@ -487,6 +493,11 @@ function getBuildTableFilters() {
|
||||
}
|
||||
|
||||
|
||||
function getBuildItemTableFilters() {
|
||||
return {};
|
||||
}
|
||||
|
||||
|
||||
// Return a dictionary of filters for the "build lines" table
|
||||
function getBuildLineTableFilters() {
|
||||
return {
|
||||
@ -770,6 +781,16 @@ function getAvailableTableFilters(tableKey) {
|
||||
tableKey = tableKey.toLowerCase();
|
||||
|
||||
switch (tableKey) {
|
||||
case 'attachments':
|
||||
return getAttachmentFilters();
|
||||
case 'build':
|
||||
return getBuildTableFilters();
|
||||
case 'builditems':
|
||||
return getBuildItemTableFilters();
|
||||
case 'buildlines':
|
||||
return getBuildLineTableFilters();
|
||||
case 'bom':
|
||||
return getBOMTableFilters();
|
||||
case 'category':
|
||||
return getPartCategoryFilters();
|
||||
case 'company':
|
||||
@ -778,12 +799,6 @@ function getAvailableTableFilters(tableKey) {
|
||||
return getContactFilters();
|
||||
case 'customerstock':
|
||||
return getCustomerStockFilters();
|
||||
case 'bom':
|
||||
return getBOMTableFilters();
|
||||
case 'build':
|
||||
return getBuildTableFilters();
|
||||
case 'buildlines':
|
||||
return getBuildLineTableFilters();
|
||||
case 'location':
|
||||
return getStockLocationFilters();
|
||||
case 'parameters':
|
||||
|
@ -38,10 +38,10 @@ function reloadBootstrapTable(table) {
|
||||
if (tbl.exists()) {
|
||||
tbl.bootstrapTable('refresh');
|
||||
} else {
|
||||
console.error(`Invalid table name passed to reloadTable(): ${table}`);
|
||||
console.error(`Invalid table name passed to reloadBootstrapTable(): ${table}`);
|
||||
}
|
||||
} else {
|
||||
console.error(`Null value passed to reloadTable()`);
|
||||
console.error(`Null value passed to reloadBootstrapTable()`);
|
||||
}
|
||||
}
|
||||
|
||||
@ -220,25 +220,6 @@ function enableButtons(elements, enabled) {
|
||||
}
|
||||
|
||||
|
||||
/* Link a bootstrap-table object to one or more buttons.
|
||||
* The buttons will only be enabled if there is at least one row selected
|
||||
*/
|
||||
function linkButtonsToSelection(table, buttons) {
|
||||
|
||||
if (typeof table === 'string') {
|
||||
table = $(table);
|
||||
}
|
||||
|
||||
// Initially set the enable state of the buttons
|
||||
enableButtons(buttons, table.bootstrapTable('getSelections').length > 0);
|
||||
|
||||
// Add a callback
|
||||
table.on('check.bs.table uncheck.bs.table check-some.bs.table uncheck-some.bs.table check-all.bs.table uncheck-all.bs.table', function() {
|
||||
enableButtons(buttons, table.bootstrapTable('getSelections').length > 0);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns true if the input looks like a valid number
|
||||
* @param {String} n
|
||||
@ -474,11 +455,6 @@ $.fn.inventreeTable = function(options) {
|
||||
console.error(`Could not get list of visible columns for table '${tableName}'`);
|
||||
}
|
||||
}
|
||||
|
||||
// Optionally, link buttons to the table selection
|
||||
if (options.buttons) {
|
||||
linkButtonsToSelection(table, options.buttons);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
@ -9,46 +9,7 @@
|
||||
{% endif %}
|
||||
|
||||
<div id='{{ prefix }}button-toolbar'>
|
||||
<div class='button-toolbar container-fluid' style='float: right;'>
|
||||
<div class='btn-group' role='group'>
|
||||
{% if barcodes %}
|
||||
<!-- Barcode actions menu -->
|
||||
<div class='btn-group' role='group'>
|
||||
<button id='stock-barcode-options' class='btn btn-primary dropdown-toggle' type='button' data-bs-toggle='dropdown' title='{% trans "Barcode Actions" %}'>
|
||||
<span class='fas fa-qrcode'></span> <span class='caret'></span>
|
||||
</button>
|
||||
<ul class='dropdown-menu'>
|
||||
<li><a class='dropdown-item' href='#' id='multi-item-barcode-scan-into-location' title='{% trans "Scan to Location" %}'><span class='fas fa-sitemap'></span> {% trans "Scan to Location" %}</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if not read_only %}
|
||||
{% if roles.stock.change or roles.stock.delete %}
|
||||
<div class="btn-group" role="group">
|
||||
<button id='stock-options' class="btn btn-primary dropdown-toggle" type="button" data-bs-toggle="dropdown" title='{% trans "Stock Options" %}'>
|
||||
<span class='fas fa-boxes'></span> <span class="caret"></span>
|
||||
</button>
|
||||
<ul class="dropdown-menu">
|
||||
{% if roles.stock.change %}
|
||||
<li><a class='dropdown-item' href="#" id='multi-item-add' title='{% trans "Add to selected stock items" %}'><span class='fas fa-plus-circle icon-green'></span> {% trans "Add stock" %}</a></li>
|
||||
<li><a class='dropdown-item' href="#" id='multi-item-remove' title='{% trans "Remove from selected stock items" %}'><span class='fas fa-minus-circle icon-red'></span> {% trans "Remove stock" %}</a></li>
|
||||
<li><a class='dropdown-item' href="#" id='multi-item-stocktake' title='{% trans "Stocktake selected stock items" %}'><span class='fas fa-check-circle icon-green'></span> {% trans "Count stock" %}</a></li>
|
||||
<li><a class='dropdown-item' href='#' id='multi-item-move' title='{% trans "Move selected stock items" %}'><span class='fas fa-exchange-alt icon-blue'></span> {% trans "Transfer stock" %}</a></li>
|
||||
<li><a class='dropdown-item' href='#' id='multi-item-status' title='{% trans "Change stock status" %}'><span class='fas fa-info-circle icon-blue'></span> {% trans "Change stock status" %}</a></li>
|
||||
<li><a class='dropdown-item' href='#' id='multi-item-merge' title='{% trans "Merge selected stock items" %}'><span class='fas fa-object-group'></span> {% trans "Merge stock" %}</a></li>
|
||||
<li><a class='dropdown-item' href='#' id='multi-item-order' title='{% trans "Order selected items" %}'><span class='fas fa-shopping-cart'></span> {% trans "Order stock" %}</a></li>
|
||||
<li><a class='dropdown-item' href='#' id='multi-item-assign' title='{% trans "Assign to customer" %}'><span class='fas fa-user-tie'></span> {% trans "Assign to customer" %}</a></li>
|
||||
{% endif %}
|
||||
{% if roles.stock.delete %}
|
||||
<li><a class='dropdown-item' href='#' id='multi-item-delete' title='{% trans "Delete selected items" %}'><span class='fas fa-trash-alt icon-red'></span> {% trans "Delete stock" %}</a></li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% include "filter_list.html" with prefix=prefix id="stock" %}
|
||||
</div>
|
||||
</div>
|
||||
{% include "filter_list.html" with prefix=prefix id="stock" %}
|
||||
</div>
|
||||
|
||||
<table class='table table-striped table-condensed' data-toolbar='#{{ prefix }}button-toolbar' id='{{ prefix }}stock-table'>
|
||||
|
Loading…
Reference in New Issue
Block a user