This is an automated email from the ASF dual-hosted git repository.

sbp pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tooling-trusted-release.git


The following commit(s) were added to refs/heads/main by this push:
     new d94f16f  Improve the form rendering macros
d94f16f is described below

commit d94f16f62777028119fde20694b90c038609fd77
Author: Sean B. Palmer <[email protected]>
AuthorDate: Tue May 13 16:30:01 2025 +0100

    Improve the form rendering macros
---
 atr/routes/projects.py                 | 31 ++++++++++++++----
 atr/templates/macros/forms.html        | 54 +++++++++++++++++--------------
 atr/templates/release-policy-form.html | 58 +++++++++++++++++-----------------
 3 files changed, 85 insertions(+), 58 deletions(-)

diff --git a/atr/routes/projects.py b/atr/routes/projects.py
index f6165a0..e81558a 100644
--- a/atr/routes/projects.py
+++ b/atr/routes/projects.py
@@ -57,28 +57,47 @@ class ReleasePolicyForm(util.QuartFormTyped):
                 wtforms.validators.Email(),
             ],
             render_kw={"size": 30},
+            description="Note: This field determines where vote and finished 
release announcement emails are sent."
+            " You can set this value to your own mailing list, but ATR will 
currently only let you send to"
+            " [email protected].",
         ),
         min_entries=1,
     )
     min_hours = wtforms.IntegerField(
-        "Minimum voting period:",
+        "Minimum voting period",
         validators=[
             wtforms.validators.InputRequired("Please provide a minimum voting 
period"),
             util.validate_vote_duration,
         ],
         default=72,
+        description="The minimum time to run the vote, in hours. Must be 0 or 
between 72 and 144 inclusive."
+        " If 0, then wait until 3 +1 votes and more +1 than -1.",
+    )
+    manual_vote = wtforms.BooleanField(
+        "Voting process",
+        description="If this is set then the vote will be completely manual 
and following policy is ignored.",
     )
-    manual_vote = wtforms.BooleanField("Voting process:")
     release_checklist = wtforms.StringField(
-        "Release checklist:", widget=wtforms.widgets.TextArea(), 
render_kw={"rows": 10}
+        "Release checklist",
+        widget=wtforms.widgets.TextArea(),
+        render_kw={"rows": 10},
+        description="Markdown text describing how to test release candidates.",
     )
     start_vote_template = wtforms.StringField(
-        "Start vote template:", widget=wtforms.widgets.TextArea(), 
render_kw={"rows": 10}
+        "Start vote template",
+        widget=wtforms.widgets.TextArea(),
+        render_kw={"rows": 10},
+        description="Email template for messages to start a vote on a 
release.",
     )
     announce_release_template = wtforms.StringField(
-        "Announce release template:", widget=wtforms.widgets.TextArea(), 
render_kw={"rows": 10}
+        "Announce release template",
+        widget=wtforms.widgets.TextArea(),
+        render_kw={"rows": 10},
+        description="Email template for messages to announce a finished 
release.",
+    )
+    pause_for_rm = wtforms.BooleanField(
+        "Pause for RM", description="If enabled, RM can confirm manually if 
the vote has passed."
     )
-    pause_for_rm = wtforms.BooleanField("Pause for RM:")
 
     submit = wtforms.SubmitField("Save")
 
diff --git a/atr/templates/macros/forms.html b/atr/templates/macros/forms.html
index aaaeb67..e6d7583 100644
--- a/atr/templates/macros/forms.html
+++ b/atr/templates/macros/forms.html
@@ -1,29 +1,37 @@
-{% macro render_field(field, label=False, class_='form-control') %}
-  {% if label and field.label %}{{ field.label(class="form-label") }}{% endif 
%}
-  {% set field_class = class_ + (' is-invalid' if field.errors else '') %}
-  {{ field(class_=field_class) }}
-  {% if field.errors %}
-    <div class="invalid-feedback">
-      {% for error in field.errors %}
-        {{ error }}
-        {% if not loop.last %}<br />{% endif %}
-      {% endfor %}
-    </div>
+{% macro label(field, classes="form-label", col=False) %}
+  {% if field.label %}
+    {% set final_classes = classes %}
+    {% if col %}
+      {% set col_classes = "col-sm-3 col-form-label text-sm-end" %}
+      {% if final_classes and final_classes != "" %}
+        {% set final_classes = col_classes + " " + final_classes %}
+      {% else %}
+        {% set final_classes = col_classes %}
+      {% endif %}
+    {% endif %}
+    {{ field.label(class=final_classes) }}
   {% endif %}
-  {% if field.description %}<div class="form-text text-muted">{{ 
field.description }}</div>{% endif %}
 {% endmacro %}
 
-{% macro render_checkbox(field, label=False, class_='form-check-input') %}
-  {% set field_class = class_ + (' is-invalid' if field.errors else '') %}
-  {{ field(class_=field_class) }}
-  {% if label and field.label %}{{ field.label(class="form-check-label") }}{% 
endif %}
+{% macro widget(field, classes="form-control") %}
+  {% set widget_class = classes %}
   {% if field.errors %}
-    <div class="invalid-feedback d-block">
-      {% for error in field.errors %}
-        {{ error }}
-        {% if not loop.last %}<br />{% endif %}
-      {% endfor %}
-    </div>
+    {% set widget_class = widget_class + ' is-invalid' %}
   {% endif %}
-  {% if field.description %}<div class="form-text text-muted">{{ 
field.description }}</div>{% endif %}
+  {{ field(class_=widget_class) }}
+{% endmacro %}
+
+{% macro errors(field, classes="invalid-feedback", item_separator="<br />") %}
+{% if field.errors %}
+  <div class="{{ classes }}">
+    {% for error in field.errors %}
+      {{ error }}
+      {% if not loop.last %}{{ item_separator|safe }}{% endif %}
+    {% endfor %}
+  </div>
+{% endif %}
+{% endmacro %}
+
+{% macro description(field, classes="form-text text-muted") %}
+  {% if field.description %}<div id="{{ field.id }}-help" class="{{ classes 
}}">{{ field.description }}</div>{% endif %}
 {% endmacro %}
