diff --git a/InvenTree/InvenTree/forms.py b/InvenTree/InvenTree/forms.py index d843c1ddef..7112c2a88b 100644 --- a/InvenTree/InvenTree/forms.py +++ b/InvenTree/InvenTree/forms.py @@ -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 """ diff --git a/InvenTree/InvenTree/urls.py b/InvenTree/InvenTree/urls.py index 3cc50bc889..41ef306a50 100644 --- a/InvenTree/InvenTree/urls.py +++ b/InvenTree/InvenTree/urls.py @@ -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\d+)/edit/user', UserSettingEdit.as_view(), name='user-setting-edit'), url(r'^(?P\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 diff --git a/InvenTree/InvenTree/views.py b/InvenTree/InvenTree/views.py index 4b559642ca..9749fd60d0 100644 --- a/InvenTree/InvenTree/views.py +++ b/InvenTree/InvenTree/views.py @@ -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): diff --git a/InvenTree/common/models.py b/InvenTree/common/models.py index ec755aad58..72e8cf8060 100644 --- a/InvenTree/common/models.py +++ b/InvenTree/common/models.py @@ -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: diff --git a/InvenTree/common/views.py b/InvenTree/common/views.py index 75fc78b4e3..6cac8bbb19 100644 --- a/InvenTree/common/views.py +++ b/InvenTree/common/views.py @@ -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 diff --git a/InvenTree/part/api.py b/InvenTree/part/api.py index 8d0ad5452d..3612a1c9f9 100644 --- a/InvenTree/part/api.py +++ b/InvenTree/part/api.py @@ -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\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\d+)/?', CategoryDetail.as_view(), name='api-part-category-detail'), url(r'^$', CategoryList.as_view(), name='api-part-category-list'), ])), diff --git a/InvenTree/part/serializers.py b/InvenTree/part/serializers.py index db543b8602..9463ec9400 100644 --- a/InvenTree/part/serializers.py +++ b/InvenTree/part/serializers.py @@ -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', ] diff --git a/InvenTree/part/templatetags/inventree_extras.py b/InvenTree/part/templatetags/inventree_extras.py index a7887ec250..f930fa4467 100644 --- a/InvenTree/part/templatetags/inventree_extras.py +++ b/InvenTree/part/templatetags/inventree_extras.py @@ -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): """ diff --git a/InvenTree/templates/InvenTree/index.html b/InvenTree/templates/InvenTree/index.html index ee08777502..51f8d2ed45 100644 --- a/InvenTree/templates/InvenTree/index.html +++ b/InvenTree/templates/InvenTree/index.html @@ -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, diff --git a/InvenTree/templates/InvenTree/settings/appearance.html b/InvenTree/templates/InvenTree/settings/appearance.html deleted file mode 100644 index d0b414e423..0000000000 --- a/InvenTree/templates/InvenTree/settings/appearance.html +++ /dev/null @@ -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 %} - -
-
-

{% trans "Color Themes" %}

-
-
- -
- {% csrf_token %} - {% load crispy_forms_tags %} - {% crispy form %} -
- -{% if invalid_color_theme %} - -{% endif %} - - -
-
-

{% trans "Language" %}

