diff --git a/x-pack/plugins/beats_management/common/constants/index.ts b/x-pack/plugins/beats_management/common/constants/index.ts
index b45f5e947cab2..b4e919607c604 100644
--- a/x-pack/plugins/beats_management/common/constants/index.ts
+++ b/x-pack/plugins/beats_management/common/constants/index.ts
@@ -7,4 +7,4 @@
export { PLUGIN } from './plugin';
export { INDEX_NAMES } from './index_names';
export { UNIQUENESS_ENFORCING_TYPES, ConfigurationBlockTypes } from './configuration_blocks';
-export const BASE_PATH = '/management/beats/';
+export const BASE_PATH = '/management/beats_management/';
diff --git a/x-pack/plugins/beats_management/index.ts b/x-pack/plugins/beats_management/index.ts
index 8b1ee828107dd..e6677d6bbcd57 100644
--- a/x-pack/plugins/beats_management/index.ts
+++ b/x-pack/plugins/beats_management/index.ts
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
import Joi from 'joi';
-import { resolve } from 'url';
+import { resolve } from 'path';
import { PLUGIN } from './common/constants';
import { initServerWithKibana } from './server/kibana.index';
@@ -22,16 +22,17 @@ export const configPrefix = 'xpack.beats';
export function beats(kibana: any) {
return new kibana.Plugin({
- config: () => config,
- configPrefix,
id: PLUGIN.ID,
require: ['kibana', 'elasticsearch', 'xpack_main'],
- init(server: any) {
- initServerWithKibana(server);
- },
publicDir: resolve(__dirname, 'public'),
uiExports: {
managementSections: ['plugins/beats_management'],
},
+ config: () => config,
+ configPrefix,
+
+ init(server: any) {
+ initServerWithKibana(server);
+ },
});
}
diff --git a/x-pack/plugins/beats_management/public/index.tsx b/x-pack/plugins/beats_management/public/index.tsx
index 20f82f9ec3f3a..1334deb1524e6 100644
--- a/x-pack/plugins/beats_management/public/index.tsx
+++ b/x-pack/plugins/beats_management/public/index.tsx
@@ -4,7 +4,6 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import { createHashHistory } from 'history';
import React from 'react';
import { BASE_PATH } from '../common/constants';
import { compose } from './lib/compose/kibana';
@@ -16,9 +15,8 @@ import { PageRouter } from './routes';
import '@elastic/eui/dist/eui_theme_light.css';
function startApp(libs: any) {
- const history = createHashHistory();
libs.framework.registerManagementSection('beats', 'Beats Management', BASE_PATH);
- libs.framework.render();
+ libs.framework.render();
}
startApp(compose());
diff --git a/x-pack/plugins/beats_management/public/lib/adapters/framework/kibana_framework_adapter.ts b/x-pack/plugins/beats_management/public/lib/adapters/framework/kibana_framework_adapter.ts
index 8ac20baab0f3f..042ebd71f9862 100644
--- a/x-pack/plugins/beats_management/public/lib/adapters/framework/kibana_framework_adapter.ts
+++ b/x-pack/plugins/beats_management/public/lib/adapters/framework/kibana_framework_adapter.ts
@@ -7,17 +7,14 @@
import { IModule, IScope } from 'angular';
import * as React from 'react';
import * as ReactDOM from 'react-dom';
+
import {
BufferedKibanaServiceCall,
- Chrome,
FrameworkAdapter,
KibanaAdapterServiceRefs,
KibanaUIConfig,
- UiKibanaAdapterScope,
} from '../../lib';
-const ROOT_ELEMENT_ID = 'react-beats-cm-root';
-
export class KibanaFrameworkAdapter implements FrameworkAdapter {
public appState: object;
public kbnVersion?: string;
@@ -26,11 +23,13 @@ export class KibanaFrameworkAdapter implements FrameworkAdapter {
private adapterService: KibanaAdapterServiceProvider;
private rootComponent: React.ReactElement | null = null;
private uiModule: IModule;
+ private routes: any;
- constructor(uiModule: IModule, management: any) {
+ constructor(uiModule: IModule, management: any, routes: any) {
this.adapterService = new KibanaAdapterServiceProvider();
this.management = management;
this.uiModule = uiModule;
+ this.routes = routes;
this.appState = {};
}
@@ -41,7 +40,7 @@ export class KibanaFrameworkAdapter implements FrameworkAdapter {
};
public render = (component: React.ReactElement) => {
- this.adapterService.callOrBuffer(() => (this.rootComponent = component));
+ this.rootComponent = component;
};
public registerManagementSection(pluginId: string, displayName: string, basePath: string) {
@@ -58,73 +57,51 @@ export class KibanaFrameworkAdapter implements FrameworkAdapter {
visible: true,
display: displayName,
order: 30,
- url: `#/${basePath}`,
+ url: `#${basePath}`,
});
this.register(this.uiModule);
}
+ private manageAngularLifecycle($scope: any, $route: any, elem: any) {
+ const lastRoute = $route.current;
+ const deregister = $scope.$on('$locationChangeSuccess', () => {
+ const currentRoute = $route.current;
+ // if templates are the same we are on the same route
+ if (lastRoute.$$route.template === currentRoute.$$route.template) {
+ // this prevents angular from destroying scope
+ $route.current = lastRoute;
+ }
+ });
+ $scope.$on('$destroy', () => {
+ if (deregister) {
+ deregister();
+ }
+ // manually unmount component when scope is destroyed
+ if (elem) {
+ ReactDOM.unmountComponentAtNode(elem);
+ }
+ });
+ }
+
private register = (adapterModule: IModule) => {
- adapterModule.provider('kibanaAdapter', this.adapterService);
-
- adapterModule.directive('beatsCMKibanaAdapter', () => ({
- controller: ($scope: UiKibanaAdapterScope, $element: JQLite) => ({
- $onDestroy: () => {
- const targetRootElement = $element[0].querySelector(`#${ROOT_ELEMENT_ID}`);
-
- if (targetRootElement) {
- ReactDOM.unmountComponentAtNode(targetRootElement);
- }
- },
- $onInit: () => {
- $scope.topNavMenu = [];
- },
- $postLink: () => {
- $scope.$watchGroup([], ([targetElement]) => {
- if (!targetElement) {
- return;
- }
-
- ReactDOM.unmountComponentAtNode(targetElement);
+ const adapter = this;
+ this.routes.when(`/management/beats_management/?`, {
+ template: '',
+ controllerAs: 'beatsManagement',
+ // tslint:disable-next-line: max-classes-per-file
+ controller: class BeatsManagementController {
+ constructor($scope: any, $route: any) {
+ $scope.$$postDigest(() => {
+ const elem = document.getElementById('beatsReactRoot');
+ ReactDOM.render(adapter.rootComponent as React.ReactElement, elem);
+ adapter.manageAngularLifecycle($scope, $route, elem);
});
- $scope.$watchGroup(
- [() => this.rootComponent, () => $element[0].querySelector(`#${ROOT_ELEMENT_ID}`)],
- ([rootComponent, targetElement]) => {
- if (!targetElement) {
- return;
- }
-
- if (rootComponent) {
- ReactDOM.render(rootComponent, targetElement);
- } else {
- ReactDOM.unmountComponentAtNode(targetElement);
- }
- }
- );
- },
- }),
- scope: true,
- template: `
-
- `,
- }));
-
- adapterModule.run((
- chrome: Chrome,
- config: KibanaUIConfig,
- kbnVersion: string,
- Private: (provider: Provider) => Provider,
- // @ts-ignore: inject kibanaAdapter to force eager instatiation
- kibanaAdapter: any
- ) => {
- this.kbnVersion = kbnVersion;
-
- chrome.setRootTemplate(
- ''
- );
+ $scope.$onInit = () => {
+ $scope.topNavMenu = [];
+ };
+ }
+ },
});
};
}
diff --git a/x-pack/plugins/beats_management/public/lib/compose/kibana.ts b/x-pack/plugins/beats_management/public/lib/compose/kibana.ts
index fe23bbc1306b8..7a98e62c18459 100644
--- a/x-pack/plugins/beats_management/public/lib/compose/kibana.ts
+++ b/x-pack/plugins/beats_management/public/lib/compose/kibana.ts
@@ -6,21 +6,21 @@
import 'ui/autoload/all';
// @ts-ignore: path dynamic for kibana
-import chrome from 'ui/chrome';
-// @ts-ignore: path dynamic for kibana
import { management } from 'ui/management';
// @ts-ignore: path dynamic for kibana
import { uiModules } from 'ui/modules';
// @ts-ignore: path dynamic for kibana
+import routes from 'ui/routes';
+// @ts-ignore: path dynamic for kibana
import { KibanaFrameworkAdapter } from '../adapters/framework/kibana_framework_adapter';
import { FrontendLibs } from '../lib';
export function compose(): FrontendLibs {
// const kbnVersion = (window as any).__KBN__.version;
- const pluginUIModule = uiModules.get('app/beats');
+ const pluginUIModule = uiModules.get('app/beats_management');
- const framework = new KibanaFrameworkAdapter(pluginUIModule, management);
+ const framework = new KibanaFrameworkAdapter(pluginUIModule, management, routes);
const libs: FrontendLibs = {
framework,
diff --git a/x-pack/plugins/beats_management/public/routes.tsx b/x-pack/plugins/beats_management/public/routes.tsx
index d1f6db5ebf11d..f5863b28aaafa 100644
--- a/x-pack/plugins/beats_management/public/routes.tsx
+++ b/x-pack/plugins/beats_management/public/routes.tsx
@@ -4,24 +4,19 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import { History } from 'history';
import React from 'react';
-import { Route, Router, Switch } from 'react-router-dom';
+import { HashRouter, Route, Switch } from 'react-router-dom';
import { NotFoundPage } from './pages/404';
import { HomePage } from './pages/home';
-interface RouterProps {
- history: History;
-}
-
-export const PageRouter: React.SFC = ({ history }) => {
+export const PageRouter: React.SFC<{}> = () => {
return (
-
+
-
+
);
};
diff --git a/x-pack/plugins/index_management/index.js b/x-pack/plugins/index_management/index.js
index c3d3e8fe1caf5..9a78cfef48c13 100644
--- a/x-pack/plugins/index_management/index.js
+++ b/x-pack/plugins/index_management/index.js
@@ -12,15 +12,13 @@ import { registerStatsRoute } from './server/routes/api/stats';
import { registerLicenseChecker } from './server/lib/register_license_checker';
import { PLUGIN } from './common/constants';
-export function indexManagement(kibana) {
+export function indexManagement(kibana) {
return new kibana.Plugin({
id: PLUGIN.ID,
publicDir: resolve(__dirname, 'public'),
require: ['kibana', 'elasticsearch', 'xpack_main'],
uiExports: {
- managementSections: [
- 'plugins/index_management',
- ]
+ managementSections: ['plugins/index_management'],
},
init: function (server) {
registerLicenseChecker(server);
@@ -28,6 +26,6 @@ export function indexManagement(kibana) {
registerSettingsRoutes(server);
registerStatsRoute(server);
registerMappingRoute(server);
- }
+ },
});
}