Skip to content

Commit f578f92

Browse files
committed
Update the global search page with all the fancy filters
The global search page did not allow filtering by any of the things that other pages allowed. This adds that filtering and sorting, as well as a bunch of additional columns. It doesn't show CI status and stats for now.
1 parent c55a507 commit f578f92

File tree

3 files changed

+182
-24
lines changed

3 files changed

+182
-24
lines changed

pgcommitfest/commitfest/templates/patch.html

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,9 @@
4444
{%endif%}
4545
{%if cfbot_branch %}
4646
<button class="btn btn-secondary" title="This adds the following to your clipboard (needs to be run in an existing git repo):
47-
git remote add commitfest https://github.com/postgresql-cfbot/postgresql.git
48-
git fetch commitfest cf/{{patch.id}}
49-
git checkout commitfest/cf/{{patch.id}}" onclick="addGitCheckoutToClipboard({{patch.id}})">Copy git checkout commands</button>
47+
git remote add commitfest https://github.com/postgresql-cfbot/postgresql.git
48+
git fetch commitfest cf/{{patch.id}}
49+
git checkout commitfest/cf/{{patch.id}}" onclick="addGitCheckoutToClipboard({{patch.id}})">Copy git checkout commands</button>
5050
{%endif%}
5151
</a>
5252
</td>

pgcommitfest/commitfest/templates/patchsearch.html

Lines changed: 99 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,34 +2,119 @@
22
{%load commitfest %}
33
{%block contents%}
44

5-
<form method="GET" action="/search/" class="d-flex gap-2" style="margin-bottom: 10px">
6-
<div class="form-group">
7-
<input type="text" class="form-control" id="searchterm" name="searchterm" placeholder="Global search">
5+
<!-- Search term input -->
6+
<form method="GET" action="/search/" class="d-flex gap-2 mb-3">
7+
<div class="form-group flex-grow-1">
8+
<input type="text" class="form-control" id="searchterm" name="searchterm" value="{{searchterm}}" placeholder="Email Message-ID or keywords" required>
89
</div>
9-
<button type="submit" class="btn btn-secondary">Search</button>
10+
<button type="submit" class="btn btn-secondary">
11+
<i class="bi bi-search"></i> Search
12+
</button>
1013
</form>
1114

