diff options
Diffstat (limited to 'app/assets/javascripts/monitoring/components/dashboard.vue')
-rw-r--r-- | app/assets/javascripts/monitoring/components/dashboard.vue | 175 |
1 files changed, 117 insertions, 58 deletions
diff --git a/app/assets/javascripts/monitoring/components/dashboard.vue b/app/assets/javascripts/monitoring/components/dashboard.vue index 12a4c83e053..b4ea415bb51 100644 --- a/app/assets/javascripts/monitoring/components/dashboard.vue +++ b/app/assets/javascripts/monitoring/components/dashboard.vue @@ -1,4 +1,7 @@ <script> +import _ from 'underscore'; +import { mapActions, mapState } from 'vuex'; +import VueDraggable from 'vuedraggable'; import { GlButton, GlDropdown, @@ -8,24 +11,26 @@ import { GlModalDirective, GlTooltipDirective, } from '@gitlab/ui'; -import _ from 'underscore'; -import { mapActions, mapState } from 'vuex'; import { __, s__ } from '~/locale'; +import createFlash from '~/flash'; import Icon from '~/vue_shared/components/icon.vue'; -import { getParameterValues, mergeUrlParams } from '~/lib/utils/url_utility'; +import { getParameterValues, mergeUrlParams, redirectTo } from '~/lib/utils/url_utility'; import invalidUrl from '~/lib/utils/invalid_url'; import PanelType from 'ee_else_ce/monitoring/components/panel_type.vue'; +import DateTimePicker from './date_time_picker/date_time_picker.vue'; import MonitorTimeSeriesChart from './charts/time_series.vue'; import MonitorSingleStatChart from './charts/single_stat.vue'; import GraphGroup from './graph_group.vue'; import EmptyState from './empty_state.vue'; -import { sidebarAnimationDuration, timeWindows } from '../constants'; -import { getTimeDiff, getTimeWindow } from '../utils'; +import { sidebarAnimationDuration } from '../constants'; +import TrackEventDirective from '~/vue_shared/directives/track_event'; +import { getTimeDiff, isValidDate, downloadCSVOptions, generateLinkToChartOptions } from '../utils'; let sidebarMutationObserver; export default { components: { + VueDraggable, MonitorTimeSeriesChart, MonitorSingleStatChart, PanelType, @@ -37,10 +42,12 @@ export default { GlDropdownItem, GlFormGroup, GlModal, + DateTimePicker, }, directives: { GlModal: GlModalDirective, GlTooltip: GlTooltipDirective, + TrackEvent: TrackEventDirective, }, props: { externalDashboardUrl: { @@ -151,15 +158,19 @@ export default { required: false, default: false, }, + rearrangePanelsAvailable: { + type: Boolean, + required: false, + default: false, + }, }, data() { return { state: 'gettingStarted', elWidth: 0, - selectedTimeWindow: '', - selectedTimeWindowKey: '', formIsValid: null, - timeWindows: {}, + selectedTimeWindow: {}, + isRearrangingPanels: false, }; }, computed: { @@ -175,7 +186,6 @@ export default { 'metricsWithData', 'useDashboardEndpoint', 'allDashboards', - 'multipleDashboardsEnabled', 'additionalPanelTypesEnabled', ]), firstDashboard() { @@ -184,6 +194,9 @@ export default { selectedDashboardText() { return this.currentDashboard || this.firstDashboard.display_name; }, + showRearrangePanelsBtn() { + return !this.showEmptyState && this.rearrangePanelsAvailable; + }, addingMetricsAvailable() { return IS_EE && this.canAddMetrics && !this.showEmptyState; }, @@ -219,11 +232,13 @@ export default { end, }; - this.timeWindows = timeWindows; - this.selectedTimeWindowKey = getTimeWindow(range); - this.selectedTimeWindow = this.timeWindows[this.selectedTimeWindowKey]; + this.selectedTimeWindow = range; - this.fetchData(range); + if (!isValidDate(start) || !isValidDate(end)) { + this.showInvalidDateError(); + } else { + this.fetchData(range); + } sidebarMutationObserver = new MutationObserver(this.onSidebarMutation); sidebarMutationObserver.observe(document.querySelector('.layout-page'), { @@ -272,9 +287,17 @@ export default { return Object.values(this.getGraphAlerts(queries)); }, showToast() { - this.$toast.show(__('Link copied to clipboard')); + this.$toast.show(__('Link copied')); }, // TODO: END + removeGraph(metrics, graphIndex) { + // At present graphs will not be removed, they should removed using the vuex store + // See https://gitlab.com/gitlab-org/gitlab/issues/27835 + metrics.splice(graphIndex, 1); + }, + showInvalidDateError() { + createFlash(s__('Metrics|Link contains an invalid time window.')); + }, generateLink(group, title, yLabel) { const dashboard = this.currentDashboard || this.firstDashboard.path; const params = _.pick({ dashboard, group, title, y_label: yLabel }, value => value != null); @@ -288,22 +311,23 @@ export default { this.elWidth = this.$el.clientWidth; }, sidebarAnimationDuration); }, + toggleRearrangingPanels() { + this.isRearrangingPanels = !this.isRearrangingPanels; + }, setFormValidity(isValid) { this.formIsValid = isValid; }, submitCustomMetricsForm() { this.$refs.customMetricsForm.submit(); }, - activeTimeWindow(key) { - return this.timeWindows[key] === this.selectedTimeWindow; - }, - setTimeWindowParameter(key) { - const { start, end } = getTimeDiff(key); - return `?start=${encodeURIComponent(start)}&end=${encodeURIComponent(end)}`; - }, groupHasData(group) { return this.chartsWithData(group.metrics).length > 0; }, + onDateTimePickerApply(timeWindowUrlParams) { + return redirectTo(mergeUrlParams(timeWindowUrlParams, window.location.href)); + }, + downloadCSVOptions, + generateLinkToChartOptions, }, addMetric: { title: s__('Metrics|Add metric'), @@ -314,15 +338,14 @@ export default { <template> <div class="prometheus-graphs"> - <div class="gl-p-3 pb-0 border-bottom bg-gray-light"> + <div class="prometheus-graphs-header gl-p-3 pb-0 border-bottom bg-gray-light"> <div class="row"> <template v-if="environmentsEndpoint"> <gl-form-group - v-if="multipleDashboardsEnabled" :label="__('Dashboard')" label-size="sm" label-for="monitor-dashboards-dropdown" - class="col-sm-12 col-md-4 col-lg-2" + class="col-sm-12 col-md-6 col-lg-2" > <gl-dropdown id="monitor-dashboards-dropdown" @@ -345,7 +368,7 @@ export default { :label="s__('Metrics|Environment')" label-size="sm" label-for="monitor-environments-dropdown" - class="col-sm-6 col-md-4 col-lg-2" + class="col-sm-6 col-md-6 col-lg-2" > <gl-dropdown id="monitor-environments-dropdown" @@ -370,36 +393,35 @@ export default { :label="s__('Metrics|Show last')" label-size="sm" label-for="monitor-time-window-dropdown" - class="col-sm-6 col-md-4 col-lg-2" + class="col-sm-6 col-md-6 col-lg-4" > - <gl-dropdown - id="monitor-time-window-dropdown" - class="mb-0 d-flex js-time-window-dropdown" - toggle-class="dropdown-menu-toggle" - :text="selectedTimeWindow" - > - <gl-dropdown-item - v-for="(value, key) in timeWindows" - :key="key" - :active="activeTimeWindow(key)" - :href="setTimeWindowParameter(key)" - active-class="active" - >{{ value }}</gl-dropdown-item - > - </gl-dropdown> + <date-time-picker + :selected-time-window="selectedTimeWindow" + @onApply="onDateTimePickerApply" + /> </gl-form-group> </template> <gl-form-group - v-if="addingMetricsAvailable || externalDashboardUrl.length" + v-if="addingMetricsAvailable || showRearrangePanelsBtn || externalDashboardUrl.length" label-for="prometheus-graphs-dropdown-buttons" - class="dropdown-buttons col-lg d-lg-flex align-items-end" + class="dropdown-buttons col-md d-md-flex col-lg d-lg-flex align-items-end" > <div id="prometheus-graphs-dropdown-buttons"> <gl-button + v-if="showRearrangePanelsBtn" + :pressed="isRearrangingPanels" + variant="default" + class="mr-2 mt-1 js-rearrange-button" + @click="toggleRearrangingPanels" + > + {{ __('Arrange charts') }} + </gl-button> + <gl-button v-if="addingMetricsAvailable" v-gl-modal="$options.addMetric.modalId" - class="mr-2 mt-1 js-add-metric-button text-success border-success" + variant="outline-success" + class="mr-2 mt-1 js-add-metric-button" > {{ $options.addMetric.title }} </gl-button> @@ -453,17 +475,42 @@ export default { :collapse-group="groupHasData(groupData)" > <template v-if="additionalPanelTypesEnabled"> - <panel-type - v-for="(graphData, graphIndex) in groupData.metrics" - :key="`panel-type-${graphIndex}`" - class="col-12 col-lg-6 pb-3" - :clipboard-text="generateLink(groupData.group, graphData.title, graphData.y_label)" - :graph-data="graphData" - :dashboard-width="elWidth" - :alerts-endpoint="alertsEndpoint" - :prometheus-alerts-available="prometheusAlertsAvailable" - :index="`${index}-${graphIndex}`" - /> + <vue-draggable + :list="groupData.metrics" + group="metrics-dashboard" + :component-data="{ attrs: { class: 'row mx-0 w-100' } }" + :disabled="!isRearrangingPanels" + > + <div + v-for="(graphData, graphIndex) in groupData.metrics" + :key="`panel-type-${graphIndex}`" + class="col-12 col-lg-6 px-2 mb-2 draggable" + :class="{ 'draggable-enabled': isRearrangingPanels }" + > + <div class="position-relative draggable-panel js-draggable-panel"> + <div + v-if="isRearrangingPanels" + class="draggable-remove js-draggable-remove p-2 w-100 position-absolute d-flex justify-content-end" + @click="removeGraph(groupData.metrics, graphIndex)" + > + <a class="mx-2 p-2 draggable-remove-link" :aria-label="__('Remove')" + ><icon name="close" + /></a> + </div> + + <panel-type + :clipboard-text=" + generateLink(groupData.group, graphData.title, graphData.y_label) + " + :graph-data="graphData" + :dashboard-width="elWidth" + :alerts-endpoint="alertsEndpoint" + :prometheus-alerts-available="prometheusAlertsAvailable" + :index="`${index}-${graphIndex}`" + /> + </div> + </div> + </vue-draggable> </template> <template v-else> <monitor-time-series-chart @@ -477,7 +524,10 @@ export default { :project-path="projectPath" group-id="monitor-time-series-chart" > - <div class="d-flex align-items-center"> + <div + class="d-flex align-items-center" + :class="alertWidgetAvailable ? 'justify-content-between' : 'justify-content-end'" + > <alert-widget v-if="alertWidgetAvailable && graphData" :modal-id="`alert-modal-${index}-${graphIndex}`" @@ -488,7 +538,7 @@ export default { /> <gl-dropdown v-gl-tooltip - class="mx-2" + class="ml-2 mr-3" toggle-class="btn btn-transparent border-0" :right="true" :no-caret="true" @@ -497,10 +547,19 @@ export default { <template slot="button-content"> <icon name="ellipsis_v" class="text-secondary" /> </template> - <gl-dropdown-item :href="downloadCsv(graphData)" download="chart_metrics.csv"> + <gl-dropdown-item + v-track-event="downloadCSVOptions(graphData.title)" + :href="downloadCsv(graphData)" + download="chart_metrics.csv" + > {{ __('Download CSV') }} </gl-dropdown-item> <gl-dropdown-item + v-track-event=" + generateLinkToChartOptions( + generateLink(groupData.group, graphData.title, graphData.y_label), + ) + " class="js-chart-link" :data-clipboard-text=" generateLink(groupData.group, graphData.title, graphData.y_label) |