Skip to content
Snippets Groups Projects
blocks.py 7.15 KiB
Newer Older
  • Learn to ignore specific revisions
  • # Credit to https://github.com/BertrandBordage for initial implementation
    
    from django import forms
    from django.db.models import BLANK_CHOICE_DASH
    from django.utils.dateparse import parse_datetime
    from django.utils.encoding import force_text
    from django.utils.text import slugify
    from django.utils.translation import ugettext_lazy as _
    from unidecode import unidecode
    from wagtail.wagtailcore.blocks import (
        StructBlock, TextBlock, CharBlock, BooleanBlock, ListBlock, StreamBlock,
    
        DateBlock, TimeBlock, DateTimeBlock, ChoiceBlock, RichTextBlock,StaticBlock
    
    )
    
    
    class FormFieldBlock(StructBlock):
        field_label = CharBlock(label=_('Label'))
        help_text = TextBlock(required=False, label=_('Help text'))
    
        field_class = forms.CharField
        widget = None
    
        def get_slug(self, struct_value):
            return force_text(slugify(unidecode(struct_value['field_label'])))
    
        def get_field_class(self, struct_value):
            return self.field_class
    
        def get_widget(self, struct_value):
            return self.widget
    
        def get_field_kwargs(self, struct_value):
            kwargs = {'label': struct_value['field_label'],
                      'help_text': struct_value['help_text'],
                      'required': struct_value.get('required', False)}
            if 'default_value' in struct_value:
                kwargs['initial'] = struct_value['default_value']
            form_widget = self.get_widget(struct_value)
            if form_widget is not None:
                kwargs['widget'] = form_widget
            return kwargs
    
        def get_field(self, struct_value):
            return self.get_field_class(struct_value)(
                **self.get_field_kwargs(struct_value))
    
    
    class OptionalFormFieldBlock(FormFieldBlock):
        required = BooleanBlock(label=_('Required'), required=False)
    
    
    CHARFIELD_FORMATS = [
        ('email', _('Email')),
        ('url', _('URL')),
    ]
    
    
    Todd Dembrey's avatar
    Todd Dembrey committed
    
    
    class CharFieldBlock(OptionalFormFieldBlock):
        format = ChoiceBlock(choices=CHARFIELD_FORMATS, required=False, label=_('Format'))
        default_value = CharBlock(required=False, label=_('Default value'))
    
        class Meta:
            label = _('Text field (single line)')
    
        def get_field_class(self, struct_value):
            text_format = struct_value['format']
            if text_format == 'url':
                return forms.URLField
            if text_format == 'email':
                return forms.EmailField
            return super().get_field_class(struct_value)
    
    
    class TextFieldBlock(OptionalFormFieldBlock):
        default_value = TextBlock(required=False, label=_('Default value'))
    
        widget = forms.Textarea(attrs={'rows': 5})
    
        class Meta:
            label = _('Text field (multi line)')
    
    
    class NumberFieldBlock(OptionalFormFieldBlock):
        default_value = CharBlock(required=False, label=_('Default value'))
    
        widget = forms.NumberInput
    
        class Meta:
            label = _('Number field')
    
    
    class CheckboxFieldBlock(FormFieldBlock):
        default_value = BooleanBlock(required=False)
    
        field_class = forms.BooleanField
    
        class Meta:
            label = _('Checkbox field')
            icon = 'tick-inverse'
    
    
    class RadioButtonsFieldBlock(OptionalFormFieldBlock):
        choices = ListBlock(CharBlock(label=_('Choice')))
    
        field_class = forms.ChoiceField
        widget = forms.RadioSelect
    
        class Meta:
            label = _('Radio buttons')
            icon = 'radio-empty'
    
        def get_field_kwargs(self, struct_value):
            kwargs = super(RadioButtonsFieldBlock,
                           self).get_field_kwargs(struct_value)
            kwargs['choices'] = [(choice, choice)
                                 for choice in struct_value['choices']]
            return kwargs
    
    
    class DropdownFieldBlock(RadioButtonsFieldBlock):
        widget = forms.Select
    
        class Meta:
            label = _('Dropdown field')
            icon = 'arrow-down-big'
    
        def get_field_kwargs(self, struct_value):
            kwargs = super(DropdownFieldBlock,
                           self).get_field_kwargs(struct_value)
            kwargs['choices'].insert(0, BLANK_CHOICE_DASH[0])
            return kwargs
    
    
    class CheckboxesFieldBlock(OptionalFormFieldBlock):
        checkboxes = ListBlock(CharBlock(label=_('Checkbox')))
    
        field_class = forms.MultipleChoiceField
        widget = forms.CheckboxSelectMultiple
    
        class Meta:
            label = _('Multiple checkboxes field')
            icon = 'list-ul'
    
        def get_field_kwargs(self, struct_value):
            kwargs = super(CheckboxesFieldBlock,
                           self).get_field_kwargs(struct_value)
            kwargs['choices'] = [(choice, choice)
                                 for choice in struct_value['checkboxes']]
            return kwargs
    
    
    class DatePickerInput(forms.DateInput):
        def __init__(self, *args, **kwargs):
            attrs = kwargs.get('attrs')
            if attrs is None:
                attrs = {}
            attrs.update({
                'data-provide': 'datepicker',
                'data-date-format': 'yyyy-mm-dd',
            })
            kwargs['attrs'] = attrs
            super().__init__(*args, **kwargs)
    
    
    class DateFieldBlock(OptionalFormFieldBlock):
        default_value = DateBlock(required=False)
    
        field_class = forms.DateField
        widget = DatePickerInput
    
        class Meta:
            label = _('Date field')
            icon = 'date'
    
    
    class HTML5TimeInput(forms.TimeInput):
        input_type = 'time'
    
    
    class TimeFieldBlock(OptionalFormFieldBlock):
        default_value = TimeBlock(required=False)
    
        field_class = forms.TimeField
        widget = HTML5TimeInput
    
        class Meta:
            label = _('Time field')
            icon = 'time'
    
    
    class DateTimePickerInput(forms.SplitDateTimeWidget):
        def __init__(self, attrs=None, date_format=None, time_format=None):
            super().__init__(attrs=attrs,
                             date_format=date_format, time_format=time_format)
            self.widgets = (
                DatePickerInput(attrs=attrs, format=date_format),
                HTML5TimeInput(attrs=attrs, format=time_format),
            )
    
        def decompress(self, value):
            if isinstance(value, str):
                value = parse_datetime(value)
            return super().decompress(value)
    
    
    class DateTimeFieldBlock(OptionalFormFieldBlock):
        default_value = DateTimeBlock(required=False)
    
        field_class = forms.SplitDateTimeField
        widget = DateTimePickerInput
    
        class Meta:
            label = _('Date+time field')
            icon = 'date'
    
    
    class ImageFieldBlock(OptionalFormFieldBlock):
        field_class = forms.ImageField
    
        class Meta:
            label = _('Image field')
            icon = 'image'
    
    
    class FileFieldBlock(OptionalFormFieldBlock):
        field_class = forms.FileField
    
        class Meta:
            label = _('File field')
            icon = 'download'
    
    
    class FormFieldsBlock(StreamBlock):
        char = CharFieldBlock(group=_('Fields'))
        text = TextFieldBlock(group=_('Fields'))
        number = NumberFieldBlock(group=_('Fields'))
        checkbox = CheckboxFieldBlock(group=_('Fields'))
        radios = RadioButtonsFieldBlock(group=_('Fields'))
        dropdown = DropdownFieldBlock(group=_('Fields'))
        checkboxes = CheckboxesFieldBlock(group=_('Fields'))
        date = DateFieldBlock(group=_('Fields'))
        time = TimeFieldBlock(group=_('Fields'))
        datetime = DateTimeFieldBlock(group=_('Fields'))
        image = ImageFieldBlock(group=_('Fields'))
        file = FileFieldBlock(group=_('Fields'))
    
        text_markup = RichTextBlock(group=_('Other'), label=_('Paragraph'))
    
    
        class Meta:
            label = _('Form fields')