15+
<!-- Filter form (same as other pages) -->
16+
<div id="collapseFilters" class="collapse show">
17+
<form id="filterform" method="GET" action="/search/" style="margin-bottom: 0px">
18+
<input type="hidden" name="searchterm" value="{{searchterm}}">
19+
<table class="table" style="margin-bottom: 0px">
20+
<thead>
21+
<tr>
22+
{%for f in form%}
23+
{%if not f.is_hidden%}
24+
<td>{{f.label}}</td>
25+
{%else%}
26+
<td></td>
27+
{%endif%}
28+
{%endfor%}
29+
<td></td>
30+
</tr>
31+
</thead>
32+
<tbody>
33+
<tr>
34+
{%for f in form%}
35+
<td>
36+
{%if not f.name in form.selectize_fields%}{{f|field_class:"form-control"}}{%else%}{{f}}{%endif%}
37+
</td>
38+
{%endfor%}
39+
<td>
40+
<input type="submit" class="btn btn-secondary" value="Filter">
41+
<a class="btn btn-secondary" href="/search/?searchterm={{searchterm}}">Clear</a>
42+
</td>
43+
</tr>
44+
</tbody>
45+
</table>
46+
</form>
47+
</div>
48+
49+
{% if patches %}
50+
<p class="text-muted">Found {{patches|length}} patch{% if patches|length != 1 %}es{% endif %} matching "{{searchterm}}"</p>
51+
{% endif %}
52+
1253
<table class="table table-striped table-bordered table-hover">
1354
<thead>
1455
<tr>
15-
<th>Patch</th>
56+
<th><a href="#" style="color:#333333;" onclick="return sortpatches(5);">Patch</a>{%if sortkey == 5%}<div style="float:right;"><i class="bi bi-sort-alpha-down"></i></div>{%elif sortkey == -5%}<div style="float:right;"><i class="bi bi-sort-alpha-up"></i></div>{%endif%}</th>
57+
<th><a href="#" style="color:#333333;" onclick="return sortpatches(4);">ID</a>{%if sortkey == 4%}<div style="float:right;"><i class="bi bi-sort-numeric-down"></i></div>{%elif sortkey == -4%}<div style="float:right;"><i class="bi bi-sort-numeric-up"></i></div>{%endif%}</th>
58+
<th>
59+
<a href="#" style="color:#333333;" onclick="return sortpatches(8);">CF</a>
60+
<i class="bi bi-question-circle text-muted" style="font-size: 0.8em; margin-left: 3px;" data-bs-toggle="tooltip" data-bs-placement="top" data-bs-html="true" title="Color coding:<br>Green = In Progress<br>Blue = Open<br>Red = Closed"></i>
61+
{%if sortkey == 8%}<div style="float:right;"><i class="bi bi-sort-numeric-down"></i></div>{%elif sortkey == -8%}<div style="float:right;"><i class="bi bi-sort-numeric-up"></i></div>{%endif%}
62+
</th>
1663
<th>Status</th>
64+
<th>Tags</th>
65+
<th>Ver</th>
1766
<th>Author</th>
67+
<th>Reviewers</th>
68+
<th>Committer</th>
69+
<th><a href="#" style="color:#333333;" onclick="return sortpatches(3);">Num cfs</a>{%if sortkey == 3%}<div style="float:right;"><i class="bi bi-sort-numeric-down-alt"></i></div>{%elif sortkey == -3%}<div style="float:right;"><i class="bi bi-sort-numeric-up-alt"></i></div>{%endif%}</th>
70+
<th><a href="#" style="color:#333333;" onclick="return sortpatches(2);">Latest mail</a>{%if sortkey == 2%}<div style="float:right;"><i class="bi bi-sort-down"></i></div>{%elif sortkey == -2%}<div style="float:right;"><i class="bi bi-sort-up"></i></div>{%endif%}</th>
1871
</tr>
1972
</thead>
2073
<tbody>
2174
{%for p in patches %}
22-
{%with p.patchoncommitfest_set.all as cfs %}
23-
<tr>
24-
<td>{%with cfs|first as firstcf%}<a href="/{{firstcf.commitfest_id}}/{{p.id}}/">{{p}}</a>{%endwith%}</td>
25-
<td>{%for c in cfs %}
26-
<div style="margin-bottom: 3px;">{{c.commitfest}}: <span class="badge bg-secondary">{{c.statusstring}}</span></div>
27-
{%endfor%}</td>
28-
<td>{{p.authors_string|default:''}}</td>
29-
</tr>
30-
{%endwith%}
75+
<tr>
76+
<td><a href="/patch/{{p.id}}/">{{p.name}}</a></td>
77+
<td>{{p.id}}</td>
78+
<td>
79+
{%with p.patchoncommitfest_set.all|first as poc%}
80+
{%if poc%}<a href="/{{poc.commitfest.id}}/"><span class="badge bg-{{poc.commitfest.status|commitfeststatuslabel}}" title="{{poc.commitfest.status|commitfeststatusstring}}">{{poc.commitfest.name}}</span></a>{%endif%}
81+
{%endwith%}
82+
</td>
83+
<td>
84+
{%with p.patchoncommitfest_set.all|first as poc%}
85+
{%if poc%}<span class="badge bg-{{poc.status|patchstatuslabel}}">{{poc.status|patchstatusstring}}</span>{%endif%}
86+
{%endwith%}
87+
</td>
88+
<td style="width: min-content;">
89+
{%for tag in p.tags.all%}
90+
<a href="?searchterm={{searchterm}}&tag={{tag.id}}">
91+
<span class="badge" style="background-color: {{tag.color}};" title="{{tag.description}}">{{tag.name}}</span>
92+
</a>
93+
{%endfor%}
94+
</td>
95+
<td>{%if p.targetversion%}<span class="badge bg-secondary">{{p.targetversion}}</span>{%endif%}</td>
96+
<td>
97+
{% for author in p.authors.all %}
98+
{{author.get_full_name|default:author.username}}{% if not forloop.last %}, {% endif %}
99+
{% endfor %}
100+
</td>
101+
<td>
102+
{% for reviewer in p.reviewers.all %}
103+
{{reviewer.get_full_name|default:reviewer.username}}{% if not forloop.last %}, {% endif %}
104+
{% endfor %}
105+
</td>
106+
<td>{% if p.committer %}{{p.committer.fullname}}{% endif %}</td>
107+
<td>{{p.patchoncommitfest_set.count}}</td>
108+
<td style="white-space: nowrap;" title="{{p.created}}">
109+
{%if userprofile.show_relative_timestamps %}{% cfwhen p.created %}{%else %}{{p.created|date:"Y-m-d"}}<br/>{{p.created|date:"H:i"}}{%endif%}
110+
</td>
111+
</tr>
31112
{%endfor%}
32113
</tbody>
33114
</table>
34115

