repos / git-pr

a self-hosted git collaboration server
git clone https://github.com/picosh/git-pr.git

commit
131005f
parent
7b83c3e
author
Eric Bower
date
2024-10-21 14:38:31 -0400 EDT
refactor: table format for prs
5 files changed,  +110, -150
M web.go
M tmpl/base.html
+1, -1
1@@ -14,6 +14,6 @@
2     <link rel="stylesheet" href="/static/vars.css" />
3     <link rel="stylesheet" href="/syntax.css" />
4   </head>
5-  <body class="container">{{template "body" .}}</body>
6+  <body class="px-2">{{template "body" .}}</body>
7 </html>
8 {{end}}
R tmpl/repo-list.html => tmpl/index.html
+1, -11
 1@@ -218,17 +218,7 @@ git push origin main
 2 <hr />
 3 
 4 <main>
 5-  <div class="group">
 6-    {{range .Repos}}
 7-    <div class="box">
 8-      <h3 class="text-lg m-0 p-0"><a href="{{.Url}}">{{.Text}}</a></h3>
 9-      <div class="text-sm">{{.Desc}}</div>
10-      {{if .LatestPr}}
11-        <div class="text-xs mt ml">{{template "pr-list-item" .LatestPr}}</div>
12-      {{end}}
13-    </div>
14-    {{end}}
15-  </div>
16+  {{template "pr-table" .Prs}}
17 </main>
18 
19 <footer>
A tmpl/pr-table.html
+32, -0
 1@@ -0,0 +1,32 @@
 2+{{define "pr-table"}}
 3+<table class="w-full">
 4+  <thead>
 5+    <tr>
 6+      <th class="text-left">Repo</th>
 7+      <th class="text-left">Status</th>
 8+      <th class="text-left">Title</th>
 9+      <th class="text-left">User</th>
10+      <th class="text-left">Created At</th>
11+    </tr>
12+  </thead>
13+
14+  <tbody>
15+    {{range .}}
16+      <tr>
17+        <td>
18+          <a href="{{.RepoLink.Url}}">{{.RepoLink.Text}}</a>
19+        </td>
20+        <td>{{template "pr-status" .Status}}</td>
21+        <td>
22+          <code>#{{.ID}}</code>
23+          <a href="{{.PrLink.Url}}">{{.PrLink.Text}}</a>
24+        </td>
25+        <td>
26+          <code class="{{if .UserData.IsAdmin}}pill-admin{{end}}" title="{{.UserData.Pubkey}}">{{.UserData.Name}}</code>
27+        </td>
28+        <td><date>{{.Date}}</date></td>
29+      </tr>
30+    {{end}}
31+  </tbody>
32+</table>
33+{{end}}
M tmpl/repo-detail.html
+1, -30
 1@@ -35,36 +35,7 @@ ssh {{.MetaData.URL}} pr ls {{.ID}}</pre>
 2 <hr />
 3 
 4 <main class="group">
 5-  <h3 class="text-lg">Open PRs</h3>
 6-  {{range .OpenPrs}}
 7-    <div class="box">{{template "pr-list-item" .}}</div>
 8-  {{else}}
 9-    <div>No open patch requests.</div>
