You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tooling.apache.org by ar...@apache.org on 2026/10/07 09:41:50 UTC
(tooling-trusted-releases) 01/02: #1717 - show matching projects on search
This is an automated email from the ASF dual-hosted git repository.
alitheg pushed a commit to branch arm
in repository https://gitbox.apache.org/repos/asf/tooling-trusted-releases.git
commit d1c9699c580cd954e56564e9f2546be3a3f0995d
Author: Alastair McFarlane <ar...@apache.org>
AuthorDate: Wed Oct 7 09:57:43 2026 +0100
#1717 - show matching projects on search
---
atr/catalog_site.py | 38 ++++++++++++++++++++++++++++-------
atr/static/js/src/card-grid.js | 24 ++++++++++++++++++++--
atr/templates/catalog_site/index.html | 17 ++++++++++++----
3 files changed, 66 insertions(+), 13 deletions(-)
diff --git a/atr/catalog_site.py b/atr/catalog_site.py
index 474bd91d..a3a3b793 100644
--- a/atr/catalog_site.py
+++ b/atr/catalog_site.py
@@ -174,11 +174,19 @@ _PROJECT_RELEASES_FILE: Final = "project_releases.json"
_PODLING_RELEASES_FILE: Final = "podling_releases.json"
+# Ordered on the name first, so a card's projects sort the way they read
+@dataclasses.dataclass(order=True)
+class _ProjectLink:
+ name: str
+ # Relative to the site root
+ target: str
+
+
@dataclasses.dataclass
class _CommitteeSummary:
release_count: int
latest_date: datetime.datetime | None
- project_names: list[str]
+ projects: list[_ProjectLink]
@dataclasses.dataclass
@@ -436,18 +444,27 @@ async def _committee_summaries(data: db.Session, committees: Sequence[sql.Commit
if (released is not None) and ((key not in latest) or (released > latest[key])):
latest[key] = released
# The search matches project names as well as committee names, so each card lists its
- # projects. The Incubator lists its podlings, which are committees rather than projects.
- names: dict[str, list[str]] = {
- committee.key: sorted(project.display_name for project in committee.projects) for committee in committees
+ # projects, ready to link straight to whichever ones a search hits. The Incubator lists
+ # its podlings, which are committees rather than projects.
+ links: dict[str, list[_ProjectLink]] = {
+ committee.key: sorted(
+ _ProjectLink(name=project.display_name, target=f"{project.key}/index.html")
+ for project in committee.projects
+ )
+ for committee in committees
}
- names[_INCUBATOR_COMMITTEE_KEY] = sorted(committee.display_name for committee in committees if committee.is_podling)
+ links[_INCUBATOR_COMMITTEE_KEY] = sorted(
+ _ProjectLink(name=committee.display_name, target=_podling_target(committee))
+ for committee in committees
+ if committee.is_podling
+ )
return {
key: _CommitteeSummary(
release_count=counts.get(key, 0),
latest_date=latest.get(key),
- project_names=names.get(key, []),
+ projects=links.get(key, []),
)
- for key in (set(counts) | set(names))
+ for key in (set(counts) | set(links))
}
@@ -538,6 +555,13 @@ def _minimal_combo(classifiers: dict[str, str], others: list[dict[str, str]]) ->
return None
+def _podling_target(podling: sql.Committee) -> str:
+ # Mirrors the Incubator page: a podling with a single project opens that project
+ if len(podling.projects) == 1:
+ return f"{podling.projects[0].key}/index.html"
+ return f"{podling.key}/index.html"
+
+
def _project_htaccess(project_key: str, versions: Sequence[api.CatalogVersion]) -> str | None:
"""Render a project's `.htaccess`, resolving `<project>@latest`, or None if there's no release.
diff --git a/atr/static/js/src/card-grid.js b/atr/static/js/src/card-grid.js
index ccd62f35..789c588f 100644
--- a/atr/static/js/src/card-grid.js
+++ b/atr/static/js/src/card-grid.js
@@ -73,9 +73,13 @@ function setupProjectToggleButtons() {
}
}
-function cardMatchesText(card, query) {
+function titleMatchesText(card, query) {
const title = card.querySelector(".card-title");
- if (title?.textContent.trim().toLowerCase().includes(query)) {
+ return title?.textContent.trim().toLowerCase().includes(query) ?? false;
+}
+
+function cardMatchesText(card, query) {
+ if (titleMatchesText(card, query)) {
return true;
}
// Catalogue cards bundle projects, so match their names too.
@@ -87,6 +91,18 @@ function cardMatchesText(card, query) {
return false;
}
+function showProjectMatches(card, query) {
+ // A search that only hits a bundled project shows that project's own link,
+ // so it can be opened directly. One that hits the card's own title shows
+ // none, or searching "commons" would list every Commons project.
+ const wanted = query && !titleMatchesText(card, query);
+ for (const match of card.querySelectorAll(".page-project-match")) {
+ const hit =
+ wanted && match.dataset.projectName.toLowerCase().includes(query);
+ match.classList.toggle("d-none", !hit);
+ }
+}
+
function updateUrl(mineOnly) {
// Write the view explicitly, so a reload can tell "chose all" apart from
// "fresh visit, use default".
@@ -153,6 +169,9 @@ function setParticipantMode(ctx, mineOnly, keepText) {
}
if (!keepText && ctx.filterInput) {
ctx.filterInput.value = "";
+ for (const card of ctx.cards) {
+ showProjectMatches(card, "");
+ }
}
setCount(ctx, visible);
}
@@ -168,6 +187,7 @@ function filterByText(ctx) {
const show =
cardEligible(ctx, card) && (!query || cardMatchesText(card, query));
card.parentElement.hidden = !show;
+ showProjectMatches(card, query);
if (show) {
visible++;
}
diff --git a/atr/templates/catalog_site/index.html b/atr/templates/catalog_site/index.html
index 4b254aa7..43b16b5b 100644
--- a/atr/templates/catalog_site/index.html
+++ b/atr/templates/catalog_site/index.html
@@ -45,10 +45,19 @@
{{ summary.release_count }} {{ "release" if summary.release_count == 1 else "releases" }}
{%- if summary.latest_date %} · latest {{ summary.latest_date.strftime("%Y-%m-%d") }}{% endif %}
</p>
- {# The projects ride along hidden so a search matches on their names too #}
- {% for name in summary.project_names %}
- <span class="d-none" data-project-name="{{ name }}"></span>
- {% endfor %}
+ {# The projects ride along hidden so a search matches on their names too. A
+ project the search hits shows its own link, sitting above the card's stretched
+ link, so it opens the project rather than its whole committee #}
+ {% if summary.projects %}
+ <ul class="list-unstyled small mb-0">
+ {% for project in summary.projects %}
+ <li class="mt-1 d-none page-project-match"
+ data-project-name="{{ project.name }}">
+ <a href="{{ root }}{{ project.target }}" class="position-relative z-2">{{ project.name }} →</a>
+ </li>
+ {% endfor %}
+ </ul>
+ {% endif %}
{% endif %}
</div>
<div class="col-5 col-lg-4 text-center">
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@tooling.apache.org
For additional commands, e-mail: commits-help@tooling.apache.org