35116
{%endblock%}
117+
118+
{%block morescript%}
119+
{%include "selectize_js.html" %}
120+
{%endblock%}

pgcommitfest/commitfest/views.py

Lines changed: 80 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
from django.contrib.auth.decorators import login_required
44
from django.contrib.auth.models import User
55
from django.db import connection, transaction
6-
from django.db.models import Q
6+
from django.db.models import Count, Q
77
from django.http import (
88
Http404,
99
HttpResponse,
@@ -692,25 +692,98 @@ def global_search(request):
692692
patches = patches_by_messageid(cleaned_id)
693693

694694
if not patches:
695-
patches = (
696-
Patch.objects.select_related()
697-
.filter(name__icontains=searchterm)
698-
.order_by(
699-
"created",
695+
patches_query = (
696+
Patch.objects.select_related("targetversion", "committer")
697+
.prefetch_related(
698+
"authors",
699+
"reviewers",
700+
"tags",
701+
"patchoncommitfest_set__commitfest",
702+
"mailthread_set",
700703
)
701-
.all()
704+
.select_related("cfbot_branch")
705+
.filter(name__icontains=searchterm)
702706
)
703707

708+
# Apply filters using the same logic as patchlist
709+
if request.GET.get("status", "-1") != "-1":
710+
try:
711+
status = int(request.GET["status"])
712+
patches_query = patches_query.filter(
713+
patchoncommitfest__status=status
714+
).distinct()
715+
except ValueError:
716+
pass
717+
718+
if request.GET.get("targetversion", "-1") != "-1":
719+
if request.GET["targetversion"] == "-2":
720+
patches_query = patches_query.filter(targetversion_id__isnull=True)
721+
else:
722+
try:
723+
ver_id = int(request.GET["targetversion"])
724+
patches_query = patches_query.filter(targetversion_id=ver_id)
725+
except ValueError:
726+
pass
727+
728+
if request.GET.getlist("tag"):
729+
try:
730+
tag_ids = [int(t) for t in request.GET.getlist("tag")]
731+
for tag_id in tag_ids:
732+
patches_query = patches_query.filter(tags__id=tag_id)
733+
patches_query = patches_query.distinct()
734+
except ValueError:
735+
pass
736+
737+
# Apply sorting based on sortkey parameter (adapted for Django ORM)
738+
sortkey = request.GET.get("sortkey", "1")
739+
if sortkey == "2": # Latest mail
740+
patches_query = patches_query.order_by("-modified") # Use modified as proxy
741+
elif sortkey == "-2":
742+
patches_query = patches_query.order_by("modified")
743+
elif sortkey == "3": # Num cfs
744+
patches_query = patches_query.annotate(
745+
num_cfs=Count("patchoncommitfest")
746+
).order_by("-num_cfs")
747+
elif sortkey == "-3":
748+
patches_query = patches_query.annotate(
749+
num_cfs=Count("patchoncommitfest")
750+
).order_by("num_cfs")
751+
elif sortkey == "4": # ID
752+
patches_query = patches_query.order_by("id")
753+
elif sortkey == "-4":
754+
patches_query = patches_query.order_by("-id")
755+
elif sortkey == "5": # Patch name
756+
patches_query = patches_query.order_by("name")
757+
elif sortkey == "-5":
758+
patches_query = patches_query.order_by("-name")
759+
elif sortkey == "8": # CF
760+
patches_query = patches_query.order_by("patchoncommitfest__commitfest__id")
761+
elif sortkey == "-8":
762+
patches_query = patches_query.order_by("-patchoncommitfest__commitfest__id")
763+
else: # Default: Created (sortkey 1)
764+
patches_query = patches_query.order_by("created")
765+
766+
patches = patches_query.all()
767+
704768
if len(patches) == 1:
705769
patch = patches[0]
706770
return HttpResponseRedirect(f"/patch/{patch.id}/")
707771

772+
# Use the existing filter form
773+
form = CommitFestFilterForm(request.GET)
774+
708775
return render(
709776
request,
710777
"patchsearch.html",
711778
{
712779
"patches": patches,
713780
"title": "Patch search results",
781+
"searchterm": searchterm,
782+
"form": form,
783+
"cf": None, # No specific commitfest context
784+
"sortkey": int(request.GET.get("sortkey") or "1"),
785+
"tags_data": get_tags_data(),
786+
"all_tags": {t.id: t for t in Tag.objects.all()},
714787
},
715788
)
716789

0 commit comments

Comments
 (0)