diff --git a/src/legacy/ui/public/agg_types/__tests__/directives/auto_select_if_only_one.js b/src/legacy/ui/public/agg_types/__tests__/directives/auto_select_if_only_one.js deleted file mode 100644 index 9e83243811d95..0000000000000 --- a/src/legacy/ui/public/agg_types/__tests__/directives/auto_select_if_only_one.js +++ /dev/null @@ -1,88 +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 expect from '@kbn/expect'; -import ngMock from 'ng_mock'; -import '../../directives/auto_select_if_only_one'; - -describe('Auto-select if only one directive', function () { - let $compile; - let $rootScope; - const zeroOptions = []; - const oneOption = [{ label: 'foo' }]; - const multiOptions = [{ label: 'foo' }, { label: 'bar' }]; - - beforeEach(ngMock.module('kibana')); - - beforeEach(ngMock.inject(function (_$compile_, _$rootScope_) { - $compile = _$compile_; - $rootScope = _$rootScope_; - const html = ''; - $compile(html)($rootScope); - $rootScope.value = null; - })); - - it('should not auto-select if there are no options', function () { - $rootScope.options = zeroOptions; - $rootScope.$digest(); - expect($rootScope.value).to.not.be.ok(); - }); - - it('should not auto-select if there are multiple options', function () { - $rootScope.options = multiOptions; - $rootScope.$digest(); - expect($rootScope.value).to.not.be.ok(); - }); - - it('should auto-select if there is only one option', function () { - $rootScope.options = oneOption; - $rootScope.$digest(); - expect($rootScope.value).to.be(oneOption[0]); - }); - - it('should still auto select if the collection contains 2 items but is filtered to 1', function () { - $rootScope.options = multiOptions; - const html = ''; - $compile(html)($rootScope); - $rootScope.value = null; - $rootScope.$digest(); - - expect($rootScope.value).to.be(multiOptions[1]); - }); - - it('should auto-select if the collection changes', function () { - $rootScope.options = multiOptions; - $rootScope.$digest(); - expect($rootScope.value).to.not.be.ok(); - $rootScope.options = oneOption; - $rootScope.$digest(); - expect($rootScope.value).to.be(oneOption[0]); - }); - - it('should auto-select if the collection is mutated', function () { - $rootScope.options = multiOptions.slice(); - $rootScope.$digest(); - expect($rootScope.value).to.not.be.ok(); - $rootScope.options.length = 1; - $rootScope.$digest(); - expect($rootScope.value).to.be($rootScope.options[0]); - }); -}); diff --git a/src/legacy/ui/public/agg_types/__tests__/metrics/top_hit.js b/src/legacy/ui/public/agg_types/__tests__/metrics/top_hit.js index d206b8f47df9b..3e1446ed1ff97 100644 --- a/src/legacy/ui/public/agg_types/__tests__/metrics/top_hit.js +++ b/src/legacy/ui/public/agg_types/__tests__/metrics/top_hit.js @@ -39,7 +39,7 @@ describe('Top hit metric', function () { params.field = field; } params.sortOrder = { - val: sortOrder + value: sortOrder }; params.aggregate = { val: aggregate diff --git a/src/legacy/ui/public/agg_types/controls/field.tsx b/src/legacy/ui/public/agg_types/controls/field.tsx index 8b6749054e92d..254ae4fa92715 100644 --- a/src/legacy/ui/public/agg_types/controls/field.tsx +++ b/src/legacy/ui/public/agg_types/controls/field.tsx @@ -30,16 +30,21 @@ import { FieldParamType } from '../param_types'; const label = i18n.translate('common.ui.aggTypes.field.fieldLabel', { defaultMessage: 'Field' }); +interface FieldParamEditorProps extends AggParamEditorProps { + customLabel?: string; +} + function FieldParamEditor({ agg, aggParam, + customLabel, indexedFields = [], showValidation, value, setTouched, setValidity, setValue, -}: AggParamEditorProps) { +}: FieldParamEditorProps) { const selectedOptions: ComboBoxGroupedOption[] = value ? [{ label: value.displayName, value }] : []; @@ -79,9 +84,24 @@ function FieldParamEditor({ [isValid] ); + useEffect(() => { + // set field if only one available + if (indexedFields.length !== 1) { + return; + } + + const options = indexedFields[0].options; + + if (!options) { + setValue(indexedFields[0].value); + } else if (options.length === 1) { + setValue(options[0].value); + } + }, []); + return ( - - - - - {{$select.selected.displayName}} - - -
-
-
- - -
- - - -
diff --git a/src/legacy/ui/public/agg_types/filters/sort_prefix_first.js b/src/legacy/ui/public/agg_types/controls/top_sort_field.tsx similarity index 61% rename from src/legacy/ui/public/agg_types/filters/sort_prefix_first.js rename to src/legacy/ui/public/agg_types/controls/top_sort_field.tsx index 553477b61f127..4ee8bb5341e02 100644 --- a/src/legacy/ui/public/agg_types/filters/sort_prefix_first.js +++ b/src/legacy/ui/public/agg_types/controls/top_sort_field.tsx @@ -17,11 +17,18 @@ * under the License. */ -import { uiModules } from '../../modules'; -import { sortPrefixFirst } from '../../utils/sort_prefix_first'; +import React from 'react'; +import { i18n } from '@kbn/i18n'; +import { AggParamEditorProps } from '../../vis/editors/default'; +import { FieldParamType } from '../param_types'; +import { FieldParamEditor } from './field'; -uiModules - .get('kibana') - .filter('sortPrefixFirst', function () { - return sortPrefixFirst; +function TopSortFieldParamEditor(props: AggParamEditorProps) { + const customLabel = i18n.translate('common.ui.aggTypes.sortOnLabel', { + defaultMessage: 'Sort on', }); + + return ; +} + +export { TopSortFieldParamEditor }; diff --git a/src/legacy/ui/public/agg_types/directives/auto_select_if_only_one.js b/src/legacy/ui/public/agg_types/directives/auto_select_if_only_one.js deleted file mode 100644 index f0bc12ceb3032..0000000000000 --- a/src/legacy/ui/public/agg_types/directives/auto_select_if_only_one.js +++ /dev/null @@ -1,36 +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 { uiModules } from '../../modules'; -const module = uiModules.get('kibana'); - -module.directive('autoSelectIfOnlyOne', function () { - return { - restrict: 'A', - require: 'ngModel', - link: function (scope, element, attributes, ngModelCtrl) { - scope.$watchCollection(attributes.autoSelectIfOnlyOne, (options) => { - if (options && options.length === 1) { - ngModelCtrl.$setViewValue(options[0]); - ngModelCtrl.$render(); - } - }); - } - }; -}); diff --git a/src/legacy/ui/public/agg_types/directives/scroll_bottom.js b/src/legacy/ui/public/agg_types/directives/scroll_bottom.js deleted file mode 100644 index 6ffd2b4964e51..0000000000000 --- a/src/legacy/ui/public/agg_types/directives/scroll_bottom.js +++ /dev/null @@ -1,57 +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 { uiModules } from '../../modules'; -const module = uiModules.get('kibana'); - -module.directive('kbnScrollBottom', function () { - return { - restrict: 'A', - link: function ($scope, $element, attr) { - let checkTimer; - - function onScroll() { - const position = $element.scrollTop() + $element.outerHeight(); - const height = $element[0].scrollHeight; - const remaining = height - position; - const margin = 50; - - if (!height || !position) return; - if (remaining <= margin) { - $scope.$evalAsync(attr.kbnScrollBottom); - } - } - - function scheduleCheck() { - if (checkTimer) return; - checkTimer = setTimeout(function () { - checkTimer = null; - onScroll(); - }, 50); - } - - $element.on('scroll', scheduleCheck); - $scope.$on('$destroy', function () { - clearTimeout(checkTimer); - $element.off('scroll', scheduleCheck); - }); - scheduleCheck(); - } - }; -}); diff --git a/src/legacy/ui/public/agg_types/metrics/top_hit.js b/src/legacy/ui/public/agg_types/metrics/top_hit.js index f6594d181a2a4..bedac2a82c157 100644 --- a/src/legacy/ui/public/agg_types/metrics/top_hit.js +++ b/src/legacy/ui/public/agg_types/metrics/top_hit.js @@ -19,11 +19,9 @@ import _ from 'lodash'; import { MetricAggType } from './metric_agg_type'; -import '../directives/auto_select_if_only_one'; -import '../directives/scroll_bottom'; -import '../filters/sort_prefix_first'; -import topSortEditor from '../controls/top_sort.html'; import aggregateAndSizeEditor from '../controls/top_aggregate_and_size.html'; +import { TopSortFieldParamEditor } from '../controls/top_sort_field'; +import { OrderParamEditor } from '../controls/order'; import { aggTypeFieldFilters } from '../param_types/filter'; import { i18n } from '@kbn/i18n'; @@ -57,7 +55,7 @@ export const topHitMetricAgg = new MetricAggType({ const firstPrefixLabel = i18n.translate('common.ui.aggTypes.metrics.topHit.firstPrefixLabel', { defaultMessage: 'First' }); - let prefix = aggConfig.params.sortOrder.val === 'desc' ? lastPrefixLabel : firstPrefixLabel; + let prefix = aggConfig.params.sortOrder.value === 'desc' ? lastPrefixLabel : firstPrefixLabel; if (aggConfig.params.size !== 1) { prefix += ` ${aggConfig.params.size}`; } @@ -171,7 +169,7 @@ export const topHitMetricAgg = new MetricAggType({ { name: 'sortField', type: 'field', - editor: null, + editorComponent: TopSortFieldParamEditor, filterFieldTypes: [ 'number', 'date', 'ip', 'string' ], default: function (agg) { return agg.getIndexPattern().timeFieldName; @@ -180,21 +178,21 @@ export const topHitMetricAgg = new MetricAggType({ }, { name: 'sortOrder', - type: 'optioned', + type: 'select', default: 'desc', - editor: topSortEditor, + editorComponent: OrderParamEditor, options: [ { - display: i18n.translate('common.ui.aggTypes.metrics.topHit.descendingLabel', { + text: i18n.translate('common.ui.aggTypes.metrics.topHit.descendingLabel', { defaultMessage: 'Descending' }), - val: 'desc' + value: 'desc' }, { - display: i18n.translate('common.ui.aggTypes.metrics.topHit.ascendingLabel', { + text: i18n.translate('common.ui.aggTypes.metrics.topHit.ascendingLabel', { defaultMessage: 'Ascending' }), - val: 'asc' + value: 'asc' } ], write(agg, output) { @@ -210,7 +208,7 @@ export const topHitMetricAgg = new MetricAggType({ lang: sortField.lang }, type: sortField.type, - order: sortOrder.val + order: sortOrder.value } } ]; @@ -218,7 +216,7 @@ export const topHitMetricAgg = new MetricAggType({ output.params.sort = [ { [ sortField.name ]: { - order: sortOrder.val + order: sortOrder.value } } ]; diff --git a/src/legacy/ui/public/agg_types/param_types/field.js b/src/legacy/ui/public/agg_types/param_types/field.js index af6cd71b3fdfb..53a861da6a8cd 100644 --- a/src/legacy/ui/public/agg_types/param_types/field.js +++ b/src/legacy/ui/public/agg_types/param_types/field.js @@ -20,9 +20,7 @@ import { sortBy } from 'lodash'; import { SavedObjectNotFound } from '../../errors'; import { FieldParamEditor } from '../controls/field'; -import '../directives/scroll_bottom'; import { BaseParamType } from './base'; -import '../filters/sort_prefix_first'; import { IndexedArray } from '../../indexed_array'; import { toastNotifications } from '../../notify'; import { createLegacyClass } from '../../utils/legacy_class'; diff --git a/test/functional/services/combo_box.ts b/test/functional/services/combo_box.ts index 1c7e942340f87..8bee9ee2863f8 100644 --- a/test/functional/services/combo_box.ts +++ b/test/functional/services/combo_box.ts @@ -52,6 +52,12 @@ export function ComboBoxProvider({ getService, getPageObjects }: FtrProviderCont */ public async setElement(comboBoxElement: WebElementWrapper, value: string): Promise { log.debug(`comboBox.setElement, value: ${value}`); + const isOptionSelected = await this.isOptionSelected(comboBoxElement, value); + + if (isOptionSelected) { + return; + } + await this._filterOptionsList(comboBoxElement, value); await this.openOptionsList(comboBoxElement); @@ -220,6 +226,24 @@ export function ComboBoxProvider({ getService, getPageObjects }: FtrProviderCont await toggleBtn.click(); } } + + /** + * check if option is already selected + * + * @param comboBoxElement + * @param value + */ + public async isOptionSelected( + comboBoxElement: WebElementWrapper, + value: string + ): Promise { + log.debug(`comboBox.isOptionSelected, value: ${value}`); + const selectedOptions = await comboBoxElement.findAllByClassName( + 'euiComboBoxPill', + WAIT_FOR_EXISTS_TIME + ); + return selectedOptions.length === 1 && (await selectedOptions[0].getVisibleText()) === value; + } } return new ComboBox(); diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index e2249fd1a0b4a..57a9137e9e770 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -257,8 +257,6 @@ "common.ui.aggTypes.sizeLabel": "サイズ", "common.ui.aggTypes.sizeTooltip": "トップ K のヒットをリクエスト。複数ヒットは「集約基準」でまとめられます。", "common.ui.aggTypes.sortOnLabel": "並べ替えオン", - "common.ui.aggTypes.sortOnPlaceholder": "フィールドを選択", - "common.ui.aggTypes.sortOnTooltip": "並べ替えオン", "common.ui.aggTypes.string.customLabel": "カスタムラベル", "common.ui.aggTypes.timeInterval.createsTooLargeBucketsTooltip": "この間隔は、選択された時間範囲に表示するには大きすぎるバケットが作成されるため、にスケーリングされています。", "common.ui.aggTypes.timeInterval.createsTooManyBucketsTooltip": "この間隔は選択された時間範囲に表示しきれない数のバケットが作成されるため、にスケーリングされています。", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index c0a438a362ed8..913f51b63a336 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -237,8 +237,6 @@ "common.ui.aggTypes.sizeLabel": "大小", "common.ui.aggTypes.sizeTooltip": "请求排名前 K 的命中。多个命中将通过“聚合对象”组合。", "common.ui.aggTypes.sortOnLabel": "排序依据", - "common.ui.aggTypes.sortOnPlaceholder": "选择字段", - "common.ui.aggTypes.sortOnTooltip": "排序依据", "common.ui.aggTypes.valuesLabel": "值", "common.ui.chrome.bigUrlWarningNotificationMessage": "在“{advancedSettingsLink}”启用“{storeInSessionStorageParam}”选项,或简化屏幕视觉效果。", "common.ui.chrome.bigUrlWarningNotificationMessage.advancedSettingsLinkText": "高级设置",