fleet/frontend/layouts/CoreLayout/CoreLayout.jsx
2022-02-02 11:27:14 -06:00

212 lines
5 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import React, { Component } from "react";
import PropTypes from "prop-types";
import { connect } from "react-redux";
import { logoutUser } from "redux/nodes/auth/actions";
import { push } from "react-router-redux";
import { TableContext } from "context/table";
import { isEqual } from "lodash";
import permissionUtils from "utilities/permissions";
import configInterface from "interfaces/config";
import FlashMessage from "components/FlashMessage";
import SiteTopNav from "components/top_nav/SiteTopNav";
import userInterface from "interfaces/user";
import notificationInterface from "interfaces/notification";
import { hideFlash } from "redux/nodes/notifications/actions";
import { licenseExpirationWarning } from "fleet/helpers";
const expirationMessage = (
<>
Your license for Fleet Premium is about to expire. If youd like to renew or
have questions about downgrading,{" "}
<a
href="https://fleetdm.com/docs/using-fleet/faq#how-do-i-downgrade-from-fleet-premium-to-fleet-free"
target="_blank"
rel="noopener noreferrer"
>
please head to the Fleet documentation
</a>
.
</>
);
export class CoreLayout extends Component {
static propTypes = {
children: PropTypes.node,
config: configInterface,
dispatch: PropTypes.func,
user: userInterface,
fullWidthFlash: PropTypes.bool,
notifications: notificationInterface,
isPremiumTier: PropTypes.bool,
};
constructor(props) {
super(props);
this.state = {
showExpirationFlashMessage: false,
};
}
componentWillReceiveProps(nextProps) {
const { notifications, config } = nextProps;
const table = this.context;
// 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)
if (!isEqual(this.props.notifications, notifications)) {
if (notifications.alertType === "success") {
setTimeout(() => {
table.setResetSelectedRows(true);
setTimeout(() => {
table.setResetSelectedRows(false);
}, 300);
}, 0);
}
}
this.setState({
showExpirationFlashMessage: licenseExpirationWarning(config.expiration),
});
}
onLogoutUser = () => {
const { dispatch } = this.props;
dispatch(logoutUser());
return false;
};
onNavItemClick = (path) => {
return (evt) => {
evt.preventDefault();
const { dispatch } = this.props;
if (path.indexOf("http") !== -1) {
global.window.open(path, "_blank");
return false;
}
dispatch(push(path));
return false;
};
};
onRemoveFlash = () => {
const { dispatch } = this.props;
dispatch(hideFlash);
return false;
};
onRemoveExpirationWarning = () => {
const { showExpirationFlashMessage } = this.state;
this.setState({
showExpirationFlashMessage: !showExpirationFlashMessage,
});
};
onUndoActionClick = (undoAction) => {
return (evt) => {
evt.preventDefault();
const { dispatch } = this.props;
const { onRemoveFlash } = this;
dispatch(undoAction);
return onRemoveFlash();
};
};
static contextType = TableContext;
render() {
const {
fullWidthFlash,
notifications,
children,
config,
user,
isPremiumTier,
} = this.props;
const { showExpirationFlashMessage } = this.state;
const {
onRemoveFlash,
onRemoveExpirationWarning,
onUndoActionClick,
} = this;
const expirationNotification = {
alertType: "warning-filled",
isVisible: true,
message: expirationMessage,
};
if (!user) return false;
const { onLogoutUser, onNavItemClick } = this;
const { pathname } = global.window.location;
return (
<div className="app-wrap">
<nav className="site-nav">
<SiteTopNav
config={config}
onLogoutUser={onLogoutUser}
onNavItemClick={onNavItemClick}
pathname={pathname}
currentUser={user}
/>
</nav>
<div className="core-wrapper">
{isPremiumTier && showExpirationFlashMessage && (
<FlashMessage
fullWidth={fullWidthFlash}
notification={expirationNotification}
onRemoveFlash={onRemoveExpirationWarning}
/>
)}
<FlashMessage
fullWidth={fullWidthFlash}
notification={notifications}
onRemoveFlash={onRemoveFlash}
onUndoActionClick={onUndoActionClick}
/>
{children}
</div>
</div>
);
}
}
const mapStateToProps = (state) => {
const {
app: { config },
auth: { user },
notifications,
} = state;
const isPremiumTier = permissionUtils.isPremiumTier(state.app.config);
const fullWidthFlash = !user;
return {
config,
fullWidthFlash,
notifications,
user,
isPremiumTier,
};
};
export default connect(mapStateToProps)(CoreLayout);