-
-
- - - -
-
{% csrf_token %} - -
- -
-
- -
-
-
-{% endblock %} diff --git a/InvenTree/templates/InvenTree/settings/barcode.html b/InvenTree/templates/InvenTree/settings/barcode.html new file mode 100644 index 0000000000..32b85151d7 --- /dev/null +++ b/InvenTree/templates/InvenTree/settings/barcode.html @@ -0,0 +1,20 @@ +{% extends "panel.html" %} +{% load i18n %} +{% load inventree_extras %} + +{% block label %}barcodes{% endblock %} + +{% block heading %} +{% trans "Barcode Settings" %} +{% endblock %} + +{% block content %} + + + {% include "InvenTree/settings/header.html" %} + + {% include "InvenTree/settings/setting.html" with key="BARCODE_ENABLE" icon="fa-qrcode" %} + +
+ +{% endblock %} \ No newline at end of file diff --git a/InvenTree/templates/InvenTree/settings/build.html b/InvenTree/templates/InvenTree/settings/build.html index 7d04a8f8b7..6d16512a99 100644 --- a/InvenTree/templates/InvenTree/settings/build.html +++ b/InvenTree/templates/InvenTree/settings/build.html @@ -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 %} {% include "InvenTree/settings/header.html" %} diff --git a/InvenTree/templates/InvenTree/settings/category.html b/InvenTree/templates/InvenTree/settings/category.html index 7ec323482c..9eb595ddde 100644 --- a/InvenTree/templates/InvenTree/settings/category.html +++ b/InvenTree/templates/InvenTree/settings/category.html @@ -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 %} - - {% csrf_token %} - {% load crispy_forms_tags %} -
- {% crispy form %} -
- +
+
+
+
+ +
+
+ +
-{% if category %} -
- -

{% trans "Category Parameter Templates" %}

- -
-
-
+
-{% 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 = ""; - var bDel = ""; - - var html = value - html += "
" + bEdit + bDel + "
"; - - 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 %} diff --git a/InvenTree/templates/InvenTree/settings/currencies.html b/InvenTree/templates/InvenTree/settings/currencies.html index 6e61533e6b..85274e91aa 100644 --- a/InvenTree/templates/InvenTree/settings/currencies.html +++ b/InvenTree/templates/InvenTree/settings/currencies.html @@ -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 %} {% include "InvenTree/settings/header.html" %} @@ -55,8 +53,4 @@
-{% endblock %} - -{% block js_ready %} -{{ block.super }} {% endblock %} \ No newline at end of file diff --git a/InvenTree/templates/InvenTree/settings/global.html b/InvenTree/templates/InvenTree/settings/global.html index 0c10a13271..1723f36b72 100644 --- a/InvenTree/templates/InvenTree/settings/global.html +++ b/InvenTree/templates/InvenTree/settings/global.html @@ -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 %} {% include "InvenTree/settings/header.html" %} @@ -23,19 +22,4 @@
-

{% trans "Barcode Settings" %}

- - {% include "InvenTree/settings/header.html" %} - - {% include "InvenTree/settings/setting.html" with key="BARCODE_ENABLE" icon="fa-qrcode" %} - -
- -

{% trans "Search Settings" %}

- - - {% include "InvenTree/settings/setting.html" with key="SEARCH_PREVIEW_RESULTS" icon="fa-search" %} - -
- {% endblock %} diff --git a/InvenTree/templates/InvenTree/settings/navbar.html b/InvenTree/templates/InvenTree/settings/navbar.html new file mode 100644 index 0000000000..83bbc10fe9 --- /dev/null +++ b/InvenTree/templates/InvenTree/settings/navbar.html @@ -0,0 +1,109 @@ +{% load i18n %} + + \ No newline at end of file diff --git a/InvenTree/templates/InvenTree/settings/part.html b/InvenTree/templates/InvenTree/settings/part.html index 4f49a63cb4..3fa20820b1 100644 --- a/InvenTree/templates/InvenTree/settings/part.html +++ b/InvenTree/templates/InvenTree/settings/part.html @@ -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 %}

{% trans "Part Options" %}

