summaryrefslogtreecommitdiffstats
path: root/models/issues/issue_project.go
diff options
context:
space:
mode:
Diffstat (limited to 'models/issues/issue_project.go')
-rw-r--r--models/issues/issue_project.go179
1 files changed, 179 insertions, 0 deletions
diff --git a/models/issues/issue_project.go b/models/issues/issue_project.go
new file mode 100644
index 0000000000..5e0a337f7d
--- /dev/null
+++ b/models/issues/issue_project.go
@@ -0,0 +1,179 @@
+// Copyright 2021 The Gitea Authors. All rights reserved.
+// Use of this source code is governed by a MIT-style
+// license that can be found in the LICENSE file.
+
+package issues
+
+import (
+ "context"
+ "fmt"
+
+ "code.gitea.io/gitea/models/db"
+ project_model "code.gitea.io/gitea/models/project"
+ user_model "code.gitea.io/gitea/models/user"
+)
+
+// LoadProject load the project the issue was assigned to
+func (i *Issue) LoadProject() (err error) {
+ return i.loadProject(db.DefaultContext)
+}
+
+func (i *Issue) loadProject(ctx context.Context) (err error) {
+ if i.Project == nil {
+ var p project_model.Project
+ if _, err = db.GetEngine(ctx).Table("project").
+ Join("INNER", "project_issue", "project.id=project_issue.project_id").
+ Where("project_issue.issue_id = ?", i.ID).
+ Get(&p); err != nil {
+ return err
+ }
+ i.Project = &p
+ }
+ return
+}
+
+// ProjectID return project id if issue was assigned to one
+func (i *Issue) ProjectID() int64 {
+ return i.projectID(db.DefaultContext)
+}
+
+func (i *Issue) projectID(ctx context.Context) int64 {
+ var ip project_model.ProjectIssue
+ has, err := db.GetEngine(ctx).Where("issue_id=?", i.ID).Get(&ip)
+ if err != nil || !has {
+ return 0
+ }
+ return ip.ProjectID
+}
+
+// ProjectBoardID return project board id if issue was assigned to one
+func (i *Issue) ProjectBoardID() int64 {
+ return i.projectBoardID(db.DefaultContext)
+}
+
+func (i *Issue) projectBoardID(ctx context.Context) int64 {
+ var ip project_model.ProjectIssue
+ has, err := db.GetEngine(ctx).Where("issue_id=?", i.ID).Get(&ip)
+ if err != nil || !has {
+ return 0
+ }
+ return ip.ProjectBoardID
+}
+
+// LoadIssuesFromBoard load issues assigned to this board
+func LoadIssuesFromBoard(b *project_model.Board) (IssueList, error) {
+ issueList := make([]*Issue, 0, 10)
+
+ if b.ID != 0 {
+ issues, err := Issues(&IssuesOptions{
+ ProjectBoardID: b.ID,
+ ProjectID: b.ProjectID,
+ })
+ if err != nil {
+ return nil, err
+ }
+ issueList = issues
+ }
+
+ if b.Default {
+ issues, err := Issues(&IssuesOptions{
+ ProjectBoardID: -1, // Issues without ProjectBoardID
+ ProjectID: b.ProjectID,
+ })
+ if err != nil {
+ return nil, err
+ }
+ issueList = append(issueList, issues...)
+ }
+
+ if err := IssueList(issueList).LoadComments(); err != nil {
+ return nil, err
+ }
+
+ return issueList, nil
+}
+
+// LoadIssuesFromBoardList load issues assigned to the boards
+func LoadIssuesFromBoardList(bs project_model.BoardList) (map[int64]IssueList, error) {
+ issuesMap := make(map[int64]IssueList, len(bs))
+ for i := range bs {
+ il, err := LoadIssuesFromBoard(bs[i])
+ if err != nil {
+ return nil, err
+ }
+ issuesMap[bs[i].ID] = il
+ }
+ return issuesMap, nil
+}
+
+// ChangeProjectAssign changes the project associated with an issue
+func ChangeProjectAssign(issue *Issue, doer *user_model.User, newProjectID int64) error {
+ ctx, committer, err := db.TxContext()
+ if err != nil {
+ return err
+ }
+ defer committer.Close()
+
+ if err := addUpdateIssueProject(ctx, issue, doer, newProjectID); err != nil {
+ return err
+ }
+
+ return committer.Commit()
+}
+
+func addUpdateIssueProject(ctx context.Context, issue *Issue, doer *user_model.User, newProjectID int64) error {
+ oldProjectID := issue.projectID(ctx)
+
+ if _, err := db.GetEngine(ctx).Where("project_issue.issue_id=?", issue.ID).Delete(&project_model.ProjectIssue{}); err != nil {
+ return err
+ }
+
+ if err := issue.LoadRepo(ctx); err != nil {
+ return err
+ }
+
+ if oldProjectID > 0 || newProjectID > 0 {
+ if _, err := CreateCommentCtx(ctx, &CreateCommentOptions{
+ Type: CommentTypeProject,
+ Doer: doer,
+ Repo: issue.Repo,
+ Issue: issue,
+ OldProjectID: oldProjectID,
+ ProjectID: newProjectID,
+ }); err != nil {
+ return err
+ }
+ }
+
+ return db.Insert(ctx, &project_model.ProjectIssue{
+ IssueID: issue.ID,
+ ProjectID: newProjectID,
+ })
+}
+
+// MoveIssueAcrossProjectBoards move a card from one board to another
+func MoveIssueAcrossProjectBoards(issue *Issue, board *project_model.Board) error {
+ ctx, committer, err := db.TxContext()
+ if err != nil {
+ return err
+ }
+ defer committer.Close()
+ sess := db.GetEngine(ctx)
+
+ var pis project_model.ProjectIssue
+ has, err := sess.Where("issue_id=?", issue.ID).Get(&pis)
+ if err != nil {
+ return err
+ }
+
+ if !has {
+ return fmt.Errorf("issue has to be added to a project first")
+ }
+
+ pis.ProjectBoardID = board.ID
+ if _, err := sess.ID(pis.ID).Cols("project_board_id").Update(&pis); err != nil {
+ return err
+ }
+
+ return committer.Commit()
+}