Use modern mount context in Dev Tools and Console (#70379)

* Use modern mount context in Dev Tools and Console, and clean up plugin definitions of Grok Debugger, Search Profiler, and Painless Lab.

* Remove return value from Console lifecycle method.

Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>
This commit is contained in:
CJ Cenizal 2020-07-01 12:40:52 -07:00 committed by GitHub
parent 97924a6d86
commit 91b8e7de24
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 89 additions and 84 deletions

View file

@ -18,17 +18,13 @@
*/
import { i18n } from '@kbn/i18n';
import { CoreSetup, CoreStart, Plugin } from 'kibana/public';
import { Plugin, CoreSetup } from 'src/core/public';
import { FeatureCatalogueCategory } from '../../home/public';
import { AppSetupUIPluginDependencies } from './types';
export class ConsoleUIPlugin implements Plugin<void, void, AppSetupUIPluginDependencies> {
constructor() {}
async setup(
public setup(
{ notifications, getStartServices }: CoreSetup,
{ devTools, home, usageCollection }: AppSetupUIPluginDependencies
) {
@ -53,16 +49,25 @@ export class ConsoleUIPlugin implements Plugin<void, void, AppSetupUIPluginDepen
defaultMessage: 'Console',
}),
enableRouting: false,
mount: async ({ core: { docLinks, i18n: i18nDep } }, { element }) => {
mount: async ({ element }) => {
const [core] = await getStartServices();
const {
injectedMetadata,
i18n: { Context: I18nContext },
docLinks: { DOC_LINK_VERSION },
} = core;
const { renderApp } = await import('./application');
const [{ injectedMetadata }] = await getStartServices();
const elasticsearchUrl = injectedMetadata.getInjectedVar(
'elasticsearchUrl',
'http://localhost:9200'
) as string;
return renderApp({
docLinkVersion: docLinks.DOC_LINK_VERSION,
I18nContext: i18nDep.Context,
docLinkVersion: DOC_LINK_VERSION,
I18nContext,
notifications,
elasticsearchUrl,
usageCollection,
@ -72,5 +77,5 @@ export class ConsoleUIPlugin implements Plugin<void, void, AppSetupUIPluginDepen
});
}
async start(core: CoreStart) {}
public start() {}
}

View file

@ -16,21 +16,21 @@
* specific language governing permissions and limitations
* under the License.
*/
import React, { useEffect, useRef } from 'react';
import ReactDOM from 'react-dom';
import { HashRouter as Router, Switch, Route, Redirect } from 'react-router-dom';
import { EuiTab, EuiTabs, EuiToolTip } from '@elastic/eui';
import { I18nProvider } from '@kbn/i18n/react';
import { i18n } from '@kbn/i18n';
import { EuiTab, EuiTabs, EuiToolTip } from '@elastic/eui';
import { HashRouter as Router, Switch, Route, Redirect } from 'react-router-dom';
import * as React from 'react';
import ReactDOM from 'react-dom';
import { useEffect, useRef } from 'react';
import { AppMountContext, AppMountDeprecated, ScopedHistory } from 'kibana/public';
import { ApplicationStart, ChromeStart, ScopedHistory } from 'src/core/public';
import { DevToolApp } from './dev_tool';
interface DevToolsWrapperProps {
devTools: readonly DevToolApp[];
activeDevTool: DevToolApp;
appMountContext: AppMountContext;
updateRoute: (newRoute: string) => void;
}
@ -40,12 +40,7 @@ interface MountedDevToolDescriptor {
unmountHandler: () => void;
}
function DevToolsWrapper({
devTools,
activeDevTool,
appMountContext,
updateRoute,
}: DevToolsWrapperProps) {
function DevToolsWrapper({ devTools, activeDevTool, updateRoute }: DevToolsWrapperProps) {
const mountedTool = useRef<MountedDevToolDescriptor | null>(null);
useEffect(
@ -90,6 +85,7 @@ function DevToolsWrapper({
if (mountedTool.current) {
mountedTool.current.unmountHandler();
}
const params = {
element,
appBasePath: '',
@ -97,9 +93,9 @@ function DevToolsWrapper({
// TODO: adapt to use Core's ScopedHistory
history: {} as any,
};
const unmountHandler = isAppMountDeprecated(activeDevTool.mount)
? await activeDevTool.mount(appMountContext, params)
: await activeDevTool.mount(params);
const unmountHandler = await activeDevTool.mount(params);
mountedTool.current = {
devTool: activeDevTool,
mountpoint: element,
@ -112,19 +108,20 @@ function DevToolsWrapper({
);
}
function redirectOnMissingCapabilities(appMountContext: AppMountContext) {
if (!appMountContext.core.application.capabilities.dev_tools.show) {
appMountContext.core.application.navigateToApp('home');
function redirectOnMissingCapabilities(application: ApplicationStart) {
if (!application.capabilities.dev_tools.show) {
application.navigateToApp('home');
return true;
}
return false;
}
function setBadge(appMountContext: AppMountContext) {
if (appMountContext.core.application.capabilities.dev_tools.save) {
function setBadge(application: ApplicationStart, chrome: ChromeStart) {
if (application.capabilities.dev_tools.save) {
return;
}
appMountContext.core.chrome.setBadge({
chrome.setBadge({
text: i18n.translate('devTools.badge.readOnly.text', {
defaultMessage: 'Read only',
}),
@ -135,16 +132,16 @@ function setBadge(appMountContext: AppMountContext) {
});
}
function setTitle(appMountContext: AppMountContext) {
appMountContext.core.chrome.docTitle.change(
function setTitle(chrome: ChromeStart) {
chrome.docTitle.change(
i18n.translate('devTools.pageTitle', {
defaultMessage: 'Dev Tools',
})
);
}
function setBreadcrumbs(appMountContext: AppMountContext) {
appMountContext.core.chrome.setBreadcrumbs([
function setBreadcrumbs(chrome: ChromeStart) {
chrome.setBreadcrumbs([
{
text: i18n.translate('devTools.k7BreadcrumbsDevToolsLabel', {
defaultMessage: 'Dev Tools',
@ -156,16 +153,19 @@ function setBreadcrumbs(appMountContext: AppMountContext) {
export function renderApp(
element: HTMLElement,
appMountContext: AppMountContext,
application: ApplicationStart,
chrome: ChromeStart,
history: ScopedHistory,
devTools: readonly DevToolApp[]
) {
if (redirectOnMissingCapabilities(appMountContext)) {
if (redirectOnMissingCapabilities(application)) {
return () => {};
}
setBadge(appMountContext);
setBreadcrumbs(appMountContext);
setTitle(appMountContext);
setBadge(application, chrome);
setBreadcrumbs(chrome);
setTitle(chrome);
ReactDOM.render(
<I18nProvider>
<Router>
@ -183,7 +183,6 @@ export function renderApp(
updateRoute={props.history.push}
activeDevTool={devTool}
devTools={devTools}
appMountContext={appMountContext}
/>
)}
/>
@ -208,8 +207,3 @@ export function renderApp(
unlisten();
};
}
function isAppMountDeprecated(mount: (...args: any[]) => any): mount is AppMountDeprecated {
// Mount functions with two arguments are assumed to expect deprecated `context` object.
return mount.length === 2;
}

View file

@ -16,7 +16,8 @@
* specific language governing permissions and limitations
* under the License.
*/
import { App } from 'kibana/public';
import { AppMount } from 'src/core/public';
/**
* Descriptor for a dev tool. A dev tool works similar to an application
@ -38,7 +39,7 @@ export class DevToolApp {
* This will be used as a label in the tab above the actual tool.
*/
public readonly title: string;
public readonly mount: App['mount'];
public readonly mount: AppMount;
/**
* Flag indicating to disable the tab of this dev tool. Navigating to a
@ -66,7 +67,7 @@ export class DevToolApp {
constructor(
id: string,
title: string,
mount: App['mount'],
mount: AppMount,
enableRouting: boolean,
order: number,
toolTipContent = '',

View file

@ -18,12 +18,14 @@
*/
import { BehaviorSubject } from 'rxjs';
import { AppUpdater, CoreSetup, Plugin } from 'kibana/public';
import { Plugin, CoreSetup, AppMountParameters } from 'src/core/public';
import { AppUpdater } from 'kibana/public';
import { i18n } from '@kbn/i18n';
import { sortBy } from 'lodash';
import { AppNavLinkStatus, DEFAULT_APP_CATEGORIES } from '../../../core/public';
import { KibanaLegacySetup } from '../../kibana_legacy/public';
import { CreateDevToolArgs, DevToolApp, createDevToolApp } from './dev_tool';
import { AppNavLinkStatus, DEFAULT_APP_CATEGORIES } from '../../../core/public';
import './index.scss';
@ -49,8 +51,10 @@ export class DevToolsPlugin implements Plugin<DevToolsSetup, void> {
return sortBy([...this.devTools.values()], 'order');
}
public setup(core: CoreSetup, { kibanaLegacy }: { kibanaLegacy: KibanaLegacySetup }) {
core.application.register({
public setup(coreSetup: CoreSetup, { kibanaLegacy }: { kibanaLegacy: KibanaLegacySetup }) {
const { application: applicationSetup, getStartServices } = coreSetup;
applicationSetup.register({
id: 'dev_tools',
title: i18n.translate('devTools.devToolsTitle', {
defaultMessage: 'Dev Tools',
@ -59,15 +63,18 @@ export class DevToolsPlugin implements Plugin<DevToolsSetup, void> {
euiIconType: 'devToolsApp',
order: 9001,
category: DEFAULT_APP_CATEGORIES.management,
mount: async (appMountContext, params) => {
if (!this.getSortedDevTools) {
throw new Error('not started yet');
}
mount: async (params: AppMountParameters) => {
const { element, history } = params;
element.classList.add('devAppWrapper');
const [core] = await getStartServices();
const { application, chrome } = core;
const { renderApp } = await import('./application');
params.element.classList.add('devAppWrapper');
return renderApp(params.element, appMountContext, params.history, this.getSortedDevTools());
return renderApp(element, application, chrome, history, this.getSortedDevTools());
},
});
kibanaLegacy.forwardApp('dev_tools', 'dev_tools');
return {

View file

@ -4,8 +4,8 @@
* you may not use this file except in compliance with the Elastic License.
*/
import { Plugin } from './plugin';
import { GrokDebuggerUIPlugin } from './plugin';
export function plugin(initializerContext) {
return new Plugin(initializerContext);
return new GrokDebuggerUIPlugin(initializerContext);
}

View file

@ -6,10 +6,11 @@
import { i18n } from '@kbn/i18n';
import { first } from 'rxjs/operators';
import { registerFeature } from './register_feature';
import { PLUGIN } from '../common/constants';
export class Plugin {
import { PLUGIN } from '../common/constants';
import { registerFeature } from './register_feature';
export class GrokDebuggerUIPlugin {
setup(coreSetup, plugins) {
registerFeature(plugins.home);
@ -20,7 +21,7 @@ export class Plugin {
}),
id: PLUGIN.ID,
enableRouting: false,
async mount(context, { element }) {
async mount({ element }) {
const [coreStart] = await coreSetup.getStartServices();
const license = await plugins.licensing.license$.pipe(first()).toPromise();
const { renderApp } = await import('./render_app');

View file

@ -5,10 +5,10 @@
*/
import React from 'react';
import { i18n } from '@kbn/i18n';
import { Plugin, CoreStart, CoreSetup } from 'kibana/public';
import { first } from 'rxjs/operators';
import { EuiBetaBadge, EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { Plugin, CoreSetup } from 'src/core/public';
import { FeatureCatalogueCategory } from '../../../../src/plugins/home/public';
@ -27,7 +27,7 @@ const checkLicenseStatus = (license: ILicense) => {
export class PainlessLabUIPlugin implements Plugin<void, void, PluginDependencies> {
languageService = new LanguageService();
async setup(
public setup(
{ http, getStartServices, uiSettings }: CoreSetup,
{ devTools, home, licensing }: PluginDependencies
) {
@ -70,7 +70,7 @@ export class PainlessLabUIPlugin implements Plugin<void, void, PluginDependencie
) as any,
enableRouting: false,
disabled: false,
mount: async (ctx, { element }) => {
mount: async ({ element }) => {
const [core] = await getStartServices();
const {
@ -115,9 +115,9 @@ export class PainlessLabUIPlugin implements Plugin<void, void, PluginDependencie
});
}
async start(core: CoreStart, plugins: any) {}
public start() {}
async stop() {
public stop() {
this.languageService.stop();
}
}

View file

@ -5,9 +5,8 @@
*/
import './styles/_index.scss';
import { PluginInitializerContext } from 'src/core/public';
import { SearchProfilerUIPlugin } from './plugin';
export function plugin(ctx: PluginInitializerContext) {
return new SearchProfilerUIPlugin(ctx);
export function plugin() {
return new SearchProfilerUIPlugin();
}

View file

@ -4,9 +4,9 @@
* you may not use this file except in compliance with the Elastic License.
*/
import { i18n } from '@kbn/i18n';
import { Plugin, CoreStart, CoreSetup, PluginInitializerContext } from 'kibana/public';
import { first } from 'rxjs/operators';
import { i18n } from '@kbn/i18n';
import { Plugin, CoreSetup } from 'src/core/public';
import { FeatureCatalogueCategory } from '../../../../src/plugins/home/public';
import { ILicense } from '../../licensing/common/types';
@ -20,9 +20,7 @@ const checkLicenseStatus = (license: ILicense) => {
};
export class SearchProfilerUIPlugin implements Plugin<void, void, AppPublicPluginDependencies> {
constructor(ctx: PluginInitializerContext) {}
async setup(
public setup(
{ http, getStartServices }: CoreSetup,
{ devTools, home, licensing }: AppPublicPluginDependencies
) {
@ -47,7 +45,7 @@ export class SearchProfilerUIPlugin implements Plugin<void, void, AppPublicPlugi
}),
order: 5,
enableRouting: false,
mount: async (ctx, params) => {
mount: async (params) => {
const [coreStart] = await getStartServices();
const { notifications, i18n: i18nDep } = coreStart;
const { boot } = await import('./application/boot');
@ -74,7 +72,7 @@ export class SearchProfilerUIPlugin implements Plugin<void, void, AppPublicPlugi
});
}
async start(core: CoreStart, plugins: any) {}
public start() {}
async stop() {}
public stop() {}
}