Commit 23f5dcf6 authored by Fatih Acet's avatar Fatih Acet

Merge branch '59974-multidash' into 'master'

Load dashboards from project's git repository

Closes #59974

See merge request gitlab-org/gitlab-ce!29348
parents 871d0699 27afe549
......@@ -106,17 +106,24 @@ export default {
},
customMetricsPath: {
type: String,
required: true,
required: false,
default: invalidUrl,
},
validateQueryPath: {
type: String,
required: true,
required: false,
default: invalidUrl,
},
dashboardEndpoint: {
type: String,
required: false,
default: invalidUrl,
},
currentDashboard: {
type: String,
required: false,
default: '',
},
},
data() {
return {
......@@ -139,10 +146,15 @@ export default {
'deploymentData',
'metricsWithData',
'useDashboardEndpoint',
'allDashboards',
'multipleDashboardsEnabled',
]),
groupsWithData() {
return this.groups.filter(group => this.chartsWithData(group.metrics).length > 0);
},
selectedDashboardText() {
return this.currentDashboard || (this.allDashboards[0] && this.allDashboards[0].display_name);
},
},
created() {
this.setEndpoints({
......@@ -150,6 +162,7 @@ export default {
environmentsEndpoint: this.environmentsEndpoint,
deploymentsEndpoint: this.deploymentsEndpoint,
dashboardEndpoint: this.dashboardEndpoint,
currentDashboard: this.currentDashboard,
});
this.timeWindows = timeWindows;
......@@ -240,6 +253,24 @@ export default {
v-if="environmentsEndpoint"
class="dropdowns d-flex align-items-center justify-content-between"
>
<div v-if="multipleDashboardsEnabled" class="d-flex align-items-center">
<label class="mb-0">{{ __('Dashboard') }}</label>
<gl-dropdown
class="ml-2 mr-3 js-dashboards-dropdown"
toggle-class="dropdown-menu-toggle"
:text="selectedDashboardText"
>
<gl-dropdown-item
v-for="dashboard in allDashboards"
:key="dashboard.path"
:active="dashboard.path === currentDashboard"
active-class="is-active"
:href="`?dashboard=${dashboard.path}`"
>
{{ dashboard.display_name || dashboard.path }}
</gl-dropdown-item>
</gl-dropdown>
</div>
<div class="d-flex align-items-center">
<strong>{{ s__('Metrics|Environment') }}</strong>
<gl-dropdown
......
import Vue from 'vue';
import { parseBoolean } from '~/lib/utils/common_utils';
import { getParameterValues } from '~/lib/utils/url_utility';
import Dashboard from 'ee_else_ce/monitoring/components/dashboard.vue';
import store from './stores';
......@@ -7,10 +8,12 @@ export default (props = {}) => {
const el = document.getElementById('prometheus-graphs');
if (el && el.dataset) {
store.dispatch(
'monitoringDashboard/setDashboardEnabled',
gon.features.environmentMetricsUsePrometheusEndpoint,
);
store.dispatch('monitoringDashboard/setFeatureFlags', {
prometheusEndpointEnabled: gon.features.environmentMetricsUsePrometheusEndpoint,
multipleDashboardsEnabled: gon.features.environmentMetricsShowMultipleDashboards,
});
const [currentDashboard] = getParameterValues('dashboard');
// eslint-disable-next-line no-new
new Vue({
......@@ -20,6 +23,7 @@ export default (props = {}) => {
return createElement(Dashboard, {
props: {
...el.dataset,
currentDashboard,
hasMetrics: parseBoolean(el.dataset.hasMetrics),
...props,
},
......
......@@ -35,14 +35,24 @@ export const setEndpoints = ({ commit }, endpoints) => {
commit(types.SET_ENDPOINTS, endpoints);
};
export const setDashboardEnabled = ({ commit }, enabled) => {
commit(types.SET_DASHBOARD_ENABLED, enabled);
export const setFeatureFlags = (
{ commit },
{ prometheusEndpointEnabled, multipleDashboardsEnabled },
) => {
commit(types.SET_DASHBOARD_ENABLED, prometheusEndpointEnabled);
commit(types.SET_MULTIPLE_DASHBOARDS_ENABLED, multipleDashboardsEnabled);
};
export const requestMetricsDashboard = ({ commit }) => {
commit(types.REQUEST_METRICS_DATA);
};
export const receiveMetricsDashboardSuccess = ({ commit, dispatch }, { response, params }) => {
export const receiveMetricsDashboardSuccess = (
{ state, commit, dispatch },
{ response, params },
) => {
if (state.multipleDashboardsEnabled) {
commit(types.SET_ALL_DASHBOARDS, response.all_dashboards);
}
commit(types.RECEIVE_METRICS_DATA_SUCCESS, response.dashboard.panel_groups);
dispatch('fetchPrometheusMetrics', params);
};
......@@ -95,6 +105,11 @@ export const fetchMetricsData = ({ state, dispatch }, params) => {
export const fetchDashboard = ({ state, dispatch }, params) => {
dispatch('requestMetricsDashboard');
if (state.currentDashboard) {
// eslint-disable-next-line no-param-reassign
params.dashboard = state.currentDashboard;
}
return axios
.get(state.dashboardEndpoint, { params })
.then(resp => resp.data)
......
......@@ -10,6 +10,8 @@ export const RECEIVE_ENVIRONMENTS_DATA_FAILURE = 'RECEIVE_ENVIRONMENTS_DATA_FAIL
export const SET_QUERY_RESULT = 'SET_QUERY_RESULT';
export const SET_TIME_WINDOW = 'SET_TIME_WINDOW';
export const SET_DASHBOARD_ENABLED = 'SET_DASHBOARD_ENABLED';
export const SET_MULTIPLE_DASHBOARDS_ENABLED = 'SET_MULTIPLE_DASHBOARDS_ENABLED';
export const SET_ALL_DASHBOARDS = 'SET_ALL_DASHBOARDS';
export const SET_ENDPOINTS = 'SET_ENDPOINTS';
export const SET_GETTING_STARTED_EMPTY_STATE = 'SET_GETTING_STARTED_EMPTY_STATE';
export const SET_NO_DATA_EMPTY_STATE = 'SET_NO_DATA_EMPTY_STATE';
......@@ -74,10 +74,14 @@ export default {
state.environmentsEndpoint = endpoints.environmentsEndpoint;
state.deploymentsEndpoint = endpoints.deploymentsEndpoint;
state.dashboardEndpoint = endpoints.dashboardEndpoint;
state.currentDashboard = endpoints.currentDashboard;
},
[types.SET_DASHBOARD_ENABLED](state, enabled) {
state.useDashboardEndpoint = enabled;
},
[types.SET_MULTIPLE_DASHBOARDS_ENABLED](state, enabled) {
state.multipleDashboardsEnabled = enabled;
},
[types.SET_GETTING_STARTED_EMPTY_STATE](state) {
state.emptyState = 'gettingStarted';
},
......@@ -85,4 +89,7 @@ export default {
state.showEmptyState = true;
state.emptyState = 'noData';
},
[types.SET_ALL_DASHBOARDS](state, dashboards) {
state.allDashboards = dashboards;
},
};
......@@ -8,10 +8,13 @@ export default () => ({
deploymentsEndpoint: null,
dashboardEndpoint: invalidUrl,
useDashboardEndpoint: false,
multipleDashboardsEnabled: false,
emptyState: 'gettingStarted',
showEmptyState: true,
groups: [],
deploymentData: [],
environments: [],
metricsWithData: [],
allDashboards: [],
currentDashboard: null,
});
......@@ -10,6 +10,7 @@ import {
mockApiEndpoint,
environmentData,
singleGroupResponse,
dashboardGitResponse,
} from './mock_data';
const propsData = {
......@@ -308,10 +309,6 @@ describe('Dashboard', () => {
spyOn(component.$store, 'dispatch').and.stub();
const getTimeDiffSpy = spyOnDependency(Dashboard, 'getTimeDiff');
component.$store.commit(
`monitoringDashboard/${types.SET_ENVIRONMENTS_ENDPOINT}`,
'/environments',
);
component.$store.commit(
`monitoringDashboard/${types.RECEIVE_ENVIRONMENTS_DATA_SUCCESS}`,
environmentData,
......@@ -430,4 +427,49 @@ describe('Dashboard', () => {
});
});
});
describe('Dashboard dropdown', () => {
beforeEach(() => {
mock.onGet(mockApiEndpoint).reply(200, metricsGroupsAPIResponse);
component = new DashboardComponent({
el: document.querySelector('.prometheus-graphs'),
propsData: {
...propsData,
hasMetrics: true,
showPanels: false,
},
store,
});
component.$store.dispatch('monitoringDashboard/setFeatureFlags', {
prometheusEndpoint: false,
multipleDashboardsEnabled: true,
});
component.$store.commit(
`monitoringDashboard/${types.RECEIVE_ENVIRONMENTS_DATA_SUCCESS}`,
environmentData,
);
component.$store.commit(
`monitoringDashboard/${types.RECEIVE_METRICS_DATA_SUCCESS}`,
singleGroupResponse,
);
component.$store.commit(
`monitoringDashboard/${types.SET_ALL_DASHBOARDS}`,
dashboardGitResponse,
);
});
it('shows the dashboard dropdown', done => {
setTimeout(() => {
const dashboardDropdown = component.$el.querySelector('.js-dashboards-dropdown');
expect(dashboardDropdown).not.toEqual(null);
done();
});
});
});
});
......@@ -922,3 +922,16 @@ export const metricsDashboardResponse = {
},
status: 'success',
};
export const dashboardGitResponse = [
{
path: 'config/prometheus/common_metrics.yml',
display_name: 'Common Metrics',
default: true,
},
{
path: '.gitlab/dashboards/super.yml',
display_name: 'Custom Dashboard 1',
default: false,
},
];
......@@ -22,6 +22,7 @@ import {
environmentData,
metricsDashboardResponse,
metricsGroupsAPIResponse,
dashboardGitResponse,
} from '../mock_data';
describe('Monitoring store actions', () => {
......@@ -212,17 +213,19 @@ describe('Monitoring store actions', () => {
describe('receiveMetricsDashboardSuccess', () => {
let commit;
let dispatch;
let state;
beforeEach(() => {
commit = jasmine.createSpy();
dispatch = jasmine.createSpy();
state = storeState();
});
it('stores groups ', () => {
const params = {};
const response = metricsDashboardResponse;
receiveMetricsDashboardSuccess({ commit, dispatch }, { response, params });
receiveMetricsDashboardSuccess({ state, commit, dispatch }, { response, params });
expect(commit).toHaveBeenCalledWith(
types.RECEIVE_METRICS_DATA_SUCCESS,
......@@ -231,6 +234,18 @@ describe('Monitoring store actions', () => {
expect(dispatch).toHaveBeenCalledWith('fetchPrometheusMetrics', params);
});
it('sets the dashboards loaded from the repository', () => {
const params = {};
const response = metricsDashboardResponse;
response.all_dashboards = dashboardGitResponse;
state.multipleDashboardsEnabled = true;
receiveMetricsDashboardSuccess({ state, commit, dispatch }, { response, params });
expect(commit).toHaveBeenCalledWith(types.SET_ALL_DASHBOARDS, dashboardGitResponse);
});
});
describe('receiveMetricsDashboardFailure', () => {
......
import mutations from '~/monitoring/stores/mutations';
import * as types from '~/monitoring/stores/mutation_types';
import state from '~/monitoring/stores/state';
import { metricsGroupsAPIResponse, deploymentData, metricsDashboardResponse } from '../mock_data';
import {
metricsGroupsAPIResponse,
deploymentData,
metricsDashboardResponse,
dashboardGitResponse,
} from '../mock_data';
describe('Monitoring mutations', () => {
let stateCopy;
......@@ -156,4 +161,12 @@ describe('Monitoring mutations', () => {
expect(stateCopy.metricsWithData).toEqual([]);
});
});
describe('SET_ALL_DASHBOARDS', () => {
it('stores the dashboards loaded from the git repository', () => {
mutations[types.SET_ALL_DASHBOARDS](stateCopy, dashboardGitResponse);
expect(stateCopy.allDashboards).toEqual(dashboardGitResponse);
});
});
});
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