From 10dd8fad80afe542b1de58a35517990ba2df882b Mon Sep 17 00:00:00 2001
From: eeintech <eeintech@eeinte.ch>
Date: Mon, 7 Sep 2020 16:27:23 -0500
Subject: [PATCH] Renamed Theme to ColorTheme, ColorTheme is now a per-user
 selection

---
 InvenTree/InvenTree/forms.py                  | 17 ++++----
 InvenTree/InvenTree/urls.py                   |  4 +-
 InvenTree/InvenTree/views.py                  | 40 ++++++++++++-------
 .../{0007_theme.py => 0007_colortheme.py}     |  7 ++--
 InvenTree/common/models.py                    | 13 +++---
 .../part/templatetags/inventree_extras.py     |  9 +++--
 .../templates/InvenTree/settings/theme.html   |  3 +-
 InvenTree/templates/base.html                 |  2 +-
 8 files changed, 56 insertions(+), 39 deletions(-)
 rename InvenTree/common/migrations/{0007_theme.py => 0007_colortheme.py} (58%)

diff --git a/InvenTree/InvenTree/forms.py b/InvenTree/InvenTree/forms.py
index 2937ad5651..24270e0617 100644
--- a/InvenTree/InvenTree/forms.py
+++ b/InvenTree/InvenTree/forms.py
@@ -11,7 +11,8 @@ from crispy_forms.helper import FormHelper
 from crispy_forms.layout import Layout, Field
 from crispy_forms.bootstrap import PrependedText, AppendedText, PrependedAppendedText, StrictButton
 from django.contrib.auth.models import User
-from common.models import Theme
+from common.models import ColorTheme
+
 
 class HelperForm(forms.ModelForm):
     """ Provides simple integration of crispy_forms extension. """
@@ -163,24 +164,24 @@ class SetPasswordForm(HelperForm):
         ]
 
 
-class ThemeSelectForm(forms.ModelForm):
+class ColorThemeSelectForm(forms.ModelForm):
     """ Form for setting color theme
     """
 
     class Meta:
-        model = Theme
+        model = ColorTheme
         fields = [
-            'theme'
+            'name'
         ]
 
     def __init__(self, *args, **kwargs):
-        super(ThemeSelectForm, self).__init__(*args, **kwargs)
+        super(ColorThemeSelectForm, self).__init__(*args, **kwargs)
         self.helper = FormHelper()
         # Form rendering
         self.helper.form_show_labels = False
         self.helper.form_class = 'form-inline'
         # self.helper.field_template = 'bootstrap4/layout/inline_field.html'
         self.helper.layout = Layout(
-                Field('theme'),
-                StrictButton(_('Apply Theme'), css_class='btn btn-primary', type='submit')
-            )
\ No newline at end of file
+            Field('name'),
+            StrictButton(_('Apply Theme'), css_class='btn btn-primary', type='submit')
+        )
diff --git a/InvenTree/InvenTree/urls.py b/InvenTree/InvenTree/urls.py
index 0ada05753c..c433cef382 100644
--- a/InvenTree/InvenTree/urls.py
+++ b/InvenTree/InvenTree/urls.py
@@ -36,7 +36,7 @@ from django.views.generic.base import RedirectView
 from rest_framework.documentation import include_docs_urls
 
 from .views import IndexView, SearchView, DatabaseStatsView
-from .views import SettingsView, EditUserView, SetPasswordView, ThemeSelectView
+from .views import SettingsView, EditUserView, SetPasswordView, ColorThemeSelectView
 from .views import DynamicJsView
 
 from .api import InfoView
