[7.x] Move local application service into Kibana platform (#50661) (#51499)

* Move local application service into Kibana platform (#50661)

* move local application service registry to new platform

* move dev tools app itself

* fix i18n

* make sure legacy dev tools are imported

* rename dev tools plugin
This commit is contained in:
Matthias Wilhelm 2019-11-25 11:47:18 +01:00 committed by GitHub
parent b904c4e8a8
commit 60696a08b1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
28 changed files with 444 additions and 260 deletions

View file

@ -8,6 +8,7 @@
"embeddableApi": "src/plugins/embeddable",
"share": "src/plugins/share",
"esUi": "src/plugins/es_ui_shared",
"devTools": "src/plugins/dev_tools",
"expressions": "src/plugins/expressions",
"inputControl": "src/legacy/core_plugins/input_control_vis",
"inspector": "src/plugins/inspector",

View file

@ -29,7 +29,7 @@ import { I18nContext } from 'ui/i18n';
/* eslint-enable @kbn/eslint/no-restricted-paths */
export interface XPluginSet {
devTools: DevToolsSetup;
dev_tools: DevToolsSetup;
home: HomePublicPluginSetup;
__LEGACY: {
I18nContext: any;

View file

@ -31,7 +31,7 @@ export class ConsoleUIPlugin implements Plugin<any, any> {
async setup({ notifications }: CoreSetup, pluginSet: XPluginSet) {
const {
__LEGACY: { I18nContext },
devTools,
dev_tools,
home,
} = pluginSet;
@ -49,7 +49,7 @@ export class ConsoleUIPlugin implements Plugin<any, any> {
category: FeatureCatalogueCategory.ADMIN,
});
devTools.register({
dev_tools.register({
id: 'console',
order: 1,
title: i18n.translate('console.consoleDisplayName', {

View file

@ -26,7 +26,6 @@ import {
} from './legacy_imports';
import { DashboardPlugin, LegacyAngularInjectedDependencies } from './plugin';
import { start as data } from '../../../data/public/legacy';
import { localApplicationService } from '../local_application_service';
import { start as embeddables } from '../../../embeddable_api/public/np_ready/public/legacy';
import { start as navigation } from '../../../navigation/public/legacy';
import './saved_dashboard/saved_dashboards';
@ -55,7 +54,6 @@ async function getAngularDependencies(): Promise<LegacyAngularInjectedDependenci
instance.setup(npSetup.core, {
...npSetup.plugins,
__LEGACY: {
localApplicationService,
getAngularDependencies,
},
});

View file

@ -27,7 +27,6 @@ import {
} from 'kibana/public';
import { i18n } from '@kbn/i18n';
import { RenderDeps } from './application';
import { LocalApplicationService } from '../local_application_service';
import { DataStart } from '../../../data/public';
import { DataPublicPluginStart as NpDataStart } from '../../../../../plugins/data/public';
import { EmbeddablePublicPlugin } from '../../../../../plugins/embeddable/public';
@ -39,6 +38,7 @@ import {
HomePublicPluginSetup,
FeatureCatalogueCategory,
} from '../../../../../plugins/home/public';
import { KibanaLegacySetup } from '../../../../../plugins/kibana_legacy/public';
export interface LegacyAngularInjectedDependencies {
dashboardConfig: any;
@ -57,9 +57,9 @@ export interface DashboardPluginStartDependencies {
export interface DashboardPluginSetupDependencies {
__LEGACY: {
getAngularDependencies: () => Promise<LegacyAngularInjectedDependencies>;
localApplicationService: LocalApplicationService;
};
home: HomePublicPluginSetup;
kibana_legacy: KibanaLegacySetup;
}
export class DashboardPlugin implements Plugin {
@ -74,10 +74,7 @@ export class DashboardPlugin implements Plugin {
public setup(
core: CoreSetup,
{
__LEGACY: { localApplicationService, getAngularDependencies, ...legacyServices },
home,
}: DashboardPluginSetupDependencies
{ __LEGACY: { getAngularDependencies }, home, kibana_legacy }: DashboardPluginSetupDependencies
) {
const app: App = {
id: '',
@ -97,7 +94,6 @@ export class DashboardPlugin implements Plugin {
const angularDependencies = await getAngularDependencies();
const deps: RenderDeps = {
core: contextCore as LegacyCoreStart,
...legacyServices,
...angularDependencies,
navigation,
dataStart,
@ -117,8 +113,8 @@ export class DashboardPlugin implements Plugin {
return renderApp(params.element, params.appBasePath, deps);
},
};
localApplicationService.register({ ...app, id: 'dashboard' });
localApplicationService.register({ ...app, id: 'dashboards' });
kibana_legacy.registerLegacyApp({ ...app, id: 'dashboard' });
kibana_legacy.registerLegacyApp({ ...app, id: 'dashboards' });
home.featureCatalogue.register({
id: 'dashboard',

View file

@ -0,0 +1,151 @@
/*
* 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,
CoreStart,
LegacyCoreStart,
Plugin,
SavedObjectsClientContract,
} from 'kibana/public';
import { i18n } from '@kbn/i18n';
import { RenderDeps } from './application';
import { DataStart } from '../../../data/public';
import { DataPublicPluginStart as NpDataStart } from '../../../../../plugins/data/public';
import { EmbeddablePublicPlugin } from '../../../../../plugins/embeddable/public';
import { Storage } from '../../../../../plugins/kibana_utils/public';
import { NavigationStart } from '../../../navigation/public';
import { DashboardConstants } from './dashboard_constants';
import { SharePluginStart } from '../../../../../plugins/share/public';
import {
HomePublicPluginSetup,
FeatureCatalogueCategory,
} from '../../../../../plugins/home/public';
<<<<<<< HEAD
=======
import { SharePluginStart } from '../../../../../plugins/share/public';
import { KibanaLegacySetup } from '../../../../../plugins/kibana_legacy/public';
>>>>>>> 8af09faa72... Move local application service into Kibana platform (#50661)
export interface LegacyAngularInjectedDependencies {
dashboardConfig: any;
savedObjectRegistry: any;
savedDashboards: any;
}
export interface DashboardPluginStartDependencies {
data: DataStart;
npData: NpDataStart;
embeddables: ReturnType<EmbeddablePublicPlugin['start']>;
navigation: NavigationStart;
share: SharePluginStart;
}
export interface DashboardPluginSetupDependencies {
__LEGACY: {
getAngularDependencies: () => Promise<LegacyAngularInjectedDependencies>;
};
home: HomePublicPluginSetup;
kibana_legacy: KibanaLegacySetup;
}
export class DashboardPlugin implements Plugin {
private startDependencies: {
dataStart: DataStart;
npDataStart: NpDataStart;
savedObjectsClient: SavedObjectsClientContract;
embeddables: ReturnType<EmbeddablePublicPlugin['start']>;
navigation: NavigationStart;
share: SharePluginStart;
} | null = null;
public setup(
core: CoreSetup,
{ __LEGACY: { getAngularDependencies }, home, kibana_legacy }: DashboardPluginSetupDependencies
) {
const app: App = {
id: '',
title: 'Dashboards',
mount: async ({ core: contextCore }, params) => {
if (this.startDependencies === null) {
throw new Error('not started yet');
}
const {
dataStart,
savedObjectsClient,
embeddables,
navigation,
share,
npDataStart,
} = this.startDependencies;
const angularDependencies = await getAngularDependencies();
const deps: RenderDeps = {
core: contextCore as LegacyCoreStart,
...angularDependencies,
navigation,
dataStart,
share,
npDataStart,
indexPatterns: dataStart.indexPatterns.indexPatterns,
savedObjectsClient,
chrome: contextCore.chrome,
addBasePath: contextCore.http.basePath.prepend,
uiSettings: contextCore.uiSettings,
savedQueryService: dataStart.search.services.savedQueryService,
embeddables,
dashboardCapabilities: contextCore.application.capabilities.dashboard,
localStorage: new Storage(localStorage),
};
const { renderApp } = await import('./application');
return renderApp(params.element, params.appBasePath, deps);
},
};
kibana_legacy.registerLegacyApp({ ...app, id: 'dashboard' });
kibana_legacy.registerLegacyApp({ ...app, id: 'dashboards' });
home.featureCatalogue.register({
id: 'dashboard',
title: i18n.translate('kbn.dashboard.featureCatalogue.dashboardTitle', {
defaultMessage: 'Dashboard',
}),
description: i18n.translate('kbn.dashboard.featureCatalogue.dashboardDescription', {
defaultMessage: 'Display and share a collection of visualizations and saved searches.',
}),
icon: 'dashboardApp',
path: `/app/kibana#${DashboardConstants.LANDING_PAGE_PATH}`,
showOnHomePage: true,
category: FeatureCatalogueCategory.DATA,
});
}
start(
{ savedObjects: { client: savedObjectsClient } }: CoreStart,
{ data: dataStart, embeddables, navigation, npData, share }: DashboardPluginStartDependencies
) {
this.startDependencies = {
dataStart,
npDataStart: npData,
savedObjectsClient,
embeddables,
navigation,
share,
};
}
}

View file

@ -0,0 +1,4 @@
This folder is just a left-over of the things that can't be moved to Kibana platform just yet:
* Styling (this can be moved as soon as there is support for styling in Kibana platform)
* Check whether there are no dev tools and hide the link in the nav bar (this can be moved as soon as all dev tools are moved)

View file

@ -17,18 +17,13 @@
* under the License.
*/
import { npSetup, npStart } from 'ui/new_platform';
// make sure all dev tools are loaded and registered.
import 'uiExports/devTools';
import { DevToolsPlugin } from './plugin';
import { localApplicationService } from '../local_application_service';
import { npStart } from 'ui/new_platform';
const instance = new DevToolsPlugin();
instance.setup(npSetup.core, {
__LEGACY: {
localApplicationService,
},
});
instance.start(npStart.core, {
newPlatformDevTools: npStart.plugins.devTools,
});
if (npStart.plugins.dev_tools.getSortedDevTools().length === 0) {
npStart.core.chrome.navLinks.update('kibana:dev_tools', {
hidden: true,
});
}

View file

@ -1,71 +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.
*/
// 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,
});
}
}
}

View file

@ -25,7 +25,6 @@ import { HomePlugin, LegacyAngularInjectedDependencies } from './plugin';
import { createUiStatsReporter, METRIC_TYPE } from '../../../ui_metric/public';
import { start as data } from '../../../data/public/legacy';
import { TelemetryOptInProvider } from '../../../telemetry/public/services';
import { localApplicationService } from '../local_application_service';
export const trackUiMetric = createUiStatsReporter('Kibana_home');
@ -54,6 +53,7 @@ let copiedLegacyCatalogue = false;
(async () => {
const instance = new HomePlugin();
instance.setup(npSetup.core, {
...npSetup.plugins,
__LEGACY: {
trackUiMetric,
metadata: npStart.core.injectedMetadata.getLegacyMetadata(),
@ -71,7 +71,6 @@ let copiedLegacyCatalogue = false;
return npStart.plugins.home.featureCatalogue.get();
},
getAngularDependencies,
localApplicationService,
},
});
instance.start(npStart.core, {

View file

@ -21,8 +21,8 @@ import { CoreSetup, CoreStart, LegacyNavLink, Plugin, UiSettingsState } from 'ki
import { UiStatsMetricType } from '@kbn/analytics';
import { DataStart } from '../../../data/public';
import { LocalApplicationService } from '../local_application_service';
import { setServices } from './kibana_services';
import { KibanaLegacySetup } from '../../../../../plugins/kibana_legacy/public';
import { FeatureCatalogueEntry } from '../../../../../plugins/home/public';
export interface LegacyAngularInjectedDependencies {
@ -53,8 +53,8 @@ export interface HomePluginSetupDependencies {
};
getFeatureCatalogueEntries: () => Promise<readonly FeatureCatalogueEntry[]>;
getAngularDependencies: () => Promise<LegacyAngularInjectedDependencies>;
localApplicationService: LocalApplicationService;
};
kibana_legacy: KibanaLegacySetup;
}
export class HomePlugin implements Plugin {
@ -64,10 +64,11 @@ export class HomePlugin implements Plugin {
setup(
core: CoreSetup,
{
__LEGACY: { localApplicationService, getAngularDependencies, ...legacyServices },
kibana_legacy,
__LEGACY: { getAngularDependencies, ...legacyServices },
}: HomePluginSetupDependencies
) {
localApplicationService.register({
kibana_legacy.registerLegacyApp({
id: 'home',
title: 'Home',
mount: async ({ core: contextCore }, params) => {

View file

@ -23,12 +23,6 @@ import { ILocationService, IScope } from 'angular';
import { npStart } from 'ui/new_platform';
import { htmlIdGenerator } from '@elastic/eui';
interface ForwardDefinition {
legacyAppId: string;
newAppId: string;
keepPrefix: boolean;
}
const matchAllWithPrefix = (prefixOrApp: string | App) =>
`/${typeof prefixOrApp === 'string' ? prefixOrApp : prefixOrApp.id}/:tail*?`;
@ -45,55 +39,8 @@ const matchAllWithPrefix = (prefixOrApp: string | App) =>
* router that handles switching between applications without page reload.
*/
export class LocalApplicationService {
private apps: App[] = [];
private forwards: ForwardDefinition[] = [];
private idGenerator = htmlIdGenerator('kibanaAppLocalApp');
/**
* Register an app to be managed by the application service.
* This method works exactly as `core.application.register`.
*
* When an app is mounted, it is responsible for routing. The app
* won't be mounted again if the route changes within the prefix
* of the app (its id). It is fine to use whatever means for handling
* routing within the app.
*
* When switching to a URL outside of the current prefix, the app router
* shouldn't do anything because it doesn't own the routing anymore -
* the local application service takes over routing again,
* unmounts the current app and mounts the next app.
*
* @param app The app descriptor
*/
register(app: App) {
this.apps.push(app);
}
/**
* Forwards every URL starting with `legacyAppId` to the same URL starting
* with `newAppId` - e.g. `/legacy/my/legacy/path?q=123` gets forwarded to
* `/newApp/my/legacy/path?q=123`.
*
* When setting the `keepPrefix` option, the new app id is simply prepended.
* The example above would become `/newApp/legacy/my/legacy/path?q=123`.
*
* This method can be used to provide backwards compatibility for URLs when
* renaming or nesting plugins. For route changes after the prefix, please
* use the routing mechanism of your app.
*
* @param legacyAppId The name of the old app to forward URLs from
* @param newAppId The name of the new app that handles the URLs now
* @param options Whether the prefix of the old app is kept to nest the legacy
* path into the new path
*/
forwardApp(
legacyAppId: string,
newAppId: string,
options: { keepPrefix: boolean } = { keepPrefix: false }
) {
this.forwards.push({ legacyAppId, newAppId, ...options });
}
/**
* Wires up listeners to handle mounting and unmounting of apps to
* the legacy angular route manager. Once all apps within the Kibana
@ -103,7 +50,7 @@ export class LocalApplicationService {
* @param angularRouteManager The current `ui/routes` instance
*/
attachToAngular(angularRouteManager: UIRoutes) {
this.apps.forEach(app => {
npStart.plugins.kibana_legacy.getApps().forEach(app => {
const wrapperElementId = this.idGenerator();
angularRouteManager.when(matchAllWithPrefix(app), {
outerAngularWrapperRoute: true,
@ -131,7 +78,7 @@ export class LocalApplicationService {
});
});
this.forwards.forEach(({ legacyAppId, newAppId, keepPrefix }) => {
npStart.plugins.kibana_legacy.getForwards().forEach(({ legacyAppId, newAppId, keepPrefix }) => {
angularRouteManager.when(matchAllWithPrefix(legacyAppId), {
resolveRedirectTo: ($location: ILocationService) => {
const url = $location.url();

View file

@ -22,7 +22,7 @@ import { getFieldFormatsRegistry } from '../../../../test_utils/public/stub_fiel
const mockObservable = () => {
return {
subscribe: () => {}
subscribe: () => {},
};
};
@ -75,16 +75,20 @@ export const npSetup = {
timefilter: {
timefilter: sinon.fake(),
history: sinon.fake(),
}
},
},
fieldFormats: getFieldFormatsRegistry(mockUiSettings),
},
share: {
register: () => {},
},
devTools: {
dev_tools: {
register: () => {},
},
kibana_legacy: {
registerLegacyApp: () => {},
forwardApp: () => {},
},
inspector: {
registerView: () => undefined,
__LEGACY: {
@ -110,7 +114,7 @@ let isAutoRefreshSelectorEnabled = true;
export const npStart = {
core: {
chrome: {}
chrome: {},
},
plugins: {
embeddable: {
@ -123,9 +127,13 @@ export const npStart = {
registerRenderer: sinon.fake(),
registerType: sinon.fake(),
},
devTools: {
dev_tools: {
getSortedDevTools: () => [],
},
kibana_legacy: {
getApps: () => [],
getForwards: () => [],
},
data: {
autocomplete: {
getProvider: sinon.fake(),
@ -142,7 +150,6 @@ export const npStart = {
setFilters: sinon.fake(),
removeAll: sinon.fake(),
getUpdates$: mockObservable,
},
timefilter: {
timefilter: {
@ -166,7 +173,7 @@ export const npStart = {
getRefreshInterval: () => {
return refreshInterval;
},
setRefreshInterval: (interval) => {
setRefreshInterval: interval => {
refreshInterval = interval;
},
enableTimeRangeSelector: () => {

View file

@ -29,6 +29,7 @@ import {
} from '../../../../plugins/inspector/public';
import { EuiUtilsStart } from '../../../../plugins/eui_utils/public';
import { DevToolsSetup, DevToolsStart } from '../../../../plugins/dev_tools/public';
import { KibanaLegacySetup, KibanaLegacyStart } from '../../../../plugins/kibana_legacy/public';
import { HomePublicPluginSetup, HomePublicPluginStart } from '../../../../plugins/home/public';
import { SharePluginSetup, SharePluginStart } from '../../../../plugins/share/public';
@ -39,8 +40,9 @@ export interface PluginsSetup {
home: HomePublicPluginSetup;
inspector: InspectorSetup;
uiActions: IUiActionsSetup;
dev_tools: DevToolsSetup;
kibana_legacy: KibanaLegacySetup;
share: SharePluginSetup;
devTools: DevToolsSetup;
}
export interface PluginsStart {
@ -51,8 +53,9 @@ export interface PluginsStart {
home: HomePublicPluginStart;
inspector: InspectorStart;
uiActions: IUiActionsStart;
dev_tools: DevToolsStart;
kibana_legacy: KibanaLegacyStart;
share: SharePluginStart;
devTools: DevToolsStart;
}
export const npSetup = {

View file

@ -1,6 +1,7 @@
{
"id": "devTools",
"id": "dev_tools",
"version": "kibana",
"server": false,
"ui": true
"ui": true,
"requiredPlugins": ["kibana_legacy"]
}

View file

@ -26,7 +26,7 @@ import ReactDOM from 'react-dom';
import { useEffect, useRef } from 'react';
import { AppMountContext } from 'kibana/public';
import { DevTool } from '../../../../../plugins/dev_tools/public';
import { DevTool } from './plugin';
interface DevToolsWrapperProps {
devTools: readonly DevTool[];
@ -120,10 +120,10 @@ function setBadge(appMountContext: AppMountContext) {
return;
}
appMountContext.core.chrome.setBadge({
text: i18n.translate('kbn.devTools.badge.readOnly.text', {
text: i18n.translate('devTools.badge.readOnly.text', {
defaultMessage: 'Read only',
}),
tooltip: i18n.translate('kbn.devTools.badge.readOnly.tooltip', {
tooltip: i18n.translate('devTools.badge.readOnly.tooltip', {
defaultMessage: 'Unable to save',
}),
iconType: 'glasses',
@ -133,7 +133,7 @@ function setBadge(appMountContext: AppMountContext) {
function setBreadcrumbs(appMountContext: AppMountContext) {
appMountContext.core.chrome.setBreadcrumbs([
{
text: i18n.translate('kbn.devTools.k7BreadcrumbsDevToolsLabel', {
text: i18n.translate('devTools.k7BreadcrumbsDevToolsLabel', {
defaultMessage: 'Dev Tools',
}),
href: '#/dev_tools',

View file

@ -19,6 +19,7 @@
import { App, CoreSetup, Plugin } from 'kibana/public';
import { sortBy } from 'lodash';
import { KibanaLegacySetup } from '../../kibana_legacy/public';
export interface DevToolsSetup {
/**
@ -93,7 +94,24 @@ export class DevToolsPlugin implements Plugin<DevToolsSetup, DevToolsStart> {
return sortBy([...this.devTools.values()], 'order');
}
public setup(core: CoreSetup) {
public setup(core: CoreSetup, { kibana_legacy }: { kibana_legacy: KibanaLegacySetup }) {
kibana_legacy.registerLegacyApp({
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()
);
},
});
return {
register: (devTool: DevTool) => {
if (this.devTools.has(devTool.id)) {

View file

@ -0,0 +1,6 @@
# kibana-legacy
This plugin will contain several helpers and services to integrate pieces of the legacy Kibana app with the new Kibana platform.
Currently, the only service offered is the ability to register apps which are rendered in the legacy "kibana" plugin.

View file

@ -0,0 +1,6 @@
{
"id": "kibana_legacy",
"version": "kibana",
"server": false,
"ui": true
}

View file

@ -0,0 +1,27 @@
/*
* 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 { PluginInitializerContext } from 'kibana/public';
import { KibanaLegacyPlugin } from './plugin';
export function plugin(initializerContext: PluginInitializerContext) {
return new KibanaLegacyPlugin();
}
export * from './plugin';

View file

@ -0,0 +1,100 @@
/*
* 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 } from 'kibana/public';
interface ForwardDefinition {
legacyAppId: string;
newAppId: string;
keepPrefix: boolean;
}
export class KibanaLegacyPlugin {
private apps: App[] = [];
private forwards: ForwardDefinition[] = [];
public setup() {
return {
/**
* @deprecated
* Register an app to be managed by the application service.
* This method works exactly as `core.application.register`.
*
* When an app is mounted, it is responsible for routing. The app
* won't be mounted again if the route changes within the prefix
* of the app (its id). It is fine to use whatever means for handling
* routing within the app.
*
* When switching to a URL outside of the current prefix, the app router
* shouldn't do anything because it doesn't own the routing anymore -
* the local application service takes over routing again,
* unmounts the current app and mounts the next app.
*
* @param app The app descriptor
*/
registerLegacyApp: (app: App) => {
this.apps.push(app);
},
/**
* @deprecated
* Forwards every URL starting with `legacyAppId` to the same URL starting
* with `newAppId` - e.g. `/legacy/my/legacy/path?q=123` gets forwarded to
* `/newApp/my/legacy/path?q=123`.
*
* When setting the `keepPrefix` option, the new app id is simply prepended.
* The example above would become `/newApp/legacy/my/legacy/path?q=123`.
*
* This method can be used to provide backwards compatibility for URLs when
* renaming or nesting plugins. For route changes after the prefix, please
* use the routing mechanism of your app.
*
* @param legacyAppId The name of the old app to forward URLs from
* @param newAppId The name of the new app that handles the URLs now
* @param options Whether the prefix of the old app is kept to nest the legacy
* path into the new path
*/
forwardApp: (
legacyAppId: string,
newAppId: string,
options: { keepPrefix: boolean } = { keepPrefix: false }
) => {
this.forwards.push({ legacyAppId, newAppId, ...options });
},
};
}
public start() {
return {
/**
* @deprecated
* Just exported for wiring up with legacy platform, should not be used.
*/
getApps: () => this.apps,
/**
* @deprecated
* Just exported for wiring up with legacy platform, should not be used.
*/
getForwards: () => this.forwards,
};
}
}
export type KibanaLegacySetup = ReturnType<KibanaLegacyPlugin['setup']>;
export type KibanaLegacyStart = ReturnType<KibanaLegacyPlugin['start']>;

View file

@ -8,7 +8,7 @@ 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({
npSetup.plugins.dev_tools.register({
order: 6,
title: i18n.translate('xpack.grokDebugger.displayName', {
defaultMessage: 'Grok Debugger',

View file

@ -10,7 +10,7 @@ import { I18nProvider } from '@kbn/i18n/react';
import { i18n } from '@kbn/i18n';
import { Query, DataPublicPluginStart } from 'src/plugins/data/public';
import { SavedObjectSaveModal } from 'ui/saved_objects/components/saved_object_save_modal';
import { CoreStart, NotificationsStart } from 'src/core/public';
import { AppMountContext, NotificationsStart } from 'src/core/public';
import {
DataStart,
IndexPattern as IndexPatternInstance,
@ -55,7 +55,7 @@ export function App({
}: {
editorFrame: EditorFrameInstance;
data: DataPublicPluginStart;
core: CoreStart;
core: AppMountContext['core'];
dataShim: DataStart;
storage: IStorageWrapper;
docId?: string;

View file

@ -17,8 +17,7 @@ import React from 'react';
import { I18nProvider, FormattedMessage } from '@kbn/i18n/react';
import { HashRouter, Switch, Route, RouteComponentProps } from 'react-router-dom';
import { render, unmountComponentAtNode } from 'react-dom';
import chrome from 'ui/chrome';
import { CoreSetup, CoreStart } from 'src/core/public';
import { CoreSetup, CoreStart, SavedObjectsClientContract } from 'src/core/public';
import { DataPublicPluginStart } from 'src/plugins/data/public';
import { DataStart } from '../../../../../../src/legacy/core_plugins/data/public';
import { Storage } from '../../../../../../src/plugins/kibana_utils/public';
@ -33,30 +32,35 @@ import {
datatableVisualizationStop,
} from '../datatable_visualization_plugin';
import { App } from './app';
import { EditorFrameInstance } from '../types';
import {
LensReportManager,
setReportManager,
stopReportManager,
trackUiEvent,
} from '../lens_ui_telemetry';
import { LocalApplicationService } from '../../../../../../src/legacy/core_plugins/kibana/public/local_application_service';
import { NOT_INTERNATIONALIZED_PRODUCT_NAME } from '../../index';
import { KibanaLegacySetup } from '../../../../../../src/plugins/kibana_legacy/public';
import { EditorFrameStart } from '../types';
export interface LensPluginSetupDependencies {
kibana_legacy: KibanaLegacySetup;
}
export interface LensPluginStartDependencies {
data: DataPublicPluginStart;
dataShim: DataStart;
__LEGACY: {
localApplicationService: LocalApplicationService;
};
}
export class AppPlugin {
private instance: EditorFrameInstance | null = null;
private store: SavedObjectIndexStore | null = null;
private startDependencies: {
data: DataPublicPluginStart;
dataShim: DataStart;
savedObjectsClient: SavedObjectsClientContract;
editorFrame: EditorFrameStart;
} | null = null;
constructor() {}
setup(core: CoreSetup, plugins: {}) {
setup(core: CoreSetup, { kibana_legacy }: LensPluginSetupDependencies) {
// TODO: These plugins should not be called from the top level, but since this is the
// entry point to the app we have no choice until the new platform is ready
const indexPattern = indexPatternDatasourceSetup();
@ -64,68 +68,57 @@ export class AppPlugin {
const xyVisualization = xyVisualizationSetup();
const metricVisualization = metricVisualizationSetup();
const editorFrameSetupInterface = editorFrameSetup();
this.store = new SavedObjectIndexStore(chrome!.getSavedObjectsClient());
editorFrameSetupInterface.registerVisualization(xyVisualization);
editorFrameSetupInterface.registerVisualization(datatableVisualization);
editorFrameSetupInterface.registerVisualization(metricVisualization);
editorFrameSetupInterface.registerDatasource('indexpattern', indexPattern);
}
start(
core: CoreStart,
{ data, dataShim, __LEGACY: { localApplicationService } }: LensPluginStartDependencies
) {
if (this.store === null) {
throw new Error('Start lifecycle called before setup lifecycle');
}
addHelpMenuToAppChrome(core.chrome);
const store = this.store;
const editorFrameStartInterface = editorFrameStart();
this.instance = editorFrameStartInterface.createInstance({});
setReportManager(
new LensReportManager({
storage: new Storage(localStorage),
http: core.http,
})
);
const renderEditor = (routeProps: RouteComponentProps<{ id?: string }>) => {
trackUiEvent('loaded');
return (
<App
core={core}
data={data}
dataShim={dataShim}
editorFrame={this.instance!}
storage={new Storage(localStorage)}
docId={routeProps.match.params.id}
docStorage={store}
redirectTo={id => {
if (!id) {
routeProps.history.push('/lens');
} else {
routeProps.history.push(`/lens/edit/${id}`);
}
}}
/>
);
};
function NotFound() {
trackUiEvent('loaded_404');
return <FormattedMessage id="xpack.lens.app404" defaultMessage="404 Not Found" />;
}
localApplicationService.register({
kibana_legacy.registerLegacyApp({
id: 'lens',
title: NOT_INTERNATIONALIZED_PRODUCT_NAME,
mount: async (context, params) => {
if (this.startDependencies === null) {
throw new Error('mounted before start phase');
}
const { data, dataShim, savedObjectsClient, editorFrame } = this.startDependencies;
addHelpMenuToAppChrome(context.core.chrome);
const instance = editorFrame.createInstance({});
setReportManager(
new LensReportManager({
storage: new Storage(localStorage),
http: core.http,
})
);
const renderEditor = (routeProps: RouteComponentProps<{ id?: string }>) => {
trackUiEvent('loaded');
return (
<App
core={context.core}
data={data}
dataShim={dataShim}
editorFrame={instance}
storage={new Storage(localStorage)}
docId={routeProps.match.params.id}
docStorage={new SavedObjectIndexStore(savedObjectsClient)}
redirectTo={id => {
if (!id) {
routeProps.history.push('/lens');
} else {
routeProps.history.push(`/lens/edit/${id}`);
}
}}
/>
);
};
function NotFound() {
trackUiEvent('loaded_404');
return <FormattedMessage id="xpack.lens.app404" defaultMessage="404 Not Found" />;
}
render(
<I18nProvider>
<HashRouter>
@ -139,17 +132,23 @@ export class AppPlugin {
params.element
);
return () => {
instance.unmount();
unmountComponentAtNode(params.element);
};
},
});
}
stop() {
if (this.instance) {
this.instance.unmount();
}
start({ savedObjects }: CoreStart, { data, dataShim }: LensPluginStartDependencies) {
this.startDependencies = {
data,
dataShim,
savedObjectsClient: savedObjects.client,
editorFrame: editorFrameStart(),
};
}
stop() {
stopReportManager();
// TODO this will be handled by the plugin platform itself

View file

@ -9,15 +9,11 @@ import { start as dataShimStart } from '../../../../../src/legacy/core_plugins/d
export * from './types';
import { localApplicationService } from '../../../../../src/legacy/core_plugins/kibana/public/local_application_service';
import { AppPlugin } from './app_plugin';
const app = new AppPlugin();
app.setup(npSetup.core, {});
app.setup(npSetup.core, npSetup.plugins);
app.start(npStart.core, {
...npStart.plugins,
dataShim: dataShimStart,
data: npStart.plugins.data,
__LEGACY: {
localApplicationService,
},
});

View file

@ -27,15 +27,15 @@ export class SearchProfilerUIPlugin implements Plugin {
notifications: ToastsStart;
formatAngularHttpError: any;
};
devTools: DevToolsSetup;
dev_tools: DevToolsSetup;
}
) {
const { http } = core;
const {
__LEGACY: { I18nContext, licenseEnabled, notifications, formatAngularHttpError },
devTools,
dev_tools,
} = plugins;
devTools.register({
dev_tools.register({
id: 'searchprofiler',
title: i18n.translate('xpack.searchProfiler.pageDisplayName', {
defaultMessage: 'Search Profiler',

View file

@ -872,6 +872,9 @@
"data.search.searchBar.savedQueryPopoverSavedQueryListItemDescriptionAriaLabel": "{savedQueryName} の説明",
"data.search.searchBar.savedQueryPopoverSavedQueryListItemSelectedButtonAriaLabel": "選択されたクエリボタン {savedQueryName} を保存しました。変更を破棄するには押してください。",
"data.search.searchBar.savedQueryPopoverTitleText": "保存されたクエリ",
"devTools.badge.readOnly.text": "読み込み専用",
"devTools.badge.readOnly.tooltip": "を保存できませんでした",
"devTools.k7BreadcrumbsDevToolsLabel": "開発ツール",
"data.filter.filterEditor.operatorSelectPlaceholderSelect": "選択してください",
"data.filter.filterEditor.operatorSelectPlaceholderWaiting": "待機中",
"data.filter.filterEditor.rangeInputLabel": "範囲",
@ -1507,9 +1510,6 @@
"kbn.dashboard.urlWasRemovedInSixZeroWarningMessage": "URL「dashboard/create」は 6.0 で廃止されました。ブックマークを更新してください。",
"kbn.dashboard.visitVisualizeAppLinkText": "可視化アプリにアクセス",
"kbn.dashboardTitle": "ダッシュボード",
"kbn.devTools.badge.readOnly.text": "読み込み専用",
"kbn.devTools.badge.readOnly.tooltip": "を保存できませんでした",
"kbn.devTools.k7BreadcrumbsDevToolsLabel": "開発ツール",
"kbn.devToolsTitle": "開発ツール",
"kbn.discover.backToTopLinkText": "最上部へ戻る。",
"kbn.discover.badge.readOnly.text": "読み込み専用",

View file

@ -873,6 +873,9 @@
"data.search.searchBar.savedQueryPopoverSavedQueryListItemDescriptionAriaLabel": "{savedQueryName} 描述",
"data.search.searchBar.savedQueryPopoverSavedQueryListItemSelectedButtonAriaLabel": "已保存查询按钮已选择 {savedQueryName}。按下可清除任何更改。",
"data.search.searchBar.savedQueryPopoverTitleText": "已保存查询",
"devTools.badge.readOnly.text": "只读",
"devTools.badge.readOnly.tooltip": "无法保存",
"devTools.k7BreadcrumbsDevToolsLabel": "开发工具",
"data.filter.filterEditor.operatorSelectPlaceholderSelect": "选择",
"data.filter.filterEditor.operatorSelectPlaceholderWaiting": "正在等候",
"data.filter.filterEditor.rangeInputLabel": "范围",
@ -1508,9 +1511,6 @@
"kbn.dashboard.urlWasRemovedInSixZeroWarningMessage": "6.0 中未移除 url“dashboard/create”。请更新您的书签。",
"kbn.dashboard.visitVisualizeAppLinkText": "访问 Visualize 应用",
"kbn.dashboardTitle": "仪表板",
"kbn.devTools.badge.readOnly.text": "只读",
"kbn.devTools.badge.readOnly.tooltip": "无法保存",
"kbn.devTools.k7BreadcrumbsDevToolsLabel": "开发工具",
"kbn.devToolsTitle": "开发工具",
"kbn.discover.backToTopLinkText": "返至顶部。",
"kbn.discover.badge.readOnly.text": "只读",