Merge branch 'jubianchi-api/issues-filter-milestone'
This commit is contained in:
commit
0c29cb3451
4 changed files with 74 additions and 9 deletions
|
@ -9,6 +9,7 @@ v 7.4.0
|
||||||
- Do not delete tmp/repositories itself during clean-up, only its contents
|
- Do not delete tmp/repositories itself during clean-up, only its contents
|
||||||
- Support for backup uploads to remote storage
|
- Support for backup uploads to remote storage
|
||||||
- Prevent notes polling when there are not notes
|
- Prevent notes polling when there are not notes
|
||||||
|
- API: filter project issues by milestone (Julien Bianchi)
|
||||||
|
|
||||||
v 7.3.1
|
v 7.3.1
|
||||||
- Fix ref parsing in Gitlab::GitAccess
|
- Fix ref parsing in Gitlab::GitAccess
|
||||||
|
|
|
@ -95,6 +95,8 @@ GET /projects/:id/issues?state=closed
|
||||||
GET /projects/:id/issues?labels=foo
|
GET /projects/:id/issues?labels=foo
|
||||||
GET /projects/:id/issues?labels=foo,bar
|
GET /projects/:id/issues?labels=foo,bar
|
||||||
GET /projects/:id/issues?labels=foo,bar&state=opened
|
GET /projects/:id/issues?labels=foo,bar&state=opened
|
||||||
|
GET /projects/:id/issues?milestone=1.0.0
|
||||||
|
GET /projects/:id/issues?milestone=1.0.0&state=opened
|
||||||
```
|
```
|
||||||
|
|
||||||
Parameters:
|
Parameters:
|
||||||
|
@ -102,6 +104,7 @@ Parameters:
|
||||||
- `id` (required) - The ID of a project
|
- `id` (required) - The ID of a project
|
||||||
- `state` (optional) - Return `all` issues or just those that are `opened` or `closed`
|
- `state` (optional) - Return `all` issues or just those that are `opened` or `closed`
|
||||||
- `labels` (optional) - Comma-separated list of label names
|
- `labels` (optional) - Comma-separated list of label names
|
||||||
|
- `milestone` (optional) - Milestone title
|
||||||
|
|
||||||
## Single issue
|
## Single issue
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@ module API
|
||||||
before { authenticate! }
|
before { authenticate! }
|
||||||
|
|
||||||
helpers do
|
helpers do
|
||||||
def filter_issues_state(issues, state = nil)
|
def filter_issues_state(issues, state)
|
||||||
case state
|
case state
|
||||||
when 'opened' then issues.opened
|
when 'opened' then issues.opened
|
||||||
when 'closed' then issues.closed
|
when 'closed' then issues.closed
|
||||||
|
@ -13,7 +13,11 @@ module API
|
||||||
end
|
end
|
||||||
|
|
||||||
def filter_issues_labels(issues, labels)
|
def filter_issues_labels(issues, labels)
|
||||||
issues.includes(:labels).where("labels.title" => labels.split(','))
|
issues.includes(:labels).where('labels.title' => labels.split(','))
|
||||||
|
end
|
||||||
|
|
||||||
|
def filter_issues_milestone(issues, milestone)
|
||||||
|
issues.includes(:milestone).where('milestones.title' => milestone)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -48,19 +52,24 @@ module API
|
||||||
# id (required) - The ID of a project
|
# id (required) - The ID of a project
|
||||||
# state (optional) - Return "opened" or "closed" issues
|
# state (optional) - Return "opened" or "closed" issues
|
||||||
# labels (optional) - Comma-separated list of label names
|
# labels (optional) - Comma-separated list of label names
|
||||||
|
# milestone (optional) - Milestone title
|
||||||
#
|
#
|
||||||
# Example Requests:
|
# Example Requests:
|
||||||
# GET /projects/:id/issues
|
# GET /projects/:id/issues
|
||||||
# GET /projects/:id/issues?state=opened
|
# GET /projects/:id/issues?state=opened
|
||||||
# GET /projects/:id/issues?state=closed
|
# GET /projects/:id/issues?state=closed
|
||||||
# GET /projects/:id/issues
|
|
||||||
# GET /projects/:id/issues?labels=foo
|
# GET /projects/:id/issues?labels=foo
|
||||||
# GET /projects/:id/issues?labels=foo,bar
|
# GET /projects/:id/issues?labels=foo,bar
|
||||||
# GET /projects/:id/issues?labels=foo,bar&state=opened
|
# GET /projects/:id/issues?labels=foo,bar&state=opened
|
||||||
|
# GET /projects/:id/issues?milestone=1.0.0
|
||||||
|
# GET /projects/:id/issues?milestone=1.0.0&state=closed
|
||||||
get ":id/issues" do
|
get ":id/issues" do
|
||||||
issues = user_project.issues
|
issues = user_project.issues
|
||||||
issues = filter_issues_state(issues, params[:state]) unless params[:state].nil?
|
issues = filter_issues_state(issues, params[:state]) unless params[:state].nil?
|
||||||
issues = filter_issues_labels(issues, params[:labels]) unless params[:labels].nil?
|
issues = filter_issues_labels(issues, params[:labels]) unless params[:labels].nil?
|
||||||
|
unless params[:milestone].nil?
|
||||||
|
issues = filter_issues_milestone(issues, params[:milestone])
|
||||||
|
end
|
||||||
issues = issues.order('issues.id DESC')
|
issues = issues.order('issues.id DESC')
|
||||||
|
|
||||||
present paginate(issues), with: Entities::Issue
|
present paginate(issues), with: Entities::Issue
|
||||||
|
|
|
@ -4,12 +4,29 @@ describe API::API, api: true do
|
||||||
include ApiHelpers
|
include ApiHelpers
|
||||||
let(:user) { create(:user) }
|
let(:user) { create(:user) }
|
||||||
let!(:project) { create(:project, namespace: user.namespace ) }
|
let!(:project) { create(:project, namespace: user.namespace ) }
|
||||||
let!(:closed_issue) { create(:closed_issue, author: user, assignee: user, project: project, state: :closed) }
|
let!(:closed_issue) do
|
||||||
let!(:issue) { create(:issue, author: user, assignee: user, project: project) }
|
create :closed_issue,
|
||||||
|
author: user,
|
||||||
|
assignee: user,
|
||||||
|
project: project,
|
||||||
|
state: :closed,
|
||||||
|
milestone: milestone
|
||||||
|
end
|
||||||
|
let!(:issue) do
|
||||||
|
create :issue,
|
||||||
|
author: user,
|
||||||
|
assignee: user,
|
||||||
|
project: project,
|
||||||
|
milestone: milestone
|
||||||
|
end
|
||||||
let!(:label) do
|
let!(:label) do
|
||||||
create(:label, title: 'label', color: '#FFAABB', project: project)
|
create(:label, title: 'label', color: '#FFAABB', project: project)
|
||||||
end
|
end
|
||||||
let!(:label_link) { create(:label_link, label: label, target: issue) }
|
let!(:label_link) { create(:label_link, label: label, target: issue) }
|
||||||
|
let!(:milestone) { create(:milestone, title: '1.0.0', project: project) }
|
||||||
|
let!(:empty_milestone) do
|
||||||
|
create(:milestone, title: '2.0.0', project: project)
|
||||||
|
end
|
||||||
|
|
||||||
before { project.team << [user, :reporter] }
|
before { project.team << [user, :reporter] }
|
||||||
|
|
||||||
|
@ -102,15 +119,18 @@ describe API::API, api: true do
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "GET /projects/:id/issues" do
|
describe "GET /projects/:id/issues" do
|
||||||
|
let(:base_url) { "/projects/#{project.id}" }
|
||||||
|
let(:title) { milestone.title }
|
||||||
|
|
||||||
it "should return project issues" do
|
it "should return project issues" do
|
||||||
get api("/projects/#{project.id}/issues", user)
|
get api("#{base_url}/issues", user)
|
||||||
response.status.should == 200
|
response.status.should == 200
|
||||||
json_response.should be_an Array
|
json_response.should be_an Array
|
||||||
json_response.first['title'].should == issue.title
|
json_response.first['title'].should == issue.title
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'should return an array of labeled project issues' do
|
it 'should return an array of labeled project issues' do
|
||||||
get api("/projects/#{project.id}/issues?labels=#{label.title}", user)
|
get api("#{base_url}/issues?labels=#{label.title}", user)
|
||||||
response.status.should == 200
|
response.status.should == 200
|
||||||
json_response.should be_an Array
|
json_response.should be_an Array
|
||||||
json_response.length.should == 1
|
json_response.length.should == 1
|
||||||
|
@ -118,7 +138,7 @@ describe API::API, api: true do
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'should return an array of labeled project issues when at least one label matches' do
|
it 'should return an array of labeled project issues when at least one label matches' do
|
||||||
get api("/projects/#{project.id}/issues?labels=#{label.title},foo,bar", user)
|
get api("#{base_url}/issues?labels=#{label.title},foo,bar", user)
|
||||||
response.status.should == 200
|
response.status.should == 200
|
||||||
json_response.should be_an Array
|
json_response.should be_an Array
|
||||||
json_response.length.should == 1
|
json_response.length.should == 1
|
||||||
|
@ -126,11 +146,43 @@ describe API::API, api: true do
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'should return an empty array if no project issue matches labels' do
|
it 'should return an empty array if no project issue matches labels' do
|
||||||
get api("/projects/#{project.id}/issues?labels=foo,bar", user)
|
get api("#{base_url}/issues?labels=foo,bar", user)
|
||||||
response.status.should == 200
|
response.status.should == 200
|
||||||
json_response.should be_an Array
|
json_response.should be_an Array
|
||||||
json_response.length.should == 0
|
json_response.length.should == 0
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it 'should return an empty array if no issue matches milestone' do
|
||||||
|
get api("#{base_url}/issues?milestone=#{empty_milestone.title}", user)
|
||||||
|
response.status.should == 200
|
||||||
|
json_response.should be_an Array
|
||||||
|
json_response.length.should == 0
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'should return an empty array if milestone does not exist' do
|
||||||
|
get api("#{base_url}/issues?milestone=foo", user)
|
||||||
|
response.status.should == 200
|
||||||
|
json_response.should be_an Array
|
||||||
|
json_response.length.should == 0
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'should return an array of issues in given milestone' do
|
||||||
|
get api("#{base_url}/issues?milestone=#{title}", user)
|
||||||
|
response.status.should == 200
|
||||||
|
json_response.should be_an Array
|
||||||
|
json_response.length.should == 2
|
||||||
|
json_response.first['id'].should == issue.id
|
||||||
|
json_response.second['id'].should == closed_issue.id
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'should return an array of issues matching state in milestone' do
|
||||||
|
get api("#{base_url}/issues?milestone=#{milestone.title}"\
|
||||||
|
'&state=closed', user)
|
||||||
|
response.status.should == 200
|
||||||
|
json_response.should be_an Array
|
||||||
|
json_response.length.should == 1
|
||||||
|
json_response.first['id'].should == closed_issue.id
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "GET /projects/:id/issues/:issue_id" do
|
describe "GET /projects/:id/issues/:issue_id" do
|
||||||
|
|
Loading…
Reference in a new issue