mirror of
https://github.com/fleetdm/fleet
synced 2026-05-23 17:08:53 +00:00
Update UI to allow for showing software install details from activities related to deleted hosts (#20866)
This commit is contained in:
parent
438b0ff4d6
commit
13e5e14a2f
5 changed files with 57 additions and 28 deletions
|
|
@ -90,6 +90,12 @@ export const AppInstallDetails = ({
|
|||
subordinate = status === "pending" ? " when it comes online" : "";
|
||||
}
|
||||
|
||||
const formattedHost = host_display_name ? (
|
||||
<b>{host_display_name}</b>
|
||||
) : (
|
||||
"the host"
|
||||
);
|
||||
|
||||
const showCommandResponse = isStatusNotNow || status !== "pending";
|
||||
|
||||
return (
|
||||
|
|
@ -98,8 +104,7 @@ export const AppInstallDetails = ({
|
|||
<div className={`${baseClass}__status-message`}>
|
||||
{!!iconName && <Icon name={iconName} />}
|
||||
<span>
|
||||
Fleet {predicate} <b>{software_title}</b> on{" "}
|
||||
<b>{host_display_name}</b>
|
||||
Fleet {predicate} <b>{software_title}</b> on {formattedHost}
|
||||
{subordinate}.
|
||||
</span>
|
||||
</div>
|
||||
|
|
@ -111,7 +116,7 @@ export const AppInstallDetails = ({
|
|||
</div>
|
||||
{showCommandResponse && (
|
||||
<div className={`${baseClass}__script-output`}>
|
||||
The response from <b>{host_display_name}</b>:
|
||||
The response from {formattedHost}:
|
||||
<Textarea className={`${baseClass}__output-textarea`}>
|
||||
{result.result}
|
||||
</Textarea>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import React from "react";
|
||||
import { useQuery } from "react-query";
|
||||
|
||||
import { IActivityDetails } from "interfaces/activity";
|
||||
import {
|
||||
ISoftwareInstallResult,
|
||||
ISoftwareInstallResults,
|
||||
|
|
@ -21,17 +22,28 @@ import {
|
|||
|
||||
const baseClass = "software-install-details";
|
||||
|
||||
// TODO: Expand to include more details as needed
|
||||
export type IPackageInstallDetails = Pick<
|
||||
IActivityDetails,
|
||||
"install_uuid" | "host_display_name"
|
||||
>;
|
||||
|
||||
const StatusMessage = ({
|
||||
result: { host_display_name, software_package, software_title, status },
|
||||
}: {
|
||||
result: ISoftwareInstallResult;
|
||||
}) => {
|
||||
const formattedHost = host_display_name ? (
|
||||
<b>{host_display_name}</b>
|
||||
) : (
|
||||
"the host"
|
||||
);
|
||||
return (
|
||||
<div className={`${baseClass}__status-message`}>
|
||||
<Icon name={INSTALL_DETAILS_STATUS_ICONS[status]} />
|
||||
<span>
|
||||
Fleet {getInstallDetailsStatusPredicate(status)} <b>{software_title}</b>{" "}
|
||||
({software_package}) on <b>{host_display_name}</b>
|
||||
({software_package}) on {formattedHost}
|
||||
{status === "pending" ? " when it comes online" : ""}.
|
||||
</span>
|
||||
</div>
|
||||
|
|
@ -56,18 +68,17 @@ const Output = ({
|
|||
};
|
||||
|
||||
export const SoftwareInstallDetails = ({
|
||||
installUuid,
|
||||
}: {
|
||||
installUuid: string;
|
||||
}) => {
|
||||
host_display_name = "",
|
||||
install_uuid = "",
|
||||
}: IPackageInstallDetails) => {
|
||||
const { data: result, isLoading, isError } = useQuery<
|
||||
ISoftwareInstallResults,
|
||||
Error,
|
||||
ISoftwareInstallResult
|
||||
>(
|
||||
["softwareInstallResults", installUuid],
|
||||
["softwareInstallResults", install_uuid],
|
||||
() => {
|
||||
return softwareAPI.getSoftwareInstallResult(installUuid);
|
||||
return softwareAPI.getSoftwareInstallResult(install_uuid);
|
||||
},
|
||||
{
|
||||
refetchOnWindowFocus: false,
|
||||
|
|
@ -88,7 +99,11 @@ export const SoftwareInstallDetails = ({
|
|||
return (
|
||||
<>
|
||||
<div className={`${baseClass}__software-install-details`}>
|
||||
<StatusMessage result={result} />
|
||||
<StatusMessage
|
||||
result={
|
||||
result.host_display_name ? result : { ...result, host_display_name } // prefer result.host_display_name (it may be empty if the host was deleted) otherwise default to whatever we received via props
|
||||
}
|
||||
/>
|
||||
{result.status !== "pending" && (
|
||||
<>
|
||||
{result.pre_install_query_output && (
|
||||
|
|
@ -106,10 +121,10 @@ export const SoftwareInstallDetails = ({
|
|||
};
|
||||
|
||||
export const SoftwareInstallDetailsModal = ({
|
||||
installUuid,
|
||||
details,
|
||||
onCancel,
|
||||
}: {
|
||||
installUuid: string;
|
||||
details: IPackageInstallDetails;
|
||||
onCancel: () => void;
|
||||
}) => {
|
||||
return (
|
||||
|
|
@ -121,7 +136,7 @@ export const SoftwareInstallDetailsModal = ({
|
|||
>
|
||||
<>
|
||||
<div className={`${baseClass}__modal-content`}>
|
||||
<SoftwareInstallDetails installUuid={installUuid} />
|
||||
<SoftwareInstallDetails {...details} />
|
||||
</div>
|
||||
<div className="modal-cta-wrap">
|
||||
<Button onClick={onCancel} variant="brand">
|
||||
|
|
|
|||
|
|
@ -37,7 +37,10 @@ const ActivityFeed = ({
|
|||
const [pageIndex, setPageIndex] = useState(0);
|
||||
const [showShowQueryModal, setShowShowQueryModal] = useState(false);
|
||||
const [showScriptDetailsModal, setShowScriptDetailsModal] = useState(false);
|
||||
const [installedSoftwareUuid, setInstalledSoftwareUuid] = useState("");
|
||||
const [
|
||||
packageInstallDetails,
|
||||
setPackageInstallDetails,
|
||||
] = useState<IActivityDetails | null>(null);
|
||||
const [
|
||||
appInstallDetails,
|
||||
setAppInstallDetails,
|
||||
|
|
@ -88,7 +91,6 @@ const ActivityFeed = ({
|
|||
activityType: ActivityType,
|
||||
details: IActivityDetails
|
||||
) => {
|
||||
console.log("activityType", activityType);
|
||||
switch (activityType) {
|
||||
case ActivityType.LiveQuery:
|
||||
queryShown.current = details.query_sql ?? "";
|
||||
|
|
@ -102,10 +104,10 @@ const ActivityFeed = ({
|
|||
setShowScriptDetailsModal(true);
|
||||
break;
|
||||
case ActivityType.InstalledSoftware:
|
||||
setInstalledSoftwareUuid(details.install_uuid ?? "");
|
||||
setPackageInstallDetails({ ...details });
|
||||
break;
|
||||
case ActivityType.InstalledAppStoreApp:
|
||||
setAppInstallDetails(details);
|
||||
setAppInstallDetails({ ...details });
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
|
@ -197,10 +199,10 @@ const ActivityFeed = ({
|
|||
onCancel={() => setShowScriptDetailsModal(false)}
|
||||
/>
|
||||
)}
|
||||
{installedSoftwareUuid && (
|
||||
{packageInstallDetails && (
|
||||
<SoftwareInstallDetailsModal
|
||||
installUuid={installedSoftwareUuid}
|
||||
onCancel={() => setInstalledSoftwareUuid("")}
|
||||
details={packageInstallDetails}
|
||||
onCancel={() => setPackageInstallDetails(null)}
|
||||
/>
|
||||
)}
|
||||
{appInstallDetails && (
|
||||
|
|
|
|||
|
|
@ -62,7 +62,10 @@ import {
|
|||
AppInstallDetailsModal,
|
||||
IAppInstallDetails,
|
||||
} from "components/ActivityDetails/InstallDetails/AppInstallDetails/AppInstallDetails";
|
||||
import { SoftwareInstallDetailsModal } from "components/ActivityDetails/InstallDetails/SoftwareInstallDetails";
|
||||
import {
|
||||
SoftwareInstallDetailsModal,
|
||||
IPackageInstallDetails,
|
||||
} from "components/ActivityDetails/InstallDetails/SoftwareInstallDetails/SoftwareInstallDetails";
|
||||
|
||||
import HostSummaryCard from "../cards/HostSummary";
|
||||
import AboutCard from "../cards/About";
|
||||
|
|
@ -172,7 +175,10 @@ const HostDetailsPage = ({
|
|||
const [selectedPolicy, setSelectedPolicy] = useState<IHostPolicy | null>(
|
||||
null
|
||||
);
|
||||
const [softwareInstallUuid, setSoftwareInstallUuid] = useState("");
|
||||
const [
|
||||
packageInstallDetails,
|
||||
setPackageInstallDetails,
|
||||
] = useState<IPackageInstallDetails | null>(null);
|
||||
const [
|
||||
appInstallDetails,
|
||||
setAppInstallDetails,
|
||||
|
|
@ -577,7 +583,7 @@ const HostDetailsPage = ({
|
|||
setScriptDetailsId(details?.script_execution_id || "");
|
||||
break;
|
||||
case "installed_software":
|
||||
setSoftwareInstallUuid(details?.install_uuid || "");
|
||||
setPackageInstallDetails({ ...details });
|
||||
break;
|
||||
case "installed_app_store_app":
|
||||
setAppInstallDetails({ ...details });
|
||||
|
|
@ -618,7 +624,7 @@ const HostDetailsPage = ({
|
|||
}, [refetchPastActivities, refetchUpcomingActivities]);
|
||||
|
||||
const onCancelSoftwareInstallDetailsModal = useCallback(() => {
|
||||
setSoftwareInstallUuid("");
|
||||
setPackageInstallDetails(null);
|
||||
}, []);
|
||||
|
||||
const onCancelAppInstallDetailsModal = useCallback(() => {
|
||||
|
|
@ -1026,9 +1032,9 @@ const HostDetailsPage = ({
|
|||
onCancel={onCancelScriptDetailsModal}
|
||||
/>
|
||||
)}
|
||||
{!!softwareInstallUuid && (
|
||||
{!!packageInstallDetails && (
|
||||
<SoftwareInstallDetailsModal
|
||||
installUuid={softwareInstallUuid}
|
||||
details={packageInstallDetails}
|
||||
onCancel={onCancelSoftwareInstallDetailsModal}
|
||||
/>
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -149,7 +149,8 @@ const InstallDetailsContent = ({
|
|||
} else if (hasHostSoftwarePackageLastInstall(software)) {
|
||||
return (
|
||||
<SoftwareInstallDetails
|
||||
installUuid={software.software_package.last_install.install_uuid}
|
||||
install_uuid={software.software_package.last_install.install_uuid}
|
||||
host_display_name={hostDisplayName}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue