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( - `
-
-

${title}

-
-
-
-
-
` - ); - - 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( + `
+
+

${title}

+
+
+
+
+
` + ); + + 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) {