diff --git a/app/main/forms.py b/app/main/forms.py index 79a935ae5..18ab60fa7 100644 --- a/app/main/forms.py +++ b/app/main/forms.py @@ -742,6 +742,26 @@ class RadioFieldWithNoneOption(FieldWithNoneOption, RadioField): pass +class NestedRadioField(RadioFieldWithNoneOption): + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + def children(self): + child_map = {} + child_ids = [ + folder['id'] for folder in self.all_template_folders + if folder['parent_id'] is None] + + child_map[None] = [option for idx, option in enumerate(self) if option.data in child_ids or idx == 0] + + for option in self: + child_ids = [ + folder['id'] for folder in self.all_template_folders + if folder['parent_id'] == option.data] + child_map[option.data] = [option for option in self if option.data in child_ids] + return child_map + + class HiddenFieldWithNoneOption(FieldWithNoneOption, HiddenField): pass @@ -1207,7 +1227,6 @@ class TemplateAndFoldersSelectionForm(Form): self, all_template_folders, template_list, - current_folder_id, allow_adding_letter_template, allow_adding_copy_of_template, *args, @@ -1221,13 +1240,10 @@ class TemplateAndFoldersSelectionForm(Form): self.op = None self.is_move_op = self.is_add_folder_op = self.is_add_template_op = False - if current_folder_id is None: - current_folder_id = RadioFieldWithNoneOption.NONE_OPTION_VALUE - + self.move_to.all_template_folders = all_template_folders self.move_to.choices = [ (item['id'], item['name']) for item in ([self.ALL_TEMPLATES_FOLDER] + all_template_folders) - if item['id'] != current_folder_id ] self.add_template_by_template_type.choices = list(filter(None, [ @@ -1262,10 +1278,12 @@ class TemplateAndFoldersSelectionForm(Form): templates_and_folders = MultiCheckboxField('Choose templates or folders', validators=[ required_for_ops('move-to-new-folder', 'move-to-existing-folder') ]) - move_to = RadioFieldWithNoneOption('Choose a folder', validators=[ - Optional(), - required_for_ops('move-to-new-folder', 'move-to-existing-folder') - ]) + move_to = NestedRadioField( + 'Choose a folder', + validators=[ + Optional(), + required_for_ops('move-to-new-folder', 'move-to-existing-folder') + ]) add_new_folder_name = StringField('Folder name', validators=[required_for_ops('add-new-folder')]) move_to_new_folder_name = StringField('Folder name', validators=[required_for_ops('move-to-new-folder')]) diff --git a/app/main/views/templates.py b/app/main/views/templates.py index 191cac718..c0617dab0 100644 --- a/app/main/views/templates.py +++ b/app/main/views/templates.py @@ -116,13 +116,13 @@ def choose_template(service_id, template_type='all', template_folder_id=None): all_template_folders=current_service.all_template_folders, template_list=template_list, template_type=template_type, - current_folder_id=template_folder_id, allow_adding_letter_template=current_service.has_permission('letter'), allow_adding_copy_of_template=( current_service.all_templates or len(user_api_client.get_service_ids_for_user(current_user)) > 1 ), ) + if request.method == 'POST' and templates_and_folders_form.validate_on_submit(): if not can_manage_folders(): abort(403) @@ -149,6 +149,7 @@ def choose_template(service_id, template_type='all', template_folder_id=None): template_type=template_type, search_form=SearchTemplatesForm(), templates_and_folders_form=templates_and_folders_form, + move_to_children=templates_and_folders_form.move_to.children() ) diff --git a/app/templates/components/radios.html b/app/templates/components/radios.html index 8b3ee19dc..84ac4bc2d 100644 --- a/app/templates/components/radios.html +++ b/app/templates/components/radios.html @@ -14,6 +14,43 @@ {% endcall %} {% endmacro %} + +{% macro radio_list( + options, + child_map, + disable=[], + option_hints={} +) %} + +{% endmacro %} + + +{% macro radios_nested( + field, + child_map, + hint=None, + disable=[], + option_hints={}, + hide_legend=False +) %} + {% set disable = [current_option_id] %} + {% call radios_wrapper( + field, hint, disable, option_hints, hide_legend + ) %} + {{ radio_list(child_map[None], child_map, disable) }} + {% endcall %} +{% endmacro %} + {% macro radios_wrapper(field, hint=None, disable=[], option_hints={}, hide_legend=False) %}
@@ -37,8 +74,12 @@
{% endmacro %} -{% macro radio(option, disable=[], option_hints={}, data_target=None) %} +{% macro radio(option, disable=[], option_hints={}, data_target=None, as_list_item=False) %} + {% if as_list_item %} +
  • + {% else %}
    + {% endif %} {% endif %} + {% if caller %} + {{ caller() }} + {% endif %} + {% if as_list_item %} +
  • + {% else %} + {% endif %} {% endmacro %} diff --git a/app/templates/views/templates/_move_to.html b/app/templates/views/templates/_move_to.html index 27e8f1124..02c014c09 100644 --- a/app/templates/views/templates/_move_to.html +++ b/app/templates/views/templates/_move_to.html @@ -1,4 +1,4 @@ -{% from "components/radios.html" import radios %} +{% from "components/radios.html" import radios, radios_nested %} {% from "components/page-footer.html" import page_footer %}
    @@ -6,7 +6,7 @@ {% if templates_and_folders_form.move_to.choices and template_list.templates_to_show %}
    - {{ radios(templates_and_folders_form.move_to) }} + {{ radios_nested(templates_and_folders_form.move_to, move_to_children, current_option) }} {{ page_footer('Move', button_name='operation', button_value='move-to-existing-folder') }}
    diff --git a/tests/app/main/views/test_template_folders.py b/tests/app/main/views/test_template_folders.py index 993987771..513b0dd66 100644 --- a/tests/app/main/views/test_template_folders.py +++ b/tests/app/main/views/test_template_folders.py @@ -13,6 +13,7 @@ from tests.conftest import ( normalize_spaces, ) +ROOT_FOLDER_ID = '__NONE__' PARENT_FOLDER_ID = '7e979e79-d970-43a5-ac69-b625a8d147b0' CHILD_FOLDER_ID = '92ee1ee0-e4ee-4dcc-b1a7-a5da9ebcfa2b' GRANDCHILD_FOLDER_ID = 'fafe723f-1d39-4a10-865f-e551e03d8886' @@ -791,10 +792,10 @@ def test_should_show_radios_and_buttons_for_move_destination_if_correct_permissi assert radios == page.select('input[name=move_to]') assert [x['value'] for x in radios] == [ - PARENT_FOLDER_ID, CHILD_FOLDER_ID, FOLDER_ONE_TWO_ID, FOLDER_TWO_ID, + ROOT_FOLDER_ID, PARENT_FOLDER_ID, CHILD_FOLDER_ID, FOLDER_ONE_TWO_ID, FOLDER_TWO_ID, ] assert [x.text.strip() for x in radio_div.select('label')] == [ - 'folder_one', 'folder_one_one', 'folder_one_two', 'folder_two', + 'All templates', 'folder_one', 'folder_one_one', 'folder_one_two', 'folder_two', ] assert set(x['value'] for x in page.find_all('button', {'name': 'operation'})) == { 'unknown', @@ -902,7 +903,7 @@ def test_should_be_able_to_move_a_sub_item( template_folder_id=PARENT_FOLDER_ID, _data={ 'operation': 'move-to-existing-folder', - 'move_to': '__NONE__', + 'move_to': ROOT_FOLDER_ID, 'templates_and_folders': [GRANDCHILD_FOLDER_ID], }, _expected_status=302, @@ -957,7 +958,7 @@ def test_should_be_able_to_move_a_sub_item( 'operation': 'add-new-template', 'templates_and_folders': [], 'move_to_new_folder_name': '', - 'move_to': '__NONE__', + 'move_to': 'ROOT_FOLDER_ID', 'add_template_by_template_type': 'email', }, # add a new template, but don't select anything @@ -1005,6 +1006,7 @@ def test_no_action_if_user_fills_in_ambiguous_fields( ] assert [ + ROOT_FOLDER_ID, FOLDER_TWO_ID, PARENT_FOLDER_ID, ] == [