Skip to content

Commit

Permalink
Merge remote-tracking branch 'master/master' into feature-reference-i…
Browse files Browse the repository at this point in the history
…n-issue
  • Loading branch information
KN4CK3R committed Jan 17, 2021
2 parents e360800 + ca63a9d commit 7e9beb1
Show file tree
Hide file tree
Showing 24 changed files with 310 additions and 130 deletions.
161 changes: 98 additions & 63 deletions models/issue.go
Original file line number Diff line number Diff line change
Expand Up @@ -1090,6 +1090,7 @@ type IssuesOptions struct {
AssigneeID int64
PosterID int64
MentionedID int64
ReviewRequestedID int64
MilestoneIDs []int64
ProjectID int64
ProjectBoardID int64
Expand Down Expand Up @@ -1151,8 +1152,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 {
Expand All @@ -1163,18 +1163,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 {
applyReviewRequestedCondition(sess, opts.ReviewRequestedID)
}

if len(opts.MilestoneIDs) > 0 {
Expand Down Expand Up @@ -1232,6 +1233,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()
Expand Down Expand Up @@ -1364,6 +1392,7 @@ type IssueStats struct {
AssignCount int64
CreateCount int64
MentionCount int64
ReviewRequestedCount int64
}

// Filter modes.
Expand All @@ -1372,6 +1401,7 @@ const (
FilterModeAssign
FilterModeCreate
FilterModeMention
FilterModeReviewRequested
)

func parseCountResult(results []map[string][]byte) int64 {
Expand All @@ -1387,14 +1417,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.
Expand Down Expand Up @@ -1423,6 +1454,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
Expand Down Expand Up @@ -1460,18 +1492,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 {
applyReviewRequestedCondition(sess, opts.ReviewRequestedID)
}

switch opts.IsPull {
Expand Down Expand Up @@ -1539,90 +1572,94 @@ 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 = applyReviewRequestedCondition(sess(cond), opts.UserID).
And("issue.is_closed = ?", false).
Count(new(Issue))
if err != nil {
return nil, err
}
stats.ClosedCount, err = applyReviewRequestedCondition(sess(cond), opts.UserID).
And("issue.is_closed = ?", true).
Count(new(Issue))
if err != nil {
return nil, err
}
}

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 = applyReviewRequestedCondition(sess(cond), opts.UserID).Count(new(Issue))
if err != nil {
return nil, err
}
Expand All @@ -1646,13 +1683,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))
Expand Down Expand Up @@ -1682,7 +1717,7 @@ func SearchIssueIDsByKeyword(kw string, repoIDs []int64, limit, start int) (int6
)

var ids = make([]int64, 0, limit)
err := x.Distinct("id").Table("issue").Where(cond).Limit(limit, start).Find(&ids)
err := x.Distinct("id").Table("issue").Where(cond).OrderBy("`updated_unix` DESC").Limit(limit, start).Find(&ids)
if err != nil {
return 0, nil, err
}
Expand Down
2 changes: 1 addition & 1 deletion models/issue_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -299,7 +299,7 @@ func TestIssue_SearchIssueIDsByKeyword(t *testing.T) {
total, ids, err = SearchIssueIDsByKeyword("for", []int64{1}, 10, 0)
assert.NoError(t, err)
assert.EqualValues(t, 5, total)
assert.EqualValues(t, []int64{1, 2, 3, 5, 11}, ids)
assert.ElementsMatch(t, []int64{1, 2, 3, 5, 11}, ids)

// issue1's comment id 2
total, ids, err = SearchIssueIDsByKeyword("good", []int64{1}, 10, 0)
Expand Down
1 change: 1 addition & 0 deletions modules/indexer/issues/bleve.go
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,7 @@ func (b *BleveIndexer) Search(keyword string, repoIDs []int64, limit, start int)
newMatchPhraseQuery(keyword, "Comments", issueIndexerAnalyzer),
))
search := bleve.NewSearchRequestOptions(indexerQuery, limit, start, false)
search.SortBy([]string{"-_score"})

result, err := b.indexer.Search(search)
if err != nil {
Expand Down
2 changes: 1 addition & 1 deletion modules/indexer/issues/elastic_search.go
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ func (b *ElasticSearchIndexer) Search(keyword string, repoIDs []int64, limit, st
searchResult, err := b.client.Search().
Index(b.indexerName).
Query(query).
Sort("id", true).
Sort("_score", false).
From(start).Size(limit).
Do(context.Background())
if err != nil {
Expand Down
4 changes: 2 additions & 2 deletions modules/indexer/issues/indexer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ func TestBleveSearchIssues(t *testing.T) {

ids, err = SearchIssuesByKeyword([]int64{1}, "for")
assert.NoError(t, err)
assert.EqualValues(t, []int64{1, 2, 3, 5, 11}, ids)
assert.ElementsMatch(t, []int64{1, 2, 3, 5, 11}, ids)

ids, err = SearchIssuesByKeyword([]int64{1}, "good")
assert.NoError(t, err)
Expand All @@ -89,7 +89,7 @@ func TestDBSearchIssues(t *testing.T) {

ids, err = SearchIssuesByKeyword([]int64{1}, "for")
assert.NoError(t, err)
assert.EqualValues(t, []int64{1, 2, 3, 5, 11}, ids)
assert.ElementsMatch(t, []int64{1, 2, 3, 5, 11}, ids)

ids, err = SearchIssuesByKeyword([]int64{1}, "good")
assert.NoError(t, err)
Expand Down
1 change: 1 addition & 0 deletions options/locale/locale_en-US.ini
Original file line number Diff line number Diff line change
Expand Up @@ -1030,6 +1030,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
Expand Down
9 changes: 9 additions & 0 deletions options/locale/locale_ja-JP.ini
Original file line number Diff line number Diff line change
Expand Up @@ -358,6 +358,7 @@ password_not_match=パスワードが一致しません。
lang_select_error=言語をリストから選択してください。

username_been_taken=ユーザー名が既に使用されています。
username_change_not_local_user=非ローカルユーザーのユーザー名は変更できません。
repo_name_been_taken=リポジトリ名が既に使用されています。
repository_files_already_exist=このリポジトリのファイルはすでに存在します。システム管理者に問い合わせてください。
repository_files_already_exist.adopt=このリポジトリのファイルはすでに存在しており、それらを登録することしかできません。
Expand Down Expand Up @@ -821,6 +822,8 @@ tag=タグ
released_this=がこれをリリース
file_raw=Raw
file_history=履歴
file_view_source=ソースを表示
file_view_rendered=レンダリング表示
file_view_raw=Rawデータを見る
file_permalink=パーマリンク
file_too_large=このファイルは大きすぎるため、表示できません。
Expand Down Expand Up @@ -1997,6 +2000,7 @@ dashboard=ダッシュボード
users=ユーザーアカウント
organizations=組織
repositories=リポジトリ
hooks=Webhook
authentication=認証ソース
emails=ユーザーメールアドレス
config=設定
Expand Down Expand Up @@ -2146,8 +2150,13 @@ repos.forks=フォーク
repos.issues=課題
repos.size=サイズ

defaulthooks=デフォルトWebhook
defaulthooks.desc=Webhookは、特定のGiteaイベントトリガーが発生した際に、自動的にHTTP POSTリクエストをサーバーへ送信するものです。 ここで定義されたWebhookはデフォルトとなり、全ての新規リポジトリにコピーされます。 詳しくは<a target="_blank" rel="noopener" href="https://docs.gitea.io/en-us/webhooks/">webhooks guide</a>をご覧下さい。
defaulthooks.add_webhook=デフォルトWebhookの追加
defaulthooks.update_webhook=デフォルトWebhookの更新

systemhooks=システムWebhook
systemhooks.desc=Webhookは、特定のGiteaイベントトリガーが発生した際に、自動的にHTTP POSTリクエストをサーバーへ送信するものです。 ここで定義したWebhookはシステム内のすべてのリポジトリで呼び出されます。 そのため、パフォーマンスに及ぼす影響を考慮したうえで設定してください。 詳しくは<a target="_blank" rel="noopener" href="https://docs.gitea.io/en-us/webhooks/">webhooks guide</a>をご覧下さい。
systemhooks.add_webhook=システムWebhookを追加
systemhooks.update_webhook=システムWebhookを更新

Expand Down
Loading

0 comments on commit 7e9beb1

Please sign in to comment.