- commit
- fe35422
- parent
- 38474f6
- author
- Eric Bower
- date
- 2024-10-21 22:43:41 -0400 EDT
feat: ability to view all patchsets
8 files changed,
+296,
-234
+4,
-0
1@@ -7,6 +7,10 @@ td, th {
2 border-bottom: 1px solid var(--grey-light);
3 }
4
5+details {
6+ margin-bottom: 0;
7+}
8+
9 .pill-success {
10 border: 1px solid var(--success);
11 color: var(--success);
+16,
-0
1@@ -0,0 +1,16 @@
2+{{define "patchset"}}
3+<div class="group">
4+ <h2 class="text-xl">
5+ Patchset <code>ps-{{.Patchset.ID}}</code>
6+ </h2>
7+ {{range $idx, $val := .Patches}}
8+ <div class="group" id="{{.Url}}">
9+ {{template "patch" .}}
10+ </div>
11+ {{else}}
12+ <div class="box">
13+ No patches found for patch request.
14+ </div>
15+ {{end}}
16+</div>
17+{{end}}
+72,
-75
1@@ -15,94 +15,91 @@
2 {{define "body"}}
3 {{template "pr-header" .}}
4
5-<hr />
6-
7 <main class="group">
8- <div class="box-sm group text-sm">
9- <h3 class="text-lg">Logs</h3>
10-
11- {{range .Logs}}
12- <div>
13- <code class='pill{{if .UserData.IsAdmin}}-admin{{end}}' title="{{.UserData.Pubkey}}">{{.UserData.Name}}</code>
14- <span class="font-bold">
15- {{if eq .Event "pr_created"}}
16- created pr with <code>{{.FormattedPatchsetID}}</code>
17- {{else if eq .Event "pr_patchset_added"}}
18- added <code>{{.FormattedPatchsetID}}</code>
19- {{else if eq .Event "pr_patchset_deleted"}}
20- deleted <code>{{.FormattedPatchsetID}}</code>
21- {{else if eq .Event "pr_reviewed"}}
22- reviewed pr with <code class="pill-review">{{.FormattedPatchsetID}}</code>
23- {{else if eq .Event "pr_patchset_replaced"}}
24- replaced <code>{{.FormattedPatchsetID}}</code>
25- {{else if eq .Event "pr_status_changed"}}
26- changed status
27- {{else if eq .Event "pr_name_changed"}}
28- changed pr name
29- {{else}}
30- {{.Event}}
31- {{end}}
32- </span>
33- <span>on <date>{{.Date}}</date></span>
34- {{if .Data}}<code>{{.Data}}</code>{{end}}
35+ <div class="flex gap-2">
36+ <div class="group text-sm" style="width: 300px;">
37+ <h3 class="text-lg">Logs</h3>
38+ {{range .Logs}}
39+ <div>
40+ {{template "user-pill" .UserData}}
41+ <span class="font-bold">
42+ {{if eq .Event "pr_created"}}
43+ {{if eq $.Patchset.ID .Patchset.ID}}
44+ created pr with <code>{{.FormattedPatchsetID}}</code>
45+ {{else}}
46+ created pr with <a href="/ps/{{.Patchset.ID}}"><code>{{.FormattedPatchsetID}}</code></a>
47+ {{end}}
48+ {{else if eq .Event "pr_patchset_added"}}
49+ {{if eq $.Patchset.ID .Patchset.ID}}
50+ added <code>{{.FormattedPatchsetID}}</code>
51+ {{else}}
52+ added <a href="/ps/{{.Patchset.ID}}"><code>{{.FormattedPatchsetID}}</code></a>
53+ {{end}}
54+ {{else if eq .Event "pr_patchset_deleted"}}
55+ deleted <code>{{.FormattedPatchsetID}}</code>
56+ {{else if eq .Event "pr_reviewed"}}
57+ reviewed pr with <code class="pill-review">{{.FormattedPatchsetID}}</code>
58+ {{else if eq .Event "pr_patchset_replaced"}}
59+ replaced <code>{{.FormattedPatchsetID}}</code>
60+ {{else if eq .Event "pr_status_changed"}}
61+ changed status
62+ {{else if eq .Event "pr_name_changed"}}
63+ changed pr name
64+ {{else}}
65+ {{.Event}}
66+ {{end}}
67+ </span>
68+ <span>on <date>{{.Date}}</date></span>
69+ {{if .Data}}<code>{{.Data}}</code>{{end}}
70+ </div>
71+ {{end}}
72 </div>
73- {{end}}
74- </div>
75
76- <div class="box-sm group text-sm">
77- <h3 class="text-lg">Patchsets</h3>
78+ <div class="group text-sm flex-1">
79+ <h3 class="text-lg">Patchsets</h3>
80
81- {{range .Patchsets}}
82- {{if .RangeDiff}}
83- <details>
84- <summary class="text-sm">Range Diff ↕</summary>
85- <div class="group">
86- {{- range .RangeDiff -}}
87- <div>
88- <code class='{{if eq .Type "rm"}}pill-admin{{else if eq .Type "add"}}pill-success{{else if eq .Type "diff"}}pill-review{{end}}'>
89- {{.Header}}
90- </code>
91- </div>
92- {{- if .Diff -}}
93- <pre>
94- {{- range .Diff -}}
95- {{- if eq .Type -1 -}}
96- <span style="color: tomato;">{{.Text}}</span>
97- {{- else if eq .Type 1 -}}
98- <span style="color: limegreen;">{{.Text}}</span>
99- {{- else -}}
100- <span>{{.Text}}</span>
101+ {{range .Patchsets}}
102+ {{if .RangeDiff}}
103+ <details>
104+ <summary class="text-sm">Range Diff ↕</summary>
105+ <div class="group">
106+ {{- range .RangeDiff -}}
107+ <div>
108+ <code class='{{if eq .Type "rm"}}pill-admin{{else if eq .Type "add"}}pill-success{{else if eq .Type "diff"}}pill-review{{end}}'>
109+ {{.Header}}
110+ </code>
111+ </div>
112+ {{- if .Diff -}}
113+ <pre>
114+ {{- range .Diff -}}
115+ {{- if eq .Type -1 -}}
116+ <span style="color: tomato;">{{.Text}}</span>
117+ {{- else if eq .Type 1 -}}
118+ <span style="color: limegreen;">{{.Text}}</span>
119+ {{- else -}}
120+ <span>{{.Text}}</span>
121+ {{- end -}}
122 {{- end -}}
123+ </pre>
124 {{- end -}}
125- </pre>
126 {{- end -}}
127- {{- end -}}
128+ </div>
129+ </details>
130+ {{end}}
131+
132+ <div>
133+ <code class="{{if .Review}}pill-review{{end}}">{{.FormattedID}}</code>
134+ <span> by </span>
135+ {{template "user-pill" .UserData}}
136+ <span>on <date>{{.Date}}</date></span>
137 </div>
138- </details>
139 {{end}}
140-
141- <div>
142- <code class="{{if .Review}}pill-review{{end}}">{{.FormattedID}}</code>
143- <span> by </span>
144- <code class="pill{{if .UserData.IsAdmin}}-admin{{end}}" title="{{.UserData.Pubkey}}">{{.UserData.Name}}</code>
145- <span>on <date>{{.Date}}</date></span>
146- </div>
147- {{end}}
148+ </div>
149 </div>
150
151 <hr class="w-full" />
152
153- <div class="group">
154- {{range $idx, $val := .Patches}}
155- <div class="group" id="{{.Url}}">
156- {{template "patch" .}}
157- </div>
158- {{else}}
159- <div class="box">
160- No patches found for patch request.
161- </div>
162- {{end}}
163- </div>
164+ {{template "patchset" .}}
165 </main>
166
167 <hr />
+2,
-2
1@@ -2,14 +2,14 @@
2 <header>
3 <h1 class="text-2xl mb">
4 <a href="{{.Repo.Url}}">{{.Repo.Text}}</a>
5- <span> / {{.Pr.Title}} <code>#{{.Pr.ID}}</code></span>
6+ <span> / {{.Pr.Title}} <a href="/prs/{{.Pr.ID}}"><code>#{{.Pr.ID}}</code></a></span>
7 </h1>
8
9 <div class="text-sm mb">
10 {{template "pr-status" .Pr.Status}}
11 <span>·</span>
12 <span>opened on <date>{{.Pr.Date}}</date> by</span>
13- <code class="pill{{if .Pr.UserData.IsAdmin}}-admin{{end}}" title="{{.Pr.UserData.Pubkey}}">{{.Pr.UserData.Name}}</code>
14+ {{template "user-pill" .Pr.UserData}}
15 </div>
16
17 <details>
+1,
-1
1@@ -7,7 +7,7 @@
2 <div>
3 <code>#{{.ID}}</code>
4 <span>opened on <date>{{.Date}}</date> by </span>
5- <code class="{{if .UserData.IsAdmin}}pill-admin{{end}}" title="{{.UserData.Pubkey}}">{{.UserData.Name}}</code>
6+ {{template "user-pill" .UserData}}
7 </div>
8 </div>
9 {{end}}
+1,
-3
1@@ -22,9 +22,7 @@
2 <a href="{{.PrLink.Url}}">{{.PrLink.Text}}</a>
3 </td>
4 <td>
5- <code class="{{if .UserData.IsAdmin}}pill-admin{{end}}" title="{{.UserData.Pubkey}}">
6- <a href="/users/{{.UserData.Name}}">{{.UserData.Name}}</a>
7- </code>
8+ {{template "user-pill" .UserData}}
9 </td>
10 <td><date>{{.Date}}</date></td>
11 </tr>
+5,
-0
1@@ -0,0 +1,5 @@
2+{{define "user-pill"}}
3+<a href="/users/{{.Name}}">
4+ <code class='pill{{if .IsAdmin}}-admin{{end}}' title="{{.Pubkey}}">{{.Name}}</code>
5+</a>
6+{{end}}
M
web.go
+195,
-153
1@@ -80,7 +80,9 @@ func getTemplate(file string) *template.Template {
2 template.ParseFS(
3 tmplFS,
4 filepath.Join("tmpl", file),
5+ filepath.Join("tmpl", "user-pill.html"),
6 filepath.Join("tmpl", "patch.html"),
7+ filepath.Join("tmpl", "patchset.html"),
8 filepath.Join("tmpl", "pr-header.html"),
9 filepath.Join("tmpl", "pr-list-item.html"),
10 filepath.Join("tmpl", "pr-table.html"),
11@@ -425,6 +427,7 @@ type PatchData struct {
12 type EventLogData struct {
13 *EventLog
14 UserData
15+ *Patchset
16 FormattedPatchsetID string
17 Date string
18 }
19@@ -441,6 +444,7 @@ type PrDetailData struct {
20 Page string
21 Repo LinkData
22 Pr PrData
23+ Patchset *Patchset
24 Patches []PatchData
25 Branch string
26 Logs []EventLogData
27@@ -448,196 +452,233 @@ type PrDetailData struct {
28 MetaData
29 }
30
31-func prDetailHandler(w http.ResponseWriter, r *http.Request) {
32- id := r.PathValue("id")
33- prID, err := strconv.Atoi(id)
34- if err != nil {
35- w.WriteHeader(http.StatusUnprocessableEntity)
36- return
37- }
38-
39- web, err := getWebCtx(r)
40- if err != nil {
41- w.WriteHeader(http.StatusInternalServerError)
42- return
43- }
44-
45- pr, err := web.Pr.GetPatchRequestByID(int64(prID))
46- if err != nil {
47- web.Pr.Backend.Logger.Error("cannot get prs", "err", err)
48- w.WriteHeader(http.StatusInternalServerError)
49- return
50- }
51-
52- repo, err := web.Pr.GetRepoByID(pr.RepoID)
53- if err != nil {
54- web.Logger.Error("cannot get repo", "err", err)
55- w.WriteHeader(http.StatusInternalServerError)
56- return
57- }
58-
59- patchsets, err := web.Pr.GetPatchsetsByPrID(int64(prID))
60- if err != nil {
61- web.Logger.Error("cannot get latest patchset", "err", err)
62- w.WriteHeader(http.StatusInternalServerError)
63- return
64- }
65-
66- // get patchsets and diff from previous patchset
67- patchsetsData := []PatchsetData{}
68- for idx, patchset := range patchsets {
69- user, err := web.Pr.GetUserByID(patchset.UserID)
70+func createPrDetail(page string) http.HandlerFunc {
71+ return func(w http.ResponseWriter, r *http.Request) {
72+ id := r.PathValue("id")
73+ prID, err := strconv.Atoi(id)
74 if err != nil {
75- web.Logger.Error("could not get user for patch", "err", err)
76- continue
77+ w.WriteHeader(http.StatusUnprocessableEntity)
78+ return
79 }
80
81- var prevPatchset *Patchset
82- if idx > 0 {
83- prevPatchset = patchsets[idx-1]
84+ web, err := getWebCtx(r)
85+ if err != nil {
86+ w.WriteHeader(http.StatusInternalServerError)
87+ return
88 }
89
90- var rangeDiff []*RangeDiffOutput
91- if idx > 0 {
92- rangeDiff, err = web.Pr.DiffPatchsets(prevPatchset, patchset)
93+ var pr *PatchRequest
94+ var ps *Patchset
95+ if page == "pr" {
96+ pr, err = web.Pr.GetPatchRequestByID(int64(prID))
97 if err != nil {
98- web.Logger.Error("could not diff patchset", "err", err)
99- continue
100+ web.Pr.Backend.Logger.Error("cannot get prs", "err", err)
101+ w.WriteHeader(http.StatusInternalServerError)
102+ return
103+ }
104+ } else if page == "ps" {
105+ ps, err = web.Pr.GetPatchsetByID(int64(prID))
106+ if err != nil {
107+ web.Pr.Backend.Logger.Error("cannot get patchset", "err", err)
108+ w.WriteHeader(http.StatusInternalServerError)
109+ return
110+ }
111+
112+ pr, err = web.Pr.GetPatchRequestByID(int64(ps.PatchRequestID))
113+ if err != nil {
114+ web.Pr.Backend.Logger.Error("cannot get pr", "err", err)
115+ w.WriteHeader(http.StatusInternalServerError)
116+ return
117 }
118 }
119
120- pk, err := web.Backend.PubkeyToPublicKey(user.Pubkey)
121+ repo, err := web.Pr.GetRepoByID(pr.RepoID)
122 if err != nil {
123- web.Logger.Error("cannot parse pubkey for pr user", "err", err)
124- w.WriteHeader(http.StatusUnprocessableEntity)
125+ web.Logger.Error("cannot get repo", "err", err)
126+ w.WriteHeader(http.StatusInternalServerError)
127 return
128 }
129
130- patchsetsData = append(patchsetsData, PatchsetData{
131- Patchset: patchset,
132- FormattedID: getFormattedPatchsetID(patchset.ID),
133- UserData: UserData{
134- UserID: user.ID,
135- Name: user.Name,
136- IsAdmin: web.Backend.IsAdmin(pk),
137- Pubkey: user.Pubkey,
138- CreatedAt: user.CreatedAt.Format(time.RFC3339),
139- },
140- Date: patchset.CreatedAt.Format(time.RFC3339),
141- RangeDiff: rangeDiff,
142- })
143- }
144-
145- patchesData := []PatchData{}
146- if len(patchsetsData) >= 1 {
147- latest := patchsetsData[len(patchsets)-1]
148- patches, err := web.Pr.GetPatchesByPatchsetID(latest.ID)
149+ patchsets, err := web.Pr.GetPatchsetsByPrID(pr.ID)
150 if err != nil {
151- web.Logger.Error("cannot get patches", "err", err)
152+ web.Logger.Error("cannot get latest patchset", "err", err)
153 w.WriteHeader(http.StatusInternalServerError)
154 return
155 }
156
157- for _, patch := range patches {
158- timestamp := patch.AuthorDate.Format(web.Backend.Cfg.TimeFormat)
159- diffStr, err := parseText(web.Formatter, web.Theme, patch.RawText)
160+ // get patchsets and diff from previous patchset
161+ patchsetsData := []PatchsetData{}
162+ for idx, patchset := range patchsets {
163+ user, err := web.Pr.GetUserByID(patchset.UserID)
164+ if err != nil {
165+ web.Logger.Error("could not get user for patch", "err", err)
166+ continue
167+ }
168+
169+ var prevPatchset *Patchset
170+ if idx > 0 {
171+ prevPatchset = patchsets[idx-1]
172+ }
173+
174+ var rangeDiff []*RangeDiffOutput
175+ if idx > 0 {
176+ rangeDiff, err = web.Pr.DiffPatchsets(prevPatchset, patchset)
177+ if err != nil {
178+ web.Logger.Error("could not diff patchset", "err", err)
179+ continue
180+ }
181+ }
182+
183+ pk, err := web.Backend.PubkeyToPublicKey(user.Pubkey)
184 if err != nil {
185- web.Logger.Error("cannot parse patch", "err", err)
186+ web.Logger.Error("cannot parse pubkey for pr user", "err", err)
187 w.WriteHeader(http.StatusUnprocessableEntity)
188 return
189 }
190
191- // highlight review
192- isReview := false
193+ // set selected patchset to latest when no ps already set
194+ if ps == nil && idx == len(patchsets)-1 {
195+ ps = patchset
196+ }
197
198- patchesData = append(patchesData, PatchData{
199- Patch: patch,
200- Url: template.URL(fmt.Sprintf("patch-%d", patch.ID)),
201- DiffStr: template.HTML(diffStr),
202- Review: isReview,
203- FormattedAuthorDate: timestamp,
204+ patchsetsData = append(patchsetsData, PatchsetData{
205+ Patchset: patchset,
206+ FormattedID: getFormattedPatchsetID(patchset.ID),
207+ UserData: UserData{
208+ UserID: user.ID,
209+ Name: user.Name,
210+ IsAdmin: web.Backend.IsAdmin(pk),
211+ Pubkey: user.Pubkey,
212+ CreatedAt: user.CreatedAt.Format(time.RFC3339),
213+ },
214+ Date: patchset.CreatedAt.Format(time.RFC3339),
215+ RangeDiff: rangeDiff,
216 })
217 }
218- }
219
220- user, err := web.Pr.GetUserByID(pr.UserID)
221- if err != nil {
222- w.WriteHeader(http.StatusNotFound)
223- return
224- }
225+ patchesData := []PatchData{}
226+ if len(patchsetsData) >= 1 {
227+ psID := ps.ID
228+ patches, err := web.Pr.GetPatchesByPatchsetID(psID)
229+ if err != nil {
230+ web.Logger.Error("cannot get patches", "err", err)
231+ w.WriteHeader(http.StatusInternalServerError)
232+ return
233+ }
234
235- w.Header().Set("content-type", "text/html")
236- tmpl := getTemplate("pr-detail.html")
237- pk, err := web.Backend.PubkeyToPublicKey(user.Pubkey)
238- if err != nil {
239- web.Logger.Error("cannot parse pubkey for pr user", "err", err)
240- w.WriteHeader(http.StatusUnprocessableEntity)
241- return
242- }
243- isAdmin := web.Backend.IsAdmin(pk)
244- logs, err := web.Pr.GetEventLogsByPrID(int64(prID))
245- if err != nil {
246- web.Logger.Error("cannot get logs for pr", "err", err)
247- w.WriteHeader(http.StatusUnprocessableEntity)
248- return
249- }
250- slices.SortFunc(logs, func(a *EventLog, b *EventLog) int {
251- return a.CreatedAt.Compare(b.CreatedAt)
252- })
253+ for _, patch := range patches {
254+ timestamp := patch.AuthorDate.Format(web.Backend.Cfg.TimeFormat)
255+ diffStr, err := parseText(web.Formatter, web.Theme, patch.RawText)
256+ if err != nil {
257+ web.Logger.Error("cannot parse patch", "err", err)
258+ w.WriteHeader(http.StatusUnprocessableEntity)
259+ return
260+ }
261+
262+ // highlight review
263+ isReview := false
264+
265+ patchesData = append(patchesData, PatchData{
266+ Patch: patch,
267+ Url: template.URL(fmt.Sprintf("patch-%d", patch.ID)),
268+ DiffStr: template.HTML(diffStr),
269+ Review: isReview,
270+ FormattedAuthorDate: timestamp,
271+ })
272+ }
273+ }
274
275- logData := []EventLogData{}
276- for _, eventlog := range logs {
277- user, _ := web.Pr.GetUserByID(eventlog.UserID)
278+ user, err := web.Pr.GetUserByID(pr.UserID)
279+ if err != nil {
280+ w.WriteHeader(http.StatusNotFound)
281+ return
282+ }
283+
284+ w.Header().Set("content-type", "text/html")
285+ tmpl := getTemplate("pr-detail.html")
286 pk, err := web.Backend.PubkeyToPublicKey(user.Pubkey)
287 if err != nil {
288 web.Logger.Error("cannot parse pubkey for pr user", "err", err)
289 w.WriteHeader(http.StatusUnprocessableEntity)
290 return
291 }
292-
293- logData = append(logData, EventLogData{
294- EventLog: eventlog,
295- FormattedPatchsetID: getFormattedPatchsetID(eventlog.PatchsetID.Int64),
296- UserData: UserData{
297- UserID: user.ID,
298- Name: user.Name,
299- IsAdmin: web.Backend.IsAdmin(pk),
300- Pubkey: user.Pubkey,
301- CreatedAt: user.CreatedAt.Format(time.RFC3339),
302- },
303- Date: eventlog.CreatedAt.Format(web.Backend.Cfg.TimeFormat),
304+ isAdmin := web.Backend.IsAdmin(pk)
305+ logs, err := web.Pr.GetEventLogsByPrID(pr.ID)
306+ if err != nil {
307+ web.Logger.Error("cannot get logs for pr", "err", err)
308+ w.WriteHeader(http.StatusUnprocessableEntity)
309+ return
310+ }
311+ slices.SortFunc(logs, func(a *EventLog, b *EventLog) int {
312+ return a.CreatedAt.Compare(b.CreatedAt)
313 })
314- }
315
316- err = tmpl.Execute(w, PrDetailData{
317- Page: "pr",
318- Repo: LinkData{
319- Url: template.URL("/repos/" + repo.ID),
320- Text: repo.ID,
321- },
322- Branch: repo.DefaultBranch,
323- Patches: patchesData,
324- Patchsets: patchsetsData,
325- Logs: logData,
326- Pr: PrData{
327- ID: pr.ID,
328- UserData: UserData{
329- UserID: user.ID,
330- Name: user.Name,
331- IsAdmin: isAdmin,
332- Pubkey: user.Pubkey,
333- CreatedAt: user.CreatedAt.Format(time.RFC3339),
334+ logData := []EventLogData{}
335+ for _, eventlog := range logs {
336+ user, _ := web.Pr.GetUserByID(eventlog.UserID)
337+ pk, err := web.Backend.PubkeyToPublicKey(user.Pubkey)
338+ if err != nil {
339+ web.Logger.Error("cannot parse pubkey for pr user", "err", err)
340+ w.WriteHeader(http.StatusUnprocessableEntity)
341+ return
342+ }
343+ var logps *Patchset
344+ if eventlog.PatchsetID.Int64 > 0 {
345+ logps, err = web.Pr.GetPatchsetByID(eventlog.PatchsetID.Int64)
346+ if err != nil {
347+ web.Logger.Error("cannot get patchset", "err", err, "ps", eventlog.PatchsetID)
348+ w.WriteHeader(http.StatusUnprocessableEntity)
349+ return
350+ }
351+ }
352+
353+ logData = append(logData, EventLogData{
354+ EventLog: eventlog,
355+ FormattedPatchsetID: getFormattedPatchsetID(eventlog.PatchsetID.Int64),
356+ Patchset: logps,
357+ UserData: UserData{
358+ UserID: user.ID,
359+ Name: user.Name,
360+ IsAdmin: web.Backend.IsAdmin(pk),
361+ Pubkey: user.Pubkey,
362+ CreatedAt: user.CreatedAt.Format(time.RFC3339),
363+ },
364+ Date: eventlog.CreatedAt.Format(web.Backend.Cfg.TimeFormat),
365+ })
366+ }
367+
368+ fmt.Println("PSSPSPSPS", ps)
369+ err = tmpl.Execute(w, PrDetailData{
370+ Page: "pr",
371+ Repo: LinkData{
372+ Url: template.URL("/repos/" + repo.ID),
373+ Text: repo.ID,
374 },
375- Title: pr.Name,
376- Date: pr.CreatedAt.Format(web.Backend.Cfg.TimeFormat),
377- Status: pr.Status,
378- },
379- MetaData: MetaData{
380- URL: web.Backend.Cfg.Url,
381- },
382- })
383- if err != nil {
384- web.Backend.Logger.Error("cannot execute template", "err", err)
385+ Branch: repo.DefaultBranch,
386+ Patchset: ps,
387+ Patches: patchesData,
388+ Patchsets: patchsetsData,
389+ Logs: logData,
390+ Pr: PrData{
391+ ID: pr.ID,
392+ UserData: UserData{
393+ UserID: user.ID,
394+ Name: user.Name,
395+ IsAdmin: isAdmin,
396+ Pubkey: user.Pubkey,
397+ CreatedAt: user.CreatedAt.Format(time.RFC3339),
398+ },
399+ Title: pr.Name,
400+ Date: pr.CreatedAt.Format(web.Backend.Cfg.TimeFormat),
401+ Status: pr.Status,
402+ },
403+ MetaData: MetaData{
404+ URL: web.Backend.Cfg.Url,
405+ },
406+ })
407+ if err != nil {
408+ web.Backend.Logger.Error("cannot execute template", "err", err)
409+ }
410 }
411 }
412
413@@ -870,8 +911,9 @@ func StartWebServer(cfg *GitCfg) {
414
415 // ensure legacy router is disabled
416 // GODEBUG=httpmuxgo121=0
417- http.HandleFunc("GET /prs/{id}", ctxMdw(ctx, prDetailHandler))
418+ http.HandleFunc("GET /prs/{id}", ctxMdw(ctx, createPrDetail("pr")))
419 http.HandleFunc("GET /prs/{id}/rss", ctxMdw(ctx, rssHandler))
420+ http.HandleFunc("GET /ps/{id}", ctxMdw(ctx, createPrDetail("ps")))
421 http.HandleFunc("GET /repos/{id}", ctxMdw(ctx, repoDetailHandler))
422 http.HandleFunc("GET /repos/{repoid}/rss", ctxMdw(ctx, rssHandler))
423 http.HandleFunc("GET /users/{name}", ctxMdw(ctx, userDetailHandler))