From ad1095a5ecd73e8b6585f2a35c96e0c7d2a6b196 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Thu, 25 Apr 2024 11:44:04 +0800 Subject: [PATCH 01/49] Fix moving column start multiple POST requests and default column will not be moved. --- models/project/board.go | 19 +++++---- models/project/issue.go | 27 ++++++++++++ routers/web/org/projects.go | 63 ++++++++++++++++++++++++++++ routers/web/web.go | 1 + templates/projects/view.tmpl | 2 +- web_src/js/features/repo-projects.js | 25 ++++++----- 6 files changed, 117 insertions(+), 20 deletions(-) diff --git a/models/project/board.go b/models/project/board.go index 7faabc52c58bf..aa995caa804cd 100644 --- a/models/project/board.go +++ b/models/project/board.go @@ -242,17 +242,11 @@ func UpdateBoard(ctx context.Context, board *Board) error { // GetBoards fetches all boards related to a project func (p *Project) GetBoards(ctx context.Context) (BoardList, error) { boards := make([]*Board, 0, 5) - - if err := db.GetEngine(ctx).Where("project_id=? AND `default`=?", p.ID, false).OrderBy("sorting").Find(&boards); err != nil { - return nil, err - } - - defaultB, err := p.getDefaultBoard(ctx) - if err != nil { + if err := db.GetEngine(ctx).Where("project_id=?", p.ID).OrderBy("sorting").Find(&boards); err != nil { return nil, err } - return append([]*Board{defaultB}, boards...), nil + return boards, nil } // getDefaultBoard return default board and ensure only one exists @@ -316,3 +310,12 @@ func UpdateBoardSorting(ctx context.Context, bs BoardList) error { return nil }) } + +func GetColumnsByIDs(ctx context.Context, columnsIDs []int64) (BoardList, error) { + columns := make([]*Board, 0, 5) + if err := db.GetEngine(ctx).In("id", columnsIDs).OrderBy("sorting").Find(&columns); err != nil { + return nil, err + } + + return columns, nil +} diff --git a/models/project/issue.go b/models/project/issue.go index ebc9719de55d0..95d0853aa5421 100644 --- a/models/project/issue.go +++ b/models/project/issue.go @@ -106,3 +106,30 @@ 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) return err } + +// MoveColumnsOnProject moves or keeps issues in a column and sorts them inside that column +func MoveColumnsOnProject(ctx context.Context, project *Project, sortedColumnIDs map[int64]int64) error { + return db.WithTx(ctx, func(ctx context.Context) error { + sess := db.GetEngine(ctx) + + columnIDs := make([]int64, 0, len(sortedColumnIDs)) + for _, columnID := range sortedColumnIDs { + columnIDs = append(columnIDs, columnID) + } + count, err := sess.Table(new(Board)).Where("project_id=?", project.ID).In("id", columnIDs).Count() + if err != nil { + return err + } + if int(count) != len(sortedColumnIDs) { + return fmt.Errorf("all issues have to be added to a project first") + } + + for sorting, columnID := range sortedColumnIDs { + _, err = sess.Exec("UPDATE `project_board` SET sorting=? WHERE id=?", sorting, columnID) + if err != nil { + return err + } + } + return nil + }) +} diff --git a/routers/web/org/projects.go b/routers/web/org/projects.go index 7f78d1c830b7f..1b0ea613afcf1 100644 --- a/routers/web/org/projects.go +++ b/routers/web/org/projects.go @@ -678,3 +678,66 @@ func MoveIssues(ctx *context.Context) { ctx.JSONOK() } + +// MoveColumns moves or keeps columns in a project and sorts them inside that project +func MoveColumns(ctx *context.Context) { + if ctx.Doer == nil { + ctx.JSON(http.StatusForbidden, map[string]string{ + "message": "Only signed in users are allowed to perform this action.", + }) + return + } + + project, err := project_model.GetProjectByID(ctx, ctx.ParamsInt64(":id")) + if err != nil { + ctx.NotFoundOrServerError("GetProjectByID", project_model.IsErrProjectNotExist, err) + return + } + if project.OwnerID != ctx.ContextUser.ID { + ctx.NotFound("InvalidRepoID", nil) + return + } + + type movedColumnsForm struct { + Columns []struct { + ColumnID int64 `json:"columnID"` + Sorting int64 `json:"sorting"` + } `json:"columns"` + } + + form := &movedColumnsForm{} + if err = json.NewDecoder(ctx.Req.Body).Decode(&form); err != nil { + ctx.ServerError("DecodeMovedColumnsForm", err) + } + + columnIDs := make([]int64, 0, len(form.Columns)) + sortedColumnIDs := make(map[int64]int64) + for _, column := range form.Columns { + columnIDs = append(columnIDs, column.ColumnID) + sortedColumnIDs[column.Sorting] = column.ColumnID + } + movedColumns, err := project_model.GetColumnsByIDs(ctx, columnIDs) + if err != nil { + ctx.NotFoundOrServerError("GetColumnsByIDs", issues_model.IsErrIssueNotExist, err) + return + } + + if len(movedColumns) != len(form.Columns) { + ctx.ServerError("some columns do not exist", errors.New("some columns do not exist")) + return + } + + for _, column := range movedColumns { + if column.ProjectID != project.ID { + ctx.ServerError("Some column's projectID is not equal to project's ID", errors.New("Some column's projectID is not equal to project's ID")) + return + } + } + + if err = project_model.MoveColumnsOnProject(ctx, project, sortedColumnIDs); err != nil { + ctx.ServerError("MoveColumnsOnProject", err) + return + } + + ctx.JSONOK() +} diff --git a/routers/web/web.go b/routers/web/web.go index c6132f0d61b95..3aa1b8aed0842 100644 --- a/routers/web/web.go +++ b/routers/web/web.go @@ -999,6 +999,7 @@ func registerRoutes(m *web.Route) { m.Post("/new", web.Bind(forms.CreateProjectForm{}), org.NewProjectPost) m.Group("/{id}", func() { m.Post("", web.Bind(forms.EditProjectBoardForm{}), org.AddBoardToProjectPost) + m.Post("/move", org.MoveColumns) m.Post("/delete", org.DeleteProject) m.Get("/edit", org.RenderEditProject) diff --git a/templates/projects/view.tmpl b/templates/projects/view.tmpl index 3e000660e2859..47f214a44e0d4 100644 --- a/templates/projects/view.tmpl +++ b/templates/projects/view.tmpl @@ -64,7 +64,7 @@
-
+
{{range .Columns}}
diff --git a/web_src/js/features/repo-projects.js b/web_src/js/features/repo-projects.js index a869c24c823ad..0ea90bcebdd4d 100644 --- a/web_src/js/features/repo-projects.js +++ b/web_src/js/features/repo-projects.js @@ -63,17 +63,20 @@ async function initRepoProjectSortable() { delay: 500, onSort: async () => { boardColumns = mainBoard.getElementsByClassName('project-column'); - for (let i = 0; i < boardColumns.length; i++) { - const column = boardColumns[i]; - if (parseInt(column.getAttribute('data-sorting')) !== i) { - try { - const bgColor = column.style.backgroundColor; // will be rgb() string - const color = bgColor ? tinycolor(bgColor).toHexString() : ''; - await PUT(column.getAttribute('data-url'), {data: {sorting: i, color}}); - } catch (error) { - console.error(error); - } - } + + const columnSorting = { + columns: Array.from(boardColumns, (column, i) => ({ + columnID: parseInt(column.getAttribute('data-id')), + sorting: i, + })), + }; + + try { + await POST(`${mainBoard.getAttribute('data-url')}`, { + data: columnSorting, + }); + } catch (error) { + console.error(error); } }, }); From 50a573f75387d5d3bc59efd0809ee1c532c90bae Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Thu, 25 Apr 2024 11:53:46 +0800 Subject: [PATCH 02/49] Fix lint --- web_src/js/features/repo-projects.js | 1 - 1 file changed, 1 deletion(-) diff --git a/web_src/js/features/repo-projects.js b/web_src/js/features/repo-projects.js index 0ea90bcebdd4d..a857e94015e00 100644 --- a/web_src/js/features/repo-projects.js +++ b/web_src/js/features/repo-projects.js @@ -2,7 +2,6 @@ import $ from 'jquery'; import {contrastColor} from '../utils/color.js'; import {createSortable} from '../modules/sortable.js'; import {POST, DELETE, PUT} from '../modules/fetch.js'; -import tinycolor from 'tinycolor2'; function updateIssueCount(cards) { const parent = cards.parentElement; From 753608a6cf1edfb3b9c4798af241976545283d68 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Thu, 25 Apr 2024 12:01:07 +0800 Subject: [PATCH 03/49] Use star as defult column's icon but not a pin and add a star icon on title of column --- templates/projects/view.tmpl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/templates/projects/view.tmpl b/templates/projects/view.tmpl index 47f214a44e0d4..8e4f0e794bed2 100644 --- a/templates/projects/view.tmpl +++ b/templates/projects/view.tmpl @@ -72,7 +72,7 @@
{{.NumIssues ctx}}
- {{.Title}} + {{.Title}}{{if .Default}}{{svg "octicon-star"}}{{end}}
{{if $canWriteProject}} {{if $canWriteProject}} {{if $canWriteProject}}