Skip to content

Commit

Permalink
[Lens] Add search provider for global search (#77448)
Browse files Browse the repository at this point in the history
  • Loading branch information
flash1293 authored Sep 23, 2020
1 parent 3c6f242 commit 6ebffef
Show file tree
Hide file tree
Showing 4 changed files with 100 additions and 3 deletions.
4 changes: 2 additions & 2 deletions x-pack/plugins/lens/common/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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()}`;
}
2 changes: 1 addition & 1 deletion x-pack/plugins/lens/kibana.json
Original file line number Diff line number Diff line change
Expand Up @@ -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"]
Expand Down
18 changes: 18 additions & 0 deletions x-pack/plugins/lens/public/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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';

Expand All @@ -41,6 +43,7 @@ export interface LensPluginSetupDependencies {
embeddable?: EmbeddableSetup;
visualizations: VisualizationsSetup;
charts: ChartsPluginSetup;
globalSearch?: GlobalSearchPluginSetup;
}

export interface LensPluginStartDependencies {
Expand Down Expand Up @@ -78,6 +81,7 @@ export class LensPlugin {
embeddable,
visualizations,
charts,
globalSearch,
}: LensPluginSetupDependencies
) {
const editorFrameSetupInterface = this.editorFrameService.setup(core, {
Expand Down Expand Up @@ -116,6 +120,20 @@ export class LensPlugin {
},
});

if (globalSearch) {
globalSearch.registerResultProvider(
getSearchProvider(
core.getStartServices().then(
([
{
application: { capabilities },
},
]) => capabilities
)
)
);
}

urlForwarding.forwardApp('lens', 'lens');
}

Expand Down
79 changes: 79 additions & 0 deletions x-pack/plugins/lens/public/search_provider.ts
Original file line number Diff line number Diff line change
@@ -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(),
},
];
})
);
},
});

0 comments on commit 6ebffef

Please sign in to comment.