Merge pull request #1863 from SchrodingersGat/settings-refactor

Refactoring existing settings views
This commit is contained in:
Oliver 2021-07-28 15:04:37 +10:00 committed by GitHub
commit 78ed2776d1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
30 changed files with 686 additions and 566 deletions

View File

@ -13,7 +13,6 @@ from crispy_forms.helper import FormHelper
from crispy_forms.layout import Layout, Field
from crispy_forms.bootstrap import PrependedText, AppendedText, PrependedAppendedText, StrictButton, Div
from common.models import ColorTheme
from part.models import PartCategory
@ -177,39 +176,6 @@ class SetPasswordForm(HelperForm):
]
class ColorThemeSelectForm(forms.ModelForm):
""" Form for setting color theme """
name = forms.ChoiceField(choices=(), required=False)
class Meta:
model = ColorTheme
fields = [
'name'
]
def __init__(self, *args, **kwargs):
super(ColorThemeSelectForm, self).__init__(*args, **kwargs)
# Populate color themes choices
self.fields['name'].choices = ColorTheme.get_color_themes_choices()
self.helper = FormHelper()
# Form rendering
self.helper.form_show_labels = False
self.helper.layout = Layout(
Div(
Div(Field('name'),
css_class='col-sm-6',
style='width: 200px;'),
Div(StrictButton(_('Apply Theme'), css_class='btn btn-primary', type='submit'),
css_class='col-sm-6',
style='width: auto;'),
css_class='row',
),
)
class SettingCategorySelectForm(forms.ModelForm):
""" Form for setting category settings """

View File

