From 628c1988586513aa509f410ef7b9380aed83ae2c Mon Sep 17 00:00:00 2001 From: sulemanof Date: Tue, 14 May 2019 18:13:46 +0300 Subject: [PATCH 01/11] EUIficate top_aggregate_and_size param editor --- .../agg_types/buckets/_inline_comp_wrapper.js | 2 +- .../ui/public/agg_types/controls/order.tsx | 3 +- .../ui/public/agg_types/controls/size.tsx | 28 +++- .../agg_types/controls/top_aggregate.tsx | 133 ++++++++++++++++++ .../ui/public/agg_types/metrics/top_hit.js | 45 +++--- .../public/agg_types/param_types/select.d.ts | 8 +- .../public/vis/editors/default/agg_param.js | 2 + .../editors/default/agg_param_editor_props.ts | 2 + 8 files changed, 184 insertions(+), 39 deletions(-) create mode 100644 src/legacy/ui/public/agg_types/controls/top_aggregate.tsx diff --git a/src/legacy/ui/public/agg_types/buckets/_inline_comp_wrapper.js b/src/legacy/ui/public/agg_types/buckets/_inline_comp_wrapper.js index 8091d8e28dde5..0c8161035adcf 100644 --- a/src/legacy/ui/public/agg_types/buckets/_inline_comp_wrapper.js +++ b/src/legacy/ui/public/agg_types/buckets/_inline_comp_wrapper.js @@ -21,7 +21,7 @@ import React from 'react'; const wrapWithInlineComp = Component => props => (
- +
); export { wrapWithInlineComp }; diff --git a/src/legacy/ui/public/agg_types/controls/order.tsx b/src/legacy/ui/public/agg_types/controls/order.tsx index 0042c3d97d0ba..a122ad4c0543d 100644 --- a/src/legacy/ui/public/agg_types/controls/order.tsx +++ b/src/legacy/ui/public/agg_types/controls/order.tsx @@ -30,6 +30,7 @@ function OrderParamEditor({ setValue, setValidity, setTouched, + wrappedWithInlineComp, }: AggParamEditorProps & SelectParamEditorProps) { const label = i18n.translate('common.ui.aggTypes.orderLabel', { defaultMessage: 'Order', @@ -48,7 +49,7 @@ function OrderParamEditor({ label={label} fullWidth={true} isInvalid={showValidation ? !isValid : false} - className="visEditorSidebar__aggParamFormRow" + className={wrappedWithInlineComp ? undefined : 'visEditorSidebar__aggParamFormRow'} > ) { - const label = i18n.translate('common.ui.aggTypes.sizeLabel', { - defaultMessage: 'Size', - }); + const label = ( + <> + + {agg.type.name === 'top_hits' ? ( + <> + {' '} + + + ) : null} + + ); const isValid = Number(value) > 0; useEffect( @@ -47,7 +65,7 @@ function SizeParamEditor({ label={label} fullWidth={true} isInvalid={showValidation ? !isValid : false} - className="visEditorSidebar__aggParamFormRow" + className={wrappedWithInlineComp ? undefined : 'visEditorSidebar__aggParamFormRow'} > & SelectParamEditorProps) { + const label = ( + <> + {' '} + + + ); + + const fieldType = agg.params.field && agg.params.field.type; + const emptyValue = { text: '', value: 'EMPTY_VALUE', disabled: true, hidden: true }; + const filteredOptions = aggParam.options.raw + .filter( + option => + agg.params.field && option.isCompatibleType(fieldType) && option.isCompatibleVis(visName) + ) + .map(({ text, value: val }) => ({ text, value: val })) + .sort((a, b) => { + if (a.text < b.text) { + return -1; + } + if (a.text > b.text) { + return 1; + } + + return 0; + }); + const isValid = !!value; + const isFirstRun = useRef(true); + + const options = [emptyValue, ...filteredOptions]; + + useEffect( + () => { + setValidity(isValid); + }, + [isValid] + ); + + useEffect( + () => { + if (isFirstRun.current) { + isFirstRun.current = false; + return; + } + + if (options.length === 2) { + setValue(aggParam.options.byValue[filteredOptions[0].value]); + } else if (value) { + setValue(undefined); + } + }, + [fieldType, visName] + ); + + const handleChange = (event: React.ChangeEvent) => { + if (event.target.value === emptyValue.value) { + setValue(undefined); + } else { + setValue(aggParam.options.byValue[event.target.value]); + } + }; + + return ( + + + + ); +} + +export { TopAggregateParamEditor }; 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..96254c56cedaa 100644 --- a/src/legacy/ui/public/agg_types/metrics/top_hit.js +++ b/src/legacy/ui/public/agg_types/metrics/top_hit.js @@ -23,9 +23,11 @@ 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 { aggTypeFieldFilters } from '../param_types/filter'; import { i18n } from '@kbn/i18n'; +import { wrapWithInlineComp } from '../buckets/_inline_comp_wrapper'; +import { SizeParamEditor } from '../controls/size'; +import { TopAggregateParamEditor } from '../controls/top_aggregate'; const isNumber = function (type) { return type === 'number'; @@ -97,47 +99,47 @@ export const topHitMetricAgg = new MetricAggType({ }, { name: 'aggregate', - type: 'optioned', - editor: aggregateAndSizeEditor, + type: 'select', + editorComponent: wrapWithInlineComp(TopAggregateParamEditor), options: [ { - display: i18n.translate('common.ui.aggTypes.metrics.topHit.minLabel', { + text: i18n.translate('common.ui.aggTypes.metrics.topHit.minLabel', { defaultMessage: 'Min' }), isCompatibleType: isNumber, isCompatibleVis: _.constant(true), disabled: true, - val: 'min' + value: 'min' }, { - display: i18n.translate('common.ui.aggTypes.metrics.topHit.maxLabel', { + text: i18n.translate('common.ui.aggTypes.metrics.topHit.maxLabel', { defaultMessage: 'Max' }), isCompatibleType: isNumber, isCompatibleVis: _.constant(true), disabled: true, - val: 'max' + value: 'max' }, { - display: i18n.translate('common.ui.aggTypes.metrics.topHit.sumLabel', { + text: i18n.translate('common.ui.aggTypes.metrics.topHit.sumLabel', { defaultMessage: 'Sum' }), isCompatibleType: isNumber, isCompatibleVis: _.constant(true), disabled: true, - val: 'sum' + value: 'sum' }, { - display: i18n.translate('common.ui.aggTypes.metrics.topHit.averageLabel', { + text: i18n.translate('common.ui.aggTypes.metrics.topHit.averageLabel', { defaultMessage: 'Average' }), isCompatibleType: isNumber, isCompatibleVis: _.constant(true), disabled: true, - val: 'average' + value: 'average' }, { - display: i18n.translate('common.ui.aggTypes.metrics.topHit.concatenateLabel', { + text: i18n.translate('common.ui.aggTypes.metrics.topHit.concatenateLabel', { defaultMessage: 'Concatenate' }), isCompatibleType: _.constant(true), @@ -145,27 +147,14 @@ export const topHitMetricAgg = new MetricAggType({ return name === 'metric' || name === 'table'; }, disabled: true, - val: 'concat' + value: 'concat' } ], - controller: function ($scope) { - $scope.options = []; - $scope.$watchGroup([ 'vis.type.name', 'agg.params.field.type' ], function ([ visName, fieldType ]) { - if (fieldType && visName) { - $scope.options = _.filter($scope.aggParam.options, option => { - return option.isCompatibleVis(visName) && option.isCompatibleType(fieldType); - }); - if ($scope.options.length === 1) { - $scope.agg.params.aggregate = $scope.options[0]; - } - } - }); - }, write: _.noop }, { name: 'size', - editor: null, // size setting is done together with the aggregation setting + editorComponent: wrapWithInlineComp(SizeParamEditor), default: 1 }, { @@ -247,7 +236,7 @@ export const topHitMetricAgg = new MetricAggType({ if (!_.compact(values).length) { return null; } - switch (agg.params.aggregate.val) { + switch (agg.params.aggregate.value) { case 'max': return _.max(values); case 'min': diff --git a/src/legacy/ui/public/agg_types/param_types/select.d.ts b/src/legacy/ui/public/agg_types/param_types/select.d.ts index 06aeb0b37e066..d2f26b34ade2e 100644 --- a/src/legacy/ui/public/agg_types/param_types/select.d.ts +++ b/src/legacy/ui/public/agg_types/param_types/select.d.ts @@ -24,15 +24,15 @@ interface SelectValueProp { text: string; } -interface SelectOptions extends IndexedArray { +interface SelectOptions extends IndexedArray { byValue: { - [key: string]: SelectValueProp; + [key: string]: T; }; } -interface SelectParamEditorProps { +interface SelectParamEditorProps { aggParam: { - options: SelectOptions; + options: SelectOptions; }; } diff --git a/src/legacy/ui/public/vis/editors/default/agg_param.js b/src/legacy/ui/public/vis/editors/default/agg_param.js index 2bb6f4087580d..137a8195bd34d 100644 --- a/src/legacy/ui/public/vis/editors/default/agg_param.js +++ b/src/legacy/ui/public/vis/editors/default/agg_param.js @@ -35,6 +35,7 @@ uiModules ['setValidity', { watchDepth: 'reference' }], 'showValidation', 'value', + 'visName' ])) .directive('visAggParamEditor', function (config) { return { @@ -62,6 +63,7 @@ uiModules indexed-fields="indexedFields" show-validation="showValidation" value="paramValue" + visName="vis.type.name" on-change="onChange" set-touched="setTouched" set-validity="setValidity" diff --git a/src/legacy/ui/public/vis/editors/default/agg_param_editor_props.ts b/src/legacy/ui/public/vis/editors/default/agg_param_editor_props.ts index 43e3edbc6bf13..85ce0c4ef040d 100644 --- a/src/legacy/ui/public/vis/editors/default/agg_param_editor_props.ts +++ b/src/legacy/ui/public/vis/editors/default/agg_param_editor_props.ts @@ -33,6 +33,8 @@ export interface AggParamEditorProps { indexedFields?: FieldParamType[]; showValidation: boolean; value: T; + visName: string; + wrappedWithInlineComp?: boolean; setValidity(isValid: boolean): void; setValue(value?: T): void; setTouched(): void; From b1732c7c438afa2cec9668359c63c9e63ef50ff6 Mon Sep 17 00:00:00 2001 From: sulemanof Date: Wed, 15 May 2019 16:03:09 +0300 Subject: [PATCH 02/11] Remove template --- .../controls/top_aggregate_and_size.html | 43 ------------------- 1 file changed, 43 deletions(-) delete mode 100644 src/legacy/ui/public/agg_types/controls/top_aggregate_and_size.html diff --git a/src/legacy/ui/public/agg_types/controls/top_aggregate_and_size.html b/src/legacy/ui/public/agg_types/controls/top_aggregate_and_size.html deleted file mode 100644 index c96f7570081e1..0000000000000 --- a/src/legacy/ui/public/agg_types/controls/top_aggregate_and_size.html +++ /dev/null @@ -1,43 +0,0 @@ -
-
- - - -
-
- - - -
-
From a2a9ec66d90e8260e3ae71ebcf90a3a4d825d65b Mon Sep 17 00:00:00 2001 From: sulemanof Date: Wed, 15 May 2019 16:45:34 +0300 Subject: [PATCH 03/11] Change typescript interfaces --- .../editors/default/agg_param_editor_props.ts | 10 +++++++--- .../editors/default/agg_param_react_wrapper.tsx | 16 ++-------------- 2 files changed, 9 insertions(+), 17 deletions(-) diff --git a/src/legacy/ui/public/vis/editors/default/agg_param_editor_props.ts b/src/legacy/ui/public/vis/editors/default/agg_param_editor_props.ts index 85ce0c4ef040d..e81eb0fee167b 100644 --- a/src/legacy/ui/public/vis/editors/default/agg_param_editor_props.ts +++ b/src/legacy/ui/public/vis/editors/default/agg_param_editor_props.ts @@ -26,7 +26,8 @@ import { EditorConfig } from '../config/types'; // as there is currently a bug on babel typescript transform plugin for it // https://github.com/babel/babel/issues/7641 // -export interface AggParamEditorProps { + +export interface AggParamCommonProps { agg: AggConfig; aggParam: AggParam; editorConfig: EditorConfig; @@ -34,8 +35,11 @@ export interface AggParamEditorProps { showValidation: boolean; value: T; visName: string; - wrappedWithInlineComp?: boolean; setValidity(isValid: boolean): void; - setValue(value?: T): void; setTouched(): void; } + +export interface AggParamEditorProps extends AggParamCommonProps { + wrappedWithInlineComp?: boolean; + setValue(value?: T): void; +} diff --git a/src/legacy/ui/public/vis/editors/default/agg_param_react_wrapper.tsx b/src/legacy/ui/public/vis/editors/default/agg_param_react_wrapper.tsx index 86c73ba9b94dc..eb694385f3be8 100644 --- a/src/legacy/ui/public/vis/editors/default/agg_param_react_wrapper.tsx +++ b/src/legacy/ui/public/vis/editors/default/agg_param_react_wrapper.tsx @@ -19,23 +19,11 @@ import React, { useEffect } from 'react'; -import { AggParam } from '../../../agg_types'; -import { FieldParamType } from '../../../agg_types/param_types'; -import { AggConfig } from '../../agg_config'; -import { AggParamEditorProps } from './agg_param_editor_props'; -import { EditorConfig } from '../config/types'; +import { AggParamEditorProps, AggParamCommonProps } from './agg_param_editor_props'; -interface AggParamReactWrapperProps { - agg: AggConfig; - aggParam: AggParam; - editorConfig: EditorConfig; - indexedFields: FieldParamType[]; - showValidation: boolean; +interface AggParamReactWrapperProps extends AggParamCommonProps { paramEditor: React.FunctionComponent>; - value: T; onChange(value?: T): void; - setTouched(): void; - setValidity(isValid: boolean): void; } function AggParamReactWrapper(props: AggParamReactWrapperProps) { From 33cea5141adcecf4132b8b147867ef938fd81110 Mon Sep 17 00:00:00 2001 From: sulemanof Date: Thu, 16 May 2019 12:12:38 +0300 Subject: [PATCH 04/11] Fix browser tests --- src/legacy/ui/public/agg_types/__tests__/metrics/top_hit.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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..e5c0fc7f8dc86 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 @@ -42,7 +42,7 @@ describe('Top hit metric', function () { val: sortOrder }; params.aggregate = { - val: aggregate + value: aggregate }; params.size = size; const vis = new Vis(indexPattern, { From 019cf759c01653575ae5f4299a37639fb258e26a Mon Sep 17 00:00:00 2001 From: sulemanof Date: Fri, 17 May 2019 11:56:54 +0300 Subject: [PATCH 05/11] Add an icon alert --- .../ui/public/agg_types/controls/size.tsx | 25 +++------ .../agg_types/controls/top_aggregate.tsx | 54 +++++++++---------- .../ui/public/agg_types/controls/top_size.tsx | 44 +++++++++++++++ .../ui/public/agg_types/metrics/top_hit.js | 4 +- 4 files changed, 79 insertions(+), 48 deletions(-) create mode 100644 src/legacy/ui/public/agg_types/controls/top_size.tsx diff --git a/src/legacy/ui/public/agg_types/controls/size.tsx b/src/legacy/ui/public/agg_types/controls/size.tsx index c2fb3a5622bf0..29139a38c96bc 100644 --- a/src/legacy/ui/public/agg_types/controls/size.tsx +++ b/src/legacy/ui/public/agg_types/controls/size.tsx @@ -20,35 +20,26 @@ import React, { useEffect } from 'react'; import { isUndefined } from 'lodash'; import { AggParamEditorProps } from 'ui/vis/editors/default'; -import { EuiFormRow, EuiIconTip, EuiFieldNumber } from '@elastic/eui'; -import { i18n } from '@kbn/i18n'; +import { EuiFormRow, EuiFieldNumber } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; +interface SizeParamEditorProps extends AggParamEditorProps { + iconTip?: React.ReactNode; +} + function SizeParamEditor({ - agg, + iconTip, value, setValue, showValidation, setValidity, setTouched, wrappedWithInlineComp, -}: AggParamEditorProps) { +}: SizeParamEditorProps) { const label = ( <> - {agg.type.name === 'top_hits' ? ( - <> - {' '} - - - ) : null} + {iconTip} ); const isValid = Number(value) > 0; diff --git a/src/legacy/ui/public/agg_types/controls/top_aggregate.tsx b/src/legacy/ui/public/agg_types/controls/top_aggregate.tsx index ff30816198f41..885e95a112f91 100644 --- a/src/legacy/ui/public/agg_types/controls/top_aggregate.tsx +++ b/src/legacy/ui/public/agg_types/controls/top_aggregate.tsx @@ -40,6 +40,27 @@ function TopAggregateParamEditor({ setTouched, wrappedWithInlineComp, }: AggParamEditorProps & SelectParamEditorProps) { + const isValid = !!value; + const isFirstRun = useRef(true); + const fieldType = agg.params.field && agg.params.field.type; + const emptyValue = { text: '', value: 'EMPTY_VALUE', disabled: true, hidden: true }; + const filteredOptions = aggParam.options.raw + .filter( + option => fieldType && option.isCompatibleType(fieldType) && option.isCompatibleVis(visName) + ) + .map(({ text, value: val }) => ({ text, value: val })) + .sort((a, b) => a.text.toLowerCase().localeCompare(b.text.toLowerCase())); + const options = [emptyValue, ...filteredOptions]; + + const iconTipContent = filteredOptions.length + ? i18n.translate('common.ui.aggTypes.aggregateWithTooltip', { + defaultMessage: + 'Choose a strategy for combining multiple hits or a multi-valued field into a single metric', + }) + : i18n.translate('common.ui.aggTypes.aggregateWith.error', { + defaultMessage: 'Chosen field has no compatible aggregations', + }); + const label = ( <> {' '} ); - const fieldType = agg.params.field && agg.params.field.type; - const emptyValue = { text: '', value: 'EMPTY_VALUE', disabled: true, hidden: true }; - const filteredOptions = aggParam.options.raw - .filter( - option => - agg.params.field && option.isCompatibleType(fieldType) && option.isCompatibleVis(visName) - ) - .map(({ text, value: val }) => ({ text, value: val })) - .sort((a, b) => { - if (a.text < b.text) { - return -1; - } - if (a.text > b.text) { - return 1; - } - - return 0; - }); - const isValid = !!value; - const isFirstRun = useRef(true); - - const options = [emptyValue, ...filteredOptions]; - useEffect( () => { setValidity(isValid); @@ -94,7 +89,7 @@ function TopAggregateParamEditor({ return; } - if (options.length === 2) { + if (filteredOptions.length === 1) { setValue(aggParam.options.byValue[filteredOptions[0].value]); } else if (value) { setValue(undefined); @@ -124,6 +119,7 @@ function TopAggregateParamEditor({ onChange={handleChange} fullWidth={true} isInvalid={showValidation ? !isValid : false} + disabled={!filteredOptions.length} onBlur={setTouched} /> diff --git a/src/legacy/ui/public/agg_types/controls/top_size.tsx b/src/legacy/ui/public/agg_types/controls/top_size.tsx new file mode 100644 index 0000000000000..5ed5606d5afec --- /dev/null +++ b/src/legacy/ui/public/agg_types/controls/top_size.tsx @@ -0,0 +1,44 @@ +/* + * 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 { AggParamEditorProps } from 'ui/vis/editors/default'; +import { EuiIconTip } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import { SizeParamEditor } from './size'; + +function TopSizeParamEditor(props: AggParamEditorProps) { + const iconTip = ( + <> + {' '} + + + ); + + return ; +} + +export { TopSizeParamEditor }; 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 96254c56cedaa..acd6e21517c0b 100644 --- a/src/legacy/ui/public/agg_types/metrics/top_hit.js +++ b/src/legacy/ui/public/agg_types/metrics/top_hit.js @@ -26,7 +26,7 @@ import topSortEditor from '../controls/top_sort.html'; import { aggTypeFieldFilters } from '../param_types/filter'; import { i18n } from '@kbn/i18n'; import { wrapWithInlineComp } from '../buckets/_inline_comp_wrapper'; -import { SizeParamEditor } from '../controls/size'; +import { TopSizeParamEditor } from '../controls/top_size'; import { TopAggregateParamEditor } from '../controls/top_aggregate'; const isNumber = function (type) { @@ -154,7 +154,7 @@ export const topHitMetricAgg = new MetricAggType({ }, { name: 'size', - editorComponent: wrapWithInlineComp(SizeParamEditor), + editorComponent: wrapWithInlineComp(TopSizeParamEditor), default: 1 }, { From 65305aca851a18fd460c5b4eab3b861ab2fee1b5 Mon Sep 17 00:00:00 2001 From: sulemanof Date: Mon, 20 May 2019 11:49:34 +0300 Subject: [PATCH 06/11] Changes due to comments --- src/legacy/ui/public/agg_types/controls/top_aggregate.tsx | 6 +++--- src/legacy/ui/public/vis/editors/default/agg_param.js | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/legacy/ui/public/agg_types/controls/top_aggregate.tsx b/src/legacy/ui/public/agg_types/controls/top_aggregate.tsx index 885e95a112f91..fcbc4de973aa0 100644 --- a/src/legacy/ui/public/agg_types/controls/top_aggregate.tsx +++ b/src/legacy/ui/public/agg_types/controls/top_aggregate.tsx @@ -57,7 +57,7 @@ function TopAggregateParamEditor({ defaultMessage: 'Choose a strategy for combining multiple hits or a multi-valued field into a single metric', }) - : i18n.translate('common.ui.aggTypes.aggregateWith.error', { + : i18n.translate('common.ui.aggTypes.aggregateWith.noAggsErrorTooltip', { defaultMessage: 'Chosen field has no compatible aggregations', }); @@ -92,7 +92,7 @@ function TopAggregateParamEditor({ if (filteredOptions.length === 1) { setValue(aggParam.options.byValue[filteredOptions[0].value]); } else if (value) { - setValue(undefined); + setValue(); } }, [fieldType, visName] @@ -100,7 +100,7 @@ function TopAggregateParamEditor({ const handleChange = (event: React.ChangeEvent) => { if (event.target.value === emptyValue.value) { - setValue(undefined); + setValue(); } else { setValue(aggParam.options.byValue[event.target.value]); } diff --git a/src/legacy/ui/public/vis/editors/default/agg_param.js b/src/legacy/ui/public/vis/editors/default/agg_param.js index 137a8195bd34d..f25e074dbe5e6 100644 --- a/src/legacy/ui/public/vis/editors/default/agg_param.js +++ b/src/legacy/ui/public/vis/editors/default/agg_param.js @@ -63,7 +63,7 @@ uiModules indexed-fields="indexedFields" show-validation="showValidation" value="paramValue" - visName="vis.type.name" + vis-name="vis.type.name" on-change="onChange" set-touched="setTouched" set-validity="setValidity" From 36a19fd8aa97288ea1515de68786499b36888afc Mon Sep 17 00:00:00 2001 From: sulemanof Date: Tue, 21 May 2019 14:44:53 +0300 Subject: [PATCH 07/11] Move error to a help text --- .../agg_types/controls/top_aggregate.tsx | 23 ++++++++++--------- .../translations/translations/zh-CN.json | 3 +-- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/legacy/ui/public/agg_types/controls/top_aggregate.tsx b/src/legacy/ui/public/agg_types/controls/top_aggregate.tsx index fcbc4de973aa0..3edf0d23e9c1a 100644 --- a/src/legacy/ui/public/agg_types/controls/top_aggregate.tsx +++ b/src/legacy/ui/public/agg_types/controls/top_aggregate.tsx @@ -52,15 +52,6 @@ function TopAggregateParamEditor({ .sort((a, b) => a.text.toLowerCase().localeCompare(b.text.toLowerCase())); const options = [emptyValue, ...filteredOptions]; - const iconTipContent = filteredOptions.length - ? i18n.translate('common.ui.aggTypes.aggregateWithTooltip', { - defaultMessage: - 'Choose a strategy for combining multiple hits or a multi-valued field into a single metric', - }) - : i18n.translate('common.ui.aggTypes.aggregateWith.noAggsErrorTooltip', { - defaultMessage: 'Chosen field has no compatible aggregations', - }); - const label = ( <> {' '} ); + const helpText = !filteredOptions.length + ? i18n.translate('common.ui.aggTypes.aggregateWith.noAggsErrorTooltip', { + defaultMessage: 'The chosen field has no compatible aggregations.', + }) + : null; + useEffect( () => { setValidity(isValid); @@ -112,6 +112,7 @@ function TopAggregateParamEditor({ fullWidth={true} isInvalid={showValidation ? !isValid : false} className={wrappedWithInlineComp ? undefined : 'visEditorSidebar__aggParamFormRow'} + helpText={helpText} > Date: Wed, 22 May 2019 15:49:43 +0300 Subject: [PATCH 08/11] Move error to a field --- .../ui/public/agg_types/controls/field.tsx | 13 +++++- .../ui/public/agg_types/controls/size.tsx | 3 ++ .../agg_types/controls/top_aggregate.tsx | 25 ++++++------ .../public/agg_types/controls/top_field.tsx | 40 +++++++++++++++++++ .../ui/public/agg_types/controls/top_size.tsx | 4 +- .../ui/public/agg_types/metrics/top_hit.js | 2 + 6 files changed, 72 insertions(+), 15 deletions(-) create mode 100644 src/legacy/ui/public/agg_types/controls/top_field.tsx diff --git a/src/legacy/ui/public/agg_types/controls/field.tsx b/src/legacy/ui/public/agg_types/controls/field.tsx index 8b6749054e92d..957d5d08b4e13 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 { + customError?: string; +} + function FieldParamEditor({ agg, aggParam, + customError, indexedFields = [], showValidation, value, setTouched, setValidity, setValue, -}: AggParamEditorProps) { +}: FieldParamEditorProps) { const selectedOptions: ComboBoxGroupedOption[] = value ? [{ label: value.displayName, value }] : []; @@ -56,6 +61,10 @@ function FieldParamEditor({ }; const errors = []; + if (customError) { + errors.push(customError); + } + if (!indexedFields.length) { errors.push( i18n.translate('common.ui.aggTypes.field.noCompatibleFieldsDescription', { @@ -70,7 +79,7 @@ function FieldParamEditor({ setTouched(); } - const isValid = !!value && !!indexedFields.length; + const isValid = !!value && !errors.length; useEffect( () => { diff --git a/src/legacy/ui/public/agg_types/controls/size.tsx b/src/legacy/ui/public/agg_types/controls/size.tsx index 29139a38c96bc..105d033b12eab 100644 --- a/src/legacy/ui/public/agg_types/controls/size.tsx +++ b/src/legacy/ui/public/agg_types/controls/size.tsx @@ -25,9 +25,11 @@ import { FormattedMessage } from '@kbn/i18n/react'; interface SizeParamEditorProps extends AggParamEditorProps { iconTip?: React.ReactNode; + disabled?: boolean; } function SizeParamEditor({ + disabled, iconTip, value, setValue, @@ -65,6 +67,7 @@ function SizeParamEditor({ isInvalid={showValidation ? !isValid : false} onBlur={setTouched} min={1} + disabled={disabled} data-test-subj="sizeParamEditor" /> diff --git a/src/legacy/ui/public/agg_types/controls/top_aggregate.tsx b/src/legacy/ui/public/agg_types/controls/top_aggregate.tsx index 3edf0d23e9c1a..23d0cb82401c2 100644 --- a/src/legacy/ui/public/agg_types/controls/top_aggregate.tsx +++ b/src/legacy/ui/public/agg_types/controls/top_aggregate.tsx @@ -22,6 +22,8 @@ import { EuiFormRow, EuiIconTip, EuiSelect } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; 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'; interface AggregateValueProp extends SelectValueProp { @@ -29,6 +31,15 @@ interface AggregateValueProp extends SelectValueProp { isCompatibleVis(visName: string): boolean; } +function getCompatibleAggs(agg: AggConfig, visName: string): AggregateValueProp[] { + const fieldType = agg.params.field && agg.params.field.type; + const { options = [] } = agg.getAggParams().find(({ name }: AggParam) => name === 'aggregate'); + return options.filter( + (option: AggregateValueProp) => + fieldType && option.isCompatibleType(fieldType) && option.isCompatibleVis(visName) + ); +} + function TopAggregateParamEditor({ agg, aggParam, @@ -44,10 +55,7 @@ function TopAggregateParamEditor({ const isFirstRun = useRef(true); const fieldType = agg.params.field && agg.params.field.type; const emptyValue = { text: '', value: 'EMPTY_VALUE', disabled: true, hidden: true }; - const filteredOptions = aggParam.options.raw - .filter( - option => fieldType && option.isCompatibleType(fieldType) && option.isCompatibleVis(visName) - ) + const filteredOptions = getCompatibleAggs(agg, visName) .map(({ text, value: val }) => ({ text, value: val })) .sort((a, b) => a.text.toLowerCase().localeCompare(b.text.toLowerCase())); const options = [emptyValue, ...filteredOptions]; @@ -69,12 +77,6 @@ function TopAggregateParamEditor({ ); - const helpText = !filteredOptions.length - ? i18n.translate('common.ui.aggTypes.aggregateWith.noAggsErrorTooltip', { - defaultMessage: 'The chosen field has no compatible aggregations.', - }) - : null; - useEffect( () => { setValidity(isValid); @@ -112,7 +114,6 @@ function TopAggregateParamEditor({ fullWidth={true} isInvalid={showValidation ? !isValid : false} className={wrappedWithInlineComp ? undefined : 'visEditorSidebar__aggParamFormRow'} - helpText={helpText} > ) { + const compatibleAggs = getCompatibleAggs(props.agg, props.visName); + let customError; + + if (!compatibleAggs.length) { + customError = i18n.translate('common.ui.aggTypes.aggregateWith.noAggsErrorTooltip', { + defaultMessage: 'The chosen field has no compatible aggregations.', + }); + } + + return ; +} + +export { TopFieldParamEditor }; diff --git a/src/legacy/ui/public/agg_types/controls/top_size.tsx b/src/legacy/ui/public/agg_types/controls/top_size.tsx index 5ed5606d5afec..2878f31b5060f 100644 --- a/src/legacy/ui/public/agg_types/controls/top_size.tsx +++ b/src/legacy/ui/public/agg_types/controls/top_size.tsx @@ -22,6 +22,7 @@ import { AggParamEditorProps } from 'ui/vis/editors/default'; import { EuiIconTip } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { SizeParamEditor } from './size'; +import { getCompatibleAggs } from './top_aggregate'; function TopSizeParamEditor(props: AggParamEditorProps) { const iconTip = ( @@ -37,8 +38,9 @@ function TopSizeParamEditor(props: AggParamEditorProps) { /> ); + const disabled = !getCompatibleAggs(props.agg, props.visName).length; - return ; + return ; } export { TopSizeParamEditor }; 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 acd6e21517c0b..580dbfd658a0b 100644 --- a/src/legacy/ui/public/agg_types/metrics/top_hit.js +++ b/src/legacy/ui/public/agg_types/metrics/top_hit.js @@ -26,6 +26,7 @@ import topSortEditor from '../controls/top_sort.html'; import { aggTypeFieldFilters } from '../param_types/filter'; import { i18n } from '@kbn/i18n'; import { wrapWithInlineComp } from '../buckets/_inline_comp_wrapper'; +import { TopFieldParamEditor } from '../controls/top_field'; import { TopSizeParamEditor } from '../controls/top_size'; import { TopAggregateParamEditor } from '../controls/top_aggregate'; @@ -70,6 +71,7 @@ export const topHitMetricAgg = new MetricAggType({ { name: 'field', type: 'field', + editorComponent: TopFieldParamEditor, onlyAggregatable: false, filterFieldTypes: '*', write(agg, output) { From f99541fa24f440ee3ed15578f41fc2a6482ba632 Mon Sep 17 00:00:00 2001 From: sulemanof Date: Wed, 22 May 2019 17:17:48 +0300 Subject: [PATCH 09/11] Change validation logic --- src/legacy/ui/public/agg_types/controls/size.tsx | 2 +- src/legacy/ui/public/agg_types/controls/top_aggregate.tsx | 5 +++-- src/legacy/ui/public/agg_types/controls/top_size.tsx | 3 ++- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/legacy/ui/public/agg_types/controls/size.tsx b/src/legacy/ui/public/agg_types/controls/size.tsx index 105d033b12eab..9357fa62f2ff2 100644 --- a/src/legacy/ui/public/agg_types/controls/size.tsx +++ b/src/legacy/ui/public/agg_types/controls/size.tsx @@ -44,7 +44,7 @@ function SizeParamEditor({ {iconTip} ); - const isValid = Number(value) > 0; + const isValid = disabled || Number(value) > 0; useEffect( () => { diff --git a/src/legacy/ui/public/agg_types/controls/top_aggregate.tsx b/src/legacy/ui/public/agg_types/controls/top_aggregate.tsx index 23d0cb82401c2..997e3c93bfd9f 100644 --- a/src/legacy/ui/public/agg_types/controls/top_aggregate.tsx +++ b/src/legacy/ui/public/agg_types/controls/top_aggregate.tsx @@ -51,7 +51,6 @@ function TopAggregateParamEditor({ setTouched, wrappedWithInlineComp, }: AggParamEditorProps & SelectParamEditorProps) { - const isValid = !!value; const isFirstRun = useRef(true); const fieldType = agg.params.field && agg.params.field.type; const emptyValue = { text: '', value: 'EMPTY_VALUE', disabled: true, hidden: true }; @@ -59,6 +58,8 @@ function TopAggregateParamEditor({ .map(({ text, value: val }) => ({ text, value: val })) .sort((a, b) => a.text.toLowerCase().localeCompare(b.text.toLowerCase())); const options = [emptyValue, ...filteredOptions]; + const disabled = fieldType && !filteredOptions.length; + const isValid = disabled || !!value; const label = ( <> @@ -121,7 +122,7 @@ function TopAggregateParamEditor({ onChange={handleChange} fullWidth={true} isInvalid={showValidation ? !isValid : false} - disabled={!filteredOptions.length} + disabled={disabled} onBlur={setTouched} /> diff --git a/src/legacy/ui/public/agg_types/controls/top_size.tsx b/src/legacy/ui/public/agg_types/controls/top_size.tsx index 2878f31b5060f..513b4681ecc74 100644 --- a/src/legacy/ui/public/agg_types/controls/top_size.tsx +++ b/src/legacy/ui/public/agg_types/controls/top_size.tsx @@ -38,7 +38,8 @@ function TopSizeParamEditor(props: AggParamEditorProps) { /> ); - const disabled = !getCompatibleAggs(props.agg, props.visName).length; + const fieldType = props.agg.params.field && props.agg.params.field.type; + const disabled = fieldType && !getCompatibleAggs(props.agg, props.visName).length; return ; } From 6e68aa4eda1f1259470ca8ceb40a246aff785438 Mon Sep 17 00:00:00 2001 From: sulemanof Date: Wed, 22 May 2019 17:42:29 +0300 Subject: [PATCH 10/11] Fix discarding changes action --- .../ui/public/agg_types/controls/top_aggregate.tsx | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/legacy/ui/public/agg_types/controls/top_aggregate.tsx b/src/legacy/ui/public/agg_types/controls/top_aggregate.tsx index 997e3c93bfd9f..6416ab96ffac1 100644 --- a/src/legacy/ui/public/agg_types/controls/top_aggregate.tsx +++ b/src/legacy/ui/public/agg_types/controls/top_aggregate.tsx @@ -92,10 +92,16 @@ function TopAggregateParamEditor({ return; } + if (value) { + if (aggParam.options.byValue[value.value]) { + return; + } + + setValue(); + } + if (filteredOptions.length === 1) { setValue(aggParam.options.byValue[filteredOptions[0].value]); - } else if (value) { - setValue(); } }, [fieldType, visName] From 559c95480c1e98ba56060149744653fe50f56114 Mon Sep 17 00:00:00 2001 From: maryia-lapata Date: Wed, 29 May 2019 10:39:32 +0300 Subject: [PATCH 11/11] Remove changed translation --- x-pack/plugins/translations/translations/ja-JP.json | 1 - 1 file changed, 1 deletion(-) diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index e2249fd1a0b4a..475218a311a26 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -80,7 +80,6 @@ "common.ui.aggResponse.fieldLabel": "フィールド", "common.ui.aggResponse.valueLabel": "値", "common.ui.aggTypes.aggregateWithLabel": "集約基準", - "common.ui.aggTypes.aggregateWithTooltip": "複数ヒットまたは複数値のフィールドを 1 つのメトリックにまとめる方法を選択してください", "common.ui.aggTypes.buckets.dateHistogramLabel": "{intervalDescription} ごとに {fieldName}", "common.ui.aggTypes.buckets.dateHistogramTitle": "Date Histogram", "common.ui.aggTypes.buckets.dateRangeTitle": "日付範囲",