@@ -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" %} {% include "InvenTree/settings/setting.html" with key="PART_TEMPLATE" icon="fa-clone" %} diff --git a/InvenTree/templates/InvenTree/settings/po.html b/InvenTree/templates/InvenTree/settings/po.html index 20e3b0074b..f8a114bb12 100644 --- a/InvenTree/templates/InvenTree/settings/po.html +++ b/InvenTree/templates/InvenTree/settings/po.html @@ -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 %} {% include "InvenTree/settings/header.html" %} diff --git a/InvenTree/templates/InvenTree/settings/report.html b/InvenTree/templates/InvenTree/settings/report.html index 4e68030ee5..b9a2bd6aec 100644 --- a/InvenTree/templates/InvenTree/settings/report.html +++ b/InvenTree/templates/InvenTree/settings/report.html @@ -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 %}
{% include "InvenTree/settings/header.html" %} diff --git a/InvenTree/templates/InvenTree/settings/setting.html b/InvenTree/templates/InvenTree/settings/setting.html index 66f3f9f3b0..1d6c785b29 100644 --- a/InvenTree/templates/InvenTree/settings/setting.html +++ b/InvenTree/templates/InvenTree/settings/setting.html @@ -17,23 +17,28 @@
{% if setting.is_bool %}
- +
{% else %} - {% if setting.value %} - - {{ setting.value }} {{ setting.units }} - - {% else %} - {% trans "No value set" %} - {% endif %} +
+ + + {% if setting.value %} + {{ setting.value }} + {% else %} + {% trans "No value set" %} + {% endif %} + + + {{ setting.units }} +
{% endif %}
{% trans setting.description %}
-
diff --git a/InvenTree/templates/InvenTree/settings/settings.html b/InvenTree/templates/InvenTree/settings/settings.html index 03cf276594..9fd069af52 100644 --- a/InvenTree/templates/InvenTree/settings/settings.html +++ b/InvenTree/templates/InvenTree/settings/settings.html @@ -8,30 +8,31 @@ {% inventree_title %} | {% trans "Settings" %} {% endblock %} +{% block menubar %} +{% include "InvenTree/settings/navbar.html" %} +{% endblock %} + {% block content %} -
-

InvenTree {% trans "Settings" %}

-
+{% include "InvenTree/settings/user.html" %} +{% include "InvenTree/settings/user_settings.html" %} +{% include "InvenTree/settings/user_homepage.html" %} +{% include "InvenTree/settings/user_search.html" %} -
- {% block tabs %} - {% include "InvenTree/settings/tabs.html" %} - {% endblock %} -
+{% if user.is_staff %} -
-

- {% block subtitle %} - SUBTITLE GOES HERE - {% endblock %} -

