Add default board to new projects, remove uncategorized pseudo-board (#29874)
On creation of an empty project (no template) a default board will be created instead of falling back to the uneditable pseudo-board. Every project now has to have exactly one default boards. As a consequence, you cannot unset a board as default, instead you have to set another board as default. Existing projects will be modified using a cron job, additionally this check will run every midnight by default. Deleting the default board is not allowed, you have to set another board as default to do it. Fixes #29873 Fixes #14679 along the way Fixes #29853 Co-authored-by: delvh <dev.lh@web.de> (cherry picked from commit e5160185ed65fd1c2bcb2fc7dc7e0b5514ddb299) Conflicts: options/locale/locale_en-US.ini trivial conflict because Forgejo strings do not have surrounding double quotes
This commit is contained in:
parent
b019ecce89
commit
8ffb9c6fb1
17 changed files with 400 additions and 196 deletions
|
@ -207,11 +207,7 @@ func ChangeProjectStatus(ctx *context.Context) {
|
|||
id := ctx.ParamsInt64(":id")
|
||||
|
||||
if err := project_model.ChangeProjectStatusByRepoIDAndID(ctx, 0, id, toClose); err != nil {
|
||||
if project_model.IsErrProjectNotExist(err) {
|
||||
ctx.NotFound("", err)
|
||||
} else {
|
||||
ctx.ServerError("ChangeProjectStatusByRepoIDAndID", err)
|
||||
}
|
||||
ctx.NotFoundOrServerError("ChangeProjectStatusByRepoIDAndID", project_model.IsErrProjectNotExist, err)
|
||||
return
|
||||
}
|
||||
ctx.Redirect(ctx.ContextUser.HomeLink() + "/-/projects?state=" + url.QueryEscape(ctx.Params(":action")))
|
||||
|
@ -221,11 +217,7 @@ func ChangeProjectStatus(ctx *context.Context) {
|
|||
func DeleteProject(ctx *context.Context) {
|
||||
p, err := project_model.GetProjectByID(ctx, ctx.ParamsInt64(":id"))
|
||||
if err != nil {
|
||||
if project_model.IsErrProjectNotExist(err) {
|
||||
ctx.NotFound("", nil)
|
||||
} else {
|
||||
ctx.ServerError("GetProjectByID", err)
|
||||
}
|
||||
ctx.NotFoundOrServerError("GetProjectByID", project_model.IsErrProjectNotExist, err)
|
||||
return
|
||||
}
|
||||
if p.OwnerID != ctx.ContextUser.ID {
|
||||
|
@ -254,11 +246,7 @@ func RenderEditProject(ctx *context.Context) {
|
|||
|
||||
p, err := project_model.GetProjectByID(ctx, ctx.ParamsInt64(":id"))
|
||||
if err != nil {
|
||||
if project_model.IsErrProjectNotExist(err) {
|
||||
ctx.NotFound("", nil)
|
||||
} else {
|
||||
ctx.ServerError("GetProjectByID", err)
|
||||
}
|
||||
ctx.NotFoundOrServerError("GetProjectByID", project_model.IsErrProjectNotExist, err)
|
||||
return
|
||||
}
|
||||
if p.OwnerID != ctx.ContextUser.ID {
|
||||
|
@ -303,11 +291,7 @@ func EditProjectPost(ctx *context.Context) {
|
|||
|
||||
p, err := project_model.GetProjectByID(ctx, projectID)
|
||||
if err != nil {
|
||||
if project_model.IsErrProjectNotExist(err) {
|
||||
ctx.NotFound("", nil)
|
||||
} else {
|
||||
ctx.ServerError("GetProjectByID", err)
|
||||
}
|
||||
ctx.NotFoundOrServerError("GetProjectByID", project_model.IsErrProjectNotExist, err)
|
||||
return
|
||||
}
|
||||
if p.OwnerID != ctx.ContextUser.ID {
|
||||
|
@ -335,11 +319,7 @@ func EditProjectPost(ctx *context.Context) {
|
|||
func ViewProject(ctx *context.Context) {
|
||||
project, err := project_model.GetProjectByID(ctx, ctx.ParamsInt64(":id"))
|
||||
if err != nil {
|
||||
if project_model.IsErrProjectNotExist(err) {
|
||||
ctx.NotFound("", nil)
|
||||
} else {
|
||||
ctx.ServerError("GetProjectByID", err)
|
||||
}
|
||||
ctx.NotFoundOrServerError("GetProjectByID", project_model.IsErrProjectNotExist, err)
|
||||
return
|
||||
}
|
||||
if project.OwnerID != ctx.ContextUser.ID {
|
||||
|
@ -353,10 +333,6 @@ func ViewProject(ctx *context.Context) {
|
|||
return
|
||||
}
|
||||
|
||||
if boards[0].ID == 0 {
|
||||
boards[0].Title = ctx.Locale.TrString("repo.projects.type.uncategorized")
|
||||
}
|
||||
|
||||
issuesMap, err := issues_model.LoadIssuesFromBoardList(ctx, boards)
|
||||
if err != nil {
|
||||
ctx.ServerError("LoadIssuesOfBoards", err)
|
||||
|
@ -493,11 +469,7 @@ func DeleteProjectBoard(ctx *context.Context) {
|
|||
|
||||
project, err := project_model.GetProjectByID(ctx, ctx.ParamsInt64(":id"))
|
||||
if err != nil {
|
||||
if project_model.IsErrProjectNotExist(err) {
|
||||
ctx.NotFound("", nil)
|
||||
} else {
|
||||
ctx.ServerError("GetProjectByID", err)
|
||||
}
|
||||
ctx.NotFoundOrServerError("GetProjectByID", project_model.IsErrProjectNotExist, err)
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -534,11 +506,7 @@ func AddBoardToProjectPost(ctx *context.Context) {
|
|||
|
||||
project, err := project_model.GetProjectByID(ctx, ctx.ParamsInt64(":id"))
|
||||
if err != nil {
|
||||
if project_model.IsErrProjectNotExist(err) {
|
||||
ctx.NotFound("", nil)
|
||||
} else {
|
||||
ctx.ServerError("GetProjectByID", err)
|
||||
}
|
||||
ctx.NotFoundOrServerError("GetProjectByID", project_model.IsErrProjectNotExist, err)
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -566,11 +534,7 @@ func CheckProjectBoardChangePermissions(ctx *context.Context) (*project_model.Pr
|
|||
|
||||
project, err := project_model.GetProjectByID(ctx, ctx.ParamsInt64(":id"))
|
||||
if err != nil {
|
||||
if project_model.IsErrProjectNotExist(err) {
|
||||
ctx.NotFound("", nil)
|
||||
} else {
|
||||
ctx.ServerError("GetProjectByID", err)
|
||||
}
|
||||
ctx.NotFoundOrServerError("GetProjectByID", project_model.IsErrProjectNotExist, err)
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
|
@ -636,21 +600,6 @@ func SetDefaultProjectBoard(ctx *context.Context) {
|
|||
ctx.JSONOK()
|
||||
}
|
||||
|
||||
// UnsetDefaultProjectBoard unset default board for uncategorized issues/pulls
|
||||
func UnsetDefaultProjectBoard(ctx *context.Context) {
|
||||
project, _ := CheckProjectBoardChangePermissions(ctx)
|
||||
if ctx.Written() {
|
||||
return
|
||||
}
|
||||
|
||||
if err := project_model.SetDefaultBoard(ctx, project.ID, 0); err != nil {
|
||||
ctx.ServerError("SetDefaultBoard", err)
|
||||
return
|
||||
}
|
||||
|
||||
ctx.JSONOK()
|
||||
}
|
||||
|
||||
// MoveIssues moves or keeps issues in a column and sorts them inside that column
|
||||
func MoveIssues(ctx *context.Context) {
|
||||
if ctx.Doer == nil {
|
||||
|
@ -662,11 +611,7 @@ func MoveIssues(ctx *context.Context) {
|
|||
|
||||
project, err := project_model.GetProjectByID(ctx, ctx.ParamsInt64(":id"))
|
||||
if err != nil {
|
||||
if project_model.IsErrProjectNotExist(err) {
|
||||
ctx.NotFound("ProjectNotExist", nil)
|
||||
} else {
|
||||
ctx.ServerError("GetProjectByID", err)
|
||||
}
|
||||
ctx.NotFoundOrServerError("GetProjectByID", project_model.IsErrProjectNotExist, err)
|
||||
return
|
||||
}
|
||||
if project.OwnerID != ctx.ContextUser.ID {
|
||||
|
@ -674,28 +619,15 @@ func MoveIssues(ctx *context.Context) {
|
|||
return
|
||||
}
|
||||
|
||||
var board *project_model.Board
|
||||
board, err := project_model.GetBoard(ctx, ctx.ParamsInt64(":boardID"))
|
||||
if err != nil {
|
||||
ctx.NotFoundOrServerError("GetProjectBoard", project_model.IsErrProjectBoardNotExist, err)
|
||||
return
|
||||
}
|
||||
|
||||
if ctx.ParamsInt64(":boardID") == 0 {
|
||||
board = &project_model.Board{
|
||||
ID: 0,
|
||||
ProjectID: project.ID,
|
||||
Title: ctx.Locale.TrString("repo.projects.type.uncategorized"),
|
||||
}
|
||||
} else {
|
||||
board, err = project_model.GetBoard(ctx, ctx.ParamsInt64(":boardID"))
|
||||
if err != nil {
|
||||
if project_model.IsErrProjectBoardNotExist(err) {
|
||||
ctx.NotFound("ProjectBoardNotExist", nil)
|
||||
} else {
|
||||
ctx.ServerError("GetProjectBoard", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
if board.ProjectID != project.ID {
|
||||
ctx.NotFound("BoardNotInProject", nil)
|
||||
return
|
||||
}
|
||||
if board.ProjectID != project.ID {
|
||||
ctx.NotFound("BoardNotInProject", nil)
|
||||
return
|
||||
}
|
||||
|
||||
type movedIssuesForm struct {
|
||||
|
@ -718,11 +650,7 @@ func MoveIssues(ctx *context.Context) {
|
|||
}
|
||||
movedIssues, err := issues_model.GetIssuesByIDs(ctx, issueIDs)
|
||||
if err != nil {
|
||||
if issues_model.IsErrIssueNotExist(err) {
|
||||
ctx.NotFound("IssueNotExisting", nil)
|
||||
} else {
|
||||
ctx.ServerError("GetIssueByID", err)
|
||||
}
|
||||
ctx.NotFoundOrServerError("GetIssueByID", issues_model.IsErrIssueNotExist, err)
|
||||
return
|
||||
}
|
||||
|
||||
|
|
|
@ -314,10 +314,6 @@ func ViewProject(ctx *context.Context) {
|
|||
return
|
||||
}
|
||||
|
||||
if boards[0].ID == 0 {
|
||||
boards[0].Title = ctx.Locale.TrString("repo.projects.type.uncategorized")
|
||||
}
|
||||
|
||||
issuesMap, err := issues_model.LoadIssuesFromBoardList(ctx, boards)
|
||||
if err != nil {
|
||||
ctx.ServerError("LoadIssuesOfBoards", err)
|
||||
|
@ -582,21 +578,6 @@ func SetDefaultProjectBoard(ctx *context.Context) {
|
|||
ctx.JSONOK()
|
||||
}
|
||||
|
||||
// UnSetDefaultProjectBoard unset default board for uncategorized issues/pulls
|
||||
func UnSetDefaultProjectBoard(ctx *context.Context) {
|
||||
project, _ := checkProjectBoardChangePermissions(ctx)
|
||||
if ctx.Written() {
|
||||
return
|
||||
}
|
||||
|
||||
if err := project_model.SetDefaultBoard(ctx, project.ID, 0); err != nil {
|
||||
ctx.ServerError("SetDefaultBoard", err)
|
||||
return
|
||||
}
|
||||
|
||||
ctx.JSONOK()
|
||||
}
|
||||
|
||||
// MoveIssues moves or keeps issues in a column and sorts them inside that column
|
||||
func MoveIssues(ctx *context.Context) {
|
||||
if ctx.Doer == nil {
|
||||
|
@ -627,28 +608,19 @@ func MoveIssues(ctx *context.Context) {
|
|||
return
|
||||
}
|
||||
|
||||
var board *project_model.Board
|
||||
board, err := project_model.GetBoard(ctx, ctx.ParamsInt64(":boardID"))
|
||||
if err != nil {
|
||||
if project_model.IsErrProjectBoardNotExist(err) {
|
||||
ctx.NotFound("ProjectBoardNotExist", nil)
|
||||
} else {
|
||||
ctx.ServerError("GetProjectBoard", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if ctx.ParamsInt64(":boardID") == 0 {
|
||||
board = &project_model.Board{
|
||||
ID: 0,
|
||||
ProjectID: project.ID,
|
||||
Title: ctx.Locale.TrString("repo.projects.type.uncategorized"),
|
||||
}
|
||||
} else {
|
||||
board, err = project_model.GetBoard(ctx, ctx.ParamsInt64(":boardID"))
|
||||
if err != nil {
|
||||
if project_model.IsErrProjectBoardNotExist(err) {
|
||||
ctx.NotFound("ProjectBoardNotExist", nil)
|
||||
} else {
|
||||
ctx.ServerError("GetProjectBoard", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
if board.ProjectID != project.ID {
|
||||
ctx.NotFound("BoardNotInProject", nil)
|
||||
return
|
||||
}
|
||||
if board.ProjectID != project.ID {
|
||||
ctx.NotFound("BoardNotInProject", nil)
|
||||
return
|
||||
}
|
||||
|
||||
type movedIssuesForm struct {
|
||||
|
|
|
@ -986,7 +986,6 @@ func registerRoutes(m *web.Route) {
|
|||
m.Put("", web.Bind(forms.EditProjectBoardForm{}), org.EditProjectBoard)
|
||||
m.Delete("", org.DeleteProjectBoard)
|
||||
m.Post("/default", org.SetDefaultProjectBoard)
|
||||
m.Post("/unsetdefault", org.UnsetDefaultProjectBoard)
|
||||
|
||||
m.Post("/move", org.MoveIssues)
|
||||
})
|
||||
|
@ -1360,7 +1359,6 @@ func registerRoutes(m *web.Route) {
|
|||
m.Put("", web.Bind(forms.EditProjectBoardForm{}), repo.EditProjectBoard)
|
||||
m.Delete("", repo.DeleteProjectBoard)
|
||||
m.Post("/default", repo.SetDefaultProjectBoard)
|
||||
m.Post("/unsetdefault", repo.UnSetDefaultProjectBoard)
|
||||
|
||||
m.Post("/move", repo.MoveIssues)
|
||||
})
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue