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 3b177b0  Add a new page for resolving a vote manually
3b177b0 is described below

commit 3b177b0595165fc107830c622e7edc3d806b1df1
Author: Sean B. Palmer <[email protected]>
AuthorDate: Wed Jul 2 15:28:57 2025 +0100

    Add a new page for resolving a vote manually
---
 atr/routes/vote.py                     | 25 +++++++++---
 atr/templates/vote-resolve-manual.html | 74 ++++++++++++++++++++++++++++++++++
 2 files changed, 94 insertions(+), 5 deletions(-)

diff --git a/atr/routes/vote.py b/atr/routes/vote.py
index 3699028..402537b 100644
--- a/atr/routes/vote.py
+++ b/atr/routes/vote.py
@@ -76,6 +76,20 @@ class ResolveVoteForm(util.QuartFormTyped):
     submit = wtforms.SubmitField("Resolve vote")
 
 
+class ResolveVoteManualForm(util.QuartFormTyped):
+    """Form for resolving a vote manually."""
+
+    email_body = wtforms.TextAreaField("Email body", render_kw={"rows": 24})
+    vote_result = wtforms.RadioField(
+        "Vote result",
+        choices=[("passed", "Passed"), ("failed", "Failed")],
+        validators=[wtforms.validators.InputRequired("Vote result is 
required")],
+    )
+    vote_thread_url = wtforms.StringField("Vote thread URL")
+    vote_result_url = wtforms.StringField("Vote result URL")
+    submit = wtforms.SubmitField("Resolve vote")
+
+
 class Vote(enum.Enum):
     YES = "Yes"
     NO = "No"
@@ -200,11 +214,12 @@ async def selected_resolve(session: 
routes.CommitterSession, project_name: str,
         with_project_release_policy=True,
     )
     if release.vote_manual:
-        raise NotImplementedError("Manual vote process is not implemented yet")
-        # return await template.render(
-        #     "vote-resolve-manual.html",
-        #     release=release,
-        # )
+        resolve_form = await ResolveVoteManualForm.create_form()
+        return await template.render(
+            "vote-resolve-manual.html",
+            release=release,
+            resolve_form=resolve_form,
+        )
 
     hidden_form = await util.HiddenFieldForm.create_form()
     tabulated_votes = None
diff --git a/atr/templates/vote-resolve-manual.html 
b/atr/templates/vote-resolve-manual.html
new file mode 100644
index 0000000..ba8afd1
--- /dev/null
+++ b/atr/templates/vote-resolve-manual.html
@@ -0,0 +1,74 @@
+{% extends "layouts/base.html" %}
+
+{% block title %}
+  Resolve vote ~ ATR
+{% endblock title %}
+
+{% block description %}
+  Resolve vote for a release.
+{% endblock description %}
+
+{% block content %}
+  <p>
+    <a href="{{ as_url(routes.vote.selected, 
project_name=release.project.name, version_name=release.version) }}"
+       class="atr-back-link">← Back to Vote for {{ release.short_display_name 
}}</a>
+  </p>
+
+  <h1>Resolve vote for {{ release.short_display_name }}</h1>
+  <p>This is a manual vote resolution.</p>
+
+  {{ forms.errors_summary(resolve_form) }}
+
+  <form method="post"
+        class="atr-canary py-4 px-5 mb-4 border rounded"
+        novalidate>
+    {{ resolve_form.hidden_tag() }}
+
+    <div class="mb-3 pb-3 row border-bottom">
+      {{ forms.label(resolve_form.vote_result, col="md3-high") }}
+      <div class="col-sm-8">
+        <div class="d-flex gap-4 mb-2">
+          {% for subfield in resolve_form.vote_result %}
+            <div class="form-check">
+              {{ subfield(class_='form-check-input') }}
+              {{ subfield.label(class_='form-check-label') }}
+            </div>
+          {% endfor %}
+        </div>
+        {{ forms.errors(resolve_form.vote_result, classes="invalid-feedback 
d-block") }}
+        {{ forms.description(resolve_form.vote_result) }}
+      </div>
+    </div>
+
+    <div class="mb-3 pb-3 row border-bottom">
+      {{ forms.label(resolve_form.vote_thread_url, col="md3") }}
+      <div class="col-sm-8">
+        {{ forms.widget(resolve_form.vote_thread_url, classes="form-control") 
}}
+        {{ forms.errors(resolve_form.vote_thread_url, 
classes="invalid-feedback d-block") }}
+        {{ forms.description(resolve_form.vote_thread_url) }}
+      </div>
+    </div>
+
+    <div class="mb-3 pb-3 row border-bottom">
+      {{ forms.label(resolve_form.vote_result_url, col="md3") }}
+      <div class="col-sm-8">
+        {{ forms.widget(resolve_form.vote_result_url, classes="form-control") 
}}
+        {{ forms.errors(resolve_form.vote_result_url, 
classes="invalid-feedback d-block") }}
+        {{ forms.description(resolve_form.vote_result_url) }}
+      </div>
+    </div>
+
+    <div class="mb-3 pb-3 row border-bottom">
+      {{ forms.label(resolve_form.email_body, col="md3") }}
+      <div class="col-sm-8">
+        {{ forms.widget(resolve_form.email_body, rows="12", 
classes="form-control font-monospace") }}
+        {{ forms.errors(resolve_form.email_body, classes="invalid-feedback 
d-block") }}
+        {{ forms.description(resolve_form.email_body) }}
+      </div>
+    </div>
+
+    <div class="row">
+      <div class="col-sm-9 offset-sm-3">{{ forms.widget(resolve_form.submit, 
classes="btn btn-primary") }}</div>
+    </div>
+  </form>
+{% endblock content %}


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

Reply via email to