mirror of
				https://gitee.com/gitea/gitea
				synced 2025-11-04 16:40:24 +08:00 
			
		
		
		
	Improve loadprojects for issue list (#25468)
This commit is contained in:
		@@ -229,39 +229,41 @@ func (issues IssueList) loadMilestones(ctx context.Context) error {
 | 
				
			|||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (issues IssueList) getProjectIDs() []int64 {
 | 
					func (issues IssueList) LoadProjects(ctx context.Context) error {
 | 
				
			||||||
	ids := make(container.Set[int64], len(issues))
 | 
						issueIDs := issues.getIssueIDs()
 | 
				
			||||||
	for _, issue := range issues {
 | 
						projectMaps := make(map[int64]*project_model.Project, len(issues))
 | 
				
			||||||
		ids.Add(issue.ProjectID())
 | 
						left := len(issueIDs)
 | 
				
			||||||
	}
 | 
					
 | 
				
			||||||
	return ids.Values()
 | 
						type projectWithIssueID struct {
 | 
				
			||||||
 | 
							*project_model.Project `xorm:"extends"`
 | 
				
			||||||
 | 
							IssueID                int64
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (issues IssueList) loadProjects(ctx context.Context) error {
 | 
					 | 
				
			||||||
	projectIDs := issues.getProjectIDs()
 | 
					 | 
				
			||||||
	if len(projectIDs) == 0 {
 | 
					 | 
				
			||||||
		return nil
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	projectMaps := make(map[int64]*project_model.Project, len(projectIDs))
 | 
					 | 
				
			||||||
	left := len(projectIDs)
 | 
					 | 
				
			||||||
	for left > 0 {
 | 
						for left > 0 {
 | 
				
			||||||
		limit := db.DefaultMaxInSize
 | 
							limit := db.DefaultMaxInSize
 | 
				
			||||||
		if left < limit {
 | 
							if left < limit {
 | 
				
			||||||
			limit = left
 | 
								limit = left
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							projects := make([]*projectWithIssueID, 0, limit)
 | 
				
			||||||
		err := db.GetEngine(ctx).
 | 
							err := db.GetEngine(ctx).
 | 
				
			||||||
			In("id", projectIDs[:limit]).
 | 
								Table("project").
 | 
				
			||||||
			Find(&projectMaps)
 | 
								Select("project.*, project_issue.issue_id").
 | 
				
			||||||
 | 
								Join("INNER", "project_issue", "project.id = project_issue.project_id").
 | 
				
			||||||
 | 
								In("project_issue.issue_id", issueIDs[:limit]).
 | 
				
			||||||
 | 
								Find(&projects)
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			return err
 | 
								return err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							for _, project := range projects {
 | 
				
			||||||
 | 
								projectMaps[project.IssueID] = project.Project
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
		left -= limit
 | 
							left -= limit
 | 
				
			||||||
		projectIDs = projectIDs[limit:]
 | 
							issueIDs = issueIDs[limit:]
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for _, issue := range issues {
 | 
						for _, issue := range issues {
 | 
				
			||||||
		issue.Project = projectMaps[issue.ProjectID()]
 | 
							issue.Project = projectMaps[issue.ID]
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -541,7 +543,7 @@ func (issues IssueList) loadAttributes(ctx context.Context) error {
 | 
				
			|||||||
		return fmt.Errorf("issue.loadAttributes: loadMilestones: %w", err)
 | 
							return fmt.Errorf("issue.loadAttributes: loadMilestones: %w", err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if err := issues.loadProjects(ctx); err != nil {
 | 
						if err := issues.LoadProjects(ctx); err != nil {
 | 
				
			||||||
		return fmt.Errorf("issue.loadAttributes: loadProjects: %w", err)
 | 
							return fmt.Errorf("issue.loadAttributes: loadProjects: %w", err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -66,8 +66,12 @@ func TestIssueList_LoadAttributes(t *testing.T) {
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
		if issue.ID == int64(1) {
 | 
							if issue.ID == int64(1) {
 | 
				
			||||||
			assert.Equal(t, int64(400), issue.TotalTrackedTime)
 | 
								assert.Equal(t, int64(400), issue.TotalTrackedTime)
 | 
				
			||||||
 | 
								assert.NotNil(t, issue.Project)
 | 
				
			||||||
		} else if issue.ID == int64(2) {
 | 
							} else if issue.ID == int64(2) {
 | 
				
			||||||
			assert.Equal(t, int64(3682), issue.TotalTrackedTime)
 | 
								assert.Equal(t, int64(3682), issue.TotalTrackedTime)
 | 
				
			||||||
 | 
								assert.Nil(t, issue.Project)
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								assert.Nil(t, issue.Project)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -27,11 +27,6 @@ func (issue *Issue) LoadProject(ctx context.Context) (err error) {
 | 
				
			|||||||
	return err
 | 
						return err
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// ProjectID return project id if issue was assigned to one
 | 
					 | 
				
			||||||
func (issue *Issue) ProjectID() int64 {
 | 
					 | 
				
			||||||
	return issue.projectID(db.DefaultContext)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (issue *Issue) projectID(ctx context.Context) int64 {
 | 
					func (issue *Issue) projectID(ctx context.Context) int64 {
 | 
				
			||||||
	var ip project_model.ProjectIssue
 | 
						var ip project_model.ProjectIssue
 | 
				
			||||||
	has, err := db.GetEngine(ctx).Where("issue_id=?", issue.ID).Get(&ip)
 | 
						has, err := db.GetEngine(ctx).Where("issue_id=?", issue.ID).Get(&ip)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -383,7 +383,7 @@ func ViewProject(ctx *context.Context) {
 | 
				
			|||||||
	ctx.HTML(http.StatusOK, tplProjectsView)
 | 
						ctx.HTML(http.StatusOK, tplProjectsView)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func getActionIssues(ctx *context.Context) []*issues_model.Issue {
 | 
					func getActionIssues(ctx *context.Context) issues_model.IssueList {
 | 
				
			||||||
	commaSeparatedIssueIDs := ctx.FormString("issue_ids")
 | 
						commaSeparatedIssueIDs := ctx.FormString("issue_ids")
 | 
				
			||||||
	if len(commaSeparatedIssueIDs) == 0 {
 | 
						if len(commaSeparatedIssueIDs) == 0 {
 | 
				
			||||||
		return nil
 | 
							return nil
 | 
				
			||||||
@@ -429,9 +429,14 @@ func UpdateIssueProject(ctx *context.Context) {
 | 
				
			|||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if err := issues.LoadProjects(ctx); err != nil {
 | 
				
			||||||
 | 
							ctx.ServerError("LoadProjects", err)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	projectID := ctx.FormInt64("id")
 | 
						projectID := ctx.FormInt64("id")
 | 
				
			||||||
	for _, issue := range issues {
 | 
						for _, issue := range issues {
 | 
				
			||||||
		oldProjectID := issue.ProjectID()
 | 
							oldProjectID := issue.Project.ID
 | 
				
			||||||
		if oldProjectID == projectID {
 | 
							if oldProjectID == projectID {
 | 
				
			||||||
			continue
 | 
								continue
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1984,7 +1984,7 @@ func checkIssueRights(ctx *context.Context, issue *issues_model.Issue) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func getActionIssues(ctx *context.Context) []*issues_model.Issue {
 | 
					func getActionIssues(ctx *context.Context) issues_model.IssueList {
 | 
				
			||||||
	commaSeparatedIssueIDs := ctx.FormString("issue_ids")
 | 
						commaSeparatedIssueIDs := ctx.FormString("issue_ids")
 | 
				
			||||||
	if len(commaSeparatedIssueIDs) == 0 {
 | 
						if len(commaSeparatedIssueIDs) == 0 {
 | 
				
			||||||
		return nil
 | 
							return nil
 | 
				
			||||||
@@ -2749,7 +2749,7 @@ func UpdateIssueStatus(ctx *context.Context) {
 | 
				
			|||||||
		log.Warn("Unrecognized action: %s", action)
 | 
							log.Warn("Unrecognized action: %s", action)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if _, err := issues_model.IssueList(issues).LoadRepositories(ctx); err != nil {
 | 
						if _, err := issues.LoadRepositories(ctx); err != nil {
 | 
				
			||||||
		ctx.ServerError("LoadRepositories", err)
 | 
							ctx.ServerError("LoadRepositories", err)
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -378,9 +378,14 @@ func UpdateIssueProject(ctx *context.Context) {
 | 
				
			|||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if err := issues.LoadProjects(ctx); err != nil {
 | 
				
			||||||
 | 
							ctx.ServerError("LoadProjects", err)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	projectID := ctx.FormInt64("id")
 | 
						projectID := ctx.FormInt64("id")
 | 
				
			||||||
	for _, issue := range issues {
 | 
						for _, issue := range issues {
 | 
				
			||||||
		oldProjectID := issue.ProjectID()
 | 
							oldProjectID := issue.Project.ID
 | 
				
			||||||
		if oldProjectID == projectID {
 | 
							if oldProjectID == projectID {
 | 
				
			||||||
			continue
 | 
								continue
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -192,9 +192,9 @@
 | 
				
			|||||||
			</div>
 | 
								</div>
 | 
				
			||||||
		</div>
 | 
							</div>
 | 
				
			||||||
		<div class="ui select-project list">
 | 
							<div class="ui select-project list">
 | 
				
			||||||
			<span class="no-select item {{if .Issue.ProjectID}}gt-hidden{{end}}">{{.locale.Tr "repo.issues.new.no_projects"}}</span>
 | 
								<span class="no-select item {{if .Issue.Project}}gt-hidden{{end}}">{{.locale.Tr "repo.issues.new.no_projects"}}</span>
 | 
				
			||||||
			<div class="selected">
 | 
								<div class="selected">
 | 
				
			||||||
				{{if .Issue.ProjectID}}
 | 
									{{if .Issue.Project}}
 | 
				
			||||||
					<a class="item muted sidebar-item-link" href="{{.Issue.Project.Link}}">
 | 
										<a class="item muted sidebar-item-link" href="{{.Issue.Project.Link}}">
 | 
				
			||||||
						{{svg .Issue.Project.IconName 18 "gt-mr-3"}}{{.Issue.Project.Title}}
 | 
											{{svg .Issue.Project.IconName 18 "gt-mr-3"}}{{.Issue.Project.Title}}
 | 
				
			||||||
					</a>
 | 
										</a>
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user