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-releases.git


The following commit(s) were added to refs/heads/main by this push:
     new a5e42e6  Update the progress of checks by polling the API
a5e42e6 is described below

commit a5e42e61d033f198221053624897a6b66eda9b75
Author: Sean B. Palmer <[email protected]>
AuthorDate: Fri Nov 28 14:34:06 2025 +0000

    Update the progress of checks by polling the API
---
 atr/templates/check-selected-release-info.html | 17 +++--
 atr/templates/check-selected.html              | 88 ++++++++++++++++++++++++--
 2 files changed, 94 insertions(+), 11 deletions(-)

diff --git a/atr/templates/check-selected-release-info.html 
b/atr/templates/check-selected-release-info.html
index bbb042c..8830992 100644
--- a/atr/templates/check-selected-release-info.html
+++ b/atr/templates/check-selected-release-info.html
@@ -59,29 +59,36 @@
            class="btn btn-secondary"><i class="bi bi-clock-history me-1"></i> 
Revisions</a>
         {% if revision_number %}
           {% if has_files and release.project.policy_manual_vote and 
(ongoing_tasks_count == 0) %}
-            <a href="{{ as_url(get.manual.start_selected_revision, 
project_name=release.project.name, version_name=release.version, 
revision=revision_number) }}"
+            <a id="start-vote-button"
+               href="{{ as_url(get.manual.start_selected_revision, 
project_name=release.project.name, version_name=release.version, 
revision=revision_number) }}"
                title="Start a manual vote on this draft"
                class="btn btn-success"><i class="bi bi-check-circle me-1"></i> 
Start manual vote</a>
           {% elif has_files and release.project.policy_manual_vote %}
-            <a href="#"
+            <a id="start-vote-button"
+               href="{{ as_url(get.manual.start_selected_revision, 
project_name=release.project.name, version_name=release.version, 
revision=revision_number) }}"
+               data-vote-href="{{ as_url(get.manual.start_selected_revision, 
project_name=release.project.name, version_name=release.version, 
revision=revision_number) }}"
                title="Background tasks must complete first"
                class="btn btn-success disabled"
                role="button"
                aria-disabled="true"
                tabindex="-1"><i class="bi bi-check-circle me-1"></i> Start 
manual vote</a>
           {% elif has_files and (not strict_checking_errors) and 
(ongoing_tasks_count == 0) %}
-            <a href="{{ as_url(get.voting.selected_revision, 
project_name=release.project.name, version_name=release.version, 
revision=revision_number) }}"
+            <a id="start-vote-button"
+               href="{{ as_url(get.voting.selected_revision, 
project_name=release.project.name, version_name=release.version, 
revision=revision_number) }}"
                title="Start a vote on this draft"
                class="btn btn-success"><i class="bi bi-check-circle me-1"></i> 
Start voting</a>
           {% elif has_files and (not strict_checking_errors) %}
-            <a href="#"
+            <a id="start-vote-button"
+               href="{{ as_url(get.voting.selected_revision, 
project_name=release.project.name, version_name=release.version, 
revision=revision_number) }}"
+               data-vote-href="{{ as_url(get.voting.selected_revision, 
project_name=release.project.name, version_name=release.version, 
revision=revision_number) }}"
                title="Background tasks must complete first"
                class="btn btn-success disabled"
                role="button"
                aria-disabled="true"
                tabindex="-1"><i class="bi bi-check-circle me-1"></i> Start 
voting</a>
           {% else %}
-            <a href="#"
+            <a id="start-vote-button"
+               href="#"
                title="Upload files to enable voting"
                class="btn btn-success disabled"
                role="button"
diff --git a/atr/templates/check-selected.html 
b/atr/templates/check-selected.html
index 123bd0f..98da71e 100644
--- a/atr/templates/check-selected.html
+++ b/atr/templates/check-selected.html
@@ -78,12 +78,13 @@
 
   {% include "check-selected-release-info.html" %}
 
