mirror of
https://github.com/inventree/InvenTree.git
synced 2025-06-18 13:05:42 +00:00
Merge branch 'master' of github.com:inventree/InvenTree into manufacturer_part
This commit is contained in:
@ -134,14 +134,14 @@ InvenTree | {% trans "Search Results" %}
|
||||
columns: [
|
||||
{
|
||||
field: 'name',
|
||||
title: 'Name',
|
||||
title: '{% trans "Name" %}',
|
||||
formatter: function(value, row, index, field) {
|
||||
return renderLink(value, '/part/category/' + row.pk + '/');
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'description',
|
||||
title: 'Description',
|
||||
title: '{% trans "Description" %}',
|
||||
},
|
||||
],
|
||||
});
|
||||
@ -286,14 +286,14 @@ InvenTree | {% trans "Search Results" %}
|
||||
columns: [
|
||||
{
|
||||
field: 'name',
|
||||
title: 'Name',
|
||||
title: '{% trans "Name" %}',
|
||||
formatter: function(value, row, index, field) {
|
||||
return renderLink(row.pathstring, '/stock/location/' + row.pk + '/');
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'description',
|
||||
title: 'Description',
|
||||
title: '{% trans "Description" %}',
|
||||
},
|
||||
],
|
||||
});
|
||||
|
@ -8,7 +8,7 @@
|
||||
<span class='fas {{ icon }}'></span>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td><b>{{ setting.name }}</b></td>
|
||||
<td><b>{% trans setting.name %}</b></td>
|
||||
<td>
|
||||
{% if setting.is_bool %}
|
||||
<div>
|
||||
@ -24,7 +24,7 @@
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
<td>
|
||||
{{ setting.description }}
|
||||
{% trans setting.description %}
|
||||
</td>
|
||||
<td>
|
||||
<div class='btn-group float-right'>
|
||||
|
@ -25,14 +25,20 @@
|
||||
<td><span class='fas fa-hashtag'></span></td>
|
||||
<td>{% trans "Django Version" %}</td><td><a href="https://www.djangoproject.com/">{% django_version %}</a></td>
|
||||
</tr>
|
||||
{% inventree_commit_hash as hash %}
|
||||
{% if hash %}
|
||||
<tr>
|
||||
<td><span class='fas fa-code-branch'></span></td>
|
||||
<td>{% trans "Commit Hash" %}</td><td><a href="https://github.com/inventree/InvenTree/commit/{% inventree_commit_hash %}">{% inventree_commit_hash %}</a></td>
|
||||
<td>{% trans "Commit Hash" %}</td><td>{{ hash }}</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% inventree_commit_date as commit_date %}
|
||||
{% if commit_date %}
|
||||
<tr>
|
||||
<td><span class='fas fa-calendar-alt'></span></td>
|
||||
<td>{% trans "Commit Date" %}</td><td>{% inventree_commit_date %}</td>
|
||||
<td>{% trans "Commit Date" %}</td><td>{{ commit_date }}</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
<tr>
|
||||
<td><span class='fas fa-book'></span></td>
|
||||
<td>{% trans "InvenTree Documentation" %}</td>
|
||||
|
@ -134,12 +134,12 @@ InvenTree
|
||||
<script type='text/javascript' src='{% static "bootstrap-table/extensions/treegrid/bootstrap-table-treegrid.js" %}'></script>
|
||||
|
||||
<script type="text/javascript" src="{% static 'fullcalendar/main.js' %}"></script>
|
||||
<script type="text/javascript" src="{% static 'fullcalendar/locales-all.js' %}"></script>
|
||||
<script type="text/javascript" src="{% static 'script/select2/select2.js' %}"></script>
|
||||
<script type='text/javascript' src="{% static 'script/moment.js' %}"></script>
|
||||
|
||||
<script type='text/javascript' src="{% static 'script/inventree/inventree.js' %}"></script>
|
||||
<script type='text/javascript' src="{% static 'script/inventree/api.js' %}"></script>
|
||||
<script type='text/javascript' src="{% static 'script/inventree/filters.js' %}"></script>
|
||||
<script type='text/javascript' src="{% static 'script/inventree/notification.js' %}"></script>
|
||||
<script type='text/javascript' src="{% static 'script/inventree/sidenav.js' %}"></script>
|
||||
|
||||
@ -156,6 +156,7 @@ InvenTree
|
||||
<script type='text/javascript' src="{% url 'calendar.js' %}"></script>
|
||||
<script type='text/javascript' src="{% url 'tables.js' %}"></script>
|
||||
<script type='text/javascript' src="{% url 'table_filters.js' %}"></script>
|
||||
<script type='text/javascript' src="{% url 'filters.js' %}"></script>
|
||||
|
||||
<script type='text/javascript' src="{% static 'fontawesome/js/solid.js' %}"></script>
|
||||
<script type='text/javascript' src="{% static 'fontawesome/js/brands.js' %}"></script>
|
||||
@ -180,6 +181,7 @@ $(document).ready(function () {
|
||||
});
|
||||
{% endif %}
|
||||
|
||||
moment.locale('{{request.LANGUAGE_CODE}}');
|
||||
});
|
||||
|
||||
</script>
|
||||
|
419
InvenTree/templates/js/filters.js
Normal file
419
InvenTree/templates/js/filters.js
Normal file
@ -0,0 +1,419 @@
|
||||
{% load i18n %}
|
||||
|
||||
/**
|
||||
* 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
|
||||
* persistent for a given table type.
|
||||
*
|
||||
* This makes use of the 'inventreeSave' and 'inventreeLoad' functions
|
||||
* for writing to and reading from session storage.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
function defaultFilters() {
|
||||
return {
|
||||
stock: "cascade=1&in_stock=1",
|
||||
build: "",
|
||||
parts: "cascade=1",
|
||||
company: "",
|
||||
salesorder: "",
|
||||
purchaseorder: "",
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 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'
|
||||
*/
|
||||
function loadTableFilters(tableKey) {
|
||||
|
||||
var lookup = "table-filters-" + tableKey.toLowerCase();
|
||||
|
||||
var defaults = defaultFilters()[tableKey] || '';
|
||||
|
||||
var filterstring = inventreeLoad(lookup, defaults);
|
||||
|
||||
var filters = {};
|
||||
|
||||
filterstring.split("&").forEach(function(item, index) {
|
||||
item = item.trim();
|
||||
|
||||
if (item.length > 0) {
|
||||
var f = item.split('=');
|
||||
|
||||
if (f.length == 2) {
|
||||
filters[f[0]] = f[1];
|
||||
} else {
|
||||
console.log(`Improperly formatted filter: ${item}`);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return filters;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Save table filters to session storage
|
||||
*
|
||||
* @param {*} tableKey - string key for the given table
|
||||
* @param {*} filters - object of string:string pairs
|
||||
*/
|
||||
function saveTableFilters(tableKey, filters) {
|
||||
var lookup = "table-filters-" + tableKey.toLowerCase();
|
||||
|
||||
var strings = [];
|
||||
|
||||
for (var key in filters) {
|
||||
strings.push(`${key.trim()}=${String(filters[key]).trim()}`);
|
||||
}
|
||||
|
||||
var filterstring = strings.join('&');
|
||||
|
||||
inventreeSave(lookup, filterstring);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Remove a named filter parameter
|
||||
*/
|
||||
function removeTableFilter(tableKey, filterKey) {
|
||||
|
||||
var filters = loadTableFilters(tableKey);
|
||||
|
||||
delete filters[filterKey];
|
||||
|
||||
saveTableFilters(tableKey, filters);
|
||||
|
||||
// Return a copy of the updated filters
|
||||
return filters;
|
||||
}
|
||||
|
||||
|
||||
function addTableFilter(tableKey, filterKey, filterValue) {
|
||||
|
||||
var filters = loadTableFilters(tableKey);
|
||||
|
||||
filters[filterKey] = filterValue;
|
||||
|
||||
saveTableFilters(tableKey, filters);
|
||||
|
||||
// Return a copy of the updated filters
|
||||
return filters;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Clear all the custom filters for a given table
|
||||
*/
|
||||
function clearTableFilters(tableKey) {
|
||||
saveTableFilters(tableKey, {});
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Return a list of the "available" filters for a given table key.
|
||||
* A filter is "available" if it is not already being used to filter the table.
|
||||
* Once a filter is selected, it will not be returned here.
|
||||
*/
|
||||
function getRemainingTableFilters(tableKey) {
|
||||
|
||||
var filters = loadTableFilters(tableKey);
|
||||
|
||||
var remaining = getAvailableTableFilters(tableKey);
|
||||
|
||||
for (var key in filters) {
|
||||
// Delete the filter if it is already in use
|
||||
delete remaining[key];
|
||||
}
|
||||
|
||||
return remaining;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Return the filter settings for a given table and key combination.
|
||||
* Return empty object if the combination does not exist.
|
||||
*/
|
||||
function getFilterSettings(tableKey, filterKey) {
|
||||
|
||||
return getAvailableTableFilters(tableKey)[filterKey] || {};
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Return a set of key:value options for the given filter.
|
||||
* If no options are specified (e.g. for a number field),
|
||||
* then a null object is returned.
|
||||
*/
|
||||
function getFilterOptionList(tableKey, filterKey) {
|
||||
|
||||
var settings = getFilterSettings(tableKey, filterKey);
|
||||
|
||||
if (settings.type == 'bool') {
|
||||
return {
|
||||
'1': {
|
||||
key: '1',
|
||||
value: 'true',
|
||||
},
|
||||
'0': {
|
||||
key: '0',
|
||||
value: 'false',
|
||||
},
|
||||
};
|
||||
} else if ('options' in settings) {
|
||||
return settings.options;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Generate a list of <option> tags for the given table.
|
||||
*/
|
||||
function generateAvailableFilterList(tableKey) {
|
||||
|
||||
var remaining = getRemainingTableFilters(tableKey);
|
||||
|
||||
var id = 'filter-tag-' + tableKey.toLowerCase();
|
||||
|
||||
var html = `<select class='form-control filter-input' id='${id}' name='tag'>`;
|
||||
|
||||
html += "<option value=''>{% trans 'Select filter' %}</option>";
|
||||
|
||||
for (var opt in remaining) {
|
||||
var title = getFilterTitle(tableKey, opt);
|
||||
html += `<option value='${opt}'>${title}</option>`;
|
||||
}
|
||||
|
||||
html += `</select>`;
|
||||
|
||||
return html;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Generate an input for setting the value of a given filter.
|
||||
*/
|
||||
function generateFilterInput(tableKey, filterKey) {
|
||||
|
||||
var id = 'filter-value-' + tableKey.toLowerCase();
|
||||
|
||||
if (filterKey == null || filterKey.length == 0) {
|
||||
// Return an 'empty' element
|
||||
return `<div class='filter-input' id='${id}'></div>`;
|
||||
}
|
||||
|
||||
var options = getFilterOptionList(tableKey, filterKey);
|
||||
|
||||
var html = '';
|
||||
|
||||
// A 'null' options list means that a simple text-input dialog should be used
|
||||
if (options == null) {
|
||||
html = `<input class='form-control filter-input' id='${id}' name='value'></input>`;
|
||||
} else {
|
||||
// Return a 'select' input with the available values
|
||||
html = `<select class='form-control filter-input' id='${id}' name='value'>`;
|
||||
|
||||
for (var key in options) {
|
||||
option = options[key];
|
||||
html += `<option value='${key}'>${option.value}</option>`;
|
||||
}
|
||||
|
||||
html += `</select>`;
|
||||
}
|
||||
|
||||
return html;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
function setupFilterList(tableKey, table, target) {
|
||||
|
||||
var addClicked = false;
|
||||
|
||||
if (target == null || target.length == 0) {
|
||||
target = `#filter-list-${tableKey}`;
|
||||
}
|
||||
|
||||
var tag = `filter-tag-${tableKey}`;
|
||||
var add = `filter-add-${tableKey}`;
|
||||
var clear = `filter-clear-${tableKey}`;
|
||||
var make = `filter-make-${tableKey}`;
|
||||
|
||||
var filters = loadTableFilters(tableKey);
|
||||
|
||||
var element = $(target);
|
||||
|
||||
// One blank slate, please
|
||||
element.empty();
|
||||
|
||||
element.append(`<button id='${add}' title='{% trans "Add new filter" %}' class='btn btn-default filter-tag'><span class='fas fa-filter'></span></button>`);
|
||||
|
||||
if (Object.keys(filters).length > 0) {
|
||||
element.append(`<button id='${clear}' title='{% trans "Clear all filters" %}' class='btn btn-default filter-tag'><span class='fas fa-trash-alt'></span></button>`);
|
||||
}
|
||||
|
||||
for (var key in filters) {
|
||||
var value = getFilterOptionValue(tableKey, key, filters[key]);
|
||||
var title = getFilterTitle(tableKey, key);
|
||||
var description = getFilterDescription(tableKey, key);
|
||||
|
||||
element.append(`<div title='${description}' class='filter-tag'>${title} = ${value}<span ${tag}='${key}' class='close'>x</span></div>`);
|
||||
}
|
||||
|
||||
// Add a callback for adding a new filter
|
||||
element.find(`#${add}`).click(function clicked() {
|
||||
|
||||
if (!addClicked) {
|
||||
|
||||
addClicked = true;
|
||||
|
||||
var html = '';
|
||||
|
||||
//`<div class='filter-input'>`;
|
||||
|
||||
html += generateAvailableFilterList(tableKey);
|
||||
html += generateFilterInput(tableKey);
|
||||
|
||||
html += `<button title='{% trans "Create filter" %}' class='btn btn-default filter-tag' id='${make}'><span class='fas fa-plus'></span></button>`;
|
||||
|
||||
//html += '</div>';
|
||||
|
||||
element.append(html);
|
||||
|
||||
// Add a callback for when the filter tag selection is changed
|
||||
element.find(`#filter-tag-${tableKey}`).on('change', function() {
|
||||
var list = element.find(`#filter-value-${tableKey}`);
|
||||
|
||||
list.replaceWith(generateFilterInput(tableKey, this.value));
|
||||
});
|
||||
|
||||
// Add a callback for when the new filter is created
|
||||
element.find(`#filter-make-${tableKey}`).click(function() {
|
||||
var tag = element.find(`#filter-tag-${tableKey}`).val();
|
||||
var val = element.find(`#filter-value-${tableKey}`).val();
|
||||
|
||||
// Only add the new filter if it is not empty!
|
||||
if (tag && tag.length > 0) {
|
||||
var filters = addTableFilter(tableKey, tag, val);
|
||||
reloadTable(table, filters);
|
||||
|
||||
// Run this function again
|
||||
setupFilterList(tableKey, table, target);
|
||||
}
|
||||
|
||||
});
|
||||
} else {
|
||||
addClicked = false;
|
||||
|
||||
setupFilterList(tableKey, table, target);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
// Add a callback for clearing all the filters
|
||||
element.find(`#${clear}`).click(function() {
|
||||
var filters = clearTableFilters(tableKey);
|
||||
|
||||
reloadTable(table, filters);
|
||||
|
||||
setupFilterList(tableKey, table, target);
|
||||
});
|
||||
|
||||
// Add callback for deleting each filter
|
||||
element.find(".close").click(function(event) {
|
||||
var me = $(this);
|
||||
|
||||
var filter = me.attr(`filter-tag-${tableKey}`);
|
||||
|
||||
var filters = removeTableFilter(tableKey, filter);
|
||||
|
||||
reloadTable(table, filters);
|
||||
|
||||
// Run this function again!
|
||||
setupFilterList(tableKey, table, target);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 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);
|
||||
return settings.title || filterKey;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the pretty description for the given table and filter selection
|
||||
*/
|
||||
function getFilterDescription(tableKey, filterKey) {
|
||||
var settings = getFilterSettings(tableKey, filterKey);
|
||||
|
||||
return settings.title;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return a description for the given table and filter selection.
|
||||
*/
|
||||
function getFilterDescription(tableKey, filterKey) {
|
||||
var settings = getFilterSettings(tableKey, filterKey);
|
||||
return settings.description || filterKey;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Return the display value for a particular option
|
||||
*/
|
||||
function getFilterOptionValue(tableKey, filterKey, valueKey) {
|
||||
|
||||
var filter = getFilterSettings(tableKey, filterKey);
|
||||
|
||||
var value = String(valueKey);
|
||||
|
||||
// Lookup for boolean options
|
||||
if (filter.type == 'bool') {
|
||||
if (value == '1') return 'true';
|
||||
if (value == '0') return 'false';
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
// Iterate through a list of options
|
||||
if ('options' in filter) {
|
||||
for (var key in filter.options) {
|
||||
|
||||
if (key == valueKey) {
|
||||
return filter.options[key].value;
|
||||
}
|
||||
}
|
||||
|
||||
// Could not find a match
|
||||
return value;
|
||||
}
|
||||
|
||||
// Cannot map to a display string - return the original text
|
||||
return value;
|
||||
}
|
||||
|
@ -253,7 +253,7 @@ function loadingMessageContent() {
|
||||
*/
|
||||
|
||||
// TODO - This can be made a lot better
|
||||
return "<span class='glyphicon glyphicon-refresh glyphicon-refresh-animate'></span> Waiting for server...";
|
||||
return "<span class='glyphicon glyphicon-refresh glyphicon-refresh-animate'></span> {% trans 'Waiting for server...' %}";
|
||||
}
|
||||
|
||||
|
||||
|
@ -976,8 +976,8 @@ function loadStockTrackingTable(table, options) {
|
||||
formatter: function(value, row, index, field) {
|
||||
// Manually created entries can be edited or deleted
|
||||
if (!row.system) {
|
||||
var bEdit = "<button title='Edit tracking entry' class='btn btn-entry-edit btn-default btn-glyph' type='button' url='/stock/track/" + row.pk + "/edit/'><span class='fas fa-edit'/></button>";
|
||||
var bDel = "<button title='Delete tracking entry' class='btn btn-entry-delete btn-default btn-glyph' type='button' url='/stock/track/" + row.pk + "/delete/'><span class='fas fa-trash-alt icon-red'/></button>";
|
||||
var bEdit = "<button title='{% trans 'Edit tracking entry' %}' class='btn btn-entry-edit btn-default btn-glyph' type='button' url='/stock/track/" + row.pk + "/edit/'><span class='fas fa-edit'/></button>";
|
||||
var bDel = "<button title='{% trans 'Delete tracking entry' %}' class='btn btn-entry-delete btn-default btn-glyph' type='button' url='/stock/track/" + row.pk + "/delete/'><span class='fas fa-trash-alt icon-red'/></button>";
|
||||
|
||||
return "<div class='btn-group' role='group'>" + bEdit + bDel + "</div>";
|
||||
} else {
|
||||
|
@ -1 +1 @@
|
||||
<button type='button' class='btn btn-default' id='show-qr-code' title='Show QR code'><span class='fas fa-qrcode'></span></button>
|
||||
<button type='button' class='btn btn-default' id='show-qr-code' title='{% trans "Show QR Code" %}'><span class='fas fa-qrcode'></span></button>
|
Reference in New Issue
Block a user