diff --git a/app/assets/javascripts/sidebar/components/reviewers/uncollapsed_reviewer_list.vue b/app/assets/javascripts/sidebar/components/reviewers/uncollapsed_reviewer_list.vue
index 2ae4a114b36101af9d1b05ef21a31bccd70de27d..e82a271d007006f3e77de2393d5fd1b57698efc0 100644
--- a/app/assets/javascripts/sidebar/components/reviewers/uncollapsed_reviewer_list.vue
+++ b/app/assets/javascripts/sidebar/components/reviewers/uncollapsed_reviewer_list.vue
@@ -75,9 +75,9 @@ export default {
:root-path="rootPath"
:issuable-type="issuableType"
>
-
-
{{ user.name }}
-
{{ username }}
+
+
{{ user.name }}
+
{{ username }}
diff --git a/app/helpers/form_helper.rb b/app/helpers/form_helper.rb
index 3dde5afcb923544e3b1175ecafe0dcb2dcfaedf2..8a8d708b0b24dc9f55d2a65a44aa5cdb0a6cbcde 100644
--- a/app/helpers/form_helper.rb
+++ b/app/helpers/form_helper.rb
@@ -56,7 +56,7 @@ def assignees_dropdown_options(issuable_type)
end
def reviewers_dropdown_options(issuable_type)
- {
+ dropdown_data = {
toggle_class: 'js-reviewer-search js-multiselect js-save-user-data',
title: 'Request review from',
filter: true,
@@ -69,13 +69,20 @@ def reviewers_dropdown_options(issuable_type)
project_id: (@target_project || @project)&.id,
field_name: "#{issuable_type}[reviewer_ids][]",
default_label: 'Unassigned',
- 'dropdown-header': 'Reviewer(s)',
+ 'max-select': 1,
+ 'dropdown-header': 'Reviewer',
multi_select: true,
'input-meta': 'name',
'always-show-selectbox': true,
current_user_info: UserSerializer.new.represent(current_user)
}
}
+
+ if merge_request_supports_multiple_reviewers?
+ dropdown_data = multiple_reviewers_dropdown_options(dropdown_data)
+ end
+
+ dropdown_data
end
# Overwritten
@@ -88,6 +95,11 @@ def merge_request_supports_multiple_assignees?
false
end
+ # Overwritten
+ def merge_request_supports_multiple_reviewers?
+ false
+ end
+
private
def multiple_assignees_dropdown_options(options)
@@ -99,6 +111,16 @@ def multiple_assignees_dropdown_options(options)
new_options
end
+
+ def multiple_reviewers_dropdown_options(options)
+ new_options = options.dup
+
+ new_options[:title] = _('Select reviewer(s)')
+ new_options[:data][:'dropdown-header'] = _('Reviewer(s)')
+ new_options[:data].delete(:'max-select')
+
+ new_options
+ end
end
FormHelper.prepend_if_ee('::EE::FormHelper')
diff --git a/ee/app/helpers/ee/form_helper.rb b/ee/app/helpers/ee/form_helper.rb
index ba0ec340d1593a18b7be07d57f6d6288599b1b8d..315947e743d17c48afdb62010786a3f12fa3ebfa 100644
--- a/ee/app/helpers/ee/form_helper.rb
+++ b/ee/app/helpers/ee/form_helper.rb
@@ -9,5 +9,9 @@ def issue_supports_multiple_assignees?
def merge_request_supports_multiple_assignees?
@merge_request&.allows_multiple_assignees?
end
+
+ def merge_request_supports_multiple_reviewers?
+ @merge_request&.allows_multiple_reviewers?
+ end
end
end
diff --git a/ee/changelogs/unreleased/246905-only-allow-multiple-reviewers-in-paid-tiers.yml b/ee/changelogs/unreleased/246905-only-allow-multiple-reviewers-in-paid-tiers.yml
new file mode 100644
index 0000000000000000000000000000000000000000..6c9edc5c86ed1405638e8df29b4fb4998df9b3ec
--- /dev/null
+++ b/ee/changelogs/unreleased/246905-only-allow-multiple-reviewers-in-paid-tiers.yml
@@ -0,0 +1,5 @@
+---
+title: Only allow multiple reviewers in paid tiers
+merge_request: 44097
+author:
+type: changed
diff --git a/ee/spec/features/merge_request/user_creates_multiple_reviewers_mr_spec.rb b/ee/spec/features/merge_request/user_creates_multiple_reviewers_mr_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..b390d3e7130a827cb8817d89726f3c279138d39f
--- /dev/null
+++ b/ee/spec/features/merge_request/user_creates_multiple_reviewers_mr_spec.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Merge request > User creates MR with multiple reviewers' do
+ include_context 'merge request create context'
+
+ before do
+ stub_licensed_features(multiple_merge_request_reviewers: true)
+ end
+
+ it_behaves_like 'multiple reviewers merge request', 'creates', 'Submit merge request'
+end
diff --git a/ee/spec/features/merge_request/user_edits_multiple_reviewers_mr_spec.rb b/ee/spec/features/merge_request/user_edits_multiple_reviewers_mr_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..2ebb76b01a29d962d13cf5e36bc41ee6a4c37af7
--- /dev/null
+++ b/ee/spec/features/merge_request/user_edits_multiple_reviewers_mr_spec.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Merge request > User edits MR with multiple reviewers' do
+ include_context 'merge request edit context'
+
+ before do
+ stub_licensed_features(multiple_merge_request_reviewers: true)
+ end
+
+ it_behaves_like 'multiple reviewers merge request', 'updates', 'Save changes'
+end
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index 2b918a14d334784701177731f780ea4b02b56ada..f13d0309825e2b4c42dad86b654efad28a3edf4d 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -23168,6 +23168,9 @@ msgstr ""
msgid "Select required regulatory standard"
msgstr ""
+msgid "Select reviewer(s)"
+msgstr ""
+
msgid "Select shards to replicate"
msgstr ""
diff --git a/spec/support/shared_examples/features/multiple_reviewers_mr_shared_examples.rb b/spec/support/shared_examples/features/multiple_reviewers_mr_shared_examples.rb
new file mode 100644
index 0000000000000000000000000000000000000000..48cde90bd9b4c1db16f4d44794c14ce452a7c71e
--- /dev/null
+++ b/spec/support/shared_examples/features/multiple_reviewers_mr_shared_examples.rb
@@ -0,0 +1,47 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples 'multiple reviewers merge request' do |action, save_button_title|
+ it "#{action} a MR with multiple reviewers", :js do
+ find('.js-reviewer-search').click
+ page.within '.dropdown-menu-user' do
+ click_link user.name
+ click_link user2.name
+ end
+
+ # Extra click needed in order to toggle the dropdown
+ find('.js-reviewer-search').click
+
+ expect(all('input[name="merge_request[reviewer_ids][]"]', visible: false).map(&:value))
+ .to match_array([user.id.to_s, user2.id.to_s])
+
+ page.within '.js-reviewer-search' do
+ expect(page).to have_content "#{user2.name} + 1 more"
+ end
+
+ click_button save_button_title
+
+ page.within '.issuable-sidebar' do
+ page.within '.reviewer' do
+ expect(page).to have_content '2 Reviewers'
+
+ click_link 'Edit'
+
+ expect(page).to have_content user.name
+ expect(page).to have_content user2.name
+ end
+ end
+
+ page.within '.dropdown-menu-user' do
+ click_link user.name
+ end
+
+ page.within '.issuable-sidebar' do
+ page.within '.reviewer' do
+ # Closing dropdown to persist
+ click_link 'Edit'
+
+ expect(page).to have_content user2.name
+ end
+ end
+ end
+end