diff --git a/InvenTree/InvenTree/urls.py b/InvenTree/InvenTree/urls.py
index b7b49a51ae..e98268db9c 100644
--- a/InvenTree/InvenTree/urls.py
+++ b/InvenTree/InvenTree/urls.py
@@ -111,6 +111,7 @@ translated_javascript_urls = [
re_path(r'^filters.js', DynamicJsView.as_view(template_name='js/translated/filters.js'), name='filters.js'),
re_path(r'^forms.js', DynamicJsView.as_view(template_name='js/translated/forms.js'), name='forms.js'),
re_path(r'^helpers.js', DynamicJsView.as_view(template_name='js/translated/helpers.js'), name='helpers.js'),
+ re_path(r'^index.js', DynamicJsView.as_view(template_name='js/translated/index.js'), name='index.js'),
re_path(r'^label.js', DynamicJsView.as_view(template_name='js/translated/label.js'), name='label.js'),
re_path(r'^model_renderers.js', DynamicJsView.as_view(template_name='js/translated/model_renderers.js'), name='model_renderers.js'),
re_path(r'^modals.js', DynamicJsView.as_view(template_name='js/translated/modals.js'), name='modals.js'),
diff --git a/InvenTree/part/api.py b/InvenTree/part/api.py
index 801b0b5f8d..a66308f161 100644
--- a/InvenTree/part/api.py
+++ b/InvenTree/part/api.py
@@ -962,7 +962,7 @@ class PartFilter(rest_filters.FilterSet):
depleted_stock = rest_filters.BooleanFilter(label='Depleted Stock', method='filter_depleted_stock')
- def filter_deployed_stock(self, queryset, name, value):
+ def filter_depleted_stock(self, queryset, name, value):
"""Filter the queryset based on whether the part is fully depleted of stock"""
if str2bool(value):
diff --git a/InvenTree/templates/InvenTree/index.html b/InvenTree/templates/InvenTree/index.html
index 03b64bfa41..7e8526ca5e 100644
--- a/InvenTree/templates/InvenTree/index.html
+++ b/InvenTree/templates/InvenTree/index.html
@@ -25,61 +25,6 @@
{{ block.super }}
-function addHeaderTitle(title) {
-
- addSidebarHeader({
- text: title,
- });
-}
-
-function addHeaderAction(label, title, icon, options) {
-
- // Construct a "badge" to add to the sidebar item
- var badge = `
-
- `;
-
- addSidebarItem({
- label: label,
- text: title,
- icon: icon,
- content_after: badge
- });
-
- // Add a detail item to the detail item-panel
- $("#detail-panels").append(
- `
`
- );
-
- let table_name = `#table-${label}`;
-
- // Connect a callback to the table
- $(table_name).on('load-success.bs.table', function(data) {
-
- let options = $(table_name).bootstrapTable('getOptions');
-
- let count = options.totalRows;
-
- let badge = $(`#sidebar-badge-${label}`);
-
- badge.html(count);
-
- if (count > 0) {
- badge.removeClass('bg-dark');
- badge.addClass('bg-primary');
- }
- });
-}
-
{% settings_value 'HOMEPAGE_HIDE_INACTIVE' user=request.user as hide_inactive %}
{% settings_value 'HOMEPAGE_PART_STARRED' user=request.user as setting_part_starred %}
{% settings_value 'HOMEPAGE_CATEGORY_STARRED' user=request.user as setting_category_starred %}
@@ -93,6 +38,7 @@ addHeaderTitle('{% trans "Parts" %}');
{% if setting_part_starred %}
addHeaderAction('starred-parts', '{% trans "Subscribed Parts" %}', 'fa-bell');
loadSimplePartTable("#table-starred-parts", "{% url 'api-part-list' %}", {
+ name: 'starred-parts',
params: {
starred: true,
{% if hide_inactive %}
@@ -116,6 +62,7 @@ loadPartCategoryTable($('#table-starred-categories'), {
{% if setting_part_latest %}
addHeaderAction('latest-parts', '{% trans "Latest Parts" %}', 'fa-newspaper');
loadSimplePartTable("#table-latest-parts", "{% url 'api-part-list' %}", {
+ name: 'latest-parts',
params: {
ordering: "-creation_date",
created_after: moment().subtract(1, 'months').format('YYYY-MM-DD'),
@@ -130,6 +77,7 @@ loadSimplePartTable("#table-latest-parts", "{% url 'api-part-list' %}", {
{% if setting_bom_validation %}
addHeaderAction('bom-validation', '{% trans "BOM Waiting Validation" %}', 'fa-times-circle');
loadSimplePartTable("#table-bom-validation", "{% url 'api-part-list' %}", {
+ name: 'parts-invalid-bom',
params: {
"bom_valid": false,
{% if hide_inactive %}
@@ -158,6 +106,7 @@ loadSimplePartTable("#table-bom-validation", "{% url 'api-part-list' %}", {
{% if setting_stock_recent %}
addHeaderAction('recently-updated-stock', '{% trans "Recently Updated" %}', 'fa-clock');
loadStockTable($('#table-recently-updated-stock'), {
+ disableFilters: true,
params: {
part_detail: true,
ordering: "-updated",
@@ -170,6 +119,7 @@ loadStockTable($('#table-recently-updated-stock'), {
{% if setting_stock_low %}
addHeaderAction('low-stock', '{% trans "Low Stock" %}', 'fa-flag');
loadSimplePartTable("#table-low-stock", "{% url 'api-part-list' %}", {
+ name: 'parts-low-stock',
params: {
low_stock: true,
{% if hide_inactive %}
@@ -183,6 +133,7 @@ loadSimplePartTable("#table-low-stock", "{% url 'api-part-list' %}", {
{% if setting_stock_depleted %}
addHeaderAction('depleted-stock', '{% trans "Depleted Stock" %}', 'fa-times');
loadSimplePartTable("#table-depleted-stock", "{% url 'api-part-list' %}", {
+ name: 'parts-depleted-stock',
params: {
depleted_stock: true,
{% if hide_inactive %}
@@ -195,15 +146,8 @@ loadSimplePartTable("#table-depleted-stock", "{% url 'api-part-list' %}", {
{% if setting_stock_needed %}
addHeaderAction('stock-to-build', '{% trans "Required for Build Orders" %}', 'fa-bullhorn');
-loadSimplePartTable("#table-stock-to-build", "{% url 'api-part-list' %}", {
- params: {
- stock_to_build: true,
- {% if hide_inactive %}
- active: true,
- {% endif %}
- },
- name: "to_build_parts",
-});
+
+loadRequiredForBuildsPartsTable("#table-stock-to-build", {});
{% endif %}
{% if expiry %}
@@ -211,6 +155,7 @@ loadSimplePartTable("#table-stock-to-build", "{% url 'api-part-list' %}", {
{% if setting_stock_expired %}
addHeaderAction('expired-stock', '{% trans "Expired Stock" %}', 'fa-calendar-times');
loadStockTable($("#table-expired-stock"), {
+ disableFilters: true,
params: {
expired: true,
location_detail: true,
@@ -219,12 +164,14 @@ loadStockTable($("#table-expired-stock"), {
active: true,
{% endif %}
},
+ name: 'expired-stock',
});
{% endif %}
{% if setting_stock_stale %}
addHeaderAction('stale-stock', '{% trans "Stale Stock" %}', 'fa-stopwatch');
loadStockTable($("#table-stale-stock"), {
+ disableFilters: true,
params: {
stale: true,
expired: false,
@@ -234,6 +181,7 @@ loadStockTable($("#table-stale-stock"), {
active: true,
{% endif %}
},
+ name: 'stale-stock',
});
{% endif %}
diff --git a/InvenTree/templates/base.html b/InvenTree/templates/base.html
index b33721693a..7d46b47416 100644
--- a/InvenTree/templates/base.html
+++ b/InvenTree/templates/base.html
@@ -161,6 +161,7 @@
+
diff --git a/InvenTree/templates/js/translated/index.js b/InvenTree/templates/js/translated/index.js
new file mode 100644
index 0000000000..7b7a24d2a1
--- /dev/null
+++ b/InvenTree/templates/js/translated/index.js
@@ -0,0 +1,135 @@
+{% load i18n %}
+
+/* globals
+ addSidebarHeader,
+ addSidebarItem,
+ checkPermission,
+ global_settings,
+ imageHoverIcon,
+ makeProgressBar,
+ renderLink,
+ shortenString,
+ user_settings,
+ withTitle,
+*/
+
+/* exported
+ addHeaderAction,
+ addHeaderTitle,
+*/
+
+
+/*
+ * Add a 'header title' to the index sidebar
+ */
+function addHeaderTitle(title) {
+ addSidebarHeader({
+ text: title,
+ });
+}
+
+
+function addHeaderAction(label, title, icon, options) {
+
+ // Construct a "badge" to add to the sidebar item
+ var badge = `
+
+ `;
+
+ addSidebarItem({
+ label: label,
+ text: title,
+ icon: icon,
+ content_after: badge
+ });
+
+ // Add a detail item to the detail item-panel
+ $("#detail-panels").append(
+ ``
+ );
+
+ let table_name = `#table-${label}`;
+
+ // Connect a callback to the table
+ $(table_name).on('load-success.bs.table', function(data) {
+
+ let options = $(table_name).bootstrapTable('getOptions');
+
+ let count = options.totalRows;
+
+ let badge = $(`#sidebar-badge-${label}`);
+
+ badge.html(count);
+
+ if (count > 0) {
+ badge.removeClass('bg-dark');
+ badge.addClass('bg-primary');
+ }
+ });
+}
+
+
+/*
+ * Load a table displaying parts which are outstanding for builds
+ */
+function loadRequiredForBuildsPartsTable(table, options={}) {
+ let name = 'parts-required-for-builds';
+
+ let params = {
+ stock_to_build: true,
+ };
+
+ $(table).inventreeTable({
+ url: '{% url "api-part-list" %}',
+ queryParams: params,
+ name: name,
+ showColumns: false,
+ search: false,
+ sortable: false,
+ formatNoMatches: function() {
+ return '{% trans "No parts required for builds" %}';
+ },
+ columns: [
+ {
+ field: 'name',
+ title: '{% trans "Part" %}',
+ formatter: function(value, row) {
+ let name = shortenString(row.full_name);
+ let display= imageHoverIcon(row.thumbnail) + renderLink(name, `/part/${row.pk}/`);
+
+ return withTitle(display, row.full_name);
+ }
+ },
+ {
+ field: 'description',
+ title: '{% trans "Description" %}',
+ },
+ {
+ field: 'total_in_stock',
+ title: '{% trans "Available" %}',
+ formatter: function(value, row) {
+ return value;
+ }
+ },
+ {
+ field: 'allocated_to_build_orders',
+ title: '{% trans "Allocated Stock" %}',
+ formatter: function(_value, row) {
+ return makeProgressBar(
+ row.allocated_to_build_orders,
+ row.required_for_build_orders,
+ );
+ }
+ },
+ ]
+ });
+}
diff --git a/InvenTree/templates/js/translated/part.js b/InvenTree/templates/js/translated/part.js
index 8545f4e5f6..8c7df7a045 100644
--- a/InvenTree/templates/js/translated/part.js
+++ b/InvenTree/templates/js/translated/part.js
@@ -2237,30 +2237,36 @@ function loadPartTable(table, url, options={}) {
options.params = options.params || {};
+ let table_name = options.name || 'parts';
+
// Ensure category detail is included
options.params['category_detail'] = true;
var params = options.params || {};
- var filters = loadTableFilters('parts', options.params);
+ let filters = {};
- setupFilterList('parts', $(table), options.filterTarget, {
- download: true,
- labels: {
- url: '{% url "api-part-label-list" %}',
- key: 'part',
- },
- singular_name: '{% trans "part" %}',
- plural_name: '{% trans "parts" %}',
- custom_actions: [
- {
- label: 'parts',
- icon: 'fa-tools',
- title: '{% trans "Part actions" %}',
- actions: makePartActions(table),
- }
- ]
- });
+ if (!options.disableFilters) {
+ filters = loadTableFilters(table_name, options.params);
+
+ setupFilterList('parts', $(table), options.filterTarget, {
+ download: true,
+ labels: {
+ url: '{% url "api-part-label-list" %}',
+ key: 'part',
+ },
+ singular_name: '{% trans "part" %}',
+ plural_name: '{% trans "parts" %}',
+ custom_actions: [
+ {
+ label: 'parts',
+ icon: 'fa-tools',
+ title: '{% trans "Part actions" %}',
+ actions: makePartActions(table),
+ }
+ ]
+ });
+ }
var columns = [
{
@@ -2426,9 +2432,9 @@ function loadPartTable(table, url, options={}) {
$(table).inventreeTable({
url: url,
method: 'get',
+ name: table_name,
queryParams: filters,
groupBy: false,
- name: options.name || 'part',
original: params,
sidePagination: 'server',
pagination: 'true',
diff --git a/InvenTree/templates/js/translated/stock.js b/InvenTree/templates/js/translated/stock.js
index a29bd7bcb3..95cef81533 100644
--- a/InvenTree/templates/js/translated/stock.js
+++ b/InvenTree/templates/js/translated/stock.js
@@ -1843,44 +1843,48 @@ function loadStockTable(table, options) {
var params = options.params || {};
- const filterTarget = options.filterTarget || '#filter-list-stock';
+ let filters = {};
- const filterKey = options.filterKey || options.name || 'stock';
+ if (!options.disableFilters) {
- let filters = loadTableFilters(filterKey, params);
+ const filterTarget = options.filterTarget || '#filter-list-stock';
+ const filterKey = options.filterKey || options.name || 'stock';
- setupFilterList(filterKey, table, filterTarget, {
- download: true,
- report: {
- url: '{% url "api-stockitem-testreport-list" %}',
- key: 'item',
- },
- labels: {
- url: '{% url "api-stockitem-label-list" %}',
- key: 'item',
- },
- singular_name: '{% trans "stock item" %}',
- 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);
+ filters = loadTableFilters(filterKey, params);
+
+ setupFilterList(filterKey, table, filterTarget, {
+ download: true,
+ report: {
+ url: '{% url "api-stockitem-testreport-list" %}',
+ key: 'item',
+ },
+ labels: {
+ url: '{% url "api-stockitem-label-list" %}',
+ key: 'item',
+ },
+ singular_name: '{% trans "stock item" %}',
+ 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',
- }
- ]
- });
+ ],
+ custom_actions: [
+ {
+ actions: makeStockActions(table),
+ icon: 'fa-boxes',
+ title: '{% trans "Stock Actions" %}',
+ label: 'stock',
+ }
+ ]
+ });
+ }
// Override the default values, or add new ones
for (var key in params) {