mirror of
https://github.com/fleetdm/fleet
synced 2026-04-21 13:37:30 +00:00
208 lines
5.3 KiB
TypeScript
208 lines
5.3 KiB
TypeScript
import React from "react";
|
|
import { InjectedRouter } from "react-router";
|
|
|
|
import { SELF_SERVICE_TOOLTIP } from "pages/SoftwarePage/helpers";
|
|
|
|
import TooltipWrapper from "components/TooltipWrapper";
|
|
import Icon from "components/Icon";
|
|
import { IconNames } from "components/icons";
|
|
import SoftwareIcon from "pages/SoftwarePage/components/icons/SoftwareIcon";
|
|
import LinkCell from "../LinkCell";
|
|
import TooltipTruncatedTextCell from "../TooltipTruncatedTextCell";
|
|
|
|
const baseClass = "software-name-cell";
|
|
|
|
type InstallType =
|
|
| "manual"
|
|
| "selfService"
|
|
| "automatic"
|
|
| "automaticSelfService";
|
|
|
|
export type PageContext = "deviceUser" | "hostDetails" | "hostDetailsLibrary";
|
|
|
|
interface InstallIconTooltip {
|
|
automaticInstallPoliciesCount?: number;
|
|
pageContext?: PageContext;
|
|
}
|
|
|
|
interface InstallIconConfig {
|
|
iconName: IconNames;
|
|
tooltip: ({
|
|
automaticInstallPoliciesCount,
|
|
pageContext,
|
|
}: InstallIconTooltip) => JSX.Element;
|
|
}
|
|
|
|
const getPolicyTooltip = (count = 0) =>
|
|
count === 1
|
|
? "A policy triggers install."
|
|
: `${count} policies trigger install.`;
|
|
|
|
const installIconMap: Record<InstallType, InstallIconConfig> = {
|
|
manual: {
|
|
iconName: "install",
|
|
tooltip: ({ pageContext }) => (
|
|
<>
|
|
Software can be installed on the{" "}
|
|
{pageContext === "hostDetails" ? "Library tab" : "Host details page"}.
|
|
</>
|
|
),
|
|
},
|
|
selfService: {
|
|
iconName: "user",
|
|
tooltip: () => SELF_SERVICE_TOOLTIP,
|
|
},
|
|
automatic: {
|
|
iconName: "refresh",
|
|
tooltip: ({ automaticInstallPoliciesCount = 0 }) => (
|
|
<>{getPolicyTooltip(automaticInstallPoliciesCount)}</>
|
|
),
|
|
},
|
|
automaticSelfService: {
|
|
iconName: "automatic-self-service",
|
|
tooltip: ({ automaticInstallPoliciesCount = 0 }) => (
|
|
<>
|
|
{getPolicyTooltip(automaticInstallPoliciesCount)}
|
|
<br />
|
|
End users can reinstall from
|
|
<br />
|
|
<b>Fleet Desktop {">"} Self-service</b>.
|
|
</>
|
|
),
|
|
},
|
|
};
|
|
|
|
interface IInstallIconWithTooltipProps {
|
|
isSelfService: boolean;
|
|
automaticInstallPoliciesCount?: number;
|
|
pageContext?: PageContext;
|
|
}
|
|
|
|
const getInstallIconType = (
|
|
isSelfService: boolean,
|
|
automaticInstallPoliciesCount = 0
|
|
): InstallType => {
|
|
if (automaticInstallPoliciesCount > 0) {
|
|
return isSelfService ? "automaticSelfService" : "automatic";
|
|
}
|
|
return isSelfService ? "selfService" : "manual";
|
|
};
|
|
|
|
const InstallIconWithTooltip = ({
|
|
isSelfService,
|
|
automaticInstallPoliciesCount,
|
|
pageContext,
|
|
}: IInstallIconWithTooltipProps) => {
|
|
const iconType = getInstallIconType(
|
|
isSelfService,
|
|
automaticInstallPoliciesCount
|
|
);
|
|
|
|
// Don't show installer icon on host software library page
|
|
if (iconType === "manual" && pageContext === "hostDetailsLibrary") {
|
|
return null;
|
|
}
|
|
|
|
const { iconName, tooltip } = installIconMap[iconType];
|
|
const tipContent = tooltip({
|
|
automaticInstallPoliciesCount,
|
|
pageContext,
|
|
});
|
|
|
|
return (
|
|
<div className={`${baseClass}__install-icon-with-tooltip`}>
|
|
<TooltipWrapper
|
|
tipContent={tipContent}
|
|
showArrow
|
|
underline={false}
|
|
position="top"
|
|
tipOffset={12}
|
|
>
|
|
<Icon
|
|
name={iconName}
|
|
className={`${baseClass}__install-icon`}
|
|
color="ui-fleet-black-50"
|
|
/>
|
|
</TooltipWrapper>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
interface ISoftwareNameCellProps {
|
|
/** Used to key default software icon and name displayed if no display_name */
|
|
name: string;
|
|
/** Overrides name for display */
|
|
display_name?: string;
|
|
source?: string;
|
|
/** pass in a `path` that this cell will link to */
|
|
path?: string;
|
|
router?: InjectedRouter;
|
|
pageContext?: PageContext;
|
|
hasInstaller?: boolean;
|
|
isSelfService?: boolean;
|
|
automaticInstallPoliciesCount?: number;
|
|
/** e.g. custom icons & app_store_app's override default icons with URLs */
|
|
iconUrl?: string | null;
|
|
}
|
|
|
|
const SoftwareNameCell = ({
|
|
name,
|
|
display_name,
|
|
source,
|
|
path,
|
|
router,
|
|
pageContext,
|
|
hasInstaller = false,
|
|
isSelfService = false,
|
|
automaticInstallPoliciesCount,
|
|
iconUrl,
|
|
}: ISoftwareNameCellProps) => {
|
|
const icon = <SoftwareIcon name={name} source={source} url={iconUrl} />;
|
|
// My device page > Software fake link as entire row opens a modal
|
|
if (pageContext === "deviceUser" && !isSelfService) {
|
|
return (
|
|
<LinkCell tooltipTruncate prefix={icon} value={display_name || name} />
|
|
);
|
|
}
|
|
|
|
// Non-clickable cell if no router/path (e.g. My device page > SelfService)
|
|
if (!router || !path) {
|
|
return (
|
|
<div className={baseClass}>
|
|
<TooltipTruncatedTextCell
|
|
prefix={icon}
|
|
value={display_name || name}
|
|
className="software-name"
|
|
/>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
const onClickSoftware = (e: React.MouseEvent) => {
|
|
// Allows for button to be clickable in a clickable row
|
|
e.stopPropagation();
|
|
router.push(path);
|
|
};
|
|
|
|
return (
|
|
<LinkCell
|
|
className={baseClass}
|
|
path={path}
|
|
tooltipTruncate
|
|
customOnClick={onClickSoftware}
|
|
prefix={icon}
|
|
value={display_name || name}
|
|
suffix={
|
|
hasInstaller ? (
|
|
<InstallIconWithTooltip
|
|
isSelfService={isSelfService}
|
|
automaticInstallPoliciesCount={automaticInstallPoliciesCount}
|
|
pageContext={pageContext}
|
|
/>
|
|
) : undefined
|
|
}
|
|
/>
|
|
);
|
|
};
|
|
|
|
export default SoftwareNameCell;
|