"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.createKbnUrlTracker = createKbnUrlTracker; var _history = require("history"); var _kbn_url_storage = require("./kbn_url_storage"); var _hash_unhash_url = require("./hash_unhash_url"); /* * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one * or more contributor license agreements. Licensed under the Elastic License * 2.0 and the Server Side Public License, v 1; you may not use this file except * in compliance with, at your election, the Elastic License 2.0 or the Server * Side Public License, v 1. */ /** * Listens to history changes and optionally to global state changes and updates the nav link url of * a given app to point to the last visited page within the app. * * This includes the following parts: * * When the app is currently active, the nav link points to the configurable default url of the app. * * When the app is not active the last visited url is set to the nav link. * * When a provided observable emits a new value, the state parameter in the url of the nav link is updated * as long as the app is not active. */ function createKbnUrlTracker({ baseUrl, defaultSubUrl, storageKey, stateParams, navLinkUpdater$, toastNotifications, history, getHistory, storage, shouldTrackUrlUpdate = () => { return true; }, onBeforeNavLinkSaved = newNavLink => newNavLink }) { const storageInstance = storage || sessionStorage; // local state storing previous active url to make restore possible let previousActiveUrl = ''; // local state storing current listeners and active url let activeUrl = ''; let unsubscribeURLHistory; let unsubscribeGlobalState; function setNavLink(hash) { navLinkUpdater$.next(() => ({ defaultPath: hash })); } function getActiveSubUrl(url) { // remove baseUrl prefix (just storing the sub url part) return url.substr(baseUrl.length); } function unsubscribe() { if (unsubscribeURLHistory) { unsubscribeURLHistory(); unsubscribeURLHistory = undefined; } if (unsubscribeGlobalState) { unsubscribeGlobalState.forEach(sub => sub.unsubscribe()); unsubscribeGlobalState = undefined; } } function setActiveUrl(newUrl) { const urlWithHashes = baseUrl + '#' + newUrl; let urlWithStates = ''; try { urlWithStates = (0, _hash_unhash_url.unhashUrl)(urlWithHashes); } catch (e) { toastNotifications.addDanger(e.message); } previousActiveUrl = activeUrl; activeUrl = getActiveSubUrl(urlWithStates || urlWithHashes); activeUrl = onBeforeNavLinkSaved(activeUrl); storageInstance.setItem(storageKey, activeUrl); } function onMountApp() { unsubscribe(); const historyInstance = history || getHistory && getHistory() || (0, _history.createHashHistory)(); // set mounted URL as active if (shouldTrackUrlUpdate(historyInstance.location.hash)) { setActiveUrl(historyInstance.location.hash.substr(1)); } // track current hash when within app unsubscribeURLHistory = historyInstance.listen(location => { if (shouldTrackUrlUpdate(location.hash)) { setActiveUrl(location.hash.substr(1)); } }); } function onUnmountApp() { unsubscribe(); // propagate state updates when in other apps unsubscribeGlobalState = stateParams.map(({ stateUpdate$, kbnUrlKey }) => stateUpdate$.subscribe(state => { const updatedUrl = (0, _kbn_url_storage.setStateToKbnUrl)(kbnUrlKey, state, { useHash: false }, baseUrl + (activeUrl || defaultSubUrl)); previousActiveUrl = activeUrl; // remove baseUrl prefix (just storing the sub url part) activeUrl = getActiveSubUrl(updatedUrl); // allow app to mutate resulting URL before committing activeUrl = onBeforeNavLinkSaved(activeUrl); storageInstance.setItem(storageKey, activeUrl); setNavLink(activeUrl); })); } // register listeners for unmounted app initially onUnmountApp(); // initialize nav link and internal state const storedUrl = storageInstance.getItem(storageKey); if (storedUrl) { activeUrl = storedUrl; previousActiveUrl = storedUrl; setNavLink(storedUrl); } return { appMounted() { onMountApp(); setNavLink(defaultSubUrl); }, appUnMounted() { onUnmountApp(); setNavLink(activeUrl); }, stop() { unsubscribe(); }, setActiveUrl, getActiveUrl() { return activeUrl; }, restorePreviousUrl() { activeUrl = previousActiveUrl; } }; }