fleet/frontend/pages/ManageControlsPage/SetupExperience/cards/InstallSoftware/InstallSoftware.tsx
Gabriel Hernandez 789b56000f
Add UI for enabling manual agent install of a bootstrap package (#28550)
For #[26070](https://github.com/fleetdm/fleet/issues/26070)

This adds the UI for enabling a manual agent install for a bootstrap
package. This includes:

**The new form option for enabling manual agent install of a bootstrap
package**


![image](https://github.com/user-attachments/assets/5d271136-e41b-4c03-bbd8-09450ded82dc)

**disabling adding install software and run script options when user has
enabled manual agent install**


![image](https://github.com/user-attachments/assets/24e3ce6e-8c8f-4987-91e6-8f3fa721d67b)


![image](https://github.com/user-attachments/assets/41be4090-b97f-4ffb-ad76-001232ccd434)


**improvements to the setup experience content styling. I've created a
`SetupExperienceContentContainer` component to centralise the styles for
the content of these sub sections.**

**updates to the preview sections copy and replacing the gifs with
videos**

- [x] Changes file added for user-visible changes in `changes/`,
`orbit/changes/` or `ee/fleetd-chrome/changes`.
- [ ] Added/updated automated tests
- [x] Manual QA for all new/changed functionality

---------

Co-authored-by: Sarah Gillespie <73313222+gillespi314@users.noreply.github.com>
2025-04-29 15:29:21 +01:00

131 lines
3.8 KiB
TypeScript

import React, { useState } from "react";
import { useQuery } from "react-query";
import { AxiosError } from "axios";
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 } from "utilities/constants";
import { IConfig } from "interfaces/config";
import { API_NO_TEAM_ID, ITeamConfig } from "interfaces/team";
import SectionHeader from "components/SectionHeader";
import DataError from "components/DataError";
import Spinner from "components/Spinner";
import InstallSoftwarePreview from "./components/InstallSoftwarePreview";
import AddInstallSoftware from "./components/AddInstallSoftware";
import SelectSoftwareModal from "./components/SelectSoftwareModal";
import SetupExperienceContentContainer from "../../components/SetupExperienceContentContainer";
import { getManualAgentInstallSetting } from "../BootstrapPackage/BootstrapPackage";
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;
interface IInstallSoftwareProps {
currentTeamId: number;
}
const InstallSoftware = ({ currentTeamId }: IInstallSoftwareProps) => {
const [showSelectSoftwareModal, setShowSelectSoftwareModal] = useState(false);
const {
data: softwareTitles,
isLoading,
isError,
refetch: refetchSoftwareTitles,
} = useQuery<
IGetSetupExperienceSoftwareResponse,
AxiosError,
ISoftwareTitle[] | null
>(
["install-software", currentTeamId],
() =>
mdmAPI.getSetupExperienceSoftware({
team_id: currentTeamId,
per_page: PER_PAGE_SIZE,
}),
{
...DEFAULT_USE_QUERY_OPTIONS,
select: (res) => res.software_titles,
}
);
const { data: globalConfig, isLoading: isLoadingGlobalConfig } = useQuery<
IConfig,
Error
>(["config", currentTeamId], () => configAPI.loadAll(), {
...DEFAULT_USE_QUERY_OPTIONS,
enabled: currentTeamId === API_NO_TEAM_ID,
});
const { data: teamConfig, isLoading: isLoadingTeamConfig } = useQuery<
ILoadTeamResponse,
Error,
ITeamConfig
>(["team", currentTeamId], () => teamsAPI.load(currentTeamId), {
...DEFAULT_USE_QUERY_OPTIONS,
enabled: currentTeamId !== API_NO_TEAM_ID,
select: (res) => res.team,
});
const onSave = async () => {
setShowSelectSoftwareModal(false);
refetchSoftwareTitles();
};
const hasManualAgentInstall = getManualAgentInstallSetting(
currentTeamId,
globalConfig,
teamConfig
);
const renderContent = () => {
if (isLoading || isLoadingGlobalConfig || isLoadingTeamConfig) {
return <Spinner />;
}
if (isError) {
return <DataError />;
}
if (softwareTitles || softwareTitles === null) {
return (
<SetupExperienceContentContainer>
<AddInstallSoftware
currentTeamId={currentTeamId}
hasManualAgentInstall={hasManualAgentInstall}
softwareTitles={softwareTitles}
onAddSoftware={() => setShowSelectSoftwareModal(true)}
/>
<InstallSoftwarePreview />
</SetupExperienceContentContainer>
);
}
return null;
};
return (
<section className={baseClass}>
<SectionHeader title="Install software" />
<>{renderContent()}</>
{showSelectSoftwareModal && softwareTitles && (
<SelectSoftwareModal
currentTeamId={currentTeamId}
softwareTitles={softwareTitles}
onSave={onSave}
onExit={() => setShowSelectSoftwareModal(false)}
/>
)}
</section>
);
};
export default InstallSoftware;