From 5c48912dd822d6f92c0a6d38d09005dd1960cb4f Mon Sep 17 00:00:00 2001 From: Romain Date: Wed, 10 Feb 2021 13:05:12 +0100 Subject: [PATCH 1/5] Sort Project boards (#14533) --- models/project_board.go | 3 ++- templates/repo/projects/view.tmpl | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/models/project_board.go b/models/project_board.go index a9c0b3ed8bb04..8d4c3b917cb2a 100644 --- a/models/project_board.go +++ b/models/project_board.go @@ -36,6 +36,7 @@ type ProjectBoard struct { ID int64 `xorm:"pk autoincr"` Title string Default bool `xorm:"NOT NULL DEFAULT false"` // issues not assigned to a specific board will be assigned to this board + Sorting int8 `xorm:"DEFAULT 0"` ProjectID int64 `xorm:"INDEX NOT NULL"` CreatorID int64 `xorm:"NOT NULL"` @@ -178,7 +179,7 @@ func GetProjectBoards(projectID int64) (ProjectBoardList, error) { func getProjectBoards(e Engine, projectID int64) ([]*ProjectBoard, error) { var boards = make([]*ProjectBoard, 0, 5) - if err := e.Where("project_id=? AND `default`=?", projectID, false).Find(&boards); err != nil { + if err := e.Where("project_id=? AND `default`=?", projectID, false).OrderBy("Sorting").Find(&boards); err != nil { return nil, err } diff --git a/templates/repo/projects/view.tmpl b/templates/repo/projects/view.tmpl index 9b2aa4bc7d04d..e82ba05a26906 100644 --- a/templates/repo/projects/view.tmpl +++ b/templates/repo/projects/view.tmpl @@ -72,7 +72,7 @@
{{ range $board := .Boards }} -
+
{{.Title}}
{{if and $.CanWriteProjects (not $.Repository.IsArchived) $.PageIsProjects (ne .ID 0)}} From c7d05b4e4cb1f57f6c0c82391668febd7449343f Mon Sep 17 00:00:00 2001 From: Romain Date: Wed, 10 Feb 2021 17:41:26 +0100 Subject: [PATCH 2/5] Sort Project board (#14533) --- models/project_board.go | 31 +++++++++++++++++++++++++++---- modules/forms/repo_form.go | 8 ++++---- routers/repo/projects.go | 12 ++++++++---- routers/routes/web.go | 4 ++-- templates/repo/projects/view.tmpl | 2 +- web_src/js/features/projects.js | 29 +++++++++++++++++++++++++++++ 6 files changed, 71 insertions(+), 15 deletions(-) diff --git a/models/project_board.go b/models/project_board.go index 8d4c3b917cb2a..e56bf8f819919 100644 --- a/models/project_board.go +++ b/models/project_board.go @@ -158,15 +158,24 @@ func getProjectBoard(e Engine, boardID int64) (*ProjectBoard, error) { return board, nil } -// UpdateProjectBoard updates the title of a project board +// UpdateProjectBoard updates a project board func UpdateProjectBoard(board *ProjectBoard) error { return updateProjectBoard(x, board) } func updateProjectBoard(e Engine, board *ProjectBoard) error { - _, err := e.ID(board.ID).Cols( - "title", - ).Update(board) + var fieldToUpdate []string + + if board.Sorting != 0 { + fieldToUpdate = append(fieldToUpdate, "sorting") + } + + if board.Title != "" { + fieldToUpdate = append(fieldToUpdate, "title") + } + + _, err := e.ID(board.ID).Cols(fieldToUpdate...).Update(board) + return err } @@ -278,3 +287,17 @@ func (bs ProjectBoardList) LoadIssues() (IssueList, error) { } return issues, nil } + +// UpdateProjectBoardSorting update project board sorting +func UpdateProjectBoardSorting(bs ProjectBoardList) error { + for i := range bs { + _, err := x.ID(bs[i].ID).Cols( + "sorting", + ).Update(bs[i]) + + if err != nil { + return err + } + } + return nil +} diff --git a/modules/forms/repo_form.go b/modules/forms/repo_form.go index ac968a1dd5b67..f177b21f05ac6 100644 --- a/modules/forms/repo_form.go +++ b/modules/forms/repo_form.go @@ -487,10 +487,10 @@ type UserCreateProjectForm struct { UID int64 `binding:"Required"` } -// EditProjectBoardTitleForm is a form for editing the title of a project's -// board -type EditProjectBoardTitleForm struct { - Title string `binding:"Required;MaxSize(100)"` +// EditProjectBoardForm is a form for editing a project board +type EditProjectBoardForm struct { + Title string `binding:"Required;MaxSize(100)"` + Sorting int8 } // _____ .__.__ __ diff --git a/routers/repo/projects.go b/routers/repo/projects.go index 49bcfef0ce5b1..4aa03e9efcb26 100644 --- a/routers/repo/projects.go +++ b/routers/repo/projects.go @@ -403,7 +403,7 @@ func DeleteProjectBoard(ctx *context.Context) { // AddBoardToProjectPost allows a new board to be added to a project. func AddBoardToProjectPost(ctx *context.Context) { - form := web.GetForm(ctx).(*auth.EditProjectBoardTitleForm) + form := web.GetForm(ctx).(*auth.EditProjectBoardForm) if !ctx.Repo.IsOwner() && !ctx.Repo.IsAdmin() && !ctx.Repo.CanAccess(models.AccessModeWrite, models.UnitTypeProjects) { ctx.JSON(403, map[string]string{ "message": "Only authorized users are allowed to perform this action.", @@ -481,9 +481,9 @@ func checkProjectBoardChangePermissions(ctx *context.Context) (*models.Project, return project, board } -// EditProjectBoardTitle allows a project board's title to be updated -func EditProjectBoardTitle(ctx *context.Context) { - form := web.GetForm(ctx).(*auth.EditProjectBoardTitleForm) +// EditProjectBoard allows a project board's to be updated +func EditProjectBoard(ctx *context.Context) { + form := web.GetForm(ctx).(*auth.EditProjectBoardForm) _, board := checkProjectBoardChangePermissions(ctx) if ctx.Written() { return @@ -493,6 +493,10 @@ func EditProjectBoardTitle(ctx *context.Context) { board.Title = form.Title } + if form.Sorting != 0 { + board.Sorting = form.Sorting + } + if err := models.UpdateProjectBoard(board); err != nil { ctx.ServerError("UpdateProjectBoard", err) return diff --git a/routers/routes/web.go b/routers/routes/web.go index 1f860a6239497..9e3e690fb965f 100644 --- a/routers/routes/web.go +++ b/routers/routes/web.go @@ -853,7 +853,7 @@ func RegisterRoutes(m *web.Route) { m.Get("/new", repo.NewProject) m.Post("/new", bindIgnErr(auth.CreateProjectForm{}), repo.NewProjectPost) m.Group("/{id}", func() { - m.Post("", bindIgnErr(auth.EditProjectBoardTitleForm{}), repo.AddBoardToProjectPost) + m.Post("", bindIgnErr(auth.EditProjectBoardForm{}), repo.AddBoardToProjectPost) m.Post("/delete", repo.DeleteProject) m.Get("/edit", repo.EditProject) @@ -861,7 +861,7 @@ func RegisterRoutes(m *web.Route) { m.Post("/{action:open|close}", repo.ChangeProjectStatus) m.Group("/{boardID}", func() { - m.Put("", bindIgnErr(auth.EditProjectBoardTitleForm{}), repo.EditProjectBoardTitle) + m.Put("", bindIgnErr(auth.EditProjectBoardForm{}), repo.EditProjectBoard) m.Delete("", repo.DeleteProjectBoard) m.Post("/default", repo.SetDefaultProjectBoard) diff --git a/templates/repo/projects/view.tmpl b/templates/repo/projects/view.tmpl index e82ba05a26906..de1fc37b03fa4 100644 --- a/templates/repo/projects/view.tmpl +++ b/templates/repo/projects/view.tmpl @@ -72,7 +72,7 @@
{{ range $board := .Boards }} -
+
{{.Title}}
{{if and $.CanWriteProjects (not $.Repository.IsArchived) $.PageIsProjects (ne .ID 0)}} diff --git a/web_src/js/features/projects.js b/web_src/js/features/projects.js index b5f52f7443891..8b6fdc2b824a9 100644 --- a/web_src/js/features/projects.js +++ b/web_src/js/features/projects.js @@ -8,6 +8,34 @@ export default async function initProject() { const {Sortable} = await import(/* webpackChunkName: "sortable" */'sortablejs'); const boardColumns = document.getElementsByClassName('board-column'); + new Sortable( + document.getElementsByClassName('board')[0], + { + group: "board-column", + draggable: ".board-column", + animation: 150, + onSort: () => { + const board = document.getElementsByClassName('board')[0]; + const boardColumns = board.getElementsByClassName('board-column'); + + boardColumns.forEach(function(column, i){ + if ($(column).data('sorting') != i) { + $.ajax({ + url: $(column).data('url'), + data: JSON.stringify({sorting: i}), + headers: { + 'X-Csrf-Token': csrf, + 'X-Remote': true, + }, + contentType: 'application/json', + method: 'PUT', + }); + } + }); + }, + }, + ); + for (const column of boardColumns) { new Sortable( column.getElementsByClassName('board')[0], @@ -74,6 +102,7 @@ export default async function initProject() { window.location.reload(); }); + $('.delete-project-board').each(function () { $(this).click(function (e) { e.preventDefault(); From cf10f698445a7533bd3ec1681c697df8ab3346db Mon Sep 17 00:00:00 2001 From: Romain Date: Wed, 10 Feb 2021 18:10:28 +0100 Subject: [PATCH 3/5] JS linter fix --- web_src/js/features/projects.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/web_src/js/features/projects.js b/web_src/js/features/projects.js index 8b6fdc2b824a9..254079b7693b3 100644 --- a/web_src/js/features/projects.js +++ b/web_src/js/features/projects.js @@ -11,15 +11,15 @@ export default async function initProject() { new Sortable( document.getElementsByClassName('board')[0], { - group: "board-column", - draggable: ".board-column", + group: 'board-column', + draggable: '.board-column', animation: 150, onSort: () => { const board = document.getElementsByClassName('board')[0]; const boardColumns = board.getElementsByClassName('board-column'); - boardColumns.forEach(function(column, i){ - if ($(column).data('sorting') != i) { + boardColumns.forEach((column, i) => { + if (parseInt($(column).data('sorting')) !== i) { $.ajax({ url: $(column).data('url'), data: JSON.stringify({sorting: i}), From db9b7bbcc7174dcd5450566a8d8560489e86b1f3 Mon Sep 17 00:00:00 2001 From: Romain Date: Wed, 10 Feb 2021 18:27:25 +0100 Subject: [PATCH 4/5] Make fmt --- web_src/js/features/projects.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web_src/js/features/projects.js b/web_src/js/features/projects.js index 254079b7693b3..642054f5419e7 100644 --- a/web_src/js/features/projects.js +++ b/web_src/js/features/projects.js @@ -19,7 +19,7 @@ export default async function initProject() { const boardColumns = board.getElementsByClassName('board-column'); boardColumns.forEach((column, i) => { - if (parseInt($(column).data('sorting')) !== i) { + if (parseInt($(column).data('sorting')) !== i) { $.ajax({ url: $(column).data('url'), data: JSON.stringify({sorting: i}), From 979c391038f911b8046ccf8cb02db70eca832a6c Mon Sep 17 00:00:00 2001 From: Romain Date: Wed, 10 Feb 2021 18:55:56 +0100 Subject: [PATCH 5/5] JS lint --- web_src/js/features/projects.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web_src/js/features/projects.js b/web_src/js/features/projects.js index 642054f5419e7..254079b7693b3 100644 --- a/web_src/js/features/projects.js +++ b/web_src/js/features/projects.js @@ -19,7 +19,7 @@ export default async function initProject() { const boardColumns = board.getElementsByClassName('board-column'); boardColumns.forEach((column, i) => { - if (parseInt($(column).data('sorting')) !== i) { + if (parseInt($(column).data('sorting')) !== i) { $.ajax({ url: $(column).data('url'), data: JSON.stringify({sorting: i}),