mirror of
https://github.com/fleetdm/fleet
synced 2026-05-04 13:59:01 +00:00
242 lines
6.5 KiB
JavaScript
242 lines
6.5 KiB
JavaScript
import React, { Component } from "react";
|
|
import PropTypes from "prop-types";
|
|
import { noop } from "lodash";
|
|
import AceEditor from "react-ace";
|
|
import classnames from "classnames";
|
|
|
|
import { humanHostMemory } from "utilities/helpers";
|
|
import FleetIcon from "components/icons/FleetIcon";
|
|
import PlatformIcon from "components/icons/PlatformIcon";
|
|
import targetInterface from "interfaces/target";
|
|
|
|
const baseClass = "target-details";
|
|
|
|
class TargetDetails extends Component {
|
|
static propTypes = {
|
|
target: targetInterface,
|
|
className: PropTypes.string,
|
|
handleBackToResults: PropTypes.func,
|
|
};
|
|
|
|
static defaultProps = {
|
|
handleBackToResults: noop,
|
|
};
|
|
|
|
onlineHosts = (labelBaseClass, count, online) => {
|
|
const offline = count - online;
|
|
const percentCount = ((count - offline) / count) * 100;
|
|
const percentOnline = parseFloat(percentCount.toFixed(2));
|
|
|
|
if (online > 0) {
|
|
return (
|
|
<span className={`${labelBaseClass}__hosts-online`}>
|
|
{" "}
|
|
({percentOnline}% ONLINE)
|
|
</span>
|
|
);
|
|
}
|
|
|
|
return false;
|
|
};
|
|
|
|
renderHost = () => {
|
|
const { className, handleBackToResults, target } = this.props;
|
|
const {
|
|
display_text: displayText,
|
|
primary_mac: hostMac,
|
|
primary_ip: hostIpAddress,
|
|
memory,
|
|
osquery_version: osqueryVersion,
|
|
os_version: osVersion,
|
|
platform,
|
|
status,
|
|
} = target;
|
|
const hostBaseClass = "host-target";
|
|
const isOnline = status === "online";
|
|
const isOffline = status === "offline";
|
|
const statusClassName = classnames(
|
|
`${hostBaseClass}__status`,
|
|
{ [`${hostBaseClass}__status--is-online`]: isOnline },
|
|
{ [`${hostBaseClass}__status--is-offline`]: isOffline }
|
|
);
|
|
|
|
return (
|
|
<div className={`${hostBaseClass} ${className}`}>
|
|
<button
|
|
className={`button button--unstyled ${hostBaseClass}__back`}
|
|
onClick={handleBackToResults}
|
|
>
|
|
<FleetIcon name="chevronleft" />
|
|
Back
|
|
</button>
|
|
|
|
<p className={`${hostBaseClass}__display-text`}>
|
|
<FleetIcon name="single-host" className={`${hostBaseClass}__icon`} />
|
|
<span>{displayText}</span>
|
|
</p>
|
|
<p className={statusClassName}>
|
|
{isOnline && (
|
|
<FleetIcon
|
|
name="success-check"
|
|
className={`${hostBaseClass}__icon ${hostBaseClass}__icon--online`}
|
|
/>
|
|
)}
|
|
{isOffline && (
|
|
<FleetIcon
|
|
name="offline"
|
|
className={`${hostBaseClass}__icon ${hostBaseClass}__icon--offline`}
|
|
/>
|
|
)}
|
|
<span>{status}</span>
|
|
</p>
|
|
<table className={`${baseClass}__table`}>
|
|
<tbody>
|
|
<tr>
|
|
<th>Private IP address</th>
|
|
<td>{hostIpAddress}</td>
|
|
</tr>
|
|
<tr>
|
|
<th>MAC address</th>
|
|
<td>
|
|
<span className={`${hostBaseClass}__mac-address`}>
|
|
{hostMac}
|
|
</span>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<th>Platform</th>
|
|
<td>
|
|
<PlatformIcon name={platform} title={platform} />
|
|
<span className={`${hostBaseClass}__platform-text`}>
|
|
{" "}
|
|
{platform}
|
|
</span>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<th>Operating system</th>
|
|
<td>{osVersion}</td>
|
|
</tr>
|
|
<tr>
|
|
<th>Osquery version</th>
|
|
<td>{osqueryVersion}</td>
|
|
</tr>
|
|
<tr>
|
|
<th>Memory</th>
|
|
<td>{humanHostMemory(memory)}</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
renderLabel = () => {
|
|
const { onlineHosts } = this;
|
|
const { handleBackToResults, className, target } = this.props;
|
|
const {
|
|
count,
|
|
description,
|
|
display_text: displayText,
|
|
label_type: labelType,
|
|
online,
|
|
query,
|
|
} = target;
|
|
const labelBaseClass = "label-target";
|
|
|
|
return (
|
|
<div className={`${labelBaseClass} ${className}`}>
|
|
<button
|
|
className={`button button--unstyled ${labelBaseClass}__back`}
|
|
onClick={handleBackToResults}
|
|
>
|
|
<FleetIcon name="chevronleft" /> Back
|
|
</button>
|
|
|
|
<p className={`${labelBaseClass}__display-text`}>
|
|
<FleetIcon name="label" fw className={`${labelBaseClass}__icon`} />
|
|
<span>{displayText}</span>
|
|
</p>
|
|
|
|
<p className={`${labelBaseClass}__hosts`}>
|
|
<span className={`${labelBaseClass}__hosts-count`}>
|
|
<strong>{count}</strong>HOSTS
|
|
</span>
|
|
{onlineHosts(labelBaseClass, count, online)}
|
|
</p>
|
|
|
|
<p className={`${labelBaseClass}__description`}>
|
|
{description || "No Description"}
|
|
</p>
|
|
|
|
{labelType !== 1 && (
|
|
<div className={`${labelBaseClass}__editor`}>
|
|
<AceEditor
|
|
editorProps={{ $blockScrolling: Infinity }}
|
|
mode="fleet"
|
|
minLines={1}
|
|
maxLines={20}
|
|
name="label-query"
|
|
readOnly
|
|
setOptions={{ wrap: true }}
|
|
showGutter={false}
|
|
showPrintMargin={false}
|
|
theme="fleet"
|
|
value={query}
|
|
width="100%"
|
|
fontSize={14}
|
|
/>
|
|
</div>
|
|
)}
|
|
</div>
|
|
);
|
|
};
|
|
|
|
renderTeam = () => {
|
|
const { className, target } = this.props;
|
|
const { count, display_text: displayText } = target;
|
|
const labelBaseClass = "label-target";
|
|
|
|
return (
|
|
<div className={`${labelBaseClass} ${className}`}>
|
|
<p className={`${labelBaseClass}__display-text`}>
|
|
<FleetIcon
|
|
name="all-hosts"
|
|
fw
|
|
className={`${labelBaseClass}__icon`}
|
|
/>
|
|
<span>{displayText}</span>
|
|
</p>
|
|
|
|
<p className={`${labelBaseClass}__hosts`}>
|
|
<span className={`${labelBaseClass}__hosts-count`}>
|
|
<strong>{count}</strong>HOSTS
|
|
</span>
|
|
</p>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
render() {
|
|
const { target } = this.props;
|
|
|
|
if (!target) {
|
|
return false;
|
|
}
|
|
|
|
const { target_type: targetType } = target;
|
|
const { renderHost, renderLabel, renderTeam } = this;
|
|
|
|
if (targetType === "labels") {
|
|
return renderLabel();
|
|
}
|
|
|
|
if (targetType === "teams") {
|
|
return renderTeam();
|
|
}
|
|
|
|
return renderHost();
|
|
}
|
|
}
|
|
|
|
export default TargetDetails;
|