Skip to content

Commit

Permalink
Multi-line kql bar (elastic#70140)
Browse files Browse the repository at this point in the history
* 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 <[email protected]>
Co-authored-by: Elastic Machine <[email protected]>
Co-authored-by: Liza K <[email protected]>
  • Loading branch information
4 people authored Jul 8, 2020
1 parent 93ac059 commit c815c96
Show file tree
Hide file tree
Showing 15 changed files with 237 additions and 123 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,5 @@
<b>Signature:</b>

```typescript
QueryStringInput: React.FC<Pick<Props, "query" | "prepend" | "placeholder" | "onChange" | "onBlur" | "onSubmit" | "indexPatterns" | "dataTestSubj" | "screenTitle" | "disableAutoFocus" | "persistedLog" | "bubbleSubmitEvent" | "languageSwitcherPopoverAnchorPosition">>
QueryStringInput: React.FC<Pick<Props, "query" | "prepend" | "placeholder" | "onChange" | "onBlur" | "onSubmit" | "indexPatterns" | "dataTestSubj" | "screenTitle" | "disableAutoFocus" | "persistedLog" | "bubbleSubmitEvent" | "languageSwitcherPopoverAnchorPosition" | "onChangeQueryInputFocus">>
```
3 changes: 1 addition & 2 deletions src/plugins/data/public/public.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,6 @@ import { ErrorToastOptions } from 'src/core/public/notifications';
import { EuiButtonEmptyProps } from '@elastic/eui';
import { EuiComboBoxProps } from '@elastic/eui';
import { EuiConfirmModalProps } from '@elastic/eui';
import { EuiFieldText } from '@elastic/eui';
import { EuiGlobalToastListToast } from '@elastic/eui';
import { ExclusiveUnion } from '@elastic/eui';
import { ExistsParams } from 'elasticsearch';
Expand Down Expand Up @@ -1482,7 +1481,7 @@ export interface QueryState {
// Warning: (ae-missing-release-tag) "QueryStringInput" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export const QueryStringInput: React.FC<Pick<Props_3, "query" | "prepend" | "placeholder" | "onChange" | "onBlur" | "onSubmit" | "indexPatterns" | "dataTestSubj" | "screenTitle" | "disableAutoFocus" | "persistedLog" | "bubbleSubmitEvent" | "languageSwitcherPopoverAnchorPosition">>;
export const QueryStringInput: React.FC<Pick<Props_3, "query" | "prepend" | "placeholder" | "onChange" | "onBlur" | "onSubmit" | "indexPatterns" | "dataTestSubj" | "screenTitle" | "disableAutoFocus" | "persistedLog" | "bubbleSubmitEvent" | "languageSwitcherPopoverAnchorPosition" | "onChangeQueryInputFocus">>;

// @public (undocumented)
export type QuerySuggestion = QuerySuggestionBasic | QuerySuggestionField;
Expand Down
44 changes: 44 additions & 0 deletions src/plugins/data/public/ui/query_string_input/_query_bar.scss
Original file line number Diff line number Diff line change
@@ -1,3 +1,41 @@
.kbnQueryBar__wrap {
max-width: 100%;
z-index: $euiZContentMenu;
}

// Uses the append style, but no bordering
.kqlQueryBar__languageSwitcherButton {
border-right: none !important;
}

.kbnQueryBar__textarea {
z-index: $euiZContentMenu;
resize: none !important; // When in the group, it will autosize
height: $euiSizeXXL;
// Unlike most inputs within layout control groups, the text area still needs a border.
// These adjusts help it sit above the control groups shadow to line up correctly.
padding-top: $euiSizeS + 3px !important;
transform: translateY(-2px);
padding: $euiSizeS - 1px;

&:not(:focus) {
@include euiYScrollWithShadows;
white-space: nowrap;
overflow-y: hidden;
overflow-x: hidden;
border: none;
box-shadow: none;
}

// When focused, let it scroll
&:focus {
overflow-x: auto;
overflow-y: auto;
width: calc(100% + 1px); // To overtake the group's fake border
white-space: normal;
}
}

@include euiBreakpoint('xs', 's') {
.kbnQueryBar--withDatePicker {
> :first-child {
Expand All @@ -16,5 +54,11 @@
// sass-lint:disable-block no-important
flex-grow: 0 !important;
flex-basis: auto !important;
margin-right: -$euiSizeXS !important;

&.kbnQueryBar__datePickerWrapper-isHidden {
width: 0;
overflow: hidden;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ export function QueryLanguageSwitcher(props: Props) {
<EuiButtonEmpty
size="xs"
onClick={() => setIsPopoverOpen(!isPopoverOpen)}
className="euiFormControlLayout__append"
className="euiFormControlLayout__append kqlQueryBar__languageSwitcherButton"
data-test-subj={'switchQueryLanguageButton'}
>
{props.language === 'lucene' ? luceneLabel : kqlLabel}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ interface Props {

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

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

function onChangeQueryInputFocus(isFocused: boolean) {
setIsQueryInputFocused(isFocused);
}

function onTimeChange({
start,
end,
Expand Down Expand Up @@ -182,6 +187,7 @@ export function QueryBarTopRow(props: Props) {
query={props.query!}
screenTitle={props.screenTitle}
onChange={onQueryChange}
onChangeQueryInputFocus={onChangeQueryInputFocus}
onSubmit={onInputSubmit}
persistedLog={persistedLog}
dataTestSubj={props.dataTestSubj}
Expand Down Expand Up @@ -268,8 +274,12 @@ export function QueryBarTopRow(props: Props) {
};
});

const wrapperClasses = classNames('kbnQueryBar__datePickerWrapper', {
'kbnQueryBar__datePickerWrapper-isHidden': isQueryInputFocused,
});

return (
<EuiFlexItem className="kbnQueryBar__datePickerWrapper">
<EuiFlexItem className={wrapperClasses}>
<EuiSuperDatePicker
start={props.dateRangeFrom}
end={props.dateRangeTo}
Expand All @@ -283,6 +293,7 @@ export function QueryBarTopRow(props: Props) {
commonlyUsedRanges={commonlyUsedRanges}
dateFormat={uiSettings!.get('dateFormat')}
isAutoRefreshOnly={props.showAutoRefreshOnly}
className="kbnQueryBar__datePicker"
/>
</EuiFlexItem>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import {
mockPersistedLogFactory,
} from './query_string_input.test.mocks';

import { EuiFieldText } from '@elastic/eui';
import { EuiTextArea } from '@elastic/eui';
import React from 'react';
import { QueryLanguageSwitcher } from './language_switcher';
import { QueryStringInput, QueryStringInputUI } from './query_string_input';
Expand Down Expand Up @@ -102,7 +102,7 @@ describe('QueryStringInput', () => {
indexPatterns: [stubIndexPatternWithFields],
})
);
expect(component.find(EuiFieldText).props().value).toBe(kqlQuery.query);
expect(component.find(EuiTextArea).props().value).toBe(kqlQuery.query);
expect(component.find(QueryLanguageSwitcher).prop('language')).toBe(kqlQuery.language);
});

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

it('Should disable autoFocus on EuiFieldText when disableAutoFocus prop is true', () => {
it('Should disable autoFocus on EuiTextArea when disableAutoFocus prop is true', () => {
const component = mount(
wrapQueryStringInputInContext({
query: kqlQuery,
Expand All @@ -126,7 +126,7 @@ describe('QueryStringInput', () => {
disableAutoFocus: true,
})
);
expect(component.find(EuiFieldText).prop('autoFocus')).toBeFalsy();
expect(component.find(EuiTextArea).prop('autoFocus')).toBeFalsy();
});

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

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

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

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

expect(mockPersistedLog.add).toHaveBeenCalledWith('response:200');
Expand Down
Loading

0 comments on commit c815c96

Please sign in to comment.