diff --git a/frontend/pages/SoftwarePage/components/AppStoreVpp/AppStoreVpp.tsx b/frontend/pages/SoftwarePage/components/AppStoreVpp/AppStoreVpp.tsx index 358c09ffad..1a1fc02ad0 100644 --- a/frontend/pages/SoftwarePage/components/AppStoreVpp/AppStoreVpp.tsx +++ b/frontend/pages/SoftwarePage/components/AppStoreVpp/AppStoreVpp.tsx @@ -20,6 +20,7 @@ import { NotificationContext } from "context/notification"; import { getErrorReason } from "interfaces/errors"; import { buildQueryStringFromParams } from "utilities/url"; import SoftwareIcon from "../icons/SoftwareIcon"; +import { getErrorMessage } from "./helpers"; const baseClass = "app-store-vpp"; @@ -171,13 +172,7 @@ const AppStoreVpp = ({ teamId, router, onExit }: IAppStoreVppProps) => { }); router.push(`${PATHS.SOFTWARE}?${queryParams}`); } catch (e) { - const reason = getErrorReason(e); - // TODO: update with pre-defined error messages we want to pass through from the API - if (reason.toLowerCase().includes("already")) { - renderFlash("error", reason); - } else { - renderFlash("error", "Couldn’t add software. Please try again."); - } + renderFlash("error", getErrorMessage(e)); } onExit(); }; diff --git a/frontend/pages/SoftwarePage/components/AppStoreVpp/helpers.tsx b/frontend/pages/SoftwarePage/components/AppStoreVpp/helpers.tsx new file mode 100644 index 0000000000..b32495cbb8 --- /dev/null +++ b/frontend/pages/SoftwarePage/components/AppStoreVpp/helpers.tsx @@ -0,0 +1,32 @@ +import React from "react"; +import { getErrorReason } from "interfaces/errors"; + +const ADD_SOFTWARE_ERROR_PREFIX = "Couldn’t add software."; +const DEFAULT_ERROR_MESSAGE = `${ADD_SOFTWARE_ERROR_PREFIX} Please try again.`; + +const generateAlreadyAvailableMessage = (msg: string) => { + const regex = new RegExp( + `${ADD_SOFTWARE_ERROR_PREFIX} (.+) already.+on the (.+) team.` + ); + + const match = msg.match(regex); + if (!match) return DEFAULT_ERROR_MESSAGE; + + return ( + <> + {ADD_SOFTWARE_ERROR_PREFIX} {match[1]} already has software + available for install on the {match[2]} team.{" "} + + ); +}; + +// eslint-disable-next-line import/prefer-default-export +export const getErrorMessage = (e: unknown) => { + const reason = getErrorReason(e); + + // software is already available for install + if (reason.toLowerCase().includes("already")) { + return generateAlreadyAvailableMessage(reason); + } + return DEFAULT_ERROR_MESSAGE; +}; diff --git a/frontend/pages/hosts/details/cards/Software/HostSoftware.tsx b/frontend/pages/hosts/details/cards/Software/HostSoftware.tsx index 6cf80111ac..f4a369cdb4 100644 --- a/frontend/pages/hosts/details/cards/Software/HostSoftware.tsx +++ b/frontend/pages/hosts/details/cards/Software/HostSoftware.tsx @@ -27,6 +27,7 @@ import CustomLink from "components/CustomLink"; import { generateSoftwareTableHeaders as generateHostSoftwareTableConfig } from "./HostSoftwareTableConfig"; import { generateSoftwareTableHeaders as generateDeviceSoftwareTableConfig } from "./DeviceSoftwareTableConfig"; import HostSoftwareTable from "./HostSoftwareTable"; +import { getErrorMessage } from "./helpers"; const baseClass = "software-card"; @@ -187,17 +188,7 @@ const HostSoftware = ({ "Software is installing or will install when the host comes online." ); } catch (e) { - const reason = upperFirst(trimEnd(getErrorReason(e), ".")); - if (reason.includes("fleetd installed")) { - renderFlash("error", `Couldn't install. ${reason}.`); - } else if (reason.includes("can be installed only on")) { - renderFlash( - "error", - `Couldn't install. ${reason.replace("darwin", "macOS")}.` - ); - } else { - renderFlash("error", "Couldn't install. Please try again."); - } + renderFlash("error", getErrorMessage(e)); } setInstallingSoftwareId(null); refetchSoftware(); diff --git a/frontend/pages/hosts/details/cards/Software/HostSoftwareTableConfig.tsx b/frontend/pages/hosts/details/cards/Software/HostSoftwareTableConfig.tsx index 0d54533b37..5825f48146 100644 --- a/frontend/pages/hosts/details/cards/Software/HostSoftwareTableConfig.tsx +++ b/frontend/pages/hosts/details/cards/Software/HostSoftwareTableConfig.tsx @@ -123,7 +123,7 @@ export const generateSoftwareTableHeaders = ({ accessor: "name", disableSortBy: false, Cell: (cellProps: ITableStringCellProps) => { - const { id, name, source } = cellProps.row.original; + const { id, name, source, app_store_app } = cellProps.row.original; const softwareTitleDetailsPath = PATHS.SOFTWARE_TITLE_DETAILS( id.toString().concat(`?team_id=${teamId}`) @@ -133,6 +133,7 @@ export const generateSoftwareTableHeaders = ({ diff --git a/frontend/pages/hosts/details/cards/Software/helpers.tsx b/frontend/pages/hosts/details/cards/Software/helpers.tsx new file mode 100644 index 0000000000..e251728bdf --- /dev/null +++ b/frontend/pages/hosts/details/cards/Software/helpers.tsx @@ -0,0 +1,36 @@ +import React from "react"; +import { getErrorReason } from "interfaces/errors"; +import { trimEnd, upperFirst } from "lodash"; + +const INSTALL_SOFTWARE_ERROR_PREFIX = "Couldn't install."; +const DEFAULT_ERROR_MESSAGE = `${INSTALL_SOFTWARE_ERROR_PREFIX} Please try again.`; + +const createOnlyInstallableOnMacOSMessage = (reason: string) => + `Couldn't install. ${reason.replace("darwin", "macOS")}.`; + +const createVPPTokenExpiredMessage = () => ( + <> + {INSTALL_SOFTWARE_ERROR_PREFIX} VPP token expired. Go to{" "} + + Settings {">"} Integration {">"} Volume Purchasing Program + {" "} + and renew token. + +); + +// eslint-disable-next-line import/prefer-default-export +export const getErrorMessage = (e: unknown) => { + const reason = upperFirst(trimEnd(getErrorReason(e), ".")); + + if (reason.includes("fleetd installed")) { + return `${INSTALL_SOFTWARE_ERROR_PREFIX}. ${reason}.`; + } else if (reason.includes("can be installed only on")) { + return createOnlyInstallableOnMacOSMessage(reason); + } else if (reason.includes("VPP token expired")) { + createVPPTokenExpiredMessage(); + } else if (reason.includes("MDM is turned off")) { + return reason; + } + + return DEFAULT_ERROR_MESSAGE; +};