From 28585644eadb5af6b2ab69438470c27d9b772e1c Mon Sep 17 00:00:00 2001 From: eeintech Date: Wed, 9 Sep 2020 14:55:32 -0500 Subject: [PATCH] Added automatic listing of custom CSS sheets (no more hardcoded), added error message when current selection is not valid and select default theme --- InvenTree/InvenTree/forms.py | 6 ++ InvenTree/InvenTree/settings.py | 3 + InvenTree/InvenTree/views.py | 59 ++++++++++++++----- .../common/migrations/0007_colortheme.py | 6 +- InvenTree/common/models.py | 47 ++++++++++++--- .../part/templatetags/inventree_extras.py | 11 ++-- .../templates/InvenTree/settings/theme.html | 11 +++- 7 files changed, 112 insertions(+), 31 deletions(-) diff --git a/InvenTree/InvenTree/forms.py b/InvenTree/InvenTree/forms.py index 87381b775a..80df8914d3 100644 --- a/InvenTree/InvenTree/forms.py +++ b/InvenTree/InvenTree/forms.py @@ -167,6 +167,8 @@ class SetPasswordForm(HelperForm): class ColorThemeSelectForm(forms.ModelForm): """ Form for setting color theme """ + name = forms.ChoiceField(choices=(), required=False) + class Meta: model = ColorTheme fields = [ @@ -175,6 +177,10 @@ class ColorThemeSelectForm(forms.ModelForm): 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 diff --git a/InvenTree/InvenTree/settings.py b/InvenTree/InvenTree/settings.py index 24ba9278c8..7e398a9c34 100644 --- a/InvenTree/InvenTree/settings.py +++ b/InvenTree/InvenTree/settings.py @@ -82,6 +82,9 @@ STATICFILES_DIRS = [ os.path.join(BASE_DIR, 'InvenTree', 'static'), ] +# Color Themes Directory +STATIC_COLOR_THEMES_DIR = os.path.join(STATIC_ROOT, 'css', 'color-themes') + # Web URL endpoint for served media files MEDIA_URL = '/media/' diff --git a/InvenTree/InvenTree/views.py b/InvenTree/InvenTree/views.py index 69649edad9..3f9bc5b0a9 100644 --- a/InvenTree/InvenTree/views.py +++ b/InvenTree/InvenTree/views.py @@ -565,7 +565,7 @@ class ColorThemeSelectView(FormView): template_name = "InvenTree/settings/theme.html" def get_user_theme(self): - """ Get user color theme """ + """ Get current user color theme """ try: user_theme = ColorTheme.objects.filter(user=self.request.user).get() except ColorTheme.DoesNotExist: @@ -574,32 +574,61 @@ class ColorThemeSelectView(FormView): return user_theme def get_initial(self): - """ Select user theme """ + """ Select current user color theme as initial choice """ + initial = super(ColorThemeSelectView, self).get_initial() + user_theme = self.get_user_theme() if user_theme: initial['name'] = user_theme.name return initial - def post(self, request, *args, **kwargs): - """ Save user color theme """ - form = self.get_form() - if form.is_valid(): - theme_select = form.cleaned_data['name'] - # Get current user theme - user_theme = self.get_user_theme() - - # Create theme entry if user did not select one yet - if not user_theme: - user_theme = ColorTheme() + 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() + + # Get current user theme + user_theme = self.get_user_theme() + + # Create theme entry if user did not select one yet + if not user_theme: + user_theme = ColorTheme() + user_theme.user = request.user + + if form.is_valid(): + theme_selected = form.cleaned_data['name'] + # Set color theme to form selection - user_theme.user = str(request.user) - user_theme.name = theme_select + 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) diff --git a/InvenTree/common/migrations/0007_colortheme.py b/InvenTree/common/migrations/0007_colortheme.py index c56e1c58fd..467e3e835f 100644 --- a/InvenTree/common/migrations/0007_colortheme.py +++ b/InvenTree/common/migrations/0007_colortheme.py @@ -1,4 +1,4 @@ -# Generated by Django 3.0.7 on 2020-09-08 21:35 +# Generated by Django 3.0.7 on 2020-09-09 19:50 from django.db import migrations, models @@ -14,8 +14,8 @@ class Migration(migrations.Migration): name='ColorTheme', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('name', models.CharField(blank=True, choices=[('', 'Default'), ('darker', 'Darker'), ('dark-reader', 'Dark Reader')], default='', max_length=20)), - ('user', models.CharField(max_length=150)), + ('name', models.CharField(blank=True, default='', max_length=20)), + ('user', models.CharField(max_length=150, unique=True)), ], ), ] diff --git a/InvenTree/common/models.py b/InvenTree/common/models.py index 4de5a037e9..b8e9959f01 100644 --- a/InvenTree/common/models.py +++ b/InvenTree/common/models.py @@ -6,7 +6,10 @@ These models are 'generic' and do not fit a particular business logic object. # -*- coding: utf-8 -*- from __future__ import unicode_literals +import os + from django.db import models +from django.conf import settings from django.utils.translation import ugettext as _ from django.core.validators import MinValueValidator, MaxValueValidator from django.core.exceptions import ValidationError @@ -159,14 +162,44 @@ class Currency(models.Model): class ColorTheme(models.Model): """ Color Theme Setting """ - class ColorThemeChoices(models.TextChoices): - DEFAULT = '', _('Default') - DARKER = 'darker', _('Darker') - DARK_READER = 'dark-reader', _('Dark Reader') + default_color_theme = ('', _('Default')) name = models.CharField(max_length=20, - choices=ColorThemeChoices.choices, - default=ColorThemeChoices.DEFAULT, + default='', blank=True) - user = models.CharField(max_length=150) + user = models.CharField(max_length=150, + unique=True) + + @classmethod + def get_color_themes_choices(cls): + """ Get all color themes from static folder """ + + # Get files list from css/color-themes/ folder + files_list = [] + for file in os.listdir(settings.STATIC_COLOR_THEMES_DIR): + files_list.append(os.path.splitext(file)) + + # Get color themes choices (CSS sheets) + choices = [(file_name.lower(), _(file_name.replace('-', ' ').title())) + for file_name, file_ext in files_list + if file_ext == '.css' and file_name.lower() != 'default'] + + # Add default option as empty option + choices.insert(0, cls.default_color_theme) + + return choices + + @classmethod + def is_valid_choice(cls, user_color_theme): + """ Check if color theme is valid choice """ + try: + user_color_theme_name = user_color_theme.name + except AttributeError: + return False + + for color_theme in cls.get_color_themes_choices(): + if user_color_theme_name == color_theme[0]: + return True + + return False diff --git a/InvenTree/part/templatetags/inventree_extras.py b/InvenTree/part/templatetags/inventree_extras.py index 55e6ae4eb8..f7bf65abc0 100644 --- a/InvenTree/part/templatetags/inventree_extras.py +++ b/InvenTree/part/templatetags/inventree_extras.py @@ -94,14 +94,15 @@ def inventree_setting(key, *args, **kwargs): @register.simple_tag() def get_color_theme_css(username): try: - user_theme = ColorTheme.objects.filter(user=username).get().name - if not user_theme: - user_theme = 'default' + user_theme = ColorTheme.objects.filter(user=username).get() + user_theme_name = user_theme.name + if not user_theme_name or not ColorTheme.is_valid_choice(user_theme): + user_theme_name = 'default' except ColorTheme.DoesNotExist: - user_theme = 'default' + user_theme_name = 'default' # Build path to CSS sheet - inventree_css_sheet = os.path.join('css', 'color-themes', user_theme + '.css') + 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) diff --git a/InvenTree/templates/InvenTree/settings/theme.html b/InvenTree/templates/InvenTree/settings/theme.html index dcccb7d4c9..90f148b468 100644 --- a/InvenTree/templates/InvenTree/settings/theme.html +++ b/InvenTree/templates/InvenTree/settings/theme.html @@ -18,6 +18,15 @@ {% csrf_token %} {% load crispy_forms_tags %} {% crispy form %} - + + +{% if invalid_color_theme %} + +{% endif %} {% endblock %}