10-  {{end}}
11-
12-  {{if .ReviewedPrs}}
13-    <hr class="my w-full" />
14-    <h3 class="text-lg">Reviews PRs</h3>
15-    {{range .ReviewedPrs}}
16-      <div class="box">{{template "pr-list-item" .}}</div>
17-    {{end}}
18-  {{end}}
19-
20-  {{if .AcceptedPrs}}
21-    <hr class="my w-full" />
22-    <h3 class="text-lg">Accepted PRs</h3>
23-    {{range .AcceptedPrs}}
24-      <div class="box">{{template "pr-list-item" .}}</div>
25-    {{end}}
26-  {{end}}
27-
28-  {{if .ClosedPrs}}
29-    <hr class="my w-full" />
30-    <h3 class="text-lg">Closed PRs</h3>
31-    {{range .ClosedPrs}}
32-      <div class="box">{{template "pr-list-item" .}}</div>
33-    {{end}}
34-  {{end}}
35+  {{template "pr-table" .Prs}}
36 </main>
37 
38 <hr />
M web.go
+75, -108
  1@@ -81,6 +81,7 @@ func getTemplate(file string) *template.Template {
  2 			filepath.Join("tmpl", "patch.html"),
  3 			filepath.Join("tmpl", "pr-header.html"),
  4 			filepath.Join("tmpl", "pr-list-item.html"),
  5+			filepath.Join("tmpl", "pr-table.html"),
  6 			filepath.Join("tmpl", "pr-status.html"),
  7 			filepath.Join("tmpl", "base.html"),
  8 		),
  9@@ -93,73 +94,75 @@ type LinkData struct {
 10 	Text string
 11 }
 12 
 13-type RepoData struct {
 14-	LinkData
 15-	Desc     string
 16-	LatestPr *PrListData
 17+type PrTableData struct {
 18+	Prs []*PrListData
 19+	MetaData
 20 }
 21 
 22-type RepoListData struct {
 23-	Repos []RepoData
 24-	MetaData
 25+func getPrTableData(web *WebCtx, prs []*PatchRequest) ([]*PrListData, error) {
 26+	prdata := []*PrListData{}
 27+	for _, curpr := range prs {
 28+		user, err := web.Pr.GetUserByID(curpr.UserID)
 29+		if err != nil {
 30+			web.Logger.Error("cannot get user from pr", "err", err)
 31+			continue
 32+		}
 33+		pk, err := web.Backend.PubkeyToPublicKey(user.Pubkey)
 34+		if err != nil {
 35+			web.Logger.Error("cannot get pubkey from user public key", "err", err)
 36+			continue
 37+		}
 38+		isAdmin := web.Backend.IsAdmin(pk)
 39+		prls := &PrListData{
 40+			RepoID: curpr.RepoID,
 41+			ID:     curpr.ID,
 42+			UserData: UserData{
 43+				Name:    user.Name,
 44+				IsAdmin: isAdmin,
 45+				Pubkey:  user.Pubkey,
 46+			},
 47+			RepoLink: LinkData{
 48+				Url:  template.URL(fmt.Sprintf("/repos/%s", curpr.RepoID)),
 49+				Text: curpr.RepoID,
 50+			},
 51+			PrLink: LinkData{
 52+				Url:  template.URL(fmt.Sprintf("/prs/%d", curpr.ID)),
 53+				Text: curpr.Name,
 54+			},
 55+			Date:   curpr.CreatedAt.Format(web.Backend.Cfg.TimeFormat),
 56+			Status: curpr.Status,
 57+		}
 58+		prdata = append(prdata, prls)
 59+	}
 60+
 61+	return prdata, nil
 62 }
 63 
 64-func repoListHandler(w http.ResponseWriter, r *http.Request) {
 65+func indexHandler(w http.ResponseWriter, r *http.Request) {
 66 	web, err := getWebCtx(r)
 67 	if err != nil {
 68 		w.WriteHeader(http.StatusInternalServerError)
 69 		return
 70 	}
 71 
 72-	repos, err := web.Pr.GetReposWithLatestPr()
 73+	prs, err := web.Pr.GetPatchRequests()
 74 	if err != nil {
 75-		web.Pr.Backend.Logger.Error("cannot get repos", "err", err)
 76+		web.Logger.Error("could not get prs", "err", err)
 77 		w.WriteHeader(http.StatusInternalServerError)
 78 		return
 79 	}
 80 
 81-	repoData := []RepoData{}
 82-	for _, repo := range repos {
 83-		var ls *PrListData
 84-		if repo.PatchRequest != nil {
 85-			curpr := repo.PatchRequest
 86-			pk, err := web.Backend.PubkeyToPublicKey(repo.User.Pubkey)
 87-			if err != nil {
 88-				w.WriteHeader(http.StatusUnprocessableEntity)
 89-				return
 90-			}
 91-			isAdmin := web.Backend.IsAdmin(pk)
 92-			ls = &PrListData{
 93-				ID: curpr.ID,
 94-				UserData: UserData{
 95-					Name:    repo.User.Name,
 96-					IsAdmin: isAdmin,
 97-					Pubkey:  repo.User.Pubkey,
 98-				},
 99-				LinkData: LinkData{
100-					Url:  template.URL(fmt.Sprintf("/prs/%d", curpr.ID)),
101-					Text: curpr.Name,
102-				},
103-				Date:   curpr.CreatedAt.Format(web.Backend.Cfg.TimeFormat),
104-				Status: curpr.Status,
105-			}
106-		}
107-
108-		d := RepoData{
109-			Desc: repo.Desc,
110-			LinkData: LinkData{
111-				Url:  template.URL("/repos/" + repo.ID),
112-				Text: repo.ID,
113-			},
114-			LatestPr: ls,
115-		}
116-		repoData = append(repoData, d)
117+	prdata, err := getPrTableData(web, prs)
118+	if err != nil {
119+		web.Logger.Error("could not get pr table data", "err", err)
120+		w.WriteHeader(http.StatusInternalServerError)
121+		return
122 	}
123 
124 	w.Header().Set("content-type", "text/html")
125-	tmpl := getTemplate("repo-list.html")
126-	err = tmpl.Execute(w, RepoListData{
127-		Repos: repoData,
128+	tmpl := getTemplate("index.html")
129+	err = tmpl.Execute(w, PrTableData{
130+		Prs: prdata,
131 		MetaData: MetaData{
132 			URL: web.Backend.Cfg.Url,
133 		},
134@@ -180,22 +183,22 @@ type MetaData struct {
135 }
136 
137 type PrListData struct {
138-	LinkData
139 	UserData
140-	ID     int64
141-	Date   string
142-	Status string
143+	RepoID   string
144+	RepoLink LinkData
145+	PrLink   LinkData
146+	Title    string
147+	ID       int64
148+	Date     string
149+	Status   string
150 }
151 
152 type RepoDetailData struct {
153-	ID          string
154-	CloneAddr   string
155-	Branch      string
156-	Desc        string
157-	OpenPrs     []PrListData
158-	AcceptedPrs []PrListData
159-	ClosedPrs   []PrListData
160-	ReviewedPrs []PrListData
161+	ID        string
162+	CloneAddr string
163+	Branch    string
164+	Desc      string
165+	Prs       []*PrListData
166 	MetaData
167 }
168 
169@@ -223,57 +226,21 @@ func repoDetailHandler(w http.ResponseWriter, r *http.Request) {
170 		return
171 	}
172 
173-	openList := []PrListData{}
174-	reviewedList := []PrListData{}
175-	acceptedList := []PrListData{}
176-	closedList := []PrListData{}
177-	for _, curpr := range prs {
178-		user, err := web.Pr.GetUserByID(curpr.UserID)
179-		if err != nil {
180-			continue
181-		}
182-		pk, err := web.Backend.PubkeyToPublicKey(user.Pubkey)
183-		if err != nil {
184-			w.WriteHeader(http.StatusUnprocessableEntity)
185-			return
186-		}
187-		isAdmin := web.Backend.IsAdmin(pk)
188-		ls := PrListData{
189-			ID: curpr.ID,
190-			UserData: UserData{
191-				Name:    user.Name,
192-				IsAdmin: isAdmin,
193-				Pubkey:  user.Pubkey,
194-			},
195-			LinkData: LinkData{
196-				Url:  template.URL(fmt.Sprintf("/prs/%d", curpr.ID)),
197-				Text: curpr.Name,
198-			},
199-			Date:   curpr.CreatedAt.Format(web.Backend.Cfg.TimeFormat),
200-			Status: curpr.Status,
201-		}
202-		if curpr.Status == "open" {
203-			openList = append(openList, ls)
204-		} else if curpr.Status == "accepted" {
205-			acceptedList = append(acceptedList, ls)
206-		} else if curpr.Status == "reviewed" {
207-			reviewedList = append(reviewedList, ls)
208-		} else {
209-			closedList = append(closedList, ls)
210-		}
211+	prdata, err := getPrTableData(web, prs)
212+	if err != nil {
213+		web.Logger.Error("cannot get pr table data", "err", err)
214+		w.WriteHeader(http.StatusInternalServerError)
215+		return
216 	}
217 
218 	w.Header().Set("content-type", "text/html")
219 	tmpl := getTemplate("repo-detail.html")
220 	err = tmpl.Execute(w, RepoDetailData{
221-		ID:          repo.ID,
222-		CloneAddr:   repo.CloneAddr,
223-		Desc:        repo.Desc,
224-		Branch:      repo.DefaultBranch,
225-		OpenPrs:     openList,
226-		AcceptedPrs: acceptedList,
227-		ClosedPrs:   closedList,
228-		ReviewedPrs: reviewedList,
229+		ID:        repo.ID,
230+		CloneAddr: repo.CloneAddr,
231+		Desc:      repo.Desc,
232+		Branch:    repo.DefaultBranch,
233+		Prs:       prdata,
234 		MetaData: MetaData{
235 			URL: web.Backend.Cfg.Url,
236 		},
237@@ -737,7 +704,7 @@ func StartWebServer(cfg *GitCfg) {
238 	http.HandleFunc("GET /prs/{id}/rss", ctxMdw(ctx, rssHandler))
239 	http.HandleFunc("GET /repos/{id}", ctxMdw(ctx, repoDetailHandler))
240 	http.HandleFunc("GET /repos/{repoid}/rss", ctxMdw(ctx, rssHandler))
241-	http.HandleFunc("GET /", ctxMdw(ctx, repoListHandler))
242+	http.HandleFunc("GET /", ctxMdw(ctx, indexHandler))
243 	http.HandleFunc("GET /syntax.css", ctxMdw(ctx, chromaStyleHandler))
244 	http.HandleFunc("GET /rss", ctxMdw(ctx, rssHandler))
245 	embedFS, err := getEmbedFS(embedStaticFS, "static")