diff --git a/models/issues/issue_list.go b/models/issues/issue_list.go index dad21c147..9cc41ec6a 100644 --- a/models/issues/issue_list.go +++ b/models/issues/issue_list.go @@ -229,39 +229,41 @@ func (issues IssueList) loadMilestones(ctx context.Context) error { return nil } -func (issues IssueList) getProjectIDs() []int64 { - ids := make(container.Set[int64], len(issues)) - for _, issue := range issues { - ids.Add(issue.ProjectID()) - } - return ids.Values() -} +func (issues IssueList) LoadProjects(ctx context.Context) error { + issueIDs := issues.getIssueIDs() + projectMaps := make(map[int64]*project_model.Project, len(issues)) + left := len(issueIDs) -func (issues IssueList) loadProjects(ctx context.Context) error { - projectIDs := issues.getProjectIDs() - if len(projectIDs) == 0 { - return nil + type projectWithIssueID struct { + *project_model.Project `xorm:"extends"` + IssueID int64 } - projectMaps := make(map[int64]*project_model.Project, len(projectIDs)) - left := len(projectIDs) for left > 0 { limit := db.DefaultMaxInSize if left < limit { limit = left } + + projects := make([]*projectWithIssueID, 0, limit) err := db.GetEngine(ctx). - In("id", projectIDs[:limit]). - Find(&projectMaps) + Table("project"). + 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 { return err } + for _, project := range projects { + projectMaps[project.IssueID] = project.Project + } left -= limit - projectIDs = projectIDs[limit:] + issueIDs = issueIDs[limit:] } for _, issue := range issues { - issue.Project = projectMaps[issue.ProjectID()] + issue.Project = projectMaps[issue.ID] } return nil } @@ -541,7 +543,7 @@ func (issues IssueList) loadAttributes(ctx context.Context) error { 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) } diff --git a/models/issues/issue_list_test.go b/models/issues/issue_list_test.go index 954a20ffe..97ce9e43b 100644 --- a/models/issues/issue_list_test.go +++ b/models/issues/issue_list_test.go @@ -66,8 +66,12 @@ func TestIssueList_LoadAttributes(t *testing.T) { } if issue.ID == int64(1) { assert.Equal(t, int64(400), issue.TotalTrackedTime) + assert.NotNil(t, issue.Project) } else if issue.ID == int64(2) { assert.Equal(t, int64(3682), issue.TotalTrackedTime) + assert.Nil(t, issue.Project) + } else { + assert.Nil(t, issue.Project) } } } diff --git a/models/issues/issue_project.go b/models/issues/issue_project.go index 04d12e055..b163c6835 100644 --- a/models/issues/issue_project.go +++ b/models/issues/issue_project.go @@ -27,11 +27,6 @@ func (issue *Issue) LoadProject(ctx context.Context) (err error) { 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 { var ip project_model.ProjectIssue has, err := db.GetEngine(ctx).Where("issue_id=?", issue.ID).Get(&ip) diff --git a/routers/web/org/projects.go b/routers/web/org/projects.go index b3f6024b6..e525f2c43 100644 --- a/routers/web/org/projects.go +++ b/routers/web/org/projects.go @@ -383,7 +383,7 @@ func ViewProject(ctx *context.Context) { 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") if len(commaSeparatedIssueIDs) == 0 { return nil @@ -429,9 +429,14 @@ func UpdateIssueProject(ctx *context.Context) { return } + if err := issues.LoadProjects(ctx); err != nil { + ctx.ServerError("LoadProjects", err) + return + } + projectID := ctx.FormInt64("id") for _, issue := range issues { - oldProjectID := issue.ProjectID() + oldProjectID := issue.Project.ID if oldProjectID == projectID { continue } diff --git a/routers/web/repo/issue.go b/routers/web/repo/issue.go index 5ab8db2e0..0756fcd53 100644 --- a/routers/web/repo/issue.go +++ b/routers/web/repo/issue.go @@ -1971,7 +1971,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") if len(commaSeparatedIssueIDs) == 0 { return nil @@ -2722,7 +2722,7 @@ func UpdateIssueStatus(ctx *context.Context) { 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) return } diff --git a/routers/web/repo/projects.go b/routers/web/repo/projects.go index 5ee5ead12..6da9edfd0 100644 --- a/routers/web/repo/projects.go +++ b/routers/web/repo/projects.go @@ -378,9 +378,14 @@ func UpdateIssueProject(ctx *context.Context) { return } + if err := issues.LoadProjects(ctx); err != nil { + ctx.ServerError("LoadProjects", err) + return + } + projectID := ctx.FormInt64("id") for _, issue := range issues { - oldProjectID := issue.ProjectID() + oldProjectID := issue.Project.ID if oldProjectID == projectID { continue } diff --git a/templates/repo/issue/view_content/sidebar.tmpl b/templates/repo/issue/view_content/sidebar.tmpl index 901f714e3..2f3263922 100644 --- a/templates/repo/issue/view_content/sidebar.tmpl +++ b/templates/repo/issue/view_content/sidebar.tmpl @@ -192,9 +192,9 @@
- {{.locale.Tr "repo.issues.new.no_projects"}} + {{.locale.Tr "repo.issues.new.no_projects"}}
- {{if .Issue.ProjectID}} + {{if .Issue.Project}} {{svg .Issue.Project.IconName 18 "gt-mr-3"}}{{.Issue.Project.Title}}