Commit 875dfa83 authored by Phil Hughes's avatar Phil Hughes

Add section names to code owners approvals list

Adds the name of the section for code owners in the merge request
widgets approvals list.

https://gitlab.com/gitlab-org/gitlab/-/issues/215050
parent dba80652
<script> <script>
import { uniqueId } from 'lodash'; import { uniqueId, orderBy } from 'lodash';
import ApprovalCheckRulePopover from 'ee/approvals/components/approval_check_rule_popover.vue'; import ApprovalCheckRulePopover from 'ee/approvals/components/approval_check_rule_popover.vue';
import EmptyRuleName from 'ee/approvals/components/empty_rule_name.vue'; import EmptyRuleName from 'ee/approvals/components/empty_rule_name.vue';
import { RULE_TYPE_CODE_OWNER, RULE_TYPE_ANY_APPROVER } from 'ee/approvals/constants'; import { RULE_TYPE_CODE_OWNER, RULE_TYPE_ANY_APPROVER } from 'ee/approvals/constants';
import { sprintf, __ } from '~/locale'; import { sprintf, __, s__ } from '~/locale';
import UserAvatarList from '~/vue_shared/components/user_avatar/user_avatar_list.vue'; import UserAvatarList from '~/vue_shared/components/user_avatar/user_avatar_list.vue';
import ApprovedIcon from './approved_icon.vue'; import ApprovedIcon from './approved_icon.vue';
...@@ -41,9 +41,13 @@ export default { ...@@ -41,9 +41,13 @@ export default {
{ {
id: uniqueId(), id: uniqueId(),
title: __('Code Owners'), title: __('Code Owners'),
rules: this.approvalRules rules: orderBy(
.filter(rule => rule.rule_type === RULE_TYPE_CODE_OWNER) this.approvalRules
.map(rule => ({ ...rule, nameClass: 'monospace' })), .filter(rule => rule.rule_type === RULE_TYPE_CODE_OWNER)
.map(rule => ({ ...rule, nameClass: 'monospace' })),
[o => o.section === 'codeowners', 'name', 'section'],
['desc', 'asc', 'asc'],
),
}, },
].filter(x => x.rules.length); ].filter(x => x.rules.length);
}, },
...@@ -77,6 +81,9 @@ export default { ...@@ -77,6 +81,9 @@ export default {
name: rule.name, name: rule.name,
}); });
}, },
sectionNameLabel(rule) {
return sprintf(s__('Approvals|Section: %section'), { section: rule.section });
},
}, },
ruleTypeAnyApprover: RULE_TYPE_ANY_APPROVER, ruleTypeAnyApprover: RULE_TYPE_ANY_APPROVER,
}; };
...@@ -103,12 +110,22 @@ export default { ...@@ -103,12 +110,22 @@ export default {
<tr v-for="rule in rules" :key="rule.id"> <tr v-for="rule in rules" :key="rule.id">
<td class="w-0"><approved-icon :is-approved="rule.approved" /></td> <td class="w-0"><approved-icon :is-approved="rule.approved" /></td>
<td :colspan="rule.rule_type === $options.ruleTypeAnyApprover ? 2 : 1"> <td :colspan="rule.rule_type === $options.ruleTypeAnyApprover ? 2 : 1">
<div class="d-none d-sm-block js-name" :class="rule.nameClass"> <div class="d-none d-sm-block js-name">
<empty-rule-name <empty-rule-name
v-if="rule.rule_type === $options.ruleTypeAnyApprover" v-if="rule.rule_type === $options.ruleTypeAnyApprover"
:eligible-approvers-docs-path="eligibleApproversDocsPath" :eligible-approvers-docs-path="eligibleApproversDocsPath"
/> />
<span v-else>{{ rule.name }}</span> <span v-else>
<span
v-if="rule.section && rule.section !== 'codeowners'"
:aria-label="sectionNameLabel(rule)"
class="text-muted small d-block"
data-testid="rule-section"
>
{{ rule.section }}
</span>
<span :class="rule.nameClass">{{ rule.name }}</span>
</span>
<approval-check-rule-popover <approval-check-rule-popover
:rule="rule" :rule="rule"
:security-approvals-help-page-path="securityApprovalsHelpPagePath" :security-approvals-help-page-path="securityApprovalsHelpPagePath"
......
...@@ -40,13 +40,14 @@ const testRuleFallback = () => ({ ...@@ -40,13 +40,14 @@ const testRuleFallback = () => ({
}); });
const testRuleCodeOwner = () => ({ const testRuleCodeOwner = () => ({
id: '*.js', id: '*.js',
name: '', name: '*.js',
fallback: true, fallback: true,
approvals_required: 3, approvals_required: 3,
approved_by: [{ id: 1 }, { id: 2 }], approved_by: [{ id: 1 }, { id: 2 }],
approvers: [], approvers: [],
approved: false, approved: false,
rule_type: 'code_owner', rule_type: 'code_owner',
section: 'Frontend',
}); });
const testRules = () => [testRuleApproved(), testRuleUnapproved(), testRuleOptional()]; const testRules = () => [testRuleApproved(), testRuleUnapproved(), testRuleOptional()];
...@@ -286,11 +287,21 @@ describe('EE MRWidget approvals list', () => { ...@@ -286,11 +287,21 @@ describe('EE MRWidget approvals list', () => {
describe('when code owner rule', () => { describe('when code owner rule', () => {
const rule = testRuleCodeOwner(); const rule = testRuleCodeOwner();
const ruleDefaultCodeOwners = {
...testRuleCodeOwner(),
id: 2,
section: 'codeowners',
};
const ruleDocsSection = {
...testRuleCodeOwner(),
id: 1,
section: 'Docs',
};
let row; let row;
beforeEach(() => { beforeEach(() => {
createComponent({ createComponent({
approvalRules: [rule], approvalRules: [rule, ruleDefaultCodeOwners, ruleDocsSection],
}); });
row = findRows().at(1); row = findRows().at(1);
}); });
...@@ -304,8 +315,15 @@ describe('EE MRWidget approvals list', () => { ...@@ -304,8 +315,15 @@ describe('EE MRWidget approvals list', () => {
it('renders the name in a monospace font', () => { it('renders the name in a monospace font', () => {
const codeOwnerRow = findRowElement(row, 'name'); const codeOwnerRow = findRowElement(row, 'name');
expect(codeOwnerRow.classes('monospace')).toEqual(true); expect(codeOwnerRow.find('.monospace').exists()).toEqual(true);
expect(codeOwnerRow.text()).toEqual(rule.name); expect(codeOwnerRow.text()).toContain(rule.name);
});
it('renders code owner section name', () => {
const ruleSection = wrapper.findAll('[data-testid="rule-section"]');
expect(ruleSection.at(0).text()).toEqual(ruleDocsSection.section);
expect(ruleSection.at(1).text()).toEqual(rule.section);
}); });
}); });
}); });
...@@ -2834,6 +2834,9 @@ msgstr "" ...@@ -2834,6 +2834,9 @@ msgstr ""
msgid "ApprovalRule|e.g. QA, Security, etc." msgid "ApprovalRule|e.g. QA, Security, etc."
msgstr "" msgstr ""
msgid "Approvals|Section: %section"
msgstr ""
msgid "Approve" msgid "Approve"
msgstr "" 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