Skip to content
Snippets Groups Projects
Verified Commit 87c88c15 authored by Heinrich Lee Yu's avatar Heinrich Lee Yu
Browse files

Expose GraphQL field for sidebar counts

This makes the backend expose the GraphQL field to use for the menu
item's count so that the frontend won't need to keep a mapping of field
names to menu item IDs.
parent fcdac712
No related branches found
No related tags found
1 merge request!171827Expose GraphQL field name for sidebar counts
Showing
with 157 additions and 36 deletions
...@@ -49,10 +49,16 @@ def pill_count ...@@ -49,10 +49,16 @@ def pill_count
end end
end end
override :pill_count_field
def pill_count_field
'openEpicsCount' if Feature.enabled?(:async_sidebar_counts, context.group.root_ancestor)
end
override :serialize_as_menu_item_args override :serialize_as_menu_item_args
def serialize_as_menu_item_args def serialize_as_menu_item_args
super.merge({ super.merge({
pill_count: pill_count, pill_count: pill_count,
pill_count_field: pill_count_field,
has_pill: has_pill?, has_pill: has_pill?,
super_sidebar_parent: ::Sidebars::Groups::SuperSidebarMenus::PlanMenu, super_sidebar_parent: ::Sidebars::Groups::SuperSidebarMenus::PlanMenu,
item_id: :group_epic_list item_id: :group_epic_list
......
...@@ -43,9 +43,26 @@ ...@@ -43,9 +43,26 @@
{ {
item_id: :group_epic_list, item_id: :group_epic_list,
pill_count: menu.pill_count, pill_count: menu.pill_count,
pill_count_field: menu.pill_count_field,
has_pill: menu.has_pill?, has_pill: menu.has_pill?,
super_sidebar_parent: Sidebars::Groups::SuperSidebarMenus::PlanMenu super_sidebar_parent: Sidebars::Groups::SuperSidebarMenus::PlanMenu
} }
end end
end end
describe '#pill_count_field' do
it 'returns the correct GraphQL field name' do
expect(menu.pill_count_field).to eq('openEpicsCount')
end
context 'when async_sidebar_counts feature flag is disabled' do
before do
stub_feature_flags(async_sidebar_counts: false)
end
it 'returns nil' do
expect(menu.pill_count_field).to be_nil
end
end
end
end end
...@@ -13,9 +13,13 @@ def has_pill? ...@@ -13,9 +13,13 @@ def has_pill?
# In this method we will need to provide the query # In this method we will need to provide the query
# to retrieve the elements count # to retrieve the elements count
def pill_count def pill_count; end
raise NotImplementedError
end # The GraphQL field name from `SidebarType` that will be used
# as the pill count for this menu item.
# This is used when the count is expensive and we want to fetch it separately
# from GraphQL.
def pill_count_field; end
def pill_html_options def pill_html_options
{} {}
......
...@@ -50,6 +50,11 @@ def pill_count ...@@ -50,6 +50,11 @@ def pill_count
nil nil
end end
override :pill_count_field
def pill_count_field
'openIssuesCount' if Feature.enabled?(:async_sidebar_counts, context.group.root_ancestor)
end
override :pill_html_options override :pill_html_options
def pill_html_options def pill_html_options
{ {
...@@ -62,6 +67,7 @@ def serialize_as_menu_item_args ...@@ -62,6 +67,7 @@ def serialize_as_menu_item_args
super.merge({ super.merge({
active_routes: list_menu_item.active_routes, active_routes: list_menu_item.active_routes,
pill_count: pill_count, pill_count: pill_count,
pill_count_field: pill_count_field,
has_pill: has_pill?, has_pill: has_pill?,
super_sidebar_parent: ::Sidebars::Groups::SuperSidebarMenus::PlanMenu, super_sidebar_parent: ::Sidebars::Groups::SuperSidebarMenus::PlanMenu,
item_id: :group_issue_list item_id: :group_issue_list
......
...@@ -43,6 +43,11 @@ def pill_count ...@@ -43,6 +43,11 @@ def pill_count
end end
end end
override :pill_count_field
def pill_count_field
'openMergeRequestsCount' if Feature.enabled?(:async_sidebar_counts, context.group.root_ancestor)
end
override :pill_html_options override :pill_html_options
def pill_html_options def pill_html_options
{ {
...@@ -59,6 +64,7 @@ def active_routes ...@@ -59,6 +64,7 @@ def active_routes
def serialize_as_menu_item_args def serialize_as_menu_item_args
super.merge({ super.merge({
pill_count: pill_count, pill_count: pill_count,
pill_count_field: pill_count_field,
has_pill: has_pill?, has_pill: has_pill?,
super_sidebar_parent: ::Sidebars::Groups::SuperSidebarMenus::CodeMenu, super_sidebar_parent: ::Sidebars::Groups::SuperSidebarMenus::CodeMenu,
item_id: :group_merge_request_list item_id: :group_merge_request_list
......
...@@ -89,9 +89,10 @@ def serialize_for_super_sidebar ...@@ -89,9 +89,10 @@ def serialize_for_super_sidebar
link: link, link: link,
is_active: is_active, is_active: is_active,
pill_count: has_pill? ? pill_count : nil, pill_count: has_pill? ? pill_count : nil,
pill_count_field: has_pill? ? pill_count_field : nil,
items: items, items: items,
separated: separated? separated: separated?
} }.compact
end end
# Returns an array of renderable menu entries, # Returns an array of renderable menu entries,
......
...@@ -4,11 +4,11 @@ module Sidebars ...@@ -4,11 +4,11 @@ module Sidebars
class MenuItem class MenuItem
include ::Sidebars::Concerns::LinkWithHtmlOptions include ::Sidebars::Concerns::LinkWithHtmlOptions
attr_reader :title, :link, :active_routes, :item_id, :container_html_options, :sprite_icon, :sprite_icon_html_options, :has_pill, :pill_count, :super_sidebar_parent, :avatar, :entity_id attr_reader :title, :link, :active_routes, :item_id, :container_html_options, :sprite_icon, :sprite_icon_html_options, :has_pill, :pill_count, :pill_count_field, :super_sidebar_parent, :avatar, :entity_id
alias_method :has_pill?, :has_pill alias_method :has_pill?, :has_pill
# rubocop: disable Metrics/ParameterLists # rubocop: disable Metrics/ParameterLists
def initialize(title:, link:, active_routes:, item_id: nil, container_html_options: {}, sprite_icon: nil, sprite_icon_html_options: {}, has_pill: false, pill_count: nil, super_sidebar_parent: nil, avatar: nil, entity_id: nil) def initialize(title:, link:, active_routes:, item_id: nil, container_html_options: {}, sprite_icon: nil, sprite_icon_html_options: {}, has_pill: false, pill_count: nil, pill_count_field: nil, super_sidebar_parent: nil, avatar: nil, entity_id: nil)
@title = title @title = title
@link = link @link = link
@active_routes = active_routes @active_routes = active_routes
...@@ -20,6 +20,7 @@ def initialize(title:, link:, active_routes:, item_id: nil, container_html_optio ...@@ -20,6 +20,7 @@ def initialize(title:, link:, active_routes:, item_id: nil, container_html_optio
@entity_id = entity_id @entity_id = entity_id
@has_pill = has_pill @has_pill = has_pill
@pill_count = pill_count @pill_count = pill_count
@pill_count_field = pill_count_field
@super_sidebar_parent = super_sidebar_parent @super_sidebar_parent = super_sidebar_parent
end end
# rubocop: enable Metrics/ParameterLists # rubocop: enable Metrics/ParameterLists
...@@ -38,13 +39,14 @@ def serialize_for_super_sidebar ...@@ -38,13 +39,14 @@ def serialize_for_super_sidebar
link: link, link: link,
active_routes: active_routes, active_routes: active_routes,
pill_count: has_pill ? pill_count : nil, pill_count: has_pill ? pill_count : nil,
pill_count_field: has_pill ? pill_count_field : nil,
link_classes: container_html_options[:class] link_classes: container_html_options[:class]
# Check whether support is needed for the following properties, # Check whether support is needed for the following properties,
# in order to get feature parity with the HAML renderer # in order to get feature parity with the HAML renderer
# https://gitlab.com/gitlab-org/gitlab/-/issues/391864 # https://gitlab.com/gitlab-org/gitlab/-/issues/391864
# #
# container_html_options # container_html_options
} }.compact
end end
end end
end end
...@@ -57,6 +57,11 @@ def pill_count ...@@ -57,6 +57,11 @@ def pill_count
end end
end end
override :pill_count_field
def pill_count_field
'openIssuesCount' if Feature.enabled?(:async_sidebar_counts, context.project.root_ancestor)
end
override :pill_html_options override :pill_html_options
def pill_html_options def pill_html_options
{ {
...@@ -68,6 +73,7 @@ def pill_html_options ...@@ -68,6 +73,7 @@ def pill_html_options
def serialize_as_menu_item_args def serialize_as_menu_item_args
super.merge({ super.merge({
pill_count: pill_count, pill_count: pill_count,
pill_count_field: pill_count_field,
has_pill: has_pill?, has_pill: has_pill?,
super_sidebar_parent: ::Sidebars::Projects::SuperSidebarMenus::PlanMenu, super_sidebar_parent: ::Sidebars::Projects::SuperSidebarMenus::PlanMenu,
item_id: :project_issue_list item_id: :project_issue_list
......
...@@ -45,6 +45,11 @@ def pill_count ...@@ -45,6 +45,11 @@ def pill_count
format_cached_count(1000, count) format_cached_count(1000, count)
end end
override :pill_count_field
def pill_count_field
'openMergeRequestsCount' if Feature.enabled?(:async_sidebar_counts, context.project.root_ancestor)
end
override :pill_html_options override :pill_html_options
def pill_html_options def pill_html_options
{ {
...@@ -65,6 +70,7 @@ def active_routes ...@@ -65,6 +70,7 @@ def active_routes
def serialize_as_menu_item_args def serialize_as_menu_item_args
super.merge({ super.merge({
pill_count: pill_count, pill_count: pill_count,
pill_count_field: pill_count_field,
has_pill: has_pill?, has_pill: has_pill?,
super_sidebar_parent: ::Sidebars::Projects::SuperSidebarMenus::CodeMenu, super_sidebar_parent: ::Sidebars::Projects::SuperSidebarMenus::CodeMenu,
item_id: :project_merge_request_list item_id: :project_merge_request_list
......
...@@ -52,6 +52,22 @@ ...@@ -52,6 +52,22 @@
let(:count_service) { ::Groups::OpenIssuesCountService } let(:count_service) { ::Groups::OpenIssuesCountService }
end end
describe '#pill_count_field' do
it 'returns the correct GraphQL field name' do
expect(menu.pill_count_field).to eq('openIssuesCount')
end
context 'when async_sidebar_counts feature flag is disabled' do
before do
stub_feature_flags(async_sidebar_counts: false)
end
it 'returns nil' do
expect(menu.pill_count_field).to be_nil
end
end
end
context 'when count query times out' do context 'when count query times out' do
let(:count_service) { ::Groups::OpenIssuesCountService } let(:count_service) { ::Groups::OpenIssuesCountService }
...@@ -78,6 +94,7 @@ ...@@ -78,6 +94,7 @@
item_id: :group_issue_list, item_id: :group_issue_list,
active_routes: { path: 'groups#issues' }, active_routes: { path: 'groups#issues' },
pill_count: menu.pill_count, pill_count: menu.pill_count,
pill_count_field: menu.pill_count_field,
has_pill: menu.has_pill?, has_pill: menu.has_pill?,
super_sidebar_parent: Sidebars::Groups::SuperSidebarMenus::PlanMenu super_sidebar_parent: Sidebars::Groups::SuperSidebarMenus::PlanMenu
} }
......
...@@ -39,9 +39,26 @@ ...@@ -39,9 +39,26 @@
{ {
item_id: :group_merge_request_list, item_id: :group_merge_request_list,
pill_count: menu.pill_count, pill_count: menu.pill_count,
pill_count_field: menu.pill_count_field,
has_pill: menu.has_pill?, has_pill: menu.has_pill?,
super_sidebar_parent: Sidebars::Groups::SuperSidebarMenus::CodeMenu super_sidebar_parent: Sidebars::Groups::SuperSidebarMenus::CodeMenu
} }
end end
end end
describe '#pill_count_field' do
it 'returns the correct GraphQL field name' do
expect(menu.pill_count_field).to eq('openMergeRequestsCount')
end
context 'when async_sidebar_counts feature flag is disabled' do
before do
stub_feature_flags(async_sidebar_counts: false)
end
it 'returns nil' do
expect(menu.pill_count_field).to be_nil
end
end
end
end end
...@@ -34,5 +34,14 @@ ...@@ -34,5 +34,14 @@
expect(subject[:avatar]).to be('/avatar.png') expect(subject[:avatar]).to be('/avatar.png')
expect(subject[:entity_id]).to be(123) expect(subject[:entity_id]).to be(123)
end end
context 'with pill data' do
let(:extra) { { has_pill: true, pill_count: '5', pill_count_field: 'countField' } }
it 'includes pill count data' do
expect(subject[:pill_count]).to eq('5')
expect(subject[:pill_count_field]).to eq('countField')
end
end
end end
end end
...@@ -52,37 +52,26 @@ ...@@ -52,37 +52,26 @@
expect(menu.serialize_for_super_sidebar).to eq( expect(menu.serialize_for_super_sidebar).to eq(
{ {
title: "Title", title: "Title",
icon: nil,
id: 'menu', id: 'menu',
avatar: nil,
avatar_shape: 'rect', avatar_shape: 'rect',
entity_id: nil,
link: "foo2", link: "foo2",
is_active: true, is_active: true,
pill_count: nil,
separated: false, separated: false,
items: [ items: [
{ {
id: 'id1', id: 'id1',
title: "Is active", title: "Is active",
icon: nil,
avatar: '/avatar.png', avatar: '/avatar.png',
entity_id: 123, entity_id: 123,
link: "foo2", link: "foo2",
is_active: true, is_active: true
pill_count: nil,
link_classes: nil
}, },
{ {
id: 'id2', id: 'id2',
title: "Not active", title: "Not active",
icon: nil,
avatar: nil,
entity_id: nil,
link: "foo3", link: "foo3",
is_active: false, is_active: false,
pill_count: 10, pill_count: 10
link_classes: nil
} }
] ]
}) })
...@@ -94,18 +83,29 @@ ...@@ -94,18 +83,29 @@
expect(menu.serialize_for_super_sidebar).to eq( expect(menu.serialize_for_super_sidebar).to eq(
{ {
title: "Title", title: "Title",
icon: nil,
id: 'menu', id: 'menu',
avatar: nil,
avatar_shape: 'rect', avatar_shape: 'rect',
entity_id: nil,
link: nil,
is_active: false, is_active: false,
pill_count: 'foo', pill_count: 'foo',
separated: false, separated: false,
items: [] items: []
}) })
end end
it 'returns pill_count_field if defined' do
allow(menu).to receive(:has_pill?).and_return(true)
allow(menu).to receive(:pill_count_field).and_return('foo')
expect(menu.serialize_for_super_sidebar).to eq(
{
title: "Title",
id: 'menu',
avatar_shape: 'rect',
is_active: false,
pill_count_field: 'foo',
separated: false,
items: []
})
end
end end
describe '#serialize_as_menu_item_args' do describe '#serialize_as_menu_item_args' do
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
item_id: :project_issue_list, item_id: :project_issue_list,
active_routes: { path: %w[projects/issues#index projects/issues#show projects/issues#new] }, active_routes: { path: %w[projects/issues#index projects/issues#show projects/issues#new] },
pill_count: menu.pill_count, pill_count: menu.pill_count,
pill_count_field: menu.pill_count_field,
has_pill: menu.has_pill?, has_pill: menu.has_pill?,
super_sidebar_parent: Sidebars::Projects::SuperSidebarMenus::PlanMenu super_sidebar_parent: Sidebars::Projects::SuperSidebarMenus::PlanMenu
} }
...@@ -100,6 +101,22 @@ ...@@ -100,6 +101,22 @@
end end
end end
describe '#pill_count_field' do
it 'returns the correct GraphQL field name' do
expect(subject.pill_count_field).to eq('openIssuesCount')
end
context 'when async_sidebar_counts feature flag is disabled' do
before do
stub_feature_flags(async_sidebar_counts: false)
end
it 'returns nil' do
expect(subject.pill_count_field).to be_nil
end
end
end
describe 'Menu Items' do describe 'Menu Items' do
subject { described_class.new(context).renderable_items.index { |e| e.item_id == item_id } } subject { described_class.new(context).renderable_items.index { |e| e.item_id == item_id } }
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
{ {
item_id: :project_merge_request_list, item_id: :project_merge_request_list,
pill_count: menu.pill_count, pill_count: menu.pill_count,
pill_count_field: menu.pill_count_field,
has_pill: menu.has_pill?, has_pill: menu.has_pill?,
super_sidebar_parent: Sidebars::Projects::SuperSidebarMenus::CodeMenu super_sidebar_parent: Sidebars::Projects::SuperSidebarMenus::CodeMenu
} }
...@@ -98,4 +99,20 @@ ...@@ -98,4 +99,20 @@
end end
end end
end end
describe '#pill_count_field' do
it 'returns the correct GraphQL field name' do
expect(subject.pill_count_field).to eq('openMergeRequestsCount')
end
context 'when async_sidebar_counts feature flag is disabled' do
before do
stub_feature_flags(async_sidebar_counts: false)
end
it 'returns nil' do
expect(subject.pill_count_field).to be_nil
end
end
end
end end
...@@ -22,24 +22,14 @@ ...@@ -22,24 +22,14 @@
{ {
id: 'id1', id: 'id1',
title: "Is active", title: "Is active",
icon: nil,
avatar: nil,
entity_id: nil,
link: "foo2", link: "foo2",
is_active: true, is_active: true
pill_count: nil,
link_classes: nil
}, },
{ {
id: 'id2', id: 'id2',
title: "Not active", title: "Not active",
icon: nil,
avatar: nil,
entity_id: nil,
link: "foo3", link: "foo3",
is_active: false, is_active: false
pill_count: nil,
link_classes: nil
} }
] ]
) )
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment