2022-06-10 18:29:45 +00:00
|
|
|
import React from "react";
|
|
|
|
|
import { Row } from "react-table";
|
2022-07-22 16:13:37 +00:00
|
|
|
import { isEmpty, pullAllBy } from "lodash";
|
2022-06-10 18:29:45 +00:00
|
|
|
|
|
|
|
|
import { IHost } from "interfaces/host";
|
2022-07-22 16:13:37 +00:00
|
|
|
import { HOSTS_SEARCH_BOX_PLACEHOLDER } from "utilities/constants";
|
2022-06-10 18:29:45 +00:00
|
|
|
|
|
|
|
|
import DataError from "components/DataError";
|
|
|
|
|
// @ts-ignore
|
2024-02-29 13:49:36 +00:00
|
|
|
import InputFieldWithIcon from "components/forms/fields/InputFieldWithIcon/InputFieldWithIcon";
|
2022-06-10 18:29:45 +00:00
|
|
|
import TableContainer from "components/TableContainer";
|
2024-07-02 16:32:35 +00:00
|
|
|
import Spinner from "components/Spinner";
|
2024-04-16 16:22:08 +00:00
|
|
|
import { ITargestInputHostTableConfig } from "./TargetsInputHostsTableConfig";
|
2022-06-10 18:29:45 +00:00
|
|
|
|
|
|
|
|
interface ITargetsInputProps {
|
2024-04-16 16:22:08 +00:00
|
|
|
tabIndex?: number;
|
2022-06-10 18:29:45 +00:00
|
|
|
searchText: string;
|
|
|
|
|
searchResults: IHost[];
|
|
|
|
|
isTargetsLoading: boolean;
|
|
|
|
|
hasFetchError: boolean;
|
|
|
|
|
targetedHosts: IHost[];
|
2024-04-16 16:22:08 +00:00
|
|
|
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;
|
2022-06-10 18:29:45 +00:00
|
|
|
setSearchText: (value: string) => void;
|
2024-04-16 16:22:08 +00:00
|
|
|
handleRowSelect: (value: Row<IHost>) => void;
|
2022-06-10 18:29:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const baseClass = "targets-input";
|
|
|
|
|
|
2024-04-16 16:22:08 +00:00
|
|
|
const DEFAULT_LABEL = "Target specific hosts";
|
|
|
|
|
|
2022-06-10 18:29:45 +00:00
|
|
|
const TargetsInput = ({
|
|
|
|
|
tabIndex,
|
|
|
|
|
searchText,
|
|
|
|
|
searchResults,
|
|
|
|
|
isTargetsLoading,
|
|
|
|
|
hasFetchError,
|
|
|
|
|
targetedHosts,
|
2024-04-16 16:22:08 +00:00
|
|
|
searchResultsTableConfig,
|
|
|
|
|
selectedHostsTableConifg,
|
|
|
|
|
disablePagination = false,
|
|
|
|
|
label = DEFAULT_LABEL,
|
|
|
|
|
placeholder = HOSTS_SEARCH_BOX_PLACEHOLDER,
|
|
|
|
|
autofocus = false,
|
2022-06-10 18:29:45 +00:00
|
|
|
handleRowSelect,
|
|
|
|
|
setSearchText,
|
|
|
|
|
}: ITargetsInputProps): JSX.Element => {
|
|
|
|
|
const dropdownHosts =
|
2022-10-14 19:26:15 +00:00
|
|
|
searchResults && pullAllBy(searchResults, targetedHosts, "display_name");
|
2022-06-10 18:29:45 +00:00
|
|
|
const isActiveSearch =
|
|
|
|
|
!isEmpty(searchText) && (!hasFetchError || isTargetsLoading);
|
|
|
|
|
const isSearchError = !isEmpty(searchText) && hasFetchError;
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<div>
|
|
|
|
|
<div className={baseClass}>
|
2024-02-29 13:49:36 +00:00
|
|
|
<InputFieldWithIcon
|
2024-04-16 16:22:08 +00:00
|
|
|
autofocus={autofocus}
|
2022-06-10 18:29:45 +00:00
|
|
|
type="search"
|
2023-09-01 14:18:29 +00:00
|
|
|
iconSvg="search"
|
2022-06-10 18:29:45 +00:00
|
|
|
value={searchText}
|
|
|
|
|
tabIndex={tabIndex}
|
|
|
|
|
iconPosition="start"
|
2024-04-16 16:22:08 +00:00
|
|
|
label={label}
|
|
|
|
|
placeholder={placeholder}
|
2022-06-10 18:29:45 +00:00
|
|
|
onChange={setSearchText}
|
|
|
|
|
/>
|
2024-07-02 16:32:35 +00:00
|
|
|
{isActiveSearch &&
|
|
|
|
|
(isTargetsLoading ? (
|
|
|
|
|
<Spinner />
|
|
|
|
|
) : (
|
|
|
|
|
<div className={`${baseClass}__hosts-search-dropdown`}>
|
|
|
|
|
<TableContainer<Row<IHost>>
|
|
|
|
|
columnConfigs={searchResultsTableConfig}
|
|
|
|
|
data={dropdownHosts}
|
|
|
|
|
isLoading={false}
|
|
|
|
|
emptyComponent={() => (
|
|
|
|
|
<div className="empty-search">
|
|
|
|
|
<div className="empty-search__inner">
|
|
|
|
|
<h4>No hosts match the current search criteria.</h4>
|
|
|
|
|
<p>
|
|
|
|
|
Expecting to see hosts? Try again in a few seconds as
|
|
|
|
|
the system catches up.
|
|
|
|
|
</p>
|
|
|
|
|
</div>
|
2022-06-10 18:29:45 +00:00
|
|
|
</div>
|
2024-07-02 16:32:35 +00:00
|
|
|
)}
|
|
|
|
|
showMarkAllPages={false}
|
|
|
|
|
isAllPagesSelected={false}
|
|
|
|
|
disableCount
|
|
|
|
|
disablePagination
|
|
|
|
|
disableMultiRowSelect
|
|
|
|
|
onClickRow={handleRowSelect}
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
))}
|
2022-06-10 18:29:45 +00:00
|
|
|
{isSearchError && (
|
|
|
|
|
<div className={`${baseClass}__hosts-search-dropdown`}>
|
|
|
|
|
<DataError />
|
|
|
|
|
</div>
|
|
|
|
|
)}
|
|
|
|
|
<div className={`${baseClass}__hosts-selected-table`}>
|
|
|
|
|
<TableContainer
|
2024-04-16 16:22:08 +00:00
|
|
|
columnConfigs={selectedHostsTableConifg}
|
2022-06-10 18:29:45 +00:00
|
|
|
data={targetedHosts}
|
|
|
|
|
isLoading={false}
|
|
|
|
|
showMarkAllPages={false}
|
|
|
|
|
isAllPagesSelected={false}
|
|
|
|
|
disableCount
|
2024-04-16 16:22:08 +00:00
|
|
|
disablePagination={disablePagination}
|
|
|
|
|
isClientSidePagination={!disablePagination}
|
2022-06-10 18:29:45 +00:00
|
|
|
emptyComponent={() => <></>}
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
export default TargetsInput;
|