import 'whatwg-fetch'; import { handlePageVisibility, withPageVisibility } from './util/PageVisibility.jsx'; import ErrorBanner from './ErrorBanner.jsx'; import MetricsTable from './MetricsTable.jsx'; import NetworkGraph from './NetworkGraph.jsx'; import PropTypes from 'prop-types'; import React from 'react'; import Spinner from './util/Spinner.jsx'; import { Trans } from '@lingui/macro'; import _filter from 'lodash/filter'; import _get from 'lodash/get'; import _isEmpty from 'lodash/isEmpty'; import _isEqual from 'lodash/isEqual'; import { friendlyTitle } from './util/Utils.js'; import { processMultiResourceRollup } from './util/MetricUtils.jsx'; import { withContext } from './util/AppContext.jsx'; class Namespaces extends React.Component { constructor(props) { super(props); this.api = props.api; this.handleApiError = this.handleApiError.bind(this); this.loadFromServer = this.loadFromServer.bind(this); this.state = this.getInitialState(props.match.params); } getInitialState(params) { const ns = _get(params, 'namespace', 'default'); return { ns, pollingInterval: 2000, metrics: {}, pendingRequests: false, loaded: false, error: null, }; } componentDidMount() { this.startServerPolling(); this.checkNamespaceMatch(); } componentDidUpdate(prevProps) { const { match, isPageVisible } = this.props; const { params } = match; if (!_isEqual(prevProps.match.params.namespace, params.namespace)) { // React won't unmount this component when switching resource pages so we need to clear state this.api.cancelCurrentRequests(); this.resetState(params); } handlePageVisibility({ prevVisibilityState: prevProps.isPageVisible, currentVisibilityState: isPageVisible, onVisible: () => this.startServerPolling(), onHidden: () => this.stopServerPolling(), }); } resetState(params) { this.setState(this.getInitialState(params)); } componentWillUnmount() { this.stopServerPolling(); } startServerPolling() { const { pollingInterval } = this.state; this.loadFromServer(); this.timerId = window.setInterval(this.loadFromServer, pollingInterval); } stopServerPolling() { window.clearInterval(this.timerId); this.api.cancelCurrentRequests(); this.setState({ pendingRequests: false }); } loadFromServer() { const { pendingRequests, ns } = this.state; if (pendingRequests) { return; // don't make more requests if the ones we sent haven't completed } this.setState({ pendingRequests: true }); this.api.setCurrentRequests([this.api.fetchMetrics(this.api.urlsForResource('all', ns, true))]); Promise.all(this.api.getCurrentPromises()) .then(([allRollup]) => { const metrics = processMultiResourceRollup(allRollup, 'all'); this.setState({ metrics, loaded: true, pendingRequests: false, error: null, }); }) .catch(this.handleApiError); } handleApiError = e => { if (e.isCanceled) { return; } this.setState({ pendingRequests: false, error: e, }); } checkNamespaceMatch = () => { const { ns } = this.state; const { selectedNamespace, updateNamespaceInContext } = this.props; if (ns !== selectedNamespace) { updateNamespaceInContext(ns); } } renderResourceSection = (resource, metrics) => { if (_isEmpty(metrics)) { return null; } return (