add ability for form builder to split choices by newline

- fixes #3001
- keep support for comma separated lists if supplied
pull/8192/head^2
Abdul 2022-03-20 19:57:59 +01:00 zatwierdzone przez LB (Ben Johnston)
rodzic 54e9d09421
commit 134bd19bef
6 zmienionych plików z 253 dodań i 15 usunięć

Wyświetl plik

@ -46,6 +46,7 @@ Changelog
* Fully remove the legacy sidebar, with slim sidebar replacing it for all users (Thibaud Colas)
* Add support for adding custom attributes for link menu items in the slim sidebar (Thibaud Colas)
* Implement new slim page editor header with breadcrumb (Steven Steinwand, Karl Hobley)
* Add the ability for choices to be separated by new lines instead of just commas within the form builder, commas will still be supported if used (Abdulmajeed Isa)
* Fix: When using `simple_translations` ensure that the user is redirected to the page edit view when submitting for a single locale (Mitchel Cabuloy)
* Fix: When previewing unsaved changes to `Form` pages, ensure that all added fields are correctly shown in the preview (Joshua Munn)
* Fix: When Documents (e.g. PDFs) have been configured to be served inline via `WAGTAILDOCS_CONTENT_TYPES` & `WAGTAILDOCS_INLINE_CONTENT_TYPES` ensure that the filename is correctly set in the `Content-Disposition` header so that saving the files will use the correct filename (John-Scott Atlakson)

Wyświetl plik

@ -75,6 +75,7 @@ class LandingPage(Page):
* Validate to and from email addresses within form builder pages when using `AbstractEmailForm` (Jake Howard)
* Add [`WAGTAILIMAGES_RENDITION_STORAGE`](wagtailimages_rendition_storage) setting to allow an alternative image rendition storage (Heather White)
* Add [`wagtail_update_image_renditions` management command](wagtail_update_image_renditions) to regenerate image renditions or purge all existing renditions (Hitansh Shah, Onno Timmerman, Damian Moore)
* Add the ability for choices to be separated by new lines instead of just commas within the form builder, commas will still be supported if used (Abdulmajeed Isa)
### Bug fixes
@ -214,3 +215,4 @@ After setting the keyword argument, make sure to generate and run the migrations
### Removed support for Jinja2 2.x
Jinja2 2.x is no longer supported as of this release; if you are using Jinja2 templating on your project, please upgrade to Jinja2 3.0 or above.

Wyświetl plik

@ -47,26 +47,20 @@ class FormBuilder:
return django.forms.DecimalField(**options)
def create_dropdown_field(self, field, options):
options["choices"] = map(
lambda x: (x.strip(), x.strip()), field.choices.split(",")
)
options["choices"] = self.get_formatted_field_choices(field)
return django.forms.ChoiceField(**options)
def create_multiselect_field(self, field, options):
options["choices"] = map(
lambda x: (x.strip(), x.strip()), field.choices.split(",")
)
options["choices"] = self.get_formatted_field_choices(field)
return django.forms.MultipleChoiceField(**options)
def create_radio_field(self, field, options):
options["choices"] = map(
lambda x: (x.strip(), x.strip()), field.choices.split(",")
)
options["choices"] = self.get_formatted_field_choices(field)
return django.forms.ChoiceField(widget=django.forms.RadioSelect, **options)
def create_checkboxes_field(self, field, options):
options["choices"] = [(x.strip(), x.strip()) for x in field.choices.split(",")]
options["initial"] = [x.strip() for x in field.default_value.split(",")]
options["choices"] = self.get_formatted_field_choices(field)
options["initial"] = self.get_formatted_field_initial(field)
return django.forms.MultipleChoiceField(
widget=django.forms.CheckboxSelectMultiple, **options
)
@ -101,6 +95,42 @@ class FormBuilder:
"Must be one of: " + ", ".join(method_list),
)
def get_formatted_field_choices(self, field):
"""
Returns a list of choices [(string, string),] for the field.
Split the provided choices into a list, separated by new lines.
If no new lines in the provided choices, split by commas.
"""
if "\n" in field.choices:
choices = map(
lambda x: (
x.strip().rstrip(",").strip(),
x.strip().rstrip(",").strip(),
),
field.choices.split("\r\n"),
)
else:
choices = map(lambda x: (x.strip(), x.strip()), field.choices.split(","))
return choices
def get_formatted_field_initial(self, field):
"""
Returns a list of initial values [string,] for the field.
Split the supplied default values into a list, separated by new lines.
If no new lines in the provided default values, split by commas.
"""
if "\n" in field.default_value:
values = [
x.strip().rstrip(",").strip() for x in field.default_value.split("\r\n")
]
else:
values = [x.strip() for x in field.default_value.split(",")]
return values
@property
def formfields(self):
formfields = OrderedDict()

Wyświetl plik

