Commit 9c7433e9 authored by Ezekiel Kigbo's avatar Ezekiel Kigbo Committed by Brandon Labuschagne

Move duration chart to component

Moves the duration chart out of the base
component into a separate component
parent befd7a23
......@@ -6,11 +6,10 @@ import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import { PROJECTS_PER_PAGE } from '../constants';
import GroupsDropdownFilter from '../../shared/components/groups_dropdown_filter.vue';
import ProjectsDropdownFilter from '../../shared/components/projects_dropdown_filter.vue';
import Scatterplot from '../../shared/components/scatterplot.vue';
import { LAST_ACTIVITY_AT, dateFormats, DATE_RANGE_LIMIT } from '../../shared/constants';
import { LAST_ACTIVITY_AT, DATE_RANGE_LIMIT } from '../../shared/constants';
import DateRange from '../../shared/components/daterange.vue';
import StageDropdownFilter from './stage_dropdown_filter.vue';
import StageTable from './stage_table.vue';
import DurationChart from './duration_chart.vue';
import TasksByTypeChart from './tasks_by_type_chart.vue';
import UrlSyncMixin from '../../shared/mixins/url_sync_mixin';
import { toYmd } from '../../shared/utils';
......@@ -20,13 +19,12 @@ export default {
name: 'CycleAnalytics',
components: {
DateRange,
DurationChart,
GlLoadingIcon,
GlEmptyState,
GroupsDropdownFilter,
ProjectsDropdownFilter,
StageTable,
StageDropdownFilter,
Scatterplot,
TasksByTypeChart,
RecentActivityCard,
},
......@@ -214,7 +212,6 @@ export default {
order_by: LAST_ACTIVITY_AT,
include_subgroups: true,
},
durationChartTooltipDateFormat: dateFormats.defaultDate,
maxDateRange: DATE_RANGE_LIMIT,
};
</script>
......@@ -323,31 +320,15 @@ export default {
/>
</div>
</div>
<template v-if="shouldDisplayDurationChart">
<template v-if="isDurationChartLoaded">
<div class="mt-3 d-flex">
<h4 class="mt-0">{{ s__('CycleAnalytics|Days to completion') }}</h4>
<stage-dropdown-filter
v-if="activeStages.length"
class="ml-auto"
:stages="activeStages"
@selected="onDurationStageSelect"
/>
</div>
<scatterplot
v-if="durationChartPlottableData"
:x-axis-title="s__('CycleAnalytics|Date')"
:y-axis-title="s__('CycleAnalytics|Total days to completion')"
:tooltip-date-format="$options.durationChartTooltipDateFormat"
:scatter-data="durationChartPlottableData"
:median-line-data="durationChartMedianData"
/>
<div v-else ref="duration-chart-no-data" class="bs-callout bs-callout-info">
{{ __('There is no data available. Please change your selection.') }}
</div>
</template>
<gl-loading-icon v-else-if="!isLoading" size="md" class="my-4 py-4" />
</template>
<div v-if="shouldDisplayDurationChart" class="mt-3">
<duration-chart
:is-loading="isLoading"
:stages="activeStages"
:scatter-data="durationChartPlottableData"
:median-line-data="durationChartMedianData"
@stageSelected="onDurationStageSelect"
/>
</div>
<template v-if="shouldDisplayTasksByTypeChart">
<div class="js-tasks-by-type-chart">
<div v-if="isTasksByTypeChartLoaded">
......
<script>
import { GlLoadingIcon } from '@gitlab/ui';
import { dateFormats } from '../../shared/constants';
import Scatterplot from '../../shared/components/scatterplot.vue';
import StageDropdownFilter from './stage_dropdown_filter.vue';
export default {
name: 'DurationChart',
components: {
GlLoadingIcon,
Scatterplot,
StageDropdownFilter,
},
props: {
isLoading: {
type: Boolean,
required: false,
default: false,
},
stages: {
type: Array,
required: true,
},
scatterData: {
type: Array,
required: true,
},
medianLineData: {
type: Array,
required: true,
},
},
computed: {
hasData() {
// TODO: check if we want to display when only the median data is available
return Boolean(this.scatterData.length || this.medianLineData.length);
},
},
methods: {},
durationChartTooltipDateFormat: dateFormats.defaultDate,
};
</script>
<template>
<gl-loading-icon v-if="isLoading" size="md" class="my-4 py-4" />
<div v-else>
<div class="d-flex">
<h4 class="mt-0">{{ s__('CycleAnalytics|Days to completion') }}</h4>
<stage-dropdown-filter
v-if="stages.length"
class="ml-auto"
:stages="stages"
@selected="$emit('stageSelected')"
/>
</div>
<scatterplot
v-if="hasData"
:x-axis-title="s__('CycleAnalytics|Date')"
:y-axis-title="s__('CycleAnalytics|Total days to completion')"
:tooltip-date-format="$options.durationChartTooltipDateFormat"
:scatter-data="scatterData"
:median-line-data="medianLineData"
/>
<div v-else ref="duration-chart-no-data" class="bs-callout bs-callout-info">
{{ __('There is no data available. Please change your selection.') }}
</div>
</div>
</template>
......@@ -23,7 +23,7 @@ export const durationChartPlottableData = state => {
const selectedStagesDurationData = durationData.filter(stage => stage.selected);
const plottableData = getDurationChartData(selectedStagesDurationData, startDate, endDate);
return plottableData.length ? plottableData : null;
return plottableData.length ? plottableData : [];
};
export const durationChartMedianData = state => {
......
......@@ -12,6 +12,7 @@ import RecentActivityCard from 'ee/analytics/cycle_analytics/components/recent_a
import StageTable from 'ee/analytics/cycle_analytics/components/stage_table.vue';
import 'bootstrap';
import '~/gl_dropdown';
import DurationChart from 'ee/analytics/cycle_analytics/components/duration_chart.vue';
import Scatterplot from 'ee/analytics/shared/components/scatterplot.vue';
import Daterange from 'ee/analytics/shared/components/daterange.vue';
import TasksByTypeChart from 'ee/analytics/cycle_analytics/components/tasks_by_type_chart.vue';
......@@ -39,6 +40,9 @@ const defaultStubs = {
'stage-nav-item': true,
'tasks-by-type-chart': true,
'labels-selector': true,
'stage-dropdown-filter': true,
Scatterplot: true,
DurationChart: true,
};
function createComponent({
......@@ -206,7 +210,17 @@ describe('Cycle Analytics component', () => {
describe('after a filter has been selected', () => {
describe('the user has access to the group', () => {
beforeEach(() => {
wrapper = createComponent({ withStageSelected: true, tasksByTypeChartEnabled: false });
wrapper = createComponent({
withStageSelected: true,
tasksByTypeChartEnabled: false,
opts: {
stubs: {
...defaultStubs,
'duration-chart': false,
},
},
});
});
it('hides the empty state', () => {
......@@ -271,7 +285,7 @@ describe('Cycle Analytics component', () => {
});
it('displays the duration chart', () => {
expect(wrapper.find(Scatterplot).exists()).toBe(true);
expect(wrapper.find(DurationChart).exists()).toBe(true);
});
});
......
......@@ -118,7 +118,7 @@ describe('Cycle analytics getters', () => {
durationData: [],
};
expect(getters.durationChartPlottableData(stateWithDurationData)).toBeNull();
expect(getters.durationChartPlottableData(stateWithDurationData)).toEqual([]);
});
});
......
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