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 9e82d45  Update the forms to derive a subproject and to start a new 
release
9e82d45 is described below

commit 9e82d45567b3b5390c27ffb683ee53ec5da652f6
Author: Sean B. Palmer <[email protected]>
AuthorDate: Tue May 13 19:27:06 2025 +0100

    Update the forms to derive a subproject and to start a new release
---
 atr/routes/projects.py                 |   1 +
 atr/routes/start.py                    |   2 +
 atr/templates/project-add-project.html | 226 ++++++++++++++++-----------------
 atr/templates/start-selected.html      |  15 ++-
 4 files changed, 124 insertions(+), 120 deletions(-)

diff --git a/atr/routes/projects.py b/atr/routes/projects.py
index e81558a..0102051 100644
--- a/atr/routes/projects.py
+++ b/atr/routes/projects.py
@@ -119,6 +119,7 @@ async def add_project(session: routes.CommitterSession, 
project_name: str) -> re
                 wtforms.validators.InputRequired("Please provide a derived 
project name."),
                 wtforms.validators.Length(min=1, max=100),
             ],
+            description="The desired suffix for the full project name.",
         )
         submit = wtforms.SubmitField("Add project")
 
diff --git a/atr/routes/start.py b/atr/routes/start.py
index 020e5ff..3d99ea6 100644
--- a/atr/routes/start.py
+++ b/atr/routes/start.py
@@ -38,6 +38,8 @@ class StartReleaseForm(util.QuartFormTyped):
             wtforms.validators.InputRequired("Version is required"),
             wtforms.validators.Length(min=1, max=100),
         ],
+        render_kw={"placeholder": "Examples: 1.2.3+rc1 or 2.5"},
+        description="Enter the version string for this new release.",
     )
     submit = wtforms.SubmitField("Start new release")
 
diff --git a/atr/templates/project-add-project.html 
b/atr/templates/project-add-project.html
index d1cde2a..e53ec2d 100644
--- a/atr/templates/project-add-project.html
+++ b/atr/templates/project-add-project.html
@@ -14,125 +14,125 @@
   </h1>
   <p>New projects can only be derived from existing projects, by adding a 
suffix.</p>
 
-  <form method="post" class="atr-canary py-4">
+  {{ forms.errors_summary(form) }}
+
+  <form method="post" class="atr-canary py-4" novalidate>
     {{ form.hidden_tag() }}
 
     <div class="mb-3 pb-3 row border-bottom">
-      <label for="{{ form.derived_project_name.id }}"
-             class="col-sm-3 col-form-label text-sm-end">{{ 
form.derived_project_name.label.text }}:</label>
+      {{ forms.label(form.derived_project_name, col="sm3") }}
       <div class="col-sm-8">
