Browse Source

Ensure all panels output their own help_text (#9240)

Co-authored-by: Thibaud Colas <thibaudcolas@gmail.com>
Matt Westcott 2 years ago
parent
commit
528801f1a0

+ 3 - 1
CHANGELOG.txt

@@ -28,6 +28,7 @@ Changelog
  * Add a toggle to collapse/expand all page panels at once (Helen Chapman)
  * Improve the GitHub Workflows (CI) security (Alex (sashashura))
  * Use `search` type input in documentation search (LB (Ben) Johnston)
+ * Render `help_text` when set on `FieldPanel`, `MultiFieldPanel`, `FieldRowPanel`, and other panel APIs where it previously worked without official support (Matt Westcott)
  * Fix: Prevent `PageQuerySet.not_public` from returning all pages when no page restrictions exist (Mehrdad Moradizadeh)
  * Fix: Ensure that duplicate block ids are unique when duplicating stream blocks in the page editor (Joshua Munn)
  * Fix: Revise colour usage so that privacy & locked indicators can be seen in Windows High Contrast mode (LB (Ben Johnston))
@@ -37,6 +38,7 @@ Changelog
  * Fix: Ensure that `ModelAdmin` correctly supports filters in combination with subsequent searches without clearing the applied filters (Stefan Hammer)
  * Fix: Add missing translated values to site settings' headers plus models presented in listings and audit report filtering labels (Stefan Hammer)
  * Fix: Remove `capitalize()` calls to avoid issues with other languages or incorrectly presented model names for reporting and parts of site settings (Stefan Hammer)
+ * Fix: Add back rendering of `help_text` for InlinePanel (Matt Westcott)
 
 
 4.0.2 (23.09.2022)
@@ -63,7 +65,7 @@ Changelog
  * Fix: Only add Translate buttons when the `simple_translation` app is installed (Dan Braghis)
  * Fix: Ensure that `MultiFieldPanel` correctly outputs all child classnames in the template (Matt Westcott)
  * Fix: Remove over-eager caching on ModelAdmin permission checks (Matt Westcott, Stefan Hammer)
- 
+
 
 4.0.1 (05.09.2022)
 ~~~~~~~~~~~~~~~~~~

+ 12 - 0
docs/reference/pages/panels.md

@@ -41,6 +41,10 @@ Here are some Wagtail-specific types that you might include as fields in your mo
 
         This allows you to override the heading for the panel, which will otherwise be set automatically using the form field's label (taken in turn from a model field's ``verbose_name``).
 
+    .. attribute:: FieldPanel.help_text (optional)
+
+        Help text to be displayed against the field. This takes precedence over any help text set on the model field.
+
     .. attribute:: FieldPanel.disable_comments (optional)
 
         This allows you to prevent a field level comment button showing for this panel if set to ``True`` (see :ref:`commenting`).
@@ -76,6 +80,10 @@ Here are some Wagtail-specific types that you might include as fields in your mo
     .. attribute:: MultiFieldPanel.heading
 
         A heading for the fields
+
+    .. attribute:: MultiFieldPanel.help_text
+
+        Help text to be displayed against the panel.
 ```
 
 ### InlinePanel
@@ -108,6 +116,10 @@ Note that you can use `classname="collapsed"` to load the panel collapsed under
     .. attribute:: FieldRowPanel.classname
 
         A class to apply to the FieldRowPanel as a whole
+
+    .. attribute:: FieldRowPanel.help_text
+
+        Help text to be displayed against the panel.
 ```
 
 ### HelpPanel

+ 2 - 0
docs/releases/4.1.md

@@ -43,6 +43,7 @@ The `register_snippet` function now accepts a `SnippetViewSet` class, allowing v
  * Add a toggle to collapse/expand all page panels at once (Helen Chapman)
  * Improve the GitHub Workflows (CI) security (Alex (sashashura))
  * Use `search` type input in documentation search (LB (Ben) Johnston)
+ * Render `help_text` when set on `FieldPanel`, `MultiFieldPanel`, `FieldRowPanel`, and other panel APIs where it previously worked without official support (Matt Westcott)
 
 ### Bug fixes
 
@@ -55,6 +56,7 @@ The `register_snippet` function now accepts a `SnippetViewSet` class, allowing v
  * Ensure that `ModelAdmin` correctly supports filters in combination with subsequent searches without clearing the applied filters (Stefan Hammer)
  * Add missing translated values to site settings' headers plus models presented in listings and audit report filtering labels (Stefan Hammer)
  * Remove `capitalize()` calls to avoid issues with other languages or incorrectly presented model names for reporting and parts of site settings (Stefan Hammer)
+ * Add back rendering of `help_text` for InlinePanel (Matt Westcott)
 
 ## Upgrade considerations
 

