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

This commit is contained in:
Matthias 2021-11-12 07:51:25 +01:00
commit e542a8f8e3
No known key found for this signature in database
GPG Key ID: F50EF5741D33E076
9 changed files with 2743 additions and 2005 deletions

File diff suppressed because one or more lines are too long

View File

@ -12,11 +12,31 @@ class SettingsAdmin(ImportExportModelAdmin):
list_display = ('key', 'value') list_display = ('key', 'value')
def get_readonly_fields(self, request, obj=None):
"""
Prevent the 'key' field being edited once the setting is created
"""
if obj:
return ['key']
else:
return []
class UserSettingsAdmin(ImportExportModelAdmin): class UserSettingsAdmin(ImportExportModelAdmin):
list_display = ('key', 'value', 'user', ) list_display = ('key', 'value', 'user', )
def get_readonly_fields(self, request, obj=None):
"""
Prevent the 'key' field being edited once the setting is created
"""
if obj:
return ['key']
else:
return []
class WebhookAdmin(ImportExportModelAdmin): class WebhookAdmin(ImportExportModelAdmin):

View File

@ -1,10 +1,30 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import logging
from django.apps import AppConfig from django.apps import AppConfig
logger = logging.getLogger('inventree')
class CommonConfig(AppConfig): class CommonConfig(AppConfig):
name = 'common' name = 'common'
def ready(self): def ready(self):
pass
self.clear_restart_flag()
def clear_restart_flag(self):
"""
Clear the SERVER_RESTART_REQUIRED setting
"""
try:
import common.models
if common.models.InvenTreeSetting.get_setting('SERVER_RESTART_REQUIRED'):
logger.info("Clearing SERVER_RESTART_REQUIRED flag")
common.models.InvenTreeSetting.set_setting('SERVER_RESTART_REQUIRED', False, None)
except:
pass

View File

