return issuesMap, nil | 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) | oldProjectID := issue.projectID(ctx) | ||||
if err := issue.LoadRepo(ctx); err != nil { | if err := issue.LoadRepo(ctx); err != nil { | ||||
return err | 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{ | return db.Insert(ctx, &project_model.ProjectIssue{ | ||||
IssueID: issue.ID, | |||||
ProjectID: newProjectID, | |||||
IssueID: issue.ID, | |||||
ProjectID: newProjectID, | |||||
ProjectBoardID: newColumnID, | |||||
Sorting: maxSorting, | |||||
}) | }) | ||||
} | } |
return fmt.Errorf("deleteBoardByID: cannot delete default board") | 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 | return err | ||||
} | } | ||||
return boards, nil | 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 | var board Board | ||||
has, err := db.GetEngine(ctx). | has, err := db.GetEngine(ctx). | ||||
Where("project_id=? AND `default` = ?", p.ID, true). | Where("project_id=? AND `default` = ?", p.ID, true). |
IssueID int64 `xorm:"INDEX"` | IssueID int64 `xorm:"INDEX"` | ||||
ProjectID 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"` | ProjectBoardID int64 `xorm:"INDEX"` | ||||
// the sorting order on the board | // the sorting order on the board | ||||
}) | }) | ||||
} | } | ||||
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 | return err | ||||
} | } | ||||
} | } | ||||
projectID := ctx.FormInt64("id") | 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 { | for _, issue := range issues { | ||||
if issue.Project != nil { | if issue.Project != nil { | ||||
if issue.Project.ID == projectID { | if issue.Project.ID == projectID { | ||||
} | } | ||||
} | } | ||||
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) | ctx.ServerError("ChangeProjectAssign", err) | ||||
return | return | ||||
} | } |
} | } | ||||
projectID := ctx.FormInt64("id") | 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 { | for _, issue := range issues { | ||||
if issue.Project != nil { | if issue.Project != nil { | ||||
if issue.Project.ID == projectID { | if issue.Project.ID == projectID { | ||||
} | } | ||||
} | } | ||||
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) | ctx.ServerError("ChangeProjectAssign", err) | ||||
return | return | ||||
} | } |
git_model "code.gitea.io/gitea/models/git" | git_model "code.gitea.io/gitea/models/git" | ||||
issues_model "code.gitea.io/gitea/models/issues" | issues_model "code.gitea.io/gitea/models/issues" | ||||
access_model "code.gitea.io/gitea/models/perm/access" | 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" | pull_model "code.gitea.io/gitea/models/pull" | ||||
repo_model "code.gitea.io/gitea/models/repo" | repo_model "code.gitea.io/gitea/models/repo" | ||||
"code.gitea.io/gitea/models/unit" | "code.gitea.io/gitea/models/unit" | ||||
if projectID > 0 { | if projectID > 0 { | ||||
if !ctx.Repo.CanWrite(unit.TypeProjects) { | 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 | 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) | ctx.ServerError("ChangeProjectAssign", err) | ||||
return | return | ||||
} | } |
} | } | ||||
} | } | ||||
if projectID > 0 { | 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 | return err | ||||
} | } | ||||
} | } |