@ -39,7 +39,7 @@ from rest_framework.documentation import include_docs_urls
from .views import auth_request
from .views import IndexView, SearchView, DatabaseStatsView
from .views import SettingsView, EditUserView, SetPasswordView
from .views import CurrencySettingsView, CurrencyRefreshView
from .views import CurrencyRefreshView
from .views import AppearanceSelectView, SettingCategorySelectView
from .views import DynamicJsView
@ -79,27 +79,18 @@ apipatterns = [
settings_urls = [
url(r'^usersettings/', SettingsView.as_view(template_name='InvenTree/settings/user_settings.html'), name='settings-user-settings'),
url(r'^user/?', SettingsView.as_view(template_name='InvenTree/settings/user.html'), name='settings-user'),
url(r'^appearance/?', AppearanceSelectView.as_view(), name='settings-appearance'),
url(r'^i18n/?', include('django.conf.urls.i18n')),
url(r'^global/', SettingsView.as_view(template_name='InvenTree/settings/global.html'), name='settings-global'),
url(r'^report/', SettingsView.as_view(template_name='InvenTree/settings/report.html'), name='settings-report'),
url(r'^category/', SettingCategorySelectView.as_view(), name='settings-category'),
url(r'^part/', SettingsView.as_view(template_name='InvenTree/settings/part.html'), name='settings-part'),
url(r'^stock/', SettingsView.as_view(template_name='InvenTree/settings/stock.html'), name='settings-stock'),
url(r'^build/', SettingsView.as_view(template_name='InvenTree/settings/build.html'), name='settings-build'),
url(r'^purchase-order/', SettingsView.as_view(template_name='InvenTree/settings/po.html'), name='settings-po'),
url(r'^sales-order/', SettingsView.as_view(template_name='InvenTree/settings/so.html'), name='settings-so'),
url(r'^currencies/', CurrencySettingsView.as_view(), name='settings-currencies'),
url(r'^appearance/?', AppearanceSelectView.as_view(), name='settings-appearance'),
url(r'^currencies-refresh/', CurrencyRefreshView.as_view(), name='settings-currencies-refresh'),
url(r'^category/', SettingCategorySelectView.as_view(), name='settings-category'),
url(r'^(?P<pk>\d+)/edit/user', UserSettingEdit.as_view(), name='user-setting-edit'),
url(r'^(?P<pk>\d+)/edit/', SettingEdit.as_view(), name='setting-edit'),
# Catch any other urls
url(r'^.*$', SettingsView.as_view(template_name='InvenTree/settings/user.html'), name='settings'),
url(r'^.*$', SettingsView.as_view(template_name='InvenTree/settings/settings.html'), name='settings'),
]
# Some javascript files are served 'dynamically', allowing them to pass through the Django translation layer

View File

@ -12,6 +12,7 @@ from django.utils.translation import gettext_lazy as _
from django.template.loader import render_to_string
from django.http import HttpResponse, JsonResponse, HttpResponseRedirect
from django.urls import reverse_lazy
from django.shortcuts import redirect
from django.contrib.auth.mixins import PermissionRequiredMixin
@ -30,7 +31,7 @@ from users.models import check_user_role, RuleSet
import InvenTree.tasks
from .forms import DeleteForm, EditUserForm, SetPasswordForm
from .forms import ColorThemeSelectForm, SettingCategorySelectForm
from .forms import SettingCategorySelectForm
from .helpers import str2bool
from rest_framework import views
@ -779,7 +780,7 @@ class SettingsView(TemplateView):
""" View for configuring User settings
"""
template_name = "InvenTree/settings.html"
template_name = "InvenTree/settings/settings.html"
def get_context_data(self, **kwargs):
@ -787,6 +788,20 @@ class SettingsView(TemplateView):
ctx['settings'] = InvenTreeSetting.objects.all().order_by('key')
ctx["base_currency"] = currency_code_default()
ctx["currencies"] = currency_codes
ctx["rates"] = Rate.objects.filter(backend="InvenTreeExchange")
ctx["categories"] = PartCategory.objects.all().order_by('tree_id', 'lft', 'name')
# When were the rates last updated?
try:
backend = ExchangeBackend.objects.get(name='InvenTreeExchange')
ctx["rates_updated"] = backend.last_update
except:
ctx["rates_updated"] = None
return ctx
@ -805,43 +820,12 @@ class CurrencyRefreshView(RedirectView):
# Will block for a little bit
InvenTree.tasks.update_exchange_rates()
return self.get(request, *args, **kwargs)
return redirect(reverse_lazy('settings'))
class CurrencySettingsView(TemplateView):
"""
View for configuring currency settings
"""
template_name = "InvenTree/settings/currencies.html"
def get_context_data(self, **kwargs):
ctx = super().get_context_data(**kwargs).copy()
ctx['settings'] = InvenTreeSetting.objects.all().order_by('key')
ctx["base_currency"] = currency_code_default()
ctx["currencies"] = currency_codes
ctx["rates"] = Rate.objects.filter(backend="InvenTreeExchange")
# When were the rates last updated?
try:
backend = ExchangeBackend.objects.get(name='InvenTreeExchange')
ctx["rates_updated"] = backend.last_update
except:
ctx["rates_updated"] = None
return ctx
class AppearanceSelectView(FormView):
class AppearanceSelectView(RedirectView):
""" View for selecting a color theme """
form_class = ColorThemeSelectForm
success_url = reverse_lazy('settings-appearance')
template_name = "InvenTree/settings/appearance.html"
def get_user_theme(self):
""" Get current user color theme """
try:
@ -851,40 +835,10 @@ class AppearanceSelectView(FormView):
return user_theme
def get_initial(self):
""" Select current user color theme as initial choice """
initial = super(AppearanceSelectView, self).get_initial()
user_theme = self.get_user_theme()
if user_theme:
initial['name'] = user_theme.name
return initial
def get(self, request, *args, **kwargs):
""" Check if current color theme exists, else display alert box """
context = {}
form = self.get_form()
context['form'] = form
user_theme = self.get_user_theme()
if user_theme:
# Check color theme is a valid choice
if not ColorTheme.is_valid_choice(user_theme):
user_color_theme_name = user_theme.name
if not user_color_theme_name:
user_color_theme_name = 'default'
context['invalid_color_theme'] = user_color_theme_name
return self.render_to_response(context)
def post(self, request, *args, **kwargs):
""" Save user color theme selection """
form = self.get_form()
theme = request.POST.get('theme', None)
# Get current user theme
user_theme = self.get_user_theme()
@ -894,20 +848,10 @@ class AppearanceSelectView(FormView):
user_theme = ColorTheme()
user_theme.user = request.user
if form.is_valid():
theme_selected = form.cleaned_data['name']
user_theme.name = theme
user_theme.save()
# Set color theme to form selection
user_theme.name = theme_selected
user_theme.save()
return self.form_valid(form)
else:
# Set color theme to default
user_theme.name = ColorTheme.default_color_theme[0]
user_theme.save()
return self.form_invalid(form)
return redirect(reverse_lazy('settings'))
class SettingCategorySelectView(FormView):

View File

@ -538,13 +538,6 @@ class InvenTreeSetting(BaseInvenTreeSetting):
'validator': bool
},
'PART_RECENT_COUNT': {
'name': _('Recent Part Count'),
'description': _('Number of recent parts to display on index page'),
'default': 10,
'validator': [int, MinValueValidator(1)]
},
'PART_TEMPLATE': {
'name': _('Template'),
'description': _('Parts are templates by default'),
@ -668,13 +661,6 @@ class InvenTreeSetting(BaseInvenTreeSetting):
'validator': bool,
},
'SEARCH_PREVIEW_RESULTS': {
'name': _('Search Preview Results'),
'description': _('Number of results to show in search preview window'),
'default': 10,
'validator': [int, MinValueValidator(1)]
},
'STOCK_ENABLE_EXPIRY': {
'name': _('Stock Expiry'),
'description': _('Enable stock expiry functionality'),
@ -718,13 +704,6 @@ class InvenTreeSetting(BaseInvenTreeSetting):
'validator': bool,
},
'STOCK_RECENT_COUNT': {
'name': _('Recent Stock Count'),
'description': _('Number of recent stock items to display on index page'),
'default': 10,
'validator': [int, MinValueValidator(1)]
},
'BUILDORDER_REFERENCE_PREFIX': {
'name': _('Build Order Reference Prefix'),
'description': _('Prefix value for build order reference'),
@ -779,6 +758,13 @@ class InvenTreeUserSetting(BaseInvenTreeSetting):
'default': True,
'validator': bool,
},
'PART_RECENT_COUNT': {
'name': _('Recent Part Count'),
'description': _('Number of recent parts to display on index page'),
'default': 10,
'validator': [int, MinValueValidator(1)]
},
'HOMEPAGE_BOM_VALIDATION': {
'name': _('Show unvalidated BOMs'),
'description': _('Show BOMs that await validation on the homepage'),
@ -791,6 +777,12 @@ class InvenTreeUserSetting(BaseInvenTreeSetting):
'default': True,
'validator': bool,
},
'STOCK_RECENT_COUNT': {
'name': _('Recent Stock Count'),
'description': _('Number of recent stock items to display on index page'),
'default': 10,
'validator': [int, MinValueValidator(1)]
},
'HOMEPAGE_STOCK_LOW': {
'name': _('Show low stock'),
'description': _('Show low stock items on the homepage'),
@ -857,6 +849,13 @@ class InvenTreeUserSetting(BaseInvenTreeSetting):
'default': True,
'validator': bool,
},
'SEARCH_PREVIEW_RESULTS': {
'name': _('Search Preview Results'),
'description': _('Number of results to show in search preview window'),
'default': 10,
'validator': [int, MinValueValidator(1)]
},
}
class Meta:

View File

