From f52656132e5c2f17a40008d968dfe2cd072a11b2 Mon Sep 17 00:00:00 2001 From: Joe Reuter Date: Mon, 14 Oct 2019 14:13:08 +0200 Subject: [PATCH 1/3] pass raw values and format afterwards --- .../__tests__/buckets/_date_range.js | 10 +++++++ .../buckets/create_filter/date_range.js | 8 +++-- .../buckets/create_filter/ip_range.js | 4 +-- .../buckets/create_filter/date_range.js | 15 ++++------ .../buckets/create_filter/ip_range.js | 9 +++--- .../ui/public/agg_types/buckets/date_range.js | 14 +++++---- .../ui/public/agg_types/buckets/ip_range.js | 20 +++++++++---- src/legacy/ui/public/utils/date_range.js | 26 ++++------------- src/legacy/ui/public/utils/ip_range.js | 29 +++++++++++++++++++ .../loader/pipeline_helpers/utilities.ts | 21 +++++++++++++- 10 files changed, 105 insertions(+), 51 deletions(-) create mode 100644 src/legacy/ui/public/utils/ip_range.js diff --git a/src/legacy/ui/public/agg_types/__tests__/buckets/_date_range.js b/src/legacy/ui/public/agg_types/__tests__/buckets/_date_range.js index 10ac4f3befeb7..94603dfa69a66 100644 --- a/src/legacy/ui/public/agg_types/__tests__/buckets/_date_range.js +++ b/src/legacy/ui/public/agg_types/__tests__/buckets/_date_range.js @@ -20,6 +20,7 @@ import { set } from 'lodash'; import expect from '@kbn/expect'; import sinon from 'sinon'; import ngMock from 'ng_mock'; +import { aggTypes } from '../..'; import AggParamWriterProvider from '../agg_param_writer'; import FixturesStubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern'; import chrome from '../../../chrome'; @@ -38,6 +39,15 @@ describe('date_range params', function () { timeField = indexPattern.timeFieldName; paramWriter = new AggParamWriter({ aggType: 'date_range' }); })); + + describe('getKey', () => { + const dateRange = aggTypes.buckets.find(agg => agg.name === 'date_range'); + it('should return object', () => { + const bucket = { from: 'from-date', to: 'to-date', key: 'from-dateto-date' }; + expect(dateRange.getKey(bucket)).to.equal({ from: 'from-date', to: 'to-date' }); + }); + }); + describe('time_zone', () => { beforeEach(() => { sinon.stub(config, 'get'); diff --git a/src/legacy/ui/public/agg_types/__tests__/buckets/create_filter/date_range.js b/src/legacy/ui/public/agg_types/__tests__/buckets/create_filter/date_range.js index 404eebf153dcc..3ba03f232428f 100644 --- a/src/legacy/ui/public/agg_types/__tests__/buckets/create_filter/date_range.js +++ b/src/legacy/ui/public/agg_types/__tests__/buckets/create_filter/date_range.js @@ -53,13 +53,15 @@ describe('AggConfig Filters', function () { }); const aggConfig = vis.aggs.byName('date_range')[0]; - const filter = createFilterDateRange(aggConfig, 'February 1st, 2015 to February 7th, 2015'); + const from = new Date('1 Feb 2015'); + const to = new Date('7 Feb 2015'); + const filter = createFilterDateRange(aggConfig, { from: from.valueOf(), to: to.valueOf() }); expect(filter).to.have.property('range'); expect(filter).to.have.property('meta'); expect(filter.meta).to.have.property('index', indexPattern.id); expect(filter.range).to.have.property('@timestamp'); - expect(filter.range['@timestamp']).to.have.property('gte', moment(new Date('1 Feb 2015')).toISOString()); - expect(filter.range['@timestamp']).to.have.property('lt', moment(new Date('7 Feb 2015')).toISOString()); + expect(filter.range['@timestamp']).to.have.property('gte', moment(from).toISOString()); + expect(filter.range['@timestamp']).to.have.property('lt', moment(to).toISOString()); }); }); }); diff --git a/src/legacy/ui/public/agg_types/__tests__/buckets/create_filter/ip_range.js b/src/legacy/ui/public/agg_types/__tests__/buckets/create_filter/ip_range.js index 2f7623d532d20..e29ebd689db20 100644 --- a/src/legacy/ui/public/agg_types/__tests__/buckets/create_filter/ip_range.js +++ b/src/legacy/ui/public/agg_types/__tests__/buckets/create_filter/ip_range.js @@ -55,7 +55,7 @@ describe('AggConfig Filters', function () { }); const aggConfig = vis.aggs.byName('ip_range')[0]; - const filter = createFilterIpRange(aggConfig, '0.0.0.0 to 1.1.1.1'); + const filter = createFilterIpRange(aggConfig, { type: 'fromTo', from: '0.0.0.0', to: '1.1.1.1' }); expect(filter).to.have.property('range'); expect(filter).to.have.property('meta'); expect(filter.meta).to.have.property('index', indexPattern.id); @@ -85,7 +85,7 @@ describe('AggConfig Filters', function () { }); const aggConfig = vis.aggs.byName('ip_range')[0]; - const filter = createFilterIpRange(aggConfig, '67.129.65.201/27'); + const filter = createFilterIpRange(aggConfig, { type: 'mask', mask: '67.129.65.201/27' }); expect(filter).to.have.property('range'); expect(filter).to.have.property('meta'); expect(filter.meta).to.have.property('index', indexPattern.id); diff --git a/src/legacy/ui/public/agg_types/buckets/create_filter/date_range.js b/src/legacy/ui/public/agg_types/buckets/create_filter/date_range.js index 4049c84743993..ad57dd728f796 100644 --- a/src/legacy/ui/public/agg_types/buckets/create_filter/date_range.js +++ b/src/legacy/ui/public/agg_types/buckets/create_filter/date_range.js @@ -17,19 +17,14 @@ * under the License. */ -import chrome from '../../../chrome'; -import { dateRange } from '../../../utils/date_range'; import { buildRangeFilter } from '@kbn/es-query'; +import moment from 'moment'; -const config = chrome.getUiSettingsClient(); - -export function createFilterDateRange(agg, key) { - const range = dateRange.parse(key, config.get('dateFormat')); - +export function createFilterDateRange(agg, { from, to }) { const filter = {}; - if (range.from) filter.gte = range.from.toISOString(); - if (range.to) filter.lt = range.to.toISOString(); - if (range.to && range.from) filter.format = 'strict_date_optional_time'; + 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()); } diff --git a/src/legacy/ui/public/agg_types/buckets/create_filter/ip_range.js b/src/legacy/ui/public/agg_types/buckets/create_filter/ip_range.js index f13c4a6369c02..bb5f2e4ccc898 100644 --- a/src/legacy/ui/public/agg_types/buckets/create_filter/ip_range.js +++ b/src/legacy/ui/public/agg_types/buckets/create_filter/ip_range.js @@ -22,13 +22,12 @@ import { buildRangeFilter } from '@kbn/es-query'; export function createFilterIpRange(aggConfig, key) { let range; - if (aggConfig.params.ipRangeType === 'mask') { - range = new CidrMask(key).getRange(); + if (key.type === 'mask') { + range = new CidrMask(key.mask).getRange(); } else { - const [from, to] = key.split(/\s+to\s+/); range = { - from: from === '-Infinity' ? -Infinity : from, - to: to === 'Infinity' ? Infinity : to + from: key.from ? key.from : -Infinity, + to: key.to ? key.to : Infinity }; } diff --git a/src/legacy/ui/public/agg_types/buckets/date_range.js b/src/legacy/ui/public/agg_types/buckets/date_range.js index e65de5d68cb92..136cfb6aafb05 100644 --- a/src/legacy/ui/public/agg_types/buckets/date_range.js +++ b/src/legacy/ui/public/agg_types/buckets/date_range.js @@ -24,6 +24,7 @@ import { BucketAggType } from './_bucket_agg_type'; import { createFilterDateRange } from './create_filter/date_range'; import { fieldFormats } from '../../registry/field_formats'; import { DateRangesParamEditor } from '../../vis/editors/default/controls/date_ranges'; +import { FieldFormat } from '../../../../../plugins/data/common/field_formats'; import { i18n } from '@kbn/i18n'; const config = chrome.getUiSettingsClient(); @@ -36,12 +37,15 @@ export const dateRangeBucketAgg = new BucketAggType({ defaultMessage: 'Date Range', }), createFilter: createFilterDateRange, - getKey: function (bucket, key, agg) { - const formatter = agg.fieldOwnFormatter('text', fieldFormats.getDefaultInstance('date')); - return dateRange.toString(bucket, formatter); + getKey: function ({ from, to }) { + return { from, to }; }, - getFormat: function () { - return fieldFormats.getDefaultInstance('string'); + getFormat: function (agg) { + const formatter = agg.fieldOwnFormatter('text', fieldFormats.getDefaultInstance('date')); + const DateRangeFormat = FieldFormat.from(function (range) { + return dateRange.toString(range, formatter); + }); + return new DateRangeFormat(); }, makeLabel: function (aggConfig) { return aggConfig.getFieldDisplayName() + ' date ranges'; diff --git a/src/legacy/ui/public/agg_types/buckets/ip_range.js b/src/legacy/ui/public/agg_types/buckets/ip_range.js index 0a21a5ab4fb23..93446e8a4fc98 100644 --- a/src/legacy/ui/public/agg_types/buckets/ip_range.js +++ b/src/legacy/ui/public/agg_types/buckets/ip_range.js @@ -22,6 +22,9 @@ import { BucketAggType } from './_bucket_agg_type'; import { createFilterIpRange } from './create_filter/ip_range'; import { IpRangeTypeParamEditor } from '../../vis/editors/default/controls/ip_range_type'; import { IpRangesParamEditor } from '../../vis/editors/default/controls/ip_ranges'; +import { fieldFormats } from '../../registry/field_formats'; +import { FieldFormat } from '../../../../../plugins/data/common/field_formats'; +import { ipRange } from '../../utils/ip_range'; import { i18n } from '@kbn/i18n'; export const ipRangeBucketAgg = new BucketAggType({ @@ -30,11 +33,18 @@ export const ipRangeBucketAgg = new BucketAggType({ defaultMessage: 'IPv4 Range', }), createFilter: createFilterIpRange, - getKey: function (bucket, key) { - if (key) return key; - const from = _.get(bucket, 'from', '-Infinity'); - const to = _.get(bucket, 'to', 'Infinity'); - return `${from} to ${to}`; + getKey: function (bucket, key, agg) { + if (agg.params.ipRangeType === 'mask') { + return { type: 'mask', mask: key }; + } + return { type: 'range', from: bucket.from, to: bucket.to }; + }, + getFormat: function (agg) { + const formatter = agg.fieldOwnFormatter('text', fieldFormats.getDefaultInstance('ip')); + const IpRangeFormat = FieldFormat.from(function (range) { + return ipRange.toString(range, formatter); + }); + return new IpRangeFormat(); }, makeLabel: function (aggConfig) { return i18n.translate('common.ui.aggTypes.buckets.ipRangeLabel', { diff --git a/src/legacy/ui/public/utils/date_range.js b/src/legacy/ui/public/utils/date_range.js index 97b869b2bfedf..142aa879eb7ff 100644 --- a/src/legacy/ui/public/utils/date_range.js +++ b/src/legacy/ui/public/utils/date_range.js @@ -17,28 +17,14 @@ * under the License. */ -import moment from 'moment'; - export const dateRange = { - toString: function (range, format) { - if (!range.from) { - return 'Before ' + format(range.to); - } else if (!range.to) { - return 'After ' + format(range.from); + toString: function ({ from, to }, format) { + if (!from) { + return 'Before ' + format(to); + } else if (!to) { + return 'After ' + format(from); } else { - return format(range.from) + ' to ' + format(range.to); + return format(from) + ' to ' + format(to); } }, - parse: function (rangeString, format) { - let chunks = rangeString.split(' to '); - if (chunks.length === 2) return { from: moment(chunks[0], format), to: moment(chunks[1], format) }; - - chunks = rangeString.split('Before '); - if (chunks.length === 2) return { to: moment(chunks[1], format) }; - - chunks = rangeString.split('After '); - if (chunks.length === 2) return { from: moment(chunks[1], format) }; - - throw new Error('Error attempting to parse date range: ' + rangeString); - } }; diff --git a/src/legacy/ui/public/utils/ip_range.js b/src/legacy/ui/public/utils/ip_range.js new file mode 100644 index 0000000000000..b5b8956a3cb58 --- /dev/null +++ b/src/legacy/ui/public/utils/ip_range.js @@ -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 const ipRange = { + toString: function (range, format) { + if (range.type === 'mask') { + return format(range.mask); + } + const from = range.from ? format(range.from) : '-Infinity'; + const to = range.to ? format(range.to) : 'Infinity'; + return `${from} to ${to}`; + }, +}; diff --git a/src/legacy/ui/public/visualize/loader/pipeline_helpers/utilities.ts b/src/legacy/ui/public/visualize/loader/pipeline_helpers/utilities.ts index 0f8761b715c0d..1432b5a215444 100644 --- a/src/legacy/ui/public/visualize/loader/pipeline_helpers/utilities.ts +++ b/src/legacy/ui/public/visualize/loader/pipeline_helpers/utilities.ts @@ -28,6 +28,10 @@ import { tabifyGetColumns } from '../../../agg_response/tabify/_get_columns'; import chrome from '../../../chrome'; // @ts-ignore import { fieldFormats } from '../../../registry/field_formats'; +// @ts-ignore +import { dateRange } from '../../../utils/date_range'; +// @ts-ignore +import { ipRange } from '../../../utils/ip_range'; interface TermsFieldFormatParams { otherBucketLabel: string; @@ -58,7 +62,8 @@ const getFieldFormat = (id: string | undefined, params: object = {}) => { export const createFormat = (agg: AggConfig): SerializedFieldFormat => { const format: SerializedFieldFormat = agg.params.field ? agg.params.field.format.toJSON() : {}; const formats: Record SerializedFieldFormat> = { - date_range: () => ({ id: 'string' }), + date_range: () => ({ id: 'date_range', params: format }), + ip_range: () => ({ id: 'ip_range', params: format }), percentile_ranks: () => ({ id: 'percent' }), count: () => ({ id: 'number' }), cardinality: () => ({ id: 'number' }), @@ -109,6 +114,20 @@ export const getFormat: FormatFactory = (mapping = {}) => { }); }); return new RangeFormat(); + } else if (id === 'date_range') { + const nestedFormatter = mapping.params as SerializedFieldFormat; + const DateRangeFormat = FieldFormat.from((range: any) => { + const format = getFieldFormat(nestedFormatter.id, nestedFormatter.params); + return dateRange.toString(range, format.convert.bind(format)); + }); + return new DateRangeFormat(); + } else if (id === 'ip_range') { + const nestedFormatter = mapping.params as SerializedFieldFormat; + const IpRangeFormat = FieldFormat.from((range: any) => { + const format = getFieldFormat(nestedFormatter.id, nestedFormatter.params); + return ipRange.toString(range, format.convert.bind(format)); + }); + return new IpRangeFormat(); } else if (isTermsFieldFormat(mapping) && mapping.params) { const params = mapping.params; return { From 9e54d3ab695dac9cb1ecc7645219170fd495838d Mon Sep 17 00:00:00 2001 From: Joe Reuter Date: Thu, 17 Oct 2019 12:22:12 +0200 Subject: [PATCH 2/3] improve typing in utilities --- .../public/visualize/loader/pipeline_helpers/utilities.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/legacy/ui/public/visualize/loader/pipeline_helpers/utilities.ts b/src/legacy/ui/public/visualize/loader/pipeline_helpers/utilities.ts index 1432b5a215444..c12bd222663ae 100644 --- a/src/legacy/ui/public/visualize/loader/pipeline_helpers/utilities.ts +++ b/src/legacy/ui/public/visualize/loader/pipeline_helpers/utilities.ts @@ -28,10 +28,10 @@ import { tabifyGetColumns } from '../../../agg_response/tabify/_get_columns'; import chrome from '../../../chrome'; // @ts-ignore import { fieldFormats } from '../../../registry/field_formats'; -// @ts-ignore import { dateRange } from '../../../utils/date_range'; -// @ts-ignore import { ipRange } from '../../../utils/ip_range'; +import { DateRangeKey } from '../../../agg_types/buckets/date_range'; +import { IpRangeKey } from '../../../agg_types/buckets/ip_range'; interface TermsFieldFormatParams { otherBucketLabel: string; @@ -116,14 +116,14 @@ export const getFormat: FormatFactory = (mapping = {}) => { return new RangeFormat(); } else if (id === 'date_range') { const nestedFormatter = mapping.params as SerializedFieldFormat; - const DateRangeFormat = FieldFormat.from((range: any) => { + const DateRangeFormat = FieldFormat.from((range: DateRangeKey) => { const format = getFieldFormat(nestedFormatter.id, nestedFormatter.params); return dateRange.toString(range, format.convert.bind(format)); }); return new DateRangeFormat(); } else if (id === 'ip_range') { const nestedFormatter = mapping.params as SerializedFieldFormat; - const IpRangeFormat = FieldFormat.from((range: any) => { + const IpRangeFormat = FieldFormat.from((range: IpRangeKey) => { const format = getFieldFormat(nestedFormatter.id, nestedFormatter.params); return ipRange.toString(range, format.convert.bind(format)); }); From fb59377bee8ba876e5a402fcdadc0383c443020e Mon Sep 17 00:00:00 2001 From: Joe Reuter Date: Thu, 17 Oct 2019 13:54:16 +0200 Subject: [PATCH 3/3] apply eslint --- src/legacy/ui/public/agg_types/buckets/date_range.ts | 6 +++--- src/legacy/ui/public/agg_types/buckets/ip_range.ts | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) 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 0fe580d6c76a9..dd7f0cb972ae2 100644 --- a/src/legacy/ui/public/agg_types/buckets/date_range.ts +++ b/src/legacy/ui/public/agg_types/buckets/date_range.ts @@ -46,12 +46,12 @@ export const dateRangeBucketAgg = new BucketAggType({ name: BUCKET_TYPES.DATE_RANGE, title: dateRangeTitle, createFilter: createFilterDateRange, - getKey: function ({ from, to }): DateRangeKey { + getKey({ from, to }): DateRangeKey { return { from, to }; }, - getFormat: function (agg) { + getFormat(agg) { const formatter = agg.fieldOwnFormatter('text', fieldFormats.getDefaultInstance('date')); - const DateRangeFormat = FieldFormat.from(function (range: DateRangeKey) { + const DateRangeFormat = FieldFormat.from(function(range: DateRangeKey) { return dateRange.toString(range, formatter); }); return new DateRangeFormat(); diff --git a/src/legacy/ui/public/agg_types/buckets/ip_range.ts b/src/legacy/ui/public/agg_types/buckets/ip_range.ts index 749b53032cf36..bbc91b0768f6b 100644 --- a/src/legacy/ui/public/agg_types/buckets/ip_range.ts +++ b/src/legacy/ui/public/agg_types/buckets/ip_range.ts @@ -44,15 +44,15 @@ export const ipRangeBucketAgg = new BucketAggType({ name: BUCKET_TYPES.IP_RANGE, title: ipRangeTitle, createFilter: createFilterIpRange, - getKey: function (bucket, key, agg): IpRangeKey { + getKey(bucket, key, agg): IpRangeKey { if (agg.params.ipRangeType === 'mask') { return { type: 'mask', mask: key }; } return { type: 'range', from: bucket.from, to: bucket.to }; }, - getFormat: function (agg) { + getFormat(agg) { const formatter = agg.fieldOwnFormatter('text', fieldFormats.getDefaultInstance('ip')); - const IpRangeFormat = FieldFormat.from(function (range: IpRangeKey) { + const IpRangeFormat = FieldFormat.from(function(range: IpRangeKey) { return ipRange.toString(range, formatter); }); return new IpRangeFormat();