[Lens] Add search provider for global search (#77448)
This commit is contained in:
parent
3c6f242981
commit
6ebffef9c5
|
@ -17,6 +17,6 @@ export function getEditPath(id: string) {
|
|||
return `#/edit/${encodeURIComponent(id)}`;
|
||||
}
|
||||
|
||||
export function getFullPath(id: string) {
|
||||
return `/app/${PLUGIN_ID}${getEditPath(id)}`;
|
||||
export function getFullPath(id?: string) {
|
||||
return `/app/${PLUGIN_ID}${id ? getEditPath(id) : getBasePath()}`;
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
"dashboard",
|
||||
"charts"
|
||||
],
|
||||
"optionalPlugins": ["embeddable", "usageCollection", "taskManager", "uiActions"],
|
||||
"optionalPlugins": ["embeddable", "usageCollection", "taskManager", "uiActions", "globalSearch"],
|
||||
"configPath": ["xpack", "lens"],
|
||||
"extraPublicDirs": ["common/constants"],
|
||||
"requiredBundles": ["savedObjects", "kibanaUtils", "kibanaReact", "embeddable"]
|
||||
|
|
|
@ -11,6 +11,7 @@ import { ExpressionsSetup, ExpressionsStart } from 'src/plugins/expressions/publ
|
|||
import { VisualizationsSetup } from 'src/plugins/visualizations/public';
|
||||
import { NavigationPublicPluginStart } from 'src/plugins/navigation/public';
|
||||
import { UrlForwardingSetup } from 'src/plugins/url_forwarding/public';
|
||||
import { GlobalSearchPluginSetup } from '../../global_search/public';
|
||||
import { ChartsPluginSetup } from '../../../../src/plugins/charts/public';
|
||||
import { EditorFrameService } from './editor_frame_service';
|
||||
import {
|
||||
|
@ -31,6 +32,7 @@ import { UiActionsStart } from '../../../../src/plugins/ui_actions/public';
|
|||
import { NOT_INTERNATIONALIZED_PRODUCT_NAME } from '../common';
|
||||
import { EditorFrameStart } from './types';
|
||||
import { getLensAliasConfig } from './vis_type_alias';
|
||||
import { getSearchProvider } from './search_provider';
|
||||
|
||||
import './index.scss';
|
||||
|
||||
|
@ -41,6 +43,7 @@ export interface LensPluginSetupDependencies {
|
|||
embeddable?: EmbeddableSetup;
|
||||
visualizations: VisualizationsSetup;
|
||||
charts: ChartsPluginSetup;
|
||||
globalSearch?: GlobalSearchPluginSetup;
|
||||
}
|
||||
|
||||
export interface LensPluginStartDependencies {
|
||||
|
@ -78,6 +81,7 @@ export class LensPlugin {
|
|||
embeddable,
|
||||
visualizations,
|
||||
charts,
|
||||
globalSearch,
|
||||
}: LensPluginSetupDependencies
|
||||
) {
|
||||
const editorFrameSetupInterface = this.editorFrameService.setup(core, {
|
||||
|
@ -116,6 +120,20 @@ export class LensPlugin {
|
|||
},
|
||||
});
|
||||
|
||||
if (globalSearch) {
|
||||
globalSearch.registerResultProvider(
|
||||
getSearchProvider(
|
||||
core.getStartServices().then(
|
||||
([
|
||||
{
|
||||
application: { capabilities },
|
||||
},
|
||||
]) => capabilities
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
urlForwarding.forwardApp('lens', 'lens');
|
||||
}
|
||||
|
||||
|
|
79
x-pack/plugins/lens/public/search_provider.ts
Normal file
79
x-pack/plugins/lens/public/search_provider.ts
Normal file
|
@ -0,0 +1,79 @@
|
|||
/*
|
||||
* 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 levenshtein from 'js-levenshtein';
|
||||
import { ApplicationStart } from 'kibana/public';
|
||||
import { from } from 'rxjs';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { DEFAULT_APP_CATEGORIES } from '../../../../src/core/public';
|
||||
import { GlobalSearchResultProvider } from '../../global_search/public';
|
||||
import { getFullPath } from '../common';
|
||||
|
||||
/**
|
||||
* Global search provider adding a Lens entry.
|
||||
* This is necessary because Lens does not show up in the nav bar and is filtered out by the
|
||||
* default app provider.
|
||||
*
|
||||
* It is inlining the same search term matching logic as the application search provider.
|
||||
*
|
||||
* TODO: This is a workaround and can be removed once there is a generic way to register sub features
|
||||
* of apps. In this case, Lens should be considered a feature of Visualize.
|
||||
*/
|
||||
export const getSearchProvider: (
|
||||
uiCapabilities: Promise<ApplicationStart['capabilities']>
|
||||
) => GlobalSearchResultProvider = (uiCapabilities) => ({
|
||||
id: 'lens',
|
||||
find: (term) => {
|
||||
return from(
|
||||
uiCapabilities.then(({ navLinks: { visualize: visualizeNavLink } }) => {
|
||||
if (!visualizeNavLink) {
|
||||
return [];
|
||||
}
|
||||
const title = i18n.translate('xpack.lens.searchTitle', {
|
||||
defaultMessage: 'Lens: create visualizations',
|
||||
description: 'Lens is a product name and should not be translated',
|
||||
});
|
||||
const searchableTitle = title.toLowerCase();
|
||||
|
||||
term = term.toLowerCase();
|
||||
let score = 0;
|
||||
|
||||
// shortcuts to avoid calculating the distance when there is an exact match somewhere.
|
||||
if (searchableTitle === term) {
|
||||
score = 100;
|
||||
} else if (searchableTitle.startsWith(term)) {
|
||||
score = 90;
|
||||
} else if (searchableTitle.includes(term)) {
|
||||
score = 75;
|
||||
} else {
|
||||
const length = Math.max(term.length, searchableTitle.length);
|
||||
const distance = levenshtein(term, searchableTitle);
|
||||
|
||||
// maximum lev distance is length, we compute the match ratio (lower distance is better)
|
||||
const ratio = Math.floor((1 - distance / length) * 100);
|
||||
if (ratio >= 60) {
|
||||
score = ratio;
|
||||
}
|
||||
}
|
||||
if (score === 0) return [];
|
||||
return [
|
||||
{
|
||||
id: 'lens',
|
||||
title,
|
||||
type: 'application',
|
||||
icon: 'logoKibana',
|
||||
meta: {
|
||||
categoryId: DEFAULT_APP_CATEGORIES.kibana.id,
|
||||
categoryLabel: DEFAULT_APP_CATEGORIES.kibana.label,
|
||||
},
|
||||
score,
|
||||
url: getFullPath(),
|
||||
},
|
||||
];
|
||||
})
|
||||
);
|
||||
},
|
||||
});
|
Loading…
Reference in a new issue