@@ -190,6 +190,18 @@ $(document).ready(function () {
{% endif %}
moment.locale('{{ request.LANGUAGE_CODE }}');
+
+ // Account notifications
+ {% if messages %}
+ {% for message in messages %}
+ showMessage(
+ '{{ message }}',
+ {
+ style: 'info',
+ }
+ );
+ {% endfor %}
+ {% endif %}
});
diff --git a/InvenTree/templates/js/dynamic/settings.js b/InvenTree/templates/js/dynamic/settings.js
index cb21e1fefc..8201dc8374 100644
--- a/InvenTree/templates/js/dynamic/settings.js
+++ b/InvenTree/templates/js/dynamic/settings.js
@@ -1,6 +1,7 @@
{% load inventree_extras %}
/* exported
+ editSetting,
user_settings,
global_settings,
*/
@@ -18,3 +19,83 @@ const global_settings = {
{{ key }}: {% primitive_to_javascript value %},
{% endfor %}
};
+
+/*
+ * Edit a setting value
+ */
+function editSetting(pk, options={}) {
+
+ // Is this a global setting or a user setting?
+ var global = options.global || false;
+
+ var url = '';
+
+ if (global) {
+ url = `/api/settings/global/${pk}/`;
+ } else {
+ url = `/api/settings/user/${pk}/`;
+ }
+
+ // First, read the settings object from the server
+ inventreeGet(url, {}, {
+ success: function(response) {
+
+ if (response.choices && response.choices.length > 0) {
+ response.type = 'choice';
+ }
+
+ // Construct the field
+ var fields = {
+ value: {
+ label: response.name,
+ help_text: response.description,
+ type: response.type,
+ choices: response.choices,
+ }
+ };
+
+ constructChangeForm(fields, {
+ url: url,
+ method: 'PATCH',
+ title: options.title,
+ processResults: function(data, fields, opts) {
+
+ switch (data.type) {
+ case 'boolean':
+ // Convert to boolean value
+ data.value = data.value.toString().toLowerCase() == 'true';
+ break;
+ case 'integer':
+ // Convert to integer value
+ data.value = parseInt(data.value.toString());
+ break;
+ default:
+ break;
+ }
+
+ return data;
+ },
+ processBeforeUpload: function(data) {
+ // Convert value to string
+ data.value = data.value.toString();
+
+ return data;
+ },
+ onSuccess: function(response) {
+
+ var setting = response.key;
+
+ if (response.type == 'boolean') {
+ var enabled = response.value.toString().toLowerCase() == 'true';
+ $(`#setting-value-${setting}`).prop('checked', enabled);
+ } else {
+ $(`#setting-value-${setting}`).html(response.value);
+ }
+ }
+ });
+ },
+ error: function(xhr) {
+ showApiError(xhr, url);
+ }
+ });
+}
diff --git a/InvenTree/templates/js/translated/api.js b/InvenTree/templates/js/translated/api.js
index d0640408be..15a74a9a71 100644
--- a/InvenTree/templates/js/translated/api.js
+++ b/InvenTree/templates/js/translated/api.js
@@ -61,7 +61,11 @@ function inventreeGet(url, filters={}, options={}) {
},
error: function(xhr, ajaxOptions, thrownError) {
console.error('Error on GET at ' + url);
- console.error(thrownError);
+
+ if (thrownError) {
+ console.error('Error: ' + thrownError);
+ }
+
if (options.error) {
options.error({
error: thrownError
@@ -174,7 +178,7 @@ function showApiError(xhr, url) {
var title = null;
var message = null;
- switch (xhr.status) {
+ switch (xhr.status || 0) {
// No response
case 0:
title = '{% trans "No Response" %}';
diff --git a/InvenTree/templates/js/translated/barcode.js b/InvenTree/templates/js/translated/barcode.js
index 2778983341..6be56d14f1 100644
--- a/InvenTree/templates/js/translated/barcode.js
+++ b/InvenTree/templates/js/translated/barcode.js
@@ -257,7 +257,7 @@ function barcodeDialog(title, options={}) {
$(modal).modal({
backdrop: 'static',
- keyboard: false,
+ keyboard: user_settings.FORMS_CLOSE_USING_ESCAPE,
});
if (options.preShow) {
diff --git a/InvenTree/templates/js/translated/build.js b/InvenTree/templates/js/translated/build.js
index 499fde9bec..bcbbfcc6d1 100644
--- a/InvenTree/templates/js/translated/build.js
+++ b/InvenTree/templates/js/translated/build.js
@@ -43,11 +43,18 @@ function buildFormFields() {
}
},
sales_order: {
+ icon: 'fa-truck',
},
batch: {},
- target_date: {},
- take_from: {},
- destination: {},
+ target_date: {
+ icon: 'fa-calendar-alt',
+ },
+ take_from: {
+ icon: 'fa-sitemap',
+ },
+ destination: {
+ icon: 'fa-sitemap',
+ },
link: {
icon: 'fa-link',
},
diff --git a/InvenTree/templates/js/translated/forms.js b/InvenTree/templates/js/translated/forms.js
index a86b64d0e2..2f25fef259 100644
--- a/InvenTree/templates/js/translated/forms.js
+++ b/InvenTree/templates/js/translated/forms.js
@@ -19,7 +19,6 @@
renderStockLocation,
renderSupplierPart,
renderUser,
- showAlertDialog,
showAlertOrCache,
showApiError,
*/
@@ -199,14 +198,6 @@ function constructChangeForm(fields, options) {
json: 'application/json',
},
success: function(data) {
-
- // Push existing 'value' to each field
- for (const field in data) {
-
- if (field in fields) {
- fields[field].value = data[field];
- }
- }
// An optional function can be provided to process the returned results,
// before they are rendered to the form
@@ -219,6 +210,14 @@ function constructChangeForm(fields, options) {
}
}
+ // Push existing 'value' to each field
+ for (const field in data) {
+
+ if (field in fields) {
+ fields[field].value = data[field];
+ }
+ }
+
// Store the entire data object
options.instance = data;
@@ -347,10 +346,12 @@ function constructForm(url, options) {
constructCreateForm(OPTIONS.actions.POST, options);
} else {
// User does not have permission to POST to the endpoint
- showAlertDialog(
- '{% trans "Action Prohibited" %}',
- '{% trans "Create operation not allowed" %}'
- );
+ showMessage('{% trans "Action Prohibited" %}', {
+ style: 'danger',
+ details: '{% trans "Create operation not allowed" %}',
+ icon: 'fas fa-user-times',
+ });
+
console.log(`'POST action unavailable at ${url}`);
}
break;
@@ -360,10 +361,12 @@ function constructForm(url, options) {
constructChangeForm(OPTIONS.actions.PUT, options);
} else {
// User does not have permission to PUT/PATCH to the endpoint
- showAlertDialog(
- '{% trans "Action Prohibited" %}',
- '{% trans "Update operation not allowed" %}'
- );
+ showMessage('{% trans "Action Prohibited" %}', {
+ style: 'danger',
+ details: '{% trans "Update operation not allowed" %}',
+ icon: 'fas fa-user-times',
+ });
+
console.log(`${options.method} action unavailable at ${url}`);
}
break;
@@ -372,10 +375,12 @@ function constructForm(url, options) {
constructDeleteForm(OPTIONS.actions.DELETE, options);
} else {
// User does not have permission to DELETE to the endpoint
- showAlertDialog(
- '{% trans "Action Prohibited" %}',
- '{% trans "Delete operation not allowed" %}'
- );
+ showMessage('{% trans "Action Prohibited" %}', {
+ style: 'danger',
+ details: '{% trans "Delete operation not allowed" %}',
+ icon: 'fas fa-user-times',
+ });
+
console.log(`DELETE action unavailable at ${url}`);
}
break;
@@ -384,10 +389,12 @@ function constructForm(url, options) {
// TODO?
} else {
// User does not have permission to GET to the endpoint
- showAlertDialog(
- '{% trans "Action Prohibited" %}',
- '{% trans "View operation not allowed" %}'
- );
+ showMessage('{% trans "Action Prohibited" %}', {
+ style: 'danger',
+ details: '{% trans "View operation not allowed" %}',
+ icon: 'fas fa-user-times',
+ });
+
console.log(`GET action unavailable at ${url}`);
}
break;
@@ -717,6 +724,11 @@ function submitFormData(fields, options) {
data = form_data;
}
+ // Optionally pre-process the data before uploading to the server
+ if (options.processBeforeUpload) {
+ data = options.processBeforeUpload(data);
+ }
+
// Submit data
upload_func(
options.url,
diff --git a/InvenTree/templates/js/translated/part.js b/InvenTree/templates/js/translated/part.js
index 742083bbe4..dc1adf8837 100644
--- a/InvenTree/templates/js/translated/part.js
+++ b/InvenTree/templates/js/translated/part.js
@@ -992,7 +992,7 @@ function loadPartTable(table, url, options={}) {
}
});
- var grid_view = inventreeLoad('part-grid-view') == 1;
+ var grid_view = options.gridView && inventreeLoad('part-grid-view') == 1;
$(table).inventreeTable({
url: url,
@@ -1020,7 +1020,7 @@ function loadPartTable(table, url, options={}) {
$('#view-part-list').removeClass('btn-outline-secondary').addClass('btn-secondary');
}
},
- buttons: [
+ buttons: options.gridView ? [
{
icon: 'fas fa-bars',
attributes: {
@@ -1053,7 +1053,7 @@ function loadPartTable(table, url, options={}) {
);
}
}
- ],
+ ] : [],
customView: function(data) {
var html = '';
diff --git a/InvenTree/templates/navbar.html b/InvenTree/templates/navbar.html
index c63031e3cb..cd2a2a0a56 100644
--- a/InvenTree/templates/navbar.html
+++ b/InvenTree/templates/navbar.html
@@ -12,9 +12,6 @@
-
{% if roles.part.view %}
@@ -84,19 +81,24 @@
{% include "search_form.html" %}
-
+
{% if barcodes %}
- -
+
-
{% endif %}
+ -
+
+
-
-
-
diff --git a/InvenTree/templates/qr_code.html b/InvenTree/templates/qr_code.html
index 8964ef02be..a39847629d 100644
--- a/InvenTree/templates/qr_code.html
+++ b/InvenTree/templates/qr_code.html
@@ -3,7 +3,7 @@