@ -102,14 +102,15 @@ class AbstractFormField(Orderable):
verbose_name=_("choices"),
blank=True,
help_text=_(
"Comma separated list of choices. Only applicable in checkboxes, radio and dropdown."
"Comma or new line separated list of choices. Only applicable in checkboxes, radio and dropdown."
),
)
default_value = models.CharField(
default_value = models.TextField(
verbose_name=_("default value"),
max_length=255,
blank=True,
help_text=_("Default value. Comma separated values supported for checkboxes."),
help_text=_(
"Default value. Comma or new line separated values supported for checkboxes."
),
)
help_text = models.CharField(
verbose_name=_("help text"), max_length=255, blank=True

Wyświetl plik

@ -222,6 +222,89 @@ class TestFormBuilder(TestCase):
self.assertIn(get_field_clean_name(unsaved_field_1.label), fb.formfields)
self.assertIn(get_field_clean_name(unsaved_field_2.label), fb.formfields)
def test_newline_value_separation_in_choices_and_default_value_fields(self):
"""Ensure that the new line present between input choices or values gets formatted into choices or value list
respectively as an alternative to commas.
"""
multiselect_field = FormField.objects.create(
page=self.form_page,
sort_order=2,
label="Your favorite colors",
field_type="multiselect",
required=True,
choices="red\r\nblue\r\ngreen",
)
self.form_page.form_fields.add(multiselect_field)
dropdown_field = FormField.objects.create(
page=self.form_page,
sort_order=2,
label="Pick your next destination",
field_type="dropdown",
required=True,
choices="hawaii\r\nparis\r\nabuja",
)
self.form_page.form_fields.add(dropdown_field)
checkboxes_field = FormField.objects.create(
page=self.form_page,
sort_order=3,
label="Do you possess these attributes",
field_type="checkboxes",
required=False,
choices="good, kind and gentle.\r\nstrong, bold and brave.",
)
self.form_page.form_fields.add(checkboxes_field)
radio_field = FormField.objects.create(
page=self.form_page,
sort_order=2,
label="Your favorite animal",
help_text="Choose one",
field_type="radio",
required=True,
choices="cat\r\ndog\r\nbird",
)
self.form_page.form_fields.add(radio_field)
checkboxes_field_with_default_value = FormField.objects.create(
page=self.form_page,
sort_order=3,
label="Choose the correct answer",
field_type="checkboxes",
required=False,
choices="a\r\nb\r\nc",
default_value="a\r\nc",
)
self.form_page.form_fields.add(checkboxes_field_with_default_value)
fb = FormBuilder(self.form_page.get_form_fields())
form_class = fb.get_form_class()
self.assertEqual(
[("red", "red"), ("blue", "blue"), ("green", "green")],
form_class.base_fields["your_favorite_colors"].choices,
)
self.assertEqual(
[("cat", "cat"), ("dog", "dog"), ("bird", "bird")],
form_class.base_fields["your_favorite_animal"].choices,
)
self.assertEqual(
[
("good, kind and gentle.", "good, kind and gentle."),
("strong, bold and brave.", "strong, bold and brave."),
],
form_class.base_fields["do_you_possess_these_attributes"].choices,
)
self.assertEqual(
[("hawaii", "hawaii"), ("paris", "paris"), ("abuja", "abuja")],
form_class.base_fields["pick_your_next_destination"].choices,
)
self.assertEqual(
["a", "c"],
form_class.base_fields["choose_the_correct_answer"].initial,
)
class TestCustomFormBuilder(TestCase):
def setUp(self):

Wyświetl plik

@ -0,0 +1,121 @@
# Generated by Django 4.0.3 on 2022-03-22 13:36
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("tests", "0064_alter_formpage_from_address_and_more"),
]
operations = [
migrations.AlterField(
model_name="extendedformfield",
name="choices",
field=models.TextField(
blank=True,
help_text="Comma or new line separated list of choices. Only applicable in checkboxes, radio and dropdown.",
verbose_name="choices",
),
),
migrations.AlterField(
model_name="extendedformfield",
name="default_value",
field=models.TextField(
blank=True,
help_text="Default value. Comma or new line separated values supported for checkboxes.",
verbose_name="default value",
),
),
migrations.AlterField(
model_name="formfield",
name="choices",
field=models.TextField(
blank=True,
help_text="Comma or new line separated list of choices. Only applicable in checkboxes, radio and dropdown.",
verbose_name="choices",
),
),
migrations.AlterField(
model_name="formfield",
name="default_value",
field=models.TextField(
blank=True,
help_text="Default value. Comma or new line separated values supported for checkboxes.",
verbose_name="default value",
),
),
migrations.AlterField(
model_name="formfieldforcustomlistviewpage",
name="choices",
field=models.TextField(
blank=True,
help_text="Comma or new line separated list of choices. Only applicable in checkboxes, radio and dropdown.",
verbose_name="choices",
),
),
migrations.AlterField(
model_name="formfieldforcustomlistviewpage",
name="default_value",
field=models.TextField(
blank=True,
help_text="Default value. Comma or new line separated values supported for checkboxes.",
verbose_name="default value",
),
),
migrations.AlterField(
model_name="formfieldwithcustomsubmission",
name="choices",
field=models.TextField(
blank=True,
help_text="Comma or new line separated list of choices. Only applicable in checkboxes, radio and dropdown.",
verbose_name="choices",
),
),
migrations.AlterField(
model_name="formfieldwithcustomsubmission",
name="default_value",
field=models.TextField(
blank=True,
help_text="Default value. Comma or new line separated values supported for checkboxes.",
verbose_name="default value",
),
),
migrations.AlterField(
model_name="jadeformfield",
name="choices",
field=models.TextField(
blank=True,
help_text="Comma or new line separated list of choices. Only applicable in checkboxes, radio and dropdown.",
verbose_name="choices",
),
),
migrations.AlterField(
model_name="jadeformfield",
name="default_value",
field=models.TextField(
blank=True,
help_text="Default value. Comma or new line separated values supported for checkboxes.",
verbose_name="default value",
),
),
migrations.AlterField(
model_name="redirectformfield",
name="choices",
field=models.TextField(
blank=True,
help_text="Comma or new line separated list of choices. Only applicable in checkboxes, radio and dropdown.",
verbose_name="choices",
),
),
migrations.AlterField(
model_name="redirectformfield",
name="default_value",
field=models.TextField(
blank=True,
help_text="Default value. Comma or new line separated values supported for checkboxes.",
verbose_name="default value",
),
),
]