@ -50,6 +50,23 @@ class SettingEdit(AjaxUpdateView):
return ctx
def get_data(self):
"""
Custom data to return to the client after POST success
"""
data = {}
setting = self.get_object()
data['pk'] = setting.pk
data['key'] = setting.key
data['value'] = setting.value
data['is_bool'] = setting.is_bool()
data['is_int'] = setting.is_int()
return data
def get_form(self):
"""
Override default get_form behaviour

View File

@ -159,7 +159,7 @@ class CategoryDetail(generics.RetrieveUpdateDestroyAPIView):
queryset = PartCategory.objects.all()
class CategoryParameters(generics.ListAPIView):
class CategoryParameterList(generics.ListAPIView):
""" API endpoint for accessing a list of PartCategoryParameterTemplate objects.
- GET: Return a list of PartCategoryParameterTemplate objects
@ -176,30 +176,27 @@ class CategoryParameters(generics.ListAPIView):
- Allow traversing all parent categories
"""
try:
cat_id = int(self.kwargs.get('pk', None))
except TypeError:
cat_id = None
fetch_parent = str2bool(self.request.query_params.get('fetch_parent', 'true'))
queryset = super().get_queryset()
if isinstance(cat_id, int):
params = self.request.query_params
category = params.get('category', None)
if category is not None:
try:
category = PartCategory.objects.get(pk=cat_id)
except PartCategory.DoesNotExist:
# Return empty queryset
return PartCategoryParameterTemplate.objects.none()
category = PartCategory.objects.get(pk=category)
category_list = [cat_id]
fetch_parent = str2bool(params.get('fetch_parent', True))
if fetch_parent:
parent_categories = category.get_ancestors()
for parent in parent_categories:
category_list.append(parent.pk)
if fetch_parent:
parents = category.get_ancestors(include_self=True)
queryset = queryset.filter(category__in=[cat.pk for cat in parents])
else:
queryset = queryset.filter(category=category)
queryset = queryset.filter(category__in=category_list)
except (ValueError, PartCategory.DoesNotExist):
pass
return queryset
@ -1094,7 +1091,8 @@ part_api_urls = [
# Base URL for PartCategory API endpoints
url(r'^category/', include([
url(r'^(?P<pk>\d+)/parameters/?', CategoryParameters.as_view(), name='api-part-category-parameters'),
url(r'^parameters/', CategoryParameterList.as_view(), name='api-part-category-parameter-list'),
url(r'^(?P<pk>\d+)/?', CategoryDetail.as_view(), name='api-part-category-detail'),
url(r'^$', CategoryList.as_view(), name='api-part-category-list'),
])),

View File

@ -526,11 +526,14 @@ class CategoryParameterTemplateSerializer(InvenTreeModelSerializer):
parameter_template = PartParameterTemplateSerializer(many=False,
read_only=True)
category_detail = CategorySerializer(source='category', many=False, read_only=True)
class Meta:
model = PartCategoryParameterTemplate
fields = [
'pk',
'category',
'category_detail',
'parameter_template',
'default_value',
]

View File

@ -226,6 +226,23 @@ def get_color_theme_css(username):
return inventree_css_static_url
@register.simple_tag()
def get_available_themes(*args, **kwargs):
"""
Return the available theme choices
"""
themes = []
for key, name in ColorTheme.get_color_themes_choices():
themes.append({
'key': key,
'name': name
})
return themes
@register.filter
def keyvalue(dict, key):
"""

View File