+ 1 - 1
wagtail/admin/panels.py

@@ -717,7 +717,7 @@ class FieldPanel(Panel):
             else:
                 self.heading = self.bound_field.label
 
-            self.help_text = self.bound_field.help_text
+            self.help_text = self.panel.help_text or self.bound_field.help_text
 
         @property
         def field_name(self):

+ 1 - 1
wagtail/admin/templates/wagtailadmin/panels/field_panel.html

@@ -1,2 +1,2 @@
 {% load wagtailadmin_tags i18n %}
-{% include "wagtailadmin/shared/field.html" with show_label=False %}
+{% include "wagtailadmin/shared/field.html" with show_label=False help_text=self.help_text %}

+ 6 - 1
wagtail/admin/templates/wagtailadmin/panels/field_row_panel.html

@@ -1,4 +1,9 @@
 {% load wagtailadmin_tags %}
+{% if self.help_text %}
+    {% help_block status="info" %}{{ self.help_text }}{% endhelp_block %}
+{% endif %}
 {% field_row %}
-    {% include "wagtailadmin/panels/multi_field_panel.html" %}
+    {% for child in self.visible_children %}
+        {% include "wagtailadmin/panels/multi_field_panel_child.html" %}
+    {% endfor %}
 {% endfield_row %}

+ 18 - 7
wagtail/admin/templates/wagtailadmin/panels/inline_panel.html

@@ -2,14 +2,25 @@
 
 {{ self.formset.management_form }}
 
+{% if self.formset.non_form_errors %}
+    <div class="error-message">
+        {% for error in self.formset.non_form_errors %}
+            <span>{{ error|escape }}</span>
+        {% endfor %}
+    </div>
+{% endif %}
+
+{% if self.help_text %}
+    {% help_block status="info" %}{{ self.help_text }}{% endhelp_block %}
+{% endif %}
+
 <div id="id_{{ self.formset.prefix }}-FORMS">
-    {% if self.formset.non_form_errors %}
-        <div class="error-message">
-            {% for error in self.formset.non_form_errors %}
-                <span>{{ error|escape }}</span>
-            {% endfor %}
-        </div>
-    {% endif %}
+    {% comment %}
+
+    Child elements of this div will become orderable elements. Do not place additional
+    "furniture" elements here unless you intend them to be part of the child ordering.
+
+    {% endcomment %}
 
     {% for child in self.children %}
         {% include "wagtailadmin/panels/inline_panel_child.html" %}

+ 4 - 14
wagtail/admin/templates/wagtailadmin/panels/multi_field_panel.html

@@ -1,18 +1,8 @@
 {% load wagtailadmin_tags %}
 {# Avoid semantic markup here. Children of this panel can either be fields, or other groups. #}
+{% if self.help_text %}
+    {% help_block status="info" %}{{ self.help_text }}{% endhelp_block %}
+{% endif %}
 {% for child in self.visible_children %}
-    <div class="w-panel__wrapper {{ child.classes|join:' ' }}">
-        {% if child.heading %}
-            {% fragment as label_content %}
-                {{ child.heading }}{% if child.is_required %}<span class="w-required-mark">*</span>{% endif %}
-            {% endfragment %}
-            {% if child.id_for_label %}
-                <label class="w-field__label" for="{{ child.id_for_label }}" id="{{ child.id_for_label }}-label">{{ label_content }}</label>
-            {% else %}
-                <h3 class="w-field__label">{{ label_content }}</h3>
-            {% endif %}
-        {% endif %}
-
-        {% component child %}
-    </div>
+    {% include "wagtailadmin/panels/multi_field_panel_child.html" %}
 {% endfor %}

+ 15 - 0
wagtail/admin/templates/wagtailadmin/panels/multi_field_panel_child.html

@@ -0,0 +1,15 @@
+{% load wagtailadmin_tags %}
+<div class="w-panel__wrapper {{ child.classes|join:' ' }}">
+    {% if child.heading %}
+        {% fragment as label_content %}
+            {{ child.heading }}{% if child.is_required %}<span class="w-required-mark">*</span>{% endif %}
+        {% endfragment %}
+        {% if child.id_for_label %}
+            <label class="w-field__label" for="{{ child.id_for_label }}" id="{{ child.id_for_label }}-label">{{ label_content }}</label>
+        {% else %}
+            <h3 class="w-field__label">{{ label_content }}</h3>
+        {% endif %}
+    {% endif %}
+
+    {% component child %}
+</div>

+ 3 - 0
wagtail/admin/templates/wagtailadmin/panels/object_list.html

@@ -1,6 +1,9 @@
 {% load wagtailadmin_tags %}
 
 <div class="w-form-width">
+    {% if self.help_text %}
+        {% help_block status="info" %}{{ self.help_text }}{% endhelp_block %}
+    {% endif %}
     {% for child, identifier in self.visible_children_with_identifiers %}
         {% panel id_prefix=self.prefix id=identifier classname=child.classes|join:' ' heading=child.heading heading_size="label" icon=child.icon id_for_label=child.id_for_label is_required=child.is_required %}
             {% component child %}

+ 4 - 0
wagtail/admin/templates/wagtailadmin/panels/tabbed_interface.html

@@ -1,5 +1,9 @@
 {% load wagtailadmin_tags i18n %}
 
+{% if self.help_text %}
+    {% help_block status="info" %}{{ self.help_text }}{% endhelp_block %}
+{% endif %}
+
 <div class="w-tabs" data-tabs>
     <div class="w-tabs__wrapper">
         <div role="tablist" class="w-tabs__list">

+ 8 - 1
wagtail/admin/tests/pages/test_edit_page.py

@@ -119,12 +119,19 @@ class TestPageEdit(TestCase, WagtailTestUtils):
         self.assertEqual(response["Content-Type"], "text/html; charset=utf-8")
         self.assertContains(response, 'id="status-sidebar-live"')
 
-        # Test InlinePanel labels/headings
+        # Test help text defined on FieldPanel
+        self.assertContains(response, "Who this event is for")
+
+        # Test InlinePanel labels/headings/help text
         self.assertContains(
             response,
             '<label class="w-field__label" for="id_speakers-__prefix__-last_name" id="id_speakers-__prefix__-last_name-label">',
         )
         self.assertContains(response, "Add speakers")
+        self.assertContains(response, "Put the keynote speaker first")
+
+        # Test MultiFieldPanel help text
+        self.assertContains(response, "For SEO nerds only")
 
         # test register_page_action_menu_item hook
         self.assertContains(

+ 6 - 2
wagtail/admin/tests/test_edit_handlers.py

@@ -728,7 +728,8 @@ class TestFieldRowPanel(TestCase):
             [
                 FieldPanel("date_from", classname="col4", heading="Start"),
                 FieldPanel("date_to", classname="coltwo"),
-            ]
+            ],
+            help_text="Confirmed event dates only",
         ).bind_to_model(EventPage)
 
     def test_render_html(self):
