@@ -5,11 +5,11 @@ package issues
55
66import (
77 "context"
8- "fmt"
98
109 "code.gitea.io/gitea/models/db"
1110 project_model "code.gitea.io/gitea/models/project"
1211 user_model "code.gitea.io/gitea/models/user"
12+ "code.gitea.io/gitea/modules/util"
1313)
1414
1515// LoadProject load the project the issue was assigned to
@@ -90,58 +90,73 @@ func LoadIssuesFromBoardList(ctx context.Context, bs project_model.BoardList) (m
9090 return issuesMap , nil
9191}
9292
93- // ChangeProjectAssign changes the project associated with an issue
94- func ChangeProjectAssign (ctx context.Context , issue * Issue , doer * user_model.User , newProjectID int64 ) error {
95- ctx , committer , err := db .TxContext (ctx )
96- if err != nil {
97- return err
98- }
99- defer committer .Close ()
100-
101- if err := addUpdateIssueProject (ctx , issue , doer , newProjectID ); err != nil {
102- return err
103- }
104-
105- return committer .Commit ()
106- }
93+ // IssueAssignOrRemoveProject changes the project associated with an issue
94+ // If newProjectID is 0, the issue is removed from the project
95+ func IssueAssignOrRemoveProject (ctx context.Context , issue * Issue , doer * user_model.User , newProjectID , newColumnID int64 ) error {
96+ return db .WithTx (ctx , func (ctx context.Context ) error {
97+ oldProjectID := issue .projectID (ctx )
10798
108- func addUpdateIssueProject (ctx context.Context , issue * Issue , doer * user_model.User , newProjectID int64 ) error {
109- oldProjectID := issue .projectID (ctx )
99+ if err := issue .LoadRepo (ctx ); err != nil {
100+ return err
101+ }
110102
111- if err := issue .LoadRepo (ctx ); err != nil {
112- return err
113- }
103+ // Only check if we add a new project and not remove it.
104+ if newProjectID > 0 {
105+ newProject , err := project_model .GetProjectByID (ctx , newProjectID )
106+ if err != nil {
107+ return err
108+ }
109+ if ! newProject .CanBeAccessedByOwnerRepo (issue .Repo .OwnerID , issue .Repo ) {
110+ return util .NewPermissionDeniedErrorf ("issue %d can't be accessed by project %d" , issue .ID , newProject .ID )
111+ }
112+ if newColumnID == 0 {
113+ newDefaultColumn , err := newProject .GetDefaultBoard (ctx )
114+ if err != nil {
115+ return err
116+ }
117+ newColumnID = newDefaultColumn .ID
118+ }
119+ }
114120
115- // Only check if we add a new project and not remove it.
116- if newProjectID > 0 {
117- newProject , err := project_model .GetProjectByID (ctx , newProjectID )
118- if err != nil {
121+ if _ , err := db .GetEngine (ctx ).Where ("project_issue.issue_id=?" , issue .ID ).Delete (& project_model.ProjectIssue {}); err != nil {
119122 return err
120123 }
121- if newProject .RepoID != issue .RepoID && newProject .OwnerID != issue .Repo .OwnerID {
122- return fmt .Errorf ("issue's repository is not the same as project's repository" )
123- }
124- }
125124
126- if _ , err := db .GetEngine (ctx ).Where ("project_issue.issue_id=?" , issue .ID ).Delete (& project_model.ProjectIssue {}); err != nil {
127- return err
128- }
125+ if oldProjectID > 0 || newProjectID > 0 {
126+ if _ , err := CreateComment (ctx , & CreateCommentOptions {
127+ Type : CommentTypeProject ,
128+ Doer : doer ,
129+ Repo : issue .Repo ,
130+ Issue : issue ,
131+ OldProjectID : oldProjectID ,
132+ ProjectID : newProjectID ,
133+ }); err != nil {
134+ return err
135+ }
136+ }
137+ if newProjectID == 0 {
138+ return nil
139+ }
140+ if newColumnID == 0 {
141+ panic ("newColumnID must not be zero" ) // shouldn't happen
142+ }
129143
130- if oldProjectID > 0 || newProjectID > 0 {
131- if _ , err := CreateComment (ctx , & CreateCommentOptions {
132- Type : CommentTypeProject ,
133- Doer : doer ,
134- Repo : issue .Repo ,
135- Issue : issue ,
136- OldProjectID : oldProjectID ,
137- ProjectID : newProjectID ,
138- }); err != nil {
144+ res := struct {
145+ MaxSorting int64
146+ IssueCount int64
147+ }{}
148+ if _ , err := db .GetEngine (ctx ).Select ("max(sorting) as max_sorting, count(*) as issue_count" ).Table ("project_issue" ).
149+ Where ("project_id=?" , newProjectID ).
150+ And ("project_board_id=?" , newColumnID ).
151+ Get (& res ); err != nil {
139152 return err
140153 }
141- }
142-
143- return db .Insert (ctx , & project_model.ProjectIssue {
144- IssueID : issue .ID ,
145- ProjectID : newProjectID ,
154+ newSorting := util .Iif (res .IssueCount > 0 , res .MaxSorting + 1 , 0 )
155+ return db .Insert (ctx , & project_model.ProjectIssue {
156+ IssueID : issue .ID ,
157+ ProjectID : newProjectID ,
158+ ProjectBoardID : newColumnID ,
159+ Sorting : newSorting ,
160+ })
146161 })
147162}
0 commit comments