fleet/frontend/pages/SoftwarePage/SoftwareAddPage/SoftwareAddPage.tsx

155 lines
4.4 KiB
TypeScript

import React, { useCallback, useContext } from "react";
import { Tab, TabList, Tabs } from "react-tabs";
import { InjectedRouter } from "react-router";
import { Location } from "history";
import PATHS from "router/paths";
import { getPathWithQueryParams } from "utilities/url";
import { QueryContext } from "context/query";
import useToggleSidePanel from "hooks/useToggleSidePanel";
import { APP_CONTEXT_NO_TEAM_ID } from "interfaces/team";
import SidePanelPage from "components/SidePanelPage";
import MainContent from "components/MainContent";
import BackButton from "components/BackButton";
import TabNav from "components/TabNav";
import TabText from "components/TabText";
import SidePanelContent from "components/SidePanelContent";
import QuerySidePanel from "components/side_panels/QuerySidePanel";
const baseClass = "software-add-page";
interface IAddSoftwareSubNavItem {
name: string;
pathname: string;
}
const addSoftwareSubNav: IAddSoftwareSubNavItem[] = [
{
name: "Fleet-maintained",
pathname: PATHS.SOFTWARE_ADD_FLEET_MAINTAINED,
},
{
name: "App store",
pathname: PATHS.SOFTWARE_ADD_APP_STORE,
},
{
name: "Custom package",
pathname: PATHS.SOFTWARE_ADD_PACKAGE,
},
];
const getTabIndex = (path: string): number => {
return addSoftwareSubNav.findIndex((navItem) => {
// tab stays highlighted for paths that start with same pathname
return path.startsWith(navItem.pathname);
});
};
export interface ISoftwareAddPageQueryParams {
fleet_id?: string;
query?: string;
page?: string;
order_key?: string;
order_direction?: "asc" | "desc";
}
interface ISoftwareAddPageProps {
children: JSX.Element;
location: Location<ISoftwareAddPageQueryParams>;
router: InjectedRouter;
}
const SoftwareAddPage = ({
children,
location,
router,
}: ISoftwareAddPageProps) => {
const { selectedOsqueryTable, setSelectedOsqueryTable } = useContext(
QueryContext
);
const { isSidePanelOpen, setSidePanelOpen } = useToggleSidePanel(false);
const navigateToNav = useCallback(
(i: number): void => {
setSidePanelOpen(false);
// Only query param to persist between tabs is team id
const navPath = getPathWithQueryParams(addSoftwareSubNav[i].pathname, {
fleet_id: location.query.fleet_id,
});
router.replace(navPath);
},
[location.query.fleet_id, router, setSidePanelOpen]
);
// Quick exit if no fleet_id param. This page must have a team id to function
// correctly. We redirect to the same page with the "No team" context if it
// is not provieded.
if (!location.query.fleet_id) {
router.replace(
getPathWithQueryParams(location.pathname, {
fleet_id: APP_CONTEXT_NO_TEAM_ID,
})
);
return null;
}
const onOsqueryTableSelect = (tableName: string) => {
setSelectedOsqueryTable(tableName);
};
const backUrl = getPathWithQueryParams(PATHS.SOFTWARE_TITLES, {
fleet_id: location.query.fleet_id,
});
return (
<SidePanelPage>
<>
<MainContent className={baseClass}>
<div className={`${baseClass}__header-links`}>
<BackButton
text="Back to software"
path={backUrl}
className={`${baseClass}__back-to-software`}
/>
</div>
<h1>Add software</h1>
<TabNav>
<Tabs
selectedIndex={getTabIndex(location?.pathname || "")}
onSelect={navigateToNav}
>
<TabList>
{addSoftwareSubNav.map((navItem) => {
return (
<Tab key={navItem.name} data-text={navItem.name}>
<TabText>{navItem.name}</TabText>
</Tab>
);
})}
</TabList>
</Tabs>
</TabNav>
{React.cloneElement(children, {
router,
currentTeamId: parseInt(location.query.fleet_id, 10),
isSidePanelOpen,
setSidePanelOpen,
})}
</MainContent>
{isSidePanelOpen && (
<SidePanelContent>
<QuerySidePanel
key="query-side-panel"
onOsqueryTableSelect={onOsqueryTableSelect}
selectedOsqueryTable={selectedOsqueryTable}
onClose={() => setSidePanelOpen(false)}
/>
</SidePanelContent>
)}
</>
</SidePanelPage>
);
};
export default SoftwareAddPage;