Make radio form components reusable for nested checkboxes

For the template folders permission editing we need a nested
checkboxes form that is similar to "move folder" input, except
it's using checkboxes instead of radio buttons.

This moves most of the macros into a shared "select-input" components
file, which are wrapped by the existing radios.html by setting the
required input type.
This commit is contained in:
Alexey Bezhan
2019-02-25 14:55:26 +00:00
parent 9bdcd81c65
commit 194756bc2e
3 changed files with 113 additions and 100 deletions

View File

@@ -837,10 +837,7 @@ class RadioFieldWithNoneOption(FieldWithNoneOption, RadioField):
pass
class NestedRadioField(RadioFieldWithNoneOption):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
class NestedFieldMixin:
def children(self):
# start map with root option as a single child entry
child_map = {None: [option for option in self
@@ -864,6 +861,14 @@ class NestedRadioField(RadioFieldWithNoneOption):
return child_map
class NestedRadioField(RadioFieldWithNoneOption, NestedFieldMixin):
pass
class NestedCheckboxesField(SelectMultipleField, NestedFieldMixin):
pass
class HiddenFieldWithNoneOption(FieldWithNoneOption, HiddenField):
pass

View File

@@ -1,111 +1,27 @@
{% macro radios(
field,
hint=None,
disable=[],
option_hints={},
hide_legend=False
) %}
{% call radios_wrapper(
field, hint, disable, option_hints, hide_legend
) %}
{% for option in field %}
{{ radio(option, disable, option_hints) }}
{% endfor %}
{% endcall %}
{% from "components/select-input.html" import select, select_list, select_nested, select_wrapper %}
{% macro radios(field, hint=None, disable=[], option_hints={}, hide_legend=False) %}
{{ select(field, hint=None, disable=[], option_hints={}, hide_legend=False, input="radio") }}
{% endmacro %}
{% macro radio_list(
options,
child_map,
disable=[],
option_hints={}
) %}
<ul>
{% for option in options %}
{% if child_map[option.data] %}
{% call radio(option, disable, option_hints, as_list_item=True) %}
{{ radio_list(child_map[option.data], child_map, disable, option_hints) }}
{% endcall %}
{% else %}
{{ radio(option, disable, option_hints, as_list_item=True) }}
{% endif %}
{% endfor %}
</ul>
{% macro radio_list(options, child_map, disable=[], option_hints={}) %}
{{ select_list(options, child_map, disable=[], option_hints={}, input="radio") }}
{% endmacro %}
{% macro radios_nested(
field,
child_map,
hint=None,
disable=[],
option_hints={},
hide_legend=False
) %}
{% call radios_wrapper(
field, hint, disable, option_hints, hide_legend
) %}
<div class="radios-nested">
{{ radio_list(child_map[None], child_map, disable, option_hints) }}
</div>
{% endcall %}
{% macro radios_nested(field, child_map, hint=None, disable=[], option_hints={}, hide_legend=False) %}
{{ select_nested(field, child_map, hint=None, disable=[], option_hints={}, hide_legend=False, input="radio") }}
{% endmacro %}
{% macro radios_wrapper(field, hint=None, disable=[], option_hints={}, hide_legend=False) %}
<div class="form-group {% if field.errors %} form-group-error{% endif %}">
<fieldset>
<legend class="{{ 'form-label' if not hide_legend else '' }}">
{% if hide_legend %}<span class="visually-hidden">{% endif %}
{{ field.label.text|safe }}
{% if hide_legend %}</span>{% endif %}
{% if hint %}
<span class="form-hint">
{{ hint }}
</span>
{% endif %}
{% if field.errors %}
<span class="error-message" data-module="track-error" data-error-type="{{ field.errors[0] }}" data-error-label="{{ field.name }}">
{{ field.errors[0] }}
</span>
{% endif %}
</legend>
{{ caller() }}
</fieldset>
</div>
{{ select_wrapper(field, hint=None, disable=[], option_hints={}, hide_legend=False, input="radio") }}
{% endmacro %}
{% macro radio(option, disable=[], option_hints={}, data_target=None, as_list_item=False) %}
{% if as_list_item %}
<li class="multiple-choice" {% if data_target %}data-target="{{ data_target }}"{% endif %}>
{% else %}
<div class="multiple-choice" {% if data_target %}data-target="{{ data_target }}"{% endif %}>
{% endif %}
<input
id="{{ option.id }}" name="{{ option.name }}" type="radio" value="{{ option.data }}"
{% if option.data in disable %}
disabled
{% endif %}
{% if option.checked %}
checked
{% endif %}
>
<label class="block-label" for="{{ option.id }}">
{{ option.label.text }}
{% if option_hints[option.data] %}
<div class="block-label-hint">
{{ option_hints[option.data] }}
</div>
{% endif %}
</label>
{% if caller %}
{{ caller() }}
{% endif %}
{% if as_list_item %}
</li>
{% else %}
</div>
{% endif %}
{{ select_input(option, disable=[], option_hints={}, data_target=None, as_list_item=False, input="radio") }}
{% endmacro %}

View File

@@ -0,0 +1,92 @@
{% macro select(field, hint=None, disable=[], option_hints={}, hide_legend=False, input="radio") %}
{% call select_wrapper(
field, hint, disable, option_hints, hide_legend
) %}
{% for option in field %}
{{ select_input(option, disable, option_hints, input=input) }}
{% endfor %}
{% endcall %}
{% endmacro %}
{% macro select_list(options, child_map, disable=[], option_hints={}, input="radio") %}
<ul>
{% for option in options %}
{% if child_map[option.data] %}
{% call select_input(option, disable, option_hints, as_list_item=True, input=input) %}
{{ select_list(child_map[option.data], child_map, disable, option_hints, input=input) }}
{% endcall %}
{% else %}
{{ select_input(option, disable, option_hints, as_list_item=True, input=input) }}
{% endif %}
{% endfor %}
</ul>
{% endmacro %}
{% macro select_nested(field, child_map, hint=None, disable=[], option_hints={}, hide_legend=False, input="radio") %}
{% call select_wrapper(
field, hint, disable, option_hints, hide_legend
) %}
<div class="{{ "radios" if input == "radio" else "checkboxes" }}-nested">
{{ select_list(child_map[None], child_map, disable, option_hints, input=input) }}
</div>
{% endcall %}
{% endmacro %}
{% macro select_wrapper(field, hint=None, disable=[], option_hints={}, hide_legend=False) %}
<div class="form-group {% if field.errors %} form-group-error{% endif %}">
<fieldset>
<legend class="{{ 'form-label' if not hide_legend else '' }}">
{% if hide_legend %}<span class="visually-hidden">{% endif %}
{{ field.label.text|safe }}
{% if hide_legend %}</span>{% endif %}
{% if hint %}
<span class="form-hint">
{{ hint }}
</span>
{% endif %}
{% if field.errors %}
<span class="error-message" data-module="track-error" data-error-type="{{ field.errors[0] }}" data-error-label="{{ field.name }}">
{{ field.errors[0] }}
</span>
{% endif %}
</legend>
{{ caller() }}
</fieldset>
</div>
{% endmacro %}
{% macro select_input(option, disable=[], option_hints={}, data_target=None, as_list_item=False, input="radio") %}
{% if as_list_item %}
<li class="multiple-choice" {% if data_target %}data-target="{{ data_target }}"{% endif %}>
{% else %}
<div class="multiple-choice" {% if data_target %}data-target="{{ data_target }}"{% endif %}>
{% endif %}
<input
id="{{ option.id }}" name="{{ option.name }}" type="{{ input }}" value="{{ option.data }}"
{% if option.data in disable %}
disabled
{% endif %}
{% if option.checked %}
checked
{% endif %}
>
<label class="block-label" for="{{ option.id }}">
{{ option.label.text }}
{% if option_hints[option.data] %}
<div class="block-label-hint">
{{ option_hints[option.data] }}
</div>
{% endif %}
</label>
{% if caller %}
{{ caller() }}
{% endif %}
{% if as_list_item %}
</li>
{% else %}
</div>
{% endif %}
{% endmacro %}