reset lastSubUrl nav links for deleted saved objects (#15508)

* untrack nav links for deleted saved objects

* move nav cleanup logic to saved_object_loader delete method

* notify with info when redirected when missing
This commit is contained in:
Nathan Reese 2017-12-13 11:20:12 -07:00 committed by GitHub
parent 04c60efe83
commit 5673f79f8f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 82 additions and 11 deletions

View file

@ -13,6 +13,6 @@ savedObjectManagementRegistry.register({
});
// This is the only thing that gets injected into controllers
module.service('savedDashboards', function (SavedDashboard, kbnIndex, kbnUrl, $http) {
return new SavedObjectLoader(SavedDashboard, kbnIndex, kbnUrl, $http);
module.service('savedDashboards', function (SavedDashboard, kbnIndex, kbnUrl, $http, chrome) {
return new SavedObjectLoader(SavedDashboard, kbnIndex, kbnUrl, $http, chrome);
});

View file

@ -14,8 +14,8 @@ savedObjectManagementRegistry.register({
title: 'searches'
});
module.service('savedSearches', function (Promise, config, kbnIndex, createNotifier, SavedSearch, kbnUrl, $http) {
const savedSearchLoader = new SavedObjectLoader(SavedSearch, kbnIndex, kbnUrl, $http);
module.service('savedSearches', function (Promise, config, kbnIndex, createNotifier, SavedSearch, kbnUrl, $http, chrome) {
const savedSearchLoader = new SavedObjectLoader(SavedSearch, kbnIndex, kbnUrl, $http, chrome);
// Customize loader properties since adding an 's' on type doesn't work for type 'search' .
savedSearchLoader.loaderProperties = {
name: 'searches',

View file

@ -13,10 +13,10 @@ savedObjectManagementRegistry.register({
title: 'visualizations'
});
app.service('savedVisualizations', function (Promise, kbnIndex, SavedVis, Private, kbnUrl, $http) {
app.service('savedVisualizations', function (Promise, kbnIndex, SavedVis, Private, kbnUrl, $http, chrome) {
const visTypes = Private(VisTypesRegistryProvider);
const saveVisualizationLoader = new SavedObjectLoader(SavedVis, kbnIndex, kbnUrl, $http);
const saveVisualizationLoader = new SavedObjectLoader(SavedVis, kbnIndex, kbnUrl, $http, chrome);
saveVisualizationLoader.mapHitSource = function (source, id) {
source.id = id;

View file

@ -13,8 +13,8 @@ savedObjectManagementRegistry.register({
});
// This is the only thing that gets injected into controllers
module.service('savedSheets', function (Promise, SavedSheet, kbnIndex, kbnUrl, $http) {
const savedSheetLoader = new SavedObjectLoader(SavedSheet, kbnIndex, kbnUrl, $http);
module.service('savedSheets', function (Promise, SavedSheet, kbnIndex, kbnUrl, $http, chrome) {
const savedSheetLoader = new SavedObjectLoader(SavedSheet, kbnIndex, kbnUrl, $http, chrome);
savedSheetLoader.urlFor = function (id) {
return kbnUrl.eval('#/{{id}}', { id: id });
};

View file

@ -92,6 +92,51 @@ describe('chrome nav apis', function () {
});
});
describe('#untrackNavLinksForDeletedSavedObjects', function () {
const appId = 'appId';
const appUrl = 'https://localhost:9200/app/kibana#test';
const deletedId = 'IAMDELETED';
it('should clear last url when last url contains link to deleted saved object', function () {
const appUrlStore = new StubBrowserStorage();
const nav = [
{
id: appId,
title: 'Discover',
linkToLastSubUrl: true,
lastSubUrl: `${appUrl}?id=${deletedId}`,
url: appUrl
}
];
const {
chrome
} = init({ appUrlStore, nav });
chrome.untrackNavLinksForDeletedSavedObjects([deletedId]);
expect(chrome.getNavLinkById('appId').lastSubUrl).to.be(appUrl);
});
it('should not clear last url when last url does not contains link to deleted saved object', function () {
const lastUrl = `${appUrl}?id=anotherSavedObjectId`;
const appUrlStore = new StubBrowserStorage();
const nav = [
{
id: appId,
title: 'Discover',
linkToLastSubUrl: true,
lastSubUrl: lastUrl,
url: appUrl
}
];
const {
chrome
} = init({ appUrlStore, nav });
chrome.untrackNavLinksForDeletedSavedObjects([deletedId]);
expect(chrome.getNavLinkById(appId).lastSubUrl).to.be(lastUrl);
});
});
describe('internals.trackPossibleSubUrl()', function () {
it('injects the globalState of the current url to all links for the same app', function () {
const appUrlStore = new StubBrowserStorage();

View file

@ -74,6 +74,27 @@ export function initChromeNavApi(chrome, internals) {
link.lastSubUrl = kibanaParsedUrl.getAbsoluteUrl();
}
/**
* Clear last url for deleted saved objects to avoid loading pages with "Could not locate.."
*/
chrome.untrackNavLinksForDeletedSavedObjects = (deletedIds) => {
function urlContainsDeletedId(url) {
const includedId = deletedIds.find(deletedId => {
return url.includes(deletedId);
});
if (includedId === undefined) {
return false;
}
return true;
}
internals.nav.forEach(link => {
if (link.linkToLastSubUrl && urlContainsDeletedId(link.lastSubUrl)) {
setLastUrl(link, link.url);
}
});
};
/**
* 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

View file

@ -28,7 +28,7 @@ export function RedirectWhenMissingProvider($location, kbnUrl, Notifier, Promise
url += (url.indexOf('?') >= 0 ? '&' : '?') + `notFound=${err.savedObjectType}`;
notify.error(err);
notify.info(err);
kbnUrl.redirect(url);
return Promise.halt();
};

View file

@ -3,12 +3,13 @@ import { StringUtils } from 'ui/utils/string_utils';
import { SavedObjectsClient } from 'ui/saved_objects';
export class SavedObjectLoader {
constructor(SavedObjectClass, kbnIndex, kbnUrl, $http) {
constructor(SavedObjectClass, kbnIndex, kbnUrl, $http, chrome) {
this.type = SavedObjectClass.type;
this.Class = SavedObjectClass;
this.lowercaseType = this.type.toLowerCase();
this.kbnIndex = kbnIndex;
this.kbnUrl = kbnUrl;
this.chrome = chrome;
this.scanner = new Scanner($http, {
index: kbnIndex,
@ -48,7 +49,11 @@ export class SavedObjectLoader {
return savedObject.delete();
});
return Promise.all(deletions);
return Promise.all(deletions).then(() => {
if (this.chrome) {
this.chrome.untrackNavLinksForDeletedSavedObjects(ids);
}
});
}
/**