Commit 06924b81 authored by Phil Hughes's avatar Phil Hughes

Merge branch '331894-say-when-MR-was-approved-by-me' into 'master'

Say when MR was approved by me

See merge request gitlab-org/gitlab!63174
parents 47de9049 2846f45a
<script> <script>
import { toNounSeriesText } from '~/lib/utils/grammar'; import { toNounSeriesText } from '~/lib/utils/grammar';
import { n__, sprintf } from '~/locale'; import { n__, sprintf } from '~/locale';
import { APPROVED_MESSAGE } from '~/vue_merge_request_widget/components/approvals/messages'; import {
APPROVED_BY_YOU_AND_OTHERS,
APPROVED_BY_YOU,
APPROVED_BY_OTHERS,
} from '~/vue_merge_request_widget/components/approvals/messages';
import UserAvatarList from '~/vue_shared/components/user_avatar/user_avatar_list.vue'; import UserAvatarList from '~/vue_shared/components/user_avatar/user_avatar_list.vue';
export default { export default {
...@@ -29,12 +33,23 @@ export default { ...@@ -29,12 +33,23 @@ export default {
}, },
}, },
computed: { computed: {
message() { approvalLeftMessage() {
if (this.approved) { if (this.rulesLeft.length) {
return APPROVED_MESSAGE; return sprintf(
n__(
'Requires %{count} approval from %{names}.',
'Requires %{count} approvals from %{names}.',
this.approvalsLeft,
),
{
names: toNounSeriesText(this.rulesLeft),
count: this.approvalsLeft,
},
false,
);
} }
if (!this.rulesLeft.length) { if (!this.approved) {
return n__( return n__(
'Requires %d approval from eligible users.', 'Requires %d approval from eligible users.',
'Requires %d approvals from eligible users.', 'Requires %d approvals from eligible users.',
...@@ -42,32 +57,51 @@ export default { ...@@ -42,32 +57,51 @@ export default {
); );
} }
return sprintf( return '';
n__( },
'Requires %{count} approval from %{names}.', message() {
'Requires %{count} approvals from %{names}.', if (this.approvedByMe && this.approvedByOthers) {
this.approvalsLeft, return APPROVED_BY_YOU_AND_OTHERS;
), }
{
names: toNounSeriesText(this.rulesLeft), if (this.approvedByMe) {
count: this.approvalsLeft, return APPROVED_BY_YOU;
}, }
false,
); if (this.approved) {
return APPROVED_BY_OTHERS;
}
return '';
}, },
hasApprovers() { hasApprovers() {
return Boolean(this.approvers.length); return Boolean(this.approvers.length);
}, },
approvedByMe() {
if (!this.currentUserId) {
return false;
}
return this.approvers.some((approver) => approver.id === this.currentUserId);
},
approvedByOthers() {
if (!this.currentUserId) {
return false;
}
return this.approvers.some((approver) => approver.id !== this.currentUserId);
},
currentUserId() {
return gon.current_user_id;
},
}, },
APPROVED_MESSAGE,
}; };
</script> </script>
<template> <template>
<div data-qa-selector="approvals_summary_content"> <div data-qa-selector="approvals_summary_content">
<strong>{{ message }}</strong> <strong>{{ approvalLeftMessage }}</strong>
<template v-if="hasApprovers"> <template v-if="hasApprovers">
<span>{{ s__('mrWidget|Approved by') }}</span> <span v-if="approvalLeftMessage">{{ message }}</span>
<strong v-else>{{ message }}</strong>
<user-avatar-list class="d-inline-block align-middle" :items="approvers" /> <user-avatar-list class="d-inline-block align-middle" :items="approvers" />
</template> </template>
</div> </div>
......
...@@ -6,4 +6,6 @@ export const FETCH_ERROR = s__( ...@@ -6,4 +6,6 @@ export const FETCH_ERROR = s__(
); );
export const APPROVE_ERROR = s__('mrWidget|An error occurred while submitting your approval.'); export const APPROVE_ERROR = s__('mrWidget|An error occurred while submitting your approval.');
export const UNAPPROVE_ERROR = s__('mrWidget|An error occurred while removing your approval.'); export const UNAPPROVE_ERROR = s__('mrWidget|An error occurred while removing your approval.');
export const APPROVED_MESSAGE = s__('mrWidget|Merge request approved.'); export const APPROVED_BY_YOU_AND_OTHERS = s__('mrWidget|Approved by you and others');
export const APPROVED_BY_YOU = s__('mrWidget|Approved by you');
export const APPROVED_BY_OTHERS = s__('mrWidget|Approved by');
...@@ -40896,6 +40896,12 @@ msgstr "" ...@@ -40896,6 +40896,12 @@ msgstr ""
msgid "mrWidget|Approved by" msgid "mrWidget|Approved by"
msgstr "" msgstr ""
msgid "mrWidget|Approved by you"
msgstr ""
msgid "mrWidget|Approved by you and others"
msgstr ""
msgid "mrWidget|Are you adding technical debt or code vulnerabilities?" msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
msgstr "" msgstr ""
...@@ -40993,9 +40999,6 @@ msgstr "" ...@@ -40993,9 +40999,6 @@ msgstr ""
msgid "mrWidget|Merge locally" msgid "mrWidget|Merge locally"
msgstr "" msgstr ""
msgid "mrWidget|Merge request approved."
msgstr ""
msgid "mrWidget|Merged by" msgid "mrWidget|Merged by"
msgstr "" msgstr ""
......
...@@ -17,7 +17,7 @@ RSpec.describe 'Merge request > User approves', :js do ...@@ -17,7 +17,7 @@ RSpec.describe 'Merge request > User approves', :js do
it 'approves merge request' do it 'approves merge request' do
click_approval_button('Approve') click_approval_button('Approve')
expect(page).to have_content('Merge request approved') expect(page).to have_content('Approved by you')
verify_approvals_count_on_index! verify_approvals_count_on_index!
......
import { shallowMount } from '@vue/test-utils'; import { shallowMount } from '@vue/test-utils';
import { toNounSeriesText } from '~/lib/utils/grammar'; import { toNounSeriesText } from '~/lib/utils/grammar';
import ApprovalsSummary from '~/vue_merge_request_widget/components/approvals/approvals_summary.vue'; import ApprovalsSummary from '~/vue_merge_request_widget/components/approvals/approvals_summary.vue';
import { APPROVED_MESSAGE } from '~/vue_merge_request_widget/components/approvals/messages'; import {
APPROVED_BY_OTHERS,
APPROVED_BY_YOU,
APPROVED_BY_YOU_AND_OTHERS,
} from '~/vue_merge_request_widget/components/approvals/messages';
import UserAvatarList from '~/vue_shared/components/user_avatar/user_avatar_list.vue'; import UserAvatarList from '~/vue_shared/components/user_avatar/user_avatar_list.vue';
const exampleUserId = 1;
const testApprovers = () => Array.from({ length: 5 }, (_, i) => i).map((id) => ({ id })); const testApprovers = () => Array.from({ length: 5 }, (_, i) => i).map((id) => ({ id }));
const testRulesLeft = () => ['Lorem', 'Ipsum', 'dolar & sit']; const testRulesLeft = () => ['Lorem', 'Ipsum', 'dolar & sit'];
const TEST_APPROVALS_LEFT = 3; const TEST_APPROVALS_LEFT = 3;
describe('MRWidget approvals summary', () => { describe('MRWidget approvals summary', () => {
const originalUserId = gon.current_user_id;
let wrapper; let wrapper;
const createComponent = (props = {}) => { const createComponent = (props = {}) => {
...@@ -28,6 +34,7 @@ describe('MRWidget approvals summary', () => { ...@@ -28,6 +34,7 @@ describe('MRWidget approvals summary', () => {
afterEach(() => { afterEach(() => {
wrapper.destroy(); wrapper.destroy();
wrapper = null; wrapper = null;
gon.current_user_id = originalUserId;
}); });
describe('when approved', () => { describe('when approved', () => {
...@@ -38,7 +45,7 @@ describe('MRWidget approvals summary', () => { ...@@ -38,7 +45,7 @@ describe('MRWidget approvals summary', () => {
}); });
it('shows approved message', () => { it('shows approved message', () => {
expect(wrapper.text()).toContain(APPROVED_MESSAGE); expect(wrapper.text()).toContain(APPROVED_BY_OTHERS);
}); });
it('renders avatar list for approvers', () => { it('renders avatar list for approvers', () => {
...@@ -51,6 +58,48 @@ describe('MRWidget approvals summary', () => { ...@@ -51,6 +58,48 @@ describe('MRWidget approvals summary', () => {
}), }),
); );
}); });
describe('by the current user', () => {
beforeEach(() => {
gon.current_user_id = exampleUserId;
createComponent({
approvers: [{ id: exampleUserId }],
approved: true,
});
});
it('shows "Approved by you" message', () => {
expect(wrapper.text()).toContain(APPROVED_BY_YOU);
});
});
describe('by the current user and others', () => {
beforeEach(() => {
gon.current_user_id = exampleUserId;
createComponent({
approvers: [{ id: exampleUserId }, { id: exampleUserId + 1 }],
approved: true,
});
});
it('shows "Approved by you and others" message', () => {
expect(wrapper.text()).toContain(APPROVED_BY_YOU_AND_OTHERS);
});
});
describe('by other users than the current user', () => {
beforeEach(() => {
gon.current_user_id = exampleUserId;
createComponent({
approvers: [{ id: exampleUserId + 1 }],
approved: true,
});
});
it('shows "Approved by others" message', () => {
expect(wrapper.text()).toContain(APPROVED_BY_OTHERS);
});
});
}); });
describe('when not approved', () => { describe('when not approved', () => {
......
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