mirror of
https://github.com/fleetdm/fleet
synced 2026-04-27 16:37:55 +00:00
relates to #10935 This is the UI for all the flows around adding, removing, downloading, and viewing information about a bootstrap package for fleet mdm. This is pretty comprehensive but includes: ### Backend **Update `Get host/id`** to include bootstrap package name ```json { "macos_setup": { ... "bootstrap_package_name": "test.pkg" } } ``` ### Frontend **UI for ABM not being set up**:  **UIs for uploading, downloading, and deleting bootstrap package**:    **UIs for seeing bootstrap status aggregate data**  **UIs for filtering hosts by bootstrap status**  **UIs for seeing package status on host details and my device page**:   - [x] Changes file added for user-visible changes in `changes/` or `orbit/changes/`. See [Changes files](https://fleetdm.com/docs/contributing/committing-changes#changes-files) for more information. - [x] Manual QA for all new/changed functionality --------- Co-authored-by: Roberto Dip <dip.jesusr@gmail.com> Co-authored-by: gillespi314 <73313222+gillespi314@users.noreply.github.com> Co-authored-by: Martin Angers <martin.n.angers@gmail.com>
107 lines
3.1 KiB
TypeScript
107 lines
3.1 KiB
TypeScript
import React, { useContext, useState } from "react";
|
||
import { useQuery } from "react-query";
|
||
import { AxiosResponse } from "axios";
|
||
|
||
import { IBootstrapPackageMetadata } from "interfaces/mdm";
|
||
import { IApiError } from "interfaces/errors";
|
||
import mdmAPI from "services/entities/mdm";
|
||
import { NotificationContext } from "context/notification";
|
||
|
||
import Spinner from "components/Spinner";
|
||
import BootstrapPackagePreview from "./components/BootstrapPackagePreview";
|
||
import PackageUploader from "./components/BootstrapPackageUploader";
|
||
import UploadedPackageView from "./components/UploadedPackageView";
|
||
import DeletePackageModal from "./components/DeletePackageModal";
|
||
|
||
const baseClass = "bootstrap-package";
|
||
|
||
interface IBootstrapPackageProps {
|
||
currentTeamId: number;
|
||
}
|
||
|
||
const BootstrapPackage = ({ currentTeamId }: IBootstrapPackageProps) => {
|
||
const { renderFlash } = useContext(NotificationContext);
|
||
const [showDeletePackageModal, setShowDeletePackageModal] = useState(false);
|
||
|
||
const {
|
||
data: bootstrapMetadata,
|
||
isLoading,
|
||
error,
|
||
refetch: refretchBootstrapMetadata,
|
||
} = useQuery<
|
||
IBootstrapPackageMetadata,
|
||
AxiosResponse<IApiError>,
|
||
IBootstrapPackageMetadata
|
||
>(
|
||
["bootstrap-metadata", currentTeamId],
|
||
() => mdmAPI.getBootstrapPackageMetadata(currentTeamId),
|
||
{
|
||
retry: false,
|
||
refetchOnWindowFocus: false,
|
||
cacheTime: 0,
|
||
}
|
||
);
|
||
|
||
const onUpload = () => {
|
||
refretchBootstrapMetadata();
|
||
};
|
||
|
||
const onDelete = async () => {
|
||
try {
|
||
await mdmAPI.deleteBootstrapPackage(currentTeamId);
|
||
renderFlash("success", "Successfully deleted!");
|
||
} catch {
|
||
renderFlash("error", "Couldn’t delete. Please try again.");
|
||
} finally {
|
||
setShowDeletePackageModal(false);
|
||
refretchBootstrapMetadata();
|
||
}
|
||
};
|
||
|
||
// we are relying on the API to tell us this resource does not exist to
|
||
// determine if the user has uploaded a bootstrap package.
|
||
const noPackageUploaded =
|
||
(error && error.status === 404) || !bootstrapMetadata;
|
||
|
||
return (
|
||
<div className={baseClass}>
|
||
<h2>Bootstrap package</h2>
|
||
{isLoading ? (
|
||
<Spinner />
|
||
) : (
|
||
<div className={`${baseClass}__content`}>
|
||
{noPackageUploaded ? (
|
||
<>
|
||
<PackageUploader
|
||
currentTeamId={currentTeamId}
|
||
onUpload={onUpload}
|
||
/>
|
||
<div className={`${baseClass}__preview-container`}>
|
||
<BootstrapPackagePreview />
|
||
</div>
|
||
</>
|
||
) : (
|
||
<>
|
||
<UploadedPackageView
|
||
bootstrapPackage={bootstrapMetadata}
|
||
currentTeamId={currentTeamId}
|
||
onDelete={() => setShowDeletePackageModal(true)}
|
||
/>
|
||
<div className={`${baseClass}__preview-container`}>
|
||
<BootstrapPackagePreview />
|
||
</div>
|
||
</>
|
||
)}
|
||
</div>
|
||
)}
|
||
{showDeletePackageModal && (
|
||
<DeletePackageModal
|
||
onDelete={onDelete}
|
||
onCancel={() => setShowDeletePackageModal(false)}
|
||
/>
|
||
)}
|
||
</div>
|
||
);
|
||
};
|
||
|
||
export default BootstrapPackage;
|