-        {{ form.derived_project_name(class_="form-control") }}
-        {% if form.derived_project_name.errors -%}
-          <span class="text-danger small">{{ 
form.derived_project_name.errors[0] }}</span>{%- endif %}
-          <p class="text-muted mt-1">The desired suffix for the full project 
name.</p>
-          <p id="capitalisation-warning" class="text-danger small mt-1 d-none">
-            <i class="bi bi-exclamation-triangle"></i>
-            Warning: Ensure all words in the derived name start with a capital 
for proper display.
-          </p>
-        </div>
-      </div>
-
-      <div class="mb-3 pb-3 row border-bottom">
-        <label id="new-project-name-label"
-               for="new-project-name-display"
-               class="col-sm-3 col-form-label text-sm-end">Project name 
preview:</label>
-        <div class="col-sm-8">
-          <code id="new-project-name-display"
-                class="form-control-plaintext bg-light p-2 rounded 
d-block"></code>
-          <p class="text-muted small mt-1">This will be the full display name 
for the derived project.</p>
-        </div>
+        {{ forms.widget(form.derived_project_name, 
id=form.derived_project_name.id) }}
+        {{ forms.errors(form.derived_project_name, classes="text-danger 
small") }}
+        {{ forms.description(form.derived_project_name, classes="text-muted 
mt-1") }}
+        <p id="capitalisation-warning" class="text-danger small mt-1 d-none">
+          <i class="bi bi-exclamation-triangle"></i>
+          Warning: Ensure all words in the derived name start with a capital 
for proper display.
+        </p>
       </div>
+    </div>
 
-      <div class="mb-3 pb-3 row border-bottom">
-        <label id="new-project-label-label"
-               for="new-project-label-display"
-               class="col-sm-3 col-form-label text-sm-end">Project label 
preview:</label>
-        <div class="col-sm-8">
-          <code id="new-project-label-display"
-                class="form-control-plaintext bg-light p-2 rounded 
d-block"></code>
-          <p class="text-muted small mt-1">This will be the short label used 
in URLs and identifiers.</p>
-        </div>
+    <div class="mb-3 pb-3 row border-bottom">
+      <label id="new-project-name-label"
+             for="new-project-name-display"
+             class="col-sm-3 col-form-label text-sm-end">Project name 
preview</label>
+      <div class="col-sm-8">
+        <code id="new-project-name-display"
+              class="form-control-plaintext bg-light p-2 rounded 
d-block"></code>
+        <p class="text-muted small mt-1">This will be the full display name 
for the derived project.</p>
       </div>
+    </div>
 
-      <div class="row">
-        <div class="col-sm-9 offset-sm-3">{{ form.submit(class_="btn 
btn-primary mt-3") }}</div>
+    <div class="mb-3 pb-3 row border-bottom">
+      <label id="new-project-label-label"
+             for="new-project-label-display"
+             class="col-sm-3 col-form-label text-sm-end">Project label 
preview</label>
+      <div class="col-sm-8">
+        <code id="new-project-label-display"
+              class="form-control-plaintext bg-light p-2 rounded 
d-block"></code>
+        <p class="text-muted small mt-1">This will be the short label used in 
URLs and identifiers.</p>
       </div>
-    </form>
-  {% endblock content %}
-
-  {% block javascripts %}
-    {{ super() }}
-    <script>
-        document.addEventListener("DOMContentLoaded", () => {
-            const projectLabel = document.getElementById("{{ 
form.project_name.id }}");
-            const projectSelect = "{{ project_name }}";
-            const derivedNameInput = document.getElementById("{{ 
form.derived_project_name.id }}");
-            const newNameDisplay = 
document.getElementById("new-project-name-display");
-            const newLabelDisplay = 
document.getElementById("new-project-label-display");
-            const capitalisationWarning = 
document.getElementById("capitalisation-warning");
-
-            if (!projectSelect || !derivedNameInput || !newNameDisplay || 
!newLabelDisplay || !capitalisationWarning) return;
-
-            function generateSlug(text) {
-                return text.toLowerCase().replace(/\s+/g, 
"-").replace(/[^a-z0-9-]/g, "");
-            }
-
-            function updatePreview() {
-                const selectedOption = projectSelect;
-                const baseLabel = projectLabel.value;
-                const baseFullName = selectedOption;
-                const derivedNameValue = derivedNameInput.value.trim();
-
-                let hasCapitalisationIssue = false;
-                if (derivedNameValue) {
-                    const words = derivedNameValue.split(/\s+/);
-                    for (const word of words) {
-                        if (word.length > 0 && !/^[A-Z]/.test(word)) {
-                            hasCapitalisationIssue = true;
-                            break;
-                        }
-                    }
-                }
-
-                if (hasCapitalisationIssue) {
-                    capitalisationWarning.classList.remove("d-none");
-                } else {
-                    capitalisationWarning.classList.add("d-none");
-                }
-
-                let newFullName = baseFullName;
-                if (derivedNameValue) {
-                    const match = baseFullName.match(/^(.*?)\s*(\(.*\))?$/);
-                    let mainPart = baseFullName.trim();
-                    let suffixPart = null;
-
-                    if (match) {
-                        mainPart = match[1] ? match[1].trim() : mainPart;
-                        suffixPart = match[2];
-                    }
-
-                    if (suffixPart) {
-                        newFullName = `${mainPart} ${derivedNameValue} 
${suffixPart}`;
-                    } else {
-                        newFullName = `${mainPart} ${derivedNameValue}`;
-                    }
-                    newFullName = newFullName.replace(/\s{2,}/g, " ").trim();
-                }
-                newNameDisplay.textContent = newFullName || "(Select base 
project)";
-
-                let newLabel = baseLabel;
-                if (derivedNameValue) {
-                    const derivedSlug = generateSlug(derivedNameValue);
-                    if (derivedSlug) {
-                        newLabel = `${baseLabel}-${derivedSlug}`;
-                    }
-                }
-                newLabelDisplay.textContent = newLabel || "(Enter derived 
project name)";
-            }
-
-            derivedNameInput.addEventListener("input", updatePreview);
-
-            updatePreview();
-        });
-    </script>
-  {% endblock javascripts %}
+    </div>
+
+    <div class="row">
+      <div class="col-sm-9 offset-sm-3">{{ form.submit(class_="btn btn-primary 
mt-3") }}</div>
+    </div>
+  </form>
+{% endblock content %}
+
+{% block javascripts %}
+  {{ super() }}
+  <script>
+      document.addEventListener("DOMContentLoaded", () => {
+          const projectLabel = document.getElementById("{{ 
form.project_name.id }}");
+          const projectSelect = "{{ project_name }}";
+          const derivedNameInput = document.getElementById("{{ 
form.derived_project_name.id }}");
+          const newNameDisplay = 
document.getElementById("new-project-name-display");
+          const newLabelDisplay = 
document.getElementById("new-project-label-display");
+          const capitalisationWarning = 
document.getElementById("capitalisation-warning");
+
+          if (!projectSelect || !derivedNameInput || !newNameDisplay || 
!newLabelDisplay || !capitalisationWarning) return;
+
+          function generateSlug(text) {
+              return text.toLowerCase().replace(/\s+/g, 
"-").replace(/[^a-z0-9-]/g, "");
+          }
+
+          function updatePreview() {
+              const selectedOption = projectSelect;
+              const baseLabel = projectLabel.value;
+              const baseFullName = selectedOption;
+              const derivedNameValue = derivedNameInput.value.trim();
+
+              let hasCapitalisationIssue = false;
+              if (derivedNameValue) {
+                  const words = derivedNameValue.split(/\s+/);
+                  for (const word of words) {
+                      if (word.length > 0 && !/^[A-Z]/.test(word)) {
+                          hasCapitalisationIssue = true;
+                          break;
+                      }
+                  }
+              }
+
+              if (hasCapitalisationIssue) {
+                  capitalisationWarning.classList.remove("d-none");
+              } else {
+                  capitalisationWarning.classList.add("d-none");
+              }
+
+              let newFullName = baseFullName;
+              if (derivedNameValue) {
+                  const match = baseFullName.match(/^(.*?)\s*(\(.*\))?$/);
+                  let mainPart = baseFullName.trim();
+                  let suffixPart = null;
+
+                  if (match) {
+                      mainPart = match[1] ? match[1].trim() : mainPart;
+                      suffixPart = match[2];
+                  }
+
+                  if (suffixPart) {
+                      newFullName = `${mainPart} ${derivedNameValue} 
${suffixPart}`;
+                  } else {
+                      newFullName = `${mainPart} ${derivedNameValue}`;
+                  }
+                  newFullName = newFullName.replace(/\s{2,}/g, " ").trim();
+              }
+              newNameDisplay.textContent = newFullName || "(Select base 
project)";
+
+              let newLabel = baseLabel;
+              if (derivedNameValue) {
+                  const derivedSlug = generateSlug(derivedNameValue);
+                  if (derivedSlug) {
+                      newLabel = `${baseLabel}-${derivedSlug}`;
+                  }
+              }
+              newLabelDisplay.textContent = newLabel || "(Enter derived 
project name)";
+          }
+
+          derivedNameInput.addEventListener("input", updatePreview);
+
+          updatePreview();
+      });
+  </script>
+{% endblock javascripts %}
diff --git a/atr/templates/start-selected.html 
b/atr/templates/start-selected.html
index cbc512d..fe55db7 100644
--- a/atr/templates/start-selected.html
+++ b/atr/templates/start-selected.html
@@ -10,10 +10,13 @@
     Starting a new release creates a <strong>release candidate draft</strong>. 
You can then add files to this draft before promoting it for voting.
   </p>
 
+  {{ forms.errors_summary(form) }}
+
   <form method="post"
         action="{{ as_url(routes.start.selected, project_name=project.name) }}"
         enctype="multipart/form-data"
-        class="atr-canary py-4 px-5 border rounded">
+        class="atr-canary py-4 px-5 border rounded"
+        novalidate>
     {{ form.hidden_tag() }}
 
     <div class="mb-4">
@@ -24,12 +27,10 @@
     </div>
 
     <div class="mb-3">
-      <label for="{{ form.version_name.id }}" class="form-label">{{ 
form.version_name.label.text }}:</label>
-      {{ form.version_name(class_="form-control form-control-lg", 
placeholder="Examples: 1.2.3+rc1 or 2.5") }}
-      {% if form.version_name.errors -%}
-        <div class="invalid-feedback d-block">{{ form.version_name.errors[0] 
}}</div>
-      {%- endif %}
-      <div id="versionHelp" class="form-text">Enter the version string for 
this new release.</div>
+      {{ forms.label(form.version_name) }}
+      {{ forms.widget(form.version_name, classes="form-control 
form-control-lg", id=form.version_name.id) }}
+      {{ forms.errors(form.version_name) }}
+      {{ forms.description(form.version_name) }}
     </div>
 
     <div class="mt-4">


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

Reply via email to