@@ -90,22 +90,16 @@ func LoadIssuesFromBoardList(ctx context.Context, bs project_model.BoardList) (m | |||
return issuesMap, nil | |||
} | |||
// ChangeProjectAssign changes the project associated with an issue | |||
func ChangeProjectAssign(ctx context.Context, issue *Issue, doer *user_model.User, newProjectID int64) error { | |||
ctx, committer, err := db.TxContext(ctx) | |||
if err != nil { | |||
return err | |||
} | |||
defer committer.Close() | |||
if err := addUpdateIssueProject(ctx, issue, doer, newProjectID); err != nil { | |||
return err | |||
} | |||
return committer.Commit() | |||
// ChangeProjectAssign changes the project associated with an issue, if newProjectID is 0, the issue is removed from the project | |||
func ChangeProjectAssign(ctx context.Context, issue *Issue, doer *user_model.User, newProjectID, newColumnID int64) error { | |||
return db.WithTx(ctx, func(ctx context.Context) error { | |||
return addUpdateIssueProject(ctx, issue, doer, newProjectID, newColumnID) | |||
}) | |||
} | |||
func addUpdateIssueProject(ctx context.Context, issue *Issue, doer *user_model.User, newProjectID int64) error { | |||
// addUpdateIssueProject adds or updates the project the default column associated with an issue | |||
// If newProjectID is 0, the issue is removed from the project | |||
func addUpdateIssueProject(ctx context.Context, issue *Issue, doer *user_model.User, newProjectID, newColumnID int64) error { | |||
oldProjectID := issue.projectID(ctx) | |||
if err := issue.LoadRepo(ctx); err != nil { | |||
@@ -139,9 +133,25 @@ func addUpdateIssueProject(ctx context.Context, issue *Issue, doer *user_model.U | |||
return err | |||
} | |||
} | |||
if newProjectID == 0 || newColumnID == 0 { | |||
return nil | |||
} | |||
var maxSorting int64 | |||
if _, err := db.GetEngine(ctx).Select("Max(sorting)").Table("project_issue"). | |||
Where("project_id=?", newProjectID). | |||
And("project_board_id=?", newColumnID). | |||
Get(&maxSorting); err != nil { | |||
return err | |||
} | |||
if maxSorting > 0 { | |||
maxSorting++ | |||
} | |||
return db.Insert(ctx, &project_model.ProjectIssue{ | |||
IssueID: issue.ID, | |||
ProjectID: newProjectID, | |||
IssueID: issue.ID, | |||
ProjectID: newProjectID, | |||
ProjectBoardID: newColumnID, | |||
Sorting: maxSorting, | |||
}) | |||
} |
@@ -198,7 +198,17 @@ func deleteBoardByID(ctx context.Context, boardID int64) error { | |||
return fmt.Errorf("deleteBoardByID: cannot delete default board") | |||
} | |||
if err = board.removeIssues(ctx); err != nil { | |||
// move all issues to the default column | |||
project, err := GetProjectByID(ctx, board.ProjectID) | |||
if err != nil { | |||
return err | |||
} | |||
defaultBoard, err := project.GetDefaultBoard(ctx) | |||
if err != nil { | |||
return err | |||
} | |||
if err = board.moveIssuesToDefault(ctx, defaultBoard.ID); err != nil { | |||
return err | |||
} | |||
@@ -258,8 +268,8 @@ func (p *Project) GetBoards(ctx context.Context) (BoardList, error) { | |||
return boards, nil | |||
} | |||
// getDefaultBoard return default board and ensure only one exists | |||
func (p *Project) getDefaultBoard(ctx context.Context) (*Board, error) { | |||
// GetDefaultBoard return default board and ensure only one exists | |||
func (p *Project) GetDefaultBoard(ctx context.Context) (*Board, error) { | |||
var board Board | |||
has, err := db.GetEngine(ctx). | |||
Where("project_id=? AND `default` = ?", p.ID, true). |
@@ -17,7 +17,7 @@ type ProjectIssue struct { //revive:disable-line:exported | |||
IssueID int64 `xorm:"INDEX"` | |||
ProjectID int64 `xorm:"INDEX"` | |||
// If 0, then it has not been added to a specific board in the project | |||
// If this should not be zero from 1.22. If it's zero, it will not be displayed on UI and maybe result in errors. | |||
ProjectBoardID int64 `xorm:"INDEX"` | |||
// the sorting order on the board | |||
@@ -102,8 +102,8 @@ func MoveIssuesOnProjectBoard(ctx context.Context, board *Board, sortedIssueIDs | |||
}) | |||
} | |||
func (b *Board) removeIssues(ctx context.Context) error { | |||
_, err := db.GetEngine(ctx).Exec("UPDATE `project_issue` SET project_board_id = 0 WHERE project_board_id = ? ", b.ID) | |||
func (b *Board) moveIssuesToDefault(ctx context.Context, defaultBoardID int64) error { | |||
_, err := db.GetEngine(ctx).Exec("UPDATE `project_issue` SET project_board_id = ? WHERE project_board_id = ? ", defaultBoardID, b.ID) | |||
return err | |||
} | |||
@@ -442,6 +442,21 @@ func UpdateIssueProject(ctx *context.Context) { | |||
} | |||
projectID := ctx.FormInt64("id") | |||
var dstColumnID int64 | |||
if projectID > 0 { | |||
dstProject, err := project_model.GetProjectByID(ctx, projectID) | |||
if err != nil { | |||
ctx.ServerError("GetProjectByID", err) | |||
return | |||
} | |||
dstDefaultColumn, err := dstProject.GetDefaultBoard(ctx) | |||
if err != nil { | |||
ctx.ServerError("GetDefaultBoard", err) | |||
return | |||
} | |||
dstColumnID = dstDefaultColumn.ID | |||
} | |||
for _, issue := range issues { | |||
if issue.Project != nil { | |||
if issue.Project.ID == projectID { | |||
@@ -449,7 +464,7 @@ func UpdateIssueProject(ctx *context.Context) { | |||
} | |||
} | |||
if err := issues_model.ChangeProjectAssign(ctx, issue, ctx.Doer, projectID); err != nil { | |||
if err := issues_model.ChangeProjectAssign(ctx, issue, ctx.Doer, projectID, dstColumnID); err != nil { | |||
ctx.ServerError("ChangeProjectAssign", err) | |||
return | |||
} |
@@ -385,6 +385,21 @@ func UpdateIssueProject(ctx *context.Context) { | |||
} | |||
projectID := ctx.FormInt64("id") | |||
var dstColumnID int64 | |||
if projectID > 0 { | |||
dstProject, err := project_model.GetProjectByID(ctx, projectID) | |||
if err != nil { | |||
ctx.ServerError("GetProjectByID", err) | |||
return | |||
} | |||
dstDefaultColumn, err := dstProject.GetDefaultBoard(ctx) | |||
if err != nil { | |||
ctx.ServerError("GetDefaultBoard", err) | |||
return | |||
} | |||
dstColumnID = dstDefaultColumn.ID | |||
} | |||
for _, issue := range issues { | |||
if issue.Project != nil { | |||
if issue.Project.ID == projectID { | |||
@@ -392,7 +407,7 @@ func UpdateIssueProject(ctx *context.Context) { | |||
} | |||
} | |||
if err := issues_model.ChangeProjectAssign(ctx, issue, ctx.Doer, projectID); err != nil { | |||
if err := issues_model.ChangeProjectAssign(ctx, issue, ctx.Doer, projectID, dstColumnID); err != nil { | |||
ctx.ServerError("ChangeProjectAssign", err) | |||
return | |||
} |
@@ -20,6 +20,7 @@ import ( | |||
git_model "code.gitea.io/gitea/models/git" | |||
issues_model "code.gitea.io/gitea/models/issues" | |||
access_model "code.gitea.io/gitea/models/perm/access" | |||
project_model "code.gitea.io/gitea/models/project" | |||
pull_model "code.gitea.io/gitea/models/pull" | |||
repo_model "code.gitea.io/gitea/models/repo" | |||
"code.gitea.io/gitea/models/unit" | |||
@@ -1332,10 +1333,20 @@ func CompareAndPullRequestPost(ctx *context.Context) { | |||
if projectID > 0 { | |||
if !ctx.Repo.CanWrite(unit.TypeProjects) { | |||
ctx.Error(http.StatusBadRequest, "user hasn't the permission to write to projects") | |||
log.Error("user hasn't the permission to write to projects") | |||
return | |||
} | |||
if err := issues_model.ChangeProjectAssign(ctx, pullIssue, ctx.Doer, projectID); err != nil { | |||
dstProject, err := project_model.GetProjectByID(ctx, projectID) | |||
if err != nil { | |||
ctx.ServerError("GetProjectByID", err) | |||
return | |||
} | |||
dstDefaultColumn, err := dstProject.GetDefaultBoard(ctx) | |||
if err != nil { | |||
ctx.ServerError("GetDefaultBoard", err) | |||
return | |||
} | |||
if err := issues_model.ChangeProjectAssign(ctx, pullIssue, ctx.Doer, projectID, dstDefaultColumn.ID); err != nil { | |||
ctx.ServerError("ChangeProjectAssign", err) | |||
return | |||
} |
@@ -42,7 +42,15 @@ func NewIssue(ctx context.Context, repo *repo_model.Repository, issue *issues_mo | |||
} | |||
} | |||
if projectID > 0 { | |||
if err := issues_model.ChangeProjectAssign(ctx, issue, issue.Poster, projectID); err != nil { | |||
project, err := project_model.GetProjectByID(ctx, projectID) | |||
if err != nil { | |||
return err | |||
} | |||
defaultBoard, err := project.GetDefaultBoard(ctx) | |||
if err != nil { | |||
return err | |||
} | |||
if err := issues_model.ChangeProjectAssign(ctx, issue, issue.Poster, projectID, defaultBoard.ID); err != nil { | |||
return err | |||
} | |||
} |