2022-03-29 17:16:31 +03:00
// Copyright 2021 The Gitea Authors. All rights reserved.
2022-11-27 21:20:29 +03:00
// SPDX-License-Identifier: MIT
2022-03-29 17:16:31 +03:00
2022-06-13 12:37:59 +03:00
package issues
2022-03-29 17:16:31 +03:00
import (
"context"
"code.gitea.io/gitea/models/db"
project_model "code.gitea.io/gitea/models/project"
user_model "code.gitea.io/gitea/models/user"
2024-05-08 16:44:57 +03:00
"code.gitea.io/gitea/modules/util"
2022-03-29 17:16:31 +03:00
)
// LoadProject load the project the issue was assigned to
2023-02-20 22:21:56 +03:00
func ( issue * Issue ) LoadProject ( ctx context . Context ) ( err error ) {
2022-06-20 13:02:49 +03:00
if issue . Project == nil {
2022-03-29 17:16:31 +03:00
var p project_model . Project
2023-07-12 17:10:35 +03:00
has , err := db . GetEngine ( ctx ) . Table ( "project" ) .
2022-03-29 17:16:31 +03:00
Join ( "INNER" , "project_issue" , "project.id=project_issue.project_id" ) .
2023-07-12 17:10:35 +03:00
Where ( "project_issue.issue_id = ?" , issue . ID ) . Get ( & p )
if err != nil {
2022-03-29 17:16:31 +03:00
return err
2023-07-12 17:10:35 +03:00
} else if has {
issue . Project = & p
2022-03-29 17:16:31 +03:00
}
}
2022-06-20 13:02:49 +03:00
return err
2022-03-29 17:16:31 +03:00
}
2022-06-20 13:02:49 +03:00
func ( issue * Issue ) projectID ( ctx context . Context ) int64 {
2022-03-29 17:16:31 +03:00
var ip project_model . ProjectIssue
2022-06-20 13:02:49 +03:00
has , err := db . GetEngine ( ctx ) . Where ( "issue_id=?" , issue . ID ) . Get ( & ip )
2022-03-29 17:16:31 +03:00
if err != nil || ! has {
return 0
}
return ip . ProjectID
}
2024-05-27 11:59:54 +03:00
// ProjectColumnID return project column id if issue was assigned to one
func ( issue * Issue ) ProjectColumnID ( ctx context . Context ) int64 {
2022-03-29 17:16:31 +03:00
var ip project_model . ProjectIssue
2022-06-20 13:02:49 +03:00
has , err := db . GetEngine ( ctx ) . Where ( "issue_id=?" , issue . ID ) . Get ( & ip )
2022-03-29 17:16:31 +03:00
if err != nil || ! has {
return 0
}
2024-05-27 11:59:54 +03:00
return ip . ProjectColumnID
2022-03-29 17:16:31 +03:00
}
2024-05-27 11:59:54 +03:00
// LoadIssuesFromColumn load issues assigned to this column
2024-09-12 06:53:40 +03:00
func LoadIssuesFromColumn ( ctx context . Context , b * project_model . Column , opts * IssuesOptions ) ( IssueList , error ) {
issueList , err := Issues ( ctx , opts . Copy ( func ( o * IssuesOptions ) {
o . ProjectColumnID = b . ID
o . ProjectID = b . ProjectID
o . SortType = "project-column-sorting"
} ) )
2024-03-27 23:54:32 +03:00
if err != nil {
return nil , err
2022-03-29 17:16:31 +03:00
}
if b . Default {
2022-11-19 11:12:33 +03:00
issues , err := Issues ( ctx , & IssuesOptions {
2024-05-27 11:59:54 +03:00
ProjectColumnID : db . NoConditionID ,
ProjectID : b . ProjectID ,
SortType : "project-column-sorting" ,
2022-03-29 17:16:31 +03:00
} )
if err != nil {
return nil , err
}
issueList = append ( issueList , issues ... )
}
2023-08-07 22:26:40 +03:00
if err := issueList . LoadComments ( ctx ) ; err != nil {
2022-03-29 17:16:31 +03:00
return nil , err
}
return issueList , nil
}
2024-05-27 11:59:54 +03:00
// LoadIssuesFromColumnList load issues assigned to the columns
2024-09-12 06:53:40 +03:00
func LoadIssuesFromColumnList ( ctx context . Context , bs project_model . ColumnList , opts * IssuesOptions ) ( map [ int64 ] IssueList , error ) {
2022-03-29 17:16:31 +03:00
issuesMap := make ( map [ int64 ] IssueList , len ( bs ) )
for i := range bs {
2024-09-12 06:53:40 +03:00
il , err := LoadIssuesFromColumn ( ctx , bs [ i ] , opts )
2022-03-29 17:16:31 +03:00
if err != nil {
return nil , err
}
issuesMap [ bs [ i ] . ID ] = il
}
return issuesMap , nil
}
2024-05-08 16:44:57 +03:00
// IssueAssignOrRemoveProject changes the project associated with an issue
// If newProjectID is 0, the issue is removed from the project
func IssueAssignOrRemoveProject ( ctx context . Context , issue * Issue , doer * user_model . User , newProjectID , newColumnID int64 ) error {
return db . WithTx ( ctx , func ( ctx context . Context ) error {
oldProjectID := issue . projectID ( ctx )
2022-03-29 17:16:31 +03:00
2024-05-08 16:44:57 +03:00
if err := issue . LoadRepo ( ctx ) ; err != nil {
return err
}
2022-03-29 17:16:31 +03:00
2024-05-08 16:44:57 +03: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 . CanBeAccessedByOwnerRepo ( issue . Repo . OwnerID , issue . Repo ) {
return util . NewPermissionDeniedErrorf ( "issue %d can't be accessed by project %d" , issue . ID , newProject . ID )
}
if newColumnID == 0 {
2024-05-27 11:59:54 +03:00
newDefaultColumn , err := newProject . GetDefaultColumn ( ctx )
2024-05-08 16:44:57 +03:00
if err != nil {
return err
}
newColumnID = newDefaultColumn . ID
}
}
2023-01-20 14:42:33 +03:00
2024-05-08 16:44:57 +03:00
if _ , err := db . GetEngine ( ctx ) . Where ( "project_issue.issue_id=?" , issue . ID ) . Delete ( & project_model . ProjectIssue { } ) ; err != nil {
2022-06-30 18:55:08 +03:00
return err
}
2024-05-08 16:44:57 +03:00
if oldProjectID > 0 || newProjectID > 0 {
if _ , err := CreateComment ( ctx , & CreateCommentOptions {
Type : CommentTypeProject ,
Doer : doer ,
Repo : issue . Repo ,
Issue : issue ,
OldProjectID : oldProjectID ,
ProjectID : newProjectID ,
} ) ; err != nil {
return err
}
}
if newProjectID == 0 {
return nil
}
if newColumnID == 0 {
panic ( "newColumnID must not be zero" ) // shouldn't happen
}
2022-03-29 17:16:31 +03:00
2024-05-08 16:44:57 +03:00
res := struct {
MaxSorting int64
IssueCount int64
} { }
if _ , err := db . GetEngine ( ctx ) . Select ( "max(sorting) as max_sorting, count(*) as issue_count" ) . Table ( "project_issue" ) .
Where ( "project_id=?" , newProjectID ) .
And ( "project_board_id=?" , newColumnID ) .
Get ( & res ) ; err != nil {
2022-03-29 17:16:31 +03:00
return err
}
2024-05-08 16:44:57 +03:00
newSorting := util . Iif ( res . IssueCount > 0 , res . MaxSorting + 1 , 0 )
return db . Insert ( ctx , & project_model . ProjectIssue {
2024-05-27 11:59:54 +03:00
IssueID : issue . ID ,
ProjectID : newProjectID ,
ProjectColumnID : newColumnID ,
Sorting : newSorting ,
2024-05-08 16:44:57 +03:00
} )
2022-03-29 17:16:31 +03:00
} )
}