Preserve the saved vis url when using the add new vis link from dashboard (#11932) (#12199)

* Preserve the saved vis url when using the add new vis link from dashboard

Fixes https://github.com/elastic/kibana/issues/11078

* Store the edit url in browser history as well

* Fix tests by reordering them.

* add a more explanatory comment
This commit is contained in:
Stacey Gammon 2017-06-08 09:14:02 -04:00 committed by GitHub
parent 79a16f85db
commit a5f1e10b1e
3 changed files with 74 additions and 29 deletions

View file

@ -67,7 +67,7 @@ uiModules
};
});
function VisEditor($rootScope, $scope, $route, timefilter, AppState, $window, kbnUrl, courier, Private, Promise) {
function VisEditor($rootScope, $scope, $route, timefilter, AppState, $window, kbnUrl, courier, Private, Promise, kbnBaseUrl) {
const docTitle = Private(DocTitleProvider);
const brushEvent = Private(UtilsBrushEventProvider);
const queryFilter = Private(FilterBarQueryFilterProvider);
@ -324,11 +324,20 @@ function VisEditor($rootScope, $scope, $route, timefilter, AppState, $window, kb
if (id) {
notify.info('Saved Visualization "' + savedVis.title + '"');
if ($scope.isAddToDashMode()) {
const savedVisualizationUrl =
kbnUrl.eval(`${kbnBaseUrl}#${VisualizeConstants.EDIT_PATH}/{{id}}`, { id: savedVis.id });
// Manually insert a new url so the back button will open the saved visualization.
$window.history.pushState({}, '', `${chrome.getBasePath()}${savedVisualizationUrl}`);
// Since we aren't reloading the page, only inserting a new browser history item, we need to manually update
// the last url for this app, so directly clicking on the Visualize tab will also bring the user to the saved
// url, not the unsaved one.
chrome.trackSubUrlForApp('kibana:visualize', savedVisualizationUrl);
const dashboardBaseUrl = chrome.getNavLinkById('kibana:dashboard');
// Not using kbnUrl.change here because the dashboardBaseUrl is a full path, not a url suffix.
// Rather than guess the right substring, we'll just navigate there directly, just as if the user
// clicked the dashboard link in the UI.
$window.location.href = `${dashboardBaseUrl.lastSubUrl}&${DashboardConstants.NEW_VISUALIZATION_ID_PARAM}=${savedVis.id}`;
const dashUrlPieces = dashboardBaseUrl.lastSubUrl.match(/(.*)kibana#(.*)/);
const dashSubUrl = `${dashUrlPieces[2]}&${DashboardConstants.NEW_VISUALIZATION_ID_PARAM}={{id}}`;
kbnUrl.change(dashSubUrl, { id: savedVis.id });
} else if (savedVis.id === $route.current.params.id) {
docTitle.change(savedVis.lastSavedTitle);
} else {

View file

@ -110,6 +110,37 @@ export function initChromeNavApi(chrome, internals) {
});
}
function relativeToAbsolute(url) {
// convert all link urls to absolute urls
const a = document.createElement('a');
a.setAttribute('href', url);
return a.href;
}
/**
* Manually sets the last url for the given app. The last url for a given app is updated automatically during
* normal page navigation, so this should only need to be called to insert a last url that was not actually
* navigated to. For instance, when saving an object and redirecting to another page, the last url of the app
* should be the saved instance, but because of the redirect to a different page (e.g. `Save and Add to Dashboard`
* on visualize tab), it won't be tracked automatically and will need to be inserted manually. See
* https://github.com/elastic/kibana/pull/11932 for more background on why this was added.
* @param appId {String}
* @param url {String} The relative url for the app. Should not include the base path portion.
*/
chrome.trackSubUrlForApp = (appId, url) => {
for (const link of internals.nav) {
if (link.id === appId) {
if (!url.startsWith('/')) {
url += '/';
}
url = `${chrome.getBasePath()}${url}`;
url = relativeToAbsolute(url);
setLastUrl(link, url);
return;
}
}
};
internals.trackPossibleSubUrl = function (url) {
const { appId, globalState: newGlobalState } = decodeKibanaUrl(url);
@ -128,13 +159,6 @@ export function initChromeNavApi(chrome, internals) {
}
};
function relativeToAbsolute(url) {
// convert all link urls to absolute urls
const a = document.createElement('a');
a.setAttribute('href', url);
return a.href;
}
internals.nav.forEach(link => {
link.url = relativeToAbsolute(link.url);
link.subUrlBase = relativeToAbsolute(link.subUrlBase);

View file

@ -5,6 +5,10 @@ import {
DEFAULT_PANEL_HEIGHT,
} from '../../../../src/core_plugins/kibana/public/dashboard/panel/panel_state';
import {
VisualizeConstants
} from '../../../../src/core_plugins/kibana/public/visualize/visualize_constants';
export default function ({ getService, getPageObjects }) {
const retry = getService('retry');
const log = getService('log');
@ -130,23 +134,6 @@ export default function ({ getService, getPageObjects }) {
});
});
it('add new visualization link', async function () {
await PageObjects.dashboard.clickAddVisualization();
await PageObjects.dashboard.clickAddNewVisualizationLink();
await PageObjects.visualize.clickAreaChart();
await PageObjects.visualize.clickNewSearch();
await PageObjects.visualize.saveVisualization('visualization from add new link');
await PageObjects.header.clickToastOK();
const visualizations = PageObjects.dashboard.getTestVisualizations();
return retry.tryForTime(10000, async function () {
const panelTitles = await PageObjects.dashboard.getPanelSizeData();
log.info('visualization titles = ' + panelTitles.map(item => item.title));
screenshots.take('Dashboard-visualization-sizes');
expect(panelTitles.length).to.eql(visualizations.length + 1);
});
});
describe('Directly modifying url updates dashboard state', () => {
it('for query parameter', async function () {
const currentQuery = await PageObjects.dashboard.getQuery();
@ -168,5 +155,30 @@ export default function ({ getService, getPageObjects }) {
expect(allPanelInfo[0].dataSizeX).to.equal(`${DEFAULT_PANEL_WIDTH * 2}`);
});
});
describe('add new visualization link', () => {
it('adds a new visualization', async () => {
await PageObjects.dashboard.clickAddVisualization();
await PageObjects.dashboard.clickAddNewVisualizationLink();
await PageObjects.visualize.clickAreaChart();
await PageObjects.visualize.clickNewSearch();
await PageObjects.visualize.saveVisualization('visualization from add new link');
await PageObjects.header.clickToastOK();
const visualizations = PageObjects.dashboard.getTestVisualizations();
return retry.tryForTime(10000, async function () {
const panelTitles = await PageObjects.dashboard.getPanelSizeData();
log.info('visualization titles = ' + panelTitles.map(item => item.title));
screenshots.take('Dashboard-visualization-sizes');
expect(panelTitles.length).to.eql(visualizations.length + 1);
});
});
it('saves the saved visualization url to the app link', async () => {
await PageObjects.header.clickVisualize();
const currentUrl = await remote.getCurrentUrl();
expect(currentUrl).to.contain(VisualizeConstants.EDIT_PATH);
});
});
});
}