-  {% if ongoing_tasks_count > 0 %}
-    <div class="alert alert-warning" role="alert">
-      <i class="bi bi-exclamation-triangle me-2"></i>
-      There {{ 'is' if ongoing_tasks_count == 1 else 'are' }} currently 
<strong>{{ ongoing_tasks_count }}</strong> background verification {{ 'task' if 
ongoing_tasks_count == 1 else 'tasks' }} running for the latest revision. 
Results shown below may be incomplete or outdated until the tasks finish. You 
cannot start a vote until the tasks finish. Refresh the page to see updates.
-    </div>
-  {% endif %}
+  <div id="ongoing-tasks-banner"
+       class="alert alert-warning{% if ongoing_tasks_count == 0 %} d-none{% 
endif %}"
+       role="alert"
+       {% if revision_number %}data-api-url="/api/checks/ongoing/{{ 
release.project.name }}/{{ release.version }}/{{ revision_number }}"{% endif %}>
+    <i class="bi bi-exclamation-triangle me-2"></i>
+    <span id="ongoing-tasks-text">There {{ 'is' if ongoing_tasks_count == 1 
else 'are' }} currently <strong id="ongoing-tasks-count">{{ ongoing_tasks_count 
}}</strong> background verification {{ 'task' if ongoing_tasks_count == 1 else 
'tasks' }} running for the latest revision. Results shown below may be 
incomplete or outdated until the tasks finish.</span>
+  </div>
 
   <div class="card mb-4">
     <div class="card-header d-flex justify-content-between align-items-center">
@@ -213,5 +214,80 @@
   {{ super() }}
   <script>
       init();
+
+      (function() {
+          const banner = document.getElementById("ongoing-tasks-banner");
+          if (!banner) return;
+
+          const apiUrl = banner.dataset.apiUrl;
+          if (!apiUrl) return;
+
+          const countSpan = document.getElementById("ongoing-tasks-count");
+          const textSpan = document.getElementById("ongoing-tasks-text");
+          const voteButton = document.getElementById("start-vote-button");
+          const pollInterval = 2500;
+
+          let currentCount = parseInt(countSpan?.textContent || "0", 10);
+          if (currentCount === 0) return;
+
+          function updateBanner(count) {
+              if (!countSpan || !textSpan) return;
+
+              currentCount = count;
+              countSpan.textContent = count;
+
+              const taskWord = count === 1 ? "task" : "tasks";
+              const isAre = count === 1 ? "is" : "are";
+              // TODO: Migrate away from setting innerHTML
+              textSpan.innerHTML = `There ${isAre} currently <strong 
id="ongoing-tasks-count">${count}</strong> background verification ${taskWord} 
running for the latest revision. Results shown below may be incomplete or 
outdated until the tasks finish.`;
+
+              if (count === 0) {
+                  // Banner always exists, but we hide it
+                  banner.classList.add("d-none");
+                  enableVoteButton();
+              }
+          }
+
+          function enableVoteButton() {
+              if (!voteButton) return;
+              if (!voteButton.classList.contains("disabled")) return;
+
+              const voteHref = voteButton.dataset.voteHref || 
voteButton.getAttribute("href");
+              if (!voteHref || voteHref === "#") return;
+
+              voteButton.classList.remove("disabled");
+              voteButton.removeAttribute("aria-disabled");
+              voteButton.removeAttribute("tabindex");
+              voteButton.removeAttribute("role");
+              voteButton.setAttribute("href", voteHref);
+              voteButton.setAttribute("title", "Start a vote on this draft");
+          }
+
+          function pollOngoingTasks() {
+              if (currentCount === 0) return;
+
+              fetch(apiUrl)
+                  .then(response => {
+                      if (!response.ok) throw new Error(`HTTP 
${response.status}`);
+                      return response.json();
+                  })
+                  .then(data => {
+                      const newCount = data.ongoing || 0;
+                      if (newCount !== currentCount) {
+                          updateBanner(newCount);
+                      }
+                      if (newCount > 0) {
+                          setTimeout(pollOngoingTasks, pollInterval);
+                      }
+                  })
+                  .catch(error => {
+                      console.error("Error polling ongoing tasks:", error);
+                      // Double the interval when there's an error
+                      setTimeout(pollOngoingTasks, pollInterval * 2);
+                  });
+          }
+
+          setTimeout(pollOngoingTasks, pollInterval);
+      })();
   </script>
 {% endblock javascripts %}


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

Reply via email to