From 1454f9dafc681875d8f6a429b80e27de62f4040e Mon Sep 17 00:00:00 2001 From: HesterG Date: Wed, 21 Jun 2023 12:25:14 +0800 Subject: [PATCH] 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 --- models/actions/run_list.go | 35 ++++++++++++++++++++ options/locale/locale_en-US.ini | 6 ++++ routers/web/repo/actions/actions.go | 24 ++++++++++++++ routers/web/repo/helper.go | 2 +- routers/web/repo/helper_test.go | 6 ++-- routers/web/repo/issue.go | 6 ++-- routers/web/repo/pull.go | 2 +- routers/web/repo/release.go | 4 +-- templates/package/shared/list.tmpl | 2 +- templates/repo/actions/list.tmpl | 46 +++++++++++++++++++++++++-- templates/repo/actions/runs_list.tmpl | 6 ++++ web_src/css/repo.css | 7 ++-- 12 files changed, 127 insertions(+), 19 deletions(-) diff --git a/models/actions/run_list.go b/models/actions/run_list.go index 56de8eb91..29ab193d5 100644 --- a/models/actions/run_list.go +++ b/models/actions/run_list.go @@ -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 { @@ -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 } @@ -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) +} diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini index 0cf881070..234b898fc 100644 --- a/options/locale/locale_en-US.ini +++ b/options/locale/locale_en-US.ini @@ -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. diff --git a/routers/web/repo/actions/actions.go b/routers/web/repo/actions/actions.go index 10acb4685..e1e07b5a7 100644 --- a/routers/web/repo/actions/actions.go +++ b/routers/web/repo/actions/actions.go @@ -5,6 +5,7 @@ package actions import ( "bytes" + "fmt" "net/http" actions_model "code.gitea.io/gitea/models/actions" @@ -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" @@ -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="//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{ @@ -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) @@ -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) diff --git a/routers/web/repo/helper.go b/routers/web/repo/helper.go index 6f9ca4874..fb5ada1bd 100644 --- a/routers/web/repo/helper.go +++ b/routers/web/repo/helper.go @@ -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 { diff --git a/routers/web/repo/helper_test.go b/routers/web/repo/helper_test.go index e9ab44fe6..226e2e81f 100644 --- a/routers/web/repo/helper_test.go +++ b/routers/web/repo/helper_test.go @@ -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) } diff --git a/routers/web/repo/issue.go b/routers/web/repo/issue.go index 49ba753a7..a9ce1cc1e 100644 --- a/routers/web/repo/issue.go +++ b/routers/web/repo/issue.go @@ -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() { @@ -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) } @@ -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)) diff --git a/routers/web/repo/pull.go b/routers/web/repo/pull.go index 309e61cf6..ef9d5856d 100644 --- a/routers/web/repo/pull.go +++ b/routers/web/repo/pull.go @@ -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() { diff --git a/routers/web/repo/release.go b/routers/web/repo/release.go index afba1f18b..5fddddb34 100644 --- a/routers/web/repo/release.go +++ b/routers/web/repo/release.go @@ -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) @@ -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) } diff --git a/templates/package/shared/list.tmpl b/templates/package/shared/list.tmpl index 707fbe357..5ac5baf0f 100644 --- a/templates/package/shared/list.tmpl +++ b/templates/package/shared/list.tmpl @@ -38,7 +38,7 @@ {{else}} {{if not .HasPackages}}
- {{svg "octicon-package" 32}} + {{svg "octicon-package" 48}}

{{.locale.Tr "packages.empty"}}

{{if and .Repository .CanWritePackages}} {{$packagesUrl := URLJoin .Owner.HomeLink "-" "packages"}} diff --git a/templates/repo/actions/list.tmpl b/templates/repo/actions/list.tmpl index ca97b67fa..46cbb3467 100644 --- a/templates/repo/actions/list.tmpl +++ b/templates/repo/actions/list.tmpl @@ -1,14 +1,14 @@ {{template "base/head" .}} -
+
{{template "repo/header" .}}
diff --git a/templates/repo/actions/runs_list.tmpl b/templates/repo/actions/runs_list.tmpl index 5f444f31f..bfd5aabe5 100644 --- a/templates/repo/actions/runs_list.tmpl +++ b/templates/repo/actions/runs_list.tmpl @@ -1,4 +1,10 @@
+ {{if eq (len .Runs) 0}} +
+ {{svg "octicon-no-entry" 48}} +

{{if $.IsFiltered}}{{.locale.Tr "actions.runs.no_results"}}{{else}}{{.locale.Tr "actions.runs.no_runs"}}{{end}}

+
+ {{end}} {{range .Runs}}
  • diff --git a/web_src/css/repo.css b/web_src/css/repo.css index 150254569..fa9739342 100644 --- a/web_src/css/repo.css +++ b/web_src/css/repo.css @@ -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; }