diff --git a/atr/templates/release-policy-form.html 
b/atr/templates/release-policy-form.html
index 7d38b9f..7662bb8 100644
--- a/atr/templates/release-policy-form.html
+++ b/atr/templates/release-policy-form.html
@@ -6,18 +6,18 @@
 
   <input type="hidden" name="form_type" value="single" />
   <div class="mb-3 pb-3 row border-bottom">
-    <label for="project_name_text" class="col-sm-3 col-form-label 
text-sm-end">Project:</label>
+    <label for="project_name_text" class="col-sm-3 col-form-label 
text-sm-end">Project</label>
     <div class="col-sm-8">
       <p id="project_name_text" class="form-control-plaintext">{{ 
project.display_name }}</p>
     </div>
   </div>
 
   <div class="mb-3 pb-3 row border-bottom">
-    <label for="{{ form.mailto_addresses.entries[0].id }}"
-           class="col-sm-3 col-form-label text-sm-end">{{ 
form.mailto_addresses.entries[0].label.text }}:</label>
+    {{ forms.label(form.mailto_addresses.entries[0], col=True) }}
     <div class="col-sm-8">
-      {{ forms.render_field(form.mailto_addresses.entries[0]) }}
-      <span class="form-text text-muted">Note: This field determines where 
vote and finished release announcement emails are sent. You can set this value 
to your own mailing list, but ATR will currently only let you send to 
<code>[email protected]</code>.</span>
+      {{ forms.widget(form.mailto_addresses.entries[0]) }}
+      {{ forms.errors(form.mailto_addresses.entries[0]) }}
+      {{ forms.description(form.mailto_addresses.entries[0]) }}
     </div>
     <!--
     <div class="col-sm-1">
@@ -27,62 +27,62 @@
   </div>
 
   <div class="mb-3 pb-3 row border-bottom">
-    <label for="{{ form.manual_vote.id }}"
-           class="col-sm-3 col-form-label text-sm-end">{{ 
form.manual_vote.label.text }}</label>
+    {{ forms.label(form.manual_vote, col=True) }}
     <div class="col-sm-8">
       <div class="form-check">
