Commit 6165b28d authored by Ezekiel Kigbo's avatar Ezekiel Kigbo

Merge branch '322140-add-issue-due-date-to-jira-issue-details-page' into 'master'

Add issue due date to Jira issue details page

See merge request gitlab-org/gitlab!54692
parents 524dff25 54c938ec
<script>
import { GlIcon, GlTooltipDirective } from '@gitlab/ui';
import { dateInWords, getDayDifference, parsePikadayDate } from '~/lib/utils/datetime_utility';
import { __ } from '~/locale';
export default {
directives: {
GlTooltip: GlTooltipDirective,
},
components: {
GlIcon,
},
props: {
dueDate: {
type: String,
required: false,
default: null,
},
},
computed: {
dueDateInWords() {
const date = parsePikadayDate(this.dueDate);
return dateInWords(date, true);
},
formattedDueDate() {
const today = new Date();
const date = parsePikadayDate(this.dueDate);
const isPastDue = getDayDifference(today, date) < 0;
let formattedDate = this.dueDateInWords;
if (isPastDue) {
formattedDate += ` (${__('Past due')})`;
}
return formattedDate;
},
dueDateTooltipProps() {
return {
boundary: 'viewport',
placement: 'left',
title: this.dueDate
? `${this.$options.i18n.dueDateTitle}<br>${this.formattedDueDate}`
: this.$options.i18n.dueDateTitle,
};
},
},
i18n: {
dueDateTitle: __('Due date'),
none: __('None'),
},
};
</script>
<template>
<div class="block">
<div
v-gl-tooltip.html="dueDateTooltipProps"
class="sidebar-collapsed-icon"
data-testid="due-date-collapsed"
>
<gl-icon name="calendar" />
<span v-if="dueDate">{{ dueDateInWords }}</span>
<span v-else>{{ $options.i18n.none }}</span>
</div>
<div class="hide-collapsed">
<div class="title">{{ $options.i18n.dueDateTitle }}</div>
<div class="value" data-testid="due-date-value">
<strong v-if="dueDate">{{ formattedDueDate }}</strong>
<span v-else class="no-value">{{ $options.i18n.none }}</span>
</div>
</div>
</div>
</template>
......@@ -3,12 +3,14 @@ import { labelsFilterParam } from 'ee/integrations/jira/issues_show/constants';
import LabelsSelect from '~/vue_shared/components/sidebar/labels_select_vue/labels_select_root.vue';
import Assignee from './assignee.vue';
import IssueDueDate from './issue_due_date.vue';
import IssueReference from './issue_reference.vue';
export default {
name: 'JiraIssuesSidebar',
components: {
Assignee,
IssueDueDate,
IssueReference,
LabelsSelect,
},
......@@ -30,10 +32,10 @@ export default {
computed: {
assignee() {
// Jira issues have at most 1 assignee
return (this.issue?.assignees || [])[0];
return (this.issue.assignees || [])[0];
},
reference() {
return this.issue?.references?.relative;
return this.issue.references?.relative;
},
},
labelsFilterParam,
......@@ -44,6 +46,8 @@ export default {
<div>
<assignee class="block" :assignee="assignee" />
<issue-due-date :due-date="issue.dueDate" />
<labels-select
:selected-labels="issue.labels"
:labels-filter-base-path="issuesListPath"
......
import { shallowMount } from '@vue/test-utils';
import IssueDueDate from 'ee/integrations/jira/issues_show/components/sidebar/issue_due_date.vue';
import { useFakeDate } from 'helpers/fake_date';
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
describe('IssueDueDate', () => {
let wrapper;
const createComponent = ({ props = {} } = {}) => {
wrapper = extendedWrapper(
shallowMount(IssueDueDate, {
propsData: props,
}),
);
};
afterEach(() => {
wrapper.destroy();
wrapper = null;
});
const findDueDateCollapsed = () => wrapper.findByTestId('due-date-collapsed');
const findDueDateValue = () => wrapper.findByTestId('due-date-value');
describe('when dueDate is null', () => {
it('renders "None" as value', () => {
createComponent();
expect(findDueDateCollapsed().text()).toBe('None');
expect(findDueDateValue().text()).toBe('None');
});
});
describe('when dueDate is in the past', () => {
const dueDate = '2021-02-14T00:00:00.000Z';
useFakeDate(2021, 2, 18);
it('renders formatted dueDate', () => {
createComponent({
props: {
dueDate,
},
});
expect(findDueDateCollapsed().text()).toBe('Feb 14, 2021');
expect(findDueDateValue().text()).toBe('Feb 14, 2021 (Past due)');
});
});
describe('when dueDate is in the future', () => {
const dueDate = '2021-02-14T00:00:00.000Z';
useFakeDate(2020, 12, 20);
it('renders formatted dueDate', () => {
createComponent({
props: {
dueDate,
},
});
expect(findDueDateCollapsed().text()).toBe('Feb 14, 2021');
expect(findDueDateValue().text()).toBe('Feb 14, 2021');
});
});
});
import { shallowMount } from '@vue/test-utils';
import Assignee from 'ee/integrations/jira/issues_show/components/sidebar/assignee.vue';
import IssueDueDate from 'ee/integrations/jira/issues_show/components/sidebar/issue_due_date.vue';
import IssueReference from 'ee/integrations/jira/issues_show/components/sidebar/issue_reference.vue';
import Sidebar from 'ee/integrations/jira/issues_show/components/sidebar/jira_issues_sidebar_root.vue';
import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
......@@ -31,21 +32,27 @@ describe('JiraIssuesSidebar', () => {
const findLabelsSelect = () => wrapper.findComponent(LabelsSelect);
const findAssignee = () => wrapper.findComponent(Assignee);
const findIssueDueDate = () => wrapper.findComponent(IssueDueDate);
const findIssueReference = () => wrapper.findComponent(IssueReference);
it('renders Labels block', async () => {
it('renders Labels block', () => {
createComponent();
expect(findLabelsSelect().exists()).toBe(true);
expect(findLabelsSelect().props('selectedLabels')).toEqual(mockJiraIssue.labels);
expect(findLabelsSelect().props('selectedLabels')).toBe(mockJiraIssue.labels);
});
it('renders Assignee block', async () => {
it('renders Assignee block', () => {
createComponent();
const assignee = findAssignee();
expect(assignee.exists()).toBe(true);
expect(assignee.props('assignee')).toEqual(mockJiraIssue.assignees[0]);
expect(assignee.props('assignee')).toBe(mockJiraIssue.assignees[0]);
});
it('renders IssueDueDate', () => {
createComponent();
const dueDate = findIssueDueDate();
expect(dueDate.props('dueDate')).toBe(mockJiraIssue.dueDate);
});
describe('when references.relative is null', () => {
......
export const mockJiraIssue = {
title_html:
'<a href="https://jira.reali.sh:8080/projects/FE/issues/FE-2">FE-2</a> The second FE issue on Jira',
title: 'FE-2 The second FE issue on Jira',
description_html:
'<a href="https://jira.reali.sh:8080/projects/FE/issues/FE-2">FE-2</a> The second FE issue on Jira',
created_at: '"2021-02-01T04:04:40.833Z"',
......@@ -16,6 +15,7 @@ export const mockJiraIssue = {
avatar_url: 'http://127.0.0.1:3000/uploads/-/system/user/avatar/1/avatar.png?width=90',
},
],
due_date: '2021-02-14T00:00:00.000Z',
labels: [
{
title: 'In Progress',
......
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