mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 17:59:23 -04:00
[Vis: Default editor] Remove select param type (#40715)
* Remove select param type * Add non-responsive to agg_add control * Remove extra braces * Add agg_group_names enum * Remove unused file agg_config_result * Revert for files from tabify folder * Get rid of importing from index * Remove unused functions # Conflicts: # src/legacy/ui/public/vis/editors/default/components/__snapshots__/default_editor_agg_params.test.tsx.snap # src/legacy/ui/public/vis/editors/default/components/default_editor_agg_params.test.tsx # src/legacy/ui/public/vis/editors/default/components/default_editor_agg_params_helper.test.ts # src/legacy/ui/public/vis/editors/default/default.js
This commit is contained in:
parent
9ffb76487b
commit
a1f647cec0
29 changed files with 593 additions and 366 deletions
|
@ -21,6 +21,7 @@ import _ from 'lodash';
|
|||
import { VisProvider } from '../../vis';
|
||||
import { aggTypes } from '..';
|
||||
import FixturesStubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern';
|
||||
import { AggGroupNames } from '../../vis/editors/default/agg_groups';
|
||||
|
||||
// eslint-disable-next-line import/no-default-export
|
||||
export default function AggParamWriterHelper(Private) {
|
||||
|
@ -75,7 +76,7 @@ export default function AggParamWriterHelper(Private) {
|
|||
|
||||
if (this.aggType.params.byName.field && !paramValues.field) {
|
||||
// pick a field rather than force a field to be specified everywhere
|
||||
if (this.aggType.type === 'metrics') {
|
||||
if (this.aggType.type === AggGroupNames.Metrics) {
|
||||
paramValues.field = _.sample(this.indexPattern.fields.byType.number);
|
||||
} else {
|
||||
const type = this.aggType.params.byName.field.filterFieldTypes || 'string';
|
||||
|
|
|
@ -22,7 +22,6 @@ import { AggParams } from '../agg_params';
|
|||
import { BaseParamType } from '../param_types/base';
|
||||
import { FieldParamType } from '../param_types/field';
|
||||
import { OptionedParamType } from '../param_types/optioned';
|
||||
import { SelectParamType } from '../param_types/select';
|
||||
|
||||
describe('AggParams class', function () {
|
||||
|
||||
|
@ -64,17 +63,17 @@ describe('AggParams class', function () {
|
|||
expect(aggParams[0]).to.be.a(OptionedParamType);
|
||||
});
|
||||
|
||||
it('Uses the SelectParamType class for params of type "select"', function () {
|
||||
it('Uses the OptionedParamType class for params of type "optioned"', function () {
|
||||
const params = [
|
||||
{
|
||||
name: 'order',
|
||||
type: 'select'
|
||||
type: 'optioned'
|
||||
}
|
||||
];
|
||||
const aggParams = new AggParams(params);
|
||||
|
||||
expect(aggParams).to.have.length(params.length);
|
||||
expect(aggParams[0]).to.be.a(SelectParamType);
|
||||
expect(aggParams[0]).to.be.a(OptionedParamType);
|
||||
});
|
||||
|
||||
it('Always converts the params to a BaseParamType', function () {
|
||||
|
|
|
@ -20,7 +20,6 @@
|
|||
import { IndexedArray } from '../indexed_array';
|
||||
import { FieldParamType } from './param_types/field';
|
||||
import { OptionedParamType } from './param_types/optioned';
|
||||
import { SelectParamType } from './param_types/select';
|
||||
import { StringParamType } from './param_types/string';
|
||||
import { JsonParamType } from './param_types/json';
|
||||
import { BaseParamType } from './param_types/base';
|
||||
|
@ -28,9 +27,7 @@ import { createLegacyClass } from '../utils/legacy_class';
|
|||
|
||||
const paramTypeMap = {
|
||||
field: FieldParamType,
|
||||
// todo: remove select type and update optioned type after EUIfication of all components;
|
||||
optioned: (OptionedParamType),
|
||||
select: SelectParamType,
|
||||
string: (StringParamType),
|
||||
json: (JsonParamType),
|
||||
_default: (BaseParamType)
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
import _ from 'lodash';
|
||||
import { buildExistsFilter, buildPhrasesFilter, buildQueryFromFilters } from '@kbn/es-query';
|
||||
import { AggGroupNames } from '../../vis/editors/default/agg_groups';
|
||||
|
||||
/**
|
||||
* walks the aggregation DSL and returns DSL starting at aggregation with id of startFromAggId
|
||||
|
@ -101,7 +102,7 @@ const getOtherAggTerms = (requestAgg, key, otherAgg) => {
|
|||
|
||||
|
||||
const buildOtherBucketAgg = (aggConfigs, aggWithOtherBucket, response) => {
|
||||
const bucketAggs = aggConfigs.filter(agg => agg.type.type === 'buckets');
|
||||
const bucketAggs = aggConfigs.filter(agg => agg.type.type === AggGroupNames.Buckets);
|
||||
const index = bucketAggs.findIndex(agg => agg.id === aggWithOtherBucket.id);
|
||||
const aggs = aggConfigs.toDsl();
|
||||
const indexPattern = aggWithOtherBucket.params.field.indexPattern;
|
||||
|
|
|
@ -26,6 +26,7 @@ import { PrecisionParamEditor } from '../controls/precision';
|
|||
import { geohashColumns } from '../../utils/decode_geo_hash';
|
||||
import { geoContains, scaleBounds } from '../../utils/geo_utils';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { AggGroupNames } from '../../vis/editors/default/agg_groups';
|
||||
|
||||
const config = chrome.getUiSettingsClient();
|
||||
|
||||
|
@ -156,7 +157,7 @@ export const geoHashBucketAgg = new BucketAggType({
|
|||
geo_bounding_box: boundingBox
|
||||
},
|
||||
schema: {
|
||||
group: 'buckets'
|
||||
group: AggGroupNames.Buckets
|
||||
}
|
||||
}, { addToAggConfigs: false }));
|
||||
}
|
||||
|
|
|
@ -174,7 +174,7 @@ export const termsBucketAgg = new BucketAggType({
|
|||
},
|
||||
{
|
||||
name: 'order',
|
||||
type: 'select',
|
||||
type: 'optioned',
|
||||
default: 'desc',
|
||||
editorComponent: wrapWithInlineComp(OrderParamEditor),
|
||||
options: [
|
||||
|
|
|
@ -21,7 +21,7 @@ import React, { useEffect } from 'react';
|
|||
import { EuiFormRow, EuiSelect } from '@elastic/eui';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { AggParamEditorProps } from 'ui/vis/editors/default';
|
||||
import { SelectValueProp, SelectParamEditorProps } from '../param_types/select';
|
||||
import { OptionedValueProp, OptionedParamEditorProps } from '../param_types/optioned';
|
||||
|
||||
function OrderParamEditor({
|
||||
aggParam,
|
||||
|
@ -31,7 +31,7 @@ function OrderParamEditor({
|
|||
setValidity,
|
||||
setTouched,
|
||||
wrappedWithInlineComp,
|
||||
}: AggParamEditorProps<SelectValueProp> & SelectParamEditorProps) {
|
||||
}: AggParamEditorProps<OptionedValueProp> & OptionedParamEditorProps) {
|
||||
const label = i18n.translate('common.ui.aggTypes.orderLabel', {
|
||||
defaultMessage: 'Order',
|
||||
});
|
||||
|
|
|
@ -22,6 +22,7 @@ import { EuiFormLabel } from '@elastic/eui';
|
|||
import { i18n } from '@kbn/i18n';
|
||||
import { AggParamEditorProps, DefaultEditorAggParams } from '../../vis/editors/default';
|
||||
import { AggConfig } from '../../vis';
|
||||
import { AggGroupNames } from '../../vis/editors/default/agg_groups';
|
||||
|
||||
function SubMetricParamEditor({
|
||||
agg,
|
||||
|
@ -42,7 +43,7 @@ function SubMetricParamEditor({
|
|||
const type = aggParam.name;
|
||||
|
||||
const aggTitle = type === 'customMetric' ? metricTitle : bucketTitle;
|
||||
const aggGroup = type === 'customMetric' ? 'metrics' : 'buckets';
|
||||
const aggGroup = type === 'customMetric' ? AggGroupNames.Metrics : AggGroupNames.Buckets;
|
||||
|
||||
useEffect(() => {
|
||||
setValue(agg.params[type] || agg.type.params.byName[type].makeAgg(agg));
|
||||
|
|
|
@ -24,9 +24,9 @@ import { FormattedMessage } from '@kbn/i18n/react';
|
|||
import { AggParamEditorProps } from 'ui/vis/editors/default';
|
||||
import { AggConfig } from 'ui/vis';
|
||||
import { AggParam } from '../agg_param';
|
||||
import { SelectValueProp, SelectParamEditorProps } from '../param_types/select';
|
||||
import { OptionedValueProp, OptionedParamEditorProps } from '../param_types/optioned';
|
||||
|
||||
interface AggregateValueProp extends SelectValueProp {
|
||||
interface AggregateValueProp extends OptionedValueProp {
|
||||
isCompatible(aggConfig: AggConfig): boolean;
|
||||
}
|
||||
|
||||
|
@ -44,7 +44,7 @@ function TopAggregateParamEditor({
|
|||
setValidity,
|
||||
setTouched,
|
||||
wrappedWithInlineComp,
|
||||
}: AggParamEditorProps<AggregateValueProp> & SelectParamEditorProps<AggregateValueProp>) {
|
||||
}: AggParamEditorProps<AggregateValueProp> & OptionedParamEditorProps<AggregateValueProp>) {
|
||||
const isFirstRun = useRef(true);
|
||||
const fieldType = agg.params.field && agg.params.field.type;
|
||||
const emptyValue = { text: '', value: 'EMPTY_VALUE', disabled: true, hidden: true };
|
||||
|
|
|
@ -99,7 +99,7 @@ export const topHitMetricAgg = new MetricAggType({
|
|||
},
|
||||
{
|
||||
name: 'aggregate',
|
||||
type: 'select',
|
||||
type: 'optioned',
|
||||
editorComponent: wrapWithInlineComp(TopAggregateParamEditor),
|
||||
options: [
|
||||
{
|
||||
|
@ -164,7 +164,7 @@ export const topHitMetricAgg = new MetricAggType({
|
|||
},
|
||||
{
|
||||
name: 'sortOrder',
|
||||
type: 'select',
|
||||
type: 'optioned',
|
||||
default: 'desc',
|
||||
editorComponent: OrderParamEditor,
|
||||
options: [
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
|
||||
import { IndexedArray } from '../../indexed_array';
|
||||
|
||||
interface SelectValueProp {
|
||||
interface OptionedValueProp {
|
||||
value: string;
|
||||
text: string;
|
||||
}
|
||||
|
@ -30,10 +30,10 @@ interface SelectOptions<T> extends IndexedArray<T> {
|
|||
};
|
||||
}
|
||||
|
||||
interface SelectParamEditorProps<T = SelectValueProp> {
|
||||
interface OptionedParamEditorProps<T = OptionedValueProp> {
|
||||
aggParam: {
|
||||
options: SelectOptions<T>;
|
||||
};
|
||||
}
|
||||
|
||||
export { SelectValueProp, SelectParamEditorProps };
|
||||
export { OptionedValueProp, OptionedParamEditorProps };
|
|
@ -26,7 +26,7 @@ function OptionedParamType(config) {
|
|||
OptionedParamType.Super.call(this, config);
|
||||
|
||||
this.options = new IndexedArray({
|
||||
index: ['val'],
|
||||
index: ['value'],
|
||||
immutable: true,
|
||||
initialSet: this.options
|
||||
});
|
||||
|
@ -38,18 +38,18 @@ function OptionedParamType(config) {
|
|||
* @return {any}
|
||||
*/
|
||||
OptionedParamType.prototype.serialize = function (selected) {
|
||||
return selected.val;
|
||||
return selected.value;
|
||||
};
|
||||
|
||||
/**
|
||||
* Take a value that was serialized to the database and
|
||||
* return the option that is represents
|
||||
*
|
||||
* @param {any} val - the value that was saved
|
||||
* @param {any} value - the value that was saved
|
||||
* @return {object}
|
||||
*/
|
||||
OptionedParamType.prototype.deserialize = function (val) {
|
||||
return this.options.byVal[val];
|
||||
OptionedParamType.prototype.deserialize = function (value) {
|
||||
return this.options.byValue[value];
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -63,7 +63,7 @@ OptionedParamType.prototype.deserialize = function (val) {
|
|||
* @return {undefined}
|
||||
*/
|
||||
OptionedParamType.prototype.write = function (aggConfig, output) {
|
||||
output.params[this.name] = aggConfig.params[this.name].val;
|
||||
output.params[this.name] = aggConfig.params[this.name].value;
|
||||
};
|
||||
|
||||
export { OptionedParamType };
|
||||
|
|
|
@ -1,69 +0,0 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import { IndexedArray } from '../../indexed_array';
|
||||
import { BaseParamType } from './base';
|
||||
import { createLegacyClass } from '../../utils/legacy_class';
|
||||
|
||||
createLegacyClass(SelectParamType).inherits(BaseParamType);
|
||||
function SelectParamType(config) {
|
||||
SelectParamType.Super.call(this, config);
|
||||
|
||||
this.options = new IndexedArray({
|
||||
index: ['value'],
|
||||
immutable: true,
|
||||
initialSet: this.options
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Serialize a selection to be stored in the database
|
||||
* @param {object} selected - the option that was selected
|
||||
* @return {any}
|
||||
*/
|
||||
SelectParamType.prototype.serialize = function (selected) {
|
||||
return selected.value;
|
||||
};
|
||||
|
||||
/**
|
||||
* Take a value that was serialized to the database and
|
||||
* return the option that is represents
|
||||
*
|
||||
* @param {any} value - the value that was saved
|
||||
* @return {object}
|
||||
*/
|
||||
SelectParamType.prototype.deserialize = function (value) {
|
||||
return this.options.byValue[value];
|
||||
};
|
||||
|
||||
/**
|
||||
* Write the aggregation parameter.
|
||||
*
|
||||
* @param {AggConfig} aggConfig - the entire configuration for this agg
|
||||
* @param {object} output - the result of calling write on all of the aggregations
|
||||
* parameters.
|
||||
* @param {object} output.params - the final object that will be included as the params
|
||||
* for the agg
|
||||
* @return {undefined}
|
||||
*/
|
||||
SelectParamType.prototype.write = function (aggConfig, output) {
|
||||
output.params[this.name] = aggConfig.params[this.name].value;
|
||||
};
|
||||
|
||||
export { SelectParamType };
|
|
@ -1,148 +0,0 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import AggConfigResult from '../agg_config_result';
|
||||
import expect from '@kbn/expect';
|
||||
import ngMock from 'ng_mock';
|
||||
import { VisProvider } from '..';
|
||||
import FixturesStubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern';
|
||||
describe('AggConfigResult', function () {
|
||||
let indexPattern;
|
||||
let Vis;
|
||||
|
||||
beforeEach(ngMock.module('kibana'));
|
||||
beforeEach(ngMock.inject(function (Private) {
|
||||
Vis = Private(VisProvider);
|
||||
indexPattern = Private(FixturesStubbedLogstashIndexPatternProvider);
|
||||
}));
|
||||
|
||||
describe('initialization', function () {
|
||||
it('should set the type to bucket for bucket based results', function () {
|
||||
const vis = new Vis(indexPattern, {
|
||||
type: 'histogram',
|
||||
aggs: [ { type: 'terms', schema: 'segment', params: { field: '_type' } } ]
|
||||
});
|
||||
const aggConfig = vis.aggs.byTypeName.terms[0];
|
||||
const results = new AggConfigResult(aggConfig, null, 10, 'apache');
|
||||
expect(results).to.have.property('aggConfig', aggConfig);
|
||||
expect(results).to.have.property('$parent', null);
|
||||
expect(results).to.have.property('type', 'bucket');
|
||||
expect(results).to.have.property('value', 10);
|
||||
expect(results).to.have.property('key', 'apache');
|
||||
});
|
||||
|
||||
it('should set the type to metric for metric based results', function () {
|
||||
const vis = new Vis(indexPattern, {
|
||||
type: 'histogram',
|
||||
aggs: [ { type: 'avg', schema: 'metric', params: { field: 'bytes' } } ]
|
||||
});
|
||||
const aggConfig = vis.aggs.byTypeName.avg[0];
|
||||
const results = new AggConfigResult(aggConfig, null, 1024);
|
||||
expect(results).to.have.property('aggConfig', aggConfig);
|
||||
expect(results).to.have.property('$parent', null);
|
||||
expect(results).to.have.property('type', 'metric');
|
||||
expect(results).to.have.property('value', 1024);
|
||||
expect(results).to.have.property('key', undefined);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
describe('hierarchical', function () {
|
||||
describe('getPath()', function () {
|
||||
|
||||
it('should return the parent and itself (in an array) for the path', function () {
|
||||
const vis = new Vis(indexPattern, {
|
||||
type: 'histogram',
|
||||
aggs: [
|
||||
{ type: 'terms', schema: 'segment', params: { field: '_type' } },
|
||||
{ type: 'terms', schema: 'segment', params: { field: 'extension' } }
|
||||
]
|
||||
});
|
||||
const parentAggConfig = vis.aggs.byTypeName.terms[0];
|
||||
const aggConfig = vis.aggs.byTypeName.terms[1];
|
||||
const parentResult = new AggConfigResult(parentAggConfig, null, 20, 'apache');
|
||||
const result = new AggConfigResult(aggConfig, parentResult, 15, 'php');
|
||||
const path = result.getPath();
|
||||
expect(path).to.be.an(Array);
|
||||
expect(path).to.have.length(2);
|
||||
expect(path[0]).to.be(parentResult);
|
||||
expect(path[1]).to.be(result);
|
||||
});
|
||||
|
||||
it('should return itself (in an array) for the path', function () {
|
||||
const vis = new Vis(indexPattern, {
|
||||
type: 'histogram',
|
||||
aggs: [
|
||||
{ type: 'terms', schema: 'segment', params: { field: 'extension' } }
|
||||
]
|
||||
});
|
||||
const aggConfig = vis.aggs.byTypeName.terms[0];
|
||||
const result = new AggConfigResult(aggConfig, null, 15, 'php');
|
||||
const path = result.getPath();
|
||||
expect(path).to.be.an(Array);
|
||||
expect(path).to.have.length(1);
|
||||
expect(path[0]).to.be(result);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('createFilter', function () {
|
||||
it('should return a filter object that represents the result', function () {
|
||||
const vis = new Vis(indexPattern, {
|
||||
type: 'histogram',
|
||||
aggs: [
|
||||
{ type: 'terms', schema: 'segment', params: { field: 'extension' } }
|
||||
]
|
||||
});
|
||||
const aggConfig = vis.aggs.byTypeName.terms[0];
|
||||
const result = new AggConfigResult(aggConfig, null, 15, 'php');
|
||||
const filter = result.createFilter();
|
||||
expect(filter).to.have.property('query');
|
||||
expect(filter.query).to.have.property('match');
|
||||
expect(filter.query.match).to.have.property('extension');
|
||||
expect(filter.query.match.extension).to.have.property('query', 'php');
|
||||
expect(filter.query.match.extension).to.have.property('type', 'phrase');
|
||||
});
|
||||
});
|
||||
|
||||
describe('toString', function () {
|
||||
it('should provide a parsedUrl to the field formatter', function () {
|
||||
const vis = new Vis(indexPattern, {
|
||||
type: 'histogram',
|
||||
aggs: [
|
||||
{ type: 'terms', schema: 'segment', params: { field: 'extension' } }
|
||||
]
|
||||
});
|
||||
|
||||
const aggConfig = vis.aggs.byTypeName.terms[0];
|
||||
aggConfig.fieldFormatter = () => {
|
||||
return (value, second, third, parsedUrl) => {
|
||||
return parsedUrl;
|
||||
};
|
||||
};
|
||||
const result = new AggConfigResult(aggConfig, null, '../app/kibana/#visualize', 'php');
|
||||
const parsedUrl = result.toString('html');
|
||||
const keys = Object.keys(parsedUrl);
|
||||
expect(keys[0]).to.be('origin');
|
||||
expect(keys[1]).to.be('pathname');
|
||||
expect(keys[2]).to.be('basePath');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
|
@ -27,6 +27,7 @@ import { AggConfigs } from '../agg_configs';
|
|||
import FixturesStubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern';
|
||||
import { Schemas } from '../editors/default/schemas';
|
||||
import { IndexedArray } from '../../indexed_array';
|
||||
import { AggGroupNames } from '../editors/default/agg_groups';
|
||||
|
||||
describe('AggConfigs', function () {
|
||||
|
||||
|
@ -108,7 +109,7 @@ describe('AggConfigs', function () {
|
|||
type: {
|
||||
schemas: new Schemas([
|
||||
{
|
||||
group: 'metrics',
|
||||
group: AggGroupNames.Metrics,
|
||||
name: 'metric',
|
||||
title: 'Simple',
|
||||
min: 1,
|
||||
|
@ -120,7 +121,7 @@ describe('AggConfigs', function () {
|
|||
]
|
||||
},
|
||||
{
|
||||
group: 'buckets',
|
||||
group: AggGroupNames.Buckets,
|
||||
name: 'segment',
|
||||
title: 'Example',
|
||||
min: 0,
|
||||
|
|
|
@ -18,7 +18,6 @@
|
|||
*/
|
||||
|
||||
import './_agg_config';
|
||||
import './_agg_config_result';
|
||||
import './_agg_configs';
|
||||
import './_vis';
|
||||
describe('Vis Component', function () {
|
||||
|
|
|
@ -1,68 +0,0 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import chrome from '../chrome';
|
||||
|
||||
// eslint-disable-next-line import/no-default-export
|
||||
export default function AggConfigResult(aggConfig, parent, value, key, filters) {
|
||||
this.key = key;
|
||||
this.value = value;
|
||||
this.aggConfig = aggConfig;
|
||||
this.filters = filters;
|
||||
this.$parent = parent;
|
||||
|
||||
if (aggConfig.type.type === 'buckets') {
|
||||
this.type = 'bucket';
|
||||
} else {
|
||||
this.type = 'metric';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of the aggConfigResult and parents up the branch
|
||||
* @returns {array} Array of aggConfigResults
|
||||
*/
|
||||
AggConfigResult.prototype.getPath = function () {
|
||||
return (function walk(result, path) {
|
||||
path.unshift(result);
|
||||
if (result.$parent) return walk(result.$parent, path);
|
||||
return path;
|
||||
}(this, []));
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns an Elasticsearch filter that represents the result.
|
||||
* @returns {object} Elasticsearch filter
|
||||
*/
|
||||
AggConfigResult.prototype.createFilter = function () {
|
||||
return this.filters || this.aggConfig.createFilter(this.key);
|
||||
};
|
||||
|
||||
AggConfigResult.prototype.toString = function (contentType) {
|
||||
const parsedUrl = {
|
||||
origin: window.location.origin,
|
||||
pathname: window.location.pathname,
|
||||
basePath: chrome.getBasePath(),
|
||||
};
|
||||
return this.aggConfig.fieldFormatter(contentType)(this.value, null, null, parsedUrl);
|
||||
};
|
||||
|
||||
AggConfigResult.prototype.valueOf = function () {
|
||||
return this.value;
|
||||
};
|
|
@ -29,6 +29,7 @@
|
|||
import _ from 'lodash';
|
||||
import { IndexedArray } from '../indexed_array';
|
||||
import { AggConfig } from './agg_config';
|
||||
import { AggGroupNames } from './editors/default/agg_groups';
|
||||
|
||||
function removeParentAggs(obj) {
|
||||
for(const prop in obj) {
|
||||
|
@ -185,7 +186,7 @@ class AggConfigs extends IndexedArray {
|
|||
|
||||
parseParentAggs(dslLvlCursor, dsl);
|
||||
|
||||
if (config.type.type === 'buckets' && i < list.length - 1) {
|
||||
if (config.type.type === AggGroupNames.Buckets && i < list.length - 1) {
|
||||
// buckets that are not the last item in the list accept sub-aggs
|
||||
subAggs = dsl.aggs || (dsl.aggs = {});
|
||||
}
|
||||
|
@ -215,7 +216,7 @@ class AggConfigs extends IndexedArray {
|
|||
return aggs ? requestValuesAggs.concat(aggs) : requestValuesAggs;
|
||||
}, []);
|
||||
//move metrics to the end
|
||||
return _.sortBy(aggregations, agg => agg.type.type === 'metrics' ? 1 : 0);
|
||||
return _.sortBy(aggregations, agg => agg.type.type === AggGroupNames.Metrics ? 1 : 0);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -18,26 +18,27 @@
|
|||
*/
|
||||
|
||||
import { groupAggregationsBy } from '../default_editor_utils';
|
||||
import { AggGroupNames } from '../agg_groups';
|
||||
|
||||
const aggs = [
|
||||
{
|
||||
title: 'Count',
|
||||
type: 'metrics',
|
||||
type: AggGroupNames.Metrics,
|
||||
subtype: 'Metric Aggregations',
|
||||
},
|
||||
{
|
||||
title: 'Average',
|
||||
type: 'metrics',
|
||||
type: AggGroupNames.Metrics,
|
||||
subtype: 'Metric Aggregations',
|
||||
},
|
||||
{
|
||||
title: 'Cumulative Sum',
|
||||
type: 'metrics',
|
||||
type: AggGroupNames.Metrics,
|
||||
subtype: 'Parent Pipeline Aggregations',
|
||||
},
|
||||
{
|
||||
title: 'Min Bucket',
|
||||
type: 'metrics',
|
||||
type: AggGroupNames.Metrics,
|
||||
subtype: 'Parent Pipeline Aggregations',
|
||||
},
|
||||
{
|
||||
|
@ -56,13 +57,13 @@ describe('Default Editor groupAggregationsBy', () => {
|
|||
it('should return aggs grouped by default type field', () => {
|
||||
const groupedAggs = [
|
||||
{
|
||||
label: 'metrics',
|
||||
label: AggGroupNames.Metrics,
|
||||
options: [
|
||||
{
|
||||
label: 'Average',
|
||||
value: {
|
||||
title: 'Average',
|
||||
type: 'metrics',
|
||||
type: AggGroupNames.Metrics,
|
||||
subtype: 'Metric Aggregations',
|
||||
},
|
||||
},
|
||||
|
@ -70,7 +71,7 @@ describe('Default Editor groupAggregationsBy', () => {
|
|||
label: 'Count',
|
||||
value: {
|
||||
title: 'Count',
|
||||
type: 'metrics',
|
||||
type: AggGroupNames.Metrics,
|
||||
subtype: 'Metric Aggregations',
|
||||
},
|
||||
},
|
||||
|
@ -78,7 +79,7 @@ describe('Default Editor groupAggregationsBy', () => {
|
|||
label: 'Cumulative Sum',
|
||||
value: {
|
||||
title: 'Cumulative Sum',
|
||||
type: 'metrics',
|
||||
type: AggGroupNames.Metrics,
|
||||
subtype: 'Parent Pipeline Aggregations',
|
||||
},
|
||||
},
|
||||
|
@ -87,7 +88,7 @@ describe('Default Editor groupAggregationsBy', () => {
|
|||
label: 'Min Bucket',
|
||||
value: {
|
||||
title: 'Min Bucket',
|
||||
type: 'metrics',
|
||||
type: AggGroupNames.Metrics,
|
||||
subtype: 'Parent Pipeline Aggregations',
|
||||
},
|
||||
},
|
||||
|
@ -126,7 +127,7 @@ describe('Default Editor groupAggregationsBy', () => {
|
|||
label: 'Average',
|
||||
value: {
|
||||
title: 'Average',
|
||||
type: 'metrics',
|
||||
type: AggGroupNames.Metrics,
|
||||
subtype: 'Metric Aggregations',
|
||||
},
|
||||
},
|
||||
|
@ -134,7 +135,7 @@ describe('Default Editor groupAggregationsBy', () => {
|
|||
label: 'Count',
|
||||
value: {
|
||||
title: 'Count',
|
||||
type: 'metrics',
|
||||
type: AggGroupNames.Metrics,
|
||||
subtype: 'Metric Aggregations',
|
||||
},
|
||||
},
|
||||
|
@ -147,7 +148,7 @@ describe('Default Editor groupAggregationsBy', () => {
|
|||
label: 'Cumulative Sum',
|
||||
value: {
|
||||
title: 'Cumulative Sum',
|
||||
type: 'metrics',
|
||||
type: AggGroupNames.Metrics,
|
||||
subtype: 'Parent Pipeline Aggregations',
|
||||
},
|
||||
},
|
||||
|
@ -156,7 +157,7 @@ describe('Default Editor groupAggregationsBy', () => {
|
|||
label: 'Min Bucket',
|
||||
value: {
|
||||
title: 'Min Bucket',
|
||||
type: 'metrics',
|
||||
type: AggGroupNames.Metrics,
|
||||
subtype: 'Parent Pipeline Aggregations',
|
||||
},
|
||||
},
|
||||
|
|
23
src/legacy/ui/public/vis/editors/default/agg_groups.ts
Normal file
23
src/legacy/ui/public/vis/editors/default/agg_groups.ts
Normal file
|
@ -0,0 +1,23 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
export enum AggGroupNames {
|
||||
Buckets = 'buckets',
|
||||
Metrics = 'metrics',
|
||||
}
|
|
@ -0,0 +1,84 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`DefaultEditorAggParams component should init with the default set of params 1`] = `
|
||||
<EuiForm
|
||||
data-test-subj="visAggEditorParams"
|
||||
error={Array []}
|
||||
isInvalid={false}
|
||||
>
|
||||
<DefaultEditorAggSelect
|
||||
aggTypeOptions={Array []}
|
||||
indexPattern={Object {}}
|
||||
isSubAggregation={false}
|
||||
setTouched={[Function]}
|
||||
setValidity={[Function]}
|
||||
setValue={[Function]}
|
||||
showValidation={false}
|
||||
value={
|
||||
Object {
|
||||
"params": Array [
|
||||
Object {
|
||||
"deserialize": [MockFunction],
|
||||
"name": "interval",
|
||||
},
|
||||
],
|
||||
}
|
||||
}
|
||||
/>
|
||||
<DefaultEditorAggParam
|
||||
aggParam={
|
||||
Object {
|
||||
"displayName": "Custom label",
|
||||
"name": "customLabel",
|
||||
"type": "string",
|
||||
}
|
||||
}
|
||||
key="customLabelundefined"
|
||||
onChange={[MockFunction]}
|
||||
setTouched={[Function]}
|
||||
setValidity={[Function]}
|
||||
showValidation={false}
|
||||
subAggParams={
|
||||
Object {
|
||||
"formIsTouched": false,
|
||||
"onAggParamsChange": [MockFunction],
|
||||
"onAggTypeChange": [MockFunction],
|
||||
}
|
||||
}
|
||||
/>
|
||||
<EuiAccordion
|
||||
buttonContent="Advanced"
|
||||
id="advancedAccordion"
|
||||
initialIsOpen={false}
|
||||
paddingSize="none"
|
||||
>
|
||||
<EuiSpacer
|
||||
size="m"
|
||||
/>
|
||||
<DefaultEditorAggParam
|
||||
aggParam={
|
||||
Object {
|
||||
"advanced": true,
|
||||
"name": "json",
|
||||
"type": "json",
|
||||
}
|
||||
}
|
||||
key="jsonundefined"
|
||||
onChange={[MockFunction]}
|
||||
setTouched={[Function]}
|
||||
setValidity={[Function]}
|
||||
showValidation={false}
|
||||
subAggParams={
|
||||
Object {
|
||||
"formIsTouched": false,
|
||||
"onAggParamsChange": [MockFunction],
|
||||
"onAggTypeChange": [MockFunction],
|
||||
}
|
||||
}
|
||||
/>
|
||||
</EuiAccordion>
|
||||
<EuiSpacer
|
||||
size="m"
|
||||
/>
|
||||
</EuiForm>
|
||||
`;
|
|
@ -31,10 +31,7 @@ import { FormattedMessage } from '@kbn/i18n/react';
|
|||
import { i18n } from '@kbn/i18n';
|
||||
import { AggConfig } from 'ui/vis';
|
||||
import { Schema } from '../schemas';
|
||||
|
||||
const GROUP_NAMES = {
|
||||
BUCKETS: 'buckets',
|
||||
};
|
||||
import { AggGroupNames } from '../agg_groups';
|
||||
|
||||
interface DefaultEditorAggAddProps {
|
||||
group?: AggConfig[];
|
||||
|
@ -74,7 +71,7 @@ function DefaultEditorAggAdd({
|
|||
);
|
||||
|
||||
const groupNameLabel =
|
||||
groupName === GROUP_NAMES.BUCKETS
|
||||
groupName === AggGroupNames.Buckets
|
||||
? i18n.translate('common.ui.vis.editors.aggAdd.bucketLabel', { defaultMessage: 'bucket' })
|
||||
: i18n.translate('common.ui.vis.editors.aggAdd.metricLabel', { defaultMessage: 'metric' });
|
||||
|
||||
|
@ -84,7 +81,7 @@ function DefaultEditorAggAdd({
|
|||
};
|
||||
|
||||
return stats.max > stats.count ? (
|
||||
<EuiFlexGroup justifyContent="center">
|
||||
<EuiFlexGroup justifyContent="center" responsive={false}>
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiPopover
|
||||
id={`addGroupButtonPopover_${groupName}`}
|
||||
|
@ -95,14 +92,14 @@ function DefaultEditorAggAdd({
|
|||
closePopover={() => setIsPopoverOpen(false)}
|
||||
>
|
||||
<EuiPopoverTitle>
|
||||
{(groupName !== GROUP_NAMES.BUCKETS || (!stats.count && !stats.deprecate)) && (
|
||||
{(groupName !== AggGroupNames.Buckets || (!stats.count && !stats.deprecate)) && (
|
||||
<FormattedMessage
|
||||
id="common.ui.vis.editors.aggAdd.addGroupButtonLabel"
|
||||
defaultMessage="Add {groupNameLabel}"
|
||||
values={{ groupNameLabel }}
|
||||
/>
|
||||
)}
|
||||
{groupName === GROUP_NAMES.BUCKETS && stats.count > 0 && !stats.deprecate && (
|
||||
{groupName === AggGroupNames.Buckets && stats.count > 0 && !stats.deprecate && (
|
||||
<FormattedMessage
|
||||
id="common.ui.vis.editors.aggAdd.addSubGroupButtonLabel"
|
||||
defaultMessage="Add sub-{groupNameLabel}"
|
||||
|
|
|
@ -0,0 +1,180 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { mount, shallow } from 'enzyme';
|
||||
import { IndexPattern } from 'ui/index_patterns';
|
||||
import { VisState } from 'ui/vis';
|
||||
import { DefaultEditorAggParams, DefaultEditorAggParamsProps } from './default_editor_agg_params';
|
||||
|
||||
const mockEditorConfig = {
|
||||
useNormalizedEsInterval: { hidden: false, fixedValue: false },
|
||||
interval: {
|
||||
hidden: false,
|
||||
help: 'Must be a multiple of rollup configuration interval: 1m',
|
||||
default: '1m',
|
||||
timeBase: '1m',
|
||||
},
|
||||
};
|
||||
|
||||
jest.mock('ui/agg_types', () => ({
|
||||
aggTypes: {
|
||||
byType: {
|
||||
metrics: [],
|
||||
buckets: [],
|
||||
},
|
||||
},
|
||||
}));
|
||||
jest.mock('../../config/editor_config_providers', () => ({
|
||||
editorConfigProviders: {
|
||||
getConfigForAgg: jest.fn(() => mockEditorConfig),
|
||||
},
|
||||
}));
|
||||
jest.mock('./default_editor_agg_params_helper', () => ({
|
||||
getAggParamsToRender: jest.fn(() => ({
|
||||
basic: [
|
||||
{
|
||||
aggParam: {
|
||||
displayName: 'Custom label',
|
||||
name: 'customLabel',
|
||||
type: 'string',
|
||||
},
|
||||
},
|
||||
],
|
||||
advanced: [
|
||||
{
|
||||
aggParam: {
|
||||
advanced: true,
|
||||
name: 'json',
|
||||
type: 'json',
|
||||
},
|
||||
},
|
||||
],
|
||||
})),
|
||||
getAggTypeOptions: jest.fn(() => []),
|
||||
getError: jest.fn((agg, aggIsTooLow) => (aggIsTooLow ? ['error'] : [])),
|
||||
isInvalidParamsTouched: jest.fn(() => false),
|
||||
}));
|
||||
jest.mock('./default_editor_agg_select', () => ({
|
||||
DefaultEditorAggSelect: () => null,
|
||||
}));
|
||||
jest.mock('./default_editor_agg_param', () => ({
|
||||
DefaultEditorAggParam: () => null,
|
||||
}));
|
||||
|
||||
describe('DefaultEditorAggParams component', () => {
|
||||
let onAggParamsChange: jest.Mock;
|
||||
let onAggTypeChange: jest.Mock;
|
||||
let setTouched: jest.Mock;
|
||||
let setValidity: jest.Mock;
|
||||
let intervalDeserialize: jest.Mock;
|
||||
let defaultProps: DefaultEditorAggParamsProps;
|
||||
|
||||
beforeEach(() => {
|
||||
onAggParamsChange = jest.fn();
|
||||
onAggTypeChange = jest.fn();
|
||||
setTouched = jest.fn();
|
||||
setValidity = jest.fn();
|
||||
intervalDeserialize = jest.fn(() => 'deserialized');
|
||||
|
||||
defaultProps = {
|
||||
agg: {
|
||||
type: {
|
||||
params: [{ name: 'interval', deserialize: intervalDeserialize }],
|
||||
},
|
||||
params: {},
|
||||
},
|
||||
groupName: 'metrics',
|
||||
formIsTouched: false,
|
||||
indexPattern: {} as IndexPattern,
|
||||
metricAggs: [],
|
||||
state: {} as VisState,
|
||||
onAggParamsChange,
|
||||
onAggTypeChange,
|
||||
setTouched,
|
||||
setValidity,
|
||||
};
|
||||
});
|
||||
|
||||
it('should init with the default set of params', () => {
|
||||
const comp = shallow(<DefaultEditorAggParams {...defaultProps} />);
|
||||
|
||||
expect(comp).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should reset the validity to true when destroyed', () => {
|
||||
const comp = mount(<DefaultEditorAggParams {...defaultProps} aggIsTooLow={true} />);
|
||||
|
||||
expect(setValidity).lastCalledWith(false);
|
||||
|
||||
comp.unmount();
|
||||
|
||||
expect(setValidity).lastCalledWith(true);
|
||||
});
|
||||
|
||||
it('should set fixed and default values when editorConfig is defined (works in rollup index)', () => {
|
||||
mount(<DefaultEditorAggParams {...defaultProps} />);
|
||||
|
||||
expect(onAggParamsChange).toHaveBeenNthCalledWith(
|
||||
1,
|
||||
defaultProps.agg.params,
|
||||
'useNormalizedEsInterval',
|
||||
false
|
||||
);
|
||||
expect(intervalDeserialize).toHaveBeenCalledWith('1m');
|
||||
expect(onAggParamsChange).toHaveBeenNthCalledWith(
|
||||
2,
|
||||
defaultProps.agg.params,
|
||||
'interval',
|
||||
'deserialized'
|
||||
);
|
||||
});
|
||||
|
||||
it('should call setTouched with false when agg type is changed', () => {
|
||||
const comp = mount(<DefaultEditorAggParams {...defaultProps} />);
|
||||
|
||||
comp.setProps({ agg: { type: { params: [] } } });
|
||||
|
||||
expect(setTouched).lastCalledWith(false);
|
||||
});
|
||||
|
||||
it('should set the validity when it changed', () => {
|
||||
const comp = mount(<DefaultEditorAggParams {...defaultProps} />);
|
||||
|
||||
comp.setProps({ aggIsTooLow: true });
|
||||
|
||||
expect(setValidity).lastCalledWith(false);
|
||||
|
||||
comp.setProps({ aggIsTooLow: false });
|
||||
|
||||
expect(setValidity).lastCalledWith(true);
|
||||
});
|
||||
|
||||
it('should call setTouched when all invalid controls were touched or they are untouched', () => {
|
||||
const comp = mount(<DefaultEditorAggParams {...defaultProps} />);
|
||||
|
||||
comp.setProps({ aggIsTooLow: true });
|
||||
|
||||
expect(setTouched).lastCalledWith(true);
|
||||
|
||||
comp.setProps({ aggIsTooLow: false });
|
||||
|
||||
expect(setTouched).lastCalledWith(false);
|
||||
});
|
||||
});
|
|
@ -46,6 +46,7 @@ import { FixedParam, TimeIntervalParam, EditorParamConfig } from '../../config/t
|
|||
// TODO: Below import is temporary, use `react-use` lib instead.
|
||||
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
|
||||
import { useUnmount } from '../../../../../../../plugins/kibana_react/public/util/use_unmount';
|
||||
import { AggGroupNames } from '../agg_groups';
|
||||
|
||||
const FIXED_VALUE_PROP = 'fixedValue';
|
||||
const DEFAULT_PROP = 'default';
|
||||
|
@ -203,7 +204,7 @@ function DefaultEditorAggParams({
|
|||
indexPattern={indexPattern}
|
||||
value={agg.type}
|
||||
aggTypeOptions={groupedAggTypeOptions}
|
||||
isSubAggregation={aggIndex >= 1 && groupName === 'buckets'}
|
||||
isSubAggregation={aggIndex >= 1 && groupName === AggGroupNames.Buckets}
|
||||
showValidation={formIsTouched || aggType.touched}
|
||||
setValue={value => {
|
||||
onAggTypeChange(agg, value);
|
||||
|
|
|
@ -0,0 +1,230 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import { AggConfig, VisState } from 'ui/vis';
|
||||
import { FieldParamType, AggType } from 'ui/agg_types';
|
||||
import { IndexPattern } from 'ui/index_patterns';
|
||||
import {
|
||||
getAggParamsToRender,
|
||||
getError,
|
||||
getAggTypeOptions,
|
||||
isInvalidParamsTouched,
|
||||
} from './default_editor_agg_params_helper';
|
||||
import { EditorConfig } from '../../config/types';
|
||||
|
||||
jest.mock('ui/agg_types', () => ({
|
||||
aggTypes: {
|
||||
byType: {
|
||||
metrics: [],
|
||||
buckets: [],
|
||||
},
|
||||
},
|
||||
}));
|
||||
jest.mock('../default_editor_utils', () => ({
|
||||
groupAggregationsBy: jest.fn(() => ['indexedFields']),
|
||||
}));
|
||||
|
||||
describe('DefaultEditorAggParams helpers', () => {
|
||||
describe('getAggParamsToRender', () => {
|
||||
let agg: AggConfig;
|
||||
let editorConfig: EditorConfig;
|
||||
const state = {} as VisState;
|
||||
const metricAggs: AggConfig[] = [];
|
||||
const emptyParams = {
|
||||
basic: [],
|
||||
advanced: [],
|
||||
};
|
||||
|
||||
it('should not create any param if they do not have editorComponents', () => {
|
||||
agg = {
|
||||
type: {
|
||||
params: [{ name: 'interval' }],
|
||||
},
|
||||
schema: {},
|
||||
};
|
||||
const params = getAggParamsToRender({ agg, editorConfig, metricAggs, state });
|
||||
|
||||
expect(params).toEqual(emptyParams);
|
||||
});
|
||||
|
||||
it('should not create any param if there is no agg type', () => {
|
||||
agg = {};
|
||||
const params = getAggParamsToRender({ agg, editorConfig, metricAggs, state });
|
||||
|
||||
expect(params).toEqual(emptyParams);
|
||||
});
|
||||
|
||||
it('should not create a param if it is hidden', () => {
|
||||
agg = {
|
||||
type: {
|
||||
params: [{ name: 'interval' }],
|
||||
},
|
||||
};
|
||||
editorConfig = {
|
||||
interval: {
|
||||
hidden: true,
|
||||
},
|
||||
};
|
||||
const params = getAggParamsToRender({ agg, editorConfig, metricAggs, state });
|
||||
|
||||
expect(params).toEqual(emptyParams);
|
||||
});
|
||||
|
||||
it('should skip customLabel param if it is hidden', () => {
|
||||
agg = {
|
||||
type: {
|
||||
params: [{ name: 'customLabel' }],
|
||||
},
|
||||
schema: {
|
||||
hideCustomLabel: true,
|
||||
},
|
||||
};
|
||||
const params = getAggParamsToRender({ agg, editorConfig, metricAggs, state });
|
||||
|
||||
expect(params).toEqual(emptyParams);
|
||||
});
|
||||
|
||||
it('should create a basic params field and orderBy', () => {
|
||||
const filterFieldTypes = ['number', 'boolean', 'date'];
|
||||
agg = {
|
||||
type: {
|
||||
params: [
|
||||
{
|
||||
name: 'field',
|
||||
type: 'field',
|
||||
filterFieldTypes,
|
||||
getAvailableFields: jest.fn((fields: FieldParamType[]) =>
|
||||
fields.filter(({ type }) => filterFieldTypes.includes(type))
|
||||
),
|
||||
editorComponent: jest.fn(),
|
||||
},
|
||||
{
|
||||
name: 'orderBy',
|
||||
editorComponent: jest.fn(),
|
||||
},
|
||||
],
|
||||
},
|
||||
schema: {},
|
||||
getIndexPattern: jest.fn(() => ({
|
||||
fields: [{ name: '@timestamp', type: 'date' }, { name: 'geo_desc', type: 'string' }],
|
||||
})),
|
||||
params: {
|
||||
orderBy: 'orderBy',
|
||||
field: 'field',
|
||||
},
|
||||
};
|
||||
const params = getAggParamsToRender({ agg, editorConfig, metricAggs, state });
|
||||
|
||||
expect(params).toEqual({
|
||||
basic: [
|
||||
{
|
||||
agg,
|
||||
aggParam: agg.type.params[0],
|
||||
editorConfig,
|
||||
indexedFields: ['indexedFields'],
|
||||
paramEditor: agg.type.params[0].editorComponent,
|
||||
metricAggs,
|
||||
state,
|
||||
value: agg.params.field,
|
||||
},
|
||||
{
|
||||
agg,
|
||||
aggParam: agg.type.params[1],
|
||||
editorConfig,
|
||||
indexedFields: [],
|
||||
paramEditor: agg.type.params[1].editorComponent,
|
||||
metricAggs,
|
||||
state,
|
||||
value: agg.params.orderBy,
|
||||
},
|
||||
],
|
||||
advanced: [],
|
||||
});
|
||||
expect(agg.getIndexPattern).toBeCalledTimes(1);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getError', () => {
|
||||
it('should not have any errors', () => {
|
||||
const errors = getError({ schema: { title: 'Split series' } }, false);
|
||||
|
||||
expect(errors).toEqual([]);
|
||||
});
|
||||
|
||||
it('should push an error if an agg is too low', () => {
|
||||
const errors = getError({ schema: { title: 'Split series' } }, true);
|
||||
|
||||
expect(errors).toEqual(['"Split series" aggs must run before all other buckets!']);
|
||||
});
|
||||
|
||||
it('should push an error if a schema is deprecated', () => {
|
||||
const errors = getError({ schema: { title: 'Split series', deprecate: true } }, false);
|
||||
|
||||
expect(errors).toEqual(['"Split series" has been deprecated.']);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getAggTypeOptions', () => {
|
||||
it('should return agg type options grouped by subtype', () => {
|
||||
const indexPattern = {} as IndexPattern;
|
||||
const aggs = getAggTypeOptions({}, indexPattern, 'metrics');
|
||||
|
||||
expect(aggs).toEqual(['indexedFields']);
|
||||
});
|
||||
});
|
||||
|
||||
describe('isInvalidParamsTouched', () => {
|
||||
let aggType: AggType;
|
||||
const aggTypeState = {
|
||||
touched: false,
|
||||
valid: true,
|
||||
};
|
||||
const aggParams = {
|
||||
orderBy: {
|
||||
touched: true,
|
||||
valid: true,
|
||||
},
|
||||
orderAgg: {
|
||||
touched: true,
|
||||
valid: true,
|
||||
},
|
||||
};
|
||||
|
||||
it('should return aggTypeState touched if there is no aggType', () => {
|
||||
const isTouched = isInvalidParamsTouched(aggType, aggTypeState, aggParams);
|
||||
|
||||
expect(isTouched).toBe(aggTypeState.touched);
|
||||
});
|
||||
|
||||
it('should return false if there is no invalid params', () => {
|
||||
aggType = 'type';
|
||||
const isTouched = isInvalidParamsTouched(aggType, aggTypeState, aggParams);
|
||||
|
||||
expect(isTouched).toBeFalsy();
|
||||
});
|
||||
|
||||
it('should return true if there is an invalid param, but not every still touched', () => {
|
||||
aggType = 'type';
|
||||
aggParams.orderAgg.valid = false;
|
||||
const isTouched = isInvalidParamsTouched(aggType, aggTypeState, aggParams);
|
||||
|
||||
expect(isTouched).toBeTruthy();
|
||||
});
|
||||
});
|
||||
});
|
|
@ -51,19 +51,17 @@ function RadiusRatioOptionControl({ editorStateParams, setValue }: AggControlPro
|
|||
|
||||
return (
|
||||
<EuiFormRow fullWidth={true} label={label}>
|
||||
{
|
||||
<EuiRange
|
||||
compressed
|
||||
fullWidth={true}
|
||||
min={1}
|
||||
max={100}
|
||||
value={editorStateParams.radiusRatio || DEFAULT_VALUE}
|
||||
onChange={e => setValue(editorStateParams, PARAM_NAME, parseFloat(e.target.value))}
|
||||
showRange
|
||||
showValue
|
||||
valueAppend="%"
|
||||
/>
|
||||
}
|
||||
<EuiRange
|
||||
compressed
|
||||
fullWidth={true}
|
||||
min={1}
|
||||
max={100}
|
||||
value={editorStateParams.radiusRatio || DEFAULT_VALUE}
|
||||
onChange={e => setValue(editorStateParams, PARAM_NAME, parseFloat(e.target.value))}
|
||||
showRange
|
||||
showValue
|
||||
valueAppend="%"
|
||||
/>
|
||||
</EuiFormRow>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -29,11 +29,12 @@ import _ from 'lodash';
|
|||
import angular from 'angular';
|
||||
import defaultEditorTemplate from './default.html';
|
||||
import { keyCodes } from '@elastic/eui';
|
||||
import { parentPipelineAggHelper } from 'ui/agg_types/metrics/lib/parent_pipeline_agg_helper';
|
||||
import { DefaultEditorSize } from '../../editor_size';
|
||||
|
||||
import { VisEditorTypesRegistryProvider } from '../../../registry/vis_editor_types';
|
||||
import { getVisualizeLoader } from '../../../visualize/loader/visualize_loader';
|
||||
|
||||
import { AggGroupNames } from './agg_groups';
|
||||
|
||||
const defaultEditor = function ($rootScope, $compile) {
|
||||
return class DefaultEditor {
|
||||
|
@ -124,16 +125,10 @@ const defaultEditor = function ($rootScope, $compile) {
|
|||
return $scope.vis.getSerializableState($scope.state);
|
||||
}, function (newState) {
|
||||
$scope.vis.dirty = !angular.equals(newState, $scope.oldState);
|
||||
$scope.responseValueAggs = null;
|
||||
try {
|
||||
$scope.responseValueAggs = $scope.state.aggs.getResponseAggs().filter(function (agg) {
|
||||
return _.get(agg, 'schema.group') === 'metrics';
|
||||
});
|
||||
}
|
||||
// this can fail when the agg.type is changed but the
|
||||
// params have not been set yet. watcher will trigger again
|
||||
// when the params update
|
||||
catch (e) {} // eslint-disable-line no-empty
|
||||
$scope.metricAggs = $scope.state.aggs.getResponseAggs().filter(agg =>
|
||||
_.get(agg, 'schema.group') === AggGroupNames.Metrics);
|
||||
const lastParentPipelineAgg = _.findLast($scope.metricAggs, ({ type }) => type.subtype === parentPipelineAggHelper.subtype);
|
||||
$scope.lastParentPipelineAggTitle = lastParentPipelineAgg && lastParentPipelineAgg.type.title;
|
||||
}, true);
|
||||
|
||||
// fires when visualization state changes, and we need to copy changes to editorState
|
||||
|
|
|
@ -18,12 +18,13 @@
|
|||
*/
|
||||
|
||||
import { AggParam } from '../../../agg_types';
|
||||
import { AggGroupNames } from './agg_groups';
|
||||
|
||||
export interface Schema {
|
||||
aggFilter: string | string[];
|
||||
deprecate: boolean;
|
||||
editor: boolean | string;
|
||||
group: 'metrics' | 'buckets';
|
||||
group: AggGroupNames;
|
||||
max: number;
|
||||
min: number;
|
||||
name: string;
|
||||
|
|
|
@ -22,6 +22,7 @@ import { IndexedArray } from '../../../indexed_array';
|
|||
import { AggParams } from '../../../agg_types/agg_params';
|
||||
import { RowsOrColumnsControl } from './controls/rows_or_columns';
|
||||
import { RadiusRatioOptionControl } from './controls/radius_ratio_option';
|
||||
import { AggGroupNames } from './agg_groups';
|
||||
|
||||
class Schemas {
|
||||
constructor(schemas) {
|
||||
|
@ -45,7 +46,7 @@ class Schemas {
|
|||
_.defaults(schema, {
|
||||
min: 0,
|
||||
max: Infinity,
|
||||
group: 'buckets',
|
||||
group: AggGroupNames.Buckets,
|
||||
title: schema.name,
|
||||
aggFilter: '*',
|
||||
editor: false,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue