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/flash_messages/FlashMessage"; import PersistentFlash from "components/flash_messages/PersistentFlash"; import SiteTopNav from "components/side_panels/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 you’d like to renew or have questions about downgrading,{" "} please head to the Fleet documentation . ); export class CoreLayout extends Component { static propTypes = { children: PropTypes.node, config: configInterface, dispatch: PropTypes.func, user: userInterface, fullWidthFlash: PropTypes.bool, notifications: notificationInterface, persistentFlash: PropTypes.shape({ showFlash: PropTypes.bool.isRequired, message: PropTypes.string.isRequired, }).isRequired, 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, persistentFlash, 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 (
{persistentFlash.showFlash && ( )} {isPremiumTier && showExpirationFlashMessage && ( )} {children}
); } } const mapStateToProps = (state) => { const { app: { config }, auth: { user }, notifications, persistentFlash, } = state; const isPremiumTier = permissionUtils.isPremiumTier(state.app.config); const fullWidthFlash = !user; return { config, fullWidthFlash, notifications, persistentFlash, user, isPremiumTier, }; }; export default connect(mapStateToProps)(CoreLayout);