diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/filters/filter_popover.test.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/filters/filter_popover.test.tsx
index a204c1ec590a4..9984bc4c22ab3 100644
--- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/filters/filter_popover.test.tsx
+++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/filters/filter_popover.test.tsx
@@ -41,7 +41,7 @@ describe('filter popover', () => {
},
setFilter: jest.fn(),
indexPattern: createMockedIndexPattern(),
- Button: () => trigger,
+ button: trigger,
isOpen: true,
triggerClose: () => {},
};
diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/filters/filter_popover.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/filters/filter_popover.tsx
index cf95ae2dfd0e8..b0e0c6c1dfa41 100644
--- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/filters/filter_popover.tsx
+++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/filters/filter_popover.tsx
@@ -19,14 +19,14 @@ export const FilterPopover = ({
filter,
setFilter,
indexPattern,
- Button,
+ button,
isOpen,
triggerClose,
}: {
filter: FilterValue;
setFilter: Function;
indexPattern: IndexPattern;
- Button: React.FunctionComponent;
+ button: React.ReactChild;
isOpen: boolean;
triggerClose: () => void;
}) => {
@@ -78,12 +78,13 @@ export const FilterPopover = ({
isOpen={isOpen}
ownFocus
closePopover={() => triggerClose()}
- button={}
+ button={button}
>
{
if (inputRef.current) inputRef.current.focus();
diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/filters/filters.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/filters/filters.tsx
index f7537cffb112e..8df49e03da4d0 100644
--- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/filters/filters.tsx
+++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/filters/filters.tsx
@@ -264,7 +264,7 @@ export const FilterList = ({
setFilter={(f: FilterValue) => {
onChangeValue(f.id, f.input, f.label);
}}
- Button={() => (
+ button={
{filter.label || filter.input.query || defaultLabel}
- )}
+ }
/>
);
diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/ranges/advanced_editor.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/ranges/advanced_editor.tsx
index 8a35a093f4ac0..7591a5d545c3c 100644
--- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/ranges/advanced_editor.tsx
+++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/ranges/advanced_editor.tsx
@@ -7,7 +7,7 @@
import './advanced_editor.scss';
-import React, { useState, MouseEventHandler, useEffect } from 'react';
+import React, { useState } from 'react';
import { i18n } from '@kbn/i18n';
import {
EuiFlexGroup,
@@ -48,22 +48,19 @@ const getBetterLabel = (range: RangeTypeLens, formatter: IFieldFormat) =>
export const RangePopover = ({
range,
setRange,
- Button,
- initiallyOpen,
+ button,
+ triggerClose,
+ isOpen,
}: {
range: LocalRangeType;
setRange: (newRange: LocalRangeType) => void;
- Button: React.FunctionComponent<{ onClick: MouseEventHandler }>;
- initiallyOpen: boolean;
+ button: React.ReactChild;
+ triggerClose: () => void;
+ isOpen: boolean;
}) => {
- const [isPopoverOpen, setIsPopoverOpen] = useState(false);
const [tempRange, setTempRange] = useState(range);
-
- // set popover open on start to work around EUI bug
- useEffect(() => {
- setIsPopoverOpen(initiallyOpen);
- // eslint-disable-next-line react-hooks/exhaustive-deps
- }, []);
+ const labelRef = React.useRef();
+ const toRef = React.useRef();
const saveRangeAndReset = (newRange: LocalRangeType, resetRange = false) => {
if (resetRange) {
@@ -91,25 +88,13 @@ export const RangePopover = ({
defaultMessage: 'Less than',
});
- const onSubmit = () => {
- if (isPopoverOpen) {
- setIsPopoverOpen(false);
- }
- };
-
return (
{
- setIsPopoverOpen((isOpen) => !isOpen);
- }}
- />
- }
+ isOpen={isOpen}
+ closePopover={() => triggerClose()}
+ button={button}
data-test-subj="indexPattern-ranges-popover"
>
@@ -131,6 +116,11 @@ export const RangePopover = ({
{lteAppendLabel}
}
+ onKeyDown={({ key }: React.KeyboardEvent) => {
+ if (keys.ENTER === key && toRef.current) {
+ toRef.current.focus();
+ }
+ }}
compressed
placeholder={FROM_PLACEHOLDER}
isInvalid={!isValidRange(tempRange)}
@@ -144,6 +134,11 @@ export const RangePopover = ({
{
+ if (toRef && node) {
+ toRef.current = node;
+ }
+ }}
onChange={({ target }) => {
const newRange = {
...tempRange,
@@ -161,8 +156,8 @@ export const RangePopover = ({
placeholder={TO_PLACEHOLDER}
isInvalid={!isValidRange(tempRange)}
onKeyDown={({ key }: React.KeyboardEvent) => {
- if (keys.ENTER === key && onSubmit) {
- onSubmit();
+ if (keys.ENTER === key && labelRef.current) {
+ labelRef.current.focus();
}
}}
step={1}
@@ -172,6 +167,7 @@ export const RangePopover = ({
{
const newRange = {
@@ -185,7 +181,9 @@ export const RangePopover = ({
'xpack.lens.indexPattern.ranges.customRangeLabelPlaceholder',
{ defaultMessage: 'Custom label' }
)}
- onSubmit={onSubmit}
+ onSubmit={() => {
+ triggerClose();
+ }}
compressed
dataTestSubj="indexPattern-ranges-label"
/>
@@ -205,15 +203,11 @@ export const AdvancedRangeEditor = ({
onToggleEditor: () => void;
formatter: IFieldFormat;
}) => {
+ const [activeRangeId, setActiveRangeId] = useState('');
// use a local state to store ids with range objects
const [localRanges, setLocalRanges] = useState(() =>
ranges.map((range) => ({ ...range, id: generateId() }))
);
- // we need to force the open state of the popover from the outside in some scenarios
- // so we need an extra state here
- const [isOpenByCreation, setIsOpenByCreation] = useState(false);
-
- const lastIndex = localRanges.length - 1;
// Update locally all the time, but bounce the parents prop function to avoid too many requests
// Avoid to trigger on first render
@@ -227,15 +221,27 @@ export const AdvancedRangeEditor = ({
);
const addNewRange = () => {
+ const newRangeId = generateId();
+
setLocalRanges([
...localRanges,
{
- id: generateId(),
+ id: newRangeId,
from: localRanges[localRanges.length - 1].to,
to: Infinity,
label: '',
},
]);
+
+ setActiveRangeId(newRangeId);
+ };
+
+ const changeActiveRange = (rangeId: string) => {
+ let newActiveRangeId = rangeId;
+ if (activeRangeId === rangeId) {
+ newActiveRangeId = ''; // toggle off
+ }
+ setActiveRangeId(newActiveRangeId);
};
return (
@@ -281,7 +287,8 @@ export const AdvancedRangeEditor = ({
>
changeActiveRange('')}
setRange={(newRange: LocalRangeType) => {
const newRanges = [...localRanges];
if (newRange.id === newRanges[idx].id) {
@@ -291,10 +298,10 @@ export const AdvancedRangeEditor = ({
}
setLocalRanges(newRanges);
}}
- Button={({ onClick }: { onClick: MouseEventHandler }) => (
+ button={
changeActiveRange(range.id)}
className="lnsRangesOperation__popoverButton"
data-test-subj="indexPattern-ranges-popover-trigger"
>
@@ -306,7 +313,7 @@ export const AdvancedRangeEditor = ({
{getBetterLabel(range, formatter)}
- )}
+ }
/>
))}
@@ -314,7 +321,6 @@ export const AdvancedRangeEditor = ({
{
addNewRange();
- setIsOpenByCreation(true);
}}
label={i18n.translate('xpack.lens.indexPattern.ranges.addRange', {
defaultMessage: 'Add range',
diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/shared_components/label_input.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/shared_components/label_input.tsx
index 81f1b669a53a2..4bc461aaa319b 100644
--- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/shared_components/label_input.tsx
+++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/shared_components/label_input.tsx
@@ -5,7 +5,7 @@
* 2.0.
*/
-import React from 'react';
+import React, { useRef } from 'react';
import { EuiFieldText, keys } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { useDebouncedValue } from '../../../../shared_components';
@@ -28,6 +28,7 @@ export const LabelInput = ({
compressed?: boolean;
}) => {
const { inputValue, handleInputChange } = useDebouncedValue({ value, onChange });
+ const localKeyHold = useRef(false);
return (
{
+ localKeyHold.current = true;
+ }}
onKeyUp={({ key }: React.KeyboardEvent) => {
- if (keys.ENTER === key && onSubmit) {
+ // only submit on key up in case the user started the keypress while the input was focused
+ if (localKeyHold.current && keys.ENTER === key && onSubmit) {
onSubmit();
}
+ localKeyHold.current = false;
}}
prepend={i18n.translate('xpack.lens.labelInput.label', {
defaultMessage: 'Label',