-
- {% block settings %} - {% endblock %} -
+{% 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" %} -
+{% 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 = ""; + var bDel = ""; + + var html = value + html += "
" + bEdit + bDel + "
"; + + 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 %} diff --git a/InvenTree/templates/InvenTree/settings/so.html b/InvenTree/templates/InvenTree/settings/so.html index 4ef1709068..2fe5680d71 100644 --- a/InvenTree/templates/InvenTree/settings/so.html +++ b/InvenTree/templates/InvenTree/settings/so.html @@ -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 %} {% include "InvenTree/settings/header.html" %} diff --git a/InvenTree/templates/InvenTree/settings/stock.html b/InvenTree/templates/InvenTree/settings/stock.html index 7cf7a94e0b..e05def09a6 100644 --- a/InvenTree/templates/InvenTree/settings/stock.html +++ b/InvenTree/templates/InvenTree/settings/stock.html @@ -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 %} -

{% trans "Stock Options" %}

+{% block content %}
{% include "InvenTree/settings/header.html" %} {% 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" %} diff --git a/InvenTree/templates/InvenTree/settings/tabs.html b/InvenTree/templates/InvenTree/settings/tabs.html deleted file mode 100644 index 846dfccd23..0000000000 --- a/InvenTree/templates/InvenTree/settings/tabs.html +++ /dev/null @@ -1,46 +0,0 @@ -{% load i18n %} - -

{% trans "User Settings" %}

- -{% if user.is_staff %} -

{% trans "InvenTree Settings" %}

- -{% endif %} diff --git a/InvenTree/templates/InvenTree/settings/user.html b/InvenTree/templates/InvenTree/settings/user.html index 1606a05cec..140d2f6b86 100644 --- a/InvenTree/templates/InvenTree/settings/user.html +++ b/InvenTree/templates/InvenTree/settings/user.html @@ -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 %} - -
-

{% trans "User Information" %}

-
-
- {% trans "Edit" %} -
-
- {% trans "Set Password" %} -
+{% block content %} +
+
+ {% trans "Edit" %} +
+
+ {% trans "Set Password" %}
- -
- - - - - - - - - - - - - - - - -
{% trans "Username" %}{{ user.username }}
{% trans "First Name" %}{{ user.first_name }}
{% trans "Last Name" %}{{ user.last_name }}
{% trans "Email Address" %}{{ user.email }}
-{% endblock %} + + + + + + + + + + + + + + + + + +
{% trans "Username" %}{{ user.username }}
{% trans "First Name" %}{{ user.first_name }}
{% trans "Last Name" %}{{ user.last_name }}
{% trans "Email Address" %}{{ user.email }}
-{% block js_ready %} -{{ block.super }} +
+

{% trans "Theme Settings" %}

+
- $("#edit-user").on('click', function() { - launchModalForm( - "{% url 'edit-user' %}", - { - reload: true, - } - ); - }); +
- $("#edit-password").on('click', function() { - launchModalForm( - "{% url 'set-password' %}", - { - reload: true, - } - ); - }); +
+ {% csrf_token %} + +
+
+
+ +
+
+
+
+ +
+
+ +
+ +
+

{% trans "Language Settings" %}

+
+ +
+
+ {% csrf_token %} + +
+ +
+
+ +
+
+
{% endblock %} \ No newline at end of file diff --git a/InvenTree/templates/InvenTree/settings/user_homepage.html b/InvenTree/templates/InvenTree/settings/user_homepage.html new file mode 100644 index 0000000000..ccaae6fa8a --- /dev/null +++ b/InvenTree/templates/InvenTree/settings/user_homepage.html @@ -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 %} + +
+ + {% include "InvenTree/settings/header.html" %} + + {% 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 %} + + {% 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 %} + + {% 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 %} + + {% 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 %} + + {% 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 %} + +
+
+{% endblock %} \ No newline at end of file diff --git a/InvenTree/templates/InvenTree/settings/user_search.html b/InvenTree/templates/InvenTree/settings/user_search.html new file mode 100644 index 0000000000..c06bfaec8d --- /dev/null +++ b/InvenTree/templates/InvenTree/settings/user_search.html @@ -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 %} + +
+ + {% include "InvenTree/settings/header.html" %} + + {% include "InvenTree/settings/setting.html" with key="SEARCH_PREVIEW_RESULTS" user_setting=True icon='fa-search' %} + +
+
+ +{% endblock %} \ No newline at end of file diff --git a/InvenTree/templates/InvenTree/settings/user_settings.html b/InvenTree/templates/InvenTree/settings/user_settings.html index 0b76b930c5..a9b9b0a82f 100644 --- a/InvenTree/templates/InvenTree/settings/user_settings.html +++ b/InvenTree/templates/InvenTree/settings/user_settings.html @@ -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 %}
{% include "InvenTree/settings/header.html" %} - - {% 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 %} - - {% 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 %} - - {% 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 %} - - {% 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 %} - - {% 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 %} - +
+ {% endblock %} diff --git a/InvenTree/templates/js/inventree.js b/InvenTree/templates/js/inventree.js index f1e9472910..aa574eae83 100644 --- a/InvenTree/templates/js/inventree.js +++ b/InvenTree/templates/js/inventree.js @@ -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) { diff --git a/InvenTree/templates/panel.html b/InvenTree/templates/panel.html new file mode 100644 index 0000000000..4fb2e87bc7 --- /dev/null +++ b/InvenTree/templates/panel.html @@ -0,0 +1,13 @@ +
+ {% block panel_heading %} +
+

{% block heading %}HEADING{% endblock %}

+
+ {% endblock %} + {% block panel_content %} +
+ {% block content %} + {% endblock %} +
+ {% endblock %} +
\ No newline at end of file