Commit a9f47a4d authored by Kushal Pandya's avatar Kushal Pandya

Merge branch '223917-jira-issue-list-page' into 'master'

Update Issues list to work with Jira issues

See merge request gitlab-org/gitlab!36073
parents 810260d9 6aa66e99
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
// TODO: need to move this component to graphql - https://gitlab.com/gitlab-org/gitlab/-/issues/221246 // TODO: need to move this component to graphql - https://gitlab.com/gitlab-org/gitlab/-/issues/221246
import { escape, isNumber } from 'lodash'; import { escape, isNumber } from 'lodash';
import { GlLink, GlTooltipDirective as GlTooltip, GlSprintf, GlLabel, GlIcon } from '@gitlab/ui'; import { GlLink, GlTooltipDirective as GlTooltip, GlSprintf, GlLabel, GlIcon } from '@gitlab/ui';
import jiraLogo from '@gitlab/svgs/dist/illustrations/logos/jira.svg';
import { import {
dateInWords, dateInWords,
formatDate, formatDate,
...@@ -25,6 +26,7 @@ import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; ...@@ -25,6 +26,7 @@ import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
export default { export default {
i18n: { i18n: {
openedAgo: __('opened %{timeAgoString} by %{user}'), openedAgo: __('opened %{timeAgoString} by %{user}'),
openedAgoJira: __('opened %{timeAgoString} by %{user} in Jira'),
}, },
components: { components: {
IssueAssignees, IssueAssignees,
...@@ -60,6 +62,11 @@ export default { ...@@ -60,6 +62,11 @@ export default {
}, },
}, },
}, },
data() {
return {
jiraLogo,
};
},
computed: { computed: {
milestoneLink() { milestoneLink() {
const { title } = this.issuable.milestone; const { title } = this.issuable.milestone;
...@@ -87,6 +94,9 @@ export default { ...@@ -87,6 +94,9 @@ export default {
isClosed() { isClosed() {
return this.issuable.state === 'closed'; return this.issuable.state === 'closed';
}, },
isJiraIssue() {
return this.issuable.external_tracker === 'jira';
},
issueCreatedToday() { issueCreatedToday() {
return getDayDifference(new Date(this.issuable.created_at), new Date()) < 1; return getDayDifference(new Date(this.issuable.created_at), new Date()) < 1;
}, },
...@@ -223,7 +233,18 @@ export default { ...@@ -223,7 +233,18 @@ export default {
:title="$options.confidentialTooltipText" :title="$options.confidentialTooltipText"
:aria-label="$options.confidentialTooltipText" :aria-label="$options.confidentialTooltipText"
></i> ></i>
<gl-link :href="issuable.web_url">{{ issuable.title }}</gl-link> <gl-link
:href="issuable.web_url"
:target="isJiraIssue ? '_blank' : null"
data-testid="issuable-title"
>
{{ issuable.title }}
<gl-icon
v-if="isJiraIssue"
name="external-link"
class="gl-vertical-align-text-bottom"
/>
</gl-link>
</span> </span>
<span v-if="issuable.has_tasks" class="ml-1 task-status d-none d-sm-inline-block"> <span v-if="issuable.has_tasks" class="ml-1 task-status d-none d-sm-inline-block">
{{ issuable.task_status }} {{ issuable.task_status }}
...@@ -231,11 +252,21 @@ export default { ...@@ -231,11 +252,21 @@ export default {
</div> </div>
<div class="issuable-info"> <div class="issuable-info">
<span class="js-ref-path">{{ referencePath }}</span> <span class="js-ref-path">
<span
v-if="isJiraIssue"
class="svg-container jira-logo-container"
data-testid="jira-logo"
v-html="jiraLogo"
></span>
{{ referencePath }}
</span>
<span data-testid="openedByMessage" class="d-none d-sm-inline-block mr-1"> <span data-testid="openedByMessage" class="d-none d-sm-inline-block mr-1">
&middot; &middot;
<gl-sprintf :message="$options.i18n.openedAgo"> <gl-sprintf
:message="isJiraIssue ? $options.i18n.openedAgoJira : $options.i18n.openedAgo"
>
<template #timeAgoString> <template #timeAgoString>
<span>{{ issuableCreatedAt }}</span> <span>{{ issuableCreatedAt }}</span>
</template> </template>
...@@ -302,6 +333,7 @@ export default { ...@@ -302,6 +333,7 @@ export default {
<!-- Issuable meta --> <!-- Issuable meta -->
<div class="flex-shrink-0 d-flex flex-column align-items-end justify-content-center"> <div class="flex-shrink-0 d-flex flex-column align-items-end justify-content-center">
<div class="controls d-flex"> <div class="controls d-flex">
<span v-if="isJiraIssue">&nbsp;</span>
<span v-if="isClosed" class="issuable-status">{{ __('CLOSED') }}</span> <span v-if="isClosed" class="issuable-status">{{ __('CLOSED') }}</span>
<issue-assignees <issue-assignees
...@@ -326,6 +358,7 @@ export default { ...@@ -326,6 +358,7 @@ export default {
</template> </template>
<gl-link <gl-link
v-if="!isJiraIssue"
v-gl-tooltip v-gl-tooltip
class="ml-2 js-notes" class="ml-2 js-notes"
:href="`${issuable.web_url}#notes`" :href="`${issuable.web_url}#notes`"
......
import initIssuablesList from '~/issuables_list';
document.addEventListener('DOMContentLoaded', () => {
initIssuablesList();
});
.svg-container.jira-logo-container {
svg {
vertical-align: text-bottom;
}
}
...@@ -27941,6 +27941,9 @@ msgstr "" ...@@ -27941,6 +27941,9 @@ msgstr ""
msgid "opened %{timeAgoString} by %{user}" msgid "opened %{timeAgoString} by %{user}"
msgstr "" msgstr ""
msgid "opened %{timeAgoString} by %{user} in Jira"
msgstr ""
msgid "opened %{timeAgo}" msgid "opened %{timeAgo}"
msgstr "" msgstr ""
......
...@@ -91,6 +91,8 @@ describe('Issuable component', () => { ...@@ -91,6 +91,8 @@ describe('Issuable component', () => {
const findBulkCheckbox = () => wrapper.find('input.selected-issuable'); const findBulkCheckbox = () => wrapper.find('input.selected-issuable');
const findScopedLabels = () => findLabels().filter(w => isScopedLabel({ title: w.text() })); const findScopedLabels = () => findLabels().filter(w => isScopedLabel({ title: w.text() }));
const findUnscopedLabels = () => findLabels().filter(w => !isScopedLabel({ title: w.text() })); const findUnscopedLabels = () => findLabels().filter(w => !isScopedLabel({ title: w.text() }));
const findIssuableTitle = () => wrapper.find('[data-testid="issuable-title"]');
const containsJiraLogo = () => wrapper.contains('[data-testid="jira-logo"]');
describe('when mounted', () => { describe('when mounted', () => {
it('initializes user popovers', () => { it('initializes user popovers', () => {
...@@ -217,6 +219,22 @@ describe('Issuable component', () => { ...@@ -217,6 +219,22 @@ describe('Issuable component', () => {
}); });
}); });
describe('with Jira issuable', () => {
beforeEach(() => {
issuable.external_tracker = 'jira';
factory({ issuable });
});
it('renders the Jira icon', () => {
expect(containsJiraLogo()).toBe(true);
});
it('opens issuable in a new tab', () => {
expect(findIssuableTitle().props('target')).toBe('_blank');
});
});
describe('with task status', () => { describe('with task status', () => {
beforeEach(() => { beforeEach(() => {
Object.assign(issuable, { Object.assign(issuable, {
......
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