Commit d9acf737 authored by Ezekiel Kigbo's avatar Ezekiel Kigbo

Update VSA empty state

Updates the empty state for VSA when there
are no value streams available
parent eca1751b
...@@ -15,6 +15,7 @@ import { METRICS_REQUESTS } from '../constants'; ...@@ -15,6 +15,7 @@ import { METRICS_REQUESTS } from '../constants';
import DurationChart from './duration_chart.vue'; import DurationChart from './duration_chart.vue';
import TypeOfWorkCharts from './type_of_work_charts.vue'; import TypeOfWorkCharts from './type_of_work_charts.vue';
import ValueStreamAggregationStatus from './value_stream_aggregation_status.vue'; import ValueStreamAggregationStatus from './value_stream_aggregation_status.vue';
import ValueStreamEmptyState from './value_stream_empty_state.vue';
import ValueStreamSelect from './value_stream_select.vue'; import ValueStreamSelect from './value_stream_select.vue';
export default { export default {
...@@ -26,6 +27,7 @@ export default { ...@@ -26,6 +27,7 @@ export default {
StageTable, StageTable,
PathNavigation, PathNavigation,
ValueStreamAggregationStatus, ValueStreamAggregationStatus,
ValueStreamEmptyState,
ValueStreamFilters, ValueStreamFilters,
ValueStreamMetrics, ValueStreamMetrics,
ValueStreamSelect, ValueStreamSelect,
...@@ -74,9 +76,10 @@ export default { ...@@ -74,9 +76,10 @@ export default {
'pathNavigationData', 'pathNavigationData',
'isOverviewStageSelected', 'isOverviewStageSelected',
'selectedStageCount', 'selectedStageCount',
'hasValueStreams',
]), ]),
shouldRenderEmptyState() { shouldRenderEmptyState() {
return !this.currentGroup && !this.isLoading; return this.isLoadingValueStreams || !this.hasValueStreams;
}, },
shouldDisplayFilters() { shouldDisplayFilters() {
return !this.errorCode && !this.hasNoAccessError; return !this.errorCode && !this.hasNoAccessError;
...@@ -198,24 +201,25 @@ export default { ...@@ -198,24 +201,25 @@ export default {
</script> </script>
<template> <template>
<div> <div>
<div <value-stream-empty-state
class="gl-mb-3 gl-display-flex gl-flex-direction-column gl-sm-flex-direction-row gl-justify-content-space-between"
>
<h3>{{ __('Value Stream Analytics') }}</h3>
<div class="gl-display-flex gl-flex-direction-row gl-align-items-center gl-mt-0 gl-sm-mt-5">
<value-stream-aggregation-status v-if="isAggregationStatusAvailable" :data="aggregation" />
<value-stream-select v-if="shouldDisplayCreateMultipleValueStreams" />
</div>
</div>
<gl-empty-state
v-if="shouldRenderEmptyState" v-if="shouldRenderEmptyState"
:title="__('Value Stream Analytics can help you determine your team’s velocity')" :is-loading="isLoadingValueStreams"
:description=" :empty-state-svg-path="emptyStateSvgPath"
__('Filter parameters are not valid. Make sure that the end date is after the start date.') :has-date-range-error="!hasDateRangeSet"
"
:svg-path="emptyStateSvgPath"
/> />
<div v-else class="gl-max-w-full"> <div v-else class="gl-max-w-full">
<div
class="gl-mb-3 gl-display-flex gl-flex-direction-column gl-sm-flex-direction-row gl-justify-content-space-between"
>
<h3>{{ __('Value Stream Analytics') }}</h3>
<div class="gl-display-flex gl-flex-direction-row gl-align-items-center gl-mt-0 gl-sm-mt-5">
<value-stream-aggregation-status
v-if="isAggregationStatusAvailable"
:data="aggregation"
/>
<value-stream-select v-if="shouldDisplayCreateMultipleValueStreams" />
</div>
</div>
<path-navigation <path-navigation
v-if="selectedStageReady" v-if="selectedStageReady"
data-testid="vsa-path-navigation" data-testid="vsa-path-navigation"
......
...@@ -76,6 +76,7 @@ export default { ...@@ -76,6 +76,7 @@ export default {
:svg-path="emptyStateSvgPath" :svg-path="emptyStateSvgPath"
:title="title" :title="title"
:description="description" :description="description"
data-testid="vsa-empty-state"
> >
<template v-if="!hasDateRangeError" #actions> <template v-if="!hasDateRangeError" #actions>
<gl-button <gl-button
......
...@@ -13,6 +13,8 @@ import { DEFAULT_VALUE_STREAM_ID, OVERVIEW_STAGE_CONFIG } from '../constants'; ...@@ -13,6 +13,8 @@ import { DEFAULT_VALUE_STREAM_ID, OVERVIEW_STAGE_CONFIG } from '../constants';
export const hasNoAccessError = (state) => state.errorCode === httpStatus.FORBIDDEN; export const hasNoAccessError = (state) => state.errorCode === httpStatus.FORBIDDEN;
export const hasValueStreams = ({ valueStreams }) => Boolean(valueStreams?.length);
export const currentValueStreamId = ({ selectedValueStream }) => export const currentValueStreamId = ({ selectedValueStream }) =>
selectedValueStream?.id || DEFAULT_VALUE_STREAM_ID; selectedValueStream?.id || DEFAULT_VALUE_STREAM_ID;
......
...@@ -9,6 +9,7 @@ import DurationChart from 'ee/analytics/cycle_analytics/components/duration_char ...@@ -9,6 +9,7 @@ import DurationChart from 'ee/analytics/cycle_analytics/components/duration_char
import TypeOfWorkCharts from 'ee/analytics/cycle_analytics/components/type_of_work_charts.vue'; import TypeOfWorkCharts from 'ee/analytics/cycle_analytics/components/type_of_work_charts.vue';
import ValueStreamSelect from 'ee/analytics/cycle_analytics/components/value_stream_select.vue'; import ValueStreamSelect from 'ee/analytics/cycle_analytics/components/value_stream_select.vue';
import ValueStreamAggregationStatus from 'ee/analytics/cycle_analytics/components/value_stream_aggregation_status.vue'; import ValueStreamAggregationStatus from 'ee/analytics/cycle_analytics/components/value_stream_aggregation_status.vue';
import ValueStreamEmptyState from 'ee/analytics/cycle_analytics/components/value_stream_empty_state.vue';
import createStore from 'ee/analytics/cycle_analytics/store'; import createStore from 'ee/analytics/cycle_analytics/store';
import waitForPromises from 'helpers/wait_for_promises'; import waitForPromises from 'helpers/wait_for_promises';
import { import {
...@@ -195,11 +196,12 @@ describe('EE Value Stream Analytics component', () => { ...@@ -195,11 +196,12 @@ describe('EE Value Stream Analytics component', () => {
expect(wrapper.findComponent(ValueStreamSelect).exists()).toBe(flag); expect(wrapper.findComponent(ValueStreamSelect).exists()).toBe(flag);
}; };
describe('without a group', () => { describe('with no value streams', () => {
beforeEach(async () => { beforeEach(async () => {
const { group, ...stateWithoutGroup } = initialCycleAnalyticsState;
mock = new MockAdapter(axios); mock = new MockAdapter(axios);
wrapper = await createComponent({ initialState: stateWithoutGroup }); wrapper = await createComponent({
initialState: { ...initialCycleAnalyticsState, valueStreams: [] },
});
}); });
afterEach(() => { afterEach(() => {
...@@ -209,10 +211,10 @@ describe('EE Value Stream Analytics component', () => { ...@@ -209,10 +211,10 @@ describe('EE Value Stream Analytics component', () => {
}); });
it('displays an empty state', () => { it('displays an empty state', () => {
const emptyState = wrapper.findComponent(GlEmptyState); const emptyState = wrapper.findComponent(ValueStreamEmptyState);
expect(emptyState.exists()).toBe(true); expect(emptyState.exists()).toBe(true);
expect(emptyState.props('svgPath')).toBe(emptyStateSvgPath); expect(emptyState.props('emptyStateSvgPath')).toBe(emptyStateSvgPath);
}); });
it('does not display the metrics cards', () => { it('does not display the metrics cards', () => {
......
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