From 71cb7aa008ecf33d6c8a4d6132c009cccefbbe72 Mon Sep 17 00:00:00 2001 From: dej611 Date: Wed, 1 Dec 2021 14:27:04 +0100 Subject: [PATCH 1/7] :lipstick: Revisit form style + spacers --- .../dimension_panel/advanced_options.tsx | 17 ++---- .../dimension_panel/dimension_editor.tsx | 6 +- .../dimension_panel/filtering.tsx | 2 +- .../dimension_panel/reference_editor.tsx | 2 +- .../dimension_panel/time_scaling.tsx | 2 +- .../dimension_panel/time_shift.tsx | 2 +- .../calculations/moving_average.tsx | 2 +- .../operations/definitions/last_value.tsx | 2 +- .../operations/definitions/percentile.tsx | 2 +- .../operations/definitions/terms/index.tsx | 57 +++++++++++++++++-- .../definitions/terms/values_input.tsx | 2 +- .../translations/translations/ja-JP.json | 2 - .../translations/translations/zh-CN.json | 2 - 13 files changed, 70 insertions(+), 30 deletions(-) diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/advanced_options.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/advanced_options.tsx index 252772903809f5..7f5d662a78cd4e 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/advanced_options.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/advanced_options.tsx @@ -26,7 +26,7 @@ export function AdvancedOptions(props: { <> {popoverOptions.length > 0 && ( - + {/* */} )} - {inlineOptions.length > 0 && ( - <> + {inlineOptions.map((option) => ( + - {inlineOptions.map((option, index) => ( - - {option.inlineElement} - {index !== inlineOptions.length - 1 && } - - ))} - - )} + {option.inlineElement} + + ))} ); } diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/dimension_editor.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/dimension_editor.tsx index c8452340e993a3..f3f629f9aacd37 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/dimension_editor.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/dimension_editor.tsx @@ -425,7 +425,7 @@ export function DimensionEditor(props: DimensionEditorProps) {
{i18n.translate('xpack.lens.indexPattern.functionsLabel', { - defaultMessage: 'Select a function', + defaultMessage: 'Functions', })} @@ -485,7 +485,7 @@ export function DimensionEditor(props: DimensionEditorProps) { /> ); })} - + {selectedOperationDefinition.selectionStyle !== 'field' ? : null} ) : null} @@ -496,7 +496,7 @@ export function DimensionEditor(props: DimensionEditorProps) { diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/last_value.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/last_value.tsx index ec949f9f9bc947..46e1b368fc9134 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/last_value.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/last_value.tsx @@ -223,7 +223,7 @@ export const lastValueOperation: OperationDefinition } - display="columnCompressed" + display="rowCompressed" fullWidth > - { + const value = id.replace( + idPrefix, + '' + ) as TermsIndexPatternColumn['params']['orderDirection']; + updateLayer( + updateColumnParam({ + layer, + columnId, + paramName: 'orderDirection', + value, + }) + ); + }} + /> + {/* + /> */} {!hasRestrictions && ( <> diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/terms/values_input.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/terms/values_input.tsx index 96b92686f76221..a107893517ea3c 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/terms/values_input.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/terms/values_input.tsx @@ -44,7 +44,7 @@ export const ValuesInput = ({ label={i18n.translate('xpack.lens.indexPattern.terms.size', { defaultMessage: 'Number of values', })} - display="columnCompressed" + display="rowCompressed" fullWidth isInvalid={isHigherThanMax || isLowerThanMin} error={ diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 5948e16a5907fa..1ac81a4979dbbd 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -14197,7 +14197,6 @@ "xpack.lens.indexPattern.cardinality": "ユニークカウント", "xpack.lens.indexPattern.cardinality.signature": "フィールド:文字列", "xpack.lens.indexPattern.cardinalityOf": "{name} のユニークカウント", - "xpack.lens.indexPattern.chooseField": "フィールドを選択", "xpack.lens.indexPattern.chooseFieldLabel": "この関数を使用するには、フィールドを選択してください。", "xpack.lens.indexPattern.chooseSubFunction": "サブ関数を選択", "xpack.lens.indexPattern.columnFormatLabel": "値の形式", @@ -14296,7 +14295,6 @@ "xpack.lens.indexPattern.formulaWarningStaticValueText": "式を上書きするには、入力フィールドの値を変更します", "xpack.lens.indexPattern.formulaWarningText": "式を上書きするには、クイック関数を選択します", "xpack.lens.indexPattern.formulaWithTooManyArguments": "演算{operation}の引数が多すぎます", - "xpack.lens.indexPattern.functionsLabel": "関数を選択", "xpack.lens.indexPattern.groupByDropdown": "グループ分けの条件", "xpack.lens.indexPattern.incompleteOperation": "(未完了)", "xpack.lens.indexPattern.intervals": "間隔", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 0da3642eefa3cb..fb4a9a0f04a2b9 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -14386,7 +14386,6 @@ "xpack.lens.indexPattern.cardinality": "唯一计数", "xpack.lens.indexPattern.cardinality.signature": "field: string", "xpack.lens.indexPattern.cardinalityOf": "{name} 的唯一计数", - "xpack.lens.indexPattern.chooseField": "选择字段", "xpack.lens.indexPattern.chooseFieldLabel": "要使用此函数,请选择字段。", "xpack.lens.indexPattern.chooseSubFunction": "选择子函数", "xpack.lens.indexPattern.columnFormatLabel": "值格式", @@ -14486,7 +14485,6 @@ "xpack.lens.indexPattern.formulaWarningStaticValueText": "要覆盖公式,请更改输入字段中的值", "xpack.lens.indexPattern.formulaWarningText": "要覆盖公式,请选择快速函数", "xpack.lens.indexPattern.formulaWithTooManyArguments": "运算 {operation} 的参数过多", - "xpack.lens.indexPattern.functionsLabel": "选择函数", "xpack.lens.indexPattern.groupByDropdown": "分组依据", "xpack.lens.indexPattern.incompleteOperation": "(不完整)", "xpack.lens.indexPattern.intervals": "时间间隔", From 3f46a758fa60bc1987d08f8863841e5bfda380c7 Mon Sep 17 00:00:00 2001 From: dej611 Date: Wed, 1 Dec 2021 14:48:06 +0100 Subject: [PATCH 2/7] :white_check_mark: Fix tests --- .../operations/definitions/terms/index.tsx | 6 ++-- .../definitions/terms/terms.test.tsx | 29 ++++++++++--------- 2 files changed, 18 insertions(+), 17 deletions(-) diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/terms/index.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/terms/index.tsx index 65164ed07714be..bf51d3ec6d2d5b 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/terms/index.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/terms/index.tsx @@ -427,7 +427,7 @@ export const termsOperation: OperationDefinition { + const original = jest.requireActual('@elastic/eui'); + + return { + ...original, + htmlIdGenerator: () => () => '', + }; +}); + const uiSettingsMock = {} as IUiSettingsClient; const defaultProps = { @@ -909,12 +919,10 @@ describe('terms', () => { /> ); - const select = instance - .find('[data-test-subj="indexPattern-terms-orderDirection"]') - .find(EuiSelect); + const selection = instance.find(EuiButtonGroup); - expect(select.prop('value')).toEqual('asc'); - expect(select.prop('options')!.map(({ value }) => value)).toEqual(['asc', 'desc']); + expect(selection.prop('idSelected')).toEqual('asc'); + expect(selection.prop('options').map(({ value }) => value)).toEqual(['asc', 'desc']); }); it('should update state with the order direction value', () => { @@ -929,14 +937,7 @@ describe('terms', () => { /> ); - instance - .find('[data-test-subj="indexPattern-terms-orderDirection"]') - .find(EuiSelect) - .simulate('change', { - target: { - value: 'desc', - }, - }); + instance.find(EuiButtonGroup).simulate('change', 'desc'); expect(updateLayerSpy).toHaveBeenCalledWith({ ...layer, From c555d3e5a61d17a69aa0c534a443d38905455239 Mon Sep 17 00:00:00 2001 From: dej611 Date: Thu, 2 Dec 2021 12:52:34 +0100 Subject: [PATCH 3/7] :sparkles: Replace percentile input with range --- .../definitions/percentile.test.tsx | 54 ++++++++++-------- .../operations/definitions/percentile.tsx | 56 +++++++++++-------- 2 files changed, 62 insertions(+), 48 deletions(-) diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/percentile.test.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/percentile.test.tsx index a8851c79be2aef..f5e21c5d8aeeb6 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/percentile.test.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/percentile.test.tsx @@ -5,7 +5,7 @@ * 2.0. */ -import React from 'react'; +import React, { ChangeEvent } from 'react'; import { shallow, mount } from 'enzyme'; import { IUiSettingsClient, SavedObjectsClientContract, HttpSetup } from 'kibana/public'; import { IStorageWrapper } from 'src/plugins/kibana_utils/public'; @@ -14,11 +14,20 @@ import { createMockedIndexPattern } from '../../mocks'; import { percentileOperation } from './index'; import { IndexPattern, IndexPatternLayer } from '../../types'; import { PercentileIndexPatternColumn } from './percentile'; -import { EuiFieldNumber } from '@elastic/eui'; +import { EuiRange } from '@elastic/eui'; import { act } from 'react-dom/test-utils'; import { EuiFormRow } from '@elastic/eui'; import { TermsIndexPatternColumn } from './terms'; +jest.mock('lodash', () => { + const original = jest.requireActual('lodash'); + + return { + ...original, + debounce: (fn: unknown) => fn, + }; +}); + const uiSettingsMock = {} as IUiSettingsClient; const defaultProps = { @@ -272,8 +281,7 @@ describe('percentile', () => { expect(input.prop('value')).toEqual('23'); }); - it('should update state on change', async () => { - jest.useFakeTimers(); + it('should update state on change', () => { const updateLayerSpy = jest.fn(); const instance = mount( { /> ); - jest.runAllTimers(); - - const input = instance.find( - '[data-test-subj="lns-indexPattern-percentile-input"] input[type="number"]' - ); + const input = instance + .find('[data-test-subj="lns-indexPattern-percentile-input"]') + .find(EuiRange); - await act(async () => { - input.simulate('change', { target: { value: '27' } }); + act(() => { + input.prop('onChange')!( + { currentTarget: { value: '27' } } as ChangeEvent, + true + ); }); instance.update(); - jest.runAllTimers(); - expect(updateLayerSpy).toHaveBeenCalledWith({ ...layer, columns: { @@ -314,7 +321,7 @@ describe('percentile', () => { }); }); - it('should not update on invalid input, but show invalid value locally', async () => { + it('should not update on invalid input, but show invalid value locally', () => { const updateLayerSpy = jest.fn(); const instance = mount( { /> ); - jest.runAllTimers(); - - const input = instance.find( - '[data-test-subj="lns-indexPattern-percentile-input"] input[type="number"]' - ); + const input = instance + .find('[data-test-subj="lns-indexPattern-percentile-input"]') + .find(EuiRange); - await act(async () => { - input.simulate('change', { target: { value: '12.12' } }); + act(() => { + input.prop('onChange')!( + { currentTarget: { value: '12.12' } } as ChangeEvent, + true + ); }); instance.update(); - jest.runAllTimers(); - expect(updateLayerSpy).not.toHaveBeenCalled(); expect( @@ -351,7 +357,7 @@ describe('percentile', () => { expect( instance .find('[data-test-subj="lns-indexPattern-percentile-input"]') - .find(EuiFieldNumber) + .find(EuiRange) .prop('value') ).toEqual('12.12'); }); diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/percentile.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/percentile.tsx index 9e6232f4fe2649..d1ce42696ea680 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/percentile.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/percentile.tsx @@ -5,8 +5,8 @@ * 2.0. */ -import { EuiFieldNumber, EuiFormRow } from '@elastic/eui'; -import React, { useCallback, useState } from 'react'; +import { EuiFormRow, EuiRange, EuiRangeProps } from '@elastic/eui'; +import React, { useCallback } from 'react'; import { i18n } from '@kbn/i18n'; import { AggFunctionsMapping } from 'src/plugins/data/public'; import { buildExpressionFunction } from '../../../../../../../src/plugins/expressions/public'; @@ -21,7 +21,7 @@ import { } from './helpers'; import { FieldBasedIndexPatternColumn } from './column_types'; import { adjustTimeScaleLabelSuffix } from '../time_scale_utils'; -import { useDebounceWithOptions } from '../../../shared_components'; +import { useDebouncedValue } from '../../../shared_components'; export interface PercentileIndexPatternColumn extends FieldBasedIndexPatternColumn { operationType: 'percentile'; @@ -150,16 +150,14 @@ export const percentileOperation: OperationDefinition< columnId, indexPattern, }) { - const [inputValue, setInputValue] = useState(String(currentColumn.params.percentile)); - - const inputValueAsNumber = Number(inputValue); - // an input is value if it's not an empty string, parses to a valid number, is between 0 and 100 (exclusive) - // and is an integer - const inputValueIsValid = isValidNumber(inputValue, true, 99, 1); - - useDebounceWithOptions( - () => { - if (!inputValueIsValid) return; + const onChange = useCallback( + (value) => { + if ( + !isValidNumber(value, true, 99, 1) || + Number(value) === currentColumn.params.percentile + ) { + return; + } updateLayer({ ...layer, columns: { @@ -171,26 +169,32 @@ export const percentileOperation: OperationDefinition< : ofName( indexPattern.getFieldByName(currentColumn.sourceField)?.displayName || currentColumn.sourceField, - inputValueAsNumber, + Number(value), currentColumn.timeShift ), params: { ...currentColumn.params, - percentile: inputValueAsNumber, + percentile: Number(value), }, } as PercentileIndexPatternColumn, }, }); }, - { skipFirstRender: true }, - 256, - [inputValue] + [updateLayer, layer, columnId, currentColumn, indexPattern] + ); + const { inputValue, handleInputChange: handleInputChangeWithoutValidation } = useDebouncedValue< + string | undefined + >({ + onChange, + value: String(currentColumn.params.percentile), + }); + const inputValueIsValid = isValidNumber(inputValue, true, 99, 1); + + const handleInputChange: EuiRangeProps['onChange'] = useCallback( + (e) => handleInputChangeWithoutValidation(String(e.currentTarget.value)), + [handleInputChangeWithoutValidation] ); - const handleInputChange = useCallback((e: React.ChangeEvent) => { - const val = String(e.target.value); - setInputValue(val); - }, []); return ( - ); From 90ff5c2e9dc9882c1e3ca72e7b470042f3c05d5b Mon Sep 17 00:00:00 2001 From: dej611 Date: Thu, 2 Dec 2021 12:55:03 +0100 Subject: [PATCH 4/7] :lipstick: Fix mobile layout --- .../editor_frame/config_panel/dimension_container.scss | 1 + 1 file changed, 1 insertion(+) diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/dimension_container.scss b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/dimension_container.scss index 692db8171d1248..365e11f6421caf 100644 --- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/dimension_container.scss +++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/dimension_container.scss @@ -16,6 +16,7 @@ @include euiBreakpoint('xs', 's', 'm') { @include euiFlyout; + left: 10vw; } .lnsFrameLayout__sidebar-isFullscreen & { From 43c2111a765f61059ce318763a33ca81a4734a8d Mon Sep 17 00:00:00 2001 From: dej611 Date: Thu, 2 Dec 2021 15:09:37 +0100 Subject: [PATCH 5/7] :lipstick: Make searchbar go below flyout --- .../editor_frame/config_panel/dimension_container.scss | 1 + 1 file changed, 1 insertion(+) diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/dimension_container.scss b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/dimension_container.scss index 365e11f6421caf..c501d1a04c8d07 100644 --- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/dimension_container.scss +++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/dimension_container.scss @@ -17,6 +17,7 @@ @include euiBreakpoint('xs', 's', 'm') { @include euiFlyout; left: 10vw; + z-index: $euiZContentMenu; } .lnsFrameLayout__sidebar-isFullscreen & { From d54fd8f63e2750f9516e62ff0a1f922c2167f7fe Mon Sep 17 00:00:00 2001 From: dej611 Date: Fri, 3 Dec 2021 14:55:05 +0100 Subject: [PATCH 6/7] :fire: Remove unused jsx --- .../indexpattern_datasource/dimension_panel/advanced_options.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/advanced_options.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/advanced_options.tsx index 7f5d662a78cd4e..ffd75163e7871f 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/advanced_options.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/advanced_options.tsx @@ -26,7 +26,6 @@ export function AdvancedOptions(props: { <> {popoverOptions.length > 0 && ( - {/* */} Date: Fri, 3 Dec 2021 11:42:18 -0500 Subject: [PATCH 7/7] [Lens] Refactor Flyout Design Updates (#14) * allow flyout to go full width on small viewports * remove hiding of layer panel when flyout open --- .../config_panel/dimension_container.scss | 14 +++++--------- .../editor_frame/config_panel/layer_panel.tsx | 7 +------ 2 files changed, 6 insertions(+), 15 deletions(-) diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/dimension_container.scss b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/dimension_container.scss index c501d1a04c8d07..48bb8bc1d70d57 100644 --- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/dimension_container.scss +++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/dimension_container.scss @@ -5,19 +5,15 @@ // Use the EuiFlyout style @include euiFlyout; // But with custom positioning to keep it within the sidebar contents - position: absolute; - left: 0; animation: euiFlyout $euiAnimSpeedNormal $euiAnimSlightResistance; + left: 0; + max-width: none !important; + z-index: $euiZContentMenu; @include euiBreakpoint('l', 'xl') { - top: 0 !important; height: 100% !important; - } - - @include euiBreakpoint('xs', 's', 'm') { - @include euiFlyout; - left: 10vw; - z-index: $euiZContentMenu; + position: absolute; + top: 0 !important; } .lnsFrameLayout__sidebar-isFullscreen & { diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/layer_panel.tsx b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/layer_panel.tsx index 84c7722ca1b880..6d0f0e290586d1 100644 --- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/layer_panel.tsx +++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/layer_panel.tsx @@ -317,12 +317,7 @@ export function LayerPanel( return ( <> -
+