mirror of
https://github.com/netbox-community/netbox.git
synced 2024-05-10 07:54:54 +00:00
Introduce UserPreference to define user preferences
This commit is contained in:
@ -2,9 +2,9 @@ from django import forms
|
|||||||
from django.contrib.auth.forms import AuthenticationForm, PasswordChangeForm as DjangoPasswordChangeForm
|
from django.contrib.auth.forms import AuthenticationForm, PasswordChangeForm as DjangoPasswordChangeForm
|
||||||
|
|
||||||
from utilities.forms import BootstrapMixin, DateTimePicker
|
from utilities.forms import BootstrapMixin, DateTimePicker
|
||||||
from utilities.paginator import EnhancedPaginator
|
|
||||||
from utilities.utils import flatten_dict
|
from utilities.utils import flatten_dict
|
||||||
from .models import Token, UserConfig
|
from .models import Token, UserConfig
|
||||||
|
from .preferences import PREFERENCES
|
||||||
|
|
||||||
|
|
||||||
class LoginForm(BootstrapMixin, AuthenticationForm):
|
class LoginForm(BootstrapMixin, AuthenticationForm):
|
||||||
@ -15,53 +15,45 @@ class PasswordChangeForm(BootstrapMixin, DjangoPasswordChangeForm):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
def get_page_lengths():
|
class UserConfigFormMetaclass(forms.models.ModelFormMetaclass):
|
||||||
return [
|
|
||||||
(v, str(v)) for v in EnhancedPaginator.default_page_lengths
|
def __new__(mcs, name, bases, attrs):
|
||||||
]
|
|
||||||
|
# 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):
|
class UserConfigForm(BootstrapMixin, forms.ModelForm, metaclass=UserConfigFormMetaclass):
|
||||||
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
|
|
||||||
)
|
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = UserConfig
|
model = UserConfig
|
||||||
fields = ()
|
fields = ()
|
||||||
fieldsets = (
|
fieldsets = (
|
||||||
('User Interface', (
|
('User Interface', (
|
||||||
'pagination__per_page',
|
'pagination.per_page',
|
||||||
'ui__colormode',
|
'ui.colormode',
|
||||||
)),
|
)),
|
||||||
('Miscellaneous', (
|
('Miscellaneous', (
|
||||||
'extras__configcontext__format',
|
'data_format',
|
||||||
)),
|
)),
|
||||||
)
|
)
|
||||||
|
|
||||||
def __init__(self, *args, instance=None, **kwargs):
|
def __init__(self, *args, instance=None, **kwargs):
|
||||||
|
|
||||||
# Get initial data from UserConfig instance
|
# Get initial data from UserConfig instance
|
||||||
initial_data = flatten_dict(instance.data, separator='__')
|
initial_data = flatten_dict(instance.data)
|
||||||
kwargs['initial'] = initial_data
|
kwargs['initial'] = initial_data
|
||||||
|
|
||||||
super().__init__(*args, instance=instance, **kwargs)
|
super().__init__(*args, instance=instance, **kwargs)
|
||||||
@ -69,9 +61,7 @@ class UserConfigForm(BootstrapMixin, forms.ModelForm):
|
|||||||
def save(self, *args, **kwargs):
|
def save(self, *args, **kwargs):
|
||||||
|
|
||||||
# Set UserConfig data
|
# Set UserConfig data
|
||||||
for field_name, value in self.cleaned_data.items():
|
for pref_name, value in self.cleaned_data.items():
|
||||||
pref_name = field_name.replace('__', '.')
|
|
||||||
print(f'{pref_name}: {value}')
|
|
||||||
self.instance.set(pref_name, value, commit=False)
|
self.instance.set(pref_name, value, commit=False)
|
||||||
|
|
||||||
return super().save(*args, **kwargs)
|
return super().save(*args, **kwargs)
|
||||||
|
46
netbox/users/preferences.py
Normal file
46
netbox/users/preferences.py
Normal file
@ -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'),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
}
|
Reference in New Issue
Block a user