@ -116,7 +116,7 @@ addHeaderAction('latest-parts', '{% trans "Latest Parts" %}', 'fa-newspaper');
loadSimplePartTable("#table-latest-parts", "{% url 'api-part-list' %}", {
params: {
ordering: "-creation_date",
max_results: {% settings_value "PART_RECENT_COUNT" %},
max_results: {% settings_value "PART_RECENT_COUNT" user=request.user %},
},
name: 'latest_parts',
});
@ -155,7 +155,7 @@ loadStockTable($('#table-recently-updated-stock'), {
params: {
part_detail: true,
ordering: "-updated",
max_results: {% settings_value "STOCK_RECENT_COUNT" %},
max_results: {% settings_value "STOCK_RECENT_COUNT" user=request.user %},
},
name: 'recently-updated-stock',
grouping: false,

View File

@ -1,65 +0,0 @@
{% extends "InvenTree/settings/settings.html" %}
{% load i18n %}
{% load inventree_extras %}
{% block tabs %}
{% include "InvenTree/settings/tabs.html" with tab='theme' %}
{% endblock %}
{% block subtitle %}
{% trans "Theme Settings" %}
{% endblock %}
{% block settings %}
<div class='row'>
<div class='col-sm-6'>
<h4>{% trans "Color Themes" %}</h4>
</div>
</div>
<form action="{% url 'settings-appearance' %}" method="post">
{% csrf_token %}
{% load crispy_forms_tags %}
{% crispy form %}
</form>
{% if invalid_color_theme %}
<div class="alert alert-danger alert-block" role="alert" style="display: inline-block;">
{% blocktrans %}
The CSS sheet "{{invalid_color_theme}}.css" for the currently selected color theme was not found.<br>
Please select another color theme :)
{% endblocktrans %}
</div>
{% endif %}
<div class='row'>
<div class='col-sm-6'>
<h4>{% trans "Language" %}</h4>
</div>
</div>
<div class="row">
<form action="{% url 'set_language' %}" method="post">{% csrf_token %}
<input name="next" type="hidden" value="{% url 'settings-appearance' %}">
<div class="col-sm-6" style="width: 200px;"><div id="div_id_name" class="form-group"><div class="controls ">
<select name="language" class="select form-control">
{% get_current_language as LANGUAGE_CODE %}
{% get_available_languages as LANGUAGES %}
{% get_language_info_list for LANGUAGES as languages %}
{% for language in languages %}
<option value="{{ language.code }}"{% if language.code == LANGUAGE_CODE %} selected{% endif %}>
{{ language.name_local }} ({{ language.code }})
</option>
{% endfor %}
</select>
</div></div></div>
<div class="col-sm-6" style="width: auto;">
<input type="submit" value="{% trans 'Set Language' %}" class="btn btn btn-primary">
</div>
</form>
</div>
{% endblock %}

View File

@ -0,0 +1,20 @@
{% extends "panel.html" %}
{% load i18n %}
{% load inventree_extras %}
{% block label %}barcodes{% endblock %}
{% block heading %}
{% trans "Barcode Settings" %}
{% endblock %}
{% 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>
</table>
{% endblock %}

View File

@ -1,16 +1,14 @@
{% extends "InvenTree/settings/settings.html" %}
{% extends "panel.html" %}
{% load i18n %}
{% load inventree_extras %}
{% block tabs %}
{% include "InvenTree/settings/tabs.html" with tab='build' %}
{% endblock %}
{% block label %}build-order{% endblock %}
{% block subtitle %}
{% block heading %}
{% trans "Build Order Settings" %}
{% endblock %}
{% block settings %}
{% block content %}
<table class='table table-striped table-condensed'>
{% include "InvenTree/settings/header.html" %}

View File

@ -1,114 +1,33 @@
{% extends "InvenTree/settings/settings.html" %}
{% extends "panel.html" %}
{% load i18n %}
{% block tabs %}
{% include "InvenTree/settings/tabs.html" with tab='category' %}
{% endblock %}
{% block label %}category{% endblock %}
{% block subtitle %}
{% block heading %}
{% trans "Category Settings" %}
{% endblock %}
{% block settings %}
{% block content %}
<form action="{% url 'settings-category' %}" method="post">
{% csrf_token %}
{% load crispy_forms_tags %}
<div id="category-select">
{% crispy form %}
</div>
</form>
<div class='row'>
<form action=''>
<div class='col-sm-6' style='width: 250px'>
<div class='form-group'><div class='controls'>
<select name='category' id='category-select'>
<!-- Will be filled by API -->
</select>
</div></div>
</div>
</form>
</div>
{% if category %}
<hr>
<h4>{% trans "Category Parameter Templates" %}</h4>
<div id='param-buttons'>
<button class='btn btn-success' id='new-param'>
<span class='fas fa-plus-circle'></span> {% trans "New Parameter" %}
<div id='cat-param-buttons'>
<button class='btn btn-success' id='new-cat-param' disabled=''>
<div class='fas fa-plus-circle'></div> {% trans "New Parameter" %}
</button>
</div>
<table class='table table-striped table-condensed' id='param-table' data-toolbar='#param-buttons'>
<table class='table table-striped table-condensed' id='cat-param-table' data-toolbar='#cat-param-buttons'>
</table>
{% endif %}
{% endblock %}
{% block js_ready %}
{{ block.super }}
{# Convert dropdown to select2 format #}
$(document).ready(function() {
attachSelect('#category-select');
});
{% if category %}
$("#param-table").inventreeTable({
url: "{% url 'api-part-category-parameters' pk=category.pk %}",
queryParams: {
ordering: 'name',
},
formatNoMatches: function() { return '{% trans "No category parameter templates found" %}'; },
columns: [
{
field: 'pk',
title: 'ID',
visible: false,
switchable: false,
},
{
field: 'parameter_template.name',
title: '{% trans "Parameter Template" %}',
sortable: 'true',
},
{
field: 'default_value',
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 html = value
html += "<div class='btn-group float-right' role='group'>" + bEdit + bDel + "</div>";
return html;
}
}
]
});
$("#new-param").click(function() {
launchModalForm("{% url 'category-param-template-create' category.pk %}", {
success: function() {
$("#param-table").bootstrapTable('refresh');
},
});
});
$("#param-table").on('click', '.template-edit', function() {
var button = $(this);
var url = "/part/category/{{ category.pk }}/parameters/" + button.attr('pk') + "/edit/";
launchModalForm(url, {
success: function() {
$("#param-table").bootstrapTable('refresh');
}
});
});
$("#param-table").on('click', '.template-delete', function() {
var button = $(this);
var url = "/part/category/{{ category.pk }}/parameters/" + button.attr('pk') + "/delete/";
launchModalForm(url, {
success: function() {
$("#param-table").bootstrapTable('refresh');
}
});
});
{% endif %}
{% endblock %}

View File

@ -1,16 +1,14 @@
{% extends "InvenTree/settings/settings.html" %}
{% extends "panel.html" %}
{% load i18n %}
{% load inventree_extras %}
{% block tabs %}
{% include "InvenTree/settings/tabs.html" with tab='currencies' %}
{% endblock %}
{% block label %}currencies{% endblock %}
{% block subtitle %}
{% block heading %}
{% trans "Currency Settings" %}
{% endblock %}
{% block settings %}
{% block content %}
<table class='table table-striped table-condensed'>
{% include "InvenTree/settings/header.html" %}
@ -55,8 +53,4 @@
</tbody>
</table>
{% endblock %}
{% block js_ready %}
{{ block.super }}
{% endblock %}

View File

@ -1,16 +1,15 @@
{% extends "InvenTree/settings/settings.html" %}
{% extends "panel.html" %}
{% load i18n %}
{% load inventree_extras %}
{% block tabs %}
{% include "InvenTree/settings/tabs.html" with tab='global' %}
{% block label %}server{% endblock %}
{% block heading %}
{% trans "Server Settings" %}
{% endblock %}
{% block subtitle %}
{% trans "Global InvenTree Settings" %}
{% endblock %}
{% block settings %}
{% block content %}
<table class='table table-striped table-condensed'>
{% include "InvenTree/settings/header.html" %}
@ -23,19 +22,4 @@
</tbody>
</table>
<h4>{% trans "Barcode Settings" %}</h4>
<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>
</table>
<h4>{% trans "Search Settings" %}</h4>
<table class='table table-striped table-condensed'>
<tbody>
{% include "InvenTree/settings/setting.html" with key="SEARCH_PREVIEW_RESULTS" icon="fa-search" %}
</tbody>
</table>
{% endblock %}

View File

@ -0,0 +1,109 @@
{% load i18n %}
<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'>
<b>{% trans "User Settings" %}</b>
</li>
<li class='list-group-item' title='{% trans "Account" %}'>
<a href='#' class='nav-toggle' id='select-account'>
<span class='fas fa-user'></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 "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'>
<b>{% trans "InvenTree Settings" %}</b>
</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 "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>
{% endif %}
</ul>

View File

@ -1,15 +1,13 @@
{% extends "InvenTree/settings/settings.html" %}
{% extends "panel.html" %}
{% load i18n %}
{% block tabs %}
{% include "InvenTree/settings/tabs.html" with tab='part' %}
{% endblock %}
{% block label %}parts{% endblock %}
{% block subtitle %}
{% block heading %}
{% trans "Part Settings" %}
{% endblock %}
{% block settings %}
{% block content %}
<h4>{% trans "Part Options" %}</h4>
@ -22,7 +20,6 @@
{% include "InvenTree/settings/setting.html" with key="PART_SHOW_QUANTITY_IN_FORMS" icon="fa-hashtag" %}
{% include "InvenTree/settings/setting.html" with key="PART_SHOW_PRICE_IN_FORMS" icon="fa-dollar-sign" %}
{% include "InvenTree/settings/setting.html" with key="PART_SHOW_RELATED" icon="fa-random" %}
{% include "InvenTree/settings/setting.html" with key="PART_RECENT_COUNT" icon="fa-clock" %}
{% include "InvenTree/settings/setting.html" with key="PART_CREATE_INITIAL" icon="fa-boxes" %}
<tr><td colspan='5'></td></tr>
{% include "InvenTree/settings/setting.html" with key="PART_TEMPLATE" icon="fa-clone" %}

View File

@ -1,15 +1,13 @@
{% extends "InvenTree/settings/settings.html" %}
{% extends "panel.html" %}
{% load i18n %}
{% block tabs %}
{% include "InvenTree/settings/tabs.html" with tab='po' %}
{% endblock %}
{% block label %}purchase-order{% endblock %}
{% block subtitle %}
{% block heading %}
{% trans "Purchase Order Settings" %}
{% endblock %}
{% block settings %}
{% block content %}
<table class='table table-striped table-condensed'>
{% include "InvenTree/settings/header.html" %}
<tbody>

View File

@ -1,16 +1,14 @@
{% extends "InvenTree/settings/settings.html" %}
{% extends "panel.html" %}
{% load i18n %}
{% load inventree_extras %}
{% block tabs %}
{% include "InvenTree/settings/tabs.html" with tab='report' %}
{% endblock %}
{% block label %}reporting{% endblock %}
{% block subtitle %}
{% block heading %}
{% trans "Report Settings" %}
{% endblock %}
{% block settings %}
{% block content %}
<table class='table table-striped table-condensed'>
{% include "InvenTree/settings/header.html" %}

View File

@ -17,23 +17,28 @@
<td>
{% if setting.is_bool %}
<div>
<input fieldname='{{ setting.key }}' class='slidey' type='checkbox' data-offstyle='warning' data-onstyle='success' data-size='small' data-toggle='toggle' disabled autocomplete='off' {% if setting.as_bool %}checked=''{% endif %}>
<input fieldname='{{ setting.key.upper }}' id='setting-value-{{ setting.key.upper }}' type='checkbox' disabled='' {% if setting.as_bool %}checked=''{% endif %}>
</div>
{% else %}
{% if setting.value %}
<i><b>
{{ setting.value }}</b> {{ setting.units }}
</i>
{% else %}
<i>{% trans "No value set" %}</i>
{% endif %}
<div id='setting-{{ setting.pk }}'>
<b>
<span id='setting-value-{{ setting.key.upper }}' fieldname='{{ setting.key.upper }}'>
{% if setting.value %}
{{ setting.value }}
{% else %}
<i>{% trans "No value set" %}</i>
{% endif %}
</span>
</b>
{{ setting.units }}
</div>
{% endif %}
<td>
{% trans setting.description %}
</td>
<td>
<div class='btn-group float-right'>
<button class='btn btn-default btn-glyph btn-edit-setting' pk='{{ setting.pk }}' setting='{{ key }}' title='{% trans "Edit setting" %}' {% if user_setting %}user='{{request.user.id}}'{% endif %}>
<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 %}>
<span class='fas fa-edit icon-green'></span>
</button>
</div>

View File

@ -8,30 +8,31 @@
{% inventree_title %} | {% trans "Settings" %}
{% endblock %}
{% block menubar %}
{% include "InvenTree/settings/navbar.html" %}
{% endblock %}
{% block content %}
<div class='settings-container'>
<h3>InvenTree {% trans "Settings" %}</h3>
<hr>
{% include "InvenTree/settings/user.html" %}
{% include "InvenTree/settings/user_settings.html" %}
{% include "InvenTree/settings/user_homepage.html" %}
{% include "InvenTree/settings/user_search.html" %}
<div class='settings-nav'>
{% block tabs %}
{% include "InvenTree/settings/tabs.html" %}
{% endblock %}
</div>
{% if user.is_staff %}
<div class='settings-content'>
<h3>
{% block subtitle %}
SUBTITLE GOES HERE
{% endblock %}
</h3>
<hr>
{% block settings %}
{% endblock %}
</div>
{% include "InvenTree/settings/global.html" %}
{% include "InvenTree/settings/barcode.html" %}
{% include "InvenTree/settings/currencies.html" %}
{% include "InvenTree/settings/report.html" %}
{% include "InvenTree/settings/part.html" %}
{% include "InvenTree/settings/category.html" %}
{% include "InvenTree/settings/stock.html" %}
{% include "InvenTree/settings/build.html" %}
{% include "InvenTree/settings/po.html" %}
{% include "InvenTree/settings/so.html" %}
</div>
{% endif %}
{% endblock %}
@ -53,10 +54,201 @@ $('table').find('.btn-edit-setting').click(function() {
launchModalForm(
url,
{
success: function(response) {
if (response.is_bool) {
var enabled = response.value.toLowerCase() == 'true';
$(`#setting-value-${setting}`).prop('checked', enabled);
} else {
$(`#setting-value-${setting}`).html(response.value);
}
}
}
);
});
$("#edit-user").on('click', function() {
launchModalForm(
"{% url 'edit-user' %}",
{
reload: true,
}
);
});
$("#edit-password").on('click', function() {
launchModalForm(
"{% url 'set-password' %}",
{
reload: true,
}
);
});
$('#category-select').select2({
placeholder: '',
width: '100%',
ajax: {
url: '{% url "api-part-category-list" %}',
dataType: 'json',
delay: 250,
cache: false,
data: function(params) {
if (!params.page) {
offset = 0;
} else {
offset = (params.page - 1) * 25;
}
return {
search: params.term,
offset: offset,
limit: 25,
};
},
processResults: function(response) {
var data = [];
var more = false;
if ('count' in response && 'results' in response) {
// Response is paginated
data = response.results;
// Any more data available?
if (response.next) {
more = true;
}
} else {
// Non-paginated response
data = response;
}
// Each 'row' must have the 'id' attribute
for (var idx = 0; idx < data.length; idx++) {
data[idx].id = data[idx].pk;
data[idx].text = data[idx].pathstring;
}
// Ref: https://select2.org/data-sources/formats
var results = {
results: data,
pagination: {
more: more,
}
};
return results;
}
},
});
$('#cat-param-table').inventreeTable({
formatNoMatches: function() { return '{% trans "No category parameter templates found" %}'; },
columns: [
{
field: 'pk',
title: 'ID',
visible: false,
switchable: false,
},
{
field: 'parameter_template.name',
title: '{% trans "Parameter Template" %}',
sortable: 'true',
},
{
field: 'category_detail.pathstring',
title: '{% trans "Category" %}',
},
{
field: 'default_value',
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 html = value
html += "<div class='btn-group float-right' role='group'>" + bEdit + bDel + "</div>";
return html;
}
}
]
});
function loadTemplateTable(pk) {
console.log('refresh:', pk);
// Enable the buttons
$('#new-cat-param').removeAttr('disabled');
// Load the parameter table
$("#cat-param-table").bootstrapTable('refresh', {
query: {
category: pk,
},
url: '{% url "api-part-category-parameter-list" %}',
});
}
$('body').on('change', '#category-select', function() {
var pk = $(this).val();
loadTemplateTable(pk);
});
$("#new-cat-param").click(function() {
var pk = $('#category-select').val();
launchModalForm(`/part/category/${pk}/parameters/new/`, {
success: function() {
$("#cat-param-table").bootstrapTable('refresh');
},
});
});
$("#cat-param-table").on('click', '.template-edit', function() {
var category = $('#category-select').val();
var pk = $(this).attr('pk');
var url = `/part/category/${category}/parameters/${pk}/edit/`;
launchModalForm(url, {
success: function() {
$("#cat-param-table").bootstrapTable('refresh');
}
});
});
$("#cat-param-table").on('click', '.template-delete', function() {
var category = $('#category-select').val();
var pk = $(this).attr('pk');
var url = `/part/category/${category}/parameters/${pk}/delete/`;
launchModalForm(url, {
success: function() {
$("#cat-param-table").bootstrapTable('refresh');
}
});
});
enableNavbar({
label: 'settings',
toggleId: '#item-menu-toggle',
});
attachNavCallbacks({
name: 'settings',
default: 'account'
});
{% endblock %}

