diff --git a/src/core_plugins/kibana/public/discover/controllers/discover.js b/src/core_plugins/kibana/public/discover/controllers/discover.js index 63dc720980fe1..51a06b3791b9f 100644 --- a/src/core_plugins/kibana/public/discover/controllers/discover.js +++ b/src/core_plugins/kibana/public/discover/controllers/discover.js @@ -21,7 +21,7 @@ import { BasicResponseHandlerProvider } from 'ui/vis/response_handlers/basic'; import { DocTitleProvider } from 'ui/doc_title'; import PluginsKibanaDiscoverHitSortFnProvider from '../_hit_sort_fn'; import { FilterBarQueryFilterProvider } from 'ui/filter_bar/query_filter'; -import { AggTypesBucketsIntervalOptionsProvider } from 'ui/agg_types/buckets/_interval_options'; +import { intervalOptions } from 'ui/agg_types/buckets/_interval_options'; import { stateMonitorFactory } from 'ui/state_management/state_monitor_factory'; import uiRoutes from 'ui/routes'; import { uiModules } from 'ui/modules'; @@ -138,7 +138,7 @@ function discoverController( }); $scope.getDocLink = getDocLink; - $scope.intervalOptions = Private(AggTypesBucketsIntervalOptionsProvider); + $scope.intervalOptions = intervalOptions; $scope.showInterval = false; $scope.minimumVisibleRows = 50; diff --git a/src/ui/public/agg_response/point_series/__tests__/_fake_x_aspect.js b/src/ui/public/agg_response/point_series/__tests__/_fake_x_aspect.js index f0c4bab715956..84fc7e6b2c588 100644 --- a/src/ui/public/agg_response/point_series/__tests__/_fake_x_aspect.js +++ b/src/ui/public/agg_response/point_series/__tests__/_fake_x_aspect.js @@ -2,20 +2,18 @@ import expect from 'expect.js'; import ngMock from 'ng_mock'; import { VisProvider } from '../../../vis'; import { AggConfig } from '../../../vis/agg_config'; -import { AggTypesAggTypeProvider } from '../../../agg_types/agg_type'; +import { AggType } from '../../../agg_types/agg_type'; import { PointSeriesFakeXAxisProvider } from '../_fake_x_aspect'; describe('makeFakeXAspect', function () { let makeFakeXAspect; let Vis; - let AggType; let indexPattern; beforeEach(ngMock.module('kibana')); beforeEach(ngMock.inject(function (Private) { Vis = Private(VisProvider); - AggType = Private(AggTypesAggTypeProvider); indexPattern = Private(VisProvider); makeFakeXAspect = Private(PointSeriesFakeXAxisProvider); })); diff --git a/src/ui/public/agg_response/point_series/_fake_x_aspect.js b/src/ui/public/agg_response/point_series/_fake_x_aspect.js index ce7ac6fa60763..15c102aeaa3d6 100644 --- a/src/ui/public/agg_response/point_series/_fake_x_aspect.js +++ b/src/ui/public/agg_response/point_series/_fake_x_aspect.js @@ -1,8 +1,7 @@ import { AggConfig } from '../../vis/agg_config'; -import { AggTypesAggTypeProvider } from '../../agg_types/agg_type'; +import { AggType } from '../../agg_types/agg_type'; -export function PointSeriesFakeXAxisProvider(Private) { - const AggType = Private(AggTypesAggTypeProvider); +export function PointSeriesFakeXAxisProvider() { const allAgg = new AggType({ name: 'all', diff --git a/src/ui/public/agg_types/__tests__/agg_param_writer.js b/src/ui/public/agg_types/__tests__/agg_param_writer.js index 2011f3be9b9f4..0b81aca108bf0 100644 --- a/src/ui/public/agg_types/__tests__/agg_param_writer.js +++ b/src/ui/public/agg_types/__tests__/agg_param_writer.js @@ -1,6 +1,6 @@ import _ from 'lodash'; import { VisProvider } from '../../vis'; -import { AggTypesIndexProvider } from '..'; +import { aggTypes } from '..'; import { VisTypesRegistryProvider } from '../../registry/vis_types'; import FixturesStubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern'; import { AggConfig } from '../../vis/agg_config'; @@ -8,7 +8,6 @@ import { AggConfig } from '../../vis/agg_config'; // eslint-disable-next-line @elastic/kibana-custom/no-default-export export default function AggParamWriterHelper(Private) { const Vis = Private(VisProvider); - const aggTypes = Private(AggTypesIndexProvider); const visTypes = Private(VisTypesRegistryProvider); const stubbedLogstashIndexPattern = Private(FixturesStubbedLogstashIndexPatternProvider); diff --git a/src/ui/public/agg_types/__tests__/agg_type.js b/src/ui/public/agg_types/__tests__/agg_type.js index 72e692a2c004e..5e206632d1bf9 100644 --- a/src/ui/public/agg_types/__tests__/agg_type.js +++ b/src/ui/public/agg_types/__tests__/agg_type.js @@ -5,11 +5,10 @@ import '../../private'; import { AggParams } from '../agg_params'; import { VisProvider } from '../../vis'; import { fieldFormats } from '../../registry/field_formats'; -import { AggTypesAggTypeProvider } from '../agg_type'; +import { AggType } from '../agg_type'; import FixturesStubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern'; describe('AggType Class', function () { - let AggType; let indexPattern; let Vis; @@ -18,7 +17,6 @@ describe('AggType Class', function () { beforeEach(ngMock.inject(function (Private) { Vis = Private(VisProvider); - AggType = Private(AggTypesAggTypeProvider); indexPattern = Private(FixturesStubbedLogstashIndexPatternProvider); })); diff --git a/src/ui/public/agg_types/__tests__/buckets/_geo_hash.js b/src/ui/public/agg_types/__tests__/buckets/_geo_hash.js index 2fa570f164377..0d710eefdb40e 100644 --- a/src/ui/public/agg_types/__tests__/buckets/_geo_hash.js +++ b/src/ui/public/agg_types/__tests__/buckets/_geo_hash.js @@ -1,9 +1,10 @@ import expect from 'expect.js'; import sinon from 'sinon'; -import ngMock from 'ng_mock'; -import { AggTypesBucketsGeoHashProvider } from '../../buckets/geo_hash'; +import { geoHashBucketAgg } from '../../buckets/geo_hash'; import * as AggConfigModule from '../../../vis/agg_config'; -import { AggTypesIndexProvider } from '../..'; +import * as BucketAggTypeModule from '../../buckets/_bucket_agg_type'; +import { aggTypes } from '../..'; +AggConfigModule.AggConfig.aggTypes = aggTypes; describe('Geohash Agg', () => { @@ -40,27 +41,15 @@ describe('Geohash Agg', () => { const AggConfigMock = (vis, aggOptions) => { return aggOptions; }; - const PrivateMock = (provider) => { - switch (provider.name) { - case 'AggTypesBucketsBucketAggTypeProvider': - return BucketAggTypeMock; - break; - default: - return () => {}; - } - }; - const configMock = { - get: () => { - return 7;//"visualization:tileMap:maxPrecision" - } - }; before(function () { sinon.stub(AggConfigModule, 'AggConfig', AggConfigMock); + sinon.stub(BucketAggTypeModule, 'BucketAggType', BucketAggTypeMock); }); after(function () { AggConfigModule.AggConfig.restore(); + BucketAggTypeModule.BucketAggType.restore(); }); @@ -93,23 +82,12 @@ describe('Geohash Agg', () => { }; } - beforeEach(ngMock.module('kibana')); - beforeEach(ngMock.inject(function (Private) { - AggConfigModule.AggConfig.aggTypes = Private(AggTypesIndexProvider); - })); - - let geohashAgg; - beforeEach(() => { - geohashAgg = AggTypesBucketsGeoHashProvider(PrivateMock, configMock); // eslint-disable-line new-cap - }); - - describe('precision parameter', () => { const PRECISION_PARAM_INDEX = 6; let precisionParam; beforeEach(() => { - precisionParam = geohashAgg.params[PRECISION_PARAM_INDEX]; + precisionParam = geoHashBucketAgg.params[PRECISION_PARAM_INDEX]; }); it('should select precision parameter', () => { @@ -169,7 +147,7 @@ describe('Geohash Agg', () => { beforeEach(() => { initVisSessionState(); initAggParams(); - requestAggs = geohashAgg.getRequestAggs(aggMock); + requestAggs = geoHashBucketAgg.getRequestAggs(aggMock); }); it('should create filter, geohash_grid, and geo_centroid aggregations', () => { @@ -189,7 +167,7 @@ describe('Geohash Agg', () => { // there was a bug because of an "&& mapZoom" check which excluded 0 as a valid mapZoom, but it is. it('should create filter, geohash_grid, and geo_centroid aggregations when zoom level 0', () => { aggMock.vis.params.mapZoom = 0; - requestAggs = geohashAgg.getRequestAggs(aggMock); + requestAggs = geoHashBucketAgg.getRequestAggs(aggMock); expect(requestAggs.length).to.equal(3); expect(requestAggs[0].type).to.equal('filter'); expect(requestAggs[1].type).to.equal('geohash_grid'); @@ -206,7 +184,7 @@ describe('Geohash Agg', () => { it('should only create geohash_grid and geo_centroid aggregations when isFilteredByCollar is false', () => { aggMock.params.isFilteredByCollar = false; - const requestAggs = geohashAgg.getRequestAggs(aggMock); + const requestAggs = geoHashBucketAgg.getRequestAggs(aggMock); expect(requestAggs.length).to.equal(2); expect(requestAggs[0].type).to.equal('geohash_grid'); expect(requestAggs[1].type).to.equal('geo_centroid'); @@ -214,7 +192,7 @@ describe('Geohash Agg', () => { it('should only create filter and geohash_grid aggregations when useGeocentroid is false', () => { aggMock.params.useGeocentroid = false; - const requestAggs = geohashAgg.getRequestAggs(aggMock); + const requestAggs = geoHashBucketAgg.getRequestAggs(aggMock); expect(requestAggs.length).to.equal(2); expect(requestAggs[0].type).to.equal('filter'); expect(requestAggs[1].type).to.equal('geohash_grid'); @@ -229,7 +207,7 @@ describe('Geohash Agg', () => { beforeEach(() => { resetMap(); initAggParams(); - origRequestAggs = geohashAgg.getRequestAggs(aggMock); + origRequestAggs = geoHashBucketAgg.getRequestAggs(aggMock); origMapCollar = aggMock.vis.sessionState.mapCollar; }); @@ -239,7 +217,7 @@ describe('Geohash Agg', () => { bottom_right: { lat: -0.9, lon: 0.9 } }); - const newRequestAggs = geohashAgg.getRequestAggs(aggMock); + const newRequestAggs = geoHashBucketAgg.getRequestAggs(aggMock); expect(JSON.stringify(origRequestAggs[0].params, null, '')).to.equal(JSON.stringify(newRequestAggs[0].params, null, '')); const newMapCollar = aggMock.vis.sessionState.mapCollar; @@ -252,7 +230,7 @@ describe('Geohash Agg', () => { bottom_right: { lat: 9.0, lon: -9.0 } }); - const newRequestAggs = geohashAgg.getRequestAggs(aggMock); + const newRequestAggs = geoHashBucketAgg.getRequestAggs(aggMock); expect(JSON.stringify(origRequestAggs[0].params, null, '')).not.to.equal(JSON.stringify(newRequestAggs[0].params, null, '')); const newMapCollar = aggMock.vis.sessionState.mapCollar; @@ -262,7 +240,7 @@ describe('Geohash Agg', () => { it('should change geo_bounding_box filter aggregation and vis session state when map zoom level changes', () => { zoomMap(-1); - const newRequestAggs = geohashAgg.getRequestAggs(aggMock); + const newRequestAggs = geoHashBucketAgg.getRequestAggs(aggMock); expect(JSON.stringify(origRequestAggs[0].params, null, '')).not.to.equal(JSON.stringify(newRequestAggs[0].params, null, '')); const newMapCollar = aggMock.vis.sessionState.mapCollar; diff --git a/src/ui/public/agg_types/__tests__/buckets/_histogram.js b/src/ui/public/agg_types/__tests__/buckets/_histogram.js index c8b7df6068e0c..4527a7168b09b 100644 --- a/src/ui/public/agg_types/__tests__/buckets/_histogram.js +++ b/src/ui/public/agg_types/__tests__/buckets/_histogram.js @@ -1,16 +1,12 @@ import expect from 'expect.js'; import ngMock from 'ng_mock'; -import { AggTypesIndexProvider } from '../..'; +import { aggTypes } from '../..'; import AggParamWriterProvider from '../agg_param_writer'; + +const histogram = aggTypes.byName.histogram; describe('Histogram Agg', function () { describe('ordered', function () { - let histogram; - - beforeEach(ngMock.module('kibana')); - beforeEach(ngMock.inject(function (Private) { - histogram = Private(AggTypesIndexProvider).byName.histogram; - })); it('is ordered', function () { expect(histogram.ordered).to.be.ok(); diff --git a/src/ui/public/agg_types/__tests__/buckets/_terms_other_bucket_helper.js b/src/ui/public/agg_types/__tests__/buckets/_terms_other_bucket_helper.js index 7e33f2d53af30..b0de9f84f8694 100644 --- a/src/ui/public/agg_types/__tests__/buckets/_terms_other_bucket_helper.js +++ b/src/ui/public/agg_types/__tests__/buckets/_terms_other_bucket_helper.js @@ -1,6 +1,6 @@ import expect from 'expect.js'; import ngMock from 'ng_mock'; -import { OtherBucketHelperProvider } from '../../buckets/_terms_other_bucket_helper'; +import { buildOtherBucketAgg, mergeOtherBucketAggResponse, updateMissingBucket } from '../../buckets/_terms_other_bucket_helper'; import { VisProvider } from '../../../vis'; import FixturesStubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern'; @@ -118,7 +118,6 @@ const nestedOtherResponse = { describe('Terms Agg Other bucket helper', () => { - let otherBucketHelper; let vis; function init(aggConfig) { @@ -126,7 +125,6 @@ describe('Terms Agg Other bucket helper', () => { ngMock.inject((Private) => { const Vis = Private(VisProvider); const indexPattern = Private(FixturesStubbedLogstashIndexPatternProvider); - otherBucketHelper = Private(OtherBucketHelperProvider); vis = new Vis(indexPattern, aggConfig); }); @@ -136,13 +134,13 @@ describe('Terms Agg Other bucket helper', () => { it('returns a function', () => { init(visConfigSingleTerm); - const agg = otherBucketHelper.buildOtherBucketAgg(vis.aggs, vis.aggs[0], singleTermResponse); + const agg = buildOtherBucketAgg(vis.aggs, vis.aggs[0], singleTermResponse); expect(agg).to.be.a('function'); }); it('correctly builds query with single terms agg', () => { init(visConfigSingleTerm); - const agg = otherBucketHelper.buildOtherBucketAgg(vis.aggs, vis.aggs[0], singleTermResponse)(); + const agg = buildOtherBucketAgg(vis.aggs, vis.aggs[0], singleTermResponse)(); const expectedResponse = { aggs: undefined, filters: { @@ -171,7 +169,7 @@ describe('Terms Agg Other bucket helper', () => { it('correctly builds query for nested terms agg', () => { init(visConfigNestedTerm); - const agg = otherBucketHelper.buildOtherBucketAgg(vis.aggs, vis.aggs[1], nestedTermResponse)(); + const agg = buildOtherBucketAgg(vis.aggs, vis.aggs[1], nestedTermResponse)(); const expectedResponse = { 'other-filter': { aggs: undefined, @@ -220,9 +218,13 @@ describe('Terms Agg Other bucket helper', () => { describe('mergeOtherBucketAggResponse', () => { it('correctly merges other bucket with single terms agg', () => { init(visConfigSingleTerm); - const otherAggConfig = otherBucketHelper.buildOtherBucketAgg(vis.aggs, vis.aggs[0], singleTermResponse)(); - const mergedResponse = otherBucketHelper - .mergeOtherBucketAggResponse(vis.aggs, singleTermResponse, singleOtherResponse, vis.aggs[0], otherAggConfig); + const otherAggConfig = buildOtherBucketAgg(vis.aggs, vis.aggs[0], singleTermResponse)(); + const mergedResponse = mergeOtherBucketAggResponse( + vis.aggs, + singleTermResponse, + singleOtherResponse, + vis.aggs[0], + otherAggConfig); expect(mergedResponse.aggregations['1'].buckets[3].key).to.equal('Other'); expect(mergedResponse.aggregations['1'].buckets[3].filters.length).to.equal(2); @@ -230,9 +232,9 @@ describe('Terms Agg Other bucket helper', () => { it('correctly merges other bucket with nested terms agg', () => { init(visConfigNestedTerm); - const otherAggConfig = otherBucketHelper.buildOtherBucketAgg(vis.aggs, vis.aggs[1], nestedTermResponse)(); - const mergedResponse = otherBucketHelper - .mergeOtherBucketAggResponse(vis.aggs, nestedTermResponse, nestedOtherResponse, vis.aggs[1], otherAggConfig); + const otherAggConfig = buildOtherBucketAgg(vis.aggs, vis.aggs[1], nestedTermResponse)(); + const mergedResponse = mergeOtherBucketAggResponse(vis.aggs, nestedTermResponse, + nestedOtherResponse, vis.aggs[1], otherAggConfig); expect(mergedResponse.aggregations['1'].buckets[1]['2'].buckets[3].key).to.equal('Other'); expect(mergedResponse.aggregations['1'].buckets[1]['2'].buckets[3].filters.length).to.equal(2); @@ -243,12 +245,12 @@ describe('Terms Agg Other bucket helper', () => { describe('updateMissingBucket', () => { it('correctly updates missing bucket key', () => { init(visConfigNestedTerm); - const updatedResponse = otherBucketHelper.updateMissingBucket(singleTermResponse, vis.aggs, vis.aggs[0]); + const updatedResponse = updateMissingBucket(singleTermResponse, vis.aggs, vis.aggs[0]); expect(updatedResponse.aggregations['1'].buckets.find(bucket => bucket.key === 'Missing')).to.not.be('undefined'); }); it('correctly sets the bucket filter', () => { - const updatedResponse = otherBucketHelper.updateMissingBucket(singleTermResponse, vis.aggs, vis.aggs[0]); + const updatedResponse = updateMissingBucket(singleTermResponse, vis.aggs, vis.aggs[0]); const missingBucket = updatedResponse.aggregations['1'].buckets.find(bucket => bucket.key === 'Missing'); expect(missingBucket.filters).to.not.be('undefined'); expect(missingBucket.filters[0]).to.eql({ diff --git a/src/ui/public/agg_types/__tests__/buckets/create_filter/date_histogram.js b/src/ui/public/agg_types/__tests__/buckets/create_filter/date_histogram.js index cd8a2431f210a..9ec493276b84a 100644 --- a/src/ui/public/agg_types/__tests__/buckets/create_filter/date_histogram.js +++ b/src/ui/public/agg_types/__tests__/buckets/create_filter/date_histogram.js @@ -5,8 +5,8 @@ import ngMock from 'ng_mock'; import expect from 'expect.js'; import { VisProvider } from '../../../../vis'; import FixturesStubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern'; -import { AggTypesBucketsCreateFilterDateHistogramProvider } from '../../../buckets/create_filter/date_histogram'; -import { AggTypesBucketsIntervalOptionsProvider } from '../../../buckets/_interval_options'; +import { createFilterDateHistogram } from '../../../buckets/create_filter/date_histogram'; +import { intervalOptions } from '../../../buckets/_interval_options'; describe('AggConfig Filters', function () { describe('date_histogram', function () { @@ -16,7 +16,6 @@ describe('AggConfig Filters', function () { let filter; let bucketKey; let bucketStart; - let intervalOptions; let init; @@ -24,8 +23,6 @@ describe('AggConfig Filters', function () { beforeEach(ngMock.inject(function (Private) { const Vis = Private(VisProvider); const indexPattern = Private(FixturesStubbedLogstashIndexPatternProvider); - const createFilter = Private(AggTypesBucketsCreateFilterDateHistogramProvider); - intervalOptions = Private(AggTypesBucketsIntervalOptionsProvider); init = function (interval, duration) { interval = interval || 'auto'; @@ -54,7 +51,7 @@ describe('AggConfig Filters', function () { }); agg.buckets.setInterval(interval); - filter = createFilter(agg, bucketKey); + filter = createFilterDateHistogram(agg, bucketKey); }; })); diff --git a/src/ui/public/agg_types/__tests__/buckets/create_filter/date_range.js b/src/ui/public/agg_types/__tests__/buckets/create_filter/date_range.js index 5b43407a6bdc3..02fd5b78b9b0a 100644 --- a/src/ui/public/agg_types/__tests__/buckets/create_filter/date_range.js +++ b/src/ui/public/agg_types/__tests__/buckets/create_filter/date_range.js @@ -3,19 +3,17 @@ import expect from 'expect.js'; import ngMock from 'ng_mock'; import { VisProvider } from '../../../../vis'; import FixturesStubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern'; -import { AggTypesBucketsCreateFilterDateRangeProvider } from '../../../buckets/create_filter/date_range'; +import { createFilterDateRange } from '../../../buckets/create_filter/date_range'; describe('AggConfig Filters', function () { describe('Date range', function () { let indexPattern; let Vis; - let createFilter; beforeEach(ngMock.module('kibana')); beforeEach(ngMock.inject(function (Private) { Vis = Private(VisProvider); indexPattern = Private(FixturesStubbedLogstashIndexPatternProvider); - createFilter = Private(AggTypesBucketsCreateFilterDateRangeProvider); })); it('should return a range filter for date_range agg', function () { @@ -35,7 +33,7 @@ describe('AggConfig Filters', function () { }); const aggConfig = vis.aggs.byTypeName.date_range[0]; - const filter = createFilter(aggConfig, 'February 1st, 2015 to February 7th, 2015'); + const filter = createFilterDateRange(aggConfig, 'February 1st, 2015 to February 7th, 2015'); 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/ui/public/agg_types/__tests__/buckets/create_filter/filters.js b/src/ui/public/agg_types/__tests__/buckets/create_filter/filters.js index 7bdd54a796980..c8c0dd3411b15 100644 --- a/src/ui/public/agg_types/__tests__/buckets/create_filter/filters.js +++ b/src/ui/public/agg_types/__tests__/buckets/create_filter/filters.js @@ -2,19 +2,17 @@ import expect from 'expect.js'; import ngMock from 'ng_mock'; import { VisProvider } from '../../../../vis'; import FixturesStubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern'; -import { AggTypesBucketsCreateFilterFiltersProvider } from '../../../buckets/create_filter/filters'; +import { createFilterFilters } from '../../../buckets/create_filter/filters'; describe('AggConfig Filters', function () { describe('filters', function () { let indexPattern; let Vis; - let createFilter; beforeEach(ngMock.module('kibana')); beforeEach(ngMock.inject(function (Private) { Vis = Private(VisProvider); indexPattern = Private(FixturesStubbedLogstashIndexPatternProvider); - createFilter = Private(AggTypesBucketsCreateFilterFiltersProvider); })); it('should return a filters filter', function () { @@ -35,7 +33,7 @@ describe('AggConfig Filters', function () { }); const aggConfig = vis.aggs.byTypeName.filters[0]; - const filter = createFilter(aggConfig, 'type:nginx'); + const filter = createFilterFilters(aggConfig, 'type:nginx'); expect(filter.query.query_string.query).to.be('type:nginx'); expect(filter.meta).to.have.property('index', indexPattern.id); diff --git a/src/ui/public/agg_types/__tests__/buckets/create_filter/histogram.js b/src/ui/public/agg_types/__tests__/buckets/create_filter/histogram.js index 569492973c03d..5304cd55e35e7 100644 --- a/src/ui/public/agg_types/__tests__/buckets/create_filter/histogram.js +++ b/src/ui/public/agg_types/__tests__/buckets/create_filter/histogram.js @@ -3,19 +3,17 @@ import expect from 'expect.js'; import ngMock from 'ng_mock'; import { VisProvider } from '../../../../vis'; import FixturesStubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern'; -import { AggTypesBucketsCreateFilterHistogramProvider } from '../../../buckets/create_filter/histogram'; +import { createFilterHistogram } from '../../../buckets/create_filter/histogram'; describe('AggConfig Filters', function () { describe('histogram', function () { let indexPattern; let Vis; - let createFilter; beforeEach(ngMock.module('kibana')); beforeEach(ngMock.inject(function (Private) { Vis = Private(VisProvider); indexPattern = Private(FixturesStubbedLogstashIndexPatternProvider); - createFilter = Private(AggTypesBucketsCreateFilterHistogramProvider); })); it('should return an range filter for histogram', function () { @@ -31,7 +29,7 @@ describe('AggConfig Filters', function () { }); const aggConfig = vis.aggs.byTypeName.histogram[0]; - const filter = createFilter(aggConfig, 2048); + const filter = createFilterHistogram(aggConfig, 2048); expect(filter).to.have.property('meta'); expect(filter.meta).to.have.property('index', indexPattern.id); expect(filter).to.have.property('range'); diff --git a/src/ui/public/agg_types/__tests__/buckets/create_filter/ip_range.js b/src/ui/public/agg_types/__tests__/buckets/create_filter/ip_range.js index ccc0b7173992b..87d73580af577 100644 --- a/src/ui/public/agg_types/__tests__/buckets/create_filter/ip_range.js +++ b/src/ui/public/agg_types/__tests__/buckets/create_filter/ip_range.js @@ -2,19 +2,17 @@ import expect from 'expect.js'; import ngMock from 'ng_mock'; import { VisProvider } from '../../../../vis'; import FixturesStubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern'; -import { AggTypesBucketsCreateFilterIpRangeProvider } from '../../../buckets/create_filter/ip_range'; +import { createFilterIpRange } from '../../../buckets/create_filter/ip_range'; describe('AggConfig Filters', function () { describe('IP range', function () { let indexPattern; let Vis; - let createFilter; beforeEach(ngMock.module('kibana')); beforeEach(ngMock.inject(function (Private) { Vis = Private(VisProvider); indexPattern = Private(FixturesStubbedLogstashIndexPatternProvider); - createFilter = Private(AggTypesBucketsCreateFilterIpRangeProvider); })); it('should return a range filter for ip_range agg', function () { @@ -38,7 +36,7 @@ describe('AggConfig Filters', function () { }); const aggConfig = vis.aggs.byTypeName.ip_range[0]; - const filter = createFilter(aggConfig, '0.0.0.0 to 1.1.1.1'); + const filter = createFilterIpRange(aggConfig, '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); @@ -68,7 +66,7 @@ describe('AggConfig Filters', function () { }); const aggConfig = vis.aggs.byTypeName.ip_range[0]; - const filter = createFilter(aggConfig, '67.129.65.201/27'); + const filter = createFilterIpRange(aggConfig, '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/ui/public/agg_types/__tests__/buckets/create_filter/range.js b/src/ui/public/agg_types/__tests__/buckets/create_filter/range.js index a9863107d5849..a619ae5718fc2 100644 --- a/src/ui/public/agg_types/__tests__/buckets/create_filter/range.js +++ b/src/ui/public/agg_types/__tests__/buckets/create_filter/range.js @@ -2,20 +2,18 @@ import expect from 'expect.js'; import ngMock from 'ng_mock'; import { VisProvider } from '../../../../vis'; import FixturesStubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern'; -import { AggTypesBucketsCreateFilterRangeProvider } from '../../../buckets/create_filter/range'; +import { createFilterRange } from '../../../buckets/create_filter/range'; describe('AggConfig Filters', function () { describe('range', function () { let indexPattern; let Vis; - let createFilter; beforeEach(ngMock.module('kibana')); beforeEach(ngMock.inject(function (Private) { Vis = Private(VisProvider); indexPattern = Private(FixturesStubbedLogstashIndexPatternProvider); - createFilter = Private(AggTypesBucketsCreateFilterRangeProvider); })); it('should return a range filter for range agg', function () { @@ -36,7 +34,7 @@ describe('AggConfig Filters', function () { }); const aggConfig = vis.aggs.byTypeName.range[0]; - const filter = createFilter(aggConfig, { gte: 1024, lt: 2048.0 }); + const filter = createFilterRange(aggConfig, { gte: 1024, lt: 2048.0 }); 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/ui/public/agg_types/__tests__/buckets/create_filter/terms.js b/src/ui/public/agg_types/__tests__/buckets/create_filter/terms.js index e0605187a9626..a99df1ae76ca4 100644 --- a/src/ui/public/agg_types/__tests__/buckets/create_filter/terms.js +++ b/src/ui/public/agg_types/__tests__/buckets/create_filter/terms.js @@ -2,20 +2,18 @@ import expect from 'expect.js'; import ngMock from 'ng_mock'; import { VisProvider } from '../../../../vis'; import FixturesStubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern'; -import { AggTypesBucketsCreateFilterTermsProvider } from '../../../buckets/create_filter/terms'; +import { createFilterTerms } from '../../../buckets/create_filter/terms'; describe('AggConfig Filters', function () { describe('terms', function () { let indexPattern; let Vis; - let createFilter; beforeEach(ngMock.module('kibana')); beforeEach(ngMock.inject(function (Private) { Vis = Private(VisProvider); indexPattern = Private(FixturesStubbedLogstashIndexPatternProvider); - createFilter = Private(AggTypesBucketsCreateFilterTermsProvider); })); it('should return a match filter for terms', function () { @@ -24,7 +22,7 @@ describe('AggConfig Filters', function () { aggs: [ { type: 'terms', schema: 'segment', params: { field: '_type' } } ] }); const aggConfig = vis.aggs.byTypeName.terms[0]; - const filter = createFilter(aggConfig, 'apache'); + const filter = createFilterTerms(aggConfig, 'apache'); expect(filter).to.have.property('query'); expect(filter.query).to.have.property('match'); expect(filter.query.match).to.have.property('_type'); @@ -41,13 +39,13 @@ describe('AggConfig Filters', function () { aggs: [ { type: 'terms', schema: 'segment', params: { field: 'ssl' } } ] }); const aggConfig = vis.aggs.byTypeName.terms[0]; - const filterFalse = createFilter(aggConfig, 0); + const filterFalse = createFilterTerms(aggConfig, 0); expect(filterFalse).to.have.property('query'); expect(filterFalse.query).to.have.property('match'); expect(filterFalse.query.match).to.have.property('ssl'); expect(filterFalse.query.match.ssl).to.have.property('query', false); - const filterTrue = createFilter(aggConfig, 1); + const filterTrue = createFilterTerms(aggConfig, 1); expect(filterTrue).to.have.property('query'); expect(filterTrue.query).to.have.property('match'); expect(filterTrue.query.match).to.have.property('ssl'); diff --git a/src/ui/public/agg_types/__tests__/buckets/date_histogram/_editor.js b/src/ui/public/agg_types/__tests__/buckets/date_histogram/_editor.js index bfd23b533761e..48285296a2fa5 100644 --- a/src/ui/public/agg_types/__tests__/buckets/date_histogram/_editor.js +++ b/src/ui/public/agg_types/__tests__/buckets/date_histogram/_editor.js @@ -4,7 +4,7 @@ import ngMock from 'ng_mock'; import expect from 'expect.js'; import FixturesStubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern'; import { VisProvider } from '../../../../vis'; -import { AggTypesBucketsIntervalOptionsProvider } from '../../../buckets/_interval_options'; +import { intervalOptions } from '../../../buckets/_interval_options'; describe('editor', function () { @@ -74,9 +74,9 @@ describe('editor', function () { let field; let interval; - beforeEach(ngMock.inject(function (Private) { + beforeEach(ngMock.inject(function () { field = _.sample(indexPattern.fields); - interval = _.sample(Private(AggTypesBucketsIntervalOptionsProvider)); + interval = _.sample(intervalOptions); params = render({ field: field, interval: interval }); })); diff --git a/src/ui/public/agg_types/__tests__/buckets/date_histogram/_params.js b/src/ui/public/agg_types/__tests__/buckets/date_histogram/_params.js index a03d25363d01e..5b599d78db785 100644 --- a/src/ui/public/agg_types/__tests__/buckets/date_histogram/_params.js +++ b/src/ui/public/agg_types/__tests__/buckets/date_histogram/_params.js @@ -4,7 +4,7 @@ import expect from 'expect.js'; import ngMock from 'ng_mock'; import AggParamWriterProvider from '../../agg_param_writer'; import FixturesStubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern'; -import { AggTypesIndexProvider } from '../../..'; +import { aggTypes } from '../../..'; import { AggConfig } from '../../../../vis/agg_config'; describe('params', function () { @@ -12,7 +12,6 @@ describe('params', function () { let paramWriter; let writeInterval; - let aggTypes; let setTimeBounds; let timeField; @@ -23,7 +22,6 @@ describe('params', function () { const timefilter = $injector.get('timefilter'); timeField = indexPattern.timeFieldName; - aggTypes = Private(AggTypesIndexProvider); paramWriter = new AggParamWriter({ aggType: 'date_histogram' }); writeInterval = function (interval) { diff --git a/src/ui/public/agg_types/__tests__/buckets/terms.js b/src/ui/public/agg_types/__tests__/buckets/terms.js index 2d3b34d474f2d..4b11180afca3c 100644 --- a/src/ui/public/agg_types/__tests__/buckets/terms.js +++ b/src/ui/public/agg_types/__tests__/buckets/terms.js @@ -1,6 +1,6 @@ import expect from 'expect.js'; import ngMock from 'ng_mock'; -import { AggTypesIndexProvider } from '../..'; +import { aggTypes } from '../..'; describe('Terms Agg', function () { describe('order agg editor UI', function () { @@ -10,7 +10,7 @@ describe('Terms Agg', function () { function init({ responseValueAggs = [], aggParams = {} }) { ngMock.module('kibana'); ngMock.inject(function (Private, $controller, _$rootScope_) { - const terms = Private(AggTypesIndexProvider).byName.terms; + const terms = aggTypes.byName.terms; const orderAggController = terms.params.byName.orderAgg.controller; $rootScope = _$rootScope_; diff --git a/src/ui/public/agg_types/__tests__/index.js b/src/ui/public/agg_types/__tests__/index.js index 4aba3dea1785f..2c9900d2b6628 100644 --- a/src/ui/public/agg_types/__tests__/index.js +++ b/src/ui/public/agg_types/__tests__/index.js @@ -1,5 +1,4 @@ import expect from 'expect.js'; -import ngMock from 'ng_mock'; import './agg_type'; import './agg_params'; import './buckets/_histogram'; @@ -8,22 +7,16 @@ import './buckets/_range'; import './buckets/_terms_other_bucket_helper'; import './buckets/date_histogram/_editor'; import './buckets/date_histogram/_params'; -import { AggTypesIndexProvider } from '..'; -import { AggTypesBucketsBucketAggTypeProvider } from '../buckets/_bucket_agg_type'; -import { AggTypesMetricsMetricAggTypeProvider } from '../metrics/metric_agg_type'; +import { aggTypes } from '..'; +import { BucketAggType } from '../buckets/_bucket_agg_type'; +import { MetricAggType } from '../metrics/metric_agg_type'; + +const bucketAggs = aggTypes.byType.buckets; +const metricAggs = aggTypes.byType.metrics; describe('AggTypesComponent', function () { describe('bucket aggs', function () { - let bucketAggs; - let BucketAggType; - - beforeEach(ngMock.module('kibana')); - beforeEach(ngMock.inject(function (Private) { - bucketAggs = Private(AggTypesIndexProvider).byType.buckets; - BucketAggType = Private(AggTypesBucketsBucketAggTypeProvider); - })); - it('all extend BucketAggType', function () { bucketAggs.forEach(function (bucketAgg) { expect(bucketAgg).to.be.a(BucketAggType); @@ -32,15 +25,6 @@ describe('AggTypesComponent', function () { }); describe('metric aggs', function () { - let metricAggs; - let MetricAggType; - - beforeEach(ngMock.module('kibana')); - beforeEach(ngMock.inject(function (Private) { - metricAggs = Private(AggTypesIndexProvider).byType.metrics; - MetricAggType = Private(AggTypesMetricsMetricAggTypeProvider); - })); - it('all extend MetricAggType', function () { metricAggs.forEach(function (metricAgg) { expect(metricAgg).to.be.a(MetricAggType); diff --git a/src/ui/public/agg_types/__tests__/metrics/parent_pipeline.js b/src/ui/public/agg_types/__tests__/metrics/parent_pipeline.js index 3e990a09615fd..77313d17235f2 100644 --- a/src/ui/public/agg_types/__tests__/metrics/parent_pipeline.js +++ b/src/ui/public/agg_types/__tests__/metrics/parent_pipeline.js @@ -1,18 +1,18 @@ import expect from 'expect.js'; import sinon from 'sinon'; import ngMock from 'ng_mock'; -import { AggTypesMetricsDerivativeProvider } from '../../metrics/derivative'; -import { AggTypesMetricsCumulativeSumProvider } from '../../metrics/cumulative_sum'; -import { AggTypesMetricsMovingAvgProvider } from '../../metrics/moving_avg'; -import { AggTypesMetricsSerialDiffProvider } from '../../metrics/serial_diff'; +import { derivativeMetricAgg } from '../../metrics/derivative'; +import { cumulativeSumMetricAgg } from '../../metrics/cumulative_sum'; +import { movingAvgMetricAgg } from '../../metrics/moving_avg'; +import { serialDiffMetricAgg } from '../../metrics/serial_diff'; import { VisProvider } from '../../../vis'; import StubbedIndexPattern from 'fixtures/stubbed_logstash_index_pattern'; const metrics = [ - { name: 'derivative', title: 'Derivative', provider: AggTypesMetricsDerivativeProvider }, - { name: 'cumulative_sum', title: 'Cumulative Sum', provider: AggTypesMetricsCumulativeSumProvider }, - { name: 'moving_avg', title: 'Moving Avg', provider: AggTypesMetricsMovingAvgProvider }, - { name: 'serial_diff', title: 'Serial Diff', provider: AggTypesMetricsSerialDiffProvider }, + { name: 'derivative', title: 'Derivative', agg: derivativeMetricAgg }, + { name: 'cumulative_sum', title: 'Cumulative Sum', agg: cumulativeSumMetricAgg }, + { name: 'moving_avg', title: 'Moving Avg', agg: movingAvgMetricAgg }, + { name: 'serial_diff', title: 'Serial Diff', agg: serialDiffMetricAgg }, ]; describe('parent pipeline aggs', function () { @@ -29,7 +29,7 @@ describe('parent pipeline aggs', function () { const Vis = Private(VisProvider); const indexPattern = Private(StubbedIndexPattern); indexPattern.stubSetFieldFormat('bytes', 'bytes'); - metricAgg = Private(metric.provider); + metricAgg = metric.agg; const params = settings || { metricAgg: '1', diff --git a/src/ui/public/agg_types/__tests__/metrics/percentile_ranks.js b/src/ui/public/agg_types/__tests__/metrics/percentile_ranks.js index 99e9a7d051656..9a0dda8503507 100644 --- a/src/ui/public/agg_types/__tests__/metrics/percentile_ranks.js +++ b/src/ui/public/agg_types/__tests__/metrics/percentile_ranks.js @@ -1,6 +1,6 @@ import expect from 'expect.js'; import ngMock from 'ng_mock'; -import { AggTypesMetricsPercentileRanksProvider } from '../../metrics/percentile_ranks'; +import { percentileRanksMetricAgg } from '../../metrics/percentile_ranks'; import { VisProvider } from '../../../vis'; import FixturesStubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern'; @@ -8,13 +8,11 @@ describe('AggTypesMetricsPercentileRanksProvider class', function () { let Vis; let indexPattern; - let aggTypeMetricPercentileRanks; beforeEach(ngMock.module('kibana')); beforeEach(ngMock.inject(function (Private) { Vis = Private(VisProvider); indexPattern = Private(FixturesStubbedLogstashIndexPatternProvider); - aggTypeMetricPercentileRanks = Private(AggTypesMetricsPercentileRanksProvider); })); it('uses the custom label if it is set', function () { @@ -29,7 +27,7 @@ describe('AggTypesMetricsPercentileRanksProvider class', function () { displayName: 'bytes' }; - const responseAggs = aggTypeMetricPercentileRanks.getResponseAggs(aggConfig); + const responseAggs = percentileRanksMetricAgg.getResponseAggs(aggConfig); const percentileRankLabelFor5kBytes = responseAggs[0].makeLabel(); const percentileRankLabelFor10kBytes = responseAggs[1].makeLabel(); diff --git a/src/ui/public/agg_types/__tests__/metrics/percentiles.js b/src/ui/public/agg_types/__tests__/metrics/percentiles.js index 9371eadec2e20..2f3c6477fca2a 100644 --- a/src/ui/public/agg_types/__tests__/metrics/percentiles.js +++ b/src/ui/public/agg_types/__tests__/metrics/percentiles.js @@ -1,6 +1,6 @@ import expect from 'expect.js'; import ngMock from 'ng_mock'; -import { AggTypesMetricsPercentilesProvider } from '../../metrics/percentiles'; +import { percentilesMetricAgg } from '../../metrics/percentiles'; import { VisProvider } from '../../../vis'; import FixturesStubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern'; @@ -8,13 +8,11 @@ describe('AggTypesMetricsPercentilesProvider class', function () { let Vis; let indexPattern; - let aggTypeMetricPercentiles; beforeEach(ngMock.module('kibana')); beforeEach(ngMock.inject(function (Private) { Vis = Private(VisProvider); indexPattern = Private(FixturesStubbedLogstashIndexPatternProvider); - aggTypeMetricPercentiles = Private(AggTypesMetricsPercentilesProvider); })); it('uses the custom label if it is set', function () { @@ -29,7 +27,7 @@ describe('AggTypesMetricsPercentilesProvider class', function () { displayName: 'bytes' }; - const responseAggs = aggTypeMetricPercentiles.getResponseAggs(aggConfig); + const responseAggs = percentilesMetricAgg.getResponseAggs(aggConfig); const ninetyFifthPercentileLabel = responseAggs[0].makeLabel(); expect(ninetyFifthPercentileLabel).to.be('95th percentile of prince'); diff --git a/src/ui/public/agg_types/__tests__/metrics/sibling_pipeline.js b/src/ui/public/agg_types/__tests__/metrics/sibling_pipeline.js index f75283dc67d19..15a23f9f0783a 100644 --- a/src/ui/public/agg_types/__tests__/metrics/sibling_pipeline.js +++ b/src/ui/public/agg_types/__tests__/metrics/sibling_pipeline.js @@ -1,18 +1,18 @@ import expect from 'expect.js'; import sinon from 'sinon'; import ngMock from 'ng_mock'; -import { AggTypesMetricsBucketSumProvider } from '../../metrics/bucket_sum'; -import { AggTypesMetricsBucketAvgProvider } from '../../metrics/bucket_avg'; -import { AggTypesMetricsBucketMinProvider } from '../../metrics/bucket_min'; -import { AggTypesMetricsBucketMaxProvider } from '../../metrics/bucket_max'; +import { bucketSumMetricAgg } from '../../metrics/bucket_sum'; +import { bucketAvgMetricAgg } from '../../metrics/bucket_avg'; +import { bucketMinMetricAgg } from '../../metrics/bucket_min'; +import { bucketMaxMetricAgg } from '../../metrics/bucket_max'; import { VisProvider } from '../../../vis'; import StubbedIndexPattern from 'fixtures/stubbed_logstash_index_pattern'; const metrics = [ - { name: 'sum_bucket', title: 'Overall Sum', provider: AggTypesMetricsBucketSumProvider }, - { name: 'avg_bucket', title: 'Overall Average', provider: AggTypesMetricsBucketAvgProvider }, - { name: 'min_bucket', title: 'Overall Min', provider: AggTypesMetricsBucketMinProvider }, - { name: 'max_bucket', title: 'Overall Max', provider: AggTypesMetricsBucketMaxProvider }, + { name: 'sum_bucket', title: 'Overall Sum', provider: bucketSumMetricAgg }, + { name: 'avg_bucket', title: 'Overall Average', provider: bucketAvgMetricAgg }, + { name: 'min_bucket', title: 'Overall Min', provider: bucketMinMetricAgg }, + { name: 'max_bucket', title: 'Overall Max', provider: bucketMaxMetricAgg }, ]; describe('sibling pipeline aggs', function () { @@ -29,7 +29,7 @@ describe('sibling pipeline aggs', function () { const Vis = Private(VisProvider); const indexPattern = Private(StubbedIndexPattern); indexPattern.stubSetFieldFormat('bytes', 'bytes'); - metricAgg = Private(metric.provider); + metricAgg = metric.provider; const params = settings || { customMetric: { diff --git a/src/ui/public/agg_types/__tests__/metrics/std_deviation.js b/src/ui/public/agg_types/__tests__/metrics/std_deviation.js index 6d464353abb65..93ee3772001d3 100644 --- a/src/ui/public/agg_types/__tests__/metrics/std_deviation.js +++ b/src/ui/public/agg_types/__tests__/metrics/std_deviation.js @@ -1,6 +1,6 @@ import expect from 'expect.js'; import ngMock from 'ng_mock'; -import { AggTypesMetricsStdDeviationProvider } from '../../metrics/std_deviation'; +import { stdDeviationMetricAgg } from '../../metrics/std_deviation'; import { VisProvider } from '../../../vis'; import FixturesStubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern'; @@ -8,13 +8,11 @@ describe('AggTypeMetricStandardDeviationProvider class', function () { let Vis; let indexPattern; - let aggTypeMetricStandardDeviation; beforeEach(ngMock.module('kibana')); beforeEach(ngMock.inject(function (Private) { Vis = Private(VisProvider); indexPattern = Private(FixturesStubbedLogstashIndexPatternProvider); - aggTypeMetricStandardDeviation = Private(AggTypesMetricsStdDeviationProvider); })); it('uses the custom label if it is set', function () { @@ -28,7 +26,7 @@ describe('AggTypeMetricStandardDeviationProvider class', function () { displayName: 'memory' }; - const responseAggs = aggTypeMetricStandardDeviation.getResponseAggs(aggConfig); + const responseAggs = stdDeviationMetricAgg.getResponseAggs(aggConfig); const lowerStdDevLabel = responseAggs[0].makeLabel(); const upperStdDevLabel = responseAggs[1].makeLabel(); @@ -46,7 +44,7 @@ describe('AggTypeMetricStandardDeviationProvider class', function () { displayName: 'memory' }; - const responseAggs = aggTypeMetricStandardDeviation.getResponseAggs(aggConfig); + const responseAggs = stdDeviationMetricAgg.getResponseAggs(aggConfig); const lowerStdDevLabel = responseAggs[0].makeLabel(); const upperStdDevLabel = responseAggs[1].makeLabel(); diff --git a/src/ui/public/agg_types/__tests__/metrics/top_hit.js b/src/ui/public/agg_types/__tests__/metrics/top_hit.js index 5bb88df495855..77f368dae9745 100644 --- a/src/ui/public/agg_types/__tests__/metrics/top_hit.js +++ b/src/ui/public/agg_types/__tests__/metrics/top_hit.js @@ -1,13 +1,12 @@ import _ from 'lodash'; import expect from 'expect.js'; import ngMock from 'ng_mock'; -import { AggTypesMetricsTopHitProvider } from '../../metrics/top_hit'; +import { topHitMetricAgg } from '../../metrics/top_hit'; import { VisProvider } from '../../../vis'; import StubbedIndexPattern from 'fixtures/stubbed_logstash_index_pattern'; describe('Top hit metric', function () { let aggDsl; - let topHitMetric; let aggConfig; function init({ field, sortOrder = 'desc', aggregate = 'concat', size = 1 }) { @@ -15,7 +14,6 @@ describe('Top hit metric', function () { ngMock.inject(function (Private) { const Vis = Private(VisProvider); const indexPattern = Private(StubbedIndexPattern); - topHitMetric = Private(AggTypesMetricsTopHitProvider); const params = {}; if (field) { @@ -54,7 +52,7 @@ describe('Top hit metric', function () { it('should return a label prefixed with Last if sorting in descending order', function () { init({ field: 'bytes' }); - expect(topHitMetric.makeLabel(aggConfig)).to.eql('Last bytes'); + expect(topHitMetricAgg.makeLabel(aggConfig)).to.eql('Last bytes'); }); it('should return a label prefixed with First if sorting in ascending order', function () { @@ -62,7 +60,7 @@ describe('Top hit metric', function () { field: 'bytes', sortOrder: 'asc' }); - expect(topHitMetric.makeLabel(aggConfig)).to.eql('First bytes'); + expect(topHitMetricAgg.makeLabel(aggConfig)).to.eql('First bytes'); }); it('should request the _source field', function () { @@ -106,7 +104,7 @@ describe('Top hit metric', function () { }; init({ field: '@tags' }); - expect(topHitMetric.getValue(aggConfig, bucket)).to.be(null); + expect(topHitMetricAgg.getValue(aggConfig, bucket)).to.be(null); }); it('should return undefined if the field does not appear in the source', function () { @@ -125,7 +123,7 @@ describe('Top hit metric', function () { }; init({ field: '@tags' }); - expect(topHitMetric.getValue(aggConfig, bucket)).to.be(undefined); + expect(topHitMetricAgg.getValue(aggConfig, bucket)).to.be(undefined); }); it('should return the field value from the top hit', function () { @@ -144,7 +142,7 @@ describe('Top hit metric', function () { }; init({ field: '@tags' }); - expect(topHitMetric.getValue(aggConfig, bucket)).to.be('aaa'); + expect(topHitMetricAgg.getValue(aggConfig, bucket)).to.be('aaa'); }); it('should return the object if the field value is an object', function () { @@ -165,7 +163,7 @@ describe('Top hit metric', function () { }; init({ field: '@tags' }); - expect(topHitMetric.getValue(aggConfig, bucket)).to.eql({ label: 'aaa' }); + expect(topHitMetricAgg.getValue(aggConfig, bucket)).to.eql({ label: 'aaa' }); }); it('should return an array if the field has more than one values', function () { @@ -184,7 +182,7 @@ describe('Top hit metric', function () { }; init({ field: '@tags' }); - expect(topHitMetric.getValue(aggConfig, bucket)).to.eql([ 'aaa', 'bbb' ]); + expect(topHitMetricAgg.getValue(aggConfig, bucket)).to.eql([ 'aaa', 'bbb' ]); }); it('should get the value from the doc_values field if the source does not have that field', function () { @@ -206,7 +204,7 @@ describe('Top hit metric', function () { }; init({ field: 'machine.os.raw' }); - expect(topHitMetric.getValue(aggConfig, bucket)).to.be('linux'); + expect(topHitMetricAgg.getValue(aggConfig, bucket)).to.be('linux'); }); it('should return undefined if the field is not in the source nor in the doc_values field', function () { @@ -228,7 +226,7 @@ describe('Top hit metric', function () { }; init({ field: 'machine.os.raw' }); - expect(topHitMetric.getValue(aggConfig, bucket)).to.be(undefined); + expect(topHitMetricAgg.getValue(aggConfig, bucket)).to.be(undefined); }); describe('Multivalued field and first/last X docs', function () { @@ -237,7 +235,7 @@ describe('Top hit metric', function () { field: 'bytes', size: 2 }); - expect(topHitMetric.makeLabel(aggConfig)).to.eql('Last 2 bytes'); + expect(topHitMetricAgg.makeLabel(aggConfig)).to.eql('Last 2 bytes'); }); it('should return a label prefixed with First X docs if sorting in ascending order', function () { @@ -246,7 +244,7 @@ describe('Top hit metric', function () { size: 2, sortOrder: 'asc' }); - expect(topHitMetric.makeLabel(aggConfig)).to.eql('First 2 bytes'); + expect(topHitMetricAgg.makeLabel(aggConfig)).to.eql('First 2 bytes'); }); [ @@ -322,7 +320,7 @@ describe('Top hit metric', function () { }; init({ field: 'bytes', aggregate: agg.type }); - expect(topHitMetric.getValue(aggConfig, bucket)).to.eql(agg.result); + expect(topHitMetricAgg.getValue(aggConfig, bucket)).to.eql(agg.result); }); it(`should return the result of the ${agg.type} aggregation over the last X docs - ${agg.description}`, function () { @@ -346,7 +344,7 @@ describe('Top hit metric', function () { }; init({ field: 'bytes', aggregate: agg.type }); - expect(topHitMetric.getValue(aggConfig, bucket)).to.eql(agg.result); + expect(topHitMetricAgg.getValue(aggConfig, bucket)).to.eql(agg.result); }); }); }); diff --git a/src/ui/public/agg_types/agg_type.js b/src/ui/public/agg_types/agg_type.js index ad7355a133f2c..7ef81cf51a5d8 100644 --- a/src/ui/public/agg_types/agg_type.js +++ b/src/ui/public/agg_types/agg_type.js @@ -2,173 +2,168 @@ import _ from 'lodash'; import { AggParams } from './agg_params'; import { fieldFormats } from '../registry/field_formats'; -export function AggTypesAggTypeProvider() { +/** + * Generic AggType Constructor + * + * Used to create the values exposed by the agg_types module. + * + * @class AggType + * @private + * @param {object} config - used to set the properties of the AggType + */ +function AggType(config) { + /** + * the unique, unchanging, name that we have assigned this aggType + * + * @property name + * @type {string} + */ + this.name = config.name; + /** + * the name of the elasticsearch aggregation that this aggType represents. Usually just this.name + * + * @property name + * @type {string} + */ + this.dslName = config.dslName || config.name; /** - * Generic AggType Constructor + * the user friendly name that will be shown in the ui for this aggType * - * Used to create the values exposed by the agg_types module. + * @property title + * @type {string} + */ + this.title = config.title; + + /** + * a function that will be called when this aggType is assigned to + * an aggConfig, and that aggConfig is being rendered (in a form, chart, etc.). * - * @class AggType - * @private - * @param {object} config - used to set the properties of the AggType + * @method makeLabel + * @param {AggConfig} aggConfig - an agg config of this type + * @returns {string} - label that can be used in the ui to descripe the aggConfig */ - function AggType(config) { - - /** - * the unique, unchanging, name that we have assigned this aggType - * - * @property name - * @type {string} - */ - this.name = config.name; - - /** - * the name of the elasticsearch aggregation that this aggType represents. Usually just this.name - * - * @property name - * @type {string} - */ - this.dslName = config.dslName || config.name; - - /** - * the user friendly name that will be shown in the ui for this aggType - * - * @property title - * @type {string} - */ - this.title = config.title; - - /** - * a function that will be called when this aggType is assigned to - * an aggConfig, and that aggConfig is being rendered (in a form, chart, etc.). - * - * @method makeLabel - * @param {AggConfig} aggConfig - an agg config of this type - * @returns {string} - label that can be used in the ui to descripe the aggConfig - */ - this.makeLabel = config.makeLabel || _.constant(this.name); - - /** - * Describes if this aggType creates data that is ordered, and if that ordered data - * is some sort of time series. - * - * If the aggType does not create ordered data, set this to something "falsey". - * - * If this does create orderedData, then the value should be an object. - * - * If the orderdata is some sort of time series, `this.ordered` should be an object - * with the property `date: true` - * - * @property ordered - * @type {object|undefined} - */ - this.ordered = config.ordered; - - /** - * Flag that prevents this aggregation from being included in the dsl. This is only - * used by the count aggregation (currently) since it doesn't really exist and it's output - * is available on every bucket. - * - * @type {Boolean} - */ - this.hasNoDsl = !!config.hasNoDsl; - - /** - * The method to create a filter representation of the bucket - * @param {object} aggConfig The instance of the aggConfig - * @param {mixed} key The key for the bucket - * @returns {object} The filter - */ - this.createFilter = config.createFilter; - - /** - * An instance of {{#crossLink "AggParams"}}{{/crossLink}}. - * - * @property params - * @type {AggParams} - */ - this.params = config.params || []; - if (!(this.params instanceof AggParams)) { - // always append the raw JSON param - this.params.push({ - name: 'json', - type: 'json', - advanced: true - }); - // always append custom label + this.makeLabel = config.makeLabel || _.constant(this.name); - if (config.customLabels !== false) { - this.params.push({ - name: 'customLabel', - type: 'string', - write: _.noop - }); - } + /** + * Describes if this aggType creates data that is ordered, and if that ordered data + * is some sort of time series. + * + * If the aggType does not create ordered data, set this to something "falsey". + * + * If this does create orderedData, then the value should be an object. + * + * If the orderdata is some sort of time series, `this.ordered` should be an object + * with the property `date: true` + * + * @property ordered + * @type {object|undefined} + */ + this.ordered = config.ordered; - this.params = new AggParams(this.params); - } + /** + * Flag that prevents this aggregation from being included in the dsl. This is only + * used by the count aggregation (currently) since it doesn't really exist and it's output + * is available on every bucket. + * + * @type {Boolean} + */ + this.hasNoDsl = !!config.hasNoDsl; - /** - * Designed for multi-value metric aggs, this method can return a - * set of AggConfigs that should replace this aggConfig in requests - * - * @method getRequestAggs - * @returns {array[AggConfig]|undefined} - an array of aggConfig objects - * that should replace this one, - * or undefined - */ - this.getRequestAggs = config.getRequestAggs || _.noop; - - /** - * Designed for multi-value metric aggs, this method can return a - * set of AggConfigs that should replace this aggConfig in result sets - * that walk the AggConfig set. - * - * @method getResponseAggs - * @returns {array[AggConfig]|undefined} - an array of aggConfig objects - * that should replace this one, - * or undefined - */ - this.getResponseAggs = config.getResponseAggs || _.noop; - - /** - * A function that will be called each time an aggConfig of this type - * is created, giving the agg type a chance to modify the agg config - */ - this.decorateAggConfig = config.decorateAggConfig || null; - - /** - * A function that needs to be called after the main request has been made - * and should return an updated response - * @param aggConfigs - agg config array used to produce main request - * @param aggConfig - AggConfig that requested the post flight request - * @param searchSourceAggs - SearchSource aggregation configuration - * @param resp - Response to the main request - * @param nestedSearchSource - the new SearchSource that will be used to make post flight request - * @return {Promise} - */ - this.postFlightRequest = config.postFlightRequest || _.identity; - - if (config.getFormat) { - this.getFormat = config.getFormat; + /** + * The method to create a filter representation of the bucket + * @param {object} aggConfig The instance of the aggConfig + * @param {mixed} key The key for the bucket + * @returns {object} The filter + */ + this.createFilter = config.createFilter; + + /** + * An instance of {{#crossLink "AggParams"}}{{/crossLink}}. + * + * @property params + * @type {AggParams} + */ + this.params = config.params || []; + if (!(this.params instanceof AggParams)) { + // always append the raw JSON param + this.params.push({ + name: 'json', + type: 'json', + advanced: true + }); + // always append custom label + + if (config.customLabels !== false) { + this.params.push({ + name: 'customLabel', + type: 'string', + write: _.noop + }); } + + this.params = new AggParams(this.params); } /** - * Pick a format for the values produced by this agg type, - * overriden by several metrics that always output a simple - * number + * Designed for multi-value metric aggs, this method can return a + * set of AggConfigs that should replace this aggConfig in requests * - * @param {agg} agg - the agg to pick a format for - * @return {FieldFromat} + * @method getRequestAggs + * @returns {array[AggConfig]|undefined} - an array of aggConfig objects + * that should replace this one, + * or undefined */ - AggType.prototype.getFormat = function (agg) { - const field = agg.getField(); - return field ? field.format : fieldFormats.getDefaultInstance('string'); - }; + this.getRequestAggs = config.getRequestAggs || _.noop; - return AggType; + /** + * Designed for multi-value metric aggs, this method can return a + * set of AggConfigs that should replace this aggConfig in result sets + * that walk the AggConfig set. + * + * @method getResponseAggs + * @returns {array[AggConfig]|undefined} - an array of aggConfig objects + * that should replace this one, + * or undefined + */ + this.getResponseAggs = config.getResponseAggs || _.noop; + + /** + * A function that will be called each time an aggConfig of this type + * is created, giving the agg type a chance to modify the agg config + */ + this.decorateAggConfig = config.decorateAggConfig || null; + + /** + * A function that needs to be called after the main request has been made + * and should return an updated response + * @param aggConfigs - agg config array used to produce main request + * @param aggConfig - AggConfig that requested the post flight request + * @param searchSourceAggs - SearchSource aggregation configuration + * @param resp - Response to the main request + * @param nestedSearchSource - the new SearchSource that will be used to make post flight request + * @return {Promise} + */ + this.postFlightRequest = config.postFlightRequest || _.identity; + + if (config.getFormat) { + this.getFormat = config.getFormat; + } } + +/** + * Pick a format for the values produced by this agg type, + * overriden by several metrics that always output a simple + * number + * + * @param {agg} agg - the agg to pick a format for + * @return {FieldFromat} + */ +AggType.prototype.getFormat = function (agg) { + const field = agg.getField(); + return field ? field.format : fieldFormats.getDefaultInstance('string'); +}; + +export { AggType }; diff --git a/src/ui/public/agg_types/buckets/_bucket_agg_type.js b/src/ui/public/agg_types/buckets/_bucket_agg_type.js index 1b56103bffac3..0f4a9ab478476 100644 --- a/src/ui/public/agg_types/buckets/_bucket_agg_type.js +++ b/src/ui/public/agg_types/buckets/_bucket_agg_type.js @@ -1,22 +1,18 @@ import _ from 'lodash'; -import { AggTypesAggTypeProvider } from '../agg_type'; +import { AggType } from '../agg_type'; import { createLegacyClass } from '../../utils/legacy_class'; -export function AggTypesBucketsBucketAggTypeProvider(Private) { - const AggType = Private(AggTypesAggTypeProvider); +createLegacyClass(BucketAggType).inherits(AggType); +function BucketAggType(config) { + BucketAggType.Super.call(this, config); - createLegacyClass(BucketAggType).inherits(AggType); - function BucketAggType(config) { - BucketAggType.Super.call(this, config); - - if (_.isFunction(config.getKey)) { - this.getKey = config.getKey; - } + if (_.isFunction(config.getKey)) { + this.getKey = config.getKey; } +} - BucketAggType.prototype.getKey = function (bucket, key) { - return key || bucket.key; - }; +BucketAggType.prototype.getKey = function (bucket, key) { + return key || bucket.key; +}; - return BucketAggType; -} +export { BucketAggType }; diff --git a/src/ui/public/agg_types/buckets/_interval_options.js b/src/ui/public/agg_types/buckets/_interval_options.js index b04455c68b2cf..541df52ce9510 100644 --- a/src/ui/public/agg_types/buckets/_interval_options.js +++ b/src/ui/public/agg_types/buckets/_interval_options.js @@ -1,49 +1,47 @@ -export function AggTypesBucketsIntervalOptionsProvider() { - return [ - { - display: 'Auto', - val: 'auto', - enabled: function (agg) { - // not only do we need a time field, but the selected field needs - // to be the time field. (see #3028) - return agg.fieldIsTimeField(); - } - }, - { - display: 'Millisecond', - val: 'ms' - }, - { - display: 'Second', - val: 's' - }, - { - display: 'Minute', - val: 'm' - }, - { - display: 'Hourly', - val: 'h' - }, - { - display: 'Daily', - val: 'd' - }, - { - display: 'Weekly', - val: 'w' - }, - { - display: 'Monthly', - val: 'M' - }, - { - display: 'Yearly', - val: 'y' - }, - { - display: 'Custom', - val: 'custom' +export const intervalOptions = [ + { + display: 'Auto', + val: 'auto', + enabled: function (agg) { + // not only do we need a time field, but the selected field needs + // to be the time field. (see #3028) + return agg.fieldIsTimeField(); } - ]; -} + }, + { + display: 'Millisecond', + val: 'ms' + }, + { + display: 'Second', + val: 's' + }, + { + display: 'Minute', + val: 'm' + }, + { + display: 'Hourly', + val: 'h' + }, + { + display: 'Daily', + val: 'd' + }, + { + display: 'Weekly', + val: 'w' + }, + { + display: 'Monthly', + val: 'M' + }, + { + display: 'Yearly', + val: 'y' + }, + { + display: 'Custom', + val: 'custom' + } +]; diff --git a/src/ui/public/agg_types/buckets/_terms_other_bucket_helper.js b/src/ui/public/agg_types/buckets/_terms_other_bucket_helper.js index e190041abef85..d4123929d0f76 100644 --- a/src/ui/public/agg_types/buckets/_terms_other_bucket_helper.js +++ b/src/ui/public/agg_types/buckets/_terms_other_bucket_helper.js @@ -83,104 +83,100 @@ const getOtherAggTerms = (requestAgg, key, otherAgg) => { ); }; +const buildOtherBucketAgg = (aggConfigs, aggWithOtherBucket, response) => { + const bucketAggs = aggConfigs.filter(agg => agg.type.type === 'buckets'); + const index = bucketAggs.findIndex(agg => agg.id === aggWithOtherBucket.id); + const aggs = aggConfigs.toDsl(); + const indexPattern = aggWithOtherBucket.params.field.indexPattern; + + // create filters aggregation + const filterAgg = new AggConfig(aggConfigs[index].vis, { + type: 'filters', + id: 'other', + schema: { + group: 'buckets' + } + }); -export const OtherBucketHelperProvider = () => { - - const buildOtherBucketAgg = (aggConfigs, aggWithOtherBucket, response) => { - const bucketAggs = aggConfigs.filter(agg => agg.type.type === 'buckets'); - const index = bucketAggs.findIndex(agg => agg.id === aggWithOtherBucket.id); - const aggs = aggConfigs.toDsl(); - const indexPattern = aggWithOtherBucket.params.field.indexPattern; - - // create filters aggregation - const filterAgg = new AggConfig(aggConfigs[index].vis, { - type: 'filters', - id: 'other', - schema: { - group: 'buckets' - } - }); - - // nest all the child aggregations of aggWithOtherBucket - const resultAgg = { - aggs: getNestedAggDSL(aggs, aggWithOtherBucket.id).aggs, - filters: filterAgg.toDsl(), - }; + // nest all the child aggregations of aggWithOtherBucket + const resultAgg = { + aggs: getNestedAggDSL(aggs, aggWithOtherBucket.id).aggs, + filters: filterAgg.toDsl(), + }; - // create filters for all parent aggregation buckets - const walkBucketTree = (aggIndex, aggs, aggId, filters, key) => { - const agg = aggs[aggId]; - const newAggIndex = aggIndex + 1; - const newAgg = bucketAggs[newAggIndex]; - const currentAgg = bucketAggs[aggIndex]; - if (aggIndex < index) { - _.each(agg.buckets, (bucket, bucketObjKey) => { - const bucketKey = currentAgg.getKey(bucket, Number.isInteger(bucketObjKey) ? null : bucketObjKey); - const filter = _.cloneDeep(bucket.filter) || currentAgg.createFilter(bucketKey); - const newFilters = [...filters, filter]; - walkBucketTree(newAggIndex, bucket, newAgg.id, newFilters, `${key}-${bucketKey.toString()}`); - }); - return; - } + // create filters for all parent aggregation buckets + const walkBucketTree = (aggIndex, aggs, aggId, filters, key) => { + const agg = aggs[aggId]; + const newAggIndex = aggIndex + 1; + const newAgg = bucketAggs[newAggIndex]; + const currentAgg = bucketAggs[aggIndex]; + if (aggIndex < index) { + _.each(agg.buckets, (bucket, bucketObjKey) => { + const bucketKey = currentAgg.getKey(bucket, Number.isInteger(bucketObjKey) ? null : bucketObjKey); + const filter = _.cloneDeep(bucket.filter) || currentAgg.createFilter(bucketKey); + const newFilters = [...filters, filter]; + walkBucketTree(newAggIndex, bucket, newAgg.id, newFilters, `${key}-${bucketKey.toString()}`); + }); + return; + } - if (!aggWithOtherBucket.params.missingBucket || agg.buckets.some(bucket => bucket.key === '__missing__')) { - filters.push(buildExistsFilter(aggWithOtherBucket.params.field, aggWithOtherBucket.params.field.indexPattern)); - } + if (!aggWithOtherBucket.params.missingBucket || agg.buckets.some(bucket => bucket.key === '__missing__')) { + filters.push(buildExistsFilter(aggWithOtherBucket.params.field, aggWithOtherBucket.params.field.indexPattern)); + } - // create not filters for all the buckets - _.each(agg.buckets, bucket => { - if (bucket.key === '__missing__') return; - const filter = currentAgg.createFilter(bucket.key); - filter.meta.negate = true; - filters.push(filter); - }); + // create not filters for all the buckets + _.each(agg.buckets, bucket => { + if (bucket.key === '__missing__') return; + const filter = currentAgg.createFilter(bucket.key); + filter.meta.negate = true; + filters.push(filter); + }); - resultAgg.filters.filters[key] = { - bool: buildQueryFromFilters(filters, _.noop, indexPattern) - }; + resultAgg.filters.filters[key] = { + bool: buildQueryFromFilters(filters, _.noop, indexPattern) }; - walkBucketTree(0, response.aggregations, bucketAggs[0].id, [], ''); + }; + walkBucketTree(0, response.aggregations, bucketAggs[0].id, [], ''); - return () => { - return { - 'other-filter': resultAgg - }; + return () => { + return { + 'other-filter': resultAgg }; }; +}; - const mergeOtherBucketAggResponse = (aggsConfig, response, otherResponse, otherAgg, requestAgg) => { - const updatedResponse = _.cloneDeep(response); - _.each(otherResponse.aggregations['other-filter'].buckets, (bucket, key) => { - if (!bucket.doc_count) return; - const bucketKey = key.replace(/^-/, ''); - const aggResultBuckets = getAggResultBuckets(aggsConfig, updatedResponse.aggregations, otherAgg, bucketKey); - const requestFilterTerms = getOtherAggTerms(requestAgg, key, otherAgg); - - const phraseFilter = buildPhrasesFilter(otherAgg.params.field, requestFilterTerms, otherAgg.params.field.indexPattern); - phraseFilter.meta.negate = true; - bucket.filters = [ phraseFilter ]; - bucket.key = otherAgg.params.otherBucketLabel; - - if (aggResultBuckets.some(bucket => bucket.key === '__missing__')) { - bucket.filters.push(buildExistsFilter(otherAgg.params.field, otherAgg.params.field.indexPattern)); - } - - aggResultBuckets.push(bucket); - }); - return updatedResponse; - }; +const mergeOtherBucketAggResponse = (aggsConfig, response, otherResponse, otherAgg, requestAgg) => { + const updatedResponse = _.cloneDeep(response); + _.each(otherResponse.aggregations['other-filter'].buckets, (bucket, key) => { + if (!bucket.doc_count) return; + const bucketKey = key.replace(/^-/, ''); + const aggResultBuckets = getAggResultBuckets(aggsConfig, updatedResponse.aggregations, otherAgg, bucketKey); + const requestFilterTerms = getOtherAggTerms(requestAgg, key, otherAgg); + + const phraseFilter = buildPhrasesFilter(otherAgg.params.field, requestFilterTerms, otherAgg.params.field.indexPattern); + phraseFilter.meta.negate = true; + bucket.filters = [ phraseFilter ]; + bucket.key = otherAgg.params.otherBucketLabel; + + if (aggResultBuckets.some(bucket => bucket.key === '__missing__')) { + bucket.filters.push(buildExistsFilter(otherAgg.params.field, otherAgg.params.field.indexPattern)); + } - const updateMissingBucket = (response, aggConfigs, agg) => { - const updatedResponse = _.cloneDeep(response); - const aggResultBuckets = getAggConfigResultMissingBuckets(updatedResponse.aggregations, agg.id); - aggResultBuckets.forEach(bucket => { - bucket.key = agg.params.missingBucketLabel; - const existsFilter = buildExistsFilter(agg.params.field, agg.params.field.indexPattern); - existsFilter.meta.negate = true; - bucket.filters = [ existsFilter ]; - }); - return updatedResponse; - }; + aggResultBuckets.push(bucket); + }); + return updatedResponse; +}; - return { buildOtherBucketAgg, mergeOtherBucketAggResponse, updateMissingBucket }; +const updateMissingBucket = (response, aggConfigs, agg) => { + const updatedResponse = _.cloneDeep(response); + const aggResultBuckets = getAggConfigResultMissingBuckets(updatedResponse.aggregations, agg.id); + aggResultBuckets.forEach(bucket => { + bucket.key = agg.params.missingBucketLabel; + const existsFilter = buildExistsFilter(agg.params.field, agg.params.field.indexPattern); + existsFilter.meta.negate = true; + bucket.filters = [ existsFilter ]; + }); + return updatedResponse; }; + +export { buildOtherBucketAgg, mergeOtherBucketAggResponse, updateMissingBucket }; diff --git a/src/ui/public/agg_types/buckets/create_filter/date_histogram.js b/src/ui/public/agg_types/buckets/create_filter/date_histogram.js index 07ca51926172a..4951052fb5ae6 100644 --- a/src/ui/public/agg_types/buckets/create_filter/date_histogram.js +++ b/src/ui/public/agg_types/buckets/create_filter/date_histogram.js @@ -1,17 +1,13 @@ import moment from 'moment'; import { buildRangeFilter } from '../../../filter_manager/lib/range'; -export function AggTypesBucketsCreateFilterDateHistogramProvider() { - - return function (agg, key) { - const start = moment(key); - const interval = agg.buckets.getInterval(); - - return buildRangeFilter(agg.params.field, { - gte: start.valueOf(), - lt: start.add(interval).valueOf(), - format: 'epoch_millis' - }, agg.vis.indexPattern); - }; - +export function createFilterDateHistogram(agg, key) { + const start = moment(key); + const interval = agg.buckets.getInterval(); + + return buildRangeFilter(agg.params.field, { + gte: start.valueOf(), + lt: start.add(interval).valueOf(), + format: 'epoch_millis' + }, agg.vis.indexPattern); } diff --git a/src/ui/public/agg_types/buckets/create_filter/date_range.js b/src/ui/public/agg_types/buckets/create_filter/date_range.js index 0ca083de1c09a..18c49a3df7f30 100644 --- a/src/ui/public/agg_types/buckets/create_filter/date_range.js +++ b/src/ui/public/agg_types/buckets/create_filter/date_range.js @@ -1,17 +1,16 @@ +import chrome from 'ui/chrome'; import { dateRange } from '../../../utils/date_range'; import { buildRangeFilter } from '../../../filter_manager/lib/range'; -export function AggTypesBucketsCreateFilterDateRangeProvider(config) { +const config = chrome.getUiSettingsClient(); - return function (agg, key) { - const range = dateRange.parse(key, config.get('dateFormat')); +export function createFilterDateRange(agg, key) { + const range = dateRange.parse(key, config.get('dateFormat')); - const filter = {}; - if (range.from) filter.gte = +range.from; - if (range.to) filter.lt = +range.to; - if (range.to && range.from) filter.format = 'epoch_millis'; - - return buildRangeFilter(agg.params.field, filter, agg.vis.indexPattern); - }; + const filter = {}; + if (range.from) filter.gte = +range.from; + if (range.to) filter.lt = +range.to; + if (range.to && range.from) filter.format = 'epoch_millis'; + return buildRangeFilter(agg.params.field, filter, agg.vis.indexPattern); } diff --git a/src/ui/public/agg_types/buckets/create_filter/filters.js b/src/ui/public/agg_types/buckets/create_filter/filters.js index 908e5d5dec81b..049fa916e3751 100644 --- a/src/ui/public/agg_types/buckets/create_filter/filters.js +++ b/src/ui/public/agg_types/buckets/create_filter/filters.js @@ -1,14 +1,12 @@ import { buildQueryFilter } from '../../../filter_manager/lib/query'; import _ from 'lodash'; -export function AggTypesBucketsCreateFilterFiltersProvider() { - return function (aggConfig, key) { - // have the aggConfig write agg dsl params - const dslFilters = _.get(aggConfig.toDsl(), 'filters.filters'); - const filter = dslFilters[key]; +export function createFilterFilters(aggConfig, key) { + // have the aggConfig write agg dsl params + const dslFilters = _.get(aggConfig.toDsl(), 'filters.filters'); + const filter = dslFilters[key]; - if (filter) { - return buildQueryFilter(filter.query, aggConfig.vis.indexPattern.id); - } - }; + if (filter) { + return buildQueryFilter(filter.query, aggConfig.vis.indexPattern.id); + } } diff --git a/src/ui/public/agg_types/buckets/create_filter/histogram.js b/src/ui/public/agg_types/buckets/create_filter/histogram.js index 6a0fe36bfcf0d..3a9b0bb6d04d4 100644 --- a/src/ui/public/agg_types/buckets/create_filter/histogram.js +++ b/src/ui/public/agg_types/buckets/create_filter/histogram.js @@ -1,14 +1,12 @@ import { buildRangeFilter } from '../../../filter_manager/lib/range'; -export function AggTypesBucketsCreateFilterHistogramProvider() { - return function (aggConfig, key) { - const value = parseInt(key, 10); +export function createFilterHistogram(aggConfig, key) { + const value = parseInt(key, 10); - return buildRangeFilter( - aggConfig.params.field, - { gte: value, lt: value + aggConfig.params.interval }, - aggConfig.vis.indexPattern, - aggConfig.fieldFormatter()(key) - ); - }; + return buildRangeFilter( + aggConfig.params.field, + { gte: value, lt: value + aggConfig.params.interval }, + aggConfig.vis.indexPattern, + aggConfig.fieldFormatter()(key) + ); } diff --git a/src/ui/public/agg_types/buckets/create_filter/ip_range.js b/src/ui/public/agg_types/buckets/create_filter/ip_range.js index 1055129491cf3..56032db262d9e 100644 --- a/src/ui/public/agg_types/buckets/create_filter/ip_range.js +++ b/src/ui/public/agg_types/buckets/create_filter/ip_range.js @@ -1,19 +1,17 @@ import { CidrMask } from '../../../utils/cidr_mask'; import { buildRangeFilter } from '../../../filter_manager/lib/range'; -export function AggTypesBucketsCreateFilterIpRangeProvider() { - return function (aggConfig, key) { - let range; - if (aggConfig.params.ipRangeType === 'mask') { - range = new CidrMask(key).getRange(); - } else { - const [from, to] = key.split(/\s+to\s+/); - range = { - from: from === '-Infinity' ? -Infinity : from, - to: to === 'Infinity' ? Infinity : to - }; - } +export function createFilterIpRange(aggConfig, key) { + let range; + if (aggConfig.params.ipRangeType === 'mask') { + range = new CidrMask(key).getRange(); + } else { + const [from, to] = key.split(/\s+to\s+/); + range = { + from: from === '-Infinity' ? -Infinity : from, + to: to === 'Infinity' ? Infinity : to + }; + } - return buildRangeFilter(aggConfig.params.field, { gte: range.from, lte: range.to }, aggConfig.vis.indexPattern); - }; + return buildRangeFilter(aggConfig.params.field, { gte: range.from, lte: range.to }, aggConfig.vis.indexPattern); } diff --git a/src/ui/public/agg_types/buckets/create_filter/range.js b/src/ui/public/agg_types/buckets/create_filter/range.js index 37062a2dc75f1..823bfeb63cc0c 100644 --- a/src/ui/public/agg_types/buckets/create_filter/range.js +++ b/src/ui/public/agg_types/buckets/create_filter/range.js @@ -1,12 +1,10 @@ import { buildRangeFilter } from '../../../filter_manager/lib/range'; -export function AggTypesBucketsCreateFilterRangeProvider() { - return function (aggConfig, key) { - return buildRangeFilter( - aggConfig.params.field, - key, - aggConfig.vis.indexPattern, - aggConfig.fieldFormatter()(key) - ); - }; +export function createFilterRange(aggConfig, key) { + return buildRangeFilter( + aggConfig.params.field, + key, + aggConfig.vis.indexPattern, + aggConfig.fieldFormatter()(key) + ); } diff --git a/src/ui/public/agg_types/buckets/create_filter/terms.js b/src/ui/public/agg_types/buckets/create_filter/terms.js index 9b501d12a1264..9511d2a505b8a 100644 --- a/src/ui/public/agg_types/buckets/create_filter/terms.js +++ b/src/ui/public/agg_types/buckets/create_filter/terms.js @@ -1,7 +1,5 @@ import { buildPhraseFilter } from '../../../filter_manager/lib/phrase'; -export function AggTypesBucketsCreateFilterTermsProvider() { - return function (aggConfig, key) { - return buildPhraseFilter(aggConfig.params.field, key, aggConfig.vis.indexPattern); - }; +export function createFilterTerms(aggConfig, key) { + return buildPhraseFilter(aggConfig.params.field, key, aggConfig.vis.indexPattern); } diff --git a/src/ui/public/agg_types/buckets/date_histogram.js b/src/ui/public/agg_types/buckets/date_histogram.js index 48978965b1ebe..a1ef774b00095 100644 --- a/src/ui/public/agg_types/buckets/date_histogram.js +++ b/src/ui/public/agg_types/buckets/date_histogram.js @@ -1,169 +1,164 @@ import { jstz as tzDetect } from 'jstimezonedetect'; import _ from 'lodash'; +import chrome from 'ui/chrome'; import moment from 'moment'; import '../../filters/field_type'; import '../../validate_date_interval'; -import { AggTypesBucketsBucketAggTypeProvider } from './_bucket_agg_type'; -import { TimeBucketsProvider } from '../../time_buckets'; -import { AggTypesBucketsCreateFilterDateHistogramProvider } from './create_filter/date_histogram'; -import { AggTypesBucketsIntervalOptionsProvider } from './_interval_options'; +import { BucketAggType } from './_bucket_agg_type'; +import { TimeBuckets } from '../../time_buckets'; +import { createFilterDateHistogram } from './create_filter/date_histogram'; +import { intervalOptions } from './_interval_options'; import intervalTemplate from '../controls/time_interval.html'; -export function AggTypesBucketsDateHistogramProvider(timefilter, config, Private) { - const BucketAggType = Private(AggTypesBucketsBucketAggTypeProvider); - const TimeBuckets = Private(TimeBucketsProvider); - const createFilter = Private(AggTypesBucketsCreateFilterDateHistogramProvider); - const intervalOptions = Private(AggTypesBucketsIntervalOptionsProvider); +const config = chrome.getUiSettingsClient(); +const detectedTimezone = tzDetect.determine().name(); +const tzOffset = moment().format('Z'); - const detectedTimezone = tzDetect.determine().name(); - const tzOffset = moment().format('Z'); - - function getInterval(agg) { - const interval = _.get(agg, ['params', 'interval']); - if (interval && interval.val === 'custom') { - return _.get(agg, ['params', 'customInterval']); - } - return interval; +function getInterval(agg) { + const interval = _.get(agg, ['params', 'interval']); + if (interval && interval.val === 'custom') { + return _.get(agg, ['params', 'customInterval']); } + return interval; +} - function getBounds(vis) { - if (timefilter.isTimeRangeSelectorEnabled && vis.filters) { - return timefilter.calculateBounds(vis.filters.timeRange); - } +function getBounds(vis) { + if (vis.API.timeFilter.isTimeRangeSelectorEnabled && vis.filters) { + return vis.API.timeFilter.calculateBounds(vis.filters.timeRange); } +} - function setBounds(agg, force) { - if (agg.buckets._alreadySet && !force) return; - agg.buckets._alreadySet = true; - const bounds = getBounds(agg.vis); - agg.buckets.setBounds(agg.fieldIsTimeField() && bounds); - } +function setBounds(agg, force) { + if (agg.buckets._alreadySet && !force) return; + agg.buckets._alreadySet = true; + const bounds = getBounds(agg.vis); + agg.buckets.setBounds(agg.fieldIsTimeField() && bounds); +} - return new BucketAggType({ - name: 'date_histogram', - title: 'Date Histogram', - ordered: { - date: true - }, - makeLabel: function (agg) { - const output = this.params.write(agg); - const field = agg.getFieldDisplayName(); - return field + ' per ' + (output.metricScaleText || output.bucketInterval.description); - }, - createFilter: createFilter, - decorateAggConfig: function () { - let buckets; - return { - buckets: { - configurable: true, - get: function () { - if (buckets) return buckets; - - buckets = new TimeBuckets(); - buckets.setInterval(getInterval(this)); - setBounds(this); - - return buckets; - } +export const dateHistogramBucketAgg = new BucketAggType({ + name: 'date_histogram', + title: 'Date Histogram', + ordered: { + date: true + }, + makeLabel: function (agg) { + const output = this.params.write(agg); + const field = agg.getFieldDisplayName(); + return field + ' per ' + (output.metricScaleText || output.bucketInterval.description); + }, + createFilter: createFilterDateHistogram, + decorateAggConfig: function () { + let buckets; + return { + buckets: { + configurable: true, + get: function () { + if (buckets) return buckets; + + buckets = new TimeBuckets(); + buckets.setInterval(getInterval(this)); + setBounds(this); + + return buckets; } - }; - }, - getFormat: function (agg) { - return agg.buckets.getScaledDateFormatter(); + } + }; + }, + getFormat: function (agg) { + return agg.buckets.getScaledDateFormatter(); + }, + params: [ + { + name: 'field', + filterFieldTypes: 'date', + default: function (agg) { + return agg.vis.indexPattern.timeFieldName; + }, + onChange: function (agg) { + if (_.get(agg, 'params.interval.val') === 'auto' && !agg.fieldIsTimeField()) { + delete agg.params.interval; + } + + setBounds(agg, true); + } }, - params: [ - { - name: 'field', - filterFieldTypes: 'date', - default: function (agg) { - return agg.vis.indexPattern.timeFieldName; - }, - onChange: function (agg) { - if (_.get(agg, 'params.interval.val') === 'auto' && !agg.fieldIsTimeField()) { - delete agg.params.interval; - } - setBounds(agg, true); - } + { + name: 'interval', + type: 'optioned', + deserialize: function (state) { + const interval = _.find(intervalOptions, { val: state }); + return interval || _.find(intervalOptions, function (option) { + // For upgrading from 4.0.x to 4.1.x - intervals are now stored as 'y' instead of 'year', + // but this maps the old values to the new values + return Number(moment.duration(1, state)) === Number(moment.duration(1, option.val)); + }); + }, + default: 'auto', + options: intervalOptions, + editor: intervalTemplate, + modifyAggConfigOnSearchRequestStart: function (agg) { + setBounds(agg, true); }, + write: function (agg, output) { + setBounds(agg); + agg.buckets.setInterval(getInterval(agg)); + + const interval = agg.buckets.getInterval(); + output.bucketInterval = interval; + output.params.interval = interval.expression; + + const isDefaultTimezone = config.isDefault('dateFormat:tz'); + if (isDefaultTimezone) { + output.params.time_zone = detectedTimezone || tzOffset; + } else { + output.params.time_zone = config.get('dateFormat:tz'); + } - { - name: 'interval', - type: 'optioned', - deserialize: function (state) { - const interval = _.find(intervalOptions, { val: state }); - return interval || _.find(intervalOptions, function (option) { - // For upgrading from 4.0.x to 4.1.x - intervals are now stored as 'y' instead of 'year', - // but this maps the old values to the new values - return Number(moment.duration(1, state)) === Number(moment.duration(1, option.val)); + const scaleMetrics = interval.scaled && interval.scale < 1; + if (scaleMetrics) { + const all = _.every(agg.vis.getAggConfig().bySchemaGroup.metrics, function (agg) { + return agg.type && agg.type.isScalable(); }); - }, - default: 'auto', - options: intervalOptions, - editor: intervalTemplate, - modifyAggConfigOnSearchRequestStart: function (agg) { - setBounds(agg, true); - }, - write: function (agg, output) { - setBounds(agg); - agg.buckets.setInterval(getInterval(agg)); - - const interval = agg.buckets.getInterval(); - output.bucketInterval = interval; - output.params.interval = interval.expression; - - const isDefaultTimezone = config.isDefault('dateFormat:tz'); - if (isDefaultTimezone) { - output.params.time_zone = detectedTimezone || tzOffset; - } else { - output.params.time_zone = config.get('dateFormat:tz'); - } - - const scaleMetrics = interval.scaled && interval.scale < 1; - if (scaleMetrics) { - const all = _.every(agg.vis.getAggConfig().bySchemaGroup.metrics, function (agg) { - return agg.type && agg.type.isScalable(); - }); - if (all) { - output.metricScale = interval.scale; - output.metricScaleText = interval.preScaled.description; - } + if (all) { + output.metricScale = interval.scale; + output.metricScaleText = interval.preScaled.description; } } - }, + } + }, - { - name: 'customInterval', - default: '2h', - write: _.noop - }, + { + name: 'customInterval', + default: '2h', + write: _.noop + }, - { - name: 'format' - }, + { + name: 'format' + }, - { - name: 'min_doc_count', - default: 1 - }, + { + name: 'min_doc_count', + default: 1 + }, - { - name: 'extended_bounds', - default: {}, - write: function (agg, output) { - const val = agg.params.extended_bounds; + { + name: 'extended_bounds', + default: {}, + write: function (agg, output) { + const val = agg.params.extended_bounds; - if (val.min != null || val.max != null) { - output.params.extended_bounds = { - min: moment(val.min).valueOf(), - max: moment(val.max).valueOf() - }; + if (val.min != null || val.max != null) { + output.params.extended_bounds = { + min: moment(val.min).valueOf(), + max: moment(val.max).valueOf() + }; - return; - } + return; } } - ] - }); -} + } + ] +}); diff --git a/src/ui/public/agg_types/buckets/date_range.js b/src/ui/public/agg_types/buckets/date_range.js index ba44334de5463..751949d03d205 100644 --- a/src/ui/public/agg_types/buckets/date_range.js +++ b/src/ui/public/agg_types/buckets/date_range.js @@ -1,43 +1,37 @@ import { dateRange } from '../../utils/date_range'; import '../../directives/validate_date_math'; import '../../directives/documentation_href'; -import { AggTypesBucketsBucketAggTypeProvider } from './_bucket_agg_type'; -import { AggTypesBucketsCreateFilterDateRangeProvider } from './create_filter/date_range'; +import { BucketAggType } from './_bucket_agg_type'; +import { createFilterDateRange } from './create_filter/date_range'; import { fieldFormats } from '../../registry/field_formats'; import dateRangesTemplate from '../controls/date_ranges.html'; -export function AggTypesBucketsDateRangeProvider(Private) { - const BucketAggType = Private(AggTypesBucketsBucketAggTypeProvider); - const createFilter = Private(AggTypesBucketsCreateFilterDateRangeProvider); - - - return new BucketAggType({ - name: 'date_range', - title: 'Date Range', - createFilter: createFilter, - getKey: function (bucket, key, agg) { - const formatter = agg.fieldOwnFormatter('text', fieldFormats.getDefaultInstance('date')); - return dateRange.toString(bucket, formatter); - }, - getFormat: function () { - return fieldFormats.getDefaultInstance('string'); - }, - makeLabel: function (aggConfig) { - return aggConfig.getFieldDisplayName() + ' date ranges'; - }, - params: [{ - name: 'field', - filterFieldTypes: 'date', - default: function (agg) { - return agg.vis.indexPattern.timeFieldName; - } - }, { - name: 'ranges', - default: [{ - from: 'now-1w/w', - to: 'now' - }], - editor: dateRangesTemplate - }] - }); -} +export const dateRangeBucketAgg = new BucketAggType({ + name: 'date_range', + title: 'Date Range', + createFilter: createFilterDateRange, + getKey: function (bucket, key, agg) { + const formatter = agg.fieldOwnFormatter('text', fieldFormats.getDefaultInstance('date')); + return dateRange.toString(bucket, formatter); + }, + getFormat: function () { + return fieldFormats.getDefaultInstance('string'); + }, + makeLabel: function (aggConfig) { + return aggConfig.getFieldDisplayName() + ' date ranges'; + }, + params: [{ + name: 'field', + filterFieldTypes: 'date', + default: function (agg) { + return agg.vis.indexPattern.timeFieldName; + } + }, { + name: 'ranges', + default: [{ + from: 'now-1w/w', + to: 'now' + }], + editor: dateRangesTemplate + }] +}); diff --git a/src/ui/public/agg_types/buckets/filter.js b/src/ui/public/agg_types/buckets/filter.js index 77164d0abca9c..771d7fecaf7b2 100644 --- a/src/ui/public/agg_types/buckets/filter.js +++ b/src/ui/public/agg_types/buckets/filter.js @@ -1,15 +1,11 @@ -import { AggTypesBucketsBucketAggTypeProvider } from './_bucket_agg_type'; +import { BucketAggType } from './_bucket_agg_type'; -export function AggTypesBucketsFilterProvider(Private) { - const BucketAggType = Private(AggTypesBucketsBucketAggTypeProvider); - - return new BucketAggType({ - name: 'filter', - title: 'Filter', - params: [ - { - name: 'geo_bounding_box' - } - ] - }); -} +export const filterBucketAgg = new BucketAggType({ + name: 'filter', + title: 'Filter', + params: [ + { + name: 'geo_bounding_box' + } + ] +}); diff --git a/src/ui/public/agg_types/buckets/filters.js b/src/ui/public/agg_types/buckets/filters.js index 56dc1ffd0ac3e..95f398b0e7c49 100644 --- a/src/ui/public/agg_types/buckets/filters.js +++ b/src/ui/public/agg_types/buckets/filters.js @@ -2,51 +2,46 @@ import _ from 'lodash'; import angular from 'angular'; import { luceneStringToDsl } from '../../courier/data_source/build_query/lucene_string_to_dsl.js'; -import { AggTypesBucketsBucketAggTypeProvider } from './_bucket_agg_type'; -import { AggTypesBucketsCreateFilterFiltersProvider } from './create_filter/filters'; -import { DecorateQueryProvider } from '../../courier/data_source/_decorate_query'; +import { BucketAggType } from './_bucket_agg_type'; +import { createFilterFilters } from './create_filter/filters'; +import { decorateQuery } from '../../courier/data_source/_decorate_query'; import filtersTemplate from '../controls/filters.html'; -export function AggTypesBucketsFiltersProvider(Private, Notifier) { - const BucketAggType = Private(AggTypesBucketsBucketAggTypeProvider); - const createFilter = Private(AggTypesBucketsCreateFilterFiltersProvider); - const decorateQuery = Private(DecorateQueryProvider); - const notif = new Notifier({ location: 'Filters Agg' }); - - return new BucketAggType({ - name: 'filters', - title: 'Filters', - createFilter: createFilter, - customLabels: false, - params: [ - { - name: 'filters', - editor: filtersTemplate, - default: [ { input: {}, label: '' } ], - write: function (aggConfig, output) { - const inFilters = aggConfig.params.filters; - if (!_.size(inFilters)) return; - - const outFilters = _.transform(inFilters, function (filters, filter) { - const input = _.cloneDeep(filter.input); - if (!input) return notif.log('malformed filter agg params, missing "input" query'); - - const query = input.query = luceneStringToDsl(input.query); - if (!query) return notif.log('malformed filter agg params, missing "query" on input'); - - decorateQuery(query); - - const matchAllLabel = (filter.input.query === '' && _.has(query, 'match_all')) ? '*' : ''; - const label = filter.label || matchAllLabel || _.get(query, 'query_string.query') || angular.toJson(query); - filters[label] = input; - }, {}); - - if (!_.size(outFilters)) return; - - const params = output.params || (output.params = {}); - params.filters = outFilters; - } +import { toastNotifications } from 'ui/notify'; + +export const filtersBucketAgg = new BucketAggType({ + name: 'filters', + title: 'Filters', + createFilter: createFilterFilters, + customLabels: false, + params: [ + { + name: 'filters', + editor: filtersTemplate, + default: [ { input: {}, label: '' } ], + write: function (aggConfig, output) { + const inFilters = aggConfig.params.filters; + if (!_.size(inFilters)) return; + + const outFilters = _.transform(inFilters, function (filters, filter) { + const input = _.cloneDeep(filter.input); + if (!input) return toastNotifications.add('malformed filter agg params, missing "input" query'); + + const query = input.query = luceneStringToDsl(input.query); + if (!query) return toastNotifications.add('malformed filter agg params, missing "query" on input'); + + decorateQuery(query); + + const matchAllLabel = (filter.input.query === '' && _.has(query, 'match_all')) ? '*' : ''; + const label = filter.label || matchAllLabel || _.get(query, 'query_string.query') || angular.toJson(query); + filters[label] = input; + }, {}); + + if (!_.size(outFilters)) return; + + const params = output.params || (output.params = {}); + params.filters = outFilters; } - ] - }); -} + } + ] +}); diff --git a/src/ui/public/agg_types/buckets/geo_hash.js b/src/ui/public/agg_types/buckets/geo_hash.js index 41ad25be0a58d..b74df06de69fa 100644 --- a/src/ui/public/agg_types/buckets/geo_hash.js +++ b/src/ui/public/agg_types/buckets/geo_hash.js @@ -1,157 +1,156 @@ import _ from 'lodash'; -import { AggTypesBucketsBucketAggTypeProvider } from './_bucket_agg_type'; +import chrome from 'ui/chrome'; +import { BucketAggType } from './_bucket_agg_type'; import { AggConfig } from '../../vis/agg_config'; import precisionTemplate from '../controls/precision.html'; import { geohashColumns } from '../../utils/decode_geo_hash'; import { geoContains, scaleBounds } from '../../utils/geo_utils'; -export function AggTypesBucketsGeoHashProvider(Private, config) { - const BucketAggType = Private(AggTypesBucketsBucketAggTypeProvider); +const config = chrome.getUiSettingsClient(); - const defaultPrecision = 2; - const maxPrecision = parseInt(config.get('visualization:tileMap:maxPrecision'), 10) || 12; - /** - * Map Leaflet zoom levels to geohash precision levels. - * The size of a geohash column-width on the map should be at least `minGeohashPixels` pixels wide. - */ - const zoomPrecision = {}; - const minGeohashPixels = 16; - for (let zoom = 0; zoom <= 21; zoom += 1) { - const worldPixels = 256 * Math.pow(2, zoom); - zoomPrecision[zoom] = 1; - for (let precision = 2; precision <= maxPrecision; precision += 1) { - const columns = geohashColumns(precision); - if ((worldPixels / columns) >= minGeohashPixels) { - zoomPrecision[zoom] = precision; - } else { - break; - } +const defaultPrecision = 2; +const maxPrecision = parseInt(config.get('visualization:tileMap:maxPrecision'), 10) || 12; +/** + * Map Leaflet zoom levels to geohash precision levels. + * The size of a geohash column-width on the map should be at least `minGeohashPixels` pixels wide. + */ +const zoomPrecision = {}; +const minGeohashPixels = 16; +for (let zoom = 0; zoom <= 21; zoom += 1) { + const worldPixels = 256 * Math.pow(2, zoom); + zoomPrecision[zoom] = 1; + for (let precision = 2; precision <= maxPrecision; precision += 1) { + const columns = geohashColumns(precision); + if ((worldPixels / columns) >= minGeohashPixels) { + zoomPrecision[zoom] = precision; + } else { + break; } } +} - function getPrecision(precision) { - - precision = parseInt(precision, 10); +function getPrecision(precision) { - if (isNaN(precision)) { - precision = defaultPrecision; - } + precision = parseInt(precision, 10); - if (precision > maxPrecision) { - return maxPrecision; - } + if (isNaN(precision)) { + precision = defaultPrecision; + } - return precision; + if (precision > maxPrecision) { + return maxPrecision; } - function getMapZoom(vis) { - if (vis.hasUiState() && parseInt(vis.uiStateVal('mapZoom')) >= 0) { - return parseInt(vis.uiStateVal('mapZoom')); - } + return precision; +} - return vis.params.mapZoom; +function getMapZoom(vis) { + if (vis.hasUiState() && parseInt(vis.uiStateVal('mapZoom')) >= 0) { + return parseInt(vis.uiStateVal('mapZoom')); } - function isOutsideCollar(bounds, collar) { - return bounds && collar && !geoContains(collar, bounds); - } + return vis.params.mapZoom; +} - return new BucketAggType({ - name: 'geohash_grid', - title: 'Geohash', - params: [ - { - name: 'field', - filterFieldTypes: 'geo_point' - }, - { - name: 'autoPrecision', - default: true, - write: _.noop - }, - { - name: 'isFilteredByCollar', - default: true, - write: _.noop - }, - { - name: 'useGeocentroid', - default: true, - write: _.noop - }, - { - name: 'mapZoom', - write: _.noop - }, - { - name: 'mapCenter', - write: _.noop +function isOutsideCollar(bounds, collar) { + return bounds && collar && !geoContains(collar, bounds); +} + +export const geoHashBucketAgg = new BucketAggType({ + name: 'geohash_grid', + title: 'Geohash', + params: [ + { + name: 'field', + filterFieldTypes: 'geo_point' + }, + { + name: 'autoPrecision', + default: true, + write: _.noop + }, + { + name: 'isFilteredByCollar', + default: true, + write: _.noop + }, + { + name: 'useGeocentroid', + default: true, + write: _.noop + }, + { + name: 'mapZoom', + write: _.noop + }, + { + name: 'mapCenter', + write: _.noop + }, + { + name: 'precision', + editor: precisionTemplate, + default: defaultPrecision, + deserialize: getPrecision, + controller: function () { }, - { - name: 'precision', - editor: precisionTemplate, - default: defaultPrecision, - deserialize: getPrecision, - controller: function () { - }, - write: function (aggConfig, output) { - const vis = aggConfig.vis; - const currZoom = getMapZoom(vis); - const autoPrecisionVal = zoomPrecision[currZoom]; - output.params.precision = aggConfig.params.autoPrecision ? autoPrecisionVal : getPrecision(aggConfig.params.precision); - } + write: function (aggConfig, output) { + const vis = aggConfig.vis; + const currZoom = getMapZoom(vis); + const autoPrecisionVal = zoomPrecision[currZoom]; + output.params.precision = aggConfig.params.autoPrecision ? autoPrecisionVal : getPrecision(aggConfig.params.precision); } - ], - getRequestAggs: function (agg) { - const aggs = []; + } + ], + getRequestAggs: function (agg) { + const aggs = []; - if (agg.params.isFilteredByCollar && agg.getField()) { - const vis = agg.vis; - const mapBounds = vis.sessionState.mapBounds; - const mapZoom = getMapZoom(vis); - if (mapBounds) { - const lastMapCollar = vis.sessionState.mapCollar; - let mapCollar; - if (!lastMapCollar || lastMapCollar.zoom !== mapZoom || isOutsideCollar(mapBounds, lastMapCollar)) { - mapCollar = scaleBounds(mapBounds); - mapCollar.zoom = mapZoom; - vis.sessionState.mapCollar = mapCollar; - } else { - mapCollar = lastMapCollar; - } - const boundingBox = {}; - boundingBox[agg.getField().name] = { - top_left: mapCollar.top_left, - bottom_right: mapCollar.bottom_right - }; - aggs.push(new AggConfig(agg.vis, { - type: 'filter', - id: 'filter_agg', - enabled: true, - params: { - geo_bounding_box: boundingBox - }, - schema: { - group: 'buckets' - } - })); + if (agg.params.isFilteredByCollar && agg.getField()) { + const vis = agg.vis; + const mapBounds = vis.sessionState.mapBounds; + const mapZoom = getMapZoom(vis); + if (mapBounds) { + const lastMapCollar = vis.sessionState.mapCollar; + let mapCollar; + if (!lastMapCollar || lastMapCollar.zoom !== mapZoom || isOutsideCollar(mapBounds, lastMapCollar)) { + mapCollar = scaleBounds(mapBounds); + mapCollar.zoom = mapZoom; + vis.sessionState.mapCollar = mapCollar; + } else { + mapCollar = lastMapCollar; } - } - - aggs.push(agg); - - if (agg.params.useGeocentroid) { + const boundingBox = {}; + boundingBox[agg.getField().name] = { + top_left: mapCollar.top_left, + bottom_right: mapCollar.bottom_right + }; aggs.push(new AggConfig(agg.vis, { - type: 'geo_centroid', + type: 'filter', + id: 'filter_agg', enabled: true, params: { - field: agg.getField() + geo_bounding_box: boundingBox }, - schema: 'metric' + schema: { + group: 'buckets' + } })); } + } - return aggs; + aggs.push(agg); + + if (agg.params.useGeocentroid) { + aggs.push(new AggConfig(agg.vis, { + type: 'geo_centroid', + enabled: true, + params: { + field: agg.getField() + }, + schema: 'metric' + })); } - }); -} + + return aggs; + } +}); diff --git a/src/ui/public/agg_types/buckets/histogram.js b/src/ui/public/agg_types/buckets/histogram.js index f078a8717d265..6189b56db86dd 100644 --- a/src/ui/public/agg_types/buckets/histogram.js +++ b/src/ui/public/agg_types/buckets/histogram.js @@ -1,142 +1,139 @@ import _ from 'lodash'; import '../../validate_date_interval'; -import { AggTypesBucketsBucketAggTypeProvider } from './_bucket_agg_type'; -import { AggTypesBucketsCreateFilterHistogramProvider } from './create_filter/histogram'; +import chrome from 'ui/chrome'; +import { BucketAggType } from './_bucket_agg_type'; +import { createFilterHistogram } from './create_filter/histogram'; import intervalTemplate from '../controls/number_interval.html'; import minDocCountTemplate from '../controls/min_doc_count.html'; import extendedBoundsTemplate from '../controls/extended_bounds.html'; -export function AggTypesBucketsHistogramProvider(Private, config) { - const BucketAggType = Private(AggTypesBucketsBucketAggTypeProvider); - const createFilter = Private(AggTypesBucketsCreateFilterHistogramProvider); +const config = chrome.getUiSettingsClient(); +export const histogramBucketAgg = new BucketAggType({ + name: 'histogram', + title: 'Histogram', + ordered: {}, + makeLabel: function (aggConfig) { + return aggConfig.getFieldDisplayName(); + }, + createFilter: createFilterHistogram, + decorateAggConfig: function () { + let autoBounds; - return new BucketAggType({ - name: 'histogram', - title: 'Histogram', - ordered: {}, - makeLabel: function (aggConfig) { - return aggConfig.getFieldDisplayName(); - }, - createFilter: createFilter, - decorateAggConfig: function () { - let autoBounds; - - return { - setAutoBounds: { - configurable: true, - value(newValue) { - autoBounds = newValue; - } - }, - getAutoBounds: { - configurable: true, - value() { - return autoBounds; - } + return { + setAutoBounds: { + configurable: true, + value(newValue) { + autoBounds = newValue; } - }; - }, - params: [ - { - name: 'field', - filterFieldTypes: 'number' }, + getAutoBounds: { + configurable: true, + value() { + return autoBounds; + } + } + }; + }, + params: [ + { + name: 'field', + filterFieldTypes: 'number' + }, - { - name: 'interval', - editor: intervalTemplate, - modifyAggConfigOnSearchRequestStart(aggConfig, searchSource) { - const field = aggConfig.getField(); - const aggBody = field.scripted - ? { script: { inline: field.script, lang: field.lang } } - : { field: field.name }; + { + name: 'interval', + editor: intervalTemplate, + modifyAggConfigOnSearchRequestStart(aggConfig, searchSource) { + const field = aggConfig.getField(); + const aggBody = field.scripted + ? { script: { inline: field.script, lang: field.lang } } + : { field: field.name }; - return searchSource - .extend() - .size(0) - .aggs({ - maxAgg: { - max: aggBody - }, - minAgg: { - min: aggBody - } - }) - .fetchAsRejectablePromise() - .then((resp) => { - aggConfig.setAutoBounds({ - min: _.get(resp, 'aggregations.minAgg.value'), - max: _.get(resp, 'aggregations.maxAgg.value') - }); + return searchSource + .extend() + .size(0) + .aggs({ + maxAgg: { + max: aggBody + }, + minAgg: { + min: aggBody + } + }) + .fetchAsRejectablePromise() + .then((resp) => { + aggConfig.setAutoBounds({ + min: _.get(resp, 'aggregations.minAgg.value'), + max: _.get(resp, 'aggregations.maxAgg.value') }); - }, - write: function (aggConfig, output) { - let interval = parseFloat(aggConfig.params.interval); - if (interval <= 0) { - interval = 1; - } + }); + }, + write: function (aggConfig, output) { + let interval = parseFloat(aggConfig.params.interval); + if (interval <= 0) { + interval = 1; + } - // ensure interval does not create too many buckets and crash browser - if (aggConfig.getAutoBounds()) { - const range = aggConfig.getAutoBounds().max - aggConfig.getAutoBounds().min; - const bars = range / interval; - if (bars > config.get('histogram:maxBars')) { - const minInterval = range / config.get('histogram:maxBars'); - // Round interval by order of magnitude to provide clean intervals - // Always round interval up so there will always be less buckets than histogram:maxBars - const orderOfMaginute = Math.pow(10, Math.floor(Math.log10(minInterval))); - let roundInterval = orderOfMaginute; - while (roundInterval < minInterval) { - roundInterval += orderOfMaginute; - } - interval = roundInterval; + // ensure interval does not create too many buckets and crash browser + if (aggConfig.getAutoBounds()) { + const range = aggConfig.getAutoBounds().max - aggConfig.getAutoBounds().min; + const bars = range / interval; + if (bars > config.get('histogram:maxBars')) { + const minInterval = range / config.get('histogram:maxBars'); + // Round interval by order of magnitude to provide clean intervals + // Always round interval up so there will always be less buckets than histogram:maxBars + const orderOfMaginute = Math.pow(10, Math.floor(Math.log10(minInterval))); + let roundInterval = orderOfMaginute; + while (roundInterval < minInterval) { + roundInterval += orderOfMaginute; } + interval = roundInterval; } - - output.params.interval = interval; } - }, - { - name: 'min_doc_count', - default: null, - editor: minDocCountTemplate, - write: function (aggConfig, output) { - if (aggConfig.params.min_doc_count) { - output.params.min_doc_count = 0; - } else { - output.params.min_doc_count = 1; - } + output.params.interval = interval; + } + }, + + { + name: 'min_doc_count', + default: null, + editor: minDocCountTemplate, + write: function (aggConfig, output) { + if (aggConfig.params.min_doc_count) { + output.params.min_doc_count = 0; + } else { + output.params.min_doc_count = 1; } - }, + } + }, - { - name: 'extended_bounds', - default: {}, - editor: extendedBoundsTemplate, - write: function (aggConfig, output) { - const val = aggConfig.params.extended_bounds; + { + name: 'extended_bounds', + default: {}, + editor: extendedBoundsTemplate, + write: function (aggConfig, output) { + const val = aggConfig.params.extended_bounds; - if (aggConfig.params.min_doc_count && (val.min != null || val.max != null)) { - output.params.extended_bounds = { - min: val.min, - max: val.max - }; - } - }, + if (aggConfig.params.min_doc_count && (val.min != null || val.max != null)) { + output.params.extended_bounds = { + min: val.min, + max: val.max + }; + } + }, - // called from the editor - shouldShow: function (aggConfig) { - const field = aggConfig.params.field; - if ( - field - && (field.type === 'number' || field.type === 'date') - ) { - return aggConfig.params.min_doc_count; - } + // called from the editor + shouldShow: function (aggConfig) { + const field = aggConfig.params.field; + if ( + field + && (field.type === 'number' || field.type === 'date') + ) { + return aggConfig.params.min_doc_count; } } - ] - }); -} + } + ] +}); diff --git a/src/ui/public/agg_types/buckets/ip_range.js b/src/ui/public/agg_types/buckets/ip_range.js index 7058b8a8911f7..f962dcfd89d2c 100644 --- a/src/ui/public/agg_types/buckets/ip_range.js +++ b/src/ui/public/agg_types/buckets/ip_range.js @@ -1,61 +1,56 @@ import _ from 'lodash'; import '../../directives/validate_ip'; import '../../directives/validate_cidr_mask'; -import { AggTypesBucketsBucketAggTypeProvider } from './_bucket_agg_type'; -import { AggTypesBucketsCreateFilterIpRangeProvider } from './create_filter/ip_range'; +import { BucketAggType } from './_bucket_agg_type'; +import { createFilterIpRange } from './create_filter/ip_range'; import ipRangesTemplate from '../controls/ip_ranges.html'; -export function AggTypesBucketsIpRangeProvider(Private) { - const BucketAggType = Private(AggTypesBucketsBucketAggTypeProvider); - const createFilter = Private(AggTypesBucketsCreateFilterIpRangeProvider); +export const ipRangeBucketAgg = new BucketAggType({ + name: 'ip_range', + title: '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}`; + }, + makeLabel: function (aggConfig) { + return aggConfig.getFieldDisplayName() + ' IP ranges'; + }, + params: [ + { + name: 'field', + filterFieldTypes: 'ip' + }, { + name: 'ipRangeType', + default: 'fromTo', + write: _.noop + }, { + name: 'ranges', + default: { + fromTo: [ + { from: '0.0.0.0', to: '127.255.255.255' }, + { from: '128.0.0.0', to: '191.255.255.255' } + ], + mask: [ + { mask: '0.0.0.0/1' }, + { mask: '128.0.0.0/2' } + ] + }, + editor: ipRangesTemplate, + write: function (aggConfig, output) { + const ipRangeType = aggConfig.params.ipRangeType; + let ranges = aggConfig.params.ranges[ipRangeType]; - return new BucketAggType({ - name: 'ip_range', - title: 'IPv4 Range', - createFilter: createFilter, - getKey: function (bucket, key) { - if (key) return key; - const from = _.get(bucket, 'from', '-Infinity'); - const to = _.get(bucket, 'to', 'Infinity'); - return `${from} to ${to}`; - }, - makeLabel: function (aggConfig) { - return aggConfig.getFieldDisplayName() + ' IP ranges'; - }, - params: [ - { - name: 'field', - filterFieldTypes: 'ip' - }, { - name: 'ipRangeType', - default: 'fromTo', - write: _.noop - }, { - name: 'ranges', - default: { - fromTo: [ - { from: '0.0.0.0', to: '127.255.255.255' }, - { from: '128.0.0.0', to: '191.255.255.255' } - ], - mask: [ - { mask: '0.0.0.0/1' }, - { mask: '128.0.0.0/2' } - ] - }, - editor: ipRangesTemplate, - write: function (aggConfig, output) { - const ipRangeType = aggConfig.params.ipRangeType; - let ranges = aggConfig.params.ranges[ipRangeType]; - - if (ipRangeType === 'fromTo') { - ranges = _.map(ranges, (range) => { - return _.omit(range, _.isNull); - }); - } - - output.params.ranges = ranges; + if (ipRangeType === 'fromTo') { + ranges = _.map(ranges, (range) => { + return _.omit(range, _.isNull); + }); } + + output.params.ranges = ranges; } - ] - }); -} + } + ] +}); diff --git a/src/ui/public/agg_types/buckets/range.js b/src/ui/public/agg_types/buckets/range.js index 58591d8b00aa9..ed89b465ac0d2 100644 --- a/src/ui/public/agg_types/buckets/range.js +++ b/src/ui/public/agg_types/buckets/range.js @@ -1,73 +1,67 @@ -import { AggTypesBucketsBucketAggTypeProvider } from './_bucket_agg_type'; -import { AggTypesBucketsCreateFilterRangeProvider } from './create_filter/range'; +import { BucketAggType } from './_bucket_agg_type'; +import { createFilterRange } from './create_filter/range'; import { FieldFormat } from '../../../field_formats/field_format'; -import { RangeKeyProvider } from './range_key'; +import { RangeKey } from './range_key'; import rangesTemplate from '../controls/ranges.html'; -export function AggTypesBucketsRangeProvider(Private) { - const BucketAggType = Private(AggTypesBucketsBucketAggTypeProvider); - const createFilter = Private(AggTypesBucketsCreateFilterRangeProvider); - const RangeKey = Private(RangeKeyProvider); +const keyCaches = new WeakMap(); +const formats = new WeakMap(); - const keyCaches = new WeakMap(); - const formats = new WeakMap(); +export const rangeBucketAgg = new BucketAggType({ + name: 'range', + title: 'Range', + createFilter: createFilterRange, + makeLabel: function (aggConfig) { + return aggConfig.getFieldDisplayName() + ' ranges'; + }, + getKey: function (bucket, key, agg) { + let keys = keyCaches.get(agg); - return new BucketAggType({ - name: 'range', - title: 'Range', - createFilter: createFilter, - makeLabel: function (aggConfig) { - return aggConfig.getFieldDisplayName() + ' ranges'; - }, - getKey: function (bucket, key, agg) { - let keys = keyCaches.get(agg); + if (!keys) { + keys = new Map(); + keyCaches.set(agg, keys); + } - if (!keys) { - keys = new Map(); - keyCaches.set(agg, keys); - } + const id = RangeKey.idBucket(bucket); - const id = RangeKey.idBucket(bucket); + key = keys.get(id); + if (!key) { + key = new RangeKey(bucket); + keys.set(id, key); + } - key = keys.get(id); - if (!key) { - key = new RangeKey(bucket); - keys.set(id, key); - } - - return key; - }, - getFormat: function (agg) { - let format = formats.get(agg); - if (format) return format; + return key; + }, + getFormat: function (agg) { + let format = formats.get(agg); + if (format) return format; - const RangeFormat = FieldFormat.from(function (range) { - const format = agg.fieldOwnFormatter(); - return `${format(range.gte)} to ${format(range.lt)}`; - }); + const RangeFormat = FieldFormat.from(function (range) { + const format = agg.fieldOwnFormatter(); + return `${format(range.gte)} to ${format(range.lt)}`; + }); - format = new RangeFormat(); + format = new RangeFormat(); - formats.set(agg, format); - return format; + formats.set(agg, format); + return format; + }, + params: [ + { + name: 'field', + filterFieldTypes: ['number'] }, - params: [ - { - name: 'field', - filterFieldTypes: ['number'] - }, - { - name: 'ranges', - default: [ - { from: 0, to: 1000 }, - { from: 1000, to: 2000 } - ], - editor: rangesTemplate, - write: function (aggConfig, output) { - output.params.ranges = aggConfig.params.ranges; - output.params.keyed = true; - } + { + name: 'ranges', + default: [ + { from: 0, to: 1000 }, + { from: 1000, to: 2000 } + ], + editor: rangesTemplate, + write: function (aggConfig, output) { + output.params.ranges = aggConfig.params.ranges; + output.params.keyed = true; } - ] - }); -} + } + ] +}); diff --git a/src/ui/public/agg_types/buckets/range_key.js b/src/ui/public/agg_types/buckets/range_key.js index edd462de91ad3..a5bd6f82e6d59 100644 --- a/src/ui/public/agg_types/buckets/range_key.js +++ b/src/ui/public/agg_types/buckets/range_key.js @@ -1,25 +1,21 @@ -export function RangeKeyProvider() { +const id = Symbol('id'); - const id = Symbol('id'); - - class RangeKey { - constructor(bucket) { - this.gte = bucket.from == null ? -Infinity : bucket.from; - this.lt = bucket.to == null ? +Infinity : bucket.to; - - this[id] = RangeKey.idBucket(bucket); - } +class RangeKey { + constructor(bucket) { + this.gte = bucket.from == null ? -Infinity : bucket.from; + this.lt = bucket.to == null ? +Infinity : bucket.to; + this[id] = RangeKey.idBucket(bucket); + } - static idBucket(bucket) { - return `from:${bucket.from},to:${bucket.to}`; - } - toString() { - return this[id]; - } + static idBucket(bucket) { + return `from:${bucket.from},to:${bucket.to}`; } - - return RangeKey; + toString() { + return this[id]; + } } + +export { RangeKey }; diff --git a/src/ui/public/agg_types/buckets/significant_terms.js b/src/ui/public/agg_types/buckets/significant_terms.js index 56a171334ad16..2b4a6267e0865 100644 --- a/src/ui/public/agg_types/buckets/significant_terms.js +++ b/src/ui/public/agg_types/buckets/significant_terms.js @@ -1,38 +1,33 @@ -import { AggTypesBucketsBucketAggTypeProvider } from './_bucket_agg_type'; -import { AggTypesBucketsCreateFilterTermsProvider } from './create_filter/terms'; +import { BucketAggType } from './_bucket_agg_type'; +import { createFilterTerms } from './create_filter/terms'; import orderAndSizeTemplate from '../controls/order_and_size.html'; -export function AggTypesBucketsSignificantTermsProvider(Private) { - const BucketAggType = Private(AggTypesBucketsBucketAggTypeProvider); - const createFilter = Private(AggTypesBucketsCreateFilterTermsProvider); - - return new BucketAggType({ - name: 'significant_terms', - title: 'Significant Terms', - makeLabel: function (aggConfig) { - return 'Top ' + aggConfig.params.size + ' unusual terms in ' + aggConfig.getFieldDisplayName(); +export const significantTermsBucketAgg = new BucketAggType({ + name: 'significant_terms', + title: 'Significant Terms', + makeLabel: function (aggConfig) { + return 'Top ' + aggConfig.params.size + ' unusual terms in ' + aggConfig.getFieldDisplayName(); + }, + createFilter: createFilterTerms, + params: [ + { + name: 'field', + scriptable: false, + filterFieldTypes: 'string' + }, + { + name: 'size', + editor: orderAndSizeTemplate, + }, + { + name: 'exclude', + type: 'regex', + advanced: true }, - createFilter: createFilter, - params: [ - { - name: 'field', - scriptable: false, - filterFieldTypes: 'string' - }, - { - name: 'size', - editor: orderAndSizeTemplate, - }, - { - name: 'exclude', - type: 'regex', - advanced: true - }, - { - name: 'include', - type: 'regex', - advanced: true - } - ] - }); -} + { + name: 'include', + type: 'regex', + advanced: true + } + ] +}); diff --git a/src/ui/public/agg_types/buckets/terms.js b/src/ui/public/agg_types/buckets/terms.js index 09c4ab274c5df..90e82978edc9c 100644 --- a/src/ui/public/agg_types/buckets/terms.js +++ b/src/ui/public/agg_types/buckets/terms.js @@ -1,253 +1,245 @@ import _ from 'lodash'; -import { AggTypesBucketsBucketAggTypeProvider } from './_bucket_agg_type'; +import { BucketAggType } from './_bucket_agg_type'; import { AggConfig } from '../../vis/agg_config'; import { Schemas } from '../../vis/editors/default/schemas'; -import { AggTypesBucketsCreateFilterTermsProvider } from './create_filter/terms'; +import { createFilterTerms } from './create_filter/terms'; import orderAggTemplate from '../controls/order_agg.html'; import orderAndSizeTemplate from '../controls/order_and_size.html'; -import otherBucketTemplate from 'ui/agg_types/controls/other_bucket.html'; -import { RouteBasedNotifierProvider } from '../../route_based_notifier'; -import { OtherBucketHelperProvider } from './_terms_other_bucket_helper'; - -export function AggTypesBucketsTermsProvider(Private) { - const BucketAggType = Private(AggTypesBucketsBucketAggTypeProvider); - const createFilter = Private(AggTypesBucketsCreateFilterTermsProvider); - const routeBasedNotifier = Private(RouteBasedNotifierProvider); - const { buildOtherBucketAgg, mergeOtherBucketAggResponse, updateMissingBucket } = Private(OtherBucketHelperProvider); - - const aggFilter = [ - '!top_hits', '!percentiles', '!median', '!std_dev', - '!derivative', '!moving_avg', '!serial_diff', '!cumulative_sum', - '!avg_bucket', '!max_bucket', '!min_bucket', '!sum_bucket' - ]; - - const orderAggSchema = (new Schemas([ - { - group: 'none', - name: 'orderAgg', - title: 'Order Agg', - hideCustomLabel: true, - aggFilter: aggFilter - } - ])).all[0]; - - function isNotType(type) { - return function (agg) { - const field = agg.params.field; - return !field || field.type !== type; - }; +import { buildOtherBucketAgg, mergeOtherBucketAggResponse, updateMissingBucket } from './_terms_other_bucket_helper'; +import { toastNotifications } from '../../notify'; + +const aggFilter = [ + '!top_hits', '!percentiles', '!median', '!std_dev', + '!derivative', '!moving_avg', '!serial_diff', '!cumulative_sum', + '!avg_bucket', '!max_bucket', '!min_bucket', '!sum_bucket' +]; + +const orderAggSchema = (new Schemas([ + { + group: 'none', + name: 'orderAgg', + title: 'Order Agg', + hideCustomLabel: true, + aggFilter: aggFilter } +])).all[0]; - const migrateIncludeExcludeFormat = { - serialize: function (value) { - if (!value || _.isString(value)) return value; - else return value.pattern; - }, - write: function (aggConfig, output) { - const value = aggConfig.params[this.name]; - if (_.isObject(value)) { - output.params[this.name] = value.pattern; - } else if (value) { - output.params[this.name] = value; - } - } +function isNotType(type) { + return function (agg) { + const field = agg.params.field; + return !field || field.type !== type; }; +} - return new BucketAggType({ - name: 'terms', - title: 'Terms', - makeLabel: function (agg) { - const params = agg.params; - return agg.getFieldDisplayName() + ': ' + params.order.display; +const migrateIncludeExcludeFormat = { + serialize: function (value) { + if (!value || _.isString(value)) return value; + else return value.pattern; + }, + write: function (aggConfig, output) { + const value = aggConfig.params[this.name]; + if (_.isObject(value)) { + output.params[this.name] = value.pattern; + } else if (value) { + output.params[this.name] = value; + } + } +}; + +export const termsBucketAgg = new BucketAggType({ + name: 'terms', + title: 'Terms', + makeLabel: function (agg) { + const params = agg.params; + return agg.getFieldDisplayName() + ': ' + params.order.display; + }, + createFilter: createFilterTerms, + postFlightRequest: async (resp, aggConfigs, aggConfig, nestedSearchSource) => { + if (aggConfig.params.otherBucket) { + const filterAgg = buildOtherBucketAgg(aggConfigs, aggConfig, resp); + nestedSearchSource.set('aggs', filterAgg); + const response = await nestedSearchSource.fetchAsRejectablePromise(); + resp = mergeOtherBucketAggResponse(aggConfigs, resp, response, aggConfig, filterAgg()); + } + if (aggConfig.params.missingBucket) { + resp = updateMissingBucket(resp, aggConfigs, aggConfig); + } + return resp; + }, + params: [ + { + name: 'field', + filterFieldTypes: ['number', 'boolean', 'date', 'ip', 'string'] }, - createFilter: createFilter, - postFlightRequest: async (resp, aggConfigs, aggConfig, nestedSearchSource) => { - if (aggConfig.params.otherBucket) { - const filterAgg = buildOtherBucketAgg(aggConfigs, aggConfig, resp); - nestedSearchSource.set('aggs', filterAgg); - const response = await nestedSearchSource.fetchAsRejectablePromise(); - resp = mergeOtherBucketAggResponse(aggConfigs, resp, response, aggConfig, filterAgg()); - } - if (aggConfig.params.missingBucket) { - resp = updateMissingBucket(resp, aggConfigs, aggConfig); - } - return resp; + { + name: 'size', + default: 5 }, - params: [ - { - name: 'field', - filterFieldTypes: ['number', 'boolean', 'date', 'ip', 'string'] + { + name: 'orderAgg', + type: AggConfig, + default: null, + editor: orderAggTemplate, + serialize: function (orderAgg) { + return orderAgg.toJSON(); }, - { - name: 'size', - default: 5 + deserialize: function (state, agg) { + return this.makeOrderAgg(agg, state); }, - { - name: 'orderAgg', - type: AggConfig, - default: null, - editor: orderAggTemplate, - serialize: function (orderAgg) { - return orderAgg.toJSON(); - }, - deserialize: function (state, agg) { - return this.makeOrderAgg(agg, state); - }, - makeOrderAgg: function (termsAgg, state) { - state = state || {}; - state.schema = orderAggSchema; - const orderAgg = new AggConfig(termsAgg.vis, state); - orderAgg.id = termsAgg.id + '-orderAgg'; - return orderAgg; - }, - controller: function ($scope) { - $scope.safeMakeLabel = function (agg) { - try { - return agg.makeLabel(); - } catch (e) { - return '- agg not valid -'; - } - }; - - const INIT = {}; // flag to know when prevOrderBy has changed - let prevOrderBy = INIT; + makeOrderAgg: function (termsAgg, state) { + state = state || {}; + state.schema = orderAggSchema; + const orderAgg = new AggConfig(termsAgg.vis, state); + orderAgg.id = termsAgg.id + '-orderAgg'; + return orderAgg; + }, + controller: function ($scope) { + $scope.safeMakeLabel = function (agg) { + try { + return agg.makeLabel(); + } catch (e) { + return '- agg not valid -'; + } + }; - $scope.$watch('responseValueAggs', updateOrderAgg); - $scope.$watch('agg.params.orderBy', updateOrderAgg); + const INIT = {}; // flag to know when prevOrderBy has changed + let prevOrderBy = INIT; - // Returns true if the agg is not compatible with the terms bucket - $scope.rejectAgg = function rejectAgg(agg) { - return aggFilter.includes(`!${agg.type.name}`); - }; + $scope.$watch('responseValueAggs', updateOrderAgg); + $scope.$watch('agg.params.orderBy', updateOrderAgg); - $scope.$watch('agg.params.field.type', (type) => { - if (type !== 'string') { - $scope.agg.params.missingBucket = false; - } - }); - - function updateOrderAgg() { - // abort until we get the responseValueAggs - if (!$scope.responseValueAggs) return; - const agg = $scope.agg; - const params = agg.params; - const orderBy = params.orderBy; - const paramDef = agg.type.params.byName.orderAgg; - - // setup the initial value of orderBy - if (!orderBy && prevOrderBy === INIT) { - let respAgg = _($scope.responseValueAggs).filter((agg) => !$scope.rejectAgg(agg)).first(); - if (!respAgg) { - respAgg = { id: '_term' }; - } - params.orderBy = respAgg.id; - return; - } + // Returns true if the agg is not compatible with the terms bucket + $scope.rejectAgg = function rejectAgg(agg) { + return aggFilter.includes(`!${agg.type.name}`); + }; - // track the previous value - prevOrderBy = orderBy; - - // we aren't creating a custom aggConfig - if (!orderBy || orderBy !== 'custom') { - params.orderAgg = null; - // ensure that orderBy is set to a valid agg - const respAgg = _($scope.responseValueAggs).filter((agg) => !$scope.rejectAgg(agg)).find({ id: orderBy }); - if (!respAgg) { - params.orderBy = '_term'; - } - return; - } - - params.orderAgg = params.orderAgg || paramDef.makeOrderAgg(agg); + $scope.$watch('agg.params.field.type', (type) => { + if (type !== 'string') { + $scope.agg.params.missingBucket = false; } - }, - write: function (agg, output) { - const vis = agg.vis; - const dir = agg.params.order.val; - const order = output.params.order = {}; - - let orderAgg = agg.params.orderAgg || vis.aggs.getResponseAggById(agg.params.orderBy); - - // TODO: This works around an Elasticsearch bug the always casts terms agg scripts to strings - // thus causing issues with filtering. This probably causes other issues since float might not - // be able to contain the number on the elasticsearch side - if (output.params.script) { - output.params.valueType = agg.getField().type === 'number' ? 'float' : agg.getField().type; - } - - if (agg.params.missingBucket && agg.params.field.type === 'string') { - output.params.missing = '__missing__'; - } - - if (!orderAgg) { - order[agg.params.orderBy || '_count'] = dir; + }); + + function updateOrderAgg() { + // abort until we get the responseValueAggs + if (!$scope.responseValueAggs) return; + const agg = $scope.agg; + const params = agg.params; + const orderBy = params.orderBy; + const paramDef = agg.type.params.byName.orderAgg; + + // setup the initial value of orderBy + if (!orderBy && prevOrderBy === INIT) { + let respAgg = _($scope.responseValueAggs).filter((agg) => !$scope.rejectAgg(agg)).first(); + if (!respAgg) { + respAgg = { id: '_term' }; + } + params.orderBy = respAgg.id; return; } - if (orderAgg.type.name === 'count') { - if (dir === 'asc') { - routeBasedNotifier.warning('Sorting in Ascending order by Count in Terms aggregations is deprecated'); + // track the previous value + prevOrderBy = orderBy; + + // we aren't creating a custom aggConfig + if (!orderBy || orderBy !== 'custom') { + params.orderAgg = null; + // ensure that orderBy is set to a valid agg + const respAgg = _($scope.responseValueAggs).filter((agg) => !$scope.rejectAgg(agg)).find({ id: orderBy }); + if (!respAgg) { + params.orderBy = '_term'; } - order._count = dir; return; } - const orderAggId = orderAgg.id; - if (orderAgg.parentId) { - orderAgg = vis.aggs.byId[orderAgg.parentId]; + params.orderAgg = params.orderAgg || paramDef.makeOrderAgg(agg); + } + }, + write: function (agg, output) { + const vis = agg.vis; + const dir = agg.params.order.val; + const order = output.params.order = {}; + + let orderAgg = agg.params.orderAgg || vis.aggs.getResponseAggById(agg.params.orderBy); + + // TODO: This works around an Elasticsearch bug the always casts terms agg scripts to strings + // thus causing issues with filtering. This probably causes other issues since float might not + // be able to contain the number on the elasticsearch side + if (output.params.script) { + output.params.valueType = agg.getField().type === 'number' ? 'float' : agg.getField().type; + } + + if (agg.params.missingBucket && agg.params.field.type === 'string') { + output.params.missing = '__missing__'; + } + + if (!orderAgg) { + order[agg.params.orderBy || '_count'] = dir; + return; + } + + if (orderAgg.type.name === 'count') { + if (dir === 'asc') { + toastNotifications.addWarning('Sorting in Ascending order by Count in Terms aggregations is deprecated'); } + order._count = dir; + return; + } - output.subAggs = (output.subAggs || []).concat(orderAgg); - order[orderAggId] = dir; + const orderAggId = orderAgg.id; + if (orderAgg.parentId) { + orderAgg = vis.aggs.byId[orderAgg.parentId]; } - }, - { - name: 'order', - type: 'optioned', - default: 'desc', - editor: orderAndSizeTemplate, - options: [ - { display: 'Descending', val: 'desc' }, - { display: 'Ascending', val: 'asc' } - ], - write: _.noop // prevent default write, it's handled by orderAgg - }, - { - name: 'orderBy', - write: _.noop // prevent default write, it's handled by orderAgg - }, - { - name: 'otherBucket', - default: false, - editor: otherBucketTemplate, - write: _.noop - }, { - name: 'otherBucketLabel', - default: 'Other', - write: _.noop - }, { - name: 'missingBucket', - default: false, - write: _.noop - }, { - name: 'missingBucketLabel', - default: 'Missing', - write: _.noop - }, - { - name: 'exclude', - type: 'string', - advanced: true, - disabled: isNotType('string'), - ...migrateIncludeExcludeFormat - }, - { - name: 'include', - type: 'string', - advanced: true, - disabled: isNotType('string'), - ...migrateIncludeExcludeFormat - }, - ] - }); -} + + output.subAggs = (output.subAggs || []).concat(orderAgg); + order[orderAggId] = dir; + } + }, + { + name: 'order', + type: 'optioned', + default: 'desc', + editor: orderAndSizeTemplate, + options: [ + { display: 'Descending', val: 'desc' }, + { display: 'Ascending', val: 'asc' } + ], + write: _.noop // prevent default write, it's handled by orderAgg + }, + { + name: 'orderBy', + write: _.noop // prevent default write, it's handled by orderAgg + }, + { + name: 'otherBucket', + default: false, + editor: otherBucketTemplate, + write: _.noop + }, { + name: 'otherBucketLabel', + default: 'Other', + write: _.noop + }, { + name: 'missingBucket', + default: false, + write: _.noop + }, { + name: 'missingBucketLabel', + default: 'Missing', + write: _.noop + }, + { + name: 'exclude', + type: 'string', + advanced: true, + disabled: isNotType('string'), + ...migrateIncludeExcludeFormat + }, + { + name: 'include', + type: 'string', + advanced: true, + disabled: isNotType('string'), + ...migrateIncludeExcludeFormat + } + ] +}); diff --git a/src/ui/public/agg_types/index.js b/src/ui/public/agg_types/index.js index 60bad1a6a9a60..818754b15d6fb 100644 --- a/src/ui/public/agg_types/index.js +++ b/src/ui/public/agg_types/index.js @@ -1,105 +1,102 @@ -import { IndexedArray } from '../indexed_array'; -import './agg_params'; -import { AggTypesMetricsCountProvider } from './metrics/count'; -import { AggTypesMetricsAvgProvider } from './metrics/avg'; -import { AggTypesMetricsSumProvider } from './metrics/sum'; -import { AggTypesMetricsMedianProvider } from './metrics/median'; -import { AggTypesMetricsMinProvider } from './metrics/min'; -import { AggTypesMetricsMaxProvider } from './metrics/max'; -import { AggTypesMetricsTopHitProvider } from './metrics/top_hit'; -import { AggTypesMetricsStdDeviationProvider } from './metrics/std_deviation'; -import { AggTypesMetricsCardinalityProvider } from './metrics/cardinality'; -import { AggTypesMetricsPercentilesProvider } from './metrics/percentiles'; -import { AggTypesMetricsGeoBoundsProvider } from './metrics/geo_bounds'; -import { AggTypesMetricsGeoCentroidProvider } from './metrics/geo_centroid'; -import { AggTypesMetricsPercentileRanksProvider } from './metrics/percentile_ranks'; -import { AggTypesMetricsDerivativeProvider } from './metrics/derivative'; -import { AggTypesMetricsCumulativeSumProvider } from './metrics/cumulative_sum'; -import { AggTypesMetricsMovingAvgProvider } from './metrics/moving_avg'; -import { AggTypesMetricsSerialDiffProvider } from './metrics/serial_diff'; -import { AggTypesBucketsDateHistogramProvider } from './buckets/date_histogram'; -import { AggTypesBucketsHistogramProvider } from './buckets/histogram'; -import { AggTypesBucketsRangeProvider } from './buckets/range'; -import { AggTypesBucketsDateRangeProvider } from './buckets/date_range'; -import { AggTypesBucketsIpRangeProvider } from './buckets/ip_range'; -import { AggTypesBucketsTermsProvider } from './buckets/terms'; -import { AggTypesBucketsFilterProvider } from './buckets/filter'; -import { AggTypesBucketsFiltersProvider } from './buckets/filters'; -import { AggTypesBucketsSignificantTermsProvider } from './buckets/significant_terms'; -import { AggTypesBucketsGeoHashProvider } from './buckets/geo_hash'; -import { AggTypesMetricsBucketSumProvider } from './metrics/bucket_sum'; -import { AggTypesMetricsBucketAvgProvider } from './metrics/bucket_avg'; -import { AggTypesMetricsBucketMinProvider } from './metrics/bucket_min'; -import { AggTypesMetricsBucketMaxProvider } from './metrics/bucket_max'; import '../directives/validate_agg'; +import './agg_params'; +import { IndexedArray } from '../indexed_array'; +import { countMetricAgg } from './metrics/count'; +import { avgMetricAgg } from './metrics/avg'; +import { sumMetricAgg } from './metrics/sum'; +import { medianMetricAgg } from './metrics/median'; +import { minMetricAgg } from './metrics/min'; +import { maxMetricAgg } from './metrics/max'; +import { topHitMetricAgg } from './metrics/top_hit'; +import { stdDeviationMetricAgg } from './metrics/std_deviation'; +import { cardinalityMetricAgg } from './metrics/cardinality'; +import { percentilesMetricAgg } from './metrics/percentiles'; +import { geoBoundsMetricAgg } from './metrics/geo_bounds'; +import { geoCentroidMetricAgg } from './metrics/geo_centroid'; +import { percentileRanksMetricAgg } from './metrics/percentile_ranks'; +import { derivativeMetricAgg } from './metrics/derivative'; +import { cumulativeSumMetricAgg } from './metrics/cumulative_sum'; +import { movingAvgMetricAgg } from './metrics/moving_avg'; +import { serialDiffMetricAgg } from './metrics/serial_diff'; +import { dateHistogramBucketAgg } from './buckets/date_histogram'; +import { histogramBucketAgg } from './buckets/histogram'; +import { rangeBucketAgg } from './buckets/range'; +import { dateRangeBucketAgg } from './buckets/date_range'; +import { ipRangeBucketAgg } from './buckets/ip_range'; +import { termsBucketAgg } from './buckets/terms'; +import { filterBucketAgg } from './buckets/filter'; +import { filtersBucketAgg } from './buckets/filters'; +import { significantTermsBucketAgg } from './buckets/significant_terms'; +import { geoHashBucketAgg } from './buckets/geo_hash'; +import { bucketSumMetricAgg } from './metrics/bucket_sum'; +import { bucketAvgMetricAgg } from './metrics/bucket_avg'; +import { bucketMinMetricAgg } from './metrics/bucket_min'; +import { bucketMaxMetricAgg } from './metrics/bucket_max'; -export function AggTypesIndexProvider(Private) { - - const aggs = { - metrics: [ - Private(AggTypesMetricsCountProvider), - Private(AggTypesMetricsAvgProvider), - Private(AggTypesMetricsSumProvider), - Private(AggTypesMetricsMedianProvider), - Private(AggTypesMetricsMinProvider), - Private(AggTypesMetricsMaxProvider), - Private(AggTypesMetricsStdDeviationProvider), - Private(AggTypesMetricsCardinalityProvider), - Private(AggTypesMetricsPercentilesProvider), - Private(AggTypesMetricsPercentileRanksProvider), - Private(AggTypesMetricsTopHitProvider), - Private(AggTypesMetricsDerivativeProvider), - Private(AggTypesMetricsCumulativeSumProvider), - Private(AggTypesMetricsMovingAvgProvider), - Private(AggTypesMetricsSerialDiffProvider), - Private(AggTypesMetricsBucketAvgProvider), - Private(AggTypesMetricsBucketSumProvider), - Private(AggTypesMetricsBucketMinProvider), - Private(AggTypesMetricsBucketMaxProvider), - Private(AggTypesMetricsGeoBoundsProvider), - Private(AggTypesMetricsGeoCentroidProvider) - ], - buckets: [ - Private(AggTypesBucketsDateHistogramProvider), - Private(AggTypesBucketsHistogramProvider), - Private(AggTypesBucketsRangeProvider), - Private(AggTypesBucketsDateRangeProvider), - Private(AggTypesBucketsIpRangeProvider), - Private(AggTypesBucketsTermsProvider), - Private(AggTypesBucketsFilterProvider), - Private(AggTypesBucketsFiltersProvider), - Private(AggTypesBucketsSignificantTermsProvider), - Private(AggTypesBucketsGeoHashProvider), - ] - }; +const aggs = { + metrics: [ + countMetricAgg, + avgMetricAgg, + sumMetricAgg, + medianMetricAgg, + minMetricAgg, + maxMetricAgg, + stdDeviationMetricAgg, + cardinalityMetricAgg, + percentilesMetricAgg, + percentileRanksMetricAgg, + topHitMetricAgg, + derivativeMetricAgg, + cumulativeSumMetricAgg, + movingAvgMetricAgg, + serialDiffMetricAgg, + bucketAvgMetricAgg, + bucketSumMetricAgg, + bucketMinMetricAgg, + bucketMaxMetricAgg, + geoBoundsMetricAgg, + geoCentroidMetricAgg + ], + buckets: [ + dateHistogramBucketAgg, + histogramBucketAgg, + rangeBucketAgg, + dateRangeBucketAgg, + ipRangeBucketAgg, + termsBucketAgg, + filterBucketAgg, + filtersBucketAgg, + significantTermsBucketAgg, + geoHashBucketAgg + ] +}; - Object.keys(aggs).forEach(function (type) { - aggs[type].forEach(function (agg) { - agg.type = type; - }); +Object.keys(aggs).forEach(function (type) { + aggs[type].forEach(function (agg) { + agg.type = type; }); +}); +/** + * IndexedArray of Aggregation Types. + * + * These types form two groups, metric and buckets. + * + * @module agg_types + * @type {IndexedArray} + */ +export const aggTypes = new IndexedArray({ + /** - * IndexedArray of Aggregation Types. - * - * These types form two groups, metric and buckets. - * - * @module agg_types - * @type {IndexedArray} + * @type {Array} */ - return new IndexedArray({ - - /** - * @type {Array} - */ - index: ['name'], + index: ['name'], - /** - * [group description] - * @type {Array} - */ - group: ['type'], - initialSet: aggs.metrics.concat(aggs.buckets) - }); -} + /** + * [group description] + * @type {Array} + */ + group: ['type'], + initialSet: aggs.metrics.concat(aggs.buckets) +}); diff --git a/src/ui/public/agg_types/metrics/avg.js b/src/ui/public/agg_types/metrics/avg.js index 71eb415ed0769..8b29aaead0e15 100644 --- a/src/ui/public/agg_types/metrics/avg.js +++ b/src/ui/public/agg_types/metrics/avg.js @@ -1,19 +1,15 @@ -import { AggTypesMetricsMetricAggTypeProvider } from './metric_agg_type'; +import { MetricAggType } from './metric_agg_type'; -export function AggTypesMetricsAvgProvider(Private) { - const MetricAggType = Private(AggTypesMetricsMetricAggTypeProvider); - - return new MetricAggType({ - name: 'avg', - title: 'Average', - makeLabel: function (aggConfig) { - return 'Average ' + aggConfig.getFieldDisplayName(); - }, - params: [ - { - name: 'field', - filterFieldTypes: 'number' - } - ] - }); -} +export const avgMetricAgg = new MetricAggType({ + name: 'avg', + title: 'Average', + makeLabel: function (aggConfig) { + return 'Average ' + aggConfig.getFieldDisplayName(); + }, + params: [ + { + name: 'field', + filterFieldTypes: 'number' + } + ] +}); diff --git a/src/ui/public/agg_types/metrics/bucket_avg.js b/src/ui/public/agg_types/metrics/bucket_avg.js index c88540fb22f44..5e0899932faf1 100644 --- a/src/ui/public/agg_types/metrics/bucket_avg.js +++ b/src/ui/public/agg_types/metrics/bucket_avg.js @@ -1,30 +1,26 @@ import { get } from 'lodash'; -import { AggTypesMetricsMetricAggTypeProvider } from './metric_agg_type'; +import { MetricAggType } from './metric_agg_type'; import { makeNestedLabel } from './lib/make_nested_label'; import { siblingPipelineAggHelper } from './lib/sibling_pipeline_agg_helper'; -export function AggTypesMetricsBucketAvgProvider(Private) { - const MetricAggType = Private(AggTypesMetricsMetricAggTypeProvider); +export const bucketAvgMetricAgg = new MetricAggType({ + name: 'avg_bucket', + title: 'Average Bucket', + makeLabel: agg => makeNestedLabel(agg, 'overall average'), + subtype: siblingPipelineAggHelper.subtype, + params: [ + ...siblingPipelineAggHelper.params() + ], + getFormat: siblingPipelineAggHelper.getFormat, + getValue: function (agg, bucket) { + const customMetric = agg.params.customMetric; + const scaleMetrics = customMetric.type && customMetric.type.isScalable(); - return new MetricAggType({ - name: 'avg_bucket', - title: 'Average Bucket', - makeLabel: agg => makeNestedLabel(agg, 'overall average'), - subtype: siblingPipelineAggHelper.subtype, - params: [ - ...siblingPipelineAggHelper.params() - ], - getFormat: siblingPipelineAggHelper.getFormat, - getValue: function (agg, bucket) { - const customMetric = agg.params.customMetric; - const scaleMetrics = customMetric.type && customMetric.type.isScalable(); - - let value = bucket[agg.id] && bucket[agg.id].value; - if (scaleMetrics) { - const aggInfo = agg.params.customBucket.write(); - value *= get(aggInfo, 'bucketInterval.scale', 1); - } - return value; + let value = bucket[agg.id] && bucket[agg.id].value; + if (scaleMetrics) { + const aggInfo = agg.params.customBucket.write(); + value *= get(aggInfo, 'bucketInterval.scale', 1); } - }); -} + return value; + } +}); diff --git a/src/ui/public/agg_types/metrics/bucket_max.js b/src/ui/public/agg_types/metrics/bucket_max.js index be31485e4f7b2..2959c449e1345 100644 --- a/src/ui/public/agg_types/metrics/bucket_max.js +++ b/src/ui/public/agg_types/metrics/bucket_max.js @@ -1,18 +1,14 @@ -import { AggTypesMetricsMetricAggTypeProvider } from './metric_agg_type'; +import { MetricAggType } from './metric_agg_type'; import { makeNestedLabel } from './lib/make_nested_label'; import { siblingPipelineAggHelper } from './lib/sibling_pipeline_agg_helper'; -export function AggTypesMetricsBucketMaxProvider(Private) { - const MetricAggType = Private(AggTypesMetricsMetricAggTypeProvider); - - return new MetricAggType({ - name: 'max_bucket', - title: 'Max Bucket', - makeLabel: agg => makeNestedLabel(agg, 'overall max'), - subtype: siblingPipelineAggHelper.subtype, - params: [ - ...siblingPipelineAggHelper.params() - ], - getFormat: siblingPipelineAggHelper.getFormat - }); -} +export const bucketMaxMetricAgg = new MetricAggType({ + name: 'max_bucket', + title: 'Max Bucket', + makeLabel: agg => makeNestedLabel(agg, 'overall max'), + subtype: siblingPipelineAggHelper.subtype, + params: [ + ...siblingPipelineAggHelper.params() + ], + getFormat: siblingPipelineAggHelper.getFormat +}); diff --git a/src/ui/public/agg_types/metrics/bucket_min.js b/src/ui/public/agg_types/metrics/bucket_min.js index fc7873f6851d0..1edae1f4e2c73 100644 --- a/src/ui/public/agg_types/metrics/bucket_min.js +++ b/src/ui/public/agg_types/metrics/bucket_min.js @@ -1,18 +1,14 @@ -import { AggTypesMetricsMetricAggTypeProvider } from './metric_agg_type'; +import { MetricAggType } from './metric_agg_type'; import { makeNestedLabel } from './lib/make_nested_label'; import { siblingPipelineAggHelper } from './lib/sibling_pipeline_agg_helper'; -export function AggTypesMetricsBucketMinProvider(Private) { - const MetricAggType = Private(AggTypesMetricsMetricAggTypeProvider); - - return new MetricAggType({ - name: 'min_bucket', - title: 'Min Bucket', - makeLabel: agg => makeNestedLabel(agg, 'overall min'), - subtype: siblingPipelineAggHelper.subtype, - params: [ - ...siblingPipelineAggHelper.params() - ], - getFormat: siblingPipelineAggHelper.getFormat - }); -} +export const bucketMinMetricAgg = new MetricAggType({ + name: 'min_bucket', + title: 'Min Bucket', + makeLabel: agg => makeNestedLabel(agg, 'overall min'), + subtype: siblingPipelineAggHelper.subtype, + params: [ + ...siblingPipelineAggHelper.params() + ], + getFormat: siblingPipelineAggHelper.getFormat +}); diff --git a/src/ui/public/agg_types/metrics/bucket_sum.js b/src/ui/public/agg_types/metrics/bucket_sum.js index f79a0d5e9e645..cd5e36af2094c 100644 --- a/src/ui/public/agg_types/metrics/bucket_sum.js +++ b/src/ui/public/agg_types/metrics/bucket_sum.js @@ -1,18 +1,14 @@ -import { AggTypesMetricsMetricAggTypeProvider } from './metric_agg_type'; +import { MetricAggType } from './metric_agg_type'; import { makeNestedLabel } from './lib/make_nested_label'; import { siblingPipelineAggHelper } from './lib/sibling_pipeline_agg_helper'; -export function AggTypesMetricsBucketSumProvider(Private) { - const MetricAggType = Private(AggTypesMetricsMetricAggTypeProvider); - - return new MetricAggType({ - name: 'sum_bucket', - title: 'Sum Bucket', - makeLabel: agg => makeNestedLabel(agg, 'overall sum'), - subtype: siblingPipelineAggHelper.subtype, - params: [ - ...siblingPipelineAggHelper.params() - ], - getFormat: siblingPipelineAggHelper.getFormat - }); -} +export const bucketSumMetricAgg = new MetricAggType({ + name: 'sum_bucket', + title: 'Sum Bucket', + makeLabel: agg => makeNestedLabel(agg, 'overall sum'), + subtype: siblingPipelineAggHelper.subtype, + params: [ + ...siblingPipelineAggHelper.params() + ], + getFormat: siblingPipelineAggHelper.getFormat +}); diff --git a/src/ui/public/agg_types/metrics/cardinality.js b/src/ui/public/agg_types/metrics/cardinality.js index bf2930bf98dd1..62523ebd5691c 100644 --- a/src/ui/public/agg_types/metrics/cardinality.js +++ b/src/ui/public/agg_types/metrics/cardinality.js @@ -1,23 +1,18 @@ -import { AggTypesMetricsMetricAggTypeProvider } from './metric_agg_type'; +import { MetricAggType } from './metric_agg_type'; import { fieldFormats } from '../../registry/field_formats'; -export function AggTypesMetricsCardinalityProvider(Private) { - const MetricAggType = Private(AggTypesMetricsMetricAggTypeProvider); - - - return new MetricAggType({ - name: 'cardinality', - title: 'Unique Count', - makeLabel: function (aggConfig) { - return 'Unique count of ' + aggConfig.getFieldDisplayName(); - }, - getFormat: function () { - return fieldFormats.getDefaultInstance('number'); - }, - params: [ - { - name: 'field' - } - ] - }); -} +export const cardinalityMetricAgg = new MetricAggType({ + name: 'cardinality', + title: 'Unique Count', + makeLabel: function (aggConfig) { + return 'Unique count of ' + aggConfig.getFieldDisplayName(); + }, + getFormat: function () { + return fieldFormats.getDefaultInstance('number'); + }, + params: [ + { + name: 'field' + } + ] +}); diff --git a/src/ui/public/agg_types/metrics/count.js b/src/ui/public/agg_types/metrics/count.js index 7f2890ec877a9..5aea5547cd016 100644 --- a/src/ui/public/agg_types/metrics/count.js +++ b/src/ui/public/agg_types/metrics/count.js @@ -1,25 +1,20 @@ -import { AggTypesMetricsMetricAggTypeProvider } from './metric_agg_type'; +import { MetricAggType } from './metric_agg_type'; import { fieldFormats } from '../../registry/field_formats'; -export function AggTypesMetricsCountProvider(Private) { - const MetricAggType = Private(AggTypesMetricsMetricAggTypeProvider); - - - return new MetricAggType({ - name: 'count', - title: 'Count', - hasNoDsl: true, - makeLabel: function () { - return 'Count'; - }, - getFormat: function () { - return fieldFormats.getDefaultInstance('number'); - }, - getValue: function (agg, bucket) { - return bucket.doc_count; - }, - isScalable: function () { - return true; - } - }); -} +export const countMetricAgg = new MetricAggType({ + name: 'count', + title: 'Count', + hasNoDsl: true, + makeLabel: function () { + return 'Count'; + }, + getFormat: function () { + return fieldFormats.getDefaultInstance('number'); + }, + getValue: function (agg, bucket) { + return bucket.doc_count; + }, + isScalable: function () { + return true; + } +}); diff --git a/src/ui/public/agg_types/metrics/cumulative_sum.js b/src/ui/public/agg_types/metrics/cumulative_sum.js index f60eccc31d710..f76b97b1a1e27 100644 --- a/src/ui/public/agg_types/metrics/cumulative_sum.js +++ b/src/ui/public/agg_types/metrics/cumulative_sum.js @@ -1,18 +1,14 @@ -import { AggTypesMetricsMetricAggTypeProvider } from './metric_agg_type'; +import { MetricAggType } from './metric_agg_type'; import { parentPipelineAggHelper } from './lib/parent_pipeline_agg_helper'; import { makeNestedLabel } from './lib/make_nested_label'; -export function AggTypesMetricsCumulativeSumProvider(Private) { - const MetricAggType = Private(AggTypesMetricsMetricAggTypeProvider); - - return new MetricAggType({ - name: 'cumulative_sum', - title: 'Cumulative Sum', - subtype: parentPipelineAggHelper.subtype, - makeLabel: agg => makeNestedLabel(agg, 'cumulative sum'), - params: [ - ...parentPipelineAggHelper.params() - ], - getFormat: parentPipelineAggHelper.getFormat - }); -} +export const cumulativeSumMetricAgg = new MetricAggType({ + name: 'cumulative_sum', + title: 'Cumulative Sum', + subtype: parentPipelineAggHelper.subtype, + makeLabel: agg => makeNestedLabel(agg, 'cumulative sum'), + params: [ + ...parentPipelineAggHelper.params() + ], + getFormat: parentPipelineAggHelper.getFormat +}); diff --git a/src/ui/public/agg_types/metrics/derivative.js b/src/ui/public/agg_types/metrics/derivative.js index 41181c1af2317..0bff9d1f49f54 100644 --- a/src/ui/public/agg_types/metrics/derivative.js +++ b/src/ui/public/agg_types/metrics/derivative.js @@ -1,18 +1,14 @@ -import { AggTypesMetricsMetricAggTypeProvider } from './metric_agg_type'; +import { MetricAggType } from './metric_agg_type'; import { parentPipelineAggHelper } from './lib/parent_pipeline_agg_helper'; import { makeNestedLabel } from './lib/make_nested_label'; -export function AggTypesMetricsDerivativeProvider(Private) { - const MetricAggType = Private(AggTypesMetricsMetricAggTypeProvider); - - return new MetricAggType({ - name: 'derivative', - title: 'Derivative', - subtype: parentPipelineAggHelper.subtype, - makeLabel: agg => makeNestedLabel(agg, 'derivative'), - params: [ - ...parentPipelineAggHelper.params() - ], - getFormat: parentPipelineAggHelper.getFormat - }); -} +export const derivativeMetricAgg = new MetricAggType({ + name: 'derivative', + title: 'Derivative', + subtype: parentPipelineAggHelper.subtype, + makeLabel: agg => makeNestedLabel(agg, 'derivative'), + params: [ + ...parentPipelineAggHelper.params() + ], + getFormat: parentPipelineAggHelper.getFormat +}); diff --git a/src/ui/public/agg_types/metrics/geo_bounds.js b/src/ui/public/agg_types/metrics/geo_bounds.js index 1130b29f067bd..91c4fb80f0250 100644 --- a/src/ui/public/agg_types/metrics/geo_bounds.js +++ b/src/ui/public/agg_types/metrics/geo_bounds.js @@ -1,19 +1,15 @@ -import { AggTypesMetricsMetricAggTypeProvider } from './metric_agg_type'; +import { MetricAggType } from './metric_agg_type'; -export function AggTypesMetricsGeoBoundsProvider(Private) { - const MetricAggType = Private(AggTypesMetricsMetricAggTypeProvider); - - return new MetricAggType({ - name: 'geo_bounds', - title: 'Geo Bounds', - makeLabel: function () { - return 'Geo Bounds'; - }, - params: [ - { - name: 'field', - filterFieldTypes: 'geo_point' - } - ] - }); -} +export const geoBoundsMetricAgg = new MetricAggType({ + name: 'geo_bounds', + title: 'Geo Bounds', + makeLabel: function () { + return 'Geo Bounds'; + }, + params: [ + { + name: 'field', + filterFieldTypes: 'geo_point' + } + ] +}); diff --git a/src/ui/public/agg_types/metrics/geo_centroid.js b/src/ui/public/agg_types/metrics/geo_centroid.js index 3306f12782d87..6f0de616c855b 100644 --- a/src/ui/public/agg_types/metrics/geo_centroid.js +++ b/src/ui/public/agg_types/metrics/geo_centroid.js @@ -1,22 +1,18 @@ -import { AggTypesMetricsMetricAggTypeProvider } from './metric_agg_type'; +import { MetricAggType } from './metric_agg_type'; -export function AggTypesMetricsGeoCentroidProvider(Private) { - const MetricAggType = Private(AggTypesMetricsMetricAggTypeProvider); - - return new MetricAggType({ - name: 'geo_centroid', - title: 'Geo Centroid', - makeLabel: function () { - return 'Geo Centroid'; - }, - params: [ - { - name: 'field', - filterFieldTypes: 'geo_point' - } - ], - getValue: function (agg, bucket) { - return bucket[agg.id] && bucket[agg.id].location; +export const geoCentroidMetricAgg = new MetricAggType({ + name: 'geo_centroid', + title: 'Geo Centroid', + makeLabel: function () { + return 'Geo Centroid'; + }, + params: [ + { + name: 'field', + filterFieldTypes: 'geo_point' } - }); -} + ], + getValue: function (agg, bucket) { + return bucket[agg.id] && bucket[agg.id].location; + } +}); diff --git a/src/ui/public/agg_types/metrics/get_response_agg_config_class.js b/src/ui/public/agg_types/metrics/get_response_agg_config_class.js index ff1b98475d38c..67fbe1e987c4e 100644 --- a/src/ui/public/agg_types/metrics/get_response_agg_config_class.js +++ b/src/ui/public/agg_types/metrics/get_response_agg_config_class.js @@ -1,50 +1,47 @@ import _ from 'lodash'; -export function AggTypesMetricsGetResponseAggConfigClassProvider() { +/** + * Get the ResponseAggConfig class for an aggConfig, + * which might be cached on the aggConfig or created. + * + * @param {AggConfig} agg - the AggConfig the VAC should inherit from + * @param {object} props - properties that the VAC should have + * @return {Constructor} - a constructor for VAC objects that will inherit the aggConfig + */ +export function getResponseAggConfigClass(agg, props) { + if (agg.$$_ResponseAggConfigClass) { + return agg.$$_ResponseAggConfigClass; + } else { + return (agg.$$_ResponseAggConfigClass = create(agg, props)); + } +} + +function create(parentAgg, props) { /** - * Get the ResponseAggConfig class for an aggConfig, - * which might be cached on the aggConfig or created. + * AggConfig "wrapper" for multi-value metric aggs which + * need to modify AggConfig behavior for each value produced. * - * @param {AggConfig} agg - the AggConfig the VAC should inherit from - * @param {object} props - properties that the VAC should have - * @return {Constructor} - a constructor for VAC objects that will inherit the aggConfig + * @param {string|number} key - the key or index that identifies + * this part of the multi-value */ - return function getResponseConfigClass(agg, props) { - if (agg.$$_ResponseAggConfigClass) { - return agg.$$_ResponseAggConfigClass; - } else { - return (agg.$$_ResponseAggConfigClass = create(agg, props)); - } - }; + function ResponseAggConfig(key) { + this.key = key; + this.parentId = this.id; - function create(parentAgg, props) { - - /** - * AggConfig "wrapper" for multi-value metric aggs which - * need to modify AggConfig behavior for each value produced. - * - * @param {string|number} key - the key or index that identifies - * this part of the multi-value - */ - function ResponseAggConfig(key) { - this.key = key; - this.parentId = this.id; - - const subId = String(key); - if (subId.indexOf('.') > -1) { - this.id = this.parentId + '[\'' + subId.replace(/'/g, '\\\'') + '\']'; - } else { - this.id = this.parentId + '.' + subId; - } + const subId = String(key); + if (subId.indexOf('.') > -1) { + this.id = this.parentId + '[\'' + subId.replace(/'/g, '\\\'') + '\']'; + } else { + this.id = this.parentId + '.' + subId; } + } - ResponseAggConfig.prototype = Object.create(parentAgg, { - constructor: ResponseAggConfig - }); + ResponseAggConfig.prototype = Object.create(parentAgg, { + constructor: ResponseAggConfig + }); - _.assign(ResponseAggConfig.prototype, props); + _.assign(ResponseAggConfig.prototype, props); - return ResponseAggConfig; - } + return ResponseAggConfig; } diff --git a/src/ui/public/agg_types/metrics/max.js b/src/ui/public/agg_types/metrics/max.js index 81ce7ea2eb9d1..7d1a712a3e250 100644 --- a/src/ui/public/agg_types/metrics/max.js +++ b/src/ui/public/agg_types/metrics/max.js @@ -1,19 +1,15 @@ -import { AggTypesMetricsMetricAggTypeProvider } from './metric_agg_type'; +import { MetricAggType } from './metric_agg_type'; -export function AggTypesMetricsMaxProvider(Private) { - const MetricAggType = Private(AggTypesMetricsMetricAggTypeProvider); - - return new MetricAggType({ - name: 'max', - title: 'Max', - makeLabel: function (aggConfig) { - return 'Max ' + aggConfig.getFieldDisplayName(); - }, - params: [ - { - name: 'field', - filterFieldTypes: 'number,date' - } - ] - }); -} +export const maxMetricAgg = new MetricAggType({ + name: 'max', + title: 'Max', + makeLabel: function (aggConfig) { + return 'Max ' + aggConfig.getFieldDisplayName(); + }, + params: [ + { + name: 'field', + filterFieldTypes: 'number,date' + } + ] +}); diff --git a/src/ui/public/agg_types/metrics/median.js b/src/ui/public/agg_types/metrics/median.js index 5298deb8ce3ec..aa82fc13f78e6 100644 --- a/src/ui/public/agg_types/metrics/median.js +++ b/src/ui/public/agg_types/metrics/median.js @@ -1,34 +1,28 @@ -import { AggTypesMetricsMetricAggTypeProvider } from './metric_agg_type'; -import { AggTypesMetricsPercentilesProvider } from './percentiles'; +import { MetricAggType } from './metric_agg_type'; +import { percentilesMetricAgg } from './percentiles'; -export function AggTypesMetricsMedianProvider(Private) { - - const MetricAggType = Private(AggTypesMetricsMetricAggTypeProvider); - const percentiles = Private(AggTypesMetricsPercentilesProvider); - - return new MetricAggType({ - name: 'median', - dslName: 'percentiles', - title: 'Median', - makeLabel: function (aggConfig) { - return 'Median ' + aggConfig.getFieldDisplayName(); +export const medianMetricAgg = new MetricAggType({ + name: 'median', + dslName: 'percentiles', + title: 'Median', + makeLabel: function (aggConfig) { + return 'Median ' + aggConfig.getFieldDisplayName(); + }, + params: [ + { + name: 'field', + filterFieldTypes: 'number' + }, + { + name: 'percents', + default: [50] }, - params: [ - { - name: 'field', - filterFieldTypes: 'number' - }, - { - name: 'percents', - default: [50] - }, - { - write(agg, output) { - output.params.keyed = false; - } + { + write(agg, output) { + output.params.keyed = false; } - ], - getResponseAggs: percentiles.getResponseAggs, - getValue: percentiles.getValue - }); -} + } + ], + getResponseAggs: percentilesMetricAgg.getResponseAggs, + getValue: percentilesMetricAgg.getValue +}); diff --git a/src/ui/public/agg_types/metrics/metric_agg_type.js b/src/ui/public/agg_types/metrics/metric_agg_type.js index 8199520513990..2db682458cfb5 100644 --- a/src/ui/public/agg_types/metrics/metric_agg_type.js +++ b/src/ui/public/agg_types/metrics/metric_agg_type.js @@ -1,60 +1,55 @@ import _ from 'lodash'; -import { AggTypesAggTypeProvider } from '../agg_type'; +import { AggType } from '../agg_type'; import { fieldFormats } from '../../registry/field_formats'; import { createLegacyClass } from '../../utils/legacy_class'; -export function AggTypesMetricsMetricAggTypeProvider(Private) { - const AggType = Private(AggTypesAggTypeProvider); - - - createLegacyClass(MetricAggType).inherits(AggType); - function MetricAggType(config) { - MetricAggType.Super.call(this, config); - - // allow overriding any value on the prototype - _.forOwn(config, function (val, key) { - if (_.has(MetricAggType.prototype, key)) { - this[key] = val; - } - }, this); - } - - MetricAggType.prototype.subtype = 'Metric Aggregations'; - /** - * Read the values for this metric from the - * @param {[type]} bucket [description] - * @return {*} [description] - */ - MetricAggType.prototype.getValue = function (agg, bucket) { - // Metric types where an empty set equals `zero` - const isSettableToZero = ['cardinality', 'sum'].indexOf(agg.__type.name) !== -1; - - // Return proper values when no buckets are present - // `Count` handles empty sets properly - if (!bucket[agg.id] && isSettableToZero) return 0; - - return bucket[agg.id] && bucket[agg.id].value; - }; - - /** - * Pick a format for the values produced by this agg type, - * overriden by several metrics that always output a simple - * number - * - * @param {agg} agg - the agg to pick a format for - * @return {FieldFromat} - */ - MetricAggType.prototype.getFormat = function (agg) { - const field = agg.getField(); - return field ? field.format : fieldFormats.getDefaultInstance('number'); - }; - - /** - * Determines if this metric can be scaled - */ - MetricAggType.prototype.isScalable = function () { - return false; - }; - - return MetricAggType; +createLegacyClass(MetricAggType).inherits(AggType); +function MetricAggType(config) { + MetricAggType.Super.call(this, config); + + // allow overriding any value on the prototype + _.forOwn(config, function (val, key) { + if (_.has(MetricAggType.prototype, key)) { + this[key] = val; + } + }, this); } + +MetricAggType.prototype.subtype = 'Metric Aggregations'; +/** + * Read the values for this metric from the + * @param {[type]} bucket [description] + * @return {*} [description] + */ +MetricAggType.prototype.getValue = function (agg, bucket) { + // Metric types where an empty set equals `zero` + const isSettableToZero = ['cardinality', 'sum'].indexOf(agg.__type.name) !== -1; + + // Return proper values when no buckets are present + // `Count` handles empty sets properly + if (!bucket[agg.id] && isSettableToZero) return 0; + + return bucket[agg.id] && bucket[agg.id].value; +}; + +/** + * Pick a format for the values produced by this agg type, + * overriden by several metrics that always output a simple + * number + * + * @param {agg} agg - the agg to pick a format for + * @return {FieldFromat} + */ +MetricAggType.prototype.getFormat = function (agg) { + const field = agg.getField(); + return field ? field.format : fieldFormats.getDefaultInstance('number'); +}; + +/** + * Determines if this metric can be scaled + */ +MetricAggType.prototype.isScalable = function () { + return false; +}; + +export { MetricAggType }; diff --git a/src/ui/public/agg_types/metrics/min.js b/src/ui/public/agg_types/metrics/min.js index 28fa47252363d..e415e0223d82f 100644 --- a/src/ui/public/agg_types/metrics/min.js +++ b/src/ui/public/agg_types/metrics/min.js @@ -1,19 +1,15 @@ -import { AggTypesMetricsMetricAggTypeProvider } from './metric_agg_type'; +import { MetricAggType } from './metric_agg_type'; -export function AggTypesMetricsMinProvider(Private) { - const MetricAggType = Private(AggTypesMetricsMetricAggTypeProvider); - - return new MetricAggType({ - name: 'min', - title: 'Min', - makeLabel: function (aggConfig) { - return 'Min ' + aggConfig.getFieldDisplayName(); - }, - params: [ - { - name: 'field', - filterFieldTypes: 'number,date' - } - ] - }); -} +export const minMetricAgg = new MetricAggType({ + name: 'min', + title: 'Min', + makeLabel: function (aggConfig) { + return 'Min ' + aggConfig.getFieldDisplayName(); + }, + params: [ + { + name: 'field', + filterFieldTypes: 'number,date' + } + ] +}); diff --git a/src/ui/public/agg_types/metrics/moving_avg.js b/src/ui/public/agg_types/metrics/moving_avg.js index 18ab29ec2b44b..c6bb93c0c646b 100644 --- a/src/ui/public/agg_types/metrics/moving_avg.js +++ b/src/ui/public/agg_types/metrics/moving_avg.js @@ -1,18 +1,14 @@ -import { AggTypesMetricsMetricAggTypeProvider } from './metric_agg_type'; +import { MetricAggType } from './metric_agg_type'; import { parentPipelineAggHelper } from './lib/parent_pipeline_agg_helper'; import { makeNestedLabel } from './lib/make_nested_label'; -export function AggTypesMetricsMovingAvgProvider(Private) { - const MetricAggType = Private(AggTypesMetricsMetricAggTypeProvider); - - return new MetricAggType({ - name: 'moving_avg', - title: 'Moving Avg', - subtype: parentPipelineAggHelper.subtype, - makeLabel: agg => makeNestedLabel(agg, 'moving avg'), - params: [ - ...parentPipelineAggHelper.params() - ], - getFormat: parentPipelineAggHelper.getFormat - }); -} +export const movingAvgMetricAgg = new MetricAggType({ + name: 'moving_avg', + title: 'Moving Avg', + subtype: parentPipelineAggHelper.subtype, + makeLabel: agg => makeNestedLabel(agg, 'moving avg'), + params: [ + ...parentPipelineAggHelper.params() + ], + getFormat: parentPipelineAggHelper.getFormat +}); diff --git a/src/ui/public/agg_types/metrics/percentile_ranks.js b/src/ui/public/agg_types/metrics/percentile_ranks.js index 0b7834189dad1..bd52884c12bf5 100644 --- a/src/ui/public/agg_types/metrics/percentile_ranks.js +++ b/src/ui/public/agg_types/metrics/percentile_ranks.js @@ -1,61 +1,56 @@ import valuesEditor from '../controls/percentile_ranks.html'; import '../../number_list'; -import { AggTypesMetricsMetricAggTypeProvider } from './metric_agg_type'; -import { AggTypesMetricsGetResponseAggConfigClassProvider } from './get_response_agg_config_class'; +import { MetricAggType } from './metric_agg_type'; +import { getResponseAggConfigClass } from './get_response_agg_config_class'; import { fieldFormats } from '../../registry/field_formats'; import { getPercentileValue } from './percentiles_get_value'; -export function AggTypesMetricsPercentileRanksProvider(Private) { - const MetricAggType = Private(AggTypesMetricsMetricAggTypeProvider); - const getResponseAggConfigClass = Private(AggTypesMetricsGetResponseAggConfigClassProvider); +// required by the values editor - // required by the values editor +const valueProps = { + makeLabel: function () { + const field = this.getField(); + const format = (field && field.format) || fieldFormats.getDefaultInstance('number'); + const label = this.params.customLabel || this.getFieldDisplayName(); - const valueProps = { - makeLabel: function () { - const field = this.getField(); - const format = (field && field.format) || fieldFormats.getDefaultInstance('number'); - const label = this.params.customLabel || this.getFieldDisplayName(); + return 'Percentile rank ' + format.convert(this.key, 'text') + ' of "' + label + '"'; + } +}; - return 'Percentile rank ' + format.convert(this.key, 'text') + ' of "' + label + '"'; - } - }; - - return new MetricAggType({ - name: 'percentile_ranks', - title: 'Percentile Ranks', - makeLabel: function (agg) { - return 'Percentile ranks of ' + agg.getFieldDisplayName(); +export const percentileRanksMetricAgg = new MetricAggType({ + name: 'percentile_ranks', + title: 'Percentile Ranks', + makeLabel: function (agg) { + return 'Percentile ranks of ' + agg.getFieldDisplayName(); + }, + params: [ + { + name: 'field', + filterFieldTypes: 'number' }, - params: [ - { - name: 'field', - filterFieldTypes: 'number' - }, - { - name: 'values', - editor: valuesEditor, - default: [] - }, - { - write(agg, output) { - output.params.keyed = false; - } - } - ], - getResponseAggs: function (agg) { - const ValueAggConfig = getResponseAggConfigClass(agg, valueProps); - - return agg.params.values.map(function (value) { - return new ValueAggConfig(value); - }); + { + name: 'values', + editor: valuesEditor, + default: [] }, - getFormat: function () { - return fieldFormats.getInstance('percent') || fieldFormats.getDefaultInstance('number'); - }, - getValue: function (agg, bucket) { - return getPercentileValue(agg, bucket) / 100; + { + write(agg, output) { + output.params.keyed = false; + } } - }); -} + ], + getResponseAggs: function (agg) { + const ValueAggConfig = getResponseAggConfigClass(agg, valueProps); + + return agg.params.values.map(function (value) { + return new ValueAggConfig(value); + }); + }, + getFormat: function () { + return fieldFormats.getInstance('percent') || fieldFormats.getDefaultInstance('number'); + }, + getValue: function (agg, bucket) { + return getPercentileValue(agg, bucket) / 100; + } +}); diff --git a/src/ui/public/agg_types/metrics/percentiles.js b/src/ui/public/agg_types/metrics/percentiles.js index 75557d055f1db..5ec2bd9f0e45e 100644 --- a/src/ui/public/agg_types/metrics/percentiles.js +++ b/src/ui/public/agg_types/metrics/percentiles.js @@ -1,52 +1,45 @@ import { ordinalSuffix } from '../../utils/ordinal_suffix'; import percentsEditor from '../controls/percentiles.html'; import '../../number_list'; -import { AggTypesMetricsMetricAggTypeProvider } from './metric_agg_type'; -import { AggTypesMetricsGetResponseAggConfigClassProvider } from './get_response_agg_config_class'; +import { MetricAggType } from './metric_agg_type'; +import { getResponseAggConfigClass } from './get_response_agg_config_class'; import { getPercentileValue } from './percentiles_get_value'; -export function AggTypesMetricsPercentilesProvider(Private) { - const MetricAggType = Private(AggTypesMetricsMetricAggTypeProvider); - const getResponseAggConfigClass = Private(AggTypesMetricsGetResponseAggConfigClassProvider); +const valueProps = { + makeLabel: function () { + const label = this.params.customLabel || this.getFieldDisplayName(); + return ordinalSuffix(this.key) + ' percentile of ' + label; + } +}; - // required by the percentiles editor - - const valueProps = { - makeLabel: function () { - const label = this.params.customLabel || this.getFieldDisplayName(); - return ordinalSuffix(this.key) + ' percentile of ' + label; - } - }; - - return new MetricAggType({ - name: 'percentiles', - title: 'Percentiles', - makeLabel: function (agg) { - return 'Percentiles of ' + agg.getFieldDisplayName(); +export const percentilesMetricAgg = new MetricAggType({ + name: 'percentiles', + title: 'Percentiles', + makeLabel: function (agg) { + return 'Percentiles of ' + agg.getFieldDisplayName(); + }, + params: [ + { + name: 'field', + filterFieldTypes: 'number' }, - params: [ - { - name: 'field', - filterFieldTypes: 'number' - }, - { - name: 'percents', - editor: percentsEditor, - default: [1, 5, 25, 50, 75, 95, 99] - }, - { - write(agg, output) { - output.params.keyed = false; - } + { + name: 'percents', + editor: percentsEditor, + default: [1, 5, 25, 50, 75, 95, 99] + }, + { + write(agg, output) { + output.params.keyed = false; } - ], - getResponseAggs: function (agg) { - const ValueAggConfig = getResponseAggConfigClass(agg, valueProps); + } + ], + getResponseAggs: function (agg) { + const ValueAggConfig = getResponseAggConfigClass(agg, valueProps); - return agg.params.percents.map(function (percent) { - return new ValueAggConfig(percent); - }); - }, - getValue: getPercentileValue - }); -} + return agg.params.percents.map(function (percent) { + return new ValueAggConfig(percent); + }); + }, + getValue: getPercentileValue +}); diff --git a/src/ui/public/agg_types/metrics/serial_diff.js b/src/ui/public/agg_types/metrics/serial_diff.js index 8e3b6e94fc1cb..adfd11661986e 100644 --- a/src/ui/public/agg_types/metrics/serial_diff.js +++ b/src/ui/public/agg_types/metrics/serial_diff.js @@ -1,18 +1,14 @@ -import { AggTypesMetricsMetricAggTypeProvider } from './metric_agg_type'; +import { MetricAggType } from './metric_agg_type'; import { parentPipelineAggHelper } from './lib/parent_pipeline_agg_helper'; import { makeNestedLabel } from './lib/make_nested_label'; -export function AggTypesMetricsSerialDiffProvider(Private) { - const MetricAggType = Private(AggTypesMetricsMetricAggTypeProvider); - - return new MetricAggType({ - name: 'serial_diff', - title: 'Serial Diff', - subtype: parentPipelineAggHelper.subtype, - makeLabel: agg => makeNestedLabel(agg, 'serial diff'), - params: [ - ...parentPipelineAggHelper.params() - ], - getFormat: parentPipelineAggHelper.getFormat - }); -} +export const serialDiffMetricAgg = new MetricAggType({ + name: 'serial_diff', + title: 'Serial Diff', + subtype: parentPipelineAggHelper.subtype, + makeLabel: agg => makeNestedLabel(agg, 'serial diff'), + params: [ + ...parentPipelineAggHelper.params() + ], + getFormat: parentPipelineAggHelper.getFormat +}); diff --git a/src/ui/public/agg_types/metrics/std_deviation.js b/src/ui/public/agg_types/metrics/std_deviation.js index f3650eefb2027..ddf70f1e1ba9c 100644 --- a/src/ui/public/agg_types/metrics/std_deviation.js +++ b/src/ui/public/agg_types/metrics/std_deviation.js @@ -1,61 +1,56 @@ import _ from 'lodash'; -import { AggTypesMetricsMetricAggTypeProvider } from './metric_agg_type'; -import { AggTypesMetricsGetResponseAggConfigClassProvider } from './get_response_agg_config_class'; +import { MetricAggType } from './metric_agg_type'; +import { getResponseAggConfigClass } from './get_response_agg_config_class'; -export function AggTypesMetricsStdDeviationProvider(Private) { - const MetricAggType = Private(AggTypesMetricsMetricAggTypeProvider); - const getResponseAggConfigClass = Private(AggTypesMetricsGetResponseAggConfigClassProvider); +const responseAggConfigProps = { + valProp: function () { + const details = this.keyedDetails(this.params.customLabel)[this.key]; + return details.valProp; + }, + makeLabel: function () { + const fieldDisplayName = this.getFieldDisplayName(); + const details = this.keyedDetails(this.params.customLabel, fieldDisplayName); + return _.get(details, [this.key, 'title']); + }, + keyedDetails: function (customLabel, fieldDisplayName) { + const label = customLabel ? customLabel : 'Standard Deviation of ' + fieldDisplayName; + return { + std_lower: { + valProp: ['std_deviation_bounds', 'lower'], + title: 'Lower ' + label + }, + std_upper: { + valProp: ['std_deviation_bounds', 'upper'], + title: 'Upper ' + label + } + }; + } +}; - const responseAggConfigProps = { - valProp: function () { - const details = this.keyedDetails(this.params.customLabel)[this.key]; - return details.valProp; - }, - makeLabel: function () { - const fieldDisplayName = this.getFieldDisplayName(); - const details = this.keyedDetails(this.params.customLabel, fieldDisplayName); - return _.get(details, [this.key, 'title']); - }, - keyedDetails: function (customLabel, fieldDisplayName) { - const label = customLabel ? customLabel : 'Standard Deviation of ' + fieldDisplayName; - return { - std_lower: { - valProp: ['std_deviation_bounds', 'lower'], - title: 'Lower ' + label - }, - std_upper: { - valProp: ['std_deviation_bounds', 'upper'], - title: 'Upper ' + label - } - }; +export const stdDeviationMetricAgg = new MetricAggType({ + name: 'std_dev', + dslName: 'extended_stats', + title: 'Standard Deviation', + makeLabel: function (agg) { + return 'Standard Deviation of ' + agg.getFieldDisplayName(); + }, + params: [ + { + name: 'field', + filterFieldTypes: 'number' } - }; - - return new MetricAggType({ - name: 'std_dev', - dslName: 'extended_stats', - title: 'Standard Deviation', - makeLabel: function (agg) { - return 'Standard Deviation of ' + agg.getFieldDisplayName(); - }, - params: [ - { - name: 'field', - filterFieldTypes: 'number' - } - ], + ], - getResponseAggs: function (agg) { - const ValueAggConfig = getResponseAggConfigClass(agg, responseAggConfigProps); + getResponseAggs: function (agg) { + const ValueAggConfig = getResponseAggConfigClass(agg, responseAggConfigProps); - return [ - new ValueAggConfig('std_lower'), - new ValueAggConfig('std_upper') - ]; - }, + return [ + new ValueAggConfig('std_lower'), + new ValueAggConfig('std_upper') + ]; + }, - getValue: function (agg, bucket) { - return _.get(bucket[agg.parentId], agg.valProp()); - } - }); -} + getValue: function (agg, bucket) { + return _.get(bucket[agg.parentId], agg.valProp()); + } +}); diff --git a/src/ui/public/agg_types/metrics/sum.js b/src/ui/public/agg_types/metrics/sum.js index e339580353d38..dc9ed8a0efe65 100644 --- a/src/ui/public/agg_types/metrics/sum.js +++ b/src/ui/public/agg_types/metrics/sum.js @@ -1,22 +1,18 @@ -import { AggTypesMetricsMetricAggTypeProvider } from './metric_agg_type'; +import { MetricAggType } from './metric_agg_type'; -export function AggTypesMetricsSumProvider(Private) { - const MetricAggType = Private(AggTypesMetricsMetricAggTypeProvider); - - return new MetricAggType({ - name: 'sum', - title: 'Sum', - makeLabel: function (aggConfig) { - return 'Sum of ' + aggConfig.getFieldDisplayName(); - }, - params: [ - { - name: 'field', - filterFieldTypes: 'number' - } - ], - isScalable: function () { - return true; +export const sumMetricAgg = new MetricAggType({ + name: 'sum', + title: 'Sum', + makeLabel: function (aggConfig) { + return 'Sum of ' + aggConfig.getFieldDisplayName(); + }, + params: [ + { + name: 'field', + filterFieldTypes: 'number' } - }); -} + ], + isScalable: function () { + return true; + } +}); diff --git a/src/ui/public/agg_types/metrics/top_hit.js b/src/ui/public/agg_types/metrics/top_hit.js index 87a401b2e6001..d844087ad12eb 100644 --- a/src/ui/public/agg_types/metrics/top_hit.js +++ b/src/ui/public/agg_types/metrics/top_hit.js @@ -1,201 +1,197 @@ import _ from 'lodash'; -import { AggTypesMetricsMetricAggTypeProvider } from './metric_agg_type'; +import { MetricAggType } from './metric_agg_type'; import topSortEditor from '../controls/top_sort.html'; import aggregateAndSizeEditor from '../controls/top_aggregate_and_size.html'; -export function AggTypesMetricsTopHitProvider(Private) { - const MetricAggType = Private(AggTypesMetricsMetricAggTypeProvider); +const isNumber = function (type) { + return type === 'number'; +}; - const isNumber = function (type) { - return type === 'number'; - }; - - return new MetricAggType({ - name: 'top_hits', - title: 'Top Hit', - makeLabel: function (aggConfig) { - let prefix = aggConfig.params.sortOrder.val === 'desc' ? 'Last' : 'First'; - if (aggConfig.params.size !== 1) { - prefix += ` ${aggConfig.params.size}`; - } - const field = aggConfig.params.field; - return `${prefix} ${field ? field.displayName : ''}`; - }, - params: [ - { - name: 'field', - onlyAggregatable: false, - filterFieldTypes: function (vis, value) { - if (vis.type.name === 'table' || vis.type.name === 'metric') { - return true; - } - return value === 'number'; - }, - write(agg, output) { - const field = agg.params.field; - output.params = {}; +export const topHitMetricAgg = new MetricAggType({ + name: 'top_hits', + title: 'Top Hit', + makeLabel: function (aggConfig) { + let prefix = aggConfig.params.sortOrder.val === 'desc' ? 'Last' : 'First'; + if (aggConfig.params.size !== 1) { + prefix += ` ${aggConfig.params.size}`; + } + const field = aggConfig.params.field; + return `${prefix} ${field ? field.displayName : ''}`; + }, + params: [ + { + name: 'field', + onlyAggregatable: false, + filterFieldTypes: function (vis, value) { + if (vis.type.name === 'table' || vis.type.name === 'metric') { + return true; + } + return value === 'number'; + }, + write(agg, output) { + const field = agg.params.field; + output.params = {}; - if (field.scripted) { - output.params.script_fields = { - [ field.name ]: { - script: { - inline: field.script, - lang: field.lang - } + if (field.scripted) { + output.params.script_fields = { + [ field.name ]: { + script: { + inline: field.script, + lang: field.lang } - }; - } else { - if (field.readFromDocValues) { - output.params.docvalue_fields = [ field.name ]; } - output.params._source = field.name === '_source' ? true : field.name; + }; + } else { + if (field.readFromDocValues) { + output.params.docvalue_fields = [ field.name ]; } + output.params._source = field.name === '_source' ? true : field.name; } - }, - { - name: 'aggregate', - type: 'optioned', - editor: aggregateAndSizeEditor, - options: [ - { - display: 'Min', - isCompatibleType: isNumber, - isCompatibleVis: _.constant(true), - disabled: true, - val: 'min' - }, - { - display: 'Max', - isCompatibleType: isNumber, - isCompatibleVis: _.constant(true), - disabled: true, - val: 'max' - }, - { - display: 'Sum', - isCompatibleType: isNumber, - isCompatibleVis: _.constant(true), - disabled: true, - val: 'sum' - }, - { - display: 'Average', - isCompatibleType: isNumber, - isCompatibleVis: _.constant(true), - disabled: true, - val: 'average' + } + }, + { + name: 'aggregate', + type: 'optioned', + editor: aggregateAndSizeEditor, + options: [ + { + display: 'Min', + isCompatibleType: isNumber, + isCompatibleVis: _.constant(true), + disabled: true, + val: 'min' + }, + { + display: 'Max', + isCompatibleType: isNumber, + isCompatibleVis: _.constant(true), + disabled: true, + val: 'max' + }, + { + display: 'Sum', + isCompatibleType: isNumber, + isCompatibleVis: _.constant(true), + disabled: true, + val: 'sum' + }, + { + display: 'Average', + isCompatibleType: isNumber, + isCompatibleVis: _.constant(true), + disabled: true, + val: 'average' + }, + { + display: 'Concatenate', + isCompatibleType: _.constant(true), + isCompatibleVis: function (name) { + return name === 'metric' || name === 'table'; }, - { - display: 'Concatenate', - isCompatibleType: _.constant(true), - isCompatibleVis: function (name) { - return name === 'metric' || name === 'table'; - }, - disabled: true, - val: 'concat' - } - ], - controller: function ($scope) { - $scope.options = []; - $scope.$watchGroup([ 'agg.vis.type.name', 'agg.params.field.type' ], function ([ visName, fieldType ]) { - if (fieldType && visName) { - $scope.options = _.filter($scope.aggParam.options, option => { - return option.isCompatibleVis(visName) && option.isCompatibleType(fieldType); - }); - if ($scope.options.length === 1) { - $scope.agg.params.aggregate = $scope.options[0]; - } + disabled: true, + val: 'concat' + } + ], + controller: function ($scope) { + $scope.options = []; + $scope.$watchGroup([ 'agg.vis.type.name', 'agg.params.field.type' ], function ([ visName, fieldType ]) { + if (fieldType && visName) { + $scope.options = _.filter($scope.aggParam.options, option => { + return option.isCompatibleVis(visName) && option.isCompatibleType(fieldType); + }); + if ($scope.options.length === 1) { + $scope.agg.params.aggregate = $scope.options[0]; } - }); - }, - write: _.noop - }, - { - name: 'size', - editor: null, // size setting is done together with the aggregation setting - default: 1 + } + }); }, - { - name: 'sortField', - type: 'field', - editor: null, - filterFieldTypes: [ 'number', 'date', 'ip', 'string' ], - default: function (agg) { - return agg.vis.indexPattern.timeFieldName; - }, - write: _.noop // prevent default write, it is handled below + write: _.noop + }, + { + name: 'size', + editor: null, // size setting is done together with the aggregation setting + default: 1 + }, + { + name: 'sortField', + type: 'field', + editor: null, + filterFieldTypes: [ 'number', 'date', 'ip', 'string' ], + default: function (agg) { + return agg.vis.indexPattern.timeFieldName; }, - { - name: 'sortOrder', - type: 'optioned', - default: 'desc', - editor: topSortEditor, - options: [ - { display: 'Descending', val: 'desc' }, - { display: 'Ascending', val: 'asc' } - ], - write(agg, output) { - const sortField = agg.params.sortField; - const sortOrder = agg.params.sortOrder; + write: _.noop // prevent default write, it is handled below + }, + { + name: 'sortOrder', + type: 'optioned', + default: 'desc', + editor: topSortEditor, + options: [ + { display: 'Descending', val: 'desc' }, + { display: 'Ascending', val: 'asc' } + ], + write(agg, output) { + const sortField = agg.params.sortField; + const sortOrder = agg.params.sortOrder; - if (sortField.scripted) { - output.params.sort = [ - { - _script: { - script: { - inline: sortField.script, - lang: sortField.lang - }, - type: sortField.type, - order: sortOrder.val - } + if (sortField.scripted) { + output.params.sort = [ + { + _script: { + script: { + inline: sortField.script, + lang: sortField.lang + }, + type: sortField.type, + order: sortOrder.val } - ]; - } else { - output.params.sort = [ - { - [ sortField.name ]: { - order: sortOrder.val - } + } + ]; + } else { + output.params.sort = [ + { + [ sortField.name ]: { + order: sortOrder.val } - ]; - } + } + ]; } } - ], - getValue(agg, bucket) { - const hits = _.get(bucket, `${agg.id}.hits.hits`); - if (!hits || !hits.length) { - return null; - } - const path = agg.params.field.name; + } + ], + getValue(agg, bucket) { + const hits = _.get(bucket, `${agg.id}.hits.hits`); + if (!hits || !hits.length) { + return null; + } + const path = agg.params.field.name; - let values = _(hits).map(hit => { - return path === '_source' ? hit._source : agg.vis.indexPattern.flattenHit(hit, true)[path]; - }) - .flatten() - .value(); + let values = _(hits).map(hit => { + return path === '_source' ? hit._source : agg.vis.indexPattern.flattenHit(hit, true)[path]; + }) + .flatten() + .value(); - if (values.length === 1) { - values = values[0]; - } + if (values.length === 1) { + values = values[0]; + } - if (Array.isArray(values)) { - if (!_.compact(values).length) { - return null; - } - switch (agg.params.aggregate.val) { - case 'max': - return _.max(values); - case 'min': - return _.min(values); - case 'sum': - return _.sum(values); - case 'average': - return _.sum(values) / values.length; - } + if (Array.isArray(values)) { + if (!_.compact(values).length) { + return null; + } + switch (agg.params.aggregate.val) { + case 'max': + return _.max(values); + case 'min': + return _.min(values); + case 'sum': + return _.sum(values); + case 'average': + return _.sum(values) / values.length; } - return values; } - }); -} + return values; + } +}); diff --git a/src/ui/public/config/__tests__/config.js b/src/ui/public/config/__tests__/config.js index e4a9314056450..92ae1fa3b68ab 100644 --- a/src/ui/public/config/__tests__/config.js +++ b/src/ui/public/config/__tests__/config.js @@ -24,6 +24,7 @@ describe('Config service', () => { config.getAll(); sinon.assert.calledOnce(uiSettings.getAll); sinon.assert.calledWithExactly(uiSettings.getAll); + uiSettings.getAll.restore(); }); }); @@ -33,6 +34,7 @@ describe('Config service', () => { config.get('key', 'default'); sinon.assert.calledOnce(uiSettings.get); sinon.assert.calledWithExactly(uiSettings.get, 'key', 'default'); + uiSettings.get.restore(); }); }); @@ -42,6 +44,7 @@ describe('Config service', () => { config.isDeclared('key'); sinon.assert.calledOnce(uiSettings.isDeclared); sinon.assert.calledWithExactly(uiSettings.isDeclared, 'key'); + uiSettings.isDeclared.restore(); }); }); @@ -51,6 +54,7 @@ describe('Config service', () => { config.isDefault('key'); sinon.assert.calledOnce(uiSettings.isDefault); sinon.assert.calledWithExactly(uiSettings.isDefault, 'key'); + uiSettings.isDefault.restore(); }); }); @@ -69,6 +73,7 @@ describe('Config service', () => { config.remove('foobar'); sinon.assert.calledOnce(uiSettings.remove); sinon.assert.calledWithExactly(uiSettings.remove, 'foobar'); + uiSettings.remove.restore(); }); it('returns an angular promise', () => { diff --git a/src/ui/public/courier/data_source/__tests__/decorate_query.js b/src/ui/public/courier/data_source/__tests__/decorate_query.js index 13fab80e81ae0..28d785b271cf8 100644 --- a/src/ui/public/courier/data_source/__tests__/decorate_query.js +++ b/src/ui/public/courier/data_source/__tests__/decorate_query.js @@ -1,36 +1,17 @@ import expect from 'expect.js'; -import ngMock from 'ng_mock'; -import { DecorateQueryProvider } from '../_decorate_query'; +import chrome from 'ui/chrome'; +import { decorateQuery } from '../_decorate_query'; +const config = chrome.getUiSettingsClient(); describe('Query decorator', function () { - let config; - - let fn; - beforeEach(ngMock.module( - 'kibana', - function ($provide) { - // Super simple config stub - $provide.service('config', function () { - const keys = {}; - return { - get: function (key) { return keys[key]; }, - set: function (key, value) { keys[key] = value; } - }; - }); - } - )); - - beforeEach(ngMock.inject(function (Private, $injector, _config_) { - config = _config_; - fn = Private(DecorateQueryProvider); - })); it('should be a function', function () { - expect(fn).to.be.a(Function); + expect(decorateQuery).to.be.a(Function); }); it('should merge in the query string options', function () { config.set('query:queryString:options', { analyze_wildcard: true }); - expect(fn({ query_string: { query: '*' } })).to.eql({ query_string: { query: '*', analyze_wildcard: true } }); + const decoratedQuery = decorateQuery({ query_string: { query: '*' } }); + expect(decoratedQuery).to.eql({ query_string: { query: '*', analyze_wildcard: true } }); }); }); diff --git a/src/ui/public/courier/data_source/_decorate_query.js b/src/ui/public/courier/data_source/_decorate_query.js index 7f1c512837217..d7cab51c01400 100644 --- a/src/ui/public/courier/data_source/_decorate_query.js +++ b/src/ui/public/courier/data_source/_decorate_query.js @@ -1,18 +1,19 @@ import _ from 'lodash'; +import chrome from 'ui/chrome'; -export function DecorateQueryProvider(config) { - /** - * Decorate queries with default parameters - * @param {query} query object - * @returns {object} - */ - return function (query) { - const queryOptions = config.get('query:queryString:options'); +const config = chrome.getUiSettingsClient(); - if (_.has(query, 'query_string.query')) { - _.extend(query.query_string, queryOptions); - } +/** + * Decorate queries with default parameters + * @param {query} query object + * @returns {object} + */ +export function decorateQuery(query) { + const queryOptions = config.get('query:queryString:options'); - return query; - }; + if (_.has(query, 'query_string.query')) { + _.extend(query.query_string, queryOptions); + } + + return query; } diff --git a/src/ui/public/courier/data_source/build_query/__tests__/build_es_query.js b/src/ui/public/courier/data_source/build_query/__tests__/build_es_query.js index 018005918c1bb..bbf0e74a545b7 100644 --- a/src/ui/public/courier/data_source/build_query/__tests__/build_es_query.js +++ b/src/ui/public/courier/data_source/build_query/__tests__/build_es_query.js @@ -4,11 +4,10 @@ import ngMock from 'ng_mock'; import { expectDeepEqual } from '../../../../../../test_utils/expect_deep_equal.js'; import { fromKueryExpression, toElasticsearchQuery } from '../../../../kuery'; import { luceneStringToDsl } from '../lucene_string_to_dsl'; -import { DecorateQueryProvider } from '../../_decorate_query'; +import { decorateQuery } from '../../_decorate_query'; let indexPattern; let buildEsQuery; -let decorateQuery; describe('build query', function () { @@ -18,7 +17,6 @@ describe('build query', function () { beforeEach(ngMock.inject(function (Private) { indexPattern = Private(StubbedLogstashIndexPatternProvider); buildEsQuery = Private(BuildESQueryProvider); - decorateQuery = Private(DecorateQueryProvider); })); it('should return the parameters of an Elasticsearch bool query', function () { diff --git a/src/ui/public/courier/data_source/build_query/__tests__/from_lucene.js b/src/ui/public/courier/data_source/build_query/__tests__/from_lucene.js index 1b7c6a43ee18f..ee6406bbea90c 100644 --- a/src/ui/public/courier/data_source/build_query/__tests__/from_lucene.js +++ b/src/ui/public/courier/data_source/build_query/__tests__/from_lucene.js @@ -1,20 +1,13 @@ import { buildQueryFromLucene } from '../from_lucene'; -import { DecorateQueryProvider } from '../../_decorate_query.js'; -import ngMock from 'ng_mock'; +import { decorateQuery } from '../../_decorate_query.js'; import { expectDeepEqual } from '../../../../../../test_utils/expect_deep_equal.js'; import { luceneStringToDsl } from '../lucene_string_to_dsl'; -let decorateQuery; describe('build query', function () { describe('buildQueryFromLucene', function () { - beforeEach(ngMock.module('kibana')); - beforeEach(ngMock.inject(function (Private) { - decorateQuery = Private(DecorateQueryProvider); - })); - it('should return the parameters of an Elasticsearch bool query', function () { const result = buildQueryFromLucene(); const expected = { diff --git a/src/ui/public/courier/data_source/build_query/build_es_query.js b/src/ui/public/courier/data_source/build_query/build_es_query.js index fe855f3db9ade..cdfeb45f8a6f7 100644 --- a/src/ui/public/courier/data_source/build_query/build_es_query.js +++ b/src/ui/public/courier/data_source/build_query/build_es_query.js @@ -1,11 +1,10 @@ import { groupBy, has } from 'lodash'; -import { DecorateQueryProvider } from '../_decorate_query'; +import { decorateQuery } from '../_decorate_query'; import { buildQueryFromKuery } from './from_kuery'; import { buildQueryFromFilters } from './from_filters'; import { buildQueryFromLucene } from './from_lucene'; -export function BuildESQueryProvider(Private, config) { - const decorateQuery = Private(DecorateQueryProvider); +export function BuildESQueryProvider(config) { /** * diff --git a/src/ui/public/time_buckets/calc_auto_interval.js b/src/ui/public/time_buckets/calc_auto_interval.js index 007aba6d69f49..ebb8358dd7ef1 100644 --- a/src/ui/public/time_buckets/calc_auto_interval.js +++ b/src/ui/public/time_buckets/calc_auto_interval.js @@ -1,71 +1,69 @@ import moment from 'moment'; const { duration: d } = moment; -export function TimeBucketsCalcAutoIntervalProvider() { - // these are the rounding rules used by roundInterval() +// these are the rounding rules used by roundInterval() - const roundingRules = [ - [ d(500, 'ms'), d(100, 'ms') ], - [ d(5, 'second'), d(1, 'second') ], - [ d(7.5, 'second'), d(5, 'second') ], - [ d(15, 'second'), d(10, 'second') ], - [ d(45, 'second'), d(30, 'second') ], - [ d(3, 'minute'), d(1, 'minute') ], - [ d(9, 'minute'), d(5, 'minute') ], - [ d(20, 'minute'), d(10, 'minute') ], - [ d(45, 'minute'), d(30, 'minute') ], - [ d(2, 'hour'), d(1, 'hour') ], - [ d(6, 'hour'), d(3, 'hour') ], - [ d(24, 'hour'), d(12, 'hour') ], - [ d(1, 'week'), d(1, 'd') ], - [ d(3, 'week'), d(1, 'week') ], - [ d(1, 'year'), d(1, 'month') ], - [ Infinity, d(1, 'year') ] - ]; +const roundingRules = [ + [ d(500, 'ms'), d(100, 'ms') ], + [ d(5, 'second'), d(1, 'second') ], + [ d(7.5, 'second'), d(5, 'second') ], + [ d(15, 'second'), d(10, 'second') ], + [ d(45, 'second'), d(30, 'second') ], + [ d(3, 'minute'), d(1, 'minute') ], + [ d(9, 'minute'), d(5, 'minute') ], + [ d(20, 'minute'), d(10, 'minute') ], + [ d(45, 'minute'), d(30, 'minute') ], + [ d(2, 'hour'), d(1, 'hour') ], + [ d(6, 'hour'), d(3, 'hour') ], + [ d(24, 'hour'), d(12, 'hour') ], + [ d(1, 'week'), d(1, 'd') ], + [ d(3, 'week'), d(1, 'week') ], + [ d(1, 'year'), d(1, 'month') ], + [ Infinity, d(1, 'year') ] +]; - const revRoundingRules = roundingRules.slice(0).reverse(); +const revRoundingRules = roundingRules.slice(0).reverse(); - function find(rules, check, last) { - function pick(buckets, duration) { - const target = duration / buckets; - let lastResp; +function find(rules, check, last) { + function pick(buckets, duration) { + const target = duration / buckets; + let lastResp; - for (let i = 0; i < rules.length; i++) { - const rule = rules[i]; - const resp = check(rule[0], rule[1], target); + for (let i = 0; i < rules.length; i++) { + const rule = rules[i]; + const resp = check(rule[0], rule[1], target); - if (resp == null) { - if (!last) continue; - if (lastResp) return lastResp; - break; - } - - if (!last) return resp; - lastResp = resp; + if (resp == null) { + if (!last) continue; + if (lastResp) return lastResp; + break; } - // fallback to just a number of milliseconds, ensure ms is >= 1 - const ms = Math.max(Math.floor(target), 1); - return moment.duration(ms, 'ms'); + if (!last) return resp; + lastResp = resp; } - return function (buckets, duration) { - const interval = pick(buckets, duration); - if (interval) return moment.duration(interval._data); - }; + // fallback to just a number of milliseconds, ensure ms is >= 1 + const ms = Math.max(Math.floor(target), 1); + return moment.duration(ms, 'ms'); } - return { - near: find(revRoundingRules, function near(bound, interval, target) { - if (bound > target) return interval; - }, true), - - lessThan: find(revRoundingRules, function (bound, interval, target) { - if (interval < target) return interval; - }), - - atLeast: find(revRoundingRules, function atLeast(bound, interval, target) { - if (interval <= target) return interval; - }), + return function (buckets, duration) { + const interval = pick(buckets, duration); + if (interval) return moment.duration(interval._data); }; } + +export const calcAutoInterval = { + near: find(revRoundingRules, function near(bound, interval, target) { + if (bound > target) return interval; + }, true), + + lessThan: find(revRoundingRules, function (bound, interval, target) { + if (interval < target) return interval; + }), + + atLeast: find(revRoundingRules, function atLeast(bound, interval, target) { + if (interval <= target) return interval; + }), +}; diff --git a/src/ui/public/time_buckets/calc_es_interval.js b/src/ui/public/time_buckets/calc_es_interval.js index 053e2ea4e79d3..8954fcbd3023b 100644 --- a/src/ui/public/time_buckets/calc_es_interval.js +++ b/src/ui/public/time_buckets/calc_es_interval.js @@ -1,48 +1,42 @@ import dateMath from '@kbn/datemath'; -export function TimeBucketsCalcEsIntervalProvider() { - - const unitsDesc = dateMath.unitsDesc; - const largeMax = unitsDesc.indexOf('M'); - - /** - * Convert a moment.duration into an es - * compatible expression, and provide - * associated metadata - * - * @param {moment.duration} duration - * @return {object} - */ - function esDuration(duration) { - for (let i = 0; i < unitsDesc.length; i++) { - const unit = unitsDesc[i]; - const val = duration.as(unit); - // find a unit that rounds neatly - if (val >= 1 && Math.floor(val) === val) { - - // if the unit is "large", like years, but - // isn't set to 1 ES will puke. So keep going until - // we get out of the "large" units - if (i <= largeMax && val !== 1) { - continue; - } - - return { - value: val, - unit: unit, - expression: val + unit - }; +const unitsDesc = dateMath.unitsDesc; +const largeMax = unitsDesc.indexOf('M'); + +/** + * Convert a moment.duration into an es + * compatible expression, and provide + * associated metadata + * + * @param {moment.duration} duration + * @return {object} + */ +export function calcEsInterval(duration) { + for (let i = 0; i < unitsDesc.length; i++) { + const unit = unitsDesc[i]; + const val = duration.as(unit); + // find a unit that rounds neatly + if (val >= 1 && Math.floor(val) === val) { + + // if the unit is "large", like years, but + // isn't set to 1 ES will puke. So keep going until + // we get out of the "large" units + if (i <= largeMax && val !== 1) { + continue; } - } - const ms = duration.as('ms'); - return { - value: ms, - unit: 'ms', - expression: ms + 'ms' - }; + return { + value: val, + unit: unit, + expression: val + unit + }; + } } - - return esDuration; + const ms = duration.as('ms'); + return { + value: ms, + unit: 'ms', + expression: ms + 'ms' + }; } diff --git a/src/ui/public/time_buckets/index.js b/src/ui/public/time_buckets/index.js index 73abb24fc7228..9d15d084ec1f8 100644 --- a/src/ui/public/time_buckets/index.js +++ b/src/ui/public/time_buckets/index.js @@ -1 +1 @@ -export { TimeBucketsProvider } from './time_buckets'; +export { TimeBuckets } from './time_buckets'; diff --git a/src/ui/public/time_buckets/time_buckets.js b/src/ui/public/time_buckets/time_buckets.js index 3cf69631d5124..40ad6da505dd6 100644 --- a/src/ui/public/time_buckets/time_buckets.js +++ b/src/ui/public/time_buckets/time_buckets.js @@ -1,380 +1,377 @@ import _ from 'lodash'; import moment from 'moment'; +import chrome from 'ui/chrome'; import { parseInterval } from '../utils/parse_interval'; -import { TimeBucketsCalcAutoIntervalProvider } from './calc_auto_interval'; -import { TimeBucketsCalcEsIntervalProvider } from './calc_es_interval'; +import { calcAutoInterval } from './calc_auto_interval'; +import { calcEsInterval } from './calc_es_interval'; import { fieldFormats } from '../registry/field_formats'; -export function TimeBucketsProvider(Private, timefilter, config) { - const calcAuto = Private(TimeBucketsCalcAutoIntervalProvider); - const calcEsInterval = Private(TimeBucketsCalcEsIntervalProvider); +const config = chrome.getUiSettingsClient(); - const getConfig = (...args) => config.get(...args); +const getConfig = (...args) => config.get(...args); - function isValidMoment(m) { - return m && ('isValid' in m) && m.isValid(); - } - - /** - * Helper class for wrapping the concept of an "Interval", - * which describes a timespan that will seperate moments. - * - * @param {state} object - one of "" - * @param {[type]} display [description] - */ - function TimeBuckets() { - return TimeBuckets.__cached__(this); - } - - /**** - * PUBLIC API - ****/ - - /** - * Set the bounds that these buckets are expected to cover. - * This is required to support interval "auto" as well - * as interval scaling. - * - * @param {object} input - an object with properties min and max, - * representing the edges for the time span - * we should cover - * - * @returns {undefined} - */ - TimeBuckets.prototype.setBounds = function (input) { - if (!input) return this.clearBounds(); - - let bounds; - if (_.isPlainObject(input)) { - // accept the response from timefilter.getActiveBounds() - bounds = [input.min, input.max]; - } else { - bounds = Array.isArray(input) ? input : []; - } - - const moments = _(bounds) - .map(_.ary(moment, 1)) - .sortBy(Number); +function isValidMoment(m) { + return m && ('isValid' in m) && m.isValid(); +} - const valid = moments.size() === 2 && moments.every(isValidMoment); - if (!valid) { - this.clearBounds(); - throw new Error('invalid bounds set: ' + input); - } +/** + * Helper class for wrapping the concept of an "Interval", + * which describes a timespan that will seperate moments. + * + * @param {state} object - one of "" + * @param {[type]} display [description] + */ +function TimeBuckets() { + return TimeBuckets.__cached__(this); +} - this._lb = moments.shift(); - this._ub = moments.pop(); - if (this.getDuration().asSeconds() < 0) { - throw new TypeError('Intervals must be positive'); - } - }; +/**** + * PUBLIC API + ****/ + +/** + * Set the bounds that these buckets are expected to cover. + * This is required to support interval "auto" as well + * as interval scaling. + * + * @param {object} input - an object with properties min and max, + * representing the edges for the time span + * we should cover + * + * @returns {undefined} + */ +TimeBuckets.prototype.setBounds = function (input) { + if (!input) return this.clearBounds(); + + let bounds; + if (_.isPlainObject(input)) { + // accept the response from timefilter.getActiveBounds() + bounds = [input.min, input.max]; + } else { + bounds = Array.isArray(input) ? input : []; + } - /** - * Clear the stored bounds - * - * @return {undefined} - */ - TimeBuckets.prototype.clearBounds = function () { - this._lb = this._ub = null; - }; + const moments = _(bounds) + .map(_.ary(moment, 1)) + .sortBy(Number); - /** - * Check to see if we have received bounds yet - * - * @return {Boolean} - */ - TimeBuckets.prototype.hasBounds = function () { - return isValidMoment(this._ub) && isValidMoment(this._lb); - }; + const valid = moments.size() === 2 && moments.every(isValidMoment); + if (!valid) { + this.clearBounds(); + throw new Error('invalid bounds set: ' + input); + } - /** - * Return the current bounds, if we have any. - * - * THIS DOES NOT CLONE THE BOUNDS, so editing them - * may have unexpected side-effects. Always - * call bounds.min.clone() before editing - * - * @return {object|undefined} - If bounds are not defined, this - * returns undefined, else it returns the bounds - * for these buckets. This object has two props, - * min and max. Each property will be a moment() - * object - * - */ - TimeBuckets.prototype.getBounds = function () { - if (!this.hasBounds()) return; - return { - min: this._lb, - max: this._ub - }; + this._lb = moments.shift(); + this._ub = moments.pop(); + if (this.getDuration().asSeconds() < 0) { + throw new TypeError('Intervals must be positive'); + } +}; + +/** + * Clear the stored bounds + * + * @return {undefined} + */ +TimeBuckets.prototype.clearBounds = function () { + this._lb = this._ub = null; +}; + +/** + * Check to see if we have received bounds yet + * + * @return {Boolean} + */ +TimeBuckets.prototype.hasBounds = function () { + return isValidMoment(this._ub) && isValidMoment(this._lb); +}; + +/** + * Return the current bounds, if we have any. + * + * THIS DOES NOT CLONE THE BOUNDS, so editing them + * may have unexpected side-effects. Always + * call bounds.min.clone() before editing + * + * @return {object|undefined} - If bounds are not defined, this + * returns undefined, else it returns the bounds + * for these buckets. This object has two props, + * min and max. Each property will be a moment() + * object + * + */ +TimeBuckets.prototype.getBounds = function () { + if (!this.hasBounds()) return; + return { + min: this._lb, + max: this._ub }; +}; + +/** + * Get a moment duration object representing + * the distance between the bounds, if the bounds + * are set. + * + * @return {moment.duration|undefined} + */ +TimeBuckets.prototype.getDuration = function () { + if (!this.hasBounds()) return; + return moment.duration(this._ub - this._lb, 'ms'); +}; + +/** + * Update the interval at which buckets should be + * generated. + * + * Input can be one of the following: + * - Any object from src/ui/agg_types/buckets/_interval_options.js + * - "auto" + * - Pass a valid moment unit + * - a moment.duration object. + * + * @param {object|string|moment.duration} input - see desc + */ +TimeBuckets.prototype.setInterval = function (input) { + let interval = input; + + // selection object -> val + if (_.isObject(input)) { + interval = input.val; + } - /** - * Get a moment duration object representing - * the distance between the bounds, if the bounds - * are set. - * - * @return {moment.duration|undefined} - */ - TimeBuckets.prototype.getDuration = function () { - if (!this.hasBounds()) return; - return moment.duration(this._ub - this._lb, 'ms'); - }; + if (!interval || interval === 'auto') { + this._i = 'auto'; + return; + } - /** - * Update the interval at which buckets should be - * generated. - * - * Input can be one of the following: - * - Any object from src/ui/agg_types/buckets/_interval_options.js - * - "auto" - * - Pass a valid moment unit - * - a moment.duration object. - * - * @param {object|string|moment.duration} input - see desc - */ - TimeBuckets.prototype.setInterval = function (input) { - let interval = input; - - // selection object -> val - if (_.isObject(input)) { - interval = input.val; + if (_.isString(interval)) { + input = interval; + interval = parseInterval(interval); + if (+interval === 0) { + interval = null; } + } - if (!interval || interval === 'auto') { - this._i = 'auto'; - return; - } + // if the value wasn't converted to a duration, and isn't + // already a duration, we have a problem + if (!moment.isDuration(interval)) { + throw new TypeError('"' + input + '" is not a valid interval.'); + } - if (_.isString(interval)) { - input = interval; - interval = parseInterval(interval); - if (+interval === 0) { - interval = null; - } - } + this._i = interval; +}; + +/** + * Get the interval for the buckets. If the + * number of buckets created by the interval set + * is larger than config:histogram:maxBars then the + * interval will be scaled up. If the number of buckets + * created is less than one, the interval is scaled back. + * + * The interval object returned is a moment.duration + * object that has been decorated with the following + * properties. + * + * interval.description: a text description of the interval. + * designed to be used list "field per {{ desc }}". + * - "minute" + * - "10 days" + * - "3 years" + * + * interval.expr: the elasticsearch expression that creates this + * interval. If the interval does not properly form an elasticsearch + * expression it will be forced into one. + * + * interval.scaled: the interval was adjusted to + * accomidate the maxBars setting. + * + * interval.scale: the numer that y-values should be + * multiplied by + * + * interval.scaleDescription: a description that reflects + * the values which will be produced by using the + * interval.scale. + * + * + * @return {[type]} [description] + */ +TimeBuckets.prototype.getInterval = function () { + const self = this; + const duration = self.getDuration(); + return decorateInterval(maybeScaleInterval(readInterval())); + + // either pull the interval from state or calculate the auto-interval + function readInterval() { + const interval = self._i; + if (moment.isDuration(interval)) return interval; + return calcAutoInterval.near(config.get('histogram:barTarget'), duration); + } - // if the value wasn't converted to a duration, and isn't - // already a duration, we have a problem - if (!moment.isDuration(interval)) { - throw new TypeError('"' + input + '" is not a valid interval.'); - } + // check to see if the interval should be scaled, and scale it if so + function maybeScaleInterval(interval) { + if (!self.hasBounds()) return interval; - this._i = interval; - }; + const maxLength = config.get('histogram:maxBars'); + const approxLen = duration / interval; + let scaled; - /** - * Get the interval for the buckets. If the - * number of buckets created by the interval set - * is larger than config:histogram:maxBars then the - * interval will be scaled up. If the number of buckets - * created is less than one, the interval is scaled back. - * - * The interval object returned is a moment.duration - * object that has been decorated with the following - * properties. - * - * interval.description: a text description of the interval. - * designed to be used list "field per {{ desc }}". - * - "minute" - * - "10 days" - * - "3 years" - * - * interval.expr: the elasticsearch expression that creates this - * interval. If the interval does not properly form an elasticsearch - * expression it will be forced into one. - * - * interval.scaled: the interval was adjusted to - * accomidate the maxBars setting. - * - * interval.scale: the numer that y-values should be - * multiplied by - * - * interval.scaleDescription: a description that reflects - * the values which will be produced by using the - * interval.scale. - * - * - * @return {[type]} [description] - */ - TimeBuckets.prototype.getInterval = function () { - const self = this; - const duration = self.getDuration(); - return decorateInterval(maybeScaleInterval(readInterval())); - - // either pull the interval from state or calculate the auto-interval - function readInterval() { - const interval = self._i; - if (moment.isDuration(interval)) return interval; - return calcAuto.near(config.get('histogram:barTarget'), duration); + if (approxLen > maxLength) { + scaled = calcAutoInterval.lessThan(maxLength, duration); + } else { + return interval; } - // check to see if the interval should be scaled, and scale it if so - function maybeScaleInterval(interval) { - if (!self.hasBounds()) return interval; - - const maxLength = config.get('histogram:maxBars'); - const approxLen = duration / interval; - let scaled; + if (+scaled === +interval) return interval; - if (approxLen > maxLength) { - scaled = calcAuto.lessThan(maxLength, duration); - } else { - return interval; - } + decorateInterval(interval); + return _.assign(scaled, { + preScaled: interval, + scale: interval / scaled, + scaled: true + }); + } - if (+scaled === +interval) return interval; + // append some TimeBuckets specific props to the interval + function decorateInterval(interval) { + const esInterval = calcEsInterval(interval); + interval.esValue = esInterval.value; + interval.esUnit = esInterval.unit; + interval.expression = esInterval.expression; + interval.overflow = duration > interval ? moment.duration(interval - duration) : false; + + const prettyUnits = moment.normalizeUnits(esInterval.unit); + if (esInterval.value === 1) { + interval.description = prettyUnits; + } else { + interval.description = esInterval.value + ' ' + prettyUnits + 's'; + } - decorateInterval(interval); - return _.assign(scaled, { - preScaled: interval, - scale: interval / scaled, - scaled: true - }); + return interval; + } +}; + +/** + * Get a date format string that will represent dates that + * progress at our interval. + * + * Since our interval can be as small as 1ms, the default + * date format is usually way too much. with `dateFormat:scaled` + * users can modify how dates are formatted within series + * produced by TimeBuckets + * + * @return {string} + */ +TimeBuckets.prototype.getScaledDateFormat = function () { + const interval = this.getInterval(); + const rules = config.get('dateFormat:scaled'); + + for (let i = rules.length - 1; i >= 0; i--) { + const rule = rules[i]; + if (!rule[0] || interval >= moment.duration(rule[0])) { + return rule[1]; } + } - // append some TimeBuckets specific props to the interval - function decorateInterval(interval) { - const esInterval = calcEsInterval(interval); - interval.esValue = esInterval.value; - interval.esUnit = esInterval.unit; - interval.expression = esInterval.expression; - interval.overflow = duration > interval ? moment.duration(interval - duration) : false; - - const prettyUnits = moment.normalizeUnits(esInterval.unit); - if (esInterval.value === 1) { - interval.description = prettyUnits; - } else { - interval.description = esInterval.value + ' ' + prettyUnits + 's'; - } + return config.get('dateFormat'); +}; - return interval; - } - }; +TimeBuckets.prototype.getScaledDateFormatter = function () { + const DateFieldFormat = fieldFormats.getType('date'); + return new DateFieldFormat({ + pattern: this.getScaledDateFormat() + }, getConfig); +}; - /** - * Get a date format string that will represent dates that - * progress at our interval. - * - * Since our interval can be as small as 1ms, the default - * date format is usually way too much. with `dateFormat:scaled` - * users can modify how dates are formatted within series - * produced by TimeBuckets - * - * @return {string} - */ - TimeBuckets.prototype.getScaledDateFormat = function () { - const interval = this.getInterval(); - const rules = config.get('dateFormat:scaled'); - - for (let i = rules.length - 1; i >= 0; i--) { - const rule = rules[i]; - if (!rule[0] || interval >= moment.duration(rule[0])) { - return rule[1]; - } - } - return config.get('dateFormat'); - }; +TimeBuckets.__cached__ = function (self) { + let cache = {}; + const sameMoment = same(moment.isMoment); + const sameDuration = same(moment.isDuration); - TimeBuckets.prototype.getScaledDateFormatter = function () { - const DateFieldFormat = fieldFormats.getType('date'); - return new DateFieldFormat({ - pattern: this.getScaledDateFormat() - }, getConfig); + const desc = { + __cached__: { + value: self + }, }; + const breakers = { + setBounds: 'bounds', + clearBounds: 'bounds', + setInterval: 'interval' + }; - TimeBuckets.__cached__ = function (self) { - let cache = {}; - const sameMoment = same(moment.isMoment); - const sameDuration = same(moment.isDuration); - - const desc = { - __cached__: { - value: self + const resources = { + bounds: { + setup: function () { + return [self._lb, self._ub]; }, - }; - - const breakers = { - setBounds: 'bounds', - clearBounds: 'bounds', - setInterval: 'interval' - }; - - const resources = { - bounds: { - setup: function () { - return [self._lb, self._ub]; - }, - changes: function (prev) { - return !sameMoment(prev[0], self._lb) || !sameMoment(prev[1], self._ub); - } + changes: function (prev) { + return !sameMoment(prev[0], self._lb) || !sameMoment(prev[1], self._ub); + } + }, + interval: { + setup: function () { + return self._i; }, - interval: { - setup: function () { - return self._i; - }, - changes: function (prev) { - return !sameDuration(prev, this._i); - } + changes: function (prev) { + return !sameDuration(prev, this._i); } - }; - - function cachedGetter(prop) { - return { - value: function cachedGetter() { - if (cache.hasOwnProperty(prop)) { - return cache[prop]; - } + } + }; - return cache[prop] = self[prop](); + function cachedGetter(prop) { + return { + value: function cachedGetter() { + if (cache.hasOwnProperty(prop)) { + return cache[prop]; } - }; - } - function cacheBreaker(prop) { - const resource = resources[breakers[prop]]; - const setup = resource.setup; - const changes = resource.changes; - const fn = self[prop]; + return cache[prop] = self[prop](); + } + }; + } - return { - value: function cacheBreaker() { - const prev = setup.call(self); - const ret = fn.apply(self, arguments); + function cacheBreaker(prop) { + const resource = resources[breakers[prop]]; + const setup = resource.setup; + const changes = resource.changes; + const fn = self[prop]; - if (changes.call(self, prev)) { - cache = {}; - } + return { + value: function cacheBreaker() { + const prev = setup.call(self); + const ret = fn.apply(self, arguments); - return ret; + if (changes.call(self, prev)) { + cache = {}; } - }; - } - function same(checkType) { - return function (a, b) { - if (a === b) return true; - if (checkType(a) === checkType(b)) return +a === +b; - return false; - }; - } + return ret; + } + }; + } + function same(checkType) { + return function (a, b) { + if (a === b) return true; + if (checkType(a) === checkType(b)) return +a === +b; + return false; + }; + } - _.forOwn(TimeBuckets.prototype, function (fn, prop) { - if (prop[0] === '_') return; - if (breakers.hasOwnProperty(prop)) { - desc[prop] = cacheBreaker(prop); - } else { - desc[prop] = cachedGetter(prop); - } - }); + _.forOwn(TimeBuckets.prototype, function (fn, prop) { + if (prop[0] === '_') return; - return Object.create(self, desc); - }; + if (breakers.hasOwnProperty(prop)) { + desc[prop] = cacheBreaker(prop); + } else { + desc[prop] = cachedGetter(prop); + } + }); - return TimeBuckets; -} + return Object.create(self, desc); +}; +export { TimeBuckets }; diff --git a/src/ui/public/vis/__tests__/_agg_config.js b/src/ui/public/vis/__tests__/_agg_config.js index 900c1484131a0..5a5460bdff651 100644 --- a/src/ui/public/vis/__tests__/_agg_config.js +++ b/src/ui/public/vis/__tests__/_agg_config.js @@ -2,7 +2,7 @@ import sinon from 'sinon'; import expect from 'expect.js'; import ngMock from 'ng_mock'; import { VisProvider } from '..'; -import { AggTypesAggTypeProvider } from '../../agg_types/agg_type'; +import { AggType } from '../../agg_types/agg_type'; import { AggConfig } from '../agg_config'; import FixturesStubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern'; import { fieldFormats } from '../../registry/field_formats'; @@ -10,13 +10,11 @@ import { fieldFormats } from '../../registry/field_formats'; describe('AggConfig', function () { let Vis; - let AggType; let indexPattern; beforeEach(ngMock.module('kibana')); beforeEach(ngMock.inject(function (Private) { Vis = Private(VisProvider); - AggType = Private(AggTypesAggTypeProvider); indexPattern = Private(FixturesStubbedLogstashIndexPatternProvider); })); diff --git a/src/ui/public/vis/agg_configs.js b/src/ui/public/vis/agg_configs.js index 77147625b552a..b4f2b795d9ea5 100644 --- a/src/ui/public/vis/agg_configs.js +++ b/src/ui/public/vis/agg_configs.js @@ -10,11 +10,11 @@ import _ from 'lodash'; import { IndexedArray } from '../indexed_array'; import { AggConfig } from './agg_config'; -import { AggTypesIndexProvider } from '../agg_types'; +import { aggTypes } from '../agg_types'; import { createLegacyClass } from '../utils/legacy_class'; -export function VisAggConfigsProvider(Private) { - AggConfig.aggTypes = Private(AggTypesIndexProvider); +export function VisAggConfigsProvider() { + AggConfig.aggTypes = aggTypes; createLegacyClass(AggConfigs).inherits(IndexedArray); function AggConfigs(vis, configStates) { diff --git a/src/ui/public/vis/editors/default/agg_params.js b/src/ui/public/vis/editors/default/agg_params.js index c296a0f57820f..643158d307a51 100644 --- a/src/ui/public/vis/editors/default/agg_params.js +++ b/src/ui/public/vis/editors/default/agg_params.js @@ -4,15 +4,14 @@ import aggSelectHtml from './agg_select.html'; import advancedToggleHtml from './advanced_toggle.html'; import '../../../filters/match_any'; import './agg_param'; -import { AggTypesIndexProvider } from '../../../agg_types'; +import { aggTypes } from '../../../agg_types'; import { uiModules } from '../../../modules'; import { documentationLinks } from '../../../documentation_links/documentation_links'; import aggParamsTemplate from './agg_params.html'; uiModules .get('app/visualize') - .directive('visEditorAggParams', function ($compile, $parse, Private) { - const aggTypes = Private(AggTypesIndexProvider); + .directive('visEditorAggParams', function ($compile) { return { restrict: 'E',