Skip to content

Commit

Permalink
[Infra UI] Show syntax error for the Processes search input (elastic#…
Browse files Browse the repository at this point in the history
…165245)

Closes elastic#164970 
Fixes elastic#165287

## Summary

- Adds an error message to the Processes tab for cases when user types
an invalid term into the search field.
- Also fixes the issue when the search field (on all tabs) would lose
focus while typing

**Showing the error**

https://github.com/elastic/kibana/assets/793851/a56ba086-decc-49f8-8a51-5e44ddd17d1d

**Before the change, field losses focus**

https://github.com/elastic/kibana/assets/793851/23cb2435-ec5c-4e3a-b955-97f2eca03307

**After the change**

https://github.com/elastic/kibana/assets/793851/a2c23da0-0d5f-4f7e-8835-e1d2e4eed4e6


## How to test
- Checkout locally
- Open host details as a page
- Go to the Processes tab and type "," in to the search field
- Make sure the app does not crash and shows the error
- Check the same for host details in the flyout
  • Loading branch information
mykolaharmash authored Aug 31, 2023
1 parent 210e75c commit be96350
Show file tree
Hide file tree
Showing 5 changed files with 66 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ export const Processes = () => {
const { asset, assetType } = useAssetDetailsRenderPropsContext();

const [searchText, setSearchText] = useState(urlState?.processSearch ?? '');
const [searchQueryError, setSearchQueryError] = useState<Error | null>(null);
const [searchBarState, setSearchBarState] = useState<Query>(() =>
searchText ? Query.parse(searchText) : Query.MATCH_ALL
);
Expand All @@ -71,22 +72,28 @@ export const Processes = () => {

const debouncedSearchOnChange = useMemo(() => {
return debounce<(queryText: string) => void>((queryText) => {
setUrlState({ processSearch: queryText });
setSearchText(queryText);
}, 500);
}, [setUrlState]);
}, []);

const searchBarOnChange = useCallback(
({ query, queryText }) => {
setSearchBarState(query);
debouncedSearchOnChange(queryText);
({ query, queryText, error: queryError }) => {
if (queryError) {
setSearchQueryError(queryError);
} else {
setUrlState({ processSearch: queryText });
setSearchQueryError(null);
setSearchBarState(query);
debouncedSearchOnChange(queryText);
}
},
[debouncedSearchOnChange]
[debouncedSearchOnChange, setUrlState]
);

const clearSearchBar = useCallback(() => {
setSearchBarState(Query.MATCH_ALL);
setUrlState({ processSearch: '' });
setSearchQueryError(null);
setSearchText('');
}, [setUrlState]);

Expand Down Expand Up @@ -167,6 +174,7 @@ export const Processes = () => {
isLoading={loading || !response}
processList={response?.processList ?? []}
sortBy={sortBy}
error={searchQueryError?.message}
setSortBy={setSortBy}
clearSearchBar={clearSearchBar}
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ import {
EuiCode,
} from '@elastic/eui';
import { css } from '@emotion/react';
import { EuiTableRow } from '@elastic/eui';
import { EuiIcon } from '@elastic/eui';
import { FORMATTERS } from '../../../../../common/formatters';
import type { SortBy } from '../../../../pages/metrics/inventory_view/hooks/use_process_list';
import type { Process } from './types';
Expand All @@ -40,6 +42,7 @@ interface TableProps {
currentTime: number;
isLoading: boolean;
sortBy: SortBy;
error?: string;
setSortBy: (s: SortBy) => void;
clearSearchBar: () => void;
}
Expand Down Expand Up @@ -73,6 +76,7 @@ export const ProcessesTable = ({
currentTime,
isLoading,
sortBy,
error,
setSortBy,
clearSearchBar,
}: TableProps) => {
Expand Down Expand Up @@ -182,7 +186,11 @@ export const ProcessesTable = ({
}
`}
>
<ProcessesTableBody items={currentItems} currentTime={currentTime} />
{error ? (
<ProcessesTableError error={error} />
) : (
<ProcessesTableBody items={currentItems} currentTime={currentTime} />
)}
</EuiTableBody>
</EuiTable>
);
Expand All @@ -205,6 +213,32 @@ const LoadingPlaceholder = () => {
);
};

interface ProcessesTableErrorProps {
error: string;
}

const ProcessesTableError = ({ error }: ProcessesTableErrorProps) => {
const { euiTheme } = useEuiTheme();

return (
<EuiTableRow>
<EuiTableRowCell
data-test-subj="infraAssetDetailsProcessesSearchInputError"
style={{
paddingTop: `${euiTheme.size.s}`,
paddingBottom: `${euiTheme.size.s}`,
}}
align="center"
colSpan={columns.length + 1}
mobileOptions={{ width: '100%' }}
textOnly={true}
>
<EuiIcon type="minusInCircle" color="danger" /> {error}
</EuiTableRowCell>
</EuiTableRow>
);
};

interface TableBodyProps {
items: Process[];
currentTime: number;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,6 @@ export const MetricDetail = () => {
params: { type: nodeType, node: nodeName },
} = useRouteMatch<{ type: InventoryItemType; node: string }>();

const PageContent = () => (nodeType === 'host' ? <AssetDetailPage /> : <MetricDetailPage />);

useMetricsBreadcrumbs([
{
text: nodeName,
Expand All @@ -30,7 +28,7 @@ export const MetricDetail = () => {
return (
<EuiErrorBoundary>
<MetricsTimeProvider>
<PageContent />
{nodeType === 'host' ? <AssetDetailPage /> : <MetricDetailPage />}
</MetricsTimeProvider>
</EuiErrorBoundary>
);
Expand Down
8 changes: 8 additions & 0 deletions x-pack/test/functional/apps/infra/node_details.ts
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,14 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => {
});
await searchInput.clearValue();
});

it('shows an error message when typing invalid term into the search input', async () => {
const searchInput = await pageObjects.assetDetails.getProcessesSearchField();

await pageObjects.assetDetails.processesSearchInputErrorMissing();
await searchInput.type(',');
await pageObjects.assetDetails.processesSearchInputErrorExists();
});
});

describe('Logs Tab', () => {
Expand Down
8 changes: 8 additions & 0 deletions x-pack/test/functional/page_objects/asset_details.ts
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,14 @@ export function AssetDetailsProvider({ getService }: FtrProviderContext) {
return await testSubjects.find('infraAssetDetailsProcessesSearchBarInput');
},

async processesSearchInputErrorMissing() {
return await testSubjects.missingOrFail('infraAssetDetailsProcessesSearchInputError');
},

async processesSearchInputErrorExists() {
return await testSubjects.existOrFail('infraAssetDetailsProcessesSearchInputError');
},

// Logs
async clickLogsTab() {
return testSubjects.click('infraAssetDetailsLogsTab');
Expand Down

0 comments on commit be96350

Please sign in to comment.