From 416b601314a788520246019001fa64f74e3c9c64 Mon Sep 17 00:00:00 2001 From: Godefroid Chapelle Date: Mon, 17 Jun 2024 12:28:02 +0200 Subject: [PATCH 1/3] required Likert, require answer for each question --- src/collective/easyform/fields.py | 9 ++++++++- .../easyform/locales/collective.easyform.pot | 6 +++++- .../locales/fr/LC_MESSAGES/collective.easyform.po | 6 +++++- .../locales/nl/LC_MESSAGES/collective.easyform.po | 6 +++++- src/collective/easyform/tests/testLikert.py | 11 +++++++++++ 5 files changed, 34 insertions(+), 4 deletions(-) diff --git a/src/collective/easyform/fields.py b/src/collective/easyform/fields.py index 19011df0..83e3054f 100644 --- a/src/collective/easyform/fields.py +++ b/src/collective/easyform/fields.py @@ -27,6 +27,7 @@ from zope.schema import TextLine from zope.schema._bootstrapinterfaces import IFromUnicode from zope.schema.interfaces import IField +from zope.schema.interfaces import ValidationError def superAdapter(specific_interface, adapter, objects, name=u""): @@ -247,6 +248,10 @@ class NorobotCaptcha(TextLine): NorobotCaptchaHandler = BaseHandler(NorobotCaptcha) +class AllAnswersRequired(ValidationError): + __doc__ = _("Answers are required for each question.") + + @implementer(ILikert) class Likert(TextLine): """A Likert field""" @@ -262,7 +267,9 @@ def __init__(self, **kwargs): def _validate(self, value): super(Likert, self)._validate(value) - self.parse(value) + result = self.parse(value) + if self.required and len(result) != len(self.questions): + raise AllAnswersRequired() def parse(self, value): result = dict() diff --git a/src/collective/easyform/locales/collective.easyform.pot b/src/collective/easyform/locales/collective.easyform.pot index 3913a9ff..e611f4bc 100644 --- a/src/collective/easyform/locales/collective.easyform.pot +++ b/src/collective/easyform/locales/collective.easyform.pot @@ -51,7 +51,11 @@ msgstr "" msgid "Allowed Fields" msgstr "" -#: ./collective/easyform/interfaces/fields.py:105 +#: collective/easyform/fields.py +msgid "Answers are required for each question." +msgstr "" + +#: collective/easyform/interfaces/fields.py:105 msgid "CSS Class" msgstr "" diff --git a/src/collective/easyform/locales/fr/LC_MESSAGES/collective.easyform.po b/src/collective/easyform/locales/fr/LC_MESSAGES/collective.easyform.po index e0f95e12..7845325a 100644 --- a/src/collective/easyform/locales/fr/LC_MESSAGES/collective.easyform.po +++ b/src/collective/easyform/locales/fr/LC_MESSAGES/collective.easyform.po @@ -48,7 +48,11 @@ msgstr "Avancé" msgid "Allowed Fields" msgstr "Champs autorisés" -#: ./collective/easyform/interfaces/fields.py:105 +#: collective/easyform/fields.py +msgid "Answers are required for each question." +msgstr "Chaque question nécessite une réponse." + +#: collective/easyform/interfaces/fields.py:105 msgid "CSS Class" msgstr "" diff --git a/src/collective/easyform/locales/nl/LC_MESSAGES/collective.easyform.po b/src/collective/easyform/locales/nl/LC_MESSAGES/collective.easyform.po index 27923b36..1322d11a 100644 --- a/src/collective/easyform/locales/nl/LC_MESSAGES/collective.easyform.po +++ b/src/collective/easyform/locales/nl/LC_MESSAGES/collective.easyform.po @@ -52,7 +52,11 @@ msgstr "Geavanceerd" msgid "Allowed Fields" msgstr "Toegestane velden" -#: ./collective/easyform/interfaces/fields.py:105 +#: collective/easyform/fields.py +msgid "Answers are required for each question." +msgstr "Elke vraag dient beantwoord te worden." + +#: collective/easyform/interfaces/fields.py:105 msgid "CSS Class" msgstr "" diff --git a/src/collective/easyform/tests/testLikert.py b/src/collective/easyform/tests/testLikert.py index 50d83f24..bd84ab2d 100644 --- a/src/collective/easyform/tests/testLikert.py +++ b/src/collective/easyform/tests/testLikert.py @@ -2,6 +2,7 @@ import six from collective.easyform.tests.base import EasyFormFunctionalTestCase +from zope.schema.interfaces import RequiredMissing class LikertFieldTests(unittest.TestCase): @@ -42,6 +43,16 @@ def test_validate_with_more_answers(self): self.assertRaises(ValueError, field.validate, u'-1:agree') self.assertRaises(ValueError, field.validate, u'Agree') + def test_validate_required(self): + from collective.easyform.fields import AllAnswersRequired + + field = self._makeOne(required=True, questions=[u'Question 1', u'Question 2'], answers=[u'Agree', u'Disagree']) + + field.validate(u'1: Disagree, 2: Agree') + self.assertRaises(RequiredMissing, field.validate, None) + self.assertRaises(AllAnswersRequired, field.validate, u'1:Agree') + self.assertRaises(AllAnswersRequired, field.validate, u'') + def test_parse(self): field = self._makeOne(required=False, questions=[u'Question 1', u'Question 2'], answers=[u'Agree', u'Disagree']) field.validate(None) From a319acb42d9f42424c66626447e2fe4c5b06a506 Mon Sep 17 00:00:00 2001 From: Thibaut Born Date: Mon, 17 Jun 2024 13:52:53 +0200 Subject: [PATCH 2/3] improve layout of likert fields --- src/collective/easyform/browser/likert_input.pt | 9 +++++---- src/collective/easyform/tests/testLikert.py | 4 ++-- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/collective/easyform/browser/likert_input.pt b/src/collective/easyform/browser/likert_input.pt index f8dcf674..37e0869b 100644 --- a/src/collective/easyform/browser/likert_input.pt +++ b/src/collective/easyform/browser/likert_input.pt @@ -1,18 +1,19 @@ - +
- - " in rendered) - self.assertTrue(u"" in rendered) + self.assertTrue(u"Agree" in rendered) + self.assertTrue(u"Disagree" in rendered) def test_likert_saved(self): import transaction From 184ca77db1b9fbfe4fc561b17174718e8503ebaf Mon Sep 17 00:00:00 2001 From: Godefroid Chapelle Date: Mon, 13 Jan 2025 14:06:52 +0100 Subject: [PATCH 3/3] update changelog --- CHANGES.rst | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGES.rst b/CHANGES.rst index b3cbfb86..7d252c90 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -5,7 +5,11 @@ Changelog 4.3.1 (unreleased) ------------------ -- Nothing changed yet. +- When Likert field is required, answer is required for each question. + [gotcha] + +- Improve Likert widget layout + [ThibautBorn] 4.3.0 (2024-12-13)
  +
+ Question Number One + onclick="jQuery(event.target).children('input').click()" + class="col-1 text-center"> Q1" in rendered) self.assertTrue(u"Q2" in rendered) - self.assertTrue(u"AgreeDisagree