Skip to content

Commit e60f1e7

Browse files
committed
web: improve visual appearance to match django version
Rework the project list into a 3-column card grid with borders. Show raw URLs instead of generic "Website" text. Link project names to the detail page. Improve the project detail page with an "About" heading, maintainers listed with email addresses on separate lines, and an archived patch count next to the active count. On the patch detail page, display the patch name as a prominent title with download links on its right. Place metadata and checks side by side in a two-column layout, with checks in a bordered box matching the metadata style. Restyle check indicators as rounded colored pills with white text. Signed-off-by: Robin Jarry <rjarry@redhat.com>
1 parent 709d9c0 commit e60f1e7

4 files changed

Lines changed: 162 additions & 66 deletions

File tree

‎pkg/web/patch.templ‎

Lines changed: 33 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -53,10 +53,14 @@ templ patchDetailPage(d patchDetailData) {
5353
{Label: "Patches", URL: "/project/" + d.Project.Linkname + "/list/"},
5454
{Label: truncate(d.Patch.Name, 72)},
5555
}, d.PC) {
56+
<title-bar>
57+
<h1>{ d.Patch.Name }</h1>
58+
@downloadLinks(d.Patch.ID, d.Project.Linkname, d.Patch.Msgid, d.Series)
59+
</title-bar>
60+
<patch-columns>
5661
<form method="post" action={ templ.SafeURL(patchURL(d.Project.Linkname, d.Patch.Msgid)) }>
5762
<input type="hidden" name="csrftoken" value={ d.PC.CSRFToken }/>
5863
<submission-meta>
59-
@downloadLinks(d.Patch.ID, d.Project.Linkname, d.Patch.Msgid, d.Series)
6064
<table>
6165
<tbody>
6266
<tr>
@@ -219,34 +223,37 @@ templ patchDetailPage(d patchDetailData) {
219223
</submission-meta>
220224
</form>
221225
if len(d.Checks) > 0 {
222-
<h2>Checks</h2>
223-
<table>
224-
<thead>
225-
<tr>
226-
<th>Context</th>
227-
<th>Check</th>
228-
<th>Description</th>
229-
</tr>
230-
</thead>
231-
<tbody>
232-
for _, c := range d.Checks {
226+
<check-list>
227+
<h2>Checks</h2>
228+
<table>
229+
<thead>
233230
<tr>
234-
<td>{ c.Context }</td>
235-
<td>
236-
@checkState(c.State)
237-
</td>
238-
<td>
239-
if c.TargetURL != "" {
240-
<a href={ templ.SafeURL(c.TargetURL) }>{ c.Description }</a>
241-
} else {
242-
{ c.Description }
243-
}
244-
</td>
231+
<th>Context</th>
232+
<th>Check</th>
233+
<th>Description</th>
245234
</tr>
246-
}
247-
</tbody>
248-
</table>
235+
</thead>
236+
<tbody>
237+
for _, c := range d.Checks {
238+
<tr>
239+
<td>{ c.Context }</td>
240+
<td>
241+
@checkState(c.State)
242+
</td>
243+
<td>
244+
if c.TargetURL != "" {
245+
<a href={ templ.SafeURL(c.TargetURL) }>{ c.Description }</a>
246+
} else {
247+
{ c.Description }
248+
}
249+
</td>
250+
</tr>
251+
}
252+
</tbody>
253+
</table>
254+
</check-list>
249255
}
256+
</patch-columns>
250257
if len(d.Related) > 0 {
251258
<h2>Related</h2>
252259
<ul>

‎pkg/web/projects.go‎

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,5 +57,14 @@ func (h *webHandler) ProjectDetail(w http.ResponseWriter, r *http.Request) {
5757
return
5858
}
5959

60-
projectDetailPage(h.projectPageCtx(r, project), *project, maintainers, nPatches).Render(ctx, w)
60+
nArchived, err := q.DB.NewSelect().Model((*db.Patch)(nil)).
61+
Where("project_id = ?", project.ID).
62+
Where("archived = ?", true).
63+
Count(q.Ctx)
64+
if err != nil {
65+
serverErrorPage(w, "count archived", err)
66+
return
67+
}
68+
69+
projectDetailPage(h.projectPageCtx(r, project), *project, maintainers, nPatches, nArchived).Render(ctx, w)
6170
}

‎pkg/web/projects.templ‎

Lines changed: 47 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -5,41 +5,48 @@
55

66
package web
77

8-
import "github.com/getpatchwork/patchwork/pkg/db"
8+
import (
9+
"fmt"
10+
11+
"github.com/getpatchwork/patchwork/pkg/db"
12+
)
913

1014
templ projectListPage(pc pageContext, projects []db.Project) {
1115
@layout("Projects", nil, pc) {
12-
<h1>Projects</h1>
1316
if len(projects) == 0 {
1417
<p>No projects found.</p>
1518
} else {
16-
<div>
19+
<project-grid>
1720
for _, p := range projects {
18-
<article>
19-
<header>
20-
<a href={ templ.SafeURL("/project/" + p.Linkname + "/list/") }>
21+
<project-card>
22+
<h3>
23+
<a href={ templ.SafeURL("/project/" + p.Linkname) }>
2124
{ p.Name }
2225
</a>
23-
</header>
26+
</h3>
2427
<p>
2528
<a href={ templ.SafeURL("/project/" + p.Linkname + "/list/") }>
2629
View patches
2730
</a>
2831
</p>
2932
if p.WebURL != "" {
30-
<p><a href={ templ.SafeURL(p.WebURL) }>Website</a></p>
33+
<p><a href={ templ.SafeURL(p.WebURL) }>{ p.WebURL }</a></p>
34+
}
35+
if p.WebScmURL != "" {
36+
<p><a href={ templ.SafeURL(p.WebScmURL) }>{ p.WebScmURL }</a></p>
3137
}
32-
</article>
38+
</project-card>
3339
}
34-
</div>
40+
</project-grid>
3541
}
3642
}
3743
}
3844

39-
templ projectDetailPage(pc pageContext, project db.Project, maintainers []db.User, nPatches int) {
45+
templ projectDetailPage(pc pageContext, project db.Project, maintainers []db.User, nPatches int, nArchived int) {
4046
@layout(project.Name, []breadcrumb{
4147
{Label: project.Name},
4248
}, pc) {
49+
<h1>About { project.Name }</h1>
4350
<submission-meta>
4451
<table>
4552
<tbody>
@@ -53,22 +60,18 @@ templ projectDetailPage(pc pageContext, project db.Project, maintainers []db.Use
5360
<td><a href={ templ.SafeURL(project.ListArchiveURL) }>{ project.ListArchiveURL }</a></td>
5461
</tr>
5562
}
56-
if project.WebURL != "" {
57-
<tr>
58-
<th>Website</th>
59-
<td><a href={ templ.SafeURL(project.WebURL) }>{ project.WebURL }</a></td>
60-
</tr>
61-
}
62-
if project.ScmURL != "" {
63-
<tr>
64-
<th>SCM</th>
65-
<td>{ project.ScmURL }</td>
66-
</tr>
67-
}
68-
if project.WebScmURL != "" {
63+
if len(maintainers) > 0 {
6964
<tr>
70-
<th>Web SCM</th>
71-
<td><a href={ templ.SafeURL(project.WebScmURL) }>{ project.WebScmURL }</a></td>
65+
<th>Maintainers</th>
66+
<td>
67+
for _, m := range maintainers {
68+
{ m.FirstName } { m.LastName }
69+
{ " <" }
70+
<a href={ templ.SafeURL("mailto:" + m.Email) }>{ m.Email }</a>
71+
{ ">" }
72+
<br/>
73+
}
74+
</td>
7275
</tr>
7376
}
7477
<tr>
@@ -77,19 +80,27 @@ templ projectDetailPage(pc pageContext, project db.Project, maintainers []db.Use
7780
<a href={ templ.SafeURL("/project/" + project.Linkname + "/list/") }>
7881
{ intStr(nPatches) }
7982
</a>
83+
if nArchived > 0 {
84+
{ fmt.Sprintf(" (+ %d archived)", nArchived) }
85+
}
8086
</td>
8187
</tr>
82-
if len(maintainers) > 0 {
88+
if project.WebURL != "" {
8389
<tr>
84-
<th>Maintainers</th>
85-
<td>
86-
for i, m := range maintainers {
87-
if i > 0 {
88-
{ ", " }
89-
}
90-
{ m.FirstName } { m.LastName }
91-
}
92-
</td>
90+
<th>Website</th>
91+
<td><a href={ templ.SafeURL(project.WebURL) }>{ project.WebURL }</a></td>
92+
</tr>
93+
}
94+
if project.WebScmURL != "" {
95+
<tr>
96+
<th>Source Code Web Interface</th>
97+
<td><a href={ templ.SafeURL(project.WebScmURL) }>{ project.WebScmURL }</a></td>
98+
</tr>
99+
}
100+
if project.ScmURL != "" {
101+
<tr>
102+
<th>Source Code Manager URL</th>
103+
<td>{ project.ScmURL }</td>
93104
</tr>
94105
}
95106
</tbody>

‎pkg/web/static/style.css‎

Lines changed: 72 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,68 @@ main {
104104
padding: 0.5em 1em;
105105
}
106106

107+
/* --- project grid --- */
108+
project-grid {
109+
display: grid;
110+
grid-template-columns: repeat(3, 1fr);
111+
gap: 1.5em;
112+
padding: 1em 0;
113+
}
114+
project-card {
115+
display: block;
116+
border: 1px solid #ddd;
117+
border-radius: 4px;
118+
padding: 1.2em 1.5em;
119+
}
120+
project-card h3 {
121+
margin: 0 0 0.4em 0;
122+
font-size: 1.5em;
123+
font-weight: normal;
124+
}
125+
project-card p {
126+
margin: 0.3em 0;
127+
}
128+
129+
/* --- patch detail columns --- */
130+
patch-columns {
131+
display: flex;
132+
gap: 1em;
133+
align-items: flex-start;
134+
}
135+
patch-columns > form {
136+
flex: 1;
137+
min-width: 0;
138+
}
139+
patch-columns > check-list {
140+
flex: 1;
141+
min-width: 0;
142+
}
143+
check-list {
144+
display: block;
145+
border: 1px solid #ddd;
146+
border-radius: 4px;
147+
padding: 5px 0;
148+
}
149+
check-list h2 {
150+
margin: 0 0.8em 0.3em;
151+
}
152+
check-list table {
153+
border-collapse: collapse;
154+
width: 100%;
155+
}
156+
check-list th {
157+
padding: 3px 0.8em;
158+
border-bottom: 2px solid #ddd;
159+
text-align: left;
160+
background: #f5f5f5;
161+
}
162+
check-list td {
163+
padding: 3px 0.8em;
164+
border-top: 1px solid #e8e8e8;
165+
white-space: nowrap;
166+
}
167+
check-list tbody tr:nth-child(odd) { background: #f9f9f9; }
168+
107169
/* --- filter bar --- */
108170
patch-count {
109171
display: block;
@@ -231,9 +293,16 @@ fieldset legend {
231293
}
232294

233295
/* --- checks --- */
234-
check-ok { color: #82ca9d; }
235-
check-warn { color: #ffc95e; }
236-
check-fail { color: #ff5555; }
296+
check-ok, check-warn, check-fail {
297+
display: inline-block;
298+
padding: 0 4px;
299+
border-radius: 6px;
300+
font-weight: bold;
301+
color: #fff;
302+
}
303+
check-ok { background: #5cb85c; }
304+
check-warn { background: #f0ad4e; }
305+
check-fail { background: #d9534f; }
237306

238307
/* --- download links --- */
239308
title-bar {

0 commit comments

Comments
 (0)