-        {{ forms.render_checkbox(form.manual_vote) }}
+        {{ forms.widget(form.manual_vote, classes="form-check-input") }}
+        {{ forms.errors(form.manual_vote, classes="invalid-feedback d-block") 
}}
         <label class="form-check-label" for="{{ form.manual_vote.id 
}}">Manual</label>
       </div>
-      <span id="manual_vote-help" class="form-text text-muted">If this is set 
then the vote will be completely manual and following policy is ignored.</span>
+      {{ forms.description(form.manual_vote) }}
     </div>
   </div>
 
   <div class="mb-3 pb-3 row border-bottom">
-    <label for="{{ form.min_hours.id }}"
-           class="col-sm-3 col-form-label text-sm-end">{{ 
form.min_hours.label.text }}</label>
+    {{ forms.label(form.min_hours, col=True) }}
     <div class="col-sm-8">
-      {{ forms.render_field(form.min_hours) }}
-      <span id="min_hours-help" class="form-text text-muted">The minimum time 
to run the vote, in hours. Must be 0 or between 72 and 144 inclusive. If 0, 
then wait until 3 +1 votes and more +1 than -1.</span>
+      {{ forms.widget(form.min_hours) }}
+      {{ forms.errors(form.min_hours) }}
+      {{ forms.description(form.min_hours) }}
     </div>
   </div>
 
   <div class="mb-3 pb-3 row border-bottom">
-    <label for="{{ form.release_checklist.id }}"
-           class="col-sm-3 col-form-label text-sm-end">{{ 
form.release_checklist.label.text }}</label>
+    {{ forms.label(form.release_checklist, col=True) }}
     <div class="col-sm-8">
-      {{ forms.render_field(form.release_checklist) }}
-      <span id="release_checklist-help" class="form-text text-muted">Markdown 
text describing how to test release candidates.</span>
+      {{ forms.widget(form.release_checklist) }}
+      {{ forms.errors(form.release_checklist) }}
+      {{ forms.description(form.release_checklist) }}
     </div>
   </div>
 
   <div class="mb-3 pb-3 row border-bottom">
-    <label for="{{ form.start_vote_template.id }}"
-           class="col-sm-3 col-form-label text-sm-end">{{ 
form.start_vote_template.label.text }}</label>
+    {{ forms.label(form.start_vote_template, col=True) }}
     <div class="col-sm-8">
-      {{ forms.render_field(form.start_vote_template) }}
-      <span id="start_vote_template-help" class="form-text text-muted">Email 
template for messages to start a vote on a release.</span>
+      {{ forms.widget(form.start_vote_template) }}
+      {{ forms.errors(form.start_vote_template) }}
+      {{ forms.description(form.start_vote_template) }}
     </div>
   </div>
 
   <div class="mb-3 pb-3 row border-bottom">
-    <label for="{{ form.announce_release_template.id }}"
-           class="col-sm-3 col-form-label text-sm-end">{{ 
form.announce_release_template.label.text }}</label>
+    {{ forms.label(form.announce_release_template, col=True) }}
     <div class="col-sm-8">
-      {{ forms.render_field(form.announce_release_template) }}
-      <span id="announce_release_template-help" class="form-text 
text-muted">Email template for messages to announce a finished release.</span>
+      {{ forms.widget(form.announce_release_template) }}
+      {{ forms.errors(form.announce_release_template) }}
+      {{ forms.description(form.announce_release_template) }}
     </div>
   </div>
 
   <div class="mb-3 pb-3 row border-bottom">
-    <label for="{{ form.pause_for_rm.id }}"
-           class="col-sm-3 col-form-label text-sm-end">{{ 
form.pause_for_rm.label.text }}</label>
+    {{ forms.label(form.pause_for_rm, col=True) }}
     <div class="col-sm-8">
       <div class="form-check">
-        {{ forms.render_checkbox(form.pause_for_rm) }}
+        {{ forms.widget(form.pause_for_rm, classes="form-check-input") }}
+        {{ forms.errors(form.pause_for_rm, classes="invalid-feedback d-block") 
}}
         <label class="form-check-label" for="{{ form.pause_for_rm.id 
}}">Enabled</label>
       </div>
-      <span id="pause_for_rm-help" class="form-text text-muted">If enabled, RM 
can confirm manually if the vote has passed.</span>
+      {{ forms.description(form.pause_for_rm) }}
     </div>
   </div>
 


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to