Skip to content

Commit fa131fd

Browse files
snideXavierMelasticmachineLiza K
committed
Multi-line kql bar (#70140)
* Multiline kql bar * fix id * use visibility rather than display to hide stuff, cross fingers for tests * another vis trick for tests * quasi fix tests, still some failures * caroline feedback * fun! * fix for mouse * fix test * check api * fix unit test on query_string_input * Fix cypress test * handle the resize of the height of the textarea when the window have been resize Co-authored-by: Xavier Mouligneau <189600+XavierM@users.noreply.github.com> Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com> Co-authored-by: Liza K <liza.katz@elastic.co>
1 parent 0c0e358 commit fa131fd

15 files changed

Lines changed: 237 additions & 123 deletions

File tree

docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinput.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,5 @@
77
<b>Signature:</b>
88

99
```typescript
10-
QueryStringInput: React.FC<Pick<Props, "query" | "prepend" | "placeholder" | "onChange" | "onBlur" | "onSubmit" | "indexPatterns" | "dataTestSubj" | "screenTitle" | "disableAutoFocus" | "persistedLog" | "bubbleSubmitEvent" | "languageSwitcherPopoverAnchorPosition">>
10+
QueryStringInput: React.FC<Pick<Props, "query" | "prepend" | "placeholder" | "onChange" | "onBlur" | "onSubmit" | "indexPatterns" | "dataTestSubj" | "screenTitle" | "disableAutoFocus" | "persistedLog" | "bubbleSubmitEvent" | "languageSwitcherPopoverAnchorPosition" | "onChangeQueryInputFocus">>
1111
```

src/plugins/data/public/public.api.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,6 @@ import { ErrorToastOptions } from 'src/core/public/notifications';
5151
import { EuiButtonEmptyProps } from '@elastic/eui';
5252
import { EuiComboBoxProps } from '@elastic/eui';
5353
import { EuiConfirmModalProps } from '@elastic/eui';
54-
import { EuiFieldText } from '@elastic/eui';
5554
import { EuiGlobalToastListToast } from '@elastic/eui';
5655
import { ExclusiveUnion } from '@elastic/eui';
5756
import { ExistsParams } from 'elasticsearch';
@@ -1492,7 +1491,7 @@ export interface QueryState {
14921491
// Warning: (ae-missing-release-tag) "QueryStringInput" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
14931492
//
14941493
// @public (undocumented)
1495-
export const QueryStringInput: React.FC<Pick<Props_3, "query" | "prepend" | "placeholder" | "onChange" | "onBlur" | "onSubmit" | "indexPatterns" | "dataTestSubj" | "screenTitle" | "disableAutoFocus" | "persistedLog" | "bubbleSubmitEvent" | "languageSwitcherPopoverAnchorPosition">>;
1494+
export const QueryStringInput: React.FC<Pick<Props_3, "query" | "prepend" | "placeholder" | "onChange" | "onBlur" | "onSubmit" | "indexPatterns" | "dataTestSubj" | "screenTitle" | "disableAutoFocus" | "persistedLog" | "bubbleSubmitEvent" | "languageSwitcherPopoverAnchorPosition" | "onChangeQueryInputFocus">>;
14961495

14971496
// @public (undocumented)
14981497
export type QuerySuggestion = QuerySuggestionBasic | QuerySuggestionField;

src/plugins/data/public/ui/query_string_input/_query_bar.scss

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,41 @@
1+
.kbnQueryBar__wrap {
2+
max-width: 100%;
3+
z-index: $euiZContentMenu;
4+
}
5+
6+
// Uses the append style, but no bordering
7+
.kqlQueryBar__languageSwitcherButton {
8+
border-right: none !important;
9+
}
10+
11+
.kbnQueryBar__textarea {
12+
z-index: $euiZContentMenu;
13+
resize: none !important; // When in the group, it will autosize
14+
height: $euiSizeXXL;
15+
// Unlike most inputs within layout control groups, the text area still needs a border.
16+
// These adjusts help it sit above the control groups shadow to line up correctly.
17+
padding-top: $euiSizeS + 3px !important;
18+
transform: translateY(-2px);
19+
padding: $euiSizeS - 1px;
20+
21+
&:not(:focus) {
22+
@include euiYScrollWithShadows;
23+
white-space: nowrap;
24+
overflow-y: hidden;
25+
overflow-x: hidden;
26+
border: none;
27+
box-shadow: none;
28+
}
29+
30+
// When focused, let it scroll
31+
&:focus {
32+
overflow-x: auto;
33+
overflow-y: auto;
34+
width: calc(100% + 1px); // To overtake the group's fake border
35+
white-space: normal;
36+
}
37+
}
38+
139
@include euiBreakpoint('xs', 's') {
240
.kbnQueryBar--withDatePicker {
341
> :first-child {
@@ -16,5 +54,11 @@
1654
// sass-lint:disable-block no-important
1755
flex-grow: 0 !important;
1856
flex-basis: auto !important;
57+
margin-right: -$euiSizeXS !important;
58+
59+
&.kbnQueryBar__datePickerWrapper-isHidden {
60+
width: 0;
61+
overflow: hidden;
62+
}
1963
}
2064
}

src/plugins/data/public/ui/query_string_input/language_switcher.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ export function QueryLanguageSwitcher(props: Props) {
6060
<EuiButtonEmpty
6161
size="xs"
6262
onClick={() => setIsPopoverOpen(!isPopoverOpen)}
63-
className="euiFormControlLayout__append"
63+
className="euiFormControlLayout__append kqlQueryBar__languageSwitcherButton"
6464
data-test-subj={'switchQueryLanguageButton'}
6565
>
6666
{props.language === 'lucene' ? luceneLabel : kqlLabel}

src/plugins/data/public/ui/query_string_input/query_bar_top_row.tsx

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ interface Props {
6969

7070
export function QueryBarTopRow(props: Props) {
7171
const [isDateRangeInvalid, setIsDateRangeInvalid] = useState(false);
72+
const [isQueryInputFocused, setIsQueryInputFocused] = useState(false);
7273

7374
const kibana = useKibana<IDataPluginServices>();
7475
const { uiSettings, notifications, storage, appName, docLinks } = kibana.services;
@@ -107,6 +108,10 @@ export function QueryBarTopRow(props: Props) {
107108
});
108109
}
109110

111+
function onChangeQueryInputFocus(isFocused: boolean) {
112+
setIsQueryInputFocused(isFocused);
113+
}
114+
110115
function onTimeChange({
111116
start,
112117
end,
@@ -182,6 +187,7 @@ export function QueryBarTopRow(props: Props) {
182187
query={props.query!}
183188
screenTitle={props.screenTitle}
184189
onChange={onQueryChange}
190+
onChangeQueryInputFocus={onChangeQueryInputFocus}
185191
onSubmit={onInputSubmit}
186192
persistedLog={persistedLog}
187193
dataTestSubj={props.dataTestSubj}
@@ -268,8 +274,12 @@ export function QueryBarTopRow(props: Props) {
268274
};
269275
});
270276

277+
const wrapperClasses = classNames('kbnQueryBar__datePickerWrapper', {
278+
'kbnQueryBar__datePickerWrapper-isHidden': isQueryInputFocused,
279+
});
280+
271281
return (
272-
<EuiFlexItem className="kbnQueryBar__datePickerWrapper">
282+
<EuiFlexItem className={wrapperClasses}>
273283
<EuiSuperDatePicker
274284
start={props.dateRangeFrom}
275285
end={props.dateRangeTo}
@@ -283,6 +293,7 @@ export function QueryBarTopRow(props: Props) {
283293
commonlyUsedRanges={commonlyUsedRanges}
284294
dateFormat={uiSettings!.get('dateFormat')}
285295
isAutoRefreshOnly={props.showAutoRefreshOnly}
296+
className="kbnQueryBar__datePicker"
286297
/>
287298
</EuiFlexItem>
288299
);

src/plugins/data/public/ui/query_string_input/query_string_input.test.tsx

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ import {
2323
mockPersistedLogFactory,
2424
} from './query_string_input.test.mocks';
2525

26-
import { EuiFieldText } from '@elastic/eui';
26+
import { EuiTextArea } from '@elastic/eui';
2727
import React from 'react';
2828
import { QueryLanguageSwitcher } from './language_switcher';
2929
import { QueryStringInput, QueryStringInputUI } from './query_string_input';
@@ -102,7 +102,7 @@ describe('QueryStringInput', () => {
102102
indexPatterns: [stubIndexPatternWithFields],
103103
})
104104
);
105-
expect(component.find(EuiFieldText).props().value).toBe(kqlQuery.query);
105+
expect(component.find(EuiTextArea).props().value).toBe(kqlQuery.query);
106106
expect(component.find(QueryLanguageSwitcher).prop('language')).toBe(kqlQuery.language);
107107
});
108108

@@ -117,7 +117,7 @@ describe('QueryStringInput', () => {
117117
expect(component.find(QueryLanguageSwitcher).prop('language')).toBe(luceneQuery.language);
118118
});
119119

120-
it('Should disable autoFocus on EuiFieldText when disableAutoFocus prop is true', () => {
120+
it('Should disable autoFocus on EuiTextArea when disableAutoFocus prop is true', () => {
121121
const component = mount(
122122
wrapQueryStringInputInContext({
123123
query: kqlQuery,
@@ -126,7 +126,7 @@ describe('QueryStringInput', () => {
126126
disableAutoFocus: true,
127127
})
128128
);
129-
expect(component.find(EuiFieldText).prop('autoFocus')).toBeFalsy();
129+
expect(component.find(EuiTextArea).prop('autoFocus')).toBeFalsy();
130130
});
131131

132132
it('Should create a unique PersistedLog based on the appName and query language', () => {
@@ -179,7 +179,7 @@ describe('QueryStringInput', () => {
179179

180180
const instance = component.find('QueryStringInputUI').instance() as QueryStringInputUI;
181181
const input = instance.inputRef;
182-
const inputWrapper = component.find(EuiFieldText).find('input');
182+
const inputWrapper = component.find(EuiTextArea).find('textarea');
183183
inputWrapper.simulate('keyDown', { target: input, keyCode: 13, key: 'Enter', metaKey: true });
184184

185185
expect(mockCallback).toHaveBeenCalledTimes(1);
@@ -199,7 +199,7 @@ describe('QueryStringInput', () => {
199199

200200
const instance = component.find('QueryStringInputUI').instance() as QueryStringInputUI;
201201
const input = instance.inputRef;
202-
const inputWrapper = component.find(EuiFieldText).find('input');
202+
const inputWrapper = component.find(EuiTextArea).find('textarea');
203203
inputWrapper.simulate('keyDown', { target: input, keyCode: 13, key: 'Enter', metaKey: true });
204204

205205
expect(mockPersistedLog.add).toHaveBeenCalledWith('response:200');

0 commit comments

Comments
 (0)