Commit 2ab68081 authored by Illya Klymov's avatar Illya Klymov

Merge branch '336969-add-empty-state' into 'master'

Add empty state for CI minutes usage quotas

See merge request gitlab-org/gitlab!73681
parents f15b64dd 9252df6a
<script>
import { GlAlert } from '@gitlab/ui';
import { GlAreaChart } from '@gitlab/ui/dist/charts';
import { USAGE_BY_MONTH, X_AXIS_MONTH_LABEL, X_AXIS_CATEGORY, Y_AXIS_LABEL } from '../constants';
import {
USAGE_BY_MONTH,
X_AXIS_MONTH_LABEL,
X_AXIS_CATEGORY,
Y_AXIS_LABEL,
NO_CI_MINUTES_MSG,
} from '../constants';
export default {
USAGE_BY_MONTH,
X_AXIS_MONTH_LABEL,
X_AXIS_CATEGORY,
Y_AXIS_LABEL,
NO_CI_MINUTES_MSG,
components: {
GlAlert,
GlAreaChart,
},
props: {
......@@ -46,5 +55,8 @@ export default {
<div>
<h5>{{ $options.USAGE_BY_MONTH }}</h5>
<gl-area-chart v-if="!isDataEmpty" class="gl-mb-3" :data="chartData" :option="chartOptions" />
<gl-alert v-else class="gl-mb-5" :dismissible="false">
{{ $options.NO_CI_MINUTES_MSG }}
</gl-alert>
</div>
</template>
<script>
import { GlDropdown, GlDropdownItem } from '@gitlab/ui';
import { GlAlert, GlDropdown, GlDropdownItem } from '@gitlab/ui';
import { GlColumnChart } from '@gitlab/ui/dist/charts';
import { keyBy } from 'lodash';
import { __ } from '~/locale';
......@@ -8,6 +8,7 @@ import {
X_AXIS_PROJECT_LABEL,
X_AXIS_CATEGORY,
Y_AXIS_LABEL,
NO_CI_MINUTES_MSG,
} from '../constants';
export default {
......@@ -15,6 +16,7 @@ export default {
X_AXIS_PROJECT_LABEL,
X_AXIS_CATEGORY,
Y_AXIS_LABEL,
NO_CI_MINUTES_MSG,
i18n: {
january: __('January'),
february: __('February'),
......@@ -30,6 +32,7 @@ export default {
december: __('December'),
},
components: {
GlAlert,
GlColumnChart,
GlDropdown,
GlDropdownItem,
......@@ -66,7 +69,7 @@ export default {
return this.minutesUsageData.map((cur) => cur.month);
},
isDataEmpty() {
return this.minutesUsageData.length === 0 && this.selectedMonth.length === 0;
return this.minutesUsageData.length === 0 && !this.selectedMonth;
},
},
watch: {
......@@ -94,8 +97,9 @@ export default {
</script>
<template>
<div>
<div class="gl-display-flex gl-my-3">
<div class="gl-display-flex gl-mt-3" :class="{ 'gl-mb-3': !isDataEmpty }">
<h5 class="gl-flex-grow-1">{{ $options.USAGE_BY_PROJECT }}</h5>
<gl-dropdown v-if="!isDataEmpty" :text="selectedMonth" data-testid="project-month-dropdown">
<gl-dropdown-item
v-for="(monthName, index) in months"
......@@ -117,5 +121,8 @@ export default {
:x-axis-title="$options.X_AXIS_PROJECT_LABEL"
:x-axis-type="$options.X_AXIS_CATEGORY"
/>
<gl-alert v-else class="gl-mb-5" :dismissible="false">
{{ $options.NO_CI_MINUTES_MSG }}
</gl-alert>
</div>
</template>
......@@ -6,5 +6,6 @@ export const USAGE_BY_PROJECT = s__('UsageQuota|CI minutes usage by project');
export const X_AXIS_MONTH_LABEL = __('Month');
export const X_AXIS_PROJECT_LABEL = __('Projects');
export const Y_AXIS_LABEL = __('Minutes');
export const NO_CI_MINUTES_MSG = s__('UsageQuota|No CI minutes usage data available.');
export const X_AXIS_CATEGORY = 'category';
import { GlAlert } from '@gitlab/ui';
import { GlAreaChart } from '@gitlab/ui/dist/charts';
import { shallowMount } from '@vue/test-utils';
import MinutesUsageMonthChart from 'ee/ci_minutes_usage/components/minutes_usage_month_chart.vue';
import { ciMinutesUsageMockData } from '../mock_data';
const defaultProps = {
minutesUsageData: ciMinutesUsageMockData.data.ciMinutesUsage.nodes.map((cur) => [
cur.month,
cur.minutes,
]),
};
describe('Minutes usage by month chart component', () => {
let wrapper;
const findAreaChart = () => wrapper.findComponent(GlAreaChart);
const findAlert = () => wrapper.findComponent(GlAlert);
const createComponent = () => {
return shallowMount(MinutesUsageMonthChart, {
const createComponent = (props = {}) => {
wrapper = shallowMount(MinutesUsageMonthChart, {
propsData: {
minutesUsageData: ciMinutesUsageMockData.data.ciMinutesUsage.nodes.map((cur) => [
cur.month,
cur.minutes,
]),
...defaultProps,
...props,
},
});
};
beforeEach(() => {
wrapper = createComponent();
});
afterEach(() => {
wrapper.destroy();
});
it('renders an area chart component', () => {
createComponent();
expect(findAreaChart().exists()).toBe(true);
expect(findAlert().exists()).toBe(false);
});
it('renders an alert when no data is available', () => {
createComponent({ minutesUsageData: [] });
expect(findAlert().exists()).toBe(true);
});
});
import { GlDropdown, GlDropdownItem } from '@gitlab/ui';
import { GlAlert, GlDropdown, GlDropdownItem } from '@gitlab/ui';
import { GlColumnChart } from '@gitlab/ui/dist/charts';
import { shallowMount } from '@vue/test-utils';
import MinutesUsageProjectChart from 'ee/ci_minutes_usage/components/minutes_usage_project_chart.vue';
import { ciMinutesUsageMockData } from '../mock_data';
const defaultProps = { minutesUsageData: ciMinutesUsageMockData.data.ciMinutesUsage.nodes };
describe('Minutes usage by project chart component', () => {
let wrapper;
const findColumnChart = () => wrapper.findComponent(GlColumnChart);
const findDropdown = () => wrapper.findComponent(GlDropdown);
const findAllDropdownItems = () => wrapper.findAllComponents(GlDropdownItem);
const findAlert = () => wrapper.findComponent(GlAlert);
const createComponent = () => {
return shallowMount(MinutesUsageProjectChart, {
const createComponent = (props = {}) => {
wrapper = shallowMount(MinutesUsageProjectChart, {
propsData: {
minutesUsageData: ciMinutesUsageMockData.data.ciMinutesUsage.nodes,
...defaultProps,
...props,
},
});
};
beforeEach(() => {
wrapper = createComponent();
});
afterEach(() => {
wrapper.destroy();
});
it('renders a column chart component with axis legends', () => {
expect(findColumnChart().exists()).toBe(true);
expect(findColumnChart().props('xAxisTitle')).toBe('Projects');
expect(findColumnChart().props('yAxisTitle')).toBe('Minutes');
});
describe('with CI minutes data', () => {
beforeEach(() => {
createComponent();
});
it('renders a column chart component with axis legends', () => {
expect(findColumnChart().exists()).toBe(true);
expect(findColumnChart().props('xAxisTitle')).toBe('Projects');
expect(findColumnChart().props('yAxisTitle')).toBe('Minutes');
expect(findAlert().exists()).toBe(false);
});
it('renders a dropdown component', () => {
expect(findDropdown().exists()).toBe(true);
expect(findDropdown().props('text')).toBe(
ciMinutesUsageMockData.data.ciMinutesUsage.nodes[0].month,
);
expect(findAlert().exists()).toBe(false);
});
it('renders a dropdown component', () => {
expect(findDropdown().exists()).toBe(true);
expect(findDropdown().props('text')).toBe(
ciMinutesUsageMockData.data.ciMinutesUsage.nodes[0].month,
);
it('renders the same amount of dropdown components as the backend response', () => {
expect(findAllDropdownItems().length).toBe(
ciMinutesUsageMockData.data.ciMinutesUsage.nodes.length,
);
});
});
it('renders the same amount of dropdown components as the backend response', () => {
expect(findAllDropdownItems().length).toBe(
ciMinutesUsageMockData.data.ciMinutesUsage.nodes.length,
);
describe('without CI minutes data', () => {
it('renders an alert when no data is available', () => {
createComponent({ minutesUsageData: [] });
expect(findAlert().exists()).toBe(true);
});
});
});
......@@ -37021,6 +37021,9 @@ msgstr ""
msgid "UsageQuota|Learn more about usage quotas"
msgstr ""
msgid "UsageQuota|No CI minutes usage data available."
msgstr ""
msgid "UsageQuota|Packages"
msgstr ""
......
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