2
0
mirror of https://github.com/inventree/InvenTree.git synced 2025-06-19 05:25:42 +00:00

Merge branch 'master' of https://github.com/inventree/InvenTree into plugin-2037

This commit is contained in:
Matthias
2021-10-30 18:23:09 +02:00
260 changed files with 72198 additions and 5878 deletions

View File

@ -7,24 +7,14 @@
{% inventree_title %} | {% trans "Index" %}
{% endblock %}
{% block content %}
<h3>{% inventree_title %} </h3>
<hr>
<div class='col-sm-3' id='item-panel'>
<div class='panel panel-default panel-inventree'>
<ul class='list-group' id='action-item-list'>
</ul>
</div>
</div>
<div class='col-sm-9' id='details-panel'>
<ul class='list-group' id='detail-item-list'>
<li class='list-group-item panel panel-default panel-inventree'>
<div class='container'>
<img class='index-bg' src='{% static "img/inventree.png" %}'>
</div>
</li>
</ul>
{% block sidebar %}
<!-- Sidebar data is filled dynamically for the index page-->
{% endblock %}
{% block content %}
<div id='detail-panels'>
</div>
{% endblock %}
@ -34,63 +24,51 @@
{{ block.super }}
function addHeaderTitle(title) {
// Add a header block to the action list
$("#action-item-list").append(
`<li class='list-group-item'><strong>${title}</strong></li>`
);
addSidebarHeader({
text: title,
});
}
function addHeaderAction(label, title, icon, options) {
// Add an action block to the action list
$("#action-item-list").append(
`<li class='list-group-item' id='action-${label}'>
<a href='#'>
<span class='fas ${icon}'></span>
${title}
</a>
<span class='badge' id='badge-${label}'>
<span class='fas fa-spin fa-spinner'></span>
</span>
</li>`
);
// Construct a "badge" to add to the sidebar item
var badge = `
<span id='sidebar-badge-${label}' class='sidebar-item-badge badge rounded-pill badge-right bg-dark'>
<span class='fas fa-spin fa-spinner'></span>
</span>
`;
addSidebarItem({
label: label,
text: title,
icon: icon,
content_after: badge
});
// Add a detail item to the detail item-panel
$("#detail-item-list").append(
`<li class='list-group-item panel panel-default panel-inventree' id='detail-${label}'>
<h4>${title}</h4>
<table class='table table-condensed table-striped' id='table-${label}'></table>
</li>`
$("#detail-panels").append(
`<div class='panel panel-inventree panel-hidden' id='panel-${label}'>
<div class='panel-heading'>
<h4>${title}</h4>
</div>
<div class='panel-content'>
<table class='table table-condensed table-striped' id='table-${label}'></table>
</div>
</div>`
);
$(`#detail-${label}`).hide();
$(`#action-${label}`).click(function() {
// Hide all child elements
$('#detail-item-list').children('li').each(function() {
$(this).hide();
});
// Show the one we want
$(`#detail-${label}`).fadeIn();
// Remove css class from all action items
$("#action-item-list").children('li').each(function() {
$(this).removeClass('index-action-selected');
});
// Add css class to the action we are interested in
$(`#action-${label}`).addClass('index-action-selected');
});
// Connect a callback to the table
$(`#table-${label}`).on('load-success.bs.table', function() {
var count = $(`#table-${label}`).bootstrapTable('getData').length;
$(`#badge-${label}`).html(count);
var badge = $(`#sidebar-badge-${label}`);
badge.html(count);
if (count > 0) {
$(`#badge-${label}`).addClass('badge-orange');
badge.removeClass('bg-dark');
badge.addClass('bg-primary');
}
});
}
@ -316,4 +294,11 @@ loadSalesOrderTable("#table-so-overdue", {
{% endif %}
{% endblock %}
enableSidebar(
'index',
{
hide_toggle: true,
}
);
{% endblock %}

View File

@ -10,35 +10,19 @@
{% block content %}
<h3>
{% trans "Search Results" %}
</h3>
<div class="container" style='width: 100%'>
{% include "search_form.html" with query_text=query %}
</div>
{% if query %}
{% else %}
<div id='empty-search-query'>
<h4><em>{% trans "Enter a search query" %}</em></h4>
</div>
{% endif %}
<div class='col-sm-3' id='item-panel'>
<div class='panel panel-default panel-inventree'>
<ul class='list-group' id='search-item-list'>
</ul>
<div class='panel panel-inventree'>
<div class='panel-content'>
{% include "search_form.html" with query_text=query %}
{% if query %}
{% else %}
<div id='empty-search-query'>
<h4><em>{% trans "Enter a search query" %}</em></h4>
</div>
{% endif %}
</div>
</div>
<div class='col-sm-9' id='details-panel'>
<ul class='list-group' id='search-result-list'>
<li class='list-group-item panel panel-default panel-inventree'>
<div class='container'>
<img class='index-bg' src='{% static "img/inventree.png" %}'>
</div>
</li>
</ul>
<div id='detail-panels'>
</div>
{% endblock %}
@ -47,65 +31,50 @@
{{ block.super }}
function addItemTitle(title) {
// Add header block to the results list
$('#search-item-list').append(
`<li class='list-group-item'><strong>${title}</strong></li>`
);
addSidebarHeader({
text: title,
});
}
function addItem(label, title, icon, options) {
// Add a search itme to the action list
$('#search-item-list').append(
`<li class='list-group-item' id='search-item-${label}'>
<a href='#'>
<span class='fas ${icon}'></span>
${title}
</a>
<span class='badge' id='badge-${label}'>
<span class='fas fa-spin fa-spinner'></span>
</span>
</li>`
);
// Construct a "badge" to add to the sidebar item
var badge = `
<span id='sidebar-badge-${label}' class='sidebar-item-badge badge rounded-pill badge-right bg-dark'>
<span class='fas fa-spin fa-spinner'></span>
</span>
`;
addSidebarItem({
label: label,
text: title,
icon: icon,
content_after: badge
});
// Add a results table
$('#search-result-list').append(
`<li class='list-group-item panel panel-default panel-inventree' id='search-result-${label}'>
<h4>${title}</h4>
<table class='table table-condensed table-striped' id='table-${label}'></table>
</li>`
$('#detail-panels').append(
`<div class='panel panel-inventree panel-hidden' id='panel-${label}'>
<div class='panel-heading'>
<h4>${title}</h4>
</div>
<div class='panel-content'>
<table class='table table-condensed table-striped' id='table-${label}'></table>
</div>
</div>`
);
// Hide the results table
$(`#search-result-${label}`).hide();
// Add callback when the action is clicked
$(`#search-item-${label}`).click(function() {
// Hide all childs
$('#search-result-list').children('li').each(function() {
$(this).hide();
});
// Show the one we want
$(`#search-result-${label}`).fadeIn();
// Remove css class from all action items
$("#search-item-list").children('li').each(function() {
$(this).removeClass('index-action-selected');
});
// Add css class to the action we are interested in
$(`#search-item-${label}`).addClass('index-action-selected');
});
// Connect a callback to the table
$(`#table-${label}`).on('load-success.bs.table', function() {
var count = $(`#table-${label}`).bootstrapTable('getData').length;
$(`#badge-${label}`).html(count);
var badge = $(`#sidebar-badge-${label}`);
badge.html(count);
if (count > 0) {
$(`#badge-${label}`).addClass('badge-orange');
badge.removeClass('bg-dark');
badge.addClass('bg-primary');
}
});
}
@ -260,7 +229,11 @@
{% endif %}
enableSidebar(
'search',
{
hide_toggle: 'true',
}
);
{% endblock %}
{% endblock %}

View File

@ -11,7 +11,6 @@
{% block content %}
<table class='table table-striped table-condensed'>
{% include "InvenTree/settings/header.html" %}
<tbody>
{% include "InvenTree/settings/setting.html" with key="BARCODE_ENABLE" icon="fa-qrcode" %}
</tbody>

View File

@ -11,7 +11,6 @@
{% block content %}
<table class='table table-striped table-condensed'>
{% include "InvenTree/settings/header.html" %}
<tbody>
{% include "InvenTree/settings/setting.html" with key="BUILDORDER_REFERENCE_PREFIX" %}
{% include "InvenTree/settings/setting.html" with key="BUILDORDER_REFERENCE_REGEX" %}

View File

@ -11,7 +11,6 @@
{% block content %}
<table class='table table-striped table-condensed'>
{% include "InvenTree/settings/header.html" %}
<tbody>
{% include "InvenTree/settings/setting.html" with key="INVENTREE_DEFAULT_CURRENCY" icon="fa-globe" %}
</tbody>
@ -45,7 +44,7 @@
<form action='{% url "settings-currencies-refresh" %}' method='post'>
<div id='refresh-rates-form'>
{% csrf_token %}
<button type='submit' id='update-rates' class='btn btn-default float-right'>{% trans "Update Now" %}</button>
<button type='submit' id='update-rates' class='btn btn-outline-secondary float-right'>{% trans "Update Now" %}</button>
</div>
</form>
</td>

View File

@ -12,7 +12,6 @@
{% block content %}
<table class='table table-striped table-condensed'>
{% include "InvenTree/settings/header.html" %}
<tbody>
{% include "InvenTree/settings/setting.html" with key="INVENTREE_INSTANCE" icon="fa-info-circle" %}
{% include "InvenTree/settings/setting.html" with key="INVENTREE_INSTANCE_TITLE" icon="fa-info-circle" %}

View File

@ -1,12 +0,0 @@
{% load i18n %}
<col width='25'>
<thead>
<tr>
<th></th>
<th>{% trans "Setting" %}</th>
<th>{% trans "Value" %}</th>
<th>{% trans "Description" %}</th>
<th></th>
</tr>
</thead>

View File

@ -12,7 +12,6 @@
{% block content %}
<table class='table table-striped table-condensed'>
{% include "InvenTree/settings/header.html" %}
<tbody>
{% include "InvenTree/settings/setting.html" with key="LOGIN_ENABLE_SSO" icon="fa-info-circle" %}
{% include "InvenTree/settings/setting.html" with key="LOGIN_ENABLE_PWD_FORGOT" icon="fa-info-circle" %}

View File

@ -1,156 +0,0 @@
{% load i18n %}
{% load plugin_extras %}
<ul class='list-group'>
<li class='list-group-item'>
<a href='#' id='item-menu-toggle'>
<span class='menu-tab-icon fas fa-expand-arrows-alt'></span>
</a>
</li>
<li class='list-group-item'>
<span class='fas fa-user'></span> <strong>{% trans "User Settings" %}</strong>
</li>
<li class='list-group-item' title='{% trans "Account" %}'>
<a href='#' class='nav-toggle' id='select-account'>
<span class='fas fa-user-cog'></span> {% trans "Account" %}
</a>
</li>
<li class='list-group-item' title='{% trans "Home Page" %}'>
<a href='#' class='nav-toggle' id='select-user-home'>
<span class='fas fa-home'></span> {% trans "Home Page" %}
</a>
</li>
<li class='list-group-item' title='{% trans "Search" %}'>
<a href='#' class='nav-toggle' id='select-user-search'>
<span class='fas fa-search'></span> {% trans "Search" %}
</a>
</li>
<li class='list-group-item' title='{% trans "Labels" %}'>
<a href='#' class='nav-toggle' id='select-user-labels'>
<span class='fas fa-tag'></span> {% trans "Labels" %}
</a>
</li>
<li class='list-group-item' title='{% trans "Reports" %}'>
<a href='#' class='nav-toggle' id='select-user-reports'>
<span class='fas fa-file-pdf'></span> {% trans "Reports" %}
</a>
</li>
<li class='list-group-item' title='{% trans "Forms" %}'>
<a href='#' class='nav-toggle' id='select-user-forms'>
<span class='fas fa-table'></span>{% trans "Forms" %}
</a>
</li>
<!--
<li class='list-group-item' title='{% trans "Settings" %}'>
<a href='#' class='nav-toggle' id='select-user-settings'>
<span class='fas fa-cog'></span> {% trans "Settings" %}
</a>
</li>
-->
{% if user.is_staff %}
<li class='list-group-item'>
<span class='fas fa-cogs'></span> <strong>{% trans "Global Settings" %}</strong>
</li>
<li class='list-group-item' title='{% trans "Server" %}'>
<a href='#' class='nav-toggle' id='select-server'>
<span class='fas fa-server'></span> {% trans "Server" %}
</a>
</li>
<li class='list-group-item' title='{% trans "Login" %}'>
<a href='#' class='nav-toggle' id='select-login'>
<span class='fas fa-fingerprint'></span> {% trans "Login" %}
</a>
</li>
<li class='list-group-item' title='{% trans "Barcodes" %}'>
<a href='#' class='nav-toggle' id='select-barcodes'>
<span class='fas fa-qrcode'></span> {% trans "Barcodes" %}
</a>
</li>
<li class='list-group-item' title='{% trans "Currencies" %}'>
<a href='#' class='nav-toggle' id='select-currencies'>
<span class='fas fa-dollar-sign'></span> {% trans "Currencies" %}
</a>
</li>
<li class='list-group-item' title='{% trans "Reporting" %}'>
<a href='#' class='nav-toggle' id='select-reporting'>
<span class='fas fa-file-pdf'></span> {% trans "Reporting" %}
</a>
</li>
<li class='list-group-item' title='{% trans "Parts" %}'>
<a href='#' class='nav-toggle' id='select-parts'>
<span class='fas fa-shapes'></span> {% trans "Parts" %}
</a>
</li>
<li class='list-group-item' title='{% trans "Categories" %}'>
<a href='#' class='nav-toggle' id='select-category'>
<span class='fas fa-shapes'></span> {% trans "Categories" %}
</a>
</li>
<li class='list-group-item' title='{% trans "Stock" %}'>
<a href='#' class='nav-toggle' id='select-stock'>
<span class='fas fa-boxes'></span> {% trans "Stock" %}
</a>
</li>
<li class='list-group-item' title='{% trans "Build Orders" %}'>
<a href='#' class='nav-toggle' id='select-build-order'>
<span class='fas fa-tools'></span> {% trans "Build Orders" %}
</a>
</li>
<li class='list-group-item' title='{% trans "Purchase Orders" %}'>
<a href='#' class='nav-toggle' id='select-purchase-order'>
<span class='fas fa-shopping-cart'></span> {% trans "Purchase Orders" %}
</a>
</li>
<li class='list-group-item' title='{% trans "Sales Orders" %}'>
<a href='#' class='nav-toggle' id='select-sales-order'>
<span class='fas fa-truck'></span> {% trans "Sales Orders" %}
</a>
</li>
<li class='list-group-item'>
<strong>{% trans "Plugin Settings" %}</strong>
</li>
<li class='list-group-item' title='{% trans "Plugin" %}'>
<a href='#' class='nav-toggle' id='select-plugin'>
<span class='fas fa-plug'></span> {% trans "Plugin" %}
</a>
</li>
{% plugin_list as pl_list %}
{% for plugin_key, plugin in pl_list.items %}
{% if plugin.registered_mixins %}
<li class='list-group-item' title='{{ plugin.human_name }}'>
<a href='#' class='text-{{plugin.sign_color}} nav-toggle' id='select-plugin-{{plugin_key}}'>
{{ plugin.human_name }}
</a>
</li>
{% endif %}
{% endfor %}
{% endif %}
</ul>

View File

@ -12,7 +12,6 @@
<h4>{% trans "Part Options" %}</h4>
<table class='table table-striped table-condensed'>
{% include "InvenTree/settings/header.html" %}
<tbody>
{% include "InvenTree/settings/setting.html" with key="PART_IPN_REGEX" %}
{% include "InvenTree/settings/setting.html" with key="PART_ALLOW_DUPLICATE_IPN" %}
@ -49,7 +48,6 @@
<table class='table table-striped table-condensed'>
{% include "InvenTree/settings/header.html" %}
<tbody>
{% include "InvenTree/settings/setting.html" with key="PART_SHOW_IMPORT" icon="fa-file-upload" %}
</tbody>

View File

@ -9,7 +9,6 @@
{% block content %}
<table class='table table-striped table-condensed'>
{% include "InvenTree/settings/header.html" %}
<tbody>
{% include "InvenTree/settings/setting.html" with key="PURCHASEORDER_REFERENCE_PREFIX" %}
</tbody>

View File

@ -11,7 +11,6 @@
{% block content %}
<table class='table table-striped table-condensed'>
{% include "InvenTree/settings/header.html" %}
<tbody>
{% include "InvenTree/settings/setting.html" with key="REPORT_DEFAULT_PAGE_SIZE" %}
{% include "InvenTree/settings/setting.html" with key="REPORT_DEBUG_MODE" %}

View File

@ -16,8 +16,8 @@
<td><strong>{% trans setting.name %}</strong></td>
<td>
{% if setting.is_bool %}
<div>
<input fieldname='{{ setting.key.upper }}' id='setting-value-{{ setting.key.upper }}' type='checkbox' disabled='' {% if setting.as_bool %}checked=''{% endif %}>
<div class='form-check form-switch'>
<input class='form-check-input' fieldname='{{ setting.key.upper }}' id='setting-value-{{ setting.key.upper }}' type='checkbox' disabled='' {% if setting.as_bool %}checked=''{% endif %}>
</div>
{% else %}
<div id='setting-{{ setting.pk }}'>
@ -38,7 +38,7 @@
</td>
<td>
<div class='btn-group float-right'>
<button class='btn btn-default btn-glyph btn-edit-setting' pk='{{ setting.pk }}' setting='{{ setting.key.upper }}' title='{% trans "Edit setting" %}' {% if user_setting %}user='{{request.user.id}}'{% endif %}>
<button class='btn btn-outline-secondary btn-small btn-edit-setting' pk='{{ setting.pk }}' setting='{{ setting.key.upper }}' title='{% trans "Edit setting" %}' {% if user_setting %}user='{{request.user.id}}'{% endif %}>
<span class='fas fa-edit icon-green'></span>
</button>
</div>

View File

@ -9,8 +9,8 @@
{% inventree_title %} | {% trans "Settings" %}
{% endblock %}
{% block menubar %}
{% include "InvenTree/settings/navbar.html" %}
{% block sidebar %}
{% include "InvenTree/settings/sidebar.html" %}
{% endblock %}
{% block content %}
@ -21,7 +21,7 @@
{% include "InvenTree/settings/user_search.html" %}
{% include "InvenTree/settings/user_labels.html" %}
{% include "InvenTree/settings/user_reports.html" %}
{% include "InvenTree/settings/user_forms.html" %}
{% include "InvenTree/settings/user_display.html" %}
{% if user.is_staff %}
@ -182,8 +182,8 @@ $('#cat-param-table').inventreeTable({
title: '{% trans "Default Value" %}',
sortable: 'true',
formatter: function(value, row, index, field) {
var bEdit = "<button title='{% trans "Edit Template" %}' class='template-edit btn btn-default btn-glyph' type='button' pk='" + row.pk + "'><span class='fas fa-edit'></span></button>";
var bDel = "<button title='{% trans "Delete Template" %}' class='template-delete btn btn-default btn-glyph' type='button' pk='" + row.pk + "'><span class='fas fa-trash-alt icon-red'></span></button>";
var bEdit = "<button title='{% trans "Edit Template" %}' class='template-edit btn btn-outline-secondary' type='button' pk='" + row.pk + "'><span class='fas fa-edit'></span></button>";
var bDel = "<button title='{% trans "Delete Template" %}' class='template-delete btn btn-outline-secondary' type='button' pk='" + row.pk + "'><span class='fas fa-trash-alt icon-red'></span></button>";
var html = value
html += "<div class='btn-group float-right' role='group'>" + bEdit + bDel + "</div>";
@ -281,8 +281,8 @@ $("#param-table").inventreeTable({
},
{
formatter: function(value, row, index, field) {
var bEdit = "<button title='{% trans "Edit Template" %}' class='template-edit btn btn-default btn-glyph' type='button' pk='" + row.pk + "'><span class='fas fa-edit'></span></button>";
var bDel = "<button title='{% trans "Delete Template" %}' class='template-delete btn btn-default btn-glyph' type='button' pk='" + row.pk + "'><span class='fas fa-trash-alt icon-red'></span></button>";
var bEdit = "<button title='{% trans "Edit Template" %}' class='template-edit btn btn-outline-secondary' type='button' pk='" + row.pk + "'><span class='fas fa-edit'></span></button>";
var bDel = "<button title='{% trans "Delete Template" %}' class='template-delete btn btn-outline-secondary' type='button' pk='" + row.pk + "'><span class='fas fa-trash-alt icon-red'></span></button>";
var html = "<div class='btn-group float-right' role='group'>" + bEdit + bDel + "</div>";
@ -328,15 +328,6 @@ $("#import-part").click(function() {
launchModalForm("{% url 'api-part-import' %}?reset", {});
});
enableNavbar({
label: 'settings',
toggleId: '#item-menu-toggle',
});
attachNavCallbacks({
name: 'settings',
default: 'account'
});
enableSidebar('settings');
{% endblock %}

View File

@ -0,0 +1,41 @@
{% load i18n %}
{% load static %}
{% load inventree_extras %}
{% include "sidebar_header.html" with text="User Settings" icon='fa-user' %}
{% include "sidebar_item.html" with label='account' text="Account Settings" icon="fa-cog" %}
{% include "sidebar_item.html" with label='user-display' text="Display Settings" icon="fa-desktop" %}
{% include "sidebar_item.html" with label='user-home' text="Home Page" icon="fa-home" %}
{% include "sidebar_item.html" with label='user-search' text="Search Settings" icon="fa-search" %}
{% include "sidebar_item.html" with label='user-labels' text="Label Printing" icon="fa-tag" %}
{% include "sidebar_item.html" with label='user-reports' text="Reporting" icon="fa-file-pdf" %}
{% if user.is_staff %}
{% include "sidebar_header.html" with text="Global Settings" icon='fa-cogs' %}
{% include "sidebar_item.html" with label='server' text="Server Configuration" icon="fa-server" %}
{% include "sidebar_item.html" with label='login' text="Login Settings" icon="fa-fingerprint" %}
{% include "sidebar_item.html" with label='barcodes' text="Barcode Support" icon="fa-qrcode" %}
{% include "sidebar_item.html" with label='currencies' text="Currencies" icon="fa-dollar-sign" %}
{% include "sidebar_item.html" with label='reporting' text="Reporting" icon="fa-file-pdf" %}
{% include "sidebar_item.html" with label='parts' text="Parts" icon="fa-shapes" %}
{% include "sidebar_item.html" with label='category' text="Categories" icon="fa-sitemap" %}
{% include "sidebar_item.html" with label='stock' text="Stock" icon="fa-boxes" %}
{% include "sidebar_item.html" with label='build-order' text="Build Orders" icon="fa-tools" %}
{% include "sidebar_item.html" with label='purchase-order' text="Purchase Orders" icon="fa-shopping-cart" %}
{% include "sidebar_item.html" with label='sales-order' text="Sales Orders" icon="fa-truck" %}
{% include "sidebar_header.html" with text="Plugin Settings" %}
{% include "sidebar_item.html" with label='plugin' text="Plugin" icon="fa-plug" %}
{% plugin_list as pl_list %}
{% for plugin_key, plugin in pl_list.items %}
{% if plugin.registered_mixins %}
{% include "sidebar_item.html" with label='plugin-'|add:{{plugin_key}} text="plugin.human_name %}
{% endif %}
{% endfor %}
{% endif %}

View File

@ -10,7 +10,6 @@
{% block content %}
<table class='table table-striped table-condensed'>
{% include "InvenTree/settings/header.html" %}
<tbody>
{% include "InvenTree/settings/setting.html" with key="SALESORDER_REFERENCE_PREFIX" %}
</tbody>

View File

@ -10,7 +10,6 @@
{% block content %}
<table class='table table-striped table-condensed'>
{% include "InvenTree/settings/header.html" %}
<tbody>
{% include "InvenTree/settings/setting.html" with key="STOCK_GROUP_BY_PART" icon="fa-layer-group" %}
{% include "InvenTree/settings/setting.html" with key="STOCK_ENABLE_EXPIRY" icon="fa-stopwatch" %}

View File

@ -3,10 +3,10 @@
{% load i18n %}
{% load inventree_extras %}
{% block label %}user-forms{% endblock %}
{% block label %}user-display{% endblock %}
{% block heading %}
{% trans "Form Settings" %}
{% trans "Display Settings" %}
{% endblock %}
{% block content %}
@ -14,6 +14,7 @@
<div class='row'>
<table class='table table-striped table-condensed'>
<tbody>
{% include "InvenTree/settings/setting.html" with key="STICKY_HEADER" icon="fa-bars" user_setting=True %}
{% include "InvenTree/settings/setting.html" with key="FORMS_CLOSE_USING_ESCAPE" icon="fa-window-close" user_setting=True %}
{% include "InvenTree/settings/setting.html" with key="PART_SHOW_QUANTITY_IN_FORMS" icon="fa-hashtag" user_setting=True %}
</tbody>

View File

@ -13,7 +13,6 @@
<div class='row'>
<table class='table table-striped table-condensed'>
{% include "InvenTree/settings/header.html" %}
<tbody>
{% include "InvenTree/settings/setting.html" with key="HOMEPAGE_PART_STARRED" icon='fa-star' user_setting=True %}
{% include "InvenTree/settings/setting.html" with key="HOMEPAGE_PART_LATEST" icon='fa-history' user_setting=True %}

View File

@ -13,7 +13,6 @@
<div class='row'>
<table class='table table-striped table-condensed'>
{% include "InvenTree/settings/header.html" %}
<tbody>
{% include "InvenTree/settings/setting.html" with key="LABEL_INLINE" icon='fa-tag' user_setting=True %}
</tbody>

View File

@ -13,7 +13,6 @@
<div class='row'>
<table class='table table-striped table-condensed'>
{% include "InvenTree/settings/header.html" %}
<tbody>
{% include "InvenTree/settings/setting.html" with key="REPORT_INLINE" icon='fa-file-pdf' user_setting=True %}
</tbody>

View File

@ -13,7 +13,6 @@
<div class='row'>
<table class='table table-striped table-condensed'>
{% include "InvenTree/settings/header.html" %}
<tbody>
{% include "InvenTree/settings/setting.html" with key="SEARCH_PREVIEW_RESULTS" user_setting=True icon='fa-search' %}
{% include "InvenTree/settings/setting.html" with key="SEARCH_SHOW_STOCK_LEVELS" user_setting=True icon='fa-boxes' %}

View File

@ -13,7 +13,6 @@
<div class='row'>
<table class='table table-striped table-condensed'>
{% include "InvenTree/settings/header.html" %}
</table>
</div>

View File

@ -6,11 +6,9 @@
<div class='modal-dialog'>
<div class='modal-content'>
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
<img src="{% static 'img/inventree.png' %}" height='60' style='float: left;' alt='Inventree Logo'>
<h3>{% trans "InvenTree Version Information" %}</h3>
<img src="{% static 'img/inventree.png' %}" height='40px' style='float: left; padding-right: 25px;' alt='Inventree Logo'>
<h4>{% trans "InvenTree Version Information" %}</h4>
<button type='button' class='btn-close' data-bs-dismiss='modal' aria-label='{% trans "Close" %}'></button>
</div>
<div class='modal-form-content-wrapper'>
<div class='modal-form-content'>
@ -24,12 +22,12 @@
<a href="https://github.com/inventree/InvenTree/releases">{% inventree_version %}</a>{% include "clip.html" %}
{% inventree_is_development as dev %}
{% if dev %}
<span class='label label-blue float-right'>{% trans "Development Version" %}</span>
<span class='badge rounded-pill bg-primary'>{% trans "Development Version" %}</span>
{% else %}
{% if up_to_date %}
<span class='label label-green float-right'>{% trans "Up to Date" %}</span>
<span class='badge rounded-pill bg-success'>{% trans "Up to Date" %}</span>
{% else %}
<span class='label label-red float-right'>{% trans "Update Available" %}</span>
<span class='badge rounded-pill bg-info'>{% trans "Update Available" %}</span>
{% endif %}
{% endif %}
</td>
@ -94,7 +92,7 @@
<td>
<span style="display: none;" id="about-copy-text">{% include "version.html" %}</span>
<span class="float-right">
<button class="btn clip-btn-version" type="button" data-toggle='tooltip' title='{% trans "copy to clipboard" %}'><em class="fas fa-copy"></em> {% trans "copy version information" %}</button>
<button class="btn clip-btn-version" type="button" data-bs-toggle='tooltip' title='{% trans "copy to clipboard" %}'><em class="fas fa-copy"></em> {% trans "copy version information" %}</button>
</span>
</td>
</tr>
@ -104,7 +102,7 @@
</div>
</div>
<div class='modal-footer'>
<button type='button' class='btn btn-default' data-dismiss='modal'>{% trans "Close" %}</button>
<button type='button' class='btn btn-outline-secondary' data-bs-dismiss='modal'>{% trans "Close" %}</button>
</div>
</div>
</div>

View File

@ -15,6 +15,7 @@
<link rel="stylesheet" href="{% static 'fontawesome/css/solid.css' %}">
<link rel="stylesheet" href="{% static 'css/bootstrap_3.3.7_css_bootstrap.min.css' %}">
<link rel="stylesheet" href="{% static 'select2/css/select2.css' %}">
<link rel="stylesheet" href="{% static 'select2/css/select2-bootstrap-5-theme.css' %}">
<link rel="stylesheet" href="{% static 'css/inventree.css' %}">
<link rel="stylesheet" href="{% get_color_theme_css user.get_username %}">

View File

@ -0,0 +1,4 @@
{% load i18n %}
<button id='admin-button' title='{% trans "View in administration panel" %}' type='button' class='btn btn-primary' url='{{ url }}'>
<span class='fas fa-user-shield'></span>
</button>

View File

@ -0,0 +1,5 @@
{% load i18n %}
<button type='button' class='btn btn-success' id='new-attachment'>
<span class='fas fa-plus-circle'></span> {% trans "Add Attachment" %}
</button>

View File

@ -2,9 +2,9 @@
<div id='attachment-buttons'>
<div class='btn-group'>
<button type='button' class='btn btn-success' id='new-attachment'>
<span class='fas fa-plus-circle'></span> {% trans "Add Attachment" %}
</button>
<div class='filter-list' id='filter-list-related'>
<!-- An empty div in which the filter list will be constructed -->
</div>
</div>
</div>

View File

@ -33,15 +33,15 @@
<meta name="theme-color" content="#ffffff">
<!-- CSS -->
<link rel='stylesheet' href='{% static "treegrid/css/jquery.treegrid.css" %}'>
<link rel="stylesheet" href="{% static 'fontawesome/css/brands.css' %}">
<link rel="stylesheet" href="{% static 'fontawesome/css/solid.css' %}">
<link rel="stylesheet" href="{% static 'css/bootstrap_3.3.7_css_bootstrap.min.css' %}">
<link rel="stylesheet" href="{% static 'bootstrap/css/bootstrap.min.css' %}">
<link rel="stylesheet" href="{% static 'bootstrap-table/bootstrap-table.css' %}">
<link rel="stylesheet" href="{% static 'bootstrap-table/extensions/group-by-v2/bootstrap-table-group-by.css' %}">
<link rel="stylesheet" href="{% static 'bootstrap-table/extensions/filter-control/bootstrap-table-filter-control.css' %}">
<link rel='stylesheet' href='{% static "treegrid/css/jquery.treegrid.css" %}'>
<link rel="stylesheet" href="{% static 'fontawesome/css/brands.css' %}">
<link rel="stylesheet" href="{% static 'fontawesome/css/solid.css' %}">
<link rel="stylesheet" href="{% static 'select2/css/select2.css' %}">
<link rel="stylesheet" href="{% static 'css/bootstrap-toggle.css' %}">
<link rel="stylesheet" href="{% static 'select2/css/select2-bootstrap-5-theme.css' %}">
<link rel="stylesheet" href="{% static 'fullcalendar/main.css' %}">
<link rel="stylesheet" href="{% static 'script/jquery-ui/jquery-ui.min.css' %}">
@ -68,47 +68,41 @@
{% include "navbar.html" %}
<div class='main body wrapper'>
<div class='main body wrapper container-fluid inventree-body'>
<div class='inventree-body'>
<div class='row flex-nowrap inventree-body'>
<div class='col-auto px-1 sidebar-wrapper'>
<div id='sidebar' class='collapse collapse-horizontal show border-end' style='display: none;'>
<div id='sidebar-nav' class='list-group text-sm-start'>
<ul id='sidebar-list-group' class='list-group sidebar-list-group'>
{% block sidebar %}
<!-- Sidebar goes here -->
{% endblock %}
{% include "sidebar_toggle.html" %}
</ul>
</div>
</div>
</div>
<main class='col ps-md-2 pt-2'>
{% block breadcrumb_list %}
<div class='container-fluid navigation'>
<nav aria-label='breadcrumb'>
<ol class='breadcrumb'>
{% block breadcrumbs %}
{% endblock %}
</ol>
</nav>
</div>
{% endblock %}
<div class='containter-fluid inventree-pre-content'>
{% block pre_content %}
{% endblock %}
</div>
<div class='inventree-navs'>
<div class='sidenav sidenav-left' id='sidenav-left'>
{% block sidenav %}
<!-- Sidenav code here -->
{% endblock %}
{% block content %}
<!-- Each view fills in here.. -->
{% endblock %}
</main>
</div>
<div class='sidenav sidenav-right' id='sidenav-right'>
{% block menubar %}
<!-- Menubar code here -->
{% endblock %}
</div>
<div class="container container-fluid inventree-content" id='inventree-content'>
{% block content %}
<!-- Each view fills in here.. -->
{% endblock %}
</div>
{% block post_content %}
{% endblock %}
</div>
{% include 'modals.html' %}
{% include 'about.html' %}
{% include 'notification.html' %}
</div>
{% include 'modals.html' %}
{% include 'about.html' %}
{% include 'notification.html' %}
</div>
<!-- Scripts -->
@ -116,11 +110,9 @@
<script type='text/javascript' src="{% static 'script/jquery.form.min.js' %}"></script>
<script type='text/javascript' src="{% static 'script/jquery-ui/jquery-ui.min.js' %}"></script>
<script type="text/javascript" src="{% static 'script/bootstrap/bootstrap.min.js' %}"></script>
<script type="text/javascript" src="{% static 'bootstrap/js/bootstrap.bundle.min.js' %}"></script>
<script type='text/javascript' src="{% static 'script/bootstrap/bootstrap-treeview.js' %}"></script>
<script type='text/javascript' src="{% static 'script/bootstrap/bootstrap-toggle.js' %}"></script>
<script type='text/javascript' src="{% static 'bootstrap-table/bootstrap-table.js' %}"></script>
<script type='text/javascript' src="{% static 'bootstrap-table/bootstrap-table-en-US.min.js' %}"></script>
<!-- jquery-treegrid -->
<script type='text/javascript' src='{% static "treegrid/js/jquery.treegrid.js" %}'></script>

View File

@ -1,5 +1,5 @@
{% load i18n %}
<span class="float-right">
<button class="btn clip-btn" type="button" data-toggle='tooltip' title='{% trans "copy to clipboard" %}'><em class="fas fa-copy"></em></button>
<button class="btn clip-btn" type="button" data-bs-toggle='tooltip' title='{% trans "copy to clipboard" %}'><em class="fas fa-copy"></em></button>
</span>

View File

@ -1,6 +1,6 @@
{% load static %}
<div class='media-left' style='float: left;'>
<div style='float: left;'>
{% if hover %}
<a class='hover-icon'>
{% endif %}

View File

@ -111,7 +111,7 @@ function inventreeDocReady() {
modal.modal({
backdrop: 'static',
keyboard: 'false',
keyboard: true,
});
modal.modal('show');
@ -169,12 +169,7 @@ function inventreeDocReady() {
html += '</span>';
if (user_settings.SEARCH_SHOW_STOCK_LEVELS) {
html += partStockLabel(
item.data,
{
label_class: 'label-right',
}
);
html += partStockLabel(item.data);
}
html += '</a>';
@ -195,6 +190,13 @@ function inventreeDocReady() {
$('.brand-icon').each(function(i, obj) {
loadBrandIcon($(this), $(this).attr('brand_name'));
});
// Callback for "admin view" button
$('#admin-button').click(function() {
var url = $(this).attr('url');
location.href = url;
});
}
function isFileTransfer(transfer) {

View File

@ -2,60 +2,26 @@
*/
/* exported
attachNavCallbacks,
enableNavbar,
initNavTree,
loadTree,
activatePanel,
addSidebarHeader,
addSidebarItem,
addSidebarLink,
enableSidebar,
onPanelLoad,
*/
/*
* Attach callbacks to navigation bar elements.
*
* Searches for elements with the class 'nav-toggle'.
* A callback is added to each element,
* to display the matching panel.
*
* The 'id' of the .nav-toggle element should be of the form "select-<x>",
* and point to a matching "panel-<x>"
*/
function attachNavCallbacks(options={}) {
$('.nav-toggle').click(function() {
var el = $(this);
// Find the matching "panel" element
var panelName = el.attr('id').replace('select-', '');
activatePanel(panelName, options);
});
var panelClass = options.name || 'unknown';
/* Look for a default panel to initialize
* First preference = URL parameter e.g. ?display=part-stock
* Second preference = localStorage
* Third preference = default
*/
var defaultPanel = $.urlParam('display') || localStorage.getItem(`inventree-selected-panel-${panelClass}`) || options.default;
if (defaultPanel) {
activatePanel(defaultPanel);
}
}
function activatePanel(panelName, options={}) {
var panelClass = options.name || 'unknown';
* Activate (display) the selected panel
*/
function activatePanel(label, panel_name, options={}) {
// First, cause any other panels to "fade out"
$('.panel-visible').hide();
$('.panel-visible').removeClass('panel-visible');
// Find the target panel
var panel = `#panel-${panelName}`;
var select = `#select-${panelName}`;
var panel = `#panel-${panel_name}`;
var select = `#select-${panel_name}`;
// Check that the selected panel (and select) exist
if ($(panel).length && $(select).length) {
@ -63,22 +29,22 @@ function activatePanel(panelName, options={}) {
} else {
// Either the select or the panel are not displayed!
// Iterate through the available 'select' elements until one matches
panelName = null;
panel_name = null;
$('.nav-toggle').each(function() {
var panel_name = $(this).attr('id').replace('select-', '');
$('.sidebar-selector').each(function() {
var name = $(this).attr('id').replace('select-', '');
if ($(`#panel-${panel_name}`).length && (panelName == null)) {
panelName = panel_name;
if ($(`#panel-${name}`).length && (panel_name == null)) {
panel_name = name;
}
panel = `#panel-${panelName}`;
select = `#select-${panelName}`;
panel = `#panel-${panel_name}`;
select = `#select-${panel_name}`;
});
}
// Save the selected panel
localStorage.setItem(`inventree-selected-panel-${panelClass}`, panelName);
localStorage.setItem(`inventree-selected-panel-${label}`, panel_name);
// Display the panel
$(panel).addClass('panel-visible');
@ -93,9 +59,9 @@ function activatePanel(panelName, options={}) {
$('.list-group-item').removeClass('active');
// Find the associated selector
var selectElement = `#select-${panelName}`;
var selector = `#select-${panel_name}`;
$(selectElement).parent('.list-group-item').addClass('active');
$(selector).addClass('active');
}
@ -117,252 +83,129 @@ function onPanelLoad(panel, callback) {
});
}
function loadTree(url, tree, options={}) {
/* Load the side-nav tree view
Args:
url: URL to request tree data
tree: html ref to treeview
options:
data: data object to pass to the AJAX request
selected: ID of currently selected item
name: name of the tree
*/
var data = {};
if (options.data) {
data = options.data;
}
var key = 'inventree-sidenav-items-';
if (options.name) {
key += options.name;
}
$.ajax({
url: url,
type: 'get',
dataType: 'json',
data: data,
success: function(response) {
if (response.tree) {
$(tree).treeview({
data: response.tree,
enableLinks: true,
showTags: true,
});
if (localStorage.getItem(key)) {
var saved_exp = localStorage.getItem(key).split(',');
// Automatically expand the desired notes
for (var q = 0; q < saved_exp.length; q++) {
$(tree).treeview('expandNode', parseInt(saved_exp[q]));
}
}
// Setup a callback whenever a node is toggled
$(tree).on('nodeExpanded nodeCollapsed', function(event, data) {
// Record the entire list of expanded items
var expanded = $(tree).treeview('getExpanded');
var exp = [];
for (var i = 0; i < expanded.length; i++) {
exp.push(expanded[i].nodeId);
}
// Save the expanded nodes
localStorage.setItem(key, exp);
});
}
},
error: function(xhr, ajaxOptions, thrownError) {
// TODO
}
});
}
/**
* Initialize navigation tree display
* Enable support for sidebar on this page
*/
function initNavTree(options) {
function enableSidebar(label, options={}) {
var resize = true;
// Enable callbacks for sidebar buttons
$('.sidebar-selector').click(function() {
var el = $(this);
if ('resize' in options) {
resize = options.resize;
}
// Find the matching panel element to display
var panel_name = el.attr('id').replace('select-', '');
var label = options.label || 'nav';
var stateLabel = `${label}-tree-state`;
var widthLabel = `${label}-tree-width`;
var treeId = options.treeId || '#sidenav-left';
var toggleId = options.toggleId;
// Initially hide the tree
$(treeId).animate({
width: '0px',
}, 0, function() {
if (resize) {
$(treeId).resizable({
minWidth: '0px',
maxWidth: '500px',
handles: 'e, se',
grid: [5, 5],
stop: function(event, ui) {
var width = Math.round(ui.element.width());
if (width < 75) {
$(treeId).animate({
width: '0px'
}, 50);
localStorage.setItem(stateLabel, 'closed');
} else {
localStorage.setItem(stateLabel, 'open');
localStorage.setItem(widthLabel, `${width}px`);
}
}
});
}
var state = localStorage.getItem(stateLabel);
var width = localStorage.getItem(widthLabel) || '300px';
if (state && state == 'open') {
$(treeId).animate({
width: width,
}, 50);
}
activatePanel(label, panel_name, options);
});
// Register callback for 'toggle' button
if (toggleId) {
$(toggleId).click(function() {
/* Look for a "default" panel to initialize for this page
*
* - First preference = URL parameter e.g. ?display=part-stock
* - Second preference = local storage
* - Third preference = default
*/
var state = localStorage.getItem(stateLabel) || 'closed';
var width = localStorage.getItem(widthLabel) || '300px';
var selected_panel = $.urlParam('display') || localStorage.getItem(`inventree-selected-panel-${label}`) || options.default;
if (state == 'open') {
$(treeId).animate({
width: '0px'
}, 50);
if (selected_panel) {
activatePanel(label, selected_panel);
} else {
// Find the "first" available panel (according to the sidebar)
var selector = $('.sidebar-selector').first();
localStorage.setItem(stateLabel, 'closed');
} else {
$(treeId).animate({
width: width,
}, 50);
if (selector.exists()) {
var panel_name = selector.attr('id').replace('select-', '');
activatePanel(label, panel_name);
}
}
localStorage.setItem(stateLabel, 'open');
}
if (options.hide_toggle) {
// Hide the toggle button if specified
$('#sidebar-toggle').remove();
} else {
$('#sidebar-toggle').click(function() {
// Add callback to "collapse" and "expand" the sidebar
// 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';
setSidebarState(label, state);
// Finally, show the sidebar
$('#sidebar').show();
}
/**
* Handle left-hand icon menubar display
/*
* Set the "toggle" state of the sidebar
*/
function enableNavbar(options) {
function setSidebarState(label, state) {
var resize = true;
if ('resize' in options) {
resize = options.resize;
}
var label = options.label || 'nav';
label = `navbar-${label}`;
var stateLabel = `${label}-state`;
var widthLabel = `${label}-width`;
var navId = options.navId || '#sidenav-right';
var toggleId = options.toggleId;
// Extract the saved width for this element
$(navId).animate({
'width': '45px',
'min-width': '45px',
'display': 'block',
}, 50, function() {
// Make the navbar resizable
if (resize) {
$(navId).resizable({
minWidth: options.minWidth || '100px',
maxWidth: options.maxWidth || '500px',
handles: 'e, se',
grid: [5, 5],
stop: function(event, ui) {
// Record the new width
var width = Math.round(ui.element.width());
// Reasonably narrow? Just close it!
if (width <= 75) {
$(navId).animate({
width: '45px'
}, 50);
localStorage.setItem(stateLabel, 'closed');
} else {
localStorage.setItem(widthLabel, `${width}px`);
localStorage.setItem(stateLabel, 'open');
}
}
});
}
var state = localStorage.getItem(stateLabel);
var width = localStorage.getItem(widthLabel) || '250px';
if (state && state == 'open') {
$(navId).animate({
width: width
}, 100);
}
});
// Register callback for 'toggle' button
if (toggleId) {
$(toggleId).click(function() {
var state = localStorage.getItem(stateLabel) || 'closed';
var width = localStorage.getItem(widthLabel) || '250px';
if (state == 'open') {
$(navId).animate({
width: '45px',
minWidth: '45px',
}, 50);
localStorage.setItem(stateLabel, 'closed');
} else {
$(navId).animate({
'width': width
}, 50);
localStorage.setItem(stateLabel, 'open');
}
if (state == 'collapsed') {
$('.sidebar-item-text').animate({
'opacity': 0.0,
'font-size': '0%',
}, 100, function() {
$('.sidebar-item-text').hide();
$('#sidebar-toggle-icon').removeClass('fa-chevron-left').addClass('fa-chevron-right');
});
} else {
$('.sidebar-item-text').show();
$('#sidebar-toggle-icon').removeClass('fa-chevron-right').addClass('fa-chevron-left');
$('.sidebar-item-text').animate({
'opacity': 1.0,
'font-size': '100%',
}, 100);
}
// Save the state of this sidebar
localStorage.setItem(`inventree-menu-state-${label}`, state);
}
/*
* Dynamically construct and insert a sidebar item into the sidebar at runtime.
* This mirrors the templated code in "sidebar_item.html"
*/
function addSidebarItem(options={}) {
var html = `
<a href='#' id='select-${options.label}' title='${options.text}' class='list-group-item sidebar-list-group-item border-end-0 d-inline-block text-truncate sidebar-selector' data-bs-parent='#sidebar'>
<i class='bi bi-bootstrap'></i>
${options.content_before || ''}
<span class='sidebar-item-icon fas ${options.icon}'></span>
<span class='sidebar-item-text' style='display: none;'>${options.text}</span>
${options.content_after || ''}
</a>
`;
$('#sidebar-list-group').append(html);
}
/*
* Dynamicall construct and insert a sidebar header into the sidebar at runtime
* This mirrors the templated code in "sidebar_header.html"
*/
function addSidebarHeader(options={}) {
var html = `
<span title='${options.text}' class="list-group-item sidebar-list-group-item border-end-0 d-inline-block text-truncate" data-bs-parent="#sidebar">
<h6>
<i class="bi bi-bootstrap"></i>
<span class='sidebar-item-text' style='display: none;'>${options.text}</span>
</h6>
</span>
`;
$('#sidebar-list-group').append(html);
}

View File

@ -27,7 +27,7 @@ function loadAttachmentTable(url, options) {
return '{% trans "No attachments found" %}';
},
sortable: true,
search: false,
search: true,
queryParams: options.filters || {},
onPostBody: function() {
// Add callback for 'edit' button
@ -58,12 +58,16 @@ function loadAttachmentTable(url, options) {
var fn = value.toLowerCase();
if (fn.endsWith('.pdf')) {
if (fn.endsWith('.csv')) {
icon = 'fa-file-csv';
} else if (fn.endsWith('.pdf')) {
icon = 'fa-file-pdf';
} else if (fn.endsWith('.xls') || fn.endsWith('.xlsx')) {
icon = 'fa-file-excel';
} else if (fn.endsWith('.doc') || fn.endsWith('.docx')) {
icon = 'fa-file-word';
} else if (fn.endsWith('.zip') || fn.endsWith('.7z')) {
icon = 'fa-file-archive';
} else {
var images = ['.png', '.jpg', '.bmp', '.gif', '.svg', '.tif'];

View File

@ -407,7 +407,7 @@ function loadBomTable(table, options) {
// Display an extra icon if this part is an assembly
if (sub_part.assembly) {
var text = `<span title='{% trans "Open subassembly" %}' class='fas fa-stream label-right'></span>`;
var text = `<span title='{% trans "Open subassembly" %}' class='fas fa-stream float-right'></span>`;
html += renderLink(text, `/part/${row.sub_part}/bom/`);
}
@ -470,7 +470,7 @@ function loadBomTable(table, options) {
var text = value;
if (value == null || value <= 0) {
text = `<span class='label label-warning'>{% trans "No Stock" %}</span>`;
text = `<span class='badge rounded-pill bg-danger'>{% trans "No Stock" %}</span>`;
}
return renderLink(text, url);
@ -612,7 +612,7 @@ function loadBomTable(table, options) {
var bValidate = makeIconButton('fa-check-circle icon-green', 'bom-validate-button', row.pk, '{% trans "Validate BOM Item" %}');
var bValid = `<span title='{% trans "This line has been validated" %}' class='fas fa-check-double icon-green'/>`;
var bValid = makeIconButton('fa-check-double icon-green', 'bom-valid-button', row.pk, '{% trans "This line has been validated" %}', {disabled: true});
var bSubs = makeIconButton('fa-exchange-alt icon-blue', 'bom-substitutes-button', row.pk, '{% trans "Edit substitute parts" %}');

View File

@ -34,8 +34,8 @@ function buildFormFields() {
reference: {
prefix: global_settings.BUILDORDER_REFERENCE_PREFIX,
},
title: {},
part: {},
title: {},
quantity: {},
parent: {
filters: {
@ -937,7 +937,10 @@ function loadBuildOutputAllocationTable(buildInfo, output, options={}) {
var progress = makeProgressBar(
allocatedLines,
totalLines
totalLines,
{
max_width: '150px',
}
);
build_progress.html(progress);

View File

@ -325,15 +325,15 @@ function loadCompanyTable(table, url, options={}) {
var html = imageHoverIcon(row.image) + renderLink(value, row.url);
if (row.is_customer) {
html += `<span title='{% trans "Customer" %}' class='fas fa-user-tie label-right'></span>`;
html += `<span title='{% trans "Customer" %}' class='fas fa-user-tie float-right'></span>`;
}
if (row.is_manufacturer) {
html += `<span title='{% trans "Manufacturer" %}' class='fas fa-industry label-right'></span>`;
html += `<span title='{% trans "Manufacturer" %}' class='fas fa-industry float-right'></span>`;
}
if (row.is_supplier) {
html += `<span title='{% trans "Supplier" %}' class='fas fa-building label-right'></span>`;
html += `<span title='{% trans "Supplier" %}' class='fas fa-building float-right'></span>`;
}
return html;
@ -493,15 +493,15 @@ function loadManufacturerPartTable(table, url, options) {
var html = imageHoverIcon(row.part_detail.thumbnail) + renderLink(value, url);
if (row.part_detail.is_template) {
html += `<span class='fas fa-clone label-right' title='{% trans "Template part" %}'></span>`;
html += `<span class='fas fa-clone float-right' title='{% trans "Template part" %}'></span>`;
}
if (row.part_detail.assembly) {
html += `<span class='fas fa-tools label-right' title='{% trans "Assembled part" %}'></span>`;
html += `<span class='fas fa-tools float-right' title='{% trans "Assembled part" %}'></span>`;
}
if (!row.part_detail.active) {
html += `<span class='label label-warning label-right'>{% trans "Inactive" %}</span>`;
html += `<span class='badge badge-right rounded-pill bg-warning'>{% trans "Inactive" %}</span>`;
}
return html;
@ -750,15 +750,15 @@ function loadSupplierPartTable(table, url, options) {
var html = imageHoverIcon(row.part_detail.thumbnail) + renderLink(value, url);
if (row.part_detail.is_template) {
html += `<span class='fas fa-clone label-right' title='{% trans "Template part" %}'></span>`;
html += `<span class='fas fa-clone float-right' title='{% trans "Template part" %}'></span>`;
}
if (row.part_detail.assembly) {
html += `<span class='fas fa-tools label-right' title='{% trans "Assembled part" %}'></span>`;
html += `<span class='fas fa-tools float-right' title='{% trans "Assembled part" %}'></span>`;
}
if (!row.part_detail.active) {
html += `<span class='label label-warning label-right'>{% trans "Inactive" %}</span>`;
html += `<span class='badge badge-right rounded-pill bg-warning'>{% trans "Inactive" %}</span>`;
}
return html;

View File

@ -281,7 +281,12 @@ function setupFilterList(tableKey, table, target) {
// One blank slate, please
element.empty();
element.append(`<button id='reload-${tableKey}' title='{% trans "Reload data" %}' class='btn btn-default filter-tag'><span class='fas fa-redo-alt'></span></button>`);
element.append(`<button id='reload-${tableKey}' title='{% trans "Reload data" %}' class='btn btn-outline-secondary filter-tag'><span class='fas fa-redo-alt'></span></button>`);
// Callback for reloading the table
element.find(`#reload-${tableKey}`).click(function() {
$(table).bootstrapTable('refresh');
});
// If there are no filters defined for this table, exit now
if (jQuery.isEmptyObject(getAvailableTableFilters(tableKey))) {
@ -289,10 +294,10 @@ function setupFilterList(tableKey, table, target) {
}
// If there are filters currently "in use", add them in!
element.append(`<button id='${add}' title='{% trans "Add new filter" %}' class='btn btn-default filter-tag'><span class='fas fa-filter'></span></button>`);
element.append(`<button id='${add}' title='{% trans "Add new filter" %}' class='btn btn-outline-secondary 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-backspace icon-red'></span></button>`);
element.append(`<button id='${clear}' title='{% trans "Clear all filters" %}' class='btn btn-outline-secondary filter-tag'><span class='fas fa-backspace icon-red'></span></button>`);
}
for (var key in filters) {
@ -303,11 +308,6 @@ function setupFilterList(tableKey, table, target) {
element.append(`<div title='${description}' class='filter-tag'>${title} = ${value}<span ${tag}='${key}' class='close'>x</span></div>`);
}
// Callback for reloading the table
element.find(`#reload-${tableKey}`).click(function() {
$(table).bootstrapTable('refresh');
});
// Add a callback for adding a new filter
element.find(`#${add}`).click(function clicked() {
@ -320,7 +320,7 @@ function setupFilterList(tableKey, table, target) {
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 += `<button title='{% trans "Create filter" %}' class='btn btn-outline-secondary filter-tag' id='${make}'><span class='fas fa-plus'></span></button>`;
element.append(html);

View File

@ -2,7 +2,6 @@
{% load inventree_extras %}
/* globals
attachToggle,
createNewModal,
inventreeFormDataUpload,
inventreeGet,
@ -49,6 +48,9 @@
*
*/
// Set global default theme for select2
$.fn.select2.defaults.set('theme', 'bootstrap-5');
/*
* Return true if the OPTIONS specify that the user
* can perform a GET method at the endpoint.
@ -519,11 +521,6 @@ function constructFormBody(fields, options) {
// Attach clear callbacks (if required)
addClearCallbacks(fields, options);
attachToggle(modal);
$(modal + ' .select2-container').addClass('select-full-width');
$(modal + ' .select2-container').css('width', '100%');
modalShowSubmitButton(modal, true);
$(modal).on('click', '#modal-form-submit', function() {
@ -563,13 +560,14 @@ function insertConfirmButton(options) {
var message = options.confirmMessage || '{% trans "Confirm" %}';
var confirm = `
<span style='float: left;'>
${message}
<input id='modal-confirm' name='confirm' type='checkbox'>
</span>`;
var html = `
<div class="form-check form-switch">
<input class="form-check-input" type="checkbox" id="modal-confirm">
<label class="form-check-label" for="modal-confirm">${message}</label>
</div>
`;
$(options.modal).find('#modal-footer-buttons').append(confirm);
$(options.modal).find('#modal-footer-buttons').append(html);
// Disable the 'submit' button
$(options.modal).find('#modal-form-submit').prop('disabled', true);
@ -621,6 +619,10 @@ function submitFormData(fields, options) {
var has_files = false;
var data_valid = true;
var data_errors = {};
// Extract values for each field
for (var idx = 0; idx < options.field_names.length; idx++) {
@ -633,6 +635,21 @@ function submitFormData(fields, options) {
if (field) {
switch (field.type) {
// Ensure numerical fields are "valid"
case 'integer':
case 'float':
case 'decimal':
if (!validateFormField(name, options)) {
data_valid = false;
data_errors[name] = ['{% trans "Enter a valid number" %}'];
}
break;
default:
break;
}
var value = getFormFieldValue(name, field, options);
// Handle file inputs
@ -662,6 +679,11 @@ function submitFormData(fields, options) {
}
}
if (!data_valid) {
handleFormErrors(data_errors, fields, options);
return;
}
var upload_func = inventreePut;
if (has_files) {
@ -732,7 +754,8 @@ function updateFieldValues(fields, options) {
* Update the value of a named field
*/
function updateFieldValue(name, value, field, options) {
var el = $(options.modal).find(`#id_${name}`);
var el = getFormFieldElement(name, options);
if (!el) {
console.log(`WARNING: updateFieldValue could not find field '${name}'`);
@ -760,6 +783,46 @@ function updateFieldValue(name, value, field, options) {
}
// Find the named field element in the modal DOM
function getFormFieldElement(name, options) {
var el = $(options.modal).find(`#id_${name}`);
if (!el.exists) {
console.log(`ERROR: Could not find form element for field '${name}'`);
}
return el;
}
/*
* Check that a "numerical" input field has a valid number in it.
* 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) {
if (getFormFieldElement(name, options)) {
var el = document.getElementById(`id_${name}`);
if (el.validity.valueMissing) {
// Accept empty strings (server will validate)
return true;
} else {
return el.validity.valid;
}
} else {
return false;
}
}
/*
* Extract and field value before sending back to the server
*
@ -771,7 +834,7 @@ function updateFieldValue(name, value, field, options) {
function getFormFieldValue(name, field, options) {
// Find the HTML element
var el = $(options.modal).find(`#id_${name}`);
var el = getFormFieldElement(name, options);
if (!el) {
return null;
@ -865,7 +928,7 @@ function clearFormErrors(options) {
$(options.modal).find('.form-error-message').remove();
// Remove the "has error" class
$(options.modal).find('.has-error').removeClass('has-error');
$(options.modal).find('.form-field-error').removeClass('form-field-error');
// Hide the 'non field errors'
$(options.modal).find('#non-field-errors').html('');
@ -1038,8 +1101,8 @@ function handleFormErrors(errors, fields, options) {
*/
function addFieldErrorMessage(field_name, error_text, error_idx, options) {
// Add the 'has-error' class
$(options.modal).find(`#div_id_${field_name}`).addClass('has-error');
// Add the 'form-field-error' class
$(options.modal).find(`#div_id_${field_name}`).addClass('form-field-error');
var field_dom = $(options.modal).find(`#errors-${field_name}`);
@ -1086,7 +1149,9 @@ function addFieldCallbacks(fields, options) {
function addFieldCallback(name, field, options) {
$(options.modal).find(`#id_${name}`).change(function() {
var el = getFormFieldElement(name, options);
el.change(function() {
var value = getFormFieldValue(name, field, options);
@ -1232,7 +1297,7 @@ function addSecondaryModal(field, fields, options) {
var html = `
<span style='float: right;'>
<div type='button' class='btn btn-primary btn-secondary' title='${secondary.title || secondary.label}' id='btn-new-${name}'>
<div type='button' class='btn btn-primary btn-secondary btn-form-secondary' title='${secondary.title || secondary.label}' id='btn-new-${name}'>
${secondary.label || secondary.title}
</div>
</span>`;
@ -1299,7 +1364,7 @@ function initializeRelatedField(field, fields, options) {
}
// Find the select element and attach a select2 to it
var select = $(options.modal).find(`#id_${name}`);
var select = getFormFieldElement(name, options);
// Add a button to launch a 'secondary' modal
if (field.secondary != null) {
@ -1492,7 +1557,7 @@ function initializeRelatedField(field, fields, options) {
*/
function setRelatedFieldData(name, data, options) {
var select = $(options.modal).find(`#id_${name}`);
var select = getFormFieldElement(name, options);
var option = new Option(name, data.pk, true, true);
@ -1513,14 +1578,11 @@ function setRelatedFieldData(name, data, options) {
function initializeChoiceField(field, fields, options) {
var name = field.name;
var select = $(options.modal).find(`#id_${name}`);
var select = getFormFieldElement(field.name, options);
select.select2({
dropdownAutoWidth: false,
dropdownParent: $(options.modal),
width: '100%',
});
}
@ -1666,7 +1728,7 @@ function constructField(name, parameters, options) {
<div class='panel-heading form-panel-heading' id='form-panel-heading-${group}'>`;
if (group_options.collapsible) {
html += `
<div data-toggle='collapse' data-target='#form-panel-content-${group}'>
<div data-bs-toggle='collapse' data-bs-target='#form-panel-content-${group}'>
<a href='#'><span id='group-icon-${group}' class='fas fa-angle-up'></span>
`;
} else {
@ -1692,7 +1754,7 @@ function constructField(name, parameters, options) {
var form_classes = 'form-group';
if (parameters.errors) {
form_classes += ' has-error';
form_classes += ' form-field-error';
}
// Optional content to render before the field
@ -1734,7 +1796,7 @@ function constructField(name, parameters, options) {
html += `<div class='input-group'>`;
if (parameters.prefix) {
html += `<span class='input-group-addon'>${parameters.prefix}</span>`;
html += `<span class='input-group-text'>${parameters.prefix}</span>`;
}
}
@ -1744,7 +1806,7 @@ function constructField(name, parameters, options) {
if (!parameters.required) {
html += `
<span class='input-group-addon form-clear' id='clear_${name}' title='{% trans "Clear input" %}'>
<span class='input-group-text form-clear' id='clear_${name}' title='{% trans "Clear input" %}'>
<span class='icon-red fas fa-backspace'></span>
</span>`;
}
@ -1753,7 +1815,11 @@ function constructField(name, parameters, options) {
}
if (parameters.help_text && !options.hideLabels) {
html += constructHelpText(name, parameters, options);
// Boolean values are handled differently!
if (parameters.type != 'boolean') {
html += constructHelpText(name, parameters, options);
}
}
// Div for error messages
@ -1926,12 +1992,29 @@ function constructInputOptions(name, classes, type, parameters) {
opts.push(`placeholder='${parameters.placeholder}'`);
}
if (parameters.type == 'boolean') {
opts.push(`style='display: inline-block; width: 20px; margin-right: 20px;'`);
switch (parameters.type) {
case 'boolean':
break;
case 'integer':
case 'float':
case 'decimal':
opts.push(`step='any'`);
break;
default:
break;
}
if (parameters.multiline) {
return `<textarea ${opts.join(' ')}></textarea>`;
} else if (parameters.type == 'boolean') {
return `
<div class='form-check form-switch'>
<input ${opts.join(' ')}>
<label class='form-check-label' for=''>
<em><small>${parameters.help_text}</small></em>
</label>
</div>
`;
} else {
return `<input ${opts.join(' ')}>`;
}
@ -1955,7 +2038,7 @@ function constructCheckboxInput(name, parameters) {
return constructInputOptions(
name,
'checkboxinput',
'form-check-input',
'checkbox',
parameters
);
@ -2040,7 +2123,7 @@ function constructChoiceInput(name, parameters) {
*/
function constructRelatedFieldInput(name) {
var html = `<select id='id_${name}' class='select form-control' name='${name}' style='width: 100%;'></select>`;
var html = `<select id='id_${name}' class='select form-control' name='${name}'></select>`;
// Don't load any options - they will be filled via an AJAX request
@ -2114,13 +2197,7 @@ function constructRawInput(name, parameters) {
*/
function constructHelpText(name, parameters) {
var style = '';
if (parameters.type == 'boolean') {
style = `style='display: inline-block; margin-left: 25px' `;
}
var html = `<div id='hint_id_${name}' ${style}class='help-block'><i>${parameters.help_text}</i></div>`;
var html = `<div id='hint_id_${name}' class='help-block'><i>${parameters.help_text}</i></div>`;
return html;
}

View File

@ -16,9 +16,9 @@
function yesNoLabel(value) {
if (value) {
return `<span class='label label-green'>{% trans "YES" %}</span>`;
return `<span class='badge rounded-pill bg-success'>{% trans "YES" %}</span>`;
} else {
return `<span class='label label-yellow'>{% trans "NO" %}</span>`;
return `<span class='badge rounded-pill bg-warning'>{% trans "NO" %}</span>`;
}
}
@ -92,7 +92,7 @@ function select2Thumbnail(image) {
*/
function makeIconBadge(icon, title) {
var html = `<span class='fas ${icon} label-right' title='${title}'></span>`;
var html = `<span class='icon-badge fas ${icon} float-right' title='${title}'></span>`;
return html;
}
@ -103,7 +103,7 @@ function makeIconBadge(icon, title) {
*/
function makeIconButton(icon, cls, pk, title, options={}) {
var classes = `btn btn-default btn-glyph ${cls}`;
var classes = `btn btn-outline-secondary ${cls}`;
var id = `${cls}-${pk}`;
@ -182,8 +182,14 @@ function makeProgressBar(value, maximum, opts={}) {
var id = options.id || 'progress-bar';
var style = '';
if (opts.max_width) {
style += `max-width: ${options.max_width}; `;
}
return `
<div id='${id}' class='progress'>
<div id='${id}' class='progress' style='${style}'>
<div class='progress-bar ${extraclass}' role='progressbar' aria-valuenow='${percent}' aria-valuemin='0' aria-valuemax='100' style='width:${percent}%'></div>
<div class='progress-value'>${text}</div>
</div>

View File

@ -47,14 +47,12 @@ function createNewModal(options={}) {
<div class='modal-dialog'>
<div class='modal-content'>
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label='{% trans "Close" %}'>
<span aria-hidden="true">&times;</span>
</button>
<h3 id='modal-title'>
<h4 id='modal-title' class='modal-title'>
<!-- Form title to be injected here -->
</h3>
</h4>
<button type='button' class='btn-close' data-bs-dismiss='modal' aria-label='{% trans "Close" %}'></button>
</div>
<div class='modal-form-content-wrapper'>
<div class='modal-body modal-form-content-wrapper'>
<div id='non-field-errors'>
<!-- Form error messages go here -->
</div>
@ -73,7 +71,8 @@ function createNewModal(options={}) {
<div id='modal-footer-buttons'>
<!-- Extra buttons can be inserted here -->
</div>
<button type='button' class='btn btn-default' id='modal-form-close' data-dismiss='modal'>{% trans "Cancel" %}</button>
<span class='flex-item' style='flex-grow: 1;'></span>
<button type='button' class='btn btn-secondary' id='modal-form-close' data-bs-dismiss='modal'>{% trans "Cancel" %}</button>
<button type='button' class='btn btn-primary' id='modal-form-submit'>{% trans "Submit" %}</button>
</div>
</div>
@ -355,22 +354,6 @@ function partialMatcher(params, data) {
}
function attachToggle(modal) {
/* Attach 'bootstrap-toggle' functionality to any checkbox in the modal.
* This is simple for visual improvement,
* and also larger toggle style buttons are easier to press!
*/
$(modal).find(`input[type='checkbox']`).each(function() {
$(this).bootstrapToggle({
size: 'small',
onstyle: 'success',
offstyle: 'warning',
});
});
}
function attachSelect(modal) {
/* Attach 'select2' functionality to any drop-down list in the modal.
* Provides search filtering for dropdown items
@ -550,14 +533,14 @@ function renderErrorMessage(xhr) {
html += `
<div class='panel-group'>
<div class='panel panel-default'>
<div class='panel'>
<div class='panel panel-heading'>
<div class='panel-title'>
<a data-toggle='collapse' href="#collapse-error-info">{% trans "Show Error Information" %}</a>
<a data-bs-toggle='collapse' href="#collapse-error-info">{% trans "Show Error Information" %}</a>
</div>
</div>
<div class='panel-collapse collapse' id='collapse-error-info'>
<div class='panel-body'>`;
<div class='panel-content'>`;
html += xhr.responseText;
@ -698,7 +681,6 @@ function injectModalForm(modal, form_html) {
*/
$(modal).find('.modal-form-content').html(form_html);
attachSelect(modal);
attachToggle(modal);
}
@ -806,7 +788,7 @@ function insertActionButton(modal, options) {
if (already_present == false) {
var html = `
<span style='float: right;'>
<button name='${options.name}' type='submit' class='btn btn-default modal-form-button' value='${options.name}'>
<button name='${options.name}' type='submit' class='btn btn-outline-secondary modal-form-button' value='${options.name}'>
${options.title}
</button>
</span>`;

View File

@ -94,7 +94,7 @@ function renderStockItem(name, data, parameters, options) {
if (data.serial && data.quantity == 1) {
stock_detail = `{% trans "Serial Number" %}: ${data.serial}`;
} else if (data.quantity == 0) {
stock_detail = `<span class='label-form label-red'>{% trans "No Stock"% }</span>`;
stock_detail = `<span class='badge rounded-pill bg-danger'>{% trans "No Stock"% }</span>`;
} else {
stock_detail = `{% trans "Quantity" %}: ${data.quantity}`;
}
@ -172,7 +172,7 @@ function renderPart(name, data, parameters, options) {
}
if (!data.active) {
extra += `<span class='label-form label-red'>{% trans "Inactive" %}</span>`;
extra += `<span class='badge badge-right rounded-pill bg-danger'>{% trans "Inactive" %}</span>`;
}
html += `

View File

@ -84,6 +84,7 @@ function createPurchaseOrder(options={}) {
prefix: global_settings.PURCHASEORDER_REFERENCE_PREFIX,
},
supplier: {
icon: 'fa-building',
value: options.supplier,
secondary: {
title: '{% trans "Add Supplier" %}',
@ -864,6 +865,7 @@ function loadPurchaseOrderLineItemTable(table, options={}) {
},
{
sortable: true,
switchable: false,
field: 'quantity',
title: '{% trans "Quantity" %}',
footerFormatter: function(data) {
@ -879,18 +881,29 @@ function loadPurchaseOrderLineItemTable(table, options={}) {
field: 'purchase_price',
title: '{% trans "Unit Price" %}',
formatter: function(value, row) {
return row.purchase_price_string || row.purchase_price;
var formatter = new Intl.NumberFormat(
'en-US',
{
style: 'currency',
currency: row.purchase_price_currency
}
);
return formatter.format(row.purchase_price);
}
},
{
field: 'total_price',
sortable: true,
field: 'total_price',
title: '{% trans "Total price" %}',
title: '{% trans "Total Price" %}',
formatter: function(value, row) {
var total = row.purchase_price * row.quantity;
var formatter = new Intl.NumberFormat('en-US', {style: 'currency', currency: row.purchase_price_currency});
return formatter.format(total);
var formatter = new Intl.NumberFormat(
'en-US',
{
style: 'currency',
currency: row.purchase_price_currency
}
);
return formatter.format(row.purchase_price * row.quantity);
},
footerFormatter: function(data) {
var total = data.map(function(row) {
@ -1436,7 +1449,7 @@ function loadSalesOrderLineItemTable(table, options={}) {
sortable: true,
field: 'reference',
title: '{% trans "Reference" %}',
switchable: false,
switchable: true,
},
{
sortable: true,
@ -1456,14 +1469,6 @@ function loadSalesOrderLineItemTable(table, options={}) {
field: 'sale_price',
title: '{% trans "Unit Price" %}',
formatter: function(value, row) {
return row.sale_price_string || row.sale_price;
}
},
{
sortable: true,
title: '{% trans "Total price" %}',
formatter: function(value, row) {
var total = row.sale_price * row.quantity;
var formatter = new Intl.NumberFormat(
'en-US',
{
@ -1472,7 +1477,23 @@ function loadSalesOrderLineItemTable(table, options={}) {
}
);
return formatter.format(total);
return formatter.format(row.sale_price);
}
},
{
field: 'total_price',
sortable: true,
title: '{% trans "Total Price" %}',
formatter: function(value, row) {
var formatter = new Intl.NumberFormat(
'en-US',
{
style: 'currency',
currency: row.sale_price_currency
}
);
return formatter.format(row.sale_price * row.quantity);
},
footerFormatter: function(data) {
var total = data.map(function(row) {
@ -1544,6 +1565,7 @@ function loadSalesOrderLineItemTable(table, options={}) {
if (pending) {
columns.push({
field: 'buttons',
switchable: false,
formatter: function(value, row, index, field) {
var html = `<div class='btn-group float-right' role='group'>`;

View File

@ -410,14 +410,12 @@ function toggleStar(options) {
}
function partStockLabel(part, options={}) {
var label_class = options.label_class || 'label-form';
function partStockLabel(part) {
if (part.in_stock) {
return `<span class='label ${label_class} label-green'>{% trans "Stock" %}: ${part.in_stock}</span>`;
return `<span class='badge rounded-pill bg-success'>{% trans "Stock" %}: ${part.in_stock}</span>`;
} else {
return `<span class='label ${label_class} label-red'>{% trans "No Stock" %}</span>`;
return `<span class='badge rounded-pill bg-danger'>{% trans "No Stock" %}</span>`;
}
}
@ -453,7 +451,7 @@ function makePartIcons(part) {
}
if (!part.active) {
html += `<span class='label label-warning label-right'>{% trans "Inactive" %}</span>`;
html += `<span class='badge badge-right rounded-pill bg-warning'>{% trans "Inactive" %}</span>`;
}
return html;
@ -530,7 +528,7 @@ function loadPartVariantTable(table, partId, options={}) {
}
if (!row.active) {
html += `<span class='label label-warning label-right'>{% trans "Inactive" %}</span>`;
html += `<span class='badge badge-right rounded-pill bg-warning'>{% trans "Inactive" %}</span>`;
}
return html;
@ -769,14 +767,10 @@ function partGridTile(part) {
// Rows for table view
var rows = '';
if (part.IPN) {
rows += `<tr><td><b>{% trans "IPN" %}</b></td><td>${part.IPN}</td></tr>`;
}
var stock = `${part.in_stock}`;
if (!part.in_stock) {
stock = `<span class='label label-red'>{% trans "No Stock" %}</label>`;
stock = `<span class='badge rounded-pill bg-danger'>{% trans "No Stock" %}</span>`;
}
rows += `<tr><td><b>{% trans "Stock" %}</b></td><td>${stock}</td></tr>`;
@ -791,8 +785,8 @@ function partGridTile(part) {
var html = `
<div class='product-card card'>
<div class='panel panel-default panel-inventree product-card-panel'>
<div class='card product-card borderless'>
<div class='panel product-card-panel'>
<div class='panel-heading'>
<a href='/part/${part.pk}/'>
<b>${part.full_name}</b>
@ -949,20 +943,20 @@ function loadPartTable(table, url, options={}) {
// Is stock "low" (below the 'minimum_stock' quantity)?
if (row.minimum_stock && row.minimum_stock > value) {
value += `<span class='label label-right label-warning'>{% trans "Low stock" %}</span>`;
value += `<span class='badge badge-right rounded-pill bg-warning'>{% trans "Low stock" %}</span>`;
}
} else if (row.on_order) {
// There is no stock available, but stock is on order
value = `0<span class='label label-right label-primary'>{% trans "On Order" %}: ${row.on_order}</span>`;
value = `0<span class='badge badge-right rounded-pill bg-info'>{% trans "On Order" %}: ${row.on_order}</span>`;
link = '?display=purchase-orders';
} else if (row.building) {
// There is no stock available, but stock is being built
value = `0<span class='label label-right label-info'>{% trans "Building" %}: ${row.building}</span>`;
value = `0<span class='badge badge-right rounded-pill bg-info'>{% trans "Building" %}: ${row.building}</span>`;
link = '?display=build-orders';
} else {
// There is no stock available
value = `0<span class='label label-right label-danger'>{% trans "No Stock" %}</span>`;
value = `0<span class='badge badge-right rounded-pill bg-danger'>{% trans "No Stock" %}</span>`;
}
return renderLink(value, `/part/${row.pk}/${link}`);
@ -989,6 +983,8 @@ function loadPartTable(table, url, options={}) {
}
});
var grid_view = inventreeLoad('part-grid-view') == 1;
$(table).inventreeTable({
url: url,
method: 'get',
@ -1003,8 +999,52 @@ function loadPartTable(table, url, options={}) {
},
columns: columns,
showColumns: true,
showCustomView: false,
showCustomView: grid_view,
showCustomViewButton: false,
onPostBody: function() {
grid_view = inventreeLoad('part-grid-view') == 1;
if (grid_view) {
$('#view-part-list').removeClass('btn-secondary').addClass('btn-outline-secondary');
$('#view-part-grid').removeClass('btn-outline-secondary').addClass('btn-secondary');
} else {
$('#view-part-grid').removeClass('btn-secondary').addClass('btn-outline-secondary');
$('#view-part-list').removeClass('btn-outline-secondary').addClass('btn-secondary');
}
},
buttons: [
{
icon: 'fas fa-bars',
attributes: {
title: '{% trans "Display as list" %}',
id: 'view-part-list',
},
event: () => {
inventreeSave('part-grid-view', 0);
$(table).bootstrapTable(
'refreshOptions',
{
showCustomView: false,
}
);
}
},
{
icon: 'fas fa-th',
attributes: {
title: '{% trans "Display as grid" %}',
id: 'view-part-grid',
},
event: () => {
inventreeSave('part-grid-view', 1);
$(table).bootstrapTable(
'refreshOptions',
{
showCustomView: true,
}
);
}
}
],
customView: function(data) {
var html = '';
@ -1117,14 +1157,88 @@ function loadPartCategoryTable(table, options) {
setupFilterList(filterKey, table, filterListElement);
var tree_view = inventreeLoad('category-tree-view') == 1;
table.inventreeTable({
treeEnable: tree_view,
rootParentId: options.params.parent,
uniqueId: 'pk',
idField: 'pk',
treeShowField: 'name',
parentIdField: 'parent',
method: 'get',
url: options.url || '{% url "api-part-category-list" %}',
queryParams: filters,
sidePagination: 'server',
disablePagination: tree_view,
sidePagination: tree_view ? 'client' : 'server',
serverSort: !tree_view,
search: !tree_view,
name: 'category',
original: original,
showColumns: true,
buttons: [
{
icon: 'fas fa-bars',
attributes: {
title: '{% trans "Display as list" %}',
id: 'view-category-list',
},
event: () => {
inventreeSave('category-tree-view', 0);
table.bootstrapTable(
'refreshOptions',
{
treeEnable: false,
serverSort: true,
search: true,
pagination: true,
}
);
}
},
{
icon: 'fas fa-sitemap',
attributes: {
title: '{% trans "Display as tree" %}',
id: 'view-category-tree',
},
event: () => {
inventreeSave('category-tree-view', 1);
table.bootstrapTable(
'refreshOptions',
{
treeEnable: true,
serverSort: false,
search: false,
pagination: false,
}
);
}
}
],
onPostBody: function() {
tree_view = inventreeLoad('category-tree-view') == 1;
if (tree_view) {
$('#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 {
$('#view-category-tree').removeClass('btn-secondary').addClass('btn-outline-secondary');
$('#view-category-list').removeClass('btn-outline-secondary').addClass('btn-secondary');
}
},
columns: [
{
checkbox: true,
@ -1154,7 +1268,8 @@ function loadPartCategoryTable(table, options) {
{
field: 'pathstring',
title: '{% trans "Path" %}',
switchable: true,
switchable: !tree_view,
visible: !tree_view,
sortable: false,
},
{

View File

@ -450,17 +450,17 @@ function removeStockRow(e) {
}
function passFailBadge(result, align='float-right') {
function passFailBadge(result) {
if (result) {
return `<span class='label label-green ${align}'>{% trans "PASS" %}</span>`;
return `<span class='badge badge-right rounded-pill bg-success'>{% trans "PASS" %}</span>`;
} else {
return `<span class='label label-red ${align}'>{% trans "FAIL" %}</span>`;
return `<span class='badge badge-right rounded-pill bg-danger'>{% trans "FAIL" %}</span>`;
}
}
function noResultBadge(align='float-right') {
return `<span class='label label-blue ${align}'>{% trans "NO RESULT" %}</span>`;
function noResultBadge() {
return `<span class='badge badge-right rounded-pill bg-info'>{% trans "NO RESULT" %}</span>`;
}
function formatDate(row) {
@ -468,11 +468,7 @@ function formatDate(row) {
var html = row.date;
if (row.user_detail) {
html += `<span class='badge'>${row.user_detail.username}</span>`;
}
if (row.attachment) {
html += `<a href='${row.attachment}'><span class='fas fa-file-alt label-right'></span></a>`;
html += `<span class='badge badge-right rounded-pill bg-secondary'>${row.user_detail.username}</span>`;
}
return html;
@ -553,6 +549,15 @@ function loadStockTestResultsTable(table, options) {
{
field: 'value',
title: '{% trans "Value" %}',
formatter: function(value, row) {
var html = value;
if (row.attachment) {
html += `<a href='${row.attachment}'><span class='fas fa-file-alt float-right'></span></a>`;
}
return html;
}
},
{
field: 'notes',
@ -878,16 +883,12 @@ function loadStockTable(table, options) {
}
if (row.quantity <= 0) {
html += `<span class='label label-right label-danger'>{% trans "Depleted" %}</span>`;
html += `<span class='badge rounded-pill bg-danger'>{% trans "Depleted" %}</span>`;
}
return html;
}
};
if (!options.params.ordering) {
col['sortable'] = true;
}
columns.push(col);
@ -1442,7 +1443,19 @@ function loadStockLocationTable(table, options) {
filters[key] = params[key];
}
var tree_view = inventreeLoad('location-tree-view') == 1;
table.inventreeTable({
treeEnable: tree_view,
rootParentId: options.params.parent,
uniqueId: 'pk',
idField: 'pk',
treeShowField: 'name',
parentIdField: 'parent',
disablePagination: tree_view,
sidePagination: tree_view ? 'client' : 'server',
serverSort: !tree_view,
search: !tree_view,
method: 'get',
url: options.url || '{% url "api-location-list" %}',
queryParams: filters,
@ -1450,6 +1463,69 @@ function loadStockLocationTable(table, options) {
name: 'location',
original: original,
showColumns: true,
onPostBody: function() {
tree_view = inventreeLoad('location-tree-view') == 1;
if (tree_view) {
$('#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 {
$('#view-location-tree').removeClass('btn-secondary').addClass('btn-outline-secondary');
$('#view-location-list').removeClass('btn-outline-secondary').addClass('btn-secondary');
}
},
buttons: [
{
icon: 'fas fa-bars',
attributes: {
title: '{% trans "Display as list" %}',
id: 'view-location-list',
},
event: () => {
inventreeSave('location-tree-view', 0);
table.bootstrapTable(
'refreshOptions',
{
treeEnable: false,
serverSort: true,
search: true,
pagination: true,
}
);
}
},
{
icon: 'fas fa-sitemap',
attributes: {
title: '{% trans "Display as tree" %}',
id: 'view-location-tree',
},
event: () => {
inventreeSave('location-tree-view', 1);
table.bootstrapTable(
'refreshOptions',
{
treeEnable: true,
serverSort: false,
search: false,
pagination: false,
}
);
}
}
],
columns: [
{
checkbox: true,
@ -1684,8 +1760,8 @@ function loadStockTrackingTable(table, options) {
formatter: function(value, row, index, field) {
// Manually created entries can be edited or deleted
if (false && !row.system) {
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>";
var bEdit = "<button title='{% trans 'Edit tracking entry' %}' class='btn btn-entry-edit btn-outline-secondary' 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-outline-secondary' 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 {

View File

@ -214,6 +214,8 @@ $.fn.inventreeTable = function(options) {
options.pageList = [25, 50, 100, 250, 'all'];
options.totalField = 'count';
options.dataField = 'results';
} else {
options.pagination = false;
}
// Extract query params
@ -397,3 +399,8 @@ function customGroupSorter(sortName, sortOrder, sortData) {
$.extend($.fn.bootstrapTable.defaults, $.fn.bootstrapTable.locales['en-US-custom']);
})(jQuery);
$.extend($.fn.treegrid.defaults, {
expanderExpandedClass: 'treegrid-expander-expanded',
expanderCollapsedClass: 'treegrid-expander-collapsed'
});

View File

@ -7,14 +7,12 @@
</div>
<div class='modal fade modal-fixed-footer modal-primary' role='dialog' id='modal-form' tabindex='-1'>
<div class='modal fade modal-fixed-footer modal-primary inventree-modal' role='dialog' id='modal-form' tabindex='-1'>
<div class='modal-dialog'>
<div class='modal-content'>
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
<h3 id='modal-title'><em>Form Title Here</em></h3>
<h4 id='modal-title'><em>Form Title Here</em></h4>
<button type='button' class='btn-close' data-bs-dismiss='modal' aria-label='{% trans "Close" %}'></button>
</div>
<div class='modal-form-content-wrapper'>
<div class='alert alert-block alert-danger' id='form-validation-warning' style='display: none;'>
@ -26,7 +24,7 @@
</div>
<div class='modal-footer'>
<div id='modal-footer-buttons'></div>
<button type='button' class='btn btn-default' id='modal-form-close' data-dismiss='modal'>{% trans "Close" %}</button>
<button type='button' class='btn btn-outline-secondary' id='modal-form-close' data-bs-dismiss='modal'>{% trans "Close" %}</button>
<button type='button' class='btn btn-primary' id='modal-form-submit'>{% trans "Submit" %}</button>
</div>
</div>
@ -37,10 +35,8 @@
<div class='modal-dialog'>
<div class='modal-content'>
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
<h3 id='modal-title'><em>Form Title Here</em></h3>
<h4 id='modal-title'><em>Form Title Here</em></h4>
<button type='button' class='btn-close' data-bs-dismiss='modal' aria-label='{% trans "Close" %}'></button>
</div>
<div class='modal-form-content-wrapper'>
<div class='alert alert-block alert-danger' id='form-validation-warning' style="display: none;">
@ -51,7 +47,7 @@
</div>
<div class='modal-footer'>
<div id='modal-footer-buttons'></div>
<button type='button' class='btn btn-default' id='modal-form-close' data-dismiss='modal'>{% trans "Close" %}</button>
<button type='button' class='btn btn-outline-secondary' id='modal-form-close' data-bs-dismiss='modal'>{% trans "Close" %}</button>
<button type='button' class='btn btn-primary' id='modal-form-submit'>{% trans "Submit" %}</button>
</div>
</div>

View File

@ -4,48 +4,57 @@
{% load i18n %}
{% settings_value 'BARCODE_ENABLE' as barcodes %}
{% settings_value 'STICKY_HEADER' user=request.user as sticky %}
{% navigation_enabled as plugin_nav %}
<nav class="navbar navbar-xs navbar-default navbar-fixed-top ">
<nav class="navbar {% if sticky %}fixed-top{% endif %} navbar-expand-lg navbar-light">
<div class="container-fluid">
<div class="navbar-header clearfix content-heading">
<a class="navbar-brand" id='logo' href="{% url 'index' %}" style="padding-top: 7px; padding-bottom: 5px;"><img src="{% static 'img/inventree.png' %}" width="32" height="32" style="display:block; margin: auto;"/></a>
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
<span class="sr-only">{% trans "Toggle navigation" %}</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
</div>
</div>
<div class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<ul class="navbar-nav">
{% if roles.part.view %}
<li><a href="{% url 'part-index' %}"><span class='fas fa-shapes icon-header'></span>{% trans "Parts" %}</a></li>
<li class='nav-item'>
<a class='nav-link' href="{% url 'part-index' %}">
<span class='fas fa-shapes icon-header'></span>{% trans "Parts" %}
</a>
</li>
{% endif %}
{% if roles.stock.view %}
<li><a href="{% url 'stock-index' %}"><span class='fas fa-boxes icon-header'></span>{% trans "Stock" %}</a></li>
<li class='nav-item'>
<a class='nav-link' href="{% url 'stock-index' %}">
<span class='fas fa-boxes icon-header'></span>{% trans "Stock" %}
</a>
</li>
{% endif %}
{% if roles.build.view %}
<li><a href="{% url 'build-index' %}"><span class='fas fa-tools icon-header'></span>{% trans "Build" %}</a></li>
<li class='nav-item'>
<a class='nav-link' href="{% url 'build-index' %}">
<span class='fas fa-tools icon-header'></span>{% trans "Build" %}
</a>
</li>
{% endif %}
{% if roles.purchase_order.view %}
<li class='nav navbar-nav'>
<a class='dropdown-toggle' data-toggle='dropdown' href='#'><span class='fas fa-shopping-cart icon-header'></span>{% trans "Buy" %}</a>
<ul class='dropdown-menu'>
<li><a href="{% url 'supplier-index' %}"><span class='fas fa-building icon-header'></span>{% trans "Suppliers" %}</a></li>
<li><a href="{% url 'manufacturer-index' %}"><span class='fas fa-industry icon-header'></span>{% trans "Manufacturers" %}</a></li>
<li><a href="{% url 'po-index' %}"><span class='fas fa-list icon-header'></span>{% trans "Purchase Orders" %}</a></li>
<li class='nav-item dropdown'>
<a class='nav-link dropdown-toggle' href='#' id='buyMenuDropdown' role='button' data-bs-toggle='dropdown'>
<span class='fas fa-shopping-cart icon-header'></span>{% trans "Buy" %}
</a>
<ul class='dropdown-menu' aria-labelledby="buyMenuDropdown">
<li><a class='dropdown-item' href="{% url 'supplier-index' %}"><span class='fas fa-building icon-header'></span>{% trans "Suppliers" %}</a></li>
<li><a class='dropdown-item' href="{% url 'manufacturer-index' %}"><span class='fas fa-industry icon-header'></span>{% trans "Manufacturers" %}</a></li>
<li><a class='dropdown-item' href="{% url 'po-index' %}"><span class='fas fa-list icon-header'></span>{% trans "Purchase Orders" %}</a></li>
</ul>
</li>
{% endif %}
{% if roles.sales_order.view %}
<li class='nav navbar-nav'>
<a class='dropdown-toggle' data-toggle='dropdown' href='#'><span class='fas fa-truck icon-header'></span>{% trans "Sell" %}</a>
<li class='nav-item dropdown'>
<a class='nav-link dropdown-toggle' href='#' id='sellMenuDropdown' role='button' data-bs-toggle='dropdown'>
<span class='fas fa-truck icon-header'></span>{% trans "Sell" %}
</a>
<ul class='dropdown-menu'>
<li><a href="{% url 'customer-index' %}"><span class='fas fa-user-tie icon-header'></span>{% trans "Customers" %}</a>
<li><a href="{% url 'so-index' %}"><span class='fas fa-list icon-header'></span>{% trans "Sales Orders" %}</a></li>
<li><a class='dropdown-item' href="{% url 'customer-index' %}"><span class='fas fa-user-tie icon-header'></span>{% trans "Customers" %}</a>
<li><a class='dropdown-item' href="{% url 'so-index' %}"><span class='fas fa-list icon-header'></span>{% trans "Sales Orders" %}</a></li>
</ul>
</li>
{% endif %}
@ -69,57 +78,54 @@
{% endif %}
</ul>
<ul class="nav navbar-nav navbar-right">
{% include "search_form.html" %}
{% if barcodes %}
<li id='navbar-barcode-li'>
<button id='barcode-scan' class='btn btn-default' title='{% trans "Scan Barcode" %}'>
<span class='fas fa-qrcode'></span>
</button>
</li>
{% endif %}
<li class='dropdown'>
<a class='dropdown-toggle' data-toggle='dropdown' href="#">
{% if user.is_staff %}
{% if not system_healthy %}
<span class='fas fa-exclamation-triangle icon-red'></span>
{% elif not up_to_date %}
<span class='fas fa-info-circle icon-green'></span>
{% endif %}
{% endif %}
<span class="fas fa-user"></span> <strong>{{ user.get_username }}</strong></a>
<ul class='dropdown-menu'>
{% if user.is_authenticated %}
{% if user.is_staff %}
<li><a href="/admin/"><span class="fas fa-user"></span> {% trans "Admin" %}</a></li>
{% endif %}
<li><a href="{% url 'account_logout' %}"><span class="fas fa-sign-out-alt"></span> {% trans "Logout" %}</a></li>
{% else %}
<li><a href="{% url 'account_login' %}"><span class="fas fa-sign-in-alt"></span> {% trans "Login" %}</a></li>
{% endif %}
<hr>
<li><a href="{% url 'settings' %}"><span class="fas fa-cog"></span> {% trans "Settings" %}</a></li>
<li id='launch-stats'><a href='#'>
{% if system_healthy or not user.is_staff %}
<span class='fas fa-server'></span>
{% else %}
<span class='fas fa-server icon-red'></span>
{% endif %}
</span> {% trans "System Information" %}
</a></li>
<li id='launch-about'>
<a href='#'>
{% if up_to_date %}
<span class="fas fa-info-circle">
{% else %}
<span class='fas fa-info-circle icon-red'>
{% endif %}
</span> {% trans "About InvenTree" %}
</a>
</li>
</ul>
</li>
</ul>
</div>
{% include "search_form.html" %}
<ul class='navbar-nav'>
{% if barcodes %}
<li id='navbar-barcode-li'>
<button id='barcode-scan' class='btn btn-secondary' title='{% trans "Scan Barcode" %}'>
<span class='fas fa-qrcode'></span>
</button>
</li>
{% endif %}
<li class='nav-item dropdown'>
<a class='nav-link dropdown-toggle' href='#' id='userMenuDropdown' role='button' data-bs-toggle='dropdown'>
<span class='fas fa-user'></span> <strong>{{ user.get_username }}</strong>
</a>
<ul class='dropdown-menu dropdown-menu-end'>
{% if user.is_authenticated %}
{% if user.is_staff %}
<li><a class='dropdown-item' href="/admin/"><span class="fas fa-user"></span> {% trans "Admin" %}</a></li>
{% endif %}
<li><a class='dropdown-item' href="{% url 'account_logout' %}"><span class="fas fa-sign-out-alt"></span> {% trans "Logout" %}</a></li>
{% else %}
<li><a class='dropdown-item' href="{% url 'account_login' %}"><span class="fas fa-sign-in-alt"></span> {% trans "Login" %}</a></li>
{% endif %}
<hr>
<li><a class='dropdown-item' href="{% url 'settings' %}"><span class="fas fa-cog"></span> {% trans "Settings" %}</a></li>
<li id='launch-stats'>
<a class='dropdown-item' href='#'>
{% if system_healthy or not user.is_staff %}
<span class='fas fa-server'></span>
{% else %}
<span class='fas fa-server icon-red'></span>
{% endif %}
{% trans "System Information" %}
</a>
</li>
<li id='launch-about'>
<a class='dropdown-item' href='#'>
{% if up_to_date %}
<span class="fas fa-info-circle"></span>
{% else %}
<span class='fas fa-info-circle icon-red'></span>
{% endif %}
{% trans "About InvenTree" %}
</a>
</li>
</ul>
</li>
</ul>
</div>
</nav>

View File

@ -1,18 +1,18 @@
<div class='notification-area'>
<div class="alert alert-success alert-dismissable" id="alert-success">
<a href="#" class="close" data-dismiss="alert" aria-label="close">&times;</a>
<a href="#" class="close" data-bs-dismiss="alert" aria-label="close">&times;</a>
<div class='alert-msg'>Success alert</div>
</div>
<div class='alert alert-info alert-dismissable' id='alert-info'>
<a href="#" class="close" data-dismiss="alert" aria-label="close">&times;</a>
<a href="#" class="close" data-bs-dismiss="alert" aria-label="close">&times;</a>
<div class='alert-msg'>Info alert</div>
</div>
<div class='alert alert-warning alert-dismissable' id='alert-warning'>
<a href="#" class="close" data-dismiss="alert" aria-label="close">&times;</a>
<a href="#" class="close" data-bs-dismiss="alert" aria-label="close">&times;</a>
<div class='alert-msg'>Warning alert</div>
</div>
<div class='alert alert-danger alert-dismissable' id='alert-danger'>
<a href="#" class="close" data-dismiss="alert" aria-label="close">&times;</a>
<a href="#" class="close" data-bs-dismiss="alert" aria-label="close">&times;</a>
<div class='alert-msg'>Danger alert</div>
</div>
</div>

View File

@ -0,0 +1,60 @@
{% extends "base.html" %}
{% load static %}
{% load i18n %}
{% block content %}
<div class='panel'>
<div class='panel-heading'>
<div class='d-flex flex-row'>
<h4>
{% block heading %}
<i>-- page header goes here --</i>
{% endblock %}
</h4>
{% include "spacer.html" %}
<div id='page-actions' class='btn-group' role='group'>
{% block actions %}
<i>-- actions go here --</i>
{% endblock %}
</div>
</div>
</div>
{% block page_info %}
<div class='panel-content'>
<div class='row'>
<div class='col-sm-6' id='detail-panel-left'>
<div class='card'>
{% block details_left %}
<div class='row g-0'>
<div class='col-md-4'>
{% block thumbnail %}
{% endblock %}
</div>
<div class='col-md-8'>
{% block details %}
{% endblock %}
</div>
</div>
{% endblock %}
</div>
</div>
<div class='col-sm-6' id='detail-panel-right'>
<div class='card'>
{% block details_right %}
block details_right
{% endblock %}
</div>
</div>
</div>
</div>
{% endblock %}
</div>
{% block page_content %}
{% endblock %}
{% endblock %}

View File

@ -1,4 +1,4 @@
<div class='panel panel-default panel-inventree panel-hidden' id='panel-{% block label %}name{% endblock %}'>
<div class='panel panel-hidden' id='panel-{% block label %}name{% endblock %}'>
{% block panel_heading %}
<div class='panel-heading'>
<h4>{% block heading %}HEADING{% endblock %}</h4>

View File

@ -1 +1 @@
<button type='button' class='btn btn-default' id='show-qr-code' title='{% trans "Show QR Code" %}'><span class='fas fa-qrcode'></span></button>
<button type='button' class='btn btn-outline-secondary' id='show-qr-code' title='{% trans "Show QR Code" %}'><span class='fas fa-qrcode'></span></button>

View File

@ -1,11 +1,9 @@
{% load i18n %}
<form class="navbar-form navbar-left" action="{% url 'search' %}" method='post'>
<form class="d-flex" action="{% url 'search' %}" method='post'>
{% csrf_token %}
<div class="form-group">
<input type="text" name='search' class="form-control" id="search-bar" placeholder="{% trans 'Search' %}"{% if query_text %} value="{{ query }}"{% endif %}>
</div>
<button type="submit" id='search-submit' class="btn btn-default" title='{% trans "Search" %}'>
<input type="text" name='search' class="form-control" aria-label='{% trans "Search" %}' id="search-bar" 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>
</form>

View File

@ -0,0 +1,8 @@
{% load i18n %}
<span title='{% trans text %}' class="list-group-item sidebar-list-group-item border-end-0 d-inline-block text-truncate" data-bs-parent="#sidebar">
<h6>
<i class="bi bi-bootstrap"></i>
{% if icon %}<span class='sidebar-item-icon fas {{ icon }}'></span>{% endif %}
{% if text %}<span class='sidebar-item-text' style='display: none;'>{% trans text %}</span>{% endif %}
</h6>
</span>

View File

@ -0,0 +1,11 @@
{% load i18n %}
<a href="#" id='select-{{ label }}' title='{% trans text %}' class="list-group-item sidebar-list-group-item border-end-0 d-inline-block text-truncate sidebar-selector" data-bs-parent="#sidebar">
<i class="bi bi-bootstrap"></i>
<span class='sidebar-item-icon fas {{ icon }}'></span>
<span class='sidebar-item-text' style='display: none;'>{% trans text %}</span>
{% if badge %}
<span id='sidebar-badge-{{ label }}' class='sidebar-item-badge badge rounded-pill badge-right bg-dark'>
<span class='fas fa-spin fa-spinner'></span>
</span>
{% endif %}
</a>

View File

@ -0,0 +1,4 @@
{% load i18n %}
<a href="{{ url }}" class="list-group-item sidebar-list-group-item border-end-0 d-inline-block text-truncate" data-bs-parent="#sidebar">
<i class="bi bi-bootstrap"></i><span class='sidebar-item-icon fas {{ icon }}'></span><span class='sidebar-item-text' style='display: none;'>{% trans text %}</span>
</a>

View File

@ -0,0 +1,3 @@
<a href="#" id='sidebar-toggle' class="list-group-item sidebar-list-group-item border-end-0 d-inline-block text-truncate sidebar-toggle" data-bs-parent="#sidebar" style='display: none;'>
<i class="bi bi-bootstrap"></i><span id='sidebar-toggle-icon' class='sidebar-item-icon fas fa-chevron-left'></span>
</a>

View File

@ -0,0 +1 @@
<span class='flex' style='flex-grow: 1;'></span>

View File

@ -40,9 +40,9 @@
<td>{% trans "Server status" %}</td>
<td>
{% if system_healthy %}
<span class='label label-green'>{% trans "Healthy" %}</span>
<span class='badge rounded-pill bg-success'>{% trans "Healthy" %}</span>
{% else %}
<span class='label label-red'>{% trans "Issues detected" %}</span>
<span class='badge rounded-pill bg-warning'>{% trans "Issues detected" %}</span>
{% endif %}
</td>
</tr>
@ -52,7 +52,7 @@
<td>{% trans "Background Worker" %}</td>
<td>
<a href='{% inventree_docs_url %}/admin/tasks'>
<span class='label label-red'>{% trans "Background worker not running" %}</span>
<span class='badge rounded-pill bg-danger'>{% trans "Background worker not running" %}</span>
</a>
</td>
</tr>
@ -63,7 +63,7 @@
<td>{% trans "Email Settings" %}</td>
<td>
<a href='{% inventree_docs_url %}/admin/email'>
<span class='label label-yellow'>{% trans "Email settings not configured" %}</span>
<span class='badge rounded-pill bg-warning'>{% trans "Email settings not configured" %}</span>
</a>
</td>
</tr>

View File

@ -5,7 +5,7 @@ const {{ label }}Codes = {
{% for opt in options %}'{{ opt.key }}': {
key: '{{ opt.key }}',
value: '{{ opt.value }}',{% if opt.color %}
label: 'label-{{ opt.color }}',{% endif %}
label: 'bg-{{ opt.color }}',{% endif %}
},
{% endfor %}
};
@ -32,7 +32,7 @@ function {{ label }}StatusDisplay(key, options={}) {
label = '';
}
var classes = `label ${label}`;
var classes = `badge rounded-pill ${label}`;
if (options.classes) {
classes += ' ' + options.classes;

View File

@ -11,7 +11,7 @@
<div id='{{ prefix }}button-toolbar'>
<div class='button-toolbar container-fluid' style='float: right;'>
<div class='btn-group'>
<button class='btn btn-default' id='stock-export' title='{% trans "Export Stock Information" %}'>
<button class='btn btn-outline-secondary' id='stock-export' title='{% trans "Export Stock Information" %}'>
<span class='fas fa-download'></span>
</button>
@ -23,44 +23,44 @@
{% endif %}
{% if barcodes %}
<!-- Barcode actions menu -->
<div class='btn-group'>
<button id='stock-barcode-options' class='btn btn-primary dropdown-toggle' type='button' data-toggle='dropdown' title='{% trans "Barcode Actions" %}'>
<div class='btn-group' role='group'>
<button id='stock-barcode-options' class='btn btn-primary dropdown-toggle' type='button' data-bs-toggle='dropdown' title='{% trans "Barcode Actions" %}'>
<span class='fas fa-qrcode'></span> <span class='caret'></span>
</button>
<ul class='dropdown-menu'>
<li><a href='#' id='multi-item-barcode-scan-into-location' title='{% trans "Scan to Location" %}'><span class='fas fa-sitemap'></span> {% trans "Scan to Location" %}</a></li>
<li><a class='dropdown-item' href='#' id='multi-item-barcode-scan-into-location' title='{% trans "Scan to Location" %}'><span class='fas fa-sitemap'></span> {% trans "Scan to Location" %}</a></li>
</ul>
</div>
{% endif %}
<!-- Printing actions menu -->
<div class='btn-group'>
<button id='stock-print-options' class='btn btn-primary dropdown-toggle' type='button' data-toggle="dropdown" title='{% trans "Printing Actions" %}'>
<button id='stock-print-options' class='btn btn-primary dropdown-toggle' type='button' data-bs-toggle="dropdown" title='{% trans "Printing Actions" %}'>
<span class='fas fa-print'></span> <span class='caret'></span>
</button>
<ul class='dropdown-menu'>
<li><a href='#' id='multi-item-print-label' title='{% trans "Print labels" %}'><span class='fas fa-tags'></span> {% trans "Print labels" %}</a></li>
<li><a class='dropdown-item' href='#' id='multi-item-print-label' title='{% trans "Print labels" %}'><span class='fas fa-tags'></span> {% trans "Print labels" %}</a></li>
{% if test_report_enabled %}
<li><a href='#' id='multi-item-print-test-report' title='{% trans "Print test reports" %}'><span class='fas fa-file-pdf'></span> {% trans "Print test reports" %}</a></li>
<li><a class='dropdown-item' href='#' id='multi-item-print-test-report' title='{% trans "Print test reports" %}'><span class='fas fa-file-pdf'></span> {% trans "Print test reports" %}</a></li>
{% endif %}
</ul>
</div>
{% if not read_only %}
{% if roles.stock.change or roles.stock.delete %}
<div class="btn-group">
<button id='stock-options' class="btn btn-primary dropdown-toggle" type="button" data-toggle="dropdown" title='{% trans "Stock Options" %}'>
<button id='stock-options' class="btn btn-primary dropdown-toggle" type="button" data-bs-toggle="dropdown" title='{% trans "Stock Options" %}'>
<span class='fas fa-boxes'></span> <span class="caret"></span>
</button>
<ul class="dropdown-menu">
{% if roles.stock.change %}
<li><a href="#" id='multi-item-add' title='{% trans "Add to selected stock items" %}'><span class='fas fa-plus-circle'></span> {% trans "Add stock" %}</a></li>
<li><a href="#" id='multi-item-remove' title='{% trans "Remove from selected stock items" %}'><span class='fas fa-minus-circle'></span> {% trans "Remove stock" %}</a></li>
<li><a href="#" id='multi-item-stocktake' title='{% trans "Stocktake selected stock items" %}'><span class='fas fa-check-circle'></span> {% trans "Count stock" %}</a></li>
<li><a href='#' id='multi-item-move' title='{% trans "Move selected stock items" %}'><span class='fas fa-exchange-alt'></span> {% trans "Move stock" %}</a></li>
<li><a href='#' id='multi-item-order' title='{% trans "Order selected items" %}'><span class='fas fa-shopping-cart'></span> {% trans "Order stock" %}</a></li>
<li><a href='#' id='multi-item-set-status' title='{% trans "Change status" %}'><span class='fas fa-exclamation-circle'></span> {% trans "Change stock status" %}</a></li>
<li><a class='dropdown-item' href="#" id='multi-item-add' title='{% trans "Add to selected stock items" %}'><span class='fas fa-plus-circle icon-green'></span> {% trans "Add stock" %}</a></li>
<li><a class='dropdown-item' href="#" id='multi-item-remove' title='{% trans "Remove from selected stock items" %}'><span class='fas fa-minus-circle'></span> {% trans "Remove stock" %}</a></li>
<li><a class='dropdown-item' href="#" id='multi-item-stocktake' title='{% trans "Stocktake selected stock items" %}'><span class='fas fa-check-circle'></span> {% trans "Count stock" %}</a></li>
<li><a class='dropdown-item' href='#' id='multi-item-move' title='{% trans "Move selected stock items" %}'><span class='fas fa-exchange-alt'></span> {% trans "Move stock" %}</a></li>
<li><a class='dropdown-item' href='#' id='multi-item-order' title='{% trans "Order selected items" %}'><span class='fas fa-shopping-cart'></span> {% trans "Order stock" %}</a></li>
<li><a class='dropdown-item' href='#' id='multi-item-set-status' title='{% trans "Change status" %}'><span class='fas fa-exclamation-circle'></span> {% trans "Change stock status" %}</a></li>
{% endif %}
{% if roles.stock.delete %}
<li><a href='#' id='multi-item-delete' title='{% trans "Delete selected items" %}'><span class='fas fa-trash-alt'></span> {% trans "Delete Stock" %}</a></li>
<li><a class='dropdown-item' href='#' id='multi-item-delete' title='{% trans "Delete selected items" %}'><span class='fas fa-trash-alt icon-red'></span> {% trans "Delete Stock" %}</a></li>
{% endif %}
</ul>
</div>

View File

@ -1,81 +0,0 @@
{% extends "base.html" %}
{% load static %}
{% load i18n %}
{% block menubar %}
<!-- Custom menubar code goes here -->
{% endblock %}
{% block content %}
{% block header_panel %}
<div class='panel panel-default panel-inventree'>
{% block header_pre_content %}
{% endblock %}
<div class='row'>
<div class='col-sm-6'>
<div class='media-left'>
{% block thumbnail %}
<!-- Image goes here -->
{% endblock %}
</div>
<div class='media-body'>
{% block page_data %}
<!-- Data next to image goes here -->
{% endblock %}
</div>
{% block below_thumbnail %}
{% endblock %}
</div>
<div class='col-sm-6'>
{% block page_details %}
<!-- Right column data goes here -->
{% endblock %}
</div>
</div>
{% block header_post_content %}
{% endblock %}
</div>
{% endblock %}
{% block page_content %}
{% block pre_content_panels %}
{% endblock %}
{% block content_panels %}
<div class='panel panel-default panel-inventree'>
<div class='panel-heading'>
<h4>
{% block heading %}
<!-- Heading goes here -->
{% endblock %}
</h4>
</div>
{% block details_panel %}
<div class='panel-content'>
{% block details %}
<!-- Particular page detail views go here -->
{% endblock %}
</div>
{% endblock %}
</div>
{% endblock %}
{% block post_content_panels %}
{% endblock %}
{% endblock %}
{% endblock %}
{% block js_ready %}
{{ block.super }}
{% endblock %}

View File

@ -1,7 +1,7 @@
{% load i18n %}
{% if value %}
<span class='label label-success'>{% trans 'Yes' %}</span>
<span class='badge rounded-pill bg-success'>{% trans 'Yes' %}</span>
{% else %}
<span class='label label-warning'>{% trans 'No' %}</span>
<span class='badge rounded-pill bg-danger'>{% trans 'No' %}</span>
{% endif %}