Skip to content

Commit 0855cfc

Browse files
JelteFclaude
andcommitted
Complete Bootstrap 5 upgrade with navigation and UX improvements
This commit completes the Bootstrap 5.3.7 upgrade with significant navigation and user experience improvements: **Bootstrap 5 Migration:** - Updated JavaScript APIs: modal() → new bootstrap.Modal() - Fixed modal header structure with proper title positioning - Updated button classes: btn-default → btn-outline-secondary - Fixed form submit buttons to use btn-primary styling **Navigation System:** - Replaced basic menu with full-width dark navbar - Added active state highlighting for current pages - Integrated search functionality in header - Added GitHub contribution button with proper icon styling - Created "More" dropdown for secondary navigation items - Added conditional "New Patch" link when CF is available **Homepage Redesign:** - Merged dashboard functionality into homepage for logged-in users - Added experience-based help text for new users (30+ days) - Removed separate /me/ route and template - Added login prompt for non-authenticated users - Integrated complete patch listing with filtering **Typography & Consistency:** - Updated all date ranges to use en dash (–) instead of hyphen (-) - Added CommitFest dates to breadcrumbs on new patch page - Fixed modal close button positioning and sizing **Context & Configuration:** - Added global context processor for navigation state - Added CommitFest.get_current() method for nav logic - Updated URL patterns and view logic Closes #74 - "New Patch" button now visible in navigation Closes #19 - GitHub contribution button added to header Improves overall UX with modern Bootstrap 5 components and better information architecture. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
1 parent 4c465f6 commit 0855cfc

File tree

13 files changed

+298
-253
lines changed

13 files changed

+298
-253
lines changed

