aboutsummaryrefslogtreecommitdiffstats
path: root/routers
diff options
context:
space:
mode:
authorLunny Xiao <xiaolunwen@gmail.com>2024-05-08 21:44:57 +0800
committerGitHub <noreply@github.com>2024-05-08 13:44:57 +0000
commita303c973e0264dab45a787c4afa200e183e0d953 (patch)
tree4151f630fda10cdfc6a6c208229ca0ebe90cd8a4 /routers
parentf5f921c09555f5b31226fc31bbbb463649d0bfdc (diff)
downloadgitea-a303c973e0264dab45a787c4afa200e183e0d953.tar.gz
gitea-a303c973e0264dab45a787c4afa200e183e0d953.zip
Fix various problems around projects board view (#30696)
# The problem The previous implementation will start multiple POST requests from the frontend when moving a column and another bug is moving the default column will never be remembered in fact. # What's changed - [x] This PR will allow the default column to move to a non-first position - [x] And it also uses one request instead of multiple requests when moving the columns - [x] Use a star instead of a pin as the icon for setting the default column action - [x] Inserted new column will be append to the end - [x] Fix #30701 the newly added issue will be append to the end of the default column - [x] Fix when deleting a column, all issues in it will be displayed from UI but database records exist. - [x] Add a limitation for columns in a project to 20. So the sorting will not be overflow because it's int8. --------- Co-authored-by: silverwind <me@silverwind.io> Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
Diffstat (limited to 'routers')
-rw-r--r--routers/web/org/projects.go69
-rw-r--r--routers/web/repo/projects.go17
-rw-r--r--routers/web/repo/pull.go14
-rw-r--r--routers/web/shared/project/column.go48
-rw-r--r--routers/web/web.go3
5 files changed, 68 insertions, 83 deletions
diff --git a/routers/web/org/projects.go b/routers/web/org/projects.go
index 7f78d1c830..50effbe963 100644
--- a/routers/web/org/projects.go
+++ b/routers/web/org/projects.go
@@ -7,7 +7,6 @@ import (
"errors"
"fmt"
"net/http"
- "strconv"
"strings"
"code.gitea.io/gitea/models/db"
@@ -390,74 +389,6 @@ func ViewProject(ctx *context.Context) {
ctx.HTML(http.StatusOK, tplProjectsView)
}
-func getActionIssues(ctx *context.Context) issues_model.IssueList {
- commaSeparatedIssueIDs := ctx.FormString("issue_ids")
- if len(commaSeparatedIssueIDs) == 0 {
- return nil
- }
- issueIDs := make([]int64, 0, 10)
- for _, stringIssueID := range strings.Split(commaSeparatedIssueIDs, ",") {
- issueID, err := strconv.ParseInt(stringIssueID, 10, 64)
- if err != nil {
- ctx.ServerError("ParseInt", err)
- return nil
- }
- issueIDs = append(issueIDs, issueID)
- }
- issues, err := issues_model.GetIssuesByIDs(ctx, issueIDs)
- if err != nil {
- ctx.ServerError("GetIssuesByIDs", err)
- return nil
- }
- // Check access rights for all issues
- issueUnitEnabled := ctx.Repo.CanRead(unit.TypeIssues)
- prUnitEnabled := ctx.Repo.CanRead(unit.TypePullRequests)
- for _, issue := range issues {
- if issue.RepoID != ctx.Repo.Repository.ID {
- ctx.NotFound("some issue's RepoID is incorrect", errors.New("some issue's RepoID is incorrect"))
- return nil
- }
- if issue.IsPull && !prUnitEnabled || !issue.IsPull && !issueUnitEnabled {
- ctx.NotFound("IssueOrPullRequestUnitNotAllowed", nil)
- return nil
- }
- if err = issue.LoadAttributes(ctx); err != nil {
- ctx.ServerError("LoadAttributes", err)
- return nil
- }
- }
- return issues
-}
-
-// UpdateIssueProject change an issue's project
-func UpdateIssueProject(ctx *context.Context) {
- issues := getActionIssues(ctx)
- if ctx.Written() {
- return
- }
-
- if err := issues.LoadProjects(ctx); err != nil {
- ctx.ServerError("LoadProjects", err)
- return
- }
-
- projectID := ctx.FormInt64("id")
- for _, issue := range issues {
- if issue.Project != nil {
- if issue.Project.ID == projectID {
- continue
- }
- }
-
- if err := issues_model.ChangeProjectAssign(ctx, issue, ctx.Doer, projectID); err != nil {
- ctx.ServerError("ChangeProjectAssign", err)
- return
- }
- }
-
- ctx.JSONOK()
-}
-
// DeleteProjectBoard allows for the deletion of a project board
func DeleteProjectBoard(ctx *context.Context) {
if ctx.Doer == nil {
diff --git a/routers/web/repo/projects.go b/routers/web/repo/projects.go
index 9b765e89e8..6186ee150c 100644
--- a/routers/web/repo/projects.go
+++ b/routers/web/repo/projects.go
@@ -21,6 +21,7 @@ import (
"code.gitea.io/gitea/modules/markup/markdown"
"code.gitea.io/gitea/modules/optional"
"code.gitea.io/gitea/modules/setting"
+ "code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/modules/web"
"code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/forms"
@@ -383,17 +384,21 @@ func UpdateIssueProject(ctx *context.Context) {
ctx.ServerError("LoadProjects", err)
return
}
+ if _, err := issues.LoadRepositories(ctx); err != nil {
+ ctx.ServerError("LoadProjects", err)
+ return
+ }
projectID := ctx.FormInt64("id")
for _, issue := range issues {
- if issue.Project != nil {
- if issue.Project.ID == projectID {
+ if issue.Project != nil && issue.Project.ID == projectID {
+ continue
+ }
+ if err := issues_model.IssueAssignOrRemoveProject(ctx, issue, ctx.Doer, projectID, 0); err != nil {
+ if errors.Is(err, util.ErrPermissionDenied) {
continue
}
- }
-
- if err := issues_model.ChangeProjectAssign(ctx, issue, ctx.Doer, projectID); err != nil {
- ctx.ServerError("ChangeProjectAssign", err)
+ ctx.ServerError("IssueAssignOrRemoveProject", err)
return
}
}
diff --git a/routers/web/repo/pull.go b/routers/web/repo/pull.go
index 7f131f2e98..7041175d9a 100644
--- a/routers/web/repo/pull.go
+++ b/routers/web/repo/pull.go
@@ -1329,14 +1329,12 @@ func CompareAndPullRequestPost(ctx *context.Context) {
return
}
- if projectID > 0 {
- if !ctx.Repo.CanWrite(unit.TypeProjects) {
- ctx.Error(http.StatusBadRequest, "user hasn't the permission to write to projects")
- return
- }
- if err := issues_model.ChangeProjectAssign(ctx, pullIssue, ctx.Doer, projectID); err != nil {
- ctx.ServerError("ChangeProjectAssign", err)
- return
+ if projectID > 0 && ctx.Repo.CanWrite(unit.TypeProjects) {
+ if err := issues_model.IssueAssignOrRemoveProject(ctx, pullIssue, ctx.Doer, projectID, 0); err != nil {
+ if !errors.Is(err, util.ErrPermissionDenied) {
+ ctx.ServerError("IssueAssignOrRemoveProject", err)
+ return
+ }
}
}
diff --git a/routers/web/shared/project/column.go b/routers/web/shared/project/column.go
new file mode 100644
index 0000000000..599842ea9e
--- /dev/null
+++ b/routers/web/shared/project/column.go
@@ -0,0 +1,48 @@
+// Copyright 2024 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package project
+
+import (
+ project_model "code.gitea.io/gitea/models/project"
+ "code.gitea.io/gitea/modules/json"
+ "code.gitea.io/gitea/services/context"
+)
+
+// MoveColumns moves or keeps columns in a project and sorts them inside that project
+func MoveColumns(ctx *context.Context) {
+ project, err := project_model.GetProjectByID(ctx, ctx.ParamsInt64(":id"))
+ if err != nil {
+ ctx.NotFoundOrServerError("GetProjectByID", project_model.IsErrProjectNotExist, err)
+ return
+ }
+ if !project.CanBeAccessedByOwnerRepo(ctx.ContextUser.ID, ctx.Repo.Repository) {
+ ctx.NotFound("CanBeAccessedByOwnerRepo", 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)
+ return
+ }
+
+ sortedColumnIDs := make(map[int64]int64)
+ for _, column := range form.Columns {
+ sortedColumnIDs[column.Sorting] = column.ColumnID
+ }
+
+ 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 91ab378d97..e1482c1e4a 100644
--- a/routers/web/web.go
+++ b/routers/web/web.go
@@ -37,6 +37,7 @@ import (
"code.gitea.io/gitea/routers/web/repo"
"code.gitea.io/gitea/routers/web/repo/actions"
repo_setting "code.gitea.io/gitea/routers/web/repo/setting"
+ "code.gitea.io/gitea/routers/web/shared/project"
"code.gitea.io/gitea/routers/web/user"
user_setting "code.gitea.io/gitea/routers/web/user/setting"
"code.gitea.io/gitea/routers/web/user/setting/security"
@@ -999,6 +1000,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", project.MoveColumns)
m.Post("/delete", org.DeleteProject)
m.Get("/edit", org.RenderEditProject)
@@ -1354,6 +1356,7 @@ func registerRoutes(m *web.Route) {
m.Post("/new", web.Bind(forms.CreateProjectForm{}), repo.NewProjectPost)
m.Group("/{id}", func() {
m.Post("", web.Bind(forms.EditProjectBoardForm{}), repo.AddBoardToProjectPost)
+ m.Post("/move", project.MoveColumns)
m.Post("/delete", repo.DeleteProject)
m.Get("/edit", repo.RenderEditProject)