diff --git a/models/fixtures/milestone.yml b/models/fixtures/milestone.yml index 8192c4fbe..15f422fc3 100644 --- a/models/fixtures/milestone.yml +++ b/models/fixtures/milestone.yml @@ -13,3 +13,11 @@ content: content2 is_closed: false num_issues: 0 + +- + id: 3 + repo_id: 1 + name: milestone3 + content: content3 + is_closed: true + num_issues: 0 diff --git a/models/fixtures/repository.yml b/models/fixtures/repository.yml index 083182e2b..609f421a9 100644 --- a/models/fixtures/repository.yml +++ b/models/fixtures/repository.yml @@ -8,7 +8,8 @@ num_closed_issues: 1 num_pulls: 2 num_closed_pulls: 0 - num_milestones: 2 + num_milestones: 3 + num_closed_milestones: 1 num_watches: 3 - @@ -495,4 +496,4 @@ num_stars: 0 num_forks: 0 num_issues: 0 - is_mirror: false \ No newline at end of file + is_mirror: false diff --git a/models/issue_milestone.go b/models/issue_milestone.go index 3bde4b558..f279dda19 100644 --- a/models/issue_milestone.go +++ b/models/issue_milestone.go @@ -190,10 +190,26 @@ func (milestones MilestoneList) getMilestoneIDs() []int64 { } // GetMilestonesByRepoID returns all opened milestones of a repository. -func GetMilestonesByRepoID(repoID int64) (MilestoneList, error) { +func GetMilestonesByRepoID(repoID int64, state api.StateType) (MilestoneList, error) { + + sess := x.Where("repo_id = ?", repoID) + + switch state { + case api.StateClosed: + sess = sess.And("is_closed = ?", true) + + case api.StateAll: + break + + case api.StateOpen: + fallthrough + + default: + sess = sess.And("is_closed = ?", false) + } + miles := make([]*Milestone, 0, 10) - return miles, x.Where("repo_id = ? AND is_closed = ?", repoID, false). - Asc("deadline_unix").Asc("id").Find(&miles) + return miles, sess.Asc("deadline_unix").Asc("id").Find(&miles) } // GetMilestones returns a list of milestones of given repository and status. diff --git a/models/issue_milestone_test.go b/models/issue_milestone_test.go index fb1ee8b7a..f9e51aff3 100644 --- a/models/issue_milestone_test.go +++ b/models/issue_milestone_test.go @@ -69,20 +69,43 @@ func TestGetMilestoneByRepoID(t *testing.T) { func TestGetMilestonesByRepoID(t *testing.T) { assert.NoError(t, PrepareTestDatabase()) - test := func(repoID int64) { + test := func(repoID int64, state api.StateType) { repo := AssertExistsAndLoadBean(t, &Repository{ID: repoID}).(*Repository) - milestones, err := GetMilestonesByRepoID(repo.ID) + milestones, err := GetMilestonesByRepoID(repo.ID, state) assert.NoError(t, err) - assert.Len(t, milestones, repo.NumMilestones) + + var n int + + switch state { + case api.StateClosed: + n = repo.NumClosedMilestones + + case api.StateAll: + n = repo.NumMilestones + + case api.StateOpen: + fallthrough + + default: + n = repo.NumOpenMilestones + } + + assert.Len(t, milestones, n) for _, milestone := range milestones { assert.EqualValues(t, repoID, milestone.RepoID) } } - test(1) - test(2) - test(3) - - milestones, err := GetMilestonesByRepoID(NonexistentID) + test(1, api.StateOpen) + test(1, api.StateAll) + test(1, api.StateClosed) + test(2, api.StateOpen) + test(2, api.StateAll) + test(2, api.StateClosed) + test(3, api.StateOpen) + test(3, api.StateClosed) + test(3, api.StateAll) + + milestones, err := GetMilestonesByRepoID(NonexistentID, api.StateOpen) assert.NoError(t, err) assert.Len(t, milestones, 0) } diff --git a/modules/structs/issue.go b/modules/structs/issue.go index af6aa6e54..6d7517bdc 100644 --- a/modules/structs/issue.go +++ b/modules/structs/issue.go @@ -16,6 +16,8 @@ const ( StateOpen StateType = "open" // StateClosed pr is closed StateClosed StateType = "closed" + // StateAll is all + StateAll StateType = "all" ) // PullRequestMeta PR info if an issue is a PR diff --git a/routers/api/v1/repo/milestone.go b/routers/api/v1/repo/milestone.go index 1d0109330..14030a218 100644 --- a/routers/api/v1/repo/milestone.go +++ b/routers/api/v1/repo/milestone.go @@ -14,7 +14,7 @@ import ( api "code.gitea.io/gitea/modules/structs" ) -// ListMilestones list all the opened milestones for a repository +// ListMilestones list milestones for a repository func ListMilestones(ctx *context.APIContext) { // swagger:operation GET /repos/{owner}/{repo}/milestones issue issueGetMilestonesList // --- @@ -32,10 +32,14 @@ func ListMilestones(ctx *context.APIContext) { // description: name of the repo // type: string // required: true + // - name: state + // in: query + // description: Milestone state, Recognised values are open, closed and all. Defaults to "open" + // type: string // responses: // "200": // "$ref": "#/responses/MilestoneList" - milestones, err := models.GetMilestonesByRepoID(ctx.Repo.Repository.ID) + milestones, err := models.GetMilestonesByRepoID(ctx.Repo.Repository.ID, api.StateType(ctx.Query("state"))) if err != nil { ctx.Error(500, "GetMilestonesByRepoID", err) return diff --git a/routers/repo/issue.go b/routers/repo/issue.go index c2749fcb4..f6030c982 100644 --- a/routers/repo/issue.go +++ b/routers/repo/issue.go @@ -24,6 +24,7 @@ import ( "code.gitea.io/gitea/modules/markup/markdown" "code.gitea.io/gitea/modules/notification" "code.gitea.io/gitea/modules/setting" + api "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/util" "github.com/Unknwon/com" @@ -305,7 +306,7 @@ func Issues(ctx *context.Context) { var err error // Get milestones. - ctx.Data["Milestones"], err = models.GetMilestonesByRepoID(ctx.Repo.Repository.ID) + ctx.Data["Milestones"], err = models.GetMilestonesByRepoID(ctx.Repo.Repository.ID, api.StateType(ctx.Query("state"))) if err != nil { ctx.ServerError("GetAllRepoMilestones", err) return diff --git a/templates/swagger/v1_json.tmpl b/templates/swagger/v1_json.tmpl index 77515bb13..0bd85fbb6 100644 --- a/templates/swagger/v1_json.tmpl +++ b/templates/swagger/v1_json.tmpl @@ -3892,6 +3892,12 @@ "name": "repo", "in": "path", "required": true + }, + { + "type": "string", + "description": "Milestone state, Recognised values are open, closed and all. Defaults to \"open\"", + "name": "state", + "in": "query" } ], "responses": {