mirror of
https://github.com/go-gitea/gitea.git
synced 2026-09-08 22:13:26 +09:00
feat(api): add project APIs (#38691)
Adds REST APIs for project boards for repo, org and user scopes, using as much shared code as possible for all 3 scopes. Fixes: https://github.com/go-gitea/gitea/issues/14299 Fixes: https://github.com/go-gitea/gitea/issues/31769 Fixes: https://github.com/go-gitea/gitea/issues/35921 Replaces: https://github.com/go-gitea/gitea/pull/37518 Replaces: https://github.com/go-gitea/gitea/pull/36008 Replaces: https://github.com/go-gitea/gitea/pull/28111 Replaces: https://github.com/go-gitea/gitea/pull/31768 Signed-off-by: silverwind <me@silverwind.io> Co-authored-by: Supen.Huang <supen.huang@qq.com> Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: Ember <ember@mubergacres.com> Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com> Co-authored-by: wxiaoguang <wxiaoguang@gmail.com> Co-authored-by: beardev-in <abhinav.edulakanti@gmail.com>
This commit is contained in:
co-authored by
Supen.Huang
Claude
Ember
Lunny Xiao
wxiaoguang
beardev-in
parent
8163139ec0
commit
7fae3d5db3
+2
-190
@@ -4,7 +4,6 @@
|
||||
package org
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strings"
|
||||
@@ -14,7 +13,6 @@ import (
|
||||
project_model "gitea.dev/models/project"
|
||||
repo_model "gitea.dev/models/repo"
|
||||
"gitea.dev/models/unit"
|
||||
"gitea.dev/modules/json"
|
||||
"gitea.dev/modules/optional"
|
||||
"gitea.dev/modules/setting"
|
||||
"gitea.dev/modules/templates"
|
||||
@@ -309,9 +307,9 @@ func ViewProject(ctx *context.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
columns, err := project.GetColumns(ctx)
|
||||
columns, err := project_model.GetColumns(ctx, project.ID, db.ListOptionsAll)
|
||||
if err != nil {
|
||||
ctx.ServerError("GetProjectColumns", err)
|
||||
ctx.ServerError("GetColumns", err)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -474,189 +472,3 @@ func ViewProject(ctx *context.Context) {
|
||||
|
||||
ctx.HTML(http.StatusOK, tplProjectsView)
|
||||
}
|
||||
|
||||
// DeleteProjectColumn allows for the deletion of a project column
|
||||
func DeleteProjectColumn(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.GetProjectByIDAndOwner(ctx, ctx.PathParamInt64("id"), ctx.ContextUser.ID)
|
||||
if err != nil {
|
||||
ctx.NotFoundOrServerError("GetProjectByID", project_model.IsErrProjectNotExist, err)
|
||||
return
|
||||
}
|
||||
|
||||
_, err = project_model.GetColumnByIDAndProjectID(ctx, ctx.PathParamInt64("columnID"), project.ID)
|
||||
if err != nil {
|
||||
ctx.NotFoundOrServerError("GetColumnByIDAndProjectID", project_model.IsErrProjectColumnNotExist, err)
|
||||
return
|
||||
}
|
||||
|
||||
if err := project_model.DeleteColumnByID(ctx, ctx.PathParamInt64("columnID")); err != nil {
|
||||
ctx.ServerError("DeleteProjectColumnByID", err)
|
||||
return
|
||||
}
|
||||
|
||||
ctx.JSONOK()
|
||||
}
|
||||
|
||||
// AddColumnToProjectPost allows a new column to be added to a project.
|
||||
func AddColumnToProjectPost(ctx *context.Context) {
|
||||
form := web.GetForm(ctx).(*forms.EditProjectColumnForm)
|
||||
|
||||
project, err := project_model.GetProjectByIDAndOwner(ctx, ctx.PathParamInt64("id"), ctx.ContextUser.ID)
|
||||
if err != nil {
|
||||
ctx.NotFoundOrServerError("GetProjectByID", project_model.IsErrProjectNotExist, err)
|
||||
return
|
||||
}
|
||||
|
||||
if err := project_model.NewColumn(ctx, &project_model.Column{
|
||||
ProjectID: project.ID,
|
||||
Title: form.Title,
|
||||
Color: form.Color,
|
||||
CreatorID: ctx.Doer.ID,
|
||||
}); err != nil {
|
||||
ctx.ServerError("NewProjectColumn", err)
|
||||
return
|
||||
}
|
||||
|
||||
ctx.JSONOK()
|
||||
}
|
||||
|
||||
// CheckProjectColumnChangePermissions check permission
|
||||
func CheckProjectColumnChangePermissions(ctx *context.Context) (*project_model.Project, *project_model.Column) {
|
||||
if ctx.Doer == nil {
|
||||
ctx.JSON(http.StatusForbidden, map[string]string{
|
||||
"message": "Only signed in users are allowed to perform this action.",
|
||||
})
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
project, err := project_model.GetProjectByIDAndOwner(ctx, ctx.PathParamInt64("id"), ctx.ContextUser.ID)
|
||||
if err != nil {
|
||||
ctx.NotFoundOrServerError("GetProjectByID", project_model.IsErrProjectNotExist, err)
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
column, err := project_model.GetColumnByIDAndProjectID(ctx, ctx.PathParamInt64("columnID"), project.ID)
|
||||
if err != nil {
|
||||
ctx.NotFoundOrServerError("GetColumnByIDAndProjectID", project_model.IsErrProjectColumnNotExist, err)
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
return project, column
|
||||
}
|
||||
|
||||
// EditProjectColumn allows a project column's to be updated
|
||||
func EditProjectColumn(ctx *context.Context) {
|
||||
form := web.GetForm(ctx).(*forms.EditProjectColumnForm)
|
||||
_, column := CheckProjectColumnChangePermissions(ctx)
|
||||
if ctx.Written() {
|
||||
return
|
||||
}
|
||||
|
||||
if form.Title != "" {
|
||||
column.Title = form.Title
|
||||
}
|
||||
column.Color = form.Color
|
||||
if form.Sorting != 0 {
|
||||
column.Sorting = form.Sorting
|
||||
}
|
||||
|
||||
if err := project_model.UpdateColumn(ctx, column); err != nil {
|
||||
ctx.ServerError("UpdateProjectColumn", err)
|
||||
return
|
||||
}
|
||||
|
||||
ctx.JSONOK()
|
||||
}
|
||||
|
||||
// SetDefaultProjectColumn set default column for uncategorized issues/pulls
|
||||
func SetDefaultProjectColumn(ctx *context.Context) {
|
||||
project, column := CheckProjectColumnChangePermissions(ctx)
|
||||
if ctx.Written() {
|
||||
return
|
||||
}
|
||||
|
||||
if err := project_model.SetDefaultColumn(ctx, project.ID, column.ID); err != nil {
|
||||
ctx.ServerError("SetDefaultColumn", 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 {
|
||||
ctx.JSON(http.StatusForbidden, map[string]string{
|
||||
"message": "Only signed in users are allowed to perform this action.",
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
project, err := project_model.GetProjectByIDAndOwner(ctx, ctx.PathParamInt64("id"), ctx.ContextUser.ID)
|
||||
if err != nil {
|
||||
ctx.NotFoundOrServerError("GetProjectByID", project_model.IsErrProjectNotExist, err)
|
||||
return
|
||||
}
|
||||
|
||||
column, err := project_model.GetColumnByIDAndProjectID(ctx, ctx.PathParamInt64("columnID"), project.ID)
|
||||
if err != nil {
|
||||
ctx.NotFoundOrServerError("GetColumnByIDAndProjectID", project_model.IsErrProjectColumnNotExist, err)
|
||||
return
|
||||
}
|
||||
|
||||
type movedIssuesForm struct {
|
||||
Issues []struct {
|
||||
IssueID int64 `json:"issueID"`
|
||||
Sorting int64 `json:"sorting"`
|
||||
} `json:"issues"`
|
||||
}
|
||||
|
||||
form := &movedIssuesForm{}
|
||||
if err = json.NewDecoder(ctx.Req.Body).Decode(&form); err != nil {
|
||||
ctx.ServerError("DecodeMovedIssuesForm", err)
|
||||
return
|
||||
}
|
||||
|
||||
issueIDs := make([]int64, 0, len(form.Issues))
|
||||
sortedIssueIDs := make(map[int64]int64)
|
||||
for _, issue := range form.Issues {
|
||||
issueIDs = append(issueIDs, issue.IssueID)
|
||||
sortedIssueIDs[issue.Sorting] = issue.IssueID
|
||||
}
|
||||
movedIssues, err := issues_model.GetIssuesByIDs(ctx, issueIDs)
|
||||
if err != nil {
|
||||
ctx.NotFoundOrServerError("GetIssueByID", issues_model.IsErrIssueNotExist, err)
|
||||
return
|
||||
}
|
||||
|
||||
if len(movedIssues) != len(form.Issues) {
|
||||
ctx.ServerError("some issues do not exist", errors.New("some issues do not exist"))
|
||||
return
|
||||
}
|
||||
|
||||
if _, err = movedIssues.LoadRepositories(ctx); err != nil {
|
||||
ctx.ServerError("LoadRepositories", err)
|
||||
return
|
||||
}
|
||||
|
||||
for _, issue := range movedIssues {
|
||||
if issue.RepoID != project.RepoID && issue.Repo.OwnerID != project.OwnerID {
|
||||
ctx.ServerError("Some issue's repoID is not equal to project's repoID", errors.New("Some issue's repoID is not equal to project's repoID"))
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if err = project_service.MoveIssuesOnProjectColumn(ctx, ctx.Doer, column, sortedIssueIDs); err != nil {
|
||||
ctx.ServerError("MoveIssuesOnProjectColumn", err)
|
||||
return
|
||||
}
|
||||
|
||||
ctx.JSONOK()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user