@ -71,13 +71,15 @@ class BaseInvenTreeSetting(models.Model):
Enforce validation and clean before saving Enforce validation and clean before saving
""" """
self.key = str(self.key).upper()
self.clean() self.clean()
self.validate_unique() self.validate_unique()
super().save() super().save()
@classmethod @classmethod
def allValues(cls, user=None): def allValues(cls, user=None, exclude_hidden=False):
""" """
Return a dict of "all" defined global settings. Return a dict of "all" defined global settings.
@ -102,9 +104,15 @@ class BaseInvenTreeSetting(models.Model):
for key in cls.GLOBAL_SETTINGS.keys(): for key in cls.GLOBAL_SETTINGS.keys():
if key.upper() not in settings: if key.upper() not in settings:
settings[key.upper()] = cls.get_setting_default(key) settings[key.upper()] = cls.get_setting_default(key)
if exclude_hidden:
hidden = cls.GLOBAL_SETTINGS[key].get('hidden', False)
if hidden:
# Remove hidden items
del settings[key.upper()]
for key, value in settings.items(): for key, value in settings.items():
validator = cls.get_setting_validator(key) validator = cls.get_setting_validator(key)
@ -568,6 +576,17 @@ class InvenTreeSetting(BaseInvenTreeSetting):
even if that key does not exist. even if that key does not exist.
""" """
def save(self, *args, **kwargs):
"""
When saving a global setting, check to see if it requires a server restart.
If so, set the "SERVER_RESTART_REQUIRED" setting to True
"""
super().save()
if self.requires_restart():
InvenTreeSetting.set_setting('SERVER_REQUIRES_RESTART', True, None)
""" """
Dict of all global settings values: Dict of all global settings values:
@ -586,6 +605,14 @@ class InvenTreeSetting(BaseInvenTreeSetting):
GLOBAL_SETTINGS = { GLOBAL_SETTINGS = {
'SERVER_RESTART_REQUIRED': {
'name': _('Restart required'),
'description': _('A setting has been changed which requires a server restart'),
'default': False,
'validator': bool,
'hidden': True,
},
'INVENTREE_INSTANCE': { 'INVENTREE_INSTANCE': {
'name': _('InvenTree Instance Name'), 'name': _('InvenTree Instance Name'),
'default': 'InvenTree server', 'default': 'InvenTree server',
@ -983,6 +1010,18 @@ class InvenTreeSetting(BaseInvenTreeSetting):
return self.__class__.get_setting(self.key) return self.__class__.get_setting(self.key)
def requires_restart(self):
"""
Return True if this setting requires a server restart after changing
"""
options = InvenTreeSetting.GLOBAL_SETTINGS.get(self.key, None)
if options:
return options.get('requires_restart', False)
else:
return False
class InvenTreeUserSetting(BaseInvenTreeSetting): class InvenTreeUserSetting(BaseInvenTreeSetting):
""" """
@ -1316,9 +1355,6 @@ def get_price(instance, quantity, moq=True, multiples=True, currency=None, break
class ColorTheme(models.Model): class ColorTheme(models.Model):
""" Color Theme Setting """ """ Color Theme Setting """
default_color_theme = ('', _('Default'))
name = models.CharField(max_length=20, name = models.CharField(max_length=20,
default='', default='',
blank=True) blank=True)
@ -1338,10 +1374,7 @@ class ColorTheme(models.Model):
# Get color themes choices (CSS sheets) # Get color themes choices (CSS sheets)
choices = [(file_name.lower(), _(file_name.replace('-', ' ').title())) choices = [(file_name.lower(), _(file_name.replace('-', ' ').title()))
for file_name, file_ext in files_list for file_name, file_ext in files_list
if file_ext == '.css' and file_name.lower() != 'default'] if file_ext == '.css']
# Add default option as empty option
choices.insert(0, cls.default_color_theme)
return choices return choices

View File

@ -251,6 +251,15 @@ def global_settings(*args, **kwargs):
return InvenTreeSetting.allValues() return InvenTreeSetting.allValues()
@register.simple_tag()
def visible_global_settings(*args, **kwargs):
"""
Return any global settings which are not marked as 'hidden'
"""
return InvenTreeSetting.allValues(exclude_hidden=True)
@register.simple_tag() @register.simple_tag()
def progress_bar(val, max, *args, **kwargs): def progress_bar(val, max, *args, **kwargs):
""" """
@ -292,6 +301,19 @@ def progress_bar(val, max, *args, **kwargs):
@register.simple_tag() @register.simple_tag()
def get_color_theme_css(username): def get_color_theme_css(username):
user_theme_name = get_user_color_theme(username)
# Build path to CSS sheet
inventree_css_sheet = os.path.join('css', 'color-themes', user_theme_name + '.css')
# Build static URL
inventree_css_static_url = os.path.join(settings.STATIC_URL, inventree_css_sheet)
return inventree_css_static_url
@register.simple_tag()
def get_user_color_theme(username):
""" Get current user color theme """
try: try:
user_theme = ColorTheme.objects.filter(user=username).get() user_theme = ColorTheme.objects.filter(user=username).get()
user_theme_name = user_theme.name user_theme_name = user_theme.name
@ -300,13 +322,7 @@ def get_color_theme_css(username):
except ColorTheme.DoesNotExist: except ColorTheme.DoesNotExist:
user_theme_name = 'default' user_theme_name = 'default'
# Build path to CSS sheet return user_theme_name
inventree_css_sheet = os.path.join('css', 'color-themes', user_theme_name + '.css')
# Build static URL
inventree_css_static_url = os.path.join(settings.STATIC_URL, inventree_css_sheet)
return inventree_css_static_url
@register.simple_tag() @register.simple_tag()

View File

@ -170,35 +170,6 @@
</div> </div>
<div class='panel-heading'>
<h4>{% trans "Theme Settings" %}</h4>
</div>
<div class='row'>
<div class='col-sm-6'>
<form action='{% url "settings-appearance" %}' method='post'>
{% csrf_token %}
<input name='next' type='hidden' value='{% url "settings" %}'>
<label for='theme' class=' requiredField'>
{% trans "Select theme" %}
</label>
<div class='form-group input-group mb-3'>
<select id='theme' 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 class='input-group-append'>
<input type="submit" value="{% trans 'Set Theme' %}" class="btn btn-primary">
</div>
</div>
</form>
</div>
</div>
<div class='panel-heading'> <div class='panel-heading'>
<h4>{% trans "Language Settings" %}</h4> <h4>{% trans "Language Settings" %}</h4>
</div> </div>

View File

@ -21,4 +21,33 @@
</table> </table>
</div> </div>
<div class='panel-heading'>
<h4>{% trans "Theme Settings" %}</h4>
</div>
<div class='row'>
<div class='col-sm-6'>
<form action='{% url "settings-appearance" %}' method='post'>
{% csrf_token %}
<input name='next' type='hidden' value='{% url "settings" %}'>
<label for='theme' class=' requiredField'>
{% trans "Select theme" %}
</label>
<div class='form-group input-group mb-3'>
<select id='theme' name='theme' class='select form-control'>
{% get_available_themes as themes %}
{% get_user_color_theme request.user.username as user_theme %}
{% for theme in themes %}
<option value='{{ theme.key }}'{% if theme.key == user_theme %} selected{% endif%}>{{ theme.name }}</option>
{% endfor %}
</select>
<div class='input-group-append'>
<input type="submit" value="{% trans 'Set Theme' %}" class="btn btn-primary">
</div>
</div>
</form>
</div>
</div>
{% endblock %} {% endblock %}

View File

@ -5,6 +5,7 @@
{% settings_value 'BARCODE_ENABLE' as barcodes %} {% settings_value 'BARCODE_ENABLE' as barcodes %}
{% settings_value 'REPORT_ENABLE_TEST_REPORT' as test_report_enabled %} {% settings_value 'REPORT_ENABLE_TEST_REPORT' as test_report_enabled %}
{% settings_value "REPORT_ENABLE" as report_enabled %} {% settings_value "REPORT_ENABLE" as report_enabled %}
{% settings_value "SERVER_RESTART_REQUIRED" as server_restart_required %}
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
@ -86,6 +87,21 @@
</div> </div>
<main class='col ps-md-2 pt-2 pe-2'> <main class='col ps-md-2 pt-2 pe-2'>
{% if server_restart_required %}
<div class='notification-area' id='restart-required'>
<div id='alert-restart-server' class='alert alert-danger' role='alert'>
<span class='fas fa-server'></span>
<b>{% trans "Server Restart Required" %}</b>
<small>
<br>
{% trans "A configuration option has been changed which requires a server restart" %}.
<br>
{% trans "Contact your system administrator for further information" %}
</small>
</div>
</div>
{% endif %}
{% block alerts %} {% block alerts %}
<div class='notification-area' id='alerts'> <div class='notification-area' id='alerts'>
<!-- Div for displayed alerts --> <!-- Div for displayed alerts -->

View File

@ -13,7 +13,7 @@ const user_settings = {
{% endfor %} {% endfor %}
}; };
{% global_settings as GLOBAL_SETTINGS %} {% visible_global_settings as GLOBAL_SETTINGS %}
const global_settings = { const global_settings = {
{% for key, value in GLOBAL_SETTINGS.items %} {% for key, value in GLOBAL_SETTINGS.items %}
{{ key }}: {% primitive_to_javascript value %}, {{ key }}: {% primitive_to_javascript value %},