mirror of
https://github.com/fleetdm/fleet
synced 2026-05-24 09:28:54 +00:00
266 lines
7.6 KiB
TypeScript
266 lines
7.6 KiB
TypeScript
import React, { useCallback, useState } from "react";
|
|
import { useQuery } from "react-query";
|
|
import { AxiosError } from "axios";
|
|
import { Tab, TabList, TabPanel, Tabs } from "react-tabs";
|
|
|
|
import PATHS from "router/paths";
|
|
|
|
import mdmAPI, {
|
|
IGetSetupExperienceSoftwareResponse,
|
|
} from "services/entities/mdm";
|
|
import configAPI from "services/entities/config";
|
|
import teamsAPI, { ILoadTeamResponse } from "services/entities/teams";
|
|
import { ISoftwareTitle } from "interfaces/software";
|
|
import {
|
|
DEFAULT_USE_QUERY_OPTIONS,
|
|
LEARN_MORE_ABOUT_BASE_LINK,
|
|
} from "utilities/constants";
|
|
import { IConfig } from "interfaces/config";
|
|
import { API_NO_TEAM_ID, ITeamConfig } from "interfaces/team";
|
|
import {
|
|
isSetupExperiencePlatform,
|
|
SetupExperiencePlatform,
|
|
} from "interfaces/platform";
|
|
|
|
import SectionHeader from "components/SectionHeader";
|
|
import DataError from "components/DataError";
|
|
import Spinner from "components/Spinner";
|
|
import TabNav from "components/TabNav";
|
|
import TabText from "components/TabText";
|
|
import GenericMsgWithNavButton from "components/GenericMsgWithNavButton";
|
|
import CustomLink from "components/CustomLink";
|
|
|
|
import AddInstallSoftware from "./components/AddInstallSoftware";
|
|
import SelectSoftwareModal from "./components/SelectSoftwareModal";
|
|
import SetupExperienceContentContainer from "../../components/SetupExperienceContentContainer";
|
|
import { ISetupExperienceCardProps } from "../../SetupExperienceNavItems";
|
|
import getManualAgentInstallSetting from "../../helpers";
|
|
|
|
const baseClass = "install-software";
|
|
|
|
// This is so large because we want to get all the software titles that are
|
|
// available for install so we can correctly display the selected count.
|
|
const PER_PAGE_SIZE = 3000;
|
|
|
|
export const PLATFORM_BY_INDEX: SetupExperiencePlatform[] = [
|
|
"macos",
|
|
"windows",
|
|
"linux",
|
|
"ios",
|
|
"ipados",
|
|
"android",
|
|
];
|
|
export interface InstallSoftwareLocation {
|
|
search: string;
|
|
pathname: string;
|
|
query: {
|
|
team_id?: string;
|
|
};
|
|
}
|
|
|
|
const InstallSoftware = ({
|
|
currentTeamId,
|
|
router,
|
|
urlPlatformParam,
|
|
}: ISetupExperienceCardProps) => {
|
|
const isValidPlatform = isSetupExperiencePlatform(urlPlatformParam);
|
|
|
|
// all uses of selectedPlatform are gated by above boolean
|
|
const selectedPlatform = urlPlatformParam as SetupExperiencePlatform;
|
|
|
|
const [showSelectSoftwareModal, setShowSelectSoftwareModal] = useState(false);
|
|
|
|
const {
|
|
data: softwareTitles,
|
|
isLoading: isLoadingSoftwareTitles,
|
|
isError,
|
|
refetch: refetchSoftwareTitles,
|
|
} = useQuery<
|
|
IGetSetupExperienceSoftwareResponse,
|
|
AxiosError,
|
|
ISoftwareTitle[] | null
|
|
>(
|
|
["install-software", currentTeamId, selectedPlatform],
|
|
() =>
|
|
mdmAPI.getSetupExperienceSoftware({
|
|
platform: selectedPlatform,
|
|
team_id: currentTeamId,
|
|
per_page: PER_PAGE_SIZE,
|
|
}),
|
|
{
|
|
...DEFAULT_USE_QUERY_OPTIONS,
|
|
select: (res) => res.software_titles,
|
|
enabled: isValidPlatform,
|
|
}
|
|
);
|
|
|
|
const { data: globalConfig, isLoading: isLoadingGlobalConfig } = useQuery<
|
|
IConfig,
|
|
Error
|
|
>(["config", currentTeamId], () => configAPI.loadAll(), {
|
|
...DEFAULT_USE_QUERY_OPTIONS,
|
|
enabled: isValidPlatform,
|
|
});
|
|
|
|
const { data: teamConfig, isLoading: isLoadingTeamConfig } = useQuery<
|
|
ILoadTeamResponse,
|
|
Error,
|
|
ITeamConfig
|
|
>(["team", currentTeamId], () => teamsAPI.load(currentTeamId), {
|
|
...DEFAULT_USE_QUERY_OPTIONS,
|
|
enabled: isValidPlatform && currentTeamId !== API_NO_TEAM_ID,
|
|
select: (res) => res.team,
|
|
});
|
|
|
|
const handleTabChange = useCallback(
|
|
(index: number) => {
|
|
const newPlatform = PLATFORM_BY_INDEX[index];
|
|
router.push(
|
|
PATHS.CONTROLS_INSTALL_SOFTWARE(newPlatform).concat(
|
|
location?.search ?? ""
|
|
)
|
|
);
|
|
},
|
|
[router]
|
|
);
|
|
|
|
if (!isValidPlatform) {
|
|
router.replace(
|
|
PATHS.CONTROLS_INSTALL_SOFTWARE("macos").concat(location?.search ?? "")
|
|
);
|
|
}
|
|
|
|
const onSave = async () => {
|
|
setShowSelectSoftwareModal(false);
|
|
refetchSoftwareTitles();
|
|
};
|
|
|
|
const hasManualAgentInstall = getManualAgentInstallSetting(
|
|
currentTeamId,
|
|
globalConfig,
|
|
teamConfig
|
|
);
|
|
|
|
const isAndroidMdmEnabled = globalConfig?.mdm.android_enabled_and_configured;
|
|
|
|
const isLoadingConfig = isLoadingGlobalConfig || isLoadingTeamConfig;
|
|
|
|
const renderTabContent = (platform: SetupExperiencePlatform) => {
|
|
if (isLoadingSoftwareTitles) {
|
|
return <Spinner />;
|
|
}
|
|
|
|
if (isError) {
|
|
return <DataError />;
|
|
}
|
|
|
|
if (softwareTitles || softwareTitles === null) {
|
|
const appleMdmAndAbmEnabled =
|
|
globalConfig?.mdm.enabled_and_configured &&
|
|
globalConfig?.mdm.apple_bm_enabled_and_configured;
|
|
const turnOnAppleMdm =
|
|
(platform === "macos" || platform === "ios" || platform === "ipados") &&
|
|
!appleMdmAndAbmEnabled;
|
|
|
|
const turnOnWindowsMdm =
|
|
platform === "windows" &&
|
|
!globalConfig?.mdm.windows_enabled_and_configured;
|
|
|
|
const turnOnMdm = turnOnAppleMdm || turnOnWindowsMdm;
|
|
|
|
if (turnOnMdm) {
|
|
return (
|
|
<GenericMsgWithNavButton
|
|
header="Additional configuration required"
|
|
info="To customize, first turn on automatic enrollment."
|
|
buttonText="Turn on"
|
|
path={PATHS.ADMIN_INTEGRATIONS_MDM}
|
|
router={router}
|
|
/>
|
|
);
|
|
}
|
|
return (
|
|
<SetupExperienceContentContainer>
|
|
<AddInstallSoftware
|
|
currentTeamId={currentTeamId}
|
|
hasManualAgentInstall={hasManualAgentInstall}
|
|
softwareTitles={softwareTitles}
|
|
onAddSoftware={() => setShowSelectSoftwareModal(true)}
|
|
platform={platform}
|
|
savedRequireAllSoftwareMacOS={
|
|
currentTeamId
|
|
? teamConfig?.mdm?.macos_setup?.require_all_software_macos
|
|
: globalConfig?.mdm?.macos_setup?.require_all_software_macos
|
|
}
|
|
/>
|
|
</SetupExperienceContentContainer>
|
|
);
|
|
}
|
|
|
|
return null;
|
|
};
|
|
|
|
return (
|
|
<section className={baseClass}>
|
|
<SectionHeader
|
|
title="Install software"
|
|
details={
|
|
<CustomLink
|
|
newTab
|
|
url={`${LEARN_MORE_ABOUT_BASE_LINK}/setup-experience/install-software`}
|
|
text="Preview end user experience"
|
|
/>
|
|
}
|
|
/>
|
|
{isLoadingConfig ? (
|
|
<Spinner />
|
|
) : (
|
|
<TabNav secondary>
|
|
<Tabs
|
|
selectedIndex={PLATFORM_BY_INDEX.indexOf(selectedPlatform)}
|
|
onSelect={handleTabChange}
|
|
>
|
|
<TabList>
|
|
<Tab>
|
|
<TabText>macOS</TabText>
|
|
</Tab>
|
|
<Tab>
|
|
<TabText>Windows</TabText>
|
|
</Tab>
|
|
<Tab>
|
|
<TabText>Linux</TabText>
|
|
</Tab>
|
|
<Tab>
|
|
<TabText>iOS</TabText>
|
|
</Tab>
|
|
<Tab>
|
|
<TabText>iPadOS</TabText>
|
|
</Tab>
|
|
{isAndroidMdmEnabled && (
|
|
<Tab>
|
|
<TabText>Android</TabText>
|
|
</Tab>
|
|
)}
|
|
</TabList>
|
|
{PLATFORM_BY_INDEX.map((platform) => {
|
|
return (
|
|
<TabPanel key={platform}>{renderTabContent(platform)}</TabPanel>
|
|
);
|
|
})}
|
|
</Tabs>
|
|
</TabNav>
|
|
)}
|
|
{showSelectSoftwareModal && softwareTitles && (
|
|
<SelectSoftwareModal
|
|
currentTeamId={currentTeamId}
|
|
softwareTitles={softwareTitles}
|
|
platform={selectedPlatform}
|
|
onSave={onSave}
|
|
onExit={() => setShowSelectSoftwareModal(false)}
|
|
/>
|
|
)}
|
|
</section>
|
|
);
|
|
};
|
|
|
|
export default InstallSoftware;
|