mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 17:59:23 -04:00
[data.search.aggs] Remove service getters from agg types (#61069)
* [data.search.aggs] Remove service getters from agg types Part of #60333 * fix JEST * fix karma:unit * fix PR commnets * fix PR comments * try to fix ci * fix CI * fix karma:unit Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>
This commit is contained in:
parent
55ed873f32
commit
37c4fd4b71
22 changed files with 713 additions and 627 deletions
|
@ -33,7 +33,11 @@ class ReactVisController {
|
|||
|
||||
const I18nContext = getI18n().Context;
|
||||
|
||||
return new Promise(resolve => {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (!this.vis.type || !this.vis.type.visConfig || !this.vis.type.visConfig.component) {
|
||||
reject('Missing component for ReactVisType');
|
||||
}
|
||||
|
||||
const Component = this.vis.type.visConfig.component;
|
||||
const config = getUISettings();
|
||||
render(
|
||||
|
|
|
@ -57,6 +57,10 @@ const mockComponent = () => {
|
|||
return null;
|
||||
};
|
||||
|
||||
let refreshInterval = undefined;
|
||||
let isTimeRangeSelectorEnabled = true;
|
||||
let isAutoRefreshSelectorEnabled = true;
|
||||
|
||||
export const mockUiSettings = {
|
||||
get: item => {
|
||||
return mockUiSettings[item];
|
||||
|
@ -64,6 +68,7 @@ export const mockUiSettings = {
|
|||
getUpdate$: () => ({
|
||||
subscribe: sinon.fake(),
|
||||
}),
|
||||
isDefault: sinon.fake(),
|
||||
'query:allowLeadingWildcards': true,
|
||||
'query:queryString:options': {},
|
||||
'courier:ignoreFilterIfFieldNotInIndex': true,
|
||||
|
@ -81,10 +86,77 @@ const mockCore = {
|
|||
},
|
||||
};
|
||||
|
||||
const querySetup = {
|
||||
state$: mockObservable(),
|
||||
filterManager: {
|
||||
getFetches$: sinon.fake(),
|
||||
getFilters: sinon.fake(),
|
||||
getAppFilters: sinon.fake(),
|
||||
getGlobalFilters: sinon.fake(),
|
||||
removeFilter: sinon.fake(),
|
||||
addFilters: sinon.fake(),
|
||||
setFilters: sinon.fake(),
|
||||
removeAll: sinon.fake(),
|
||||
getUpdates$: mockObservable,
|
||||
},
|
||||
timefilter: {
|
||||
timefilter: {
|
||||
getFetch$: mockObservable,
|
||||
getAutoRefreshFetch$: mockObservable,
|
||||
getEnabledUpdated$: mockObservable,
|
||||
getTimeUpdate$: mockObservable,
|
||||
getRefreshIntervalUpdate$: mockObservable,
|
||||
isTimeRangeSelectorEnabled: () => {
|
||||
return isTimeRangeSelectorEnabled;
|
||||
},
|
||||
isAutoRefreshSelectorEnabled: () => {
|
||||
return isAutoRefreshSelectorEnabled;
|
||||
},
|
||||
disableAutoRefreshSelector: () => {
|
||||
isAutoRefreshSelectorEnabled = false;
|
||||
},
|
||||
enableAutoRefreshSelector: () => {
|
||||
isAutoRefreshSelectorEnabled = true;
|
||||
},
|
||||
getRefreshInterval: () => {
|
||||
return refreshInterval;
|
||||
},
|
||||
setRefreshInterval: interval => {
|
||||
refreshInterval = interval;
|
||||
},
|
||||
enableTimeRangeSelector: () => {
|
||||
isTimeRangeSelectorEnabled = true;
|
||||
},
|
||||
disableTimeRangeSelector: () => {
|
||||
isTimeRangeSelectorEnabled = false;
|
||||
},
|
||||
getTime: sinon.fake(),
|
||||
setTime: sinon.fake(),
|
||||
getActiveBounds: sinon.fake(),
|
||||
getBounds: sinon.fake(),
|
||||
calculateBounds: sinon.fake(),
|
||||
createFilter: sinon.fake(),
|
||||
},
|
||||
history: sinon.fake(),
|
||||
},
|
||||
savedQueries: {
|
||||
saveQuery: sinon.fake(),
|
||||
getAllSavedQueries: sinon.fake(),
|
||||
findSavedQueries: sinon.fake(),
|
||||
getSavedQuery: sinon.fake(),
|
||||
deleteSavedQuery: sinon.fake(),
|
||||
getSavedQueryCount: sinon.fake(),
|
||||
},
|
||||
};
|
||||
|
||||
const mockAggTypesRegistry = () => {
|
||||
const registry = new AggTypesRegistry();
|
||||
const registrySetup = registry.setup();
|
||||
const aggTypes = getAggTypes({ uiSettings: mockCore.uiSettings });
|
||||
const aggTypes = getAggTypes({
|
||||
uiSettings: mockCore.uiSettings,
|
||||
notifications: mockCore.notifications,
|
||||
query: querySetup,
|
||||
});
|
||||
aggTypes.buckets.forEach(type => registrySetup.registerBucket(type));
|
||||
aggTypes.metrics.forEach(type => registrySetup.registerMetric(type));
|
||||
|
||||
|
@ -93,10 +165,6 @@ const mockAggTypesRegistry = () => {
|
|||
|
||||
const aggTypesRegistry = mockAggTypesRegistry();
|
||||
|
||||
let refreshInterval = undefined;
|
||||
let isTimeRangeSelectorEnabled = true;
|
||||
let isAutoRefreshSelectorEnabled = true;
|
||||
|
||||
export const npSetup = {
|
||||
core: mockCore,
|
||||
plugins: {
|
||||
|
@ -135,72 +203,7 @@ export const npSetup = {
|
|||
addProvider: sinon.fake(),
|
||||
getProvider: sinon.fake(),
|
||||
},
|
||||
query: {
|
||||
state$: mockObservable(),
|
||||
filterManager: {
|
||||
getFetches$: sinon.fake(),
|
||||
getFilters: sinon.fake(),
|
||||
getAppFilters: sinon.fake(),
|
||||
getGlobalFilters: sinon.fake(),
|
||||
removeFilter: sinon.fake(),
|
||||
addFilters: sinon.fake(),
|
||||
setFilters: sinon.fake(),
|
||||
removeAll: sinon.fake(),
|
||||
getUpdates$: mockObservable,
|
||||
},
|
||||
timefilter: {
|
||||
timefilter: {
|
||||
getTime: sinon.fake(),
|
||||
getRefreshInterval: sinon.fake(),
|
||||
getTimeUpdate$: mockObservable,
|
||||
getRefreshIntervalUpdate$: mockObservable,
|
||||
getFetch$: mockObservable,
|
||||
getAutoRefreshFetch$: mockObservable,
|
||||
getEnabledUpdated$: mockObservable,
|
||||
getTimeUpdate$: mockObservable,
|
||||
getRefreshIntervalUpdate$: mockObservable,
|
||||
isTimeRangeSelectorEnabled: () => {
|
||||
return isTimeRangeSelectorEnabled;
|
||||
},
|
||||
isAutoRefreshSelectorEnabled: () => {
|
||||
return isAutoRefreshSelectorEnabled;
|
||||
},
|
||||
disableAutoRefreshSelector: () => {
|
||||
isAutoRefreshSelectorEnabled = false;
|
||||
},
|
||||
enableAutoRefreshSelector: () => {
|
||||
isAutoRefreshSelectorEnabled = true;
|
||||
},
|
||||
getRefreshInterval: () => {
|
||||
return refreshInterval;
|
||||
},
|
||||
setRefreshInterval: interval => {
|
||||
refreshInterval = interval;
|
||||
},
|
||||
enableTimeRangeSelector: () => {
|
||||
isTimeRangeSelectorEnabled = true;
|
||||
},
|
||||
disableTimeRangeSelector: () => {
|
||||
isTimeRangeSelectorEnabled = false;
|
||||
},
|
||||
getTime: sinon.fake(),
|
||||
setTime: sinon.fake(),
|
||||
getActiveBounds: sinon.fake(),
|
||||
getBounds: sinon.fake(),
|
||||
calculateBounds: sinon.fake(),
|
||||
createFilter: sinon.fake(),
|
||||
},
|
||||
history: sinon.fake(),
|
||||
},
|
||||
savedQueries: {
|
||||
saveQuery: sinon.fake(),
|
||||
getAllSavedQueries: sinon.fake(),
|
||||
findSavedQueries: sinon.fake(),
|
||||
getSavedQuery: sinon.fake(),
|
||||
deleteSavedQuery: sinon.fake(),
|
||||
getSavedQueryCount: sinon.fake(),
|
||||
},
|
||||
},
|
||||
query: querySetup,
|
||||
search: {
|
||||
aggs: {
|
||||
calculateAutoTimeExpression: sinon.fake(),
|
||||
|
@ -410,7 +413,6 @@ export const npStart = {
|
|||
search: {
|
||||
aggs: {
|
||||
calculateAutoTimeExpression: sinon.fake(),
|
||||
createAggConfigs: sinon.fake(),
|
||||
createAggConfigs: (indexPattern, configStates = []) => {
|
||||
return new AggConfigs(indexPattern, configStates, {
|
||||
typesRegistry: aggTypesRegistry.start(),
|
||||
|
|
|
@ -121,7 +121,10 @@ export class DataPublicPlugin implements Plugin<DataPublicPluginSetup, DataPubli
|
|||
|
||||
return {
|
||||
autocomplete: this.autocomplete.setup(core),
|
||||
search: this.searchService.setup(core, this.packageInfo),
|
||||
search: this.searchService.setup(core, {
|
||||
packageInfo: this.packageInfo,
|
||||
query: queryService,
|
||||
}),
|
||||
fieldFormats: this.fieldFormatsService.setup(core),
|
||||
query: queryService,
|
||||
};
|
||||
|
|
|
@ -17,7 +17,8 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
import { IUiSettingsClient } from 'src/core/public';
|
||||
import { IUiSettingsClient, NotificationsSetup } from 'src/core/public';
|
||||
import { QuerySetup } from '../../query/query_service';
|
||||
|
||||
import { countMetricAgg } from './metrics/count';
|
||||
import { avgMetricAgg } from './metrics/avg';
|
||||
|
@ -36,10 +37,10 @@ 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 { getDateHistogramBucketAgg } from './buckets/date_histogram';
|
||||
import { getHistogramBucketAgg } from './buckets/histogram';
|
||||
import { rangeBucketAgg } from './buckets/range';
|
||||
import { dateRangeBucketAgg } from './buckets/date_range';
|
||||
import { getDateRangeBucketAgg } from './buckets/date_range';
|
||||
import { ipRangeBucketAgg } from './buckets/ip_range';
|
||||
import { termsBucketAgg } from './buckets/terms';
|
||||
import { filterBucketAgg } from './buckets/filter';
|
||||
|
@ -52,44 +53,47 @@ import { bucketAvgMetricAgg } from './metrics/bucket_avg';
|
|||
import { bucketMinMetricAgg } from './metrics/bucket_min';
|
||||
import { bucketMaxMetricAgg } from './metrics/bucket_max';
|
||||
|
||||
export function getAggTypes(deps: { uiSettings: IUiSettingsClient }) {
|
||||
const { uiSettings } = deps;
|
||||
return {
|
||||
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,
|
||||
getFiltersBucketAgg({ uiSettings }),
|
||||
significantTermsBucketAgg,
|
||||
geoHashBucketAgg,
|
||||
geoTileBucketAgg,
|
||||
],
|
||||
};
|
||||
export interface AggTypesDependencies {
|
||||
notifications: NotificationsSetup;
|
||||
uiSettings: IUiSettingsClient;
|
||||
query: QuerySetup;
|
||||
}
|
||||
|
||||
export const getAggTypes = ({ notifications, uiSettings, query }: AggTypesDependencies) => ({
|
||||
metrics: [
|
||||
countMetricAgg,
|
||||
avgMetricAgg,
|
||||
sumMetricAgg,
|
||||
medianMetricAgg,
|
||||
minMetricAgg,
|
||||
maxMetricAgg,
|
||||
stdDeviationMetricAgg,
|
||||
cardinalityMetricAgg,
|
||||
percentilesMetricAgg,
|
||||
percentileRanksMetricAgg,
|
||||
topHitMetricAgg,
|
||||
derivativeMetricAgg,
|
||||
cumulativeSumMetricAgg,
|
||||
movingAvgMetricAgg,
|
||||
serialDiffMetricAgg,
|
||||
bucketAvgMetricAgg,
|
||||
bucketSumMetricAgg,
|
||||
bucketMinMetricAgg,
|
||||
bucketMaxMetricAgg,
|
||||
geoBoundsMetricAgg,
|
||||
geoCentroidMetricAgg,
|
||||
],
|
||||
buckets: [
|
||||
getDateHistogramBucketAgg({ uiSettings, query }),
|
||||
getHistogramBucketAgg({ uiSettings, notifications }),
|
||||
rangeBucketAgg,
|
||||
getDateRangeBucketAgg({ uiSettings }),
|
||||
ipRangeBucketAgg,
|
||||
termsBucketAgg,
|
||||
filterBucketAgg,
|
||||
getFiltersBucketAgg({ uiSettings }),
|
||||
significantTermsBucketAgg,
|
||||
geoHashBucketAgg,
|
||||
geoTileBucketAgg,
|
||||
],
|
||||
});
|
||||
|
|
|
@ -22,23 +22,35 @@ import { createFilterDateHistogram } from './date_histogram';
|
|||
import { intervalOptions } from '../_interval_options';
|
||||
import { AggConfigs } from '../../agg_configs';
|
||||
import { mockDataServices, mockAggTypesRegistry } from '../../test_helpers';
|
||||
import { dateHistogramBucketAgg, IBucketDateHistogramAggConfig } from '../date_histogram';
|
||||
import {
|
||||
getDateHistogramBucketAgg,
|
||||
DateHistogramBucketAggDependencies,
|
||||
IBucketDateHistogramAggConfig,
|
||||
} from '../date_histogram';
|
||||
import { BUCKET_TYPES } from '../bucket_agg_types';
|
||||
import { RangeFilter } from '../../../../../common';
|
||||
import { coreMock } from '../../../../../../../core/public/mocks';
|
||||
import { queryServiceMock } from '../../../../query/mocks';
|
||||
|
||||
describe('AggConfig Filters', () => {
|
||||
describe('date_histogram', () => {
|
||||
beforeEach(() => {
|
||||
mockDataServices();
|
||||
});
|
||||
|
||||
const typesRegistry = mockAggTypesRegistry([dateHistogramBucketAgg]);
|
||||
|
||||
let aggTypesDependencies: DateHistogramBucketAggDependencies;
|
||||
let agg: IBucketDateHistogramAggConfig;
|
||||
let filter: RangeFilter;
|
||||
let bucketStart: any;
|
||||
let field: any;
|
||||
|
||||
beforeEach(() => {
|
||||
const { uiSettings } = coreMock.createSetup();
|
||||
|
||||
aggTypesDependencies = {
|
||||
uiSettings,
|
||||
query: queryServiceMock.createSetupContract(),
|
||||
};
|
||||
|
||||
mockDataServices();
|
||||
});
|
||||
|
||||
const init = (interval: string = 'auto', duration: any = moment.duration(15, 'minutes')) => {
|
||||
field = {
|
||||
name: 'date',
|
||||
|
@ -61,7 +73,7 @@ describe('AggConfig Filters', () => {
|
|||
params: { field: field.name, interval, customInterval: '5d' },
|
||||
},
|
||||
],
|
||||
{ typesRegistry }
|
||||
{ typesRegistry: mockAggTypesRegistry([getDateHistogramBucketAgg(aggTypesDependencies)]) }
|
||||
);
|
||||
const bucketKey = 1422579600000;
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
*/
|
||||
|
||||
import moment from 'moment';
|
||||
import { dateRangeBucketAgg } from '../date_range';
|
||||
import { getDateRangeBucketAgg, DateRangeBucketAggDependencies } from '../date_range';
|
||||
import { createFilterDateRange } from './date_range';
|
||||
import { FieldFormatsGetConfigFn } from '../../../../../common';
|
||||
import { DateFormat } from '../../../../field_formats';
|
||||
|
@ -26,10 +26,20 @@ import { AggConfigs } from '../../agg_configs';
|
|||
import { mockAggTypesRegistry } from '../../test_helpers';
|
||||
import { BUCKET_TYPES } from '../bucket_agg_types';
|
||||
import { IBucketAggConfig } from '../_bucket_agg_type';
|
||||
import { coreMock } from '../../../../../../../core/public/mocks';
|
||||
|
||||
describe('AggConfig Filters', () => {
|
||||
describe('Date range', () => {
|
||||
const typesRegistry = mockAggTypesRegistry([dateRangeBucketAgg]);
|
||||
let aggTypesDependencies: DateRangeBucketAggDependencies;
|
||||
|
||||
beforeEach(() => {
|
||||
const { uiSettings } = coreMock.createSetup();
|
||||
|
||||
aggTypesDependencies = {
|
||||
uiSettings,
|
||||
};
|
||||
});
|
||||
|
||||
const getConfig = (() => {}) as FieldFormatsGetConfigFn;
|
||||
const getAggConfigs = () => {
|
||||
const field = {
|
||||
|
@ -57,7 +67,7 @@ describe('AggConfig Filters', () => {
|
|||
},
|
||||
},
|
||||
],
|
||||
{ typesRegistry }
|
||||
{ typesRegistry: mockAggTypesRegistry([getDateRangeBucketAgg(aggTypesDependencies)]) }
|
||||
);
|
||||
};
|
||||
|
||||
|
|
|
@ -17,25 +17,24 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
|
||||
import { coreMock } from '../../../../../../../../src/core/public/mocks';
|
||||
import { getFiltersBucketAgg } from '../filters';
|
||||
import { getFiltersBucketAgg, FiltersBucketAggDependencies } from '../filters';
|
||||
import { createFilterFilters } from './filters';
|
||||
import { AggConfigs } from '../../agg_configs';
|
||||
import { mockDataServices, mockAggTypesRegistry } from '../../test_helpers';
|
||||
import { mockAggTypesRegistry } from '../../test_helpers';
|
||||
import { IBucketAggConfig } from '../_bucket_agg_type';
|
||||
import { coreMock } from '../../../../../../../core/public/mocks';
|
||||
|
||||
describe('AggConfig Filters', () => {
|
||||
describe('filters', () => {
|
||||
beforeEach(() => {
|
||||
mockDataServices();
|
||||
});
|
||||
let aggTypesDependencies: FiltersBucketAggDependencies;
|
||||
|
||||
const typesRegistry = mockAggTypesRegistry([
|
||||
getFiltersBucketAgg({
|
||||
uiSettings: coreMock.createSetup().uiSettings,
|
||||
}),
|
||||
]);
|
||||
beforeEach(() => {
|
||||
const { uiSettings } = coreMock.createSetup();
|
||||
|
||||
aggTypesDependencies = {
|
||||
uiSettings,
|
||||
};
|
||||
});
|
||||
|
||||
const getAggConfigs = () => {
|
||||
const field = {
|
||||
|
@ -65,7 +64,7 @@ describe('AggConfig Filters', () => {
|
|||
},
|
||||
},
|
||||
],
|
||||
{ typesRegistry }
|
||||
{ typesRegistry: mockAggTypesRegistry([getFiltersBucketAgg(aggTypesDependencies)]) }
|
||||
);
|
||||
};
|
||||
it('should return a filters filter', () => {
|
||||
|
|
|
@ -17,9 +17,10 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
import _ from 'lodash';
|
||||
import { get, noop, find, every } from 'lodash';
|
||||
import moment from 'moment-timezone';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { IUiSettingsClient } from 'src/core/public';
|
||||
|
||||
import { TimeBuckets } from './lib/time_buckets';
|
||||
import { BucketAggType, IBucketAggConfig } from './_bucket_agg_type';
|
||||
|
@ -32,7 +33,8 @@ import { isMetricAggType } from '../metrics/metric_agg_type';
|
|||
|
||||
import { FIELD_FORMAT_IDS, KBN_FIELD_TYPES } from '../../../../common';
|
||||
import { TimefilterContract } from '../../../query';
|
||||
import { getFieldFormats, getQueryService, getUiSettings } from '../../../../public/services';
|
||||
import { getFieldFormats } from '../../../../public/services';
|
||||
import { QuerySetup } from '../../../query/query_service';
|
||||
|
||||
const detectedTimezone = moment.tz.guess();
|
||||
const tzOffset = moment().format('Z');
|
||||
|
@ -56,6 +58,11 @@ interface ITimeBuckets {
|
|||
getInterval: Function;
|
||||
}
|
||||
|
||||
export interface DateHistogramBucketAggDependencies {
|
||||
uiSettings: IUiSettingsClient;
|
||||
query: QuerySetup;
|
||||
}
|
||||
|
||||
export interface IBucketDateHistogramAggConfig extends IBucketAggConfig {
|
||||
buckets: ITimeBuckets;
|
||||
}
|
||||
|
@ -64,212 +71,214 @@ export function isDateHistogramBucketAggConfig(agg: any): agg is IBucketDateHist
|
|||
return Boolean(agg.buckets);
|
||||
}
|
||||
|
||||
export const dateHistogramBucketAgg = new BucketAggType<IBucketDateHistogramAggConfig>({
|
||||
name: BUCKET_TYPES.DATE_HISTOGRAM,
|
||||
title: i18n.translate('data.search.aggs.buckets.dateHistogramTitle', {
|
||||
defaultMessage: 'Date Histogram',
|
||||
}),
|
||||
ordered: {
|
||||
date: true,
|
||||
},
|
||||
makeLabel(agg) {
|
||||
let output: Record<string, any> = {};
|
||||
export const getDateHistogramBucketAgg = ({
|
||||
uiSettings,
|
||||
query,
|
||||
}: DateHistogramBucketAggDependencies) =>
|
||||
new BucketAggType<IBucketDateHistogramAggConfig>({
|
||||
name: BUCKET_TYPES.DATE_HISTOGRAM,
|
||||
title: i18n.translate('data.search.aggs.buckets.dateHistogramTitle', {
|
||||
defaultMessage: 'Date Histogram',
|
||||
}),
|
||||
ordered: {
|
||||
date: true,
|
||||
},
|
||||
makeLabel(agg) {
|
||||
let output: Record<string, any> = {};
|
||||
|
||||
if (this.params) {
|
||||
output = writeParams(this.params, agg);
|
||||
}
|
||||
if (this.params) {
|
||||
output = writeParams(this.params, agg);
|
||||
}
|
||||
|
||||
const field = agg.getFieldDisplayName();
|
||||
return i18n.translate('data.search.aggs.buckets.dateHistogramLabel', {
|
||||
defaultMessage: '{fieldName} per {intervalDescription}',
|
||||
values: {
|
||||
fieldName: field,
|
||||
intervalDescription: output.metricScaleText || output.bucketInterval.description,
|
||||
},
|
||||
});
|
||||
},
|
||||
createFilter: createFilterDateHistogram,
|
||||
decorateAggConfig() {
|
||||
const uiSettings = getUiSettings();
|
||||
let buckets: any;
|
||||
|
||||
return {
|
||||
buckets: {
|
||||
configurable: true,
|
||||
get() {
|
||||
if (buckets) return buckets;
|
||||
|
||||
const { timefilter } = getQueryService().timefilter;
|
||||
buckets = new TimeBuckets({ uiSettings });
|
||||
updateTimeBuckets(this, timefilter, buckets);
|
||||
|
||||
return buckets;
|
||||
const field = agg.getFieldDisplayName();
|
||||
return i18n.translate('data.search.aggs.buckets.dateHistogramLabel', {
|
||||
defaultMessage: '{fieldName} per {intervalDescription}',
|
||||
values: {
|
||||
fieldName: field,
|
||||
intervalDescription: output.metricScaleText || output.bucketInterval.description,
|
||||
},
|
||||
} as any,
|
||||
};
|
||||
},
|
||||
getFormat(agg) {
|
||||
const DateFieldFormat = getFieldFormats().getType(FIELD_FORMAT_IDS.DATE);
|
||||
});
|
||||
},
|
||||
createFilter: createFilterDateHistogram,
|
||||
decorateAggConfig() {
|
||||
let buckets: any;
|
||||
|
||||
if (!DateFieldFormat) {
|
||||
throw new Error('Unable to retrieve Date Field Format');
|
||||
}
|
||||
return {
|
||||
buckets: {
|
||||
configurable: true,
|
||||
get() {
|
||||
if (buckets) return buckets;
|
||||
|
||||
return new DateFieldFormat(
|
||||
const { timefilter } = query.timefilter;
|
||||
buckets = new TimeBuckets({ uiSettings });
|
||||
updateTimeBuckets(this, timefilter, buckets);
|
||||
|
||||
return buckets;
|
||||
},
|
||||
} as any,
|
||||
};
|
||||
},
|
||||
getFormat(agg) {
|
||||
const DateFieldFormat = getFieldFormats().getType(FIELD_FORMAT_IDS.DATE);
|
||||
|
||||
if (!DateFieldFormat) {
|
||||
throw new Error('Unable to retrieve Date Field Format');
|
||||
}
|
||||
|
||||
return new DateFieldFormat(
|
||||
{
|
||||
pattern: agg.buckets.getScaledDateFormat(),
|
||||
},
|
||||
(key: string) => uiSettings.get(key)
|
||||
);
|
||||
},
|
||||
params: [
|
||||
{
|
||||
pattern: agg.buckets.getScaledDateFormat(),
|
||||
},
|
||||
(key: string) => getUiSettings().get(key)
|
||||
);
|
||||
},
|
||||
params: [
|
||||
{
|
||||
name: 'field',
|
||||
type: 'field',
|
||||
filterFieldTypes: KBN_FIELD_TYPES.DATE,
|
||||
default(agg: IBucketDateHistogramAggConfig) {
|
||||
return agg.getIndexPattern().timeFieldName;
|
||||
},
|
||||
onChange(agg: IBucketDateHistogramAggConfig) {
|
||||
if (_.get(agg, 'params.interval') === 'auto' && !agg.fieldIsTimeField()) {
|
||||
delete agg.params.interval;
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'timeRange',
|
||||
default: null,
|
||||
write: _.noop,
|
||||
},
|
||||
{
|
||||
name: 'useNormalizedEsInterval',
|
||||
default: true,
|
||||
write: _.noop,
|
||||
},
|
||||
{
|
||||
name: 'scaleMetricValues',
|
||||
default: false,
|
||||
write: _.noop,
|
||||
advanced: true,
|
||||
},
|
||||
{
|
||||
name: 'interval',
|
||||
deserialize(state: any, agg) {
|
||||
// For upgrading from 7.0.x to 7.1.x - intervals are now stored as key of options or custom value
|
||||
if (state === 'custom') {
|
||||
return _.get(agg, 'params.customInterval');
|
||||
}
|
||||
|
||||
const interval = _.find(intervalOptions, { val: state });
|
||||
|
||||
// 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
|
||||
if (!interval && state === 'year') {
|
||||
return 'y';
|
||||
}
|
||||
return state;
|
||||
},
|
||||
default: 'auto',
|
||||
options: intervalOptions,
|
||||
write(agg, output, aggs) {
|
||||
const { timefilter } = getQueryService().timefilter;
|
||||
updateTimeBuckets(agg, timefilter);
|
||||
|
||||
const { useNormalizedEsInterval, scaleMetricValues } = agg.params;
|
||||
const interval = agg.buckets.getInterval(useNormalizedEsInterval);
|
||||
output.bucketInterval = interval;
|
||||
if (interval.expression === '0ms') {
|
||||
// We are hitting this code a couple of times while configuring in editor
|
||||
// with an interval of 0ms because the overall time range has not yet been
|
||||
// set. Since 0ms is not a valid ES interval, we cannot pass it through dateHistogramInterval
|
||||
// below, since it would throw an exception. So in the cases we still have an interval of 0ms
|
||||
// here we simply skip the rest of the method and never write an interval into the DSL, since
|
||||
// this DSL will anyway not be used before we're passing this code with an actual interval.
|
||||
return;
|
||||
}
|
||||
output.params = {
|
||||
...output.params,
|
||||
...dateHistogramInterval(interval.expression),
|
||||
};
|
||||
|
||||
const scaleMetrics = scaleMetricValues && interval.scaled && interval.scale < 1;
|
||||
if (scaleMetrics && aggs) {
|
||||
const metrics = aggs.aggs.filter(a => isMetricAggType(a.type));
|
||||
const all = _.every(metrics, (a: IBucketAggConfig) => {
|
||||
const { type } = a;
|
||||
|
||||
if (isMetricAggType(type)) {
|
||||
return type.isScalable();
|
||||
}
|
||||
});
|
||||
if (all) {
|
||||
output.metricScale = interval.scale;
|
||||
output.metricScaleText = interval.preScaled.description;
|
||||
name: 'field',
|
||||
type: 'field',
|
||||
filterFieldTypes: KBN_FIELD_TYPES.DATE,
|
||||
default(agg: IBucketDateHistogramAggConfig) {
|
||||
return agg.getIndexPattern().timeFieldName;
|
||||
},
|
||||
onChange(agg: IBucketDateHistogramAggConfig) {
|
||||
if (get(agg, 'params.interval') === 'auto' && !agg.fieldIsTimeField()) {
|
||||
delete agg.params.interval;
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'time_zone',
|
||||
default: undefined,
|
||||
// We don't ever want this parameter to be serialized out (when saving or to URLs)
|
||||
// since we do all the logic handling it "on the fly" in the `write` method, to prevent
|
||||
// time_zones being persisted into saved_objects
|
||||
serialize: _.noop,
|
||||
write(agg, output) {
|
||||
// If a time_zone has been set explicitly always prefer this.
|
||||
let tz = agg.params.time_zone;
|
||||
if (!tz && agg.params.field) {
|
||||
// If a field has been configured check the index pattern's typeMeta if a date_histogram on that
|
||||
// field requires a specific time_zone
|
||||
tz = _.get(agg.getIndexPattern(), [
|
||||
'typeMeta',
|
||||
'aggs',
|
||||
'date_histogram',
|
||||
agg.params.field.name,
|
||||
'time_zone',
|
||||
]);
|
||||
}
|
||||
if (!tz) {
|
||||
const config = getUiSettings();
|
||||
// If the index pattern typeMeta data, didn't had a time zone assigned for the selected field use the configured tz
|
||||
const isDefaultTimezone = config.isDefault('dateFormat:tz');
|
||||
tz = isDefaultTimezone ? detectedTimezone || tzOffset : config.get('dateFormat:tz');
|
||||
}
|
||||
output.params.time_zone = tz;
|
||||
{
|
||||
name: 'timeRange',
|
||||
default: null,
|
||||
write: noop,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'drop_partials',
|
||||
default: false,
|
||||
write: _.noop,
|
||||
shouldShow: agg => {
|
||||
const field = agg.params.field;
|
||||
return field && field.name && field.name === agg.getIndexPattern().timeFieldName;
|
||||
{
|
||||
name: 'useNormalizedEsInterval',
|
||||
default: true,
|
||||
write: noop,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'format',
|
||||
},
|
||||
{
|
||||
name: 'min_doc_count',
|
||||
default: 1,
|
||||
},
|
||||
{
|
||||
name: 'extended_bounds',
|
||||
default: {},
|
||||
write(agg, output) {
|
||||
const val = agg.params.extended_bounds;
|
||||
{
|
||||
name: 'scaleMetricValues',
|
||||
default: false,
|
||||
write: noop,
|
||||
advanced: true,
|
||||
},
|
||||
{
|
||||
name: 'interval',
|
||||
deserialize(state: any, agg) {
|
||||
// For upgrading from 7.0.x to 7.1.x - intervals are now stored as key of options or custom value
|
||||
if (state === 'custom') {
|
||||
return get(agg, 'params.customInterval');
|
||||
}
|
||||
|
||||
if (val.min != null || val.max != null) {
|
||||
output.params.extended_bounds = {
|
||||
min: moment(val.min).valueOf(),
|
||||
max: moment(val.max).valueOf(),
|
||||
const interval = find(intervalOptions, { val: state });
|
||||
|
||||
// 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
|
||||
if (!interval && state === 'year') {
|
||||
return 'y';
|
||||
}
|
||||
return state;
|
||||
},
|
||||
default: 'auto',
|
||||
options: intervalOptions,
|
||||
write(agg, output, aggs) {
|
||||
const { timefilter } = query.timefilter;
|
||||
updateTimeBuckets(agg, timefilter);
|
||||
|
||||
const { useNormalizedEsInterval, scaleMetricValues } = agg.params;
|
||||
const interval = agg.buckets.getInterval(useNormalizedEsInterval);
|
||||
output.bucketInterval = interval;
|
||||
if (interval.expression === '0ms') {
|
||||
// We are hitting this code a couple of times while configuring in editor
|
||||
// with an interval of 0ms because the overall time range has not yet been
|
||||
// set. Since 0ms is not a valid ES interval, we cannot pass it through dateHistogramInterval
|
||||
// below, since it would throw an exception. So in the cases we still have an interval of 0ms
|
||||
// here we simply skip the rest of the method and never write an interval into the DSL, since
|
||||
// this DSL will anyway not be used before we're passing this code with an actual interval.
|
||||
return;
|
||||
}
|
||||
output.params = {
|
||||
...output.params,
|
||||
...dateHistogramInterval(interval.expression),
|
||||
};
|
||||
|
||||
return;
|
||||
}
|
||||
const scaleMetrics = scaleMetricValues && interval.scaled && interval.scale < 1;
|
||||
if (scaleMetrics && aggs) {
|
||||
const metrics = aggs.aggs.filter(a => isMetricAggType(a.type));
|
||||
const all = every(metrics, (a: IBucketAggConfig) => {
|
||||
const { type } = a;
|
||||
|
||||
if (isMetricAggType(type)) {
|
||||
return type.isScalable();
|
||||
}
|
||||
});
|
||||
if (all) {
|
||||
output.metricScale = interval.scale;
|
||||
output.metricScaleText = interval.preScaled.description;
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
{
|
||||
name: 'time_zone',
|
||||
default: undefined,
|
||||
// We don't ever want this parameter to be serialized out (when saving or to URLs)
|
||||
// since we do all the logic handling it "on the fly" in the `write` method, to prevent
|
||||
// time_zones being persisted into saved_objects
|
||||
serialize: noop,
|
||||
write(agg, output) {
|
||||
// If a time_zone has been set explicitly always prefer this.
|
||||
let tz = agg.params.time_zone;
|
||||
if (!tz && agg.params.field) {
|
||||
// If a field has been configured check the index pattern's typeMeta if a date_histogram on that
|
||||
// field requires a specific time_zone
|
||||
tz = get(agg.getIndexPattern(), [
|
||||
'typeMeta',
|
||||
'aggs',
|
||||
'date_histogram',
|
||||
agg.params.field.name,
|
||||
'time_zone',
|
||||
]);
|
||||
}
|
||||
if (!tz) {
|
||||
// If the index pattern typeMeta data, didn't had a time zone assigned for the selected field use the configured tz
|
||||
const isDefaultTimezone = uiSettings.isDefault('dateFormat:tz');
|
||||
tz = isDefaultTimezone ? detectedTimezone || tzOffset : uiSettings.get('dateFormat:tz');
|
||||
}
|
||||
output.params.time_zone = tz;
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'drop_partials',
|
||||
default: false,
|
||||
write: noop,
|
||||
shouldShow: agg => {
|
||||
const field = agg.params.field;
|
||||
return field && field.name && field.name === agg.getIndexPattern().timeFieldName;
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'format',
|
||||
},
|
||||
{
|
||||
name: 'min_doc_count',
|
||||
default: 1,
|
||||
},
|
||||
{
|
||||
name: 'extended_bounds',
|
||||
default: {},
|
||||
write(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(),
|
||||
};
|
||||
|
||||
return;
|
||||
}
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
|
|
|
@ -17,20 +17,22 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
|
||||
import { coreMock } from '../../../../../../../src/core/public/mocks';
|
||||
import { setUiSettings } from '../../../../public/services';
|
||||
import { dateRangeBucketAgg } from './date_range';
|
||||
import { getDateRangeBucketAgg, DateRangeBucketAggDependencies } from './date_range';
|
||||
import { AggConfigs } from '../agg_configs';
|
||||
import { mockDataServices, mockAggTypesRegistry } from '../test_helpers';
|
||||
import { mockAggTypesRegistry } from '../test_helpers';
|
||||
import { BUCKET_TYPES } from './bucket_agg_types';
|
||||
|
||||
describe('date_range params', () => {
|
||||
beforeEach(() => {
|
||||
mockDataServices();
|
||||
});
|
||||
let aggTypesDependencies: DateRangeBucketAggDependencies;
|
||||
|
||||
const typesRegistry = mockAggTypesRegistry([dateRangeBucketAgg]);
|
||||
beforeEach(() => {
|
||||
const { uiSettings } = coreMock.createSetup();
|
||||
|
||||
aggTypesDependencies = {
|
||||
uiSettings,
|
||||
};
|
||||
});
|
||||
|
||||
const getAggConfigs = (params: Record<string, any> = {}, hasIncludeTypeMeta: boolean = true) => {
|
||||
const field = {
|
||||
|
@ -67,12 +69,12 @@ describe('date_range params', () => {
|
|||
params,
|
||||
},
|
||||
],
|
||||
{ typesRegistry }
|
||||
{ typesRegistry: mockAggTypesRegistry([getDateRangeBucketAgg(aggTypesDependencies)]) }
|
||||
);
|
||||
};
|
||||
|
||||
describe('getKey', () => {
|
||||
it('should return object', () => {
|
||||
test('should return object', () => {
|
||||
const aggConfigs = getAggConfigs();
|
||||
const dateRange = aggConfigs.aggs[0];
|
||||
const bucket = { from: 'from-date', to: 'to-date', key: 'from-dateto-date' };
|
||||
|
@ -82,7 +84,7 @@ describe('date_range params', () => {
|
|||
});
|
||||
|
||||
describe('time_zone', () => {
|
||||
it('should use the specified time_zone', () => {
|
||||
test('should use the specified time_zone', () => {
|
||||
const aggConfigs = getAggConfigs({
|
||||
time_zone: 'Europe/Minsk',
|
||||
field: 'bytes',
|
||||
|
@ -93,7 +95,7 @@ describe('date_range params', () => {
|
|||
expect(params.time_zone).toBe('Europe/Minsk');
|
||||
});
|
||||
|
||||
it('should use the fixed time_zone from the index pattern typeMeta', () => {
|
||||
test('should use the fixed time_zone from the index pattern typeMeta', () => {
|
||||
const aggConfigs = getAggConfigs({
|
||||
field: 'bytes',
|
||||
});
|
||||
|
@ -103,12 +105,14 @@ describe('date_range params', () => {
|
|||
expect(params.time_zone).toBe('defaultTimeZone');
|
||||
});
|
||||
|
||||
it('should use the Kibana time_zone if no parameter specified', () => {
|
||||
const core = coreMock.createStart();
|
||||
setUiSettings({
|
||||
...core.uiSettings,
|
||||
get: () => 'kibanaTimeZone' as any,
|
||||
});
|
||||
test('should use the Kibana time_zone if no parameter specified', () => {
|
||||
aggTypesDependencies = {
|
||||
...aggTypesDependencies,
|
||||
uiSettings: {
|
||||
...aggTypesDependencies.uiSettings,
|
||||
get: () => 'kibanaTimeZone' as any,
|
||||
},
|
||||
};
|
||||
|
||||
const aggConfigs = getAggConfigs(
|
||||
{
|
||||
|
@ -119,8 +123,6 @@ describe('date_range params', () => {
|
|||
const dateRange = aggConfigs.aggs[0];
|
||||
const params = dateRange.toDsl()[BUCKET_TYPES.DATE_RANGE];
|
||||
|
||||
setUiSettings(core.uiSettings); // clean up
|
||||
|
||||
expect(params.time_zone).toBe('kibanaTimeZone');
|
||||
});
|
||||
});
|
||||
|
|
|
@ -20,86 +20,92 @@
|
|||
import { get } from 'lodash';
|
||||
import moment from 'moment-timezone';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { IUiSettingsClient } from 'src/core/public';
|
||||
|
||||
import { BUCKET_TYPES } from './bucket_agg_types';
|
||||
import { BucketAggType, IBucketAggConfig } from './_bucket_agg_type';
|
||||
import { createFilterDateRange } from './create_filter/date_range';
|
||||
import { convertDateRangeToString, DateRangeKey } from './lib/date_range';
|
||||
|
||||
import { KBN_FIELD_TYPES, FieldFormat, TEXT_CONTEXT_TYPE } from '../../../../common';
|
||||
import { getFieldFormats, getUiSettings } from '../../../../public/services';
|
||||
import { getFieldFormats } from '../../../../public/services';
|
||||
|
||||
const dateRangeTitle = i18n.translate('data.search.aggs.buckets.dateRangeTitle', {
|
||||
defaultMessage: 'Date Range',
|
||||
});
|
||||
|
||||
export const dateRangeBucketAgg = new BucketAggType({
|
||||
name: BUCKET_TYPES.DATE_RANGE,
|
||||
title: dateRangeTitle,
|
||||
createFilter: createFilterDateRange,
|
||||
getKey({ from, to }): DateRangeKey {
|
||||
return { from, to };
|
||||
},
|
||||
getFormat(agg) {
|
||||
const fieldFormatsService = getFieldFormats();
|
||||
export interface DateRangeBucketAggDependencies {
|
||||
uiSettings: IUiSettingsClient;
|
||||
}
|
||||
|
||||
const formatter = agg.fieldOwnFormatter(
|
||||
TEXT_CONTEXT_TYPE,
|
||||
fieldFormatsService.getDefaultInstance(KBN_FIELD_TYPES.DATE)
|
||||
);
|
||||
const DateRangeFormat = FieldFormat.from(function(range: DateRangeKey) {
|
||||
return convertDateRangeToString(range, formatter);
|
||||
});
|
||||
return new DateRangeFormat();
|
||||
},
|
||||
makeLabel(aggConfig) {
|
||||
return aggConfig.getFieldDisplayName() + ' date ranges';
|
||||
},
|
||||
params: [
|
||||
{
|
||||
name: 'field',
|
||||
type: 'field',
|
||||
filterFieldTypes: KBN_FIELD_TYPES.DATE,
|
||||
default(agg: IBucketAggConfig) {
|
||||
return agg.getIndexPattern().timeFieldName;
|
||||
},
|
||||
export const getDateRangeBucketAgg = ({ uiSettings }: DateRangeBucketAggDependencies) =>
|
||||
new BucketAggType({
|
||||
name: BUCKET_TYPES.DATE_RANGE,
|
||||
title: dateRangeTitle,
|
||||
createFilter: createFilterDateRange,
|
||||
getKey({ from, to }): DateRangeKey {
|
||||
return { from, to };
|
||||
},
|
||||
{
|
||||
name: 'ranges',
|
||||
default: [
|
||||
{
|
||||
from: 'now-1w/w',
|
||||
to: 'now',
|
||||
getFormat(agg) {
|
||||
const fieldFormatsService = getFieldFormats();
|
||||
|
||||
const formatter = agg.fieldOwnFormatter(
|
||||
TEXT_CONTEXT_TYPE,
|
||||
fieldFormatsService.getDefaultInstance(KBN_FIELD_TYPES.DATE)
|
||||
);
|
||||
const DateRangeFormat = FieldFormat.from(function(range: DateRangeKey) {
|
||||
return convertDateRangeToString(range, formatter);
|
||||
});
|
||||
return new DateRangeFormat();
|
||||
},
|
||||
makeLabel(aggConfig) {
|
||||
return aggConfig.getFieldDisplayName() + ' date ranges';
|
||||
},
|
||||
params: [
|
||||
{
|
||||
name: 'field',
|
||||
type: 'field',
|
||||
filterFieldTypes: KBN_FIELD_TYPES.DATE,
|
||||
default(agg: IBucketAggConfig) {
|
||||
return agg.getIndexPattern().timeFieldName;
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'time_zone',
|
||||
default: undefined,
|
||||
// Implimentation method is the same as that of date_histogram
|
||||
serialize: () => undefined,
|
||||
write: (agg, output) => {
|
||||
const field = agg.getParam('field');
|
||||
let tz = agg.getParam('time_zone');
|
||||
|
||||
if (!tz && field) {
|
||||
tz = get(agg.getIndexPattern(), [
|
||||
'typeMeta',
|
||||
'aggs',
|
||||
'date_range',
|
||||
field.name,
|
||||
'time_zone',
|
||||
]);
|
||||
}
|
||||
if (!tz) {
|
||||
const config = getUiSettings();
|
||||
const detectedTimezone = moment.tz.guess();
|
||||
const tzOffset = moment().format('Z');
|
||||
const isDefaultTimezone = config.isDefault('dateFormat:tz');
|
||||
|
||||
tz = isDefaultTimezone ? detectedTimezone || tzOffset : config.get('dateFormat:tz');
|
||||
}
|
||||
output.params.time_zone = tz;
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
{
|
||||
name: 'ranges',
|
||||
default: [
|
||||
{
|
||||
from: 'now-1w/w',
|
||||
to: 'now',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'time_zone',
|
||||
default: undefined,
|
||||
// Implimentation method is the same as that of date_histogram
|
||||
serialize: () => undefined,
|
||||
write: (agg, output) => {
|
||||
const field = agg.getParam('field');
|
||||
let tz = agg.getParam('time_zone');
|
||||
|
||||
if (!tz && field) {
|
||||
tz = get(agg.getIndexPattern(), [
|
||||
'typeMeta',
|
||||
'aggs',
|
||||
'date_range',
|
||||
field.name,
|
||||
'time_zone',
|
||||
]);
|
||||
}
|
||||
if (!tz) {
|
||||
const detectedTimezone = moment.tz.guess();
|
||||
const tzOffset = moment().format('Z');
|
||||
const isDefaultTimezone = uiSettings.isDefault('dateFormat:tz');
|
||||
|
||||
tz = isDefaultTimezone ? detectedTimezone || tzOffset : uiSettings.get('dateFormat:tz');
|
||||
}
|
||||
output.params.time_zone = tz;
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
|
|
|
@ -17,9 +17,8 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
import _ from 'lodash';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
|
||||
import { size, transform, cloneDeep } from 'lodash';
|
||||
import { IUiSettingsClient } from 'src/core/public';
|
||||
|
||||
import { createFilterFilters } from './create_filter/filters';
|
||||
|
@ -27,7 +26,6 @@ import { toAngularJSON } from '../utils';
|
|||
import { BucketAggType } from './_bucket_agg_type';
|
||||
import { BUCKET_TYPES } from './bucket_agg_types';
|
||||
import { Storage } from '../../../../../../plugins/kibana_utils/public';
|
||||
|
||||
import { getEsQueryConfig, buildEsQuery, Query } from '../../../../common';
|
||||
import { getQueryLog } from '../../../query';
|
||||
|
||||
|
@ -43,9 +41,12 @@ interface FilterValue {
|
|||
id: string;
|
||||
}
|
||||
|
||||
export function getFiltersBucketAgg(deps: { uiSettings: IUiSettingsClient }) {
|
||||
const { uiSettings } = deps;
|
||||
return new BucketAggType({
|
||||
export interface FiltersBucketAggDependencies {
|
||||
uiSettings: IUiSettingsClient;
|
||||
}
|
||||
|
||||
export const getFiltersBucketAgg = ({ uiSettings }: FiltersBucketAggDependencies) =>
|
||||
new BucketAggType({
|
||||
name: BUCKET_TYPES.FILTERS,
|
||||
title: filtersTitle,
|
||||
createFilter: createFilterFilters,
|
||||
|
@ -58,7 +59,7 @@ export function getFiltersBucketAgg(deps: { uiSettings: IUiSettingsClient }) {
|
|||
],
|
||||
write(aggConfig, output) {
|
||||
const inFilters: FilterValue[] = aggConfig.params.filters;
|
||||
if (!_.size(inFilters)) return;
|
||||
if (!size(inFilters)) return;
|
||||
|
||||
inFilters.forEach(filter => {
|
||||
const persistedLog = getQueryLog(
|
||||
|
@ -70,10 +71,10 @@ export function getFiltersBucketAgg(deps: { uiSettings: IUiSettingsClient }) {
|
|||
persistedLog.add(filter.input.query);
|
||||
});
|
||||
|
||||
const outFilters = _.transform(
|
||||
const outFilters = transform(
|
||||
inFilters,
|
||||
function(filters, filter) {
|
||||
const input = _.cloneDeep(filter.input);
|
||||
const input = cloneDeep(filter.input);
|
||||
|
||||
if (!input) {
|
||||
console.log('malformed filter agg params, missing "input" query'); // eslint-disable-line no-console
|
||||
|
@ -100,7 +101,7 @@ export function getFiltersBucketAgg(deps: { uiSettings: IUiSettingsClient }) {
|
|||
{}
|
||||
);
|
||||
|
||||
if (!_.size(outFilters)) return;
|
||||
if (!size(outFilters)) return;
|
||||
|
||||
const params = output.params || (output.params = {});
|
||||
params.filters = outFilters;
|
||||
|
@ -108,4 +109,3 @@ export function getFiltersBucketAgg(deps: { uiSettings: IUiSettingsClient }) {
|
|||
},
|
||||
],
|
||||
});
|
||||
}
|
||||
|
|
|
@ -24,8 +24,6 @@ import { BUCKET_TYPES } from './bucket_agg_types';
|
|||
import { IBucketAggConfig } from './_bucket_agg_type';
|
||||
|
||||
describe('Geohash Agg', () => {
|
||||
// const typesRegistry = mockAggTypesRegistry([geoHashBucketAgg]);
|
||||
const typesRegistry = mockAggTypesRegistry();
|
||||
const getAggConfigs = (params?: Record<string, any>) => {
|
||||
const indexPattern = {
|
||||
id: '1234',
|
||||
|
@ -63,7 +61,7 @@ describe('Geohash Agg', () => {
|
|||
},
|
||||
},
|
||||
],
|
||||
{ typesRegistry }
|
||||
{ typesRegistry: mockAggTypesRegistry() }
|
||||
);
|
||||
};
|
||||
|
||||
|
|
|
@ -17,21 +17,29 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
|
||||
import { coreMock } from '../../../../../../../src/core/public/mocks';
|
||||
import { setUiSettings } from '../../../../public/services';
|
||||
import { AggConfigs } from '../agg_configs';
|
||||
import { mockDataServices, mockAggTypesRegistry } from '../test_helpers';
|
||||
import { mockAggTypesRegistry } from '../test_helpers';
|
||||
import { BUCKET_TYPES } from './bucket_agg_types';
|
||||
import { IBucketHistogramAggConfig, histogramBucketAgg, AutoBounds } from './histogram';
|
||||
import {
|
||||
IBucketHistogramAggConfig,
|
||||
getHistogramBucketAgg,
|
||||
AutoBounds,
|
||||
HistogramBucketAggDependencies,
|
||||
} from './histogram';
|
||||
import { BucketAggType } from './_bucket_agg_type';
|
||||
|
||||
describe('Histogram Agg', () => {
|
||||
beforeEach(() => {
|
||||
mockDataServices();
|
||||
});
|
||||
let aggTypesDependencies: HistogramBucketAggDependencies;
|
||||
|
||||
const typesRegistry = mockAggTypesRegistry([histogramBucketAgg]);
|
||||
beforeEach(() => {
|
||||
const { uiSettings, notifications } = coreMock.createSetup();
|
||||
|
||||
aggTypesDependencies = {
|
||||
uiSettings,
|
||||
notifications,
|
||||
};
|
||||
});
|
||||
|
||||
const getAggConfigs = (params: Record<string, any>) => {
|
||||
const indexPattern = {
|
||||
|
@ -58,7 +66,7 @@ describe('Histogram Agg', () => {
|
|||
params,
|
||||
},
|
||||
],
|
||||
{ typesRegistry }
|
||||
{ typesRegistry: mockAggTypesRegistry([getHistogramBucketAgg(aggTypesDependencies)]) }
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -76,7 +84,7 @@ describe('Histogram Agg', () => {
|
|||
let histogramType: BucketAggType<IBucketHistogramAggConfig>;
|
||||
|
||||
beforeEach(() => {
|
||||
histogramType = histogramBucketAgg;
|
||||
histogramType = getHistogramBucketAgg(aggTypesDependencies);
|
||||
});
|
||||
|
||||
it('is ordered', () => {
|
||||
|
@ -150,6 +158,14 @@ describe('Histogram Agg', () => {
|
|||
params?: Record<string, any>,
|
||||
autoBounds?: AutoBounds
|
||||
) => {
|
||||
aggTypesDependencies = {
|
||||
...aggTypesDependencies,
|
||||
uiSettings: {
|
||||
...aggTypesDependencies.uiSettings,
|
||||
get: () => maxBars as any,
|
||||
},
|
||||
};
|
||||
|
||||
const aggConfigs = getAggConfigs({
|
||||
...params,
|
||||
field: {
|
||||
|
@ -162,15 +178,7 @@ describe('Histogram Agg', () => {
|
|||
aggConfig.setAutoBounds(autoBounds);
|
||||
}
|
||||
|
||||
const core = coreMock.createStart();
|
||||
setUiSettings({
|
||||
...core.uiSettings,
|
||||
get: () => maxBars as any,
|
||||
});
|
||||
|
||||
const interval = aggConfig.write(aggConfigs).params;
|
||||
setUiSettings(core.uiSettings); // clean up
|
||||
return interval;
|
||||
return aggConfig.write(aggConfigs).params;
|
||||
};
|
||||
|
||||
it('will respect the histogram:maxBars setting', () => {
|
||||
|
|
|
@ -17,182 +17,190 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
import _ from 'lodash';
|
||||
import { get } from 'lodash';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { IUiSettingsClient, NotificationsSetup } from 'src/core/public';
|
||||
|
||||
import { BucketAggType, IBucketAggConfig } from './_bucket_agg_type';
|
||||
import { createFilterHistogram } from './create_filter/histogram';
|
||||
import { BUCKET_TYPES } from './bucket_agg_types';
|
||||
import { KBN_FIELD_TYPES } from '../../../../common';
|
||||
import { getNotifications, getUiSettings } from '../../../../public/services';
|
||||
|
||||
export interface AutoBounds {
|
||||
min: number;
|
||||
max: number;
|
||||
}
|
||||
|
||||
export interface HistogramBucketAggDependencies {
|
||||
uiSettings: IUiSettingsClient;
|
||||
notifications: NotificationsSetup;
|
||||
}
|
||||
|
||||
export interface IBucketHistogramAggConfig extends IBucketAggConfig {
|
||||
setAutoBounds: (bounds: AutoBounds) => void;
|
||||
getAutoBounds: () => AutoBounds;
|
||||
}
|
||||
|
||||
export const histogramBucketAgg = new BucketAggType<IBucketHistogramAggConfig>({
|
||||
name: BUCKET_TYPES.HISTOGRAM,
|
||||
title: i18n.translate('data.search.aggs.buckets.histogramTitle', {
|
||||
defaultMessage: 'Histogram',
|
||||
}),
|
||||
ordered: {},
|
||||
makeLabel(aggConfig) {
|
||||
return aggConfig.getFieldDisplayName();
|
||||
},
|
||||
createFilter: createFilterHistogram,
|
||||
decorateAggConfig() {
|
||||
let autoBounds: AutoBounds;
|
||||
|
||||
return {
|
||||
setAutoBounds: {
|
||||
configurable: true,
|
||||
value(newValue: AutoBounds) {
|
||||
autoBounds = newValue;
|
||||
},
|
||||
},
|
||||
getAutoBounds: {
|
||||
configurable: true,
|
||||
value() {
|
||||
return autoBounds;
|
||||
},
|
||||
},
|
||||
};
|
||||
},
|
||||
params: [
|
||||
{
|
||||
name: 'field',
|
||||
type: 'field',
|
||||
filterFieldTypes: KBN_FIELD_TYPES.NUMBER,
|
||||
export const getHistogramBucketAgg = ({
|
||||
uiSettings,
|
||||
notifications,
|
||||
}: HistogramBucketAggDependencies) =>
|
||||
new BucketAggType<IBucketHistogramAggConfig>({
|
||||
name: BUCKET_TYPES.HISTOGRAM,
|
||||
title: i18n.translate('data.search.aggs.buckets.histogramTitle', {
|
||||
defaultMessage: 'Histogram',
|
||||
}),
|
||||
ordered: {},
|
||||
makeLabel(aggConfig) {
|
||||
return aggConfig.getFieldDisplayName();
|
||||
},
|
||||
{
|
||||
/*
|
||||
* This parameter can be set if you want the auto scaled interval to always
|
||||
* be a multiple of a specific base.
|
||||
*/
|
||||
name: 'intervalBase',
|
||||
default: null,
|
||||
write: () => {},
|
||||
createFilter: createFilterHistogram,
|
||||
decorateAggConfig() {
|
||||
let autoBounds: AutoBounds;
|
||||
|
||||
return {
|
||||
setAutoBounds: {
|
||||
configurable: true,
|
||||
value(newValue: AutoBounds) {
|
||||
autoBounds = newValue;
|
||||
},
|
||||
},
|
||||
getAutoBounds: {
|
||||
configurable: true,
|
||||
value() {
|
||||
return autoBounds;
|
||||
},
|
||||
},
|
||||
};
|
||||
},
|
||||
{
|
||||
name: 'interval',
|
||||
modifyAggConfigOnSearchRequestStart(
|
||||
aggConfig: IBucketHistogramAggConfig,
|
||||
searchSource: any,
|
||||
options: any
|
||||
) {
|
||||
const field = aggConfig.getField();
|
||||
const aggBody = field.scripted
|
||||
? { script: { source: field.script, lang: field.lang } }
|
||||
: { field: field.name };
|
||||
params: [
|
||||
{
|
||||
name: 'field',
|
||||
type: 'field',
|
||||
filterFieldTypes: KBN_FIELD_TYPES.NUMBER,
|
||||
},
|
||||
{
|
||||
/*
|
||||
* This parameter can be set if you want the auto scaled interval to always
|
||||
* be a multiple of a specific base.
|
||||
*/
|
||||
name: 'intervalBase',
|
||||
default: null,
|
||||
write: () => {},
|
||||
},
|
||||
{
|
||||
name: 'interval',
|
||||
modifyAggConfigOnSearchRequestStart(
|
||||
aggConfig: IBucketHistogramAggConfig,
|
||||
searchSource: any,
|
||||
options: any
|
||||
) {
|
||||
const field = aggConfig.getField();
|
||||
const aggBody = field.scripted
|
||||
? { script: { source: field.script, lang: field.lang } }
|
||||
: { field: field.name };
|
||||
|
||||
const childSearchSource = searchSource
|
||||
.createChild()
|
||||
.setField('size', 0)
|
||||
.setField('aggs', {
|
||||
maxAgg: {
|
||||
max: aggBody,
|
||||
},
|
||||
minAgg: {
|
||||
min: aggBody,
|
||||
},
|
||||
});
|
||||
|
||||
return childSearchSource
|
||||
.fetch(options)
|
||||
.then((resp: any) => {
|
||||
aggConfig.setAutoBounds({
|
||||
min: _.get(resp, 'aggregations.minAgg.value'),
|
||||
max: _.get(resp, 'aggregations.maxAgg.value'),
|
||||
const childSearchSource = searchSource
|
||||
.createChild()
|
||||
.setField('size', 0)
|
||||
.setField('aggs', {
|
||||
maxAgg: {
|
||||
max: aggBody,
|
||||
},
|
||||
minAgg: {
|
||||
min: aggBody,
|
||||
},
|
||||
});
|
||||
})
|
||||
.catch((e: Error) => {
|
||||
if (e.name === 'AbortError') return;
|
||||
getNotifications().toasts.addWarning(
|
||||
i18n.translate('data.search.aggs.histogram.missingMaxMinValuesWarning', {
|
||||
defaultMessage:
|
||||
'Unable to retrieve max and min values to auto-scale histogram buckets. This may lead to poor visualization performance.',
|
||||
})
|
||||
);
|
||||
});
|
||||
},
|
||||
write(aggConfig, output) {
|
||||
let interval = parseFloat(aggConfig.params.interval);
|
||||
if (interval <= 0) {
|
||||
interval = 1;
|
||||
}
|
||||
const autoBounds = aggConfig.getAutoBounds();
|
||||
|
||||
// ensure interval does not create too many buckets and crash browser
|
||||
if (autoBounds) {
|
||||
const range = autoBounds.max - autoBounds.min;
|
||||
const bars = range / interval;
|
||||
return childSearchSource
|
||||
.fetch(options)
|
||||
.then((resp: any) => {
|
||||
aggConfig.setAutoBounds({
|
||||
min: get(resp, 'aggregations.minAgg.value'),
|
||||
max: get(resp, 'aggregations.maxAgg.value'),
|
||||
});
|
||||
})
|
||||
.catch((e: Error) => {
|
||||
if (e.name === 'AbortError') return;
|
||||
notifications.toasts.addWarning(
|
||||
i18n.translate('data.search.aggs.histogram.missingMaxMinValuesWarning', {
|
||||
defaultMessage:
|
||||
'Unable to retrieve max and min values to auto-scale histogram buckets. This may lead to poor visualization performance.',
|
||||
})
|
||||
);
|
||||
});
|
||||
},
|
||||
write(aggConfig, output) {
|
||||
let interval = parseFloat(aggConfig.params.interval);
|
||||
if (interval <= 0) {
|
||||
interval = 1;
|
||||
}
|
||||
const autoBounds = aggConfig.getAutoBounds();
|
||||
|
||||
const config = getUiSettings();
|
||||
if (bars > config.get('histogram:maxBars')) {
|
||||
const minInterval = range / config.get('histogram:maxBars');
|
||||
// ensure interval does not create too many buckets and crash browser
|
||||
if (autoBounds) {
|
||||
const range = autoBounds.max - autoBounds.min;
|
||||
const bars = range / interval;
|
||||
|
||||
// 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 orderOfMagnitude = Math.pow(10, Math.floor(Math.log10(minInterval)));
|
||||
let roundInterval = orderOfMagnitude;
|
||||
if (bars > uiSettings.get('histogram:maxBars')) {
|
||||
const minInterval = range / uiSettings.get('histogram:maxBars');
|
||||
|
||||
while (roundInterval < minInterval) {
|
||||
roundInterval += orderOfMagnitude;
|
||||
// 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 orderOfMagnitude = Math.pow(10, Math.floor(Math.log10(minInterval)));
|
||||
let roundInterval = orderOfMagnitude;
|
||||
|
||||
while (roundInterval < minInterval) {
|
||||
roundInterval += orderOfMagnitude;
|
||||
}
|
||||
interval = roundInterval;
|
||||
}
|
||||
interval = roundInterval;
|
||||
}
|
||||
}
|
||||
const base = aggConfig.params.intervalBase;
|
||||
const base = aggConfig.params.intervalBase;
|
||||
|
||||
if (base) {
|
||||
if (interval < base) {
|
||||
// In case the specified interval is below the base, just increase it to it's base
|
||||
interval = base;
|
||||
} else if (interval % base !== 0) {
|
||||
// In case the interval is not a multiple of the base round it to the next base
|
||||
interval = Math.round(interval / base) * base;
|
||||
if (base) {
|
||||
if (interval < base) {
|
||||
// In case the specified interval is below the base, just increase it to it's base
|
||||
interval = base;
|
||||
} else if (interval % base !== 0) {
|
||||
// In case the interval is not a multiple of the base round it to the next base
|
||||
interval = Math.round(interval / base) * base;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
output.params.interval = interval;
|
||||
output.params.interval = interval;
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'min_doc_count',
|
||||
default: false,
|
||||
write(aggConfig, output) {
|
||||
if (aggConfig.params.min_doc_count) {
|
||||
output.params.min_doc_count = 0;
|
||||
} else {
|
||||
output.params.min_doc_count = 1;
|
||||
}
|
||||
{
|
||||
name: 'min_doc_count',
|
||||
default: false,
|
||||
write(aggConfig, output) {
|
||||
if (aggConfig.params.min_doc_count) {
|
||||
output.params.min_doc_count = 0;
|
||||
} else {
|
||||
output.params.min_doc_count = 1;
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'has_extended_bounds',
|
||||
default: false,
|
||||
write: () => {},
|
||||
},
|
||||
{
|
||||
name: 'extended_bounds',
|
||||
default: {
|
||||
min: '',
|
||||
max: '',
|
||||
{
|
||||
name: 'has_extended_bounds',
|
||||
default: false,
|
||||
write: () => {},
|
||||
},
|
||||
write(aggConfig, output) {
|
||||
const { min, max } = aggConfig.params.extended_bounds;
|
||||
{
|
||||
name: 'extended_bounds',
|
||||
default: {
|
||||
min: '',
|
||||
max: '',
|
||||
},
|
||||
write(aggConfig, output) {
|
||||
const { min, max } = aggConfig.params.extended_bounds;
|
||||
|
||||
if (aggConfig.params.has_extended_bounds && (min || min === 0) && (max || max === 0)) {
|
||||
output.params.extended_bounds = { min, max };
|
||||
}
|
||||
if (aggConfig.params.has_extended_bounds && (min || min === 0) && (max || max === 0)) {
|
||||
output.params.extended_bounds = { min, max };
|
||||
}
|
||||
},
|
||||
shouldShow: (aggConfig: IBucketAggConfig) => aggConfig.params.has_extended_bounds,
|
||||
},
|
||||
shouldShow: (aggConfig: IBucketAggConfig) => aggConfig.params.has_extended_bounds,
|
||||
},
|
||||
],
|
||||
});
|
||||
],
|
||||
});
|
||||
|
|
|
@ -48,8 +48,6 @@ describe('Range Agg', () => {
|
|||
mockDataServices();
|
||||
});
|
||||
|
||||
const typesRegistry = mockAggTypesRegistry([rangeBucketAgg]);
|
||||
|
||||
const getConfig = (() => {}) as FieldFormatsGetConfigFn;
|
||||
const getAggConfigs = () => {
|
||||
const field = {
|
||||
|
@ -86,7 +84,7 @@ describe('Range Agg', () => {
|
|||
},
|
||||
},
|
||||
],
|
||||
{ typesRegistry }
|
||||
{ typesRegistry: mockAggTypesRegistry([rangeBucketAgg]) }
|
||||
);
|
||||
};
|
||||
|
||||
|
|
|
@ -26,7 +26,6 @@ import { IBucketAggConfig } from './_bucket_agg_type';
|
|||
describe('Significant Terms Agg', () => {
|
||||
describe('order agg editor UI', () => {
|
||||
describe('convert include/exclude from old format', () => {
|
||||
const typesRegistry = mockAggTypesRegistry([significantTermsBucketAgg]);
|
||||
const getAggConfigs = (params: Record<string, any> = {}) => {
|
||||
const indexPattern = {
|
||||
id: '1234',
|
||||
|
@ -52,12 +51,12 @@ describe('Significant Terms Agg', () => {
|
|||
params,
|
||||
},
|
||||
],
|
||||
{ typesRegistry }
|
||||
{ typesRegistry: mockAggTypesRegistry([significantTermsBucketAgg]) }
|
||||
);
|
||||
};
|
||||
|
||||
const testSerializeAndWrite = (aggs: IAggConfigs) => {
|
||||
const agg = aggs.aggs[0];
|
||||
const [agg] = aggs.aggs;
|
||||
const { [BUCKET_TYPES.SIGNIFICANT_TERMS]: params } = agg.toDsl();
|
||||
|
||||
expect(params.field).toBe('field');
|
||||
|
|
|
@ -23,7 +23,6 @@ import { BUCKET_TYPES } from './bucket_agg_types';
|
|||
|
||||
describe('Terms Agg', () => {
|
||||
describe('order agg editor UI', () => {
|
||||
const typesRegistry = mockAggTypesRegistry();
|
||||
const getAggConfigs = (params: Record<string, any> = {}) => {
|
||||
const indexPattern = {
|
||||
id: '1234',
|
||||
|
@ -48,7 +47,7 @@ describe('Terms Agg', () => {
|
|||
type: BUCKET_TYPES.TERMS,
|
||||
},
|
||||
],
|
||||
{ typesRegistry }
|
||||
{ typesRegistry: mockAggTypesRegistry() }
|
||||
);
|
||||
};
|
||||
|
||||
|
|
|
@ -22,24 +22,29 @@ import { getAggTypes } from './index';
|
|||
|
||||
import { isBucketAggType } from './buckets/_bucket_agg_type';
|
||||
import { isMetricAggType } from './metrics/metric_agg_type';
|
||||
|
||||
const aggTypes = getAggTypes({ uiSettings: coreMock.createStart().uiSettings });
|
||||
|
||||
const bucketAggs = aggTypes.buckets;
|
||||
const metricAggs = aggTypes.metrics;
|
||||
import { QueryStart } from '../../query';
|
||||
|
||||
describe('AggTypesComponent', () => {
|
||||
const core = coreMock.createSetup();
|
||||
const aggTypes = getAggTypes({
|
||||
uiSettings: core.uiSettings,
|
||||
notifications: core.notifications,
|
||||
query: {} as QueryStart,
|
||||
});
|
||||
|
||||
const { buckets, metrics } = aggTypes;
|
||||
|
||||
describe('bucket aggs', () => {
|
||||
it('all extend BucketAggType', () => {
|
||||
bucketAggs.forEach(bucketAgg => {
|
||||
test('all extend BucketAggType', () => {
|
||||
buckets.forEach(bucketAgg => {
|
||||
expect(isBucketAggType(bucketAgg)).toBeTruthy();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('metric aggs', () => {
|
||||
it('all extend MetricAggType', () => {
|
||||
metricAggs.forEach(metricAgg => {
|
||||
test('all extend MetricAggType', () => {
|
||||
metrics.forEach(metricAgg => {
|
||||
expect(isMetricAggType(metricAgg)).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
|
|
@ -23,6 +23,7 @@ import { AggTypesRegistry, AggTypesRegistryStart } from '../agg_types_registry';
|
|||
import { getAggTypes } from '../agg_types';
|
||||
import { BucketAggType } from '../buckets/_bucket_agg_type';
|
||||
import { MetricAggType } from '../metrics/metric_agg_type';
|
||||
import { queryServiceMock } from '../../../query/mocks';
|
||||
|
||||
/**
|
||||
* Testing utility which creates a new instance of AggTypesRegistry,
|
||||
|
@ -51,7 +52,13 @@ export function mockAggTypesRegistry<T extends BucketAggType<any> | MetricAggTyp
|
|||
}
|
||||
});
|
||||
} else {
|
||||
const aggTypes = getAggTypes({ uiSettings: coreMock.createSetup().uiSettings });
|
||||
const core = coreMock.createSetup();
|
||||
const aggTypes = getAggTypes({
|
||||
uiSettings: core.uiSettings,
|
||||
notifications: core.notifications,
|
||||
query: queryServiceMock.createSetupContract(),
|
||||
});
|
||||
|
||||
aggTypes.buckets.forEach(type => registrySetup.registerBucket(type));
|
||||
aggTypes.metrics.forEach(type => registrySetup.registerMetric(type));
|
||||
}
|
||||
|
|
|
@ -34,7 +34,7 @@ describe('Search service', () => {
|
|||
describe('setup()', () => {
|
||||
it('exposes proper contract', async () => {
|
||||
const setup = searchService.setup(mockCoreSetup, {
|
||||
version: '8',
|
||||
packageInfo: { version: '8' },
|
||||
} as any);
|
||||
expect(setup).toHaveProperty('registerSearchStrategyProvider');
|
||||
});
|
||||
|
|
|
@ -25,6 +25,7 @@ import { TStrategyTypes } from './strategy_types';
|
|||
import { getEsClient, LegacyApiCaller } from './es_client';
|
||||
import { ES_SEARCH_STRATEGY, DEFAULT_SEARCH_STRATEGY } from '../../common/search';
|
||||
import { esSearchStrategyProvider } from './es_search/es_search_strategy';
|
||||
import { QuerySetup } from '../query/query_service';
|
||||
import { SearchInterceptor } from './search_interceptor';
|
||||
import {
|
||||
getAggTypes,
|
||||
|
@ -40,6 +41,11 @@ import {
|
|||
siblingPipelineAggHelper,
|
||||
} from './aggs';
|
||||
|
||||
interface SearchServiceSetupDependencies {
|
||||
packageInfo: PackageInfo;
|
||||
query: QuerySetup;
|
||||
}
|
||||
|
||||
/**
|
||||
* The search plugin exposes two registration methods for other plugins:
|
||||
* - registerSearchStrategyProvider for plugins to add their own custom
|
||||
|
@ -73,13 +79,21 @@ export class SearchService implements Plugin<ISearchSetup, ISearchStart> {
|
|||
return strategyProvider;
|
||||
};
|
||||
|
||||
public setup(core: CoreSetup, packageInfo: PackageInfo): ISearchSetup {
|
||||
public setup(
|
||||
core: CoreSetup,
|
||||
{ packageInfo, query }: SearchServiceSetupDependencies
|
||||
): ISearchSetup {
|
||||
this.esClient = getEsClient(core.injectedMetadata, core.http, packageInfo);
|
||||
this.registerSearchStrategyProvider(SYNC_SEARCH_STRATEGY, syncSearchStrategyProvider);
|
||||
this.registerSearchStrategyProvider(ES_SEARCH_STRATEGY, esSearchStrategyProvider);
|
||||
|
||||
const aggTypesSetup = this.aggTypesRegistry.setup();
|
||||
const aggTypes = getAggTypes({ uiSettings: core.uiSettings });
|
||||
const aggTypes = getAggTypes({
|
||||
query,
|
||||
uiSettings: core.uiSettings,
|
||||
notifications: core.notifications,
|
||||
});
|
||||
|
||||
aggTypes.buckets.forEach(b => aggTypesSetup.registerBucket(b));
|
||||
aggTypes.metrics.forEach(m => aggTypesSetup.registerMetric(m));
|
||||
|
||||
|
|
|
@ -17,8 +17,7 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
import { NotificationsStart } from 'src/core/public';
|
||||
import { CoreSetup, CoreStart } from 'kibana/public';
|
||||
import { NotificationsStart, CoreSetup, CoreStart } from 'src/core/public';
|
||||
import { FieldFormatsStart } from './field_formats';
|
||||
import { createGetterSetter } from '../../kibana_utils/public';
|
||||
import { IndexPatternsContract } from './index_patterns';
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue