]: NP[K] };
+
+type ExtendedObjectType = ObjectType<
+ ExtendedProps
+>;
+
+type ExtendedObjectTypeOptions
= ObjectTypeOptions<
+ ExtendedProps
+>;
+
interface UnknownOptions {
/**
* Options for dealing with unknown keys:
@@ -61,10 +81,13 @@ export type ObjectTypeOptions
= TypeOptions extends Type> {
- private props: Record;
+ private props: P;
+ private options: ObjectTypeOptions;
+ private propSchemas: Record;
- constructor(props: P, { unknowns = 'forbid', ...typeOptions }: ObjectTypeOptions = {}) {
+ constructor(props: P, options: ObjectTypeOptions
= {}) {
const schemaKeys = {} as Record;
+ const { unknowns = 'forbid', ...typeOptions } = options;
for (const [key, value] of Object.entries(props)) {
schemaKeys[key] = value.getSchema();
}
@@ -77,7 +100,93 @@ export class ObjectType extends Type>
.options({ stripUnknown: { objects: unknowns === 'ignore' } });
super(schema, typeOptions);
- this.props = schemaKeys;
+ this.props = props;
+ this.propSchemas = schemaKeys;
+ this.options = options;
+ }
+
+ /**
+ * Return a new `ObjectType` instance extended with given `newProps` properties.
+ * Original properties can be deleted from the copy by passing a `null` or `undefined` value for the key.
+ *
+ * @example
+ * How to add a new key to an object schema
+ * ```ts
+ * const origin = schema.object({
+ * initial: schema.string(),
+ * });
+ *
+ * const extended = origin.extends({
+ * added: schema.number(),
+ * });
+ * ```
+ *
+ * How to remove an existing key from an object schema
+ * ```ts
+ * const origin = schema.object({
+ * initial: schema.string(),
+ * toRemove: schema.number(),
+ * });
+ *
+ * const extended = origin.extends({
+ * toRemove: undefined,
+ * });
+ * ```
+ *
+ * How to override the schema's options
+ * ```ts
+ * const origin = schema.object({
+ * initial: schema.string(),
+ * }, { defaultValue: { initial: 'foo' }});
+ *
+ * const extended = origin.extends({
+ * added: schema.number(),
+ * }, { defaultValue: { initial: 'foo', added: 'bar' }});
+ *
+ * @remarks
+ * `extends` only support extending first-level properties. It's currently not possible to perform deep/nested extensions.
+ *
+ * ```ts
+ * const origin = schema.object({
+ * foo: schema.string(),
+ * nested: schema.object({
+ * a: schema.string(),
+ * b: schema.string(),
+ * }),
+ * });
+ *
+ * const extended = origin.extends({
+ * nested: schema.object({
+ * c: schema.string(),
+ * }),
+ * });
+ *
+ * // TypeOf is `{ foo: string; nested: { c: string } }`
+ * ```
+ */
+ public extends(
+ newProps: NP,
+ newOptions?: ExtendedObjectTypeOptions
+ ): ExtendedObjectType
{
+ const extendedProps = Object.entries({
+ ...this.props,
+ ...newProps,
+ }).reduce((memo, [key, value]) => {
+ if (value !== null && value !== undefined) {
+ return {
+ ...memo,
+ [key]: value,
+ };
+ }
+ return memo;
+ }, {} as ExtendedProps
);
+
+ const extendedOptions = {
+ ...this.options,
+ ...newOptions,
+ } as ExtendedObjectTypeOptions
;
+
+ return new ObjectType(extendedProps, extendedOptions);
}
protected handleError(type: string, { reason, value }: Record) {
@@ -95,10 +204,10 @@ export class ObjectType extends Type>
}
validateKey(key: string, value: any) {
- if (!this.props[key]) {
+ if (!this.propSchemas[key]) {
throw new Error(`${key} is not a valid part of this schema`);
}
- const { value: validatedValue, error } = this.props[key].validate(value);
+ const { value: validatedValue, error } = this.propSchemas[key].validate(value);
if (error) {
throw new ValidationError(error as any, key);
}
diff --git a/packages/kbn-monaco/README.md b/packages/kbn-monaco/README.md
new file mode 100644
index 0000000000000..c5d7dd7dbfed5
--- /dev/null
+++ b/packages/kbn-monaco/README.md
@@ -0,0 +1,5 @@
+# @kbn/monaco
+
+A customized version of monaco that is automatically configured the way we want it to be when imported as `@kbn/monaco`. Additionally, imports to this package are automatically shared with all plugins using `@kbn/ui-shared-deps`.
+
+Includes custom xjson language support. The `es_ui_shared` plugin has an example of how to use it, in the future we will likely expose helpers from this package to make using it everywhere a little more seamless.
\ No newline at end of file
diff --git a/packages/kbn-monaco/package.json b/packages/kbn-monaco/package.json
new file mode 100644
index 0000000000000..170c014e6e326
--- /dev/null
+++ b/packages/kbn-monaco/package.json
@@ -0,0 +1,27 @@
+{
+ "name": "@kbn/monaco",
+ "version": "1.0.0",
+ "private": true,
+ "main": "./target/index.js",
+ "license": "Apache-2.0",
+ "scripts": {
+ "build": "node ./scripts/build.js",
+ "kbn:bootstrap": "yarn build --dev"
+ },
+ "dependencies": {
+ "regenerator-runtime": "^0.13.3",
+ "monaco-editor": "~0.17.0"
+ },
+ "devDependencies": {
+ "@kbn/babel-preset": "1.0.0",
+ "@kbn/dev-utils": "1.0.0",
+ "babel-loader": "^8.0.6",
+ "css-loader": "^3.4.2",
+ "del": "^5.1.0",
+ "raw-loader": "3.1.0",
+ "supports-color": "^7.0.0",
+ "typescript": "3.7.2",
+ "webpack": "^4.41.5",
+ "webpack-cli": "^3.3.10"
+ }
+}
diff --git a/packages/kbn-monaco/scripts/build.js b/packages/kbn-monaco/scripts/build.js
new file mode 100644
index 0000000000000..c5540e3c956c8
--- /dev/null
+++ b/packages/kbn-monaco/scripts/build.js
@@ -0,0 +1,64 @@
+/*
+ * 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.
+ */
+
+const path = require('path');
+const del = require('del');
+const supportsColor = require('supports-color');
+const { run } = require('@kbn/dev-utils');
+
+const TARGET_BUILD_DIR = path.resolve(__dirname, '../target');
+const ROOT_DIR = path.resolve(__dirname, '../');
+const WEBPACK_CONFIG_PATH = path.resolve(ROOT_DIR, 'webpack.config.js');
+
+run(
+ async ({ procRunner, log, flags }) => {
+ log.info('Deleting old output');
+
+ await del(TARGET_BUILD_DIR);
+
+ const cwd = ROOT_DIR;
+ const env = { ...process.env };
+ if (supportsColor.stdout) {
+ env.FORCE_COLOR = 'true';
+ }
+
+ await procRunner.run('worker', {
+ cmd: 'webpack',
+ args: ['--config', WEBPACK_CONFIG_PATH, flags.dev ? '--env.dev' : '--env.prod'],
+ wait: true,
+ env,
+ cwd,
+ });
+
+ await procRunner.run('tsc ', {
+ cmd: 'tsc',
+ args: [],
+ wait: true,
+ env,
+ cwd,
+ });
+
+ log.success('Complete');
+ },
+ {
+ flags: {
+ boolean: ['dev'],
+ },
+ }
+);
diff --git a/packages/kbn-monaco/src/index.ts b/packages/kbn-monaco/src/index.ts
new file mode 100644
index 0000000000000..9213a1bfe1327
--- /dev/null
+++ b/packages/kbn-monaco/src/index.ts
@@ -0,0 +1,25 @@
+/*
+ * 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.
+ */
+
+export { monaco } from './monaco';
+export { XJsonLang } from './xjson';
+
+/* eslint-disable-next-line @kbn/eslint/module_migration */
+import * as BarePluginApi from 'monaco-editor/esm/vs/editor/editor.api';
+export { BarePluginApi };
diff --git a/packages/kbn-ui-shared-deps/monaco.ts b/packages/kbn-monaco/src/monaco.ts
similarity index 96%
rename from packages/kbn-ui-shared-deps/monaco.ts
rename to packages/kbn-monaco/src/monaco.ts
index 42801c69a3e2c..a40b2212ef0e2 100644
--- a/packages/kbn-ui-shared-deps/monaco.ts
+++ b/packages/kbn-monaco/src/monaco.ts
@@ -17,6 +17,8 @@
* under the License.
*/
+/* eslint-disable @kbn/eslint/module_migration */
+
import * as monaco from 'monaco-editor/esm/vs/editor/editor.api';
import 'monaco-editor/esm/vs/base/common/worker/simpleWorker';
diff --git a/packages/kbn-monaco/src/xjson/README.md b/packages/kbn-monaco/src/xjson/README.md
new file mode 100644
index 0000000000000..8652d0bd776d2
--- /dev/null
+++ b/packages/kbn-monaco/src/xjson/README.md
@@ -0,0 +1,28 @@
+# README
+
+This folder contains the language definitions for XJSON used by the Monaco editor.
+
+## Summary of contents
+
+Note: All source code.
+
+### ./worker
+
+The worker proxy and worker instantiation code used in both the main thread and the worker thread.
+
+### ./lexer_rules
+
+Contains the Monarch-specific language tokenization rules for XJSON. Each set of rules registers itself against monaco.
+
+### ./constants.ts
+
+Contains the unique language ID.
+
+### ./language
+
+Takes care of global setup steps for the language (like registering it against Monaco) and exports a way to load up
+the grammar parser.
+
+### ./worker_proxy_service
+
+A stateful mechanism for holding a reference to the Monaco-provided proxy getter.
diff --git a/packages/kbn-monaco/src/xjson/constants.ts b/packages/kbn-monaco/src/xjson/constants.ts
new file mode 100644
index 0000000000000..dc107abff4ffe
--- /dev/null
+++ b/packages/kbn-monaco/src/xjson/constants.ts
@@ -0,0 +1,20 @@
+/*
+ * 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.
+ */
+
+export const ID = 'xjson';
diff --git a/packages/kbn-monaco/src/xjson/grammar.ts b/packages/kbn-monaco/src/xjson/grammar.ts
new file mode 100644
index 0000000000000..e95059f9ece2d
--- /dev/null
+++ b/packages/kbn-monaco/src/xjson/grammar.ts
@@ -0,0 +1,213 @@
+/*
+ * 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.
+ */
+
+export enum AnnoTypes {
+ error = 'error',
+ warning = 'warning',
+}
+
+/* eslint-disable */
+
+export const createParser = () => {
+ 'use strict';
+ let at: any,
+ annos: any[], // annotations
+ ch: any,
+ text: any,
+ value: any,
+ escapee: any = {
+ '"': '"',
+ '\\': '\\',
+ '/': '/',
+ b: '\b',
+ f: '\f',
+ n: '\n',
+ r: '\r',
+ t: ' ',
+ },
+ error = function (m: string) {
+ throw {
+ at: at,
+ text: m,
+ message: m,
+ };
+ },
+ warning = function (m: string, idx: number) {
+ annos.push({
+ type: AnnoTypes.warning,
+ at: idx,
+ text: m,
+ });
+ },
+ reset = function (newAt: number) {
+ ch = text.charAt(newAt);
+ at = newAt + 1;
+ },
+ next = function (c?: string) {
+ return (
+ c && c !== ch && error("Expected '" + c + "' instead of '" + ch + "'"),
+ (ch = text.charAt(at)),
+ (at += 1),
+ ch
+ );
+ },
+ nextUpTo = function (upTo: any, errorMessage: string) {
+ let currentAt = at,
+ i = text.indexOf(upTo, currentAt);
+ if (i < 0) {
+ error(errorMessage || "Expected '" + upTo + "'");
+ }
+ reset(i + upTo.length);
+ return text.substring(currentAt, i);
+ },
+ peek = function (c: string) {
+ return text.substr(at, c.length) === c; // nocommit - double check
+ },
+ number = function () {
+ var number,
+ string = '';
+ for ('-' === ch && ((string = '-'), next('-')); ch >= '0' && '9' >= ch; )
+ (string += ch), next();
+ if ('.' === ch) for (string += '.'; next() && ch >= '0' && '9' >= ch; ) string += ch;
+ if ('e' === ch || 'E' === ch)
+ for (
+ string += ch, next(), ('-' === ch || '+' === ch) && ((string += ch), next());
+ ch >= '0' && '9' >= ch;
+
+ )
+ (string += ch), next();
+ return (number = +string), isNaN(number) ? (error('Bad number'), void 0) : number;
+ },
+ string = function () {
+ let hex: any,
+ i: any,
+ uffff: any,
+ string = '';
+ if ('"' === ch) {
+ if (peek('""')) {
+ // literal
+ next('"');
+ next('"');
+ return nextUpTo('"""', 'failed to find closing \'"""\'');
+ } else {
+ for (; next(); ) {
+ if ('"' === ch) return next(), string;
+ if ('\\' === ch)
+ if ((next(), 'u' === ch)) {
+ for (
+ uffff = 0, i = 0;
+ 4 > i && ((hex = parseInt(next(), 16)), isFinite(hex));
+ i += 1
+ )
+ uffff = 16 * uffff + hex;
+ string += String.fromCharCode(uffff);
+ } else {
+ if ('string' != typeof escapee[ch]) break;
+ string += escapee[ch];
+ }
+ else string += ch;
+ }
+ }
+ }
+ error('Bad string');
+ },
+ white = function () {
+ for (; ch && ' ' >= ch; ) next();
+ },
+ word = function () {
+ switch (ch) {
+ case 't':
+ return next('t'), next('r'), next('u'), next('e'), !0;
+ case 'f':
+ return next('f'), next('a'), next('l'), next('s'), next('e'), !1;
+ case 'n':
+ return next('n'), next('u'), next('l'), next('l'), null;
+ }
+ error("Unexpected '" + ch + "'");
+ },
+ array = function () {
+ var array: any[] = [];
+ if ('[' === ch) {
+ if ((next('['), white(), ']' === ch)) return next(']'), array;
+ for (; ch; ) {
+ if ((array.push(value()), white(), ']' === ch)) return next(']'), array;
+ next(','), white();
+ }
+ }
+ error('Bad array');
+ },
+ object = function () {
+ var key,
+ object: any = {};
+ if ('{' === ch) {
+ if ((next('{'), white(), '}' === ch)) return next('}'), object;
+ for (; ch; ) {
+ let latchKeyStart = at;
+ if (
+ ((key = string()),
+ white(),
+ next(':'),
+ Object.hasOwnProperty.call(object, key) &&
+ warning('Duplicate key "' + key + '"', latchKeyStart),
+ (object[key] = value()),
+ white(),
+ '}' === ch)
+ )
+ return next('}'), object;
+ next(','), white();
+ }
+ }
+ error('Bad object');
+ };
+ return (
+ (value = function () {
+ switch ((white(), ch)) {
+ case '{':
+ return object();
+ case '[':
+ return array();
+ case '"':
+ return string();
+ case '-':
+ return number();
+ default:
+ return ch >= '0' && '9' >= ch ? number() : word();
+ }
+ }),
+ function (source: string) {
+ annos = [];
+ let errored = false;
+ text = source;
+ at = 0;
+ ch = ' ';
+ white();
+
+ try {
+ value();
+ } catch (e) {
+ errored = true;
+ annos.push({ type: AnnoTypes.error, at: e.at - 1, text: e.message });
+ }
+ if (!errored && ch) {
+ error('Syntax error');
+ }
+ return { annotations: annos };
+ }
+ );
+};
diff --git a/packages/kbn-monaco/src/xjson/index.ts b/packages/kbn-monaco/src/xjson/index.ts
new file mode 100644
index 0000000000000..35fd35887bc56
--- /dev/null
+++ b/packages/kbn-monaco/src/xjson/index.ts
@@ -0,0 +1,24 @@
+/*
+ * 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 { registerGrammarChecker } from './language';
+
+import { ID } from './constants';
+
+export const XJsonLang = { registerGrammarChecker, ID };
diff --git a/packages/kbn-monaco/src/xjson/language.ts b/packages/kbn-monaco/src/xjson/language.ts
new file mode 100644
index 0000000000000..fe505818d3c9a
--- /dev/null
+++ b/packages/kbn-monaco/src/xjson/language.ts
@@ -0,0 +1,89 @@
+/*
+ * 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 file contains a lot of single setup logic for registering a language globally
+
+import { monaco } from '../monaco';
+import { WorkerProxyService } from './worker_proxy_service';
+import { registerLexerRules } from './lexer_rules';
+import { ID } from './constants';
+// @ts-ignore
+import workerSrc from '!!raw-loader!../../target/public/xjson.editor.worker.js';
+
+const wps = new WorkerProxyService();
+
+// Register rules against shared monaco instance.
+registerLexerRules(monaco);
+
+// In future we will need to make this map languages to workers using "id" and/or "label" values
+// that get passed in.
+// @ts-ignore
+window.MonacoEnvironment = {
+ getWorker: (id: any, label: any) => {
+ // In kibana we will probably build this once and then load with raw-loader
+ const blob = new Blob([workerSrc], { type: 'application/javascript' });
+ return new Worker(URL.createObjectURL(blob));
+ },
+};
+
+monaco.languages.onLanguage(ID, async () => {
+ return wps.setup();
+});
+
+const OWNER = 'XJSON_GRAMMAR_CHECKER';
+export const registerGrammarChecker = (editor: monaco.editor.IEditor) => {
+ const allDisposables: monaco.IDisposable[] = [];
+
+ const updateAnnos = async () => {
+ const { annotations } = await wps.getAnnos();
+ const model = editor.getModel() as monaco.editor.ITextModel;
+ monaco.editor.setModelMarkers(
+ model,
+ OWNER,
+ annotations.map(({ at, text, type }) => {
+ const { column, lineNumber } = model.getPositionAt(at);
+ return {
+ startLineNumber: lineNumber,
+ startColumn: column,
+ endLineNumber: lineNumber,
+ endColumn: column,
+ message: text,
+ severity: type === 'error' ? monaco.MarkerSeverity.Error : monaco.MarkerSeverity.Warning,
+ };
+ })
+ );
+ };
+
+ const onModelAdd = (model: monaco.editor.IModel) => {
+ allDisposables.push(
+ model.onDidChangeContent(async () => {
+ updateAnnos();
+ })
+ );
+
+ updateAnnos();
+ };
+
+ allDisposables.push(monaco.editor.onDidCreateModel(onModelAdd));
+ monaco.editor.getModels().forEach(onModelAdd);
+ return () => {
+ wps.stop();
+ allDisposables.forEach((d) => d.dispose());
+ };
+};
diff --git a/packages/kbn-monaco/src/xjson/lexer_rules/esql.ts b/packages/kbn-monaco/src/xjson/lexer_rules/esql.ts
new file mode 100644
index 0000000000000..e75b1013d3727
--- /dev/null
+++ b/packages/kbn-monaco/src/xjson/lexer_rules/esql.ts
@@ -0,0 +1,270 @@
+/*
+ * 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 { monaco } from '../../monaco';
+
+export const ID = 'esql';
+
+const brackets = [
+ { open: '[', close: ']', token: 'delimiter.square' },
+ { open: '(', close: ')', token: 'delimiter.parenthesis' },
+];
+
+const keywords = [
+ 'describe',
+ 'between',
+ 'in',
+ 'like',
+ 'not',
+ 'and',
+ 'or',
+ 'desc',
+ 'select',
+ 'from',
+ 'where',
+ 'having',
+ 'group',
+ 'by',
+ 'order',
+ 'asc',
+ 'desc',
+ 'pivot',
+ 'for',
+ 'in',
+ 'as',
+ 'show',
+ 'columns',
+ 'include',
+ 'frozen',
+ 'tables',
+ 'escape',
+ 'limit',
+ 'rlike',
+ 'all',
+ 'distinct',
+ 'is',
+];
+const builtinFunctions = [
+ 'avg',
+ 'count',
+ 'first',
+ 'first_value',
+ 'last',
+ 'last_value',
+ 'max',
+ 'min',
+ 'sum',
+ 'kurtosis',
+ 'mad',
+ 'percentile',
+ 'percentile_rank',
+ 'skewness',
+ 'stddev_pop',
+ 'sum_of_squares',
+ 'var_pop',
+ 'histogram',
+ 'case',
+ 'coalesce',
+ 'greatest',
+ 'ifnull',
+ 'iif',
+ 'isnull',
+ 'least',
+ 'nullif',
+ 'nvl',
+ 'curdate',
+ 'current_date',
+ 'current_time',
+ 'current_timestamp',
+ 'curtime',
+ 'dateadd',
+ 'datediff',
+ 'datepart',
+ 'datetrunc',
+ 'date_add',
+ 'date_diff',
+ 'date_part',
+ 'date_trunc',
+ 'day',
+ 'dayname',
+ 'dayofmonth',
+ 'dayofweek',
+ 'dayofyear',
+ 'day_name',
+ 'day_of_month',
+ 'day_of_week',
+ 'day_of_year',
+ 'dom',
+ 'dow',
+ 'doy',
+ 'hour',
+ 'hour_of_day',
+ 'idow',
+ 'isodayofweek',
+ 'isodow',
+ 'isoweek',
+ 'isoweekofyear',
+ 'iso_day_of_week',
+ 'iso_week_of_year',
+ 'iw',
+ 'iwoy',
+ 'minute',
+ 'minute_of_day',
+ 'minute_of_hour',
+ 'month',
+ 'monthname',
+ 'month_name',
+ 'month_of_year',
+ 'now',
+ 'quarter',
+ 'second',
+ 'second_of_minute',
+ 'timestampadd',
+ 'timestampdiff',
+ 'timestamp_add',
+ 'timestamp_diff',
+ 'today',
+ 'week',
+ 'week_of_year',
+ 'year',
+ 'abs',
+ 'acos',
+ 'asin',
+ 'atan',
+ 'atan2',
+ 'cbrt',
+ 'ceil',
+ 'ceiling',
+ 'cos',
+ 'cosh',
+ 'cot',
+ 'degrees',
+ 'e',
+ 'exp',
+ 'expm1',
+ 'floor',
+ 'log',
+ 'log10',
+ 'mod',
+ 'pi',
+ 'power',
+ 'radians',
+ 'rand',
+ 'random',
+ 'round',
+ 'sign',
+ 'signum|sin',
+ 'sinh',
+ 'sqrt',
+ 'tan',
+ 'truncate',
+ 'ascii',
+ 'bit_length',
+ 'char',
+ 'character_length',
+ 'char_length',
+ 'concat',
+ 'insert',
+ 'lcase',
+ 'left',
+ 'length',
+ 'locate',
+ 'ltrim',
+ 'octet_length',
+ 'position',
+ 'repeat',
+ 'replace',
+ 'right',
+ 'rtrim',
+ 'space',
+ 'substring',
+ 'ucase',
+ 'cast',
+ 'convert',
+ 'database',
+ 'user',
+ 'st_astext',
+ 'st_aswkt',
+ 'st_distance',
+ 'st_geometrytype',
+ 'st_geomfromtext',
+ 'st_wkttosql',
+ 'st_x',
+ 'st_y',
+ 'st_z',
+ 'score',
+];
+
+export const lexerRules = {
+ defaultToken: 'invalid',
+ ignoreCase: true,
+ tokenPostfix: '',
+ keywords,
+ builtinFunctions,
+ brackets,
+ tokenizer: {
+ root: [
+ [
+ /[a-zA-Z_$][a-zA-Z0-9_$]*\b/,
+ {
+ cases: {
+ '@keywords': 'keyword',
+ '@builtinFunctions': 'identifier',
+ '@default': 'identifier',
+ },
+ },
+ ],
+ [/[()]/, '@brackets'],
+ [/--.*$/, 'comment'],
+ [/\/\*/, 'comment', '@comment'],
+ [/\/.*$/, 'comment'],
+
+ [/".*?"/, 'string'],
+
+ [/'.*?'/, 'constant'],
+ [/`.*?`/, 'string'],
+ // whitespace
+ [/[ \t\r\n]+/, { token: '@whitespace' }],
+ [/[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b/, 'entity.name.function'],
+ [/⇐|<⇒|\*|\.|\:\:|\+|\-|\/|\/\/|%|&|\^|~|<|>|<=|=>|==|!=|<>|=/, 'keyword.operator'],
+ [/[\(]/, 'paren.lparen'],
+ [/[\)]/, 'paren.rparen'],
+ [/\s+/, 'text'],
+ ],
+ numbers: [
+ [/0[xX][0-9a-fA-F]*/, 'number'],
+ [/[$][+-]*\d*(\.\d*)?/, 'number'],
+ [/((\d+(\.\d*)?)|(\.\d+))([eE][\-+]?\d+)?/, 'number'],
+ ],
+ strings: [
+ [/N'/, { token: 'string', next: '@string' }],
+ [/'/, { token: 'string', next: '@string' }],
+ ],
+ string: [
+ [/[^']+/, 'string'],
+ [/''/, 'string'],
+ [/'/, { token: 'string', next: '@pop' }],
+ ],
+ comment: [
+ [/[^\/*]+/, 'comment'],
+ [/\*\//, 'comment', '@pop'],
+ [/[\/*]/, 'comment'],
+ ],
+ },
+} as monaco.languages.IMonarchLanguage;
diff --git a/packages/kbn-monaco/src/xjson/lexer_rules/index.ts b/packages/kbn-monaco/src/xjson/lexer_rules/index.ts
new file mode 100644
index 0000000000000..515de09510a61
--- /dev/null
+++ b/packages/kbn-monaco/src/xjson/lexer_rules/index.ts
@@ -0,0 +1,33 @@
+/*
+ * 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.
+ */
+
+/* eslint-disable-next-line @kbn/eslint/module_migration */
+import * as monaco from 'monaco-editor/esm/vs/editor/editor.api';
+import * as xJson from './xjson';
+import * as esql from './esql';
+import * as painless from './painless';
+
+export const registerLexerRules = (m: typeof monaco) => {
+ m.languages.register({ id: xJson.ID });
+ m.languages.setMonarchTokensProvider(xJson.ID, xJson.lexerRules);
+ m.languages.register({ id: painless.ID });
+ m.languages.setMonarchTokensProvider(painless.ID, painless.lexerRules);
+ m.languages.register({ id: esql.ID });
+ m.languages.setMonarchTokensProvider(esql.ID, esql.lexerRules);
+};
diff --git a/packages/kbn-monaco/src/xjson/lexer_rules/painless.ts b/packages/kbn-monaco/src/xjson/lexer_rules/painless.ts
new file mode 100644
index 0000000000000..676eb3134026a
--- /dev/null
+++ b/packages/kbn-monaco/src/xjson/lexer_rules/painless.ts
@@ -0,0 +1,194 @@
+/*
+ * 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 { monaco } from '../../monaco';
+
+export const ID = 'painless';
+
+/**
+ * Extends the default type for a Monarch language so we can use
+ * attribute references (like @keywords to reference the keywords list)
+ * in the defined tokenizer
+ */
+interface Language extends monaco.languages.IMonarchLanguage {
+ default: string;
+ brackets: any;
+ keywords: string[];
+ symbols: RegExp;
+ escapes: RegExp;
+ digits: RegExp;
+ primitives: string[];
+ octaldigits: RegExp;
+ binarydigits: RegExp;
+ constants: string[];
+ operators: string[];
+}
+
+export const lexerRules = {
+ default: 'invalid',
+ tokenPostfix: '',
+ // painless does not use < >, so we define our own
+ brackets: [
+ ['{', '}', 'delimiter.curly'],
+ ['[', ']', 'delimiter.square'],
+ ['(', ')', 'delimiter.parenthesis'],
+ ],
+ keywords: [
+ 'if',
+ 'in',
+ 'else',
+ 'while',
+ 'do',
+ 'for',
+ 'continue',
+ 'break',
+ 'return',
+ 'new',
+ 'try',
+ 'catch',
+ 'throw',
+ 'this',
+ 'instanceof',
+ ],
+ primitives: ['void', 'boolean', 'byte', 'short', 'char', 'int', 'long', 'float', 'double', 'def'],
+ constants: ['true', 'false'],
+ operators: [
+ '=',
+ '>',
+ '<',
+ '!',
+ '~',
+ '?',
+ '?:',
+ '?.',
+ ':',
+ '==',
+ '===',
+ '<=',
+ '>=',
+ '!=',
+ '!==',
+ '&&',
+ '||',
+ '++',
+ '--',
+ '+',
+ '-',
+ '*',
+ '/',
+ '&',
+ '|',
+ '^',
+ '%',
+ '<<',
+ '>>',
+ '>>>',
+ '+=',
+ '-=',
+ '*=',
+ '/=',
+ '&=',
+ '|=',
+ '^=',
+ '%=',
+ '<<=',
+ '>>=',
+ '>>>=',
+ '->',
+ '::',
+ '=~',
+ '==~',
+ ],
+ symbols: /[=> {
+ worker.initialize((ctx: any, createData: any) => {
+ return new XJsonWorker(ctx);
+ });
+};
diff --git a/packages/kbn-monaco/src/xjson/worker/xjson_worker.ts b/packages/kbn-monaco/src/xjson/worker/xjson_worker.ts
new file mode 100644
index 0000000000000..501adcacb6990
--- /dev/null
+++ b/packages/kbn-monaco/src/xjson/worker/xjson_worker.ts
@@ -0,0 +1,35 @@
+/*
+ * 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.
+ */
+
+/* eslint-disable-next-line @kbn/eslint/module_migration */
+import * as monaco from 'monaco-editor/esm/vs/editor/editor.api';
+import { createParser } from '../grammar';
+
+export class XJsonWorker {
+ constructor(private ctx: monaco.worker.IWorkerContext) {}
+ private parser: any;
+
+ async parse() {
+ if (!this.parser) {
+ this.parser = createParser();
+ }
+ const [model] = this.ctx.getMirrorModels();
+ return this.parser(model.getValue());
+ }
+}
diff --git a/packages/kbn-monaco/src/xjson/worker_proxy_service.ts b/packages/kbn-monaco/src/xjson/worker_proxy_service.ts
new file mode 100644
index 0000000000000..17d6d56e51e59
--- /dev/null
+++ b/packages/kbn-monaco/src/xjson/worker_proxy_service.ts
@@ -0,0 +1,55 @@
+/*
+ * 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 { AnnoTypes } from './grammar';
+import { monaco } from '../monaco';
+import { XJsonWorker } from './worker';
+import { ID } from './constants';
+
+export interface Annotation {
+ name?: string;
+ type: AnnoTypes;
+ text: string;
+ at: number;
+}
+
+export interface AnnotationsResponse {
+ annotations: Annotation[];
+}
+
+export class WorkerProxyService {
+ private worker: monaco.editor.MonacoWebWorker | undefined;
+
+ public async getAnnos(): Promise {
+ if (!this.worker) {
+ throw new Error('Worker Proxy Service has not been setup!');
+ }
+ await this.worker.withSyncedResources(monaco.editor.getModels().map(({ uri }) => uri));
+ const proxy = await this.worker.getProxy();
+ return proxy.parse();
+ }
+
+ public setup() {
+ this.worker = monaco.editor.createWebWorker({ label: ID, moduleId: '' });
+ }
+
+ public stop() {
+ if (this.worker) this.worker.dispose();
+ }
+}
diff --git a/packages/kbn-monaco/tsconfig.json b/packages/kbn-monaco/tsconfig.json
new file mode 100644
index 0000000000000..95acfd32b24dd
--- /dev/null
+++ b/packages/kbn-monaco/tsconfig.json
@@ -0,0 +1,15 @@
+{
+ "extends": "../../tsconfig.json",
+ "compilerOptions": {
+ "outDir": "./target",
+ "declaration": true,
+ "sourceMap": true,
+ "types": [
+ "jest",
+ "node"
+ ]
+ },
+ "include": [
+ "src/**/*"
+ ]
+}
diff --git a/packages/kbn-monaco/webpack.config.js b/packages/kbn-monaco/webpack.config.js
new file mode 100644
index 0000000000000..1a7d8c031670c
--- /dev/null
+++ b/packages/kbn-monaco/webpack.config.js
@@ -0,0 +1,51 @@
+/*
+ * 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.
+ */
+
+const path = require('path');
+
+const createLangWorkerConfig = (lang) => ({
+ mode: 'production',
+ entry: path.resolve(__dirname, 'src', lang, 'worker', `${lang}.worker.ts`),
+ output: {
+ path: path.resolve(__dirname, 'target/public'),
+ filename: `${lang}.editor.worker.js`,
+ },
+ resolve: {
+ modules: ['node_modules'],
+ extensions: ['.js', '.ts', '.tsx'],
+ },
+ stats: 'errors-only',
+ module: {
+ rules: [
+ {
+ test: /\.(js|ts)$/,
+ exclude: /node_modules/,
+ use: {
+ loader: 'babel-loader',
+ options: {
+ babelrc: false,
+ presets: [require.resolve('@kbn/babel-preset/webpack_preset')],
+ },
+ },
+ },
+ ],
+ },
+});
+
+module.exports = [createLangWorkerConfig('xjson')];
diff --git a/packages/kbn-monaco/yarn.lock b/packages/kbn-monaco/yarn.lock
new file mode 120000
index 0000000000000..3f82ebc9cdbae
--- /dev/null
+++ b/packages/kbn-monaco/yarn.lock
@@ -0,0 +1 @@
+../../yarn.lock
\ No newline at end of file
diff --git a/packages/kbn-test/package.json b/packages/kbn-test/package.json
index 0ab0048619358..8e2fd1c9182ff 100644
--- a/packages/kbn-test/package.json
+++ b/packages/kbn-test/package.json
@@ -14,6 +14,7 @@
"@kbn/babel-preset": "1.0.0",
"@kbn/dev-utils": "1.0.0",
"@types/parse-link-header": "^1.0.0",
+ "@types/puppeteer": "^3.0.0",
"@types/strip-ansi": "^5.2.1",
"@types/xml2js": "^0.4.5",
"diff": "^4.0.1"
@@ -25,6 +26,7 @@
"getopts": "^2.2.4",
"glob": "^7.1.2",
"parse-link-header": "^1.0.1",
+ "puppeteer": "^3.3.0",
"strip-ansi": "^5.2.0",
"rxjs": "^6.5.3",
"tar-fs": "^1.16.3",
diff --git a/packages/kbn-test/src/index.ts b/packages/kbn-test/src/index.ts
index 585ce8181df5f..0bc7cc664df68 100644
--- a/packages/kbn-test/src/index.ts
+++ b/packages/kbn-test/src/index.ts
@@ -58,3 +58,5 @@ export { runFailedTestsReporterCli } from './failed_tests_reporter';
export { makeJunitReportPath } from './junit_report_path';
export { CI_PARALLEL_PROCESS_PREFIX } from './ci_parallel_process_prefix';
+
+export * from './page_load_metrics';
diff --git a/packages/kbn-test/src/page_load_metrics/capture_page_load_metrics.ts b/packages/kbn-test/src/page_load_metrics/capture_page_load_metrics.ts
new file mode 100644
index 0000000000000..013d49a29a51c
--- /dev/null
+++ b/packages/kbn-test/src/page_load_metrics/capture_page_load_metrics.ts
@@ -0,0 +1,81 @@
+/*
+ * 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 { ToolingLog } from '@kbn/dev-utils';
+import { NavigationOptions, createUrl, navigateToApps } from './navigation';
+
+export async function capturePageLoadMetrics(log: ToolingLog, options: NavigationOptions) {
+ const responsesByPageView = await navigateToApps(log, options);
+
+ const assetSizeMeasurements = new Map();
+
+ const numberOfPagesVisited = responsesByPageView.size;
+
+ for (const [, frameResponses] of responsesByPageView) {
+ for (const [, { url, dataLength }] of frameResponses) {
+ if (url.length === 0) {
+ throw new Error('navigateToApps(); failed to identify the url of the request');
+ }
+ if (assetSizeMeasurements.has(url)) {
+ assetSizeMeasurements.set(url, [dataLength].concat(assetSizeMeasurements.get(url) || []));
+ } else {
+ assetSizeMeasurements.set(url, [dataLength]);
+ }
+ }
+ }
+
+ return Array.from(assetSizeMeasurements.entries())
+ .map(([url, measurements]) => {
+ const baseUrl = createUrl('/', options.appConfig.url);
+ const relativeUrl = url
+ // remove the baseUrl (expect the trailing slash) to make url relative
+ .replace(baseUrl.slice(0, -1), '')
+ // strip the build number from asset urls
+ .replace(/^\/\d+\//, '/');
+ return [relativeUrl, measurements] as const;
+ })
+ .filter(([url, measurements]) => {
+ if (measurements.length !== numberOfPagesVisited) {
+ // ignore urls seen only on some pages
+ return false;
+ }
+
+ if (url.startsWith('data:')) {
+ // ignore data urls since they are already counted by other assets
+ return false;
+ }
+
+ if (url.startsWith('/api/') || url.startsWith('/internal/')) {
+ // ignore api requests since they don't have deterministic sizes
+ return false;
+ }
+
+ const allMetricsAreEqual = measurements.every((x, i) =>
+ i === 0 ? true : x === measurements[i - 1]
+ );
+ if (!allMetricsAreEqual) {
+ throw new Error(`measurements for url [${url}] are not equal [${measurements.join(',')}]`);
+ }
+
+ return true;
+ })
+ .map(([url, measurements]) => {
+ return { group: 'page load asset size', id: url, value: measurements[0] };
+ });
+}
diff --git a/packages/kbn-test/src/page_load_metrics/cli.ts b/packages/kbn-test/src/page_load_metrics/cli.ts
new file mode 100644
index 0000000000000..95421384c79cb
--- /dev/null
+++ b/packages/kbn-test/src/page_load_metrics/cli.ts
@@ -0,0 +1,90 @@
+/*
+ * 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 Url from 'url';
+
+import { run, createFlagError } from '@kbn/dev-utils';
+import { resolve, basename } from 'path';
+import { capturePageLoadMetrics } from './capture_page_load_metrics';
+
+const defaultScreenshotsDir = resolve(__dirname, 'screenshots');
+
+export function runPageLoadMetricsCli() {
+ run(
+ async ({ flags, log }) => {
+ const kibanaUrl = flags['kibana-url'];
+ if (!kibanaUrl || typeof kibanaUrl !== 'string') {
+ throw createFlagError('Expect --kibana-url to be a string');
+ }
+
+ const parsedUrl = Url.parse(kibanaUrl);
+
+ const [username, password] = parsedUrl.auth
+ ? parsedUrl.auth.split(':')
+ : [flags.username, flags.password];
+
+ if (typeof username !== 'string' || typeof password !== 'string') {
+ throw createFlagError(
+ 'Mising username and/or password, either specify in --kibana-url or pass --username and --password'
+ );
+ }
+
+ const headless = !flags.head;
+
+ const screenshotsDir = flags.screenshotsDir || defaultScreenshotsDir;
+
+ if (typeof screenshotsDir !== 'string' || screenshotsDir === basename(screenshotsDir)) {
+ throw createFlagError('Expect screenshotsDir to be valid path string');
+ }
+
+ const metrics = await capturePageLoadMetrics(log, {
+ headless,
+ appConfig: {
+ url: kibanaUrl,
+ username,
+ password,
+ },
+ screenshotsDir,
+ });
+ for (const metric of metrics) {
+ log.info(`${metric.id}: ${metric.value}`);
+ }
+ },
+ {
+ description: `Loads several pages with Puppeteer to capture the size of assets`,
+ flags: {
+ string: ['kibana-url', 'username', 'password', 'screenshotsDir'],
+ boolean: ['head'],
+ default: {
+ username: 'elastic',
+ password: 'changeme',
+ debug: true,
+ screenshotsDir: defaultScreenshotsDir,
+ },
+ help: `
+ --kibana-url Url for Kibana we should connect to, can include login info
+ --head Run puppeteer with graphical user interface
+ --username Set username, defaults to 'elastic'
+ --password Set password, defaults to 'changeme'
+ --screenshotsDir Set screenshots directory, defaults to '${defaultScreenshotsDir}'
+ `,
+ },
+ }
+ );
+}
diff --git a/packages/kbn-test/src/page_load_metrics/event.ts b/packages/kbn-test/src/page_load_metrics/event.ts
new file mode 100644
index 0000000000000..481954bbf672e
--- /dev/null
+++ b/packages/kbn-test/src/page_load_metrics/event.ts
@@ -0,0 +1,34 @@
+/*
+ * 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.
+ */
+
+export interface ResponseReceivedEvent {
+ frameId: string;
+ loaderId: string;
+ requestId: string;
+ response: Record;
+ timestamp: number;
+ type: string;
+}
+
+export interface DataReceivedEvent {
+ encodedDataLength: number;
+ dataLength: number;
+ requestId: string;
+ timestamp: number;
+}
diff --git a/packages/kbn-test/src/page_load_metrics/index.ts b/packages/kbn-test/src/page_load_metrics/index.ts
new file mode 100644
index 0000000000000..4309d558518a6
--- /dev/null
+++ b/packages/kbn-test/src/page_load_metrics/index.ts
@@ -0,0 +1,21 @@
+/*
+ * 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.
+ */
+
+export * from './cli';
+export { capturePageLoadMetrics } from './capture_page_load_metrics';
diff --git a/packages/kbn-test/src/page_load_metrics/navigation.ts b/packages/kbn-test/src/page_load_metrics/navigation.ts
new file mode 100644
index 0000000000000..21dc681951b21
--- /dev/null
+++ b/packages/kbn-test/src/page_load_metrics/navigation.ts
@@ -0,0 +1,165 @@
+/*
+ * 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 Fs from 'fs';
+import Url from 'url';
+import _ from 'lodash';
+import puppeteer from 'puppeteer';
+import { resolve } from 'path';
+import { ToolingLog } from '@kbn/dev-utils';
+import { ResponseReceivedEvent, DataReceivedEvent } from './event';
+
+export interface NavigationOptions {
+ headless: boolean;
+ appConfig: { url: string; username: string; password: string };
+ screenshotsDir: string;
+}
+
+export type NavigationResults = Map>;
+
+interface FrameResponse {
+ url: string;
+ dataLength: number;
+}
+
+function joinPath(pathA: string, pathB: string) {
+ return `${pathA.endsWith('/') ? pathA.slice(0, -1) : pathA}/${
+ pathB.startsWith('/') ? pathB.slice(1) : pathB
+ }`;
+}
+
+export function createUrl(path: string, url: string) {
+ const baseUrl = Url.parse(url);
+ return Url.format({
+ protocol: baseUrl.protocol,
+ hostname: baseUrl.hostname,
+ port: baseUrl.port,
+ pathname: joinPath(baseUrl.pathname || '', path),
+ });
+}
+
+async function loginToKibana(
+ log: ToolingLog,
+ browser: puppeteer.Browser,
+ options: NavigationOptions
+) {
+ log.debug(`log in to the app..`);
+ const page = await browser.newPage();
+ const loginUrl = createUrl('/login', options.appConfig.url);
+ await page.goto(loginUrl, {
+ waitUntil: 'networkidle0',
+ });
+ await page.type('[data-test-subj="loginUsername"]', options.appConfig.username);
+ await page.type('[data-test-subj="loginPassword"]', options.appConfig.password);
+ await page.click('[data-test-subj="loginSubmit"]');
+ await page.waitForNavigation({ waitUntil: 'networkidle0' });
+ await page.close();
+}
+
+export async function navigateToApps(log: ToolingLog, options: NavigationOptions) {
+ const browser = await puppeteer.launch({ headless: options.headless, args: ['--no-sandbox'] });
+ const devToolsResponses: NavigationResults = new Map();
+ const apps = [
+ { path: '/app/discover', locator: '[data-test-subj="discover-sidebar"]' },
+ { path: '/app/home', locator: '[data-test-subj="homeApp"]' },
+ { path: '/app/canvas', locator: '[data-test-subj="create-workpad-button"]' },
+ { path: '/app/maps', locator: '[title="Maps"]' },
+ { path: '/app/apm', locator: '[data-test-subj="apmMainContainer"]' },
+ ];
+
+ await loginToKibana(log, browser, options);
+
+ await Promise.all(
+ apps.map(async (app) => {
+ const page = await browser.newPage();
+ page.setCacheEnabled(false);
+ page.setDefaultNavigationTimeout(0);
+ const frameResponses = new Map();
+ devToolsResponses.set(app.path, frameResponses);
+
+ const client = await page.target().createCDPSession();
+ await client.send('Network.enable');
+
+ function getRequestData(requestId: string) {
+ if (!frameResponses.has(requestId)) {
+ frameResponses.set(requestId, { url: '', dataLength: 0 });
+ }
+
+ return frameResponses.get(requestId)!;
+ }
+
+ client.on('Network.responseReceived', (event: ResponseReceivedEvent) => {
+ getRequestData(event.requestId).url = event.response.url;
+ });
+
+ client.on('Network.dataReceived', (event: DataReceivedEvent) => {
+ getRequestData(event.requestId).dataLength += event.dataLength;
+ });
+
+ const url = createUrl(app.path, options.appConfig.url);
+ log.debug(`goto ${url}`);
+ await page.goto(url, {
+ waitUntil: 'networkidle0',
+ });
+
+ let readyAttempt = 0;
+ let selectorFound = false;
+ while (!selectorFound) {
+ readyAttempt += 1;
+ try {
+ await page.waitForSelector(app.locator, { timeout: 5000 });
+ selectorFound = true;
+ } catch (error) {
+ log.error(
+ `Page '${app.path}' was not loaded properly, unable to find '${
+ app.locator
+ }', url: ${page.url()}`
+ );
+
+ if (readyAttempt < 6) {
+ continue;
+ }
+
+ const failureDir = resolve(options.screenshotsDir, 'failure');
+ const screenshotPath = resolve(
+ failureDir,
+ `${app.path.slice(1).split('/').join('_')}_navigation.png`
+ );
+ Fs.mkdirSync(failureDir, { recursive: true });
+
+ await page.bringToFront();
+ await page.screenshot({
+ path: screenshotPath,
+ type: 'png',
+ fullPage: true,
+ });
+ log.debug(`Saving screenshot to ${screenshotPath}`);
+
+ throw new Error(`Page load timeout: ${app.path} not loaded after 30 seconds`);
+ }
+ }
+
+ await page.close();
+ })
+ );
+
+ await browser.close();
+
+ return devToolsResponses;
+}
diff --git a/packages/kbn-ui-shared-deps/entry.js b/packages/kbn-ui-shared-deps/entry.js
index ab044a6723da7..88e84fc87ae53 100644
--- a/packages/kbn-ui-shared-deps/entry.js
+++ b/packages/kbn-ui-shared-deps/entry.js
@@ -30,8 +30,8 @@ export const KbnI18nReact = require('@kbn/i18n/react');
export const Angular = require('angular');
export const Moment = require('moment');
export const MomentTimezone = require('moment-timezone/moment-timezone');
-export const Monaco = require('./monaco.ts');
-export const MonacoBare = require('monaco-editor/esm/vs/editor/editor.api');
+export const KbnMonaco = require('@kbn/monaco');
+export const MonacoBarePluginApi = require('@kbn/monaco').BarePluginApi;
export const React = require('react');
export const ReactDom = require('react-dom');
export const ReactDomServer = require('react-dom/server');
diff --git a/packages/kbn-ui-shared-deps/index.js b/packages/kbn-ui-shared-deps/index.js
index eb3add68e2866..301d176555847 100644
--- a/packages/kbn-ui-shared-deps/index.js
+++ b/packages/kbn-ui-shared-deps/index.js
@@ -42,9 +42,9 @@ exports.externals = {
'react-intl': '__kbnSharedDeps__.ReactIntl',
'react-router': '__kbnSharedDeps__.ReactRouter',
'react-router-dom': '__kbnSharedDeps__.ReactRouterDom',
- '@kbn/ui-shared-deps/monaco': '__kbnSharedDeps__.Monaco',
+ '@kbn/monaco': '__kbnSharedDeps__.KbnMonaco',
// this is how plugins/consumers from npm load monaco
- 'monaco-editor/esm/vs/editor/editor.api': '__kbnSharedDeps__.MonacoBare',
+ 'monaco-editor/esm/vs/editor/editor.api': '__kbnSharedDeps__.MonacoBarePluginApi',
/**
* big deps which are locked to a single version
diff --git a/packages/kbn-ui-shared-deps/package.json b/packages/kbn-ui-shared-deps/package.json
index 93afa303c8cad..744a656c54a7f 100644
--- a/packages/kbn-ui-shared-deps/package.json
+++ b/packages/kbn-ui-shared-deps/package.json
@@ -13,6 +13,7 @@
"@elastic/eui": "23.3.1",
"@elastic/numeral": "^2.5.0",
"@kbn/i18n": "1.0.0",
+ "@kbn/monaco": "1.0.0",
"abortcontroller-polyfill": "^1.4.0",
"angular": "^1.7.9",
"compression-webpack-plugin": "^3.1.0",
@@ -22,7 +23,6 @@
"jquery": "^3.5.0",
"moment": "^2.24.0",
"moment-timezone": "^0.5.27",
- "monaco-editor": "~0.17.0",
"react": "^16.12.0",
"react-dom": "^16.12.0",
"react-intl": "^2.8.0",
diff --git a/packages/kbn-ui-shared-deps/tsconfig.json b/packages/kbn-ui-shared-deps/tsconfig.json
index 5d981c73f1d21..5aa0f45e4100d 100644
--- a/packages/kbn-ui-shared-deps/tsconfig.json
+++ b/packages/kbn-ui-shared-deps/tsconfig.json
@@ -1,7 +1,4 @@
{
"extends": "../../tsconfig.json",
- "include": [
- "index.d.ts",
- "monaco.ts"
- ]
+ "include": ["index.d.ts", "./monaco"]
}
diff --git a/packages/kbn-ui-shared-deps/webpack.config.js b/packages/kbn-ui-shared-deps/webpack.config.js
index 7295f2e88c530..523927bd64a20 100644
--- a/packages/kbn-ui-shared-deps/webpack.config.js
+++ b/packages/kbn-ui-shared-deps/webpack.config.js
@@ -78,17 +78,6 @@ exports.getWebpackConfig = ({ dev = false } = {}) => ({
test: /\.css$/,
use: [MiniCssExtractPlugin.loader, 'css-loader'],
},
- {
- include: [require.resolve('./monaco.ts')],
- use: [
- {
- loader: 'babel-loader',
- options: {
- presets: [require.resolve('@kbn/babel-preset/webpack_preset')],
- },
- },
- ],
- },
],
},
@@ -96,6 +85,7 @@ exports.getWebpackConfig = ({ dev = false } = {}) => ({
alias: {
moment: MOMENT_SRC,
},
+ extensions: ['.js', '.ts'],
},
optimization: {
diff --git a/rfcs/text/0011_global_search.md b/rfcs/text/0011_global_search.md
index 5ec368a1c2f02..3b2120283d06a 100644
--- a/rfcs/text/0011_global_search.md
+++ b/rfcs/text/0011_global_search.md
@@ -194,7 +194,7 @@ Notes:
### Plugin API
-#### server API
+#### Common types
```ts
/**
@@ -208,6 +208,21 @@ type GlobalSearchResult = Omit & {
url: string;
};
+
+/**
+ * Response returned from the {@link GlobalSearchServiceStart | global search service}'s `find` API
+ */
+type GlobalSearchBatchedResults = {
+ /**
+ * Results for this batch
+ */
+ results: GlobalSearchResult[];
+};
+```
+
+#### server API
+
+```ts
/**
* Options for the server-side {@link GlobalSearchServiceStart.find | find API}
*/
@@ -226,16 +241,6 @@ interface GlobalSearchFindOptions {
aborted$?: Observable;
}
-/**
- * Response returned from the server-side {@link GlobalSearchServiceStart | global search service}'s `find` API
- */
-type GlobalSearchBatchedResults = {
- /**
- * Results for this batch
- */
- results: GlobalSearchResult[];
-};
-
/** @public */
interface GlobalSearchPluginSetup {
registerResultProvider(provider: GlobalSearchResultProvider);
@@ -265,28 +270,6 @@ interface GlobalSearchFindOptions {
aborted$?: Observable;
}
-/**
- * Enhanced {@link GlobalSearchResult | result type} for the client-side,
- * to allow navigating to a given result.
- */
-interface NavigableGlobalSearchResult extends GlobalSearchResult {
- /**
- * Navigate to this result's associated url. If the result is on this kibana instance, user will be redirected to it
- * in a SPA friendly way using `application.navigateToApp`, else, a full page refresh will be performed.
- */
- navigate: () => Promise;
-}
-
-/**
- * Response returned from the client-side {@link GlobalSearchServiceStart | global search service}'s `find` API
- */
-type GlobalSearchBatchedResults = {
- /**
- * Results for this batch
- */
- results: NavigableGlobalSearchResult[];
-};
-
/** @public */
interface GlobalSearchPluginSetup {
registerResultProvider(provider: GlobalSearchResultProvider);
@@ -304,9 +287,6 @@ Notes:
- The `registerResultProvider` setup APIs share the same signature, however the input `GlobalSearchResultProvider`
types are different on the client and server.
- The `find` start API signature got a `KibanaRequest` for `server`, when this parameter is not present for `public`.
-- The `find` API returns a observable of `NavigableGlobalSearchResult` instead of plain `GlobalSearchResult`. This type
- is here to enhance results with a `navigate` method to let the `GlobalSearch` plugin handle the navigation logic, which is
- non-trivial. See the [Redirecting to a result](#redirecting-to-a-result) section for more info.
#### http API
@@ -395,14 +375,11 @@ In current specification, the only conversion step is to transform the `result.u
#### redirecting to a result
-Parsing a relative or absolute result url to perform SPA navigation can be non trivial, and should remains the responsibility
-of the GlobalSearch plugin API.
-
-This is why `NavigableGlobalSearchResult.navigate` has been introduced on the client-side version of the `find` API
+Parsing a relative or absolute result url to perform SPA navigation can be non trivial. This is why `ApplicationService.navigateToUrl` has been introduced on the client-side core API
-When using `navigate` from a result instance, the following logic will be executed:
+When using `navigateToUrl` with the url of a result instance, the following logic will be executed:
-If all these criteria are true for `result.url`:
+If all these criteria are true for `url`:
- (only for absolute URLs) The origin of the URL matches the origin of the browser's current location
- The pathname of the URL starts with the current basePath (eg. /mybasepath/s/my-space)
diff --git a/scripts/page_load_metrics.js b/scripts/page_load_metrics.js
new file mode 100644
index 0000000000000..37500c26e0b20
--- /dev/null
+++ b/scripts/page_load_metrics.js
@@ -0,0 +1,21 @@
+/*
+ * 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.
+ */
+
+require('../src/setup_node_env');
+require('@kbn/test').runPageLoadMetricsCli();
diff --git a/src/cli/cluster/cluster_manager.ts b/src/cli/cluster/cluster_manager.ts
index dec16b63d78f0..09f9bb2333dbe 100644
--- a/src/cli/cluster/cluster_manager.ts
+++ b/src/cli/cluster/cluster_manager.ts
@@ -262,7 +262,7 @@ export class ClusterManager {
...pluginInternalDirsIgnore,
fromRoot('src/legacy/server/sass/__tmp__'),
fromRoot('x-pack/plugins/reporting/.chromium'),
- fromRoot('x-pack/plugins/siem/cypress'),
+ fromRoot('x-pack/plugins/security_solution/cypress'),
fromRoot('x-pack/plugins/apm/e2e'),
fromRoot('x-pack/plugins/apm/scripts'),
fromRoot('x-pack/plugins/canvas/canvas_plugin_src'), // prevents server from restarting twice for Canvas plugin changes,
diff --git a/src/core/server/plugins/plugin_context.ts b/src/core/server/plugins/plugin_context.ts
index 7afb607192cae..f0db3a25e313d 100644
--- a/src/core/server/plugins/plugin_context.ts
+++ b/src/core/server/plugins/plugin_context.ts
@@ -17,7 +17,7 @@
* under the License.
*/
-import { map } from 'rxjs/operators';
+import { map, shareReplay } from 'rxjs/operators';
import { combineLatest } from 'rxjs';
import { CoreContext } from '../core_context';
import { PluginWrapper } from './plugin';
@@ -107,8 +107,8 @@ export function createPluginInitializerContext(
* @param ConfigClass A class (not an instance of a class) that contains a
* static `schema` that we validate the config at the given `path` against.
*/
- create() {
- return coreContext.configService.atPath(pluginManifest.configPath);
+ create() {
+ return coreContext.configService.atPath(pluginManifest.configPath).pipe(shareReplay(1));
},
createIfExists() {
return coreContext.configService.optionalAtPath(pluginManifest.configPath);
diff --git a/src/core/server/saved_objects/migrations/kibana/kibana_migrator.ts b/src/core/server/saved_objects/migrations/kibana/kibana_migrator.ts
index 4f69d45c192e9..69b57a498936e 100644
--- a/src/core/server/saved_objects/migrations/kibana/kibana_migrator.ts
+++ b/src/core/server/saved_objects/migrations/kibana/kibana_migrator.ts
@@ -74,6 +74,7 @@ export class KibanaMigrator {
private readonly status$ = new BehaviorSubject({
status: 'waiting',
});
+ private readonly activeMappings: IndexMapping;
/**
* Creates an instance of KibanaMigrator.
@@ -100,6 +101,9 @@ export class KibanaMigrator {
validateDoc: docValidator(savedObjectValidations || {}),
log: this.log,
});
+ // Building the active mappings (and associated md5sums) is an expensive
+ // operation so we cache the result
+ this.activeMappings = buildActiveMappings(this.mappingProperties);
}
/**
@@ -172,7 +176,7 @@ export class KibanaMigrator {
*
*/
public getActiveMappings(): IndexMapping {
- return buildActiveMappings(this.mappingProperties);
+ return this.activeMappings;
}
/**
diff --git a/src/core/server/saved_objects/routes/integration_tests/bulk_create.test.ts b/src/core/server/saved_objects/routes/integration_tests/bulk_create.test.ts
index 5b52665b6268e..28afdefe1413f 100644
--- a/src/core/server/saved_objects/routes/integration_tests/bulk_create.test.ts
+++ b/src/core/server/saved_objects/routes/integration_tests/bulk_create.test.ts
@@ -21,7 +21,7 @@ import supertest from 'supertest';
import { UnwrapPromise } from '@kbn/utility-types';
import { registerBulkCreateRoute } from '../bulk_create';
import { savedObjectsClientMock } from '../../../../../core/server/mocks';
-import { setupServer } from './test_utils';
+import { setupServer } from '../test_utils';
type setupServerReturn = UnwrapPromise>;
diff --git a/src/core/server/saved_objects/routes/integration_tests/bulk_get.test.ts b/src/core/server/saved_objects/routes/integration_tests/bulk_get.test.ts
index 845bae47b41f2..521e62e16b1d8 100644
--- a/src/core/server/saved_objects/routes/integration_tests/bulk_get.test.ts
+++ b/src/core/server/saved_objects/routes/integration_tests/bulk_get.test.ts
@@ -21,7 +21,7 @@ import supertest from 'supertest';
import { UnwrapPromise } from '@kbn/utility-types';
import { registerBulkGetRoute } from '../bulk_get';
import { savedObjectsClientMock } from '../../../../../core/server/mocks';
-import { setupServer } from './test_utils';
+import { setupServer } from '../test_utils';
type setupServerReturn = UnwrapPromise>;
diff --git a/src/core/server/saved_objects/routes/integration_tests/bulk_update.test.ts b/src/core/server/saved_objects/routes/integration_tests/bulk_update.test.ts
index 6356fc787a8d8..9c888406b0c96 100644
--- a/src/core/server/saved_objects/routes/integration_tests/bulk_update.test.ts
+++ b/src/core/server/saved_objects/routes/integration_tests/bulk_update.test.ts
@@ -21,7 +21,7 @@ import supertest from 'supertest';
import { UnwrapPromise } from '@kbn/utility-types';
import { registerBulkUpdateRoute } from '../bulk_update';
import { savedObjectsClientMock } from '../../../../../core/server/mocks';
-import { setupServer } from './test_utils';
+import { setupServer } from '../test_utils';
type setupServerReturn = UnwrapPromise>;
diff --git a/src/core/server/saved_objects/routes/integration_tests/create.test.ts b/src/core/server/saved_objects/routes/integration_tests/create.test.ts
index 5a53a30209281..ba3d620f8fdb5 100644
--- a/src/core/server/saved_objects/routes/integration_tests/create.test.ts
+++ b/src/core/server/saved_objects/routes/integration_tests/create.test.ts
@@ -21,7 +21,7 @@ import supertest from 'supertest';
import { UnwrapPromise } from '@kbn/utility-types';
import { registerCreateRoute } from '../create';
import { savedObjectsClientMock } from '../../service/saved_objects_client.mock';
-import { setupServer } from './test_utils';
+import { setupServer } from '../test_utils';
type setupServerReturn = UnwrapPromise>;
diff --git a/src/core/server/saved_objects/routes/integration_tests/delete.test.ts b/src/core/server/saved_objects/routes/integration_tests/delete.test.ts
index d4ce4d421dde1..652d267f08fe7 100644
--- a/src/core/server/saved_objects/routes/integration_tests/delete.test.ts
+++ b/src/core/server/saved_objects/routes/integration_tests/delete.test.ts
@@ -21,7 +21,7 @@ import supertest from 'supertest';
import { UnwrapPromise } from '@kbn/utility-types';
import { registerDeleteRoute } from '../delete';
import { savedObjectsClientMock } from '../../../../../core/server/mocks';
-import { setupServer } from './test_utils';
+import { setupServer } from '../test_utils';
type setupServerReturn = UnwrapPromise>;
diff --git a/src/core/server/saved_objects/routes/integration_tests/export.test.ts b/src/core/server/saved_objects/routes/integration_tests/export.test.ts
index bdb2e23f0826d..7b342dde2febe 100644
--- a/src/core/server/saved_objects/routes/integration_tests/export.test.ts
+++ b/src/core/server/saved_objects/routes/integration_tests/export.test.ts
@@ -27,7 +27,7 @@ import supertest from 'supertest';
import { UnwrapPromise } from '@kbn/utility-types';
import { SavedObjectConfig } from '../../saved_objects_config';
import { registerExportRoute } from '../export';
-import { setupServer, createExportableType } from './test_utils';
+import { setupServer, createExportableType } from '../test_utils';
type setupServerReturn = UnwrapPromise>;
const exportSavedObjectsToStream = exportMock.exportSavedObjectsToStream as jest.Mock;
diff --git a/src/core/server/saved_objects/routes/integration_tests/find.test.ts b/src/core/server/saved_objects/routes/integration_tests/find.test.ts
index 7916100e46831..31bda1d6b9cbd 100644
--- a/src/core/server/saved_objects/routes/integration_tests/find.test.ts
+++ b/src/core/server/saved_objects/routes/integration_tests/find.test.ts
@@ -23,7 +23,7 @@ import querystring from 'querystring';
import { UnwrapPromise } from '@kbn/utility-types';
import { registerFindRoute } from '../find';
import { savedObjectsClientMock } from '../../../../../core/server/mocks';
-import { setupServer } from './test_utils';
+import { setupServer } from '../test_utils';
type setupServerReturn = UnwrapPromise>;
diff --git a/src/core/server/saved_objects/routes/integration_tests/import.test.ts b/src/core/server/saved_objects/routes/integration_tests/import.test.ts
index c4a03a0e2e7d2..c4e304a3f892f 100644
--- a/src/core/server/saved_objects/routes/integration_tests/import.test.ts
+++ b/src/core/server/saved_objects/routes/integration_tests/import.test.ts
@@ -22,7 +22,7 @@ import { UnwrapPromise } from '@kbn/utility-types';
import { registerImportRoute } from '../import';
import { savedObjectsClientMock } from '../../../../../core/server/mocks';
import { SavedObjectConfig } from '../../saved_objects_config';
-import { setupServer, createExportableType } from './test_utils';
+import { setupServer, createExportableType } from '../test_utils';
type setupServerReturn = UnwrapPromise>;
diff --git a/src/core/server/saved_objects/routes/integration_tests/log_legacy_import.test.ts b/src/core/server/saved_objects/routes/integration_tests/log_legacy_import.test.ts
index 4bbe3271e0232..0fe07245dda20 100644
--- a/src/core/server/saved_objects/routes/integration_tests/log_legacy_import.test.ts
+++ b/src/core/server/saved_objects/routes/integration_tests/log_legacy_import.test.ts
@@ -21,7 +21,7 @@ import supertest from 'supertest';
import { UnwrapPromise } from '@kbn/utility-types';
import { registerLogLegacyImportRoute } from '../log_legacy_import';
import { loggingServiceMock } from '../../../logging/logging_service.mock';
-import { setupServer } from './test_utils';
+import { setupServer } from '../test_utils';
type setupServerReturn = UnwrapPromise>;
diff --git a/src/core/server/saved_objects/routes/integration_tests/resolve_import_errors.test.ts b/src/core/server/saved_objects/routes/integration_tests/resolve_import_errors.test.ts
index a36f246f9dbc5..27750ec692e5a 100644
--- a/src/core/server/saved_objects/routes/integration_tests/resolve_import_errors.test.ts
+++ b/src/core/server/saved_objects/routes/integration_tests/resolve_import_errors.test.ts
@@ -21,7 +21,7 @@ import supertest from 'supertest';
import { UnwrapPromise } from '@kbn/utility-types';
import { registerResolveImportErrorsRoute } from '../resolve_import_errors';
import { savedObjectsClientMock } from '../../../../../core/server/mocks';
-import { setupServer, createExportableType } from './test_utils';
+import { setupServer, createExportableType } from '../test_utils';
import { SavedObjectConfig } from '../../saved_objects_config';
type setupServerReturn = UnwrapPromise>;
diff --git a/src/core/server/saved_objects/routes/integration_tests/update.test.ts b/src/core/server/saved_objects/routes/integration_tests/update.test.ts
index b0c3d68090db6..eb6eb1cdb6bd9 100644
--- a/src/core/server/saved_objects/routes/integration_tests/update.test.ts
+++ b/src/core/server/saved_objects/routes/integration_tests/update.test.ts
@@ -21,7 +21,7 @@ import supertest from 'supertest';
import { UnwrapPromise } from '@kbn/utility-types';
import { registerUpdateRoute } from '../update';
import { savedObjectsClientMock } from '../../../../../core/server/mocks';
-import { setupServer } from './test_utils';
+import { setupServer } from '../test_utils';
type setupServerReturn = UnwrapPromise>;
diff --git a/src/core/server/saved_objects/routes/integration_tests/test_utils.ts b/src/core/server/saved_objects/routes/test_utils.ts
similarity index 83%
rename from src/core/server/saved_objects/routes/integration_tests/test_utils.ts
rename to src/core/server/saved_objects/routes/test_utils.ts
index 23e0285201dc7..a2227a8033dbd 100644
--- a/src/core/server/saved_objects/routes/integration_tests/test_utils.ts
+++ b/src/core/server/saved_objects/routes/test_utils.ts
@@ -17,14 +17,14 @@
* under the License.
*/
-import { ContextService } from '../../../context';
-import { createHttpServer, createCoreContext } from '../../../http/test_utils';
-import { coreMock } from '../../../mocks';
-import { SavedObjectsType } from '../../types';
+import { ContextService } from '../../context';
+import { createHttpServer, createCoreContext } from '../../http/test_utils';
+import { coreMock } from '../../mocks';
+import { SavedObjectsType } from '../types';
-const coreId = Symbol('core');
+const defaultCoreId = Symbol('core');
-export const setupServer = async () => {
+export const setupServer = async (coreId: symbol = defaultCoreId) => {
const coreContext = createCoreContext({ coreId });
const contextService = new ContextService(coreContext);
diff --git a/src/core/server/saved_objects/service/lib/repository.ts b/src/core/server/saved_objects/service/lib/repository.ts
index e23f8dec5927c..b093fe779cab7 100644
--- a/src/core/server/saved_objects/service/lib/repository.ts
+++ b/src/core/server/saved_objects/service/lib/repository.ts
@@ -136,7 +136,7 @@ export class SavedObjectsRepository {
injectedConstructor: any = SavedObjectsRepository
): ISavedObjectsRepository {
const mappings = migrator.getActiveMappings();
- const allTypes = Object.keys(getRootPropertiesObjects(mappings));
+ const allTypes = typeRegistry.getAllTypes().map((t) => t.name);
const serializer = new SavedObjectsSerializer(typeRegistry);
const visibleTypes = allTypes.filter((type) => !typeRegistry.isHidden(type));
diff --git a/src/core/server/test_utils.ts b/src/core/server/test_utils.ts
index f7e6fbcd0c131..6b16fe3bdef61 100644
--- a/src/core/server/test_utils.ts
+++ b/src/core/server/test_utils.ts
@@ -19,3 +19,4 @@
export { createHttpServer } from './http/test_utils';
export { ServiceStatusLevelSnapshotSerializer } from './status/test_utils';
+export { setupServer } from './saved_objects/routes/test_utils';
diff --git a/src/core/types/index.ts b/src/core/types/index.ts
index 346b4cfce70c1..07d7789d235ec 100644
--- a/src/core/types/index.ts
+++ b/src/core/types/index.ts
@@ -26,3 +26,4 @@ export * from './capabilities';
export * from './app_category';
export * from './ui_settings';
export * from './saved_objects';
+export * from './serializable';
diff --git a/src/core/types/serializable.ts b/src/core/types/serializable.ts
new file mode 100644
index 0000000000000..9e8ea123bea91
--- /dev/null
+++ b/src/core/types/serializable.ts
@@ -0,0 +1,32 @@
+/*
+ * 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.
+ */
+
+export type Serializable =
+ | string
+ | number
+ | boolean
+ | null
+ | SerializableArray
+ | SerializableRecord;
+
+// we need interfaces instead of types here to allow cyclic references
+// eslint-disable-next-line @typescript-eslint/no-empty-interface
+export interface SerializableArray extends Array {}
+// eslint-disable-next-line @typescript-eslint/no-empty-interface
+export interface SerializableRecord extends Record {}
diff --git a/src/dev/build/build_distributables.js b/src/dev/build/build_distributables.js
index 3a8709893565d..66f0c0355c2d9 100644
--- a/src/dev/build/build_distributables.js
+++ b/src/dev/build/build_distributables.js
@@ -30,6 +30,7 @@ import {
CleanTypescriptTask,
CleanNodeBuildsTask,
CleanTask,
+ CopyBinScriptsTask,
CopySourceTask,
CreateArchivesSourcesTask,
CreateArchivesTask,
@@ -110,6 +111,7 @@ export async function buildDistributables(options) {
* run platform-generic build tasks
*/
await run(CopySourceTask);
+ await run(CopyBinScriptsTask);
await run(CreateEmptyDirsAndFilesTask);
await run(CreateReadmeTask);
await run(TranspileBabelTask);
diff --git a/src/dev/build/tasks/bin/copy_bin_scripts_task.js b/src/dev/build/tasks/bin/copy_bin_scripts_task.js
new file mode 100644
index 0000000000000..f620f12b17d88
--- /dev/null
+++ b/src/dev/build/tasks/bin/copy_bin_scripts_task.js
@@ -0,0 +1,31 @@
+/*
+ * 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 { copyAll } from '../../lib';
+
+export const CopyBinScriptsTask = {
+ description: 'Copying bin scripts into platform-generic build directory',
+
+ async run(config, log, build) {
+ await copyAll(
+ config.resolveFromRepo('src/dev/build/tasks/bin/scripts'),
+ build.resolvePath('bin')
+ );
+ },
+};
diff --git a/src/dev/build/tasks/bin/index.js b/src/dev/build/tasks/bin/index.js
new file mode 100644
index 0000000000000..e970ac5ec044b
--- /dev/null
+++ b/src/dev/build/tasks/bin/index.js
@@ -0,0 +1,20 @@
+/*
+ * 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.
+ */
+
+export { CopyBinScriptsTask } from './copy_bin_scripts_task';
diff --git a/bin/kibana b/src/dev/build/tasks/bin/scripts/kibana
similarity index 100%
rename from bin/kibana
rename to src/dev/build/tasks/bin/scripts/kibana
diff --git a/bin/kibana-keystore b/src/dev/build/tasks/bin/scripts/kibana-keystore
similarity index 100%
rename from bin/kibana-keystore
rename to src/dev/build/tasks/bin/scripts/kibana-keystore
diff --git a/bin/kibana-keystore.bat b/src/dev/build/tasks/bin/scripts/kibana-keystore.bat
similarity index 100%
rename from bin/kibana-keystore.bat
rename to src/dev/build/tasks/bin/scripts/kibana-keystore.bat
diff --git a/bin/kibana-plugin b/src/dev/build/tasks/bin/scripts/kibana-plugin
similarity index 100%
rename from bin/kibana-plugin
rename to src/dev/build/tasks/bin/scripts/kibana-plugin
diff --git a/bin/kibana-plugin.bat b/src/dev/build/tasks/bin/scripts/kibana-plugin.bat
similarity index 100%
rename from bin/kibana-plugin.bat
rename to src/dev/build/tasks/bin/scripts/kibana-plugin.bat
diff --git a/bin/kibana.bat b/src/dev/build/tasks/bin/scripts/kibana.bat
similarity index 100%
rename from bin/kibana.bat
rename to src/dev/build/tasks/bin/scripts/kibana.bat
diff --git a/src/dev/build/tasks/copy_source_task.js b/src/dev/build/tasks/copy_source_task.js
index ee9dc159de47f..ddc6d000bca19 100644
--- a/src/dev/build/tasks/copy_source_task.js
+++ b/src/dev/build/tasks/copy_source_task.js
@@ -42,7 +42,6 @@ export const CopySourceTask = {
'!src/es_archiver/**',
'!src/functional_test_runner/**',
'!src/dev/**',
- 'bin/**',
'typings/**',
'webpackShims/**',
'config/kibana.yml',
diff --git a/src/dev/build/tasks/index.js b/src/dev/build/tasks/index.js
index 8105fa8a7d5d4..bafb5a2fe115e 100644
--- a/src/dev/build/tasks/index.js
+++ b/src/dev/build/tasks/index.js
@@ -17,6 +17,7 @@
* under the License.
*/
+export * from './bin';
export * from './build_packages_task';
export * from './clean_tasks';
export * from './copy_source_task';
diff --git a/src/dev/code_coverage/nyc_config/nyc.functional.config.js b/src/dev/code_coverage/nyc_config/nyc.functional.config.js
new file mode 100644
index 0000000000000..20d266ab9e2c3
--- /dev/null
+++ b/src/dev/code_coverage/nyc_config/nyc.functional.config.js
@@ -0,0 +1,31 @@
+/*
+ * 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.
+ */
+
+const defaultExclude = require('@istanbuljs/schema/default-exclude');
+const extraExclude = ['data/optimize/**', 'src/core/server/**', '**/test/**'];
+const path = require('path');
+
+module.exports = {
+ 'temp-dir': process.env.COVERAGE_TEMP_DIR
+ ? path.resolve(process.env.COVERAGE_TEMP_DIR, 'functional')
+ : 'target/kibana-coverage/functional',
+ 'report-dir': 'target/kibana-coverage/functional-combined',
+ reporter: ['html', 'json-summary'],
+ exclude: extraExclude.concat(defaultExclude),
+};
diff --git a/src/dev/code_coverage/nyc_config/nyc.jest.config.js b/src/dev/code_coverage/nyc_config/nyc.jest.config.js
new file mode 100644
index 0000000000000..1f73347837ab3
--- /dev/null
+++ b/src/dev/code_coverage/nyc_config/nyc.jest.config.js
@@ -0,0 +1,28 @@
+/*
+ * 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.
+ */
+
+const path = require('path');
+
+module.exports = {
+ 'temp-dir': process.env.COVERAGE_TEMP_DIR
+ ? path.resolve(process.env.COVERAGE_TEMP_DIR, 'jest')
+ : 'target/kibana-coverage/jest',
+ 'report-dir': 'target/kibana-coverage/jest-combined',
+ reporter: ['html', 'json-summary'],
+};
diff --git a/src/dev/code_coverage/shell_scripts/merge_jest_and_functional.sh b/src/dev/code_coverage/shell_scripts/merge_jest_and_functional.sh
index ff9cb36c894f8..707c6de3f88a0 100644
--- a/src/dev/code_coverage/shell_scripts/merge_jest_and_functional.sh
+++ b/src/dev/code_coverage/shell_scripts/merge_jest_and_functional.sh
@@ -1,10 +1,9 @@
#!/bin/bash
-EXTRACT_START_DIR=tmp/extracted_coverage
-EXTRACT_END_DIR=target/kibana-coverage
-COMBINED_EXTRACT_DIR=/${EXTRACT_START_DIR}/${EXTRACT_END_DIR}
+COVERAGE_TEMP_DIR=/tmp/extracted_coverage/target/kibana-coverage/
+export COVERAGE_TEMP_DIR
echo "### Merge coverage reports"
for x in jest functional; do
- yarn nyc report --temp-dir $COMBINED_EXTRACT_DIR/${x} --report-dir $EXTRACT_END_DIR/${x}-combined --reporter=html --reporter=json-summary
+ yarn nyc report --nycrc-path src/dev/code_coverage/nyc_config/nyc.${x}.config.js
done
diff --git a/src/dev/jest/config.js b/src/dev/jest/config.js
index 497a639ecab56..64db131f5219a 100644
--- a/src/dev/jest/config.js
+++ b/src/dev/jest/config.js
@@ -64,7 +64,8 @@ export default {
'\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$':
'/src/dev/jest/mocks/file_mock.js',
'\\.(css|less|scss)$': '/src/dev/jest/mocks/style_mock.js',
- '\\.ace\\.worker.js$': '/src/dev/jest/mocks/ace_worker_module_mock.js',
+ '\\.ace\\.worker.js$': '/src/dev/jest/mocks/worker_module_mock.js',
+ '\\.editor\\.worker.js$': '/src/dev/jest/mocks/worker_module_mock.js',
'^(!!)?file-loader!': '/src/dev/jest/mocks/file_mock.js',
},
setupFiles: [
diff --git a/src/dev/jest/mocks/ace_worker_module_mock.js b/src/dev/jest/mocks/worker_module_mock.js
similarity index 100%
rename from src/dev/jest/mocks/ace_worker_module_mock.js
rename to src/dev/jest/mocks/worker_module_mock.js
diff --git a/src/dev/storybook/aliases.ts b/src/dev/storybook/aliases.ts
index 416702c56d852..2f785896da8d5 100644
--- a/src/dev/storybook/aliases.ts
+++ b/src/dev/storybook/aliases.ts
@@ -18,7 +18,6 @@
*/
export const storybookAliases = {
- advanced_ui_actions: 'x-pack/plugins/advanced_ui_actions/scripts/storybook.js',
apm: 'x-pack/plugins/apm/scripts/storybook.js',
canvas: 'x-pack/plugins/canvas/scripts/storybook_new.js',
codeeditor: 'src/plugins/kibana_react/public/code_editor/scripts/storybook.ts',
@@ -26,5 +25,6 @@ export const storybookAliases = {
drilldowns: 'x-pack/plugins/drilldowns/scripts/storybook.js',
embeddable: 'src/plugins/embeddable/scripts/storybook.js',
infra: 'x-pack/legacy/plugins/infra/scripts/storybook.js',
- siem: 'x-pack/plugins/siem/scripts/storybook.js',
+ security_solution: 'x-pack/plugins/security_solution/scripts/storybook.js',
+ ui_actions_enhanced: 'x-pack/plugins/ui_actions_enhanced/scripts/storybook.js',
};
diff --git a/src/dev/typescript/projects.ts b/src/dev/typescript/projects.ts
index b368949cc33e1..1e0b631308d9e 100644
--- a/src/dev/typescript/projects.ts
+++ b/src/dev/typescript/projects.ts
@@ -27,8 +27,8 @@ export const PROJECTS = [
new Project(resolve(REPO_ROOT, 'test/tsconfig.json'), { name: 'kibana/test' }),
new Project(resolve(REPO_ROOT, 'x-pack/tsconfig.json')),
new Project(resolve(REPO_ROOT, 'x-pack/test/tsconfig.json'), { name: 'x-pack/test' }),
- new Project(resolve(REPO_ROOT, 'x-pack/plugins/siem/cypress/tsconfig.json'), {
- name: 'siem/cypress',
+ new Project(resolve(REPO_ROOT, 'x-pack/plugins/security_solution/cypress/tsconfig.json'), {
+ name: 'security_solution/cypress',
}),
new Project(resolve(REPO_ROOT, 'x-pack/plugins/apm/e2e/tsconfig.json'), {
name: 'apm/cypress',
diff --git a/src/legacy/core_plugins/kibana/server/ui_setting_defaults.js b/src/legacy/core_plugins/kibana/server/ui_setting_defaults.js
index 0d1b69778263c..b7af6a73e1bc1 100644
--- a/src/legacy/core_plugins/kibana/server/ui_setting_defaults.js
+++ b/src/legacy/core_plugins/kibana/server/ui_setting_defaults.js
@@ -18,53 +18,32 @@
*/
import moment from 'moment-timezone';
-import numeralLanguages from '@elastic/numeral/languages';
import { i18n } from '@kbn/i18n';
import { schema } from '@kbn/config-schema';
import { isRelativeUrl } from '../../../../core/server';
-import { DEFAULT_QUERY_LANGUAGE } from '../../../../plugins/data/common';
export function getUiSettingDefaults() {
const weekdays = moment.weekdays().slice();
const [defaultWeekday] = weekdays;
- // We add the `en` key manually here, since that's not a real numeral locale, but the
- // default fallback in case the locale is not found.
- const numeralLanguageIds = [
- 'en',
- ...numeralLanguages.map(function (numeralLanguage) {
- return numeralLanguage.id;
- }),
- ];
-
- const luceneQueryLanguageLabel = i18n.translate(
- 'kbn.advancedSettings.searchQueryLanguageLucene',
- {
- defaultMessage: 'Lucene',
- }
- );
-
- const queryLanguageSettingName = i18n.translate('kbn.advancedSettings.searchQueryLanguageTitle', {
- defaultMessage: 'Query language',
- });
-
- const requestPreferenceOptionLabels = {
- sessionId: i18n.translate('kbn.advancedSettings.courier.requestPreferenceSessionId', {
- defaultMessage: 'Session ID',
- }),
- custom: i18n.translate('kbn.advancedSettings.courier.requestPreferenceCustom', {
- defaultMessage: 'Custom',
- }),
- none: i18n.translate('kbn.advancedSettings.courier.requestPreferenceNone', {
- defaultMessage: 'None',
- }),
- };
// wrapped in provider so that a new instance is given to each app/test
return {
buildNum: {
readonly: true,
},
+ 'state:storeInSessionStorage': {
+ name: i18n.translate('kbn.advancedSettings.storeUrlTitle', {
+ defaultMessage: 'Store URLs in session storage',
+ }),
+ value: false,
+ description: i18n.translate('kbn.advancedSettings.storeUrlText', {
+ defaultMessage:
+ 'The URL can sometimes grow to be too large for some browsers to handle. ' +
+ 'To counter-act this we are testing if storing parts of the URL in session storage could help. ' +
+ 'Please let us know how it goes!',
+ }),
+ },
defaultRoute: {
name: i18n.translate('kbn.advancedSettings.defaultRoute.defaultRouteTitle', {
defaultMessage: 'Default route',
@@ -89,83 +68,6 @@ export function getUiSettingDefaults() {
'The route must be a relative URL.',
}),
},
- 'query:queryString:options': {
- name: i18n.translate('kbn.advancedSettings.query.queryStringOptionsTitle', {
- defaultMessage: 'Query string options',
- }),
- value: '{ "analyze_wildcard": true }',
- description: i18n.translate('kbn.advancedSettings.query.queryStringOptionsText', {
- defaultMessage:
- '{optionsLink} for the lucene query string parser. Is only used when "{queryLanguage}" is set ' +
- 'to {luceneLanguage}.',
- description:
- 'Part of composite text: kbn.advancedSettings.query.queryStringOptions.optionsLinkText + ' +
- 'kbn.advancedSettings.query.queryStringOptionsText',
- values: {
- optionsLink:
- '' +
- i18n.translate('kbn.advancedSettings.query.queryStringOptions.optionsLinkText', {
- defaultMessage: 'Options',
- }) +
- '',
- luceneLanguage: luceneQueryLanguageLabel,
- queryLanguage: queryLanguageSettingName,
- },
- }),
- type: 'json',
- },
- 'query:allowLeadingWildcards': {
- name: i18n.translate('kbn.advancedSettings.query.allowWildcardsTitle', {
- defaultMessage: 'Allow leading wildcards in query',
- }),
- value: true,
- description: i18n.translate('kbn.advancedSettings.query.allowWildcardsText', {
- defaultMessage:
- 'When set, * is allowed as the first character in a query clause. ' +
- 'Currently only applies when experimental query features are enabled in the query bar. ' +
- 'To disallow leading wildcards in basic lucene queries, use {queryStringOptionsPattern}.',
- values: {
- queryStringOptionsPattern: 'query:queryString:options',
- },
- }),
- },
- 'search:queryLanguage': {
- name: queryLanguageSettingName,
- value: DEFAULT_QUERY_LANGUAGE,
- description: i18n.translate('kbn.advancedSettings.searchQueryLanguageText', {
- defaultMessage:
- 'Query language used by the query bar. KQL is a new language built specifically for Kibana.',
- }),
- type: 'select',
- options: ['lucene', 'kuery'],
- optionLabels: {
- lucene: luceneQueryLanguageLabel,
- kuery: i18n.translate('kbn.advancedSettings.searchQueryLanguageKql', {
- defaultMessage: 'KQL',
- }),
- },
- },
- 'sort:options': {
- name: i18n.translate('kbn.advancedSettings.sortOptionsTitle', {
- defaultMessage: 'Sort options',
- }),
- value: '{ "unmapped_type": "boolean" }',
- description: i18n.translate('kbn.advancedSettings.sortOptionsText', {
- defaultMessage: '{optionsLink} for the Elasticsearch sort parameter',
- description:
- 'Part of composite text: kbn.advancedSettings.sortOptions.optionsLinkText + ' +
- 'kbn.advancedSettings.sortOptionsText',
- values: {
- optionsLink:
- '' +
- i18n.translate('kbn.advancedSettings.sortOptions.optionsLinkText', {
- defaultMessage: 'Options',
- }) +
- '',
- },
- }),
- type: 'json',
- },
dateFormat: {
name: i18n.translate('kbn.advancedSettings.dateFormatTitle', {
defaultMessage: 'Date format',
@@ -261,160 +163,6 @@ export function getUiSettingDefaults() {
},
}),
},
- defaultIndex: {
- name: i18n.translate('kbn.advancedSettings.defaultIndexTitle', {
- defaultMessage: 'Default index',
- }),
- value: null,
- type: 'string',
- description: i18n.translate('kbn.advancedSettings.defaultIndexText', {
- defaultMessage: 'The index to access if no index is set',
- }),
- },
- 'courier:ignoreFilterIfFieldNotInIndex': {
- name: i18n.translate('kbn.advancedSettings.courier.ignoreFilterTitle', {
- defaultMessage: 'Ignore filter(s)',
- }),
- value: false,
- description: i18n.translate('kbn.advancedSettings.courier.ignoreFilterText', {
- defaultMessage:
- 'This configuration enhances support for dashboards containing visualizations accessing dissimilar indexes. ' +
- 'When disabled, all filters are applied to all visualizations. ' +
- 'When enabled, filter(s) will be ignored for a visualization ' +
- `when the visualization's index does not contain the filtering field.`,
- }),
- category: ['search'],
- },
- 'courier:setRequestPreference': {
- name: i18n.translate('kbn.advancedSettings.courier.requestPreferenceTitle', {
- defaultMessage: 'Request preference',
- }),
- value: 'sessionId',
- options: ['sessionId', 'custom', 'none'],
- optionLabels: requestPreferenceOptionLabels,
- type: 'select',
- description: i18n.translate('kbn.advancedSettings.courier.requestPreferenceText', {
- defaultMessage: `Allows you to set which shards handle your search requests.
-
- - {sessionId}: restricts operations to execute all search requests on the same shards.
- This has the benefit of reusing shard caches across requests.
- - {custom}: allows you to define a your own preference.
- Use courier:customRequestPreference to customize your preference value.
- - {none}: means do not set a preference.
- This might provide better performance because requests can be spread across all shard copies.
- However, results might be inconsistent because different shards might be in different refresh states.
-
`,
- values: {
- sessionId: requestPreferenceOptionLabels.sessionId,
- custom: requestPreferenceOptionLabels.custom,
- none: requestPreferenceOptionLabels.none,
- },
- }),
- category: ['search'],
- },
- 'courier:customRequestPreference': {
- name: i18n.translate('kbn.advancedSettings.courier.customRequestPreferenceTitle', {
- defaultMessage: 'Custom request preference',
- }),
- value: '_local',
- type: 'string',
- description: i18n.translate('kbn.advancedSettings.courier.customRequestPreferenceText', {
- defaultMessage:
- '{requestPreferenceLink} used when {setRequestReferenceSetting} is set to {customSettingValue}.',
- description:
- 'Part of composite text: kbn.advancedSettings.courier.customRequestPreference.requestPreferenceLinkText + ' +
- 'kbn.advancedSettings.courier.customRequestPreferenceText',
- values: {
- setRequestReferenceSetting: 'courier:setRequestPreference',
- customSettingValue: '"custom"',
- requestPreferenceLink:
- '' +
- i18n.translate(
- 'kbn.advancedSettings.courier.customRequestPreference.requestPreferenceLinkText',
- {
- defaultMessage: 'Request Preference',
- }
- ) +
- '',
- },
- }),
- category: ['search'],
- },
- 'courier:maxConcurrentShardRequests': {
- name: i18n.translate('kbn.advancedSettings.courier.maxRequestsTitle', {
- defaultMessage: 'Max Concurrent Shard Requests',
- }),
- value: 0,
- type: 'number',
- description: i18n.translate('kbn.advancedSettings.courier.maxRequestsText', {
- defaultMessage:
- 'Controls the {maxRequestsLink} setting used for _msearch requests sent by Kibana. ' +
- 'Set to 0 to disable this config and use the Elasticsearch default.',
- values: {
- maxRequestsLink: `max_concurrent_shard_requests`,
- },
- }),
- category: ['search'],
- },
- 'courier:batchSearches': {
- name: i18n.translate('kbn.advancedSettings.courier.batchSearchesTitle', {
- defaultMessage: 'Batch concurrent searches',
- }),
- value: false,
- type: 'boolean',
- description: i18n.translate('kbn.advancedSettings.courier.batchSearchesText', {
- defaultMessage: `When disabled, dashboard panels will load individually, and search requests will terminate when users navigate
- away or update the query. When enabled, dashboard panels will load together when all of the data is loaded, and
- searches will not terminate.`,
- }),
- deprecation: {
- message: i18n.translate('kbn.advancedSettings.courier.batchSearchesTextDeprecation', {
- defaultMessage: 'This setting is deprecated and will be removed in Kibana 8.0.',
- }),
- docLinksKey: 'kibanaSearchSettings',
- },
- category: ['search'],
- },
- 'search:includeFrozen': {
- name: 'Search in frozen indices',
- description: `Will include frozen indices in results if enabled. Searching through frozen indices
- might increase the search time.`,
- value: false,
- category: ['search'],
- },
- 'histogram:barTarget': {
- name: i18n.translate('kbn.advancedSettings.histogram.barTargetTitle', {
- defaultMessage: 'Target bars',
- }),
- value: 50,
- description: i18n.translate('kbn.advancedSettings.histogram.barTargetText', {
- defaultMessage:
- 'Attempt to generate around this many bars when using "auto" interval in date histograms',
- }),
- },
- 'histogram:maxBars': {
- name: i18n.translate('kbn.advancedSettings.histogram.maxBarsTitle', {
- defaultMessage: 'Maximum bars',
- }),
- value: 100,
- description: i18n.translate('kbn.advancedSettings.histogram.maxBarsText', {
- defaultMessage:
- 'Never show more than this many bars in date histograms, scale values if needed',
- }),
- },
- 'visualize:enableLabs': {
- name: i18n.translate('kbn.advancedSettings.visualizeEnableLabsTitle', {
- defaultMessage: 'Enable experimental visualizations',
- }),
- value: true,
- description: i18n.translate('kbn.advancedSettings.visualizeEnableLabsText', {
- defaultMessage: `Allows users to create, view, and edit experimental visualizations. If disabled,
- only visualizations that are considered production-ready are available to the user.`,
- }),
- category: ['visualization'],
- },
'visualization:tileMap:maxPrecision': {
name: i18n.translate('kbn.advancedSettings.visualization.tileMap.maxPrecisionTitle', {
defaultMessage: 'Maximum tile map precision',
@@ -493,43 +241,6 @@ export function getUiSettingDefaults() {
}),
category: ['visualization'],
},
- 'csv:separator': {
- name: i18n.translate('kbn.advancedSettings.csv.separatorTitle', {
- defaultMessage: 'CSV separator',
- }),
- value: ',',
- description: i18n.translate('kbn.advancedSettings.csv.separatorText', {
- defaultMessage: 'Separate exported values with this string',
- }),
- },
- 'csv:quoteValues': {
- name: i18n.translate('kbn.advancedSettings.csv.quoteValuesTitle', {
- defaultMessage: 'Quote CSV values',
- }),
- value: true,
- description: i18n.translate('kbn.advancedSettings.csv.quoteValuesText', {
- defaultMessage: 'Should values be quoted in csv exports?',
- }),
- },
- 'history:limit': {
- name: i18n.translate('kbn.advancedSettings.historyLimitTitle', {
- defaultMessage: 'History limit',
- }),
- value: 10,
- description: i18n.translate('kbn.advancedSettings.historyLimitText', {
- defaultMessage:
- 'In fields that have history (e.g. query inputs), show this many recent values',
- }),
- },
- 'shortDots:enable': {
- name: i18n.translate('kbn.advancedSettings.shortenFieldsTitle', {
- defaultMessage: 'Shorten fields',
- }),
- value: false,
- description: i18n.translate('kbn.advancedSettings.shortenFieldsText', {
- defaultMessage: 'Shorten long fields, for example, instead of foo.bar.baz, show f.b.baz',
- }),
- },
'truncate:maxHeight': {
name: i18n.translate('kbn.advancedSettings.maxCellHeightTitle', {
defaultMessage: 'Maximum table cell height',
@@ -540,138 +251,6 @@ export function getUiSettingDefaults() {
'The maximum height that a cell in a table should occupy. Set to 0 to disable truncation',
}),
},
- 'format:defaultTypeMap': {
- name: i18n.translate('kbn.advancedSettings.format.defaultTypeMapTitle', {
- defaultMessage: 'Field type format name',
- }),
- value: `{
- "ip": { "id": "ip", "params": {} },
- "date": { "id": "date", "params": {} },
- "date_nanos": { "id": "date_nanos", "params": {}, "es": true },
- "number": { "id": "number", "params": {} },
- "boolean": { "id": "boolean", "params": {} },
- "_source": { "id": "_source", "params": {} },
- "_default_": { "id": "string", "params": {} }
-}`,
- type: 'json',
- description: i18n.translate('kbn.advancedSettings.format.defaultTypeMapText', {
- defaultMessage:
- 'Map of the format name to use by default for each field type. ' +
- '{defaultFormat} is used if the field type is not mentioned explicitly',
- values: {
- defaultFormat: '"_default_"',
- },
- }),
- },
- 'format:number:defaultPattern': {
- name: i18n.translate('kbn.advancedSettings.format.numberFormatTitle', {
- defaultMessage: 'Number format',
- }),
- value: '0,0.[000]',
- type: 'string',
- description: i18n.translate('kbn.advancedSettings.format.numberFormatText', {
- defaultMessage: 'Default {numeralFormatLink} for the "number" format',
- description:
- 'Part of composite text: kbn.advancedSettings.format.numberFormatText + ' +
- 'kbn.advancedSettings.format.numberFormat.numeralFormatLinkText',
- values: {
- numeralFormatLink:
- '' +
- i18n.translate('kbn.advancedSettings.format.numberFormat.numeralFormatLinkText', {
- defaultMessage: 'numeral format',
- }) +
- '',
- },
- }),
- },
- 'format:bytes:defaultPattern': {
- name: i18n.translate('kbn.advancedSettings.format.bytesFormatTitle', {
- defaultMessage: 'Bytes format',
- }),
- value: '0,0.[0]b',
- type: 'string',
- description: i18n.translate('kbn.advancedSettings.format.bytesFormatText', {
- defaultMessage: 'Default {numeralFormatLink} for the "bytes" format',
- description:
- 'Part of composite text: kbn.advancedSettings.format.bytesFormatText + ' +
- 'kbn.advancedSettings.format.bytesFormat.numeralFormatLinkText',
- values: {
- numeralFormatLink:
- '' +
- i18n.translate('kbn.advancedSettings.format.bytesFormat.numeralFormatLinkText', {
- defaultMessage: 'numeral format',
- }) +
- '',
- },
- }),
- },
- 'format:percent:defaultPattern': {
- name: i18n.translate('kbn.advancedSettings.format.percentFormatTitle', {
- defaultMessage: 'Percent format',
- }),
- value: '0,0.[000]%',
- type: 'string',
- description: i18n.translate('kbn.advancedSettings.format.percentFormatText', {
- defaultMessage: 'Default {numeralFormatLink} for the "percent" format',
- description:
- 'Part of composite text: kbn.advancedSettings.format.percentFormatText + ' +
- 'kbn.advancedSettings.format.percentFormat.numeralFormatLinkText',
- values: {
- numeralFormatLink:
- '' +
- i18n.translate('kbn.advancedSettings.format.percentFormat.numeralFormatLinkText', {
- defaultMessage: 'numeral format',
- }) +
- '',
- },
- }),
- },
- 'format:currency:defaultPattern': {
- name: i18n.translate('kbn.advancedSettings.format.currencyFormatTitle', {
- defaultMessage: 'Currency format',
- }),
- value: '($0,0.[00])',
- type: 'string',
- description: i18n.translate('kbn.advancedSettings.format.currencyFormatText', {
- defaultMessage: 'Default {numeralFormatLink} for the "currency" format',
- description:
- 'Part of composite text: kbn.advancedSettings.format.currencyFormatText + ' +
- 'kbn.advancedSettings.format.currencyFormat.numeralFormatLinkText',
- values: {
- numeralFormatLink:
- '' +
- i18n.translate('kbn.advancedSettings.format.currencyFormat.numeralFormatLinkText', {
- defaultMessage: 'numeral format',
- }) +
- '',
- },
- }),
- },
- 'format:number:defaultLocale': {
- name: i18n.translate('kbn.advancedSettings.format.formattingLocaleTitle', {
- defaultMessage: 'Formatting locale',
- }),
- value: 'en',
- type: 'select',
- options: numeralLanguageIds,
- optionLabels: Object.fromEntries(
- numeralLanguages.map((language) => [language.id, language.name])
- ),
- description: i18n.translate('kbn.advancedSettings.format.formattingLocaleText', {
- defaultMessage: `{numeralLanguageLink} locale`,
- description:
- 'Part of composite text: kbn.advancedSettings.format.formattingLocale.numeralLanguageLinkText + ' +
- 'kbn.advancedSettings.format.formattingLocaleText',
- values: {
- numeralLanguageLink:
- '' +
- i18n.translate('kbn.advancedSettings.format.formattingLocale.numeralLanguageLinkText', {
- defaultMessage: 'Numeral language',
- }) +
- '',
- },
- }),
- },
'timepicker:timeDefaults': {
name: i18n.translate('kbn.advancedSettings.timepicker.timeDefaultsTitle', {
defaultMessage: 'Time filter defaults',
@@ -686,120 +265,6 @@ export function getUiSettingDefaults() {
}),
requiresPageReload: true,
},
- 'timepicker:refreshIntervalDefaults': {
- name: i18n.translate('kbn.advancedSettings.timepicker.refreshIntervalDefaultsTitle', {
- defaultMessage: 'Time filter refresh interval',
- }),
- value: `{
- "pause": false,
- "value": 0
-}`,
- type: 'json',
- description: i18n.translate('kbn.advancedSettings.timepicker.refreshIntervalDefaultsText', {
- defaultMessage: `The timefilter's default refresh interval`,
- }),
- requiresPageReload: true,
- },
- 'timepicker:quickRanges': {
- name: i18n.translate('kbn.advancedSettings.timepicker.quickRangesTitle', {
- defaultMessage: 'Time filter quick ranges',
- }),
- value: JSON.stringify(
- [
- {
- from: 'now/d',
- to: 'now/d',
- display: i18n.translate('kbn.advancedSettings.timepicker.today', {
- defaultMessage: 'Today',
- }),
- },
- {
- from: 'now/w',
- to: 'now/w',
- display: i18n.translate('kbn.advancedSettings.timepicker.thisWeek', {
- defaultMessage: 'This week',
- }),
- },
- {
- from: 'now-15m',
- to: 'now',
- display: i18n.translate('kbn.advancedSettings.timepicker.last15Minutes', {
- defaultMessage: 'Last 15 minutes',
- }),
- },
- {
- from: 'now-30m',
- to: 'now',
- display: i18n.translate('kbn.advancedSettings.timepicker.last30Minutes', {
- defaultMessage: 'Last 30 minutes',
- }),
- },
- {
- from: 'now-1h',
- to: 'now',
- display: i18n.translate('kbn.advancedSettings.timepicker.last1Hour', {
- defaultMessage: 'Last 1 hour',
- }),
- },
- {
- from: 'now-24h',
- to: 'now',
- display: i18n.translate('kbn.advancedSettings.timepicker.last24Hours', {
- defaultMessage: 'Last 24 hours',
- }),
- },
- {
- from: 'now-7d',
- to: 'now',
- display: i18n.translate('kbn.advancedSettings.timepicker.last7Days', {
- defaultMessage: 'Last 7 days',
- }),
- },
- {
- from: 'now-30d',
- to: 'now',
- display: i18n.translate('kbn.advancedSettings.timepicker.last30Days', {
- defaultMessage: 'Last 30 days',
- }),
- },
- {
- from: 'now-90d',
- to: 'now',
- display: i18n.translate('kbn.advancedSettings.timepicker.last90Days', {
- defaultMessage: 'Last 90 days',
- }),
- },
- {
- from: 'now-1y',
- to: 'now',
- display: i18n.translate('kbn.advancedSettings.timepicker.last1Year', {
- defaultMessage: 'Last 1 year',
- }),
- },
- ],
- null,
- 2
- ),
- type: 'json',
- description: i18n.translate('kbn.advancedSettings.timepicker.quickRangesText', {
- defaultMessage:
- 'The list of ranges to show in the Quick section of the time filter. This should be an array of objects, ' +
- 'with each object containing "from", "to" (see {acceptedFormatsLink}), and ' +
- '"display" (the title to be displayed).',
- description:
- 'Part of composite text: kbn.advancedSettings.timepicker.quickRangesText + ' +
- 'kbn.advancedSettings.timepicker.quickRanges.acceptedFormatsLinkText',
- values: {
- acceptedFormatsLink:
- `` +
- i18n.translate('kbn.advancedSettings.timepicker.quickRanges.acceptedFormatsLinkText', {
- defaultMessage: 'accepted formats',
- }) +
- '',
- },
- }),
- },
'theme:darkMode': {
name: i18n.translate('kbn.advancedSettings.darkModeTitle', {
defaultMessage: 'Dark mode',
@@ -822,26 +287,6 @@ export function getUiSettingDefaults() {
}),
requiresPageReload: true,
},
- 'filters:pinnedByDefault': {
- name: i18n.translate('kbn.advancedSettings.pinFiltersTitle', {
- defaultMessage: 'Pin filters by default',
- }),
- value: false,
- description: i18n.translate('kbn.advancedSettings.pinFiltersText', {
- defaultMessage: 'Whether the filters should have a global state (be pinned) by default',
- }),
- },
- 'filterEditor:suggestValues': {
- name: i18n.translate('kbn.advancedSettings.suggestFilterValuesTitle', {
- defaultMessage: 'Filter editor suggest values',
- description: '"Filter editor" refers to the UI you create filters in.',
- }),
- value: true,
- description: i18n.translate('kbn.advancedSettings.suggestFilterValuesText', {
- defaultMessage:
- 'Set this property to false to prevent the filter editor from suggesting values for fields.',
- }),
- },
'notifications:banner': {
name: i18n.translate('kbn.advancedSettings.notifications.bannerTitle', {
defaultMessage: 'Custom banner notification',
@@ -930,28 +375,6 @@ export function getUiSettingDefaults() {
type: 'number',
category: ['notifications'],
},
- 'state:storeInSessionStorage': {
- name: i18n.translate('kbn.advancedSettings.storeUrlTitle', {
- defaultMessage: 'Store URLs in session storage',
- }),
- value: false,
- description: i18n.translate('kbn.advancedSettings.storeUrlText', {
- defaultMessage:
- 'The URL can sometimes grow to be too large for some browsers to handle. ' +
- 'To counter-act this we are testing if storing parts of the URL in session storage could help. ' +
- 'Please let us know how it goes!',
- }),
- },
- 'indexPattern:placeholder': {
- name: i18n.translate('kbn.advancedSettings.indexPatternPlaceholderTitle', {
- defaultMessage: 'Index pattern placeholder',
- }),
- value: '',
- description: i18n.translate('kbn.advancedSettings.indexPatternPlaceholderText', {
- defaultMessage:
- 'The placeholder for the "Index pattern name" field in "Management > Index Patterns > Create Index Pattern".',
- }),
- },
'accessibility:disableAnimations': {
name: i18n.translate('kbn.advancedSettings.disableAnimationsTitle', {
defaultMessage: 'Disable Animations',
diff --git a/src/legacy/core_plugins/timelion/public/directives/saved_object_finder.js b/src/legacy/core_plugins/timelion/public/directives/saved_object_finder.js
index 08a347fbf7295..879fab206b99d 100644
--- a/src/legacy/core_plugins/timelion/public/directives/saved_object_finder.js
+++ b/src/legacy/core_plugins/timelion/public/directives/saved_object_finder.js
@@ -29,6 +29,7 @@ import {
PaginateDirectiveProvider,
} from '../../../../../plugins/kibana_legacy/public';
import { PER_PAGE_SETTING } from '../../../../../plugins/saved_objects/common';
+import { VISUALIZE_ENABLE_LABS_SETTING } from '../../../../../plugins/visualizations/public';
const module = uiModules.get('kibana');
@@ -294,7 +295,7 @@ module
prevSearch = filter;
- const isLabsEnabled = config.get('visualize:enableLabs');
+ const isLabsEnabled = config.get(VISUALIZE_ENABLE_LABS_SETTING);
self.service.find(filter).then(function (hits) {
hits.hits = hits.hits.filter(
(hit) => isLabsEnabled || _.get(hit, 'type.stage') !== 'experimental'
diff --git a/src/legacy/server/saved_objects/saved_objects_mixin.js b/src/legacy/server/saved_objects/saved_objects_mixin.js
index 7d84c27bd1ef0..63839b9d0f1d7 100644
--- a/src/legacy/server/saved_objects/saved_objects_mixin.js
+++ b/src/legacy/server/saved_objects/saved_objects_mixin.js
@@ -27,14 +27,13 @@ import {
importSavedObjectsFromStream,
resolveSavedObjectsImportErrors,
} from '../../../core/server/saved_objects';
-import { getRootPropertiesObjects } from '../../../core/server/saved_objects/mappings';
import { convertTypesToLegacySchema } from '../../../core/server/saved_objects/utils';
export function savedObjectsMixin(kbnServer, server) {
const migrator = kbnServer.newPlatform.__internals.kibanaMigrator;
const typeRegistry = kbnServer.newPlatform.start.core.savedObjects.getTypeRegistry();
const mappings = migrator.getActiveMappings();
- const allTypes = Object.keys(getRootPropertiesObjects(mappings));
+ const allTypes = typeRegistry.getAllTypes().map((t) => t.name);
const schema = new SavedObjectsSchema(convertTypesToLegacySchema(typeRegistry.getAllTypes()));
const visibleTypes = allTypes.filter((type) => !schema.isHiddenType(type));
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 229bfb1978a4e..d98770842a0f0 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
@@ -28,6 +28,11 @@ import {
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
} from '../../../../../src/plugins/data/public/search/aggs';
import { ComponentRegistry } from '../../../../../src/plugins/advanced_settings/public/';
+import { UI_SETTINGS } from '../../../../../src/plugins/data/public/';
+import {
+ CSV_SEPARATOR_SETTING,
+ CSV_QUOTE_VALUES_SETTING,
+} from '../../../../../src/plugins/share/public';
const mockObservable = () => {
return {
@@ -49,18 +54,31 @@ let isTimeRangeSelectorEnabled = true;
let isAutoRefreshSelectorEnabled = true;
export const mockUiSettings = {
- get: (item) => {
- return mockUiSettings[item];
+ get: (item, defaultValue) => {
+ const defaultValues = {
+ dateFormat: 'MMM D, YYYY @ HH:mm:ss.SSS',
+ 'dateFormat:tz': 'UTC',
+ [UI_SETTINGS.SHORT_DOTS_ENABLE]: true,
+ [UI_SETTINGS.COURIER_IGNORE_FILTER_IF_FIELD_NOT_IN_INDEX]: true,
+ [UI_SETTINGS.QUERY_ALLOW_LEADING_WILDCARDS]: true,
+ [UI_SETTINGS.QUERY_STRING_OPTIONS]: {},
+ [UI_SETTINGS.FORMAT_CURRENCY_DEFAULT_PATTERN]: '($0,0.[00])',
+ [UI_SETTINGS.FORMAT_NUMBER_DEFAULT_PATTERN]: '0,0.[000]',
+ [UI_SETTINGS.FORMAT_PERCENT_DEFAULT_PATTERN]: '0,0.[000]%',
+ [UI_SETTINGS.FORMAT_NUMBER_DEFAULT_LOCALE]: 'en',
+ [UI_SETTINGS.FORMAT_DEFAULT_TYPE_MAP]: {},
+ [CSV_SEPARATOR_SETTING]: ',',
+ [CSV_QUOTE_VALUES_SETTING]: true,
+ [UI_SETTINGS.SEARCH_QUERY_LANGUAGE]: 'kuery',
+ 'state:storeInSessionStorage': false,
+ };
+
+ return defaultValues[item] || defaultValue;
},
getUpdate$: () => ({
subscribe: sinon.fake(),
}),
isDefault: sinon.fake(),
- 'query:allowLeadingWildcards': true,
- 'query:queryString:options': {},
- 'courier:ignoreFilterIfFieldNotInIndex': true,
- 'dateFormat:tz': 'Browser',
- 'format:defaultTypeMap': {},
};
const mockCoreSetup = {
@@ -236,6 +254,9 @@ export const npSetup = {
},
share: {
register: () => {},
+ urlGenerators: {
+ registerUrlGenerator: () => {},
+ },
},
devTools: {
register: () => {},
@@ -524,6 +545,8 @@ export function __setup__(coreSetup) {
// bootstrap an LP plugin outside of tests)
npSetup.core.application.register = () => {};
+ npSetup.core.uiSettings.get = mockUiSettings.get;
+
// Services that need to be set in the legacy platform since the legacy data
// & vis plugins which previously provided them have been removed.
setSetupServices(npSetup);
@@ -532,6 +555,8 @@ export function __setup__(coreSetup) {
export function __start__(coreStart) {
npStart.core = coreStart;
+ npStart.core.uiSettings.get = mockUiSettings.get;
+
// Services that need to be set in the legacy platform since the legacy data
// & vis plugins which previously provided them have been removed.
setStartServices(npStart);
diff --git a/src/legacy/ui/public/new_platform/set_services.ts b/src/legacy/ui/public/new_platform/set_services.ts
index 9d02ad67b3937..ee92eda064aa8 100644
--- a/src/legacy/ui/public/new_platform/set_services.ts
+++ b/src/legacy/ui/public/new_platform/set_services.ts
@@ -65,6 +65,7 @@ export function setStartServices(npStart: NpStart) {
visualizationsServices.setCapabilities(npStart.core.application.capabilities);
visualizationsServices.setHttp(npStart.core.http);
visualizationsServices.setApplication(npStart.core.application);
+ visualizationsServices.setEmbeddable(npStart.plugins.embeddable);
visualizationsServices.setSavedObjects(npStart.core.savedObjects);
visualizationsServices.setIndexPatterns(npStart.plugins.data.indexPatterns);
visualizationsServices.setFilterManager(npStart.plugins.data.query.filterManager);
diff --git a/src/legacy/ui/public/styles/_legacy/_base.scss b/src/legacy/ui/public/styles/_legacy/_base.scss
index fd0a1335f9685..877ae033ae584 100644
--- a/src/legacy/ui/public/styles/_legacy/_base.scss
+++ b/src/legacy/ui/public/styles/_legacy/_base.scss
@@ -64,10 +64,6 @@ input[type='checkbox'],
padding-bottom: $euiSizeS;
}
- .globalQueryBar {
- padding: 0px $euiSizeS $euiSizeS $euiSizeS;
- }
-
> nav,
> navbar {
z-index: 2 !important;
diff --git a/src/legacy/ui/public/timefilter/setup_router.ts b/src/legacy/ui/public/timefilter/setup_router.ts
index a7492e538b3af..7c25c6aa3166e 100644
--- a/src/legacy/ui/public/timefilter/setup_router.ts
+++ b/src/legacy/ui/public/timefilter/setup_router.ts
@@ -21,10 +21,15 @@ import _ from 'lodash';
import { IScope } from 'angular';
import moment from 'moment';
import chrome from 'ui/chrome';
-import { RefreshInterval, TimeRange, TimefilterContract } from 'src/plugins/data/public';
import { Subscription } from 'rxjs';
import { fatalError } from 'ui/notify/fatal_error';
import { subscribeWithScope } from '../../../../plugins/kibana_legacy/public';
+import {
+ RefreshInterval,
+ TimeRange,
+ TimefilterContract,
+ UI_SETTINGS,
+} from '../../../../plugins/data/public';
// TODO
// remove everything underneath once globalState is no longer an angular service
@@ -38,7 +43,7 @@ export function getTimefilterConfig() {
const settings = chrome.getUiSettingsClient();
return {
timeDefaults: settings.get('timepicker:timeDefaults'),
- refreshIntervalDefaults: settings.get('timepicker:refreshIntervalDefaults'),
+ refreshIntervalDefaults: settings.get(UI_SETTINGS.TIMEPICKER_REFRESH_INTERVAL_DEFAULTS),
};
}
diff --git a/src/plugins/advanced_settings/public/management_app/lib/get_category_name.ts b/src/plugins/advanced_settings/public/management_app/lib/get_category_name.ts
index bf3ac9628754a..31df6875c97d9 100644
--- a/src/plugins/advanced_settings/public/management_app/lib/get_category_name.ts
+++ b/src/plugins/advanced_settings/public/management_app/lib/get_category_name.ts
@@ -46,8 +46,8 @@ const names: Record = {
search: i18n.translate('advancedSettings.categoryNames.searchLabel', {
defaultMessage: 'Search',
}),
- siem: i18n.translate('advancedSettings.categoryNames.siemLabel', {
- defaultMessage: 'SIEM',
+ securitySolution: i18n.translate('advancedSettings.categoryNames.securitySolutionLabel', {
+ defaultMessage: 'Security Solution',
}),
};
diff --git a/src/plugins/charts/public/services/theme/theme.ts b/src/plugins/charts/public/services/theme/theme.ts
index 166e1c539688a..e1e71573caa3a 100644
--- a/src/plugins/charts/public/services/theme/theme.ts
+++ b/src/plugins/charts/public/services/theme/theme.ts
@@ -42,8 +42,10 @@ export class ThemeService {
/** A React hook for consuming the charts theme */
public useChartsTheme = () => {
+ /* eslint-disable-next-line react-hooks/rules-of-hooks */
const [value, update] = useState(this.chartsDefaultTheme);
+ /* eslint-disable-next-line react-hooks/rules-of-hooks */
useEffect(() => {
const s = this.chartsTheme$.subscribe(update);
return () => s.unsubscribe();
diff --git a/src/plugins/console/public/application/containers/editor/editor.tsx b/src/plugins/console/public/application/containers/editor/editor.tsx
index 0bfe837f2cd90..66d3cbab20ac5 100644
--- a/src/plugins/console/public/application/containers/editor/editor.tsx
+++ b/src/plugins/console/public/application/containers/editor/editor.tsx
@@ -47,6 +47,7 @@ export const Editor = memo(({ loading }: Props) => {
INITIAL_PANEL_WIDTH,
]);
+ /* eslint-disable-next-line react-hooks/exhaustive-deps */
const onPanelWidthChange = useCallback(
debounce((widths: number[]) => {
storage.set(StorageKeys.WIDTH, widths);
diff --git a/src/plugins/console/public/application/hooks/use_save_current_text_object.ts b/src/plugins/console/public/application/hooks/use_save_current_text_object.ts
index ab517ba1bfdd1..1bd1a7fb09bd1 100644
--- a/src/plugins/console/public/application/hooks/use_save_current_text_object.ts
+++ b/src/plugins/console/public/application/hooks/use_save_current_text_object.ts
@@ -32,6 +32,7 @@ export const useSaveCurrentTextObject = () => {
const { currentTextObject } = useEditorReadContext();
+ /* eslint-disable-next-line react-hooks/exhaustive-deps */
return useCallback(
throttle(
(text: string) => {
diff --git a/src/plugins/console/server/lib/spec_definitions/js/filter.ts b/src/plugins/console/server/lib/spec_definitions/js/filter.ts
index 27e02f7cf1837..b5e99e610b8ba 100644
--- a/src/plugins/console/server/lib/spec_definitions/js/filter.ts
+++ b/src/plugins/console/server/lib/spec_definitions/js/filter.ts
@@ -58,13 +58,6 @@ filters.limit = {
value: 100,
};
-filters.type = {
- __template: {
- value: 'TYPE',
- },
- value: '{type}',
-};
-
filters.geo_bounding_box = {
__template: {
FIELD: {
diff --git a/src/plugins/dashboard/public/application/dashboard_app_controller.tsx b/src/plugins/dashboard/public/application/dashboard_app_controller.tsx
index 8dd0a766da97b..206ef4f3d4313 100644
--- a/src/plugins/dashboard/public/application/dashboard_app_controller.tsx
+++ b/src/plugins/dashboard/public/application/dashboard_app_controller.tsx
@@ -19,8 +19,9 @@
import _, { uniq } from 'lodash';
import { i18n } from '@kbn/i18n';
-import { EUI_MODAL_CANCEL_BUTTON } from '@elastic/eui';
-import React from 'react';
+import { EUI_MODAL_CANCEL_BUTTON, EuiCheckboxGroup } from '@elastic/eui';
+import { EuiCheckboxGroupIdToSelectedMap } from '@elastic/eui/src/components/form/checkbox/checkbox_group';
+import React, { useState, ReactElement } from 'react';
import ReactDOM from 'react-dom';
import angular from 'angular';
@@ -41,6 +42,7 @@ import {
QueryState,
SavedQuery,
syncQueryStateWithUrl,
+ UI_SETTINGS,
} from '../../../data/public';
import { getSavedObjectFinder, SaveResult, showSaveModal } from '../../../saved_objects/public';
@@ -93,6 +95,25 @@ export interface DashboardAppControllerDependencies extends RenderDeps {
navigation: NavigationStart;
}
+enum UrlParams {
+ SHOW_TOP_MENU = 'show-top-menu',
+ SHOW_QUERY_INPUT = 'show-query-input',
+ SHOW_TIME_FILTER = 'show-time-filter',
+ SHOW_FILTER_BAR = 'show-filter-bar',
+ HIDE_FILTER_BAR = 'hide-filter-bar',
+}
+
+interface UrlParamsSelectedMap {
+ [UrlParams.SHOW_TOP_MENU]: boolean;
+ [UrlParams.SHOW_QUERY_INPUT]: boolean;
+ [UrlParams.SHOW_TIME_FILTER]: boolean;
+ [UrlParams.SHOW_FILTER_BAR]: boolean;
+}
+
+interface UrlParamValues extends Omit {
+ [UrlParams.HIDE_FILTER_BAR]: boolean;
+}
+
export class DashboardAppController {
// Part of the exposed plugin API - do not remove without careful consideration.
appStatus: {
@@ -132,8 +153,16 @@ export class DashboardAppController {
const filterManager = queryService.filterManager;
const queryFilter = filterManager;
const timefilter = queryService.timefilter.timefilter;
- let showSearchBar = true;
- let showQueryBar = true;
+ const isEmbeddedExternally = Boolean($routeParams.embed);
+
+ // url param rules should only apply when embedded (e.g. url?embed=true)
+ const shouldForceDisplay = (param: string): boolean =>
+ isEmbeddedExternally && Boolean($routeParams[param]);
+
+ const forceShowTopNavMenu = shouldForceDisplay(UrlParams.SHOW_TOP_MENU);
+ const forceShowQueryInput = shouldForceDisplay(UrlParams.SHOW_QUERY_INPUT);
+ const forceShowDatePicker = shouldForceDisplay(UrlParams.SHOW_TIME_FILTER);
+ const forceHideFilterBar = shouldForceDisplay(UrlParams.HIDE_FILTER_BAR);
let lastReloadRequestTime = 0;
const dash = ($scope.dash = $route.current.locals.dash);
@@ -250,9 +279,6 @@ export class DashboardAppController {
}
};
- const showFilterBar = () =>
- $scope.model.filters.length > 0 || !dashboardStateManager.getFullScreenMode();
-
const getEmptyScreenProps = (
shouldShowEditHelp: boolean,
isEmptyInReadOnlyMode: boolean
@@ -298,6 +324,7 @@ export class DashboardAppController {
viewMode: dashboardStateManager.getViewMode(),
panels: embeddablesMap,
isFullScreenMode: dashboardStateManager.getFullScreenMode(),
+ isEmbeddedExternally,
isEmptyState: shouldShowEditHelp || shouldShowViewHelp || isEmptyInReadonlyMode,
useMargins: dashboardStateManager.getUseMargins(),
lastReloadRequestTime,
@@ -430,7 +457,8 @@ export class DashboardAppController {
dashboardStateManager.getQuery() || {
query: '',
language:
- localStorage.get('kibana.userQueryLanguage') || uiSettings.get('search:queryLanguage'),
+ localStorage.get('kibana.userQueryLanguage') ||
+ uiSettings.get(UI_SETTINGS.SEARCH_QUERY_LANGUAGE),
},
queryFilter.getFilters()
);
@@ -588,17 +616,33 @@ export class DashboardAppController {
dashboardStateManager.setSavedQueryId(savedQueryId);
};
+ const shouldShowFilterBar = (forceHide: boolean): boolean =>
+ !forceHide && ($scope.model.filters.length > 0 || !dashboardStateManager.getFullScreenMode());
+
+ const shouldShowNavBarComponent = (forceShow: boolean): boolean =>
+ (forceShow || $scope.isVisible) && !dashboardStateManager.getFullScreenMode();
+
const getNavBarProps = () => {
const isFullScreenMode = dashboardStateManager.getFullScreenMode();
const screenTitle = dashboardStateManager.getTitle();
+ const showTopNavMenu = shouldShowNavBarComponent(forceShowTopNavMenu);
+ const showQueryInput = shouldShowNavBarComponent(forceShowQueryInput);
+ const showDatePicker = shouldShowNavBarComponent(forceShowDatePicker);
+ const showQueryBar = showQueryInput || showDatePicker;
+ const showFilterBar = shouldShowFilterBar(forceHideFilterBar);
+ const showSearchBar = showQueryBar || showFilterBar;
+
return {
appName: 'dashboard',
- config: $scope.isVisible ? $scope.topNavMenu : undefined,
+ config: showTopNavMenu ? $scope.topNavMenu : undefined,
className: isFullScreenMode ? 'kbnTopNavMenu-isFullScreen' : undefined,
screenTitle,
+ showTopNavMenu,
showSearchBar,
showQueryBar,
- showFilterBar: showFilterBar(),
+ showQueryInput,
+ showDatePicker,
+ showFilterBar,
indexPatterns: $scope.indexPatterns,
showSaveQuery: $scope.showSaveQuery,
query: $scope.model.query,
@@ -796,7 +840,6 @@ export class DashboardAppController {
} = {};
navActions[TopNavIds.FULL_SCREEN] = () => {
dashboardStateManager.setFullScreenMode(true);
- showQueryBar = false;
updateNavBar();
};
navActions[TopNavIds.EXIT_EDIT_MODE] = () => onChangeViewMode(ViewMode.VIEW);
@@ -921,6 +964,80 @@ export class DashboardAppController {
if (share) {
// the share button is only availabale if "share" plugin contract enabled
navActions[TopNavIds.SHARE] = (anchorElement) => {
+ const EmbedUrlParamExtension = ({
+ setParamValue,
+ }: {
+ setParamValue: (paramUpdate: UrlParamValues) => void;
+ }): ReactElement => {
+ const [urlParamsSelectedMap, setUrlParamsSelectedMap] = useState({
+ [UrlParams.SHOW_TOP_MENU]: false,
+ [UrlParams.SHOW_QUERY_INPUT]: false,
+ [UrlParams.SHOW_TIME_FILTER]: false,
+ [UrlParams.SHOW_FILTER_BAR]: true,
+ });
+
+ const checkboxes = [
+ {
+ id: UrlParams.SHOW_TOP_MENU,
+ label: i18n.translate('dashboard.embedUrlParamExtension.topMenu', {
+ defaultMessage: 'Top menu',
+ }),
+ },
+ {
+ id: UrlParams.SHOW_QUERY_INPUT,
+ label: i18n.translate('dashboard.embedUrlParamExtension.query', {
+ defaultMessage: 'Query',
+ }),
+ },
+ {
+ id: UrlParams.SHOW_TIME_FILTER,
+ label: i18n.translate('dashboard.embedUrlParamExtension.timeFilter', {
+ defaultMessage: 'Time filter',
+ }),
+ },
+ {
+ id: UrlParams.SHOW_FILTER_BAR,
+ label: i18n.translate('dashboard.embedUrlParamExtension.filterBar', {
+ defaultMessage: 'Filter bar',
+ }),
+ },
+ ];
+
+ const handleChange = (param: string): void => {
+ const urlParamsSelectedMapUpdate = {
+ ...urlParamsSelectedMap,
+ [param]: !urlParamsSelectedMap[param as keyof UrlParamsSelectedMap],
+ };
+ setUrlParamsSelectedMap(urlParamsSelectedMapUpdate);
+
+ const urlParamValues = {
+ [UrlParams.SHOW_TOP_MENU]: urlParamsSelectedMap[UrlParams.SHOW_TOP_MENU],
+ [UrlParams.SHOW_QUERY_INPUT]: urlParamsSelectedMap[UrlParams.SHOW_QUERY_INPUT],
+ [UrlParams.SHOW_TIME_FILTER]: urlParamsSelectedMap[UrlParams.SHOW_TIME_FILTER],
+ [UrlParams.HIDE_FILTER_BAR]: !urlParamsSelectedMap[UrlParams.SHOW_FILTER_BAR],
+ [param === UrlParams.SHOW_FILTER_BAR ? UrlParams.HIDE_FILTER_BAR : param]:
+ param === UrlParams.SHOW_FILTER_BAR
+ ? urlParamsSelectedMap[UrlParams.SHOW_FILTER_BAR]
+ : !urlParamsSelectedMap[param as keyof UrlParamsSelectedMap],
+ };
+ setParamValue(urlParamValues);
+ };
+
+ return (
+
+ );
+ };
+
share.toggleShareContextMenu({
anchorElement,
allowEmbed: true,
@@ -933,6 +1050,12 @@ export class DashboardAppController {
title: dash.title,
},
isDirty: dashboardStateManager.getIsDirty(),
+ embedUrlParamExtensions: [
+ {
+ paramName: 'embed',
+ component: EmbedUrlParamExtension,
+ },
+ ],
});
};
}
@@ -953,8 +1076,6 @@ export class DashboardAppController {
const visibleSubscription = chrome.getIsVisible$().subscribe((isVisible) => {
$scope.$evalAsync(() => {
$scope.isVisible = isVisible;
- showSearchBar = isVisible || showFilterBar();
- showQueryBar = !dashboardStateManager.getFullScreenMode() && isVisible;
updateNavBar();
});
});
diff --git a/src/plugins/dashboard/public/application/embeddable/dashboard_container.tsx b/src/plugins/dashboard/public/application/embeddable/dashboard_container.tsx
index 7e25d80c9d619..2121ca4c784bd 100644
--- a/src/plugins/dashboard/public/application/embeddable/dashboard_container.tsx
+++ b/src/plugins/dashboard/public/application/embeddable/dashboard_container.tsx
@@ -57,6 +57,7 @@ export interface DashboardContainerInput extends ContainerInput {
useMargins: boolean;
title: string;
description?: string;
+ isEmbeddedExternally: boolean;
isFullScreenMode: boolean;
panels: {
[panelId: string]: DashboardPanelState;
@@ -105,6 +106,7 @@ export class DashboardContainer extends Container
-
+
,
dom
diff --git a/src/plugins/dashboard/public/application/embeddable/dashboard_container_factory.tsx b/src/plugins/dashboard/public/application/embeddable/dashboard_container_factory.tsx
index a20ba148115a0..22e18ddbf22d5 100644
--- a/src/plugins/dashboard/public/application/embeddable/dashboard_container_factory.tsx
+++ b/src/plugins/dashboard/public/application/embeddable/dashboard_container_factory.tsx
@@ -65,6 +65,7 @@ export class DashboardContainerFactory
public getDefaultInput(): Partial {
return {
panels: {},
+ isEmbeddedExternally: false,
isFullScreenMode: false,
useMargins: true,
};
diff --git a/src/plugins/dashboard/public/application/embeddable/grid/dashboard_grid.test.tsx b/src/plugins/dashboard/public/application/embeddable/grid/dashboard_grid.test.tsx
index 9b7cec2f182ba..9a2610a82b97d 100644
--- a/src/plugins/dashboard/public/application/embeddable/grid/dashboard_grid.test.tsx
+++ b/src/plugins/dashboard/public/application/embeddable/grid/dashboard_grid.test.tsx
@@ -80,6 +80,7 @@ function prepare(props?: Partial) {
dashboardContainer = new DashboardContainer(initialInput, options);
const defaultTestProps: DashboardGridProps = {
container: dashboardContainer,
+ PanelComponent: () => ,
kibana: null as any,
intl: null as any,
};
diff --git a/src/plugins/dashboard/public/application/embeddable/grid/dashboard_grid.tsx b/src/plugins/dashboard/public/application/embeddable/grid/dashboard_grid.tsx
index 19d9ad34e729c..dcd07fe394c7d 100644
--- a/src/plugins/dashboard/public/application/embeddable/grid/dashboard_grid.tsx
+++ b/src/plugins/dashboard/public/application/embeddable/grid/dashboard_grid.tsx
@@ -30,7 +30,7 @@ import React from 'react';
import { Subscription } from 'rxjs';
import ReactGridLayout, { Layout } from 'react-grid-layout';
import { GridData } from '../../../../common';
-import { ViewMode, EmbeddableChildPanel } from '../../../embeddable_plugin';
+import { ViewMode, EmbeddableChildPanel, EmbeddableStart } from '../../../embeddable_plugin';
import { DASHBOARD_GRID_COLUMN_COUNT, DASHBOARD_GRID_HEIGHT } from '../dashboard_constants';
import { DashboardPanelState } from '../types';
import { withKibana } from '../../../../../kibana_react/public';
@@ -115,6 +115,7 @@ const ResponsiveSizedGrid = sizeMe(config)(ResponsiveGrid);
export interface DashboardGridProps extends ReactIntl.InjectedIntlProps {
kibana: DashboardReactContextValue;
+ PanelComponent: EmbeddableStart['EmbeddablePanel'];
container: DashboardContainer;
}
@@ -271,14 +272,7 @@ class DashboardGridUi extends React.Component {
);
diff --git a/src/plugins/dashboard/public/application/embeddable/panel/dashboard_panel_placement.ts b/src/plugins/dashboard/public/application/embeddable/panel/dashboard_panel_placement.ts
index 62a39ee898d3a..1b060c186db97 100644
--- a/src/plugins/dashboard/public/application/embeddable/panel/dashboard_panel_placement.ts
+++ b/src/plugins/dashboard/public/application/embeddable/panel/dashboard_panel_placement.ts
@@ -108,16 +108,32 @@ interface IplacementDirection {
fits: boolean;
}
+/**
+ * Compare grid data by an ending y coordinate. Grid data with a smaller ending y coordinate
+ * comes first.
+ * @param a
+ * @param b
+ */
+function comparePanels(a: GridData, b: GridData): number {
+ if (a.y + a.h < b.y + b.h) {
+ return -1;
+ }
+ if (a.y + a.h > b.y + b.h) {
+ return 1;
+ }
+ // a.y === b.y
+ if (a.x + a.w <= b.x + b.w) {
+ return -1;
+ }
+ return 1;
+}
+
export function placePanelBeside({
width,
height,
currentPanels,
placeBesideId,
}: IPanelPlacementBesideArgs): Omit {
- // const clonedPanels = _.cloneDeep(currentPanels);
- if (!placeBesideId) {
- throw new Error('Place beside method called without placeBesideId');
- }
const panelToPlaceBeside = currentPanels[placeBesideId];
if (!panelToPlaceBeside) {
throw new PanelNotFoundError();
@@ -130,10 +146,11 @@ export function placePanelBeside({
const possiblePlacementDirections: IplacementDirection[] = [
{ grid: { x: beside.x + beside.w, y: beside.y, w: width, h: height }, fits: true }, // right
- { grid: { x: beside.x - width, y: beside.y, w: width, h: height }, fits: true }, // left
+ { grid: { x: 0, y: beside.y + beside.h, w: width, h: height }, fits: true }, // left side of next row
{ grid: { x: beside.x, y: beside.y + beside.h, w: width, h: height }, fits: true }, // bottom
];
+ // first, we check if there is place around the current panel
for (const direction of possiblePlacementDirections) {
if (
direction.grid.x >= 0 &&
@@ -156,13 +173,32 @@ export function placePanelBeside({
}
}
// if we get here that means there is no blank space around the panel we are placing beside. This means it's time to mess up the dashboard's groove. Fun!
- const [, , bottomPlacement] = possiblePlacementDirections;
- for (const currentPanelGrid of otherPanels) {
- if (bottomPlacement.grid.y <= currentPanelGrid.y) {
- const movedPanel = _.cloneDeep(currentPanels[currentPanelGrid.i]);
- movedPanel.gridData.y = movedPanel.gridData.y + bottomPlacement.grid.h;
- currentPanels[currentPanelGrid.i] = movedPanel;
+ /**
+ * 1. sort the panels in the grid
+ * 2. place the cloned panel to the bottom
+ * 3. reposition the panels after the cloned panel in the grid
+ */
+ const grid = otherPanels.sort(comparePanels);
+
+ let position = 0;
+ for (position; position < grid.length; position++) {
+ if (beside.i === grid[position].i) {
+ break;
}
}
+ const bottomPlacement = possiblePlacementDirections[2];
+ // place to the bottom and move all other panels
+ let originalPositionInTheGrid = grid[position + 1].i;
+ const diff =
+ bottomPlacement.grid.y +
+ bottomPlacement.grid.h -
+ currentPanels[originalPositionInTheGrid].gridData.y;
+
+ for (let j = position + 1; j < grid.length; j++) {
+ originalPositionInTheGrid = grid[j].i;
+ const movedPanel = _.cloneDeep(currentPanels[originalPositionInTheGrid]);
+ movedPanel.gridData.y = movedPanel.gridData.y + diff;
+ currentPanels[originalPositionInTheGrid] = movedPanel;
+ }
return bottomPlacement.grid;
}
diff --git a/src/plugins/dashboard/public/application/embeddable/viewport/dashboard_viewport.test.tsx b/src/plugins/dashboard/public/application/embeddable/viewport/dashboard_viewport.test.tsx
index 1b257880b9401..25e451dc7f793 100644
--- a/src/plugins/dashboard/public/application/embeddable/viewport/dashboard_viewport.test.tsx
+++ b/src/plugins/dashboard/public/application/embeddable/viewport/dashboard_viewport.test.tsx
@@ -87,6 +87,7 @@ function getProps(
dashboardContainer = new DashboardContainer(input, options);
const defaultTestProps: DashboardViewportProps = {
container: dashboardContainer,
+ PanelComponent: () => ,
};
return {
diff --git a/src/plugins/dashboard/public/application/embeddable/viewport/dashboard_viewport.tsx b/src/plugins/dashboard/public/application/embeddable/viewport/dashboard_viewport.tsx
index ae239bc27fdba..9ee50426b19bb 100644
--- a/src/plugins/dashboard/public/application/embeddable/viewport/dashboard_viewport.tsx
+++ b/src/plugins/dashboard/public/application/embeddable/viewport/dashboard_viewport.tsx
@@ -19,7 +19,7 @@
import React from 'react';
import { Subscription } from 'rxjs';
-import { PanelState } from '../../../embeddable_plugin';
+import { PanelState, EmbeddableStart } from '../../../embeddable_plugin';
import { DashboardContainer, DashboardReactContextValue } from '../dashboard_container';
import { DashboardGrid } from '../grid';
import { context } from '../../../../../kibana_react/public';
@@ -27,6 +27,7 @@ import { context } from '../../../../../kibana_react/public';
export interface DashboardViewportProps {
container: DashboardContainer;
renderEmpty?: () => React.ReactNode;
+ PanelComponent: EmbeddableStart['EmbeddablePanel'];
}
interface State {
@@ -35,6 +36,7 @@ interface State {
title: string;
description?: string;
panels: { [key: string]: PanelState };
+ isEmbeddedExternally?: boolean;
isEmptyState?: boolean;
}
@@ -51,6 +53,7 @@ export class DashboardViewport extends React.Component
{isFullScreenMode && (
)}
{renderEmpty && renderEmpty()}
@@ -114,8 +121,15 @@ export class DashboardViewport extends React.Component
)}
-
+
);
}
diff --git a/src/plugins/dashboard/public/application/test_helpers/get_sample_dashboard_input.ts b/src/plugins/dashboard/public/application/test_helpers/get_sample_dashboard_input.ts
index 4ceac90672cb3..825a69155ba22 100644
--- a/src/plugins/dashboard/public/application/test_helpers/get_sample_dashboard_input.ts
+++ b/src/plugins/dashboard/public/application/test_helpers/get_sample_dashboard_input.ts
@@ -27,6 +27,7 @@ export function getSampleDashboardInput(
id: '123',
filters: [],
useMargins: false,
+ isEmbeddedExternally: false,
isFullScreenMode: false,
title: 'My Dashboard',
query: {
diff --git a/src/plugins/dashboard/public/plugin.tsx b/src/plugins/dashboard/public/plugin.tsx
index 0de3982039928..a3338ab3bbcbb 100644
--- a/src/plugins/dashboard/public/plugin.tsx
+++ b/src/plugins/dashboard/public/plugin.tsx
@@ -167,15 +167,26 @@ export class DashboardPlugin
const getStartServices = async () => {
const [coreStart, deps] = await core.getStartServices();
- const useHideChrome = () => {
+ const useHideChrome = ({ toggleChrome } = { toggleChrome: true }) => {
React.useEffect(() => {
- coreStart.chrome.setIsVisible(false);
- return () => coreStart.chrome.setIsVisible(true);
- }, []);
+ if (toggleChrome) {
+ coreStart.chrome.setIsVisible(false);
+ }
+
+ return () => {
+ if (toggleChrome) {
+ coreStart.chrome.setIsVisible(true);
+ }
+ };
+ }, [toggleChrome]);
};
- const ExitFullScreenButton: React.FC = (props) => {
- useHideChrome();
+ const ExitFullScreenButton: React.FC<
+ ExitFullScreenButtonProps & {
+ toggleChrome: boolean;
+ }
+ > = ({ toggleChrome, ...props }) => {
+ useHideChrome({ toggleChrome });
return ;
};
return {
diff --git a/src/plugins/data/common/constants.ts b/src/plugins/data/common/constants.ts
index 66a96e3e6e129..8ec72dc1f9a74 100644
--- a/src/plugins/data/common/constants.ts
+++ b/src/plugins/data/common/constants.ts
@@ -18,5 +18,33 @@
*/
export const DEFAULT_QUERY_LANGUAGE = 'kuery';
-export const META_FIELDS_SETTING = 'metaFields';
-export const DOC_HIGHLIGHT_SETTING = 'doc_table:highlight';
+
+export const UI_SETTINGS = {
+ META_FIELDS: 'metaFields',
+ DOC_HIGHLIGHT: 'doc_table:highlight',
+ QUERY_STRING_OPTIONS: 'query:queryString:options',
+ QUERY_ALLOW_LEADING_WILDCARDS: 'query:allowLeadingWildcards',
+ SEARCH_QUERY_LANGUAGE: 'search:queryLanguage',
+ SORT_OPTIONS: 'sort:options',
+ COURIER_IGNORE_FILTER_IF_FIELD_NOT_IN_INDEX: 'courier:ignoreFilterIfFieldNotInIndex',
+ COURIER_SET_REQUEST_PREFERENCE: 'courier:setRequestPreference',
+ COURIER_CUSTOM_REQUEST_PREFERENCE: 'courier:customRequestPreference',
+ COURIER_MAX_CONCURRENT_SHARD_REQUESTS: 'courier:maxConcurrentShardRequests',
+ COURIER_BATCH_SEARCHES: 'courier:batchSearches',
+ SEARCH_INCLUDE_FROZEN: 'search:includeFrozen',
+ HISTOGRAM_BAR_TARGET: 'histogram:barTarget',
+ HISTOGRAM_MAX_BARS: 'histogram:maxBars',
+ HISTORY_LIMIT: 'history:limit',
+ SHORT_DOTS_ENABLE: 'shortDots:enable',
+ FORMAT_DEFAULT_TYPE_MAP: 'format:defaultTypeMap',
+ FORMAT_NUMBER_DEFAULT_PATTERN: 'format:number:defaultPattern',
+ FORMAT_PERCENT_DEFAULT_PATTERN: 'format:percent:defaultPattern',
+ FORMAT_BYTES_DEFAULT_PATTERN: 'format:bytes:defaultPattern',
+ FORMAT_CURRENCY_DEFAULT_PATTERN: 'format:currency:defaultPattern',
+ FORMAT_NUMBER_DEFAULT_LOCALE: 'format:number:defaultLocale',
+ TIMEPICKER_REFRESH_INTERVAL_DEFAULTS: 'timepicker:refreshIntervalDefaults',
+ TIMEPICKER_QUICK_RANGES: 'timepicker:quickRanges',
+ INDEXPATTERN_PLACEHOLDER: 'indexPattern:placeholder',
+ FILTERS_PINNED_BY_DEFAULT: 'filters:pinnedByDefault',
+ FILTERS_EDITOR_SUGGEST_VALUES: 'filterEditor:suggestValues',
+};
diff --git a/src/plugins/data/common/es_query/es_query/get_es_query_config.test.ts b/src/plugins/data/common/es_query/es_query/get_es_query_config.test.ts
index d146d81973d0d..5fa3c67dea400 100644
--- a/src/plugins/data/common/es_query/es_query/get_es_query_config.test.ts
+++ b/src/plugins/data/common/es_query/es_query/get_es_query_config.test.ts
@@ -19,18 +19,19 @@
import { get } from 'lodash';
import { getEsQueryConfig } from './get_es_query_config';
import { IUiSettingsClient } from 'kibana/public';
+import { UI_SETTINGS } from '../../';
const config = ({
get(item: string) {
return get(config, item);
},
- 'query:allowLeadingWildcards': {
+ [UI_SETTINGS.QUERY_ALLOW_LEADING_WILDCARDS]: {
allowLeadingWildcards: true,
},
- 'query:queryString:options': {
+ [UI_SETTINGS.QUERY_STRING_OPTIONS]: {
queryStringOptions: {},
},
- 'courier:ignoreFilterIfFieldNotInIndex': {
+ [UI_SETTINGS.COURIER_IGNORE_FILTER_IF_FIELD_NOT_IN_INDEX]: {
ignoreFilterIfFieldNotInIndex: true,
},
'dateFormat:tz': {
diff --git a/src/plugins/data/common/es_query/es_query/get_es_query_config.ts b/src/plugins/data/common/es_query/es_query/get_es_query_config.ts
index 0a82cf03bdb44..ff8fc5b11b26e 100644
--- a/src/plugins/data/common/es_query/es_query/get_es_query_config.ts
+++ b/src/plugins/data/common/es_query/es_query/get_es_query_config.ts
@@ -18,15 +18,18 @@
*/
import { EsQueryConfig } from './build_es_query';
+import { UI_SETTINGS } from '../../';
interface KibanaConfig {
get(key: string): T;
}
export function getEsQueryConfig(config: KibanaConfig) {
- const allowLeadingWildcards = config.get('query:allowLeadingWildcards');
- const queryStringOptions = config.get('query:queryString:options');
- const ignoreFilterIfFieldNotInIndex = config.get('courier:ignoreFilterIfFieldNotInIndex');
+ const allowLeadingWildcards = config.get(UI_SETTINGS.QUERY_ALLOW_LEADING_WILDCARDS);
+ const queryStringOptions = config.get(UI_SETTINGS.QUERY_STRING_OPTIONS);
+ const ignoreFilterIfFieldNotInIndex = config.get(
+ UI_SETTINGS.COURIER_IGNORE_FILTER_IF_FIELD_NOT_IN_INDEX
+ );
const dateFormatTZ = config.get('dateFormat:tz');
return {
diff --git a/src/plugins/data/common/field_formats/converters/bytes.test.ts b/src/plugins/data/common/field_formats/converters/bytes.test.ts
index 8dad9fc206e72..e0c26170c2907 100644
--- a/src/plugins/data/common/field_formats/converters/bytes.test.ts
+++ b/src/plugins/data/common/field_formats/converters/bytes.test.ts
@@ -18,11 +18,12 @@
*/
import { BytesFormat } from './bytes';
+import { UI_SETTINGS } from '../../constants';
describe('BytesFormat', () => {
const config: Record = {};
- config['format:bytes:defaultPattern'] = '0,0.[000]b';
+ config[UI_SETTINGS.FORMAT_BYTES_DEFAULT_PATTERN] = '0,0.[000]b';
const getConfig = (key: string) => config[key];
diff --git a/src/plugins/data/common/field_formats/converters/number.test.ts b/src/plugins/data/common/field_formats/converters/number.test.ts
index fe36d5b12e873..31c5ea41bf5af 100644
--- a/src/plugins/data/common/field_formats/converters/number.test.ts
+++ b/src/plugins/data/common/field_formats/converters/number.test.ts
@@ -18,11 +18,12 @@
*/
import { NumberFormat } from './number';
+import { UI_SETTINGS } from '../../constants';
describe('NumberFormat', () => {
const config: Record = {};
- config['format:number:defaultPattern'] = '0,0.[000]';
+ config[UI_SETTINGS.FORMAT_NUMBER_DEFAULT_PATTERN] = '0,0.[000]';
const getConfig = (key: string) => config[key];
diff --git a/src/plugins/data/common/field_formats/converters/numeral.ts b/src/plugins/data/common/field_formats/converters/numeral.ts
index a483b5a1e4f99..1d844bca3f89a 100644
--- a/src/plugins/data/common/field_formats/converters/numeral.ts
+++ b/src/plugins/data/common/field_formats/converters/numeral.ts
@@ -24,6 +24,7 @@ import numeralLanguages from '@elastic/numeral/languages';
import { KBN_FIELD_TYPES } from '../../kbn_field_types/types';
import { FieldFormat } from '../field_format';
import { TextContextTypeConvert } from '../types';
+import { UI_SETTINGS } from '../../constants';
const numeralInst = numeral();
@@ -51,7 +52,8 @@ export abstract class NumeralFormat extends FieldFormat {
if (isNaN(val)) return '';
const previousLocale = numeral.language();
- const defaultLocale = (this.getConfig && this.getConfig('format:number:defaultLocale')) || 'en';
+ const defaultLocale =
+ (this.getConfig && this.getConfig(UI_SETTINGS.FORMAT_NUMBER_DEFAULT_LOCALE)) || 'en';
numeral.language(defaultLocale);
const formatted = numeralInst.set(val).format(this.param('pattern'));
diff --git a/src/plugins/data/common/field_formats/converters/percent.test.ts b/src/plugins/data/common/field_formats/converters/percent.test.ts
index 8b26564814af3..754234bdeb78b 100644
--- a/src/plugins/data/common/field_formats/converters/percent.test.ts
+++ b/src/plugins/data/common/field_formats/converters/percent.test.ts
@@ -18,11 +18,12 @@
*/
import { PercentFormat } from './percent';
+import { UI_SETTINGS } from '../../constants';
describe('PercentFormat', () => {
const config: Record = {};
- config['format:percent:defaultPattern'] = '0,0.[000]%';
+ config[UI_SETTINGS.FORMAT_PERCENT_DEFAULT_PATTERN] = '0,0.[000]%';
const getConfig = (key: string) => config[key];
diff --git a/src/plugins/data/common/field_formats/converters/percent.ts b/src/plugins/data/common/field_formats/converters/percent.ts
index ef3b0a1503a98..ecf9c7d19108d 100644
--- a/src/plugins/data/common/field_formats/converters/percent.ts
+++ b/src/plugins/data/common/field_formats/converters/percent.ts
@@ -20,6 +20,7 @@
import { i18n } from '@kbn/i18n';
import { NumeralFormat } from './numeral';
import { TextContextTypeConvert, FIELD_FORMAT_IDS } from '../types';
+import { UI_SETTINGS } from '../../constants';
export class PercentFormat extends NumeralFormat {
static id = FIELD_FORMAT_IDS.PERCENT;
@@ -32,7 +33,7 @@ export class PercentFormat extends NumeralFormat {
allowsNumericalAggregations = true;
getParamDefaults = () => ({
- pattern: this.getConfig!('format:percent:defaultPattern'),
+ pattern: this.getConfig!(UI_SETTINGS.FORMAT_PERCENT_DEFAULT_PATTERN),
fractional: true,
});
diff --git a/src/plugins/data/common/field_formats/converters/source.ts b/src/plugins/data/common/field_formats/converters/source.ts
index 9e50d47bb2624..f00261e00971a 100644
--- a/src/plugins/data/common/field_formats/converters/source.ts
+++ b/src/plugins/data/common/field_formats/converters/source.ts
@@ -22,6 +22,7 @@ import { shortenDottedString } from '../../utils';
import { KBN_FIELD_TYPES } from '../../kbn_field_types/types';
import { FieldFormat } from '../field_format';
import { TextContextTypeConvert, HtmlContextTypeConvert, FIELD_FORMAT_IDS } from '../types';
+import { UI_SETTINGS } from '../../';
/**
* Remove all of the whitespace between html tags
@@ -71,7 +72,7 @@ export class SourceFormat extends FieldFormat {
const formatted = field.indexPattern.formatHit(hit);
const highlightPairs: any[] = [];
const sourcePairs: any[] = [];
- const isShortDots = this.getConfig!('shortDots:enable');
+ const isShortDots = this.getConfig!(UI_SETTINGS.SHORT_DOTS_ENABLE);
keys(formatted).forEach((key) => {
const pairs = highlights[key] ? highlightPairs : sourcePairs;
diff --git a/src/plugins/data/common/field_formats/field_formats_registry.ts b/src/plugins/data/common/field_formats/field_formats_registry.ts
index c04a371066de3..9325485bce75d 100644
--- a/src/plugins/data/common/field_formats/field_formats_registry.ts
+++ b/src/plugins/data/common/field_formats/field_formats_registry.ts
@@ -33,6 +33,7 @@ import { baseFormatters } from './constants/base_formatters';
import { FieldFormat } from './field_format';
import { SerializedFieldFormat } from '../../../expressions/common/types';
import { ES_FIELD_TYPES, KBN_FIELD_TYPES } from '../types';
+import { UI_SETTINGS } from '../';
export class FieldFormatsRegistry {
protected fieldFormats: Map = new Map();
@@ -49,7 +50,7 @@ export class FieldFormatsRegistry {
metaParamsOptions: Record = {},
defaultFieldConverters: FieldFormatInstanceType[] = baseFormatters
) {
- const defaultTypeMap = getConfig('format:defaultTypeMap');
+ const defaultTypeMap = getConfig(UI_SETTINGS.FORMAT_DEFAULT_TYPE_MAP);
this.register(defaultFieldConverters);
this.parseDefaultTypeMap(defaultTypeMap);
this.getConfig = getConfig;
diff --git a/src/plugins/data/public/autocomplete/providers/value_suggestion_provider.ts b/src/plugins/data/public/autocomplete/providers/value_suggestion_provider.ts
index ef7a0e8c3a5ad..a6a45a26f06b3 100644
--- a/src/plugins/data/public/autocomplete/providers/value_suggestion_provider.ts
+++ b/src/plugins/data/public/autocomplete/providers/value_suggestion_provider.ts
@@ -19,7 +19,7 @@
import { memoize } from 'lodash';
import { CoreSetup } from 'src/core/public';
-import { IIndexPattern, IFieldType } from '../../../common';
+import { IIndexPattern, IFieldType, UI_SETTINGS } from '../../../common';
function resolver(title: string, field: IFieldType, query: string, boolFilter: any) {
// Only cache results for a minute
@@ -58,7 +58,9 @@ export const setupValueSuggestionProvider = (core: CoreSetup): ValueSuggestionsG
boolFilter,
signal,
}: ValueSuggestionsGetFnArgs): Promise => {
- const shouldSuggestValues = core!.uiSettings.get('filterEditor:suggestValues');
+ const shouldSuggestValues = core!.uiSettings.get(
+ UI_SETTINGS.FILTERS_EDITOR_SUGGEST_VALUES
+ );
const { title } = indexPattern;
if (field.type === 'boolean') {
diff --git a/src/plugins/data/public/field_formats/field_formats_service.ts b/src/plugins/data/public/field_formats/field_formats_service.ts
index 22c7e90c06130..3ddc8d0b68a5b 100644
--- a/src/plugins/data/public/field_formats/field_formats_service.ts
+++ b/src/plugins/data/public/field_formats/field_formats_service.ts
@@ -18,7 +18,7 @@
*/
import { CoreSetup } from 'src/core/public';
-import { FieldFormatsRegistry } from '../../common';
+import { FieldFormatsRegistry, UI_SETTINGS } from '../../common';
import { deserializeFieldFormat } from './utils/deserialize';
import { FormatFactory } from '../../common/field_formats/utils';
import { baseFormattersPublic } from './constants';
@@ -28,7 +28,7 @@ export class FieldFormatsService {
public setup(core: CoreSetup) {
core.uiSettings.getUpdate$().subscribe(({ key, newValue }) => {
- if (key === 'format:defaultTypeMap') {
+ if (key === UI_SETTINGS.FORMAT_DEFAULT_TYPE_MAP) {
this.fieldFormatsRegistry.parseDefaultTypeMap(newValue);
}
});
diff --git a/src/plugins/data/public/index.ts b/src/plugins/data/public/index.ts
index 0c946fc6e1858..5540039323756 100644
--- a/src/plugins/data/public/index.ts
+++ b/src/plugins/data/public/index.ts
@@ -17,8 +17,6 @@
* under the License.
*/
-import './index.scss';
-
import { PluginInitializerContext } from '../../../core/public';
import { ConfigSchema } from '../config';
@@ -267,6 +265,7 @@ export {
ES_FIELD_TYPES,
KBN_FIELD_TYPES,
IndexPatternAttributes,
+ UI_SETTINGS,
} from '../common';
/*
diff --git a/src/plugins/data/public/index_patterns/index_patterns/index_pattern.ts b/src/plugins/data/public/index_patterns/index_patterns/index_pattern.ts
index 43404c32cb3d4..3d54009d0fdca 100644
--- a/src/plugins/data/public/index_patterns/index_patterns/index_pattern.ts
+++ b/src/plugins/data/public/index_patterns/index_patterns/index_pattern.ts
@@ -33,7 +33,7 @@ import {
KBN_FIELD_TYPES,
IIndexPattern,
IFieldType,
- META_FIELDS_SETTING,
+ UI_SETTINGS,
} from '../../../common';
import { findByTitle } from '../utils';
import { IndexPatternMissingIndices } from '../lib';
@@ -108,8 +108,8 @@ export class IndexPattern implements IIndexPattern {
// which cause problems when being consumed from angular
this.getConfig = getConfig;
- this.shortDotsEnable = this.getConfig('shortDots:enable');
- this.metaFields = this.getConfig(META_FIELDS_SETTING);
+ this.shortDotsEnable = this.getConfig(UI_SETTINGS.SHORT_DOTS_ENABLE);
+ this.metaFields = this.getConfig(UI_SETTINGS.META_FIELDS);
this.createFieldList = getIndexPatternFieldListCreator({
fieldFormats: getFieldFormats(),
@@ -117,8 +117,12 @@ export class IndexPattern implements IIndexPattern {
});
this.fields = this.createFieldList(this, [], this.shortDotsEnable);
- this.fieldsFetcher = createFieldsFetcher(this, apiClient, this.getConfig(META_FIELDS_SETTING));
- this.flattenHit = flattenHitWrapper(this, this.getConfig(META_FIELDS_SETTING));
+ this.fieldsFetcher = createFieldsFetcher(
+ this,
+ apiClient,
+ this.getConfig(UI_SETTINGS.META_FIELDS)
+ );
+ this.flattenHit = flattenHitWrapper(this, this.getConfig(UI_SETTINGS.META_FIELDS));
this.formatHit = formatHitProvider(
this,
getFieldFormats().getDefaultInstance(KBN_FIELD_TYPES.STRING)
diff --git a/src/plugins/data/public/plugin.ts b/src/plugins/data/public/plugin.ts
index 66e8d5a6e739a..06b5cbdfdfdfb 100644
--- a/src/plugins/data/public/plugin.ts
+++ b/src/plugins/data/public/plugin.ts
@@ -17,6 +17,8 @@
* under the License.
*/
+import './index.scss';
+
import {
PluginInitializerContext,
CoreSetup,
diff --git a/src/plugins/data/public/public.api.md b/src/plugins/data/public/public.api.md
index ebb4e9d583bc0..dcdb528ac8b7d 100644
--- a/src/plugins/data/public/public.api.md
+++ b/src/plugins/data/public/public.api.md
@@ -1792,6 +1792,39 @@ export interface TimeRange {
// @public
export type TSearchStrategyProvider = (context: ISearchContext) => ISearchStrategy;
+// Warning: (ae-missing-release-tag) "UI_SETTINGS" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+//
+// @public (undocumented)
+export const UI_SETTINGS: {
+ META_FIELDS: string;
+ DOC_HIGHLIGHT: string;
+ QUERY_STRING_OPTIONS: string;
+ QUERY_ALLOW_LEADING_WILDCARDS: string;
+ SEARCH_QUERY_LANGUAGE: string;
+ SORT_OPTIONS: string;
+ COURIER_IGNORE_FILTER_IF_FIELD_NOT_IN_INDEX: string;
+ COURIER_SET_REQUEST_PREFERENCE: string;
+ COURIER_CUSTOM_REQUEST_PREFERENCE: string;
+ COURIER_MAX_CONCURRENT_SHARD_REQUESTS: string;
+ COURIER_BATCH_SEARCHES: string;
+ SEARCH_INCLUDE_FROZEN: string;
+ HISTOGRAM_BAR_TARGET: string;
+ HISTOGRAM_MAX_BARS: string;
+ HISTORY_LIMIT: string;
+ SHORT_DOTS_ENABLE: string;
+ FORMAT_DEFAULT_TYPE_MAP: string;
+ FORMAT_NUMBER_DEFAULT_PATTERN: string;
+ FORMAT_PERCENT_DEFAULT_PATTERN: string;
+ FORMAT_BYTES_DEFAULT_PATTERN: string;
+ FORMAT_CURRENCY_DEFAULT_PATTERN: string;
+ FORMAT_NUMBER_DEFAULT_LOCALE: string;
+ TIMEPICKER_REFRESH_INTERVAL_DEFAULTS: string;
+ TIMEPICKER_QUICK_RANGES: string;
+ INDEXPATTERN_PLACEHOLDER: string;
+ FILTERS_PINNED_BY_DEFAULT: string;
+ FILTERS_EDITOR_SUGGEST_VALUES: string;
+};
+
// Warnings were encountered during analysis:
//
@@ -1800,52 +1833,52 @@ export type TSearchStrategyProvider = (context: ISearc
// src/plugins/data/common/es_query/filters/match_all_filter.ts:28:3 - (ae-forgotten-export) The symbol "MatchAllFilterMeta" needs to be exported by the entry point index.d.ts
// src/plugins/data/common/es_query/filters/phrase_filter.ts:33:3 - (ae-forgotten-export) The symbol "PhraseFilterMeta" needs to be exported by the entry point index.d.ts
// src/plugins/data/common/es_query/filters/phrases_filter.ts:31:3 - (ae-forgotten-export) The symbol "PhrasesFilterMeta" needs to be exported by the entry point index.d.ts
-// src/plugins/data/public/index.ts:67:23 - (ae-forgotten-export) The symbol "FilterLabel" needs to be exported by the entry point index.d.ts
-// src/plugins/data/public/index.ts:67:23 - (ae-forgotten-export) The symbol "FILTERS" needs to be exported by the entry point index.d.ts
-// src/plugins/data/public/index.ts:67:23 - (ae-forgotten-export) The symbol "getDisplayValueFromFilter" needs to be exported by the entry point index.d.ts
-// src/plugins/data/public/index.ts:67:23 - (ae-forgotten-export) The symbol "generateFilters" needs to be exported by the entry point index.d.ts
-// src/plugins/data/public/index.ts:67:23 - (ae-forgotten-export) The symbol "changeTimeFilter" needs to be exported by the entry point index.d.ts
-// src/plugins/data/public/index.ts:67:23 - (ae-forgotten-export) The symbol "convertRangeFilterToTimeRangeString" needs to be exported by the entry point index.d.ts
-// src/plugins/data/public/index.ts:67:23 - (ae-forgotten-export) The symbol "extractTimeFilter" needs to be exported by the entry point index.d.ts
-// src/plugins/data/public/index.ts:138:21 - (ae-forgotten-export) The symbol "buildEsQuery" needs to be exported by the entry point index.d.ts
-// src/plugins/data/public/index.ts:138:21 - (ae-forgotten-export) The symbol "getEsQueryConfig" needs to be exported by the entry point index.d.ts
-// src/plugins/data/public/index.ts:138:21 - (ae-forgotten-export) The symbol "luceneStringToDsl" needs to be exported by the entry point index.d.ts
-// src/plugins/data/public/index.ts:138:21 - (ae-forgotten-export) The symbol "decorateQuery" needs to be exported by the entry point index.d.ts
-// src/plugins/data/public/index.ts:180:26 - (ae-forgotten-export) The symbol "FieldFormatsRegistry" needs to be exported by the entry point index.d.ts
-// src/plugins/data/public/index.ts:180:26 - (ae-forgotten-export) The symbol "BoolFormat" needs to be exported by the entry point index.d.ts
-// src/plugins/data/public/index.ts:180:26 - (ae-forgotten-export) The symbol "BytesFormat" needs to be exported by the entry point index.d.ts
-// src/plugins/data/public/index.ts:180:26 - (ae-forgotten-export) The symbol "ColorFormat" needs to be exported by the entry point index.d.ts
-// src/plugins/data/public/index.ts:180:26 - (ae-forgotten-export) The symbol "DateNanosFormat" needs to be exported by the entry point index.d.ts
-// src/plugins/data/public/index.ts:180:26 - (ae-forgotten-export) The symbol "DurationFormat" needs to be exported by the entry point index.d.ts
-// src/plugins/data/public/index.ts:180:26 - (ae-forgotten-export) The symbol "IpFormat" needs to be exported by the entry point index.d.ts
-// src/plugins/data/public/index.ts:180:26 - (ae-forgotten-export) The symbol "NumberFormat" needs to be exported by the entry point index.d.ts
-// src/plugins/data/public/index.ts:180:26 - (ae-forgotten-export) The symbol "PercentFormat" needs to be exported by the entry point index.d.ts
-// src/plugins/data/public/index.ts:180:26 - (ae-forgotten-export) The symbol "RelativeDateFormat" needs to be exported by the entry point index.d.ts
-// src/plugins/data/public/index.ts:180:26 - (ae-forgotten-export) The symbol "SourceFormat" needs to be exported by the entry point index.d.ts
-// src/plugins/data/public/index.ts:180:26 - (ae-forgotten-export) The symbol "StaticLookupFormat" needs to be exported by the entry point index.d.ts
-// src/plugins/data/public/index.ts:180:26 - (ae-forgotten-export) The symbol "UrlFormat" needs to be exported by the entry point index.d.ts
-// src/plugins/data/public/index.ts:180:26 - (ae-forgotten-export) The symbol "StringFormat" needs to be exported by the entry point index.d.ts
-// src/plugins/data/public/index.ts:180:26 - (ae-forgotten-export) The symbol "TruncateFormat" needs to be exported by the entry point index.d.ts
-// src/plugins/data/public/index.ts:238:27 - (ae-forgotten-export) The symbol "isFilterable" needs to be exported by the entry point index.d.ts
-// src/plugins/data/public/index.ts:238:27 - (ae-forgotten-export) The symbol "isNestedField" needs to be exported by the entry point index.d.ts
-// src/plugins/data/public/index.ts:238:27 - (ae-forgotten-export) The symbol "validateIndexPattern" needs to be exported by the entry point index.d.ts
-// src/plugins/data/public/index.ts:238:27 - (ae-forgotten-export) The symbol "getFromSavedObject" needs to be exported by the entry point index.d.ts
-// src/plugins/data/public/index.ts:238:27 - (ae-forgotten-export) The symbol "flattenHitWrapper" needs to be exported by the entry point index.d.ts
-// src/plugins/data/public/index.ts:238:27 - (ae-forgotten-export) The symbol "formatHitProvider" needs to be exported by the entry point index.d.ts
-// src/plugins/data/public/index.ts:378:20 - (ae-forgotten-export) The symbol "getRequestInspectorStats" needs to be exported by the entry point index.d.ts
-// src/plugins/data/public/index.ts:378:20 - (ae-forgotten-export) The symbol "getResponseInspectorStats" needs to be exported by the entry point index.d.ts
-// src/plugins/data/public/index.ts:378:20 - (ae-forgotten-export) The symbol "tabifyAggResponse" needs to be exported by the entry point index.d.ts
-// src/plugins/data/public/index.ts:378:20 - (ae-forgotten-export) The symbol "tabifyGetColumns" needs to be exported by the entry point index.d.ts
-// src/plugins/data/public/index.ts:380:1 - (ae-forgotten-export) The symbol "CidrMask" needs to be exported by the entry point index.d.ts
-// src/plugins/data/public/index.ts:381:1 - (ae-forgotten-export) The symbol "dateHistogramInterval" needs to be exported by the entry point index.d.ts
-// src/plugins/data/public/index.ts:390:1 - (ae-forgotten-export) The symbol "InvalidEsCalendarIntervalError" needs to be exported by the entry point index.d.ts
-// src/plugins/data/public/index.ts:391:1 - (ae-forgotten-export) The symbol "InvalidEsIntervalFormatError" needs to be exported by the entry point index.d.ts
-// src/plugins/data/public/index.ts:392:1 - (ae-forgotten-export) The symbol "isDateHistogramBucketAggConfig" needs to be exported by the entry point index.d.ts
-// src/plugins/data/public/index.ts:396:1 - (ae-forgotten-export) The symbol "isValidEsInterval" needs to be exported by the entry point index.d.ts
-// src/plugins/data/public/index.ts:397:1 - (ae-forgotten-export) The symbol "isValidInterval" needs to be exported by the entry point index.d.ts
-// src/plugins/data/public/index.ts:400:1 - (ae-forgotten-export) The symbol "parseInterval" needs to be exported by the entry point index.d.ts
-// src/plugins/data/public/index.ts:401:1 - (ae-forgotten-export) The symbol "propFilter" needs to be exported by the entry point index.d.ts
-// src/plugins/data/public/index.ts:404:1 - (ae-forgotten-export) The symbol "toAbsoluteDates" needs to be exported by the entry point index.d.ts
+// src/plugins/data/public/index.ts:65:23 - (ae-forgotten-export) The symbol "FilterLabel" needs to be exported by the entry point index.d.ts
+// src/plugins/data/public/index.ts:65:23 - (ae-forgotten-export) The symbol "FILTERS" needs to be exported by the entry point index.d.ts
+// src/plugins/data/public/index.ts:65:23 - (ae-forgotten-export) The symbol "getDisplayValueFromFilter" needs to be exported by the entry point index.d.ts
+// src/plugins/data/public/index.ts:65:23 - (ae-forgotten-export) The symbol "generateFilters" needs to be exported by the entry point index.d.ts
+// src/plugins/data/public/index.ts:65:23 - (ae-forgotten-export) The symbol "changeTimeFilter" needs to be exported by the entry point index.d.ts
+// src/plugins/data/public/index.ts:65:23 - (ae-forgotten-export) The symbol "convertRangeFilterToTimeRangeString" needs to be exported by the entry point index.d.ts
+// src/plugins/data/public/index.ts:65:23 - (ae-forgotten-export) The symbol "extractTimeFilter" needs to be exported by the entry point index.d.ts
+// src/plugins/data/public/index.ts:136:21 - (ae-forgotten-export) The symbol "buildEsQuery" needs to be exported by the entry point index.d.ts
+// src/plugins/data/public/index.ts:136:21 - (ae-forgotten-export) The symbol "getEsQueryConfig" needs to be exported by the entry point index.d.ts
+// src/plugins/data/public/index.ts:136:21 - (ae-forgotten-export) The symbol "luceneStringToDsl" needs to be exported by the entry point index.d.ts
+// src/plugins/data/public/index.ts:136:21 - (ae-forgotten-export) The symbol "decorateQuery" needs to be exported by the entry point index.d.ts
+// src/plugins/data/public/index.ts:178:26 - (ae-forgotten-export) The symbol "FieldFormatsRegistry" needs to be exported by the entry point index.d.ts
+// src/plugins/data/public/index.ts:178:26 - (ae-forgotten-export) The symbol "BoolFormat" needs to be exported by the entry point index.d.ts
+// src/plugins/data/public/index.ts:178:26 - (ae-forgotten-export) The symbol "BytesFormat" needs to be exported by the entry point index.d.ts
+// src/plugins/data/public/index.ts:178:26 - (ae-forgotten-export) The symbol "ColorFormat" needs to be exported by the entry point index.d.ts
+// src/plugins/data/public/index.ts:178:26 - (ae-forgotten-export) The symbol "DateNanosFormat" needs to be exported by the entry point index.d.ts
+// src/plugins/data/public/index.ts:178:26 - (ae-forgotten-export) The symbol "DurationFormat" needs to be exported by the entry point index.d.ts
+// src/plugins/data/public/index.ts:178:26 - (ae-forgotten-export) The symbol "IpFormat" needs to be exported by the entry point index.d.ts
+// src/plugins/data/public/index.ts:178:26 - (ae-forgotten-export) The symbol "NumberFormat" needs to be exported by the entry point index.d.ts
+// src/plugins/data/public/index.ts:178:26 - (ae-forgotten-export) The symbol "PercentFormat" needs to be exported by the entry point index.d.ts
+// src/plugins/data/public/index.ts:178:26 - (ae-forgotten-export) The symbol "RelativeDateFormat" needs to be exported by the entry point index.d.ts
+// src/plugins/data/public/index.ts:178:26 - (ae-forgotten-export) The symbol "SourceFormat" needs to be exported by the entry point index.d.ts
+// src/plugins/data/public/index.ts:178:26 - (ae-forgotten-export) The symbol "StaticLookupFormat" needs to be exported by the entry point index.d.ts
+// src/plugins/data/public/index.ts:178:26 - (ae-forgotten-export) The symbol "UrlFormat" needs to be exported by the entry point index.d.ts
+// src/plugins/data/public/index.ts:178:26 - (ae-forgotten-export) The symbol "StringFormat" needs to be exported by the entry point index.d.ts
+// src/plugins/data/public/index.ts:178:26 - (ae-forgotten-export) The symbol "TruncateFormat" needs to be exported by the entry point index.d.ts
+// src/plugins/data/public/index.ts:236:27 - (ae-forgotten-export) The symbol "isFilterable" needs to be exported by the entry point index.d.ts
+// src/plugins/data/public/index.ts:236:27 - (ae-forgotten-export) The symbol "isNestedField" needs to be exported by the entry point index.d.ts
+// src/plugins/data/public/index.ts:236:27 - (ae-forgotten-export) The symbol "validateIndexPattern" needs to be exported by the entry point index.d.ts
+// src/plugins/data/public/index.ts:236:27 - (ae-forgotten-export) The symbol "getFromSavedObject" needs to be exported by the entry point index.d.ts
+// src/plugins/data/public/index.ts:236:27 - (ae-forgotten-export) The symbol "flattenHitWrapper" needs to be exported by the entry point index.d.ts
+// src/plugins/data/public/index.ts:236:27 - (ae-forgotten-export) The symbol "formatHitProvider" needs to be exported by the entry point index.d.ts
+// src/plugins/data/public/index.ts:377:20 - (ae-forgotten-export) The symbol "getRequestInspectorStats" needs to be exported by the entry point index.d.ts
+// src/plugins/data/public/index.ts:377:20 - (ae-forgotten-export) The symbol "getResponseInspectorStats" needs to be exported by the entry point index.d.ts
+// src/plugins/data/public/index.ts:377:20 - (ae-forgotten-export) The symbol "tabifyAggResponse" needs to be exported by the entry point index.d.ts
+// src/plugins/data/public/index.ts:377:20 - (ae-forgotten-export) The symbol "tabifyGetColumns" needs to be exported by the entry point index.d.ts
+// src/plugins/data/public/index.ts:379:1 - (ae-forgotten-export) The symbol "CidrMask" needs to be exported by the entry point index.d.ts
+// src/plugins/data/public/index.ts:380:1 - (ae-forgotten-export) The symbol "dateHistogramInterval" needs to be exported by the entry point index.d.ts
+// src/plugins/data/public/index.ts:389:1 - (ae-forgotten-export) The symbol "InvalidEsCalendarIntervalError" needs to be exported by the entry point index.d.ts
+// src/plugins/data/public/index.ts:390:1 - (ae-forgotten-export) The symbol "InvalidEsIntervalFormatError" needs to be exported by the entry point index.d.ts
+// src/plugins/data/public/index.ts:391:1 - (ae-forgotten-export) The symbol "isDateHistogramBucketAggConfig" needs to be exported by the entry point index.d.ts
+// src/plugins/data/public/index.ts:395:1 - (ae-forgotten-export) The symbol "isValidEsInterval" needs to be exported by the entry point index.d.ts
+// src/plugins/data/public/index.ts:396:1 - (ae-forgotten-export) The symbol "isValidInterval" needs to be exported by the entry point index.d.ts
+// src/plugins/data/public/index.ts:399:1 - (ae-forgotten-export) The symbol "parseInterval" needs to be exported by the entry point index.d.ts
+// src/plugins/data/public/index.ts:400:1 - (ae-forgotten-export) The symbol "propFilter" needs to be exported by the entry point index.d.ts
+// src/plugins/data/public/index.ts:403:1 - (ae-forgotten-export) The symbol "toAbsoluteDates" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/query/state_sync/connect_to_query_state.ts:33:33 - (ae-forgotten-export) The symbol "FilterStateStore" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/query/state_sync/connect_to_query_state.ts:37:1 - (ae-forgotten-export) The symbol "QueryStateChange" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/types.ts:52:5 - (ae-forgotten-export) The symbol "createFiltersFromValueClickAction" needs to be exported by the entry point index.d.ts
diff --git a/src/plugins/data/public/query/filter_manager/filter_manager.test.ts b/src/plugins/data/public/query/filter_manager/filter_manager.test.ts
index 3c69a498e74cd..878142906f54b 100644
--- a/src/plugins/data/public/query/filter_manager/filter_manager.test.ts
+++ b/src/plugins/data/public/query/filter_manager/filter_manager.test.ts
@@ -24,14 +24,14 @@ import { Subscription } from 'rxjs';
import { FilterManager } from './filter_manager';
import { getFilter } from './test_helpers/get_stub_filter';
import { getFiltersArray } from './test_helpers/get_filters_array';
-import { Filter, FilterStateStore } from '../../../common';
+import { Filter, FilterStateStore, UI_SETTINGS } from '../../../common';
import { coreMock } from '../../../../../core/public/mocks';
const setupMock = coreMock.createSetup();
const uiSettingsMock = (pinnedByDefault: boolean) => (key: string) => {
switch (key) {
- case 'filters:pinnedByDefault':
+ case UI_SETTINGS.FILTERS_PINNED_BY_DEFAULT:
return pinnedByDefault;
default:
throw new Error(`Unexpected uiSettings key in FilterManager mock: ${key}`);
diff --git a/src/plugins/data/public/query/filter_manager/filter_manager.ts b/src/plugins/data/public/query/filter_manager/filter_manager.ts
index d58a0eb45c04f..60a49a4bd50f4 100644
--- a/src/plugins/data/public/query/filter_manager/filter_manager.ts
+++ b/src/plugins/data/public/query/filter_manager/filter_manager.ts
@@ -34,6 +34,7 @@ import {
isFilterPinned,
compareFilters,
COMPARE_ALL_OPTIONS,
+ UI_SETTINGS,
} from '../../../common';
export class FilterManager {
@@ -129,7 +130,7 @@ export class FilterManager {
public addFilters(
filters: Filter[] | Filter,
- pinFilterStatus: boolean = this.uiSettings.get('filters:pinnedByDefault')
+ pinFilterStatus: boolean = this.uiSettings.get(UI_SETTINGS.FILTERS_PINNED_BY_DEFAULT)
) {
if (!Array.isArray(filters)) {
filters = [filters];
@@ -157,7 +158,7 @@ export class FilterManager {
public setFilters(
newFilters: Filter[],
- pinFilterStatus: boolean = this.uiSettings.get('filters:pinnedByDefault')
+ pinFilterStatus: boolean = this.uiSettings.get(UI_SETTINGS.FILTERS_PINNED_BY_DEFAULT)
) {
const store = pinFilterStatus ? FilterStateStore.GLOBAL_STATE : FilterStateStore.APP_STATE;
diff --git a/src/plugins/data/public/query/lib/get_query_log.ts b/src/plugins/data/public/query/lib/get_query_log.ts
index a71eb7580cf07..b7827d2c8de02 100644
--- a/src/plugins/data/public/query/lib/get_query_log.ts
+++ b/src/plugins/data/public/query/lib/get_query_log.ts
@@ -20,6 +20,7 @@
import { IUiSettingsClient } from 'src/core/public';
import { IStorageWrapper } from 'src/plugins/kibana_utils/public';
import { PersistedLog } from '../persisted_log';
+import { UI_SETTINGS } from '../../../common';
export function getQueryLog(
uiSettings: IUiSettingsClient,
@@ -30,7 +31,7 @@ export function getQueryLog(
return new PersistedLog(
`typeahead:${appName}-${language}`,
{
- maxLength: uiSettings.get('history:limit'),
+ maxLength: uiSettings.get(UI_SETTINGS.HISTORY_LIMIT),
filterDuplicates: true,
},
storage
diff --git a/src/plugins/data/public/query/state_sync/connect_to_query_state.test.ts b/src/plugins/data/public/query/state_sync/connect_to_query_state.test.ts
index 06e4c1c8be6d5..4e394445b75ae 100644
--- a/src/plugins/data/public/query/state_sync/connect_to_query_state.test.ts
+++ b/src/plugins/data/public/query/state_sync/connect_to_query_state.test.ts
@@ -20,7 +20,7 @@
import { Subscription } from 'rxjs';
import { FilterManager } from '../filter_manager';
import { getFilter } from '../filter_manager/test_helpers/get_stub_filter';
-import { Filter, FilterStateStore } from '../../../common';
+import { Filter, FilterStateStore, UI_SETTINGS } from '../../../common';
import { coreMock } from '../../../../../core/public/mocks';
import { BaseStateContainer, createStateContainer, Storage } from '../../../../kibana_utils/public';
import { QueryService, QueryStart } from '../query_service';
@@ -46,11 +46,11 @@ const startMock = coreMock.createStart();
setupMock.uiSettings.get.mockImplementation((key: string) => {
switch (key) {
- case 'filters:pinnedByDefault':
+ case UI_SETTINGS.FILTERS_PINNED_BY_DEFAULT:
return true;
case 'timepicker:timeDefaults':
return { from: 'now-15m', to: 'now' };
- case 'timepicker:refreshIntervalDefaults':
+ case UI_SETTINGS.TIMEPICKER_REFRESH_INTERVAL_DEFAULTS:
return { pause: false, value: 0 };
default:
throw new Error(`sync_query test: not mocked uiSetting: ${key}`);
diff --git a/src/plugins/data/public/query/state_sync/sync_state_with_url.test.ts b/src/plugins/data/public/query/state_sync/sync_state_with_url.test.ts
index 50dc35ea955ee..7727153537257 100644
--- a/src/plugins/data/public/query/state_sync/sync_state_with_url.test.ts
+++ b/src/plugins/data/public/query/state_sync/sync_state_with_url.test.ts
@@ -21,7 +21,7 @@ import { Subscription } from 'rxjs';
import { createBrowserHistory, History } from 'history';
import { FilterManager } from '../filter_manager';
import { getFilter } from '../filter_manager/test_helpers/get_stub_filter';
-import { Filter, FilterStateStore } from '../../../common';
+import { Filter, FilterStateStore, UI_SETTINGS } from '../../../common';
import { coreMock } from '../../../../../core/public/mocks';
import {
createKbnUrlStateStorage,
@@ -39,11 +39,11 @@ const startMock = coreMock.createStart();
setupMock.uiSettings.get.mockImplementation((key: string) => {
switch (key) {
- case 'filters:pinnedByDefault':
+ case UI_SETTINGS.FILTERS_PINNED_BY_DEFAULT:
return true;
case 'timepicker:timeDefaults':
return { from: 'now-15m', to: 'now' };
- case 'timepicker:refreshIntervalDefaults':
+ case UI_SETTINGS.TIMEPICKER_REFRESH_INTERVAL_DEFAULTS:
return { pause: false, value: 0 };
default:
throw new Error(`sync_query test: not mocked uiSetting: ${key}`);
diff --git a/src/plugins/data/public/query/timefilter/timefilter_service.ts b/src/plugins/data/public/query/timefilter/timefilter_service.ts
index 413163ed059ad..df2fbc8e5a8f3 100644
--- a/src/plugins/data/public/query/timefilter/timefilter_service.ts
+++ b/src/plugins/data/public/query/timefilter/timefilter_service.ts
@@ -20,6 +20,7 @@
import { IUiSettingsClient } from 'src/core/public';
import { IStorageWrapper } from 'src/plugins/kibana_utils/public';
import { TimeHistory, Timefilter, TimeHistoryContract, TimefilterContract } from './index';
+import { UI_SETTINGS } from '../../../common';
/**
* Filter Service
@@ -35,7 +36,7 @@ export class TimefilterService {
public setup({ uiSettings, storage }: TimeFilterServiceDependencies): TimefilterSetup {
const timefilterConfig = {
timeDefaults: uiSettings.get('timepicker:timeDefaults'),
- refreshIntervalDefaults: uiSettings.get('timepicker:refreshIntervalDefaults'),
+ refreshIntervalDefaults: uiSettings.get(UI_SETTINGS.TIMEPICKER_REFRESH_INTERVAL_DEFAULTS),
};
const history = new TimeHistory(storage);
const timefilter = new Timefilter(timefilterConfig, history);
diff --git a/src/plugins/data/public/search/aggs/buckets/date_histogram.ts b/src/plugins/data/public/search/aggs/buckets/date_histogram.ts
index d5c97d0c95c5c..8a5596f669cb7 100644
--- a/src/plugins/data/public/search/aggs/buckets/date_histogram.ts
+++ b/src/plugins/data/public/search/aggs/buckets/date_histogram.ts
@@ -31,7 +31,7 @@ import { dateHistogramInterval, TimeRange } from '../../../../common';
import { writeParams } from '../agg_params';
import { isMetricAggType } from '../metrics/metric_agg_type';
-import { FIELD_FORMAT_IDS, KBN_FIELD_TYPES } from '../../../../common';
+import { FIELD_FORMAT_IDS, KBN_FIELD_TYPES, UI_SETTINGS } from '../../../../common';
import { TimefilterContract } from '../../../query';
import { QuerySetup } from '../../../query/query_service';
import { GetInternalStartServicesFn } from '../../../types';
@@ -125,8 +125,8 @@ export const getDateHistogramBucketAgg = ({
const { timefilter } = query.timefilter;
buckets = new TimeBuckets({
- 'histogram:maxBars': uiSettings.get('histogram:maxBars'),
- 'histogram:barTarget': uiSettings.get('histogram:barTarget'),
+ 'histogram:maxBars': uiSettings.get(UI_SETTINGS.HISTOGRAM_MAX_BARS),
+ 'histogram:barTarget': uiSettings.get(UI_SETTINGS.HISTOGRAM_BAR_TARGET),
dateFormat: uiSettings.get('dateFormat'),
'dateFormat:scaled': uiSettings.get('dateFormat:scaled'),
});
diff --git a/src/plugins/data/public/search/aggs/buckets/filters.ts b/src/plugins/data/public/search/aggs/buckets/filters.ts
index 3f3f13bb955c1..4052c0b390155 100644
--- a/src/plugins/data/public/search/aggs/buckets/filters.ts
+++ b/src/plugins/data/public/search/aggs/buckets/filters.ts
@@ -26,7 +26,7 @@ import { toAngularJSON } from '../utils';
import { BucketAggType } from './bucket_agg_type';
import { BUCKET_TYPES } from './bucket_agg_types';
import { Storage } from '../../../../../../plugins/kibana_utils/public';
-import { getEsQueryConfig, buildEsQuery, Query } from '../../../../common';
+import { getEsQueryConfig, buildEsQuery, Query, UI_SETTINGS } from '../../../../common';
import { getQueryLog } from '../../../query';
import { GetInternalStartServicesFn } from '../../../types';
import { BaseAggParams } from '../types';
@@ -69,7 +69,10 @@ export const getFiltersBucketAgg = ({
{
name: 'filters',
default: [
- { input: { query: '', language: uiSettings.get('search:queryLanguage') }, label: '' },
+ {
+ input: { query: '', language: uiSettings.get(UI_SETTINGS.SEARCH_QUERY_LANGUAGE) },
+ label: '',
+ },
],
write(aggConfig, output) {
const inFilters: FilterValue[] = aggConfig.params.filters;
diff --git a/src/plugins/data/public/search/aggs/buckets/histogram.ts b/src/plugins/data/public/search/aggs/buckets/histogram.ts
index d04df4f8aac6b..c1fad17f488db 100644
--- a/src/plugins/data/public/search/aggs/buckets/histogram.ts
+++ b/src/plugins/data/public/search/aggs/buckets/histogram.ts
@@ -24,7 +24,7 @@ import { IUiSettingsClient } from 'src/core/public';
import { BucketAggType, IBucketAggConfig } from './bucket_agg_type';
import { createFilterHistogram } from './create_filter/histogram';
import { BUCKET_TYPES } from './bucket_agg_types';
-import { KBN_FIELD_TYPES } from '../../../../common';
+import { KBN_FIELD_TYPES, UI_SETTINGS } from '../../../../common';
import { GetInternalStartServicesFn } from '../../../types';
import { BaseAggParams } from '../types';
import { ExtendedBounds } from './lib/extended_bounds';
@@ -155,8 +155,8 @@ export const getHistogramBucketAgg = ({
const range = autoBounds.max - autoBounds.min;
const bars = range / interval;
- if (bars > uiSettings.get('histogram:maxBars')) {
- const minInterval = range / uiSettings.get('histogram:maxBars');
+ if (bars > uiSettings.get(UI_SETTINGS.HISTOGRAM_MAX_BARS)) {
+ const minInterval = range / uiSettings.get(UI_SETTINGS.HISTOGRAM_MAX_BARS);
// Round interval by order of magnitude to provide clean intervals
// Always round interval up so there will always be less buckets than histogram:maxBars
diff --git a/src/plugins/data/public/search/aggs/utils/calculate_auto_time_expression.ts b/src/plugins/data/public/search/aggs/utils/calculate_auto_time_expression.ts
index 9d976784329cc..30fcdd9d83a38 100644
--- a/src/plugins/data/public/search/aggs/utils/calculate_auto_time_expression.ts
+++ b/src/plugins/data/public/search/aggs/utils/calculate_auto_time_expression.ts
@@ -19,7 +19,7 @@
import moment from 'moment';
import { IUiSettingsClient } from 'src/core/public';
import { TimeBuckets } from '../buckets/lib/time_buckets';
-import { toAbsoluteDates, TimeRange } from '../../../../common';
+import { toAbsoluteDates, TimeRange, UI_SETTINGS } from '../../../../common';
export function getCalculateAutoTimeExpression(uiSettings: IUiSettingsClient) {
return function calculateAutoTimeExpression(range: TimeRange) {
@@ -29,8 +29,8 @@ export function getCalculateAutoTimeExpression(uiSettings: IUiSettingsClient) {
}
const buckets = new TimeBuckets({
- 'histogram:maxBars': uiSettings.get('histogram:maxBars'),
- 'histogram:barTarget': uiSettings.get('histogram:barTarget'),
+ 'histogram:maxBars': uiSettings.get(UI_SETTINGS.HISTOGRAM_MAX_BARS),
+ 'histogram:barTarget': uiSettings.get(UI_SETTINGS.HISTOGRAM_BAR_TARGET),
dateFormat: uiSettings.get('dateFormat'),
'dateFormat:scaled': uiSettings.get('dateFormat:scaled'),
});
diff --git a/src/plugins/data/public/search/es_search/get_es_preference.test.ts b/src/plugins/data/public/search/es_search/get_es_preference.test.ts
index 8b8156b4519d6..05a74b3e6205a 100644
--- a/src/plugins/data/public/search/es_search/get_es_preference.test.ts
+++ b/src/plugins/data/public/search/es_search/get_es_preference.test.ts
@@ -20,6 +20,7 @@
import { getEsPreference } from './get_es_preference';
import { CoreStart } from '../../../../../core/public';
import { coreMock } from '../../../../../core/public/mocks';
+import { UI_SETTINGS } from '../../../common';
describe('Get ES preference', () => {
let mockCoreStart: MockedKeys;
@@ -30,8 +31,8 @@ describe('Get ES preference', () => {
test('returns the session ID if set to sessionId', () => {
mockCoreStart.uiSettings.get.mockImplementation((key: string) => {
- if (key === 'courier:setRequestPreference') return 'sessionId';
- if (key === 'courier:customRequestPreference') return 'foobar';
+ if (key === UI_SETTINGS.COURIER_SET_REQUEST_PREFERENCE) return 'sessionId';
+ if (key === UI_SETTINGS.COURIER_CUSTOM_REQUEST_PREFERENCE) return 'foobar';
});
const preference = getEsPreference(mockCoreStart.uiSettings, 'my_session_id');
expect(preference).toBe('my_session_id');
@@ -39,8 +40,8 @@ describe('Get ES preference', () => {
test('returns the custom preference if set to custom', () => {
mockCoreStart.uiSettings.get.mockImplementation((key: string) => {
- if (key === 'courier:setRequestPreference') return 'custom';
- if (key === 'courier:customRequestPreference') return 'foobar';
+ if (key === UI_SETTINGS.COURIER_SET_REQUEST_PREFERENCE) return 'custom';
+ if (key === UI_SETTINGS.COURIER_CUSTOM_REQUEST_PREFERENCE) return 'foobar';
});
const preference = getEsPreference(mockCoreStart.uiSettings);
expect(preference).toBe('foobar');
@@ -48,8 +49,8 @@ describe('Get ES preference', () => {
test('returns undefined if set to none', () => {
mockCoreStart.uiSettings.get.mockImplementation((key: string) => {
- if (key === 'courier:setRequestPreference') return 'none';
- if (key === 'courier:customRequestPreference') return 'foobar';
+ if (key === UI_SETTINGS.COURIER_SET_REQUEST_PREFERENCE) return 'none';
+ if (key === UI_SETTINGS.COURIER_CUSTOM_REQUEST_PREFERENCE) return 'foobar';
});
const preference = getEsPreference(mockCoreStart.uiSettings);
expect(preference).toBe(undefined);
diff --git a/src/plugins/data/public/search/es_search/get_es_preference.ts b/src/plugins/data/public/search/es_search/get_es_preference.ts
index 3f1c2b9b3b736..5e40712067bb0 100644
--- a/src/plugins/data/public/search/es_search/get_es_preference.ts
+++ b/src/plugins/data/public/search/es_search/get_es_preference.ts
@@ -18,12 +18,13 @@
*/
import { IUiSettingsClient } from '../../../../../core/public';
+import { UI_SETTINGS } from '../../../common';
const defaultSessionId = `${Date.now()}`;
export function getEsPreference(uiSettings: IUiSettingsClient, sessionId = defaultSessionId) {
- const setPreference = uiSettings.get('courier:setRequestPreference');
+ const setPreference = uiSettings.get(UI_SETTINGS.COURIER_SET_REQUEST_PREFERENCE);
if (setPreference === 'sessionId') return `${sessionId}`;
- const customPreference = uiSettings.get('courier:customRequestPreference');
+ const customPreference = uiSettings.get(UI_SETTINGS.COURIER_CUSTOM_REQUEST_PREFERENCE);
return setPreference === 'custom' ? customPreference : undefined;
}
diff --git a/src/plugins/data/public/search/fetch/get_search_params.test.ts b/src/plugins/data/public/search/fetch/get_search_params.test.ts
index 4809d76a46f59..f9b62fdd4fc61 100644
--- a/src/plugins/data/public/search/fetch/get_search_params.test.ts
+++ b/src/plugins/data/public/search/fetch/get_search_params.test.ts
@@ -19,6 +19,7 @@
import { getSearchParams } from './get_search_params';
import { IUiSettingsClient } from 'kibana/public';
+import { UI_SETTINGS } from '../../../common';
function getConfigStub(config: any = {}) {
return {
@@ -40,21 +41,21 @@ describe('getSearchParams', () => {
});
test('includes ignore_throttled according to search:includeFrozen', () => {
- let config = getConfigStub({ 'search:includeFrozen': true });
+ let config = getConfigStub({ [UI_SETTINGS.SEARCH_INCLUDE_FROZEN]: true });
let searchParams = getSearchParams(config);
expect(searchParams.ignore_throttled).toBe(false);
- config = getConfigStub({ 'search:includeFrozen': false });
+ config = getConfigStub({ [UI_SETTINGS.SEARCH_INCLUDE_FROZEN]: false });
searchParams = getSearchParams(config);
expect(searchParams.ignore_throttled).toBe(true);
});
test('includes max_concurrent_shard_requests according to courier:maxConcurrentShardRequests', () => {
- let config = getConfigStub({ 'courier:maxConcurrentShardRequests': 0 });
+ let config = getConfigStub({ [UI_SETTINGS.COURIER_MAX_CONCURRENT_SHARD_REQUESTS]: 0 });
let searchParams = getSearchParams(config);
expect(searchParams.max_concurrent_shard_requests).toBe(undefined);
- config = getConfigStub({ 'courier:maxConcurrentShardRequests': 5 });
+ config = getConfigStub({ [UI_SETTINGS.COURIER_MAX_CONCURRENT_SHARD_REQUESTS]: 5 });
searchParams = getSearchParams(config);
expect(searchParams.max_concurrent_shard_requests).toBe(5);
});
diff --git a/src/plugins/data/public/search/fetch/get_search_params.ts b/src/plugins/data/public/search/fetch/get_search_params.ts
index f0c43bd2e74cd..60bdc9ed6473a 100644
--- a/src/plugins/data/public/search/fetch/get_search_params.ts
+++ b/src/plugins/data/public/search/fetch/get_search_params.ts
@@ -18,6 +18,7 @@
*/
import { IUiSettingsClient } from 'kibana/public';
+import { UI_SETTINGS } from '../../../common';
const sessionId = Date.now();
@@ -33,19 +34,19 @@ export function getSearchParams(config: IUiSettingsClient, esShardTimeout: numbe
}
export function getIgnoreThrottled(config: IUiSettingsClient) {
- return !config.get('search:includeFrozen');
+ return !config.get(UI_SETTINGS.SEARCH_INCLUDE_FROZEN);
}
export function getMaxConcurrentShardRequests(config: IUiSettingsClient) {
- const maxConcurrentShardRequests = config.get('courier:maxConcurrentShardRequests');
+ const maxConcurrentShardRequests = config.get(UI_SETTINGS.COURIER_MAX_CONCURRENT_SHARD_REQUESTS);
return maxConcurrentShardRequests > 0 ? maxConcurrentShardRequests : undefined;
}
export function getPreference(config: IUiSettingsClient) {
- const setRequestPreference = config.get('courier:setRequestPreference');
+ const setRequestPreference = config.get(UI_SETTINGS.COURIER_SET_REQUEST_PREFERENCE);
if (setRequestPreference === 'sessionId') return sessionId;
return setRequestPreference === 'custom'
- ? config.get('courier:customRequestPreference')
+ ? config.get(UI_SETTINGS.COURIER_CUSTOM_REQUEST_PREFERENCE)
: undefined;
}
diff --git a/src/plugins/data/public/search/legacy/default_search_strategy.test.ts b/src/plugins/data/public/search/legacy/default_search_strategy.test.ts
index c619c9b17d9a8..436b522744622 100644
--- a/src/plugins/data/public/search/legacy/default_search_strategy.test.ts
+++ b/src/plugins/data/public/search/legacy/default_search_strategy.test.ts
@@ -21,6 +21,7 @@ import { IUiSettingsClient } from 'kibana/public';
import { defaultSearchStrategy } from './default_search_strategy';
import { searchStartMock } from '../mocks';
import { SearchStrategySearchParams } from './types';
+import { UI_SETTINGS } from '../../../common';
const { search } = defaultSearchStrategy;
@@ -69,30 +70,30 @@ describe('defaultSearchStrategy', function () {
});
test('does not send max_concurrent_shard_requests by default', async () => {
- const config = getConfigStub({ 'courier:batchSearches': true });
+ const config = getConfigStub({ [UI_SETTINGS.COURIER_BATCH_SEARCHES]: true });
await search({ ...searchArgs, config });
expect(es.msearch.mock.calls[0][0].max_concurrent_shard_requests).toBe(undefined);
});
test('allows configuration of max_concurrent_shard_requests', async () => {
const config = getConfigStub({
- 'courier:batchSearches': true,
- 'courier:maxConcurrentShardRequests': 42,
+ [UI_SETTINGS.COURIER_BATCH_SEARCHES]: true,
+ [UI_SETTINGS.COURIER_MAX_CONCURRENT_SHARD_REQUESTS]: 42,
});
await search({ ...searchArgs, config });
expect(es.msearch.mock.calls[0][0].max_concurrent_shard_requests).toBe(42);
});
test('should set rest_total_hits_as_int to true on a request', async () => {
- const config = getConfigStub({ 'courier:batchSearches': true });
+ const config = getConfigStub({ [UI_SETTINGS.COURIER_BATCH_SEARCHES]: true });
await search({ ...searchArgs, config });
expect(es.msearch.mock.calls[0][0]).toHaveProperty('rest_total_hits_as_int', true);
});
test('should set ignore_throttled=false when including frozen indices', async () => {
const config = getConfigStub({
- 'courier:batchSearches': true,
- 'search:includeFrozen': true,
+ [UI_SETTINGS.COURIER_BATCH_SEARCHES]: true,
+ [UI_SETTINGS.SEARCH_INCLUDE_FROZEN]: true,
});
await search({ ...searchArgs, config });
expect(es.msearch.mock.calls[0][0]).toHaveProperty('ignore_throttled', false);
@@ -100,7 +101,7 @@ describe('defaultSearchStrategy', function () {
test('should properly call abort with msearch', () => {
const config = getConfigStub({
- 'courier:batchSearches': true,
+ [UI_SETTINGS.COURIER_BATCH_SEARCHES]: true,
});
search({ ...searchArgs, config }).abort();
expect(msearchMockResponse.abort).toHaveBeenCalled();
diff --git a/src/plugins/data/public/search/legacy/fetch_soon.test.ts b/src/plugins/data/public/search/legacy/fetch_soon.test.ts
index e99e13ba33d1a..61d3568350b6b 100644
--- a/src/plugins/data/public/search/legacy/fetch_soon.test.ts
+++ b/src/plugins/data/public/search/legacy/fetch_soon.test.ts
@@ -22,6 +22,7 @@ import { callClient } from './call_client';
import { IUiSettingsClient } from 'kibana/public';
import { FetchHandlers, FetchOptions } from '../fetch/types';
import { SearchRequest, SearchResponse } from '../index';
+import { UI_SETTINGS } from '../../../common';
function getConfigStub(config: any = {}) {
return {
@@ -60,7 +61,7 @@ describe('fetchSoon', () => {
test('should execute asap if config is set to not batch searches', () => {
const config = getConfigStub({
- 'courier:batchSearches': false,
+ [UI_SETTINGS.COURIER_BATCH_SEARCHES]: false,
});
const request = {};
const options = {};
@@ -72,7 +73,7 @@ describe('fetchSoon', () => {
test('should delay by 50ms if config is set to batch searches', () => {
const config = getConfigStub({
- 'courier:batchSearches': true,
+ [UI_SETTINGS.COURIER_BATCH_SEARCHES]: true,
});
const request = {};
const options = {};
@@ -88,7 +89,7 @@ describe('fetchSoon', () => {
test('should send a batch of requests to callClient', () => {
const config = getConfigStub({
- 'courier:batchSearches': true,
+ [UI_SETTINGS.COURIER_BATCH_SEARCHES]: true,
});
const requests = [{ foo: 1 }, { foo: 2 }];
const options = [{ bar: 1 }, { bar: 2 }];
@@ -105,7 +106,7 @@ describe('fetchSoon', () => {
test('should return the response to the corresponding call for multiple batched requests', async () => {
const config = getConfigStub({
- 'courier:batchSearches': true,
+ [UI_SETTINGS.COURIER_BATCH_SEARCHES]: true,
});
const requests = [{ _mockResponseId: 'foo' }, { _mockResponseId: 'bar' }];
@@ -120,7 +121,7 @@ describe('fetchSoon', () => {
test('should wait for the previous batch to start before starting a new batch', () => {
const config = getConfigStub({
- 'courier:batchSearches': true,
+ [UI_SETTINGS.COURIER_BATCH_SEARCHES]: true,
});
const firstBatch = [{ foo: 1 }, { foo: 2 }];
const secondBatch = [{ bar: 1 }, { bar: 2 }];
diff --git a/src/plugins/data/public/search/legacy/fetch_soon.ts b/src/plugins/data/public/search/legacy/fetch_soon.ts
index 304c1c4d63f5b..fed2c52bc491f 100644
--- a/src/plugins/data/public/search/legacy/fetch_soon.ts
+++ b/src/plugins/data/public/search/legacy/fetch_soon.ts
@@ -20,6 +20,7 @@
import { callClient } from './call_client';
import { FetchHandlers, FetchOptions } from '../fetch/types';
import { SearchRequest, SearchResponse } from '../index';
+import { UI_SETTINGS } from '../../../common';
/**
* This function introduces a slight delay in the request process to allow multiple requests to queue
@@ -30,7 +31,7 @@ export async function fetchSoon(
options: FetchOptions,
fetchHandlers: FetchHandlers
) {
- const msToDelay = fetchHandlers.config.get('courier:batchSearches') ? 50 : 0;
+ const msToDelay = fetchHandlers.config.get(UI_SETTINGS.COURIER_BATCH_SEARCHES) ? 50 : 0;
return delayedFetch(request, options, fetchHandlers, msToDelay);
}
diff --git a/src/plugins/data/public/search/legacy/get_msearch_params.test.ts b/src/plugins/data/public/search/legacy/get_msearch_params.test.ts
index ce98f6ab2a7bb..dc61e19406631 100644
--- a/src/plugins/data/public/search/legacy/get_msearch_params.test.ts
+++ b/src/plugins/data/public/search/legacy/get_msearch_params.test.ts
@@ -19,6 +19,7 @@
import { getMSearchParams } from './get_msearch_params';
import { IUiSettingsClient } from '../../../../../core/public';
+import { UI_SETTINGS } from '../../../common';
function getConfigStub(config: any = {}) {
return {
@@ -34,29 +35,29 @@ describe('getMSearchParams', () => {
});
test('includes ignore_throttled according to search:includeFrozen', () => {
- let config = getConfigStub({ 'search:includeFrozen': true });
+ let config = getConfigStub({ [UI_SETTINGS.SEARCH_INCLUDE_FROZEN]: true });
let msearchParams = getMSearchParams(config);
expect(msearchParams.ignore_throttled).toBe(false);
- config = getConfigStub({ 'search:includeFrozen': false });
+ config = getConfigStub({ [UI_SETTINGS.SEARCH_INCLUDE_FROZEN]: false });
msearchParams = getMSearchParams(config);
expect(msearchParams.ignore_throttled).toBe(true);
});
test('includes max_concurrent_shard_requests according to courier:maxConcurrentShardRequests if greater than 0', () => {
- let config = getConfigStub({ 'courier:maxConcurrentShardRequests': 0 });
+ let config = getConfigStub({ [UI_SETTINGS.COURIER_MAX_CONCURRENT_SHARD_REQUESTS]: 0 });
let msearchParams = getMSearchParams(config);
expect(msearchParams.max_concurrent_shard_requests).toBe(undefined);
- config = getConfigStub({ 'courier:maxConcurrentShardRequests': 5 });
+ config = getConfigStub({ [UI_SETTINGS.COURIER_MAX_CONCURRENT_SHARD_REQUESTS]: 5 });
msearchParams = getMSearchParams(config);
expect(msearchParams.max_concurrent_shard_requests).toBe(5);
});
test('does not include other search params that are included in the msearch header or body', () => {
const config = getConfigStub({
- 'search:includeFrozen': false,
- 'courier:maxConcurrentShardRequests': 5,
+ [UI_SETTINGS.SEARCH_INCLUDE_FROZEN]: false,
+ [UI_SETTINGS.COURIER_MAX_CONCURRENT_SHARD_REQUESTS]: 5,
});
const msearchParams = getMSearchParams(config);
expect(msearchParams.hasOwnProperty('ignore_unavailable')).toBe(false);
diff --git a/src/plugins/data/public/search/search_source/search_source.ts b/src/plugins/data/public/search/search_source/search_source.ts
index 38f4ce73713c8..b926739112e0e 100644
--- a/src/plugins/data/public/search/search_source/search_source.ts
+++ b/src/plugins/data/public/search/search_source/search_source.ts
@@ -75,12 +75,11 @@ import { CoreStart } from 'kibana/public';
import { normalizeSortRequest } from './normalize_sort_request';
import { filterDocvalueFields } from './filter_docvalue_fields';
import { fieldWildcardFilter } from '../../../../kibana_utils/public';
-import { META_FIELDS_SETTING, DOC_HIGHLIGHT_SETTING } from '../../../common';
import { IIndexPattern, ISearchGeneric, SearchRequest } from '../..';
import { SearchSourceOptions, SearchSourceFields } from './types';
import { FetchOptions, RequestFailure, getSearchParams, handleResponse } from '../fetch';
-import { getEsQueryConfig, buildEsQuery, Filter } from '../../../common';
+import { getEsQueryConfig, buildEsQuery, Filter, UI_SETTINGS } from '../../../common';
import { getHighlightRequest } from '../../../common/field_formats';
import { fetchSoon } from '../legacy';
import { extractReferences } from './extract_references';
@@ -251,7 +250,7 @@ export class SearchSource {
this.history = [searchRequest];
let response;
- if (uiSettings.get('courier:batchSearches')) {
+ if (uiSettings.get(UI_SETTINGS.COURIER_BATCH_SEARCHES)) {
response = await this.legacyFetch(searchRequest, options);
} else {
response = this.fetch$(searchRequest, options.abortSignal).toPromise();
@@ -365,7 +364,7 @@ export class SearchSource {
const sort = normalizeSortRequest(
val,
this.getField('index'),
- uiSettings.get('sort:options')
+ uiSettings.get(UI_SETTINGS.SORT_OPTIONS)
);
return addToBody(key, sort);
default:
@@ -425,7 +424,7 @@ export class SearchSource {
// exclude source fields for this index pattern specified by the user
const filter = fieldWildcardFilter(
body._source.excludes,
- uiSettings.get(META_FIELDS_SETTING)
+ uiSettings.get(UI_SETTINGS.META_FIELDS)
);
body.docvalue_fields = body.docvalue_fields.filter((docvalueField: any) =>
filter(docvalueField.field)
@@ -448,7 +447,7 @@ export class SearchSource {
body.query = buildEsQuery(index, query, filters, esQueryConfigs);
if (highlightAll && body.query) {
- body.highlight = getHighlightRequest(body.query, uiSettings.get(DOC_HIGHLIGHT_SETTING));
+ body.highlight = getHighlightRequest(body.query, uiSettings.get(UI_SETTINGS.DOC_HIGHLIGHT));
delete searchRequest.highlightAll;
}
diff --git a/src/plugins/data/public/ui/filter_bar/_global_filter_group.scss b/src/plugins/data/public/ui/filter_bar/_global_filter_group.scss
index 1c47c28097454..731c9f4d7f18d 100644
--- a/src/plugins/data/public/ui/filter_bar/_global_filter_group.scss
+++ b/src/plugins/data/public/ui/filter_bar/_global_filter_group.scss
@@ -3,6 +3,10 @@
padding: 0px $euiSizeS $euiSizeS $euiSizeS;
}
+.globalQueryBar:first-child {
+ padding-top: $euiSizeS;
+}
+
.globalQueryBar:not(:empty) {
padding-bottom: $euiSizeS;
}
diff --git a/src/plugins/data/public/ui/filter_bar/filter_bar.tsx b/src/plugins/data/public/ui/filter_bar/filter_bar.tsx
index a54a25acc5913..43dba150bf8d4 100644
--- a/src/plugins/data/public/ui/filter_bar/filter_bar.tsx
+++ b/src/plugins/data/public/ui/filter_bar/filter_bar.tsx
@@ -36,6 +36,7 @@ import {
toggleFilterDisabled,
toggleFilterNegated,
unpinFilter,
+ UI_SETTINGS,
} from '../../../common';
interface Props {
@@ -76,7 +77,7 @@ function FilterBarUI(props: Props) {
}
function renderAddFilter() {
- const isPinned = uiSettings!.get('filters:pinnedByDefault');
+ const isPinned = uiSettings!.get(UI_SETTINGS.FILTERS_PINNED_BY_DEFAULT);
const [indexPattern] = props.indexPatterns;
const index = indexPattern && indexPattern.id;
const newFilter = buildEmptyFilter(isPinned, index);
diff --git a/src/plugins/data/public/ui/filter_bar/filter_editor/phrase_suggestor.tsx b/src/plugins/data/public/ui/filter_bar/filter_editor/phrase_suggestor.tsx
index 546365b89d9be..94138f60b52b1 100644
--- a/src/plugins/data/public/ui/filter_bar/filter_editor/phrase_suggestor.tsx
+++ b/src/plugins/data/public/ui/filter_bar/filter_editor/phrase_suggestor.tsx
@@ -22,6 +22,7 @@ import { debounce } from 'lodash';
import { withKibana, KibanaReactContextValue } from '../../../../../kibana_react/public';
import { IDataPluginServices, IIndexPattern, IFieldType } from '../../..';
+import { UI_SETTINGS } from '../../../../common';
export interface PhraseSuggestorProps {
kibana: KibanaReactContextValue;
@@ -54,7 +55,9 @@ export class PhraseSuggestorUI extends React.Com
}
protected isSuggestingValues() {
- const shouldSuggestValues = this.services.uiSettings.get('filterEditor:suggestValues');
+ const shouldSuggestValues = this.services.uiSettings.get(
+ UI_SETTINGS.FILTERS_EDITOR_SUGGEST_VALUES
+ );
const { field } = this.props;
return shouldSuggestValues && field && field.aggregatable && field.type === 'string';
}
diff --git a/src/plugins/data/public/ui/filter_bar/filter_item.tsx b/src/plugins/data/public/ui/filter_bar/filter_item.tsx
index c44e1faeb8e7f..053fca7d5773b 100644
--- a/src/plugins/data/public/ui/filter_bar/filter_item.tsx
+++ b/src/plugins/data/public/ui/filter_bar/filter_item.tsx
@@ -74,7 +74,8 @@ export function FilterItem(props: Props) {
setIndexPatternExists(false);
});
} else {
- setIndexPatternExists(false);
+ // Allow filters without an index pattern and don't validate them.
+ setIndexPatternExists(true);
}
}, [props.filter.meta.index]);
@@ -244,6 +245,9 @@ export function FilterItem(props: Props) {
* This function makes this behavior explicit, but it needs to be revised.
*/
function isFilterApplicable() {
+ // Any filter is applicable if no index patterns were provided to FilterBar.
+ if (!props.indexPatterns.length) return true;
+
const ip = getIndexPatternFromFilter(filter, indexPatterns);
if (ip) return true;
diff --git a/src/plugins/data/public/ui/query_string_input/query_bar_top_row.test.tsx b/src/plugins/data/public/ui/query_string_input/query_bar_top_row.test.tsx
index f579adbc0c7e2..5f2d4c00cd6b6 100644
--- a/src/plugins/data/public/ui/query_string_input/query_bar_top_row.test.tsx
+++ b/src/plugins/data/public/ui/query_string_input/query_bar_top_row.test.tsx
@@ -28,6 +28,7 @@ import { dataPluginMock } from '../../mocks';
import { KibanaContextProvider } from 'src/plugins/kibana_react/public';
import { I18nProvider } from '@kbn/i18n/react';
import { stubIndexPatternWithFields } from '../../stubs';
+import { UI_SETTINGS } from '../../../common';
const startMock = coreMock.createStart();
const mockTimeHistory = {
@@ -38,7 +39,7 @@ const mockTimeHistory = {
startMock.uiSettings.get.mockImplementation((key: string) => {
switch (key) {
- case 'timepicker:quickRanges':
+ case UI_SETTINGS.TIMEPICKER_QUICK_RANGES:
return [
{
from: 'now/d',
@@ -48,7 +49,7 @@ startMock.uiSettings.get.mockImplementation((key: string) => {
];
case 'dateFormat':
return 'MMM D, YYYY @ HH:mm:ss.SSS';
- case 'history:limit':
+ case UI_SETTINGS.HISTORY_LIMIT:
return 10;
case 'timepicker:timeDefaults':
return {
diff --git a/src/plugins/data/public/ui/query_string_input/query_bar_top_row.tsx b/src/plugins/data/public/ui/query_string_input/query_bar_top_row.tsx
index 433cb652ee5ce..f65bf97e391e2 100644
--- a/src/plugins/data/public/ui/query_string_input/query_bar_top_row.tsx
+++ b/src/plugins/data/public/ui/query_string_input/query_bar_top_row.tsx
@@ -38,7 +38,7 @@ import { Toast } from 'src/core/public';
import { IDataPluginServices, IIndexPattern, TimeRange, TimeHistoryContract, Query } from '../..';
import { useKibana, toMountPoint } from '../../../../kibana_react/public';
import { QueryStringInput } from './query_string_input';
-import { doesKueryExpressionHaveLuceneSyntaxError } from '../../../common';
+import { doesKueryExpressionHaveLuceneSyntaxError, UI_SETTINGS } from '../../../common';
import { PersistedLog, getQueryLog } from '../../query';
interface Props {
@@ -255,7 +255,7 @@ export function QueryBarTopRow(props: Props) {
}
const commonlyUsedRanges = uiSettings!
- .get('timepicker:quickRanges')
+ .get(UI_SETTINGS.TIMEPICKER_QUICK_RANGES)
.map(({ from, to, display }: { from: string; to: string; display: string }) => {
return {
start: from,
diff --git a/src/plugins/data/public/ui/search_bar/create_search_bar.tsx b/src/plugins/data/public/ui/search_bar/create_search_bar.tsx
index 7723254f3aa51..81e84e3198072 100644
--- a/src/plugins/data/public/ui/search_bar/create_search_bar.tsx
+++ b/src/plugins/data/public/ui/search_bar/create_search_bar.tsx
@@ -27,7 +27,7 @@ import { useFilterManager } from './lib/use_filter_manager';
import { useTimefilter } from './lib/use_timefilter';
import { useSavedQuery } from './lib/use_saved_query';
import { DataPublicPluginStart } from '../../types';
-import { Filter, Query, TimeRange } from '../../../common';
+import { Filter, Query, TimeRange, UI_SETTINGS } from '../../../common';
interface StatefulSearchBarDeps {
core: CoreStart;
@@ -125,7 +125,8 @@ export function createSearchBar({ core, storage, data }: StatefulSearchBarDeps)
const defaultQuery = {
query: '',
language:
- storage.get('kibana.userQueryLanguage') || core.uiSettings.get('search:queryLanguage'),
+ storage.get('kibana.userQueryLanguage') ||
+ core.uiSettings.get(UI_SETTINGS.SEARCH_QUERY_LANGUAGE),
};
const [query, setQuery] = useState(props.query || defaultQuery);
@@ -134,12 +135,14 @@ export function createSearchBar({ core, storage, data }: StatefulSearchBarDeps)
queryRef.current = props.query;
setQuery(props.query || defaultQuery);
}
+ /* eslint-disable-next-line react-hooks/exhaustive-deps */
}, [defaultQuery, props.query]);
useEffect(() => {
if (props.onQuerySubmit !== onQuerySubmitRef.current) {
onQuerySubmitRef.current = props.onQuerySubmit;
}
+ /* eslint-disable-next-line react-hooks/exhaustive-deps */
}, [props.onQuerySubmit]);
// handle service state updates.
diff --git a/src/plugins/data/server/index.ts b/src/plugins/data/server/index.ts
index 72a29e377ac54..831d23864d228 100644
--- a/src/plugins/data/server/index.ts
+++ b/src/plugins/data/server/index.ts
@@ -146,6 +146,7 @@ export {
ES_FIELD_TYPES,
KBN_FIELD_TYPES,
IndexPatternAttributes,
+ UI_SETTINGS,
} from '../common';
/**
diff --git a/src/plugins/data/server/kql_telemetry/usage_collector/fetch.test.ts b/src/plugins/data/server/kql_telemetry/usage_collector/fetch.test.ts
index 446320b09757a..81e352fea51b2 100644
--- a/src/plugins/data/server/kql_telemetry/usage_collector/fetch.test.ts
+++ b/src/plugins/data/server/kql_telemetry/usage_collector/fetch.test.ts
@@ -22,6 +22,9 @@ import { APICaller } from 'kibana/server';
jest.mock('../../../common', () => ({
DEFAULT_QUERY_LANGUAGE: 'lucene',
+ UI_SETTINGS: {
+ SEARCH_QUERY_LANGUAGE: 'search:queryLanguage',
+ },
}));
let fetch: ReturnType;
diff --git a/src/plugins/data/server/kql_telemetry/usage_collector/fetch.ts b/src/plugins/data/server/kql_telemetry/usage_collector/fetch.ts
index 9f3437161541f..157716b38f523 100644
--- a/src/plugins/data/server/kql_telemetry/usage_collector/fetch.ts
+++ b/src/plugins/data/server/kql_telemetry/usage_collector/fetch.ts
@@ -19,7 +19,7 @@
import { get } from 'lodash';
import { APICaller } from 'kibana/server';
-import { DEFAULT_QUERY_LANGUAGE } from '../../../common';
+import { DEFAULT_QUERY_LANGUAGE, UI_SETTINGS } from '../../../common';
const defaultSearchQueryLanguageSetting = DEFAULT_QUERY_LANGUAGE;
@@ -40,7 +40,7 @@ export function fetchProvider(index: string) {
const queryLanguageConfigValue = get(
config,
- 'hits.hits[0]._source.config.search:queryLanguage'
+ `hits.hits[0]._source.config.${UI_SETTINGS.SEARCH_QUERY_LANGUAGE}`
);
// search:queryLanguage can potentially be in four states in the .kibana index:
diff --git a/src/plugins/data/server/plugin.ts b/src/plugins/data/server/plugin.ts
index df7a7b9cf4d01..8c9d0df2ed894 100644
--- a/src/plugins/data/server/plugin.ts
+++ b/src/plugins/data/server/plugin.ts
@@ -28,7 +28,7 @@ import { KqlTelemetryService } from './kql_telemetry';
import { UsageCollectionSetup } from '../../usage_collection/server';
import { AutocompleteService } from './autocomplete';
import { FieldFormatsService, FieldFormatsSetup, FieldFormatsStart } from './field_formats';
-import { uiSettings } from './ui_settings';
+import { getUiSettings } from './ui_settings';
export interface DataPluginSetup {
search: ISearchSetup;
@@ -65,7 +65,8 @@ export class DataServerPlugin implements Plugin = (context: ISearchContext, caller: APICaller_2, search: ISearchGeneric) => ISearchStrategy;
+// Warning: (ae-missing-release-tag) "UI_SETTINGS" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+//
+// @public (undocumented)
+export const UI_SETTINGS: {
+ META_FIELDS: string;
+ DOC_HIGHLIGHT: string;
+ QUERY_STRING_OPTIONS: string;
+ QUERY_ALLOW_LEADING_WILDCARDS: string;
+ SEARCH_QUERY_LANGUAGE: string;
+ SORT_OPTIONS: string;
+ COURIER_IGNORE_FILTER_IF_FIELD_NOT_IN_INDEX: string;
+ COURIER_SET_REQUEST_PREFERENCE: string;
+ COURIER_CUSTOM_REQUEST_PREFERENCE: string;
+ COURIER_MAX_CONCURRENT_SHARD_REQUESTS: string;
+ COURIER_BATCH_SEARCHES: string;
+ SEARCH_INCLUDE_FROZEN: string;
+ HISTOGRAM_BAR_TARGET: string;
+ HISTOGRAM_MAX_BARS: string;
+ HISTORY_LIMIT: string;
+ SHORT_DOTS_ENABLE: string;
+ FORMAT_DEFAULT_TYPE_MAP: string;
+ FORMAT_NUMBER_DEFAULT_PATTERN: string;
+ FORMAT_PERCENT_DEFAULT_PATTERN: string;
+ FORMAT_BYTES_DEFAULT_PATTERN: string;
+ FORMAT_CURRENCY_DEFAULT_PATTERN: string;
+ FORMAT_NUMBER_DEFAULT_LOCALE: string;
+ TIMEPICKER_REFRESH_INTERVAL_DEFAULTS: string;
+ TIMEPICKER_QUICK_RANGES: string;
+ INDEXPATTERN_PLACEHOLDER: string;
+ FILTERS_PINNED_BY_DEFAULT: string;
+ FILTERS_EDITOR_SUGGEST_VALUES: string;
+};
+
// Warnings were encountered during analysis:
//
@@ -745,12 +778,12 @@ export type TSearchStrategyProvider = (context: ISearc
// src/plugins/data/server/index.ts:103:26 - (ae-forgotten-export) The symbol "TruncateFormat" needs to be exported by the entry point index.d.ts
// src/plugins/data/server/index.ts:131:27 - (ae-forgotten-export) The symbol "isFilterable" needs to be exported by the entry point index.d.ts
// src/plugins/data/server/index.ts:131:27 - (ae-forgotten-export) The symbol "isNestedField" needs to be exported by the entry point index.d.ts
-// src/plugins/data/server/index.ts:183:1 - (ae-forgotten-export) The symbol "dateHistogramInterval" needs to be exported by the entry point index.d.ts
-// src/plugins/data/server/index.ts:184:1 - (ae-forgotten-export) The symbol "InvalidEsCalendarIntervalError" needs to be exported by the entry point index.d.ts
-// src/plugins/data/server/index.ts:185:1 - (ae-forgotten-export) The symbol "InvalidEsIntervalFormatError" needs to be exported by the entry point index.d.ts
-// src/plugins/data/server/index.ts:186:1 - (ae-forgotten-export) The symbol "isValidEsInterval" needs to be exported by the entry point index.d.ts
-// src/plugins/data/server/index.ts:187:1 - (ae-forgotten-export) The symbol "isValidInterval" needs to be exported by the entry point index.d.ts
-// src/plugins/data/server/index.ts:190:1 - (ae-forgotten-export) The symbol "toAbsoluteDates" needs to be exported by the entry point index.d.ts
+// src/plugins/data/server/index.ts:184:1 - (ae-forgotten-export) The symbol "dateHistogramInterval" needs to be exported by the entry point index.d.ts
+// src/plugins/data/server/index.ts:185:1 - (ae-forgotten-export) The symbol "InvalidEsCalendarIntervalError" needs to be exported by the entry point index.d.ts
+// src/plugins/data/server/index.ts:186:1 - (ae-forgotten-export) The symbol "InvalidEsIntervalFormatError" needs to be exported by the entry point index.d.ts
+// src/plugins/data/server/index.ts:187:1 - (ae-forgotten-export) The symbol "isValidEsInterval" needs to be exported by the entry point index.d.ts
+// src/plugins/data/server/index.ts:188:1 - (ae-forgotten-export) The symbol "isValidInterval" needs to be exported by the entry point index.d.ts
+// src/plugins/data/server/index.ts:191:1 - (ae-forgotten-export) The symbol "toAbsoluteDates" needs to be exported by the entry point index.d.ts
// src/plugins/data/server/plugin.ts:66:14 - (ae-forgotten-export) The symbol "ISearchSetup" needs to be exported by the entry point index.d.ts
// (No @packageDocumentation comment for this package)
diff --git a/src/plugins/data/server/ui_settings.ts b/src/plugins/data/server/ui_settings.ts
index 5af62be295201..de978c7968aee 100644
--- a/src/plugins/data/server/ui_settings.ts
+++ b/src/plugins/data/server/ui_settings.ts
@@ -19,33 +19,652 @@
import { i18n } from '@kbn/i18n';
import { schema } from '@kbn/config-schema';
-
import { UiSettingsParams } from 'kibana/server';
-import { META_FIELDS_SETTING, DOC_HIGHLIGHT_SETTING } from '../common';
+// @ts-ignore untyped module
+import numeralLanguages from '@elastic/numeral/languages';
+import { DEFAULT_QUERY_LANGUAGE, UI_SETTINGS } from '../common';
+
+const luceneQueryLanguageLabel = i18n.translate('data.advancedSettings.searchQueryLanguageLucene', {
+ defaultMessage: 'Lucene',
+});
+
+const queryLanguageSettingName = i18n.translate('data.advancedSettings.searchQueryLanguageTitle', {
+ defaultMessage: 'Query language',
+});
-export const uiSettings: Record = {
- [META_FIELDS_SETTING]: {
- name: i18n.translate('data.advancedSettings.metaFieldsTitle', {
- defaultMessage: 'Meta fields',
- }),
- value: ['_source', '_id', '_type', '_index', '_score'],
- description: i18n.translate('data.advancedSettings.metaFieldsText', {
- defaultMessage:
- 'Fields that exist outside of _source to merge into our document when displaying it',
- }),
- schema: schema.arrayOf(schema.string()),
- },
- [DOC_HIGHLIGHT_SETTING]: {
- name: i18n.translate('data.advancedSettings.docTableHighlightTitle', {
- defaultMessage: 'Highlight results',
- }),
- value: true,
- description: i18n.translate('data.advancedSettings.docTableHighlightText', {
- defaultMessage:
- 'Highlight results in Discover and Saved Searches Dashboard. ' +
- 'Highlighting makes requests slow when working on big documents.',
- }),
- category: ['discover'],
- schema: schema.boolean(),
- },
+const requestPreferenceOptionLabels = {
+ sessionId: i18n.translate('data.advancedSettings.courier.requestPreferenceSessionId', {
+ defaultMessage: 'Session ID',
+ }),
+ custom: i18n.translate('data.advancedSettings.courier.requestPreferenceCustom', {
+ defaultMessage: 'Custom',
+ }),
+ none: i18n.translate('data.advancedSettings.courier.requestPreferenceNone', {
+ defaultMessage: 'None',
+ }),
};
+
+// We add the `en` key manually here, since that's not a real numeral locale, but the
+// default fallback in case the locale is not found.
+const numeralLanguageIds = [
+ 'en',
+ ...numeralLanguages.map((numeralLanguage: any) => {
+ return numeralLanguage.id;
+ }),
+];
+
+export function getUiSettings(): Record> {
+ return {
+ [UI_SETTINGS.META_FIELDS]: {
+ name: i18n.translate('data.advancedSettings.metaFieldsTitle', {
+ defaultMessage: 'Meta fields',
+ }),
+ value: ['_source', '_id', '_type', '_index', '_score'],
+ description: i18n.translate('data.advancedSettings.metaFieldsText', {
+ defaultMessage:
+ 'Fields that exist outside of _source to merge into our document when displaying it',
+ }),
+ schema: schema.arrayOf(schema.string()),
+ },
+ [UI_SETTINGS.DOC_HIGHLIGHT]: {
+ name: i18n.translate('data.advancedSettings.docTableHighlightTitle', {
+ defaultMessage: 'Highlight results',
+ }),
+ value: true,
+ description: i18n.translate('data.advancedSettings.docTableHighlightText', {
+ defaultMessage:
+ 'Highlight results in Discover and Saved Searches Dashboard. ' +
+ 'Highlighting makes requests slow when working on big documents.',
+ }),
+ category: ['discover'],
+ schema: schema.boolean(),
+ },
+ [UI_SETTINGS.QUERY_STRING_OPTIONS]: {
+ name: i18n.translate('data.advancedSettings.query.queryStringOptionsTitle', {
+ defaultMessage: 'Query string options',
+ }),
+ value: '{ "analyze_wildcard": true }',
+ description: i18n.translate('data.advancedSettings.query.queryStringOptionsText', {
+ defaultMessage:
+ '{optionsLink} for the lucene query string parser. Is only used when "{queryLanguage}" is set ' +
+ 'to {luceneLanguage}.',
+ description:
+ 'Part of composite text: data.advancedSettings.query.queryStringOptions.optionsLinkText + ' +
+ 'data.advancedSettings.query.queryStringOptionsText',
+ values: {
+ optionsLink:
+ '' +
+ i18n.translate('data.advancedSettings.query.queryStringOptions.optionsLinkText', {
+ defaultMessage: 'Options',
+ }) +
+ '',
+ luceneLanguage: luceneQueryLanguageLabel,
+ queryLanguage: queryLanguageSettingName,
+ },
+ }),
+ type: 'json',
+ schema: schema.object({
+ analyze_wildcard: schema.boolean(),
+ }),
+ },
+ [UI_SETTINGS.QUERY_ALLOW_LEADING_WILDCARDS]: {
+ name: i18n.translate('data.advancedSettings.query.allowWildcardsTitle', {
+ defaultMessage: 'Allow leading wildcards in query',
+ }),
+ value: true,
+ description: i18n.translate('data.advancedSettings.query.allowWildcardsText', {
+ defaultMessage:
+ 'When set, * is allowed as the first character in a query clause. ' +
+ 'Currently only applies when experimental query features are enabled in the query bar. ' +
+ 'To disallow leading wildcards in basic lucene queries, use {queryStringOptionsPattern}.',
+ values: {
+ queryStringOptionsPattern: UI_SETTINGS.QUERY_STRING_OPTIONS,
+ },
+ }),
+ schema: schema.boolean(),
+ },
+ [UI_SETTINGS.SEARCH_QUERY_LANGUAGE]: {
+ name: queryLanguageSettingName,
+ value: DEFAULT_QUERY_LANGUAGE,
+ description: i18n.translate('data.advancedSettings.searchQueryLanguageText', {
+ defaultMessage:
+ 'Query language used by the query bar. KQL is a new language built specifically for Kibana.',
+ }),
+ type: 'select',
+ options: ['lucene', 'kuery'],
+ optionLabels: {
+ lucene: luceneQueryLanguageLabel,
+ kuery: i18n.translate('data.advancedSettings.searchQueryLanguageKql', {
+ defaultMessage: 'KQL',
+ }),
+ },
+ schema: schema.string(),
+ },
+ [UI_SETTINGS.SORT_OPTIONS]: {
+ name: i18n.translate('data.advancedSettings.sortOptionsTitle', {
+ defaultMessage: 'Sort options',
+ }),
+ value: '{ "unmapped_type": "boolean" }',
+ description: i18n.translate('data.advancedSettings.sortOptionsText', {
+ defaultMessage: '{optionsLink} for the Elasticsearch sort parameter',
+ description:
+ 'Part of composite text: data.advancedSettings.sortOptions.optionsLinkText + ' +
+ 'data.advancedSettings.sortOptionsText',
+ values: {
+ optionsLink:
+ '' +
+ i18n.translate('data.advancedSettings.sortOptions.optionsLinkText', {
+ defaultMessage: 'Options',
+ }) +
+ '',
+ },
+ }),
+ type: 'json',
+ schema: schema.object({
+ unmapped_type: schema.string(),
+ }),
+ },
+ defaultIndex: {
+ name: i18n.translate('data.advancedSettings.defaultIndexTitle', {
+ defaultMessage: 'Default index',
+ }),
+ value: null,
+ type: 'string',
+ description: i18n.translate('data.advancedSettings.defaultIndexText', {
+ defaultMessage: 'The index to access if no index is set',
+ }),
+ schema: schema.nullable(schema.string()),
+ },
+ [UI_SETTINGS.COURIER_IGNORE_FILTER_IF_FIELD_NOT_IN_INDEX]: {
+ name: i18n.translate('data.advancedSettings.courier.ignoreFilterTitle', {
+ defaultMessage: 'Ignore filter(s)',
+ }),
+ value: false,
+ description: i18n.translate('data.advancedSettings.courier.ignoreFilterText', {
+ defaultMessage:
+ 'This configuration enhances support for dashboards containing visualizations accessing dissimilar indexes. ' +
+ 'When disabled, all filters are applied to all visualizations. ' +
+ 'When enabled, filter(s) will be ignored for a visualization ' +
+ `when the visualization's index does not contain the filtering field.`,
+ }),
+ category: ['search'],
+ schema: schema.boolean(),
+ },
+ [UI_SETTINGS.COURIER_SET_REQUEST_PREFERENCE]: {
+ name: i18n.translate('data.advancedSettings.courier.requestPreferenceTitle', {
+ defaultMessage: 'Request preference',
+ }),
+ value: 'sessionId',
+ options: ['sessionId', 'custom', 'none'],
+ optionLabels: requestPreferenceOptionLabels,
+ type: 'select',
+ description: i18n.translate('data.advancedSettings.courier.requestPreferenceText', {
+ defaultMessage: `Allows you to set which shards handle your search requests.
+
+ - {sessionId}: restricts operations to execute all search requests on the same shards.
+ This has the benefit of reusing shard caches across requests.
+ - {custom}: allows you to define a your own preference.
+ Use 'courier:customRequestPreference' to customize your preference value.
+ - {none}: means do not set a preference.
+ This might provide better performance because requests can be spread across all shard copies.
+ However, results might be inconsistent because different shards might be in different refresh states.
+
`,
+ values: {
+ sessionId: requestPreferenceOptionLabels.sessionId,
+ custom: requestPreferenceOptionLabels.custom,
+ none: requestPreferenceOptionLabels.none,
+ },
+ }),
+ category: ['search'],
+ schema: schema.string(),
+ },
+ [UI_SETTINGS.COURIER_CUSTOM_REQUEST_PREFERENCE]: {
+ name: i18n.translate('data.advancedSettings.courier.customRequestPreferenceTitle', {
+ defaultMessage: 'Custom request preference',
+ }),
+ value: '_local',
+ type: 'string',
+ description: i18n.translate('data.advancedSettings.courier.customRequestPreferenceText', {
+ defaultMessage:
+ '{requestPreferenceLink} used when {setRequestReferenceSetting} is set to {customSettingValue}.',
+ description:
+ 'Part of composite text: data.advancedSettings.courier.customRequestPreference.requestPreferenceLinkText + ' +
+ 'data.advancedSettings.courier.customRequestPreferenceText',
+ values: {
+ setRequestReferenceSetting: `${UI_SETTINGS.COURIER_SET_REQUEST_PREFERENCE}`,
+ customSettingValue: '"custom"',
+ requestPreferenceLink:
+ '' +
+ i18n.translate(
+ 'data.advancedSettings.courier.customRequestPreference.requestPreferenceLinkText',
+ {
+ defaultMessage: 'Request Preference',
+ }
+ ) +
+ '',
+ },
+ }),
+ category: ['search'],
+ schema: schema.string(),
+ },
+ [UI_SETTINGS.COURIER_MAX_CONCURRENT_SHARD_REQUESTS]: {
+ name: i18n.translate('data.advancedSettings.courier.maxRequestsTitle', {
+ defaultMessage: 'Max Concurrent Shard Requests',
+ }),
+ value: 0,
+ type: 'number',
+ description: i18n.translate('data.advancedSettings.courier.maxRequestsText', {
+ defaultMessage:
+ 'Controls the {maxRequestsLink} setting used for _msearch requests sent by Kibana. ' +
+ 'Set to 0 to disable this config and use the Elasticsearch default.',
+ values: {
+ maxRequestsLink: `max_concurrent_shard_requests`,
+ },
+ }),
+ category: ['search'],
+ schema: schema.number(),
+ },
+ [UI_SETTINGS.COURIER_BATCH_SEARCHES]: {
+ name: i18n.translate('data.advancedSettings.courier.batchSearchesTitle', {
+ defaultMessage: 'Batch concurrent searches',
+ }),
+ value: false,
+ type: 'boolean',
+ description: i18n.translate('data.advancedSettings.courier.batchSearchesText', {
+ defaultMessage: `When disabled, dashboard panels will load individually, and search requests will terminate when users navigate
+ away or update the query. When enabled, dashboard panels will load together when all of the data is loaded, and
+ searches will not terminate.`,
+ }),
+ deprecation: {
+ message: i18n.translate('data.advancedSettings.courier.batchSearchesTextDeprecation', {
+ defaultMessage: 'This setting is deprecated and will be removed in Kibana 8.0.',
+ }),
+ docLinksKey: 'kibanaSearchSettings',
+ },
+ category: ['search'],
+ schema: schema.boolean(),
+ },
+ [UI_SETTINGS.SEARCH_INCLUDE_FROZEN]: {
+ name: 'Search in frozen indices',
+ description: `Will include frozen indices in results if enabled. Searching through frozen indices
+ might increase the search time.`,
+ value: false,
+ category: ['search'],
+ schema: schema.boolean(),
+ },
+ [UI_SETTINGS.HISTOGRAM_BAR_TARGET]: {
+ name: i18n.translate('data.advancedSettings.histogram.barTargetTitle', {
+ defaultMessage: 'Target bars',
+ }),
+ value: 50,
+ description: i18n.translate('data.advancedSettings.histogram.barTargetText', {
+ defaultMessage:
+ 'Attempt to generate around this many bars when using "auto" interval in date histograms',
+ }),
+ schema: schema.number(),
+ },
+ [UI_SETTINGS.HISTOGRAM_MAX_BARS]: {
+ name: i18n.translate('data.advancedSettings.histogram.maxBarsTitle', {
+ defaultMessage: 'Maximum bars',
+ }),
+ value: 100,
+ description: i18n.translate('data.advancedSettings.histogram.maxBarsText', {
+ defaultMessage:
+ 'Never show more than this many bars in date histograms, scale values if needed',
+ }),
+ schema: schema.number(),
+ },
+ [UI_SETTINGS.HISTORY_LIMIT]: {
+ name: i18n.translate('data.advancedSettings.historyLimitTitle', {
+ defaultMessage: 'History limit',
+ }),
+ value: 10,
+ description: i18n.translate('data.advancedSettings.historyLimitText', {
+ defaultMessage:
+ 'In fields that have history (e.g. query inputs), show this many recent values',
+ }),
+ schema: schema.number(),
+ },
+ [UI_SETTINGS.SHORT_DOTS_ENABLE]: {
+ name: i18n.translate('data.advancedSettings.shortenFieldsTitle', {
+ defaultMessage: 'Shorten fields',
+ }),
+ value: false,
+ description: i18n.translate('data.advancedSettings.shortenFieldsText', {
+ defaultMessage: 'Shorten long fields, for example, instead of foo.bar.baz, show f.b.baz',
+ }),
+ schema: schema.boolean(),
+ },
+ [UI_SETTINGS.FORMAT_DEFAULT_TYPE_MAP]: {
+ name: i18n.translate('data.advancedSettings.format.defaultTypeMapTitle', {
+ defaultMessage: 'Field type format name',
+ }),
+ value: `{
+ "ip": { "id": "ip", "params": {} },
+ "date": { "id": "date", "params": {} },
+ "date_nanos": { "id": "date_nanos", "params": {}, "es": true },
+ "number": { "id": "number", "params": {} },
+ "boolean": { "id": "boolean", "params": {} },
+ "_source": { "id": "_source", "params": {} },
+ "_default_": { "id": "string", "params": {} }
+}`,
+ type: 'json',
+ description: i18n.translate('data.advancedSettings.format.defaultTypeMapText', {
+ defaultMessage:
+ 'Map of the format name to use by default for each field type. ' +
+ '{defaultFormat} is used if the field type is not mentioned explicitly',
+ values: {
+ defaultFormat: '"_default_"',
+ },
+ }),
+ schema: schema.object({
+ ip: schema.object({
+ id: schema.string(),
+ params: schema.object({}),
+ }),
+ date: schema.object({
+ id: schema.string(),
+ params: schema.object({}),
+ }),
+ date_nanos: schema.object({
+ id: schema.string(),
+ params: schema.object({}),
+ es: schema.boolean(),
+ }),
+ number: schema.object({
+ id: schema.string(),
+ params: schema.object({}),
+ }),
+ boolean: schema.object({
+ id: schema.string(),
+ params: schema.object({}),
+ }),
+ _source: schema.object({
+ id: schema.string(),
+ params: schema.object({}),
+ }),
+ _default_: schema.object({
+ id: schema.string(),
+ params: schema.object({}),
+ }),
+ }),
+ },
+ [UI_SETTINGS.FORMAT_NUMBER_DEFAULT_PATTERN]: {
+ name: i18n.translate('data.advancedSettings.format.numberFormatTitle', {
+ defaultMessage: 'Number format',
+ }),
+ value: '0,0.[000]',
+ type: 'string',
+ description: i18n.translate('data.advancedSettings.format.numberFormatText', {
+ defaultMessage: 'Default {numeralFormatLink} for the "number" format',
+ description:
+ 'Part of composite text: data.advancedSettings.format.numberFormatText + ' +
+ 'data.advancedSettings.format.numberFormat.numeralFormatLinkText',
+ values: {
+ numeralFormatLink:
+ '' +
+ i18n.translate('data.advancedSettings.format.numberFormat.numeralFormatLinkText', {
+ defaultMessage: 'numeral format',
+ }) +
+ '',
+ },
+ }),
+ schema: schema.string(),
+ },
+ [UI_SETTINGS.FORMAT_PERCENT_DEFAULT_PATTERN]: {
+ name: i18n.translate('data.advancedSettings.format.percentFormatTitle', {
+ defaultMessage: 'Percent format',
+ }),
+ value: '0,0.[000]%',
+ type: 'string',
+ description: i18n.translate('data.advancedSettings.format.percentFormatText', {
+ defaultMessage: 'Default {numeralFormatLink} for the "percent" format',
+ description:
+ 'Part of composite text: data.advancedSettings.format.percentFormatText + ' +
+ 'data.advancedSettings.format.percentFormat.numeralFormatLinkText',
+ values: {
+ numeralFormatLink:
+ '' +
+ i18n.translate('data.advancedSettings.format.percentFormat.numeralFormatLinkText', {
+ defaultMessage: 'numeral format',
+ }) +
+ '',
+ },
+ }),
+ schema: schema.string(),
+ },
+ [UI_SETTINGS.FORMAT_BYTES_DEFAULT_PATTERN]: {
+ name: i18n.translate('data.advancedSettings.format.bytesFormatTitle', {
+ defaultMessage: 'Bytes format',
+ }),
+ value: '0,0.[0]b',
+ type: 'string',
+ description: i18n.translate('data.advancedSettings.format.bytesFormatText', {
+ defaultMessage: 'Default {numeralFormatLink} for the "bytes" format',
+ description:
+ 'Part of composite text: data.advancedSettings.format.bytesFormatText + ' +
+ 'data.advancedSettings.format.bytesFormat.numeralFormatLinkText',
+ values: {
+ numeralFormatLink:
+ '' +
+ i18n.translate('data.advancedSettings.format.bytesFormat.numeralFormatLinkText', {
+ defaultMessage: 'numeral format',
+ }) +
+ '',
+ },
+ }),
+ schema: schema.string(),
+ },
+ [UI_SETTINGS.FORMAT_CURRENCY_DEFAULT_PATTERN]: {
+ name: i18n.translate('data.advancedSettings.format.currencyFormatTitle', {
+ defaultMessage: 'Currency format',
+ }),
+ value: '($0,0.[00])',
+ type: 'string',
+ description: i18n.translate('data.advancedSettings.format.currencyFormatText', {
+ defaultMessage: 'Default {numeralFormatLink} for the "currency" format',
+ description:
+ 'Part of composite text: data.advancedSettings.format.currencyFormatText + ' +
+ 'data.advancedSettings.format.currencyFormat.numeralFormatLinkText',
+ values: {
+ numeralFormatLink:
+ '' +
+ i18n.translate('data.advancedSettings.format.currencyFormat.numeralFormatLinkText', {
+ defaultMessage: 'numeral format',
+ }) +
+ '',
+ },
+ }),
+ schema: schema.string(),
+ },
+ [UI_SETTINGS.FORMAT_NUMBER_DEFAULT_LOCALE]: {
+ name: i18n.translate('data.advancedSettings.format.formattingLocaleTitle', {
+ defaultMessage: 'Formatting locale',
+ }),
+ value: 'en',
+ type: 'select',
+ options: numeralLanguageIds,
+ optionLabels: Object.fromEntries(
+ numeralLanguages.map((language: Record) => [language.id, language.name])
+ ),
+ description: i18n.translate('data.advancedSettings.format.formattingLocaleText', {
+ defaultMessage: `{numeralLanguageLink} locale`,
+ description:
+ 'Part of composite text: data.advancedSettings.format.formattingLocale.numeralLanguageLinkText + ' +
+ 'data.advancedSettings.format.formattingLocaleText',
+ values: {
+ numeralLanguageLink:
+ '' +
+ i18n.translate(
+ 'data.advancedSettings.format.formattingLocale.numeralLanguageLinkText',
+ {
+ defaultMessage: 'Numeral language',
+ }
+ ) +
+ '',
+ },
+ }),
+ schema: schema.string(),
+ },
+ [UI_SETTINGS.TIMEPICKER_REFRESH_INTERVAL_DEFAULTS]: {
+ name: i18n.translate('data.advancedSettings.timepicker.refreshIntervalDefaultsTitle', {
+ defaultMessage: 'Time filter refresh interval',
+ }),
+ value: `{
+ "pause": false,
+ "value": 0
+}`,
+ type: 'json',
+ description: i18n.translate('data.advancedSettings.timepicker.refreshIntervalDefaultsText', {
+ defaultMessage: `The timefilter's default refresh interval`,
+ }),
+ requiresPageReload: true,
+ schema: schema.object({
+ pause: schema.boolean(),
+ value: schema.number(),
+ }),
+ },
+ [UI_SETTINGS.TIMEPICKER_QUICK_RANGES]: {
+ name: i18n.translate('data.advancedSettings.timepicker.quickRangesTitle', {
+ defaultMessage: 'Time filter quick ranges',
+ }),
+ value: JSON.stringify(
+ [
+ {
+ from: 'now/d',
+ to: 'now/d',
+ display: i18n.translate('data.advancedSettings.timepicker.today', {
+ defaultMessage: 'Today',
+ }),
+ },
+ {
+ from: 'now/w',
+ to: 'now/w',
+ display: i18n.translate('data.advancedSettings.timepicker.thisWeek', {
+ defaultMessage: 'This week',
+ }),
+ },
+ {
+ from: 'now-15m',
+ to: 'now',
+ display: i18n.translate('data.advancedSettings.timepicker.last15Minutes', {
+ defaultMessage: 'Last 15 minutes',
+ }),
+ },
+ {
+ from: 'now-30m',
+ to: 'now',
+ display: i18n.translate('data.advancedSettings.timepicker.last30Minutes', {
+ defaultMessage: 'Last 30 minutes',
+ }),
+ },
+ {
+ from: 'now-1h',
+ to: 'now',
+ display: i18n.translate('data.advancedSettings.timepicker.last1Hour', {
+ defaultMessage: 'Last 1 hour',
+ }),
+ },
+ {
+ from: 'now-24h',
+ to: 'now',
+ display: i18n.translate('data.advancedSettings.timepicker.last24Hours', {
+ defaultMessage: 'Last 24 hours',
+ }),
+ },
+ {
+ from: 'now-7d',
+ to: 'now',
+ display: i18n.translate('data.advancedSettings.timepicker.last7Days', {
+ defaultMessage: 'Last 7 days',
+ }),
+ },
+ {
+ from: 'now-30d',
+ to: 'now',
+ display: i18n.translate('data.advancedSettings.timepicker.last30Days', {
+ defaultMessage: 'Last 30 days',
+ }),
+ },
+ {
+ from: 'now-90d',
+ to: 'now',
+ display: i18n.translate('data.advancedSettings.timepicker.last90Days', {
+ defaultMessage: 'Last 90 days',
+ }),
+ },
+ {
+ from: 'now-1y',
+ to: 'now',
+ display: i18n.translate('data.advancedSettings.timepicker.last1Year', {
+ defaultMessage: 'Last 1 year',
+ }),
+ },
+ ],
+ null,
+ 2
+ ),
+ type: 'json',
+ description: i18n.translate('data.advancedSettings.timepicker.quickRangesText', {
+ defaultMessage:
+ 'The list of ranges to show in the Quick section of the time filter. This should be an array of objects, ' +
+ 'with each object containing "from", "to" (see {acceptedFormatsLink}), and ' +
+ '"display" (the title to be displayed).',
+ description:
+ 'Part of composite text: data.advancedSettings.timepicker.quickRangesText + ' +
+ 'data.advancedSettings.timepicker.quickRanges.acceptedFormatsLinkText',
+ values: {
+ acceptedFormatsLink:
+ `` +
+ i18n.translate('data.advancedSettings.timepicker.quickRanges.acceptedFormatsLinkText', {
+ defaultMessage: 'accepted formats',
+ }) +
+ '',
+ },
+ }),
+ schema: schema.arrayOf(
+ schema.object({
+ from: schema.string(),
+ to: schema.string(),
+ display: schema.string(),
+ })
+ ),
+ },
+ [UI_SETTINGS.INDEXPATTERN_PLACEHOLDER]: {
+ name: i18n.translate('data.advancedSettings.indexPatternPlaceholderTitle', {
+ defaultMessage: 'Index pattern placeholder',
+ }),
+ value: '',
+ description: i18n.translate('data.advancedSettings.indexPatternPlaceholderText', {
+ defaultMessage:
+ 'The placeholder for the "Index pattern name" field in "Management > Index Patterns > Create Index Pattern".',
+ }),
+ schema: schema.string(),
+ },
+ [UI_SETTINGS.FILTERS_PINNED_BY_DEFAULT]: {
+ name: i18n.translate('data.advancedSettings.pinFiltersTitle', {
+ defaultMessage: 'Pin filters by default',
+ }),
+ value: false,
+ description: i18n.translate('data.advancedSettings.pinFiltersText', {
+ defaultMessage: 'Whether the filters should have a global state (be pinned) by default',
+ }),
+ schema: schema.boolean(),
+ },
+ [UI_SETTINGS.FILTERS_EDITOR_SUGGEST_VALUES]: {
+ name: i18n.translate('data.advancedSettings.suggestFilterValuesTitle', {
+ defaultMessage: 'Filter editor suggest values',
+ description: '"Filter editor" refers to the UI you create filters in.',
+ }),
+ value: true,
+ description: i18n.translate('data.advancedSettings.suggestFilterValuesText', {
+ defaultMessage:
+ 'Set this property to false to prevent the filter editor from suggesting values for fields.',
+ }),
+ schema: schema.boolean(),
+ },
+ };
+}
diff --git a/src/plugins/discover/kibana.json b/src/plugins/discover/kibana.json
index 0b3a07e98624e..14dd399697b56 100644
--- a/src/plugins/discover/kibana.json
+++ b/src/plugins/discover/kibana.json
@@ -1,6 +1,7 @@
{
"id": "discover",
"version": "kibana",
+ "optionalPlugins": ["share"],
"server": true,
"ui": true,
"requiredPlugins": [
diff --git a/src/plugins/discover/public/application/angular/discover.js b/src/plugins/discover/public/application/angular/discover.js
index 1a2bff8211db5..88885b3eb211b 100644
--- a/src/plugins/discover/public/application/angular/discover.js
+++ b/src/plugins/discover/public/application/angular/discover.js
@@ -72,6 +72,7 @@ import {
syncQueryStateWithUrl,
getDefaultQuery,
search,
+ UI_SETTINGS,
} from '../../../../data/public';
import { getIndexPatternId } from '../helpers/get_index_pattern_id';
import { addFatalError } from '../../../../kibana_legacy/public';
@@ -592,7 +593,8 @@ function discoverController(
const query =
$scope.searchSource.getField('query') ||
getDefaultQuery(
- localStorage.get('kibana.userQueryLanguage') || config.get('search:queryLanguage')
+ localStorage.get('kibana.userQueryLanguage') ||
+ config.get(UI_SETTINGS.SEARCH_QUERY_LANGUAGE)
);
return {
query,
@@ -750,6 +752,13 @@ function discoverController(
// Update defaults so that "reload saved query" functions correctly
setAppState(getStateDefaults());
chrome.docTitle.change(savedSearch.lastSavedTitle);
+ chrome.setBreadcrumbs([
+ {
+ text: discoverBreadcrumbsTitle,
+ href: '#/',
+ },
+ { text: savedSearch.title },
+ ]);
}
}
});
diff --git a/src/plugins/discover/public/application/angular/doc_table/components/table_header.ts b/src/plugins/discover/public/application/angular/doc_table/components/table_header.ts
index 60dfb69e85e74..82bfcc8bc42f9 100644
--- a/src/plugins/discover/public/application/angular/doc_table/components/table_header.ts
+++ b/src/plugins/discover/public/application/angular/doc_table/components/table_header.ts
@@ -19,6 +19,7 @@
import { TableHeader } from './table_header/table_header';
import { getServices } from '../../../../kibana_services';
import { SORT_DEFAULT_ORDER_SETTING, DOC_HIDE_TIME_COLUMN_SETTING } from '../../../../../common';
+import { UI_SETTINGS } from '../../../../../../data/public';
export function createTableHeaderDirective(reactDirective: any) {
const { uiSettings: config } = getServices();
@@ -38,7 +39,7 @@ export function createTableHeaderDirective(reactDirective: any) {
{ restrict: 'A' },
{
hideTimeColumn: config.get(DOC_HIDE_TIME_COLUMN_SETTING, false),
- isShortDots: config.get('shortDots:enable'),
+ isShortDots: config.get(UI_SETTINGS.SHORT_DOTS_ENABLE),
defaultSortOrder: config.get(SORT_DEFAULT_ORDER_SETTING, 'desc'),
}
);
diff --git a/src/plugins/discover/public/application/components/sidebar/discover_sidebar.tsx b/src/plugins/discover/public/application/components/sidebar/discover_sidebar.tsx
index 99a5547ed0760..5a319d30b2515 100644
--- a/src/plugins/discover/public/application/components/sidebar/discover_sidebar.tsx
+++ b/src/plugins/discover/public/application/components/sidebar/discover_sidebar.tsx
@@ -33,6 +33,7 @@ import {
IIndexPatternFieldList,
IndexPatternField,
IndexPattern,
+ UI_SETTINGS,
} from '../../../../../data/public';
import { AppState } from '../../angular/discover_state';
import { getDetails } from './lib/get_details';
@@ -133,7 +134,7 @@ export function DiscoverSidebar({
);
const popularLimit = services.uiSettings.get(FIELDS_LIMIT_SETTING);
- const useShortDots = services.uiSettings.get('shortDots:enable');
+ const useShortDots = services.uiSettings.get(UI_SETTINGS.SHORT_DOTS_ENABLE);
const {
selected: selectedFields,
diff --git a/src/plugins/discover/public/index.ts b/src/plugins/discover/public/index.ts
index 359d91325f064..4154fdfeb3ff4 100644
--- a/src/plugins/discover/public/index.ts
+++ b/src/plugins/discover/public/index.ts
@@ -27,3 +27,4 @@ export function plugin(initializerContext: PluginInitializerContext) {
export { SavedSearch, SavedSearchLoader, createSavedSearchesLoader } from './saved_searches';
export { ISearchEmbeddable, SEARCH_EMBEDDABLE_TYPE, SearchInput } from './application/embeddable';
+export { DISCOVER_APP_URL_GENERATOR } from './url_generator';
diff --git a/src/plugins/discover/public/mocks.ts b/src/plugins/discover/public/mocks.ts
index c394fe2c11a71..e4314426bfce5 100644
--- a/src/plugins/discover/public/mocks.ts
+++ b/src/plugins/discover/public/mocks.ts
@@ -34,6 +34,9 @@ const createSetupContract = (): Setup => {
const createStartContract = (): Start => {
const startContract: Start = {
savedSearchLoader: {} as any,
+ urlGenerator: {
+ createUrl: jest.fn(),
+ } as any,
};
return startContract;
};
diff --git a/src/plugins/discover/public/plugin.ts b/src/plugins/discover/public/plugin.ts
index 4323e3d8deda4..091288e3e65aa 100644
--- a/src/plugins/discover/public/plugin.ts
+++ b/src/plugins/discover/public/plugin.ts
@@ -34,7 +34,7 @@ import { UiActionsStart, UiActionsSetup } from 'src/plugins/ui_actions/public';
import { EmbeddableStart, EmbeddableSetup } from 'src/plugins/embeddable/public';
import { ChartsPluginStart } from 'src/plugins/charts/public';
import { NavigationPublicPluginStart as NavigationStart } from 'src/plugins/navigation/public';
-import { SharePluginStart } from 'src/plugins/share/public';
+import { SharePluginStart, SharePluginSetup, UrlGeneratorContract } from 'src/plugins/share/public';
import { VisualizationsStart, VisualizationsSetup } from 'src/plugins/visualizations/public';
import { KibanaLegacySetup } from 'src/plugins/kibana_legacy/public';
import { HomePublicPluginSetup } from 'src/plugins/home/public';
@@ -43,7 +43,7 @@ import { DataPublicPluginStart, DataPublicPluginSetup, esFilters } from '../../d
import { SavedObjectLoader } from '../../saved_objects/public';
import { createKbnUrlTracker } from '../../kibana_utils/public';
import { DEFAULT_APP_CATEGORIES } from '../../../core/public';
-
+import { UrlGeneratorState } from '../../share/public';
import { DocViewInput, DocViewInputFn } from './application/doc_views/doc_views_types';
import { DocViewsRegistry } from './application/doc_views/doc_views_registry';
import { DocViewTable } from './application/components/table/table';
@@ -59,6 +59,17 @@ import {
import { createSavedSearchesLoader } from './saved_searches';
import { registerFeature } from './register_feature';
import { buildServices } from './build_services';
+import {
+ DiscoverUrlGeneratorState,
+ DISCOVER_APP_URL_GENERATOR,
+ DiscoverUrlGenerator,
+} from './url_generator';
+
+declare module '../../share/public' {
+ export interface UrlGeneratorStateMapping {
+ [DISCOVER_APP_URL_GENERATOR]: UrlGeneratorState;
+ }
+}
/**
* @public
@@ -76,12 +87,31 @@ export interface DiscoverSetup {
export interface DiscoverStart {
savedSearchLoader: SavedObjectLoader;
+
+ /**
+ * `share` plugin URL generator for Discover app. Use it to generate links into
+ * Discover application, example:
+ *
+ * ```ts
+ * const url = await plugins.discover.urlGenerator.createUrl({
+ * savedSearchId: '571aaf70-4c88-11e8-b3d7-01146121b73d',
+ * indexPatternId: 'c367b774-a4c2-11ea-bb37-0242ac130002',
+ * timeRange: {
+ * to: 'now',
+ * from: 'now-15m',
+ * mode: 'relative',
+ * },
+ * });
+ * ```
+ */
+ readonly urlGenerator: undefined | UrlGeneratorContract<'DISCOVER_APP_URL_GENERATOR'>;
}
/**
* @internal
*/
export interface DiscoverSetupPlugins {
+ share?: SharePluginSetup;
uiActions: UiActionsSetup;
embeddable: EmbeddableSetup;
kibanaLegacy: KibanaLegacySetup;
@@ -122,6 +152,7 @@ export class DiscoverPlugin
private stopUrlTracking: (() => void) | undefined = undefined;
private servicesInitialized: boolean = false;
private innerAngularInitialized: boolean = false;
+ private urlGenerator?: DiscoverStart['urlGenerator'];
/**
* why are those functions public? they are needed for some mocha tests
@@ -131,6 +162,17 @@ export class DiscoverPlugin
public initializeServices?: () => Promise<{ core: CoreStart; plugins: DiscoverStartPlugins }>;
setup(core: CoreSetup, plugins: DiscoverSetupPlugins) {
+ const baseUrl = core.http.basePath.prepend('/app/discover');
+
+ if (plugins.share) {
+ this.urlGenerator = plugins.share.urlGenerators.registerUrlGenerator(
+ new DiscoverUrlGenerator({
+ appBasePath: baseUrl,
+ useHash: core.uiSettings.get('state:storeInSessionStorage'),
+ })
+ );
+ }
+
this.docViewsRegistry = new DocViewsRegistry();
setDocViewsRegistry(this.docViewsRegistry);
this.docViewsRegistry.addDocView({
@@ -158,7 +200,7 @@ export class DiscoverPlugin
// so history is lazily created (when app is mounted)
// this prevents redundant `#` when not in discover app
getHistory: getScopedHistory,
- baseUrl: core.http.basePath.prepend('/app/discover'),
+ baseUrl,
defaultSubUrl: '#/',
storageKey: `lastUrl:${core.http.basePath.get()}:discover`,
navLinkUpdater$: this.appStateUpdater,
@@ -266,6 +308,7 @@ export class DiscoverPlugin
};
return {
+ urlGenerator: this.urlGenerator,
savedSearchLoader: createSavedSearchesLoader({
savedObjectsClient: core.savedObjects.client,
indexPatterns: plugins.data.indexPatterns,
diff --git a/src/plugins/discover/public/url_generator.test.ts b/src/plugins/discover/public/url_generator.test.ts
new file mode 100644
index 0000000000000..cf9beb246fea2
--- /dev/null
+++ b/src/plugins/discover/public/url_generator.test.ts
@@ -0,0 +1,259 @@
+/*
+ * 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 { DiscoverUrlGenerator } from './url_generator';
+import { hashedItemStore, getStatesFromKbnUrl } from '../../kibana_utils/public';
+// eslint-disable-next-line
+import { mockStorage } from '../../kibana_utils/public/storage/hashed_item_store/mock';
+import { FilterStateStore } from '../../data/common';
+
+const appBasePath: string = 'xyz/app/discover';
+const indexPatternId: string = 'c367b774-a4c2-11ea-bb37-0242ac130002';
+const savedSearchId: string = '571aaf70-4c88-11e8-b3d7-01146121b73d';
+
+interface SetupParams {
+ useHash?: boolean;
+}
+
+const setup = async ({ useHash = false }: SetupParams = {}) => {
+ const generator = new DiscoverUrlGenerator({
+ appBasePath,
+ useHash,
+ });
+
+ return {
+ generator,
+ };
+};
+
+beforeEach(() => {
+ // @ts-ignore
+ hashedItemStore.storage = mockStorage;
+});
+
+describe('Discover url generator', () => {
+ test('can create a link to Discover with no state and no saved search', async () => {
+ const { generator } = await setup();
+ const url = await generator.createUrl({});
+ const { _a, _g } = getStatesFromKbnUrl(url, ['_a', '_g']);
+
+ expect(url.startsWith(appBasePath)).toBe(true);
+ expect(_a).toEqual({});
+ expect(_g).toEqual({});
+ });
+
+ test('can create a link to a saved search in Discover', async () => {
+ const { generator } = await setup();
+ const url = await generator.createUrl({ savedSearchId });
+ const { _a, _g } = getStatesFromKbnUrl(url, ['_a', '_g']);
+
+ expect(url.startsWith(`${appBasePath}#/${savedSearchId}`)).toBe(true);
+ expect(_a).toEqual({});
+ expect(_g).toEqual({});
+ });
+
+ test('can specify specific index pattern', async () => {
+ const { generator } = await setup();
+ const url = await generator.createUrl({
+ indexPatternId,
+ });
+ const { _a, _g } = getStatesFromKbnUrl(url, ['_a', '_g']);
+
+ expect(_a).toEqual({
+ index: indexPatternId,
+ });
+ expect(_g).toEqual({});
+ });
+
+ test('can specify specific time range', async () => {
+ const { generator } = await setup();
+ const url = await generator.createUrl({
+ timeRange: { to: 'now', from: 'now-15m', mode: 'relative' },
+ });
+ const { _a, _g } = getStatesFromKbnUrl(url, ['_a', '_g']);
+
+ expect(_a).toEqual({});
+ expect(_g).toEqual({
+ time: {
+ from: 'now-15m',
+ mode: 'relative',
+ to: 'now',
+ },
+ });
+ });
+
+ test('can specify query', async () => {
+ const { generator } = await setup();
+ const url = await generator.createUrl({
+ query: {
+ language: 'kuery',
+ query: 'foo',
+ },
+ });
+ const { _a, _g } = getStatesFromKbnUrl(url, ['_a', '_g']);
+
+ expect(_a).toEqual({
+ query: {
+ language: 'kuery',
+ query: 'foo',
+ },
+ });
+ expect(_g).toEqual({});
+ });
+
+ test('can specify local and global filters', async () => {
+ const { generator } = await setup();
+ const url = await generator.createUrl({
+ filters: [
+ {
+ meta: {
+ alias: 'foo',
+ disabled: false,
+ negate: false,
+ },
+ $state: {
+ store: FilterStateStore.APP_STATE,
+ },
+ },
+ {
+ meta: {
+ alias: 'bar',
+ disabled: false,
+ negate: false,
+ },
+ $state: {
+ store: FilterStateStore.GLOBAL_STATE,
+ },
+ },
+ ],
+ });
+ const { _a, _g } = getStatesFromKbnUrl(url, ['_a', '_g']);
+
+ expect(_a).toEqual({
+ filters: [
+ {
+ $state: {
+ store: 'appState',
+ },
+ meta: {
+ alias: 'foo',
+ disabled: false,
+ negate: false,
+ },
+ },
+ ],
+ });
+ expect(_g).toEqual({
+ filters: [
+ {
+ $state: {
+ store: 'globalState',
+ },
+ meta: {
+ alias: 'bar',
+ disabled: false,
+ negate: false,
+ },
+ },
+ ],
+ });
+ });
+
+ test('can set refresh interval', async () => {
+ const { generator } = await setup();
+ const url = await generator.createUrl({
+ refreshInterval: {
+ pause: false,
+ value: 666,
+ },
+ });
+ const { _a, _g } = getStatesFromKbnUrl(url, ['_a', '_g']);
+
+ expect(_a).toEqual({});
+ expect(_g).toEqual({
+ refreshInterval: {
+ pause: false,
+ value: 666,
+ },
+ });
+ });
+
+ test('can set time range', async () => {
+ const { generator } = await setup();
+ const url = await generator.createUrl({
+ timeRange: {
+ from: 'now-3h',
+ to: 'now',
+ },
+ });
+ const { _a, _g } = getStatesFromKbnUrl(url, ['_a', '_g']);
+
+ expect(_a).toEqual({});
+ expect(_g).toEqual({
+ time: {
+ from: 'now-3h',
+ to: 'now',
+ },
+ });
+ });
+
+ describe('useHash property', () => {
+ describe('when default useHash is set to false', () => {
+ test('when using default, sets index pattern ID in the generated URL', async () => {
+ const { generator } = await setup();
+ const url = await generator.createUrl({
+ indexPatternId,
+ });
+
+ expect(url.indexOf(indexPatternId) > -1).toBe(true);
+ });
+
+ test('when enabling useHash, does not set index pattern ID in the generated URL', async () => {
+ const { generator } = await setup();
+ const url = await generator.createUrl({
+ useHash: true,
+ indexPatternId,
+ });
+
+ expect(url.indexOf(indexPatternId) > -1).toBe(false);
+ });
+ });
+
+ describe('when default useHash is set to true', () => {
+ test('when using default, does not set index pattern ID in the generated URL', async () => {
+ const { generator } = await setup({ useHash: true });
+ const url = await generator.createUrl({
+ indexPatternId,
+ });
+
+ expect(url.indexOf(indexPatternId) > -1).toBe(false);
+ });
+
+ test('when disabling useHash, sets index pattern ID in the generated URL', async () => {
+ const { generator } = await setup();
+ const url = await generator.createUrl({
+ useHash: false,
+ indexPatternId,
+ });
+
+ expect(url.indexOf(indexPatternId) > -1).toBe(true);
+ });
+ });
+ });
+});
diff --git a/src/plugins/discover/public/url_generator.ts b/src/plugins/discover/public/url_generator.ts
new file mode 100644
index 0000000000000..42d689050d5ad
--- /dev/null
+++ b/src/plugins/discover/public/url_generator.ts
@@ -0,0 +1,114 @@
+/*
+ * 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 {
+ TimeRange,
+ Filter,
+ Query,
+ esFilters,
+ QueryState,
+ RefreshInterval,
+} from '../../data/public';
+import { setStateToKbnUrl } from '../../kibana_utils/public';
+import { UrlGeneratorsDefinition } from '../../share/public';
+
+export const DISCOVER_APP_URL_GENERATOR = 'DISCOVER_APP_URL_GENERATOR';
+
+export interface DiscoverUrlGeneratorState {
+ /**
+ * Optionally set saved search ID.
+ */
+ savedSearchId?: string;
+
+ /**
+ * Optionally set index pattern ID.
+ */
+ indexPatternId?: string;
+
+ /**
+ * Optionally set the time range in the time picker.
+ */
+ timeRange?: TimeRange;
+
+ /**
+ * Optionally set the refresh interval.
+ */
+ refreshInterval?: RefreshInterval;
+
+ /**
+ * Optionally apply filers.
+ */
+ filters?: Filter[];
+
+ /**
+ * Optionally set a query. NOTE: if given and used in conjunction with `dashboardId`, and the
+ * saved dashboard has a query saved with it, this will _replace_ that query.
+ */
+ query?: Query;
+
+ /**
+ * If not given, will use the uiSettings configuration for `storeInSessionStorage`. useHash determines
+ * whether to hash the data in the url to avoid url length issues.
+ */
+ useHash?: boolean;
+}
+
+interface Params {
+ appBasePath: string;
+ useHash: boolean;
+}
+
+export class DiscoverUrlGenerator
+ implements UrlGeneratorsDefinition {
+ constructor(private readonly params: Params) {}
+
+ public readonly id = DISCOVER_APP_URL_GENERATOR;
+
+ public readonly createUrl = async ({
+ filters,
+ indexPatternId,
+ query,
+ refreshInterval,
+ savedSearchId,
+ timeRange,
+ useHash = this.params.useHash,
+ }: DiscoverUrlGeneratorState): Promise => {
+ const savedSearchPath = savedSearchId ? encodeURIComponent(savedSearchId) : '';
+ const appState: {
+ query?: Query;
+ filters?: Filter[];
+ index?: string;
+ } = {};
+ const queryState: QueryState = {};
+
+ if (query) appState.query = query;
+ if (filters) appState.filters = filters?.filter((f) => !esFilters.isFilterPinned(f));
+ if (indexPatternId) appState.index = indexPatternId;
+
+ if (timeRange) queryState.time = timeRange;
+ if (filters) queryState.filters = filters?.filter((f) => esFilters.isFilterPinned(f));
+ if (refreshInterval) queryState.refreshInterval = refreshInterval;
+
+ let url = `${this.params.appBasePath}#/${savedSearchPath}`;
+ url = setStateToKbnUrl('_g', queryState, { useHash }, url);
+ url = setStateToKbnUrl('_a', appState, { useHash }, url);
+
+ return url;
+ };
+}
diff --git a/src/plugins/embeddable/public/lib/containers/embeddable_child_panel.test.tsx b/src/plugins/embeddable/public/lib/containers/embeddable_child_panel.test.tsx
index b046376a304ae..e29e941e898fb 100644
--- a/src/plugins/embeddable/public/lib/containers/embeddable_child_panel.test.tsx
+++ b/src/plugins/embeddable/public/lib/containers/embeddable_child_panel.test.tsx
@@ -31,7 +31,7 @@ import {
// eslint-disable-next-line
import { inspectorPluginMock } from '../../../../inspector/public/mocks';
import { mount } from 'enzyme';
-import { embeddablePluginMock } from '../../mocks';
+import { embeddablePluginMock, createEmbeddablePanelMock } from '../../mocks';
test('EmbeddableChildPanel renders an embeddable when it is done loading', async () => {
const inspector = inspectorPluginMock.createStartContract();
@@ -58,18 +58,17 @@ test('EmbeddableChildPanel renders an embeddable when it is done loading', async
expect(newEmbeddable.id).toBeDefined();
+ const testPanel = createEmbeddablePanelMock({
+ getAllEmbeddableFactories: start.getEmbeddableFactories,
+ getEmbeddableFactory,
+ inspector,
+ });
+
const component = mount(
Promise.resolve([])}
- getAllEmbeddableFactories={start.getEmbeddableFactories}
- getEmbeddableFactory={getEmbeddableFactory}
- notifications={{} as any}
- application={{} as any}
- overlays={{} as any}
- inspector={inspector}
- SavedObjectFinder={() => null}
+ PanelComponent={testPanel}
/>
);
@@ -97,19 +96,9 @@ test(`EmbeddableChildPanel renders an error message if the factory doesn't exist
{ getEmbeddableFactory } as any
);
+ const testPanel = createEmbeddablePanelMock({ inspector });
const component = mount(
- Promise.resolve([])}
- getAllEmbeddableFactories={(() => []) as any}
- getEmbeddableFactory={(() => undefined) as any}
- notifications={{} as any}
- overlays={{} as any}
- application={{} as any}
- inspector={inspector}
- SavedObjectFinder={() => null}
- />
+
);
await nextTick();
diff --git a/src/plugins/embeddable/public/lib/containers/embeddable_child_panel.tsx b/src/plugins/embeddable/public/lib/containers/embeddable_child_panel.tsx
index 70628665e6e8c..be8ff2c95fe09 100644
--- a/src/plugins/embeddable/public/lib/containers/embeddable_child_panel.tsx
+++ b/src/plugins/embeddable/public/lib/containers/embeddable_child_panel.tsx
@@ -22,12 +22,7 @@ import React from 'react';
import { EuiLoadingChart } from '@elastic/eui';
import { Subscription } from 'rxjs';
-import { CoreStart } from 'src/core/public';
-import { UiActionsService } from 'src/plugins/ui_actions/public';
-
-import { Start as InspectorStartContract } from 'src/plugins/inspector/public';
import { ErrorEmbeddable, IEmbeddable } from '../embeddables';
-import { EmbeddablePanel } from '../panel';
import { IContainer } from './i_container';
import { EmbeddableStart } from '../../plugin';
@@ -35,14 +30,7 @@ export interface EmbeddableChildPanelProps {
embeddableId: string;
className?: string;
container: IContainer;
- getActions: UiActionsService['getTriggerCompatibleActions'];
- getEmbeddableFactory: EmbeddableStart['getEmbeddableFactory'];
- getAllEmbeddableFactories: EmbeddableStart['getEmbeddableFactories'];
- overlays: CoreStart['overlays'];
- notifications: CoreStart['notifications'];
- application: CoreStart['application'];
- inspector: InspectorStartContract;
- SavedObjectFinder: React.ComponentType;
+ PanelComponent: EmbeddableStart['EmbeddablePanel'];
}
interface State {
@@ -87,6 +75,7 @@ export class EmbeddableChildPanel extends React.Component
) : (
-
+
)}
);
diff --git a/src/plugins/embeddable/public/lib/test_samples/embeddables/hello_world_container.tsx b/src/plugins/embeddable/public/lib/test_samples/embeddables/hello_world_container.tsx
index 31e14a0af59d7..913c3a0b30826 100644
--- a/src/plugins/embeddable/public/lib/test_samples/embeddables/hello_world_container.tsx
+++ b/src/plugins/embeddable/public/lib/test_samples/embeddables/hello_world_container.tsx
@@ -19,9 +19,6 @@
import React from 'react';
import ReactDOM from 'react-dom';
import { I18nProvider } from '@kbn/i18n/react';
-import { CoreStart } from 'src/core/public';
-import { UiActionsService } from 'src/plugins/ui_actions/public';
-import { Start as InspectorStartContract } from 'src/plugins/inspector/public';
import { Container, ViewMode, ContainerInput } from '../..';
import { HelloWorldContainerComponent } from './hello_world_container_component';
import { EmbeddableStart } from '../../../plugin';
@@ -45,14 +42,8 @@ interface HelloWorldContainerInput extends ContainerInput {
}
interface HelloWorldContainerOptions {
- getActions: UiActionsService['getTriggerCompatibleActions'];
getEmbeddableFactory: EmbeddableStart['getEmbeddableFactory'];
- getAllEmbeddableFactories: EmbeddableStart['getEmbeddableFactories'];
- overlays: CoreStart['overlays'];
- application: CoreStart['application'];
- notifications: CoreStart['notifications'];
- inspector: InspectorStartContract;
- SavedObjectFinder: React.ComponentType;
+ panelComponent: EmbeddableStart['EmbeddablePanel'];
}
export class HelloWorldContainer extends Container {
@@ -78,14 +69,7 @@ export class HelloWorldContainer extends Container
,
node
diff --git a/src/plugins/embeddable/public/lib/test_samples/embeddables/hello_world_container_component.tsx b/src/plugins/embeddable/public/lib/test_samples/embeddables/hello_world_container_component.tsx
index 6453046b86e20..5fefa1fc90720 100644
--- a/src/plugins/embeddable/public/lib/test_samples/embeddables/hello_world_container_component.tsx
+++ b/src/plugins/embeddable/public/lib/test_samples/embeddables/hello_world_container_component.tsx
@@ -20,22 +20,12 @@ import React, { Component, RefObject } from 'react';
import { Subscription } from 'rxjs';
import { EuiFlexGroup, EuiFlexItem, EuiSpacer } from '@elastic/eui';
-import { CoreStart } from 'src/core/public';
-import { UiActionsService } from 'src/plugins/ui_actions/public';
-import { Start as InspectorStartContract } from 'src/plugins/inspector/public';
import { IContainer, PanelState, EmbeddableChildPanel } from '../..';
import { EmbeddableStart } from '../../../plugin';
interface Props {
container: IContainer;
- getActions: UiActionsService['getTriggerCompatibleActions'];
- getEmbeddableFactory: EmbeddableStart['getEmbeddableFactory'];
- getAllEmbeddableFactories: EmbeddableStart['getEmbeddableFactories'];
- overlays: CoreStart['overlays'];
- application: CoreStart['application'];
- notifications: CoreStart['notifications'];
- inspector: InspectorStartContract;
- SavedObjectFinder: React.ComponentType;
+ panelComponent: EmbeddableStart['EmbeddablePanel'];
}
interface State {
@@ -108,14 +98,7 @@ export class HelloWorldContainerComponent extends Component {
);
diff --git a/src/plugins/embeddable/public/mocks.ts b/src/plugins/embeddable/public/mocks.tsx
similarity index 62%
rename from src/plugins/embeddable/public/mocks.ts
rename to src/plugins/embeddable/public/mocks.tsx
index f5487c381cfcb..9da0b7602c4f8 100644
--- a/src/plugins/embeddable/public/mocks.ts
+++ b/src/plugins/embeddable/public/mocks.tsx
@@ -16,14 +16,20 @@
* specific language governing permissions and limitations
* under the License.
*/
+import React from 'react';
import {
EmbeddableStart,
EmbeddableSetup,
EmbeddableSetupDependencies,
EmbeddableStartDependencies,
+ IEmbeddable,
+ EmbeddablePanel,
} from '.';
import { EmbeddablePublicPlugin } from './plugin';
import { coreMock } from '../../../core/public/mocks';
+import { UiActionsService } from './lib/ui_actions';
+import { CoreStart } from '../../../core/public';
+import { Start as InspectorStart } from '../../inspector/public';
// eslint-disable-next-line
import { inspectorPluginMock } from '../../inspector/public/mocks';
@@ -33,6 +39,42 @@ import { uiActionsPluginMock } from '../../ui_actions/public/mocks';
export type Setup = jest.Mocked;
export type Start = jest.Mocked;
+interface CreateEmbeddablePanelMockArgs {
+ getActions: UiActionsService['getTriggerCompatibleActions'];
+ getEmbeddableFactory: EmbeddableStart['getEmbeddableFactory'];
+ getAllEmbeddableFactories: EmbeddableStart['getEmbeddableFactories'];
+ overlays: CoreStart['overlays'];
+ notifications: CoreStart['notifications'];
+ application: CoreStart['application'];
+ inspector: InspectorStart;
+ SavedObjectFinder: React.ComponentType;
+}
+
+export const createEmbeddablePanelMock = ({
+ getActions,
+ getEmbeddableFactory,
+ getAllEmbeddableFactories,
+ overlays,
+ notifications,
+ application,
+ inspector,
+ SavedObjectFinder,
+}: Partial) => {
+ return ({ embeddable }: { embeddable: IEmbeddable }) => (
+ Promise.resolve([]))}
+ getAllEmbeddableFactories={getAllEmbeddableFactories || ((() => []) as any)}
+ getEmbeddableFactory={getEmbeddableFactory || ((() => undefined) as any)}
+ notifications={notifications || ({} as any)}
+ application={application || ({} as any)}
+ overlays={overlays || ({} as any)}
+ inspector={inspector || ({} as any)}
+ SavedObjectFinder={SavedObjectFinder || (() => null)}
+ />
+ );
+};
+
const createSetupContract = (): Setup => {
const setupContract: Setup = {
registerEmbeddableFactory: jest.fn(),
diff --git a/src/plugins/embeddable/public/tests/apply_filter_action.test.ts b/src/plugins/embeddable/public/tests/apply_filter_action.test.ts
index ebb76c743393b..ec92f334267f5 100644
--- a/src/plugins/embeddable/public/tests/apply_filter_action.test.ts
+++ b/src/plugins/embeddable/public/tests/apply_filter_action.test.ts
@@ -31,8 +31,7 @@ import {
FilterableEmbeddableInput,
} from '../lib/test_samples';
// eslint-disable-next-line
-import { inspectorPluginMock } from '../../../../plugins/inspector/public/mocks';
-import { esFilters } from '../../../../plugins/data/public';
+import { esFilters } from '../../../data/public';
test('ApplyFilterAction applies the filter to the root of the container tree', async () => {
const { doStart, setup } = testPlugin();
@@ -95,26 +94,16 @@ test('ApplyFilterAction applies the filter to the root of the container tree', a
});
test('ApplyFilterAction is incompatible if the root container does not accept a filter as input', async () => {
- const { doStart, coreStart, setup } = testPlugin();
- const inspector = inspectorPluginMock.createStartContract();
+ const { doStart, setup } = testPlugin();
const factory = new FilterableEmbeddableFactory();
setup.registerEmbeddableFactory(factory.type, factory);
const api = doStart();
const applyFilterAction = createFilterAction();
- const parent = new HelloWorldContainer(
- { id: 'root', panels: {} },
- {
- getActions: () => Promise.resolve([]),
- getEmbeddableFactory: api.getEmbeddableFactory,
- getAllEmbeddableFactories: api.getEmbeddableFactories,
- overlays: coreStart.overlays,
- notifications: coreStart.notifications,
- application: coreStart.application,
- inspector,
- SavedObjectFinder: () => null,
- }
- );
+
+ const parent = new HelloWorldContainer({ id: 'root', panels: {} }, {
+ getEmbeddableFactory: api.getEmbeddableFactory,
+ } as any);
const embeddable = await parent.addNewEmbeddable<
FilterableContainerInput,
EmbeddableOutput,
@@ -130,27 +119,17 @@ test('ApplyFilterAction is incompatible if the root container does not accept a
});
test('trying to execute on incompatible context throws an error ', async () => {
- const { doStart, coreStart, setup } = testPlugin();
- const inspector = inspectorPluginMock.createStartContract();
+ const { doStart, setup } = testPlugin();
const factory = new FilterableEmbeddableFactory();
setup.registerEmbeddableFactory(factory.type, factory);
const api = doStart();
const applyFilterAction = createFilterAction();
- const parent = new HelloWorldContainer(
- { id: 'root', panels: {} },
- {
- getActions: () => Promise.resolve([]),
- getEmbeddableFactory: api.getEmbeddableFactory,
- getAllEmbeddableFactories: api.getEmbeddableFactories,
- overlays: coreStart.overlays,
- notifications: coreStart.notifications,
- application: coreStart.application,
- inspector,
- SavedObjectFinder: () => null,
- }
- );
+
+ const parent = new HelloWorldContainer({ id: 'root', panels: {} }, {
+ getEmbeddableFactory: api.getEmbeddableFactory,
+ } as any);
const embeddable = await parent.addNewEmbeddable<
FilterableContainerInput,
diff --git a/src/plugins/embeddable/public/tests/container.test.ts b/src/plugins/embeddable/public/tests/container.test.ts
index 4cd01abaf7995..490f0c00c7c4d 100644
--- a/src/plugins/embeddable/public/tests/container.test.ts
+++ b/src/plugins/embeddable/public/tests/container.test.ts
@@ -48,6 +48,7 @@ import { coreMock } from '../../../../core/public/mocks';
import { testPlugin } from './test_plugin';
import { of } from './helpers';
import { esFilters, Filter } from '../../../../plugins/data/public';
+import { createEmbeddablePanelMock } from '../mocks';
async function creatHelloWorldContainerAndEmbeddable(
containerInput: ContainerInput = { id: 'hello', panels: {} },
@@ -68,15 +69,18 @@ async function creatHelloWorldContainerAndEmbeddable(
const start = doStart();
- const container = new HelloWorldContainer(containerInput, {
+ const testPanel = createEmbeddablePanelMock({
getActions: uiActions.getTriggerCompatibleActions,
getEmbeddableFactory: start.getEmbeddableFactory,
getAllEmbeddableFactories: start.getEmbeddableFactories,
overlays: coreStart.overlays,
notifications: coreStart.notifications,
application: coreStart.application,
- inspector: {} as any,
- SavedObjectFinder: () => null,
+ });
+
+ const container = new HelloWorldContainer(containerInput, {
+ getEmbeddableFactory: start.getEmbeddableFactory,
+ panelComponent: testPanel,
});
const embeddable = await container.addNewEmbeddable<
ContactCardEmbeddableInput,
@@ -88,7 +92,7 @@ async function creatHelloWorldContainerAndEmbeddable(
throw new Error('Error adding embeddable');
}
- return { container, embeddable, coreSetup, coreStart, setup, start, uiActions };
+ return { container, embeddable, coreSetup, coreStart, setup, start, uiActions, testPanel };
}
test('Container initializes embeddables', async (done) => {
@@ -131,7 +135,8 @@ test('Container.addNewEmbeddable', async () => {
});
test('Container.removeEmbeddable removes and cleans up', async (done) => {
- const { start, coreStart, uiActions } = await creatHelloWorldContainerAndEmbeddable();
+ const { start, testPanel } = await creatHelloWorldContainerAndEmbeddable();
+
const container = new HelloWorldContainer(
{
id: 'hello',
@@ -143,14 +148,8 @@ test('Container.removeEmbeddable removes and cleans up', async (done) => {
},
},
{
- getActions: uiActions.getTriggerCompatibleActions,
getEmbeddableFactory: start.getEmbeddableFactory,
- getAllEmbeddableFactories: start.getEmbeddableFactories,
- overlays: coreStart.overlays,
- notifications: coreStart.notifications,
- application: coreStart.application,
- inspector: {} as any,
- SavedObjectFinder: () => null,
+ panelComponent: testPanel,
}
);
const embeddable = await container.addNewEmbeddable<
@@ -323,15 +322,17 @@ test(`Container updates its state when a child's input is updated`, async (done)
// Make sure a brand new container built off the output of container also creates an embeddable
// with "Dr.", not the default the embeddable was first added with. Makes sure changed input
// is preserved with the container.
- const containerClone = new HelloWorldContainer(container.getInput(), {
+ const testPanel = createEmbeddablePanelMock({
getActions: uiActions.getTriggerCompatibleActions,
- getAllEmbeddableFactories: start.getEmbeddableFactories,
getEmbeddableFactory: start.getEmbeddableFactory,
- notifications: coreStart.notifications,
+ getAllEmbeddableFactories: start.getEmbeddableFactories,
overlays: coreStart.overlays,
+ notifications: coreStart.notifications,
application: coreStart.application,
- inspector: {} as any,
- SavedObjectFinder: () => null,
+ });
+ const containerClone = new HelloWorldContainer(container.getInput(), {
+ getEmbeddableFactory: start.getEmbeddableFactory,
+ panelComponent: testPanel,
});
const cloneSubscription = Rx.merge(
containerClone.getOutput$(),
@@ -575,6 +576,14 @@ test('Container changes made directly after adding a new embeddable are propagat
const start = doStart();
+ const testPanel = createEmbeddablePanelMock({
+ getActions: uiActions.getTriggerCompatibleActions,
+ getEmbeddableFactory: start.getEmbeddableFactory,
+ getAllEmbeddableFactories: start.getEmbeddableFactories,
+ overlays: coreStart.overlays,
+ notifications: coreStart.notifications,
+ application: coreStart.application,
+ });
const container = new HelloWorldContainer(
{
id: 'hello',
@@ -582,14 +591,8 @@ test('Container changes made directly after adding a new embeddable are propagat
viewMode: ViewMode.EDIT,
},
{
- getActions: uiActions.getTriggerCompatibleActions,
getEmbeddableFactory: start.getEmbeddableFactory,
- getAllEmbeddableFactories: start.getEmbeddableFactories,
- overlays: coreStart.overlays,
- notifications: coreStart.notifications,
- application: coreStart.application,
- inspector: {} as any,
- SavedObjectFinder: () => null,
+ panelComponent: testPanel,
}
);
@@ -701,20 +704,22 @@ test('untilEmbeddableLoaded() throws an error if there is no such child panel in
coreMock.createStart()
);
const start = doStart();
+ const testPanel = createEmbeddablePanelMock({
+ getActions: uiActions.getTriggerCompatibleActions,
+ getEmbeddableFactory: start.getEmbeddableFactory,
+ getAllEmbeddableFactories: start.getEmbeddableFactories,
+ overlays: coreStart.overlays,
+ notifications: coreStart.notifications,
+ application: coreStart.application,
+ });
const container = new HelloWorldContainer(
{
id: 'hello',
panels: {},
},
{
- getActions: uiActions.getTriggerCompatibleActions,
getEmbeddableFactory: start.getEmbeddableFactory,
- getAllEmbeddableFactories: start.getEmbeddableFactories,
- overlays: coreStart.overlays,
- notifications: coreStart.notifications,
- application: coreStart.application,
- inspector: {} as any,
- SavedObjectFinder: () => null,
+ panelComponent: testPanel,
}
);
@@ -731,6 +736,14 @@ test('untilEmbeddableLoaded() resolves if child is loaded in the container', asy
const factory = new HelloWorldEmbeddableFactory();
setup.registerEmbeddableFactory(factory.type, factory);
const start = doStart();
+ const testPanel = createEmbeddablePanelMock({
+ getActions: uiActions.getTriggerCompatibleActions,
+ getEmbeddableFactory: start.getEmbeddableFactory,
+ getAllEmbeddableFactories: start.getEmbeddableFactories,
+ overlays: coreStart.overlays,
+ notifications: coreStart.notifications,
+ application: coreStart.application,
+ });
const container = new HelloWorldContainer(
{
id: 'hello',
@@ -742,14 +755,8 @@ test('untilEmbeddableLoaded() resolves if child is loaded in the container', asy
},
},
{
- getActions: uiActions.getTriggerCompatibleActions,
getEmbeddableFactory: start.getEmbeddableFactory,
- getAllEmbeddableFactories: start.getEmbeddableFactories,
- overlays: coreStart.overlays,
- notifications: coreStart.notifications,
- application: coreStart.application,
- inspector: {} as any,
- SavedObjectFinder: () => null,
+ panelComponent: testPanel,
}
);
@@ -771,6 +778,14 @@ test('untilEmbeddableLoaded resolves with undefined if child is subsequently rem
setup.registerEmbeddableFactory(factory.type, factory);
const start = doStart();
+ const testPanel = createEmbeddablePanelMock({
+ getActions: uiActions.getTriggerCompatibleActions,
+ getEmbeddableFactory: start.getEmbeddableFactory,
+ getAllEmbeddableFactories: start.getEmbeddableFactories,
+ overlays: coreStart.overlays,
+ notifications: coreStart.notifications,
+ application: coreStart.application,
+ });
const container = new HelloWorldContainer(
{
id: 'hello',
@@ -782,14 +797,8 @@ test('untilEmbeddableLoaded resolves with undefined if child is subsequently rem
},
},
{
- getActions: uiActions.getTriggerCompatibleActions,
getEmbeddableFactory: start.getEmbeddableFactory,
- getAllEmbeddableFactories: start.getEmbeddableFactories,
- overlays: coreStart.overlays,
- notifications: coreStart.notifications,
- application: coreStart.application,
- inspector: {} as any,
- SavedObjectFinder: () => null,
+ panelComponent: testPanel,
}
);
@@ -812,6 +821,14 @@ test('adding a panel then subsequently removing it before its loaded removes the
});
setup.registerEmbeddableFactory(factory.type, factory);
const start = doStart();
+ const testPanel = createEmbeddablePanelMock({
+ getActions: uiActions.getTriggerCompatibleActions,
+ getEmbeddableFactory: start.getEmbeddableFactory,
+ getAllEmbeddableFactories: start.getEmbeddableFactories,
+ overlays: coreStart.overlays,
+ notifications: coreStart.notifications,
+ application: coreStart.application,
+ });
const container = new HelloWorldContainer(
{
id: 'hello',
@@ -823,14 +840,8 @@ test('adding a panel then subsequently removing it before its loaded removes the
},
},
{
- getActions: uiActions.getTriggerCompatibleActions,
getEmbeddableFactory: start.getEmbeddableFactory,
- getAllEmbeddableFactories: start.getEmbeddableFactories,
- overlays: coreStart.overlays,
- notifications: coreStart.notifications,
- application: coreStart.application,
- inspector: {} as any,
- SavedObjectFinder: () => null,
+ panelComponent: testPanel,
}
);
diff --git a/src/plugins/embeddable/public/tests/customize_panel_modal.test.tsx b/src/plugins/embeddable/public/tests/customize_panel_modal.test.tsx
index a9cb83504d958..311efae49f735 100644
--- a/src/plugins/embeddable/public/tests/customize_panel_modal.test.tsx
+++ b/src/plugins/embeddable/public/tests/customize_panel_modal.test.tsx
@@ -37,6 +37,7 @@ import { testPlugin } from './test_plugin';
import { CustomizePanelModal } from '../lib/panel/panel_header/panel_actions/customize_title/customize_panel_modal';
import { mount } from 'enzyme';
import { EmbeddableStart } from '../plugin';
+import { createEmbeddablePanelMock } from '../mocks';
let api: EmbeddableStart;
let container: Container;
@@ -55,17 +56,20 @@ beforeEach(async () => {
setup.registerEmbeddableFactory(contactCardFactory.type, contactCardFactory);
api = doStart();
+
+ const testPanel = createEmbeddablePanelMock({
+ getActions: uiActions.getTriggerCompatibleActions,
+ getEmbeddableFactory: api.getEmbeddableFactory,
+ getAllEmbeddableFactories: api.getEmbeddableFactories,
+ overlays: coreStart.overlays,
+ notifications: coreStart.notifications,
+ application: coreStart.application,
+ });
container = new HelloWorldContainer(
{ id: '123', panels: {} },
{
- getActions: uiActions.getTriggerCompatibleActions,
getEmbeddableFactory: api.getEmbeddableFactory,
- getAllEmbeddableFactories: api.getEmbeddableFactories,
- overlays: coreStart.overlays,
- notifications: coreStart.notifications,
- application: coreStart.application,
- inspector: {} as any,
- SavedObjectFinder: () => null,
+ panelComponent: testPanel,
}
);
const contactCardEmbeddable = await container.addNewEmbeddable<
diff --git a/src/plugins/embeddable/public/tests/explicit_input.test.ts b/src/plugins/embeddable/public/tests/explicit_input.test.ts
index 6bea4fe46a497..d64ff94d71800 100644
--- a/src/plugins/embeddable/public/tests/explicit_input.test.ts
+++ b/src/plugins/embeddable/public/tests/explicit_input.test.ts
@@ -36,6 +36,7 @@ import { HelloWorldContainer } from '../lib/test_samples/embeddables/hello_world
// eslint-disable-next-line
import { coreMock } from '../../../../core/public/mocks';
import { esFilters, Filter } from '../../../../plugins/data/public';
+import { createEmbeddablePanelMock } from '../mocks';
const { setup, doStart, coreStart, uiActions } = testPlugin(
coreMock.createSetup(),
@@ -80,17 +81,19 @@ test('Explicit embeddable input mapped to undefined will default to inherited',
});
test('Explicit embeddable input mapped to undefined with no inherited value will get passed to embeddable', async (done) => {
+ const testPanel = createEmbeddablePanelMock({
+ getActions: uiActions.getTriggerCompatibleActions,
+ getEmbeddableFactory: start.getEmbeddableFactory,
+ getAllEmbeddableFactories: start.getEmbeddableFactories,
+ overlays: coreStart.overlays,
+ notifications: coreStart.notifications,
+ application: coreStart.application,
+ });
const container = new HelloWorldContainer(
{ id: 'hello', panels: {} },
{
- getActions: uiActions.getTriggerCompatibleActions,
- getAllEmbeddableFactories: start.getEmbeddableFactories,
getEmbeddableFactory: start.getEmbeddableFactory,
- notifications: coreStart.notifications,
- overlays: coreStart.overlays,
- application: coreStart.application,
- inspector: {} as any,
- SavedObjectFinder: () => null,
+ panelComponent: testPanel,
}
);
@@ -121,6 +124,14 @@ test('Explicit embeddable input mapped to undefined with no inherited value will
// but before the embeddable factory returns the embeddable, that the `inheritedChildInput` and
// embeddable input comparisons won't cause explicit input to be set when it shouldn't.
test('Explicit input tests in async situations', (done: () => void) => {
+ const testPanel = createEmbeddablePanelMock({
+ getActions: uiActions.getTriggerCompatibleActions,
+ getEmbeddableFactory: start.getEmbeddableFactory,
+ getAllEmbeddableFactories: start.getEmbeddableFactories,
+ overlays: coreStart.overlays,
+ notifications: coreStart.notifications,
+ application: coreStart.application,
+ });
const container = new HelloWorldContainer(
{
id: 'hello',
@@ -132,14 +143,8 @@ test('Explicit input tests in async situations', (done: () => void) => {
},
},
{
- getActions: uiActions.getTriggerCompatibleActions,
- getAllEmbeddableFactories: start.getEmbeddableFactories,
getEmbeddableFactory: start.getEmbeddableFactory,
- notifications: coreStart.notifications,
- overlays: coreStart.overlays,
- application: coreStart.application,
- inspector: {} as any,
- SavedObjectFinder: () => null,
+ panelComponent: testPanel,
}
);
diff --git a/src/plugins/es_ui_shared/__packages_do_not_import__/monaco/index.ts b/src/plugins/es_ui_shared/__packages_do_not_import__/monaco/index.ts
new file mode 100644
index 0000000000000..a9c6ea1e01d54
--- /dev/null
+++ b/src/plugins/es_ui_shared/__packages_do_not_import__/monaco/index.ts
@@ -0,0 +1,20 @@
+/*
+ * 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.
+ */
+
+export { useXJsonMode } from './use_xjson_mode';
diff --git a/src/plugins/es_ui_shared/__packages_do_not_import__/monaco/use_xjson_mode.ts b/src/plugins/es_ui_shared/__packages_do_not_import__/monaco/use_xjson_mode.ts
new file mode 100644
index 0000000000000..b783045492f05
--- /dev/null
+++ b/src/plugins/es_ui_shared/__packages_do_not_import__/monaco/use_xjson_mode.ts
@@ -0,0 +1,32 @@
+/*
+ * 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 { XJsonLang } from '@kbn/monaco';
+import { useXJsonMode as useBaseXJsonMode } from '../xjson';
+
+interface ReturnValue extends ReturnType {
+ XJsonLang: typeof XJsonLang;
+}
+
+export const useXJsonMode = (json: Parameters[0]): ReturnValue => {
+ return {
+ ...useBaseXJsonMode(json),
+ XJsonLang,
+ };
+};
diff --git a/src/plugins/es_ui_shared/__packages_do_not_import__/xjson/index.ts b/src/plugins/es_ui_shared/__packages_do_not_import__/xjson/index.ts
new file mode 100644
index 0000000000000..a9c6ea1e01d54
--- /dev/null
+++ b/src/plugins/es_ui_shared/__packages_do_not_import__/xjson/index.ts
@@ -0,0 +1,20 @@
+/*
+ * 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.
+ */
+
+export { useXJsonMode } from './use_xjson_mode';
diff --git a/src/plugins/es_ui_shared/__packages_do_not_import__/xjson/use_xjson_mode.ts b/src/plugins/es_ui_shared/__packages_do_not_import__/xjson/use_xjson_mode.ts
new file mode 100644
index 0000000000000..7dcc7c9ed83bc
--- /dev/null
+++ b/src/plugins/es_ui_shared/__packages_do_not_import__/xjson/use_xjson_mode.ts
@@ -0,0 +1,41 @@
+/*
+ * 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 { useState, Dispatch } from 'react';
+import { collapseLiteralStrings, expandLiteralStrings } from '../../public';
+
+interface ReturnValue {
+ xJson: string;
+ setXJson: Dispatch;
+ convertToJson: typeof collapseLiteralStrings;
+}
+
+export const useXJsonMode = (json: Record | string | null): ReturnValue => {
+ const [xJson, setXJson] = useState(() =>
+ json === null
+ ? ''
+ : expandLiteralStrings(typeof json === 'string' ? json : JSON.stringify(json, null, 2))
+ );
+
+ return {
+ xJson,
+ setXJson,
+ convertToJson: collapseLiteralStrings,
+ };
+};
diff --git a/src/plugins/es_ui_shared/public/index.ts b/src/plugins/es_ui_shared/public/index.ts
index 7e5510d7c9c65..4ab791289dd88 100644
--- a/src/plugins/es_ui_shared/public/index.ts
+++ b/src/plugins/es_ui_shared/public/index.ts
@@ -47,6 +47,10 @@ export {
expandLiteralStrings,
} from './console_lang';
+import * as Monaco from './monaco';
+
+export { Monaco };
+
export {
AuthorizationContext,
AuthorizationProvider,
diff --git a/src/plugins/es_ui_shared/public/monaco/index.ts b/src/plugins/es_ui_shared/public/monaco/index.ts
new file mode 100644
index 0000000000000..23ba93e913234
--- /dev/null
+++ b/src/plugins/es_ui_shared/public/monaco/index.ts
@@ -0,0 +1,20 @@
+/*
+ * 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.
+ */
+
+export { useXJsonMode } from '../../__packages_do_not_import__/monaco';
diff --git a/src/plugins/es_ui_shared/static/ace_x_json/hooks/use_x_json.ts b/src/plugins/es_ui_shared/static/ace_x_json/hooks/use_x_json.ts
index 2b0bf0c8a3a7c..3a093ac6869d0 100644
--- a/src/plugins/es_ui_shared/static/ace_x_json/hooks/use_x_json.ts
+++ b/src/plugins/es_ui_shared/static/ace_x_json/hooks/use_x_json.ts
@@ -16,23 +16,18 @@
* specific language governing permissions and limitations
* under the License.
*/
-
-import { useState } from 'react';
-import { XJsonMode, collapseLiteralStrings, expandLiteralStrings } from '../../../public';
+import { XJsonMode } from '../../../public';
+import { useXJsonMode as useBaseXJsonMode } from '../../../__packages_do_not_import__/xjson';
const xJsonMode = new XJsonMode();
-export const useXJsonMode = (json: Record | string | null) => {
- const [xJson, setXJson] = useState(() =>
- json === null
- ? ''
- : expandLiteralStrings(typeof json === 'string' ? json : JSON.stringify(json, null, 2))
- );
+interface ReturnValue extends ReturnType {
+ xJsonMode: typeof xJsonMode;
+}
+export const useXJsonMode = (json: Parameters[0]): ReturnValue => {
return {
- xJson,
- setXJson,
+ ...useBaseXJsonMode(json),
xJsonMode,
- convertToJson: collapseLiteralStrings,
};
};
diff --git a/src/plugins/home/public/application/components/__snapshots__/add_data.test.js.snap b/src/plugins/home/public/application/components/__snapshots__/add_data.test.js.snap
index 3b3f86e579f1a..2545bbcb5114d 100644
--- a/src/plugins/home/public/application/components/__snapshots__/add_data.test.js.snap
+++ b/src/plugins/home/public/application/components/__snapshots__/add_data.test.js.snap
@@ -202,17 +202,17 @@ exports[`apmUiEnabled 1`] = `
}
textAlign="left"
- title="SIEM"
+ title="Security"
titleSize="xs"
/>
@@ -468,17 +468,17 @@ exports[`isNewKibanaInstance 1`] = `
}
textAlign="left"
- title="SIEM"
+ title="Security"
titleSize="xs"
/>
@@ -765,17 +765,17 @@ exports[`mlEnabled 1`] = `
}
textAlign="left"
- title="SIEM"
+ title="Security"
titleSize="xs"
/>
@@ -1067,17 +1067,17 @@ exports[`render 1`] = `
}
textAlign="left"
- title="SIEM"
+ title="Security"
titleSize="xs"
/>
diff --git a/src/plugins/home/public/application/components/add_data.js b/src/plugins/home/public/application/components/add_data.js
index 2f7f07a0e4549..fa1327b3fcd08 100644
--- a/src/plugins/home/public/application/components/add_data.js
+++ b/src/plugins/home/public/application/components/add_data.js
@@ -80,11 +80,11 @@ const AddDataUi = ({ apmUiEnabled, isNewKibanaInstance, intl, mlEnabled }) => {
};
const siemData = {
title: intl.formatMessage({
- id: 'home.addData.siem.nameTitle',
- defaultMessage: 'SIEM',
+ id: 'home.addData.securitySolution.nameTitle',
+ defaultMessage: 'Security',
}),
description: intl.formatMessage({
- id: 'home.addData.siem.nameDescription',
+ id: 'home.addData.securitySolution.nameDescription',
defaultMessage:
'Centralize security events for interactive investigation in ready-to-go visualizations.',
}),
@@ -221,11 +221,11 @@ const AddDataUi = ({ apmUiEnabled, isNewKibanaInstance, intl, mlEnabled }) => {
footer={
diff --git a/src/plugins/home/public/application/components/tutorial_directory.js b/src/plugins/home/public/application/components/tutorial_directory.js
index 4d2cec158f63e..774b23af11ac8 100644
--- a/src/plugins/home/public/application/components/tutorial_directory.js
+++ b/src/plugins/home/public/application/components/tutorial_directory.js
@@ -75,10 +75,10 @@ class TutorialDirectoryUi extends React.Component {
}),
},
{
- id: 'siem',
+ id: 'security',
name: this.props.intl.formatMessage({
- id: 'home.tutorial.tabs.siemTitle',
- defaultMessage: 'SIEM',
+ id: 'home.tutorial.tabs.securitySolutionTitle',
+ defaultMessage: 'Security',
}),
},
{
diff --git a/src/plugins/home/server/services/tutorials/lib/tutorial_schema.ts b/src/plugins/home/server/services/tutorials/lib/tutorial_schema.ts
index 24f5a39feb4c5..32e5483b8b070 100644
--- a/src/plugins/home/server/services/tutorials/lib/tutorial_schema.ts
+++ b/src/plugins/home/server/services/tutorials/lib/tutorial_schema.ts
@@ -26,7 +26,7 @@ const PARAM_TYPES = {
const TUTORIAL_CATEGORY = {
LOGGING: 'logging',
- SIEM: 'siem',
+ SECURITY_SOLUTION: 'security solution',
METRICS: 'metrics',
OTHER: 'other',
};
diff --git a/src/plugins/home/server/services/tutorials/lib/tutorials_registry_types.ts b/src/plugins/home/server/services/tutorials/lib/tutorials_registry_types.ts
index 80849513a3fad..3325240147640 100644
--- a/src/plugins/home/server/services/tutorials/lib/tutorials_registry_types.ts
+++ b/src/plugins/home/server/services/tutorials/lib/tutorials_registry_types.ts
@@ -22,7 +22,7 @@ import { KibanaRequest } from 'src/core/server';
/** @public */
export enum TutorialsCategory {
LOGGING = 'logging',
- SIEM = 'siem',
+ SECURITY_SOLUTION = 'security',
METRICS = 'metrics',
OTHER = 'other',
}
diff --git a/src/plugins/home/server/tutorials/auditbeat/index.ts b/src/plugins/home/server/tutorials/auditbeat/index.ts
index dadbf913d5ed5..214fda5a7cc53 100644
--- a/src/plugins/home/server/tutorials/auditbeat/index.ts
+++ b/src/plugins/home/server/tutorials/auditbeat/index.ts
@@ -36,7 +36,7 @@ export function auditbeatSpecProvider(context: TutorialContext): TutorialSchema
name: i18n.translate('home.tutorials.auditbeat.nameTitle', {
defaultMessage: 'Auditbeat',
}),
- category: TutorialsCategory.SIEM,
+ category: TutorialsCategory.SECURITY_SOLUTION,
shortDescription: i18n.translate('home.tutorials.auditbeat.shortDescription', {
defaultMessage: 'Collect audit data from your hosts.',
}),
@@ -53,9 +53,9 @@ processes, users, logins, sockets information, file accesses, and more. \
artifacts: {
dashboards: [],
application: {
- path: '/app/siem',
+ path: '/app/security',
label: i18n.translate('home.tutorials.auditbeat.artifacts.dashboards.linkLabel', {
- defaultMessage: 'SIEM App',
+ defaultMessage: 'Security App',
}),
},
exportedFields: {
diff --git a/src/plugins/home/server/tutorials/cisco_logs/index.ts b/src/plugins/home/server/tutorials/cisco_logs/index.ts
index 4514b61570b07..2322f503b80ce 100644
--- a/src/plugins/home/server/tutorials/cisco_logs/index.ts
+++ b/src/plugins/home/server/tutorials/cisco_logs/index.ts
@@ -37,7 +37,7 @@ export function ciscoLogsSpecProvider(context: TutorialContext): TutorialSchema
name: i18n.translate('home.tutorials.ciscoLogs.nameTitle', {
defaultMessage: 'Cisco',
}),
- category: TutorialsCategory.SIEM,
+ category: TutorialsCategory.SECURITY_SOLUTION,
shortDescription: i18n.translate('home.tutorials.ciscoLogs.shortDescription', {
defaultMessage: 'Collect and parse logs received from Cisco ASA firewalls.',
}),
@@ -54,9 +54,9 @@ supports the "asa" fileset for Cisco ASA firewall logs received over syslog or r
artifacts: {
dashboards: [],
application: {
- path: '/app/siem',
+ path: '/app/security',
label: i18n.translate('home.tutorials.ciscoLogs.artifacts.dashboards.linkLabel', {
- defaultMessage: 'SIEM App',
+ defaultMessage: 'Security App',
}),
},
exportedFields: {
diff --git a/src/plugins/home/server/tutorials/coredns_logs/index.ts b/src/plugins/home/server/tutorials/coredns_logs/index.ts
index 1c62366251661..4304fb7acb907 100644
--- a/src/plugins/home/server/tutorials/coredns_logs/index.ts
+++ b/src/plugins/home/server/tutorials/coredns_logs/index.ts
@@ -37,7 +37,7 @@ export function corednsLogsSpecProvider(context: TutorialContext): TutorialSchem
name: i18n.translate('home.tutorials.corednsLogs.nameTitle', {
defaultMessage: 'CoreDNS logs',
}),
- category: TutorialsCategory.SIEM,
+ category: TutorialsCategory.SECURITY_SOLUTION,
shortDescription: i18n.translate('home.tutorials.corednsLogs.shortDescription', {
defaultMessage: 'Collect the logs created by Coredns.',
}),
diff --git a/src/plugins/home/server/tutorials/envoyproxy_logs/index.ts b/src/plugins/home/server/tutorials/envoyproxy_logs/index.ts
index 3d88cce36d752..a9b9c33d61bdf 100644
--- a/src/plugins/home/server/tutorials/envoyproxy_logs/index.ts
+++ b/src/plugins/home/server/tutorials/envoyproxy_logs/index.ts
@@ -37,7 +37,7 @@ export function envoyproxyLogsSpecProvider(context: TutorialContext): TutorialSc
name: i18n.translate('home.tutorials.envoyproxyLogs.nameTitle', {
defaultMessage: 'Envoyproxy',
}),
- category: TutorialsCategory.SIEM,
+ category: TutorialsCategory.SECURITY_SOLUTION,
shortDescription: i18n.translate('home.tutorials.envoyproxyLogs.shortDescription', {
defaultMessage: 'Collect and parse logs received from the Envoy proxy.',
}),
@@ -54,9 +54,9 @@ It supports both standalone deployment and Envoy proxy deployment in Kubernetes.
artifacts: {
dashboards: [],
application: {
- path: '/app/siem',
+ path: '/app/security',
label: i18n.translate('home.tutorials.envoyproxyLogs.artifacts.dashboards.linkLabel', {
- defaultMessage: 'SIEM App',
+ defaultMessage: 'Security App',
}),
},
exportedFields: {
diff --git a/src/plugins/home/server/tutorials/iptables_logs/index.ts b/src/plugins/home/server/tutorials/iptables_logs/index.ts
index e72e0ef300e04..fd84894dae850 100644
--- a/src/plugins/home/server/tutorials/iptables_logs/index.ts
+++ b/src/plugins/home/server/tutorials/iptables_logs/index.ts
@@ -37,7 +37,7 @@ export function iptablesLogsSpecProvider(context: TutorialContext): TutorialSche
name: i18n.translate('home.tutorials.iptablesLogs.nameTitle', {
defaultMessage: 'Iptables / Ubiquiti',
}),
- category: TutorialsCategory.SIEM,
+ category: TutorialsCategory.SECURITY_SOLUTION,
shortDescription: i18n.translate('home.tutorials.iptablesLogs.shortDescription', {
defaultMessage: 'Collect and parse iptables and ip6tables logs or from Ubiqiti firewalls.',
}),
@@ -56,9 +56,9 @@ number and the action performed on the traffic (allow/deny).. \
artifacts: {
dashboards: [],
application: {
- path: '/app/siem',
+ path: '/app/security',
label: i18n.translate('home.tutorials.iptablesLogs.artifacts.dashboards.linkLabel', {
- defaultMessage: 'SIEM App',
+ defaultMessage: 'Security App',
}),
},
exportedFields: {
diff --git a/src/plugins/home/server/tutorials/netflow/index.ts b/src/plugins/home/server/tutorials/netflow/index.ts
index 7c6fcadcff625..ec0aa8953b146 100644
--- a/src/plugins/home/server/tutorials/netflow/index.ts
+++ b/src/plugins/home/server/tutorials/netflow/index.ts
@@ -28,7 +28,7 @@ export function netflowSpecProvider() {
return {
id: 'netflow',
name: 'Netflow',
- category: TutorialsCategory.SIEM,
+ category: TutorialsCategory.SECURITY_SOLUTION,
shortDescription: i18n.translate('home.tutorials.netflow.tutorialShortDescription', {
defaultMessage: 'Collect Netflow records sent by a Netflow exporter.',
}),
diff --git a/src/plugins/home/server/tutorials/osquery_logs/index.ts b/src/plugins/home/server/tutorials/osquery_logs/index.ts
index 34a1b9e7f619d..8781d6201a771 100644
--- a/src/plugins/home/server/tutorials/osquery_logs/index.ts
+++ b/src/plugins/home/server/tutorials/osquery_logs/index.ts
@@ -37,7 +37,7 @@ export function osqueryLogsSpecProvider(context: TutorialContext): TutorialSchem
name: i18n.translate('home.tutorials.osqueryLogs.nameTitle', {
defaultMessage: 'Osquery logs',
}),
- category: TutorialsCategory.SIEM,
+ category: TutorialsCategory.SECURITY_SOLUTION,
shortDescription: i18n.translate('home.tutorials.osqueryLogs.shortDescription', {
defaultMessage: 'Collect the result logs created by osqueryd.',
}),
diff --git a/src/plugins/home/server/tutorials/suricata_logs/index.ts b/src/plugins/home/server/tutorials/suricata_logs/index.ts
index c02cb05889ebb..6bcfc1d43a250 100644
--- a/src/plugins/home/server/tutorials/suricata_logs/index.ts
+++ b/src/plugins/home/server/tutorials/suricata_logs/index.ts
@@ -37,7 +37,7 @@ export function suricataLogsSpecProvider(context: TutorialContext): TutorialSche
name: i18n.translate('home.tutorials.suricataLogs.nameTitle', {
defaultMessage: 'Suricata logs',
}),
- category: TutorialsCategory.SIEM,
+ category: TutorialsCategory.SECURITY_SOLUTION,
shortDescription: i18n.translate('home.tutorials.suricataLogs.shortDescription', {
defaultMessage: 'Collect the result logs created by Suricata IDS/IPS/NSM.',
}),
diff --git a/src/plugins/home/server/tutorials/windows_event_logs/index.ts b/src/plugins/home/server/tutorials/windows_event_logs/index.ts
index 5349bedb21279..c2ea9ff3015e4 100644
--- a/src/plugins/home/server/tutorials/windows_event_logs/index.ts
+++ b/src/plugins/home/server/tutorials/windows_event_logs/index.ts
@@ -36,7 +36,7 @@ export function windowsEventLogsSpecProvider(context: TutorialContext): Tutorial
defaultMessage: 'Windows Event Log',
}),
isBeta: false,
- category: TutorialsCategory.SIEM,
+ category: TutorialsCategory.SECURITY_SOLUTION,
shortDescription: i18n.translate('home.tutorials.windowsEventLogs.shortDescription', {
defaultMessage: 'Fetch logs from the Windows Event Log.',
}),
diff --git a/src/plugins/home/server/tutorials/zeek_logs/index.ts b/src/plugins/home/server/tutorials/zeek_logs/index.ts
index 4bd54c96481b6..c273a93b1b0d5 100644
--- a/src/plugins/home/server/tutorials/zeek_logs/index.ts
+++ b/src/plugins/home/server/tutorials/zeek_logs/index.ts
@@ -37,7 +37,7 @@ export function zeekLogsSpecProvider(context: TutorialContext): TutorialSchema {
name: i18n.translate('home.tutorials.zeekLogs.nameTitle', {
defaultMessage: 'Zeek logs',
}),
- category: TutorialsCategory.SIEM,
+ category: TutorialsCategory.SECURITY_SOLUTION,
shortDescription: i18n.translate('home.tutorials.zeekLogs.shortDescription', {
defaultMessage: 'Collect the logs created by Zeek/Bro.',
}),
diff --git a/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/step_index_pattern/step_index_pattern.tsx b/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/step_index_pattern/step_index_pattern.tsx
index edb96f119385e..b6205a8731dfa 100644
--- a/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/step_index_pattern/step_index_pattern.tsx
+++ b/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/step_index_pattern/step_index_pattern.tsx
@@ -21,7 +21,11 @@ import React, { Component } from 'react';
import { EuiPanel, EuiSpacer, EuiCallOut } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n/react';
-import { indexPatterns, IndexPatternAttributes } from '../../../../../../../plugins/data/public';
+import {
+ indexPatterns,
+ IndexPatternAttributes,
+ UI_SETTINGS,
+} from '../../../../../../../plugins/data/public';
import { MAX_SEARCH_SIZE } from '../../constants';
import {
getIndices,
@@ -82,7 +86,8 @@ export class StepIndexPattern extends Component fieldWildcardMatcher(filters, uiSettings.get('metaFields')),
+ (filters: string[]) => fieldWildcardMatcher(filters, uiSettings.get(UI_SETTINGS.META_FIELDS)),
[uiSettings]
);
diff --git a/src/plugins/index_pattern_management/public/components/field_editor/components/scripting_help/test_script.tsx b/src/plugins/index_pattern_management/public/components/field_editor/components/scripting_help/test_script.tsx
index a1b7289efee21..c97f19f59d340 100644
--- a/src/plugins/index_pattern_management/public/components/field_editor/components/scripting_help/test_script.tsx
+++ b/src/plugins/index_pattern_management/public/components/field_editor/components/scripting_help/test_script.tsx
@@ -35,7 +35,12 @@ import {
import { FormattedMessage } from '@kbn/i18n/react';
import { i18n } from '@kbn/i18n';
-import { esQuery, IndexPattern, Query } from '../../../../../../../plugins/data/public';
+import {
+ esQuery,
+ IndexPattern,
+ Query,
+ UI_SETTINGS,
+} from '../../../../../../../plugins/data/public';
import { context as contextType } from '../../../../../../kibana_react/public';
import { IndexPatternManagmentContextValue } from '../../../../types';
import { ExecuteScript } from '../../types';
@@ -244,7 +249,7 @@ export class TestScript extends Component {
showDatePicker={false}
showQueryInput={true}
query={{
- language: this.context.services.uiSettings.get('search:queryLanguage'),
+ language: this.context.services.uiSettings.get(UI_SETTINGS.SEARCH_QUERY_LANGUAGE),
query: '',
}}
onQuerySubmit={this.previewScript}
diff --git a/src/plugins/inspector/public/views/data/components/data_table.tsx b/src/plugins/inspector/public/views/data/components/data_table.tsx
index 69be069272f79..0fdf3d9b13e33 100644
--- a/src/plugins/inspector/public/views/data/components/data_table.tsx
+++ b/src/plugins/inspector/public/views/data/components/data_table.tsx
@@ -37,6 +37,7 @@ import { DataDownloadOptions } from './download_options';
import { DataViewRow, DataViewColumn } from '../types';
import { TabularData } from '../../../../common/adapters/data/types';
import { IUiSettingsClient } from '../../../../../../core/public';
+import { CSV_SEPARATOR_SETTING, CSV_QUOTE_VALUES_SETTING } from '../../../../../share/public';
interface DataTableFormatState {
columns: DataViewColumn[];
@@ -58,8 +59,8 @@ export class DataTableFormat extends Component (reactDirective) => {
// All modifiers default to true.
// Set to false to hide subcomponents.
'showSearchBar',
- 'showFilterBar',
'showQueryBar',
'showQueryInput',
- 'showDatePicker',
'showSaveQuery',
+ 'showDatePicker',
+ 'showFilterBar',
'appName',
'screenTitle',
diff --git a/src/plugins/kibana_react/public/code_editor/code_editor.examples.tsx b/src/plugins/kibana_react/public/code_editor/code_editor.examples.tsx
index b6d5f2c5460f6..892c97e0ffae0 100644
--- a/src/plugins/kibana_react/public/code_editor/code_editor.examples.tsx
+++ b/src/plugins/kibana_react/public/code_editor/code_editor.examples.tsx
@@ -20,7 +20,7 @@
import { action } from '@storybook/addon-actions';
import { storiesOf } from '@storybook/react';
import React from 'react';
-import { monaco as monacoEditor } from '@kbn/ui-shared-deps/monaco';
+import { monaco as monacoEditor } from '@kbn/monaco';
import { CodeEditor } from './code_editor';
// A sample language definition with a few example tokens
diff --git a/src/plugins/kibana_react/public/code_editor/code_editor.test.tsx b/src/plugins/kibana_react/public/code_editor/code_editor.test.tsx
index bcb46fac36856..2f0670226cf46 100644
--- a/src/plugins/kibana_react/public/code_editor/code_editor.test.tsx
+++ b/src/plugins/kibana_react/public/code_editor/code_editor.test.tsx
@@ -19,9 +19,11 @@
import React from 'react';
import { CodeEditor } from './code_editor';
-import { monaco } from '@kbn/ui-shared-deps/monaco';
+import { monaco } from '@kbn/monaco';
import { shallow } from 'enzyme';
+// disabled because this is a test, but also it seems we shouldn't need this?
+/* eslint-disable-next-line @kbn/eslint/module_migration */
import 'monaco-editor/esm/vs/basic-languages/html/html.contribution.js';
// A sample language definition with a few example tokens
diff --git a/src/plugins/kibana_react/public/code_editor/code_editor.tsx b/src/plugins/kibana_react/public/code_editor/code_editor.tsx
index e8b118b804347..f049085ccff61 100644
--- a/src/plugins/kibana_react/public/code_editor/code_editor.tsx
+++ b/src/plugins/kibana_react/public/code_editor/code_editor.tsx
@@ -21,7 +21,7 @@ import React from 'react';
import ReactResizeDetector from 'react-resize-detector';
import MonacoEditor from 'react-monaco-editor';
-import { monaco } from '@kbn/ui-shared-deps/monaco';
+import { monaco } from '@kbn/monaco';
import { LIGHT_THEME, DARK_THEME } from './editor_theme';
diff --git a/src/plugins/kibana_react/public/code_editor/editor_theme.ts b/src/plugins/kibana_react/public/code_editor/editor_theme.ts
index 586b4a568c348..91d66ce8cbf81 100644
--- a/src/plugins/kibana_react/public/code_editor/editor_theme.ts
+++ b/src/plugins/kibana_react/public/code_editor/editor_theme.ts
@@ -16,7 +16,7 @@
* specific language governing permissions and limitations
* under the License.
*/
-import { monaco } from '@kbn/ui-shared-deps/monaco';
+import { monaco } from '@kbn/monaco';
import darkTheme from '@elastic/eui/dist/eui_theme_dark.json';
import lightTheme from '@elastic/eui/dist/eui_theme_light.json';
diff --git a/src/plugins/kibana_utils/public/core/create_start_service_getter.ts b/src/plugins/kibana_utils/public/core/create_start_service_getter.ts
index 14e2588a0a9cf..5e4a0f2bc7aeb 100644
--- a/src/plugins/kibana_utils/public/core/create_start_service_getter.ts
+++ b/src/plugins/kibana_utils/public/core/create_start_service_getter.ts
@@ -19,16 +19,17 @@
import { CoreStart, StartServicesAccessor } from '../../../../core/public';
-export interface StartServices {
+export interface StartServices {
plugins: Plugins;
self: OwnContract;
- core: CoreStart;
+ core: Core;
}
-export type StartServicesGetter = () => StartServices<
- Plugins,
- OwnContract
->;
+export type StartServicesGetter<
+ Plugins = unknown,
+ OwnContract = unknown,
+ Core = CoreStart
+> = () => StartServices;
/**
* Use this utility to create a synchronous *start* service getter in *setup*
diff --git a/src/plugins/navigation/public/top_nav_menu/top_nav_menu.test.tsx b/src/plugins/navigation/public/top_nav_menu/top_nav_menu.test.tsx
index 74cfd125c2e3a..46384fb3f27d5 100644
--- a/src/plugins/navigation/public/top_nav_menu/top_nav_menu.test.tsx
+++ b/src/plugins/navigation/public/top_nav_menu/top_nav_menu.test.tsx
@@ -29,6 +29,7 @@ const dataShim = {
};
describe('TopNavMenu', () => {
+ const WRAPPER_SELECTOR = '.kbnTopNavMenu__wrapper';
const TOP_NAV_ITEM_SELECTOR = 'TopNavMenuItem';
const SEARCH_BAR_SELECTOR = 'SearchBar';
const menuItems: TopNavMenuData[] = [
@@ -51,18 +52,28 @@ describe('TopNavMenu', () => {
it('Should render nothing when no config is provided', () => {
const component = shallowWithIntl();
+ expect(component.find(WRAPPER_SELECTOR).length).toBe(0);
+ expect(component.find(TOP_NAV_ITEM_SELECTOR).length).toBe(0);
+ expect(component.find(SEARCH_BAR_SELECTOR).length).toBe(0);
+ });
+
+ it('Should not render menu items when config is empty', () => {
+ const component = shallowWithIntl();
+ expect(component.find(WRAPPER_SELECTOR).length).toBe(0);
expect(component.find(TOP_NAV_ITEM_SELECTOR).length).toBe(0);
expect(component.find(SEARCH_BAR_SELECTOR).length).toBe(0);
});
it('Should render 1 menu item', () => {
const component = shallowWithIntl();
+ expect(component.find(WRAPPER_SELECTOR).length).toBe(1);
expect(component.find(TOP_NAV_ITEM_SELECTOR).length).toBe(1);
expect(component.find(SEARCH_BAR_SELECTOR).length).toBe(0);
});
it('Should render multiple menu items', () => {
const component = shallowWithIntl();
+ expect(component.find(WRAPPER_SELECTOR).length).toBe(1);
expect(component.find(TOP_NAV_ITEM_SELECTOR).length).toBe(menuItems.length);
expect(component.find(SEARCH_BAR_SELECTOR).length).toBe(0);
});
@@ -71,15 +82,25 @@ describe('TopNavMenu', () => {
const component = shallowWithIntl(
);
-
+ expect(component.find(WRAPPER_SELECTOR).length).toBe(1);
expect(component.find(TOP_NAV_ITEM_SELECTOR).length).toBe(0);
expect(component.find(SEARCH_BAR_SELECTOR).length).toBe(1);
});
+ it('Should render menu items and search bar', () => {
+ const component = shallowWithIntl(
+
+ );
+ expect(component.find(WRAPPER_SELECTOR).length).toBe(1);
+ expect(component.find(TOP_NAV_ITEM_SELECTOR).length).toBe(menuItems.length);
+ expect(component.find(SEARCH_BAR_SELECTOR).length).toBe(1);
+ });
+
it('Should render with a class name', () => {
const component = shallowWithIntl(
{
return (
+ {renderItems()}
+
+ );
+ }
+
+ function renderSearchBar(): ReactElement | null {
// Validate presense of all required fields
- if (!showSearchBar || !props.data) return;
+ if (!showSearchBar || !props.data) return null;
const { SearchBar } = props.data.ui;
return ;
}
@@ -70,16 +95,7 @@ export function TopNavMenu(props: TopNavMenuProps) {
const className = classNames('kbnTopNavMenu', props.className);
return (
-
- {renderItems()}
-
+ {renderMenu(className)}
{renderSearchBar()}
);
diff --git a/src/plugins/share/common/constants.ts b/src/plugins/share/common/constants.ts
new file mode 100644
index 0000000000000..7ad8e39c279d3
--- /dev/null
+++ b/src/plugins/share/common/constants.ts
@@ -0,0 +1,21 @@
+/*
+ * 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.
+ */
+
+export const CSV_SEPARATOR_SETTING = 'csv:separator';
+export const CSV_QUOTE_VALUES_SETTING = 'csv:quoteValues';
diff --git a/src/plugins/share/public/components/__snapshots__/url_panel_content.test.tsx.snap b/src/plugins/share/public/components/__snapshots__/url_panel_content.test.tsx.snap
index 8787e0c027375..cae7aa96a7c0e 100644
--- a/src/plugins/share/public/components/__snapshots__/url_panel_content.test.tsx.snap
+++ b/src/plugins/share/public/components/__snapshots__/url_panel_content.test.tsx.snap
@@ -44,7 +44,9 @@ exports[`share url panel content render 1`] = `
gutterSize="none"
responsive={false}
>
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
`;
+
+exports[`should show url param extensions 1`] = `
+
+
+
+ }
+ labelType="label"
+ >
+
+
+
+
+
+
+ }
+ position="bottom"
+ />
+
+ ,
+ },
+ Object {
+ "data-test-subj": "exportAsSavedObject",
+ "disabled": false,
+ "id": "savedObject",
+ "label":
+
+
+
+
+
+ }
+ position="bottom"
+ />
+
+ ,
+ },
+ ]
+ }
+ />
+
+
+
+
+
+
+
+
+ }
+ onChange={[Function]}
+ />
+
+
+
+ }
+ position="bottom"
+ />
+
+
+
+
+
+
+
+
+
+`;
diff --git a/src/plugins/share/public/components/share_context_menu.tsx b/src/plugins/share/public/components/share_context_menu.tsx
index c12e9dabd1938..26426853ddabe 100644
--- a/src/plugins/share/public/components/share_context_menu.tsx
+++ b/src/plugins/share/public/components/share_context_menu.tsx
@@ -26,7 +26,7 @@ import { EuiContextMenu, EuiContextMenuPanelDescriptor } from '@elastic/eui';
import { HttpStart } from 'kibana/public';
import { UrlPanelContent } from './url_panel_content';
-import { ShareMenuItem, ShareContextMenuPanelItem } from '../types';
+import { ShareMenuItem, ShareContextMenuPanelItem, UrlParamExtension } from '../types';
interface Props {
allowEmbed: boolean;
@@ -39,6 +39,7 @@ interface Props {
onClose: () => void;
basePath: string;
post: HttpStart['post'];
+ embedUrlParamExtensions?: UrlParamExtension[];
}
export class ShareContextMenu extends Component {
@@ -100,6 +101,7 @@ export class ShareContextMenu extends Component {
basePath={this.props.basePath}
post={this.props.post}
shareableUrl={this.props.shareableUrl}
+ urlParamExtensions={this.props.embedUrlParamExtensions}
/>
),
};
diff --git a/src/plugins/share/public/components/url_panel_content.test.tsx b/src/plugins/share/public/components/url_panel_content.test.tsx
index bd30dbf002df8..481f8312f4262 100644
--- a/src/plugins/share/public/components/url_panel_content.test.tsx
+++ b/src/plugins/share/public/components/url_panel_content.test.tsx
@@ -202,3 +202,13 @@ describe('share url panel content', () => {
});
});
});
+
+test('should show url param extensions', () => {
+ const TestExtension = () => ;
+ const extensions = [{ paramName: 'testExtension', component: TestExtension }];
+ const component = shallow(
+
+ );
+ expect(component.find('TestExtension').length).toBe(1);
+ expect(component).toMatchSnapshot();
+});
diff --git a/src/plugins/share/public/components/url_panel_content.tsx b/src/plugins/share/public/components/url_panel_content.tsx
index 2ece2052c4b95..65a8538693a49 100644
--- a/src/plugins/share/public/components/url_panel_content.tsx
+++ b/src/plugins/share/public/components/url_panel_content.tsx
@@ -17,7 +17,7 @@
* under the License.
*/
-import React, { Component } from 'react';
+import React, { Component, ReactElement } from 'react';
import {
EuiButton,
@@ -41,6 +41,7 @@ import { HttpStart } from 'kibana/public';
import { i18n } from '@kbn/i18n';
import { shortenUrl } from '../lib/url_shortener';
+import { UrlParamExtension } from '../types';
interface Props {
allowShortUrl: boolean;
@@ -50,6 +51,7 @@ interface Props {
shareableUrl?: string;
basePath: string;
post: HttpStart['post'];
+ urlParamExtensions?: UrlParamExtension[];
}
export enum ExportUrlAsType {
@@ -57,12 +59,19 @@ export enum ExportUrlAsType {
EXPORT_URL_AS_SNAPSHOT = 'snapshot',
}
+interface UrlParams {
+ [extensionName: string]: {
+ [queryParam: string]: boolean;
+ };
+}
+
interface State {
exportUrlAs: ExportUrlAsType;
useShortUrl: boolean;
isCreatingShortUrl: boolean;
url?: string;
shortUrlErrorMsg?: string;
+ urlParams?: UrlParams;
}
export class UrlPanelContent extends Component {
@@ -100,7 +109,7 @@ export class UrlPanelContent extends Component {
{this.renderExportAsRadioGroup()}
-
+ {this.renderUrlParamExtensions()}
{this.renderShortUrlSwitch()}
@@ -151,6 +160,13 @@ export class UrlPanelContent extends Component {
}
};
+ private updateUrlParams = (url: string) => {
+ const embedUrl = this.props.isEmbedded ? this.makeUrlEmbeddable(url) : url;
+ const extendUrl = this.state.urlParams ? this.getUrlParamExtensions(embedUrl) : embedUrl;
+
+ return extendUrl;
+ };
+
private getSavedObjectUrl = () => {
if (this.isNotSaved()) {
return;
@@ -166,7 +182,7 @@ export class UrlPanelContent extends Component {
// Get the application route, after the hash, and remove the #.
const parsedAppUrl = parseUrl(parsedUrl.hash.slice(1), true);
- let formattedUrl = formatUrl({
+ const formattedUrl = formatUrl({
protocol: parsedUrl.protocol,
auth: parsedUrl.auth,
host: parsedUrl.host,
@@ -180,28 +196,42 @@ export class UrlPanelContent extends Component {
},
}),
});
- if (this.props.isEmbedded) {
- formattedUrl = this.makeUrlEmbeddable(formattedUrl);
- }
- return formattedUrl;
+ return this.updateUrlParams(formattedUrl);
};
private getSnapshotUrl = () => {
- let url = this.props.shareableUrl || window.location.href;
- if (this.props.isEmbedded) {
- url = this.makeUrlEmbeddable(url);
- }
- return url;
+ const url = this.props.shareableUrl || window.location.href;
+
+ return this.updateUrlParams(url);
};
- private makeUrlEmbeddable = (url: string) => {
- const embedQueryParam = '?embed=true';
+ private makeUrlEmbeddable = (url: string): string => {
+ const embedParam = '?embed=true';
const urlHasQueryString = url.indexOf('?') !== -1;
+
if (urlHasQueryString) {
- return url.replace('?', `${embedQueryParam}&`);
+ return url.replace('?', `${embedParam}&`);
}
- return `${url}${embedQueryParam}`;
+
+ return `${url}${embedParam}`;
+ };
+
+ private getUrlParamExtensions = (url: string): string => {
+ const { urlParams } = this.state;
+ return urlParams
+ ? Object.keys(urlParams).reduce((urlAccumulator, key) => {
+ const urlParam = urlParams[key];
+ return urlParam
+ ? Object.keys(urlParam).reduce((queryAccumulator, queryParam) => {
+ const isQueryParamEnabled = urlParam[queryParam];
+ return isQueryParamEnabled
+ ? queryAccumulator + `&${queryParam}=true`
+ : queryAccumulator;
+ }, urlAccumulator)
+ : urlAccumulator;
+ }, url)
+ : url;
};
private makeIframeTag = (url?: string) => {
@@ -247,6 +277,10 @@ export class UrlPanelContent extends Component {
}
// "Use short URL" is checked but shortUrl has not been generated yet so one needs to be created.
+ this.createShortUrl();
+ };
+
+ private createShortUrl = async () => {
this.setState({
isCreatingShortUrl: true,
shortUrlErrorMsg: undefined,
@@ -262,7 +296,7 @@ export class UrlPanelContent extends Component {
this.setState(
{
isCreatingShortUrl: false,
- useShortUrl: isChecked,
+ useShortUrl: true,
},
this.setUrl
);
@@ -321,7 +355,7 @@ export class UrlPanelContent extends Component {
private renderWithIconTip = (child: React.ReactNode, tipContent: React.ReactNode) => {
return (
- {child}
+ {child}
@@ -397,4 +431,34 @@ export class UrlPanelContent extends Component {
);
};
+
+ private renderUrlParamExtensions = (): ReactElement | void => {
+ if (!this.props.urlParamExtensions) {
+ return;
+ }
+
+ const setParamValue = (paramName: string) => (
+ values: { [queryParam: string]: boolean } = {}
+ ): void => {
+ const stateUpdate = {
+ urlParams: {
+ ...this.state.urlParams,
+ [paramName]: {
+ ...values,
+ },
+ },
+ };
+ this.setState(stateUpdate, this.state.useShortUrl ? this.createShortUrl : this.setUrl);
+ };
+
+ return (
+
+ {this.props.urlParamExtensions.map(({ paramName, component: UrlParamComponent }) => (
+
+
+
+ ))}
+
+ );
+ };
}
diff --git a/src/plugins/share/public/index.ts b/src/plugins/share/public/index.ts
index 183219645467e..e3d6c41a278cd 100644
--- a/src/plugins/share/public/index.ts
+++ b/src/plugins/share/public/index.ts
@@ -17,6 +17,8 @@
* under the License.
*/
+export { CSV_QUOTE_VALUES_SETTING, CSV_SEPARATOR_SETTING } from '../common/constants';
+
export { UrlGeneratorStateMapping } from './url_generators/url_generator_definition';
export { SharePluginSetup, SharePluginStart } from './plugin';
diff --git a/src/plugins/share/public/services/share_menu_manager.tsx b/src/plugins/share/public/services/share_menu_manager.tsx
index 35116efa85961..3325c5503fe89 100644
--- a/src/plugins/share/public/services/share_menu_manager.tsx
+++ b/src/plugins/share/public/services/share_menu_manager.tsx
@@ -67,6 +67,7 @@ export class ShareMenuManager {
shareableUrl,
post,
basePath,
+ embedUrlParamExtensions,
}: ShowShareMenuOptions & {
menuItems: ShareMenuItem[];
post: HttpStart['post'];
@@ -102,6 +103,7 @@ export class ShareMenuManager {
onClose={this.onClose}
post={post}
basePath={basePath}
+ embedUrlParamExtensions={embedUrlParamExtensions}
/>
diff --git a/src/plugins/share/public/types.ts b/src/plugins/share/public/types.ts
index 6b20f1f53a28c..8dda9f1195a39 100644
--- a/src/plugins/share/public/types.ts
+++ b/src/plugins/share/public/types.ts
@@ -17,6 +17,7 @@
* under the License.
*/
+import { ComponentType } from 'react';
import { EuiContextMenuPanelDescriptor, EuiContextMenuPanelItemDescriptor } from '@elastic/eui';
/**
@@ -80,9 +81,19 @@ export interface ShareMenuProvider {
getShareMenuItems: (context: ShareContext) => ShareMenuItem[];
}
+interface UrlParamExtensionProps {
+ setParamValue: (values: {}) => void;
+}
+
+export interface UrlParamExtension {
+ paramName: string;
+ component: ComponentType;
+}
+
/** @public */
export interface ShowShareMenuOptions extends Omit {
anchorElement: HTMLElement;
allowEmbed: boolean;
allowShortUrl: boolean;
+ embedUrlParamExtensions?: UrlParamExtension[];
}
diff --git a/src/plugins/share/public/url_generators/url_generator_service.ts b/src/plugins/share/public/url_generators/url_generator_service.ts
index 13c1b94acdd07..b63e2a45d6812 100644
--- a/src/plugins/share/public/url_generators/url_generator_service.ts
+++ b/src/plugins/share/public/url_generators/url_generator_service.ts
@@ -24,7 +24,7 @@ import { UrlGeneratorInternal } from './url_generator_internal';
import { UrlGeneratorContract } from './url_generator_contract';
export interface UrlGeneratorsStart {
- getUrlGenerator: (urlGeneratorId: UrlGeneratorId) => UrlGeneratorContract;
+ getUrlGenerator: (urlGeneratorId: T) => UrlGeneratorContract;
}
export interface UrlGeneratorsSetup {
diff --git a/src/plugins/share/server/index.ts b/src/plugins/share/server/index.ts
index 9e574314f8000..ff419ce68d46b 100644
--- a/src/plugins/share/server/index.ts
+++ b/src/plugins/share/server/index.ts
@@ -20,6 +20,8 @@
import { PluginInitializerContext } from '../../../core/server';
import { SharePlugin } from './plugin';
+export { CSV_QUOTE_VALUES_SETTING, CSV_SEPARATOR_SETTING } from '../common/constants';
+
export function plugin(initializerContext: PluginInitializerContext) {
return new SharePlugin(initializerContext);
}
diff --git a/src/plugins/share/server/plugin.ts b/src/plugins/share/server/plugin.ts
index 0d9f183d13404..e444cb1658d95 100644
--- a/src/plugins/share/server/plugin.ts
+++ b/src/plugins/share/server/plugin.ts
@@ -17,9 +17,12 @@
* under the License.
*/
+import { i18n } from '@kbn/i18n';
+import { schema } from '@kbn/config-schema';
import { CoreSetup, Plugin, PluginInitializerContext } from 'kibana/server';
import { createRoutes } from './routes/create_routes';
import { url } from './saved_objects';
+import { CSV_SEPARATOR_SETTING, CSV_QUOTE_VALUES_SETTING } from '../common/constants';
export class SharePlugin implements Plugin {
constructor(private readonly initializerContext: PluginInitializerContext) {}
@@ -27,6 +30,28 @@ export class SharePlugin implements Plugin {
public async setup(core: CoreSetup) {
createRoutes(core, this.initializerContext.logger.get());
core.savedObjects.registerType(url);
+ core.uiSettings.register({
+ [CSV_SEPARATOR_SETTING]: {
+ name: i18n.translate('share.advancedSettings.csv.separatorTitle', {
+ defaultMessage: 'CSV separator',
+ }),
+ value: ',',
+ description: i18n.translate('share.advancedSettings.csv.separatorText', {
+ defaultMessage: 'Separate exported values with this string',
+ }),
+ schema: schema.string(),
+ },
+ [CSV_QUOTE_VALUES_SETTING]: {
+ name: i18n.translate('share.advancedSettings.csv.quoteValuesTitle', {
+ defaultMessage: 'Quote CSV values',
+ }),
+ value: true,
+ description: i18n.translate('share.advancedSettings.csv.quoteValuesText', {
+ defaultMessage: 'Should values be quoted in csv exports?',
+ }),
+ schema: schema.boolean(),
+ },
+ });
}
public start() {
diff --git a/src/plugins/vis_default_editor/public/components/controls/filters.tsx b/src/plugins/vis_default_editor/public/components/controls/filters.tsx
index 7a655b935a45e..9a9933b5e1e83 100644
--- a/src/plugins/vis_default_editor/public/components/controls/filters.tsx
+++ b/src/plugins/vis_default_editor/public/components/controls/filters.tsx
@@ -23,7 +23,7 @@ import { htmlIdGenerator, EuiButton, EuiSpacer } from '@elastic/eui';
import { FormattedMessage } from '@kbn/i18n/react';
import { useMount } from 'react-use';
-import { Query } from 'src/plugins/data/public';
+import { Query, UI_SETTINGS } from '../../../../data/public';
import { useKibana } from '../../../../kibana_react/public';
import { FilterRow } from './filter';
import { AggParamEditorProps } from '../agg_param_props';
@@ -68,7 +68,7 @@ function FiltersParamEditor({ agg, value = [], setValue }: AggParamEditorProps) {
setValue(value && agg.params.min_doc_count);
}
+ /* eslint-disable-next-line react-hooks/exhaustive-deps */
}, [agg.params.min_doc_count, setValue, value]);
return (
diff --git a/src/plugins/vis_default_editor/public/components/controls/number_interval.tsx b/src/plugins/vis_default_editor/public/components/controls/number_interval.tsx
index 02bf680734526..0d21eb04c12b2 100644
--- a/src/plugins/vis_default_editor/public/components/controls/number_interval.tsx
+++ b/src/plugins/vis_default_editor/public/components/controls/number_interval.tsx
@@ -23,6 +23,7 @@ import React, { useEffect, useCallback } from 'react';
import { EuiFieldNumber, EuiFormRow, EuiIconTip } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n/react';
+import { UI_SETTINGS } from '../../../../data/public';
import { AggParamEditorProps } from '../agg_param_props';
@@ -38,7 +39,7 @@ const label = (
}
type="questionInCircle"
diff --git a/src/plugins/vis_default_editor/public/components/controls/utils/agg_utils.ts b/src/plugins/vis_default_editor/public/components/controls/utils/agg_utils.ts
index ee24e2b42113d..950c856349230 100644
--- a/src/plugins/vis_default_editor/public/components/controls/utils/agg_utils.ts
+++ b/src/plugins/vis_default_editor/public/components/controls/utils/agg_utils.ts
@@ -33,6 +33,7 @@ const CUSTOM_METRIC = {
};
function useCompatibleAggCallback(aggFilter: AggFilter) {
+ /* eslint-disable-next-line react-hooks/exhaustive-deps */
return useCallback(isCompatibleAggregation(aggFilter), [aggFilter]);
}
diff --git a/src/plugins/vis_type_table/public/agg_table/agg_table.js b/src/plugins/vis_type_table/public/agg_table/agg_table.js
index f67dcf42adff6..bd7626a493338 100644
--- a/src/plugins/vis_type_table/public/agg_table/agg_table.js
+++ b/src/plugins/vis_type_table/public/agg_table/agg_table.js
@@ -17,6 +17,7 @@
* under the License.
*/
import _ from 'lodash';
+import { CSV_SEPARATOR_SETTING, CSV_QUOTE_VALUES_SETTING } from '../../../share/public';
import aggTableTemplate from './agg_table.html';
import { getFormatService } from '../services';
import { i18n } from '@kbn/i18n';
@@ -47,8 +48,8 @@ export function KbnAggTable(config, RecursionHelper) {
self._saveAs = require('@elastic/filesaver').saveAs;
self.csv = {
- separator: config.get('csv:separator'),
- quoteValues: config.get('csv:quoteValues'),
+ separator: config.get(CSV_SEPARATOR_SETTING),
+ quoteValues: config.get(CSV_QUOTE_VALUES_SETTING),
};
self.exportAsCsv = function (formatted) {
diff --git a/src/plugins/vis_type_timelion/public/components/panel.tsx b/src/plugins/vis_type_timelion/public/components/panel.tsx
index 4c28e4e5a18ab..99c5532c04832 100644
--- a/src/plugins/vis_type_timelion/public/components/panel.tsx
+++ b/src/plugins/vis_type_timelion/public/components/panel.tsx
@@ -102,6 +102,7 @@ function Panel({ interval, seriesList, renderComplete }: PanelProps) {
[chartElem]
);
+ /* eslint-disable-next-line react-hooks/exhaustive-deps */
const highlightSeries = useCallback(
debounce(({ currentTarget }: JQuery.TriggeredEvent) => {
const id = Number(currentTarget.getAttribute(SERIES_ID_ATTR));
@@ -295,6 +296,7 @@ function Panel({ interval, seriesList, renderComplete }: PanelProps) {
[plot, legendValueNumbers, unhighlightSeries, legendCaption]
);
+ /* eslint-disable-next-line react-hooks/exhaustive-deps */
const debouncedSetLegendNumbers = useCallback(
debounce(setLegendNumbers, DEBOUNCE_DELAY, {
maxWait: DEBOUNCE_DELAY,
diff --git a/src/plugins/vis_type_timelion/public/components/timelion_expression_input.tsx b/src/plugins/vis_type_timelion/public/components/timelion_expression_input.tsx
index 8c76b41df0ced..8258b92b096c1 100644
--- a/src/plugins/vis_type_timelion/public/components/timelion_expression_input.tsx
+++ b/src/plugins/vis_type_timelion/public/components/timelion_expression_input.tsx
@@ -20,7 +20,7 @@
import React, { useEffect, useCallback, useRef, useMemo } from 'react';
import { EuiFormLabel } from '@elastic/eui';
import { FormattedMessage } from '@kbn/i18n/react';
-import { monaco } from '@kbn/ui-shared-deps/monaco';
+import { monaco } from '@kbn/monaco';
import { CodeEditor, useKibana } from '../../../kibana_react/public';
import { suggest, getSuggestion } from './timelion_expression_input_helpers';
diff --git a/src/plugins/vis_type_timelion/public/components/timelion_expression_input_helpers.ts b/src/plugins/vis_type_timelion/public/components/timelion_expression_input_helpers.ts
index f7b3433105b76..8db057cdb3cc5 100644
--- a/src/plugins/vis_type_timelion/public/components/timelion_expression_input_helpers.ts
+++ b/src/plugins/vis_type_timelion/public/components/timelion_expression_input_helpers.ts
@@ -19,7 +19,7 @@
import { get, startsWith } from 'lodash';
import { i18n } from '@kbn/i18n';
-import { monaco } from '@kbn/ui-shared-deps/monaco';
+import { monaco } from '@kbn/monaco';
import { Parser } from 'pegjs';
diff --git a/src/plugins/vis_type_timelion/server/series_functions/es/es.test.js b/src/plugins/vis_type_timelion/server/series_functions/es/es.test.js
index 1bc979399b1b1..a624ff72ead69 100644
--- a/src/plugins/vis_type_timelion/server/series_functions/es/es.test.js
+++ b/src/plugins/vis_type_timelion/server/series_functions/es/es.test.js
@@ -30,6 +30,7 @@ import _ from 'lodash';
import { expect } from 'chai';
import sinon from 'sinon';
import invoke from '../helpers/invoke_series_fn.js';
+import { UI_SETTINGS } from '../../../../data/server';
function stubRequestAndServer(response, indexPatternSavedObjects = []) {
return {
@@ -216,14 +217,14 @@ describe('es', () => {
it('sets ignore_throttled=true on the request', () => {
config.index = 'beer';
- tlConfig.settings['search:includeFrozen'] = false;
+ tlConfig.settings[UI_SETTINGS.SEARCH_INCLUDE_FROZEN] = false;
const request = fn(config, tlConfig, emptyScriptedFields);
expect(request.ignore_throttled).to.equal(true);
});
it('sets no timeout if elasticsearch.shardTimeout is set to 0', () => {
- tlConfig.settings['search:includeFrozen'] = true;
+ tlConfig.settings[UI_SETTINGS.SEARCH_INCLUDE_FROZEN] = true;
config.index = 'beer';
const request = fn(config, tlConfig, emptyScriptedFields);
diff --git a/src/plugins/vis_type_timelion/server/series_functions/es/lib/build_request.js b/src/plugins/vis_type_timelion/server/series_functions/es/lib/build_request.js
index 65b28fb833279..bc0e368fbdab1 100644
--- a/src/plugins/vis_type_timelion/server/series_functions/es/lib/build_request.js
+++ b/src/plugins/vis_type_timelion/server/series_functions/es/lib/build_request.js
@@ -21,6 +21,7 @@ import _ from 'lodash';
import moment from 'moment';
import { buildAggBody } from './agg_body';
import createDateAgg from './create_date_agg';
+import { UI_SETTINGS } from '../../../../../data/server';
export default function buildRequest(config, tlConfig, scriptedFields, timeout) {
const bool = { must: [] };
@@ -78,7 +79,7 @@ export default function buildRequest(config, tlConfig, scriptedFields, timeout)
const request = {
index: config.index,
- ignore_throttled: !tlConfig.settings['search:includeFrozen'],
+ ignore_throttled: !tlConfig.settings[UI_SETTINGS.SEARCH_INCLUDE_FROZEN],
body: {
query: {
bool: bool,
diff --git a/src/plugins/vis_type_timeseries/public/application/components/lib/get_default_query_language.js b/src/plugins/vis_type_timeseries/public/application/components/lib/get_default_query_language.js
index 972f937ad109d..84da28718e323 100644
--- a/src/plugins/vis_type_timeseries/public/application/components/lib/get_default_query_language.js
+++ b/src/plugins/vis_type_timeseries/public/application/components/lib/get_default_query_language.js
@@ -18,7 +18,8 @@
*/
import { getUISettings } from '../../../services';
+import { UI_SETTINGS } from '../../../../../data/public';
export function getDefaultQueryLanguage() {
- return getUISettings().get('search:queryLanguage');
+ return getUISettings().get(UI_SETTINGS.SEARCH_QUERY_LANGUAGE);
}
diff --git a/src/plugins/vis_type_timeseries/public/application/components/lib/tick_formatter.test.js b/src/plugins/vis_type_timeseries/public/application/components/lib/tick_formatter.test.js
index 71e82770bfa03..308579126eeb1 100644
--- a/src/plugins/vis_type_timeseries/public/application/components/lib/tick_formatter.test.js
+++ b/src/plugins/vis_type_timeseries/public/application/components/lib/tick_formatter.test.js
@@ -20,6 +20,7 @@
import { createTickFormatter } from './tick_formatter';
import { getFieldFormatsRegistry } from '../../../../../../test_utils/public/stub_field_formats';
import { setFieldFormats } from '../../../services';
+import { UI_SETTINGS } from '../../../../../data/public';
const mockUiSettings = {
get: (item) => {
@@ -28,11 +29,11 @@ const mockUiSettings = {
getUpdate$: () => ({
subscribe: jest.fn(),
}),
- 'query:allowLeadingWildcards': true,
- 'query:queryString:options': {},
- 'courier:ignoreFilterIfFieldNotInIndex': true,
+ [UI_SETTINGS.QUERY_ALLOW_LEADING_WILDCARDS]: true,
+ [UI_SETTINGS.QUERY_STRING_OPTIONS]: {},
+ [UI_SETTINGS.COURIER_IGNORE_FILTER_IF_FIELD_NOT_IN_INDEX]: true,
'dateFormat:tz': 'Browser',
- 'format:defaultTypeMap': {},
+ [UI_SETTINGS.FORMAT_DEFAULT_TYPE_MAP]: {},
};
const mockCore = {
@@ -55,7 +56,7 @@ describe('createTickFormatter(format, template)', () => {
test('returns a percent with percent formatter', () => {
const config = {
- 'format:percent:defaultPattern': '0.[00]%',
+ [UI_SETTINGS.FORMAT_PERCENT_DEFAULT_PATTERN]: '0.[00]%',
};
const fn = createTickFormatter('percent', null, (key) => config[key]);
expect(fn(0.5556)).toEqual('55.56%');
@@ -63,7 +64,7 @@ describe('createTickFormatter(format, template)', () => {
test('returns a byte formatted string with byte formatter', () => {
const config = {
- 'format:bytes:defaultPattern': '0.0b',
+ [UI_SETTINGS.FORMAT_BYTES_DEFAULT_PATTERN]: '0.0b',
};
const fn = createTickFormatter('bytes', null, (key) => config[key]);
expect(fn(1500 ^ 10)).toEqual('1.5KB');
@@ -76,7 +77,7 @@ describe('createTickFormatter(format, template)', () => {
test('returns a located string with custom locale setting', () => {
const config = {
- 'format:number:defaultLocale': 'fr',
+ [UI_SETTINGS.FORMAT_NUMBER_DEFAULT_LOCALE]: 'fr',
};
const fn = createTickFormatter('0,0.0', null, (key) => config[key]);
expect(fn(1500)).toEqual('1 500,0');
@@ -99,7 +100,7 @@ describe('createTickFormatter(format, template)', () => {
test('returns formatted value if passed a bad template', () => {
const config = {
- 'format:number:defaultPattern': '0,0.[00]',
+ [UI_SETTINGS.FORMAT_NUMBER_DEFAULT_PATTERN]: '0,0.[00]',
};
const fn = createTickFormatter('number', '{{value', (key) => config[key]);
expect(fn(1.5556)).toEqual('1.56');
diff --git a/src/plugins/vis_type_timeseries/public/application/components/vis_editor.js b/src/plugins/vis_type_timeseries/public/application/components/vis_editor.js
index 0c53ddd3f0ba8..a96890d4d1502 100644
--- a/src/plugins/vis_type_timeseries/public/application/components/vis_editor.js
+++ b/src/plugins/vis_type_timeseries/public/application/components/vis_editor.js
@@ -29,7 +29,7 @@ import { PanelConfig } from './panel_config';
import { createBrushHandler } from '../lib/create_brush_handler';
import { fetchFields } from '../lib/fetch_fields';
import { extractIndexPatterns } from '../../../../../plugins/vis_type_timeseries/common/extract_index_patterns';
-import { esKuery } from '../../../../../plugins/data/public';
+import { esKuery, UI_SETTINGS } from '../../../../../plugins/data/public';
import { getSavedObjectsClient, getUISettings, getDataStart, getCoreStart } from '../../services';
import { CoreStartContextProvider } from '../contexts/query_input_bar_context';
@@ -89,7 +89,9 @@ export class VisEditor extends Component {
isValidKueryQuery = (filterQuery) => {
if (filterQuery && filterQuery.language === 'kuery') {
try {
- const queryOptions = this.coreContext.uiSettings.get('query:allowLeadingWildcards');
+ const queryOptions = this.coreContext.uiSettings.get(
+ UI_SETTINGS.QUERY_ALLOW_LEADING_WILDCARDS
+ );
esKuery.fromKueryExpression(filterQuery.query, { allowLeadingWildcards: queryOptions });
} catch (error) {
return false;
diff --git a/src/plugins/vis_type_timeseries/server/lib/search_strategies/search_requests/multi_search_request.js b/src/plugins/vis_type_timeseries/server/lib/search_strategies/search_requests/multi_search_request.js
index 93a4eaba4ad9e..9ada39e359589 100644
--- a/src/plugins/vis_type_timeseries/server/lib/search_strategies/search_requests/multi_search_request.js
+++ b/src/plugins/vis_type_timeseries/server/lib/search_strategies/search_requests/multi_search_request.js
@@ -17,12 +17,15 @@
* under the License.
*/
import { AbstractSearchRequest } from './abstract_request';
+import { UI_SETTINGS } from '../../../../../data/server';
const SEARCH_METHOD = 'msearch';
export class MultiSearchRequest extends AbstractSearchRequest {
async search(searches) {
- const includeFrozen = await this.req.getUiSettingsService().get('search:includeFrozen');
+ const includeFrozen = await this.req
+ .getUiSettingsService()
+ .get(UI_SETTINGS.SEARCH_INCLUDE_FROZEN);
const multiSearchBody = searches.reduce(
(acc, { body, index }) => [
...acc,
diff --git a/src/plugins/vis_type_timeseries/server/lib/search_strategies/search_requests/multi_search_request.test.js b/src/plugins/vis_type_timeseries/server/lib/search_strategies/search_requests/multi_search_request.test.js
index 1e28965a35793..c113db76332b7 100644
--- a/src/plugins/vis_type_timeseries/server/lib/search_strategies/search_requests/multi_search_request.test.js
+++ b/src/plugins/vis_type_timeseries/server/lib/search_strategies/search_requests/multi_search_request.test.js
@@ -17,6 +17,7 @@
* under the License.
*/
import { MultiSearchRequest } from './multi_search_request';
+import { UI_SETTINGS } from '../../../../../data/server';
describe('MultiSearchRequest', () => {
let searchRequest;
@@ -51,7 +52,7 @@ describe('MultiSearchRequest', () => {
expect(responses).toEqual([]);
expect(req.getUiSettingsService).toHaveBeenCalled();
- expect(getServiceMock).toHaveBeenCalledWith('search:includeFrozen');
+ expect(getServiceMock).toHaveBeenCalledWith(UI_SETTINGS.SEARCH_INCLUDE_FROZEN);
expect(callWithRequest).toHaveBeenCalledWith(req, 'msearch', {
body: [
{ ignoreUnavailable: true, index: 'index' },
diff --git a/src/plugins/vis_type_timeseries/server/lib/search_strategies/search_requests/single_search_request.js b/src/plugins/vis_type_timeseries/server/lib/search_strategies/search_requests/single_search_request.js
index 110deb6a9bc1b..7d8b60a7e4595 100644
--- a/src/plugins/vis_type_timeseries/server/lib/search_strategies/search_requests/single_search_request.js
+++ b/src/plugins/vis_type_timeseries/server/lib/search_strategies/search_requests/single_search_request.js
@@ -17,12 +17,15 @@
* under the License.
*/
import { AbstractSearchRequest } from './abstract_request';
+import { UI_SETTINGS } from '../../../../../data/server';
const SEARCH_METHOD = 'search';
export class SingleSearchRequest extends AbstractSearchRequest {
async search([{ body, index }]) {
- const includeFrozen = await this.req.getUiSettingsService().get('search:includeFrozen');
+ const includeFrozen = await this.req
+ .getUiSettingsService()
+ .get(UI_SETTINGS.SEARCH_INCLUDE_FROZEN);
const resp = await this.callWithRequest(this.req, SEARCH_METHOD, {
ignore_throttled: !includeFrozen,
body,
diff --git a/src/plugins/vis_type_timeseries/server/lib/search_strategies/search_requests/single_search_request.test.js b/src/plugins/vis_type_timeseries/server/lib/search_strategies/search_requests/single_search_request.test.js
index 043bd52d87aad..b899814f2fe13 100644
--- a/src/plugins/vis_type_timeseries/server/lib/search_strategies/search_requests/single_search_request.test.js
+++ b/src/plugins/vis_type_timeseries/server/lib/search_strategies/search_requests/single_search_request.test.js
@@ -17,6 +17,7 @@
* under the License.
*/
import { SingleSearchRequest } from './single_search_request';
+import { UI_SETTINGS } from '../../../../../data/server';
describe('SingleSearchRequest', () => {
let searchRequest;
@@ -48,7 +49,7 @@ describe('SingleSearchRequest', () => {
expect(responses).toEqual([{}]);
expect(req.getUiSettingsService).toHaveBeenCalled();
- expect(getServiceMock).toHaveBeenCalledWith('search:includeFrozen');
+ expect(getServiceMock).toHaveBeenCalledWith(UI_SETTINGS.SEARCH_INCLUDE_FROZEN);
expect(callWithRequest).toHaveBeenCalledWith(req, 'search', {
body: 'body',
index: 'index',
diff --git a/src/plugins/vis_type_timeseries/server/lib/vis_data/helpers/get_es_query_uisettings.js b/src/plugins/vis_type_timeseries/server/lib/vis_data/helpers/get_es_query_uisettings.js
index 42b8681f142e0..b427e5f12cadc 100644
--- a/src/plugins/vis_type_timeseries/server/lib/vis_data/helpers/get_es_query_uisettings.js
+++ b/src/plugins/vis_type_timeseries/server/lib/vis_data/helpers/get_es_query_uisettings.js
@@ -17,12 +17,14 @@
* under the License.
*/
+import { UI_SETTINGS } from '../../../../../data/server';
+
export async function getEsQueryConfig(req) {
const uiSettings = req.getUiSettingsService();
- const allowLeadingWildcards = await uiSettings.get('query:allowLeadingWildcards');
- const queryStringOptions = await uiSettings.get('query:queryString:options');
+ const allowLeadingWildcards = await uiSettings.get(UI_SETTINGS.QUERY_ALLOW_LEADING_WILDCARDS);
+ const queryStringOptions = await uiSettings.get(UI_SETTINGS.QUERY_STRING_OPTIONS);
const ignoreFilterIfFieldNotInIndex = await uiSettings.get(
- 'courier:ignoreFilterIfFieldNotInIndex'
+ UI_SETTINGS.COURIER_IGNORE_FILTER_IF_FIELD_NOT_IN_INDEX
);
return {
allowLeadingWildcards,
diff --git a/src/plugins/visualizations/common/constants.ts b/src/plugins/visualizations/common/constants.ts
new file mode 100644
index 0000000000000..9129f060c5eef
--- /dev/null
+++ b/src/plugins/visualizations/common/constants.ts
@@ -0,0 +1,20 @@
+/*
+ * 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.
+ */
+
+export const VISUALIZE_ENABLE_LABS_SETTING = 'visualize:enableLabs';
diff --git a/src/plugins/visualizations/public/embeddable/create_vis_embeddable_from_object.ts b/src/plugins/visualizations/public/embeddable/create_vis_embeddable_from_object.ts
index 81794c31527ad..45c750de05ae1 100644
--- a/src/plugins/visualizations/public/embeddable/create_vis_embeddable_from_object.ts
+++ b/src/plugins/visualizations/public/embeddable/create_vis_embeddable_from_object.ts
@@ -29,6 +29,7 @@ import {
getCapabilities,
} from '../services';
import { VisualizeEmbeddableFactoryDeps } from './visualize_embeddable_factory';
+import { VISUALIZE_ENABLE_LABS_SETTING } from '../../common/constants';
export const createVisEmbeddableFromObject = (deps: VisualizeEmbeddableFactoryDeps) => async (
vis: Vis,
@@ -44,7 +45,7 @@ export const createVisEmbeddableFromObject = (deps: VisualizeEmbeddableFactoryDe
const editUrl = visId
? getHttp().basePath.prepend(`/app/visualize${savedVisualizations.urlFor(visId)}`)
: '';
- const isLabsEnabled = getUISettings().get('visualize:enableLabs');
+ const isLabsEnabled = getUISettings().get(VISUALIZE_ENABLE_LABS_SETTING);
if (!isLabsEnabled && vis.type.stage === 'experimental') {
return new DisabledLabEmbeddable(vis.title, input);
diff --git a/src/plugins/visualizations/public/embeddable/visualize_embeddable_factory.tsx b/src/plugins/visualizations/public/embeddable/visualize_embeddable_factory.tsx
index c4aa4c262edb0..c4267c9a36f78 100644
--- a/src/plugins/visualizations/public/embeddable/visualize_embeddable_factory.tsx
+++ b/src/plugins/visualizations/public/embeddable/visualize_embeddable_factory.tsx
@@ -43,6 +43,7 @@ import { convertToSerializedVis } from '../saved_visualizations/_saved_vis';
import { createVisEmbeddableFromObject } from './create_vis_embeddable_from_object';
import { StartServicesGetter } from '../../../kibana_utils/public';
import { VisualizationsStartDeps } from '../plugin';
+import { VISUALIZE_ENABLE_LABS_SETTING } from '../../common/constants';
interface VisualizationAttributes extends SavedObjectAttributes {
visState: string;
@@ -82,7 +83,7 @@ export class VisualizeEmbeddableFactory
if (!visType) {
return false;
}
- if (getUISettings().get('visualize:enableLabs')) {
+ if (getUISettings().get(VISUALIZE_ENABLE_LABS_SETTING)) {
return true;
}
return visType.stage !== 'experimental';
diff --git a/src/plugins/visualizations/public/index.ts b/src/plugins/visualizations/public/index.ts
index e475684ed5934..0bbf862216ed5 100644
--- a/src/plugins/visualizations/public/index.ts
+++ b/src/plugins/visualizations/public/index.ts
@@ -17,8 +17,6 @@
* under the License.
*/
-import './index.scss';
-
import { PublicContract } from '@kbn/utility-types';
import { PluginInitializerContext } from 'src/core/public';
import { VisualizationsPlugin, VisualizationsSetup, VisualizationsStart } from './plugin';
@@ -53,3 +51,4 @@ export {
VisSavedObject,
VisResponseValue,
} from './types';
+export { VISUALIZE_ENABLE_LABS_SETTING } from '../common/constants';
diff --git a/src/plugins/visualizations/public/mocks.ts b/src/plugins/visualizations/public/mocks.ts
index 70c3bc2c1ed05..05644eddc5fca 100644
--- a/src/plugins/visualizations/public/mocks.ts
+++ b/src/plugins/visualizations/public/mocks.ts
@@ -66,6 +66,7 @@ const createInstance = async () => {
inspector: inspectorPluginMock.createStartContract(),
uiActions: uiActionsPluginMock.createStartContract(),
application: applicationServiceMock.createStartContract(),
+ embeddable: embeddablePluginMock.createStartContract(),
});
return {
diff --git a/src/plugins/visualizations/public/plugin.ts b/src/plugins/visualizations/public/plugin.ts
index ef64eccfea31f..3546fa4056491 100644
--- a/src/plugins/visualizations/public/plugin.ts
+++ b/src/plugins/visualizations/public/plugin.ts
@@ -17,6 +17,8 @@
* under the License.
*/
+import './index.scss';
+
import {
PluginInitializerContext,
CoreSetup,
@@ -45,6 +47,7 @@ import {
setChrome,
setOverlays,
setSavedSearchLoader,
+ setEmbeddable,
} from './services';
import {
VISUALIZE_EMBEDDABLE_TYPE,
@@ -52,7 +55,7 @@ import {
createVisEmbeddableFromObject,
} from './embeddable';
import { ExpressionsSetup, ExpressionsStart } from '../../expressions/public';
-import { EmbeddableSetup } from '../../embeddable/public';
+import { EmbeddableSetup, EmbeddableStart } from '../../embeddable/public';
import { visualization as visualizationFunction } from './expressions/visualization_function';
import { visualization as visualizationRenderer } from './expressions/visualization_renderer';
import { range as rangeExpressionFunction } from './expression_functions/range';
@@ -102,6 +105,7 @@ export interface VisualizationsSetupDeps {
export interface VisualizationsStartDeps {
data: DataPublicPluginStart;
expressions: ExpressionsStart;
+ embeddable: EmbeddableStart;
inspector: InspectorStart;
uiActions: UiActionsStart;
application: ApplicationStart;
@@ -151,11 +155,12 @@ export class VisualizationsPlugin
public start(
core: CoreStart,
- { data, expressions, uiActions }: VisualizationsStartDeps
+ { data, expressions, uiActions, embeddable }: VisualizationsStartDeps
): VisualizationsStart {
const types = this.types.start();
setI18n(core.i18n);
setTypes(types);
+ setEmbeddable(embeddable);
setApplication(core.application);
setCapabilities(core.application.capabilities);
setHttp(core.http);
diff --git a/src/plugins/visualizations/public/services.ts b/src/plugins/visualizations/public/services.ts
index 15055022af8aa..0761b8862e8e3 100644
--- a/src/plugins/visualizations/public/services.ts
+++ b/src/plugins/visualizations/public/services.ts
@@ -40,6 +40,7 @@ import { ExpressionsStart } from '../../../plugins/expressions/public';
import { UiActionsStart } from '../../../plugins/ui_actions/public';
import { SavedVisualizationsLoader } from './saved_visualizations';
import { SavedObjectLoader } from '../../saved_objects/public';
+import { EmbeddableStart } from '../../embeddable/public';
export const [getUISettings, setUISettings] = createGetterSetter('UISettings');
@@ -49,6 +50,8 @@ export const [getHttp, setHttp] = createGetterSetter('Http');
export const [getApplication, setApplication] = createGetterSetter('Application');
+export const [getEmbeddable, setEmbeddable] = createGetterSetter('Embeddable');
+
export const [getSavedObjects, setSavedObjects] = createGetterSetter(
'SavedObjects'
);
diff --git a/src/plugins/visualizations/public/wizard/new_vis_modal.tsx b/src/plugins/visualizations/public/wizard/new_vis_modal.tsx
index cea92b1db93aa..1a970e505b7c7 100644
--- a/src/plugins/visualizations/public/wizard/new_vis_modal.tsx
+++ b/src/plugins/visualizations/public/wizard/new_vis_modal.tsx
@@ -29,6 +29,7 @@ import { TypeSelection } from './type_selection';
import { TypesStart, VisType, VisTypeAlias } from '../vis_types';
import { UsageCollectionSetup } from '../../../../plugins/usage_collection/public';
import { EMBEDDABLE_ORIGINATING_APP_PARAM } from '../../../embeddable/public';
+import { VISUALIZE_ENABLE_LABS_SETTING } from '../../common/constants';
interface TypeSelectionProps {
isOpen: boolean;
@@ -65,7 +66,7 @@ class NewVisModal extends React.Component originatingApp;
const visStateToEditorState = () => {
diff --git a/src/plugins/visualize/public/application/listing/visualize_listing.js b/src/plugins/visualize/public/application/listing/visualize_listing.js
index 228cfa1e9e492..e8e8d92034113 100644
--- a/src/plugins/visualize/public/application/listing/visualize_listing.js
+++ b/src/plugins/visualize/public/application/listing/visualize_listing.js
@@ -25,6 +25,8 @@ import { i18n } from '@kbn/i18n';
import { getServices } from '../../kibana_services';
import { syncQueryStateWithUrl } from '../../../../data/public';
+import { VISUALIZE_ENABLE_LABS_SETTING } from '../../../../visualizations/public';
+
import { EuiLink } from '@elastic/eui';
import React from 'react';
@@ -120,7 +122,7 @@ export function VisualizeListingController($scope, createNewVis, kbnUrlStateStor
}
this.fetchItems = (filter) => {
- const isLabsEnabled = uiSettings.get('visualize:enableLabs');
+ const isLabsEnabled = uiSettings.get(VISUALIZE_ENABLE_LABS_SETTING);
return savedVisualizations
.findListItems(filter, savedObjectsPublic.settings.getListingLimit())
.then((result) => {
diff --git a/test/functional/apps/bundles/index.js b/test/functional/apps/bundles/index.js
index 503517a98c69e..ead6412564751 100644
--- a/test/functional/apps/bundles/index.js
+++ b/test/functional/apps/bundles/index.js
@@ -25,7 +25,7 @@ export default function ({ getService }) {
const supertest = getService('supertest');
describe('bundle compression', function () {
- this.tags('ciGroup12');
+ this.tags(['ciGroup12', 'skipCoverage']);
let buildNum;
before(async () => {
diff --git a/test/functional/apps/context/_filters.js b/test/functional/apps/context/_filters.js
index 470ef462b9d9d..66888d441954e 100644
--- a/test/functional/apps/context/_filters.js
+++ b/test/functional/apps/context/_filters.js
@@ -17,8 +17,6 @@
* under the License.
*/
-import expect from '@kbn/expect';
-
const TEST_INDEX_PATTERN = 'logstash-*';
const TEST_ANCHOR_ID = 'AU_x3_BrGFA8no6QjjaI';
const TEST_ANCHOR_FILTER_FIELD = 'geo.src';
@@ -40,20 +38,19 @@ export default function ({ getService, getPageObjects }) {
});
it('inclusive filter should be addable via expanded doc table rows', async function () {
- await docTable.toggleRowExpanded({ isAnchorRow: true });
-
- await retry.try(async () => {
+ await retry.waitFor(`filter ${TEST_ANCHOR_FILTER_FIELD} in filterbar`, async () => {
+ await docTable.toggleRowExpanded({ isAnchorRow: true });
const anchorDetailsRow = await docTable.getAnchorDetailsRow();
await docTable.addInclusiveFilter(anchorDetailsRow, TEST_ANCHOR_FILTER_FIELD);
await PageObjects.context.waitUntilContextLoadingHasFinished();
- expect(
- await filterBar.hasFilter(TEST_ANCHOR_FILTER_FIELD, TEST_ANCHOR_FILTER_VALUE, true)
- ).to.be(true);
+
+ return await filterBar.hasFilter(TEST_ANCHOR_FILTER_FIELD, TEST_ANCHOR_FILTER_VALUE, true);
+ });
+ await retry.waitFor(`filter matching docs in docTable`, async () => {
const fields = await docTable.getFields();
- const hasOnlyFilteredRows = fields
+ return fields
.map((row) => row[2])
.every((fieldContent) => fieldContent === TEST_ANCHOR_FILTER_VALUE);
- expect(hasOnlyFilteredRows).to.be(true);
});
});
@@ -64,26 +61,27 @@ export default function ({ getService, getPageObjects }) {
await filterBar.toggleFilterEnabled(TEST_ANCHOR_FILTER_FIELD);
await PageObjects.context.waitUntilContextLoadingHasFinished();
- await retry.try(async () => {
- expect(
- await filterBar.hasFilter(TEST_ANCHOR_FILTER_FIELD, TEST_ANCHOR_FILTER_VALUE, false)
- ).to.be(true);
+ await retry.waitFor(`a disabled filter in filterbar`, async () => {
+ return await filterBar.hasFilter(TEST_ANCHOR_FILTER_FIELD, TEST_ANCHOR_FILTER_VALUE, false);
+ });
+
+ await retry.waitFor('filters are disabled', async () => {
const fields = await docTable.getFields();
const hasOnlyFilteredRows = fields
.map((row) => row[2])
.every((fieldContent) => fieldContent === TEST_ANCHOR_FILTER_VALUE);
- expect(hasOnlyFilteredRows).to.be(false);
+ return hasOnlyFilteredRows === false;
});
});
it('filter for presence should be addable via expanded doc table rows', async function () {
await docTable.toggleRowExpanded({ isAnchorRow: true });
- await retry.try(async () => {
+ await retry.waitFor('an exists filter in the filterbar', async () => {
const anchorDetailsRow = await docTable.getAnchorDetailsRow();
await docTable.addExistsFilter(anchorDetailsRow, TEST_ANCHOR_FILTER_FIELD);
await PageObjects.context.waitUntilContextLoadingHasFinished();
- expect(await filterBar.hasFilter(TEST_ANCHOR_FILTER_FIELD, 'exists', true)).to.be(true);
+ return await filterBar.hasFilter(TEST_ANCHOR_FILTER_FIELD, 'exists', true);
});
});
});
diff --git a/test/functional/apps/context/_size.js b/test/functional/apps/context/_size.js
index 3beb070b50deb..067a23daacb4a 100644
--- a/test/functional/apps/context/_size.js
+++ b/test/functional/apps/context/_size.js
@@ -16,69 +16,69 @@
* specific language governing permissions and limitations
* under the License.
*/
-
-import expect from '@kbn/expect';
-
const TEST_INDEX_PATTERN = 'logstash-*';
const TEST_ANCHOR_ID = 'AU_x3_BrGFA8no6QjjaI';
-const TEST_DEFAULT_CONTEXT_SIZE = 7;
-const TEST_STEP_SIZE = 3;
+const TEST_DEFAULT_CONTEXT_SIZE = 2;
+const TEST_STEP_SIZE = 2;
export default function ({ getService, getPageObjects }) {
const kibanaServer = getService('kibanaServer');
const retry = getService('retry');
const docTable = getService('docTable');
const PageObjects = getPageObjects(['context']);
+ let expectedRowLength = 2 * TEST_DEFAULT_CONTEXT_SIZE + 1;
- // FLAKY: https://github.com/elastic/kibana/issues/53888
- describe.skip('context size', function contextSize() {
+ describe('context size', function contextSize() {
before(async function () {
await kibanaServer.uiSettings.update({
'context:defaultSize': `${TEST_DEFAULT_CONTEXT_SIZE}`,
'context:step': `${TEST_STEP_SIZE}`,
});
+ await PageObjects.context.navigateTo(TEST_INDEX_PATTERN, TEST_ANCHOR_ID);
});
it('should default to the `context:defaultSize` setting', async function () {
- await PageObjects.context.navigateTo(TEST_INDEX_PATTERN, TEST_ANCHOR_ID);
-
- await retry.try(async function () {
- expect(await docTable.getRowsText()).to.have.length(2 * TEST_DEFAULT_CONTEXT_SIZE + 1);
- });
- await retry.try(async function () {
- const predecessorCountPicker = await PageObjects.context.getPredecessorCountPicker();
- expect(await predecessorCountPicker.getAttribute('value')).to.equal(
- `${TEST_DEFAULT_CONTEXT_SIZE}`
- );
- });
- await retry.try(async function () {
- const successorCountPicker = await PageObjects.context.getSuccessorCountPicker();
- expect(await successorCountPicker.getAttribute('value')).to.equal(
- `${TEST_DEFAULT_CONTEXT_SIZE}`
- );
- });
+ await retry.waitFor(
+ `number of rows displayed initially is ${expectedRowLength}`,
+ async function () {
+ const rows = await docTable.getRowsText();
+ return rows.length === expectedRowLength;
+ }
+ );
+ await retry.waitFor(
+ `predecessor count picker is set to ${TEST_DEFAULT_CONTEXT_SIZE}`,
+ async function () {
+ const predecessorCountPicker = await PageObjects.context.getPredecessorCountPicker();
+ const value = await predecessorCountPicker.getAttribute('value');
+ return value === String(TEST_DEFAULT_CONTEXT_SIZE);
+ }
+ );
});
it('should increase according to the `context:step` setting when clicking the `load newer` button', async function () {
- await PageObjects.context.navigateTo(TEST_INDEX_PATTERN, TEST_ANCHOR_ID);
await PageObjects.context.clickPredecessorLoadMoreButton();
+ expectedRowLength += TEST_STEP_SIZE;
- await retry.try(async function () {
- expect(await docTable.getRowsText()).to.have.length(
- 2 * TEST_DEFAULT_CONTEXT_SIZE + TEST_STEP_SIZE + 1
- );
- });
+ await retry.waitFor(
+ `number of rows displayed after clicking load more predecessors is ${expectedRowLength}`,
+ async function () {
+ const rows = await docTable.getRowsText();
+ return rows.length === expectedRowLength;
+ }
+ );
});
it('should increase according to the `context:step` setting when clicking the `load older` button', async function () {
- await PageObjects.context.navigateTo(TEST_INDEX_PATTERN, TEST_ANCHOR_ID);
await PageObjects.context.clickSuccessorLoadMoreButton();
+ expectedRowLength += TEST_STEP_SIZE;
- await retry.try(async function () {
- expect(await docTable.getRowsText()).to.have.length(
- 2 * TEST_DEFAULT_CONTEXT_SIZE + TEST_STEP_SIZE + 1
- );
- });
+ await retry.waitFor(
+ `number of rows displayed after clicking load more successors is ${expectedRowLength}`,
+ async function () {
+ const rows = await docTable.getRowsText();
+ return rows.length === expectedRowLength;
+ }
+ );
});
});
}
diff --git a/test/functional/apps/dashboard/create_and_add_embeddables.js b/test/functional/apps/dashboard/create_and_add_embeddables.js
index ba715f3472b98..f5c2496a9a5aa 100644
--- a/test/functional/apps/dashboard/create_and_add_embeddables.js
+++ b/test/functional/apps/dashboard/create_and_add_embeddables.js
@@ -20,6 +20,7 @@
import expect from '@kbn/expect';
import { VisualizeConstants } from '../../../../src/plugins/visualize/public/application/visualize_constants';
+import { VISUALIZE_ENABLE_LABS_SETTING } from '../../../../src/plugins/visualizations/common/constants';
export default function ({ getService, getPageObjects }) {
const retry = getService('retry');
@@ -102,7 +103,7 @@ export default function ({ getService, getPageObjects }) {
before(async () => {
await PageObjects.header.clickStackManagement();
await PageObjects.settings.clickKibanaSettings();
- await PageObjects.settings.toggleAdvancedSettingCheckbox('visualize:enableLabs');
+ await PageObjects.settings.toggleAdvancedSettingCheckbox(VISUALIZE_ENABLE_LABS_SETTING);
});
it('should not display lab visualizations in add panel', async () => {
@@ -117,7 +118,7 @@ export default function ({ getService, getPageObjects }) {
after(async () => {
await PageObjects.header.clickStackManagement();
await PageObjects.settings.clickKibanaSettings();
- await PageObjects.settings.clearAdvancedSettings('visualize:enableLabs');
+ await PageObjects.settings.clearAdvancedSettings(VISUALIZE_ENABLE_LABS_SETTING);
await PageObjects.header.clickDashboard();
});
});
diff --git a/test/functional/apps/dashboard/dashboard_filter_bar.js b/test/functional/apps/dashboard/dashboard_filter_bar.js
index 6bc34a8b998a4..c931e6763f483 100644
--- a/test/functional/apps/dashboard/dashboard_filter_bar.js
+++ b/test/functional/apps/dashboard/dashboard_filter_bar.js
@@ -217,6 +217,11 @@ export default function ({ getService, getPageObjects }) {
const hasWarningFieldFilter = await filterBar.hasFilter('extension', 'warn', true);
expect(hasWarningFieldFilter).to.be(true);
});
+
+ it('filter without an index pattern is rendred as a warning, if the dashboard has an index pattern', async function () {
+ const noIndexPatternFilter = await filterBar.hasFilter('banana', 'warn', true);
+ expect(noIndexPatternFilter).to.be(true);
+ });
});
});
}
diff --git a/test/functional/apps/dashboard/embed_mode.js b/test/functional/apps/dashboard/embed_mode.js
index 65ef75f3f65e1..a1828143555b0 100644
--- a/test/functional/apps/dashboard/embed_mode.js
+++ b/test/functional/apps/dashboard/embed_mode.js
@@ -20,6 +20,7 @@
import expect from '@kbn/expect';
export default function ({ getService, getPageObjects }) {
+ const testSubjects = getService('testSubjects');
const retry = getService('retry');
const esArchiver = getService('esArchiver');
const kibanaServer = getService('kibanaServer');
@@ -28,6 +29,13 @@ export default function ({ getService, getPageObjects }) {
const globalNav = getService('globalNav');
describe('embed mode', () => {
+ const urlParamExtensions = [
+ 'show-top-menu=true',
+ 'show-query-input=true',
+ 'show-time-filter=true',
+ 'hide-filter-bar=true',
+ ];
+
before(async () => {
await esArchiver.load('dashboard/current/kibana');
await kibanaServer.uiSettings.replace({
@@ -54,9 +62,28 @@ export default function ({ getService, getPageObjects }) {
});
});
+ it('shows or hides elements based on URL params', async () => {
+ await testSubjects.missingOrFail('top-nav');
+ await testSubjects.missingOrFail('queryInput');
+ await testSubjects.missingOrFail('superDatePickerToggleQuickMenuButton');
+ await testSubjects.existOrFail('showFilterActions');
+
+ const currentUrl = await browser.getCurrentUrl();
+ const newUrl = [currentUrl].concat(urlParamExtensions).join('&');
+ // Embed parameter only works on a hard refresh.
+ const useTimeStamp = true;
+ await browser.get(newUrl.toString(), useTimeStamp);
+
+ await testSubjects.existOrFail('top-nav');
+ await testSubjects.existOrFail('queryInput');
+ await testSubjects.existOrFail('superDatePickerToggleQuickMenuButton');
+ await testSubjects.missingOrFail('showFilterActions');
+ });
+
after(async function () {
const currentUrl = await browser.getCurrentUrl();
- const newUrl = currentUrl.replace('&embed=true', '');
+ const replaceParams = ['', 'embed=true'].concat(urlParamExtensions).join('&');
+ const newUrl = currentUrl.replace(replaceParams, '');
// First use the timestamp to cause a hard refresh so the new embed parameter works correctly.
let useTimeStamp = true;
await browser.get(newUrl.toString(), useTimeStamp);
diff --git a/test/functional/apps/discover/_discover.js b/test/functional/apps/discover/_discover.js
index 9f3ce667d64b5..ecaa5aa2da97f 100644
--- a/test/functional/apps/discover/_discover.js
+++ b/test/functional/apps/discover/_discover.js
@@ -69,6 +69,16 @@ export default function ({ getService, getPageObjects }) {
});
});
+ it('renaming a saved query should modify name in breadcrumb', async function () {
+ const queryName2 = 'Modified Query # 1';
+ await PageObjects.discover.loadSavedSearch(queryName1);
+ await PageObjects.discover.saveSearch(queryName2);
+
+ await retry.try(async function () {
+ expect(await PageObjects.discover.getCurrentQueryName()).to.be(queryName2);
+ });
+ });
+
it('should show the correct hit count', async function () {
const expectedHitCount = '14,004';
await retry.try(async function () {
diff --git a/test/functional/apps/visualize/_lab_mode.js b/test/functional/apps/visualize/_lab_mode.js
index b356d01cdb63b..27c149b9e0e0a 100644
--- a/test/functional/apps/visualize/_lab_mode.js
+++ b/test/functional/apps/visualize/_lab_mode.js
@@ -18,6 +18,7 @@
*/
import expect from '@kbn/expect';
+import { VISUALIZE_ENABLE_LABS_SETTING } from '../../../../src/plugins/visualizations/common/constants';
export default function ({ getService, getPageObjects }) {
const log = getService('log');
@@ -37,7 +38,7 @@ export default function ({ getService, getPageObjects }) {
// Navigate to advanced setting and disable lab mode
await PageObjects.header.clickStackManagement();
await PageObjects.settings.clickKibanaSettings();
- await PageObjects.settings.toggleAdvancedSettingCheckbox('visualize:enableLabs');
+ await PageObjects.settings.toggleAdvancedSettingCheckbox(VISUALIZE_ENABLE_LABS_SETTING);
// Expect the discover still to list that saved visualization in the open list
await PageObjects.header.clickDiscover();
@@ -51,7 +52,7 @@ export default function ({ getService, getPageObjects }) {
await PageObjects.discover.closeLoadSaveSearchPanel();
await PageObjects.header.clickStackManagement();
await PageObjects.settings.clickKibanaSettings();
- await PageObjects.settings.clearAdvancedSettings('visualize:enableLabs');
+ await PageObjects.settings.clearAdvancedSettings(VISUALIZE_ENABLE_LABS_SETTING);
});
});
}
diff --git a/test/functional/apps/visualize/index.ts b/test/functional/apps/visualize/index.ts
index bd427577cd787..42b82486dc13f 100644
--- a/test/functional/apps/visualize/index.ts
+++ b/test/functional/apps/visualize/index.ts
@@ -18,6 +18,7 @@
*/
import { FtrProviderContext } from '../../ftr_provider_context.d';
+import { UI_SETTINGS } from '../../../../src/plugins/data/common';
// eslint-disable-next-line @typescript-eslint/no-namespace, import/no-default-export
export default function ({ getService, getPageObjects, loadTestFile }: FtrProviderContext) {
@@ -37,7 +38,7 @@ export default function ({ getService, getPageObjects, loadTestFile }: FtrProvid
await esArchiver.load('visualize');
await kibanaServer.uiSettings.replace({
defaultIndex: 'logstash-*',
- 'format:bytes:defaultPattern': '0,0.[000]b',
+ [UI_SETTINGS.FORMAT_BYTES_DEFAULT_PATTERN]: '0,0.[000]b',
});
isOss = await PageObjects.common.isOss();
});
diff --git a/test/functional/fixtures/es_archiver/dashboard/current/kibana/data.json.gz b/test/functional/fixtures/es_archiver/dashboard/current/kibana/data.json.gz
index a052aad9450f5..ae78761fef0d3 100644
Binary files a/test/functional/fixtures/es_archiver/dashboard/current/kibana/data.json.gz and b/test/functional/fixtures/es_archiver/dashboard/current/kibana/data.json.gz differ
diff --git a/test/functional/page_objects/common_page.ts b/test/functional/page_objects/common_page.ts
index 91e9c020a0e7c..fe5694efc35da 100644
--- a/test/functional/page_objects/common_page.ts
+++ b/test/functional/page_objects/common_page.ts
@@ -67,17 +67,17 @@ export function CommonPageProvider({ getService, getPageObjects }: FtrProviderCo
* @param appUrl Kibana URL
*/
private async loginIfPrompted(appUrl: string, insertTimestamp: boolean) {
+ // Disable the welcome screen. This is relevant for environments
+ // which don't allow to use the yml setting, e.g. cloud production.
+ // It is done here so it applies to logins but also to a login re-use.
+ await browser.setLocalStorageItem('home:welcome:show', 'false');
+
let currentUrl = await browser.getCurrentUrl();
log.debug(`currentUrl = ${currentUrl}\n appUrl = ${appUrl}`);
await testSubjects.find('kibanaChrome', 6 * defaultFindTimeout); // 60 sec waiting
const loginPage = currentUrl.includes('/login');
const wantedLoginPage = appUrl.includes('/login') || appUrl.includes('/logout');
- // Disable the welcome screen. This is relevant for environments
- // which don't allow to use the yml setting, e.g. cloud production.
- // It is done here so it applies to logins but also to a login re-use.
- await browser.setLocalStorageItem('home:welcome:show', 'false');
-
if (loginPage && !wantedLoginPage) {
log.debug('Found login page');
if (config.get('security.disableTestUser')) {
diff --git a/test/plugin_functional/plugins/core_provider_plugin/kibana.json b/test/plugin_functional/plugins/core_provider_plugin/kibana.json
index 1d5c5824d6b97..8d9b30acab893 100644
--- a/test/plugin_functional/plugins/core_provider_plugin/kibana.json
+++ b/test/plugin_functional/plugins/core_provider_plugin/kibana.json
@@ -2,7 +2,7 @@
"id": "core_provider_plugin",
"version": "0.0.1",
"kibanaVersion": "kibana",
- "optionalPlugins": ["core_plugin_a", "core_plugin_b", "licensing"],
+ "optionalPlugins": ["core_plugin_a", "core_plugin_b", "licensing", "globalSearchTest"],
"server": false,
"ui": true
}
diff --git a/test/plugin_functional/plugins/kbn_tp_embeddable_explorer/public/app/dashboard_input.ts b/test/plugin_functional/plugins/kbn_tp_embeddable_explorer/public/app/dashboard_input.ts
index 6f4e1f052f5e0..21b12e2134767 100644
--- a/test/plugin_functional/plugins/kbn_tp_embeddable_explorer/public/app/dashboard_input.ts
+++ b/test/plugin_functional/plugins/kbn_tp_embeddable_explorer/public/app/dashboard_input.ts
@@ -92,6 +92,7 @@ export const dashboardInput: DashboardContainerInput = {
},
},
},
+ isEmbeddedExternally: false,
isFullScreenMode: false,
filters: [],
useMargins: true,
diff --git a/test/scripts/jenkins_ci_group.sh b/test/scripts/jenkins_ci_group.sh
index 778142d95e4b4..60d7f0406f4c9 100755
--- a/test/scripts/jenkins_ci_group.sh
+++ b/test/scripts/jenkins_ci_group.sh
@@ -31,4 +31,12 @@ else
mkdir -p ../kibana/target/kibana-coverage/functional
mv target/kibana-coverage/functional/* ../kibana/target/kibana-coverage/functional/
fi
+
+ echo " -> moving junit output, silently fail in case of no report"
+ mkdir -p ../kibana/target/junit
+ mv target/junit/* ../kibana/target/junit/ || echo "copying junit failed"
+
+ echo " -> copying screenshots and html for failures"
+ cp -r test/functional/screenshots/* ../kibana/test/functional/screenshots/ || echo "copying screenshots failed"
+ cp -r test/functional/failure_debug ../kibana/test/functional/ || echo "copying html failed"
fi
diff --git a/test/scripts/jenkins_siem_cypress.sh b/test/scripts/jenkins_security_solution_cypress.sh
similarity index 67%
rename from test/scripts/jenkins_siem_cypress.sh
rename to test/scripts/jenkins_security_solution_cypress.sh
index c7157e97b36cc..23b83cf946d49 100644
--- a/test/scripts/jenkins_siem_cypress.sh
+++ b/test/scripts/jenkins_security_solution_cypress.sh
@@ -8,14 +8,14 @@ cp -R "$installDir" "$destDir"
export KIBANA_INSTALL_DIR="$destDir"
-echo " -> Running SIEM cypress tests"
+echo " -> Running security solution cypress tests"
cd "$XPACK_DIR"
-checks-reporter-with-killswitch "SIEM Cypress Tests" \
+checks-reporter-with-killswitch "Security solution Cypress Tests" \
node scripts/functional_tests \
--debug --bail \
--kibana-install-dir "$KIBANA_INSTALL_DIR" \
- --config test/siem_cypress/config.ts
+ --config test/security_solution_cypress/config.ts
echo ""
echo ""
diff --git a/test/scripts/jenkins_xpack.sh b/test/scripts/jenkins_xpack.sh
index 50a92a41e3932..067ed213c49f5 100755
--- a/test/scripts/jenkins_xpack.sh
+++ b/test/scripts/jenkins_xpack.sh
@@ -17,7 +17,7 @@ if [[ -z "$CODE_COVERAGE" ]] ; then
echo " -> Running SIEM cyclic dependency test"
cd "$XPACK_DIR"
- checks-reporter-with-killswitch "X-Pack SIEM cyclic dependency test" node plugins/siem/scripts/check_circular_deps
+ checks-reporter-with-killswitch "X-Pack SIEM cyclic dependency test" node plugins/security_solution/scripts/check_circular_deps
echo ""
echo ""
diff --git a/test/scripts/jenkins_xpack_ci_group.sh b/test/scripts/jenkins_xpack_ci_group.sh
index a6e600630364e..648605135b359 100755
--- a/test/scripts/jenkins_xpack_ci_group.sh
+++ b/test/scripts/jenkins_xpack_ci_group.sh
@@ -32,4 +32,12 @@ else
mkdir -p ../../kibana/target/kibana-coverage/functional
mv ../target/kibana-coverage/functional/* ../../kibana/target/kibana-coverage/functional/
fi
+
+ echo " -> moving junit output, silently fail in case of no report"
+ mkdir -p ../../kibana/target/junit
+ mv ../target/junit/* ../../kibana/target/junit/ || echo "copying junit failed"
+
+ echo " -> copying screenshots and html for failures"
+ cp -r test/functional/screenshots/* ../../kibana/x-pack/test/functional/screenshots/ || echo "copying screenshots failed"
+ cp -r test/functional/failure_debug ../../kibana/x-pack/test/functional/ || echo "copying html failed"
fi
\ No newline at end of file
diff --git a/test/scripts/jenkins_xpack_page_load_metrics.sh b/test/scripts/jenkins_xpack_page_load_metrics.sh
new file mode 100644
index 0000000000000..679f0b8d2ddc5
--- /dev/null
+++ b/test/scripts/jenkins_xpack_page_load_metrics.sh
@@ -0,0 +1,9 @@
+#!/usr/bin/env bash
+
+source test/scripts/jenkins_test_setup_xpack.sh
+
+checks-reporter-with-killswitch "Capture Kibana page load metrics" \
+ node scripts/functional_tests \
+ --debug --bail \
+ --kibana-install-dir "$installDir" \
+ --config test/page_load_metrics/config.ts;
diff --git a/vars/kibanaCoverage.groovy b/vars/kibanaCoverage.groovy
index 0305f86475a9a..66b16566418b5 100644
--- a/vars/kibanaCoverage.groovy
+++ b/vars/kibanaCoverage.groovy
@@ -98,7 +98,7 @@ def collectVcsInfo(title) {
def generateReports(title) {
kibanaPipeline.bash("""
- source src/dev/ci_setup/setup_env.sh
+ source src/dev/ci_setup/setup_env.sh true
# bootstrap from x-pack folder
cd x-pack
yarn kbn bootstrap --prefer-offline
diff --git a/x-pack/.gitignore b/x-pack/.gitignore
index 5245e8a2e95c4..68262c4bf734b 100644
--- a/x-pack/.gitignore
+++ b/x-pack/.gitignore
@@ -3,8 +3,11 @@
/target
/test/functional/failure_debug
/test/functional/screenshots
+/test/page_load_metrics/screenshots
/test/functional/apps/reporting/reports/session
/test/reporting/configs/failure_debug/
+/legacy/plugins/reporting/.chromium/
+/legacy/plugins/reporting/.phantom/
/plugins/reporting/.chromium/
/plugins/reporting/.phantom/
/.aws-config.json
@@ -12,4 +15,4 @@
/.kibana-plugin-helpers.dev.*
!/legacy/plugins/infra/**/target
.cache
-!/legacy/plugins/siem/**/target
+!/legacy/plugins/security_solution/**/target
diff --git a/x-pack/.i18nrc.json b/x-pack/.i18nrc.json
index 48dfa341f6385..85b40d33c4089 100644
--- a/x-pack/.i18nrc.json
+++ b/x-pack/.i18nrc.json
@@ -2,8 +2,7 @@
"prefix": "xpack",
"paths": {
"xpack.actions": "plugins/actions",
- "xpack.advancedUiActions": "plugins/advanced_ui_actions",
- "xpack.uiActionsEnhanced": "examples/ui_actions_enhanced_examples",
+ "xpack.uiActionsEnhanced": ["plugins/ui_actions_enhanced", "examples/ui_actions_enhanced_examples"],
"xpack.alerts": "plugins/alerts",
"xpack.alertingBuiltins": "plugins/alerting_builtins",
"xpack.apm": ["legacy/plugins/apm", "plugins/apm"],
@@ -18,6 +17,7 @@
"xpack.endpoint": "plugins/endpoint",
"xpack.features": "plugins/features",
"xpack.fileUpload": "plugins/file_upload",
+ "xpack.globalSearch": ["plugins/global_search"],
"xpack.graph": ["plugins/graph"],
"xpack.grokDebugger": "plugins/grokdebugger",
"xpack.idxMgmt": "plugins/index_management",
@@ -38,9 +38,9 @@
"xpack.reporting": ["plugins/reporting"],
"xpack.rollupJobs": ["legacy/plugins/rollup", "plugins/rollup"],
"xpack.searchProfiler": "plugins/searchprofiler",
- "xpack.security": ["legacy/plugins/security", "plugins/security"],
+ "xpack.security": "plugins/security",
"xpack.server": "legacy/server",
- "xpack.siem": "plugins/siem",
+ "xpack.securitySolution": "plugins/security_solution",
"xpack.snapshotRestore": "plugins/snapshot_restore",
"xpack.spaces": ["legacy/plugins/spaces", "plugins/spaces"],
"xpack.taskManager": "legacy/plugins/task_manager",
@@ -48,7 +48,8 @@
"xpack.triggersActionsUI": "plugins/triggers_actions_ui",
"xpack.upgradeAssistant": "plugins/upgrade_assistant",
"xpack.uptime": ["plugins/uptime"],
- "xpack.watcher": "plugins/watcher"
+ "xpack.watcher": "plugins/watcher",
+ "xpack.observability": "plugins/observability"
},
"translations": [
"plugins/translations/translations/zh-CN.json",
diff --git a/x-pack/README.md b/x-pack/README.md
index 744d97ca02c75..03d2e3287c0f0 100644
--- a/x-pack/README.md
+++ b/x-pack/README.md
@@ -25,8 +25,8 @@ Examples:
- Run the jest test case whose description matches 'filtering should skip values of null':
`cd x-pack && yarn test:jest -t 'filtering should skip values of null' plugins/ml/public/application/explorer/explorer_charts/explorer_charts_container_service.test.js`
- Run the x-pack api integration test case whose description matches the given string:
- `node scripts/functional_tests_server --config x-pack/test/api_integration/config.js`
- `node scripts/functional_test_runner --config x-pack/test/api_integration/config.js --grep='apis Monitoring Beats list with restarted beat instance should load multiple clusters'`
+ `node scripts/functional_tests_server --config x-pack/test/api_integration/config.ts`
+ `node scripts/functional_test_runner --config x-pack/test/api_integration/config.ts --grep='apis Monitoring Beats list with restarted beat instance should load multiple clusters'`
In addition to to providing a regular expression argument, specific tests can also be run by appeding `.only` to an `it` or `describe` function block. E.g. `describe(` to `describe.only(`.
@@ -63,7 +63,7 @@ yarn test:mocha
For more info, see [the Elastic functional test development guide](https://www.elastic.co/guide/en/kibana/current/development-functional-tests.html).
-The functional UI tests, the API integration tests, and the SAML API integration tests are all run against a live browser, Kibana, and Elasticsearch install. Each set of tests is specified with a unique config that describes how to start the Elasticsearch server, the Kibana server, and what tests to run against them. The sets of tests that exist today are *functional UI tests* ([specified by this config](test/functional/config.js)), *API integration tests* ([specified by this config](test/api_integration/config.js)), and *SAML API integration tests* ([specified by this config](test/saml_api_integration/config.js)).
+The functional UI tests, the API integration tests, and the SAML API integration tests are all run against a live browser, Kibana, and Elasticsearch install. Each set of tests is specified with a unique config that describes how to start the Elasticsearch server, the Kibana server, and what tests to run against them. The sets of tests that exist today are *functional UI tests* ([specified by this config](test/functional/config.js)), *API integration tests* ([specified by this config](test/api_integration/config.ts)), and *SAML API integration tests* ([specified by this config](test/saml_api_integration/config.ts)).
The script runs all sets of tests sequentially like so:
* builds Elasticsearch and X-Pack
diff --git a/x-pack/dev-tools/jest/create_jest_config.js b/x-pack/dev-tools/jest/create_jest_config.js
index a222e11d28f4a..74553bbde0cd6 100644
--- a/x-pack/dev-tools/jest/create_jest_config.js
+++ b/x-pack/dev-tools/jest/create_jest_config.js
@@ -24,7 +24,8 @@ export function createJestConfig({ kibanaDirectory, rootDir, xPackKibanaDirector
'\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$': fileMockPath,
'\\.module.(css|scss)$': `${kibanaDirectory}/src/dev/jest/mocks/css_module_mock.js`,
'\\.(css|less|scss)$': `${kibanaDirectory}/src/dev/jest/mocks/style_mock.js`,
- '\\.ace\\.worker.js$': `${kibanaDirectory}/src/dev/jest/mocks/ace_worker_module_mock.js`,
+ '\\.ace\\.worker.js$': `${kibanaDirectory}/src/dev/jest/mocks/worker_module_mock.js`,
+ '\\.editor\\.worker.js$': `${kibanaDirectory}/src/dev/jest/mocks/worker_module_mock.js`,
'^test_utils/enzyme_helpers': `${xPackKibanaDirectory}/test_utils/enzyme_helpers.tsx`,
'^test_utils/find_test_subject': `${xPackKibanaDirectory}/test_utils/find_test_subject.ts`,
'^test_utils/stub_web_worker': `${xPackKibanaDirectory}/test_utils/stub_web_worker.ts`,
@@ -42,6 +43,7 @@ export function createJestConfig({ kibanaDirectory, rootDir, xPackKibanaDirector
'!**/scripts/**',
'!**/mocks/**',
'!**/plugins/apm/e2e/**',
+ '!**/plugins/siem/cypress/**',
],
coveragePathIgnorePatterns: ['.*\\.d\\.ts'],
coverageDirectory: `${kibanaDirectory}/target/kibana-coverage/jest`,
diff --git a/x-pack/examples/ui_actions_enhanced_examples/kibana.json b/x-pack/examples/ui_actions_enhanced_examples/kibana.json
index e220cdd5cd297..a1cd895bb3cd6 100644
--- a/x-pack/examples/ui_actions_enhanced_examples/kibana.json
+++ b/x-pack/examples/ui_actions_enhanced_examples/kibana.json
@@ -5,6 +5,6 @@
"configPath": ["ui_actions_enhanced_examples"],
"server": false,
"ui": true,
- "requiredPlugins": ["advancedUiActions", "data"],
+ "requiredPlugins": ["uiActionsEnhanced", "data", "discover"],
"optionalPlugins": []
}
diff --git a/x-pack/examples/ui_actions_enhanced_examples/public/dashboard_hello_world_drilldown/index.tsx b/x-pack/examples/ui_actions_enhanced_examples/public/dashboard_hello_world_drilldown/index.tsx
index 847035403da02..bfe853241ae1d 100644
--- a/x-pack/examples/ui_actions_enhanced_examples/public/dashboard_hello_world_drilldown/index.tsx
+++ b/x-pack/examples/ui_actions_enhanced_examples/public/dashboard_hello_world_drilldown/index.tsx
@@ -7,7 +7,7 @@
import React from 'react';
import { EuiFormRow, EuiFieldText } from '@elastic/eui';
import { reactToUiComponent } from '../../../../../src/plugins/kibana_react/public';
-import { UiActionsEnhancedDrilldownDefinition as Drilldown } from '../../../../plugins/advanced_ui_actions/public';
+import { UiActionsEnhancedDrilldownDefinition as Drilldown } from '../../../../plugins/ui_actions_enhanced/public';
import {
RangeSelectTriggerContext,
ValueClickTriggerContext,
diff --git a/x-pack/examples/ui_actions_enhanced_examples/public/dashboard_to_discover_drilldown/components/discover_drilldown_config/discover_drilldown_config.tsx b/x-pack/examples/ui_actions_enhanced_examples/public/dashboard_to_discover_drilldown/components/discover_drilldown_config/discover_drilldown_config.tsx
index 0237e128c5a2f..da9b0e921fb1c 100644
--- a/x-pack/examples/ui_actions_enhanced_examples/public/dashboard_to_discover_drilldown/components/discover_drilldown_config/discover_drilldown_config.tsx
+++ b/x-pack/examples/ui_actions_enhanced_examples/public/dashboard_to_discover_drilldown/components/discover_drilldown_config/discover_drilldown_config.tsx
@@ -31,9 +31,7 @@ export const DiscoverDrilldownConfig: React.FC = (
onIndexPatternSelect,
customIndexPattern,
onCustomIndexPatternToggle,
- carryFiltersAndQuery,
onCarryFiltersAndQueryToggle,
- carryTimeRange,
onCarryTimeRangeToggle,
}) => {
return (
@@ -82,9 +80,10 @@ export const DiscoverDrilldownConfig: React.FC = (
{!!onCarryFiltersAndQueryToggle && (
@@ -92,9 +91,10 @@ export const DiscoverDrilldownConfig: React.FC = (
{!!onCarryTimeRangeToggle && (
diff --git a/x-pack/examples/ui_actions_enhanced_examples/public/dashboard_to_discover_drilldown/drilldown.tsx b/x-pack/examples/ui_actions_enhanced_examples/public/dashboard_to_discover_drilldown/drilldown.tsx
index fef01c9640f0d..ba88f49861ffe 100644
--- a/x-pack/examples/ui_actions_enhanced_examples/public/dashboard_to_discover_drilldown/drilldown.tsx
+++ b/x-pack/examples/ui_actions_enhanced_examples/public/dashboard_to_discover_drilldown/drilldown.tsx
@@ -11,7 +11,7 @@ import { StartServicesGetter } from '../../../../../src/plugins/kibana_utils/pub
import { ActionContext, Config, CollectConfigProps } from './types';
import { CollectConfigContainer } from './collect_config_container';
import { SAMPLE_DASHBOARD_TO_DISCOVER_DRILLDOWN } from './constants';
-import { UiActionsEnhancedDrilldownDefinition as Drilldown } from '../../../../plugins/advanced_ui_actions/public';
+import { UiActionsEnhancedDrilldownDefinition as Drilldown } from '../../../../plugins/ui_actions_enhanced/public';
import { txtGoToDiscover } from './i18n';
const isOutputWithIndexPatterns = (
@@ -22,7 +22,7 @@ const isOutputWithIndexPatterns = (
};
export interface Params {
- start: StartServicesGetter>;
+ start: StartServicesGetter>;
}
export class DashboardToDiscoverDrilldown implements Drilldown {
@@ -54,6 +54,10 @@ export class DashboardToDiscoverDrilldown implements Drilldown => {
+ const { urlGenerator } = this.params.start().plugins.discover;
+
+ if (!urlGenerator) throw new Error('Discover URL generator not available.');
+
let indexPatternId =
!!config.customIndexPattern && !!config.indexPatternId ? config.indexPatternId : '';
@@ -64,8 +68,9 @@ export class DashboardToDiscoverDrilldown implements Drilldown => {
diff --git a/x-pack/examples/ui_actions_enhanced_examples/public/dashboard_to_url_drilldown/index.tsx b/x-pack/examples/ui_actions_enhanced_examples/public/dashboard_to_url_drilldown/index.tsx
index 20267a8b7292b..4810fb2d6ad8d 100644
--- a/x-pack/examples/ui_actions_enhanced_examples/public/dashboard_to_url_drilldown/index.tsx
+++ b/x-pack/examples/ui_actions_enhanced_examples/public/dashboard_to_url_drilldown/index.tsx
@@ -7,7 +7,7 @@
import React from 'react';
import { EuiFormRow, EuiSwitch, EuiFieldText, EuiCallOut, EuiSpacer } from '@elastic/eui';
import { reactToUiComponent } from '../../../../../src/plugins/kibana_react/public';
-import { UiActionsEnhancedDrilldownDefinition as Drilldown } from '../../../../plugins/advanced_ui_actions/public';
+import { UiActionsEnhancedDrilldownDefinition as Drilldown } from '../../../../plugins/ui_actions_enhanced/public';
import {
RangeSelectTriggerContext,
ValueClickTriggerContext,
diff --git a/x-pack/examples/ui_actions_enhanced_examples/public/plugin.ts b/x-pack/examples/ui_actions_enhanced_examples/public/plugin.ts
index 0d4f274caf57f..8034c378cc64f 100644
--- a/x-pack/examples/ui_actions_enhanced_examples/public/plugin.ts
+++ b/x-pack/examples/ui_actions_enhanced_examples/public/plugin.ts
@@ -9,27 +9,30 @@ import { DataPublicPluginSetup, DataPublicPluginStart } from '../../../../src/pl
import {
AdvancedUiActionsSetup,
AdvancedUiActionsStart,
-} from '../../../../x-pack/plugins/advanced_ui_actions/public';
+} from '../../../../x-pack/plugins/ui_actions_enhanced/public';
import { DashboardHelloWorldDrilldown } from './dashboard_hello_world_drilldown';
import { DashboardToUrlDrilldown } from './dashboard_to_url_drilldown';
import { DashboardToDiscoverDrilldown } from './dashboard_to_discover_drilldown';
import { createStartServicesGetter } from '../../../../src/plugins/kibana_utils/public';
+import { DiscoverSetup, DiscoverStart } from '../../../../src/plugins/discover/public';
export interface SetupDependencies {
data: DataPublicPluginSetup;
- advancedUiActions: AdvancedUiActionsSetup;
+ discover: DiscoverSetup;
+ uiActionsEnhanced: AdvancedUiActionsSetup;
}
export interface StartDependencies {
data: DataPublicPluginStart;
- advancedUiActions: AdvancedUiActionsStart;
+ discover: DiscoverStart;
+ uiActionsEnhanced: AdvancedUiActionsStart;
}
export class UiActionsEnhancedExamplesPlugin
implements Plugin {
public setup(
core: CoreSetup,
- { advancedUiActions: uiActions }: SetupDependencies
+ { uiActionsEnhanced: uiActions }: SetupDependencies
) {
const start = createStartServicesGetter(core.getStartServices);
diff --git a/x-pack/legacy/plugins/beats_management/readme.md b/x-pack/legacy/plugins/beats_management/readme.md
index 301caad683dd5..3414f09deed46 100644
--- a/x-pack/legacy/plugins/beats_management/readme.md
+++ b/x-pack/legacy/plugins/beats_management/readme.md
@@ -15,7 +15,7 @@ In one shell, from **~/kibana/x-pack**:
`node scripts/functional_tests-server.js`
In another shell, from **~kibana/x-pack**:
-`node ../scripts/functional_test_runner.js --config test/api_integration/config.js`.
+`node ../scripts/functional_test_runner.js --config test/api_integration/config.ts`.
### Manual e2e testing
diff --git a/x-pack/legacy/plugins/beats_management/server/lib/adapters/framework/adapter_types.ts b/x-pack/legacy/plugins/beats_management/server/lib/adapters/framework/adapter_types.ts
index bb1f68e1c03b3..80599f38d982a 100644
--- a/x-pack/legacy/plugins/beats_management/server/lib/adapters/framework/adapter_types.ts
+++ b/x-pack/legacy/plugins/beats_management/server/lib/adapters/framework/adapter_types.ts
@@ -8,6 +8,7 @@
import { Lifecycle, ResponseToolkit } from 'hapi';
import * as t from 'io-ts';
+import { SecurityPluginSetup } from '../../../../../../../plugins/security/server';
import { LicenseType } from '../../../../common/constants/security';
export const internalAuthData = Symbol('internalAuthData');
@@ -39,6 +40,11 @@ export interface BackendFrameworkAdapter {
}
export interface KibanaLegacyServer {
+ newPlatform: {
+ setup: {
+ plugins: { security: SecurityPluginSetup };
+ };
+ };
plugins: {
xpack_main: {
status: {
@@ -53,9 +59,6 @@ export interface KibanaLegacyServer {
};
};
};
- security: {
- getUser: (request: KibanaServerRequest) => any;
- };
elasticsearch: {
status: {
on: (status: 'green' | 'yellow' | 'red', callback: () => void) => void;
diff --git a/x-pack/legacy/plugins/beats_management/server/lib/adapters/framework/kibana_framework_adapter.ts b/x-pack/legacy/plugins/beats_management/server/lib/adapters/framework/kibana_framework_adapter.ts
index 589f34ac74601..1bf9bbb22b352 100644
--- a/x-pack/legacy/plugins/beats_management/server/lib/adapters/framework/kibana_framework_adapter.ts
+++ b/x-pack/legacy/plugins/beats_management/server/lib/adapters/framework/kibana_framework_adapter.ts
@@ -8,6 +8,7 @@ import { ResponseToolkit } from 'hapi';
import { PathReporter } from 'io-ts/lib/PathReporter';
import { get } from 'lodash';
import { isLeft } from 'fp-ts/lib/Either';
+import { KibanaRequest, LegacyRequest } from '../../../../../../../../src/core/server';
// @ts-ignore
import { mirrorPluginStatus } from '../../../../../../server/lib/mirror_plugin_status';
import {
@@ -128,13 +129,10 @@ export class KibanaBackendFrameworkAdapter implements BackendFrameworkAdapter {
}
private async getUser(request: KibanaServerRequest): Promise {
- let user;
- try {
- user = await this.server.plugins.security.getUser(request);
- } catch (e) {
- return null;
- }
- if (user === null) {
+ const user = this.server.newPlatform.setup.plugins.security?.authc.getCurrentUser(
+ KibanaRequest.from((request as unknown) as LegacyRequest)
+ );
+ if (!user) {
return null;
}
const assertKibanaUser = RuntimeKibanaUser.decode(user);
diff --git a/x-pack/legacy/plugins/security/index.ts b/x-pack/legacy/plugins/security/index.ts
index 41371fcbc4c65..addeef34f63bf 100644
--- a/x-pack/legacy/plugins/security/index.ts
+++ b/x-pack/legacy/plugins/security/index.ts
@@ -6,64 +6,17 @@
import { Root } from 'joi';
import { resolve } from 'path';
-import { Server } from 'src/legacy/server/kbn_server';
-import { KibanaRequest, LegacyRequest } from '../../../../src/core/server';
-// @ts-ignore
-import { watchStatusAndLicenseToInitialize } from '../../server/lib/watch_status_and_license_to_initialize';
-import { AuthenticatedUser, SecurityPluginSetup } from '../../../plugins/security/server';
-
-/**
- * Public interface of the security plugin.
- */
-export interface SecurityPlugin {
- getUser: (request: LegacyRequest) => Promise;
-}
-
-function getSecurityPluginSetup(server: Server) {
- const securityPlugin = server.newPlatform.setup.plugins.security as SecurityPluginSetup;
- if (!securityPlugin) {
- throw new Error('Kibana Platform Security plugin is not available.');
- }
-
- return securityPlugin;
-}
export const security = (kibana: Record) =>
new kibana.Plugin({
id: 'security',
publicDir: resolve(__dirname, 'public'),
- require: ['kibana', 'xpack_main'],
+ require: ['kibana'],
configPrefix: 'xpack.security',
- uiExports: {
- hacks: ['plugins/security/hacks/legacy'],
- injectDefaultVars: (server: Server) => {
- return { enableSpaceAwarePrivileges: server.config().get('xpack.spaces.enabled') };
- },
- },
-
- config(Joi: Root) {
- return Joi.object({
- enabled: Joi.boolean().default(true),
- })
+ uiExports: { hacks: ['plugins/security/hacks/legacy'] },
+ config: (Joi: Root) =>
+ Joi.object({ enabled: Joi.boolean().default(true) })
.unknown()
- .default();
- },
-
- async postInit(server: Server) {
- watchStatusAndLicenseToInitialize(server.plugins.xpack_main, this, async () => {
- const xpackInfo = server.plugins.xpack_main.info;
- if (xpackInfo.isAvailable() && xpackInfo.feature('security').isEnabled()) {
- await getSecurityPluginSetup(server).__legacyCompat.registerPrivilegesWithCluster();
- }
- });
- },
-
- async init(server: Server) {
- const securityPlugin = getSecurityPluginSetup(server);
-
- server.expose({
- getUser: async (request: LegacyRequest) =>
- securityPlugin.authc.getCurrentUser(KibanaRequest.from(request)),
- });
- },
+ .default(),
+ init() {},
});
diff --git a/x-pack/plugins/actions/server/builtin_action_types/case/types.ts b/x-pack/plugins/actions/server/builtin_action_types/case/types.ts
index 459e9d2b03f92..992b2cb16fb06 100644
--- a/x-pack/plugins/actions/server/builtin_action_types/case/types.ts
+++ b/x-pack/plugins/actions/server/builtin_action_types/case/types.ts
@@ -21,6 +21,7 @@ import {
ExecutorSubActionGetIncidentParamsSchema,
ExecutorSubActionHandshakeParamsSchema,
} from './schema';
+import { LicenseType } from '../../../../../legacy/common/constants';
export interface AnyParams {
[index: string]: string | number | object | undefined | null;
@@ -51,6 +52,7 @@ export type Comment = TypeOf;
export interface ExternalServiceConfiguration {
id: string;
name: string;
+ minimumLicenseRequired: LicenseType;
}
export interface ExternalServiceCredentials {
diff --git a/x-pack/plugins/actions/server/builtin_action_types/case/utils.ts b/x-pack/plugins/actions/server/builtin_action_types/case/utils.ts
index 315d13b5aa773..dd8d971b7df44 100644
--- a/x-pack/plugins/actions/server/builtin_action_types/case/utils.ts
+++ b/x-pack/plugins/actions/server/builtin_action_types/case/utils.ts
@@ -120,9 +120,7 @@ export const createConnector = ({
configurationUtilities,
executor = createConnectorExecutor({ api, createExternalService }),
}: CreateActionTypeArgs): ActionType => ({
- id: config.id,
- name: config.name,
- minimumLicenseRequired: 'platinum',
+ ...config,
validate: {
config: schema.object(validationSchema.config, {
validate: curry(validate.config)(configurationUtilities),
diff --git a/x-pack/plugins/actions/server/builtin_action_types/jira/config.ts b/x-pack/plugins/actions/server/builtin_action_types/jira/config.ts
index 7e415109f1bd9..54f28e447010a 100644
--- a/x-pack/plugins/actions/server/builtin_action_types/jira/config.ts
+++ b/x-pack/plugins/actions/server/builtin_action_types/jira/config.ts
@@ -10,4 +10,5 @@ import * as i18n from './translations';
export const config: ExternalServiceConfiguration = {
id: '.jira',
name: i18n.NAME,
+ minimumLicenseRequired: 'gold',
};
diff --git a/x-pack/plugins/actions/server/builtin_action_types/servicenow/config.ts b/x-pack/plugins/actions/server/builtin_action_types/servicenow/config.ts
index 4ad8108c3b137..70d53ab79f631 100644
--- a/x-pack/plugins/actions/server/builtin_action_types/servicenow/config.ts
+++ b/x-pack/plugins/actions/server/builtin_action_types/servicenow/config.ts
@@ -10,4 +10,5 @@ import * as i18n from './translations';
export const config: ExternalServiceConfiguration = {
id: '.servicenow',
name: i18n.NAME,
+ minimumLicenseRequired: 'platinum',
};
diff --git a/x-pack/plugins/apm/public/application/index.tsx b/x-pack/plugins/apm/public/application/index.tsx
index cb8600ed2c214..56c427e67ad4c 100644
--- a/x-pack/plugins/apm/public/application/index.tsx
+++ b/x-pack/plugins/apm/public/application/index.tsx
@@ -9,6 +9,7 @@ import React from 'react';
import ReactDOM from 'react-dom';
import { Route, Router, Switch } from 'react-router-dom';
import styled from 'styled-components';
+import { EuiThemeProvider } from '../../../observability/public';
import { CoreStart, AppMountParameters } from '../../../../../src/core/public';
import { ApmPluginSetupDeps } from '../plugin';
import { ApmPluginContext } from '../context/ApmPluginContext';
@@ -18,7 +19,10 @@ import { LocationProvider } from '../context/LocationContext';
import { MatchedRouteProvider } from '../context/MatchedRouteContext';
import { UrlParamsProvider } from '../context/UrlParamsContext';
import { AlertsContextProvider } from '../../../triggers_actions_ui/public';
-import { KibanaContextProvider } from '../../../../../src/plugins/kibana_react/public';
+import {
+ KibanaContextProvider,
+ useUiSetting$,
+} from '../../../../../src/plugins/kibana_react/public';
import { px, unit, units } from '../style/variables';
import { UpdateBreadcrumbs } from '../components/app/Main/UpdateBreadcrumbs';
import { APMIndicesPermission } from '../components/app/APMIndicesPermission';
@@ -35,18 +39,22 @@ const MainContainer = styled.div`
`;
const App = () => {
+ const [darkMode] = useUiSetting$('theme:darkMode');
+
return (
-
-
-
-
-
- {routes.map((route, i) => (
-
- ))}
-
-
-
+
+
+
+
+
+
+ {routes.map((route, i) => (
+
+ ))}
+
+
+
+
);
};
diff --git a/x-pack/plugins/apm/public/components/app/Settings/AgentConfigurations/AgentConfigurationCreateEdit/index.tsx b/x-pack/plugins/apm/public/components/app/Settings/AgentConfigurations/AgentConfigurationCreateEdit/index.tsx
index 5bb678d1c08af..50eb85715969a 100644
--- a/x-pack/plugins/apm/public/components/app/Settings/AgentConfigurations/AgentConfigurationCreateEdit/index.tsx
+++ b/x-pack/plugins/apm/public/components/app/Settings/AgentConfigurations/AgentConfigurationCreateEdit/index.tsx
@@ -79,6 +79,7 @@ export function AgentConfigurationCreateEdit({
..._newConfig,
settings: existingConfig?.settings || {},
}));
+ /* eslint-disable-next-line react-hooks/exhaustive-deps */
}, [existingConfig]);
// update newConfig when existingConfig has loaded
diff --git a/x-pack/plugins/apm/public/components/app/TransactionDetails/Distribution/index.tsx b/x-pack/plugins/apm/public/components/app/TransactionDetails/Distribution/index.tsx
index d39ad530c1b4c..1244dd01a3b43 100644
--- a/x-pack/plugins/apm/public/components/app/TransactionDetails/Distribution/index.tsx
+++ b/x-pack/plugins/apm/public/components/app/TransactionDetails/Distribution/index.tsx
@@ -109,10 +109,12 @@ export const TransactionDistribution: FunctionComponent = (
bucketIndex,
} = props;
+ /* eslint-disable-next-line react-hooks/exhaustive-deps */
const formatYShort = useCallback(getFormatYShort(transactionType), [
transactionType,
]);
+ /* eslint-disable-next-line react-hooks/exhaustive-deps */
const formatYLong = useCallback(getFormatYLong(transactionType), [
transactionType,
]);
diff --git a/x-pack/plugins/apm/public/components/shared/TransactionActionMenu/TransactionActionMenu.tsx b/x-pack/plugins/apm/public/components/shared/TransactionActionMenu/TransactionActionMenu.tsx
index 988edb197a230..2507eca9ff663 100644
--- a/x-pack/plugins/apm/public/components/shared/TransactionActionMenu/TransactionActionMenu.tsx
+++ b/x-pack/plugins/apm/public/components/shared/TransactionActionMenu/TransactionActionMenu.tsx
@@ -66,6 +66,7 @@ export const TransactionActionMenu: FunctionComponent = ({
{ key: 'transaction.name', value: transaction?.transaction.name },
{ key: 'transaction.type', value: transaction?.transaction.type },
].filter((filter): filter is Filter => typeof filter.value === 'string'),
+ /* eslint-disable-next-line react-hooks/exhaustive-deps */
[transaction]
);
diff --git a/x-pack/plugins/apm/public/hooks/useFetcher.test.tsx b/x-pack/plugins/apm/public/hooks/useFetcher.test.tsx
index 28b836cd2c650..2db4659c83603 100644
--- a/x-pack/plugins/apm/public/hooks/useFetcher.test.tsx
+++ b/x-pack/plugins/apm/public/hooks/useFetcher.test.tsx
@@ -106,6 +106,7 @@ describe('useFetcher', () => {
jest.useFakeTimers();
const hook = renderHook(
+ /* eslint-disable-next-line react-hooks/exhaustive-deps */
({ callback, args }) => useFetcher(callback, args),
{
initialProps: {
@@ -165,6 +166,7 @@ describe('useFetcher', () => {
it('should return the same object reference when data is unchanged between rerenders', async () => {
const hook = renderHook(
+ /* eslint-disable-next-line react-hooks/exhaustive-deps */
({ callback, args }) => useFetcher(callback, args),
{
initialProps: {
diff --git a/x-pack/plugins/apm/public/plugin.ts b/x-pack/plugins/apm/public/plugin.ts
index 76320efe617ea..0939c51b16605 100644
--- a/x-pack/plugins/apm/public/plugin.ts
+++ b/x-pack/plugins/apm/public/plugin.ts
@@ -75,7 +75,7 @@ export class ApmPlugin implements Plugin {
core.application.register({
id: 'apm',
title: 'APM',
- order: 8100,
+ order: 8300,
euiIconType: 'apmApp',
appRoute: '/app/apm',
icon: 'plugins/apm/public/icon.svg',
diff --git a/x-pack/plugins/apm/readme.md b/x-pack/plugins/apm/readme.md
index ceed5e6c39716..cb694712d7c97 100644
--- a/x-pack/plugins/apm/readme.md
+++ b/x-pack/plugins/apm/readme.md
@@ -83,13 +83,13 @@ For debugging access Elasticsearch on http://localhost:9220` (elastic/changeme)
**Start server**
```
-node scripts/functional_tests_server --config x-pack/test/api_integration/config.js
+node scripts/functional_tests_server --config x-pack/test/api_integration/config.ts
```
**Run tests**
```
-node scripts/functional_test_runner --config x-pack/test/api_integration/config.js --grep='APM specs'
+node scripts/functional_test_runner --config x-pack/test/api_integration/config.ts --grep='APM specs'
```
APM tests are located in `x-pack/test/api_integration/apis/apm`.
diff --git a/x-pack/plugins/apm/server/lib/helpers/es_client.ts b/x-pack/plugins/apm/server/lib/helpers/es_client.ts
index c7a17197ca778..892f8f0ddd105 100644
--- a/x-pack/plugins/apm/server/lib/helpers/es_client.ts
+++ b/x-pack/plugins/apm/server/lib/helpers/es_client.ts
@@ -19,6 +19,7 @@ import {
ESSearchRequest,
ESSearchResponse,
} from '../../../typings/elasticsearch';
+import { UI_SETTINGS } from '../../../../../../src/plugins/data/server';
import { OBSERVER_VERSION_MAJOR } from '../../../common/elasticsearch_fieldnames';
import { pickKeys } from '../../../common/utils/pick_keys';
import { APMRequestHandlerContext } from '../../routes/typings';
@@ -95,7 +96,7 @@ async function getParamsForSearchRequest(
savedObjectsClient: context.core.savedObjects.client,
config: context.config,
}),
- uiSettings.client.get('search:includeFrozen'),
+ uiSettings.client.get(UI_SETTINGS.SEARCH_INCLUDE_FROZEN),
]);
// Get indices for legacy data filter (only those which apply)
diff --git a/x-pack/plugins/canvas/canvas_plugin_src/elements/metric/index.ts b/x-pack/plugins/canvas/canvas_plugin_src/elements/metric/index.ts
index 7256657903aab..14409ae166a84 100644
--- a/x-pack/plugins/canvas/canvas_plugin_src/elements/metric/index.ts
+++ b/x-pack/plugins/canvas/canvas_plugin_src/elements/metric/index.ts
@@ -7,6 +7,7 @@
import { openSans } from '../../../common/lib/fonts';
import { ElementFactory } from '../../../types';
import { SetupInitializer } from '../../plugin';
+import { UI_SETTINGS } from '../../../../../../src/plugins/data/public';
export const metricElementInitializer: SetupInitializer = (core, setup) => {
return () => ({
@@ -23,7 +24,7 @@ export const metricElementInitializer: SetupInitializer = (core,
| metric "Countries"
metricFont={font size=48 family="${openSans.value}" color="#000000" align="center" lHeight=48}
labelFont={font size=14 family="${openSans.value}" color="#000000" align="center"}
- metricFormat="${core.uiSettings.get('format:number:defaultPattern')}"
+ metricFormat="${core.uiSettings.get(UI_SETTINGS.FORMAT_NUMBER_DEFAULT_PATTERN)}"
| render`,
});
};
diff --git a/x-pack/plugins/canvas/canvas_plugin_src/renderers/embeddable/embeddable.tsx b/x-pack/plugins/canvas/canvas_plugin_src/renderers/embeddable/embeddable.tsx
index 2dd116d5ada08..ad368a912cd8c 100644
--- a/x-pack/plugins/canvas/canvas_plugin_src/renderers/embeddable/embeddable.tsx
+++ b/x-pack/plugins/canvas/canvas_plugin_src/renderers/embeddable/embeddable.tsx
@@ -11,12 +11,10 @@ import { StartDeps } from '../../plugin';
import {
IEmbeddable,
EmbeddableFactory,
- EmbeddablePanel,
EmbeddableFactoryNotFoundError,
} from '../../../../../../src/plugins/embeddable/public';
import { EmbeddableExpression } from '../../expression_types/embeddable';
import { RendererStrings } from '../../../i18n';
-import { getSavedObjectFinder } from '../../../../../../src/plugins/saved_objects/public';
import { embeddableInputToExpression } from './embeddable_input_to_expression';
import { EmbeddableInput } from '../../expression_types';
import { RendererHandlers } from '../../../types';
@@ -38,17 +36,7 @@ const renderEmbeddableFactory = (core: CoreStart, plugins: StartDeps) => {
style={{ width: domNode.offsetWidth, height: domNode.offsetHeight, cursor: 'auto' }}
>
-
+
);
diff --git a/x-pack/plugins/canvas/canvas_plugin_src/renderers/time_filter/index.tsx b/x-pack/plugins/canvas/canvas_plugin_src/renderers/time_filter/index.tsx
index ef5bfb70d4b3d..25278adcf4529 100644
--- a/x-pack/plugins/canvas/canvas_plugin_src/renderers/time_filter/index.tsx
+++ b/x-pack/plugins/canvas/canvas_plugin_src/renderers/time_filter/index.tsx
@@ -7,6 +7,7 @@
import ReactDOM from 'react-dom';
import React from 'react';
import { toExpression } from '@kbn/interpreter/common';
+import { UI_SETTINGS } from '../../../../../../src/plugins/data/public';
import { syncFilterExpression } from '../../../public/lib/sync_filter_expression';
import { RendererStrings } from '../../../i18n';
import { TimeFilter } from './components';
@@ -20,7 +21,7 @@ const { timeFilter: strings } = RendererStrings;
export const timeFilterFactory: StartInitializer> = (core, plugins) => {
const { uiSettings } = core;
- const customQuickRanges = (uiSettings.get('timepicker:quickRanges') || []).map(
+ const customQuickRanges = (uiSettings.get(UI_SETTINGS.TIMEPICKER_QUICK_RANGES) || []).map(
({ from, to, display }: { from: string; to: string; display: string }) => ({
start: from,
end: to,
diff --git a/x-pack/plugins/canvas/canvas_plugin_src/uis/arguments/number_format/index.ts b/x-pack/plugins/canvas/canvas_plugin_src/uis/arguments/number_format/index.ts
index 4025d4deaf997..5a3e3904f4f23 100644
--- a/x-pack/plugins/canvas/canvas_plugin_src/uis/arguments/number_format/index.ts
+++ b/x-pack/plugins/canvas/canvas_plugin_src/uis/arguments/number_format/index.ts
@@ -11,6 +11,7 @@ import { templateFromReactComponent } from '../../../../public/lib/template_from
import { ArgumentFactory } from '../../../../types/arguments';
import { ArgumentStrings } from '../../../../i18n';
import { SetupInitializer } from '../../../plugin';
+import { UI_SETTINGS } from '../../../../../../../src/plugins/data/public';
const { NumberFormat: strings } = ArgumentStrings;
@@ -19,11 +20,11 @@ export const numberFormatInitializer: SetupInitializer {
const formatMap = {
- NUMBER: core.uiSettings.get('format:number:defaultPattern'),
- PERCENT: core.uiSettings.get('format:percent:defaultPattern'),
- CURRENCY: core.uiSettings.get('format:currency:defaultPattern'),
+ NUMBER: core.uiSettings.get(UI_SETTINGS.FORMAT_NUMBER_DEFAULT_PATTERN),
+ PERCENT: core.uiSettings.get(UI_SETTINGS.FORMAT_PERCENT_DEFAULT_PATTERN),
+ CURRENCY: core.uiSettings.get(UI_SETTINGS.FORMAT_CURRENCY_DEFAULT_PATTERN),
DURATION: '00:00:00',
- BYTES: core.uiSettings.get('format:bytes:defaultPattern'),
+ BYTES: core.uiSettings.get(UI_SETTINGS.FORMAT_BYTES_DEFAULT_PATTERN),
};
const numberFormats = [
diff --git a/x-pack/plugins/canvas/canvas_plugin_src/uis/views/metric.ts b/x-pack/plugins/canvas/canvas_plugin_src/uis/views/metric.ts
index 93912b7b0517f..11bee46088576 100644
--- a/x-pack/plugins/canvas/canvas_plugin_src/uis/views/metric.ts
+++ b/x-pack/plugins/canvas/canvas_plugin_src/uis/views/metric.ts
@@ -7,6 +7,7 @@
import { openSans } from '../../../common/lib/fonts';
import { ViewStrings } from '../../../i18n';
import { SetupInitializer } from '../../plugin';
+import { UI_SETTINGS } from '../../../../../../src/plugins/data/public';
const { Metric: strings } = ViewStrings;
@@ -22,7 +23,7 @@ export const metricInitializer: SetupInitializer = (core, plugin) => {
displayName: strings.getMetricFormatDisplayName(),
help: strings.getMetricFormatHelp(),
argType: 'numberFormat',
- default: `"${core.uiSettings.get('format:number:defaultPattern')}"`,
+ default: `"${core.uiSettings.get(UI_SETTINGS.FORMAT_NUMBER_DEFAULT_PATTERN)}"`,
},
{
name: '_',
diff --git a/x-pack/plugins/canvas/public/components/expression_input/__examples__/expression_input.examples.tsx b/x-pack/plugins/canvas/public/components/expression_input/__examples__/expression_input.examples.tsx
index 51caf1db196bc..d010f4a554b87 100644
--- a/x-pack/plugins/canvas/public/components/expression_input/__examples__/expression_input.examples.tsx
+++ b/x-pack/plugins/canvas/public/components/expression_input/__examples__/expression_input.examples.tsx
@@ -7,7 +7,7 @@
import { action } from '@storybook/addon-actions';
import { storiesOf } from '@storybook/react';
import React from 'react';
-import { monaco } from '@kbn/ui-shared-deps/monaco';
+import { monaco } from '@kbn/monaco';
import { ExpressionInput } from '../expression_input';
import { language, LANGUAGE_ID } from '../../../lib/monaco_language_def';
diff --git a/x-pack/plugins/canvas/public/components/expression_input/expression_input.tsx b/x-pack/plugins/canvas/public/components/expression_input/expression_input.tsx
index 99e12b14104be..5ada495208fba 100644
--- a/x-pack/plugins/canvas/public/components/expression_input/expression_input.tsx
+++ b/x-pack/plugins/canvas/public/components/expression_input/expression_input.tsx
@@ -8,7 +8,7 @@ import React from 'react';
import PropTypes from 'prop-types';
import { EuiFormRow } from '@elastic/eui';
import { debounce } from 'lodash';
-import { monaco } from '@kbn/ui-shared-deps/monaco';
+import { monaco } from '@kbn/monaco';
import { ExpressionFunction } from '../../../types';
import { CodeEditor } from '../../../../../../src/plugins/kibana_react/public';
import {
diff --git a/x-pack/plugins/canvas/public/lib/monaco_language_def.ts b/x-pack/plugins/canvas/public/lib/monaco_language_def.ts
index 7bd9ea7b6ef9a..5b88658ddcd63 100644
--- a/x-pack/plugins/canvas/public/lib/monaco_language_def.ts
+++ b/x-pack/plugins/canvas/public/lib/monaco_language_def.ts
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import { monaco } from '@kbn/ui-shared-deps/monaco';
+import { monaco } from '@kbn/monaco';
import { ExpressionFunction } from '../../types';
export const LANGUAGE_ID = 'canvas-expression';
diff --git a/x-pack/plugins/dashboard_enhanced/kibana.json b/x-pack/plugins/dashboard_enhanced/kibana.json
index f416ca97f7110..37211ea537179 100644
--- a/x-pack/plugins/dashboard_enhanced/kibana.json
+++ b/x-pack/plugins/dashboard_enhanced/kibana.json
@@ -3,6 +3,6 @@
"version": "kibana",
"server": false,
"ui": true,
- "requiredPlugins": ["data", "advancedUiActions", "drilldowns", "embeddable", "dashboard", "share"],
+ "requiredPlugins": ["data", "uiActionsEnhanced", "drilldowns", "embeddable", "dashboard", "share"],
"configPath": ["xpack", "dashboardEnhanced"]
}
diff --git a/x-pack/plugins/dashboard_enhanced/public/plugin.ts b/x-pack/plugins/dashboard_enhanced/public/plugin.ts
index c258a4148f84a..413f5a7afe356 100644
--- a/x-pack/plugins/dashboard_enhanced/public/plugin.ts
+++ b/x-pack/plugins/dashboard_enhanced/public/plugin.ts
@@ -9,19 +9,19 @@ import { SharePluginStart, SharePluginSetup } from '../../../../src/plugins/shar
import { EmbeddableSetup, EmbeddableStart } from '../../../../src/plugins/embeddable/public';
import { DashboardDrilldownsService } from './services';
import { DataPublicPluginStart } from '../../../../src/plugins/data/public';
-import { AdvancedUiActionsSetup, AdvancedUiActionsStart } from '../../advanced_ui_actions/public';
+import { AdvancedUiActionsSetup, AdvancedUiActionsStart } from '../../ui_actions_enhanced/public';
import { DrilldownsSetup, DrilldownsStart } from '../../drilldowns/public';
import { DashboardStart } from '../../../../src/plugins/dashboard/public';
export interface SetupDependencies {
- advancedUiActions: AdvancedUiActionsSetup;
+ uiActionsEnhanced: AdvancedUiActionsSetup;
drilldowns: DrilldownsSetup;
embeddable: EmbeddableSetup;
share: SharePluginSetup;
}
export interface StartDependencies {
- advancedUiActions: AdvancedUiActionsStart;
+ uiActionsEnhanced: AdvancedUiActionsStart;
data: DataPublicPluginStart;
drilldowns: DrilldownsStart;
embeddable: EmbeddableStart;
diff --git a/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/actions/flyout_edit_drilldown/flyout_edit_drilldown.test.tsx b/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/actions/flyout_edit_drilldown/flyout_edit_drilldown.test.tsx
index 555acf1fca5ff..309e6cbf53a3d 100644
--- a/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/actions/flyout_edit_drilldown/flyout_edit_drilldown.test.tsx
+++ b/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/actions/flyout_edit_drilldown/flyout_edit_drilldown.test.tsx
@@ -8,7 +8,7 @@ import { FlyoutEditDrilldownAction, FlyoutEditDrilldownParams } from './flyout_e
import { coreMock } from '../../../../../../../../src/core/public/mocks';
import { drilldownsPluginMock } from '../../../../../../drilldowns/public/mocks';
import { ViewMode } from '../../../../../../../../src/plugins/embeddable/public';
-import { uiActionsEnhancedPluginMock } from '../../../../../../advanced_ui_actions/public/mocks';
+import { uiActionsEnhancedPluginMock } from '../../../../../../ui_actions_enhanced/public/mocks';
import { EnhancedEmbeddable } from '../../../../../../embeddable_enhanced/public';
import { MockEmbeddable, enhanceEmbeddable } from '../test_helpers';
diff --git a/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/actions/flyout_edit_drilldown/menu_item.test.tsx b/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/actions/flyout_edit_drilldown/menu_item.test.tsx
index ec3a78e97eae4..9a4ecb2d4bfb0 100644
--- a/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/actions/flyout_edit_drilldown/menu_item.test.tsx
+++ b/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/actions/flyout_edit_drilldown/menu_item.test.tsx
@@ -8,7 +8,7 @@ import React from 'react';
import { render, cleanup, act } from '@testing-library/react/pure';
import { MenuItem } from './menu_item';
import { createStateContainer } from '../../../../../../../../src/plugins/kibana_utils/public';
-import { UiActionsEnhancedDynamicActionManager as DynamicActionManager } from '../../../../../../advanced_ui_actions/public';
+import { UiActionsEnhancedDynamicActionManager as DynamicActionManager } from '../../../../../../ui_actions_enhanced/public';
import { EnhancedEmbeddable } from '../../../../../../embeddable_enhanced/public';
import '@testing-library/jest-dom';
diff --git a/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/actions/test_helpers.ts b/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/actions/test_helpers.ts
index cccacf701a9ad..e831f87baa11c 100644
--- a/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/actions/test_helpers.ts
+++ b/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/actions/test_helpers.ts
@@ -10,9 +10,9 @@ import {
UiActionsEnhancedMemoryActionStorage as MemoryActionStorage,
UiActionsEnhancedDynamicActionManager as DynamicActionManager,
AdvancedUiActionsStart,
-} from '../../../../../advanced_ui_actions/public';
+} from '../../../../../ui_actions_enhanced/public';
import { TriggerContextMapping } from '../../../../../../../src/plugins/ui_actions/public';
-import { uiActionsEnhancedPluginMock } from '../../../../../advanced_ui_actions/public/mocks';
+import { uiActionsEnhancedPluginMock } from '../../../../../ui_actions_enhanced/public/mocks';
export class MockEmbeddable extends Embeddable {
public rootType = 'dashboard';
diff --git a/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/dashboard_drilldowns_services.ts b/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/dashboard_drilldowns_services.ts
index f5926cd6961c2..4325e3309b898 100644
--- a/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/dashboard_drilldowns_services.ts
+++ b/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/dashboard_drilldowns_services.ts
@@ -41,7 +41,7 @@ export class DashboardDrilldownsService {
setupDrilldowns(
core: CoreSetup,
- { advancedUiActions: uiActions }: SetupDependencies
+ { uiActionsEnhanced: uiActions }: SetupDependencies
) {
const start = createStartServicesGetter(core.getStartServices);
const getDashboardUrlGenerator = () => {
diff --git a/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/dashboard_to_dashboard_drilldown/drilldown.test.tsx b/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/dashboard_to_dashboard_drilldown/drilldown.test.tsx
index c94d19d28e6da..6ce7dccd3a3ec 100644
--- a/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/dashboard_to_dashboard_drilldown/drilldown.test.tsx
+++ b/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/dashboard_to_dashboard_drilldown/drilldown.test.tsx
@@ -101,13 +101,13 @@ describe('.execute() & getHref', () => {
},
},
plugins: {
- advancedUiActions: {},
+ uiActionsEnhanced: {},
data: {
actions: dataPluginActions,
},
},
self: {},
- })) as unknown) as StartServicesGetter>,
+ })) as unknown) as StartServicesGetter>,
getDashboardUrlGenerator: () =>
new UrlGeneratorsService().setup(coreMock.createSetup()).registerUrlGenerator(
createDashboardUrlGenerator(() =>
diff --git a/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/dashboard_to_dashboard_drilldown/drilldown.tsx b/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/dashboard_to_dashboard_drilldown/drilldown.tsx
index 7ff84a75dd52c..26a69132cffb1 100644
--- a/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/dashboard_to_dashboard_drilldown/drilldown.tsx
+++ b/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/dashboard_to_dashboard_drilldown/drilldown.tsx
@@ -10,7 +10,7 @@ import { DashboardUrlGenerator } from '../../../../../../../src/plugins/dashboar
import { ActionContext, Config } from './types';
import { CollectConfigContainer } from './components';
import { DASHBOARD_TO_DASHBOARD_DRILLDOWN } from './constants';
-import { UiActionsEnhancedDrilldownDefinition as Drilldown } from '../../../../../advanced_ui_actions/public';
+import { UiActionsEnhancedDrilldownDefinition as Drilldown } from '../../../../../ui_actions_enhanced/public';
import { txtGoToDashboard } from './i18n';
import { esFilters } from '../../../../../../../src/plugins/data/public';
import { VisualizeEmbeddableContract } from '../../../../../../../src/plugins/visualizations/public';
@@ -22,7 +22,7 @@ import { StartServicesGetter } from '../../../../../../../src/plugins/kibana_uti
import { StartDependencies } from '../../../plugin';
export interface Params {
- start: StartServicesGetter>;
+ start: StartServicesGetter>;
getDashboardUrlGenerator: () => DashboardUrlGenerator;
}
diff --git a/x-pack/plugins/data_enhanced/public/search/es_search_strategy.ts b/x-pack/plugins/data_enhanced/public/search/es_search_strategy.ts
index c493e8ce86781..3a511c7b5a176 100644
--- a/x-pack/plugins/data_enhanced/public/search/es_search_strategy.ts
+++ b/x-pack/plugins/data_enhanced/public/search/es_search_strategy.ts
@@ -11,6 +11,7 @@ import {
ISearchContext,
ISearch,
getEsPreference,
+ UI_SETTINGS,
} from '../../../../../src/plugins/data/public';
import { IEnhancedEsSearchRequest, EnhancedSearchParams } from '../../common';
import { ASYNC_SEARCH_STRATEGY } from './async_search_strategy';
@@ -27,7 +28,7 @@ export const enhancedEsSearchStrategyProvider: TSearchStrategyProvider {
const params: EnhancedSearchParams = {
- ignoreThrottled: !context.core.uiSettings.get('search:includeFrozen'),
+ ignoreThrottled: !context.core.uiSettings.get(UI_SETTINGS.SEARCH_INCLUDE_FROZEN),
preference: getEsPreference(context.core.uiSettings),
...request.params,
};
diff --git a/x-pack/plugins/drilldowns/kibana.json b/x-pack/plugins/drilldowns/kibana.json
index 678c054aa322c..1614f94b488fd 100644
--- a/x-pack/plugins/drilldowns/kibana.json
+++ b/x-pack/plugins/drilldowns/kibana.json
@@ -3,6 +3,6 @@
"version": "kibana",
"server": false,
"ui": true,
- "requiredPlugins": ["uiActions", "embeddable", "advancedUiActions"],
+ "requiredPlugins": ["uiActions", "embeddable", "uiActionsEnhanced"],
"configPath": ["xpack", "drilldowns"]
}
diff --git a/x-pack/plugins/drilldowns/public/components/connected_flyout_manage_drilldowns/connected_flyout_manage_drilldowns.story.tsx b/x-pack/plugins/drilldowns/public/components/connected_flyout_manage_drilldowns/connected_flyout_manage_drilldowns.story.tsx
index a186feec33924..5fde4fc79e433 100644
--- a/x-pack/plugins/drilldowns/public/components/connected_flyout_manage_drilldowns/connected_flyout_manage_drilldowns.story.tsx
+++ b/x-pack/plugins/drilldowns/public/components/connected_flyout_manage_drilldowns/connected_flyout_manage_drilldowns.story.tsx
@@ -12,13 +12,13 @@ import {
dashboardFactory,
urlFactory,
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
-} from '../../../../advanced_ui_actions/public/components/action_wizard/test_data';
+} from '../../../../ui_actions_enhanced/public/components/action_wizard/test_data';
import { Storage } from '../../../../../../src/plugins/kibana_utils/public';
import { StubBrowserStorage } from '../../../../../../src/test_utils/public/stub_browser_storage';
import { mockDynamicActionManager } from './test_data';
const FlyoutManageDrilldowns = createFlyoutManageDrilldowns({
- advancedUiActions: {
+ uiActionsEnhanced: {
getActionFactories() {
return [dashboardFactory, urlFactory];
},
diff --git a/x-pack/plugins/drilldowns/public/components/connected_flyout_manage_drilldowns/connected_flyout_manage_drilldowns.test.tsx b/x-pack/plugins/drilldowns/public/components/connected_flyout_manage_drilldowns/connected_flyout_manage_drilldowns.test.tsx
index 0f7f0cb22760b..32cbec795d092 100644
--- a/x-pack/plugins/drilldowns/public/components/connected_flyout_manage_drilldowns/connected_flyout_manage_drilldowns.test.tsx
+++ b/x-pack/plugins/drilldowns/public/components/connected_flyout_manage_drilldowns/connected_flyout_manage_drilldowns.test.tsx
@@ -11,7 +11,7 @@ import { createFlyoutManageDrilldowns } from './connected_flyout_manage_drilldow
import {
dashboardFactory,
urlFactory,
-} from '../../../../advanced_ui_actions/public/components/action_wizard/test_data';
+} from '../../../../ui_actions_enhanced/public/components/action_wizard/test_data';
import { StubBrowserStorage } from '../../../../../../src/test_utils/public/stub_browser_storage';
import { Storage } from '../../../../../../src/plugins/kibana_utils/public';
import { mockDynamicActionManager } from './test_data';
@@ -24,7 +24,7 @@ import { toastDrilldownsCRUDError } from './i18n';
const storage = new Storage(new StubBrowserStorage());
const notifications = coreMock.createStart().notifications;
const FlyoutManageDrilldowns = createFlyoutManageDrilldowns({
- advancedUiActions: {
+ uiActionsEnhanced: {
getActionFactories() {
return [dashboardFactory, urlFactory];
},
diff --git a/x-pack/plugins/drilldowns/public/components/connected_flyout_manage_drilldowns/connected_flyout_manage_drilldowns.tsx b/x-pack/plugins/drilldowns/public/components/connected_flyout_manage_drilldowns/connected_flyout_manage_drilldowns.tsx
index 3c9d2d2a86fb1..45cf7365ebd91 100644
--- a/x-pack/plugins/drilldowns/public/components/connected_flyout_manage_drilldowns/connected_flyout_manage_drilldowns.tsx
+++ b/x-pack/plugins/drilldowns/public/components/connected_flyout_manage_drilldowns/connected_flyout_manage_drilldowns.tsx
@@ -7,12 +7,12 @@
import React, { useEffect, useState } from 'react';
import useMountedState from 'react-use/lib/useMountedState';
import {
- AdvancedUiActionsActionFactory as ActionFactory,
+ UiActionsEnhancedActionFactory as ActionFactory,
AdvancedUiActionsStart,
UiActionsEnhancedDynamicActionManager as DynamicActionManager,
UiActionsEnhancedSerializedAction,
UiActionsEnhancedSerializedEvent,
-} from '../../../../advanced_ui_actions/public';
+} from '../../../../ui_actions_enhanced/public';
import { NotificationsStart } from '../../../../../../src/core/public';
import { DrilldownWizardConfig, FlyoutDrilldownWizard } from '../flyout_drilldown_wizard';
import { FlyoutListManageDrilldowns } from '../flyout_list_manage_drilldowns';
@@ -48,17 +48,17 @@ enum Routes {
}
export function createFlyoutManageDrilldowns({
- advancedUiActions,
+ uiActionsEnhanced,
storage,
notifications,
}: {
- advancedUiActions: AdvancedUiActionsStart;
+ uiActionsEnhanced: AdvancedUiActionsStart;
storage: IStorageWrapper;
notifications: NotificationsStart;
}) {
// fine to assume this is static,
// because all action factories should be registered in setup phase
- const allActionFactories = advancedUiActions.getActionFactories();
+ const allActionFactories = uiActionsEnhanced.getActionFactories();
const allActionFactoriesById = allActionFactories.reduce((acc, next) => {
acc[next.id] = next;
return acc;
diff --git a/x-pack/plugins/drilldowns/public/components/connected_flyout_manage_drilldowns/test_data.ts b/x-pack/plugins/drilldowns/public/components/connected_flyout_manage_drilldowns/test_data.ts
index c9cb0b0eb1cb3..d585fa0692e8c 100644
--- a/x-pack/plugins/drilldowns/public/components/connected_flyout_manage_drilldowns/test_data.ts
+++ b/x-pack/plugins/drilldowns/public/components/connected_flyout_manage_drilldowns/test_data.ts
@@ -9,7 +9,7 @@ import {
UiActionsEnhancedDynamicActionManager as DynamicActionManager,
UiActionsEnhancedDynamicActionManagerState as DynamicActionManagerState,
UiActionsEnhancedSerializedAction,
-} from '../../../../advanced_ui_actions/public';
+} from '../../../../ui_actions_enhanced/public';
import { TriggerContextMapping } from '../../../../../../src/plugins/ui_actions/public';
import { createStateContainer } from '../../../../../../src/plugins/kibana_utils/common';
diff --git a/x-pack/plugins/drilldowns/public/components/flyout_drilldown_wizard/flyout_drilldown_wizard.story.tsx b/x-pack/plugins/drilldowns/public/components/flyout_drilldown_wizard/flyout_drilldown_wizard.story.tsx
index add8b748afee9..be048bf920602 100644
--- a/x-pack/plugins/drilldowns/public/components/flyout_drilldown_wizard/flyout_drilldown_wizard.story.tsx
+++ b/x-pack/plugins/drilldowns/public/components/flyout_drilldown_wizard/flyout_drilldown_wizard.story.tsx
@@ -14,8 +14,8 @@ import {
dashboardFactory,
urlFactory,
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
-} from '../../../../advanced_ui_actions/public/components/action_wizard/test_data';
-import { AdvancedUiActionsActionFactory as ActionFactory } from '../../../../advanced_ui_actions/public/';
+} from '../../../../ui_actions_enhanced/public/components/action_wizard/test_data';
+import { UiActionsEnhancedActionFactory as ActionFactory } from '../../../../ui_actions_enhanced/public/';
storiesOf('components/FlyoutDrilldownWizard', module)
.add('default', () => {
diff --git a/x-pack/plugins/drilldowns/public/components/flyout_drilldown_wizard/flyout_drilldown_wizard.tsx b/x-pack/plugins/drilldowns/public/components/flyout_drilldown_wizard/flyout_drilldown_wizard.tsx
index 84c1a04a71d15..87f886817517f 100644
--- a/x-pack/plugins/drilldowns/public/components/flyout_drilldown_wizard/flyout_drilldown_wizard.tsx
+++ b/x-pack/plugins/drilldowns/public/components/flyout_drilldown_wizard/flyout_drilldown_wizard.tsx
@@ -16,7 +16,7 @@ import {
txtEditDrilldownTitle,
} from './i18n';
import { DrilldownHelloBar } from '../drilldown_hello_bar';
-import { AdvancedUiActionsActionFactory as ActionFactory } from '../../../../advanced_ui_actions/public';
+import { UiActionsEnhancedActionFactory as ActionFactory } from '../../../../ui_actions_enhanced/public';
export interface DrilldownWizardConfig {
name: string;
diff --git a/x-pack/plugins/drilldowns/public/components/form_drilldown_wizard/form_drilldown_wizard.tsx b/x-pack/plugins/drilldowns/public/components/form_drilldown_wizard/form_drilldown_wizard.tsx
index 38168377b02bd..1813851d728db 100644
--- a/x-pack/plugins/drilldowns/public/components/form_drilldown_wizard/form_drilldown_wizard.tsx
+++ b/x-pack/plugins/drilldowns/public/components/form_drilldown_wizard/form_drilldown_wizard.tsx
@@ -8,9 +8,9 @@ import React from 'react';
import { EuiFieldText, EuiForm, EuiFormRow, EuiSpacer } from '@elastic/eui';
import { txtDrilldownAction, txtNameOfDrilldown, txtUntitledDrilldown } from './i18n';
import {
- AdvancedUiActionsActionFactory as ActionFactory,
+ UiActionsEnhancedActionFactory as ActionFactory,
ActionWizard,
-} from '../../../../advanced_ui_actions/public';
+} from '../../../../ui_actions_enhanced/public';
const noopFn = () => {};
diff --git a/x-pack/plugins/drilldowns/public/plugin.ts b/x-pack/plugins/drilldowns/public/plugin.ts
index 0108e04df9c99..32176241c102f 100644
--- a/x-pack/plugins/drilldowns/public/plugin.ts
+++ b/x-pack/plugins/drilldowns/public/plugin.ts
@@ -6,18 +6,18 @@
import { CoreStart, CoreSetup, Plugin } from 'src/core/public';
import { UiActionsSetup, UiActionsStart } from '../../../../src/plugins/ui_actions/public';
-import { AdvancedUiActionsSetup, AdvancedUiActionsStart } from '../../advanced_ui_actions/public';
+import { AdvancedUiActionsSetup, AdvancedUiActionsStart } from '../../ui_actions_enhanced/public';
import { createFlyoutManageDrilldowns } from './components/connected_flyout_manage_drilldowns';
import { Storage } from '../../../../src/plugins/kibana_utils/public';
export interface SetupDependencies {
uiActions: UiActionsSetup;
- advancedUiActions: AdvancedUiActionsSetup;
+ uiActionsEnhanced: AdvancedUiActionsSetup;
}
export interface StartDependencies {
uiActions: UiActionsStart;
- advancedUiActions: AdvancedUiActionsStart;
+ uiActionsEnhanced: AdvancedUiActionsStart;
}
// eslint-disable-next-line
@@ -36,7 +36,7 @@ export class DrilldownsPlugin
public start(core: CoreStart, plugins: StartDependencies): StartContract {
return {
FlyoutManageDrilldowns: createFlyoutManageDrilldowns({
- advancedUiActions: plugins.advancedUiActions,
+ uiActionsEnhanced: plugins.uiActionsEnhanced,
storage: new Storage(localStorage),
notifications: core.notifications,
}),
diff --git a/x-pack/plugins/embeddable_enhanced/kibana.json b/x-pack/plugins/embeddable_enhanced/kibana.json
index 780a1d5d89870..5663671de7bd9 100644
--- a/x-pack/plugins/embeddable_enhanced/kibana.json
+++ b/x-pack/plugins/embeddable_enhanced/kibana.json
@@ -3,5 +3,5 @@
"version": "kibana",
"server": false,
"ui": true,
- "requiredPlugins": ["embeddable", "advancedUiActions"]
+ "requiredPlugins": ["embeddable", "uiActionsEnhanced"]
}
diff --git a/x-pack/plugins/embeddable_enhanced/public/embeddables/embeddable_action_storage.test.ts b/x-pack/plugins/embeddable_enhanced/public/embeddables/embeddable_action_storage.test.ts
index f8b3a9dfb92d0..5c5d98d75295d 100644
--- a/x-pack/plugins/embeddable_enhanced/public/embeddables/embeddable_action_storage.test.ts
+++ b/x-pack/plugins/embeddable_enhanced/public/embeddables/embeddable_action_storage.test.ts
@@ -9,7 +9,7 @@ import {
EmbeddableActionStorage,
EmbeddableWithDynamicActionsInput,
} from './embeddable_action_storage';
-import { UiActionsEnhancedSerializedEvent } from '../../../advanced_ui_actions/public';
+import { UiActionsEnhancedSerializedEvent } from '../../../ui_actions_enhanced/public';
import { of } from '../../../../../src/plugins/kibana_utils/public';
class TestEmbeddable extends Embeddable {
diff --git a/x-pack/plugins/embeddable_enhanced/public/embeddables/embeddable_action_storage.ts b/x-pack/plugins/embeddable_enhanced/public/embeddables/embeddable_action_storage.ts
index e93674ba650a7..fdc42585a80ce 100644
--- a/x-pack/plugins/embeddable_enhanced/public/embeddables/embeddable_action_storage.ts
+++ b/x-pack/plugins/embeddable_enhanced/public/embeddables/embeddable_action_storage.ts
@@ -7,7 +7,7 @@
import {
UiActionsEnhancedAbstractActionStorage as AbstractActionStorage,
UiActionsEnhancedSerializedEvent as SerializedEvent,
-} from '../../../advanced_ui_actions/public';
+} from '../../../ui_actions_enhanced/public';
import {
EmbeddableInput,
EmbeddableOutput,
diff --git a/x-pack/plugins/embeddable_enhanced/public/plugin.ts b/x-pack/plugins/embeddable_enhanced/public/plugin.ts
index d26acb4459a71..e6413ac03aeae 100644
--- a/x-pack/plugins/embeddable_enhanced/public/plugin.ts
+++ b/x-pack/plugins/embeddable_enhanced/public/plugin.ts
@@ -27,7 +27,7 @@ import {
UiActionsEnhancedDynamicActionManager as DynamicActionManager,
AdvancedUiActionsSetup,
AdvancedUiActionsStart,
-} from '../../advanced_ui_actions/public';
+} from '../../ui_actions_enhanced/public';
import { PanelNotificationsAction, ACTION_PANEL_NOTIFICATIONS } from './actions';
declare module '../../../../src/plugins/ui_actions/public' {
@@ -38,12 +38,12 @@ declare module '../../../../src/plugins/ui_actions/public' {
export interface SetupDependencies {
embeddable: EmbeddableSetup;
- advancedUiActions: AdvancedUiActionsSetup;
+ uiActionsEnhanced: AdvancedUiActionsSetup;
}
export interface StartDependencies {
embeddable: EmbeddableStart;
- advancedUiActions: AdvancedUiActionsStart;
+ uiActionsEnhanced: AdvancedUiActionsStart;
}
// eslint-disable-next-line
@@ -56,20 +56,20 @@ export class EmbeddableEnhancedPlugin
implements Plugin {
constructor(protected readonly context: PluginInitializerContext) {}
- private uiActions?: StartDependencies['advancedUiActions'];
+ private uiActions?: StartDependencies['uiActionsEnhanced'];
public setup(core: CoreSetup, plugins: SetupDependencies): SetupContract {
this.setCustomEmbeddableFactoryProvider(plugins);
const panelNotificationAction = new PanelNotificationsAction();
- plugins.advancedUiActions.registerAction(panelNotificationAction);
- plugins.advancedUiActions.attachAction(PANEL_NOTIFICATION_TRIGGER, panelNotificationAction.id);
+ plugins.uiActionsEnhanced.registerAction(panelNotificationAction);
+ plugins.uiActionsEnhanced.attachAction(PANEL_NOTIFICATION_TRIGGER, panelNotificationAction.id);
return {};
}
public start(core: CoreStart, plugins: StartDependencies): StartContract {
- this.uiActions = plugins.advancedUiActions;
+ this.uiActions = plugins.uiActionsEnhanced;
return {};
}
diff --git a/x-pack/plugins/embeddable_enhanced/public/types.ts b/x-pack/plugins/embeddable_enhanced/public/types.ts
index 924605be332b2..4f5c316f2fc17 100644
--- a/x-pack/plugins/embeddable_enhanced/public/types.ts
+++ b/x-pack/plugins/embeddable_enhanced/public/types.ts
@@ -5,7 +5,7 @@
*/
import { IEmbeddable } from '../../../../src/plugins/embeddable/public';
-import { UiActionsEnhancedDynamicActionManager as DynamicActionManager } from '../../advanced_ui_actions/public';
+import { UiActionsEnhancedDynamicActionManager as DynamicActionManager } from '../../ui_actions_enhanced/public';
export type EnhancedEmbeddable = E & {
enhancements: {
diff --git a/x-pack/plugins/event_log/server/es/cluster_client_adapter.test.ts b/x-pack/plugins/event_log/server/es/cluster_client_adapter.test.ts
index 0144e573fc146..ada86adf84cfd 100644
--- a/x-pack/plugins/event_log/server/es/cluster_client_adapter.test.ts
+++ b/x-pack/plugins/event_log/server/es/cluster_client_adapter.test.ts
@@ -51,7 +51,7 @@ describe('doesIlmPolicyExist', () => {
await clusterClientAdapter.doesIlmPolicyExist('foo');
expect(clusterClient.callAsInternalUser).toHaveBeenCalledWith('transport.request', {
method: 'GET',
- path: '_ilm/policy/foo',
+ path: '/_ilm/policy/foo',
});
});
@@ -78,7 +78,7 @@ describe('createIlmPolicy', () => {
await clusterClientAdapter.createIlmPolicy('foo', { args: true });
expect(clusterClient.callAsInternalUser).toHaveBeenCalledWith('transport.request', {
method: 'PUT',
- path: '_ilm/policy/foo',
+ path: '/_ilm/policy/foo',
body: { args: true },
});
});
diff --git a/x-pack/plugins/event_log/server/es/cluster_client_adapter.ts b/x-pack/plugins/event_log/server/es/cluster_client_adapter.ts
index 7fd239ca49369..a036bfb74e408 100644
--- a/x-pack/plugins/event_log/server/es/cluster_client_adapter.ts
+++ b/x-pack/plugins/event_log/server/es/cluster_client_adapter.ts
@@ -41,7 +41,7 @@ export class ClusterClientAdapter {
public async doesIlmPolicyExist(policyName: string): Promise {
const request = {
method: 'GET',
- path: `_ilm/policy/${policyName}`,
+ path: `/_ilm/policy/${policyName}`,
};
try {
await this.callEs('transport.request', request);
@@ -55,7 +55,7 @@ export class ClusterClientAdapter {
public async createIlmPolicy(policyName: string, policy: unknown): Promise {
const request = {
method: 'PUT',
- path: `_ilm/policy/${policyName}`,
+ path: `/_ilm/policy/${policyName}`,
body: policy,
};
try {
diff --git a/x-pack/plugins/global_search/README.md b/x-pack/plugins/global_search/README.md
new file mode 100644
index 0000000000000..d47e0bd696fd8
--- /dev/null
+++ b/x-pack/plugins/global_search/README.md
@@ -0,0 +1,49 @@
+# Kibana GlobalSearch plugin
+
+The GlobalSearch plugin provides an easy way to search for various objects, such as applications
+or dashboards from the Kibana instance, from both server and client-side plugins
+
+## Consuming the globalSearch API
+
+```ts
+startDeps.globalSearch.find('some term').subscribe({
+ next: ({ results }) => {
+ addNewResultsToList(results);
+ },
+ error: () => {},
+ complete: () => {
+ showAsyncSearchIndicator(false);
+ }
+});
+```
+
+## Registering custom result providers
+
+The GlobalSearch API allows to extend provided results by registering your own provider.
+
+```ts
+setupDeps.globalSearch.registerResultProvider({
+ id: 'my_provider',
+ find: (term, options, context) => {
+ const resultPromise = myService.search(term, context.core.savedObjects.client);
+ return from(resultPromise).pipe(takeUntil(options.aborted$);
+ },
+});
+```
+
+## Known limitations
+
+### Client-side registered providers
+
+Results from providers registered from the client-side `registerResultProvider` API will
+not be available when performing a search from the server-side. For this reason, prefer
+registering providers using the server-side API when possible.
+
+Refer to the [RFC](rfcs/text/0011_global_search.md#result_provider_registration) for more details
+
+### Search completion cause
+
+There is currently no way to identify `globalSearch.find` observable completion cause:
+searches completing because all providers returned all their results and searches
+completing because the consumer aborted the search using the `aborted$` option or because
+the internal timout period has been reaches will both complete the same way.
diff --git a/x-pack/plugins/global_search/common/errors.test.ts b/x-pack/plugins/global_search/common/errors.test.ts
new file mode 100644
index 0000000000000..949795abd701a
--- /dev/null
+++ b/x-pack/plugins/global_search/common/errors.test.ts
@@ -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 { GlobalSearchFindError } from './errors';
+
+describe('GlobalSearchFindError', () => {
+ describe('#invalidLicense', () => {
+ it('create an error with the correct `type`', () => {
+ const error = GlobalSearchFindError.invalidLicense('foobar');
+ expect(error.message).toBe('foobar');
+ expect(error.type).toBe('invalid-license');
+ });
+
+ it('can be identified via instanceof', () => {
+ const error = GlobalSearchFindError.invalidLicense('foo');
+ expect(error instanceof GlobalSearchFindError).toBe(true);
+ });
+ });
+});
diff --git a/x-pack/plugins/global_search/common/errors.ts b/x-pack/plugins/global_search/common/errors.ts
new file mode 100644
index 0000000000000..15bc0958cb8aa
--- /dev/null
+++ b/x-pack/plugins/global_search/common/errors.ts
@@ -0,0 +1,27 @@
+/*
+ * 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.
+ */
+
+// only one type for now, but already present for future-proof reasons
+export type GlobalSearchFindErrorType = 'invalid-license';
+
+/**
+ * Error thrown from the {@link GlobalSearchPluginStart.find | GlobalSearch find API}'s result observable
+ *
+ * @public
+ */
+export class GlobalSearchFindError extends Error {
+ public static invalidLicense(message: string) {
+ return new GlobalSearchFindError('invalid-license', message);
+ }
+
+ private constructor(public readonly type: GlobalSearchFindErrorType, message: string) {
+ super(message);
+
+ // Set the prototype explicitly, see:
+ // https://github.com/Microsoft/TypeScript/wiki/Breaking-Changes#extending-built-ins-like-error-array-and-map-may-no-longer-work
+ Object.setPrototypeOf(this, GlobalSearchFindError.prototype);
+ }
+}
diff --git a/x-pack/plugins/global_search/common/license_checker.mock.ts b/x-pack/plugins/global_search/common/license_checker.mock.ts
new file mode 100644
index 0000000000000..e19a2562e53d8
--- /dev/null
+++ b/x-pack/plugins/global_search/common/license_checker.mock.ts
@@ -0,0 +1,24 @@
+/*
+ * 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 { ILicenseChecker } from './license_checker';
+
+const createLicenseCheckerMock = (): jest.Mocked => {
+ const mock = {
+ getState: jest.fn(),
+ getLicense: jest.fn(),
+ clean: jest.fn(),
+ };
+
+ mock.getLicense.mockReturnValue(undefined);
+ mock.getState.mockReturnValue({ valid: true });
+
+ return mock;
+};
+
+export const licenseCheckerMock = {
+ create: createLicenseCheckerMock,
+};
diff --git a/x-pack/plugins/global_search/common/license_checker.test.ts b/x-pack/plugins/global_search/common/license_checker.test.ts
new file mode 100644
index 0000000000000..47a0d41016d71
--- /dev/null
+++ b/x-pack/plugins/global_search/common/license_checker.test.ts
@@ -0,0 +1,63 @@
+/*
+ * 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 { Observable, of, BehaviorSubject } from 'rxjs';
+import { licenseMock } from '../../licensing/common/licensing.mock';
+import { ILicense, LicenseCheck } from '../../licensing/common/types';
+import { LicenseChecker } from './license_checker';
+
+describe('LicenseChecker', () => {
+ const createLicense = (check: LicenseCheck): ILicense => {
+ const license = licenseMock.createLicenseMock();
+ license.check.mockReturnValue(check);
+ return license;
+ };
+
+ const createLicense$ = (check: LicenseCheck): Observable => of(createLicense(check));
+
+ it('returns the correct state of the license', () => {
+ let checker = new LicenseChecker(createLicense$({ state: 'valid' }));
+ expect(checker.getState()).toEqual({ valid: true });
+
+ checker = new LicenseChecker(createLicense$({ state: 'expired' }));
+ expect(checker.getState()).toEqual({ valid: false, message: 'expired' });
+
+ checker = new LicenseChecker(createLicense$({ state: 'invalid' }));
+ expect(checker.getState()).toEqual({ valid: false, message: 'invalid' });
+
+ checker = new LicenseChecker(createLicense$({ state: 'unavailable' }));
+ expect(checker.getState()).toEqual({ valid: false, message: 'unavailable' });
+ });
+
+ it('updates the state when the license changes', () => {
+ const license$ = new BehaviorSubject(createLicense({ state: 'valid' }));
+
+ const checker = new LicenseChecker(license$);
+ expect(checker.getState()).toEqual({ valid: true });
+
+ license$.next(createLicense({ state: 'expired' }));
+ expect(checker.getState()).toEqual({ valid: false, message: 'expired' });
+
+ license$.next(createLicense({ state: 'valid' }));
+ expect(checker.getState()).toEqual({ valid: true });
+ });
+
+ it('removes the subscription when calling `clean`', () => {
+ const mockUnsubscribe = jest.fn();
+ const mockObs = {
+ subscribe: jest.fn().mockReturnValue({ unsubscribe: mockUnsubscribe }),
+ };
+
+ const checker = new LicenseChecker(mockObs as any);
+
+ expect(mockObs.subscribe).toHaveBeenCalledTimes(1);
+ expect(mockUnsubscribe).not.toHaveBeenCalled();
+
+ checker.clean();
+
+ expect(mockUnsubscribe).toHaveBeenCalledTimes(1);
+ });
+});
diff --git a/x-pack/plugins/global_search/common/license_checker.ts b/x-pack/plugins/global_search/common/license_checker.ts
new file mode 100644
index 0000000000000..d201b31802b32
--- /dev/null
+++ b/x-pack/plugins/global_search/common/license_checker.ts
@@ -0,0 +1,49 @@
+/*
+ * 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 { Observable, Subscription } from 'rxjs';
+import { ILicense } from '../../licensing/common/types';
+
+export type LicenseState = { valid: false; message: string } | { valid: true };
+
+export type CheckLicense = (license: ILicense) => LicenseState;
+
+const checkLicense: CheckLicense = (license) => {
+ const check = license.check('globalSearch', 'basic');
+ switch (check.state) {
+ case 'expired':
+ return { valid: false, message: 'expired' };
+ case 'invalid':
+ return { valid: false, message: 'invalid' };
+ case 'unavailable':
+ return { valid: false, message: 'unavailable' };
+ case 'valid':
+ return { valid: true };
+ default:
+ throw new Error(`Invalid license state: ${check.state}`);
+ }
+};
+
+export type ILicenseChecker = PublicMethodsOf;
+
+export class LicenseChecker {
+ private subscription: Subscription;
+ private state: LicenseState = { valid: false, message: 'unknown' };
+
+ constructor(license$: Observable) {
+ this.subscription = license$.subscribe((license) => {
+ this.state = checkLicense(license);
+ });
+ }
+
+ public getState() {
+ return this.state;
+ }
+
+ public clean() {
+ this.subscription.unsubscribe();
+ }
+}
diff --git a/x-pack/plugins/index_management/public/application/store/middlewares/index.ts b/x-pack/plugins/global_search/common/operators/index.ts
similarity index 77%
rename from x-pack/plugins/index_management/public/application/store/middlewares/index.ts
rename to x-pack/plugins/global_search/common/operators/index.ts
index 06d77a9c3d348..2a0cf066a04aa 100644
--- a/x-pack/plugins/index_management/public/application/store/middlewares/index.ts
+++ b/x-pack/plugins/global_search/common/operators/index.ts
@@ -4,4 +4,4 @@
* you may not use this file except in compliance with the Elastic License.
*/
-export { syncUrlHashQueryParam } from './sync_url_hash_query_param.js';
+export { takeInArray } from './take_in_array';
diff --git a/x-pack/plugins/global_search/common/operators/take_in_array.test.ts b/x-pack/plugins/global_search/common/operators/take_in_array.test.ts
new file mode 100644
index 0000000000000..b73ee20c9889a
--- /dev/null
+++ b/x-pack/plugins/global_search/common/operators/take_in_array.test.ts
@@ -0,0 +1,62 @@
+/*
+ * 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 { TestScheduler } from 'rxjs/testing';
+import { takeInArray } from './take_in_array';
+
+const getTestScheduler = () =>
+ new TestScheduler((actual, expected) => {
+ expect(actual).toEqual(expected);
+ });
+
+describe('takeInArray', () => {
+ it('only emits a given `count` of items from an array observable', () => {
+ getTestScheduler().run(({ expectObservable, hot }) => {
+ const source = hot('a-b-c', { a: [1], b: [2], c: [3] });
+ const expected = 'a-(b|)';
+
+ expectObservable(source.pipe(takeInArray(2))).toBe(expected, {
+ a: [1],
+ b: [2],
+ });
+ });
+ });
+
+ it('completes if the source completes before reaching the given `count`', () => {
+ getTestScheduler().run(({ expectObservable, hot }) => {
+ const source = hot('a-b-c-|', { a: [1, 2], b: [3, 4], c: [5] });
+ const expected = 'a-b-c-|';
+
+ expectObservable(source.pipe(takeInArray(10))).toBe(expected, {
+ a: [1, 2],
+ b: [3, 4],
+ c: [5],
+ });
+ });
+ });
+
+ it('split the emission if `count` is reached in a given emission', () => {
+ getTestScheduler().run(({ expectObservable, hot }) => {
+ const source = hot('a-b-c', { a: [1, 2, 3], b: [4, 5, 6], c: [7, 8] });
+ const expected = 'a-(b|)';
+
+ expectObservable(source.pipe(takeInArray(5))).toBe(expected, {
+ a: [1, 2, 3],
+ b: [4, 5],
+ });
+ });
+ });
+
+ it('throws when trying to take a negative number of items', () => {
+ getTestScheduler().run(({ expectObservable, hot }) => {
+ const source = hot('a-b-c', { a: [1, 2, 3], b: [4, 5, 6], c: [7, 8] });
+
+ expect(() => {
+ source.pipe(takeInArray(-4)).subscribe(() => undefined);
+ }).toThrowErrorMatchingInlineSnapshot(`"Cannot take a negative number of items"`);
+ });
+ });
+});
diff --git a/x-pack/plugins/global_search/common/operators/take_in_array.ts b/x-pack/plugins/global_search/common/operators/take_in_array.ts
new file mode 100644
index 0000000000000..7d041d3c2bab0
--- /dev/null
+++ b/x-pack/plugins/global_search/common/operators/take_in_array.ts
@@ -0,0 +1,74 @@
+/*
+ * 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.
+ */
+
+// eslint-disable-next-line max-classes-per-file
+import {
+ EMPTY,
+ MonoTypeOperatorFunction,
+ Observable,
+ Operator,
+ Subscriber,
+ TeardownLogic,
+} from 'rxjs';
+
+/**
+ * Emits only the first `count` items from the arrays emitted by the source Observable. The limit
+ * is global to all emitted values, and not per emission.
+ *
+ * @example
+ * ```ts
+ * const source = of([1, 2], [3, 4], [5, 6]);
+ * const takeThreeInArray = source.pipe(takeInArray(3));
+ * takeThreeInArray.subscribe(x => console.log(x));
+ *
+ * // Logs:
+ * // [1,2]
+ * // [3]
+ * ```
+ *
+ * @param count The total maximum number of value to keep from the emitted arrays
+ */
+export function takeInArray(count: number): MonoTypeOperatorFunction {
+ return function takeLastOperatorFunction(source: Observable): Observable {
+ if (count === 0) {
+ return EMPTY;
+ } else {
+ return source.lift(new TakeInArray(count));
+ }
+ };
+}
+
+class TakeInArray implements Operator {
+ constructor(private total: number) {
+ if (this.total < 0) {
+ throw new Error('Cannot take a negative number of items');
+ }
+ }
+
+ call(subscriber: Subscriber, source: any): TeardownLogic {
+ return source.subscribe(new TakeInArraySubscriber(subscriber, this.total));
+ }
+}
+
+class TakeInArraySubscriber extends Subscriber {
+ private current: number = 0;
+
+ constructor(destination: Subscriber, private total: number) {
+ super(destination);
+ }
+
+ protected _next(value: T[]): void {
+ const remaining = this.total - this.current;
+ if (remaining > value.length) {
+ this.destination.next!(value);
+ this.current += value.length;
+ } else {
+ this.destination.next!(value.slice(0, remaining));
+ this.destination.complete!();
+ this.unsubscribe();
+ }
+ }
+}
diff --git a/x-pack/plugins/global_search/common/process_result.test.mocks.ts b/x-pack/plugins/global_search/common/process_result.test.mocks.ts
new file mode 100644
index 0000000000000..718ac7a1a6a52
--- /dev/null
+++ b/x-pack/plugins/global_search/common/process_result.test.mocks.ts
@@ -0,0 +1,10 @@
+/*
+ * 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.
+ */
+
+export const convertResultUrlMock = jest.fn().mockReturnValue('converted-url');
+jest.doMock('./utils', () => ({
+ convertResultUrl: convertResultUrlMock,
+}));
diff --git a/x-pack/plugins/global_search/common/process_result.test.ts b/x-pack/plugins/global_search/common/process_result.test.ts
new file mode 100644
index 0000000000000..723f21a24f552
--- /dev/null
+++ b/x-pack/plugins/global_search/common/process_result.test.ts
@@ -0,0 +1,73 @@
+/*
+ * 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 { convertResultUrlMock } from './process_result.test.mocks';
+
+import { IBasePath } from './utils';
+import { GlobalSearchProviderResult } from './types';
+import { processProviderResult } from './process_result';
+
+const createResult = (parts: Partial): GlobalSearchProviderResult => ({
+ id: 'id',
+ title: 'title',
+ type: 'type',
+ icon: 'icon',
+ url: '/foo/bar',
+ score: 42,
+ meta: { foo: 'bar' },
+ ...parts,
+});
+
+describe('processProviderResult', () => {
+ let basePath: jest.Mocked;
+
+ beforeEach(() => {
+ basePath = {
+ prepend: jest.fn(),
+ };
+
+ convertResultUrlMock.mockClear();
+ });
+
+ it('returns all properties unchanged except `url`', () => {
+ const r1 = createResult({
+ id: '1',
+ type: 'test',
+ url: '/url-1',
+ title: 'title 1',
+ icon: 'foo',
+ score: 69,
+ meta: { hello: 'dolly' },
+ });
+
+ expect(processProviderResult(r1, basePath)).toEqual({
+ ...r1,
+ url: expect.any(String),
+ });
+ });
+
+ it('converts the url using `convertResultUrl`', () => {
+ const r1 = createResult({ id: '1', url: '/url-1' });
+ const r2 = createResult({ id: '2', url: '/url-2' });
+
+ convertResultUrlMock.mockReturnValueOnce('/url-A');
+ convertResultUrlMock.mockReturnValueOnce('/url-B');
+
+ expect(convertResultUrlMock).not.toHaveBeenCalled();
+
+ const g1 = processProviderResult(r1, basePath);
+
+ expect(g1.url).toEqual('/url-A');
+ expect(convertResultUrlMock).toHaveBeenCalledTimes(1);
+ expect(convertResultUrlMock).toHaveBeenCalledWith(r1.url, basePath);
+
+ const g2 = processProviderResult(r2, basePath);
+
+ expect(g2.url).toEqual('/url-B');
+ expect(convertResultUrlMock).toHaveBeenCalledTimes(2);
+ expect(convertResultUrlMock).toHaveBeenCalledWith(r2.url, basePath);
+ });
+});
diff --git a/x-pack/plugins/global_search/common/process_result.ts b/x-pack/plugins/global_search/common/process_result.ts
new file mode 100644
index 0000000000000..fed6dc14f066b
--- /dev/null
+++ b/x-pack/plugins/global_search/common/process_result.ts
@@ -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 { GlobalSearchProviderResult, GlobalSearchResult } from './types';
+import { convertResultUrl, IBasePath } from './utils';
+
+/**
+ * Convert a {@link GlobalSearchProviderResult | provider result}
+ * to a {@link GlobalSearchResult | service result}
+ */
+export const processProviderResult = (
+ result: GlobalSearchProviderResult,
+ basePath: IBasePath
+): GlobalSearchResult => {
+ return {
+ ...result,
+ url: convertResultUrl(result.url, basePath),
+ };
+};
diff --git a/x-pack/plugins/global_search/common/types.ts b/x-pack/plugins/global_search/common/types.ts
new file mode 100644
index 0000000000000..26940806a4ecd
--- /dev/null
+++ b/x-pack/plugins/global_search/common/types.ts
@@ -0,0 +1,89 @@
+/*
+ * 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 { Observable } from 'rxjs';
+import { Serializable } from 'src/core/types';
+
+/**
+ * Options provided to {@link GlobalSearchResultProvider | a result provider}'s `find` method.
+ */
+export interface GlobalSearchProviderFindOptions {
+ /**
+ * A custom preference token associated with a search 'session' that should be used to get consistent scoring
+ * when performing calls to ES. Can also be used as a 'session' token for providers returning data from elsewhere
+ * than an elasticsearch cluster.
+ */
+ preference: string;
+ /**
+ * Observable that emits once if and when the `find` call has been aborted, either manually by the consumer,
+ * or when the internal timeout period as been reached.
+ *
+ * When a `find` request is effectively aborted, the service will stop emitting any new result to the consumer anyway, but
+ * this can (and should) be used to cancel any pending asynchronous task and complete the result observable from within the provider.
+ */
+ aborted$: Observable;
+ /**
+ * The total maximum number of results (including all batches, not per emission) that should be returned by the provider for a given `find` request.
+ * Any result emitted exceeding this quota will be ignored by the service and not emitted to the consumer.
+ */
+ maxResults: number;
+}
+
+/**
+ * Structured type for the {@link GlobalSearchProviderResult.url | provider result's url property}
+ */
+export type GlobalSearchProviderResultUrl = string | { path: string; prependBasePath: boolean };
+
+/**
+ * Representation of a result returned by a {@link GlobalSearchResultProvider | result provider}
+ */
+export interface GlobalSearchProviderResult {
+ /** an id that should be unique for an individual provider's results */
+ id: string;
+ /** the title/label of the result */
+ title: string;
+ /** the type of result */
+ type: string;
+ /** an optional EUI icon name to associate with the search result */
+ icon?: string;
+ /**
+ * The url associated with this result.
+ * This can be either an absolute url, a path relative to the basePath, or a structure specifying if the basePath should be prepended.
+ *
+ * @example
+ * `result.url = 'https://kibana-instance:8080/base-path/app/my-app/my-result-type/id';`
+ * `result.url = '/app/my-app/my-result-type/id';`
+ * `result.url = { path: '/base-path/app/my-app/my-result-type/id', prependBasePath: false };`
+ */
+ url: GlobalSearchProviderResultUrl;
+ /** the score of the result, from 1 (lowest) to 100 (highest) */
+ score: number;
+ /** an optional record of metadata for this result */
+ meta?: Record