2
0
mirror of https://github.com/inventree/InvenTree.git synced 2025-06-18 04:55:44 +00:00

fix trailing

This commit is contained in:
Matthias Mair
2022-05-20 13:20:55 +02:00
parent bd195105e7
commit 93b6934127
99 changed files with 2341 additions and 2347 deletions

View File

@ -14,7 +14,7 @@
{% block body_class %}login-screen{% endblock %}
{% block body %}
<!--
<!--
Background Image Attribution: https://unsplash.com/photos/Ixvv3YZkd7w
-->
<div class='container-fluid'>

View File

@ -224,7 +224,7 @@
{% endif %}
{% endif %}
{% endif %}
enableSidebar(
'search',

View File

@ -46,7 +46,7 @@
<div class='btn-group' role='group'>
<button class='btn btn-success' id='import-part'>
<span class='fas fa-plus-circle'></span> {% trans "Import Part" %}
</button>
</button>
</div>
</div>
</div>

View File

@ -36,7 +36,7 @@
<div class='btn-group' role='group'>
{% url 'admin:plugin_pluginconfig_changelist' as url %}
{% include "admin_button.html" with url=url %}
<button class="btn btn-success" id="install-plugin" title="{% trans 'Install Plugin' %}"><span class='fas fa-plus-circle'></span> {% trans "Install Plugin" %}</button>
<button class="btn btn-success" id="install-plugin" title="{% trans 'Install Plugin' %}"><span class='fas fa-plus-circle'></span> {% trans "Install Plugin" %}</button>
</div>
</div>
</div>
@ -52,7 +52,7 @@
<th>{% trans "Version" %}</th>
</tr>
</thead>
<tbody>
{% plugin_list as pl_list %}
{% for plugin_key, plugin in pl_list.items %}
@ -133,7 +133,7 @@
<th>{% trans "Message" %}</th>
</tr>
</thead>
<tbody>
{% for stage, errors in pl_errors.items %}
{% for error_detail in errors %}

View File

@ -70,7 +70,7 @@
<div class='alert alert-block alert-info'>
{% trans 'The code information is pulled from the latest git commit for this plugin. It might not reflect official version numbers or information but the actual code running.' %}
</div>
{% endif %}
</div>
<div class="col">

View File

@ -99,7 +99,7 @@ $('table').find('.boolean-setting').change(function() {
}
}
);
});
// Callback for when non-boolean settings are edited

View File

@ -76,7 +76,7 @@
{% if lang_translated > 10 or lang_code == 'en' or lang_code == LANGUAGE_CODE %}{% define True as use_lang %}{% else %}{% define False as use_lang %}{% endif %}
{% if ALL_LANG or use_lang %}
<option value="{{ lang_code }}"{% if lang_code == LANGUAGE_CODE %} selected{% endif %}>
{{ language.name_local }} ({{ lang_code }})
{{ language.name_local }} ({{ lang_code }})
{% if lang_translated %}
{% blocktrans %}{{ lang_translated }}% translated{% endblocktrans %}
{% else %}
@ -105,4 +105,4 @@
</div>
</div>
{% endblock %}
{% endblock %}

View File

@ -25,11 +25,11 @@
{% include "InvenTree/settings/setting.html" with key="SEARCH_PREVIEW_EXCLUDE_INACTIVE_PURCHASE_ORDERS" user_setting=True icon='fa-eye-slash' %}
{% include "InvenTree/settings/setting.html" with key="SEARCH_PREVIEW_SHOW_SALES_ORDERS" user_setting=True icon='fa-truck' %}
{% include "InvenTree/settings/setting.html" with key="SEARCH_PREVIEW_EXCLUDE_INACTIVE_SALES_ORDERS" user_setting=True icon='fa-eye-slash' %}
{% include "InvenTree/settings/setting.html" with key="SEARCH_PREVIEW_RESULTS" user_setting=True icon='fa-search' %}
</tbody>
</table>
</div>
{% endblock %}
{% endblock %}

View File

@ -50,7 +50,7 @@
</head>
<body class='login-screen'>
<!--
<!--
Background Image Attribution: https://unsplash.com/photos/Ixvv3YZkd7w
-->
<div class='container-fluid'>
@ -130,4 +130,4 @@ $(document).ready(function () {
</script>
</body>
</html>
</html>

View File

@ -65,7 +65,7 @@
<title>
{% block page_title %}
{% inventree_title %}
{% inventree_title %}
{% endblock %}
</title>
</head>
@ -91,7 +91,7 @@
</div>
</div>
<main class='col ps-md-2 pt-2 pe-2'>
{% block alerts %}
<div class='notification-area' id='alerts'>
<!-- Div for displayed alerts -->
@ -164,7 +164,7 @@
<script type='text/javascript' src="{% static 'script/moment.js' %}"></script>
<script type='text/javascript' src="{% static 'script/chartjs-adapter-moment.js' %}"></script>
<script type='text/javascript' src="{% static 'easymde/easymde.min.js' %}"></script>
<script type='text/javascript' src="{% static 'script/clipboard.min.js' %}"></script>
<script type='text/javascript' src="{% static 'script/randomColor.min.js' %}"></script>
<script type='text/javascript' src="{% static 'script/qr-scanner.umd.min.js' %}"></script>
@ -246,4 +246,4 @@ $(document).ready(function () {
{% endblock %}
</body>
</html>
</html>

View File

@ -68,7 +68,7 @@ function activatePanel(label, panel_name, options={}) {
function onPanelLoad(panel, callback) {
// One-time callback when a panel is first displayed
// Used to implement lazy-loading, rather than firing
// Used to implement lazy-loading, rather than firing
// multiple AJAX queries when the page is first loaded.
var panelId = `#panel-${panel}`;
@ -130,12 +130,12 @@ function enableSidebar(label, options={}) {
// By default, the menu is "expanded"
var state = localStorage.getItem(`inventree-menu-state-${label}`) || 'expanded';
// We wish to "toggle" the state!
setSidebarState(label, state == 'expanded' ? 'collapsed' : 'expanded');
});
}
// Set the initial state (default = expanded)
var state = localStorage.getItem(`inventree-menu-state-${label}`) || 'expanded';
@ -204,7 +204,7 @@ function enableBreadcrumbTree(options) {
node = nodes[node.parent];
}
}
} else {
roots.push(node);
}
@ -227,7 +227,7 @@ function enableBreadcrumbTree(options) {
// Toggle treeview visibilty
$('#breadcrumb-tree-collapse').toggle();
});
}

View File