View File

@ -1,15 +1,13 @@
{% extends "InvenTree/settings/settings.html" %}
{% extends "panel.html" %}
{% load i18n %}
{% block tabs %}
{% include "InvenTree/settings/tabs.html" with tab='so' %}
{% endblock %}
{% block label %}sales-order{% endblock %}
{% block subtitle %}
{% block heading %}
{% trans "Sales Order Settings" %}
{% endblock %}
{% block settings %}
{% block content %}
<table class='table table-striped table-condensed'>
{% include "InvenTree/settings/header.html" %}

View File

@ -1,22 +1,18 @@
{% extends "InvenTree/settings/settings.html" %}
{% extends "panel.html" %}
{% load i18n %}
{% block tabs %}
{% include "InvenTree/settings/tabs.html" with tab='stock' %}
{% endblock %}
{% block label %}stock{% endblock %}
{% block subtitle %}
{% block heading %}
{% trans "Stock Settings" %}
{% endblock %}
{% block settings %}
<h4>{% trans "Stock Options" %}</h4>
{% 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_RECENT_COUNT" icon="fa-clock" %}
{% include "InvenTree/settings/setting.html" with key="STOCK_ENABLE_EXPIRY" icon="fa-stopwatch" %}
{% include "InvenTree/settings/setting.html" with key="STOCK_STALE_DAYS" icon="fa-calendar" %}
{% include "InvenTree/settings/setting.html" with key="STOCK_ALLOW_EXPIRED_SALE" icon="fa-truck" %}

View File

@ -1,46 +0,0 @@
{% load i18n %}
<h4><span class='fas fa-user'></span> {% trans "User Settings" %}</h4>
<ul class='nav nav-pills nav-stacked'>
<li{% ifequal tab 'user' %} class='active'{% endifequal %}>
<a href="{% url 'settings-user' %}"><span class='fas fa-user'></span> {% trans "Account" %}</a>
</li>
<li{% ifequal tab 'theme' %} class='active'{% endifequal %}>
<a href="{% url 'settings-appearance' %}"><span class='fas fa-fill'></span> {% trans "Appearance" %}</a>
</li>
<li{% ifequal tab 'user_settings' %} class='active'{% endifequal %}>
<a href="{% url 'settings-user-settings' %}"><span class='fas fa-cog'></span> {% trans "User Settings" %}</a>
</li>
</ul>
{% if user.is_staff %}
<h4><span class='fas fa-cogs'></span> {% trans "InvenTree Settings" %}</h4>
<ul class='nav nav-pills nav-stacked'>
<li {% if tab == 'global' %} class='active' {% endif %}>
<a href='{% url "settings-global" %}'><span class='fas fa-globe'></span> {% trans "Global" %}</a>
</li>
<li {% if tab == 'currencies' %} class='active'{% endif %}>
<a href="{% url 'settings-currencies' %}"><span class='fas fa-dollar-sign'></span> {% trans "Currencies" %}</a>
</li>
<li {% if tab == 'report' %} class='active' {% endif %}>
<a href='{% url "settings-report" %}'><span class='fas fa-file-pdf'></span> {% trans "Report" %}</a>
</li>
<li{% ifequal tab 'category' %} class='active'{% endifequal %}>
<a href="{% url 'settings-category' %}"><span class='fa fa-sitemap'></span> {% trans "Categories" %}</a>
</li>
<li{% ifequal tab 'part' %} class='active'{% endifequal %}>
<a href="{% url 'settings-part' %}"><span class='fas fa-shapes'></span> {% trans "Parts" %}</a>
</li>
<li {% if tab == 'stock' %} class='active'{% endif %}>
<a href='{% url 'settings-stock' %}'><span class='fas fa-boxes'></span> {% trans "Stock" %}</a>
</li>
<li {% if tab == 'build' %} class='active'{% endif %}>
<a href="{% url 'settings-build' %}"><span class='fas fa-tools'></span> {% trans "Build Orders" %}</a>
</li>
<li {% if tab == 'po' %} class='active'{% endif %}>
<a href="{% url 'settings-po' %}"><span class='fas fa-shopping-cart'></span> {% trans "Purchase Orders" %}</a>
</li>
<li {% if tab == 'so' %} class='active'{% endif %}>
<a href="{% url 'settings-so' %}"><span class='fas fa-truck'></span> {% trans "Sales Orders" %}</a>
</li>
</ul>
{% endif %}

View File

@ -1,69 +1,95 @@
{% extends "InvenTree/settings/settings.html" %}
{% extends "panel.html" %}
{% load i18n %}
{% load inventree_extras %}
{% block tabs %}
{% include "InvenTree/settings/tabs.html" with tab='user' %}
{% block label %}account{% endblock %}
{% block heading %}
{% trans "Account Settings" %}
{% endblock %}
{% block subtitle %}
{% trans "User Settings" %}
{% endblock %}
{% block settings %}
<div class='container'>
<h4>{% trans "User Information" %}</h4>
<div class='btn-group' style='float: right;'>
<div class='btn btn-primary' type='button' id='edit-user' title='{% trans "Edit User Information" %}'>
<span class='fas fa-user-cog'></span> {% trans "Edit" %}
</div>
<div class='btn btn-primary' type='button' id='edit-password' title='{% trans "Change Password" %}'>
<span class='fas fa-key'></span> {% trans "Set Password" %}
</div>
{% block content %}
<div class='btn-group' style='float: right;'>
<div class='btn btn-primary' type='button' id='edit-user' title='{% trans "Edit User Information" %}'>
<span class='fas fa-user-cog'></span> {% trans "Edit" %}
</div>
<div class='btn btn-primary' type='button' id='edit-password' title='{% trans "Change Password" %}'>
<span class='fas fa-key'></span> {% trans "Set Password" %}
</div>
<table class='table table-striped table-condensed'>
<tr>
<td>{% trans "Username" %}</td>
<td>{{ user.username }}</td>
</tr>
<tr>
<td>{% trans "First Name" %}</td>
<td>{{ user.first_name }}</td>
</tr>
<tr>
<td>{% trans "Last Name" %}</td>
<td>{{ user.last_name }}</td>
</tr>
<tr>
<td>{% trans "Email Address" %}</td>
<td>{{ user.email }}</td>
</tr>
</table>
</div>
{% endblock %}
<table class='table table-striped table-condensed'>
<tr>
<td>{% trans "Username" %}</td>
<td>{{ user.username }}</td>
</tr>
<tr>
<td>{% trans "First Name" %}</td>
<td>{{ user.first_name }}</td>
</tr>
<tr>
<td>{% trans "Last Name" %}</td>
<td>{{ user.last_name }}</td>
</tr>
<tr>
<td>{% trans "Email Address" %}</td>
<td>{{ user.email }}</td>
</tr>
</table>
{% block js_ready %}
{{ block.super }}
<div class='panel-heading'>
<h4>{% trans "Theme Settings" %}</h4>
</div>
$("#edit-user").on('click', function() {
launchModalForm(
"{% url 'edit-user' %}",
{
reload: true,
}
);
});
<div class='row'>
$("#edit-password").on('click', function() {
launchModalForm(
"{% url 'set-password' %}",
{
reload: true,
}
);
});
<form action='{% url "settings-appearance" %}' method='post'>
{% csrf_token %}
<input name='next' type='hidden' value='{% url "settings" %}'>
<div class="col-sm-6" style="width: 200px;">
<div id="div_id_themes" class="form-group">
<div class="controls ">
<select name='theme' class='select form-control'>
{% get_available_themes as themes %}
{% for theme in themes %}
<option value='{{ theme.key }}'>{{ theme.name }}</option>
{% endfor %}
</select>
</div>
</div>
</div>
<div class="col-sm-6" style="width: auto;">
<input type="submit" value="{% trans 'Set Theme' %}" class="btn btn btn-primary">
</div>
</form>
</div>
<div class='panel-heading'>
<h4>{% trans "Language Settings" %}</h4>
</div>
<div class="row">
<form action="{% url 'set_language' %}" method="post">
{% csrf_token %}
<input name="next" type="hidden" value="{% url 'settings' %}">
<div class="col-sm-6" style="width: 200px;"><div id="div_id_language" class="form-group"><div class="controls ">
<select name="language" class="select form-control">
{% get_current_language as LANGUAGE_CODE %}
{% get_available_languages as LANGUAGES %}
{% get_language_info_list for LANGUAGES as languages %}
{% for language in languages %}
<option value="{{ language.code }}"{% if language.code == LANGUAGE_CODE %} selected{% endif %}>
{{ language.name_local }} ({{ language.code }})
</option>
{% endfor %}
</select>
</div></div></div>
<div class="col-sm-6" style="width: auto;">
<input type="submit" value="{% trans 'Set Language' %}" class="btn btn btn-primary">
</div>
</form>
</div>
{% endblock %}

View File

@ -0,0 +1,42 @@
{% extends "panel.html" %}
{% load i18n %}
{% load inventree_extras %}
{% block label %}user-home{% endblock %}
{% block heading %}
{% trans "Home Page Settings" %}
{% endblock %}
{% block content %}
<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 %}
{% include "InvenTree/settings/setting.html" with key="PART_RECENT_COUNT" icon="fa-clock" user_setting=True %}
{% include "InvenTree/settings/setting.html" with key="HOMEPAGE_BOM_VALIDATION" user_setting=True %}
<tr><td colspan='5'></td></tr>
{% include "InvenTree/settings/setting.html" with key="HOMEPAGE_STOCK_RECENT" icon='fa-history' user_setting=True %}
{% include "InvenTree/settings/setting.html" with key="STOCK_RECENT_COUNT" icon="fa-clock" user_setting=True %}
{% include "InvenTree/settings/setting.html" with key="HOMEPAGE_STOCK_LOW" user_setting=True %}
{% include "InvenTree/settings/setting.html" with key="HOMEPAGE_STOCK_DEPLETED" user_setting=True %}
{% include "InvenTree/settings/setting.html" with key="HOMEPAGE_STOCK_NEEDED" user_setting=True %}
{% include "InvenTree/settings/setting.html" with key="HOMEPAGE_STOCK_EXPIRED" icon='fa-calendar-alt' user_setting=True %}
{% include "InvenTree/settings/setting.html" with key="HOMEPAGE_STOCK_STALE" icon='fa-calendar-alt' user_setting=True %}
<tr><td colspan='5'></td></tr>
{% include "InvenTree/settings/setting.html" with key="HOMEPAGE_BUILD_PENDING" user_setting=True %}
{% include "InvenTree/settings/setting.html" with key="HOMEPAGE_BUILD_OVERDUE" user_setting=True %}
<tr><td colspan='5'></td></tr>
{% include "InvenTree/settings/setting.html" with key="HOMEPAGE_PO_OUTSTANDING" user_setting=True %}
{% include "InvenTree/settings/setting.html" with key="HOMEPAGE_PO_OVERDUE" user_setting=True %}
<tr><td colspan='5'></td></tr>
{% include "InvenTree/settings/setting.html" with key="HOMEPAGE_SO_OUTSTANDING" user_setting=True %}
{% include "InvenTree/settings/setting.html" with key="HOMEPAGE_SO_OVERDUE" user_setting=True %}
</tbody>
</table>
</div>
{% endblock %}

