Fixed count of filtered issues when api request. (#12275)
* Improved total count of issue when filtered. * Fixed size of slice when selected 1 repository. * Improved function of error check. * improved comment * Added parameter of return header. Co-authored-by: 6543 <6543@obermui.de> * Updated corresponded to the current vendored of "xorm.io/xorm". * Dedublicated it by store the Options Struct into a variable. * format code * Update routers/api/v1/repo/issue.go Co-authored-by: 6543 <6543@obermui.de> * Update routers/api/v1/repo/issue.go Co-authored-by: 6543 <6543@obermui.de> * Updated number of range. Co-authored-by: 6543 <6543@obermui.de> * Updated number of range. Co-authored-by: 6543 <6543@obermui.de> * Removed total value. * make fmt * Improved value of sql. Co-authored-by: zeripath <art27@cantab.net> * Improved value of sql. * improved message * improved message * improved message * fixed message Co-authored-by: 6543 <6543@obermui.de> Co-authored-by: zeripath <art27@cantab.net> Co-authored-by: techknowlogick <techknowlogick@gitea.io>
This commit is contained in:
parent
b5109272db
commit
6fa19a8458
|
@ -1266,7 +1266,7 @@ func Issues(opts *IssuesOptions) ([]*Issue, error) {
|
||||||
opts.setupSession(sess)
|
opts.setupSession(sess)
|
||||||
sortIssuesSession(sess, opts.SortType, opts.PriorityRepoID)
|
sortIssuesSession(sess, opts.SortType, opts.PriorityRepoID)
|
||||||
|
|
||||||
issues := make([]*Issue, 0, setting.UI.IssuePagingNum)
|
issues := make([]*Issue, 0, opts.ListOptions.PageSize)
|
||||||
if err := sess.Find(&issues); err != nil {
|
if err := sess.Find(&issues); err != nil {
|
||||||
return nil, fmt.Errorf("Find: %v", err)
|
return nil, fmt.Errorf("Find: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -1279,6 +1279,27 @@ func Issues(opts *IssuesOptions) ([]*Issue, error) {
|
||||||
return issues, nil
|
return issues, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CountIssues number return of issues by given conditions.
|
||||||
|
func CountIssues(opts *IssuesOptions) (int64, error) {
|
||||||
|
sess := x.NewSession()
|
||||||
|
defer sess.Close()
|
||||||
|
|
||||||
|
countsSlice := make([]*struct {
|
||||||
|
RepoID int64
|
||||||
|
Count int64
|
||||||
|
}, 0, 1)
|
||||||
|
|
||||||
|
sess.Select("COUNT(issue.id) AS count").Table("issue")
|
||||||
|
opts.setupSession(sess)
|
||||||
|
if err := sess.Find(&countsSlice); err != nil {
|
||||||
|
return 0, fmt.Errorf("Find: %v", err)
|
||||||
|
}
|
||||||
|
if len(countsSlice) < 1 {
|
||||||
|
return 0, fmt.Errorf("there is less than one result sql record")
|
||||||
|
}
|
||||||
|
return countsSlice[0].Count, nil
|
||||||
|
}
|
||||||
|
|
||||||
// GetParticipantsIDsByIssueID returns the IDs of all users who participated in comments of an issue,
|
// GetParticipantsIDsByIssueID returns the IDs of all users who participated in comments of an issue,
|
||||||
// but skips joining with `user` for performance reasons.
|
// but skips joining with `user` for performance reasons.
|
||||||
// User permissions must be verified elsewhere if required.
|
// User permissions must be verified elsewhere if required.
|
||||||
|
|
|
@ -93,7 +93,6 @@ func SearchIssues(ctx *context.APIContext) {
|
||||||
opts.AllLimited = true
|
opts.AllLimited = true
|
||||||
}
|
}
|
||||||
|
|
||||||
issueCount := 0
|
|
||||||
for page := 1; ; page++ {
|
for page := 1; ; page++ {
|
||||||
opts.Page = page
|
opts.Page = page
|
||||||
repos, count, err := models.SearchRepositoryByName(opts)
|
repos, count, err := models.SearchRepositoryByName(opts)
|
||||||
|
@ -107,19 +106,12 @@ func SearchIssues(ctx *context.APIContext) {
|
||||||
}
|
}
|
||||||
log.Trace("Processing next %d repos of %d", len(repos), count)
|
log.Trace("Processing next %d repos of %d", len(repos), count)
|
||||||
for _, repo := range repos {
|
for _, repo := range repos {
|
||||||
switch isClosed {
|
|
||||||
case util.OptionalBoolTrue:
|
|
||||||
issueCount += repo.NumClosedIssues
|
|
||||||
case util.OptionalBoolFalse:
|
|
||||||
issueCount += repo.NumOpenIssues
|
|
||||||
case util.OptionalBoolNone:
|
|
||||||
issueCount += repo.NumIssues
|
|
||||||
}
|
|
||||||
repoIDs = append(repoIDs, repo.ID)
|
repoIDs = append(repoIDs, repo.ID)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var issues []*models.Issue
|
var issues []*models.Issue
|
||||||
|
var filteredCount int64
|
||||||
|
|
||||||
keyword := strings.Trim(ctx.Query("q"), " ")
|
keyword := strings.Trim(ctx.Query("q"), " ")
|
||||||
if strings.IndexByte(keyword, 0) >= 0 {
|
if strings.IndexByte(keyword, 0) >= 0 {
|
||||||
|
@ -129,7 +121,10 @@ func SearchIssues(ctx *context.APIContext) {
|
||||||
var labelIDs []int64
|
var labelIDs []int64
|
||||||
var err error
|
var err error
|
||||||
if len(keyword) > 0 && len(repoIDs) > 0 {
|
if len(keyword) > 0 && len(repoIDs) > 0 {
|
||||||
issueIDs, err = issue_indexer.SearchIssuesByKeyword(repoIDs, keyword)
|
if issueIDs, err = issue_indexer.SearchIssuesByKeyword(repoIDs, keyword); err != nil {
|
||||||
|
ctx.Error(http.StatusInternalServerError, "SearchIssuesByKeyword", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var isPull util.OptionalBool
|
var isPull util.OptionalBool
|
||||||
|
@ -151,12 +146,11 @@ func SearchIssues(ctx *context.APIContext) {
|
||||||
// Only fetch the issues if we either don't have a keyword or the search returned issues
|
// Only fetch the issues if we either don't have a keyword or the search returned issues
|
||||||
// This would otherwise return all issues if no issues were found by the search.
|
// This would otherwise return all issues if no issues were found by the search.
|
||||||
if len(keyword) == 0 || len(issueIDs) > 0 || len(labelIDs) > 0 {
|
if len(keyword) == 0 || len(issueIDs) > 0 || len(labelIDs) > 0 {
|
||||||
issues, err = models.Issues(&models.IssuesOptions{
|
issuesOpt := &models.IssuesOptions{
|
||||||
ListOptions: models.ListOptions{
|
ListOptions: models.ListOptions{
|
||||||
Page: ctx.QueryInt("page"),
|
Page: ctx.QueryInt("page"),
|
||||||
PageSize: setting.UI.IssuePagingNum,
|
PageSize: setting.UI.IssuePagingNum,
|
||||||
},
|
},
|
||||||
|
|
||||||
RepoIDs: repoIDs,
|
RepoIDs: repoIDs,
|
||||||
IsClosed: isClosed,
|
IsClosed: isClosed,
|
||||||
IssueIDs: issueIDs,
|
IssueIDs: issueIDs,
|
||||||
|
@ -164,16 +158,24 @@ func SearchIssues(ctx *context.APIContext) {
|
||||||
SortType: "priorityrepo",
|
SortType: "priorityrepo",
|
||||||
PriorityRepoID: ctx.QueryInt64("priority_repo_id"),
|
PriorityRepoID: ctx.QueryInt64("priority_repo_id"),
|
||||||
IsPull: isPull,
|
IsPull: isPull,
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if issues, err = models.Issues(issuesOpt); err != nil {
|
||||||
ctx.Error(http.StatusInternalServerError, "Issues", err)
|
ctx.Error(http.StatusInternalServerError, "Issues", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.SetLinkHeader(issueCount, setting.UI.IssuePagingNum)
|
issuesOpt.ListOptions = models.ListOptions{
|
||||||
ctx.Header().Set("X-Total-Count", fmt.Sprintf("%d", issueCount))
|
Page: -1,
|
||||||
|
}
|
||||||
|
if filteredCount, err = models.CountIssues(issuesOpt); err != nil {
|
||||||
|
ctx.Error(http.StatusInternalServerError, "CountIssues", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.SetLinkHeader(int(filteredCount), setting.UI.IssuePagingNum)
|
||||||
|
ctx.Header().Set("X-Total-Count", fmt.Sprintf("%d", filteredCount))
|
||||||
ctx.Header().Set("Access-Control-Expose-Headers", "X-Total-Count, Link")
|
ctx.Header().Set("Access-Control-Expose-Headers", "X-Total-Count, Link")
|
||||||
ctx.JSON(http.StatusOK, convert.ToAPIIssueList(issues))
|
ctx.JSON(http.StatusOK, convert.ToAPIIssueList(issues))
|
||||||
}
|
}
|
||||||
|
@ -241,6 +243,7 @@ func ListIssues(ctx *context.APIContext) {
|
||||||
}
|
}
|
||||||
|
|
||||||
var issues []*models.Issue
|
var issues []*models.Issue
|
||||||
|
var filteredCount int64
|
||||||
|
|
||||||
keyword := strings.Trim(ctx.Query("q"), " ")
|
keyword := strings.Trim(ctx.Query("q"), " ")
|
||||||
if strings.IndexByte(keyword, 0) >= 0 {
|
if strings.IndexByte(keyword, 0) >= 0 {
|
||||||
|
@ -251,6 +254,10 @@ func ListIssues(ctx *context.APIContext) {
|
||||||
var err error
|
var err error
|
||||||
if len(keyword) > 0 {
|
if len(keyword) > 0 {
|
||||||
issueIDs, err = issue_indexer.SearchIssuesByKeyword([]int64{ctx.Repo.Repository.ID}, keyword)
|
issueIDs, err = issue_indexer.SearchIssuesByKeyword([]int64{ctx.Repo.Repository.ID}, keyword)
|
||||||
|
if err != nil {
|
||||||
|
ctx.Error(http.StatusInternalServerError, "SearchIssuesByKeyword", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if splitted := strings.Split(ctx.Query("labels"), ","); len(splitted) > 0 {
|
if splitted := strings.Split(ctx.Query("labels"), ","); len(splitted) > 0 {
|
||||||
|
@ -306,7 +313,7 @@ func ListIssues(ctx *context.APIContext) {
|
||||||
// Only fetch the issues if we either don't have a keyword or the search returned issues
|
// Only fetch the issues if we either don't have a keyword or the search returned issues
|
||||||
// This would otherwise return all issues if no issues were found by the search.
|
// This would otherwise return all issues if no issues were found by the search.
|
||||||
if len(keyword) == 0 || len(issueIDs) > 0 || len(labelIDs) > 0 {
|
if len(keyword) == 0 || len(issueIDs) > 0 || len(labelIDs) > 0 {
|
||||||
issues, err = models.Issues(&models.IssuesOptions{
|
issuesOpt := &models.IssuesOptions{
|
||||||
ListOptions: listOptions,
|
ListOptions: listOptions,
|
||||||
RepoIDs: []int64{ctx.Repo.Repository.ID},
|
RepoIDs: []int64{ctx.Repo.Repository.ID},
|
||||||
IsClosed: isClosed,
|
IsClosed: isClosed,
|
||||||
|
@ -314,18 +321,25 @@ func ListIssues(ctx *context.APIContext) {
|
||||||
LabelIDs: labelIDs,
|
LabelIDs: labelIDs,
|
||||||
MilestoneIDs: mileIDs,
|
MilestoneIDs: mileIDs,
|
||||||
IsPull: isPull,
|
IsPull: isPull,
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if issues, err = models.Issues(issuesOpt); err != nil {
|
||||||
ctx.Error(http.StatusInternalServerError, "Issues", err)
|
ctx.Error(http.StatusInternalServerError, "Issues", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.SetLinkHeader(ctx.Repo.Repository.NumIssues, listOptions.PageSize)
|
issuesOpt.ListOptions = models.ListOptions{
|
||||||
ctx.Header().Set("X-Total-Count", fmt.Sprintf("%d", ctx.Repo.Repository.NumIssues))
|
Page: -1,
|
||||||
ctx.Header().Set("Access-Control-Expose-Headers", "X-Total-Count, Link")
|
}
|
||||||
|
if filteredCount, err = models.CountIssues(issuesOpt); err != nil {
|
||||||
|
ctx.Error(http.StatusInternalServerError, "CountIssues", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.SetLinkHeader(int(filteredCount), listOptions.PageSize)
|
||||||
|
ctx.Header().Set("X-Total-Count", fmt.Sprintf("%d", filteredCount))
|
||||||
|
ctx.Header().Set("Access-Control-Expose-Headers", "X-Total-Count, Link")
|
||||||
ctx.JSON(http.StatusOK, convert.ToAPIIssueList(issues))
|
ctx.JSON(http.StatusOK, convert.ToAPIIssueList(issues))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue