Commit d611e6d1 authored by Natalia Tepluhina's avatar Natalia Tepluhina

Merge branch '35288-update-metrics-dashboard-dropdowns' into 'master'

Added search box to dashboards dropdown

See merge request gitlab-org/gitlab!23906
parents 23318c9a 79614a08
...@@ -402,7 +402,9 @@ export default { ...@@ -402,7 +402,9 @@ export default {
:text="currentEnvironmentName" :text="currentEnvironmentName"
> >
<div class="d-flex flex-column overflow-hidden"> <div class="d-flex flex-column overflow-hidden">
<gl-dropdown-header class="text-center">{{ __('Environment') }}</gl-dropdown-header> <gl-dropdown-header class="monitor-environment-dropdown-header text-center">{{
__('Environment')
}}</gl-dropdown-header>
<gl-dropdown-divider /> <gl-dropdown-divider />
<gl-search-box-by-type <gl-search-box-by-type
v-if="shouldRenderSearchableEnvironmentsDropdown" v-if="shouldRenderSearchableEnvironmentsDropdown"
......
...@@ -4,11 +4,14 @@ import { ...@@ -4,11 +4,14 @@ import {
GlAlert, GlAlert,
GlDropdown, GlDropdown,
GlDropdownItem, GlDropdownItem,
GlDropdownHeader,
GlDropdownDivider, GlDropdownDivider,
GlSearchBoxByType,
GlModal, GlModal,
GlLoadingIcon, GlLoadingIcon,
GlModalDirective, GlModalDirective,
} from '@gitlab/ui'; } from '@gitlab/ui';
import { s__ } from '~/locale';
import DuplicateDashboardForm from './duplicate_dashboard_form.vue'; import DuplicateDashboardForm from './duplicate_dashboard_form.vue';
const events = { const events = {
...@@ -20,7 +23,9 @@ export default { ...@@ -20,7 +23,9 @@ export default {
GlAlert, GlAlert,
GlDropdown, GlDropdown,
GlDropdownItem, GlDropdownItem,
GlDropdownHeader,
GlDropdownDivider, GlDropdownDivider,
GlSearchBoxByType,
GlModal, GlModal,
GlLoadingIcon, GlLoadingIcon,
DuplicateDashboardForm, DuplicateDashboardForm,
...@@ -44,6 +49,7 @@ export default { ...@@ -44,6 +49,7 @@ export default {
alert: null, alert: null,
loading: false, loading: false,
form: {}, form: {},
searchTerm: '',
}; };
}, },
computed: { computed: {
...@@ -54,6 +60,17 @@ export default { ...@@ -54,6 +60,17 @@ export default {
selectedDashboardText() { selectedDashboardText() {
return this.selectedDashboard.display_name; return this.selectedDashboard.display_name;
}, },
filteredDashboards() {
return this.allDashboards.filter(({ display_name }) =>
display_name.toLowerCase().includes(this.searchTerm.toLowerCase()),
);
},
shouldShowNoMsgContainer() {
return this.filteredDashboards.length === 0;
},
okButtonText() {
return this.loading ? s__('Metrics|Duplicating...') : s__('Metrics|Duplicate');
},
}, },
methods: { methods: {
...mapActions('monitoringDashboard', ['duplicateSystemDashboard']), ...mapActions('monitoringDashboard', ['duplicateSystemDashboard']),
...@@ -95,45 +112,70 @@ export default { ...@@ -95,45 +112,70 @@ export default {
}; };
</script> </script>
<template> <template>
<gl-dropdown toggle-class="dropdown-menu-toggle" :text="selectedDashboardText"> <gl-dropdown
<gl-dropdown-item toggle-class="dropdown-menu-toggle"
v-for="dashboard in allDashboards" menu-class="monitor-dashboard-dropdown-menu"
:key="dashboard.path" :text="selectedDashboardText"
:active="dashboard.path === selectedDashboard.path" >
active-class="is-active" <div class="d-flex flex-column overflow-hidden">
@click="selectDashboard(dashboard)" <gl-dropdown-header class="monitor-dashboard-dropdown-header text-center">{{
> __('Dashboard')
{{ dashboard.display_name || dashboard.path }} }}</gl-dropdown-header>
</gl-dropdown-item>
<template v-if="isSystemDashboard">
<gl-dropdown-divider /> <gl-dropdown-divider />
<gl-search-box-by-type
ref="monitorDashboardsDropdownSearch"
v-model="searchTerm"
class="m-2"
/>
<div class="flex-fill overflow-auto">
<gl-dropdown-item
v-for="dashboard in filteredDashboards"
:key="dashboard.path"
:active="dashboard.path === selectedDashboard.path"
active-class="is-active"
@click="selectDashboard(dashboard)"
>
{{ dashboard.display_name || dashboard.path }}
</gl-dropdown-item>
</div>
<gl-modal <div
ref="duplicateDashboardModal" v-show="shouldShowNoMsgContainer"
modal-id="duplicateDashboardModal" ref="monitorDashboardsDropdownMsg"
:title="s__('Metrics|Duplicate dashboard')" class="text-secondary no-matches-message"
ok-variant="success"
@ok="ok"
@hide="hide"
> >
<gl-alert v-if="alert" class="mb-3" variant="danger" @dismiss="alert = null"> {{ __('No matching results') }}
{{ alert }} </div>
</gl-alert>
<duplicate-dashboard-form <template v-if="isSystemDashboard">
:dashboard="selectedDashboard" <gl-dropdown-divider />
:default-branch="defaultBranch"
@change="formChange" <gl-modal
/> ref="duplicateDashboardModal"
<template #modal-ok> modal-id="duplicateDashboardModal"
<gl-loading-icon v-if="loading" inline color="light" /> :title="s__('Metrics|Duplicate dashboard')"
{{ loading ? s__('Metrics|Duplicating...') : s__('Metrics|Duplicate') }} ok-variant="success"
</template> @ok="ok"
</gl-modal> @hide="hide"
>
<gl-alert v-if="alert" class="mb-3" variant="danger" @dismiss="alert = null">
{{ alert }}
</gl-alert>
<duplicate-dashboard-form
:dashboard="selectedDashboard"
:default-branch="defaultBranch"
@change="formChange"
/>
<template #modal-ok>
<gl-loading-icon v-if="loading" inline color="light" />
{{ okButtonText }}
</template>
</gl-modal>
<gl-dropdown-item ref="duplicateDashboardItem" v-gl-modal="'duplicateDashboardModal'"> <gl-dropdown-item ref="duplicateDashboardItem" v-gl-modal="'duplicateDashboardModal'">
{{ s__('Metrics|Duplicate dashboard') }} {{ s__('Metrics|Duplicate dashboard') }}
</gl-dropdown-item> </gl-dropdown-item>
</template> </template>
</div>
</gl-dropdown> </gl-dropdown>
</template> </template>
...@@ -47,7 +47,12 @@ ...@@ -47,7 +47,12 @@
} }
.prometheus-graphs-header { .prometheus-graphs-header {
.monitor-environment-dropdown-menu { .monitor-dashboard-dropdown-header header {
font-size: $gl-font-size;
}
.monitor-environment-dropdown-menu,
.monitor-dashboard-dropdown-menu {
&.show { &.show {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
......
---
title: Added search box to dashboards dropdown in monitoring dashboard
merge_request: 23906
author:
type: added
...@@ -44,7 +44,7 @@ exports[`Dashboard template matches the default snapshot 1`] = ` ...@@ -44,7 +44,7 @@ exports[`Dashboard template matches the default snapshot 1`] = `
class="d-flex flex-column overflow-hidden" class="d-flex flex-column overflow-hidden"
> >
<gl-dropdown-header-stub <gl-dropdown-header-stub
class="text-center" class="monitor-environment-dropdown-header text-center"
> >
Environment Environment
</gl-dropdown-header-stub> </gl-dropdown-header-stub>
......
...@@ -35,13 +35,17 @@ describe('DashboardsDropdown', () => { ...@@ -35,13 +35,17 @@ describe('DashboardsDropdown', () => {
const findItems = () => wrapper.findAll(GlDropdownItem); const findItems = () => wrapper.findAll(GlDropdownItem);
const findItemAt = i => wrapper.findAll(GlDropdownItem).at(i); const findItemAt = i => wrapper.findAll(GlDropdownItem).at(i);
const findSearchInput = () => wrapper.find({ ref: 'monitorDashboardsDropdownSearch' });
const findNoItemsMsg = () => wrapper.find({ ref: 'monitorDashboardsDropdownMsg' });
const setSearchTerm = searchTerm => wrapper.setData({ searchTerm });
describe('when it receives dashboards data', () => { describe('when it receives dashboards data', () => {
beforeEach(() => { beforeEach(() => {
wrapper = createComponent(); wrapper = createComponent();
}); });
it('displays an item for each dashboard', () => { it('displays an item for each dashboard', () => {
expect(wrapper.findAll(GlDropdownItem).length).toEqual(dashboardGitResponse.length); expect(findItems().length).toEqual(dashboardGitResponse.length);
}); });
it('displays items with the dashboard display name', () => { it('displays items with the dashboard display name', () => {
...@@ -49,6 +53,32 @@ describe('DashboardsDropdown', () => { ...@@ -49,6 +53,32 @@ describe('DashboardsDropdown', () => {
expect(findItemAt(1).text()).toBe(dashboardGitResponse[1].display_name); expect(findItemAt(1).text()).toBe(dashboardGitResponse[1].display_name);
expect(findItemAt(2).text()).toBe(dashboardGitResponse[2].display_name); expect(findItemAt(2).text()).toBe(dashboardGitResponse[2].display_name);
}); });
it('displays a search input', () => {
expect(findSearchInput().isVisible()).toBe(true);
});
it('hides no message text by default', () => {
expect(findNoItemsMsg().isVisible()).toBe(false);
});
it('filters dropdown items when searched for item exists in the list', () => {
const searchTerm = 'Default';
setSearchTerm(searchTerm);
return wrapper.vm.$nextTick(() => {
expect(findItems()).toHaveLength(1);
});
});
it('shows no items found message when searched for item does not exists in the list', () => {
const searchTerm = 'does-not-exist';
setSearchTerm(searchTerm);
return wrapper.vm.$nextTick(() => {
expect(findNoItemsMsg().isVisible()).toBe(true);
});
});
}); });
describe('when a system dashboard is selected', () => { describe('when a system dashboard is selected', () => {
...@@ -224,7 +254,7 @@ describe('DashboardsDropdown', () => { ...@@ -224,7 +254,7 @@ describe('DashboardsDropdown', () => {
it('displays an item for each dashboard', () => { it('displays an item for each dashboard', () => {
const item = wrapper.findAll({ ref: 'duplicateDashboardItem' }); const item = wrapper.findAll({ ref: 'duplicateDashboardItem' });
expect(findItems().length).toEqual(dashboardGitResponse.length); expect(findItems()).toHaveLength(dashboardGitResponse.length);
expect(item.length).toBe(0); expect(item.length).toBe(0);
}); });
......
...@@ -518,6 +518,15 @@ export const metricsDashboardPayload = { ...@@ -518,6 +518,15 @@ export const metricsDashboardPayload = {
], ],
}; };
const customDashboardsData = new Array(30).fill(null).map((_, idx) => ({
default: false,
display_name: `Custom Dashboard ${idx}`,
can_edit: true,
system_dashboard: false,
project_blob_path: `${mockProjectDir}/blob/master/dashboards/.gitlab/dashboards/dashboard_${idx}.yml`,
path: `.gitlab/dashboards/dashboard_${idx}.yml`,
}));
export const dashboardGitResponse = [ export const dashboardGitResponse = [
{ {
default: true, default: true,
...@@ -527,22 +536,7 @@ export const dashboardGitResponse = [ ...@@ -527,22 +536,7 @@ export const dashboardGitResponse = [
project_blob_path: null, project_blob_path: null,
path: 'config/prometheus/common_metrics.yml', path: 'config/prometheus/common_metrics.yml',
}, },
{ ...customDashboardsData,
default: false,
display_name: 'Custom Dashboard 1',
can_edit: true,
system_dashboard: false,
project_blob_path: `${mockProjectDir}/blob/master/dashboards/.gitlab/dashboards/dashboard_1.yml`,
path: '.gitlab/dashboards/dashboard_1.yml',
},
{
default: false,
display_name: 'Custom Dashboard 2',
can_edit: true,
system_dashboard: false,
project_blob_path: `${mockProjectDir}/blob/master/dashboards/.gitlab/dashboards/dashboard_2.yml`,
path: '.gitlab/dashboards/dashboard_2.yml',
},
]; ];
export const graphDataPrometheusQuery = { export const graphDataPrometheusQuery = {
......
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