Skip to content

Commit

Permalink
Add actor and status dropdowns to run list (#25118)
Browse files Browse the repository at this point in the history
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
  • Loading branch information
HesterG authored Jun 21, 2023
1 parent e79ff50 commit 1454f9d
Show file tree
Hide file tree
Showing 12 changed files with 127 additions and 19 deletions.
35 changes: 35 additions & 0 deletions models/actions/run_list.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ type FindRunOptions struct {
WorkflowFileName string
TriggerUserID int64
Approved bool // not util.OptionalBool, it works only when it's true
Status Status
}

func (opts FindRunOptions) toConds() builder.Cond {
Expand All @@ -90,6 +91,9 @@ func (opts FindRunOptions) toConds() builder.Cond {
if opts.Approved {
cond = cond.And(builder.Gt{"approved_by": 0})
}
if opts.Status > StatusUnknown {
cond = cond.And(builder.Eq{"status": opts.Status})
}
return cond
}

Expand All @@ -106,3 +110,34 @@ func FindRuns(ctx context.Context, opts FindRunOptions) (RunList, int64, error)
func CountRuns(ctx context.Context, opts FindRunOptions) (int64, error) {
return db.GetEngine(ctx).Where(opts.toConds()).Count(new(ActionRun))
}

type StatusInfo struct {
Status int
DisplayedStatus string
}

// GetStatusInfoList returns a slice of StatusInfo
func GetStatusInfoList(ctx context.Context) []StatusInfo {
// same as those in aggregateJobStatus
allStatus := []Status{StatusSuccess, StatusFailure, StatusWaiting, StatusRunning}
statusInfoList := make([]StatusInfo, 0, 4)
for _, s := range allStatus {
statusInfoList = append(statusInfoList, StatusInfo{
Status: int(s),
DisplayedStatus: s.String(),
})
}
return statusInfoList
}

// GetActors returns a slice of Actors
func GetActors(ctx context.Context, repoID int64) ([]*user_model.User, error) {
actors := make([]*user_model.User, 0, 10)

return actors, db.GetEngine(ctx).Where(builder.In("id", builder.Select("`action_run`.trigger_user_id").From("`action_run`").
GroupBy("`action_run`.trigger_user_id").
Where(builder.Eq{"`action_run`.repo_id": repoID}))).
Cols("id", "name", "full_name", "avatar", "avatar_email", "use_custom_avatar").
OrderBy(user_model.GetOrderByName()).
Find(&actors)
}
6 changes: 6 additions & 0 deletions options/locale/locale_en-US.ini
Original file line number Diff line number Diff line change
Expand Up @@ -3460,6 +3460,12 @@ runs.commit = Commit
runs.pushed_by = Pushed by
runs.invalid_workflow_helper = Workflow config file is invalid. Please check your config file: %s
runs.no_matching_runner_helper = No matching runner: %s
runs.actor = Actor
runs.status = Status
runs.actors_no_select = All actors
runs.status_no_select = All status
runs.no_results = No results matched.
runs.no_runs = The workflow has no runs yet.
need_approval_desc = Need approval to run workflows for fork pull request.
Expand Down
24 changes: 24 additions & 0 deletions routers/web/repo/actions/actions.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ package actions

import (
"bytes"
"fmt"
"net/http"

actions_model "code.gitea.io/gitea/models/actions"
Expand All @@ -16,6 +17,7 @@ import (
"code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/routers/web/repo"
"code.gitea.io/gitea/services/convert"

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

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

opts := actions_model.FindRunOptions{
ListOptions: db.ListOptions{
Expand All @@ -134,6 +145,8 @@ func List(ctx *context.Context) {
},
RepoID: ctx.Repo.Repository.ID,
WorkflowFileName: workflow,
TriggerUserID: actorID,
Status: actions_model.Status(status),
}

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

ctx.Data["Runs"] = runs

actors, err := actions_model.GetActors(ctx, ctx.Repo.Repository.ID)
if err != nil {
ctx.Error(http.StatusInternalServerError, err.Error())
return
}
ctx.Data["Actors"] = repo.MakeSelfOnTop(ctx, actors)

ctx.Data["StatusInfoList"] = actions_model.GetStatusInfoList(ctx)

pager := context.NewPagination(int(total), opts.PageSize, opts.Page, 5)
pager.SetDefaultParams(ctx)
pager.AddParamString("workflow", workflow)
pager.AddParamString("actor", fmt.Sprint(actorID))
pager.AddParamString("status", fmt.Sprint(status))
ctx.Data["Page"] = pager

ctx.HTML(http.StatusOK, tplListActions)
Expand Down
2 changes: 1 addition & 1 deletion routers/web/repo/helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import (
"code.gitea.io/gitea/modules/context"
)

func makeSelfOnTop(ctx *context.Context, users []*user.User) []*user.User {
func MakeSelfOnTop(ctx *context.Context, users []*user.User) []*user.User {
if ctx.Doer != nil {
sort.Slice(users, func(i, j int) bool {
if users[i].ID == users[j].ID {
Expand Down
6 changes: 3 additions & 3 deletions routers/web/repo/helper_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,15 @@ import (
)

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

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

users = makeSelfOnTop(&context.Context{Doer: &user.User{ID: 2}}, []*user.User{{ID: 2}, {ID: 1}})
users = MakeSelfOnTop(&context.Context{Doer: &user.User{ID: 2}}, []*user.User{{ID: 2}, {ID: 1}})
assert.Len(t, users, 2)
assert.EqualValues(t, 2, users[0].ID)
}
6 changes: 3 additions & 3 deletions routers/web/repo/issue.go
Original file line number Diff line number Diff line change
Expand Up @@ -312,7 +312,7 @@ func issues(ctx *context.Context, milestoneID, projectID int64, isPullOption uti
ctx.ServerError("GetRepoAssignees", err)
return
}
ctx.Data["Assignees"] = makeSelfOnTop(ctx, assigneeUsers)
ctx.Data["Assignees"] = MakeSelfOnTop(ctx, assigneeUsers)

handleTeamMentions(ctx)
if ctx.Written() {
Expand Down Expand Up @@ -508,7 +508,7 @@ func RetrieveRepoMilestonesAndAssignees(ctx *context.Context, repo *repo_model.R
ctx.ServerError("GetRepoAssignees", err)
return
}
ctx.Data["Assignees"] = makeSelfOnTop(ctx, assigneeUsers)
ctx.Data["Assignees"] = MakeSelfOnTop(ctx, assigneeUsers)

handleTeamMentions(ctx)
}
Expand Down Expand Up @@ -3487,7 +3487,7 @@ func IssuePosters(ctx *context.Context) {
}
}

posters = makeSelfOnTop(ctx, posters)
posters = MakeSelfOnTop(ctx, posters)

resp := &userSearchResponse{}
resp.Results = make([]*userSearchInfo, len(posters))
Expand Down
2 changes: 1 addition & 1 deletion routers/web/repo/pull.go
Original file line number Diff line number Diff line change
Expand Up @@ -809,7 +809,7 @@ func ViewPullFiles(ctx *context.Context) {
ctx.ServerError("GetRepoAssignees", err)
return
}
ctx.Data["Assignees"] = makeSelfOnTop(ctx, assigneeUsers)
ctx.Data["Assignees"] = MakeSelfOnTop(ctx, assigneeUsers)

handleTeamMentions(ctx)
if ctx.Written() {
Expand Down
4 changes: 2 additions & 2 deletions routers/web/repo/release.go
Original file line number Diff line number Diff line change
Expand Up @@ -349,7 +349,7 @@ func NewRelease(ctx *context.Context) {
ctx.ServerError("GetRepoAssignees", err)
return
}
ctx.Data["Assignees"] = makeSelfOnTop(ctx, assigneeUsers)
ctx.Data["Assignees"] = MakeSelfOnTop(ctx, assigneeUsers)

upload.AddUploadContext(ctx, "release")
ctx.HTML(http.StatusOK, tplReleaseNew)
Expand Down Expand Up @@ -517,7 +517,7 @@ func EditRelease(ctx *context.Context) {
ctx.ServerError("GetRepoAssignees", err)
return
}
ctx.Data["Assignees"] = makeSelfOnTop(ctx, assigneeUsers)
ctx.Data["Assignees"] = MakeSelfOnTop(ctx, assigneeUsers)

ctx.HTML(http.StatusOK, tplReleaseNew)
}
Expand Down
2 changes: 1 addition & 1 deletion templates/package/shared/list.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
{{else}}
{{if not .HasPackages}}
<div class="empty center">
{{svg "octicon-package" 32}}
{{svg "octicon-package" 48}}
<h2>{{.locale.Tr "packages.empty"}}</h2>
{{if and .Repository .CanWritePackages}}
{{$packagesUrl := URLJoin .Owner.HomeLink "-" "packages"}}
Expand Down
46 changes: 43 additions & 3 deletions templates/repo/actions/list.tmpl
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
{{template "base/head" .}}
<div class="page-content repository">
<div class="page-content repository actions">
{{template "repo/header" .}}
<div class="ui container">
<div class="ui stackable grid">
<div class="four wide column">
<div class="ui fluid vertical menu">
<a class="item{{if not $.CurWorkflow}} active{{end}}" href="{{$.Link}}">{{.locale.Tr "actions.runs.all_workflows"}}</a>
<a class="item{{if not $.CurWorkflow}} active{{end}}" href="{{$.Link}}?actor={{$.CurActor}}&status={{$.CurStatus}}">{{.locale.Tr "actions.runs.all_workflows"}}</a>
<div class="divider"></div>
{{range .workflows}}
<a class="item{{if eq .Entry.Name $.CurWorkflow}} active{{end}}" href="{{$.Link}}?workflow={{.Entry.Name}}">{{.Entry.Name}}
<a class="item{{if eq .Entry.Name $.CurWorkflow}} active{{end}}" href="{{$.Link}}?workflow={{.Entry.Name}}&actor={{$.CurActor}}&status={{$.CurStatus}}">{{.Entry.Name}}
{{if .ErrMsg}}
<span data-tooltip-content="{{.ErrMsg}}">
{{svg "octicon-alert" 16 "text red"}}
Expand All @@ -19,6 +19,46 @@
</div>
</div>
<div class="twelve wide column content">
<div class="ui secondary filter stackable menu gt-je">
<!-- Actor -->
<div class="ui{{if not .Actors}} disabled{{end}} dropdown jump item">
<span class="text">{{.locale.Tr "actions.runs.actor"}}</span>
{{svg "octicon-triangle-down" 14 "dropdown icon"}}
<div class="menu">
<div class="ui icon search input">
<i class="icon">{{svg "octicon-search"}}</i>
<input type="text" placeholder="{{.locale.Tr "actions.runs.actor"}}">
</div>
<a class="item{{if not $.CurActor}} active{{end}}" href="{{$.Link}}?workflow={{$.CurWorkflow}}&status={{$.CurStatus}}&actor=0">
{{.locale.Tr "actions.runs.actors_no_select"}}
</a>
{{range .Actors}}
<a class="item{{if eq .ID $.CurActor}} active{{end}}" href="{{$.Link}}?workflow={{$.CurWorkflow}}&actor={{.ID}}&status={{$.CurStatus}}">
{{avatar $.Context . 20}} {{.GetDisplayName}}
</a>
{{end}}
</div>
</div>
<!-- Status -->
<div class="ui dropdown jump item">
<span class="text">{{.locale.Tr "actions.runs.status"}}</span>
{{svg "octicon-triangle-down" 14 "dropdown icon"}}
<div class="menu">
<div class="ui icon search input">
<i class="icon">{{svg "octicon-search"}}</i>
<input type="text" placeholder="{{.locale.Tr "actions.runs.status"}}">
</div>
<a class="item{{if not $.CurStatus}} active{{end}}" href="{{$.Link}}?workflow={{$.CurWorkflow}}&actor={{$.CurActor}}&status=0">
{{.locale.Tr "actions.runs.status_no_select"}}
</a>
{{range .StatusInfoList}}
<a class="item{{if eq .Status $.CurStatus}} active{{end}}" href="{{$.Link}}?workflow={{$.CurWorkflow}}&actor={{$.CurActor}}&status={{.Status}}">
{{.DisplayedStatus}}
</a>
{{end}}
</div>
</div>
</div>
{{template "repo/actions/runs_list" .}}
</div>
</div>
Expand Down
6 changes: 6 additions & 0 deletions templates/repo/actions/runs_list.tmpl
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
<div class="issue list gt-m-0">
{{if eq (len .Runs) 0}}
<div class="empty center">
{{svg "octicon-no-entry" 48}}
<h2>{{if $.IsFiltered}}{{.locale.Tr "actions.runs.no_results"}}{{else}}{{.locale.Tr "actions.runs.no_runs"}}{{end}}</h2>
</div>
{{end}}
{{range .Runs}}
<li class="item gt-df gt-py-4">
<div class="issue-item-left issue-item-icon gt-df gt-items-start">
Expand Down
7 changes: 2 additions & 5 deletions web_src/css/repo.css
Original file line number Diff line number Diff line change
Expand Up @@ -1877,15 +1877,12 @@
flex: 1
}

.repository.packages .empty {
.repository.packages .empty,
.repository.actions .empty {
padding-top: 70px;
padding-bottom: 100px;
}

.repository.packages .empty .svg {
height: 48px;
}

.repository.packages .file-size {
white-space: nowrap;
}
Expand Down

0 comments on commit 1454f9d

Please sign in to comment.