Skip to content

Commit

Permalink
[7.10] [UX] Fix search term reset from url (#81654) (#81821)
Browse files Browse the repository at this point in the history
Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
  • Loading branch information
shahzad31 and kibanamachine authored Oct 28, 2020
1 parent 7ecedd1 commit c5d28ef
Show file tree
Hide file tree
Showing 4 changed files with 117 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import React, {
useRef,
useState,
KeyboardEvent,
useEffect,
} from 'react';
import {
EuiFlexGroup,
Expand Down Expand Up @@ -67,6 +68,7 @@ interface Props {
searchValue: string;
onClose: () => void;
popoverIsOpen: boolean;
initialValue?: string;
setPopoverIsOpen: React.Dispatch<SetStateAction<boolean>>;
}

Expand All @@ -80,6 +82,7 @@ export function SelectableUrlList({
onClose,
popoverIsOpen,
setPopoverIsOpen,
initialValue,
}: Props) {
const [darkMode] = useUiSetting$<boolean>('theme:darkMode');

Expand All @@ -92,6 +95,9 @@ export function SelectableUrlList({
if (evt.key.toLowerCase() === 'enter') {
onTermChange();
setPopoverIsOpen(false);
if (searchRef) {
searchRef.blur();
}
}
};

Expand Down Expand Up @@ -126,6 +132,16 @@ export function SelectableUrlList({
}
};

useEffect(() => {
if (searchRef && initialValue) {
searchRef.value = initialValue;
}

// only want to call it at initial render to set value
// coming from initial value/url
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [searchRef]);

const loadingMessage = (
<EuiSelectableMessage style={{ minHeight: 300 }}>
<EuiLoadingSpinner size="l" />
Expand Down Expand Up @@ -165,12 +181,12 @@ export function SelectableUrlList({
renderOption={selectableRenderOptions}
singleSelection={false}
searchProps={{
placeholder: I18LABELS.searchByUrl,
isClearable: true,
onFocus: searchOnFocus,
onBlur: searchOnBlur,
onInput: onSearchInput,
inputRef: setSearchRef,
placeholder: I18LABELS.searchByUrl,
}}
listProps={{
rowHeight: 68,
Expand All @@ -197,7 +213,7 @@ export function SelectableUrlList({
<EuiText size="s">
<FormattedMessage
id="xpack.apm.ux.url.hitEnter.include"
defaultMessage="Hit {icon} to include all urls matching {searchValue}"
defaultMessage="Hit {icon} or click apply to include all urls matching {searchValue}"
values={{
searchValue: <strong>{searchValue}</strong>,
icon: (
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
import React from 'react';
import { createMemoryHistory } from 'history';
import * as fetcherHook from '../../../../../../hooks/useFetcher';
import { SelectableUrlList } from '../SelectableUrlList';
import { render } from '../../../utils/test_helper';

describe('SelectableUrlList', () => {
it('it uses search term value from url', () => {
jest.spyOn(fetcherHook, 'useFetcher').mockReturnValue({
data: {},
status: fetcherHook.FETCH_STATUS.SUCCESS,
refetch: jest.fn(),
});

const customHistory = createMemoryHistory({
initialEntries: ['/?searchTerm=blog'],
});

const { getByDisplayValue } = render(
<SelectableUrlList
initialValue={'blog'}
loading={false}
data={{ items: [], total: 0 }}
onChange={jest.fn()}
searchValue={'blog'}
onClose={jest.fn()}
onInputChange={jest.fn()}
onTermChange={jest.fn()}
popoverIsOpen={false}
setPopoverIsOpen={jest.fn()}
/>,
{ customHistory }
);
expect(getByDisplayValue('blog')).toBeInTheDocument();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,9 @@ export function URLSearch({ onChange: onFilterChange }: Props) {

const [popoverIsOpen, setPopoverIsOpen] = useState(false);

const [searchValue, setSearchValue] = useState('');
const [searchValue, setSearchValue] = useState(searchTerm ?? '');

const [debouncedValue, setDebouncedValue] = useState('');
const [debouncedValue, setDebouncedValue] = useState(searchTerm ?? '');

useDebounce(
() => {
Expand All @@ -44,12 +44,16 @@ export function URLSearch({ onChange: onFilterChange }: Props) {

const updateSearchTerm = useCallback(
(searchTermN: string) => {
const newQuery = {
...toQuery(history.location.search),
searchTerm: searchTermN || undefined,
};
if (!searchTermN) {
delete newQuery.searchTerm;
}
const newLocation = {
...history.location,
search: fromQuery({
...toQuery(history.location.search),
searchTerm: searchTermN,
}),
search: fromQuery(newQuery),
};
history.push(newLocation);
},
Expand Down Expand Up @@ -133,6 +137,7 @@ export function URLSearch({ onChange: onFilterChange }: Props) {
<h4>{I18LABELS.url}</h4>
</EuiTitle>
<SelectableUrlList
initialValue={searchTerm}
loading={isLoading}
onInputChange={onInputChange}
onTermChange={onTermChange}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

import React from 'react';
import { render as testLibRender } from '@testing-library/react';
import { CoreStart } from 'kibana/public';
import { of } from 'rxjs';
import { createMemoryHistory } from 'history';
import { Router } from 'react-router-dom';
import { MemoryHistory } from 'history';
import { EuiThemeProvider } from '../../../../../../observability/public';
import { KibanaContextProvider } from '../../../../../../../../src/plugins/kibana_react/public';
import { UrlParamsProvider } from '../../../../context/UrlParamsContext';

export const core = ({
http: {
basePath: {
prepend: jest.fn(),
},
},
uiSettings: {
get: (key: string) => true,
get$: (key: string) => of(true),
},
} as unknown) as CoreStart;

export const render = (
component: React.ReactNode,
options: { customHistory: MemoryHistory }
) => {
const history = options?.customHistory ?? createMemoryHistory();

history.location.key = 'TestKeyForTesting';

return testLibRender(
<Router history={history}>
<KibanaContextProvider services={{ ...core }}>
<UrlParamsProvider>
<EuiThemeProvider>{component}</EuiThemeProvider>
</UrlParamsProvider>
</KibanaContextProvider>
</Router>
);
};

0 comments on commit c5d28ef

Please sign in to comment.