Commit be079d40 authored by Brett Walker's avatar Brett Walker Committed by Stan Hu

Add pagination and sorting

for jira issue controller
parent 2c966430
......@@ -7,14 +7,19 @@ module Projects
RequestError = Class.new(StandardError)
class IssuesFinder
attr_reader :issues, :total_count
attr_reader :issues, :total_count, :per_page
class << self
def valid_params
@valid_params ||= %i[page per_page search state]
end
end
def initialize(project, params = {})
@project = project
@jira_service = project.jira_service
@page = params[:page].presence || 1
@params = params
@params = @params.reverse_merge(map_sort_values(@params.delete(:sort)))
@params = params.merge(map_sort_values(params[:sort]))
set_pagination
end
def execute
......@@ -35,7 +40,9 @@ module Projects
# rubocop: disable CodeReuse/ServiceClass
def fetch_issues(project_key)
jql = ::Jira::JqlBuilderService.new(project_key, params).execute
response = ::Jira::Requests::Issues::ListService.new(jira_service, { jql: jql, page: page }).execute
response = ::Jira::Requests::Issues::ListService
.new(jira_service, { jql: jql, page: page, per_page: per_page })
.execute
if response.success?
@total_count = response.payload[:total_count]
......@@ -54,6 +61,11 @@ module Projects
{ sort: ::Jira::JqlBuilderService::DEFAULT_SORT, sort_direction: ::Jira::JqlBuilderService::DEFAULT_SORT_DIRECTION }
end
end
def set_pagination
@page = (params[:page].presence || 1).to_i
@per_page = (params[:per_page].presence || ::Jira::Requests::Issues::ListService::PER_PAGE).to_i
end
end
end
end
......
......@@ -5,6 +5,8 @@ module Projects
module Jira
class IssuesController < Projects::ApplicationController
include RecordUserLastActivity
include SortingHelper
include SortingPreference
before_action :check_feature_enabled!
......@@ -27,9 +29,42 @@ module Projects
private
def issues_json
jira_issues = ::Projects::Integrations::Jira::IssuesFinder.new(project, {}).execute
jira_issues = finder.execute
jira_issues = Kaminari.paginate_array(jira_issues, limit: finder.per_page, total_count: finder.total_count)
::Integrations::Jira::IssueSerializer.new.represent(jira_issues, project: project)
::Integrations::Jira::IssueSerializer.new
.with_pagination(request, response)
.represent(jira_issues, project: project)
end
def finder
@finder ||= finder_type.new(project, finder_options)
end
def finder_type
::Projects::Integrations::Jira::IssuesFinder
end
def finder_options
params[:state] = default_state if params[:state].blank?
options = { sort: set_sort_order }
# Used by view to highlight active option
@sort = options[:sort]
params.permit(finder_type.valid_params).merge(options)
end
def default_state
'opened'
end
def default_sort_order
case params[:state]
when 'opened', 'all' then sort_value_created_date
when 'closed' then sort_value_recently_updated
else sort_value_created_date
end
end
protected
......
......@@ -3,6 +3,8 @@
module Integrations
module Jira
class IssueSerializer < BaseSerializer
include WithPagination
entity ::Integrations::Jira::IssueEntity
end
end
......
......@@ -53,7 +53,7 @@ RSpec.describe Projects::Integrations::Jira::IssuesController do
let(:jira_issues) { [] }
it 'returns a list of serialized jira issues' do
expect_next_instance_of(Projects::Integrations::Jira::IssuesFinder, project, {}) do |finder|
expect_next_instance_of(Projects::Integrations::Jira::IssuesFinder) do |finder|
expect(finder).to receive(:execute).and_return(jira_issues)
end
......@@ -83,6 +83,59 @@ RSpec.describe Projects::Integrations::Jira::IssuesController do
expect(response).to have_gitlab_http_status(:bad_request)
expect(json_response['errors']).to eq ['Request error']
end
it 'sets pagination headers' do
expect_next_instance_of(Projects::Integrations::Jira::IssuesFinder) do |finder|
expect(finder).to receive(:execute).and_return(jira_issues)
end
get :index, params: { namespace_id: project.namespace, project_id: project }, format: :json
expect(response).to include_pagination_headers
expect(response.headers['X-Page']).to eq '1'
expect(response.headers['X-Per-Page']).to eq Jira::Requests::Issues::ListService::PER_PAGE.to_s
expect(response.headers['X-Total']).to eq '0'
end
context 'when parameters are passed' do
shared_examples 'proper parameter values' do
it 'properly set the values' do
expect_next_instance_of(Projects::Integrations::Jira::IssuesFinder, project, expected_params) do |finder|
expect(finder).to receive(:execute).and_return(jira_issues)
end
get :index, params: { namespace_id: project.namespace, project_id: project }.merge(params), format: :json
end
end
context 'when there are no params' do
it_behaves_like 'proper parameter values' do
let(:params) { {} }
let(:expected_params) { { 'state' => 'opened', 'sort' => 'created_date' } }
end
end
context 'when pagination params' do
it_behaves_like 'proper parameter values' do
let(:params) { { 'page' => '12', 'per_page' => '20' } }
let(:expected_params) { { 'page' => '12', 'per_page' => '20', 'state' => 'opened', 'sort' => 'created_date' } }
end
end
context 'when state is closed' do
it_behaves_like 'proper parameter values' do
let(:params) { { 'state' => 'closed' } }
let(:expected_params) { { 'state' => 'closed', 'sort' => 'updated_desc' } }
end
end
context 'when invalid params' do
it_behaves_like 'proper parameter values' do
let(:params) { { 'invalid' => '12' } }
let(:expected_params) { { 'state' => 'opened', 'sort' => 'created_date' } }
end
end
end
end
end
......
......@@ -99,6 +99,18 @@ RSpec.describe Projects::Integrations::Jira::IssuesFinder do
subject
end
end
context 'when pagination params used' do
let(:params) { { page: '10', per_page: '20' } }
it 'passes them to JqlBuilderService ' do
expect(::Jira::JqlBuilderService).to receive(:new)
.with(jira_service.project_key, include({ page: '10', per_page: '20' }))
.and_call_original
subject
end
end
end
end
end
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment