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 b94f86e Move background task polling and committee filtering to
separate files
b94f86e is described below
commit b94f86e399058daee79a5def20157ccb6ac24cf6
Author: Sean B. Palmer <[email protected]>
AuthorDate: Wed Dec 10 14:54:14 2025 +0000
Move background task polling and committee filtering to separate files
---
atr/static/js/committee-directory.js | 139 ++++++++++++++++++++++++++++++++
atr/static/js/ongoing-tasks-poll.js | 99 +++++++++++++++++++++++
atr/templates/check-selected.html | 102 +----------------------
atr/templates/committee-directory.html | 143 +--------------------------------
4 files changed, 240 insertions(+), 243 deletions(-)
diff --git a/atr/static/js/committee-directory.js
b/atr/static/js/committee-directory.js
new file mode 100644
index 0000000..9818a10
--- /dev/null
+++ b/atr/static/js/committee-directory.js
@@ -0,0 +1,139 @@
+let allCommitteeCards = [];
+
+function filterCommitteesByText() {
+ const projectFilter = document.getElementById("project-filter").value;
+ const cards = allCommitteeCards;
+ let visibleCount = 0;
+
+ if (participantButton && participantButton.dataset.showing ===
"participant") {
+ participantButton.dataset.showing = "all";
+ participantButton.textContent = "Show my committees";
+ participantButton.setAttribute("aria-pressed", "false");
+ }
+
+ for (let card of cards) {
+ const nameElement = card.querySelector(".card-title");
+ const name = nameElement.textContent.trim();
+ if (!projectFilter) {
+ card.parentElement.hidden = false;
+ visibleCount++;
+ } else {
+ let regex;
+ try {
+ regex = new RegExp(projectFilter, "i");
+ } catch (e) {
+ const escapedFilter =
projectFilter.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
+ regex = new RegExp(escapedFilter, "i");
+ }
+ card.parentElement.hidden = !name.match(regex);
+ if (!card.parentElement.hidden) {
+ visibleCount++;
+ }
+ }
+ }
+ document.getElementById("committee-count").textContent = visibleCount;
+}
+
+document.getElementById("filter-button").addEventListener("click",
filterCommitteesByText);
+document.getElementById("project-filter").addEventListener("keydown",
function(event) {
+ if (event.key === "Enter") {
+ filterCommitteesByText();
+ event.preventDefault();
+ }
+});
+
+const participantButton = document.getElementById("filter-participant-button");
+if (participantButton) {
+ participantButton.addEventListener("click", function() {
+ const showing = this.dataset.showing;
+ const cards = allCommitteeCards;
+ let visibleCount = 0;
+
+ if (showing === "all") {
+ cards.forEach(card => {
+ const isParticipant = card.dataset.isParticipant === "true";
+ card.parentElement.hidden = !isParticipant;
+ if (!card.parentElement.hidden) {
+ visibleCount++;
+ }
+ });
+ this.textContent = "Show all committees";
+ this.dataset.showing = "participant";
+ this.setAttribute("aria-pressed", "true");
+ } else {
+ cards.forEach(card => {
+ card.parentElement.hidden = false;
+ visibleCount++;
+ });
+ this.textContent = "Show my committees";
+ this.dataset.showing = "all";
+ this.setAttribute("aria-pressed", "false");
+ }
+ document.getElementById("project-filter").value = "";
+ document.getElementById("committee-count").textContent = visibleCount;
+ });
+}
+
+document.addEventListener("DOMContentLoaded", function() {
+ allCommitteeCards =
Array.from(document.querySelectorAll(".page-project-card"));
+ const cards = allCommitteeCards;
+ const committeeCountSpan = document.getElementById("committee-count");
+ let initialVisibleCount = 0;
+ const initialShowingMode = participantButton ?
participantButton.dataset.showing : "all";
+
+ if (participantButton) {
+ if (initialShowingMode === "participant") {
+ participantButton.setAttribute("aria-pressed", "true");
+ } else {
+ participantButton.setAttribute("aria-pressed", "false");
+ }
+ }
+
+ if (initialShowingMode === "participant") {
+ cards.forEach(card => {
+ const isParticipant = card.dataset.isParticipant === "true";
+ card.parentElement.hidden = !isParticipant;
+ if (!card.parentElement.hidden) {
+ initialVisibleCount++;
+ }
+ });
+ } else {
+ cards.forEach(card => {
+ card.parentElement.hidden = false;
+ initialVisibleCount++;
+ });
+ }
+ committeeCountSpan.textContent = initialVisibleCount;
+
+ // Add a click listener to project subcards to handle navigation
+ // TODO: Improve accessibility
+
document.querySelectorAll(".page-project-subcard").forEach(function(subcard) {
+ subcard.addEventListener("click", function(event) {
+ if (this.dataset.projectUrl) {
+ window.location.href = this.dataset.projectUrl;
+ }
+ });
+ });
+
+ // Add a click listener for toggling project visibility within each
committee
+
document.querySelectorAll(".page-toggle-committee-projects").forEach(function(button)
{
+ button.addEventListener("click", function() {
+ const projectListContainer =
this.closest(".page-project-list-container");
+ if (projectListContainer) {
+ const extraProjects =
projectListContainer.querySelectorAll(".page-project-extra");
+ extraProjects.forEach(function(proj) {
+ proj.classList.toggle("d-none");
+ });
+
+ const isExpanded = this.getAttribute("aria-expanded") ===
"true";
+ if (isExpanded) {
+ this.textContent = this.dataset.textShow;
+ this.setAttribute("aria-expanded", "false");
+ } else {
+ this.textContent = this.dataset.textHide;
+ this.setAttribute("aria-expanded", "true");
+ }
+ }
+ });
+ });
+});
diff --git a/atr/static/js/ongoing-tasks-poll.js
b/atr/static/js/ongoing-tasks-poll.js
new file mode 100644
index 0000000..348305f
--- /dev/null
+++ b/atr/static/js/ongoing-tasks-poll.js
@@ -0,0 +1,99 @@
+(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 progress = document.getElementById("poll-progress");
+ const pollInterval = 3000;
+
+ let currentCount = parseInt(countSpan?.textContent || "0", 10);
+ if (currentCount === 0) return;
+
+ function restartProgress() {
+ if (!progress) return;
+ progress.style.animation = "none";
+ progress.offsetHeight;
+ progress.style.animation = `poll-grow ${pollInterval}ms linear
forwards`;
+ }
+
+ 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;
+
+ if (progress) {
+ progress.style.animation = "none";
+ progress.style.width = "100%";
+ progress.classList.remove("bg-warning");
+ progress.classList.add("bg-info", "progress-bar-striped",
"progress-bar-animated");
+ }
+ fetch(apiUrl)
+ .then(response => {
+ if (!response.ok) throw new Error(`HTTP ${response.status}`);
+ return response.json();
+ })
+ .then(data => {
+ if (progress) {
+ progress.classList.remove("bg-info",
"progress-bar-striped", "progress-bar-animated");
+ progress.classList.add("bg-warning");
+ }
+ const newCount = data.ongoing || 0;
+ if (newCount !== currentCount) {
+ updateBanner(newCount);
+ }
+ if (newCount > 0) {
+ restartProgress();
+ setTimeout(pollOngoingTasks, pollInterval);
+ }
+ })
+ .catch(error => {
+ console.error("Error polling ongoing tasks:", error);
+ if (progress) {
+ progress.classList.remove("bg-info",
"progress-bar-striped", "progress-bar-animated");
+ progress.classList.add("bg-warning");
+ }
+ restartProgress();
+ // Double the interval when there's an error
+ setTimeout(pollOngoingTasks, pollInterval * 2);
+ });
+ }
+
+ restartProgress();
+ setTimeout(pollOngoingTasks, pollInterval);
+})();
diff --git a/atr/templates/check-selected.html
b/atr/templates/check-selected.html
index 9f86cdd..aefc386 100644
--- a/atr/templates/check-selected.html
+++ b/atr/templates/check-selected.html
@@ -195,105 +195,5 @@
{% block javascripts %}
{{ super() }}
- <script>
- (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 progress = document.getElementById("poll-progress");
- const pollInterval = 3000;
-
- let currentCount = parseInt(countSpan?.textContent || "0", 10);
- if (currentCount === 0) return;
-
- function restartProgress() {
- if (!progress) return;
- progress.style.animation = "none";
- progress.offsetHeight;
- progress.style.animation = `poll-grow ${pollInterval}ms linear
forwards`;
- }
-
- 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;
-
- if (progress) {
- progress.style.animation = "none";
- progress.style.width = "100%";
- progress.classList.remove("bg-warning");
- progress.classList.add("bg-info", "progress-bar-striped",
"progress-bar-animated");
- }
- fetch(apiUrl)
- .then(response => {
- if (!response.ok) throw new Error(`HTTP ${response.status}`);
- return response.json();
- })
- .then(data => {
- if (progress) {
- progress.classList.remove("bg-info", "progress-bar-striped",
"progress-bar-animated");
- progress.classList.add("bg-warning");
- }
- const newCount = data.ongoing || 0;
- if (newCount !== currentCount) {
- updateBanner(newCount);
- }
- if (newCount > 0) {
- restartProgress();
- setTimeout(pollOngoingTasks, pollInterval);
- }
- })
- .catch(error => {
- console.error("Error polling ongoing tasks:", error);
- if (progress) {
- progress.classList.remove("bg-info", "progress-bar-striped",
"progress-bar-animated");
- progress.classList.add("bg-warning");
- }
- restartProgress();
- // Double the interval when there's an error
- setTimeout(pollOngoingTasks, pollInterval * 2);
- });
- }
-
- restartProgress();
- setTimeout(pollOngoingTasks, pollInterval);
- })();
- </script>
+ <script src="{{ static_url('js/ongoing-tasks-poll.js') }}"></script>
{% endblock javascripts %}
diff --git a/atr/templates/committee-directory.html
b/atr/templates/committee-directory.html
index 23c9e58..6d92852 100644
--- a/atr/templates/committee-directory.html
+++ b/atr/templates/committee-directory.html
@@ -178,146 +178,5 @@
{% block javascripts %}
{{ super() }}
- <script>
- let allCommitteeCards = [];
-
- function filterCommitteesByText() {
- const projectFilter =
document.getElementById("project-filter").value;
- const cards = allCommitteeCards;
- let visibleCount = 0;
-
- if (participantButton && participantButton.dataset.showing ===
"participant") {
- participantButton.dataset.showing = "all";
- participantButton.textContent = "Show my committees";
- participantButton.setAttribute("aria-pressed", "false");
- }
-
- for (let card of cards) {
- const nameElement = card.querySelector(".card-title");
- const name = nameElement.textContent.trim();
- if (!projectFilter) {
- card.parentElement.hidden = false;
- visibleCount++;
- } else {
- let regex;
- try {
- regex = new RegExp(projectFilter, "i");
- } catch (e) {
- const escapedFilter =
projectFilter.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
- regex = new RegExp(escapedFilter, "i");
- }
- card.parentElement.hidden = !name.match(regex);
- if (!card.parentElement.hidden) {
- visibleCount++;
- }
- }
- }
- document.getElementById("committee-count").textContent =
visibleCount;
- }
-
- // Add event listeners
- document.getElementById("filter-button").addEventListener("click",
filterCommitteesByText);
- document.getElementById("project-filter").addEventListener("keydown",
function(event) {
- if (event.key === "Enter") {
- filterCommitteesByText();
- event.preventDefault();
- }
- });
-
- const participantButton =
document.getElementById("filter-participant-button");
- if (participantButton) {
- participantButton.addEventListener("click", function() {
- const showing = this.dataset.showing;
- const cards = allCommitteeCards;
- let visibleCount = 0;
-
- if (showing === "all") {
- cards.forEach(card => {
- const isParticipant = card.dataset.isParticipant ===
"true";
- card.parentElement.hidden = !isParticipant;
- if (!card.parentElement.hidden) {
- visibleCount++;
- }
- });
- this.textContent = "Show all committees";
- this.dataset.showing = "participant";
- this.setAttribute("aria-pressed", "true");
- } else {
- cards.forEach(card => {
- card.parentElement.hidden = false;
- visibleCount++;
- });
- this.textContent = "Show my committees";
- this.dataset.showing = "all";
- this.setAttribute("aria-pressed", "false");
- }
- document.getElementById("project-filter").value = "";
- document.getElementById("committee-count").textContent =
visibleCount;
- });
- }
-
- document.addEventListener("DOMContentLoaded", function() {
- allCommitteeCards =
Array.from(document.querySelectorAll(".page-project-card"));
- const cards = allCommitteeCards;
- const committeeCountSpan =
document.getElementById("committee-count");
- let initialVisibleCount = 0;
- const initialShowingMode = participantButton ?
participantButton.dataset.showing : "all";
-
- if (participantButton) {
- if (initialShowingMode === "participant") {
- participantButton.setAttribute("aria-pressed", "true");
- } else {
- participantButton.setAttribute("aria-pressed", "false");
- }
- }
-
- if (initialShowingMode === "participant") {
- cards.forEach(card => {
- const isParticipant = card.dataset.isParticipant ===
"true";
- card.parentElement.hidden = !isParticipant;
- if (!card.parentElement.hidden) {
- initialVisibleCount++;
- }
- });
- } else {
- cards.forEach(card => {
- card.parentElement.hidden = false;
- initialVisibleCount++;
- });
- }
- committeeCountSpan.textContent = initialVisibleCount;
-
- // Add a click listener to project subcards to handle navigation
- // TODO: Improve accessibility
-
document.querySelectorAll(".page-project-subcard").forEach(function(subcard) {
- subcard.addEventListener("click", function(event) {
- if (this.dataset.projectUrl) {
- window.location.href = this.dataset.projectUrl;
- }
- });
- });
-
- // Add a click listener for toggling project visibility within each
committee
-
document.querySelectorAll(".page-toggle-committee-projects").forEach(function(button)
{
- button.addEventListener("click", function() {
- const projectListContainer =
this.closest(".page-project-list-container");
- if (projectListContainer) {
- const extraProjects =
projectListContainer.querySelectorAll(".page-project-extra");
- extraProjects.forEach(function(proj) {
- proj.classList.toggle("d-none");
- });
-
- const isExpanded = this.getAttribute("aria-expanded")
=== "true";
- if (isExpanded) {
- this.textContent = this.dataset.textShow;
- this.setAttribute("aria-expanded", "false");
- } else {
- this.textContent = this.dataset.textHide;
- this.setAttribute("aria-expanded", "true");
- }
- }
- });
- });
- });
- </script>
+ <script src="{{ static_url('js/committee-directory.js') }}"></script>
{% endblock javascripts %}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]