From 8d0a527ef906abed5b31047dfbcce345f1aabce9 Mon Sep 17 00:00:00 2001 From: Jimmy Praet Date: Wed, 25 Nov 2020 19:52:19 +0100 Subject: [PATCH 1/5] Add review requested filter on pull request overview #13682 fix formatting --- models/issue.go | 64 +++++++++++++++++++--- options/locale/locale_en-US.ini | 1 + routers/repo/issue.go | 53 ++++++++++-------- routers/user/home.go | 4 ++ templates/repo/issue/list.tmpl | 3 + templates/repo/issue/milestone_issues.tmpl | 1 + templates/user/dashboard/issues.tmpl | 6 ++ 7 files changed, 100 insertions(+), 32 deletions(-) diff --git a/models/issue.go b/models/issue.go index 787d873f249a4..e26db0805586e 100644 --- a/models/issue.go +++ b/models/issue.go @@ -1090,6 +1090,7 @@ type IssuesOptions struct { AssigneeID int64 PosterID int64 MentionedID int64 + ReviewRequestedID int64 MilestoneIDs []int64 ProjectID int64 ProjectBoardID int64 @@ -1176,6 +1177,13 @@ func (opts *IssuesOptions) setupSession(sess *xorm.Session) { And("issue_user.uid = ?", opts.MentionedID) } + if opts.ReviewRequestedID > 0 { + sess.Join("INNER", []string{"review", "r"}, "issue.id = r.issue_id"). + And("r.reviewer_id = ?", opts.ReviewRequestedID). + And("r.type = ?", ReviewTypeRequest). + And("r.id in (select max(id) from review where issue_id = r.issue_id and reviewer_id = r.reviewer_id)") + } + if len(opts.MilestoneIDs) > 0 { sess.In("issue.milestone_id", opts.MilestoneIDs) } @@ -1359,6 +1367,7 @@ type IssueStats struct { AssignCount int64 CreateCount int64 MentionCount int64 + ReviewRequestedCount int64 } // Filter modes. @@ -1367,6 +1376,7 @@ const ( FilterModeAssign FilterModeCreate FilterModeMention + FilterModeReviewRequested ) func parseCountResult(results []map[string][]byte) int64 { @@ -1381,14 +1391,15 @@ func parseCountResult(results []map[string][]byte) int64 { // IssueStatsOptions contains parameters accepted by GetIssueStats. type IssueStatsOptions struct { - RepoID int64 - Labels string - MilestoneID int64 - AssigneeID int64 - MentionedID int64 - PosterID int64 - IsPull util.OptionalBool - IssueIDs []int64 + RepoID int64 + Labels string + MilestoneID int64 + AssigneeID int64 + MentionedID int64 + PosterID int64 + ReviewRequestedID int64 + IsPull util.OptionalBool + IssueIDs []int64 } // GetIssueStats returns issue statistic information by given conditions. @@ -1417,6 +1428,7 @@ func GetIssueStats(opts *IssueStatsOptions) (*IssueStats, error) { accum.AssignCount += stats.AssignCount accum.CreateCount += stats.CreateCount accum.OpenCount += stats.MentionCount + accum.ReviewRequestedCount += stats.ReviewRequestedCount i = chunk } return accum, nil @@ -1468,6 +1480,13 @@ func getIssueStatsChunk(opts *IssueStatsOptions, issueIDs []int64) (*IssueStats, And("issue_user.is_mentioned = ?", true) } + if opts.ReviewRequestedID > 0 { + sess.Join("INNER", []string{"review", "r"}, "issue.id = r.issue_id"). + And("r.reviewer_id = ?", opts.ReviewRequestedID). + And("r.type = ?", ReviewTypeRequest). + And("r.id in (select max(id) from review where issue_id = r.issue_id and reviewer_id = r.reviewer_id)") + } + switch opts.IsPull { case util.OptionalBoolTrue: sess.And("issue.is_pull=?", true) @@ -1573,6 +1592,25 @@ func GetUserIssueStats(opts UserIssueStatsOptions) (*IssueStats, error) { if err != nil { return nil, err } + case FilterModeReviewRequested: + stats.OpenCount, err = x.Where(cond).And("issue.is_closed = ?", false). + Join("INNER", []string{"review", "r"}, "issue.id = r.issue_id"). + And("r.reviewer_id = ?", opts.UserID). + And("r.type = ?", ReviewTypeRequest). + And("r.id in (select max(id) from review where issue_id = r.issue_id and reviewer_id = r.reviewer_id)"). + Count(new(Issue)) + if err != nil { + return nil, err + } + stats.ClosedCount, err = x.Where(cond).And("issue.is_closed = ?", true). + Join("INNER", []string{"review", "r"}, "issue.id = r.issue_id"). + And("r.reviewer_id = ?", opts.UserID). + And("r.type = ?", ReviewTypeRequest). + And("r.id in (select max(id) from review where issue_id = r.issue_id and reviewer_id = r.reviewer_id)"). + Count(new(Issue)) + if err != nil { + return nil, err + } } cond = cond.And(builder.Eq{"issue.is_closed": opts.IsClosed}) @@ -1606,6 +1644,16 @@ func GetUserIssueStats(opts UserIssueStatsOptions) (*IssueStats, error) { return nil, err } + stats.ReviewRequestedCount, err = x.Where(cond). + Join("INNER", []string{"review", "r"}, "issue.id = r.issue_id"). + And("r.reviewer_id = ?", opts.UserID). + And("r.type = ?", ReviewTypeRequest). + And("r.id in (select max(id) from review where issue_id = r.issue_id and reviewer_id = r.reviewer_id)"). + Count(new(Issue)) + if err != nil { + return nil, err + } + return stats, nil } diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini index d7d6b751f6a4a..4d7d189848c29 100644 --- a/options/locale/locale_en-US.ini +++ b/options/locale/locale_en-US.ini @@ -1023,6 +1023,7 @@ issues.filter_type.all_issues = All issues issues.filter_type.assigned_to_you = Assigned to you issues.filter_type.created_by_you = Created by you issues.filter_type.mentioning_you = Mentioning you +issues.filter_type.review_requested = Review requested issues.filter_sort = Sort issues.filter_sort.latest = Newest issues.filter_sort.oldest = Oldest diff --git a/routers/repo/issue.go b/routers/repo/issue.go index b999f2f51b10a..183168e6b92d8 100644 --- a/routers/repo/issue.go +++ b/routers/repo/issue.go @@ -113,16 +113,17 @@ func issues(ctx *context.Context, milestoneID, projectID int64, isPullOption uti var err error viewType := ctx.Query("type") sortType := ctx.Query("sort") - types := []string{"all", "your_repositories", "assigned", "created_by", "mentioned"} + types := []string{"all", "your_repositories", "assigned", "created_by", "mentioned", "review_requested"} if !com.IsSliceContainsStr(types, viewType) { viewType = "all" } var ( - assigneeID = ctx.QueryInt64("assignee") - posterID int64 - mentionedID int64 - forceEmpty bool + assigneeID = ctx.QueryInt64("assignee") + posterID int64 + mentionedID int64 + reviewRequestedID int64 + forceEmpty bool ) if ctx.IsSigned { @@ -133,6 +134,8 @@ func issues(ctx *context.Context, milestoneID, projectID int64, isPullOption uti mentionedID = ctx.User.ID case "assigned": assigneeID = ctx.User.ID + case "review_requested": + reviewRequestedID = ctx.User.ID } } @@ -169,14 +172,15 @@ func issues(ctx *context.Context, milestoneID, projectID int64, isPullOption uti issueStats = &models.IssueStats{} } else { issueStats, err = models.GetIssueStats(&models.IssueStatsOptions{ - RepoID: repo.ID, - Labels: selectLabels, - MilestoneID: milestoneID, - AssigneeID: assigneeID, - MentionedID: mentionedID, - PosterID: posterID, - IsPull: isPullOption, - IssueIDs: issueIDs, + RepoID: repo.ID, + Labels: selectLabels, + MilestoneID: milestoneID, + AssigneeID: assigneeID, + MentionedID: mentionedID, + PosterID: posterID, + ReviewRequestedID: reviewRequestedID, + IsPull: isPullOption, + IssueIDs: issueIDs, }) if err != nil { ctx.ServerError("GetIssueStats", err) @@ -217,17 +221,18 @@ func issues(ctx *context.Context, milestoneID, projectID int64, isPullOption uti Page: pager.Paginater.Current(), PageSize: setting.UI.IssuePagingNum, }, - RepoIDs: []int64{repo.ID}, - AssigneeID: assigneeID, - PosterID: posterID, - MentionedID: mentionedID, - MilestoneIDs: mileIDs, - ProjectID: projectID, - IsClosed: util.OptionalBoolOf(isShowClosed), - IsPull: isPullOption, - LabelIDs: labelIDs, - SortType: sortType, - IssueIDs: issueIDs, + RepoIDs: []int64{repo.ID}, + AssigneeID: assigneeID, + PosterID: posterID, + MentionedID: mentionedID, + ReviewRequestedID: reviewRequestedID, + MilestoneIDs: mileIDs, + ProjectID: projectID, + IsClosed: util.OptionalBoolOf(isShowClosed), + IsPull: isPullOption, + LabelIDs: labelIDs, + SortType: sortType, + IssueIDs: issueIDs, }) if err != nil { ctx.ServerError("Issues", err) diff --git a/routers/user/home.go b/routers/user/home.go index 92a9138475c55..c541ea65e827f 100644 --- a/routers/user/home.go +++ b/routers/user/home.go @@ -374,6 +374,8 @@ func Issues(ctx *context.Context) { filterMode = models.FilterModeCreate case "mentioned": filterMode = models.FilterModeMention + case "review_requested": + filterMode = models.FilterModeReviewRequested case "your_repositories": // filterMode already set to All default: viewType = "your_repositories" @@ -452,6 +454,8 @@ func Issues(ctx *context.Context) { opts.PosterID = ctxUser.ID case models.FilterModeMention: opts.MentionedID = ctxUser.ID + case models.FilterModeReviewRequested: + opts.ReviewRequestedID = ctxUser.ID } var forceEmpty bool diff --git a/templates/repo/issue/list.tmpl b/templates/repo/issue/list.tmpl index 2b64d26700628..7b856e60cb6cb 100644 --- a/templates/repo/issue/list.tmpl +++ b/templates/repo/issue/list.tmpl @@ -89,6 +89,9 @@ {{.i18n.Tr "repo.issues.filter_type.assigned_to_you"}} {{.i18n.Tr "repo.issues.filter_type.created_by_you"}} {{.i18n.Tr "repo.issues.filter_type.mentioning_you"}} + {{if .PageIsPullList}} + {{.i18n.Tr "repo.issues.filter_type.review_requested"}} + {{end}} {{end}} diff --git a/templates/repo/issue/milestone_issues.tmpl b/templates/repo/issue/milestone_issues.tmpl index 638134c442620..c2c81682ff0ff 100644 --- a/templates/repo/issue/milestone_issues.tmpl +++ b/templates/repo/issue/milestone_issues.tmpl @@ -88,6 +88,7 @@ {{.i18n.Tr "repo.issues.filter_type.assigned_to_you"}} {{.i18n.Tr "repo.issues.filter_type.created_by_you"}} {{.i18n.Tr "repo.issues.filter_type.mentioning_you"}} + {{.i18n.Tr "repo.issues.filter_type.review_requested"}} {{end}} diff --git a/templates/user/dashboard/issues.tmpl b/templates/user/dashboard/issues.tmpl index b8625ec2c1543..edc525e08d318 100644 --- a/templates/user/dashboard/issues.tmpl +++ b/templates/user/dashboard/issues.tmpl @@ -22,6 +22,12 @@ {{.i18n.Tr "repo.issues.filter_type.mentioning_you"}} {{CountFmt .IssueStats.MentionCount}} + {{if .PageIsPulls}} + + {{.i18n.Tr "repo.issues.filter_type.review_requested"}} + {{CountFmt .IssueStats.ReviewRequestedCount}} + + {{end}} {{end}}
From 92c25fa992ca21882e23202699d55d4f1750d61c Mon Sep 17 00:00:00 2001 From: Jimmy Praet Date: Tue, 22 Dec 2020 10:47:32 +0100 Subject: [PATCH 2/5] add review_requested filter to /repos/issues/search API endpoint --- routers/api/v1/repo/issue.go | 9 ++++++++- templates/swagger/v1_json.tmpl | 6 ++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/routers/api/v1/repo/issue.go b/routers/api/v1/repo/issue.go index 25153ad50773c..bab8f373ce271 100644 --- a/routers/api/v1/repo/issue.go +++ b/routers/api/v1/repo/issue.go @@ -79,6 +79,10 @@ func SearchIssues(ctx *context.APIContext) { // in: query // description: filter (issues / pulls) mentioning you, default is false // type: boolean + // - name: review_requested + // in: query + // description: filter pulls requesting your review, default is false + // type: boolean // - name: page // in: query // description: page number of results to return (1-based) @@ -204,7 +208,7 @@ func SearchIssues(ctx *context.APIContext) { UpdatedAfterUnix: since, } - // Filter for: Created by User, Assigned to User, Mentioning User + // Filter for: Created by User, Assigned to User, Mentioning User, Review of User Requested if ctx.QueryBool("created") { issuesOpt.PosterID = ctx.User.ID } @@ -214,6 +218,9 @@ func SearchIssues(ctx *context.APIContext) { if ctx.QueryBool("mentioned") { issuesOpt.MentionedID = ctx.User.ID } + if ctx.QueryBool("review_requested") { + issuesOpt.ReviewRequestedID = ctx.User.ID + } if issues, err = models.Issues(issuesOpt); err != nil { ctx.Error(http.StatusInternalServerError, "Issues", err) diff --git a/templates/swagger/v1_json.tmpl b/templates/swagger/v1_json.tmpl index d0303040c56fb..96a9d03691670 100644 --- a/templates/swagger/v1_json.tmpl +++ b/templates/swagger/v1_json.tmpl @@ -1911,6 +1911,12 @@ "name": "mentioned", "in": "query" }, + { + "type": "boolean", + "description": "filter pulls requesting your review, default is false", + "name": "review_requested", + "in": "query" + }, { "type": "integer", "description": "page number of results to return (1-based)", From 4ee14d2df28207cb3838e6c0a27265f67b5a2368 Mon Sep 17 00:00:00 2001 From: Jimmy Praet Date: Tue, 22 Dec 2020 20:08:14 +0100 Subject: [PATCH 3/5] only Approve and Reject status should supersede Request status --- models/issue.go | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/models/issue.go b/models/issue.go index e26db0805586e..aa7f6663a7325 100644 --- a/models/issue.go +++ b/models/issue.go @@ -1181,7 +1181,8 @@ func (opts *IssuesOptions) setupSession(sess *xorm.Session) { sess.Join("INNER", []string{"review", "r"}, "issue.id = r.issue_id"). And("r.reviewer_id = ?", opts.ReviewRequestedID). And("r.type = ?", ReviewTypeRequest). - And("r.id in (select max(id) from review where issue_id = r.issue_id and reviewer_id = r.reviewer_id)") + And("r.id in (select max(id) from review where issue_id = r.issue_id and reviewer_id = r.reviewer_id and type in (?, ?, ?))", + ReviewTypeApprove, ReviewTypeReject, ReviewTypeRequest) } if len(opts.MilestoneIDs) > 0 { @@ -1484,7 +1485,8 @@ func getIssueStatsChunk(opts *IssueStatsOptions, issueIDs []int64) (*IssueStats, sess.Join("INNER", []string{"review", "r"}, "issue.id = r.issue_id"). And("r.reviewer_id = ?", opts.ReviewRequestedID). And("r.type = ?", ReviewTypeRequest). - And("r.id in (select max(id) from review where issue_id = r.issue_id and reviewer_id = r.reviewer_id)") + And("r.id in (select max(id) from review where issue_id = r.issue_id and reviewer_id = r.reviewer_id and type in (?, ?, ?))", + ReviewTypeApprove, ReviewTypeReject, ReviewTypeRequest) } switch opts.IsPull { @@ -1597,7 +1599,8 @@ func GetUserIssueStats(opts UserIssueStatsOptions) (*IssueStats, error) { Join("INNER", []string{"review", "r"}, "issue.id = r.issue_id"). And("r.reviewer_id = ?", opts.UserID). And("r.type = ?", ReviewTypeRequest). - And("r.id in (select max(id) from review where issue_id = r.issue_id and reviewer_id = r.reviewer_id)"). + And("r.id in (select max(id) from review where issue_id = r.issue_id and reviewer_id = r.reviewer_id and type in (?, ?, ?))", + ReviewTypeApprove, ReviewTypeReject, ReviewTypeRequest). Count(new(Issue)) if err != nil { return nil, err @@ -1606,7 +1609,8 @@ func GetUserIssueStats(opts UserIssueStatsOptions) (*IssueStats, error) { Join("INNER", []string{"review", "r"}, "issue.id = r.issue_id"). And("r.reviewer_id = ?", opts.UserID). And("r.type = ?", ReviewTypeRequest). - And("r.id in (select max(id) from review where issue_id = r.issue_id and reviewer_id = r.reviewer_id)"). + And("r.id in (select max(id) from review where issue_id = r.issue_id and reviewer_id = r.reviewer_id and type in (?, ?, ?))", + ReviewTypeApprove, ReviewTypeReject, ReviewTypeRequest). Count(new(Issue)) if err != nil { return nil, err @@ -1648,7 +1652,8 @@ func GetUserIssueStats(opts UserIssueStatsOptions) (*IssueStats, error) { Join("INNER", []string{"review", "r"}, "issue.id = r.issue_id"). And("r.reviewer_id = ?", opts.UserID). And("r.type = ?", ReviewTypeRequest). - And("r.id in (select max(id) from review where issue_id = r.issue_id and reviewer_id = r.reviewer_id)"). + And("r.id in (select max(id) from review where issue_id = r.issue_id and reviewer_id = r.reviewer_id and type in (?, ?, ?))", + ReviewTypeApprove, ReviewTypeReject, ReviewTypeRequest). Count(new(Issue)) if err != nil { return nil, err From f2c1fbea9e7de4147b2dc534ec26ae729c09f25e Mon Sep 17 00:00:00 2001 From: Jimmy Praet Date: Sun, 3 Jan 2021 14:42:02 +0100 Subject: [PATCH 4/5] add support for team reviews --- models/issue.go | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/models/issue.go b/models/issue.go index 12c56bba9255c..2b5d1e557c1ce 100644 --- a/models/issue.go +++ b/models/issue.go @@ -1179,10 +1179,10 @@ func (opts *IssuesOptions) setupSession(sess *xorm.Session) { if opts.ReviewRequestedID > 0 { sess.Join("INNER", []string{"review", "r"}, "issue.id = r.issue_id"). - And("r.reviewer_id = ?", opts.ReviewRequestedID). And("r.type = ?", ReviewTypeRequest). - And("r.id in (select max(id) from review where issue_id = r.issue_id and reviewer_id = r.reviewer_id and type in (?, ?, ?))", - ReviewTypeApprove, ReviewTypeReject, ReviewTypeRequest) + And("r.reviewer_id = ? and r.id in (select max(id) from review where issue_id = r.issue_id and reviewer_id = r.reviewer_id and type in (?, ?, ?))"+ + " or r.reviewer_team_id in (select team_id from team_user where uid = ?)", + opts.ReviewRequestedID, ReviewTypeApprove, ReviewTypeReject, ReviewTypeRequest, opts.ReviewRequestedID) } if len(opts.MilestoneIDs) > 0 { @@ -1484,10 +1484,10 @@ func getIssueStatsChunk(opts *IssueStatsOptions, issueIDs []int64) (*IssueStats, if opts.ReviewRequestedID > 0 { sess.Join("INNER", []string{"review", "r"}, "issue.id = r.issue_id"). - And("r.reviewer_id = ?", opts.ReviewRequestedID). And("r.type = ?", ReviewTypeRequest). - And("r.id in (select max(id) from review where issue_id = r.issue_id and reviewer_id = r.reviewer_id and type in (?, ?, ?))", - ReviewTypeApprove, ReviewTypeReject, ReviewTypeRequest) + And("r.reviewer_id = ? and r.id in (select max(id) from review where issue_id = r.issue_id and reviewer_id = r.reviewer_id and type in (?, ?, ?))"+ + " or r.reviewer_team_id in (select team_id from team_user where uid = ?)", + opts.ReviewRequestedID, ReviewTypeApprove, ReviewTypeReject, ReviewTypeRequest, opts.ReviewRequestedID) } switch opts.IsPull { @@ -1608,20 +1608,20 @@ func GetUserIssueStats(opts UserIssueStatsOptions) (*IssueStats, error) { case FilterModeReviewRequested: stats.OpenCount, err = x.Where(cond).And("issue.is_closed = ?", false). Join("INNER", []string{"review", "r"}, "issue.id = r.issue_id"). - And("r.reviewer_id = ?", opts.UserID). And("r.type = ?", ReviewTypeRequest). - And("r.id in (select max(id) from review where issue_id = r.issue_id and reviewer_id = r.reviewer_id and type in (?, ?, ?))", - ReviewTypeApprove, ReviewTypeReject, ReviewTypeRequest). + And("r.reviewer_id = ? and r.id in (select max(id) from review where issue_id = r.issue_id and reviewer_id = r.reviewer_id and type in (?, ?, ?))"+ + " or r.reviewer_team_id in (select team_id from team_user where uid = ?)", + opts.UserID, ReviewTypeApprove, ReviewTypeReject, ReviewTypeRequest, opts.UserID). Count(new(Issue)) if err != nil { return nil, err } stats.ClosedCount, err = x.Where(cond).And("issue.is_closed = ?", true). Join("INNER", []string{"review", "r"}, "issue.id = r.issue_id"). - And("r.reviewer_id = ?", opts.UserID). And("r.type = ?", ReviewTypeRequest). - And("r.id in (select max(id) from review where issue_id = r.issue_id and reviewer_id = r.reviewer_id and type in (?, ?, ?))", - ReviewTypeApprove, ReviewTypeReject, ReviewTypeRequest). + And("r.reviewer_id = ? and r.id in (select max(id) from review where issue_id = r.issue_id and reviewer_id = r.reviewer_id and type in (?, ?, ?))"+ + " or r.reviewer_team_id in (select team_id from team_user where uid = ?)", + opts.UserID, ReviewTypeApprove, ReviewTypeReject, ReviewTypeRequest, opts.UserID). Count(new(Issue)) if err != nil { return nil, err @@ -1661,10 +1661,10 @@ func GetUserIssueStats(opts UserIssueStatsOptions) (*IssueStats, error) { stats.ReviewRequestedCount, err = x.Where(cond). Join("INNER", []string{"review", "r"}, "issue.id = r.issue_id"). - And("r.reviewer_id = ?", opts.UserID). And("r.type = ?", ReviewTypeRequest). - And("r.id in (select max(id) from review where issue_id = r.issue_id and reviewer_id = r.reviewer_id and type in (?, ?, ?))", - ReviewTypeApprove, ReviewTypeReject, ReviewTypeRequest). + And("r.reviewer_id = ? and r.id in (select max(id) from review where issue_id = r.issue_id and reviewer_id = r.reviewer_id and type in (?, ?, ?))"+ + " or r.reviewer_team_id in (select team_id from team_user where uid = ?)", + opts.UserID, ReviewTypeApprove, ReviewTypeReject, ReviewTypeRequest, opts.UserID). Count(new(Issue)) if err != nil { return nil, err From 8820bb9af8ddacd294bdb6abd84ddcb94cf64a72 Mon Sep 17 00:00:00 2001 From: Jimmy Praet Date: Sun, 3 Jan 2021 15:39:22 +0100 Subject: [PATCH 5/5] refactor: remove duplication of issue filtering conditions --- models/issue.go | 148 +++++++++++++++++++++--------------------------- 1 file changed, 65 insertions(+), 83 deletions(-) diff --git a/models/issue.go b/models/issue.go index 2b5d1e557c1ce..31bac96f9f341 100644 --- a/models/issue.go +++ b/models/issue.go @@ -1151,8 +1151,7 @@ func (opts *IssuesOptions) setupSession(sess *xorm.Session) { } if len(opts.RepoIDs) > 0 { - // In case repository IDs are provided but actually no repository has issue. - sess.In("issue.repo_id", opts.RepoIDs) + applyReposCondition(sess, opts.RepoIDs) } switch opts.IsClosed { @@ -1163,26 +1162,19 @@ func (opts *IssuesOptions) setupSession(sess *xorm.Session) { } if opts.AssigneeID > 0 { - sess.Join("INNER", "issue_assignees", "issue.id = issue_assignees.issue_id"). - And("issue_assignees.assignee_id = ?", opts.AssigneeID) + applyAssigneeCondition(sess, opts.AssigneeID) } if opts.PosterID > 0 { - sess.And("issue.poster_id=?", opts.PosterID) + applyPosterCondition(sess, opts.PosterID) } if opts.MentionedID > 0 { - sess.Join("INNER", "issue_user", "issue.id = issue_user.issue_id"). - And("issue_user.is_mentioned = ?", true). - And("issue_user.uid = ?", opts.MentionedID) + applyMentionedCondition(sess, opts.MentionedID) } if opts.ReviewRequestedID > 0 { - sess.Join("INNER", []string{"review", "r"}, "issue.id = r.issue_id"). - And("r.type = ?", ReviewTypeRequest). - And("r.reviewer_id = ? and r.id in (select max(id) from review where issue_id = r.issue_id and reviewer_id = r.reviewer_id and type in (?, ?, ?))"+ - " or r.reviewer_team_id in (select team_id from team_user where uid = ?)", - opts.ReviewRequestedID, ReviewTypeApprove, ReviewTypeReject, ReviewTypeRequest, opts.ReviewRequestedID) + applyReviewRequestedCondition(sess, opts.ReviewRequestedID) } if len(opts.MilestoneIDs) > 0 { @@ -1236,6 +1228,33 @@ func (opts *IssuesOptions) setupSession(sess *xorm.Session) { } } +func applyReposCondition(sess *xorm.Session, repoIDs []int64) *xorm.Session { + return sess.In("issue.repo_id", repoIDs) +} + +func applyAssigneeCondition(sess *xorm.Session, assigneeID int64) *xorm.Session { + return sess.Join("INNER", "issue_assignees", "issue.id = issue_assignees.issue_id"). + And("issue_assignees.assignee_id = ?", assigneeID) +} + +func applyPosterCondition(sess *xorm.Session, posterID int64) *xorm.Session { + return sess.And("issue.poster_id=?", posterID) +} + +func applyMentionedCondition(sess *xorm.Session, mentionedID int64) *xorm.Session { + return sess.Join("INNER", "issue_user", "issue.id = issue_user.issue_id"). + And("issue_user.is_mentioned = ?", true). + And("issue_user.uid = ?", mentionedID) +} + +func applyReviewRequestedCondition(sess *xorm.Session, reviewRequestedID int64) *xorm.Session { + return sess.Join("INNER", []string{"review", "r"}, "issue.id = r.issue_id"). + And("r.type = ?", ReviewTypeRequest). + And("r.reviewer_id = ? and r.id in (select max(id) from review where issue_id = r.issue_id and reviewer_id = r.reviewer_id and type in (?, ?, ?))"+ + " or r.reviewer_team_id in (select team_id from team_user where uid = ?)", + reviewRequestedID, ReviewTypeApprove, ReviewTypeReject, ReviewTypeRequest, reviewRequestedID) +} + // CountIssuesByRepo map from repoID to number of issues matching the options func CountIssuesByRepo(opts *IssuesOptions) (map[int64]int64, error) { sess := x.NewSession() @@ -1468,26 +1487,19 @@ func getIssueStatsChunk(opts *IssueStatsOptions, issueIDs []int64) (*IssueStats, } if opts.AssigneeID > 0 { - sess.Join("INNER", "issue_assignees", "issue.id = issue_assignees.issue_id"). - And("issue_assignees.assignee_id = ?", opts.AssigneeID) + applyAssigneeCondition(sess, opts.AssigneeID) } if opts.PosterID > 0 { - sess.And("issue.poster_id = ?", opts.PosterID) + applyPosterCondition(sess, opts.PosterID) } if opts.MentionedID > 0 { - sess.Join("INNER", "issue_user", "issue.id = issue_user.issue_id"). - And("issue_user.uid = ?", opts.MentionedID). - And("issue_user.is_mentioned = ?", true) + applyMentionedCondition(sess, opts.MentionedID) } if opts.ReviewRequestedID > 0 { - sess.Join("INNER", []string{"review", "r"}, "issue.id = r.issue_id"). - And("r.type = ?", ReviewTypeRequest). - And("r.reviewer_id = ? and r.id in (select max(id) from review where issue_id = r.issue_id and reviewer_id = r.reviewer_id and type in (?, ?, ?))"+ - " or r.reviewer_team_id in (select team_id from team_user where uid = ?)", - opts.ReviewRequestedID, ReviewTypeApprove, ReviewTypeReject, ReviewTypeRequest, opts.ReviewRequestedID) + applyReviewRequestedCondition(sess, opts.ReviewRequestedID) } switch opts.IsPull { @@ -1550,78 +1562,66 @@ func GetUserIssueStats(opts UserIssueStatsOptions) (*IssueStats, error) { switch opts.FilterMode { case FilterModeAll: - stats.OpenCount, err = sess(cond).And("issue.is_closed = ?", false). - And(builder.In("issue.repo_id", opts.UserRepoIDs)). + stats.OpenCount, err = applyReposCondition(sess(cond), opts.UserRepoIDs). + And("issue.is_closed = ?", false). Count(new(Issue)) if err != nil { return nil, err } - stats.ClosedCount, err = sess(cond).And("issue.is_closed = ?", true). - And(builder.In("issue.repo_id", opts.UserRepoIDs)). + stats.ClosedCount, err = applyReposCondition(sess(cond), opts.UserRepoIDs). + And("issue.is_closed = ?", true). Count(new(Issue)) if err != nil { return nil, err } case FilterModeAssign: - stats.OpenCount, err = sess(cond).And("issue.is_closed = ?", false). - Join("INNER", "issue_assignees", "issue.id = issue_assignees.issue_id"). - And("issue_assignees.assignee_id = ?", opts.UserID). + stats.OpenCount, err = applyAssigneeCondition(sess(cond), opts.UserID). + And("issue.is_closed = ?", false). Count(new(Issue)) if err != nil { return nil, err } - stats.ClosedCount, err = sess(cond).And("issue.is_closed = ?", true). - Join("INNER", "issue_assignees", "issue.id = issue_assignees.issue_id"). - And("issue_assignees.assignee_id = ?", opts.UserID). + stats.ClosedCount, err = applyAssigneeCondition(sess(cond), opts.UserID). + And("issue.is_closed = ?", true). Count(new(Issue)) if err != nil { return nil, err } case FilterModeCreate: - stats.OpenCount, err = sess(cond).And("issue.is_closed = ?", false). - And("issue.poster_id = ?", opts.UserID). + stats.OpenCount, err = applyPosterCondition(sess(cond), opts.UserID). + And("issue.is_closed = ?", false). Count(new(Issue)) if err != nil { return nil, err } - stats.ClosedCount, err = sess(cond).And("issue.is_closed = ?", true). - And("issue.poster_id = ?", opts.UserID). + stats.ClosedCount, err = applyPosterCondition(sess(cond), opts.UserID). + And("issue.is_closed = ?", true). Count(new(Issue)) if err != nil { return nil, err } case FilterModeMention: - stats.OpenCount, err = sess(cond).And("issue.is_closed = ?", false). - Join("INNER", "issue_user", "issue.id = issue_user.issue_id and issue_user.is_mentioned = ?", true). - And("issue_user.uid = ?", opts.UserID). + stats.OpenCount, err = applyMentionedCondition(sess(cond), opts.UserID). + And("issue.is_closed = ?", false). Count(new(Issue)) if err != nil { return nil, err } - stats.ClosedCount, err = sess(cond).And("issue.is_closed = ?", true). - Join("INNER", "issue_user", "issue.id = issue_user.issue_id and issue_user.is_mentioned = ?", true). - And("issue_user.uid = ?", opts.UserID). + stats.ClosedCount, err = applyMentionedCondition(sess(cond), opts.UserID). + And("issue.is_closed = ?", true). Count(new(Issue)) if err != nil { return nil, err } case FilterModeReviewRequested: - stats.OpenCount, err = x.Where(cond).And("issue.is_closed = ?", false). - Join("INNER", []string{"review", "r"}, "issue.id = r.issue_id"). - And("r.type = ?", ReviewTypeRequest). - And("r.reviewer_id = ? and r.id in (select max(id) from review where issue_id = r.issue_id and reviewer_id = r.reviewer_id and type in (?, ?, ?))"+ - " or r.reviewer_team_id in (select team_id from team_user where uid = ?)", - opts.UserID, ReviewTypeApprove, ReviewTypeReject, ReviewTypeRequest, opts.UserID). + stats.OpenCount, err = applyReviewRequestedCondition(sess(cond), opts.UserID). + And("issue.is_closed = ?", false). Count(new(Issue)) if err != nil { return nil, err } - stats.ClosedCount, err = x.Where(cond).And("issue.is_closed = ?", true). - Join("INNER", []string{"review", "r"}, "issue.id = r.issue_id"). - And("r.type = ?", ReviewTypeRequest). - And("r.reviewer_id = ? and r.id in (select max(id) from review where issue_id = r.issue_id and reviewer_id = r.reviewer_id and type in (?, ?, ?))"+ - " or r.reviewer_team_id in (select team_id from team_user where uid = ?)", - opts.UserID, ReviewTypeApprove, ReviewTypeReject, ReviewTypeRequest, opts.UserID). + stats.ClosedCount, err = applyReviewRequestedCondition(sess(cond), opts.UserID). + And("issue.is_closed = ?", true). Count(new(Issue)) if err != nil { return nil, err @@ -1629,43 +1629,27 @@ func GetUserIssueStats(opts UserIssueStatsOptions) (*IssueStats, error) { } cond = cond.And(builder.Eq{"issue.is_closed": opts.IsClosed}) - stats.AssignCount, err = sess(cond). - Join("INNER", "issue_assignees", "issue.id = issue_assignees.issue_id"). - And("issue_assignees.assignee_id = ?", opts.UserID). - Count(new(Issue)) + stats.AssignCount, err = applyAssigneeCondition(sess(cond), opts.UserID).Count(new(Issue)) if err != nil { return nil, err } - stats.CreateCount, err = sess(cond). - And("poster_id = ?", opts.UserID). - Count(new(Issue)) + stats.CreateCount, err = applyPosterCondition(sess(cond), opts.UserID).Count(new(Issue)) if err != nil { return nil, err } - stats.MentionCount, err = sess(cond). - Join("INNER", "issue_user", "issue.id = issue_user.issue_id and issue_user.is_mentioned = ?", true). - And("issue_user.uid = ?", opts.UserID). - Count(new(Issue)) + stats.MentionCount, err = applyMentionedCondition(sess(cond), opts.UserID).Count(new(Issue)) if err != nil { return nil, err } - stats.YourRepositoriesCount, err = sess(cond). - And(builder.In("issue.repo_id", opts.UserRepoIDs)). - Count(new(Issue)) + stats.YourRepositoriesCount, err = applyReposCondition(sess(cond), opts.UserRepoIDs).Count(new(Issue)) if err != nil { return nil, err } - stats.ReviewRequestedCount, err = x.Where(cond). - Join("INNER", []string{"review", "r"}, "issue.id = r.issue_id"). - And("r.type = ?", ReviewTypeRequest). - And("r.reviewer_id = ? and r.id in (select max(id) from review where issue_id = r.issue_id and reviewer_id = r.reviewer_id and type in (?, ?, ?))"+ - " or r.reviewer_team_id in (select team_id from team_user where uid = ?)", - opts.UserID, ReviewTypeApprove, ReviewTypeReject, ReviewTypeRequest, opts.UserID). - Count(new(Issue)) + stats.ReviewRequestedCount, err = applyReviewRequestedCondition(sess(cond), opts.UserID).Count(new(Issue)) if err != nil { return nil, err } @@ -1689,13 +1673,11 @@ func GetRepoIssueStats(repoID, uid int64, filterMode int, isPull bool) (numOpen switch filterMode { case FilterModeAssign: - openCountSession.Join("INNER", "issue_assignees", "issue.id = issue_assignees.issue_id"). - And("issue_assignees.assignee_id = ?", uid) - closedCountSession.Join("INNER", "issue_assignees", "issue.id = issue_assignees.issue_id"). - And("issue_assignees.assignee_id = ?", uid) + applyAssigneeCondition(openCountSession, uid) + applyAssigneeCondition(closedCountSession, uid) case FilterModeCreate: - openCountSession.And("poster_id = ?", uid) - closedCountSession.And("poster_id = ?", uid) + applyPosterCondition(openCountSession, uid) + applyPosterCondition(closedCountSession, uid) } openResult, _ := openCountSession.Count(new(Issue))