Signed-off-by: dusk y.bera003.06@protonmail.com
+2
-2
appview/db/artifact.go
+2
-2
appview/db/artifact.go
···
57
57
return err
58
58
}
59
59
60
-
func GetArtifact(e Execer, filters ...filter) ([]Artifact, error) {
60
+
func GetArtifact(e Execer, filters ...Filter) ([]Artifact, error) {
61
61
var artifacts []Artifact
62
62
63
63
var conditions []string
···
130
130
return artifacts, nil
131
131
}
132
132
133
-
func DeleteArtifact(e Execer, filters ...filter) error {
133
+
func DeleteArtifact(e Execer, filters ...Filter) error {
134
134
var conditions []string
135
135
var args []any
136
136
for _, filter := range filters {
+1
-1
appview/db/collaborators.go
+1
-1
appview/db/collaborators.go
+13
-13
appview/db/db.go
+13
-13
appview/db/db.go
···
918
918
return d.DB.Close()
919
919
}
920
920
921
-
type filter struct {
921
+
type Filter struct {
922
922
key string
923
923
arg any
924
924
cmp string
925
925
}
926
926
927
-
func newFilter(key, cmp string, arg any) filter {
928
-
return filter{
927
+
func newFilter(key, cmp string, arg any) Filter {
928
+
return Filter{
929
929
key: key,
930
930
arg: arg,
931
931
cmp: cmp,
932
932
}
933
933
}
934
934
935
-
func FilterEq(key string, arg any) filter { return newFilter(key, "=", arg) }
936
-
func FilterNotEq(key string, arg any) filter { return newFilter(key, "<>", arg) }
937
-
func FilterGte(key string, arg any) filter { return newFilter(key, ">=", arg) }
938
-
func FilterLte(key string, arg any) filter { return newFilter(key, "<=", arg) }
939
-
func FilterIs(key string, arg any) filter { return newFilter(key, "is", arg) }
940
-
func FilterIsNot(key string, arg any) filter { return newFilter(key, "is not", arg) }
941
-
func FilterIn(key string, arg any) filter { return newFilter(key, "in", arg) }
942
-
func FilterBetween(key string, arg1, arg2 any) filter {
935
+
func FilterEq(key string, arg any) Filter { return newFilter(key, "=", arg) }
936
+
func FilterNotEq(key string, arg any) Filter { return newFilter(key, "<>", arg) }
937
+
func FilterGte(key string, arg any) Filter { return newFilter(key, ">=", arg) }
938
+
func FilterLte(key string, arg any) Filter { return newFilter(key, "<=", arg) }
939
+
func FilterIs(key string, arg any) Filter { return newFilter(key, "is", arg) }
940
+
func FilterIsNot(key string, arg any) Filter { return newFilter(key, "is not", arg) }
941
+
func FilterIn(key string, arg any) Filter { return newFilter(key, "in", arg) }
942
+
func FilterBetween(key string, arg1, arg2 any) Filter {
943
943
return newFilter(key, "between", []any{arg1, arg2})
944
944
}
945
945
946
-
func (f filter) Condition() string {
946
+
func (f Filter) Condition() string {
947
947
rv := reflect.ValueOf(f.arg)
948
948
kind := rv.Kind()
949
949
···
969
969
return fmt.Sprintf("%s %s ?", f.key, f.cmp)
970
970
}
971
971
972
-
func (f filter) Arg() []any {
972
+
func (f Filter) Arg() []any {
973
973
rv := reflect.ValueOf(f.arg)
974
974
kind := rv.Kind()
975
975
if (kind == reflect.Slice && rv.Type().Elem().Kind() != reflect.Uint8) || kind == reflect.Array {
+1
-1
appview/db/follow.go
+1
-1
appview/db/follow.go
+7
-7
appview/db/issues.go
+7
-7
appview/db/issues.go
···
245
245
return err
246
246
}
247
247
248
-
func GetIssuesPaginated(e Execer, page pagination.Page, filters ...filter) ([]Issue, error) {
248
+
func GetIssuesPaginated(e Execer, page pagination.Page, filters ...Filter) ([]Issue, error) {
249
249
issueMap := make(map[string]*Issue) // at-uri -> issue
250
250
251
251
var conditions []string
···
395
395
return issues, nil
396
396
}
397
397
398
-
func GetIssues(e Execer, filters ...filter) ([]Issue, error) {
398
+
func GetIssues(e Execer, filters ...Filter) ([]Issue, error) {
399
399
return GetIssuesPaginated(e, pagination.Page{No: 0, Count: 10}, filters...)
400
400
}
401
401
···
462
462
return id, nil
463
463
}
464
464
465
-
func DeleteIssueComments(e Execer, filters ...filter) error {
465
+
func DeleteIssueComments(e Execer, filters ...Filter) error {
466
466
var conditions []string
467
467
var args []any
468
468
for _, filter := range filters {
···
481
481
return err
482
482
}
483
483
484
-
func GetIssueComments(e Execer, filters ...filter) ([]IssueComment, error) {
484
+
func GetIssueComments(e Execer, filters ...Filter) ([]IssueComment, error) {
485
485
var comments []IssueComment
486
486
487
487
var conditions []string
···
571
571
return comments, nil
572
572
}
573
573
574
-
func DeleteIssues(e Execer, filters ...filter) error {
574
+
func DeleteIssues(e Execer, filters ...Filter) error {
575
575
var conditions []string
576
576
var args []any
577
577
for _, filter := range filters {
···
589
589
return err
590
590
}
591
591
592
-
func CloseIssues(e Execer, filters ...filter) error {
592
+
func CloseIssues(e Execer, filters ...Filter) error {
593
593
var conditions []string
594
594
var args []any
595
595
for _, filter := range filters {
···
607
607
return err
608
608
}
609
609
610
-
func ReopenIssues(e Execer, filters ...filter) error {
610
+
func ReopenIssues(e Execer, filters ...Filter) error {
611
611
var conditions []string
612
612
var args []any
613
613
for _, filter := range filters {
+1
-1
appview/db/language.go
+1
-1
appview/db/language.go
+62
-14
appview/db/pipeline.go
+62
-14
appview/db/pipeline.go
···
131
131
ExitCode int
132
132
}
133
133
134
-
func GetPipelines(e Execer, filters ...filter) ([]Pipeline, error) {
134
+
func GetPipelines(e Execer, filters ...Filter) ([]Pipeline, error) {
135
135
var pipelines []Pipeline
136
136
137
137
var conditions []string
···
290
290
291
291
// this is a mega query, but the most useful one:
292
292
// get N pipelines, for each one get the latest status of its N workflows
293
-
func GetPipelineStatuses(e Execer, filters ...filter) ([]Pipeline, error) {
293
+
func GetPipelineStatuses(e Execer, filters ...Filter) ([]Pipeline, error) {
294
294
var conditions []string
295
295
var args []any
296
296
for _, filter := range filters {
···
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
···
485
507
486
508
return all, nil
487
509
}
510
+
511
+
// get pipeline counts, implement with filters
512
+
func GetPipelineCount(e Execer, filters ...Filter) (int, error) {
513
+
var conditions []string
514
+
var args []any
515
+
for _, filter := range filters {
516
+
conditions = append(conditions, filter.Condition())
517
+
args = append(args, filter.Arg()...)
518
+
}
519
+
520
+
whereClause := ""
521
+
if conditions != nil {
522
+
whereClause = " where " + strings.Join(conditions, " and ")
523
+
}
524
+
525
+
query := fmt.Sprintf(`select count(*) as count from pipelines %s`, whereClause)
526
+
527
+
row := e.QueryRow(query, args...)
528
+
529
+
var count int
530
+
if err := row.Scan(&count); err != nil {
531
+
return 0, err
532
+
}
533
+
534
+
return count, nil
535
+
}
+1
-1
appview/db/profile.go
+1
-1
appview/db/profile.go
···
366
366
return tx.Commit()
367
367
}
368
368
369
-
func GetProfiles(e Execer, filters ...filter) (map[string]*Profile, error) {
369
+
func GetProfiles(e Execer, filters ...Filter) (map[string]*Profile, error) {
370
370
var conditions []string
371
371
var args []any
372
372
for _, filter := range filters {
+4
-4
appview/db/pulls.go
+4
-4
appview/db/pulls.go
···
311
311
return pullId - 1, err
312
312
}
313
313
314
-
func GetPullsWithLimit(e Execer, limit int, filters ...filter) ([]*Pull, error) {
314
+
func GetPullsWithLimit(e Execer, limit int, filters ...Filter) ([]*Pull, error) {
315
315
pulls := make(map[int]*Pull)
316
316
317
317
var conditions []string
···
529
529
return orderedByPullId, nil
530
530
}
531
531
532
-
func GetPulls(e Execer, filters ...filter) ([]*Pull, error) {
532
+
func GetPulls(e Execer, filters ...Filter) ([]*Pull, error) {
533
533
return GetPullsWithLimit(e, 0, filters...)
534
534
}
535
535
···
884
884
return err
885
885
}
886
886
887
-
func SetPullParentChangeId(e Execer, parentChangeId string, filters ...filter) error {
887
+
func SetPullParentChangeId(e Execer, parentChangeId string, filters ...Filter) error {
888
888
var conditions []string
889
889
var args []any
890
890
···
908
908
909
909
// Only used when stacking to update contents in the event of a rebase (the interdiff should be empty).
910
910
// otherwise submissions are immutable
911
-
func UpdatePull(e Execer, newPatch, sourceRev string, filters ...filter) error {
911
+
func UpdatePull(e Execer, newPatch, sourceRev string, filters ...Filter) error {
912
912
var conditions []string
913
913
var args []any
914
914
+1
-1
appview/db/punchcard.go
+1
-1
appview/db/punchcard.go
···
29
29
Punches []Punch
30
30
}
31
31
32
-
func MakePunchcard(e Execer, filters ...filter) (*Punchcard, error) {
32
+
func MakePunchcard(e Execer, filters ...Filter) (*Punchcard, error) {
33
33
punchcard := &Punchcard{}
34
34
now := time.Now()
35
35
startOfYear := time.Date(now.Year(), 1, 1, 0, 0, 0, 0, time.UTC)
+3
-3
appview/db/registration.go
+3
-3
appview/db/registration.go
···
48
48
NeedsUpgrade
49
49
)
50
50
51
-
func GetRegistrations(e Execer, filters ...filter) ([]Registration, error) {
51
+
func GetRegistrations(e Execer, filters ...Filter) ([]Registration, error) {
52
52
var registrations []Registration
53
53
54
54
var conditions []string
···
108
108
return registrations, nil
109
109
}
110
110
111
-
func MarkRegistered(e Execer, filters ...filter) error {
111
+
func MarkRegistered(e Execer, filters ...Filter) error {
112
112
var conditions []string
113
113
var args []any
114
114
for _, filter := range filters {
···
133
133
return err
134
134
}
135
135
136
-
func DeleteKnot(e Execer, filters ...filter) error {
136
+
func DeleteKnot(e Execer, filters ...Filter) error {
137
137
var conditions []string
138
138
var args []any
139
139
for _, filter := range filters {
+2
-2
appview/db/repos.go
+2
-2
appview/db/repos.go
···
39
39
return p
40
40
}
41
41
42
-
func GetRepos(e Execer, limit int, filters ...filter) ([]Repo, error) {
42
+
func GetRepos(e Execer, limit int, filters ...Filter) ([]Repo, error) {
43
43
repoMap := make(map[syntax.ATURI]*Repo)
44
44
45
45
var conditions []string
···
285
285
return repos, nil
286
286
}
287
287
288
-
func CountRepos(e Execer, filters ...filter) (int64, error) {
288
+
func CountRepos(e Execer, filters ...Filter) (int64, error) {
289
289
var conditions []string
290
290
var args []any
291
291
for _, filter := range filters {
+5
-5
appview/db/spindle.go
+5
-5
appview/db/spindle.go
···
27
27
Created time.Time
28
28
}
29
29
30
-
func GetSpindles(e Execer, filters ...filter) ([]Spindle, error) {
30
+
func GetSpindles(e Execer, filters ...Filter) ([]Spindle, error) {
31
31
var spindles []Spindle
32
32
33
33
var conditions []string
···
109
109
return err
110
110
}
111
111
112
-
func VerifySpindle(e Execer, filters ...filter) (int64, error) {
112
+
func VerifySpindle(e Execer, filters ...Filter) (int64, error) {
113
113
var conditions []string
114
114
var args []any
115
115
for _, filter := range filters {
···
132
132
return res.RowsAffected()
133
133
}
134
134
135
-
func DeleteSpindle(e Execer, filters ...filter) error {
135
+
func DeleteSpindle(e Execer, filters ...Filter) error {
136
136
var conditions []string
137
137
var args []any
138
138
for _, filter := range filters {
···
162
162
return err
163
163
}
164
164
165
-
func RemoveSpindleMember(e Execer, filters ...filter) error {
165
+
func RemoveSpindleMember(e Execer, filters ...Filter) error {
166
166
var conditions []string
167
167
var args []any
168
168
for _, filter := range filters {
···
181
181
return err
182
182
}
183
183
184
-
func GetSpindleMembers(e Execer, filters ...filter) ([]SpindleMember, error) {
184
+
func GetSpindleMembers(e Execer, filters ...Filter) ([]SpindleMember, error) {
185
185
var members []SpindleMember
186
186
187
187
var conditions []string
+2
-2
appview/db/star.go
+2
-2
appview/db/star.go
···
102
102
}
103
103
}
104
104
105
-
func GetStars(e Execer, limit int, filters ...filter) ([]Star, error) {
105
+
func GetStars(e Execer, limit int, filters ...Filter) ([]Star, error) {
106
106
var conditions []string
107
107
var args []any
108
108
for _, filter := range filters {
···
185
185
return stars, nil
186
186
}
187
187
188
-
func CountStars(e Execer, filters ...filter) (int64, error) {
188
+
func CountStars(e Execer, filters ...Filter) (int64, error) {
189
189
var conditions []string
190
190
var args []any
191
191
for _, filter := range filters {
+3
-3
appview/db/strings.go
+3
-3
appview/db/strings.go
···
123
123
return err
124
124
}
125
125
126
-
func GetStrings(e Execer, limit int, filters ...filter) ([]String, error) {
126
+
func GetStrings(e Execer, limit int, filters ...Filter) ([]String, error) {
127
127
var all []String
128
128
129
129
var conditions []string
···
206
206
return all, nil
207
207
}
208
208
209
-
func CountStrings(e Execer, filters ...filter) (int64, error) {
209
+
func CountStrings(e Execer, filters ...Filter) (int64, error) {
210
210
var conditions []string
211
211
var args []any
212
212
for _, filter := range filters {
···
230
230
return count, nil
231
231
}
232
232
233
-
func DeleteString(e Execer, filters ...filter) error {
233
+
func DeleteString(e Execer, filters ...Filter) error {
234
234
var conditions []string
235
235
var args []any
236
236
for _, filter := range filters {
+1
appview/pages/pages.go
+1
appview/pages/pages.go
+33
-1
appview/pages/templates/repo/pipelines/pipelines.html
+33
-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
+
{{ $currentPage := .Pagination.CurrentPage }}
107
+
<div class="flex place-self-end mt-4 gap-2">
108
+
{{ if gt $currentPage.No 0 }}
109
+
{{ $prev := .Pagination.PreviousPage }}
110
+
<a
111
+
class="btn flex items-center gap-2 no-underline hover:no-underline dark:text-white dark:hover:bg-gray-700"
112
+
hx-boost="true"
113
+
href = "/{{ $.RepoInfo.FullName }}/pipelines?page={{ add $prev.No 1 }}&count={{ $prev.Count }}"
114
+
>
115
+
{{ i "chevron-left" "w-4 h-4" }}
116
+
previous
117
+
</a>
118
+
{{ else }}
119
+
<div></div>
120
+
{{ end }}
121
+
122
+
{{ if lt (add $currentPage.No 1) .Pagination.TotalPageCount }}
123
+
{{ $next := .Pagination.NextPage }}
124
+
<a
125
+
class="btn flex items-center gap-2 no-underline hover:no-underline dark:text-white dark:hover:bg-gray-700"
126
+
hx-boost="true"
127
+
href = "/{{ $.RepoInfo.FullName }}/pipelines?page={{ add $next.No 1 }}&count={{ $next.Count }}"
128
+
>
129
+
next
130
+
{{ i "chevron-right" "w-4 h-4" }}
131
+
</a>
132
+
{{ end }}
133
+
</div>
134
+
{{ end }}
+29
-3
appview/pipelines/pipelines.go
+29
-3
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"
···
71
72
}
72
73
73
74
repoInfo := f.RepoInfo(user)
74
-
75
-
ps, err := db.GetPipelineStatuses(
76
-
p.db,
75
+
filters := []db.Filter{
77
76
db.FilterEq("repo_owner", repoInfo.OwnerDid),
78
77
db.FilterEq("repo_name", repoInfo.Name),
79
78
db.FilterEq("knot", repoInfo.Knot),
79
+
}
80
+
81
+
page, ok := r.Context().Value("page").(pagination.Page)
82
+
if !ok {
83
+
l.Error("failed to get page")
84
+
page = pagination.Page{No: 0, Count: 16}
85
+
}
86
+
pipelinesCount, err := db.GetPipelineCount(p.db, filters...)
87
+
if err != nil {
88
+
l.Error("failed to get pipeline count", "err", err)
89
+
p.pages.Notice(w, "pipelines", "Failed to load pipelines. Try again later.")
90
+
return
91
+
}
92
+
paginate := pagination.NewFromPage(page, pipelinesCount)
93
+
94
+
currentPage := paginate.CurrentPage()
95
+
filters = append(filters, db.FilterBetween(
96
+
"row_num",
97
+
currentPage.Count*currentPage.No+1,
98
+
currentPage.Count*(currentPage.No+1),
99
+
))
100
+
101
+
ps, err := db.GetPipelineStatuses(
102
+
p.db,
103
+
filters...,
80
104
)
81
105
if err != nil {
82
106
l.Error("failed to query db", "err", err)
107
+
p.pages.Notice(w, "pipelines", "Failed to load pipelines. Try again later.")
83
108
return
84
109
}
85
110
86
111
p.pages.Pipelines(w, pages.PipelinesParams{
87
112
LoggedInUser: user,
88
113
RepoInfo: repoInfo,
114
+
Pagination: paginate,
89
115
Pipelines: ps,
90
116
})
91
117
}
+1
-1
appview/pipelines/router.go
+1
-1
appview/pipelines/router.go
···
9
9
10
10
func (p *Pipelines) Router(mw *middleware.Middleware) http.Handler {
11
11
r := chi.NewRouter()
12
-
r.Get("/", p.Index)
12
+
r.With(middleware.Paginate(16)).Get("/", p.Index)
13
13
r.Get("/{pipeline}/workflow/{workflow}", p.Workflow)
14
14
r.Get("/{pipeline}/workflow/{workflow}/logs", p.Logs)
15
15