forked from tangled.org/core
this repo has no description

more progress on patches

- fix up filters
- fix missing icons bug
- fix missing close button

authored by oppi.li and committed by anirudh.fi c2f38ac4 52eb05db

Changed files
+111 -56
appview
db
pages
templates
state
+1 -1
appview/db/db.go
··· 114 pull_at text, 115 rkey text not null, 116 target_branch text not null, 117 - open integer not null default 1, 118 created text not null default (strftime('%Y-%m-%dT%H:%M:%SZ', 'now')), 119 unique(repo_at, pull_id), 120 foreign key (repo_at) references repos(at_uri) on delete cascade
··· 114 pull_at text, 115 rkey text not null, 116 target_branch text not null, 117 + state integer not null default 0 check (state in (0, 1, 2)), -- open, merged, closed 118 created text not null default (strftime('%Y-%m-%dT%H:%M:%SZ', 'now')), 119 unique(repo_at, pull_id), 120 foreign key (repo_at) references repos(at_uri) on delete cascade
+70 -15
appview/db/pulls.go
··· 7 "github.com/bluesky-social/indigo/atproto/syntax" 8 ) 9 10 type Pull struct { 11 ID int 12 OwnerDid string ··· 17 PullId int 18 Title string 19 Body string 20 - Open int 21 Created time.Time 22 Rkey string 23 } ··· 89 return pullId - 1, err 90 } 91 92 - func GetPulls(e Execer, repoAt syntax.ATURI) ([]Pull, error) { 93 var pulls []Pull 94 95 - rows, err := e.Query(`select owner_did, pull_id, created, title, open, target_branch, pull_at, body, patch, rkey from pulls where repo_at = ? order by created desc`, repoAt) 96 if err != nil { 97 return nil, err 98 } ··· 101 for rows.Next() { 102 var pull Pull 103 var createdAt string 104 - err := rows.Scan(&pull.OwnerDid, &pull.PullId, &createdAt, &pull.Title, &pull.Open, &pull.TargetBranch, &pull.PullAt, &pull.Body, &pull.Patch, &pull.Rkey) 105 if err != nil { 106 return nil, err 107 } ··· 123 } 124 125 func GetPull(e Execer, repoAt syntax.ATURI, pullId int) (*Pull, error) { 126 - query := `select owner_did, created, title, open, target_branch, pull_at, body, patch, rkey from pulls where repo_at = ? and pull_id = ?` 127 row := e.QueryRow(query, repoAt, pullId) 128 129 var pull Pull 130 var createdAt string 131 - err := row.Scan(&pull.OwnerDid, &createdAt, &pull.Title, &pull.Open, &pull.TargetBranch, &pull.PullAt, &pull.Body, &pull.Patch, &pull.Rkey) 132 if err != nil { 133 return nil, err 134 } ··· 143 } 144 145 func GetPullWithComments(e Execer, repoAt syntax.ATURI, pullId int) (*Pull, []PullComment, error) { 146 - query := `select owner_did, pull_id, created, title, open, target_branch, pull_at, body, patch, rkey from pulls where repo_at = ? and pull_id = ?` 147 row := e.QueryRow(query, repoAt, pullId) 148 149 var pull Pull 150 var createdAt string 151 - err := row.Scan(&pull.OwnerDid, &pull.PullId, &createdAt, &pull.Title, &pull.Open, &pull.TargetBranch, &pull.PullAt, &pull.Body, &pull.Patch, &pull.Rkey) 152 if err != nil { 153 return nil, nil, err 154 } ··· 217 return comments, nil 218 } 219 220 func ClosePull(e Execer, repoAt syntax.ATURI, pullId int) error { 221 - _, err := e.Exec(`update pulls set open = 0 where repo_at = ? and pull_id = ?`, repoAt, pullId) 222 return err 223 } 224 225 func ReopenPull(e Execer, repoAt syntax.ATURI, pullId int) error { 226 - _, err := e.Exec(`update pulls set open = 1 where repo_at = ? and pull_id = ?`, repoAt, pullId) 227 return err 228 } 229 230 func MergePull(e Execer, repoAt syntax.ATURI, pullId int) error { 231 - _, err := e.Exec(`update pulls set open = 2 where repo_at = ? and pull_id = ?`, repoAt, pullId) 232 return err 233 } 234 235 type PullCount struct { 236 Open int 237 Closed int 238 } 239 240 func GetPullCount(e Execer, repoAt syntax.ATURI) (PullCount, error) { 241 row := e.QueryRow(` 242 select 243 - count(case when open = 1 then 1 end) as open_count, 244 - count(case when open = 0 then 1 end) as closed_count 245 from pulls 246 where repo_at = ?`, 247 repoAt, 248 ) 249 250 var count PullCount 251 - if err := row.Scan(&count.Open, &count.Closed); err != nil { 252 - return PullCount{0, 0}, err 253 } 254 255 return count, nil
··· 7 "github.com/bluesky-social/indigo/atproto/syntax" 8 ) 9 10 + type PullState int 11 + 12 + const ( 13 + PullOpen PullState = iota 14 + PullMerged 15 + PullClosed 16 + ) 17 + 18 + func (p PullState) String() string { 19 + switch p { 20 + case PullOpen: 21 + return "open" 22 + case PullMerged: 23 + return "merged" 24 + case PullClosed: 25 + return "closed" 26 + default: 27 + return "closed" 28 + } 29 + } 30 + 31 + func (p PullState) IsOpen() bool { 32 + return p == PullOpen 33 + } 34 + func (p PullState) IsMerged() bool { 35 + return p == PullMerged 36 + } 37 + func (p PullState) IsClosed() bool { 38 + return p == PullClosed 39 + } 40 + 41 type Pull struct { 42 ID int 43 OwnerDid string ··· 48 PullId int 49 Title string 50 Body string 51 + State PullState 52 Created time.Time 53 Rkey string 54 } ··· 120 return pullId - 1, err 121 } 122 123 + func GetPulls(e Execer, repoAt syntax.ATURI, state PullState) ([]Pull, error) { 124 var pulls []Pull 125 126 + rows, err := e.Query(` 127 + select 128 + owner_did, 129 + pull_id, 130 + created, 131 + title, 132 + state, 133 + target_branch, 134 + pull_at, 135 + body, 136 + patch, 137 + rkey 138 + from 139 + pulls 140 + where 141 + repo_at = ? and state = ? 142 + order by 143 + created desc`, repoAt, state) 144 if err != nil { 145 return nil, err 146 } ··· 149 for rows.Next() { 150 var pull Pull 151 var createdAt string 152 + err := rows.Scan(&pull.OwnerDid, &pull.PullId, &createdAt, &pull.Title, &pull.State, &pull.TargetBranch, &pull.PullAt, &pull.Body, &pull.Patch, &pull.Rkey) 153 if err != nil { 154 return nil, err 155 } ··· 171 } 172 173 func GetPull(e Execer, repoAt syntax.ATURI, pullId int) (*Pull, error) { 174 + query := `select owner_did, created, title, state, target_branch, pull_at, body, patch, rkey from pulls where repo_at = ? and pull_id = ?` 175 row := e.QueryRow(query, repoAt, pullId) 176 177 var pull Pull 178 var createdAt string 179 + err := row.Scan(&pull.OwnerDid, &createdAt, &pull.Title, &pull.State, &pull.TargetBranch, &pull.PullAt, &pull.Body, &pull.Patch, &pull.Rkey) 180 if err != nil { 181 return nil, err 182 } ··· 191 } 192 193 func GetPullWithComments(e Execer, repoAt syntax.ATURI, pullId int) (*Pull, []PullComment, error) { 194 + query := `select owner_did, pull_id, created, title, state, target_branch, pull_at, body, patch, rkey from pulls where repo_at = ? and pull_id = ?` 195 row := e.QueryRow(query, repoAt, pullId) 196 197 var pull Pull 198 var createdAt string 199 + err := row.Scan(&pull.OwnerDid, &pull.PullId, &createdAt, &pull.Title, &pull.State, &pull.TargetBranch, &pull.PullAt, &pull.Body, &pull.Patch, &pull.Rkey) 200 if err != nil { 201 return nil, nil, err 202 } ··· 265 return comments, nil 266 } 267 268 + func SetPullState(e Execer, repoAt syntax.ATURI, pullId int, pullState PullState) error { 269 + _, err := e.Exec(`update pulls set state = ? where repo_at = ? and pull_id = ?`, pullState, repoAt, pullId) 270 + return err 271 + } 272 + 273 func ClosePull(e Execer, repoAt syntax.ATURI, pullId int) error { 274 + err := SetPullState(e, repoAt, pullId, PullClosed) 275 return err 276 } 277 278 func ReopenPull(e Execer, repoAt syntax.ATURI, pullId int) error { 279 + err := SetPullState(e, repoAt, pullId, PullOpen) 280 return err 281 } 282 283 func MergePull(e Execer, repoAt syntax.ATURI, pullId int) error { 284 + err := SetPullState(e, repoAt, pullId, PullMerged) 285 return err 286 } 287 288 type PullCount struct { 289 Open int 290 + Merged int 291 Closed int 292 } 293 294 func GetPullCount(e Execer, repoAt syntax.ATURI) (PullCount, error) { 295 row := e.QueryRow(` 296 select 297 + count(case when state = 0 then 1 end) as open_count, 298 + count(case when state = 1 then 1 end) as merged_count, 299 + count(case when state = 2 then 1 end) as closed_count 300 from pulls 301 where repo_at = ?`, 302 repoAt, 303 ) 304 305 var count PullCount 306 + if err := row.Scan(&count.Open, &count.Merged, &count.Closed); err != nil { 307 + return PullCount{0, 0, 0}, err 308 } 309 310 return count, nil
+1
appview/db/repos.go
··· 246 type RepoStats struct { 247 StarCount int 248 IssueCount IssueCount 249 } 250 251 func scanRepo(rows *sql.Rows, did, name, knot, rkey, description *string, created *time.Time) error {
··· 246 type RepoStats struct { 247 StarCount int 248 IssueCount IssueCount 249 + PullCount PullCount 250 } 251 252 func scanRepo(rows *sql.Rows, did, name, knot, rkey, description *string, created *time.Time) error {
+2 -9
appview/pages/pages.go
··· 272 meta := make(map[string]any) 273 274 meta["issues"] = r.Stats.IssueCount.Open 275 276 // more stuff? 277 ··· 524 Pulls []db.Pull 525 Active string 526 DidHandleMap map[string]string 527 } 528 529 func (p *Pages) RepoPulls(w io.Writer, params RepoPullsParams) error { ··· 536 RepoInfo RepoInfo 537 DidHandleMap map[string]string 538 Pull db.Pull 539 - State string 540 PullOwnerHandle string 541 Comments []db.PullComment 542 Active string ··· 544 } 545 546 func (p *Pages) RepoSinglePull(w io.Writer, params RepoSinglePullParams) error { 547 - switch params.Pull.Open { 548 - case 0: 549 - params.State = "close" 550 - case 1: 551 - params.State = "open" 552 - case 2: 553 - params.State = "merged" 554 - } 555 params.Active = "pulls" 556 return p.executeRepo("repo/pulls/pull", w, params) 557 }
··· 272 meta := make(map[string]any) 273 274 meta["issues"] = r.Stats.IssueCount.Open 275 + meta["pulls"] = r.Stats.PullCount.Open 276 277 // more stuff? 278 ··· 525 Pulls []db.Pull 526 Active string 527 DidHandleMap map[string]string 528 + FilteringBy db.PullState 529 } 530 531 func (p *Pages) RepoPulls(w io.Writer, params RepoPullsParams) error { ··· 538 RepoInfo RepoInfo 539 DidHandleMap map[string]string 540 Pull db.Pull 541 PullOwnerHandle string 542 Comments []db.PullComment 543 Active string ··· 545 } 546 547 func (p *Pages) RepoSinglePull(w io.Writer, params RepoSinglePullParams) error { 548 params.Active = "pulls" 549 return p.executeRepo("repo/pulls/pull", w, params) 550 }
+1 -1
appview/pages/templates/repo/pulls/new.html
··· 15 <p class="text-gray-500"> 16 The branch you want to make your change against. 17 </p> 18 - <select class="p-1 border border-gray-200 bg-white"> 19 <option disabled selected>Select a branch</option> 20 {{ range .Branches }} 21 <option
··· 15 <p class="text-gray-500"> 16 The branch you want to make your change against. 17 </p> 18 + <select name="targetBranch" class="p-1 border border-gray-200 bg-white"> 19 <option disabled selected>Select a branch</option> 20 {{ range .Branches }} 21 <option
+9 -7
appview/pages/templates/repo/pulls/pull.html
··· 14 15 {{ $bgColor := "bg-gray-800" }} 16 {{ $icon := "ban" }} 17 - {{ if eq .State "open" }} 18 {{ $bgColor = "bg-green-600" }} 19 {{ $icon = "circle-dot" }} 20 - {{ else if eq .State "merged" }} 21 {{ $bgColor = "bg-purple-600" }} 22 {{ $icon = "git-merge" }} 23 {{ end }} ··· 33 data-lucide="{{ $icon }}" 34 class="w-4 h-4 mr-1.5 text-white" 35 ></i> 36 - <span class="text-white">{{ .State }}</span> 37 </div> 38 <span class="text-gray-400 text-sm"> 39 opened by ··· 41 <a href="/{{ $owner }}" class="no-underline hover:underline" 42 >{{ $owner }}</a 43 > 44 - <span class="px-1 select-none before:content-['\00B7']"></span> 45 <time>{{ .Pull.Created | timeFmt }}</time> 46 </span> 47 </div> 48 ··· 257 {{ $action := "close" }} 258 {{ $icon := "circle-x" }} 259 {{ $hoverColor := "red" }} 260 - {{ if eq .State "closed" }} 261 {{ $action = "reopen" }} 262 {{ $icon = "circle-dot" }} 263 {{ $hoverColor = "green" }} ··· 265 <form 266 hx-post="/{{ .RepoInfo.FullName }}/pulls/{{ .Pull.PullId }}/{{ $action }}" 267 hx-swap="none" 268 - class="mt-8" 269 - > 270 <button type="submit" class="btn hover:bg-{{ $hoverColor }}-300"> 271 <i 272 data-lucide="{{ $icon }}"
··· 14 15 {{ $bgColor := "bg-gray-800" }} 16 {{ $icon := "ban" }} 17 + 18 + {{ if .Pull.State.IsOpen }} 19 {{ $bgColor = "bg-green-600" }} 20 {{ $icon = "circle-dot" }} 21 + {{ else if .Pull.State.IsMerged }} 22 {{ $bgColor = "bg-purple-600" }} 23 {{ $icon = "git-merge" }} 24 {{ end }} ··· 34 data-lucide="{{ $icon }}" 35 class="w-4 h-4 mr-1.5 text-white" 36 ></i> 37 + <span class="text-white">{{ .Pull.State.String }}</span> 38 </div> 39 <span class="text-gray-400 text-sm"> 40 opened by ··· 42 <a href="/{{ $owner }}" class="no-underline hover:underline" 43 >{{ $owner }}</a 44 > 45 + <span class="select-none before:content-['\00B7']"></span> 46 <time>{{ .Pull.Created | timeFmt }}</time> 47 + <span class="select-none before:content-['\00B7']"></span> 48 + <time>targeting branch {{ .Pull.TargetBranch }}</time> 49 </span> 50 </div> 51 ··· 260 {{ $action := "close" }} 261 {{ $icon := "circle-x" }} 262 {{ $hoverColor := "red" }} 263 + {{ if .Pull.State.IsClosed }} 264 {{ $action = "reopen" }} 265 {{ $icon = "circle-dot" }} 266 {{ $hoverColor = "green" }} ··· 268 <form 269 hx-post="/{{ .RepoInfo.FullName }}/pulls/{{ .Pull.PullId }}/{{ $action }}" 270 hx-swap="none" 271 + class="mt-8"> 272 <button type="submit" class="btn hover:bg-{{ $hoverColor }}-300"> 273 <i 274 data-lucide="{{ $icon }}"
+9 -21
appview/pages/templates/repo/pulls/pulls.html
··· 8 class="border px-1 bg-white border-gray-200" 9 onchange="window.location.href = '/{{ .RepoInfo.FullName }}/pulls?state=' + this.value" 10 > 11 - <option value="open" {{ if .FilteringByOpen }}selected{{ end }}> 12 open 13 </option> 14 - <option 15 - value="closed" 16 - {{ if eq .FilteringState "closed" }}selected{{ end }} 17 - > 18 - closed 19 - </option> 20 - <option 21 - value="merged" 22 - {{ if eq .FilteringState "merged" }}selected{{ end }} 23 - > 24 merged 25 </option> 26 </select> 27 pull requests 28 </p> ··· 42 {{ range .Pulls }} 43 <div class="rounded drop-shadow-sm bg-white px-6 py-4"> 44 <div class="pb-2"> 45 - <a 46 - href="/{{ $.RepoInfo.FullName }}/pulls/{{ .PullId }}" 47 - class="no-underline hover:underline" 48 - > 49 {{ .Title }} 50 <span class="text-gray-500">#{{ .PullId }}</span> 51 </a> ··· 53 <p class="text-sm text-gray-500"> 54 {{ $bgColor := "bg-gray-800" }} 55 {{ $icon := "ban" }} 56 - {{ $state := "closed" }} 57 58 - {{ if eq .Open 1 }} 59 {{ $bgColor = "bg-green-600" }} 60 {{ $icon = "git-pull-request" }} 61 - {{ $state = "open" }} 62 - {{ else if eq .Open 2 }} 63 {{ $bgColor = "bg-purple-600" }} 64 {{ $icon = "git-merge" }} 65 - {{ $state = "merged" }} 66 {{ end }} 67 68 ··· 73 data-lucide="{{ $icon }}" 74 class="w-3 h-3 mr-1.5 text-white" 75 ></i> 76 - <span class="text-white">{{ $state }}</span> 77 </span> 78 79 <span>
··· 8 class="border px-1 bg-white border-gray-200" 9 onchange="window.location.href = '/{{ .RepoInfo.FullName }}/pulls?state=' + this.value" 10 > 11 + <option value="open" {{ if .FilteringBy.IsOpen }}selected{{ end }}> 12 open 13 </option> 14 + <option value="merged" {{ if .FilteringBy.IsMerged }}selected{{ end }}> 15 merged 16 </option> 17 + <option value="closed" {{ if .FilteringBy.IsClosed }}selected{{ end }}> 18 + closed 19 + </option> 20 </select> 21 pull requests 22 </p> ··· 36 {{ range .Pulls }} 37 <div class="rounded drop-shadow-sm bg-white px-6 py-4"> 38 <div class="pb-2"> 39 + <a href="/{{ $.RepoInfo.FullName }}/pulls/{{ .PullId }}"> 40 {{ .Title }} 41 <span class="text-gray-500">#{{ .PullId }}</span> 42 </a> ··· 44 <p class="text-sm text-gray-500"> 45 {{ $bgColor := "bg-gray-800" }} 46 {{ $icon := "ban" }} 47 48 + {{ if .State.IsOpen }} 49 {{ $bgColor = "bg-green-600" }} 50 {{ $icon = "git-pull-request" }} 51 + {{ else if .State.IsMerged }} 52 {{ $bgColor = "bg-purple-600" }} 53 {{ $icon = "git-merge" }} 54 {{ end }} 55 56 ··· 61 data-lucide="{{ $icon }}" 62 class="w-3 h-3 mr-1.5 text-white" 63 ></i> 64 + <span class="text-white">{{ .State.String }}</span> 65 </span> 66 67 <span>
+18 -2
appview/state/repo.go
··· 413 targetBranch := r.FormValue("targetBranch") 414 patch := r.FormValue("patch") 415 416 - if title == "" || body == "" || patch == "" { 417 s.pages.Notice(w, "pull", "Title, body and patch diff are required.") 418 return 419 } ··· 990 if err != nil { 991 log.Println("failed to get issue count for ", f.RepoAt) 992 } 993 994 knot := f.Knot 995 if knot == "knot1.tangled.sh" { ··· 1008 Stats: db.RepoStats{ 1009 StarCount: starCount, 1010 IssueCount: issueCount, 1011 }, 1012 } 1013 } ··· 1383 1384 func (s *State) RepoPulls(w http.ResponseWriter, r *http.Request) { 1385 user := s.auth.GetUser(r) 1386 f, err := fullyResolvedRepo(r) 1387 if err != nil { 1388 log.Println("failed to get repo and knot", err) 1389 return 1390 } 1391 1392 - pulls, err := db.GetPulls(s.db, f.RepoAt) 1393 if err != nil { 1394 log.Println("failed to get pulls", err) 1395 s.pages.Notice(w, "pulls", "Failed to load pulls. Try again later.") ··· 1415 RepoInfo: f.RepoInfo(s, user), 1416 Pulls: pulls, 1417 DidHandleMap: didHandleMap, 1418 }) 1419 return 1420 }
··· 413 targetBranch := r.FormValue("targetBranch") 414 patch := r.FormValue("patch") 415 416 + if title == "" || body == "" || patch == "" || targetBranch == "" { 417 s.pages.Notice(w, "pull", "Title, body and patch diff are required.") 418 return 419 } ··· 990 if err != nil { 991 log.Println("failed to get issue count for ", f.RepoAt) 992 } 993 + pullCount, err := db.GetPullCount(s.db, f.RepoAt) 994 + if err != nil { 995 + log.Println("failed to get issue count for ", f.RepoAt) 996 + } 997 998 knot := f.Knot 999 if knot == "knot1.tangled.sh" { ··· 1012 Stats: db.RepoStats{ 1013 StarCount: starCount, 1014 IssueCount: issueCount, 1015 + PullCount: pullCount, 1016 }, 1017 } 1018 } ··· 1388 1389 func (s *State) RepoPulls(w http.ResponseWriter, r *http.Request) { 1390 user := s.auth.GetUser(r) 1391 + params := r.URL.Query() 1392 + 1393 + state := db.PullOpen 1394 + switch params.Get("state") { 1395 + case "closed": 1396 + state = db.PullClosed 1397 + case "merged": 1398 + state = db.PullMerged 1399 + } 1400 + 1401 f, err := fullyResolvedRepo(r) 1402 if err != nil { 1403 log.Println("failed to get repo and knot", err) 1404 return 1405 } 1406 1407 + pulls, err := db.GetPulls(s.db, f.RepoAt, state) 1408 if err != nil { 1409 log.Println("failed to get pulls", err) 1410 s.pages.Notice(w, "pulls", "Failed to load pulls. Try again later.") ··· 1430 RepoInfo: f.RepoInfo(s, user), 1431 Pulls: pulls, 1432 DidHandleMap: didHandleMap, 1433 + FilteringBy: state, 1434 }) 1435 return 1436 }