diff options
Diffstat (limited to 'app/assets/javascripts/issuable/components/issue_milestone.vue')
-rw-r--r-- | app/assets/javascripts/issuable/components/issue_milestone.vue | 91 |
1 files changed, 91 insertions, 0 deletions
diff --git a/app/assets/javascripts/issuable/components/issue_milestone.vue b/app/assets/javascripts/issuable/components/issue_milestone.vue new file mode 100644 index 00000000000..6a0c21602bd --- /dev/null +++ b/app/assets/javascripts/issuable/components/issue_milestone.vue @@ -0,0 +1,91 @@ +<script> +import { GlTooltip, GlIcon } from '@gitlab/ui'; +import { timeFor, parsePikadayDate, dateInWords } from '~/lib/utils/datetime_utility'; +import { __, sprintf } from '~/locale'; +import timeagoMixin from '~/vue_shared/mixins/timeago'; + +export default { + components: { + GlIcon, + GlTooltip, + }, + mixins: [timeagoMixin], + props: { + milestone: { + type: Object, + required: true, + }, + }, + computed: { + milestoneDue() { + const dueDate = this.milestone.due_date || this.milestone.dueDate; + + return dueDate ? parsePikadayDate(dueDate) : null; + }, + milestoneStart() { + const startDate = this.milestone.start_date || this.milestone.startDate; + + return startDate ? parsePikadayDate(startDate) : null; + }, + isMilestoneStarted() { + if (!this.milestoneStart) { + return false; + } + return Date.now() > this.milestoneStart; + }, + isMilestonePastDue() { + if (!this.milestoneDue) { + return false; + } + return Date.now() > this.milestoneDue; + }, + milestoneDatesAbsolute() { + if (this.milestoneDue) { + return `(${dateInWords(this.milestoneDue)})`; + } else if (this.milestoneStart) { + return `(${dateInWords(this.milestoneStart)})`; + } + return ''; + }, + milestoneDatesHuman() { + if (this.milestoneStart || this.milestoneDue) { + if (this.milestoneDue) { + return timeFor( + this.milestoneDue, + sprintf(__('Expired %{expiredOn}'), { + expiredOn: this.timeFormatted(this.milestoneDue), + }), + ); + } + + return sprintf( + this.isMilestoneStarted ? __('Started %{startsIn}') : __('Starts %{startsIn}'), + { + startsIn: this.timeFormatted(this.milestoneStart), + }, + ); + } + return ''; + }, + }, +}; +</script> +<template> + <div ref="milestoneDetails" class="issue-milestone-details"> + <gl-icon :size="16" class="gl-mr-2" name="clock" /> + <span class="milestone-title d-inline-block">{{ milestone.title }}</span> + <gl-tooltip :target="() => $refs.milestoneDetails" placement="bottom" class="js-item-milestone"> + <span class="bold">{{ __('Milestone') }}</span> <br /> + <span>{{ milestone.title }}</span> <br /> + <span + v-if="milestoneStart || milestoneDue" + :class="{ + 'text-danger-muted': isMilestonePastDue, + 'text-tertiary': !isMilestonePastDue, + }" + ><span>{{ milestoneDatesHuman }}</span + ><br /><span>{{ milestoneDatesAbsolute }}</span> + </span> + </gl-tooltip> + </div> +</template> |