Skip to content

Commit

Permalink
Extract angular configuration from ui/chrome (elastic#34314)
Browse files Browse the repository at this point in the history
  • Loading branch information
joshdover committed Apr 10, 2019
1 parent 13e6a4a commit 51d86b3
Show file tree
Hide file tree
Showing 15 changed files with 557 additions and 410 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ new CoreSystem({
legacyMetadata: {
version: '1.2.3',
buildNum: 1234,
devMode: true,
uiSettings: {
defaults: ${JSON.stringify(defaultUiSettings, null, 2).split('\n').join('\n ')},
user: {}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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', () => {
Expand Down
116 changes: 0 additions & 116 deletions src/legacy/ui/public/chrome/api/__tests__/xsrf.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,12 @@
* under the License.
*/

import $ from 'jquery';
import expect from '@kbn/expect';
import sinon from 'sinon';
import ngMock from 'ng_mock';

import { initChromeXsrfApi } from '../xsrf';
import { version } from '../../../../../utils/package_json';

const xsrfHeader = 'kbn-version';

describe('chrome xsrf apis', function () {
const sandbox = sinon.createSandbox();

Expand All @@ -41,116 +37,4 @@ describe('chrome xsrf apis', function () {
expect(chrome.getXsrfToken()).to.be(version);
});
});

describe('jQuery support', function () {
it('adds a global jQuery prefilter', function () {
sandbox.stub($, 'ajaxPrefilter');
initChromeXsrfApi({}, { version });
expect($.ajaxPrefilter.callCount).to.be(1);
});

describe('jQuery prefilter', function () {
let prefilter;

beforeEach(function () {
sandbox.stub($, 'ajaxPrefilter');
initChromeXsrfApi({}, { version });
prefilter = $.ajaxPrefilter.args[0][0];
});

it(`sets the ${xsrfHeader} header`, function () {
const setHeader = sinon.stub();
prefilter({}, {}, { setRequestHeader: setHeader });

expect(setHeader.callCount).to.be(1);
expect(setHeader.args[0]).to.eql([
xsrfHeader,
version
]);
});

it('can be canceled by setting the kbnXsrfToken option', function () {
const setHeader = sinon.stub();
prefilter({ kbnXsrfToken: false }, {}, { setRequestHeader: setHeader });
expect(setHeader.callCount).to.be(0);
});
});

describe('Angular support', function () {

let $http;
let $httpBackend;

beforeEach(function () {
sandbox.stub($, 'ajaxPrefilter');
const chrome = {};
initChromeXsrfApi(chrome, { version });
ngMock.module(chrome.$setupXsrfRequestInterceptor);
});

beforeEach(ngMock.inject(function ($injector) {
$http = $injector.get('$http');
$httpBackend = $injector.get('$httpBackend');

$httpBackend
.when('POST', '/api/test')
.respond('ok');
}));

afterEach(function () {
$httpBackend.verifyNoOutstandingExpectation();
$httpBackend.verifyNoOutstandingRequest();
});

it(`injects a ${xsrfHeader} header on every request`, function () {
$httpBackend.expectPOST('/api/test', undefined, function (headers) {
return headers[xsrfHeader] === version;
}).respond(200, '');

$http.post('/api/test');
$httpBackend.flush();
});

it('skips requests with the kbnXsrfToken set falsy', function () {
$httpBackend.expectPOST('/api/test', undefined, function (headers) {
return !(xsrfHeader in headers);
}).respond(200, '');

$http({
method: 'POST',
url: '/api/test',
kbnXsrfToken: 0
});

$http({
method: 'POST',
url: '/api/test',
kbnXsrfToken: ''
});

$http({
method: 'POST',
url: '/api/test',
kbnXsrfToken: false
});

$httpBackend.flush();
});

it('treats the kbnXsrfToken option as boolean-y', function () {
const customToken = `custom:${version}`;
$httpBackend.expectPOST('/api/test', undefined, function (headers) {
return headers[xsrfHeader] === version;
}).respond(200, '');

$http({
method: 'POST',
url: '/api/test',
kbnXsrfToken: customToken
});

$httpBackend.flush();
});
});
});
});
112 changes: 5 additions & 107 deletions src/legacy/ui/public/chrome/api/angular.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,125 +17,23 @@
* under the License.
*/

import React, { Fragment } from 'react';
import _ from 'lodash';
import { modifyUrl } from 'ui/url';
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n/react';

import { uiModules } from '../../modules';
import { toastNotifications } from '../../notify';
import { UrlOverflowServiceProvider } from '../../error_url_overflow';

import { directivesProvider } from '../directives';

const URL_LIMIT_WARN_WITHIN = 1000;
import { registerSubUrlHooks } from './sub_url_hooks';
import { configureAppAngularModule } from 'ui/legacy_compat';

export function initAngularApi(chrome, internals) {
chrome.getFirstPathSegment = _.noop;

chrome.setupAngular = function () {
const kibana = uiModules.get('kibana');

_.forOwn(chrome.getInjected(), function (val, name) {
kibana.value(name, val);
});
configureAppAngularModule(kibana);

kibana
.value('kbnVersion', internals.version)
.value('buildNum', internals.buildNum)
.value('buildSha', internals.buildSha)
.value('serverName', internals.serverName)
.value('sessionId', Date.now())
.value('chrome', chrome)
.value('esUrl', (function () {
const a = document.createElement('a');
a.href = chrome.addBasePath('/elasticsearch');
const protocolPort = /https/.test(a.protocol) ? 443 : 80;
const port = a.port || protocolPort;
return {
host: a.hostname,
port,
protocol: a.protocol,
pathname: a.pathname
};
}()))
.config($locationProvider => {
$locationProvider.html5Mode({
enabled: false,
requireBase: false,
rewriteLinks: false,
});
})
.config(chrome.$setupXsrfRequestInterceptor)
.config(function ($compileProvider, $locationProvider) {
if (!internals.devMode) {
$compileProvider.debugInfoEnabled(false);
}

$locationProvider.hashPrefix('');
})
.run(internals.capture$httpLoadingCount)
.run(internals.$setupBreadcrumbsAutoClear)
.run(internals.$setupHelpExtensionAutoClear)
.run(internals.$initNavLinksDeepWatch)
.run(($location, $rootScope, Private, config) => {
chrome.getFirstPathSegment = () => {
return $location.path().split('/')[1];
};

const urlOverflow = Private(UrlOverflowServiceProvider);
const check = () => {
// disable long url checks when storing state in session storage
if (config.get('state:storeInSessionStorage')) {
return;
}

if ($location.path() === '/error/url-overflow') {
return;
}

try {
if (urlOverflow.check($location.absUrl()) <= URL_LIMIT_WARN_WITHIN) {
toastNotifications.addWarning({
title: i18n.translate('common.ui.chrome.bigUrlWarningNotificationTitle', {
defaultMessage: 'The URL is big and Kibana might stop working'
}),
text: (
<Fragment>
<FormattedMessage
id="common.ui.chrome.bigUrlWarningNotificationMessage"
defaultMessage="Either enable the {storeInSessionStorageParam} option
in {advancedSettingsLink} or simplify the onscreen visuals."
values={{
storeInSessionStorageParam: <code>state:storeInSessionStorage</code>,
advancedSettingsLink: (
<a href="#/management/kibana/settings">
<FormattedMessage
id="common.ui.chrome.bigUrlWarningNotificationMessage.advancedSettingsLinkText"
defaultMessage="advanced settings"
/>
</a>
)
}}
/>
</Fragment>
),
});
}
} catch (e) {
window.location.href = modifyUrl(window.location.href, parts => {
parts.hash = '#/error/url-overflow';
});
// force the browser to reload to that Kibana's potentially unstable state is unloaded
window.location.reload();
}
};

$rootScope.$on('$routeUpdate', check);
$rootScope.$on('$routeChangeStart', check);
});
.run(internals.$initNavLinksDeepWatch);

registerSubUrlHooks(kibana, internals);
directivesProvider(chrome, internals);

uiModules.link(kibana);
Expand Down
42 changes: 1 addition & 41 deletions src/legacy/ui/public/chrome/api/breadcrumbs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,6 @@
* under the License.
*/

import { IRootScopeService } from 'angular';
import { fatalError } from 'ui/notify/fatal_error';
import { ChromeBreadcrumb, ChromeSetup } from '../../../../../core/public';
export type Breadcrumb = ChromeBreadcrumb;

Expand All @@ -34,16 +32,12 @@ export function __newPlatformInit__(instance: ChromeSetup) {
}

function createBreadcrumbsApi(chrome: { [key: string]: any }) {
// A flag used to determine if we should automatically
// clear the breadcrumbs between angular route changes.
let breadcrumbSetSinceRouteChange = false;
let currentBreadcrumbs: Breadcrumb[] = [];

// reset breadcrumbSetSinceRouteChange any time the breadcrumbs change, even
// if it was done directly through the new platform
newPlatformChrome.getBreadcrumbs$().subscribe({
next(nextBreadcrumbs) {
breadcrumbSetSinceRouteChange = true;
currentBreadcrumbs = nextBreadcrumbs;
},
});
Expand Down Expand Up @@ -79,47 +73,13 @@ function createBreadcrumbsApi(chrome: { [key: string]: any }) {
newPlatformChrome.setBreadcrumbs(currentBreadcrumbs.filter(fn));
},
},

/**
* internal angular run function that will be called when angular bootstraps and
* lets us integrate with the angular router so that we can automatically clear
* the breadcrumbs if we switch to a Kibana app that does not use breadcrumbs correctly
*/
$setupBreadcrumbsAutoClear: ($rootScope: IRootScopeService, $injector: any) => {
const $route = $injector.has('$route') ? $injector.get('$route') : {};

$rootScope.$on('$routeChangeStart', () => {
breadcrumbSetSinceRouteChange = false;
});

$rootScope.$on('$routeChangeSuccess', () => {
const current = $route.current || {};

if (breadcrumbSetSinceRouteChange || (current.$$route && current.$$route.redirectTo)) {
return;
}

const k7BreadcrumbsProvider = current.k7Breadcrumbs;
if (!k7BreadcrumbsProvider) {
newPlatformChrome.setBreadcrumbs([]);
return;
}

try {
chrome.breadcrumbs.set($injector.invoke(k7BreadcrumbsProvider));
} catch (error) {
fatalError(error);
}
});
},
};
}

export function initBreadcrumbsApi(
chrome: { [key: string]: any },
internals: { [key: string]: any }
) {
const { breadcrumbs, $setupBreadcrumbsAutoClear } = createBreadcrumbsApi(chrome);
const { breadcrumbs } = createBreadcrumbsApi(chrome);
chrome.breadcrumbs = breadcrumbs;
internals.$setupBreadcrumbsAutoClear = $setupBreadcrumbsAutoClear;
}
Loading

0 comments on commit 51d86b3

Please sign in to comment.