Commit 4f251ab3 authored by Miguel Rincon's avatar Miguel Rincon

Update the url when a panel is expanded

Respond to a change in the current view of dashboard by updating the
browser URL effectively syncronnizing with the panel specific URL.
parent 34dcf767
...@@ -259,8 +259,17 @@ export default { ...@@ -259,8 +259,17 @@ export default {
); );
} }
}, },
expandedPanel: {
handler({ group, panel }) {
const dashboardPath = this.currentDashboard || this.firstDashboard.path;
updateHistory({
url: panelToUrl(dashboardPath, group, panel),
title: document.title,
});
},
deep: true,
},
}, },
created() { created() {
this.setInitialState({ this.setInitialState({
metricsEndpoint: this.metricsEndpoint, metricsEndpoint: this.metricsEndpoint,
......
import { pickBy } from 'lodash';
import { queryToObject, mergeUrlParams, removeParams } from '~/lib/utils/url_utility'; import { queryToObject, mergeUrlParams, removeParams } from '~/lib/utils/url_utility';
import { import {
timeRangeParamNames, timeRangeParamNames,
...@@ -174,25 +173,30 @@ export const expandedPanelPayloadFromUrl = (dashboard, search = window.location. ...@@ -174,25 +173,30 @@ export const expandedPanelPayloadFromUrl = (dashboard, search = window.location.
* Convert panel information to a URL for the user to * Convert panel information to a URL for the user to
* bookmark or share highlighting a specific panel. * bookmark or share highlighting a specific panel.
* *
* @param {String} dashboardPath - Dashboard path used as identifier * If no group/panel is set, the dashboard URL is returned.
* @param {String} group - Group Identifier *
* @param {?String} dashboard - Dashboard path, used as identifier for a dashboard
* @param {?String} group - Group Identifier
* @param {?Object} panel - Panel object from the dashboard * @param {?Object} panel - Panel object from the dashboard
* @param {?String} url - Base URL including current search params * @param {?String} url - Base URL including current search params
* @returns Dashboard URL which expands a panel (chart) * @returns Dashboard URL which expands a panel (chart)
*/ */
export const panelToUrl = (dashboardPath, group, panel, url = window.location.href) => { export const panelToUrl = (dashboard = null, group, panel, url = window.location.href) => {
if (!group || !panel) { const params = {
return null; dashboard,
};
if (group && panel) {
params.group = group;
params.title = panel.title;
params.y_label = panel.y_label;
} else {
// Remove existing parameters if any
params.group = null;
params.title = null;
params.y_label = null;
} }
const params = pickBy(
{
dashboard: dashboardPath,
group,
title: panel.title,
y_label: panel.y_label,
},
value => value != null,
);
return mergeUrlParams(params, url); return mergeUrlParams(params, url);
}; };
......
---
title: Update metrics dashboard url when a panel is expanded or contracted
merge_request: 30704
author:
type: added
...@@ -234,6 +234,90 @@ describe('Dashboard', () => { ...@@ -234,6 +234,90 @@ describe('Dashboard', () => {
}); });
}); });
describe('when the panel is expanded', () => {
let group;
let panel;
const expandPanel = (mockGroup, mockPanel) => {
store.commit(`monitoringDashboard/${types.SET_EXPANDED_PANEL}`, {
group: mockGroup,
panel: mockPanel,
});
};
beforeEach(() => {
setupStoreWithData(store);
const { panelGroups } = store.state.monitoringDashboard.dashboard;
group = panelGroups[0].group;
[panel] = panelGroups[0].panels;
jest.spyOn(window.history, 'pushState').mockImplementation();
});
afterEach(() => {
window.history.pushState.mockRestore();
});
it('URL is updated with panel parameters', () => {
createMountedWrapper({ hasMetrics: true });
expandPanel(group, panel);
const expectedSearch = objectToQuery({
group,
title: panel.title,
y_label: panel.y_label,
});
return wrapper.vm.$nextTick(() => {
expect(window.history.pushState).toHaveBeenCalledTimes(1);
expect(window.history.pushState).toHaveBeenCalledWith(
expect.anything(), // state
expect.any(String), // document title
expect.stringContaining(`?${expectedSearch}`),
);
});
});
it('URL is updated with panel parameters and custom dashboard', () => {
const dashboard = 'dashboard.yml';
createMountedWrapper({ hasMetrics: true, currentDashboard: dashboard });
expandPanel(group, panel);
const expectedSearch = objectToQuery({
dashboard,
group,
title: panel.title,
y_label: panel.y_label,
});
return wrapper.vm.$nextTick(() => {
expect(window.history.pushState).toHaveBeenCalledTimes(1);
expect(window.history.pushState).toHaveBeenCalledWith(
expect.anything(), // state
expect.any(String), // document title
expect.stringContaining(`?${expectedSearch}`),
);
});
});
it('URL is updated with no parameters', () => {
expandPanel(group, panel);
createMountedWrapper({ hasMetrics: true });
expandPanel(null, null);
return wrapper.vm.$nextTick(() => {
expect(window.history.pushState).toHaveBeenCalledTimes(1);
expect(window.history.pushState).toHaveBeenCalledWith(
expect.anything(), // state
expect.any(String), // document title
expect.not.stringContaining('?'), // no params
);
});
});
});
describe('when all requests have been commited by the store', () => { describe('when all requests have been commited by the store', () => {
beforeEach(() => { beforeEach(() => {
createMountedWrapper({ hasMetrics: true }); createMountedWrapper({ hasMetrics: true });
......
...@@ -274,9 +274,10 @@ describe('monitoring/utils', () => { ...@@ -274,9 +274,10 @@ describe('monitoring/utils', () => {
const [panelGroup] = metricsDashboardViewModel.panelGroups; const [panelGroup] = metricsDashboardViewModel.panelGroups;
const [panel] = panelGroup.panels; const [panel] = panelGroup.panels;
const getUrlParams = url => urlUtils.queryToObject(url.split('?')[1]);
it('returns URL for a panel when query parameters are given', () => { it('returns URL for a panel when query parameters are given', () => {
const [, query] = panelToUrl(dashboard, panelGroup.group, panel).split('?'); const params = getUrlParams(panelToUrl(dashboard, panelGroup.group, panel));
const params = urlUtils.queryToObject(query);
expect(params).toEqual({ expect(params).toEqual({
dashboard, dashboard,
...@@ -286,12 +287,14 @@ describe('monitoring/utils', () => { ...@@ -286,12 +287,14 @@ describe('monitoring/utils', () => {
}); });
}); });
it('returns `null` if group is missing', () => { it('returns a dashboard only URL if group is missing', () => {
expect(panelToUrl(dashboard, null, panel)).toBe(null); const params = getUrlParams(panelToUrl(dashboard, null, panel));
expect(params).toEqual({ dashboard: 'metrics.yml' });
}); });
it('returns `null` if panel is missing', () => { it('returns a dashboard only URL if panel is missing', () => {
expect(panelToUrl(dashboard, panelGroup.group, null)).toBe(null); const params = getUrlParams(panelToUrl(dashboard, panelGroup.group, null));
expect(params).toEqual({ dashboard: 'metrics.yml' });
}); });
}); });
......
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