Skip to content

Commit 7d6d4f9

Browse files
GustedEarl Warren
authored andcommitted
feat(api): add sort parameter to list issues API (go-gitea#7211)
- Add the `sort` parameter to the `/api/v1/{repo}/{owner}/issues` API endpoint. Default behavior is preserved. - Resolves forgejo/forgejo#4173 - Add (non-exhaustive) integration testing. Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/7211 Reviewed-by: Otto <[email protected]> Co-authored-by: Gusted <[email protected]> Co-committed-by: Gusted <[email protected]>
1 parent a624b6a commit 7d6d4f9

File tree

4 files changed

+97
-1
lines changed

4 files changed

+97
-1
lines changed

modules/indexer/issues/indexer.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"fmt"
99
"os"
1010
"runtime/pprof"
11+
"strings"
1112
"sync/atomic"
1213
"time"
1314

@@ -280,6 +281,33 @@ const (
280281
SortByDeadlineAsc = internal.SortByDeadlineAsc
281282
)
282283

284+
// ParseSortBy parses the `sortBy` string and returns the associated `SortBy`
285+
// value, if one exists. Otherwise return `defaultSortBy`.
286+
func ParseSortBy(sortBy string, defaultSortBy internal.SortBy) internal.SortBy {
287+
switch strings.ToLower(sortBy) {
288+
case "relevance":
289+
return SortByScore
290+
case "latest":
291+
return SortByCreatedDesc
292+
case "oldest":
293+
return SortByCreatedAsc
294+
case "recentupdate":
295+
return SortByUpdatedDesc
296+
case "leastupdate":
297+
return SortByUpdatedAsc
298+
case "mostcomment":
299+
return SortByCommentsDesc
300+
case "leastcomment":
301+
return SortByCommentsAsc
302+
case "nearduedate":
303+
return SortByDeadlineAsc
304+
case "farduedate":
305+
return SortByDeadlineDesc
306+
default:
307+
return defaultSortBy
308+
}
309+
}
310+
283311
// SearchIssues search issues by options.
284312
func SearchIssues(ctx context.Context, opts *SearchOptions) ([]int64, int64, error) {
285313
indexer := *globalIndexer.Load()

routers/api/v1/repo/issue.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -397,6 +397,12 @@ func ListIssues(ctx *context.APIContext) {
397397
// in: query
398398
// description: page size of results
399399
// type: integer
400+
// - name: sort
401+
// in: query
402+
// description: Type of sort
403+
// type: string
404+
// enum: [relevance, latest, oldest, recentupdate, leastupdate, mostcomment, leastcomment, nearduedate, farduedate]
405+
// default: latest
400406
// responses:
401407
// "200":
402408
// "$ref": "#/responses/IssueList"
@@ -510,7 +516,7 @@ func ListIssues(ctx *context.APIContext) {
510516
RepoIDs: []int64{ctx.Repo.Repository.ID},
511517
IsPull: isPull,
512518
IsClosed: isClosed,
513-
SortBy: issue_indexer.SortByCreatedDesc,
519+
SortBy: issue_indexer.ParseSortBy(ctx.FormString("sort"), issue_indexer.SortByCreatedDesc),
514520
}
515521
if since != 0 {
516522
searchOpt.UpdatedAfterUnix = optional.Some(since)

templates/swagger/v1_json.tmpl

Lines changed: 18 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tests/integration/api_issue_test.go

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,50 @@ func TestAPIListIssues(t *testing.T) {
7474
if assert.Len(t, apiIssues, 1) {
7575
assert.EqualValues(t, 1, apiIssues[0].ID)
7676
}
77+
78+
t.Run("Sort", func(t *testing.T) {
79+
defer tests.PrintCurrentTest(t)()
80+
81+
link.RawQuery = url.Values{"token": {token}, "sort": {"oldest"}}.Encode()
82+
resp = MakeRequest(t, NewRequest(t, "GET", link.String()), http.StatusOK)
83+
DecodeJSON(t, resp, &apiIssues)
84+
if assert.Len(t, apiIssues, 4) {
85+
assert.EqualValues(t, 1, apiIssues[0].ID)
86+
assert.EqualValues(t, 2, apiIssues[1].ID)
87+
assert.EqualValues(t, 3, apiIssues[2].ID)
88+
assert.EqualValues(t, 11, apiIssues[3].ID)
89+
}
90+
91+
link.RawQuery = url.Values{"token": {token}, "sort": {"newest"}}.Encode()
92+
resp = MakeRequest(t, NewRequest(t, "GET", link.String()), http.StatusOK)
93+
DecodeJSON(t, resp, &apiIssues)
94+
if assert.Len(t, apiIssues, 4) {
95+
assert.EqualValues(t, 11, apiIssues[0].ID)
96+
assert.EqualValues(t, 3, apiIssues[1].ID)
97+
assert.EqualValues(t, 2, apiIssues[2].ID)
98+
assert.EqualValues(t, 1, apiIssues[3].ID)
99+
}
100+
101+
link.RawQuery = url.Values{"token": {token}, "sort": {"recentupdate"}}.Encode()
102+
resp = MakeRequest(t, NewRequest(t, "GET", link.String()), http.StatusOK)
103+
DecodeJSON(t, resp, &apiIssues)
104+
if assert.Len(t, apiIssues, 4) {
105+
assert.EqualValues(t, 11, apiIssues[0].ID)
106+
assert.EqualValues(t, 1, apiIssues[1].ID)
107+
assert.EqualValues(t, 2, apiIssues[2].ID)
108+
assert.EqualValues(t, 3, apiIssues[3].ID)
109+
}
110+
111+
link.RawQuery = url.Values{"token": {token}, "sort": {"leastupdate"}}.Encode()
112+
resp = MakeRequest(t, NewRequest(t, "GET", link.String()), http.StatusOK)
113+
DecodeJSON(t, resp, &apiIssues)
114+
if assert.Len(t, apiIssues, 4) {
115+
assert.EqualValues(t, 3, apiIssues[0].ID)
116+
assert.EqualValues(t, 2, apiIssues[1].ID)
117+
assert.EqualValues(t, 1, apiIssues[2].ID)
118+
assert.EqualValues(t, 11, apiIssues[3].ID)
119+
}
120+
})
77121
}
78122

79123
func TestAPIListIssuesPublicOnly(t *testing.T) {

0 commit comments

Comments
 (0)