From 4a80de23f2996bac6c73b2868193320a7298f0b0 Mon Sep 17 00:00:00 2001 From: RachelElysia <71795832+RachelElysia@users.noreply.github.com> Date: Fri, 24 Oct 2025 09:42:55 -0400 Subject: [PATCH] Fleet UI: Hide version unknown, hide advanced options help text from script packages (#34647) --- .../InstallerDetailsWidget.tests.tsx | 27 ++++++++- .../InstallerDetailsWidget.tsx | 56 +++++++++++++++++-- .../SoftwareInstallerCard.tsx | 34 +---------- .../ViewYamlModal/ViewYamlModal.tsx | 5 +- .../ViewYamlModal/helpers.tests.ts | 14 +++++ .../ViewYamlModal/helpers.tsx | 15 +++-- 6 files changed, 110 insertions(+), 41 deletions(-) diff --git a/frontend/pages/SoftwarePage/SoftwareTitleDetailsPage/SoftwareInstallerCard/InstallerDetailsWidget/InstallerDetailsWidget.tests.tsx b/frontend/pages/SoftwarePage/SoftwareTitleDetailsPage/SoftwareInstallerCard/InstallerDetailsWidget/InstallerDetailsWidget.tests.tsx index e2021da338..5ea27486a1 100644 --- a/frontend/pages/SoftwarePage/SoftwareTitleDetailsPage/SoftwareInstallerCard/InstallerDetailsWidget/InstallerDetailsWidget.tests.tsx +++ b/frontend/pages/SoftwarePage/SoftwareTitleDetailsPage/SoftwareInstallerCard/InstallerDetailsWidget/InstallerDetailsWidget.tests.tsx @@ -21,8 +21,9 @@ describe("InstallerDetailsWidget", () => { softwareName: "Test Software", installerType: "package" as const, addedTimestamp: "2024-05-06T10:00:00Z", - versionInfo: v1.2.3, + version: "v1.2.3", isFma: false, + isScriptPackage: false, }; it("renders the package icon when installerType is 'package'", () => { @@ -42,6 +43,30 @@ describe("InstallerDetailsWidget", () => { expect(screen.getByText(/2 days ago/i)).toBeInTheDocument(); }); + it("does not render Version (unknown) info for a script package", () => { + render( + + ); + expect(screen.queryByText(/Version \(unknown\)/i)).not.toBeInTheDocument(); + expect(screen.getByText(/2 days ago/i)).toBeInTheDocument(); + }); + + it("renders Version (unknown) info for a non-script package with no version info", () => { + render( + + ); + expect(screen.getByText(/Version \(unknown\)/i)).toBeInTheDocument(); + expect(screen.getByText(/2 days ago/i)).toBeInTheDocument(); + }); + it("renders only version info when addedTimestamp is not present", () => { render( diff --git a/frontend/pages/SoftwarePage/SoftwareTitleDetailsPage/SoftwareInstallerCard/InstallerDetailsWidget/InstallerDetailsWidget.tsx b/frontend/pages/SoftwarePage/SoftwareTitleDetailsPage/SoftwareInstallerCard/InstallerDetailsWidget/InstallerDetailsWidget.tsx index 139f5c204f..76ac3ed0df 100644 --- a/frontend/pages/SoftwarePage/SoftwareTitleDetailsPage/SoftwareInstallerCard/InstallerDetailsWidget/InstallerDetailsWidget.tsx +++ b/frontend/pages/SoftwarePage/SoftwareTitleDetailsPage/SoftwareInstallerCard/InstallerDetailsWidget/InstallerDetailsWidget.tsx @@ -3,10 +3,11 @@ import React, { useState } from "react"; import classnames from "classnames"; -import { stringToClipboard } from "utilities/copy_text"; +import { stringToClipboard } from "utilities/copy_text"; import { internationalTimeFormat } from "utilities/helpers"; import { addedFromNow } from "utilities/date_format"; +import { LEARN_MORE_ABOUT_BASE_LINK } from "utilities/constants"; import { useCheckTruncatedElement } from "hooks/useCheckTruncatedElement"; import Graphic from "components/Graphic"; @@ -14,6 +15,7 @@ import SoftwareIcon from "pages/SoftwarePage/components/icons/SoftwareIcon"; import TooltipWrapper from "components/TooltipWrapper"; import Button from "components/buttons/Button"; import Icon from "components/Icon"; +import CustomLink from "components/CustomLink"; const baseClass = "installer-details-widget"; @@ -52,9 +54,10 @@ interface IInstallerDetailsWidgetProps { softwareName: string; installerType: "package" | "vpp"; addedTimestamp?: string; - versionInfo?: JSX.Element; + version?: string | null; sha256?: string | null; isFma: boolean; + isScriptPackage: boolean; } const InstallerDetailsWidget = ({ @@ -63,8 +66,9 @@ const InstallerDetailsWidget = ({ installerType, addedTimestamp, sha256, - versionInfo, + version, isFma, + isScriptPackage, }: IInstallerDetailsWidgetProps) => { const classNames = classnames(baseClass, className); @@ -92,6 +96,49 @@ const InstallerDetailsWidget = ({ }; const renderDetails = () => { + const renderVersionInfo = () => { + if (isScriptPackage) { + return null; + } + + let versionInfo = {version}; + + if (installerType === "vpp") { + versionInfo = ( + Updated every hour.}> + {version} + + ); + } + + if (!version) { + versionInfo = ( + + Fleet couldn't read the version from {softwareName}. + {installerType === "package" && ( + <> + {" "} + + + )} + + } + > + Version (unknown) + + ); + } + + return <> • {versionInfo}; + }; + const renderTimeStamp = () => addedTimestamp ? ( <> @@ -143,7 +190,8 @@ const InstallerDetailsWidget = ({ return ( <> - {renderInstallerDisplayText(installerType, isFma)} • {versionInfo} + {renderInstallerDisplayText(installerType, isFma)} + {renderVersionInfo()} {renderTimeStamp()} {renderSha256()} diff --git a/frontend/pages/SoftwarePage/SoftwareTitleDetailsPage/SoftwareInstallerCard/SoftwareInstallerCard.tsx b/frontend/pages/SoftwarePage/SoftwareTitleDetailsPage/SoftwareInstallerCard/SoftwareInstallerCard.tsx index 993b451648..c8070c229c 100644 --- a/frontend/pages/SoftwarePage/SoftwareTitleDetailsPage/SoftwareInstallerCard/SoftwareInstallerCard.tsx +++ b/frontend/pages/SoftwarePage/SoftwareTitleDetailsPage/SoftwareInstallerCard/SoftwareInstallerCard.tsx @@ -266,36 +266,6 @@ const SoftwareInstallerCard = ({ } }, [renderFlash, softwareId, name, teamId]); - let versionInfo = {version}; - - if (installerType === "vpp") { - versionInfo = ( - Updated every hour.}> - {version} - - ); - } - - if (installerType === "package" && !version) { - versionInfo = ( - - Fleet couldn't read the version from {name}.{" "} - - - } - > - Version (unknown) - - ); - } - const showActions = isGlobalAdmin || isGlobalMaintainer || isTeamAdmin || isTeamMaintainer; @@ -307,10 +277,11 @@ const SoftwareInstallerCard = ({
{Array.isArray(automaticInstallPolicies) && @@ -411,6 +382,7 @@ const SoftwareInstallerCard = ({ iconUrl={iconUrl} softwarePackage={softwareInstaller as ISoftwarePackage} onExit={onToggleViewYaml} + isScriptPackage={isScriptPackage} /> )} diff --git a/frontend/pages/SoftwarePage/SoftwareTitleDetailsPage/ViewYamlModal/ViewYamlModal.tsx b/frontend/pages/SoftwarePage/SoftwareTitleDetailsPage/ViewYamlModal/ViewYamlModal.tsx index 0844ec8785..85aaf77835 100644 --- a/frontend/pages/SoftwarePage/SoftwareTitleDetailsPage/ViewYamlModal/ViewYamlModal.tsx +++ b/frontend/pages/SoftwarePage/SoftwareTitleDetailsPage/ViewYamlModal/ViewYamlModal.tsx @@ -6,7 +6,7 @@ import { NotificationContext } from "context/notification"; import { LEARN_MORE_ABOUT_BASE_LINK } from "utilities/constants"; import { getExtensionFromFileName } from "utilities/file/fileUtils"; import FileSaver from "file-saver"; -import { ISoftwarePackage } from "interfaces/software"; +import { ISoftwarePackage, SCRIPT_PACKAGE_SOURCES } from "interfaces/software"; import softwareAPI from "services/entities/software"; import Modal from "components/Modal"; @@ -29,6 +29,7 @@ interface IViewYamlModalProps { iconUrl?: string | null; softwarePackage: ISoftwarePackage; onExit: () => void; + isScriptPackage?: boolean; } interface HandleDownloadParams { @@ -47,6 +48,7 @@ const ViewYamlModal = ({ iconUrl, softwarePackage, onExit, + isScriptPackage = false, }: IViewYamlModalProps) => { const { renderFlash } = useContext(NotificationContext); const { config } = useContext(AppContext); @@ -227,6 +229,7 @@ const ViewYamlModal = ({ ? onDownloadUninstallScript : undefined, onClickIcon: iconUrl ? onDownloadIcon : undefined, + hasAdvancedOptionsAvailable: !isScriptPackage, })}

diff --git a/frontend/pages/SoftwarePage/SoftwareTitleDetailsPage/ViewYamlModal/helpers.tests.ts b/frontend/pages/SoftwarePage/SoftwareTitleDetailsPage/ViewYamlModal/helpers.tests.ts index 2930be55b9..4b7dd81564 100644 --- a/frontend/pages/SoftwarePage/SoftwareTitleDetailsPage/ViewYamlModal/helpers.tests.ts +++ b/frontend/pages/SoftwarePage/SoftwareTitleDetailsPage/ViewYamlModal/helpers.tests.ts @@ -285,4 +285,18 @@ describe("renderYamlHelperText", () => { ) ).toBeInTheDocument(); }); + + it("does not render advanced options help text when hasAdvancedOptionsAvailable is false", () => { + render( + renderDownloadFilesText({ + installScript: "echo install", + onClickInstallScript: noop, + hasAdvancedOptionsAvailable: false, + }) + ); + + // Should not show the "Advanced options" instructional text + expect(screen.queryByText(/If you edited/i)).not.toBeInTheDocument(); + expect(screen.queryByText(/Advanced options/i)).not.toBeInTheDocument(); + }); }); diff --git a/frontend/pages/SoftwarePage/SoftwareTitleDetailsPage/ViewYamlModal/helpers.tsx b/frontend/pages/SoftwarePage/SoftwareTitleDetailsPage/ViewYamlModal/helpers.tsx index 534bcaf022..74b2c0fbde 100644 --- a/frontend/pages/SoftwarePage/SoftwareTitleDetailsPage/ViewYamlModal/helpers.tsx +++ b/frontend/pages/SoftwarePage/SoftwareTitleDetailsPage/ViewYamlModal/helpers.tsx @@ -14,6 +14,7 @@ interface RenderYamlHelperText { onClickPostInstallScript?: (evt: MouseEvent) => void; onClickUninstallScript?: (evt: MouseEvent) => void; onClickIcon?: (evt: MouseEvent) => void; + hasAdvancedOptionsAvailable?: boolean; } // Helper to join items with commas and Oxford comma before "and" @@ -48,6 +49,7 @@ export const renderDownloadFilesText = ({ onClickPostInstallScript, onClickUninstallScript, onClickIcon, + hasAdvancedOptionsAvailable = true, }: RenderYamlHelperText): JSX.Element => { const items: { key: string; element: JSX.Element }[] = []; @@ -120,10 +122,15 @@ export const renderDownloadFilesText = ({ <> Next, download your {joinWithCommasAnd(items)} and add{" "} {items.length === 1 ? "it" : "them"} to your repository using the{" "} - {items.length === 1 ? "path" : "paths"} above. If you edited{" "} - Advanced options, download and replace the{" "} - {items.length === 1 ? "file" : "files"} in your repository with the - updated {items.length === 1 ? "one" : "ones"}. + {items.length === 1 ? "path" : "paths"} above. + {hasAdvancedOptionsAvailable && ( + <> + {" "} + If you edited Advanced options, download and replace the{" "} + {items.length === 1 ? "file" : "files"} in your repository with the + updated {items.length === 1 ? "one" : "ones"}. + + )} ); };