Skip to content

Commit 1454f9d

Browse files
authored
Add actor and status dropdowns to run list (#25118)
Part of #25042 1. Added actor and status dropdowns first in case something is offtrack and PR is too large. 2. Also added "No results matched." and "The workflow has no runs yet.", and "No results matched." will show if there is no filter results and there is no workflows (with [reference to github action](https://github.com/go-gitea/gitea/actions/workflows/files-changed.yml?query=actor%3AGiteaBot)) Demo: https://github.com/go-gitea/gitea/assets/17645053/6e76292c-4c1f-450d-8b48-99944cfc920c TODOs: - [x] Get available status (same as those in `aggregateJobStatus`) instead of getting from database - [x] Use `JOIN` to get actors, actors order by name - [x] Make self on top
1 parent e79ff50 commit 1454f9d

File tree

12 files changed

+127
-19
lines changed

12 files changed

+127
-19
lines changed

models/actions/run_list.go

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ type FindRunOptions struct {
7171
WorkflowFileName string
7272
TriggerUserID int64
7373
Approved bool // not util.OptionalBool, it works only when it's true
74+
Status Status
7475
}
7576

7677
func (opts FindRunOptions) toConds() builder.Cond {
@@ -90,6 +91,9 @@ func (opts FindRunOptions) toConds() builder.Cond {
9091
if opts.Approved {
9192
cond = cond.And(builder.Gt{"approved_by": 0})
9293
}
94+
if opts.Status > StatusUnknown {
95+
cond = cond.And(builder.Eq{"status": opts.Status})
96+
}
9397
return cond
9498
}
9599

@@ -106,3 +110,34 @@ func FindRuns(ctx context.Context, opts FindRunOptions) (RunList, int64, error)
106110
func CountRuns(ctx context.Context, opts FindRunOptions) (int64, error) {
107111
return db.GetEngine(ctx).Where(opts.toConds()).Count(new(ActionRun))
108112
}
113+
114+
type StatusInfo struct {
115+
Status int
116+
DisplayedStatus string
117+
}
118+
119+
// GetStatusInfoList returns a slice of StatusInfo
120+
func GetStatusInfoList(ctx context.Context) []StatusInfo {
121+
// same as those in aggregateJobStatus
122+
allStatus := []Status{StatusSuccess, StatusFailure, StatusWaiting, StatusRunning}
123+
statusInfoList := make([]StatusInfo, 0, 4)
124+
for _, s := range allStatus {
125+
statusInfoList = append(statusInfoList, StatusInfo{
126+
Status: int(s),
127+
DisplayedStatus: s.String(),
128+
})
129+
}
130+
return statusInfoList
131+
}
132+
133+
// GetActors returns a slice of Actors
134+
func GetActors(ctx context.Context, repoID int64) ([]*user_model.User, error) {
135+
actors := make([]*user_model.User, 0, 10)
136+
137+
return actors, db.GetEngine(ctx).Where(builder.In("id", builder.Select("`action_run`.trigger_user_id").From("`action_run`").
138+
GroupBy("`action_run`.trigger_user_id").
139+
Where(builder.Eq{"`action_run`.repo_id": repoID}))).
140+
Cols("id", "name", "full_name", "avatar", "avatar_email", "use_custom_avatar").
141+
OrderBy(user_model.GetOrderByName()).
142+
Find(&actors)
143+
}

options/locale/locale_en-US.ini

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3460,6 +3460,12 @@ runs.commit = Commit
34603460
runs.pushed_by = Pushed by
34613461
runs.invalid_workflow_helper = Workflow config file is invalid. Please check your config file: %s
34623462
runs.no_matching_runner_helper = No matching runner: %s
3463+
runs.actor = Actor
3464+
runs.status = Status
3465+
runs.actors_no_select = All actors
3466+
runs.status_no_select = All status
3467+
runs.no_results = No results matched.
3468+
runs.no_runs = The workflow has no runs yet.
34633469
34643470
need_approval_desc = Need approval to run workflows for fork pull request.
34653471

routers/web/repo/actions/actions.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ package actions
55

66
import (
77
"bytes"
8+
"fmt"
89
"net/http"
910

1011
actions_model "code.gitea.io/gitea/models/actions"
@@ -16,6 +17,7 @@ import (
1617
"code.gitea.io/gitea/modules/context"
1718
"code.gitea.io/gitea/modules/git"
1819
"code.gitea.io/gitea/modules/setting"
20+
"code.gitea.io/gitea/routers/web/repo"
1921
"code.gitea.io/gitea/services/convert"
2022

2123
"github.com/nektos/act/pkg/model"
@@ -125,7 +127,16 @@ func List(ctx *context.Context) {
125127
}
126128

127129
workflow := ctx.FormString("workflow")
130+
actorID := ctx.FormInt64("actor")
131+
status := ctx.FormInt("status")
128132
ctx.Data["CurWorkflow"] = workflow
133+
// if status or actor query param is not given to frontend href, (href="/<repoLink>/actions")
134+
// they will be 0 by default, which indicates get all status or actors
135+
ctx.Data["CurActor"] = actorID
136+
ctx.Data["CurStatus"] = status
137+
if actorID > 0 || status > int(actions_model.StatusUnknown) {
138+
ctx.Data["IsFiltered"] = true
139+
}
129140

130141
opts := actions_model.FindRunOptions{
131142
ListOptions: db.ListOptions{
@@ -134,6 +145,8 @@ func List(ctx *context.Context) {
134145
},
135146
RepoID: ctx.Repo.Repository.ID,
136147
WorkflowFileName: workflow,
148+
TriggerUserID: actorID,
149+
Status: actions_model.Status(status),
137150
}
138151

139152
runs, total, err := actions_model.FindRuns(ctx, opts)
@@ -153,9 +166,20 @@ func List(ctx *context.Context) {
153166

154167
ctx.Data["Runs"] = runs
155168

169+
actors, err := actions_model.GetActors(ctx, ctx.Repo.Repository.ID)
170+
if err != nil {
171+
ctx.Error(http.StatusInternalServerError, err.Error())
172+
return
173+
}
174+
ctx.Data["Actors"] = repo.MakeSelfOnTop(ctx, actors)
175+
176+
ctx.Data["StatusInfoList"] = actions_model.GetStatusInfoList(ctx)
177+
156178
pager := context.NewPagination(int(total), opts.PageSize, opts.Page, 5)
157179
pager.SetDefaultParams(ctx)
158180
pager.AddParamString("workflow", workflow)
181+
pager.AddParamString("actor", fmt.Sprint(actorID))
182+
pager.AddParamString("status", fmt.Sprint(status))
159183
ctx.Data["Page"] = pager
160184

161185
ctx.HTML(http.StatusOK, tplListActions)

routers/web/repo/helper.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import (
1010
"code.gitea.io/gitea/modules/context"
1111
)
1212

13-
func makeSelfOnTop(ctx *context.Context, users []*user.User) []*user.User {
13+
func MakeSelfOnTop(ctx *context.Context, users []*user.User) []*user.User {
1414
if ctx.Doer != nil {
1515
sort.Slice(users, func(i, j int) bool {
1616
if users[i].ID == users[j].ID {

routers/web/repo/helper_test.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,15 +13,15 @@ import (
1313
)
1414

1515
func TestMakeSelfOnTop(t *testing.T) {
16-
users := makeSelfOnTop(&context.Context{}, []*user.User{{ID: 2}, {ID: 1}})
16+
users := MakeSelfOnTop(&context.Context{}, []*user.User{{ID: 2}, {ID: 1}})
1717
assert.Len(t, users, 2)
1818
assert.EqualValues(t, 2, users[0].ID)
1919

20-
users = makeSelfOnTop(&context.Context{Doer: &user.User{ID: 1}}, []*user.User{{ID: 2}, {ID: 1}})
20+
users = MakeSelfOnTop(&context.Context{Doer: &user.User{ID: 1}}, []*user.User{{ID: 2}, {ID: 1}})
2121
assert.Len(t, users, 2)
2222
assert.EqualValues(t, 1, users[0].ID)
2323

24-
users = makeSelfOnTop(&context.Context{Doer: &user.User{ID: 2}}, []*user.User{{ID: 2}, {ID: 1}})
24+
users = MakeSelfOnTop(&context.Context{Doer: &user.User{ID: 2}}, []*user.User{{ID: 2}, {ID: 1}})
2525
assert.Len(t, users, 2)
2626
assert.EqualValues(t, 2, users[0].ID)
2727
}

routers/web/repo/issue.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -312,7 +312,7 @@ func issues(ctx *context.Context, milestoneID, projectID int64, isPullOption uti
312312
ctx.ServerError("GetRepoAssignees", err)
313313
return
314314
}
315-
ctx.Data["Assignees"] = makeSelfOnTop(ctx, assigneeUsers)
315+
ctx.Data["Assignees"] = MakeSelfOnTop(ctx, assigneeUsers)
316316

317317
handleTeamMentions(ctx)
318318
if ctx.Written() {
@@ -508,7 +508,7 @@ func RetrieveRepoMilestonesAndAssignees(ctx *context.Context, repo *repo_model.R
508508
ctx.ServerError("GetRepoAssignees", err)
509509
return
510510
}
511-
ctx.Data["Assignees"] = makeSelfOnTop(ctx, assigneeUsers)
511+
ctx.Data["Assignees"] = MakeSelfOnTop(ctx, assigneeUsers)
512512

513513
handleTeamMentions(ctx)
514514
}
@@ -3487,7 +3487,7 @@ func IssuePosters(ctx *context.Context) {
34873487
}
34883488
}
34893489

3490-
posters = makeSelfOnTop(ctx, posters)
3490+
posters = MakeSelfOnTop(ctx, posters)
34913491

34923492
resp := &userSearchResponse{}
34933493
resp.Results = make([]*userSearchInfo, len(posters))

routers/web/repo/pull.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -809,7 +809,7 @@ func ViewPullFiles(ctx *context.Context) {
809809
ctx.ServerError("GetRepoAssignees", err)
810810
return
811811
}
812-
ctx.Data["Assignees"] = makeSelfOnTop(ctx, assigneeUsers)
812+
ctx.Data["Assignees"] = MakeSelfOnTop(ctx, assigneeUsers)
813813

814814
handleTeamMentions(ctx)
815815
if ctx.Written() {

routers/web/repo/release.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -349,7 +349,7 @@ func NewRelease(ctx *context.Context) {
349349
ctx.ServerError("GetRepoAssignees", err)
350350
return
351351
}
352-
ctx.Data["Assignees"] = makeSelfOnTop(ctx, assigneeUsers)
352+
ctx.Data["Assignees"] = MakeSelfOnTop(ctx, assigneeUsers)
353353

354354
upload.AddUploadContext(ctx, "release")
355355
ctx.HTML(http.StatusOK, tplReleaseNew)
@@ -517,7 +517,7 @@ func EditRelease(ctx *context.Context) {
517517
ctx.ServerError("GetRepoAssignees", err)
518518
return
519519
}
520-
ctx.Data["Assignees"] = makeSelfOnTop(ctx, assigneeUsers)
520+
ctx.Data["Assignees"] = MakeSelfOnTop(ctx, assigneeUsers)
521521

522522
ctx.HTML(http.StatusOK, tplReleaseNew)
523523
}

templates/package/shared/list.tmpl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@
3838
{{else}}
3939
{{if not .HasPackages}}
4040
<div class="empty center">
41-
{{svg "octicon-package" 32}}
41+
{{svg "octicon-package" 48}}
4242
<h2>{{.locale.Tr "packages.empty"}}</h2>
4343
{{if and .Repository .CanWritePackages}}
4444
{{$packagesUrl := URLJoin .Owner.HomeLink "-" "packages"}}

templates/repo/actions/list.tmpl

Lines changed: 43 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
{{template "base/head" .}}
2-
<div class="page-content repository">
2+
<div class="page-content repository actions">
33
{{template "repo/header" .}}
44
<div class="ui container">
55
<div class="ui stackable grid">
66
<div class="four wide column">
77
<div class="ui fluid vertical menu">
8-
<a class="item{{if not $.CurWorkflow}} active{{end}}" href="{{$.Link}}">{{.locale.Tr "actions.runs.all_workflows"}}</a>
8+
<a class="item{{if not $.CurWorkflow}} active{{end}}" href="{{$.Link}}?actor={{$.CurActor}}&status={{$.CurStatus}}">{{.locale.Tr "actions.runs.all_workflows"}}</a>
99
<div class="divider"></div>
1010
{{range .workflows}}
11-
<a class="item{{if eq .Entry.Name $.CurWorkflow}} active{{end}}" href="{{$.Link}}?workflow={{.Entry.Name}}">{{.Entry.Name}}
11+
<a class="item{{if eq .Entry.Name $.CurWorkflow}} active{{end}}" href="{{$.Link}}?workflow={{.Entry.Name}}&actor={{$.CurActor}}&status={{$.CurStatus}}">{{.Entry.Name}}
1212
{{if .ErrMsg}}
1313
<span data-tooltip-content="{{.ErrMsg}}">
1414
{{svg "octicon-alert" 16 "text red"}}
@@ -19,6 +19,46 @@
1919
</div>
2020
</div>
2121
<div class="twelve wide column content">
22+
<div class="ui secondary filter stackable menu gt-je">
23+
<!-- Actor -->
24+
<div class="ui{{if not .Actors}} disabled{{end}} dropdown jump item">
25+
<span class="text">{{.locale.Tr "actions.runs.actor"}}</span>
26+
{{svg "octicon-triangle-down" 14 "dropdown icon"}}
27+
<div class="menu">
28+
<div class="ui icon search input">
29+
<i class="icon">{{svg "octicon-search"}}</i>
30+
<input type="text" placeholder="{{.locale.Tr "actions.runs.actor"}}">
31+
</div>
32+
<a class="item{{if not $.CurActor}} active{{end}}" href="{{$.Link}}?workflow={{$.CurWorkflow}}&status={{$.CurStatus}}&actor=0">
33+
{{.locale.Tr "actions.runs.actors_no_select"}}
34+
</a>
35+
{{range .Actors}}
36+
<a class="item{{if eq .ID $.CurActor}} active{{end}}" href="{{$.Link}}?workflow={{$.CurWorkflow}}&actor={{.ID}}&status={{$.CurStatus}}">
37+
{{avatar $.Context . 20}} {{.GetDisplayName}}
38+
</a>
39+
{{end}}
40+
</div>
41+
</div>
42+
<!-- Status -->
43+
<div class="ui dropdown jump item">
44+
<span class="text">{{.locale.Tr "actions.runs.status"}}</span>
45+
{{svg "octicon-triangle-down" 14 "dropdown icon"}}
46+
<div class="menu">
47+
<div class="ui icon search input">
48+
<i class="icon">{{svg "octicon-search"}}</i>
49+
<input type="text" placeholder="{{.locale.Tr "actions.runs.status"}}">
50+
</div>
51+
<a class="item{{if not $.CurStatus}} active{{end}}" href="{{$.Link}}?workflow={{$.CurWorkflow}}&actor={{$.CurActor}}&status=0">
52+
{{.locale.Tr "actions.runs.status_no_select"}}
53+
</a>
54+
{{range .StatusInfoList}}
55+
<a class="item{{if eq .Status $.CurStatus}} active{{end}}" href="{{$.Link}}?workflow={{$.CurWorkflow}}&actor={{$.CurActor}}&status={{.Status}}">
56+
{{.DisplayedStatus}}
57+
</a>
58+
{{end}}
59+
</div>
60+
</div>
61+
</div>
2262
{{template "repo/actions/runs_list" .}}
2363
</div>
2464
</div>

templates/repo/actions/runs_list.tmpl

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,10 @@
11
<div class="issue list gt-m-0">
2+
{{if eq (len .Runs) 0}}
3+
<div class="empty center">
4+
{{svg "octicon-no-entry" 48}}
5+
<h2>{{if $.IsFiltered}}{{.locale.Tr "actions.runs.no_results"}}{{else}}{{.locale.Tr "actions.runs.no_runs"}}{{end}}</h2>
6+
</div>
7+
{{end}}
28
{{range .Runs}}
39
<li class="item gt-df gt-py-4">
410
<div class="issue-item-left issue-item-icon gt-df gt-items-start">

web_src/css/repo.css

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1877,15 +1877,12 @@
18771877
flex: 1
18781878
}
18791879

1880-
.repository.packages .empty {
1880+
.repository.packages .empty,
1881+
.repository.actions .empty {
18811882
padding-top: 70px;
18821883
padding-bottom: 100px;
18831884
}
18841885

1885-
.repository.packages .empty .svg {
1886-
height: 48px;
1887-
}
1888-
18891886
.repository.packages .file-size {
18901887
white-space: nowrap;
18911888
}

0 commit comments

Comments
 (0)