appview: implement pagination for pipelines index #521

closed
opened by ptr.pet targeting master from ptr.pet/core: pipeline-paginated
Changed files
+78 -14
appview
db
pages
templates
repo
pipelines
pipelines
+34 -12
appview/db/pipeline.go
···
}
query := fmt.Sprintf(`
+
with ranked_pipelines as (
+
select
+
p.id,
+
p.knot,
+
p.rkey,
+
p.repo_owner,
+
p.repo_name,
+
p.sha,
+
p.created,
+
t.id,
+
t.kind,
+
t.push_ref,
+
t.push_new_sha,
+
t.push_old_sha,
+
t.pr_source_branch,
+
t.pr_target_branch,
+
t.pr_source_sha,
+
t.pr_action,
+
row_number() over (order by p.created desc) as row_num
+
from
+
pipelines p
+
join
+
triggers t ON p.trigger_id = t.id
+
)
select
p.id,
p.knot,
···
p.repo_name,
p.sha,
p.created,
-
t.id,
-
t.kind,
-
t.push_ref,
-
t.push_new_sha,
-
t.push_old_sha,
-
t.pr_source_branch,
-
t.pr_target_branch,
-
t.pr_source_sha,
-
t.pr_action
+
p.id,
+
p.kind,
+
p.push_ref,
+
p.push_new_sha,
+
p.push_old_sha,
+
p.pr_source_branch,
+
p.pr_target_branch,
+
p.pr_source_sha,
+
p.pr_action
from
-
pipelines p
-
join
-
triggers t ON p.trigger_id = t.id
+
ranked_pipelines p
%s
`, whereClause)
+1
appview/pages/pages.go
···
LoggedInUser *oauth.User
RepoInfo repoinfo.RepoInfo
Pipelines []db.Pipeline
+
Page pagination.Page
Active string
+32 -1
appview/pages/templates/repo/pipelines/pipelines.html
···
{{ end }}
{{ define "repoContent" }}
-
<div class="flex justify-between items-center gap-4">
+
<div class="flex flex-col justify-between items-center gap-4">
<div class="w-full flex flex-col gap-2">
{{ range .Pipelines }}
{{ block "pipeline" (list $ .) }} {{ end }}
···
</p>
{{ end }}
</div>
+
{{ block "pagination" . }} {{ end }}
</div>
{{ end }}
···
</div>
{{ end }}
{{ end }}
+
+
{{ define "pagination" }}
+
<div class="flex place-self-end mt-4 gap-2">
+
{{ if gt .Page.Offset 0 }}
+
{{ $prev := .Page.Previous }}
+
<a
+
class="btn flex items-center gap-2 no-underline hover:no-underline dark:text-white dark:hover:bg-gray-700"
+
hx-boost="true"
+
href = "/{{ $.RepoInfo.FullName }}/pipelines?&offset={{ $prev.Offset }}&limit={{ $prev.Limit }}"
+
>
+
{{ i "chevron-left" "w-4 h-4" }}
+
previous
+
</a>
+
{{ else }}
+
<div></div>
+
{{ end }}
+
+
{{ if eq (len .Pipelines) .Page.Limit }}
+
{{ $next := .Page.Next }}
+
<a
+
class="btn flex items-center gap-2 no-underline hover:no-underline dark:text-white dark:hover:bg-gray-700"
+
hx-boost="true"
+
href = "/{{ $.RepoInfo.FullName }}/pipelines?offset={{ $next.Offset }}&limit={{ $next.Limit }}"
+
>
+
next
+
{{ i "chevron-right" "w-4 h-4" }}
+
</a>
+
{{ end }}
+
</div>
+
{{ end }}
+9
appview/pipelines/pipelines.go
···
"tangled.sh/tangled.sh/core/appview/db"
"tangled.sh/tangled.sh/core/appview/oauth"
"tangled.sh/tangled.sh/core/appview/pages"
+
"tangled.sh/tangled.sh/core/appview/pagination"
"tangled.sh/tangled.sh/core/appview/reporesolver"
"tangled.sh/tangled.sh/core/eventconsumer"
"tangled.sh/tangled.sh/core/idresolver"
···
return
}
+
page, ok := r.Context().Value("page").(pagination.Page)
+
if !ok {
+
l.Error("failed to get page")
+
page = pagination.FirstPage(16)
+
}
+
repoInfo := f.RepoInfo(user)
ps, err := db.GetPipelineStatuses(
···
db.FilterEq("repo_owner", repoInfo.OwnerDid),
db.FilterEq("repo_name", repoInfo.Name),
db.FilterEq("knot", repoInfo.Knot),
+
db.FilterBetween("row_num", page.Offset+1, page.Offset+page.Limit),
)
if err != nil {
l.Error("failed to query db", "err", err)
···
p.pages.Pipelines(w, pages.PipelinesParams{
LoggedInUser: user,
RepoInfo: repoInfo,
+
Page: page,
Pipelines: ps,
})
}
+2 -1
appview/pipelines/router.go
···
"github.com/go-chi/chi/v5"
"tangled.sh/tangled.sh/core/appview/middleware"
+
"tangled.sh/tangled.sh/core/appview/pagination"
)
func (p *Pipelines) Router(mw *middleware.Middleware) http.Handler {
r := chi.NewRouter()
-
r.Get("/", p.Index)
+
r.With(middleware.Paginate(pagination.FirstPage(16))).Get("/", p.Index)
r.Get("/{pipeline}/workflow/{workflow}", p.Workflow)
r.Get("/{pipeline}/workflow/{workflow}/logs", p.Logs)