diff --git a/frontend/hooks/useSoftwareInstallerMeta.ts b/frontend/hooks/useSoftwareInstallerMeta.ts index 60eb5eaa42..cd818409ac 100644 --- a/frontend/hooks/useSoftwareInstallerMeta.ts +++ b/frontend/hooks/useSoftwareInstallerMeta.ts @@ -13,11 +13,15 @@ import { getInstallerCardInfo, InstallerCardInfo, } from "pages/SoftwarePage/SoftwareTitleDetailsPage/helpers"; +import { isAndroidWebApp } from "pages/SoftwarePage/helpers"; import { compareVersions } from "utilities/helpers"; export interface SoftwareInstallerMeta { installerType: InstallerType; + /** Includes both Google Play Store apps and Google Play Store web apps */ isAndroidPlayStoreApp: boolean; + /** Only includes Google Play Store web apps */ + isAndroidPlayStoreWebApp: boolean; isFleetMaintainedApp: boolean; isLatestFmaVersion: boolean; isCustomPackage: boolean; @@ -64,6 +68,11 @@ export const useSoftwareInstaller = ( const isAndroidPlayStoreApp = "platform" in softwareInstaller && isAndroid(softwareInstaller.platform); + const isAndroidPlayStoreWebApp = + isAndroidPlayStoreApp && "app_store_id" in softwareInstaller + ? isAndroidWebApp(softwareInstaller.app_store_id) + : false; + const isFleetMaintainedApp = "fleet_maintained_app_id" in softwareInstaller && !!softwareInstaller.fleet_maintained_app_id; @@ -129,6 +138,7 @@ export const useSoftwareInstaller = ( meta: { installerType, isAndroidPlayStoreApp, + isAndroidPlayStoreWebApp, isFleetMaintainedApp, isLatestFmaVersion, fmaVersions, diff --git a/frontend/pages/SoftwarePage/SoftwareTitleDetailsPage/SoftwareInstallerCard/InstallerDetailsWidget/InstallerDetailsWidget.tests.tsx b/frontend/pages/SoftwarePage/SoftwareTitleDetailsPage/SoftwareInstallerCard/InstallerDetailsWidget/InstallerDetailsWidget.tests.tsx index 191987f58d..51fd69edd8 100644 --- a/frontend/pages/SoftwarePage/SoftwareTitleDetailsPage/SoftwareInstallerCard/InstallerDetailsWidget/InstallerDetailsWidget.tests.tsx +++ b/frontend/pages/SoftwarePage/SoftwareTitleDetailsPage/SoftwareInstallerCard/InstallerDetailsWidget/InstallerDetailsWidget.tests.tsx @@ -60,9 +60,8 @@ describe("InstallerDetailsWidget", () => { it("renders Version (unknown) info for a non-script package with no version info", () => { render( ); expect(screen.getByText(/Version \(unknown\)/i)).toBeInTheDocument(); @@ -119,6 +118,20 @@ describe("InstallerDetailsWidget", () => { expect(screen.getByText(/latest/i)).toBeInTheDocument(); }); + it("renders Web app label and does not render Version (unknown) info for a Google playstore webapp", () => { + render( + + ); + expect(screen.getByText(/Web app/i)).toBeInTheDocument(); + expect(screen.queryByText(/Version \(unknown\)/i)).not.toBeInTheDocument(); + expect(screen.getByText(/2 days ago/i)).toBeInTheDocument(); + }); + it("InstallerName disables tooltip if not truncated", () => { // useCheckTruncatedElement is mocked to return false render(); diff --git a/frontend/pages/SoftwarePage/SoftwareTitleDetailsPage/SoftwareInstallerCard/InstallerDetailsWidget/InstallerDetailsWidget.tsx b/frontend/pages/SoftwarePage/SoftwareTitleDetailsPage/SoftwareInstallerCard/InstallerDetailsWidget/InstallerDetailsWidget.tsx index a42be8a6f2..f0410f4f88 100644 --- a/frontend/pages/SoftwarePage/SoftwareTitleDetailsPage/SoftwareInstallerCard/InstallerDetailsWidget/InstallerDetailsWidget.tsx +++ b/frontend/pages/SoftwarePage/SoftwareTitleDetailsPage/SoftwareInstallerCard/InstallerDetailsWidget/InstallerDetailsWidget.tsx @@ -11,6 +11,8 @@ import { LEARN_MORE_ABOUT_BASE_LINK } from "utilities/constants"; import { useCheckTruncatedElement } from "hooks/useCheckTruncatedElement"; import { InstallerType } from "interfaces/software"; +import { isAndroidWebApp } from "pages/SoftwarePage/helpers"; + import Graphic from "components/Graphic"; import SoftwareIcon from "pages/SoftwarePage/components/icons/SoftwareIcon"; import TooltipWrapper from "components/TooltipWrapper"; @@ -53,6 +55,10 @@ const renderInstallerDisplayText = ( return isFma ? "Fleet-maintained" : "Custom package"; } if (androidPlayStoreId) { + if (isAndroidWebApp(androidPlayStoreId)) { + return "Web app"; + } + return "Google Play Store"; } return "App Store (VPP)"; @@ -118,7 +124,8 @@ const InstallerDetailsWidget = ({ } const renderVersionInfo = () => { - if (isScriptPackage) { + // Hide version info from script package and Android Play Store web apps + if (isScriptPackage || isAndroidWebApp(androidPlayStoreId)) { return null; } diff --git a/frontend/pages/SoftwarePage/SoftwareTitleDetailsPage/SoftwareSummaryCard/SoftwareSummaryCard.tests.tsx b/frontend/pages/SoftwarePage/SoftwareTitleDetailsPage/SoftwareSummaryCard/SoftwareSummaryCard.tests.tsx index 847c4db010..b323d37cb6 100644 --- a/frontend/pages/SoftwarePage/SoftwareTitleDetailsPage/SoftwareSummaryCard/SoftwareSummaryCard.tests.tsx +++ b/frontend/pages/SoftwarePage/SoftwareTitleDetailsPage/SoftwareSummaryCard/SoftwareSummaryCard.tests.tsx @@ -152,5 +152,31 @@ describe("Software Summary Card", () => { expect(options).not.toContain("Edit software"); expect(options).not.toContain("Schedule auto updates"); }); + + it("displays Edit appearance (but not Edit configuration nor Edit software) for Android web apps", async () => { + const { user } = render( + + ); + + const options = await getDropdownOptions(user); + + expect(options).toContain("Edit appearance"); + expect(options).not.toContain("Edit software"); + expect(options).not.toContain("Edit configuration"); + expect(options).not.toContain("Schedule auto updates"); + }); }); }); diff --git a/frontend/pages/SoftwarePage/SoftwareTitleDetailsPage/SoftwareSummaryCard/SoftwareSummaryCard.tsx b/frontend/pages/SoftwarePage/SoftwareTitleDetailsPage/SoftwareSummaryCard/SoftwareSummaryCard.tsx index 45126d0dac..4ea7ef1860 100644 --- a/frontend/pages/SoftwarePage/SoftwareTitleDetailsPage/SoftwareSummaryCard/SoftwareSummaryCard.tsx +++ b/frontend/pages/SoftwarePage/SoftwareTitleDetailsPage/SoftwareSummaryCard/SoftwareSummaryCard.tsx @@ -112,12 +112,15 @@ const SoftwareSummaryCard = ({ isIosOrIpadosApp, isFleetMaintainedApp, isAndroidPlayStoreApp, + isAndroidPlayStoreWebApp, canManageSoftware, } = meta; const canEditAppearance = canManageSoftware; - const canEditSoftware = canManageSoftware; - const canEditConfiguration = canManageSoftware && isAndroidPlayStoreApp; + const canEditSoftware = canManageSoftware && !isAndroidPlayStoreApp; + /** Permission to manage software + Google Playstore app that's not a web app */ + const canEditConfiguration = + canManageSoftware && isAndroidPlayStoreApp && !isAndroidPlayStoreWebApp; /** Installer modals require a specific team; hidden from "All Teams" */ const hasValidTeamId = typeof teamId === "number" && teamId >= 0; const softwareInstallerOnTeam = hasValidTeamId && softwareInstaller; diff --git a/frontend/pages/SoftwarePage/components/cards/SoftwareDetailsSummary/SoftwareDetailsSummary.tsx b/frontend/pages/SoftwarePage/components/cards/SoftwareDetailsSummary/SoftwareDetailsSummary.tsx index 2227cc43c3..da26e03f4c 100644 --- a/frontend/pages/SoftwarePage/components/cards/SoftwareDetailsSummary/SoftwareDetailsSummary.tsx +++ b/frontend/pages/SoftwarePage/components/cards/SoftwareDetailsSummary/SoftwareDetailsSummary.tsx @@ -12,6 +12,8 @@ import { TooltipContent } from "interfaces/dropdownOption"; import { getPathWithQueryParams, QueryParams } from "utilities/url"; import { getGitOpsModeTipContent } from "utilities/helpers"; +import { isSafeImagePreviewUrl } from "pages/SoftwarePage/helpers"; + import paths from "router/paths"; import { NO_VERSION_OR_HOST_DATA_SOURCES, @@ -26,7 +28,6 @@ import DropdownWrapper from "components/forms/fields/DropdownWrapper"; import TooltipWrapper from "components/TooltipWrapper"; import TooltipTruncatedText from "components/TooltipTruncatedText"; import CustomLink from "components/CustomLink"; -import { isSafeImagePreviewUrl } from "pages/SoftwarePage/helpers"; import TooltipWrapperArchLinuxRolling from "components/TooltipWrapperArchLinuxRolling"; import SoftwareIcon from "../../icons/SoftwareIcon"; @@ -41,7 +42,8 @@ const buildActionOptions = ( gitOpsModeEnabled: boolean | undefined, repoURL: string | undefined, source: string | undefined, - androidSoftwareAvailableForInstall: boolean, + canEditSoftware: boolean, + canEditConfiguration: boolean, canConfigureAutoUpdate: boolean ): CustomOptionType[] => { let disableEditAppearanceTooltipContent: TooltipContent | undefined; @@ -69,8 +71,8 @@ const buildActionOptions = ( }, ]; - // Hides edit software option only for Android installers, as they are currently non-editable - if (!androidSoftwareAvailableForInstall) { + // Hides edit software option only for Android installers (Playstore and Web apps), as they are currently non-editable + if (canEditSoftware) { options.push({ label: "Edit software", value: ACTION_EDIT_SOFTWARE, @@ -79,8 +81,8 @@ const buildActionOptions = ( }); } - // Show edit configuration option only for Android installers - if (androidSoftwareAvailableForInstall) { + // Show edit configuration option only for Android installers that are not web apps + if (canEditConfiguration) { options.push({ label: "Edit configuration", value: ACTION_EDIT_CONFIGURATION, @@ -215,6 +217,7 @@ const SoftwareDetailsSummary = ({ gitOpsModeEnabled, repoURL, source, + !!onClickEditSoftware, !!onClickEditConfiguration, !!onClickEditAutoUpdateConfig ); diff --git a/frontend/pages/SoftwarePage/helpers.tsx b/frontend/pages/SoftwarePage/helpers.tsx index f166315e81..8996da21f6 100644 --- a/frontend/pages/SoftwarePage/helpers.tsx +++ b/frontend/pages/SoftwarePage/helpers.tsx @@ -289,3 +289,7 @@ export const getDisplayedSoftwareName = ( // This should not happen return "Software"; }; + +export const isAndroidWebApp = (androidPlayStoreId?: string) => + !!androidPlayStoreId && + androidPlayStoreId.startsWith("com.google.enterprise.webapp");