Display results for parts and stock items

- Use the existing rendering functions
This commit is contained in:
Oliver Walters 2022-03-29 22:35:47 +11:00
parent 51d26b1d16
commit 78e5a685dc
4 changed files with 118 additions and 34 deletions

View File

@ -1018,4 +1018,30 @@ input[type='number']{
a {
text-decoration: none;
background-color: transparent;
}
/* Quicksearch Panel */
.search-result-panel {
max-width: 800px;
width: 50%
}
.search-result-group {
padding: 5px;
border: 1px solid var(--border-color);
margin-bottom: 10px;
}
.search-result-group-buttons > button{
padding: 2px;
padding-left: 5px;
padding-right: 5px;
font-size: 80%;
}
.search-result-entry {
border-top: 1px solid var(--border-color);
padding: 3px;
margin-top: 3px;
}

View File

@ -31,7 +31,7 @@
// Renderer for "Company" model
// eslint-disable-next-line no-unused-vars
function renderCompany(name, data, parameters, options) {
function renderCompany(name, data, parameters={}, options={}) {
var html = select2Thumbnail(data.image);
@ -45,7 +45,7 @@ function renderCompany(name, data, parameters, options) {
// Renderer for "StockItem" model
// eslint-disable-next-line no-unused-vars
function renderStockItem(name, data, parameters, options) {
function renderStockItem(name, data, parameters={}, options={}) {
var image = blankImage();
@ -111,7 +111,7 @@ function renderStockItem(name, data, parameters, options) {
// Renderer for "StockLocation" model
// eslint-disable-next-line no-unused-vars
function renderStockLocation(name, data, parameters, options) {
function renderStockLocation(name, data, parameters={}, options={}) {
var level = '- '.repeat(data.level);
@ -133,7 +133,7 @@ function renderStockLocation(name, data, parameters, options) {
}
// eslint-disable-next-line no-unused-vars
function renderBuild(name, data, parameters, options) {
function renderBuild(name, data, parameters={}, options={}) {
var image = null;
@ -154,7 +154,7 @@ function renderBuild(name, data, parameters, options) {
// Renderer for "Part" model
// eslint-disable-next-line no-unused-vars
function renderPart(name, data, parameters, options) {
function renderPart(name, data, parameters={}, options={}) {
var html = select2Thumbnail(data.image);
@ -164,13 +164,14 @@ function renderPart(name, data, parameters, options) {
html += ` - <i><small>${data.description}</small></i>`;
}
var extra = '';
var stock_data = '';
// Display available part quantity
if (user_settings.PART_SHOW_QUANTITY_IN_FORMS) {
extra += partStockLabel(data);
stock_data = partStockLabel(data);
}
var extra = '';
if (!data.active) {
extra += `<span class='badge badge-right rounded-pill bg-danger'>{% trans "Inactive" %}</span>`;
}
@ -178,6 +179,7 @@ function renderPart(name, data, parameters, options) {
html += `
<span class='float-right'>
<small>
${stock_data}
${extra}
{% trans "Part ID" %}: ${data.pk}
</small>
@ -188,7 +190,7 @@ function renderPart(name, data, parameters, options) {
// Renderer for "User" model
// eslint-disable-next-line no-unused-vars
function renderUser(name, data, parameters, options) {
function renderUser(name, data, parameters={}, options={}) {
var html = `<span>${data.username}</span>`;
@ -202,7 +204,7 @@ function renderUser(name, data, parameters, options) {
// Renderer for "Owner" model
// eslint-disable-next-line no-unused-vars
function renderOwner(name, data, parameters, options) {
function renderOwner(name, data, parameters={}, options={}) {
var html = `<span>${data.name}</span>`;
@ -223,7 +225,7 @@ function renderOwner(name, data, parameters, options) {
// Renderer for "PurchaseOrder" model
// eslint-disable-next-line no-unused-vars
function renderPurchaseOrder(name, data, parameters, options) {
function renderPurchaseOrder(name, data, parameters={}, options={}) {
var html = '';
var prefix = global_settings.PURCHASEORDER_REFERENCE_PREFIX;
@ -257,7 +259,7 @@ function renderPurchaseOrder(name, data, parameters, options) {
// Renderer for "SalesOrder" model
// eslint-disable-next-line no-unused-vars
function renderSalesOrder(name, data, parameters, options) {
function renderSalesOrder(name, data, parameters={}, options={}) {
var html = `<span>${data.reference}</span>`;
if (data.description) {
@ -277,7 +279,7 @@ function renderSalesOrder(name, data, parameters, options) {
// Renderer for "SalesOrderShipment" model
// eslint-disable-next-line no-unused-vars
function renderSalesOrderShipment(name, data, parameters, options) {
function renderSalesOrderShipment(name, data, parameters={}, options={}) {
var so_prefix = global_settings.SALESORDER_REFERENCE_PREFIX;
@ -294,7 +296,7 @@ function renderSalesOrderShipment(name, data, parameters, options) {
// Renderer for "PartCategory" model
// eslint-disable-next-line no-unused-vars
function renderPartCategory(name, data, parameters, options) {
function renderPartCategory(name, data, parameters={}, options={}) {
var level = '- '.repeat(data.level);
@ -310,7 +312,7 @@ function renderPartCategory(name, data, parameters, options) {
}
// eslint-disable-next-line no-unused-vars
function renderPartParameterTemplate(name, data, parameters, options) {
function renderPartParameterTemplate(name, data, parameters={}, options={}) {
var units = '';
@ -326,7 +328,7 @@ function renderPartParameterTemplate(name, data, parameters, options) {
// Renderer for "ManufacturerPart" model
// eslint-disable-next-line no-unused-vars
function renderManufacturerPart(name, data, parameters, options) {
function renderManufacturerPart(name, data, parameters={}, options={}) {
var manufacturer_image = null;
var part_image = null;
@ -355,7 +357,7 @@ function renderManufacturerPart(name, data, parameters, options) {
// Renderer for "SupplierPart" model
// eslint-disable-next-line no-unused-vars
function renderSupplierPart(name, data, parameters, options) {
function renderSupplierPart(name, data, parameters={}, options={}) {
var supplier_image = null;
var part_image = null;

View File

@ -32,6 +32,11 @@ function openSearchPanel() {
panel.find('#search-input').on('keyup change', searchTextChanged);
// Callback for "clear search" button
panel.find('#search-clear').click(function() {
panel.find('#search-input').val('');
clearSearchResults();
});
}
var searchRequests = [];
@ -80,7 +85,15 @@ function updateSearch() {
},
{
success: function(response) {
addSearchResults('part', response.results, '{% trans "Parts" %}');
addSearchResults(
'part',
response.results,
'{% trans "Parts" %}',
renderPart,
{
show_stock_data: false,
}
);
}
}
));
@ -92,10 +105,19 @@ function updateSearch() {
search: searchText,
limit: 10,
offset: 0,
part_detail: true,
location_detail: true,
},
{
success: function(response) {
addSearchResults('stock', response.results, '{% trans "Stock Items" %}');
addSearchResults(
'stock',
response.results,
'{% trans "Stock Items" %}',
renderStockItem,
{
}
);
}
}
));
@ -115,7 +137,7 @@ function clearSearchResults() {
// Add a group of results to the list
function addSearchResults(key, results, title, formatter) {
function addSearchResults(key, results, title, renderFunc, renderParams={}) {
if (results.length == 0) {
// Do not display this group, as there are no results
@ -126,21 +148,48 @@ function addSearchResults(key, results, title, formatter) {
// Ensure the 'no results found' element is hidden
panel.find('#search-no-results').hide();
var results_element = panel.find('#search-results');
var header = `search-results-${key}`;
panel.find('#search-results').append(`
<div class='search-result-group' id='${header}'>
<h5>${title}</h5>
<div class='search-result-group' id='search-results-${key}'>
<div class='search-result-header' style='display: flex;'>
<h5>${title}</h5>
<span class='flex' style='flex-grow: 1;'></span>
<div class='search-result-group-buttons btn-group float-right' role='group'>
<button class='btn btn-outline-secondary' id='hide-results-${key}' title='{% trans "Minimize results" %}'>
<span class='fas fa-chevron-up'></span>
</button>
<button class='btn btn-outline-secondary' id='remove-results-${key}' title='{% trans "Remove results" %}'>
<span class='fas fa-times icon-red'></span>
</button>
</div>
</div>
<div class='collapse search-result-list' id='search-result-list-${key}'>
</div>
</div>
`);
results.forEach(function(result) {
// results_html.append(formatter(result));
var result_html = `<div class='search-result-entry'>hello result</div>`;
var html = renderFunc(key, result, renderParams);
panel.find(`#${header}`).append(result_html);
var result_html = `
<div class='search-result-entry' id='search-result-${key}-${result.pk || result.id}'>
${html}
</div>
`;
panel.find(`#search-result-list-${key}`).append(result_html);
});
}
// Expand results panel
panel.find(`#search-result-list-${key}`).toggle();
// Add callback for "toggle" button
panel.find(`#hide-results-${key}`).click(function() {
panel.find(`#search-result-list-${key}`).toggle();
});
// Add callback for "remove" button
panel.find(`#remove-results-${key}`).click(function() {
panel.find(`#search-results-${key}`).remove();
});
}

View File

@ -1,14 +1,21 @@
{% load i18n %}
<div class="offcanvas offcanvas-end" tabindex="-1" id="offcanvas-search" data-bs-scroll="true" aria-labelledby="offcanvas-search-label">
<div class="offcanvas offcanvas-end search-result-panel" tabindex="-1" id="offcanvas-search" data-bs-scroll="true" aria-labelledby="offcanvas-search-label">
<div class="offcanvas-header">
<div class='input-group'>
<input type="text" name='search-input' class="form-control" aria-label='{% trans "Search" %}' id="search-input" placeholder="{% trans 'Search' %}"{% if query_text %} value="{{ query }}"{% endif %}>
<button type="submit" id='search-submit' class="btn btn-secondary" title='{% trans "Search" %}'>
<span class='fas fa-search'></span>
<button id='search-clear' class='btn btn-outline-secondary' title='{% trans "Clear search" %}'>
<span class='fas fa-backspace'></span>
</button>
<!--
<button id='search-filter' class="btn btn-outline-secondary" title='{% trans "Filter results" %}'>
<span class='fas fa-filter'></span>
</button>
-->
<button id='search-close' class="btn btn-outline-secondary" data-bs-dismiss='offcanvas' title='{% trans "Close search menu" %}'>
<span class='fas fa-times icon-red'></span>
</button>
</div>
<button type="button" class="btn-close text-reset" data-bs-dismiss="offcanvas" aria-label="Close"></button>
</div>
<div class="offcanvas-body">
<div id="search-center">