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 4605c0e New top nav menus (#393)
4605c0e is described below
commit 4605c0e001c8327d102899153d6ffd1a12a326e7
Author: Dave Fisher <[email protected]>
AuthorDate: Mon Dec 8 12:28:50 2025 -0800
New top nav menus (#393)
* New top nav menus
* Hamburger drop down
* Responsive point for top nav hamburger
* Cleanup head data whitespace #372
* Revert "Cleanup head data whitespace #372"
This reverts commit ebc396f1ee60aacb0ea86a4c4f43717df36cc0dd.
* Proper jinja block use
* Recheck playwright error
* Test without sidebar
* Click topnav button
* Revert "Recheck playwright error"
This reverts commit 67d50f1e6b83b23ce05e64b3f5b96e824c474694.
* Revert "Test without sidebar"
This reverts commit 9cd008403b4daee8fb3accf62356acf23bff9cb1.
* Revert "Click topnav button"
This reverts commit 22b05f769b02994e6e00d88514922966ad913e25.
* Adjust some menu titles
---
atr/static/css/atr.css | 100 +++++++++-
atr/templates/includes/sidebar.html | 11 --
atr/templates/includes/topnav.html | 369 ++++++++++++++++++++++++++++++++++++
atr/templates/layouts/base.html | 40 +++-
4 files changed, 499 insertions(+), 21 deletions(-)
diff --git a/atr/static/css/atr.css b/atr/static/css/atr.css
index 67c673d..67486bc 100644
--- a/atr/static/css/atr.css
+++ b/atr/static/css/atr.css
@@ -37,6 +37,59 @@ body {
font-weight: 425;
}
+.bg-info-light {
+ background-color: #e3f7fc !important;
+}
+
+.dropdown-menu {
+ width: 250px;
+ max-height: 80vh;
+ overflow: hidden auto; /* prevents sideways scrollbars */
+ scrollbar-width: thin; /* Firefox */
+}
+
+.dropdown-menu::-webkit-scrollbar {
+ width: 8px; /* Chrome/Edge */
+}
+
+html {
+ scroll-padding-top: 80px;
+}
+
+.fixed-top {
+ position: fixed;
+ top: 0;
+ right: 0;
+ left: 0;
+ z-index:1030
+}
+
+.user-menu {
+ text-align: center;
+}
+
+.navbar-ribbon {
+ position: relative;
+}
+
+.navbar-ribbon::after {
+ content: "";
+ position: absolute;
+ left: 0;
+ bottom: 0;
+ width: 100%;
+ height: 8px;
+ background: linear-gradient(
+ 90deg,
+ #282661 0%,
+ #662f8f 20%,
+ #9e2165 40%,
+ #cb2138 60%,
+ #ea7826 80%,
+ #f7ae18 100%
+ );
+}
+
footer {
padding: 1rem;
background: #eeeeee;
@@ -59,13 +112,13 @@ h1 {
h2 {
border-bottom: 1px solid #d1d2d3;
padding-bottom: 0.5rem;
- margin-top: 2.5rem;
+ margin-top: 1.5rem;
margin-bottom: 1.5rem;
}
h3 {
font-size: 1.3333rem;
- margin-top: 1.5rem;
+ margin-top: .5rem;
font-weight: 525 !important;
}
@@ -266,6 +319,7 @@ span.warning {
.content {
flex: 1;
display: flex;
+ margin-left: 250px;
}
.main-container {
@@ -292,8 +346,15 @@ aside.sidebar nav a:hover {
}
.sidebar {
+ position: fixed;
+ left: 0;
+ top: 72px;
+ bottom: 0;
+ height: calc(100vh - 72px); /* ensures the sidebar fills the space below
the top bar */
+ overflow-y: auto; /* enables vertical scrolling */
+ z-index: 101;
width: 250px;
- background-color: #f6f7f8;
+ background-color: #e3f7fc !important;
border-right: 1px solid #d1d2d3;
padding: 1rem;
}
@@ -334,6 +395,7 @@ aside.sidebar nav a:hover {
border: none;
cursor: pointer;
padding: 0;
+ padding-top: 20px;
z-index: 100;
}
@@ -350,22 +412,44 @@ aside.sidebar nav a:hover {
display: none;
}
+
+@media (width <= 990px) {
+ .dropdown-menu {
+ max-height: 40vh;
+ }
+}
+
@media (width <= 768px) {
.hamburger {
display: block;
position: fixed;
- top: 20px;
+ top: 72px;
padding-left: 2rem;
transition: 0.3s;
}
+ .hamburger::before {
+ content: "";
+ position: absolute;
+ width: 26px; /* size of the square */
+ height: 32px;
+ bottom: 0; /* anchor to bottom */
+ right: 0; /* anchor to right */
+ background: #e3f7fc !important;
+ border-radius: 4px; /* rounded square */
+ box-shadow: 0 2px 2px rgb(0 0 0 / 20%);
+ z-index: -1; /* places it behind the icon */
+ }
+
.sidebar {
position: fixed;
left: -250px;
- top: 20px;
+ top: 72px;
bottom: 0;
+ height: calc(100vh - 72px); /* ensures the sidebar fills the space
below the top bar */
+ overflow-y: auto; /* enables vertical scrolling */
transition: 0.3s;
- z-index: 99;
+ z-index: 101;
}
/* Show sidebar when checkbox is checked */
@@ -394,6 +478,10 @@ aside.sidebar nav a:hover {
margin-left: 0;
padding-top: 4rem;
}
+
+ .content {
+ margin-left: 0;
+ }
}
/* Flash Messages */
diff --git a/atr/templates/includes/sidebar.html
b/atr/templates/includes/sidebar.html
index 1bd3fae..aac14b1 100644
--- a/atr/templates/includes/sidebar.html
+++ b/atr/templates/includes/sidebar.html
@@ -1,15 +1,4 @@
<aside class="sidebar">
- <div class="sidebar-header">
- <a href="{{ as_url(get.root.index) }}" class="site-title">
- <h1>
- <span class="apache">A<span class="rest">pache</span></span>
- <br />
- <span class="trusted">T<span class="rest">rusted</span></span>
- <br />
- <span class="release">R<span class="rest">eleases</span></span>
- </h1>
- </a>
- </div>
<div class="user-section">
{% if current_user %}
<div>
diff --git a/atr/templates/includes/topnav.html
b/atr/templates/includes/topnav.html
new file mode 100644
index 0000000..67269a9
--- /dev/null
+++ b/atr/templates/includes/topnav.html
@@ -0,0 +1,369 @@
+<!-- nav bar -->
+<nav class="navbar navbar-expand-lg navbar-light bg-info-light fixed-top
navbar-ribbon"
+ aria-label="Fifth navbar example">
+ <div class="container-fluid">
+ <a class="navbar-brand" href="{{ as_url(get.root.index) }}">
+ <img src="https://apache.org/img/asf_logo.png"
+ alt="The Apache Software Foundation"
+ class="asf-logo" />
+ <span class="trusted-releases">Trusted Releases</span>
+ </a>
+ <button class="navbar-toggler"
+ type="button"
+ data-bs-toggle="collapse"
+ data-bs-target="#navbarADP"
+ aria-controls="navbarADP"
+ aria-expanded="false"
+ aria-label="Toggle navigation">
+ <span class="navbar-toggler-icon"></span>
+ </button>
+ <div class="collapse navbar-collapse navbar-adp-offset" id="navbarADP">
+ <ul class="navbar-nav me-auto">
+ {% if current_user %}
+ <li class="nav-item dropdown">
+ <button class="nav-link dropdown-toggle btn"
+ id="dropdownCandidates"
+ type="button"
+ data-bs-toggle="dropdown"
+ aria-expanded="false"
+ aria-controls="menuCandidates">Draft</button>
+ <ul class="dropdown-menu"
+ 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>
+ </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 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>
+ {# 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>
+<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>
+ {# 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>
+ {% 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/layouts/base.html b/atr/templates/layouts/base.html
index 1644b4f..476b78f 100644
--- a/atr/templates/layouts/base.html
+++ b/atr/templates/layouts/base.html
@@ -5,7 +5,10 @@
<meta name="viewport" content="width=device-width,initial-scale=1.0" />
<meta name="description"
content="{%- block description -%}{%- endblock description -%}" />
- <title>{%- block title -%}{%- endblock title -%}</title>
+ <title>
+ {% block title %}
+ {% endblock title %}
+ </title>
<link rel="icon"
type="image/x-icon"
@@ -16,13 +19,42 @@
<link rel="stylesheet"
href="{{ static_url('css/bootstrap-icons.min.css') }}" />
<link rel="stylesheet" href="{{ static_url('css/bootstrap.custom.css')
}}" />
+ <style>
+ body {
+ padding-top: 72px;
+ }
+
+ .fixed-top {
+ position: fixed;
+ }
+
+ .asf-logo {
+ height: 42px;
+ margin-left: 6px;
+ }
+
+ .trusted-releases {
+ position: relative;
+ top: -10px;
+ margin-left: 10px;
+ font-weight: 650 !important;
+ }
+
+ .navbar-adp-offset {
+ position: relative;
+ top: 3px;
+ margin-left: 16px;
+ }
+ </style>
{% endblock stylesheets %}
{% block head_extra %}
{% endblock head_extra %}
</head>
<body class="{%- block body_class -%}{%- endblock body_class -%}">
- <div class="wrapper">
- <div class="ribbon"></div>
+
+ {% include "includes/topnav.html" %}
+
+ <main class="wrapper">
<div class="content">
<input type="checkbox" id="nav-toggle" class="nav-toggle" />
<label for="nav-toggle" class="hamburger" aria-label="Menu">
@@ -50,7 +82,7 @@
</div>
</div>
- </div>
+ </main>
{% block javascripts %}
<script src="{{ static_url('js/bootstrap.bundle.min.js') }}"></script>
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]