): void;
-}
-
// @public
export interface IRouter {
delete: (route: RouteConfig
, handler: RequestHandler
) => void;
@@ -839,7 +809,7 @@ export interface LegacyRequest extends Request {
// @public @deprecated (undocumented)
export interface LegacyServiceSetupDeps {
- // Warning: (ae-incompatible-release-tags) The symbol "core" is marked as @public, but its signature references "InternalCoreSetup" which is marked as @internal
+ // Warning: (ae-forgotten-export) The symbol "InternalCoreSetup" needs to be exported by the entry point index.d.ts
//
// (undocumented)
core: InternalCoreSetup & {
@@ -851,7 +821,7 @@ export interface LegacyServiceSetupDeps {
// @public @deprecated (undocumented)
export interface LegacyServiceStartDeps {
- // Warning: (ae-incompatible-release-tags) The symbol "core" is marked as @public, but its signature references "InternalCoreStart" which is marked as @internal
+ // Warning: (ae-forgotten-export) The symbol "InternalCoreStart" needs to be exported by the entry point index.d.ts
//
// (undocumented)
core: InternalCoreStart & {
@@ -1492,6 +1462,8 @@ export interface SavedObjectsLegacyService {
// (undocumented)
schema: SavedObjectsSchema;
// (undocumented)
+ setScopedSavedObjectsClientFactory: SavedObjectsClientProvider['setClientFactory'];
+ // (undocumented)
types: string[];
}
diff --git a/src/core/server/server.test.ts b/src/core/server/server.test.ts
index aee6461580654..f912a31901ad8 100644
--- a/src/core/server/server.test.ts
+++ b/src/core/server/server.test.ts
@@ -70,7 +70,10 @@ test('injects legacy dependency to context#setup()', async () => {
const pluginA = Symbol();
const pluginB = Symbol();
- const pluginDependencies = new Map([[pluginA, []], [pluginB, [pluginA]]]);
+ const pluginDependencies = new Map([
+ [pluginA, []],
+ [pluginB, [pluginA]],
+ ]);
mockPluginsService.discover.mockResolvedValue(pluginDependencies);
await server.setup();
diff --git a/src/core/server/server.ts b/src/core/server/server.ts
index 46974e204c7a4..6c38de03f0f2d 100644
--- a/src/core/server/server.ts
+++ b/src/core/server/server.ts
@@ -39,7 +39,8 @@ import { config as uiSettingsConfig } from './ui_settings';
import { mapToObject } from '../utils/';
import { ContextService } from './context';
import { SavedObjectsServiceSetup } from './saved_objects/saved_objects_service';
-import { RequestHandlerContext, InternalCoreSetup } from '.';
+import { RequestHandlerContext } from '.';
+import { InternalCoreSetup } from './internal_types';
const coreId = Symbol('core');
diff --git a/src/core/server/ui_settings/ui_settings_client.ts b/src/core/server/ui_settings/ui_settings_client.ts
index 423ff2a1dfd90..1a0f29f6ae6d9 100644
--- a/src/core/server/ui_settings/ui_settings_client.ts
+++ b/src/core/server/ui_settings/ui_settings_client.ts
@@ -83,14 +83,11 @@ export class UiSettingsClient implements IUiSettingsClient {
async getAll() {
const raw = await this.getRaw();
- return Object.keys(raw).reduce(
- (all, key) => {
- const item = raw[key];
- all[key] = ('userValue' in item ? item.userValue : item.value) as T;
- return all;
- },
- {} as Record
- );
+ return Object.keys(raw).reduce((all, key) => {
+ const item = raw[key];
+ all[key] = ('userValue' in item ? item.userValue : item.value) as T;
+ return all;
+ }, {} as Record);
}
async getUserProvided(): Promise> {
diff --git a/src/core/utils/context.ts b/src/core/utils/context.ts
index 022c3e4330032..775c890675410 100644
--- a/src/core/utils/context.ts
+++ b/src/core/utils/context.ts
@@ -254,23 +254,20 @@ export class ContextContainer>
return [...this.contextProviders]
.sort(sortByCoreFirst(this.coreId))
.filter(([contextName]) => contextsToBuild.has(contextName))
- .reduce(
- async (contextPromise, [contextName, { provider, source: providerSource }]) => {
- const resolvedContext = await contextPromise;
+ .reduce(async (contextPromise, [contextName, { provider, source: providerSource }]) => {
+ const resolvedContext = await contextPromise;
- // For the next provider, only expose the context available based on the dependencies of the plugin that
- // registered that provider.
- const exposedContext = pick(resolvedContext, [
- ...this.getContextNamesForSource(providerSource),
- ]) as Partial>;
+ // For the next provider, only expose the context available based on the dependencies of the plugin that
+ // registered that provider.
+ const exposedContext = pick(resolvedContext, [
+ ...this.getContextNamesForSource(providerSource),
+ ]) as Partial>;
- return {
- ...resolvedContext,
- [contextName]: await provider(exposedContext, ...contextArgs),
- };
- },
- Promise.resolve({}) as Promise>
- );
+ return {
+ ...resolvedContext,
+ [contextName]: await provider(exposedContext, ...contextArgs),
+ };
+ }, Promise.resolve({}) as Promise>);
}
private getContextNamesForSource(
diff --git a/src/core/utils/map_utils.test.ts b/src/core/utils/map_utils.test.ts
index 0d9b2a6129de0..315ae3328c47f 100644
--- a/src/core/utils/map_utils.test.ts
+++ b/src/core/utils/map_utils.test.ts
@@ -42,7 +42,11 @@ describe('groupIntoMap', () => {
const groupBy = (item: { id: number }) => item.id;
expect(groupIntoMap([{ id: 1 }, { id: 2 }, { id: 3 }], groupBy)).toEqual(
- new Map([[1, [{ id: 1 }]], [2, [{ id: 2 }]], [3, [{ id: 3 }]]])
+ new Map([
+ [1, [{ id: 1 }]],
+ [2, [{ id: 2 }]],
+ [3, [{ id: 3 }]],
+ ])
);
});
@@ -93,7 +97,12 @@ describe('mapValuesOfMap', () => {
map.set(even, 2);
map.set(odd, 1);
- expect(mapValuesOfMap(map, mapper)).toEqual(new Map([[even, 6], [odd, 3]]));
+ expect(mapValuesOfMap(map, mapper)).toEqual(
+ new Map([
+ [even, 6],
+ [odd, 3],
+ ])
+ );
expect(map.get(odd)).toEqual(1);
expect(map.get(even)).toEqual(2);
});
diff --git a/src/core/utils/merge.ts b/src/core/utils/merge.ts
index aead3f35ba841..8e5d9f4860d95 100644
--- a/src/core/utils/merge.ts
+++ b/src/core/utils/merge.ts
@@ -66,20 +66,17 @@ const mergeObjects = , U extends Record
- [...new Set([...Object.keys(baseObj), ...Object.keys(overrideObj)])].reduce(
- (merged, key) => {
- const baseVal = baseObj[key];
- const overrideVal = overrideObj[key];
+ [...new Set([...Object.keys(baseObj), ...Object.keys(overrideObj)])].reduce((merged, key) => {
+ const baseVal = baseObj[key];
+ const overrideVal = overrideObj[key];
- if (isMergable(baseVal) && isMergable(overrideVal)) {
- merged[key] = mergeObjects(baseVal, overrideVal);
- } else if (overrideVal !== undefined) {
- merged[key] = overrideVal;
- } else if (baseVal !== undefined) {
- merged[key] = baseVal;
- }
+ if (isMergable(baseVal) && isMergable(overrideVal)) {
+ merged[key] = mergeObjects(baseVal, overrideVal);
+ } else if (overrideVal !== undefined) {
+ merged[key] = overrideVal;
+ } else if (baseVal !== undefined) {
+ merged[key] = baseVal;
+ }
- return merged;
- },
- {} as any
- );
+ return merged;
+ }, {} as any);
diff --git a/src/core/utils/pick.ts b/src/core/utils/pick.ts
index 77854f9af680b..08288343d9077 100644
--- a/src/core/utils/pick.ts
+++ b/src/core/utils/pick.ts
@@ -18,14 +18,11 @@
*/
export function pick(obj: T, keys: K[]): Pick {
- return keys.reduce(
- (acc, key) => {
- if (obj.hasOwnProperty(key)) {
- acc[key] = obj[key];
- }
+ return keys.reduce((acc, key) => {
+ if (obj.hasOwnProperty(key)) {
+ acc[key] = obj[key];
+ }
- return acc;
- },
- {} as Pick
- );
+ return acc;
+ }, {} as Pick);
}
diff --git a/src/dev/build/tasks/os_packages/docker_generator/resources/bin/kibana-docker b/src/dev/build/tasks/os_packages/docker_generator/resources/bin/kibana-docker
index 0926ef365c894..6609b905b81ec 100755
--- a/src/dev/build/tasks/os_packages/docker_generator/resources/bin/kibana-docker
+++ b/src/dev/build/tasks/os_packages/docker_generator/resources/bin/kibana-docker
@@ -181,6 +181,7 @@ kibana_vars=(
xpack.security.secureCookies
xpack.security.sessionTimeout
telemetry.enabled
+ telemetry.sendUsageFrom
)
longopts=''
diff --git a/src/dev/license_checker/valid.ts b/src/dev/license_checker/valid.ts
index 8fe09db0a5874..9142955185a1a 100644
--- a/src/dev/license_checker/valid.ts
+++ b/src/dev/license_checker/valid.ts
@@ -36,24 +36,21 @@ interface Options {
* violations or returns undefined.
*/
export function assertLicensesValid({ packages, validLicenses }: Options) {
- const invalidMsgs = packages.reduce(
- (acc, pkg) => {
- const invalidLicenses = pkg.licenses.filter(license => !validLicenses.includes(license));
+ const invalidMsgs = packages.reduce((acc, pkg) => {
+ const invalidLicenses = pkg.licenses.filter(license => !validLicenses.includes(license));
- if (pkg.licenses.length && !invalidLicenses.length) {
- return acc;
- }
+ if (pkg.licenses.length && !invalidLicenses.length) {
+ return acc;
+ }
- return acc.concat(dedent`
+ return acc.concat(dedent`
${pkg.name}
version: ${pkg.version}
all licenses: ${pkg.licenses}
invalid licenses: ${invalidLicenses.join(', ')}
path: ${pkg.relative}
`);
- },
- [] as string[]
- );
+ }, [] as string[]);
if (invalidMsgs.length) {
throw createFailError(
diff --git a/src/es_archiver/lib/docs/__tests__/index_doc_records_stream.js b/src/es_archiver/lib/docs/__tests__/index_doc_records_stream.js
index e48af1f60509b..4a5d048637fcc 100644
--- a/src/es_archiver/lib/docs/__tests__/index_doc_records_stream.js
+++ b/src/es_archiver/lib/docs/__tests__/index_doc_records_stream.js
@@ -35,11 +35,11 @@ import {
const recordsToBulkBody = records => {
return records.reduce((acc, record) => {
- const { index, type, id, source } = record.value;
+ const { index, id, source } = record.value;
return [
...acc,
- { index: { _index: index, _type: type, _id: id } },
+ { index: { _index: index, _id: id } },
source
];
}, []);
diff --git a/src/es_archiver/lib/docs/index_doc_records_stream.js b/src/es_archiver/lib/docs/index_doc_records_stream.js
index 943b1e6e2f329..3e88f10387f9e 100644
--- a/src/es_archiver/lib/docs/index_doc_records_stream.js
+++ b/src/es_archiver/lib/docs/index_doc_records_stream.js
@@ -30,7 +30,6 @@ export function createIndexDocRecordsStream(client, stats, progress) {
{
index: {
_index: doc.index,
- _type: doc.type,
_id: doc.id,
}
},
diff --git a/src/es_archiver/lib/indices/__tests__/create_index_stream.js b/src/es_archiver/lib/indices/__tests__/create_index_stream.js
index 830512f3476ed..4ce12ab3376a3 100644
--- a/src/es_archiver/lib/indices/__tests__/create_index_stream.js
+++ b/src/es_archiver/lib/indices/__tests__/create_index_stream.js
@@ -113,7 +113,6 @@ describe('esArchiver: createCreateIndexStream()', () => {
sinon.assert.calledWith(client.indices.create, {
method: 'PUT',
index: 'index',
- include_type_name: false,
body: {
settings: undefined,
mappings: undefined,
diff --git a/src/es_archiver/lib/indices/create_index_stream.js b/src/es_archiver/lib/indices/create_index_stream.js
index 746f0d689ce56..0daccbee91bd0 100644
--- a/src/es_archiver/lib/indices/create_index_stream.js
+++ b/src/es_archiver/lib/indices/create_index_stream.js
@@ -41,9 +41,6 @@ export function createCreateIndexStream({ client, stats, skipExisting, log }) {
async function handleIndex(record) {
const { index, settings, mappings, aliases } = record.value;
-
- // Determine if the mapping belongs to a pre-7.0 instance, for BWC tests, mainly
- const isPre7Mapping = !!mappings && Object.keys(mappings).length > 0 && !mappings.properties;
const isKibana = index.startsWith('.kibana');
async function attemptToCreate(attemptNumber = 1) {
@@ -55,7 +52,6 @@ export function createCreateIndexStream({ client, stats, skipExisting, log }) {
await client.indices.create({
method: 'PUT',
index,
- include_type_name: isPre7Mapping,
body: {
settings,
mappings,
diff --git a/src/es_archiver/lib/indices/kibana_index.js b/src/es_archiver/lib/indices/kibana_index.js
index dc916e11d698c..6f491783829a8 100644
--- a/src/es_archiver/lib/indices/kibana_index.js
+++ b/src/es_archiver/lib/indices/kibana_index.js
@@ -176,7 +176,6 @@ export async function cleanKibanaIndices({ client, stats, log, kibanaPluginIds }
export async function createDefaultSpace({ index, client }) {
await client.create({
index,
- type: '_doc',
id: 'space:default',
ignore: 409,
body: {
diff --git a/src/fixtures/fake_row.js b/src/fixtures/fake_row.js
index 5bc752de299b2..747c6e06be427 100644
--- a/src/fixtures/fake_row.js
+++ b/src/fixtures/fake_row.js
@@ -31,7 +31,6 @@ export function getFakeRow(id, mapping) {
_id: id,
_index: 'test',
_source: getFakeRowVals('original', id, mapping),
- _type: 'doc',
sort: [id],
};
}
diff --git a/src/fixtures/hits.js b/src/fixtures/hits.js
index 413501a3599ed..e8da3e8ee285b 100644
--- a/src/fixtures/hits.js
+++ b/src/fixtures/hits.js
@@ -37,7 +37,6 @@ export default function fitsFixture() {
return {
_score: 1,
_id: 1000 + i,
- _type: 'test',
_index: 'test-index',
_source: {
'@timestamp': row[0],
diff --git a/src/fixtures/logstash_fields.js b/src/fixtures/logstash_fields.js
index 0ae6c62def0f7..ab96b69851b71 100644
--- a/src/fixtures/logstash_fields.js
+++ b/src/fixtures/logstash_fields.js
@@ -19,7 +19,7 @@
import { castEsToKbnFieldTypeName } from '../plugins/data/common';
// eslint-disable-next-line max-len
-import { shouldReadFieldFromDocValues } from '../legacy/server/index_patterns/service/lib/field_capabilities/should_read_field_from_doc_values';
+import { shouldReadFieldFromDocValues } from '../plugins/data/server';
function stubbedLogstashFields() {
return [
diff --git a/src/legacy/core_plugins/console/np_ready/public/application/constants/help_example.txt b/src/legacy/core_plugins/console/np_ready/public/application/constants/help_example.txt
index 9bc22ecd2d630..fd37c41367033 100644
--- a/src/legacy/core_plugins/console/np_ready/public/application/constants/help_example.txt
+++ b/src/legacy/core_plugins/console/np_ready/public/application/constants/help_example.txt
@@ -1,8 +1,8 @@
# index a doc
-PUT index/type/1
+PUT index/1
{
"body": "here"
}
# and get it ...
-GET index/type/1
+GET index/1
diff --git a/src/legacy/core_plugins/console/public/quarantined/tests/src/input_tokenization.test.js b/src/legacy/core_plugins/console/public/quarantined/tests/src/input_tokenization.test.js
index cfb0f1b8c24db..01f30f826ab26 100644
--- a/src/legacy/core_plugins/console/public/quarantined/tests/src/input_tokenization.test.js
+++ b/src/legacy/core_plugins/console/public/quarantined/tests/src/input_tokenization.test.js
@@ -251,10 +251,10 @@ describe('Input Tokenization', () => {
'paren.lparen', '{', 'paren.rparen', '}', 'paren.rparen', '}'
],
'POST _search\n' +
- '{\n' +
- ' "q": {}\n' +
- ' \n' +
- '}'
+ '{\n' +
+ ' "q": {}\n' +
+ ' \n' +
+ '}'
);
tokenTest(
@@ -263,10 +263,10 @@ describe('Input Tokenization', () => {
'paren.rparen', '}', 'paren.rparen', '}'
],
'POST _search\n' +
- '{\n' +
- ' "q": { "s": {}}\n' +
- ' \n' +
- '}'
+ '{\n' +
+ ' "q": { "s": {}}\n' +
+ ' \n' +
+ '}'
);
function statesAsList() {
@@ -305,44 +305,44 @@ describe('Input Tokenization', () => {
statesTest(
['start', 'json', 'json', 'start'],
'POST _search\n' +
- '{\n' +
- ' "query": { "match_all": {} }\n' +
- '}'
+ '{\n' +
+ ' "query": { "match_all": {} }\n' +
+ '}'
);
statesTest(
['start', 'json', ['json', 'json'], ['json', 'json'], 'json', 'start'],
'POST _search\n' +
- '{\n' +
- ' "query": { \n' +
- ' "match_all": {} \n' +
- ' }\n' +
- '}'
+ '{\n' +
+ ' "query": { \n' +
+ ' "match_all": {} \n' +
+ ' }\n' +
+ '}'
);
statesTest(
['start', 'json', 'json', 'start'],
'POST _search\n' +
- '{\n' +
- ' "script": { "source": "" }\n' +
- '}'
+ '{\n' +
+ ' "script": { "source": "" }\n' +
+ '}'
);
statesTest(
['start', 'json', 'json', 'start'],
'POST _search\n' +
- '{\n' +
- ' "script": ""\n' +
- '}'
+ '{\n' +
+ ' "script": ""\n' +
+ '}'
);
statesTest(
['start', 'json', ['json', 'json'], 'json', 'start'],
'POST _search\n' +
- '{\n' +
- ' "script": {\n' +
- ' }\n' +
- '}'
+ '{\n' +
+ ' "script": {\n' +
+ ' }\n' +
+ '}'
);
@@ -350,41 +350,41 @@ describe('Input Tokenization', () => {
['start', 'json', ['script-start', 'json', 'json', 'json'], ['script-start', 'json', 'json', 'json'],
['json', 'json'], 'json', 'start'],
'POST _search\n' +
- '{\n' +
- ' "test": { "script": """\n' +
- ' test script\n' +
- ' """\n' +
- ' }\n' +
- '}'
+ '{\n' +
+ ' "test": { "script": """\n' +
+ ' test script\n' +
+ ' """\n' +
+ ' }\n' +
+ '}'
);
statesTest(
['start', 'json', ['script-start', 'json'], ['script-start', 'json'], 'json', 'start'],
'POST _search\n' +
- '{\n' +
- ' "script": """\n' +
- ' test script\n' +
- ' """,\n' +
- '}'
+ '{\n' +
+ ' "script": """\n' +
+ ' test script\n' +
+ ' """,\n' +
+ '}'
);
statesTest(
['start', 'json', 'json', 'start'],
'POST _search\n' +
- '{\n' +
- ' "script": """test script""",\n' +
- '}'
+ '{\n' +
+ ' "script": """test script""",\n' +
+ '}'
);
statesTest(
['start', 'json', ['string_literal', 'json'], ['string_literal', 'json'], 'json', 'start'],
'POST _search\n' +
- '{\n' +
- ' "something": """\n' +
- ' test script\n' +
- ' """,\n' +
- '}'
+ '{\n' +
+ ' "something": """\n' +
+ ' test script\n' +
+ ' """,\n' +
+ '}'
);
statesTest(
@@ -392,21 +392,21 @@ describe('Input Tokenization', () => {
['json', 'json'], ['json', 'json'],
'json', 'start'],
'POST _search\n' +
- '{\n' +
- ' "something": { "f" : """\n' +
- ' test script\n' +
- ' """,\n' +
- ' "g": 1\n' +
- ' }\n' +
- '}'
+ '{\n' +
+ ' "something": { "f" : """\n' +
+ ' test script\n' +
+ ' """,\n' +
+ ' "g": 1\n' +
+ ' }\n' +
+ '}'
);
statesTest(
['start', 'json', 'json', 'start'],
'POST _search\n' +
- '{\n' +
- ' "something": """test script""",\n' +
- '}'
+ '{\n' +
+ ' "something": """test script""",\n' +
+ '}'
);
});
diff --git a/src/legacy/core_plugins/console/server/__tests__/proxy_route/params.js b/src/legacy/core_plugins/console/server/__tests__/proxy_route/params.js
index 7c6e221d9ce81..aa7b764f84fc7 100644
--- a/src/legacy/core_plugins/console/server/__tests__/proxy_route/params.js
+++ b/src/legacy/core_plugins/console/server/__tests__/proxy_route/params.js
@@ -61,7 +61,7 @@ describe('Console Proxy Route', () => {
const { statusCode } = await server.inject({
method: 'POST',
- url: '/api/console/proxy?method=GET&path=/baz/type/id',
+ url: '/api/console/proxy?method=GET&path=/baz/id',
});
expect(statusCode).to.be(403);
@@ -79,7 +79,7 @@ describe('Console Proxy Route', () => {
const { statusCode } = await server.inject({
method: 'POST',
- url: '/api/console/proxy?method=GET&path=/foo/type/id',
+ url: '/api/console/proxy?method=GET&path=/foo/id',
});
expect(statusCode).to.be(200);
@@ -98,7 +98,7 @@ describe('Console Proxy Route', () => {
const { statusCode } = await server.inject({
method: 'POST',
- url: '/api/console/proxy?method=GET&path=/foo/type/id',
+ url: '/api/console/proxy?method=GET&path=/foo/id',
});
expect(statusCode).to.be(200);
@@ -116,7 +116,7 @@ describe('Console Proxy Route', () => {
server.route(createProxyRoute({ baseUrl: 'http://localhost:9200', getConfigForReq }));
await server.inject({
method: 'POST',
- url: '/api/console/proxy?method=HEAD&path=/index/type/id',
+ url: '/api/console/proxy?method=HEAD&path=/index/id',
});
sinon.assert.calledOnce(getConfigForReq);
@@ -125,8 +125,8 @@ describe('Console Proxy Route', () => {
expect(args[0]).to.have.property('method', 'post');
expect(args[0])
.to.have.property('query')
- .eql({ method: 'HEAD', path: '/index/type/id' });
- expect(args[1]).to.be('http://localhost:9200/index/type/id?pretty=true');
+ .eql({ method: 'HEAD', path: '/index/id' });
+ expect(args[1]).to.be('http://localhost:9200/index/id?pretty=true');
});
it('sends the returned timeout, agent, and base headers to request', async () => {
@@ -154,7 +154,7 @@ describe('Console Proxy Route', () => {
await server.inject({
method: 'POST',
- url: '/api/console/proxy?method=HEAD&path=/index/type/id',
+ url: '/api/console/proxy?method=HEAD&path=/index/id',
});
sinon.assert.calledOnce(requestModule.sendRequest);
diff --git a/src/legacy/core_plugins/console/server/__tests__/proxy_route/query_string.js b/src/legacy/core_plugins/console/server/__tests__/proxy_route/query_string.js
index 7cabe89177164..f20adb897be65 100644
--- a/src/legacy/core_plugins/console/server/__tests__/proxy_route/query_string.js
+++ b/src/legacy/core_plugins/console/server/__tests__/proxy_route/query_string.js
@@ -85,19 +85,19 @@ describe('Console Proxy Route', () => {
});
describe('starts with a slash', () => {
it('combines well with the base url', async () => {
- await request('GET', '/index/type/id');
+ await request('GET', '/index/id');
sinon.assert.calledOnce(requestModule.sendRequest);
expect(requestModule.sendRequest.getCall(0).args[0].uri.href).to.be(
- 'http://localhost:9200/index/type/id?pretty=true'
+ 'http://localhost:9200/index/id?pretty=true'
);
});
});
describe(`doesn't start with a slash`, () => {
it('combines well with the base url', async () => {
- await request('GET', 'index/type/id');
+ await request('GET', 'index/id');
sinon.assert.calledOnce(requestModule.sendRequest);
expect(requestModule.sendRequest.getCall(0).args[0].uri.href).to.be(
- 'http://localhost:9200/index/type/id?pretty=true'
+ 'http://localhost:9200/index/id?pretty=true'
);
});
});
diff --git a/src/legacy/core_plugins/console/server/__tests__/wildcard_matcher.js b/src/legacy/core_plugins/console/server/__tests__/wildcard_matcher.js
index 4eb0de4e5ebec..9999c98701ffc 100644
--- a/src/legacy/core_plugins/console/server/__tests__/wildcard_matcher.js
+++ b/src/legacy/core_plugins/console/server/__tests__/wildcard_matcher.js
@@ -40,7 +40,7 @@ describe('WildcardMatcher', function () {
it('matches nothing', () => should('', '*'));
it('does not match /', () => shouldNot('/', '*'));
it('matches localhost', () => should('localhost', '*'));
- it('matches a path', () => should('/index/type/_search', '*'));
+ it('matches a path', () => should('/index/_search', '*'));
describe('defaultValue = /', function () {
it('matches /', () => should('/', '*', '/'));
@@ -52,7 +52,7 @@ describe('WildcardMatcher', function () {
it('does not match https', () => shouldNot('https', 'http'));
it('does not match nothing', () => shouldNot('', 'http'));
it('does not match localhost', () => shouldNot('localhost', 'http'));
- it('does not match a path', () => shouldNot('/index/type/_search', 'http'));
+ it('does not match a path', () => shouldNot('/index/_search', 'http'));
});
describe('pattern = 560{1..9}', function () {
diff --git a/src/legacy/core_plugins/console/server/api_server/spec/generated/count.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/count.json
index a657440f1fe4a..bd69fd0c77ec8 100644
--- a/src/legacy/core_plugins/console/server/api_server/spec/generated/count.json
+++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/count.json
@@ -30,8 +30,7 @@
],
"patterns": [
"_count",
- "{indices}/_count",
- "{indices}/{type}/_count"
+ "{indices}/_count"
],
"documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/search-count.html"
}
diff --git a/src/legacy/core_plugins/console/server/api_server/spec/generated/delete_by_query.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/delete_by_query.json
index 12735f2d4b693..3867efd814238 100644
--- a/src/legacy/core_plugins/console/server/api_server/spec/generated/delete_by_query.json
+++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/delete_by_query.json
@@ -1,6 +1,7 @@
{
"delete_by_query": {
"url_params": {
+ "analyzer": "",
"analyze_wildcard": "__flag__",
"default_operator": [
"AND",
@@ -30,7 +31,6 @@
"dfs_query_then_fetch"
],
"search_timeout": "",
- "size": "",
"max_docs": "all documents",
"sort": [],
"_source": [],
@@ -52,8 +52,7 @@
"POST"
],
"patterns": [
- "{indices}/_delete_by_query",
- "{indices}/{type}/_delete_by_query"
+ "{indices}/_delete_by_query"
],
"documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/docs-delete-by-query.html"
}
diff --git a/src/legacy/core_plugins/console/server/api_server/spec/generated/exists.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/exists.json
index 4b7b18b9fe1b3..a6799b9e361cd 100644
--- a/src/legacy/core_plugins/console/server/api_server/spec/generated/exists.json
+++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/exists.json
@@ -21,8 +21,7 @@
"HEAD"
],
"patterns": [
- "{indices}/_doc/{id}",
- "{indices}/{type}/{id}"
+ "{indices}/_doc/{id}"
],
"documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/docs-get.html"
}
diff --git a/src/legacy/core_plugins/console/server/api_server/spec/generated/explain.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/explain.json
index be01e462878db..e4654a99a76ea 100644
--- a/src/legacy/core_plugins/console/server/api_server/spec/generated/explain.json
+++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/explain.json
@@ -22,8 +22,7 @@
"POST"
],
"patterns": [
- "{indices}/_explain/{id}",
- "{indices}/{type}/{id}/_explain"
+ "{indices}/_explain/{id}"
],
"documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/search-explain.html"
}
diff --git a/src/legacy/core_plugins/console/server/api_server/spec/generated/get.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/get.json
index a0b70545baff9..5a72761c7c32e 100644
--- a/src/legacy/core_plugins/console/server/api_server/spec/generated/get.json
+++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/get.json
@@ -21,8 +21,7 @@
"GET"
],
"patterns": [
- "{indices}/_doc/{id}",
- "{indices}/{type}/{id}"
+ "{indices}/_doc/{id}"
],
"documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/docs-get.html"
}
diff --git a/src/legacy/core_plugins/console/server/api_server/spec/generated/get_script_context.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/get_script_context.json
new file mode 100644
index 0000000000000..528c261df7707
--- /dev/null
+++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/get_script_context.json
@@ -0,0 +1,10 @@
+{
+ "get_script_context": {
+ "methods": [
+ "GET"
+ ],
+ "patterns": [
+ "_script_context"
+ ]
+ }
+}
diff --git a/src/legacy/core_plugins/console/server/api_server/spec/generated/get_source.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/get_source.json
index 420e03a1bdcf1..8201960363a78 100644
--- a/src/legacy/core_plugins/console/server/api_server/spec/generated/get_source.json
+++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/get_source.json
@@ -20,8 +20,7 @@
"GET"
],
"patterns": [
- "{indices}/_source/{id}",
- "{indices}/{type}/{id}/_source"
+ "{indices}/_source/{id}"
],
"documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/docs-get.html"
}
diff --git a/src/legacy/core_plugins/console/server/api_server/spec/generated/index.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/index.json
index 7b5551727d645..25977806776a7 100644
--- a/src/legacy/core_plugins/console/server/api_server/spec/generated/index.json
+++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/index.json
@@ -29,9 +29,7 @@
],
"patterns": [
"{indices}/_doc/{id}",
- "{indices}/_doc",
- "{indices}/{type}",
- "{indices}/{type}/{id}"
+ "{indices}/_doc"
],
"documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/docs-index_.html"
}
diff --git a/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.create.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.create.json
index 1970f88b30958..8227e38d3c6d9 100644
--- a/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.create.json
+++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.create.json
@@ -1,7 +1,6 @@
{
"indices.create": {
"url_params": {
- "include_type_name": "__flag__",
"wait_for_active_shards": "",
"timeout": "",
"master_timeout": ""
diff --git a/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.get.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.get.json
index f515e73b250a7..7ca9e88274aa5 100644
--- a/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.get.json
+++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.get.json
@@ -1,7 +1,6 @@
{
"indices.get": {
"url_params": {
- "include_type_name": "__flag__",
"local": "__flag__",
"ignore_unavailable": "__flag__",
"allow_no_indices": "__flag__",
diff --git a/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.get_field_mapping.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.get_field_mapping.json
index ae82696434ced..ea952435566ed 100644
--- a/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.get_field_mapping.json
+++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.get_field_mapping.json
@@ -1,7 +1,6 @@
{
"indices.get_field_mapping": {
"url_params": {
- "include_type_name": "__flag__",
"include_defaults": "__flag__",
"ignore_unavailable": "__flag__",
"allow_no_indices": "__flag__",
@@ -18,9 +17,7 @@
],
"patterns": [
"_mapping/field/{fields}",
- "{indices}/_mapping/field/{fields}",
- "_mapping/{type}/field/{fields}",
- "{indices}/_mapping/{type}/field/{fields}"
+ "{indices}/_mapping/field/{fields}"
],
"documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/indices-get-field-mapping.html"
}
diff --git a/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.get_mapping.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.get_mapping.json
index 03f5de56ea351..73f4e42262bf2 100644
--- a/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.get_mapping.json
+++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.get_mapping.json
@@ -1,7 +1,6 @@
{
"indices.get_mapping": {
"url_params": {
- "include_type_name": "__flag__",
"ignore_unavailable": "__flag__",
"allow_no_indices": "__flag__",
"expand_wildcards": [
@@ -18,9 +17,7 @@
],
"patterns": [
"_mapping",
- "{indices}/_mapping",
- "_mapping/{type}",
- "{indices}/_mapping/{type}"
+ "{indices}/_mapping"
],
"documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/indices-get-mapping.html"
}
diff --git a/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.get_template.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.get_template.json
index d5f52ec76b374..f5902929c25cc 100644
--- a/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.get_template.json
+++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.get_template.json
@@ -1,7 +1,6 @@
{
"indices.get_template": {
"url_params": {
- "include_type_name": "__flag__",
"flat_settings": "__flag__",
"master_timeout": "",
"local": "__flag__"
diff --git a/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.put_mapping.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.put_mapping.json
index 3b833117be499..07a62a64b64e1 100644
--- a/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.put_mapping.json
+++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.put_mapping.json
@@ -1,7 +1,6 @@
{
"indices.put_mapping": {
"url_params": {
- "include_type_name": "__flag__",
"timeout": "",
"master_timeout": "",
"ignore_unavailable": "__flag__",
@@ -18,14 +17,7 @@
"POST"
],
"patterns": [
- "{indices}/_mapping",
- "{indices}/{type}/_mapping",
- "{indices}/_mapping/{type}",
- "{indices}/{type}/_mappings",
- "{indices}/_mappings/{type}",
- "_mappings/{type}",
- "{indices}/_mappings",
- "_mapping/{type}"
+ "{indices}/_mapping"
],
"documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/indices-put-mapping.html"
}
diff --git a/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.put_template.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.put_template.json
index 8b3480f24d8fb..54a7625a2713c 100644
--- a/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.put_template.json
+++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.put_template.json
@@ -1,7 +1,6 @@
{
"indices.put_template": {
"url_params": {
- "include_type_name": "__flag__",
"order": "",
"create": "__flag__",
"timeout": "",
diff --git a/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.rollover.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.rollover.json
index 7fa76a687eb77..19e0f1f909ab8 100644
--- a/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.rollover.json
+++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.rollover.json
@@ -1,7 +1,6 @@
{
"indices.rollover": {
"url_params": {
- "include_type_name": "__flag__",
"timeout": "",
"dry_run": "__flag__",
"master_timeout": "",
diff --git a/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.shrink.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.shrink.json
index 6fbdea0f1244b..31acc86a2fa56 100644
--- a/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.shrink.json
+++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.shrink.json
@@ -1,7 +1,6 @@
{
"indices.shrink": {
"url_params": {
- "copy_settings": "__flag__",
"timeout": "",
"master_timeout": "",
"wait_for_active_shards": ""
diff --git a/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.split.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.split.json
index 68f2e338cd201..1bfbaa078b796 100644
--- a/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.split.json
+++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.split.json
@@ -1,7 +1,6 @@
{
"indices.split": {
"url_params": {
- "copy_settings": "__flag__",
"timeout": "",
"master_timeout": "",
"wait_for_active_shards": ""
diff --git a/src/legacy/core_plugins/console/server/api_server/spec/generated/mget.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/mget.json
index f84b46a379cf4..612bef571fe3f 100644
--- a/src/legacy/core_plugins/console/server/api_server/spec/generated/mget.json
+++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/mget.json
@@ -16,8 +16,7 @@
],
"patterns": [
"_mget",
- "{indices}/_mget",
- "{indices}/{type}/_mget"
+ "{indices}/_mget"
],
"documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/docs-multi-get.html"
}
diff --git a/src/legacy/core_plugins/console/server/api_server/spec/generated/msearch.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/msearch.json
index 502d3e25686df..ecb71e9ba23c0 100644
--- a/src/legacy/core_plugins/console/server/api_server/spec/generated/msearch.json
+++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/msearch.json
@@ -20,8 +20,7 @@
],
"patterns": [
"_msearch",
- "{indices}/_msearch",
- "{indices}/{type}/_msearch"
+ "{indices}/_msearch"
],
"documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/search-multi-search.html"
}
diff --git a/src/legacy/core_plugins/console/server/api_server/spec/generated/msearch_template.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/msearch_template.json
index 02077dd91439b..0b0ca087b1819 100644
--- a/src/legacy/core_plugins/console/server/api_server/spec/generated/msearch_template.json
+++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/msearch_template.json
@@ -9,7 +9,8 @@
],
"typed_keys": "__flag__",
"max_concurrent_searches": "",
- "rest_total_hits_as_int": "__flag__"
+ "rest_total_hits_as_int": "__flag__",
+ "ccs_minimize_roundtrips": "__flag__"
},
"methods": [
"GET",
@@ -17,8 +18,7 @@
],
"patterns": [
"_msearch/template",
- "{indices}/_msearch/template",
- "{indices}/{type}/_msearch/template"
+ "{indices}/_msearch/template"
],
"documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/search-multi-search.html"
}
diff --git a/src/legacy/core_plugins/console/server/api_server/spec/generated/mtermvectors.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/mtermvectors.json
index f5c8cbe76bbc4..72a134eca4d2e 100644
--- a/src/legacy/core_plugins/console/server/api_server/spec/generated/mtermvectors.json
+++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/mtermvectors.json
@@ -25,8 +25,7 @@
],
"patterns": [
"_mtermvectors",
- "{indices}/_mtermvectors",
- "{indices}/{type}/_mtermvectors"
+ "{indices}/_mtermvectors"
],
"documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/docs-multi-termvectors.html"
}
diff --git a/src/legacy/core_plugins/console/server/api_server/spec/generated/search.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/search.json
index 24bda08dd5dbf..eb21b43644d77 100644
--- a/src/legacy/core_plugins/console/server/api_server/spec/generated/search.json
+++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/search.json
@@ -65,8 +65,7 @@
],
"patterns": [
"_search",
- "{indices}/_search",
- "{indices}/{type}/_search"
+ "{indices}/_search"
],
"documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/search-search.html"
}
diff --git a/src/legacy/core_plugins/console/server/api_server/spec/generated/search_template.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/search_template.json
index 6b73e939843a4..582ecab1dd614 100644
--- a/src/legacy/core_plugins/console/server/api_server/spec/generated/search_template.json
+++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/search_template.json
@@ -22,7 +22,8 @@
"explain": "__flag__",
"profile": "__flag__",
"typed_keys": "__flag__",
- "rest_total_hits_as_int": "__flag__"
+ "rest_total_hits_as_int": "__flag__",
+ "ccs_minimize_roundtrips": "__flag__"
},
"methods": [
"GET",
@@ -30,8 +31,7 @@
],
"patterns": [
"_search/template",
- "{indices}/_search/template",
- "{indices}/{type}/_search/template"
+ "{indices}/_search/template"
],
"documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/search-template.html"
}
diff --git a/src/legacy/core_plugins/console/server/api_server/spec/generated/termvectors.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/termvectors.json
index 80373d903aad8..d94cffc38b7af 100644
--- a/src/legacy/core_plugins/console/server/api_server/spec/generated/termvectors.json
+++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/termvectors.json
@@ -24,9 +24,7 @@
],
"patterns": [
"{indices}/_termvectors/{id}",
- "{indices}/_termvectors",
- "{indices}/{type}/{id}/_termvectors",
- "{indices}/{type}/_termvectors"
+ "{indices}/_termvectors"
],
"documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/docs-termvectors.html"
}
diff --git a/src/legacy/core_plugins/console/server/api_server/spec/generated/update_by_query.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/update_by_query.json
index e5857f219af46..739ea16888146 100644
--- a/src/legacy/core_plugins/console/server/api_server/spec/generated/update_by_query.json
+++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/update_by_query.json
@@ -32,7 +32,6 @@
"dfs_query_then_fetch"
],
"search_timeout": "",
- "size": "",
"max_docs": "all documents",
"sort": [],
"_source": [],
@@ -55,8 +54,7 @@
"POST"
],
"patterns": [
- "{indices}/_update_by_query",
- "{indices}/{type}/_update_by_query"
+ "{indices}/_update_by_query"
],
"documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/docs-update-by-query.html"
}
diff --git a/src/legacy/core_plugins/data/public/filter/action/apply_filter_action.ts b/src/legacy/core_plugins/data/public/filter/action/apply_filter_action.ts
index 5db3d779d12fa..abe9ec6d6e873 100644
--- a/src/legacy/core_plugins/data/public/filter/action/apply_filter_action.ts
+++ b/src/legacy/core_plugins/data/public/filter/action/apply_filter_action.ts
@@ -18,21 +18,25 @@
*/
import { i18n } from '@kbn/i18n';
-import { Filter } from '@kbn/es-query';
import { CoreStart } from 'src/core/public';
import {
IAction,
createAction,
IncompatibleActionError,
} from '../../../../../../plugins/ui_actions/public';
-import { FilterManager } from '../../../../../../plugins/data/public';
-import { TimefilterContract, changeTimeFilter, extractTimeFilter } from '../../timefilter';
+import {
+ esFilters,
+ FilterManager,
+ TimefilterContract,
+ changeTimeFilter,
+ extractTimeFilter,
+} from '../../../../../../plugins/data/public';
import { applyFiltersPopover } from '../apply_filters/apply_filters_popover';
import { IndexPatternsStart } from '../../index_patterns';
export const GLOBAL_APPLY_FILTER_ACTION = 'GLOBAL_APPLY_FILTER_ACTION';
interface ActionContext {
- filters: Filter[];
+ filters: esFilters.Filter[];
timeFieldName?: string;
}
@@ -64,7 +68,7 @@ export function createFilterAction(
throw new IncompatibleActionError();
}
- let selectedFilters: Filter[] = filters;
+ let selectedFilters: esFilters.Filter[] = filters;
if (selectedFilters.length > 1) {
const indexPatterns = await Promise.all(
@@ -73,7 +77,7 @@ export function createFilterAction(
})
);
- const filterSelectionPromise: Promise = new Promise(resolve => {
+ const filterSelectionPromise: Promise = new Promise(resolve => {
const overlay = overlays.openModal(
applyFiltersPopover(
filters,
@@ -82,7 +86,7 @@ export function createFilterAction(
overlay.close();
resolve([]);
},
- (filterSelection: Filter[]) => {
+ (filterSelection: esFilters.Filter[]) => {
overlay.close();
resolve(filterSelection);
}
diff --git a/src/legacy/core_plugins/data/public/filter/apply_filters/apply_filter_popover_content.tsx b/src/legacy/core_plugins/data/public/filter/apply_filters/apply_filter_popover_content.tsx
index 8fc6b33f3f68a..e9d05d6340e58 100644
--- a/src/legacy/core_plugins/data/public/filter/apply_filters/apply_filter_popover_content.tsx
+++ b/src/legacy/core_plugins/data/public/filter/apply_filters/apply_filter_popover_content.tsx
@@ -28,19 +28,18 @@ import {
EuiModalHeaderTitle,
EuiSwitch,
} from '@elastic/eui';
-import { Filter } from '@kbn/es-query';
import { FormattedMessage } from '@kbn/i18n/react';
import React, { Component } from 'react';
import { IndexPattern } from '../../index_patterns';
import { getFilterDisplayText } from '../filter_bar/filter_editor/lib/get_filter_display_text';
-import { mapAndFlattenFilters } from '../../../../../../plugins/data/public';
+import { mapAndFlattenFilters, esFilters } from '../../../../../../plugins/data/public';
import { getDisplayValueFromFilter } from '../filter_bar/filter_editor/lib/get_display_value';
interface Props {
- filters: Filter[];
+ filters: esFilters.Filter[];
indexPatterns: IndexPattern[];
onCancel: () => void;
- onSubmit: (filters: Filter[]) => void;
+ onSubmit: (filters: esFilters.Filter[]) => void;
}
interface State {
@@ -58,7 +57,7 @@ export class ApplyFiltersPopoverContent extends Component {
isFilterSelected: props.filters.map(() => true),
};
}
- private getLabel(filter: Filter) {
+ private getLabel(filter: esFilters.Filter) {
const filterDisplayValue = getDisplayValueFromFilter(filter, this.props.indexPatterns);
return getFilterDisplayText(filter, filterDisplayValue);
}
diff --git a/src/legacy/core_plugins/data/public/filter/apply_filters/apply_filters_popover.tsx b/src/legacy/core_plugins/data/public/filter/apply_filters/apply_filters_popover.tsx
index 0687701429866..41f757e726c40 100644
--- a/src/legacy/core_plugins/data/public/filter/apply_filters/apply_filters_popover.tsx
+++ b/src/legacy/core_plugins/data/public/filter/apply_filters/apply_filters_popover.tsx
@@ -18,15 +18,15 @@
*/
import { EuiModal, EuiOverlayMask } from '@elastic/eui';
-import { Filter } from '@kbn/es-query';
import React, { Component } from 'react';
import { ApplyFiltersPopoverContent } from './apply_filter_popover_content';
import { IndexPattern } from '../../index_patterns/index_patterns';
+import { esFilters } from '../../../../../../plugins/data/public';
interface Props {
- filters: Filter[];
+ filters: esFilters.Filter[];
onCancel: () => void;
- onSubmit: (filters: Filter[]) => void;
+ onSubmit: (filters: esFilters.Filter[]) => void;
indexPatterns: IndexPattern[];
}
@@ -56,9 +56,9 @@ export class ApplyFiltersPopover extends Component {
}
type cancelFunction = () => void;
-type submitFunction = (filters: Filter[]) => void;
+type submitFunction = (filters: esFilters.Filter[]) => void;
export const applyFiltersPopover = (
- filters: Filter[],
+ filters: esFilters.Filter[],
indexPatterns: IndexPattern[],
onCancel: cancelFunction,
onSubmit: submitFunction
diff --git a/src/legacy/core_plugins/data/public/filter/filter_bar/filter_bar.tsx b/src/legacy/core_plugins/data/public/filter/filter_bar/filter_bar.tsx
index 8a8fb36ea24bf..333e1e328651d 100644
--- a/src/legacy/core_plugins/data/public/filter/filter_bar/filter_bar.tsx
+++ b/src/legacy/core_plugins/data/public/filter/filter_bar/filter_bar.tsx
@@ -18,16 +18,6 @@
*/
import { EuiButtonEmpty, EuiFlexGroup, EuiFlexItem, EuiPopover } from '@elastic/eui';
-import {
- buildEmptyFilter,
- disableFilter,
- enableFilter,
- Filter,
- pinFilter,
- toggleFilterDisabled,
- toggleFilterNegated,
- unpinFilter,
-} from '@kbn/es-query';
import { FormattedMessage, InjectedIntl, injectI18n } from '@kbn/i18n/react';
import classNames from 'classnames';
import React, { useState } from 'react';
@@ -38,10 +28,11 @@ import { FilterEditor } from './filter_editor';
import { FilterItem } from './filter_item';
import { FilterOptions } from './filter_options';
import { useKibana, KibanaContextProvider } from '../../../../../../plugins/kibana_react/public';
+import { esFilters } from '../../../../../../plugins/data/public';
interface Props {
- filters: Filter[];
- onFiltersUpdated?: (filters: Filter[]) => void;
+ filters: esFilters.Filter[];
+ onFiltersUpdated?: (filters: esFilters.Filter[]) => void;
className: string;
indexPatterns: IndexPattern[];
intl: InjectedIntl;
@@ -87,7 +78,7 @@ function FilterBarUI(props: Props) {
return content;
}
- function onFiltersUpdated(filters: Filter[]) {
+ function onFiltersUpdated(filters: esFilters.Filter[]) {
if (props.onFiltersUpdated) {
props.onFiltersUpdated(filters);
}
@@ -112,7 +103,7 @@ function FilterBarUI(props: Props) {
const isPinned = uiSettings!.get('filters:pinnedByDefault');
const [indexPattern] = props.indexPatterns;
const index = indexPattern && indexPattern.id;
- const newFilter = buildEmptyFilter(isPinned, index);
+ const newFilter = esFilters.buildEmptyFilter(isPinned, index);
const button = (
void;
+ onSubmit: (filter: esFilters.Filter) => void;
onCancel: () => void;
intl: InjectedIntl;
}
@@ -379,7 +380,9 @@ class FilterEditorUI extends Component {
private getFieldFromFilter() {
const indexPattern = this.getIndexPatternFromFilter();
- return indexPattern && getFieldFromFilter(this.props.filter as FieldFilter, indexPattern);
+ return (
+ indexPattern && getFieldFromFilter(this.props.filter as esFilters.FieldFilter, indexPattern)
+ );
}
private getSelectedOperator() {
@@ -429,7 +432,7 @@ class FilterEditorUI extends Component {
this.setState({ selectedOperator, params });
};
- private onCustomLabelSwitchChange = (event: React.ChangeEvent) => {
+ private onCustomLabelSwitchChange = (event: EuiSwitchEvent) => {
const useCustomLabel = event.target.checked;
const customLabel = event.target.checked ? '' : null;
this.setState({ useCustomLabel, customLabel });
diff --git a/src/legacy/core_plugins/data/public/filter/filter_bar/filter_editor/lib/filter_editor_utils.test.ts b/src/legacy/core_plugins/data/public/filter/filter_bar/filter_editor/lib/filter_editor_utils.test.ts
index 734c5d00e58d5..7ee3e375c0967 100644
--- a/src/legacy/core_plugins/data/public/filter/filter_bar/filter_editor/lib/filter_editor_utils.test.ts
+++ b/src/legacy/core_plugins/data/public/filter/filter_bar/filter_editor/lib/filter_editor_utils.test.ts
@@ -17,8 +17,8 @@
* under the License.
*/
-import { FilterStateStore, toggleFilterNegated } from '@kbn/es-query';
-import { mockFields, mockIndexPattern } from '../../../../index_patterns';
+/* eslint-disable @kbn/eslint/no-restricted-paths */
+import { stubIndexPattern, stubFields } from '../../../../../../../../plugins/data/public/stubs';
import { IndexPattern, Field } from '../../../../index';
import {
buildFilter,
@@ -42,11 +42,12 @@ import { existsFilter } from './fixtures/exists_filter';
import { phraseFilter } from './fixtures/phrase_filter';
import { phrasesFilter } from './fixtures/phrases_filter';
import { rangeFilter } from './fixtures/range_filter';
+import { esFilters } from '../../../../../../../../plugins/data/public';
jest.mock('ui/new_platform');
-const mockedFields = mockFields as Field[];
-const mockedIndexPattern = mockIndexPattern as IndexPattern;
+const mockedFields = stubFields as Field[];
+const mockedIndexPattern = stubIndexPattern as IndexPattern;
describe('Filter editor utils', () => {
describe('getQueryDslFromFilter', () => {
@@ -81,7 +82,7 @@ describe('Filter editor utils', () => {
});
it('should return "is not" for phrase filter', () => {
- const negatedPhraseFilter = toggleFilterNegated(phraseFilter);
+ const negatedPhraseFilter = esFilters.toggleFilterNegated(phraseFilter);
const operator = getOperatorFromFilter(negatedPhraseFilter);
expect(operator).not.toBeUndefined();
expect(operator && operator.type).toBe('phrase');
@@ -96,7 +97,7 @@ describe('Filter editor utils', () => {
});
it('should return "is not one of" for negated phrases filter', () => {
- const negatedPhrasesFilter = toggleFilterNegated(phrasesFilter);
+ const negatedPhrasesFilter = esFilters.toggleFilterNegated(phrasesFilter);
const operator = getOperatorFromFilter(negatedPhrasesFilter);
expect(operator).not.toBeUndefined();
expect(operator && operator.type).toBe('phrases');
@@ -111,7 +112,7 @@ describe('Filter editor utils', () => {
});
it('should return "is not between" for negated range filter', () => {
- const negatedRangeFilter = toggleFilterNegated(rangeFilter);
+ const negatedRangeFilter = esFilters.toggleFilterNegated(rangeFilter);
const operator = getOperatorFromFilter(negatedRangeFilter);
expect(operator).not.toBeUndefined();
expect(operator && operator.type).toBe('range');
@@ -126,7 +127,7 @@ describe('Filter editor utils', () => {
});
it('should return "does not exists" for negated exists filter', () => {
- const negatedExistsFilter = toggleFilterNegated(existsFilter);
+ const negatedExistsFilter = esFilters.toggleFilterNegated(existsFilter);
const operator = getOperatorFromFilter(negatedExistsFilter);
expect(operator).not.toBeUndefined();
expect(operator && operator.type).toBe('exists');
@@ -171,14 +172,14 @@ describe('Filter editor utils', () => {
describe('getOperatorOptions', () => {
it('returns range for number fields', () => {
- const [field] = mockFields.filter(({ type }) => type === 'number');
+ const [field] = stubFields.filter(({ type }) => type === 'number');
const operatorOptions = getOperatorOptions(field as Field);
const rangeOperator = operatorOptions.find(operator => operator.type === 'range');
expect(rangeOperator).not.toBeUndefined();
});
it('does not return range for string fields', () => {
- const [field] = mockFields.filter(({ type }) => type === 'string');
+ const [field] = stubFields.filter(({ type }) => type === 'string');
const operatorOptions = getOperatorOptions(field as Field);
const rangeOperator = operatorOptions.find(operator => operator.type === 'range');
expect(rangeOperator).toBeUndefined();
@@ -246,7 +247,7 @@ describe('Filter editor utils', () => {
it('should build phrase filters', () => {
const params = 'foo';
const alias = 'bar';
- const state = FilterStateStore.APP_STATE;
+ const state = esFilters.FilterStateStore.APP_STATE;
const filter = buildFilter(
mockedIndexPattern,
mockedFields[0],
@@ -268,7 +269,7 @@ describe('Filter editor utils', () => {
it('should build phrases filters', () => {
const params = ['foo', 'bar'];
const alias = 'bar';
- const state = FilterStateStore.APP_STATE;
+ const state = esFilters.FilterStateStore.APP_STATE;
const filter = buildFilter(
mockedIndexPattern,
mockedFields[0],
@@ -290,7 +291,7 @@ describe('Filter editor utils', () => {
it('should build range filters', () => {
const params = { from: 'foo', to: 'qux' };
const alias = 'bar';
- const state = FilterStateStore.APP_STATE;
+ const state = esFilters.FilterStateStore.APP_STATE;
const filter = buildFilter(
mockedIndexPattern,
mockedFields[0],
@@ -311,7 +312,7 @@ describe('Filter editor utils', () => {
it('should build exists filters', () => {
const params = undefined;
const alias = 'bar';
- const state = FilterStateStore.APP_STATE;
+ const state = esFilters.FilterStateStore.APP_STATE;
const filter = buildFilter(
mockedIndexPattern,
mockedFields[0],
@@ -332,7 +333,7 @@ describe('Filter editor utils', () => {
it('should include disabled state', () => {
const params = undefined;
const alias = 'bar';
- const state = FilterStateStore.APP_STATE;
+ const state = esFilters.FilterStateStore.APP_STATE;
const filter = buildFilter(
mockedIndexPattern,
mockedFields[0],
@@ -348,7 +349,7 @@ describe('Filter editor utils', () => {
it('should negate based on operator', () => {
const params = undefined;
const alias = 'bar';
- const state = FilterStateStore.APP_STATE;
+ const state = esFilters.FilterStateStore.APP_STATE;
const filter = buildFilter(
mockedIndexPattern,
mockedFields[0],
diff --git a/src/legacy/core_plugins/data/public/filter/filter_bar/filter_editor/lib/filter_editor_utils.ts b/src/legacy/core_plugins/data/public/filter/filter_bar/filter_editor/lib/filter_editor_utils.ts
index f0628f03c173e..b7d20526a6b92 100644
--- a/src/legacy/core_plugins/data/public/filter/filter_bar/filter_editor/lib/filter_editor_utils.ts
+++ b/src/legacy/core_plugins/data/public/filter/filter_bar/filter_editor/lib/filter_editor_utils.ts
@@ -18,42 +18,30 @@
*/
import dateMath from '@elastic/datemath';
-import {
- buildExistsFilter,
- buildPhraseFilter,
- buildPhrasesFilter,
- buildRangeFilter,
- FieldFilter,
- Filter,
- FilterMeta,
- FilterStateStore,
- PhraseFilter,
- PhrasesFilter,
- RangeFilter,
-} from '@kbn/es-query';
import { omit } from 'lodash';
import { Ipv4Address } from '../../../../../../../../plugins/kibana_utils/public';
import { Field, IndexPattern, isFilterable } from '../../../../index_patterns';
import { FILTER_OPERATORS, Operator } from './filter_operators';
+import { esFilters } from '../../../../../../../../plugins/data/public';
export function getIndexPatternFromFilter(
- filter: Filter,
+ filter: esFilters.Filter,
indexPatterns: IndexPattern[]
): IndexPattern | undefined {
return indexPatterns.find(indexPattern => indexPattern.id === filter.meta.index);
}
-export function getFieldFromFilter(filter: FieldFilter, indexPattern: IndexPattern) {
+export function getFieldFromFilter(filter: esFilters.FieldFilter, indexPattern: IndexPattern) {
return indexPattern.fields.find(field => field.name === filter.meta.key);
}
-export function getOperatorFromFilter(filter: Filter) {
+export function getOperatorFromFilter(filter: esFilters.Filter) {
return FILTER_OPERATORS.find(operator => {
return filter.meta.type === operator.type && filter.meta.negate === operator.negate;
});
}
-export function getQueryDslFromFilter(filter: Filter) {
+export function getQueryDslFromFilter(filter: esFilters.Filter) {
return omit(filter, ['$state', 'meta']);
}
@@ -67,16 +55,16 @@ export function getOperatorOptions(field: Field) {
});
}
-export function getFilterParams(filter: Filter) {
+export function getFilterParams(filter: esFilters.Filter) {
switch (filter.meta.type) {
case 'phrase':
- return (filter as PhraseFilter).meta.params.query;
+ return (filter as esFilters.PhraseFilter).meta.params.query;
case 'phrases':
- return (filter as PhrasesFilter).meta.params;
+ return (filter as esFilters.PhrasesFilter).meta.params;
case 'range':
return {
- from: (filter as RangeFilter).meta.params.gte,
- to: (filter as RangeFilter).meta.params.lt,
+ from: (filter as esFilters.RangeFilter).meta.params.gte,
+ to: (filter as esFilters.RangeFilter).meta.params.lt,
};
}
}
@@ -133,8 +121,8 @@ export function buildFilter(
disabled: boolean,
params: any,
alias: string | null,
- store: FilterStateStore
-): Filter {
+ store: esFilters.FilterStateStore
+): esFilters.Filter {
const filter = buildBaseFilter(indexPattern, field, operator, params);
filter.meta.alias = alias;
filter.meta.negate = operator.negate;
@@ -148,17 +136,17 @@ function buildBaseFilter(
field: Field,
operator: Operator,
params: any
-): Filter {
+): esFilters.Filter {
switch (operator.type) {
case 'phrase':
- return buildPhraseFilter(field, params, indexPattern);
+ return esFilters.buildPhraseFilter(field, params, indexPattern);
case 'phrases':
- return buildPhrasesFilter(field, params, indexPattern);
+ return esFilters.buildPhrasesFilter(field, params, indexPattern);
case 'range':
const newParams = { gte: params.from, lt: params.to };
- return buildRangeFilter(field, newParams, indexPattern);
+ return esFilters.buildRangeFilter(field, newParams, indexPattern);
case 'exists':
- return buildExistsFilter(field, indexPattern);
+ return esFilters.buildExistsFilter(field, indexPattern);
default:
throw new Error(`Unknown operator type: ${operator.type}`);
}
@@ -170,10 +158,10 @@ export function buildCustomFilter(
disabled: boolean,
negate: boolean,
alias: string | null,
- store: FilterStateStore
-): Filter {
- const meta: FilterMeta = { index, type: 'custom', disabled, negate, alias };
- const filter: Filter = { ...queryDsl, meta };
+ store: esFilters.FilterStateStore
+): esFilters.Filter {
+ const meta: esFilters.FilterMeta = { index, type: 'custom', disabled, negate, alias };
+ const filter: esFilters.Filter = { ...queryDsl, meta };
filter.$state = { store };
return filter;
}
diff --git a/src/legacy/core_plugins/data/public/filter/filter_bar/filter_editor/lib/fixtures/exists_filter.ts b/src/legacy/core_plugins/data/public/filter/filter_bar/filter_editor/lib/fixtures/exists_filter.ts
index a17f767006f3e..5af97818f9bfb 100644
--- a/src/legacy/core_plugins/data/public/filter/filter_bar/filter_editor/lib/fixtures/exists_filter.ts
+++ b/src/legacy/core_plugins/data/public/filter/filter_bar/filter_editor/lib/fixtures/exists_filter.ts
@@ -17,9 +17,9 @@
* under the License.
*/
-import { ExistsFilter, FilterStateStore } from '@kbn/es-query';
+import { esFilters } from '../../../../../../../../../plugins/data/public';
-export const existsFilter: ExistsFilter = {
+export const existsFilter: esFilters.ExistsFilter = {
meta: {
index: 'logstash-*',
negate: false,
@@ -29,6 +29,6 @@ export const existsFilter: ExistsFilter = {
alias: null,
},
$state: {
- store: FilterStateStore.APP_STATE,
+ store: esFilters.FilterStateStore.APP_STATE,
},
};
diff --git a/src/legacy/core_plugins/data/public/filter/filter_bar/filter_editor/lib/fixtures/phrase_filter.ts b/src/legacy/core_plugins/data/public/filter/filter_bar/filter_editor/lib/fixtures/phrase_filter.ts
index 77bb8e06c801a..b6c8b9905e6b3 100644
--- a/src/legacy/core_plugins/data/public/filter/filter_bar/filter_editor/lib/fixtures/phrase_filter.ts
+++ b/src/legacy/core_plugins/data/public/filter/filter_bar/filter_editor/lib/fixtures/phrase_filter.ts
@@ -17,9 +17,9 @@
* under the License.
*/
-import { FilterStateStore, PhraseFilter } from '@kbn/es-query';
+import { esFilters } from '../../../../../../../../../plugins/data/public';
-export const phraseFilter: PhraseFilter = {
+export const phraseFilter: esFilters.PhraseFilter = {
meta: {
negate: false,
index: 'logstash-*',
@@ -33,6 +33,6 @@ export const phraseFilter: PhraseFilter = {
},
},
$state: {
- store: FilterStateStore.APP_STATE,
+ store: esFilters.FilterStateStore.APP_STATE,
},
};
diff --git a/src/legacy/core_plugins/data/public/filter/filter_bar/filter_editor/lib/fixtures/phrases_filter.ts b/src/legacy/core_plugins/data/public/filter/filter_bar/filter_editor/lib/fixtures/phrases_filter.ts
index e86c3ee1318e3..2e2ba4f798bdd 100644
--- a/src/legacy/core_plugins/data/public/filter/filter_bar/filter_editor/lib/fixtures/phrases_filter.ts
+++ b/src/legacy/core_plugins/data/public/filter/filter_bar/filter_editor/lib/fixtures/phrases_filter.ts
@@ -17,9 +17,9 @@
* under the License.
*/
-import { FilterStateStore, PhrasesFilter } from '@kbn/es-query';
+import { esFilters } from '../../../../../../../../../plugins/data/public';
-export const phrasesFilter: PhrasesFilter = {
+export const phrasesFilter: esFilters.PhrasesFilter = {
meta: {
index: 'logstash-*',
type: 'phrases',
@@ -31,6 +31,6 @@ export const phrasesFilter: PhrasesFilter = {
alias: null,
},
$state: {
- store: FilterStateStore.APP_STATE,
+ store: esFilters.FilterStateStore.APP_STATE,
},
};
diff --git a/src/legacy/core_plugins/data/public/filter/filter_bar/filter_editor/lib/fixtures/range_filter.ts b/src/legacy/core_plugins/data/public/filter/filter_bar/filter_editor/lib/fixtures/range_filter.ts
index 46a5181450fea..c6438e30ecec6 100644
--- a/src/legacy/core_plugins/data/public/filter/filter_bar/filter_editor/lib/fixtures/range_filter.ts
+++ b/src/legacy/core_plugins/data/public/filter/filter_bar/filter_editor/lib/fixtures/range_filter.ts
@@ -17,9 +17,9 @@
* under the License.
*/
-import { FilterStateStore, RangeFilter } from '@kbn/es-query';
+import { esFilters } from '../../../../../../../../../plugins/data/public';
-export const rangeFilter: RangeFilter = {
+export const rangeFilter: esFilters.RangeFilter = {
meta: {
index: 'logstash-*',
negate: false,
@@ -34,7 +34,7 @@ export const rangeFilter: RangeFilter = {
},
},
$state: {
- store: FilterStateStore.APP_STATE,
+ store: esFilters.FilterStateStore.APP_STATE,
},
range: {},
};
diff --git a/src/legacy/core_plugins/data/public/filter/filter_bar/filter_editor/lib/get_display_value.ts b/src/legacy/core_plugins/data/public/filter/filter_bar/filter_editor/lib/get_display_value.ts
index 551b99d01b7da..d8af7b3e97ad2 100644
--- a/src/legacy/core_plugins/data/public/filter/filter_bar/filter_editor/lib/get_display_value.ts
+++ b/src/legacy/core_plugins/data/public/filter/filter_bar/filter_editor/lib/get_display_value.ts
@@ -18,7 +18,7 @@
*/
import { get } from 'lodash';
-import { Filter } from '@kbn/es-query';
+import { esFilters } from '../../../../../../../../plugins/data/public';
import { IndexPattern } from '../../../../index_patterns/index_patterns';
import { Field } from '../../../../index_patterns/fields';
import { getIndexPatternFromFilter } from './filter_editor_utils';
@@ -33,7 +33,10 @@ function getValueFormatter(indexPattern?: IndexPattern, key?: string) {
return format;
}
-export function getDisplayValueFromFilter(filter: Filter, indexPatterns: IndexPattern[]): string {
+export function getDisplayValueFromFilter(
+ filter: esFilters.Filter,
+ indexPatterns: IndexPattern[]
+): string {
const indexPattern = getIndexPatternFromFilter(filter, indexPatterns);
if (typeof filter.meta.value === 'function') {
diff --git a/src/legacy/core_plugins/data/public/filter/filter_bar/filter_editor/lib/get_filter_display_text.tsx b/src/legacy/core_plugins/data/public/filter/filter_bar/filter_editor/lib/get_filter_display_text.tsx
index 429381694ddf8..21abcd8510046 100644
--- a/src/legacy/core_plugins/data/public/filter/filter_bar/filter_editor/lib/get_filter_display_text.tsx
+++ b/src/legacy/core_plugins/data/public/filter/filter_bar/filter_editor/lib/get_filter_display_text.tsx
@@ -19,11 +19,11 @@
import React, { Fragment } from 'react';
import { EuiTextColor } from '@elastic/eui';
-import { Filter } from '@kbn/es-query';
import { i18n } from '@kbn/i18n';
import { existsOperator, isOneOfOperator } from './filter_operators';
+import { esFilters } from '../../../../../../../../plugins/data/public';
-export function getFilterDisplayText(filter: Filter, filterDisplayName: string) {
+export function getFilterDisplayText(filter: esFilters.Filter, filterDisplayName: string) {
const prefixText = filter.meta.negate
? ` ${i18n.translate('data.filter.filterBar.negatedFilterPrefix', {
defaultMessage: 'NOT ',
diff --git a/src/legacy/core_plugins/data/public/filter/filter_bar/filter_item.tsx b/src/legacy/core_plugins/data/public/filter/filter_bar/filter_item.tsx
index 2e98cbd306e9c..50c1672333801 100644
--- a/src/legacy/core_plugins/data/public/filter/filter_bar/filter_item.tsx
+++ b/src/legacy/core_plugins/data/public/filter/filter_bar/filter_item.tsx
@@ -18,13 +18,6 @@
*/
import { EuiContextMenu, EuiPopover } from '@elastic/eui';
-import {
- Filter,
- isFilterPinned,
- toggleFilterDisabled,
- toggleFilterNegated,
- toggleFilterPinned,
-} from '@kbn/es-query';
import { InjectedIntl, injectI18n } from '@kbn/i18n/react';
import classNames from 'classnames';
import React, { Component } from 'react';
@@ -33,13 +26,14 @@ import { IndexPattern } from '../../index_patterns';
import { FilterEditor } from './filter_editor';
import { FilterView } from './filter_view';
import { getDisplayValueFromFilter } from './filter_editor/lib/get_display_value';
+import { esFilters } from '../../../../../../plugins/data/public';
interface Props {
id: string;
- filter: Filter;
+ filter: esFilters.Filter;
indexPatterns: IndexPattern[];
className?: string;
- onUpdate: (filter: Filter) => void;
+ onUpdate: (filter: esFilters.Filter) => void;
onRemove: () => void;
intl: InjectedIntl;
uiSettings: UiSettingsClientContract;
@@ -62,7 +56,7 @@ class FilterItemUI extends Component {
'globalFilterItem',
{
'globalFilterItem-isDisabled': disabled,
- 'globalFilterItem-isPinned': isFilterPinned(filter),
+ 'globalFilterItem-isPinned': esFilters.isFilterPinned(filter),
'globalFilterItem-isExcluded': negate,
},
this.props.className
@@ -91,7 +85,7 @@ class FilterItemUI extends Component {
id: 0,
items: [
{
- name: isFilterPinned(filter)
+ name: esFilters.isFilterPinned(filter)
? this.props.intl.formatMessage({
id: 'data.filter.filterBar.unpinFilterButtonLabel',
defaultMessage: 'Unpin',
@@ -209,23 +203,23 @@ class FilterItemUI extends Component {
});
};
- private onSubmit = (filter: Filter) => {
+ private onSubmit = (filter: esFilters.Filter) => {
this.closePopover();
this.props.onUpdate(filter);
};
private onTogglePinned = () => {
- const filter = toggleFilterPinned(this.props.filter);
+ const filter = esFilters.toggleFilterPinned(this.props.filter);
this.props.onUpdate(filter);
};
private onToggleNegated = () => {
- const filter = toggleFilterNegated(this.props.filter);
+ const filter = esFilters.toggleFilterNegated(this.props.filter);
this.props.onUpdate(filter);
};
private onToggleDisabled = () => {
- const filter = toggleFilterDisabled(this.props.filter);
+ const filter = esFilters.toggleFilterDisabled(this.props.filter);
this.props.onUpdate(filter);
};
}
diff --git a/src/legacy/core_plugins/data/public/filter/filter_bar/filter_view/index.tsx b/src/legacy/core_plugins/data/public/filter/filter_bar/filter_view/index.tsx
index 1dc93335d42be..6421691c4ef41 100644
--- a/src/legacy/core_plugins/data/public/filter/filter_bar/filter_view/index.tsx
+++ b/src/legacy/core_plugins/data/public/filter/filter_bar/filter_view/index.tsx
@@ -18,13 +18,13 @@
*/
import { EuiBadge, useInnerText } from '@elastic/eui';
-import { Filter, isFilterPinned } from '@kbn/es-query';
import { i18n } from '@kbn/i18n';
import React, { SFC } from 'react';
import { getFilterDisplayText } from '../filter_editor/lib/get_filter_display_text';
+import { esFilters } from '../../../../../../../plugins/data/public';
interface Props {
- filter: Filter;
+ filter: esFilters.Filter;
displayName: string;
[propName: string]: any;
}
@@ -44,7 +44,7 @@ export const FilterView: SFC = ({
values: { innerText },
});
- if (isFilterPinned(filter)) {
+ if (esFilters.isFilterPinned(filter)) {
title = `${i18n.translate('data.filter.filterBar.pinnedFilterPrefix', {
defaultMessage: 'Pinned',
})} ${title}`;
diff --git a/src/legacy/core_plugins/data/public/filter/filter_manager/filter_state_manager.test.ts b/src/legacy/core_plugins/data/public/filter/filter_manager/filter_state_manager.test.ts
index aae9c0754a8d8..08d5955d3fae9 100644
--- a/src/legacy/core_plugins/data/public/filter/filter_manager/filter_state_manager.test.ts
+++ b/src/legacy/core_plugins/data/public/filter/filter_manager/filter_state_manager.test.ts
@@ -19,12 +19,11 @@
import sinon from 'sinon';
-import { FilterStateStore } from '@kbn/es-query';
import { FilterStateManager } from './filter_state_manager';
import { StubState } from './test_helpers/stub_state';
import { getFilter } from './test_helpers/get_stub_filter';
-import { FilterManager } from '../../../../../../plugins/data/public';
+import { FilterManager, esFilters } from '../../../../../../plugins/data/public';
import { coreMock } from '../../../../../../core/public/mocks';
const setupMock = coreMock.createSetup();
@@ -59,7 +58,7 @@ describe('filter_state_manager', () => {
});
test('should NOT watch state until both app and global state are defined', done => {
- const f1 = getFilter(FilterStateStore.GLOBAL_STATE, false, false, 'age', 34);
+ const f1 = getFilter(esFilters.FilterStateStore.GLOBAL_STATE, false, false, 'age', 34);
globalStateStub.filters.push(f1);
setTimeout(() => {
@@ -72,8 +71,8 @@ describe('filter_state_manager', () => {
appStateStub.save = sinon.stub();
globalStateStub.save = sinon.stub();
- const f1 = getFilter(FilterStateStore.APP_STATE, false, false, 'age', 34);
- const f2 = getFilter(FilterStateStore.GLOBAL_STATE, false, false, 'age', 34);
+ const f1 = getFilter(esFilters.FilterStateStore.APP_STATE, false, false, 'age', 34);
+ const f2 = getFilter(esFilters.FilterStateStore.GLOBAL_STATE, false, false, 'age', 34);
filterManager.setFilters([f1, f2]);
@@ -109,7 +108,7 @@ describe('filter_state_manager', () => {
done();
});
- const f1 = getFilter(FilterStateStore.GLOBAL_STATE, true, true, 'age', 34);
+ const f1 = getFilter(esFilters.FilterStateStore.GLOBAL_STATE, true, true, 'age', 34);
globalStateStub.filters.push(f1);
});
@@ -122,7 +121,7 @@ describe('filter_state_manager', () => {
done();
});
- const f1 = getFilter(FilterStateStore.APP_STATE, false, false, 'age', 34);
+ const f1 = getFilter(esFilters.FilterStateStore.APP_STATE, false, false, 'age', 34);
appStateStub.filters.push(f1);
});
@@ -130,8 +129,8 @@ describe('filter_state_manager', () => {
appStateStub.save = sinon.stub();
globalStateStub.save = sinon.stub();
- const f1 = getFilter(FilterStateStore.APP_STATE, false, false, 'age', 34);
- const f2 = getFilter(FilterStateStore.GLOBAL_STATE, false, false, 'age', 34);
+ const f1 = getFilter(esFilters.FilterStateStore.APP_STATE, false, false, 'age', 34);
+ const f2 = getFilter(esFilters.FilterStateStore.GLOBAL_STATE, false, false, 'age', 34);
filterManager.setFilters([f1, f2]);
@@ -143,8 +142,8 @@ describe('filter_state_manager', () => {
appStateStub.save = sinon.stub();
globalStateStub.save = sinon.stub();
- const f1 = getFilter(FilterStateStore.APP_STATE, false, false, 'age', 34);
- const f2 = getFilter(FilterStateStore.GLOBAL_STATE, false, false, 'age', 34);
+ const f1 = getFilter(esFilters.FilterStateStore.APP_STATE, false, false, 'age', 34);
+ const f2 = getFilter(esFilters.FilterStateStore.GLOBAL_STATE, false, false, 'age', 34);
filterManager.addFilters([f1, f2]);
@@ -160,7 +159,7 @@ describe('filter_state_manager', () => {
** And triggers *another* filter manager update.
*/
test('should NOT re-trigger filter manager', done => {
- const f1 = getFilter(FilterStateStore.APP_STATE, false, false, 'age', 34);
+ const f1 = getFilter(esFilters.FilterStateStore.APP_STATE, false, false, 'age', 34);
filterManager.setFilters([f1]);
const setFiltersSpy = sinon.spy(filterManager, 'setFilters');
diff --git a/src/legacy/core_plugins/data/public/filter/filter_manager/filter_state_manager.ts b/src/legacy/core_plugins/data/public/filter/filter_manager/filter_state_manager.ts
index af8722c37c703..61821b7ad45e9 100644
--- a/src/legacy/core_plugins/data/public/filter/filter_manager/filter_state_manager.ts
+++ b/src/legacy/core_plugins/data/public/filter/filter_manager/filter_state_manager.ts
@@ -17,11 +17,9 @@
* under the License.
*/
-import { FilterStateStore } from '@kbn/es-query';
-
import _ from 'lodash';
import { State } from 'ui/state_management/state';
-import { FilterManager } from '../../../../../../plugins/data/public';
+import { FilterManager, esFilters } from '../../../../../../plugins/data/public';
type GetAppStateFunc = () => State | undefined | null;
@@ -73,8 +71,8 @@ export class FilterStateManager {
const newGlobalFilters = _.cloneDeep(globalFilters);
const newAppFilters = _.cloneDeep(appFilters);
- FilterManager.setFiltersStore(newAppFilters, FilterStateStore.APP_STATE);
- FilterManager.setFiltersStore(newGlobalFilters, FilterStateStore.GLOBAL_STATE);
+ FilterManager.setFiltersStore(newAppFilters, esFilters.FilterStateStore.APP_STATE);
+ FilterManager.setFiltersStore(newGlobalFilters, esFilters.FilterStateStore.GLOBAL_STATE);
this.filterManager.setFilters(newGlobalFilters.concat(newAppFilters));
}, 10);
diff --git a/src/legacy/core_plugins/data/public/filter/filter_manager/test_helpers/get_stub_filter.ts b/src/legacy/core_plugins/data/public/filter/filter_manager/test_helpers/get_stub_filter.ts
index 20d9e236f49be..5238efe5efa59 100644
--- a/src/legacy/core_plugins/data/public/filter/filter_manager/test_helpers/get_stub_filter.ts
+++ b/src/legacy/core_plugins/data/public/filter/filter_manager/test_helpers/get_stub_filter.ts
@@ -17,15 +17,15 @@
* under the License.
*/
-import { Filter, FilterStateStore } from '@kbn/es-query';
+import { esFilters } from '../../../../../../../plugins/data/public';
export function getFilter(
- store: FilterStateStore,
+ store: esFilters.FilterStateStore,
disabled: boolean,
negated: boolean,
queryKey: string,
queryValue: any
-): Filter {
+): esFilters.Filter {
return {
$state: {
store,
diff --git a/src/legacy/core_plugins/data/public/filter/filter_manager/test_helpers/stub_state.ts b/src/legacy/core_plugins/data/public/filter/filter_manager/test_helpers/stub_state.ts
index ab92016d1b9ab..f0a4bdef0229d 100644
--- a/src/legacy/core_plugins/data/public/filter/filter_manager/test_helpers/stub_state.ts
+++ b/src/legacy/core_plugins/data/public/filter/filter_manager/test_helpers/stub_state.ts
@@ -19,11 +19,11 @@
import sinon from 'sinon';
-import { Filter } from '@kbn/es-query';
import { State } from 'ui/state_management/state';
+import { esFilters } from '../../../../../../../plugins/data/public';
export class StubState implements State {
- filters: Filter[];
+ filters: esFilters.Filter[];
save: sinon.SinonSpy;
constructor() {
diff --git a/src/legacy/core_plugins/data/public/index.ts b/src/legacy/core_plugins/data/public/index.ts
index 502ca206e8e12..c3892fa581fc4 100644
--- a/src/legacy/core_plugins/data/public/index.ts
+++ b/src/legacy/core_plugins/data/public/index.ts
@@ -58,15 +58,4 @@ export {
IndexPatternMissingIndices,
NoDefaultIndexPattern,
NoDefinedIndexPatterns,
- mockFields,
- mockIndexPattern,
} from './index_patterns';
-
-export {
- TimeHistoryContract,
- TimefilterContract,
- getTime,
- InputTimeRange,
- extractTimeFilter,
- changeTimeFilter,
-} from './timefilter';
diff --git a/src/legacy/core_plugins/data/public/index_patterns/index_patterns/index_patterns.ts b/src/legacy/core_plugins/data/public/index_patterns/index_patterns/index_patterns.ts
index d445e2e58cd54..2c58af9deaf49 100644
--- a/src/legacy/core_plugins/data/public/index_patterns/index_patterns/index_patterns.ts
+++ b/src/legacy/core_plugins/data/public/index_patterns/index_patterns/index_patterns.ts
@@ -29,7 +29,7 @@ import { fieldFormats } from 'ui/registry/field_formats';
import { createIndexPatternCache } from './_pattern_cache';
import { IndexPattern } from './index_pattern';
-import { IndexPatternsApiClient } from './index_patterns_api_client';
+import { IndexPatternsApiClient, GetFieldsOptions } from './index_patterns_api_client';
const indexPatternCache = createIndexPatternCache();
@@ -52,11 +52,13 @@ export class IndexPatterns {
}
private async refreshSavedObjectsCache() {
- this.savedObjectsCache = (await this.savedObjectsClient.find({
- type: 'index-pattern',
- fields: [],
- perPage: 10000,
- })).savedObjects;
+ this.savedObjectsCache = (
+ await this.savedObjectsClient.find({
+ type: 'index-pattern',
+ fields: [],
+ perPage: 10000,
+ })
+ ).savedObjects;
}
getIds = async (refresh: boolean = false) => {
@@ -93,6 +95,14 @@ export class IndexPatterns {
});
};
+ getFieldsForTimePattern = (options: GetFieldsOptions = {}) => {
+ return this.apiClient.getFieldsForTimePattern(options);
+ };
+
+ getFieldsForWildcard = (options: GetFieldsOptions = {}) => {
+ return this.apiClient.getFieldsForWildcard(options);
+ };
+
clearCache = (id?: string) => {
this.savedObjectsCache = null;
if (id) {
diff --git a/src/legacy/core_plugins/data/public/index_patterns/index_patterns_service.ts b/src/legacy/core_plugins/data/public/index_patterns/index_patterns_service.ts
index bdeeb787c983d..9ce1b5f2e4a20 100644
--- a/src/legacy/core_plugins/data/public/index_patterns/index_patterns_service.ts
+++ b/src/legacy/core_plugins/data/public/index_patterns/index_patterns_service.ts
@@ -24,11 +24,11 @@ import {
NotificationsStart,
} from 'src/core/public';
import { Field, FieldList, FieldListInterface, FieldType } from './fields';
-import { createFlattenHitWrapper } from './index_patterns';
import { createIndexPatternSelect } from './components';
import { setNotifications } from './services';
import {
+ createFlattenHitWrapper,
formatHitProvider,
IndexPattern,
IndexPatterns,
@@ -92,8 +92,6 @@ export {
INDEX_PATTERN_ILLEGAL_CHARACTERS_VISIBLE,
isFilterable,
validateIndexPattern,
- mockFields,
- mockIndexPattern,
} from './utils';
/** @public */
diff --git a/src/legacy/core_plugins/data/public/index_patterns/utils.ts b/src/legacy/core_plugins/data/public/index_patterns/utils.ts
index 62f5ddbe9e2b0..1c877f4f14251 100644
--- a/src/legacy/core_plugins/data/public/index_patterns/utils.ts
+++ b/src/legacy/core_plugins/data/public/index_patterns/utils.ts
@@ -19,8 +19,7 @@
import { find, get } from 'lodash';
-import { Field, FieldType } from './fields';
-import { StaticIndexPattern } from './index_patterns';
+import { Field } from './fields';
import { getFilterableKbnTypeNames } from '../../../../../plugins/data/public';
import { SavedObjectsClientContract, SimpleSavedObject } from '../../../../../core/public';
@@ -139,69 +138,3 @@ export function getRoutes() {
sourceFilters: '/management/kibana/index_patterns/{{id}}?_a=(tab:sourceFilters)',
};
}
-
-export const mockFields: FieldType[] = [
- {
- name: 'machine.os',
- esTypes: ['text'],
- type: 'string',
- aggregatable: false,
- searchable: false,
- filterable: true,
- },
- {
- name: 'machine.os.raw',
- type: 'string',
- esTypes: ['keyword'],
- aggregatable: true,
- searchable: true,
- filterable: true,
- },
- {
- name: 'not.filterable',
- type: 'string',
- esTypes: ['text'],
- aggregatable: true,
- searchable: false,
- filterable: false,
- },
- {
- name: 'bytes',
- type: 'number',
- esTypes: ['long'],
- aggregatable: true,
- searchable: true,
- filterable: true,
- },
- {
- name: '@timestamp',
- type: 'date',
- esTypes: ['date'],
- aggregatable: true,
- searchable: true,
- filterable: true,
- },
- {
- name: 'clientip',
- type: 'ip',
- esTypes: ['ip'],
- aggregatable: true,
- searchable: true,
- filterable: true,
- },
- {
- name: 'bool.field',
- type: 'boolean',
- esTypes: ['boolean'],
- aggregatable: true,
- searchable: true,
- filterable: true,
- },
-];
-
-export const mockIndexPattern: StaticIndexPattern = {
- id: 'logstash-*',
- fields: mockFields,
- title: 'logstash-*',
- timeFieldName: '@timestamp',
-};
diff --git a/src/legacy/core_plugins/data/public/mocks.ts b/src/legacy/core_plugins/data/public/mocks.ts
index 4a7fe8efa4068..d3b5944127965 100644
--- a/src/legacy/core_plugins/data/public/mocks.ts
+++ b/src/legacy/core_plugins/data/public/mocks.ts
@@ -19,13 +19,11 @@
import { indexPatternsServiceMock } from './index_patterns/index_patterns_service.mock';
import { queryServiceMock } from './query/query_service.mock';
-import { timefilterServiceMock } from './timefilter/timefilter_service.mock';
function createDataSetupMock() {
return {
indexPatterns: indexPatternsServiceMock.createSetupContract(),
query: queryServiceMock.createSetupContract(),
- timefilter: timefilterServiceMock.createSetupContract(),
};
}
diff --git a/src/legacy/core_plugins/data/public/plugin.ts b/src/legacy/core_plugins/data/public/plugin.ts
index 03c9b0e93309d..76beb4ee56053 100644
--- a/src/legacy/core_plugins/data/public/plugin.ts
+++ b/src/legacy/core_plugins/data/public/plugin.ts
@@ -20,7 +20,6 @@
import { CoreSetup, CoreStart, Plugin } from 'kibana/public';
import { SearchService, SearchStart, createSearchBar, StatetfulSearchBarProps } from './search';
import { QueryService, QuerySetup } from './query';
-import { TimefilterService, TimefilterSetup } from './timefilter';
import { IndexPatternsService, IndexPatternsSetup, IndexPatternsStart } from './index_patterns';
import { Storage, IStorageWrapper } from '../../../../../src/plugins/kibana_utils/public';
import { DataPublicPluginStart } from '../../../../plugins/data/public';
@@ -44,7 +43,6 @@ export interface DataPluginStartDependencies {
*/
export interface DataSetup {
query: QuerySetup;
- timefilter: TimefilterSetup;
indexPatterns: IndexPatternsSetup;
}
@@ -55,7 +53,6 @@ export interface DataSetup {
*/
export interface DataStart {
query: QuerySetup;
- timefilter: TimefilterSetup;
indexPatterns: IndexPatternsStart;
search: SearchStart;
ui: {
@@ -79,24 +76,16 @@ export class DataPlugin implements Plugin ({
+jest.mock('../../../../../../../plugins/data/public/query/persisted_log', () => ({
PersistedLog: mockPersistedLogFactory,
}));
diff --git a/src/legacy/core_plugins/data/public/query/query_bar/components/query_bar_input.tsx b/src/legacy/core_plugins/data/public/query/query_bar/components/query_bar_input.tsx
index bfa29bef63462..5576427b1592a 100644
--- a/src/legacy/core_plugins/data/public/query/query_bar/components/query_bar_input.tsx
+++ b/src/legacy/core_plugins/data/public/query/query_bar/components/query_bar_input.tsx
@@ -33,11 +33,11 @@ import {
import { InjectedIntl, injectI18n, FormattedMessage } from '@kbn/i18n/react';
import { debounce, compact, isEqual } from 'lodash';
-import { documentationLinks } from 'ui/documentation_links';
import { Toast } from 'src/core/public';
import {
AutocompleteSuggestion,
AutocompleteSuggestionType,
+ PersistedLog,
} from '../../../../../../../plugins/data/public';
import {
withKibana,
@@ -48,7 +48,6 @@ import { Query, getQueryLog } from '../index';
import { fromUser, matchPairs, toUser } from '../lib';
import { QueryLanguageSwitcher } from './language_switcher';
import { SuggestionsComponent } from './typeahead/suggestions_component';
-import { PersistedLog } from '../../persisted_log';
import { fetchIndexPatterns } from '../lib/fetch_index_patterns';
import { IDataPluginServices } from '../../../types';
@@ -348,7 +347,7 @@ export class QueryBarInputUI extends Component {
suggestion.field.subType.nested &&
!this.services.storage.get('kibana.KQLNestedQuerySyntaxInfoOptOut')
) {
- const notifications = this.services.notifications;
+ const { notifications, docLinks } = this.services;
const onKQLNestedQuerySyntaxInfoOptOut = (toast: Toast) => {
if (!this.services.storage) return;
@@ -356,7 +355,7 @@ export class QueryBarInputUI extends Component {
notifications!.toasts.remove(toast);
};
- if (notifications) {
+ if (notifications && docLinks) {
const toast = notifications.toasts.add({
title: this.props.intl.formatMessage({
id: 'data.query.queryBar.KQLNestedQuerySyntaxInfoTitle',
@@ -372,7 +371,7 @@ export class QueryBarInputUI extends Component {
Learn more in our {link}."
values={{
link: (
-
+
{
- return [];
-});
+const mockTimeHistory = {
+ get: () => {
+ return [];
+ },
+};
startMock.uiSettings.get.mockImplementation((key: string) => {
switch (key) {
@@ -140,7 +139,7 @@ describe('QueryBarTopRowTopRow', () => {
screenTitle: 'Another Screen',
isDirty: false,
indexPatterns: [mockIndexPattern],
- timeHistory: timefilterSetupMock.history,
+ timeHistory: mockTimeHistory,
})
);
@@ -154,7 +153,7 @@ describe('QueryBarTopRowTopRow', () => {
query: kqlQuery,
screenTitle: 'Another Screen',
indexPatterns: [mockIndexPattern],
- timeHistory: timefilterSetupMock.history,
+ timeHistory: mockTimeHistory,
disableAutoFocus: true,
isDirty: false,
})
@@ -167,7 +166,7 @@ describe('QueryBarTopRowTopRow', () => {
const component = mount(
wrapQueryBarTopRowInContext({
isDirty: false,
- timeHistory: timefilterSetupMock.history,
+ timeHistory: mockTimeHistory,
})
);
@@ -179,7 +178,7 @@ describe('QueryBarTopRowTopRow', () => {
const component = mount(
wrapQueryBarTopRowInContext({
showDatePicker: false,
- timeHistory: timefilterSetupMock.history,
+ timeHistory: mockTimeHistory,
isDirty: false,
})
);
@@ -196,7 +195,7 @@ describe('QueryBarTopRowTopRow', () => {
showDatePicker: true,
dateRangeFrom: 'now-7d',
dateRangeTo: 'now',
- timeHistory: timefilterSetupMock.history,
+ timeHistory: mockTimeHistory,
})
);
@@ -212,7 +211,7 @@ describe('QueryBarTopRowTopRow', () => {
showDatePicker: true,
dateRangeFrom: 'now-7d',
dateRangeTo: 'now',
- timeHistory: timefilterSetupMock.history,
+ timeHistory: mockTimeHistory,
})
);
@@ -232,7 +231,7 @@ describe('QueryBarTopRowTopRow', () => {
showDatePicker: false,
dateRangeFrom: 'now-7d',
dateRangeTo: 'now',
- timeHistory: timefilterSetupMock.history,
+ timeHistory: mockTimeHistory,
})
);
@@ -249,7 +248,7 @@ describe('QueryBarTopRowTopRow', () => {
indexPatterns: [mockIndexPattern],
showQueryInput: false,
showDatePicker: false,
- timeHistory: timefilterSetupMock.history,
+ timeHistory: mockTimeHistory,
})
);
@@ -263,7 +262,7 @@ describe('QueryBarTopRowTopRow', () => {
isDirty: false,
screenTitle: 'Another Screen',
showDatePicker: false,
- timeHistory: timefilterSetupMock.history,
+ timeHistory: mockTimeHistory,
})
);
diff --git a/src/legacy/core_plugins/data/public/query/query_bar/components/query_bar_top_row.tsx b/src/legacy/core_plugins/data/public/query/query_bar/components/query_bar_top_row.tsx
index d2953621d86d1..d31ac2d76d0d9 100644
--- a/src/legacy/core_plugins/data/public/query/query_bar/components/query_bar_top_row.tsx
+++ b/src/legacy/core_plugins/data/public/query/query_bar/components/query_bar_top_row.tsx
@@ -35,15 +35,14 @@ import {
import { EuiSuperUpdateButton, OnRefreshProps } from '@elastic/eui';
import { FormattedMessage, InjectedIntl, injectI18n } from '@kbn/i18n/react';
import { Toast } from 'src/core/public';
-import { TimeRange } from 'src/plugins/data/public';
+import { TimeRange, TimeHistoryContract } from 'src/plugins/data/public';
import { useKibana } from '../../../../../../../plugins/kibana_react/public';
+import { PersistedLog } from '../../../../../../../plugins/data/public';
import { IndexPattern } from '../../../index_patterns';
import { QueryBarInput } from './query_bar_input';
import { Query, getQueryLog } from '../index';
-import { TimeHistoryContract } from '../../../timefilter';
import { IDataPluginServices } from '../../../types';
-import { PersistedLog } from '../../persisted_log';
interface Props {
query?: Query;
diff --git a/src/legacy/core_plugins/data/public/query/query_bar/lib/get_query_log.ts b/src/legacy/core_plugins/data/public/query/query_bar/lib/get_query_log.ts
index f78eb5e07f189..66424d9a1d6a3 100644
--- a/src/legacy/core_plugins/data/public/query/query_bar/lib/get_query_log.ts
+++ b/src/legacy/core_plugins/data/public/query/query_bar/lib/get_query_log.ts
@@ -19,7 +19,7 @@
import { UiSettingsClientContract } from 'src/core/public';
import { IStorageWrapper } from 'src/plugins/kibana_utils/public';
-import { PersistedLog } from '../../persisted_log';
+import { PersistedLog } from '../../../../../../../plugins/data/public';
export function getQueryLog(
uiSettings: UiSettingsClientContract,
diff --git a/src/legacy/core_plugins/data/public/search/search_bar/components/create_search_bar.tsx b/src/legacy/core_plugins/data/public/search/search_bar/components/create_search_bar.tsx
index c186edf9a3ac9..4485b74ca0901 100644
--- a/src/legacy/core_plugins/data/public/search/search_bar/components/create_search_bar.tsx
+++ b/src/legacy/core_plugins/data/public/search/search_bar/components/create_search_bar.tsx
@@ -19,20 +19,18 @@
import React, { useState, useEffect } from 'react';
import { Subscription } from 'rxjs';
-import { Filter } from '@kbn/es-query';
import { CoreStart } from 'src/core/public';
import { DataPublicPluginStart } from 'src/plugins/data/public';
import { IStorageWrapper } from 'src/plugins/kibana_utils/public';
import { KibanaContextProvider } from '../../../../../../../../src/plugins/kibana_react/public';
-import { TimefilterSetup } from '../../../timefilter';
import { SearchBar } from '../../../';
import { SearchBarOwnProps } from '.';
+import { esFilters } from '../../../../../../../plugins/data/public';
interface StatefulSearchBarDeps {
core: CoreStart;
data: DataPublicPluginStart;
storage: IStorageWrapper;
- timefilter: TimefilterSetup;
}
export type StatetfulSearchBarProps = SearchBarOwnProps & {
@@ -40,25 +38,26 @@ export type StatetfulSearchBarProps = SearchBarOwnProps & {
};
const defaultFiltersUpdated = (data: DataPublicPluginStart) => {
- return (filters: Filter[]) => {
+ return (filters: esFilters.Filter[]) => {
data.query.filterManager.setFilters(filters);
};
};
-const defaultOnRefreshChange = (timefilter: TimefilterSetup) => {
+const defaultOnRefreshChange = (data: DataPublicPluginStart) => {
+ const { timefilter } = data.query.timefilter;
return (options: { isPaused: boolean; refreshInterval: number }) => {
- timefilter.timefilter.setRefreshInterval({
+ timefilter.setRefreshInterval({
value: options.refreshInterval,
pause: options.isPaused,
});
};
};
-export function createSearchBar({ core, storage, timefilter, data }: StatefulSearchBarDeps) {
+export function createSearchBar({ core, storage, data }: StatefulSearchBarDeps) {
// App name should come from the core application service.
// Until it's available, we'll ask the user to provide it for the pre-wired component.
return (props: StatetfulSearchBarProps) => {
- const { filterManager } = data.query;
+ const { filterManager, timefilter } = data.query;
const tfRefreshInterval = timefilter.timefilter.getRefreshInterval();
const fmFilters = filterManager.getFilters();
const [refreshInterval, setRefreshInterval] = useState(tfRefreshInterval.value);
@@ -119,7 +118,7 @@ export function createSearchBar({ core, storage, timefilter, data }: StatefulSea
isRefreshPaused={refreshPaused}
filters={filters}
onFiltersUpdated={defaultFiltersUpdated(data)}
- onRefreshChange={defaultOnRefreshChange(timefilter)}
+ onRefreshChange={defaultOnRefreshChange(data)}
{...props}
/>
diff --git a/src/legacy/core_plugins/data/public/search/search_bar/components/saved_query_management/saved_query_management_component.tsx b/src/legacy/core_plugins/data/public/search/search_bar/components/saved_query_management/saved_query_management_component.tsx
index 56116e155eb2f..b73b8edb39e54 100644
--- a/src/legacy/core_plugins/data/public/search/search_bar/components/saved_query_management/saved_query_management_component.tsx
+++ b/src/legacy/core_plugins/data/public/search/search_bar/components/saved_query_management/saved_query_management_component.tsx
@@ -29,6 +29,7 @@ import {
EuiPagination,
EuiText,
EuiSpacer,
+ EuiIcon,
} from '@elastic/eui';
import { i18n } from '@kbn/i18n';
@@ -116,8 +117,6 @@ export const SavedQueryManagementComponent: FunctionComponent = ({
const savedQueryPopoverButton = (
{
setIsOpen(!isOpen);
}}
@@ -129,7 +128,8 @@ export const SavedQueryManagementComponent: FunctionComponent = ({
})}
data-test-subj="saved-query-management-popover-button"
>
- #
+
+
);
diff --git a/src/legacy/core_plugins/data/public/search/search_bar/components/search_bar.test.tsx b/src/legacy/core_plugins/data/public/search/search_bar/components/search_bar.test.tsx
index 9b77ec369c55b..44637365247fb 100644
--- a/src/legacy/core_plugins/data/public/search/search_bar/components/search_bar.test.tsx
+++ b/src/legacy/core_plugins/data/public/search/search_bar/components/search_bar.test.tsx
@@ -27,9 +27,13 @@ import { I18nProvider } from '@kbn/i18n/react';
import { coreMock } from '../../../../../../../../src/core/public/mocks';
const startMock = coreMock.createStart();
-import { timefilterServiceMock } from '../../../timefilter/timefilter_service.mock';
import { mount } from 'enzyme';
-const timefilterSetupMock = timefilterServiceMock.createSetupContract();
+
+const mockTimeHistory = {
+ get: () => {
+ return [];
+ },
+};
jest.mock('../../../../../data/public', () => {
return {
@@ -86,7 +90,7 @@ const kqlQuery = {
function wrapSearchBarInContext(testProps: any) {
const defaultOptions = {
appName: 'test',
- timeHistory: timefilterSetupMock.history,
+ timeHistory: mockTimeHistory,
intl: null as any,
};
diff --git a/src/legacy/core_plugins/data/public/search/search_bar/components/search_bar.tsx b/src/legacy/core_plugins/data/public/search/search_bar/components/search_bar.tsx
index c7f8b02caf853..a57b7b17a0da6 100644
--- a/src/legacy/core_plugins/data/public/search/search_bar/components/search_bar.tsx
+++ b/src/legacy/core_plugins/data/public/search/search_bar/components/search_bar.tsx
@@ -18,7 +18,6 @@
*/
import { compact } from 'lodash';
-import { Filter } from '@kbn/es-query';
import { InjectedIntl, injectI18n } from '@kbn/i18n/react';
import classNames from 'classnames';
import React, { Component } from 'react';
@@ -26,6 +25,7 @@ import ResizeObserver from 'resize-observer-polyfill';
import { get, isEqual } from 'lodash';
import { TimeRange } from 'src/plugins/data/common/types';
+import { TimeHistoryContract } from 'src/plugins/data/public';
import { IndexPattern, Query, FilterBar } from '../../../../../data/public';
import { QueryBarTopRow } from '../../../query';
import { SavedQuery, SavedQueryAttributes } from '../index';
@@ -33,20 +33,20 @@ import { SavedQueryMeta, SaveQueryForm } from './saved_query_management/save_que
import { SavedQueryManagementComponent } from './saved_query_management/saved_query_management_component';
import { SavedQueryService } from '../lib/saved_query_service';
import { createSavedQueryService } from '../lib/saved_query_service';
-import { TimeHistoryContract } from '../../../timefilter';
import {
withKibana,
KibanaReactContextValue,
} from '../../../../../../../plugins/kibana_react/public';
import { IDataPluginServices } from '../../../types';
+import { esFilters } from '../../../../../../../plugins/data/public';
interface SearchBarInjectedDeps {
kibana: KibanaReactContextValue;
intl: InjectedIntl;
timeHistory: TimeHistoryContract;
// Filter bar
- onFiltersUpdated?: (filters: Filter[]) => void;
- filters?: Filter[];
+ onFiltersUpdated?: (filters: esFilters.Filter[]) => void;
+ filters?: esFilters.Filter[];
// Date picker
dateRangeFrom?: string;
dateRangeTo?: string;
diff --git a/src/legacy/core_plugins/data/public/search/search_bar/index.tsx b/src/legacy/core_plugins/data/public/search/search_bar/index.tsx
index 0c677bea98536..ebde9d60b0b51 100644
--- a/src/legacy/core_plugins/data/public/search/search_bar/index.tsx
+++ b/src/legacy/core_plugins/data/public/search/search_bar/index.tsx
@@ -17,9 +17,9 @@
* under the License.
*/
-import { Filter } from '@kbn/es-query';
import { RefreshInterval, TimeRange } from 'src/plugins/data/public';
import { Query } from '../../query/query_bar';
+import { esFilters } from '../../../../../../plugins/data/public';
export * from './components';
@@ -36,6 +36,6 @@ export interface SavedQueryAttributes {
title: string;
description: string;
query: Query;
- filters?: Filter[];
+ filters?: esFilters.Filter[];
timefilter?: SavedQueryTimeFilter;
}
diff --git a/src/legacy/core_plugins/data/public/search/search_bar/lib/saved_query_service.test.ts b/src/legacy/core_plugins/data/public/search/search_bar/lib/saved_query_service.test.ts
index ac5fdb7fe99d5..415da8a2c32cc 100644
--- a/src/legacy/core_plugins/data/public/search/search_bar/lib/saved_query_service.test.ts
+++ b/src/legacy/core_plugins/data/public/search/search_bar/lib/saved_query_service.test.ts
@@ -19,7 +19,7 @@
import { SavedQueryAttributes } from '../index';
import { createSavedQueryService } from './saved_query_service';
-import { FilterStateStore } from '@kbn/es-query';
+import { esFilters } from '../../../../../../../plugins/data/public';
const savedQueryAttributes: SavedQueryAttributes = {
title: 'foo',
@@ -43,7 +43,7 @@ const savedQueryAttributesWithFilters: SavedQueryAttributes = {
filters: [
{
query: { match_all: {} },
- $state: { store: FilterStateStore.APP_STATE },
+ $state: { store: esFilters.FilterStateStore.APP_STATE },
meta: {
disabled: false,
negate: false,
diff --git a/src/legacy/core_plugins/data/public/shim/legacy_module.ts b/src/legacy/core_plugins/data/public/shim/legacy_module.ts
index b0ed3d43a4c8c..edc389b411971 100644
--- a/src/legacy/core_plugins/data/public/shim/legacy_module.ts
+++ b/src/legacy/core_plugins/data/public/shim/legacy_module.ts
@@ -24,7 +24,7 @@ import { wrapInI18nContext } from 'ui/i18n';
// @ts-ignore
import { uiModules } from 'ui/modules';
import { npStart } from 'ui/new_platform';
-import { FilterBar, ApplyFiltersPopover } from '../filter';
+import { FilterBar } from '../filter';
import { IndexPatterns } from '../index_patterns/index_patterns';
/** @internal */
@@ -70,54 +70,7 @@ export const initLegacyModule = once((indexPatterns: IndexPatterns): void => {
['className', { watchDepth: 'reference' }],
['pluginDataStart', { watchDepth: 'reference' }],
]);
- })
- .directive('applyFiltersPopover', () => {
- return {
- restrict: 'E',
- template: '',
- compile: (elem: any) => {
- const child = document.createElement('apply-filters-popover-helper');
-
- // Copy attributes to the child directive
- for (const attr of elem[0].attributes) {
- child.setAttribute(attr.name, attr.value);
- }
-
- // Add a key attribute that will force a full rerender every time that
- // a filter changes.
- child.setAttribute('key', 'key');
-
- // Append helper directive
- elem.append(child);
-
- const linkFn = ($scope: any, _: any, $attr: any) => {
- // Watch only for filter changes to update key.
- $scope.$watch(
- () => {
- return $scope.$eval($attr.filters) || [];
- },
- (newVal: any) => {
- $scope.key = Date.now();
- },
- true
- );
- };
-
- return linkFn;
- },
- };
- })
- .directive('applyFiltersPopoverHelper', (reactDirective: any) =>
- reactDirective(wrapInI18nContext(ApplyFiltersPopover), [
- ['filters', { watchDepth: 'collection' }],
- ['onCancel', { watchDepth: 'reference' }],
- ['onSubmit', { watchDepth: 'reference' }],
- ['indexPatterns', { watchDepth: 'collection' }],
-
- // Key is needed to trigger a full rerender of the component
- 'key',
- ])
- );
+ });
uiModules.get('kibana/index_patterns').value('indexPatterns', indexPatterns);
});
diff --git a/src/legacy/core_plugins/expressions/public/np_ready/public/execute.ts b/src/legacy/core_plugins/expressions/public/np_ready/public/execute.ts
index 8043e0fb6e3f9..45d5c07cd1b26 100644
--- a/src/legacy/core_plugins/expressions/public/np_ready/public/execute.ts
+++ b/src/legacy/core_plugins/expressions/public/np_ready/public/execute.ts
@@ -17,7 +17,7 @@
* under the License.
*/
-import { fromExpression } from '@kbn/interpreter/target/common';
+import { fromExpression, toExpression } from '@kbn/interpreter/target/common';
import { DataAdapter, RequestAdapter, Adapters } from '../../../../../../plugins/inspector/public';
import { getInterpreter } from './services';
import { ExpressionAST, IExpressionLoaderParams, IInterpreterResult } from './types';
@@ -38,17 +38,18 @@ export class ExpressionDataHandler {
private inspectorAdapters: Adapters;
private promise: Promise;
+ public isPending: boolean = true;
constructor(expression: string | ExpressionAST, params: IExpressionLoaderParams) {
if (typeof expression === 'string') {
this.expression = expression;
this.ast = fromExpression(expression) as ExpressionAST;
} else {
this.ast = expression;
- this.expression = '';
+ this.expression = toExpression(this.ast);
}
this.abortController = new AbortController();
- this.inspectorAdapters = this.getActiveInspectorAdapters();
+ this.inspectorAdapters = params.inspectorAdapters || this.getActiveInspectorAdapters();
const getInitialContext = () => ({
type: 'kibana_context',
@@ -58,11 +59,21 @@ export class ExpressionDataHandler {
const defaultContext = { type: 'null' };
const interpreter = getInterpreter();
- this.promise = interpreter.interpretAst(this.ast, params.context || defaultContext, {
- getInitialContext,
- inspectorAdapters: this.inspectorAdapters,
- abortSignal: this.abortController.signal,
- });
+ this.promise = interpreter
+ .interpretAst(this.ast, params.context || defaultContext, {
+ getInitialContext,
+ inspectorAdapters: this.inspectorAdapters,
+ abortSignal: this.abortController.signal,
+ })
+ .then(
+ (v: IInterpreterResult) => {
+ this.isPending = false;
+ return v;
+ },
+ () => {
+ this.isPending = false;
+ }
+ );
}
cancel = () => {
diff --git a/src/legacy/core_plugins/expressions/public/np_ready/public/loader.test.ts b/src/legacy/core_plugins/expressions/public/np_ready/public/loader.test.ts
index a3caa1c47b150..4c3bc76af351d 100644
--- a/src/legacy/core_plugins/expressions/public/np_ready/public/loader.test.ts
+++ b/src/legacy/core_plugins/expressions/public/np_ready/public/loader.test.ts
@@ -67,7 +67,7 @@ describe('execute helper function', () => {
});
describe('ExpressionLoader', () => {
- const expressionString = '';
+ const expressionString = 'demodata';
describe('constructor', () => {
it('accepts expression string', () => {
@@ -134,6 +134,8 @@ describe('ExpressionLoader', () => {
(ExpressionDataHandler as jest.Mock).mockImplementationOnce(() => ({
getData: () => true,
cancel: cancelMock,
+ isPending: () => true,
+ inspect: () => {},
}));
const expressionLoader = new ExpressionLoader(element, expressionString, {});
@@ -160,10 +162,15 @@ describe('ExpressionLoader', () => {
(ExpressionDataHandler as jest.Mock).mockImplementationOnce(() => ({
getData,
cancel: cancelMock,
+ isPending: () => true,
+ inspect: () => {},
}));
+
(ExpressionDataHandler as jest.Mock).mockImplementationOnce(() => ({
getData,
cancel: cancelMock,
+ isPending: () => true,
+ inspect: () => {},
}));
const expressionLoader = new ExpressionLoader(element, expressionString, {});
@@ -193,6 +200,8 @@ describe('ExpressionLoader', () => {
(ExpressionDataHandler as jest.Mock).mockImplementationOnce(() => ({
getData,
cancel: cancelMock,
+ isPending: () => true,
+ inspect: () => {},
}));
const expressionLoader = new ExpressionLoader(element, expressionString, {});
diff --git a/src/legacy/core_plugins/expressions/public/np_ready/public/loader.ts b/src/legacy/core_plugins/expressions/public/np_ready/public/loader.ts
index 709fbc78a9b52..2213cd30010b2 100644
--- a/src/legacy/core_plugins/expressions/public/np_ready/public/loader.ts
+++ b/src/legacy/core_plugins/expressions/public/np_ready/public/loader.ts
@@ -38,11 +38,12 @@ export class ExpressionLoader {
private loadingSubject: Subject;
private data: Data;
private params: IExpressionLoaderParams = {};
+ private ignoreNextResponse = false;
constructor(
element: HTMLElement,
- expression: string | ExpressionAST,
- params: IExpressionLoaderParams
+ expression?: string | ExpressionAST,
+ params?: IExpressionLoaderParams
) {
this.dataSubject = new Subject();
this.data$ = this.dataSubject.asObservable().pipe(share());
@@ -65,7 +66,9 @@ export class ExpressionLoader {
this.setParams(params);
- this.loadData(expression, this.params);
+ if (expression) {
+ this.loadData(expression, this.params);
+ }
}
destroy() {
@@ -117,9 +120,10 @@ export class ExpressionLoader {
update(expression?: string | ExpressionAST, params?: IExpressionLoaderParams): void {
this.setParams(params);
+ this.loadingSubject.next();
if (expression) {
this.loadData(expression, this.params);
- } else {
+ } else if (this.data) {
this.render(this.data);
}
}
@@ -128,18 +132,22 @@ export class ExpressionLoader {
expression: string | ExpressionAST,
params: IExpressionLoaderParams
): Promise => {
- this.loadingSubject.next();
- if (this.dataHandler) {
+ if (this.dataHandler && this.dataHandler.isPending) {
+ this.ignoreNextResponse = true;
this.dataHandler.cancel();
}
this.setParams(params);
this.dataHandler = new ExpressionDataHandler(expression, params);
+ if (!params.inspectorAdapters) params.inspectorAdapters = this.dataHandler.inspect();
const data = await this.dataHandler.getData();
+ if (this.ignoreNextResponse) {
+ this.ignoreNextResponse = false;
+ return;
+ }
this.dataSubject.next(data);
};
private render(data: Data): void {
- this.loadingSubject.next();
this.renderHandler.render(data, this.params.extraHandlers);
}
@@ -148,23 +156,16 @@ export class ExpressionLoader {
return;
}
- if (params.searchContext && this.params.searchContext) {
+ if (params.searchContext) {
this.params.searchContext = _.defaults(
{},
params.searchContext,
- this.params.searchContext
+ this.params.searchContext || {}
) as any;
}
if (params.extraHandlers && this.params) {
this.params.extraHandlers = params.extraHandlers;
}
-
- if (!Object.keys(this.params).length) {
- this.params = {
- ...params,
- searchContext: { type: 'kibana_context', ...(params.searchContext || {}) },
- };
- }
}
}
diff --git a/src/legacy/core_plugins/expressions/public/np_ready/public/types.ts b/src/legacy/core_plugins/expressions/public/np_ready/public/types.ts
index a8d89b4456693..9d7b4fb6d0480 100644
--- a/src/legacy/core_plugins/expressions/public/np_ready/public/types.ts
+++ b/src/legacy/core_plugins/expressions/public/np_ready/public/types.ts
@@ -17,10 +17,9 @@
* under the License.
*/
-import { Filter } from '@kbn/es-query';
import { TimeRange } from '../../../../../../plugins/data/public';
import { Adapters } from '../../../../../../plugins/inspector/public';
import { Query } from '../../../../../../plugins/data/public';
-export { TimeRange, Adapters, Filter, Query };
+export { TimeRange, Adapters, Query };
export * from '../../../../../../plugins/expressions/public';
diff --git a/src/legacy/core_plugins/input_control_vis/public/components/editor/list_control_editor.test.js b/src/legacy/core_plugins/input_control_vis/public/components/editor/list_control_editor.test.js
index 96c0802d3772a..ea029af9e4890 100644
--- a/src/legacy/core_plugins/input_control_vis/public/components/editor/list_control_editor.test.js
+++ b/src/legacy/core_plugins/input_control_vis/public/components/editor/list_control_editor.test.js
@@ -236,7 +236,7 @@ test('handleCheckboxOptionChange - multiselect', async () => {
component.update();
const checkbox = findTestSubject(component, 'listControlMultiselectInput');
- checkbox.simulate('change', { target: { checked: true } });
+ checkbox.simulate('click');
sinon.assert.notCalled(handleFieldNameChange);
sinon.assert.notCalled(handleIndexPatternChange);
sinon.assert.notCalled(handleNumberOptionChange);
@@ -247,7 +247,9 @@ test('handleCheckboxOptionChange - multiselect', async () => {
expectedControlIndex,
expectedOptionName,
sinon.match((evt) => {
- if (evt.target.checked === true) {
+ // Synthetic `evt.target.checked` does not get altered by EuiSwitch,
+ // but its aria attribute is correctly updated
+ if (evt.target.getAttribute('aria-checked') === 'true') {
return true;
}
return false;
diff --git a/src/legacy/core_plugins/input_control_vis/public/components/editor/options_tab.test.js b/src/legacy/core_plugins/input_control_vis/public/components/editor/options_tab.test.js
index 39f5f6a50a5a6..8784f0e79ca8d 100644
--- a/src/legacy/core_plugins/input_control_vis/public/components/editor/options_tab.test.js
+++ b/src/legacy/core_plugins/input_control_vis/public/components/editor/options_tab.test.js
@@ -47,8 +47,8 @@ describe('OptionsTab', () => {
it('should update updateFiltersOnChange', () => {
const component = mountWithIntl( );
- const checkbox = component.find('[data-test-subj="inputControlEditorUpdateFiltersOnChangeCheckbox"] input[type="checkbox"]');
- checkbox.simulate('change', { target: { checked: true } });
+ const checkbox = component.find('[data-test-subj="inputControlEditorUpdateFiltersOnChangeCheckbox"] button');
+ checkbox.simulate('click');
expect(props.setValue).toHaveBeenCalledTimes(1);
expect(props.setValue).toHaveBeenCalledWith('updateFiltersOnChange', true);
@@ -56,8 +56,8 @@ describe('OptionsTab', () => {
it('should update useTimeFilter', () => {
const component = mountWithIntl( );
- const checkbox = component.find('[data-test-subj="inputControlEditorUseTimeFilterCheckbox"] input[type="checkbox"]');
- checkbox.simulate('change', { target: { checked: true } });
+ const checkbox = component.find('[data-test-subj="inputControlEditorUseTimeFilterCheckbox"] button');
+ checkbox.simulate('click');
expect(props.setValue).toHaveBeenCalledTimes(1);
expect(props.setValue).toHaveBeenCalledWith('useTimeFilter', true);
@@ -65,8 +65,8 @@ describe('OptionsTab', () => {
it('should update pinFilters', () => {
const component = mountWithIntl( );
- const checkbox = component.find('[data-test-subj="inputControlEditorPinFiltersCheckbox"] input[type="checkbox"]');
- checkbox.simulate('change', { target: { checked: true } });
+ const checkbox = component.find('[data-test-subj="inputControlEditorPinFiltersCheckbox"] button');
+ checkbox.simulate('click');
expect(props.setValue).toHaveBeenCalledTimes(1);
expect(props.setValue).toHaveBeenCalledWith('pinFilters', true);
diff --git a/src/legacy/core_plugins/input_control_vis/public/control/filter_manager/phrase_filter_manager.js b/src/legacy/core_plugins/input_control_vis/public/control/filter_manager/phrase_filter_manager.js
index 9f0ed1dfb5097..65b1d41fa8239 100644
--- a/src/legacy/core_plugins/input_control_vis/public/control/filter_manager/phrase_filter_manager.js
+++ b/src/legacy/core_plugins/input_control_vis/public/control/filter_manager/phrase_filter_manager.js
@@ -20,12 +20,8 @@
import _ from 'lodash';
import { FilterManager } from './filter_manager.js';
import {
- buildPhraseFilter,
- buildPhrasesFilter,
- getPhraseFilterField,
- getPhraseFilterValue,
- isPhraseFilter,
-} from '@kbn/es-query';
+ esFilters,
+} from '../../../../../../plugins/data/public';
export class PhraseFilterManager extends FilterManager {
constructor(controlId, fieldName, indexPattern, queryFilter) {
@@ -43,12 +39,12 @@ export class PhraseFilterManager extends FilterManager {
createFilter(phrases) {
let newFilter;
if (phrases.length === 1) {
- newFilter = buildPhraseFilter(
+ newFilter = esFilters.buildPhraseFilter(
this.indexPattern.fields.getByName(this.fieldName),
phrases[0],
this.indexPattern);
} else {
- newFilter = buildPhrasesFilter(
+ newFilter = esFilters.buildPhrasesFilter(
this.indexPattern.fields.getByName(this.fieldName),
phrases,
this.indexPattern);
@@ -107,12 +103,12 @@ export class PhraseFilterManager extends FilterManager {
}
// single phrase filter
- if (isPhraseFilter(kbnFilter)) {
- if (getPhraseFilterField(kbnFilter) !== this.fieldName) {
+ if (esFilters.isPhraseFilter(kbnFilter)) {
+ if (esFilters.getPhraseFilterField(kbnFilter) !== this.fieldName) {
return;
}
- return getPhraseFilterValue(kbnFilter);
+ return esFilters.getPhraseFilterValue(kbnFilter);
}
// single phrase filter from bool filter
diff --git a/src/legacy/core_plugins/input_control_vis/public/control/filter_manager/range_filter_manager.js b/src/legacy/core_plugins/input_control_vis/public/control/filter_manager/range_filter_manager.js
index 1c8f5e2aa5a3e..3a232fd8b543d 100644
--- a/src/legacy/core_plugins/input_control_vis/public/control/filter_manager/range_filter_manager.js
+++ b/src/legacy/core_plugins/input_control_vis/public/control/filter_manager/range_filter_manager.js
@@ -19,7 +19,7 @@
import _ from 'lodash';
import { FilterManager } from './filter_manager.js';
-import { buildRangeFilter } from '@kbn/es-query';
+import { esFilters } from '../../../../../../plugins/data/public';
// Convert slider value into ES range filter
function toRange(sliderValue) {
@@ -55,7 +55,7 @@ export class RangeFilterManager extends FilterManager {
* @return {object} range filter
*/
createFilter(value) {
- const newFilter = buildRangeFilter(
+ const newFilter = esFilters.buildRangeFilter(
this.indexPattern.fields.getByName(this.fieldName),
toRange(value),
this.indexPattern);
diff --git a/src/legacy/core_plugins/interpreter/public/functions/esaggs.ts b/src/legacy/core_plugins/interpreter/public/functions/esaggs.ts
index d232a97c3c34c..bcb8d00663e01 100644
--- a/src/legacy/core_plugins/interpreter/public/functions/esaggs.ts
+++ b/src/legacy/core_plugins/interpreter/public/functions/esaggs.ts
@@ -22,9 +22,15 @@ import { i18n } from '@kbn/i18n';
import { AggConfigs } from 'ui/agg_types/agg_configs';
import { createFormat } from 'ui/visualize/loader/pipeline_helpers/utilities';
import chrome from 'ui/chrome';
-import { TimeRange } from 'src/plugins/data/public';
+
+import { Query, TimeRange, esFilters } from 'src/plugins/data/public';
import { SearchSource } from '../../../../ui/public/courier/search_source';
-import { FilterBarQueryFilterProvider } from '../../../../ui/public/filter_manager/query_filter';
+// @ts-ignore
+import {
+ FilterBarQueryFilterProvider,
+ QueryFilter,
+} from '../../../../ui/public/filter_manager/query_filter';
+
import { buildTabularInspectorData } from '../../../../ui/public/inspector/build_tabular_inspector_data';
import {
getRequestInspectorStats,
@@ -32,15 +38,30 @@ import {
} from '../../../../ui/public/courier/utils/courier_inspector_utils';
import { calculateObjectHash } from '../../../../ui/public/vis/lib/calculate_object_hash';
import { getTime } from '../../../../ui/public/timefilter';
-import { RequestHandlerParams } from '../../../../ui/public/visualize/loader/embedded_visualize_handler';
-import { KibanaContext, KibanaDatatable } from '../../common';
-import { ExpressionFunction, KibanaDatatableColumn } from '../../types';
-import { start as data } from '../../../data/public/legacy';
+
+export interface RequestHandlerParams {
+ searchSource: SearchSource;
+ aggs: AggConfigs;
+ timeRange?: TimeRange;
+ query?: Query;
+ filters?: esFilters.Filter[];
+ forceFetch: boolean;
+ queryFilter: QueryFilter;
+ uiState?: PersistedState;
+ partialRows?: boolean;
+ inspectorAdapters: Adapters;
+ metricsAtAllLevels?: boolean;
+ visParams?: any;
+ abortSignal?: AbortSignal;
+}
// @ts-ignore
import { tabifyAggResponse } from '../../../../ui/public/agg_response/tabify/tabify';
-// @ts-ignore
-import { SearchSourceProvider } from '../../../../ui/public/courier/search_source';
+import { KibanaContext, KibanaDatatable } from '../../common';
+import { ExpressionFunction, KibanaDatatableColumn } from '../../types';
+import { start as data } from '../../../data/public/legacy';
+import { PersistedState } from '../../../../ui/public/persisted_state';
+import { Adapters } from '../../../../../plugins/inspector/public';
const name = 'esaggs';
diff --git a/src/legacy/core_plugins/interpreter/public/renderers/visualization.ts b/src/legacy/core_plugins/interpreter/public/renderers/visualization.tsx
similarity index 73%
rename from src/legacy/core_plugins/interpreter/public/renderers/visualization.ts
rename to src/legacy/core_plugins/interpreter/public/renderers/visualization.tsx
index bedba6bfacede..9de6cdeaf5ec3 100644
--- a/src/legacy/core_plugins/interpreter/public/renderers/visualization.ts
+++ b/src/legacy/core_plugins/interpreter/public/renderers/visualization.tsx
@@ -18,9 +18,11 @@
*/
import chrome from 'ui/chrome';
-import { visualizationLoader } from 'ui/visualize/loader/visualization_loader';
+import React from 'react';
+import { render, unmountComponentAtNode } from 'react-dom';
// @ts-ignore
-import { VisProvider } from 'ui/visualize/loader/vis';
+import { VisProvider } from '../../../../ui/public/visualize/loader/vis';
+import { Visualization } from '../../../../ui/public/visualize/components';
export const visualization = () => ({
name: 'visualization',
@@ -50,17 +52,27 @@ export const visualization = () => ({
type: visType,
params: visConfig,
});
- handlers.vis.eventsSubject = handlers.eventsSubject;
}
+ handlers.vis.eventsSubject = { next: handlers.event };
+
const uiState = handlers.uiState || handlers.vis.getUiState();
- handlers.onDestroy(() => visualizationLoader.destroy());
+ handlers.onDestroy(() => {
+ unmountComponentAtNode(domNode);
+ });
- await visualizationLoader
- .render(domNode, handlers.vis, visData, handlers.vis.params, uiState, params)
- .then(() => {
- if (handlers.done) handlers.done();
- });
+ const listenOnChange = params ? params.listenOnChange : false;
+ render(
+ ,
+ domNode
+ );
},
});
diff --git a/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/metrics_axes/index.tsx b/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/metrics_axes/index.tsx
index c7ada18f9e1f2..2ca4ed1e2343d 100644
--- a/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/metrics_axes/index.tsx
+++ b/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/metrics_axes/index.tsx
@@ -83,9 +83,11 @@ function MetricsAxisOptions(props: ValidationVisOptionsProps)
// stores previous aggs' custom labels
const [lastCustomLabels, setLastCustomLabels] = useState({} as { [key: string]: string });
// stores previous aggs' field and type
- const [lastSeriesAgg, setLastSeriesAgg] = useState({} as {
- [key: string]: { type: string; field: string };
- });
+ const [lastSeriesAgg, setLastSeriesAgg] = useState(
+ {} as {
+ [key: string]: { type: string; field: string };
+ }
+ );
const updateAxisTitle = () => {
const axes = cloneDeep(stateParams.valueAxes);
diff --git a/src/legacy/core_plugins/kibana/public/dashboard/dashboard_app.html b/src/legacy/core_plugins/kibana/public/dashboard/dashboard_app.html
index 68c8131fa1a7b..f644f3811e3e0 100644
--- a/src/legacy/core_plugins/kibana/public/dashboard/dashboard_app.html
+++ b/src/legacy/core_plugins/kibana/public/dashboard/dashboard_app.html
@@ -42,13 +42,6 @@
index-patterns="indexPatterns"
>
-
-
diff --git a/src/legacy/core_plugins/kibana/public/dashboard/dashboard_app.tsx b/src/legacy/core_plugins/kibana/public/dashboard/dashboard_app.tsx
index 7a0398e86a60d..5fa3a938ed9df 100644
--- a/src/legacy/core_plugins/kibana/public/dashboard/dashboard_app.tsx
+++ b/src/legacy/core_plugins/kibana/public/dashboard/dashboard_app.tsx
@@ -35,7 +35,6 @@ import {
} from 'ui/state_management/app_state';
import { KbnUrl } from 'ui/url/kbn_url';
-import { Filter } from '@kbn/es-query';
import { TimeRange } from 'src/plugins/data/public';
import { IndexPattern } from 'ui/index_patterns';
import { IPrivate } from 'ui/private';
@@ -46,6 +45,7 @@ import { Subscription } from 'rxjs';
import { ViewMode } from '../../../embeddable_api/public/np_ready/public';
import { SavedObjectDashboard } from './saved_dashboard/saved_dashboard';
import { DashboardAppState, SavedDashboardPanel, ConfirmModalFn } from './types';
+import { esFilters } from '../../../../../../src/plugins/data/public';
import { DashboardAppController } from './dashboard_app_controller';
@@ -55,7 +55,7 @@ export interface DashboardAppScope extends ng.IScope {
screenTitle: string;
model: {
query: Query;
- filters: Filter[];
+ filters: esFilters.Filter[];
timeRestore: boolean;
title: string;
description: string;
@@ -81,9 +81,9 @@ export interface DashboardAppScope extends ng.IScope {
isPaused: boolean;
refreshInterval: any;
}) => void;
- onFiltersUpdated: (filters: Filter[]) => void;
+ onFiltersUpdated: (filters: esFilters.Filter[]) => void;
onCancelApplyFilters: () => void;
- onApplyFilters: (filters: Filter[]) => void;
+ onApplyFilters: (filters: esFilters.Filter[]) => void;
onQuerySaved: (savedQuery: SavedQuery) => void;
onSavedQueryUpdated: (savedQuery: SavedQuery) => void;
onClearSavedQuery: () => void;
diff --git a/src/legacy/core_plugins/kibana/public/dashboard/dashboard_app_controller.tsx b/src/legacy/core_plugins/kibana/public/dashboard/dashboard_app_controller.tsx
index abf7b22a6e48c..548a66297a3f9 100644
--- a/src/legacy/core_plugins/kibana/public/dashboard/dashboard_app_controller.tsx
+++ b/src/legacy/core_plugins/kibana/public/dashboard/dashboard_app_controller.tsx
@@ -48,7 +48,6 @@ import {
} from 'ui/state_management/app_state';
import { KbnUrl } from 'ui/url/kbn_url';
-import { Filter } from '@kbn/es-query';
import { IndexPattern } from 'ui/index_patterns';
import { IPrivate } from 'ui/private';
import { Query, SavedQuery } from 'src/legacy/core_plugins/data/public';
@@ -57,7 +56,6 @@ import { capabilities } from 'ui/capabilities';
import { Subscription } from 'rxjs';
import { npStart } from 'ui/new_platform';
import { SavedObjectFinder } from 'ui/saved_objects/components/saved_object_finder';
-import { extractTimeFilter, changeTimeFilter } from '../../../data/public';
import { start as data } from '../../../data/public/legacy';
import {
@@ -417,31 +415,6 @@ export class DashboardAppController {
queryFilter.setFilters(filters);
};
- $scope.onCancelApplyFilters = () => {
- $scope.appState.$newFilters = [];
- };
-
- $scope.onApplyFilters = filters => {
- if (filters.length) {
- // All filters originated from one visualization.
- const indexPatternId = filters[0].meta.index;
- const indexPattern = _.find(
- $scope.indexPatterns,
- (p: IndexPattern) => p.id === indexPatternId
- );
- if (indexPattern && indexPattern.timeFieldName) {
- const { timeRangeFilter, restOfFilters } = extractTimeFilter(
- indexPattern.timeFieldName,
- filters
- );
- queryFilter.addFilters(restOfFilters);
- if (timeRangeFilter) changeTimeFilter(timefilter, timeRangeFilter);
- }
- }
-
- $scope.appState.$newFilters = [];
- };
-
$scope.onQuerySaved = savedQuery => {
$scope.savedQuery = savedQuery;
};
@@ -514,12 +487,6 @@ export class DashboardAppController {
}
);
- $scope.$watch('appState.$newFilters', (filters: Filter[] = []) => {
- if (filters.length === 1) {
- $scope.onApplyFilters(filters);
- }
- });
-
$scope.indexPatterns = [];
$scope.$watch('model.query', (newQuery: Query) => {
diff --git a/src/legacy/core_plugins/kibana/public/dashboard/dashboard_state.test.ts b/src/legacy/core_plugins/kibana/public/dashboard/dashboard_state.test.ts
index a25ce1e607f9a..5e81373001bf5 100644
--- a/src/legacy/core_plugins/kibana/public/dashboard/dashboard_state.test.ts
+++ b/src/legacy/core_plugins/kibana/public/dashboard/dashboard_state.test.ts
@@ -23,7 +23,7 @@ import { DashboardStateManager } from './dashboard_state_manager';
import { getAppStateMock, getSavedDashboardMock } from './__tests__';
import { AppStateClass } from 'ui/state_management/app_state';
import { DashboardAppState } from './types';
-import { TimeRange } from 'src/plugins/data/public';
+import { TimeRange, TimefilterContract } from 'src/plugins/data/public';
import { ViewMode } from 'src/plugins/embeddable/public';
import { InputTimeRange } from 'ui/timefilter';
@@ -33,22 +33,19 @@ jest.mock('ui/registry/field_formats', () => ({
},
}));
-import { dataPluginMock } from '../../../../core_plugins/data/public/mocks';
-const dataSetupMock = dataPluginMock.createSetup();
-
describe('DashboardState', function() {
let dashboardState: DashboardStateManager;
const savedDashboard = getSavedDashboardMock();
let mockTime: TimeRange = { to: 'now', from: 'now-15m' };
- const mockTimefilter = dataSetupMock.timefilter!.timefilter;
-
- mockTimefilter.setTime.mockImplementation((time: InputTimeRange) => {
- mockTime = time as TimeRange;
- });
- mockTimefilter.getTime.mockImplementation(() => {
- return mockTime;
- });
+ const mockTimefilter = {
+ getTime: () => {
+ return mockTime;
+ },
+ setTime: (time: InputTimeRange) => {
+ mockTime = time as TimeRange;
+ },
+ } as TimefilterContract;
function initDashboardState() {
dashboardState = new DashboardStateManager({
diff --git a/src/legacy/core_plugins/kibana/public/dashboard/dashboard_state_manager.ts b/src/legacy/core_plugins/kibana/public/dashboard/dashboard_state_manager.ts
index 7c1fc771de349..8ffabe5add1c3 100644
--- a/src/legacy/core_plugins/kibana/public/dashboard/dashboard_state_manager.ts
+++ b/src/legacy/core_plugins/kibana/public/dashboard/dashboard_state_manager.ts
@@ -20,7 +20,6 @@
import { i18n } from '@kbn/i18n';
import _ from 'lodash';
-import { Filter } from '@kbn/es-query';
import { stateMonitorFactory, StateMonitor } from 'ui/state_management/state_monitor_factory';
import { Timefilter } from 'ui/timefilter';
import { AppStateClass as TAppStateClass } from 'ui/state_management/app_state';
@@ -29,6 +28,7 @@ import { Moment } from 'moment';
import { DashboardContainer } from 'src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public';
import { ViewMode } from '../../../../../../src/plugins/embeddable/public';
+import { esFilters } from '../../../../../../src/plugins/data/public';
import { Query } from '../../../data/public';
import { getAppStateDefaults, migrateAppState } from './lib';
@@ -50,7 +50,7 @@ export class DashboardStateManager {
public lastSavedDashboardFilters: {
timeTo?: string | Moment;
timeFrom?: string | Moment;
- filterBars: Filter[];
+ filterBars: esFilters.Filter[];
query: Query;
};
private stateDefaults: DashboardAppStateDefaults;
@@ -303,7 +303,7 @@ export class DashboardStateManager {
return this.savedDashboard.timeRestore;
}
- public getLastSavedFilterBars(): Filter[] {
+ public getLastSavedFilterBars(): esFilters.Filter[] {
return this.lastSavedDashboardFilters.filterBars;
}
@@ -461,7 +461,7 @@ export class DashboardStateManager {
* Applies the current filter state to the dashboard.
* @param filter An array of filter bar filters.
*/
- public applyFilters(query: Query, filters: Filter[]) {
+ public applyFilters(query: Query, filters: esFilters.Filter[]) {
this.appState.query = query;
this.savedDashboard.searchSource.setField('query', query);
this.savedDashboard.searchSource.setField('filter', filters);
diff --git a/src/legacy/core_plugins/kibana/public/dashboard/lib/filter_utils.ts b/src/legacy/core_plugins/kibana/public/dashboard/lib/filter_utils.ts
index 1fd50081c58bd..19a0c32210737 100644
--- a/src/legacy/core_plugins/kibana/public/dashboard/lib/filter_utils.ts
+++ b/src/legacy/core_plugins/kibana/public/dashboard/lib/filter_utils.ts
@@ -19,7 +19,7 @@
import _ from 'lodash';
import moment, { Moment } from 'moment';
-import { Filter } from '@kbn/es-query';
+import { esFilters } from '../../../../../../plugins/data/public';
/**
* @typedef {Object} QueryFilter
@@ -65,9 +65,9 @@ export class FilterUtils {
* @param filters {Array.
}
* @returns {Array.}
*/
- public static cleanFiltersForComparison(filters: Filter[]) {
+ public static cleanFiltersForComparison(filters: esFilters.Filter[]) {
return _.map(filters, filter => {
- const f: Partial = _.omit(filter, ['$$hashKey', '$state']);
+ const f: Partial = _.omit(filter, ['$$hashKey', '$state']);
if (f.meta) {
// f.meta.value is the value displayed in the filter bar.
// It may also be loaded differently and shouldn't be used in this comparison.
diff --git a/src/legacy/core_plugins/kibana/public/dashboard/listing/__snapshots__/dashboard_listing.test.js.snap b/src/legacy/core_plugins/kibana/public/dashboard/listing/__snapshots__/dashboard_listing.test.js.snap
index e23102a0785fc..1ed05035f5f4c 100644
--- a/src/legacy/core_plugins/kibana/public/dashboard/listing/__snapshots__/dashboard_listing.test.js.snap
+++ b/src/legacy/core_plugins/kibana/public/dashboard/listing/__snapshots__/dashboard_listing.test.js.snap
@@ -1,7 +1,7 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`after fetch hideWriteControls 1`] = `
-
`;
exports[`after fetch initialFilter 1`] = `
-
`;
exports[`after fetch renders call to action when no dashboards exist 1`] = `
-
`;
exports[`after fetch renders table rows 1`] = `
-
`;
exports[`after fetch renders warning when listingLimit is exceeded 1`] = `
-
`;
exports[`renders empty page in before initial fetch to avoid flickering 1`] = `
-
`;
diff --git a/src/legacy/core_plugins/kibana/public/dashboard/listing/dashboard_listing.js b/src/legacy/core_plugins/kibana/public/dashboard/listing/dashboard_listing.js
index d8216361562e2..c222fcd3c928c 100644
--- a/src/legacy/core_plugins/kibana/public/dashboard/listing/dashboard_listing.js
+++ b/src/legacy/core_plugins/kibana/public/dashboard/listing/dashboard_listing.js
@@ -23,8 +23,9 @@ import { FormattedMessage } from '@kbn/i18n/react';
import { i18n } from '@kbn/i18n';
import { EuiLink, EuiButton, EuiEmptyPrompt } from '@elastic/eui';
+import { npStart } from 'ui/new_platform';
-import { TableListView } from './../../table_list_view';
+import { TableListView } from '../../../../../../../src/plugins/kibana_react/public';
export const EMPTY_FILTER = '';
@@ -58,6 +59,8 @@ export class DashboardListing extends React.Component {
tableListTitle={i18n.translate('kbn.dashboard.listing.dashboardsTitle', {
defaultMessage: 'Dashboards',
})}
+ toastNotifications={npStart.core.notifications.toasts}
+ uiSettings={npStart.core.uiSettings}
/>
);
}
diff --git a/src/legacy/core_plugins/kibana/public/dashboard/listing/dashboard_listing.test.js b/src/legacy/core_plugins/kibana/public/dashboard/listing/dashboard_listing.test.js
index 57de395525e1b..be542c60bfe7a 100644
--- a/src/legacy/core_plugins/kibana/public/dashboard/listing/dashboard_listing.test.js
+++ b/src/legacy/core_plugins/kibana/public/dashboard/listing/dashboard_listing.test.js
@@ -42,6 +42,17 @@ jest.mock(
{ virtual: true }
);
+jest.mock('ui/new_platform', () => {
+ return {
+ npStart: {
+ core: {
+ notifications: { toasts: { } },
+ uiSettings: { get: jest.fn(() => 10) },
+ },
+ },
+ };
+});
+
import React from 'react';
import { shallow } from 'enzyme';
diff --git a/src/legacy/core_plugins/kibana/public/dashboard/migrations/move_filters_to_query.test.ts b/src/legacy/core_plugins/kibana/public/dashboard/migrations/move_filters_to_query.test.ts
index 1f503ee675407..ae3edae3b85d6 100644
--- a/src/legacy/core_plugins/kibana/public/dashboard/migrations/move_filters_to_query.test.ts
+++ b/src/legacy/core_plugins/kibana/public/dashboard/migrations/move_filters_to_query.test.ts
@@ -18,12 +18,12 @@
*/
import { moveFiltersToQuery, Pre600FilterQuery } from './move_filters_to_query';
-import { Filter, FilterStateStore } from '@kbn/es-query';
+import { esFilters } from '../../../../../../plugins/data/public';
-const filter: Filter = {
+const filter: esFilters.Filter = {
meta: { disabled: false, negate: false, alias: '' },
query: {},
- $state: { store: FilterStateStore.APP_STATE },
+ $state: { store: esFilters.FilterStateStore.APP_STATE },
};
const queryFilter: Pre600FilterQuery = {
@@ -38,7 +38,7 @@ test('Migrates an old filter query into the query field', () => {
expect(newSearchSource).toEqual({
filter: [
{
- $state: { store: FilterStateStore.APP_STATE },
+ $state: { store: esFilters.FilterStateStore.APP_STATE },
meta: {
alias: '',
disabled: false,
diff --git a/src/legacy/core_plugins/kibana/public/dashboard/migrations/move_filters_to_query.ts b/src/legacy/core_plugins/kibana/public/dashboard/migrations/move_filters_to_query.ts
index 153bdeba9d35f..8522495b9dedb 100644
--- a/src/legacy/core_plugins/kibana/public/dashboard/migrations/move_filters_to_query.ts
+++ b/src/legacy/core_plugins/kibana/public/dashboard/migrations/move_filters_to_query.ts
@@ -18,7 +18,7 @@
*/
import { Query } from 'src/legacy/core_plugins/data/public';
-import { Filter } from '@kbn/es-query';
+import { esFilters } from '../../../../../../plugins/data/public';
export interface Pre600FilterQuery {
// pre 6.0.0 global query:queryString:options were stored per dashboard and would
@@ -30,18 +30,18 @@ export interface Pre600FilterQuery {
export interface SearchSourcePre600 {
// I encountered at least one export from 7.0.0-alpha that was missing the filter property in here.
// The maps data in esarchives actually has it, but I don't know how/when they created it.
- filter?: Array;
+ filter?: Array;
}
export interface SearchSource730 {
- filter: Filter[];
+ filter: esFilters.Filter[];
query: Query;
highlightAll?: boolean;
version?: boolean;
}
-function isQueryFilter(filter: Filter | { query: unknown }): filter is Pre600FilterQuery {
- return filter.query && !(filter as Filter).meta;
+function isQueryFilter(filter: esFilters.Filter | { query: unknown }): filter is Pre600FilterQuery {
+ return filter.query && !(filter as esFilters.Filter).meta;
}
export function moveFiltersToQuery(
diff --git a/src/legacy/core_plugins/kibana/public/dashboard/saved_dashboard/saved_dashboard.d.ts b/src/legacy/core_plugins/kibana/public/dashboard/saved_dashboard/saved_dashboard.d.ts
index 1231ca28ed014..5b860b0a2cc7c 100644
--- a/src/legacy/core_plugins/kibana/public/dashboard/saved_dashboard/saved_dashboard.d.ts
+++ b/src/legacy/core_plugins/kibana/public/dashboard/saved_dashboard/saved_dashboard.d.ts
@@ -19,10 +19,9 @@
import { SearchSource } from 'ui/courier';
import { SavedObject } from 'ui/saved_objects/saved_object';
-import moment from 'moment';
import { RefreshInterval } from 'src/plugins/data/public';
import { Query } from 'src/legacy/core_plugins/data/public';
-import { Filter } from '@kbn/es-query';
+import { esFilters } from '../../../../../../plugins/data/public';
export interface SavedObjectDashboard extends SavedObject {
id?: string;
@@ -41,5 +40,5 @@ export interface SavedObjectDashboard extends SavedObject {
destroy: () => void;
refreshInterval?: RefreshInterval;
getQuery(): Query;
- getFilters(): Filter[];
+ getFilters(): esFilters.Filter[];
}
diff --git a/src/legacy/core_plugins/kibana/public/dashboard/types.ts b/src/legacy/core_plugins/kibana/public/dashboard/types.ts
index ccccc89004e36..5aaca7b62094f 100644
--- a/src/legacy/core_plugins/kibana/public/dashboard/types.ts
+++ b/src/legacy/core_plugins/kibana/public/dashboard/types.ts
@@ -18,7 +18,6 @@
*/
import { AppState } from 'ui/state_management/app_state';
-import { Filter } from '@kbn/es-query';
import { Query } from 'src/legacy/core_plugins/data/public';
import { AppState as TAppState } from 'ui/state_management/app_state';
import { ViewMode } from 'src/plugins/embeddable/public';
@@ -30,6 +29,7 @@ import {
RawSavedDashboardPanel640To720,
RawSavedDashboardPanel730ToLatest,
} from './migrations/types';
+import { esFilters } from '../../../../../plugins/data/public';
export type NavAction = (anchorElement?: any) => void;
@@ -110,7 +110,7 @@ export interface DashboardAppStateParameters {
useMargins: boolean;
};
query: Query | string;
- filters: Filter[];
+ filters: esFilters.Filter[];
viewMode: ViewMode;
savedQuery?: string;
}
diff --git a/src/legacy/core_plugins/kibana/public/discover/angular/context/api/context.ts b/src/legacy/core_plugins/kibana/public/discover/angular/context/api/context.ts
index 268f176f2c61e..3314bbbf189c4 100644
--- a/src/legacy/core_plugins/kibana/public/discover/angular/context/api/context.ts
+++ b/src/legacy/core_plugins/kibana/public/discover/angular/context/api/context.ts
@@ -17,7 +17,6 @@
* under the License.
*/
-import { Filter } from '@kbn/es-query';
import { IndexPatterns, IndexPattern, getServices } from '../../../kibana_services';
import { reverseSortDir, SortDirection } from './utils/sorting';
import { extractNanos, convertIsoToMillis } from './utils/date_conversion';
@@ -25,6 +24,7 @@ import { fetchHitsInInterval } from './utils/fetch_hits_in_interval';
import { generateIntervals } from './utils/generate_intervals';
import { getEsQuerySearchAfter } from './utils/get_es_query_search_after';
import { getEsQuerySort } from './utils/get_es_query_sort';
+import { esFilters } from '../../../../../../../../plugins/data/public';
export type SurrDocType = 'successors' | 'predecessors';
export interface EsHitRecord {
@@ -67,7 +67,7 @@ function fetchContextProvider(indexPatterns: IndexPatterns) {
tieBreakerField: string,
sortDir: SortDirection,
size: number,
- filters: Filter[]
+ filters: esFilters.Filter[]
) {
if (typeof anchor !== 'object' || anchor === null) {
return [];
@@ -112,7 +112,7 @@ function fetchContextProvider(indexPatterns: IndexPatterns) {
return documents;
}
- async function createSearchSource(indexPattern: IndexPattern, filters: Filter[]) {
+ async function createSearchSource(indexPattern: IndexPattern, filters: esFilters.Filter[]) {
return new SearchSource()
.setParent(false)
.setField('index', indexPattern)
diff --git a/src/legacy/core_plugins/kibana/public/discover/angular/doc_table/components/table_row.js b/src/legacy/core_plugins/kibana/public/discover/angular/doc_table/components/table_row.js
index 355d9defbb63d..6f5a94442e977 100644
--- a/src/legacy/core_plugins/kibana/public/discover/angular/doc_table/components/table_row.js
+++ b/src/legacy/core_plugins/kibana/public/discover/angular/doc_table/components/table_row.js
@@ -26,10 +26,10 @@ import { noWhiteSpace } from '../../../../../common/utils/no_white_space';
import openRowHtml from './table_row/open.html';
import detailsHtml from './table_row/details.html';
import { getServices } from '../../../kibana_services';
-import { disableFilter } from '@kbn/es-query';
import { dispatchRenderComplete } from '../../../../../../../../plugins/kibana_utils/public';
import cellTemplateHtml from '../components/table_row/cell.html';
import truncateByHeightTemplateHtml from '../components/table_row/truncate_by_height.html';
+import { esFilters } from '../../../../../../../../plugins/data/public';
const module = getServices().uiModules.get('app/discover');
@@ -117,7 +117,7 @@ module.directive('kbnTableRow', function ($compile, $httpParamSerializer, kbnUrl
const hash = $httpParamSerializer({
_a: rison.encode({
columns: $scope.columns,
- filters: ($scope.filters || []).map(disableFilter),
+ filters: ($scope.filters || []).map(esFilters.disableFilter),
}),
});
return `${path}?${hash}`;
diff --git a/src/legacy/core_plugins/kibana/public/discover/components/field_chooser/discover_field_search.test.tsx b/src/legacy/core_plugins/kibana/public/discover/components/field_chooser/discover_field_search.test.tsx
index c207585499483..5054f7b4bdad1 100644
--- a/src/legacy/core_plugins/kibana/public/discover/components/field_chooser/discover_field_search.test.tsx
+++ b/src/legacy/core_plugins/kibana/public/discover/components/field_chooser/discover_field_search.test.tsx
@@ -16,13 +16,13 @@
* specific language governing permissions and limitations
* under the License.
*/
-import React from 'react';
+import React, { EventHandler, MouseEvent as ReactMouseEvent } from 'react';
import { act } from 'react-dom/test-utils';
import { mountWithIntl } from 'test_utils/enzyme_helpers';
// @ts-ignore
import { findTestSubject } from '@elastic/eui/lib/test';
import { DiscoverFieldSearch, Props } from './discover_field_search';
-import { EuiButtonGroupProps } from '@elastic/eui';
+import { EuiButtonGroupProps, EuiPopover } from '@elastic/eui';
import { ReactWrapper } from 'enzyme';
describe('DiscoverFieldSearch', () => {
@@ -121,7 +121,7 @@ describe('DiscoverFieldSearch', () => {
// @ts-ignore
(aggregtableButtonGroup.props() as EuiButtonGroupProps).onChange('aggregatable-true', null);
});
- missingSwitch.simulate('change', { target: { value: false } });
+ missingSwitch.simulate('click');
expect(onChange).toBeCalledTimes(2);
});
@@ -136,4 +136,44 @@ describe('DiscoverFieldSearch', () => {
typeSelector.simulate('change', { target: { value: 'any' } });
expect(onChange).toBeCalledWith('type', 'any');
});
+
+ test('click on filter button should open and close popover', () => {
+ const component = mountComponent();
+ const btn = findTestSubject(component, 'toggleFieldFilterButton');
+ btn.simulate('click');
+ let popover = component.find(EuiPopover);
+ expect(popover.prop('isOpen')).toBe(true);
+ btn.simulate('click');
+ popover = component.find(EuiPopover);
+ expect(popover.prop('isOpen')).toBe(false);
+ });
+
+ test('click outside popover should close popover', () => {
+ const triggerDocumentMouseDown: EventHandler = (e: ReactMouseEvent) => {
+ const event = new Event('mousedown');
+ // @ts-ignore
+ event.euiGeneratedBy = e.nativeEvent.euiGeneratedBy;
+ document.dispatchEvent(event);
+ };
+ const triggerDocumentMouseUp: EventHandler = (e: ReactMouseEvent) => {
+ const event = new Event('mouseup');
+ // @ts-ignore
+ event.euiGeneratedBy = e.nativeEvent.euiGeneratedBy;
+ document.dispatchEvent(event);
+ };
+ const component = mountWithIntl(
+
+
+
+ );
+ const btn = findTestSubject(component, 'toggleFieldFilterButton');
+ btn.simulate('click');
+ let popover = component.find(EuiPopover);
+ expect(popover.length).toBe(1);
+ expect(popover.prop('isOpen')).toBe(true);
+ component.find('#wrapperId').simulate('mousedown');
+ component.find('#wrapperId').simulate('mouseup');
+ popover = component.find(EuiPopover);
+ expect(popover.prop('isOpen')).toBe(false);
+ });
});
diff --git a/src/legacy/core_plugins/kibana/public/discover/components/field_chooser/discover_field_search.tsx b/src/legacy/core_plugins/kibana/public/discover/components/field_chooser/discover_field_search.tsx
index f0685c4357c5a..d5f6b63d12199 100644
--- a/src/legacy/core_plugins/kibana/public/discover/components/field_chooser/discover_field_search.tsx
+++ b/src/legacy/core_plugins/kibana/public/discover/components/field_chooser/discover_field_search.tsx
@@ -29,9 +29,11 @@ import {
EuiPopoverTitle,
EuiSelect,
EuiSwitch,
+ EuiSwitchEvent,
EuiForm,
EuiFormRow,
EuiButtonGroup,
+ EuiOutsideClickDetector,
} from '@elastic/eui';
import { FormattedMessage } from '@kbn/i18n/react';
@@ -153,7 +155,7 @@ export function DiscoverFieldSearch({ onChange, value, types }: Props) {
setActiveFiltersCount(activeFiltersCount + diff);
};
- const handleMissingChange = (e: React.ChangeEvent) => {
+ const handleMissingChange = (e: EuiSwitchEvent) => {
const missingValue = e.target.checked;
handleValueChange('missing', missingValue);
};
@@ -244,6 +246,7 @@ export function DiscoverFieldSearch({ onChange, value, types }: Props) {
);
+
return (
@@ -260,33 +263,37 @@ export function DiscoverFieldSearch({ onChange, value, types }: Props) {
- {}}
- button={buttonContent}
- >
-
- {i18n.translate('kbn.discover.fieldChooser.filter.filterByTypeLabel', {
- defaultMessage: 'Filter by type',
- })}
-
- {selectionPanel}
-
- {}} isDisabled={!isPopoverOpen}>
+ {
+ setPopoverOpen(false);
+ }}
+ button={buttonContent}
+ >
+
+ {i18n.translate('kbn.discover.fieldChooser.filter.filterByTypeLabel', {
+ defaultMessage: 'Filter by type',
})}
- checked={values.missing}
- onChange={handleMissingChange}
- data-test-subj="missingSwitch"
- />
-
-
+
+ {selectionPanel}
+
+
+
+
+
);
diff --git a/src/legacy/core_plugins/kibana/public/discover/embeddable/search_embeddable.ts b/src/legacy/core_plugins/kibana/public/discover/embeddable/search_embeddable.ts
index e777501d35ca0..732fb6d2e4e70 100644
--- a/src/legacy/core_plugins/kibana/public/discover/embeddable/search_embeddable.ts
+++ b/src/legacy/core_plugins/kibana/public/discover/embeddable/search_embeddable.ts
@@ -19,12 +19,16 @@
import _ from 'lodash';
import * as Rx from 'rxjs';
import { Subscription } from 'rxjs';
-import { Filter, FilterStateStore } from '@kbn/es-query';
import { i18n } from '@kbn/i18n';
import { TExecuteTriggerActions } from 'src/plugins/ui_actions/public';
-import { TimeRange, onlyDisabledFiltersChanged } from '../../../../../../plugins/data/public';
-import { setup as data } from '../../../../data/public/legacy';
-import { Query, getTime } from '../../../../data/public';
+import { npStart } from 'ui/new_platform';
+import {
+ esFilters,
+ TimeRange,
+ onlyDisabledFiltersChanged,
+ getTime,
+} from '../../../../../../plugins/data/public';
+import { Query } from '../../../../data/public';
import {
APPLY_FILTER_TRIGGER,
Container,
@@ -49,6 +53,8 @@ import {
} from '../kibana_services';
import { SEARCH_EMBEDDABLE_TYPE } from './constants';
+const { data } = npStart.plugins;
+
interface SearchScope extends ng.IScope {
columns?: string[];
description?: string;
@@ -75,7 +81,7 @@ export interface FilterManager {
values: string | string[],
operation: string,
index: number
- ) => Filter[];
+ ) => esFilters.Filter[];
}
interface SearchEmbeddableConfig {
@@ -105,7 +111,7 @@ export class SearchEmbeddable extends Embeddable
private abortController?: AbortController;
private prevTimeRange?: TimeRange;
- private prevFilters?: Filter[];
+ private prevFilters?: esFilters.Filter[];
private prevQuery?: Query;
constructor(
@@ -136,9 +142,9 @@ export class SearchEmbeddable extends Embeddable
requests: new RequestAdapter(),
};
this.initializeSearchScope();
- this.autoRefreshFetchSubscription = data.timefilter.timefilter
- .getAutoRefreshFetch$()
- .subscribe(this.fetch);
+ const { timefilter } = data.query.timefilter;
+
+ this.autoRefreshFetchSubscription = timefilter.getAutoRefreshFetch$().subscribe(this.fetch);
this.subscription = Rx.merge(this.getOutput$(), this.getInput$()).subscribe(() => {
this.panelTitle = this.output.title || '';
@@ -248,7 +254,7 @@ export class SearchEmbeddable extends Embeddable
let filters = this.filterGen.generate(field, value, operator, indexPattern.id);
filters = filters.map(filter => ({
...filter,
- $state: { store: FilterStateStore.APP_STATE },
+ $state: { store: esFilters.FilterStateStore.APP_STATE },
}));
await this.executeTriggerActions(APPLY_FILTER_TRIGGER, {
diff --git a/src/legacy/core_plugins/kibana/public/discover/embeddable/types.ts b/src/legacy/core_plugins/kibana/public/discover/embeddable/types.ts
index db8d2afc7aff3..5473ec0e7b8b4 100644
--- a/src/legacy/core_plugins/kibana/public/discover/embeddable/types.ts
+++ b/src/legacy/core_plugins/kibana/public/discover/embeddable/types.ts
@@ -19,16 +19,16 @@
import { TimeRange } from 'src/plugins/data/public';
import { Query } from 'src/legacy/core_plugins/data/public';
-import { Filter } from '@kbn/es-query';
import { EmbeddableInput, EmbeddableOutput, IEmbeddable } from 'src/plugins/embeddable/public';
import { StaticIndexPattern } from '../kibana_services';
import { SavedSearch } from '../types';
import { SortOrder } from '../angular/doc_table/components/table_header/helpers';
+import { esFilters } from '../../../../../../plugins/data/public';
export interface SearchInput extends EmbeddableInput {
timeRange: TimeRange;
query?: Query;
- filters?: Filter[];
+ filters?: esFilters.Filter[];
hidePanelTitles?: boolean;
columns?: string[];
sort?: SortOrder[];
diff --git a/src/legacy/core_plugins/kibana/public/home/components/__snapshots__/home.test.js.snap b/src/legacy/core_plugins/kibana/public/home/components/__snapshots__/home.test.js.snap
index fcf60a6009b29..0bf8c808ae920 100644
--- a/src/legacy/core_plugins/kibana/public/home/components/__snapshots__/home.test.js.snap
+++ b/src/legacy/core_plugins/kibana/public/home/components/__snapshots__/home.test.js.snap
@@ -2,6 +2,7 @@
exports[`home directories should not render directory entry when showOnHomePage is false 1`] = `
`;
exports[`home welcome stores skip welcome setting if skipped 1`] = `
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+`;
+
+exports[`should render a Welcome screen with the telemetry disclaimer 1`] = `
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+`;
diff --git a/src/legacy/core_plugins/kibana/public/home/components/home.js b/src/legacy/core_plugins/kibana/public/home/components/home.js
index e4c7de9b495a0..3266bbb79c625 100644
--- a/src/legacy/core_plugins/kibana/public/home/components/home.js
+++ b/src/legacy/core_plugins/kibana/public/home/components/home.js
@@ -51,6 +51,7 @@ export class Home extends Component {
getServices().getInjected('disableWelcomeScreen') ||
props.localStorage.getItem(KEY_ENABLE_WELCOME) === 'false'
);
+ const showTelemetryDisclaimer = getServices().getInjected('allowChangingOptInStatus');
this.state = {
// If welcome is enabled, we wait for loading to complete
@@ -60,6 +61,7 @@ export class Home extends Component {
isLoading: isWelcomeEnabled,
isNewKibanaInstance: false,
isWelcomeEnabled,
+ showTelemetryDisclaimer,
};
}
@@ -136,7 +138,7 @@ export class Home extends Component {
const { apmUiEnabled, mlEnabled } = this.props;
return (
-
+
@@ -228,10 +230,7 @@ export class Home extends Component {
);
}
@@ -254,10 +253,6 @@ export class Home extends Component {
Home.propTypes = {
addBasePath: PropTypes.func.isRequired,
- fetchTelemetry: PropTypes.func.isRequired,
- getTelemetryBannerId: PropTypes.func.isRequired,
- setOptIn: PropTypes.func.isRequired,
- shouldShowTelemetryOptIn: PropTypes.bool,
directories: PropTypes.arrayOf(
PropTypes.shape({
id: PropTypes.string.isRequired,
diff --git a/src/legacy/core_plugins/kibana/public/home/components/home_app.js b/src/legacy/core_plugins/kibana/public/home/components/home_app.js
index 005d4bdb0a99e..f8476a0c09670 100644
--- a/src/legacy/core_plugins/kibana/public/home/components/home_app.js
+++ b/src/legacy/core_plugins/kibana/public/home/components/home_app.js
@@ -18,26 +18,19 @@
*/
import React from 'react';
+import { I18nProvider } from '@kbn/i18n/react';
import PropTypes from 'prop-types';
import { Home } from './home';
import { FeatureDirectory } from './feature_directory';
import { TutorialDirectory } from './tutorial_directory';
import { Tutorial } from './tutorial/tutorial';
-import {
- HashRouter as Router,
- Switch,
- Route,
-} from 'react-router-dom';
+import { HashRouter as Router, Switch, Route, Redirect } from 'react-router-dom';
import { getTutorial } from '../load_tutorials';
import { replaceTemplateStrings } from './tutorial/replace_template_strings';
-import {
- getServices
-} from '../kibana_services';
+import { getServices } from '../kibana_services';
export function HomeApp({ directories }) {
const {
- telemetryOptInProvider,
- shouldShowTelemetryOptIn,
getInjected,
savedObjectsClient,
getBasePath,
@@ -47,8 +40,9 @@ export function HomeApp({ directories }) {
const isCloudEnabled = getInjected('isCloudEnabled', false);
const apmUiEnabled = getInjected('apmUiEnabled', true);
const mlEnabled = getInjected('mlEnabled', false);
+ const defaultAppId = getInjected('kbnDefaultAppId', 'discover');
- const renderTutorialDirectory = (props) => {
+ const renderTutorialDirectory = props => {
return (
{
+ const renderTutorial = props => {
return (
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
);
}
HomeApp.propTypes = {
- directories: PropTypes.arrayOf(PropTypes.shape({
- id: PropTypes.string.isRequired,
- title: PropTypes.string.isRequired,
- description: PropTypes.string.isRequired,
- icon: PropTypes.string.isRequired,
- path: PropTypes.string.isRequired,
- showOnHomePage: PropTypes.bool.isRequired,
- category: PropTypes.string.isRequired,
- })),
+ directories: PropTypes.arrayOf(
+ PropTypes.shape({
+ id: PropTypes.string.isRequired,
+ title: PropTypes.string.isRequired,
+ description: PropTypes.string.isRequired,
+ icon: PropTypes.string.isRequired,
+ path: PropTypes.string.isRequired,
+ showOnHomePage: PropTypes.bool.isRequired,
+ category: PropTypes.string.isRequired,
+ })
+ ),
};
diff --git a/src/legacy/core_plugins/kibana/public/home/components/telemetry_opt_in/telemetry_opt_in_card.tsx b/src/legacy/core_plugins/kibana/public/home/components/telemetry_opt_in/telemetry_opt_in_card.tsx
deleted file mode 100644
index 572188d9c9b93..0000000000000
--- a/src/legacy/core_plugins/kibana/public/home/components/telemetry_opt_in/telemetry_opt_in_card.tsx
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Licensed to Elasticsearch B.V. under one or more contributor
- * license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright
- * ownership. Elasticsearch B.V. licenses this file to you under
- * the Apache License, Version 2.0 (the "License"); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-import React from 'react';
-import { FormattedMessage } from '@kbn/i18n/react';
-import {
- // @ts-ignore
- EuiCard,
- EuiButton,
-} from '@elastic/eui';
-import { OptInMessage } from '../../../../../telemetry/public/components/opt_in_message';
-
-export interface Props {
- urlBasePath: string;
- onConfirm: () => void;
- onDecline: () => void;
- fetchTelemetry: () => Promise;
-}
-
-export function renderTelemetryOptInCard({
- urlBasePath,
- fetchTelemetry,
- onConfirm,
- onDecline,
-}: Props) {
- return (
-
- }
- description={ }
- footer={
-
- }
- />
- );
-}
diff --git a/src/legacy/core_plugins/kibana/public/home/components/welcome.test.tsx b/src/legacy/core_plugins/kibana/public/home/components/welcome.test.tsx
new file mode 100644
index 0000000000000..195a527707af6
--- /dev/null
+++ b/src/legacy/core_plugins/kibana/public/home/components/welcome.test.tsx
@@ -0,0 +1,52 @@
+/*
+ * 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 React from 'react';
+import { shallow } from 'enzyme';
+import { Welcome } from './welcome';
+
+jest.mock('../kibana_services', () => ({
+ getServices: () => ({
+ addBasePath: (path: string) => `root${path}`,
+ trackUiMetric: () => {},
+ METRIC_TYPE: {
+ LOADED: 'loaded',
+ CLICK: 'click',
+ },
+ }),
+}));
+
+test('should render a Welcome screen with the telemetry disclaimer', () => {
+ const component = shallow(
+ // @ts-ignore
+ {}} showTelemetryDisclaimer={true} />
+ );
+
+ expect(component).toMatchSnapshot();
+});
+
+test('should render a Welcome screen with no telemetry disclaimer', () => {
+ // @ts-ignore
+ const component = shallow(
+ // @ts-ignore
+ {}} showTelemetryDisclaimer={false} />
+ );
+
+ expect(component).toMatchSnapshot();
+});
diff --git a/src/legacy/core_plugins/kibana/public/home/components/welcome.tsx b/src/legacy/core_plugins/kibana/public/home/components/welcome.tsx
index afe43a23e18cb..d919a4ecf239c 100644
--- a/src/legacy/core_plugins/kibana/public/home/components/welcome.tsx
+++ b/src/legacy/core_plugins/kibana/public/home/components/welcome.tsx
@@ -25,6 +25,8 @@
import React from 'react';
import {
+ EuiLink,
+ EuiTextColor,
EuiTitle,
EuiSpacer,
EuiFlexGroup,
@@ -37,29 +39,18 @@ import { FormattedMessage } from '@kbn/i18n/react';
import { getServices } from '../kibana_services';
import { SampleDataCard } from './sample_data';
-import { TelemetryOptInCard } from './telemetry_opt_in';
interface Props {
urlBasePath: string;
- onSkip: () => {};
- fetchTelemetry: () => Promise;
- setOptIn: (enabled: boolean) => Promise;
- getTelemetryBannerId: () => string;
- shouldShowTelemetryOptIn: boolean;
-}
-
-interface State {
- step: number;
+ onSkip: () => void;
+ showTelemetryDisclaimer: boolean;
}
/**
* Shows a full-screen welcome page that gives helpful quick links to beginners.
*/
-export class Welcome extends React.PureComponent {
+export class Welcome extends React.Component {
private services = getServices();
- public readonly state: State = {
- step: 0,
- };
private hideOnEsc = (e: KeyboardEvent) => {
if (e.key === 'Escape') {
@@ -72,19 +63,11 @@ export class Welcome extends React.PureComponent {
window.location.href = path;
}
- private async handleTelemetrySelection(confirm: boolean) {
- const metricName = `telemetryOptIn${confirm ? 'Confirm' : 'Decline'}`;
- this.services.trackUiMetric(this.services.METRIC_TYPE.CLICK, metricName);
- await this.props.setOptIn(confirm);
- const bannerId = this.props.getTelemetryBannerId();
- this.services.banners.remove(bannerId);
- this.setState(() => ({ step: 1 }));
- }
-
private onSampleDataDecline = () => {
this.services.trackUiMetric(this.services.METRIC_TYPE.CLICK, 'sampleDataDecline');
this.props.onSkip();
};
+
private onSampleDataConfirm = () => {
this.services.trackUiMetric(this.services.METRIC_TYPE.CLICK, 'sampleDataConfirm');
this.redirecToSampleData();
@@ -92,12 +75,6 @@ export class Welcome extends React.PureComponent {
componentDidMount() {
this.services.trackUiMetric(this.services.METRIC_TYPE.LOADED, 'welcomeScreenMount');
- if (this.props.shouldShowTelemetryOptIn) {
- this.services.trackUiMetric(
- this.services.METRIC_TYPE.COUNT,
- 'welcomeScreenWithTelemetryOptIn'
- );
- }
document.addEventListener('keydown', this.hideOnEsc);
}
@@ -106,8 +83,7 @@ export class Welcome extends React.PureComponent {
}
render() {
- const { urlBasePath, shouldShowTelemetryOptIn, fetchTelemetry } = this.props;
- const { step } = this.state;
+ const { urlBasePath, showTelemetryDisclaimer } = this.props;
return (
@@ -137,20 +113,39 @@ export class Welcome extends React.PureComponent {
- {shouldShowTelemetryOptIn && step === 0 && (
-
- )}
- {(!shouldShowTelemetryOptIn || step === 1) && (
-
+
+
+ {showTelemetryDisclaimer && (
+
+
+
+
+
+
+
+
+
+
)}
diff --git a/src/legacy/core_plugins/kibana/public/home/home_ng_wrapper.html b/src/legacy/core_plugins/kibana/public/home/home_ng_wrapper.html
deleted file mode 100644
index 645855766fab8..0000000000000
--- a/src/legacy/core_plugins/kibana/public/home/home_ng_wrapper.html
+++ /dev/null
@@ -1,5 +0,0 @@
-
diff --git a/src/legacy/core_plugins/kibana/public/home/index.js b/src/legacy/core_plugins/kibana/public/home/index.js
deleted file mode 100644
index 01f94b8ee4368..0000000000000
--- a/src/legacy/core_plugins/kibana/public/home/index.js
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Licensed to Elasticsearch B.V. under one or more contributor
- * license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright
- * ownership. Elasticsearch B.V. licenses this file to you under
- * the Apache License, Version 2.0 (the "License"); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-import { getServices } from './kibana_services';
-import template from './home_ng_wrapper.html';
-import {
- HomeApp
-} from './components/home_app';
-import { i18n } from '@kbn/i18n';
-
-const { wrapInI18nContext, uiRoutes, uiModules } = getServices();
-
-const app = uiModules.get('apps/home', []);
-app.directive('homeApp', function (reactDirective) {
- return reactDirective(wrapInI18nContext(HomeApp));
-});
-
-const homeTitle = i18n.translate('kbn.home.breadcrumbs.homeTitle', { defaultMessage: 'Home' });
-
-function getRoute() {
- return {
- template,
- resolve: {
- directories: () => getServices().getFeatureCatalogueEntries()
- },
- controller($scope, $route) {
- const { chrome, addBasePath } = getServices();
- $scope.directories = $route.current.locals.directories;
- $scope.recentlyAccessed = chrome.recentlyAccessed.get().map(item => {
- item.link = addBasePath(item.link);
- return item;
- });
- },
- k7Breadcrumbs: () => [
- { text: homeTitle },
- ]
- };
-}
-
-// All routing will be handled inside HomeApp via react, we just need to make sure angular doesn't
-// redirect us to the default page by encountering a url it isn't marked as being able to handle.
-uiRoutes.when('/home', getRoute());
-uiRoutes.when('/home/feature_directory', getRoute());
-uiRoutes.when('/home/tutorial_directory/:tab?', getRoute());
-uiRoutes.when('/home/tutorial/:id', getRoute());
diff --git a/src/legacy/core_plugins/kibana/public/home/index.ts b/src/legacy/core_plugins/kibana/public/home/index.ts
new file mode 100644
index 0000000000000..4ebf719b86233
--- /dev/null
+++ b/src/legacy/core_plugins/kibana/public/home/index.ts
@@ -0,0 +1,80 @@
+/*
+ * 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 { FeatureCatalogueRegistryProvider } from 'ui/registry/feature_catalogue';
+import { npSetup, npStart } from 'ui/new_platform';
+import chrome from 'ui/chrome';
+import { IPrivate } from 'ui/private';
+import { HomePlugin, LegacyAngularInjectedDependencies } from './plugin';
+import { createUiStatsReporter, METRIC_TYPE } from '../../../ui_metric/public';
+import { start as data } from '../../../data/public/legacy';
+import { TelemetryOptInProvider } from '../../../telemetry/public/services';
+import { localApplicationService } from '../local_application_service';
+
+export const trackUiMetric = createUiStatsReporter('Kibana_home');
+
+/**
+ * Get dependencies relying on the global angular context.
+ * They also have to get resolved together with the legacy imports above
+ */
+async function getAngularDependencies(): Promise {
+ const injector = await chrome.dangerouslyGetActiveInjector();
+
+ const Private = injector.get('Private');
+
+ const telemetryEnabled = npStart.core.injectedMetadata.getInjectedVar('telemetryEnabled');
+ const telemetryBanner = npStart.core.injectedMetadata.getInjectedVar('telemetryBanner');
+ const telemetryOptInProvider = Private(TelemetryOptInProvider);
+
+ return {
+ telemetryOptInProvider,
+ shouldShowTelemetryOptIn:
+ telemetryEnabled && telemetryBanner && !telemetryOptInProvider.getOptIn(),
+ };
+}
+
+let copiedLegacyCatalogue = false;
+
+(async () => {
+ const instance = new HomePlugin();
+ instance.setup(npSetup.core, {
+ __LEGACY: {
+ trackUiMetric,
+ metadata: npStart.core.injectedMetadata.getLegacyMetadata(),
+ METRIC_TYPE,
+ getFeatureCatalogueEntries: async () => {
+ if (!copiedLegacyCatalogue) {
+ const injector = await chrome.dangerouslyGetActiveInjector();
+ const Private = injector.get('Private');
+ // Merge legacy registry with new registry
+ (Private(FeatureCatalogueRegistryProvider as any) as any).inTitleOrder.map(
+ npSetup.plugins.feature_catalogue.register
+ );
+ copiedLegacyCatalogue = true;
+ }
+ return npStart.plugins.feature_catalogue.get();
+ },
+ getAngularDependencies,
+ localApplicationService,
+ },
+ });
+ instance.start(npStart.core, {
+ data,
+ });
+})();
diff --git a/src/legacy/core_plugins/kibana/public/home/kibana_services.ts b/src/legacy/core_plugins/kibana/public/home/kibana_services.ts
index b9f2ae1cfa7e8..6189204ee4cfc 100644
--- a/src/legacy/core_plugins/kibana/public/home/kibana_services.ts
+++ b/src/legacy/core_plugins/kibana/public/home/kibana_services.ts
@@ -17,69 +17,63 @@
* under the License.
*/
-// @ts-ignore
-import { toastNotifications, banners } from 'ui/notify';
-import { kfetch } from 'ui/kfetch';
-import chrome from 'ui/chrome';
+import {
+ ChromeStart,
+ DocLinksStart,
+ HttpStart,
+ LegacyNavLink,
+ NotificationsSetup,
+ OverlayStart,
+ SavedObjectsClientContract,
+ UiSettingsClientContract,
+ UiSettingsState,
+} from 'kibana/public';
+import { UiStatsMetricType } from '@kbn/analytics';
+import { FeatureCatalogueEntry } from '../../../../../plugins/feature_catalogue/public';
-import { wrapInI18nContext } from 'ui/i18n';
+export interface HomeKibanaServices {
+ indexPatternService: any;
+ getFeatureCatalogueEntries: () => Promise;
+ metadata: {
+ app: unknown;
+ bundleId: string;
+ nav: LegacyNavLink[];
+ version: string;
+ branch: string;
+ buildNum: number;
+ buildSha: string;
+ basePath: string;
+ serverName: string;
+ devMode: boolean;
+ uiSettings: { defaults: UiSettingsState; user?: UiSettingsState | undefined };
+ };
+ getInjected: (name: string, defaultValue?: any) => unknown;
+ chrome: ChromeStart;
+ telemetryOptInProvider: any;
+ uiSettings: UiSettingsClientContract;
+ http: HttpStart;
+ savedObjectsClient: SavedObjectsClientContract;
+ toastNotifications: NotificationsSetup['toasts'];
+ banners: OverlayStart['banners'];
+ METRIC_TYPE: any;
+ trackUiMetric: (type: UiStatsMetricType, eventNames: string | string[], count?: number) => void;
+ getBasePath: () => string;
+ shouldShowTelemetryOptIn: boolean;
+ docLinks: DocLinksStart;
+ addBasePath: (url: string) => string;
+}
-// @ts-ignore
-import { uiModules as modules } from 'ui/modules';
-import routes from 'ui/routes';
-import { npSetup, npStart } from 'ui/new_platform';
-import { IPrivate } from 'ui/private';
-import { FeatureCatalogueRegistryProvider } from 'ui/registry/feature_catalogue';
-import { createUiStatsReporter, METRIC_TYPE } from '../../../ui_metric/public';
-import { TelemetryOptInProvider } from '../../../telemetry/public/services';
-import { start as data } from '../../../data/public/legacy';
+let services: HomeKibanaServices | null = null;
-let shouldShowTelemetryOptIn: boolean;
-let telemetryOptInProvider: any;
+export function setServices(newServices: HomeKibanaServices) {
+ services = newServices;
+}
export function getServices() {
- return {
- getInjected: npStart.core.injectedMetadata.getInjectedVar,
- metadata: npStart.core.injectedMetadata.getLegacyMetadata(),
- docLinks: npStart.core.docLinks,
-
- uiRoutes: routes,
- uiModules: modules,
-
- savedObjectsClient: npStart.core.savedObjects.client,
- chrome: npStart.core.chrome,
- uiSettings: npStart.core.uiSettings,
- addBasePath: npStart.core.http.basePath.prepend,
- getBasePath: npStart.core.http.basePath.get,
-
- indexPatternService: data.indexPatterns.indexPatterns,
- shouldShowTelemetryOptIn,
- telemetryOptInProvider,
- getFeatureCatalogueEntries: async () => {
- const injector = await chrome.dangerouslyGetActiveInjector();
- const Private = injector.get('Private');
- // Merge legacy registry with new registry
- (Private(FeatureCatalogueRegistryProvider as any) as any).inTitleOrder.map(
- npSetup.plugins.feature_catalogue.register
- );
- return npStart.plugins.feature_catalogue.get();
- },
-
- trackUiMetric: createUiStatsReporter('Kibana_home'),
- METRIC_TYPE,
-
- toastNotifications,
- banners,
- kfetch,
- wrapInI18nContext,
- };
+ if (!services) {
+ throw new Error(
+ 'Kibana services not set - are you trying to import this module from outside of the home app?'
+ );
+ }
+ return services;
}
-
-modules.get('kibana').run((Private: IPrivate) => {
- const telemetryEnabled = npStart.core.injectedMetadata.getInjectedVar('telemetryEnabled');
- const telemetryBanner = npStart.core.injectedMetadata.getInjectedVar('telemetryBanner');
-
- telemetryOptInProvider = Private(TelemetryOptInProvider);
- shouldShowTelemetryOptIn =
- telemetryEnabled && telemetryBanner && !telemetryOptInProvider.getOptIn();
-});
diff --git a/src/legacy/core_plugins/kibana/public/home/plugin.ts b/src/legacy/core_plugins/kibana/public/home/plugin.ts
new file mode 100644
index 0000000000000..2a2ea371d7f3b
--- /dev/null
+++ b/src/legacy/core_plugins/kibana/public/home/plugin.ts
@@ -0,0 +1,103 @@
+/*
+ * 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 { CoreSetup, CoreStart, LegacyNavLink, Plugin, UiSettingsState } from 'kibana/public';
+import { UiStatsMetricType } from '@kbn/analytics';
+
+import { DataStart } from '../../../data/public';
+import { LocalApplicationService } from '../local_application_service';
+import { setServices } from './kibana_services';
+import { FeatureCatalogueEntry } from '../../../../../plugins/feature_catalogue/public';
+
+export interface LegacyAngularInjectedDependencies {
+ telemetryOptInProvider: any;
+ shouldShowTelemetryOptIn: boolean;
+}
+
+export interface HomePluginStartDependencies {
+ data: DataStart;
+}
+
+export interface HomePluginSetupDependencies {
+ __LEGACY: {
+ trackUiMetric: (type: UiStatsMetricType, eventNames: string | string[], count?: number) => void;
+ METRIC_TYPE: any;
+ metadata: {
+ app: unknown;
+ bundleId: string;
+ nav: LegacyNavLink[];
+ version: string;
+ branch: string;
+ buildNum: number;
+ buildSha: string;
+ basePath: string;
+ serverName: string;
+ devMode: boolean;
+ uiSettings: { defaults: UiSettingsState; user?: UiSettingsState | undefined };
+ };
+ getFeatureCatalogueEntries: () => Promise;
+ getAngularDependencies: () => Promise;
+ localApplicationService: LocalApplicationService;
+ };
+}
+
+export class HomePlugin implements Plugin {
+ private dataStart: DataStart | null = null;
+ private savedObjectsClient: any = null;
+
+ setup(
+ core: CoreSetup,
+ {
+ __LEGACY: { localApplicationService, getAngularDependencies, ...legacyServices },
+ }: HomePluginSetupDependencies
+ ) {
+ localApplicationService.register({
+ id: 'home',
+ title: 'Home',
+ mount: async ({ core: contextCore }, params) => {
+ const angularDependencies = await getAngularDependencies();
+ setServices({
+ ...legacyServices,
+ http: contextCore.http,
+ toastNotifications: core.notifications.toasts,
+ banners: contextCore.overlays.banners,
+ getInjected: core.injectedMetadata.getInjectedVar,
+ docLinks: contextCore.docLinks,
+ savedObjectsClient: this.savedObjectsClient!,
+ chrome: contextCore.chrome,
+ uiSettings: core.uiSettings,
+ addBasePath: core.http.basePath.prepend,
+ getBasePath: core.http.basePath.get,
+ indexPatternService: this.dataStart!.indexPatterns.indexPatterns,
+ ...angularDependencies,
+ });
+ const { renderApp } = await import('./render_app');
+ return await renderApp(params.element);
+ },
+ });
+ }
+
+ start(core: CoreStart, { data }: HomePluginStartDependencies) {
+ // TODO is this really the right way? I though the app context would give us those
+ this.dataStart = data;
+ this.savedObjectsClient = core.savedObjects.client;
+ }
+
+ stop() {}
+}
diff --git a/src/legacy/core_plugins/kibana/public/home/render_app.tsx b/src/legacy/core_plugins/kibana/public/home/render_app.tsx
new file mode 100644
index 0000000000000..a8c35144a45b0
--- /dev/null
+++ b/src/legacy/core_plugins/kibana/public/home/render_app.tsx
@@ -0,0 +1,38 @@
+/*
+ * 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 React from 'react';
+import { render, unmountComponentAtNode } from 'react-dom';
+import { i18n } from '@kbn/i18n';
+// @ts-ignore
+import { HomeApp } from './components/home_app';
+import { getServices } from './kibana_services';
+
+export const renderApp = async (element: HTMLElement) => {
+ const homeTitle = i18n.translate('kbn.home.breadcrumbs.homeTitle', { defaultMessage: 'Home' });
+ const { getFeatureCatalogueEntries, chrome } = getServices();
+ const directories = await getFeatureCatalogueEntries();
+ chrome.setBreadcrumbs([{ text: homeTitle }]);
+
+ render( , element);
+
+ return () => {
+ unmountComponentAtNode(element);
+ };
+};
diff --git a/src/legacy/core_plugins/kibana/public/home/sample_data_client.js b/src/legacy/core_plugins/kibana/public/home/sample_data_client.js
index 9411373004c25..eca88604a559d 100644
--- a/src/legacy/core_plugins/kibana/public/home/sample_data_client.js
+++ b/src/legacy/core_plugins/kibana/public/home/sample_data_client.js
@@ -26,11 +26,11 @@ function clearIndexPatternsCache() {
}
export async function listSampleDataSets() {
- return await getServices().kfetch({ method: 'GET', pathname: sampleDataUrl });
+ return await getServices().http.get(sampleDataUrl);
}
export async function installSampleDataSet(id, sampleDataDefaultIndex) {
- await getServices().kfetch({ method: 'POST', pathname: `${sampleDataUrl}/${id}` });
+ await getServices().http.post(`${sampleDataUrl}/${id}`);
if (getServices().uiSettings.isDefault('defaultIndex')) {
getServices().uiSettings.set('defaultIndex', sampleDataDefaultIndex);
@@ -40,7 +40,7 @@ export async function installSampleDataSet(id, sampleDataDefaultIndex) {
}
export async function uninstallSampleDataSet(id, sampleDataDefaultIndex) {
- await getServices().kfetch({ method: 'DELETE', pathname: `${sampleDataUrl}/${id}` });
+ await getServices().http.delete(`${sampleDataUrl}/${id}`);
const uiSettings = getServices().uiSettings;
diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/__jest__/objects_table.test.js b/src/legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/__jest__/objects_table.test.js
index 39a9f7cd98a57..5956b6c306b0e 100644
--- a/src/legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/__jest__/objects_table.test.js
+++ b/src/legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/__jest__/objects_table.test.js
@@ -106,10 +106,10 @@ const allSavedObjects = [
},
];
-const $http = () => {};
+const $http = () => { };
$http.post = jest.fn().mockImplementation(() => []);
const defaultProps = {
- goInspectObject: () => {},
+ goInspectObject: () => { },
confirmModalPromise: jest.fn(),
savedObjectsClient: {
find: jest.fn(),
@@ -256,7 +256,6 @@ describe('ObjectsTable', () => {
const mockSavedObjects = mockSelectedSavedObjects.map(obj => ({
_id: obj.id,
- _type: obj._type,
_source: {},
}));
@@ -297,7 +296,6 @@ describe('ObjectsTable', () => {
const mockSavedObjects = mockSelectedSavedObjects.map(obj => ({
_id: obj.id,
- _type: obj._type,
_source: {},
}));
diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/__jest__/extract_export_details.test.ts b/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/__jest__/extract_export_details.test.ts
index a6ed2e36839f4..4ecc3583e76ce 100644
--- a/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/__jest__/extract_export_details.test.ts
+++ b/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/__jest__/extract_export_details.test.ts
@@ -62,7 +62,10 @@ describe('extractExportDetails', () => {
[
[
objLine('1', 'index-pattern'),
- detailsLine(1, [{ id: '2', type: 'index-pattern' }, { id: '3', type: 'index-pattern' }]),
+ detailsLine(1, [
+ { id: '2', type: 'index-pattern' },
+ { id: '3', type: 'index-pattern' },
+ ]),
].join(''),
],
{
@@ -75,7 +78,10 @@ describe('extractExportDetails', () => {
expect(result).toEqual({
exportedCount: 1,
missingRefCount: 2,
- missingReferences: [{ id: '2', type: 'index-pattern' }, { id: '3', type: 'index-pattern' }],
+ missingReferences: [
+ { id: '2', type: 'index-pattern' },
+ { id: '3', type: 'index-pattern' },
+ ],
});
});
diff --git a/src/legacy/core_plugins/kibana/public/management/sections/settings/components/field/__snapshots__/field.test.js.snap b/src/legacy/core_plugins/kibana/public/management/sections/settings/components/field/__snapshots__/field.test.js.snap
index 08a8cf3898e94..8e7ae33a60068 100644
--- a/src/legacy/core_plugins/kibana/public/management/sections/settings/components/field/__snapshots__/field.test.js.snap
+++ b/src/legacy/core_plugins/kibana/public/management/sections/settings/components/field/__snapshots__/field.test.js.snap
@@ -463,7 +463,7 @@ exports[`Field for boolean setting should render as read only if saving is disab
display="row"
error={null}
fullWidth={false}
- hasChildLabel={true}
+ hasChildLabel={false}
hasEmptyLabelSpace={false}
helpText={null}
isInvalid={false}
@@ -557,7 +557,7 @@ exports[`Field for boolean setting should render as read only with help text if
display="row"
error={null}
fullWidth={false}
- hasChildLabel={true}
+ hasChildLabel={false}
hasEmptyLabelSpace={false}
helpText={
diff --git a/src/legacy/core_plugins/kibana/public/management/sections/settings/components/field/field.js b/src/legacy/core_plugins/kibana/public/management/sections/settings/components/field/field.js
index e52f789eb8af7..a953d09906ed1 100644
--- a/src/legacy/core_plugins/kibana/public/management/sections/settings/components/field/field.js
+++ b/src/legacy/core_plugins/kibana/public/management/sections/settings/components/field/field.js
@@ -195,7 +195,7 @@ export class Field extends PureComponent {
this.setState({
unsavedValue: newUnsavedValue,
isInvalid,
- error
+ error,
});
};
@@ -764,6 +764,7 @@ export class Field extends PureComponent {
helpText={this.renderHelpText(setting)}
describedByIds={[`${setting.name}-aria`]}
className="mgtAdvancedSettings__fieldRow"
+ hasChildLabel={setting.type !== 'boolean'}
>
{this.renderField(setting)}
diff --git a/src/legacy/core_plugins/kibana/public/visualize/editor/editor.js b/src/legacy/core_plugins/kibana/public/visualize/editor/editor.js
index c0a7615f207ed..58a0075e94b99 100644
--- a/src/legacy/core_plugins/kibana/public/visualize/editor/editor.js
+++ b/src/legacy/core_plugins/kibana/public/visualize/editor/editor.js
@@ -31,7 +31,6 @@ import editorTemplate from './editor.html';
import { DashboardConstants } from '../../dashboard/dashboard_constants';
import { VisualizeConstants } from '../visualize_constants';
import { getEditBreadcrumbs, getCreateBreadcrumbs } from '../breadcrumbs';
-import { extractTimeFilter, changeTimeFilter } from '../../../../data/public';
import { addHelpMenuToAppChrome } from '../help_menu/help_menu_util';
@@ -343,23 +342,6 @@ function VisEditor(
queryFilter.setFilters(filters);
};
- $scope.onCancelApplyFilters = () => {
- $scope.state.$newFilters = [];
- };
-
- $scope.onApplyFilters = filters => {
- const { timeRangeFilter, restOfFilters } = extractTimeFilter($scope.indexPattern.timeFieldName, filters);
- queryFilter.addFilters(restOfFilters);
- if (timeRangeFilter) changeTimeFilter(timefilter, timeRangeFilter);
- $scope.state.$newFilters = [];
- };
-
- $scope.$watch('state.$newFilters', (filters = []) => {
- if (filters.length === 1) {
- $scope.onApplyFilters(filters);
- }
- });
-
$scope.showSaveQuery = capabilities.visualize.saveQuery;
$scope.$watch(() => capabilities.visualize.saveQuery, (newCapability) => {
@@ -458,6 +440,12 @@ function VisEditor(
next: $scope.fetch
}));
+ subscriptions.add(subscribeWithScope($scope, timefilter.getAutoRefreshFetch$(), {
+ next: () => {
+ $scope.vis.forceReload();
+ }
+ }));
+
$scope.$on('$destroy', function () {
if ($scope._handler) {
$scope._handler.destroy();
diff --git a/src/legacy/core_plugins/kibana/public/visualize/embeddable/visualize_embeddable.ts b/src/legacy/core_plugins/kibana/public/visualize/embeddable/visualize_embeddable.ts
index ef9c9a00f980b..60cf7c7ec1928 100644
--- a/src/legacy/core_plugins/kibana/public/visualize/embeddable/visualize_embeddable.ts
+++ b/src/legacy/core_plugins/kibana/public/visualize/embeddable/visualize_embeddable.ts
@@ -17,36 +17,53 @@
* under the License.
*/
-import _ from 'lodash';
-import { EmbeddedVisualizeHandler } from 'ui/visualize/loader/embedded_visualize_handler';
+import _, { forEach } from 'lodash';
+import { StaticIndexPattern } from 'ui/index_patterns';
+import { PersistedState } from 'ui/persisted_state';
import { Subscription } from 'rxjs';
import * as Rx from 'rxjs';
-import { Filter } from '@kbn/es-query';
-import { TimeRange, onlyDisabledFiltersChanged } from '../../../../../../plugins/data/public';
-import { Query } from '../../../../data/public';
+import { buildPipeline } from 'ui/visualize/loader/pipeline_helpers';
+import { SavedObject } from 'ui/saved_objects/saved_object';
+import { Vis } from 'ui/vis';
+import { SearchSource } from 'ui/courier';
+import { queryGeohashBounds } from 'ui/visualize/loader/utils';
+import { getTableAggs } from 'ui/visualize/loader/pipeline_helpers/utilities';
+import { AppState } from 'ui/state_management/app_state';
+import { npStart } from 'ui/new_platform';
+import { IExpressionLoaderParams } from '../../../../expressions/public/np_ready/public/types';
+import { start as expressions } from '../../../../expressions/public/legacy';
import { VISUALIZE_EMBEDDABLE_TYPE } from './constants';
-
+import { Query } from '../../../../data/public';
+import {
+ TimeRange,
+ onlyDisabledFiltersChanged,
+ esFilters,
+} from '../../../../../../plugins/data/public';
import {
- AppState,
- Container,
- Embeddable,
EmbeddableInput,
EmbeddableOutput,
- PersistedState,
- StaticIndexPattern,
- VisSavedObject,
- VisualizeLoader,
- VisualizeLoaderParams,
- VisualizeUpdateParams,
-} from '../kibana_services';
+ Embeddable,
+ Container,
+ APPLY_FILTER_TRIGGER,
+} from '../../../../../../plugins/embeddable/public';
+import { dispatchRenderComplete } from '../../../../../../plugins/kibana_utils/public';
+import { mapAndFlattenFilters } from '../../../../../../plugins/data/public';
const getKeys = (o: T): Array => Object.keys(o) as Array;
+export interface VisSavedObject extends SavedObject {
+ vis: Vis;
+ description?: string;
+ searchSource: SearchSource;
+ title: string;
+ uiStateJSON?: string;
+ destroy: () => void;
+}
+
export interface VisualizeEmbeddableConfiguration {
savedVisualization: VisSavedObject;
indexPatterns?: StaticIndexPattern[];
editUrl: string;
- loader: VisualizeLoader;
editable: boolean;
appState?: AppState;
uiState?: PersistedState;
@@ -55,7 +72,7 @@ export interface VisualizeEmbeddableConfiguration {
export interface VisualizeInput extends EmbeddableInput {
timeRange?: TimeRange;
query?: Query;
- filters?: Filter[];
+ filters?: esFilters.Filter[];
vis?: {
colors?: { [key: string]: string };
};
@@ -70,24 +87,28 @@ export interface VisualizeOutput extends EmbeddableOutput {
visTypeName: string;
}
+type ExpressionLoader = InstanceType;
+
export class VisualizeEmbeddable extends Embeddable {
+ private handler?: ExpressionLoader;
private savedVisualization: VisSavedObject;
- private loader: VisualizeLoader;
private appState: AppState | undefined;
private uiState: PersistedState;
- private handler?: EmbeddedVisualizeHandler;
private timeRange?: TimeRange;
private query?: Query;
private title?: string;
- private filters?: Filter[];
+ private filters?: esFilters.Filter[];
private visCustomizations: VisualizeInput['vis'];
- private subscription: Subscription;
+ private subscriptions: Subscription[] = [];
+ private expression: string = '';
+ private actions: any = {};
+ private vis: Vis;
+ private domNode: any;
public readonly type = VISUALIZE_EMBEDDABLE_TYPE;
constructor(
{
savedVisualization,
- loader,
editUrl,
indexPatterns,
editable,
@@ -109,8 +130,12 @@ export class VisualizeEmbeddable extends Embeddable {
- this.handleChanges();
- });
+ this.subscriptions.push(
+ Rx.merge(this.getOutput$(), this.getInput$()).subscribe(() => {
+ this.handleChanges();
+ })
+ );
}
public getVisualizationDescription() {
return this.savedVisualization.description;
}
- public getInspectorAdapters() {
+ public getInspectorAdapters = () => {
if (!this.handler) {
return undefined;
}
- return this.handler.inspectorAdapters;
- }
+ return this.handler.inspect();
+ };
+
+ public openInspector = () => {
+ if (this.handler) {
+ return this.handler.openInspector(this.getTitle() || '');
+ }
+ };
/**
* Transfers all changes in the containerState.customization into
@@ -167,87 +202,148 @@ export class VisualizeEmbeddable extends Embeddable {
+ if (event.disabled || !eventName) {
+ return;
+ } else {
+ this.actions[eventName] = event.defaultAction;
+ }
+ });
+
+ // This is a hack to give maps visualizations access to data in the
+ // globalState, since they can no longer access it via searchSource.
+ // TODO: Remove this as a part of elastic/kibana#30593
+ this.vis.API.getGeohashBounds = () => {
+ return queryGeohashBounds(this.savedVisualization.vis, {
+ filters: this.filters,
+ query: this.query,
+ searchSource: this.savedVisualization.searchSource,
+ });
};
+
+ // this is a hack to make editor still work, will be removed once we clean up editor
+ this.vis.hasInspector = () => {
+ const visTypesWithoutInspector = ['markdown', 'input_control_vis', 'metrics', 'vega'];
+ if (visTypesWithoutInspector.includes(this.vis.type.name)) {
+ return false;
+ }
+ return this.getInspectorAdapters();
+ };
+
+ this.vis.openInspector = this.openInspector;
+
+ const div = document.createElement('div');
+ div.className = `visualize panel-content panel-content--fullWidth`;
+ domNode.appendChild(div);
+ this.domNode = div;
+
+ this.handler = new expressions.ExpressionLoader(this.domNode);
+
+ this.subscriptions.push(
+ this.handler.events$.subscribe(async event => {
+ if (this.actions[event.name]) {
+ event.data.aggConfigs = getTableAggs(this.vis);
+ const filters: esFilters.Filter[] = this.actions[event.name](event.data) || [];
+ const mappedFilters = mapAndFlattenFilters(filters);
+ const timeFieldName = this.vis.indexPattern.timeFieldName;
+
+ npStart.plugins.uiActions.executeTriggerActions(APPLY_FILTER_TRIGGER, {
+ embeddable: this,
+ filters: mappedFilters,
+ timeFieldName,
+ });
+ }
+ })
+ );
+
+ div.setAttribute('data-title', this.output.title || '');
+
if (this.savedVisualization.description) {
- dataAttrs.description = this.savedVisualization.description;
+ div.setAttribute('data-description', this.savedVisualization.description);
}
- const handlerParams: VisualizeLoaderParams = {
- appState: this.appState,
- uiState: this.uiState,
- // Append visualization to container instead of replacing its content
- append: true,
- timeRange: _.cloneDeep(this.input.timeRange),
- query: this.query,
- filters: this.filters,
- cssClass: `panel-content panel-content--fullWidth`,
- dataAttrs,
- };
+ div.setAttribute('data-test-subj', 'visualizationLoader');
+ div.setAttribute('data-shared-item', '');
+ div.setAttribute('data-rendering-count', '0');
+ div.setAttribute('data-render-complete', 'false');
+
+ this.subscriptions.push(
+ this.handler.loading$.subscribe(() => {
+ div.setAttribute('data-render-complete', 'false');
+ div.setAttribute('data-loading', '');
+ })
+ );
- this.handler = this.loader.embedVisualizationWithSavedObject(
- domNode,
- this.savedVisualization,
- handlerParams
+ this.subscriptions.push(
+ this.handler.render$.subscribe(count => {
+ div.removeAttribute('data-loading');
+ div.setAttribute('data-render-complete', 'true');
+ div.setAttribute('data-rendering-count', count.toString());
+ dispatchRenderComplete(div);
+ })
);
+
+ this.updateHandler();
}
public destroy() {
super.destroy();
- if (this.subscription) {
- this.subscription.unsubscribe();
- }
+ this.subscriptions.forEach(s => s.unsubscribe());
this.uiState.off('change', this.uiStateChangeHandler);
+ this.savedVisualization.vis.removeListener('reload', this.reload);
+ this.savedVisualization.vis.removeListener('update', this.handleVisUpdate);
this.savedVisualization.destroy();
if (this.handler) {
this.handler.destroy();
@@ -255,12 +351,44 @@ export class VisualizeEmbeddable extends Embeddable {
+ this.handleVisUpdate();
+ };
+
+ private async updateHandler() {
+ const expressionParams: IExpressionLoaderParams = {
+ searchContext: {
+ type: 'kibana_context',
+ timeRange: this.timeRange,
+ query: this.input.query,
+ filters: this.input.filters,
+ },
+ extraHandlers: {
+ vis: this.vis,
+ uiState: this.uiState,
+ },
+ };
+ this.expression = await buildPipeline(this.vis, {
+ searchSource: this.savedVisualization.searchSource,
+ timeRange: this.timeRange,
+ });
+
+ this.vis.filters = { timeRange: this.timeRange };
+
if (this.handler) {
- this.handler.reload();
+ this.handler.update(this.expression, expressionParams);
}
}
+ private handleVisUpdate = async () => {
+ if (this.appState) {
+ this.appState.vis = this.savedVisualization.vis.getState();
+ this.appState.save();
+ }
+
+ this.updateHandler();
+ };
+
private uiStateChangeHandler = () => {
this.updateInput({
...this.uiState.toJSON(),
diff --git a/src/legacy/core_plugins/kibana/public/visualize/embeddable/visualize_embeddable_factory.tsx b/src/legacy/core_plugins/kibana/public/visualize/embeddable/visualize_embeddable_factory.tsx
index c1ce4f67cfdb3..15ad9a33232ef 100644
--- a/src/legacy/core_plugins/kibana/public/visualize/embeddable/visualize_embeddable_factory.tsx
+++ b/src/legacy/core_plugins/kibana/public/visualize/embeddable/visualize_embeddable_factory.tsx
@@ -36,7 +36,6 @@ import {
EmbeddableFactory,
EmbeddableOutput,
ErrorEmbeddable,
- getVisualizeLoader,
VisSavedObject,
} from '../kibana_services';
@@ -131,7 +130,6 @@ export class VisualizeEmbeddableFactory extends EmbeddableFactory<
const visId = savedObject.id as string;
const editUrl = visId ? addBasePath(`/app/kibana${savedVisualizations.urlFor(visId)}`) : '';
- const loader = await getVisualizeLoader();
const isLabsEnabled = config.get('visualize:enableLabs');
if (!isLabsEnabled && savedObject.vis.type.stage === 'experimental') {
@@ -143,7 +141,6 @@ export class VisualizeEmbeddableFactory extends EmbeddableFactory<
return new VisualizeEmbeddable(
{
savedVisualization: savedObject,
- loader,
indexPatterns,
editUrl,
editable: this.isEditable(),
diff --git a/src/legacy/core_plugins/kibana/public/visualize/kibana_services.ts b/src/legacy/core_plugins/kibana/public/visualize/kibana_services.ts
index 7e8435bbdc65e..5c6d06b5eaeb6 100644
--- a/src/legacy/core_plugins/kibana/public/visualize/kibana_services.ts
+++ b/src/legacy/core_plugins/kibana/public/visualize/kibana_services.ts
@@ -42,7 +42,7 @@ import { timefilter } from 'ui/timefilter';
// Saved objects
import { SavedObjectsClientProvider } from 'ui/saved_objects';
// @ts-ignore
-import { SavedObjectProvider } from 'ui/saved_objects/saved_object';
+import { SavedObject, SavedObjectProvider } from 'ui/saved_objects/saved_object';
import { SavedObjectRegistryProvider } from 'ui/saved_objects/saved_object_registry';
import { createUiStatsReporter, METRIC_TYPE } from '../../../ui_metric/public';
@@ -105,7 +105,6 @@ export { absoluteToParsedUrl } from 'ui/url/absolute_to_parsed_url';
export { KibanaParsedUrl } from 'ui/url/kibana_parsed_url';
export { migrateLegacyQuery } from 'ui/utils/migrate_legacy_query';
export { subscribeWithScope } from 'ui/utils/subscribe_with_scope';
-export { getVisualizeLoader } from 'ui/visualize/loader';
export { SavedObjectSaveModal } from 'ui/saved_objects/components/saved_object_save_modal';
export {
Container,
@@ -121,12 +120,8 @@ export { METRIC_TYPE };
export { StaticIndexPattern } from 'ui/index_patterns';
export { AppState } from 'ui/state_management/app_state';
export { VisType } from 'ui/vis';
-export { VisualizeLoader } from 'ui/visualize/loader';
-export {
- VisSavedObject,
- VisualizeLoaderParams,
- VisualizeUpdateParams,
-} from 'ui/visualize/loader/types';
// export const
export { FeatureCatalogueCategory } from 'ui/registry/feature_catalogue';
+
+export { VisSavedObject } from './embeddable/visualize_embeddable';
diff --git a/src/legacy/core_plugins/kibana/public/visualize/listing/visualize_listing_table.js b/src/legacy/core_plugins/kibana/public/visualize/listing/visualize_listing_table.js
index fbd70a0d8c0f7..efab03303aa80 100644
--- a/src/legacy/core_plugins/kibana/public/visualize/listing/visualize_listing_table.js
+++ b/src/legacy/core_plugins/kibana/public/visualize/listing/visualize_listing_table.js
@@ -21,13 +21,13 @@ import React, { Component, Fragment } from 'react';
import PropTypes from 'prop-types';
import { FormattedMessage } from '@kbn/i18n/react';
import { i18n } from '@kbn/i18n';
-import { TableListView } from './../../table_list_view';
+import { TableListView } from '../../../../../../../src/plugins/kibana_react/public';
import { EuiIcon, EuiBetaBadge, EuiLink, EuiButton, EuiEmptyPrompt } from '@elastic/eui';
import { getServices } from '../kibana_services';
-const { capabilities } = getServices();
+const { capabilities, toastNotifications, uiSettings } = getServices();
class VisualizeListingTable extends Component {
constructor(props) {
@@ -57,6 +57,8 @@ class VisualizeListingTable extends Component {
tableListTitle={i18n.translate('kbn.visualize.listing.table.listTitle', {
defaultMessage: 'Visualizations',
})}
+ toastNotifications={toastNotifications}
+ uiSettings={uiSettings}
/>
);
}
diff --git a/src/legacy/core_plugins/kibana/server/lib/kql_usage_collector/fetch.test.js b/src/legacy/core_plugins/kibana/server/lib/kql_usage_collector/fetch.test.js
index e8e95fd92dd11..a5db4602872ee 100644
--- a/src/legacy/core_plugins/kibana/server/lib/kql_usage_collector/fetch.test.js
+++ b/src/legacy/core_plugins/kibana/server/lib/kql_usage_collector/fetch.test.js
@@ -32,7 +32,6 @@ function setupMockCallCluster(optCount, language) {
if (optCount === null) {
return Promise.resolve({
_index: '.kibana_1',
- _type: 'doc',
_id: 'kql-telemetry:kql-telemetry',
found: false,
});
diff --git a/src/legacy/core_plugins/kibana/server/routes/api/management/saved_objects/scroll.js b/src/legacy/core_plugins/kibana/server/routes/api/management/saved_objects/scroll.js
index a2cc63b4b8679..6926fa72b0ae2 100644
--- a/src/legacy/core_plugins/kibana/server/routes/api/management/saved_objects/scroll.js
+++ b/src/legacy/core_plugins/kibana/server/routes/api/management/saved_objects/scroll.js
@@ -53,10 +53,8 @@ export function registerScrollForExportRoute(server) {
});
return objects.map(hit => {
- const type = hit.type;
return {
_id: hit.id,
- _type: type,
_source: hit.attributes,
_meta: {
savedObjectVersion: 2
diff --git a/src/legacy/core_plugins/navigation/public/top_nav_menu/top_nav_menu.test.tsx b/src/legacy/core_plugins/navigation/public/top_nav_menu/top_nav_menu.test.tsx
index 4f8c5d11f1916..9077de8910327 100644
--- a/src/legacy/core_plugins/navigation/public/top_nav_menu/top_nav_menu.test.tsx
+++ b/src/legacy/core_plugins/navigation/public/top_nav_menu/top_nav_menu.test.tsx
@@ -22,11 +22,15 @@ import { TopNavMenu } from './top_nav_menu';
import { TopNavMenuData } from './top_nav_menu_data';
import { shallowWithIntl } from 'test_utils/enzyme_helpers';
-import { timefilterServiceMock } from '../../../../core_plugins/data/public/timefilter/timefilter_service.mock';
-const timefilterSetupMock = timefilterServiceMock.createSetupContract();
-
jest.mock('ui/new_platform');
+const mockTimeHistory = {
+ add: () => {},
+ get: () => {
+ return [];
+ },
+};
+
const dataShim = {
ui: {
SearchBar: () =>
,
@@ -77,7 +81,7 @@ describe('TopNavMenu', () => {
);
diff --git a/src/legacy/core_plugins/newsfeed/constants.ts b/src/legacy/core_plugins/newsfeed/constants.ts
new file mode 100644
index 0000000000000..55a0c51c2ac65
--- /dev/null
+++ b/src/legacy/core_plugins/newsfeed/constants.ts
@@ -0,0 +1,23 @@
+/*
+ * 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 PLUGIN_ID = 'newsfeed';
+export const DEFAULT_SERVICE_URLROOT = 'https://feeds.elastic.co';
+export const DEV_SERVICE_URLROOT = 'https://feeds-staging.elastic.co';
+export const DEFAULT_SERVICE_PATH = '/kibana/v{VERSION}.json';
diff --git a/src/legacy/core_plugins/newsfeed/index.ts b/src/legacy/core_plugins/newsfeed/index.ts
new file mode 100644
index 0000000000000..cf8852be09a1e
--- /dev/null
+++ b/src/legacy/core_plugins/newsfeed/index.ts
@@ -0,0 +1,71 @@
+/*
+ * 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 { resolve } from 'path';
+import { LegacyPluginApi, LegacyPluginSpec, ArrayOrItem } from 'src/legacy/plugin_discovery/types';
+import { Legacy } from 'kibana';
+import { NewsfeedPluginInjectedConfig } from '../../../plugins/newsfeed/types';
+import {
+ PLUGIN_ID,
+ DEFAULT_SERVICE_URLROOT,
+ DEV_SERVICE_URLROOT,
+ DEFAULT_SERVICE_PATH,
+} from './constants';
+
+// eslint-disable-next-line import/no-default-export
+export default function(kibana: LegacyPluginApi): ArrayOrItem {
+ const pluginSpec: Legacy.PluginSpecOptions = {
+ id: PLUGIN_ID,
+ config(Joi: any) {
+ // NewsfeedPluginInjectedConfig in Joi form
+ return Joi.object({
+ enabled: Joi.boolean().default(true),
+ service: Joi.object({
+ pathTemplate: Joi.string().default(DEFAULT_SERVICE_PATH),
+ urlRoot: Joi.when('$prod', {
+ is: true,
+ then: Joi.string().default(DEFAULT_SERVICE_URLROOT),
+ otherwise: Joi.string().default(DEV_SERVICE_URLROOT),
+ }),
+ }).default(),
+ defaultLanguage: Joi.string().default('en'),
+ mainInterval: Joi.number().default(120 * 1000), // (2min) How often to retry failed fetches, and/or check if newsfeed items need to be refreshed from remote
+ fetchInterval: Joi.number().default(86400 * 1000), // (1day) How often to fetch remote and reset the last fetched time
+ }).default();
+ },
+ uiExports: {
+ styleSheetPaths: resolve(__dirname, 'public/index.scss'),
+ injectDefaultVars(server): NewsfeedPluginInjectedConfig {
+ const config = server.config();
+ return {
+ newsfeed: {
+ service: {
+ pathTemplate: config.get('newsfeed.service.pathTemplate') as string,
+ urlRoot: config.get('newsfeed.service.urlRoot') as string,
+ },
+ defaultLanguage: config.get('newsfeed.defaultLanguage') as string,
+ mainInterval: config.get('newsfeed.mainInterval') as number,
+ fetchInterval: config.get('newsfeed.fetchInterval') as number,
+ },
+ };
+ },
+ },
+ };
+ return new kibana.Plugin(pluginSpec);
+}
diff --git a/src/legacy/core_plugins/newsfeed/package.json b/src/legacy/core_plugins/newsfeed/package.json
new file mode 100644
index 0000000000000..d4d753f32b0f9
--- /dev/null
+++ b/src/legacy/core_plugins/newsfeed/package.json
@@ -0,0 +1,4 @@
+{
+ "name": "newsfeed",
+ "version": "kibana"
+}
diff --git a/src/legacy/core_plugins/newsfeed/public/index.scss b/src/legacy/core_plugins/newsfeed/public/index.scss
new file mode 100644
index 0000000000000..a77132379041c
--- /dev/null
+++ b/src/legacy/core_plugins/newsfeed/public/index.scss
@@ -0,0 +1,3 @@
+@import 'src/legacy/ui/public/styles/styling_constants';
+
+@import './np_ready/components/header_alert/_index';
diff --git a/src/legacy/core_plugins/newsfeed/public/np_ready/components/header_alert/_index.scss b/src/legacy/core_plugins/newsfeed/public/np_ready/components/header_alert/_index.scss
new file mode 100644
index 0000000000000..e25dbd25daaf5
--- /dev/null
+++ b/src/legacy/core_plugins/newsfeed/public/np_ready/components/header_alert/_index.scss
@@ -0,0 +1,27 @@
+@import '@elastic/eui/src/components/header/variables';
+
+.kbnNews__flyout {
+ top: $euiHeaderChildSize + 1px;
+ height: calc(100% - #{$euiHeaderChildSize});
+}
+
+.kbnNewsFeed__headerAlert.euiHeaderAlert {
+ margin-bottom: $euiSizeL;
+ padding: 0 $euiSizeS $euiSizeL;
+ border-bottom: $euiBorderThin;
+ border-top: none;
+
+ .euiHeaderAlert__title {
+ @include euiTitle('xs');
+ margin-bottom: $euiSizeS;
+ }
+
+ .euiHeaderAlert__text {
+ @include euiFontSizeS;
+ margin-bottom: $euiSize;
+ }
+
+ .euiHeaderAlert__action {
+ @include euiFontSizeS;
+ }
+}
diff --git a/src/legacy/core_plugins/newsfeed/public/np_ready/components/header_alert/header_alert.tsx b/src/legacy/core_plugins/newsfeed/public/np_ready/components/header_alert/header_alert.tsx
new file mode 100644
index 0000000000000..c3c3e4144fca8
--- /dev/null
+++ b/src/legacy/core_plugins/newsfeed/public/np_ready/components/header_alert/header_alert.tsx
@@ -0,0 +1,76 @@
+/*
+ * 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 React from 'react';
+import PropTypes from 'prop-types';
+import classNames from 'classnames';
+
+import { EuiFlexGroup, EuiFlexItem, EuiI18n } from '@elastic/eui';
+
+interface IEuiHeaderAlertProps {
+ action: JSX.Element;
+ className?: string;
+ date: string;
+ text: string;
+ title: string;
+ badge?: JSX.Element;
+ rest?: string[];
+}
+
+export const EuiHeaderAlert = ({
+ action,
+ className,
+ date,
+ text,
+ title,
+ badge,
+ ...rest
+}: IEuiHeaderAlertProps) => {
+ const classes = classNames('euiHeaderAlert', 'kbnNewsFeed__headerAlert', className);
+
+ const badgeContent = badge || null;
+
+ return (
+
+ {(dismiss: any) => (
+
+
+
+ {date}
+
+ {badgeContent}
+
+
+
{title}
+
{text}
+
{action}
+
+ )}
+
+ );
+};
+
+EuiHeaderAlert.propTypes = {
+ action: PropTypes.node,
+ className: PropTypes.string,
+ date: PropTypes.node.isRequired,
+ text: PropTypes.node,
+ title: PropTypes.node.isRequired,
+ badge: PropTypes.node,
+};
diff --git a/src/legacy/core_plugins/region_map/public/components/region_map_options.tsx b/src/legacy/core_plugins/region_map/public/components/region_map_options.tsx
index 9749c7fa8e2f9..8306b3274a914 100644
--- a/src/legacy/core_plugins/region_map/public/components/region_map_options.tsx
+++ b/src/legacy/core_plugins/region_map/public/components/region_map_options.tsx
@@ -82,7 +82,10 @@ function RegionMapOptions(props: RegionMapOptionsProps) {
const setField = useCallback(
(paramName: 'selectedJoinField', value: FileLayerField['name']) => {
if (stateParams.selectedLayer) {
- setValue(paramName, stateParams.selectedLayer.fields.find(f => f.name === value));
+ setValue(
+ paramName,
+ stateParams.selectedLayer.fields.find(f => f.name === value)
+ );
}
},
[setValue, stateParams.selectedLayer]
diff --git a/src/legacy/core_plugins/telemetry/common/constants.ts b/src/legacy/core_plugins/telemetry/common/constants.ts
index ab1397b2cc232..7b0c62276f290 100644
--- a/src/legacy/core_plugins/telemetry/common/constants.ts
+++ b/src/legacy/core_plugins/telemetry/common/constants.ts
@@ -51,7 +51,7 @@ export const LOCALSTORAGE_KEY = 'telemetry.data';
/**
* Link to the Elastic Telemetry privacy statement.
*/
-export const PRIVACY_STATEMENT_URL = `https://www.elastic.co/legal/telemetry-privacy-statement`;
+export const PRIVACY_STATEMENT_URL = `https://www.elastic.co/legal/privacy-statement`;
/**
* The type name used within the Monitoring index to publish localization stats.
@@ -59,6 +59,12 @@ export const PRIVACY_STATEMENT_URL = `https://www.elastic.co/legal/telemetry-pri
*/
export const KIBANA_LOCALIZATION_STATS_TYPE = 'localization';
+/**
+ * The type name used to publish telemetry plugin stats.
+ * @type {string}
+ */
+export const TELEMETRY_STATS_TYPE = 'telemetry';
+
/**
* UI metric usage type
* @type {string}
diff --git a/src/legacy/core_plugins/telemetry/index.ts b/src/legacy/core_plugins/telemetry/index.ts
index 3271373449eb3..149fa99938563 100644
--- a/src/legacy/core_plugins/telemetry/index.ts
+++ b/src/legacy/core_plugins/telemetry/index.ts
@@ -17,6 +17,7 @@
* under the License.
*/
+import * as Rx from 'rxjs';
import { resolve } from 'path';
import JoiNamespace from 'joi';
import { Server } from 'hapi';
@@ -26,12 +27,13 @@ import { i18n } from '@kbn/i18n';
import mappings from './mappings.json';
import { CONFIG_TELEMETRY, getConfigTelemetryDesc } from './common/constants';
import { getXpackConfigWithDeprecated } from './common/get_xpack_config_with_deprecated';
-import { telemetryPlugin, getTelemetryOptIn } from './server';
+import { telemetryPlugin, replaceTelemetryInjectedVars, FetcherTask } from './server';
import {
createLocalizationUsageCollector,
createTelemetryUsageCollector,
createUiMetricUsageCollector,
+ createTelemetryPluginUsageCollector,
} from './server/collectors';
const ENDPOINT_VERSION = 'v2';
@@ -45,6 +47,15 @@ const telemetry = (kibana: any) => {
config(Joi: typeof JoiNamespace) {
return Joi.object({
enabled: Joi.boolean().default(true),
+ allowChangingOptInStatus: Joi.boolean().default(true),
+ optIn: Joi.when('allowChangingOptInStatus', {
+ is: false,
+ then: Joi.valid(true).required(),
+ otherwise: Joi.boolean()
+ .allow(null)
+ .default(null),
+ }),
+
// `config` is used internally and not intended to be set
config: Joi.string().default(Joi.ref('$defaultConfigPath')),
banner: Joi.boolean().default(true),
@@ -57,6 +68,9 @@ const telemetry = (kibana: any) => {
`https://telemetry.elastic.co/xpack/${ENDPOINT_VERSION}/send`
),
}),
+ sendUsageFrom: Joi.string()
+ .allow(['server', 'browser'])
+ .default('browser'),
}).default();
},
uiExports: {
@@ -77,27 +91,50 @@ const telemetry = (kibana: any) => {
},
},
async replaceInjectedVars(originalInjectedVars: any, request: any) {
- const telemetryOptedIn = await getTelemetryOptIn(request);
-
- return {
- ...originalInjectedVars,
- telemetryOptedIn,
- };
+ const telemetryInjectedVars = await replaceTelemetryInjectedVars(request);
+ return Object.assign({}, originalInjectedVars, telemetryInjectedVars);
},
injectDefaultVars(server: Server) {
const config = server.config();
return {
telemetryEnabled: getXpackConfigWithDeprecated(config, 'telemetry.enabled'),
telemetryUrl: getXpackConfigWithDeprecated(config, 'telemetry.url'),
- telemetryBanner: getXpackConfigWithDeprecated(config, 'telemetry.banner'),
- telemetryOptedIn: null,
+ telemetryBanner:
+ config.get('telemetry.allowChangingOptInStatus') !== false &&
+ getXpackConfigWithDeprecated(config, 'telemetry.banner'),
+ telemetryOptedIn: config.get('telemetry.optIn'),
+ allowChangingOptInStatus: config.get('telemetry.allowChangingOptInStatus'),
+ telemetrySendUsageFrom: config.get('telemetry.sendUsageFrom'),
};
},
hacks: ['plugins/telemetry/hacks/telemetry_init', 'plugins/telemetry/hacks/telemetry_opt_in'],
mappings,
},
+ postInit(server: Server) {
+ const fetcherTask = new FetcherTask(server);
+ fetcherTask.start();
+ },
init(server: Server) {
- const initializerContext = {} as PluginInitializerContext;
+ const initializerContext = {
+ env: {
+ packageInfo: {
+ version: server.config().get('pkg.version'),
+ },
+ },
+ config: {
+ create() {
+ const config = server.config();
+ return Rx.of({
+ enabled: config.get('telemetry.enabled'),
+ optIn: config.get('telemetry.optIn'),
+ config: config.get('telemetry.config'),
+ banner: config.get('telemetry.banner'),
+ url: config.get('telemetry.url'),
+ allowChangingOptInStatus: config.get('telemetry.allowChangingOptInStatus'),
+ });
+ },
+ },
+ } as PluginInitializerContext;
const coreSetup = ({
http: { server },
@@ -107,6 +144,7 @@ const telemetry = (kibana: any) => {
telemetryPlugin(initializerContext).setup(coreSetup);
// register collectors
+ server.usage.collectorSet.register(createTelemetryPluginUsageCollector(server));
server.usage.collectorSet.register(createLocalizationUsageCollector(server));
server.usage.collectorSet.register(createTelemetryUsageCollector(server));
server.usage.collectorSet.register(createUiMetricUsageCollector(server));
diff --git a/src/legacy/core_plugins/telemetry/mappings.json b/src/legacy/core_plugins/telemetry/mappings.json
index d83f7f5967630..95c6ebfc7dc79 100644
--- a/src/legacy/core_plugins/telemetry/mappings.json
+++ b/src/legacy/core_plugins/telemetry/mappings.json
@@ -3,6 +3,17 @@
"properties": {
"enabled": {
"type": "boolean"
+ },
+ "sendUsageFrom": {
+ "ignore_above": 256,
+ "type": "keyword"
+ },
+ "lastReported": {
+ "type": "date"
+ },
+ "lastVersionChecked": {
+ "ignore_above": 256,
+ "type": "keyword"
}
}
}
diff --git a/src/legacy/core_plugins/telemetry/public/components/__snapshots__/opt_in_message.test.tsx.snap b/src/legacy/core_plugins/telemetry/public/components/__snapshots__/opt_in_message.test.tsx.snap
new file mode 100644
index 0000000000000..c80485332fa8a
--- /dev/null
+++ b/src/legacy/core_plugins/telemetry/public/components/__snapshots__/opt_in_message.test.tsx.snap
@@ -0,0 +1,24 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`OptInMessage renders as expected 1`] = `
+
+
+
+ ,
+ }
+ }
+ />
+
+`;
diff --git a/src/legacy/core_plugins/telemetry/public/components/__snapshots__/telemetry_form.test.js.snap b/src/legacy/core_plugins/telemetry/public/components/__snapshots__/telemetry_form.test.js.snap
index c1ad6276aee25..3340197fda513 100644
--- a/src/legacy/core_plugins/telemetry/public/components/__snapshots__/telemetry_form.test.js.snap
+++ b/src/legacy/core_plugins/telemetry/public/components/__snapshots__/telemetry_form.test.js.snap
@@ -1,6 +1,8 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
-exports[`TelemetryForm renders as expected 1`] = `
+exports[`TelemetryForm doesn't render form when not allowed to change optIn status 1`] = `""`;
+
+exports[`TelemetryForm renders as expected when allows to change optIn status 1`] = `
@@ -50,7 +53,7 @@ exports[`TelemetryForm renders as expected 1`] = `
{
const title = (
);
return (
@@ -45,12 +45,18 @@ export class OptInBanner extends React.PureComponent {
this.props.optInClick(true)}>
-
+
this.props.optInClick(false)}>
-
+
diff --git a/src/legacy/core_plugins/telemetry/public/components/opt_in_message.test.tsx b/src/legacy/core_plugins/telemetry/public/components/opt_in_message.test.tsx
new file mode 100644
index 0000000000000..1a9fabceda907
--- /dev/null
+++ b/src/legacy/core_plugins/telemetry/public/components/opt_in_message.test.tsx
@@ -0,0 +1,29 @@
+/*
+ * 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 React from 'react';
+import { shallowWithIntl } from 'test_utils/enzyme_helpers';
+import { OptInMessage } from './opt_in_message';
+
+describe('OptInMessage', () => {
+ it('renders as expected', () => {
+ expect(
+ shallowWithIntl( [])} />)
+ ).toMatchSnapshot();
+ });
+});
diff --git a/src/legacy/core_plugins/telemetry/public/components/opt_in_message.tsx b/src/legacy/core_plugins/telemetry/public/components/opt_in_message.tsx
index 928bb1015b715..4221d78516e10 100644
--- a/src/legacy/core_plugins/telemetry/public/components/opt_in_message.tsx
+++ b/src/legacy/core_plugins/telemetry/public/components/opt_in_message.tsx
@@ -21,8 +21,7 @@ import * as React from 'react';
import { EuiLink } from '@elastic/eui';
import { FormattedMessage } from '@kbn/i18n/react';
-import { getConfigTelemetryDesc, PRIVACY_STATEMENT_URL } from '../../common/constants';
-import { OptInExampleFlyout } from './opt_in_details_component';
+import { PRIVACY_STATEMENT_URL } from '../../common/constants';
interface Props {
fetchTelemetry: () => Promise;
@@ -46,60 +45,22 @@ export class OptInMessage extends React.PureComponent {
};
render() {
- const { showDetails, showExample } = this.state;
-
- const getDetails = () => (
-
-
-
- ),
- telemetryPrivacyStatementLink: (
-
-
-
- ),
- }}
- />
- );
-
- const getFlyoutDetails = () => (
- this.setState({ showExample: false })}
- fetchTelemetry={this.props.fetchTelemetry}
- />
- );
-
- const getReadMore = () => (
- this.setState({ showDetails: true })}>
-
-
- );
-
return (
- {getConfigTelemetryDesc()} {!showDetails && getReadMore()}
- {showDetails && (
-
- {getDetails()}
- {showExample && getFlyoutDetails()}
-
- )}
+
+
+
+ ),
+ }}
+ />
);
}
diff --git a/src/legacy/core_plugins/telemetry/public/components/telemetry_form.js b/src/legacy/core_plugins/telemetry/public/components/telemetry_form.js
index c2dcd48ee57da..aff830334d577 100644
--- a/src/legacy/core_plugins/telemetry/public/components/telemetry_form.js
+++ b/src/legacy/core_plugins/telemetry/public/components/telemetry_form.js
@@ -33,6 +33,7 @@ import { getConfigTelemetryDesc, PRIVACY_STATEMENT_URL } from '../../common/cons
import { OptInExampleFlyout } from './opt_in_details_component';
import { Field } from 'ui/management';
import { FormattedMessage } from '@kbn/i18n/react';
+import { i18n } from '@kbn/i18n';
const SEARCH_TERMS = ['telemetry', 'usage', 'data', 'usage data'];
@@ -78,6 +79,10 @@ export class TelemetryForm extends Component {
queryMatches,
} = this.state;
+ if (!telemetryOptInProvider.canChangeOptInStatus()) {
+ return null;
+ }
+
if (queryMatches !== null && !queryMatches) {
return null;
}
@@ -113,6 +118,7 @@ export class TelemetryForm extends Component {
value: telemetryOptInProvider.getOptIn() || false,
description: this.renderDescription(),
defVal: false,
+ ariaName: i18n.translate('telemetry.provideUsageStatisticsLabel', { defaultMessage: 'Provide usage statistics' })
}}
save={this.toggleOptIn}
clear={this.toggleOptIn}
diff --git a/src/legacy/core_plugins/telemetry/public/components/telemetry_form.test.js b/src/legacy/core_plugins/telemetry/public/components/telemetry_form.test.js
index 4d2c1dec27176..836fbc5d914de 100644
--- a/src/legacy/core_plugins/telemetry/public/components/telemetry_form.test.js
+++ b/src/legacy/core_plugins/telemetry/public/components/telemetry_form.test.js
@@ -17,7 +17,7 @@
* under the License.
*/
-import '../services/telemetry_opt_in.test.mocks';
+import { mockInjectedMetadata } from '../services/telemetry_opt_in.test.mocks';
import React from 'react';
import { shallowWithIntl } from 'test_utils/enzyme_helpers';
import { TelemetryForm } from './telemetry_form';
@@ -33,6 +33,8 @@ const buildTelemetryOptInProvider = () => {
switch (key) {
case '$http':
return mockHttp;
+ case 'allowChangingOptInStatus':
+ return true;
default:
return null;
}
@@ -47,7 +49,23 @@ const buildTelemetryOptInProvider = () => {
};
describe('TelemetryForm', () => {
- it('renders as expected', () => {
+ it('renders as expected when allows to change optIn status', () => {
+ mockInjectedMetadata({ telemetryOptedIn: null, allowChangingOptInStatus: true });
+
+ expect(shallowWithIntl(
+ )
+ ).toMatchSnapshot();
+ });
+
+ it(`doesn't render form when not allowed to change optIn status`, () => {
+ mockInjectedMetadata({ telemetryOptedIn: null, allowChangingOptInStatus: false });
+
expect(shallowWithIntl(
{
const optIn = true;
const bannerId = 'bruce-banner';
- mockInjectedMetadata({ telemetryOptedIn: optIn });
+ mockInjectedMetadata({ telemetryOptedIn: optIn, allowChangingOptInStatus: true });
const telemetryOptInProvider = getTelemetryOptInProvider();
telemetryOptInProvider.setBannerId(bannerId);
@@ -92,7 +92,7 @@ describe('click_banner', () => {
remove: sinon.spy()
};
const optIn = true;
- mockInjectedMetadata({ telemetryOptedIn: null });
+ mockInjectedMetadata({ telemetryOptedIn: null, allowChangingOptInStatus: true });
const telemetryOptInProvider = getTelemetryOptInProvider({ simulateFailure: true });
await clickBanner(telemetryOptInProvider, optIn, { _banners: banners, _toastNotifications: toastNotifications });
@@ -110,7 +110,7 @@ describe('click_banner', () => {
remove: sinon.spy()
};
const optIn = false;
- mockInjectedMetadata({ telemetryOptedIn: null });
+ mockInjectedMetadata({ telemetryOptedIn: null, allowChangingOptInStatus: true });
const telemetryOptInProvider = getTelemetryOptInProvider({ simulateError: true });
await clickBanner(telemetryOptInProvider, optIn, { _banners: banners, _toastNotifications: toastNotifications });
diff --git a/src/legacy/core_plugins/telemetry/public/hacks/welcome_banner/handle_old_settings.js b/src/legacy/core_plugins/telemetry/public/hacks/welcome_banner/handle_old_settings.js
index 31091e1952053..4f0f2983477e0 100644
--- a/src/legacy/core_plugins/telemetry/public/hacks/welcome_banner/handle_old_settings.js
+++ b/src/legacy/core_plugins/telemetry/public/hacks/welcome_banner/handle_old_settings.js
@@ -27,8 +27,9 @@ import { CONFIG_TELEMETRY } from '../../../common/constants';
* @param {Object} config The advanced settings config object.
* @return {Boolean} {@code true} if the banner should still be displayed. {@code false} if the banner should not be displayed.
*/
+const CONFIG_ALLOW_REPORT = 'xPackMonitoring:allowReport';
+
export async function handleOldSettings(config, telemetryOptInProvider) {
- const CONFIG_ALLOW_REPORT = 'xPackMonitoring:allowReport';
const CONFIG_SHOW_BANNER = 'xPackMonitoring:showBanner';
const oldAllowReportSetting = config.get(CONFIG_ALLOW_REPORT, null);
const oldTelemetrySetting = config.get(CONFIG_TELEMETRY, null);
@@ -62,3 +63,24 @@ export async function handleOldSettings(config, telemetryOptInProvider) {
return true;
}
+
+
+export async function isOptInHandleOldSettings(config, telemetryOptInProvider) {
+ const currentOptInSettting = telemetryOptInProvider.getOptIn();
+
+ if (typeof currentOptInSettting === 'boolean') {
+ return currentOptInSettting;
+ }
+
+ const oldTelemetrySetting = config.get(CONFIG_TELEMETRY, null);
+ if (typeof oldTelemetrySetting === 'boolean') {
+ return oldTelemetrySetting;
+ }
+
+ const oldAllowReportSetting = config.get(CONFIG_ALLOW_REPORT, null);
+ if (typeof oldAllowReportSetting === 'boolean') {
+ return oldAllowReportSetting;
+ }
+
+ return null;
+}
diff --git a/src/legacy/core_plugins/telemetry/public/hacks/welcome_banner/handle_old_settings.test.js b/src/legacy/core_plugins/telemetry/public/hacks/welcome_banner/handle_old_settings.test.js
index fd21a5122b594..f26ca0ca0e3c5 100644
--- a/src/legacy/core_plugins/telemetry/public/hacks/welcome_banner/handle_old_settings.test.js
+++ b/src/legacy/core_plugins/telemetry/public/hacks/welcome_banner/handle_old_settings.test.js
@@ -38,7 +38,7 @@ const getTelemetryOptInProvider = (enabled, { simulateFailure = false } = {}) =>
const chrome = {
addBasePath: url => url
};
- mockInjectedMetadata({ telemetryOptedIn: enabled });
+ mockInjectedMetadata({ telemetryOptedIn: enabled, allowChangingOptInStatus: true });
const $injector = {
get: (key) => {
diff --git a/src/legacy/core_plugins/telemetry/public/hacks/welcome_banner/should_show_banner.test.js b/src/legacy/core_plugins/telemetry/public/hacks/welcome_banner/should_show_banner.test.js
index 19e7ccbe61866..240c991a75b64 100644
--- a/src/legacy/core_plugins/telemetry/public/hacks/welcome_banner/should_show_banner.test.js
+++ b/src/legacy/core_plugins/telemetry/public/hacks/welcome_banner/should_show_banner.test.js
@@ -38,7 +38,7 @@ const getMockInjector = () => {
};
const getTelemetryOptInProvider = ({ telemetryOptedIn = null } = {}) => {
- mockInjectedMetadata({ telemetryOptedIn });
+ mockInjectedMetadata({ telemetryOptedIn, allowChangingOptInStatus: true });
const injector = getMockInjector();
const chrome = {
addBasePath: (url) => url
diff --git a/src/legacy/core_plugins/telemetry/public/services/telemetry_opt_in.test.js b/src/legacy/core_plugins/telemetry/public/services/telemetry_opt_in.test.js
index 0034fa4438238..26f14fc87d937 100644
--- a/src/legacy/core_plugins/telemetry/public/services/telemetry_opt_in.test.js
+++ b/src/legacy/core_plugins/telemetry/public/services/telemetry_opt_in.test.js
@@ -34,7 +34,7 @@ describe('TelemetryOptInProvider', () => {
addBasePath: (url) => url
};
- mockInjectedMetadata({ telemetryOptedIn: optedIn });
+ mockInjectedMetadata({ telemetryOptedIn: optedIn, allowChangingOptInStatus: true });
const mockInjector = {
get: (key) => {
diff --git a/src/legacy/core_plugins/telemetry/public/services/telemetry_opt_in.test.mocks.js b/src/legacy/core_plugins/telemetry/public/services/telemetry_opt_in.test.mocks.js
index f98f5e16e00c3..012f8de640042 100644
--- a/src/legacy/core_plugins/telemetry/public/services/telemetry_opt_in.test.mocks.js
+++ b/src/legacy/core_plugins/telemetry/public/services/telemetry_opt_in.test.mocks.js
@@ -24,10 +24,11 @@ import {
} from '../../../../../core/public/mocks';
const injectedMetadataMock = injectedMetadataServiceMock.createStartContract();
-export function mockInjectedMetadata({ telemetryOptedIn }) {
+export function mockInjectedMetadata({ telemetryOptedIn, allowChangingOptInStatus }) {
const mockGetInjectedVar = jest.fn().mockImplementation((key) => {
switch (key) {
case 'telemetryOptedIn': return telemetryOptedIn;
+ case 'allowChangingOptInStatus': return allowChangingOptInStatus;
default: throw new Error(`unexpected injectedVar ${key}`);
}
});
diff --git a/src/legacy/core_plugins/telemetry/public/services/telemetry_opt_in.ts b/src/legacy/core_plugins/telemetry/public/services/telemetry_opt_in.ts
index f4462ffea7a33..f7b09b1befafa 100644
--- a/src/legacy/core_plugins/telemetry/public/services/telemetry_opt_in.ts
+++ b/src/legacy/core_plugins/telemetry/public/services/telemetry_opt_in.ts
@@ -28,15 +28,22 @@ let currentOptInStatus = false;
export function TelemetryOptInProvider($injector: any, chrome: any) {
currentOptInStatus = npStart.core.injectedMetadata.getInjectedVar('telemetryOptedIn') as boolean;
+ const allowChangingOptInStatus = npStart.core.injectedMetadata.getInjectedVar(
+ 'allowChangingOptInStatus'
+ ) as boolean;
setCanTrackUiMetrics(currentOptInStatus);
const provider = {
getBannerId: () => bannerId,
getOptIn: () => currentOptInStatus,
+ canChangeOptInStatus: () => allowChangingOptInStatus,
setBannerId(id: string) {
bannerId = id;
},
setOptIn: async (enabled: boolean) => {
+ if (!allowChangingOptInStatus) {
+ return;
+ }
setCanTrackUiMetrics(enabled);
const $http = $injector.get('$http');
diff --git a/src/legacy/core_plugins/telemetry/server/collection_manager.ts b/src/legacy/core_plugins/telemetry/server/collection_manager.ts
index fef0a9b0f9f40..19bc735b9a965 100644
--- a/src/legacy/core_plugins/telemetry/server/collection_manager.ts
+++ b/src/legacy/core_plugins/telemetry/server/collection_manager.ts
@@ -17,20 +17,72 @@
* under the License.
*/
-class TelemetryCollectionManager {
- private getterMethod?: any;
+import { encryptTelemetry } from './collectors';
+
+export type EncryptedStatsGetterConfig = { unencrypted: false } & {
+ server: any;
+ start: any;
+ end: any;
+ isDev: boolean;
+};
+
+export type UnencryptedStatsGetterConfig = { unencrypted: true } & {
+ req: any;
+ start: any;
+ end: any;
+ isDev: boolean;
+};
+
+export interface StatsCollectionConfig {
+ callCluster: any;
+ server: any;
+ start: any;
+ end: any;
+}
+
+export type StatsGetterConfig = UnencryptedStatsGetterConfig | EncryptedStatsGetterConfig;
+
+export type StatsGetter = (config: StatsGetterConfig) => Promise;
+
+export const getStatsCollectionConfig = (
+ config: StatsGetterConfig,
+ esClustser: string
+): StatsCollectionConfig => {
+ const { start, end } = config;
+ const server = config.unencrypted ? config.req.server : config.server;
+ const { callWithRequest, callWithInternalUser } = server.plugins.elasticsearch.getCluster(
+ esClustser
+ );
+ const callCluster = config.unencrypted
+ ? (...args: any[]) => callWithRequest(config.req, ...args)
+ : callWithInternalUser;
+
+ return { server, callCluster, start, end };
+};
+
+export class TelemetryCollectionManager {
+ private getterMethod?: StatsGetter;
private collectionTitle?: string;
- private getterMethodPriority = 0;
+ private getterMethodPriority = -1;
- public setStatsGetter = (statsGetter: any, title: string, priority = 0) => {
- if (priority >= this.getterMethodPriority) {
+ public setStatsGetter = (statsGetter: StatsGetter, title: string, priority = 0) => {
+ if (priority > this.getterMethodPriority) {
this.getterMethod = statsGetter;
this.collectionTitle = title;
this.getterMethodPriority = priority;
}
};
- getCollectionTitle = () => {
+ private getStats = async (config: StatsGetterConfig) => {
+ if (!this.getterMethod) {
+ throw Error('Stats getter method not set.');
+ }
+ const usageData = await this.getterMethod(config);
+
+ if (config.unencrypted) return usageData;
+ return encryptTelemetry(usageData, config.isDev);
+ };
+ public getCollectionTitle = () => {
return this.collectionTitle;
};
@@ -39,7 +91,7 @@ class TelemetryCollectionManager {
throw Error('Stats getter method not set.');
}
return {
- getStats: this.getterMethod,
+ getStats: this.getStats,
priority: this.getterMethodPriority,
title: this.collectionTitle,
};
diff --git a/src/legacy/core_plugins/telemetry/server/collectors/index.ts b/src/legacy/core_plugins/telemetry/server/collectors/index.ts
index 0bc1d50fab1be..f963ecec0477c 100644
--- a/src/legacy/core_plugins/telemetry/server/collectors/index.ts
+++ b/src/legacy/core_plugins/telemetry/server/collectors/index.ts
@@ -21,3 +21,4 @@ export { encryptTelemetry } from './encryption';
export { createTelemetryUsageCollector } from './usage';
export { createUiMetricUsageCollector } from './ui_metric';
export { createLocalizationUsageCollector } from './localization';
+export { createTelemetryPluginUsageCollector } from './telemetry_plugin';
diff --git a/src/legacy/core_plugins/telemetry/server/collectors/telemetry_plugin/index.ts b/src/legacy/core_plugins/telemetry/server/collectors/telemetry_plugin/index.ts
new file mode 100644
index 0000000000000..e96c47741f79c
--- /dev/null
+++ b/src/legacy/core_plugins/telemetry/server/collectors/telemetry_plugin/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 { createTelemetryPluginUsageCollector } from './telemetry_plugin_collector';
diff --git a/src/legacy/core_plugins/telemetry/server/collectors/telemetry_plugin/telemetry_plugin_collector.ts b/src/legacy/core_plugins/telemetry/server/collectors/telemetry_plugin/telemetry_plugin_collector.ts
new file mode 100644
index 0000000000000..e092ceb5e8593
--- /dev/null
+++ b/src/legacy/core_plugins/telemetry/server/collectors/telemetry_plugin/telemetry_plugin_collector.ts
@@ -0,0 +1,75 @@
+/*
+ * 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 { TELEMETRY_STATS_TYPE } from '../../../common/constants';
+import { getTelemetrySavedObject, TelemetrySavedObject } from '../../telemetry_repository';
+import { getTelemetryOptIn, getTelemetryUsageFetcher } from '../../telemetry_config';
+export interface TelemetryUsageStats {
+ opt_in_status?: boolean | null;
+ usage_fetcher?: 'browser' | 'server';
+ last_reported?: number;
+}
+
+export function createCollectorFetch(server: any) {
+ return async function fetchUsageStats(): Promise {
+ const config = server.config();
+ const configTelemetrySendUsageFrom = config.get('telemetry.sendUsageFrom');
+ const allowChangingOptInStatus = config.get('telemetry.allowChangingOptInStatus');
+ const configTelemetryOptIn = config.get('telemetry.optIn');
+ const currentKibanaVersion = config.get('pkg.version');
+
+ let telemetrySavedObject: TelemetrySavedObject = {};
+
+ try {
+ const { getSavedObjectsRepository } = server.savedObjects;
+ const { callWithInternalUser } = server.plugins.elasticsearch.getCluster('admin');
+ const internalRepository = getSavedObjectsRepository(callWithInternalUser);
+ telemetrySavedObject = await getTelemetrySavedObject(internalRepository);
+ } catch (err) {
+ // no-op
+ }
+
+ return {
+ opt_in_status: getTelemetryOptIn({
+ currentKibanaVersion,
+ telemetrySavedObject,
+ allowChangingOptInStatus,
+ configTelemetryOptIn,
+ }),
+ last_reported: telemetrySavedObject ? telemetrySavedObject.lastReported : undefined,
+ usage_fetcher: getTelemetryUsageFetcher({
+ telemetrySavedObject,
+ configTelemetrySendUsageFrom,
+ }),
+ };
+ };
+}
+
+/*
+ * @param {Object} server
+ * @return {Object} kibana usage stats type collection object
+ */
+export function createTelemetryPluginUsageCollector(server: any) {
+ const { collectorSet } = server.usage;
+ return collectorSet.makeUsageCollector({
+ type: TELEMETRY_STATS_TYPE,
+ isReady: () => true,
+ fetch: createCollectorFetch(server),
+ });
+}
diff --git a/src/legacy/core_plugins/telemetry/server/collectors/usage/ensure_deep_object.ts b/src/legacy/core_plugins/telemetry/server/collectors/usage/ensure_deep_object.ts
index 6594c7f8e7a6f..3b7a9355da746 100644
--- a/src/legacy/core_plugins/telemetry/server/collectors/usage/ensure_deep_object.ts
+++ b/src/legacy/core_plugins/telemetry/server/collectors/usage/ensure_deep_object.ts
@@ -42,19 +42,16 @@ export function ensureDeepObject(obj: any): any {
return obj.map(item => ensureDeepObject(item));
}
- return Object.keys(obj).reduce(
- (fullObject, propertyKey) => {
- const propertyValue = obj[propertyKey];
- if (!propertyKey.includes(separator)) {
- fullObject[propertyKey] = ensureDeepObject(propertyValue);
- } else {
- walk(fullObject, propertyKey.split(separator), propertyValue);
- }
+ return Object.keys(obj).reduce((fullObject, propertyKey) => {
+ const propertyValue = obj[propertyKey];
+ if (!propertyKey.includes(separator)) {
+ fullObject[propertyKey] = ensureDeepObject(propertyValue);
+ } else {
+ walk(fullObject, propertyKey.split(separator), propertyValue);
+ }
- return fullObject;
- },
- {} as any
- );
+ return fullObject;
+ }, {} as any);
}
function walk(obj: any, keys: string[], value: any) {
diff --git a/src/legacy/core_plugins/telemetry/server/fetcher.ts b/src/legacy/core_plugins/telemetry/server/fetcher.ts
new file mode 100644
index 0000000000000..43883395eac99
--- /dev/null
+++ b/src/legacy/core_plugins/telemetry/server/fetcher.ts
@@ -0,0 +1,148 @@
+/*
+ * 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 moment from 'moment';
+// @ts-ignore
+import fetch from 'node-fetch';
+import { telemetryCollectionManager } from './collection_manager';
+import { getTelemetryOptIn, getTelemetryUsageFetcher } from './telemetry_config';
+import { getTelemetrySavedObject, updateTelemetrySavedObject } from './telemetry_repository';
+import { REPORT_INTERVAL_MS } from '../common/constants';
+import { getXpackConfigWithDeprecated } from '../common/get_xpack_config_with_deprecated';
+
+export class FetcherTask {
+ private readonly checkDurationMs = 60 * 1000 * 5;
+ private intervalId?: NodeJS.Timeout;
+ private lastReported?: number;
+ private isSending = false;
+ private server: any;
+
+ constructor(server: any) {
+ this.server = server;
+ }
+
+ private getInternalRepository = () => {
+ const { getSavedObjectsRepository } = this.server.savedObjects;
+ const { callWithInternalUser } = this.server.plugins.elasticsearch.getCluster('admin');
+ const internalRepository = getSavedObjectsRepository(callWithInternalUser);
+ return internalRepository;
+ };
+
+ private getCurrentConfigs = async () => {
+ const internalRepository = this.getInternalRepository();
+ const telemetrySavedObject = await getTelemetrySavedObject(internalRepository);
+ const config = this.server.config();
+ const currentKibanaVersion = config.get('pkg.version');
+ const configTelemetrySendUsageFrom = config.get('telemetry.sendUsageFrom');
+ const allowChangingOptInStatus = config.get('telemetry.allowChangingOptInStatus');
+ const configTelemetryOptIn = config.get('telemetry.optIn');
+ const telemetryUrl = getXpackConfigWithDeprecated(config, 'telemetry.url') as string;
+
+ return {
+ telemetryOptIn: getTelemetryOptIn({
+ currentKibanaVersion,
+ telemetrySavedObject,
+ allowChangingOptInStatus,
+ configTelemetryOptIn,
+ }),
+ telemetrySendUsageFrom: getTelemetryUsageFetcher({
+ telemetrySavedObject,
+ configTelemetrySendUsageFrom,
+ }),
+ telemetryUrl,
+ };
+ };
+
+ private updateLastReported = async () => {
+ const internalRepository = this.getInternalRepository();
+ this.lastReported = Date.now();
+ updateTelemetrySavedObject(internalRepository, {
+ lastReported: this.lastReported,
+ });
+ };
+
+ private shouldSendReport = ({ telemetryOptIn, telemetrySendUsageFrom }: any) => {
+ if (telemetryOptIn && telemetrySendUsageFrom === 'server') {
+ if (!this.lastReported || Date.now() - this.lastReported > REPORT_INTERVAL_MS) {
+ return true;
+ }
+ }
+ return false;
+ };
+
+ private fetchTelemetry = async () => {
+ const { getStats, title } = telemetryCollectionManager.getStatsGetter();
+ this.server.log(['debug', 'telemetry', 'fetcher'], `Fetching usage using ${title} getter.`);
+ const config = this.server.config();
+
+ return await getStats({
+ unencrypted: false,
+ server: this.server,
+ start: moment()
+ .subtract(20, 'minutes')
+ .toISOString(),
+ end: moment().toISOString(),
+ isDev: config.get('env.dev'),
+ });
+ };
+
+ private sendTelemetry = async (url: string, cluster: any): Promise => {
+ this.server.log(['debug', 'telemetry', 'fetcher'], `Sending usage stats.`);
+ await fetch(url, {
+ method: 'post',
+ body: cluster,
+ });
+ };
+
+ private sendIfDue = async () => {
+ if (this.isSending) {
+ return;
+ }
+ try {
+ const telemetryConfig = await this.getCurrentConfigs();
+ if (!this.shouldSendReport(telemetryConfig)) {
+ return;
+ }
+
+ // mark that we are working so future requests are ignored until we're done
+ this.isSending = true;
+ const clusters = await this.fetchTelemetry();
+ for (const cluster of clusters) {
+ await this.sendTelemetry(telemetryConfig.telemetryUrl, cluster);
+ }
+
+ await this.updateLastReported();
+ } catch (err) {
+ this.server.log(
+ ['warning', 'telemetry', 'fetcher'],
+ `Error sending telemetry usage data: ${err}`
+ );
+ }
+ this.isSending = false;
+ };
+
+ public start = () => {
+ this.intervalId = setInterval(() => this.sendIfDue(), this.checkDurationMs);
+ };
+ public stop = () => {
+ if (this.intervalId) {
+ clearInterval(this.intervalId);
+ }
+ };
+}
diff --git a/src/legacy/core_plugins/telemetry/server/index.ts b/src/legacy/core_plugins/telemetry/server/index.ts
index b8ae5fc231fba..02752ca773488 100644
--- a/src/legacy/core_plugins/telemetry/server/index.ts
+++ b/src/legacy/core_plugins/telemetry/server/index.ts
@@ -21,9 +21,10 @@ import { PluginInitializerContext } from 'src/core/server';
import { TelemetryPlugin } from './plugin';
import * as constants from '../common/constants';
-export { getTelemetryOptIn } from './get_telemetry_opt_in';
+export { FetcherTask } from './fetcher';
+export { replaceTelemetryInjectedVars } from './telemetry_config';
export { telemetryCollectionManager } from './collection_manager';
export const telemetryPlugin = (initializerContext: PluginInitializerContext) =>
- new TelemetryPlugin();
+ new TelemetryPlugin(initializerContext);
export { constants };
diff --git a/src/legacy/core_plugins/telemetry/server/plugin.ts b/src/legacy/core_plugins/telemetry/server/plugin.ts
index 70de51b2abe99..a5f0f1234799a 100644
--- a/src/legacy/core_plugins/telemetry/server/plugin.ts
+++ b/src/legacy/core_plugins/telemetry/server/plugin.ts
@@ -17,14 +17,21 @@
* under the License.
*/
-import { CoreSetup } from 'src/core/server';
+import { CoreSetup, PluginInitializerContext } from 'src/core/server';
import { registerRoutes } from './routes';
import { telemetryCollectionManager } from './collection_manager';
import { getStats } from './telemetry_collection';
export class TelemetryPlugin {
+ private readonly currentKibanaVersion: string;
+
+ constructor(initializerContext: PluginInitializerContext) {
+ this.currentKibanaVersion = initializerContext.env.packageInfo.version;
+ }
+
public setup(core: CoreSetup) {
+ const currentKibanaVersion = this.currentKibanaVersion;
telemetryCollectionManager.setStatsGetter(getStats, 'local');
- registerRoutes(core);
+ registerRoutes({ core, currentKibanaVersion });
}
}
diff --git a/src/legacy/core_plugins/telemetry/server/routes/index.ts b/src/legacy/core_plugins/telemetry/server/routes/index.ts
index 12ba541d699f9..93654f6470555 100644
--- a/src/legacy/core_plugins/telemetry/server/routes/index.ts
+++ b/src/legacy/core_plugins/telemetry/server/routes/index.ts
@@ -18,10 +18,15 @@
*/
import { CoreSetup } from 'src/core/server';
-import { registerOptInRoutes } from './opt_in';
+import { registerTelemetryConfigRoutes } from './telemetry_config';
import { registerTelemetryDataRoutes } from './telemetry_stats';
-export function registerRoutes(core: CoreSetup) {
- registerOptInRoutes(core);
+interface RegisterRoutesParams {
+ core: CoreSetup;
+ currentKibanaVersion: string;
+}
+
+export function registerRoutes({ core, currentKibanaVersion }: RegisterRoutesParams) {
+ registerTelemetryConfigRoutes({ core, currentKibanaVersion });
registerTelemetryDataRoutes(core);
}
diff --git a/src/legacy/core_plugins/telemetry/server/routes/opt_in.ts b/src/legacy/core_plugins/telemetry/server/routes/telemetry_config.ts
similarity index 52%
rename from src/legacy/core_plugins/telemetry/server/routes/opt_in.ts
rename to src/legacy/core_plugins/telemetry/server/routes/telemetry_config.ts
index aabc0259f08fc..440f83277340a 100644
--- a/src/legacy/core_plugins/telemetry/server/routes/opt_in.ts
+++ b/src/legacy/core_plugins/telemetry/server/routes/telemetry_config.ts
@@ -20,8 +20,21 @@
import Joi from 'joi';
import { boomify } from 'boom';
import { CoreSetup } from 'src/core/server';
+import { getTelemetryAllowChangingOptInStatus } from '../telemetry_config';
+import {
+ TelemetrySavedObjectAttributes,
+ updateTelemetrySavedObject,
+} from '../telemetry_repository';
-export function registerOptInRoutes(core: CoreSetup) {
+interface RegisterOptInRoutesParams {
+ core: CoreSetup;
+ currentKibanaVersion: string;
+}
+
+export function registerTelemetryConfigRoutes({
+ core,
+ currentKibanaVersion,
+}: RegisterOptInRoutesParams) {
const { server } = core.http as any;
server.route({
@@ -35,18 +48,24 @@ export function registerOptInRoutes(core: CoreSetup) {
},
},
handler: async (req: any, h: any) => {
- const savedObjectsClient = req.getSavedObjectsClient();
try {
- await savedObjectsClient.create(
- 'telemetry',
- {
- enabled: req.payload.enabled,
- },
- {
- id: 'telemetry',
- overwrite: true,
- }
+ const attributes: TelemetrySavedObjectAttributes = {
+ enabled: req.payload.enabled,
+ lastVersionChecked: currentKibanaVersion,
+ };
+ const config = req.server.config();
+ const savedObjectsClient = req.getSavedObjectsClient();
+ const configTelemetryAllowChangingOptInStatus = config.get(
+ 'telemetry.allowChangingOptInStatus'
);
+ const allowChangingOptInStatus = getTelemetryAllowChangingOptInStatus({
+ telemetrySavedObject: savedObjectsClient,
+ configTelemetryAllowChangingOptInStatus,
+ });
+ if (!allowChangingOptInStatus) {
+ return h.response({ error: 'Not allowed to change Opt-in Status.' }).code(400);
+ }
+ await updateTelemetrySavedObject(savedObjectsClient, attributes);
} catch (err) {
return boomify(err);
}
diff --git a/src/legacy/core_plugins/telemetry/server/routes/telemetry_stats.ts b/src/legacy/core_plugins/telemetry/server/routes/telemetry_stats.ts
index 8a91d24b34ed2..e87c041a263a5 100644
--- a/src/legacy/core_plugins/telemetry/server/routes/telemetry_stats.ts
+++ b/src/legacy/core_plugins/telemetry/server/routes/telemetry_stats.ts
@@ -20,7 +20,6 @@
import Joi from 'joi';
import { boomify } from 'boom';
import { CoreSetup } from 'src/core/server';
-import { encryptTelemetry } from '../collectors';
import { telemetryCollectionManager } from '../collection_manager';
export function registerTelemetryDataRoutes(core: CoreSetup) {
@@ -49,12 +48,16 @@ export function registerTelemetryDataRoutes(core: CoreSetup) {
try {
const { getStats, title } = telemetryCollectionManager.getStatsGetter();
- server.log(['debug', 'telemetry'], `Using Stats Getter: ${title}`);
+ server.log(['debug', 'telemetry', 'fetcher'], `Fetching usage using ${title} getter.`);
- const usageData = await getStats(req, config, start, end, unencrypted);
-
- if (unencrypted) return usageData;
- return encryptTelemetry(usageData, isDev);
+ return await getStats({
+ unencrypted,
+ server,
+ req,
+ start,
+ end,
+ isDev,
+ });
} catch (err) {
if (isDev) {
// don't ignore errors when running in dev mode
diff --git a/src/legacy/core_plugins/telemetry/server/telemetry_collection/__tests__/get_local_stats.js b/src/legacy/core_plugins/telemetry/server/telemetry_collection/__tests__/get_local_stats.js
index d0de9cc365a71..261012e594b1c 100644
--- a/src/legacy/core_plugins/telemetry/server/telemetry_collection/__tests__/get_local_stats.js
+++ b/src/legacy/core_plugins/telemetry/server/telemetry_collection/__tests__/get_local_stats.js
@@ -26,7 +26,6 @@ import { mockGetClusterStats } from './get_cluster_stats';
import { omit } from 'lodash';
import {
getLocalStats,
- getLocalStatsWithCaller,
handleLocalStats,
} from '../get_local_stats';
@@ -153,7 +152,7 @@ describe('get_local_stats', () => {
});
});
- describe('getLocalStatsWithCaller', () => {
+ describe('getLocalStats', () => {
it('returns expected object without xpack data when X-Pack fails to respond', async () => {
const callClusterUsageFailed = sinon.stub();
@@ -162,8 +161,10 @@ describe('get_local_stats', () => {
Promise.resolve(clusterInfo),
Promise.resolve(clusterStats),
);
-
- const result = await getLocalStatsWithCaller(getMockServer(), callClusterUsageFailed);
+ const result = await getLocalStats({
+ server: getMockServer(),
+ callCluster: callClusterUsageFailed,
+ });
expect(result.cluster_uuid).to.eql(combinedStatsResult.cluster_uuid);
expect(result.cluster_name).to.eql(combinedStatsResult.cluster_name);
expect(result.cluster_stats).to.eql(combinedStatsResult.cluster_stats);
@@ -184,51 +185,13 @@ describe('get_local_stats', () => {
Promise.resolve(clusterStats),
);
- const result = await getLocalStatsWithCaller(getMockServer(callCluster, kibana), callCluster);
+ const result = await getLocalStats({
+ server: getMockServer(callCluster, kibana),
+ callCluster,
+ });
+
expect(result.stack_stats.xpack).to.eql(combinedStatsResult.stack_stats.xpack);
expect(result.stack_stats.kibana).to.eql(combinedStatsResult.stack_stats.kibana);
});
});
-
- describe('getLocalStats', () => {
- it('uses callWithInternalUser from data cluster', async () => {
- const getCluster = sinon.stub();
- const req = { server: getMockServer(getCluster) };
- const callWithInternalUser = sinon.stub();
-
- getCluster.withArgs('data').returns({ callWithInternalUser });
-
- mockGetLocalStats(
- callWithInternalUser,
- Promise.resolve(clusterInfo),
- Promise.resolve(clusterStats),
- );
-
- const result = await getLocalStats(req, { useInternalUser: true });
- expect(result.cluster_uuid).to.eql(combinedStatsResult.cluster_uuid);
- expect(result.cluster_name).to.eql(combinedStatsResult.cluster_name);
- expect(result.version).to.eql(combinedStatsResult.version);
- expect(result.cluster_stats).to.eql(combinedStatsResult.cluster_stats);
- });
- it('uses callWithRequest from data cluster', async () => {
- const getCluster = sinon.stub();
- const req = { server: getMockServer(getCluster) };
- const callWithRequest = sinon.stub();
-
- getCluster.withArgs('data').returns({ callWithRequest });
-
- mockGetLocalStats(
- callWithRequest,
- Promise.resolve(clusterInfo),
- Promise.resolve(clusterStats),
- req
- );
-
- const result = await getLocalStats(req, { useInternalUser: false });
- expect(result.cluster_uuid).to.eql(combinedStatsResult.cluster_uuid);
- expect(result.cluster_name).to.eql(combinedStatsResult.cluster_name);
- expect(result.version).to.eql(combinedStatsResult.version);
- expect(result.cluster_stats).to.eql(combinedStatsResult.cluster_stats);
- });
- });
});
diff --git a/src/legacy/core_plugins/telemetry/server/telemetry_collection/get_local_stats.js b/src/legacy/core_plugins/telemetry/server/telemetry_collection/get_local_stats.js
index 67fc721306c21..6125dadc3646f 100644
--- a/src/legacy/core_plugins/telemetry/server/telemetry_collection/get_local_stats.js
+++ b/src/legacy/core_plugins/telemetry/server/telemetry_collection/get_local_stats.js
@@ -51,7 +51,7 @@ export function handleLocalStats(server, clusterInfo, clusterStats, kibana) {
* @param {function} callCluster The callWithInternalUser handler (exposed for testing)
* @return {Promise} The object containing the current Elasticsearch cluster's telemetry.
*/
-export async function getLocalStatsWithCaller(server, callCluster) {
+export async function getLocalStats({ server, callCluster }) {
const [ clusterInfo, clusterStats, kibana ] = await Promise.all([
getClusterInfo(callCluster), // cluster info
getClusterStats(callCluster), // cluster stats (not to be confused with cluster _state_)
@@ -60,19 +60,3 @@ export async function getLocalStatsWithCaller(server, callCluster) {
return handleLocalStats(server, clusterInfo, clusterStats, kibana);
}
-
-
-/**
- * Get statistics for the connected Elasticsearch cluster.
- *
- * @param {Object} req The incoming request
- * @param {Boolean} useRequestUser callWithRequest, otherwise callWithInternalUser
- * @return {Promise} The cluster object containing telemetry.
- */
-export async function getLocalStats(req, { useInternalUser = false } = {}) {
- const { server } = req;
- const { callWithRequest, callWithInternalUser } = server.plugins.elasticsearch.getCluster('data');
- const callCluster = useInternalUser ? callWithInternalUser : (...args) => callWithRequest(req, ...args);
-
- return await getLocalStatsWithCaller(server, callCluster);
-}
diff --git a/src/legacy/core_plugins/telemetry/server/telemetry_collection/get_stats.ts b/src/legacy/core_plugins/telemetry/server/telemetry_collection/get_stats.ts
index 024272e0f805c..b739b20545678 100644
--- a/src/legacy/core_plugins/telemetry/server/telemetry_collection/get_stats.ts
+++ b/src/legacy/core_plugins/telemetry/server/telemetry_collection/get_stats.ts
@@ -19,27 +19,10 @@
// @ts-ignore
import { getLocalStats } from './get_local_stats';
+import { StatsGetter, getStatsCollectionConfig } from '../collection_manager';
-/**
- * Get the telemetry data.
- *
- * @param {Object} req The incoming request.
- * @param {Object} config Kibana config.
- * @param {String} start The start time of the request (likely 20m ago).
- * @param {String} end The end time of the request.
- * @param {Boolean} unencrypted Is the request payload going to be unencrypted.
- * @return {Promise} An array of telemetry objects.
- */
-export async function getStats(
- req: any,
- config: any,
- start: string,
- end: string,
- unencrypted: boolean
-) {
- return [
- await getLocalStats(req, {
- useInternalUser: !unencrypted,
- }),
- ];
-}
+export const getStats: StatsGetter = async function(config) {
+ const { callCluster, server } = getStatsCollectionConfig(config, 'data');
+
+ return [await getLocalStats({ callCluster, server })];
+};
diff --git a/src/legacy/core_plugins/telemetry/server/telemetry_collection/index.ts b/src/legacy/core_plugins/telemetry/server/telemetry_collection/index.ts
index f33727d82f44c..f54aaf0ce1bc0 100644
--- a/src/legacy/core_plugins/telemetry/server/telemetry_collection/index.ts
+++ b/src/legacy/core_plugins/telemetry/server/telemetry_collection/index.ts
@@ -19,6 +19,4 @@
// @ts-ignore
export { getLocalStats } from './get_local_stats';
-
-// @ts-ignore
export { getStats } from './get_stats';
diff --git a/test/plugin_functional/plugins/kbn_tp_visualize_embedding/index.js b/src/legacy/core_plugins/telemetry/server/telemetry_config/get_telemetry_allow_changing_opt_in_status.ts
similarity index 53%
rename from test/plugin_functional/plugins/kbn_tp_visualize_embedding/index.js
rename to src/legacy/core_plugins/telemetry/server/telemetry_config/get_telemetry_allow_changing_opt_in_status.ts
index 1ec4ea2b9e096..9fa4fbc5e0227 100644
--- a/test/plugin_functional/plugins/kbn_tp_visualize_embedding/index.js
+++ b/src/legacy/core_plugins/telemetry/server/telemetry_config/get_telemetry_allow_changing_opt_in_status.ts
@@ -16,24 +16,24 @@
* specific language governing permissions and limitations
* under the License.
*/
+import { TelemetrySavedObject } from '../telemetry_repository/get_telemetry_saved_object';
-export default function (kibana) {
- return new kibana.Plugin({
- uiExports: {
- app: {
- title: 'Embedding Vis',
- description: 'This is a sample plugin to test embedding of visualizations',
- main: 'plugins/kbn_tp_visualize_embedding/app',
- }
- },
+interface GetTelemetryAllowChangingOptInStatus {
+ configTelemetryAllowChangingOptInStatus: boolean;
+ telemetrySavedObject: TelemetrySavedObject;
+}
+
+export function getTelemetryAllowChangingOptInStatus({
+ telemetrySavedObject,
+ configTelemetryAllowChangingOptInStatus,
+}: GetTelemetryAllowChangingOptInStatus) {
+ if (!telemetrySavedObject) {
+ return configTelemetryAllowChangingOptInStatus;
+ }
+
+ if (typeof telemetrySavedObject.telemetryAllowChangingOptInStatus === 'undefined') {
+ return configTelemetryAllowChangingOptInStatus;
+ }
- init(server) {
- // The following lines copy over some configuration variables from Kibana
- // to this plugin. This will be needed when embedding visualizations, so that e.g.
- // region map is able to get its configuration.
- server.injectUiAppVars('kbn_tp_visualize_embedding', async () => {
- return await server.getInjectedUiAppVars('kibana');
- });
- }
- });
+ return telemetrySavedObject.telemetryAllowChangingOptInStatus;
}
diff --git a/src/legacy/core_plugins/telemetry/server/telemetry_config/get_telemetry_opt_in.test.ts b/src/legacy/core_plugins/telemetry/server/telemetry_config/get_telemetry_opt_in.test.ts
new file mode 100644
index 0000000000000..efc4a020e0ff0
--- /dev/null
+++ b/src/legacy/core_plugins/telemetry/server/telemetry_config/get_telemetry_opt_in.test.ts
@@ -0,0 +1,174 @@
+/*
+ * 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 { getTelemetryOptIn } from './get_telemetry_opt_in';
+import { TelemetrySavedObject } from '../telemetry_repository/get_telemetry_saved_object';
+
+describe('getTelemetryOptIn', () => {
+ it('returns null when saved object not found', () => {
+ const params = getCallGetTelemetryOptInParams({
+ savedObjectNotFound: true,
+ });
+
+ const result = callGetTelemetryOptIn(params);
+
+ expect(result).toBe(null);
+ });
+
+ it('returns false when saved object forbidden', () => {
+ const params = getCallGetTelemetryOptInParams({
+ savedObjectForbidden: true,
+ });
+
+ const result = callGetTelemetryOptIn(params);
+
+ expect(result).toBe(false);
+ });
+
+ it('returns null if enabled is null or undefined', () => {
+ for (const enabled of [null, undefined]) {
+ const params = getCallGetTelemetryOptInParams({
+ enabled,
+ });
+
+ const result = callGetTelemetryOptIn(params);
+
+ expect(result).toBe(null);
+ }
+ });
+
+ it('returns true when enabled is true', () => {
+ const params = getCallGetTelemetryOptInParams({
+ enabled: true,
+ });
+
+ const result = callGetTelemetryOptIn(params);
+
+ expect(result).toBe(true);
+ });
+
+ // build a table of tests with version checks, with results for enabled false
+ type VersionCheckTable = Array>;
+
+ const EnabledFalseVersionChecks: VersionCheckTable = [
+ { lastVersionChecked: '8.0.0', currentKibanaVersion: '8.0.0', result: false },
+ { lastVersionChecked: '8.0.0', currentKibanaVersion: '8.0.1', result: false },
+ { lastVersionChecked: '8.0.1', currentKibanaVersion: '8.0.0', result: false },
+ { lastVersionChecked: '8.0.0', currentKibanaVersion: '8.1.0', result: null },
+ { lastVersionChecked: '8.0.0', currentKibanaVersion: '9.0.0', result: null },
+ { lastVersionChecked: '8.0.0', currentKibanaVersion: '7.0.0', result: false },
+ { lastVersionChecked: '8.1.0', currentKibanaVersion: '8.0.0', result: false },
+ { lastVersionChecked: '8.0.0-X', currentKibanaVersion: '8.0.0', result: false },
+ { lastVersionChecked: '8.0.0', currentKibanaVersion: '8.0.0-X', result: false },
+ { lastVersionChecked: null, currentKibanaVersion: '8.0.0', result: null },
+ { lastVersionChecked: undefined, currentKibanaVersion: '8.0.0', result: null },
+ { lastVersionChecked: 5, currentKibanaVersion: '8.0.0', result: null },
+ { lastVersionChecked: '8.0.0', currentKibanaVersion: 'beta', result: null },
+ { lastVersionChecked: 'beta', currentKibanaVersion: '8.0.0', result: null },
+ { lastVersionChecked: 'beta', currentKibanaVersion: 'beta', result: false },
+ { lastVersionChecked: 'BETA', currentKibanaVersion: 'beta', result: null },
+ ].map(el => ({ ...el, enabled: false }));
+
+ // build a table of tests with version checks, with results for enabled true/null/undefined
+ const EnabledTrueVersionChecks: VersionCheckTable = EnabledFalseVersionChecks.map(el => ({
+ ...el,
+ enabled: true,
+ result: true,
+ }));
+
+ const EnabledNullVersionChecks: VersionCheckTable = EnabledFalseVersionChecks.map(el => ({
+ ...el,
+ enabled: null,
+ result: null,
+ }));
+
+ const EnabledUndefinedVersionChecks: VersionCheckTable = EnabledFalseVersionChecks.map(el => ({
+ ...el,
+ enabled: undefined,
+ result: null,
+ }));
+
+ const AllVersionChecks = [
+ ...EnabledFalseVersionChecks,
+ ...EnabledTrueVersionChecks,
+ ...EnabledNullVersionChecks,
+ ...EnabledUndefinedVersionChecks,
+ ];
+
+ test.each(AllVersionChecks)(
+ 'returns expected result for version check with %j',
+ async (params: Partial) => {
+ const result = await callGetTelemetryOptIn({ ...DefaultParams, ...params });
+ expect(result).toBe(params.result);
+ }
+ );
+});
+
+interface CallGetTelemetryOptInParams {
+ savedObjectNotFound: boolean;
+ savedObjectForbidden: boolean;
+ lastVersionChecked?: any; // should be a string, but test with non-strings
+ currentKibanaVersion: string;
+ result?: boolean | null;
+ enabled: boolean | null | undefined;
+ configTelemetryOptIn: boolean | null;
+ allowChangingOptInStatus: boolean;
+}
+
+const DefaultParams = {
+ savedObjectNotFound: false,
+ savedObjectForbidden: false,
+ enabled: true,
+ lastVersionChecked: '8.0.0',
+ currentKibanaVersion: '8.0.0',
+ configTelemetryOptIn: null,
+ allowChangingOptInStatus: true,
+};
+
+function getCallGetTelemetryOptInParams(
+ overrides: Partial
+): CallGetTelemetryOptInParams {
+ return { ...DefaultParams, ...overrides };
+}
+
+function callGetTelemetryOptIn(params: CallGetTelemetryOptInParams) {
+ const { currentKibanaVersion, configTelemetryOptIn, allowChangingOptInStatus } = params;
+ const telemetrySavedObject = getMockTelemetrySavedObject(params);
+ return getTelemetryOptIn({
+ currentKibanaVersion,
+ telemetrySavedObject,
+ allowChangingOptInStatus,
+ configTelemetryOptIn,
+ });
+}
+
+function getMockTelemetrySavedObject(params: CallGetTelemetryOptInParams): TelemetrySavedObject {
+ const { savedObjectNotFound, savedObjectForbidden } = params;
+ if (savedObjectForbidden) {
+ return false;
+ }
+ if (savedObjectNotFound) {
+ return null;
+ }
+
+ return {
+ enabled: params.enabled,
+ lastVersionChecked: params.lastVersionChecked,
+ };
+}
diff --git a/src/legacy/core_plugins/telemetry/server/telemetry_config/get_telemetry_opt_in.ts b/src/legacy/core_plugins/telemetry/server/telemetry_config/get_telemetry_opt_in.ts
new file mode 100644
index 0000000000000..057a8b0c47958
--- /dev/null
+++ b/src/legacy/core_plugins/telemetry/server/telemetry_config/get_telemetry_opt_in.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 semver from 'semver';
+import { TelemetrySavedObject } from '../telemetry_repository/get_telemetry_saved_object';
+
+interface GetTelemetryOptInConfig {
+ telemetrySavedObject: TelemetrySavedObject;
+ currentKibanaVersion: string;
+ allowChangingOptInStatus: boolean;
+ configTelemetryOptIn: boolean | null;
+}
+
+type GetTelemetryOptIn = (config: GetTelemetryOptInConfig) => null | boolean;
+
+export const getTelemetryOptIn: GetTelemetryOptIn = ({
+ telemetrySavedObject,
+ currentKibanaVersion,
+ allowChangingOptInStatus,
+ configTelemetryOptIn,
+}) => {
+ if (typeof configTelemetryOptIn === 'boolean' && !allowChangingOptInStatus) {
+ return configTelemetryOptIn;
+ }
+
+ if (telemetrySavedObject === false) {
+ return false;
+ }
+
+ if (telemetrySavedObject === null || typeof telemetrySavedObject.enabled !== 'boolean') {
+ return null;
+ }
+
+ const savedOptIn = telemetrySavedObject.enabled;
+
+ // if enabled is true, return it
+ if (savedOptIn === true) return savedOptIn;
+
+ // Additional check if they've already opted out (enabled: false):
+ // - if the Kibana version has changed by at least a minor version,
+ // return null to re-prompt.
+
+ const lastKibanaVersion = telemetrySavedObject.lastVersionChecked;
+
+ // if the last kibana version isn't set, or is somehow not a string, return null
+ if (typeof lastKibanaVersion !== 'string') return null;
+
+ // if version hasn't changed, just return enabled value
+ if (lastKibanaVersion === currentKibanaVersion) return savedOptIn;
+
+ const lastSemver = parseSemver(lastKibanaVersion);
+ const currentSemver = parseSemver(currentKibanaVersion);
+
+ // if either version is invalid, return null
+ if (lastSemver == null || currentSemver == null) return null;
+
+ // actual major/minor version comparison, for cases when to return null
+ if (currentSemver.major > lastSemver.major) return null;
+ if (currentSemver.major === lastSemver.major) {
+ if (currentSemver.minor > lastSemver.minor) return null;
+ }
+
+ // current version X.Y is not greater than last version X.Y, return enabled
+ return savedOptIn;
+};
+
+function parseSemver(version: string): semver.SemVer | null {
+ // semver functions both return nulls AND throw exceptions: "it depends!"
+ try {
+ return semver.parse(version);
+ } catch (err) {
+ return null;
+ }
+}
diff --git a/src/legacy/core_plugins/telemetry/server/telemetry_config/get_telemetry_usage_fetcher.test.ts b/src/legacy/core_plugins/telemetry/server/telemetry_config/get_telemetry_usage_fetcher.test.ts
new file mode 100644
index 0000000000000..f2f99104433a3
--- /dev/null
+++ b/src/legacy/core_plugins/telemetry/server/telemetry_config/get_telemetry_usage_fetcher.test.ts
@@ -0,0 +1,85 @@
+/*
+ * 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 { getTelemetryUsageFetcher } from './get_telemetry_usage_fetcher';
+import { TelemetrySavedObject } from '../telemetry_repository/get_telemetry_saved_object';
+
+describe('getTelemetryUsageFetcher', () => {
+ it('returns kibana.yml config when saved object not found', () => {
+ const params: CallGetTelemetryUsageFetcherParams = {
+ savedObjectNotFound: true,
+ configSendUsageFrom: 'browser',
+ };
+
+ const result = callGetTelemetryUsageFetcher(params);
+
+ expect(result).toBe('browser');
+ });
+
+ it('returns kibana.yml config when saved object forbidden', () => {
+ const params: CallGetTelemetryUsageFetcherParams = {
+ savedObjectForbidden: true,
+ configSendUsageFrom: 'browser',
+ };
+
+ const result = callGetTelemetryUsageFetcher(params);
+
+ expect(result).toBe('browser');
+ });
+
+ it('returns kibana.yml config when saved object sendUsageFrom is undefined', () => {
+ const params: CallGetTelemetryUsageFetcherParams = {
+ savedSendUsagefrom: undefined,
+ configSendUsageFrom: 'server',
+ };
+
+ const result = callGetTelemetryUsageFetcher(params);
+
+ expect(result).toBe('server');
+ });
+});
+
+interface CallGetTelemetryUsageFetcherParams {
+ savedObjectNotFound?: boolean;
+ savedObjectForbidden?: boolean;
+ savedSendUsagefrom?: 'browser' | 'server';
+ configSendUsageFrom: 'browser' | 'server';
+}
+
+function callGetTelemetryUsageFetcher(params: CallGetTelemetryUsageFetcherParams) {
+ const telemetrySavedObject = getMockTelemetrySavedObject(params);
+ const configTelemetrySendUsageFrom = params.configSendUsageFrom;
+ return getTelemetryUsageFetcher({ configTelemetrySendUsageFrom, telemetrySavedObject });
+}
+
+function getMockTelemetrySavedObject(
+ params: CallGetTelemetryUsageFetcherParams
+): TelemetrySavedObject {
+ const { savedObjectNotFound, savedObjectForbidden } = params;
+ if (savedObjectForbidden) {
+ return false;
+ }
+ if (savedObjectNotFound) {
+ return null;
+ }
+
+ return {
+ sendUsageFrom: params.savedSendUsagefrom,
+ };
+}
diff --git a/src/legacy/core_plugins/telemetry/server/telemetry_config/get_telemetry_usage_fetcher.ts b/src/legacy/core_plugins/telemetry/server/telemetry_config/get_telemetry_usage_fetcher.ts
new file mode 100644
index 0000000000000..98f2d6b0c7bbf
--- /dev/null
+++ b/src/legacy/core_plugins/telemetry/server/telemetry_config/get_telemetry_usage_fetcher.ts
@@ -0,0 +1,39 @@
+/*
+ * 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 { TelemetrySavedObject } from '../telemetry_repository/get_telemetry_saved_object';
+
+interface GetTelemetryUsageFetcherConfig {
+ configTelemetrySendUsageFrom: 'browser' | 'server';
+ telemetrySavedObject: TelemetrySavedObject;
+}
+
+export function getTelemetryUsageFetcher({
+ telemetrySavedObject,
+ configTelemetrySendUsageFrom,
+}: GetTelemetryUsageFetcherConfig) {
+ if (!telemetrySavedObject) {
+ return configTelemetrySendUsageFrom;
+ }
+
+ if (typeof telemetrySavedObject.sendUsageFrom === 'undefined') {
+ return configTelemetrySendUsageFrom;
+ }
+
+ return telemetrySavedObject.sendUsageFrom;
+}
diff --git a/src/legacy/core_plugins/telemetry/server/telemetry_config/index.ts b/src/legacy/core_plugins/telemetry/server/telemetry_config/index.ts
new file mode 100644
index 0000000000000..25b588b99a3b8
--- /dev/null
+++ b/src/legacy/core_plugins/telemetry/server/telemetry_config/index.ts
@@ -0,0 +1,23 @@
+/*
+ * 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 { replaceTelemetryInjectedVars } from './replace_injected_vars';
+export { getTelemetryOptIn } from './get_telemetry_opt_in';
+export { getTelemetryUsageFetcher } from './get_telemetry_usage_fetcher';
+export { getTelemetryAllowChangingOptInStatus } from './get_telemetry_allow_changing_opt_in_status';
diff --git a/src/legacy/core_plugins/telemetry/server/telemetry_config/replace_injected_vars.ts b/src/legacy/core_plugins/telemetry/server/telemetry_config/replace_injected_vars.ts
new file mode 100644
index 0000000000000..c9b4f4ebcd650
--- /dev/null
+++ b/src/legacy/core_plugins/telemetry/server/telemetry_config/replace_injected_vars.ts
@@ -0,0 +1,63 @@
+/*
+ * 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 { getTelemetrySavedObject } from '../telemetry_repository';
+import { getTelemetryOptIn } from './get_telemetry_opt_in';
+import { getTelemetryUsageFetcher } from './get_telemetry_usage_fetcher';
+import { getTelemetryAllowChangingOptInStatus } from './get_telemetry_allow_changing_opt_in_status';
+
+export async function replaceTelemetryInjectedVars(request: any) {
+ const config = request.server.config();
+ const configTelemetrySendUsageFrom = config.get('telemetry.sendUsageFrom');
+ const configTelemetryOptIn = config.get('telemetry.optIn');
+ const configTelemetryAllowChangingOptInStatus = config.get('telemetry.allowChangingOptInStatus');
+ const isRequestingApplication = request.path.startsWith('/app');
+
+ // Prevent interstitial screens (such as the space selector) from prompting for telemetry
+ if (!isRequestingApplication) {
+ return {
+ telemetryOptedIn: false,
+ };
+ }
+
+ const currentKibanaVersion = config.get('pkg.version');
+ const savedObjectsClient = request.getSavedObjectsClient();
+ const telemetrySavedObject = await getTelemetrySavedObject(savedObjectsClient);
+ const allowChangingOptInStatus = getTelemetryAllowChangingOptInStatus({
+ configTelemetryAllowChangingOptInStatus,
+ telemetrySavedObject,
+ });
+
+ const telemetryOptedIn = getTelemetryOptIn({
+ configTelemetryOptIn,
+ allowChangingOptInStatus,
+ telemetrySavedObject,
+ currentKibanaVersion,
+ });
+
+ const telemetrySendUsageFrom = getTelemetryUsageFetcher({
+ configTelemetrySendUsageFrom,
+ telemetrySavedObject,
+ });
+
+ return {
+ telemetryOptedIn,
+ telemetrySendUsageFrom,
+ };
+}
diff --git a/src/legacy/core_plugins/telemetry/server/telemetry_repository/get_telemetry_saved_object.test.ts b/src/legacy/core_plugins/telemetry/server/telemetry_repository/get_telemetry_saved_object.test.ts
new file mode 100644
index 0000000000000..7cc177878de4d
--- /dev/null
+++ b/src/legacy/core_plugins/telemetry/server/telemetry_repository/get_telemetry_saved_object.test.ts
@@ -0,0 +1,104 @@
+/*
+ * 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 { getTelemetrySavedObject } from './get_telemetry_saved_object';
+import { SavedObjectsErrorHelpers } from '../../../../../core/server';
+
+describe('getTelemetrySavedObject', () => {
+ it('returns null when saved object not found', async () => {
+ const params = getCallGetTelemetrySavedObjectParams({
+ savedObjectNotFound: true,
+ });
+
+ const result = await callGetTelemetrySavedObject(params);
+
+ expect(result).toBe(null);
+ });
+
+ it('returns false when saved object forbidden', async () => {
+ const params = getCallGetTelemetrySavedObjectParams({
+ savedObjectForbidden: true,
+ });
+
+ const result = await callGetTelemetrySavedObject(params);
+
+ expect(result).toBe(false);
+ });
+
+ it('throws an error on unexpected saved object error', async () => {
+ const params = getCallGetTelemetrySavedObjectParams({
+ savedObjectOtherError: true,
+ });
+
+ let threw = false;
+ try {
+ await callGetTelemetrySavedObject(params);
+ } catch (err) {
+ threw = true;
+ expect(err.message).toBe(SavedObjectOtherErrorMessage);
+ }
+
+ expect(threw).toBe(true);
+ });
+});
+
+interface CallGetTelemetrySavedObjectParams {
+ savedObjectNotFound: boolean;
+ savedObjectForbidden: boolean;
+ savedObjectOtherError: boolean;
+ result?: any;
+}
+
+const DefaultParams = {
+ savedObjectNotFound: false,
+ savedObjectForbidden: false,
+ savedObjectOtherError: false,
+};
+
+function getCallGetTelemetrySavedObjectParams(
+ overrides: Partial
+): CallGetTelemetrySavedObjectParams {
+ return { ...DefaultParams, ...overrides };
+}
+
+async function callGetTelemetrySavedObject(params: CallGetTelemetrySavedObjectParams) {
+ const savedObjectsClient = getMockSavedObjectsClient(params);
+ return await getTelemetrySavedObject(savedObjectsClient);
+}
+
+const SavedObjectForbiddenMessage = 'savedObjectForbidden';
+const SavedObjectOtherErrorMessage = 'savedObjectOtherError';
+
+function getMockSavedObjectsClient(params: CallGetTelemetrySavedObjectParams) {
+ return {
+ async get(type: string, id: string) {
+ if (params.savedObjectNotFound) throw SavedObjectsErrorHelpers.createGenericNotFoundError();
+ if (params.savedObjectForbidden)
+ throw SavedObjectsErrorHelpers.decorateForbiddenError(
+ new Error(SavedObjectForbiddenMessage)
+ );
+ if (params.savedObjectOtherError)
+ throw SavedObjectsErrorHelpers.decorateGeneralError(
+ new Error(SavedObjectOtherErrorMessage)
+ );
+
+ return { attributes: { enabled: null } };
+ },
+ };
+}
diff --git a/src/legacy/core_plugins/telemetry/server/get_telemetry_opt_in.ts b/src/legacy/core_plugins/telemetry/server/telemetry_repository/get_telemetry_saved_object.ts
similarity index 64%
rename from src/legacy/core_plugins/telemetry/server/get_telemetry_opt_in.ts
rename to src/legacy/core_plugins/telemetry/server/telemetry_repository/get_telemetry_saved_object.ts
index 9b365d6dd7ae5..91965ef201ecb 100644
--- a/src/legacy/core_plugins/telemetry/server/get_telemetry_opt_in.ts
+++ b/src/legacy/core_plugins/telemetry/server/telemetry_repository/get_telemetry_saved_object.ts
@@ -17,30 +17,27 @@
* under the License.
*/
-export async function getTelemetryOptIn(request: any) {
- const isRequestingApplication = request.path.startsWith('/app');
+import { TelemetrySavedObjectAttributes } from './';
+import { SavedObjectsErrorHelpers } from '../../../../../core/server';
- // Prevent interstitial screens (such as the space selector) from prompting for telemetry
- if (!isRequestingApplication) {
- return false;
- }
-
- const savedObjectsClient = request.getSavedObjectsClient();
+export type TelemetrySavedObject = TelemetrySavedObjectAttributes | null | false;
+type GetTelemetrySavedObject = (repository: any) => Promise;
+export const getTelemetrySavedObject: GetTelemetrySavedObject = async (repository: any) => {
try {
- const { attributes } = await savedObjectsClient.get('telemetry', 'telemetry');
- return attributes.enabled;
+ const { attributes } = await repository.get('telemetry', 'telemetry');
+ return attributes;
} catch (error) {
- if (savedObjectsClient.errors.isNotFoundError(error)) {
+ if (SavedObjectsErrorHelpers.isNotFoundError(error)) {
return null;
}
// if we aren't allowed to get the telemetry document, we can assume that we won't
// be able to opt into telemetry either, so we're returning `false` here instead of null
- if (savedObjectsClient.errors.isForbiddenError(error)) {
+ if (SavedObjectsErrorHelpers.isForbiddenError(error)) {
return false;
}
throw error;
}
-}
+};
diff --git a/src/legacy/core_plugins/telemetry/server/telemetry_repository/index.ts b/src/legacy/core_plugins/telemetry/server/telemetry_repository/index.ts
new file mode 100644
index 0000000000000..f3629abc1620c
--- /dev/null
+++ b/src/legacy/core_plugins/telemetry/server/telemetry_repository/index.ts
@@ -0,0 +1,29 @@
+/*
+ * 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 { getTelemetrySavedObject, TelemetrySavedObject } from './get_telemetry_saved_object';
+export { updateTelemetrySavedObject } from './update_telemetry_saved_object';
+
+export interface TelemetrySavedObjectAttributes {
+ enabled?: boolean | null;
+ lastVersionChecked?: string;
+ sendUsageFrom?: 'browser' | 'server';
+ lastReported?: number;
+ telemetryAllowChangingOptInStatus?: boolean;
+}
diff --git a/src/legacy/core_plugins/telemetry/server/telemetry_repository/update_telemetry_saved_object.ts b/src/legacy/core_plugins/telemetry/server/telemetry_repository/update_telemetry_saved_object.ts
new file mode 100644
index 0000000000000..b66e01faaa6bc
--- /dev/null
+++ b/src/legacy/core_plugins/telemetry/server/telemetry_repository/update_telemetry_saved_object.ts
@@ -0,0 +1,38 @@
+/*
+ * 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 { TelemetrySavedObjectAttributes } from './';
+import { SavedObjectsErrorHelpers } from '../../../../../core/server';
+
+export async function updateTelemetrySavedObject(
+ savedObjectsClient: any,
+ savedObjectAttributes: TelemetrySavedObjectAttributes
+) {
+ try {
+ return await savedObjectsClient.update('telemetry', 'telemetry', savedObjectAttributes);
+ } catch (err) {
+ if (SavedObjectsErrorHelpers.isNotFoundError(err)) {
+ return await savedObjectsClient.create('telemetry', savedObjectAttributes, {
+ id: 'telemetry',
+ overwrite: true,
+ });
+ }
+ throw err;
+ }
+}
diff --git a/src/legacy/core_plugins/tile_map/public/tile_map_visualization.js b/src/legacy/core_plugins/tile_map/public/tile_map_visualization.js
index ca798b6bf2470..560a5c93c938c 100644
--- a/src/legacy/core_plugins/tile_map/public/tile_map_visualization.js
+++ b/src/legacy/core_plugins/tile_map/public/tile_map_visualization.js
@@ -79,6 +79,7 @@ export const createTileMapVisualization = ({ serviceSettings, $injector }) => {
return;
}
if (precisionChange) {
+ updateGeohashAgg();
this.vis.updateState();
} else {
//when we filter queries by collar
diff --git a/src/legacy/core_plugins/timelion/public/legacy.ts b/src/legacy/core_plugins/timelion/public/legacy.ts
index 77cd94279c879..d989a68d40eeb 100644
--- a/src/legacy/core_plugins/timelion/public/legacy.ts
+++ b/src/legacy/core_plugins/timelion/public/legacy.ts
@@ -21,13 +21,12 @@ import { PluginInitializerContext } from 'kibana/public';
import { npSetup, npStart } from 'ui/new_platform';
import { plugin } from '.';
import { setup as visualizations } from '../../visualizations/public/np_ready/public/legacy';
-import { setup as data } from '../../data/public/legacy';
import { TimelionPluginSetupDependencies } from './plugin';
import { LegacyDependenciesPlugin } from './shim';
const setupPlugins: Readonly = {
visualizations,
- data,
+ data: npSetup.plugins.data,
expressions: npSetup.plugins.expressions,
// Temporary solution
diff --git a/src/legacy/core_plugins/timelion/public/plugin.ts b/src/legacy/core_plugins/timelion/public/plugin.ts
index 6447e3bbc5f51..6291948f75077 100644
--- a/src/legacy/core_plugins/timelion/public/plugin.ts
+++ b/src/legacy/core_plugins/timelion/public/plugin.ts
@@ -25,12 +25,11 @@ import {
HttpSetup,
} from 'kibana/public';
import { Plugin as ExpressionsPlugin } from 'src/plugins/expressions/public';
+import { DataPublicPluginSetup, TimefilterContract } from 'src/plugins/data/public';
import { VisualizationsSetup } from '../../visualizations/public/np_ready/public';
import { getTimelionVisualizationConfig } from './timelion_vis_fn';
import { getTimelionVisualization } from './vis';
import { getTimeChart } from './panels/timechart/timechart';
-import { DataSetup } from '../../data/public';
-import { TimefilterSetup } from '../../data/public/timefilter';
import { Panel } from './panels/panel';
import { LegacyDependenciesPlugin, LegacyDependenciesPluginSetup } from './shim';
@@ -39,14 +38,14 @@ export interface TimelionVisualizationDependencies extends LegacyDependenciesPlu
uiSettings: UiSettingsClientContract;
http: HttpSetup;
timelionPanels: Map;
- timefilter: TimefilterSetup;
+ timefilter: TimefilterContract;
}
/** @internal */
export interface TimelionPluginSetupDependencies {
expressions: ReturnType;
visualizations: VisualizationsSetup;
- data: DataSetup;
+ data: DataPublicPluginSetup;
// Temporary solution
__LEGACY: LegacyDependenciesPlugin;
@@ -69,8 +68,8 @@ export class TimelionPlugin implements Plugin, void> {
const dependencies: TimelionVisualizationDependencies = {
uiSettings: core.uiSettings,
http: core.http,
- timefilter: data.timefilter,
timelionPanels,
+ timefilter: data.query.timefilter.timefilter,
...(await __LEGACY.setup(core, timelionPanels)),
};
diff --git a/src/legacy/core_plugins/timelion/public/vis/timelion_request_handler.ts b/src/legacy/core_plugins/timelion/public/vis/timelion_request_handler.ts
index eb4fb3f397149..6239e4027c392 100644
--- a/src/legacy/core_plugins/timelion/public/vis/timelion_request_handler.ts
+++ b/src/legacy/core_plugins/timelion/public/vis/timelion_request_handler.ts
@@ -18,12 +18,12 @@
*/
// @ts-ignore
-import { buildEsQuery, getEsQueryConfig, Filter } from '@kbn/es-query';
+import { buildEsQuery, getEsQueryConfig } from '@kbn/es-query';
// @ts-ignore
import { timezoneProvider } from 'ui/vis/lib/timezone';
import { KIBANA_CONTEXT_NAME } from 'src/plugins/expressions/public';
import { Query } from 'src/legacy/core_plugins/data/public';
-import { TimeRange } from 'src/plugins/data/public';
+import { TimeRange, esFilters } from 'src/plugins/data/public';
import { VisParams } from 'ui/vis';
import { i18n } from '@kbn/i18n';
import { TimelionVisualizationDependencies } from '../plugin';
@@ -60,7 +60,7 @@ export function getTimelionRequestHandler(dependencies: TimelionVisualizationDep
visParams,
}: {
timeRange: TimeRange;
- filters: Filter[];
+ filters: esFilters.Filter[];
query: Query;
visParams: VisParams;
forceFetch?: boolean;
@@ -78,7 +78,7 @@ export function getTimelionRequestHandler(dependencies: TimelionVisualizationDep
const esQueryConfigs = getEsQueryConfig(uiSettings);
// parse the time range client side to make sure it behaves like other charts
- const timeRangeBounds = timefilter.timefilter.calculateBounds(timeRange);
+ const timeRangeBounds = timefilter.calculateBounds(timeRange);
try {
return await http.post('../api/timelion/run', {
diff --git a/src/legacy/core_plugins/ui_metric/index.ts b/src/legacy/core_plugins/ui_metric/index.ts
index 6c957f23b5c40..964e3497accba 100644
--- a/src/legacy/core_plugins/ui_metric/index.ts
+++ b/src/legacy/core_plugins/ui_metric/index.ts
@@ -39,13 +39,13 @@ export default function(kibana: any) {
injectDefaultVars(server: Server) {
const config = server.config();
return {
+ uiMetricEnabled: config.get('ui_metric.enabled'),
debugUiMetric: config.get('ui_metric.debug'),
};
},
mappings: require('./mappings.json'),
hacks: ['plugins/ui_metric/hacks/ui_metric_init'],
},
-
init(server: Legacy.Server) {
registerUiMetricRoute(server);
},
diff --git a/src/legacy/core_plugins/ui_metric/public/hacks/ui_metric_init.ts b/src/legacy/core_plugins/ui_metric/public/hacks/ui_metric_init.ts
index 7aafc82cfe4c6..983434f09922b 100644
--- a/src/legacy/core_plugins/ui_metric/public/hacks/ui_metric_init.ts
+++ b/src/legacy/core_plugins/ui_metric/public/hacks/ui_metric_init.ts
@@ -20,15 +20,26 @@
// @ts-ignore
import { uiModules } from 'ui/modules';
import chrome from 'ui/chrome';
-import { createAnalyticsReporter, setTelemetryReporter } from '../services/telemetry_analytics';
+import { kfetch } from 'ui/kfetch';
+import {
+ createAnalyticsReporter,
+ setTelemetryReporter,
+ trackUserAgent,
+} from '../services/telemetry_analytics';
+import { isUnauthenticated } from '../../../telemetry/public/services';
function telemetryInit($injector: any) {
- const localStorage = $injector.get('localStorage');
+ const uiMetricEnabled = chrome.getInjected('uiMetricEnabled');
const debug = chrome.getInjected('debugUiMetric');
- const $http = $injector.get('$http');
- const basePath = chrome.getBasePath();
- const uiReporter = createAnalyticsReporter({ localStorage, $http, basePath, debug });
+ if (!uiMetricEnabled || isUnauthenticated()) {
+ return;
+ }
+ const localStorage = $injector.get('localStorage');
+
+ const uiReporter = createAnalyticsReporter({ localStorage, debug, kfetch });
setTelemetryReporter(uiReporter);
+ uiReporter.start();
+ trackUserAgent('kibana');
}
uiModules.get('kibana').run(telemetryInit);
diff --git a/src/legacy/core_plugins/ui_metric/public/index.ts b/src/legacy/core_plugins/ui_metric/public/index.ts
index b1e78b56d05d0..5c327234b1e7c 100644
--- a/src/legacy/core_plugins/ui_metric/public/index.ts
+++ b/src/legacy/core_plugins/ui_metric/public/index.ts
@@ -17,5 +17,5 @@
* under the License.
*/
-export { createUiStatsReporter } from './services/telemetry_analytics';
-export { METRIC_TYPE } from '@kbn/analytics';
+export { createUiStatsReporter, trackUserAgent } from './services/telemetry_analytics';
+export { METRIC_TYPE, UiStatsMetricType } from '@kbn/analytics';
diff --git a/src/legacy/core_plugins/ui_metric/public/services/telemetry_analytics.ts b/src/legacy/core_plugins/ui_metric/public/services/telemetry_analytics.ts
index 7310ee5b5f172..ee928b8a1d9ee 100644
--- a/src/legacy/core_plugins/ui_metric/public/services/telemetry_analytics.ts
+++ b/src/legacy/core_plugins/ui_metric/public/services/telemetry_analytics.ts
@@ -17,7 +17,9 @@
* under the License.
*/
-import { createReporter, Reporter, UiStatsMetricType } from '@kbn/analytics';
+import { Reporter, UiStatsMetricType } from '@kbn/analytics';
+// @ts-ignore
+import { addSystemApiHeader } from 'ui/system_api';
let telemetryReporter: Reporter;
@@ -39,28 +41,36 @@ export const createUiStatsReporter = (appName: string) => (
}
};
+export const trackUserAgent = (appName: string) => {
+ if (telemetryReporter) {
+ return telemetryReporter.reportUserAgent(appName);
+ }
+};
+
interface AnalyicsReporterConfig {
localStorage: any;
- basePath: string;
debug: boolean;
- $http: ng.IHttpService;
+ kfetch: any;
}
export function createAnalyticsReporter(config: AnalyicsReporterConfig) {
- const { localStorage, basePath, debug } = config;
+ const { localStorage, debug, kfetch } = config;
- return createReporter({
+ return new Reporter({
debug,
storage: localStorage,
async http(report) {
- const url = `${basePath}/api/telemetry/report`;
- await fetch(url, {
+ const response = await kfetch({
method: 'POST',
- headers: {
- 'kbn-xsrf': 'true',
- },
- body: JSON.stringify({ report }),
+ pathname: '/api/telemetry/report',
+ body: JSON.stringify(report),
+ headers: addSystemApiHeader({}),
});
+
+ if (response.status !== 'ok') {
+ throw Error('Unable to store report.');
+ }
+ return response;
},
});
}
diff --git a/src/legacy/core_plugins/ui_metric/server/routes/api/ui_metric.ts b/src/legacy/core_plugins/ui_metric/server/routes/api/ui_metric.ts
index 8a7950c46fa31..e2de23ea806e4 100644
--- a/src/legacy/core_plugins/ui_metric/server/routes/api/ui_metric.ts
+++ b/src/legacy/core_plugins/ui_metric/server/routes/api/ui_metric.ts
@@ -18,7 +18,6 @@
*/
import Joi from 'joi';
-import Boom from 'boom';
import { Report } from '@kbn/analytics';
import { Server } from 'hapi';
@@ -27,15 +26,27 @@ export async function storeReport(server: any, report: Report) {
const { callWithInternalUser } = server.plugins.elasticsearch.getCluster('admin');
const internalRepository = getSavedObjectsRepository(callWithInternalUser);
- const metricKeys = Object.keys(report.uiStatsMetrics);
- return Promise.all(
- metricKeys.map(async key => {
- const metric = report.uiStatsMetrics[key];
+ const uiStatsMetrics = report.uiStatsMetrics ? Object.entries(report.uiStatsMetrics) : [];
+ const userAgents = report.userAgent ? Object.entries(report.userAgent) : [];
+ return Promise.all([
+ ...userAgents.map(async ([key, metric]) => {
+ const { userAgent } = metric;
+ const savedObjectId = `${key}:${userAgent}`;
+ return await internalRepository.create(
+ 'ui-metric',
+ { count: 1 },
+ {
+ id: savedObjectId,
+ overwrite: true,
+ }
+ );
+ }),
+ ...uiStatsMetrics.map(async ([key, metric]) => {
const { appName, eventName } = metric;
const savedObjectId = `${appName}:${eventName}`;
- return internalRepository.incrementCounter('ui-metric', savedObjectId, 'count');
- })
- );
+ return await internalRepository.incrementCounter('ui-metric', savedObjectId, 'count');
+ }),
+ ]);
}
export function registerUiMetricRoute(server: Server) {
@@ -45,36 +56,46 @@ export function registerUiMetricRoute(server: Server) {
options: {
validate: {
payload: Joi.object({
- report: Joi.object({
- uiStatsMetrics: Joi.object()
- .pattern(
- /.*/,
- Joi.object({
- key: Joi.string().required(),
- type: Joi.string().required(),
- appName: Joi.string().required(),
- eventName: Joi.string().required(),
- stats: Joi.object({
- min: Joi.number(),
- sum: Joi.number(),
- max: Joi.number(),
- avg: Joi.number(),
- }).allow(null),
- })
- )
- .allow(null),
- }),
+ reportVersion: Joi.number().optional(),
+ userAgent: Joi.object()
+ .pattern(
+ /.*/,
+ Joi.object({
+ key: Joi.string().required(),
+ type: Joi.string().required(),
+ appName: Joi.string().required(),
+ userAgent: Joi.string().required(),
+ })
+ )
+ .allow(null)
+ .optional(),
+ uiStatsMetrics: Joi.object()
+ .pattern(
+ /.*/,
+ Joi.object({
+ key: Joi.string().required(),
+ type: Joi.string().required(),
+ appName: Joi.string().required(),
+ eventName: Joi.string().required(),
+ stats: Joi.object({
+ min: Joi.number(),
+ sum: Joi.number(),
+ max: Joi.number(),
+ avg: Joi.number(),
+ }).allow(null),
+ })
+ )
+ .allow(null),
}),
},
},
handler: async (req: any, h: any) => {
- const { report } = req.payload;
-
try {
+ const report = req.payload;
await storeReport(server, report);
- return {};
+ return { status: 'ok' };
} catch (error) {
- return new Boom('Something went wrong', { statusCode: error.status });
+ return { status: 'fail' };
}
},
});
diff --git a/src/legacy/core_plugins/vis_type_timeseries/public/components/vis_editor_visualization.js b/src/legacy/core_plugins/vis_type_timeseries/public/components/vis_editor_visualization.js
index f873cf9c178f8..ae82dc41fa9bc 100644
--- a/src/legacy/core_plugins/vis_type_timeseries/public/components/vis_editor_visualization.js
+++ b/src/legacy/core_plugins/vis_type_timeseries/public/components/vis_editor_visualization.js
@@ -75,13 +75,13 @@ class VisEditorVisualizationUI extends Component {
this._handler = await embeddables.getEmbeddableFactory('visualization').createFromObject(savedObj, {
vis: {},
timeRange: timeRange,
- filters: appState.filters || [],
+ filters: appState ? appState.filters || [] : [],
});
- this._handler.render(this._visEl.current);
+ await this._handler.render(this._visEl.current);
this._subscription = this._handler.handler.data$.subscribe(data => {
- this.setPanelInterval(data.visData);
- onDataChange(data);
+ this.setPanelInterval(data.value.visData);
+ onDataChange(data.value);
});
}
diff --git a/src/legacy/core_plugins/vis_type_timeseries/server/lib/get_index_pattern_service.js b/src/legacy/core_plugins/vis_type_timeseries/server/lib/get_index_pattern_service.js
index 0766e6a48765f..54e90ab7dd9b7 100644
--- a/src/legacy/core_plugins/vis_type_timeseries/server/lib/get_index_pattern_service.js
+++ b/src/legacy/core_plugins/vis_type_timeseries/server/lib/get_index_pattern_service.js
@@ -17,7 +17,7 @@
* under the License.
*/
-import { IndexPatternsService } from '../../../../server/index_patterns/service';
+import { IndexPatternsFetcher } from '../../../../../plugins/data/server/';
export const getIndexPatternService = {
assign: 'indexPatternsService',
method(req) {
@@ -25,6 +25,6 @@ export const getIndexPatternService = {
const callDataCluster = (...args) => {
return dataCluster.callWithRequest(req, ...args);
};
- return new IndexPatternsService(callDataCluster);
+ return new IndexPatternsFetcher(callDataCluster);
},
};
diff --git a/src/legacy/core_plugins/vis_type_vega/public/vega_request_handler.ts b/src/legacy/core_plugins/vis_type_vega/public/vega_request_handler.ts
index 22a71bd999d54..b4c32f37eb90c 100644
--- a/src/legacy/core_plugins/vis_type_vega/public/vega_request_handler.ts
+++ b/src/legacy/core_plugins/vis_type_vega/public/vega_request_handler.ts
@@ -16,13 +16,14 @@
* specific language governing permissions and limitations
* under the License.
*/
-import { Filter } from '@kbn/es-query';
+
import { timefilter } from 'ui/timefilter';
import { TimeRange } from 'src/plugins/data/public';
import { Query } from 'src/legacy/core_plugins/data/public';
-
-// @ts-ignore
import { buildEsQuery, getEsQueryConfig } from '@kbn/es-query';
+
+import { esFilters } from '../../../../plugins/data/public';
+
// @ts-ignore
import { VegaParser } from './data_model/vega_parser';
// @ts-ignore
@@ -35,7 +36,7 @@ import { VisParams } from './vega_fn';
interface VegaRequestHandlerParams {
query: Query;
- filters: Filter;
+ filters: esFilters.Filter;
timeRange: TimeRange;
visParams: VisParams;
}
diff --git a/src/legacy/core_plugins/vis_type_vega/public/vega_view/vega_base_view.js b/src/legacy/core_plugins/vis_type_vega/public/vega_view/vega_base_view.js
index ec898080c581e..5abb99e9bf716 100644
--- a/src/legacy/core_plugins/vis_type_vega/public/vega_view/vega_base_view.js
+++ b/src/legacy/core_plugins/vis_type_vega/public/vega_view/vega_base_view.js
@@ -27,7 +27,7 @@ import { Utils } from '../data_model/utils';
import { VISUALIZATION_COLORS } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { TooltipHandler } from './vega_tooltip';
-import { buildQueryFilter } from '@kbn/es-query';
+import { esFilters } from '../../../../../plugins/data/public';
import { getEnableExternalUrls } from '../helpers/vega_config_provider';
@@ -263,7 +263,7 @@ export class VegaBaseView {
*/
async addFilterHandler(query, index) {
const indexId = await this._findIndex(index);
- const filter = buildQueryFilter(query, indexId);
+ const filter = esFilters.buildQueryFilter(query, indexId);
this._queryfilter.addFilters(filter);
}
@@ -274,7 +274,7 @@ export class VegaBaseView {
async removeFilterHandler(query, index) {
const $injector = await chrome.dangerouslyGetActiveInjector();
const indexId = await this._findIndex(index);
- const filter = buildQueryFilter(query, indexId);
+ const filter = esFilters.buildQueryFilter(query, indexId);
// This is a workaround for the https://github.com/elastic/kibana/issues/18863
// Once fixed, replace with a direct call (no await is needed because its not async)
diff --git a/src/legacy/server/index_patterns/index.ts b/src/legacy/server/index_patterns/index.ts
index eea8a4a998e2d..75d0038cf9023 100644
--- a/src/legacy/server/index_patterns/index.ts
+++ b/src/legacy/server/index_patterns/index.ts
@@ -17,7 +17,9 @@
* under the License.
*/
-// @ts-ignore no types
export { indexPatternsMixin } from './mixin';
-export { IndexPatternsService, FieldDescriptor } from './service';
+export {
+ IndexPatternsFetcher,
+ FieldDescriptor,
+} from '../../../plugins/data/server/index_patterns/fetcher';
export { IndexPatternsServiceFactory } from './mixin';
diff --git a/src/legacy/server/index_patterns/mixin.ts b/src/legacy/server/index_patterns/mixin.ts
index a7180d6a2d70e..6b04c3842007b 100644
--- a/src/legacy/server/index_patterns/mixin.ts
+++ b/src/legacy/server/index_patterns/mixin.ts
@@ -17,11 +17,10 @@
* under the License.
*/
-import { IndexPatternsService } from './service';
+import { IndexPatternsFetcher } from '../../../plugins/data/server';
import KbnServer from '../kbn_server';
import { APICaller, CallAPIOptions } from '../../../core/server';
import { Legacy } from '../../../../kibana';
-import { registerRoutes } from './routes';
export function indexPatternsMixin(kbnServer: KbnServer, server: Legacy.Server) {
/**
@@ -31,7 +30,7 @@ export function indexPatternsMixin(kbnServer: KbnServer, server: Legacy.Server)
* @type {IndexPatternsService}
*/
server.decorate('server', 'indexPatternsServiceFactory', ({ callCluster }) => {
- return new IndexPatternsService(callCluster);
+ return new IndexPatternsFetcher(callCluster);
});
/**
@@ -50,10 +49,8 @@ export function indexPatternsMixin(kbnServer: KbnServer, server: Legacy.Server)
) => callWithRequest(request, endpoint, params, options);
return server.indexPatternsServiceFactory({ callCluster });
});
-
- registerRoutes(kbnServer.newPlatform.setup.core);
}
export type IndexPatternsServiceFactory = (args: {
callCluster: (endpoint: string, clientParams: any, options: any) => Promise;
-}) => IndexPatternsService;
+}) => IndexPatternsFetcher;
diff --git a/src/legacy/server/kbn_server.d.ts b/src/legacy/server/kbn_server.d.ts
index e7f2f4c85435f..9cc4e30d4252d 100644
--- a/src/legacy/server/kbn_server.d.ts
+++ b/src/legacy/server/kbn_server.d.ts
@@ -150,5 +150,5 @@ export default class KbnServer {
export { Server, Request, ResponseToolkit } from 'hapi';
// Re-export commonly accessed api types.
-export { IndexPatternsService } from './index_patterns';
+export { IndexPatternsFetcher as IndexPatternsService } from './index_patterns';
export { SavedObjectsLegacyService, SavedObjectsClient } from 'src/core/server';
diff --git a/src/legacy/server/usage/README.md b/src/legacy/server/usage/README.md
index ad1bb822b70cd..5c4bcc05bbc38 100644
--- a/src/legacy/server/usage/README.md
+++ b/src/legacy/server/usage/README.md
@@ -90,5 +90,3 @@ There are a few ways you can test that your usage collector is working properly.
Yes. When you talk to the Platform team about new fields being added, point out specifically which properties will have dynamic inner fields.
5. **If I accumulate an event counter in server memory, which my fetch method returns, won't it reset when the Kibana server restarts?**
Yes, but that is not a major concern. A visualization on such info might be a date histogram that gets events-per-second or something, which would be impacted by server restarts, so we'll have to offset the beginning of the time range when we detect that the latest metric is smaller than the earliest metric. That would be a pretty custom visualization, but perhaps future Kibana enhancements will be able to support that.
-6. **Who can I talk to with more questions?**
- The Kibana Platform team is the owner of the telemetry service. You can bring questions to them. You can also talk to Tim Sullivan, who created the Kibana telemetry service, or Chris Earle, who set up the telemetry cluster and AWS Lambas for the upstream prod and staging endpoints that recieve the data sent from end-user browsers.
diff --git a/src/legacy/ui/public/agg_types/agg_configs.ts b/src/legacy/ui/public/agg_types/agg_configs.ts
index 675d37d05c33c..7c0245f30a1fd 100644
--- a/src/legacy/ui/public/agg_types/agg_configs.ts
+++ b/src/legacy/ui/public/agg_types/agg_configs.ts
@@ -253,13 +253,10 @@ export class AggConfigs {
// collect all the aggregations
const aggregations = this.aggs
.filter(agg => agg.enabled && agg.type)
- .reduce(
- (requestValuesAggs, agg: AggConfig) => {
- const aggs = agg.getRequestAggs();
- return aggs ? requestValuesAggs.concat(aggs) : requestValuesAggs;
- },
- [] as AggConfig[]
- );
+ .reduce((requestValuesAggs, agg: AggConfig) => {
+ const aggs = agg.getRequestAggs();
+ return aggs ? requestValuesAggs.concat(aggs) : requestValuesAggs;
+ }, [] as AggConfig[]);
// move metrics to the end
return _.sortBy(aggregations, (agg: AggConfig) =>
agg.type.type === AggGroupNames.Metrics ? 1 : 0
@@ -282,13 +279,10 @@ export class AggConfigs {
* @return {array[AggConfig]}
*/
getResponseAggs(): AggConfig[] {
- return this.getRequestAggs().reduce(
- function(responseValuesAggs, agg: AggConfig) {
- const aggs = agg.getResponseAggs();
- return aggs ? responseValuesAggs.concat(aggs) : responseValuesAggs;
- },
- [] as AggConfig[]
- );
+ return this.getRequestAggs().reduce(function(responseValuesAggs, agg: AggConfig) {
+ const aggs = agg.getResponseAggs();
+ return aggs ? responseValuesAggs.concat(aggs) : responseValuesAggs;
+ }, [] as AggConfig[]);
}
/**
diff --git a/src/legacy/ui/public/agg_types/buckets/_terms_other_bucket_helper.js b/src/legacy/ui/public/agg_types/buckets/_terms_other_bucket_helper.js
index 5dfa2e3d6ae3f..70bca2e40ae3f 100644
--- a/src/legacy/ui/public/agg_types/buckets/_terms_other_bucket_helper.js
+++ b/src/legacy/ui/public/agg_types/buckets/_terms_other_bucket_helper.js
@@ -18,8 +18,9 @@
*/
import _ from 'lodash';
-import { buildExistsFilter, buildPhrasesFilter, buildQueryFromFilters } from '@kbn/es-query';
+import { buildQueryFromFilters } from '@kbn/es-query';
import { AggGroupNames } from '../../vis/editors/default/agg_groups';
+import { esFilters } from '../../../../../plugins/data/public';
/**
* walks the aggregation DSL and returns DSL starting at aggregation with id of startFromAggId
@@ -180,7 +181,7 @@ export const buildOtherBucketAgg = (aggConfigs, aggWithOtherBucket, response) =>
agg.buckets.some(bucket => bucket.key === '__missing__')
) {
filters.push(
- buildExistsFilter(
+ esFilters.buildExistsFilter(
aggWithOtherBucket.params.field,
aggWithOtherBucket.params.field.indexPattern
)
@@ -232,7 +233,7 @@ export const mergeOtherBucketAggResponse = (
);
const requestFilterTerms = getOtherAggTerms(requestAgg, key, otherAgg);
- const phraseFilter = buildPhrasesFilter(
+ const phraseFilter = esFilters.buildPhrasesFilter(
otherAgg.params.field,
requestFilterTerms,
otherAgg.params.field.indexPattern
@@ -243,7 +244,7 @@ export const mergeOtherBucketAggResponse = (
if (aggResultBuckets.some(bucket => bucket.key === '__missing__')) {
bucket.filters.push(
- buildExistsFilter(otherAgg.params.field, otherAgg.params.field.indexPattern)
+ esFilters.buildExistsFilter(otherAgg.params.field, otherAgg.params.field.indexPattern)
);
}
aggResultBuckets.push(bucket);
diff --git a/src/legacy/ui/public/agg_types/buckets/create_filter/date_histogram.test.ts b/src/legacy/ui/public/agg_types/buckets/create_filter/date_histogram.test.ts
index f67fa55b27859..9426df7d34c29 100644
--- a/src/legacy/ui/public/agg_types/buckets/create_filter/date_histogram.test.ts
+++ b/src/legacy/ui/public/agg_types/buckets/create_filter/date_histogram.test.ts
@@ -18,19 +18,19 @@
*/
import moment from 'moment';
-import { RangeFilter } from '@kbn/es-query';
import { createFilterDateHistogram } from './date_histogram';
import { intervalOptions } from '../_interval_options';
import { AggConfigs } from '../../agg_configs';
import { IBucketDateHistogramAggConfig } from '../date_histogram';
import { BUCKET_TYPES } from '../bucket_agg_types';
+import { esFilters } from '../../../../../../plugins/data/public';
jest.mock('ui/new_platform');
describe('AggConfig Filters', () => {
describe('date_histogram', () => {
let agg: IBucketDateHistogramAggConfig;
- let filter: RangeFilter;
+ let filter: esFilters.RangeFilter;
let bucketStart: any;
let field: any;
diff --git a/src/legacy/ui/public/agg_types/buckets/create_filter/date_histogram.ts b/src/legacy/ui/public/agg_types/buckets/create_filter/date_histogram.ts
index 8c6140cc4b37a..f91a92eab1c33 100644
--- a/src/legacy/ui/public/agg_types/buckets/create_filter/date_histogram.ts
+++ b/src/legacy/ui/public/agg_types/buckets/create_filter/date_histogram.ts
@@ -18,8 +18,8 @@
*/
import moment from 'moment';
-import { buildRangeFilter } from '@kbn/es-query';
import { IBucketDateHistogramAggConfig } from '../date_histogram';
+import { esFilters } from '../../../../../../plugins/data/public';
export const createFilterDateHistogram = (
agg: IBucketDateHistogramAggConfig,
@@ -28,7 +28,7 @@ export const createFilterDateHistogram = (
const start = moment(key);
const interval = agg.buckets.getInterval();
- return buildRangeFilter(
+ return esFilters.buildRangeFilter(
agg.params.field,
{
gte: start.toISOString(),
diff --git a/src/legacy/ui/public/agg_types/buckets/create_filter/date_range.ts b/src/legacy/ui/public/agg_types/buckets/create_filter/date_range.ts
index cd4b0ffc215b0..01689d954a072 100644
--- a/src/legacy/ui/public/agg_types/buckets/create_filter/date_range.ts
+++ b/src/legacy/ui/public/agg_types/buckets/create_filter/date_range.ts
@@ -17,16 +17,16 @@
* under the License.
*/
-import { buildRangeFilter, RangeFilterParams } from '@kbn/es-query';
import moment from 'moment';
import { IBucketAggConfig } from '../_bucket_agg_type';
import { DateRangeKey } from '../date_range';
+import { esFilters } from '../../../../../../plugins/data/public';
export const createFilterDateRange = (agg: IBucketAggConfig, { from, to }: DateRangeKey) => {
- const filter: RangeFilterParams = {};
+ const filter: esFilters.RangeFilterParams = {};
if (from) filter.gte = moment(from).toISOString();
if (to) filter.lt = moment(to).toISOString();
if (to && from) filter.format = 'strict_date_optional_time';
- return buildRangeFilter(agg.params.field, filter, agg.getIndexPattern());
+ return esFilters.buildRangeFilter(agg.params.field, filter, agg.getIndexPattern());
};
diff --git a/src/legacy/ui/public/agg_types/buckets/create_filter/filters.ts b/src/legacy/ui/public/agg_types/buckets/create_filter/filters.ts
index bf30b333056bc..6b614514580b6 100644
--- a/src/legacy/ui/public/agg_types/buckets/create_filter/filters.ts
+++ b/src/legacy/ui/public/agg_types/buckets/create_filter/filters.ts
@@ -18,8 +18,8 @@
*/
import { get } from 'lodash';
-import { buildQueryFilter } from '@kbn/es-query';
import { IBucketAggConfig } from '../_bucket_agg_type';
+import { esFilters } from '../../../../../../plugins/data/public';
export const createFilterFilters = (aggConfig: IBucketAggConfig, key: string) => {
// have the aggConfig write agg dsl params
@@ -28,6 +28,6 @@ export const createFilterFilters = (aggConfig: IBucketAggConfig, key: string) =>
const indexPattern = aggConfig.getIndexPattern();
if (filter && indexPattern && indexPattern.id) {
- return buildQueryFilter(filter.query, indexPattern.id, key);
+ return esFilters.buildQueryFilter(filter.query, indexPattern.id, key);
}
};
diff --git a/src/legacy/ui/public/agg_types/buckets/create_filter/histogram.ts b/src/legacy/ui/public/agg_types/buckets/create_filter/histogram.ts
index 37d5c6bc8adc1..fc587fa9ecdb6 100644
--- a/src/legacy/ui/public/agg_types/buckets/create_filter/histogram.ts
+++ b/src/legacy/ui/public/agg_types/buckets/create_filter/histogram.ts
@@ -17,14 +17,14 @@
* under the License.
*/
-import { buildRangeFilter, RangeFilterParams } from '@kbn/es-query';
import { IBucketAggConfig } from '../_bucket_agg_type';
+import { esFilters } from '../../../../../../plugins/data/public';
export const createFilterHistogram = (aggConfig: IBucketAggConfig, key: string) => {
const value = parseInt(key, 10);
- const params: RangeFilterParams = { gte: value, lt: value + aggConfig.params.interval };
+ const params: esFilters.RangeFilterParams = { gte: value, lt: value + aggConfig.params.interval };
- return buildRangeFilter(
+ return esFilters.buildRangeFilter(
aggConfig.params.field,
params,
aggConfig.getIndexPattern(),
diff --git a/src/legacy/ui/public/agg_types/buckets/create_filter/ip_range.ts b/src/legacy/ui/public/agg_types/buckets/create_filter/ip_range.ts
index 83769578725f2..803f6d97ae42d 100644
--- a/src/legacy/ui/public/agg_types/buckets/create_filter/ip_range.ts
+++ b/src/legacy/ui/public/agg_types/buckets/create_filter/ip_range.ts
@@ -17,13 +17,13 @@
* under the License.
*/
-import { buildRangeFilter, RangeFilterParams } from '@kbn/es-query';
import { CidrMask } from '../../../utils/cidr_mask';
import { IBucketAggConfig } from '../_bucket_agg_type';
import { IpRangeKey } from '../ip_range';
+import { esFilters } from '../../../../../../plugins/data/public';
export const createFilterIpRange = (aggConfig: IBucketAggConfig, key: IpRangeKey) => {
- let range: RangeFilterParams;
+ let range: esFilters.RangeFilterParams;
if (key.type === 'mask') {
range = new CidrMask(key.mask).getRange();
@@ -34,7 +34,7 @@ export const createFilterIpRange = (aggConfig: IBucketAggConfig, key: IpRangeKey
};
}
- return buildRangeFilter(
+ return esFilters.buildRangeFilter(
aggConfig.params.field,
{ gte: range.from, lte: range.to },
aggConfig.getIndexPattern()
diff --git a/src/legacy/ui/public/agg_types/buckets/create_filter/range.ts b/src/legacy/ui/public/agg_types/buckets/create_filter/range.ts
index cf2c83884651a..929827c6e3fec 100644
--- a/src/legacy/ui/public/agg_types/buckets/create_filter/range.ts
+++ b/src/legacy/ui/public/agg_types/buckets/create_filter/range.ts
@@ -17,11 +17,11 @@
* under the License.
*/
-import { buildRangeFilter } from '@kbn/es-query';
import { IBucketAggConfig } from '../_bucket_agg_type';
+import { esFilters } from '../../../../../../plugins/data/public';
export const createFilterRange = (aggConfig: IBucketAggConfig, params: any) => {
- return buildRangeFilter(
+ return esFilters.buildRangeFilter(
aggConfig.params.field,
params,
aggConfig.getIndexPattern(),
diff --git a/src/legacy/ui/public/agg_types/buckets/create_filter/terms.test.ts b/src/legacy/ui/public/agg_types/buckets/create_filter/terms.test.ts
index b00e939eac8d8..42f8349d5a2a3 100644
--- a/src/legacy/ui/public/agg_types/buckets/create_filter/terms.test.ts
+++ b/src/legacy/ui/public/agg_types/buckets/create_filter/terms.test.ts
@@ -16,10 +16,11 @@
* specific language governing permissions and limitations
* under the License.
*/
-import { ExistsFilter, Filter } from '@kbn/es-query';
+
import { createFilterTerms } from './terms';
import { AggConfigs } from '../../agg_configs';
import { BUCKET_TYPES } from '../bucket_agg_types';
+import { esFilters } from '../../../../../../plugins/data/public';
jest.mock('ui/new_platform');
@@ -48,7 +49,7 @@ describe('AggConfig Filters', () => {
{ type: BUCKET_TYPES.TERMS, schema: 'segment', params: { field: 'field' } },
]);
- const filter = createFilterTerms(aggConfigs.aggs[0], 'apache', {}) as Filter;
+ const filter = createFilterTerms(aggConfigs.aggs[0], 'apache', {}) as esFilters.Filter;
expect(filter).toHaveProperty('query');
expect(filter.query).toHaveProperty('match_phrase');
@@ -63,14 +64,14 @@ describe('AggConfig Filters', () => {
{ type: BUCKET_TYPES.TERMS, schema: 'segment', params: { field: 'field' } },
]);
- const filterFalse = createFilterTerms(aggConfigs.aggs[0], '', {}) as Filter;
+ const filterFalse = createFilterTerms(aggConfigs.aggs[0], '', {}) as esFilters.Filter;
expect(filterFalse).toHaveProperty('query');
expect(filterFalse.query).toHaveProperty('match_phrase');
expect(filterFalse.query.match_phrase).toHaveProperty('field');
expect(filterFalse.query.match_phrase.field).toBeFalsy();
- const filterTrue = createFilterTerms(aggConfigs.aggs[0], '1', {}) as Filter;
+ const filterTrue = createFilterTerms(aggConfigs.aggs[0], '1', {}) as esFilters.Filter;
expect(filterTrue).toHaveProperty('query');
expect(filterTrue.query).toHaveProperty('match_phrase');
@@ -82,7 +83,11 @@ describe('AggConfig Filters', () => {
const aggConfigs = getAggConfigs([
{ type: BUCKET_TYPES.TERMS, schema: 'segment', params: { field: 'field' } },
]);
- const filter = createFilterTerms(aggConfigs.aggs[0], '__missing__', {}) as ExistsFilter;
+ const filter = createFilterTerms(
+ aggConfigs.aggs[0],
+ '__missing__',
+ {}
+ ) as esFilters.ExistsFilter;
expect(filter).toHaveProperty('exists');
expect(filter.exists).toHaveProperty('field', 'field');
@@ -98,7 +103,7 @@ describe('AggConfig Filters', () => {
const [filter] = createFilterTerms(aggConfigs.aggs[0], '__other__', {
terms: ['apache'],
- }) as Filter[];
+ }) as esFilters.Filter[];
expect(filter).toHaveProperty('query');
expect(filter.query).toHaveProperty('bool');
diff --git a/src/legacy/ui/public/agg_types/buckets/create_filter/terms.ts b/src/legacy/ui/public/agg_types/buckets/create_filter/terms.ts
index e5d4406c752c7..5bd770e672786 100644
--- a/src/legacy/ui/public/agg_types/buckets/create_filter/terms.ts
+++ b/src/legacy/ui/public/agg_types/buckets/create_filter/terms.ts
@@ -17,8 +17,8 @@
* under the License.
*/
-import { Filter, buildPhraseFilter, buildPhrasesFilter, buildExistsFilter } from '@kbn/es-query';
import { IBucketAggConfig } from '../_bucket_agg_type';
+import { esFilters } from '../../../../../../plugins/data/public';
export const createFilterTerms = (aggConfig: IBucketAggConfig, key: string, params: any) => {
const field = aggConfig.params.field;
@@ -27,20 +27,20 @@ export const createFilterTerms = (aggConfig: IBucketAggConfig, key: string, para
if (key === '__other__') {
const terms = params.terms;
- const phraseFilter = buildPhrasesFilter(field, terms, indexPattern);
+ const phraseFilter = esFilters.buildPhrasesFilter(field, terms, indexPattern);
phraseFilter.meta.negate = true;
- const filters: Filter[] = [phraseFilter];
+ const filters: esFilters.Filter[] = [phraseFilter];
if (terms.some((term: string) => term === '__missing__')) {
- filters.push(buildExistsFilter(field, indexPattern));
+ filters.push(esFilters.buildExistsFilter(field, indexPattern));
}
return filters;
} else if (key === '__missing__') {
- const existsFilter = buildExistsFilter(field, indexPattern);
+ const existsFilter = esFilters.buildExistsFilter(field, indexPattern);
existsFilter.meta.negate = true;
return existsFilter;
}
- return buildPhraseFilter(field, key, indexPattern);
+ return esFilters.buildPhraseFilter(field, key, indexPattern);
};
diff --git a/src/legacy/ui/public/agg_types/buckets/date_histogram.ts b/src/legacy/ui/public/agg_types/buckets/date_histogram.ts
index 4c2e67f758a7e..e86d561a1c79b 100644
--- a/src/legacy/ui/public/agg_types/buckets/date_histogram.ts
+++ b/src/legacy/ui/public/agg_types/buckets/date_histogram.ts
@@ -32,7 +32,6 @@ import { ScaleMetricsParamEditor } from '../../vis/editors/default/controls/scal
import { dateHistogramInterval } from '../../../../core_plugins/data/public';
import { writeParams } from '../agg_params';
import { AggConfigs } from '../agg_configs';
-import { AggConfig } from '../agg_config';
import { isMetricAggType } from '../metrics/metric_agg_type';
import { KBN_FIELD_TYPES } from '../../../../../plugins/data/common';
@@ -189,7 +188,7 @@ export const dateHistogramBucketAgg = new BucketAggType isMetricAggType(a.type));
- const all = _.every(metrics, (a: AggConfig) => {
+ const all = _.every(metrics, (a: IBucketAggConfig) => {
const { type } = a;
if (isMetricAggType(type)) {
diff --git a/src/legacy/ui/public/agg_types/buckets/date_range.ts b/src/legacy/ui/public/agg_types/buckets/date_range.ts
index dd7f0cb972ae2..4de6002e2e374 100644
--- a/src/legacy/ui/public/agg_types/buckets/date_range.ts
+++ b/src/legacy/ui/public/agg_types/buckets/date_range.ts
@@ -21,9 +21,8 @@ import moment from 'moment-timezone';
import { i18n } from '@kbn/i18n';
import { npStart } from 'ui/new_platform';
import { BUCKET_TYPES } from './bucket_agg_types';
-import { BucketAggType } from './_bucket_agg_type';
+import { BucketAggType, IBucketAggConfig } from './_bucket_agg_type';
import { createFilterDateRange } from './create_filter/date_range';
-import { AggConfig } from '../agg_config';
import { FieldFormat } from '../../../../../plugins/data/common/field_formats';
import { DateRangesParamEditor } from '../../vis/editors/default/controls/date_ranges';
@@ -64,7 +63,7 @@ export const dateRangeBucketAgg = new BucketAggType({
name: 'field',
type: 'field',
filterFieldTypes: KBN_FIELD_TYPES.DATE,
- default(agg: AggConfig) {
+ default(agg: IBucketAggConfig) {
return agg.getIndexPattern().timeFieldName;
},
},
@@ -83,7 +82,7 @@ export const dateRangeBucketAgg = new BucketAggType({
default: undefined,
// Implimentation method is the same as that of date_histogram
serialize: () => undefined,
- write: (agg: AggConfig, output: Record) => {
+ write: (agg: IBucketAggConfig, output: Record) => {
const field = agg.getParam('field');
let tz = agg.getParam('time_zone');
diff --git a/src/legacy/ui/public/agg_types/buckets/geo_hash.test.ts b/src/legacy/ui/public/agg_types/buckets/geo_hash.test.ts
index 5c599f16e09c2..effa49f0ade6b 100644
--- a/src/legacy/ui/public/agg_types/buckets/geo_hash.test.ts
+++ b/src/legacy/ui/public/agg_types/buckets/geo_hash.test.ts
@@ -156,8 +156,9 @@ describe('Geohash Agg', () => {
describe('aggregation options', () => {
it('should only create geohash_grid and geo_centroid aggregations when isFilteredByCollar is false', () => {
const aggConfigs = getAggConfigs({ isFilteredByCollar: false });
- const requestAggs = geoHashBucketAgg.getRequestAggs(aggConfigs
- .aggs[0] as IBucketGeoHashGridAggConfig) as IBucketGeoHashGridAggConfig[];
+ const requestAggs = geoHashBucketAgg.getRequestAggs(
+ aggConfigs.aggs[0] as IBucketGeoHashGridAggConfig
+ ) as IBucketGeoHashGridAggConfig[];
expect(requestAggs.length).toEqual(2);
expect(requestAggs[0].type.name).toEqual('geohash_grid');
@@ -166,8 +167,9 @@ describe('Geohash Agg', () => {
it('should only create filter and geohash_grid aggregations when useGeocentroid is false', () => {
const aggConfigs = getAggConfigs({ useGeocentroid: false });
- const requestAggs = geoHashBucketAgg.getRequestAggs(aggConfigs
- .aggs[0] as IBucketGeoHashGridAggConfig) as IBucketGeoHashGridAggConfig[];
+ const requestAggs = geoHashBucketAgg.getRequestAggs(
+ aggConfigs.aggs[0] as IBucketGeoHashGridAggConfig
+ ) as IBucketGeoHashGridAggConfig[];
expect(requestAggs.length).toEqual(2);
expect(requestAggs[0].type.name).toEqual('filter');
@@ -179,36 +181,43 @@ describe('Geohash Agg', () => {
let originalRequestAggs: IBucketGeoHashGridAggConfig[];
beforeEach(() => {
- originalRequestAggs = geoHashBucketAgg.getRequestAggs(getAggConfigs()
- .aggs[0] as IBucketGeoHashGridAggConfig) as IBucketGeoHashGridAggConfig[];
+ originalRequestAggs = geoHashBucketAgg.getRequestAggs(
+ getAggConfigs().aggs[0] as IBucketGeoHashGridAggConfig
+ ) as IBucketGeoHashGridAggConfig[];
});
it('should change geo_bounding_box filter aggregation and vis session state when map movement is outside map collar', () => {
- const [, geoBoxingBox] = geoHashBucketAgg.getRequestAggs(getAggConfigs({
- mapBounds: {
- top_left: { lat: 10.0, lon: -10.0 },
- bottom_right: { lat: 9.0, lon: -9.0 },
- },
- }).aggs[0] as IBucketGeoHashGridAggConfig) as IBucketGeoHashGridAggConfig[];
+ const [, geoBoxingBox] = geoHashBucketAgg.getRequestAggs(
+ getAggConfigs({
+ mapBounds: {
+ top_left: { lat: 10.0, lon: -10.0 },
+ bottom_right: { lat: 9.0, lon: -9.0 },
+ },
+ }).aggs[0] as IBucketGeoHashGridAggConfig
+ ) as IBucketGeoHashGridAggConfig[];
expect(originalRequestAggs[1].params).not.toEqual(geoBoxingBox.params);
});
it('should not change geo_bounding_box filter aggregation and vis session state when map movement is within map collar', () => {
- const [, geoBoxingBox] = geoHashBucketAgg.getRequestAggs(getAggConfigs({
- mapBounds: {
- top_left: { lat: 1, lon: -1 },
- bottom_right: { lat: -1, lon: 1 },
- },
- }).aggs[0] as IBucketGeoHashGridAggConfig) as IBucketGeoHashGridAggConfig[];
+ const [, geoBoxingBox] = geoHashBucketAgg.getRequestAggs(
+ getAggConfigs({
+ mapBounds: {
+ top_left: { lat: 1, lon: -1 },
+ bottom_right: { lat: -1, lon: 1 },
+ },
+ }).aggs[0] as IBucketGeoHashGridAggConfig
+ ) as IBucketGeoHashGridAggConfig[];
expect(originalRequestAggs[1].params).toEqual(geoBoxingBox.params);
});
it('should change geo_bounding_box filter aggregation and vis session state when map zoom level changes', () => {
- const [, geoBoxingBox] = geoHashBucketAgg.getRequestAggs(getAggConfigs({
- mapZoom: -1,
- }).aggs[0] as IBucketGeoHashGridAggConfig) as IBucketGeoHashGridAggConfig[];
+ const [, geoBoxingBox] = geoHashBucketAgg.getRequestAggs(
+ getAggConfigs({
+ mapZoom: -1,
+ }).aggs[0] as IBucketGeoHashGridAggConfig
+ ) as IBucketGeoHashGridAggConfig[];
expect(originalRequestAggs[1].lastMapCollar).not.toEqual(geoBoxingBox.lastMapCollar);
});
diff --git a/src/legacy/ui/public/agg_types/buckets/geo_hash.ts b/src/legacy/ui/public/agg_types/buckets/geo_hash.ts
index 555aa94b636b8..1716891231b83 100644
--- a/src/legacy/ui/public/agg_types/buckets/geo_hash.ts
+++ b/src/legacy/ui/public/agg_types/buckets/geo_hash.ts
@@ -26,7 +26,6 @@ import { IsFilteredByCollarParamEditor } from '../../vis/editors/default/control
import { PrecisionParamEditor } from '../../vis/editors/default/controls/precision';
import { geohashColumns } from '../../utils/decode_geo_hash';
import { AggGroupNames } from '../../vis/editors/default/agg_groups';
-import { AggConfig } from '../agg_config';
import { KBN_FIELD_TYPES } from '../../../../../plugins/data/common';
// @ts-ignore
@@ -143,7 +142,7 @@ export const geoHashBucketAgg = new BucketAggType({
},
],
getRequestAggs(agg) {
- const aggs: AggConfig[] = [];
+ const aggs: IBucketAggConfig[] = [];
const params = agg.params;
if (params.isFilteredByCollar && agg.getField()) {
diff --git a/src/legacy/ui/public/agg_types/buckets/histogram.ts b/src/legacy/ui/public/agg_types/buckets/histogram.ts
index 74a2da4a0eb67..fba2f47010c34 100644
--- a/src/legacy/ui/public/agg_types/buckets/histogram.ts
+++ b/src/legacy/ui/public/agg_types/buckets/histogram.ts
@@ -28,7 +28,6 @@ import { NumberIntervalParamEditor } from '../../vis/editors/default/controls/nu
import { MinDocCountParamEditor } from '../../vis/editors/default/controls/min_doc_count';
import { HasExtendedBoundsParamEditor } from '../../vis/editors/default/controls/has_extended_bounds';
import { ExtendedBoundsParamEditor } from '../../vis/editors/default/controls/extended_bounds';
-import { AggConfig } from '../agg_config';
import { KBN_FIELD_TYPES } from '../../../../../plugins/data/common';
import { BUCKET_TYPES } from './bucket_agg_types';
@@ -177,7 +176,7 @@ export const histogramBucketAgg = new BucketAggType({
name: 'min_doc_count',
default: false,
editorComponent: MinDocCountParamEditor,
- write(aggConfig: AggConfig, output: Record) {
+ write(aggConfig: IBucketAggConfig, output: Record) {
if (aggConfig.params.min_doc_count) {
output.params.min_doc_count = 0;
} else {
@@ -198,14 +197,14 @@ export const histogramBucketAgg = new BucketAggType({
max: '',
},
editorComponent: ExtendedBoundsParamEditor,
- write(aggConfig: AggConfig, output: Record) {
+ write(aggConfig: IBucketAggConfig, output: Record) {
const { min, max } = aggConfig.params.extended_bounds;
if (aggConfig.params.has_extended_bounds && (min || min === 0) && (max || max === 0)) {
output.params.extended_bounds = { min, max };
}
},
- shouldShow: (aggConfig: AggConfig) => aggConfig.params.has_extended_bounds,
+ shouldShow: (aggConfig: IBucketAggConfig) => aggConfig.params.has_extended_bounds,
},
],
});
diff --git a/src/legacy/ui/public/agg_types/buckets/migrate_include_exclude_format.ts b/src/legacy/ui/public/agg_types/buckets/migrate_include_exclude_format.ts
index 2bf0930d37684..e4527ff87f48c 100644
--- a/src/legacy/ui/public/agg_types/buckets/migrate_include_exclude_format.ts
+++ b/src/legacy/ui/public/agg_types/buckets/migrate_include_exclude_format.ts
@@ -18,7 +18,6 @@
*/
import { isString, isObject } from 'lodash';
-import { AggConfig } from 'ui/agg_types';
import { IBucketAggConfig, BucketAggType, BucketAggParam } from './_bucket_agg_type';
export const isType = (type: string) => {
@@ -32,12 +31,16 @@ export const isType = (type: string) => {
export const isStringType = isType('string');
export const migrateIncludeExcludeFormat = {
- serialize(this: BucketAggParam, value: any, agg: AggConfig) {
+ serialize(this: BucketAggParam, value: any, agg: IBucketAggConfig) {
if (this.shouldShow && !this.shouldShow(agg)) return;
if (!value || isString(value)) return value;
else return value.pattern;
},
- write(this: BucketAggType, aggConfig: AggConfig, output: Record) {
+ write(
+ this: BucketAggType,
+ aggConfig: IBucketAggConfig,
+ output: Record
+ ) {
const value = aggConfig.getParam(this.name);
if (isObject(value)) {
diff --git a/src/legacy/ui/public/agg_types/buckets/range.test.ts b/src/legacy/ui/public/agg_types/buckets/range.test.ts
index f7cae60cce773..1b423e64c48ae 100644
--- a/src/legacy/ui/public/agg_types/buckets/range.test.ts
+++ b/src/legacy/ui/public/agg_types/buckets/range.test.ts
@@ -72,7 +72,10 @@ describe('Range Agg', () => {
schema: 'segment',
params: {
field: 'bytes',
- ranges: [{ from: 0, to: 1000 }, { from: 1000, to: 2000 }],
+ ranges: [
+ { from: 0, to: 1000 },
+ { from: 1000, to: 2000 },
+ ],
},
},
],
diff --git a/src/legacy/ui/public/agg_types/buckets/range.ts b/src/legacy/ui/public/agg_types/buckets/range.ts
index 348fccdab3fe3..230675ab487ad 100644
--- a/src/legacy/ui/public/agg_types/buckets/range.ts
+++ b/src/legacy/ui/public/agg_types/buckets/range.ts
@@ -98,7 +98,10 @@ export const rangeBucketAgg = new BucketAggType({
},
{
name: 'ranges',
- default: [{ from: 0, to: 1000 }, { from: 1000, to: 2000 }],
+ default: [
+ { from: 0, to: 1000 },
+ { from: 1000, to: 2000 },
+ ],
editorComponent: RangesEditor,
write(aggConfig: IBucketAggConfig, output: Record) {
output.params.ranges = aggConfig.params.ranges;
diff --git a/src/legacy/ui/public/agg_types/filter/prop_filter.ts b/src/legacy/ui/public/agg_types/filter/prop_filter.ts
index 45f350ea6adc8..e6b5f3831e65d 100644
--- a/src/legacy/ui/public/agg_types/filter/prop_filter.ts
+++ b/src/legacy/ui/public/agg_types/filter/prop_filter.ts
@@ -59,24 +59,21 @@ function propFilter(prop: P) {
return list;
}
- const options = filters.reduce(
- (acc, filter) => {
- let type = 'include';
- let value = filter;
+ const options = filters.reduce((acc, filter) => {
+ let type = 'include';
+ let value = filter;
- if (filter.charAt(0) === '!') {
- type = 'exclude';
- value = filter.substr(1);
- }
+ if (filter.charAt(0) === '!') {
+ type = 'exclude';
+ value = filter.substr(1);
+ }
- if (!acc[type]) {
- acc[type] = [];
- }
- acc[type].push(value);
- return acc;
- },
- {} as { [type: string]: string[] }
- );
+ if (!acc[type]) {
+ acc[type] = [];
+ }
+ acc[type].push(value);
+ return acc;
+ }, {} as { [type: string]: string[] });
return list.filter(item => {
const value = item[prop];
diff --git a/src/legacy/ui/public/agg_types/metrics/metric_agg_type.ts b/src/legacy/ui/public/agg_types/metrics/metric_agg_type.ts
index 66bc205cead13..c1f5528825bcc 100644
--- a/src/legacy/ui/public/agg_types/metrics/metric_agg_type.ts
+++ b/src/legacy/ui/public/agg_types/metrics/metric_agg_type.ts
@@ -58,8 +58,9 @@ export class MetricAggType<
config.getValue ||
((agg, bucket) => {
// Metric types where an empty set equals `zero`
- const isSettableToZero = [METRIC_TYPES.CARDINALITY, METRIC_TYPES.SUM].includes(agg.type
- .name as METRIC_TYPES);
+ const isSettableToZero = [METRIC_TYPES.CARDINALITY, METRIC_TYPES.SUM].includes(
+ agg.type.name as METRIC_TYPES
+ );
// Return proper values when no buckets are present
// `Count` handles empty sets properly
diff --git a/src/legacy/ui/public/agg_types/metrics/percentile_ranks.test.ts b/src/legacy/ui/public/agg_types/metrics/percentile_ranks.test.ts
index f3882ca57161f..7461b5cf07ee7 100644
--- a/src/legacy/ui/public/agg_types/metrics/percentile_ranks.test.ts
+++ b/src/legacy/ui/public/agg_types/metrics/percentile_ranks.test.ts
@@ -63,8 +63,9 @@ describe('AggTypesMetricsPercentileRanksProvider class', function() {
});
it('uses the custom label if it is set', function() {
- const responseAggs: any = percentileRanksMetricAgg.getResponseAggs(aggConfigs
- .aggs[0] as IPercentileRanksAggConfig);
+ const responseAggs: any = percentileRanksMetricAgg.getResponseAggs(
+ aggConfigs.aggs[0] as IPercentileRanksAggConfig
+ );
const percentileRankLabelFor5kBytes = responseAggs[0].makeLabel();
const percentileRankLabelFor10kBytes = responseAggs[1].makeLabel();
diff --git a/src/legacy/ui/public/agg_types/metrics/percentiles.test.ts b/src/legacy/ui/public/agg_types/metrics/percentiles.test.ts
index 1503f43b22dc3..c9f4bcc3862a0 100644
--- a/src/legacy/ui/public/agg_types/metrics/percentiles.test.ts
+++ b/src/legacy/ui/public/agg_types/metrics/percentiles.test.ts
@@ -63,8 +63,9 @@ describe('AggTypesMetricsPercentilesProvider class', () => {
});
it('uses the custom label if it is set', () => {
- const responseAggs: any = percentilesMetricAgg.getResponseAggs(aggConfigs
- .aggs[0] as IPercentileAggConfig);
+ const responseAggs: any = percentilesMetricAgg.getResponseAggs(
+ aggConfigs.aggs[0] as IPercentileAggConfig
+ );
const ninetyFifthPercentileLabel = responseAggs[0].makeLabel();
diff --git a/src/legacy/ui/public/agg_types/metrics/std_deviation.test.ts b/src/legacy/ui/public/agg_types/metrics/std_deviation.test.ts
index ae09b5cd78977..3125026a52185 100644
--- a/src/legacy/ui/public/agg_types/metrics/std_deviation.test.ts
+++ b/src/legacy/ui/public/agg_types/metrics/std_deviation.test.ts
@@ -58,8 +58,9 @@ describe('AggTypeMetricStandardDeviationProvider class', () => {
it('uses the custom label if it is set', () => {
const aggConfigs = getAggConfigs('custom label');
- const responseAggs: any = stdDeviationMetricAgg.getResponseAggs(aggConfigs
- .aggs[0] as IStdDevAggConfig);
+ const responseAggs: any = stdDeviationMetricAgg.getResponseAggs(
+ aggConfigs.aggs[0] as IStdDevAggConfig
+ );
const lowerStdDevLabel = responseAggs[0].makeLabel();
const upperStdDevLabel = responseAggs[1].makeLabel();
@@ -71,8 +72,9 @@ describe('AggTypeMetricStandardDeviationProvider class', () => {
it('uses the default labels if custom label is not set', () => {
const aggConfigs = getAggConfigs();
- const responseAggs: any = stdDeviationMetricAgg.getResponseAggs(aggConfigs
- .aggs[0] as IStdDevAggConfig);
+ const responseAggs: any = stdDeviationMetricAgg.getResponseAggs(
+ aggConfigs.aggs[0] as IStdDevAggConfig
+ );
const lowerStdDevLabel = responseAggs[0].makeLabel();
const upperStdDevLabel = responseAggs[1].makeLabel();
diff --git a/src/legacy/ui/public/chrome/directives/kbn_chrome.html b/src/legacy/ui/public/chrome/directives/kbn_chrome.html
index 541082e68de58..7738093fe9dea 100644
--- a/src/legacy/ui/public/chrome/directives/kbn_chrome.html
+++ b/src/legacy/ui/public/chrome/directives/kbn_chrome.html
@@ -1,4 +1,4 @@
-
+
{
- const searching = es.search({ index: index.title || index, body, ...searchParams })
- .catch(({ response }) => JSON.parse(response));
+ const searching = es.search({ index: index.title || index, body, ...searchParams });
abortController.signal.addEventListener('abort', searching.abort);
- return searching;
+ return searching.catch(({ response }) => JSON.parse(response));
});
return {
searching: Promise.all(promises),
diff --git a/src/legacy/ui/public/courier/search_strategy/default_search_strategy.test.js b/src/legacy/ui/public/courier/search_strategy/default_search_strategy.test.js
index 953ca4fe800f1..a1ea53e8b5b47 100644
--- a/src/legacy/ui/public/courier/search_strategy/default_search_strategy.test.js
+++ b/src/legacy/ui/public/courier/search_strategy/default_search_strategy.test.js
@@ -27,16 +27,29 @@ function getConfigStub(config = {}) {
};
}
+const msearchMockResponse = Promise.resolve([]);
+msearchMockResponse.abort = jest.fn();
+const msearchMock = jest.fn().mockReturnValue(msearchMockResponse);
+
+const searchMockResponse = Promise.resolve([]);
+searchMockResponse.abort = jest.fn();
+const searchMock = jest.fn().mockReturnValue(searchMockResponse);
+
describe('defaultSearchStrategy', function () {
describe('search', function () {
let searchArgs;
beforeEach(() => {
- const msearchMock = jest.fn().mockReturnValue(Promise.resolve([]));
- const searchMock = jest.fn().mockReturnValue(Promise.resolve([]));
+ msearchMockResponse.abort.mockClear();
+ msearchMock.mockClear();
+
+ searchMockResponse.abort.mockClear();
+ searchMock.mockClear();
searchArgs = {
- searchRequests: [],
+ searchRequests: [{
+ index: { title: 'foo' }
+ }],
es: {
msearch: msearchMock,
search: searchMock,
@@ -73,5 +86,21 @@ describe('defaultSearchStrategy', function () {
await search(searchArgs);
expect(searchArgs.es.msearch.mock.calls[0][0]).toHaveProperty('ignore_throttled', false);
});
+
+ test('should properly call abort with msearch', () => {
+ searchArgs.config = getConfigStub({
+ 'courier:batchSearches': true
+ });
+ search(searchArgs).abort();
+ expect(msearchMockResponse.abort).toHaveBeenCalled();
+ });
+
+ test('should properly abort with search', async () => {
+ searchArgs.config = getConfigStub({
+ 'courier:batchSearches': false
+ });
+ search(searchArgs).abort();
+ expect(searchMockResponse.abort).toHaveBeenCalled();
+ });
});
});
diff --git a/src/legacy/ui/public/filter_manager/__tests__/filter_generator.js b/src/legacy/ui/public/filter_manager/__tests__/filter_generator.js
index ed7e25704d5a5..5b6455bf20847 100644
--- a/src/legacy/ui/public/filter_manager/__tests__/filter_generator.js
+++ b/src/legacy/ui/public/filter_manager/__tests__/filter_generator.js
@@ -24,8 +24,8 @@ import expect from '@kbn/expect';
import ngMock from 'ng_mock';
import { getFilterGenerator } from '..';
import { FilterBarQueryFilterProvider } from '../../filter_manager/query_filter';
-import { uniqFilters } from '../../../../../plugins/data/public';
-import { getPhraseScript } from '@kbn/es-query';
+import { uniqFilters, esFilters } from '../../../../../plugins/data/public';
+
let queryFilter;
let filterGen;
let appState;
@@ -137,14 +137,14 @@ describe('Filter Manager', function () {
filterGen.add(scriptedField, 1, '+', 'myIndex');
checkAddFilters(1, [{
meta: { index: 'myIndex', negate: false, field: 'scriptedField' },
- script: getPhraseScript(scriptedField, 1)
+ script: esFilters.getPhraseScript(scriptedField, 1)
}], 4);
expect(appState.filters).to.have.length(3);
filterGen.add(scriptedField, 1, '-', 'myIndex');
checkAddFilters(1, [{
meta: { index: 'myIndex', negate: true, disabled: false, field: 'scriptedField' },
- script: getPhraseScript(scriptedField, 1)
+ script: esFilters.getPhraseScript(scriptedField, 1)
}], 5);
expect(appState.filters).to.have.length(3);
});
diff --git a/src/legacy/ui/public/filter_manager/filter_generator.js b/src/legacy/ui/public/filter_manager/filter_generator.js
index f119a95833668..e11e0ff6653a7 100644
--- a/src/legacy/ui/public/filter_manager/filter_generator.js
+++ b/src/legacy/ui/public/filter_manager/filter_generator.js
@@ -18,7 +18,7 @@
*/
import _ from 'lodash';
-import { getPhraseFilterField, getPhraseFilterValue, getPhraseScript, isPhraseFilter } from '@kbn/es-query';
+import { esFilters } from '../../../../plugins/data/public';
// Adds a filter to a passed state
export function getFilterGenerator(queryFilter) {
@@ -42,8 +42,8 @@ export function getFilterGenerator(queryFilter) {
return filter.exists.field === value;
}
- if (isPhraseFilter(filter)) {
- return getPhraseFilterField(filter) === fieldName && getPhraseFilterValue(filter) === value;
+ if (esFilters.isPhraseFilter(filter)) {
+ return esFilters.getPhraseFilterField(filter) === fieldName && esFilters.getPhraseFilterValue(filter) === value;
}
if (filter.script) {
@@ -73,7 +73,7 @@ export function getFilterGenerator(queryFilter) {
if (field.scripted) {
filter = {
meta: { negate, index, field: fieldName },
- script: getPhraseScript(field, value)
+ script: esFilters.getPhraseScript(field, value)
};
} else {
filter = { meta: { negate, index }, query: { match_phrase: {} } };
diff --git a/src/legacy/ui/public/index_patterns/__mocks__/index.ts b/src/legacy/ui/public/index_patterns/__mocks__/index.ts
index 85c07cb3b1df1..2dd3f370c6d6a 100644
--- a/src/legacy/ui/public/index_patterns/__mocks__/index.ts
+++ b/src/legacy/ui/public/index_patterns/__mocks__/index.ts
@@ -45,6 +45,4 @@ export {
IndexPatternMissingIndices,
NoDefaultIndexPattern,
NoDefinedIndexPatterns,
- mockFields,
- mockIndexPattern,
} from '../../../../core_plugins/data/public';
diff --git a/src/legacy/ui/public/index_patterns/index.ts b/src/legacy/ui/public/index_patterns/index.ts
index 67c370cad82a5..3b4952ac81519 100644
--- a/src/legacy/ui/public/index_patterns/index.ts
+++ b/src/legacy/ui/public/index_patterns/index.ts
@@ -47,8 +47,6 @@ export {
IndexPatternMissingIndices,
NoDefaultIndexPattern,
NoDefinedIndexPatterns,
- mockFields,
- mockIndexPattern,
} from '../../../core_plugins/data/public';
// types
diff --git a/src/legacy/ui/public/legacy_compat/angular_config.tsx b/src/legacy/ui/public/legacy_compat/angular_config.tsx
index 27484fb88f22e..58b8422cb2f8a 100644
--- a/src/legacy/ui/public/legacy_compat/angular_config.tsx
+++ b/src/legacy/ui/public/legacy_compat/angular_config.tsx
@@ -290,6 +290,9 @@ const $setupHelpExtensionAutoClear = (newPlatform: CoreStart) => (
});
$rootScope.$on('$routeChangeSuccess', () => {
+ if (isDummyWrapperRoute($route)) {
+ return;
+ }
const current = $route.current || {};
if (helpExtensionSetSinceRouteChange || (current.$$route && current.$$route.redirectTo)) {
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 611a182cf5d7f..bb055d6ce1e33 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
@@ -19,6 +19,12 @@
import sinon from 'sinon';
+const mockObservable = () => {
+ return {
+ subscribe: () => {}
+ };
+};
+
export const npSetup = {
core: {
chrome: {}
@@ -44,8 +50,16 @@ export const npSetup = {
},
},
data: {
+ autocomplete: {
+ addProvider: sinon.fake(),
+ getProvider: sinon.fake(),
+ },
query: {
filterManager: sinon.fake(),
+ timefilter: {
+ timefilter: sinon.fake(),
+ history: sinon.fake(),
+ }
},
},
inspector: {
@@ -64,6 +78,10 @@ export const npSetup = {
},
};
+let refreshInterval = undefined;
+let isTimeRangeSelectorEnabled = true;
+let isAutoRefreshSelectorEnabled = true;
+
export const npStart = {
core: {
chrome: {}
@@ -80,6 +98,9 @@ export const npStart = {
registerType: sinon.fake(),
},
data: {
+ autocomplete: {
+ getProvider: sinon.fake(),
+ },
getSuggestions: sinon.fake(),
query: {
filterManager: {
@@ -91,13 +112,48 @@ export const npStart = {
addFilters: sinon.fake(),
setFilters: sinon.fake(),
removeAll: sinon.fake(),
- getUpdates$: () => {
- return {
- subscribe: () => {}
- };
- },
+ getUpdates$: mockObservable,
},
+ timefilter: {
+ timefilter: {
+ getFetch$: mockObservable,
+ getAutoRefreshFetch$: mockObservable,
+ getEnabledUpdated$: mockObservable,
+ getTimeUpdate$: mockObservable,
+ getRefreshIntervalUpdate$: mockObservable,
+ isTimeRangeSelectorEnabled: () => {
+ return isTimeRangeSelectorEnabled;
+ },
+ isAutoRefreshSelectorEnabled: () => {
+ return isAutoRefreshSelectorEnabled;
+ },
+ disableAutoRefreshSelector: () => {
+ isAutoRefreshSelectorEnabled = false;
+ },
+ enableAutoRefreshSelector: () => {
+ isAutoRefreshSelectorEnabled = true;
+ },
+ getRefreshInterval: () => {
+ return refreshInterval;
+ },
+ setRefreshInterval: (interval) => {
+ refreshInterval = interval;
+ },
+ enableTimeRangeSelector: () => {
+ isTimeRangeSelectorEnabled = true;
+ },
+ disableTimeRangeSelector: () => {
+ isTimeRangeSelectorEnabled = false;
+ },
+ getTime: sinon.fake(),
+ setTime: sinon.fake(),
+ getBounds: sinon.fake(),
+ calculateBounds: sinon.fake(),
+ createFilter: sinon.fake(),
+ },
+ history: sinon.fake(),
+ },
},
},
inspector: {
diff --git a/src/legacy/ui/public/timefilter/index.ts b/src/legacy/ui/public/timefilter/index.ts
index c102d979c951a..82e2531ec62a6 100644
--- a/src/legacy/ui/public/timefilter/index.ts
+++ b/src/legacy/ui/public/timefilter/index.ts
@@ -18,20 +18,20 @@
*/
import uiRoutes from 'ui/routes';
-import { TimefilterContract, TimeHistoryContract } from '../../../core_plugins/data/public';
+import { npStart } from 'ui/new_platform';
+import { TimefilterContract, TimeHistoryContract } from '../../../../plugins/data/public';
import { registerTimefilterWithGlobalState } from './setup_router';
-import { start as data } from '../../../core_plugins/data/public/legacy';
export {
getTime,
InputTimeRange,
TimeHistoryContract,
TimefilterContract,
-} from '../../../core_plugins/data/public';
+} from '../../../../plugins/data/public';
export type Timefilter = TimefilterContract;
export type TimeHistory = TimeHistoryContract;
-export const timeHistory = data.timefilter.history;
-export const timefilter = data.timefilter.timefilter;
+export const timeHistory = npStart.plugins.data.query.timefilter.history;
+export const timefilter = npStart.plugins.data.query.timefilter.timefilter;
uiRoutes.addSetupWork((globalState, $rootScope) => {
return registerTimefilterWithGlobalState(timefilter, globalState, $rootScope);
diff --git a/src/legacy/ui/public/timefilter/setup_router.ts b/src/legacy/ui/public/timefilter/setup_router.ts
index ffc8a1fca6c64..0a73378f99cd7 100644
--- a/src/legacy/ui/public/timefilter/setup_router.ts
+++ b/src/legacy/ui/public/timefilter/setup_router.ts
@@ -22,8 +22,7 @@ import { IScope } from 'angular';
import moment from 'moment';
import { subscribeWithScope } from 'ui/utils/subscribe_with_scope';
import chrome from 'ui/chrome';
-import { RefreshInterval, TimeRange } from 'src/plugins/data/public';
-import { TimefilterContract } from '../../../core_plugins/data/public/timefilter';
+import { RefreshInterval, TimeRange, TimefilterContract } from 'src/plugins/data/public';
// TODO
// remove everything underneath once globalState is no longer an angular service
diff --git a/src/legacy/ui/public/vis/editors/default/components/agg.test.tsx b/src/legacy/ui/public/vis/editors/default/components/agg.test.tsx
index 7806b1c0f78fb..661ece5944fa3 100644
--- a/src/legacy/ui/public/vis/editors/default/components/agg.test.tsx
+++ b/src/legacy/ui/public/vis/editors/default/components/agg.test.tsx
@@ -248,10 +248,9 @@ describe('DefaultEditorAgg component', () => {
expect(compHistogram.find(DefaultEditorAggParams).props()).toHaveProperty('disabledParams', [
'min_doc_count',
]);
- expect(compDateHistogram.find(DefaultEditorAggParams).props()).toHaveProperty(
- 'disabledParams',
- ['min_doc_count']
- );
+ expect(
+ compDateHistogram.find(DefaultEditorAggParams).props()
+ ).toHaveProperty('disabledParams', ['min_doc_count']);
});
it('should set error when agg is not histogram or date_histogram', () => {
diff --git a/src/legacy/ui/public/vis/editors/default/components/agg_group.tsx b/src/legacy/ui/public/vis/editors/default/components/agg_group.tsx
index 6d3b5fc4e6355..528914f4fd006 100644
--- a/src/legacy/ui/public/vis/editors/default/components/agg_group.tsx
+++ b/src/legacy/ui/public/vis/editors/default/components/agg_group.tsx
@@ -26,7 +26,9 @@ import {
EuiDraggable,
EuiSpacer,
EuiPanel,
+ EuiFormErrorText,
} from '@elastic/eui';
+import { i18n } from '@kbn/i18n';
import { AggConfig } from '../../../../agg_types/agg_config';
import { aggGroupNamesMap, AggGroupNames } from '../agg_groups';
@@ -80,7 +82,15 @@ function DefaultEditorAggGroup({
const [aggsState, setAggsState] = useReducer(aggGroupReducer, group, initAggsState);
- const isGroupValid = Object.values(aggsState).every(item => item.valid);
+ const bucketsError =
+ lastParentPipelineAggTitle && groupName === AggGroupNames.Buckets && !group.length
+ ? i18n.translate('common.ui.aggTypes.buckets.mustHaveBucketErrorMessage', {
+ defaultMessage: 'Add a bucket with "Date Histogram" or "Histogram" aggregation.',
+ description: 'Date Histogram and Histogram should not be translated',
+ })
+ : undefined;
+
+ const isGroupValid = !bucketsError && Object.values(aggsState).every(item => item.valid);
const isAllAggsTouched = isInvalidAggsTouched(aggsState);
const isMetricAggregationDisabled = useMemo(
() => groupName === AggGroupNames.Metrics && getEnabledMetricAggsCount(group) === 1,
@@ -144,6 +154,12 @@ function DefaultEditorAggGroup({
{groupNameLabel}
+ {bucketsError && (
+ <>
+
{bucketsError}
+
+ >
+ )}
<>
{group.map((agg: AggConfig, index: number) => (
diff --git a/src/legacy/ui/public/vis/editors/default/components/agg_group_state.tsx b/src/legacy/ui/public/vis/editors/default/components/agg_group_state.tsx
index 8e8926f027cad..980889743c20d 100644
--- a/src/legacy/ui/public/vis/editors/default/components/agg_group_state.tsx
+++ b/src/legacy/ui/public/vis/editors/default/components/agg_group_state.tsx
@@ -53,13 +53,10 @@ function aggGroupReducer(state: AggsState, action: AggsAction): AggsState {
}
function initAggsState(group: AggConfig[]): AggsState {
- return group.reduce(
- (state, agg) => {
- state[agg.id] = { touched: false, valid: true };
- return state;
- },
- {} as AggsState
- );
+ return group.reduce((state, agg) => {
+ state[agg.id] = { touched: false, valid: true };
+ return state;
+ }, {} as AggsState);
}
export { aggGroupReducer, initAggsState };
diff --git a/src/legacy/ui/public/vis/editors/default/components/agg_params_helper.test.ts b/src/legacy/ui/public/vis/editors/default/components/agg_params_helper.test.ts
index 5fb241714b2e8..eb6bef4887642 100644
--- a/src/legacy/ui/public/vis/editors/default/components/agg_params_helper.test.ts
+++ b/src/legacy/ui/public/vis/editors/default/components/agg_params_helper.test.ts
@@ -121,7 +121,10 @@ describe('DefaultEditorAggParams helpers', () => {
},
schema: {},
getIndexPattern: jest.fn(() => ({
- fields: [{ name: '@timestamp', type: 'date' }, { name: 'geo_desc', type: 'string' }],
+ fields: [
+ { name: '@timestamp', type: 'date' },
+ { name: 'geo_desc', type: 'string' },
+ ],
})),
params: {
orderBy: 'orderBy',
diff --git a/src/legacy/ui/public/vis/editors/default/controls/auto_precision.tsx b/src/legacy/ui/public/vis/editors/default/controls/auto_precision.tsx
index 3b6aebe8c2b0c..53f74465e90a5 100644
--- a/src/legacy/ui/public/vis/editors/default/controls/auto_precision.tsx
+++ b/src/legacy/ui/public/vis/editors/default/controls/auto_precision.tsx
@@ -23,7 +23,7 @@ import { EuiSwitch, EuiFormRow } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { AggParamEditorProps } from '..';
-function AutoPrecisionParamEditor({ value, setValue }: AggParamEditorProps) {
+function AutoPrecisionParamEditor({ value = false, setValue }: AggParamEditorProps) {
const label = i18n.translate('common.ui.aggTypes.changePrecisionLabel', {
defaultMessage: 'Change precision on map zoom',
});
diff --git a/src/legacy/ui/public/vis/editors/default/controls/components/number_list/utils.test.ts b/src/legacy/ui/public/vis/editors/default/controls/components/number_list/utils.test.ts
index 3928c0a62eeaa..c6772cc108762 100644
--- a/src/legacy/ui/public/vis/editors/default/controls/components/number_list/utils.test.ts
+++ b/src/legacy/ui/public/vis/editors/default/controls/components/number_list/utils.test.ts
@@ -35,7 +35,10 @@ describe('NumberList utils', () => {
let range: Range;
beforeEach(() => {
- modelList = [{ value: 1, id: '1', isInvalid: false }, { value: 2, id: '2', isInvalid: false }];
+ modelList = [
+ { value: 1, id: '1', isInvalid: false },
+ { value: 2, id: '2', isInvalid: false },
+ ];
range = {
min: 1,
max: 10,
diff --git a/src/legacy/ui/public/vis/editors/default/controls/switch.tsx b/src/legacy/ui/public/vis/editors/default/controls/switch.tsx
index a5fc9682bd954..de675386d9100 100644
--- a/src/legacy/ui/public/vis/editors/default/controls/switch.tsx
+++ b/src/legacy/ui/public/vis/editors/default/controls/switch.tsx
@@ -30,7 +30,7 @@ interface SwitchParamEditorProps extends AggParamEditorProps {
}
function SwitchParamEditor({
- value,
+ value = false,
setValue,
dataTestSubj,
displayToolTip,
diff --git a/src/legacy/ui/public/vis/editors/default/controls/use_geocentroid.tsx b/src/legacy/ui/public/vis/editors/default/controls/use_geocentroid.tsx
index 6da32690912e7..932a4d19b495c 100644
--- a/src/legacy/ui/public/vis/editors/default/controls/use_geocentroid.tsx
+++ b/src/legacy/ui/public/vis/editors/default/controls/use_geocentroid.tsx
@@ -23,7 +23,7 @@ import { EuiSwitch, EuiFormRow } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { AggParamEditorProps } from '..';
-function UseGeocentroidParamEditor({ value, setValue }: AggParamEditorProps) {
+function UseGeocentroidParamEditor({ value = false, setValue }: AggParamEditorProps) {
const label = i18n.translate('common.ui.aggTypes.placeMarkersOffGridLabel', {
defaultMessage: 'Place markers off grid (use geocentroid)',
});
diff --git a/src/legacy/ui/public/vis/editors/default/default.html b/src/legacy/ui/public/vis/editors/default/default.html
index 3e7a94c77ac42..2a759815f57f2 100644
--- a/src/legacy/ui/public/vis/editors/default/default.html
+++ b/src/legacy/ui/public/vis/editors/default/default.html
@@ -11,11 +11,6 @@
diff --git a/src/legacy/ui/public/vis/editors/default/utils.tsx b/src/legacy/ui/public/vis/editors/default/utils.tsx
index efc424488ec41..4f82298aaca41 100644
--- a/src/legacy/ui/public/vis/editors/default/utils.tsx
+++ b/src/legacy/ui/public/vis/editors/default/utils.tsx
@@ -44,24 +44,21 @@ function groupAndSortBy<
TGroupBy extends string = 'type',
TLabelName extends string = 'title'
>(objects: T[], groupBy: TGroupBy, labelName: TLabelName): ComboBoxGroupedOptions
{
- const groupedOptions = objects.reduce(
- (array, obj) => {
- const group = array.find(element => element.label === obj[groupBy]);
- const option = {
- label: obj[labelName],
- target: obj,
- };
+ const groupedOptions = objects.reduce((array, obj) => {
+ const group = array.find(element => element.label === obj[groupBy]);
+ const option = {
+ label: obj[labelName],
+ target: obj,
+ };
- if (group && group.options) {
- group.options.push(option);
- } else {
- array.push({ label: obj[groupBy], options: [option] });
- }
+ if (group && group.options) {
+ group.options.push(option);
+ } else {
+ array.push({ label: obj[groupBy], options: [option] });
+ }
- return array;
- },
- [] as Array>
- );
+ return array;
+ }, [] as Array>);
groupedOptions.sort(sortByLabel);
diff --git a/src/legacy/ui/public/vis/vis_filters/brush_event.js b/src/legacy/ui/public/vis/vis_filters/brush_event.js
index 90cbaf7c048ee..17ab302a20cb1 100644
--- a/src/legacy/ui/public/vis/vis_filters/brush_event.js
+++ b/src/legacy/ui/public/vis/vis_filters/brush_event.js
@@ -19,7 +19,7 @@
import _ from 'lodash';
import moment from 'moment';
-import { buildRangeFilter } from '@kbn/es-query';
+import { esFilters } from '../../../../../plugins/data/public';
export function onBrushEvent(event) {
const isNumber = event.data.ordered;
@@ -56,7 +56,7 @@ export function onBrushEvent(event) {
};
}
- const newFilter = buildRangeFilter(
+ const newFilter = esFilters.buildRangeFilter(
field,
range,
indexPattern,
diff --git a/src/legacy/ui/public/vis/vis_filters/vis_filters.js b/src/legacy/ui/public/vis/vis_filters/vis_filters.js
index 9343585fa9508..e879d040125f1 100644
--- a/src/legacy/ui/public/vis/vis_filters/vis_filters.js
+++ b/src/legacy/ui/public/vis/vis_filters/vis_filters.js
@@ -20,8 +20,8 @@
import _ from 'lodash';
import { pushFilterBarFilters } from '../push_filters';
import { onBrushEvent } from './brush_event';
-import { uniqFilters } from '../../../../../plugins/data/public';
-import { toggleFilterNegated } from '@kbn/es-query';
+import { uniqFilters, esFilters } from '../../../../../plugins/data/public';
+
/**
* For terms aggregations on `__other__` buckets, this assembles a list of applicable filter
* terms based on a specific cell in the tabified data.
@@ -94,7 +94,7 @@ const createFiltersFromEvent = (event) => {
if (filter) {
filter.forEach(f => {
if (event.negate) {
- f = toggleFilterNegated(f);
+ f = esFilters.toggleFilterNegated(f);
}
filters.push(f);
});
diff --git a/src/legacy/ui/public/visualize/components/visualization_chart.test.js b/src/legacy/ui/public/visualize/components/visualization_chart.test.js
index 280370cdfe995..09d24ab71097a 100644
--- a/src/legacy/ui/public/visualize/components/visualization_chart.test.js
+++ b/src/legacy/ui/public/visualize/components/visualization_chart.test.js
@@ -57,46 +57,10 @@ describe(' ', () => {
expect(wrapper.text()).toBe('Test Visualization visualization, not yet accessible');
});
- it('should emit render start and render end', async () => {
- const renderStart = jest.fn();
- const renderComplete = jest.fn();
- const domNode = document.createElement('div');
- domNode.addEventListener('renderStart', renderStart);
- domNode.addEventListener('renderComplete', renderComplete);
-
- mount( , {
- attachTo: domNode
- });
-
- jest.runAllTimers();
- await renderPromise;
- expect(renderStart).toHaveBeenCalledTimes(1);
- expect(renderComplete).toHaveBeenCalledTimes(1);
-
- });
-
it('should render visualization', async () => {
const wrapper = mount( );
jest.runAllTimers();
await renderPromise;
expect(wrapper.find('.visChart').text()).toMatch(/markdown/);
});
-
- it('should re-render on param change', async () => {
- const renderComplete = jest.fn();
- const wrapper = mount( );
- const domNode = wrapper.getDOMNode();
- domNode.addEventListener('renderComplete', renderComplete);
- jest.runAllTimers();
- await renderPromise;
- expect(renderComplete).toHaveBeenCalledTimes(1);
-
- vis.params.markdown = 'new text';
- wrapper.setProps({ vis });
- jest.runAllTimers();
- await renderPromise;
-
- expect(wrapper.find('.visChart').text()).toBe('new text');
- expect(renderComplete).toHaveBeenCalledTimes(2);
- });
});
diff --git a/src/legacy/ui/public/visualize/components/visualization_chart.tsx b/src/legacy/ui/public/visualize/components/visualization_chart.tsx
index 06e44a4fd6e1c..eb7f130ec1a54 100644
--- a/src/legacy/ui/public/visualize/components/visualization_chart.tsx
+++ b/src/legacy/ui/public/visualize/components/visualization_chart.tsx
@@ -19,13 +19,9 @@
import React from 'react';
import * as Rx from 'rxjs';
-import { debounceTime, filter, share, switchMap, tap } from 'rxjs/operators';
+import { debounceTime, filter, share, switchMap } from 'rxjs/operators';
import { PersistedState } from '../../persisted_state';
-import {
- dispatchRenderComplete,
- dispatchRenderStart,
-} from '../../../../../plugins/kibana_utils/public';
import { ResizeChecker } from '../../resize_checker';
import { Vis, VisualizationController } from '../../vis';
import { getUpdateStatus } from '../../vis/update_status';
@@ -59,11 +55,6 @@ class VisualizationChart extends React.Component {
const render$ = this.renderSubject.asObservable().pipe(share());
const success$ = render$.pipe(
- tap(() => {
- if (this.chartDiv.current) {
- dispatchRenderStart(this.chartDiv.current);
- }
- }),
filter(
({ vis, visData, container }) => vis && container && (!vis.type.requiresSearch || visData)
),
@@ -85,8 +76,8 @@ class VisualizationChart extends React.Component {
const requestError$ = render$.pipe(filter(({ vis }) => vis.requestError));
this.renderSubscription = Rx.merge(success$, requestError$).subscribe(() => {
- if (this.chartDiv.current !== null) {
- dispatchRenderComplete(this.chartDiv.current);
+ if (this.props.onInit) {
+ this.props.onInit();
}
});
}
@@ -111,19 +102,11 @@ class VisualizationChart extends React.Component {
throw new Error('chartDiv and currentDiv reference should always be present.');
}
- const { vis, onInit } = this.props;
+ const { vis } = this.props;
const Visualization = vis.type.visualization;
this.visualization = new Visualization(this.chartDiv.current, vis);
- if (onInit) {
- // In case the visualization implementation has an isLoaded function, we
- // call that and wait for the result to resolve (in case it was a promise).
- const visLoaded =
- this.visualization && this.visualization.isLoaded && this.visualization.isLoaded();
- Promise.resolve(visLoaded).then(onInit);
- }
-
// We know that containerDiv.current will never be null, since we will always
// have rendered and the div is always rendered into the tree (i.e. not
// inside any condition).
diff --git a/src/legacy/ui/public/visualize/loader/__snapshots__/embedded_visualize_handler.test.ts.snap b/src/legacy/ui/public/visualize/loader/__snapshots__/embedded_visualize_handler.test.ts.snap
deleted file mode 100644
index 6650731942e7e..0000000000000
--- a/src/legacy/ui/public/visualize/loader/__snapshots__/embedded_visualize_handler.test.ts.snap
+++ /dev/null
@@ -1,30 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`EmbeddedVisualizeHandler data$ observable can be used to get response data in the correct format 1`] = `
-Object {
- "params": Object {},
- "visConfig": Object {},
- "visData": Object {},
- "visType": "histogram",
-}
-`;
-
-exports[`EmbeddedVisualizeHandler update should add provided data- attributes to the html element 1`] = `
-
-`;
-
-exports[`EmbeddedVisualizeHandler update should remove null data- attributes from the html element 1`] = `
-
-`;
diff --git a/src/legacy/ui/public/visualize/loader/__tests__/visualization_loader.js b/src/legacy/ui/public/visualize/loader/__tests__/visualization_loader.js
deleted file mode 100644
index ffce391fc1a07..0000000000000
--- a/src/legacy/ui/public/visualize/loader/__tests__/visualization_loader.js
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Licensed to Elasticsearch B.V. under one or more contributor
- * license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright
- * ownership. Elasticsearch B.V. licenses this file to you under
- * the Apache License, Version 2.0 (the "License"); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-import $ from 'jquery';
-import expect from '@kbn/expect';
-import ngMock from 'ng_mock';
-
-import { setupAndTeardownInjectorStub } from 'test_utils/stub_get_active_injector';
-
-import FixturesStubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern';
-
-import { VisProvider } from '../../../vis';
-import { visualizationLoader } from '../visualization_loader';
-
-describe('visualization loader', () => {
- let vis;
-
- beforeEach(ngMock.module('kibana', 'kibana/directive'));
- beforeEach(ngMock.inject((_$rootScope_, savedVisualizations, Private) => {
- const indexPattern = Private(FixturesStubbedLogstashIndexPatternProvider);
-
- // Create a new Vis object
- const Vis = Private(VisProvider);
- vis = new Vis(indexPattern, {
- type: 'markdown',
- params: { markdown: 'this is test' },
- });
-
- }));
- setupAndTeardownInjectorStub();
-
- it('should render visualization', async () => {
- const element = document.createElement('div');
- expect(visualizationLoader.render).to.be.a('function');
- visualizationLoader.render(element, vis, null, vis.params);
- expect($(element).find('.visualization').length).to.be(1);
- });
-
-
-});
diff --git a/src/legacy/ui/public/visualize/loader/__tests__/visualize_loader.js b/src/legacy/ui/public/visualize/loader/__tests__/visualize_loader.js
deleted file mode 100644
index 3fff184ffd199..0000000000000
--- a/src/legacy/ui/public/visualize/loader/__tests__/visualize_loader.js
+++ /dev/null
@@ -1,478 +0,0 @@
-/*
- * Licensed to Elasticsearch B.V. under one or more contributor
- * license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright
- * ownership. Elasticsearch B.V. licenses this file to you under
- * the Apache License, Version 2.0 (the "License"); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-import angular from 'angular';
-import expect from '@kbn/expect';
-import ngMock from 'ng_mock';
-import sinon from 'sinon';
-import { cloneDeep } from 'lodash';
-
-import { setupAndTeardownInjectorStub } from 'test_utils/stub_get_active_injector';
-
-import FixturesStubbedSearchSourceProvider from 'fixtures/stubbed_search_source';
-import FixturesStubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern';
-
-import { VisProvider } from '../../../vis';
-import { getVisualizeLoader } from '../visualize_loader';
-import { EmbeddedVisualizeHandler } from '../embedded_visualize_handler';
-import { Inspector } from '../../../inspector/inspector';
-import { dispatchRenderComplete } from '../../../../../../plugins/kibana_utils/public';
-import { PipelineDataLoader } from '../pipeline_data_loader';
-import { PersistedState } from '../../../persisted_state';
-import { DataAdapter, RequestAdapter } from '../../../inspector/adapters';
-
-describe('visualize loader', () => {
-
- let DataLoader;
- let searchSource;
- let vis;
- let $rootScope;
- let loader;
- let mockedSavedObject;
- let sandbox;
-
- function createSavedObject() {
- return {
- vis,
- searchSource,
- };
- }
-
- async function timeout(delay = 0) {
- return new Promise(resolve => {
- setTimeout(resolve, delay);
- });
- }
-
- function newContainer() {
- return angular.element('
');
- }
-
- function embedWithParams(params) {
- const container = newContainer();
- loader.embedVisualizationWithSavedObject(container[0], createSavedObject(), params);
- $rootScope.$digest();
- return container.find('[data-test-subj="visualizationLoader"]');
- }
-
- beforeEach(ngMock.module('kibana', 'kibana/directive'));
- beforeEach(ngMock.inject((_$rootScope_, savedVisualizations, Private) => {
- $rootScope = _$rootScope_;
- searchSource = Private(FixturesStubbedSearchSourceProvider);
- const indexPattern = Private(FixturesStubbedLogstashIndexPatternProvider);
-
- DataLoader = PipelineDataLoader;
- // Create a new Vis object
- const Vis = Private(VisProvider);
- vis = new Vis(indexPattern, {
- type: 'pie',
- title: 'testVis',
- params: {},
- aggs: [
- { type: 'count', schema: 'metric' },
- {
- type: 'range',
- schema: 'bucket',
- params: {
- field: 'bytes',
- ranges: [
- { from: 0, to: 1000 },
- { from: 1000, to: 2000 }
- ]
- }
- }
- ]
- });
- vis.type.requestHandler = 'courier';
- vis.type.responseHandler = 'none';
- vis.type.requiresSearch = false;
-
- // Setup savedObject
- mockedSavedObject = createSavedObject();
-
- sandbox = sinon.sandbox.create();
- // Mock savedVisualizations.get to return 'mockedSavedObject' when id is 'exists'
- sandbox.stub(savedVisualizations, 'get').callsFake((id) =>
- id === 'exists' ? Promise.resolve(mockedSavedObject) : Promise.reject()
- );
- }));
- setupAndTeardownInjectorStub();
- beforeEach(async () => {
- loader = await getVisualizeLoader();
- });
-
- afterEach(() => {
- if (sandbox) {
- sandbox.restore();
- }
- });
-
- describe('getVisualizeLoader', () => {
-
- it('should return a promise', () => {
- expect(getVisualizeLoader().then).to.be.a('function');
- });
-
- it('should resolve to an object', async () => {
- const visualizeLoader = await getVisualizeLoader();
- expect(visualizeLoader).to.be.an('object');
- });
-
- });
-
- describe('service', () => {
-
- describe('getVisualizationList', () => {
-
- it('should be a function', async () => {
- expect(loader.getVisualizationList).to.be.a('function');
- });
-
- });
-
- describe('embedVisualizationWithSavedObject', () => {
-
- it('should be a function', () => {
- expect(loader.embedVisualizationWithSavedObject).to.be.a('function');
- });
-
- it('should render the visualize element', () => {
- const container = newContainer();
- loader.embedVisualizationWithSavedObject(container[0], createSavedObject(), {});
- expect(container.find('[data-test-subj="visualizationLoader"]').length).to.be(1);
- });
-
- it('should not mutate vis.params', () => {
- const container = newContainer();
- const savedObject = createSavedObject();
- const paramsBefore = cloneDeep(vis.params);
- loader.embedVisualizationWithSavedObject(container[0], savedObject, {});
- const paramsAfter = cloneDeep(vis.params);
- expect(paramsBefore).to.eql(paramsAfter);
- });
-
- it('should replace content of container by default', () => {
- const container = angular.element('');
- loader.embedVisualizationWithSavedObject(container[0], createSavedObject(), {});
- expect(container.find('#prevContent').length).to.be(0);
- });
-
- it('should append content to container when using append parameter', () => {
- const container = angular.element('');
- loader.embedVisualizationWithSavedObject(container[0], createSavedObject(), {
- append: true
- });
- expect(container.children().length).to.be(2);
- expect(container.find('#prevContent').length).to.be(1);
- });
-
- it('should apply css classes from parameters', () => {
- const vis = embedWithParams({ cssClass: 'my-css-class another-class' });
- expect(vis.hasClass('my-css-class')).to.be(true);
- expect(vis.hasClass('another-class')).to.be(true);
- });
-
- it('should apply data attributes from dataAttrs parameter', () => {
- const vis = embedWithParams({
- dataAttrs: {
- 'foo': '',
- 'with-dash': 'value',
- }
- });
- expect(vis.attr('data-foo')).to.be('');
- expect(vis.attr('data-with-dash')).to.be('value');
- });
- });
-
- describe('embedVisualizationWithId', () => {
-
- it('should be a function', async () => {
- expect(loader.embedVisualizationWithId).to.be.a('function');
- });
-
- it('should reject if the id was not found', () => {
- const resolveSpy = sinon.spy();
- const rejectSpy = sinon.spy();
- const container = newContainer();
- return loader.embedVisualizationWithId(container[0], 'not-existing', {})
- .then(resolveSpy, rejectSpy)
- .then(() => {
- expect(resolveSpy.called).to.be(false);
- expect(rejectSpy.calledOnce).to.be(true);
- });
- });
-
- it('should render a visualize element, if id was found', async () => {
- const container = newContainer();
- await loader.embedVisualizationWithId(container[0], 'exists', {});
- expect(container.find('[data-test-subj="visualizationLoader"]').length).to.be(1);
- });
-
- });
-
- describe('EmbeddedVisualizeHandler', () => {
- it('should be returned from embedVisualizationWithId via a promise', async () => {
- const handler = await loader.embedVisualizationWithId(newContainer()[0], 'exists', {});
- expect(handler instanceof EmbeddedVisualizeHandler).to.be(true);
- });
-
- it('should be returned from embedVisualizationWithSavedObject', async () => {
- const handler = loader.embedVisualizationWithSavedObject(newContainer()[0], createSavedObject(), {});
- expect(handler instanceof EmbeddedVisualizeHandler).to.be(true);
- });
-
- it('should give access to the visualize element', () => {
- const container = newContainer();
- const handler = loader.embedVisualizationWithSavedObject(container[0], createSavedObject(), {});
- expect(handler.getElement()).to.be(container.find('[data-test-subj="visualizationLoader"]')[0]);
- });
-
- it('should allow opening the inspector of the visualization and return its session', () => {
- const handler = loader.embedVisualizationWithSavedObject(newContainer()[0], createSavedObject(), {});
- sandbox.spy(Inspector, 'open');
- const inspectorSession = handler.openInspector();
- expect(Inspector.open.calledOnce).to.be(true);
- expect(inspectorSession.close).to.be.a('function');
- inspectorSession.close();
- });
-
- describe('inspector', () => {
-
- describe('hasInspector()', () => {
- it('should forward to inspectors hasInspector', () => {
- const handler = loader.embedVisualizationWithSavedObject(newContainer()[0], createSavedObject(), {});
- sinon.spy(Inspector, 'isAvailable');
- handler.hasInspector();
- expect(Inspector.isAvailable.calledOnce).to.be(true);
- const adapters = Inspector.isAvailable.lastCall.args[0];
- expect(adapters.data).to.be.a(DataAdapter);
- expect(adapters.requests).to.be.a(RequestAdapter);
- });
-
- it('should return hasInspectors result', () => {
- const handler = loader.embedVisualizationWithSavedObject(newContainer()[0], createSavedObject(), {});
- const stub = sinon.stub(Inspector, 'isAvailable');
- stub.returns(true);
- expect(handler.hasInspector()).to.be(true);
- stub.returns(false);
- expect(handler.hasInspector()).to.be(false);
- });
-
- afterEach(() => {
- Inspector.isAvailable.restore();
- });
- });
-
- describe('openInspector()', () => {
-
- beforeEach(() => {
- sinon.stub(Inspector, 'open');
- });
-
- it('should call openInspector with all attached inspectors', () => {
- const handler = loader.embedVisualizationWithSavedObject(newContainer()[0], createSavedObject(), {});
- handler.openInspector();
- expect(Inspector.open.calledOnce).to.be(true);
- const adapters = Inspector.open.lastCall.args[0];
- expect(adapters).to.be(handler.inspectorAdapters);
- });
-
- it('should pass the vis title to the openInspector call', () => {
- const handler = loader.embedVisualizationWithSavedObject(newContainer()[0], createSavedObject(), {});
- handler.openInspector();
- expect(Inspector.open.calledOnce).to.be(true);
- const params = Inspector.open.lastCall.args[1];
- expect(params.title).to.be('testVis');
- });
-
- afterEach(() => {
- Inspector.open.restore();
- });
- });
-
- describe('inspectorAdapters', () => {
-
- it('should register none for none requestHandler', () => {
- const savedObj = createSavedObject();
- savedObj.vis.type.requestHandler = 'none';
- const handler = loader.embedVisualizationWithSavedObject(newContainer()[0], savedObj, {});
- expect(handler.inspectorAdapters).to.eql({});
- });
-
- it('should attach data and request handler for courier', () => {
- const handler = loader.embedVisualizationWithSavedObject(newContainer()[0], createSavedObject(), {});
- expect(handler.inspectorAdapters.data).to.be.a(DataAdapter);
- expect(handler.inspectorAdapters.requests).to.be.a(RequestAdapter);
- });
-
- it('should allow enabling data adapter manually', () => {
- const handler = loader.embedVisualizationWithSavedObject(newContainer()[0], createSavedObject(), {});
- expect(handler.inspectorAdapters.data).to.be.a(DataAdapter);
- });
-
- it('should allow enabling requests adapter manually', () => {
- const handler = loader.embedVisualizationWithSavedObject(newContainer()[0], createSavedObject(), {});
- expect(handler.inspectorAdapters.requests).to.be.a(RequestAdapter);
- });
-
- it('should allow adding custom inspector adapters via the custom key', () => {
- const Foodapter = class { };
- const Bardapter = class { };
- const savedObj = createSavedObject();
- savedObj.vis.type.inspectorAdapters = {
- custom: { foo: Foodapter, bar: Bardapter }
- };
- const handler = loader.embedVisualizationWithSavedObject(newContainer()[0], savedObj, {});
- expect(handler.inspectorAdapters.foo).to.be.a(Foodapter);
- expect(handler.inspectorAdapters.bar).to.be.a(Bardapter);
- });
-
- it('should not share adapter instances between vis instances', () => {
- const Foodapter = class { };
- const savedObj1 = createSavedObject();
- const savedObj2 = createSavedObject();
- savedObj1.vis.type.inspectorAdapters = { custom: { foo: Foodapter } };
- savedObj2.vis.type.inspectorAdapters = { custom: { foo: Foodapter } };
- const handler1 = loader.embedVisualizationWithSavedObject(newContainer()[0], savedObj1, {});
- const handler2 = loader.embedVisualizationWithSavedObject(newContainer()[0], savedObj2, {});
- expect(handler1.inspectorAdapters.foo).to.be.a(Foodapter);
- expect(handler2.inspectorAdapters.foo).to.be.a(Foodapter);
- expect(handler1.inspectorAdapters.foo).not.to.be(handler2.inspectorAdapters.foo);
- expect(handler1.inspectorAdapters.data).to.be.a(DataAdapter);
- expect(handler2.inspectorAdapters.data).to.be.a(DataAdapter);
- expect(handler1.inspectorAdapters.data).not.to.be(handler2.inspectorAdapters.data);
- });
- });
-
- });
-
- it('should have whenFirstRenderComplete returns a promise resolving on first renderComplete event', async () => {
- const container = newContainer();
- const handler = loader.embedVisualizationWithSavedObject(container[0], createSavedObject(), {});
- const spy = sinon.spy();
- handler.whenFirstRenderComplete().then(spy);
- expect(spy.notCalled).to.be(true);
- dispatchRenderComplete(container.find('[data-test-subj="visualizationLoader"]')[0]);
- await timeout();
- expect(spy.calledOnce).to.be(true);
- });
-
- it('should add listeners via addRenderCompleteListener that triggers on renderComplete events', async () => {
- const container = newContainer();
- const handler = loader.embedVisualizationWithSavedObject(container[0], createSavedObject(), {});
- const spy = sinon.spy();
- handler.addRenderCompleteListener(spy);
- expect(spy.notCalled).to.be(true);
- dispatchRenderComplete(container.find('[data-test-subj="visualizationLoader"]')[0]);
- await timeout();
- expect(spy.calledOnce).to.be(true);
- });
-
- it('should call render complete listeners once per renderComplete event', async () => {
- const container = newContainer();
- const handler = loader.embedVisualizationWithSavedObject(container[0], createSavedObject(), {});
- const spy = sinon.spy();
- handler.addRenderCompleteListener(spy);
- expect(spy.notCalled).to.be(true);
- dispatchRenderComplete(container.find('[data-test-subj="visualizationLoader"]')[0]);
- dispatchRenderComplete(container.find('[data-test-subj="visualizationLoader"]')[0]);
- dispatchRenderComplete(container.find('[data-test-subj="visualizationLoader"]')[0]);
- expect(spy.callCount).to.be(3);
- });
-
- it('should successfully remove listeners from render complete', async () => {
- const container = newContainer();
- const handler = loader.embedVisualizationWithSavedObject(container[0], createSavedObject(), {});
- const spy = sinon.spy();
- handler.addRenderCompleteListener(spy);
- expect(spy.notCalled).to.be(true);
- dispatchRenderComplete(container.find('[data-test-subj="visualizationLoader"]')[0]);
- expect(spy.calledOnce).to.be(true);
- spy.resetHistory();
- handler.removeRenderCompleteListener(spy);
- dispatchRenderComplete(container.find('[data-test-subj="visualizationLoader"]')[0]);
- expect(spy.notCalled).to.be(true);
- });
-
-
- it('should allow updating and deleting data attributes', () => {
- const container = newContainer();
- const handler = loader.embedVisualizationWithSavedObject(container[0], createSavedObject(), {
- dataAttrs: {
- foo: 42
- }
- });
- expect(container.find('[data-test-subj="visualizationLoader"]').attr('data-foo')).to.be('42');
- handler.update({
- dataAttrs: {
- foo: null,
- added: 'value',
- }
- });
- expect(container.find('[data-test-subj="visualizationLoader"]')[0].hasAttribute('data-foo')).to.be(false);
- expect(container.find('[data-test-subj="visualizationLoader"]').attr('data-added')).to.be('value');
- });
-
- it('should allow updating the time range of the visualization', async () => {
- const spy = sandbox.spy(DataLoader.prototype, 'fetch');
-
- const handler = loader.embedVisualizationWithSavedObject(newContainer()[0], createSavedObject(), {
- timeRange: { from: 'now-7d', to: 'now' }
- });
-
- // Wait for the initial fetch and render to happen
- await timeout(150);
- spy.resetHistory();
-
- handler.update({
- timeRange: { from: 'now-10d/d', to: 'now' }
- });
-
- // Wait for fetch debounce to happen (as soon as we use lodash 4+ we could use fake timers here for the debounce)
- await timeout(150);
-
- sinon.assert.calledOnce(spy);
- sinon.assert.calledWith(spy, sinon.match({ timeRange: { from: 'now-10d/d', to: 'now' } }));
- });
-
- it('should not set forceFetch on uiState change', async () => {
- const spy = sandbox.spy(DataLoader.prototype, 'fetch');
-
- const uiState = new PersistedState();
- loader.embedVisualizationWithSavedObject(newContainer()[0], createSavedObject(), {
- timeRange: { from: 'now-7d', to: 'now' },
- uiState: uiState,
- });
-
- // Wait for the initial fetch and render to happen
- await timeout(150);
- spy.resetHistory();
-
- uiState.set('property', 'value');
-
- // Wait for fetch debounce to happen (as soon as we use lodash 4+ we could use fake timers here for the debounce)
- await timeout(150);
-
- sinon.assert.calledOnce(spy);
- sinon.assert.calledWith(spy, sinon.match({ forceFetch: false }));
- });
- });
-
- });
-});
diff --git a/src/legacy/ui/public/visualize/loader/embedded_visualize_handler.test.mocks.ts b/src/legacy/ui/public/visualize/loader/embedded_visualize_handler.test.mocks.ts
deleted file mode 100644
index 4ca90d6c6b61b..0000000000000
--- a/src/legacy/ui/public/visualize/loader/embedded_visualize_handler.test.mocks.ts
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Licensed to Elasticsearch B.V. under one or more contributor
- * license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright
- * ownership. Elasticsearch B.V. licenses this file to you under
- * the Apache License, Version 2.0 (the "License"); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-jest.useFakeTimers();
-
-import { Subject } from 'rxjs';
-
-jest.mock('ui/notify', () => ({
- toastNotifications: jest.fn(),
-}));
-
-jest.mock('./utils', () => ({
- queryGeohashBounds: jest.fn(),
-}));
-
-jest.mock('./pipeline_helpers/utilities', () => ({
- getFormat: jest.fn(),
- getTableAggs: jest.fn(),
-}));
-
-const autoRefreshFetchSub = new Subject();
-
-export const timefilter = {
- _triggerAutoRefresh: () => {
- autoRefreshFetchSub.next();
- },
- getAutoRefreshFetch$: () => {
- return autoRefreshFetchSub.asObservable();
- },
-};
-jest.doMock('../../timefilter', () => ({ timefilter }));
-
-jest.mock('../../inspector', () => ({
- Inspector: {
- open: jest.fn(),
- isAvailable: jest.fn(),
- },
-}));
-
-export const mockDataLoaderFetch = jest.fn().mockReturnValue({
- as: 'visualization',
- value: {
- visType: 'histogram',
- visData: {},
- visConfig: {},
- params: {},
- },
-});
-const MockDataLoader = class {
- public async fetch(data: any) {
- return await mockDataLoaderFetch(data);
- }
-};
-
-jest.mock('./pipeline_data_loader', () => ({
- PipelineDataLoader: MockDataLoader,
-}));
diff --git a/src/legacy/ui/public/visualize/loader/embedded_visualize_handler.test.ts b/src/legacy/ui/public/visualize/loader/embedded_visualize_handler.test.ts
deleted file mode 100644
index c73f787457a03..0000000000000
--- a/src/legacy/ui/public/visualize/loader/embedded_visualize_handler.test.ts
+++ /dev/null
@@ -1,299 +0,0 @@
-/*
- * Licensed to Elasticsearch B.V. under one or more contributor
- * license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright
- * ownership. Elasticsearch B.V. licenses this file to you under
- * the Apache License, Version 2.0 (the "License"); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-jest.mock('ui/new_platform');
-
-import { searchSourceMock } from '../../courier/search_source/mocks';
-import { mockDataLoaderFetch, timefilter } from './embedded_visualize_handler.test.mocks';
-
-import _ from 'lodash';
-// @ts-ignore
-import MockState from '../../../../../fixtures/mock_state';
-import { Vis } from '../../vis';
-import { VisResponseData } from './types';
-import { Inspector } from '../../inspector';
-import { EmbeddedVisualizeHandler, RequestHandlerParams } from './embedded_visualize_handler';
-import { AggConfigs } from 'ui/agg_types/agg_configs';
-
-jest.mock('plugins/interpreter/interpreter', () => ({
- getInterpreter: () => {
- return Promise.resolve();
- },
-}));
-
-jest.mock('../../../../core_plugins/interpreter/public/registries', () => ({
- registries: {
- renderers: {
- get: (name: string) => {
- return {
- render: async () => {
- return {};
- },
- };
- },
- },
- },
-}));
-
-describe('EmbeddedVisualizeHandler', () => {
- let handler: any;
- let div: HTMLElement;
- let dataLoaderParams: RequestHandlerParams;
- const mockVis: Vis = {
- title: 'My Vis',
- // @ts-ignore
- type: 'foo',
- getAggConfig: () => [],
- _setUiState: () => ({}),
- getUiState: () => new MockState(),
- on: () => ({}),
- off: () => ({}),
- removeListener: jest.fn(),
- API: {},
- };
-
- beforeEach(() => {
- jest.clearAllMocks();
-
- jest.spyOn(_, 'debounce').mockImplementation(
- // @ts-ignore
- (f: Function) => {
- // @ts-ignore
- f.cancel = () => {};
- return f;
- }
- );
-
- dataLoaderParams = {
- aggs: ([] as any) as AggConfigs,
- filters: undefined,
- forceFetch: false,
- inspectorAdapters: {},
- query: undefined,
- queryFilter: null,
- searchSource: searchSourceMock,
- timeRange: undefined,
- uiState: undefined,
- };
-
- div = document.createElement('div');
- handler = new EmbeddedVisualizeHandler(
- div,
- {
- vis: mockVis,
- title: 'My Vis',
- searchSource: searchSourceMock,
- destroy: () => ({}),
- copyOnSave: false,
- save: () => Promise.resolve('123'),
- },
- {
- autoFetch: true,
- Private: (provider: () => T) => provider(),
- queryFilter: null,
- }
- );
- });
-
- afterEach(() => {
- handler.destroy();
- });
-
- describe('autoFetch', () => {
- it('should trigger a reload when autoFetch=true and auto refresh happens', () => {
- const spy = jest.spyOn(handler, 'fetchAndRender');
- timefilter._triggerAutoRefresh();
- jest.runAllTimers();
- expect(spy).toHaveBeenCalledTimes(1);
- expect(spy).toHaveBeenCalledWith(true);
- });
-
- it('should not trigger a reload when autoFetch=false and auto refresh happens', () => {
- handler = new EmbeddedVisualizeHandler(
- div,
- {
- vis: mockVis,
- title: 'My Vis',
- searchSource: searchSourceMock,
- destroy: () => ({}),
- copyOnSave: false,
- save: () => Promise.resolve('123'),
- },
- {
- autoFetch: false,
- Private: (provider: () => T) => provider(),
- queryFilter: null,
- }
- );
- const spy = jest.spyOn(handler, 'fetchAndRender');
- timefilter._triggerAutoRefresh();
- jest.runAllTimers();
- expect(spy).not.toHaveBeenCalled();
- });
- });
-
- describe('getElement', () => {
- it('should return the provided html element', () => {
- expect(handler.getElement()).toBe(div);
- });
- });
-
- describe('update', () => {
- it('should add provided data- attributes to the html element', () => {
- const spy = jest.spyOn(handler, 'fetchAndRender');
- const params = {
- dataAttrs: { foo: 'bar' },
- };
- handler.update(params);
- expect(spy).not.toHaveBeenCalled();
- expect(handler.getElement()).toMatchSnapshot();
- });
-
- it('should remove null data- attributes from the html element', () => {
- const spy = jest.spyOn(handler, 'fetchAndRender');
- handler.update({
- dataAttrs: { foo: 'bar' },
- });
- const params = {
- dataAttrs: {
- foo: null,
- baz: 'qux',
- },
- };
- handler.update(params);
- expect(spy).not.toHaveBeenCalled();
- expect(handler.getElement()).toMatchSnapshot();
- });
-
- it('should call dataLoader.render with updated timeRange', () => {
- const params = { timeRange: { foo: 'bar' } };
- handler.update(params);
- expect(mockDataLoaderFetch).toHaveBeenCalled();
- const callIndex = mockDataLoaderFetch.mock.calls.length - 1;
- const { abortSignal, ...otherParams } = mockDataLoaderFetch.mock.calls[callIndex][0];
- expect(abortSignal).toBeInstanceOf(AbortSignal);
- expect(otherParams).toEqual({ ...dataLoaderParams, ...params });
- });
-
- it('should call dataLoader.render with updated filters', () => {
- const params = { filters: [{ meta: { disabled: false } }] };
- handler.update(params);
- expect(mockDataLoaderFetch).toHaveBeenCalled();
- const callIndex = mockDataLoaderFetch.mock.calls.length - 1;
- const { abortSignal, ...otherParams } = mockDataLoaderFetch.mock.calls[callIndex][0];
- expect(abortSignal).toBeInstanceOf(AbortSignal);
- expect(otherParams).toEqual({ ...dataLoaderParams, ...params });
- });
-
- it('should call dataLoader.render with updated query', () => {
- const params = { query: { foo: 'bar' } };
- handler.update(params);
- expect(mockDataLoaderFetch).toHaveBeenCalled();
- const callIndex = mockDataLoaderFetch.mock.calls.length - 1;
- const { abortSignal, ...otherParams } = mockDataLoaderFetch.mock.calls[callIndex][0];
- expect(abortSignal).toBeInstanceOf(AbortSignal);
- expect(otherParams).toEqual({ ...dataLoaderParams, ...params });
- });
- });
-
- describe('destroy', () => {
- it('should remove vis event listeners', () => {
- const spy = jest.spyOn(mockVis, 'removeListener');
- handler.destroy();
- expect(spy).toHaveBeenCalledTimes(2);
- expect(spy.mock.calls[0][0]).toBe('reload');
- expect(spy.mock.calls[1][0]).toBe('update');
- });
-
- it('should remove element event listeners', () => {
- const spy = jest.spyOn(handler.getElement(), 'removeEventListener');
- handler.destroy();
- expect(spy).toHaveBeenCalled();
- });
-
- it('should prevent subsequent renders', () => {
- const spy = jest.spyOn(handler, 'fetchAndRender');
- handler.destroy();
- expect(spy).not.toHaveBeenCalled();
- });
-
- it('should cancel debounced fetchAndRender', () => {
- const spy = jest.spyOn(handler.debouncedFetchAndRender, 'cancel');
- handler.destroy();
- expect(spy).toHaveBeenCalledTimes(1);
- });
-
- it('should call abort on controller', () => {
- handler.abortController = new AbortController();
- const spy = jest.spyOn(handler.abortController, 'abort');
- handler.destroy();
- expect(spy).toHaveBeenCalled();
- });
- });
-
- describe('openInspector', () => {
- it('calls Inspector.open()', () => {
- handler.openInspector();
- expect(Inspector.open).toHaveBeenCalledTimes(1);
- expect(Inspector.open).toHaveBeenCalledWith({}, { title: 'My Vis' });
- });
- });
-
- describe('hasInspector', () => {
- it('calls Inspector.isAvailable()', () => {
- handler.hasInspector();
- expect(Inspector.isAvailable).toHaveBeenCalledTimes(1);
- expect(Inspector.isAvailable).toHaveBeenCalledWith({});
- });
- });
-
- describe('reload', () => {
- it('should force fetch and render', () => {
- const spy = jest.spyOn(handler, 'fetchAndRender');
- handler.reload();
- expect(spy).toHaveBeenCalledTimes(1);
- expect(spy).toHaveBeenCalledWith(true);
- });
- });
-
- describe('data$', () => {
- it('observable can be used to get response data in the correct format', async () => {
- let response;
- handler.data$.subscribe((data: VisResponseData) => (response = data));
- await handler.fetch(true);
- jest.runAllTimers();
- expect(response).toMatchSnapshot();
- });
- });
-
- describe('render', () => {
- // TODO
- });
-
- describe('whenFirstRenderComplete', () => {
- // TODO
- });
-
- describe('addRenderCompleteListener', () => {
- // TODO
- });
-
- describe('removeRenderCompleteListener', () => {
- // TODO
- });
-});
diff --git a/src/legacy/ui/public/visualize/loader/embedded_visualize_handler.ts b/src/legacy/ui/public/visualize/loader/embedded_visualize_handler.ts
deleted file mode 100644
index bb9f5832ac4e5..0000000000000
--- a/src/legacy/ui/public/visualize/loader/embedded_visualize_handler.ts
+++ /dev/null
@@ -1,553 +0,0 @@
-/*
- * Licensed to Elasticsearch B.V. under one or more contributor
- * license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright
- * ownership. Elasticsearch B.V. licenses this file to you under
- * the Apache License, Version 2.0 (the "License"); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-import { EventEmitter } from 'events';
-import { debounce, forEach, get, isEqual } from 'lodash';
-import * as Rx from 'rxjs';
-import { share } from 'rxjs/operators';
-import { i18n } from '@kbn/i18n';
-import { Filter } from '@kbn/es-query';
-import { toastNotifications } from 'ui/notify';
-// @ts-ignore untyped dependency
-import { AggConfigs } from 'ui/agg_types/agg_configs';
-import { SearchSource } from 'ui/courier';
-import { QueryFilter } from 'ui/filter_manager/query_filter';
-
-import { TimeRange, onlyDisabledFiltersChanged } from '../../../../../plugins/data/public';
-import { registries } from '../../../../core_plugins/interpreter/public/registries';
-import { Inspector } from '../../inspector';
-import { Adapters } from '../../inspector/types';
-import { PersistedState } from '../../persisted_state';
-import { IPrivate } from '../../private';
-import { RenderCompleteHelper } from '../../../../../plugins/kibana_utils/public';
-import { AppState } from '../../state_management/app_state';
-import { timefilter } from '../../timefilter';
-import { Vis } from '../../vis';
-// @ts-ignore untyped dependency
-import { VisFiltersProvider } from '../../vis/vis_filters';
-import { PipelineDataLoader } from './pipeline_data_loader';
-import { visualizationLoader } from './visualization_loader';
-import { Query } from '../../../../core_plugins/data/public';
-
-import { DataAdapter, RequestAdapter } from '../../inspector/adapters';
-
-import { getTableAggs } from './pipeline_helpers/utilities';
-import {
- VisResponseData,
- VisSavedObject,
- VisualizeLoaderParams,
- VisualizeUpdateParams,
-} from './types';
-import { queryGeohashBounds } from './utils';
-
-interface EmbeddedVisualizeHandlerParams extends VisualizeLoaderParams {
- Private: IPrivate;
- queryFilter: any;
- autoFetch?: boolean;
-}
-
-export interface RequestHandlerParams {
- searchSource: SearchSource;
- aggs: AggConfigs;
- timeRange?: TimeRange;
- query?: Query;
- filters?: Filter[];
- forceFetch: boolean;
- queryFilter: QueryFilter;
- uiState?: PersistedState;
- partialRows?: boolean;
- inspectorAdapters: Adapters;
- metricsAtAllLevels?: boolean;
- visParams?: any;
- abortSignal?: AbortSignal;
-}
-
-const RENDER_COMPLETE_EVENT = 'render_complete';
-const DATA_SHARED_ITEM = 'data-shared-item';
-const LOADING_ATTRIBUTE = 'data-loading';
-const RENDERING_COUNT_ATTRIBUTE = 'data-rendering-count';
-
-/**
- * A handler to the embedded visualization. It offers several methods to interact
- * with the visualization.
- */
-export class EmbeddedVisualizeHandler {
- /**
- * This observable will emit every time new data is loaded for the
- * visualization. The emitted value is the loaded data after it has
- * been transformed by the visualization's response handler.
- * This should not be used by any plugin.
- * @ignore
- */
- public readonly data$: Rx.Observable;
- public readonly inspectorAdapters: Adapters = {};
- private vis: Vis;
- private handlers: any;
- private loaded: boolean = false;
- private destroyed: boolean = false;
-
- private listeners = new EventEmitter();
- private firstRenderComplete: Promise;
- private renderCompleteHelper: RenderCompleteHelper;
- private shouldForceNextFetch: boolean = false;
- private debouncedFetchAndRender = debounce(() => {
- if (this.destroyed) {
- return;
- }
-
- const forceFetch = this.shouldForceNextFetch;
- this.shouldForceNextFetch = false;
- this.fetch(forceFetch).then(this.render);
- }, 100);
-
- private dataLoaderParams: RequestHandlerParams;
- private readonly appState?: AppState;
- private uiState: PersistedState;
- private dataLoader: PipelineDataLoader;
- private dataSubject: Rx.Subject;
- private actions: any = {};
- private events$: Rx.Observable;
- private autoFetch: boolean;
- private abortController?: AbortController;
- private autoRefreshFetchSubscription: Rx.Subscription | undefined;
-
- constructor(
- private readonly element: HTMLElement,
- savedObject: VisSavedObject,
- params: EmbeddedVisualizeHandlerParams
- ) {
- const { searchSource, vis } = savedObject;
-
- const {
- appState,
- uiState,
- queryFilter,
- timeRange,
- filters,
- query,
- autoFetch = true,
- Private,
- } = params;
-
- this.dataLoaderParams = {
- searchSource,
- timeRange,
- query,
- queryFilter,
- filters,
- uiState,
- aggs: vis.getAggConfig(),
- forceFetch: false,
- inspectorAdapters: this.inspectorAdapters,
- };
-
- // Listen to the first RENDER_COMPLETE_EVENT to resolve this promise
- this.firstRenderComplete = new Promise(resolve => {
- this.listeners.once(RENDER_COMPLETE_EVENT, resolve);
- });
-
- element.setAttribute(LOADING_ATTRIBUTE, '');
- element.setAttribute(DATA_SHARED_ITEM, '');
- element.setAttribute(RENDERING_COUNT_ATTRIBUTE, '0');
-
- element.addEventListener('renderComplete', this.onRenderCompleteListener);
-
- this.autoFetch = autoFetch;
- this.appState = appState;
- this.vis = vis;
- if (uiState) {
- vis._setUiState(uiState);
- }
- this.uiState = this.vis.getUiState();
-
- this.handlers = {
- vis: this.vis,
- uiState: this.uiState,
- onDestroy: (fn: () => never) => (this.handlers.destroyFn = fn),
- };
-
- this.vis.on('update', this.handleVisUpdate);
- this.vis.on('reload', this.reload);
- this.uiState.on('change', this.onUiStateChange);
- if (autoFetch) {
- this.autoRefreshFetchSubscription = timefilter.getAutoRefreshFetch$().subscribe(this.reload);
- }
-
- // This is a hack to give maps visualizations access to data in the
- // globalState, since they can no longer access it via searchSource.
- // TODO: Remove this as a part of elastic/kibana#30593
- this.vis.API.getGeohashBounds = () => {
- return queryGeohashBounds(this.vis, {
- filters: this.dataLoaderParams.filters,
- query: this.dataLoaderParams.query,
- });
- };
-
- this.dataLoader = new PipelineDataLoader(vis);
- const visFilters: any = Private(VisFiltersProvider);
- this.renderCompleteHelper = new RenderCompleteHelper(element);
- this.inspectorAdapters = this.getActiveInspectorAdapters();
- this.vis.openInspector = this.openInspector;
- this.vis.hasInspector = this.hasInspector;
-
- // init default actions
- forEach(this.vis.type.events, (event, eventName) => {
- if (event.disabled || !eventName) {
- return;
- } else {
- this.actions[eventName] = event.defaultAction;
- }
- });
-
- this.handlers.eventsSubject = new Rx.Subject();
- this.vis.eventsSubject = this.handlers.eventsSubject;
- this.events$ = this.handlers.eventsSubject.asObservable().pipe(share());
- this.events$.subscribe(event => {
- if (this.actions[event.name]) {
- event.data.aggConfigs = getTableAggs(this.vis);
- const newFilters = this.actions[event.name](event.data) || [];
- if (event.name === 'brush') {
- const fieldName = newFilters[0].meta.key;
- const $state = this.vis.API.getAppState();
- const existingFilter = $state.filters.find(
- (filter: any) => filter.meta && filter.meta.key === fieldName
- );
- if (existingFilter) {
- Object.assign(existingFilter, newFilters[0]);
- }
- }
- visFilters.pushFilters(newFilters);
- }
- });
-
- this.dataSubject = new Rx.Subject();
- this.data$ = this.dataSubject.asObservable().pipe(share());
-
- this.render();
- }
-
- /**
- * Update properties of the embedded visualization. This method does not allow
- * updating all initial parameters, but only a subset of the ones allowed
- * in {@link VisualizeUpdateParams}.
- *
- * @param params The parameters that should be updated.
- */
- public update(params: VisualizeUpdateParams = {}) {
- // Apply data- attributes to the element if specified
- const dataAttrs = params.dataAttrs;
- if (dataAttrs) {
- Object.keys(dataAttrs).forEach(key => {
- if (dataAttrs[key] === null) {
- this.element.removeAttribute(`data-${key}`);
- return;
- }
-
- this.element.setAttribute(`data-${key}`, dataAttrs[key]);
- });
- }
-
- let fetchRequired = false;
- if (
- params.hasOwnProperty('timeRange') &&
- !isEqual(this.dataLoaderParams.timeRange, params.timeRange)
- ) {
- fetchRequired = true;
- this.dataLoaderParams.timeRange = params.timeRange;
- }
- if (
- params.hasOwnProperty('filters') &&
- !onlyDisabledFiltersChanged(this.dataLoaderParams.filters, params.filters)
- ) {
- fetchRequired = true;
- this.dataLoaderParams.filters = params.filters;
- }
- if (params.hasOwnProperty('query') && !isEqual(this.dataLoaderParams.query, params.query)) {
- fetchRequired = true;
- this.dataLoaderParams.query = params.query;
- }
-
- if (fetchRequired) {
- this.fetchAndRender();
- }
- }
-
- /**
- * Destroy the underlying Angular scope of the visualization. This should be
- * called whenever you remove the visualization.
- */
- public destroy(): void {
- this.destroyed = true;
- this.cancel();
- this.debouncedFetchAndRender.cancel();
- if (this.autoFetch) {
- if (this.autoRefreshFetchSubscription) this.autoRefreshFetchSubscription.unsubscribe();
- }
- this.vis.removeListener('reload', this.reload);
- this.vis.removeListener('update', this.handleVisUpdate);
- this.element.removeEventListener('renderComplete', this.onRenderCompleteListener);
- this.uiState.off('change', this.onUiStateChange);
- visualizationLoader.destroy(this.element);
- this.renderCompleteHelper.destroy();
- if (this.handlers.destroyFn) {
- this.handlers.destroyFn();
- }
- }
-
- /**
- * Return the actual DOM element (wrapped in jQuery) of the rendered visualization.
- * This is especially useful if you used `append: true` in the parameters where
- * the visualization will be appended to the specified container.
- */
- public getElement(): HTMLElement {
- return this.element;
- }
-
- /**
- * renders visualization with provided data
- * @param response: visualization data
- */
- public render = (response: VisResponseData | null = null): void => {
- const executeRenderer = this.rendererProvider(response);
- if (!executeRenderer) {
- return;
- }
-
- // TODO: we have this weird situation when we need to render first,
- // and then we call fetch and render... we need to get rid of that.
- executeRenderer().then(() => {
- if (!this.loaded) {
- this.loaded = true;
- if (this.autoFetch) {
- this.fetchAndRender();
- }
- }
- });
- };
-
- /**
- * Opens the inspector for the embedded visualization. This will return an
- * handler to the inspector to close and interact with it.
- * @return An inspector session to interact with the opened inspector.
- */
- public openInspector = () => {
- return Inspector.open(this.inspectorAdapters, {
- title: this.vis.title,
- });
- };
-
- public hasInspector = () => {
- return Inspector.isAvailable(this.inspectorAdapters);
- };
-
- /**
- * Returns a promise, that will resolve (without a value) once the first rendering of
- * the visualization has finished. If you want to listen to consecutive rendering
- * events, look into the `addRenderCompleteListener` method.
- *
- * @returns Promise, that resolves as soon as the visualization is done rendering
- * for the first time.
- */
- public whenFirstRenderComplete(): Promise {
- return this.firstRenderComplete;
- }
-
- /**
- * Adds a listener to be called whenever the visualization finished rendering.
- * This can be called multiple times, when the visualization rerenders, e.g. due
- * to new data.
- *
- * @param {function} listener The listener to be notified about complete renders.
- */
- public addRenderCompleteListener(listener: () => void) {
- this.listeners.addListener(RENDER_COMPLETE_EVENT, listener);
- }
-
- /**
- * Removes a previously registered render complete listener from this handler.
- * This listener will no longer be called when the visualization finished rendering.
- *
- * @param {function} listener The listener to remove from this handler.
- */
- public removeRenderCompleteListener(listener: () => void) {
- this.listeners.removeListener(RENDER_COMPLETE_EVENT, listener);
- }
-
- /**
- * Force the fetch of new data and renders the chart again.
- */
- public reload = () => {
- this.fetchAndRender(true);
- };
-
- private incrementRenderingCount = () => {
- const renderingCount = Number(this.element.getAttribute(RENDERING_COUNT_ATTRIBUTE) || 0);
- this.element.setAttribute(RENDERING_COUNT_ATTRIBUTE, `${renderingCount + 1}`);
- };
-
- private onRenderCompleteListener = () => {
- this.listeners.emit(RENDER_COMPLETE_EVENT);
- this.element.removeAttribute(LOADING_ATTRIBUTE);
- this.incrementRenderingCount();
- };
-
- private onUiStateChange = () => {
- this.fetchAndRender();
- };
-
- /**
- * Returns an object of all inspectors for this vis object.
- * This must only be called after this.type has properly be initialized,
- * since we need to read out data from the the vis type to check which
- * inspectors are available.
- */
- private getActiveInspectorAdapters = (): Adapters => {
- const adapters: Adapters = {};
- const { inspectorAdapters: typeAdapters } = this.vis.type;
-
- // Add the requests inspector adapters if the vis type explicitly requested it via
- // inspectorAdapters.requests: true in its definition or if it's using the courier
- // request handler, since that will automatically log its requests.
- if ((typeAdapters && typeAdapters.requests) || this.vis.type.requestHandler === 'courier') {
- adapters.requests = new RequestAdapter();
- }
-
- // Add the data inspector adapter if the vis type requested it or if the
- // vis is using courier, since we know that courier supports logging
- // its data.
- if ((typeAdapters && typeAdapters.data) || this.vis.type.requestHandler === 'courier') {
- adapters.data = new DataAdapter();
- }
-
- // Add all inspectors, that are explicitly registered with this vis type
- if (typeAdapters && typeAdapters.custom) {
- Object.entries(typeAdapters.custom).forEach(([key, Adapter]) => {
- adapters[key] = new (Adapter as any)();
- });
- }
-
- return adapters;
- };
-
- /**
- * Fetches new data and renders the chart. This will happen debounced for a couple
- * of milliseconds, to bundle fast successive calls into one fetch and render,
- * e.g. while resizing the window, this will be triggered constantly on the resize
- * event.
- *
- * @param forceFetch=false Whether the request handler should be signaled to forceFetch
- * (i.e. ignore caching in case it supports it). If at least one call to this
- * passed `true` the debounced fetch and render will be a force fetch.
- */
- private fetchAndRender = (forceFetch = false): void => {
- this.shouldForceNextFetch = forceFetch || this.shouldForceNextFetch;
- this.element.setAttribute(LOADING_ATTRIBUTE, '');
- this.debouncedFetchAndRender();
- };
-
- private handleVisUpdate = () => {
- if (this.appState) {
- this.appState.vis = this.vis.getState();
- this.appState.save();
- }
-
- this.fetchAndRender();
- };
-
- private cancel = () => {
- if (this.abortController) this.abortController.abort();
- };
-
- private fetch = (forceFetch: boolean = false) => {
- this.cancel();
- this.abortController = new AbortController();
- this.dataLoaderParams.abortSignal = this.abortController.signal;
- this.dataLoaderParams.aggs = this.vis.getAggConfig();
- this.dataLoaderParams.forceFetch = forceFetch;
- this.dataLoaderParams.inspectorAdapters = this.inspectorAdapters;
-
- this.vis.filters = { timeRange: this.dataLoaderParams.timeRange };
- this.vis.requestError = undefined;
- this.vis.showRequestError = false;
-
- return (
- this.dataLoader
- // Don't pass in this.dataLoaderParams directly because it may be modified async in another
- // call to fetch before the previous one has completed
- .fetch({ ...this.dataLoaderParams })
- .then(data => {
- // Pipeline responses never throw errors, so we need to check for
- // `type: 'error'`, and then throw so it can be caught below.
- // TODO: We should revisit this after we have fully migrated
- // to the new expression pipeline infrastructure.
- if (data && data.type === 'error') {
- throw data.error;
- }
-
- if (data && data.value) {
- this.dataSubject.next(data.value);
- }
- return data;
- })
- .catch(this.handleDataLoaderError)
- );
- };
-
- /**
- * When dataLoader returns an error, we need to make sure it surfaces in the UI.
- *
- * TODO: Eventually we should add some custom error messages for issues that are
- * frequently encountered by users.
- */
- private handleDataLoaderError = (error: any): void => {
- // If the data loader was aborted then no need to surface this error in the UI
- if (error && error.name === 'AbortError') return;
-
- // Cancel execution of pipeline expressions
- if (this.abortController) {
- this.abortController.abort();
- }
-
- this.vis.requestError = error;
- this.vis.showRequestError =
- error.type && ['NO_OP_SEARCH_STRATEGY', 'UNSUPPORTED_QUERY'].includes(error.type);
-
- toastNotifications.addDanger({
- title: i18n.translate('common.ui.visualize.dataLoaderError', {
- defaultMessage: 'Error in visualization',
- }),
- text: error.message,
- });
- };
-
- private rendererProvider = (response: VisResponseData | null) => {
- const renderer = registries.renderers.get(get(response || {}, 'as', 'visualization'));
-
- if (!renderer) {
- return null;
- }
-
- return () =>
- renderer.render(
- this.element,
- get(response, 'value', { visType: this.vis.type.name }),
- this.handlers
- );
- };
-}
diff --git a/src/legacy/ui/public/visualize/loader/pipeline_data_loader.ts b/src/legacy/ui/public/visualize/loader/pipeline_data_loader.ts
deleted file mode 100644
index c1aa6903abe88..0000000000000
--- a/src/legacy/ui/public/visualize/loader/pipeline_data_loader.ts
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Licensed to Elasticsearch B.V. under one or more contributor
- * license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright
- * ownership. Elasticsearch B.V. licenses this file to you under
- * the Apache License, Version 2.0 (the "License"); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-import { Vis } from '../../vis';
-import { buildPipeline, runPipeline } from './pipeline_helpers';
-import { RequestHandlerParams } from './embedded_visualize_handler';
-
-export class PipelineDataLoader {
- constructor(private readonly vis: Vis) {}
-
- public async fetch(params: RequestHandlerParams): Promise {
- this.vis.pipelineExpression = await buildPipeline(this.vis, params);
-
- return runPipeline(
- this.vis.pipelineExpression,
- { type: 'null' },
- {
- getInitialContext: () => ({
- type: 'kibana_context',
- query: params.query,
- timeRange: params.timeRange,
- filters: params.filters
- ? params.filters.filter(filter => !filter.meta.disabled)
- : undefined,
- }),
- inspectorAdapters: params.inspectorAdapters,
- abortSignal: params.abortSignal,
- }
- );
- }
-}
diff --git a/src/legacy/ui/public/visualize/loader/pipeline_helpers/build_pipeline.test.ts b/src/legacy/ui/public/visualize/loader/pipeline_helpers/build_pipeline.test.ts
index 056f3e8cfc586..70e0c1f1382fa 100644
--- a/src/legacy/ui/public/visualize/loader/pipeline_helpers/build_pipeline.test.ts
+++ b/src/legacy/ui/public/visualize/loader/pipeline_helpers/build_pipeline.test.ts
@@ -172,7 +172,10 @@ describe('visualize loader pipeline helpers: build pipeline', () => {
const visState = { ...visStateDef, params: { foo: 'bar' } };
const schemas = {
...schemasDef,
- metric: [{ ...schemaConfig, accessor: 0 }, { ...schemaConfig, accessor: 1 }],
+ metric: [
+ { ...schemaConfig, accessor: 0 },
+ { ...schemaConfig, accessor: 1 },
+ ],
};
const actual = buildPipelineVisFunction.table(visState, schemas, uiState);
expect(actual).toMatchSnapshot();
@@ -192,7 +195,10 @@ describe('visualize loader pipeline helpers: build pipeline', () => {
const visState = { ...visStateDef, params: { foo: 'bar' } };
const schemas = {
...schemasDef,
- metric: [{ ...schemaConfig, accessor: 0 }, { ...schemaConfig, accessor: 1 }],
+ metric: [
+ { ...schemaConfig, accessor: 0 },
+ { ...schemaConfig, accessor: 1 },
+ ],
split_row: [2, 4],
bucket: [3],
};
@@ -250,7 +256,10 @@ describe('visualize loader pipeline helpers: build pipeline', () => {
const visState = { ...visStateDef, params: { metric: {} } };
const schemas = {
...schemasDef,
- metric: [{ ...schemaConfig, accessor: 0 }, { ...schemaConfig, accessor: 1 }],
+ metric: [
+ { ...schemaConfig, accessor: 0 },
+ { ...schemaConfig, accessor: 1 },
+ ],
};
const actual = buildPipelineVisFunction.metric(visState, schemas, uiState);
expect(actual).toMatchSnapshot();
@@ -260,7 +269,10 @@ describe('visualize loader pipeline helpers: build pipeline', () => {
const visState = { ...visStateDef, params: { metric: {} } };
const schemas = {
...schemasDef,
- metric: [{ ...schemaConfig, accessor: 0 }, { ...schemaConfig, accessor: 1 }],
+ metric: [
+ { ...schemaConfig, accessor: 0 },
+ { ...schemaConfig, accessor: 1 },
+ ],
group: [{ accessor: 2 }],
};
const actual = buildPipelineVisFunction.metric(visState, schemas, uiState);
diff --git a/src/legacy/ui/public/visualize/loader/pipeline_helpers/index.ts b/src/legacy/ui/public/visualize/loader/pipeline_helpers/index.ts
index 69c29339a8713..a1292c59ac61d 100644
--- a/src/legacy/ui/public/visualize/loader/pipeline_helpers/index.ts
+++ b/src/legacy/ui/public/visualize/loader/pipeline_helpers/index.ts
@@ -18,4 +18,3 @@
*/
export { buildPipeline } from './build_pipeline';
-export { runPipeline } from './run_pipeline';
diff --git a/src/legacy/ui/public/visualize/loader/pipeline_helpers/run_pipeline.ts b/src/legacy/ui/public/visualize/loader/pipeline_helpers/run_pipeline.ts
deleted file mode 100644
index 78a959b2b0f71..0000000000000
--- a/src/legacy/ui/public/visualize/loader/pipeline_helpers/run_pipeline.ts
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Licensed to Elasticsearch B.V. under one or more contributor
- * license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright
- * ownership. Elasticsearch B.V. licenses this file to you under
- * the Apache License, Version 2.0 (the "License"); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-// @ts-ignore
-import { fromExpression } from '@kbn/interpreter/common';
-import { Adapters } from 'ui/inspector';
-import { getInterpreter } from '../../../../../core_plugins/interpreter/public/interpreter';
-import { KibanaContext } from '../../../../../core_plugins/interpreter/public';
-
-type getInitialContextFunction = () => KibanaContext;
-
-export interface RunPipelineHandlers {
- getInitialContext: getInitialContextFunction;
- inspectorAdapters?: Adapters;
- abortSignal?: AbortSignal;
-}
-
-export const runPipeline = async (
- expression: string,
- context: any,
- handlers: RunPipelineHandlers
-) => {
- const ast = fromExpression(expression);
- const { interpreter } = await getInterpreter();
- const pipelineResponse = await interpreter.interpretAst(ast, context, handlers as any);
- return pipelineResponse;
-};
diff --git a/src/legacy/ui/public/visualize/loader/types.ts b/src/legacy/ui/public/visualize/loader/types.ts
deleted file mode 100644
index 87183d839e637..0000000000000
--- a/src/legacy/ui/public/visualize/loader/types.ts
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * Licensed to Elasticsearch B.V. under one or more contributor
- * license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright
- * ownership. Elasticsearch B.V. licenses this file to you under
- * the Apache License, Version 2.0 (the "License"); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-import { Filter } from '@kbn/es-query';
-import { TimeRange } from 'src/plugins/data/public';
-import { Query } from 'src/legacy/core_plugins/data/public';
-import { SavedObject } from 'ui/saved_objects/saved_object';
-import { VisResponseValue } from 'src/plugins/visualizations/public';
-import { SearchSource } from '../../courier';
-import { PersistedState } from '../../persisted_state';
-import { AppState } from '../../state_management/app_state';
-import { Vis } from '../../vis';
-
-export interface VisSavedObject extends SavedObject {
- vis: Vis;
- description?: string;
- searchSource: SearchSource;
- title: string;
- uiStateJSON?: string;
- destroy: () => void;
-}
-
-export interface VisResponseData {
- as: string;
- value: VisResponseValue;
-}
-
-/**
- * The parameters accepted by the embedVisualize calls.
- */
-export interface VisualizeLoaderParams {
- /**
- * An object with a from/to key, that must be either a date in ISO format, or a
- * valid datetime Elasticsearch expression, e.g.: { from: 'now-7d/d', to: 'now' }
- */
- timeRange?: TimeRange;
- /**
- * If set to true, the visualization will be appended to the passed element instead
- * of replacing all its content. (default: false)
- */
- append?: boolean;
- /**
- * If specified this CSS class (or classes with space separated) will be set to
- * the root visualize element.
- */
- cssClass?: string;
- /**
- * An object of key-value pairs, that will be set as data-{key}="{value}" attributes
- * on the visualization element.
- */
- dataAttrs?: { [key: string]: string };
- /**
- * Specifies the filters that should be applied to that visualization.
- */
- filters?: Filter[];
- /**
- * The query that should apply to that visualization.
- */
- query?: Query;
- /**
- * The current uiState of the application. If you don't pass a uiState, the
- * visualization will creates it's own uiState to store information like whether
- * the legend is open or closed, but you don't have access to it from the outside.
- * Pass one in if you need that access, e.g. for saving that state.
- */
- uiState?: PersistedState;
- /**
- * The appState this visualization should use. If you don't specify it, the
- * global AppState (that is decoded in the URL) will be used. Usually you don't
- * need to overwrite this, unless you don't want the visualization to use the
- * global AppState.
- */
- appState?: AppState;
- /**
- * Whether or not the visualization should fetch its data automatically. If this is
- * set to `false` the loader won't trigger a fetch on embedding or when an auto refresh
- * cycle happens. Default value: `true`
- */
- autoFetch?: boolean;
-}
-
-/**
- * The subset of properties allowed to update on an already embedded visualization.
- */
-export type VisualizeUpdateParams = Pick<
- VisualizeLoaderParams,
- 'timeRange' | 'dataAttrs' | 'filters' | 'query'
->;
diff --git a/src/legacy/ui/public/visualize/loader/utils/query_geohash_bounds.ts b/src/legacy/ui/public/visualize/loader/utils/query_geohash_bounds.ts
index ec612f7dd0373..912afab74bef4 100644
--- a/src/legacy/ui/public/visualize/loader/utils/query_geohash_bounds.ts
+++ b/src/legacy/ui/public/visualize/loader/utils/query_geohash_bounds.ts
@@ -22,14 +22,16 @@ import { get } from 'lodash';
import { toastNotifications } from 'ui/notify';
import { AggConfig } from 'ui/vis';
-import { Filter } from '@kbn/es-query';
import { Query } from 'src/legacy/core_plugins/data/public';
import { timefilter } from 'ui/timefilter';
import { Vis } from '../../../vis';
+import { SearchSource } from '../../../courier';
+import { esFilters } from '../../../../../../plugins/data/public';
interface QueryGeohashBoundsParams {
- filters?: Filter[];
+ filters?: esFilters.Filter[];
query?: Query;
+ searchSource?: SearchSource;
}
/**
@@ -47,7 +49,9 @@ export async function queryGeohashBounds(vis: Vis, params: QueryGeohashBoundsPar
});
if (agg) {
- const searchSource = vis.searchSource.createChild();
+ const searchSource = params.searchSource
+ ? params.searchSource.createChild()
+ : new SearchSource();
searchSource.setField('size', 0);
searchSource.setField('aggs', () => {
const geoBoundsAgg = vis.getAggConfig().createAggConfig(
@@ -76,7 +80,7 @@ export async function queryGeohashBounds(vis: Vis, params: QueryGeohashBoundsPar
const useTimeFilter = !!indexPattern.timeFieldName;
if (useTimeFilter) {
const filter = timefilter.createFilter(indexPattern);
- if (filter) activeFilters.push((filter as any) as Filter);
+ if (filter) activeFilters.push((filter as any) as esFilters.Filter);
}
return activeFilters;
});
diff --git a/src/legacy/ui/public/visualize/loader/vis.js b/src/legacy/ui/public/visualize/loader/vis.js
index 85ab07528b846..1942fd58afebb 100644
--- a/src/legacy/ui/public/visualize/loader/vis.js
+++ b/src/legacy/ui/public/visualize/loader/vis.js
@@ -33,8 +33,7 @@ import { PersistedState } from '../../persisted_state';
import { start as visualizations } from '../../../../core_plugins/visualizations/public/np_ready/public/legacy';
-
-export function VisProvider(indexPatterns, getAppState) {
+export function VisProvider(getAppState) {
const visTypes = visualizations.types;
class Vis extends EventEmitter {
diff --git a/src/legacy/ui/public/visualize/loader/visualization_loader.tsx b/src/legacy/ui/public/visualize/loader/visualization_loader.tsx
deleted file mode 100644
index 307ef0354f451..0000000000000
--- a/src/legacy/ui/public/visualize/loader/visualization_loader.tsx
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Licensed to Elasticsearch B.V. under one or more contributor
- * license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright
- * ownership. Elasticsearch B.V. licenses this file to you under
- * the Apache License, Version 2.0 (the "License"); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-import _ from 'lodash';
-import React from 'react';
-import { render, unmountComponentAtNode } from 'react-dom';
-
-import { PersistedState } from '../../persisted_state';
-import { Vis } from '../../vis';
-import { Visualization } from '../components/visualization';
-
-interface VisualizationLoaderParams {
- listenOnChange?: boolean;
-}
-
-function renderVisualization(
- element: HTMLElement,
- vis: Vis,
- visData: any,
- visParams: any,
- uiState: PersistedState,
- params: VisualizationLoaderParams
-) {
- return new Promise(resolve => {
- const listenOnChange = _.get(params, 'listenOnChange', false);
- render(
- ,
- element
- );
- });
-}
-
-function destroy(element?: HTMLElement) {
- if (element) {
- unmountComponentAtNode(element);
- }
-}
-
-export const visualizationLoader = {
- render: renderVisualization,
- destroy,
-};
diff --git a/src/legacy/ui/public/visualize/loader/visualize_loader.ts b/src/legacy/ui/public/visualize/loader/visualize_loader.ts
deleted file mode 100644
index 086b16711a581..0000000000000
--- a/src/legacy/ui/public/visualize/loader/visualize_loader.ts
+++ /dev/null
@@ -1,159 +0,0 @@
-/*
- * Licensed to Elasticsearch B.V. under one or more contributor
- * license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright
- * ownership. Elasticsearch B.V. licenses this file to you under
- * the Apache License, Version 2.0 (the "License"); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-/**
- * IMPORTANT: If you make changes to this API, please make sure to check that
- * the docs (docs/development/visualize/development-create-visualization.asciidoc)
- * are up to date.
- */
-
-import chrome from '../../chrome';
-import { FilterBarQueryFilterProvider } from '../../filter_manager/query_filter';
-import { IPrivate } from '../../private';
-import { EmbeddedVisualizeHandler } from './embedded_visualize_handler';
-import { VisSavedObject, VisualizeLoaderParams } from './types';
-
-export class VisualizeLoader {
- constructor(private readonly savedVisualizations: any, private readonly Private: IPrivate) {}
-
- /**
- * Renders a saved visualization specified by its id into a DOM element.
- *
- * @param element The DOM element to render the visualization into.
- * You can alternatively pass a jQuery element instead.
- * @param id The id of the saved visualization. This is the id of the
- * saved object that is stored in the .kibana index.
- * @param params A list of parameters that will influence rendering.
- *
- * @return A promise that resolves to the
- * handler for this visualization as soon as the saved object could be found.
- */
- public async embedVisualizationWithId(
- element: HTMLElement,
- savedVisualizationId: string,
- params: VisualizeLoaderParams
- ) {
- return new Promise((resolve, reject) => {
- this.savedVisualizations.get(savedVisualizationId).then((savedObj: VisSavedObject) => {
- const handler = this.renderVis(element, savedObj, params);
- resolve(handler);
- }, reject);
- });
- }
-
- /**
- * Renders a saved visualization specified by its savedObject into a DOM element.
- * In most of the cases you will need this method, since it allows you to specify
- * filters, handlers, queries, etc. on the savedObject before rendering.
- *
- * We do not encourage you to use this method, since it will most likely be changed
- * or removed in a future version of Kibana. Rather embed a visualization by its id
- * via the {@link #embedVisualizationWithId} method.
- *
- * @deprecated You should rather embed by id, since this method will be removed in the future.
- * @param element The DOM element to render the visualization into.
- * You can alternatively pass a jQuery element instead.
- * @param savedObj The savedObject as it could be retrieved by the
- * `savedVisualizations` service.
- * @param params A list of parameters that will influence rendering.
- *
- * @return The handler to the visualization.
- */
- public embedVisualizationWithSavedObject(
- el: HTMLElement,
- savedObj: VisSavedObject,
- params: VisualizeLoaderParams
- ) {
- return this.renderVis(el, savedObj, params);
- }
-
- /**
- * Returns a promise, that resolves to a list of all saved visualizations.
- *
- * @return Resolves with a list of all saved visualizations as
- * returned by the `savedVisualizations` service in Kibana.
- */
- public getVisualizationList(): Promise {
- return this.savedVisualizations.find().then((result: any) => result.hits);
- }
-
- private renderVis(
- container: HTMLElement,
- savedObj: VisSavedObject,
- params: VisualizeLoaderParams
- ) {
- const { vis, description, searchSource } = savedObj;
-
- vis.description = description;
- vis.searchSource = searchSource;
-
- if (!params.append) {
- container.innerHTML = '';
- }
-
- const element = document.createElement('div');
- element.className = 'visualize';
- element.setAttribute('data-test-subj', 'visualizationLoader');
- container.appendChild(element);
- // We need the container to have display: flex so visualization will render correctly
- container.style.display = 'flex';
-
- // If params specified cssClass, we will set this to the element.
- if (params.cssClass) {
- params.cssClass.split(' ').forEach(cssClass => {
- element.classList.add(cssClass);
- });
- }
-
- // Apply data- attributes to the element if specified
- const dataAttrs = params.dataAttrs;
- if (dataAttrs) {
- Object.keys(dataAttrs).forEach(key => {
- element.setAttribute(`data-${key}`, dataAttrs[key]);
- });
- }
-
- const handlerParams = {
- ...params,
- // lets add query filter angular service to the params
- queryFilter: this.Private(FilterBarQueryFilterProvider),
- // lets add Private to the params, we'll need to pass it to visualize later
- Private: this.Private,
- };
-
- return new EmbeddedVisualizeHandler(element, savedObj, handlerParams);
- }
-}
-
-function VisualizeLoaderProvider(savedVisualizations: any, Private: IPrivate) {
- return new VisualizeLoader(savedVisualizations, Private);
-}
-
-/**
- * Returns a promise, that resolves with the visualize loader, once it's ready.
- * @return A promise, that resolves to the visualize loader.
- */
-function getVisualizeLoader(): Promise {
- return chrome.dangerouslyGetActiveInjector().then($injector => {
- const Private: IPrivate = $injector.get('Private');
- return Private(VisualizeLoaderProvider);
- });
-}
-
-export { getVisualizeLoader, VisualizeLoaderProvider };
diff --git a/src/plugins/dashboard_embeddable_container/public/embeddable/dashboard_container.tsx b/src/plugins/dashboard_embeddable_container/public/embeddable/dashboard_container.tsx
index 36aaecb45ad49..8b258f3558438 100644
--- a/src/plugins/dashboard_embeddable_container/public/embeddable/dashboard_container.tsx
+++ b/src/plugins/dashboard_embeddable_container/public/embeddable/dashboard_container.tsx
@@ -20,7 +20,6 @@
import React from 'react';
import ReactDOM from 'react-dom';
import { I18nProvider } from '@kbn/i18n/react';
-import { Filter } from '@kbn/es-query';
import { RefreshInterval, TimeRange, Query } from '../../../data/public';
import { CoreStart } from '../../../../core/public';
import { IUiActionsStart } from '../ui_actions_plugin';
@@ -38,6 +37,7 @@ import { createPanelState } from './panel';
import { DashboardPanelState } from './types';
import { DashboardViewport } from './viewport/dashboard_viewport';
import { Start as InspectorStartContract } from '../../../inspector/public';
+import { esFilters } from '../../../../plugins/data/public';
import {
KibanaContextProvider,
KibanaReactContext,
@@ -46,7 +46,7 @@ import {
export interface DashboardContainerInput extends ContainerInput {
viewMode: ViewMode;
- filters: Filter[];
+ filters: esFilters.Filter[];
query: Query;
timeRange: TimeRange;
refreshConfig?: RefreshInterval;
@@ -65,7 +65,7 @@ interface IndexSignature {
}
export interface InheritedChildInput extends IndexSignature {
- filters: Filter[];
+ filters: esFilters.Filter[];
query: Query;
timeRange: TimeRange;
refreshConfig?: RefreshInterval;
diff --git a/src/plugins/dashboard_embeddable_container/public/plugin.tsx b/src/plugins/dashboard_embeddable_container/public/plugin.tsx
index eadf70a36416a..dbb5a06da9cd9 100644
--- a/src/plugins/dashboard_embeddable_container/public/plugin.tsx
+++ b/src/plugins/dashboard_embeddable_container/public/plugin.tsx
@@ -61,9 +61,10 @@ export class DashboardEmbeddableContainerPublicPlugin
const { application, notifications, overlays } = core;
const { embeddable, inspector, uiActions } = plugins;
- const SavedObjectFinder: React.FC<
- Exclude
- > = props => (
+ const SavedObjectFinder: React.FC> = props => (
fields.find(field => field.name === name);
diff --git a/packages/kbn-es-query/src/filters/lib/custom_filter.ts b/src/plugins/data/common/es_query/filters/custom_filter.ts
similarity index 100%
rename from packages/kbn-es-query/src/filters/lib/custom_filter.ts
rename to src/plugins/data/common/es_query/filters/custom_filter.ts
diff --git a/packages/kbn-es-query/src/filters/lib/exists_filter.ts b/src/plugins/data/common/es_query/filters/exists_filter.ts
similarity index 81%
rename from packages/kbn-es-query/src/filters/lib/exists_filter.ts
rename to src/plugins/data/common/es_query/filters/exists_filter.ts
index 5843c25c43cff..1a404ca415117 100644
--- a/packages/kbn-es-query/src/filters/lib/exists_filter.ts
+++ b/src/plugins/data/common/es_query/filters/exists_filter.ts
@@ -18,6 +18,7 @@
*/
import { Filter, FilterMeta } from './meta_filter';
+import { IndexPattern, Field } from '../../types';
export type ExistsFilterMeta = FilterMeta;
@@ -31,3 +32,14 @@ export type ExistsFilter = Filter & {
};
export const isExistsFilter = (filter: any): filter is ExistsFilter => filter && filter.exists;
+
+export const buildExistsFilter = (field: Field, indexPattern: IndexPattern) => {
+ return {
+ meta: {
+ index: indexPattern.id,
+ },
+ exists: {
+ field: field.name,
+ },
+ } as ExistsFilter;
+};
diff --git a/packages/kbn-es-query/src/filters/lib/geo_bounding_box_filter.ts b/src/plugins/data/common/es_query/filters/geo_bounding_box_filter.ts
similarity index 100%
rename from packages/kbn-es-query/src/filters/lib/geo_bounding_box_filter.ts
rename to src/plugins/data/common/es_query/filters/geo_bounding_box_filter.ts
diff --git a/packages/kbn-es-query/src/filters/lib/geo_polygon_filter.ts b/src/plugins/data/common/es_query/filters/geo_polygon_filter.ts
similarity index 100%
rename from packages/kbn-es-query/src/filters/lib/geo_polygon_filter.ts
rename to src/plugins/data/common/es_query/filters/geo_polygon_filter.ts
diff --git a/src/plugins/data/common/es_query/filters/index.ts b/src/plugins/data/common/es_query/filters/index.ts
new file mode 100644
index 0000000000000..e28ce9ba74975
--- /dev/null
+++ b/src/plugins/data/common/es_query/filters/index.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 * from './custom_filter';
+export * from './exists_filter';
+export * from './geo_bounding_box_filter';
+export * from './geo_polygon_filter';
+export * from './match_all_filter';
+export * from './meta_filter';
+export * from './missing_filter';
+export * from './phrase_filter';
+export * from './phrases_filter';
+export * from './query_string_filter';
+export * from './range_filter';
+
+export * from './types';
diff --git a/packages/kbn-es-query/src/filters/lib/match_all_filter.ts b/src/plugins/data/common/es_query/filters/match_all_filter.ts
similarity index 100%
rename from packages/kbn-es-query/src/filters/lib/match_all_filter.ts
rename to src/plugins/data/common/es_query/filters/match_all_filter.ts
diff --git a/packages/kbn-es-query/src/filters/lib/meta_filter.ts b/src/plugins/data/common/es_query/filters/meta_filter.ts
similarity index 75%
rename from packages/kbn-es-query/src/filters/lib/meta_filter.ts
rename to src/plugins/data/common/es_query/filters/meta_filter.ts
index 8f6aef782cea2..9adfdc4eedcb3 100644
--- a/packages/kbn-es-query/src/filters/lib/meta_filter.ts
+++ b/src/plugins/data/common/es_query/filters/meta_filter.ts
@@ -55,7 +55,7 @@ export interface LatLon {
lon: number;
}
-export function buildEmptyFilter(isPinned: boolean, index?: string): Filter {
+export const buildEmptyFilter = (isPinned: boolean, index?: string): Filter => {
const meta: FilterMeta = {
disabled: false,
negate: false,
@@ -65,43 +65,43 @@ export function buildEmptyFilter(isPinned: boolean, index?: string): Filter {
const $state: FilterState = {
store: isPinned ? FilterStateStore.GLOBAL_STATE : FilterStateStore.APP_STATE,
};
+
return { meta, $state };
-}
+};
-export function isFilterPinned(filter: Filter) {
+export const isFilterPinned = (filter: Filter) => {
return filter.$state && filter.$state.store === FilterStateStore.GLOBAL_STATE;
-}
+};
-export function toggleFilterDisabled(filter: Filter) {
+export const toggleFilterDisabled = (filter: Filter) => {
const disabled = !filter.meta.disabled;
const meta = { ...filter.meta, disabled };
+
return { ...filter, meta };
-}
+};
-export function toggleFilterNegated(filter: Filter) {
+export const toggleFilterNegated = (filter: Filter) => {
const negate = !filter.meta.negate;
const meta = { ...filter.meta, negate };
+
return { ...filter, meta };
-}
+};
-export function toggleFilterPinned(filter: Filter) {
+export const toggleFilterPinned = (filter: Filter) => {
const store = isFilterPinned(filter) ? FilterStateStore.APP_STATE : FilterStateStore.GLOBAL_STATE;
const $state = { ...filter.$state, store };
+
return { ...filter, $state };
-}
+};
-export function enableFilter(filter: Filter) {
- return !filter.meta.disabled ? filter : toggleFilterDisabled(filter);
-}
+export const enableFilter = (filter: Filter) =>
+ !filter.meta.disabled ? filter : toggleFilterDisabled(filter);
-export function disableFilter(filter: Filter) {
- return filter.meta.disabled ? filter : toggleFilterDisabled(filter);
-}
+export const disableFilter = (filter: Filter) =>
+ filter.meta.disabled ? filter : toggleFilterDisabled(filter);
-export function pinFilter(filter: Filter) {
- return isFilterPinned(filter) ? filter : toggleFilterPinned(filter);
-}
+export const pinFilter = (filter: Filter) =>
+ isFilterPinned(filter) ? filter : toggleFilterPinned(filter);
-export function unpinFilter(filter: Filter) {
- return !isFilterPinned(filter) ? filter : toggleFilterPinned(filter);
-}
+export const unpinFilter = (filter: Filter) =>
+ !isFilterPinned(filter) ? filter : toggleFilterPinned(filter);
diff --git a/packages/kbn-es-query/src/filters/lib/missing_filter.ts b/src/plugins/data/common/es_query/filters/missing_filter.ts
similarity index 100%
rename from packages/kbn-es-query/src/filters/lib/missing_filter.ts
rename to src/plugins/data/common/es_query/filters/missing_filter.ts
diff --git a/src/plugins/data/common/es_query/filters/phrase_filter.test.ts b/src/plugins/data/common/es_query/filters/phrase_filter.test.ts
new file mode 100644
index 0000000000000..250ec792fbb57
--- /dev/null
+++ b/src/plugins/data/common/es_query/filters/phrase_filter.test.ts
@@ -0,0 +1,97 @@
+/*
+ * 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 { buildInlineScriptForPhraseFilter, buildPhraseFilter } from './phrase_filter';
+import { IndexPattern } from '../../types';
+import { getField } from '../__tests__/fields_mock';
+
+describe('Phrase filter builder', () => {
+ let indexPattern: IndexPattern;
+
+ beforeEach(() => {
+ indexPattern = {
+ id: 'id',
+ };
+ });
+
+ it('should be a function', () => {
+ expect(typeof buildPhraseFilter).toBe('function');
+ });
+
+ it('should return a match query filter when passed a standard field', () => {
+ const field = getField('bytes');
+
+ expect(buildPhraseFilter(field, 5, indexPattern)).toEqual({
+ meta: {
+ index: 'id',
+ },
+ query: {
+ match_phrase: {
+ bytes: 5,
+ },
+ },
+ });
+ });
+
+ it('should return a script filter when passed a scripted field', () => {
+ const field = getField('script number');
+
+ expect(buildPhraseFilter(field, 5, indexPattern)).toEqual({
+ meta: {
+ index: 'id',
+ field: 'script number',
+ },
+ script: {
+ script: {
+ lang: 'expression',
+ params: {
+ value: 5,
+ },
+ source: '(1234) == value',
+ },
+ },
+ });
+ });
+});
+
+describe('buildInlineScriptForPhraseFilter', () => {
+ it('should wrap painless scripts in a lambda', () => {
+ const field = {
+ lang: 'painless',
+ script: 'return foo;',
+ };
+
+ const expected =
+ `boolean compare(Supplier s, def v) {return s.get() == v;}` +
+ `compare(() -> { return foo; }, params.value);`;
+
+ expect(buildInlineScriptForPhraseFilter(field)).toBe(expected);
+ });
+
+ it('should create a simple comparison for other langs', () => {
+ const field = {
+ lang: 'expression',
+ script: 'doc[bytes].value',
+ };
+
+ const expected = `(doc[bytes].value) == value`;
+
+ expect(buildInlineScriptForPhraseFilter(field)).toBe(expected);
+ });
+});
diff --git a/src/plugins/data/common/es_query/filters/phrase_filter.ts b/src/plugins/data/common/es_query/filters/phrase_filter.ts
new file mode 100644
index 0000000000000..35110c924fe61
--- /dev/null
+++ b/src/plugins/data/common/es_query/filters/phrase_filter.ts
@@ -0,0 +1,144 @@
+/*
+ * 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 { get, isPlainObject } from 'lodash';
+import { Filter, FilterMeta } from './meta_filter';
+import { IndexPattern, Field } from '../../types';
+
+export type PhraseFilterMeta = FilterMeta & {
+ params?: {
+ query: string; // The unformatted value
+ };
+ script?: {
+ script: {
+ source?: any;
+ lang?: string;
+ params: any;
+ };
+ };
+ field?: any;
+ index?: any;
+};
+
+export type PhraseFilter = Filter & {
+ meta: PhraseFilterMeta;
+};
+
+type PhraseFilterValue = string | number | boolean;
+
+export const isPhraseFilter = (filter: any): filter is PhraseFilter => {
+ const isMatchPhraseQuery = filter && filter.query && filter.query.match_phrase;
+
+ const isDeprecatedMatchPhraseQuery =
+ filter &&
+ filter.query &&
+ filter.query.match &&
+ Object.values(filter.query.match).find((params: any) => params.type === 'phrase');
+
+ return !!(isMatchPhraseQuery || isDeprecatedMatchPhraseQuery);
+};
+
+export const isScriptedPhraseFilter = (filter: any): filter is PhraseFilter =>
+ Boolean(get(filter, 'script.script.params.value'));
+
+export const getPhraseFilterField = (filter: PhraseFilter) => {
+ const queryConfig = filter.query.match_phrase || filter.query.match;
+ return Object.keys(queryConfig)[0];
+};
+
+export const getPhraseFilterValue = (filter: PhraseFilter): PhraseFilterValue => {
+ const queryConfig = filter.query.match_phrase || filter.query.match;
+ const queryValue = Object.values(queryConfig)[0] as any;
+ return isPlainObject(queryValue) ? queryValue.query : queryValue;
+};
+
+export const buildPhraseFilter = (
+ field: Field,
+ value: any,
+ indexPattern: IndexPattern
+): PhraseFilter => {
+ const convertedValue = getConvertedValueForField(field, value);
+
+ if (field.scripted) {
+ return {
+ meta: { index: indexPattern.id, field: field.name } as PhraseFilterMeta,
+ script: getPhraseScript(field, value),
+ } as PhraseFilter;
+ } else {
+ return {
+ meta: { index: indexPattern.id },
+ query: {
+ match_phrase: {
+ [field.name]: convertedValue,
+ },
+ },
+ } as PhraseFilter;
+ }
+};
+
+export const getPhraseScript = (field: Field, value: string) => {
+ const convertedValue = getConvertedValueForField(field, value);
+ const script = buildInlineScriptForPhraseFilter(field);
+
+ return {
+ script: {
+ source: script,
+ lang: field.lang,
+ params: {
+ value: convertedValue,
+ },
+ },
+ };
+};
+
+// See https://github.com/elastic/elasticsearch/issues/20941 and https://github.com/elastic/kibana/issues/8677
+// and https://github.com/elastic/elasticsearch/pull/22201
+// for the reason behind this change. Aggs now return boolean buckets with a key of 1 or 0.
+export const getConvertedValueForField = (field: Field, value: any) => {
+ if (typeof value !== 'boolean' && field.type === 'boolean') {
+ if ([1, 'true'].includes(value)) {
+ return true;
+ } else if ([0, 'false'].includes(value)) {
+ return false;
+ } else {
+ throw new Error(`${value} is not a valid boolean value for boolean field ${field.name}`);
+ }
+ }
+ return value;
+};
+
+/**
+ * Takes a scripted field and returns an inline script appropriate for use in a script query.
+ * Handles lucene expression and Painless scripts. Other langs aren't guaranteed to generate valid
+ * scripts.
+ *
+ * @param {object} scriptedField A Field object representing a scripted field
+ * @returns {string} The inline script string
+ */
+export const buildInlineScriptForPhraseFilter = (scriptedField: any) => {
+ // We must wrap painless scripts in a lambda in case they're more than a simple expression
+ if (scriptedField.lang === 'painless') {
+ return (
+ `boolean compare(Supplier s, def v) {return s.get() == v;}` +
+ `compare(() -> { ${scriptedField.script} }, params.value);`
+ );
+ } else {
+ return `(${scriptedField.script}) == value`;
+ }
+};
diff --git a/packages/kbn-es-query/src/filters/phrases.js b/src/plugins/data/common/es_query/filters/phrases_filter.ts
similarity index 50%
rename from packages/kbn-es-query/src/filters/phrases.js
rename to src/plugins/data/common/es_query/filters/phrases_filter.ts
index f02b3763f37bb..e207a3ff5961b 100644
--- a/packages/kbn-es-query/src/filters/phrases.js
+++ b/src/plugins/data/common/es_query/filters/phrases_filter.ts
@@ -17,47 +17,54 @@
* under the License.
*/
-import { getPhraseScript } from './phrase';
+import { Filter, FilterMeta } from './meta_filter';
+import { Field, IndexPattern } from '../../types';
+import { getPhraseScript } from './phrase_filter';
+
+export type PhrasesFilterMeta = FilterMeta & {
+ params: string[]; // The unformatted values
+ field?: string;
+};
+
+export type PhrasesFilter = Filter & {
+ meta: PhrasesFilterMeta;
+};
+
+export const isPhrasesFilter = (filter: any): filter is PhrasesFilter =>
+ filter && filter.meta.type === 'phrases';
// Creates a filter where the given field matches one or more of the given values
// params should be an array of values
-export function buildPhrasesFilter(field, params, indexPattern) {
+export const buildPhrasesFilter = (field: Field, params: any, indexPattern: IndexPattern) => {
const index = indexPattern.id;
const type = 'phrases';
const key = field.name;
- const value = params
- .map(value => format(field, value))
- .join(', ');
- const filter = {
- meta: { index, type, key, value, params }
- };
+ const format = (f: Field, value: any) =>
+ f && f.format && f.format.convert ? f.format.convert(value) : value;
+
+ const value = params.map((v: any) => format(field, v)).join(', ');
let should;
if (field.scripted) {
- should = params.map((value) => ({
- script: getPhraseScript(field, value)
+ should = params.map((v: any) => ({
+ script: getPhraseScript(field, v),
}));
} else {
- should = params.map((value) => ({
+ should = params.map((v: any) => ({
match_phrase: {
- [field.name]: value
- }
+ [field.name]: v,
+ },
}));
}
- filter.query = {
- bool: {
- should,
- minimum_should_match: 1
- }
- };
-
- return filter;
-}
-
-function format(field, value) {
- return field && field.format && field.format.convert
- ? field.format.convert(value)
- : value;
-}
+ return {
+ meta: { index, type, key, value, params },
+ query: {
+ bool: {
+ should,
+ minimum_should_match: 1,
+ },
+ },
+ } as PhrasesFilter;
+};
diff --git a/src/plugins/data/common/es_query/filters/query_string_filter.test.ts b/src/plugins/data/common/es_query/filters/query_string_filter.test.ts
new file mode 100644
index 0000000000000..5a580db0c57b8
--- /dev/null
+++ b/src/plugins/data/common/es_query/filters/query_string_filter.test.ts
@@ -0,0 +1,47 @@
+/*
+ * 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 { buildQueryFilter } from './query_string_filter';
+import { IndexPattern } from '../../types';
+
+describe('Phrase filter builder', () => {
+ let indexPattern: IndexPattern;
+
+ beforeEach(() => {
+ indexPattern = {
+ id: 'id',
+ };
+ });
+
+ it('should be a function', () => {
+ expect(typeof buildQueryFilter).toBe('function');
+ });
+
+ it('should return a query filter when passed a standard field', () => {
+ expect(buildQueryFilter({ foo: 'bar' }, indexPattern.id, '')).toEqual({
+ meta: {
+ alias: '',
+ index: 'id',
+ },
+ query: {
+ foo: 'bar',
+ },
+ });
+ });
+});
diff --git a/packages/kbn-es-query/src/filters/lib/query_string_filter.ts b/src/plugins/data/common/es_query/filters/query_string_filter.ts
similarity index 78%
rename from packages/kbn-es-query/src/filters/lib/query_string_filter.ts
rename to src/plugins/data/common/es_query/filters/query_string_filter.ts
index 3b3b97fafba9b..d2374162b195f 100644
--- a/packages/kbn-es-query/src/filters/lib/query_string_filter.ts
+++ b/src/plugins/data/common/es_query/filters/query_string_filter.ts
@@ -18,6 +18,7 @@
*/
import { Filter, FilterMeta } from './meta_filter';
+import { IndexPattern } from '../../types';
export type QueryStringFilterMeta = FilterMeta;
@@ -32,3 +33,17 @@ export type QueryStringFilter = Filter & {
export const isQueryStringFilter = (filter: any): filter is QueryStringFilter =>
filter && filter.query && filter.query.query_string;
+
+// Creates a filter corresponding to a raw Elasticsearch query DSL object
+export const buildQueryFilter = (
+ query: QueryStringFilter['query'],
+ index: IndexPattern,
+ alias: string
+) =>
+ ({
+ query,
+ meta: {
+ index,
+ alias,
+ },
+ } as QueryStringFilter);
diff --git a/src/plugins/data/common/es_query/filters/range_filter.test.ts b/src/plugins/data/common/es_query/filters/range_filter.test.ts
new file mode 100644
index 0000000000000..017bb8e9cb7c5
--- /dev/null
+++ b/src/plugins/data/common/es_query/filters/range_filter.test.ts
@@ -0,0 +1,174 @@
+/*
+ * 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 { each } from 'lodash';
+import { buildRangeFilter, RangeFilter } from './range_filter';
+import { IndexPattern, Field } from '../../types';
+import { getField } from '../__tests__/fields_mock';
+
+describe('Range filter builder', () => {
+ let indexPattern: IndexPattern;
+
+ beforeEach(() => {
+ indexPattern = {
+ id: 'id',
+ };
+ });
+
+ it('should be a function', () => {
+ expect(typeof buildRangeFilter).toBe('function');
+ });
+
+ it('should return a range filter when passed a standard field', () => {
+ const field = getField('bytes');
+
+ expect(buildRangeFilter(field, { gte: 1, lte: 3 }, indexPattern)).toEqual({
+ meta: {
+ index: 'id',
+ params: {},
+ },
+ range: {
+ bytes: {
+ gte: 1,
+ lte: 3,
+ },
+ },
+ });
+ });
+
+ it('should return a script filter when passed a scripted field', () => {
+ const field = getField('script number');
+
+ expect(buildRangeFilter(field, { gte: 1, lte: 3 }, indexPattern)).toEqual({
+ meta: {
+ field: 'script number',
+ index: 'id',
+ params: {},
+ },
+ script: {
+ script: {
+ lang: 'expression',
+ source: '(' + field!.script + ')>=gte && (' + field!.script + ')<=lte',
+ params: {
+ value: '>=1 <=3',
+ gte: 1,
+ lte: 3,
+ },
+ },
+ },
+ });
+ });
+
+ it('should wrap painless scripts in comparator lambdas', () => {
+ const field = getField('script date');
+ const expected =
+ `boolean gte(Supplier s, def v) {return !s.get().toInstant().isBefore(Instant.parse(v))} ` +
+ `boolean lte(Supplier s, def v) {return !s.get().toInstant().isAfter(Instant.parse(v))}` +
+ `gte(() -> { ${field!.script} }, params.gte) && ` +
+ `lte(() -> { ${field!.script} }, params.lte)`;
+
+ const rangeFilter = buildRangeFilter(field, { gte: 1, lte: 3 }, indexPattern);
+
+ expect(rangeFilter.script!.script.source).toBe(expected);
+ });
+
+ it('should throw an error when gte and gt, or lte and lt are both passed', () => {
+ const field = getField('script number');
+
+ expect(() => {
+ buildRangeFilter(field, { gte: 1, gt: 3 }, indexPattern);
+ }).toThrowError();
+
+ expect(() => {
+ buildRangeFilter(field, { lte: 1, lt: 3 }, indexPattern);
+ }).toThrowError();
+ });
+
+ it('to use the right operator for each of gte, gt, lt and lte', () => {
+ const field = getField('script number');
+
+ each({ gte: '>=', gt: '>', lte: '<=', lt: '<' }, (operator: string, key: any) => {
+ const params = {
+ [key]: 5,
+ };
+
+ const filter = buildRangeFilter(field, params, indexPattern);
+ const script = filter.script!.script;
+
+ expect(script.source).toBe('(' + field!.script + ')' + operator + key);
+ expect(script.params[key]).toBe(5);
+ expect(script.params.value).toBe(operator + 5);
+ });
+ });
+
+ describe('when given params where one side is infinite', () => {
+ let field: Field;
+ let filter: RangeFilter;
+
+ beforeEach(() => {
+ field = getField('script number');
+ filter = buildRangeFilter(field, { gte: 0, lt: Infinity }, indexPattern);
+ });
+
+ describe('returned filter', () => {
+ it('is a script filter', () => {
+ expect(filter).toHaveProperty('script');
+ });
+
+ it('contain a param for the finite side', () => {
+ expect(filter.script!.script.params).toHaveProperty('gte', 0);
+ });
+
+ it('does not contain a param for the infinite side', () => {
+ expect(filter.script!.script.params).not.toHaveProperty('lt');
+ });
+
+ it('does not contain a script condition for the infinite side', () => {
+ const script = field!.script;
+
+ expect(filter.script!.script.source).toEqual(`(${script})>=gte`);
+ });
+ });
+ });
+
+ describe('when given params where both sides are infinite', () => {
+ let field: Field;
+ let filter: RangeFilter;
+
+ beforeEach(() => {
+ field = getField('script number');
+ filter = buildRangeFilter(field, { gte: -Infinity, lt: Infinity }, indexPattern);
+ });
+
+ describe('returned filter', () => {
+ it('is a match_all filter', () => {
+ expect(filter).not.toHaveProperty('script');
+ expect(filter).toHaveProperty('match_all');
+ });
+
+ it('does not contain params', () => {
+ expect(filter).not.toHaveProperty('params');
+ });
+
+ it('meta field is set to field name', () => {
+ expect(filter.meta.field).toEqual('script number');
+ });
+ });
+ });
+});
diff --git a/packages/kbn-es-query/src/filters/range.js b/src/plugins/data/common/es_query/filters/range_filter.ts
similarity index 51%
rename from packages/kbn-es-query/src/filters/range.js
rename to src/plugins/data/common/es_query/filters/range_filter.ts
index 357f9209c50de..c2513a9dc0c5e 100644
--- a/packages/kbn-es-query/src/filters/range.js
+++ b/src/plugins/data/common/es_query/filters/range_filter.ts
@@ -16,9 +16,12 @@
* specific language governing permissions and limitations
* under the License.
*/
+import { map, reduce, mapValues, get, keys, pick } from 'lodash';
+import { Filter, FilterMeta } from './meta_filter';
+import { Field, IndexPattern } from '../../types';
-import _ from 'lodash';
const OPERANDS_IN_RANGE = 2;
+
const operators = {
gt: '>',
gte: '>=',
@@ -39,33 +42,85 @@ const dateComparators = {
lt: 'boolean lt(Supplier s, def v) {return s.get().toInstant().isBefore(Instant.parse(v))}',
};
-function formatValue(field, params) {
- return _.map(params, (val, key) => operators[key] + format(field, val)).join(' ');
+export interface RangeFilterParams {
+ from?: number | string;
+ to?: number | string;
+ gt?: number | string;
+ lt?: number | string;
+ gte?: number | string;
+ lte?: number | string;
+ format?: string;
}
+const hasRangeKeys = (params: RangeFilterParams) =>
+ Boolean(
+ keys(params).find((key: string) => ['gte', 'gt', 'lte', 'lt', 'from', 'to'].includes(key))
+ );
+
+export type RangeFilterMeta = FilterMeta & {
+ params: RangeFilterParams;
+ field?: any;
+ formattedValue?: string;
+};
+
+export type RangeFilter = Filter & {
+ meta: RangeFilterMeta;
+ script?: {
+ script: {
+ params: any;
+ lang: string;
+ source: any;
+ };
+ };
+ match_all?: any;
+ range: { [key: string]: RangeFilterParams };
+};
+
+export const isRangeFilter = (filter: any): filter is RangeFilter => filter && filter.range;
+
+export const isScriptedRangeFilter = (filter: any): filter is RangeFilter => {
+ const params: RangeFilterParams = get(filter, 'script.script.params', {});
+
+ return hasRangeKeys(params);
+};
+
+const formatValue = (field: Field, params: any[]) =>
+ map(params, (val: any, key: string) => get(operators, key) + format(field, val)).join(' ');
+
+const format = (field: Field, value: any) =>
+ field && field.format && field.format.convert ? field.format.convert(value) : value;
+
// Creates a filter where the value for the given field is in the given range
// params should be an object containing `lt`, `lte`, `gt`, and/or `gte`
-export function buildRangeFilter(field, params, indexPattern, formattedValue) {
- const filter = { meta: { index: indexPattern.id } };
- if (formattedValue) filter.meta.formattedValue = formattedValue;
+export const buildRangeFilter = (
+ field: Field,
+ params: RangeFilterParams,
+ indexPattern: IndexPattern,
+ formattedValue?: string
+): RangeFilter => {
+ const filter: any = { meta: { index: indexPattern.id, params: {} } };
+
+ if (formattedValue) {
+ filter.meta.formattedValue = formattedValue;
+ }
- params = _.mapValues(params, (value) => {
- return (field.type === 'number') ? parseFloat(value) : value;
- });
+ params = mapValues(params, value => (field.type === 'number' ? parseFloat(value) : value));
if ('gte' in params && 'gt' in params) throw new Error('gte and gt are mutually exclusive');
if ('lte' in params && 'lt' in params) throw new Error('lte and lt are mutually exclusive');
- const totalInfinite = ['gt', 'lt'].reduce((totalInfinite, op) => {
+ const totalInfinite = ['gt', 'lt'].reduce((acc: number, op: any) => {
const key = op in params ? op : `${op}e`;
- const isInfinite = Math.abs(params[key]) === Infinity;
+ const isInfinite = Math.abs(get(params, key)) === Infinity;
if (isInfinite) {
- totalInfinite++;
+ acc++;
+
+ // @ts-ignore
delete params[key];
}
- return totalInfinite;
+ return acc;
}, 0);
if (totalInfinite === OPERANDS_IN_RANGE) {
@@ -81,25 +136,29 @@ export function buildRangeFilter(field, params, indexPattern, formattedValue) {
filter.range[field.name] = params;
}
- return filter;
-}
+ return filter as RangeFilter;
+};
-export function getRangeScript(field, params) {
- const knownParams = _.pick(params, (val, key) => {
- return key in operators;
- });
- let script = _.map(knownParams, function (val, key) {
- return '(' + field.script + ')' + operators[key] + key;
- }).join(' && ');
+export const getRangeScript = (field: IndexPattern, params: RangeFilterParams) => {
+ const knownParams = pick(params, (val, key: any) => key in operators);
+ let script = map(
+ knownParams,
+ (val: any, key: string) => '(' + field.script + ')' + get(operators, key) + key
+ ).join(' && ');
// We must wrap painless scripts in a lambda in case they're more than a simple expression
if (field.lang === 'painless') {
const comp = field.type === 'date' ? dateComparators : comparators;
- const currentComparators = _.reduce(knownParams, (acc, val, key) => acc.concat(comp[key]), []).join(' ');
+ const currentComparators = reduce(
+ knownParams,
+ (acc, val, key) => acc.concat(get(comp, key)),
+ []
+ ).join(' ');
- const comparisons = _.map(knownParams, function (val, key) {
- return `${key}(() -> { ${field.script} }, params.${key})`;
- }).join(' && ');
+ const comparisons = map(
+ knownParams,
+ (val, key) => `${key}(() -> { ${field.script} }, params.${key})`
+ ).join(' && ');
script = `${currentComparators}${comparisons}`;
}
@@ -108,14 +167,7 @@ export function getRangeScript(field, params) {
script: {
source: script,
params: knownParams,
- lang: field.lang
- }
+ lang: field.lang,
+ },
};
-}
-
-function format(field, value) {
- return field && field.format && field.format.convert
- ? field.format.convert(value)
- : value;
-}
-
+};
diff --git a/src/plugins/data/common/es_query/filters/types.ts b/src/plugins/data/common/es_query/filters/types.ts
new file mode 100644
index 0000000000000..a242df4811c05
--- /dev/null
+++ b/src/plugins/data/common/es_query/filters/types.ts
@@ -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.
+ */
+
+import { ExistsFilter } from './exists_filter';
+import { GeoBoundingBoxFilter } from './geo_bounding_box_filter';
+import { GeoPolygonFilter } from './geo_polygon_filter';
+import { PhrasesFilter } from './phrases_filter';
+import { PhraseFilter } from './phrase_filter';
+import { RangeFilter } from './range_filter';
+import { MatchAllFilter } from './match_all_filter';
+import { MissingFilter } from './missing_filter';
+
+// Any filter associated with a field (used in the filter bar/editor)
+export type FieldFilter =
+ | ExistsFilter
+ | GeoBoundingBoxFilter
+ | GeoPolygonFilter
+ | PhraseFilter
+ | PhrasesFilter
+ | RangeFilter
+ | MatchAllFilter
+ | MissingFilter;
+
+export enum FILTERS {
+ CUSTOM = 'custom',
+ PHRASES = 'phrases',
+ PHRASE = 'phrase',
+ EXISTS = 'exists',
+ MATCH_ALL = 'match_all',
+ MISSING = 'missing',
+ QUERY_STRING = 'query_string',
+ RANGE = 'range',
+ GEO_BOUNDING_BOX = 'geo_bounding_box',
+ GEO_POLYGON = 'geo_polygon',
+}
diff --git a/src/legacy/server/index_patterns/service/index.ts b/src/plugins/data/common/es_query/index.ts
similarity index 92%
rename from src/legacy/server/index_patterns/service/index.ts
rename to src/plugins/data/common/es_query/index.ts
index 496c4ba7b5b6f..88e14a43cfaae 100644
--- a/src/legacy/server/index_patterns/service/index.ts
+++ b/src/plugins/data/common/es_query/index.ts
@@ -16,5 +16,6 @@
* specific language governing permissions and limitations
* under the License.
*/
+import * as esFilters from './filters';
-export * from './index_patterns_service';
+export { esFilters };
diff --git a/src/plugins/data/common/index.ts b/src/plugins/data/common/index.ts
index dca7897bd2766..42b5a03fcc926 100644
--- a/src/plugins/data/common/index.ts
+++ b/src/plugins/data/common/index.ts
@@ -20,5 +20,6 @@
export * from './query';
export * from './field_formats';
export * from './kbn_field_types';
+export * from './es_query';
export * from './types';
diff --git a/src/plugins/data/common/types.ts b/src/plugins/data/common/types.ts
index 9eda75d8abd0b..ec8d8b006317f 100644
--- a/src/plugins/data/common/types.ts
+++ b/src/plugins/data/common/types.ts
@@ -21,3 +21,10 @@ export * from './field_formats/types';
export * from './timefilter/types';
export * from './query/types';
export * from './kbn_field_types/types';
+
+// We can't import the real types from the data plugin, so need to either duplicate
+// them here or figure out another solution, perhaps housing them in this package
+// will be replaces after Fieds / IndexPattern will be moved into new platform
+export type Field = any;
+export type IndexPattern = any;
+export type StaticIndexPattern = any;
diff --git a/src/plugins/data/public/autocomplete_provider/types.ts b/src/plugins/data/public/autocomplete_provider/types.ts
index 1f2d8f914dde3..d838e54e9ead4 100644
--- a/src/plugins/data/public/autocomplete_provider/types.ts
+++ b/src/plugins/data/public/autocomplete_provider/types.ts
@@ -17,8 +17,8 @@
* under the License.
*/
-import { StaticIndexPattern, Field } from 'ui/index_patterns';
import { AutocompleteProviderRegister } from '.';
+import { Field, StaticIndexPattern } from '..';
export type AutocompletePublicPluginSetup = Pick<
AutocompleteProviderRegister,
diff --git a/src/plugins/data/public/index.ts b/src/plugins/data/public/index.ts
index 51f26a4bd7f31..32153df69f367 100644
--- a/src/plugins/data/public/index.ts
+++ b/src/plugins/data/public/index.ts
@@ -34,5 +34,4 @@ export * from './types';
export { IRequestTypesMap, IResponseTypesMap } from './search';
export * from './search';
-
export * from './query';
diff --git a/src/plugins/data/public/index_patterns/field.stub.ts b/src/plugins/data/public/index_patterns/field.stub.ts
new file mode 100644
index 0000000000000..315894cd212c4
--- /dev/null
+++ b/src/plugins/data/public/index_patterns/field.stub.ts
@@ -0,0 +1,79 @@
+/*
+ * 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 { Field } from '../../common';
+
+export const stubFields: Field[] = [
+ {
+ name: 'machine.os',
+ esTypes: ['text'],
+ type: 'string',
+ aggregatable: false,
+ searchable: false,
+ filterable: true,
+ },
+ {
+ name: 'machine.os.raw',
+ type: 'string',
+ esTypes: ['keyword'],
+ aggregatable: true,
+ searchable: true,
+ filterable: true,
+ },
+ {
+ name: 'not.filterable',
+ type: 'string',
+ esTypes: ['text'],
+ aggregatable: true,
+ searchable: false,
+ filterable: false,
+ },
+ {
+ name: 'bytes',
+ type: 'number',
+ esTypes: ['long'],
+ aggregatable: true,
+ searchable: true,
+ filterable: true,
+ },
+ {
+ name: '@timestamp',
+ type: 'date',
+ esTypes: ['date'],
+ aggregatable: true,
+ searchable: true,
+ filterable: true,
+ },
+ {
+ name: 'clientip',
+ type: 'ip',
+ esTypes: ['ip'],
+ aggregatable: true,
+ searchable: true,
+ filterable: true,
+ },
+ {
+ name: 'bool.field',
+ type: 'boolean',
+ esTypes: ['boolean'],
+ aggregatable: true,
+ searchable: true,
+ filterable: true,
+ },
+];
diff --git a/packages/kbn-es-query/src/filters/index.js b/src/plugins/data/public/index_patterns/index_pattern.stub.ts
similarity index 77%
rename from packages/kbn-es-query/src/filters/index.js
rename to src/plugins/data/public/index_patterns/index_pattern.stub.ts
index d7d092eabd8a2..444e65cd0cd4b 100644
--- a/packages/kbn-es-query/src/filters/index.js
+++ b/src/plugins/data/public/index_patterns/index_pattern.stub.ts
@@ -17,9 +17,12 @@
* under the License.
*/
-export * from './exists';
-export * from './phrase';
-export * from './phrases';
-export * from './query';
-export * from './range';
-export * from './lib';
+import { IndexPattern } from '../../common';
+import { stubFields } from './field.stub';
+
+export const stubIndexPattern: IndexPattern = {
+ id: 'logstash-*',
+ fields: stubFields,
+ title: 'logstash-*',
+ timeFieldName: '@timestamp',
+};
diff --git a/src/plugins/data/public/mocks.ts b/src/plugins/data/public/mocks.ts
index 2269ba3c55bce..4aae63c24d7fc 100644
--- a/src/plugins/data/public/mocks.ts
+++ b/src/plugins/data/public/mocks.ts
@@ -31,8 +31,8 @@ const autocompleteMock: any = {
const createSetupContract = (): Setup => {
const querySetupMock = queryServiceMock.createSetupContract();
- const setupContract: Setup = {
- autocomplete: autocompleteMock as Setup['autocomplete'],
+ const setupContract = {
+ autocomplete: autocompleteMock,
search: searchSetupMock,
query: querySetupMock,
};
@@ -42,8 +42,8 @@ const createSetupContract = (): Setup => {
const createStartContract = (): Start => {
const queryStartMock = queryServiceMock.createStartContract();
- const startContract: Start = {
- autocomplete: autocompleteMock as Start['autocomplete'],
+ const startContract = {
+ autocomplete: autocompleteMock,
getSuggestions: jest.fn(),
search: { search: jest.fn() },
query: queryStartMock,
diff --git a/src/plugins/data/public/plugin.ts b/src/plugins/data/public/plugin.ts
index a13e912e77846..79db34c022b39 100644
--- a/src/plugins/data/public/plugin.ts
+++ b/src/plugins/data/public/plugin.ts
@@ -18,6 +18,7 @@
*/
import { PluginInitializerContext, CoreSetup, CoreStart, Plugin } from '../../../core/public';
+import { Storage } from '../../kibana_utils/public';
import { DataPublicPluginSetup, DataPublicPluginStart } from './types';
import { AutocompleteProviderRegister } from './autocomplete_provider';
import { getSuggestionsProvider } from './suggestions_provider';
@@ -35,11 +36,13 @@ export class DataPublicPlugin implements Plugin {
let updateListener: sinon.SinonSpy;
let filterManager: FilterManager;
- let readyFilters: Filter[];
+ let readyFilters: esFilters.Filter[];
beforeEach(() => {
updateListener = sinon.stub();
@@ -82,7 +82,7 @@ describe('filter_manager', () => {
test('app state should be set', async () => {
updateSubscription = filterManager.getUpdates$().subscribe(updateListener);
- const f1 = getFilter(FilterStateStore.APP_STATE, false, false, 'age', 34);
+ const f1 = getFilter(esFilters.FilterStateStore.APP_STATE, false, false, 'age', 34);
filterManager.setFilters([f1]);
expect(filterManager.getAppFilters()).toHaveLength(1);
expect(filterManager.getGlobalFilters()).toHaveLength(0);
@@ -96,7 +96,7 @@ describe('filter_manager', () => {
test('global state should be set', async () => {
updateSubscription = filterManager.getUpdates$().subscribe(updateListener);
- const f1 = getFilter(FilterStateStore.GLOBAL_STATE, false, false, 'age', 34);
+ const f1 = getFilter(esFilters.FilterStateStore.GLOBAL_STATE, false, false, 'age', 34);
filterManager.setFilters([f1]);
expect(filterManager.getAppFilters()).toHaveLength(0);
expect(filterManager.getGlobalFilters()).toHaveLength(1);
@@ -110,8 +110,8 @@ describe('filter_manager', () => {
test('both states should be set', async () => {
updateSubscription = filterManager.getUpdates$().subscribe(updateListener);
- const f1 = getFilter(FilterStateStore.GLOBAL_STATE, false, false, 'age', 34);
- const f2 = getFilter(FilterStateStore.APP_STATE, false, false, 'gender', 'FEMALE');
+ const f1 = getFilter(esFilters.FilterStateStore.GLOBAL_STATE, false, false, 'age', 34);
+ const f2 = getFilter(esFilters.FilterStateStore.APP_STATE, false, false, 'gender', 'FEMALE');
filterManager.setFilters([f1, f2]);
expect(filterManager.getAppFilters()).toHaveLength(1);
expect(filterManager.getGlobalFilters()).toHaveLength(1);
@@ -128,8 +128,8 @@ describe('filter_manager', () => {
test('set state should override previous state', async () => {
updateSubscription = filterManager.getUpdates$().subscribe(updateListener);
- const f1 = getFilter(FilterStateStore.GLOBAL_STATE, false, false, 'age', 34);
- const f2 = getFilter(FilterStateStore.APP_STATE, false, false, 'gender', 'FEMALE');
+ const f1 = getFilter(esFilters.FilterStateStore.GLOBAL_STATE, false, false, 'age', 34);
+ const f2 = getFilter(esFilters.FilterStateStore.APP_STATE, false, false, 'gender', 'FEMALE');
filterManager.setFilters([f1]);
filterManager.setFilters([f2]);
@@ -150,7 +150,7 @@ describe('filter_manager', () => {
test('changing a disabled filter should fire only update event', async function() {
const updateStub = jest.fn();
const fetchStub = jest.fn();
- const f1 = getFilter(FilterStateStore.GLOBAL_STATE, true, false, 'age', 34);
+ const f1 = getFilter(esFilters.FilterStateStore.GLOBAL_STATE, true, false, 'age', 34);
filterManager.setFilters([f1]);
@@ -175,7 +175,7 @@ describe('filter_manager', () => {
describe('add filters', () => {
test('app state should accept a single filter', async function() {
updateSubscription = filterManager.getUpdates$().subscribe(updateListener);
- const f1 = getFilter(FilterStateStore.APP_STATE, false, false, 'age', 34);
+ const f1 = getFilter(esFilters.FilterStateStore.APP_STATE, false, false, 'age', 34);
filterManager.addFilters(f1);
const appFilters = filterManager.getAppFilters();
expect(appFilters).toHaveLength(1);
@@ -184,20 +184,21 @@ describe('filter_manager', () => {
expect(updateListener.callCount).toBe(1);
});
- test('app state should accept array', async () => {
- const f1 = getFilter(FilterStateStore.APP_STATE, false, false, 'age', 34);
- const f2 = getFilter(FilterStateStore.APP_STATE, false, false, 'gender', 'female');
+ test('app state should accept array and preserve order', async () => {
+ const f1 = getFilter(esFilters.FilterStateStore.APP_STATE, false, false, 'age', 34);
+ const f2 = getFilter(esFilters.FilterStateStore.APP_STATE, false, false, 'gender', 'female');
+
filterManager.addFilters([f1]);
filterManager.addFilters([f2]);
const appFilters = filterManager.getAppFilters();
expect(appFilters).toHaveLength(2);
- expect(appFilters).toEqual([f2, f1]);
+ expect(appFilters).toEqual([f1, f2]);
expect(filterManager.getGlobalFilters()).toHaveLength(0);
});
test('global state should accept a single filer', async () => {
updateSubscription = filterManager.getUpdates$().subscribe(updateListener);
- const f1 = getFilter(FilterStateStore.GLOBAL_STATE, false, false, 'age', 34);
+ const f1 = getFilter(esFilters.FilterStateStore.GLOBAL_STATE, false, false, 'age', 34);
filterManager.addFilters(f1);
expect(filterManager.getAppFilters()).toHaveLength(0);
const globalFilters = filterManager.getGlobalFilters();
@@ -206,20 +207,57 @@ describe('filter_manager', () => {
expect(updateListener.callCount).toBe(1);
});
- test('global state should be accept array', async () => {
- const f1 = getFilter(FilterStateStore.GLOBAL_STATE, false, false, 'age', 34);
- const f2 = getFilter(FilterStateStore.GLOBAL_STATE, false, false, 'gender', 'female');
+ test('global state should be accept array and preserve order', async () => {
+ const f1 = getFilter(esFilters.FilterStateStore.GLOBAL_STATE, false, false, 'age', 34);
+ const f2 = getFilter(
+ esFilters.FilterStateStore.GLOBAL_STATE,
+ false,
+ false,
+ 'gender',
+ 'female'
+ );
+
filterManager.addFilters([f1, f2]);
expect(filterManager.getAppFilters()).toHaveLength(0);
const globalFilters = filterManager.getGlobalFilters();
expect(globalFilters).toHaveLength(2);
- expect(globalFilters).toEqual([f2, f1]);
+ expect(globalFilters).toEqual([f1, f2]);
+ });
+
+ test('mixed filters: global filters should stay in the beginning', async () => {
+ const f1 = getFilter(esFilters.FilterStateStore.GLOBAL_STATE, false, false, 'age', 34);
+ const f2 = getFilter(esFilters.FilterStateStore.APP_STATE, false, false, 'gender', 'female');
+ filterManager.addFilters([f1, f2]);
+ const filters = filterManager.getFilters();
+ expect(filters).toHaveLength(2);
+ expect(filters).toEqual([f1, f2]);
+ });
+
+ test('mixed filters: global filters should move to the beginning', async () => {
+ const f1 = getFilter(esFilters.FilterStateStore.APP_STATE, false, false, 'age', 34);
+ const f2 = getFilter(
+ esFilters.FilterStateStore.GLOBAL_STATE,
+ false,
+ false,
+ 'gender',
+ 'female'
+ );
+ filterManager.addFilters([f1, f2]);
+ const filters = filterManager.getFilters();
+ expect(filters).toHaveLength(2);
+ expect(filters).toEqual([f2, f1]);
});
test('add multiple filters at once', async () => {
updateSubscription = filterManager.getUpdates$().subscribe(updateListener);
- const f1 = getFilter(FilterStateStore.GLOBAL_STATE, false, false, 'age', 34);
- const f2 = getFilter(FilterStateStore.GLOBAL_STATE, false, false, 'gender', 'female');
+ const f1 = getFilter(esFilters.FilterStateStore.GLOBAL_STATE, false, false, 'age', 34);
+ const f2 = getFilter(
+ esFilters.FilterStateStore.GLOBAL_STATE,
+ false,
+ false,
+ 'gender',
+ 'female'
+ );
filterManager.addFilters([f1, f2]);
expect(filterManager.getAppFilters()).toHaveLength(0);
expect(filterManager.getGlobalFilters()).toHaveLength(2);
@@ -228,8 +266,8 @@ describe('filter_manager', () => {
test('add same filter to global and app', async () => {
updateSubscription = filterManager.getUpdates$().subscribe(updateListener);
- const f1 = getFilter(FilterStateStore.GLOBAL_STATE, false, false, 'age', 34);
- const f2 = getFilter(FilterStateStore.APP_STATE, false, false, 'age', 34);
+ const f1 = getFilter(esFilters.FilterStateStore.GLOBAL_STATE, false, false, 'age', 34);
+ const f2 = getFilter(esFilters.FilterStateStore.APP_STATE, false, false, 'age', 34);
filterManager.addFilters([f1, f2]);
// FILTER SHOULD BE ADDED ONLY ONCE, TO GLOBAL
@@ -240,8 +278,8 @@ describe('filter_manager', () => {
test('add same filter with different values to global and app', async () => {
updateSubscription = filterManager.getUpdates$().subscribe(updateListener);
- const f1 = getFilter(FilterStateStore.GLOBAL_STATE, false, false, 'age', 38);
- const f2 = getFilter(FilterStateStore.APP_STATE, false, false, 'age', 34);
+ const f1 = getFilter(esFilters.FilterStateStore.GLOBAL_STATE, false, false, 'age', 38);
+ const f2 = getFilter(esFilters.FilterStateStore.APP_STATE, false, false, 'age', 34);
filterManager.addFilters([f1, f2]);
// FILTER SHOULD BE ADDED TWICE
@@ -251,7 +289,7 @@ describe('filter_manager', () => {
});
test('add filter with no state, and force pin', async () => {
- const f1 = getFilter(FilterStateStore.GLOBAL_STATE, false, false, 'age', 38);
+ const f1 = getFilter(esFilters.FilterStateStore.GLOBAL_STATE, false, false, 'age', 38);
f1.$state = undefined;
filterManager.addFilters([f1], true);
@@ -260,12 +298,12 @@ describe('filter_manager', () => {
const f1Output = filterManager.getFilters()[0];
expect(f1Output.$state).toBeDefined();
if (f1Output.$state) {
- expect(f1Output.$state.store).toBe(FilterStateStore.GLOBAL_STATE);
+ expect(f1Output.$state.store).toBe(esFilters.FilterStateStore.GLOBAL_STATE);
}
});
test('add filter with no state, and dont force pin', async () => {
- const f1 = getFilter(FilterStateStore.GLOBAL_STATE, false, false, 'age', 38);
+ const f1 = getFilter(esFilters.FilterStateStore.GLOBAL_STATE, false, false, 'age', 38);
f1.$state = undefined;
filterManager.addFilters([f1], false);
@@ -274,7 +312,7 @@ describe('filter_manager', () => {
const f1Output = filterManager.getFilters()[0];
expect(f1Output.$state).toBeDefined();
if (f1Output.$state) {
- expect(f1Output.$state.store).toBe(FilterStateStore.APP_STATE);
+ expect(f1Output.$state.store).toBe(esFilters.FilterStateStore.APP_STATE);
}
});
@@ -286,11 +324,11 @@ describe('filter_manager', () => {
// global filters should be listed first
let res = filterManager.getFilters();
expect(res).toHaveLength(2);
- expect(res[0].$state && res[0].$state.store).toEqual(FilterStateStore.GLOBAL_STATE);
+ expect(res[0].$state && res[0].$state.store).toEqual(esFilters.FilterStateStore.GLOBAL_STATE);
expect(res[0].meta.disabled).toEqual(filters[1].meta.disabled);
expect(res[0].query).toEqual(filters[1].query);
- expect(res[1].$state && res[1].$state.store).toEqual(FilterStateStore.APP_STATE);
+ expect(res[1].$state && res[1].$state.store).toEqual(esFilters.FilterStateStore.APP_STATE);
expect(res[1].meta.disabled).toEqual(filters[0].meta.disabled);
expect(res[1].query).toEqual(filters[0].query);
@@ -310,7 +348,7 @@ describe('filter_manager', () => {
const res = filterManager.getFilters();
expect(res).toHaveLength(3);
_.each(res, function(filter) {
- expect(filter.$state && filter.$state.store).toBe(FilterStateStore.GLOBAL_STATE);
+ expect(filter.$state && filter.$state.store).toBe(esFilters.FilterStateStore.GLOBAL_STATE);
});
});
@@ -393,7 +431,7 @@ describe('filter_manager', () => {
});
test('should de-dupe global filters being set', async () => {
- const f1 = getFilter(FilterStateStore.GLOBAL_STATE, false, false, 'age', 34);
+ const f1 = getFilter(esFilters.FilterStateStore.GLOBAL_STATE, false, false, 'age', 34);
const f2 = _.cloneDeep(f1);
filterManager.setFilters([f1, f2]);
expect(filterManager.getAppFilters()).toHaveLength(0);
@@ -402,7 +440,7 @@ describe('filter_manager', () => {
});
test('should de-dupe app filters being set', async () => {
- const f1 = getFilter(FilterStateStore.APP_STATE, false, false, 'age', 34);
+ const f1 = getFilter(esFilters.FilterStateStore.APP_STATE, false, false, 'age', 34);
const f2 = _.cloneDeep(f1);
filterManager.setFilters([f1, f2]);
expect(filterManager.getAppFilters()).toHaveLength(1);
@@ -417,7 +455,7 @@ describe('filter_manager', () => {
const appFilter = _.cloneDeep(readyFilters[idx]);
appFilter.meta.negate = true;
appFilter.$state = {
- store: FilterStateStore.APP_STATE,
+ store: esFilters.FilterStateStore.APP_STATE,
};
filterManager.addFilters(appFilter);
const res = filterManager.getFilters();
@@ -434,7 +472,7 @@ describe('filter_manager', () => {
const appFilter = _.cloneDeep(readyFilters[1]);
appFilter.meta.negate = true;
appFilter.$state = {
- store: FilterStateStore.APP_STATE,
+ store: esFilters.FilterStateStore.APP_STATE,
};
filterManager.addFilters(appFilter, false);
@@ -443,7 +481,7 @@ describe('filter_manager', () => {
expect(res).toHaveLength(3);
expect(
res.filter(function(filter) {
- return filter.$state && filter.$state.store === FilterStateStore.GLOBAL_STATE;
+ return filter.$state && filter.$state.store === esFilters.FilterStateStore.GLOBAL_STATE;
}).length
).toBe(3);
});
@@ -496,8 +534,8 @@ describe('filter_manager', () => {
});
test('remove on full should clean and fire events', async () => {
- const f1 = getFilter(FilterStateStore.GLOBAL_STATE, false, false, 'age', 34);
- const f2 = getFilter(FilterStateStore.APP_STATE, false, false, 'gender', 'FEMALE');
+ const f1 = getFilter(esFilters.FilterStateStore.GLOBAL_STATE, false, false, 'age', 34);
+ const f2 = getFilter(esFilters.FilterStateStore.APP_STATE, false, false, 'gender', 'FEMALE');
filterManager.setFilters([f1, f2]);
updateSubscription = filterManager.getUpdates$().subscribe(updateListener);
@@ -507,9 +545,9 @@ describe('filter_manager', () => {
});
test('remove non existing filter should do nothing and not fire events', async () => {
- const f1 = getFilter(FilterStateStore.GLOBAL_STATE, false, false, 'age', 34);
- const f2 = getFilter(FilterStateStore.APP_STATE, false, false, 'gender', 'FEMALE');
- const f3 = getFilter(FilterStateStore.APP_STATE, false, false, 'country', 'US');
+ const f1 = getFilter(esFilters.FilterStateStore.GLOBAL_STATE, false, false, 'age', 34);
+ const f2 = getFilter(esFilters.FilterStateStore.APP_STATE, false, false, 'gender', 'FEMALE');
+ const f3 = getFilter(esFilters.FilterStateStore.APP_STATE, false, false, 'country', 'US');
filterManager.setFilters([f1, f2]);
expect(filterManager.getFilters()).toHaveLength(2);
@@ -520,9 +558,9 @@ describe('filter_manager', () => {
});
test('remove existing filter should remove and fire events', async () => {
- const f1 = getFilter(FilterStateStore.GLOBAL_STATE, false, false, 'age', 34);
- const f2 = getFilter(FilterStateStore.APP_STATE, false, false, 'gender', 'FEMALE');
- const f3 = getFilter(FilterStateStore.APP_STATE, false, false, 'country', 'US');
+ const f1 = getFilter(esFilters.FilterStateStore.GLOBAL_STATE, false, false, 'age', 34);
+ const f2 = getFilter(esFilters.FilterStateStore.APP_STATE, false, false, 'gender', 'FEMALE');
+ const f3 = getFilter(esFilters.FilterStateStore.APP_STATE, false, false, 'country', 'US');
filterManager.setFilters([f1, f2, f3]);
expect(filterManager.getFilters()).toHaveLength(3);
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 66b65a40926cb..06e2b77dca238 100644
--- a/src/plugins/data/public/query/filter_manager/filter_manager.ts
+++ b/src/plugins/data/public/query/filter_manager/filter_manager.ts
@@ -17,8 +17,6 @@
* under the License.
*/
-import { Filter, isFilterPinned, FilterStateStore } from '@kbn/es-query';
-
import _ from 'lodash';
import { Subject } from 'rxjs';
@@ -29,9 +27,10 @@ import { mapAndFlattenFilters } from './lib/map_and_flatten_filters';
import { uniqFilters } from './lib/uniq_filters';
import { onlyDisabledFiltersChanged } from './lib/only_disabled';
import { PartitionedFilters } from './types';
+import { esFilters } from '../../../common/es_query';
export class FilterManager {
- private filters: Filter[] = [];
+ private filters: esFilters.Filter[] = [];
private updated$: Subject = new Subject();
private fetch$: Subject = new Subject();
private uiSettings: UiSettingsClientContract;
@@ -40,7 +39,7 @@ export class FilterManager {
this.uiSettings = uiSettings;
}
- private mergeIncomingFilters(partitionedFilters: PartitionedFilters): Filter[] {
+ private mergeIncomingFilters(partitionedFilters: PartitionedFilters): esFilters.Filter[] {
const globalFilters = partitionedFilters.globalFilters;
const appFilters = partitionedFilters.appFilters;
@@ -61,25 +60,33 @@ export class FilterManager {
return FilterManager.mergeFilters(appFilters, globalFilters);
}
- private static mergeFilters(appFilters: Filter[], globalFilters: Filter[]): Filter[] {
+ private static mergeFilters(
+ appFilters: esFilters.Filter[],
+ globalFilters: esFilters.Filter[]
+ ): esFilters.Filter[] {
return uniqFilters(appFilters.reverse().concat(globalFilters.reverse())).reverse();
}
- private static partitionFilters(filters: Filter[]): PartitionedFilters {
- const [globalFilters, appFilters] = _.partition(filters, isFilterPinned);
+ private static partitionFilters(filters: esFilters.Filter[]): PartitionedFilters {
+ const [globalFilters, appFilters] = _.partition(filters, esFilters.isFilterPinned);
return {
globalFilters,
appFilters,
};
}
- private handleStateUpdate(newFilters: Filter[]) {
+ private handleStateUpdate(newFilters: esFilters.Filter[]) {
// global filters should always be first
- newFilters.sort(({ $state: a }: Filter, { $state: b }: Filter): number => {
- return a!.store === FilterStateStore.GLOBAL_STATE &&
- b!.store !== FilterStateStore.GLOBAL_STATE
- ? -1
- : 1;
+
+ newFilters.sort(({ $state: a }: esFilters.Filter, { $state: b }: esFilters.Filter): number => {
+ if (a!.store === b!.store) {
+ return 0;
+ } else {
+ return a!.store === esFilters.FilterStateStore.GLOBAL_STATE &&
+ b!.store !== esFilters.FilterStateStore.GLOBAL_STATE
+ ? -1
+ : 1;
+ }
});
const filtersUpdated = !_.isEqual(this.filters, newFilters);
@@ -124,7 +131,7 @@ export class FilterManager {
/* Setters */
- public addFilters(filters: Filter[] | Filter, pinFilterStatus?: boolean) {
+ public addFilters(filters: esFilters.Filter[] | esFilters.Filter, pinFilterStatus?: boolean) {
if (!Array.isArray(filters)) {
filters = [filters];
}
@@ -139,7 +146,10 @@ export class FilterManager {
// Set the store of all filters. For now.
// In the future, all filters should come in with filter state store already set.
- const store = pinFilterStatus ? FilterStateStore.GLOBAL_STATE : FilterStateStore.APP_STATE;
+ const store = pinFilterStatus
+ ? esFilters.FilterStateStore.GLOBAL_STATE
+ : esFilters.FilterStateStore.APP_STATE;
+
FilterManager.setFiltersStore(filters, store);
const mappedFilters = mapAndFlattenFilters(filters);
@@ -154,14 +164,14 @@ export class FilterManager {
this.handleStateUpdate(newFilters);
}
- public setFilters(newFilters: Filter[]) {
+ public setFilters(newFilters: esFilters.Filter[]) {
const mappedFilters = mapAndFlattenFilters(newFilters);
const newPartitionedFilters = FilterManager.partitionFilters(mappedFilters);
const mergedFilters = this.mergeIncomingFilters(newPartitionedFilters);
this.handleStateUpdate(mergedFilters);
}
- public removeFilter(filter: Filter) {
+ public removeFilter(filter: esFilters.Filter) {
const filterIndex = _.findIndex(this.filters, item => {
return _.isEqual(item.meta, filter.meta) && _.isEqual(item.query, filter.query);
});
@@ -177,8 +187,8 @@ export class FilterManager {
this.setFilters([]);
}
- public static setFiltersStore(filters: Filter[], store: FilterStateStore) {
- _.map(filters, (filter: Filter) => {
+ public static setFiltersStore(filters: esFilters.Filter[], store: esFilters.FilterStateStore) {
+ _.map(filters, (filter: esFilters.Filter) => {
// Override status only for filters that didn't have state in the first place.
if (filter.$state === undefined) {
filter.$state = { store };
diff --git a/src/plugins/data/public/query/filter_manager/lib/compare_filters.test.ts b/src/plugins/data/public/query/filter_manager/lib/compare_filters.test.ts
index e8244feb988b6..6bde6b528d07b 100644
--- a/src/plugins/data/public/query/filter_manager/lib/compare_filters.test.ts
+++ b/src/plugins/data/public/query/filter_manager/lib/compare_filters.test.ts
@@ -16,42 +16,48 @@
* specific language governing permissions and limitations
* under the License.
*/
-import { buildQueryFilter, buildEmptyFilter, FilterStateStore } from '@kbn/es-query';
+
import { compareFilters } from './compare_filters';
+import { esFilters } from '../../../../common/es_query';
describe('filter manager utilities', () => {
describe('compare filters', () => {
test('should compare filters', () => {
- const f1 = buildQueryFilter(
+ const f1 = esFilters.buildQueryFilter(
{ _type: { match: { query: 'apache', type: 'phrase' } } },
- 'index'
+ 'index',
+ ''
);
- const f2 = buildEmptyFilter(true);
+ const f2 = esFilters.buildEmptyFilter(true);
expect(compareFilters(f1, f2)).toBeFalsy();
});
test('should compare duplicates', () => {
- const f1 = buildQueryFilter(
+ const f1 = esFilters.buildQueryFilter(
{ _type: { match: { query: 'apache', type: 'phrase' } } },
- 'index'
+ 'index',
+ ''
);
- const f2 = buildQueryFilter(
+ const f2 = esFilters.buildQueryFilter(
{ _type: { match: { query: 'apache', type: 'phrase' } } },
- 'index'
+ 'index',
+ ''
);
expect(compareFilters(f1, f2)).toBeTruthy();
});
test('should compare duplicates, ignoring meta attributes', () => {
- const f1 = buildQueryFilter(
+ const f1 = esFilters.buildQueryFilter(
{ _type: { match: { query: 'apache', type: 'phrase' } } },
- 'index1'
+ 'index1',
+ ''
);
- const f2 = buildQueryFilter(
+ const f2 = esFilters.buildQueryFilter(
{ _type: { match: { query: 'apache', type: 'phrase' } } },
- 'index2'
+ 'index2',
+ ''
);
expect(compareFilters(f1, f2)).toBeTruthy();
@@ -59,12 +65,20 @@ describe('filter manager utilities', () => {
test('should compare duplicates, ignoring $state attributes', () => {
const f1 = {
- $state: { store: FilterStateStore.APP_STATE },
- ...buildQueryFilter({ _type: { match: { query: 'apache', type: 'phrase' } } }, 'index'),
+ $state: { store: esFilters.FilterStateStore.APP_STATE },
+ ...esFilters.buildQueryFilter(
+ { _type: { match: { query: 'apache', type: 'phrase' } } },
+ 'index',
+ ''
+ ),
};
const f2 = {
- $state: { store: FilterStateStore.GLOBAL_STATE },
- ...buildQueryFilter({ _type: { match: { query: 'apache', type: 'phrase' } } }, 'index'),
+ $state: { store: esFilters.FilterStateStore.GLOBAL_STATE },
+ ...esFilters.buildQueryFilter(
+ { _type: { match: { query: 'apache', type: 'phrase' } } },
+ 'index',
+ ''
+ ),
};
expect(compareFilters(f1, f2)).toBeTruthy();
diff --git a/src/plugins/data/public/query/filter_manager/lib/compare_filters.ts b/src/plugins/data/public/query/filter_manager/lib/compare_filters.ts
index 44bc333ae2b4f..2a7cbe6e3303b 100644
--- a/src/plugins/data/public/query/filter_manager/lib/compare_filters.ts
+++ b/src/plugins/data/public/query/filter_manager/lib/compare_filters.ts
@@ -17,8 +17,8 @@
* under the License.
*/
-import { Filter, FilterMeta } from '@kbn/es-query';
import { defaults, isEqual, omit } from 'lodash';
+import { esFilters } from '../../../../common/es_query';
/**
* Compare two filters to see if they match
@@ -29,10 +29,14 @@ import { defaults, isEqual, omit } from 'lodash';
*
* @returns {bool} Filters are the same
*/
-export const compareFilters = (first: Filter, second: Filter, comparatorOptions: any = {}) => {
+export const compareFilters = (
+ first: esFilters.Filter,
+ second: esFilters.Filter,
+ comparatorOptions: any = {}
+) => {
let comparators: any = {};
- const mapFilter = (filter: Filter) => {
- const cleaned: FilterMeta = omit(filter, excludedAttributes);
+ const mapFilter = (filter: esFilters.Filter) => {
+ const cleaned: esFilters.FilterMeta = omit(filter, excludedAttributes);
if (comparators.negate) cleaned.negate = filter.meta && Boolean(filter.meta.negate);
if (comparators.disabled) cleaned.disabled = filter.meta && Boolean(filter.meta.disabled);
diff --git a/src/plugins/data/public/query/filter_manager/lib/dedup_filters.test.ts b/src/plugins/data/public/query/filter_manager/lib/dedup_filters.test.ts
index 75bd9d5dfbd81..9b493add0886c 100644
--- a/src/plugins/data/public/query/filter_manager/lib/dedup_filters.test.ts
+++ b/src/plugins/data/public/query/filter_manager/lib/dedup_filters.test.ts
@@ -17,19 +17,27 @@
* under the License.
*/
-import { Filter, buildRangeFilter, FilterStateStore, buildQueryFilter } from '@kbn/es-query';
import { dedupFilters } from './dedup_filters';
+import { esFilters } from '../../../../common/es_query';
describe('filter manager utilities', () => {
describe('dedupFilters(existing, filters)', () => {
test('should return only filters which are not in the existing', () => {
- const existing: Filter[] = [
- buildRangeFilter({ name: 'bytes' }, { from: 0, to: 1024 }, 'index'),
- buildQueryFilter({ match: { _term: { query: 'apache', type: 'phrase' } } }, 'index'),
+ const existing: esFilters.Filter[] = [
+ esFilters.buildRangeFilter({ name: 'bytes' }, { from: 0, to: 1024 }, 'index', ''),
+ esFilters.buildQueryFilter(
+ { match: { _term: { query: 'apache', type: 'phrase' } } },
+ 'index',
+ ''
+ ),
];
- const filters: Filter[] = [
- buildRangeFilter({ name: 'bytes' }, { from: 1024, to: 2048 }, 'index'),
- buildQueryFilter({ match: { _term: { query: 'apache', type: 'phrase' } } }, 'index'),
+ const filters: esFilters.Filter[] = [
+ esFilters.buildRangeFilter({ name: 'bytes' }, { from: 1024, to: 2048 }, 'index', ''),
+ esFilters.buildQueryFilter(
+ { match: { _term: { query: 'apache', type: 'phrase' } } },
+ 'index',
+ ''
+ ),
];
const results = dedupFilters(existing, filters);
@@ -38,16 +46,24 @@ describe('filter manager utilities', () => {
});
test('should ignore the disabled attribute when comparing ', () => {
- const existing: Filter[] = [
- buildRangeFilter({ name: 'bytes' }, { from: 0, to: 1024 }, 'index'),
+ const existing: esFilters.Filter[] = [
+ esFilters.buildRangeFilter({ name: 'bytes' }, { from: 0, to: 1024 }, 'index', ''),
{
- ...buildQueryFilter({ match: { _term: { query: 'apache', type: 'phrase' } } }, 'index'),
+ ...esFilters.buildQueryFilter(
+ { match: { _term: { query: 'apache', type: 'phrase' } } },
+ 'index1',
+ ''
+ ),
meta: { disabled: true, negate: false, alias: null },
},
];
- const filters: Filter[] = [
- buildRangeFilter({ name: 'bytes' }, { from: 1024, to: 2048 }, 'index'),
- buildQueryFilter({ match: { _term: { query: 'apache', type: 'phrase' } } }, 'index'),
+ const filters: esFilters.Filter[] = [
+ esFilters.buildRangeFilter({ name: 'bytes' }, { from: 1024, to: 2048 }, 'index', ''),
+ esFilters.buildQueryFilter(
+ { match: { _term: { query: 'apache', type: 'phrase' } } },
+ 'index1',
+ ''
+ ),
];
const results = dedupFilters(existing, filters);
@@ -56,18 +72,26 @@ describe('filter manager utilities', () => {
});
test('should ignore $state attribute', () => {
- const existing: Filter[] = [
- buildRangeFilter({ name: 'bytes' }, { from: 0, to: 1024 }, 'index'),
+ const existing: esFilters.Filter[] = [
+ esFilters.buildRangeFilter({ name: 'bytes' }, { from: 0, to: 1024 }, 'index', ''),
{
- ...buildQueryFilter({ match: { _term: { query: 'apache', type: 'phrase' } } }, 'index'),
- $state: { store: FilterStateStore.APP_STATE },
+ ...esFilters.buildQueryFilter(
+ { match: { _term: { query: 'apache', type: 'phrase' } } },
+ 'index',
+ ''
+ ),
+ $state: { store: esFilters.FilterStateStore.APP_STATE },
},
];
- const filters: Filter[] = [
- buildRangeFilter({ name: 'bytes' }, { from: 1024, to: 2048 }, 'index'),
+ const filters: esFilters.Filter[] = [
+ esFilters.buildRangeFilter({ name: 'bytes' }, { from: 1024, to: 2048 }, 'index', ''),
{
- ...buildQueryFilter({ match: { _term: { query: 'apache', type: 'phrase' } } }, 'index'),
- $state: { store: FilterStateStore.GLOBAL_STATE },
+ ...esFilters.buildQueryFilter(
+ { match: { _term: { query: 'apache', type: 'phrase' } } },
+ 'index',
+ ''
+ ),
+ $state: { store: esFilters.FilterStateStore.GLOBAL_STATE },
},
];
const results = dedupFilters(existing, filters);
diff --git a/src/plugins/data/public/query/filter_manager/lib/dedup_filters.ts b/src/plugins/data/public/query/filter_manager/lib/dedup_filters.ts
index 9565cbd80b779..6d6f49cb5e833 100644
--- a/src/plugins/data/public/query/filter_manager/lib/dedup_filters.ts
+++ b/src/plugins/data/public/query/filter_manager/lib/dedup_filters.ts
@@ -17,9 +17,9 @@
* under the License.
*/
-import { Filter } from '@kbn/es-query';
import { filter, find } from 'lodash';
import { compareFilters } from './compare_filters';
+import { esFilters } from '../../../../../../plugins/data/public';
/**
* Combine 2 filter collections, removing duplicates
@@ -31,8 +31,8 @@ import { compareFilters } from './compare_filters';
* @returns {object} An array of filters that were not in existing
*/
export const dedupFilters = (
- existingFilters: Filter[],
- filters: Filter[],
+ existingFilters: esFilters.Filter[],
+ filters: esFilters.Filter[],
comparatorOptions: any = {}
) => {
if (!Array.isArray(filters)) {
@@ -41,8 +41,8 @@ export const dedupFilters = (
return filter(
filters,
- (f: Filter) =>
- !find(existingFilters, (existingFilter: Filter) =>
+ (f: esFilters.Filter) =>
+ !find(existingFilters, (existingFilter: esFilters.Filter) =>
compareFilters(existingFilter, f, comparatorOptions)
)
);
diff --git a/src/plugins/data/public/query/filter_manager/lib/generate_mapping_chain.test.ts b/src/plugins/data/public/query/filter_manager/lib/generate_mapping_chain.test.ts
index c0c509634aba2..dfe3a093c6614 100644
--- a/src/plugins/data/public/query/filter_manager/lib/generate_mapping_chain.test.ts
+++ b/src/plugins/data/public/query/filter_manager/lib/generate_mapping_chain.test.ts
@@ -18,8 +18,8 @@
*/
import sinon from 'sinon';
-import { Filter, buildEmptyFilter } from '@kbn/es-query';
import { generateMappingChain } from './generate_mapping_chain';
+import { esFilters } from '../../../../../../plugins/data/public';
describe('filter manager utilities', () => {
let mapping: any;
@@ -32,7 +32,7 @@ describe('filter manager utilities', () => {
describe('generateMappingChain()', () => {
test('should create a chaining function which calls the next function if the error is thrown', async () => {
- const filter: Filter = buildEmptyFilter(true);
+ const filter = esFilters.buildEmptyFilter(true);
mapping.throws(filter);
next.returns('good');
@@ -45,7 +45,7 @@ describe('filter manager utilities', () => {
});
test('should create a chaining function which DOES NOT call the next function if the result is returned', async () => {
- const filter: Filter = buildEmptyFilter(true);
+ const filter = esFilters.buildEmptyFilter(true);
mapping.returns('good');
next.returns('bad');
@@ -57,7 +57,7 @@ describe('filter manager utilities', () => {
});
test('should resolve result for the mapping function', async () => {
- const filter: Filter = buildEmptyFilter(true);
+ const filter = esFilters.buildEmptyFilter(true);
mapping.returns({ key: 'test', value: 'example' });
@@ -70,7 +70,7 @@ describe('filter manager utilities', () => {
test('should call the mapping function with the argument to the chain', async () => {
// @ts-ignore
- const filter: Filter = { test: 'example' };
+ const filter: esFilters.Filter = { test: 'example' };
mapping.returns({ key: 'test', value: 'example' });
@@ -84,7 +84,7 @@ describe('filter manager utilities', () => {
});
test('should resolve result for the next function', async () => {
- const filter: Filter = buildEmptyFilter(true);
+ const filter = esFilters.buildEmptyFilter(true);
mapping.throws(filter);
next.returns({ key: 'test', value: 'example' });
@@ -98,7 +98,7 @@ describe('filter manager utilities', () => {
});
test('should throw an error if no functions match', async done => {
- const filter: Filter = buildEmptyFilter(true);
+ const filter = esFilters.buildEmptyFilter(true);
mapping.throws(filter);
diff --git a/src/plugins/data/public/query/filter_manager/lib/generate_mapping_chain.ts b/src/plugins/data/public/query/filter_manager/lib/generate_mapping_chain.ts
index 760270edd7170..b6764389e0db9 100644
--- a/src/plugins/data/public/query/filter_manager/lib/generate_mapping_chain.ts
+++ b/src/plugins/data/public/query/filter_manager/lib/generate_mapping_chain.ts
@@ -16,14 +16,14 @@
* specific language governing permissions and limitations
* under the License.
*/
-import { Filter } from '@kbn/es-query';
+import { esFilters } from '../../../../../../plugins/data/public';
const noop = () => {
throw new Error('No mappings have been found for filter.');
};
export const generateMappingChain = (fn: Function, next: Function = noop) => {
- return (filter: Filter) => {
+ return (filter: esFilters.Filter) => {
try {
return fn(filter);
} catch (result) {
diff --git a/src/plugins/data/public/query/filter_manager/lib/map_and_flatten_filters.test.ts b/src/plugins/data/public/query/filter_manager/lib/map_and_flatten_filters.test.ts
index fce2aa0373ebe..9a0d0d93698f6 100644
--- a/src/plugins/data/public/query/filter_manager/lib/map_and_flatten_filters.test.ts
+++ b/src/plugins/data/public/query/filter_manager/lib/map_and_flatten_filters.test.ts
@@ -17,14 +17,14 @@
* under the License.
*/
-import { Filter } from '@kbn/es-query';
import { mapAndFlattenFilters } from './map_and_flatten_filters';
+import { esFilters } from '../../../../../data/public';
describe('filter manager utilities', () => {
describe('mapAndFlattenFilters()', () => {
let filters: unknown;
- function getDisplayName(filter: Filter) {
+ function getDisplayName(filter: esFilters.Filter) {
return typeof filter.meta.value === 'function' ? filter.meta.value() : filter.meta.value;
}
@@ -45,7 +45,7 @@ describe('filter manager utilities', () => {
});
test('should map and flatten the filters', () => {
- const results = mapAndFlattenFilters(filters as Filter[]);
+ const results = mapAndFlattenFilters(filters as esFilters.Filter[]);
expect(results).toHaveLength(5);
expect(results[0]).toHaveProperty('meta');
diff --git a/src/plugins/data/public/query/filter_manager/lib/map_and_flatten_filters.ts b/src/plugins/data/public/query/filter_manager/lib/map_and_flatten_filters.ts
index b350c3957b142..5326d59f3e32b 100644
--- a/src/plugins/data/public/query/filter_manager/lib/map_and_flatten_filters.ts
+++ b/src/plugins/data/public/query/filter_manager/lib/map_and_flatten_filters.ts
@@ -18,9 +18,9 @@
*/
import { compact, flatten } from 'lodash';
-import { Filter } from '@kbn/es-query';
import { mapFilter } from './map_filter';
+import { esFilters } from '../../../../../data/public';
-export const mapAndFlattenFilters = (filters: Filter[]) => {
- return compact(flatten(filters)).map((item: Filter) => mapFilter(item));
+export const mapAndFlattenFilters = (filters: esFilters.Filter[]) => {
+ return compact(flatten(filters)).map((item: esFilters.Filter) => mapFilter(item));
};
diff --git a/src/plugins/data/public/query/filter_manager/lib/map_filter.test.ts b/src/plugins/data/public/query/filter_manager/lib/map_filter.test.ts
index c1d4ebfd3f7fc..0d115125451ee 100644
--- a/src/plugins/data/public/query/filter_manager/lib/map_filter.test.ts
+++ b/src/plugins/data/public/query/filter_manager/lib/map_filter.test.ts
@@ -17,11 +17,11 @@
* under the License.
*/
-import { Filter } from '@kbn/es-query';
import { mapFilter } from './map_filter';
+import { esFilters } from '../../../../../data/public';
describe('filter manager utilities', () => {
- function getDisplayName(filter: Filter) {
+ function getDisplayName(filter: esFilters.Filter) {
return typeof filter.meta.value === 'function' ? filter.meta.value() : filter.meta.value;
}
@@ -31,7 +31,7 @@ describe('filter manager utilities', () => {
meta: { index: 'logstash-*' },
query: { match: { _type: { query: 'apache', type: 'phrase' } } },
};
- const after = mapFilter(before as Filter);
+ const after = mapFilter(before as esFilters.Filter);
expect(after).toHaveProperty('meta');
expect(after.meta).toHaveProperty('key', '_type');
@@ -43,7 +43,7 @@ describe('filter manager utilities', () => {
test('should map exists filters', async () => {
const before: any = { meta: { index: 'logstash-*' }, exists: { field: '@timestamp' } };
- const after = mapFilter(before as Filter);
+ const after = mapFilter(before as esFilters.Filter);
expect(after).toHaveProperty('meta');
expect(after.meta).toHaveProperty('key', '@timestamp');
@@ -55,7 +55,7 @@ describe('filter manager utilities', () => {
test('should map missing filters', async () => {
const before: any = { meta: { index: 'logstash-*' }, missing: { field: '@timestamp' } };
- const after = mapFilter(before as Filter);
+ const after = mapFilter(before as esFilters.Filter);
expect(after).toHaveProperty('meta');
expect(after.meta).toHaveProperty('key', '@timestamp');
@@ -67,7 +67,7 @@ describe('filter manager utilities', () => {
test('should map json filter', async () => {
const before: any = { meta: { index: 'logstash-*' }, query: { match_all: {} } };
- const after = mapFilter(before as Filter);
+ const after = mapFilter(before as esFilters.Filter);
expect(after).toHaveProperty('meta');
expect(after.meta).toHaveProperty('key', 'query');
@@ -81,7 +81,7 @@ describe('filter manager utilities', () => {
const before: any = { meta: { index: 'logstash-*' } };
try {
- mapFilter(before as Filter);
+ mapFilter(before as esFilters.Filter);
} catch (e) {
expect(e).toBeInstanceOf(Error);
expect(e.message).toBe('No mappings have been found for filter.');
diff --git a/src/plugins/data/public/query/filter_manager/lib/map_filter.ts b/src/plugins/data/public/query/filter_manager/lib/map_filter.ts
index cda9591e40b33..2dc855caabfd3 100644
--- a/src/plugins/data/public/query/filter_manager/lib/map_filter.ts
+++ b/src/plugins/data/public/query/filter_manager/lib/map_filter.ts
@@ -17,7 +17,6 @@
* under the License.
*/
-import { Filter } from '@kbn/es-query';
import { reduceRight } from 'lodash';
import { mapMatchAll } from './mappers/map_match_all';
@@ -31,8 +30,9 @@ import { mapGeoBoundingBox } from './mappers/map_geo_bounding_box';
import { mapGeoPolygon } from './mappers/map_geo_polygon';
import { mapDefault } from './mappers/map_default';
import { generateMappingChain } from './generate_mapping_chain';
+import { esFilters } from '../../../../../data/public';
-export function mapFilter(filter: Filter) {
+export function mapFilter(filter: esFilters.Filter) {
/** Mappers **/
// Each mapper is a simple promise function that test if the mapper can
diff --git a/src/plugins/data/public/query/filter_manager/lib/mappers/map_default.test.ts b/src/plugins/data/public/query/filter_manager/lib/mappers/map_default.test.ts
index acb6e89711033..f10766901e5b7 100644
--- a/src/plugins/data/public/query/filter_manager/lib/mappers/map_default.test.ts
+++ b/src/plugins/data/public/query/filter_manager/lib/mappers/map_default.test.ts
@@ -16,13 +16,14 @@
* specific language governing permissions and limitations
* under the License.
*/
-import { CustomFilter, buildEmptyFilter, buildQueryFilter } from '@kbn/es-query';
+
import { mapDefault } from './map_default';
+import { esFilters } from '../../../../../common/es_query';
describe('filter manager utilities', () => {
describe('mapDefault()', () => {
test('should return the key and value for matching filters', async () => {
- const filter: CustomFilter = buildQueryFilter({ match_all: {} }, 'index');
+ const filter = esFilters.buildQueryFilter({ match_all: {} }, 'index', '');
const result = mapDefault(filter);
expect(result).toHaveProperty('key', 'query');
@@ -30,7 +31,7 @@ describe('filter manager utilities', () => {
});
test('should return undefined if there is no valid key', async () => {
- const filter = buildEmptyFilter(true) as CustomFilter;
+ const filter = esFilters.buildEmptyFilter(true);
try {
mapDefault(filter);
diff --git a/src/plugins/data/public/query/filter_manager/lib/mappers/map_default.ts b/src/plugins/data/public/query/filter_manager/lib/mappers/map_default.ts
index 70c191879c22e..fd84c5c742589 100644
--- a/src/plugins/data/public/query/filter_manager/lib/mappers/map_default.ts
+++ b/src/plugins/data/public/query/filter_manager/lib/mappers/map_default.ts
@@ -17,15 +17,15 @@
* under the License.
*/
-import { Filter, FILTERS } from '@kbn/es-query';
import { find, keys, get } from 'lodash';
+import { esFilters } from '../../../../../common/es_query';
-export const mapDefault = (filter: Filter) => {
+export const mapDefault = (filter: esFilters.Filter) => {
const metaProperty = /(^\$|meta)/;
const key = find(keys(filter), item => !item.match(metaProperty));
if (key) {
- const type = FILTERS.CUSTOM;
+ const type = esFilters.FILTERS.CUSTOM;
const value = JSON.stringify(get(filter, key, {}));
return { type, key, value };
diff --git a/src/plugins/data/public/query/filter_manager/lib/mappers/map_exists.test.ts b/src/plugins/data/public/query/filter_manager/lib/mappers/map_exists.test.ts
index c352d3e2b9a73..ff0ed4f4e4d94 100644
--- a/src/plugins/data/public/query/filter_manager/lib/mappers/map_exists.test.ts
+++ b/src/plugins/data/public/query/filter_manager/lib/mappers/map_exists.test.ts
@@ -16,14 +16,15 @@
* specific language governing permissions and limitations
* under the License.
*/
-import { ExistsFilter, buildEmptyFilter, buildExistsFilter } from '@kbn/es-query';
+
import { mapExists } from './map_exists';
import { mapQueryString } from './map_query_string';
+import { esFilters } from '../../../../../common/es_query';
describe('filter manager utilities', () => {
describe('mapExists()', () => {
test('should return the key and value for matching filters', async () => {
- const filter: ExistsFilter = buildExistsFilter({ name: '_type' }, 'index');
+ const filter = esFilters.buildExistsFilter({ name: '_type' }, 'index');
const result = mapExists(filter);
expect(result).toHaveProperty('key', '_type');
@@ -31,7 +32,7 @@ describe('filter manager utilities', () => {
});
test('should return undefined for none matching', async done => {
- const filter = buildEmptyFilter(true) as ExistsFilter;
+ const filter = esFilters.buildEmptyFilter(true);
try {
mapQueryString(filter);
diff --git a/src/plugins/data/public/query/filter_manager/lib/mappers/map_exists.ts b/src/plugins/data/public/query/filter_manager/lib/mappers/map_exists.ts
index d539219a1ca24..63665bdd88ccb 100644
--- a/src/plugins/data/public/query/filter_manager/lib/mappers/map_exists.ts
+++ b/src/plugins/data/public/query/filter_manager/lib/mappers/map_exists.ts
@@ -17,14 +17,14 @@
* under the License.
*/
-import { Filter, isExistsFilter, FILTERS } from '@kbn/es-query';
import { get } from 'lodash';
+import { esFilters } from '../../../../../common/es_query';
-export const mapExists = (filter: Filter) => {
- if (isExistsFilter(filter)) {
+export const mapExists = (filter: esFilters.Filter) => {
+ if (esFilters.isExistsFilter(filter)) {
return {
- type: FILTERS.EXISTS,
- value: FILTERS.EXISTS,
+ type: esFilters.FILTERS.EXISTS,
+ value: esFilters.FILTERS.EXISTS,
key: get(filter, 'exists.field'),
};
}
diff --git a/src/plugins/data/public/query/filter_manager/lib/mappers/map_geo_bounding_box.test.ts b/src/plugins/data/public/query/filter_manager/lib/mappers/map_geo_bounding_box.test.ts
index c3c99e6f6c4a3..5fca4a652bad8 100644
--- a/src/plugins/data/public/query/filter_manager/lib/mappers/map_geo_bounding_box.test.ts
+++ b/src/plugins/data/public/query/filter_manager/lib/mappers/map_geo_bounding_box.test.ts
@@ -18,7 +18,7 @@
*/
import { mapGeoBoundingBox } from './map_geo_bounding_box';
-import { Filter, GeoBoundingBoxFilter } from '@kbn/es-query';
+import { esFilters } from '../../../../../common/es_query';
describe('filter manager utilities', () => {
describe('mapGeoBoundingBox()', () => {
@@ -34,7 +34,7 @@ describe('filter manager utilities', () => {
bottom_right: { lat: 15, lon: 20 },
},
},
- } as GeoBoundingBoxFilter;
+ } as esFilters.GeoBoundingBoxFilter;
const result = mapGeoBoundingBox(filter);
@@ -63,7 +63,8 @@ describe('filter manager utilities', () => {
bottom_right: { lat: 15, lon: 20 },
},
},
- } as GeoBoundingBoxFilter;
+ } as esFilters.GeoBoundingBoxFilter;
+
const result = mapGeoBoundingBox(filter);
expect(result).toHaveProperty('key', 'point');
@@ -82,7 +83,7 @@ describe('filter manager utilities', () => {
const filter = {
meta: { index: 'logstash-*' },
query: { query_string: { query: 'foo:bar' } },
- } as Filter;
+ } as esFilters.Filter;
try {
mapGeoBoundingBox(filter);
diff --git a/src/plugins/data/public/query/filter_manager/lib/mappers/map_geo_bounding_box.ts b/src/plugins/data/public/query/filter_manager/lib/mappers/map_geo_bounding_box.ts
index 1f9b8cd842509..091e9a3f34000 100644
--- a/src/plugins/data/public/query/filter_manager/lib/mappers/map_geo_bounding_box.ts
+++ b/src/plugins/data/public/query/filter_manager/lib/mappers/map_geo_bounding_box.ts
@@ -16,16 +16,10 @@
* specific language governing permissions and limitations
* under the License.
*/
-import {
- GeoBoundingBoxFilter,
- Filter,
- FILTERS,
- isGeoBoundingBoxFilter,
- FilterValueFormatter,
-} from '@kbn/es-query';
+import { esFilters } from '../../../../../common/es_query';
const getFormattedValueFn = (params: any) => {
- return (formatter?: FilterValueFormatter) => {
+ return (formatter?: esFilters.FilterValueFormatter) => {
const corners = formatter
? {
topLeft: formatter.convert(params.top_left),
@@ -40,20 +34,20 @@ const getFormattedValueFn = (params: any) => {
};
};
-const getParams = (filter: GeoBoundingBoxFilter) => {
+const getParams = (filter: esFilters.GeoBoundingBoxFilter) => {
const key = Object.keys(filter.geo_bounding_box).filter(k => k !== 'ignore_unmapped')[0];
const params = filter.geo_bounding_box[key];
return {
key,
params,
- type: FILTERS.GEO_BOUNDING_BOX,
+ type: esFilters.FILTERS.GEO_BOUNDING_BOX,
value: getFormattedValueFn(params),
};
};
-export const mapGeoBoundingBox = (filter: Filter) => {
- if (!isGeoBoundingBoxFilter(filter)) {
+export const mapGeoBoundingBox = (filter: esFilters.Filter) => {
+ if (!esFilters.isGeoBoundingBoxFilter(filter)) {
throw filter;
}
diff --git a/src/plugins/data/public/query/filter_manager/lib/mappers/map_geo_polygon.test.ts b/src/plugins/data/public/query/filter_manager/lib/mappers/map_geo_polygon.test.ts
index ee4f9b295d682..1847296016c73 100644
--- a/src/plugins/data/public/query/filter_manager/lib/mappers/map_geo_polygon.test.ts
+++ b/src/plugins/data/public/query/filter_manager/lib/mappers/map_geo_polygon.test.ts
@@ -16,23 +16,31 @@
* specific language governing permissions and limitations
* under the License.
*/
+
import { mapGeoPolygon } from './map_geo_polygon';
-import { GeoPolygonFilter, Filter } from '@kbn/es-query';
+import { esFilters } from '../../../../../common/es_query';
describe('filter manager utilities', () => {
- describe('mapGeoPolygon()', () => {
- test('should return the key and value for matching filters with bounds', async () => {
- const filter = {
- meta: {
- index: 'logstash-*',
- },
- geo_polygon: {
- point: {
- points: [{ lat: 5, lon: 10 }, { lat: 15, lon: 20 }],
- },
+ let filter: esFilters.GeoPolygonFilter;
+
+ beforeEach(() => {
+ filter = {
+ meta: {
+ index: 'logstash-*',
+ },
+ geo_polygon: {
+ point: {
+ points: [
+ { lat: 5, lon: 10 },
+ { lat: 15, lon: 20 },
+ ],
},
- } as GeoPolygonFilter;
+ },
+ } as esFilters.GeoPolygonFilter;
+ });
+ describe('mapGeoPolygon()', () => {
+ test('should return the key and value for matching filters with bounds', async () => {
const result = mapGeoPolygon(filter);
expect(result).toHaveProperty('key', 'point');
@@ -48,17 +56,6 @@ describe('filter manager utilities', () => {
});
test('should return the key and value even when using ignore_unmapped', async () => {
- const filter = {
- meta: {
- index: 'logstash-*',
- },
- geo_polygon: {
- ignore_unmapped: true,
- point: {
- points: [{ lat: 5, lon: 10 }, { lat: 15, lon: 20 }],
- },
- },
- } as GeoPolygonFilter;
const result = mapGeoPolygon(filter);
expect(result).toHaveProperty('key', 'point');
@@ -74,15 +71,15 @@ describe('filter manager utilities', () => {
});
test('should return undefined for none matching', async done => {
- const filter = {
+ const wrongFilter = {
meta: { index: 'logstash-*' },
query: { query_string: { query: 'foo:bar' } },
- } as Filter;
+ } as esFilters.Filter;
try {
- mapGeoPolygon(filter);
+ mapGeoPolygon(wrongFilter);
} catch (e) {
- expect(e).toBe(filter);
+ expect(e).toBe(wrongFilter);
done();
}
diff --git a/src/plugins/data/public/query/filter_manager/lib/mappers/map_geo_polygon.ts b/src/plugins/data/public/query/filter_manager/lib/mappers/map_geo_polygon.ts
index 03ce4130d0c97..a7881b4a145a1 100644
--- a/src/plugins/data/public/query/filter_manager/lib/mappers/map_geo_polygon.ts
+++ b/src/plugins/data/public/query/filter_manager/lib/mappers/map_geo_polygon.ts
@@ -16,38 +16,33 @@
* specific language governing permissions and limitations
* under the License.
*/
-import {
- GeoPolygonFilter,
- Filter,
- FILTERS,
- isGeoPolygonFilter,
- FilterValueFormatter,
-} from '@kbn/es-query';
+
+import { esFilters } from '../../../../../common/es_query';
const POINTS_SEPARATOR = ', ';
const getFormattedValueFn = (points: string[]) => {
- return (formatter?: FilterValueFormatter) => {
+ return (formatter?: esFilters.FilterValueFormatter) => {
return points
.map((point: string) => (formatter ? formatter.convert(point) : JSON.stringify(point)))
.join(POINTS_SEPARATOR);
};
};
-function getParams(filter: GeoPolygonFilter) {
+function getParams(filter: esFilters.GeoPolygonFilter) {
const key = Object.keys(filter.geo_polygon).filter(k => k !== 'ignore_unmapped')[0];
const params = filter.geo_polygon[key];
return {
key,
params,
- type: FILTERS.GEO_POLYGON,
+ type: esFilters.FILTERS.GEO_POLYGON,
value: getFormattedValueFn(params.points || []),
};
}
-export function mapGeoPolygon(filter: Filter) {
- if (!isGeoPolygonFilter(filter)) {
+export function mapGeoPolygon(filter: esFilters.Filter) {
+ if (!esFilters.isGeoPolygonFilter(filter)) {
throw filter;
}
return getParams(filter);
diff --git a/src/plugins/data/public/query/filter_manager/lib/mappers/map_match_all.test.ts b/src/plugins/data/public/query/filter_manager/lib/mappers/map_match_all.test.ts
index 2f0641598a2ce..4fc6d0b492414 100644
--- a/src/plugins/data/public/query/filter_manager/lib/mappers/map_match_all.test.ts
+++ b/src/plugins/data/public/query/filter_manager/lib/mappers/map_match_all.test.ts
@@ -16,12 +16,13 @@
* specific language governing permissions and limitations
* under the License.
*/
-import { MatchAllFilter } from '@kbn/es-query';
+
import { mapMatchAll } from './map_match_all';
+import { esFilters } from '../../../../../common/es_query';
describe('filter_manager/lib', () => {
describe('mapMatchAll()', () => {
- let filter: MatchAllFilter;
+ let filter: esFilters.MatchAllFilter;
beforeEach(() => {
filter = {
diff --git a/src/plugins/data/public/query/filter_manager/lib/mappers/map_match_all.ts b/src/plugins/data/public/query/filter_manager/lib/mappers/map_match_all.ts
index a1387e6dbe457..4e93b1d41e9a8 100644
--- a/src/plugins/data/public/query/filter_manager/lib/mappers/map_match_all.ts
+++ b/src/plugins/data/public/query/filter_manager/lib/mappers/map_match_all.ts
@@ -16,12 +16,12 @@
* specific language governing permissions and limitations
* under the License.
*/
-import { Filter, FILTERS, isMatchAllFilter } from '@kbn/es-query';
+import { esFilters } from '../../../../../common/es_query';
-export const mapMatchAll = (filter: Filter) => {
- if (isMatchAllFilter(filter)) {
+export const mapMatchAll = (filter: esFilters.Filter) => {
+ if (esFilters.isMatchAllFilter(filter)) {
return {
- type: FILTERS.MATCH_ALL,
+ type: esFilters.FILTERS.MATCH_ALL,
key: filter.meta.field,
value: filter.meta.formattedValue || 'all',
};
diff --git a/src/plugins/data/public/query/filter_manager/lib/mappers/map_missing.test.ts b/src/plugins/data/public/query/filter_manager/lib/mappers/map_missing.test.ts
index ca23f25826906..1847eb37ca42f 100644
--- a/src/plugins/data/public/query/filter_manager/lib/mappers/map_missing.test.ts
+++ b/src/plugins/data/public/query/filter_manager/lib/mappers/map_missing.test.ts
@@ -16,15 +16,16 @@
* specific language governing permissions and limitations
* under the License.
*/
-import { MissingFilter, buildEmptyFilter, ExistsFilter } from '@kbn/es-query';
+
import { mapMissing } from './map_missing';
+import { esFilters } from '../../../../../common/es_query';
describe('filter manager utilities', () => {
describe('mapMissing()', () => {
test('should return the key and value for matching filters', async () => {
- const filter: MissingFilter = {
+ const filter: esFilters.MissingFilter = {
missing: { field: '_type' },
- ...buildEmptyFilter(true),
+ ...esFilters.buildEmptyFilter(true),
};
const result = mapMissing(filter);
@@ -33,7 +34,7 @@ describe('filter manager utilities', () => {
});
test('should return undefined for none matching', async done => {
- const filter = buildEmptyFilter(true) as ExistsFilter;
+ const filter = esFilters.buildEmptyFilter(true);
try {
mapMissing(filter);
diff --git a/src/plugins/data/public/query/filter_manager/lib/mappers/map_missing.ts b/src/plugins/data/public/query/filter_manager/lib/mappers/map_missing.ts
index 861a84ed61646..51dee89ad884b 100644
--- a/src/plugins/data/public/query/filter_manager/lib/mappers/map_missing.ts
+++ b/src/plugins/data/public/query/filter_manager/lib/mappers/map_missing.ts
@@ -16,13 +16,14 @@
* specific language governing permissions and limitations
* under the License.
*/
-import { Filter, FILTERS, isMissingFilter } from '@kbn/es-query';
-export const mapMissing = (filter: Filter) => {
- if (isMissingFilter(filter)) {
+import { esFilters } from '../../../../../common/es_query';
+
+export const mapMissing = (filter: esFilters.Filter) => {
+ if (esFilters.isMissingFilter(filter)) {
return {
- type: FILTERS.MISSING,
- value: FILTERS.MISSING,
+ type: esFilters.FILTERS.MISSING,
+ value: esFilters.FILTERS.MISSING,
key: filter.missing.field,
};
}
diff --git a/src/plugins/data/public/query/filter_manager/lib/mappers/map_phrase.test.ts b/src/plugins/data/public/query/filter_manager/lib/mappers/map_phrase.test.ts
index c95a2529add14..05372d37264b0 100644
--- a/src/plugins/data/public/query/filter_manager/lib/mappers/map_phrase.test.ts
+++ b/src/plugins/data/public/query/filter_manager/lib/mappers/map_phrase.test.ts
@@ -17,7 +17,7 @@
* under the License.
*/
import { mapPhrase } from './map_phrase';
-import { PhraseFilter, Filter } from '@kbn/es-query';
+import { esFilters } from '../../../../../common/es_query';
describe('filter manager utilities', () => {
describe('mapPhrase()', () => {
@@ -25,11 +25,13 @@ describe('filter manager utilities', () => {
const filter = {
meta: { index: 'logstash-*' },
query: { match: { _type: { query: 'apache', type: 'phrase' } } },
- } as PhraseFilter;
+ } as esFilters.PhraseFilter;
+
const result = mapPhrase(filter);
expect(result).toHaveProperty('value');
expect(result).toHaveProperty('key', '_type');
+
if (result.value) {
const displayName = result.value();
expect(displayName).toBe('apache');
@@ -40,7 +42,7 @@ describe('filter manager utilities', () => {
const filter = {
meta: { index: 'logstash-*' },
query: { query_string: { query: 'foo:bar' } },
- } as Filter;
+ } as esFilters.Filter;
try {
mapPhrase(filter);
diff --git a/src/plugins/data/public/query/filter_manager/lib/mappers/map_phrase.ts b/src/plugins/data/public/query/filter_manager/lib/mappers/map_phrase.ts
index efa348c9ad320..b6e9c2007db97 100644
--- a/src/plugins/data/public/query/filter_manager/lib/mappers/map_phrase.ts
+++ b/src/plugins/data/public/query/filter_manager/lib/mappers/map_phrase.ts
@@ -18,45 +18,36 @@
*/
import { get } from 'lodash';
-import {
- PhraseFilter,
- Filter,
- FILTERS,
- isPhraseFilter,
- isScriptedPhraseFilter,
- getPhraseFilterField,
- getPhraseFilterValue,
- FilterValueFormatter,
-} from '@kbn/es-query';
+import { esFilters } from '../../../../../common/es_query';
-const getScriptedPhraseValue = (filter: PhraseFilter) =>
+const getScriptedPhraseValue = (filter: esFilters.PhraseFilter) =>
get(filter, ['script', 'script', 'params', 'value']);
const getFormattedValueFn = (value: any) => {
- return (formatter?: FilterValueFormatter) => {
+ return (formatter?: esFilters.FilterValueFormatter) => {
return formatter ? formatter.convert(value) : value;
};
};
-const getParams = (filter: PhraseFilter) => {
+const getParams = (filter: esFilters.PhraseFilter) => {
const scriptedPhraseValue = getScriptedPhraseValue(filter);
const isScriptedFilter = Boolean(scriptedPhraseValue);
- const key = isScriptedFilter ? filter.meta.field || '' : getPhraseFilterField(filter);
- const query = scriptedPhraseValue || getPhraseFilterValue(filter);
+ const key = isScriptedFilter ? filter.meta.field || '' : esFilters.getPhraseFilterField(filter);
+ const query = scriptedPhraseValue || esFilters.getPhraseFilterValue(filter);
const params = { query };
return {
key,
params,
- type: FILTERS.PHRASE,
+ type: esFilters.FILTERS.PHRASE,
value: getFormattedValueFn(query),
};
};
-export const isMapPhraseFilter = (filter: any): filter is PhraseFilter =>
- isPhraseFilter(filter) || isScriptedPhraseFilter(filter);
+export const isMapPhraseFilter = (filter: any): filter is esFilters.PhraseFilter =>
+ esFilters.isPhraseFilter(filter) || esFilters.isScriptedPhraseFilter(filter);
-export const mapPhrase = (filter: Filter) => {
+export const mapPhrase = (filter: esFilters.Filter) => {
if (!isMapPhraseFilter(filter)) {
throw filter;
}
diff --git a/src/plugins/data/public/query/filter_manager/lib/mappers/map_phrases.ts b/src/plugins/data/public/query/filter_manager/lib/mappers/map_phrases.ts
index c17ff11d49fd4..7240d87d02b5a 100644
--- a/src/plugins/data/public/query/filter_manager/lib/mappers/map_phrases.ts
+++ b/src/plugins/data/public/query/filter_manager/lib/mappers/map_phrases.ts
@@ -17,10 +17,10 @@
* under the License.
*/
-import { Filter, isPhrasesFilter } from '@kbn/es-query';
+import { esFilters } from '../../../../../common/es_query';
-export const mapPhrases = (filter: Filter) => {
- if (!isPhrasesFilter(filter)) {
+export const mapPhrases = (filter: esFilters.Filter) => {
+ if (!esFilters.isPhrasesFilter(filter)) {
throw filter;
}
diff --git a/src/plugins/data/public/query/filter_manager/lib/mappers/map_query_string.test.ts b/src/plugins/data/public/query/filter_manager/lib/mappers/map_query_string.test.ts
index 4b1a5d39c405d..c60e7d3454fe0 100644
--- a/src/plugins/data/public/query/filter_manager/lib/mappers/map_query_string.test.ts
+++ b/src/plugins/data/public/query/filter_manager/lib/mappers/map_query_string.test.ts
@@ -17,27 +17,28 @@
* under the License.
*/
-import { QueryStringFilter, buildQueryFilter, buildEmptyFilter } from '@kbn/es-query';
import { mapQueryString } from './map_query_string';
+import { esFilters } from '../../../../../common/es_query';
describe('filter manager utilities', () => {
describe('mapQueryString()', () => {
test('should return the key and value for matching filters', async () => {
- const filter: QueryStringFilter = buildQueryFilter(
+ const filter = esFilters.buildQueryFilter(
{ query_string: { query: 'foo:bar' } },
- 'index'
+ 'index',
+ ''
);
- const result = mapQueryString(filter);
+ const result = mapQueryString(filter as esFilters.Filter);
expect(result).toHaveProperty('key', 'query');
expect(result).toHaveProperty('value', 'foo:bar');
});
test('should return undefined for none matching', async done => {
- const filter = buildEmptyFilter(true) as QueryStringFilter;
+ const filter = esFilters.buildEmptyFilter(true);
try {
- mapQueryString(filter);
+ mapQueryString(filter as esFilters.Filter);
} catch (e) {
expect(e).toBe(filter);
done();
diff --git a/src/plugins/data/public/query/filter_manager/lib/mappers/map_query_string.ts b/src/plugins/data/public/query/filter_manager/lib/mappers/map_query_string.ts
index 94da8074edd04..20c3555639a3e 100644
--- a/src/plugins/data/public/query/filter_manager/lib/mappers/map_query_string.ts
+++ b/src/plugins/data/public/query/filter_manager/lib/mappers/map_query_string.ts
@@ -16,12 +16,12 @@
* specific language governing permissions and limitations
* under the License.
*/
-import { Filter, FILTERS, isQueryStringFilter } from '@kbn/es-query';
+import { esFilters } from '../../../../../common/es_query';
-export const mapQueryString = (filter: Filter) => {
- if (isQueryStringFilter(filter)) {
+export const mapQueryString = (filter: esFilters.Filter) => {
+ if (esFilters.isQueryStringFilter(filter)) {
return {
- type: FILTERS.QUERY_STRING,
+ type: esFilters.FILTERS.QUERY_STRING,
key: 'query',
value: filter.query.query_string.query,
};
diff --git a/src/plugins/data/public/query/filter_manager/lib/mappers/map_range.test.ts b/src/plugins/data/public/query/filter_manager/lib/mappers/map_range.test.ts
index 12d2919e2d47b..c0d5773d6f2c1 100644
--- a/src/plugins/data/public/query/filter_manager/lib/mappers/map_range.test.ts
+++ b/src/plugins/data/public/query/filter_manager/lib/mappers/map_range.test.ts
@@ -18,30 +18,15 @@
*/
import { mapRange } from './map_range';
-import { RangeFilter, Filter, FilterMeta } from '@kbn/es-query';
+import { esFilters } from '../../../../../common/es_query';
describe('filter manager utilities', () => {
describe('mapRange()', () => {
test('should return the key and value for matching filters with gt/lt', async () => {
const filter = {
- meta: { index: 'logstash-*' } as FilterMeta,
+ meta: { index: 'logstash-*' } as esFilters.FilterMeta,
range: { bytes: { lt: 2048, gt: 1024 } },
- } as RangeFilter;
- const result = mapRange(filter);
-
- expect(result).toHaveProperty('key', 'bytes');
- expect(result).toHaveProperty('value');
- if (result.value) {
- const displayName = result.value();
- expect(displayName).toBe('1024 to 2048');
- }
- });
-
- test('should return the key and value for matching filters with gte/lte', async () => {
- const filter = {
- meta: { index: 'logstash-*' } as FilterMeta,
- range: { bytes: { lte: 2048, gte: 1024 } },
- } as RangeFilter;
+ } as esFilters.RangeFilter;
const result = mapRange(filter);
expect(result).toHaveProperty('key', 'bytes');
@@ -56,7 +41,7 @@ describe('filter manager utilities', () => {
const filter = {
meta: { index: 'logstash-*' },
query: { query_string: { query: 'foo:bar' } },
- } as Filter;
+ } as esFilters.Filter;
try {
mapRange(filter);
diff --git a/src/plugins/data/public/query/filter_manager/lib/mappers/map_range.ts b/src/plugins/data/public/query/filter_manager/lib/mappers/map_range.ts
index 76f9d3621e171..51fb970f5f03e 100644
--- a/src/plugins/data/public/query/filter_manager/lib/mappers/map_range.ts
+++ b/src/plugins/data/public/query/filter_manager/lib/mappers/map_range.ts
@@ -17,18 +17,11 @@
* under the License.
*/
-import {
- Filter,
- RangeFilter,
- FILTERS,
- isRangeFilter,
- isScriptedRangeFilter,
- FilterValueFormatter,
-} from '@kbn/es-query';
import { get, has } from 'lodash';
+import { esFilters } from '../../../../../common/es_query';
const getFormattedValueFn = (left: any, right: any) => {
- return (formatter?: FilterValueFormatter) => {
+ return (formatter?: esFilters.FilterValueFormatter) => {
let displayValue = `${left} to ${right}`;
if (formatter) {
const convert = formatter.getConverterFor('text');
@@ -38,11 +31,12 @@ const getFormattedValueFn = (left: any, right: any) => {
};
};
-const getFirstRangeKey = (filter: RangeFilter) => filter.range && Object.keys(filter.range)[0];
-const getRangeByKey = (filter: RangeFilter, key: string) => get(filter, ['range', key]);
+const getFirstRangeKey = (filter: esFilters.RangeFilter) =>
+ filter.range && Object.keys(filter.range)[0];
+const getRangeByKey = (filter: esFilters.RangeFilter, key: string) => get(filter, ['range', key]);
-function getParams(filter: RangeFilter) {
- const isScriptedRange = isScriptedRangeFilter(filter);
+function getParams(filter: esFilters.RangeFilter) {
+ const isScriptedRange = esFilters.isScriptedRangeFilter(filter);
const key: string = (isScriptedRange ? filter.meta.field : getFirstRangeKey(filter)) || '';
const params: any = isScriptedRange
? get(filter, 'script.script.params')
@@ -56,13 +50,13 @@ function getParams(filter: RangeFilter) {
const value = getFormattedValueFn(left, right);
- return { type: FILTERS.RANGE, key, value, params };
+ return { type: esFilters.FILTERS.RANGE, key, value, params };
}
-export const isMapRangeFilter = (filter: any): filter is RangeFilter =>
- isRangeFilter(filter) || isScriptedRangeFilter(filter);
+export const isMapRangeFilter = (filter: any): filter is esFilters.RangeFilter =>
+ esFilters.isRangeFilter(filter) || esFilters.isScriptedRangeFilter(filter);
-export const mapRange = (filter: Filter) => {
+export const mapRange = (filter: esFilters.Filter) => {
if (!isMapRangeFilter(filter)) {
throw filter;
}
diff --git a/src/plugins/data/public/query/filter_manager/lib/only_disabled.test.ts b/src/plugins/data/public/query/filter_manager/lib/only_disabled.test.ts
index 3fedcf97a625a..b9731797c9ee3 100644
--- a/src/plugins/data/public/query/filter_manager/lib/only_disabled.test.ts
+++ b/src/plugins/data/public/query/filter_manager/lib/only_disabled.test.ts
@@ -17,8 +17,8 @@
* under the License.
*/
-import { Filter } from '@kbn/es-query';
import { onlyDisabledFiltersChanged } from './only_disabled';
+import { esFilters } from '../../../../../data/public';
describe('filter manager utilities', () => {
describe('onlyDisabledFiltersChanged()', () => {
@@ -27,20 +27,20 @@ describe('filter manager utilities', () => {
{ meta: { disabled: true } },
{ meta: { disabled: true } },
{ meta: { disabled: true } },
- ] as Filter[];
- const newFilters = [{ meta: { disabled: true } }] as Filter[];
+ ] as esFilters.Filter[];
+ const newFilters = [{ meta: { disabled: true } }] as esFilters.Filter[];
expect(onlyDisabledFiltersChanged(newFilters, filters)).toBe(true);
});
test('should return false if there are no old filters', () => {
- const newFilters = [{ meta: { disabled: false } }] as Filter[];
+ const newFilters = [{ meta: { disabled: false } }] as esFilters.Filter[];
expect(onlyDisabledFiltersChanged(newFilters, undefined)).toBe(false);
});
test('should return false if there are no new filters', () => {
- const filters = [{ meta: { disabled: false } }] as Filter[];
+ const filters = [{ meta: { disabled: false } }] as esFilters.Filter[];
expect(onlyDisabledFiltersChanged(undefined, filters)).toBe(false);
});
@@ -50,8 +50,8 @@ describe('filter manager utilities', () => {
{ meta: { disabled: false } },
{ meta: { disabled: false } },
{ meta: { disabled: false } },
- ] as Filter[];
- const newFilters = [{ meta: { disabled: false } }] as Filter[];
+ ] as esFilters.Filter[];
+ const newFilters = [{ meta: { disabled: false } }] as esFilters.Filter[];
expect(onlyDisabledFiltersChanged(newFilters, filters)).toBe(false);
});
@@ -61,8 +61,8 @@ describe('filter manager utilities', () => {
{ meta: { disabled: true } },
{ meta: { disabled: true } },
{ meta: { disabled: true } },
- ] as Filter[];
- const newFilters = [{ meta: { disabled: false } }] as Filter[];
+ ] as esFilters.Filter[];
+ const newFilters = [{ meta: { disabled: false } }] as esFilters.Filter[];
expect(onlyDisabledFiltersChanged(newFilters, filters)).toBe(false);
});
@@ -72,8 +72,8 @@ describe('filter manager utilities', () => {
{ meta: { disabled: false } },
{ meta: { disabled: false } },
{ meta: { disabled: false } },
- ] as Filter[];
- const newFilters = [{ meta: { disabled: true } }] as Filter[];
+ ] as esFilters.Filter[];
+ const newFilters = [{ meta: { disabled: true } }] as esFilters.Filter[];
expect(onlyDisabledFiltersChanged(newFilters, filters)).toBe(false);
});
@@ -83,8 +83,8 @@ describe('filter manager utilities', () => {
{ meta: { disabled: true } },
{ meta: { disabled: true } },
{ meta: { disabled: true } },
- ] as Filter[];
- const newFilters = [] as Filter[];
+ ] as esFilters.Filter[];
+ const newFilters = [] as esFilters.Filter[];
expect(onlyDisabledFiltersChanged(newFilters, filters)).toBe(true);
});
@@ -94,8 +94,8 @@ describe('filter manager utilities', () => {
{ meta: { disabled: false } },
{ meta: { disabled: false } },
{ meta: { disabled: false } },
- ] as Filter[];
- const newFilters = [] as Filter[];
+ ] as esFilters.Filter[];
+ const newFilters = [] as esFilters.Filter[];
expect(onlyDisabledFiltersChanged(newFilters, filters)).toBe(false);
});
@@ -104,11 +104,11 @@ describe('filter manager utilities', () => {
const filters = [
{ meta: { disabled: true, negate: false } },
{ meta: { disabled: true, negate: false } },
- ] as Filter[];
+ ] as esFilters.Filter[];
const newFilters = [
{ meta: { disabled: true, negate: true } },
{ meta: { disabled: true, negate: true } },
- ] as Filter[];
+ ] as esFilters.Filter[];
expect(onlyDisabledFiltersChanged(newFilters, filters)).toBe(true);
});
@@ -118,8 +118,8 @@ describe('filter manager utilities', () => {
{ meta: { disabled: false } },
{ meta: { disabled: false } },
{ meta: { disabled: true } },
- ] as Filter[];
- const newFilters = [{ meta: { disabled: false } }] as Filter[];
+ ] as esFilters.Filter[];
+ const newFilters = [{ meta: { disabled: false } }] as esFilters.Filter[];
expect(onlyDisabledFiltersChanged(newFilters, filters)).toBe(false);
});
@@ -129,15 +129,15 @@ describe('filter manager utilities', () => {
{ meta: { disabled: true } },
{ meta: { disabled: false } },
{ meta: { disabled: true } },
- ] as Filter[];
- const newFilters = [] as Filter[];
+ ] as esFilters.Filter[];
+ const newFilters = [] as esFilters.Filter[];
expect(onlyDisabledFiltersChanged(newFilters, filters)).toBe(false);
});
test('should not throw with null filters', () => {
- const filters = [null, { meta: { disabled: true } }] as Filter[];
- const newFilters = [] as Filter[];
+ const filters = [null, { meta: { disabled: true } }] as esFilters.Filter[];
+ const newFilters = [] as esFilters.Filter[];
expect(() => {
onlyDisabledFiltersChanged(newFilters, filters);
diff --git a/src/plugins/data/public/query/filter_manager/lib/only_disabled.ts b/src/plugins/data/public/query/filter_manager/lib/only_disabled.ts
index 9c0b5f43acb3e..0fb6894a297a1 100644
--- a/src/plugins/data/public/query/filter_manager/lib/only_disabled.ts
+++ b/src/plugins/data/public/query/filter_manager/lib/only_disabled.ts
@@ -17,17 +17,20 @@
* under the License.
*/
-import { Filter } from '@kbn/es-query';
import { filter, isEqual } from 'lodash';
+import { esFilters } from '../../../../../../plugins/data/public';
-const isEnabled = (f: Filter) => f && f.meta && !f.meta.disabled;
+const isEnabled = (f: esFilters.Filter) => f && f.meta && !f.meta.disabled;
/**
* Checks to see if only disabled filters have been changed
*
* @returns {bool} Only disabled filters
*/
-export const onlyDisabledFiltersChanged = (newFilters?: Filter[], oldFilters?: Filter[]) => {
+export const onlyDisabledFiltersChanged = (
+ newFilters?: esFilters.Filter[],
+ oldFilters?: esFilters.Filter[]
+) => {
// If it's the same - compare only enabled filters
const newEnabledFilters = filter(newFilters || [], isEnabled);
const oldEnabledFilters = filter(oldFilters || [], isEnabled);
diff --git a/src/plugins/data/public/query/filter_manager/lib/uniq_filters.test.ts b/src/plugins/data/public/query/filter_manager/lib/uniq_filters.test.ts
index 86f059913cd96..08eeabc1497e3 100644
--- a/src/plugins/data/public/query/filter_manager/lib/uniq_filters.test.ts
+++ b/src/plugins/data/public/query/filter_manager/lib/uniq_filters.test.ts
@@ -16,15 +16,24 @@
* specific language governing permissions and limitations
* under the License.
*/
-import { Filter, buildQueryFilter, FilterStateStore } from '@kbn/es-query';
+
import { uniqFilters } from './uniq_filters';
+import { esFilters } from '../../../../../data/public';
describe('filter manager utilities', () => {
describe('niqFilter', () => {
test('should filter out dups', () => {
- const before: Filter[] = [
- buildQueryFilter({ _type: { match: { query: 'apache', type: 'phrase' } } }, 'index'),
- buildQueryFilter({ _type: { match: { query: 'apache', type: 'phrase' } } }, 'index'),
+ const before: esFilters.Filter[] = [
+ esFilters.buildQueryFilter(
+ { _type: { match: { query: 'apache', type: 'phrase' } } },
+ 'index',
+ ''
+ ),
+ esFilters.buildQueryFilter(
+ { _type: { match: { query: 'apache', type: 'phrase' } } },
+ 'index',
+ ''
+ ),
];
const results = uniqFilters(before);
@@ -32,9 +41,17 @@ describe('filter manager utilities', () => {
});
test('should filter out duplicates, ignoring meta attributes', () => {
- const before: Filter[] = [
- buildQueryFilter({ _type: { match: { query: 'apache', type: 'phrase' } } }, 'index1'),
- buildQueryFilter({ _type: { match: { query: 'apache', type: 'phrase' } } }, 'index2'),
+ const before: esFilters.Filter[] = [
+ esFilters.buildQueryFilter(
+ { _type: { match: { query: 'apache', type: 'phrase' } } },
+ 'index1',
+ ''
+ ),
+ esFilters.buildQueryFilter(
+ { _type: { match: { query: 'apache', type: 'phrase' } } },
+ 'index2',
+ ''
+ ),
];
const results = uniqFilters(before);
@@ -42,14 +59,22 @@ describe('filter manager utilities', () => {
});
test('should filter out duplicates, ignoring $state attributes', () => {
- const before: Filter[] = [
+ const before: esFilters.Filter[] = [
{
- $state: { store: FilterStateStore.APP_STATE },
- ...buildQueryFilter({ _type: { match: { query: 'apache', type: 'phrase' } } }, 'index'),
+ $state: { store: esFilters.FilterStateStore.APP_STATE },
+ ...esFilters.buildQueryFilter(
+ { _type: { match: { query: 'apache', type: 'phrase' } } },
+ 'index',
+ ''
+ ),
},
{
- $state: { store: FilterStateStore.GLOBAL_STATE },
- ...buildQueryFilter({ _type: { match: { query: 'apache', type: 'phrase' } } }, 'index'),
+ $state: { store: esFilters.FilterStateStore.GLOBAL_STATE },
+ ...esFilters.buildQueryFilter(
+ { _type: { match: { query: 'apache', type: 'phrase' } } },
+ 'index',
+ ''
+ ),
},
];
const results = uniqFilters(before);
diff --git a/src/plugins/data/public/query/filter_manager/lib/uniq_filters.ts b/src/plugins/data/public/query/filter_manager/lib/uniq_filters.ts
index 12e793253371e..e96c52e6db3de 100644
--- a/src/plugins/data/public/query/filter_manager/lib/uniq_filters.ts
+++ b/src/plugins/data/public/query/filter_manager/lib/uniq_filters.ts
@@ -16,9 +16,9 @@
* specific language governing permissions and limitations
* under the License.
*/
-import { Filter } from '@kbn/es-query';
import { each, union } from 'lodash';
import { dedupFilters } from './dedup_filters';
+import { esFilters } from '../../../../../data/public';
/**
* Remove duplicate filters from an array of filters
@@ -28,10 +28,10 @@ import { dedupFilters } from './dedup_filters';
* @returns {object} The original filters array with duplicates removed
*/
-export const uniqFilters = (filters: Filter[], comparatorOptions: any = {}) => {
- let results: Filter[] = [];
+export const uniqFilters = (filters: esFilters.Filter[], comparatorOptions: any = {}) => {
+ let results: esFilters.Filter[] = [];
- each(filters, (filter: Filter) => {
+ each(filters, (filter: esFilters.Filter) => {
results = union(results, dedupFilters(results, [filter]), comparatorOptions);
});
diff --git a/src/plugins/data/public/query/filter_manager/test_helpers/get_filters_array.ts b/src/plugins/data/public/query/filter_manager/test_helpers/get_filters_array.ts
index 27f627b477c35..aa047647c5751 100644
--- a/src/plugins/data/public/query/filter_manager/test_helpers/get_filters_array.ts
+++ b/src/plugins/data/public/query/filter_manager/test_helpers/get_filters_array.ts
@@ -17,9 +17,9 @@
* under the License.
*/
-import { Filter } from '@kbn/es-query';
+import { esFilters } from '../../../../../../plugins/data/public';
-export function getFiltersArray(): Filter[] {
+export function getFiltersArray(): esFilters.Filter[] {
return [
{
query: { match: { extension: { query: 'jpg', type: 'phrase' } } },
diff --git a/src/plugins/data/public/query/filter_manager/test_helpers/get_stub_filter.ts b/src/plugins/data/public/query/filter_manager/test_helpers/get_stub_filter.ts
index 20d9e236f49be..adc72c961b08b 100644
--- a/src/plugins/data/public/query/filter_manager/test_helpers/get_stub_filter.ts
+++ b/src/plugins/data/public/query/filter_manager/test_helpers/get_stub_filter.ts
@@ -17,15 +17,15 @@
* under the License.
*/
-import { Filter, FilterStateStore } from '@kbn/es-query';
+import { esFilters } from '../../../../../../plugins/data/public';
export function getFilter(
- store: FilterStateStore,
+ store: esFilters.FilterStateStore,
disabled: boolean,
negated: boolean,
queryKey: string,
queryValue: any
-): Filter {
+): esFilters.Filter {
return {
$state: {
store,
diff --git a/src/plugins/data/public/query/filter_manager/types.ts b/src/plugins/data/public/query/filter_manager/types.ts
index e74b48b722cc4..0b3dbca2d6e0a 100644
--- a/src/plugins/data/public/query/filter_manager/types.ts
+++ b/src/plugins/data/public/query/filter_manager/types.ts
@@ -17,9 +17,9 @@
* under the License.
*/
-import { Filter } from '@kbn/es-query';
+import { esFilters } from '../../../../../plugins/data/public';
export interface PartitionedFilters {
- globalFilters: Filter[];
- appFilters: Filter[];
+ globalFilters: esFilters.Filter[];
+ appFilters: esFilters.Filter[];
}
diff --git a/src/plugins/data/public/query/index.tsx b/src/plugins/data/public/query/index.tsx
index 44b371b6adf19..9d7c2ffc56f70 100644
--- a/src/plugins/data/public/query/index.tsx
+++ b/src/plugins/data/public/query/index.tsx
@@ -18,5 +18,8 @@
*/
export * from './query_service';
-
export * from './filter_manager';
+
+export * from './timefilter';
+
+export * from './persisted_log';
diff --git a/src/plugins/data/public/query/mocks.ts b/src/plugins/data/public/query/mocks.ts
index e5030c5765316..f2832b6b67fa2 100644
--- a/src/plugins/data/public/query/mocks.ts
+++ b/src/plugins/data/public/query/mocks.ts
@@ -17,21 +17,24 @@
* under the License.
*/
-import { QueryService, QueryStart, QuerySetup } from '.';
+import { QueryService, QuerySetup } from '.';
+import { timefilterServiceMock } from './timefilter/timefilter_service.mock';
type QueryServiceClientContract = PublicMethodsOf;
const createSetupContractMock = () => {
const setupContract: jest.Mocked = {
filterManager: jest.fn() as any,
+ timefilter: timefilterServiceMock.createSetupContract(),
};
return setupContract;
};
const createStartContractMock = () => {
- const startContract: jest.Mocked = {
+ const startContract = {
filterManager: jest.fn() as any,
+ timefilter: timefilterServiceMock.createStartContract(),
};
return startContract;
diff --git a/src/legacy/core_plugins/data/public/query/persisted_log/index.ts b/src/plugins/data/public/query/persisted_log/index.ts
similarity index 100%
rename from src/legacy/core_plugins/data/public/query/persisted_log/index.ts
rename to src/plugins/data/public/query/persisted_log/index.ts
diff --git a/src/legacy/core_plugins/data/public/query/persisted_log/persisted_log.test.ts b/src/plugins/data/public/query/persisted_log/persisted_log.test.ts
similarity index 97%
rename from src/legacy/core_plugins/data/public/query/persisted_log/persisted_log.test.ts
rename to src/plugins/data/public/query/persisted_log/persisted_log.test.ts
index e0bc8f2c3525f..87c1ec29c1aee 100644
--- a/src/legacy/core_plugins/data/public/query/persisted_log/persisted_log.test.ts
+++ b/src/plugins/data/public/query/persisted_log/persisted_log.test.ts
@@ -36,12 +36,6 @@ const createMockStorage = () => ({
clear: jest.fn(),
});
-jest.mock('ui/chrome', () => {
- return {
- getBasePath: () => `/some/base/path`,
- };
-});
-
const historyName = 'testHistory';
const historyLimit = 10;
const payload = [
diff --git a/src/legacy/core_plugins/data/public/query/persisted_log/persisted_log.ts b/src/plugins/data/public/query/persisted_log/persisted_log.ts
similarity index 100%
rename from src/legacy/core_plugins/data/public/query/persisted_log/persisted_log.ts
rename to src/plugins/data/public/query/persisted_log/persisted_log.ts
diff --git a/src/plugins/data/public/query/query_service.ts b/src/plugins/data/public/query/query_service.ts
index d34909a5e03b7..206f8ac284ec3 100644
--- a/src/plugins/data/public/query/query_service.ts
+++ b/src/plugins/data/public/query/query_service.ts
@@ -18,7 +18,9 @@
*/
import { UiSettingsClientContract } from 'src/core/public';
+import { IStorageWrapper } from 'src/plugins/kibana_utils/public';
import { FilterManager } from './filter_manager';
+import { TimefilterService, TimefilterSetup } from './timefilter';
/**
* Query Service
@@ -26,23 +28,33 @@ import { FilterManager } from './filter_manager';
*/
export interface QueryServiceDependencies {
+ storage: IStorageWrapper;
uiSettings: UiSettingsClientContract;
}
export class QueryService {
filterManager!: FilterManager;
+ timefilter!: TimefilterSetup;
- public setup({ uiSettings }: QueryServiceDependencies) {
+ public setup({ uiSettings, storage }: QueryServiceDependencies) {
this.filterManager = new FilterManager(uiSettings);
+ const timefilterService = new TimefilterService();
+ this.timefilter = timefilterService.setup({
+ uiSettings,
+ storage,
+ });
+
return {
filterManager: this.filterManager,
+ timefilter: this.timefilter,
};
}
public start() {
return {
filterManager: this.filterManager,
+ timefilter: this.timefilter,
};
}
diff --git a/src/legacy/core_plugins/data/public/timefilter/get_time.test.ts b/src/plugins/data/public/query/timefilter/get_time.test.ts
similarity index 100%
rename from src/legacy/core_plugins/data/public/timefilter/get_time.test.ts
rename to src/plugins/data/public/query/timefilter/get_time.test.ts
diff --git a/src/legacy/core_plugins/data/public/timefilter/get_time.ts b/src/plugins/data/public/query/timefilter/get_time.ts
similarity index 94%
rename from src/legacy/core_plugins/data/public/timefilter/get_time.ts
rename to src/plugins/data/public/query/timefilter/get_time.ts
index 18a43d789714d..55ee6527fbb1a 100644
--- a/src/legacy/core_plugins/data/public/timefilter/get_time.ts
+++ b/src/plugins/data/public/query/timefilter/get_time.ts
@@ -19,7 +19,9 @@
import dateMath from '@elastic/datemath';
import { TimeRange } from 'src/plugins/data/public';
-import { IndexPattern, Field } from '../index_patterns';
+
+// TODO: remove this
+import { IndexPattern, Field } from '../../../../../legacy/core_plugins/data/public/index_patterns';
interface CalculateBoundsOptions {
forceNow?: Date;
diff --git a/src/legacy/core_plugins/data/public/timefilter/index.ts b/src/plugins/data/public/query/timefilter/index.ts
similarity index 100%
rename from src/legacy/core_plugins/data/public/timefilter/index.ts
rename to src/plugins/data/public/query/timefilter/index.ts
diff --git a/src/legacy/core_plugins/data/public/timefilter/lib/change_time_filter.test.ts b/src/plugins/data/public/query/timefilter/lib/change_time_filter.test.ts
similarity index 91%
rename from src/legacy/core_plugins/data/public/timefilter/lib/change_time_filter.test.ts
rename to src/plugins/data/public/query/timefilter/lib/change_time_filter.test.ts
index 5e16120f3b3c2..df3e33060b01f 100644
--- a/src/legacy/core_plugins/data/public/timefilter/lib/change_time_filter.test.ts
+++ b/src/plugins/data/public/query/timefilter/lib/change_time_filter.test.ts
@@ -16,10 +16,10 @@
* specific language governing permissions and limitations
* under the License.
*/
-import { RangeFilter } from '@kbn/es-query';
import { changeTimeFilter } from './change_time_filter';
import { TimeRange } from 'src/plugins/data/public';
import { timefilterServiceMock } from '../timefilter_service.mock';
+import { esFilters } from '../../../../../../plugins/data/public';
const timefilterMock = timefilterServiceMock.createSetupContract();
const timefilter = timefilterMock.timefilter;
@@ -42,7 +42,7 @@ describe('changeTimeFilter()', () => {
test('should change the timefilter to match the range gt/lt', () => {
const filter: any = { range: { '@timestamp': { gt, lt } } };
- changeTimeFilter(timefilter, filter as RangeFilter);
+ changeTimeFilter(timefilter, filter as esFilters.RangeFilter);
const { to, from } = timefilter.getTime();
@@ -52,7 +52,7 @@ describe('changeTimeFilter()', () => {
test('should change the timefilter to match the range gte/lte', () => {
const filter: any = { range: { '@timestamp': { gte: gt, lte: lt } } };
- changeTimeFilter(timefilter, filter as RangeFilter);
+ changeTimeFilter(timefilter, filter as esFilters.RangeFilter);
const { to, from } = timefilter.getTime();
diff --git a/src/legacy/core_plugins/data/public/timefilter/lib/change_time_filter.ts b/src/plugins/data/public/query/timefilter/lib/change_time_filter.ts
similarity index 87%
rename from src/legacy/core_plugins/data/public/timefilter/lib/change_time_filter.ts
rename to src/plugins/data/public/query/timefilter/lib/change_time_filter.ts
index 4780ddb6b4b44..7943aab3c151f 100644
--- a/src/legacy/core_plugins/data/public/timefilter/lib/change_time_filter.ts
+++ b/src/plugins/data/public/query/timefilter/lib/change_time_filter.ts
@@ -19,10 +19,10 @@
import moment from 'moment';
import { keys } from 'lodash';
-import { RangeFilter } from '@kbn/es-query';
import { TimefilterContract } from '../timefilter';
+import { esFilters } from '../../../../../../plugins/data/public';
-export function convertRangeFilterToTimeRange(filter: RangeFilter) {
+export function convertRangeFilterToTimeRange(filter: esFilters.RangeFilter) {
const key = keys(filter.range)[0];
const values = filter.range[key];
@@ -32,6 +32,6 @@ export function convertRangeFilterToTimeRange(filter: RangeFilter) {
};
}
-export function changeTimeFilter(timeFilter: TimefilterContract, filter: RangeFilter) {
+export function changeTimeFilter(timeFilter: TimefilterContract, filter: esFilters.RangeFilter) {
timeFilter.setTime(convertRangeFilterToTimeRange(filter));
}
diff --git a/src/legacy/core_plugins/data/public/timefilter/lib/diff_time_picker_vals.test.ts b/src/plugins/data/public/query/timefilter/lib/diff_time_picker_vals.test.ts
similarity index 100%
rename from src/legacy/core_plugins/data/public/timefilter/lib/diff_time_picker_vals.test.ts
rename to src/plugins/data/public/query/timefilter/lib/diff_time_picker_vals.test.ts
diff --git a/src/legacy/core_plugins/data/public/timefilter/lib/diff_time_picker_vals.ts b/src/plugins/data/public/query/timefilter/lib/diff_time_picker_vals.ts
similarity index 100%
rename from src/legacy/core_plugins/data/public/timefilter/lib/diff_time_picker_vals.ts
rename to src/plugins/data/public/query/timefilter/lib/diff_time_picker_vals.ts
diff --git a/src/legacy/core_plugins/data/public/timefilter/lib/extract_time_filter.test.ts b/src/plugins/data/public/query/timefilter/lib/extract_time_filter.test.ts
similarity index 63%
rename from src/legacy/core_plugins/data/public/timefilter/lib/extract_time_filter.test.ts
rename to src/plugins/data/public/query/timefilter/lib/extract_time_filter.test.ts
index d55c9babeed79..981c50844c4f3 100644
--- a/src/legacy/core_plugins/data/public/timefilter/lib/extract_time_filter.test.ts
+++ b/src/plugins/data/public/query/timefilter/lib/extract_time_filter.test.ts
@@ -17,15 +17,23 @@
* under the License.
*/
-import { Filter, buildRangeFilter, buildQueryFilter, buildPhraseFilter } from '@kbn/es-query';
import { extractTimeFilter } from './extract_time_filter';
+import { esFilters } from '../../../../../../plugins/data/public';
describe('filter manager utilities', () => {
describe('extractTimeFilter()', () => {
test('should detect timeFilter', async () => {
- const filters: Filter[] = [
- buildQueryFilter({ _type: { match: { query: 'apache', type: 'phrase' } } }, 'logstash-*'),
- buildRangeFilter({ name: 'time' }, { gt: 1388559600000, lt: 1388646000000 }, 'logstash-*'),
+ const filters: esFilters.Filter[] = [
+ esFilters.buildQueryFilter(
+ { _type: { match: { query: 'apache', type: 'phrase' } } },
+ 'logstash-*',
+ ''
+ ),
+ esFilters.buildRangeFilter(
+ { name: 'time' },
+ { gt: 1388559600000, lt: 1388646000000 },
+ 'logstash-*'
+ ),
];
const result = await extractTimeFilter('time', filters);
@@ -34,9 +42,13 @@ describe('filter manager utilities', () => {
});
test("should not return timeFilter when name doesn't match", async () => {
- const filters: Filter[] = [
- buildQueryFilter({ _type: { match: { query: 'apache', type: 'phrase' } } }, 'logstash-*'),
- buildRangeFilter({ name: '@timestamp' }, { from: 1, to: 2 }, 'logstash-*'),
+ const filters: esFilters.Filter[] = [
+ esFilters.buildQueryFilter(
+ { _type: { match: { query: 'apache', type: 'phrase' } } },
+ 'logstash-*',
+ ''
+ ),
+ esFilters.buildRangeFilter({ name: '@timestamp' }, { from: 1, to: 2 }, 'logstash-*', ''),
];
const result = await extractTimeFilter('time', filters);
@@ -45,9 +57,13 @@ describe('filter manager utilities', () => {
});
test('should not return a non range filter, even when names match', async () => {
- const filters: Filter[] = [
- buildQueryFilter({ _type: { match: { query: 'apache', type: 'phrase' } } }, 'logstash-*'),
- buildPhraseFilter({ name: 'time' }, 'banana', 'logstash-*'),
+ const filters: esFilters.Filter[] = [
+ esFilters.buildQueryFilter(
+ { _type: { match: { query: 'apache', type: 'phrase' } } },
+ 'logstash-*',
+ ''
+ ),
+ esFilters.buildPhraseFilter({ name: 'time' }, 'banana', 'logstash-*'),
];
const result = await extractTimeFilter('time', filters);
diff --git a/src/legacy/core_plugins/data/public/timefilter/lib/extract_time_filter.ts b/src/plugins/data/public/query/timefilter/lib/extract_time_filter.ts
similarity index 82%
rename from src/legacy/core_plugins/data/public/timefilter/lib/extract_time_filter.ts
rename to src/plugins/data/public/query/timefilter/lib/extract_time_filter.ts
index 22bda5b21295e..4281610cb63e4 100644
--- a/src/legacy/core_plugins/data/public/timefilter/lib/extract_time_filter.ts
+++ b/src/plugins/data/public/query/timefilter/lib/extract_time_filter.ts
@@ -18,13 +18,13 @@
*/
import { keys, partition } from 'lodash';
-import { Filter, isRangeFilter, RangeFilter } from '@kbn/es-query';
+import { esFilters } from '../../../../../../plugins/data/public';
-export function extractTimeFilter(timeFieldName: string, filters: Filter[]) {
- const [timeRangeFilter, restOfFilters] = partition(filters, (obj: Filter) => {
+export function extractTimeFilter(timeFieldName: string, filters: esFilters.Filter[]) {
+ const [timeRangeFilter, restOfFilters] = partition(filters, (obj: esFilters.Filter) => {
let key;
- if (isRangeFilter(obj)) {
+ if (esFilters.isRangeFilter(obj)) {
key = keys(obj.range)[0];
}
@@ -33,6 +33,6 @@ export function extractTimeFilter(timeFieldName: string, filters: Filter[]) {
return {
restOfFilters,
- timeRangeFilter: timeRangeFilter[0] as RangeFilter | undefined,
+ timeRangeFilter: timeRangeFilter[0] as esFilters.RangeFilter | undefined,
};
}
diff --git a/src/legacy/core_plugins/data/public/timefilter/lib/parse_querystring.ts b/src/plugins/data/public/query/timefilter/lib/parse_querystring.ts
similarity index 100%
rename from src/legacy/core_plugins/data/public/timefilter/lib/parse_querystring.ts
rename to src/plugins/data/public/query/timefilter/lib/parse_querystring.ts
diff --git a/src/legacy/core_plugins/data/public/timefilter/time_history.ts b/src/plugins/data/public/query/timefilter/time_history.ts
similarity index 97%
rename from src/legacy/core_plugins/data/public/timefilter/time_history.ts
rename to src/plugins/data/public/query/timefilter/time_history.ts
index 36ad1a4427a47..e14c9ac0bc7ca 100644
--- a/src/legacy/core_plugins/data/public/timefilter/time_history.ts
+++ b/src/plugins/data/public/query/timefilter/time_history.ts
@@ -20,7 +20,7 @@
import moment from 'moment';
import { TimeRange } from 'src/plugins/data/public';
import { IStorageWrapper } from 'src/plugins/kibana_utils/public';
-import { PersistedLog } from '../query/persisted_log';
+import { PersistedLog } from '../persisted_log';
export class TimeHistory {
private history: PersistedLog;
diff --git a/src/legacy/core_plugins/data/public/timefilter/timefilter.test.ts b/src/plugins/data/public/query/timefilter/timefilter.test.ts
similarity index 100%
rename from src/legacy/core_plugins/data/public/timefilter/timefilter.test.ts
rename to src/plugins/data/public/query/timefilter/timefilter.test.ts
diff --git a/src/legacy/core_plugins/data/public/timefilter/timefilter.ts b/src/plugins/data/public/query/timefilter/timefilter.ts
similarity index 97%
rename from src/legacy/core_plugins/data/public/timefilter/timefilter.ts
rename to src/plugins/data/public/query/timefilter/timefilter.ts
index 14e167b0fd56e..137e5100aa20e 100644
--- a/src/legacy/core_plugins/data/public/timefilter/timefilter.ts
+++ b/src/plugins/data/public/query/timefilter/timefilter.ts
@@ -20,13 +20,15 @@
import _ from 'lodash';
import { Subject, BehaviorSubject } from 'rxjs';
import moment from 'moment';
-import { RefreshInterval, TimeRange } from 'src/plugins/data/public';
-import { IndexPattern, TimeHistoryContract } from '../index';
+import { RefreshInterval, TimeRange, TimeHistoryContract } from 'src/plugins/data/public';
+import { IndexPattern } from 'src/legacy/core_plugins/data/public';
import { areRefreshIntervalsDifferent, areTimeRangesDifferent } from './lib/diff_time_picker_vals';
import { parseQueryString } from './lib/parse_querystring';
import { calculateBounds, getTime } from './get_time';
import { TimefilterConfig, InputTimeRange, TimeRangeBounds } from './types';
+// TODO: remove!
+
export class Timefilter {
// Fired when isTimeRangeSelectorEnabled \ isAutoRefreshSelectorEnabled are toggled
private enabledUpdated$ = new BehaviorSubject(false);
diff --git a/src/legacy/core_plugins/data/public/timefilter/timefilter_service.mock.ts b/src/plugins/data/public/query/timefilter/timefilter_service.mock.ts
similarity index 100%
rename from src/legacy/core_plugins/data/public/timefilter/timefilter_service.mock.ts
rename to src/plugins/data/public/query/timefilter/timefilter_service.mock.ts
diff --git a/src/legacy/core_plugins/data/public/timefilter/timefilter_service.ts b/src/plugins/data/public/query/timefilter/timefilter_service.ts
similarity index 100%
rename from src/legacy/core_plugins/data/public/timefilter/timefilter_service.ts
rename to src/plugins/data/public/query/timefilter/timefilter_service.ts
diff --git a/src/legacy/core_plugins/data/public/timefilter/types.ts b/src/plugins/data/public/query/timefilter/types.ts
similarity index 100%
rename from src/legacy/core_plugins/data/public/timefilter/types.ts
rename to src/plugins/data/public/query/timefilter/types.ts
diff --git a/src/plugins/data/public/search/create_app_mount_context_search.test.ts b/src/plugins/data/public/search/create_app_mount_context_search.test.ts
index deab9af4e3a01..fa7cdbcda3082 100644
--- a/src/plugins/data/public/search/create_app_mount_context_search.test.ts
+++ b/src/plugins/data/public/search/create_app_mount_context_search.test.ts
@@ -62,8 +62,10 @@ describe('Create app mount search context', () => {
});
},
});
- context
- .search({ greeting: 'hi' } as any, {}, 'mysearch')
- .subscribe(response => {}, () => {}, done);
+ context.search({ greeting: 'hi' } as any, {}, 'mysearch').subscribe(
+ response => {},
+ () => {},
+ done
+ );
});
});
diff --git a/src/plugins/data/public/search/es_search/es_search_strategy.ts b/src/plugins/data/public/search/es_search/es_search_strategy.ts
index 643ded120799e..d29f3b6882b26 100644
--- a/src/plugins/data/public/search/es_search/es_search_strategy.ts
+++ b/src/plugins/data/public/search/es_search/es_search_strategy.ts
@@ -20,6 +20,7 @@
import { Observable } from 'rxjs';
import { ES_SEARCH_STRATEGY, IEsSearchResponse } from '../../../common/search';
import { SYNC_SEARCH_STRATEGY } from '../sync_search_strategy';
+import { getEsPreference } from './get_es_preference';
import { TSearchStrategyProvider, ISearchStrategy, ISearchGeneric, ISearchContext } from '..';
export const esSearchStrategyProvider: TSearchStrategyProvider = (
@@ -27,11 +28,17 @@ export const esSearchStrategyProvider: TSearchStrategyProvider => {
return {
- search: (request, options) =>
- search(
+ search: (request, options) => {
+ if (typeof request.params.preference === 'undefined') {
+ const setPreference = context.core.uiSettings.get('courier:setRequestPreference');
+ const customPreference = context.core.uiSettings.get('courier:customRequestPreference');
+ request.params.preference = getEsPreference(setPreference, customPreference);
+ }
+ return search(
{ ...request, serverStrategy: ES_SEARCH_STRATEGY },
options,
SYNC_SEARCH_STRATEGY
- ) as Observable,
+ ) as Observable;
+ },
};
};
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
new file mode 100644
index 0000000000000..27e6f9b48bbdd
--- /dev/null
+++ b/src/plugins/data/public/search/es_search/get_es_preference.test.ts
@@ -0,0 +1,46 @@
+/*
+ * 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 { getEsPreference } from './get_es_preference';
+
+jest.useFakeTimers();
+
+describe('Get ES preference', () => {
+ test('returns the session ID if set to sessionId', () => {
+ const setPreference = 'sessionId';
+ const customPreference = 'foobar';
+ const sessionId = 'my_session_id';
+ const preference = getEsPreference(setPreference, customPreference, sessionId);
+ expect(preference).toBe(sessionId);
+ });
+
+ test('returns the custom preference if set to custom', () => {
+ const setPreference = 'custom';
+ const customPreference = 'foobar';
+ const preference = getEsPreference(setPreference, customPreference);
+ expect(preference).toBe(customPreference);
+ });
+
+ test('returns undefined if set to none', () => {
+ const setPreference = 'none';
+ const customPreference = 'foobar';
+ const preference = getEsPreference(setPreference, customPreference);
+ 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
new file mode 100644
index 0000000000000..200e5bacb7f18
--- /dev/null
+++ b/src/plugins/data/public/search/es_search/get_es_preference.ts
@@ -0,0 +1,29 @@
+/*
+ * 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 defaultSessionId = `${Date.now()}`;
+
+export function getEsPreference(
+ setRequestPreference: string,
+ customRequestPreference?: string,
+ sessionId: string = defaultSessionId
+) {
+ if (setRequestPreference === 'sessionId') return `${sessionId}`;
+ return setRequestPreference === 'custom' ? customRequestPreference : undefined;
+}
diff --git a/src/plugins/data/public/stubs.ts b/src/plugins/data/public/stubs.ts
new file mode 100644
index 0000000000000..40a5e7d18f8d9
--- /dev/null
+++ b/src/plugins/data/public/stubs.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 { stubIndexPattern } from './index_patterns/index_pattern.stub';
+export { stubFields } from './index_patterns/field.stub';
diff --git a/src/plugins/data/public/suggestions_provider/types.ts b/src/plugins/data/public/suggestions_provider/types.ts
index eac380dde6a62..988b5fcd43fa8 100644
--- a/src/plugins/data/public/suggestions_provider/types.ts
+++ b/src/plugins/data/public/suggestions_provider/types.ts
@@ -16,8 +16,6 @@
* specific language governing permissions and limitations
* under the License.
*/
-
-// Should be import { Field } from './index_patterns';
-export type Field = any;
+import { Field } from '..';
export type IGetSuggestions = (index: string, field: Field, query: string, boolFilter?: any) => any;
diff --git a/src/plugins/data/public/suggestions_provider/value_suggestions.test.ts b/src/plugins/data/public/suggestions_provider/value_suggestions.test.ts
index 13ccbbd9f3dde..7dc8ff0fe133d 100644
--- a/src/plugins/data/public/suggestions_provider/value_suggestions.test.ts
+++ b/src/plugins/data/public/suggestions_provider/value_suggestions.test.ts
@@ -19,9 +19,8 @@
// TODO: remove when index patterns are moved here.
jest.mock('ui/new_platform');
-jest.mock('ui/index_patterns');
-import { mockFields, mockIndexPattern } from 'ui/index_patterns';
+import { stubIndexPattern, stubFields } from '../stubs';
import { getSuggestionsProvider } from './value_suggestions';
import { UiSettingsClientContract } from 'kibana/public';
@@ -37,8 +36,8 @@ describe('getSuggestions', () => {
});
it('should return an empty array', async () => {
- const index = mockIndexPattern.id;
- const [field] = mockFields;
+ const index = stubIndexPattern.id;
+ const [field] = stubFields;
const query = '';
const suggestions = await getSuggestions(index, field, query);
expect(suggestions).toEqual([]);
@@ -54,8 +53,8 @@ describe('getSuggestions', () => {
});
it('should return true/false for boolean fields', async () => {
- const index = mockIndexPattern.id;
- const [field] = mockFields.filter(({ type }) => type === 'boolean');
+ const index = stubIndexPattern.id;
+ const [field] = stubFields.filter(({ type }) => type === 'boolean');
const query = '';
const suggestions = await getSuggestions(index, field, query);
expect(suggestions).toEqual([true, false]);
@@ -63,8 +62,8 @@ describe('getSuggestions', () => {
});
it('should return an empty array if the field type is not a string or boolean', async () => {
- const index = mockIndexPattern.id;
- const [field] = mockFields.filter(({ type }) => type !== 'string' && type !== 'boolean');
+ const index = stubIndexPattern.id;
+ const [field] = stubFields.filter(({ type }) => type !== 'string' && type !== 'boolean');
const query = '';
const suggestions = await getSuggestions(index, field, query);
expect(suggestions).toEqual([]);
@@ -72,8 +71,8 @@ describe('getSuggestions', () => {
});
it('should return an empty array if the field is not aggregatable', async () => {
- const index = mockIndexPattern.id;
- const [field] = mockFields.filter(({ aggregatable }) => !aggregatable);
+ const index = stubIndexPattern.id;
+ const [field] = stubFields.filter(({ aggregatable }) => !aggregatable);
const query = '';
const suggestions = await getSuggestions(index, field, query);
expect(suggestions).toEqual([]);
@@ -81,8 +80,8 @@ describe('getSuggestions', () => {
});
it('should otherwise request suggestions', async () => {
- const index = mockIndexPattern.id;
- const [field] = mockFields.filter(
+ const index = stubIndexPattern.id;
+ const [field] = stubFields.filter(
({ type, aggregatable }) => type === 'string' && aggregatable
);
const query = '';
@@ -91,8 +90,8 @@ describe('getSuggestions', () => {
});
it('should cache results if using the same index/field/query/filter', async () => {
- const index = mockIndexPattern.id;
- const [field] = mockFields.filter(
+ const index = stubIndexPattern.id;
+ const [field] = stubFields.filter(
({ type, aggregatable }) => type === 'string' && aggregatable
);
const query = '';
@@ -102,8 +101,8 @@ describe('getSuggestions', () => {
});
it('should cache results for only one minute', async () => {
- const index = mockIndexPattern.id;
- const [field] = mockFields.filter(
+ const index = stubIndexPattern.id;
+ const [field] = stubFields.filter(
({ type, aggregatable }) => type === 'string' && aggregatable
);
const query = '';
@@ -119,7 +118,7 @@ describe('getSuggestions', () => {
});
it('should not cache results if using a different index/field/query', async () => {
- const fields = mockFields.filter(
+ const fields = stubFields.filter(
({ type, aggregatable }) => type === 'string' && aggregatable
);
await getSuggestions('index', fields[0], '');
diff --git a/src/plugins/data/public/suggestions_provider/value_suggestions.ts b/src/plugins/data/public/suggestions_provider/value_suggestions.ts
index 03eaa5d9594d2..c769f64025b0e 100644
--- a/src/plugins/data/public/suggestions_provider/value_suggestions.ts
+++ b/src/plugins/data/public/suggestions_provider/value_suggestions.ts
@@ -20,7 +20,8 @@
import { memoize } from 'lodash';
import { UiSettingsClientContract, HttpServiceBase } from 'src/core/public';
-import { IGetSuggestions, Field } from './types';
+import { IGetSuggestions } from './types';
+import { Field } from '..';
export function getSuggestionsProvider(
uiSettings: UiSettingsClientContract,
diff --git a/src/plugins/data/server/index.ts b/src/plugins/data/server/index.ts
index df933167cee25..f0b6117b928cd 100644
--- a/src/plugins/data/server/index.ts
+++ b/src/plugins/data/server/index.ts
@@ -25,6 +25,11 @@ export function plugin(initializerContext: PluginInitializerContext) {
}
export { DataServerPlugin as Plugin };
+export {
+ IndexPatternsFetcher,
+ FieldDescriptor,
+ shouldReadFieldFromDocValues,
+} from './index_patterns';
export * from './search';
diff --git a/src/plugins/data/server/index_patterns/fetcher/index.ts b/src/plugins/data/server/index_patterns/fetcher/index.ts
new file mode 100644
index 0000000000000..19306696885db
--- /dev/null
+++ b/src/plugins/data/server/index_patterns/fetcher/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 './index_patterns_fetcher';
+export { shouldReadFieldFromDocValues } from './lib';
diff --git a/src/legacy/server/index_patterns/service/index_patterns_service.ts b/src/plugins/data/server/index_patterns/fetcher/index_patterns_fetcher.ts
similarity index 98%
rename from src/legacy/server/index_patterns/service/index_patterns_service.ts
rename to src/plugins/data/server/index_patterns/fetcher/index_patterns_fetcher.ts
index 62cf51828a4cc..5f1493a49ab7d 100644
--- a/src/legacy/server/index_patterns/service/index_patterns_service.ts
+++ b/src/plugins/data/server/index_patterns/fetcher/index_patterns_fetcher.ts
@@ -36,7 +36,7 @@ interface FieldSubType {
nested?: { path: string };
}
-export class IndexPatternsService {
+export class IndexPatternsFetcher {
private _callDataCluster: APICaller;
constructor(callDataCluster: APICaller) {
diff --git a/src/legacy/server/index_patterns/service/lib/errors.ts b/src/plugins/data/server/index_patterns/fetcher/lib/errors.ts
similarity index 100%
rename from src/legacy/server/index_patterns/service/lib/errors.ts
rename to src/plugins/data/server/index_patterns/fetcher/lib/errors.ts
diff --git a/src/legacy/server/index_patterns/service/lib/es_api.test.js b/src/plugins/data/server/index_patterns/fetcher/lib/es_api.test.js
similarity index 100%
rename from src/legacy/server/index_patterns/service/lib/es_api.test.js
rename to src/plugins/data/server/index_patterns/fetcher/lib/es_api.test.js
diff --git a/src/legacy/server/index_patterns/service/lib/es_api.ts b/src/plugins/data/server/index_patterns/fetcher/lib/es_api.ts
similarity index 99%
rename from src/legacy/server/index_patterns/service/lib/es_api.ts
rename to src/plugins/data/server/index_patterns/fetcher/lib/es_api.ts
index 63c1824784dbd..92b64fafddd66 100644
--- a/src/legacy/server/index_patterns/service/lib/es_api.ts
+++ b/src/plugins/data/server/index_patterns/fetcher/lib/es_api.ts
@@ -18,7 +18,6 @@
*/
import { APICaller } from 'src/core/server';
-// @ts-ignore
import { convertEsError } from './errors';
import { FieldCapsResponse } from './field_capabilities';
diff --git a/src/legacy/server/index_patterns/service/lib/field_capabilities/__fixtures__/es_field_caps_response.json b/src/plugins/data/server/index_patterns/fetcher/lib/field_capabilities/__fixtures__/es_field_caps_response.json
similarity index 100%
rename from src/legacy/server/index_patterns/service/lib/field_capabilities/__fixtures__/es_field_caps_response.json
rename to src/plugins/data/server/index_patterns/fetcher/lib/field_capabilities/__fixtures__/es_field_caps_response.json
diff --git a/src/legacy/server/index_patterns/service/lib/field_capabilities/field_capabilities.test.js b/src/plugins/data/server/index_patterns/fetcher/lib/field_capabilities/field_capabilities.test.js
similarity index 100%
rename from src/legacy/server/index_patterns/service/lib/field_capabilities/field_capabilities.test.js
rename to src/plugins/data/server/index_patterns/fetcher/lib/field_capabilities/field_capabilities.test.js
diff --git a/src/legacy/server/index_patterns/service/lib/field_capabilities/field_capabilities.ts b/src/plugins/data/server/index_patterns/fetcher/lib/field_capabilities/field_capabilities.ts
similarity index 97%
rename from src/legacy/server/index_patterns/service/lib/field_capabilities/field_capabilities.ts
rename to src/plugins/data/server/index_patterns/fetcher/lib/field_capabilities/field_capabilities.ts
index 05e8d591f13a9..c275fb714088e 100644
--- a/src/legacy/server/index_patterns/service/lib/field_capabilities/field_capabilities.ts
+++ b/src/plugins/data/server/index_patterns/fetcher/lib/field_capabilities/field_capabilities.ts
@@ -23,7 +23,7 @@ import { APICaller } from 'src/core/server';
import { callFieldCapsApi } from '../es_api';
import { FieldCapsResponse, readFieldCapsResponse } from './field_caps_response';
import { mergeOverrides } from './overrides';
-import { FieldDescriptor } from '../../index_patterns_service';
+import { FieldDescriptor } from '../../index_patterns_fetcher';
export function concatIfUniq(arr: T[], value: T) {
return arr.includes(value) ? arr : arr.concat(value);
diff --git a/src/legacy/server/index_patterns/service/lib/field_capabilities/field_caps_response.test.js b/src/plugins/data/server/index_patterns/fetcher/lib/field_capabilities/field_caps_response.test.js
similarity index 99%
rename from src/legacy/server/index_patterns/service/lib/field_capabilities/field_caps_response.test.js
rename to src/plugins/data/server/index_patterns/fetcher/lib/field_capabilities/field_caps_response.test.js
index c0a5492aaba36..cf4af615b9577 100644
--- a/src/legacy/server/index_patterns/service/lib/field_capabilities/field_caps_response.test.js
+++ b/src/plugins/data/server/index_patterns/fetcher/lib/field_capabilities/field_caps_response.test.js
@@ -24,7 +24,7 @@ import sinon from 'sinon';
import * as shouldReadFieldFromDocValuesNS from './should_read_field_from_doc_values';
import { shouldReadFieldFromDocValues } from './should_read_field_from_doc_values';
-import { getKbnFieldType } from '../../../../../../plugins/data/common';
+import { getKbnFieldType } from '../../../../../../data/common';
import { readFieldCapsResponse } from './field_caps_response';
import esResponse from './__fixtures__/es_field_caps_response.json';
diff --git a/src/legacy/server/index_patterns/service/lib/field_capabilities/field_caps_response.ts b/src/plugins/data/server/index_patterns/fetcher/lib/field_capabilities/field_caps_response.ts
similarity index 98%
rename from src/legacy/server/index_patterns/service/lib/field_capabilities/field_caps_response.ts
rename to src/plugins/data/server/index_patterns/fetcher/lib/field_capabilities/field_caps_response.ts
index 19288014de297..06eb30db0b24b 100644
--- a/src/legacy/server/index_patterns/service/lib/field_capabilities/field_caps_response.ts
+++ b/src/plugins/data/server/index_patterns/fetcher/lib/field_capabilities/field_caps_response.ts
@@ -18,9 +18,9 @@
*/
import { uniq } from 'lodash';
-import { FieldDescriptor } from '../..';
+import { castEsToKbnFieldTypeName } from '../../../../../common';
import { shouldReadFieldFromDocValues } from './should_read_field_from_doc_values';
-import { castEsToKbnFieldTypeName } from '../../../../../../plugins/data/common';
+import { FieldDescriptor } from '../../../fetcher';
interface FieldCapObject {
type: string;
diff --git a/src/legacy/server/index_patterns/service/lib/field_capabilities/index.ts b/src/plugins/data/server/index_patterns/fetcher/lib/field_capabilities/index.ts
similarity index 91%
rename from src/legacy/server/index_patterns/service/lib/field_capabilities/index.ts
rename to src/plugins/data/server/index_patterns/fetcher/lib/field_capabilities/index.ts
index 8ac4225557784..6a541aff56471 100644
--- a/src/legacy/server/index_patterns/service/lib/field_capabilities/index.ts
+++ b/src/plugins/data/server/index_patterns/fetcher/lib/field_capabilities/index.ts
@@ -19,3 +19,4 @@
export { getFieldCapabilities } from './field_capabilities';
export { FieldCapsResponse } from './field_caps_response';
+export { shouldReadFieldFromDocValues } from './should_read_field_from_doc_values';
diff --git a/src/legacy/server/index_patterns/service/lib/field_capabilities/overrides.ts b/src/plugins/data/server/index_patterns/fetcher/lib/field_capabilities/overrides.ts
similarity index 95%
rename from src/legacy/server/index_patterns/service/lib/field_capabilities/overrides.ts
rename to src/plugins/data/server/index_patterns/fetcher/lib/field_capabilities/overrides.ts
index 6310bf02e4430..518bfeccac01a 100644
--- a/src/legacy/server/index_patterns/service/lib/field_capabilities/overrides.ts
+++ b/src/plugins/data/server/index_patterns/fetcher/lib/field_capabilities/overrides.ts
@@ -18,7 +18,7 @@
*/
import { merge } from 'lodash';
-import { FieldDescriptor } from '../../index_patterns_service';
+import { FieldDescriptor } from '../../index_patterns_fetcher';
const OVERRIDES: Record> = {
_source: { type: '_source' },
diff --git a/src/legacy/server/index_patterns/service/lib/field_capabilities/should_read_field_from_doc_values.ts b/src/plugins/data/server/index_patterns/fetcher/lib/field_capabilities/should_read_field_from_doc_values.ts
similarity index 100%
rename from src/legacy/server/index_patterns/service/lib/field_capabilities/should_read_field_from_doc_values.ts
rename to src/plugins/data/server/index_patterns/fetcher/lib/field_capabilities/should_read_field_from_doc_values.ts
diff --git a/src/legacy/server/index_patterns/service/lib/index.ts b/src/plugins/data/server/index_patterns/fetcher/lib/index.ts
similarity index 90%
rename from src/legacy/server/index_patterns/service/lib/index.ts
rename to src/plugins/data/server/index_patterns/fetcher/lib/index.ts
index cd239b3753aa3..20e74d2b1a579 100644
--- a/src/legacy/server/index_patterns/service/lib/index.ts
+++ b/src/plugins/data/server/index_patterns/fetcher/lib/index.ts
@@ -17,8 +17,6 @@
* under the License.
*/
-export { getFieldCapabilities } from './field_capabilities';
-// @ts-ignore
+export { getFieldCapabilities, shouldReadFieldFromDocValues } from './field_capabilities';
export { resolveTimePattern } from './resolve_time_pattern';
-// @ts-ignore
export { createNoMatchingIndicesError } from './errors';
diff --git a/src/legacy/server/index_patterns/service/lib/resolve_time_pattern.test.js b/src/plugins/data/server/index_patterns/fetcher/lib/resolve_time_pattern.test.js
similarity index 100%
rename from src/legacy/server/index_patterns/service/lib/resolve_time_pattern.test.js
rename to src/plugins/data/server/index_patterns/fetcher/lib/resolve_time_pattern.test.js
diff --git a/src/legacy/server/index_patterns/service/lib/resolve_time_pattern.ts b/src/plugins/data/server/index_patterns/fetcher/lib/resolve_time_pattern.ts
similarity index 100%
rename from src/legacy/server/index_patterns/service/lib/resolve_time_pattern.ts
rename to src/plugins/data/server/index_patterns/fetcher/lib/resolve_time_pattern.ts
diff --git a/src/legacy/server/index_patterns/service/lib/time_pattern_to_wildcard.test.ts b/src/plugins/data/server/index_patterns/fetcher/lib/time_pattern_to_wildcard.test.ts
similarity index 100%
rename from src/legacy/server/index_patterns/service/lib/time_pattern_to_wildcard.test.ts
rename to src/plugins/data/server/index_patterns/fetcher/lib/time_pattern_to_wildcard.test.ts
diff --git a/src/legacy/server/index_patterns/service/lib/time_pattern_to_wildcard.ts b/src/plugins/data/server/index_patterns/fetcher/lib/time_pattern_to_wildcard.ts
similarity index 100%
rename from src/legacy/server/index_patterns/service/lib/time_pattern_to_wildcard.ts
rename to src/plugins/data/server/index_patterns/fetcher/lib/time_pattern_to_wildcard.ts
diff --git a/src/plugins/data/server/index_patterns/index.ts b/src/plugins/data/server/index_patterns/index.ts
new file mode 100644
index 0000000000000..6937fa22c4e5d
--- /dev/null
+++ b/src/plugins/data/server/index_patterns/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 { IndexPatternsFetcher, FieldDescriptor, shouldReadFieldFromDocValues } from './fetcher';
+export { IndexPatternsService } from './index_patterns_service';
diff --git a/src/plugins/data/server/index_patterns/index_patterns_service.ts b/src/plugins/data/server/index_patterns/index_patterns_service.ts
new file mode 100644
index 0000000000000..30d199c0e522e
--- /dev/null
+++ b/src/plugins/data/server/index_patterns/index_patterns_service.ts
@@ -0,0 +1,30 @@
+/*
+ * 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 { CoreSetup } from 'kibana/server';
+import { Plugin } from '../../../../core/server';
+import { registerRoutes } from './routes';
+
+export class IndexPatternsService implements Plugin {
+ public setup({ http, elasticsearch }: CoreSetup) {
+ registerRoutes(http, elasticsearch);
+ }
+
+ public start() {}
+}
diff --git a/src/legacy/server/index_patterns/routes.ts b/src/plugins/data/server/index_patterns/routes.ts
similarity index 90%
rename from src/legacy/server/index_patterns/routes.ts
rename to src/plugins/data/server/index_patterns/routes.ts
index fb78b94e0f77f..7975e923e219b 100644
--- a/src/legacy/server/index_patterns/routes.ts
+++ b/src/plugins/data/server/index_patterns/routes.ts
@@ -25,18 +25,18 @@ import {
RequestHandlerContext,
APICaller,
CallAPIOptions,
-} from '../../../core/server';
-import { IndexPatternsService } from './service';
+} from '../../../../core/server';
+import { IndexPatternsFetcher } from './fetcher';
-export function registerRoutes(core: CoreSetup) {
- const getIndexPatternsService = async (request: KibanaRequest): Promise => {
- const client = await core.elasticsearch.dataClient$.pipe(first()).toPromise();
+export function registerRoutes(http: CoreSetup['http'], elasticsearch: CoreSetup['elasticsearch']) {
+ const getIndexPatternsService = async (request: KibanaRequest): Promise => {
+ const client = await elasticsearch.dataClient$.pipe(first()).toPromise();
const callCluster: APICaller = (
endpoint: string,
params?: Record,
options?: CallAPIOptions
) => client.asScoped(request).callAsCurrentUser(endpoint, params, options);
- return new Promise(resolve => resolve(new IndexPatternsService(callCluster)));
+ return new Promise(resolve => resolve(new IndexPatternsFetcher(callCluster)));
};
const parseMetaFields = (metaFields: string | string[]) => {
@@ -49,7 +49,7 @@ export function registerRoutes(core: CoreSetup) {
return parsedFields;
};
- const router = core.http.createRouter();
+ const router = http.createRouter();
router.get(
{
path: '/api/index_patterns/_fields_for_wildcard',
diff --git a/src/plugins/data/server/plugin.ts b/src/plugins/data/server/plugin.ts
index 9cf08b0702e9e..e81250e653ebd 100644
--- a/src/plugins/data/server/plugin.ts
+++ b/src/plugins/data/server/plugin.ts
@@ -18,19 +18,21 @@
*/
import { PluginInitializerContext, CoreSetup, CoreStart, Plugin } from '../../../core/server';
+import { IndexPatternsService } from './index_patterns';
import { ISearchSetup } from './search';
import { SearchService } from './search/search_service';
export interface DataPluginSetup {
search: ISearchSetup;
}
-
export class DataServerPlugin implements Plugin {
private readonly searchService: SearchService;
+ private readonly indexPatterns = new IndexPatternsService();
constructor(initializerContext: PluginInitializerContext) {
this.searchService = new SearchService(initializerContext);
}
public setup(core: CoreSetup) {
+ this.indexPatterns.setup(core);
return {
search: this.searchService.setup(core),
};
diff --git a/src/plugins/embeddable/public/lib/actions/apply_filter_action.ts b/src/plugins/embeddable/public/lib/actions/apply_filter_action.ts
index 99cfb2ea13d07..e2592b70397f3 100644
--- a/src/plugins/embeddable/public/lib/actions/apply_filter_action.ts
+++ b/src/plugins/embeddable/public/lib/actions/apply_filter_action.ts
@@ -18,16 +18,16 @@
*/
import { i18n } from '@kbn/i18n';
-import { Filter } from '@kbn/es-query';
import { IAction, createAction, IncompatibleActionError } from '../ui_actions';
import { IEmbeddable, EmbeddableInput } from '../embeddables';
+import { esFilters } from '../../../../../plugins/data/public';
export const APPLY_FILTER_ACTION = 'APPLY_FILTER_ACTION';
-type RootEmbeddable = IEmbeddable;
+type RootEmbeddable = IEmbeddable;
interface ActionContext {
embeddable: IEmbeddable;
- filters: Filter[];
+ filters: esFilters.Filter[];
}
async function isCompatible(context: ActionContext) {
diff --git a/src/plugins/embeddable/public/lib/panel/panel_header/panel_actions/add_panel/add_panel_action.test.tsx b/src/plugins/embeddable/public/lib/panel/panel_header/panel_actions/add_panel/add_panel_action.test.tsx
index 802be5bf1282e..47113ffc59561 100644
--- a/src/plugins/embeddable/public/lib/panel/panel_header/panel_actions/add_panel/add_panel_action.test.tsx
+++ b/src/plugins/embeddable/public/lib/panel/panel_header/panel_actions/add_panel/add_panel_action.test.tsx
@@ -20,7 +20,6 @@
import { ViewMode, EmbeddableOutput, isErrorEmbeddable } from '../../../../';
import { AddPanelAction } from './add_panel_action';
import { EmbeddableFactory } from '../../../../embeddables';
-import { Filter, FilterStateStore } from '@kbn/es-query';
import {
FILTERABLE_EMBEDDABLE,
FilterableEmbeddable,
@@ -32,6 +31,7 @@ import { GetEmbeddableFactory } from '../../../../types';
// eslint-disable-next-line
import { coreMock } from '../../../../../../../../core/public/mocks';
import { ContactCardEmbeddable } from '../../../../test_samples';
+import { esFilters } from '../../../../../../../../plugins/data/public';
const embeddableFactories = new Map();
embeddableFactories.set(FILTERABLE_EMBEDDABLE, new FilterableEmbeddableFactory());
@@ -51,8 +51,8 @@ beforeEach(async () => {
() => null
);
- const derivedFilter: Filter = {
- $state: { store: FilterStateStore.APP_STATE },
+ const derivedFilter: esFilters.Filter = {
+ $state: { store: esFilters.FilterStateStore.APP_STATE },
meta: { disabled: false, alias: 'name', negate: false },
query: { match: {} },
};
diff --git a/src/plugins/embeddable/public/lib/panel/panel_header/panel_actions/inspect_panel_action.test.tsx b/src/plugins/embeddable/public/lib/panel/panel_header/panel_actions/inspect_panel_action.test.tsx
index 550f9706a634b..8d9beec940acc 100644
--- a/src/plugins/embeddable/public/lib/panel/panel_header/panel_actions/inspect_panel_action.test.tsx
+++ b/src/plugins/embeddable/public/lib/panel/panel_header/panel_actions/inspect_panel_action.test.tsx
@@ -28,7 +28,6 @@ import {
} from '../../../test_samples';
// eslint-disable-next-line
import { inspectorPluginMock } from 'src/plugins/inspector/public/mocks';
-import { FilterStateStore } from '@kbn/es-query';
import {
EmbeddableFactory,
EmbeddableOutput,
@@ -37,6 +36,7 @@ import {
} from '../../../embeddables';
import { GetEmbeddableFactory } from '../../../types';
import { of } from '../../../../tests/helpers';
+import { esFilters } from '../../../../../../../plugins/data/public';
const setup = async () => {
const embeddableFactories = new Map();
@@ -48,7 +48,7 @@ const setup = async () => {
panels: {},
filters: [
{
- $state: { store: FilterStateStore.APP_STATE },
+ $state: { store: esFilters.FilterStateStore.APP_STATE },
meta: { disabled: false, alias: 'name', negate: false },
query: { match: {} },
},
diff --git a/src/plugins/embeddable/public/lib/panel/panel_header/panel_actions/remove_panel_action.test.tsx b/src/plugins/embeddable/public/lib/panel/panel_header/panel_actions/remove_panel_action.test.tsx
index 22e3be89f1ae9..684a8c45a4e89 100644
--- a/src/plugins/embeddable/public/lib/panel/panel_header/panel_actions/remove_panel_action.test.tsx
+++ b/src/plugins/embeddable/public/lib/panel/panel_header/panel_actions/remove_panel_action.test.tsx
@@ -17,7 +17,6 @@
* under the License.
*/
-import { Filter, FilterStateStore } from '@kbn/es-query';
import { EmbeddableOutput, isErrorEmbeddable } from '../../../';
import { RemovePanelAction } from './remove_panel_action';
import { EmbeddableFactory } from '../../../embeddables';
@@ -30,6 +29,7 @@ import { FilterableEmbeddableFactory } from '../../../test_samples/embeddables/f
import { FilterableContainer } from '../../../test_samples/embeddables/filterable_container';
import { GetEmbeddableFactory, ViewMode } from '../../../types';
import { ContactCardEmbeddable } from '../../../test_samples/embeddables/contact_card/contact_card_embeddable';
+import { esFilters } from '../../../../../../../plugins/data/public';
const embeddableFactories = new Map();
embeddableFactories.set(FILTERABLE_EMBEDDABLE, new FilterableEmbeddableFactory());
@@ -39,8 +39,8 @@ let container: FilterableContainer;
let embeddable: FilterableEmbeddable;
beforeEach(async () => {
- const derivedFilter: Filter = {
- $state: { store: FilterStateStore.APP_STATE },
+ const derivedFilter: esFilters.Filter = {
+ $state: { store: esFilters.FilterStateStore.APP_STATE },
meta: { disabled: false, alias: 'name', negate: false },
query: { match: {} },
};
diff --git a/src/plugins/embeddable/public/lib/test_samples/embeddables/filterable_container.tsx b/src/plugins/embeddable/public/lib/test_samples/embeddables/filterable_container.tsx
index eaef8048a6fbf..de708b778c3c7 100644
--- a/src/plugins/embeddable/public/lib/test_samples/embeddables/filterable_container.tsx
+++ b/src/plugins/embeddable/public/lib/test_samples/embeddables/filterable_container.tsx
@@ -16,14 +16,15 @@
* specific language governing permissions and limitations
* under the License.
*/
-import { Filter } from '@kbn/es-query';
+
import { Container, ContainerInput } from '../../containers';
import { GetEmbeddableFactory } from '../../types';
+import { esFilters } from '../../../../../data/public';
export const FILTERABLE_CONTAINER = 'FILTERABLE_CONTAINER';
export interface FilterableContainerInput extends ContainerInput {
- filters: Filter[];
+ filters: esFilters.Filter[];
}
/**
@@ -33,7 +34,7 @@ export interface FilterableContainerInput extends ContainerInput {
*/
// eslint-disable-next-line @typescript-eslint/consistent-type-definitions
export type InheritedChildrenInput = {
- filters: Filter[];
+ filters: esFilters.Filter[];
id?: string;
};
diff --git a/src/plugins/embeddable/public/lib/test_samples/embeddables/filterable_embeddable.tsx b/src/plugins/embeddable/public/lib/test_samples/embeddables/filterable_embeddable.tsx
index f6885ca25b437..56aa7688f37a6 100644
--- a/src/plugins/embeddable/public/lib/test_samples/embeddables/filterable_embeddable.tsx
+++ b/src/plugins/embeddable/public/lib/test_samples/embeddables/filterable_embeddable.tsx
@@ -17,14 +17,14 @@
* under the License.
*/
-import { Filter } from '@kbn/es-query';
import { IContainer } from '../../containers';
import { EmbeddableOutput, EmbeddableInput, Embeddable } from '../../embeddables';
+import { esFilters } from '../../../../../data/public';
export const FILTERABLE_EMBEDDABLE = 'FILTERABLE_EMBEDDABLE';
export interface FilterableEmbeddableInput extends EmbeddableInput {
- filters: Filter[];
+ filters: esFilters.Filter[];
}
export class FilterableEmbeddable extends Embeddable {
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 52500acc3dc59..0721acb1a1fba 100644
--- a/src/plugins/embeddable/public/tests/apply_filter_action.test.ts
+++ b/src/plugins/embeddable/public/tests/apply_filter_action.test.ts
@@ -32,7 +32,7 @@ import {
} from '../lib/test_samples';
// eslint-disable-next-line
import { inspectorPluginMock } from 'src/plugins/inspector/public/mocks';
-import { FilterStateStore } from '@kbn/es-query';
+import { esFilters } from '../../../../plugins/data/public';
test('ApplyFilterAction applies the filter to the root of the container tree', async () => {
const { doStart } = testPlugin();
@@ -76,7 +76,7 @@ test('ApplyFilterAction applies the filter to the root of the container tree', a
}
const filter: any = {
- $state: { store: FilterStateStore.APP_STATE },
+ $state: { store: esFilters.FilterStateStore.APP_STATE },
meta: {
disabled: false,
negate: false,
diff --git a/src/plugins/embeddable/public/tests/container.test.ts b/src/plugins/embeddable/public/tests/container.test.ts
index 3bdbcbad857d6..f97c26a41b901 100644
--- a/src/plugins/embeddable/public/tests/container.test.ts
+++ b/src/plugins/embeddable/public/tests/container.test.ts
@@ -26,7 +26,6 @@ import {
FILTERABLE_EMBEDDABLE,
} from '../lib/test_samples/embeddables/filterable_embeddable';
import { ERROR_EMBEDDABLE_TYPE } from '../lib/embeddables/error_embeddable';
-import { Filter, FilterStateStore } from '@kbn/es-query';
import { FilterableEmbeddableFactory } from '../lib/test_samples/embeddables/filterable_embeddable_factory';
import { CONTACT_CARD_EMBEDDABLE } from '../lib/test_samples/embeddables/contact_card/contact_card_embeddable_factory';
import { SlowContactCardEmbeddableFactory } from '../lib/test_samples/embeddables/contact_card/slow_contact_card_embeddable_factory';
@@ -46,6 +45,7 @@ import {
import { coreMock } from '../../../../core/public/mocks';
import { testPlugin } from './test_plugin';
import { of } from './helpers';
+import { esFilters } from '../../../../plugins/data/public';
async function creatHelloWorldContainerAndEmbeddable(
containerInput: ContainerInput = { id: 'hello', panels: {} },
@@ -437,8 +437,8 @@ test('Test nested reactions', async done => {
test('Explicit embeddable input mapped to undefined will default to inherited', async () => {
const { start } = await creatHelloWorldContainerAndEmbeddable();
- const derivedFilter: Filter = {
- $state: { store: FilterStateStore.APP_STATE },
+ const derivedFilter: esFilters.Filter = {
+ $state: { store: esFilters.FilterStateStore.APP_STATE },
meta: { disabled: false, alias: 'name', negate: false },
query: { match: {} },
};
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 b11bd167e15f2..70d7c99d3fb9d 100644
--- a/src/plugins/embeddable/public/tests/customize_panel_modal.test.tsx
+++ b/src/plugins/embeddable/public/tests/customize_panel_modal.test.tsx
@@ -173,7 +173,7 @@ test('Can set title to an empty string', async () => {
);
const inputField = findTestSubject(component, 'customizePanelHideTitle');
- inputField.simulate('change');
+ inputField.simulate('click');
findTestSubject(component, 'saveNewTitleButton').simulate('click');
expect(inputField.props().value).toBeUndefined();
diff --git a/src/plugins/embeddable/public/tests/explicit_input.test.ts b/src/plugins/embeddable/public/tests/explicit_input.test.ts
index 6cde7bdc48ba1..47c4b0944cef2 100644
--- a/src/plugins/embeddable/public/tests/explicit_input.test.ts
+++ b/src/plugins/embeddable/public/tests/explicit_input.test.ts
@@ -18,7 +18,6 @@
*/
import { skip } from 'rxjs/operators';
-import { Filter, FilterStateStore } from '@kbn/es-query';
import { testPlugin } from './test_plugin';
import {
FILTERABLE_EMBEDDABLE,
@@ -34,6 +33,7 @@ import { isErrorEmbeddable } from '../lib';
import { HelloWorldContainer } from '../lib/test_samples/embeddables/hello_world_container';
// eslint-disable-next-line
import { coreMock } from '../../../../core/public/mocks';
+import { esFilters } from '../../../../plugins/data/public';
const { setup, doStart, coreStart, uiActions } = testPlugin(
coreMock.createSetup(),
@@ -50,8 +50,8 @@ setup.registerEmbeddableFactory(CONTACT_CARD_EMBEDDABLE, factory);
setup.registerEmbeddableFactory(HELLO_WORLD_EMBEDDABLE_TYPE, new HelloWorldEmbeddableFactory());
test('Explicit embeddable input mapped to undefined will default to inherited', async () => {
- const derivedFilter: Filter = {
- $state: { store: FilterStateStore.APP_STATE },
+ const derivedFilter: esFilters.Filter = {
+ $state: { store: esFilters.FilterStateStore.APP_STATE },
meta: { disabled: false, alias: 'name', negate: false },
query: { match: {} },
};
diff --git a/src/plugins/es_ui_shared/static/forms/components/fields/toggle_field.tsx b/src/plugins/es_ui_shared/static/forms/components/fields/toggle_field.tsx
index 417f3436a2c63..0c075c497a4d0 100644
--- a/src/plugins/es_ui_shared/static/forms/components/fields/toggle_field.tsx
+++ b/src/plugins/es_ui_shared/static/forms/components/fields/toggle_field.tsx
@@ -18,7 +18,7 @@
*/
import React from 'react';
-import { EuiFormRow, EuiSwitch } from '@elastic/eui';
+import { EuiFormRow, EuiSwitch, EuiSwitchEvent } from '@elastic/eui';
import { FieldHook } from '../../hook_form_lib';
import { getFieldValidityAndErrorMessage } from '../helpers';
@@ -33,6 +33,14 @@ interface Props {
export const ToggleField = ({ field, euiFieldProps = {}, ...rest }: Props) => {
const { isInvalid, errorMessage } = getFieldValidityAndErrorMessage(field);
+ // Shim for sufficient overlap between EuiSwitchEvent and FieldHook[onChange] event
+ const onChange = (e: EuiSwitchEvent) => {
+ const event = ({ ...e, value: `${e.target.checked}` } as unknown) as React.ChangeEvent<{
+ value: string;
+ }>;
+ field.onChange(event);
+ };
+
return (
{
diff --git a/src/plugins/es_ui_shared/static/forms/helpers/serializers.ts b/src/plugins/es_ui_shared/static/forms/helpers/serializers.ts
index e288f61de8681..0bb89cc1af593 100644
--- a/src/plugins/es_ui_shared/static/forms/helpers/serializers.ts
+++ b/src/plugins/es_ui_shared/static/forms/helpers/serializers.ts
@@ -69,24 +69,21 @@ export const stripEmptyFields = (
): { [key: string]: any } => {
const { types = ['string', 'object'], recursive = false } = options || {};
- return Object.entries(object).reduce(
- (acc, [key, value]) => {
- const type = typeof value;
- const shouldStrip = types.includes(type as 'string');
+ return Object.entries(object).reduce((acc, [key, value]) => {
+ const type = typeof value;
+ const shouldStrip = types.includes(type as 'string');
- if (shouldStrip && type === 'string' && value.trim() === '') {
+ if (shouldStrip && type === 'string' && value.trim() === '') {
+ return acc;
+ } else if (type === 'object' && !Array.isArray(value) && value !== null) {
+ if (Object.keys(value).length === 0 && shouldStrip) {
return acc;
- } else if (type === 'object' && !Array.isArray(value) && value !== null) {
- if (Object.keys(value).length === 0 && shouldStrip) {
- return acc;
- } else if (recursive) {
- value = stripEmptyFields({ ...value }, options);
- }
+ } else if (recursive) {
+ value = stripEmptyFields({ ...value }, options);
}
+ }
- acc[key] = value;
- return acc;
- },
- {} as { [key: string]: any }
- );
+ acc[key] = value;
+ return acc;
+ }, {} as { [key: string]: any });
};
diff --git a/src/plugins/es_ui_shared/static/forms/hook_form_lib/hooks/use_form.ts b/src/plugins/es_ui_shared/static/forms/hook_form_lib/hooks/use_form.ts
index 360182368ae63..3902b0615a33d 100644
--- a/src/plugins/es_ui_shared/static/forms/hook_form_lib/hooks/use_form.ts
+++ b/src/plugins/es_ui_shared/static/forms/hook_form_lib/hooks/use_form.ts
@@ -65,15 +65,12 @@ export function useForm(
const stripEmptyFields = (fields: FieldsMap): FieldsMap => {
if (formOptions.stripEmptyFields) {
- return Object.entries(fields).reduce(
- (acc, [key, field]) => {
- if (typeof field.value !== 'string' || field.value.trim() !== '') {
- acc[key] = field;
- }
- return acc;
- },
- {} as FieldsMap
- );
+ return Object.entries(fields).reduce((acc, [key, field]) => {
+ if (typeof field.value !== 'string' || field.value.trim() !== '') {
+ acc[key] = field;
+ }
+ return acc;
+ }, {} as FieldsMap);
}
return fields;
};
diff --git a/src/plugins/es_ui_shared/static/forms/hook_form_lib/lib/utils.ts b/src/plugins/es_ui_shared/static/forms/hook_form_lib/lib/utils.ts
index 66c3e8d983f98..62867a0c07a6b 100644
--- a/src/plugins/es_ui_shared/static/forms/hook_form_lib/lib/utils.ts
+++ b/src/plugins/es_ui_shared/static/forms/hook_form_lib/lib/utils.ts
@@ -50,10 +50,7 @@ export const mapFormFields = (
formFields: Record,
fn: (field: FieldHook) => any
) =>
- Object.entries(formFields).reduce(
- (acc, [key, field]) => {
- acc[key] = fn(field);
- return acc;
- },
- {} as Record
- );
+ Object.entries(formFields).reduce((acc, [key, field]) => {
+ acc[key] = fn(field);
+ return acc;
+ }, {} as Record);
diff --git a/src/plugins/expressions/public/expression_types/kibana_context.ts b/src/plugins/expressions/public/expression_types/kibana_context.ts
index 174517abc2c05..bcf8e2853dec8 100644
--- a/src/plugins/expressions/public/expression_types/kibana_context.ts
+++ b/src/plugins/expressions/public/expression_types/kibana_context.ts
@@ -17,8 +17,7 @@
* under the License.
*/
-import { Filter } from '@kbn/es-query';
-import { TimeRange, Query } from 'src/plugins/data/public';
+import { TimeRange, Query, esFilters } from 'src/plugins/data/public';
const name = 'kibana_context';
export type KIBANA_CONTEXT_NAME = 'kibana_context';
@@ -26,7 +25,7 @@ export type KIBANA_CONTEXT_NAME = 'kibana_context';
export interface KibanaContext {
type: typeof name;
query?: Query | Query[];
- filters?: Filter[];
+ filters?: esFilters.Filter[];
timeRange?: TimeRange;
}
diff --git a/src/plugins/expressions/public/expression_types/number.ts b/src/plugins/expressions/public/expression_types/number.ts
index 8434536f8f6b8..52b2bb1ff3194 100644
--- a/src/plugins/expressions/public/expression_types/number.ts
+++ b/src/plugins/expressions/public/expression_types/number.ts
@@ -17,6 +17,7 @@
* under the License.
*/
+import { i18n } from '@kbn/i18n';
import { ExpressionType } from '../types';
import { Datatable } from './datatable';
import { Render } from './render';
@@ -28,7 +29,20 @@ export const number = (): ExpressionType => ({
from: {
null: () => 0,
boolean: b => Number(b),
- string: n => Number(n),
+ string: n => {
+ const value = Number(n);
+ if (Number.isNaN(value)) {
+ throw new Error(
+ i18n.translate('expressions_np.types.number.fromStringConversionErrorMessage', {
+ defaultMessage: 'Can\'t typecast "{string}" string to number',
+ values: {
+ string: n,
+ },
+ })
+ );
+ }
+ return value;
+ },
},
to: {
render: (value: number): Render<{ text: string }> => {
diff --git a/packages/kbn-es-query/src/filters/query.js b/src/plugins/expressions/public/expression_types/tests/number.test.ts
similarity index 72%
rename from packages/kbn-es-query/src/filters/query.js
rename to src/plugins/expressions/public/expression_types/tests/number.test.ts
index ded877231bf67..3336a1384ea79 100644
--- a/packages/kbn-es-query/src/filters/query.js
+++ b/src/plugins/expressions/public/expression_types/tests/number.test.ts
@@ -17,18 +17,12 @@
* under the License.
*/
-// Creates a filter corresponding to a raw Elasticsearch query DSL object
-export function buildQueryFilter(query, index, alias) {
- const filter = {
- query: query,
- meta: {
- index,
- }
- };
+import { number } from '../number';
- if (alias) {
- filter.meta.alias = alias;
- }
-
- return filter;
-}
+describe('number', () => {
+ it('should fail when typecasting not numeric string to number', () => {
+ expect(() => number().from!.string('123test', {})).toThrowErrorMatchingInlineSnapshot(
+ `"Can't typecast \\"123test\\" string to number"`
+ );
+ });
+});
diff --git a/src/plugins/expressions/public/interpreter_provider.ts b/src/plugins/expressions/public/interpreter_provider.ts
index cb84370ad69c5..15d6b1c025f54 100644
--- a/src/plugins/expressions/public/interpreter_provider.ts
+++ b/src/plugins/expressions/public/interpreter_provider.ts
@@ -163,9 +163,9 @@ export function interpreterProvider(config: InterpreterConfig): ExpressionInterp
// Check for missing required arguments
each(argDefs, argDef => {
- const { aliases, default: argDefault, name: argName, required } = argDef as (ArgumentType<
+ const { aliases, default: argDefault, name: argName, required } = argDef as ArgumentType<
any
- > & { name: string });
+ > & { name: string };
if (
typeof argDefault === 'undefined' &&
required &&
diff --git a/src/plugins/expressions/public/types/index.ts b/src/plugins/expressions/public/types/index.ts
index 2adb0d7794159..87ef810682f60 100644
--- a/src/plugins/expressions/public/types/index.ts
+++ b/src/plugins/expressions/public/types/index.ts
@@ -17,13 +17,13 @@
* under the License.
*/
-import { Filter } from '@kbn/es-query';
import { ExpressionInterpret } from '../interpreter_provider';
import { TimeRange } from '../../../data/public';
import { Adapters } from '../../../inspector/public';
import { Query } from '../../../data/public';
import { ExpressionAST } from '../../../expressions/public';
import { ExpressionArgAST } from '../../../../plugins/expressions/public';
+import { esFilters } from '../../../../plugins/data/public';
export { ArgumentType } from './arguments';
export {
@@ -76,7 +76,7 @@ export type Context = object;
export interface SearchContext {
type: 'kibana_context';
- filters?: Filter[];
+ filters?: esFilters.Filter[];
query?: Query;
timeRange?: TimeRange;
}
@@ -91,6 +91,7 @@ export interface IExpressionLoaderParams {
customFunctions?: [];
customRenderers?: [];
extraHandlers?: Record;
+ inspectorAdapters?: Adapters;
}
export interface IInterpreterHandlers {
diff --git a/src/plugins/kibana_react/public/context/context.tsx b/src/plugins/kibana_react/public/context/context.tsx
index cbae5c4638ca2..cbf2ad07b463e 100644
--- a/src/plugins/kibana_react/public/context/context.tsx
+++ b/src/plugins/kibana_react/public/context/context.tsx
@@ -32,12 +32,11 @@ const defaultContextValue = {
export const context = createContext>(defaultContextValue);
-export const useKibana = (): KibanaReactContextValue<
- KibanaServices & Extra
-> =>
- useContext((context as unknown) as React.Context<
- KibanaReactContextValue