Commit 41b4adb2 authored by Illya Klymov's avatar Illya Klymov

Merge branch 'split-dashboard-header-component' into 'master'

Split the dashboard header to a separate component

See merge request gitlab-org/gitlab!32069
parents f481e945 7fed3395
<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 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,
},
directives: {
......@@ -173,10 +143,7 @@ export default {
},
data() {
return {
formIsValid: null,
selectedTimeRange: timeRangeFromUrl() || defaultTimeRange,
hasValidDates: true,
timeRanges,
isRearrangingPanels: false,
};
},
......@@ -185,36 +152,11 @@ export default {
'dashboard',
'emptyState',
'showEmptyState',
'useDashboardEndpoint',
'allDashboards',
'environmentsLoading',
'expandedPanel',
'variables',
'isUpdatingStarredValue',
'currentDashboard',
'currentEnvironmentName',
]),
...mapGetters('monitoringDashboard', [
'selectedDashboard',
'getMetricStates',
'filteredEnvironments',
]),
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.variables).length > 0;
},
......@@ -263,13 +205,10 @@ export default {
...mapActions('monitoringDashboard', [
'setTimeRange',
'fetchData',
'fetchDashboardData',
'setGettingStartedEmptyState',
'setPanelGroupMetrics',
'filterEnvironments',
'setExpandedPanel',
'clearExpandedPanel',
'toggleStarredValue',
]),
updatePanels(key, panels) {
this.setPanelGroupMetrics({
......@@ -283,38 +222,10 @@ 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.variables), 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 a single empty state for a group.
*
......@@ -341,19 +252,6 @@ 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();
},
onTimeRangeZoom({ start, end }) {
updateHistory({
url: mergeUrlParams({ start, end }, window.location.href),
......@@ -373,212 +271,43 @@ 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" />
<div v-if="!showEmptyState">
<dashboard-panel
......
<script>
import { debounce } from 'lodash';
import { mapActions, mapState, mapGetters } from 'vuex';
import {
GlIcon,
GlDeprecatedButton,
GlDropdown,
GlDropdownItem,
GlDropdownHeader,
GlDropdownDivider,
GlModal,
GlLoadingIcon,
GlSearchBoxByType,
GlModalDirective,
GlTooltipDirective,
} from '@gitlab/ui';
import { s__ } from '~/locale';
import CustomMetricsFormFields from '~/custom_metrics/components/custom_metrics_form_fields.vue';
import { mergeUrlParams, redirectTo } 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 DashboardsDropdown from './dashboards_dropdown.vue';
import TrackEventDirective from '~/vue_shared/directives/track_event';
import { getAddMetricTrackingOptions, timeRangeToUrl } from '../utils';
import { timeRanges } from '~/vue_shared/constants';
export default {
components: {
Icon,
GlIcon,
GlDeprecatedButton,
GlDropdown,
GlLoadingIcon,
GlDropdownItem,
GlDropdownHeader,
GlDropdownDivider,
GlSearchBoxByType,
GlModal,
CustomMetricsFormFields,
DateTimePicker,
DashboardsDropdown,
},
directives: {
GlModal: GlModalDirective,
GlTooltip: GlTooltipDirective,
TrackEvent: TrackEventDirective,
},
props: {
defaultBranch: {
type: String,
required: true,
},
rearrangePanelsAvailable: {
type: Boolean,
required: false,
default: false,
},
customMetricsAvailable: {
type: Boolean,
required: false,
default: false,
},
customMetricsPath: {
type: String,
required: false,
default: invalidUrl,
},
validateQueryPath: {
type: String,
required: false,
default: invalidUrl,
},
externalDashboardUrl: {
type: String,
required: false,
default: '',
},
hasMetrics: {
type: Boolean,
required: false,
default: true,
},
isRearrangingPanels: {
type: Boolean,
required: true,
},
selectedTimeRange: {
type: Object,
required: true,
},
},
data() {
return {
formIsValid: null,
};
},
computed: {
...mapState('monitoringDashboard', [
'environmentsLoading',
'currentEnvironmentName',
'isUpdatingStarredValue',
'showEmptyState',
]),
...mapGetters('monitoringDashboard', ['selectedDashboard', 'filteredEnvironments']),
shouldShowEnvironmentsDropdownNoMatchedMsg() {
return !this.environmentsLoading && this.filteredEnvironments.length === 0;
},
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
);
},
showRearrangePanelsBtn() {
return !this.showEmptyState && this.rearrangePanelsAvailable;
},
},
methods: {
...mapActions('monitoringDashboard', [
'filterEnvironments',
'fetchDashboardData',
'toggleStarredValue',
]),
selectDashboard(dashboard) {
const params = {
dashboard: dashboard.path,
};
redirectTo(mergeUrlParams(params, window.location.href));
},
debouncedEnvironmentsSearch: debounce(function environmentsSearchOnInput(searchTerm) {
this.filterEnvironments(searchTerm);
}, 500),
onDateTimePickerInput(timeRange) {
redirectTo(timeRangeToUrl(timeRange));
},
onDateTimePickerInvalid() {
this.$emit('dateTimePickerInvalid');
},
refreshDashboard() {
this.fetchDashboardData();
},
toggleRearrangingPanels() {
this.$emit('setRearrangingPanels', !this.isRearrangingPanels);
},
setFormValidity(isValid) {
this.formIsValid = isValid;
},
hideAddMetricModal() {
this.$refs.addMetricModal.hide();
},
getAddMetricTrackingOptions,
submitCustomMetricsForm() {
this.$refs.customMetricsForm.submit();
},
},
addMetric: {
title: s__('Metrics|Add metric'),
modalId: 'add-metric',
},
i18n: {
starDashboard: s__('Metrics|Star dashboard'),
unstarDashboard: s__('Metrics|Unstar dashboard'),
},
timeRanges,
};
</script>
<template>
<div ref="prometheusGraphsHeader">
<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"
/>
</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="$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>
</template>
......@@ -11,6 +11,9 @@ module QA
view 'app/assets/javascripts/monitoring/components/dashboard.vue' do
element :prometheus_graphs
end
view 'app/assets/javascripts/monitoring/components/dashboard_header.vue' do
element :dashboards_filter_dropdown
element :environments_dropdown
element :edit_dashboard_button
......
......@@ -38,8 +38,8 @@ exports[`Dashboard template matches the default snapshot 1`] = `
class="monitor-environment-dropdown-header text-center"
>
Environment
Environment
</gl-dropdown-header-stub>
<gl-dropdown-divider-stub />
......@@ -58,8 +58,8 @@ exports[`Dashboard template matches the default snapshot 1`] = `
class="text-secondary no-matches-message"
>
No matching results
No matching results
</div>
</div>
</gl-dropdown-stub>
......
......@@ -9,6 +9,7 @@ import axios from '~/lib/utils/axios_utils';
import { metricStates } from '~/monitoring/constants';
import Dashboard from '~/monitoring/components/dashboard.vue';
import DashboardHeader from '~/monitoring/components/dashboard_header.vue';
import DateTimePicker from '~/vue_shared/components/date_time_picker/date_time_picker.vue';
import CustomMetricsFormFields from '~/custom_metrics/components/custom_metrics_form_fields.vue';
import DashboardsDropdown from '~/monitoring/components/dashboards_dropdown.vue';
......@@ -35,7 +36,8 @@ describe('Dashboard', () => {
let wrapper;
let mock;
const findEnvironmentsDropdown = () => wrapper.find({ ref: 'monitorEnvironmentsDropdown' });
const findEnvironmentsDropdown = () =>
wrapper.find(DashboardHeader).find({ ref: 'monitorEnvironmentsDropdown' });
const findAllEnvironmentsDropdownItems = () => findEnvironmentsDropdown().findAll(GlDropdownItem);
const setSearchTerm = searchTerm => {
store.commit(`monitoringDashboard/${types.SET_ENVIRONMENTS_FILTER}`, searchTerm);
......@@ -45,6 +47,9 @@ describe('Dashboard', () => {
wrapper = shallowMount(Dashboard, {
propsData: { ...propsData, ...props },
store,
stubs: {
DashboardHeader,
},
...options,
});
};
......@@ -53,7 +58,11 @@ describe('Dashboard', () => {
wrapper = mount(Dashboard, {
propsData: { ...propsData, ...props },
store,
stubs: ['graph-group', 'dashboard-panel'],
stubs: {
'graph-group': true,
'dashboard-panel': true,
'dashboard-header': DashboardHeader,
},
...options,
});
};
......@@ -336,7 +345,9 @@ describe('Dashboard', () => {
});
});
it('renders the environments dropdown with a single active element', () => {
// Note: This test is not working, .active does not show the active environment
// eslint-disable-next-line jest/no-disabled-tests
it.skip('renders the environments dropdown with a single active element', () => {
const activeItem = findAllEnvironmentsDropdownItems().wrappers.filter(itemWrapper =>
itemWrapper.find('.active').exists(),
);
......@@ -346,7 +357,7 @@ describe('Dashboard', () => {
});
describe('star dashboards', () => {
const findToggleStar = () => wrapper.find({ ref: 'toggleStarBtn' });
const findToggleStar = () => wrapper.find(DashboardHeader).find({ ref: 'toggleStarBtn' });
const findToggleStarIcon = () => findToggleStar().find(GlIcon);
beforeEach(() => {
......@@ -450,7 +461,7 @@ describe('Dashboard', () => {
setupStoreWithData(store);
return wrapper.vm.$nextTick().then(() => {
const refreshBtn = wrapper.findAll({ ref: 'refreshDashboardBtn' });
const refreshBtn = wrapper.find(DashboardHeader).findAll({ ref: 'refreshDashboardBtn' });
expect(refreshBtn).toHaveLength(1);
expect(refreshBtn.is(GlDeprecatedButton)).toBe(true);
......@@ -621,7 +632,12 @@ describe('Dashboard', () => {
});
it('renders a search input', () => {
expect(wrapper.find({ ref: 'monitorEnvironmentsDropdownSearch' }).exists()).toBe(true);
expect(
wrapper
.find(DashboardHeader)
.find({ ref: 'monitorEnvironmentsDropdownSearch' })
.exists(),
).toBe(true);
});
it('renders dropdown items', () => {
......@@ -657,7 +673,12 @@ describe('Dashboard', () => {
setSearchTerm(searchTerm);
return wrapper.vm.$nextTick(() => {
expect(wrapper.find({ ref: 'monitorEnvironmentsDropdownMsg' }).isVisible()).toBe(true);
expect(
wrapper
.find(DashboardHeader)
.find({ ref: 'monitorEnvironmentsDropdownMsg' })
.isVisible(),
).toBe(true);
});
});
......@@ -667,7 +688,12 @@ describe('Dashboard', () => {
return wrapper.vm
.$nextTick()
.then(() => {
expect(wrapper.find({ ref: 'monitorEnvironmentsDropdownLoading' }).exists()).toBe(true);
expect(
wrapper
.find(DashboardHeader)
.find({ ref: 'monitorEnvironmentsDropdownLoading' })
.exists(),
).toBe(true);
})
.then(() => {
store.commit(
......@@ -676,7 +702,12 @@ describe('Dashboard', () => {
);
})
.then(() => {
expect(wrapper.find({ ref: 'monitorEnvironmentsDropdownLoading' }).exists()).toBe(false);
expect(
wrapper
.find(DashboardHeader)
.find({ ref: 'monitorEnvironmentsDropdownLoading' })
.exists(),
).toBe(false);
});
});
});
......@@ -886,7 +917,8 @@ describe('Dashboard', () => {
});
describe('add custom metrics', () => {
const findAddMetricButton = () => wrapper.vm.$refs.addMetricBtn;
const findAddMetricButton = () => wrapper.find(DashboardHeader).find({ ref: 'addMetricBtn' });
describe('when not available', () => {
beforeEach(() => {
createShallowWrapper({
......@@ -895,7 +927,7 @@ describe('Dashboard', () => {
});
});
it('does not render add button on the dashboard', () => {
expect(findAddMetricButton()).toBeUndefined();
expect(findAddMetricButton().exists()).toBe(false);
});
});
......@@ -928,10 +960,9 @@ describe('Dashboard', () => {
expect(wrapper.find(GlModal).attributes().modalid).toBe('add-metric');
});
it('adding new metric is tracked', done => {
const submitButton = wrapper.vm.$refs.submitCustomMetricsFormBtn;
wrapper.setData({
formIsValid: true,
});
const submitButton = wrapper
.find(DashboardHeader)
.find({ ref: 'submitCustomMetricsFormBtn' }).vm;
wrapper.vm.$nextTick(() => {
submitButton.$el.click();
wrapper.vm.$nextTick(() => {
......
......@@ -2,6 +2,7 @@ import { shallowMount } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter';
import axios from '~/lib/utils/axios_utils';
import Dashboard from '~/monitoring/components/dashboard.vue';
import DashboardHeader from '~/monitoring/components/dashboard_header.vue';
import { createStore } from '~/monitoring/stores';
import { setupAllDashboards } from '../store_utils';
import { propsData } from '../mock_data';
......@@ -27,7 +28,13 @@ describe('Dashboard template', () => {
});
it('matches the default snapshot', () => {
wrapper = shallowMount(Dashboard, { propsData: { ...propsData }, store });
wrapper = shallowMount(Dashboard, {
propsData: { ...propsData },
store,
stubs: {
DashboardHeader,
},
});
expect(wrapper.element).toMatchSnapshot();
});
......
......@@ -12,6 +12,7 @@ import axios from '~/lib/utils/axios_utils';
import { mockProjectDir, propsData } from '../mock_data';
import Dashboard from '~/monitoring/components/dashboard.vue';
import DashboardHeader from '~/monitoring/components/dashboard_header.vue';
import { createStore } from '~/monitoring/stores';
import { defaultTimeRange } from '~/vue_shared/constants';
......@@ -27,12 +28,12 @@ describe('dashboard invalid url parameters', () => {
wrapper = mount(Dashboard, {
propsData: { ...propsData, ...props },
store,
stubs: ['graph-group', 'dashboard-panel'],
stubs: { 'graph-group': true, 'dashboard-panel': true, 'dashboard-header': DashboardHeader },
...options,
});
};
const findDateTimePicker = () => wrapper.find({ ref: 'dateTimePicker' });
const findDateTimePicker = () => wrapper.find(DashboardHeader).find({ ref: 'dateTimePicker' });
beforeEach(() => {
store = createStore();
......
......@@ -52,7 +52,6 @@ export const initialState = () => ({
dashboard: {
panel_groups: [],
},
useDashboardEndpoint: true,
});
export const initialEmbedGroupState = () => ({
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment