Skip to content

Commit

Permalink
Extract KQL autocomplete to a plugin (#20747)
Browse files Browse the repository at this point in the history
* fix: move autocomplete to x-pack basic

* fix: apm support

* fix: renames

* [uiExports] switch to new autocompleteProviders export type

* fix: remove unnecessary stuff from the plugin spec
  • Loading branch information
lukasolson committed Jul 24, 2018
1 parent a56c856 commit ecc0f5e
Show file tree
Hide file tree
Showing 24 changed files with 160 additions and 242 deletions.
1 change: 1 addition & 0 deletions src/core_plugins/kibana/public/kibana.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ import 'uiExports/docViews';
import 'uiExports/embeddableFactories';
import 'uiExports/inspectorViews';
import 'uiExports/search';
import 'uiExports/autocompleteProviders';

import 'ui/autoload/all';
import './home';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,22 +17,12 @@
* under the License.
*/

export function escapeQuotes(string) {
return string.replace(/"/g, '\\"');
}

export const escapeKuery = (string) => escapeNot(escapeAndOr(escapeSpecialCharacters(string)));

// See the SpecialCharacter rule in kuery.peg
function escapeSpecialCharacters(string) {
return string.replace(/[\\():<>"*]/g, '\\$&'); // $& means the whole matched string
}
const autocompleteProviders = new Map();

// See the Keyword rule in kuery.peg
function escapeAndOr(string) {
return string.replace(/(\s+)(and|or)(\s+)/ig, '$1\\$2$3');
export function addAutocompleteProvider(language, provider) {
autocompleteProviders.set(language, provider);
}

function escapeNot(string) {
return string.replace(/not(\s+)/ig, '\\$&');
export function getAutocompleteProvider(language) {
return autocompleteProviders.get(language);
}
1 change: 0 additions & 1 deletion src/ui/public/kuery/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,3 @@
export * from './ast';
export * from './filter_migration';
export * from './node_types';
export * from './suggestions';
41 changes: 0 additions & 41 deletions src/ui/public/kuery/suggestions/conjunction.js

This file was deleted.

39 changes: 20 additions & 19 deletions src/ui/public/query_bar/directive/query_bar.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,12 @@
* under the License.
*/

import { compact, get } from 'lodash';
import { compact } from 'lodash';
import { uiModules } from '../../modules';
import { callAfterBindingsWorkaround } from '../../compat';
import template from './query_bar.html';
import suggestionTemplate from './suggestion.html';
import { getSuggestionsProvider } from '../../kuery';
import { getAutocompleteProvider } from '../../autocomplete_providers';
import './suggestion.less';
import '../../directives/match_pairs';
import './query_popover';
Expand Down Expand Up @@ -75,18 +75,25 @@ module.directive('queryBar', function () {
}
};

this.updateSuggestions = () => {
const query = get(this, 'localQuery.query');
if (typeof query === 'undefined') return;
this.updateSuggestions = async () => {
const suggestions = await this.getSuggestions();
$scope.$apply(() => this.suggestions = suggestions);
};

this.getSuggestions = async () => {
const { localQuery: { query, language } } = this;
const recentSearchSuggestions = this.getRecentSearchSuggestions(query);

this.suggestions = this.getRecentSearchSuggestions(query);
if (this.localQuery.language !== 'kuery' || !this.getKuerySuggestions) return;
const autocompleteProvider = getAutocompleteProvider(language);
if (!autocompleteProvider) return recentSearchSuggestions;

const legacyIndexPatterns = await this.getIndexPatterns();
const indexPatterns = getFromLegacyIndexPattern(legacyIndexPatterns);
const getAutocompleteSuggestions = autocompleteProvider({ config, indexPatterns });

const { selectionStart, selectionEnd } = $element.find('input')[0];
this.getKuerySuggestions({ query, selectionStart, selectionEnd })
.then(suggestions => {
$scope.$apply(() => this.suggestions = [...suggestions, ...this.suggestions]);
});
const suggestions = await getAutocompleteSuggestions({ query, selectionStart, selectionEnd });
return [...suggestions, ...recentSearchSuggestions];
};

// TODO: Figure out a better way to set selection
Expand All @@ -107,6 +114,7 @@ module.directive('queryBar', function () {
};

this.getRecentSearchSuggestions = (query) => {
if (!this.persistedLog) return [];
const recentSearches = this.persistedLog.get();
const matchingRecentSearches = recentSearches.filter(search => search.includes(query));
return matchingRecentSearches.map(recentSearch => {
Expand All @@ -133,14 +141,7 @@ module.directive('queryBar', function () {
}, true);

$scope.$watch('queryBar.indexPatterns', () => {
this.getIndexPatterns().then(indexPatterns => {

this.getKuerySuggestions = getSuggestionsProvider({
config,
indexPatterns: getFromLegacyIndexPattern(indexPatterns)
});
this.updateSuggestions();
});
this.updateSuggestions();
});
})
};
Expand Down
1 change: 1 addition & 0 deletions src/ui/ui_exports/ui_export_types/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ export {
aliases,
visualize,
search,
autocompleteProviders,
} from './ui_app_extensions';

export {
Expand Down
1 change: 1 addition & 0 deletions src/ui/ui_exports/ui_export_types/ui_app_extensions.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ export const visTypes = appExtension;
export const visResponseHandlers = appExtension;
export const visRequestHandlers = appExtension;
export const visEditorTypes = appExtension;
export const autocompleteProviders = appExtension;
export const savedObjectTypes = appExtension;
export const embeddableFactories = appExtension;
export const dashboardPanelActions = appExtension;
Expand Down
2 changes: 2 additions & 0 deletions x-pack/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import { cloud } from './plugins/cloud';
import { indexManagement } from './plugins/index_management';
import { consoleExtensions } from './plugins/console_extensions';
import { notifications } from './plugins/notifications';
import { kueryAutocomplete } from './plugins/kuery_autocomplete';

module.exports = function (kibana) {
return [
Expand All @@ -43,5 +44,6 @@ module.exports = function (kibana) {
indexManagement(kibana),
consoleExtensions(kibana),
notifications(kibana),
kueryAutocomplete(kibana)
];
};
1 change: 1 addition & 0 deletions x-pack/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
"enzyme-adapter-react-16": "^1.1.1",
"enzyme-to-json": "3.3.1",
"expect.js": "0.3.1",
"fetch-mock": "^5.13.1",
"gulp": "3.9.1",
"gulp-load-plugins": "1.2.0",
"gulp-mocha": "2.2.0",
Expand Down
13 changes: 6 additions & 7 deletions x-pack/plugins/apm/public/services/kuery.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,8 @@
* you may not use this file except in compliance with the Elastic License.
*/

import {
fromKueryExpression,
toElasticsearchQuery,
getSuggestionsProvider
} from 'ui/kuery';
import { fromKueryExpression, toElasticsearchQuery } from 'ui/kuery';
import { getAutocompleteProvider } from 'ui/autocomplete_providers';

export function convertKueryToEsQuery(kuery, indexPattern) {
const ast = fromKueryExpression(kuery);
Expand All @@ -21,16 +18,18 @@ export async function getSuggestions(
apmIndexPattern,
boolFilter
) {
const autocompleteProvider = getAutocompleteProvider('kuery');
if (!autocompleteProvider) return [];
const config = {
get: () => true
};

const getKuerySuggestions = getSuggestionsProvider({
const getAutocompleteSuggestions = autocompleteProvider({
config,
indexPatterns: [apmIndexPattern],
boolFilter
});
return getKuerySuggestions({
return getAutocompleteSuggestions({
query,
selectionStart,
selectionEnd: selectionStart
Expand Down
2 changes: 1 addition & 1 deletion x-pack/plugins/dashboard_mode/public/dashboard_viewer.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import 'uiExports/navbarExtensions';
import 'uiExports/docViews';
import 'uiExports/fieldFormats';
import 'uiExports/search';

import 'uiExports/autocompleteProviders';
import _ from 'lodash';
import 'ui/autoload/all';
import 'plugins/kibana/dashboard';
Expand Down
18 changes: 18 additions & 0 deletions x-pack/plugins/kuery_autocomplete/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/*
* 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 { resolve } from 'path';


export const kueryAutocomplete = (kibana) => new kibana.Plugin({
id: 'kuery_autocomplete',
publicDir: resolve(__dirname, 'public'),
uiExports: {
autocompleteProviders: [
'plugins/kuery_autocomplete/autocomplete_providers'
],
}
});
Original file line number Diff line number Diff line change
@@ -1,20 +1,7 @@
/*
* 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.
* 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 expect from 'expect.js';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,7 @@
/*
* 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.
* 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 expect from 'expect.js';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,26 +1,13 @@
/*
* 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.
* 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 expect from 'expect.js';
import { getSuggestionsProvider } from '../field';
import indexPatternResponse from '../../__tests__/index_pattern_response.json';
import { isFilterable } from '../../../index_patterns/static_utils';
import indexPatternResponse from 'ui/kuery/__tests__/index_pattern_response.json';
import { isFilterable } from 'ui/index_patterns/static_utils';

describe('Kuery field suggestions', function () {
let indexPattern;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,25 +1,12 @@
/*
* 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.
* 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 expect from 'expect.js';
import { getSuggestionsProvider } from '../operator';
import indexPatternResponse from '../../__tests__/index_pattern_response.json';
import indexPatternResponse from 'ui/kuery/__tests__/index_pattern_response.json';

describe('Kuery operator suggestions', function () {
let indexPatterns;
Expand Down
Loading

0 comments on commit ecc0f5e

Please sign in to comment.