@ -58,13 +58,13 @@ function editSetting(key, options={}) {
// First, read the settings object from the server
inventreeGet(url, {}, {
success: function(response) {
if (response.choices && response.choices.length > 0) {
response.type = 'choice';
reload_required = true;
}
// Construct the field
// Construct the field
var fields = {
value: {
label: response.name,
@ -77,7 +77,7 @@ function editSetting(key, options={}) {
// Foreign key lookup available!
if (response.type == 'related field') {
if (response.model_name && response.api_url) {
fields.value.type = 'related field';
fields.value.model = response.model_name.split('.').at(-1);

View File

@ -14,11 +14,11 @@
$.urlParam = function(name) {
// eslint-disable-next-line no-useless-escape
var results = new RegExp('[\?&]' + name + '=([^&#]*)').exec(window.location.href);
if (results == null) {
return null;
}
return decodeURI(results[1]) || 0;
};
@ -80,9 +80,9 @@ function inventreeGet(url, filters={}, options={}) {
function inventreeFormDataUpload(url, data, options={}) {
/* Upload via AJAX using the FormData approach.
*
*
* Note that the following AJAX parameters are required for FormData upload
*
*
* processData: false
* contentType: false
*/

View File

@ -14,7 +14,7 @@
/*
* Add callbacks to buttons for creating new attachments.
*
*
* Note: Attachments can also be external links!
*/
function addAttachmentButtonCallbacks(url, fields={}) {
@ -46,7 +46,7 @@ function addAttachmentButtonCallbacks(url, fields={}) {
};
Object.assign(link_fields, fields);
constructForm(url, {
fields: link_fields,
method: 'POST',
@ -88,7 +88,7 @@ function loadAttachmentTable(url, options) {
constructForm(`${url}${pk}/`, {
fields: {
link: {},
comment: {},
comment: {},
},
processResults: function(data, fields, opts) {
// Remove the "link" field if the attachment is a file!
@ -100,7 +100,7 @@ function loadAttachmentTable(url, options) {
title: '{% trans "Edit Attachment" %}',
});
});
// Add callback for 'delete' button
$(table).find('.button-attachment-delete').click(function() {
var pk = $(this).attr('pk');

View File

@ -324,7 +324,7 @@ function barcodeDialog(title, options={}) {
function barcodeScanDialog() {
/*
* Perform a barcode scan,
* and (potentially) redirect the browser
* and (potentially) redirect the browser
*/
var modal = '#modal-form';
@ -345,9 +345,9 @@ function barcodeScanDialog() {
'warning'
);
}
}
}
},
);
);
}
@ -647,7 +647,7 @@ function scanItemsIntoLocation(item_list, options={}) {
item_list.forEach(function(item) {
items.push({
pk: item.pk || item.id,
quantity: item.quantity,
quantity: item.quantity,
});
});

View File

@ -95,7 +95,7 @@ function constructBomUploadTable(data, options={}) {
// Handle any errors raised by initial data import
if (row.data.errors.part) {
addFieldErrorMessage(`items_sub_part_${idx}`, row.data.errors.part);
addFieldErrorMessage(`items_sub_part_${idx}`, row.data.errors.part);
}
if (row.data.errors.quantity) {
@ -156,7 +156,7 @@ function constructBomUploadTable(data, options={}) {
// Request API endpoint options
getApiEndpointOptions('{% url "api-bom-list" %}', function(response) {
var fields = response.actions.POST;
data.rows.forEach(function(row, idx) {
@ -543,7 +543,7 @@ function bomSubstitutesDialog(bom_item_id, substitutes, options={}) {
${part_thumb} ${part_name} - <em>${part_desc}</em>
</div>
`;
// Add a table of individual rows
html += `
<table class='table table-striped table-condensed' id='substitute-table'>
@ -643,7 +643,7 @@ function bomSubstitutesDialog(bom_item_id, substitutes, options={}) {
// Re-enable the "submit" button
$(opts.modal).find('#modal-form-submit').prop('disabled', false);
// Reload the parent BOM table
reloadParentTable();
}
@ -659,7 +659,7 @@ function deleteBomItems(items, options={}) {
var sub_part = item.sub_part_detail;
var thumb = thumbnailImage(sub_part.thumbnail || sub_part.image);
var html = `
<tr>
<td>${thumb} ${sub_part.full_name}</td>
@ -709,7 +709,7 @@ function deleteBomItems(items, options={}) {
function deleteNextBomItem() {
if (items.length > 0) {
var item = items.shift();
inventreeDelete(`/api/bom/${item.pk}/`,
@ -735,13 +735,13 @@ function deleteBomItems(items, options={}) {
function loadBomTable(table, options={}) {
/* Load a BOM table with some configurable options.
*
*
* Following options are available:
* editable - Should the BOM table be editable?
* bom_url - Address to request BOM data from
* part_url - Address to request Part data from
* parent_id - Parent ID of the owning part
*
*
* BOM data are retrieved from the server via AJAX query
*/
@ -831,10 +831,10 @@ function loadBomTable(table, options={}) {
var html = '';
var sub_part = row.sub_part_detail;
// Display an extra icon if this part is an assembly
if (sub_part.assembly) {
if (row.sub_assembly_received) {
// Data received, ignore
} else if (row.sub_assembly_requested) {
@ -895,7 +895,7 @@ function loadBomTable(table, options={}) {
text = parseFloat(text);
if (row.optional) {
text += ' ({% trans "Optional" %})';
text += ' ({% trans "Optional" %})';
}
if (row.overage) {
@ -920,7 +920,7 @@ function loadBomTable(table, options={}) {
var variant_stock = row.allow_variants ? (row.available_variant_stock || 0) : 0;
var available_stock = availableQuantity(row);
var text = `${available_stock}`;
if (available_stock <= 0) {
@ -957,7 +957,7 @@ function loadBomTable(table, options={}) {
}
}
});
if (show_pricing) {
cols.push({
field: 'purchase_price_range',
@ -1139,7 +1139,7 @@ function loadBomTable(table, options={}) {
row.sub_assembly_received = true;
$(table).bootstrapTable('updateByUniqueId', bom_pk, row, true);
table.bootstrapTable('append', response);
},
error: function(xhr) {
@ -1302,10 +1302,10 @@ function loadBomTable(table, options={}) {
* Arguments:
* - table: The ID string of the table element e.g. '#used-in-table'
* - part_id: The ID (PK) of the part we are interested in
*
*
* Options:
* -
*
* -
*
* The following "options" are available.
*/
function loadUsedInTable(table, part_id, options={}) {
@ -1343,14 +1343,14 @@ function loadUsedInTable(table, part_id, options={}) {
// Iterate through each variant item
for (var jj = 0; jj < variantData.length; jj++) {
variantData[jj].parent = row.pk;
var variant = variantData[jj];
// Add this variant to the table, augmented
$(table).bootstrapTable('append', [{
// Point the parent to the "master" assembly row
// Point the parent to the "master" assembly row
parent: row.pk,
part: variant.pk,
part: variant.pk,
part_detail: variant,
sub_part: row.sub_part,
sub_part_detail: row.sub_part_detail,

View File

@ -126,7 +126,7 @@ function newBuildOrder(options={}) {
/* Construct a form to cancel a build order */
function cancelBuildOrder(build_id, options={}) {
constructForm(
`/api/build/${build_id}/cancel/`,
{
@ -304,7 +304,7 @@ function createBuildOutput(build_id, options) {
* Construct a set of output buttons for a particular build output
*/
function makeBuildOutputButtons(output_id, build_info, options={}) {
var html = `<div class='btn-group float-right' role='group'>`;
// Tracked parts? Must be individually allocated
@ -355,7 +355,7 @@ function makeBuildOutputButtons(output_id, build_info, options={}) {
/*
* Unallocate stock against a particular build order
*
*
* Options:
* - output: pk value for a stock item "build output"
* - bom_item: pk value for a particular BOMItem (build item)
@ -401,7 +401,7 @@ function unallocateStock(build_id, options={}) {
* Launch a modal form to complete selected build outputs
*/
function completeBuildOutputs(build_id, outputs, options={}) {
if (outputs.length == 0) {
showAlertDialog(
'{% trans "Select Build Outputs" %}',
@ -487,7 +487,7 @@ function completeBuildOutputs(build_id, outputs, options={}) {
});
},
onSubmit: function(fields, opts) {
// Extract data elements from the form
var data = {
outputs: [],
@ -631,7 +631,7 @@ function deleteBuildOutputs(build_id, outputs, options={}) {
var pk = $(this).attr('pk');
$(opts.modal).find(`#output_row_${pk}`).remove();
});
});
},
onSubmit: function(fields, opts) {
var data = {
@ -753,7 +753,7 @@ function loadBuildOrderAllocationTable(table, options={}) {
if (!value) {
return '{% trans "Location not specified" %}';
}
var link = `/stock/location/${value}`;
var text = row.location_detail.description;
@ -803,7 +803,7 @@ function sumAllocationsForBomRow(bom_row, allocations) {
* Display a "build output" table for a particular build.
*
* This displays a list of "active" (i.e. "in production") build outputs for a given build
*
*
*/
function loadBuildOutputTable(build_info, options={}) {
@ -825,7 +825,7 @@ function loadBuildOutputTable(build_info, options={}) {
setupFilterList('builditems', $(table), options.filterTarget || '#filter-list-incompletebuilditems');
function setupBuildOutputButtonCallbacks() {
// Callback for the "allocate" button
$(table).find('.button-output-allocate').click(function() {
var pk = $(this).attr('pk');
@ -997,7 +997,7 @@ function loadBuildOutputTable(build_info, options={}) {
// Check how many BOM lines have been completely allocated for this build output
bom_items.forEach(function(bom_item) {
var required_quantity = bom_item.quantity * row.quantity;
if (sumAllocationsForBomRow(bom_item, row.allocations) >= required_quantity) {
@ -1281,7 +1281,7 @@ function loadBuildOutputTable(build_info, options={}) {
$(table).on('expand-row.bs.table', function(detail, index, row) {
$(`#button-output-allocate-${row.pk}`).prop('disabled', false);
});
// Disable the "allocate" button when the sub-table is collapsed
$(table).on('collapse-row.bs.table', function(detail, index, row) {
$(`#button-output-allocate-${row.pk}`).prop('disabled', true);
@ -1364,9 +1364,9 @@ function loadBuildOutputTable(build_info, options={}) {
/*
* Display the "allocation table" for a particular build output.
*
*
* This displays a table of required allocations for a particular build output
*
*
* Args:
* - buildId: The PK of the Build object
* - partId: The PK of the Part object
@ -1375,7 +1375,7 @@ function loadBuildOutputTable(build_info, options={}) {
* -- table: The #id of the table (will be auto-calculated if not provided)
*/
function loadBuildOutputAllocationTable(buildInfo, output, options={}) {
var buildId = buildInfo.pk;
var partId = buildInfo.part;
@ -1628,7 +1628,7 @@ function loadBuildOutputAllocationTable(buildInfo, output, options={}) {
$(table).inventreeTable({
data: bom_items,
disablePagination: true,
formatNoMatches: function() {
formatNoMatches: function() {
return '{% trans "No BOM items found" %}';
},
name: 'build-allocation',
@ -1715,7 +1715,7 @@ function loadBuildOutputAllocationTable(buildInfo, output, options={}) {
field: 'actions',
formatter: function(value, row) {
/* Actions available for a particular stock item allocation:
*
*
* - Edit the allocation quantity
* - Delete the allocation
*/
@ -1812,15 +1812,15 @@ function loadBuildOutputAllocationTable(buildInfo, output, options={}) {
var variant_stock = row.allow_variants ? (row.available_variant_stock || 0) : 0;
var available_stock = availableQuantity(row);
var required = requiredQuantity(row);
var text = '';
if (available_stock > 0) {
text += `${available_stock}`;
}
if (available_stock < required) {
text += `<span class='fas fa-times-circle icon-red float-right' title='{% trans "Insufficient stock available" %}'></span>`;
} else {
@ -1838,12 +1838,12 @@ function loadBuildOutputAllocationTable(buildInfo, output, options={}) {
} else if (substitute_stock > 0) {
extra = '{% trans "Includes substitute stock" %}';
}
if (extra) {
text += `<span title='${extra}' class='fas fa-info-circle float-right icon-blue'></span>`;
}
}
return renderLink(text, url);
},
sorter: function(valA, valB, rowA, rowB) {
@ -1862,7 +1862,7 @@ function loadBuildOutputAllocationTable(buildInfo, output, options={}) {
},
sorter: function(valA, valB, rowA, rowB) {
// Custom sorting function for progress bars
var aA = allocatedQuantity(rowA);
var aB = allocatedQuantity(rowB);
@ -1932,12 +1932,12 @@ function loadBuildOutputAllocationTable(buildInfo, output, options={}) {
/**
* Allocate stock items to a build
*
*
* arguments:
* - buildId: ID / PK value for the build
* - partId: ID / PK value for the part being built
* - bom_items: A list of BomItem objects to be allocated
*
*
* options:
* - output: ID / PK of the associated build output (or null for untracked items)
* - source_location: ID / PK of the top-level StockLocation to source stock from (or null)
@ -2109,7 +2109,7 @@ function allocateStockToBuild(build_id, part_id, bom_items, options={}) {
</tbody>
</table>
`;
constructForm(`/api/build/${build_id}/allocate/`, {
method: 'POST',
fields: {},
@ -2193,7 +2193,7 @@ function allocateStockToBuild(build_id, part_id, bom_items, options={}) {
filters.location = location;
filters.cascade = true;
return filters;
},
noResults: function(query) {
@ -2371,7 +2371,7 @@ function loadBuildTable(table, options) {
columns: [
{
field: 'pk',
title: 'ID',
title: 'ID',
visible: false,
switchable: false,
},

View File

@ -10,7 +10,7 @@
setupFilterList,
showQuestionDialog,
*/
/* exported
createCompany,
createManufacturerPart,
@ -26,7 +26,7 @@
/**
* Construct a set of form fields for creating / editing a ManufacturerPart
* @returns
* @returns
*/
function manufacturerPartFields() {
@ -46,7 +46,7 @@ function manufacturerPartFields() {
/**
* Launches a form to create a new ManufacturerPart
* @param {object} options
* @param {object} options
*/
function createManufacturerPart(options={}) {
@ -67,7 +67,7 @@ function createManufacturerPart(options={}) {
var company_fields = companyFormFields();
company_fields.is_manufacturer.value = true;
return company_fields;
}
};
@ -84,7 +84,7 @@ function createManufacturerPart(options={}) {
/**
* Launches a form to edit a ManufacturerPart
* @param {integer} part - ID of a ManufacturerPart
* @param {object} options
* @param {object} options
*/
function editManufacturerPart(part, options={}) {
@ -414,7 +414,7 @@ function deleteManufacturerParts(selections, options={}) {
<p>${item.MPN} - ${item.part_detail.full_name}</p>
</li>`;
});
text += `
</ul>
</div>`;
@ -577,7 +577,7 @@ function loadManufacturerPartTable(table, url, options) {
var pk = $(this).attr('pk');
editManufacturerPart(
pk,
pk,
{
onSuccess: function() {
$(table).bootstrapTable('refresh');
@ -590,7 +590,7 @@ function loadManufacturerPartTable(table, url, options) {
var pk = $(this).attr('pk');
deleteManufacturerPart(
pk,
pk,
{
onSuccess: function() {
$(table).bootstrapTable('refresh');
@ -775,7 +775,7 @@ function loadSupplierPartTable(table, url, options) {
formatter: function(value, row) {
if (value) {
var name = row.supplier_detail.name;
var url = `/company/${value}/`;
var url = `/company/${value}/`;
var html = imageHoverIcon(row.supplier_detail.image) + renderLink(name, url);
return html;
@ -875,7 +875,7 @@ function loadSupplierPartTable(table, url, options) {
var pk = $(this).attr('pk');
editSupplierPart(
pk,
pk,
{
onSuccess: function() {
$(table).bootstrapTable('refresh');
@ -888,7 +888,7 @@ function loadSupplierPartTable(table, url, options) {
var pk = $(this).attr('pk');
deleteSupplierPart(
pk,
pk,
{
onSuccess: function() {
$(table).bootstrapTable('refresh');

View File

@ -6,22 +6,22 @@
inventreeSave,
reloadTableFilters,
*/
/* exported
setupFilterList,
*/
/**
* Code for managing query filters / table options.
*
*
* Optional query filters are available to the user for various
* tables display in the web interface.
* These filters are saved to the web session, and should be
* These filters are saved to the web session, and should be
* persistent for a given table type.
*
*
* This makes use of the 'inventreeSave' and 'inventreeLoad' functions
* for writing to and reading from session storage.
*
*
*/
@ -39,7 +39,7 @@ function defaultFilters() {
/**
* Load table filters for the given table from session storage
*
*
* @param tableKey - String key for the particular table
* @param defaults - Default filters for this table e.g. 'cascade=1&location=5'
*/
@ -73,7 +73,7 @@ function loadTableFilters(tableKey) {
/**
* Save table filters to session storage
*
*
* @param {*} tableKey - string key for the given table
* @param {*} filters - object of string:string pairs
*/
@ -251,7 +251,7 @@ function generateFilterInput(tableKey, filterKey) {
/**
* Configure a filter list for a given table
*
*
* @param {*} tableKey - string lookup key for filter settings
* @param {*} table - bootstrapTable element to update
* @param {*} target - name of target element on page
@ -410,7 +410,7 @@ function setupFilterList(tableKey, table, target, options={}) {
/**
* Return the pretty title for the given table and filter selection.
* If no title is provided, default to the key value.
*
*
*/
function getFilterTitle(tableKey, filterKey) {
var settings = getFilterSettings(tableKey, filterKey);
@ -460,4 +460,3 @@ function getFilterOptionValue(tableKey, filterKey, valueKey) {
// Cannot map to a display string - return the original text
return value;
}

View File

@ -62,7 +62,7 @@ $.fn.select2.defaults.set('theme', 'bootstrap-5');
* can perform a GET method at the endpoint.
*/
function canView(OPTIONS) {
if ('actions' in OPTIONS) {
return ('GET' in OPTIONS.actions);
} else {
@ -90,7 +90,7 @@ function canCreate(OPTIONS) {
* can perform a PUT or PATCH method at the endpoint
*/
function canChange(OPTIONS) {
if ('actions' in OPTIONS) {
return ('PUT' in OPTIONS.actions || 'PATCH' in OPTIONS.actions);
} else {
@ -147,25 +147,25 @@ function getApiEndpointOptions(url, callback) {
/*
* Construct a 'creation' (POST) form, to create a new model in the database.
*
*
* arguments:
* - fields: The 'actions' object provided by the OPTIONS endpoint
*
*
* options:
* -
* -
*/
function constructCreateForm(fields, options) {
// Check if default values were provided for any fields
for (const name in fields) {
var field = fields[name];
var field_options = options.fields[name] || {};
// If a 'value' is not provided for the field,
if (field.value == null) {
if ('value' in field_options) {
// Client has specified the default value for the field
field.value = field_options.value;
@ -183,12 +183,12 @@ function constructCreateForm(fields, options) {
/*
* Construct a 'change' (PATCH) form, to create a new model in the database.
*
*
* arguments:
* - fields: The 'actions' object provided by the OPTIONS endpoint
*
*
* options:
* -
* -
*/
function constructChangeForm(fields, options) {
@ -203,12 +203,12 @@ function constructChangeForm(fields, options) {
json: 'application/json',
},
success: function(data) {
// An optional function can be provided to process the returned results,
// before they are rendered to the form
if (options.processResults) {
var processed = options.processResults(data, fields, options);
// If the processResults function returns data, it will be stored
if (processed) {
data = processed;
@ -225,7 +225,7 @@ function constructChangeForm(fields, options) {
// Store the entire data object
options.instance = data;
constructFormBody(fields, options);
},
error: function(xhr) {
@ -240,7 +240,7 @@ function constructChangeForm(fields, options) {
/*
* Construct a 'delete' form, to remove a model instance from the database.
*
*
* arguments:
* - fields: The 'actions' object provided by the OPTIONS request
* - options: The 'options' object provided by the client
@ -282,7 +282,7 @@ function constructDeleteForm(fields, options) {
/*
* Request API OPTIONS data from the server,
* and construct a modal form based on the response.
*
*
* url: API URL which defines form data
* options:
* - method: The HTTP method e.g. 'PUT', 'POST', 'DELETE' (default='PATCH')
@ -310,7 +310,7 @@ function constructDeleteForm(fields, options) {
* - reload: Set to true to reload the current page after form success
* - confirm: Set to true to require a "confirm" button
* - confirmText: Text for confirm button (default = "Confirm")
*
*
*/
function constructForm(url, options) {
@ -321,7 +321,7 @@ function constructForm(url, options) {
options.fields = options.fields || {};
// Save the URL
// Save the URL
options.url = url;
// Default HTTP method
@ -345,7 +345,7 @@ function constructForm(url, options) {
/*
* Determine what "type" of form we want to construct,
* based on the requested action.
*
*
* First we must determine if the user has the correct permissions!
*/
@ -360,7 +360,7 @@ function constructForm(url, options) {
details: '{% trans "Create operation not allowed" %}',
icon: 'fas fa-user-times',
});
console.warn(`'POST action unavailable at ${url}`);
}
break;
@ -375,7 +375,7 @@ function constructForm(url, options) {
details: '{% trans "Update operation not allowed" %}',
icon: 'fas fa-user-times',
});
console.warn(`${options.method} action unavailable at ${url}`);
}
break;
@ -389,7 +389,7 @@ function constructForm(url, options) {
details: '{% trans "Delete operation not allowed" %}',
icon: 'fas fa-user-times',
});
console.warn(`DELETE action unavailable at ${url}`);
}
break;
@ -403,7 +403,7 @@ function constructForm(url, options) {
details: '{% trans "View operation not allowed" %}',
icon: 'fas fa-user-times',
});
console.warn(`GET action unavailable at ${url}`);
}
break;
@ -417,7 +417,7 @@ function constructForm(url, options) {
/*
* Construct a modal form based on the provided options
*
*
* arguments:
* - fields: The endpoint description returned from the OPTIONS request
* - options: form options object provided by the client.
@ -450,7 +450,7 @@ function constructFormBody(fields, options) {
// Provide each field object with its own name
for (field in fields) {
fields[field].name = field;
// If any "instance_filters" are defined for the endpoint, copy them across (overwrite)
if (fields[field].instance_filters) {
fields[field].filters = Object.assign(fields[field].filters || {}, fields[field].instance_filters);
@ -512,7 +512,7 @@ function constructFormBody(fields, options) {
default:
break;
}
html += constructField(field_name, field, options);
}
@ -529,7 +529,7 @@ function constructFormBody(fields, options) {
var modal = options.modal;
modalEnable(modal, true);
// Insert generated form content
$(modal).find('#form-content').html(html);
@ -547,7 +547,7 @@ function constructFormBody(fields, options) {
if (options.postFormContent) {
$(modal).find('#post-form-content').html(options.postFormContent);
}
// Clear any existing buttons from the modal
$(modal).find('#modal-footer-buttons').html('');
@ -659,7 +659,7 @@ function extractFormData(fields, options) {
var data = {};
for (var idx = 0; idx < options.field_names.length; idx++) {
var name = options.field_names[idx];
var field = fields[name] || null;
@ -677,7 +677,7 @@ function extractFormData(fields, options) {
/*
* Submit form data to the server.
*
*
*/
function submitFormData(fields, options) {
@ -712,7 +712,7 @@ function submitFormData(fields, options) {
case 'decimal':
if (!validateFormField(name, options)) {
data_valid = false;
data_errors[name] = ['{% trans "Enter a valid number" %}'];
}
break;
@ -734,7 +734,7 @@ function submitFormData(fields, options) {
var file = field_files[0];
form_data.append(name, file);
has_files = true;
}
} else {
@ -780,7 +780,7 @@ function submitFormData(fields, options) {
handleFormSuccess(response, options);
},
error: function(xhr) {
$(options.modal).find('#modal-progress-spinner').hide();
switch (xhr.status) {
@ -808,7 +808,7 @@ function submitFormData(fields, options) {
*
*/
function updateFieldValues(fields, options) {
for (var idx = 0; idx < options.field_names.length; idx++) {
var name = options.field_names[idx];
@ -896,7 +896,7 @@ function getFormFieldElement(name, options) {
* An invalid number is expunged at the client side by the getFormFieldValue() function,
* which means that an empty string '' is sent to the server if the number is not valud.
* This can result in confusing error messages displayed under the form field.
*
*
* So, we can invalid numbers and display errors *before* the form is submitted!
*/
function validateFormField(name, options) {
@ -962,7 +962,7 @@ function getFormFieldValue(name, field={}, options={}) {
/*
* Handle successful form posting
*
*
* arguments:
* - response: The JSON response object from the server
* - options: The original options object provided by the client
@ -1004,7 +1004,7 @@ function handleFormSuccess(response, options) {
target: msg_target,
});
}
if (response && response.info) {
showAlertOrCache(response.info, cache, {style: 'info'});
}
@ -1020,7 +1020,7 @@ function handleFormSuccess(response, options) {
if (persist) {
// Instead of closing the form and going somewhere else,
// reload (empty) the form so the user can input more data
// Reset the status of the "submit" button
if (options.modal) {
$(options.modal).find('#modal-form-submit').prop('disabled', false);
@ -1065,7 +1065,7 @@ function clearFormErrors(options={}) {
if (options && options.modal) {
// Remove the individual error messages
$(options.modal).find('.form-error-message').remove();
$(options.modal).find('.modal-content').removeClass('modal-error');
// Remove the "has error" class
@ -1086,12 +1086,12 @@ function clearFormErrors(options={}) {
*
* We need to know the unique ID of each item in the array,
* and the array length must equal the length of the array returned from the server
*
*
* arguments:
* - response: The JSON error response from the server
* - parent: The name of the parent field e.g. "items"
* - options: The global options struct
*
*
* options:
* - nested: A map of nested ID values for the "parent" field
* e.g.
@ -1102,7 +1102,7 @@ function clearFormErrors(options={}) {
* 12
* ]
* }
*
*
*/
function handleNestedErrors(errors, field_name, options={}) {
@ -1115,7 +1115,7 @@ function handleNestedErrors(errors, field_name, options={}) {
}
var nest_list = nest_list = options['nested'][field_name];
// Nest list must be provided!
if (!nest_list) {
console.warn(`handleNestedErrors missing nesting options for field '${fieldName}'`);
@ -1123,9 +1123,9 @@ function handleNestedErrors(errors, field_name, options={}) {
}
for (var idx = 0; idx < error_list.length; idx++) {
var error_item = error_list[idx];
if (idx >= nest_list.length) {
console.warn(`handleNestedErrors returned greater number of errors (${error_list.length}) than could be handled (${nest_list.length})`);
break;
@ -1133,7 +1133,7 @@ function handleNestedErrors(errors, field_name, options={}) {
// Extract the particular ID of the nested item
var nest_id = nest_list[idx];
// Here, error_item is a map of field names to error messages
for (sub_field_name in error_item) {
@ -1158,7 +1158,7 @@ function handleNestedErrors(errors, field_name, options={}) {
row.after(html);
}
}
// Find the target (nested) field
@ -1178,7 +1178,7 @@ function handleNestedErrors(errors, field_name, options={}) {
/*
* Display form error messages as returned from the server.
*
*
* arguments:
* - errors: The JSON error response from the server
* - fields: The form data object
@ -1195,7 +1195,7 @@ function handleFormErrors(errors, fields={}, options={}) {
clearFormErrors(options);
var non_field_errors = null;
if (options.modal) {
non_field_errors = $(options.modal).find('#non-field-errors');
} else {
@ -1310,13 +1310,13 @@ function isFieldVisible(field, options) {
/*
* Attach callbacks to specified fields,
* triggered after the field value is edited.
*
*
* Callback function is called with arguments (name, field, options)
*/
function addFieldCallbacks(fields, options) {
for (var idx = 0; idx < options.field_names.length; idx++) {
var name = options.field_names[idx];
var field = fields[name];
@ -1581,7 +1581,7 @@ function addSecondaryModal(field, fields, options) {
/*
* Initialize a single related-field
*
*
* argument:
* - modal: DOM identifier for the modal window
* - name: name of the field e.g. 'location'
@ -1657,7 +1657,7 @@ function initializeRelatedField(field, fields, options={}) {
query.search = params.term;
query.offset = offset;
query.limit = pageSize;
// Allow custom run-time filter augmentation
if ('adjustFilters' in field) {
query = field.adjustFilters(query, options);
@ -1707,7 +1707,7 @@ function initializeRelatedField(field, fields, options={}) {
// Extract 'instance' data passed through from an initial value
// Or, use the raw 'item' data as a backup
var data = item;
if (item.element && item.element.instance) {
data = item.element.instance;
}
@ -1732,7 +1732,7 @@ function initializeRelatedField(field, fields, options={}) {
// Extract 'instance' data passed through from an initial value
// Or, use the raw 'item' data as a backup
var data = item;
if (item.element && item.element.instance) {
data = item.element.instance;
}
@ -1761,7 +1761,7 @@ function initializeRelatedField(field, fields, options={}) {
// If a 'value' is already defined, grab the model info from the server
if (field.value) {
var pk = field.value;
var url = `${field.api_url}/${pk}/`.replace('//', '/');
@ -1806,7 +1806,7 @@ function initializeRelatedField(field, fields, options={}) {
/*
* Set the value of a select2 instace for a "related field",
* e.g. with data returned from a secondary modal
*
*
* arguments:
* - name: The name of the field
* - data: JSON data representing the model instance
@ -1852,7 +1852,7 @@ function searching() {
/*
* Render a "foreign key" model reference in a select2 instance.
* Allows custom rendering with access to the entire serialized object.
*
*
* arguments:
* - name: The name of the field e.g. 'location'
* - model: The name of the InvenTree model e.g. 'stockitem'
@ -1872,7 +1872,7 @@ function renderModelData(name, model, data, parameters, options) {
var renderer = null;
// Find a custom renderer
// Find a custom renderer
switch (model) {
case 'company':
renderer = renderCompany;
@ -1919,7 +1919,7 @@ function renderModelData(name, model, data, parameters, options) {
default:
break;
}
if (renderer != null) {
html = renderer(name, data, parameters, options);
}
@ -1954,16 +1954,16 @@ function getFieldName(name, options={}) {
/*
* Construct a single form 'field' for rendering in a form.
*
*
* arguments:
* - name: The 'name' of the field
* - parameters: The field parameters supplied by the DRF OPTIONS method
*
*
* options:
* -
*
* -
*
* The function constructs a fieldset which mostly replicates django "crispy" forms:
*
*
* - Field name
* - Field <input> (depends on specified field type)
* - Field description (help text)
@ -2012,7 +2012,7 @@ function constructField(name, parameters, options={}) {
if (group_options.collapsible) {
html += `
<div data-bs-toggle='collapse' data-bs-target='#form-panel-content-${group_id}'>
<a href='#'><span id='group-icon-${group_id}' class='fas fa-angle-up'></span>
<a href='#'><span id='group-icon-${group_id}' class='fas fa-angle-up'></span>
`;
} else {
html += `<div>`;
@ -2044,7 +2044,7 @@ function constructField(name, parameters, options={}) {
if (parameters.before) {
html += parameters.before;
}
var hover_title = '';
if (parameters.help_text) {
@ -2062,7 +2062,7 @@ function constructField(name, parameters, options={}) {
// Does this input deserve "extra" decorators?
var extra = (parameters.icon != null) || (parameters.prefix != null) || (parameters.prefixRaw != null);
// Some fields can have 'clear' inputs associated with them
if (!parameters.required && !parameters.read_only) {
switch (parameters.type) {
@ -2080,10 +2080,10 @@ function constructField(name, parameters, options={}) {
break;
}
}
if (extra) {
html += `<div class='input-group'>`;
if (parameters.prefix) {
html += `<span class='input-group-text'>${parameters.prefix}</span>`;
} else if (parameters.prefixRaw) {
@ -2120,7 +2120,7 @@ function constructField(name, parameters, options={}) {
html += `</div>`; // controls
html += `</div>`; // form-group
if (parameters.after) {
html += parameters.after;
}
@ -2145,17 +2145,17 @@ function constructLabel(name, parameters) {
}
var html = `<label class='${label_classes}' for='id_${name}'>`;
if (parameters.label) {
html += `${parameters.label}`;
} else {
html += `${name}`;
}
if (parameters.required) {
html += `<span class='asteriskField'>*</span>`;
}
html += `</label>`;
return html;
@ -2164,11 +2164,11 @@ function constructLabel(name, parameters) {
/*
* Construct a form input based on the field parameters
*
*
* arguments:
* - name: The name of the field
* - parameters: Field parameters returned by the OPTIONS method
*
*
*/
function constructInput(name, parameters, options={}) {
@ -2212,7 +2212,7 @@ function constructInput(name, parameters, options={}) {
// Unsupported field type!
break;
}
if (func != null) {
html = func(name, parameters, options);
} else {
@ -2499,14 +2499,14 @@ function constructRawInput(name, parameters) {
/*
* Construct a 'help text' div based on the field parameters
*
*
* arguments:
* - name: The name of the field
* - parameters: Field parameters returned by the OPTIONS method
*
*
*/
function constructHelpText(name, parameters) {
var html = `<div id='hint_id_${name}' class='help-block'><i>${parameters.help_text}</i></div>`;
return html;
@ -2567,7 +2567,7 @@ function selectImportFields(url, data={}, options={}) {
var headers = `<tr><th>{% trans "File Column" %}</th><th>{% trans "Field Name" %}</th></tr>`;
var html = '';
if (options.preamble) {
html += options.preamble;
}
@ -2580,7 +2580,7 @@ function selectImportFields(url, data={}, options={}) {
fields: {},
preFormContent: html,
onSubmit: function(fields, opts) {
var columns = [];
for (var idx = 0; idx < field_names.length; idx++) {
@ -2605,16 +2605,16 @@ function selectImportFields(url, data={}, options={}) {
}
},
error: function(xhr) {
$(opts.modal).find('#modal-progress-spinner').hide();
switch (xhr.status) {
case 400:
handleFormErrors(xhr.responseJSON, fields, opts);
break;
default:
$(opts.modal).modal('hide');
console.error(`upload error at ${opts.url}`);
showApiError(xhr, opts.url);
break;

View File

@ -60,7 +60,7 @@ function imageHoverIcon(url) {
/**
* Renders a simple thumbnail image
* @param {String} url is the image URL
* @param {String} url is the image URL
* @returns html <img> tag
*/
function thumbnailImage(url, options={}) {
@ -131,7 +131,7 @@ function makeIconButton(icon, cls, pk, title, options={}) {
/*
* Render a progessbar!
*
*
* @param value is the current value of the progress bar
* @param maximum is the maximum value of the progress bar
*/
@ -164,7 +164,7 @@ function makeProgressBar(value, maximum, opts={}) {
var style = options.style || '';
var text = options.text;
if (!text) {
if (style == 'percent') {
// Display e.g. "50%"
@ -247,13 +247,13 @@ function setupNotesField(element, url, options={}) {
if (editable) {
// Heading icons
toolbar_icons.push('heading-1', 'heading-2', 'heading-3', '|');
// Font style
toolbar_icons.push('bold', 'italic', 'strikethrough', '|');
// Text formatting
toolbar_icons.push('unordered-list', 'ordered-list', 'code', 'quote', '|');
// Elements
toolbar_icons.push('table', 'link', 'image');
}
@ -275,11 +275,11 @@ function setupNotesField(element, url, options={}) {
if (!editable) {
// Set readonly
mde.codemirror.setOption('readOnly', true);
// Hide the "edit" and "save" buttons
$('#edit-notes').hide();
$('#save-notes').hide();
} else {
mde.togglePreview();
@ -289,7 +289,7 @@ function setupNotesField(element, url, options={}) {
$('#save-notes').show();
// Show the toolbar
$(`#${element}`).next('.EasyMDEContainer').find('.editor-toolbar').show();
$(`#${element}`).next('.EasyMDEContainer').find('.editor-toolbar').show();
mde.togglePreview();
});
@ -313,4 +313,3 @@ function setupNotesField(element, url, options={}) {
});
}
}

View File

@ -224,7 +224,7 @@ function selectLabel(labels, items, options={}) {
/**
* Present the user with the available labels,
* and allow them to select which label to print.
*
*
* The intent is that the available labels have been requested
* (via AJAX) from the server.
*/
@ -249,7 +249,7 @@ function selectLabel(labels, items, options={}) {
}
var plugin_selection = '';
if (plugins_enabled && plugins.length > 0) {
plugin_selection =`
<div class='form-group'>

View File

@ -20,7 +20,7 @@
/*
* Create and display a new modal dialog
*
*
* options:
* - title: Form title to render
* - submitText: Text to render on 'submit' button (default = "Submit")
@ -94,7 +94,7 @@ function createNewModal(options={}) {
if (options.focus) {
getFieldByName(modal_name, options.focus).focus();
}
// Steal keyboard focus
$(modal_name).focus();
@ -122,7 +122,7 @@ function createNewModal(options={}) {
// Simulate a click on the 'Submit' button
$(modal_name).find('#modal-form-submit').click();
}
return false;
}
});
@ -163,10 +163,10 @@ function makeOptionsList(elements, textFunc, valueFunc, titleFunc) {
* from the (assumed array) of elements.
* For each element, we pass the element to the supplied functions,
* which (in turn) generate display / value / title values.
*
*
* Args:
* - elements: List of elements
* - textFunc: Function which takes an element and generates the text to be displayed
* - textFunc: Function which takes an element and generates the text to be displayed
* - valueFunc: optional function which takes an element and generates the value
* - titleFunc: optional function which takes an element and generates a title
*/
@ -214,7 +214,7 @@ function setFieldOptions(fieldName, optionList, options={}) {
var addEmptyOption = options.addEmptyOption || true;
// If not appending, clear out the field...
// If not appending, clear out the field...
if (!append) {
field.find('option').remove();
}
@ -246,7 +246,7 @@ function reloadFieldOptions(fieldName, options) {
*
* Args:
* - fieldName: The name of the field
* - options:
* - options:
* -- url: Query url
* -- params: Query params
* -- value: A function which takes a returned option and returns the 'value' (if not specified, the `pk` field is used)
@ -289,7 +289,7 @@ function reloadFieldOptions(fieldName, options) {
function enableField(fieldName, enabled, options={}) {
/* Enable (or disable) a particular field in a modal.
*
*
* Args:
* - fieldName: The name of the field
* - enabled: boolean enabled / disabled status
@ -366,7 +366,7 @@ function partialMatcher(params, data) {
function attachSelect(modal) {
/* Attach 'select2' functionality to any drop-down list in the modal.
/* Attach 'select2' functionality to any drop-down list in the modal.
* Provides search filtering for dropdown items
*/
@ -391,7 +391,7 @@ function attachBootstrapCheckbox(modal) {
function loadingMessageContent() {
/* Render a 'loading' message to display in a form
/* Render a 'loading' message to display in a form
* when waiting for a response from the server
*/
@ -404,7 +404,7 @@ function afterForm(response, options) {
/* afterForm is called after a form is successfully submitted,
* and the form is dismissed.
* Used for general purpose functionality after form submission:
*
*
* - Display a bootstrap alert (success / info / warning / danger)
* - Run a supplied success callback function
* - Redirect the browser to a different URL
@ -424,11 +424,11 @@ function afterForm(response, options) {
if (response.info) {
showAlertOrCache(response.info, cache, {style: 'info'});
}
if (response.warning) {
showAlertOrCache(response.warning, cache, {style: 'warning'});
}
if (response.danger) {
showAlertOrCache(response.danger, cache, {style: 'danger'});
}
@ -467,7 +467,7 @@ function modalEnable(modal, enable=true) {
function modalSetTitle(modal, title='') {
/* Update the title of a modal form
/* Update the title of a modal form
*/
$(modal + ' #modal-title').html(title);
}
@ -496,7 +496,7 @@ function modalSetCloseText(modal, text) {
function modalSetButtonText(modal, submit_text, close_text) {
/* Set the button text for a modal form
*
*
* submit_text - text for the form submit button
* close_text - text for the form dismiss button
*/
@ -575,8 +575,8 @@ function renderErrorMessage(xhr) {
function showAlertDialog(title, content, options={}) {
/* Display a modal dialog message box.
*
* title - Title text
*
* title - Title text
* content - HTML content of the dialog window
*/
@ -600,7 +600,7 @@ function showAlertDialog(title, content, options={}) {
function showQuestionDialog(title, content, options={}) {
/* Display a modal dialog for user input (Yes/No confirmation dialog)
*
*
* title - Title text
* content - HTML content of the dialog window
* options:
@ -609,7 +609,7 @@ function showQuestionDialog(title, content, options={}) {
* cancel_text - Text for the cancel button (default = 'Cancel')
* accept - Function to run if the user presses 'Accept'
* cancel - Functino to run if the user presses 'Cancel'
*/
*/
var modal = createNewModal({
title: title,
@ -632,9 +632,9 @@ function showQuestionDialog(title, content, options={}) {
function openModal(options) {
/* Open a modal form, and perform some action based on the provided options object:
*
*
* options can contain:
*
*
* modal - ID of the modal form element (default = '#modal-form')
* title - Custom title for the form
* content - Default content for the form panel
@ -743,7 +743,7 @@ function attachSecondaryModal(modal, options) {
/* Attach a secondary modal form to the primary modal form.
* Inserts a button into the primary form which, when clicked,
* will launch the secondary modal to do /something/ and then return a result.
*
*
* options:
* field: Name of the field to attach to
* label: Button text
@ -834,7 +834,7 @@ function attachButtons(modal, buttons) {
function attachFieldCallback(modal, callback) {
/* Attach a 'callback' function to a given field in the modal form.
* When the value of that field is changed, the callback function is performed.
*
*
* options:
* - field: The name of the field to attach to
* - action: A function to perform
@ -867,7 +867,7 @@ function attachCallbacks(modal, callbacks) {
function handleModalForm(url, options) {
/* Update a modal form after data are received from the server.
* Manages POST requests until the form is successfully submitted.
*
*
* The server should respond with a JSON object containing a boolean value 'form_valid'
* Form submission repeats (after user interaction) until 'form_valid' = true
*/
@ -952,8 +952,8 @@ function handleModalForm(url, options) {
error: function(xhr) {
// There was an error submitting form data via POST
$(modal).modal('hide');
showAlertDialog('{% trans "Error posting form data" %}', renderErrorMessage(xhr));
$(modal).modal('hide');
showAlertDialog('{% trans "Error posting form data" %}', renderErrorMessage(xhr));
},
complete: function() {
// TODO
@ -965,15 +965,15 @@ function handleModalForm(url, options) {
function launchModalForm(url, options = {}) {
/* Launch a modal form, and request data from the server to fill the form
* If the form data is returned from the server, calls handleModalForm()
* If the form data is returned from the server, calls handleModalForm()
*
* A successful request will return a JSON object with, at minimum,
* an object called 'html_form'
*
*
* If the request is NOT successful, displays an appropriate error message.
*
*
* options:
*
*
* modal - Name of the modal (default = '#modal-form')
* data - Data to pass through to the AJAX request to fill the form
* submit_text - Text for the submit button (default = 'Submit')

View File

@ -21,9 +21,9 @@
/*
* This file contains functions for rendering various InvenTree database models,
* in particular for displaying them in modal forms in a 'select2' context.
*
*
* Each renderer is provided with three arguments:
*
*
* - name: The 'name' of the model instance in the referring model
* - data: JSON data which represents the model instance. Returned via a GET request.
* - parameters: The field parameters provided via an OPTIONS request to the endpoint.
@ -40,7 +40,7 @@ function renderId(title, pk, parameters={}) {
if ('render_pk' in parameters) {
render = parameters['render_pk'];
}
if (render) {
return `<span class='float-right'><small>${title}: ${pk}</small></span>`;
} else {
@ -52,7 +52,7 @@ function renderId(title, pk, parameters={}) {
// Renderer for "Company" model
// eslint-disable-next-line no-unused-vars
function renderCompany(name, data, parameters={}, options={}) {
var html = select2Thumbnail(data.image);
html += `<span><b>${data.name}</b></span> - <i>${data.description}</i>`;
@ -68,11 +68,11 @@ function renderCompany(name, data, parameters={}, options={}) {
function renderStockItem(name, data, parameters={}, options={}) {
var image = blankImage();
if (data.part_detail) {
image = data.part_detail.thumbnail || data.part_detail.image || blankImage();
}
var render_part_detail = true;
if ('render_part_detail' in parameters) {
@ -151,12 +151,12 @@ function renderStockLocation(name, data, parameters={}, options={}) {
// eslint-disable-next-line no-unused-vars
function renderBuild(name, data, parameters={}, options={}) {
var image = null;
if (data.part_detail && data.part_detail.thumbnail) {
image = data.part_detail.thumbnail;
}
}
var html = select2Thumbnail(image);
@ -173,7 +173,7 @@ function renderBuild(name, data, parameters={}, options={}) {
function renderPart(name, data, parameters={}, options={}) {
var html = select2Thumbnail(data.image);
html += ` <span>${data.full_name || data.name}</span>`;
if (data.description) {
@ -245,9 +245,9 @@ function renderPurchaseOrder(name, data, parameters={}, options={}) {
var prefix = global_settings.PURCHASEORDER_REFERENCE_PREFIX;
var html = `<span>${prefix}${data.reference}</span>`;
var thumbnail = null;
if (data.supplier_detail) {
thumbnail = data.supplier_detail.thumbnail || data.supplier_detail.image;
@ -268,10 +268,10 @@ function renderPurchaseOrder(name, data, parameters={}, options={}) {
// Renderer for "SalesOrder" model
// eslint-disable-next-line no-unused-vars
function renderSalesOrder(name, data, parameters={}, options={}) {
var prefix = global_settings.SALESORDER_REFERENCE_PREFIX;
var html = `<span>${prefix}${data.reference}</span>`;
var thumbnail = null;
if (data.customer_detail) {
@ -335,7 +335,7 @@ function renderPartParameterTemplate(name, data, parameters={}, options={}) {
if (data.units) {
units = ` [${data.units}]`;
}
var html = `<span>${data.name}${units}</span>`;
return html;
@ -377,7 +377,7 @@ function renderSupplierPart(name, data, parameters={}, options={}) {
var supplier_image = null;
var part_image = null;
if (data.supplier_detail) {
supplier_image = data.supplier_detail.image;
}
@ -387,13 +387,13 @@ function renderSupplierPart(name, data, parameters={}, options={}) {
}
var html = '';
html += select2Thumbnail(supplier_image);
if (data.part_detail) {
html += select2Thumbnail(part_image);
}
if (data.supplier_detail) {
html += ` <span><b>${data.supplier_detail.name}</b> - ${data.SKU}</span>`;
}

View File

@ -74,14 +74,14 @@ function showCachedAlerts() {
}
/*
/*
* Display an alert message at the top of the screen.
* The message will contain a "close" button,
* and also dismiss automatically after a certain amount of time.
*
*
* arguments:
* - message: Text / HTML content to display
*
*
* options:
* - style: alert style e.g. 'success' / 'warning'
* - timeout: Time (in milliseconds) after which the message will be dismissed
@ -119,7 +119,7 @@ function showMessage(message, options={}) {
${icon}
<b>${message}</b>
${details}
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
</div>
`;
@ -152,7 +152,7 @@ var notificationUpdateTic = 0;
/**
* The notification checker is initiated when the document is loaded. It checks if there are unread notifications
* if unread messages exist the notification indicator is updated
*
*
* options:
* - force: set true to force an update now (if you got in focus for example)
**/
@ -182,10 +182,10 @@ function notificationCheck(force = false) {
/**
* handles read / unread buttons and UI rebuilding
*
*
* arguments:
* - btn: element that got clicked / fired the event -> must contain pk and target as attributes
*
*
* options:
* - panel_caller: this button was clicked in the notification panel
**/
@ -220,7 +220,7 @@ function updateNotificationReadState(btn, panel_caller=false) {
/**
* Returns the html for a read / unread button
*
*
* arguments:
* - pk: primary key of the notification
* - state: current state of the notification (read / unread) -> just pass what you were handed by the api

View File

@ -190,7 +190,7 @@ function completePurchaseOrder(order_id, options={}) {
* Launches a modal form to mark a PurchaseOrder as 'cancelled'
*/
function cancelPurchaseOrder(order_id, options={}) {
constructForm(
`/api/order/po/${order_id}/cancel/`,
{
@ -343,7 +343,7 @@ function createSalesOrder(options={}) {
title: '{% trans "Add Customer" %}',
fields: function() {
var fields = companyFormFields();
fields.is_customer.value = true;
return fields;
@ -531,7 +531,7 @@ function newSupplierPartFromOrderWizard(e) {
createSupplierPart({
part: part,
onSuccess: function(data) {
// TODO: 2021-08-23 - This whole form wizard needs to be refactored.
// In the future, use the API forms functionality to add the new item
// For now, this hack will have to do...
@ -568,9 +568,9 @@ function newSupplierPartFromOrderWizard(e) {
/**
* Export an order (PurchaseOrder or SalesOrder)
*
*
* - Display a simple form which presents the user with export options
*
*
*/
function exportOrder(redirect_url, options={}) {
@ -828,7 +828,7 @@ function orderParts(parts_list, options={}) {
filters: supplier_part_filters,
noResults: function(query) {
return '{% trans "No matching supplier parts" %}';
}
}
}, null, opts);
// Configure the "purchase order" field
@ -971,26 +971,26 @@ function newPurchaseOrderFromOrderWizard(e) {
var dropdown = `#id-purchase-order-${supplier}`;
var option = new Option(text, pk, true, true);
$('#modal-form').find(dropdown).append(option).trigger('change');
}
}
);
}
});
});
}
/**
* Receive stock items against a PurchaseOrder
* Uses the PurchaseOrderReceive API endpoint
*
*
* arguments:
* - order_id, ID / PK for the PurchaseOrder instance
* - line_items: A list of PurchaseOrderLineItems objects to be allocated
*
*
* options:
* -
* -
*/
function receivePurchaseOrderItems(order_id, line_items, options={}) {
@ -1012,7 +1012,7 @@ function receivePurchaseOrderItems(order_id, line_items, options={}) {
var thumb = thumbnailImage(line_item.part_detail.thumbnail);
var quantity = (line_item.quantity || 0) - (line_item.received || 0);
if (quantity < 0) {
quantity = 0;
}
@ -1022,14 +1022,14 @@ function receivePurchaseOrderItems(order_id, line_items, options={}) {
<span class='input-group-text' title='{% trans "Add batch code" %}' data-bs-toggle='collapse' href='#div-batch-${pk}'>
<span class='fas fa-layer-group'></span>
</span>
`;
`;
var toggle_serials = `
<span class='input-group-text' title='{% trans "Add serial numbers" %}' data-bs-toggle='collapse' href='#div-serials-${pk}'>
<span class='fas fa-hashtag'></span>
</span>
`;
// Quantity to Receive
var quantity_input = constructField(
`items_quantity_${pk}`,
@ -1363,7 +1363,7 @@ function editPurchaseOrderLineItem(e) {
function removePurchaseOrderLineItem(e) {
/* Delete a purchase order line item in a modal form
/* Delete a purchase order line item in a modal form
*/
e = e || window.event;
@ -1371,7 +1371,7 @@ function removePurchaseOrderLineItem(e) {
var src = e.target || e.srcElement;
var url = $(src).attr('url');
// TODO: Migrate this to the API forms
launchModalForm(url, {
reload: true,
@ -1437,7 +1437,7 @@ function loadPurchaseOrderTable(table, options) {
return html;
}
},
},
{
field: 'supplier_detail',
title: '{% trans "Supplier" %}',
@ -1491,11 +1491,11 @@ function loadPurchaseOrderTable(table, options) {
switchable: true,
sortable: false,
formatter: function(value, row) {
if (!row.responsible_detail) {
return '-';
}
var html = row.responsible_detail.name;
if (row.responsible_detail.label == 'group') {
@ -1514,7 +1514,7 @@ function loadPurchaseOrderTable(table, options) {
/**
* Load a table displaying line items for a particular PurchasesOrder
* @param {String} table - HTML ID tag e.g. '#table'
* @param {String} table - HTML ID tag e.g. '#table'
* @param {Object} options - options which must provide:
* - order (integer PK)
* - supplier (integer PK)
@ -1533,7 +1533,7 @@ function loadPurchaseOrderLineItemTable(table, options={}) {
for (var key in options.params) {
filters[key] = options.params[key];
}
var target = options.filter_target || '#filter-list-purchase-order-lines';
setupFilterList('purchaseorderlineitem', $(table), target, {download: true});
@ -1651,7 +1651,7 @@ function loadPurchaseOrderLineItemTable(table, options={}) {
formatter: function(value, row, index, field) {
if (row.part) {
return imageHoverIcon(row.part_detail.thumbnail) + renderLink(row.part_detail.full_name, `/part/${row.part_detail.pk}/`);
} else {
} else {
return '-';
}
},
@ -1752,7 +1752,7 @@ function loadPurchaseOrderLineItemTable(table, options={}) {
currency: currency
}
);
return formatter.format(total);
}
},
@ -1789,14 +1789,14 @@ function loadPurchaseOrderLineItemTable(table, options={}) {
});
},
sorter: function(valA, valB, rowA, rowB) {
if (rowA.received == 0 && rowB.received == 0) {
return (rowA.quantity > rowB.quantity) ? 1 : -1;
}
var progressA = parseFloat(rowA.received) / rowA.quantity;
var progressB = parseFloat(rowB.received) / rowB.quantity;
return (progressA < progressB) ? 1 : -1;
}
},
@ -1821,9 +1821,9 @@ function loadPurchaseOrderLineItemTable(table, options={}) {
title: '',
formatter: function(value, row, index, field) {
var html = `<div class='btn-group' role='group'>`;
var pk = row.pk;
if (options.allow_receive && row.received < row.quantity) {
html += makeIconButton('fa-sign-in-alt icon-green', 'button-line-receive', pk, '{% trans "Receive line item" %}');
}
@ -1835,7 +1835,7 @@ function loadPurchaseOrderLineItemTable(table, options={}) {
}
html += `</div>`;
return html;
},
}
@ -1847,7 +1847,7 @@ function loadPurchaseOrderLineItemTable(table, options={}) {
/**
* Load a table displaying lines for a particular PurchaseOrder
*
*
* @param {String} table : HTML ID tag e.g. '#table'
* @param {Object} options : object which contains:
* - order {integer} : pk of the PurchaseOrder
@ -1872,7 +1872,7 @@ function loadPurchaseOrderExtraLineTable(table, options={}) {
options.params.order = options.order;
options.params.part_detail = true;
options.params.allocations = true;
var filters = loadTableFilters('purchaseorderextraline');
for (var key in options.params) {
@ -1948,15 +1948,15 @@ function loadPurchaseOrderExtraLineTable(table, options={}) {
}, 0);
var currency = (data.slice(-1)[0] && data.slice(-1)[0].price_currency) || 'USD';
var formatter = new Intl.NumberFormat(
'en-US',
{
style: 'currency',
style: 'currency',
currency: currency
}
);
return formatter.format(total);
}
}
@ -2359,21 +2359,21 @@ function loadSalesOrderShipmentTable(table, options={}) {
/**
* Allocate stock items against a SalesOrder
*
*
* arguments:
* - order_id: The ID / PK value for the SalesOrder
* - lines: A list of SalesOrderLineItem objects to be allocated
*
*
* options:
* - source_location: ID / PK of the top-level StockLocation to source stock from (or null)
*/
function allocateStockToSalesOrder(order_id, line_items, options={}) {
function renderLineItemRow(line_item, quantity) {
// Function to render a single line_item row
var pk = line_item.pk;
var part = line_item.part_detail;
var thumb = thumbnailImage(part.thumbnail || part.image);
@ -2449,7 +2449,7 @@ function allocateStockToSalesOrder(order_id, line_items, options={}) {
'{% trans "Select Parts" %}',
'{% trans "You must select at least one part to allocate" %}',
);
return;
}
@ -2757,12 +2757,12 @@ function loadSalesOrderAllocationTable(table, options={}) {
/**
* Display an "allocations" sub table, showing stock items allocated againt a sales order
* @param {*} index
* @param {*} row
* @param {*} element
* @param {*} index
* @param {*} row
* @param {*} element
*/
function showAllocationSubTable(index, row, element, options) {
// Construct a sub-table element
var html = `
<div class='sub-table'>
@ -2798,7 +2798,7 @@ function showAllocationSubTable(index, row, element, options) {
// Add callbacks for 'delete' buttons
table.find('.button-allocation-delete').click(function() {
var pk = $(this).attr('pk');
constructForm(
`/api/order/so-allocation/${pk}/`,
{
@ -2894,7 +2894,7 @@ function showFulfilledSubTable(index, row, element, options) {
}
var id = `fulfilled-table-${row.pk}`;
var html = `
<div class='sub-table'>
<table class='table table-striped table-condensed' id='${id}'>
@ -2976,7 +2976,7 @@ function reloadTotal() {
/**
* Load a table displaying line items for a particular SalesOrder
*
*
* @param {String} table : HTML ID tag e.g. '#table'
* @param {Object} options : object which contains:
* - order {integer} : pk of the SalesOrder
@ -3001,7 +3001,7 @@ function loadSalesOrderLineItemTable(table, options={}) {
options.params.order = options.order;
options.params.part_detail = true;
options.params.allocations = true;
var filters = loadTableFilters('salesorderlineitem');
for (var key in options.params) {
@ -3107,15 +3107,15 @@ function loadSalesOrderLineItemTable(table, options={}) {
}, 0);
var currency = (data.slice(-1)[0] && data.slice(-1)[0].sale_price_currency) || 'USD';
var formatter = new Intl.NumberFormat(
'en-US',
{
style: 'currency',
style: 'currency',
currency: currency
}
);
return formatter.format(total);
}
},
@ -3138,7 +3138,7 @@ function loadSalesOrderLineItemTable(table, options={}) {
return `<em>${renderDate(row.order_detail.target_date)}</em>`;
} else {
return '-';
}
}
}
}
];
@ -3166,17 +3166,17 @@ function loadSalesOrderLineItemTable(table, options={}) {
});
},
sorter: function(valA, valB, rowA, rowB) {
var A = rowA.allocated;
var B = rowB.allocated;
if (A == 0 && B == 0) {
return (rowA.quantity > rowB.quantity) ? 1 : -1;
}
var progressA = parseFloat(A) / rowA.quantity;
var progressB = parseFloat(B) / rowB.quantity;
return (progressA < progressB) ? 1 : -1;
}
},
@ -3391,11 +3391,11 @@ function loadSalesOrderLineItemTable(table, options={}) {
// Extract the row data from the table!
var idx = $(this).closest('tr').attr('data-index');
var row = $(table).bootstrapTable('getData')[idx];
var quantity = 1;
if (row.allocated < row.quantity) {
quantity = row.quantity - row.allocated;
}
@ -3489,7 +3489,7 @@ function loadSalesOrderLineItemTable(table, options={}) {
/**
* Load a table displaying lines for a particular SalesOrder
*
*
* @param {String} table : HTML ID tag e.g. '#table'
* @param {Object} options : object which contains:
* - order {integer} : pk of the SalesOrder
@ -3514,7 +3514,7 @@ function loadSalesOrderExtraLineTable(table, options={}) {
options.params.order = options.order;
options.params.part_detail = true;
options.params.allocations = true;
var filters = loadTableFilters('salesorderextraline');
for (var key in options.params) {
@ -3590,15 +3590,15 @@ function loadSalesOrderExtraLineTable(table, options={}) {
}, 0);
var currency = (data.slice(-1)[0] && data.slice(-1)[0].price_currency) || 'USD';
var formatter = new Intl.NumberFormat(
'en-US',
{
style: 'currency',
style: 'currency',
currency: currency
}
);
return formatter.format(total);
}
}

View File

@ -209,7 +209,7 @@ function partFields(options={}) {
help_text: '{% trans "Create initial supplier data for this part" %}',
group: 'supplier',
};
fields.supplier = {
type: 'related field',
model: 'company',
@ -221,14 +221,14 @@ function partFields(options={}) {
api_url: '{% url "api-company-list" %}',
group: 'supplier',
};
fields.SKU = {
type: 'string',
label: '{% trans "SKU" %}',
label: '{% trans "SKU" %}',
help_text: '{% trans "Supplier stock keeping unit" %}',
group: 'supplier',
};
fields.manufacturer = {
type: 'related field',
model: 'company',
@ -240,7 +240,7 @@ function partFields(options={}) {
api_url: '{% url "api-company-list" %}',
group: 'supplier',
};
fields.MPN = {
type: 'string',
label: '{% trans "MPN" %}',
@ -357,7 +357,7 @@ function duplicatePart(pk, options={}) {
inventreeGet(`/api/part/${pk}/`, {}, {
success: function(data) {
var fields = partFields({
duplicate: pk,
});
@ -378,7 +378,7 @@ function duplicatePart(pk, options={}) {
// By default, disable "is_template" when making a variant *of* a template
data.is_template = false;
}
constructForm('{% url "api-part-list" %}', {
method: 'POST',
fields: fields,
@ -397,7 +397,7 @@ function duplicatePart(pk, options={}) {
/* Toggle the 'starred' status of a part.
* Performs AJAX queries and updates the display on the button.
*
*
* options:
* - button: ID of the button (default = '#part-star-icon')
* - URL: API url of the object
@ -578,7 +578,7 @@ function makePartIcons(part) {
}
if (!part.active) {
html += `<span class='badge badge-right rounded-pill bg-warning'>{% trans "Inactive" %}</span> `;
html += `<span class='badge badge-right rounded-pill bg-warning'>{% trans "Inactive" %}</span> `;
}
return html;
@ -655,7 +655,7 @@ function loadPartVariantTable(table, partId, options={}) {
}
if (!row.active) {
html += `<span class='badge badge-right rounded-pill bg-warning'>{% trans "Inactive" %}</span>`;
html += `<span class='badge badge-right rounded-pill bg-warning'>{% trans "Inactive" %}</span>`;
}
return html;
@ -839,7 +839,7 @@ function loadPartParameterTable(table, url, options) {
/*
* Construct a table showing a list of purchase orders for a given part.
*
*
* This requests API data from the PurchaseOrderLineItem endpoint
*/
function loadPartPurchaseOrderTable(table, part_id, options={}) {
@ -850,7 +850,7 @@ function loadPartPurchaseOrderTable(table, part_id, options={}) {
options.params.base_part = part_id;
options.params.part_detail = true;
options.params.order_detail = true;
var filters = loadTableFilters('purchaseorderlineitem');
for (var key in options.params) {
@ -1014,7 +1014,7 @@ function loadPartPurchaseOrderTable(table, part_id, options={}) {
title: '',
switchable: false,
formatter: function(value, row) {
if (row.received >= row.quantity) {
// Already recevied
return `<span class='badge bg-success rounded-pill'>{% trans "Received" %}</span>`;
@ -1089,7 +1089,7 @@ function loadRelatedPartsTable(table, part_id, options={}) {
title: '',
switchable: false,
formatter: function(value, row) {
var html = `<div class='btn-group float-right' role='group'>`;
html += makeIconButton('fa-trash-alt icon-red', 'button-related-delete', row.pk, '{% trans "Delete part relationship" %}');
@ -1234,7 +1234,7 @@ function partGridTile(part) {
}
var html = `
<div class='card product-card borderless'>
<div class='panel product-card-panel'>
<div class='panel-heading'>
@ -1258,7 +1258,7 @@ function partGridTile(part) {
</div>
</div>
</div>
</div>
</div>
`;
return html;
@ -1267,7 +1267,7 @@ function partGridTile(part) {
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
@ -1340,7 +1340,7 @@ function loadPartTable(table, url, options={}) {
display += makePartIcons(row);
return display;
return display;
}
};
@ -1373,7 +1373,7 @@ function loadPartTable(table, url, options={}) {
} else {
return '{% trans "No category" %}';
}
}
}
};
if (!options.params.ordering) {
@ -1386,7 +1386,7 @@ function loadPartTable(table, url, options={}) {
field: 'unallocated_stock',
title: '{% trans "Stock" %}',
searchable: false,
formatter: function(value, row) {
formatter: function(value, row) {
var link = '?display=part-stock';
if (row.in_stock) {
@ -1538,7 +1538,7 @@ function loadPartTable(table, url, options={}) {
html = `<div class='row full-height'>`;
data.forEach(function(row, index) {
// Force a new row every 5 columns
if ((index > 0) && (index % 5 == 0) && (index < data.length)) {
html += `</div><div class='row full-height'>`;
@ -1552,7 +1552,7 @@ function loadPartTable(table, url, options={}) {
return html;
}
});
if (options.buttons) {
linkButtonsToSelection($(table), options.buttons);
}
@ -1624,11 +1624,11 @@ function loadPartCategoryTable(table, options) {
filters = loadTableFilters(filterKey);
}
var tree_view = options.allowTreeView && inventreeLoad('category-tree-view') == 1;
if (tree_view) {
params.cascade = true;
params.cascade = true;
}
var original = {};
@ -1652,7 +1652,7 @@ function loadPartCategoryTable(table, options) {
queryParams: filters,
disablePagination: tree_view,
sidePagination: tree_view ? 'client' : 'server',
serverSort: !tree_view,
serverSort: !tree_view,
search: !tree_view,
name: 'category',
original: original,
@ -1707,14 +1707,14 @@ function loadPartCategoryTable(table, options) {
$('#view-category-list').removeClass('btn-secondary').addClass('btn-outline-secondary');
$('#view-category-tree').removeClass('btn-outline-secondary').addClass('btn-secondary');
table.treegrid({
treeColumn: 0,
onChange: function() {
table.bootstrapTable('resetView');
},
onExpand: function() {
}
});
} else {
@ -1862,7 +1862,7 @@ function loadPartTestTemplateTable(table, options) {
} else {
var text = '{% trans "This test is defined for a parent part" %}';
return renderLink(text, `/part/${row.part}/tests/`);
return renderLink(text, `/part/${row.part}/tests/`);
}
}
}
@ -1871,9 +1871,9 @@ function loadPartTestTemplateTable(table, options) {
table.find('.button-test-edit').click(function() {
var pk = $(this).attr('pk');
var url = `/api/part/test-template/${pk}/`;
constructForm(url, {
fields: {
test_name: {},
@ -1891,9 +1891,9 @@ function loadPartTestTemplateTable(table, options) {
table.find('.button-test-delete').click(function() {
var pk = $(this).attr('pk');
var url = `/api/part/test-template/${pk}/`;
constructForm(url, {
method: 'DELETE',
title: '{% trans "Delete Test Result Template" %}',
@ -1975,14 +1975,14 @@ function loadPriceBreakTable(table, options) {
sortable: true,
formatter: function(value, row) {
var html = value;
html += `<div class='btn-group float-right' role='group'>`;
html += makeIconButton('fa-edit icon-blue', `button-${name}-edit`, row.pk, `{% trans "Edit ${human_name}" %}`);
html += makeIconButton('fa-trash-alt icon-red', `button-${name}-delete`, row.pk, `{% trans "Delete ${human_name}" %}`);
html += `</div>`;
return html;
}
},

View File

@ -25,7 +25,7 @@ function selectReport(reports, items, options={}) {
/**
* Present the user with the available reports,
* and allow them to select which report to print.
*
*
* The intent is that the available report templates have been requested
* (via AJAX) from the server.
*/

View File

@ -34,11 +34,11 @@ function openSearchPanel() {
// Prevent this button from actually submitting the form
event.preventDefault();
panel.find('#search-input').val('');
clearSearchResults();
});
// Callback for the "close search" button
panel.find('#search-close').click(function(event) {
// Prevent this button from actually submitting the form
@ -67,11 +67,11 @@ function updateSearch() {
}
clearSearchResults();
if (searchText.length == 0) {
return;
}
searchTextCurrent = searchText;
// Cancel any previous AJAX requests
@ -83,7 +83,7 @@ function updateSearch() {
// Show the "searching" text
$('#offcanvas-search').find('#search-pending').show();
if (user_settings.SEARCH_PREVIEW_SHOW_PARTS) {
var params = {};
@ -122,7 +122,7 @@ function updateSearch() {
if (user_settings.SEARCH_PREVIEW_SHOW_STOCK) {
// Search for matching stock items
var filters = {
part_detail: true,
location_detail: true,
@ -220,7 +220,7 @@ function updateSearch() {
}
);
}
// Wait until all the pending queries are completed
$.when.apply($, searchQueries).done(function() {
$('#offcanvas-search').find('#search-pending').hide();
@ -231,13 +231,13 @@ function updateSearch() {
function clearSearchResults() {
var panel = $('#offcanvas-search');
// Ensure the 'no results found' element is visible
panel.find('#search-no-results').show();
// Ensure that the 'searching' element is hidden
panel.find('#search-pending').hide();
// Delete any existing search results
panel.find('#search-results').empty();
@ -287,7 +287,7 @@ function addSearchQuery(key, title, query_url, query_params, render_func, render
// Add a group of results to the list
function addSearchResults(key, results, title, renderFunc, renderParams={}) {
if (results.length == 0) {
// Do not display this group, as there are no results
return;
@ -297,7 +297,7 @@ function addSearchResults(key, results, title, renderFunc, renderParams={}) {
// Ensure the 'no results found' element is hidden
panel.find('#search-no-results').hide();
panel.find(`#search-results-wrapper-${key}`).append(`
<div class='search-result-group' id='search-results-${key}'>
<div class='search-result-header' style='display: flex;'>

View File

@ -202,7 +202,7 @@ function stockItemFields(options={}) {
} else {
clearFormInput('supplier_part', opts);
clearFormInput('purchase_price', opts);
disableFormInput('supplier_part', opts);
disableFormInput('purchase_price', opts);
disableFormInput('purchase_price_currency', opts);
@ -315,11 +315,11 @@ function duplicateStockItem(pk, options) {
delete data['serial'];
options.data = data;
options.create = true;
options.fields = stockItemFields(options);
options.groups = stockItemGroups(options);
options.method = 'POST';
options.title = '{% trans "Duplicate Stock Item" %}';
@ -342,7 +342,7 @@ function editStockItem(pk, options={}) {
options.groups = stockItemGroups(options);
options.title = '{% trans "Edit Stock Item" %}';
// Query parameters for retrieving stock item data
options.params = {
part_detail: true,
@ -443,7 +443,7 @@ function findStockItemBySerialNumber(part_id) {
onSubmit: function(fields, opts) {
var serial = getFormFieldValue('serial', fields['serial'], opts);
serial = serial.toString().trim();
if (!serial) {
@ -540,7 +540,7 @@ function assignStockToCustomer(items, options={}) {
for (var idx = 0; idx < items.length; idx++) {
var item = items[idx];
var pk = item.pk;
var part = item.part_detail;
@ -1069,7 +1069,7 @@ function adjustStock(action, items, options={}) {
}
},
onSubmit: function(fields, opts) {
// Extract data elements from the form
var data = {
items: [],
@ -1094,7 +1094,7 @@ function adjustStock(action, items, options={}) {
if (row.exists()) {
item_pk_values.push(pk);
var quantity = getFormFieldValue(`items_quantity_${pk}`, {}, opts);
data.items.push({
@ -1514,9 +1514,9 @@ function loadStockTestResultsTable(table, options) {
function locationDetail(row, showLink=true) {
/*
/*
* Function to display a "location" of a StockItem.
*
*
* Complicating factors: A StockItem may not actually *be* in a location!
* - Could be at a customer
* - Could be installed in another stock item
@ -1568,7 +1568,7 @@ function loadStockTable(table, options) {
/* 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.
*
*
* Options:
* url - URL for the stock query
* params - query params for augmenting stock data request
@ -1657,7 +1657,7 @@ function loadStockTable(table, options) {
return html;
}
};
if (!options.params.ordering) {
col['sortable'] = true;
}
@ -1711,7 +1711,7 @@ function loadStockTable(table, options) {
if (row.is_building) {
html += makeIconBadge('fa-tools', '{% trans "Stock item is in production" %}');
}
}
if (row.sales_order) {
// Stock item has been assigned to a sales order
@ -1760,7 +1760,7 @@ function loadStockTable(table, options) {
return html;
}
};
columns.push(col);
col = {
@ -1870,7 +1870,7 @@ function loadStockTable(table, options) {
});
col = {
field: 'supplier_part',
title: '{% trans "Supplier Part" %}',
visible: params['supplier_part_detail'] || false,
@ -1987,7 +1987,7 @@ function loadStockTable(table, options) {
});
if (global_settings.BARCODE_ENABLE) {
$('#multi-item-barcode-scan-into-location').click(function() {
$('#multi-item-barcode-scan-into-location').click(function() {
var selections = $(table).bootstrapTable('getSelections');
var items = [];
@ -2158,7 +2158,7 @@ function loadStockTable(table, options) {
}
/*
/*
* Display a table of stock locations
*/
function loadStockLocationTable(table, options) {
@ -2220,14 +2220,14 @@ function loadStockLocationTable(table, options) {
$('#view-location-list').removeClass('btn-secondary').addClass('btn-outline-secondary');
$('#view-location-tree').removeClass('btn-outline-secondary').addClass('btn-secondary');
table.treegrid({
treeColumn: 1,
onChange: function() {
table.bootstrapTable('resetView');
},
onExpand: function() {
}
});
} else {
@ -2664,7 +2664,7 @@ function uninstallStockItem(installed_item_id, options={}) {
},
preFormContent: function(opts) {
var html = '';
if (installed_item_id == null) {
html += `
<div class='alert alert-block alert-info'>

View File

@ -15,7 +15,7 @@
/**
* Reload a named table
* @param table
* @param table
*/
function reloadtable(table) {
$(table).bootstrapTable('refresh');
@ -25,7 +25,7 @@ function reloadtable(table) {
/**
* Download data from a table, via the API.
* This requires a number of conditions to be met:
*
*
* - The API endpoint supports data download (on the server side)
* - The table is "flat" (does not support multi-level loading, etc)
* - The table has been loaded using the inventreeTable() function, not bootstrapTable()
@ -60,16 +60,16 @@ function downloadTableData(table, opts={}) {
},
onSubmit: function(fields, form_options) {
var format = getFormFieldValue('format', fields['format'], form_options);
// Hide the modal
$(form_options.modal).modal('hide');
for (const [key, value] of Object.entries(query_params)) {
url += `${key}=${value}&`;
}
url += `export=${format}`;
location.href = url;
}
});
@ -80,9 +80,9 @@ function downloadTableData(table, opts={}) {
/**
* Render a URL for display
* @param {String} text
* @param {String} url
* @param {object} options
* @param {String} text
* @param {String} url
* @param {object} options
* @returns link text
*/
function renderLink(text, url, options={}) {
@ -134,8 +134,8 @@ function linkButtonsToSelection(table, buttons) {
/**
* Returns true if the input looks like a valid number
* @param {String} n
* @returns
* @param {String} n
* @returns
*/
function isNumeric(n) {
return !isNaN(parseFloat(n)) && isFinite(n);
@ -251,7 +251,7 @@ function convertQueryParameters(params, filters) {
delete params['original_search'];
}
return params;
}

View File

@ -95,9 +95,9 @@
{% include "spacer.html" %}
{% include "spacer.html" %}
{% endif %}
<ul class='navbar-nav flex-row'>
<li class='nav-item me-2'>
<button data-bs-toggle='offcanvas' data-bs-target="#offcanvas-search" class='btn position-relative' title='{% trans "Search" %}'>
<span class='fas fa-search'></span>

View File

@ -21,7 +21,7 @@
</div>
</div>
</div>
{% block page_info %}
<div class='panel-content'>
{% block details_above %}
@ -57,7 +57,7 @@
</div>
</div>
{% endblock %}
</div>
{% block page_content %}

View File

@ -40,4 +40,3 @@
</div>
</div>
</div>

View File

@ -5,13 +5,13 @@
{% for provider in socialaccount_providers %}
{% if provider.id == "openid" %}
{% for brand in provider.get_brands %}
<a title="{{brand.name}}"
class="btn btn-primary socialaccount_provider {{provider.id}} {{brand.id}}"
<a title="{{brand.name}}"
class="btn btn-primary socialaccount_provider {{provider.id}} {{brand.id}}"
href="{% provider_login_url provider.id openid=brand.openid_url process=process %}"
><span class='brand-icon' brand_name='{{provider.id}}'></span> {{brand.name}}</a>
{% endfor %}
{% endif %}
<a title="{{provider.name}}" class="btn btn-primary socialaccount_provider {{provider.id}}"
<a title="{{provider.name}}" class="btn btn-primary socialaccount_provider {{provider.id}}"
href="{% provider_login_url provider.id process=process scope=scope auth_params=auth_params %}"
><span class='brand-icon' brand_name='{{provider.id}}'></span> {{provider.name}}</a>
{% endfor %}

View File

@ -10,7 +10,7 @@ const {{ label }}Codes = {
{% endfor %}
};
/*
/*
* Render the status for a {{ label }} object.
* Uses the values specified in "status_codes.py"
* This function is generated by the "status_codes.html" template