summaryrefslogtreecommitdiff
path: root/app/assets/javascripts/issuables_list/components/issuable.vue
diff options
context:
space:
mode:
Diffstat (limited to 'app/assets/javascripts/issuables_list/components/issuable.vue')
-rw-r--r--app/assets/javascripts/issuables_list/components/issuable.vue121
1 files changed, 80 insertions, 41 deletions
diff --git a/app/assets/javascripts/issuables_list/components/issuable.vue b/app/assets/javascripts/issuables_list/components/issuable.vue
index 947c7518289..b7f4292a126 100644
--- a/app/assets/javascripts/issuables_list/components/issuable.vue
+++ b/app/assets/javascripts/issuables_list/components/issuable.vue
@@ -3,8 +3,11 @@
* This is tightly coupled to projects/issues/_issue.html.haml,
* any changes done to the haml need to be reflected here.
*/
+
+// TODO: need to move this component to graphql - https://gitlab.com/gitlab-org/gitlab/-/issues/221246
import { escape, isNumber } from 'lodash';
-import { GlLink, GlTooltipDirective as GlTooltip, GlSprintf } 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 {
dateInWords,
formatDate,
@@ -16,22 +19,26 @@ import {
import { sprintf, __ } from '~/locale';
import initUserPopovers from '~/user_popovers';
import { mergeUrlParams } from '~/lib/utils/url_utility';
-import Icon from '~/vue_shared/components/icon.vue';
import IssueAssignees from '~/vue_shared/components/issue/issue_assignees.vue';
+import { isScopedLabel } from '~/lib/utils/common_utils';
+import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
export default {
i18n: {
openedAgo: __('opened %{timeAgoString} by %{user}'),
+ openedAgoJira: __('opened %{timeAgoString} by %{user} in Jira'),
},
components: {
- Icon,
IssueAssignees,
GlLink,
+ GlLabel,
+ GlIcon,
GlSprintf,
},
directives: {
GlTooltip,
},
+ mixins: [glFeatureFlagsMixin()],
props: {
issuable: {
type: Object,
@@ -55,14 +62,19 @@ export default {
},
},
},
+ data() {
+ return {
+ jiraLogo,
+ };
+ },
computed: {
milestoneLink() {
const { title } = this.issuable.milestone;
return this.issuableLink({ milestone_title: title });
},
- hasLabels() {
- return Boolean(this.issuable.labels && this.issuable.labels.length);
+ scopedLabelsAvailable() {
+ return this.glFeatures.scopedLabels;
},
hasWeight() {
return isNumber(this.issuable.weight);
@@ -82,6 +94,12 @@ export default {
isClosed() {
return this.issuable.state === 'closed';
},
+ isJiraIssue() {
+ return this.issuable.external_tracker === 'jira';
+ },
+ linkTarget() {
+ return this.isJiraIssue ? '_blank' : null;
+ },
issueCreatedToday() {
return getDayDifference(new Date(this.issuable.created_at), new Date()) < 1;
},
@@ -147,14 +165,14 @@ export default {
value: this.issuable.upvotes,
title: __('Upvotes'),
class: 'js-upvotes',
- faicon: 'fa-thumbs-up',
+ icon: 'thumb-up',
},
{
key: 'downvotes',
value: this.issuable.downvotes,
title: __('Downvotes'),
class: 'js-downvotes',
- faicon: 'fa-thumbs-down',
+ icon: 'thumb-down',
},
];
},
@@ -165,16 +183,17 @@ export default {
initUserPopovers([this.$refs.openedAgoByContainer.$el]);
},
methods: {
- labelStyle(label) {
- return {
- backgroundColor: label.color,
- color: label.text_color,
- };
- },
issuableLink(params) {
return mergeUrlParams(params, this.baseUrl);
},
+ isScoped({ name }) {
+ return isScopedLabel({ title: name }) && this.scopedLabelsAvailable;
+ },
labelHref({ name }) {
+ if (this.isJiraIssue) {
+ return this.issuableLink({ 'labels[]': name });
+ }
+
return this.issuableLink({ 'label_name[]': name });
},
onSelect(ev) {
@@ -214,14 +233,23 @@ export default {
<div class="flex-grow-1">
<div class="title">
<span class="issue-title-text">
- <i
+ <gl-icon
v-if="issuable.confidential"
v-gl-tooltip
- class="fa fa-eye-slash"
+ name="eye-slash"
+ class="gl-vertical-align-text-bottom"
+ :size="16"
:title="$options.confidentialTooltipText"
:aria-label="$options.confidentialTooltipText"
- ></i>
- <gl-link :href="issuable.web_url">{{ issuable.title }}</gl-link>
+ />
+ <gl-link :href="issuable.web_url" :target="linkTarget" data-testid="issuable-title">
+ {{ issuable.title }}
+ <gl-icon
+ v-if="isJiraIssue"
+ name="external-link"
+ class="gl-vertical-align-text-bottom"
+ />
+ </gl-link>
</span>
<span v-if="issuable.has_tasks" class="ml-1 task-status d-none d-sm-inline-block">
{{ issuable.task_status }}
@@ -229,11 +257,21 @@ export default {
</div>
<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">
&middot;
- <gl-sprintf :message="$options.i18n.openedAgo">
+ <gl-sprintf
+ :message="isJiraIssue ? $options.i18n.openedAgoJira : $options.i18n.openedAgo"
+ >
<template #timeAgoString>
<span>{{ issuableCreatedAt }}</span>
</template>
@@ -242,6 +280,7 @@ export default {
ref="openedAgoByContainer"
v-bind="popoverDataAttrs"
:href="issuableAuthor.web_url"
+ :target="linkTarget"
>
{{ issuableAuthor.name }}
</gl-link>
@@ -271,30 +310,29 @@ export default {
{{ dueDateWords }}
</span>
- <span v-if="hasLabels" class="js-labels">
- <gl-link
- v-for="label in issuable.labels"
- :key="label.id"
- class="label-link mr-1"
- :href="labelHref(label)"
- >
- <span
- v-gl-tooltip
- class="badge color-label"
- :style="labelStyle(label)"
- :title="label.description"
- >{{ label.name }}</span
- >
- </gl-link>
- </span>
+ <gl-label
+ v-for="label in issuable.labels"
+ :key="label.id"
+ data-qa-selector="issuable-label"
+ :target="labelHref(label)"
+ :background-color="label.color"
+ :description="label.description"
+ :color="label.text_color"
+ :title="label.name"
+ :scoped="isScoped(label)"
+ size="sm"
+ class="mr-1"
+ >{{ label.name }}</gl-label
+ >
<span
v-if="hasWeight"
v-gl-tooltip
:title="__('Weight')"
class="d-none d-sm-inline-block js-weight"
+ data-testid="weight"
>
- <icon name="weight" class="align-text-bottom" />
+ <gl-icon name="weight" class="align-text-bottom" />
{{ issuable.weight }}
</span>
</div>
@@ -303,7 +341,8 @@ export default {
<!-- Issuable meta -->
<div class="flex-shrink-0 d-flex flex-column align-items-end justify-content-center">
<div class="controls d-flex">
- <span v-if="isClosed" class="issuable-status">{{ __('CLOSED') }}</span>
+ <span v-if="isJiraIssue" data-testid="issuable-status">{{ issuable.status }}</span>
+ <span v-else-if="isClosed" class="issuable-status">{{ __('CLOSED') }}</span>
<issue-assignees
:assignees="issuable.assignees"
@@ -318,23 +357,23 @@ export default {
v-if="meta.value"
:key="meta.key"
v-gl-tooltip
- :class="['d-none d-sm-inline-block ml-2', meta.class]"
+ :class="['d-none d-sm-inline-block ml-2 vertical-align-middle', meta.class]"
:title="meta.title"
>
- <icon v-if="meta.icon" :name="meta.icon" />
- <i v-else :class="['fa', meta.faicon]"></i>
+ <gl-icon v-if="meta.icon" :name="meta.icon" />
{{ meta.value }}
</span>
</template>
<gl-link
+ v-if="!isJiraIssue"
v-gl-tooltip
class="ml-2 js-notes"
:href="`${issuable.web_url}#notes`"
:title="__('Comments')"
:class="{ 'no-comments': hasNoComments }"
>
- <i class="fa fa-comments"></i>
+ <gl-icon name="comments" class="gl-vertical-align-text-bottom" />
{{ userNotesCount }}
</gl-link>
</div>