Commit 8a2db291 authored by Kushal Pandya's avatar Kushal Pandya

Expose discussion and notes count

Exposes `userDiscussionsCount` & `userNotesCount`
props in Group Epics query.
parent 5fa9332d
......@@ -1802,6 +1802,16 @@ type BoardEpic implements CurrentUserTodos & Noteable {
"""
upvotes: Int!
"""
Number of user discussions in the epic
"""
userDiscussionsCount: Int!
"""
Number of user notes of the epic
"""
userNotesCount: Int!
"""
Permissions for the current user on the resource
"""
......@@ -7245,6 +7255,16 @@ type Epic implements CurrentUserTodos & Noteable {
"""
upvotes: Int!
"""
Number of user discussions in the epic
"""
userDiscussionsCount: Int!
"""
Number of user notes of the epic
"""
userNotesCount: Int!
"""
Permissions for the current user on the resource
"""
......
......@@ -4753,6 +4753,42 @@
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "userDiscussionsCount",
"description": "Number of user discussions in the epic",
"args": [
],
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "Int",
"ofType": null
}
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "userNotesCount",
"description": "Number of user notes of the epic",
"args": [
],
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "Int",
"ofType": null
}
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "userPermissions",
"description": "Permissions for the current user on the resource",
......@@ -20045,6 +20081,42 @@
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "userDiscussionsCount",
"description": "Number of user discussions in the epic",
"args": [
],
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "Int",
"ofType": null
}
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "userNotesCount",
"description": "Number of user notes of the epic",
"args": [
],
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "Int",
"ofType": null
}
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "userPermissions",
"description": "Permissions for the current user on the resource",
......@@ -290,6 +290,8 @@ Represents an epic on an issue board.
| `title` | String | Title of the epic |
| `updatedAt` | Time | Timestamp of when the epic was updated |
| `upvotes` | Int! | Number of upvotes the epic has received |
| `userDiscussionsCount` | Int! | Number of user discussions in the epic |
| `userNotesCount` | Int! | Number of user notes of the epic |
| `userPermissions` | EpicPermissions! | Permissions for the current user on the resource |
| `userPreferences` | BoardEpicUserPreferences | User preferences for the epic on the issue board |
| `webPath` | String! | Web path of the epic |
......@@ -1189,6 +1191,8 @@ Represents an epic.
| `title` | String | Title of the epic |
| `updatedAt` | Time | Timestamp of when the epic was updated |
| `upvotes` | Int! | Number of upvotes the epic has received |
| `userDiscussionsCount` | Int! | Number of user discussions in the epic |
| `userNotesCount` | Int! | Number of user notes of the epic |
| `userPermissions` | EpicPermissions! | Permissions for the current user on the resource |
| `webPath` | String! | Web path of the epic |
| `webUrl` | String! | Web URL of the epic |
......
......@@ -66,6 +66,11 @@ module Types
field :downvotes, GraphQL::INT_TYPE, null: false,
description: 'Number of downvotes the epic has received'
field :user_notes_count, GraphQL::INT_TYPE, null: false,
description: 'Number of user notes of the epic'
field :user_discussions_count, GraphQL::INT_TYPE, null: false,
description: 'Number of user discussions in the epic'
field :closed_at, Types::TimeType, null: true,
description: 'Timestamp of when the epic was closed'
field :created_at, Types::TimeType, null: true,
......@@ -144,6 +149,26 @@ module Types
Epics::DescendantCountService.new(epic, ctx[:current_user])
end
def user_notes_count
BatchLoader::GraphQL.for(object.id).batch(key: :epic_user_notes_count) do |ids, loader, args|
counts = Note.count_for_collection(ids, 'Epic').index_by(&:noteable_id)
ids.each do |id|
loader.call(id, counts[id]&.count || 0)
end
end
end
def user_discussions_count
BatchLoader::GraphQL.for(object.id).batch(key: :epic_user_discussions_count) do |ids, loader, args|
counts = Note.count_for_collection(ids, 'Epic', 'COUNT(DISTINCT discussion_id) as count').index_by(&:noteable_id)
ids.each do |id|
loader.call(id, counts[id]&.count || 0)
end
end
end
def has_children?
Gitlab::Graphql::Aggregations::Epics::LazyEpicAggregate.new(context, object.id, COUNT) do |node, _aggregate_object|
node.children.any?
......
---
title: Expose discussion and notes count in Epic query
merge_request: 47409
author:
type: added
......@@ -11,8 +11,8 @@ RSpec.describe GitlabSchema.types['Epic'] do
closed_at created_at updated_at children has_children has_issues has_parent
web_path web_url relation_path reference issues user_permissions
notes discussions relative_position subscribed participants
descendant_counts descendant_weight_sum upvotes downvotes health_status
current_user_todos
descendant_counts descendant_weight_sum upvotes downvotes
user_notes_count user_discussions_count health_status current_user_todos
]
end
......
......@@ -206,6 +206,47 @@ RSpec.describe 'Epics through GroupQuery' do
end
end
describe 'N+1 query checks' do
let(:epic_a) { create(:epic, group: group) }
let(:epic_b) { create(:epic, group: group) }
let(:epics) { [epic_a, epic_b] }
let(:extra_iid_for_second_query) { epic_b.iid.to_s }
let(:search_params) { { iids: [epic_a.iid.to_s] } }
def execute_query
query = graphql_query_for(
:group,
{ full_path: group.full_path },
query_graphql_field(:epics, search_params, [
query_graphql_field(:nodes, nil, requested_fields)
])
)
post_graphql(query, current_user: user)
end
context 'when requesting `user_notes_count`' do
let(:requested_fields) { [:user_notes_count] }
before do
create_list(:note_on_epic, 2, noteable: epic_a)
create(:note_on_epic, noteable: epic_b)
end
include_examples 'N+1 query check'
end
context 'when requesting `user_discussions_count`' do
let(:requested_fields) { [:user_discussions_count] }
before do
create_list(:note_on_epic, 2, noteable: epic_a)
create(:note_on_epic, noteable: epic_b)
end
include_examples 'N+1 query check'
end
end
def expect_array_response(items)
expect(response).to have_gitlab_http_status(:success)
expect(epics_data).to be_an Array
......
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