@@ -756,9 +757,12 @@ class TestFieldRowPanel(TestCase):
             result,
         )
 
-        # check that help text is included
+        # check that field help text is included
         self.assertIn("Not required if event is on a single day", result)
 
+        # check that row help text is included
+        self.assertIn("Confirmed event dates only", result)
+
         # check that the populated form field is included
         self.assertIn('value="2014-07-22"', result)
 

+ 2 - 0
wagtail/snippets/tests/test_snippets.py

@@ -686,6 +686,8 @@ class TestSnippetCreateView(TestCase, WagtailTestUtils):
             response,
             '<a id="tab-label-other" href="#tab-other" class="w-tabs__tab " role="tab" aria-selected="false" tabindex="-1">',
         )
+        self.assertContains(response, "Other panels help text")
+        self.assertContains(response, "Top-level help text")
 
     def test_create_with_limited_permissions(self):
         self.user.is_superuser = False

+ 15 - 5
wagtail/test/testapp/models.py

@@ -382,12 +382,17 @@ class EventPage(Page):
         FieldPanel("time_from"),
         FieldPanel("time_to"),
         FieldPanel("location"),
-        FieldPanel("audience"),
+        FieldPanel("audience", help_text="Who this event is for"),
         FieldPanel("cost"),
         FieldPanel("signup_link"),
         InlinePanel("carousel_items", label="Carousel items"),
         FieldPanel("body"),
-        InlinePanel("speakers", label="Speakers", heading="Speaker lineup"),
+        InlinePanel(
+            "speakers",
+            label="Speakers",
+            heading="Speaker lineup",
+            help_text="Put the keynote speaker first",
+        ),
         InlinePanel("related_links", label="Related links"),
         FieldPanel("categories"),
         # InlinePanel related model uses `pk` not `id`
@@ -395,7 +400,9 @@ class EventPage(Page):
     ]
 
     promote_panels = [
-        MultiFieldPanel(COMMON_PANELS, "Common page configuration"),
+        MultiFieldPanel(
+            COMMON_PANELS, "Common page configuration", help_text="For SEO nerds only"
+        ),
         FieldPanel("feed_image"),
     ]
 
@@ -948,8 +955,11 @@ class AdvertWithTabbedInterface(models.Model):
     edit_handler = TabbedInterface(
         [
             ObjectList(advert_panels, heading="Advert"),
-            ObjectList(other_panels, heading="Other"),
-        ]
+            ObjectList(
+                other_panels, heading="Other", help_text="Other panels help text"
+            ),
+        ],
+        help_text="Top-level help text",
     )
 
     def __str__(self):