media/commitfest/css/commitfest.css

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,3 +141,8 @@ a .badge {
141141
a:hover .badge {
142142
text-decoration: none !important;
143143
}
144+
145+
/* Make GitHub icon white in dark navbar */
146+
.navbar-dark .github-logo {
147+
filter: brightness(0) invert(1);
148+
}

media/commitfest/js/commitfest.js

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,10 @@ function browseThreads(attachfunc, closefunc) {
5252
$("#attachModal").on("hidden.bs.modal", (e) => {
5353
if (closefunc) closefunc();
5454
});
55-
$("#attachModal").modal();
55+
const attachModal = new bootstrap.Modal(
56+
document.getElementById("attachModal"),
57+
);
58+
attachModal.show();
5659
findLatestThreads();
5760

5861
$("#doAttachThreadButton").unbind("click");
@@ -74,7 +77,10 @@ function browseThreads(attachfunc, closefunc) {
7477
$("#attachThreadSearchButton").addClass("disabled");
7578
$("#attachThreadButton").addClass("disabled");
7679
if (attachfunc(msgid, subject)) {
77-
$("#attachModal").modal("hide");
80+
const attachModal = bootstrap.Modal.getInstance(
81+
document.getElementById("attachModal"),
82+
);
83+
attachModal.hide();
7884
}
7985
$("#attachThreadListWrap").removeClass("loading");
8086
$("#attachThreadSearchButton").removeClass("disabled");
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
from .models import CommitFest
2+
3+
4+
def global_context(request):
5+
"""Add global context variables available in all templates."""
6+
return {
7+
"current_cf": CommitFest.get_current(),
8+
"open_cf": CommitFest.get_open_regular(),
9+
}

pgcommitfest/commitfest/models.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ def statusstring(self):
6363

6464
@property
6565
def periodstring(self):
66-
return "{0} - {1}".format(self.startdate, self.enddate)
66+
return "{0} {1}".format(self.startdate, self.enddate)
6767

6868
@property
6969
def last_open_date(self):
@@ -277,6 +277,15 @@ def get_in_progress(cls):
277277
def get_open_regular(cls):
278278
return cls.objects.filter(status=CommitFest.STATUS_OPEN, draft=False).first()
279279

280+
@classmethod
281+
def get_current(cls):
282+
# First try to get in-progress CommitFest
283+
current = cls.get_in_progress()
284+
if current:
285+
return current
286+
# If no in-progress, fall back to open regular CommitFest
287+
return cls.get_open_regular()
288+
280289
def __str__(self):
281290
return self.name
282291

pgcommitfest/commitfest/templates/base.html

Lines changed: 30 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -14,32 +14,52 @@
1414
</head>
1515
<body>
1616
<!-- Main Navigation -->
17-
<nav class="navbar navbar-expand-lg navbar-light bg-light mb-3">
17+
<nav class="navbar navbar-expand-lg navbar-dark bg-dark mb-3">
1818
<div class="container-fluid">
1919
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#mainNavbar" aria-controls="mainNavbar" aria-expanded="false" aria-label="Toggle navigation">
2020
<span class="navbar-toggler-icon"></span>
2121
</button>
2222
<div class="collapse navbar-collapse" id="mainNavbar">
2323
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
2424
<li class="nav-item">
25-
<a class="nav-link" href="/me/">Dashboard</a>
25+
<a class="nav-link{% if request.resolver_match.url_name == 'home' or request.path == '/' %} active{% endif %}" href="/">Home</a>
2626
</li>
27+
{% if current_cf %}
28+
<li class="nav-item">
29+
<a class="nav-link{% if '/new/' in request.path %} active{% endif %}" href="/{{current_cf.id}}/new/">New Patch</a>
30+
</li>
31+
{% endif %}
32+
{% if current_cf %}
33+
<li class="nav-item">
34+
<a class="nav-link{% if cf and cf.is_in_progress %} active{% endif %}" href="/current/">Current CF</a>
35+
</li>
36+
{% endif %}
2737
<li class="nav-item">
28-
<a class="nav-link" href="/current/">Current CF</a>
38+
<a class="nav-link{% if cf and cf.is_open_regular %} active{% endif %}" href="/open/">Open CF</a>
2939
</li>
3040
<li class="nav-item">
31-
<a class="nav-link" href="/open/">Open CF</a>
41+
<a class="nav-link{% if cf and cf.is_open_draft %} active{% endif %}" href="/draft/">Draft CF</a>
3242
</li>
33-
<li class="nav-item">
34-
<a class="nav-link" href="/activity/">Activity Log</a>
35-
</li>
36-
<li class="nav-item">
37-
<a class="nav-link" href="/commitfest_history/">All CommitFests</a>
43+
<li class="nav-item dropdown">
44+
<a class="nav-link dropdown-toggle{% if '/activity/' in request.path or '/commitfest_history/' in request.path %} active{% endif %}" href="#" id="moreDropdown" role="button" data-bs-toggle="dropdown" aria-expanded="false">
45+
More
46+
</a>
47+
<ul class="dropdown-menu" aria-labelledby="moreDropdown">
48+
<li><a class="dropdown-item" href="/activity/">Activity Log</a></li>
49+
<li><a class="dropdown-item" href="/commitfest_history/">All CommitFests</a></li>
50+
</ul>
3851
</li>
3952
<li class="nav-item">
40-
<a class="nav-link" href="/help/">Help</a>
53+
<a class="nav-link{% if '/help/' in request.path %} active{% endif %}" href="/help/">Help</a>
4154
</li>
4255
</ul>
56+
<div class="d-flex gap-2 align-items-center">
57+
<form method="GET" action="/search/" class="d-flex gap-1">
58+
<input type="text" class="form-control" name="searchterm" placeholder="Email Message-ID or keywords" style="width: 250px;">
59+
<button type="submit" class="btn btn-outline-light">Search</button>
60+
</form>
61+
<a class="btn btn-primary" href="https://github.com/postgres/pgcommitfest" target="_blank"><img class="github-logo" src="/media/commitfest/github-mark.svg"/> Contribute on GitHub</a>
62+
</div>
4363
</div>
4464
</div>
4565
</nav>

pgcommitfest/commitfest/templates/base_form.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
{%endfor%}
3232
<div class="form-group">
3333
<div class="col-lg-12">
34-
<div class="control"><input type="submit" class="btn btn-outline-secondary" value="{{savebutton|default:"Save"}}"></div>
34+
<div class="control"><input type="submit" class="btn btn-primary" value="{{savebutton|default:"Save"}}"></div>
3535
</div>
3636
</div>
3737
</form>
@@ -45,8 +45,8 @@
4545
<div class="modal-dialog modal-lg">
4646
<div class="modal-content">
4747
<div class="modal-header">
48+
<h3 class="modal-title">Search user</h3>
4849
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
49-
<h3>Search user</h3>
5050
</div>
5151
<div class="modal-body">
5252
<form class="d-flex gap-2" style="margin-bottom: 5px;">

pgcommitfest/commitfest/templates/home.html

Lines changed: 132 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,13 @@
11
{%extends "base.html"%}
2+
{%load commitfest %}
23
{%block contents%}
3-
<p>
4-
First time user? <a href="/help">Here is a help page</a> for you to understand how this website works.
5-
</p>
4+
{% if not is_experienced_user %}
5+
<p>
6+
First time user? <a href="/help">Here is a help page</a> for you to understand how this website works.
7+
</p>
8+
{% endif %}
9+
10+
<h3>CommitFests</h3>
611
<p>
712
<table class="table" style="table-layout: auto; width: auto;">
813
<style>
@@ -22,7 +27,7 @@
2227
<tr>
2328
<td><strong>Open:</strong></td>
2429
<td><a href="/{{cfs.open.id}}/">{{cfs.open}}</a></td>
25-
<td>Now - {{cfs.open.last_open_date}}</td>
30+
<td>Now {{cfs.open.last_open_date}}</td>
2631
<td>{{cfs.open.periodstring}}</td>
2732
</tr>
2833
<tr>
@@ -41,7 +46,7 @@
4146
</td>
4247
<td>
4348
{%if cfs.in_progress %}
44-
Now - {{cfs.in_progress.enddate}}
49+
Now {{cfs.in_progress.enddate}}
4550
{%endif%}
4651
</td>
4752
</tr>
@@ -54,13 +59,13 @@
5459
<tr>
5560
<td><strong>Draft:</strong></td>
5661
<td><a href="/{{cfs.draft.id}}/">{{cfs.draft}}</a></td>
57-
<td>Now - {{cfs.draft.enddate}}</td>
62+
<td>Now {{cfs.draft.enddate}}</td>
5863
<td><span class="text-muted">N/A</span></td>
5964
</tr>
6065
<tr>
6166
<td><strong>Next open:</strong></td>
6267
<td>{{cfs.next_open}}</td>
63-
<td>{{cfs.open.startdate}}- {{cfs.next_open.last_open_date}}</td>
68+
<td>{{cfs.open.startdate}} {{cfs.next_open.last_open_date}}</td>
6469
<td>{{cfs.next_open.periodstring}}</td>
6570
</tr>
6671
<tr>
@@ -74,11 +79,11 @@
7479
</td>
7580
<td>
7681
{%if cfs.final.status == 2 %}
77-
Now - {{cfs.final.last_open_date}}
82+
Now {{cfs.final.last_open_date}}
7883
{%elif cfs.final.status == 3 %}
7984
<span class="text-muted">Not open anymore</span>
8085
{%else%}
81-
{{cfs.final.startdate.year}}-01-01 - {{cfs.final.last_open_date}}
86+
{{cfs.final.startdate.year}}-01-01 {{cfs.final.last_open_date}}
8287
{%endif%}
8388
</td>
8489
<td>
@@ -88,12 +93,123 @@
8893
</tbody>
8994
</table>
9095
</p>
91-
<h3>Search</h3>
92-
<form method="GET" action="/search/" class="d-flex gap-2">
93-
<div class="form-group">
94-
<input type="text" class="form-control" id="searchterm" name="searchterm" placeholder="Email Message-ID or keywords">
96+
97+
<hr>
98+
<h3>Your Dashboard</h3>
99+
100+
{% if not user.is_authenticated %}
101+
<div class="my-4">
102+
<a href="/account/login/?next=/" class="btn btn-primary btn-lg">Login to view your dashboard</a>
95103
</div>
96-
<button type="submit" class="btn btn-outline-secondary">Search</button>
97-
</form>
98-
<br/>
104+
{% endif %}
105+
106+
{% if show_dashboard %}
107+
108+
<button type="button" class="btn btn-outline-secondary{%if has_filter%} active{%endif%}" id="filterButton" onClick="togglePatchFilterButton('filterButton', 'collapseFilters')">Search/filter</button>
109+
110+
<p>
111+
<br/>
112+
<b>Status summary: </b>{%for id,title,num in statussummary%}<a href="?status={{id}}">{{title}}</a>: {{num}}. {%endfor%}
113+
</p>
114+
115+
116+
{%include "filter_form.html" %}
117+
{%for p in patches %}
118+
{%ifchanged p.is_open%}
119+
{%if not forloop.first%}
120+
</tbody>
121+
</table>
122+
{%endif%}
123+
<h3>{%if user.is_authenticated%}Open patches you are subscribed to{%elif p.is_open%}Active patches in the current commitfest{%else%}Closed patches in the current commitfest{%endif%}</h3>
124+
<table class="table table-striped table-bordered table-hover">
125+
<thead>
126+
<tr>
127+
<th><a href="#" style="color:#333333;" onclick="return sortpatches(5);">Patch</a>{%if sortkey == 5%}<div style="float:right;"></div>{%elif sortkey == -5%}<div style="float:right;"></div>{%endif%}</th>
128+
<th><a href="#" style="color:#333333;" onclick="return sortpatches(4);">ID</a>{%if sortkey == 4%}<div style="float:right;"></div>{%elif sortkey == -4%}<div style="float:right;"></div>{%endif%}</th>
129+
{%if user.is_authenticated %}
130+
<th><a href="#" style="color:#333333;" onclick="return sortpatches(8);">CF</a>{%if sortkey == 8%}<div style="float:right;"></div>{%elif sortkey == -8%}<div style="float:right;"></div>{%endif%}</th>
131+
{%endif%}
132+
<th>Status</th>
133+
<th>Tags</th>
134+
<th>Ver</th>
135+
<th><a href="#" style="color:#333333;" onclick="return sortpatches(7);">CI status</a>{%if sortkey == 7%}<div style="float:right;"></div>{%elif sortkey == -7%}<div style="float:right;"></div>{%endif%}</th>
136+
<th><a href="#" style="color:#333333;" onclick="return sortpatches(6);">Stats</a>{%if sortkey == 6%}<div style="float:right;"></div>{%elif sortkey == -6%}<div style="float:right;"></div>{%endif%}</th>
137+
<th>Author</th>
138+
<th>Reviewers</th>
139+
<th>Committer</th>
140+
<th><a href="#" style="color:#333333;" onclick="return sortpatches(3);">Num cfs</a>{%if sortkey == 3%}<div style="float:right;"></div>{%elif sortkey == -3%}<div style="float:right;"></div>{%endif%}</th>
141+
<th><a href="#" style="color:#333333;" onclick="return sortpatches(2);">Latest mail</a>{%if sortkey == 2%}<div style="float:right;"></div>{%elif sortkey == -2%}<div style="float:right;"></div>{%endif%}</th>
142+
</tr>
143+
</thead>
144+
<tbody>
145+
{%endifchanged%}
146+
147+
{%if grouping%}
148+
{%ifchanged p.topic%}
149+
<tr><th colspan="{%if user.is_authenticated %}13{%else%}12{%endif%}">{{p.topic}}</th></tr>
150+
{%endifchanged%}
151+
{%endif%}
152+
<tr>
153+
<td><a href="/patch/{{p.id}}/">{{p.name}}</a></td>
154+
<td>{{p.id}}</td>
155+
{%if user.is_authenticated %}
156+
<td><a href="/{{p.cf_id}}/"><span class="badge bg-{{p.cf_status|commitfeststatuslabel}}">{{p.cf_name}}</span></a></td>
157+
{%endif%}
158+
<td><span class="badge bg-{{p.status|patchstatuslabel}}">{{p.status|patchstatusstring}}</span></td>
159+
<td style="width: min-content;">
160+
{%for t in p.tag_ids%}
161+
<a href="?tag={{t}}">
162+
<span class="badge" style="background-color: {{all_tags|tagcolor:t}};" title="{{all_tags|tagdescription:t}}">{{all_tags|tagname:t}}</span>
163+
</a>
164+
{%endfor%}
165+
</td>
166+
<td>{%if p.targetversion%}<span class="badge bg-secondary">{{p.targetversion}}</span>{%endif%}</td>
167+
<td class="cfbot-summary">
168+
{%with p.cfbot_results as cfb%}
169+
{%if not cfb %}
170+
<span class="badge bg-secondary">Not processed</span>
171+
{%elif p.needs_rebase_since %}
172+
<a href="{{cfb.apply_url}}" title="View git apply logs. Needs rebase {% cfsince p.needs_rebase_since %}. {%if p.failing_since and p.failing_since != p.needs_rebase_since %}Failing {% cfsince p.failing_since %}.{%endif%}">
173+
<span class="badge bg-warning">Needs rebase!</span>
174+
</a>
175+
{%else%}
176+
<a href="https://github.com/postgresql-cfbot/postgresql/compare/cf/{{p.id}}~1...cf/{{p.id}}" title="View last patch set on GitHub"><img class="github-logo" src="/media/commitfest/github-mark.svg"/></a>
177+
<a href="https://cirrus-ci.com/github/postgresql-cfbot/postgresql/cf%2F{{p.id}}"
178+
title="View CI history. {%if p.failing_since%}Failing {% cfsince p.failing_since %}. {%endif%}{%if cfb.failed_task_names %}Failed jobs: {{cfb.failed_task_names}}{%endif%}">
179+
{%if cfb.failed > 0 or cfb.branch_status == 'failed' or cfb.branch_status == 'timeout' %}
180+
<img src="/media/commitfest/new_failure.svg"/>
181+
{%elif cfb.completed < cfb.total %}
182+
<img src="/media/commitfest/running.svg"/>
183+
{%else%}
184+
<img src="/media/commitfest/new_success.svg"/>
185+
{%endif%}
186+
<span class="run-counters">
187+
{{cfb.completed}}/{{cfb.total}}
188+
</span>
189+
</a>
190+
{%endif%}
191+
</td>
192+
<td>
193+
{%if cfb and cfb.all_additions is not none %}
194+
<span class="additions">+{{ cfb.all_additions }}</span><span class="deletions">&#8722;{{ cfb.all_deletions }}</span>
195+
{%endif%}
196+
</td>
197+
{%endwith%}
198+
<td>{{p.author_names|default:''}}</td>
199+
<td>{{p.reviewer_names|default:''}}</td>
200+
<td>{{p.committer|default:''}}</td>
201+
<td>{{p.num_cfs}}</td>
202+
<td style="white-space: nowrap;" title="{{p.lastmail}}">{%if p.lastmail and userprofile.show_relative_timestamps %}{% cfwhen p.lastmail %}{%elif p.lastmail %}{{p.lastmail|date:"Y-m-d"}}<br/>{{p.lastmail|date:"H:i"}}{%endif%}</td>
203+
</tr>
204+
{%if forloop.last%}
205+
</tbody>
206+
</table>
207+
{%endif%}
208+
{%endfor%}
209+
{% endif %}
210+
{%endblock%}
211+
{%block morescript%}
212+
{% if show_dashboard %}
213+
{% include "selectize_js.html" %}
214+
{% endif %}
99215
{%endblock%}

0 commit comments

Comments
 (0)