From cb0c6b52be9000c738266789c0e0729af67a5b00 Mon Sep 17 00:00:00 2001 From: iminfinity Date: Thu, 4 Apr 2024 17:57:11 +0530 Subject: [PATCH] add label filters in org/{org_name}/issues (cherry picked from commit 8d13ed4a8d03a7542641faf771dad56783ab3a4c) --- routers/web/user/home.go | 31 +++++++++++++++++ routers/web/user/home_test.go | 34 ++++++++++++++++++ services/contexttest/context_tests.go | 14 ++++++++ templates/repo/issue/filter_list.tmpl | 50 +-------------------------- templates/shared/label_filter.tmpl | 50 +++++++++++++++++++++++++++ templates/user/dashboard/issues.tmpl | 24 +++++++------ tests/integration/org_test.go | 25 ++++++++++++++ 7 files changed, 169 insertions(+), 59 deletions(-) create mode 100644 templates/shared/label_filter.tmpl diff --git a/routers/web/user/home.go b/routers/web/user/home.go index f122dc5d9c..52aca1825a 100644 --- a/routers/web/user/home.go +++ b/routers/web/user/home.go @@ -538,6 +538,36 @@ func buildIssueOverview(ctx *context.Context, unitType unit.Type) { } } + if org != nil { + // Get Org Labels + labels, err := issues_model.GetLabelsByOrgID(ctx, ctx.Org.Organization.ID, ctx.FormString("sort"), db.ListOptions{}) + if err != nil { + ctx.ServerError("GetLabelsByOrgID", err) + return + } + + // Get the exclusive scope for every label ID + labelExclusiveScopes := make([]string, 0, len(opts.LabelIDs)) + for _, labelID := range opts.LabelIDs { + foundExclusiveScope := false + for _, label := range labels { + if label.ID == labelID || label.ID == -labelID { + labelExclusiveScopes = append(labelExclusiveScopes, label.ExclusiveScope()) + foundExclusiveScope = true + break + } + } + if !foundExclusiveScope { + labelExclusiveScopes = append(labelExclusiveScopes, "") + } + } + + for _, l := range labels { + l.LoadSelectedLabelsAfterClick(opts.LabelIDs, labelExclusiveScopes) + } + ctx.Data["Labels"] = labels + } + // ------------------------------ // Get issues as defined by opts. // ------------------------------ @@ -621,6 +651,7 @@ func buildIssueOverview(ctx *context.Context, unitType unit.Type) { ctx.Data["SortType"] = sortType ctx.Data["IsShowClosed"] = isShowClosed ctx.Data["SelectLabels"] = selectedLabels + ctx.Data["PageIsOrgIssues"] = org != nil if isShowClosed { ctx.Data["State"] = "closed" diff --git a/routers/web/user/home_test.go b/routers/web/user/home_test.go index 1cc9886308..a59afce12c 100644 --- a/routers/web/user/home_test.go +++ b/routers/web/user/home_test.go @@ -8,6 +8,7 @@ import ( "testing" "code.gitea.io/gitea/models/db" + issues_model "code.gitea.io/gitea/models/issues" repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/models/unittest" "code.gitea.io/gitea/modules/setting" @@ -130,3 +131,36 @@ func TestDashboardPagination(t *testing.T) { assert.NoError(t, err) assert.Contains(t, out, ``) } + +func TestOrgLabels(t *testing.T) { + assert.NoError(t, unittest.LoadFixtures()) + + ctx, _ := contexttest.MockContext(t, "org/org3/issues") + contexttest.LoadUser(t, ctx, 2) + contexttest.LoadOrganization(t, ctx, 3) + Issues(ctx) + assert.EqualValues(t, http.StatusOK, ctx.Resp.Status()) + + assert.True(t, ctx.Data["PageIsOrgIssues"].(bool)) + + orgLabels := []struct { + ID int64 + OrgID int64 + Name string + }{ + {3, 3, "orglabel3"}, + {4, 3, "orglabel4"}, + } + + labels, ok := ctx.Data["Labels"].([]*issues_model.Label) + + assert.True(t, ok) + + if assert.Len(t, labels, len(orgLabels)) { + for i, label := range labels { + assert.EqualValues(t, orgLabels[i].OrgID, label.OrgID) + assert.EqualValues(t, orgLabels[i].ID, label.ID) + assert.EqualValues(t, orgLabels[i].Name, label.Name) + } + } +} diff --git a/services/contexttest/context_tests.go b/services/contexttest/context_tests.go index d3e6de7efe..7bfab2ed16 100644 --- a/services/contexttest/context_tests.go +++ b/services/contexttest/context_tests.go @@ -15,6 +15,7 @@ import ( "testing" "time" + org_model "code.gitea.io/gitea/models/organization" access_model "code.gitea.io/gitea/models/perm/access" repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/models/unittest" @@ -146,6 +147,19 @@ func LoadUser(t *testing.T, ctx gocontext.Context, userID int64) { } } +// LoadOrganization load an org into a test context +func LoadOrganization(t *testing.T, ctx gocontext.Context, orgID int64) { + org := unittest.AssertExistsAndLoadBean(t, &org_model.Organization{ID: orgID}) + switch ctx := ctx.(type) { + case *context.Context: + ctx.Org.Organization = org + case *context.APIContext: + ctx.Org.Organization = org + default: + assert.FailNow(t, "context is not *context.Context or *context.APIContext") + } +} + // LoadGitRepo load a git repo into a test context. Requires that ctx.Repo has // already been populated. func LoadGitRepo(t *testing.T, ctx *context.Context) { diff --git a/templates/repo/issue/filter_list.tmpl b/templates/repo/issue/filter_list.tmpl index 997557c45e..f60389766e 100644 --- a/templates/repo/issue/filter_list.tmpl +++ b/templates/repo/issue/filter_list.tmpl @@ -1,53 +1,5 @@ - +{{template "shared/label_filter" .}} {{if not .Milestone}} diff --git a/templates/shared/label_filter.tmpl b/templates/shared/label_filter.tmpl new file mode 100644 index 0000000000..9daeb3f100 --- /dev/null +++ b/templates/shared/label_filter.tmpl @@ -0,0 +1,50 @@ + + diff --git a/templates/user/dashboard/issues.tmpl b/templates/user/dashboard/issues.tmpl index 89f23163f7..b7cc54091c 100644 --- a/templates/user/dashboard/issues.tmpl +++ b/templates/user/dashboard/issues.tmpl @@ -37,11 +37,11 @@
diff --git a/tests/integration/org_test.go b/tests/integration/org_test.go index 94c4e19727..a1e448be8a 100644 --- a/tests/integration/org_test.go +++ b/tests/integration/org_test.go @@ -222,3 +222,28 @@ func TestTeamSearch(t *testing.T) { req.Header.Add("X-Csrf-Token", csrf) session.MakeRequest(t, req, http.StatusNotFound) } + +func TestOrgDashboardLabels(t *testing.T) { + defer tests.PrepareTestEnv(t)() + + user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 4}) + org := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 3, Type: user_model.UserTypeOrganization}) + session := loginUser(t, user.Name) + + req := NewRequestf(t, "GET", "/org/%s/issues?labels=3,4", org.Name) + resp := session.MakeRequest(t, req, http.StatusOK) + htmlDoc := NewHTMLParser(t, resp.Body) + + labelFilterHref, ok := htmlDoc.Find(".list-header-sort a").Attr("href") + assert.True(t, ok) + assert.Contains(t, labelFilterHref, "labels=3%2c4") + + // Exclude label + req = NewRequestf(t, "GET", "/org/%s/issues?labels=3,-4", org.Name) + resp = session.MakeRequest(t, req, http.StatusOK) + htmlDoc = NewHTMLParser(t, resp.Body) + + labelFilterHref, ok = htmlDoc.Find(".list-header-sort a").Attr("href") + assert.True(t, ok) + assert.Contains(t, labelFilterHref, "labels=3%2c-4") +}