diff options
author | Laura Montemayor <lmontemayor@gitlab.com> | 2019-08-14 22:57:33 +0000 |
---|---|---|
committer | Clement Ho <408677-ClemMakesApps@users.noreply.gitlab.com> | 2019-08-14 22:57:33 +0000 |
commit | 9e75711aead6c5991ea116a9326762d58b91b18b (patch) | |
tree | 25cc9fbfd266f54c529da25d6c966932bee898d9 | |
parent | 0b43c1027f712567d654c3e61c6557db1f4e2faa (diff) | |
download | gitlab-ce-9e75711aead6c5991ea116a9326762d58b91b18b.tar.gz |
Adds download CSV functionality to dropdown in metrics
This MR adds the functionality to download metrics data
as CSV. It also removes the exportMetricsToCsvEnabled feature
flag which was used before the dropdown was implemented to
display a button.
12 files changed, 83 insertions, 73 deletions
diff --git a/app/assets/javascripts/monitoring/components/charts/area.vue b/app/assets/javascripts/monitoring/components/charts/area.vue index 5b950f8c966..838447e6c75 100644 --- a/app/assets/javascripts/monitoring/components/charts/area.vue +++ b/app/assets/javascripts/monitoring/components/charts/area.vue @@ -1,7 +1,6 @@ <script> import { __ } from '~/locale'; -import { mapState } from 'vuex'; -import { GlLink, GlButton } from '@gitlab/ui'; +import { GlLink } from '@gitlab/ui'; import { GlAreaChart, GlChartSeriesLabel } from '@gitlab/ui/dist/charts'; import dateFormat from 'dateformat'; import { debounceByAnimationFrame, roundOffFloat } from '~/lib/utils/common_utils'; @@ -16,7 +15,6 @@ let debouncedResize; export default { components: { GlAreaChart, - GlButton, GlChartSeriesLabel, GlLink, Icon, @@ -69,7 +67,6 @@ export default { }; }, computed: { - ...mapState('monitoringDashboard', ['exportMetricsToCsvEnabled']), chartData() { // Transforms & supplements query data to render appropriate labels & styles // Input: [{ queryAttributes1 }, { queryAttributes2 }] @@ -179,18 +176,6 @@ export default { yAxisLabel() { return `${this.graphData.y_label}`; }, - csvText() { - const chartData = this.chartData[0].data; - const header = `timestamp,${this.graphData.y_label}\r\n`; // eslint-disable-line @gitlab/i18n/no-non-i18n-strings - return chartData.reduce((csv, data) => { - const row = data.join(','); - return `${csv}${row}\r\n`; - }, header); - }, - downloadLink() { - const data = new Blob([this.csvText], { type: 'text/plain' }); - return window.URL.createObjectURL(data); - }, }, watch: { containerWidth: 'onResize', @@ -259,16 +244,6 @@ export default { <div :class="{ 'prometheus-graph-embed w-100 p-3': showBorder }"> <div class="prometheus-graph-header"> <h5 ref="graphTitle" class="prometheus-graph-title">{{ graphData.title }}</h5> - <gl-button - v-if="exportMetricsToCsvEnabled" - :href="downloadLink" - :title="__('Download CSV')" - :aria-label="__('Download CSV')" - style="margin-left: 200px;" - download="chart_metrics.csv" - > - {{ __('Download CSV') }} - </gl-button> <div ref="graphWidgets" class="prometheus-graph-widgets"><slot></slot></div> </div> <gl-area-chart diff --git a/app/assets/javascripts/monitoring/components/dashboard.vue b/app/assets/javascripts/monitoring/components/dashboard.vue index 782e4310f3e..587392adbc3 100644 --- a/app/assets/javascripts/monitoring/components/dashboard.vue +++ b/app/assets/javascripts/monitoring/components/dashboard.vue @@ -235,6 +235,19 @@ export default { chart.metrics.some(metric => this.metricsWithData.includes(metric.metric_id)), ); }, + csvText(graphData) { + const chartData = graphData.queries[0].result[0].values; + const yLabel = graphData.y_label; + const header = `timestamp,${yLabel}\r\n`; // eslint-disable-line @gitlab/i18n/no-non-i18n-strings + return chartData.reduce((csv, data) => { + const row = data.join(','); + return `${csv}${row}\r\n`; + }, header); + }, + downloadCsv(graphData) { + const data = new Blob([this.csvText(graphData)], { type: 'text/plain' }); + return window.URL.createObjectURL(data); + }, // TODO: BEGIN, Duplicated code with panel_type until feature flag is removed // Issue number: https://gitlab.com/gitlab-org/gitlab-ce/issues/63845 getGraphAlerts(queries) { @@ -448,7 +461,6 @@ export default { @setAlerts="setAlerts" /> <gl-dropdown - v-if="alertWidgetAvailable" v-gl-tooltip class="mx-2" toggle-class="btn btn-transparent border-0" @@ -459,6 +471,9 @@ export default { <template slot="button-content"> <icon name="ellipsis_v" class="text-secondary" /> </template> + <gl-dropdown-item :href="downloadCsv(graphData)" download="chart_metrics.csv"> + {{ __('Download CSV') }} + </gl-dropdown-item> <gl-dropdown-item v-if="alertWidgetAvailable" v-gl-modal="`alert-modal-${index}-${graphIndex}`" diff --git a/app/assets/javascripts/monitoring/components/panel_type.vue b/app/assets/javascripts/monitoring/components/panel_type.vue index 295c0851f12..3fbac71f3d7 100644 --- a/app/assets/javascripts/monitoring/components/panel_type.vue +++ b/app/assets/javascripts/monitoring/components/panel_type.vue @@ -1,7 +1,14 @@ <script> import { mapState } from 'vuex'; import _ from 'underscore'; -import { GlDropdown, GlDropdownItem, GlModal, GlModalDirective } from '@gitlab/ui'; +import { + GlDropdown, + GlDropdownItem, + GlModal, + GlModalDirective, + GlTooltipDirective, +} from '@gitlab/ui'; +import Icon from '~/vue_shared/components/icon.vue'; import MonitorAreaChart from './charts/area.vue'; import MonitorSingleStatChart from './charts/single_stat.vue'; import MonitorEmptyChart from './charts/empty_chart.vue'; @@ -11,12 +18,14 @@ export default { MonitorAreaChart, MonitorSingleStatChart, MonitorEmptyChart, + Icon, GlDropdown, GlDropdownItem, GlModal, }, directives: { GlModal: GlModalDirective, + GlTooltip: GlTooltipDirective, }, props: { graphData: { @@ -41,6 +50,19 @@ export default { graphDataHasMetrics() { return this.graphData.queries[0].result.length > 0; }, + csvText() { + const chartData = this.graphData.queries[0].result[0].values; + const yLabel = this.graphData.y_label; + const header = `timestamp,${yLabel}\r\n`; // eslint-disable-line @gitlab/i18n/no-non-i18n-strings + return chartData.reduce((csv, data) => { + const row = data.join(','); + return `${csv}${row}\r\n`; + }, header); + }, + downloadCsv() { + const data = new Blob([this.csvText], { type: 'text/plain' }); + return window.URL.createObjectURL(data); + }, }, methods: { getGraphAlerts(queries) { @@ -81,7 +103,6 @@ export default { @setAlerts="setAlerts" /> <gl-dropdown - v-if="alertWidgetAvailable" v-gl-tooltip class="mx-2" toggle-class="btn btn-transparent border-0" @@ -92,6 +113,9 @@ export default { <template slot="button-content"> <icon name="ellipsis_v" class="text-secondary" /> </template> + <gl-dropdown-item :href="downloadCsv" download="chart_metrics.csv"> + {{ __('Download CSV') }} + </gl-dropdown-item> <gl-dropdown-item v-if="alertWidgetAvailable" v-gl-modal="`alert-modal-${index}`"> {{ __('Alerts') }} </gl-dropdown-item> diff --git a/app/assets/javascripts/monitoring/monitoring_bundle.js b/app/assets/javascripts/monitoring/monitoring_bundle.js index 366034becd0..c0fee1ebb99 100644 --- a/app/assets/javascripts/monitoring/monitoring_bundle.js +++ b/app/assets/javascripts/monitoring/monitoring_bundle.js @@ -13,7 +13,6 @@ export default (props = {}) => { prometheusEndpointEnabled: gon.features.environmentMetricsUsePrometheusEndpoint, multipleDashboardsEnabled: gon.features.environmentMetricsShowMultipleDashboards, additionalPanelTypesEnabled: gon.features.environmentMetricsAdditionalPanelTypes, - exportMetricsToCsvEnabled: gon.features.exportMetricsToCsvEnabled, }); } diff --git a/app/assets/javascripts/monitoring/stores/actions.js b/app/assets/javascripts/monitoring/stores/actions.js index a9c491c7c6c..0cbad179f17 100644 --- a/app/assets/javascripts/monitoring/stores/actions.js +++ b/app/assets/javascripts/monitoring/stores/actions.js @@ -37,17 +37,11 @@ export const setEndpoints = ({ commit }, endpoints) => { export const setFeatureFlags = ( { commit }, - { - prometheusEndpointEnabled, - multipleDashboardsEnabled, - additionalPanelTypesEnabled, - exportMetricsToCsvEnabled, - }, + { prometheusEndpointEnabled, multipleDashboardsEnabled, additionalPanelTypesEnabled }, ) => { commit(types.SET_DASHBOARD_ENABLED, prometheusEndpointEnabled); commit(types.SET_MULTIPLE_DASHBOARDS_ENABLED, multipleDashboardsEnabled); commit(types.SET_ADDITIONAL_PANEL_TYPES_ENABLED, additionalPanelTypesEnabled); - commit(types.SET_EXPORT_METRICS_TO_CSV_ENABLED, exportMetricsToCsvEnabled); }; export const setShowErrorBanner = ({ commit }, enabled) => { diff --git a/app/assets/javascripts/monitoring/stores/mutation_types.js b/app/assets/javascripts/monitoring/stores/mutation_types.js index 9ec8214b167..4b1aadbcf05 100644 --- a/app/assets/javascripts/monitoring/stores/mutation_types.js +++ b/app/assets/javascripts/monitoring/stores/mutation_types.js @@ -17,4 +17,3 @@ export const SET_ENDPOINTS = 'SET_ENDPOINTS'; export const SET_GETTING_STARTED_EMPTY_STATE = 'SET_GETTING_STARTED_EMPTY_STATE'; export const SET_NO_DATA_EMPTY_STATE = 'SET_NO_DATA_EMPTY_STATE'; export const SET_SHOW_ERROR_BANNER = 'SET_SHOW_ERROR_BANNER'; -export const SET_EXPORT_METRICS_TO_CSV_ENABLED = 'SET_EXPORT_METRICS_TO_CSV_ENABLED'; diff --git a/app/assets/javascripts/monitoring/stores/mutations.js b/app/assets/javascripts/monitoring/stores/mutations.js index a2dceb21fc0..b19520d6638 100644 --- a/app/assets/javascripts/monitoring/stores/mutations.js +++ b/app/assets/javascripts/monitoring/stores/mutations.js @@ -99,7 +99,4 @@ export default { [types.SET_SHOW_ERROR_BANNER](state, enabled) { state.showErrorBanner = enabled; }, - [types.SET_EXPORT_METRICS_TO_CSV_ENABLED](state, enabled) { - state.exportMetricsToCsvEnabled = enabled; - }, }; diff --git a/app/assets/javascripts/monitoring/stores/state.js b/app/assets/javascripts/monitoring/stores/state.js index a14a25e3a20..440bdc951e0 100644 --- a/app/assets/javascripts/monitoring/stores/state.js +++ b/app/assets/javascripts/monitoring/stores/state.js @@ -10,7 +10,6 @@ export default () => ({ useDashboardEndpoint: false, multipleDashboardsEnabled: false, additionalPanelTypesEnabled: false, - exportMetricsToCsvEnabled: false, emptyState: 'gettingStarted', showEmptyState: true, showErrorBanner: true, diff --git a/app/controllers/projects/environments_controller.rb b/app/controllers/projects/environments_controller.rb index df9e55fda2a..5a1f93dc609 100644 --- a/app/controllers/projects/environments_controller.rb +++ b/app/controllers/projects/environments_controller.rb @@ -15,7 +15,6 @@ class Projects::EnvironmentsController < Projects::ApplicationController push_frontend_feature_flag(:environment_metrics_show_multiple_dashboards) push_frontend_feature_flag(:environment_metrics_additional_panel_types) push_frontend_feature_flag(:prometheus_computed_alerts) - push_frontend_feature_flag(:export_metrics_to_csv_enabled) end def index diff --git a/changelogs/unreleased/64950-move-download-csv-button-functionality-in-metrics-dashboard-cards-i.yml b/changelogs/unreleased/64950-move-download-csv-button-functionality-in-metrics-dashboard-cards-i.yml new file mode 100644 index 00000000000..21771c76873 --- /dev/null +++ b/changelogs/unreleased/64950-move-download-csv-button-functionality-in-metrics-dashboard-cards-i.yml @@ -0,0 +1,5 @@ +--- +title: 'feat: adds a download to csv functionality to the dropdown in prometheus metrics' +merge_request: 31679 +author: +type: changed diff --git a/spec/javascripts/monitoring/charts/area_spec.js b/spec/javascripts/monitoring/charts/area_spec.js index 4541119dd2e..57f99a09002 100644 --- a/spec/javascripts/monitoring/charts/area_spec.js +++ b/spec/javascripts/monitoring/charts/area_spec.js @@ -24,7 +24,6 @@ describe('Area component', () => { store.commit(`monitoringDashboard/${types.RECEIVE_METRICS_DATA_SUCCESS}`, MonitoringMock.data); store.commit(`monitoringDashboard/${types.RECEIVE_DEPLOYMENTS_DATA_SUCCESS}`, deploymentData); - store.dispatch('monitoringDashboard/setFeatureFlags', { exportMetricsToCsvEnabled: true }); [mockGraphData] = store.state.monitoringDashboard.groups[0].metrics; areaChart = shallowMount(Area, { @@ -109,16 +108,6 @@ describe('Area component', () => { }); }); - describe('when exportMetricsToCsvEnabled is disabled', () => { - beforeEach(() => { - store.dispatch('monitoringDashboard/setFeatureFlags', { exportMetricsToCsvEnabled: false }); - }); - - it('does not render the Download CSV button', () => { - expect(areaChart.contains('glbutton-stub')).toBe(false); - }); - }); - describe('methods', () => { describe('formatTooltipText', () => { const mockDate = deploymentData[0].created_at; @@ -264,23 +253,5 @@ describe('Area component', () => { expect(areaChart.vm.yAxisLabel).toBe('CPU'); }); }); - - describe('csvText', () => { - it('converts data from json to csv', () => { - const header = `timestamp,${mockGraphData.y_label}`; - const data = mockGraphData.queries[0].result[0].values; - const firstRow = `${data[0][0]},${data[0][1]}`; - - expect(areaChart.vm.csvText).toMatch(`^${header}\r\n${firstRow}`); - }); - }); - - describe('downloadLink', () => { - it('produces a link to download metrics as csv', () => { - const link = areaChart.vm.downloadLink; - - expect(link).toContain('blob:'); - }); - }); }); }); diff --git a/spec/javascripts/monitoring/dashboard_spec.js b/spec/javascripts/monitoring/dashboard_spec.js index 36f650d5933..b78896c45fc 100644 --- a/spec/javascripts/monitoring/dashboard_spec.js +++ b/spec/javascripts/monitoring/dashboard_spec.js @@ -5,7 +5,7 @@ import { timeWindows, timeWindowsKeyNames } from '~/monitoring/constants'; import * as types from '~/monitoring/stores/mutation_types'; import { createStore } from '~/monitoring/stores'; import axios from '~/lib/utils/axios_utils'; -import { +import MonitoringMock, { metricsGroupsAPIResponse, mockApiEndpoint, environmentData, @@ -40,6 +40,7 @@ describe('Dashboard', () => { let mock; let store; let component; + let mockGraphData; beforeEach(() => { setFixtures(` @@ -482,4 +483,36 @@ describe('Dashboard', () => { }); }); }); + + describe('when downloading metrics data as CSV', () => { + beforeEach(() => { + component = new DashboardComponent({ + propsData: { + ...propsData, + }, + store, + }); + store.commit( + `monitoringDashboard/${types.RECEIVE_METRICS_DATA_SUCCESS}`, + MonitoringMock.data, + ); + [mockGraphData] = component.$store.state.monitoringDashboard.groups[0].metrics; + }); + + describe('csvText', () => { + it('converts metrics data from json to csv', () => { + const header = `timestamp,${mockGraphData.y_label}`; + const data = mockGraphData.queries[0].result[0].values; + const firstRow = `${data[0][0]},${data[0][1]}`; + + expect(component.csvText(mockGraphData)).toMatch(`^${header}\r\n${firstRow}`); + }); + }); + + describe('downloadCsv', () => { + it('produces a link with a Blob', () => { + expect(component.downloadCsv(mockGraphData)).toContain(`blob:`); + }); + }); + }); }); |