Closes #14740: Remove BootstrapMixin (#14841)

* Introduce custom form widget templates to apply CSS classes

* Apply both mandatory and optional CSS classes to form widgets

* Omit required & placeholder attrs

* Move annotation of field validation failures to CSS

* Remove BootstrapMixin class

* Remove obsolete ComponentTemplateImportForm class

* Remove obsolete custom forms for login & password change

* Clean up obsolete accommodations for 'required' widget attr
This commit is contained in:
Jeremy Stretch
2024-01-19 14:02:33 -05:00
committed by GitHub
parent 874685fd6f
commit da085e60c2
33 changed files with 102 additions and 180 deletions

View File

@@ -10,10 +10,9 @@ from core.forms.mixins import SyncedDataMixin
from utilities.choices import CSVDelimiterChoices, ImportFormatChoices, ImportMethodChoices
from utilities.constants import CSV_DELIMITERS
from utilities.forms.utils import parse_csv
from .mixins import BootstrapMixin
class BulkImportForm(BootstrapMixin, SyncedDataMixin, forms.Form):
class BulkImportForm(SyncedDataMixin, forms.Form):
import_method = forms.ChoiceField(
choices=ImportMethodChoices,
required=False

View File

@@ -2,7 +2,6 @@ import re
from django import forms
from django.utils.translation import gettext as _
from .mixins import BootstrapMixin
__all__ = (
'BulkEditForm',
@@ -14,7 +13,7 @@ __all__ = (
)
class ConfirmationForm(BootstrapMixin, forms.Form):
class ConfirmationForm(forms.Form):
"""
A generic confirmation form. The form is not valid unless the `confirm` field is checked.
"""
@@ -29,14 +28,14 @@ class ConfirmationForm(BootstrapMixin, forms.Form):
)
class BulkEditForm(BootstrapMixin, forms.Form):
class BulkEditForm(forms.Form):
"""
Provides bulk edit support for objects.
"""
nullable_fields = ()
class BulkRenameForm(BootstrapMixin, forms.Form):
class BulkRenameForm(forms.Form):
"""
An extendable form to be used for renaming objects in bulk.
"""
@@ -90,7 +89,7 @@ class CSVModelForm(forms.ModelForm):
return super().clean()
class FilterForm(BootstrapMixin, forms.Form):
class FilterForm(forms.Form):
"""
Base Form class for FilterSet forms.
"""
@@ -100,7 +99,7 @@ class FilterForm(BootstrapMixin, forms.Form):
)
class TableConfigForm(BootstrapMixin, forms.Form):
class TableConfigForm(forms.Form):
"""
Form for configuring user's table preferences.
"""

View File

@@ -3,68 +3,11 @@ import time
from django import forms
from django.utils.translation import gettext_lazy as _
from .widgets import APISelect, APISelectMultiple, ClearableFileInput
__all__ = (
'BootstrapMixin',
'CheckLastUpdatedMixin',
)
class BootstrapMixin:
"""
Add the base Bootstrap CSS classes to form elements.
"""
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
exempt_widgets = [
forms.FileInput,
forms.RadioSelect,
APISelect,
APISelectMultiple,
ClearableFileInput,
]
for field_name, field in self.fields.items():
css = field.widget.attrs.get('class', '')
if field.widget.__class__ in exempt_widgets:
continue
elif isinstance(field.widget, forms.CheckboxInput):
field.widget.attrs['class'] = f'{css} form-check-input'
elif isinstance(field.widget, forms.SelectMultiple) and 'size' in field.widget.attrs:
# Use native Bootstrap class for multi-line <select> widgets
field.widget.attrs['class'] = f'{css} form-select form-select-sm'
elif isinstance(field.widget, (forms.Select, forms.SelectMultiple)):
field.widget.attrs['class'] = f'{css} netbox-static-select'
else:
field.widget.attrs['class'] = f'{css} form-control'
if field.required and not isinstance(field.widget, forms.FileInput):
field.widget.attrs['required'] = 'required'
if 'placeholder' not in field.widget.attrs and field.label is not None:
field.widget.attrs['placeholder'] = field.label
def is_valid(self):
is_valid = super().is_valid()
# Apply is-invalid CSS class to fields with errors
if not is_valid:
for field_name in self.errors:
# Ignore e.g. __all__
if field := self.fields.get(field_name):
css = field.widget.attrs.get('class', '')
field.widget.attrs['class'] = f'{css} is-invalid'
return is_valid
class CheckLastUpdatedMixin(forms.Form):
"""
Checks whether the object being saved has been updated since the form was initialized. If so, validation fails.