2022-04-01 06:42:26 +00:00
|
|
|
|
import React, { useState, useContext } from "react";
|
|
|
|
|
|
import { InjectedRouter } from "react-router";
|
2023-03-31 17:40:14 +00:00
|
|
|
|
import { Params } from "react-router/lib/Router";
|
|
|
|
|
|
|
2022-04-01 06:42:26 +00:00
|
|
|
|
import { AppContext } from "context/app";
|
|
|
|
|
|
import { NotificationContext } from "context/notification";
|
|
|
|
|
|
import { TableContext } from "context/table";
|
|
|
|
|
|
|
2022-04-07 16:08:00 +00:00
|
|
|
|
import paths from "router/paths";
|
2022-04-22 16:45:35 +00:00
|
|
|
|
import useDeepEffect from "hooks/useDeepEffect";
|
2022-04-01 06:42:26 +00:00
|
|
|
|
import FlashMessage from "components/FlashMessage";
|
|
|
|
|
|
import SiteTopNav from "components/top_nav/SiteTopNav";
|
2022-10-27 18:06:57 +00:00
|
|
|
|
import CustomLink from "components/CustomLink";
|
2022-04-01 06:42:26 +00:00
|
|
|
|
import { INotification } from "interfaces/notification";
|
2022-04-22 16:45:35 +00:00
|
|
|
|
import { licenseExpirationWarning } from "utilities/helpers";
|
2023-03-31 17:40:14 +00:00
|
|
|
|
import { QueryParams } from "utilities/url";
|
2022-04-01 06:42:26 +00:00
|
|
|
|
|
2022-08-03 13:12:07 +00:00
|
|
|
|
import smallScreenImage from "../../../assets/images/small-screen-160x80@2x.png";
|
|
|
|
|
|
|
2022-04-01 06:42:26 +00:00
|
|
|
|
interface ICoreLayoutProps {
|
|
|
|
|
|
children: React.ReactNode;
|
|
|
|
|
|
router: InjectedRouter; // v3
|
2023-03-31 17:40:14 +00:00
|
|
|
|
// TODO: standardize typing and usage of location across app components
|
|
|
|
|
|
location: {
|
|
|
|
|
|
pathname: string;
|
|
|
|
|
|
search: string;
|
|
|
|
|
|
hash?: string;
|
|
|
|
|
|
query: QueryParams;
|
|
|
|
|
|
};
|
|
|
|
|
|
params: Params;
|
2022-04-01 06:42:26 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const expirationMessage = (
|
|
|
|
|
|
<>
|
|
|
|
|
|
Your license for Fleet Premium is about to expire. If you’d like to renew or
|
|
|
|
|
|
have questions about downgrading,{" "}
|
2022-10-27 18:06:57 +00:00
|
|
|
|
<CustomLink
|
|
|
|
|
|
url="https://fleetdm.com/docs/using-fleet/faq#how-do-i-downgrade-from-fleet-premium-to-fleet-free"
|
|
|
|
|
|
text="please head to the Fleet documentation"
|
|
|
|
|
|
newTab
|
|
|
|
|
|
multiline
|
|
|
|
|
|
/>
|
2022-04-01 06:42:26 +00:00
|
|
|
|
</>
|
|
|
|
|
|
);
|
|
|
|
|
|
|
2023-03-31 17:40:14 +00:00
|
|
|
|
const CoreLayout = ({
|
|
|
|
|
|
children,
|
|
|
|
|
|
router,
|
|
|
|
|
|
location,
|
|
|
|
|
|
params: routeParams,
|
|
|
|
|
|
}: ICoreLayoutProps) => {
|
2022-04-01 06:42:26 +00:00
|
|
|
|
const { config, currentUser, isPremiumTier } = useContext(AppContext);
|
2022-04-07 16:08:00 +00:00
|
|
|
|
const { notification, hideFlash } = useContext(NotificationContext);
|
2022-04-01 06:42:26 +00:00
|
|
|
|
const { setResetSelectedRows } = useContext(TableContext);
|
2022-09-01 15:28:02 +00:00
|
|
|
|
const [showExpirationFlashMessage, setShowExpirationFlashMessage] = useState(
|
|
|
|
|
|
false
|
|
|
|
|
|
);
|
2022-04-01 06:42:26 +00:00
|
|
|
|
|
|
|
|
|
|
// on success of an action, the table will reset its checkboxes.
|
|
|
|
|
|
// setTimeout is to help with race conditions as table reloads
|
|
|
|
|
|
// in some instances (i.e. Manage Hosts)
|
|
|
|
|
|
useDeepEffect(() => {
|
|
|
|
|
|
if (notification?.alertType === "success") {
|
|
|
|
|
|
setTimeout(() => {
|
|
|
|
|
|
setResetSelectedRows(true);
|
|
|
|
|
|
setTimeout(() => {
|
|
|
|
|
|
setResetSelectedRows(false);
|
|
|
|
|
|
}, 300);
|
|
|
|
|
|
}, 0);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
setShowExpirationFlashMessage(
|
2022-04-07 16:08:00 +00:00
|
|
|
|
licenseExpirationWarning(config?.license.expiration || "")
|
2022-04-01 06:42:26 +00:00
|
|
|
|
);
|
|
|
|
|
|
}, [notification]);
|
|
|
|
|
|
|
|
|
|
|
|
const onLogoutUser = async () => {
|
2022-04-07 16:08:00 +00:00
|
|
|
|
const { LOGOUT } = paths;
|
|
|
|
|
|
router.push(LOGOUT);
|
2022-04-01 06:42:26 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
const onNavItemClick = (path: string) => {
|
|
|
|
|
|
return (evt: React.MouseEvent<HTMLButtonElement>) => {
|
|
|
|
|
|
evt.preventDefault();
|
|
|
|
|
|
|
|
|
|
|
|
if (path.indexOf("http") !== -1) {
|
|
|
|
|
|
global.window.open(path, "_blank");
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
router.push(path);
|
|
|
|
|
|
return false;
|
|
|
|
|
|
};
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
const onUndoActionClick = (undoAction?: () => void) => {
|
|
|
|
|
|
return (evt: React.MouseEvent<HTMLButtonElement>) => {
|
|
|
|
|
|
evt.preventDefault();
|
|
|
|
|
|
|
|
|
|
|
|
if (undoAction) {
|
|
|
|
|
|
undoAction();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
hideFlash();
|
|
|
|
|
|
};
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
const fullWidthFlash = !currentUser;
|
|
|
|
|
|
const expirationNotification: INotification = {
|
|
|
|
|
|
alertType: "warning-filled",
|
|
|
|
|
|
isVisible: true,
|
|
|
|
|
|
message: expirationMessage,
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
if (!currentUser || !config) {
|
|
|
|
|
|
return null;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
|
<div className="app-wrap">
|
2022-08-03 13:12:07 +00:00
|
|
|
|
<div className="overlay">
|
|
|
|
|
|
<img src={smallScreenImage} alt="Unsupported screen size" />
|
|
|
|
|
|
<div className="overlay__text">
|
|
|
|
|
|
<h1>This screen size is not supported yet.</h1>
|
|
|
|
|
|
<p>Please enlarge your browser or try again on a computer.</p>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
2023-01-26 19:33:54 +00:00
|
|
|
|
<nav className="site-nav-container">
|
2022-04-01 06:42:26 +00:00
|
|
|
|
<SiteTopNav
|
|
|
|
|
|
config={config}
|
2023-03-31 17:40:14 +00:00
|
|
|
|
currentUser={currentUser}
|
|
|
|
|
|
location={location}
|
2022-04-01 06:42:26 +00:00
|
|
|
|
onLogoutUser={onLogoutUser}
|
|
|
|
|
|
onNavItemClick={onNavItemClick}
|
|
|
|
|
|
/>
|
|
|
|
|
|
</nav>
|
|
|
|
|
|
<div className="core-wrapper">
|
|
|
|
|
|
{isPremiumTier && showExpirationFlashMessage && (
|
|
|
|
|
|
<FlashMessage
|
|
|
|
|
|
fullWidth={fullWidthFlash}
|
|
|
|
|
|
notification={expirationNotification}
|
|
|
|
|
|
onRemoveFlash={() =>
|
|
|
|
|
|
setShowExpirationFlashMessage(!showExpirationFlashMessage)
|
|
|
|
|
|
}
|
|
|
|
|
|
/>
|
|
|
|
|
|
)}
|
|
|
|
|
|
<FlashMessage
|
|
|
|
|
|
fullWidth={fullWidthFlash}
|
|
|
|
|
|
notification={notification}
|
|
|
|
|
|
onRemoveFlash={hideFlash}
|
|
|
|
|
|
onUndoActionClick={onUndoActionClick}
|
|
|
|
|
|
/>
|
|
|
|
|
|
{children}
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
);
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
export default CoreLayout;
|