Commit 6c2b0676 authored by charlie ablett's avatar charlie ablett

Expose epicsCount under epic board lists

- Add tests
- Slight refactor to use current_user method in type
- Move some logic into BasicItemsListService
parent a2ce003c
...@@ -8,6 +8,8 @@ module Types ...@@ -8,6 +8,8 @@ module Types
graphql_name 'BoardList' graphql_name 'BoardList'
description 'Represents a list for an issue board' description 'Represents a list for an issue board'
alias_method :list, :object
field :id, GraphQL::ID_TYPE, null: false, field :id, GraphQL::ID_TYPE, null: false,
description: 'ID (global ID) of the list.' description: 'ID (global ID) of the list.'
field :title, GraphQL::STRING_TYPE, null: false, field :title, GraphQL::STRING_TYPE, null: false,
...@@ -37,12 +39,10 @@ module Types ...@@ -37,12 +39,10 @@ module Types
def metadata def metadata
strong_memoize(:metadata) do strong_memoize(:metadata) do
list = self.object
user = context[:current_user]
params = (context[:issue_filters] || {}).merge(board_id: list.board_id, id: list.id) params = (context[:issue_filters] || {}).merge(board_id: list.board_id, id: list.id)
::Boards::Issues::ListService ::Boards::Issues::ListService
.new(list.board.resource_parent, user, params) .new(list.board.resource_parent, current_user, params)
.metadata .metadata
end end
end end
......
...@@ -11,8 +11,24 @@ module Boards ...@@ -11,8 +11,24 @@ module Boards
ordered_items ordered_items
end end
# rubocop: disable CodeReuse/ActiveRecord
def metadata
issues = item_model.arel_table
keys = metadata_fields.keys
# TODO: eliminate need for SQL literal fragment
columns = Arel.sql(metadata_fields.values_at(*keys).join(', '))
results = item_model.where(id: items.select(issues[:id])).pluck(columns)
Hash[keys.zip(results.flatten)]
end
# rubocop: enable CodeReuse/ActiveRecord
private private
def metadata_fields
{ size: 'COUNT(*)' }
end
def ordered_items def ordered_items
raise NotImplementedError raise NotImplementedError
end end
......
...@@ -35,10 +35,6 @@ module Boards ...@@ -35,10 +35,6 @@ module Boards
@board ||= parent.boards.find(params[:board_id]) @board ||= parent.boards.find(params[:board_id])
end end
def metadata_fields
{ size: 'COUNT(*)' }
end
def filter_params def filter_params
set_scope set_scope
set_non_archived set_non_archived
......
...@@ -1973,6 +1973,7 @@ Represents an epic board list. ...@@ -1973,6 +1973,7 @@ Represents an epic board list.
| ----- | ---- | ----------- | | ----- | ---- | ----------- |
| `collapsed` | Boolean | Indicates if this list is collapsed for this user. | | `collapsed` | Boolean | Indicates if this list is collapsed for this user. |
| `epics` | EpicConnection | List epics. | | `epics` | EpicConnection | List epics. |
| `epicsCount` | Int | Count of epics in the list. |
| `id` | BoardsEpicListID! | Global ID of the board list. | | `id` | BoardsEpicListID! | Global ID of the board list. |
| `label` | Label | Label of the list. | | `label` | Label | Label of the list. |
| `listType` | String! | Type of the list. | | `listType` | String! | Type of the list. |
......
...@@ -4,11 +4,15 @@ module Types ...@@ -4,11 +4,15 @@ module Types
module Boards module Boards
# rubocop: disable Graphql/AuthorizeTypes # rubocop: disable Graphql/AuthorizeTypes
class EpicListType < BaseObject class EpicListType < BaseObject
include Gitlab::Utils::StrongMemoize
graphql_name 'EpicList' graphql_name 'EpicList'
description 'Represents an epic board list' description 'Represents an epic board list'
accepts ::Boards::EpicList accepts ::Boards::EpicList
alias_method :list, :object
field :id, type: ::Types::GlobalIDType[::Boards::EpicList], null: false, field :id, type: ::Types::GlobalIDType[::Boards::EpicList], null: false,
description: 'Global ID of the board list.' description: 'Global ID of the board list.'
...@@ -31,9 +35,24 @@ module Types ...@@ -31,9 +35,24 @@ module Types
resolver: Resolvers::Boards::BoardListEpicsResolver, resolver: Resolvers::Boards::BoardListEpicsResolver,
description: 'List epics.' description: 'List epics.'
field :epics_count, GraphQL::INT_TYPE, null: true,
description: 'Count of epics in the list.'
def collapsed def collapsed
object.collapsed?(current_user) object.collapsed?(current_user)
end end
def epics_count
metadata[:size]
end
def metadata
strong_memoize(:metadata) do
::Boards::Epics::ListService
.new(list.epic_board.resource_parent, current_user, { board_id: list.epic_board_id, id: list.id })
.metadata
end
end
end end
# rubocop: enable Graphql/AuthorizeTypes # rubocop: enable Graphql/AuthorizeTypes
end end
......
...@@ -6,7 +6,7 @@ RSpec.describe GitlabSchema.types['EpicList'] do ...@@ -6,7 +6,7 @@ RSpec.describe GitlabSchema.types['EpicList'] do
specify { expect(described_class.graphql_name).to eq('EpicList') } specify { expect(described_class.graphql_name).to eq('EpicList') }
it 'has specific fields' do it 'has specific fields' do
expected_fields = %w[id title list_type position label epics collapsed] expected_fields = %w[id title list_type position label epics epics_count collapsed]
expect(described_class).to include_graphql_fields(*expected_fields) expect(described_class).to include_graphql_fields(*expected_fields)
end end
......
...@@ -12,6 +12,8 @@ RSpec.describe 'get list of epic boards' do ...@@ -12,6 +12,8 @@ RSpec.describe 'get list of epic boards' do
let_it_be(:list2) { create(:epic_list, epic_board: board, list_type: :closed) } let_it_be(:list2) { create(:epic_list, epic_board: board, list_type: :closed) }
let_it_be(:list3) { create(:epic_list, epic_board: board, list_type: :backlog) } let_it_be(:list3) { create(:epic_list, epic_board: board, list_type: :backlog) }
let_it_be(:some_epics) { create_list(:epic, 2, group: group) }
def pagination_query(params = {}) def pagination_query(params = {})
graphql_query_for(:group, { full_path: group.full_path }, graphql_query_for(:group, { full_path: group.full_path },
<<~BOARDS <<~BOARDS
...@@ -78,6 +80,13 @@ RSpec.describe 'get list of epic boards' do ...@@ -78,6 +80,13 @@ RSpec.describe 'get list of epic boards' do
assert_field_value('id', [global_id_of(list3), global_id_of(list1), global_id_of(list2)]) assert_field_value('id', [global_id_of(list3), global_id_of(list1), global_id_of(list2)])
assert_field_value('collapsed', [false, true, false]) assert_field_value('collapsed', [false, true, false])
end end
it 'returns the correct values for count' do
post_graphql(pagination_query, current_user: current_user)
assert_field_value('epicsCount', [2, 0, 0])
end
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