@@ -71,7 +71,7 @@ settings_urls = [
     url(r'^user/?', SettingsView.as_view(template_name='InvenTree/settings/user.html'), name='settings-user'),
     url(r'^currency/?', SettingsView.as_view(template_name='InvenTree/settings/currency.html'), name='settings-currency'),
     url(r'^part/?', SettingsView.as_view(template_name='InvenTree/settings/part.html'), name='settings-part'),
-    url(r'^theme/?', ThemeSelectView.as_view(), name='settings-theme'),
+    url(r'^theme/?', ColorThemeSelectView.as_view(), name='settings-theme'),
     url(r'^other/?', SettingsView.as_view(template_name='InvenTree/settings/other.html'), name='settings-other'),
 
     # Catch any other urls
diff --git a/InvenTree/InvenTree/views.py b/InvenTree/InvenTree/views.py
index 0fd81698e7..69649edad9 100644
--- a/InvenTree/InvenTree/views.py
+++ b/InvenTree/InvenTree/views.py
@@ -19,9 +19,9 @@ from django.views.generic.base import TemplateView
 
 from part.models import Part, PartCategory
 from stock.models import StockLocation, StockItem
-from common.models import InvenTreeSetting, Theme
+from common.models import InvenTreeSetting, ColorTheme
 
-from .forms import DeleteForm, EditUserForm, SetPasswordForm, ThemeSelectForm
+from .forms import DeleteForm, EditUserForm, SetPasswordForm, ColorThemeSelectForm
 from .helpers import str2bool
 
 from rest_framework import views
@@ -557,33 +557,45 @@ class SettingsView(TemplateView):
         return ctx
 
 
-class ThemeSelectView(FormView):
+class ColorThemeSelectView(FormView):
     """ View for selecting a color theme """
 
-    form_class = ThemeSelectForm
+    form_class = ColorThemeSelectForm
     success_url = reverse_lazy('settings-theme')
     template_name = "InvenTree/settings/theme.html"
 
+    def get_user_theme(self):
+        """ Get user color theme """
+        try:
+            user_theme = ColorTheme.objects.filter(user=self.request.user).get()
+        except ColorTheme.DoesNotExist:
+            user_theme = None
+
+        return user_theme
+
     def get_initial(self):
         """ Select user theme """
-        initial = super(ThemeSelectView, self).get_initial()
-        initial['theme'] = Theme.objects.all().get().theme
+        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['theme']
+            theme_select = form.cleaned_data['name']
+            # Get current user theme
+            user_theme = self.get_user_theme()
             
-            try:
-                user_theme = Theme.objects.all().get()
-            except Theme.DoesNotExist:
-                print('No theme selected yet')
-                user_theme = Theme()
+            # Create theme entry if user did not select one yet
+            if not user_theme:
+                user_theme = ColorTheme()
 
-            # Set color theme 
-            user_theme.theme = theme_select
+            # Set color theme to form selection
+            user_theme.user = str(request.user)
+            user_theme.name = theme_select
             user_theme.save()
 
             return self.form_valid(form)
diff --git a/InvenTree/common/migrations/0007_theme.py b/InvenTree/common/migrations/0007_colortheme.py
similarity index 58%
rename from InvenTree/common/migrations/0007_theme.py
rename to InvenTree/common/migrations/0007_colortheme.py
index ca763b0b07..b0455073a0 100644
--- a/InvenTree/common/migrations/0007_theme.py
+++ b/InvenTree/common/migrations/0007_colortheme.py
@@ -1,4 +1,4 @@
-# Generated by Django 3.0.7 on 2020-09-07 20:12
+# Generated by Django 3.0.7 on 2020-09-07 21:13
 
 from django.db import migrations, models
 
@@ -11,10 +11,11 @@ class Migration(migrations.Migration):
 
     operations = [
         migrations.CreateModel(
-            name='Theme',
+            name='ColorTheme',
             fields=[
                 ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
-                ('theme', models.CharField(blank=True, choices=[('', 'Default'), ('-darker', 'Darker')], default='', max_length=20)),
+                ('name', models.CharField(blank=True, choices=[('', 'Default'), ('-darker', 'Darker')], default='', max_length=20)),
+                ('user', models.CharField(max_length=150)),
             ],
         ),
     ]
diff --git a/InvenTree/common/models.py b/InvenTree/common/models.py
index b696c5486a..04c0082489 100644
--- a/InvenTree/common/models.py
+++ b/InvenTree/common/models.py
@@ -156,15 +156,16 @@ class Currency(models.Model):
         super().save(*args, **kwargs)
 
 
-class Theme(models.Model):
+class ColorTheme(models.Model):
     """ Color Theme setting """
 
-    class ThemeChoices(models.TextChoices):
+    class ColorThemeChoices(models.TextChoices):
         DEFAULT = '', _('Default')
         DARKER = '-darker', _('Darker')
 
-    theme = models.CharField(max_length=20,
-                             choices=ThemeChoices.choices,
-                             default=ThemeChoices.DEFAULT,
-                             blank=True)
+    name = models.CharField(max_length=20,
+                            choices=ColorThemeChoices.choices,
+                            default=ColorThemeChoices.DEFAULT,
+                            blank=True)
 
+    user = models.CharField(max_length=150)
\ No newline at end of file
diff --git a/InvenTree/part/templatetags/inventree_extras.py b/InvenTree/part/templatetags/inventree_extras.py
index d2a4f66607..0026c5e7f8 100644
--- a/InvenTree/part/templatetags/inventree_extras.py
+++ b/InvenTree/part/templatetags/inventree_extras.py
@@ -6,7 +6,7 @@ from django import template
 from InvenTree import version, settings
 from InvenTree.helpers import decimal2string
 
-from common.models import InvenTreeSetting, Theme
+from common.models import InvenTreeSetting, ColorTheme
 
 register = template.Library()
 
@@ -91,6 +91,9 @@ def inventree_setting(key, *args, **kwargs):
 
 
 @register.simple_tag()
-def get_theme_css():
-    user_theme = Theme.objects.all().get().theme
+def get_theme_css(username):
+    try:
+        user_theme = ColorTheme.objects.filter(user=username).get().name
+    except ColorTheme.DoesNotExist:
+        user_theme = ''
     return f'{settings.STATIC_URL}css/inventree' + user_theme + '.css'
diff --git a/InvenTree/templates/InvenTree/settings/theme.html b/InvenTree/templates/InvenTree/settings/theme.html
index e09739671b..55d6745281 100644
--- a/InvenTree/templates/InvenTree/settings/theme.html
+++ b/InvenTree/templates/InvenTree/settings/theme.html
@@ -21,10 +21,9 @@
                 {% csrf_token %}
                 {% load crispy_forms_tags %}
                 {% crispy form %}
-{#                 <button type='submit' class='btn btn-primary'>{% trans "Apply Theme" %}</button> #}
             </form> 
         </div>
     </div>
 </div>
 
-{% endblock %}
\ No newline at end of file
+{% endblock %}
diff --git a/InvenTree/templates/base.html b/InvenTree/templates/base.html
index 1b4cfd0af9..b622fbed26 100644
--- a/InvenTree/templates/base.html
+++ b/InvenTree/templates/base.html
@@ -39,7 +39,7 @@
 <link rel="stylesheet" href="{% static 'css/select2.css' %}">
 <link rel="stylesheet" href="{% static 'css/select2-bootstrap.css' %}">
 <link rel="stylesheet" href="{% static 'css/bootstrap-toggle.css' %}">
-<link rel="stylesheet" href="{% get_theme_css %}">
+<link rel="stylesheet" href="{% get_theme_css user.get_username %}">
 
 {% block css %}
 {% endblock %}