Commit 3e053379 authored by Olena Horal-Koretska's avatar Olena Horal-Koretska Committed by Phil Hughes

Display assignees in Incident List

parent 63b2e6c4
<script> <script>
import { GlLoadingIcon, GlTable, GlAlert } from '@gitlab/ui'; import {
GlLoadingIcon,
GlTable,
GlAlert,
GlAvatarsInline,
GlAvatarLink,
GlAvatar,
GlTooltipDirective,
} from '@gitlab/ui';
import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue'; import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
import { s__ } from '~/locale'; import { s__ } from '~/locale';
import getIncidents from '../graphql/queries/get_incidents.query.graphql'; import getIncidents from '../graphql/queries/get_incidents.query.graphql';
...@@ -37,8 +45,14 @@ export default { ...@@ -37,8 +45,14 @@ export default {
GlLoadingIcon, GlLoadingIcon,
GlTable, GlTable,
GlAlert, GlAlert,
GlAvatarsInline,
GlAvatarLink,
GlAvatar,
TimeAgoTooltip, TimeAgoTooltip,
}, },
directives: {
GlTooltip: GlTooltipDirective,
},
inject: ['projectPath'], inject: ['projectPath'],
apollo: { apollo: {
incidents: { incidents: {
...@@ -78,10 +92,8 @@ export default { ...@@ -78,10 +92,8 @@ export default {
}, },
}, },
methods: { methods: {
getAssignees(assignees) { hasAssignees(assignees) {
return assignees.nodes?.length > 0 return Boolean(assignees.nodes?.length);
? assignees.nodes[0]?.username
: s__('IncidentManagement|Unassigned');
}, },
}, },
}; };
...@@ -114,8 +126,32 @@ export default { ...@@ -114,8 +126,32 @@ export default {
</template> </template>
<template #cell(assignees)="{ item }"> <template #cell(assignees)="{ item }">
<div class="gl-max-w-full text-truncate" data-testid="assigneesField"> <div data-testid="incident-assignees">
{{ getAssignees(item.assignees) }} <template v-if="hasAssignees(item.assignees)">
<gl-avatars-inline
:avatars="item.assignees.nodes"
:collapsed="true"
:max-visible="4"
:avatar-size="24"
badge-tooltip-prop="name"
:badge-tooltip-max-chars="100"
>
<template #avatar="{ avatar }">
<gl-avatar-link
:key="avatar.username"
v-gl-tooltip
target="_blank"
:href="avatar.webUrl"
:title="avatar.name"
>
<gl-avatar :src="avatar.avatarUrl" :label="avatar.name" :size="24" />
</gl-avatar-link>
</template>
</gl-avatars-inline>
</template>
<template v-else>
{{ $options.i18n.unassigned }}
</template>
</div> </div>
</template> </template>
......
...@@ -4,4 +4,5 @@ import { s__ } from '~/locale'; ...@@ -4,4 +4,5 @@ import { s__ } from '~/locale';
export const I18N = { export const I18N = {
errorMsg: s__('IncidentManagement|There was an error displaying the incidents.'), errorMsg: s__('IncidentManagement|There was an error displaying the incidents.'),
noIncidents: s__('IncidentManagement|No incidents to display.'), noIncidents: s__('IncidentManagement|No incidents to display.'),
unassigned: s__('IncidentManagement|Unassigned'),
}; };
...@@ -13,7 +13,10 @@ query getIncidents($projectPath: ID!, $labelNames: [String], $state: IssuableSta ...@@ -13,7 +13,10 @@ query getIncidents($projectPath: ID!, $labelNames: [String], $state: IssuableSta
} }
assignees { assignees {
nodes { nodes {
name
username username
avatarUrl
webUrl
} }
} }
} }
......
---
title: Display assignees in Incident List
merge_request: 37608
author:
type: added
import { mount } from '@vue/test-utils'; import { mount } from '@vue/test-utils';
import { GlAlert, GlLoadingIcon, GlTable } from '@gitlab/ui'; import { GlAlert, GlLoadingIcon, GlTable, GlAvatar } from '@gitlab/ui';
import IncidentsList from '~/incidents/components/incidents_list.vue'; import IncidentsList from '~/incidents/components/incidents_list.vue';
import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue'; import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
import { I18N } from '~/incidents/constants'; import { I18N } from '~/incidents/constants';
...@@ -13,6 +13,7 @@ describe('Incidents List', () => { ...@@ -13,6 +13,7 @@ describe('Incidents List', () => {
const findAlert = () => wrapper.find(GlAlert); const findAlert = () => wrapper.find(GlAlert);
const findLoader = () => wrapper.find(GlLoadingIcon); const findLoader = () => wrapper.find(GlLoadingIcon);
const findTimeAgo = () => wrapper.findAll(TimeAgoTooltip); const findTimeAgo = () => wrapper.findAll(TimeAgoTooltip);
const findAssingees = () => wrapper.findAll('[data-testid="incident-assignees"]');
function mountComponent({ data = { incidents: [] }, loading = false }) { function mountComponent({ data = { incidents: [] }, loading = false }) {
wrapper = mount(IncidentsList, { wrapper = mount(IncidentsList, {
...@@ -31,6 +32,9 @@ describe('Incidents List', () => { ...@@ -31,6 +32,9 @@ describe('Incidents List', () => {
provide: { provide: {
projectPath: '/project/path', projectPath: '/project/path',
}, },
stubs: {
GlAvatar: true,
},
}); });
} }
...@@ -80,5 +84,27 @@ describe('Incidents List', () => { ...@@ -80,5 +84,27 @@ describe('Incidents List', () => {
it('renders a createdAt with timeAgo component per row', () => { it('renders a createdAt with timeAgo component per row', () => {
expect(findTimeAgo().length).toBe(mockIncidents.length); expect(findTimeAgo().length).toBe(mockIncidents.length);
}); });
describe('Assignees', () => {
it('shows Unassigned when there are no assignees', () => {
expect(
findAssingees()
.at(0)
.text(),
).toBe(I18N.unassigned);
});
it('renders an avatar component when there is an assignee', () => {
const avatar = findAssingees()
.at(1)
.find(GlAvatar);
const { src, label } = avatar.attributes();
const { name, avatarUrl } = mockIncidents[1].assignees.nodes[0];
expect(avatar.exists()).toBe(true);
expect(label).toBe(name);
expect(src).toBe(avatarUrl);
});
});
}); });
}); });
...@@ -9,7 +9,16 @@ ...@@ -9,7 +9,16 @@
"iid": "14", "iid": "14",
"title": "Create issue4", "title": "Create issue4",
"createdAt": "2020-05-19T09:26:07Z", "createdAt": "2020-05-19T09:26:07Z",
"assignees": {} "assignees": {
"nodes": [
{
"name": "Benjamin Braun",
"username": "kami.hegmann",
"avatarUrl": "https://invalid'",
"webUrl": "https://invalid"
}
]
}
}, },
{ {
"iid": "13", "iid": "13",
......
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