From 62d035390eb63234464e79b615e275dedc0e16f1 Mon Sep 17 00:00:00 2001 From: Joe Reuter Date: Thu, 14 Nov 2019 10:38:44 +0100 Subject: [PATCH] Shim dev tools (#49349) --- src/legacy/core_plugins/console/index.ts | 3 - .../application/containers/main/main.tsx | 4 +- .../console/np_ready/public/legacy.ts | 69 +------ .../console/np_ready/public/plugin.ts | 43 +++- .../console/public/quarantined/index.html | 3 - src/legacy/core_plugins/kibana/index.js | 2 +- .../kibana/public/dev_tools/_index.scss | 3 + .../kibana/public/dev_tools/application.tsx | 184 ++++++++++++++++++ .../dev_tools/directives/dev_tools_app.js | 50 ----- .../hacks/__tests__/hide_empty_tools.js | 59 ------ .../dev_tools/hacks/hide_empty_tools.js | 33 ---- .../kibana/public/dev_tools/index.js | 77 -------- .../public/dev_tools/index.ts} | 24 ++- .../dev_tools/partials/dev_tools_app.html | 22 --- .../kibana/public/dev_tools/plugin.ts | 71 +++++++ .../core_plugins/kibana/public/kibana.js | 1 - src/legacy/plugin_discovery/types.ts | 1 - .../new_platform/new_platform.karma_mock.js | 6 + .../ui/public/new_platform/new_platform.ts | 3 + src/plugins/dev_tools/README.md | 29 +++ src/plugins/dev_tools/kibana.json | 6 + .../dev_tools/public/index.ts} | 12 +- src/plugins/dev_tools/public/plugin.ts | 115 +++++++++++ x-pack/legacy/plugins/grokdebugger/index.js | 3 +- .../custom_patterns_input.js | 2 +- .../components/custom_patterns_input/index.js | 0 .../components/event_input/event_input.js | 2 +- .../components/event_input/index.js | 0 .../components/event_output/event_output.js | 0 .../components/event_output/index.js | 0 .../components/grok_debugger/grok_debugger.js | 2 +- .../components/grok_debugger/index.js | 0 .../components/pattern_input/index.js | 0 .../components/pattern_input/pattern_input.js | 4 +- .../plugins/grokdebugger/public/register.js | 33 ++++ .../plugins/grokdebugger/public/render_app.js | 22 +++ .../directives/grokdebugger/grokdebugger.js | 25 --- .../directives/grokdebugger/index.js | 7 - .../grokdebugger/grokdebugger_route.html | 3 - .../grokdebugger/grokdebugger_route.js | 40 ---- .../public/sections/grokdebugger/index.js | 7 - .../public/sections/grokdebugger/register.js | 22 --- .../grokdebugger_service.factory.js | 14 -- .../grokdebugger/grokdebugger_service.js | 11 +- .../public/services/grokdebugger/index.js | 7 - x-pack/legacy/plugins/searchprofiler/index.ts | 1 - .../plugins/searchprofiler/public/legacy.ts | 51 +---- .../searchprofiler/public/np_ready/plugin.ts | 21 +- .../plugins/searchprofiler/public/register.js | 20 -- .../translations/translations/ja-JP.json | 4 +- .../translations/translations/zh-CN.json | 4 +- .../feature_controls/dev_tools_security.ts | 4 +- .../feature_controls/dev_tools_spaces.ts | 2 +- 53 files changed, 581 insertions(+), 550 deletions(-) delete mode 100644 src/legacy/core_plugins/console/public/quarantined/index.html create mode 100644 src/legacy/core_plugins/kibana/public/dev_tools/application.tsx delete mode 100644 src/legacy/core_plugins/kibana/public/dev_tools/directives/dev_tools_app.js delete mode 100644 src/legacy/core_plugins/kibana/public/dev_tools/hacks/__tests__/hide_empty_tools.js delete mode 100644 src/legacy/core_plugins/kibana/public/dev_tools/hacks/hide_empty_tools.js delete mode 100644 src/legacy/core_plugins/kibana/public/dev_tools/index.js rename src/legacy/core_plugins/{console/public/quarantined/hacks/register.js => kibana/public/dev_tools/index.ts} (68%) delete mode 100644 src/legacy/core_plugins/kibana/public/dev_tools/partials/dev_tools_app.html create mode 100644 src/legacy/core_plugins/kibana/public/dev_tools/plugin.ts create mode 100644 src/plugins/dev_tools/README.md create mode 100644 src/plugins/dev_tools/kibana.json rename src/{legacy/ui/public/registry/dev_tools.js => plugins/dev_tools/public/index.ts} (77%) create mode 100644 src/plugins/dev_tools/public/plugin.ts rename x-pack/legacy/plugins/grokdebugger/public/{sections/grokdebugger => }/components/custom_patterns_input/custom_patterns_input.js (96%) rename x-pack/legacy/plugins/grokdebugger/public/{sections/grokdebugger => }/components/custom_patterns_input/index.js (100%) rename x-pack/legacy/plugins/grokdebugger/public/{sections/grokdebugger => }/components/event_input/event_input.js (94%) rename x-pack/legacy/plugins/grokdebugger/public/{sections/grokdebugger => }/components/event_input/index.js (100%) rename x-pack/legacy/plugins/grokdebugger/public/{sections/grokdebugger => }/components/event_output/event_output.js (100%) rename x-pack/legacy/plugins/grokdebugger/public/{sections/grokdebugger => }/components/event_output/index.js (100%) rename x-pack/legacy/plugins/grokdebugger/public/{sections/grokdebugger => }/components/grok_debugger/grok_debugger.js (98%) rename x-pack/legacy/plugins/grokdebugger/public/{sections/grokdebugger => }/components/grok_debugger/index.js (100%) rename x-pack/legacy/plugins/grokdebugger/public/{sections/grokdebugger => }/components/pattern_input/index.js (100%) rename x-pack/legacy/plugins/grokdebugger/public/{sections/grokdebugger => }/components/pattern_input/pattern_input.js (91%) create mode 100644 x-pack/legacy/plugins/grokdebugger/public/register.js create mode 100644 x-pack/legacy/plugins/grokdebugger/public/render_app.js delete mode 100644 x-pack/legacy/plugins/grokdebugger/public/sections/grokdebugger/directives/grokdebugger/grokdebugger.js delete mode 100644 x-pack/legacy/plugins/grokdebugger/public/sections/grokdebugger/directives/grokdebugger/index.js delete mode 100644 x-pack/legacy/plugins/grokdebugger/public/sections/grokdebugger/grokdebugger_route.html delete mode 100644 x-pack/legacy/plugins/grokdebugger/public/sections/grokdebugger/grokdebugger_route.js delete mode 100644 x-pack/legacy/plugins/grokdebugger/public/sections/grokdebugger/index.js delete mode 100644 x-pack/legacy/plugins/grokdebugger/public/sections/grokdebugger/register.js delete mode 100644 x-pack/legacy/plugins/grokdebugger/public/services/grokdebugger/grokdebugger_service.factory.js delete mode 100644 x-pack/legacy/plugins/grokdebugger/public/services/grokdebugger/index.js delete mode 100644 x-pack/legacy/plugins/searchprofiler/public/register.js diff --git a/src/legacy/core_plugins/console/index.ts b/src/legacy/core_plugins/console/index.ts index 30a85f4e7d342b..caef3ff6f99f38 100644 --- a/src/legacy/core_plugins/console/index.ts +++ b/src/legacy/core_plugins/console/index.ts @@ -56,7 +56,6 @@ export default function(kibana: any) { const npSrc = resolve(__dirname, 'np_ready/public'); let defaultVars: any; - const apps: any[] = []; return new kibana.Plugin({ id: 'console', require: ['elasticsearch'], @@ -181,8 +180,6 @@ export default function(kibana: any) { }, uiExports: { - apps, - hacks: ['plugins/console/quarantined/hacks/register'], devTools: [`${npSrc}/legacy`], styleSheetPaths: resolve(__dirname, 'public/quarantined/index.scss'), diff --git a/src/legacy/core_plugins/console/np_ready/public/application/containers/main/main.tsx b/src/legacy/core_plugins/console/np_ready/public/application/containers/main/main.tsx index 4e5afbdb5821e9..518630c5a07c1c 100644 --- a/src/legacy/core_plugins/console/np_ready/public/application/containers/main/main.tsx +++ b/src/legacy/core_plugins/console/np_ready/public/application/containers/main/main.tsx @@ -70,7 +70,7 @@ export function Main() { }; return ( - <> +
setShowSettings(false)} /> : null} {showHelp ? setShowHelp(false)} /> : null} - +
); } diff --git a/src/legacy/core_plugins/console/np_ready/public/legacy.ts b/src/legacy/core_plugins/console/np_ready/public/legacy.ts index 1a2d312823f6f2..8c60ff23648be3 100644 --- a/src/legacy/core_plugins/console/np_ready/public/legacy.ts +++ b/src/legacy/core_plugins/console/np_ready/public/legacy.ts @@ -24,80 +24,31 @@ import 'brace/mode/json'; import 'brace/mode/text'; /* eslint-disable @kbn/eslint/no-restricted-paths */ -import { toastNotifications as notifications } from 'ui/notify'; import { npSetup, npStart } from 'ui/new_platform'; -import uiRoutes from 'ui/routes'; -import { DOC_LINK_VERSION } from 'ui/documentation_links'; import { I18nContext } from 'ui/i18n'; import { ResizeChecker } from 'ui/resize_checker'; -import 'ui/capabilities/route_setup'; /* eslint-enable @kbn/eslint/no-restricted-paths */ -import template from '../../public/quarantined/index.html'; -import { App, AppUnmount, NotificationsSetup } from '../../../../../core/public'; - export interface XPluginSet { + devTools: DevToolsSetup; + feature_catalogue: FeatureCatalogueSetup; __LEGACY: { I18nContext: any; ResizeChecker: any; - docLinkVersion: string; }; } import { plugin } from '.'; +import { DevToolsSetup } from '../../../../../plugins/dev_tools/public'; +import { FeatureCatalogueSetup } from '../../../../../plugins/feature_catalogue/public'; const pluginInstance = plugin({} as any); -const anyObject = {} as any; - -uiRoutes.when('/dev_tools/console', { - requireUICapability: 'dev_tools.show', - controller: function RootController($scope) { - // Stub out this config for now... - $scope.topNavMenu = []; - - $scope.initReactApp = () => { - const targetElement = document.querySelector('#consoleRoot'); - if (!targetElement) { - const message = `Could not mount Console App!`; - npSetup.core.fatalErrors.add(message); - throw new Error(message); - } - - let unmount: AppUnmount | Promise; - - const mockedSetupCore = { - ...npSetup.core, - notifications: (notifications as unknown) as NotificationsSetup, - application: { - register(app: App): void { - try { - unmount = app.mount(anyObject, { element: targetElement, appBasePath: '' }); - } catch (e) { - npSetup.core.fatalErrors.add(e); - } - }, - registerMountContext() {}, - }, - }; - - pluginInstance.setup(mockedSetupCore, { - ...npSetup.plugins, - __LEGACY: { - I18nContext, - ResizeChecker, - docLinkVersion: DOC_LINK_VERSION, - }, - }); - pluginInstance.start(npStart.core); - - $scope.$on('$destroy', async () => { - if (unmount) { - const fn = await unmount; - fn(); - } - }); - }; +pluginInstance.setup(npSetup.core, { + ...npSetup.plugins, + __LEGACY: { + I18nContext, + ResizeChecker, }, - template, }); +pluginInstance.start(npStart.core); diff --git a/src/legacy/core_plugins/console/np_ready/public/plugin.ts b/src/legacy/core_plugins/console/np_ready/public/plugin.ts index 188a738d597944..f02b0b5e729992 100644 --- a/src/legacy/core_plugins/console/np_ready/public/plugin.ts +++ b/src/legacy/core_plugins/console/np_ready/public/plugin.ts @@ -18,26 +18,55 @@ */ import { render, unmountComponentAtNode } from 'react-dom'; +import { i18n } from '@kbn/i18n'; +import { FeatureCatalogueCategory } from 'ui/registry/feature_catalogue'; import { PluginInitializerContext, Plugin, CoreStart, CoreSetup } from '../../../../../core/public'; import { XPluginSet } from './legacy'; -import { boot } from './application'; export class ConsoleUIPlugin implements Plugin { // @ts-ignore constructor(private readonly ctx: PluginInitializerContext) {} - async setup({ application, notifications }: CoreSetup, pluginSet: XPluginSet) { + async setup({ notifications }: CoreSetup, pluginSet: XPluginSet) { const { - __LEGACY: { docLinkVersion, I18nContext, ResizeChecker }, + __LEGACY: { I18nContext, ResizeChecker }, + devTools, + feature_catalogue, } = pluginSet; - application.register({ + feature_catalogue.register({ + id: 'console', + title: i18n.translate('console.devToolsTitle', { + defaultMessage: 'Console', + }), + description: i18n.translate('console.devToolsDescription', { + defaultMessage: 'Skip cURL and use this JSON interface to work with your data directly.', + }), + icon: 'consoleApp', + path: '/app/kibana#/dev_tools/console', + showOnHomePage: true, + category: FeatureCatalogueCategory.ADMIN, + }); + + devTools.register({ id: 'console', order: 1, - title: 'Console', - mount(ctx, { element }) { - render(boot({ docLinkVersion, I18nContext, ResizeChecker, notifications }), element); + title: i18n.translate('console.consoleDisplayName', { + defaultMessage: 'Console', + }), + enableRouting: false, + async mount(ctx, { element }) { + const { boot } = await import('./application'); + render( + boot({ + docLinkVersion: ctx.core.docLinks.DOC_LINK_VERSION, + I18nContext, + ResizeChecker, + notifications, + }), + element + ); return () => { unmountComponentAtNode(element); }; diff --git a/src/legacy/core_plugins/console/public/quarantined/index.html b/src/legacy/core_plugins/console/public/quarantined/index.html deleted file mode 100644 index 66a693d4b2af78..00000000000000 --- a/src/legacy/core_plugins/console/public/quarantined/index.html +++ /dev/null @@ -1,3 +0,0 @@ - -
-
diff --git a/src/legacy/core_plugins/kibana/index.js b/src/legacy/core_plugins/kibana/index.js index 24cd4369123956..c7cda8aec0165d 100644 --- a/src/legacy/core_plugins/kibana/index.js +++ b/src/legacy/core_plugins/kibana/index.js @@ -62,7 +62,7 @@ export default function (kibana) { uiExports: { hacks: [ - 'plugins/kibana/dev_tools/hacks/hide_empty_tools', + 'plugins/kibana/dev_tools', ], fieldFormats: ['plugins/kibana/field_formats/register'], savedObjectTypes: [ diff --git a/src/legacy/core_plugins/kibana/public/dev_tools/_index.scss b/src/legacy/core_plugins/kibana/public/dev_tools/_index.scss index 563b140fd2eade..2e88d2e1285e3c 100644 --- a/src/legacy/core_plugins/kibana/public/dev_tools/_index.scss +++ b/src/legacy/core_plugins/kibana/public/dev_tools/_index.scss @@ -16,3 +16,6 @@ } } +.devApp { + height: 100%; +} diff --git a/src/legacy/core_plugins/kibana/public/dev_tools/application.tsx b/src/legacy/core_plugins/kibana/public/dev_tools/application.tsx new file mode 100644 index 00000000000000..3945d8d8dc8568 --- /dev/null +++ b/src/legacy/core_plugins/kibana/public/dev_tools/application.tsx @@ -0,0 +1,184 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +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 } from 'kibana/public'; +import { DevTool } from '../../../../../plugins/dev_tools/public'; + +interface DevToolsWrapperProps { + devTools: readonly DevTool[]; + activeDevTool: DevTool; + appMountContext: AppMountContext; + updateRoute: (newRoute: string) => void; +} + +interface MountedDevToolDescriptor { + devTool: DevTool; + mountpoint: HTMLElement; + unmountHandler: () => void; +} + +function DevToolsWrapper({ + devTools, + activeDevTool, + appMountContext, + updateRoute, +}: DevToolsWrapperProps) { + const mountedTool = useRef(null); + + useEffect( + () => () => { + if (mountedTool.current) { + mountedTool.current.unmountHandler(); + } + }, + [] + ); + + return ( +
+ + {devTools.map(currentDevTool => ( + + { + if (!currentDevTool.disabled) { + updateRoute(`/dev_tools/${currentDevTool.id}`); + } + }} + > + {currentDevTool.title} + + + ))} + +
{ + if ( + element && + (mountedTool.current === null || + mountedTool.current.devTool !== activeDevTool || + mountedTool.current.mountpoint !== element) + ) { + if (mountedTool.current) { + mountedTool.current.unmountHandler(); + } + const unmountHandler = await activeDevTool.mount(appMountContext, { + element, + appBasePath: '', + }); + mountedTool.current = { + devTool: activeDevTool, + mountpoint: element, + unmountHandler, + }; + } + }} + /> +
+ ); +} + +function redirectOnMissingCapabilities(appMountContext: AppMountContext) { + if (!appMountContext.core.application.capabilities.dev_tools.show) { + window.location.hash = '/home'; + return true; + } + return false; +} + +function setBadge(appMountContext: AppMountContext) { + if (appMountContext.core.application.capabilities.dev_tools.save) { + return; + } + appMountContext.core.chrome.setBadge({ + text: i18n.translate('kbn.devTools.badge.readOnly.text', { + defaultMessage: 'Read only', + }), + tooltip: i18n.translate('kbn.devTools.badge.readOnly.tooltip', { + defaultMessage: 'Unable to save', + }), + iconType: 'glasses', + }); +} + +function setBreadcrumbs(appMountContext: AppMountContext) { + appMountContext.core.chrome.setBreadcrumbs([ + { + text: i18n.translate('kbn.devTools.k7BreadcrumbsDevToolsLabel', { + defaultMessage: 'Dev Tools', + }), + href: '#/dev_tools', + }, + ]); +} + +export function renderApp( + element: HTMLElement, + appMountContext: AppMountContext, + basePath: string, + devTools: readonly DevTool[] +) { + if (redirectOnMissingCapabilities(appMountContext)) { + return () => {}; + } + setBadge(appMountContext); + setBreadcrumbs(appMountContext); + ReactDOM.render( + + + + {devTools.map(devTool => ( + ( + + )} + /> + ))} + + + + + + , + element + ); + + return () => ReactDOM.unmountComponentAtNode(element); +} diff --git a/src/legacy/core_plugins/kibana/public/dev_tools/directives/dev_tools_app.js b/src/legacy/core_plugins/kibana/public/dev_tools/directives/dev_tools_app.js deleted file mode 100644 index c7cb877be676b1..00000000000000 --- a/src/legacy/core_plugins/kibana/public/dev_tools/directives/dev_tools_app.js +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { uiModules } from 'ui/modules'; -import { DevToolsRegistryProvider } from 'ui/registry/dev_tools'; -import template from '../partials/dev_tools_app.html'; - -uiModules - .get('apps/dev_tools') - .directive('kbnDevToolsApp', function (Private, $location) { - const devToolsRegistry = Private(DevToolsRegistryProvider); - - return { - restrict: 'E', - replace: true, - template, - transclude: true, - scope: { - topNavConfig: '=' - }, - bindToController: true, - controllerAs: 'kbnDevToolsApp', - controller() { - this.devTools = devToolsRegistry.inOrder; - this.currentPath = `#${$location.path()}`; - - this.onClick = (item, $event) => { - if (item.disabled) { - $event.preventDefault(); - } - }; - } - }; - }); diff --git a/src/legacy/core_plugins/kibana/public/dev_tools/hacks/__tests__/hide_empty_tools.js b/src/legacy/core_plugins/kibana/public/dev_tools/hacks/__tests__/hide_empty_tools.js deleted file mode 100644 index 25c7b945b9dfb4..00000000000000 --- a/src/legacy/core_plugins/kibana/public/dev_tools/hacks/__tests__/hide_empty_tools.js +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import expect from '@kbn/expect'; -import sinon from 'sinon'; - -import { hideEmptyDevTools } from '../hide_empty_tools'; -import { npStart } from 'ui/new_platform'; - -describe('hide dev tools', function () { - let updateNavLink; - - function PrivateWithoutTools() { - return []; - } - - function PrivateWithTools() { - return ['tool1', 'tool2']; - } - - function isHidden() { - return updateNavLink.calledWith('kibana:dev_tools', { hidden: true }); - } - - beforeEach(function () { - const coreNavLinks = npStart.core.chrome.navLinks; - updateNavLink = sinon.spy(coreNavLinks, 'update'); - }); - - it('should hide the app if there are no dev tools', function () { - hideEmptyDevTools(PrivateWithTools); - expect(isHidden()).to.be(false); - }); - - it('should not hide the app if there are tools', function () { - hideEmptyDevTools(PrivateWithoutTools); - expect(isHidden()).to.be(true); - }); - - afterEach(function () { - updateNavLink.restore(); - }); -}); diff --git a/src/legacy/core_plugins/kibana/public/dev_tools/hacks/hide_empty_tools.js b/src/legacy/core_plugins/kibana/public/dev_tools/hacks/hide_empty_tools.js deleted file mode 100644 index 4dc55194562e5a..00000000000000 --- a/src/legacy/core_plugins/kibana/public/dev_tools/hacks/hide_empty_tools.js +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { uiModules } from 'ui/modules'; -import { DevToolsRegistryProvider } from 'ui/registry/dev_tools'; -import { npStart } from 'ui/new_platform'; - -export function hideEmptyDevTools(Private) { - const hasTools = !!Private(DevToolsRegistryProvider).length; - if (!hasTools) { - npStart.core.chrome.navLinks.update('kibana:dev_tools', { - hidden: true - }); - } -} - -uiModules.get('kibana').run(hideEmptyDevTools); diff --git a/src/legacy/core_plugins/kibana/public/dev_tools/index.js b/src/legacy/core_plugins/kibana/public/dev_tools/index.js deleted file mode 100644 index e36e75f6837ab8..00000000000000 --- a/src/legacy/core_plugins/kibana/public/dev_tools/index.js +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import uiRoutes from 'ui/routes'; -import { i18n } from '@kbn/i18n'; -import { DevToolsRegistryProvider } from 'ui/registry/dev_tools'; -import { FeatureCatalogueRegistryProvider, FeatureCatalogueCategory } from 'ui/registry/feature_catalogue'; -import 'ui/directives/kbn_href'; -import './directives/dev_tools_app'; - -uiRoutes - .when('/dev_tools', { - resolve: { - redirect(Private, kbnUrl) { - const items = Private(DevToolsRegistryProvider).inOrder; - kbnUrl.redirect(items[0].url.substring(1)); - } - } - }); - -uiRoutes.defaults(/^\/dev_tools(\/|$)/, { - badge: uiCapabilities => { - if (uiCapabilities.dev_tools.save) { - return undefined; - } - - return { - text: i18n.translate('kbn.devTools.badge.readOnly.text', { - defaultMessage: 'Read only', - }), - tooltip: i18n.translate('kbn.devTools.badge.readOnly.tooltip', { - defaultMessage: 'Unable to save', - }), - iconType: 'glasses' - }; - }, - k7Breadcrumbs: () => [ - { - text: i18n.translate('kbn.devTools.k7BreadcrumbsDevToolsLabel', { - defaultMessage: 'Dev Tools' - }), - href: '#/dev_tools' - } - ] -}); - -FeatureCatalogueRegistryProvider.register(() => { - return { - id: 'console', - title: i18n.translate('kbn.devTools.consoleTitle', { - defaultMessage: 'Console' - }), - description: i18n.translate('kbn.devTools.consoleDescription', { - defaultMessage: 'Skip cURL and use this JSON interface to work with your data directly.' - }), - icon: 'consoleApp', - path: '/app/kibana#/dev_tools/console', - showOnHomePage: true, - category: FeatureCatalogueCategory.ADMIN - }; -}); diff --git a/src/legacy/core_plugins/console/public/quarantined/hacks/register.js b/src/legacy/core_plugins/kibana/public/dev_tools/index.ts similarity index 68% rename from src/legacy/core_plugins/console/public/quarantined/hacks/register.js rename to src/legacy/core_plugins/kibana/public/dev_tools/index.ts index b5df1c1af99c5b..74708e36a98aac 100644 --- a/src/legacy/core_plugins/console/public/quarantined/hacks/register.js +++ b/src/legacy/core_plugins/kibana/public/dev_tools/index.ts @@ -17,14 +17,18 @@ * under the License. */ -import { DevToolsRegistryProvider } from 'ui/registry/dev_tools'; -import { i18n } from '@kbn/i18n'; +import { npSetup, npStart } from 'ui/new_platform'; -DevToolsRegistryProvider.register(() => ({ - order: 1, - name: 'console', - display: i18n.translate('console.consoleDisplayName', { - defaultMessage: 'Console', - }), - url: '#/dev_tools/console', -})); +import { DevToolsPlugin } from './plugin'; +import { localApplicationService } from '../local_application_service'; + +const instance = new DevToolsPlugin(); + +instance.setup(npSetup.core, { + __LEGACY: { + localApplicationService, + }, +}); +instance.start(npStart.core, { + newPlatformDevTools: npStart.plugins.devTools, +}); diff --git a/src/legacy/core_plugins/kibana/public/dev_tools/partials/dev_tools_app.html b/src/legacy/core_plugins/kibana/public/dev_tools/partials/dev_tools_app.html deleted file mode 100644 index 6c076092c76d5d..00000000000000 --- a/src/legacy/core_plugins/kibana/public/dev_tools/partials/dev_tools_app.html +++ /dev/null @@ -1,22 +0,0 @@ -
- - -
-
diff --git a/src/legacy/core_plugins/kibana/public/dev_tools/plugin.ts b/src/legacy/core_plugins/kibana/public/dev_tools/plugin.ts new file mode 100644 index 00000000000000..ec9af1a6acd929 --- /dev/null +++ b/src/legacy/core_plugins/kibana/public/dev_tools/plugin.ts @@ -0,0 +1,71 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +// This import makes sure dev tools are registered before the app is. +import 'uiExports/devTools'; + +import { CoreSetup, CoreStart, Plugin } from 'kibana/public'; + +import { LocalApplicationService } from '../local_application_service'; +import { DevTool, DevToolsStart } from '../../../../../plugins/dev_tools/public'; + +export interface DevToolsPluginSetupDependencies { + __LEGACY: { + localApplicationService: LocalApplicationService; + }; +} + +export interface DevToolsPluginStartDependencies { + newPlatformDevTools: DevToolsStart; +} + +export class DevToolsPlugin implements Plugin { + private getSortedDevTools: (() => readonly DevTool[]) | null = null; + + public setup( + core: CoreSetup, + { __LEGACY: { localApplicationService } }: DevToolsPluginSetupDependencies + ) { + localApplicationService.register({ + id: 'dev_tools', + title: 'Dev Tools', + mount: async (appMountContext, params) => { + if (!this.getSortedDevTools) { + throw new Error('not started yet'); + } + const { renderApp } = await import('./application'); + return renderApp( + params.element, + appMountContext, + params.appBasePath, + this.getSortedDevTools() + ); + }, + }); + } + + public start(core: CoreStart, { newPlatformDevTools }: DevToolsPluginStartDependencies) { + this.getSortedDevTools = newPlatformDevTools.getSortedDevTools; + if (this.getSortedDevTools().length === 0) { + core.chrome.navLinks.update('kibana:dev_tools', { + hidden: true, + }); + } + } +} diff --git a/src/legacy/core_plugins/kibana/public/kibana.js b/src/legacy/core_plugins/kibana/public/kibana.js index fe741a357cbfe7..c5b9d86b57aaea 100644 --- a/src/legacy/core_plugins/kibana/public/kibana.js +++ b/src/legacy/core_plugins/kibana/public/kibana.js @@ -37,7 +37,6 @@ import 'uiExports/navbarExtensions'; import 'uiExports/contextMenuActions'; import 'uiExports/managementSections'; import 'uiExports/indexManagement'; -import 'uiExports/devTools'; import 'uiExports/docViews'; import 'uiExports/embeddableFactories'; import 'uiExports/embeddableActions'; diff --git a/src/legacy/plugin_discovery/types.ts b/src/legacy/plugin_discovery/types.ts index c14daa37f57060..dfd36f2aa7b2b2 100644 --- a/src/legacy/plugin_discovery/types.ts +++ b/src/legacy/plugin_discovery/types.ts @@ -62,7 +62,6 @@ export interface LegacyPluginOptions { }>; apps: any; hacks: string[]; - devTools: string[]; styleSheetPaths: string; injectDefaultVars: (server: Server) => Record; noParse: string[]; diff --git a/src/legacy/ui/public/new_platform/new_platform.karma_mock.js b/src/legacy/ui/public/new_platform/new_platform.karma_mock.js index bb055d6ce1e334..e62ceeb2f31027 100644 --- a/src/legacy/ui/public/new_platform/new_platform.karma_mock.js +++ b/src/legacy/ui/public/new_platform/new_platform.karma_mock.js @@ -62,6 +62,9 @@ export const npSetup = { } }, }, + devTools: { + register: () => {}, + }, inspector: { registerView: () => undefined, __LEGACY: { @@ -97,6 +100,9 @@ export const npStart = { registerRenderer: sinon.fake(), registerType: sinon.fake(), }, + devTools: { + getSortedDevTools: () => [], + }, data: { autocomplete: { getProvider: sinon.fake(), diff --git a/src/legacy/ui/public/new_platform/new_platform.ts b/src/legacy/ui/public/new_platform/new_platform.ts index 0c7b28e7da3df2..9ee5d8580a90b9 100644 --- a/src/legacy/ui/public/new_platform/new_platform.ts +++ b/src/legacy/ui/public/new_platform/new_platform.ts @@ -28,6 +28,7 @@ import { Start as InspectorStart, } from '../../../../plugins/inspector/public'; import { EuiUtilsStart } from '../../../../plugins/eui_utils/public'; +import { DevToolsSetup, DevToolsStart } from '../../../../plugins/dev_tools/public'; import { FeatureCatalogueSetup, FeatureCatalogueStart, @@ -40,6 +41,7 @@ export interface PluginsSetup { feature_catalogue: FeatureCatalogueSetup; inspector: InspectorSetup; uiActions: IUiActionsSetup; + devTools: DevToolsSetup; } export interface PluginsStart { @@ -50,6 +52,7 @@ export interface PluginsStart { feature_catalogue: FeatureCatalogueStart; inspector: InspectorStart; uiActions: IUiActionsStart; + devTools: DevToolsStart; } export const npSetup = { diff --git a/src/plugins/dev_tools/README.md b/src/plugins/dev_tools/README.md new file mode 100644 index 00000000000000..1610411b9c98e0 --- /dev/null +++ b/src/plugins/dev_tools/README.md @@ -0,0 +1,29 @@ +# Dev tools plugin + +The ui/registry/dev_tools is removed in favor of the `dev_tools` plugin which exposes a register method in the setup contract. +Registering app works mostly the same as registering apps in core.application.register. +Routing will be handled by the id of the dev tool - your dev tool will be mounted when the URL matches `/app/kibana#/dev_tools/`. +This API doesn't support angular, for registering angular dev tools, bootstrap a local module on mount into the given HTML element. + +During the migration this plugin exposes the registered dev tools in the start contract. This is necessary to keep the dev tools app +which is still living in the legacy platform working and will be removed once everything is moved over to the new platform. It should +not be used by other plugins. + +## Example registration + +```ts +// For legacy plugins +import { npSetup } from 'ui/new_platform'; +npSetup.plugins.dev_tools.register(/* same details here */); + +// For new plugins: first add 'dev_tools' to the list of `optionalPlugins` +// in your kibana.json file. Then access the plugin directly in `setup`: + +class MyPlugin { + setup(core, plugins) { + if (plugins.dev_tools) { + plugins.dev_tools.register(/* same details here. */); + } + } +} +``` diff --git a/src/plugins/dev_tools/kibana.json b/src/plugins/dev_tools/kibana.json new file mode 100644 index 00000000000000..307035c7ec6645 --- /dev/null +++ b/src/plugins/dev_tools/kibana.json @@ -0,0 +1,6 @@ +{ + "id": "devTools", + "version": "kibana", + "server": false, + "ui": true +} diff --git a/src/legacy/ui/public/registry/dev_tools.js b/src/plugins/dev_tools/public/index.ts similarity index 77% rename from src/legacy/ui/public/registry/dev_tools.js rename to src/plugins/dev_tools/public/index.ts index 1741f39f86375c..3a0d1455e2168f 100644 --- a/src/legacy/ui/public/registry/dev_tools.js +++ b/src/plugins/dev_tools/public/index.ts @@ -17,11 +17,11 @@ * under the License. */ -import { uiRegistry } from './_registry'; +import { PluginInitializerContext } from 'kibana/public'; +import { DevToolsPlugin } from './plugin'; -export const DevToolsRegistryProvider = uiRegistry({ - name: 'devTools', - index: ['name'], - order: ['order'] -}); +export function plugin(initializerContext: PluginInitializerContext) { + return new DevToolsPlugin(); +} +export * from './plugin'; diff --git a/src/plugins/dev_tools/public/plugin.ts b/src/plugins/dev_tools/public/plugin.ts new file mode 100644 index 00000000000000..8098308c0882bc --- /dev/null +++ b/src/plugins/dev_tools/public/plugin.ts @@ -0,0 +1,115 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { App, CoreSetup, Plugin } from 'kibana/public'; +import { sortBy } from 'lodash'; + +export interface DevToolsSetup { + /** + * Register a developer tool. It will be available + * in the dev tools app under a separate tab. + * + * Registering dev tools works almost similar to registering + * applications in the core application service, + * but they will be rendered with a frame containing tabs + * to switch between the tools. + * @param devTool The dev tools descriptor + */ + register: (devTool: DevTool) => void; +} + +export interface DevToolsStart { + /** + * Returns all registered dev tools in an ordered array. + * This function is only exposed because the dev tools app + * actually rendering the tool has to stay in the legacy platform + * for now. Once it is moved into this plugin, this function + * becomes an implementation detail. + * @deprecated + */ + getSortedDevTools: () => readonly DevTool[]; +} + +/** + * Descriptor for a dev tool. A dev tool works similar to an application + * registered in the core application service. + */ +export interface DevTool { + /** + * The id of the dev tools. This will become part of the URL path + * (`dev_tools/${devTool.id}`. It has to be unique among registered + * dev tools. + */ + id: string; + /** + * The human readable name of the dev tool. Should be internationalized. + * This will be used as a label in the tab above the actual tool. + */ + title: string; + mount: App['mount']; + /** + * Flag indicating to disable the tab of this dev tool. Navigating to a + * disabled dev tool will be treated as the navigation to an unknown route + * (redirect to the console). + */ + disabled?: boolean; + /** + * Optional tooltip content of the tab. + */ + tooltipContent?: string; + /** + * Flag indicating whether the dev tool will do routing within the `dev_tools/${devTool.id}/` + * prefix. If it is set to true, the dev tool is responsible to redirect + * the user when navigating to unknown URLs within the prefix. If set + * to false only the root URL of the dev tool will be recognized as valid. + */ + enableRouting: boolean; + /** + * Number used to order the tabs. + */ + order: number; +} + +export class DevToolsPlugin implements Plugin { + private readonly devTools = new Map(); + + private getSortedDevTools(): readonly DevTool[] { + return sortBy([...this.devTools.values()], 'order'); + } + + public setup(core: CoreSetup) { + return { + register: (devTool: DevTool) => { + if (this.devTools.has(devTool.id)) { + throw new Error( + `Dev tool with id [${devTool.id}] has already been registered. Use a unique id.` + ); + } + + this.devTools.set(devTool.id, devTool); + }, + }; + } + + public start() { + return { + getSortedDevTools: this.getSortedDevTools.bind(this), + }; + } +} diff --git a/x-pack/legacy/plugins/grokdebugger/index.js b/x-pack/legacy/plugins/grokdebugger/index.js index 337e913bb3e6fc..8dd0945743bf0d 100644 --- a/x-pack/legacy/plugins/grokdebugger/index.js +++ b/x-pack/legacy/plugins/grokdebugger/index.js @@ -20,8 +20,7 @@ export const grokdebugger = (kibana) => new kibana.Plugin({ }).default(); }, uiExports: { - devTools: ['plugins/grokdebugger/sections/grokdebugger'], - hacks: ['plugins/grokdebugger/sections/grokdebugger/register'], + devTools: ['plugins/grokdebugger/register'], home: ['plugins/grokdebugger/register_feature'], }, init: (server) => { diff --git a/x-pack/legacy/plugins/grokdebugger/public/sections/grokdebugger/components/custom_patterns_input/custom_patterns_input.js b/x-pack/legacy/plugins/grokdebugger/public/components/custom_patterns_input/custom_patterns_input.js similarity index 96% rename from x-pack/legacy/plugins/grokdebugger/public/sections/grokdebugger/components/custom_patterns_input/custom_patterns_input.js rename to x-pack/legacy/plugins/grokdebugger/public/components/custom_patterns_input/custom_patterns_input.js index 87df1976b7dc84..cc1d2bc53a9df6 100644 --- a/x-pack/legacy/plugins/grokdebugger/public/sections/grokdebugger/components/custom_patterns_input/custom_patterns_input.js +++ b/x-pack/legacy/plugins/grokdebugger/public/components/custom_patterns_input/custom_patterns_input.js @@ -14,7 +14,7 @@ import { EuiCodeEditor, EuiSpacer } from '@elastic/eui'; -import { EDITOR } from '../../../../../common/constants'; +import { EDITOR } from '../../../common/constants'; import { FormattedMessage } from '@kbn/i18n/react'; export function CustomPatternsInput({ value, onChange }) { diff --git a/x-pack/legacy/plugins/grokdebugger/public/sections/grokdebugger/components/custom_patterns_input/index.js b/x-pack/legacy/plugins/grokdebugger/public/components/custom_patterns_input/index.js similarity index 100% rename from x-pack/legacy/plugins/grokdebugger/public/sections/grokdebugger/components/custom_patterns_input/index.js rename to x-pack/legacy/plugins/grokdebugger/public/components/custom_patterns_input/index.js diff --git a/x-pack/legacy/plugins/grokdebugger/public/sections/grokdebugger/components/event_input/event_input.js b/x-pack/legacy/plugins/grokdebugger/public/components/event_input/event_input.js similarity index 94% rename from x-pack/legacy/plugins/grokdebugger/public/sections/grokdebugger/components/event_input/event_input.js rename to x-pack/legacy/plugins/grokdebugger/public/components/event_input/event_input.js index 00ee2dbd9074c0..19335a88e9b877 100644 --- a/x-pack/legacy/plugins/grokdebugger/public/sections/grokdebugger/components/event_input/event_input.js +++ b/x-pack/legacy/plugins/grokdebugger/public/components/event_input/event_input.js @@ -10,7 +10,7 @@ import { EuiPanel, EuiCodeEditor } from '@elastic/eui'; -import { EDITOR } from '../../../../../common/constants'; +import { EDITOR } from '../../../common/constants'; import { FormattedMessage } from '@kbn/i18n/react'; export function EventInput({ value, onChange }) { diff --git a/x-pack/legacy/plugins/grokdebugger/public/sections/grokdebugger/components/event_input/index.js b/x-pack/legacy/plugins/grokdebugger/public/components/event_input/index.js similarity index 100% rename from x-pack/legacy/plugins/grokdebugger/public/sections/grokdebugger/components/event_input/index.js rename to x-pack/legacy/plugins/grokdebugger/public/components/event_input/index.js diff --git a/x-pack/legacy/plugins/grokdebugger/public/sections/grokdebugger/components/event_output/event_output.js b/x-pack/legacy/plugins/grokdebugger/public/components/event_output/event_output.js similarity index 100% rename from x-pack/legacy/plugins/grokdebugger/public/sections/grokdebugger/components/event_output/event_output.js rename to x-pack/legacy/plugins/grokdebugger/public/components/event_output/event_output.js diff --git a/x-pack/legacy/plugins/grokdebugger/public/sections/grokdebugger/components/event_output/index.js b/x-pack/legacy/plugins/grokdebugger/public/components/event_output/index.js similarity index 100% rename from x-pack/legacy/plugins/grokdebugger/public/sections/grokdebugger/components/event_output/index.js rename to x-pack/legacy/plugins/grokdebugger/public/components/event_output/index.js diff --git a/x-pack/legacy/plugins/grokdebugger/public/sections/grokdebugger/components/grok_debugger/grok_debugger.js b/x-pack/legacy/plugins/grokdebugger/public/components/grok_debugger/grok_debugger.js similarity index 98% rename from x-pack/legacy/plugins/grokdebugger/public/sections/grokdebugger/components/grok_debugger/grok_debugger.js rename to x-pack/legacy/plugins/grokdebugger/public/components/grok_debugger/grok_debugger.js index eaf66b2b1a0442..2a9fa499f37ea9 100644 --- a/x-pack/legacy/plugins/grokdebugger/public/sections/grokdebugger/components/grok_debugger/grok_debugger.js +++ b/x-pack/legacy/plugins/grokdebugger/public/components/grok_debugger/grok_debugger.js @@ -18,7 +18,7 @@ import { EventInput } from '../event_input'; import { PatternInput } from '../pattern_input'; import { CustomPatternsInput } from '../custom_patterns_input'; import { EventOutput } from '../event_output'; -import { GrokdebuggerRequest } from '../../../../models/grokdebugger_request'; +import { GrokdebuggerRequest } from '../../models/grokdebugger_request'; import { toastNotifications } from 'ui/notify'; import { FormattedMessage } from '@kbn/i18n/react'; diff --git a/x-pack/legacy/plugins/grokdebugger/public/sections/grokdebugger/components/grok_debugger/index.js b/x-pack/legacy/plugins/grokdebugger/public/components/grok_debugger/index.js similarity index 100% rename from x-pack/legacy/plugins/grokdebugger/public/sections/grokdebugger/components/grok_debugger/index.js rename to x-pack/legacy/plugins/grokdebugger/public/components/grok_debugger/index.js diff --git a/x-pack/legacy/plugins/grokdebugger/public/sections/grokdebugger/components/pattern_input/index.js b/x-pack/legacy/plugins/grokdebugger/public/components/pattern_input/index.js similarity index 100% rename from x-pack/legacy/plugins/grokdebugger/public/sections/grokdebugger/components/pattern_input/index.js rename to x-pack/legacy/plugins/grokdebugger/public/components/pattern_input/index.js diff --git a/x-pack/legacy/plugins/grokdebugger/public/sections/grokdebugger/components/pattern_input/pattern_input.js b/x-pack/legacy/plugins/grokdebugger/public/components/pattern_input/pattern_input.js similarity index 91% rename from x-pack/legacy/plugins/grokdebugger/public/sections/grokdebugger/components/pattern_input/pattern_input.js rename to x-pack/legacy/plugins/grokdebugger/public/components/pattern_input/pattern_input.js index bb06da7183b9a0..09a6e100d9f88e 100644 --- a/x-pack/legacy/plugins/grokdebugger/public/sections/grokdebugger/components/pattern_input/pattern_input.js +++ b/x-pack/legacy/plugins/grokdebugger/public/components/pattern_input/pattern_input.js @@ -10,8 +10,8 @@ import { EuiPanel, EuiCodeEditor } from '@elastic/eui'; -import { EDITOR } from '../../../../../common/constants'; -import { GrokMode } from '../../../../lib/ace'; +import { EDITOR } from '../../../common/constants'; +import { GrokMode } from '../../lib/ace'; import { FormattedMessage } from '@kbn/i18n/react'; export function PatternInput({ value, onChange }) { diff --git a/x-pack/legacy/plugins/grokdebugger/public/register.js b/x-pack/legacy/plugins/grokdebugger/public/register.js new file mode 100644 index 00000000000000..74679d65e52d2c --- /dev/null +++ b/x-pack/legacy/plugins/grokdebugger/public/register.js @@ -0,0 +1,33 @@ +/* + * 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. + */ + +import { i18n } from '@kbn/i18n'; +import { xpackInfo } from 'plugins/xpack_main/services/xpack_info'; +import { npSetup, npStart } from 'ui/new_platform'; + +npSetup.plugins.devTools.register({ + order: 6, + title: i18n.translate('xpack.grokDebugger.displayName', { + defaultMessage: 'Grok Debugger', + }), + id: 'grokdebugger', + enableRouting: false, + disabled: !xpackInfo.get('features.grokdebugger.enableLink', false), + tooltipContent: xpackInfo.get('features.grokdebugger.message'), + async mount(context, { element }) { + const licenseCheck = { + showPage: xpackInfo.get('features.grokdebugger.enableLink'), + message: xpackInfo.get('features.grokdebugger.message'), + }; + if (!licenseCheck.showPage) { + npStart.core.notifications.toasts.addDanger(licenseCheck.message); + window.location.hash = '/dev_tools'; + return () => {}; + } + const { renderApp } = await import('./render_app'); + return renderApp(element, npStart); + }, +}); diff --git a/x-pack/legacy/plugins/grokdebugger/public/render_app.js b/x-pack/legacy/plugins/grokdebugger/public/render_app.js new file mode 100644 index 00000000000000..2c4894bb70ee1a --- /dev/null +++ b/x-pack/legacy/plugins/grokdebugger/public/render_app.js @@ -0,0 +1,22 @@ +/* + * 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. + */ + +import React from 'react'; +import { render, unmountComponentAtNode } from 'react-dom'; + +import { GrokDebugger } from './components/grok_debugger'; +import { GrokdebuggerService } from './services/grokdebugger/grokdebugger_service'; +import { I18nProvider } from '@kbn/i18n/react'; + +export function renderApp(element, npStart) { + render( + + + , + element + ); + return () => unmountComponentAtNode(element); +} diff --git a/x-pack/legacy/plugins/grokdebugger/public/sections/grokdebugger/directives/grokdebugger/grokdebugger.js b/x-pack/legacy/plugins/grokdebugger/public/sections/grokdebugger/directives/grokdebugger/grokdebugger.js deleted file mode 100644 index a07ba56057b4bc..00000000000000 --- a/x-pack/legacy/plugins/grokdebugger/public/sections/grokdebugger/directives/grokdebugger/grokdebugger.js +++ /dev/null @@ -1,25 +0,0 @@ -/* - * 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. - */ - -import { uiModules } from 'ui/modules'; -import 'plugins/grokdebugger/services/grokdebugger'; -import { GrokDebugger } from '../../components/grok_debugger'; -import { render } from 'react-dom'; -import React from 'react'; -import { I18nContext } from 'ui/i18n'; - -const app = uiModules.get('xpack/grokdebugger'); - -app.directive('grokdebugger', function ($injector) { - const grokdebuggerService = $injector.get('grokdebuggerService'); - - return { - restrict: 'E', - link: (scope, el) => { - render(, el[0]); - } - }; -}); diff --git a/x-pack/legacy/plugins/grokdebugger/public/sections/grokdebugger/directives/grokdebugger/index.js b/x-pack/legacy/plugins/grokdebugger/public/sections/grokdebugger/directives/grokdebugger/index.js deleted file mode 100644 index b33973ed71736d..00000000000000 --- a/x-pack/legacy/plugins/grokdebugger/public/sections/grokdebugger/directives/grokdebugger/index.js +++ /dev/null @@ -1,7 +0,0 @@ -/* - * 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. - */ - -import './grokdebugger'; diff --git a/x-pack/legacy/plugins/grokdebugger/public/sections/grokdebugger/grokdebugger_route.html b/x-pack/legacy/plugins/grokdebugger/public/sections/grokdebugger/grokdebugger_route.html deleted file mode 100644 index f1de4653ead0a9..00000000000000 --- a/x-pack/legacy/plugins/grokdebugger/public/sections/grokdebugger/grokdebugger_route.html +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/x-pack/legacy/plugins/grokdebugger/public/sections/grokdebugger/grokdebugger_route.js b/x-pack/legacy/plugins/grokdebugger/public/sections/grokdebugger/grokdebugger_route.js deleted file mode 100644 index 9f588bbe510ae1..00000000000000 --- a/x-pack/legacy/plugins/grokdebugger/public/sections/grokdebugger/grokdebugger_route.js +++ /dev/null @@ -1,40 +0,0 @@ -/* - * 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. - */ - -import routes from 'ui/routes'; -import 'ui/capabilities/route_setup'; -import { toastNotifications } from 'ui/notify'; -import { xpackInfo } from 'plugins/xpack_main/services/xpack_info'; -import template from './grokdebugger_route.html'; -import './directives/grokdebugger'; - - -routes - .when('/dev_tools/grokdebugger', { - template: template, - requireUICapability: 'dev_tools.show', - resolve: { - licenseCheckResults() { - return { - showPage: xpackInfo.get('features.grokdebugger.enableLink'), - message: xpackInfo.get('features.grokdebugger.message') - }; - } - }, - controller: class GrokDebuggerRouteController { - constructor($injector) { - const $route = $injector.get('$route'); - const kbnUrl = $injector.get('kbnUrl'); - - const licenseCheckResults = $route.current.locals.licenseCheckResults; - if (!licenseCheckResults.showPage) { - kbnUrl.change('/dev_tools'); - toastNotifications.addDanger(licenseCheckResults.message); - return; - } - } - } - }); diff --git a/x-pack/legacy/plugins/grokdebugger/public/sections/grokdebugger/index.js b/x-pack/legacy/plugins/grokdebugger/public/sections/grokdebugger/index.js deleted file mode 100644 index b9fb58f1f12c9c..00000000000000 --- a/x-pack/legacy/plugins/grokdebugger/public/sections/grokdebugger/index.js +++ /dev/null @@ -1,7 +0,0 @@ -/* - * 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. - */ - -import './grokdebugger_route'; diff --git a/x-pack/legacy/plugins/grokdebugger/public/sections/grokdebugger/register.js b/x-pack/legacy/plugins/grokdebugger/public/sections/grokdebugger/register.js deleted file mode 100644 index 0a2ea2644bf14b..00000000000000 --- a/x-pack/legacy/plugins/grokdebugger/public/sections/grokdebugger/register.js +++ /dev/null @@ -1,22 +0,0 @@ -/* - * 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. - */ - -import { DevToolsRegistryProvider } from 'ui/registry/dev_tools'; -import { i18n } from '@kbn/i18n'; -import { xpackInfo } from 'plugins/xpack_main/services/xpack_info'; - -DevToolsRegistryProvider.register(() => { - return { - order: 6, - name: 'grokdebugger', - display: i18n.translate('xpack.grokDebugger.displayName', { - defaultMessage: 'Grok Debugger', - }), - url: '#/dev_tools/grokdebugger', - disabled: !xpackInfo.get('features.grokdebugger.enableLink', false), - tooltipContent: xpackInfo.get('features.grokdebugger.message') - }; -}); diff --git a/x-pack/legacy/plugins/grokdebugger/public/services/grokdebugger/grokdebugger_service.factory.js b/x-pack/legacy/plugins/grokdebugger/public/services/grokdebugger/grokdebugger_service.factory.js deleted file mode 100644 index 17dc66d67e8722..00000000000000 --- a/x-pack/legacy/plugins/grokdebugger/public/services/grokdebugger/grokdebugger_service.factory.js +++ /dev/null @@ -1,14 +0,0 @@ -/* - * 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. - */ - -import { uiModules } from 'ui/modules'; -import { GrokdebuggerService } from './grokdebugger_service'; - -uiModules.get('xpack/grokdebugger') - .factory('grokdebuggerService', ($injector) => { - const $http = $injector.get('$http'); - return new GrokdebuggerService($http); - }); diff --git a/x-pack/legacy/plugins/grokdebugger/public/services/grokdebugger/grokdebugger_service.js b/x-pack/legacy/plugins/grokdebugger/public/services/grokdebugger/grokdebugger_service.js index 56041949c1ff8a..7a656b33d59ff3 100644 --- a/x-pack/legacy/plugins/grokdebugger/public/services/grokdebugger/grokdebugger_service.js +++ b/x-pack/legacy/plugins/grokdebugger/public/services/grokdebugger/grokdebugger_service.js @@ -9,18 +9,19 @@ import { ROUTES } from '../../../common/constants'; import { GrokdebuggerResponse } from 'plugins/grokdebugger/models/grokdebugger_response'; export class GrokdebuggerService { - constructor($http) { - this.$http = $http; + constructor(http) { + this.http = http; this.basePath = chrome.addBasePath(ROUTES.API_ROOT); } simulate(grokdebuggerRequest) { - return this.$http.post(`${this.basePath}/simulate`, grokdebuggerRequest.upstreamJSON) + return this.http + .post(`${this.basePath}/simulate`, { body: JSON.stringify(grokdebuggerRequest.upstreamJSON) }) .then(response => { - return GrokdebuggerResponse.fromUpstreamJSON(response.data.grokdebuggerResponse); + return GrokdebuggerResponse.fromUpstreamJSON(response.grokdebuggerResponse); }) .catch(e => { - throw e.data.message; + throw e.body.message; }); } } diff --git a/x-pack/legacy/plugins/grokdebugger/public/services/grokdebugger/index.js b/x-pack/legacy/plugins/grokdebugger/public/services/grokdebugger/index.js deleted file mode 100644 index 766ed7c8766aef..00000000000000 --- a/x-pack/legacy/plugins/grokdebugger/public/services/grokdebugger/index.js +++ /dev/null @@ -1,7 +0,0 @@ -/* - * 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. - */ - -import './grokdebugger_service.factory'; diff --git a/x-pack/legacy/plugins/searchprofiler/index.ts b/x-pack/legacy/plugins/searchprofiler/index.ts index 5de6ba710235bc..834f331cd7bf41 100644 --- a/x-pack/legacy/plugins/searchprofiler/index.ts +++ b/x-pack/legacy/plugins/searchprofiler/index.ts @@ -26,7 +26,6 @@ export const searchprofiler = (kibana: any) => { devTools: [`${publicSrc}/legacy`], styleSheetPaths: `${publicSrc}/np_ready/application/index.scss`, // Legacy - hacks: ['plugins/searchprofiler/register'], home: ['plugins/searchprofiler/register_feature'], }, init(server: Server) { diff --git a/x-pack/legacy/plugins/searchprofiler/public/legacy.ts b/x-pack/legacy/plugins/searchprofiler/public/legacy.ts index 61dabe8ac7b05c..b767705e025a00 100644 --- a/x-pack/legacy/plugins/searchprofiler/public/legacy.ts +++ b/x-pack/legacy/plugins/searchprofiler/public/legacy.ts @@ -7,59 +7,22 @@ /* eslint-disable @kbn/eslint/no-restricted-paths */ import { npSetup } from 'ui/new_platform'; import { I18nContext } from 'ui/i18n'; -import uiRoutes from 'ui/routes'; -import 'ui/capabilities/route_setup'; // @ts-ignore import { xpackInfo } from 'plugins/xpack_main/services/xpack_info'; // @ts-ignore import { formatAngularHttpError } from 'ui/notify/lib'; import 'ui/autoload/all'; -/* eslint-enable @kbn/eslint/no-restricted-paths */ -import { ApplicationSetup } from 'src/core/public'; import { plugin } from './np_ready'; const pluginInstance = plugin({} as any); -const template = ` -
-`; - -uiRoutes.when('/dev_tools/searchprofiler', { - template, - requireUICapability: 'dev_tools.show', - controller: $scope => { - $scope.startReactApp = () => { - const el = document.querySelector('#searchProfilerAppRoot'); - if (!el) { - const errorMessage = 'Could not mount Searchprofiler App!'; - npSetup.core.fatalErrors.add(errorMessage); - throw new Error(errorMessage); - } - - const coreApplicationSetupShim: ApplicationSetup = { - register(app: any) { - const unmount = app.mount(); - $scope.$on('$destroy', () => unmount()); - }, - registerMountContext: {} as any, - }; - - pluginInstance.setup( - { - ...npSetup.core, - application: coreApplicationSetupShim, - }, - { - __LEGACY: { - I18nContext, - licenseEnabled: xpackInfo.get('features.searchprofiler.enableAppLink'), - notifications: npSetup.core.notifications.toasts, - formatAngularHttpError, - el, - }, - } - ); - }; +pluginInstance.setup(npSetup.core, { + ...npSetup.plugins, + __LEGACY: { + I18nContext, + licenseEnabled: xpackInfo.get('features.searchprofiler.enableAppLink'), + notifications: npSetup.core.notifications.toasts, + formatAngularHttpError, }, }); diff --git a/x-pack/legacy/plugins/searchprofiler/public/np_ready/plugin.ts b/x-pack/legacy/plugins/searchprofiler/public/np_ready/plugin.ts index ff98e706abf5cd..7a5981fcb0a690 100644 --- a/x-pack/legacy/plugins/searchprofiler/public/np_ready/plugin.ts +++ b/x-pack/legacy/plugins/searchprofiler/public/np_ready/plugin.ts @@ -4,6 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ +import { i18n } from '@kbn/i18n'; import { Plugin, CoreStart, @@ -12,7 +13,7 @@ import { ToastsStart, } from 'src/core/public'; -import { boot } from './application/boot'; +import { DevToolsSetup } from '../../../../../../src/plugins/dev_tools/public'; export class SearchProfilerUIPlugin implements Plugin { constructor(ctx: PluginInitializerContext) {} @@ -25,22 +26,28 @@ export class SearchProfilerUIPlugin implements Plugin { licenseEnabled: boolean; notifications: ToastsStart; formatAngularHttpError: any; - el: HTMLElement; }; + devTools: DevToolsSetup; } ) { const { http } = core; const { - __LEGACY: { I18nContext, licenseEnabled, notifications, formatAngularHttpError, el }, + __LEGACY: { I18nContext, licenseEnabled, notifications, formatAngularHttpError }, + devTools, } = plugins; - core.application.register({ + devTools.register({ id: 'searchprofiler', - title: 'SearchProfiler', - mount(ctx, params) { + title: i18n.translate('xpack.searchProfiler.pageDisplayName', { + defaultMessage: 'Search Profiler', + }), + order: 5, + enableRouting: false, + async mount(ctx, params) { + const { boot } = await import('./application/boot'); return boot({ http, licenseEnabled, - el, + el: params.element, I18nContext, notifications, formatAngularHttpError, diff --git a/x-pack/legacy/plugins/searchprofiler/public/register.js b/x-pack/legacy/plugins/searchprofiler/public/register.js deleted file mode 100644 index 45da747801a4ba..00000000000000 --- a/x-pack/legacy/plugins/searchprofiler/public/register.js +++ /dev/null @@ -1,20 +0,0 @@ -/* - * 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. - */ - -import { DevToolsRegistryProvider } from 'ui/registry/dev_tools'; - -import { i18n } from '@kbn/i18n'; - -DevToolsRegistryProvider.register(() => ({ - order: 5, - name: 'searchprofiler', - - display: i18n.translate('xpack.searchProfiler.pageDisplayName', { - defaultMessage: 'Search Profiler', - }), - - url: '#/dev_tools/searchprofiler' -})); diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index f745c7b40d7033..34491036e5a453 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -712,6 +712,8 @@ "inspector.requests.statisticsTabLabel": "統計", "console.autocomplete.addMethodMetaText": "メソド", "console.consoleDisplayName": "コンソール", + "console.devToolsDescription": "cURL をスキップしこの JSON インスタンスを使って、データに直接アクセスします。", + "console.devToolsTitle": "コンソール", "console.helpPage.keyboardCommands.autoIndentDescription": "現在のリクエストを自動インデントします", "console.helpPage.keyboardCommands.closeAutoCompleteMenuDescription": "自動入力メニューを閉じます", "console.helpPage.keyboardCommands.collapseAllScopesDescription": "現在のスコープを除きすべてのスコープを最小表示します。シフトを追加して拡張します。", @@ -1490,8 +1492,6 @@ "kbn.dashboardTitle": "ダッシュボード", "kbn.devTools.badge.readOnly.text": "読み込み専用", "kbn.devTools.badge.readOnly.tooltip": "を保存できませんでした", - "kbn.devTools.consoleDescription": "cURL をスキップしこの JSON インスタンスを使って、データに直接アクセスします。", - "kbn.devTools.consoleTitle": "コンソール", "kbn.devTools.k7BreadcrumbsDevToolsLabel": "開発ツール", "kbn.devToolsTitle": "開発ツール", "kbn.discover.backToTopLinkText": "最上部へ戻る。", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 52b45200b7ff7f..df00be9685ccfe 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -713,6 +713,8 @@ "inspector.requests.statisticsTabLabel": "统计信息", "console.autocomplete.addMethodMetaText": "方法", "console.consoleDisplayName": "Console", + "console.devToolsDescription": "跳过 cURL 并使用此 JSON 接口来直接处理您的数据。", + "console.devToolsTitle": "Console", "console.helpPage.keyboardCommands.autoIndentDescription": "自动缩进当前请求", "console.helpPage.keyboardCommands.closeAutoCompleteMenuDescription": "关闭自动完成菜单", "console.helpPage.keyboardCommands.collapseAllScopesDescription": "折叠当前范围除外的所有范围。通过加按 Shift 键来展开。", @@ -1491,8 +1493,6 @@ "kbn.dashboardTitle": "仪表板", "kbn.devTools.badge.readOnly.text": "只读", "kbn.devTools.badge.readOnly.tooltip": "无法保存", - "kbn.devTools.consoleDescription": "跳过 cURL 并使用此 JSON 接口来直接处理您的数据。", - "kbn.devTools.consoleTitle": "Console", "kbn.devTools.k7BreadcrumbsDevToolsLabel": "开发工具", "kbn.devToolsTitle": "开发工具", "kbn.discover.backToTopLinkText": "返至顶部。", diff --git a/x-pack/test/functional/apps/dev_tools/feature_controls/dev_tools_security.ts b/x-pack/test/functional/apps/dev_tools/feature_controls/dev_tools_security.ts index 1a63a6ad3c9e44..95bcdb195e09ea 100644 --- a/x-pack/test/functional/apps/dev_tools/feature_controls/dev_tools_security.ts +++ b/x-pack/test/functional/apps/dev_tools/feature_controls/dev_tools_security.ts @@ -90,7 +90,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) { }); it(`can navigate to search profiler`, async () => { - await testSubjects.existOrFail('searchProfiler'); + await testSubjects.existOrFail('searchprofiler'); }); it(`doesn't show read-only badge`, async () => { @@ -173,7 +173,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) { }); it(`can navigate to search profiler`, async () => { - await testSubjects.existOrFail('searchProfiler'); + await testSubjects.existOrFail('searchprofiler'); }); it(`shows read-only badge`, async () => { diff --git a/x-pack/test/functional/apps/dev_tools/feature_controls/dev_tools_spaces.ts b/x-pack/test/functional/apps/dev_tools/feature_controls/dev_tools_spaces.ts index 666b9175da275f..1c052e0103e70d 100644 --- a/x-pack/test/functional/apps/dev_tools/feature_controls/dev_tools_spaces.ts +++ b/x-pack/test/functional/apps/dev_tools/feature_controls/dev_tools_spaces.ts @@ -54,7 +54,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) { it(`can navigate to search profiler`, async () => { await PageObjects.common.navigateToApp('searchProfiler'); - await testSubjects.existOrFail('searchProfiler'); + await testSubjects.existOrFail('searchprofiler'); }); it(`can navigate to grok debugger`, async () => {