appview: implement pagination for pipelines index #521

closed
opened by ptr.pet targeting master from [deleted fork]: pipeline-paginated
Changed files
+78 -14
appview
db
pages
templates
repo
pipelines
pipelines
+34 -12
appview/db/pipeline.go
··· 305 305 } 306 306 307 307 query := fmt.Sprintf(` 308 + with ranked_pipelines as ( 309 + select 310 + p.id, 311 + p.knot, 312 + p.rkey, 313 + p.repo_owner, 314 + p.repo_name, 315 + p.sha, 316 + p.created, 317 + t.id, 318 + t.kind, 319 + t.push_ref, 320 + t.push_new_sha, 321 + t.push_old_sha, 322 + t.pr_source_branch, 323 + t.pr_target_branch, 324 + t.pr_source_sha, 325 + t.pr_action, 326 + row_number() over (order by p.created desc) as row_num 327 + from 328 + pipelines p 329 + join 330 + triggers t ON p.trigger_id = t.id 331 + ) 308 332 select 309 333 p.id, 310 334 p.knot, ··· 313 337 p.repo_name, 314 338 p.sha, 315 339 p.created, 316 - t.id, 317 - t.kind, 318 - t.push_ref, 319 - t.push_new_sha, 320 - t.push_old_sha, 321 - t.pr_source_branch, 322 - t.pr_target_branch, 323 - t.pr_source_sha, 324 - t.pr_action 340 + p.id, 341 + p.kind, 342 + p.push_ref, 343 + p.push_new_sha, 344 + p.push_old_sha, 345 + p.pr_source_branch, 346 + p.pr_target_branch, 347 + p.pr_source_sha, 348 + p.pr_action 325 349 from 326 - pipelines p 327 - join 328 - triggers t ON p.trigger_id = t.id 350 + ranked_pipelines p 329 351 %s 330 352 `, whereClause) 331 353
+1
appview/pages/pages.go
··· 1094 1094 LoggedInUser *oauth.User 1095 1095 RepoInfo repoinfo.RepoInfo 1096 1096 Pipelines []db.Pipeline 1097 + Page pagination.Page 1097 1098 Active string 1098 1099 } 1099 1100
+32 -1
appview/pages/templates/repo/pipelines/pipelines.html
··· 7 7 {{ end }} 8 8 9 9 {{ define "repoContent" }} 10 - <div class="flex justify-between items-center gap-4"> 10 + <div class="flex flex-col justify-between items-center gap-4"> 11 11 <div class="w-full flex flex-col gap-2"> 12 12 {{ range .Pipelines }} 13 13 {{ block "pipeline" (list $ .) }} {{ end }} ··· 17 17 </p> 18 18 {{ end }} 19 19 </div> 20 + {{ block "pagination" . }} {{ end }} 20 21 </div> 21 22 {{ end }} 22 23 ··· 100 101 </div> 101 102 {{ end }} 102 103 {{ end }} 104 + 105 + {{ define "pagination" }} 106 + <div class="flex place-self-end mt-4 gap-2"> 107 + {{ if gt .Page.Offset 0 }} 108 + {{ $prev := .Page.Previous }} 109 + <a 110 + class="btn flex items-center gap-2 no-underline hover:no-underline dark:text-white dark:hover:bg-gray-700" 111 + hx-boost="true" 112 + href = "/{{ $.RepoInfo.FullName }}/pipelines?&offset={{ $prev.Offset }}&limit={{ $prev.Limit }}" 113 + > 114 + {{ i "chevron-left" "w-4 h-4" }} 115 + previous 116 + </a> 117 + {{ else }} 118 + <div></div> 119 + {{ end }} 120 + 121 + {{ if eq (len .Pipelines) .Page.Limit }} 122 + {{ $next := .Page.Next }} 123 + <a 124 + class="btn flex items-center gap-2 no-underline hover:no-underline dark:text-white dark:hover:bg-gray-700" 125 + hx-boost="true" 126 + href = "/{{ $.RepoInfo.FullName }}/pipelines?offset={{ $next.Offset }}&limit={{ $next.Limit }}" 127 + > 128 + next 129 + {{ i "chevron-right" "w-4 h-4" }} 130 + </a> 131 + {{ end }} 132 + </div> 133 + {{ end }}
+9
appview/pipelines/pipelines.go
··· 13 13 "tangled.sh/tangled.sh/core/appview/db" 14 14 "tangled.sh/tangled.sh/core/appview/oauth" 15 15 "tangled.sh/tangled.sh/core/appview/pages" 16 + "tangled.sh/tangled.sh/core/appview/pagination" 16 17 "tangled.sh/tangled.sh/core/appview/reporesolver" 17 18 "tangled.sh/tangled.sh/core/eventconsumer" 18 19 "tangled.sh/tangled.sh/core/idresolver" ··· 70 71 return 71 72 } 72 73 74 + page, ok := r.Context().Value("page").(pagination.Page) 75 + if !ok { 76 + l.Error("failed to get page") 77 + page = pagination.FirstPage(16) 78 + } 79 + 73 80 repoInfo := f.RepoInfo(user) 74 81 75 82 ps, err := db.GetPipelineStatuses( ··· 77 84 db.FilterEq("repo_owner", repoInfo.OwnerDid), 78 85 db.FilterEq("repo_name", repoInfo.Name), 79 86 db.FilterEq("knot", repoInfo.Knot), 87 + db.FilterBetween("row_num", page.Offset+1, page.Offset+page.Limit), 80 88 ) 81 89 if err != nil { 82 90 l.Error("failed to query db", "err", err) ··· 86 94 p.pages.Pipelines(w, pages.PipelinesParams{ 87 95 LoggedInUser: user, 88 96 RepoInfo: repoInfo, 97 + Page: page, 89 98 Pipelines: ps, 90 99 }) 91 100 }
+2 -1
appview/pipelines/router.go
··· 5 5 6 6 "github.com/go-chi/chi/v5" 7 7 "tangled.sh/tangled.sh/core/appview/middleware" 8 + "tangled.sh/tangled.sh/core/appview/pagination" 8 9 ) 9 10 10 11 func (p *Pipelines) Router(mw *middleware.Middleware) http.Handler { 11 12 r := chi.NewRouter() 12 - r.Get("/", p.Index) 13 + r.With(middleware.Paginate(pagination.FirstPage(16))).Get("/", p.Index) 13 14 r.Get("/{pipeline}/workflow/{workflow}", p.Workflow) 14 15 r.Get("/{pipeline}/workflow/{workflow}/logs", p.Logs) 15 16