2022-03-29 22:16:31 +08:00
// 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.
2022-06-13 17:37:59 +08:00
package issues
2022-03-29 22:16:31 +08:00
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
2022-06-20 12:02:49 +02:00
func ( issue * Issue ) LoadProject ( ) ( err error ) {
return issue . loadProject ( db . DefaultContext )
2022-03-29 22:16:31 +08:00
}
2022-06-20 12:02:49 +02:00
func ( issue * Issue ) loadProject ( ctx context . Context ) ( err error ) {
if issue . Project == nil {
2022-03-29 22:16:31 +08:00
var p project_model . Project
2022-05-20 22:08:52 +08:00
if _ , err = db . GetEngine ( ctx ) . Table ( "project" ) .
2022-03-29 22:16:31 +08:00
Join ( "INNER" , "project_issue" , "project.id=project_issue.project_id" ) .
2022-06-20 12:02:49 +02:00
Where ( "project_issue.issue_id = ?" , issue . ID ) .
2022-03-29 22:16:31 +08:00
Get ( & p ) ; err != nil {
return err
}
2022-06-20 12:02:49 +02:00
issue . Project = & p
2022-03-29 22:16:31 +08:00
}
2022-06-20 12:02:49 +02:00
return err
2022-03-29 22:16:31 +08:00
}
// ProjectID return project id if issue was assigned to one
2022-06-20 12:02:49 +02:00
func ( issue * Issue ) ProjectID ( ) int64 {
return issue . projectID ( db . DefaultContext )
2022-03-29 22:16:31 +08:00
}
2022-06-20 12:02:49 +02:00
func ( issue * Issue ) projectID ( ctx context . Context ) int64 {
2022-03-29 22:16:31 +08:00
var ip project_model . ProjectIssue
2022-06-20 12:02:49 +02:00
has , err := db . GetEngine ( ctx ) . Where ( "issue_id=?" , issue . ID ) . Get ( & ip )
2022-03-29 22:16:31 +08:00
if err != nil || ! has {
return 0
}
return ip . ProjectID
}
// ProjectBoardID return project board id if issue was assigned to one
2022-06-20 12:02:49 +02:00
func ( issue * Issue ) ProjectBoardID ( ) int64 {
return issue . projectBoardID ( db . DefaultContext )
2022-03-29 22:16:31 +08:00
}
2022-06-20 12:02:49 +02:00
func ( issue * Issue ) projectBoardID ( ctx context . Context ) int64 {
2022-03-29 22:16:31 +08:00
var ip project_model . ProjectIssue
2022-06-20 12:02:49 +02:00
has , err := db . GetEngine ( ctx ) . Where ( "issue_id=?" , issue . ID ) . Get ( & ip )
2022-03-29 22:16:31 +08:00
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 {
2022-05-20 22:08:52 +08:00
oldProjectID := issue . projectID ( ctx )
2022-03-29 22:16:31 +08:00
2022-06-30 23:55:08 +08:00
// Only check if we add a new project and not remove it.
if newProjectID > 0 {
newProject , err := project_model . GetProjectByID ( ctx , newProjectID )
if err != nil {
return err
}
if newProject . RepoID != issue . RepoID {
return fmt . Errorf ( "issue's repository is not the same as project's repository" )
}
}
2022-05-20 22:08:52 +08:00
if _ , err := db . GetEngine ( ctx ) . Where ( "project_issue.issue_id=?" , issue . ID ) . Delete ( & project_model . ProjectIssue { } ) ; err != nil {
2022-03-29 22:16:31 +08:00
return err
}
2022-04-08 17:11:15 +08:00
if err := issue . LoadRepo ( ctx ) ; err != nil {
2022-03-29 22:16:31 +08:00
return err
}
if oldProjectID > 0 || newProjectID > 0 {
2022-04-08 17:11:15 +08:00
if _ , err := CreateCommentCtx ( ctx , & CreateCommentOptions {
2022-03-29 22:16:31 +08:00
Type : CommentTypeProject ,
Doer : doer ,
Repo : issue . Repo ,
Issue : issue ,
OldProjectID : oldProjectID ,
ProjectID : newProjectID ,
} ) ; err != nil {
return err
}
}
2022-05-20 22:08:52 +08:00
return db . Insert ( ctx , & project_model . ProjectIssue {
2022-03-29 22:16:31 +08:00
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 ( )
}