Add label names as filter in issue search api (#5946)
This commit is contained in:
parent
f21ae12abb
commit
024871ade6
4 changed files with 59 additions and 2 deletions
|
@ -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.
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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",
|
||||||
|
|
Reference in a new issue