Commit 0e274436 authored by Scott Stern's avatar Scott Stern Committed by Phil Hughes

Add loading state to initial load of assignees in dropdown

parent 67b39236
...@@ -6,6 +6,7 @@ import { ...@@ -6,6 +6,7 @@ import {
GlAvatarLabeled, GlAvatarLabeled,
GlAvatarLink, GlAvatarLink,
GlSearchBoxByType, GlSearchBoxByType,
GlLoadingIcon,
} from '@gitlab/ui'; } from '@gitlab/ui';
import { __, n__ } from '~/locale'; import { __, n__ } from '~/locale';
import IssuableAssignees from '~/sidebar/components/assignees/issuable_assignees.vue'; import IssuableAssignees from '~/sidebar/components/assignees/issuable_assignees.vue';
...@@ -32,6 +33,7 @@ export default { ...@@ -32,6 +33,7 @@ export default {
GlAvatarLabeled, GlAvatarLabeled,
GlAvatarLink, GlAvatarLink,
GlSearchBoxByType, GlSearchBoxByType,
GlLoadingIcon,
}, },
data() { data() {
return { return {
...@@ -132,45 +134,48 @@ export default { ...@@ -132,45 +134,48 @@ export default {
<gl-search-box-by-type v-model.trim="search" /> <gl-search-box-by-type v-model.trim="search" />
</template> </template>
<template #items> <template #items>
<gl-dropdown-item <gl-loading-icon v-if="$apollo.queries.participants.loading" size="lg" />
:is-checked="selectedIsEmpty" <template v-else>
data-testid="unassign" <gl-dropdown-item
class="mt-2" :is-checked="selectedIsEmpty"
@click="selectAssignee()" data-testid="unassign"
>{{ $options.i18n.unassigned }}</gl-dropdown-item class="mt-2"
> @click="selectAssignee()"
<gl-dropdown-divider data-testid="unassign-divider" /> >{{ $options.i18n.unassigned }}</gl-dropdown-item
<gl-dropdown-item >
v-for="item in selected" <gl-dropdown-divider data-testid="unassign-divider" />
:key="item.id" <gl-dropdown-item
:is-checked="isChecked(item.username)" v-for="item in selected"
@click="unselect(item.username)" :key="item.id"
> :is-checked="isChecked(item.username)"
<gl-avatar-link> @click="unselect(item.username)"
<gl-avatar-labeled >
:size="32" <gl-avatar-link>
:label="item.name" <gl-avatar-labeled
:sub-label="item.username" :size="32"
:src="item.avatarUrl || item.avatar" :label="item.name"
/> :sub-label="item.username"
</gl-avatar-link> :src="item.avatarUrl || item.avatar"
</gl-dropdown-item> />
<gl-dropdown-divider v-if="!selectedIsEmpty" data-testid="selected-user-divider" /> </gl-avatar-link>
<gl-dropdown-item </gl-dropdown-item>
v-for="unselectedUser in unSelectedFiltered" <gl-dropdown-divider v-if="!selectedIsEmpty" data-testid="selected-user-divider" />
:key="unselectedUser.id" <gl-dropdown-item
:data-testid="`item_${unselectedUser.name}`" v-for="unselectedUser in unSelectedFiltered"
@click="selectAssignee(unselectedUser)" :key="unselectedUser.id"
> :data-testid="`item_${unselectedUser.name}`"
<gl-avatar-link> @click="selectAssignee(unselectedUser)"
<gl-avatar-labeled >
:size="32" <gl-avatar-link>
:label="unselectedUser.name" <gl-avatar-labeled
:sub-label="unselectedUser.username" :size="32"
:src="unselectedUser.avatarUrl || unselectedUser.avatar" :label="unselectedUser.name"
/> :sub-label="unselectedUser.username"
</gl-avatar-link> :src="unselectedUser.avatarUrl || unselectedUser.avatar"
</gl-dropdown-item> />
</gl-avatar-link>
</gl-dropdown-item>
</template>
</template> </template>
</multi-select-dropdown> </multi-select-dropdown>
</template> </template>
......
---
title: Add loading state to assignees dropdown
merge_request: 47848
author:
type: added
...@@ -26,6 +26,15 @@ describe('ee/BoardContentSidebar', () => { ...@@ -26,6 +26,15 @@ describe('ee/BoardContentSidebar', () => {
'board-sidebar-due-date': '<div></div>', 'board-sidebar-due-date': '<div></div>',
'board-sidebar-subscription': '<div></div>', 'board-sidebar-subscription': '<div></div>',
}, },
mocks: {
$apollo: {
queries: {
participants: {
loading: false,
},
},
},
},
}); });
}; };
...@@ -55,7 +64,7 @@ describe('ee/BoardContentSidebar', () => { ...@@ -55,7 +64,7 @@ describe('ee/BoardContentSidebar', () => {
expect(wrapper.find(IssuableTitle).text()).toContain('One'); expect(wrapper.find(IssuableTitle).text()).toContain('One');
}); });
it('renders IssuableAssignees', () => { it('renders BoardAssigneeDropdown', () => {
expect(wrapper.find(BoardAssigneeDropdown).exists()).toBe(true); expect(wrapper.find(BoardAssigneeDropdown).exists()).toBe(true);
}); });
......
import { mount, createLocalVue } from '@vue/test-utils'; import { mount, createLocalVue } from '@vue/test-utils';
import { GlDropdownItem, GlAvatarLink, GlAvatarLabeled, GlSearchBoxByType } from '@gitlab/ui'; import {
GlDropdownItem,
GlAvatarLink,
GlAvatarLabeled,
GlSearchBoxByType,
GlLoadingIcon,
} from '@gitlab/ui';
import createMockApollo from 'jest/helpers/mock_apollo_helper'; import createMockApollo from 'jest/helpers/mock_apollo_helper';
import VueApollo from 'vue-apollo'; import VueApollo from 'vue-apollo';
import BoardAssigneeDropdown from '~/boards/components/board_assignee_dropdown.vue'; import BoardAssigneeDropdown from '~/boards/components/board_assignee_dropdown.vue';
...@@ -25,7 +31,7 @@ describe('BoardCardAssigneeDropdown', () => { ...@@ -25,7 +31,7 @@ describe('BoardCardAssigneeDropdown', () => {
const activeIssueName = 'test'; const activeIssueName = 'test';
const anotherIssueName = 'hello'; const anotherIssueName = 'hello';
const createComponent = (search = '') => { const createComponent = (search = '', loading = false) => {
wrapper = mount(BoardAssigneeDropdown, { wrapper = mount(BoardAssigneeDropdown, {
data() { data() {
return { return {
...@@ -39,6 +45,15 @@ describe('BoardCardAssigneeDropdown', () => { ...@@ -39,6 +45,15 @@ describe('BoardCardAssigneeDropdown', () => {
canUpdate: true, canUpdate: true,
rootPath: '', rootPath: '',
}, },
mocks: {
$apollo: {
queries: {
participants: {
loading,
},
},
},
},
}); });
}; };
...@@ -82,6 +97,8 @@ describe('BoardCardAssigneeDropdown', () => { ...@@ -82,6 +97,8 @@ describe('BoardCardAssigneeDropdown', () => {
return wrapper.findAll(GlDropdownItem).wrappers.find(node => node.text().indexOf(text) === 0); return wrapper.findAll(GlDropdownItem).wrappers.find(node => node.text().indexOf(text) === 0);
}; };
const findLoadingIcon = () => wrapper.find(GlLoadingIcon);
beforeEach(() => { beforeEach(() => {
store.state.activeId = '1'; store.state.activeId = '1';
store.state.issues = { store.state.issues = {
...@@ -243,6 +260,30 @@ describe('BoardCardAssigneeDropdown', () => { ...@@ -243,6 +260,30 @@ describe('BoardCardAssigneeDropdown', () => {
}, },
); );
describe('when participants is loading', () => {
beforeEach(() => {
createComponent('', true);
});
it('finds a loading icon in the dropdown', () => {
expect(findLoadingIcon().exists()).toBe(true);
});
});
describe('when participants is loading is false', () => {
beforeEach(() => {
createComponent();
});
it('does not find GlLoading icon in the dropdown', () => {
expect(findLoadingIcon().exists()).toBe(false);
});
it('finds at least 1 GlDropdownItem', () => {
expect(wrapper.findAll(GlDropdownItem).length).toBeGreaterThan(0);
});
});
describe('Apollo', () => { describe('Apollo', () => {
beforeEach(() => { beforeEach(() => {
getIssueParticipantsSpy = jest.fn().mockResolvedValue({ getIssueParticipantsSpy = jest.fn().mockResolvedValue({
......
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