Commit 25a6603d authored by Robert Speicher's avatar Robert Speicher

Merge branch 'list_issue_filters' into 'master'

Add issue filters to board list count/weight

See merge request gitlab-org/gitlab!43968
parents 8374665e c6565fa3
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
module Resolvers module Resolvers
class BoardListsResolver < BaseResolver class BoardListsResolver < BaseResolver
include BoardIssueFilterable
include Gitlab::Graphql::Authorize::AuthorizeResource include Gitlab::Graphql::Authorize::AuthorizeResource
type Types::BoardListType, null: true type Types::BoardListType, null: true
...@@ -10,12 +11,17 @@ module Resolvers ...@@ -10,12 +11,17 @@ module Resolvers
required: false, required: false,
description: 'Find a list by its global ID' description: 'Find a list by its global ID'
argument :issue_filters, Types::Boards::BoardIssueInputType,
required: false,
description: 'Filters applied when getting issue metadata in the board list'
alias_method :board, :object alias_method :board, :object
def resolve(lookahead: nil, id: nil) def resolve(lookahead: nil, id: nil, issue_filters: {})
authorize!(board) authorize!(board)
lists = board_lists(id) lists = board_lists(id)
context.scoped_set!(:issue_filters, issue_filters(issue_filters))
if load_preferences?(lookahead) if load_preferences?(lookahead)
List.preload_preferences_for_user(lists, context[:current_user]) List.preload_preferences_for_user(lists, context[:current_user])
......
...@@ -32,17 +32,14 @@ module Types ...@@ -32,17 +32,14 @@ module Types
metadata[:size] metadata[:size]
end end
def total_weight
metadata[:total_weight]
end
def metadata def metadata
strong_memoize(:metadata) do strong_memoize(:metadata) do
list = self.object list = self.object
user = context[:current_user] user = context[:current_user]
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, board_id: list.board_id, id: list.id) .new(list.board.resource_parent, user, params)
.metadata .metadata
end end
end end
......
---
title: Accept issue filters when getting board lists in GraphQL
merge_request: 43968
author:
type: added
...@@ -1096,6 +1096,11 @@ type Board { ...@@ -1096,6 +1096,11 @@ type Board {
""" """
id: ID id: ID
"""
Filters applied when getting issue metadata in the board list
"""
issueFilters: BoardIssueInput
""" """
Returns the last _n_ elements from the list. Returns the last _n_ elements from the list.
""" """
......
...@@ -2854,6 +2854,16 @@ ...@@ -2854,6 +2854,16 @@
}, },
"defaultValue": null "defaultValue": null
}, },
{
"name": "issueFilters",
"description": "Filters applied when getting issue metadata in the board list",
"type": {
"kind": "INPUT_OBJECT",
"name": "BoardIssueInput",
"ofType": null
},
"defaultValue": null
},
{ {
"name": "after", "name": "after",
"description": "Returns the elements in the list that come after the specified cursor.", "description": "Returns the elements in the list that come after the specified cursor.",
...@@ -26,6 +26,10 @@ module EE ...@@ -26,6 +26,10 @@ module EE
def assignee def assignee
object.assignee? ? object.user : nil object.assignee? ? object.user : nil
end end
def total_weight
metadata[:total_weight]
end
end end
end end
end end
......
...@@ -49,6 +49,12 @@ RSpec.describe Resolvers::BoardListsResolver do ...@@ -49,6 +49,12 @@ RSpec.describe Resolvers::BoardListsResolver do
end end
def resolve_board_lists(args: {}, current_user: user) def resolve_board_lists(args: {}, current_user: user)
resolve(described_class, obj: board, args: args, ctx: { current_user: current_user }) context = GraphQL::Query::Context.new(
query: OpenStruct.new(schema: nil),
values: { current_user: current_user },
object: nil
)
resolve(described_class, obj: board, args: args, ctx: context)
end end
end end
...@@ -6,14 +6,16 @@ RSpec.describe 'get board lists' do ...@@ -6,14 +6,16 @@ RSpec.describe 'get board lists' do
include GraphqlHelpers include GraphqlHelpers
let_it_be(:current_user) { create(:user) } let_it_be(:current_user) { create(:user) }
let_it_be(:project) { create(:project, creator_id: current_user.id, namespace: current_user.namespace ) }
let_it_be(:group) { create(:group, :private) } let_it_be(:group) { create(:group, :private) }
let_it_be(:project) { create(:project, creator_id: current_user.id, group: group) }
let_it_be(:project_milestone) { create(:milestone, project: project) } let_it_be(:project_milestone) { create(:milestone, project: project) }
let_it_be(:project_milestone2) { create(:milestone, project: project) } let_it_be(:project_milestone2) { create(:milestone, project: project) }
let_it_be(:group_milestone) { create(:milestone, group: group) } let_it_be(:group_milestone) { create(:milestone, group: group) }
let_it_be(:group_milestone2) { create(:milestone, group: group) } let_it_be(:group_milestone2) { create(:milestone, group: group) }
let_it_be(:assignee) { create(:assignee) } let_it_be(:assignee) { create(:assignee) }
let_it_be(:assignee2) { create(:assignee) } let_it_be(:assignee2) { create(:assignee) }
let_it_be(:label) { create(:group_label, group: group) }
let_it_be(:label2) { create(:group_label, group: group) }
let(:params) { '' } let(:params) { '' }
let(:board) { } let(:board) { }
...@@ -120,6 +122,24 @@ RSpec.describe 'get board lists' do ...@@ -120,6 +122,24 @@ RSpec.describe 'get board lists' do
expect(list['maxIssueWeight']).to eq(4) expect(list['maxIssueWeight']).to eq(4)
end end
end end
describe 'total issue count and weight' do
it 'returns total count and weight of issues matching issue filters' do
label_list = create(:list, board: board, label: label, position: 10)
create(:issue, project: project, labels: [label, label2], weight: 2)
create(:issue, project: project, labels: [label], weight: 2)
post_graphql(query(id: global_id_of(label_list), issueFilters: { labelName: label2.title }), current_user: current_user)
aggregate_failures do
list_node = lists_data[0]['node']
expect(list_node['title']).to eq label_list.title
expect(list_node['issuesCount']).to eq 1
expect(list_node['totalWeight']).to eq 2
end
end
end
end end
end end
......
...@@ -101,6 +101,12 @@ RSpec.describe Resolvers::BoardListsResolver do ...@@ -101,6 +101,12 @@ RSpec.describe Resolvers::BoardListsResolver do
end end
def resolve_board_lists(args: {}, current_user: user) def resolve_board_lists(args: {}, current_user: user)
resolve(described_class, obj: board, args: args, ctx: { current_user: current_user }) context = GraphQL::Query::Context.new(
query: OpenStruct.new(schema: nil),
values: { current_user: current_user },
object: nil
)
resolve(described_class, obj: board, args: args, ctx: context )
end end
end end
...@@ -7,8 +7,8 @@ RSpec.describe 'get board lists' do ...@@ -7,8 +7,8 @@ RSpec.describe 'get board lists' do
let_it_be(:user) { create(:user) } let_it_be(:user) { create(:user) }
let_it_be(:unauth_user) { create(:user) } let_it_be(:unauth_user) { create(:user) }
let_it_be(:project) { create(:project, creator_id: user.id, namespace: user.namespace ) }
let_it_be(:group) { create(:group, :private) } let_it_be(:group) { create(:group, :private) }
let_it_be(:project) { create(:project, creator_id: user.id, group: group) }
let_it_be(:project_label) { create(:label, project: project, name: 'Development') } let_it_be(:project_label) { create(:label, project: project, name: 'Development') }
let_it_be(:project_label2) { create(:label, project: project, name: 'Testing') } let_it_be(:project_label2) { create(:label, project: project, name: 'Testing') }
let_it_be(:group_label) { create(:group_label, group: group, name: 'Development') } let_it_be(:group_label) { create(:group_label, group: group, name: 'Development') }
...@@ -111,12 +111,19 @@ RSpec.describe 'get board lists' do ...@@ -111,12 +111,19 @@ RSpec.describe 'get board lists' do
board_parent.add_reporter(user) board_parent.add_reporter(user)
end end
it 'finds the correct list' do it 'returns the correct list with issue count for matching issue filters' do
label_list = create(:list, board: board, label: label, position: 10) label_list = create(:list, board: board, label: label, position: 10)
create(:issue, project: project, labels: [label, label2])
create(:issue, project: project, labels: [label])
post_graphql(query("id: \"#{global_id_of(label_list)}\""), current_user: user) post_graphql(query(id: global_id_of(label_list), issueFilters: { labelName: label2.title }), current_user: user)
expect(lists_data[0]['node']['title']).to eq label_list.title aggregate_failures do
list_node = lists_data[0]['node']
expect(list_node['title']).to eq label_list.title
expect(list_node['issuesCount']).to eq 1
end
end end
end end
end end
......
...@@ -219,6 +219,7 @@ module GraphqlHelpers ...@@ -219,6 +219,7 @@ module GraphqlHelpers
def as_graphql_literal(value) def as_graphql_literal(value)
case value case value
when Array then "[#{value.map { |v| as_graphql_literal(v) }.join(',')}]" when Array then "[#{value.map { |v| as_graphql_literal(v) }.join(',')}]"
when Hash then "{#{value.map { |k, v| "#{k}:#{as_graphql_literal(v)}" }.join(',')}}"
when Integer, Float then value.to_s when Integer, Float then value.to_s
when String then "\"#{value.gsub(/"/, '\\"')}\"" when String then "\"#{value.gsub(/"/, '\\"')}\""
when Symbol then value when Symbol then value
......
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