kibana/x-pack/plugins/graph/public/application.ts
Tim Roes c48428ed22
[Graph] Use new ES client and change license API (#84398)
* Remove deprecated Graph licensing methods

* Use new elasticsearch client

* fix typing error

Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
2020-11-30 18:08:58 +01:00

159 lines
5.3 KiB
TypeScript

/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
// inner angular imports
// these are necessary to bootstrap the local angular.
// They can stay even after NP cutover
import angular from 'angular';
import { i18nDirective, i18nFilter, I18nProvider } from '@kbn/i18n/angular';
import 'brace';
import 'brace/mode/json';
import '@elastic/ui-ace/ui-ace';
// required for i18nIdDirective and `ngSanitize` angular module
import 'angular-sanitize';
// required for ngRoute
import 'angular-route';
// type imports
import {
AppMountContext,
ChromeStart,
CoreStart,
PluginInitializerContext,
SavedObjectsClientContract,
ToastsStart,
OverlayStart,
AppMountParameters,
} from 'kibana/public';
// @ts-ignore
import { initGraphApp } from './app';
import { Plugin as DataPlugin, IndexPatternsContract } from '../../../../src/plugins/data/public';
import { LicensingPluginStart } from '../../licensing/public';
import { checkLicense } from '../common/check_license';
import { NavigationPublicPluginStart as NavigationStart } from '../../../../src/plugins/navigation/public';
import { Storage } from '../../../../src/plugins/kibana_utils/public';
import {
configureAppAngularModule,
createTopNavDirective,
createTopNavHelper,
KibanaLegacyStart,
} from '../../../../src/plugins/kibana_legacy/public';
import './index.scss';
import { SavedObjectsStart } from '../../../../src/plugins/saved_objects/public';
/**
* These are dependencies of the Graph app besides the base dependencies
* provided by the application service. Some of those still rely on non-shimmed
* plugins in LP-world, but if they are migrated only the import path in the plugin
* itself changes
*/
export interface GraphDependencies {
pluginInitializerContext: PluginInitializerContext;
core: CoreStart;
element: HTMLElement;
appBasePath: string;
capabilities: Record<string, boolean | Record<string, boolean>>;
coreStart: AppMountContext['core'];
navigation: NavigationStart;
licensing: LicensingPluginStart;
chrome: ChromeStart;
toastNotifications: ToastsStart;
indexPatterns: IndexPatternsContract;
data: ReturnType<DataPlugin['start']>;
savedObjectsClient: SavedObjectsClientContract;
addBasePath: (url: string) => string;
getBasePath: () => string;
storage: Storage;
canEditDrillDownUrls: boolean;
graphSavePolicy: string;
overlays: OverlayStart;
savedObjects: SavedObjectsStart;
kibanaLegacy: KibanaLegacyStart;
setHeaderActionMenu: AppMountParameters['setHeaderActionMenu'];
}
export const renderApp = ({ appBasePath, element, kibanaLegacy, ...deps }: GraphDependencies) => {
kibanaLegacy.loadFontAwesome();
const graphAngularModule = createLocalAngularModule(deps.navigation);
configureAppAngularModule(
graphAngularModule,
{ core: deps.core, env: deps.pluginInitializerContext.env },
true
);
const licenseSubscription = deps.licensing.license$.subscribe((license) => {
const info = checkLicense(license);
const licenseAllowsToShowThisPage = info.showAppLink && info.enableAppLink;
if (!licenseAllowsToShowThisPage) {
deps.coreStart.notifications.toasts.addDanger(info.message);
// This has to happen in the next tick because otherwise the original navigation
// bringing us to the graph app in the first place
// never completes and the browser enters are redirect loop
setTimeout(() => {
deps.coreStart.application.navigateToApp('home');
}, 0);
}
});
initGraphApp(graphAngularModule, deps);
const $injector = mountGraphApp(appBasePath, element);
return () => {
licenseSubscription.unsubscribe();
$injector.get('$rootScope').$destroy();
};
};
const mainTemplate = (basePath: string) => `<div ng-view class="gphAppWrapper">
<base href="${basePath}" />
</div>
`;
const moduleName = 'app/graph';
const thirdPartyAngularDependencies = ['ngSanitize', 'ngRoute', 'react', 'ui.bootstrap', 'ui.ace'];
function mountGraphApp(appBasePath: string, element: HTMLElement) {
const mountpoint = document.createElement('div');
mountpoint.setAttribute('class', 'gphAppWrapper');
// eslint-disable-next-line no-unsanitized/property
mountpoint.innerHTML = mainTemplate(appBasePath);
// bootstrap angular into detached element and attach it later to
// make angular-within-angular possible
const $injector = angular.bootstrap(mountpoint, [moduleName]);
element.appendChild(mountpoint);
element.setAttribute('class', 'gphAppWrapper');
return $injector;
}
function createLocalAngularModule(navigation: NavigationStart) {
createLocalI18nModule();
createLocalTopNavModule(navigation);
const graphAngularModule = angular.module(moduleName, [
...thirdPartyAngularDependencies,
'graphI18n',
'graphTopNav',
]);
return graphAngularModule;
}
function createLocalTopNavModule(navigation: NavigationStart) {
angular
.module('graphTopNav', ['react'])
.directive('kbnTopNav', createTopNavDirective)
.directive('kbnTopNavHelper', createTopNavHelper(navigation.ui));
}
function createLocalI18nModule() {
angular
.module('graphI18n', [])
.provider('i18n', I18nProvider)
.filter('i18n', i18nFilter)
.directive('i18nId', i18nDirective);
}