From 3d8ebb6322745709ac911c72f4df380280a03729 Mon Sep 17 00:00:00 2001 From: Todd Dembrey <todd.dembrey@torchbox.com> Date: Wed, 26 Sep 2018 14:48:53 +0100 Subject: [PATCH] Add the concept of single include block as alternative to required --- opentech/apply/funds/blocks.py | 16 ++++++++++++++-- opentech/apply/utils/blocks.py | 27 ++++++++++++++++++--------- 2 files changed, 32 insertions(+), 11 deletions(-) diff --git a/opentech/apply/funds/blocks.py b/opentech/apply/funds/blocks.py index 614bf4918..d0d8b78ad 100644 --- a/opentech/apply/funds/blocks.py +++ b/opentech/apply/funds/blocks.py @@ -6,7 +6,16 @@ from django.utils.translation import ugettext_lazy as _ from addressfield.fields import AddressField from opentech.apply.categories.blocks import CategoryQuestionBlock from opentech.apply.stream_forms.blocks import FormFieldsBlock -from opentech.apply.utils.blocks import MustIncludeFieldBlock, CustomFormFieldsBlock, RichTextFieldBlock +from opentech.apply.utils.blocks import ( + CustomFormFieldsBlock, + MustIncludeFieldBlock, + RichTextFieldBlock, + SingleIncludeBlock, +) + + +class ApplicationSingleIncludeFieldBlock(SingleIncludeBlock): + pass class ApplicationMustIncludeFieldBlock(MustIncludeFieldBlock): @@ -36,7 +45,7 @@ class EmailBlock(ApplicationMustIncludeFieldBlock): icon = 'mail' -class AddressFieldBlock(ApplicationMustIncludeFieldBlock): +class AddressFieldBlock(ApplicationSingleIncludeFieldBlock): name = 'address' description = 'The postal address of the user' @@ -105,6 +114,9 @@ class ApplicationCustomFormFieldsBlock(CustomFormFieldsBlock, FormFieldsBlock): category = CategoryQuestionBlock(group=_('Custom')) rich_text = RichTextFieldBlock(group=_('Fields')) required_blocks = ApplicationMustIncludeFieldBlock.__subclasses__() + single_blocks = ApplicationSingleIncludeFieldBlock.__subclasses__() REQUIRED_BLOCK_NAMES = [block.name for block in ApplicationMustIncludeFieldBlock.__subclasses__()] + +SINGLE_BLOCK_NAMES = [block.name for block in ApplicationSingleIncludeFieldBlock.__subclasses__()] diff --git a/opentech/apply/utils/blocks.py b/opentech/apply/utils/blocks.py index 898e0487a..124911764 100644 --- a/opentech/apply/utils/blocks.py +++ b/opentech/apply/utils/blocks.py @@ -8,7 +8,7 @@ from django.utils.text import mark_safe from wagtail.core.blocks import StaticBlock, StreamValue, StreamBlock -from opentech.apply.stream_forms.blocks import FormFieldBlock, TextFieldBlock +from opentech.apply.stream_forms.blocks import FormFieldBlock, OptionalFormFieldBlock, TextFieldBlock from opentech.apply.utils.options import RICH_TEXT_WIDGET @@ -45,10 +45,13 @@ class RichTextFieldBlock(TextFieldBlock): class CustomFormFieldsBlock(StreamBlock): rich_text = RichTextFieldBlock(group=_('Fields')) required_blocks = [] + single_blocks = [] def __init__(self, *args, **kwargs): child_blocks = [(block.name, block(group=_('Required'))) for block in self.required_blocks] + child_blocks += [(block.name, block(group=_('Custom'))) for block in self.single_blocks] self.required_block_names = [block.name for block in self.required_blocks] + self.single_block_names = [block.name for block in self.single_blocks] + self.required_block_names super().__init__(child_blocks, *args, **kwargs) @@ -65,7 +68,7 @@ class CustomFormFieldsBlock(StreamBlock): duplicates = [ name for name in find_duplicates(block_types) - if name in self.required_block_names + if name in self.single_block_names ] all_errors = list() @@ -76,7 +79,7 @@ class CustomFormFieldsBlock(StreamBlock): if duplicates: all_errors.append( - 'You have duplicates of the following required fields: {}'.format(', '.join(prettify_names(duplicates))) + 'You have duplicates of the following non duplicate fields: {}'.format(', '.join(prettify_names(duplicates))) ) for i, block_name in enumerate(block_types): if block_name in duplicates: @@ -110,7 +113,7 @@ class CustomFormFieldsBlock(StreamBlock): return StreamValue(self, value, is_lazy=True) -class MustIncludeStatic(StaticBlock): +class SingleIncludeStatic(StaticBlock): """Helper block which displays additional information about the must include block and helps display the error in a noticeable way. """ @@ -137,15 +140,21 @@ class MustIncludeStatic(StaticBlock): return ('wagtail.core.blocks.static_block.StaticBlock', (), {}) -class MustIncludeFieldBlock(FormFieldBlock): - """Any block inheriting from this will need to be included in the application forms - This data will also be available to query on the submission object - """ +class SingleIncludeMixin: def __init__(self, *args, **kwargs): info_name = f'{self.name.title()} Field' - child_blocks = [('info', MustIncludeStatic(label=info_name, description=self.description))] + child_blocks = [('info', SingleIncludeStatic(label=info_name, description=self.description))] super().__init__(child_blocks, *args, **kwargs) + +class SingleIncludeBlock(SingleIncludeMixin, OptionalFormFieldBlock): + """A block that is only allowed to be included once in the form, but is optional""" + + +class MustIncludeFieldBlock(SingleIncludeMixin, FormFieldBlock): + """Any block inheriting from this will need to be included in the application forms + This data will also be available to query on the submission object + """ def get_field_kwargs(self, struct_value): kwargs = super().get_field_kwargs(struct_value) kwargs['required'] = True -- GitLab