Host Details Page: Resolve policy issues (#2571)

This commit is contained in:
RachelElysia 2021-10-19 19:18:02 -04:00 committed by GitHub
parent 1dfe37accc
commit 34510ed144
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 112 additions and 22 deletions

View file

@ -0,0 +1 @@
* Host details page renders total issues if present and policies modal with query description and resolution

View file

@ -1,15 +1,19 @@
import PropTypes from "prop-types";
export default PropTypes.shape({
id: PropTypes.number,
id: PropTypes.number.isRequired,
query_id: PropTypes.number,
query_name: PropTypes.string,
query_name: PropTypes.string.isRequired,
query_description: PropTypes.string,
response: PropTypes.string,
resolution: PropTypes.string,
});
export interface IHostPolicy {
id: number;
query_id: number;
query_name: string;
query_description?: string;
response: string;
resolution?: string;
}

View file

@ -65,6 +65,7 @@ import BackChevron from "../../../../assets/images/icon-chevron-down-9x6@2x.png"
import DeleteIcon from "../../../../assets/images/icon-action-delete-14x14@2x.png";
import TransferIcon from "../../../../assets/images/icon-action-transfer-16x16@2x.png";
import QueryIcon from "../../../../assets/images/icon-action-query-16x16@2x.png";
import IssueIcon from "../../../../assets/images/icon-issue-fleet-black-50-16x16@2x.png";
const baseClass = "host-details";
@ -107,11 +108,25 @@ const HostDetailsPage = ({
false
);
const [showQueryHostModal, setShowQueryHostModal] = useState<boolean>(false);
const [showPolicyDetailsModal, setPolicyDetailsModal] = useState(false);
const [showPolicyDetailsModal, setPolicyDetailsModal] = useState<boolean>(
false
);
const [selectedPolicy, setSelectedPolicy] = useState<IHostPolicy | null>(
null
);
const togglePolicyDetailsModal = useCallback(() => {
const togglePolicyDetailsModal = useCallback(
(policy: IHostPolicy) => {
setPolicyDetailsModal(!showPolicyDetailsModal);
setSelectedPolicy(policy);
},
[showPolicyDetailsModal, setPolicyDetailsModal, setSelectedPolicy]
);
const onCancelPolicyDetailsModal = useCallback(() => {
setPolicyDetailsModal(!showPolicyDetailsModal);
}, [showPolicyDetailsModal, setPolicyDetailsModal]);
setSelectedPolicy(null);
}, [showPolicyDetailsModal, setPolicyDetailsModal, setSelectedPolicy]);
const [refetchStartTime, setRefetchStartTime] = useState<number | null>(null);
const [
@ -276,6 +291,7 @@ const HostDetailsPage = ({
const titleData = normalizeEmptyValues(
pick(host, [
"status",
"issues",
"memory",
"cpu_type",
"os_version",
@ -741,6 +757,37 @@ const HostDetailsPage = ({
);
};
const renderIssues = () => (
<div className="info-flex__item info-flex__item--title">
<span className="info-flex__header">Issues</span>
<span className="info-flex__data">
<span
className="host-issue tooltip__tooltip-icon"
data-tip
data-for="host-issue-count"
data-tip-disable={false}
>
<img alt="host issue" src={IssueIcon} />
</span>
<ReactTooltip
place="bottom"
type="dark"
effect="solid"
backgroundColor="#3e4771"
id="host-issue-count"
data-html
>
<span className={`tooltip__tooltip-text`}>
Failing policies ({host?.issues.failing_policies_count})
</span>
</ReactTooltip>
<span className={`total-issues-count`}>
{host?.issues.total_issues_count}
</span>
</span>
</div>
);
const renderHostTeam = () => (
<div className="info-flex__item info-flex__item--title">
<span className="info-flex__header">Team</span>
@ -879,6 +926,7 @@ const HostDetailsPage = ({
{titleData.status}
</span>
</div>
{titleData.issues.total_issues_count > 0 && renderIssues()}
{isPremiumTier && renderHostTeam()}
{renderDeviceUser()}
<div className="info-flex__item info-flex__item--title">
@ -987,7 +1035,10 @@ const HostDetailsPage = ({
/>
)}
{!!host && showPolicyDetailsModal && (
<PolicyDetailsModal onCancel={togglePolicyDetailsModal} />
<PolicyDetailsModal
onCancel={onCancelPolicyDetailsModal}
policy={selectedPolicy}
/>
)}
</div>
);

View file

@ -52,7 +52,7 @@ const getPolicyStatus = (policy: IHostPolicy): string => {
// NOTE: cellProps come from react-table
// more info here https://react-table.tanstack.com/docs/api/useTable#cell-properties
const generatePolicyTableHeaders = (
togglePolicyDetails: () => void
togglePolicyDetails: (policy: IHostPolicy) => void
): IDataColumn[] => {
return [
{
@ -64,7 +64,12 @@ const generatePolicyTableHeaders = (
const { query_name } = cellProps.row.original;
return (
<>
<Button onClick={togglePolicyDetails} variant={"text-icon"}>
<Button
onClick={() => {
togglePolicyDetails(cellProps.row.original);
}}
variant={"text-icon"}
>
<>
{query_name}
<img src={ArrowIcon} alt="View policy details" />

View file

@ -2,32 +2,41 @@ import React from "react";
import Button from "components/buttons/Button";
import Modal from "components/modals/Modal";
import { IHostPolicy } from "interfaces/host_policy";
interface IPolicyDetailsProps {
onCancel: () => void;
policy: IHostPolicy | null;
}
const baseClass = "policy-details-modal";
const PolicyDetailsModal = (props: IPolicyDetailsProps): JSX.Element => {
const { onCancel } = props;
const PolicyDetailsModal = ({
onCancel,
policy,
}: IPolicyDetailsProps): JSX.Element => {
return (
<Modal title={"Policy Name"} onExit={onCancel} className={baseClass}>
<Modal
title={`${policy?.query_name || "Query name"}`}
onExit={onCancel}
className={baseClass}
>
<div className={`${baseClass}__modal-body`}>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas
feugiat venenatis quam, nec eleifend nisi aliquet non. Sed feugiat
rutrum turpis, ac convallis odio egestas sit amet. Fusce vel sem
massa. Quisque porttitor metus id vulputate vehicula. Donec ut nunc
tempor, pretium lorem et, tempus est.
</p>
<p>{policy?.query_description}</p>
{policy?.resolution && (
<div className={`${baseClass}__resolution`}>
<span className={`${baseClass}__resolve-header`}> Resolve:</span>
<br />
{policy?.resolution}
</div>
)}
<div className={`${baseClass}__btn-wrap`}>
<Button
className={`${baseClass}__btn`}
onClick={onCancel}
variant="brand"
>
Cancel
Done
</Button>
</div>
</div>

View file

@ -1,8 +1,18 @@
.policy-details-modal {
&__resolution {
p {
margin-top: $pad-xsmall;
}
}
&__resolve-header {
font-weight: $bold;
}
&__btn-wrap {
display: flex;
flex-direction: row-reverse;
margin-top: $pad-xxlarge;
margin-top: $pad-large;
}
&__btn {

View file

@ -42,10 +42,20 @@
&--title {
margin-right: $pad-xxlarge;
.info__data {
.info-flex__data {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
img {
width: 16px;
height: 16px;
vertical-align: sub;
}
.total-issues-count {
margin-left: $pad-small;
}
}
}
}