fleet/frontend/pages/ManageControlsPage/ManageControlsPage.tsx
Jacob Shandling cb58849d95
Fleet Premium to Sandbox (#11372)
## Addresses #9371 
### Adds a suite of UI logic for premium features in the Sandbox
environment

For reviewer: please review the work for the below 3 substasks, which
are the only remaining subtasks encompassed by this PR that have not yet
passed review individually:
  - #10822 (9)
  - #10823 (10)
  - #10824 (11)

## Checklist for submitter
- [x] Changes file added for user-visible changes in `changes/`
- [x] Manual QA for all new/changed functionality

---------

Co-authored-by: Jacob Shandling <jacob@fleetdm.com>
Co-authored-by: Martin Angers <martin.n.angers@gmail.com>
2023-04-27 08:53:30 -07:00

194 lines
5 KiB
TypeScript

import React, { useCallback, useContext } from "react";
import { Tab, Tabs, TabList } from "react-tabs";
import { InjectedRouter } from "react-router";
import PATHS from "router/paths";
import { AppContext } from "context/app";
import useTeamIdParam from "hooks/useTeamIdParam";
import TabsWrapper from "components/TabsWrapper";
import MainContent from "components/MainContent";
import TeamsDropdown from "components/TeamsDropdown";
import EmptyTable from "components/EmptyTable";
import Button from "components/buttons/Button";
interface IControlsSubNavItem {
name: string;
pathname: string;
}
const controlsSubNav: IControlsSubNavItem[] = [
{
name: "macOS updates",
pathname: PATHS.CONTROLS_MAC_OS_UPDATES,
},
{
name: "macOS settings",
pathname: PATHS.CONTROLS_MAC_SETTINGS,
},
{
name: "macOS setup",
pathname: PATHS.CONTROLS_MAC_SETUP,
},
];
interface IManageControlsPageProps {
children: JSX.Element;
location: {
pathname: string;
search: string;
hash?: string;
query: {
team_id?: string;
};
};
router: InjectedRouter; // v3
}
const getTabIndex = (path: string): number => {
return controlsSubNav.findIndex((navItem) => {
// tab stays highlighted for paths that start with same pathname
return path.startsWith(navItem.pathname);
});
};
const baseClass = "manage-controls-page";
const ManageControlsPage = ({
// TODO(sarah): decide on pattern to pass team id to subcomponents.
// using children makes it difficult to centralize page-level control
// over team id param
children,
location,
router,
}: IManageControlsPageProps): JSX.Element => {
const {
config,
isFreeTier,
isOnGlobalTeam,
isPremiumTier,
isGlobalAdmin,
isSandboxMode,
} = useContext(AppContext);
const {
currentTeamId,
userTeams,
teamIdForApi,
handleTeamChange,
} = useTeamIdParam({
location,
router,
includeAllTeams: false,
includeNoTeam: true,
permittedAccessByTeamRole: {
admin: true,
maintainer: true,
observer: false,
observer_plus: false,
},
});
const navigateToNav = useCallback(
(i: number): void => {
const navPath = controlsSubNav[i].pathname;
router.replace(
navPath.concat(location?.search || "").concat(location?.hash || "")
);
},
[location, router]
);
const onConnectClick = () => {
router.push(PATHS.ADMIN_INTEGRATIONS_MDM);
};
const renderConnectButton = () => {
if (isGlobalAdmin) {
return (
<Button
variant="brand"
onClick={onConnectClick}
className={`${baseClass}__connectAPC-button`}
>
Connect
</Button>
);
}
return <></>;
};
const getInfoText = () => {
if (isGlobalAdmin) {
return "Connect Fleet to the Apple Push Certificates Portal to get started.";
}
return "Your Fleet administrator must connect Fleet to the Apple Push Certificates Portal to get started.";
};
const renderBody = () => {
return config?.mdm.enabled_and_configured ? (
<div>
<TabsWrapper>
<Tabs
selectedIndex={getTabIndex(location?.pathname || "")}
onSelect={navigateToNav}
>
<TabList>
{controlsSubNav.map((navItem) => {
return (
<Tab key={navItem.name} data-text={navItem.name}>
{navItem.name}
</Tab>
);
})}
</TabList>
</Tabs>
</TabsWrapper>
{React.cloneElement(children, { teamIdForApi })}
</div>
) : (
<EmptyTable
header="Manage your macOS hosts"
info={getInfoText()}
primaryButton={renderConnectButton()}
/>
);
};
return (
<MainContent>
<div className={`${baseClass}__wrapper`}>
<div className={`${baseClass}__header-wrap`}>
<div className={`${baseClass}__header-wrap`}>
<div className={`${baseClass}__header`}>
<div className={`${baseClass}__text`}>
<div className={`${baseClass}__title`}>
{isFreeTier && <h1>Controls</h1>}
{isPremiumTier &&
userTeams &&
(userTeams.length > 1 || isOnGlobalTeam) && (
<TeamsDropdown
currentUserTeams={userTeams}
selectedTeamId={currentTeamId}
onChange={handleTeamChange}
includeAll={false}
includeNoTeams
isSandboxMode={isSandboxMode}
/>
)}
{isPremiumTier &&
!isOnGlobalTeam &&
userTeams &&
userTeams.length === 1 && <h1>{userTeams[0].name}</h1>}
</div>
</div>
</div>
</div>
</div>
{renderBody()}
</div>
</MainContent>
);
};
export default ManageControlsPage;