mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 01:38:56 -04:00
[Kuery] Remove Angular dependencies (#17836)
* [kuery] Remove `byName` dependency * Remove $http from kuery * Fix test * Add request headers * Replace byName with getFieldByName; add isFilterable * Replace Angular mock with static mock * Update index pattern for query bar * manually attach format.convert method to field * Use KBN_FIELD_TYPES to determine isFilterable * Bump yarn.lock file * Add kfetch (Kibana fetch) * Moved `getFromLegacyIndexPattern` to static index pattern functions * Fix tests * Mock out kfetch * Move value formatting from getRangeScript to buildRangeFilter * Remove getFieldByName (over abstraction) * Split kfetch options into two
This commit is contained in:
parent
2bcb0d2975
commit
f1380e3ac5
39 changed files with 684 additions and 250 deletions
|
@ -121,6 +121,7 @@
|
|||
"even-better": "7.0.2",
|
||||
"expiry-js": "0.1.7",
|
||||
"extract-text-webpack-plugin": "3.0.1",
|
||||
"fetch-mock": "^5.13.1",
|
||||
"file-loader": "1.1.4",
|
||||
"font-awesome": "4.4.0",
|
||||
"glob": "5.0.13",
|
||||
|
|
|
@ -1,5 +1,21 @@
|
|||
import _ from 'lodash';
|
||||
const OPERANDS_IN_RANGE = 2;
|
||||
const operators = {
|
||||
gt: '>',
|
||||
gte: '>=',
|
||||
lte: '<=',
|
||||
lt: '<',
|
||||
};
|
||||
const comparators = {
|
||||
gt: 'boolean gt(Supplier s, def v) {return s.get() > v}',
|
||||
gte: 'boolean gte(Supplier s, def v) {return s.get() >= v}',
|
||||
lte: 'boolean lte(Supplier s, def v) {return s.get() <= v}',
|
||||
lt: 'boolean lt(Supplier s, def v) {return s.get() < v}',
|
||||
};
|
||||
|
||||
function formatValue(field, params) {
|
||||
return _.map(params, (val, key) => operators[key] + field.format.convert(val)).join(' ');
|
||||
}
|
||||
|
||||
export function buildRangeFilter(field, params, indexPattern, formattedValue) {
|
||||
const filter = { meta: { index: indexPattern.id } };
|
||||
|
@ -29,6 +45,8 @@ export function buildRangeFilter(field, params, indexPattern, formattedValue) {
|
|||
filter.meta.field = field.name;
|
||||
} else if (field.scripted) {
|
||||
filter.script = getRangeScript(field, params);
|
||||
filter.script.script.params.value = formatValue(field, filter.script.script.params);
|
||||
|
||||
filter.meta.field = field.name;
|
||||
} else {
|
||||
filter.range = {};
|
||||
|
@ -39,19 +57,6 @@ export function buildRangeFilter(field, params, indexPattern, formattedValue) {
|
|||
}
|
||||
|
||||
export function getRangeScript(field, params) {
|
||||
const operators = {
|
||||
gt: '>',
|
||||
gte: '>=',
|
||||
lte: '<=',
|
||||
lt: '<',
|
||||
};
|
||||
const comparators = {
|
||||
gt: 'boolean gt(Supplier s, def v) {return s.get() > v}',
|
||||
gte: 'boolean gte(Supplier s, def v) {return s.get() >= v}',
|
||||
lte: 'boolean lte(Supplier s, def v) {return s.get() <= v}',
|
||||
lt: 'boolean lt(Supplier s, def v) {return s.get() < v}',
|
||||
};
|
||||
|
||||
const knownParams = _.pick(params, (val, key) => {
|
||||
return key in operators;
|
||||
});
|
||||
|
@ -70,17 +75,10 @@ export function getRangeScript(field, params) {
|
|||
script = `${currentComparators}${comparisons}`;
|
||||
}
|
||||
|
||||
const value = _.map(knownParams, function (val, key) {
|
||||
return operators[key] + field.format.convert(val);
|
||||
}).join(' ');
|
||||
|
||||
return {
|
||||
script: {
|
||||
inline: script,
|
||||
params: {
|
||||
...knownParams,
|
||||
value,
|
||||
},
|
||||
params: knownParams,
|
||||
lang: field.lang
|
||||
}
|
||||
};
|
||||
|
|
|
@ -1,2 +1,4 @@
|
|||
export { IndexPatternsProvider } from './index_patterns';
|
||||
export { IndexPatternsApiClientProvider } from './index_patterns_api_client_provider';
|
||||
export {
|
||||
IndexPatternsApiClientProvider,
|
||||
} from './index_patterns_api_client_provider';
|
||||
|
|
26
src/ui/public/index_patterns/static_utils/__tests__/index.js
Normal file
26
src/ui/public/index_patterns/static_utils/__tests__/index.js
Normal file
|
@ -0,0 +1,26 @@
|
|||
import expect from 'expect.js';
|
||||
import { isFilterable } from '../index';
|
||||
|
||||
describe('static utils', () => {
|
||||
describe('isFilterable', () => {
|
||||
it('should be filterable', () => {
|
||||
['string', 'number', 'date', 'ip', 'boolean'].forEach(type => {
|
||||
expect(isFilterable({ type })).to.be(true);
|
||||
});
|
||||
});
|
||||
|
||||
it('should not be filterable', () => {
|
||||
[
|
||||
'geo_point',
|
||||
'geo_shape',
|
||||
'attachment',
|
||||
'murmur3',
|
||||
'_source',
|
||||
'unknown',
|
||||
'conflict',
|
||||
].forEach(type => {
|
||||
expect(isFilterable({ type })).to.be(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
23
src/ui/public/index_patterns/static_utils/index.js
Normal file
23
src/ui/public/index_patterns/static_utils/index.js
Normal file
|
@ -0,0 +1,23 @@
|
|||
import { KBN_FIELD_TYPES } from '../../../../utils/kbn_field_types';
|
||||
|
||||
const filterableTypes = KBN_FIELD_TYPES.filter(type => type.filterable).map(
|
||||
type => type.name
|
||||
);
|
||||
|
||||
export function isFilterable(field) {
|
||||
return filterableTypes.includes(field.type);
|
||||
}
|
||||
|
||||
export function getFromSavedObject(savedObject) {
|
||||
return {
|
||||
fields: JSON.parse(savedObject.attributes.fields),
|
||||
title: savedObject.attributes.title,
|
||||
};
|
||||
}
|
||||
|
||||
export function getFromLegacyIndexPattern(indexPatterns) {
|
||||
return indexPatterns.map(indexPattern => ({
|
||||
fields: indexPattern.fields.raw,
|
||||
title: indexPattern.title,
|
||||
}));
|
||||
}
|
47
src/ui/public/kfetch/index.js
Normal file
47
src/ui/public/kfetch/index.js
Normal file
|
@ -0,0 +1,47 @@
|
|||
import 'isomorphic-fetch';
|
||||
import url from 'url';
|
||||
import chrome from '../chrome';
|
||||
import { metadata } from '../metadata';
|
||||
import { merge } from 'lodash';
|
||||
|
||||
class FetchError extends Error {
|
||||
constructor(res) {
|
||||
super(res.statusText);
|
||||
this.res = res;
|
||||
Error.captureStackTrace(this, FetchError);
|
||||
}
|
||||
}
|
||||
|
||||
export async function kfetch(fetchOptions, kibanaOptions) {
|
||||
// fetch specific options with defaults
|
||||
const { pathname, query, ...combinedFetchOptions } = merge(
|
||||
{
|
||||
method: 'GET',
|
||||
credentials: 'same-origin',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'kbn-version': metadata.version,
|
||||
},
|
||||
},
|
||||
fetchOptions
|
||||
);
|
||||
|
||||
// kibana specific options with defaults
|
||||
const combinedKibanaOptions = {
|
||||
prependBasePath: true,
|
||||
...kibanaOptions,
|
||||
};
|
||||
|
||||
const fullUrl = url.format({
|
||||
pathname: combinedKibanaOptions.prependBasePath ? chrome.addBasePath(pathname) : pathname,
|
||||
query,
|
||||
});
|
||||
|
||||
const res = await fetch(fullUrl, combinedFetchOptions);
|
||||
|
||||
if (!res.ok) {
|
||||
throw new FetchError(res);
|
||||
}
|
||||
|
||||
return res.json();
|
||||
}
|
98
src/ui/public/kfetch/index.test.js
Normal file
98
src/ui/public/kfetch/index.test.js
Normal file
|
@ -0,0 +1,98 @@
|
|||
import fetchMock from 'fetch-mock';
|
||||
import { kfetch } from './index';
|
||||
|
||||
jest.mock('../chrome', () => ({
|
||||
addBasePath: path => `myBase/${path}`,
|
||||
}));
|
||||
jest.mock('../metadata', () => ({
|
||||
metadata: {
|
||||
version: 'my-version',
|
||||
},
|
||||
}));
|
||||
|
||||
describe('kfetch', () => {
|
||||
const matcherName = /my\/path/;
|
||||
|
||||
describe('resolves', () => {
|
||||
beforeEach(() =>
|
||||
fetchMock.get({
|
||||
matcher: matcherName,
|
||||
response: new Response(JSON.stringify({ foo: 'bar' })),
|
||||
}));
|
||||
afterEach(() => fetchMock.restore());
|
||||
|
||||
it('should return response', async () => {
|
||||
expect(await kfetch({ pathname: 'my/path', query: { a: 'b' } })).toEqual({
|
||||
foo: 'bar',
|
||||
});
|
||||
});
|
||||
|
||||
it('should prepend with basepath by default', async () => {
|
||||
await kfetch({ pathname: 'my/path', query: { a: 'b' } });
|
||||
expect(fetchMock.lastUrl(matcherName)).toBe('myBase/my/path?a=b');
|
||||
});
|
||||
|
||||
it('should not prepend with basepath when disabled', async () => {
|
||||
await kfetch(
|
||||
{
|
||||
pathname: 'my/path',
|
||||
query: { a: 'b' },
|
||||
},
|
||||
{
|
||||
prependBasePath: false,
|
||||
}
|
||||
);
|
||||
|
||||
expect(fetchMock.lastUrl(matcherName)).toBe('my/path?a=b');
|
||||
});
|
||||
|
||||
it('should call with default options', async () => {
|
||||
await kfetch({ pathname: 'my/path', query: { a: 'b' } });
|
||||
|
||||
expect(fetchMock.lastOptions(matcherName)).toEqual({
|
||||
method: 'GET',
|
||||
credentials: 'same-origin',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'kbn-version': 'my-version',
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('should merge headers', async () => {
|
||||
await kfetch({
|
||||
pathname: 'my/path',
|
||||
query: { a: 'b' },
|
||||
headers: { myHeader: 'foo' },
|
||||
});
|
||||
expect(fetchMock.lastOptions(matcherName).headers).toEqual({
|
||||
'Content-Type': 'application/json',
|
||||
'kbn-version': 'my-version',
|
||||
myHeader: 'foo',
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('rejects', () => {
|
||||
beforeEach(() => {
|
||||
fetchMock.get({
|
||||
matcher: matcherName,
|
||||
response: {
|
||||
status: 404,
|
||||
},
|
||||
});
|
||||
});
|
||||
afterEach(() => fetchMock.restore());
|
||||
|
||||
it('should throw custom error containing response object', () => {
|
||||
return kfetch({
|
||||
pathname: 'my/path',
|
||||
query: { a: 'b' }
|
||||
}).catch(e => {
|
||||
expect(e.message).toBe('Not Found');
|
||||
expect(e.res.status).toBe(404);
|
||||
expect(e.res.url).toBe('myBase/my/path?a=b');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
256
src/ui/public/kuery/__tests__/index_pattern_response.json
Normal file
256
src/ui/public/kuery/__tests__/index_pattern_response.json
Normal file
|
@ -0,0 +1,256 @@
|
|||
{
|
||||
"title": "logstash-*",
|
||||
"fields": [
|
||||
{
|
||||
"name": "bytes",
|
||||
"type": "number",
|
||||
"count": 10,
|
||||
"scripted": false,
|
||||
"searchable": true,
|
||||
"aggregatable": true,
|
||||
"readFromDocValues": true
|
||||
},
|
||||
{
|
||||
"name": "ssl",
|
||||
"type": "boolean",
|
||||
"count": 20,
|
||||
"scripted": false,
|
||||
"searchable": true,
|
||||
"aggregatable": true,
|
||||
"readFromDocValues": true
|
||||
},
|
||||
{
|
||||
"name": "@timestamp",
|
||||
"type": "date",
|
||||
"count": 30,
|
||||
"scripted": false,
|
||||
"searchable": true,
|
||||
"aggregatable": true,
|
||||
"readFromDocValues": true
|
||||
},
|
||||
{
|
||||
"name": "time",
|
||||
"type": "date",
|
||||
"count": 30,
|
||||
"scripted": false,
|
||||
"searchable": true,
|
||||
"aggregatable": true,
|
||||
"readFromDocValues": true
|
||||
},
|
||||
{
|
||||
"name": "@tags",
|
||||
"type": "string",
|
||||
"count": 0,
|
||||
"scripted": false,
|
||||
"searchable": true,
|
||||
"aggregatable": true,
|
||||
"readFromDocValues": true
|
||||
},
|
||||
{
|
||||
"name": "utc_time",
|
||||
"type": "date",
|
||||
"count": 0,
|
||||
"scripted": false,
|
||||
"searchable": true,
|
||||
"aggregatable": true,
|
||||
"readFromDocValues": true
|
||||
},
|
||||
{
|
||||
"name": "phpmemory",
|
||||
"type": "number",
|
||||
"count": 0,
|
||||
"scripted": false,
|
||||
"searchable": true,
|
||||
"aggregatable": true,
|
||||
"readFromDocValues": true
|
||||
},
|
||||
{
|
||||
"name": "ip",
|
||||
"type": "ip",
|
||||
"count": 0,
|
||||
"scripted": false,
|
||||
"searchable": true,
|
||||
"aggregatable": true,
|
||||
"readFromDocValues": true
|
||||
},
|
||||
{
|
||||
"name": "request_body",
|
||||
"type": "attachment",
|
||||
"count": 0,
|
||||
"scripted": false,
|
||||
"searchable": true,
|
||||
"aggregatable": true,
|
||||
"readFromDocValues": true
|
||||
},
|
||||
{
|
||||
"name": "point",
|
||||
"type": "geo_point",
|
||||
"count": 0,
|
||||
"scripted": false,
|
||||
"searchable": true,
|
||||
"aggregatable": true,
|
||||
"readFromDocValues": true
|
||||
},
|
||||
{
|
||||
"name": "area",
|
||||
"type": "geo_shape",
|
||||
"count": 0,
|
||||
"scripted": false,
|
||||
"searchable": true,
|
||||
"aggregatable": true,
|
||||
"readFromDocValues": true
|
||||
},
|
||||
{
|
||||
"name": "hashed",
|
||||
"type": "murmur3",
|
||||
"count": 0,
|
||||
"scripted": false,
|
||||
"searchable": true,
|
||||
"aggregatable": false,
|
||||
"readFromDocValues": false
|
||||
},
|
||||
{
|
||||
"name": "geo.coordinates",
|
||||
"type": "geo_point",
|
||||
"count": 0,
|
||||
"scripted": false,
|
||||
"searchable": true,
|
||||
"aggregatable": true,
|
||||
"readFromDocValues": true
|
||||
},
|
||||
{
|
||||
"name": "extension",
|
||||
"type": "string",
|
||||
"count": 0,
|
||||
"scripted": false,
|
||||
"searchable": true,
|
||||
"aggregatable": true,
|
||||
"readFromDocValues": true
|
||||
},
|
||||
{
|
||||
"name": "machine.os",
|
||||
"type": "string",
|
||||
"count": 0,
|
||||
"scripted": false,
|
||||
"searchable": true,
|
||||
"aggregatable": true,
|
||||
"readFromDocValues": false
|
||||
},
|
||||
{
|
||||
"name": "machine.os.raw",
|
||||
"type": "string",
|
||||
"count": 0,
|
||||
"scripted": false,
|
||||
"searchable": true,
|
||||
"aggregatable": true,
|
||||
"readFromDocValues": true
|
||||
},
|
||||
{
|
||||
"name": "geo.src",
|
||||
"type": "string",
|
||||
"count": 0,
|
||||
"scripted": false,
|
||||
"searchable": true,
|
||||
"aggregatable": true,
|
||||
"readFromDocValues": true
|
||||
},
|
||||
{
|
||||
"name": "_id",
|
||||
"type": "string",
|
||||
"count": 0,
|
||||
"scripted": false,
|
||||
"searchable": true,
|
||||
"aggregatable": true,
|
||||
"readFromDocValues": false
|
||||
},
|
||||
{
|
||||
"name": "_type",
|
||||
"type": "string",
|
||||
"count": 0,
|
||||
"scripted": false,
|
||||
"searchable": true,
|
||||
"aggregatable": true,
|
||||
"readFromDocValues": false
|
||||
},
|
||||
{
|
||||
"name": "_source",
|
||||
"type": "_source",
|
||||
"count": 0,
|
||||
"scripted": false,
|
||||
"searchable": true,
|
||||
"aggregatable": true,
|
||||
"readFromDocValues": false
|
||||
},
|
||||
{
|
||||
"name": "non-filterable",
|
||||
"type": "string",
|
||||
"count": 0,
|
||||
"scripted": false,
|
||||
"searchable": false,
|
||||
"aggregatable": true,
|
||||
"readFromDocValues": false
|
||||
},
|
||||
{
|
||||
"name": "non-sortable",
|
||||
"type": "string",
|
||||
"count": 0,
|
||||
"scripted": false,
|
||||
"searchable": false,
|
||||
"aggregatable": false,
|
||||
"readFromDocValues": false
|
||||
},
|
||||
{
|
||||
"name": "custom_user_field",
|
||||
"type": "conflict",
|
||||
"count": 0,
|
||||
"scripted": false,
|
||||
"searchable": true,
|
||||
"aggregatable": true,
|
||||
"readFromDocValues": true
|
||||
},
|
||||
{
|
||||
"name": "script string",
|
||||
"type": "string",
|
||||
"count": 0,
|
||||
"scripted": true,
|
||||
"script": "'i am a string'",
|
||||
"lang": "expression",
|
||||
"searchable": true,
|
||||
"aggregatable": true,
|
||||
"readFromDocValues": false
|
||||
},
|
||||
{
|
||||
"name": "script number",
|
||||
"type": "number",
|
||||
"count": 0,
|
||||
"scripted": true,
|
||||
"script": "1234",
|
||||
"lang": "expression",
|
||||
"searchable": true,
|
||||
"aggregatable": true,
|
||||
"readFromDocValues": false
|
||||
},
|
||||
{
|
||||
"name": "script date",
|
||||
"type": "date",
|
||||
"count": 0,
|
||||
"scripted": true,
|
||||
"script": "1234",
|
||||
"lang": "painless",
|
||||
"searchable": true,
|
||||
"aggregatable": true,
|
||||
"readFromDocValues": false
|
||||
},
|
||||
{
|
||||
"name": "script murmur3",
|
||||
"type": "murmur3",
|
||||
"count": 0,
|
||||
"scripted": true,
|
||||
"script": "1234",
|
||||
"lang": "expression",
|
||||
"searchable": true,
|
||||
"aggregatable": true,
|
||||
"readFromDocValues": false
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,8 +1,8 @@
|
|||
import * as ast from '../ast';
|
||||
import expect from 'expect.js';
|
||||
import { nodeTypes } from '../../node_types/index';
|
||||
import StubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern';
|
||||
import ngMock from 'ng_mock';
|
||||
import indexPatternResponse from '../../__tests__/index_pattern_response.json';
|
||||
|
||||
import { expectDeepEqual } from '../../../../../test_utils/expect_deep_equal.js';
|
||||
|
||||
|
||||
|
@ -16,10 +16,10 @@ let indexPattern;
|
|||
|
||||
describe('kuery AST API', function () {
|
||||
|
||||
beforeEach(ngMock.module('kibana'));
|
||||
beforeEach(ngMock.inject(function (Private) {
|
||||
indexPattern = Private(StubbedLogstashIndexPatternProvider);
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
indexPattern = indexPatternResponse;
|
||||
});
|
||||
|
||||
describe('fromLegacyKueryExpression', function () {
|
||||
|
||||
|
|
|
@ -2,8 +2,8 @@ import expect from 'expect.js';
|
|||
import * as and from '../and';
|
||||
import { nodeTypes } from '../../node_types';
|
||||
import * as ast from '../../ast';
|
||||
import StubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern';
|
||||
import ngMock from 'ng_mock';
|
||||
import indexPatternResponse from '../../__tests__/index_pattern_response.json';
|
||||
|
||||
|
||||
let indexPattern;
|
||||
|
||||
|
@ -11,13 +11,11 @@ const childNode1 = nodeTypes.function.buildNode('is', 'machine.os', 'osx');
|
|||
const childNode2 = nodeTypes.function.buildNode('is', 'extension', 'jpg');
|
||||
|
||||
describe('kuery functions', function () {
|
||||
|
||||
describe('and', function () {
|
||||
|
||||
beforeEach(ngMock.module('kibana'));
|
||||
beforeEach(ngMock.inject(function (Private) {
|
||||
indexPattern = Private(StubbedLogstashIndexPatternProvider);
|
||||
}));
|
||||
beforeEach(() => {
|
||||
indexPattern = indexPatternResponse;
|
||||
});
|
||||
|
||||
describe('buildNodeParams', function () {
|
||||
|
||||
|
@ -27,7 +25,6 @@ describe('kuery functions', function () {
|
|||
expect(actualChildNode1).to.be(childNode1);
|
||||
expect(actualChildNode2).to.be(childNode2);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('toElasticsearchQuery', function () {
|
||||
|
|
|
@ -2,22 +2,19 @@ import expect from 'expect.js';
|
|||
import * as exists from '../exists';
|
||||
import { nodeTypes } from '../../node_types';
|
||||
import _ from 'lodash';
|
||||
import StubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern';
|
||||
import ngMock from 'ng_mock';
|
||||
import indexPatternResponse from '../../__tests__/index_pattern_response.json';
|
||||
|
||||
|
||||
let indexPattern;
|
||||
|
||||
describe('kuery functions', function () {
|
||||
|
||||
describe('exists', function () {
|
||||
|
||||
beforeEach(ngMock.module('kibana'));
|
||||
beforeEach(ngMock.inject(function (Private) {
|
||||
indexPattern = Private(StubbedLogstashIndexPatternProvider);
|
||||
}));
|
||||
beforeEach(() => {
|
||||
indexPattern = indexPatternResponse;
|
||||
});
|
||||
|
||||
describe('buildNodeParams', function () {
|
||||
|
||||
it('should return a single "arguments" param', function () {
|
||||
const result = exists.buildNodeParams('response');
|
||||
expect(result).to.only.have.key('arguments');
|
||||
|
@ -28,11 +25,9 @@ describe('kuery functions', function () {
|
|||
expect(arg).to.have.property('type', 'literal');
|
||||
expect(arg).to.have.property('value', 'response');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('toElasticsearchQuery', function () {
|
||||
|
||||
it('should return an ES exists query', function () {
|
||||
const expected = {
|
||||
exists: { field: 'response' }
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
import expect from 'expect.js';
|
||||
import * as geoBoundingBox from '../geo_bounding_box';
|
||||
import { nodeTypes } from '../../node_types';
|
||||
import StubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern';
|
||||
import ngMock from 'ng_mock';
|
||||
import indexPatternResponse from '../../__tests__/index_pattern_response.json';
|
||||
|
||||
let indexPattern;
|
||||
const params = {
|
||||
|
@ -17,13 +16,11 @@ const params = {
|
|||
};
|
||||
|
||||
describe('kuery functions', function () {
|
||||
|
||||
describe('geoBoundingBox', function () {
|
||||
|
||||
beforeEach(ngMock.module('kibana'));
|
||||
beforeEach(ngMock.inject(function (Private) {
|
||||
indexPattern = Private(StubbedLogstashIndexPatternProvider);
|
||||
}));
|
||||
beforeEach(() => {
|
||||
indexPattern = indexPatternResponse;
|
||||
});
|
||||
|
||||
describe('buildNodeParams', function () {
|
||||
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import expect from 'expect.js';
|
||||
import * as geoPolygon from '../geo_polygon';
|
||||
import { nodeTypes } from '../../node_types';
|
||||
import StubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern';
|
||||
import ngMock from 'ng_mock';
|
||||
import indexPatternResponse from '../../__tests__/index_pattern_response.json';
|
||||
|
||||
|
||||
let indexPattern;
|
||||
const points = [
|
||||
|
@ -24,10 +24,10 @@ describe('kuery functions', function () {
|
|||
|
||||
describe('geoPolygon', function () {
|
||||
|
||||
beforeEach(ngMock.module('kibana'));
|
||||
beforeEach(ngMock.inject(function (Private) {
|
||||
indexPattern = Private(StubbedLogstashIndexPatternProvider);
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
indexPattern = indexPatternResponse;
|
||||
});
|
||||
|
||||
describe('buildNodeParams', function () {
|
||||
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import expect from 'expect.js';
|
||||
import * as is from '../is';
|
||||
import { nodeTypes } from '../../node_types';
|
||||
import StubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern';
|
||||
import ngMock from 'ng_mock';
|
||||
import indexPatternResponse from '../../__tests__/index_pattern_response.json';
|
||||
|
||||
import { expectDeepEqual } from '../../../../../test_utils/expect_deep_equal';
|
||||
|
||||
let indexPattern;
|
||||
|
@ -11,10 +11,10 @@ describe('kuery functions', function () {
|
|||
|
||||
describe('is', function () {
|
||||
|
||||
beforeEach(ngMock.module('kibana'));
|
||||
beforeEach(ngMock.inject(function (Private) {
|
||||
indexPattern = Private(StubbedLogstashIndexPatternProvider);
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
indexPattern = indexPatternResponse;
|
||||
});
|
||||
|
||||
describe('buildNodeParams', function () {
|
||||
|
||||
|
|
|
@ -2,8 +2,8 @@ import expect from 'expect.js';
|
|||
import * as not from '../not';
|
||||
import { nodeTypes } from '../../node_types';
|
||||
import * as ast from '../../ast';
|
||||
import StubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern';
|
||||
import ngMock from 'ng_mock';
|
||||
import indexPatternResponse from '../../__tests__/index_pattern_response.json';
|
||||
|
||||
|
||||
let indexPattern;
|
||||
|
||||
|
@ -13,10 +13,10 @@ describe('kuery functions', function () {
|
|||
|
||||
describe('not', function () {
|
||||
|
||||
beforeEach(ngMock.module('kibana'));
|
||||
beforeEach(ngMock.inject(function (Private) {
|
||||
indexPattern = Private(StubbedLogstashIndexPatternProvider);
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
indexPattern = indexPatternResponse;
|
||||
});
|
||||
|
||||
describe('buildNodeParams', function () {
|
||||
|
||||
|
|
|
@ -2,8 +2,8 @@ import expect from 'expect.js';
|
|||
import * as or from '../or';
|
||||
import { nodeTypes } from '../../node_types';
|
||||
import * as ast from '../../ast';
|
||||
import StubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern';
|
||||
import ngMock from 'ng_mock';
|
||||
import indexPatternResponse from '../../__tests__/index_pattern_response.json';
|
||||
|
||||
|
||||
let indexPattern;
|
||||
|
||||
|
@ -14,10 +14,10 @@ describe('kuery functions', function () {
|
|||
|
||||
describe('or', function () {
|
||||
|
||||
beforeEach(ngMock.module('kibana'));
|
||||
beforeEach(ngMock.inject(function (Private) {
|
||||
indexPattern = Private(StubbedLogstashIndexPatternProvider);
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
indexPattern = indexPatternResponse;
|
||||
});
|
||||
|
||||
describe('buildNodeParams', function () {
|
||||
|
||||
|
|
|
@ -2,8 +2,8 @@ import expect from 'expect.js';
|
|||
import { expectDeepEqual } from '../../../../../test_utils/expect_deep_equal';
|
||||
import * as range from '../range';
|
||||
import { nodeTypes } from '../../node_types';
|
||||
import StubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern';
|
||||
import ngMock from 'ng_mock';
|
||||
import indexPatternResponse from '../../__tests__/index_pattern_response.json';
|
||||
|
||||
|
||||
let indexPattern;
|
||||
|
||||
|
@ -11,10 +11,10 @@ describe('kuery functions', function () {
|
|||
|
||||
describe('range', function () {
|
||||
|
||||
beforeEach(ngMock.module('kibana'));
|
||||
beforeEach(ngMock.inject(function (Private) {
|
||||
indexPattern = Private(StubbedLogstashIndexPatternProvider);
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
indexPattern = indexPatternResponse;
|
||||
});
|
||||
|
||||
describe('buildNodeParams', function () {
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { getFields } from '../../utils/get_fields';
|
||||
import expect from 'expect.js';
|
||||
import StubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern';
|
||||
import ngMock from 'ng_mock';
|
||||
import indexPatternResponse from '../../../__tests__/index_pattern_response.json';
|
||||
|
||||
import { nodeTypes } from '../../..';
|
||||
import { expectDeepEqual } from '../../../../../../test_utils/expect_deep_equal';
|
||||
|
||||
|
@ -9,10 +9,10 @@ let indexPattern;
|
|||
|
||||
describe('getFields', function () {
|
||||
|
||||
beforeEach(ngMock.module('kibana'));
|
||||
beforeEach(ngMock.inject(function (Private) {
|
||||
indexPattern = Private(StubbedLogstashIndexPatternProvider);
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
indexPattern = indexPatternResponse;
|
||||
});
|
||||
|
||||
describe('field names without a wildcard', function () {
|
||||
|
||||
|
@ -34,13 +34,11 @@ describe('getFields', function () {
|
|||
it('should not match a wildcard in a literal node', function () {
|
||||
const indexPatternWithWildField = {
|
||||
title: 'wildIndex',
|
||||
fields: {
|
||||
byName: {
|
||||
'foo*': {
|
||||
name: 'foo*'
|
||||
}
|
||||
}
|
||||
}
|
||||
fields: [
|
||||
{
|
||||
name: 'foo*',
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const fieldNameNode = nodeTypes.literal.buildNode('foo*');
|
||||
|
|
|
@ -9,7 +9,7 @@ export function buildNodeParams(fieldName) {
|
|||
export function toElasticsearchQuery(node, indexPattern) {
|
||||
const { arguments: [ fieldNameArg ] } = node;
|
||||
const fieldName = literal.toElasticsearchQuery(fieldNameArg);
|
||||
const field = indexPattern.fields.byName[fieldName];
|
||||
const field = indexPattern.fields.find(field => field.name === fieldName);
|
||||
|
||||
if (field && field.scripted) {
|
||||
throw new Error(`Exists query does not support scripted fields`);
|
||||
|
|
|
@ -18,7 +18,7 @@ export function buildNodeParams(fieldName, params) {
|
|||
export function toElasticsearchQuery(node, indexPattern) {
|
||||
const [ fieldNameArg, ...args ] = node.arguments;
|
||||
const fieldName = nodeTypes.literal.toElasticsearchQuery(fieldNameArg);
|
||||
const field = indexPattern.fields.byName[fieldName];
|
||||
const field = indexPattern.fields.find(field => field.name === fieldName);
|
||||
const queryParams = args.reduce((acc, arg) => {
|
||||
const snakeArgName = _.snakeCase(arg.name);
|
||||
return {
|
||||
|
|
|
@ -16,7 +16,7 @@ export function buildNodeParams(fieldName, points) {
|
|||
export function toElasticsearchQuery(node, indexPattern) {
|
||||
const [ fieldNameArg, ...points ] = node.arguments;
|
||||
const fieldName = nodeTypes.literal.toElasticsearchQuery(fieldNameArg);
|
||||
const field = indexPattern.fields.byName[fieldName];
|
||||
const field = indexPattern.fields.find(field => field.name === fieldName);
|
||||
const queryParams = {
|
||||
points: points.map(ast.toElasticsearchQuery)
|
||||
};
|
||||
|
|
|
@ -38,9 +38,7 @@ export function toElasticsearchQuery(node, indexPattern) {
|
|||
const queries = fields.map((field) => {
|
||||
if (field.scripted) {
|
||||
return {
|
||||
script: {
|
||||
...getRangeScript(field, queryParams)
|
||||
}
|
||||
script: getRangeScript(field, queryParams),
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ import * as wildcard from '../../node_types/wildcard';
|
|||
export function getFields(node, indexPattern) {
|
||||
if (node.type === 'literal') {
|
||||
const fieldName = literal.toElasticsearchQuery(node);
|
||||
const field = indexPattern.fields.byName[fieldName];
|
||||
const field = indexPattern.fields.find(field => field.name === fieldName);
|
||||
if (!field) {
|
||||
return [];
|
||||
}
|
||||
|
|
|
@ -3,8 +3,8 @@ import _ from 'lodash';
|
|||
import expect from 'expect.js';
|
||||
import { expectDeepEqual } from '../../../../../test_utils/expect_deep_equal.js';
|
||||
import * as isFunction from '../../functions/is';
|
||||
import StubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern';
|
||||
import ngMock from 'ng_mock';
|
||||
import indexPatternResponse from '../../__tests__/index_pattern_response.json';
|
||||
|
||||
import { nodeTypes } from '../../node_types';
|
||||
|
||||
describe('kuery node types', function () {
|
||||
|
@ -13,10 +13,10 @@ describe('kuery node types', function () {
|
|||
|
||||
let indexPattern;
|
||||
|
||||
beforeEach(ngMock.module('kibana'));
|
||||
beforeEach(ngMock.inject(function (Private) {
|
||||
indexPattern = Private(StubbedLogstashIndexPatternProvider);
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
indexPattern = indexPatternResponse;
|
||||
});
|
||||
|
||||
describe('buildNode', function () {
|
||||
|
||||
|
|
|
@ -1,19 +1,18 @@
|
|||
import expect from 'expect.js';
|
||||
import ngMock from 'ng_mock';
|
||||
import { getSuggestionsProvider } from '../field';
|
||||
import StubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern';
|
||||
import indexPatternResponse from '../../__tests__/index_pattern_response.json';
|
||||
import { isFilterable } from '../../../index_patterns/static_utils';
|
||||
|
||||
describe('Kuery field suggestions', function () {
|
||||
let indexPattern;
|
||||
let indexPatterns;
|
||||
let getSuggestions;
|
||||
|
||||
beforeEach(ngMock.module('kibana'));
|
||||
beforeEach(ngMock.inject(function (Private) {
|
||||
indexPattern = Private(StubbedLogstashIndexPatternProvider);
|
||||
beforeEach(() => {
|
||||
indexPattern = indexPatternResponse;
|
||||
indexPatterns = [indexPattern];
|
||||
getSuggestions = getSuggestionsProvider({ indexPatterns });
|
||||
}));
|
||||
});
|
||||
|
||||
it('should return a function', function () {
|
||||
expect(typeof getSuggestions).to.be('function');
|
||||
|
@ -23,7 +22,7 @@ describe('Kuery field suggestions', function () {
|
|||
const prefix = '';
|
||||
const suffix = '';
|
||||
const suggestions = getSuggestions({ prefix, suffix });
|
||||
const filterableFields = indexPattern.fields.filter(field => field.filterable);
|
||||
const filterableFields = indexPattern.fields.filter(isFilterable);
|
||||
expect(suggestions.length).to.be(filterableFields.length);
|
||||
});
|
||||
|
||||
|
|
|
@ -1,17 +1,15 @@
|
|||
import expect from 'expect.js';
|
||||
import ngMock from 'ng_mock';
|
||||
import { getSuggestionsProvider } from '../operator';
|
||||
import StubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern';
|
||||
import indexPatternResponse from '../../__tests__/index_pattern_response.json';
|
||||
|
||||
describe('Kuery operator suggestions', function () {
|
||||
let indexPatterns;
|
||||
let getSuggestions;
|
||||
|
||||
beforeEach(ngMock.module('kibana'));
|
||||
beforeEach(ngMock.inject(function (Private) {
|
||||
indexPatterns = [Private(StubbedLogstashIndexPatternProvider)];
|
||||
beforeEach(() => {
|
||||
indexPatterns = [indexPatternResponse];
|
||||
getSuggestions = getSuggestionsProvider({ indexPatterns });
|
||||
}));
|
||||
});
|
||||
|
||||
it('should return a function', function () {
|
||||
expect(typeof getSuggestions).to.be('function');
|
||||
|
|
|
@ -1,26 +1,26 @@
|
|||
import expect from 'expect.js';
|
||||
import sinon from 'sinon';
|
||||
import ngMock from 'ng_mock';
|
||||
import fetchMock from 'fetch-mock';
|
||||
import { getSuggestionsProvider } from '../value';
|
||||
import StubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern';
|
||||
import indexPatternResponse from '../../__tests__/index_pattern_response.json';
|
||||
|
||||
describe('Kuery value suggestions', function () {
|
||||
let $http;
|
||||
let config;
|
||||
let indexPatterns;
|
||||
let getSuggestions;
|
||||
|
||||
const mockValues = ['foo', 'bar'];
|
||||
const fetchUrlMatcher = /\/api\/kibana\/suggestions\/values\/*/;
|
||||
|
||||
beforeEach(ngMock.module('kibana'));
|
||||
beforeEach(() => fetchMock.post(fetchUrlMatcher, mockValues));
|
||||
afterEach(() => fetchMock.restore());
|
||||
|
||||
describe('with config setting turned off', () => {
|
||||
beforeEach(ngMock.inject(function (Private) {
|
||||
$http = getHttpStub(false, mockValues);
|
||||
beforeEach(() => {
|
||||
config = getConfigStub(false);
|
||||
indexPatterns = [Private(StubbedLogstashIndexPatternProvider)];
|
||||
getSuggestions = getSuggestionsProvider({ $http, config, indexPatterns });
|
||||
}));
|
||||
indexPatterns = [indexPatternResponse];
|
||||
getSuggestions = getSuggestionsProvider({ config, indexPatterns });
|
||||
});
|
||||
|
||||
it('should return a function', function () {
|
||||
expect(typeof getSuggestions).to.be('function');
|
||||
|
@ -31,18 +31,17 @@ describe('Kuery value suggestions', function () {
|
|||
const prefix = '';
|
||||
const suffix = '';
|
||||
const suggestions = await getSuggestions({ fieldName, prefix, suffix });
|
||||
sinon.assert.notCalled($http.post);
|
||||
expect(fetchMock.called(fetchUrlMatcher)).to.be(false);
|
||||
expect(suggestions).to.eql([]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('with config setting turned on', () => {
|
||||
beforeEach(ngMock.inject(function (Private) {
|
||||
$http = getHttpStub(false, mockValues);
|
||||
beforeEach(() => {
|
||||
config = getConfigStub(true);
|
||||
indexPatterns = [Private(StubbedLogstashIndexPatternProvider)];
|
||||
getSuggestions = getSuggestionsProvider({ $http, config, indexPatterns });
|
||||
}));
|
||||
indexPatterns = [indexPatternResponse];
|
||||
getSuggestions = getSuggestionsProvider({ config, indexPatterns });
|
||||
});
|
||||
|
||||
it('should return a function', function () {
|
||||
expect(typeof getSuggestions).to.be('function');
|
||||
|
@ -64,20 +63,12 @@ describe('Kuery value suggestions', function () {
|
|||
expect(suggestions.map(({ text }) => text)).to.eql(['false ']);
|
||||
});
|
||||
|
||||
it('should return boolean suggestions for boolean fields', async () => {
|
||||
const fieldName = 'ssl';
|
||||
const prefix = '';
|
||||
const suffix = '';
|
||||
const suggestions = await getSuggestions({ fieldName, prefix, suffix });
|
||||
expect(suggestions.map(({ text }) => text)).to.eql(['true ', 'false ']);
|
||||
});
|
||||
|
||||
it('should not make a request for non-aggregatable fields', async () => {
|
||||
const fieldName = 'non-sortable';
|
||||
const prefix = '';
|
||||
const suffix = '';
|
||||
const suggestions = await getSuggestions({ fieldName, prefix, suffix });
|
||||
sinon.assert.notCalled($http.post);
|
||||
expect(fetchMock.called(fetchUrlMatcher)).to.be(false);
|
||||
expect(suggestions).to.eql([]);
|
||||
});
|
||||
|
||||
|
@ -86,7 +77,7 @@ describe('Kuery value suggestions', function () {
|
|||
const prefix = '';
|
||||
const suffix = '';
|
||||
const suggestions = await getSuggestions({ fieldName, prefix, suffix });
|
||||
sinon.assert.notCalled($http.post);
|
||||
expect(fetchMock.called(fetchUrlMatcher)).to.be(false);
|
||||
expect(suggestions).to.eql([]);
|
||||
});
|
||||
|
||||
|
@ -95,7 +86,18 @@ describe('Kuery value suggestions', function () {
|
|||
const prefix = '';
|
||||
const suffix = '';
|
||||
const suggestions = await getSuggestions({ fieldName, prefix, suffix });
|
||||
sinon.assert.calledOnce($http.post);
|
||||
|
||||
const lastCall = fetchMock.lastCall(fetchUrlMatcher, 'POST');
|
||||
expect(lastCall[0]).to.eql('/api/kibana/suggestions/values/logstash-*');
|
||||
expect(lastCall[1]).to.eql({
|
||||
method: 'POST',
|
||||
body: '{"query":"","field":"machine.os.raw"}',
|
||||
credentials: 'same-origin',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'kbn-version': '1.2.3',
|
||||
},
|
||||
});
|
||||
expect(suggestions.map(({ text }) => text)).to.eql(['"foo" ', '"bar" ']);
|
||||
});
|
||||
|
||||
|
@ -116,8 +118,3 @@ function getConfigStub(suggestValues) {
|
|||
const get = sinon.stub().returns(suggestValues);
|
||||
return { get };
|
||||
}
|
||||
|
||||
function getHttpStub(reject, data) {
|
||||
const post = sinon.stub().returns(reject ? Promise.reject() : Promise.resolve({ data }));
|
||||
return { post };
|
||||
}
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
import { escape, flatten } from 'lodash';
|
||||
import { escapeKuery } from './escape_kuery';
|
||||
import { sortPrefixFirst } from '../../utils/sort_prefix_first';
|
||||
import { isFilterable } from '../../index_patterns/static_utils';
|
||||
|
||||
|
||||
const type = 'field';
|
||||
|
||||
|
@ -9,10 +11,10 @@ function getDescription(fieldName) {
|
|||
}
|
||||
|
||||
export function getSuggestionsProvider({ indexPatterns }) {
|
||||
const allFields = flatten(indexPatterns.map(indexPattern => indexPattern.fields.raw));
|
||||
const allFields = flatten(indexPatterns.map(indexPattern => indexPattern.fields));
|
||||
return function getFieldSuggestions({ start, end, prefix, suffix }) {
|
||||
const search = `${prefix}${suffix}`.toLowerCase();
|
||||
const filterableFields = allFields.filter(field => field.filterable);
|
||||
const filterableFields = allFields.filter(isFilterable);
|
||||
const fieldNames = filterableFields.map(field => field.name);
|
||||
const matchingFieldNames = fieldNames.filter(name => name.toLowerCase().includes(search));
|
||||
const sortedFieldNames = sortPrefixFirst(matchingFieldNames.sort(keywordComparator), search);
|
||||
|
|
|
@ -7,9 +7,9 @@ import { getSuggestionsProvider as conjunction } from './conjunction';
|
|||
|
||||
const cursorSymbol = '@kuery-cursor@';
|
||||
|
||||
export function getSuggestionsProvider({ $http, config, indexPatterns }) {
|
||||
export function getSuggestionsProvider({ config, indexPatterns }) {
|
||||
const getSuggestionsByType = mapValues({ field, value, operator, conjunction }, provider => {
|
||||
return provider({ $http, config, indexPatterns });
|
||||
return provider({ config, indexPatterns });
|
||||
});
|
||||
|
||||
return function getSuggestions({ query, selectionStart, selectionEnd }) {
|
||||
|
|
|
@ -33,7 +33,7 @@ function getDescription(operator) {
|
|||
}
|
||||
|
||||
export function getSuggestionsProvider({ indexPatterns }) {
|
||||
const allFields = flatten(indexPatterns.map(indexPattern => indexPattern.fields.raw));
|
||||
const allFields = flatten(indexPatterns.map(indexPattern => indexPattern.fields));
|
||||
return function getOperatorSuggestions({ end, fieldName }) {
|
||||
const fields = allFields.filter(field => field.name === fieldName);
|
||||
return flatten(fields.map(field => {
|
||||
|
|
|
@ -1,37 +1,59 @@
|
|||
import 'isomorphic-fetch';
|
||||
import { flatten, memoize } from 'lodash';
|
||||
import chrome from '../../chrome';
|
||||
import { escapeQuotes } from './escape_kuery';
|
||||
import { kfetch } from '../../kfetch';
|
||||
|
||||
const baseUrl = chrome.addBasePath('/api/kibana/suggestions/values');
|
||||
const type = 'value';
|
||||
|
||||
export function getSuggestionsProvider({ $http, config, indexPatterns }) {
|
||||
const allFields = flatten(indexPatterns.map(indexPattern => indexPattern.fields.raw));
|
||||
const requestSuggestions = memoize((query, field) => {
|
||||
const queryParams = { query, field: field.name };
|
||||
return $http.post(`${baseUrl}/${field.indexPattern.title}`, queryParams);
|
||||
}, resolver);
|
||||
const requestSuggestions = memoize((query, field) => {
|
||||
return kfetch({
|
||||
pathname: `/api/kibana/suggestions/values/${field.indexPatternTitle}`,
|
||||
method: 'POST',
|
||||
body: JSON.stringify({ query, field: field.name }),
|
||||
});
|
||||
}, resolver);
|
||||
|
||||
export function getSuggestionsProvider({ config, indexPatterns }) {
|
||||
const allFields = flatten(
|
||||
indexPatterns.map(indexPattern => {
|
||||
return indexPattern.fields.map(field => ({
|
||||
...field,
|
||||
indexPatternTitle: indexPattern.title,
|
||||
}));
|
||||
})
|
||||
);
|
||||
const shouldSuggestValues = config.get('filterEditor:suggestValues');
|
||||
|
||||
return function getValueSuggestions({ start, end, prefix, suffix, fieldName }) {
|
||||
return function getValueSuggestions({
|
||||
start,
|
||||
end,
|
||||
prefix,
|
||||
suffix,
|
||||
fieldName,
|
||||
}) {
|
||||
const fields = allFields.filter(field => field.name === fieldName);
|
||||
const query = `${prefix}${suffix}`;
|
||||
|
||||
const suggestionsByField = fields.map(field => {
|
||||
if (field.type === 'boolean') {
|
||||
return wrapAsSuggestions(start, end, query, ['true', 'false']);
|
||||
} else if (!shouldSuggestValues || !field.aggregatable || field.type !== 'string') {
|
||||
} else if (
|
||||
!shouldSuggestValues ||
|
||||
!field.aggregatable ||
|
||||
field.type !== 'string'
|
||||
) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return requestSuggestions(query, field).then(({ data }) => {
|
||||
return requestSuggestions(query, field).then(data => {
|
||||
const quotedValues = data.map(value => `"${escapeQuotes(value)}"`);
|
||||
return wrapAsSuggestions(start, end, query, quotedValues);
|
||||
});
|
||||
});
|
||||
|
||||
return Promise.all(suggestionsByField)
|
||||
.then(suggestions => flatten(suggestions));
|
||||
return Promise.all(suggestionsByField).then(suggestions =>
|
||||
flatten(suggestions)
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -47,5 +69,5 @@ function wrapAsSuggestions(start, end, query, values) {
|
|||
function resolver(query, field) {
|
||||
// Only cache results for a minute
|
||||
const ttl = Math.floor(Date.now() / 1000 / 60);
|
||||
return [ttl, query, field.indexPattern.title, field.name].join('|');
|
||||
return [ttl, query, field.indexPatternTitle, field.name].join('|');
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ import { getSuggestionsProvider } from '../../kuery';
|
|||
import './suggestion.less';
|
||||
import '../../directives/match_pairs';
|
||||
import './query_popover';
|
||||
import { getFromLegacyIndexPattern } from '../../index_patterns/static_utils';
|
||||
|
||||
const module = uiModules.get('kibana');
|
||||
|
||||
|
@ -114,7 +115,11 @@ module.directive('queryBar', function () {
|
|||
|
||||
$scope.$watch('queryBar.indexPatterns', () => {
|
||||
this.getIndexPatterns().then(indexPatterns => {
|
||||
this.getKuerySuggestions = getSuggestionsProvider({ $http, config, indexPatterns });
|
||||
|
||||
this.getKuerySuggestions = getSuggestionsProvider({
|
||||
config,
|
||||
indexPatterns: getFromLegacyIndexPattern(indexPatterns)
|
||||
});
|
||||
this.updateSuggestions();
|
||||
});
|
||||
});
|
||||
|
|
|
@ -17,7 +17,7 @@ export class KbnFieldType {
|
|||
}
|
||||
}
|
||||
|
||||
const KBN_FIELD_TYPES = [
|
||||
export const KBN_FIELD_TYPES = [
|
||||
new KbnFieldType({
|
||||
name: 'string',
|
||||
sortable: true,
|
||||
|
|
|
@ -43,7 +43,6 @@
|
|||
"enzyme-adapter-react-16": "^1.1.1",
|
||||
"enzyme-to-json": "3.3.1",
|
||||
"expect.js": "0.3.1",
|
||||
"fetch-mock": "5.13.1",
|
||||
"gulp": "3.9.1",
|
||||
"gulp-load-plugins": "1.2.0",
|
||||
"gulp-mocha": "2.2.0",
|
||||
|
|
9
x-pack/plugins/__mocks__/ui/kfetch.js
Normal file
9
x-pack/plugins/__mocks__/ui/kfetch.js
Normal file
|
@ -0,0 +1,9 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
export const kfetch = () => {
|
||||
return Promise.resolve('mock value');
|
||||
};
|
|
@ -6,4 +6,5 @@
|
|||
|
||||
export const metadata = {
|
||||
branch: 'my-metadata-branch',
|
||||
version: 'my-metadata-version'
|
||||
};
|
||||
|
|
|
@ -6,68 +6,52 @@
|
|||
|
||||
import 'isomorphic-fetch';
|
||||
import { camelizeKeys } from 'humps';
|
||||
import url from 'url';
|
||||
import _ from 'lodash';
|
||||
import chrome from 'ui/chrome';
|
||||
import { kfetch } from 'ui/kfetch';
|
||||
import { omit } from 'lodash';
|
||||
|
||||
async function callApi(options) {
|
||||
const { pathname, query, camelcase, compact, ...requestOptions } = {
|
||||
function removeEmpty(query) {
|
||||
return omit(query, val => val == null);
|
||||
}
|
||||
|
||||
async function callApi(fetchOptions, kibanaOptions) {
|
||||
const combinedKibanaOptions = {
|
||||
compact: true, // remove empty query args
|
||||
camelcase: true,
|
||||
credentials: 'same-origin',
|
||||
method: 'GET',
|
||||
headers: new Headers({
|
||||
'Content-Type': 'application/json',
|
||||
'kbn-xsrf': true
|
||||
}),
|
||||
...options
|
||||
...kibanaOptions
|
||||
};
|
||||
|
||||
const fullUrl = url.format({
|
||||
pathname,
|
||||
query: compact ? _.omit(query, val => val == null) : query
|
||||
});
|
||||
const combinedFetchOptions = {
|
||||
...fetchOptions,
|
||||
query: combinedKibanaOptions.compact
|
||||
? removeEmpty(fetchOptions.query)
|
||||
: fetchOptions.query
|
||||
};
|
||||
|
||||
try {
|
||||
const response = await fetch(fullUrl, requestOptions);
|
||||
const json = await response.json();
|
||||
if (!response.ok) {
|
||||
throw new Error(JSON.stringify(json, null, 4));
|
||||
}
|
||||
return camelcase ? camelizeKeys(json) : json;
|
||||
} catch (err) {
|
||||
console.error(
|
||||
'Rest request error with options:\n',
|
||||
JSON.stringify(options, null, 4),
|
||||
'\n',
|
||||
err.message,
|
||||
err.stack
|
||||
);
|
||||
throw err;
|
||||
}
|
||||
const res = await kfetch(combinedFetchOptions, combinedKibanaOptions);
|
||||
return combinedKibanaOptions.camelcase ? camelizeKeys(res) : res;
|
||||
}
|
||||
|
||||
export async function loadLicense() {
|
||||
return callApi({
|
||||
pathname: chrome.addBasePath(`/api/xpack/v1/info`)
|
||||
pathname: `/api/xpack/v1/info`
|
||||
});
|
||||
}
|
||||
|
||||
export async function loadServerStatus() {
|
||||
return callApi({
|
||||
pathname: chrome.addBasePath(`/api/apm/status/server`)
|
||||
pathname: `/api/apm/status/server`
|
||||
});
|
||||
}
|
||||
|
||||
export async function loadAgentStatus() {
|
||||
return callApi({
|
||||
pathname: chrome.addBasePath(`/api/apm/status/agent`)
|
||||
pathname: `/api/apm/status/agent`
|
||||
});
|
||||
}
|
||||
|
||||
export async function loadServiceList({ start, end }) {
|
||||
return callApi({
|
||||
pathname: chrome.addBasePath(`/api/apm/services`),
|
||||
pathname: `/api/apm/services`,
|
||||
query: {
|
||||
start,
|
||||
end
|
||||
|
@ -77,7 +61,7 @@ export async function loadServiceList({ start, end }) {
|
|||
|
||||
export async function loadServiceDetails({ start, end, serviceName }) {
|
||||
return callApi({
|
||||
pathname: chrome.addBasePath(`/api/apm/services/${serviceName}`),
|
||||
pathname: `/api/apm/services/${serviceName}`,
|
||||
query: {
|
||||
start,
|
||||
end
|
||||
|
@ -92,9 +76,7 @@ export async function loadTransactionList({
|
|||
transactionType
|
||||
}) {
|
||||
return callApi({
|
||||
pathname: chrome.addBasePath(
|
||||
`/api/apm/services/${serviceName}/transactions`
|
||||
),
|
||||
pathname: `/api/apm/services/${serviceName}/transactions`,
|
||||
query: {
|
||||
start,
|
||||
end,
|
||||
|
@ -110,9 +92,7 @@ export async function loadTransactionDistribution({
|
|||
transactionName
|
||||
}) {
|
||||
return callApi({
|
||||
pathname: chrome.addBasePath(
|
||||
`/api/apm/services/${serviceName}/transactions/distribution`
|
||||
),
|
||||
pathname: `/api/apm/services/${serviceName}/transactions/distribution`,
|
||||
query: {
|
||||
start,
|
||||
end,
|
||||
|
@ -123,9 +103,7 @@ export async function loadTransactionDistribution({
|
|||
|
||||
export async function loadSpans({ serviceName, start, end, transactionId }) {
|
||||
return callApi({
|
||||
pathname: chrome.addBasePath(
|
||||
`/api/apm/services/${serviceName}/transactions/${transactionId}/spans`
|
||||
),
|
||||
pathname: `/api/apm/services/${serviceName}/transactions/${transactionId}/spans`,
|
||||
query: {
|
||||
start,
|
||||
end
|
||||
|
@ -140,9 +118,7 @@ export async function loadTransaction({
|
|||
transactionId
|
||||
}) {
|
||||
const res = await callApi({
|
||||
pathname: chrome.addBasePath(
|
||||
`/api/apm/services/${serviceName}/transactions/${transactionId}`
|
||||
),
|
||||
pathname: `/api/apm/services/${serviceName}/transactions/${transactionId}`,
|
||||
camelcase: false,
|
||||
query: {
|
||||
start,
|
||||
|
@ -164,9 +140,7 @@ export async function loadCharts({
|
|||
transactionName
|
||||
}) {
|
||||
return callApi({
|
||||
pathname: chrome.addBasePath(
|
||||
`/api/apm/services/${serviceName}/transactions/charts`
|
||||
),
|
||||
pathname: `/api/apm/services/${serviceName}/transactions/charts`,
|
||||
query: {
|
||||
start,
|
||||
end,
|
||||
|
@ -186,7 +160,7 @@ export async function loadErrorGroupList({
|
|||
sortOrder
|
||||
}) {
|
||||
return callApi({
|
||||
pathname: chrome.addBasePath(`/api/apm/services/${serviceName}/errors`),
|
||||
pathname: `/api/apm/services/${serviceName}/errors`,
|
||||
query: {
|
||||
start,
|
||||
end,
|
||||
|
@ -205,9 +179,7 @@ export async function loadErrorGroupDetails({
|
|||
end
|
||||
}) {
|
||||
const res = await callApi({
|
||||
pathname: chrome.addBasePath(
|
||||
`/api/apm/services/${serviceName}/errors/${errorGroupId}`
|
||||
),
|
||||
pathname: `/api/apm/services/${serviceName}/errors/${errorGroupId}`,
|
||||
camelcase: false,
|
||||
query: {
|
||||
start,
|
||||
|
@ -228,9 +200,7 @@ export async function loadErrorDistribution({
|
|||
errorGroupId
|
||||
}) {
|
||||
return callApi({
|
||||
pathname: chrome.addBasePath(
|
||||
`/api/apm/services/${serviceName}/errors/${errorGroupId}/distribution`
|
||||
),
|
||||
pathname: `/api/apm/services/${serviceName}/errors/${errorGroupId}/distribution`,
|
||||
query: {
|
||||
start,
|
||||
end
|
||||
|
@ -241,7 +211,7 @@ export async function loadErrorDistribution({
|
|||
export async function createWatch(id, watch) {
|
||||
return callApi({
|
||||
method: 'PUT',
|
||||
pathname: chrome.addBasePath(`/api/watcher/watch/${id}`),
|
||||
pathname: `/api/watcher/watch/${id}`,
|
||||
body: JSON.stringify({ type: 'json', id, watch })
|
||||
});
|
||||
}
|
||||
|
|
|
@ -2533,14 +2533,6 @@ fd-slicer@~1.0.1:
|
|||
dependencies:
|
||||
pend "~1.2.0"
|
||||
|
||||
fetch-mock@5.13.1:
|
||||
version "5.13.1"
|
||||
resolved "https://registry.yarnpkg.com/fetch-mock/-/fetch-mock-5.13.1.tgz#955794a77f3d972f1644b9ace65a0fdfd60f1df7"
|
||||
dependencies:
|
||||
glob-to-regexp "^0.3.0"
|
||||
node-fetch "^1.3.3"
|
||||
path-to-regexp "^1.7.0"
|
||||
|
||||
figures@^1.3.5:
|
||||
version "1.7.0"
|
||||
resolved "https://registry.yarnpkg.com/figures/-/figures-1.7.0.tgz#cbe1e3affcf1cd44b80cadfed28dc793a9701d2e"
|
||||
|
@ -2916,10 +2908,6 @@ glob-stream@^6.1.0:
|
|||
to-absolute-glob "^2.0.0"
|
||||
unique-stream "^2.0.2"
|
||||
|
||||
glob-to-regexp@^0.3.0:
|
||||
version "0.3.0"
|
||||
resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.3.0.tgz#8c5a1494d2066c570cc3bfe4496175acc4d502ab"
|
||||
|
||||
glob-watcher@^0.0.6:
|
||||
version "0.0.6"
|
||||
resolved "https://registry.yarnpkg.com/glob-watcher/-/glob-watcher-0.0.6.tgz#b95b4a8df74b39c83298b0c05c978b4d9a3b710b"
|
||||
|
@ -5136,7 +5124,7 @@ nigel@2.x.x:
|
|||
hoek "4.x.x"
|
||||
vise "2.x.x"
|
||||
|
||||
node-fetch@^1.0.1, node-fetch@^1.3.3:
|
||||
node-fetch@^1.0.1:
|
||||
version "1.7.3"
|
||||
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-1.7.3.tgz#980f6f72d85211a5347c6b2bc18c5b84c3eb47ef"
|
||||
dependencies:
|
||||
|
|
10
yarn.lock
10
yarn.lock
|
@ -4709,6 +4709,14 @@ fd-slicer@~1.0.1:
|
|||
dependencies:
|
||||
pend "~1.2.0"
|
||||
|
||||
fetch-mock@^5.13.1:
|
||||
version "5.13.1"
|
||||
resolved "https://registry.yarnpkg.com/fetch-mock/-/fetch-mock-5.13.1.tgz#955794a77f3d972f1644b9ace65a0fdfd60f1df7"
|
||||
dependencies:
|
||||
glob-to-regexp "^0.3.0"
|
||||
node-fetch "^1.3.3"
|
||||
path-to-regexp "^1.7.0"
|
||||
|
||||
figures@^1.3.5:
|
||||
version "1.7.0"
|
||||
resolved "https://registry.yarnpkg.com/figures/-/figures-1.7.0.tgz#cbe1e3affcf1cd44b80cadfed28dc793a9701d2e"
|
||||
|
@ -8771,7 +8779,7 @@ node-fetch@1.3.2:
|
|||
dependencies:
|
||||
encoding "^0.1.11"
|
||||
|
||||
node-fetch@^1.0.1:
|
||||
node-fetch@^1.0.1, node-fetch@^1.3.3:
|
||||
version "1.7.3"
|
||||
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-1.7.3.tgz#980f6f72d85211a5347c6b2bc18c5b84c3eb47ef"
|
||||
dependencies:
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue