mirror of
https://github.com/fleetdm/fleet
synced 2026-05-15 13:08:42 +00:00
## Addresses second major part of #15011 (item 3) – Host query report _Note for reviewers: The most important files here are:_ - HostQueryReport.tsx - HQRTable.tsx - HQRTableConfig.tsx _The rest are associated API services, interfaces, helpers, routes, styles, and miscellanious code improvements I made along the way._ ____________ ### See linked issue for enumeration of feature-related tasks <img width="1230" alt="Screenshot 2023-12-08 at 4 23 50 PM" src="https://github.com/fleetdm/fleet/assets/61553566/4ae4b41b-9209-4afa-ae50-8844d01ff8fd"> <img width="1230" alt="collecting" src="https://github.com/fleetdm/fleet/assets/61553566/061ac2bc-899f-4b29-91ba-36ebecf5ce58"> <img width="1230" alt="Screenshot 2023-12-08 at 4 24 39 PM" src="https://github.com/fleetdm/fleet/assets/61553566/f8b25e01-fe3b-47e6-b980-eba9538b1a01"> <img width="1230" alt="Screenshot 2023-12-08 at 4 25 01 PM" src="https://github.com/fleetdm/fleet/assets/61553566/46360274-8500-494c-8fb7-3a1d45347ce0"> Re-routes to host details > queries if: - query reports are globally disabled: https://github.com/fleetdm/fleet/assets/61553566/ac67da8c-57bc-4d9b-96be-daf3b198e704 - query has `Discard data` enabled: https://github.com/fleetdm/fleet/assets/61553566/b797dd24-9893-4360-bf40-b80298848864 - [x] Manual QA for all new/changed functionality --------- Co-authored-by: Jacob Shandling <jacob@fleetdm.com>
113 lines
3.5 KiB
TypeScript
113 lines
3.5 KiB
TypeScript
import React 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 Input from "components/forms/fields/InputFieldWithIcon";
|
|
import TableContainer from "components/TableContainer";
|
|
import { generateTableHeaders } from "./TargetsInputHostsTableConfig";
|
|
|
|
interface ITargetsInputProps {
|
|
tabIndex: number;
|
|
searchText: string;
|
|
searchResults: IHost[];
|
|
isTargetsLoading: boolean;
|
|
hasFetchError: boolean;
|
|
targetedHosts: IHost[];
|
|
setSearchText: (value: string) => void;
|
|
handleRowSelect: (value: Row) => void;
|
|
handleRowRemove: (value: Row) => void;
|
|
}
|
|
|
|
const baseClass = "targets-input";
|
|
|
|
const TargetsInput = ({
|
|
tabIndex,
|
|
searchText,
|
|
searchResults,
|
|
isTargetsLoading,
|
|
hasFetchError,
|
|
targetedHosts,
|
|
handleRowSelect,
|
|
handleRowRemove,
|
|
setSearchText,
|
|
}: ITargetsInputProps): JSX.Element => {
|
|
const resultsDropdownTableHeaders = generateTableHeaders();
|
|
const selectedTableHeaders = generateTableHeaders(handleRowRemove);
|
|
const dropdownHosts =
|
|
searchResults && pullAllBy(searchResults, targetedHosts, "display_name");
|
|
// const finalSelectedHostTargets =
|
|
// targetedHosts && filter(targetedHosts, "display_name");
|
|
const isActiveSearch =
|
|
!isEmpty(searchText) && (!hasFetchError || isTargetsLoading);
|
|
const isSearchError = !isEmpty(searchText) && hasFetchError;
|
|
|
|
return (
|
|
<div>
|
|
<div className={baseClass}>
|
|
<Input
|
|
autofocus
|
|
type="search"
|
|
iconSvg="search"
|
|
value={searchText}
|
|
tabIndex={tabIndex}
|
|
iconPosition="start"
|
|
label="Target specific hosts"
|
|
placeholder={HOSTS_SEARCH_BOX_PLACEHOLDER}
|
|
onChange={setSearchText}
|
|
/>
|
|
{isActiveSearch && (
|
|
<div className={`${baseClass}__hosts-search-dropdown`}>
|
|
<TableContainer
|
|
columnConfigs={resultsDropdownTableHeaders}
|
|
data={dropdownHosts}
|
|
isLoading={isTargetsLoading}
|
|
resultsTitle=""
|
|
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>
|
|
</div>
|
|
)}
|
|
showMarkAllPages={false}
|
|
isAllPagesSelected={false}
|
|
disableCount
|
|
disablePagination
|
|
disableMultiRowSelect
|
|
onSelectSingleRow={handleRowSelect}
|
|
/>
|
|
</div>
|
|
)}
|
|
{isSearchError && (
|
|
<div className={`${baseClass}__hosts-search-dropdown`}>
|
|
<DataError />
|
|
</div>
|
|
)}
|
|
<div className={`${baseClass}__hosts-selected-table`}>
|
|
<TableContainer
|
|
columnConfigs={selectedTableHeaders}
|
|
data={targetedHosts}
|
|
isLoading={false}
|
|
resultsTitle=""
|
|
showMarkAllPages={false}
|
|
isAllPagesSelected={false}
|
|
disableCount
|
|
disablePagination
|
|
emptyComponent={() => <></>}
|
|
/>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default TargetsInput;
|