Add label names as filter in issue search api (#5946)

This commit is contained in:
Lanre Adelowo 2019-02-04 16:20:44 +01:00 committed by techknowlogick
parent f21ae12abb
commit 024871ade6
4 changed files with 59 additions and 2 deletions

View file

@ -203,13 +203,26 @@ func GetLabelInRepoByName(repoID int64, labelName string) (*Label, error) {
return getLabelInRepoByName(x, repoID, labelName) return getLabelInRepoByName(x, repoID, labelName)
} }
// GetLabelIDsInRepoByNames returns a list of labelIDs by names in a given
// repository.
// it silently ignores label names that do not belong to the repository.
func GetLabelIDsInRepoByNames(repoID int64, labelNames []string) ([]int64, error) {
labelIDs := make([]int64, 0, len(labelNames))
return labelIDs, x.Table("label").
Where("repo_id = ?", repoID).
In("name", labelNames).
Asc("name").
Cols("id").
Find(&labelIDs)
}
// GetLabelInRepoByID returns a label by ID in given repository. // GetLabelInRepoByID returns a label by ID in given repository.
func GetLabelInRepoByID(repoID, labelID int64) (*Label, error) { func GetLabelInRepoByID(repoID, labelID int64) (*Label, error) {
return getLabelInRepoByID(x, repoID, labelID) return getLabelInRepoByID(x, repoID, labelID)
} }
// GetLabelsInRepoByIDs returns a list of labels by IDs in given repository, // GetLabelsInRepoByIDs returns a list of labels by IDs in given repository,
// it silently ignores label IDs that are not belong to the repository. // it silently ignores label IDs that do not belong to the repository.
func GetLabelsInRepoByIDs(repoID int64, labelIDs []int64) ([]*Label, error) { func GetLabelsInRepoByIDs(repoID int64, labelIDs []int64) ([]*Label, error) {
labels := make([]*Label, 0, len(labelIDs)) labels := make([]*Label, 0, len(labelIDs))
return labels, x. return labels, x.

View file

@ -81,6 +81,30 @@ func TestGetLabelInRepoByName(t *testing.T) {
assert.True(t, IsErrLabelNotExist(err)) assert.True(t, IsErrLabelNotExist(err))
} }
func TestGetLabelInRepoByNames(t *testing.T) {
assert.NoError(t, PrepareTestDatabase())
labelIDs, err := GetLabelIDsInRepoByNames(1, []string{"label1", "label2"})
assert.NoError(t, err)
assert.Len(t, labelIDs, 2)
assert.Equal(t, int64(1), labelIDs[0])
assert.Equal(t, int64(2), labelIDs[1])
}
func TestGetLabelInRepoByNamesDiscardsNonExistentLabels(t *testing.T) {
assert.NoError(t, PrepareTestDatabase())
// label3 doesn't exists.. See labels.yml
labelIDs, err := GetLabelIDsInRepoByNames(1, []string{"label1", "label2", "label3"})
assert.NoError(t, err)
assert.Len(t, labelIDs, 2)
assert.Equal(t, int64(1), labelIDs[0])
assert.Equal(t, int64(2), labelIDs[1])
assert.NoError(t, err)
}
func TestGetLabelInRepoByID(t *testing.T) { func TestGetLabelInRepoByID(t *testing.T) {
assert.NoError(t, PrepareTestDatabase()) assert.NoError(t, PrepareTestDatabase())
label, err := GetLabelInRepoByID(1, 1) label, err := GetLabelInRepoByID(1, 1)

View file

@ -43,6 +43,10 @@ func ListIssues(ctx *context.APIContext) {
// in: query // in: query
// description: whether issue is open or closed // description: whether issue is open or closed
// type: string // type: string
// - name: labels
// in: query
// description: comma separated list of labels. Fetch only issues that have any of this labels. Non existent labels are discarded
// type: string
// - name: page // - name: page
// in: query // in: query
// description: page number of requested issues // description: page number of requested issues
@ -71,20 +75,30 @@ func ListIssues(ctx *context.APIContext) {
keyword = "" keyword = ""
} }
var issueIDs []int64 var issueIDs []int64
var labelIDs []int64
var err error var err error
if len(keyword) > 0 { if len(keyword) > 0 {
issueIDs, err = indexer.SearchIssuesByKeyword(ctx.Repo.Repository.ID, keyword) issueIDs, err = indexer.SearchIssuesByKeyword(ctx.Repo.Repository.ID, keyword)
} }
if splitted := strings.Split(ctx.Query("labels"), ","); len(splitted) > 0 {
labelIDs, err = models.GetLabelIDsInRepoByNames(ctx.Repo.Repository.ID, splitted)
if err != nil {
ctx.Error(500, "GetLabelIDsInRepoByNames", err)
return
}
}
// Only fetch the issues if we either don't have a keyword or the search returned issues // Only fetch the issues if we either don't have a keyword or the search returned issues
// This would otherwise return all issues if no issues were found by the search. // This would otherwise return all issues if no issues were found by the search.
if len(keyword) == 0 || len(issueIDs) > 0 { if len(keyword) == 0 || len(issueIDs) > 0 || len(labelIDs) > 0 {
issues, err = models.Issues(&models.IssuesOptions{ issues, err = models.Issues(&models.IssuesOptions{
RepoIDs: []int64{ctx.Repo.Repository.ID}, RepoIDs: []int64{ctx.Repo.Repository.ID},
Page: ctx.QueryInt("page"), Page: ctx.QueryInt("page"),
PageSize: setting.UI.IssuePagingNum, PageSize: setting.UI.IssuePagingNum,
IsClosed: isClosed, IsClosed: isClosed,
IssueIDs: issueIDs, IssueIDs: issueIDs,
LabelIDs: labelIDs,
}) })
} }

View file

@ -2059,6 +2059,12 @@
"name": "state", "name": "state",
"in": "query" "in": "query"
}, },
{
"type": "string",
"description": "comma separated list of labels. Fetch only issues that have any of this labels. Non existent labels are discarded",
"name": "labels",
"in": "query"
},
{ {
"type": "integer", "type": "integer",
"description": "page number of requested issues", "description": "page number of requested issues",