diff --git a/routers/api/v1/api.go b/routers/api/v1/api.go index 2edd859b5a..8d3c19a033 100644 --- a/routers/api/v1/api.go +++ b/routers/api/v1/api.go @@ -1563,6 +1563,7 @@ func Routes() *web.Route { m.Combo("/boards"). Get(projects.ListProjectBoards). Post(bind(api.NewProjectBoardPayload{}), projects.CreateProjectBoard) + m.Get("/boards/{boardId}/cards", projects.ListProjectBoardCards) }) m.Group("/boards", func() { diff --git a/routers/api/v1/projects/boards.go b/routers/api/v1/projects/boards.go index c9f47641e6..afbdfb3fc2 100644 --- a/routers/api/v1/projects/boards.go +++ b/routers/api/v1/projects/boards.go @@ -6,6 +6,7 @@ package projects import ( "net/http" + issues_model "code.gitea.io/gitea/models/issues" project_model "code.gitea.io/gitea/models/project" "code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/setting" @@ -69,6 +70,80 @@ func ListProjectBoards(ctx *context.APIContext) { } +// ProjectBoardCard represents an issue card on a project board. +type ProjectBoardCard struct { + ID int64 `json:"id"` + Issue *api.Issue `json:"issue,omitempty"` +} + +func ListProjectBoardCards(ctx *context.APIContext) { + // swagger:operation GET /projects/{projectId}/boards/{boardId}/cards board boardGetProjectBoardCards + // --- + // summary: Get project board cards + // produces: + // - application/json + // parameters: + // - name: projectId + // in: path + // description: id of the project + // type: string + // required: true + // - name: boardId + // in: path + // description: id of the board + // type: string + // required: true + // responses: + // "200": + // "description": "Project board cards" + // "403": + // "$ref": "#/responses/forbidden" + // "404": + // "$ref": "#/responses/notFound" + projectID := ctx.ParamsInt64(":projectId") + project, err := project_model.GetProjectByID(ctx, projectID) + if err != nil { + ctx.Error(http.StatusNotFound, "ListProjectBoardCards", err) + return + } + + boardID := ctx.ParamsInt64(":boardId") + var board *project_model.Board + if boardID == 0 { + board = &project_model.Board{ + ID: 0, + ProjectID: project.ID, + Default: true, + Title: "Uncategorized", + } + } else { + board, err = project_model.GetBoard(ctx, boardID) + if err != nil { + ctx.Error(http.StatusNotFound, "GetProjectBoard", err) + return + } + if board.ProjectID != project.ID { + ctx.NotFound("BoardNotInProject", nil) + return + } + } + + issues, err := issues_model.LoadIssuesFromBoard(ctx, board) + if err != nil { + ctx.InternalServerError(err) + return + } + + cards := make([]*ProjectBoardCard, 0, len(issues)) + for _, issue := range issues { + cards = append(cards, &ProjectBoardCard{ + ID: issue.ID, + Issue: convert.ToAPIIssue(ctx, issue), + }) + } + ctx.JSON(http.StatusOK, cards) +} + func CreateProjectBoard(ctx *context.APIContext) { // swagger:operation POST /projects/{projectId}/boards board boardCreateProjectBoard // --- diff --git a/services/convert/project.go b/services/convert/project.go index 506202f073..1a7e5213a1 100644 --- a/services/convert/project.go +++ b/services/convert/project.go @@ -36,6 +36,7 @@ func ToApiProjectBoardList( func ToAPIProject(ctx context.Context, project *project_model.Project) *api.Project { apiProject := &api.Project{ + ID: project.ID, Title: project.Title, Description: project.Description, BoardType: uint8(project.BoardType),