This is an automated email from the ASF dual-hosted git repository.
sbp pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tooling-trusted-release.git
The following commit(s) were added to refs/heads/main by this push:
new 8cfcd78 Improve the navigation of distribution pages
8cfcd78 is described below
commit 8cfcd789ce00e1c8e12d15abbcf390edae23aa2f
Author: Sean B. Palmer <[email protected]>
AuthorDate: Thu Aug 7 19:52:33 2025 +0100
Improve the navigation of distribution pages
---
atr/htm.py | 14 +++++++++-
atr/routes/distribution.py | 64 +++++++++++++++++++++++++++++++++++++---------
2 files changed, 65 insertions(+), 13 deletions(-)
diff --git a/atr/htm.py b/atr/htm.py
index 6fece29..c4cddaa 100644
--- a/atr/htm.py
+++ b/atr/htm.py
@@ -70,7 +70,11 @@ class Block:
def append(self, element: htpy.Element) -> None:
self.elements.append(element)
- def collect(self) -> htpy.Element:
+ def collect(self, separator: str | None = None) -> htpy.Element:
+ if separator is not None:
+ separated: list[htpy.Element | str] = [separator] * (2 *
len(self.elements) - 1)
+ separated[::2] = self.elements
+ self.elements = separated
if self.element is None:
return htpy.div[*self.elements]
return self.element[*self.elements]
@@ -111,6 +115,14 @@ class Block:
def pre(self) -> BlockElementCallable:
return BlockElementCallable(self, htpy.pre)
+ @property
+ def span(self) -> BlockElementCallable:
+ return BlockElementCallable(self, htpy.span)
+
+ @property
+ def strong(self) -> BlockElementCallable:
+ return BlockElementCallable(self, htpy.strong)
+
@property
def summary(self) -> BlockElementCallable:
return BlockElementCallable(self, htpy.summary)
diff --git a/atr/routes/distribution.py b/atr/routes/distribution.py
index acf6a21..c3988eb 100644
--- a/atr/routes/distribution.py
+++ b/atr/routes/distribution.py
@@ -20,7 +20,7 @@ from __future__ import annotations
import dataclasses
import datetime
import json
-from typing import TYPE_CHECKING
+from typing import TYPE_CHECKING, Literal
import aiohttp
import htpy
@@ -43,6 +43,8 @@ import atr.util as util
if TYPE_CHECKING:
import werkzeug.wrappers.response as response
+type Phase = Literal["COMPOSE", "VOTE", "FINISH"]
+
class ArtifactHubAvailableVersion(schema.Lax):
ts: int
@@ -200,6 +202,9 @@ async def list_get(session: routes.CommitterSession,
project: str, version: str)
).all()
block = htm.Block()
+ back_url = util.as_url(finish.selected, project_name=project,
version_name=version)
+ _nav(block, back_url, back_anchor=f"Finish {project} {version}",
phase="FINISH")
+
# Distribution list for project-version
block.h1["Distribution list for ", htpy.em[f"{project}-{version}"]]
if not distributions:
@@ -211,6 +216,13 @@ async def list_get(session: routes.CommitterSession,
project: str, version: str)
)
block.p["Here are all of the distributions recorded for this release."]
+ ## Actions
+ block.p[
+ "You can also ",
+ htpy.a(href=util.as_url(record, project=project,
version=version))["record a distribution"],
+ ".",
+ ]
+
## Distributions
block.h2["Distributions"]
for distribution in distributions:
@@ -245,12 +257,6 @@ async def list_get(session: routes.CommitterSession,
project: str, version: str)
)
block.append(htpy.div(".mb-3")[delete_form_element])
- ## Actions
- block.h2["Actions"]
- block.p[htpy.a(href=util.as_url(record, project=project,
version=version))["Record a distribution"]]
- block.p[
- htpy.a(href=util.as_url(finish.selected, project_name=project,
version_name=version))["Return to release page"]
- ]
title = f"Distribution list for {project} {version}"
return await template.blank(title, content=block.collect())
@@ -287,6 +293,9 @@ async def _distribute_page(fpv: FormProjectVersion, *,
extra_content: htpy.Eleme
# Render the explanation and form
block = htm.Block()
+ back_url = util.as_url(finish.selected, project_name=fpv.project,
version_name=fpv.version)
+ _nav(block, back_url, back_anchor=f"Finish {fpv.project} {fpv.version}",
phase="FINISH")
+
# Record a manual distribution
block.h1["Record a manual distribution"]
if extra_content:
@@ -298,14 +307,13 @@ async def _distribute_page(fpv: FormProjectVersion, *,
extra_content: htpy.Eleme
htpy.span(".atr-phase-three.atr-phase-label")["FINISH"],
" phase using the form below.",
]
- block.append(forms.render_columns(fpv.form, action=quart.request.path,
descriptions=True))
block.p[
- "Or view the ",
- htpy.a(href=util.as_url(list_get, project=fpv.project,
version=fpv.version))["distribution list"],
- ", or return to the ",
- htpy.a(href=util.as_url(finish.selected, project_name=fpv.project,
version_name=fpv.version))["release page"],
+ "You can also ",
+ htpy.a(href=util.as_url(list_get, project=fpv.project,
version=fpv.version))["view the distribution list"],
".",
]
+ block.append(forms.render_columns(fpv.form, action=quart.request.path,
descriptions=True))
+
# Render the page
return await template.blank("Record a manual distribution",
content=block.collect())
@@ -436,6 +444,38 @@ def _distribute_post_table(block: htm.Block, dd:
DistributeData) -> None:
block.table(".table.table-striped.table-bordered")[tbody]
+# TODO: Move this to an appropriate module
+def _nav(container: htm.Block, back_url: str, back_anchor: str, phase: Phase)
-> None:
+ classes = ".d-flex.justify-content-between.align-items-center"
+ block = htm.Block(htpy.p(classes))
+ block.a(".atr-back-link", href=back_url)[f"← Back to {back_anchor}"]
+ span = htm.Block(htpy.span)
+
+ def _phase(actual: Phase, expected: Phase) -> None:
+ nonlocal span
+ match expected:
+ case "COMPOSE":
+ symbol = "①"
+ case "VOTE":
+ symbol = "②"
+ case "FINISH":
+ symbol = "③"
+ if actual == expected:
+ span.strong(f".atr-phase-{actual}.atr-phase-symbol")[symbol]
+ span.span(f".atr-phase-{actual}.atr-phase-label")[actual]
+ else:
+ span.span(".atr-phase-symbol-other")[symbol]
+
+ _phase(phase, "COMPOSE")
+ span.span(".atr-phase-arrow")["→"]
+ _phase(phase, "VOTE")
+ span.span(".atr-phase-arrow")["→"]
+ _phase(phase, "FINISH")
+
+ block.append(span.collect(separator=" "))
+ container.append(block.collect())
+
+
def _platform_upload_date( # noqa: C901
platform: sql.DistributionPlatform,
data: basic.JSON,
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]