Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'app/assets/javascripts/boards/components/board_card_inner.vue')
-rw-r--r--app/assets/javascripts/boards/components/board_card_inner.vue131
1 files changed, 118 insertions, 13 deletions
diff --git a/app/assets/javascripts/boards/components/board_card_inner.vue b/app/assets/javascripts/boards/components/board_card_inner.vue
index 2f4e9044b9e..05b64ddc773 100644
--- a/app/assets/javascripts/boards/components/board_card_inner.vue
+++ b/app/assets/javascripts/boards/components/board_card_inner.vue
@@ -1,5 +1,12 @@
<script>
-import { GlLabel, GlTooltipDirective, GlIcon, GlLoadingIcon } from '@gitlab/ui';
+import {
+ GlLabel,
+ GlTooltip,
+ GlTooltipDirective,
+ GlIcon,
+ GlLoadingIcon,
+ GlSprintf,
+} from '@gitlab/ui';
import { sortBy } from 'lodash';
import { mapActions, mapGetters, mapState } from 'vuex';
import boardCardInner from 'ee_else_ce/boards/mixins/board_card_inner';
@@ -16,6 +23,7 @@ import IssueTimeEstimate from './issue_time_estimate.vue';
export default {
components: {
+ GlTooltip,
GlLabel,
GlLoadingIcon,
GlIcon,
@@ -25,6 +33,7 @@ export default {
IssueTimeEstimate,
IssueCardWeight: () => import('ee_component/boards/components/issue_card_weight.vue'),
BoardBlockedIcon,
+ GlSprintf,
},
directives: {
GlTooltip: GlTooltipDirective,
@@ -55,7 +64,7 @@ export default {
};
},
computed: {
- ...mapState(['isShowingLabels', 'issuableType']),
+ ...mapState(['isShowingLabels', 'issuableType', 'allowSubEpics']),
...mapGetters(['isEpicBoard']),
cappedAssignees() {
// e.g. maxRender is 4,
@@ -99,6 +108,12 @@ export default {
}
return false;
},
+ shouldRenderEpicCountables() {
+ return this.isEpicBoard && this.item.hasIssues;
+ },
+ shouldRenderEpicProgress() {
+ return this.totalWeight > 0;
+ },
showLabelFooter() {
return this.isShowingLabels && this.item.labels.find(this.showLabel);
},
@@ -115,6 +130,20 @@ export default {
}
return __('Blocked issue');
},
+ totalEpicsCount() {
+ return this.item.descendantCounts.openedEpics + this.item.descendantCounts.closedEpics;
+ },
+ totalIssuesCount() {
+ return this.item.descendantCounts.openedIssues + this.item.descendantCounts.closedIssues;
+ },
+ totalWeight() {
+ return (
+ this.item.descendantWeightSum.openedIssues + this.item.descendantWeightSum.closedIssues
+ );
+ },
+ totalProgress() {
+ return Math.round((this.item.descendantWeightSum.closedIssues / this.totalWeight) * 100);
+ },
},
methods: {
...mapActions(['performSearch', 'setError']),
@@ -227,17 +256,93 @@ export default {
{{ itemId }}
</span>
<span class="board-info-items gl-mt-3 gl-display-inline-block">
- <issue-due-date
- v-if="item.dueDate"
- :date="item.dueDate"
- :closed="item.closed || Boolean(item.closedAt)"
- />
- <issue-time-estimate v-if="item.timeEstimate" :estimate="item.timeEstimate" />
- <issue-card-weight
- v-if="validIssueWeight(item)"
- :weight="item.weight"
- @click="filterByWeight(item.weight)"
- />
+ <span v-if="shouldRenderEpicCountables" data-testid="epic-countables">
+ <gl-tooltip :target="() => $refs.countBadge" data-testid="epic-countables-tooltip">
+ <p v-if="allowSubEpics" class="gl-font-weight-bold gl-m-0">
+ {{ __('Epics') }} &#8226;
+ <span class="gl-font-weight-normal">
+ <gl-sprintf :message="__('%{openedEpics} open, %{closedEpics} closed')">
+ <template #openedEpics>{{ item.descendantCounts.openedEpics }}</template>
+ <template #closedEpics>{{ item.descendantCounts.closedEpics }}</template>
+ </gl-sprintf>
+ </span>
+ </p>
+ <p class="gl-font-weight-bold gl-m-0">
+ {{ __('Issues') }} &#8226;
+ <span class="gl-font-weight-normal">
+ <gl-sprintf :message="__('%{openedIssues} open, %{closedIssues} closed')">
+ <template #openedIssues>{{ item.descendantCounts.openedIssues }}</template>
+ <template #closedIssues>{{ item.descendantCounts.closedIssues }}</template>
+ </gl-sprintf>
+ </span>
+ </p>
+ <p class="gl-font-weight-bold gl-m-0">
+ {{ __('Total weight') }} &#8226;
+ <span class="gl-font-weight-normal" data-testid="epic-countables-total-weight">
+ {{ totalWeight }}
+ </span>
+ </p>
+ </gl-tooltip>
+
+ <gl-tooltip
+ v-if="shouldRenderEpicProgress"
+ :target="() => $refs.progressBadge"
+ data-testid="epic-progress-tooltip"
+ >
+ <p class="gl-font-weight-bold gl-m-0">
+ {{ __('Progress') }} &#8226;
+ <span class="gl-font-weight-normal" data-testid="epic-progress-tooltip-content">
+ <gl-sprintf
+ :message="__('%{completedWeight} of %{totalWeight} weight completed')"
+ >
+ <template #completedWeight>{{
+ item.descendantWeightSum.closedIssues
+ }}</template>
+ <template #totalWeight>{{ totalWeight }}</template>
+ </gl-sprintf>
+ </span>
+ </p>
+ </gl-tooltip>
+
+ <span ref="countBadge" class="issue-count-badge board-card-info gl-mr-0 gl-pr-0">
+ <span v-if="allowSubEpics" class="gl-mr-3">
+ <gl-icon name="epic" />
+ {{ totalEpicsCount }}
+ </span>
+ <span class="gl-mr-3" data-testid="epic-countables-counts-issues">
+ <gl-icon name="issues" />
+ {{ totalIssuesCount }}
+ </span>
+ <span class="gl-mr-3" data-testid="epic-countables-weight-issues">
+ <gl-icon name="weight" />
+ {{ totalWeight }}
+ </span>
+ </span>
+
+ <span
+ v-if="shouldRenderEpicProgress"
+ ref="progressBadge"
+ class="issue-count-badge board-card-info gl-pl-0"
+ >
+ <span class="gl-mr-3" data-testid="epic-progress">
+ <gl-icon name="progress" />
+ {{ totalProgress }}%
+ </span>
+ </span>
+ </span>
+ <span v-if="!isEpicBoard">
+ <issue-due-date
+ v-if="item.dueDate"
+ :date="item.dueDate"
+ :closed="item.closed || Boolean(item.closedAt)"
+ />
+ <issue-time-estimate v-if="item.timeEstimate" :estimate="item.timeEstimate" />
+ <issue-card-weight
+ v-if="validIssueWeight(item)"
+ :weight="item.weight"
+ @click="filterByWeight(item.weight)"
+ />
+ </span>
</span>
</div>
<div class="board-card-assignee gl-display-flex">