mirror of
				https://gitee.com/gitea/gitea
				synced 2025-11-04 08:30:25 +08:00 
			
		
		
		
	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:
		@@ -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 issues, err = models.Issues(issuesOpt); err != nil {
 | 
				
			||||||
 | 
								ctx.Error(http.StatusInternalServerError, "Issues", err)
 | 
				
			||||||
 | 
								return
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							issuesOpt.ListOptions = models.ListOptions{
 | 
				
			||||||
 | 
								Page: -1,
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if filteredCount, err = models.CountIssues(issuesOpt); err != nil {
 | 
				
			||||||
 | 
								ctx.Error(http.StatusInternalServerError, "CountIssues", err)
 | 
				
			||||||
 | 
								return
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if err != nil {
 | 
						ctx.SetLinkHeader(int(filteredCount), setting.UI.IssuePagingNum)
 | 
				
			||||||
		ctx.Error(http.StatusInternalServerError, "Issues", err)
 | 
						ctx.Header().Set("X-Total-Count", fmt.Sprintf("%d", filteredCount))
 | 
				
			||||||
		return
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	ctx.SetLinkHeader(issueCount, setting.UI.IssuePagingNum)
 | 
					 | 
				
			||||||
	ctx.Header().Set("X-Total-Count", fmt.Sprintf("%d", issueCount))
 | 
					 | 
				
			||||||
	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 issues, err = models.Issues(issuesOpt); err != nil {
 | 
				
			||||||
 | 
								ctx.Error(http.StatusInternalServerError, "Issues", err)
 | 
				
			||||||
 | 
								return
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							issuesOpt.ListOptions = models.ListOptions{
 | 
				
			||||||
 | 
								Page: -1,
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if filteredCount, err = models.CountIssues(issuesOpt); err != nil {
 | 
				
			||||||
 | 
								ctx.Error(http.StatusInternalServerError, "CountIssues", err)
 | 
				
			||||||
 | 
								return
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if err != nil {
 | 
						ctx.SetLinkHeader(int(filteredCount), listOptions.PageSize)
 | 
				
			||||||
		ctx.Error(http.StatusInternalServerError, "Issues", err)
 | 
						ctx.Header().Set("X-Total-Count", fmt.Sprintf("%d", filteredCount))
 | 
				
			||||||
		return
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	ctx.SetLinkHeader(ctx.Repo.Repository.NumIssues, listOptions.PageSize)
 | 
					 | 
				
			||||||
	ctx.Header().Set("X-Total-Count", fmt.Sprintf("%d", ctx.Repo.Repository.NumIssues))
 | 
					 | 
				
			||||||
	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))
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user