1
0
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:
jeremystretch
2021-12-21 17:05:06 -05:00
parent 70f257b1ea
commit 36d2422eef
2 changed files with 71 additions and 35 deletions

View File

@ -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)

View 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'),
),
),
}