From f21e9f67b22f3698c8f3cefc77b419ba3d64e615 Mon Sep 17 00:00:00 2001
From: RachelElysia <71795832+RachelElysia@users.noreply.github.com>
Date: Wed, 8 Oct 2025 13:30:58 -0400
Subject: [PATCH] Fleet UI: Remove install tooltip and add timestamp to
InstallDetails modal (#33991)
---
.../SoftwareInstallDetailsModal.tests.tsx | 16 +++++---
.../SoftwareInstallDetailsModal.tsx | 41 ++++++++++---------
.../SoftwareUninstallDetailsModal.tests.tsx | 8 ++--
.../SoftwareUninstallDetailsModal.tsx | 8 ++--
.../VppInstallDetailsModal.tests.tsx | 2 +-
.../VppInstallDetailsModal.tsx | 18 ++++----
.../InstallStatusCell.tests.tsx | 9 ++--
.../InstallStatusCell/InstallStatusCell.tsx | 16 +-------
8 files changed, 56 insertions(+), 62 deletions(-)
diff --git a/frontend/components/ActivityDetails/InstallDetails/SoftwareInstallDetailsModal/SoftwareInstallDetailsModal.tests.tsx b/frontend/components/ActivityDetails/InstallDetails/SoftwareInstallDetailsModal/SoftwareInstallDetailsModal.tests.tsx
index 2ed8d2f9c6..889ec19ace 100644
--- a/frontend/components/ActivityDetails/InstallDetails/SoftwareInstallDetailsModal/SoftwareInstallDetailsModal.tests.tsx
+++ b/frontend/components/ActivityDetails/InstallDetails/SoftwareInstallDetailsModal/SoftwareInstallDetailsModal.tests.tsx
@@ -19,7 +19,7 @@ import SoftwareInstallDetailsModal, {
describe("SoftwareInstallDetailsModal", () => {
describe("StatusMessage component", () => {
it("renders basic 'is installed' message when not installed by fleet (no installResult provided)", () => {
- render();
+ render();
expect(screen.getByText(/CoolApp/)).toBeInTheDocument();
expect(screen.getByText(/is installed/)).toBeInTheDocument();
});
@@ -31,7 +31,7 @@ describe("SoftwareInstallDetailsModal", () => {
installResult={createMockSoftwareInstallResult({
status: "pending_install",
})}
- isDUP={false}
+ isMyDevicePage={false}
/>
);
@@ -42,6 +42,7 @@ describe("SoftwareInstallDetailsModal", () => {
expect(screen.getByText(/\(com\.cool\.app\)/)).toBeInTheDocument();
expect(screen.getByText(/Test Host/)).toBeInTheDocument();
expect(screen.getByText(/when it comes online/)).toBeInTheDocument();
+ expect(screen.queryByText(/\d+.*ago/)).not.toBeInTheDocument();
});
it("on device user page, renders failed install with retry option with contact link", () => {
@@ -51,7 +52,7 @@ describe("SoftwareInstallDetailsModal", () => {
installResult={createMockSoftwareInstallResult({
status: "failed_install",
})}
- isDUP
+ isMyDevicePage
contactUrl="http://support"
/>
);
@@ -61,6 +62,7 @@ describe("SoftwareInstallDetailsModal", () => {
expect(screen.getByText(/CoolApp/)).toBeInTheDocument();
// Host name should not be rendered for device user page
expect(screen.queryByText(/Test Host/)).not.toBeInTheDocument();
+ expect(screen.getByText(/\d+.*ago/)).toBeInTheDocument();
expect(screen.getByText(/You can retry/)).toBeInTheDocument();
expect(
screen.getByRole("link", { name: /contact your IT admin/ })
@@ -74,7 +76,7 @@ describe("SoftwareInstallDetailsModal", () => {
installResult={createMockSoftwareInstallResult({
status: "failed_install",
})}
- isDUP
+ isMyDevicePage
/>
);
@@ -83,6 +85,7 @@ describe("SoftwareInstallDetailsModal", () => {
expect(screen.getByText(/CoolApp/)).toBeInTheDocument();
// Host name should not be rendered for device user page
expect(screen.queryByText(/Test Host/)).not.toBeInTheDocument();
+ expect(screen.getByText(/\d+.*ago/)).toBeInTheDocument();
expect(screen.getByText(/You can retry/)).toBeInTheDocument();
// Don't show link of not provided
expect(
@@ -97,7 +100,7 @@ describe("SoftwareInstallDetailsModal", () => {
installResult={createMockSoftwareInstallResult({
status: "failed_install",
})}
- isDUP={false}
+ isMyDevicePage={false}
contactUrl="http://support"
/>
);
@@ -106,6 +109,7 @@ describe("SoftwareInstallDetailsModal", () => {
expect(screen.getByText(/failed to install/)).toBeInTheDocument();
expect(screen.getByText(/Test Host/)).toBeInTheDocument();
expect(screen.queryByText(/You can retry/)).not.toBeInTheDocument();
+ expect(screen.getByText(/\d+.*ago/)).toBeInTheDocument();
});
it("on host details page/install activity, renders installed message with timestamp", () => {
@@ -115,7 +119,7 @@ describe("SoftwareInstallDetailsModal", () => {
installResult={createMockSoftwareInstallResult({
status: "installed",
})}
- isDUP={false}
+ isMyDevicePage={false}
/>
);
diff --git a/frontend/components/ActivityDetails/InstallDetails/SoftwareInstallDetailsModal/SoftwareInstallDetailsModal.tsx b/frontend/components/ActivityDetails/InstallDetails/SoftwareInstallDetailsModal/SoftwareInstallDetailsModal.tsx
index aaee988a0c..d7c490c53c 100644
--- a/frontend/components/ActivityDetails/InstallDetails/SoftwareInstallDetailsModal/SoftwareInstallDetailsModal.tsx
+++ b/frontend/components/ActivityDetails/InstallDetails/SoftwareInstallDetailsModal/SoftwareInstallDetailsModal.tsx
@@ -53,7 +53,7 @@ export const renderContactOption = (url?: string) => (
interface IInstallStatusMessage {
softwareName: string;
installResult?: ISoftwareInstallResult;
- isDUP: boolean;
+ isMyDevicePage: boolean;
contactUrl?: string;
}
@@ -62,7 +62,7 @@ interface IInstallStatusMessage {
export const StatusMessage = ({
softwareName,
installResult,
- isDUP,
+ isMyDevicePage,
contactUrl,
}: IInstallStatusMessage) => {
// the case when software is installed by the user and not by Fleet
@@ -107,22 +107,25 @@ export const StatusMessage = ({
Fleet {getInstallDetailsStatusPredicate(status)} {software_title}
>
);
- let middle = null;
- if (isDUP) {
- if (status === "failed_install") {
- middle = <>. You can retry{renderContactOption(contactUrl)}>;
- }
- } else {
- // host details page
- middle = (
- <>
- {" "}
- ({software_package}) on {formattedHost}
- {status === "pending_install" ? " when it comes online" : ""}
- {displayTimeStamp}
- >
- );
- }
+
+ const middle = isMyDevicePage ? (
+ <>
+ {" "}
+ {displayTimeStamp}
+ {status === "failed_install" && (
+ <>. You can retry{renderContactOption(contactUrl)}>
+ )}
+ >
+ ) : (
+ <>
+ {" "}
+ ({software_package}) on {formattedHost}
+ {status === "pending_install"
+ ? " when it comes online"
+ : displayTimeStamp}
+ >
+ );
+
return (
{prefix}
@@ -349,7 +352,7 @@ export const SoftwareInstallDetailsModal = ({
diff --git a/frontend/components/ActivityDetails/InstallDetails/SoftwareUninstallDetailsModal/SoftwareUninstallDetailsModal.tests.tsx b/frontend/components/ActivityDetails/InstallDetails/SoftwareUninstallDetailsModal/SoftwareUninstallDetailsModal.tests.tsx
index dcef508182..e7dea355c5 100644
--- a/frontend/components/ActivityDetails/InstallDetails/SoftwareUninstallDetailsModal/SoftwareUninstallDetailsModal.tests.tsx
+++ b/frontend/components/ActivityDetails/InstallDetails/SoftwareUninstallDetailsModal/SoftwareUninstallDetailsModal.tests.tsx
@@ -15,7 +15,7 @@ describe("SoftwareUninstallDetailsModal - StatusMessage component", () => {
status="pending_uninstall"
softwareName="CoolApp"
softwarePackageName="com.cool.app"
- isDUP={false}
+ isMyDevicePage={false}
/>
);
@@ -36,7 +36,7 @@ describe("SoftwareUninstallDetailsModal - StatusMessage component", () => {
hostDisplayName="Test Host"
status="failed_uninstall"
softwareName="CoolApp"
- isDUP
+ isMyDevicePage
contactUrl="http://support"
/>
);
@@ -54,7 +54,7 @@ describe("SoftwareUninstallDetailsModal - StatusMessage component", () => {
hostDisplayName="Test Host"
status="failed_uninstall"
softwareName="CoolApp"
- isDUP={false}
+ isMyDevicePage={false}
contactUrl="http://support"
/>
);
@@ -74,7 +74,7 @@ describe("SoftwareUninstallDetailsModal - StatusMessage component", () => {
softwareName="CoolApp"
softwarePackageName="com.cool.app"
timestamp="2025-08-10T12:00:00Z"
- isDUP={false}
+ isMyDevicePage={false}
/>
);
diff --git a/frontend/components/ActivityDetails/InstallDetails/SoftwareUninstallDetailsModal/SoftwareUninstallDetailsModal.tsx b/frontend/components/ActivityDetails/InstallDetails/SoftwareUninstallDetailsModal/SoftwareUninstallDetailsModal.tsx
index ecac88aecf..113c3e2d39 100644
--- a/frontend/components/ActivityDetails/InstallDetails/SoftwareUninstallDetailsModal/SoftwareUninstallDetailsModal.tsx
+++ b/frontend/components/ActivityDetails/InstallDetails/SoftwareUninstallDetailsModal/SoftwareUninstallDetailsModal.tsx
@@ -36,7 +36,7 @@ interface IUninstallStatusMessage {
softwareName: string;
softwarePackageName?: string;
timestamp?: string;
- isDUP: boolean;
+ isMyDevicePage: boolean;
contactUrl?: string;
}
@@ -46,7 +46,7 @@ export const StatusMessage = ({
softwareName,
softwarePackageName,
timestamp,
- isDUP,
+ isMyDevicePage,
contactUrl,
}: IUninstallStatusMessage) => {
const formattedHost = hostDisplayName ? {hostDisplayName} : "the host";
@@ -67,7 +67,7 @@ export const StatusMessage = ({
>
);
let suffix = null;
- if (isDUP) {
+ if (isMyDevicePage) {
if (status === "failed_uninstall") {
suffix = <>. You can retry{renderContactOption(contactUrl)}>;
}
@@ -232,7 +232,7 @@ const SoftwareUninstallDetailsModal = ({
softwareName={softwareName}
softwarePackageName={softwarePackageName}
timestamp={uninstallResult?.created_at}
- isDUP={!!deviceAuthToken}
+ isMyDevicePage={!!deviceAuthToken}
contactUrl={contactUrl}
/>
{uninstallStatus !== "pending_uninstall" && (
diff --git a/frontend/components/ActivityDetails/InstallDetails/VppInstallDetailsModal/VppInstallDetailsModal.tests.tsx b/frontend/components/ActivityDetails/InstallDetails/VppInstallDetailsModal/VppInstallDetailsModal.tests.tsx
index 95794aa8e1..5913eb8fcf 100644
--- a/frontend/components/ActivityDetails/InstallDetails/VppInstallDetailsModal/VppInstallDetailsModal.tests.tsx
+++ b/frontend/components/ActivityDetails/InstallDetails/VppInstallDetailsModal/VppInstallDetailsModal.tests.tsx
@@ -158,7 +158,7 @@ describe("getStatusMessage helper function", () => {
it("on the device user page, does not show host info", () => {
render(
getStatusMessage({
- isDUP: true,
+ isMyDevicePage: true,
displayStatus: "installed",
isMDMStatusNotNow: false,
isMDMStatusAcknowledged: false,
diff --git a/frontend/components/ActivityDetails/InstallDetails/VppInstallDetailsModal/VppInstallDetailsModal.tsx b/frontend/components/ActivityDetails/InstallDetails/VppInstallDetailsModal/VppInstallDetailsModal.tsx
index 07e7da13f0..8644ec313f 100644
--- a/frontend/components/ActivityDetails/InstallDetails/VppInstallDetailsModal/VppInstallDetailsModal.tsx
+++ b/frontend/components/ActivityDetails/InstallDetails/VppInstallDetailsModal/VppInstallDetailsModal.tsx
@@ -29,7 +29,7 @@ import {
} from "../constants";
interface IGetStatusMessageProps {
- isDUP?: boolean;
+ isMyDevicePage?: boolean;
/** "pending" is an edge case here where VPP install activities that were added to the feed prior to v4.57
* (when we split pending into pending_install/pending_uninstall) will list the status as "pending" rather than "pending_install" */
displayStatus: SoftwareInstallStatus | "pending";
@@ -41,7 +41,7 @@ interface IGetStatusMessageProps {
}
export const getStatusMessage = ({
- isDUP = false,
+ isMyDevicePage = false,
displayStatus,
isMDMStatusNotNow,
isMDMStatusAcknowledged,
@@ -79,7 +79,7 @@ export const getStatusMessage = ({
return (
<>
Fleet tried to install {appName}
- {!isDUP && (
+ {!isMyDevicePage && (
<>
{" "}
on {formattedHost} but couldn't because the host was locked or
@@ -96,9 +96,9 @@ export const getStatusMessage = ({
return (
<>
The MDM command (request) to install {appName}
- {!isDUP && <> on {formattedHost}>} was acknowledged but the
+ {!isMyDevicePage && <> on {formattedHost}>} was acknowledged but the
installation has not been verified. To re-check, select Refetch
- {!isDUP && " for this host"}.
+ {!isMyDevicePage && " for this host"}.
>
);
}
@@ -108,7 +108,7 @@ export const getStatusMessage = ({
return (
<>
The MDM command (request) to install {appName}
- {!isDUP && <> on {formattedHost}>} was acknowledged but the
+ {!isMyDevicePage && <> on {formattedHost}>} was acknowledged but the
installation has not been verified. Please re-attempt this installation.
>
);
@@ -119,7 +119,7 @@ export const getStatusMessage = ({
return (
<>
The MDM command (request) to install {appName}
- {!isDUP && <> on {formattedHost}>} failed
+ {!isMyDevicePage && <> on {formattedHost}>} failed
{displayTimeStamp && <> {displayTimeStamp}>}. Please re-attempt this
installation.
>
@@ -127,7 +127,7 @@ export const getStatusMessage = ({
}
const renderSuffix = () => {
- if (isDUP) {
+ if (isMyDevicePage) {
return <> {displayTimeStamp && <> {displayTimeStamp}>}>;
}
return (
@@ -299,7 +299,7 @@ export const VppInstallDetailsModal = ({
: true; // if no hostSoftware passed in, can assume this is the activity feed, meaning this can only refer to a Fleet-handled install
const statusMessage = getStatusMessage({
- isDUP: !!deviceAuthToken,
+ isMyDevicePage: !!deviceAuthToken,
displayStatus,
isMDMStatusNotNow,
isMDMStatusAcknowledged,
diff --git a/frontend/pages/hosts/details/cards/Software/InstallStatusCell/InstallStatusCell.tests.tsx b/frontend/pages/hosts/details/cards/Software/InstallStatusCell/InstallStatusCell.tests.tsx
index f7d03adee1..4eada43992 100644
--- a/frontend/pages/hosts/details/cards/Software/InstallStatusCell/InstallStatusCell.tests.tsx
+++ b/frontend/pages/hosts/details/cards/Software/InstallStatusCell/InstallStatusCell.tests.tsx
@@ -19,7 +19,7 @@ jest.mock("lodash", () => ({
const testSoftwarePackage = createMockHostSoftwarePackage();
describe("InstallStatusCell - component", () => {
- it("renders 'Installed' status with tooltip", async () => {
+ it("renders 'Installed' status without tooltip", async () => {
const { user } = renderWithSetup(
{
await user.hover(screen.getByText("Installed"));
- await waitFor(() => {
- expect(screen.getByText(/Software was installed/i)).toBeInTheDocument();
- });
+ // No tooltip on install status
+ expect(
+ screen.queryByText(/Software was installed/i)
+ ).not.toBeInTheDocument();
// There SHOULD be a button with this label
expect(
diff --git a/frontend/pages/hosts/details/cards/Software/InstallStatusCell/InstallStatusCell.tsx b/frontend/pages/hosts/details/cards/Software/InstallStatusCell/InstallStatusCell.tsx
index 66f446ae00..6eac9f7522 100644
--- a/frontend/pages/hosts/details/cards/Software/InstallStatusCell/InstallStatusCell.tsx
+++ b/frontend/pages/hosts/details/cards/Software/InstallStatusCell/InstallStatusCell.tsx
@@ -74,21 +74,7 @@ export const INSTALL_STATUS_DISPLAY_OPTIONS: Record<
installed: {
iconName: "success",
displayText: "Installed",
- tooltip: ({ isSelfService, isAppStoreApp, lastInstalledAt }) => {
- if (!lastInstalledAt) {
- return undefined;
- }
-
- return (
- <>
- Software was installed{" "}
- {!isSelfService &&
- !isAppStoreApp &&
- "(install script finished with exit code 0) "}
- {dateAgo(lastInstalledAt)}.
- >
- );
- },
+ tooltip: () => undefined, // No tooltip for installed state
},
recently_updated: {
iconName: "success",