import _ from 'lodash'; import ApiHelpers from './util/ApiHelpers.jsx'; import { Link } from 'react-router-dom'; import logo from './../../img/logo-only.svg'; import PropTypes from 'prop-types'; import React from 'react'; import ReactRouterPropTypes from 'react-router-prop-types'; import SocialLinks from './SocialLinks.jsx'; import Version from './Version.jsx'; import { withContext } from './util/AppContext.jsx'; import wordLogo from './../../img/word-logo.svg'; import { Icon, Layout, Menu } from 'antd'; import './../../css/sidebar.css'; class Sidebar extends React.Component { static defaultProps = { productName: 'controller' } static propTypes = { api: PropTypes.shape({ PrefixedLink: PropTypes.func.isRequired, }).isRequired, location: ReactRouterPropTypes.location.isRequired, pathPrefix: PropTypes.string.isRequired, productName: PropTypes.string, releaseVersion: PropTypes.string.isRequired, uuid: PropTypes.string.isRequired, } constructor(props) { super(props); this.api= this.props.api; this.toggleCollapse = this.toggleCollapse.bind(this); this.loadFromServer = this.loadFromServer.bind(this); this.handleApiError = this.handleApiError.bind(this); this.state = this.getInitialState(); } getInitialState() { return { pollingInterval: 12000, maxNsItemsToShow: 8, initialCollapse: true, collapsed: true, error: null, latestVersion: '', isLatest: true, pendingRequests: false }; } componentDidMount() { this.startServerPolling(); } componentWillUnmount() { // the Sidebar never unmounts, but if something ever does, we should take care of it this.stopServerPolling(); } startServerPolling() { this.loadFromServer(); this.timerId = window.setInterval(this.loadFromServer, this.state.pollingInterval); } stopServerPolling() { window.clearInterval(this.timerId); this.api.cancelCurrentRequests(); } loadFromServer() { if (this.state.pendingRequests) { return; // don't make more requests if the ones we sent haven't completed } this.setState({ pendingRequests: true }); let versionUrl = `https://versioncheck.conduit.io/version.json?version=${this.props.releaseVersion}?uuid=${this.props.uuid}`; this.api.setCurrentRequests([ ApiHelpers("").fetch(versionUrl), this.api.fetchMetrics(this.api.urlsForResource("namespace")) ]); // expose serverPromise for testing this.serverPromise = Promise.all(this.api.getCurrentPromises()) .then(([versionRsp, nsRsp]) => { let nsStats = _.get(nsRsp, ["ok", "statTables", 0, "podGroup", "rows"], []); let namespaces = _(nsStats).map(r => r.resource.name).sortBy().value(); this.setState({ latestVersion: versionRsp.version, isLatest: versionRsp.version === this.props.releaseVersion, namespaces, pendingRequests: false, }); }).catch(this.handleApiError); } handleApiError(e) { this.setState({ pendingRequests: false, error: e }); } toggleCollapse() { if (this.state.initialCollapse) { // fix weird situation where toggleCollapsed is called on pageload, // causing the toggle states to be inconsistent. Don't toggle on the // very first call to toggleCollapse() this.setState({ initialCollapse: false}); } else { this.setState({ collapsed: !this.state.collapsed }); } } render() { let normalizedPath = this.props.location.pathname.replace(this.props.pathPrefix, ""); let PrefixedLink = this.api.PrefixedLink; let numHiddenNamespaces = _.size(this.state.namespaces) - this.state.maxNsItemsToShow; return (
Linkerd logo { // awful hack to deal with the fact that we don't serve assets off absolute paths e.target.src = e.target.src.replace(/(.*)(\/[a-zA-Z]*)(\/dist)(.*)/, "$1$3$4"); }} />
Service mesh Namespaces { _.map(_.take(this.state.namespaces, this.state.maxNsItemsToShow), ns => { return ( {this.state.collapsed ? _.take(ns, 2) :    } {ns} {this.state.collapsed ? "namespace" : ""} ); }) } { // if we're hiding some namespaces, show a count numHiddenNamespaces > 0 ? {this.state.collapsed ? ... :    } {numHiddenNamespaces} more namespace{numHiddenNamespaces === 1 ? "" : "s"} : null } {this.state.collapsed ? "" : "Resources"}}> Authorities Deployments Pods Replication Controllers Documentation { this.state.isLatest ? null : ( Update {this.props.productName} )} { this.state.collapsed ? null : (
)}
); } } export default withContext(Sidebar);