Commit 54a319fe authored by Jose Ivan Vargas's avatar Jose Ivan Vargas

Merge branch '233736-add-reviewer-approval-rules' into 'master'

Display which approval rules match a given reviewer (FE)

See merge request gitlab-org/gitlab!46738
parents 71074380 ef89ff91
......@@ -49,6 +49,7 @@ function UsersSelect(currentUser, els, options = {}) {
options.todoStateFilter = $dropdown.data('todoStateFilter');
options.iid = $dropdown.data('iid');
options.issuableType = $dropdown.data('issuableType');
options.targetBranch = $dropdown.data('targetBranch');
const showNullUser = $dropdown.data('nullUser');
const defaultNullUser = $dropdown.data('nullUserDefault');
const showMenuAbove = $dropdown.data('showMenuAbove');
......@@ -582,7 +583,14 @@ function UsersSelect(currentUser, els, options = {}) {
img = `<img src='${avatar}' class='avatar avatar-inline m-0' width='32' />`;
}
return userSelect.renderRow(options.issuableType, user, selected, username, img);
return userSelect.renderRow(
options.issuableType,
user,
selected,
username,
img,
elsClassName,
);
},
});
});
......@@ -746,8 +754,17 @@ UsersSelect.prototype.users = function(query, options, callback) {
...getAjaxUsersSelectParams(options, AJAX_USERS_SELECT_PARAMS_MAP),
};
if (options.issuableType === 'merge_request') {
const isMergeRequest = options.issuableType === 'merge_request';
const isEditMergeRequest = !options.issuableType && (options.iid && options.targetBranch);
const isNewMergeRequest = !options.issuableType && (!options.iid && options.targetBranch);
if (isMergeRequest || isEditMergeRequest || isNewMergeRequest) {
params.merge_request_iid = options.iid || null;
params.approval_rules = true;
}
if (isNewMergeRequest) {
params.target_branch = options.targetBranch || null;
}
return axios.get(url, { params }).then(({ data }) => {
......@@ -762,7 +779,14 @@ UsersSelect.prototype.buildUrl = function(url) {
return url;
};
UsersSelect.prototype.renderRow = function(issuableType, user, selected, username, img) {
UsersSelect.prototype.renderRow = function(
issuableType,
user,
selected,
username,
img,
elsClassName,
) {
const tooltip = issuableType === 'merge_request' && !user.can_merge ? __('Cannot merge') : '';
const tooltipClass = tooltip ? `has-tooltip` : '';
const selectedClass = selected === true ? 'is-active' : '';
......@@ -776,10 +800,15 @@ UsersSelect.prototype.renderRow = function(issuableType, user, selected, usernam
<a href="#" class="dropdown-menu-user-link d-flex align-items-center ${linkClasses}" ${tooltipAttributes}>
${this.renderRowAvatar(issuableType, user, img)}
<span class="d-flex flex-column overflow-hidden">
<strong class="dropdown-menu-user-full-name">
<strong class="dropdown-menu-user-full-name gl-font-weight-bold">
${escape(user.name)}
</strong>
${username ? `<span class="dropdown-menu-user-username">${username}</span>` : ''}
${
username
? `<span class="dropdown-menu-user-username gl-text-gray-400">${username}</span>`
: ''
}
${this.renderApprovalRules(elsClassName, user.applicable_approval_rules)}
</span>
</a>
</li>
......@@ -802,4 +831,22 @@ UsersSelect.prototype.renderRowAvatar = function(issuableType, user, img) {
</span>`;
};
UsersSelect.prototype.renderApprovalRules = function(elsClassName, approvalRules = []) {
if (!gon.features?.reviewerApprovalRules || !elsClassName?.includes('reviewer')) {
return '';
}
const count = approvalRules.length;
const [rule] = approvalRules;
const countText = sprintf(__('(+%{count}&nbsp;rules)'), { count });
const renderApprovalRulesCount = count > 1 ? `<span class="ml-1">${countText}</span>` : '';
return count
? `<div class="gl-display-flex gl-font-sm">
<span class="gl-text-truncate" title="${rule.name}">${rule.name}</span>
${renderApprovalRulesCount}
</div>`
: '';
};
export default UsersSelect;
......@@ -14,6 +14,7 @@ class Projects::MergeRequests::CreationsController < Projects::MergeRequests::Ap
before_action do
push_frontend_feature_flag(:merge_request_reviewers, @project, default_enabled: true)
push_frontend_feature_flag(:mr_collapsed_approval_rules, @project)
push_frontend_feature_flag(:reviewer_approval_rules, @project)
end
def new
......
......@@ -53,6 +53,7 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
push_frontend_feature_flag(:vue_issuable_sidebar, @project.group)
push_frontend_feature_flag(:merge_request_reviewers, @project, default_enabled: true)
push_frontend_feature_flag(:mr_collapsed_approval_rules, @project)
push_frontend_feature_flag(:reviewer_approval_rules, @project)
end
around_action :allow_gitaly_ref_name_caching, only: [:index, :show, :discussions]
......
......@@ -55,7 +55,7 @@ module FormHelper
dropdown_data
end
def reviewers_dropdown_options(issuable_type)
def reviewers_dropdown_options(issuable_type, iid = nil, target_branch = nil)
dropdown_data = {
toggle_class: 'js-reviewer-search js-multiselect js-save-user-data',
title: 'Request review from',
......@@ -78,6 +78,14 @@ module FormHelper
}
}
if iid
dropdown_data[:data][:iid] = iid
end
if target_branch
dropdown_data[:data][:target_branch] = target_branch
end
if merge_request_supports_multiple_reviewers?
dropdown_data = multiple_reviewers_dropdown_options(dropdown_data)
end
......
......@@ -7,6 +7,6 @@
- if issuable.reviewers.empty?
= hidden_field_tag "#{issuable.to_ability_name}[reviewer_ids][]", 0, id: nil, data: { meta: '' }
= dropdown_tag(users_dropdown_label(issuable.reviewers), options: reviewers_dropdown_options(issuable.to_ability_name))
= dropdown_tag(users_dropdown_label(issuable.reviewers), options: reviewers_dropdown_options(issuable.to_ability_name, issuable.iid, issuable.target_branch))
- if Feature.enabled?(:mr_collapsed_approval_rules, @project)
= render_if_exists 'shared/issuable/approver_suggestion', issuable: issuable, presenter: presenter
---
name: reviewer_approval_rules
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/46738
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/293742
milestone: '13.7'
type: development
group: group::code review
default_enabled: false
......@@ -10,4 +10,45 @@ RSpec.describe 'Merge request > User edits MR with multiple reviewers' do
end
it_behaves_like 'multiple reviewers merge request', 'updates', 'Save changes'
context 'user approval rules', :js do
let(:rule_name) { 'some-custom-rule' }
let!(:mr_rule) { create(:approval_merge_request_rule, merge_request: merge_request, users: [user], name: rule_name, approvals_required: 1 )}
it 'is not shown in assignee dropdown' do
find('.js-assignee-search').click
wait_for_requests
page.within '.dropdown-menu-assignee' do
expect(page).not_to have_content(rule_name)
end
end
it 'is shown in reviewer dropdown' do
find('.js-reviewer-search').click
wait_for_requests
page.within '.dropdown-menu-reviewer' do
expect(page).to have_content(rule_name)
end
end
end
context 'when reviewer_approval_rules feature flag off' do
let(:rule_name) { 'some-custom-rule' }
let!(:mr_rule) { create(:approval_merge_request_rule, merge_request: merge_request, users: [user], name: rule_name, approvals_required: 1 )}
before do
stub_feature_flags(reviewer_approval_rules: false)
end
it 'is not shown in reviewer dropdown' do
find('.js-reviewer-search').click
wait_for_requests
page.within '.dropdown-menu-reviewer' do
expect(page).not_to have_content(rule_name)
end
end
end
end
......@@ -962,6 +962,9 @@ msgstr ""
msgid "(%{value}) has already been taken"
msgstr ""
msgid "(+%{count}&nbsp;rules)"
msgstr ""
msgid "(No changes)"
msgstr ""
......
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