Fleet UI: Select targets distributed interval tooltips (#9975)

This commit is contained in:
RachelElysia
2023-02-22 16:27:02 -05:00
committed by GitHub
parent f4df9b58a4
commit 1dcf9781ab
7 changed files with 136 additions and 34 deletions
@@ -0,0 +1 @@
- UI includes live query distributed interval warnings on select targets picker and live query result page
@@ -4,11 +4,22 @@ import React from "react";
import { Row } from "react-table";
import { IDataColumn } from "interfaces/datatable_config";
import { IHost } from "interfaces/host";
import TextCell from "components/TableContainer/DataTable/TextCell";
import LiveQueryIssueCell from "components/TableContainer/DataTable/LiveQueryIssueCell/LiveQueryIssueCell";
import StatusIndicator from "components/StatusIndicator";
import RemoveIcon from "../../../../assets/images/icon-action-remove-20x20@2x.png";
interface ICellProps {
cell: {
value: string;
};
row: {
original: IHost;
};
}
// NOTE: cellProps come from react-table
// more info here https://react-table.tanstack.com/docs/api/useTable#cell-properties
export const generateTableHeaders = (
@@ -33,9 +44,17 @@ export const generateTableHeaders = (
{
title: "Host",
Header: "Host",
disableSortBy: true,
accessor: "display_name",
Cell: (cellProps) => <TextCell value={cellProps.cell.value} />,
Cell: (cellProps: ICellProps) => {
return (
<LiveQueryIssueCell
displayName={cellProps.cell.value}
distributedInterval={cellProps.row.original.distributed_interval}
status={cellProps.row.original.status}
rowId={cellProps.row.original.id}
/>
);
},
},
// TODO: Consider removing status column from selected hosts table because
// status info is not refreshed once a target has been selected
@@ -0,0 +1,63 @@
import React from "react";
import ReactTooltip from "react-tooltip";
import Icon from "components/Icon";
interface ILiveQueryIssueCellProps<T> {
displayName: string;
distributedInterval: number;
status: string;
rowId: number;
}
const LiveQueryIssueCell = ({
displayName,
distributedInterval,
status,
rowId,
}: ILiveQueryIssueCellProps<any>): JSX.Element => {
if (distributedInterval < 60 && status === "online") {
return <>{displayName}</>;
}
return (
<>
{displayName}{" "}
<span
className={`host-issue tooltip tooltip__tooltip-icon`}
data-tip
data-for={`host-issue__${rowId.toString()}`}
data-tip-disable={false}
>
<Icon
name="issue"
size="small"
color={status === "offline" ? "status-error" : "status-warning"}
/>
</span>
<ReactTooltip
place="top"
effect="solid"
backgroundColor="#3e4771"
id={`host-issue__${rowId.toString()}`}
data-html
>
<span className={`tooltip__tooltip-text`}>
{status === "offline" ? (
<>
Offline hosts will not <br />
respond to a live query.
</>
) : (
<>
This host might take up to
<br /> {distributedInterval} seconds to respond.
</>
)}
</span>
</ReactTooltip>
</>
);
};
export default LiveQueryIssueCell;
@@ -0,0 +1 @@
export { default } from "./LiveQueryIssueCell";
+8 -3
View File
@@ -1,16 +1,21 @@
import React from "react";
import { COLORS, Colors } from "styles/var/colors";
import { ICON_SIZES, IconSizes } from "styles/var/icon_sizes";
interface IErrorProps {
color?: Colors;
size?: IconSizes;
}
const Issue = ({ color = "ui-fleet-black-50" }: IErrorProps) => {
const Issue = ({
color = "ui-fleet-black-50",
size = "medium",
}: IErrorProps) => {
return (
<svg
width="16"
height="16"
width={ICON_SIZES[size]}
height={ICON_SIZES[size]}
fill="none"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 16 16"
@@ -87,31 +87,44 @@ const QuertResultsHeading = ({
return (
<div className={`${baseClass}`}>
<h1>{pageTitle}</h1>
<div className={`${baseClass}__targeted-wrapper`}>
<span className={`${baseClass}__targeted-count`}>
{targetsTotalCount}
</span>
<span>&nbsp;{pluralizeHost(targetsTotalCount)} targeted</span>
</div>
<div className={`${baseClass}__percent-responded`}>
{!isQueryFinished && <span>Fleet is talking to your hosts,&nbsp;</span>}
<span>
({`${percentResponded}% `}
<TooltipWrapper
tipContent={`
<div className={`${baseClass}__query-information`}>
<div className={`${baseClass}__targeted-wrapper`}>
<span className={`${baseClass}__targeted-count`}>
{targetsTotalCount}
</span>
<span>&nbsp;{pluralizeHost(targetsTotalCount)} targeted</span>
</div>
<div className={`${baseClass}__percent-responded`}>
{!isQueryFinished && (
<span>Fleet is talking to your hosts,&nbsp;</span>
)}
<span>
({`${percentResponded}% `}
<TooltipWrapper
tipContent={`
Hosts that respond may<br /> return results, errors, or <br />no results`}
>
responded
</TooltipWrapper>
)
</span>
>
responded
</TooltipWrapper>
)
</span>
{!isQueryFinished && (
<Spinner
size="x-small"
centered={false}
includeContainer={false}
className={`${baseClass}__responding-spinner`}
/>
)}
</div>
{!isQueryFinished && (
<Spinner
size="x-small"
centered={false}
includeContainer={false}
className={`${baseClass}__responding-spinner`}
/>
<div className={`${baseClass}__tooltip`}>
<TooltipWrapper
tipContent={`The hosts distributed interval can <br/>impact live query response times.`}
>
Taking longer than 15 seconds?
</TooltipWrapper>
</div>
)}
</div>
{isQueryFinished ? (
@@ -1,14 +1,14 @@
.query-results-heading {
&__targeted-wrapper,
&__percent-responded {
&__query-information {
margin-top: 20px;
gap: $pad-small;
display: flex;
flex-direction: column;
font-size: $x-small;
}
&__targeted-wrapper {
margin-top: 20px;
margin-bottom: $pad-small;
&__percent-responded {
display: flex;
}
&__targeted-count {