Commit 0b5bc45e authored by Jose Ivan Vargas's avatar Jose Ivan Vargas

Merge branch '291008-default-emoji-persists-in-group-members-list' into 'master'

Fix how busy is displayed in group/project members list

See merge request gitlab-org/gitlab!79780
parents e02b3c46 953da37d
...@@ -8,10 +8,14 @@ import { ...@@ -8,10 +8,14 @@ import {
import { generateBadges } from 'ee_else_ce/members/utils'; import { generateBadges } from 'ee_else_ce/members/utils';
import { glEmojiTag } from '~/emoji'; import { glEmojiTag } from '~/emoji';
import { __ } from '~/locale'; import { __ } from '~/locale';
import { isUserBusy } from '~/set_status_modal/utils';
import { AVATAR_SIZE } from '../../constants'; import { AVATAR_SIZE } from '../../constants';
export default { export default {
name: 'UserAvatar', name: 'UserAvatar',
i18n: {
busy: __('Busy'),
},
avatarSize: AVATAR_SIZE, avatarSize: AVATAR_SIZE,
orphanedUserLabel: __('Orphaned member'), orphanedUserLabel: __('Orphaned member'),
safeHtmlConfig: { ADD_TAGS: ['gl-emoji'] }, safeHtmlConfig: { ADD_TAGS: ['gl-emoji'] },
...@@ -46,7 +50,10 @@ export default { ...@@ -46,7 +50,10 @@ export default {
}).filter((badge) => badge.show); }).filter((badge) => badge.show);
}, },
statusEmoji() { statusEmoji() {
return this.user?.status?.emoji; return this.user?.showStatus && this.user?.status?.emoji;
},
isUserBusy() {
return isUserBusy(this.user?.availability || '');
}, },
}, },
methods: { methods: {
...@@ -73,6 +80,11 @@ export default { ...@@ -73,6 +80,11 @@ export default {
:entity-id="user.id" :entity-id="user.id"
> >
<template #meta> <template #meta>
<div v-if="isUserBusy" class="gl-p-1">
<span class="gl-text-gray-500 gl-font-sm gl-font-weight-normal"
>({{ $options.i18n.busy }})</span
>
</div>
<div v-if="statusEmoji" class="gl-p-1"> <div v-if="statusEmoji" class="gl-p-1">
<span <span
v-safe-html:[$options.safeHtmlConfig]="glEmojiTag(statusEmoji)" v-safe-html:[$options.safeHtmlConfig]="glEmojiTag(statusEmoji)"
......
# frozen_string_literal: true # frozen_string_literal: true
class MemberUserEntity < UserEntity class MemberUserEntity < UserEntity
unexpose :show_status
unexpose :path unexpose :path
unexpose :state unexpose :state
unexpose :status_tooltip_html unexpose :status_tooltip_html
......
{ {
"type": "object", "type": "object",
"required": ["id", "name", "username", "avatar_url", "web_url", "blocked", "two_factor_enabled"], "required": ["id", "name", "username", "avatar_url", "web_url", "blocked", "two_factor_enabled", "show_status"],
"properties": { "properties": {
"id": { "type": "integer" }, "id": { "type": "integer" },
"name": { "type": "string" }, "name": { "type": "string" },
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
"emoji": { "type": "string" } "emoji": { "type": "string" }
}, },
"additionalProperties": false "additionalProperties": false
} },
"show_status": { "type": "boolean" }
} }
} }
import { GlAvatarLink, GlBadge } from '@gitlab/ui'; import { GlAvatarLink, GlBadge } from '@gitlab/ui';
import { within } from '@testing-library/dom'; import { mountExtended } from 'helpers/vue_test_utils_helper';
import { mount, createWrapper } from '@vue/test-utils';
import UserAvatar from '~/members/components/avatars/user_avatar.vue'; import UserAvatar from '~/members/components/avatars/user_avatar.vue';
import { AVAILABILITY_STATUS } from '~/set_status_modal/utils';
import { member as memberMock, member2faEnabled, orphanedMember } from '../../mock_data'; import { member as memberMock, member2faEnabled, orphanedMember } from '../../mock_data';
describe('UserAvatar', () => { describe('UserAvatar', () => {
...@@ -10,7 +11,7 @@ describe('UserAvatar', () => { ...@@ -10,7 +11,7 @@ describe('UserAvatar', () => {
const { user } = memberMock; const { user } = memberMock;
const createComponent = (propsData = {}, provide = {}) => { const createComponent = (propsData = {}, provide = {}) => {
wrapper = mount(UserAvatar, { wrapper = mountExtended(UserAvatar, {
propsData: { propsData: {
member: memberMock, member: memberMock,
isCurrentUser: false, isCurrentUser: false,
...@@ -23,9 +24,6 @@ describe('UserAvatar', () => { ...@@ -23,9 +24,6 @@ describe('UserAvatar', () => {
}); });
}; };
const getByText = (text, options) =>
createWrapper(within(wrapper.element).findByText(text, options));
const findStatusEmoji = (emoji) => wrapper.find(`gl-emoji[data-name="${emoji}"]`); const findStatusEmoji = (emoji) => wrapper.find(`gl-emoji[data-name="${emoji}"]`);
afterEach(() => { afterEach(() => {
...@@ -48,13 +46,13 @@ describe('UserAvatar', () => { ...@@ -48,13 +46,13 @@ describe('UserAvatar', () => {
it("renders user's name", () => { it("renders user's name", () => {
createComponent(); createComponent();
expect(getByText(user.name).exists()).toBe(true); expect(wrapper.findByText(user.name).exists()).toBe(true);
}); });
it("renders user's username", () => { it("renders user's username", () => {
createComponent(); createComponent();
expect(getByText(`@${user.username}`).exists()).toBe(true); expect(wrapper.findByText(`@${user.username}`).exists()).toBe(true);
}); });
it("renders user's avatar", () => { it("renders user's avatar", () => {
...@@ -67,7 +65,7 @@ describe('UserAvatar', () => { ...@@ -67,7 +65,7 @@ describe('UserAvatar', () => {
it('displays an orphaned user', () => { it('displays an orphaned user', () => {
createComponent({ member: orphanedMember }); createComponent({ member: orphanedMember });
expect(getByText('Orphaned member').exists()).toBe(true); expect(wrapper.findByText('Orphaned member').exists()).toBe(true);
}); });
}); });
...@@ -85,13 +83,13 @@ describe('UserAvatar', () => { ...@@ -85,13 +83,13 @@ describe('UserAvatar', () => {
it('renders the "It\'s you" badge when member is current user', () => { it('renders the "It\'s you" badge when member is current user', () => {
createComponent({ isCurrentUser: true }); createComponent({ isCurrentUser: true });
expect(getByText("It's you").exists()).toBe(true); expect(wrapper.findByText("It's you").exists()).toBe(true);
}); });
it('does not render 2FA badge when `canManageMembers` is `false`', () => { it('does not render 2FA badge when `canManageMembers` is `false`', () => {
createComponent({ member: member2faEnabled }, { canManageMembers: false }); createComponent({ member: member2faEnabled }, { canManageMembers: false });
expect(within(wrapper.element).queryByText('2FA')).toBe(null); expect(wrapper.findByText('2FA').exists()).toBe(false);
}); });
}); });
...@@ -112,6 +110,23 @@ describe('UserAvatar', () => { ...@@ -112,6 +110,23 @@ describe('UserAvatar', () => {
expect(findStatusEmoji(emoji).exists()).toBe(true); expect(findStatusEmoji(emoji).exists()).toBe(true);
}); });
describe('when `user.showStatus` is `false', () => {
it('does not display status emoji', () => {
createComponent({
member: {
...memberMock,
user: {
...memberMock.user,
showStatus: false,
status: { emoji, messageHtml: 'On vacation' },
},
},
});
expect(findStatusEmoji(emoji).exists()).toBe(false);
});
});
}); });
describe('when not set', () => { describe('when not set', () => {
...@@ -122,4 +137,30 @@ describe('UserAvatar', () => { ...@@ -122,4 +137,30 @@ describe('UserAvatar', () => {
}); });
}); });
}); });
describe('user availability', () => {
describe('when `user.availability` is `null`', () => {
it("does not show `(Busy)` next to user's name", () => {
createComponent();
expect(wrapper.findByText('(Busy)').exists()).toBe(false);
});
});
describe(`when user.availability is ${AVAILABILITY_STATUS.BUSY}`, () => {
it("shows `(Busy)` next to user's name", () => {
createComponent({
member: {
...memberMock,
user: {
...memberMock.user,
availability: AVAILABILITY_STATUS.BUSY,
},
},
});
expect(wrapper.findByText('(Busy)').exists()).toBe(true);
});
});
});
}); });
...@@ -25,6 +25,8 @@ export const member = { ...@@ -25,6 +25,8 @@ export const member = {
twoFactorEnabled: false, twoFactorEnabled: false,
oncallSchedules: [{ name: 'schedule 1' }], oncallSchedules: [{ name: 'schedule 1' }],
escalationPolicies: [{ name: 'policy 1' }], escalationPolicies: [{ name: 'policy 1' }],
availability: null,
showStatus: true,
}, },
id: 238, id: 238,
createdAt: '2020-07-17T16:22:46.923Z', createdAt: '2020-07-17T16:22:46.923Z',
......
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