summaryrefslogtreecommitdiff
path: root/app/assets/javascripts/monitoring/components/dashboard.vue
diff options
context:
space:
mode:
Diffstat (limited to 'app/assets/javascripts/monitoring/components/dashboard.vue')
-rw-r--r--app/assets/javascripts/monitoring/components/dashboard.vue175
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)