Skip to content

Blocks

hypha.apply.projects.blocks

ProjectFormCustomFormFieldsBlock

ProjectFormCustomFormFieldsBlock(*args, **kwargs)

Bases: CustomFormFieldsBlock, FormFieldsBlock

A block that can be used for customizable Project-related forms: PAF, SOW, and Report.

Source code in hypha/apply/utils/blocks.py
def __init__(self, *args, **kwargs):
    # The space before " Required" is to make the group sort first. Ugly but easy, and it works.
    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)

text_markup class-attribute instance-attribute

text_markup = RichTextBlock(group=gettext_lazy('Custom'), label=gettext_lazy('Paragraph'))

header_markup class-attribute instance-attribute

header_markup = HeadingBlock(group=gettext_lazy('Custom'), label=gettext_lazy('Section header'))

char class-attribute instance-attribute

char = CharFieldBlock(group=gettext_lazy('Fields'))

multi_inputs_char class-attribute instance-attribute

multi_inputs_char = MultiInputCharFieldBlock(group=gettext_lazy('Fields'))

text class-attribute instance-attribute

text = TextFieldBlock(group=gettext_lazy('Fields'))

number class-attribute instance-attribute

number = NumberFieldBlock(group=gettext_lazy('Fields'))

checkbox class-attribute instance-attribute

checkbox = CheckboxFieldBlock(group=gettext_lazy('Fields'))

radios class-attribute instance-attribute

radios = RadioButtonsFieldBlock(group=gettext_lazy('Fields'))

dropdown class-attribute instance-attribute

dropdown = DropdownFieldBlock(group=gettext_lazy('Fields'))

checkboxes class-attribute instance-attribute

checkboxes = CheckboxesFieldBlock(group=gettext_lazy('Fields'))

date class-attribute instance-attribute

date = DateFieldBlock(group=gettext_lazy('Fields'))

time class-attribute instance-attribute

time = TimeFieldBlock(group=gettext_lazy('Fields'))

datetime class-attribute instance-attribute

datetime = DateTimeFieldBlock(group=gettext_lazy('Fields'))

image class-attribute instance-attribute

image = ImageFieldBlock(group=gettext_lazy('Fields'))

file class-attribute instance-attribute

file = FileFieldBlock(group=gettext_lazy('Fields'))

multi_file class-attribute instance-attribute

multi_file = MultiFileFieldBlock(group=gettext_lazy('Fields'))

group_toggle class-attribute instance-attribute

group_toggle = GroupToggleBlock(group=gettext_lazy('Custom'))

group_toggle_end class-attribute instance-attribute

group_toggle_end = GroupToggleEndBlock(group=gettext_lazy('Custom'))

rich_text class-attribute instance-attribute

rich_text = RichTextFieldBlock(group=gettext_lazy('Fields'))

markdown_text class-attribute instance-attribute

markdown_text = MarkdownTextFieldBlock(group=gettext_lazy('Fields'))

required_blocks class-attribute instance-attribute

required_blocks = []

single_blocks class-attribute instance-attribute

single_blocks = []

required_block_names instance-attribute

required_block_names = [name for block in required_blocks]

single_block_names instance-attribute

single_block_names = [name for block in single_blocks] + required_block_names

Meta

label class-attribute instance-attribute
label = gettext_lazy('Form fields')

clean

clean(value)
Source code in hypha/apply/utils/blocks.py
def clean(self, value):
    try:
        value = super().clean(value)
    except ValidationError as e:
        error_dict = e.params or {}
    else:
        error_dict = {}

    block_types = [block.block_type for block in value]
    missing = set(self.required_block_names) - set(block_types)

    duplicates = [
        name
        for name in find_duplicates(block_types)
        if name in self.single_block_names
    ]

    all_errors = []
    if missing:
        all_errors.append(
            "You are missing the following required fields: {}".format(
                ", ".join(prettify_names(missing))
            )
        )

    if duplicates:
        all_errors.append(
            "The following fields must be included only once: {}".format(
                ", ".join(prettify_names(duplicates))
            )
        )
        for i, block_name in enumerate(block_types):
            if block_name in duplicates:
                self.add_error_to_child(error_dict, i, "info", "Duplicate field")

    for block in value:
        if hasattr(block.block, "child_blocks"):
            for child_block_name, child_block in block.block.child_blocks.items():
                if child_block.required and not block.value[child_block_name]:
                    all_errors.append(
                        "{} cannot be empty for {}".format(
                            child_block.label, block.block.label
                        )
                    )
                if (
                    isinstance(child_block, ListBlock)
                    and child_block.child_block.required
                ):
                    for child_value in block.value[child_block_name]:
                        if not child_value:
                            all_errors.append(
                                "{} cannot be empty for {}".format(
                                    child_block.label, block.block.label
                                )
                            )

    if all_errors or error_dict:
        error_dict["__all__"] = all_errors
        raise ValidationError(all_errors, params=error_dict)

    return value

add_error_to_child

add_error_to_child(errors, child_number, field, message)
Source code in hypha/apply/utils/blocks.py
def add_error_to_child(self, errors, child_number, field, message):
    new_error = ErrorList([message])
    try:
        errors[child_number].data[0].params[field] = new_error
    except KeyError:
        errors[child_number] = ErrorList(
            [ValidationError("Error", params={field: new_error})]
        )

to_python

to_python(value)

This allows historic data to still be accessible even if a custom field type is removed from the code in the future.

Source code in hypha/apply/utils/blocks.py
def to_python(self, value):
    """
    This allows historic data to still be accessible even
    if a custom field type is removed from the code in the future.
    """
    # If the data type is missing, fallback to a CharField
    for child_data in value:
        if child_data["type"] not in self.child_blocks:
            child_data["type"] = "char"

    return StreamValue(self, value, is_lazy=True)