mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 09:48:58 -04:00
* EUIficate agg-select * Improve validation; update TS * Apply styles for helpLink * Fix unit test * Update functional tests * Adjust comboBox service to chose the item where the text mates exactly * Update vis page object * Add default value for agg * Move aggs grouping function to a separate file * Use labelAppend prop for help link node * Add watcher for aggType to manage to discard changes * Add default value for agg type title * Fix defining selected option when aggType is defined * Fix validation issues * Remove a bootstrap specific class * Change css selector in test * Update according to SASS guidelines * Update functinal comboBox service * Added check for undefined * Add jsdoc for groupAggregationsBy function * Add unit tests for groupAggregationsBy * Move setValidity invocation to DefaultEditorAggSelect component * Wrap setValidity into useEffect due to react warning when select is cleaned at the first time * Move help link definition to select component
This commit is contained in:
parent
4f7ba1111e
commit
1e56476510
13 changed files with 538 additions and 37 deletions
|
@ -26,8 +26,8 @@ function StringParamEditor({ agg, aggParam, value, setValue }: AggParamEditorPro
|
|||
return (
|
||||
<EuiFormRow
|
||||
label={aggParam.displayName || aggParam.name}
|
||||
className="form-group"
|
||||
fullWidth={true}
|
||||
className="visEditorSidebar__aggParamFormRow"
|
||||
>
|
||||
<EuiFieldText
|
||||
value={value || ''}
|
||||
|
|
|
@ -0,0 +1,194 @@
|
|||
/*
|
||||
* 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 { groupAggregationsBy } from '../default_editor_utils';
|
||||
|
||||
const aggs = [
|
||||
{
|
||||
title: 'Count',
|
||||
type: 'metrics',
|
||||
subtype: 'Metric Aggregations',
|
||||
},
|
||||
{
|
||||
title: 'Average',
|
||||
type: 'metrics',
|
||||
subtype: 'Metric Aggregations',
|
||||
},
|
||||
{
|
||||
title: 'Cumulative Sum',
|
||||
type: 'metrics',
|
||||
subtype: 'Parent Pipeline Aggregations',
|
||||
},
|
||||
{
|
||||
title: 'Min Bucket',
|
||||
type: 'metrics',
|
||||
subtype: 'Parent Pipeline Aggregations',
|
||||
},
|
||||
{
|
||||
title: 'Sub string agg',
|
||||
type: 'string',
|
||||
subtype: 'Sub-String aggregations',
|
||||
},
|
||||
{
|
||||
title: 'String agg',
|
||||
type: 'string',
|
||||
subtype: 'String aggregations',
|
||||
},
|
||||
];
|
||||
|
||||
describe('Default Editor groupAggregationsBy', () => {
|
||||
it('should return aggs grouped by default type field', () => {
|
||||
const groupedAggs = [
|
||||
{
|
||||
label: 'metrics',
|
||||
options: [
|
||||
{
|
||||
label: 'Average',
|
||||
value: {
|
||||
title: 'Average',
|
||||
type: 'metrics',
|
||||
subtype: 'Metric Aggregations',
|
||||
},
|
||||
},
|
||||
{
|
||||
label: 'Count',
|
||||
value: {
|
||||
title: 'Count',
|
||||
type: 'metrics',
|
||||
subtype: 'Metric Aggregations',
|
||||
},
|
||||
},
|
||||
{
|
||||
label: 'Cumulative Sum',
|
||||
value: {
|
||||
title: 'Cumulative Sum',
|
||||
type: 'metrics',
|
||||
subtype: 'Parent Pipeline Aggregations',
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
label: 'Min Bucket',
|
||||
value: {
|
||||
title: 'Min Bucket',
|
||||
type: 'metrics',
|
||||
subtype: 'Parent Pipeline Aggregations',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
label: 'string',
|
||||
options: [
|
||||
{
|
||||
label: 'String agg',
|
||||
value: {
|
||||
title: 'String agg',
|
||||
type: 'string',
|
||||
subtype: 'String aggregations',
|
||||
},
|
||||
},
|
||||
{
|
||||
label: 'Sub string agg',
|
||||
value: {
|
||||
title: 'Sub string agg',
|
||||
type: 'string',
|
||||
subtype: 'Sub-String aggregations',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
expect(groupAggregationsBy(aggs)).toEqual(groupedAggs);
|
||||
});
|
||||
it('should return aggs grouped by subtype field', () => {
|
||||
const groupedAggs = [
|
||||
{
|
||||
label: 'Metric Aggregations',
|
||||
options: [
|
||||
{
|
||||
label: 'Average',
|
||||
value: {
|
||||
title: 'Average',
|
||||
type: 'metrics',
|
||||
subtype: 'Metric Aggregations',
|
||||
},
|
||||
},
|
||||
{
|
||||
label: 'Count',
|
||||
value: {
|
||||
title: 'Count',
|
||||
type: 'metrics',
|
||||
subtype: 'Metric Aggregations',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
label: 'Parent Pipeline Aggregations',
|
||||
options: [
|
||||
{
|
||||
label: 'Cumulative Sum',
|
||||
value: {
|
||||
title: 'Cumulative Sum',
|
||||
type: 'metrics',
|
||||
subtype: 'Parent Pipeline Aggregations',
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
label: 'Min Bucket',
|
||||
value: {
|
||||
title: 'Min Bucket',
|
||||
type: 'metrics',
|
||||
subtype: 'Parent Pipeline Aggregations',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
label: 'String aggregations',
|
||||
options: [
|
||||
{
|
||||
label: 'String agg',
|
||||
value: {
|
||||
title: 'String agg',
|
||||
type: 'string',
|
||||
subtype: 'String aggregations',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
label: 'Sub-String aggregations',
|
||||
options: [
|
||||
{
|
||||
label: 'Sub string agg',
|
||||
value: {
|
||||
title: 'Sub string agg',
|
||||
type: 'string',
|
||||
subtype: 'Sub-String aggregations',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
expect(groupAggregationsBy(aggs, 'subtype')).toEqual(groupedAggs);
|
||||
});
|
||||
});
|
|
@ -20,3 +20,7 @@
|
|||
.visEditorAggSelect__helpLink {
|
||||
@include euiFontSizeXS;
|
||||
}
|
||||
|
||||
.visEditorAggSelect__formRow {
|
||||
margin-bottom: $euiSizeS;
|
||||
}
|
||||
|
|
|
@ -222,5 +222,6 @@
|
|||
}
|
||||
|
||||
.visEditorSidebar__aggParamFormRow {
|
||||
margin-top: $euiSizeS;
|
||||
margin-bottom: $euiSizeS;
|
||||
}
|
||||
|
|
|
@ -53,7 +53,7 @@ uiModules
|
|||
* @return {[type]} [description]
|
||||
*/
|
||||
$scope.describe = function () {
|
||||
if (!$scope.agg.type.makeLabel) return '';
|
||||
if (!$scope.agg.type || !$scope.agg.type.makeLabel) return '';
|
||||
const label = $scope.agg.type.makeLabel($scope.agg);
|
||||
return label ? label : '';
|
||||
};
|
||||
|
|
|
@ -33,4 +33,11 @@
|
|||
</p>
|
||||
</div>
|
||||
|
||||
<vis-agg-select
|
||||
agg="agg"
|
||||
is-sub-aggregation="isSubAggregation"
|
||||
agg-type-options="groupedAggTypeOptions"
|
||||
ng-model="_internalNgModelStateAggType"
|
||||
/>
|
||||
|
||||
<!-- schema editors get added down here: aggSelect.html, agg_types/controls/*.html -->
|
||||
|
|
|
@ -18,18 +18,18 @@
|
|||
*/
|
||||
|
||||
import $ from 'jquery';
|
||||
import { get, has } from 'lodash';
|
||||
import { get } from 'lodash';
|
||||
import { aggTypes } from '../../../agg_types';
|
||||
import { aggTypeFilters } from '../../../agg_types/filter';
|
||||
import { aggTypeFieldFilters } from '../../../agg_types/param_types/filter';
|
||||
import { documentationLinks } from '../../../documentation_links/documentation_links';
|
||||
import '../../../filters/match_any';
|
||||
import { uiModules } from '../../../modules';
|
||||
import { editorConfigProviders } from '../config/editor_config_providers';
|
||||
import advancedToggleHtml from './advanced_toggle.html';
|
||||
import './agg_param';
|
||||
import './agg_select';
|
||||
import aggParamsTemplate from './agg_params.html';
|
||||
import aggSelectHtml from './agg_select.html';
|
||||
import { groupAggregationsBy } from './default_editor_utils';
|
||||
|
||||
uiModules
|
||||
.get('app/visualize')
|
||||
|
@ -56,6 +56,15 @@ uiModules
|
|||
updateEditorConfig('default');
|
||||
});
|
||||
|
||||
$scope.groupedAggTypeOptions = groupAggregationsBy($scope.aggTypeOptions, 'subtype');
|
||||
$scope.isSubAggregation = $scope.$index >= 1 && $scope.groupName === 'buckets';
|
||||
|
||||
$scope.onAggTypeChange = (agg, value) => {
|
||||
if (agg.type !== value) {
|
||||
agg.type = value;
|
||||
}
|
||||
};
|
||||
|
||||
$scope.onParamChange = (agg, paramName, value) => {
|
||||
if(agg.params[paramName] !== value) {
|
||||
agg.params[paramName] = value;
|
||||
|
@ -91,9 +100,6 @@ uiModules
|
|||
// controls for the agg, which is why they are first
|
||||
addSchemaEditor();
|
||||
|
||||
// allow selection of an aggregation
|
||||
addAggSelector();
|
||||
|
||||
function addSchemaEditor() {
|
||||
const $schemaEditor = $('<div>').addClass('schemaEditors form-group').appendTo($el);
|
||||
|
||||
|
@ -103,21 +109,12 @@ uiModules
|
|||
}
|
||||
}
|
||||
|
||||
function addAggSelector() {
|
||||
const $aggSelect = $(aggSelectHtml).appendTo($el);
|
||||
$compile($aggSelect)($scope);
|
||||
}
|
||||
|
||||
// params for the selected agg, these are rebuilt every time the agg in $aggSelect changes
|
||||
let $aggParamEditors; // container for agg type param editors
|
||||
let $aggParamEditorsScope;
|
||||
|
||||
function updateAggParamEditor() {
|
||||
updateEditorConfig();
|
||||
$scope.aggHelpLink = null;
|
||||
if (has($scope, 'agg.type.name')) {
|
||||
$scope.aggHelpLink = get(documentationLinks, ['aggs', $scope.agg.type.name]);
|
||||
}
|
||||
|
||||
if ($aggParamEditors) {
|
||||
$aggParamEditors.remove();
|
||||
|
|
91
src/legacy/ui/public/vis/editors/default/agg_select.js
Normal file
91
src/legacy/ui/public/vis/editors/default/agg_select.js
Normal file
|
@ -0,0 +1,91 @@
|
|||
/*
|
||||
* 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 'ngreact';
|
||||
import { uiModules } from '../../../modules';
|
||||
import { DefaultEditorAggSelect } from './components/default_editor_agg_select';
|
||||
import { wrapInI18nContext } from 'ui/i18n';
|
||||
|
||||
uiModules
|
||||
.get('app/visualize', ['react'])
|
||||
.directive('visAggSelectReactWrapper', reactDirective => reactDirective(wrapInI18nContext(DefaultEditorAggSelect), [
|
||||
['agg', { watchDepth: 'collection' }],
|
||||
['aggTypeOptions', { watchDepth: 'collection' }],
|
||||
['setValue', { watchDepth: 'reference' }],
|
||||
['setTouched', { watchDepth: 'reference' }],
|
||||
['setValidity', { watchDepth: 'reference' }],
|
||||
'value',
|
||||
'isSubAggregation',
|
||||
'aggHelpLink',
|
||||
'isSelectInvalid'
|
||||
]))
|
||||
.directive('visAggSelect', function () {
|
||||
return {
|
||||
restrict: 'E',
|
||||
scope: true,
|
||||
require: '^ngModel',
|
||||
template: function () {
|
||||
return `<vis-agg-select-react-wrapper
|
||||
agg="agg"
|
||||
value="paramValue"
|
||||
set-value="onChange"
|
||||
is-sub-aggregation="isSubAggregation"
|
||||
agg-help-link="aggHelpLink"
|
||||
agg-type-options="aggTypeOptions"
|
||||
is-select-invalid="isSelectInvalid"
|
||||
set-touched="setTouched"
|
||||
set-validity="setValidity"
|
||||
></vis-agg-select-react-wrapper>`;
|
||||
},
|
||||
link: {
|
||||
pre: function ($scope, $el, attr) {
|
||||
$scope.$bind('agg', attr.agg);
|
||||
$scope.$bind('isSubAggregation', attr.isSubAggregation);
|
||||
$scope.$bind('aggTypeOptions', attr.aggTypeOptions);
|
||||
},
|
||||
post: function ($scope, $el, attr, ngModelCtrl) {
|
||||
$scope.$watch('agg.type', (value) => {
|
||||
// Whenever the value of the parameter changed (e.g. by a reset or actually by calling)
|
||||
// we store the new value in $scope.paramValue, which will be passed as a new value to the react component.
|
||||
$scope.paramValue = value;
|
||||
});
|
||||
|
||||
$scope.onChange = (value) => {
|
||||
// This is obviously not a good code quality, but without using scope binding (which we can't see above)
|
||||
// to bind function values, this is right now the best temporary fix, until all of this will be gone.
|
||||
$scope.$parent.onAggTypeChange($scope.agg, value);
|
||||
|
||||
ngModelCtrl.$setDirty();
|
||||
};
|
||||
|
||||
$scope.setTouched = () => {
|
||||
ngModelCtrl.$setTouched();
|
||||
$scope.isSelectInvalid = !$scope.paramValue;
|
||||
};
|
||||
|
||||
$scope.setValidity = (isValid) => {
|
||||
// The field will be marked as invalid when the value is empty and the field is touched.
|
||||
$scope.isSelectInvalid = ngModelCtrl.$touched ? !isValid : false;
|
||||
// Since aggType is required field, the form should become invalid when the aggregation field is set to empty.
|
||||
ngModelCtrl.$setValidity(`agg${$scope.agg.id}`, isValid);
|
||||
};
|
||||
}
|
||||
}
|
||||
};
|
||||
});
|
|
@ -0,0 +1,124 @@
|
|||
/*
|
||||
* 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 { get, has, isFunction } from 'lodash';
|
||||
import React, { useEffect } from 'react';
|
||||
|
||||
import { EuiComboBox, EuiFormRow, EuiLink } from '@elastic/eui';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { FormattedMessage } from '@kbn/i18n/react';
|
||||
import { AggType } from 'ui/agg_types';
|
||||
import { AggConfig } from 'ui/vis/agg_config';
|
||||
import { documentationLinks } from '../../../../documentation_links/documentation_links';
|
||||
import { ComboBoxGroupedOption } from '../default_editor_utils';
|
||||
|
||||
interface DefaultEditorAggSelectProps {
|
||||
agg: AggConfig;
|
||||
value: AggType;
|
||||
setValue: (aggType: AggType) => void;
|
||||
aggTypeOptions: AggType[];
|
||||
isSubAggregation: boolean;
|
||||
isSelectInvalid: boolean;
|
||||
setTouched: () => void;
|
||||
setValidity: (isValid: boolean) => void;
|
||||
}
|
||||
|
||||
function DefaultEditorAggSelect({
|
||||
agg = {},
|
||||
value = { title: '' },
|
||||
setValue,
|
||||
aggTypeOptions = [],
|
||||
isSelectInvalid,
|
||||
isSubAggregation,
|
||||
setTouched,
|
||||
setValidity,
|
||||
}: DefaultEditorAggSelectProps) {
|
||||
const isAggTypeDefined = value && Boolean(value.title);
|
||||
const selectedOptions: ComboBoxGroupedOption[] = isAggTypeDefined
|
||||
? [{ label: value.title, value }]
|
||||
: [];
|
||||
|
||||
const label = isSubAggregation ? (
|
||||
<FormattedMessage
|
||||
id="common.ui.vis.defaultEditor.aggSelect.subAggregationLabel"
|
||||
defaultMessage="Sub aggregation"
|
||||
/>
|
||||
) : (
|
||||
<FormattedMessage
|
||||
id="common.ui.vis.defaultEditor.aggSelect.aggregationLabel"
|
||||
defaultMessage="Aggregation"
|
||||
/>
|
||||
);
|
||||
|
||||
let aggHelpLink = null;
|
||||
if (has(agg, 'type.name')) {
|
||||
aggHelpLink = get(documentationLinks, ['aggs', agg.type.name]);
|
||||
}
|
||||
|
||||
const helpLink = isAggTypeDefined && aggHelpLink && (
|
||||
<EuiLink
|
||||
href={aggHelpLink}
|
||||
target="_blank"
|
||||
rel="noopener"
|
||||
className="visEditorAggSelect__helpLink"
|
||||
>
|
||||
<FormattedMessage
|
||||
id="common.ui.vis.defaultEditor.aggSelect.helpLinkLabel"
|
||||
defaultMessage="{aggTitle} help"
|
||||
values={{ aggTitle: isAggTypeDefined ? value.title : '' }}
|
||||
/>
|
||||
</EuiLink>
|
||||
);
|
||||
|
||||
useEffect(
|
||||
() => {
|
||||
if (isFunction(setValidity)) {
|
||||
setValidity(isAggTypeDefined);
|
||||
}
|
||||
},
|
||||
[isAggTypeDefined]
|
||||
);
|
||||
|
||||
return (
|
||||
<EuiFormRow
|
||||
label={label}
|
||||
labelAppend={helpLink}
|
||||
isInvalid={isSelectInvalid}
|
||||
fullWidth={true}
|
||||
className="visEditorAggSelect__formRow"
|
||||
>
|
||||
<EuiComboBox
|
||||
placeholder={i18n.translate('common.ui.vis.defaultEditor.aggSelect.selectAggPlaceholder', {
|
||||
defaultMessage: 'Select an aggregation…',
|
||||
})}
|
||||
id={`visDefaultEditorAggSelect${agg.id}`}
|
||||
options={aggTypeOptions}
|
||||
selectedOptions={selectedOptions}
|
||||
singleSelection={{ asPlainText: true }}
|
||||
onChange={options => setValue(get(options, '0.value'))}
|
||||
data-test-subj="defaultEditorAggSelect"
|
||||
isClearable={false}
|
||||
isInvalid={isSelectInvalid}
|
||||
fullWidth={true}
|
||||
onBlur={() => setTouched()}
|
||||
/>
|
||||
</EuiFormRow>
|
||||
);
|
||||
}
|
||||
|
||||
export { DefaultEditorAggSelect };
|
|
@ -0,0 +1,79 @@
|
|||
/*
|
||||
* 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 { EuiComboBoxOptionProps } from '@elastic/eui';
|
||||
import { AggType } from 'ui/agg_types';
|
||||
|
||||
export type ComboBoxGroupedOption = EuiComboBoxOptionProps & {
|
||||
value?: AggType;
|
||||
options?: ComboBoxGroupedOption[];
|
||||
};
|
||||
|
||||
/**
|
||||
* Groups and sorts alphabetically aggregation objects and returns an array of options that are compatible with EuiComboBox options.
|
||||
*
|
||||
* @param aggs An array of aggregations that will be grouped.
|
||||
* @param groupBy A field name which aggregations is grouped by.
|
||||
*
|
||||
* @returns An array of grouped and sorted alphabetically `aggs` that are compatible with EuiComboBox options. If `aggs` is not an array, the function returns an ampry array.
|
||||
*/
|
||||
function groupAggregationsBy(
|
||||
aggs: AggType[],
|
||||
groupBy: string = 'type'
|
||||
): ComboBoxGroupedOption[] | [] {
|
||||
if (!Array.isArray(aggs)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const groupedOptions: ComboBoxGroupedOption[] = aggs.reduce((array: AggType[], type: AggType) => {
|
||||
const group = array.find(element => element.label === type[groupBy]);
|
||||
const option = {
|
||||
label: type.title,
|
||||
value: type,
|
||||
};
|
||||
|
||||
if (group) {
|
||||
group.options.push(option);
|
||||
} else {
|
||||
array.push({ label: type[groupBy], options: [option] });
|
||||
}
|
||||
|
||||
return array;
|
||||
}, []);
|
||||
|
||||
groupedOptions.sort(sortByLabel);
|
||||
|
||||
groupedOptions.forEach((group: ComboBoxGroupedOption) => {
|
||||
if (Array.isArray(group.options)) {
|
||||
group.options.sort(sortByLabel);
|
||||
}
|
||||
});
|
||||
|
||||
if (groupedOptions.length === 1 && !groupedOptions[0].label) {
|
||||
return groupedOptions[0].options || [];
|
||||
}
|
||||
|
||||
return groupedOptions;
|
||||
}
|
||||
|
||||
function sortByLabel(a: { label: string }, b: { label: string }) {
|
||||
return a.label.toLowerCase().localeCompare(b.label.toLowerCase());
|
||||
}
|
||||
|
||||
export { groupAggregationsBy };
|
|
@ -34,6 +34,7 @@ export function VisualizePageProvider({ getService, getPageObjects, updateBaseli
|
|||
const globalNav = getService('globalNav');
|
||||
const PageObjects = getPageObjects(['common', 'header']);
|
||||
const defaultFindTimeout = config.get('timeouts.find');
|
||||
const comboBox = getService('comboBox');
|
||||
|
||||
class VisualizePage {
|
||||
|
||||
|
@ -431,19 +432,14 @@ export function VisualizePageProvider({ getService, getPageObjects, updateBaseli
|
|||
}
|
||||
|
||||
async selectAggregation(myString, groupName = 'buckets', childAggregationType = null) {
|
||||
const selector = `
|
||||
const comboBoxElement = await find.byCssSelector(`
|
||||
[group-name="${groupName}"]
|
||||
vis-editor-agg-params:not(.ng-hide)
|
||||
${childAggregationType ? `vis-editor-agg-params[group-name="'${childAggregationType}'"]:not(.ng-hide)` : ''}
|
||||
.agg-select
|
||||
`;
|
||||
[data-test-subj="defaultEditorAggSelect"]
|
||||
`);
|
||||
|
||||
await retry.try(async () => {
|
||||
await find.clickByCssSelector(selector);
|
||||
const input = await find.byCssSelector(`${selector} input.ui-select-search`);
|
||||
await input.type(myString);
|
||||
await input.pressKeys(browser.keys.RETURN);
|
||||
});
|
||||
await comboBox.setElement(comboBoxElement, myString);
|
||||
await PageObjects.common.sleep(500);
|
||||
}
|
||||
|
||||
|
@ -481,13 +477,12 @@ export function VisualizePageProvider({ getService, getPageObjects, updateBaseli
|
|||
// So to modify a metric or aggregation tests need to keep track of the
|
||||
// order they are added.
|
||||
await this.toggleOpenEditor(index);
|
||||
const aggSelect = await find
|
||||
.byCssSelector(`#visAggEditorParams${index} div [data-test-subj="visEditorAggSelect"] div span[aria-label="Select box activate"]`);
|
||||
// open agg selection list
|
||||
await aggSelect.click();
|
||||
|
||||
// select our agg
|
||||
const aggItem = await find.byCssSelector(`[data-test-subj="${agg}"]`);
|
||||
await aggItem.click();
|
||||
const aggSelect = await find
|
||||
.byCssSelector(`#visAggEditorParams${index} [data-test-subj="defaultEditorAggSelect"]`);
|
||||
await comboBox.setElement(aggSelect, agg);
|
||||
|
||||
const fieldSelect = await find
|
||||
.byCssSelector(`#visAggEditorParams${index} > [agg-param="agg.type.params[0]"] > div > div > div.ui-select-match > span`);
|
||||
// open field selection list
|
||||
|
|
|
@ -36,7 +36,20 @@ export function ComboBoxProvider({ getService }) {
|
|||
log.debug(`comboBox.setElement, value: ${value}`);
|
||||
await this._filterOptionsList(comboBoxElement, value);
|
||||
await this.openOptionsList(comboBoxElement);
|
||||
await find.clickByCssSelector('.euiComboBoxOption');
|
||||
|
||||
if (value !== undefined) {
|
||||
const options = await find.allByCssSelector(`.euiComboBoxOption[title^="${value.toString().trim()}"]`);
|
||||
|
||||
if (options.length > 0) {
|
||||
await options[0].click();
|
||||
} else {
|
||||
// if it doesn't find the item which text starts with value, it will choose the first option
|
||||
await find.clickByCssSelector('.euiComboBoxOption');
|
||||
}
|
||||
} else {
|
||||
await find.clickByCssSelector('.euiComboBoxOption');
|
||||
}
|
||||
|
||||
await this.closeOptionsList(comboBoxElement);
|
||||
}
|
||||
|
||||
|
|
|
@ -641,10 +641,6 @@
|
|||
"common.ui.vis.editors.aggGroups.metricsText": "指标",
|
||||
"common.ui.vis.editors.aggParams.errors.aggWrongRunOrderErrorMessage": "“{schema}” 聚合必须在所有其他存储桶之前运行!",
|
||||
"common.ui.vis.editors.aggParams.errors.schemaIsDeprecatedErrorMessage": "‘’{schema}”已弃用。",
|
||||
"common.ui.vis.editors.aggSelect.aggregationLabel": "聚合",
|
||||
"common.ui.vis.editors.aggSelect.helpLinkLabel": "{aggTitle} 帮助",
|
||||
"common.ui.vis.editors.aggSelect.selectAggPlaceholder": "选择聚合",
|
||||
"common.ui.vis.editors.aggSelect.subAggregationLabel": "子聚合",
|
||||
"common.ui.vis.editors.howToModifyScreenReaderPriorityDescription": "使用此按钮上的向上和向下键上移和下移此聚合的优先级顺序。",
|
||||
"common.ui.vis.editors.resizeAriaLabels": "按向左/向右键以调整编辑器的大小",
|
||||
"common.ui.vis.editors.sidebar.applyChangesAriaLabel": "使用您的更改更新可视化",
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue