summaryrefslogtreecommitdiff
path: root/app/assets/javascripts/cycle_analytics/components/base.vue
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2021-06-16 18:25:58 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2021-06-16 18:25:58 +0000
commita5f4bba440d7f9ea47046a0a561d49adf0a1e6d4 (patch)
treefb69158581673816a8cd895f9d352dcb3c678b1e /app/assets/javascripts/cycle_analytics/components/base.vue
parentd16b2e8639e99961de6ddc93909f3bb5c1445ba1 (diff)
downloadgitlab-ce-a5f4bba440d7f9ea47046a0a561d49adf0a1e6d4.tar.gz
Add latest changes from gitlab-org/gitlab@14-0-stable-eev14.0.0-rc42
Diffstat (limited to 'app/assets/javascripts/cycle_analytics/components/base.vue')
-rw-r--r--app/assets/javascripts/cycle_analytics/components/base.vue129
1 files changed, 54 insertions, 75 deletions
diff --git a/app/assets/javascripts/cycle_analytics/components/base.vue b/app/assets/javascripts/cycle_analytics/components/base.vue
index 11a263015e4..8492f0b73e1 100644
--- a/app/assets/javascripts/cycle_analytics/components/base.vue
+++ b/app/assets/javascripts/cycle_analytics/components/base.vue
@@ -1,7 +1,8 @@
<script>
import { GlIcon, GlEmptyState, GlLoadingIcon, GlSprintf } from '@gitlab/ui';
import Cookies from 'js-cookie';
-import { mapActions, mapState } from 'vuex';
+import { mapActions, mapState, mapGetters } from 'vuex';
+import PathNavigation from '~/cycle_analytics/components/path_navigation.vue';
import { __ } from '~/locale';
import banner from './banner.vue';
import stageCodeComponent from './stage_code_component.vue';
@@ -29,6 +30,7 @@ export default {
'stage-staging-component': stageStagingComponent,
'stage-production-component': stageComponent,
'stage-nav-item': stageNavItem,
+ PathNavigation,
},
props: {
noDataSvgPath: {
@@ -52,21 +54,33 @@ export default {
'isEmptyStage',
'selectedStage',
'selectedStageEvents',
+ 'selectedStageError',
'stages',
'summary',
'startDate',
+ 'permissions',
]),
+ ...mapGetters(['pathNavigationData']),
displayStageEvents() {
const { selectedStageEvents, isLoadingStage, isEmptyStage } = this;
return selectedStageEvents.length && !isLoadingStage && !isEmptyStage;
},
displayNotEnoughData() {
- const { selectedStage, isEmptyStage, isLoadingStage } = this;
- return selectedStage && isEmptyStage && !isLoadingStage;
+ return this.selectedStageReady && this.isEmptyStage;
},
displayNoAccess() {
- const { selectedStage } = this;
- return selectedStage && !selectedStage.isUserAllowed;
+ return this.selectedStageReady && !this.isUserAllowed(this.selectedStage.id);
+ },
+ selectedStageReady() {
+ return !this.isLoadingStage && this.selectedStage;
+ },
+ emptyStageTitle() {
+ return this.selectedStageError
+ ? this.selectedStageError
+ : __("We don't have enough data to show this stage.");
+ },
+ emptyStageText() {
+ return !this.selectedStageError ? this.selectedStage.emptyStageText : '';
},
},
methods: {
@@ -78,25 +92,18 @@ export default {
]),
handleDateSelect(startDate) {
this.setDateRange({ startDate });
- this.fetchCycleAnalyticsData();
},
- isActiveStage(stage) {
- return stage.slug === this.selectedStage.slug;
- },
- selectStage(stage) {
- if (this.selectedStage === stage) return;
-
+ onSelectStage(stage) {
this.setSelectedStage(stage);
- if (!stage.isUserAllowed) {
- return;
- }
-
- this.fetchStageData();
},
dismissOverviewDialog() {
this.isOverviewDialogDismissed = true;
Cookies.set(OVERVIEW_DIALOG_COOKIE, '1', { expires: 365 });
},
+ isUserAllowed(id) {
+ const { permissions } = this;
+ return Boolean(permissions?.[id]);
+ },
},
dayRangeOptions: [7, 30, 90],
i18n: {
@@ -106,9 +113,23 @@ export default {
</script>
<template>
<div class="cycle-analytics">
+ <path-navigation
+ v-if="selectedStageReady"
+ class="js-path-navigation gl-w-full gl-pb-2"
+ :loading="isLoading"
+ :stages="pathNavigationData"
+ :selected-stage="selectedStage"
+ :with-stage-counts="false"
+ @selected="onSelectStage"
+ />
<gl-loading-icon v-if="isLoading" size="lg" />
<div v-else class="wrapper">
- <div class="card">
+ <!--
+ We wont have access to the stage counts until we move to a default value stream
+ For now we can use the `withStageCounts` flag to ensure we don't display empty stage counts
+ Related issue: https://gitlab.com/gitlab-org/gitlab/-/issues/326705
+ -->
+ <div class="card" data-testid="vsa-stage-overview-metrics">
<div class="card-header">{{ __('Recent Project Activity') }}</div>
<div class="d-flex justify-content-between">
<div v-for="item in summary" :key="item.title" class="gl-flex-grow-1 gl-text-center">
@@ -139,40 +160,12 @@ export default {
</div>
</div>
</div>
- <div class="stage-panel-container">
- <div class="card stage-panel">
+ <div class="stage-panel-container" data-testid="vsa-stage-table">
+ <div class="card stage-panel gl-px-5">
<div class="card-header border-bottom-0">
<nav class="col-headers">
- <ul>
- <li class="stage-header pl-5">
- <span class="stage-name font-weight-bold">{{
- s__('ProjectLifecycle|Stage')
- }}</span>
- <span
- class="has-tooltip"
- data-placement="top"
- :title="__('The phase of the development lifecycle.')"
- aria-hidden="true"
- >
- <gl-icon name="question-o" class="gl-text-gray-500" />
- </span>
- </li>
- <li class="median-header">
- <span class="stage-name font-weight-bold">{{ __('Median') }}</span>
- <span
- class="has-tooltip"
- data-placement="top"
- :title="
- __(
- 'The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6.',
- )
- "
- aria-hidden="true"
- >
- <gl-icon name="question-o" class="gl-text-gray-500" />
- </span>
- </li>
- <li class="event-header pl-3">
+ <ul class="gl-display-flex gl-justify-content-space-between gl-list-style-none">
+ <li>
<span v-if="selectedStage" class="stage-name font-weight-bold">{{
selectedStage.legend ? __(selectedStage.legend) : __('Related Issues')
}}</span>
@@ -187,7 +180,7 @@ export default {
<gl-icon name="question-o" class="gl-text-gray-500" />
</span>
</li>
- <li class="total-time-header pr-5 text-right">
+ <li>
<span class="stage-name font-weight-bold">{{ __('Time') }}</span>
<span
class="has-tooltip"
@@ -201,45 +194,31 @@ export default {
</ul>
</nav>
</div>
-
<div class="stage-panel-body">
- <nav class="stage-nav">
- <ul>
- <stage-nav-item
- v-for="stage in stages"
- :key="stage.title"
- :title="stage.title"
- :is-user-allowed="stage.isUserAllowed"
- :value="stage.value"
- :is-active="isActiveStage(stage)"
- @select="selectStage(stage)"
- />
- </ul>
- </nav>
- <section class="stage-events overflow-auto">
- <gl-loading-icon v-show="isLoadingStage" size="lg" />
- <template v-if="displayNoAccess">
+ <section class="stage-events gl-overflow-auto gl-w-full">
+ <gl-loading-icon v-if="isLoadingStage" size="lg" />
+ <template v-else>
<gl-empty-state
+ v-if="displayNoAccess"
class="js-empty-state"
:title="__('You need permission.')"
:svg-path="noAccessSvgPath"
:description="__('Want to see the data? Please ask an administrator for access.')"
/>
- </template>
- <template v-else>
- <template v-if="displayNotEnoughData">
+ <template v-else>
<gl-empty-state
+ v-if="displayNotEnoughData"
class="js-empty-state"
- :description="selectedStage.emptyStageText"
+ :description="emptyStageText"
:svg-path="noDataSvgPath"
- :title="__('We don\'t have enough data to show this stage.')"
+ :title="emptyStageTitle"
/>
- </template>
- <template v-if="displayStageEvents">
<component
:is="selectedStage.component"
+ v-if="displayStageEvents"
:stage="selectedStage"
:items="selectedStageEvents"
+ data-testid="stage-table-events"
/>
</template>
</template>