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.vue407
1 files changed, 55 insertions, 352 deletions
diff --git a/app/assets/javascripts/monitoring/components/dashboard.vue b/app/assets/javascripts/monitoring/components/dashboard.vue
index 2018c706b11..f54319d283e 100644
--- a/app/assets/javascripts/monitoring/components/dashboard.vue
+++ b/app/assets/javascripts/monitoring/components/dashboard.vue
@@ -1,73 +1,45 @@
<script>
-import { debounce } from 'lodash';
import { mapActions, mapState, mapGetters } from 'vuex';
import VueDraggable from 'vuedraggable';
-import {
- GlIcon,
- GlButton,
- GlDeprecatedButton,
- GlDropdown,
- GlDropdownItem,
- GlDropdownHeader,
- GlDropdownDivider,
- GlModal,
- GlLoadingIcon,
- GlSearchBoxByType,
- GlModalDirective,
- GlTooltipDirective,
-} from '@gitlab/ui';
+import { GlIcon, GlButton, GlModalDirective, GlTooltipDirective } from '@gitlab/ui';
+import DashboardHeader from './dashboard_header.vue';
import DashboardPanel from './dashboard_panel.vue';
import { s__ } from '~/locale';
import createFlash from '~/flash';
import { ESC_KEY, ESC_KEY_IE11 } from '~/lib/utils/keys';
-import CustomMetricsFormFields from '~/custom_metrics/components/custom_metrics_form_fields.vue';
-import { mergeUrlParams, redirectTo, updateHistory } from '~/lib/utils/url_utility';
+import { mergeUrlParams, updateHistory } from '~/lib/utils/url_utility';
import invalidUrl from '~/lib/utils/invalid_url';
import Icon from '~/vue_shared/components/icon.vue';
-import DateTimePicker from '~/vue_shared/components/date_time_picker/date_time_picker.vue';
import GraphGroup from './graph_group.vue';
import EmptyState from './empty_state.vue';
import GroupEmptyState from './group_empty_state.vue';
-import DashboardsDropdown from './dashboards_dropdown.vue';
import VariablesSection from './variables_section.vue';
+import LinksSection from './links_section.vue';
import TrackEventDirective from '~/vue_shared/directives/track_event';
import {
- getAddMetricTrackingOptions,
- timeRangeToUrl,
timeRangeFromUrl,
panelToUrl,
expandedPanelPayloadFromUrl,
convertVariablesForURL,
} from '../utils';
import { metricStates } from '../constants';
-import { defaultTimeRange, timeRanges } from '~/vue_shared/constants';
+import { defaultTimeRange } from '~/vue_shared/constants';
export default {
components: {
VueDraggable,
+ DashboardHeader,
DashboardPanel,
Icon,
GlIcon,
GlButton,
- GlDeprecatedButton,
- GlDropdown,
- GlLoadingIcon,
- GlDropdownItem,
- GlDropdownHeader,
- GlDropdownDivider,
- GlSearchBoxByType,
- GlModal,
- CustomMetricsFormFields,
-
- DateTimePicker,
GraphGroup,
EmptyState,
GroupEmptyState,
- DashboardsDropdown,
-
VariablesSection,
+ LinksSection,
},
directives: {
GlModal: GlModalDirective,
@@ -111,27 +83,10 @@ export default {
type: String,
required: true,
},
- projectPath: {
- type: String,
- required: true,
- },
- logsPath: {
- type: String,
- required: false,
- default: invalidUrl,
- },
defaultBranch: {
type: String,
- required: true,
- },
- metricsEndpoint: {
- type: String,
- required: true,
- },
- deploymentsEndpoint: {
- type: String,
required: false,
- default: null,
+ default: '',
},
emptyGettingStartedSvgPath: {
type: String,
@@ -153,10 +108,6 @@ export default {
type: String,
required: true,
},
- currentEnvironmentName: {
- type: String,
- required: true,
- },
customMetricsAvailable: {
type: Boolean,
required: false,
@@ -172,21 +123,6 @@ export default {
required: false,
default: invalidUrl,
},
- dashboardEndpoint: {
- type: String,
- required: false,
- default: invalidUrl,
- },
- dashboardsEndpoint: {
- type: String,
- required: false,
- default: invalidUrl,
- },
- currentDashboard: {
- type: String,
- required: false,
- default: '',
- },
smallEmptyState: {
type: Boolean,
required: false,
@@ -210,11 +146,9 @@ export default {
},
data() {
return {
- formIsValid: null,
selectedTimeRange: timeRangeFromUrl() || defaultTimeRange,
- hasValidDates: true,
- timeRanges,
isRearrangingPanels: false,
+ originalDocumentTitle: document.title,
};
},
computed: {
@@ -222,36 +156,17 @@ export default {
'dashboard',
'emptyState',
'showEmptyState',
- 'useDashboardEndpoint',
- 'allDashboards',
- 'environmentsLoading',
'expandedPanel',
- 'promVariables',
- 'isUpdatingStarredValue',
- ]),
- ...mapGetters('monitoringDashboard', [
- 'selectedDashboard',
- 'getMetricStates',
- 'filteredEnvironments',
+ 'variables',
+ 'links',
+ 'currentDashboard',
]),
- showRearrangePanelsBtn() {
- return !this.showEmptyState && this.rearrangePanelsAvailable;
- },
- addingMetricsAvailable() {
- return (
- this.customMetricsAvailable &&
- !this.showEmptyState &&
- // Custom metrics only avaialble on system dashboards because
- // they are stored in the database. This can be improved. See:
- // https://gitlab.com/gitlab-org/gitlab/-/issues/28241
- this.selectedDashboard?.system_dashboard
- );
- },
- shouldShowEnvironmentsDropdownNoMatchedMsg() {
- return !this.environmentsLoading && this.filteredEnvironments.length === 0;
- },
+ ...mapGetters('monitoringDashboard', ['selectedDashboard', 'getMetricStates']),
shouldShowVariablesSection() {
- return Object.keys(this.promVariables).length > 0;
+ return Object.keys(this.variables).length > 0;
+ },
+ shouldShowLinksSection() {
+ return Object.keys(this.links).length > 0;
},
},
watch: {
@@ -273,24 +188,17 @@ export default {
handler({ group, panel }) {
const dashboardPath = this.currentDashboard || this.selectedDashboard?.path;
updateHistory({
- url: panelToUrl(dashboardPath, convertVariablesForURL(this.promVariables), group, panel),
+ url: panelToUrl(dashboardPath, convertVariablesForURL(this.variables), group, panel),
title: document.title,
});
},
deep: true,
},
+ selectedDashboard(dashboard) {
+ this.prependToDocumentTitle(dashboard?.display_name);
+ },
},
created() {
- this.setInitialState({
- metricsEndpoint: this.metricsEndpoint,
- deploymentsEndpoint: this.deploymentsEndpoint,
- dashboardEndpoint: this.dashboardEndpoint,
- dashboardsEndpoint: this.dashboardsEndpoint,
- currentDashboard: this.currentDashboard,
- projectPath: this.projectPath,
- logsPath: this.logsPath,
- currentEnvironmentName: this.currentEnvironmentName,
- });
window.addEventListener('keyup', this.onKeyup);
},
destroyed() {
@@ -308,14 +216,10 @@ export default {
...mapActions('monitoringDashboard', [
'setTimeRange',
'fetchData',
- 'fetchDashboardData',
'setGettingStartedEmptyState',
- 'setInitialState',
'setPanelGroupMetrics',
- 'filterEnvironments',
'setExpandedPanel',
'clearExpandedPanel',
- 'toggleStarredValue',
]),
updatePanels(key, panels) {
this.setPanelGroupMetrics({
@@ -329,37 +233,9 @@ export default {
key,
});
},
-
- onDateTimePickerInput(timeRange) {
- redirectTo(timeRangeToUrl(timeRange));
- },
- onDateTimePickerInvalid() {
- createFlash(
- s__(
- 'Metrics|Link contains an invalid time window, please verify the link to see the requested time range.',
- ),
- );
- // As a fallback, switch to default time range instead
- this.selectedTimeRange = defaultTimeRange;
- },
generatePanelUrl(groupKey, panel) {
const dashboardPath = this.currentDashboard || this.selectedDashboard?.path;
- return panelToUrl(dashboardPath, convertVariablesForURL(this.promVariables), groupKey, panel);
- },
- hideAddMetricModal() {
- this.$refs.addMetricModal.hide();
- },
- toggleRearrangingPanels() {
- this.isRearrangingPanels = !this.isRearrangingPanels;
- },
- setFormValidity(isValid) {
- this.formIsValid = isValid;
- },
- debouncedEnvironmentsSearch: debounce(function environmentsSearchOnInput(searchTerm) {
- this.filterEnvironments(searchTerm);
- }, 500),
- submitCustomMetricsForm() {
- this.$refs.customMetricsForm.submit();
+ return panelToUrl(dashboardPath, convertVariablesForURL(this.variables), groupKey, panel);
},
/**
* Return a single empty state for a group.
@@ -387,25 +263,20 @@ export default {
// Collapse group if no data is available
return !this.getMetricStates(groupKey).includes(metricStates.OK);
},
- getAddMetricTrackingOptions,
-
- selectDashboard(dashboard) {
- const params = {
- dashboard: dashboard.path,
- };
- redirectTo(mergeUrlParams(params, window.location.href));
- },
-
- refreshDashboard() {
- this.fetchDashboardData();
+ prependToDocumentTitle(text) {
+ if (text) {
+ document.title = `${text} ยท ${this.originalDocumentTitle}`;
+ }
},
-
onTimeRangeZoom({ start, end }) {
updateHistory({
url: mergeUrlParams({ start, end }, window.location.href),
title: document.title,
});
this.selectedTimeRange = { start, end };
+ // keep the current dashboard time range
+ // in sync with the Vuex store
+ this.setTimeRange(this.selectedTimeRange);
},
onExpandPanel(group, panel) {
this.setExpandedPanel({ group, panel });
@@ -419,213 +290,45 @@ export default {
this.clearExpandedPanel();
}
},
- },
- addMetric: {
- title: s__('Metrics|Add metric'),
- modalId: 'add-metric',
+ onSetRearrangingPanels(isRearrangingPanels) {
+ this.isRearrangingPanels = isRearrangingPanels;
+ },
+ onDateTimePickerInvalid() {
+ createFlash(
+ s__(
+ 'Metrics|Link contains an invalid time window, please verify the link to see the requested time range.',
+ ),
+ );
+ // As a fallback, switch to default time range instead
+ this.selectedTimeRange = defaultTimeRange;
+ },
},
i18n: {
goBackLabel: s__('Metrics|Go back (Esc)'),
- starDashboard: s__('Metrics|Star dashboard'),
- unstarDashboard: s__('Metrics|Unstar dashboard'),
},
};
</script>
<template>
<div class="prometheus-graphs" data-qa-selector="prometheus_graphs">
- <div
+ <dashboard-header
v-if="showHeader"
ref="prometheusGraphsHeader"
class="prometheus-graphs-header d-sm-flex flex-sm-wrap pt-2 pr-1 pb-0 pl-2 border-bottom bg-gray-light"
- >
- <div class="mb-2 pr-2 d-flex d-sm-block">
- <dashboards-dropdown
- id="monitor-dashboards-dropdown"
- data-qa-selector="dashboards_filter_dropdown"
- class="flex-grow-1"
- toggle-class="dropdown-menu-toggle"
- :default-branch="defaultBranch"
- @selectDashboard="selectDashboard($event)"
- />
- </div>
-
- <div class="mb-2 pr-2 d-flex d-sm-block">
- <gl-dropdown
- id="monitor-environments-dropdown"
- ref="monitorEnvironmentsDropdown"
- class="flex-grow-1"
- data-qa-selector="environments_dropdown"
- toggle-class="dropdown-menu-toggle"
- menu-class="monitor-environment-dropdown-menu"
- :text="currentEnvironmentName"
- >
- <div class="d-flex flex-column overflow-hidden">
- <gl-dropdown-header class="monitor-environment-dropdown-header text-center">
- {{ __('Environment') }}
- </gl-dropdown-header>
- <gl-dropdown-divider />
- <gl-search-box-by-type
- ref="monitorEnvironmentsDropdownSearch"
- class="m-2"
- @input="debouncedEnvironmentsSearch"
- />
- <gl-loading-icon
- v-if="environmentsLoading"
- ref="monitorEnvironmentsDropdownLoading"
- :inline="true"
- />
- <div v-else class="flex-fill overflow-auto">
- <gl-dropdown-item
- v-for="environment in filteredEnvironments"
- :key="environment.id"
- :active="environment.name === currentEnvironmentName"
- active-class="is-active"
- :href="environment.metrics_path"
- >{{ environment.name }}</gl-dropdown-item
- >
- </div>
- <div
- v-show="shouldShowEnvironmentsDropdownNoMatchedMsg"
- ref="monitorEnvironmentsDropdownMsg"
- class="text-secondary no-matches-message"
- >
- {{ __('No matching results') }}
- </div>
- </div>
- </gl-dropdown>
- </div>
-
- <div class="mb-2 pr-2 d-flex d-sm-block">
- <date-time-picker
- ref="dateTimePicker"
- class="flex-grow-1 show-last-dropdown"
- data-qa-selector="range_picker_dropdown"
- :value="selectedTimeRange"
- :options="timeRanges"
- @input="onDateTimePickerInput"
- @invalid="onDateTimePickerInvalid"
- />
- </div>
-
- <div class="mb-2 pr-2 d-flex d-sm-block">
- <gl-deprecated-button
- ref="refreshDashboardBtn"
- v-gl-tooltip
- class="flex-grow-1"
- variant="default"
- :title="s__('Metrics|Refresh dashboard')"
- @click="refreshDashboard"
- >
- <icon name="retry" />
- </gl-deprecated-button>
- </div>
-
- <div class="flex-grow-1"></div>
-
- <div class="d-sm-flex">
- <div v-if="selectedDashboard" class="mb-2 mr-2 d-flex">
- <!--
- wrapper for tooltip as button can be `disabled`
- https://bootstrap-vue.org/docs/components/tooltip#disabled-elements
- -->
- <div
- v-gl-tooltip
- class="flex-grow-1"
- :title="
- selectedDashboard.starred
- ? $options.i18n.unstarDashboard
- : $options.i18n.starDashboard
- "
- >
- <gl-deprecated-button
- ref="toggleStarBtn"
- class="w-100"
- :disabled="isUpdatingStarredValue"
- variant="default"
- @click="toggleStarredValue()"
- >
- <gl-icon :name="selectedDashboard.starred ? 'star' : 'star-o'" />
- </gl-deprecated-button>
- </div>
- </div>
-
- <div v-if="showRearrangePanelsBtn" class="mb-2 mr-2 d-flex">
- <gl-deprecated-button
- :pressed="isRearrangingPanels"
- variant="default"
- class="flex-grow-1 js-rearrange-button"
- @click="toggleRearrangingPanels"
- >
- {{ __('Arrange charts') }}
- </gl-deprecated-button>
- </div>
- <div v-if="addingMetricsAvailable" class="mb-2 mr-2 d-flex d-sm-block">
- <gl-deprecated-button
- ref="addMetricBtn"
- v-gl-modal="$options.addMetric.modalId"
- variant="outline-success"
- data-qa-selector="add_metric_button"
- class="flex-grow-1"
- >
- {{ $options.addMetric.title }}
- </gl-deprecated-button>
- <gl-modal
- ref="addMetricModal"
- :modal-id="$options.addMetric.modalId"
- :title="$options.addMetric.title"
- >
- <form ref="customMetricsForm" :action="customMetricsPath" method="post">
- <custom-metrics-form-fields
- :validate-query-path="validateQueryPath"
- form-operation="post"
- @formValidation="setFormValidity"
- />
- </form>
- <div slot="modal-footer">
- <gl-deprecated-button @click="hideAddMetricModal">
- {{ __('Cancel') }}
- </gl-deprecated-button>
- <gl-deprecated-button
- ref="submitCustomMetricsFormBtn"
- v-track-event="getAddMetricTrackingOptions()"
- :disabled="!formIsValid"
- variant="success"
- @click="submitCustomMetricsForm"
- >
- {{ __('Save changes') }}
- </gl-deprecated-button>
- </div>
- </gl-modal>
- </div>
-
- <div
- v-if="selectedDashboard && selectedDashboard.can_edit"
- class="mb-2 mr-2 d-flex d-sm-block"
- >
- <gl-deprecated-button
- class="flex-grow-1 js-edit-link"
- :href="selectedDashboard.project_blob_path"
- data-qa-selector="edit_dashboard_button"
- >
- {{ __('Edit dashboard') }}
- </gl-deprecated-button>
- </div>
-
- <div v-if="externalDashboardUrl.length" class="mb-2 mr-2 d-flex d-sm-block">
- <gl-deprecated-button
- class="flex-grow-1 js-external-dashboard-link"
- variant="primary"
- :href="externalDashboardUrl"
- target="_blank"
- rel="noopener noreferrer"
- >
- {{ __('View full dashboard') }} <icon name="external-link" />
- </gl-deprecated-button>
- </div>
- </div>
- </div>
+ :default-branch="defaultBranch"
+ :rearrange-panels-available="rearrangePanelsAvailable"
+ :custom-metrics-available="customMetricsAvailable"
+ :custom-metrics-path="customMetricsPath"
+ :validate-query-path="validateQueryPath"
+ :external-dashboard-url="externalDashboardUrl"
+ :has-metrics="hasMetrics"
+ :is-rearranging-panels="isRearrangingPanels"
+ :selected-time-range="selectedTimeRange"
+ @dateTimePickerInvalid="onDateTimePickerInvalid"
+ @setRearrangingPanels="onSetRearrangingPanels"
+ />
<variables-section v-if="shouldShowVariablesSection && !showEmptyState" />
+ <links-section v-if="shouldShowLinksSection && !showEmptyState" />
<div v-if="!showEmptyState">
<dashboard-panel
v-show="expandedPanel.panel"