mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 01:13:23 -04:00
* EUIficate order_agg param editor * Update browser tests * Add types * Update enzyme version in x-pack * Fix functional tests * Changes due to comments * Update_terms_helper.tsx Co-Authored-By: Maryia Lapata <mary.lopato@gmail.com> * Fix code review comments * Update yarn.lock
This commit is contained in:
parent
e10c35156f
commit
8791531896
14 changed files with 394 additions and 247 deletions
|
@ -47,84 +47,8 @@ describe('Terms Agg', function () {
|
|||
});
|
||||
}
|
||||
|
||||
it('defaults to the first metric agg', function () {
|
||||
init({
|
||||
responseValueAggs: [
|
||||
{
|
||||
id: 'agg1',
|
||||
type: {
|
||||
name: 'count'
|
||||
}
|
||||
},
|
||||
{
|
||||
id: 'agg2',
|
||||
type: {
|
||||
name: 'count'
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
expect($rootScope.agg.params.orderBy).to.be('agg1');
|
||||
});
|
||||
|
||||
it('defaults to the first metric agg that is compatible with the terms bucket', function () {
|
||||
init({
|
||||
responseValueAggs: [
|
||||
{
|
||||
id: 'agg1',
|
||||
type: {
|
||||
name: 'top_hits'
|
||||
}
|
||||
},
|
||||
{
|
||||
id: 'agg2',
|
||||
type: {
|
||||
name: 'percentiles'
|
||||
}
|
||||
},
|
||||
{
|
||||
id: 'agg3',
|
||||
type: {
|
||||
name: 'median'
|
||||
}
|
||||
},
|
||||
{
|
||||
id: 'agg4',
|
||||
type: {
|
||||
name: 'std_dev'
|
||||
}
|
||||
},
|
||||
{
|
||||
id: 'agg5',
|
||||
type: {
|
||||
name: 'count'
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
expect($rootScope.agg.params.orderBy).to.be('agg5');
|
||||
});
|
||||
|
||||
it('defaults to the _key metric if no agg is compatible', function () {
|
||||
init({
|
||||
responseValueAggs: [
|
||||
{
|
||||
id: 'agg1',
|
||||
type: {
|
||||
name: 'top_hits'
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
expect($rootScope.agg.params.orderBy).to.be('_key');
|
||||
});
|
||||
|
||||
it('selects _key if there are no metric aggs', function () {
|
||||
init({});
|
||||
expect($rootScope.agg.params.orderBy).to.be('_key');
|
||||
});
|
||||
|
||||
it('selects _key if the selected metric becomes incompatible', function () {
|
||||
// should be rewritten after EUIficate order_agg.html
|
||||
it.skip('selects _key if the selected metric becomes incompatible', function () {
|
||||
init({
|
||||
responseValueAggs: [
|
||||
{
|
||||
|
@ -148,36 +72,8 @@ describe('Terms Agg', function () {
|
|||
expect($rootScope.agg.params.orderBy).to.be('_key');
|
||||
});
|
||||
|
||||
it('selects first metric if it is avg', function () {
|
||||
init({
|
||||
responseValueAggs: [
|
||||
{
|
||||
id: 'agg1',
|
||||
type: {
|
||||
name: 'avg',
|
||||
field: 'bytes'
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
expect($rootScope.agg.params.orderBy).to.be('agg1');
|
||||
});
|
||||
|
||||
it('selects _key if the first metric is avg_bucket', function () {
|
||||
$rootScope.responseValueAggs = [
|
||||
{
|
||||
id: 'agg1',
|
||||
type: {
|
||||
name: 'avg_bucket',
|
||||
metric: 'custom'
|
||||
}
|
||||
}
|
||||
];
|
||||
$rootScope.$digest();
|
||||
expect($rootScope.agg.params.orderBy).to.be('_key');
|
||||
});
|
||||
|
||||
it('selects _key if the selected metric is removed', function () {
|
||||
// should be rewritten after EUIficate order_agg.html
|
||||
it.skip('selects _key if the selected metric is removed', function () {
|
||||
init({
|
||||
responseValueAggs: [
|
||||
{
|
||||
|
|
53
src/legacy/ui/public/agg_types/buckets/_terms_helper.tsx
Normal file
53
src/legacy/ui/public/agg_types/buckets/_terms_helper.tsx
Normal file
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
* 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 } from 'ui/vis';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
|
||||
const aggFilter = [
|
||||
'!top_hits',
|
||||
'!percentiles',
|
||||
'!median',
|
||||
'!std_dev',
|
||||
'!derivative',
|
||||
'!moving_avg',
|
||||
'!serial_diff',
|
||||
'!cumulative_sum',
|
||||
'!avg_bucket',
|
||||
'!max_bucket',
|
||||
'!min_bucket',
|
||||
'!sum_bucket',
|
||||
];
|
||||
|
||||
// Returns true if the agg is compatible with the terms bucket
|
||||
function isCompatibleAgg(agg: AggConfig) {
|
||||
return !aggFilter.includes(`!${agg.type.name}`);
|
||||
}
|
||||
|
||||
function safeMakeLabel(agg: AggConfig) {
|
||||
try {
|
||||
return agg.makeLabel();
|
||||
} catch (e) {
|
||||
return i18n.translate('common.ui.aggTypes.buckets.terms.aggNotValidLabel', {
|
||||
defaultMessage: '- agg not valid -',
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export { aggFilter, isCompatibleAgg, safeMakeLabel };
|
|
@ -17,29 +17,23 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
import _ from 'lodash';
|
||||
import chrome from 'ui/chrome';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { BucketAggType } from './_bucket_agg_type';
|
||||
import { AggConfig } from '../../vis/agg_config';
|
||||
import { Schemas } from '../../vis/editors/default/schemas';
|
||||
import { getRequestInspectorStats, getResponseInspectorStats } from '../../courier/utils/courier_inspector_utils';
|
||||
import { createFilterTerms } from './create_filter/terms';
|
||||
import { wrapWithInlineComp } from './_inline_comp_wrapper';
|
||||
import { buildOtherBucketAgg, mergeOtherBucketAggResponse, updateMissingBucket } from './_terms_other_bucket_helper';
|
||||
import { isStringType, migrateIncludeExcludeFormat } from './migrate_include_exclude_format';
|
||||
import { aggFilter } from './_terms_helper';
|
||||
import orderAggTemplate from '../controls/order_agg.html';
|
||||
import { OrderParamEditor } from '../controls/order';
|
||||
import { OrderAggParamEditor } from '../controls/order_agg';
|
||||
import { SizeParamEditor } from '../controls/size';
|
||||
import { wrapWithInlineComp } from './_inline_comp_wrapper';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
|
||||
import { getRequestInspectorStats, getResponseInspectorStats } from '../../courier/utils/courier_inspector_utils';
|
||||
import { buildOtherBucketAgg, mergeOtherBucketAggResponse, updateMissingBucket } from './_terms_other_bucket_helper';
|
||||
import { MissingBucketParamEditor } from '../controls/missing_bucket';
|
||||
import { OtherBucketParamEditor } from '../controls/other_bucket';
|
||||
import { isStringType, migrateIncludeExcludeFormat } from './migrate_include_exclude_format';
|
||||
|
||||
const aggFilter = [
|
||||
'!top_hits', '!percentiles', '!median', '!std_dev',
|
||||
'!derivative', '!moving_avg', '!serial_diff', '!cumulative_sum',
|
||||
'!avg_bucket', '!max_bucket', '!min_bucket', '!sum_bucket'
|
||||
];
|
||||
|
||||
const orderAggSchema = (new Schemas([
|
||||
{
|
||||
|
@ -120,6 +114,11 @@ export const termsBucketAgg = new BucketAggType({
|
|||
type: 'field',
|
||||
filterFieldTypes: ['number', 'boolean', 'date', 'ip', 'string']
|
||||
},
|
||||
{
|
||||
name: 'orderBy',
|
||||
editorComponent: OrderAggParamEditor,
|
||||
write: () => {} // prevent default write, it's handled by orderAgg
|
||||
},
|
||||
{
|
||||
name: 'orderAgg',
|
||||
type: AggConfig,
|
||||
|
@ -139,33 +138,9 @@ export const termsBucketAgg = new BucketAggType({
|
|||
return orderAgg;
|
||||
},
|
||||
controller: function ($scope) {
|
||||
$scope.safeMakeLabel = function (agg) {
|
||||
try {
|
||||
return agg.makeLabel();
|
||||
} catch (e) {
|
||||
return i18n.translate('common.ui.aggTypes.buckets.terms.aggNotValidLabel', {
|
||||
defaultMessage: '- agg not valid -',
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const INIT = {}; // flag to know when prevOrderBy has changed
|
||||
let prevOrderBy = INIT;
|
||||
|
||||
$scope.$watch('responseValueAggs', updateOrderAgg);
|
||||
$scope.$watch('agg.params.orderBy', updateOrderAgg);
|
||||
|
||||
// Returns true if the agg is not compatible with the terms bucket
|
||||
$scope.rejectAgg = function rejectAgg(agg) {
|
||||
return aggFilter.includes(`!${agg.type.name}`);
|
||||
};
|
||||
|
||||
$scope.$watch('agg.params.field.type', (type) => {
|
||||
if (type !== 'string') {
|
||||
$scope.agg.params.missingBucket = false;
|
||||
}
|
||||
});
|
||||
|
||||
function updateOrderAgg() {
|
||||
// abort until we get the responseValueAggs
|
||||
if (!$scope.responseValueAggs) return;
|
||||
|
@ -174,27 +149,9 @@ export const termsBucketAgg = new BucketAggType({
|
|||
const orderBy = params.orderBy;
|
||||
const paramDef = agg.type.params.byName.orderAgg;
|
||||
|
||||
// setup the initial value of orderBy
|
||||
if (!orderBy && prevOrderBy === INIT) {
|
||||
let respAgg = _($scope.responseValueAggs).filter((agg) => !$scope.rejectAgg(agg)).first();
|
||||
if (!respAgg) {
|
||||
respAgg = { id: '_key' };
|
||||
}
|
||||
params.orderBy = respAgg.id;
|
||||
return;
|
||||
}
|
||||
|
||||
// track the previous value
|
||||
prevOrderBy = orderBy;
|
||||
|
||||
// we aren't creating a custom aggConfig
|
||||
if (!orderBy || orderBy !== 'custom') {
|
||||
params.orderAgg = null;
|
||||
// ensure that orderBy is set to a valid agg
|
||||
const respAgg = _($scope.responseValueAggs).filter((agg) => !$scope.rejectAgg(agg)).find({ id: orderBy });
|
||||
if (!respAgg) {
|
||||
params.orderBy = '_key';
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -256,22 +213,18 @@ export const termsBucketAgg = new BucketAggType({
|
|||
value: 'asc'
|
||||
}
|
||||
],
|
||||
write: _.noop // prevent default write, it's handled by orderAgg
|
||||
write: () => {} // prevent default write, it's handled by orderAgg
|
||||
},
|
||||
{
|
||||
name: 'size',
|
||||
editorComponent: wrapWithInlineComp(SizeParamEditor),
|
||||
default: 5
|
||||
},
|
||||
{
|
||||
name: 'orderBy',
|
||||
write: _.noop // prevent default write, it's handled by orderAgg
|
||||
},
|
||||
{
|
||||
name: 'otherBucket',
|
||||
default: false,
|
||||
editorComponent: OtherBucketParamEditor,
|
||||
write: _.noop,
|
||||
write: () => {},
|
||||
},
|
||||
{
|
||||
name: 'otherBucketLabel',
|
||||
|
@ -283,13 +236,13 @@ export const termsBucketAgg = new BucketAggType({
|
|||
defaultMessage: 'Label for other bucket',
|
||||
}),
|
||||
shouldShow: agg => agg.params.otherBucket,
|
||||
write: _.noop,
|
||||
write: () => {},
|
||||
},
|
||||
{
|
||||
name: 'missingBucket',
|
||||
default: false,
|
||||
editorComponent: MissingBucketParamEditor,
|
||||
write: _.noop,
|
||||
write: () => {},
|
||||
},
|
||||
{
|
||||
name: 'missingBucketLabel',
|
||||
|
@ -303,7 +256,7 @@ export const termsBucketAgg = new BucketAggType({
|
|||
defaultMessage: 'Label for missing values',
|
||||
}),
|
||||
shouldShow: agg => agg.params.missingBucket,
|
||||
write: _.noop,
|
||||
write: () => {},
|
||||
},
|
||||
{
|
||||
name: 'exclude',
|
||||
|
|
|
@ -17,13 +17,24 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import React, { useEffect } from 'react';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { AggParamEditorProps } from 'ui/vis/editors/default';
|
||||
import { SwitchParamEditor } from './switch';
|
||||
import { isStringType } from '../buckets/migrate_include_exclude_format';
|
||||
|
||||
function MissingBucketParamEditor(props: AggParamEditorProps<boolean>) {
|
||||
const fieldTypeIsNotString = !isStringType(props.agg);
|
||||
|
||||
useEffect(
|
||||
() => {
|
||||
if (fieldTypeIsNotString) {
|
||||
props.setValue(false);
|
||||
}
|
||||
},
|
||||
[fieldTypeIsNotString]
|
||||
);
|
||||
|
||||
return (
|
||||
<SwitchParamEditor
|
||||
dataTestSubj="missingBucketSwitch"
|
||||
|
@ -37,7 +48,7 @@ function MissingBucketParamEditor(props: AggParamEditorProps<boolean>) {
|
|||
'If not in the top N, and you enable "Group other values in separate bucket", ' +
|
||||
'Elasticsearch adds the missing values to the "other" bucket.',
|
||||
})}
|
||||
disabled={!isStringType(props.agg)}
|
||||
disabled={fieldTypeIsNotString}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
|
|
|
@ -1,49 +1,12 @@
|
|||
<div ng-controller="aggParam.controller">
|
||||
<div class="form-group">
|
||||
<label
|
||||
for="visEditorOrder{{agg.id}}"
|
||||
i18n-id="common.ui.aggTypes.orderAgg.orderByLabel"
|
||||
i18n-default-message="Order By"
|
||||
></label>
|
||||
<select
|
||||
id="visEditorOrder{{agg.id}}"
|
||||
name="orderBy"
|
||||
ng-model="agg.params.orderBy"
|
||||
required
|
||||
class="form-control">
|
||||
<option
|
||||
ng-repeat="respAgg in responseValueAggs track by respAgg.id"
|
||||
value="{{respAgg.id}}"
|
||||
data-test-subj="visEditorOrder{{agg.id}}-{{respAgg.id}}"
|
||||
ng-disabled="rejectAgg(respAgg)"
|
||||
ng-selected="agg.params.orderBy === respAgg.id"
|
||||
i18n-id="common.ui.aggTypes.orderAgg.metricLabel"
|
||||
i18n-default-message="metric: {metric}"
|
||||
i18n-values="{ metric: safeMakeLabel(respAgg) }"
|
||||
>
|
||||
</option>
|
||||
<option
|
||||
value="custom"
|
||||
data-test-subj="visEditorOrder{{agg.id}}-custom"
|
||||
ng-selected="agg.params.orderBy === 'custom'"
|
||||
i18n-id="common.ui.aggTypes.orderAgg.customMetricLabel"
|
||||
i18n-default-message="Custom Metric"
|
||||
></option>
|
||||
<option
|
||||
value="_key"
|
||||
data-test-subj="visEditorOrder{{agg.id}}-key"
|
||||
ng-selected="agg.params.orderBy === '_key'"
|
||||
i18n-id="common.ui.aggTypes.orderAgg.alphabeticalLabel"
|
||||
i18n-default-message="Alphabetical"
|
||||
></option>
|
||||
</select>
|
||||
</div>
|
||||
<div ng-show="agg.params.orderAgg" class="visEditorAgg__subAgg">
|
||||
<vis-editor-agg-params
|
||||
index-pattern="agg.getIndexPattern()"
|
||||
agg="agg.params.orderAgg"
|
||||
ng-if="agg.params.orderAgg"
|
||||
group-name="'metrics'">
|
||||
</vis-editor-agg-params>
|
||||
</div>
|
||||
<div
|
||||
ng-controller="aggParam.controller"
|
||||
ng-show="agg.params.orderAgg"
|
||||
class="visEditorAgg__subAgg"
|
||||
>
|
||||
<vis-editor-agg-params
|
||||
index-pattern="agg.getIndexPattern()"
|
||||
agg="agg.params.orderAgg"
|
||||
ng-if="agg.params.orderAgg"
|
||||
group-name="'metrics'">
|
||||
</vis-editor-agg-params>
|
||||
</div>
|
||||
|
|
167
src/legacy/ui/public/agg_types/controls/order_agg.test.tsx
Normal file
167
src/legacy/ui/public/agg_types/controls/order_agg.test.tsx
Normal file
|
@ -0,0 +1,167 @@
|
|||
/*
|
||||
* 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 } from 'enzyme';
|
||||
import { OrderAggParamEditor } from './order_agg';
|
||||
|
||||
describe('OrderAggParamEditor component', () => {
|
||||
let setValue: jest.Mock;
|
||||
let setValidity: jest.Mock;
|
||||
let setTouched: jest.Mock;
|
||||
let defaultProps: any;
|
||||
|
||||
beforeEach(() => {
|
||||
setValue = jest.fn();
|
||||
setValidity = jest.fn();
|
||||
setTouched = jest.fn();
|
||||
|
||||
defaultProps = {
|
||||
agg: {},
|
||||
aggParam: {
|
||||
name: 'orderAgg',
|
||||
type: '',
|
||||
},
|
||||
editorConfig: {},
|
||||
value: '',
|
||||
showValidation: false,
|
||||
setValue,
|
||||
setValidity,
|
||||
setTouched,
|
||||
};
|
||||
});
|
||||
|
||||
it('defaults to the first metric agg after init', () => {
|
||||
const responseValueAggs = [
|
||||
{
|
||||
id: 'agg1',
|
||||
type: {
|
||||
name: 'count',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'agg2',
|
||||
type: {
|
||||
name: 'count',
|
||||
},
|
||||
},
|
||||
];
|
||||
const props = { ...defaultProps, responseValueAggs };
|
||||
|
||||
mount(<OrderAggParamEditor {...props} />);
|
||||
|
||||
expect(setValue).toHaveBeenCalledWith('agg1');
|
||||
});
|
||||
|
||||
it('defaults to the first metric agg that is compatible with the terms bucket', () => {
|
||||
const responseValueAggs = [
|
||||
{
|
||||
id: 'agg1',
|
||||
type: {
|
||||
name: 'top_hits',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'agg2',
|
||||
type: {
|
||||
name: 'percentiles',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'agg3',
|
||||
type: {
|
||||
name: 'median',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'agg4',
|
||||
type: {
|
||||
name: 'std_dev',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'agg5',
|
||||
type: {
|
||||
name: 'count',
|
||||
},
|
||||
},
|
||||
];
|
||||
const props = { ...defaultProps, responseValueAggs };
|
||||
|
||||
mount(<OrderAggParamEditor {...props} />);
|
||||
|
||||
expect(setValue).toHaveBeenCalledWith('agg5');
|
||||
});
|
||||
|
||||
it('defaults to the _key metric if no agg is compatible', () => {
|
||||
const responseValueAggs = [
|
||||
{
|
||||
id: 'agg1',
|
||||
type: {
|
||||
name: 'top_hits',
|
||||
},
|
||||
},
|
||||
];
|
||||
const props = { ...defaultProps, responseValueAggs };
|
||||
|
||||
mount(<OrderAggParamEditor {...props} />);
|
||||
|
||||
expect(setValue).toHaveBeenCalledWith('_key');
|
||||
});
|
||||
|
||||
it('selects first metric if it is avg', () => {
|
||||
const responseValueAggs = [
|
||||
{
|
||||
id: 'agg1',
|
||||
type: {
|
||||
name: 'avg',
|
||||
field: 'bytes',
|
||||
},
|
||||
},
|
||||
];
|
||||
const props = { ...defaultProps, responseValueAggs };
|
||||
|
||||
mount(<OrderAggParamEditor {...props} />);
|
||||
|
||||
expect(setValue).toHaveBeenCalledWith('agg1');
|
||||
});
|
||||
|
||||
it('selects _key if the first metric is avg_bucket', () => {
|
||||
const responseValueAggs = [
|
||||
{
|
||||
id: 'agg1',
|
||||
type: {
|
||||
name: 'avg_bucket',
|
||||
metric: 'custom',
|
||||
},
|
||||
},
|
||||
];
|
||||
const props = { ...defaultProps, responseValueAggs };
|
||||
|
||||
mount(<OrderAggParamEditor {...props} />);
|
||||
|
||||
expect(setValue).toHaveBeenCalledWith('_key');
|
||||
});
|
||||
|
||||
it('selects _key if there are no metric aggs', () => {
|
||||
mount(<OrderAggParamEditor {...defaultProps} />);
|
||||
|
||||
expect(setValue).toHaveBeenCalledWith('_key');
|
||||
});
|
||||
});
|
119
src/legacy/ui/public/agg_types/controls/order_agg.tsx
Normal file
119
src/legacy/ui/public/agg_types/controls/order_agg.tsx
Normal file
|
@ -0,0 +1,119 @@
|
|||
/*
|
||||
* 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, { useEffect } from 'react';
|
||||
import { EuiFormRow, EuiSelect } from '@elastic/eui';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { AggParamEditorProps } from 'ui/vis/editors/default';
|
||||
import { safeMakeLabel, isCompatibleAgg } from '../buckets/_terms_helper';
|
||||
|
||||
function OrderAggParamEditor({
|
||||
agg,
|
||||
value,
|
||||
showValidation,
|
||||
setValue,
|
||||
setValidity,
|
||||
setTouched,
|
||||
responseValueAggs,
|
||||
}: AggParamEditorProps<string>) {
|
||||
const label = i18n.translate('common.ui.aggTypes.orderAgg.orderByLabel', {
|
||||
defaultMessage: 'Order by',
|
||||
});
|
||||
const isValid = !!value;
|
||||
|
||||
useEffect(
|
||||
() => {
|
||||
setValidity(isValid);
|
||||
},
|
||||
[isValid]
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
// setup the initial value of orderBy
|
||||
if (!value) {
|
||||
let respAgg = { id: '_key' };
|
||||
|
||||
if (responseValueAggs) {
|
||||
respAgg = responseValueAggs.filter(isCompatibleAgg)[0] || respAgg;
|
||||
}
|
||||
|
||||
setValue(respAgg.id);
|
||||
}
|
||||
}, []);
|
||||
|
||||
useEffect(
|
||||
() => {
|
||||
if (responseValueAggs && value && value !== 'custom') {
|
||||
// ensure that orderBy is set to a valid agg
|
||||
const respAgg = responseValueAggs
|
||||
.filter(isCompatibleAgg)
|
||||
.find(aggregation => aggregation.id === value);
|
||||
|
||||
if (!respAgg) {
|
||||
setValue('_key');
|
||||
}
|
||||
}
|
||||
},
|
||||
[responseValueAggs]
|
||||
);
|
||||
|
||||
const defaultOptions = [
|
||||
{
|
||||
text: i18n.translate('common.ui.aggTypes.orderAgg.customMetricLabel', {
|
||||
defaultMessage: 'Custom metric',
|
||||
}),
|
||||
value: 'custom',
|
||||
},
|
||||
{
|
||||
text: i18n.translate('common.ui.aggTypes.orderAgg.alphabeticalLabel', {
|
||||
defaultMessage: 'Alphabetical',
|
||||
}),
|
||||
value: '_key',
|
||||
},
|
||||
];
|
||||
|
||||
const options = responseValueAggs
|
||||
? responseValueAggs.map(respAgg => ({
|
||||
text: i18n.translate('common.ui.aggTypes.orderAgg.metricLabel', {
|
||||
defaultMessage: 'Metric: {metric}',
|
||||
values: {
|
||||
metric: safeMakeLabel(respAgg),
|
||||
},
|
||||
}),
|
||||
value: respAgg.id,
|
||||
disabled: !isCompatibleAgg(respAgg),
|
||||
}))
|
||||
: [];
|
||||
|
||||
return (
|
||||
<EuiFormRow label={label} fullWidth={true} isInvalid={showValidation ? !isValid : false}>
|
||||
<EuiSelect
|
||||
options={[...options, ...defaultOptions]}
|
||||
value={value}
|
||||
onChange={ev => setValue(ev.target.value)}
|
||||
fullWidth={true}
|
||||
isInvalid={showValidation ? !isValid : false}
|
||||
onBlur={setTouched}
|
||||
data-test-subj={`visEditorOrderBy${agg.id}`}
|
||||
/>
|
||||
</EuiFormRow>
|
||||
);
|
||||
}
|
||||
|
||||
export { OrderAggParamEditor };
|
|
@ -34,6 +34,7 @@ uiModules
|
|||
['onChange', { watchDepth: 'reference' }],
|
||||
['setTouched', { watchDepth: 'reference' }],
|
||||
['setValidity', { watchDepth: 'reference' }],
|
||||
['responseValueAggs', { watchDepth: 'reference' }],
|
||||
'showValidation',
|
||||
'value',
|
||||
'visName'
|
||||
|
@ -69,6 +70,7 @@ uiModules
|
|||
on-change="onChange"
|
||||
set-touched="setTouched"
|
||||
set-validity="setValidity"
|
||||
response-value-aggs="responseValueAggs"
|
||||
></vis-agg-param-react-wrapper>`;
|
||||
}
|
||||
|
||||
|
|
|
@ -35,6 +35,7 @@ export interface AggParamCommonProps<T> {
|
|||
indexedFields?: FieldParamType[];
|
||||
showValidation: boolean;
|
||||
value: T;
|
||||
responseValueAggs: AggConfig[] | null;
|
||||
visName: string;
|
||||
setValidity(isValid: boolean): void;
|
||||
setTouched(): void;
|
||||
|
|
|
@ -86,7 +86,7 @@ export default function ({ getService, getPageObjects }) {
|
|||
const expectedChartData = ['png 1,373', 'php 445', 'jpg 9,109', 'gif 918', 'css 2,159'];
|
||||
|
||||
log.debug('Order By = Term');
|
||||
await PageObjects.visualize.selectOrderBy('_key');
|
||||
await PageObjects.visualize.selectOrderByMetric(2, '_key');
|
||||
await PageObjects.visualize.clickGo();
|
||||
await retry.try(async function () {
|
||||
const data = await PageObjects.visualize.getLineChartData();
|
||||
|
|
|
@ -49,7 +49,7 @@ export default function ({ getService, getPageObjects }) {
|
|||
await retry.try(async function tryingForTime() {
|
||||
await PageObjects.visualize.selectField(termsField);
|
||||
});
|
||||
await PageObjects.visualize.selectOrderBy('_key');
|
||||
await PageObjects.visualize.selectOrderByMetric(2, '_key');
|
||||
await PageObjects.visualize.clickGo();
|
||||
});
|
||||
|
||||
|
|
|
@ -550,21 +550,6 @@ export function VisualizePageProvider({ getService, getPageObjects, updateBaseli
|
|||
await find.clickByCssSelector(`#${id} > option[label="${fieldValue}"]`);
|
||||
}
|
||||
|
||||
async orderBy(fieldValue) {
|
||||
await find.clickByCssSelector(
|
||||
'select.form-control.ng-pristine.ng-valid.ng-untouched.ng-valid-required[ng-model="agg.params.orderBy"]'
|
||||
+ `option:contains("${fieldValue}")`);
|
||||
}
|
||||
|
||||
async selectOrderBy(fieldValue) {
|
||||
await find.clickByCssSelector(`select[name="orderBy"] > option[value="${fieldValue}"]`);
|
||||
}
|
||||
|
||||
async getInputTypeParam(paramName) {
|
||||
const input = await find.byCssSelector(`input[ng-model="agg.params.${paramName}"]`);
|
||||
return await input.getProperty('value');
|
||||
}
|
||||
|
||||
async getInterval() {
|
||||
return await comboBox.getComboBoxSelectedOptions('visEditorInterval');
|
||||
}
|
||||
|
@ -1237,13 +1222,14 @@ export function VisualizePageProvider({ getService, getPageObjects, updateBaseli
|
|||
return errorMessage;
|
||||
}
|
||||
|
||||
async selectSortMetric(agg, metric) {
|
||||
const sortMetric = await find.byCssSelector(`[data-test-subj="visEditorOrder${agg}-${metric}"]`);
|
||||
return await sortMetric.click();
|
||||
async selectOrderByMetric(agg, metric) {
|
||||
const sortSelect = await testSubjects.find(`visEditorOrderBy${agg}`);
|
||||
const sortMetric = await sortSelect.findByCssSelector(`option[value="${metric}"]`);
|
||||
await sortMetric.click();
|
||||
}
|
||||
|
||||
async selectCustomSortMetric(agg, metric, field) {
|
||||
await this.selectSortMetric(agg, 'custom');
|
||||
await this.selectOrderByMetric(agg, 'custom');
|
||||
await this.selectAggregation(metric, 'groupName');
|
||||
await this.selectField(field, 'groupName');
|
||||
}
|
||||
|
|
|
@ -230,9 +230,7 @@
|
|||
"common.ui.aggTypes.onlyRequestDataAroundMapExtentLabel": "マップ範囲のデータのみリクエストしてください",
|
||||
"common.ui.aggTypes.onlyRequestDataAroundMapExtentTooltip": "Apply geo_bounding_box filter aggregation to narrow the subject area to the map view box with collar",
|
||||
"common.ui.aggTypes.orderAgg.alphabeticalLabel": "アルファベット順",
|
||||
"common.ui.aggTypes.orderAgg.customMetricLabel": "カスタムメトリック",
|
||||
"common.ui.aggTypes.orderAgg.metricLabel": "メトリック: {metric}",
|
||||
"common.ui.aggTypes.orderAgg.orderByLabel": "並び順",
|
||||
"common.ui.aggTypes.orderLabel": "順序",
|
||||
"common.ui.aggTypes.otherBucket.groupValuesLabel": "他の値を別のバケットにまとめる",
|
||||
"common.ui.aggTypes.otherBucket.groupValuesTooltip": "トップ N 以外の値はこのバケットにまとめられます。欠測値があるドキュメントを含めるには、「欠測値を表示」を有効にしてください。",
|
||||
|
|
|
@ -230,9 +230,7 @@
|
|||
"common.ui.aggTypes.onlyRequestDataAroundMapExtentLabel": "仅请求地图范围的数据",
|
||||
"common.ui.aggTypes.onlyRequestDataAroundMapExtentTooltip": "应用 geo_bounding_box 筛选聚合以使用领口将主题区域缩小到地图视图框",
|
||||
"common.ui.aggTypes.orderAgg.alphabeticalLabel": "按字母顺序",
|
||||
"common.ui.aggTypes.orderAgg.customMetricLabel": "定制指标",
|
||||
"common.ui.aggTypes.orderAgg.metricLabel": "指标:{metric}",
|
||||
"common.ui.aggTypes.orderAgg.orderByLabel": "排序依据",
|
||||
"common.ui.aggTypes.orderLabel": "顺序",
|
||||
"common.ui.aggTypes.otherBucket.groupValuesLabel": "在单独的存储桶中对其他值分组",
|
||||
"common.ui.aggTypes.otherBucket.groupValuesTooltip": "不在排名前 N 中的值将在此存储桶中进行分组。要包括缺失值的文档,请启用“显示缺失值”。",
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue