You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

issue_project.go 3.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. // Copyright 2021 The Gitea Authors. All rights reserved.
  2. // SPDX-License-Identifier: MIT
  3. package issues
  4. import (
  5. "context"
  6. "fmt"
  7. "code.gitea.io/gitea/models/db"
  8. project_model "code.gitea.io/gitea/models/project"
  9. user_model "code.gitea.io/gitea/models/user"
  10. )
  11. // LoadProject load the project the issue was assigned to
  12. func (issue *Issue) LoadProject(ctx context.Context) (err error) {
  13. if issue.Project == nil {
  14. var p project_model.Project
  15. has, err := db.GetEngine(ctx).Table("project").
  16. Join("INNER", "project_issue", "project.id=project_issue.project_id").
  17. Where("project_issue.issue_id = ?", issue.ID).Get(&p)
  18. if err != nil {
  19. return err
  20. } else if has {
  21. issue.Project = &p
  22. }
  23. }
  24. return err
  25. }
  26. func (issue *Issue) projectID(ctx context.Context) int64 {
  27. var ip project_model.ProjectIssue
  28. has, err := db.GetEngine(ctx).Where("issue_id=?", issue.ID).Get(&ip)
  29. if err != nil || !has {
  30. return 0
  31. }
  32. return ip.ProjectID
  33. }
  34. // ProjectBoardID return project board id if issue was assigned to one
  35. func (issue *Issue) ProjectBoardID(ctx context.Context) int64 {
  36. var ip project_model.ProjectIssue
  37. has, err := db.GetEngine(ctx).Where("issue_id=?", issue.ID).Get(&ip)
  38. if err != nil || !has {
  39. return 0
  40. }
  41. return ip.ProjectBoardID
  42. }
  43. // LoadIssuesFromBoard load issues assigned to this board
  44. func LoadIssuesFromBoard(ctx context.Context, b *project_model.Board) (IssueList, error) {
  45. issueList, err := Issues(ctx, &IssuesOptions{
  46. ProjectBoardID: b.ID,
  47. ProjectID: b.ProjectID,
  48. SortType: "project-column-sorting",
  49. })
  50. if err != nil {
  51. return nil, err
  52. }
  53. if b.Default {
  54. issues, err := Issues(ctx, &IssuesOptions{
  55. ProjectBoardID: db.NoConditionID,
  56. ProjectID: b.ProjectID,
  57. SortType: "project-column-sorting",
  58. })
  59. if err != nil {
  60. return nil, err
  61. }
  62. issueList = append(issueList, issues...)
  63. }
  64. if err := issueList.LoadComments(ctx); err != nil {
  65. return nil, err
  66. }
  67. return issueList, nil
  68. }
  69. // LoadIssuesFromBoardList load issues assigned to the boards
  70. func LoadIssuesFromBoardList(ctx context.Context, bs project_model.BoardList) (map[int64]IssueList, error) {
  71. issuesMap := make(map[int64]IssueList, len(bs))
  72. for i := range bs {
  73. il, err := LoadIssuesFromBoard(ctx, bs[i])
  74. if err != nil {
  75. return nil, err
  76. }
  77. issuesMap[bs[i].ID] = il
  78. }
  79. return issuesMap, nil
  80. }
  81. // ChangeProjectAssign changes the project associated with an issue
  82. func ChangeProjectAssign(ctx context.Context, issue *Issue, doer *user_model.User, newProjectID int64) error {
  83. ctx, committer, err := db.TxContext(ctx)
  84. if err != nil {
  85. return err
  86. }
  87. defer committer.Close()
  88. if err := addUpdateIssueProject(ctx, issue, doer, newProjectID); err != nil {
  89. return err
  90. }
  91. return committer.Commit()
  92. }
  93. func addUpdateIssueProject(ctx context.Context, issue *Issue, doer *user_model.User, newProjectID int64) error {
  94. oldProjectID := issue.projectID(ctx)
  95. if err := issue.LoadRepo(ctx); err != nil {
  96. return err
  97. }
  98. // Only check if we add a new project and not remove it.
  99. if newProjectID > 0 {
  100. newProject, err := project_model.GetProjectByID(ctx, newProjectID)
  101. if err != nil {
  102. return err
  103. }
  104. if newProject.RepoID != issue.RepoID && newProject.OwnerID != issue.Repo.OwnerID {
  105. return fmt.Errorf("issue's repository is not the same as project's repository")
  106. }
  107. }
  108. if _, err := db.GetEngine(ctx).Where("project_issue.issue_id=?", issue.ID).Delete(&project_model.ProjectIssue{}); err != nil {
  109. return err
  110. }
  111. if oldProjectID > 0 || newProjectID > 0 {
  112. if _, err := CreateComment(ctx, &CreateCommentOptions{
  113. Type: CommentTypeProject,
  114. Doer: doer,
  115. Repo: issue.Repo,
  116. Issue: issue,
  117. OldProjectID: oldProjectID,
  118. ProjectID: newProjectID,
  119. }); err != nil {
  120. return err
  121. }
  122. }
  123. return db.Insert(ctx, &project_model.ProjectIssue{
  124. IssueID: issue.ID,
  125. ProjectID: newProjectID,
  126. })
  127. }