View File

@ -0,0 +1,23 @@
{% extends "panel.html" %}
{% load i18n %}
{% load inventree_extras %}
{% block label %}user-search{% endblock %}
{% block heading %}
{% trans "Search Settings" %}
{% endblock %}
{% block content %}
<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' %}
</tbody>
</table>
</div>
{% endblock %}

View File

@ -1,41 +1,21 @@
{% extends "InvenTree/settings/settings.html" %}
{% extends "panel.html" %}
{% load i18n %}
{% load inventree_extras %}
{% block tabs %}
{% include "InvenTree/settings/tabs.html" with tab='user_settings' %}
{% endblock %}
{% block label %}user-settings{% endblock %}
{% block subtitle %}
{% block heading %}
{% trans "User Settings" %}
{% endblock %}
{% block settings %}
{% block content %}
<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" user_setting=True %}
{% include "InvenTree/settings/setting.html" with key="HOMEPAGE_PART_LATEST" user_setting=True %}
{% include "InvenTree/settings/setting.html" with key="HOMEPAGE_BOM_VALIDATION" user_setting=True %}
<tr><td colspan='5'></td></tr>
{% include "InvenTree/settings/setting.html" with key="HOMEPAGE_STOCK_RECENT" user_setting=True %}
{% include "InvenTree/settings/setting.html" with key="HOMEPAGE_STOCK_LOW" user_setting=True %}
{% include "InvenTree/settings/setting.html" with key="HOMEPAGE_STOCK_DEPLETED" user_setting=True %}
{% include "InvenTree/settings/setting.html" with key="HOMEPAGE_STOCK_NEEDED" user_setting=True %}
{% include "InvenTree/settings/setting.html" with key="HOMEPAGE_STOCK_EXPIRED" user_setting=True %}
{% include "InvenTree/settings/setting.html" with key="HOMEPAGE_STOCK_STALE" user_setting=True %}
<tr><td colspan='5'></td></tr>
{% include "InvenTree/settings/setting.html" with key="HOMEPAGE_BUILD_PENDING" user_setting=True %}
{% include "InvenTree/settings/setting.html" with key="HOMEPAGE_BUILD_OVERDUE" user_setting=True %}
<tr><td colspan='5'></td></tr>
{% include "InvenTree/settings/setting.html" with key="HOMEPAGE_PO_OUTSTANDING" user_setting=True %}
{% include "InvenTree/settings/setting.html" with key="HOMEPAGE_PO_OVERDUE" user_setting=True %}
<tr><td colspan='5'></td></tr>
{% include "InvenTree/settings/setting.html" with key="HOMEPAGE_SO_OUTSTANDING" user_setting=True %}
{% include "InvenTree/settings/setting.html" with key="HOMEPAGE_SO_OVERDUE" user_setting=True %}
</tbody>
</table>
</div>
{% endblock %}

View File

@ -91,7 +91,11 @@ function inventreeDocReady() {
url: '/api/part/',
data: {
search: request.term,
limit: {% settings_value 'SEARCH_PREVIEW_RESULTS' %},
{% if request.user %}
limit: {% settings_value 'SEARCH_PREVIEW_RESULTS' user=request.user %},
{% else %}
limit: 25
{% endif %}
offset: 0
},
success: function (data) {

View File

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