diff options
Diffstat (limited to 'app/assets/javascripts/monitoring/components/dashboard.vue')
-rw-r--r-- | app/assets/javascripts/monitoring/components/dashboard.vue | 407 |
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" |