Teams Details Page: Add generate installer and manage enroll secret CTA buttons (#3864)
This commit is contained in:
@@ -0,0 +1 @@
|
||||
* Add generate installer and manage enroll secrets to team details page
|
||||
+2
-2
@@ -6,7 +6,7 @@ import EnrollSecretTable from "components/EnrollSecretTable";
|
||||
import { ITeam } from "interfaces/team";
|
||||
import { IEnrollSecret } from "interfaces/enroll_secret";
|
||||
|
||||
import PlusIcon from "../../../../../../assets/images/icon-plus-16x16@2x.png";
|
||||
import PlusIcon from "../../../assets/images/icon-plus-16x16@2x.png";
|
||||
|
||||
interface IEnrollSecretModal {
|
||||
selectedTeam: number;
|
||||
@@ -17,7 +17,7 @@ interface IEnrollSecretModal {
|
||||
setSelectedSecret: React.Dispatch<
|
||||
React.SetStateAction<IEnrollSecret | undefined>
|
||||
>;
|
||||
globalSecrets: IEnrollSecret[] | undefined;
|
||||
globalSecrets?: IEnrollSecret[] | undefined;
|
||||
}
|
||||
|
||||
const baseClass = "enroll-secret-modal";
|
||||
+3
-3
@@ -18,10 +18,10 @@ import Button from "components/buttons/Button";
|
||||
import InputField from "components/forms/fields/InputField";
|
||||
import TabsWrapper from "components/TabsWrapper";
|
||||
|
||||
import { isValidPemCertificate } from "../../../helpers";
|
||||
import { isValidPemCertificate } from "../../../pages/hosts/ManageHostsPage/helpers";
|
||||
|
||||
import CopyIcon from "../../../../../../../assets/images/icon-copy-clipboard-fleet-blue-20x20@2x.png";
|
||||
import DownloadIcon from "../../../../../../../assets/images/icon-download-12x12@2x.png";
|
||||
import CopyIcon from "../../../../assets/images/icon-copy-clipboard-fleet-blue-20x20@2x.png";
|
||||
import DownloadIcon from "../../../../assets/images/icon-download-12x12@2x.png";
|
||||
|
||||
interface IPlatformSubNav {
|
||||
name: string;
|
||||
+238
-73
@@ -1,19 +1,26 @@
|
||||
import React, { useState, useEffect, useCallback, useContext } from "react";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import { useDispatch } from "react-redux";
|
||||
import { useQuery } from "react-query";
|
||||
import { InjectedRouter, Link, RouteProps } from "react-router";
|
||||
import { push } from "react-router-redux";
|
||||
import { Tab, TabList, Tabs } from "react-tabs";
|
||||
import { find, memoize, toNumber } from "lodash";
|
||||
import { find, toNumber } from "lodash";
|
||||
import classnames from "classnames";
|
||||
|
||||
import PATHS from "router/paths";
|
||||
import { ITeam } from "interfaces/team";
|
||||
import { IUser } from "interfaces/user";
|
||||
import { ITeam, ITeamSummary } from "interfaces/team";
|
||||
import { AppContext } from "context/app";
|
||||
// ignore TS error for now until these are rewritten in ts.
|
||||
// @ts-ignore
|
||||
import { renderFlash } from "redux/nodes/notifications/actions";
|
||||
import teamsAPI from "services/entities/teams";
|
||||
import enrollSecretsAPI from "services/entities/enroll_secret";
|
||||
import teamActions from "redux/nodes/entities/teams/actions";
|
||||
import {
|
||||
IEnrollSecret,
|
||||
IEnrollSecretsResponse,
|
||||
} from "interfaces/enroll_secret";
|
||||
import sortUtils from "utilities/sort";
|
||||
import Spinner from "components/Spinner";
|
||||
import Button from "components/buttons/Button";
|
||||
import TabsWrapper from "components/TabsWrapper";
|
||||
@@ -22,9 +29,13 @@ import { getNextLocationPath } from "pages/admin/UserManagementPage/helpers/user
|
||||
import DeleteTeamModal from "../components/DeleteTeamModal";
|
||||
import EditTeamModal from "../components/EditTeamModal";
|
||||
import { IEditTeamFormData } from "../components/EditTeamModal/EditTeamModal";
|
||||
import AddHostsRedirectModal from "./components/AddHostsModal/AddHostsRedirectModal";
|
||||
import DeleteSecretModal from "../../../../components/DeleteSecretModal";
|
||||
import SecretEditorModal from "../../../../components/SecretEditorModal";
|
||||
import GenerateInstallerModal from "../../../../components/GenerateInstallerModal";
|
||||
import EnrollSecretModal from "../../../../components/EnrollSecretModal";
|
||||
|
||||
import BackChevron from "../../../../../assets/images/icon-chevron-down-9x6@2x.png";
|
||||
import EyeIcon from "../../../../../assets/images/icon-eye-16x16@2x.png";
|
||||
import PencilIcon from "../../../../../assets/images/icon-pencil-14x14@2x.png";
|
||||
import TrashIcon from "../../../../../assets/images/icon-trash-14x14@2x.png";
|
||||
|
||||
@@ -46,16 +57,8 @@ const teamDetailsSubNav: ITeamDetailsSubNavItem[] = [
|
||||
},
|
||||
];
|
||||
|
||||
interface IRootState {
|
||||
auth: {
|
||||
user: IUser;
|
||||
};
|
||||
entities: {
|
||||
teams: {
|
||||
loading: boolean;
|
||||
data: { [id: number]: ITeam };
|
||||
};
|
||||
};
|
||||
interface ITeamsResponse {
|
||||
teams: ITeam[];
|
||||
}
|
||||
|
||||
interface ITeamDetailsPageProps {
|
||||
@@ -70,19 +73,11 @@ interface ITeamDetailsPageProps {
|
||||
router: InjectedRouter;
|
||||
}
|
||||
|
||||
const getTeams = (data: { [id: string]: ITeam }) => {
|
||||
return Object.keys(data).map((teamId) => {
|
||||
return data[teamId];
|
||||
});
|
||||
};
|
||||
|
||||
const memoizedGetTeams = memoize(getTeams);
|
||||
|
||||
const generateUpdateData = (
|
||||
currentTeamData: ITeam,
|
||||
currentTeam: ITeamSummary,
|
||||
formData: IEditTeamFormData
|
||||
): IEditTeamFormData | null => {
|
||||
if (currentTeamData.name !== formData.name) {
|
||||
if (currentTeam.name !== formData.name) {
|
||||
return {
|
||||
name: formData.name,
|
||||
};
|
||||
@@ -103,31 +98,66 @@ const TeamDetailsWrapper = ({
|
||||
location: { pathname },
|
||||
params: routeParams,
|
||||
}: ITeamDetailsPageProps): JSX.Element => {
|
||||
const { isGlobalAdmin, isOnGlobalTeam, setCurrentTeam } = useContext(
|
||||
AppContext
|
||||
);
|
||||
const dispatch = useDispatch();
|
||||
|
||||
const isLoadingTeams = useSelector(
|
||||
(state: IRootState) => state.entities.teams.loading
|
||||
);
|
||||
const team = useSelector((state: IRootState) => {
|
||||
return state.entities.teams.data[routeParams.team_id];
|
||||
});
|
||||
const teams = useSelector((state: IRootState) => {
|
||||
return memoizedGetTeams(state.entities.teams.data);
|
||||
});
|
||||
const userTeams = useSelector((state: IRootState) => {
|
||||
return state.auth.user.teams;
|
||||
});
|
||||
const {
|
||||
currentUser,
|
||||
isGlobalAdmin,
|
||||
currentTeam,
|
||||
isOnGlobalTeam,
|
||||
isPremiumTier,
|
||||
setCurrentTeam,
|
||||
} = useContext(AppContext);
|
||||
|
||||
const userTeams = currentUser?.teams || [];
|
||||
const routeTemplate = route && route.path ? route.path : "";
|
||||
|
||||
const [showAddHostsRedirectModal, setShowAddHostsRedirectModal] = useState(
|
||||
const [selectedSecret, setSelectedSecret] = useState<IEnrollSecret>();
|
||||
const [showGenerateInstallerModal, setShowGenerateInstallerModal] = useState(
|
||||
false
|
||||
);
|
||||
const [
|
||||
showManageEnrollSecretsModal,
|
||||
setShowManageEnrollSecretsModal,
|
||||
] = useState(false);
|
||||
const [showDeleteSecretModal, setShowDeleteSecretModal] = useState(false);
|
||||
const [showEnrollSecretModal, setShowEnrollSecretModal] = useState(false);
|
||||
const [showSecretEditorModal, setShowSecretEditorModal] = useState(false);
|
||||
const [showDeleteTeamModal, setShowDeleteTeamModal] = useState(false);
|
||||
const [showEditTeamModal, setShowEditTeamModal] = useState(false);
|
||||
|
||||
const dispatch = useDispatch();
|
||||
const {
|
||||
data: teams,
|
||||
isLoading: isLoadingTeams,
|
||||
refetch: refetchTeams,
|
||||
} = useQuery<ITeamsResponse, Error, ITeam[]>(
|
||||
["teams"],
|
||||
() => teamsAPI.loadAll(),
|
||||
{
|
||||
select: (data: ITeamsResponse) =>
|
||||
data.teams.sort((a, b) => sortUtils.caseInsensitiveAsc(a.name, b.name)),
|
||||
onSuccess: (responseTeams: ITeam[]) => {
|
||||
const findTeam = responseTeams.find(
|
||||
(team) => team.id === Number(routeParams.team_id)
|
||||
);
|
||||
setCurrentTeam(findTeam);
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
const {
|
||||
isLoading: isTeamSecretsLoading,
|
||||
data: teamSecrets,
|
||||
refetch: refetchTeamSecrets,
|
||||
} = useQuery<IEnrollSecretsResponse, Error, IEnrollSecret[]>(
|
||||
["team secrets", routeParams],
|
||||
() => {
|
||||
return enrollSecretsAPI.getTeamEnrollSecrets(routeParams.team_id);
|
||||
},
|
||||
{
|
||||
select: (data: IEnrollSecretsResponse) => data.secrets,
|
||||
}
|
||||
);
|
||||
|
||||
const navigateToNav = (i: number): void => {
|
||||
const navPath = teamDetailsSubNav[i].getPathname(routeParams.team_id);
|
||||
@@ -140,9 +170,38 @@ const TeamDetailsWrapper = ({
|
||||
|
||||
const [teamMenuIsOpen, setTeamMenuIsOpen] = useState<boolean>(false);
|
||||
|
||||
const toggleAddHostsRedirectModal = useCallback(() => {
|
||||
setShowAddHostsRedirectModal(!showAddHostsRedirectModal);
|
||||
}, [showAddHostsRedirectModal, setShowAddHostsRedirectModal]);
|
||||
const toggleGenerateInstallerModal = useCallback(() => {
|
||||
setShowGenerateInstallerModal(!showGenerateInstallerModal);
|
||||
}, [showGenerateInstallerModal, setShowGenerateInstallerModal]);
|
||||
|
||||
const toggleManageEnrollSecretsModal = useCallback(() => {
|
||||
setShowManageEnrollSecretsModal(!showManageEnrollSecretsModal);
|
||||
}, [showManageEnrollSecretsModal, setShowManageEnrollSecretsModal]);
|
||||
|
||||
const toggleDeleteSecretModal = useCallback(() => {
|
||||
// open and closes delete modal
|
||||
setShowDeleteSecretModal(!showDeleteSecretModal);
|
||||
// open and closes main enroll secret modal
|
||||
setShowEnrollSecretModal(!showEnrollSecretModal);
|
||||
}, [
|
||||
setShowDeleteSecretModal,
|
||||
showDeleteSecretModal,
|
||||
setShowEnrollSecretModal,
|
||||
showEnrollSecretModal,
|
||||
]);
|
||||
|
||||
// this is called when we click add or edit
|
||||
const toggleSecretEditorModal = useCallback(() => {
|
||||
// open and closes add/edit modal
|
||||
setShowSecretEditorModal(!showSecretEditorModal);
|
||||
// open and closes main enroll secret modall
|
||||
setShowEnrollSecretModal(!showEnrollSecretModal);
|
||||
}, [
|
||||
setShowSecretEditorModal,
|
||||
showSecretEditorModal,
|
||||
setShowEnrollSecretModal,
|
||||
showEnrollSecretModal,
|
||||
]);
|
||||
|
||||
const toggleDeleteTeamModal = useCallback(() => {
|
||||
setShowDeleteTeamModal(!showDeleteTeamModal);
|
||||
@@ -152,12 +211,76 @@ const TeamDetailsWrapper = ({
|
||||
setShowEditTeamModal(!showEditTeamModal);
|
||||
}, [showEditTeamModal, setShowEditTeamModal]);
|
||||
|
||||
const onAddHostsRedirectClick = useCallback(() => {
|
||||
dispatch(push(PATHS.MANAGE_HOSTS));
|
||||
}, [dispatch]);
|
||||
const onSaveSecret = async (enrollSecretString: string) => {
|
||||
// Creates new list of secrets removing selected secret and adding new secret
|
||||
const currentSecrets = teamSecrets || [];
|
||||
|
||||
const newSecrets = currentSecrets.filter(
|
||||
(s) => s.secret !== selectedSecret?.secret
|
||||
);
|
||||
|
||||
if (enrollSecretString) {
|
||||
newSecrets.push({ secret: enrollSecretString });
|
||||
}
|
||||
|
||||
try {
|
||||
await enrollSecretsAPI.modifyTeamEnrollSecrets(
|
||||
routeParams.team_id,
|
||||
newSecrets
|
||||
);
|
||||
refetchTeamSecrets();
|
||||
|
||||
toggleSecretEditorModal();
|
||||
isPremiumTier && refetchTeams();
|
||||
dispatch(
|
||||
renderFlash(
|
||||
"success",
|
||||
`Successfully ${selectedSecret ? "edited" : "added"} enroll secret.`
|
||||
)
|
||||
);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
dispatch(
|
||||
renderFlash(
|
||||
"error",
|
||||
`Could not ${
|
||||
selectedSecret ? "edit" : "add"
|
||||
} enroll secret. Please try again.`
|
||||
)
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
const onDeleteSecret = async () => {
|
||||
// create new list of secrets removing selected secret
|
||||
const currentSecrets = teamSecrets || [];
|
||||
|
||||
const newSecrets = currentSecrets.filter(
|
||||
(s) => s.secret !== selectedSecret?.secret
|
||||
);
|
||||
|
||||
try {
|
||||
await enrollSecretsAPI.modifyTeamEnrollSecrets(
|
||||
routeParams.team_id,
|
||||
newSecrets
|
||||
);
|
||||
refetchTeamSecrets();
|
||||
toggleDeleteSecretModal();
|
||||
refetchTeams();
|
||||
dispatch(renderFlash("success", `Successfully deleted enroll secret.`));
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
dispatch(
|
||||
renderFlash(
|
||||
"error",
|
||||
"Could not delete enroll secret. Please try again."
|
||||
)
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
const onDeleteSubmit = useCallback(() => {
|
||||
dispatch(teamActions.destroy(team?.id))
|
||||
dispatch(teamActions.destroy(currentTeam?.id))
|
||||
.then(() => {
|
||||
dispatch(renderFlash("success", "Team removed"));
|
||||
dispatch(push(PATHS.ADMIN_TEAMS));
|
||||
@@ -165,17 +288,18 @@ const TeamDetailsWrapper = ({
|
||||
})
|
||||
.catch(() => null);
|
||||
toggleDeleteTeamModal();
|
||||
}, [dispatch, toggleDeleteTeamModal, team?.id]);
|
||||
}, [dispatch, toggleDeleteTeamModal, currentTeam?.id]);
|
||||
|
||||
const onEditSubmit = useCallback(
|
||||
(formData: IEditTeamFormData) => {
|
||||
const updatedAttrs = generateUpdateData(team, formData);
|
||||
const updatedAttrs =
|
||||
currentTeam && generateUpdateData(currentTeam, formData);
|
||||
// no updates, so no need for a request.
|
||||
if (updatedAttrs === null) {
|
||||
toggleEditTeamModal();
|
||||
return;
|
||||
}
|
||||
dispatch(teamActions.update(team?.id, updatedAttrs))
|
||||
dispatch(teamActions.update(currentTeam?.id, updatedAttrs))
|
||||
.then(() => {
|
||||
dispatch(teamActions.loadAll({ perPage: 500 }));
|
||||
dispatch(renderFlash("success", "Team updated"));
|
||||
@@ -184,7 +308,7 @@ const TeamDetailsWrapper = ({
|
||||
.catch(() => null);
|
||||
toggleEditTeamModal();
|
||||
},
|
||||
[dispatch, toggleEditTeamModal, team]
|
||||
[dispatch, toggleEditTeamModal, currentTeam]
|
||||
);
|
||||
|
||||
const handleTeamSelect = (teamId: number) => {
|
||||
@@ -220,14 +344,16 @@ const TeamDetailsWrapper = ({
|
||||
"team-settings": !isOnGlobalTeam,
|
||||
});
|
||||
|
||||
if (isLoadingTeams || team === undefined) {
|
||||
if (isLoadingTeams || isTeamSecretsLoading || currentTeam === undefined) {
|
||||
return (
|
||||
<div className={`${baseClass}__loading-spinner`}>
|
||||
<Spinner />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
const hostsCount = team.host_count;
|
||||
|
||||
// const hostsCount = currentTeam.host_count;
|
||||
const hostsCount = teams?.length || 1;
|
||||
const hostsTotalDisplay = hostsCount === 1 ? "1 host" : `${hostsCount} hosts`;
|
||||
const userAdminTeams = userTeams.filter(
|
||||
(thisTeam) => thisTeam.role === "admin"
|
||||
@@ -247,8 +373,8 @@ const TeamDetailsWrapper = ({
|
||||
</>
|
||||
<div className={`${baseClass}__team-header`}>
|
||||
<div className={`${baseClass}__team-details`}>
|
||||
{adminTeams.length === 1 ? (
|
||||
<h1>{team.name}</h1>
|
||||
{adminTeams?.length === 1 ? (
|
||||
<h1>{currentTeam.name}</h1>
|
||||
) : (
|
||||
<TeamsDropdown
|
||||
selectedTeamId={toNumber(routeParams.team_id)}
|
||||
@@ -267,18 +393,27 @@ const TeamDetailsWrapper = ({
|
||||
</span>
|
||||
</div>
|
||||
<div className={`${baseClass}__team-actions`}>
|
||||
<Button onClick={toggleAddHostsRedirectModal}>Add hosts</Button>
|
||||
<Button onClick={toggleGenerateInstallerModal}>
|
||||
Generate installer
|
||||
</Button>
|
||||
<Button
|
||||
onClick={toggleManageEnrollSecretsModal}
|
||||
variant={"text-icon"}
|
||||
>
|
||||
<>
|
||||
Manage enroll secrets{" "}
|
||||
<img src={EyeIcon} alt="Manage enroll secrets icon" />
|
||||
</>
|
||||
</Button>
|
||||
<Button onClick={toggleEditTeamModal} variant={"text-icon"}>
|
||||
<>
|
||||
<img src={PencilIcon} alt="Edit team icon" />
|
||||
Edit team
|
||||
Edit team <img src={PencilIcon} alt="Edit team icon" />
|
||||
</>
|
||||
</Button>
|
||||
{isGlobalAdmin && (
|
||||
<Button onClick={toggleDeleteTeamModal} variant={"text-icon"}>
|
||||
<>
|
||||
<img src={TrashIcon} alt="Delete team icon" />
|
||||
Delete team
|
||||
Delete team <img src={TrashIcon} alt="Delete team icon" />
|
||||
</>
|
||||
</Button>
|
||||
)}
|
||||
@@ -301,26 +436,56 @@ const TeamDetailsWrapper = ({
|
||||
</TabList>
|
||||
</Tabs>
|
||||
</TabsWrapper>
|
||||
{showAddHostsRedirectModal ? (
|
||||
<AddHostsRedirectModal
|
||||
onCancel={toggleAddHostsRedirectModal}
|
||||
onSubmit={onAddHostsRedirectClick}
|
||||
{showGenerateInstallerModal && (
|
||||
<GenerateInstallerModal
|
||||
onCancel={toggleGenerateInstallerModal}
|
||||
selectedTeam={{
|
||||
name: currentTeam.name,
|
||||
secrets: teamSecrets || null,
|
||||
}}
|
||||
/>
|
||||
) : null}
|
||||
{showDeleteTeamModal ? (
|
||||
)}
|
||||
{showManageEnrollSecretsModal && (
|
||||
<EnrollSecretModal
|
||||
selectedTeam={routeParams.team_id}
|
||||
teams={teams || []}
|
||||
onReturnToApp={toggleManageEnrollSecretsModal}
|
||||
toggleSecretEditorModal={toggleSecretEditorModal}
|
||||
toggleDeleteSecretModal={toggleDeleteSecretModal}
|
||||
setSelectedSecret={setSelectedSecret}
|
||||
/>
|
||||
)}
|
||||
{showSecretEditorModal && (
|
||||
<SecretEditorModal
|
||||
selectedTeam={routeParams.team_id}
|
||||
teams={teams || []}
|
||||
onSaveSecret={onSaveSecret}
|
||||
toggleSecretEditorModal={toggleSecretEditorModal}
|
||||
selectedSecret={selectedSecret}
|
||||
/>
|
||||
)}
|
||||
{showDeleteSecretModal && (
|
||||
<DeleteSecretModal
|
||||
onDeleteSecret={onDeleteSecret}
|
||||
selectedTeam={routeParams.team_id}
|
||||
teams={teams || []}
|
||||
toggleDeleteSecretModal={toggleDeleteSecretModal}
|
||||
/>
|
||||
)}
|
||||
{showDeleteTeamModal && (
|
||||
<DeleteTeamModal
|
||||
onCancel={toggleDeleteTeamModal}
|
||||
onSubmit={onDeleteSubmit}
|
||||
name={team.name}
|
||||
name={currentTeam.name}
|
||||
/>
|
||||
) : null}
|
||||
{showEditTeamModal ? (
|
||||
)}
|
||||
{showEditTeamModal && (
|
||||
<EditTeamModal
|
||||
onCancel={toggleEditTeamModal}
|
||||
onSubmit={onEditSubmit}
|
||||
defaultName={team.name}
|
||||
defaultName={currentTeam.name}
|
||||
/>
|
||||
) : null}
|
||||
)}
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -51,7 +51,7 @@
|
||||
display: flex;
|
||||
|
||||
button {
|
||||
margin-left: $pad-small;
|
||||
margin-left: $pad-medium;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
-45
@@ -1,45 +0,0 @@
|
||||
import React from "react";
|
||||
import Button from "components/buttons/Button";
|
||||
import Modal from "components/Modal";
|
||||
|
||||
interface IAddHostsModalProps {
|
||||
onCancel: () => void;
|
||||
onSubmit: () => void;
|
||||
}
|
||||
|
||||
const baseClass = "add-hosts-redirect-modal";
|
||||
|
||||
const AddHostsRedirectModal = ({
|
||||
onCancel,
|
||||
onSubmit,
|
||||
}: IAddHostsModalProps): JSX.Element => {
|
||||
return (
|
||||
<Modal title={"Add hosts"} onExit={onCancel} className={baseClass}>
|
||||
<div className={`${baseClass}__modal-body`}>
|
||||
<p>
|
||||
Head to the Hosts page to transfer hosts that are already enrolled to
|
||||
Fleet or enroll new hosts.
|
||||
</p>
|
||||
<div className={`${baseClass}__btn-wrap`}>
|
||||
<Button
|
||||
className={`${baseClass}__btn`}
|
||||
type="button"
|
||||
variant="brand"
|
||||
onClick={onSubmit}
|
||||
>
|
||||
Go to Hosts page
|
||||
</Button>
|
||||
<Button
|
||||
className={`${baseClass}__btn`}
|
||||
onClick={onCancel}
|
||||
variant="inverse"
|
||||
>
|
||||
Cancel
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</Modal>
|
||||
);
|
||||
};
|
||||
|
||||
export default AddHostsRedirectModal;
|
||||
-11
@@ -1,11 +0,0 @@
|
||||
.add-hosts-redirect-modal {
|
||||
&__btn-wrap {
|
||||
display: flex;
|
||||
flex-direction: row-reverse;
|
||||
margin-top: $pad-xxlarge;
|
||||
}
|
||||
|
||||
&__btn {
|
||||
margin-left: 12px;
|
||||
}
|
||||
}
|
||||
-1
@@ -1 +0,0 @@
|
||||
export { default } from "./AddHostsRedirectModal";
|
||||
@@ -74,9 +74,10 @@ import {
|
||||
getNextLocationPath,
|
||||
} from "./helpers";
|
||||
|
||||
import DeleteSecretModal from "./components/DeleteSecretModal";
|
||||
import SecretEditorModal from "./components/SecretEditorModal";
|
||||
import EnrollSecretModal from "./components/EnrollSecretModal";
|
||||
import DeleteSecretModal from "../../../components/DeleteSecretModal";
|
||||
import SecretEditorModal from "../../../components/SecretEditorModal";
|
||||
import GenerateInstallerModal from "../../../components/GenerateInstallerModal";
|
||||
import EnrollSecretModal from "../../../components/EnrollSecretModal";
|
||||
// @ts-ignore
|
||||
import NoHosts from "./components/NoHosts";
|
||||
import EmptyHosts from "./components/EmptyHosts";
|
||||
@@ -86,8 +87,6 @@ import EditColumnsModal from "./components/EditColumnsModal/EditColumnsModal";
|
||||
import TransferHostModal from "./components/TransferHostModal";
|
||||
import DeleteHostModal from "./components/DeleteHostModal";
|
||||
import SoftwareVulnerabilities from "./components/SoftwareVulnerabilities";
|
||||
// @ts-ignore
|
||||
import GenerateInstallerModal from "./components/GenerateInstallerModal";
|
||||
import EditColumnsIcon from "../../../../assets/images/icon-edit-columns-16x16@2x.png";
|
||||
import PencilIcon from "../../../../assets/images/icon-pencil-14x14@2x.png";
|
||||
import TrashIcon from "../../../../assets/images/icon-trash-14x14@2x.png";
|
||||
@@ -1186,21 +1185,15 @@ const ManageHostsPage = ({
|
||||
}
|
||||
|
||||
return (
|
||||
<Modal
|
||||
title="Enroll secret"
|
||||
onExit={() => setShowEnrollSecretModal(false)}
|
||||
className={`${baseClass}__enroll-secret-modal`}
|
||||
>
|
||||
<EnrollSecretModal
|
||||
selectedTeam={currentTeam?.id || 0}
|
||||
teams={teams || []}
|
||||
onReturnToApp={() => setShowEnrollSecretModal(false)}
|
||||
toggleSecretEditorModal={toggleSecretEditorModal}
|
||||
toggleDeleteSecretModal={toggleDeleteSecretModal}
|
||||
setSelectedSecret={setSelectedSecret}
|
||||
globalSecrets={globalSecrets}
|
||||
/>
|
||||
</Modal>
|
||||
<EnrollSecretModal
|
||||
selectedTeam={currentTeam?.id || 0}
|
||||
teams={teams || []}
|
||||
onReturnToApp={() => setShowEnrollSecretModal(false)}
|
||||
toggleSecretEditorModal={toggleSecretEditorModal}
|
||||
toggleDeleteSecretModal={toggleDeleteSecretModal}
|
||||
setSelectedSecret={setSelectedSecret}
|
||||
globalSecrets={globalSecrets}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1529,28 +1522,30 @@ const ManageHostsPage = ({
|
||||
!isGlobalSecretsLoading &&
|
||||
!globalSecrets?.length;
|
||||
|
||||
return ((canEnrollHosts && noTeamEnrollSecrets) ||
|
||||
(canEnrollGlobalHosts && noGlobalEnrollSecrets)) &&
|
||||
showNoEnrollSecretBanner ? (
|
||||
<div className={`${baseClass}__no-enroll-secret-banner`}>
|
||||
<div>
|
||||
<span>
|
||||
You have no enroll secrets. Manage enroll secrets to enroll hosts to{" "}
|
||||
<b>{currentTeam?.id ? currentTeam.name : "Fleet"}</b>.
|
||||
</span>
|
||||
return (
|
||||
((canEnrollHosts && noTeamEnrollSecrets) ||
|
||||
(canEnrollGlobalHosts && noGlobalEnrollSecrets)) &&
|
||||
showNoEnrollSecretBanner && (
|
||||
<div className={`${baseClass}__no-enroll-secret-banner`}>
|
||||
<div>
|
||||
<span>
|
||||
You have no enroll secrets. Manage enroll secrets to enroll hosts
|
||||
to <b>{currentTeam?.id ? currentTeam.name : "Fleet"}</b>.
|
||||
</span>
|
||||
</div>
|
||||
<div className={`dismiss-banner-button`}>
|
||||
<button
|
||||
className="button button--unstyled"
|
||||
onClick={() =>
|
||||
setShowNoEnrollSecretBanner(!showNoEnrollSecretBanner)
|
||||
}
|
||||
>
|
||||
<img alt="Dismiss no enroll secret banner" src={CloseIconBlack} />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div className={`dismiss-banner-button`}>
|
||||
<button
|
||||
className="button button--unstyled"
|
||||
onClick={() =>
|
||||
setShowNoEnrollSecretBanner(!showNoEnrollSecretBanner)
|
||||
}
|
||||
>
|
||||
<img alt="Dismiss no enroll secret banner" src={CloseIconBlack} />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
) : null;
|
||||
)
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
|
||||
Reference in New Issue
Block a user