diff --git a/InvenTree/InvenTree/static/script/inventree/part.js b/InvenTree/InvenTree/static/script/inventree/part.js
index 92460a51a7..64849a30a6 100644
--- a/InvenTree/InvenTree/static/script/inventree/part.js
+++ b/InvenTree/InvenTree/static/script/inventree/part.js
@@ -2,22 +2,6 @@
* Requires api.js to be loaded first
*/
-function getPartCategoryList(filters={}, options={}) {
- return inventreeGet('/api/part/category/', filters, options);
-}
-
-function getSupplierPartList(filters={}, options={}) {
- return inventreeGet('/api/part/supplier/', filters, options);
-}
-
-function getPartList(filters={}, options={}) {
- return inventreeGet('/api/part/', filters, options);
-}
-
-function getBomList(filters={}, options={}) {
- return inventreeGet('/api/bom/', filters, options);
-}
-
function toggleStar(options) {
/* Toggle the 'starred' status of a part.
* Performs AJAX queries and updates the display on the button.
@@ -72,230 +56,4 @@ function toggleStar(options) {
},
}
);
-}
-
-function loadPartTable(table, url, options={}) {
- /* Load part listing data into specified table.
- *
- * Args:
- * - table: HTML reference to the table
- * - url: Base URL for API query
- * - options: object containing following (optional) fields
- * checkbox: Show the checkbox column
- * query: extra query params for API request
- * buttons: If provided, link buttons to selection status of this table
- * disableFilters: If true, disable custom filters
- */
-
- // Ensure category detail is included
- options.params['category_detail'] = true;
-
- var params = options.params || {};
-
- var filters = {};
-
- if (!options.disableFilters) {
- filters = loadTableFilters("parts");
- }
-
- for (var key in params) {
- filters[key] = params[key];
- }
-
- setupFilterList("parts", $(table));
-
- var columns = [
- {
- field: 'pk',
- title: 'ID',
- visible: false,
- }
- ];
-
- if (options.checkbox) {
- columns.push({
- checkbox: true,
- title: 'Select',
- searchable: false,
- });
- }
-
- columns.push({
- field: 'name',
- title: 'Part',
- sortable: true,
- formatter: function(value, row, index, field) {
-
- var name = '';
-
- if (row.IPN) {
- name += row.IPN;
- name += ' | ';
- }
-
- name += value;
-
- if (row.revision) {
- name += ' | ';
- name += row.revision;
- }
-
- if (row.is_template) {
- name = '' + name + '';
- }
-
- var display = imageHoverIcon(row.thumbnail) + renderLink(name, '/part/' + row.pk + '/');
-
- if (row.is_template) {
- display += ``;
- }
-
- if (row.assembly) {
- display += ``;
- }
-
- if (row.starred) {
- display += ``;
- }
-
- if (row.salable) {
- display += ``;
- }
-
- /*
- if (row.component) {
- display = display + ``;
- }
- */
-
- if (!row.active) {
- display += `INACTIVE`;
- }
- return display;
- }
- });
-
- columns.push({
- sortable: true,
- field: 'description',
- title: 'Description',
- formatter: function(value, row, index, field) {
-
- if (row.is_template) {
- value = '' + value + '';
- }
-
- return value;
- }
- });
-
- columns.push({
- sortable: true,
- field: 'category_detail',
- title: 'Category',
- formatter: function(value, row, index, field) {
- if (row.category) {
- return renderLink(value.pathstring, "/part/category/" + row.category + "/");
- }
- else {
- return 'No category';
- }
- }
- });
-
- columns.push({
- field: 'in_stock',
- title: 'Stock',
- searchable: false,
- sortable: true,
- formatter: function(value, row, index, field) {
- var link = "stock";
-
- if (value) {
- // There IS stock available for this part
-
- // Is stock "low" (below the 'minimum_stock' quantity)?
- if (row.minimum_stock && row.minimum_stock > value) {
- value += "Low stock";
- }
-
- } else if (row.on_order) {
- // There is no stock available, but stock is on order
- value = "0On Order : " + row.on_order + "";
- link = "orders";
- } else if (row.building) {
- // There is no stock available, but stock is being built
- value = "0Building : " + row.building + "";
- link = "builds";
- } else {
- // There is no stock available
- value = "0No Stock";
- }
-
- return renderLink(value, '/part/' + row.pk + "/" + link + "/");
- }
- });
-
- $(table).inventreeTable({
- url: url,
- sortName: 'name',
- method: 'get',
- queryParams: filters,
- groupBy: false,
- original: params,
- formatNoMatches: function() { return "No parts found"; },
- columns: columns,
- });
-
- if (options.buttons) {
- linkButtonsToSelection($(table), options.buttons);
- }
-
- /* Button callbacks for part table buttons */
-
- $("#multi-part-order").click(function() {
- var selections = $(table).bootstrapTable("getSelections");
-
- var parts = [];
-
- selections.forEach(function(item) {
- parts.push(item.pk);
- });
-
- launchModalForm("/order/purchase-order/order-parts/", {
- data: {
- parts: parts,
- },
- });
- });
-
- $("#multi-part-category").click(function() {
- var selections = $(table).bootstrapTable("getSelections");
-
- var parts = [];
-
- selections.forEach(function(item) {
- parts.push(item.pk);
- });
-
- launchModalForm("/part/set-category/", {
- data: {
- parts: parts,
- },
- reload: true,
- });
- });
-
- $('#multi-part-export').click(function() {
- var selections = $(table).bootstrapTable("getSelections");
-
- var parts = '';
-
- selections.forEach(function(item) {
- parts += item.pk;
- parts += ',';
- });
-
- location.href = '/part/export/?parts=' + parts;
- });
}
\ No newline at end of file
diff --git a/InvenTree/InvenTree/urls.py b/InvenTree/InvenTree/urls.py
index cf53667fb9..a3a8950401 100644
--- a/InvenTree/InvenTree/urls.py
+++ b/InvenTree/InvenTree/urls.py
@@ -35,6 +35,7 @@ from rest_framework.documentation import include_docs_urls
from .views import IndexView, SearchView, DatabaseStatsView
from .views import SettingsView, EditUserView, SetPasswordView
+from .views import DynamicJsView
from .api import InfoView, BarcodePluginView, ActionPluginView
@@ -74,6 +75,7 @@ settings_urls = [
]
dynamic_javascript_urls = [
+ url(r'^part.js', DynamicJsView.as_view(template_name='js/part.js'), name='part.js'),
]
urlpatterns = [
diff --git a/InvenTree/InvenTree/views.py b/InvenTree/InvenTree/views.py
index 943a18d35c..400981eb17 100644
--- a/InvenTree/InvenTree/views.py
+++ b/InvenTree/InvenTree/views.py
@@ -514,6 +514,18 @@ class SearchView(TemplateView):
return super(TemplateView, self).render_to_response(context)
+class DynamicJsView(TemplateView):
+ """
+ View for returning javacsript files,
+ which instead of being served dynamically,
+ are passed through the django translation engine!
+ """
+
+ template_name = ""
+ content_type = 'text/javascript'
+
+
+
class SettingsView(TemplateView):
""" View for configuring User settings
"""
diff --git a/InvenTree/templates/base.html b/InvenTree/templates/base.html
index bf5fa4a1c3..9d8f650c69 100644
--- a/InvenTree/templates/base.html
+++ b/InvenTree/templates/base.html
@@ -114,6 +114,8 @@ InvenTree
+
+
diff --git a/InvenTree/templates/js/part.js b/InvenTree/templates/js/part.js
new file mode 100644
index 0000000000..aea67065ca
--- /dev/null
+++ b/InvenTree/templates/js/part.js
@@ -0,0 +1,227 @@
+{% load i18n %}
+
+function loadPartTable(table, url, options={}) {
+ /* Load part listing data into specified table.
+ *
+ * Args:
+ * - table: HTML reference to the table
+ * - url: Base URL for API query
+ * - options: object containing following (optional) fields
+ * checkbox: Show the checkbox column
+ * query: extra query params for API request
+ * buttons: If provided, link buttons to selection status of this table
+ * disableFilters: If true, disable custom filters
+ */
+
+ // Ensure category detail is included
+ options.params['category_detail'] = true;
+
+ var params = options.params || {};
+
+ var filters = {};
+
+ if (!options.disableFilters) {
+ filters = loadTableFilters("parts");
+ }
+
+ for (var key in params) {
+ filters[key] = params[key];
+ }
+
+ setupFilterList("parts", $(table));
+
+ var columns = [
+ {
+ field: 'pk',
+ title: 'ID',
+ visible: false,
+ }
+ ];
+
+ if (options.checkbox) {
+ columns.push({
+ checkbox: true,
+ title: 'Select',
+ searchable: false,
+ });
+ }
+
+ columns.push({
+ field: 'name',
+ title: 'Part',
+ sortable: true,
+ formatter: function(value, row, index, field) {
+
+ var name = '';
+
+ if (row.IPN) {
+ name += row.IPN;
+ name += ' | ';
+ }
+
+ name += value;
+
+ if (row.revision) {
+ name += ' | ';
+ name += row.revision;
+ }
+
+ if (row.is_template) {
+ name = '' + name + '';
+ }
+
+ var display = imageHoverIcon(row.thumbnail) + renderLink(name, '/part/' + row.pk + '/');
+
+ if (row.is_template) {
+ display += ``;
+ }
+
+ if (row.assembly) {
+ display += ``;
+ }
+
+ if (row.starred) {
+ display += ``;
+ }
+
+ if (row.salable) {
+ display += ``;
+ }
+
+ /*
+ if (row.component) {
+ display = display + ``;
+ }
+ */
+
+ if (!row.active) {
+ display += `INACTIVE`;
+ }
+ return display;
+ }
+ });
+
+ columns.push({
+ sortable: true,
+ field: 'description',
+ title: 'Description',
+ formatter: function(value, row, index, field) {
+
+ if (row.is_template) {
+ value = '' + value + '';
+ }
+
+ return value;
+ }
+ });
+
+ columns.push({
+ sortable: true,
+ field: 'category_detail',
+ title: 'Category',
+ formatter: function(value, row, index, field) {
+ if (row.category) {
+ return renderLink(value.pathstring, "/part/category/" + row.category + "/");
+ }
+ else {
+ return 'No category';
+ }
+ }
+ });
+
+ columns.push({
+ field: 'in_stock',
+ title: 'Stock',
+ searchable: false,
+ sortable: true,
+ formatter: function(value, row, index, field) {
+ var link = "stock";
+
+ if (value) {
+ // There IS stock available for this part
+
+ // Is stock "low" (below the 'minimum_stock' quantity)?
+ if (row.minimum_stock && row.minimum_stock > value) {
+ value += "Low stock";
+ }
+
+ } else if (row.on_order) {
+ // There is no stock available, but stock is on order
+ value = "0On Order : " + row.on_order + "";
+ link = "orders";
+ } else if (row.building) {
+ // There is no stock available, but stock is being built
+ value = "0Building : " + row.building + "";
+ link = "builds";
+ } else {
+ // There is no stock available
+ value = "0No Stock";
+ }
+
+ return renderLink(value, '/part/' + row.pk + "/" + link + "/");
+ }
+ });
+
+ $(table).inventreeTable({
+ url: url,
+ sortName: 'name',
+ method: 'get',
+ queryParams: filters,
+ groupBy: false,
+ original: params,
+ formatNoMatches: function() { return "No parts found"; },
+ columns: columns,
+ });
+
+ if (options.buttons) {
+ linkButtonsToSelection($(table), options.buttons);
+ }
+
+ /* Button callbacks for part table buttons */
+
+ $("#multi-part-order").click(function() {
+ var selections = $(table).bootstrapTable("getSelections");
+
+ var parts = [];
+
+ selections.forEach(function(item) {
+ parts.push(item.pk);
+ });
+
+ launchModalForm("/order/purchase-order/order-parts/", {
+ data: {
+ parts: parts,
+ },
+ });
+ });
+
+ $("#multi-part-category").click(function() {
+ var selections = $(table).bootstrapTable("getSelections");
+
+ var parts = [];
+
+ selections.forEach(function(item) {
+ parts.push(item.pk);
+ });
+
+ launchModalForm("/part/set-category/", {
+ data: {
+ parts: parts,
+ },
+ reload: true,
+ });
+ });
+
+ $('#multi-part-export').click(function() {
+ var selections = $(table).bootstrapTable("getSelections");
+
+ var parts = '';
+
+ selections.forEach(function(item) {
+ parts += item.pk;
+ parts += ',';
+ });
+
+ location.href = '/part/export/?parts=' + parts;
+ });
+}
\ No newline at end of file