import { githubIcon, linkerdWordLogo, slackIcon } from './util/SvgWrappers.jsx'; import AppBar from '@material-ui/core/AppBar'; import BreadcrumbHeader from './BreadcrumbHeader.jsx'; import BuildIcon from '@material-ui/icons/Build'; import ChevronLeftIcon from '@material-ui/icons/ChevronLeft'; import CloudQueueIcon from '@material-ui/icons/CloudQueue'; import Divider from '@material-ui/core/Divider'; import Drawer from '@material-ui/core/Drawer'; import EmailIcon from '@material-ui/icons/Email'; import HomeIcon from '@material-ui/icons/Home'; import Icon from '@material-ui/core/Icon'; import IconButton from '@material-ui/core/IconButton'; import LibraryBooksIcon from '@material-ui/icons/LibraryBooks'; import { Link } from 'react-router-dom'; import ListItem from '@material-ui/core/ListItem'; import ListItemIcon from '@material-ui/core/ListItemIcon'; import ListItemText from '@material-ui/core/ListItemText'; import MenuIcon from '@material-ui/icons/Menu'; import MenuItem from '@material-ui/core/MenuItem'; import MenuList from '@material-ui/core/MenuList'; import NavigationResources from './NavigationResources.jsx'; import PropTypes from 'prop-types'; import React from 'react'; import ReactRouterPropTypes from 'react-router-prop-types'; import Toolbar from '@material-ui/core/Toolbar'; import Typography from '@material-ui/core/Typography'; import Version from './Version.jsx'; import classNames from 'classnames'; import { withContext } from './util/AppContext.jsx'; import { withStyles } from '@material-ui/core/styles'; const styles = theme => { const drawerWidth = theme.spacing.unit * 31; const drawerWidthClosed = theme.spacing.unit * 9; const navLogoWidth = theme.spacing.unit * 22.5; const contentPadding = theme.spacing.unit * 3; const enteringFn = prop => theme.transitions.create(prop, { easing: theme.transitions.easing.sharp, duration: theme.transitions.duration.enteringScreen, }); const leavingFn = prop => theme.transitions.create(prop, { easing: theme.transitions.easing.sharp, duration: theme.transitions.duration.leavingScreen, }); const entering = enteringFn('width'); const leaving = leavingFn('width'); return { root: { display: 'flex', }, appBar: { position: "absolute", width: `calc(100% - ${drawerWidthClosed}px)`, color: 'white', transition: leaving, }, appBarShift: { width: `calc(100% - ${drawerWidth}px)`, transition: entering, }, drawer: { width: drawerWidth, transition: entering, }, drawerClose: { width: drawerWidthClosed, transition: leaving, }, drawerPaper: { overflowX: 'hidden', whiteSpace: 'nowrap', width: drawerWidth, transition: entering, }, drawerPaperClose: { transition: leaving, width: drawerWidthClosed, [theme.breakpoints.up('sm')]: { width: drawerWidthClosed, }, }, toolbar: theme.mixins.toolbar, navToolbar: { display: 'flex', alignItems: 'center', padding: `0 0 0 ${theme.spacing.unit*2}px`, boxShadow: theme.shadows[4], // to match elevation == 4 on main AppBar ...theme.mixins.toolbar, backgroundColor: theme.palette.primary.main, }, content: { flexGrow: 1, width: `calc(100% - ${drawerWidth}px)`, backgroundColor: theme.palette.background.default, padding: contentPadding, transition: entering, }, contentDrawerClose: { width: `calc(100% - ${drawerWidthClosed}px)`, transition: leaving, }, linkerdNavLogo: { minWidth: `${navLogoWidth}px`, transition: enteringFn(['margin', 'opacity']), }, linkerdNavLogoClose: { opacity: "0", marginLeft: `-${navLogoWidth+theme.spacing.unit/2}px`, transition: leavingFn(['margin', 'opacity']), }, navMenuItem: { paddingLeft: `${contentPadding}px`, paddingRight: `${contentPadding}px`, }, helpMenuItem: { outline: "none", }, shrinkIcon: { fontSize: "18px", paddingLeft: "3px", paddingRight: "3px", } }; }; class NavigationBase extends React.Component { constructor(props) { super(props); this.api = this.props.api; this.handleApiError = this.handleApiError.bind(this); this.state = this.getInitialState(); } getInitialState() { return { drawerOpen: true, helpMenuOpen: false, latestVersion: '', isLatest: true, namespaceFilter: "all" }; } componentDidMount() { this.fetchVersion(); } fetchVersion() { let versionUrl = `https://versioncheck.linkerd.io/version.json?version=${this.props.releaseVersion}&uuid=${this.props.uuid}&source=web`; this.versionPromise = fetch(versionUrl, { credentials: 'include' }) .then(rsp => rsp.json()) .then(versionRsp => { let latestVersion; let parts = this.props.releaseVersion.split("-", 2); if (parts.length === 2) { latestVersion = versionRsp[parts[0]]; } this.setState({ latestVersion, isLatest: latestVersion === this.props.releaseVersion }); }).catch(this.handleApiError); } handleApiError(e) { this.setState({ error: e }); } handleDrawerClick = () => { this.setState(state => ({ drawerOpen: !state.drawerOpen })); }; handleHelpMenuClick = () => { this.setState(state => ({ helpMenuOpen: !state.helpMenuOpen })); } menuItem(path, title, icon) { const { classes, api } = this.props; let normalizedPath = this.props.location.pathname.replace(this.props.pathPrefix, ""); let isCurrentPage = path => path === normalizedPath; return ( {icon} ); } render() { const { classes, ChildComponent, ...otherProps } = this.props; return (
{linkerdWordLogo}
{this.state.drawerOpen ? : }
{ this.menuItem("/overview", "Overview", ) } { this.menuItem("/tap", "Tap", ) } { this.menuItem("/top", "Top", ) } { this.menuItem("/routes", "Top Routes", ) } { this.menuItem("/servicemesh", "Service Mesh", ) } { this.menuItem("/debug", "Debug", ) } {slackIcon} {githubIcon} { !this.state.drawerOpen ? null : }
); } } NavigationBase.propTypes = { api: PropTypes.shape({}).isRequired, ChildComponent: PropTypes.func.isRequired, classes: PropTypes.shape({}).isRequired, location: ReactRouterPropTypes.location.isRequired, pathPrefix: PropTypes.string.isRequired, releaseVersion: PropTypes.string.isRequired, theme: PropTypes.shape({}).isRequired, uuid: PropTypes.string.isRequired, }; export default withContext(withStyles(styles, { withTheme: true })(NavigationBase));