mirror of
https://github.com/fleetdm/fleet
synced 2026-05-24 09:28:54 +00:00
## #22661  - Update `FlashMessage` behavior to, by default, hide itself when the user performs any URL-changing navigation - Add `persistOnPageChange` option to `renderFlash` API and associated notification context and reducer logic, allowing override of this behavior on a per-call basis - Ensure proper order of evaluation of URL changes and render flash action dispatches on the event loop - Clean up legacy unused "undo"-related arguments and logic - Allow the user to click in the same horizontal dimension as a flash message - Other misc. cleanup and refactoring [Demo - messages hidden on page (any URL) change](https://www.loom.com/share/1e884b6ba11c4b59bc74f51df3690131?sid=9b53e78b-6535-4541-b676-377760366cf4) - [x] Changes file added for user-visible changes in `changes/`, - [x] Manual QA for all new/changed functionality --------- Co-authored-by: Jacob Shandling <jacob@fleetdm.com>
98 lines
2.6 KiB
TypeScript
98 lines
2.6 KiB
TypeScript
import React, { useContext } from "react";
|
|
import { InjectedRouter } from "react-router";
|
|
|
|
import UnsupportedScreenSize from "layouts/UnsupportedScreenSize";
|
|
|
|
import { AppContext } from "context/app";
|
|
import { NotificationContext } from "context/notification";
|
|
import { TableContext } from "context/table";
|
|
|
|
import paths from "router/paths";
|
|
import useDeepEffect from "hooks/useDeepEffect";
|
|
import FlashMessage from "components/FlashMessage";
|
|
import SiteTopNav from "components/top_nav/SiteTopNav";
|
|
import { QueryParams } from "utilities/url";
|
|
|
|
interface ICoreLayoutProps {
|
|
children: React.ReactNode;
|
|
router: InjectedRouter; // v3
|
|
// TODO: standardize typing and usage of location across app components
|
|
location: {
|
|
pathname: string;
|
|
search: string;
|
|
hash?: string;
|
|
query: QueryParams;
|
|
};
|
|
}
|
|
|
|
const CoreLayout = ({ children, router, location }: ICoreLayoutProps) => {
|
|
const { config, currentUser } = useContext(AppContext);
|
|
const { notification, hideFlash } = useContext(NotificationContext);
|
|
const { setResetSelectedRows } = useContext(TableContext);
|
|
|
|
// 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);
|
|
}
|
|
}, [notification]);
|
|
|
|
const onLogoutUser = async () => {
|
|
const { LOGOUT } = paths;
|
|
router.push(LOGOUT);
|
|
};
|
|
|
|
const onUserMenuItemClick = (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 fullWidthFlash = !currentUser;
|
|
|
|
if (!currentUser || !config) {
|
|
return null;
|
|
}
|
|
|
|
return (
|
|
<div className="app-wrap">
|
|
<UnsupportedScreenSize />
|
|
<nav className="site-nav-container">
|
|
<SiteTopNav
|
|
config={config}
|
|
currentUser={currentUser}
|
|
location={location}
|
|
onLogoutUser={onLogoutUser}
|
|
onUserMenuItemClick={onUserMenuItemClick}
|
|
/>
|
|
</nav>
|
|
<div className="core-wrapper">
|
|
<FlashMessage
|
|
fullWidth={fullWidthFlash}
|
|
notification={notification}
|
|
onRemoveFlash={hideFlash}
|
|
pathname={location.pathname}
|
|
/>
|
|
|
|
{children}
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default CoreLayout;
|