Commit 55e88eaa authored by Illya Klymov's avatar Illya Klymov

Merge branch 'tomquirk/335524-approval-list-select-avatars' into 'master'

Use GlAvatar in approval rule selector

See merge request gitlab-org/gitlab!73334
parents a3f7b34c d47b6744
...@@ -63,3 +63,6 @@ export const timeRanges = [ ...@@ -63,3 +63,6 @@ export const timeRanges = [
export const defaultTimeRange = timeRanges.find((tr) => tr.default); export const defaultTimeRange = timeRanges.find((tr) => tr.default);
export const getTimeWindow = (timeWindowName) => export const getTimeWindow = (timeWindowName) =>
timeRanges.find((tr) => tr.name === timeWindowName); timeRanges.find((tr) => tr.name === timeWindowName);
export const AVATAR_SHAPE_OPTION_CIRCLE = 'circle';
export const AVATAR_SHAPE_OPTION_RECT = 'rect';
<script> <script>
import { GlButton, GlTooltipDirective } from '@gitlab/ui'; import { GlButton, GlTooltipDirective, GlAvatarLabeled } from '@gitlab/ui';
import Avatar from '~/vue_shared/components/deprecated_project_avatar/default.vue'; import { __ } from '~/locale';
import { AVATAR_SHAPE_OPTION_CIRCLE, AVATAR_SHAPE_OPTION_RECT } from '~/vue_shared/constants';
import { TYPE_USER, TYPE_GROUP, TYPE_HIDDEN_GROUPS } from '../constants'; import { TYPE_USER, TYPE_GROUP, TYPE_HIDDEN_GROUPS } from '../constants';
import HiddenGroupsItem from './hidden_groups_item.vue'; import HiddenGroupsItem from './hidden_groups_item.vue';
const types = [TYPE_USER, TYPE_GROUP, TYPE_HIDDEN_GROUPS]; const VALID_APPROVER_TYPES = [TYPE_USER, TYPE_GROUP, TYPE_HIDDEN_GROUPS];
export default { export default {
components: { components: {
GlButton, GlButton,
Avatar, GlAvatarLabeled,
HiddenGroupsItem, HiddenGroupsItem,
}, },
directives: { directives: {
...@@ -19,7 +20,7 @@ export default { ...@@ -19,7 +20,7 @@ export default {
approver: { approver: {
type: Object, type: Object,
required: true, required: true,
validator: ({ type }) => type && types.indexOf(type) >= 0, validator: ({ type }) => type && VALID_APPROVER_TYPES.includes(type),
}, },
}, },
computed: { computed: {
...@@ -32,23 +33,36 @@ export default { ...@@ -32,23 +33,36 @@ export default {
displayName() { displayName() {
return this.isGroup ? this.approver.full_path : this.approver.name; return this.isGroup ? this.approver.full_path : this.approver.name;
}, },
avatarShape() {
return this.isGroup ? AVATAR_SHAPE_OPTION_RECT : AVATAR_SHAPE_OPTION_CIRCLE;
},
},
i18n: {
removeApproverText: __('Remove'),
}, },
}; };
</script> </script>
<template> <template>
<transition name="fade"> <transition name="fade">
<li class="d-flex align-items-center px-3"> <li class="gl-display-flex! gl-align-items-center gl-px-5!">
<hidden-groups-item v-if="isHiddenGroups" /> <hidden-groups-item v-if="isHiddenGroups" />
<template v-else> <gl-avatar-labeled
<avatar :project="approver" :size="24" /><span>{{ displayName }}</span> v-else
</template> :shape="avatarShape"
:entity-name="approver.name"
:label="displayName"
:src="approver.avatar_url"
:alt="approver.name"
:size="24"
/>
<gl-button <gl-button
v-gl-tooltip v-gl-tooltip
class="ml-auto" class="gl-ml-auto"
icon="remove" icon="remove"
:aria-label="__('Remove')" :aria-label="$options.i18n.removeApproverText"
:title="__('Remove')" :title="$options.i18n.removeApproverText"
@click="$emit('remove', approver)" @click="$emit('remove', approver)"
/> />
</li> </li>
......
import { GlButton } from '@gitlab/ui'; import { GlButton, GlAvatarLabeled } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils'; import { shallowMount } from '@vue/test-utils';
import ApproversListItem from 'ee/approvals/components/approvers_list_item.vue'; import ApproversListItem from 'ee/approvals/components/approvers_list_item.vue';
import HiddenGroupsItem from 'ee/approvals/components/hidden_groups_item.vue'; import HiddenGroupsItem from 'ee/approvals/components/hidden_groups_item.vue';
import { TYPE_USER, TYPE_GROUP, TYPE_HIDDEN_GROUPS } from 'ee/approvals/constants'; import { TYPE_USER, TYPE_GROUP, TYPE_HIDDEN_GROUPS } from 'ee/approvals/constants';
import Avatar from '~/vue_shared/components/deprecated_project_avatar/default.vue';
const TEST_USER = { const TEST_USER = {
id: 1, id: 1,
type: TYPE_USER, type: TYPE_USER,
name: 'Lorem Ipsum', name: 'Lorem Ipsum',
avatar_url: '/asd/1',
}; };
const TEST_GROUP = { const TEST_GROUP = {
id: 1, id: 1,
type: TYPE_GROUP, type: TYPE_GROUP,
name: 'Lorem Group', name: 'Lorem Group',
full_path: 'dolar/sit/amit', full_path: 'dolar/sit/amit',
avatar_url: '/asd/2',
}; };
describe('Approvals ApproversListItem', () => { describe('Approvals ApproversListItem', () => {
...@@ -26,6 +27,9 @@ describe('Approvals ApproversListItem', () => { ...@@ -26,6 +27,9 @@ describe('Approvals ApproversListItem', () => {
}); });
}; };
const findAvatar = () => wrapper.findComponent(GlAvatarLabeled);
const findHiddenGroupsItem = () => wrapper.findComponent(HiddenGroupsItem);
describe('when user', () => { describe('when user', () => {
beforeEach(() => { beforeEach(() => {
factory({ factory({
...@@ -35,26 +39,25 @@ describe('Approvals ApproversListItem', () => { ...@@ -35,26 +39,25 @@ describe('Approvals ApproversListItem', () => {
}); });
}); });
it('renders avatar', () => { it('renders GlAvatar for user', () => {
const avatar = wrapper.find(Avatar); const avatar = findAvatar();
expect(avatar.exists()).toBe(true); expect(avatar.exists()).toBe(true);
expect(avatar.props('project')).toEqual(TEST_USER); expect(avatar.attributes()).toMatchObject({
'entity-name': TEST_USER.name,
src: TEST_USER.avatar_url,
shape: 'circle',
alt: TEST_USER.name,
}); });
expect(avatar.props('label')).toBe(TEST_USER.name);
it('renders name', () => {
expect(wrapper.text()).toContain(TEST_USER.name);
}); });
it('when remove clicked, emits remove', () => { it('when remove clicked, emits remove', async () => {
const button = wrapper.find(GlButton); const button = wrapper.findComponent(GlButton);
button.vm.$emit('click'); await button.vm.$emit('click');
return wrapper.vm.$nextTick().then(() => {
expect(wrapper.emitted().remove).toEqual([[TEST_USER]]); expect(wrapper.emitted().remove).toEqual([[TEST_USER]]);
}); });
}); });
});
describe('when group', () => { describe('when group', () => {
beforeEach(() => { beforeEach(() => {
...@@ -65,13 +68,20 @@ describe('Approvals ApproversListItem', () => { ...@@ -65,13 +68,20 @@ describe('Approvals ApproversListItem', () => {
}); });
}); });
it('renders full_path', () => { it('renders ProjectAvatar for group', () => {
expect(wrapper.text()).toContain(TEST_GROUP.full_path); const avatar = findAvatar();
expect(wrapper.text()).not.toContain(TEST_GROUP.name); expect(avatar.exists()).toBe(true);
expect(avatar.attributes()).toMatchObject({
'entity-name': TEST_GROUP.name,
src: TEST_GROUP.avatar_url,
shape: 'rect',
alt: TEST_GROUP.name,
});
expect(avatar.props('label')).toBe(TEST_GROUP.full_path);
}); });
it('does not render hidden-groups-item', () => { it('does not render hidden-groups-item', () => {
expect(wrapper.find(HiddenGroupsItem).exists()).toBe(false); expect(findHiddenGroupsItem().exists()).toBe(false);
}); });
}); });
...@@ -85,11 +95,11 @@ describe('Approvals ApproversListItem', () => { ...@@ -85,11 +95,11 @@ describe('Approvals ApproversListItem', () => {
}); });
it('renders hidden-groups-item', () => { it('renders hidden-groups-item', () => {
expect(wrapper.find(HiddenGroupsItem).exists()).toBe(true); expect(findHiddenGroupsItem().exists()).toBe(true);
}); });
it('does not render avatar', () => { it('does not render any avatar', () => {
expect(wrapper.find(Avatar).exists()).toBe(false); expect(findAvatar().exists()).toBe(false);
}); });
}); });
}); });
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