diff --git a/src/legacy/ui/public/chrome/directives/__tests__/sub_url_route_filter.js b/src/legacy/ui/public/chrome/api/__tests__/sub_url_route_filter.js similarity index 98% rename from src/legacy/ui/public/chrome/directives/__tests__/sub_url_route_filter.js rename to src/legacy/ui/public/chrome/api/__tests__/sub_url_route_filter.js index 5ce42b9c729160c..46421fdbd228020 100644 --- a/src/legacy/ui/public/chrome/directives/__tests__/sub_url_route_filter.js +++ b/src/legacy/ui/public/chrome/api/__tests__/sub_url_route_filter.js @@ -20,7 +20,7 @@ import ngMock from 'ng_mock'; import expect from '@kbn/expect'; -import { SubUrlRouteFilterProvider } from '../sub_url_route_filter'; +import { SubUrlRouteFilterProvider } from '../sub_url_hooks'; describe('kbn-chrome subUrlRouteFilter()', () => { describe('no ngRoute', () => { diff --git a/src/legacy/ui/public/chrome/api/angular.js b/src/legacy/ui/public/chrome/api/angular.js index 145653ad261128f..70aa3f8d86c2bfb 100644 --- a/src/legacy/ui/public/chrome/api/angular.js +++ b/src/legacy/ui/public/chrome/api/angular.js @@ -28,6 +28,7 @@ import { toastNotifications } from '../../notify'; import { UrlOverflowServiceProvider } from '../../error_url_overflow'; import { directivesProvider } from '../directives'; +import { registerSubUrlHooks } from './sub_url_hooks'; const URL_LIMIT_WARN_WITHIN = 1000; @@ -137,6 +138,7 @@ export function initAngularApi(chrome, internals) { }); directivesProvider(chrome, internals); + registerSubUrlHooks(kibana, internals); uiModules.link(kibana); }; diff --git a/src/legacy/ui/public/chrome/api/sub_url_hooks.js b/src/legacy/ui/public/chrome/api/sub_url_hooks.js new file mode 100644 index 000000000000000..1890e7af5c42730 --- /dev/null +++ b/src/legacy/ui/public/chrome/api/sub_url_hooks.js @@ -0,0 +1,80 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import url from 'url'; + +import { + getUnhashableStatesProvider, + unhashUrl, +} from '../../state_management/state_hashing'; + +export function registerSubUrlHooks(angularModule, internals) { + angularModule.run(($rootScope, Private, $location) => { + const getUnhashableStates = Private(getUnhashableStatesProvider); + const subUrlRouteFilter = Private(SubUrlRouteFilterProvider); + + function updateSubUrls() { + const urlWithHashes = window.location.href; + const urlWithStates = unhashUrl(urlWithHashes, getUnhashableStates()); + internals.trackPossibleSubUrl(urlWithStates); + } + + function onRouteChange($event) { + if (subUrlRouteFilter($event)) { + updateSubUrls(); + } + } + + $rootScope.$on('$locationChangeStart', (e, newUrl) => { + // This handler fixes issue #31238 where browser back navigation + // fails due to angular 1.6 parsing url encoded params wrong. + const absUrlHash = url.parse($location.absUrl()).hash.slice(1); + const decodedAbsUrlHash = decodeURIComponent(absUrlHash); + const hash = url.parse(newUrl).hash.slice(1); + const decodedHash = decodeURIComponent(hash); + if (absUrlHash !== hash && decodedHash === decodedAbsUrlHash) { + // replace the urlencoded hash with the version that angular sees. + $location.url(absUrlHash).replace(); + } + }); + + $rootScope.$on('$routeChangeSuccess', onRouteChange); + $rootScope.$on('$routeUpdate', onRouteChange); + updateSubUrls(); // initialize sub urls + }); +} + +/** + * Creates a function that will be called on each route change + * to determine if the event should be used to update the last + * subUrl of chrome links/tabs + * @injected + */ +export function SubUrlRouteFilterProvider($injector) { + if (!$injector.has('$route')) { + return function alwaysUpdate() { + return true; + }; + } + + const $route = $injector.get('$route'); + return function ignoreRedirectToRoutes() { + return Boolean($route.current && !$route.current.redirectTo); + }; +} diff --git a/src/legacy/ui/public/chrome/directives/kbn_chrome.js b/src/legacy/ui/public/chrome/directives/kbn_chrome.js index 7d7f703ccc88051..682af0abc47d9a1 100644 --- a/src/legacy/ui/public/chrome/directives/kbn_chrome.js +++ b/src/legacy/ui/public/chrome/directives/kbn_chrome.js @@ -20,19 +20,15 @@ import React from 'react'; import ReactDOM from 'react-dom'; import $ from 'jquery'; -import url from 'url'; import { uiModules } from '../../modules'; -import { - getUnhashableStatesProvider, - unhashUrl, -} from '../../state_management/state_hashing'; + import { notify, GlobalBannerList, banners, } from '../../notify'; -import { SubUrlRouteFilterProvider } from './sub_url_route_filter'; + import { I18nContext } from '../../i18n'; export function kbnChromeProvider(chrome, internals) { @@ -58,39 +54,7 @@ export function kbnChromeProvider(chrome, internals) { }, controllerAs: 'chrome', - controller($scope, $rootScope, Private, $location) { - const getUnhashableStates = Private(getUnhashableStatesProvider); - const subUrlRouteFilter = Private(SubUrlRouteFilterProvider); - - function updateSubUrls() { - const urlWithHashes = window.location.href; - const urlWithStates = unhashUrl(urlWithHashes, getUnhashableStates()); - internals.trackPossibleSubUrl(urlWithStates); - } - - function onRouteChange($event) { - if (subUrlRouteFilter($event)) { - updateSubUrls(); - } - } - - $rootScope.$on('$locationChangeStart', (e, newUrl) => { - // This handler fixes issue #31238 where browser back navigation - // fails due to angular 1.6 parsing url encoded params wrong. - const absUrlHash = url.parse($location.absUrl()).hash.slice(1); - const decodedAbsUrlHash = decodeURIComponent(absUrlHash); - const hash = url.parse(newUrl).hash.slice(1); - const decodedHash = decodeURIComponent(hash); - if (absUrlHash !== hash && decodedHash === decodedAbsUrlHash) { - // replace the urlencoded hash with the version that angular sees. - $location.url(absUrlHash).replace(); - } - }); - - $rootScope.$on('$routeChangeSuccess', onRouteChange); - $rootScope.$on('$routeUpdate', onRouteChange); - updateSubUrls(); // initialize sub urls - + controller($scope) { // Notifications $scope.notifList = notify._notifs; diff --git a/src/legacy/ui/public/chrome/directives/sub_url_route_filter.js b/src/legacy/ui/public/chrome/directives/sub_url_route_filter.js deleted file mode 100644 index 0ccd10d97ad25c8..000000000000000 --- a/src/legacy/ui/public/chrome/directives/sub_url_route_filter.js +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -/** - * Creates a function that will be called on each route change - * to determine if the event should be used to update the last - * subUrl of chrome links/tabs - * @injected - */ -export function SubUrlRouteFilterProvider($injector) { - if (!$injector.has('$route')) { - return function alwaysUpdate() { - return true; - }; - } - - const $route = $injector.get('$route'); - return function ignoreRedirectToRoutes() { - return Boolean($route.current && !$route.current.redirectTo); - }; -}