This is an automated email from the ASF dual-hosted git repository.
wave 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 fdc7d52 Switch to djhtml from djLint (#410)
fdc7d52 is described below
commit fdc7d52e74fdb6be539701e4e8e149e04bd01509
Author: Dave Fisher <[email protected]>
AuthorDate: Mon Dec 8 14:12:01 2025 -0800
Switch to djhtml from djLint (#410)
---
.pre-commit-config.yaml | 35 +-
atr/admin/templates/all-releases.html | 10 +-
atr/admin/templates/data-browser.html | 94 ++---
atr/admin/templates/delete-release.html | 8 +-
atr/admin/templates/ldap-lookup.html | 8 +-
atr/admin/templates/performance.html | 156 ++++---
atr/admin/templates/tasks.html | 18 +-
atr/admin/templates/toggle-admin-view.html | 6 +-
atr/admin/templates/update-keys.html | 252 ++++++-----
atr/admin/templates/update-projects.html | 254 ++++++------
atr/admin/templates/validation.html | 8 +-
atr/policy/third-party-licenses.html | 2 +-
atr/templates/about.html | 32 +-
atr/templates/blank.html | 4 +-
atr/templates/check-selected.html | 224 +++++-----
atr/templates/committee-directory.html | 552 ++++++++++++-------------
atr/templates/committee-view.html | 2 -
atr/templates/delete-committee-keys.html | 2 -
atr/templates/download-all.html | 2 -
atr/templates/draft-tools.html | 4 +-
atr/templates/error.html | 2 -
atr/templates/includes/topnav.html | 642 ++++++++++++++---------------
atr/templates/index-committer.html | 32 +-
atr/templates/index-public.html | 2 -
atr/templates/layouts/base.html | 42 +-
atr/templates/notfound.html | 2 -
atr/templates/project-select.html | 2 -
atr/templates/projects.html | 226 +++++-----
atr/templates/release-select.html | 2 -
atr/templates/releases-finished.html | 2 -
atr/templates/releases.html | 18 +-
atr/templates/report-selected-path.html | 172 ++++----
atr/templates/resolve-tabulated.html | 2 -
atr/templates/tutorial.html | 12 +-
atr/templates/user-ssh-keys.html | 2 +-
35 files changed, 1382 insertions(+), 1451 deletions(-)
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 5e8516f..cb65e96 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -49,22 +49,27 @@ repos:
rev: v0.11.0.1
hooks:
- id: shellcheck
-- repo: https://github.com/Riverside-Healthcare/djLint
- rev: v1.36.4
+- repo: https://github.com/rtts/djhtml
+ rev: 3.0.10
hooks:
- - id: djlint
- files: "atr/templates/.*\\.html$"
- types_or: ['html']
- args:
- - --profile=jinja
- - --lint
- - id: djlint
- name: Format HTML templates
- files: "atr/templates/.*\\.html$"
- types_or: ['html']
- args:
- - --profile=jinja
- - --reformat
+ - id: djhtml
+ files: .*/.*\.html$
+#- repo: https://github.com/Riverside-Healthcare/djLint
+# rev: v1.36.4
+# hooks:
+# - id: djlint
+# files: "atr/templates/.*\\.html$"
+# types_or: ['html']
+# args:
+# - --profile=jinja
+# - --lint
+# - id: djlint
+# name: Format HTML templates
+# files: "atr/templates/.*\\.html$"
+# types_or: ['html']
+# args:
+# - --profile=jinja
+# - --reformat
- repo: https://github.com/thibaudcolas/pre-commit-stylelint
rev: v16.25.0
hooks:
diff --git a/atr/admin/templates/all-releases.html
b/atr/admin/templates/all-releases.html
index 4b688da..6c93920 100644
--- a/atr/admin/templates/all-releases.html
+++ b/atr/admin/templates/all-releases.html
@@ -1,12 +1,8 @@
{% extends "layouts/base.html" %}
-{% block title %}
- All releases ~ ATR Admin
-{% endblock title %}
+{%- block title -%}All releases ~ ATR Admin{%- endblock title -%}
-{% block description %}
- View all releases across all stages and phases, for debugging.
-{% endblock description %}
+{%- block description -%}View all releases across all stages and phases, for
debugging.{%- endblock description -%}
{% block content %}
<h1>All releases</h1>
@@ -26,7 +22,7 @@
<tr>
<td>
{% if release.project %}
- <a href="{{ release_as_url(release) }}">{{ release.name }}</a>
+ <a href="{{ release_as_url(release) }}">{{ release.name }}</a>
{% else %}
{{ release.name }}
{% endif %}
diff --git a/atr/admin/templates/data-browser.html
b/atr/admin/templates/data-browser.html
index ad09444..37045d2 100644
--- a/atr/admin/templates/data-browser.html
+++ b/atr/admin/templates/data-browser.html
@@ -1,66 +1,62 @@
{% extends "layouts/base-admin.html" %}
-{% block title %}
- Data browser ~ ATR
-{% endblock title %}
+{%- block title -%}Data browser ~ ATR{%- endblock title -%}
-{% block description %}
- Browse all records in the database.
-{% endblock description %}
+{%- block description -%}Browse all records in the database.{%- endblock
description -%}
{% block stylesheets %}
{{ super() }}
<style>
- .page-model-nav {
- margin: 1rem 0;
- padding: 0.5rem;
- background: #f5f5f5;
- border-radius: 4px;
- }
+ .page-model-nav {
+ margin: 1rem 0;
+ padding: 0.5rem;
+ background: #f5f5f5;
+ border-radius: 4px;
+ }
- .page-model-nav a {
- margin-right: 1rem;
- padding: 0.25rem 0.5rem;
- text-decoration: none;
- color: #333;
- }
+ .page-model-nav a {
+ margin-right: 1rem;
+ padding: 0.25rem 0.5rem;
+ text-decoration: none;
+ color: #333;
+ }
- .page-model-nav a.active {
- background: #333;
- color: white;
- border-radius: 2px;
- }
+ .page-model-nav a.active {
+ background: #333;
+ color: white;
+ border-radius: 2px;
+ }
- .page-record {
- border: 1px solid #ddd;
- padding: 1rem;
- margin-bottom: 1rem;
- border-radius: 4px;
- }
+ .page-record {
+ border: 1px solid #ddd;
+ padding: 1rem;
+ margin-bottom: 1rem;
+ border-radius: 4px;
+ }
- .page-record pre {
- background: #f5f5f5;
- padding: 0.5rem;
- border-radius: 2px;
- overflow-x: auto;
- }
+ .page-record pre {
+ background: #f5f5f5;
+ padding: 0.5rem;
+ border-radius: 2px;
+ overflow-x: auto;
+ }
- .page-record-header {
- display: flex;
- justify-content: space-between;
- align-items: center;
- margin-bottom: 0.5rem;
- }
+ .page-record-header {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ margin-bottom: 0.5rem;
+ }
- .page-record-meta {
- color: #666;
- font-size: 0.9em;
- }
+ .page-record-meta {
+ color: #666;
+ font-size: 0.9em;
+ }
- .page-no-records {
- color: #666;
- font-style: italic;
- }
+ .page-no-records {
+ color: #666;
+ font-style: italic;
+ }
</style>
{% endblock stylesheets %}
diff --git a/atr/admin/templates/delete-release.html
b/atr/admin/templates/delete-release.html
index 2e721a8..56cba07 100644
--- a/atr/admin/templates/delete-release.html
+++ b/atr/admin/templates/delete-release.html
@@ -1,12 +1,8 @@
{% extends "layouts/base.html" %}
-{% block title %}
- Delete release ~ ATR Admin
-{% endblock title %}
+{%- block title -%}Delete release ~ ATR Admin{%- endblock title -%}
-{% block description %}
- Permanently delete a release and all associated data.
-{% endblock description %}
+{%- block description -%}Permanently delete a release and all associated
data.{%- endblock description -%}
{% block content %}
<h1>Delete release</h1>
diff --git a/atr/admin/templates/ldap-lookup.html
b/atr/admin/templates/ldap-lookup.html
index 47bbe06..7278e96 100644
--- a/atr/admin/templates/ldap-lookup.html
+++ b/atr/admin/templates/ldap-lookup.html
@@ -1,12 +1,8 @@
{% extends "layouts/base-admin.html" %}
-{% block title %}
- LDAP lookup ~ ATR
-{% endblock title %}
+{%- block title -%}LDAP lookup ~ ATR{%- endblock title -%}
-{% block description %}
- Perform a lookup in the ASF LDAP directory.
-{% endblock description %}
+{%- block description -%}Perform a lookup in the ASF LDAP directory.{%-
endblock description -%}
{% block content %}
<h1>LDAP lookup</h1>
diff --git a/atr/admin/templates/performance.html
b/atr/admin/templates/performance.html
index a1f1d97..b5f49b2 100644
--- a/atr/admin/templates/performance.html
+++ b/atr/admin/templates/performance.html
@@ -1,88 +1,86 @@
{% extends "layouts/base-admin.html" %}
-{% block title %}
- Performance dashboard
-{% endblock title %}
+{%- block title -%}Performance dashboard{%- endblock title -%}
{% block stylesheets %}
{{ super() }}
<style>
- .page-performance-stats {
- display: grid;
- grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
- gap: 1rem;
- margin: 1rem 0;
- }
-
- .page-route-card {
- background: #fff;
- border-radius: 8px;
- padding: 1rem;
- box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
- }
-
- .page-route-card.slow {
- border-left: 4px solid #dc3545;
- }
-
- .page-route-card.medium {
- border-left: 4px solid #ffc107;
- }
-
- .page-route-card.fast {
- border-left: 4px solid #28a745;
- }
-
- .page-route-card h3 {
- margin: 0 0 0.5rem 0;
- font-size: 1.1rem;
- font-family: monospace;
- }
-
- .page-route-meta {
- display: flex;
- gap: 1rem;
- font-size: 0.9rem;
- color: #666;
- margin-bottom: 1rem;
- }
-
- .page-timing-grid {
- display: grid;
- grid-template-columns: repeat(3, 1fr);
- gap: 1rem;
- margin-bottom: 1rem;
- }
-
- .page-timing-section h4 {
- margin: 0 0 0.5rem 0;
- font-size: 0.9rem;
- color: #444;
- }
-
- .page-timing-section dl {
- margin: 0;
- font-size: 0.85rem;
- }
-
- .page-timing-section dt {
- color: #666;
- float: left;
- clear: left;
- margin-right: 0.5rem;
- }
-
- .page-timing-section dd {
- margin: 0;
- font-family: monospace;
- }
-
- .page-last-seen {
- font-size: 0.8rem;
- color: #666;
- border-top: 1px solid #eee;
- padding-top: 0.5rem;
- }
+ .page-performance-stats {
+ display: grid;
+ grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
+ gap: 1rem;
+ margin: 1rem 0;
+ }
+
+ .page-route-card {
+ background: #fff;
+ border-radius: 8px;
+ padding: 1rem;
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
+ }
+
+ .page-route-card.slow {
+ border-left: 4px solid #dc3545;
+ }
+
+ .page-route-card.medium {
+ border-left: 4px solid #ffc107;
+ }
+
+ .page-route-card.fast {
+ border-left: 4px solid #28a745;
+ }
+
+ .page-route-card h3 {
+ margin: 0 0 0.5rem 0;
+ font-size: 1.1rem;
+ font-family: monospace;
+ }
+
+ .page-route-meta {
+ display: flex;
+ gap: 1rem;
+ font-size: 0.9rem;
+ color: #666;
+ margin-bottom: 1rem;
+ }
+
+ .page-timing-grid {
+ display: grid;
+ grid-template-columns: repeat(3, 1fr);
+ gap: 1rem;
+ margin-bottom: 1rem;
+ }
+
+ .page-timing-section h4 {
+ margin: 0 0 0.5rem 0;
+ font-size: 0.9rem;
+ color: #444;
+ }
+
+ .page-timing-section dl {
+ margin: 0;
+ font-size: 0.85rem;
+ }
+
+ .page-timing-section dt {
+ color: #666;
+ float: left;
+ clear: left;
+ margin-right: 0.5rem;
+ }
+
+ .page-timing-section dd {
+ margin: 0;
+ font-family: monospace;
+ }
+
+ .page-last-seen {
+ font-size: 0.8rem;
+ color: #666;
+ border-top: 1px solid #eee;
+ padding-top: 0.5rem;
+ }
</style>
{% endblock stylesheets %}
diff --git a/atr/admin/templates/tasks.html b/atr/admin/templates/tasks.html
index b934a48..3a72def 100644
--- a/atr/admin/templates/tasks.html
+++ b/atr/admin/templates/tasks.html
@@ -1,8 +1,6 @@
{% extends "layouts/base-admin.html" %}
-{% block title %}
- Executed Tasks ~ ATR
-{% endblock %}
+{%- block title -%}Executed Tasks ~ ATR{%- endblock -%}
{% block stylesheets %}
{{ super() }}
@@ -11,7 +9,7 @@
<style>
.gridjs-pages button {
- color: unset;
+ color: unset;
}
</style>
{% endblock stylesheets %}
@@ -30,16 +28,16 @@
new gridjs.Grid({
columns: [
{
- name: 'ID',
- width: '40px'
+ name: 'ID',
+ width: '40px'
},
{
- name: 'Task Type',
- width: '140px'
+ name: 'Task Type',
+ width: '140px'
},
{
- name: 'Task Status',
- width: '60px'
+ name: 'Task Status',
+ width: '60px'
},
{
name: 'Added',
diff --git a/atr/admin/templates/toggle-admin-view.html
b/atr/admin/templates/toggle-admin-view.html
index 2dd7bf9..6d2b594 100644
--- a/atr/admin/templates/toggle-admin-view.html
+++ b/atr/admin/templates/toggle-admin-view.html
@@ -1,10 +1,8 @@
{% extends "layouts/base-admin.html" %}
-{% block title %}Toggle admin view{% endblock title %}
+{%- block title -%}Toggle admin view{%- endblock title -%}
-{% block description %}
- Switch between administrator and regular user views.
-{% endblock description %}
+{%- block description -%}Switch between administrator and regular user
views.{%- endblock description -%}
{% block content %}
<h1>Toggle admin view</h1>
diff --git a/atr/admin/templates/update-keys.html
b/atr/admin/templates/update-keys.html
index 2184c12..6fd31b6 100644
--- a/atr/admin/templates/update-keys.html
+++ b/atr/admin/templates/update-keys.html
@@ -1,152 +1,148 @@
{% extends "layouts/base-admin.html" %}
-{% block title %}
- Update keys ~ ATR
-{% endblock title %}
+{%- block title -%}Update keys ~ ATR{%- endblock title -%}
-{% block description %}
- Update keys from remote data sources.
-{% endblock description %}
+{%- block description -%}Update keys from remote data sources.{%- endblock
description -%}
{% block stylesheets %}
- {{ super() }}
- <style>
- .page-form-group {
- margin-bottom: 1rem;
- }
-
- button {
- margin-top: 1rem;
- padding: 0.5rem 1rem;
- background: #036;
- color: white;
- border: none;
- border-radius: 4px;
- cursor: pointer;
- font-weight: 500;
- }
-
- button:hover {
- background: #047;
- }
-
- button:disabled {
- color: gray;
- }
-
- .page-warning {
- margin: 1.5rem 0;
- padding: 1rem;
- background: #fff3cd;
- border: 1px solid #ffeeba;
- border-radius: 4px;
- color: #856404;
- }
-
- .page-warning p:last-child {
- margin-bottom: 0;
- }
-
- .page-warning strong {
- color: #533f03;
- }
-
- .page-status-message {
- margin: 1.5rem 0;
- padding: 1rem;
- border-radius: 4px;
- }
-
- .page-status-message.success {
- background: #d4edda;
- border: 1px solid #c3e6cb;
- color: #155724;
- }
-
- .page-status-message.error {
- background: #f8d7da;
- border: 1px solid #f5c6cb;
- color: #721c24;
- }
- </style>
+ {{ super() }}
+ <style>
+ .page-form-group {
+ margin-bottom: 1rem;
+ }
+
+ button {
+ margin-top: 1rem;
+ padding: 0.5rem 1rem;
+ background: #036;
+ color: white;
+ border: none;
+ border-radius: 4px;
+ cursor: pointer;
+ font-weight: 500;
+ }
+
+ button:hover {
+ background: #047;
+ }
+
+ button:disabled {
+ color: gray;
+ }
+
+ .page-warning {
+ margin: 1.5rem 0;
+ padding: 1rem;
+ background: #fff3cd;
+ border: 1px solid #ffeeba;
+ border-radius: 4px;
+ color: #856404;
+ }
+
+ .page-warning p:last-child {
+ margin-bottom: 0;
+ }
+
+ .page-warning strong {
+ color: #533f03;
+ }
+
+ .page-status-message {
+ margin: 1.5rem 0;
+ padding: 1rem;
+ border-radius: 4px;
+ }
+
+ .page-status-message.success {
+ background: #d4edda;
+ border: 1px solid #c3e6cb;
+ color: #155724;
+ }
+
+ .page-status-message.error {
+ background: #f8d7da;
+ border: 1px solid #f5c6cb;
+ color: #721c24;
+ }
+ </style>
{% endblock stylesheets %}
{% block content %}
- <h1>Update keys</h1>
- <p>
- This page allows you to update keys in the database from remote data
sources.
- </p>
-
- <div class="page-warning">
+ <h1>Update keys</h1>
<p>
- <strong>Note:</strong> This operation will update all keys from remote
KEYS files.
+ This page allows you to update keys in the database from remote data
sources.
</p>
- </div>
- <div id="status"></div>
+ <div class="page-warning">
+ <p>
+ <strong>Note:</strong> This operation will update all keys from
remote KEYS files.
+ </p>
+ </div>
- {{ empty_form }}
+ <div id="status"></div>
- {% if previous_output %}
- <h2>Previous output</h2>
- <pre>{{ previous_output }}</pre>
- {% endif %}
+ {{ empty_form }}
- <script>
- document.addEventListener('DOMContentLoaded', () => {
- const form = document.querySelector('form');
- const button = form.querySelector('button[type="submit"]');
+ {% if previous_output %}
+ <h2>Previous output</h2>
+ <pre>{{ previous_output }}</pre>
+ {% endif %}
- form.addEventListener('submit', async (e) => {
- e.preventDefault();
+ <script>
+ document.addEventListener('DOMContentLoaded', () => {
+ const form = document.querySelector('form');
+ const button = form.querySelector('button[type="submit"]');
- button.disabled = true;
- document.body.style.cursor = "wait";
+ form.addEventListener('submit', async (e) => {
+ e.preventDefault();
- const statusElement = document.getElementById("status");
- while (statusElement.firstChild) {
- statusElement.firstChild.remove();
- }
+ button.disabled = true;
+ document.body.style.cursor = "wait";
- const csrfToken =
document.querySelector("input[name='csrf_token']").value;
+ const statusElement = document.getElementById("status");
+ while (statusElement.firstChild) {
+ statusElement.firstChild.remove();
+ }
- try {
- const response = await fetch(window.location.href, {
- method: "POST",
- headers: {
- "X-CSRFToken": csrfToken
+ const csrfToken =
document.querySelector("input[name='csrf_token']").value;
+
+ try {
+ const response = await fetch(window.location.href, {
+ method: "POST",
+ headers: {
+ "X-CSRFToken": csrfToken
+ }
+ });
+
+ if (!response.ok) {
+ addStatusMessage(statusElement, "Could not make
network request", "error");
+ return
+ }
+
+ const data = await response.json();
+ addStatusMessage(statusElement, data.message,
data.category)
+ } catch (error) {
+ addStatusMessage(statusElement, error, "error")
+ } finally {
+ button.disabled = false;
+ document.body.style.cursor = "default";
}
});
-
- if (!response.ok) {
- addStatusMessage(statusElement, "Could not make network
request", "error");
- return
+ });
+
+ function addStatusMessage(parentElement, message, category) {
+ const divElement = document.createElement("div");
+ divElement.classList.add("page-status-message");
+ divElement.classList.add(category);
+ if (category === "error") {
+ const prefixElement = document.createElement("strong");
+ const textElement = document.createTextNode("Error: ");
+ prefixElement.appendChild(textElement);
+ divElement.appendChild(prefixElement);
}
-
- const data = await response.json();
- addStatusMessage(statusElement, data.message, data.category)
- } catch (error) {
- addStatusMessage(statusElement, error, "error")
- } finally {
- button.disabled = false;
- document.body.style.cursor = "default";
+ const textNode = document.createTextNode(message);
+ divElement.appendChild(textNode);
+ parentElement.appendChild(divElement);
}
- });
- });
-
- function addStatusMessage(parentElement, message, category) {
- const divElement = document.createElement("div");
- divElement.classList.add("page-status-message");
- divElement.classList.add(category);
- if (category === "error") {
- const prefixElement = document.createElement("strong");
- const textElement = document.createTextNode("Error: ");
- prefixElement.appendChild(textElement);
- divElement.appendChild(prefixElement);
- }
- const textNode = document.createTextNode(message);
- divElement.appendChild(textNode);
- parentElement.appendChild(divElement);
- }
- </script>
+ </script>
{% endblock content %}
diff --git a/atr/admin/templates/update-projects.html
b/atr/admin/templates/update-projects.html
index a0f73cc..dcda398 100644
--- a/atr/admin/templates/update-projects.html
+++ b/atr/admin/templates/update-projects.html
@@ -1,152 +1,148 @@
{% extends "layouts/base-admin.html" %}
-{% block title %}
- Update projects ~ ATR
-{% endblock title %}
+{%- block title -%}Update projects ~ ATR{%- endblock title -%}
-{% block description %}
- Update PMCs and podlings from remote data sources.
-{% endblock description %}
+{%- block description -%}Update PMCs and podlings from remote data sources.{%-
endblock description -%}
{% block stylesheets %}
- {{ super() }}
- <style>
- .page-form-group {
- margin-bottom: 1rem;
- }
-
- button {
- margin-top: 1rem;
- padding: 0.5rem 1rem;
- background: #036;
- color: white;
- border: none;
- border-radius: 4px;
- cursor: pointer;
- font-weight: 500;
- }
-
- button:hover {
- background: #047;
- }
-
- button:disabled {
- color: gray;
- }
-
- .page-warning {
- margin: 1.5rem 0;
- padding: 1rem;
- background: #fff3cd;
- border: 1px solid #ffeeba;
- border-radius: 4px;
- color: #856404;
- }
-
- .page-warning p:last-child {
- margin-bottom: 0;
- }
-
- .page-warning strong {
- color: #533f03;
- }
-
- .page-status-message {
- margin: 1.5rem 0;
- padding: 1rem;
- border-radius: 4px;
- }
-
- .page-status-message.success {
- background: #d4edda;
- border: 1px solid #c3e6cb;
- color: #155724;
- }
-
- .page-status-message.error {
- background: #f8d7da;
- border: 1px solid #f5c6cb;
- color: #721c24;
- }
- </style>
+ {{ super() }}
+ <style>
+ .page-form-group {
+ margin-bottom: 1rem;
+ }
+
+ button {
+ margin-top: 1rem;
+ padding: 0.5rem 1rem;
+ background: #036;
+ color: white;
+ border: none;
+ border-radius: 4px;
+ cursor: pointer;
+ font-weight: 500;
+ }
+
+ button:hover {
+ background: #047;
+ }
+
+ button:disabled {
+ color: gray;
+ }
+
+ .page-warning {
+ margin: 1.5rem 0;
+ padding: 1rem;
+ background: #fff3cd;
+ border: 1px solid #ffeeba;
+ border-radius: 4px;
+ color: #856404;
+ }
+
+ .page-warning p:last-child {
+ margin-bottom: 0;
+ }
+
+ .page-warning strong {
+ color: #533f03;
+ }
+
+ .page-status-message {
+ margin: 1.5rem 0;
+ padding: 1rem;
+ border-radius: 4px;
+ }
+
+ .page-status-message.success {
+ background: #d4edda;
+ border: 1px solid #c3e6cb;
+ color: #155724;
+ }
+
+ .page-status-message.error {
+ background: #f8d7da;
+ border: 1px solid #f5c6cb;
+ color: #721c24;
+ }
+ </style>
{% endblock stylesheets %}
{% block content %}
- <h1>Update projects</h1>
- <p>
- This page allows you to update PMC and podling information in the database
from remote data sources.
- </p>
-
- <div class="page-warning">
+ <h1>Update projects</h1>
<p>
- <strong>Note:</strong> This operation will update all project
information, including:
+ This page allows you to update PMC and podling information in the
database from remote data sources.
</p>
- <ul>
- <li>PMC member lists and release manager assignments</li>
- <li>Podling status and basic information</li>
- <li>Project metadata and relationships</li>
- </ul>
- </div>
- <div id="status"></div>
+ <div class="page-warning">
+ <p>
+ <strong>Note:</strong> This operation will update all project
information, including:
+ </p>
+ <ul>
+ <li>PMC member lists and release manager assignments</li>
+ <li>Podling status and basic information</li>
+ <li>Project metadata and relationships</li>
+ </ul>
+ </div>
- {{ empty_form }}
+ <div id="status"></div>
- <script>
- document.addEventListener('DOMContentLoaded', () => {
- const form = document.querySelector('form');
- const button = form.querySelector('button[type="submit"]');
+ {{ empty_form }}
- form.addEventListener('submit', async (e) => {
- e.preventDefault();
+ <script>
+ document.addEventListener('DOMContentLoaded', () => {
+ const form = document.querySelector('form');
+ const button = form.querySelector('button[type="submit"]');
- button.disabled = true;
- document.body.style.cursor = "wait";
+ form.addEventListener('submit', async (e) => {
+ e.preventDefault();
- const statusElement = document.getElementById("status");
- while (statusElement.firstChild) {
- statusElement.firstChild.remove();
- }
+ button.disabled = true;
+ document.body.style.cursor = "wait";
- const csrfToken =
document.querySelector("input[name='csrf_token']").value;
+ const statusElement = document.getElementById("status");
+ while (statusElement.firstChild) {
+ statusElement.firstChild.remove();
+ }
- try {
- const response = await fetch(window.location.href, {
- method: "POST",
- headers: {
- "X-CSRFToken": csrfToken
+ const csrfToken =
document.querySelector("input[name='csrf_token']").value;
+
+ try {
+ const response = await fetch(window.location.href, {
+ method: "POST",
+ headers: {
+ "X-CSRFToken": csrfToken
+ }
+ });
+
+ if (!response.ok) {
+ addStatusMessage(statusElement, "Could not make
network request", "error");
+ return
+ }
+
+ const data = await response.json();
+ addStatusMessage(statusElement, data.message,
data.category)
+ } catch (error) {
+ addStatusMessage(statusElement, error, "error")
+ } finally {
+ button.disabled = false;
+ document.body.style.cursor = "default";
}
});
-
- if (!response.ok) {
- addStatusMessage(statusElement, "Could not make network
request", "error");
- return
+ });
+
+ function addStatusMessage(parentElement, message, category) {
+ const divElement = document.createElement("div");
+ divElement.classList.add("page-status-message");
+ divElement.classList.add(category);
+ if (category === "error") {
+ const prefixElement = document.createElement("strong");
+ const textElement = document.createTextNode("Error: ");
+ prefixElement.appendChild(textElement);
+ divElement.appendChild(prefixElement);
}
-
- const data = await response.json();
- addStatusMessage(statusElement, data.message, data.category)
- } catch (error) {
- addStatusMessage(statusElement, error, "error")
- } finally {
- button.disabled = false;
- document.body.style.cursor = "default";
+ const textNode = document.createTextNode(message);
+ divElement.appendChild(textNode);
+ parentElement.appendChild(divElement);
}
- });
- });
-
- function addStatusMessage(parentElement, message, category) {
- const divElement = document.createElement("div");
- divElement.classList.add("page-status-message");
- divElement.classList.add(category);
- if (category === "error") {
- const prefixElement = document.createElement("strong");
- const textElement = document.createTextNode("Error: ");
- prefixElement.appendChild(textElement);
- divElement.appendChild(prefixElement);
- }
- const textNode = document.createTextNode(message);
- divElement.appendChild(textNode);
- parentElement.appendChild(divElement);
- }
- </script>
+ </script>
{% endblock content %}
diff --git a/atr/admin/templates/validation.html
b/atr/admin/templates/validation.html
index a57ea85..79ef7aa 100644
--- a/atr/admin/templates/validation.html
+++ b/atr/admin/templates/validation.html
@@ -1,12 +1,8 @@
{% extends "layouts/base.html" %}
-{% block title %}
- Validation ~ ATR Admin
-{% endblock title %}
+{%- block title -%}Validation ~ ATR Admin{%- endblock title -%}
-{% block description %}
- Results of running server data validators.
-{% endblock description %}
+{%- block description -%}Results of running server data validators.{%-
endblock description -%}
{% block content %}
<h1>Validation</h1>
diff --git a/atr/policy/third-party-licenses.html
b/atr/policy/third-party-licenses.html
index 12b6099..8f9932c 100644
--- a/atr/policy/third-party-licenses.html
+++ b/atr/policy/third-party-licenses.html
@@ -1,5 +1,5 @@
<p>Title: ASF 3rd Party License Policy
-license: https://www.apache.org/licenses/LICENSE-2.0</p>
+ license: https://www.apache.org/licenses/LICENSE-2.0</p>
<p>[TOC]</p>
<h2>Purpose {#audience}</h2>
<p>This policy provides licensing guidance to Apache Software Foundation
projects. It identifies the acceptable
diff --git a/atr/templates/about.html b/atr/templates/about.html
index 3e11f82..6aa969d 100644
--- a/atr/templates/about.html
+++ b/atr/templates/about.html
@@ -1,32 +1,30 @@
{% extends "layouts/base.html" %}
-{# djlint:off #}
{%- block title -%}About ATR ~ ATR{%- endblock title -%}
{%- block description -%}About ATR ~ ATR{%- endblock description -%}
-{# djlint:on #}
{% block stylesheets %}
{{ super() }}
<style>
- img {
- border: 1px solid #cccccc;
- box-shadow: 0 0 1rem rgba(0, 0, 0, 0.2);
- margin: 1rem 0;
- max-width: 50%;
- }
+ img {
+ border: 1px solid #cccccc;
+ box-shadow: 0 0 1rem rgba(0, 0, 0, 0.2);
+ margin: 1rem 0;
+ max-width: 50%;
+ }
- table {
- border: 1px solid #eeeeee;
- }
+ table {
+ border: 1px solid #eeeeee;
+ }
- th.step {
- width: 15%;
- }
+ th.step {
+ width: 15%;
+ }
- td {
- width: 28.333%;
- }
+ td {
+ width: 28.333%;
+ }
</style>
{% endblock stylesheets %}
diff --git a/atr/templates/blank.html b/atr/templates/blank.html
index 68d47d6..0994483 100644
--- a/atr/templates/blank.html
+++ b/atr/templates/blank.html
@@ -1,10 +1,8 @@
{% extends "layouts/base.html" %}
-{# djlint:off #}
{%- block title -%}{{ title }} ~ ATR{%- endblock title -%}
{%- block description -%}{{ description }}{%- endblock description -%}
-{# djlint:on #}
{% block content %}
{{ content }}
@@ -17,5 +15,5 @@
{% endif %}
{% if init_js %}<script>
init();
-</script>{% endif %}
+ </script>{% endif %}
{% endblock javascripts %}
diff --git a/atr/templates/check-selected.html
b/atr/templates/check-selected.html
index 5884761..8ae75d3 100644
--- a/atr/templates/check-selected.html
+++ b/atr/templates/check-selected.html
@@ -1,42 +1,40 @@
{% extends "layouts/base.html" %}
-{# djlint:off #}
{%- block title -%}{{ release.project.display_name }} {{ version_name }} ~
ATR{%- endblock title -%}
{%- block description -%}Review page for the {{ release.project.display_name
}} {{ version_name }} candidate{%- endblock description -%}
-{# djlint:on #}
{% import 'macros/dialog.html' as dialog %}
{% block stylesheets %}
{{ super() }}
<style>
- .page-table-striped-odd {
- background-color: #eeeeee;
+ .page-table-striped-odd {
+ background-color: #eeeeee;
+ }
+
+ .page-icon-cell {
+ width: 2em;
+ text-align: center;
+ }
+
+ table tr {
+ border-bottom: none;
+ }
+
+ #poll-progress-container {
+ height: 6px;
+ }
+
+ @keyframes poll-grow {
+ from {
+ width: 0%;
}
- .page-icon-cell {
- width: 2em;
- text-align: center;
- }
-
- table tr {
- border-bottom: none;
- }
-
- #poll-progress-container {
- height: 6px;
- }
-
- @keyframes poll-grow {
- from {
- width: 0%;
- }
-
- to {
- width: 100%;
- }
+ to {
+ width: 100%;
}
+ }
</style>
{% endblock stylesheets %}
@@ -200,106 +198,106 @@
{% block javascripts %}
{{ super() }}
<script>
- init();
+ init();
- (function() {
- const banner = document.getElementById("ongoing-tasks-banner");
- if (!banner) return;
+ (function() {
+ const banner = document.getElementById("ongoing-tasks-banner");
+ if (!banner) return;
- const apiUrl = banner.dataset.apiUrl;
- if (!apiUrl) 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;
+ 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;
+ 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 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;
+ function updateBanner(count) {
+ if (!countSpan || !textSpan) return;
- currentCount = count;
- countSpan.textContent = count;
+ currentCount = count;
+ countSpan.textContent = count;
- const taskWord = count === 1 ? "task" : "tasks";
- const isAre = count === 1 ? "is" : "are";
+ 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.`;
+ 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) {
+ 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();
+ 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);
- });
- }
+ setTimeout(pollOngoingTasks, pollInterval * 2);
+ });
+ }
- restartProgress();
- setTimeout(pollOngoingTasks, pollInterval);
- })();
+ restartProgress();
+ setTimeout(pollOngoingTasks, pollInterval);
+ })();
</script>
{% endblock javascripts %}
diff --git a/atr/templates/committee-directory.html
b/atr/templates/committee-directory.html
index 81157ae..23c9e58 100644
--- a/atr/templates/committee-directory.html
+++ b/atr/templates/committee-directory.html
@@ -1,325 +1,323 @@
{% extends "layouts/base.html" %}
-{# djlint:off #}
{%- block title -%}Committee directory ~ ATR{%- endblock title -%}
{%- block description -%}List of all ASF committees and their assated
projects.{%- endblock description -%}
-{# djlint:on #}
{% block stylesheets %}
- {{ super() }}
- <style>
- .page-committee-title-link:hover {
- cursor: pointer;
- }
+ {{ super() }}
+ <style>
+ .page-committee-title-link:hover {
+ cursor: pointer;
+ }
- .page-logo {
- max-height: 100%;
- width: auto;
- object-fit: contain;
- }
+ .page-logo {
+ max-height: 100%;
+ width: auto;
+ object-fit: contain;
+ }
- .page-logo-container {
- height: 48px;
- width: 100%;
- display: flex;
- justify-content: center;
- align-items: center;
- }
+ .page-logo-container {
+ height: 48px;
+ width: 100%;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ }
- .page-project-subcard {
- min-height: 96px;
- background-color: #f8f9fa;
- }
+ .page-project-subcard {
+ min-height: 96px;
+ background-color: #f8f9fa;
+ }
- .page-project-subcard:hover {
- border-color: gray;
- cursor: pointer;
- }
+ .page-project-subcard:hover {
+ border-color: gray;
+ cursor: pointer;
+ }
- .page-project-subcard-categories {
- font-size: 0.8em;
- }
+ .page-project-subcard-categories {
+ font-size: 0.8em;
+ }
- .page-project-inactive {
- opacity: 0.6;
- }
- </style>
+ .page-project-inactive {
+ opacity: 0.6;
+ }
+ </style>
{% endblock stylesheets %}
{% block content %}
- <h1>Committee directory</h1>
- <p>Current ASF committees and their projects:</p>
+ <h1>Committee directory</h1>
+ <p>Current ASF committees and their projects:</p>
- <div class="mb-3">
- <input type="text"
- id="project-filter"
- aria-label="Project name filter"
- class="form-control d-inline-block w-auto" />
- <button type="button" class="btn btn-primary" id="filter-button">Filter
all</button>
- {% if current_user %}
- <button type="button"
- class="btn btn-secondary ms-2"
- id="filter-participant-button"
- aria-pressed="false"
- data-showing="participant">
+ <div class="mb-3">
+ <input type="text"
+ id="project-filter"
+ aria-label="Project name filter"
+ class="form-control d-inline-block w-auto" />
+ <button type="button" class="btn btn-primary"
id="filter-button">Filter all</button>
{% if current_user %}
- Show all committees
- {% else %}
- Show my committees
+ <button type="button"
+ class="btn btn-secondary ms-2"
+ id="filter-participant-button"
+ aria-pressed="false"
+ data-showing="participant">
+ {% if current_user %}
+ Show all committees
+ {% else %}
+ Show my committees
+ {% endif %}
+ </button>
{% endif %}
- </button>
- {% endif %}
- </div>
+ </div>
- <div class="mb-3">
- <p>
- Total count: <span id="committee-count">{{ committees|length }}</span>
- </p>
- </div>
+ <div class="mb-3">
+ <p>
+ Total count: <span id="committee-count">{{ committees|length
}}</span>
+ </p>
+ </div>
- <div class="row row-cols-1 row-cols-md-2 row-cols-lg-3 g-4">
- {% for committee in committees %}
- {% set is_part = false %}
- {% if current_user and committee %}
- {% if (current_user.uid in committee.committee_members) or
- (current_user.uid in committee.committers) or
- (current_user.uid in committee.release_managers) %}
- {% set is_part = true %}
+ <div class="row row-cols-1 row-cols-md-2 row-cols-lg-3 g-4">
+ {% for committee in committees %}
+ {% set is_part = false %}
+ {% if current_user and committee %}
+ {% if (current_user.uid in committee.committee_members) or
+ (current_user.uid in committee.committers) or
+ (current_user.uid in committee.release_managers) %}
+ {% set is_part = true %}
+ {% endif %}
{% endif %}
- {% endif %}
- <div class="col">
- <div class="card h-100 shadow-sm page-project-card"
- data-is-participant="{{ 'true' if is_part else 'false' }}">
- <div class="card-body">
- <div class="row mb-3 align-items-center">
- <div class="col">
- <h3 class="card-title fs-4 mb-0">
- <a href="{{ as_url(get.committees.view, name=committee.name)
}}"
- class="text-decoration-none text-dark
page-committee-title-link">{{ committee.display_name }}</a>
- </h3>
- </div>
- <div class="col-5 col-lg-4 text-center">
- <div class="page-logo-container">
- {% if (committee.name == "incubator") or
committee.name.startswith("incubator-") %}
- <img
src="https://www.apache.org/logos/res/incubator/default.png"
- alt=""
- class="page-logo"
- onerror="this.style.display='none';" />
- {% else %}
- <img src="https://www.apache.org/logos/res/{{
committee.name }}/default.png"
- alt=""
- class="page-logo"
- onerror="this.style.display='none';" />
- {% endif %}
- </div>
- </div>
- </div>
- <div class="mt-3 page-project-list-container">
- {% set max_initial_projects = 2 %}
- {% if committee.projects %}
- {% for project in committee.projects|sort(attribute="name") %}
- <div class="card mb-3 shadow-sm page-project-subcard {% if
loop.index > max_initial_projects %}page-project-extra d-none{% endif %} {% if
project.status.value.lower() != "active" %}page-project-inactive{% endif %}"
- data-project-url="{{ as_url(get.projects.view,
name=project.name) }}">
- <div class="card-body p-3 d-flex flex-column h-100">
- <div class="d-flex justify-content-between
align-items-start">
- <p class="mb-1 me-2 fs-6">
- <a href="{{ as_url(get.projects.view,
name=project.name) }}"
- class="text-decoration-none stretched-link">{{
project.display_name }}</a>
- </p>
- <div>
- {% if project.status.value.lower() != "active" %}
- <span class="badge text-bg-secondary ms-1">{{
project.status.value.lower() }}</span>
- {% endif %}
+ <div class="col">
+ <div class="card h-100 shadow-sm page-project-card"
+ data-is-participant="{{ 'true' if is_part else 'false' }}">
+ <div class="card-body">
+ <div class="row mb-3 align-items-center">
+ <div class="col">
+ <h3 class="card-title fs-4 mb-0">
+ <a href="{{ as_url(get.committees.view,
name=committee.name) }}"
+ class="text-decoration-none text-dark
page-committee-title-link">{{ committee.display_name }}</a>
+ </h3>
+ </div>
+ <div class="col-5 col-lg-4 text-center">
+ <div class="page-logo-container">
+ {% if (committee.name == "incubator") or
committee.name.startswith("incubator-") %}
+ <img
src="https://www.apache.org/logos/res/incubator/default.png"
+ alt=""
+ class="page-logo"
+ onerror="this.style.display='none';"
/>
+ {% else %}
+ <img
src="https://www.apache.org/logos/res/{{ committee.name }}/default.png"
+ alt=""
+ class="page-logo"
+ onerror="this.style.display='none';"
/>
+ {% endif %}
+ </div>
</div>
- </div>
- <div class="mb-1 page-project-subcard-categories">
- {% set categories = project.category.split(', ') if
project.category else [] %}
- {% for category in categories %}
- {% if category != "retired" %}<span class="badge
text-bg-primary me-1">{{ category }}</span>{% endif %}
- {% endfor %}
- {% set langs = project.programming_languages.split(',
') if project.programming_languages else [] %}
- {% for lang in langs[:1] %}<span class="badge
text-bg-success me-1">{{ lang }}</span>{% endfor %}
- </div>
</div>
- </div>
- {% endfor %}
- {% if committee.projects|length > max_initial_projects %}
- <button type="button"
- class="btn btn-sm btn-outline-secondary mt-2
page-toggle-committee-projects"
- aria-expanded="false"
- data-text-show="Show {{ committee.projects|length -
max_initial_projects }} more projects..."
- data-text-hide="Show less...">
- Show {{ committee.projects|length - max_initial_projects
}} more projects...
- </button>
- {% endif %}
+ <div class="mt-3 page-project-list-container">
+ {% set max_initial_projects = 2 %}
+ {% if committee.projects %}
+ {% for project in
committee.projects|sort(attribute="name") %}
+ <div class="card mb-3 shadow-sm
page-project-subcard {% if loop.index > max_initial_projects
%}page-project-extra d-none{% endif %} {% if project.status.value.lower() !=
"active" %}page-project-inactive{% endif %}"
+ data-project-url="{{
as_url(get.projects.view, name=project.name) }}">
+ <div class="card-body p-3 d-flex
flex-column h-100">
+ <div class="d-flex
justify-content-between align-items-start">
+ <p class="mb-1 me-2 fs-6">
+ <a href="{{
as_url(get.projects.view, name=project.name) }}"
+ class="text-decoration-none
stretched-link">{{ project.display_name }}</a>
+ </p>
+ <div>
+ {% if
project.status.value.lower() != "active" %}
+ <span class="badge
text-bg-secondary ms-1">{{ project.status.value.lower() }}</span>
+ {% endif %}
+ </div>
+ </div>
+ <div class="mb-1
page-project-subcard-categories">
+ {% set categories =
project.category.split(', ') if project.category else [] %}
+ {% for category in categories %}
+ {% if category != "retired"
%}<span class="badge text-bg-primary me-1">{{ category }}</span>{% endif %}
+ {% endfor %}
+ {% set langs =
project.programming_languages.split(', ') if project.programming_languages else
[] %}
+ {% for lang in langs[:1] %}<span
class="badge text-bg-success me-1">{{ lang }}</span>{% endfor %}
+ </div>
+ </div>
+ </div>
+ {% endfor %}
+ {% if committee.projects|length >
max_initial_projects %}
+ <button type="button"
+ class="btn btn-sm
btn-outline-secondary mt-2 page-toggle-committee-projects"
+ aria-expanded="false"
+ data-text-show="Show {{
committee.projects|length - max_initial_projects }} more projects..."
+ data-text-hide="Show less...">
+ Show {{ committee.projects|length -
max_initial_projects }} more projects...
+ </button>
+ {% endif %}
{# Add an else clause here if we decide to show an alternative
to an empty card #}
- {% endif %}
- </div>
- {% if current_user and is_part and (not
committee_is_standing(committee.name)) %}
- <a href="{{ as_url(get.projects.add_project,
committee_name=committee.name) }}"
- title="Create a project for {{ committee.display_name }}"
- class="text-decoration-none d-block mt-4 mb-3">
- <div class="card h-100 shadow-sm atr-cursor-pointer
page-project-subcard">
- <div class="card-body d-flex align-items-center
text-secondary p-3">
- <div>
- <i class="bi bi-plus-circle me-2"></i>Create project
- <br />
- <small class="text-muted">for {{ committee.display_name
}}</small>
+ {% endif %}
</div>
- </div>
+ {% if current_user and is_part and (not
committee_is_standing(committee.name)) %}
+ <a href="{{ as_url(get.projects.add_project,
committee_name=committee.name) }}"
+ title="Create a project for {{
committee.display_name }}"
+ class="text-decoration-none d-block mt-4 mb-3">
+ <div class="card h-100 shadow-sm
atr-cursor-pointer page-project-subcard">
+ <div class="card-body d-flex
align-items-center text-secondary p-3">
+ <div>
+ <i class="bi bi-plus-circle
me-2"></i>Create project
+ <br />
+ <small class="text-muted">for {{
committee.display_name }}</small>
+ </div>
+ </div>
+ </div>
+ </a>
+ {% endif %}
</div>
- </a>
- {% endif %}
- </div>
+ </div>
</div>
- </div>
- {% endfor %}
- </div>
+{% endfor %}
+</div>
{% endblock content %}
{% block javascripts %}
- {{ super() }}
- <script>
- let allCommitteeCards = [];
+ {{ super() }}
+ <script>
+ let allCommitteeCards = [];
- function filterCommitteesByText() {
- const projectFilter =
document.getElementById("project-filter").value;
- const cards = allCommitteeCards;
- let visibleCount = 0;
+ 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");
- }
+ 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;
- }
+ 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();
- }
- });
+ 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;
+ 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;
- });
- }
+ 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";
+ 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 (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;
+ 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;
- }
- });
- });
+
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");
- });
+
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>
+ 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>
{% endblock javascripts %}
diff --git a/atr/templates/committee-view.html
b/atr/templates/committee-view.html
index 1319d3b..c7fd3bb 100644
--- a/atr/templates/committee-view.html
+++ b/atr/templates/committee-view.html
@@ -1,10 +1,8 @@
{% extends "layouts/base.html" %}
-{# djlint:off #}
{%- block title -%}Committee ~ ATR{%- endblock title -%}
{%- block description -%}Information regarding an Apachommittee.{%- endblock
description -%}
-{# djlint:on #}
{% block content %}
<h1>{{ committee.display_name }}</h1>
diff --git a/atr/templates/delete-committee-keys.html
b/atr/templates/delete-committee-keys.html
index f16938b..afbf30a 100644
--- a/atr/templates/delete-committee-keys.html
+++ b/atr/templates/delete-committee-keys.html
@@ -2,11 +2,9 @@
{% import "macros/forms.html" as forms %}
-{# djlint:off #}
{%- block title -%}Delete committee keys{%- endblock title -%}
{%- block description -%}Delete committee keys{%- endblock description -%}
-{# djlint:on #}
{% block content %}
<div class="container mx-auto p-4">
diff --git a/atr/templates/download-all.html b/atr/templates/download-all.html
index b91d6ca..109eb5d 100644
--- a/atr/templates/download-all.html
+++ b/atr/templates/download-all.html
@@ -1,10 +1,8 @@
{% extends "layouts/base.html" %}
-{# djlint:off #}
{%- block title -%}Download {{ release.project.display_name }} {{
release.version }} ~ ATR{%- endblock title -%}
{%- block description -%}Download commands for {{ release.project.display_name
}} {{ release.version }}.{%- endblock description -%}
-{# djlint:on #}
{% block content %}
{% set phase = release.phase.value %}
diff --git a/atr/templates/draft-tools.html b/atr/templates/draft-tools.html
index 1cb1fb8..163465b 100644
--- a/atr/templates/draft-tools.html
+++ b/atr/templates/draft-tools.html
@@ -1,10 +1,8 @@
{% extends "layouts/base.html" %}
-{# djlint:off #}
{%- block title -%}File tools ~ ATR{%- endblock title -%}
{%- block description -%}Manage a file in the candidate draft using tools.{%-
endblock description -%}
-{# djlint:on #}
{% block content %}
<a href="{{ as_url(get.compose.selected, project_name=project_name,
version_name=version_name) }}"
@@ -28,7 +26,7 @@
<p>Generate an SHA256 or SHA512 hash file for this file.</p>
<div class="alert alert-warning">
<i class="bi bi-exclamation-triangle me-2"></i> IMPORTANT: The ASF
security team <a
href="https://infra.apache.org/release-signing.html#sha-checksum"
- class="alert-link">recommends using SHA512</a> as the hash algorithm.
+
class="alert-link">recommends using SHA512</a> as the hash algorithm.
Please select SHA512 unless you have a specific reason to use SHA256.
</div>
<div class="d-flex gap-2 mb-4">
diff --git a/atr/templates/error.html b/atr/templates/error.html
index 8602be6..56fc640 100644
--- a/atr/templates/error.html
+++ b/atr/templates/error.html
@@ -1,10 +1,8 @@
{% extends "layouts/base.html" %}
-{# djlint:off #}
{%- block title -%}Error ~ ATR{%- endblock title -%}
{%- block description -%}An error occurred while processing your request.{%-
endblock description -%}
-{# djlint:on #}
{% block content %}
<div>
diff --git a/atr/templates/includes/topnav.html
b/atr/templates/includes/topnav.html
index 67269a9..daa1c47 100644
--- a/atr/templates/includes/topnav.html
+++ b/atr/templates/includes/topnav.html
@@ -31,339 +31,339 @@
id="menuCandidates"
aria-labelledby="dropdownCandidates">
<li>
- <a class="dropdown-item" href="{{ as_url(get.root.index) }}"><i
class="bi bi-play-circle"></i>
- Candidates</a>
- </li>
- {% set unfinished_releases =
unfinished_releases_fn(current_user.uid) %}
- {% if unfinished_releases %}
- {% for project_short_display_name, project_name, releases in
unfinished_releases %}
- <li>
- <hr class="dropdown-divider" />
- </li>
- <li>
- <a class="dropdown-item fw-bold"
- href="{{ as_url(get.projects.view, name=project_name)
}}">{{ project_short_display_name }}</a>
+ <a class="dropdown-item" href="{{ as_url(get.root.index)
}}"><i class="bi bi-play-circle"></i>
+ Candidates</a>
</li>
- {% for release in releases %}
+ {% set unfinished_releases =
unfinished_releases_fn(current_user.uid) %}
+ {% if unfinished_releases %}
+ {% for project_short_display_name, project_name, releases in
unfinished_releases %}
+ <li>
+ <hr class="dropdown-divider" />
+ </li>
+ <li>
+ <a class="dropdown-item fw-bold"
+ href="{{ as_url(get.projects.view, name=project_name)
}}">{{ project_short_display_name }}</a>
+ </li>
+ {% for release in releases %}
+ <li>
+ <a class="dropdown-item" href="{{
release_as_url(release) }}"><i class="bi bi-tag"></i>
+ {{ release.version }}</a>
+ </li>
+ {% endfor %}
+ {% endfor %}
+ {% endif %}
+ {% set user_projects = user_projects_fn(current_user.uid) %}
+ {% if user_projects %}
+ {% set max_projects = 8 %}
+ <li>
+ <hr class="dropdown-divider" />
+ </li>
<li>
- <a class="dropdown-item" href="{{ release_as_url(release)
}}"><i class="bi bi-tag"></i>
- {{ release.version }}</a>
+ <a class="dropdown-item fw-bold" href="{{
as_url(get.root.index) }}">Start a release</a>
+ </li>
+ {% for project_name, project_full_name in
user_projects[:max_projects] %}
+ <li>
+ <a class="dropdown-item"
+ href="{{ as_url(get.start.selected,
project_name=project_name) }}"><i class="bi bi-plus-circle"></i>
+ {{ project_full_name.removeprefix("Apache
").removesuffix(" (Incubating)") }}</a>
+ </li>
+ {% endfor %}
+ {% if user_projects|length > max_projects %}
+ <li>
+ <a class="dropdown-item" href="{{ as_url(get.root.index)
}}"><i class="bi bi-three-dots"></i> {{ user_projects|length - max_projects }}
more</a>
+ </li>
+ {% endif %}
+ {% endif %}
+ </ul>
+ </li>
+ {% endif %}
+ <li class="nav-item dropdown">
+ <button class="nav-link dropdown-toggle btn"
+ id="dropdownCatalog"
+ type="button"
+ data-bs-toggle="dropdown"
+ aria-expanded="false"
+ aria-controls="menuCatalog">Releases</button>
+ <ul class="dropdown-menu"
+ id="menuCatalog"
+ aria-labelledby="dropdownCatalog">
+ <li>
+ <a class="dropdown-item" href="{{ as_url(get.release.releases)
}}"><i class="bi bi-view-list"></i>
+ Catalog</a>
</li>
- {% endfor %}
- {% endfor %}
- {% endif %}
- {% set user_projects = user_projects_fn(current_user.uid) %}
- {% if user_projects %}
- {% set max_projects = 8 %}
- <li>
- <hr class="dropdown-divider" />
- </li>
- <li>
- <a class="dropdown-item fw-bold" href="{{ as_url(get.root.index)
}}">Start a release</a>
- </li>
- {% for project_name, project_full_name in user_projects[:max_projects]
%}
- <li>
- <a class="dropdown-item"
- href="{{ as_url(get.start.selected, project_name=project_name)
}}"><i class="bi bi-plus-circle"></i>
- {{ project_full_name.removeprefix("Apache ").removesuffix("
(Incubating)") }}</a>
- </li>
- {% endfor %}
- {% if user_projects|length > max_projects %}
- <li>
- <a class="dropdown-item" href="{{ as_url(get.root.index) }}"><i
class="bi bi-three-dots"></i> {{ user_projects|length - max_projects }} more</a>
- </li>
- {% endif %}
- {% endif %}
-</ul>
-</li>
-{% endif %}
-<li class="nav-item dropdown">
- <button class="nav-link dropdown-toggle btn"
- id="dropdownCatalog"
- type="button"
- data-bs-toggle="dropdown"
- aria-expanded="false"
- aria-controls="menuCatalog">Releases</button>
- <ul class="dropdown-menu"
- id="menuCatalog"
- aria-labelledby="dropdownCatalog">
- <li>
- <a class="dropdown-item" href="{{ as_url(get.release.releases) }}"><i
class="bi bi-view-list"></i>
- Catalog</a>
-</li>
-<li>
-<a class="dropdown-item" href="{{ as_url(get.committees.directory) }}"><i
class="bi bi-collection"></i>
-Committees</a>
-</li>
-<li>
+ <li>
+ <a class="dropdown-item" href="{{
as_url(get.committees.directory) }}"><i class="bi bi-collection"></i>
+ Committees</a>
+ </li>
+ <li>
{# This path is handled by the frontend proxy server #}
{# https://djlint.com/docs/ignoring-code/ #}
{# djlint:off J018 #} <a class="dropdown-item" href="/downloads/"><i
class="bi bi-download"></i> Downloads</a> {# djlint:on #}
-</li>
-</ul>
-</li>
-{% if current_user %}
- <li class="nav-item dropdown">
- <button class="nav-link dropdown-toggle btn"
- id="dropdownConfigure"
- type="button"
- data-bs-toggle="dropdown"
- aria-expanded="false"
- aria-controls="menuCandidates">Configure</button>
- <ul class="dropdown-menu"
- id="menuConfigure"
- aria-labelledby="dropdownConfigure">
- <li>
- <a class="dropdown-item" href="{{ as_url(get.committees.directory)
}}"><i class="bi bi-collection"></i>
- Committees</a>
- </li>
- <li>
- <a class="dropdown-item" href="{{ as_url(get.projects.projects) }}"><i
class="bi bi-collection"></i>
-Projects</a>
-</li>
+ </li>
+ </ul>
+ </li>
+ {% if current_user %}
+ <li class="nav-item dropdown">
+ <button class="nav-link dropdown-toggle btn"
+ id="dropdownConfigure"
+ type="button"
+ data-bs-toggle="dropdown"
+ aria-expanded="false"
+ aria-controls="menuCandidates">Configure</button>
+ <ul class="dropdown-menu"
+ id="menuConfigure"
+ aria-labelledby="dropdownConfigure">
+ <li>
+ <a class="dropdown-item" href="{{
as_url(get.committees.directory) }}"><i class="bi bi-collection"></i>
+ Committees</a>
+ </li>
+ <li>
+ <a class="dropdown-item" href="{{
as_url(get.projects.projects) }}"><i class="bi bi-collection"></i>
+ Projects</a>
+ </li>
<!--
<li>
<a class="dropdown-item" href="{{ as_url(get.keys.keys) }}"><i class="bi
bi-key"></i>
Public keys</a>
</li>
-->
-<li>
-<a class="dropdown-item" href="{{ as_url(get.tokens.tokens) }}"><i class="bi
bi-key"></i>
-API tokens</a>
-</li>
-</ul>
-</li>
-{% endif %}
-<li class="nav-item dropdown">
- <button class="nav-link dropdown-toggle btn"
- id="dropdownHelp"
- type="button"
- data-bs-toggle="dropdown"
- aria-expanded="false"
- aria-controls="menuHelp">Help</button>
- <ul class="dropdown-menu" id="menuHelp" aria-labelledby="dropdownHelp">
- {% if current_user %}
- <li>
- <a class="dropdown-item" href="{{ as_url(get.root.tutorial) }}"><i
class="bi bi-book"></i>
- Tutorial</a>
- </li>
-{% endif %}
-<li>
-<a class="dropdown-item" href="{{ as_url(get.docs.index) }}"><i class="bi
bi-book"></i>
-Documentation</a>
-</li>
-<li>
-<a class="dropdown-item" href="{{ as_url(get.root.policies) }}"><i class="bi
bi-book"></i>
-ASF Policies</a>
-</li>
-{% if current_user %}
- <li>
+ <li>
+ <a class="dropdown-item" href="{{ as_url(get.tokens.tokens)
}}"><i class="bi bi-key"></i>
+ API tokens</a>
+ </li>
+ </ul>
+ </li>
+ {% endif %}
+ <li class="nav-item dropdown">
+ <button class="nav-link dropdown-toggle btn"
+ id="dropdownHelp"
+ type="button"
+ data-bs-toggle="dropdown"
+ aria-expanded="false"
+ aria-controls="menuHelp">Help</button>
+ <ul class="dropdown-menu" id="menuHelp"
aria-labelledby="dropdownHelp">
+ {% if current_user %}
+ <li>
+ <a class="dropdown-item" href="{{ as_url(get.root.tutorial)
}}"><i class="bi bi-book"></i>
+ Tutorial</a>
+ </li>
+ {% endif %}
+ <li>
+ <a class="dropdown-item" href="{{ as_url(get.docs.index) }}"><i
class="bi bi-book"></i>
+ Documentation</a>
+ </li>
+ <li>
+ <a class="dropdown-item" href="{{ as_url(get.root.policies)
}}"><i class="bi bi-book"></i>
+ ASF Policies</a>
+ </li>
+ {% if current_user %}
+ <li>
{# djlint:off J018 #} <a class="dropdown-item" href="/api/docs"><i
class="bi bi-file-earmark-code"></i>
- OpenAPI</a> {# djlint:on #}
- </li>
- <li>
- <hr class="dropdown-divider" />
- </li>
- <li>
- <a class="dropdown-item"
- href="https://github.com/apache/tooling-docs/"
- target="_blank"><i class="bi bi-github"></i> Tooling Docs</a>
- </li>
- <li>
- <hr class="dropdown-divider" />
- </li>
- <li>
- <a class="dropdown-item"
- href="https://github.com/apache/tooling-trusted-releases"
- target="_blank"><i class="bi bi-github"></i> Trusted Releases</a>
- </li>
- <li>
- <a class="dropdown-item"
- href="https://github.com/apache/tooling-releases-client"
- target="_blank"><i class="bi bi-github"></i> Trusted Releases Client</a>
- </li>
- <li>
- <a class="dropdown-item"
- href="https://github.com/apache/tooling-actions"
- target="_blank"><i class="bi bi-github"></i> Trusted Releases
Actions</a>
- </li>
-{% endif %}
-</ul>
-</li>
-{% if is_viewing_as_admin_fn(current_user.uid) %}
- <li class="nav-item dropdown">
- <button class="nav-link dropdown-toggle btn"
- id="dropdownAdmin"
- type="button"
- data-bs-toggle="dropdown"
- aria-expanded="false"
- aria-controls="menuAdmin">Admin</button>
- <ul class="dropdown-menu" id="menuAdmin" aria-labelledby="dropdownAdmin">
- <li>
- <a class="dropdown-item"
- href="{{ as_url(admin.all_releases) }}"
- {% if request.endpoint == 'atr_admin_all_releases'
%}class="active"{% endif %}><i class="bi bi-list-ul"></i> All releases</a>
- </li>
- <li>
- <a class="dropdown-item"
- href="{{ as_url(admin.browse_as_get) }}"
- {% if request.endpoint == 'atr_admin_browse_as_get'
%}class="active"{% endif %}><i class="bi bi-person-plus"></i> Browse as user</a>
- </li>
- <li>
- <a class="dropdown-item"
- href="{{ as_url(admin.consistency) }}"
- {% if request.endpoint == 'atr_admin_consistency'
%}class="active"{% endif %}><i class="bi bi-arrow-repeat"></i> Consistency</a>
- </li>
- <li>
- <a class="dropdown-item"
- href="{{ as_url(admin.data) }}"
- {% if request.endpoint == 'atr_admin_data' %}class="active"{% endif
%}><i class="bi bi-database"></i> Browse database</a>
- </li>
- <li>
- <a class="dropdown-item"
- href="{{ as_url(admin.delete_committee_keys_get) }}"
- {% if request.endpoint == 'atr_admin_delete_committee_keys_get'
%}class="active"{% endif %}><i class="bi bi-trash"></i> Delete committee
keys</a>
- </li>
- <li>
- <a class="dropdown-item"
- href="{{ as_url(admin.delete_release_get) }}"
- {% if request.endpoint == 'atr_admin_delete_release_get'
%}class="active"{% endif %}><i class="bi bi-trash"></i> Delete release</a>
- </li>
- <li>
- <a class="dropdown-item"
- href="{{ as_url(admin.env) }}"
- {% if request.endpoint == 'atr_admin_env' %}class="active"{% endif
%}><i class="bi bi-gear"></i> Environment</a>
- </li>
- <li>
- <a class="dropdown-item"
- href="{{ as_url(admin.keys_check_get) }}"
- {% if request.endpoint == 'atr_admin_keys_check_get'
%}class="active"{% endif %}><i class="bi bi-key"></i> Keys check</a>
- </li>
- <li>
- <a class="dropdown-item"
- href="{{ as_url(admin.keys_regenerate_all_get) }}"
- {% if request.endpoint == 'atr_admin_keys_regenerate_all_get'
%}class="active"{% endif %}><i class="bi bi-key"></i> Regenerate all keys</a>
- </li>
- <li>
- <a class="dropdown-item"
- href="{{ as_url(admin.keys_update_get) }}"
- {% if request.endpoint == 'atr_admin_keys_update_get'
%}class="active"{% endif %}><i class="bi bi-key"></i> Update keys</a>
- </li>
- <li>
- <a class="dropdown-item"
- href="{{ as_url(admin.ldap_get) }}"
- {% if request.endpoint == 'atr_admin_ldap_get' %}class="active"{%
endif %}><i class="bi bi-person-plus"></i> LDAP search</a>
- </li>
- <li>
- <a class="dropdown-item"
- href="{{ as_url(admin.performance) }}"
- {% if request.endpoint == 'atr_admin_performance'
%}class="active"{% endif %}><i class="bi bi-speedometer2"></i> Page
performance</a>
- </li>
- <li>
- <a class="dropdown-item"
- href="{{ as_url(admin.projects_update_get) }}"
- {% if request.endpoint == 'atr_admin_projects_update_get'
%}class="active"{% endif %}><i class="bi bi-arrow-repeat"></i> Update
projects</a>
- </li>
- <li>
- <a class="dropdown-item"
- href="{{ as_url(admin.tasks_) }}"
- {% if request.endpoint == 'atr_admin_tasks_' %}class="active"{%
endif %}><i class="bi bi-list-task"></i> Background tasks</a>
- </li>
- <li>
- <hr class="dropdown-divider" />
- </li>
- <li>
- <a class="dropdown-item"
- href="{{ as_url(admin.tasks_recent, minutes=5) }}"><i class="bi
bi-clock-history"></i> Recent tasks</a>
- </li>
- <li>
- <a class="dropdown-item"
- href="{{ as_url(admin.toggle_view_get) }}"
- {% if request.endpoint == 'atr_admin_toggle_view_get'
%}class="active"{% endif %}><i class="bi bi-person-badge"></i> Toggle admin
view</a>
- </li>
- <li>
- <a class="dropdown-item"
- href="{{ as_url(admin.validate_) }}"
- {% if request.endpoint == 'atr_admin_validate_' %}class="active"{%
endif %}><i class="bi bi-arrow-repeat"></i> Validate</a>
- </li>
- </ul>
- </li>
-{% endif %}
-</ul>
-<ul class="navbar-nav">
- <li class="nav-item dropdown">
- <button class="nav-link dropdown-toggle btn"
- id="dropdownUser"
- type="button"
- data-bs-toggle="dropdown"
- aria-expanded="false"
- aria-controls="menuUser">
- Log
- {% if current_user %}
- out
- {% else %}
- in
- {% endif %}
- </button>
- <ul class="dropdown-menu dropdown-menu-end"
- id="menuUser"
- aria-labelledby="dropdownUser">
- <div class="user-menu">
- {% if current_user %}
- <span>{{ current_user.fullname }}</span>
- (<code>{{ current_user.uid }}</code>)
- <br />
- <a href="#"
- onclick="location.href='/auth?logout=/';"
- class="logout-link btn btn-sm btn-outline-secondary mt-2">Log
out</a>
- {% else %}
- <a href="#"
- onclick="location.href='/auth?login=' + window.location.pathname;"
- class="login-link btn btn-sm btn-secondary">Log in</a>
+ OpenAPI</a> {# djlint:on #}
+ </li>
+ <li>
+ <hr class="dropdown-divider" />
+ </li>
+ <li>
+ <a class="dropdown-item"
+ href="https://github.com/apache/tooling-docs/"
+ target="_blank"><i class="bi bi-github"></i> Tooling
Docs</a>
+ </li>
+ <li>
+ <hr class="dropdown-divider" />
+ </li>
+ <li>
+ <a class="dropdown-item"
+ href="https://github.com/apache/tooling-trusted-releases"
+ target="_blank"><i class="bi bi-github"></i> Trusted
Releases</a>
+ </li>
+ <li>
+ <a class="dropdown-item"
+ href="https://github.com/apache/tooling-releases-client"
+ target="_blank"><i class="bi bi-github"></i> Trusted
Releases Client</a>
+ </li>
+ <li>
+ <a class="dropdown-item"
+ href="https://github.com/apache/tooling-actions"
+ target="_blank"><i class="bi bi-github"></i> Trusted
Releases Actions</a>
+ </li>
+ {% endif %}
+ </ul>
+ </li>
+ {% if is_viewing_as_admin_fn(current_user.uid) %}
+ <li class="nav-item dropdown">
+ <button class="nav-link dropdown-toggle btn"
+ id="dropdownAdmin"
+ type="button"
+ data-bs-toggle="dropdown"
+ aria-expanded="false"
+ aria-controls="menuAdmin">Admin</button>
+ <ul class="dropdown-menu" id="menuAdmin"
aria-labelledby="dropdownAdmin">
+ <li>
+ <a class="dropdown-item"
+ href="{{ as_url(admin.all_releases) }}"
+ {% if request.endpoint == 'atr_admin_all_releases'
%}class="active"{% endif %}><i class="bi bi-list-ul"></i> All releases</a>
+ </li>
+ <li>
+ <a class="dropdown-item"
+ href="{{ as_url(admin.browse_as_get) }}"
+ {% if request.endpoint == 'atr_admin_browse_as_get'
%}class="active"{% endif %}><i class="bi bi-person-plus"></i> Browse as user</a>
+ </li>
+ <li>
+ <a class="dropdown-item"
+ href="{{ as_url(admin.consistency) }}"
+ {% if request.endpoint == 'atr_admin_consistency'
%}class="active"{% endif %}><i class="bi bi-arrow-repeat"></i> Consistency</a>
+ </li>
+ <li>
+ <a class="dropdown-item"
+ href="{{ as_url(admin.data) }}"
+ {% if request.endpoint == 'atr_admin_data'
%}class="active"{% endif %}><i class="bi bi-database"></i> Browse database</a>
+ </li>
+ <li>
+ <a class="dropdown-item"
+ href="{{ as_url(admin.delete_committee_keys_get) }}"
+ {% if request.endpoint ==
'atr_admin_delete_committee_keys_get' %}class="active"{% endif %}><i class="bi
bi-trash"></i> Delete committee keys</a>
+ </li>
+ <li>
+ <a class="dropdown-item"
+ href="{{ as_url(admin.delete_release_get) }}"
+ {% if request.endpoint == 'atr_admin_delete_release_get'
%}class="active"{% endif %}><i class="bi bi-trash"></i> Delete release</a>
+ </li>
+ <li>
+ <a class="dropdown-item"
+ href="{{ as_url(admin.env) }}"
+ {% if request.endpoint == 'atr_admin_env'
%}class="active"{% endif %}><i class="bi bi-gear"></i> Environment</a>
+ </li>
+ <li>
+ <a class="dropdown-item"
+ href="{{ as_url(admin.keys_check_get) }}"
+ {% if request.endpoint == 'atr_admin_keys_check_get'
%}class="active"{% endif %}><i class="bi bi-key"></i> Keys check</a>
+ </li>
+ <li>
+ <a class="dropdown-item"
+ href="{{ as_url(admin.keys_regenerate_all_get) }}"
+ {% if request.endpoint ==
'atr_admin_keys_regenerate_all_get' %}class="active"{% endif %}><i class="bi
bi-key"></i> Regenerate all keys</a>
+ </li>
+ <li>
+ <a class="dropdown-item"
+ href="{{ as_url(admin.keys_update_get) }}"
+ {% if request.endpoint == 'atr_admin_keys_update_get'
%}class="active"{% endif %}><i class="bi bi-key"></i> Update keys</a>
+ </li>
+ <li>
+ <a class="dropdown-item"
+ href="{{ as_url(admin.ldap_get) }}"
+ {% if request.endpoint == 'atr_admin_ldap_get'
%}class="active"{% endif %}><i class="bi bi-person-plus"></i> LDAP search</a>
+ </li>
+ <li>
+ <a class="dropdown-item"
+ href="{{ as_url(admin.performance) }}"
+ {% if request.endpoint == 'atr_admin_performance'
%}class="active"{% endif %}><i class="bi bi-speedometer2"></i> Page
performance</a>
+ </li>
+ <li>
+ <a class="dropdown-item"
+ href="{{ as_url(admin.projects_update_get) }}"
+ {% if request.endpoint == 'atr_admin_projects_update_get'
%}class="active"{% endif %}><i class="bi bi-arrow-repeat"></i> Update
projects</a>
+ </li>
+ <li>
+ <a class="dropdown-item"
+ href="{{ as_url(admin.tasks_) }}"
+ {% if request.endpoint == 'atr_admin_tasks_'
%}class="active"{% endif %}><i class="bi bi-list-task"></i> Background tasks</a>
+ </li>
+ <li>
+ <hr class="dropdown-divider" />
+ </li>
+ <li>
+ <a class="dropdown-item"
+ href="{{ as_url(admin.tasks_recent, minutes=5) }}"><i
class="bi bi-clock-history"></i> Recent tasks</a>
+ </li>
+ <li>
+ <a class="dropdown-item"
+ href="{{ as_url(admin.toggle_view_get) }}"
+ {% if request.endpoint == 'atr_admin_toggle_view_get'
%}class="active"{% endif %}><i class="bi bi-person-badge"></i> Toggle admin
view</a>
+ </li>
+ <li>
+ <a class="dropdown-item"
+ href="{{ as_url(admin.validate_) }}"
+ {% if request.endpoint == 'atr_admin_validate_'
%}class="active"{% endif %}><i class="bi bi-arrow-repeat"></i> Validate</a>
+ </li>
+ </ul>
+ </li>
{% endif %}
- </div>
- </ul>
- </li>
- <li class="nav-item dropdown">
- <button class="nav-link dropdown-toggle btn"
- id="dropdownASF"
- type="button"
- data-bs-toggle="dropdown"
- aria-expanded="false"
- aria-controls="menuASF">About The ASF</button>
- <ul class="dropdown-menu dropdown-menu-end"
- id="menuASF"
- aria-labelledby="dropdownASF">
- <li>
- <a class="dropdown-item" href="https://www.apache.org/">Foundation</a>
- </li>
- <li>
- <hr class="dropdown-divider" />
- </li>
- <li>
- <a class="dropdown-item"
href="https://www.apache.org/licenses/">License</a>
- </li>
- <li>
- <a class="dropdown-item"
-
href="https://www.apache.org/foundation/sponsorship.html">Sponsorship</a>
- </li>
- <li>
- <a class="dropdown-item"
- href="https://www.apache.org/foundation/thanks.html">Thanks</a>
- </li>
- <li>
- <hr class="dropdown-divider" />
- </li>
- <li>
- <a class="dropdown-item"
href="https://www.apache.org/security/">Security</a>
- </li>
- <li>
- <a class="dropdown-item"
-
href="https://privacy.apache.org/policies/privacy-policy-public.html">Privacy
Policy</a>
- </li>
- </ul>
- </li>
-</ul>
-</div>
-</div>
+ </ul>
+ <ul class="navbar-nav">
+ <li class="nav-item dropdown">
+ <button class="nav-link dropdown-toggle btn"
+ id="dropdownUser"
+ type="button"
+ data-bs-toggle="dropdown"
+ aria-expanded="false"
+ aria-controls="menuUser">
+ Log
+ {% if current_user %}
+ out
+ {% else %}
+ in
+ {% endif %}
+ </button>
+ <ul class="dropdown-menu dropdown-menu-end"
+ id="menuUser"
+ aria-labelledby="dropdownUser">
+ <div class="user-menu">
+ {% if current_user %}
+ <span>{{ current_user.fullname }}</span>
+ (<code>{{ current_user.uid }}</code>)
+ <br />
+ <a href="#"
+ onclick="location.href='/auth?logout=/';"
+ class="logout-link btn btn-sm btn-outline-secondary
mt-2">Log out</a>
+ {% else %}
+ <a href="#"
+ onclick="location.href='/auth?login=' +
window.location.pathname;"
+ class="login-link btn btn-sm btn-secondary">Log in</a>
+ {% endif %}
+ </div>
+ </ul>
+ </li>
+ <li class="nav-item dropdown">
+ <button class="nav-link dropdown-toggle btn"
+ id="dropdownASF"
+ type="button"
+ data-bs-toggle="dropdown"
+ aria-expanded="false"
+ aria-controls="menuASF">About The ASF</button>
+ <ul class="dropdown-menu dropdown-menu-end"
+ id="menuASF"
+ aria-labelledby="dropdownASF">
+ <li>
+ <a class="dropdown-item"
href="https://www.apache.org/">Foundation</a>
+ </li>
+ <li>
+ <hr class="dropdown-divider" />
+ </li>
+ <li>
+ <a class="dropdown-item"
href="https://www.apache.org/licenses/">License</a>
+ </li>
+ <li>
+ <a class="dropdown-item"
+
href="https://www.apache.org/foundation/sponsorship.html">Sponsorship</a>
+ </li>
+ <li>
+ <a class="dropdown-item"
+
href="https://www.apache.org/foundation/thanks.html">Thanks</a>
+ </li>
+ <li>
+ <hr class="dropdown-divider" />
+ </li>
+ <li>
+ <a class="dropdown-item"
href="https://www.apache.org/security/">Security</a>
+ </li>
+ <li>
+ <a class="dropdown-item"
+
href="https://privacy.apache.org/policies/privacy-policy-public.html">Privacy
Policy</a>
+ </li>
+ </ul>
+ </li>
+ </ul>
+ </div>
+ </div>
</nav>
diff --git a/atr/templates/index-committer.html
b/atr/templates/index-committer.html
index 2a5d3df..2011d4e 100644
--- a/atr/templates/index-committer.html
+++ b/atr/templates/index-committer.html
@@ -1,29 +1,27 @@
{% extends "layouts/base.html" %}
-{# djlint:off #}
{%- block title -%}Select a release ~ ATR{%- endblock title -%}
{%- block description -%}Select a release ~ ATR{%- endblock description -%}
-{# djlint:on #}
{% block stylesheets %}
{{ super() }}
<style>
- .page-card {
- min-width: 18rem;
- min-height: 105px;
- }
-
- .page-version {
- border-bottom: 1px solid #aaaaaa;
- padding-bottom: 1rem;
- }
-
- .page-logo {
- max-height: 72px;
- background-color: #ffffff;
- padding-left: 0.5rem;
- }
+ .page-card {
+ min-width: 18rem;
+ min-height: 105px;
+ }
+
+ .page-version {
+ border-bottom: 1px solid #aaaaaa;
+ padding-bottom: 1rem;
+ }
+
+ .page-logo {
+ max-height: 72px;
+ background-color: #ffffff;
+ padding-left: 0.5rem;
+ }
</style>
{% endblock stylesheets %}
diff --git a/atr/templates/index-public.html b/atr/templates/index-public.html
index fee83ce..98a03dc 100644
--- a/atr/templates/index-public.html
+++ b/atr/templates/index-public.html
@@ -1,10 +1,8 @@
{% extends "layouts/base.html" %}
-{# djlint:off #}
{%- block title -%}Apache Trusted Releases{%- endblock title -%}
{%- block description -%}Apache Trusted Releases{%- endblock description -%}
-{# djlint:on #}
{% block content %}
<h1>Apache Trusted Releases</h1>
diff --git a/atr/templates/layouts/base.html b/atr/templates/layouts/base.html
index 9d05757..5dd1f9e 100644
--- a/atr/templates/layouts/base.html
+++ b/atr/templates/layouts/base.html
@@ -17,31 +17,31 @@
href="{{ static_url('css/bootstrap-icons.min.css') }}" />
<link rel="stylesheet" href="{{ static_url('css/bootstrap.custom.css')
}}" />
<style>
- body {
- padding-top: 72px;
- }
+ body {
+ padding-top: 72px;
+ }
- .fixed-top {
- position: fixed;
- }
+ .fixed-top {
+ position: fixed;
+ }
- .asf-logo {
- height: 42px;
- margin-left: 6px;
- }
+ .asf-logo {
+ height: 42px;
+ margin-left: 6px;
+ }
- .trusted-releases {
- position: relative;
- top: -10px;
- margin-left: 10px;
- font-weight: 650 !important;
- }
+ .trusted-releases {
+ position: relative;
+ top: -10px;
+ margin-left: 10px;
+ font-weight: 650 !important;
+ }
- .navbar-adp-offset {
- position: relative;
- top: 3px;
- margin-left: 16px;
- }
+ .navbar-adp-offset {
+ position: relative;
+ top: 3px;
+ margin-left: 16px;
+ }
</style>
{% endblock stylesheets %}
{% block head_extra %}
diff --git a/atr/templates/notfound.html b/atr/templates/notfound.html
index 92425ca..8416c7f 100644
--- a/atr/templates/notfound.html
+++ b/atr/templates/notfound.html
@@ -1,10 +1,8 @@
{% extends "layouts/base.html" %}
-{# djlint:off #}
{%- block title -%}404 ~ ATR{%- endblock title -%}
{%- block description -%}An error occurred while cessing your request.{%-
endblock description -%}
-{# djlint:on #}
{% block content %}
<div>
diff --git a/atr/templates/project-select.html
b/atr/templates/project-select.html
index 5ba0c4b..0b0f7b0 100644
--- a/atr/templates/project-select.html
+++ b/atr/templates/project-select.html
@@ -1,10 +1,8 @@
{% extends "layouts/base.html" %}
-{# djlint:off #}
{%- block title -%}Select a project ~ ATR{%- endblock title -%}
{%- block description -%}Select a project ~ ATR{%- endblock description -%}
-{# djlint:on #}
{% block content %}
diff --git a/atr/templates/projects.html b/atr/templates/projects.html
index 38aeea4..442779e 100644
--- a/atr/templates/projects.html
+++ b/atr/templates/projects.html
@@ -1,10 +1,8 @@
{% extends "layouts/base.html" %}
-{# djlint:off #}
{%- block title -%}Projects ~ ATR{%- endblock title -%}
{%- block description -%}Directory of current ASF projs and their releases.{%-
endblock description -%}
-{# djlint:on #}
{% block content %}
<h1>Projects</h1>
@@ -32,148 +30,148 @@
{% set is_part = false %}
{% if current_user and project.committee %}
{% if current_user.uid in project.committee.committee_members or
- current_user.uid in project.committee.committers or
- current_user.uid in project.committee.release_managers %}
- {% set is_part = true %}
- {% endif %}
+ current_user.uid in project.committee.committers or
+ current_user.uid in project.committee.release_managers %}
+ {% set is_part = true %}
{% endif %}
- <div class="col">
- <div class="card h-100 shadow-sm atr-cursor-pointer page-project-card
{{ '' if project.status.value.lower() == 'active' else 'bg-body-secondary' }}"
- data-project-url="{{ as_url(get.projects.view, name=project.name)
}}"
- data-is-participant="{{ 'true' if is_part else 'false' }}">
- <div class="card-body">
- <div class="row g-1">
- <div class="col-sm">
- <h3 class="card-title fs-4 mb-3">{{ project.display_name
}}</h3>
- </div>
- {% if project.status.value.lower() != 'active' %}
- <div class="col-sm-2">
- <span class="badge text-bg-secondary">{{
project.status.value.lower() }}</span>
- </div>
- {% endif %}
+ {% endif %}
+ <div class="col">
+ <div class="card h-100 shadow-sm atr-cursor-pointer page-project-card {{
'' if project.status.value.lower() == 'active' else 'bg-body-secondary' }}"
+ data-project-url="{{ as_url(get.projects.view, name=project.name)
}}"
+ data-is-participant="{{ 'true' if is_part else 'false' }}">
+ <div class="card-body">
+ <div class="row g-1">
+ <div class="col-sm">
+ <h3 class="card-title fs-4 mb-3">{{ project.display_name }}</h3>
</div>
- {% if project.category %}
- <div class="row g-1">
- {% set categories = project.category.split(', ') %}
- {% for category in categories if category != "retired" %}
- <div class="col-sm-auto">
- <span class="badge text-bg-primary">{{ category }}</span>
- </div>
- {% endfor %}
- </div>
- {% endif %}
- {% if project.programming_languages %}
- <div class="row g-1">
- {% set langs = project.programming_languages.split(', ') %}
- {% for lang in langs %}
- <div class="col-sm-auto">
- <span class="badge text-bg-success">{{ lang }}</span>
- </div>
- {% endfor %}
+ {% if project.status.value.lower() != 'active' %}
+ <div class="col-sm-2">
+ <span class="badge text-bg-secondary">{{
project.status.value.lower() }}</span>
</div>
{% endif %}
+ </div>
+ {% if project.category %}
+ <div class="row g-1">
+ {% set categories = project.category.split(', ') %}
+ {% for category in categories if category != "retired" %}
+ <div class="col-sm-auto">
+ <span class="badge text-bg-primary">{{ category }}</span>
+ </div>
+ {% endfor %}
+ </div>
+ {% endif %}
+ {% if project.programming_languages %}
+ <div class="row g-1">
+ {% set langs = project.programming_languages.split(', ') %}
+ {% for lang in langs %}
+ <div class="col-sm-auto">
+ <span class="badge text-bg-success">{{ lang }}</span>
+ </div>
+ {% endfor %}
+ </div>
+ {% endif %}
{# TODO: Could add "or is_viewing_as_admin_fn(current_user.uid)" #}
{# But then the page is noisy for admins #}
- {% if project.created_by == current_user.uid %}
- <div class="mt-3">
- <form method="post"
- action="{{ as_url(post.projects.delete) }}"
- class="d-inline-block m-0"
- onsubmit="return confirm('Are you sure you want to
delete the project \'{{ project.display_name }}\'? This cannot be undone.');">
- {{ empty_form.hidden_tag() }}
+ {% if project.created_by == current_user.uid %}
+ <div class="mt-3">
+ <form method="post"
+ action="{{ as_url(post.projects.delete) }}"
+ class="d-inline-block m-0"
+ onsubmit="return confirm('Are you sure you want to delete
the project \'{{ project.display_name }}\'? This cannot be undone.');">
+ {{ empty_form.hidden_tag() }}
- <input type="hidden" name="project_name" value="{{
project.name }}" />
- <button type="submit"
- class="btn btn-sm btn-outline-danger"
- title="Delete {{ project.display_name }}">
- <i class="bi bi-trash"></i> Delete project
- </button>
- </form>
- </div>
- {% endif %}
+ <input type="hidden" name="project_name" value="{{
project.name }}" />
+ <button type="submit"
+ class="btn btn-sm btn-outline-danger"
+ title="Delete {{ project.display_name }}">
+ <i class="bi bi-trash"></i> Delete project
+ </button>
+ </form>
+ </div>
+ {% endif %}
- </div>
</div>
</div>
- {% endfor %}
- </div>
+ </div>
+{% endfor %}
+</div>
{% endblock content %}
{% block javascripts %}
{{ super() }}
<script>
- function filter() {
- const projectFilter =
document.getElementById("project-filter").value;
- const cards = document.querySelectorAll(".page-project-card");
- let visibleCount = 0;
- for (let card of cards) {
- const nameElement = card.querySelector(".card-title");
- const name = nameElement.innerHTML;
- if (!projectFilter) {
- card.parentElement.hidden = false;
- visibleCount++;
- } else {
- card.parentElement.hidden = !name.match(new
RegExp(projectFilter, 'i'));
- if (!card.parentElement.hidden) {
- visibleCount++;
- }
- }
+ function filter() {
+ const projectFilter = document.getElementById("project-filter").value;
+ const cards = document.querySelectorAll(".page-project-card");
+ let visibleCount = 0;
+ for (let card of cards) {
+ const nameElement = card.querySelector(".card-title");
+ const name = nameElement.innerHTML;
+ if (!projectFilter) {
+ card.parentElement.hidden = false;
+ visibleCount++;
+ } else {
+ card.parentElement.hidden = !name.match(new RegExp(projectFilter,
'i'));
+ if (!card.parentElement.hidden) {
+ visibleCount++;
}
- document.getElementById("project-count").textContent = visibleCount;
+ }
}
+ document.getElementById("project-count").textContent = visibleCount;
+ }
// Add event listeners
- document.getElementById("filter-button").addEventListener("click",
filter);
- document.getElementById("project-filter").addEventListener("keydown",
function(event) {
- if (event.key === "Enter") {
- filter();
- event.preventDefault();
- }
- });
+ document.getElementById("filter-button").addEventListener("click", filter);
+ document.getElementById("project-filter").addEventListener("keydown",
function(event) {
+ if (event.key === "Enter") {
+ filter();
+ event.preventDefault();
+ }
+ });
// Add click handlers for project cards
- document.querySelectorAll(".page-project-card").forEach(function(card) {
- card.addEventListener("click", function(event) {
+ document.querySelectorAll(".page-project-card").forEach(function(card) {
+ card.addEventListener("click", function(event) {
// Prevent card navigation if click is inside a form
- if (event.target.closest("form")) {
- return;
- }
- window.location.href = this.getAttribute("data-project-url");
- });
+ if (event.target.closest("form")) {
+ return;
+ }
+ window.location.href = this.getAttribute("data-project-url");
});
+ });
// Participant filter logic
- const participantButton =
document.getElementById("filter-participant-button");
- participantButton.addEventListener("click", function() {
- const showing = this.dataset.showing;
- const cards = document.querySelectorAll(".page-project-card");
- let visibleCount = 0;
+ const participantButton =
document.getElementById("filter-participant-button");
+ participantButton.addEventListener("click", function() {
+ const showing = this.dataset.showing;
+ const cards = document.querySelectorAll(".page-project-card");
+ let visibleCount = 0;
- if (showing === "all") {
+ if (showing === "all") {
// Switch to showing only participant projects
- cards.forEach(card => {
- const isParticipant = card.dataset.isParticipant === 'true';
- card.parentElement.hidden = !isParticipant;
- if (!card.parentElement.hidden) {
- visibleCount++;
- }
- });
- this.textContent = "Show all projects";
- this.dataset.showing = "participant";
- } else {
- // Switch to showing all projects
- cards.forEach(card => {
- card.parentElement.hidden = false;
- visibleCount++;
- });
- this.textContent = "Show my projects";
- this.dataset.showing = "all";
+ cards.forEach(card => {
+ const isParticipant = card.dataset.isParticipant === 'true';
+ card.parentElement.hidden = !isParticipant;
+ if (!card.parentElement.hidden) {
+ visibleCount++;
}
+ });
+ this.textContent = "Show all projects";
+ this.dataset.showing = "participant";
+ } else {
+ // Switch to showing all projects
+ cards.forEach(card => {
+ card.parentElement.hidden = false;
+ visibleCount++;
+ });
+ this.textContent = "Show my projects";
+ this.dataset.showing = "all";
+ }
// Reset text filter when toggling participant view
- document.getElementById("project-filter").value = "";
+ document.getElementById("project-filter").value = "";
// Update count
- document.getElementById("project-count").textContent = visibleCount;
- });
+ document.getElementById("project-count").textContent = visibleCount;
+ });
</script>
{% endblock javascripts %}
diff --git a/atr/templates/release-select.html
b/atr/templates/release-select.html
index 2793894..9a179fd 100644
--- a/atr/templates/release-select.html
+++ b/atr/templates/release-select.html
@@ -1,10 +1,8 @@
{% extends "layouts/base.html" %}
-{# djlint:off #}
{%- block title -%}Select a release of {{ project.display_name }} ~ ATR{%-
endblock title -%}
{%- block description -%}Select a release of {{ project.display_name }} ~
ATR{%- endblock description -%}
-{# djlint:on #}
{% block content %}
<p class="atr-breadcrumbs">
diff --git a/atr/templates/releases-finished.html
b/atr/templates/releases-finished.html
index ecf202f..c57ba4d 100644
--- a/atr/templates/releases-finished.html
+++ b/atr/templates/releases-finished.html
@@ -1,10 +1,8 @@
{% extends "layouts/base.html" %}
-{# djlint:off #}
{%- block title -%}Releases of {{ project.display_name }} ~ ATR{%- endblock
title -%}
{%- block description -%}All of the finished releases of {{
project.display_name }} ATR.{%- endblock description -%}
-{# djlint:on #}
{% block content %}
<p>
diff --git a/atr/templates/releases.html b/atr/templates/releases.html
index ec95042..4e5111f 100644
--- a/atr/templates/releases.html
+++ b/atr/templates/releases.html
@@ -1,23 +1,21 @@
{% extends "layouts/base.html" %}
-{# djlint:off #}
{%- block title -%}Releases ~ ATR{%- endblock title -%}
{%- block description -%}Review public releases.{%- endblock description -%}
-{# djlint:on #}
{% block stylesheets %}
{{ super() }}
<style>
- .page-release-meta-item::after {
- content: "•";
- margin-left: 1rem;
- color: #ccc;
- }
+ .page-release-meta-item::after {
+ content: "•";
+ margin-left: 1rem;
+ color: #ccc;
+ }
- .page-release-meta-item:last-child::after {
- content: none;
- }
+ .page-release-meta-item:last-child::after {
+ content: none;
+ }
</style>
{% endblock stylesheets %}
diff --git a/atr/templates/report-selected-path.html
b/atr/templates/report-selected-path.html
index 4bce635..89e44ed 100644
--- a/atr/templates/report-selected-path.html
+++ b/atr/templates/report-selected-path.html
@@ -1,21 +1,19 @@
{% extends "layouts/base.html" %}
-{# djlint:off #}
{%- block title -%}Report for {{ release.short_display_name }} {{
package.filename }} ~ ATR{%- endblock title -%}
{%- block description -%}Show the report for the {{ release.short_display_name
}} {{ package.filename }} candidate draft file.{%- endblock description -%}
-{# djlint:on #}
{% block stylesheets %}
{{ super() }}
<style>
- .page-member-path-hide {
- display: none !important;
- }
+ .page-member-path-hide {
+ display: none !important;
+ }
- .page-member-visible-odd {
- background-color: rgba(0, 0, 0, 0.05);
- }
+ .page-member-visible-odd {
+ background-color: rgba(0, 0, 0, 0.05);
+ }
</style>
{% endblock stylesheets %}
@@ -54,11 +52,11 @@
</div>
{% if primary_results %}
{% set status_counts = {
- "success": primary_results|selectattr("status.value", "equalto",
"success")|list|length,
- "failure": primary_results|selectattr("status.value", "equalto",
"failure")|list|length,
- "warning": primary_results|selectattr("status.value", "equalto",
"warning")|list|length,
- "exception": primary_results|selectattr("status.value", "equalto",
"exception")|list|length
- } %}
+ "success": primary_results|selectattr("status.value", "equalto",
"success")|list|length,
+ "failure": primary_results|selectattr("status.value", "equalto",
"failure")|list|length,
+ "warning": primary_results|selectattr("status.value", "equalto",
"warning")|list|length,
+ "exception": primary_results|selectattr("status.value", "equalto",
"exception")|list|length
+ } %}
{% set earliest_checked = primary_results|min(attribute="created") %}
{% set latest_checked = primary_results|max(attribute="created") %}
<p>
@@ -340,89 +338,89 @@
{% block javascripts %}
{{ super() }}
<script>
- function toggleAllDetails() {
- const details = document.querySelectorAll("details");
+ function toggleAllDetails() {
+ const details = document.querySelectorAll("details");
// Check if any are closed
- const anyClosed = Array.from(details).some(detail => !detail.open);
+ const anyClosed = Array.from(details).some(detail => !detail.open);
// If any are closed, open all
// Otherwise, close all
- details.forEach(detail => detail.open = anyClosed);
- }
+ details.forEach(detail => detail.open = anyClosed);
+ }
- function toggleStatusVisibility(type, status) {
- const btn = document.getElementById(`btn-toggle-${type}-${status}`);
- const targets =
document.querySelectorAll(`.atr-result-${type}.atr-result-status-${status}`);
- if (!targets.length) return;
- let elementsCurrentlyHidden =
targets[0].classList.contains("atr-hide");
- targets.forEach(el => {
- if (elementsCurrentlyHidden) {
- el.classList.remove("atr-hide");
- } else {
- el.classList.add("atr-hide");
- }
- });
- const bsSt = (status === "failure" || status === "exception") ?
"danger" : status;
- const cntMatch = btn.textContent.match(/\((\d+)\)/);
- if (!cntMatch) {
- console.error("Button text regex mismatch for:",
btn.textContent);
- return;
- }
- const cnt = cntMatch[0];
- const newButtonAction = elementsCurrentlyHidden ? "Hide" : "Show";
- btn.querySelector("span").textContent = newButtonAction;
- if (newButtonAction === "Hide") {
- btn.classList.remove(`btn-outline-${bsSt}`);
- btn.classList.add(`btn-${bsSt}`);
- } else {
- btn.classList.remove(`btn-${bsSt}`);
- btn.classList.add(`btn-outline-${bsSt}`);
- }
- if (type === "member") {
- updateMemberStriping();
- } else if (type === "primary") {
- updatePrimaryStriping();
- }
+ function toggleStatusVisibility(type, status) {
+ const btn = document.getElementById(`btn-toggle-${type}-${status}`);
+ const targets =
document.querySelectorAll(`.atr-result-${type}.atr-result-status-${status}`);
+ if (!targets.length) return;
+ let elementsCurrentlyHidden = targets[0].classList.contains("atr-hide");
+ targets.forEach(el => {
+ if (elementsCurrentlyHidden) {
+ el.classList.remove("atr-hide");
+ } else {
+ el.classList.add("atr-hide");
+ }
+ });
+ const bsSt = (status === "failure" || status === "exception") ? "danger"
: status;
+ const cntMatch = btn.textContent.match(/\((\d+)\)/);
+ if (!cntMatch) {
+ console.error("Button text regex mismatch for:", btn.textContent);
+ return;
}
-
- function restripeVisibleRows(rowSelector, stripeClass) {
- let visibleIdx = 0;
- document.querySelectorAll(rowSelector).forEach(row => {
- row.classList.remove(stripeClass);
- const hidden = row.classList.contains("atr-hide") ||
row.classList.contains("page-member-path-hide");
- if (!hidden) {
- if (visibleIdx % 2 === 0) row.classList.add(stripeClass);
- visibleIdx++;
- }
- });
+ const cnt = cntMatch[0];
+ const newButtonAction = elementsCurrentlyHidden ? "Hide" : "Show";
+ btn.querySelector("span").textContent = newButtonAction;
+ if (newButtonAction === "Hide") {
+ btn.classList.remove(`btn-outline-${bsSt}`);
+ btn.classList.add(`btn-${bsSt}`);
+ } else {
+ btn.classList.remove(`btn-${bsSt}`);
+ btn.classList.add(`btn-outline-${bsSt}`);
}
-
- function updatePrimaryStriping() {
- restripeVisibleRows(".atr-result-primary",
"page-member-visible-odd");
+ if (type === "member") {
+ updateMemberStriping();
+ } else if (type === "primary") {
+ updatePrimaryStriping();
}
+ }
- function updateMemberStriping() {
- restripeVisibleRows(".atr-result-member", "page-member-visible-odd");
- }
+ function restripeVisibleRows(rowSelector, stripeClass) {
+ let visibleIdx = 0;
+ document.querySelectorAll(rowSelector).forEach(row => {
+ row.classList.remove(stripeClass);
+ const hidden = row.classList.contains("atr-hide") ||
row.classList.contains("page-member-path-hide");
+ if (!hidden) {
+ if (visibleIdx % 2 === 0) row.classList.add(stripeClass);
+ visibleIdx++;
+ }
+ });
+ }
- const mpfInput = document.getElementById("member-path-filter");
- if (mpfInput) {
- mpfInput.addEventListener("input", function() {
- const filterText = this.value.toLowerCase();
- document.querySelectorAll(".atr-result-member").forEach(row => {
- const pathCell = row.cells[0];
- let hide = false;
- if (filterText) {
- if
(!pathCell.textContent.toLowerCase().includes(filterText)) {
- hide = true;
- }
- }
- row.classList.toggle("page-member-path-hide", hide);
- });
- updateMemberStriping();
- });
- }
- updatePrimaryStriping();
- updateMemberStriping();
+ function updatePrimaryStriping() {
+ restripeVisibleRows(".atr-result-primary", "page-member-visible-odd");
+ }
+
+ function updateMemberStriping() {
+ restripeVisibleRows(".atr-result-member", "page-member-visible-odd");
+ }
+
+ const mpfInput = document.getElementById("member-path-filter");
+ if (mpfInput) {
+ mpfInput.addEventListener("input", function() {
+ const filterText = this.value.toLowerCase();
+ document.querySelectorAll(".atr-result-member").forEach(row => {
+ const pathCell = row.cells[0];
+ let hide = false;
+ if (filterText) {
+ if (!pathCell.textContent.toLowerCase().includes(filterText)) {
+ hide = true;
+ }
+ }
+ row.classList.toggle("page-member-path-hide", hide);
+ });
+ updateMemberStriping();
+ });
+ }
+ updatePrimaryStriping();
+ updateMemberStriping();
</script>
{% endblock javascripts %}
diff --git a/atr/templates/resolve-tabulated.html
b/atr/templates/resolve-tabulated.html
index a998786..843d72c 100644
--- a/atr/templates/resolve-tabulated.html
+++ b/atr/templates/resolve-tabulated.html
@@ -1,10 +1,8 @@
{% extends "layouts/base.html" %}
-{# djlint:off #}
{%- block title -%}Resolve vote ~ ATR{%- endblock title -%}
{%- block description -%}Resolve vote for a release.{%- endblock description
-%}
-{# djlint:on #}
{% block content %}
<p>
diff --git a/atr/templates/tutorial.html b/atr/templates/tutorial.html
index a5a16af..7ee8ee0 100644
--- a/atr/templates/tutorial.html
+++ b/atr/templates/tutorial.html
@@ -1,20 +1,18 @@
{% extends "layouts/base.html" %}
-{# djlint:off #}
{%- block description -%}Tutorial for release managers ~ ATR{%- endblock
description -%}
{%- block title -%}Tutorial for release managers ~ ATR{%- endblock title -%}
-{# djlint:on #}
{% block stylesheets %}
{{ super() }}<style>
img {
- border: 1px < !-- djlint:on -->solid #cccccc;
- box-shadow: 0 0 1rem rgba(0, 0, 0, 0.2);
- margin: 1rem 0;
- max-width: 50%;
+ border: 1px < !-- djlint:on -->solid #cccccc;
+ box-shadow: 0 0 1rem rgba(0, 0, 0, 0.2);
+ margin: 1rem 0;
+ max-width: 50%;
}
-</style>
+ </style>
{% endblock stylesheets %}
{% block content %}
diff --git a/atr/templates/user-ssh-keys.html b/atr/templates/user-ssh-keys.html
index 95662d9..c0c4490 100644
--- a/atr/templates/user-ssh-keys.html
+++ b/atr/templates/user-ssh-keys.html
@@ -11,7 +11,7 @@
{% set key_comment = key_parts[2] if key_parts|length > 2 else 'key' %}
<p>
We have the SSH key <a href="{{ as_url(get.keys.keys, _anchor='ssh-key-' +
key.fingerprint) }}"
- title="{{ key.fingerprint }}"><code>{{- key_comment | trim -}}</code></a>
on file for you. You can also <a href="{{ as_url(get.keys.ssh_add) }}">add
another SSH key</a>.
+ title="{{ key.fingerprint }}"><code>{{- key_comment
| trim -}}</code></a> on file for you. You can also <a href="{{
as_url(get.keys.ssh_add) }}">add another SSH key</a>.
</p>
{% elif key_count > 1 %}
<p>We have the following SSH keys on file for you:</p>
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]