Преглед на файлове

Introduce UserPreference to define user preferences

jeremystretch преди 4 години
родител
ревизия
36d2422eef
променени са 2 файла, в които са добавени 71 реда и са изтрити 35 реда
  1. 25 35
      netbox/users/forms.py
  2. 46 0
      netbox/users/preferences.py

+ 25 - 35
netbox/users/forms.py

@@ -2,9 +2,9 @@ from django import forms
 from django.contrib.auth.forms import AuthenticationForm, PasswordChangeForm as DjangoPasswordChangeForm
 
 from utilities.forms import BootstrapMixin, DateTimePicker
-from utilities.paginator import EnhancedPaginator
 from utilities.utils import flatten_dict
 from .models import Token, UserConfig
+from .preferences import PREFERENCES
 
 
 class LoginForm(BootstrapMixin, AuthenticationForm):
@@ -15,53 +15,45 @@ class PasswordChangeForm(BootstrapMixin, DjangoPasswordChangeForm):
     pass
 
 
-def get_page_lengths():
-    return [
-        (v, str(v)) for v in EnhancedPaginator.default_page_lengths
-    ]
+class UserConfigFormMetaclass(forms.models.ModelFormMetaclass):
 
+    def __new__(mcs, name, bases, attrs):
 
-class UserConfigForm(BootstrapMixin, forms.ModelForm):
-    pagination__per_page = forms.TypedChoiceField(
-        label='Page length',
-        coerce=lambda val: int(val),
-        choices=get_page_lengths,
-        required=False
-    )
-    ui__colormode = forms.ChoiceField(
-        label='Color mode',
-        choices=(
-            ('light', 'Light'),
-            ('dark', 'Dark'),
-        ),
-        required=False
-    )
-    extras__configcontext__format = forms.ChoiceField(
-        label='ConfigContext format',
-        choices=(
-            ('json', 'JSON'),
-            ('yaml', 'YAML'),
-        ),
-        required=False
-    )
+        # Emulate a declared field for each supported user preference
+        preference_fields = {}
+        for field_name, preference in PREFERENCES.items():
+            field_kwargs = {
+                'label': preference.label,
+                'choices': preference.choices,
+                'help_text': preference.description,
+                'coerce': preference.coerce,
+                'required': False,
+            }
+            preference_fields[field_name] = forms.TypedChoiceField(**field_kwargs)
+        attrs.update(preference_fields)
+
+        return super().__new__(mcs, name, bases, attrs)
+
+
+class UserConfigForm(BootstrapMixin, forms.ModelForm, metaclass=UserConfigFormMetaclass):
 
     class Meta:
         model = UserConfig
         fields = ()
         fieldsets = (
             ('User Interface', (
-                'pagination__per_page',
-                'ui__colormode',
+                'pagination.per_page',
+                'ui.colormode',
             )),
             ('Miscellaneous', (
-                'extras__configcontext__format',
+                'data_format',
             )),
         )
 
     def __init__(self, *args, instance=None, **kwargs):
 
         # Get initial data from UserConfig instance
-        initial_data = flatten_dict(instance.data, separator='__')
+        initial_data = flatten_dict(instance.data)
         kwargs['initial'] = initial_data
 
         super().__init__(*args, instance=instance, **kwargs)
@@ -69,9 +61,7 @@ class UserConfigForm(BootstrapMixin, forms.ModelForm):
     def save(self, *args, **kwargs):
 
         # Set UserConfig data
-        for field_name, value in self.cleaned_data.items():
-            pref_name = field_name.replace('__', '.')
-            print(f'{pref_name}: {value}')
+        for pref_name, value in self.cleaned_data.items():
             self.instance.set(pref_name, value, commit=False)
 
         return super().save(*args, **kwargs)

+ 46 - 0
netbox/users/preferences.py

@@ -0,0 +1,46 @@
+from utilities.paginator import EnhancedPaginator
+
+
+def get_page_lengths():
+    return [
+        (v, str(v)) for v in EnhancedPaginator.default_page_lengths
+    ]
+
+
+class UserPreference:
+
+    def __init__(self, label, choices, default=None, description='', coerce=lambda x: x):
+        self.label = label
+        self.choices = choices
+        self.default = default if default is not None else choices[0]
+        self.description = description
+        self.coerce = coerce
+
+
+PREFERENCES = {
+
+    # User interface
+    'ui.colormode': UserPreference(
+        label='Color mode',
+        choices=(
+            ('light', 'Light'),
+            ('dark', 'Dark'),
+        ),
+        default='light',
+    ),
+    'pagination.per_page': UserPreference(
+        label='Page length',
+        choices=get_page_lengths(),
+        coerce=lambda x: int(x)
+    ),
+
+    # Miscellaneous
+    'data_format': UserPreference(
+        label='Data format',
+        choices=(
+            ('json', 'JSON'),
+            ('yaml', 'YAML'),
+        ),
+    ),
+
+}