mirror of
https://github.com/inventree/InvenTree
synced 2024-08-30 18:33:04 +00:00
More features
- Custom renderers depending on specified model name - Paginate API results
This commit is contained in:
parent
b29db6f258
commit
565631ef87
@ -973,3 +973,10 @@ input[type="date"].form-control, input[type="time"].form-control, input[type="da
|
||||
.select2-container {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.select2-thumbnail {
|
||||
max-width: 24px;
|
||||
max-height: 24px;
|
||||
border-radius: 4px;
|
||||
margin-right: 10px;
|
||||
}
|
@ -105,6 +105,7 @@ settings_urls = [
|
||||
dynamic_javascript_urls = [
|
||||
url(r'^api.js', DynamicJsView.as_view(template_name='js/api.js'), name='api.js'),
|
||||
url(r'^forms.js', DynamicJsView.as_view(template_name='js/forms.js'), name='forms.js'),
|
||||
url(r'^model_renderers.js', DynamicJsView.as_view(template_name='js/model_renderers.js'), name='model_renderers.js'),
|
||||
url(r'^modals.js', DynamicJsView.as_view(template_name='js/modals.js'), name='modals.js'),
|
||||
url(r'^barcode.js', DynamicJsView.as_view(template_name='js/barcode.js'), name='barcode.js'),
|
||||
url(r'^bom.js', DynamicJsView.as_view(template_name='js/bom.js'), name='bom.js'),
|
||||
|
@ -150,6 +150,7 @@
|
||||
<!-- translated -->
|
||||
<script type='text/javascript' src="{% i18n_static 'api.js' %}"></script>
|
||||
<script type='text/javascript' src="{% i18n_static 'forms.js' %}"></script>
|
||||
<script type='text/javascript' src="{% i18n_static 'model_renderers.js' %}"></script>
|
||||
<script type='text/javascript' src="{% i18n_static 'barcode.js' %}"></script>
|
||||
<script type='text/javascript' src="{% i18n_static 'bom.js' %}"></script>
|
||||
<script type='text/javascript' src="{% i18n_static 'company.js' %}"></script>
|
||||
|
@ -364,7 +364,8 @@ function initializeRelatedField(modal, name, field, options) {
|
||||
|
||||
// TODO: Add 'placeholder' support for entry select2 fields
|
||||
|
||||
// TODO: Add 'pagination' support for the query
|
||||
// limit size for AJAX requests
|
||||
var pageSize = options.pageSize || 25;
|
||||
|
||||
select.select2({
|
||||
ajax: {
|
||||
@ -377,31 +378,52 @@ function initializeRelatedField(modal, name, field, options) {
|
||||
cache: true,
|
||||
// matcher: partialMatcher,
|
||||
data: function(params) {
|
||||
|
||||
if (!params.page) {
|
||||
offset = 0;
|
||||
} else {
|
||||
offset = (params.page - 1) * pageSize;
|
||||
}
|
||||
|
||||
// Re-format search term into InvenTree API style
|
||||
return {
|
||||
search: params.term,
|
||||
offset: offset,
|
||||
limit: pageSize,
|
||||
};
|
||||
},
|
||||
processResults: function(data) {
|
||||
processResults: function(response) {
|
||||
// Convert the returned InvenTree data into select2-friendly format
|
||||
var rows = [];
|
||||
|
||||
// Only ever show the first x items
|
||||
for (var idx = 0; idx < data.length && idx < 50; idx++) {
|
||||
var row = data[idx];
|
||||
var data = [];
|
||||
|
||||
// Reformat to match select2 requirements
|
||||
row.id = row.id || row.pk;
|
||||
var more = false;
|
||||
|
||||
// TODO: Fix me?
|
||||
row.text = `This is ${field.api_url}${row.id}/`;
|
||||
if ('count' in response && 'results' in response) {
|
||||
// Response is paginated
|
||||
data = response.results;
|
||||
|
||||
rows.push(row);
|
||||
// Any more data available?
|
||||
if (response.next) {
|
||||
more = true;
|
||||
}
|
||||
|
||||
} else {
|
||||
// Non-paginated response
|
||||
data = response;
|
||||
}
|
||||
|
||||
// Each 'row' must have the 'id' attribute
|
||||
for (var idx = 0; idx < data.length; idx++) {
|
||||
data[idx].id = data[idx].pk;
|
||||
}
|
||||
|
||||
// Ref: https://select2.org/data-sources/formats
|
||||
var results = {
|
||||
results: rows,
|
||||
results: data,
|
||||
pagination: {
|
||||
more: more,
|
||||
}
|
||||
};
|
||||
|
||||
return results;
|
||||
@ -442,7 +464,7 @@ function initializeRelatedField(modal, name, field, options) {
|
||||
* - parameters: The field definition (OPTIONS) request
|
||||
* - options: Other options provided at time of modal creation by the client
|
||||
*/
|
||||
function renderModelData(name, model, data, paramaters, options) {
|
||||
function renderModelData(name, model, data, parameters, options) {
|
||||
|
||||
if (!data) {
|
||||
return '{% trans "Searching" %}...';
|
||||
@ -452,20 +474,41 @@ function renderModelData(name, model, data, paramaters, options) {
|
||||
|
||||
var html = null;
|
||||
|
||||
var renderer = null;
|
||||
|
||||
// Find a custom renderer
|
||||
switch (model) {
|
||||
case 'company':
|
||||
html = `<span>${data.name}</span> - <i>${data.description}</i>`;
|
||||
renderer = renderCompany;
|
||||
break;
|
||||
case 'stockitem':
|
||||
renderer = renderStockItem;
|
||||
break;
|
||||
case 'stocklocation':
|
||||
renderer = renderStockLocation;
|
||||
break;
|
||||
case 'part':
|
||||
renderer = renderPart;
|
||||
break;
|
||||
case 'partcategory':
|
||||
renderer = renderPartCategory;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (renderer != null) {
|
||||
html = renderer(name, data, parameters, options);
|
||||
}
|
||||
|
||||
if (html != null) {
|
||||
// Render HTML to an object
|
||||
var $state = $(html);
|
||||
return $state;
|
||||
} else {
|
||||
console.log(`ERROR: Rendering not implemented for model '${model}'`);
|
||||
// Simple text rendering
|
||||
return data.text;
|
||||
return data.id;
|
||||
}
|
||||
}
|
||||
|
||||
|
83
InvenTree/templates/js/model_renderers.js
Normal file
83
InvenTree/templates/js/model_renderers.js
Normal file
@ -0,0 +1,83 @@
|
||||
/*
|
||||
* 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.
|
||||
* - options: User options provided by the client
|
||||
*/
|
||||
|
||||
|
||||
// Renderer for "Company" model
|
||||
function renderCompany(name, data, parameters, options) {
|
||||
|
||||
var html = `<span>${data.name}</span> - <i>${data.description}</i>`;
|
||||
|
||||
return html;
|
||||
}
|
||||
|
||||
|
||||
// Renderer for "StockItem" model
|
||||
function renderStockItem(name, data, parameters, options) {
|
||||
|
||||
// TODO - Include part detail, location, quantity
|
||||
// TODO - Include part image
|
||||
}
|
||||
|
||||
|
||||
// Renderer for "StockLocation" model
|
||||
function renderStockLocation(name, data, parameters, options) {
|
||||
|
||||
var html = `<span>${data.name}</span>`;
|
||||
|
||||
if (data.description) {
|
||||
html += ` - <i>${data.description}</i>`;
|
||||
}
|
||||
|
||||
if (data.pathstring) {
|
||||
html += `<p><small>${data.pathstring}</small></p>`;
|
||||
}
|
||||
|
||||
return html;
|
||||
}
|
||||
|
||||
|
||||
// Renderer for "Part" model
|
||||
function renderPart(name, data, parameters, options) {
|
||||
|
||||
var image = data.image;
|
||||
|
||||
if (!image) {
|
||||
image = `/static/img/blank_image.png`;
|
||||
}
|
||||
|
||||
var html = `<img src='${image}' class='select2-thumbnail'>`;
|
||||
|
||||
html += ` <span>${data.full_name ?? data.name}</span>`;
|
||||
|
||||
if (data.description) {
|
||||
html += ` - <i>${data.description}</i>`;
|
||||
}
|
||||
|
||||
return html;
|
||||
}
|
||||
|
||||
|
||||
// Renderer for "PartCategory" model
|
||||
function renderPartCategory(name, data, parameters, options) {
|
||||
|
||||
var html = `<span>${data.name}</span>`;
|
||||
|
||||
if (data.description) {
|
||||
html += ` - <i>${data.description}</i>`;
|
||||
}
|
||||
|
||||
if (data.pathstring) {
|
||||
html += `<p><small>${data.pathstring}</small></p>`;
|
||||
}
|
||||
|
||||
return html;
|
||||
}
|
Loading…
Reference in New Issue
Block a user