diff options
Diffstat (limited to 'app/assets/javascripts/pages/projects/graphs/components/code_coverage.vue')
-rw-r--r-- | app/assets/javascripts/pages/projects/graphs/components/code_coverage.vue | 177 |
1 files changed, 177 insertions, 0 deletions
diff --git a/app/assets/javascripts/pages/projects/graphs/components/code_coverage.vue b/app/assets/javascripts/pages/projects/graphs/components/code_coverage.vue new file mode 100644 index 00000000000..af8fb032c22 --- /dev/null +++ b/app/assets/javascripts/pages/projects/graphs/components/code_coverage.vue @@ -0,0 +1,177 @@ +<script> +import { GlAlert, GlDropdown, GlDropdownItem, GlIcon, GlSprintf } from '@gitlab/ui'; +import { GlAreaChart } from '@gitlab/ui/dist/charts'; +import dateFormat from 'dateformat'; +import axios from '~/lib/utils/axios_utils'; +import { get } from 'lodash'; + +import { __ } from '~/locale'; + +export default { + components: { + GlAlert, + GlAreaChart, + GlDropdown, + GlDropdownItem, + GlIcon, + GlSprintf, + }, + props: { + graphEndpoint: { + type: String, + required: true, + }, + }, + data() { + return { + dailyCoverageData: [], + hasFetchError: false, + isLoading: true, + selectedCoverageIndex: 0, + tooltipTitle: '', + coveragePercentage: '', + chartOptions: { + yAxis: { + name: __('Bi-weekly code coverage'), + type: 'value', + min: 0, + max: 100, + }, + xAxis: { + name: '', + type: 'category', + }, + }, + }; + }, + computed: { + hasData() { + return this.dailyCoverageData.length > 0; + }, + isReady() { + return !this.isLoading && !this.hasFetchError; + }, + canShowData() { + return this.isReady && this.hasData; + }, + noDataAvailable() { + return this.isReady && !this.hasData; + }, + selectedDailyCoverage() { + return this.hasData && this.dailyCoverageData[this.selectedCoverageIndex]; + }, + selectedDailyCoverageName() { + return this.selectedDailyCoverage?.group_name; + }, + formattedData() { + if (this.selectedDailyCoverage?.data) { + return this.selectedDailyCoverage.data.map(value => [ + dateFormat(value.date, 'mmm dd'), + value.coverage, + ]); + } + + // If the fetching failed, we return an empty array which + // allow the graph to render while empty + return []; + }, + chartData() { + return [ + { + // The default string 'data' will get shown in the legend if we fail to fetch the data + name: this.canShowData ? this.selectedDailyCoverageName : __('data'), + data: this.formattedData, + type: 'line', + smooth: true, + }, + ]; + }, + }, + created() { + axios + .get(this.graphEndpoint) + .then(({ data }) => { + this.dailyCoverageData = data; + }) + .catch(() => { + this.hasFetchError = true; + }) + .finally(() => { + this.isLoading = false; + }); + }, + methods: { + setSelectedCoverage(index) { + this.selectedCoverageIndex = index; + }, + formatTooltipText(params) { + this.tooltipTitle = params.value; + this.coveragePercentage = get(params, 'seriesData[0].data[1]', ''); + }, + }, + height: 200, +}; +</script> + +<template> + <div> + <div class="gl-mt-3 gl-mb-3"> + <gl-alert + v-if="hasFetchError" + variant="danger" + :title="s__('Code Coverage|Couldn\'t fetch the code coverage data')" + :dismissible="false" + /> + <gl-alert + v-if="noDataAvailable" + variant="info" + :title="s__('Code Coverage| Empty code coverage data')" + :dismissible="false" + > + <span> + {{ __('It seems that there is currently no available data for code coverage') }} + </span> + </gl-alert> + <gl-dropdown v-if="canShowData" :text="selectedDailyCoverageName"> + <gl-dropdown-item + v-for="({ group_name }, index) in dailyCoverageData" + :key="index" + :value="group_name" + @click="setSelectedCoverage(index)" + > + <div class="gl-display-flex"> + <gl-icon + v-if="index === selectedCoverageIndex" + name="mobile-issue-close" + class="gl-absolute" + /> + <span class="gl-display-flex align-items-center ml-4"> + {{ group_name }} + </span> + </div> + </gl-dropdown-item> + </gl-dropdown> + </div> + <gl-area-chart + v-if="!isLoading" + :height="$options.height" + :data="chartData" + :option="chartOptions" + :format-tooltip-text="formatTooltipText" + > + <template v-if="canShowData" #tooltipTitle> + {{ tooltipTitle }} + </template> + <template v-if="canShowData" #tooltipContent> + <gl-sprintf :message="__('Code Coverage: %{coveragePercentage}%{percentSymbol}')"> + <template #coveragePercentage> + {{ coveragePercentage }} + </template> + <template #percentSymbol> + % + </template> + </gl-sprintf> + </template> + </gl-area-chart> + </div> +</template> |