Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion x-pack/plugins/beats_management/common/constants/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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/';
13 changes: 7 additions & 6 deletions x-pack/plugins/beats_management/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';

Expand All @@ -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);
},
});
}
4 changes: 1 addition & 3 deletions x-pack/plugins/beats_management/public/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand All @@ -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(<PageRouter history={history} />);
libs.framework.render(<PageRouter />);
}

startApp(compose());
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -26,11 +23,13 @@ export class KibanaFrameworkAdapter implements FrameworkAdapter {
private adapterService: KibanaAdapterServiceProvider;
private rootComponent: React.ReactElement<any> | 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 = {};
}

Expand All @@ -41,7 +40,7 @@ export class KibanaFrameworkAdapter implements FrameworkAdapter {
};

public render = (component: React.ReactElement<any>) => {
this.adapterService.callOrBuffer(() => (this.rootComponent = component));
this.rootComponent = component;
};

public registerManagementSection(pluginId: string, displayName: string, basePath: string) {
Expand All @@ -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: '<beats-cm><div id="beatsReactRoot" style="flex-grow: 1;"></div></beats-cm>',
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<any>, 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: `
<div
id="${ROOT_ELEMENT_ID}"
style="display: flex; flex-direction: column; align-items: stretch; flex: 1 0 0; overflow: hidden;"
></div>
`,
}));

adapterModule.run((
chrome: Chrome,
config: KibanaUIConfig,
kbnVersion: string,
Private: <Provider>(provider: Provider) => Provider,
// @ts-ignore: inject kibanaAdapter to force eager instatiation
kibanaAdapter: any
) => {
this.kbnVersion = kbnVersion;

chrome.setRootTemplate(
'<beats-cm-ui-kibana-adapter style="display: flex; align-items: stretch; flex: 1 0 0;"></beats-cm-ui-kibana-adapter>'
);
$scope.$onInit = () => {
$scope.topNavMenu = [];
};
}
},
});
};
}
Expand Down
8 changes: 4 additions & 4 deletions x-pack/plugins/beats_management/public/lib/compose/kibana.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
13 changes: 4 additions & 9 deletions x-pack/plugins/beats_management/public/routes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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<RouterProps> = ({ history }) => {
export const PageRouter: React.SFC<{}> = () => {
return (
<Router history={history}>
<HashRouter basename="/management/beats_management">
<Switch>
<Route path="/" exact={true} component={HomePage} />
<Route component={NotFoundPage} />
</Switch>
</Router>
</HashRouter>
);
};
8 changes: 3 additions & 5 deletions x-pack/plugins/index_management/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,22 +12,20 @@ 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);
registerIndicesRoutes(server);
registerSettingsRoutes(server);
registerStatsRoute(server);
registerMappingRoute(server);
}
},
});
}