import React, { useRef, useEffect, useState } from "react"; import { Row } from "react-table"; import { isEmpty, pullAllBy } from "lodash"; import { IHost } from "interfaces/host"; import { HOSTS_SEARCH_BOX_PLACEHOLDER } from "utilities/constants"; import DataError from "components/DataError"; // @ts-ignore import InputFieldWithIcon from "components/forms/fields/InputFieldWithIcon/InputFieldWithIcon"; import TableContainer from "components/TableContainer"; import { ITargestInputHostTableConfig } from "./TargetsInputHostsTableConfig"; interface ITargetsInputProps { searchText: string; searchResults: IHost[]; isTargetsLoading: boolean; hasFetchError: boolean; targetedHosts: IHost[]; searchResultsTableConfig: ITargestInputHostTableConfig[]; selectedHostsTableConifg: ITargestInputHostTableConfig[]; /** disabled pagination for the results table. The pagination is currently * client side pagination. Defaults to `false` */ disablePagination?: boolean; label?: string; placeholder?: string; autofocus?: boolean; setSearchText: (value: string) => void; handleRowSelect: (value: Row) => void; } const baseClass = "targets-input"; const DEFAULT_LABEL = "Target specific hosts"; const TargetsInput = ({ searchText, searchResults, isTargetsLoading, hasFetchError, targetedHosts, searchResultsTableConfig, selectedHostsTableConifg, disablePagination = false, label = DEFAULT_LABEL, placeholder = HOSTS_SEARCH_BOX_PLACEHOLDER, autofocus = false, handleRowSelect, setSearchText, }: ITargetsInputProps): JSX.Element => { const dropdownRef = useRef(null); const dropdownHosts = searchResults && pullAllBy(searchResults, targetedHosts, "id"); const [isActiveSearch, setIsActiveSearch] = useState(false); const isSearchError = !isEmpty(searchText) && hasFetchError; // Closes target search results when clicking outside of results // But not during API loading state as it will reopen on API return useEffect(() => { if (!isTargetsLoading) { const handleClickOutside = (event: MouseEvent) => { if ( dropdownRef.current && !dropdownRef.current.contains(event.target as Node) ) { setIsActiveSearch(false); } }; document.addEventListener("mousedown", handleClickOutside); return () => { document.removeEventListener("mousedown", handleClickOutside); }; } }, [isTargetsLoading]); useEffect(() => { setIsActiveSearch( !isEmpty(searchText) && (!hasFetchError || isTargetsLoading) ); }, [searchText, hasFetchError, isTargetsLoading]); return (
{isActiveSearch && (
> columnConfigs={searchResultsTableConfig} data={dropdownHosts} isLoading={isTargetsLoading} emptyComponent={() => (

No matching hosts.

Expecting to see hosts? Try again in a few seconds as the system catches up.

)} showMarkAllPages={false} isAllPagesSelected={false} disableCount disablePagination disableMultiRowSelect onClickRow={handleRowSelect} keyboardSelectableRows />
)} {isSearchError && (
)}
<>} />
); }; export default TargetsInput;