Source code for cdh.core.forms

from typing import List, Optional

from django import forms
from django.forms.widgets import CheckboxInput, CheckboxSelectMultiple, \
    RadioSelect, Select

from cdh.core.file_loading import add_js_file


[docs]class TemplatedFormMixin: """Mixin for Django Form to enable the UU-Form styling :param str form_template: the form_template to use :param bool show_help_column: if False, the help column will be removed on every field :param bool always_show_help_column: if False, the help column will be removed on fields that don't have help texts """ template_name = 'cdh.core/form_template.html' # If False, it will hide the help column on every field show_help_column = True # If False, it will hide the help column on fields without a help text always_show_help_column = True # If False, it will supress the is-valid feedback on submit show_valid_fields = True
[docs] def get_context(self): context = super().get_context() form_was_changed = len(self.changed_data) != 0 for field, errors in context['fields']: # Fix for fields that do not set this attr if 'class' not in field.field.widget.attrs: field.field.widget.attrs['class'] = '' field.field.widget.attrs['class'] += ' form-control' if errors: field.field.widget.attrs['valid'] = 'is-invalid' field.field.widget.attrs['class'] += ' is-invalid' elif form_was_changed: # Only add if the data on the form was # changed, as that would indicate a validation step gone wrong. field.field.widget.attrs['class'] += ' is-valid' field.field.widget.attrs['valid'] = 'is-valid' context['show_help_column'] = self.show_help_column context['always_show_help_column'] = self.always_show_help_column return context
[docs]class TemplatedForm(TemplatedFormMixin, forms.Form): """Extension of the default Form to enable the UU-Form styling Uses :class:`.TemplatedFormMixin` """ pass
[docs]class TemplatedModelForm(TemplatedFormMixin, forms.ModelForm): """Extension of the default Form to enable the UU-Form styling Uses :class:`.TemplatedFormMixin` """ pass
[docs]class BootstrapSelect(Select): """Override of Django's version to use the right Bootstrap classes"""
[docs] def get_context(self, *args, **kwargs): if 'class' not in self.attrs: self.attrs['class'] = "" if 'form-control' in self.attrs['class']: self.attrs['class'] = self.attrs['class'].replace( 'form-control', 'form-select' ) else: self.attrs['class'] += ' form-select' return super().get_context(*args, **kwargs)
[docs]class BootstrapCheckboxInput(CheckboxInput): """Override of Django's version to use the right Bootstrap classes""" template_name = "cdh.core/forms/widgets/bootstrap_checkbox.html"
[docs]class BootstrapRadioSelect(RadioSelect): """Override of Django's version to use the right Bootstrap classes""" template_name = "cdh.core/forms/widgets/bootstrap_radio.html" option_template_name = "cdh.core/forms/widgets/bootstrap_radio_option.html"
[docs]class BootstrapCheckboxSelectMultiple(CheckboxSelectMultiple): """Override of Django's version to use the right Bootstrap classes""" template_name = "cdh.core/forms/widgets/bootstrap_radio.html" option_template_name = "cdh.core/forms/widgets/bootstrap_radio_option.html"
[docs]class PasswordField(forms.CharField): """Override of Django's version to use the right HTML5 input""" widget = forms.PasswordInput
[docs]class ColorInput(forms.TextInput): """Override of Django's version to use the right HTML5 input""" input_type = 'color'
[docs]class ColorField(forms.CharField): """Override of Django's version to use the right HTML5 input""" widget = ColorInput
[docs]class TelephoneInput(forms.TextInput): """Override of Django's version to use the right HTML5 input""" input_type = 'tel'
[docs]class TelephoneField(forms.CharField): """Override of Django's version to use the right HTML5 input""" widget = TelephoneInput
[docs]class DateInput(forms.DateInput): """Override of Django's version to use the right HTML5 input""" input_type = 'date'
[docs]class DateField(forms.DateField): """Override of Django's version to use the right HTML5 input""" widget = DateInput
[docs]class TimeInput(forms.TimeInput): """Override of Django's version to use the right HTML5 input""" input_type = 'time'
[docs]class TimeField(forms.TimeField): """Override of Django's version to use the right HTML5 input""" widget = TimeInput
[docs]class DateTimeInput(forms.DateTimeInput): """Override of Django's version to use the right HTML5 input""" input_type = 'datetime-local'
[docs]class DateTimeField(forms.DateTimeField): """Override of Django's version to use the right HTML5 input""" widget = DateTimeInput
[docs]class SplitDateTimeWidget(forms.SplitDateTimeWidget): """Override of Django SplitDateTimeWidget to use HTML5 fields"""
[docs] def __init__(self, attrs=None, date_format=None, time_format=None, date_attrs=None, time_attrs=None): widgets = ( DateInput( attrs=attrs if date_attrs is None else date_attrs, format=date_format, ), TimeInput( attrs=attrs if time_attrs is None else time_attrs, format=time_format, ), ) forms.MultiWidget.__init__(self, widgets)
[docs]class SplitDateTimeField(forms.SplitDateTimeField): """Override of Django SplitDateTimeField to use HTML5 fields""" widget = SplitDateTimeWidget
[docs]class TinyMCEWidget(forms.Widget): """A TinyMCE widget for HTML editting""" template_name = "cdh.core/forms/widgets/tinymce.html"
[docs] def __init__( self, menubar: bool = False, plugins: Optional[List[str]] = None, toolbar: Optional[str] = 'undo redo casechange blocks bold ' 'italic underline link bullist numlist' ' | code', *args, **kwargs ): """ All parameters should have sensible defaults. :param bool menubar: if the TinyMCE menubar needs to be shown. Probably not :param plugins: a list of TinyMCE plugins to load :param str plugins: a TinyMCE toolbar definition """ super().__init__(*args, **kwargs) if plugins is None: plugins = [ 'link', 'image', 'visualblocks', 'wordcount', 'lists', 'code', ] self.menubar = menubar self.plugins = plugins self.toolbar = toolbar add_js_file('cdh.core/js/tinymce/tinymce.min.js') add_js_file('cdh.core/js/tinymce/tinymce-jquery.min.js') add_js_file('cdh.core/js/tinymce/shim.js')
[docs] def get_context(self, *args, **kwargs): context = super().get_context(*args, **kwargs) context['menubar'] = self.menubar context['plugins'] = ",".join(self.plugins) context['toolbar'] = self.toolbar return context