KanBan: be able to set default board (#14147)
Co-authored-by: silverwind <me@silverwind.io> Co-authored-by: zeripath <art27@cantab.net>
This commit is contained in:
		
							parent
							
								
									c09e11d018
								
							
						
					
					
						commit
						3091600cc8
					
				
					 7 changed files with 193 additions and 56 deletions
				
			
		|  | @ -8,6 +8,7 @@ import ( | ||||||
| 	"code.gitea.io/gitea/modules/setting" | 	"code.gitea.io/gitea/modules/setting" | ||||||
| 	"code.gitea.io/gitea/modules/timeutil" | 	"code.gitea.io/gitea/modules/timeutil" | ||||||
| 
 | 
 | ||||||
|  | 	"xorm.io/builder" | ||||||
| 	"xorm.io/xorm" | 	"xorm.io/xorm" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
|  | @ -164,22 +165,43 @@ func UpdateProjectBoard(board *ProjectBoard) error { | ||||||
| func updateProjectBoard(e Engine, board *ProjectBoard) error { | func updateProjectBoard(e Engine, board *ProjectBoard) error { | ||||||
| 	_, err := e.ID(board.ID).Cols( | 	_, err := e.ID(board.ID).Cols( | ||||||
| 		"title", | 		"title", | ||||||
| 		"default", |  | ||||||
| 	).Update(board) | 	).Update(board) | ||||||
| 	return err | 	return err | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // GetProjectBoards fetches all boards related to a project
 | // GetProjectBoards fetches all boards related to a project
 | ||||||
| func GetProjectBoards(projectID int64) ([]*ProjectBoard, error) { | // if no default board set, first board is a temporary "Uncategorized" board
 | ||||||
| 
 | func GetProjectBoards(projectID int64) (ProjectBoardList, error) { | ||||||
| 	var boards = make([]*ProjectBoard, 0, 5) | 	return getProjectBoards(x, projectID) | ||||||
| 
 |  | ||||||
| 	sess := x.Where("project_id=?", projectID) |  | ||||||
| 	return boards, sess.Find(&boards) |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // GetUncategorizedBoard represents a board for issues not assigned to one
 | func getProjectBoards(e Engine, projectID int64) ([]*ProjectBoard, error) { | ||||||
| func GetUncategorizedBoard(projectID int64) (*ProjectBoard, error) { | 	var boards = make([]*ProjectBoard, 0, 5) | ||||||
|  | 
 | ||||||
|  | 	if err := e.Where("project_id=? AND `default`=?", projectID, false).Find(&boards); err != nil { | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	defaultB, err := getDefaultBoard(e, projectID) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return append([]*ProjectBoard{defaultB}, boards...), nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // getDefaultBoard return default board and create a dummy if none exist
 | ||||||
|  | func getDefaultBoard(e Engine, projectID int64) (*ProjectBoard, error) { | ||||||
|  | 	var board ProjectBoard | ||||||
|  | 	exist, err := e.Where("project_id=? AND `default`=?", projectID, true).Get(&board) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  | 	if exist { | ||||||
|  | 		return &board, nil | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// represents a board for issues not assigned to one
 | ||||||
| 	return &ProjectBoard{ | 	return &ProjectBoard{ | ||||||
| 		ProjectID: projectID, | 		ProjectID: projectID, | ||||||
| 		Title:     "Uncategorized", | 		Title:     "Uncategorized", | ||||||
|  | @ -187,22 +209,55 @@ func GetUncategorizedBoard(projectID int64) (*ProjectBoard, error) { | ||||||
| 	}, nil | 	}, nil | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | // SetDefaultBoard represents a board for issues not assigned to one
 | ||||||
|  | // if boardID is 0 unset default
 | ||||||
|  | func SetDefaultBoard(projectID, boardID int64) error { | ||||||
|  | 	sess := x | ||||||
|  | 
 | ||||||
|  | 	_, err := sess.Where(builder.Eq{ | ||||||
|  | 		"project_id": projectID, | ||||||
|  | 		"`default`":  true, | ||||||
|  | 	}).Cols("`default`").Update(&ProjectBoard{Default: false}) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if boardID > 0 { | ||||||
|  | 		_, err = sess.ID(boardID).Where(builder.Eq{"project_id": projectID}). | ||||||
|  | 			Cols("`default`").Update(&ProjectBoard{Default: true}) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return err | ||||||
|  | } | ||||||
|  | 
 | ||||||
| // LoadIssues load issues assigned to this board
 | // LoadIssues load issues assigned to this board
 | ||||||
| func (b *ProjectBoard) LoadIssues() (IssueList, error) { | func (b *ProjectBoard) LoadIssues() (IssueList, error) { | ||||||
| 	var boardID int64 | 	issueList := make([]*Issue, 0, 10) | ||||||
| 	if !b.Default { |  | ||||||
| 		boardID = b.ID |  | ||||||
| 
 | 
 | ||||||
| 	} else { | 	if b.ID != 0 { | ||||||
| 		// Issues without ProjectBoardID
 | 		issues, err := Issues(&IssuesOptions{ | ||||||
| 		boardID = -1 | 			ProjectBoardID: b.ID, | ||||||
|  | 			ProjectID:      b.ProjectID, | ||||||
|  | 		}) | ||||||
|  | 		if err != nil { | ||||||
|  | 			return nil, err | ||||||
|  | 		} | ||||||
|  | 		issueList = issues | ||||||
| 	} | 	} | ||||||
| 	issues, err := Issues(&IssuesOptions{ | 
 | ||||||
| 		ProjectBoardID: boardID, | 	if b.Default { | ||||||
| 		ProjectID:      b.ProjectID, | 		issues, err := Issues(&IssuesOptions{ | ||||||
| 	}) | 			ProjectBoardID: -1, // Issues without ProjectBoardID
 | ||||||
| 	b.Issues = issues | 			ProjectID:      b.ProjectID, | ||||||
| 	return issues, err | 		}) | ||||||
|  | 		if err != nil { | ||||||
|  | 			return nil, err | ||||||
|  | 		} | ||||||
|  | 		issueList = append(issueList, issues...) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	b.Issues = issueList | ||||||
|  | 	return issueList, nil | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // LoadIssues load issues assigned to the boards
 | // LoadIssues load issues assigned to the boards
 | ||||||
|  |  | ||||||
|  | @ -945,6 +945,8 @@ projects.board.edit_title = "New Board Name" | ||||||
| projects.board.new_title = "New Board Name" | projects.board.new_title = "New Board Name" | ||||||
| projects.board.new_submit = "Submit" | projects.board.new_submit = "Submit" | ||||||
| projects.board.new = "New Board" | projects.board.new = "New Board" | ||||||
|  | projects.board.set_default = "Set Default" | ||||||
|  | projects.board.set_default_desc = "Set this board as default for uncategorized issues and pulls" | ||||||
| projects.board.delete = "Delete Board" | projects.board.delete = "Delete Board" | ||||||
| projects.board.deletion_desc = "Deleting a project board moves all related issues to 'Uncategorized'. Continue?" | projects.board.deletion_desc = "Deleting a project board moves all related issues to 'Uncategorized'. Continue?" | ||||||
| projects.open = Open | projects.open = Open | ||||||
|  |  | ||||||
|  | @ -270,23 +270,17 @@ func ViewProject(ctx *context.Context) { | ||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	uncategorizedBoard, err := models.GetUncategorizedBoard(project.ID) |  | ||||||
| 	uncategorizedBoard.Title = ctx.Tr("repo.projects.type.uncategorized") |  | ||||||
| 	if err != nil { |  | ||||||
| 		ctx.ServerError("GetUncategorizedBoard", err) |  | ||||||
| 		return |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	boards, err := models.GetProjectBoards(project.ID) | 	boards, err := models.GetProjectBoards(project.ID) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		ctx.ServerError("GetProjectBoards", err) | 		ctx.ServerError("GetProjectBoards", err) | ||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	allBoards := models.ProjectBoardList{uncategorizedBoard} | 	if boards[0].ID == 0 { | ||||||
| 	allBoards = append(allBoards, boards...) | 		boards[0].Title = ctx.Tr("repo.projects.type.uncategorized") | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
| 	if ctx.Data["Issues"], err = allBoards.LoadIssues(); err != nil { | 	if ctx.Data["Issues"], err = boards.LoadIssues(); err != nil { | ||||||
| 		ctx.ServerError("LoadIssuesOfBoards", err) | 		ctx.ServerError("LoadIssuesOfBoards", err) | ||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
|  | @ -295,7 +289,7 @@ func ViewProject(ctx *context.Context) { | ||||||
| 
 | 
 | ||||||
| 	ctx.Data["CanWriteProjects"] = ctx.Repo.Permission.CanWrite(models.UnitTypeProjects) | 	ctx.Data["CanWriteProjects"] = ctx.Repo.Permission.CanWrite(models.UnitTypeProjects) | ||||||
| 	ctx.Data["Project"] = project | 	ctx.Data["Project"] = project | ||||||
| 	ctx.Data["Boards"] = allBoards | 	ctx.Data["Boards"] = boards | ||||||
| 	ctx.Data["PageIsProjects"] = true | 	ctx.Data["PageIsProjects"] = true | ||||||
| 	ctx.Data["RequiresDraggable"] = true | 	ctx.Data["RequiresDraggable"] = true | ||||||
| 
 | 
 | ||||||
|  | @ -416,21 +410,19 @@ func AddBoardToProjectPost(ctx *context.Context, form auth.EditProjectBoardTitle | ||||||
| 	}) | 	}) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // EditProjectBoardTitle allows a project board's title to be updated
 | func checkProjectBoardChangePermissions(ctx *context.Context) (*models.Project, *models.ProjectBoard) { | ||||||
| func EditProjectBoardTitle(ctx *context.Context, form auth.EditProjectBoardTitleForm) { |  | ||||||
| 
 |  | ||||||
| 	if ctx.User == nil { | 	if ctx.User == nil { | ||||||
| 		ctx.JSON(403, map[string]string{ | 		ctx.JSON(403, map[string]string{ | ||||||
| 			"message": "Only signed in users are allowed to perform this action.", | 			"message": "Only signed in users are allowed to perform this action.", | ||||||
| 		}) | 		}) | ||||||
| 		return | 		return nil, nil | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if !ctx.Repo.IsOwner() && !ctx.Repo.IsAdmin() && !ctx.Repo.CanAccess(models.AccessModeWrite, models.UnitTypeProjects) { | 	if !ctx.Repo.IsOwner() && !ctx.Repo.IsAdmin() && !ctx.Repo.CanAccess(models.AccessModeWrite, models.UnitTypeProjects) { | ||||||
| 		ctx.JSON(403, map[string]string{ | 		ctx.JSON(403, map[string]string{ | ||||||
| 			"message": "Only authorized users are allowed to perform this action.", | 			"message": "Only authorized users are allowed to perform this action.", | ||||||
| 		}) | 		}) | ||||||
| 		return | 		return nil, nil | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	project, err := models.GetProjectByID(ctx.ParamsInt64(":id")) | 	project, err := models.GetProjectByID(ctx.ParamsInt64(":id")) | ||||||
|  | @ -440,25 +432,35 @@ func EditProjectBoardTitle(ctx *context.Context, form auth.EditProjectBoardTitle | ||||||
| 		} else { | 		} else { | ||||||
| 			ctx.ServerError("GetProjectByID", err) | 			ctx.ServerError("GetProjectByID", err) | ||||||
| 		} | 		} | ||||||
| 		return | 		return nil, nil | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	board, err := models.GetProjectBoard(ctx.ParamsInt64(":boardID")) | 	board, err := models.GetProjectBoard(ctx.ParamsInt64(":boardID")) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		ctx.ServerError("GetProjectBoard", err) | 		ctx.ServerError("GetProjectBoard", err) | ||||||
| 		return | 		return nil, nil | ||||||
| 	} | 	} | ||||||
| 	if board.ProjectID != ctx.ParamsInt64(":id") { | 	if board.ProjectID != ctx.ParamsInt64(":id") { | ||||||
| 		ctx.JSON(422, map[string]string{ | 		ctx.JSON(422, map[string]string{ | ||||||
| 			"message": fmt.Sprintf("ProjectBoard[%d] is not in Project[%d] as expected", board.ID, project.ID), | 			"message": fmt.Sprintf("ProjectBoard[%d] is not in Project[%d] as expected", board.ID, project.ID), | ||||||
| 		}) | 		}) | ||||||
| 		return | 		return nil, nil | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if project.RepoID != ctx.Repo.Repository.ID { | 	if project.RepoID != ctx.Repo.Repository.ID { | ||||||
| 		ctx.JSON(422, map[string]string{ | 		ctx.JSON(422, map[string]string{ | ||||||
| 			"message": fmt.Sprintf("ProjectBoard[%d] is not in Repository[%d] as expected", board.ID, ctx.Repo.Repository.ID), | 			"message": fmt.Sprintf("ProjectBoard[%d] is not in Repository[%d] as expected", board.ID, ctx.Repo.Repository.ID), | ||||||
| 		}) | 		}) | ||||||
|  | 		return nil, nil | ||||||
|  | 	} | ||||||
|  | 	return project, board | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // EditProjectBoardTitle allows a project board's title to be updated
 | ||||||
|  | func EditProjectBoardTitle(ctx *context.Context, form auth.EditProjectBoardTitleForm) { | ||||||
|  | 
 | ||||||
|  | 	_, board := checkProjectBoardChangePermissions(ctx) | ||||||
|  | 	if ctx.Written() { | ||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -476,6 +478,24 @@ func EditProjectBoardTitle(ctx *context.Context, form auth.EditProjectBoardTitle | ||||||
| 	}) | 	}) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | // SetDefaultProjectBoard set default board for uncategorized issues/pulls
 | ||||||
|  | func SetDefaultProjectBoard(ctx *context.Context) { | ||||||
|  | 
 | ||||||
|  | 	project, board := checkProjectBoardChangePermissions(ctx) | ||||||
|  | 	if ctx.Written() { | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if err := models.SetDefaultBoard(project.ID, board.ID); err != nil { | ||||||
|  | 		ctx.ServerError("SetDefaultBoard", err) | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	ctx.JSON(200, map[string]interface{}{ | ||||||
|  | 		"ok": true, | ||||||
|  | 	}) | ||||||
|  | } | ||||||
|  | 
 | ||||||
| // MoveIssueAcrossBoards move a card from one board to another in a project
 | // MoveIssueAcrossBoards move a card from one board to another in a project
 | ||||||
| func MoveIssueAcrossBoards(ctx *context.Context) { | func MoveIssueAcrossBoards(ctx *context.Context) { | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
							
								
								
									
										28
									
								
								routers/repo/projects_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								routers/repo/projects_test.go
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,28 @@ | ||||||
|  | // Copyright 2020 The Gitea Authors. All rights reserved.
 | ||||||
|  | // Use of this source code is governed by a MIT-style
 | ||||||
|  | // license that can be found in the LICENSE file.
 | ||||||
|  | 
 | ||||||
|  | package repo | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"testing" | ||||||
|  | 
 | ||||||
|  | 	"code.gitea.io/gitea/models" | ||||||
|  | 	"code.gitea.io/gitea/modules/test" | ||||||
|  | 
 | ||||||
|  | 	"github.com/stretchr/testify/assert" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | func TestCheckProjectBoardChangePermissions(t *testing.T) { | ||||||
|  | 	models.PrepareTestEnv(t) | ||||||
|  | 	ctx := test.MockContext(t, "user2/repo1/projects/1/2") | ||||||
|  | 	test.LoadUser(t, ctx, 2) | ||||||
|  | 	test.LoadRepo(t, ctx, 1) | ||||||
|  | 	ctx.SetParams(":id", "1") | ||||||
|  | 	ctx.SetParams(":boardID", "2") | ||||||
|  | 
 | ||||||
|  | 	project, board := checkProjectBoardChangePermissions(ctx) | ||||||
|  | 	assert.NotNil(t, project) | ||||||
|  | 	assert.NotNil(t, board) | ||||||
|  | 	assert.False(t, ctx.Written()) | ||||||
|  | } | ||||||
|  | @ -800,6 +800,7 @@ func RegisterMacaronRoutes(m *macaron.Macaron) { | ||||||
| 					m.Group("/:boardID", func() { | 					m.Group("/:boardID", func() { | ||||||
| 						m.Put("", bindIgnErr(auth.EditProjectBoardTitleForm{}), repo.EditProjectBoardTitle) | 						m.Put("", bindIgnErr(auth.EditProjectBoardTitleForm{}), repo.EditProjectBoardTitle) | ||||||
| 						m.Delete("", repo.DeleteProjectBoard) | 						m.Delete("", repo.DeleteProjectBoard) | ||||||
|  | 						m.Post("/default", repo.SetDefaultProjectBoard) | ||||||
| 
 | 
 | ||||||
| 						m.Post("/:index", repo.MoveIssueAcrossBoards) | 						m.Post("/:index", repo.MoveIssueAcrossBoards) | ||||||
| 					}) | 					}) | ||||||
|  |  | ||||||
|  | @ -85,6 +85,12 @@ | ||||||
| 									{{svg "octicon-pencil"}} | 									{{svg "octicon-pencil"}} | ||||||
| 									{{$.i18n.Tr "repo.projects.board.edit"}} | 									{{$.i18n.Tr "repo.projects.board.edit"}} | ||||||
| 								</a> | 								</a> | ||||||
|  | 								{{if not .Default}} | ||||||
|  | 									<a class="item show-modal button" data-modal="#set-default-project-board-modal-{{.ID}}"> | ||||||
|  | 										{{svg "octicon-pin"}} | ||||||
|  | 										{{$.i18n.Tr "repo.projects.board.set_default"}} | ||||||
|  | 									</a> | ||||||
|  | 								{{end}} | ||||||
| 								<a class="item show-modal button" data-modal="#delete-board-modal-{{.ID}}"> | 								<a class="item show-modal button" data-modal="#delete-board-modal-{{.ID}}"> | ||||||
| 									{{svg "octicon-trashcan"}} | 									{{svg "octicon-trashcan"}} | ||||||
| 									{{$.i18n.Tr "repo.projects.board.delete"}} | 									{{$.i18n.Tr "repo.projects.board.delete"}} | ||||||
|  | @ -109,24 +115,34 @@ | ||||||
| 									</div> | 									</div> | ||||||
| 								</div> | 								</div> | ||||||
| 
 | 
 | ||||||
|  | 								<div class="ui basic modal" id="set-default-project-board-modal-{{.ID}}"> | ||||||
|  | 									<div class="ui icon header"> | ||||||
|  | 										{{$.i18n.Tr "repo.projects.board.set_default"}} | ||||||
|  | 									</div> | ||||||
|  | 									<div class="content center"> | ||||||
|  | 										<label> | ||||||
|  | 											{{$.i18n.Tr "repo.projects.board.set_default_desc"}} | ||||||
|  | 										</label> | ||||||
|  | 									</div> | ||||||
|  | 									<div class="text right actions"> | ||||||
|  | 										<div class="ui cancel button">{{$.i18n.Tr "settings.cancel"}}</div> | ||||||
|  | 										<button class="ui red button set-default-project-board" data-url="{{$.RepoLink}}/projects/{{$.Project.ID}}/{{.ID}}/default">{{$.i18n.Tr "repo.projects.board.set_default"}}</button> | ||||||
|  | 									</div> | ||||||
|  | 								</div> | ||||||
|  | 
 | ||||||
| 								<div class="ui basic modal" id="delete-board-modal-{{.ID}}"> | 								<div class="ui basic modal" id="delete-board-modal-{{.ID}}"> | ||||||
| 									<div class="ui icon header"> | 									<div class="ui icon header"> | ||||||
| 										{{$.i18n.Tr "repo.projects.board.delete"}} | 										{{$.i18n.Tr "repo.projects.board.delete"}} | ||||||
| 									</div> | 									</div> | ||||||
| 									<div class="content center"> | 									<div class="content center"> | ||||||
| 										<input type="hidden" name="action" value="delete"> | 										<label> | ||||||
| 										<div class="field"> | 											{{$.i18n.Tr "repo.projects.board.deletion_desc"}} | ||||||
| 											<label> | 										</label> | ||||||
| 												{{$.i18n.Tr "repo.projects.board.deletion_desc"}} | 									</div> | ||||||
| 											</label> | 									<div class="text right actions"> | ||||||
| 										</div> | 										<div class="ui cancel button">{{$.i18n.Tr "settings.cancel"}}</div> | ||||||
|  | 										<button class="ui red button delete-project-board" data-url="{{$.RepoLink}}/projects/{{$.Project.ID}}/{{.ID}}">{{$.i18n.Tr "repo.projects.board.delete"}}</button> | ||||||
| 									</div> | 									</div> | ||||||
| 									<form class="ui form" method="post"> |  | ||||||
| 										<div class="text right actions"> |  | ||||||
| 											<div class="ui cancel button">{{$.i18n.Tr "settings.cancel"}}</div> |  | ||||||
| 											<button class="ui red button delete-project-board" data-url="{{$.RepoLink}}/projects/{{$.Project.ID}}/{{.ID}}">{{$.i18n.Tr "repo.projects.board.delete"}}</button> |  | ||||||
| 										</div> |  | ||||||
| 									</form> |  | ||||||
| 								</div> | 								</div> | ||||||
| 							</div> | 							</div> | ||||||
| 						</div> | 						</div> | ||||||
|  |  | ||||||
|  | @ -27,14 +27,14 @@ export default async function initProject() { | ||||||
|             }, |             }, | ||||||
|           }); |           }); | ||||||
|         }, |         }, | ||||||
|       } |       }, | ||||||
|     ); |     ); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   $('.edit-project-board').each(function () { |   $('.edit-project-board').each(function () { | ||||||
|     const projectTitleLabel = $(this).closest('.board-column-header').find('.board-label'); |     const projectTitleLabel = $(this).closest('.board-column-header').find('.board-label'); | ||||||
|     const projectTitleInput = $(this).find( |     const projectTitleInput = $(this).find( | ||||||
|       '.content > .form > .field > .project-board-title' |       '.content > .form > .field > .project-board-title', | ||||||
|     ); |     ); | ||||||
| 
 | 
 | ||||||
|     $(this) |     $(this) | ||||||
|  | @ -59,6 +59,21 @@ export default async function initProject() { | ||||||
|       }); |       }); | ||||||
|   }); |   }); | ||||||
| 
 | 
 | ||||||
|  |   $(document).on('click', '.set-default-project-board', async function (e) { | ||||||
|  |     e.preventDefault(); | ||||||
|  | 
 | ||||||
|  |     await $.ajax({ | ||||||
|  |       method: 'POST', | ||||||
|  |       url: $(this).data('url'), | ||||||
|  |       headers: { | ||||||
|  |         'X-Csrf-Token': csrf, | ||||||
|  |         'X-Remote': true, | ||||||
|  |       }, | ||||||
|  |       contentType: 'application/json', | ||||||
|  |     }); | ||||||
|  | 
 | ||||||
|  |     window.location.reload(); | ||||||
|  |   }); | ||||||
|   $('.delete-project-board').each(function () { |   $('.delete-project-board').each(function () { | ||||||
|     $(this).click(function (e) { |     $(this).click(function (e) { | ||||||
|       e.preventDefault(); |       e.preventDefault(); | ||||||
|  | @ -72,7 +87,7 @@ export default async function initProject() { | ||||||
|         contentType: 'application/json', |         contentType: 'application/json', | ||||||
|         method: 'DELETE', |         method: 'DELETE', | ||||||
|       }).done(() => { |       }).done(() => { | ||||||
|         setTimeout(window.location.reload(true), 2000); |         window.location.reload(); | ||||||
|       }); |       }); | ||||||
|     }); |     }); | ||||||
|   }); |   }); | ||||||
|  | @ -93,7 +108,7 @@ export default async function initProject() { | ||||||
|       method: 'POST', |       method: 'POST', | ||||||
|     }).done(() => { |     }).done(() => { | ||||||
|       boardTitle.closest('form').removeClass('dirty'); |       boardTitle.closest('form').removeClass('dirty'); | ||||||
|       setTimeout(window.location.reload(true), 2000); |       window.location.reload(); | ||||||
|     }); |     }); | ||||||
|   }); |   }); | ||||||
| } | } | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue