import { connect } from 'react-redux'; import cn from 'classnames'; import withPageTitle from 'HOCs/withPageTitle'; import { setPeriod, setPlatform, fetchMetadataOptions } from 'Duck/dashboard'; import { NoContent } from 'UI'; import { WIDGET_KEYS } from 'Types/dashboard'; import { MissingResources, SlowestResources, DomBuildingTime, ResourceLoadingTime, ResponseTime, ResponseTimeDistribution, TimeToRender, SessionsImpactedBySlowRequests, MemoryConsumption, CpuLoad, FPS, Crashes, SlowestDomains, ErrorsPerDomain, CallWithErrors, ErrorsByType, ErrorsByOrigin, ResourceLoadedVsResponseEnd, ResourceLoadedVsVisuallyComplete, SessionsAffectedByJSErrors, BreakdownOfLoadedResources, SpeedIndexLocation, SessionsPerBrowser, CallsErrors5xx, CallsErrors4xx } from './Widgets'; import SideMenuSection from './SideMenu/SideMenuSection'; import styles from './dashboard.css'; import WidgetSection from 'Shared/WidgetSection/WidgetSection'; import OverviewWidgets from './Widgets/OverviewWidgets/OverviewWidgets'; import WidgetHolder from './WidgetHolder/WidgetHolder'; import MetricsFilters from 'Shared/MetricsFilters/MetricsFilters'; import { withRouter } from 'react-router'; const OVERVIEW = 'overview'; const PERFORMANCE = 'performance'; const ERRORS_N_CRASHES = 'errors_n_crashes'; const RESOURCES = 'resources'; const menuList = [ { key: OVERVIEW, section: 'metrics', icon: "info-square", label: getStatusLabel(OVERVIEW), active: status === OVERVIEW, }, { key: ERRORS_N_CRASHES, section: 'metrics', icon: "exclamation-circle", label: getStatusLabel(ERRORS_N_CRASHES), active: status === ERRORS_N_CRASHES, }, { key: PERFORMANCE, section: 'metrics', icon: "tachometer-slow", label: getStatusLabel(PERFORMANCE), active: status === PERFORMANCE, }, { key: RESOURCES, section: 'metrics', icon: "collection", label: getStatusLabel(RESOURCES), active: status === RESOURCES, }, ]; function getStatusLabel(status) { switch(status) { case OVERVIEW: return "Overview"; case PERFORMANCE: return "Performance"; case ERRORS_N_CRASHES: return "Errors"; case RESOURCES: return "Resources"; default: return ""; } } function isInViewport(el) { const rect = el.getBoundingClientRect(); return ( rect.top >= 0 && rect.left >= 0 && rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) && rect.right <= (window.innerWidth || document.documentElement.clientWidth) ); } @connect(state => ({ period: state.getIn([ 'dashboard', 'period' ]), comparing: state.getIn([ 'dashboard', 'comparing' ]), platform: state.getIn([ 'dashboard', 'platform' ]), dashboardAppearance: state.getIn([ 'user', 'account', 'appearance', 'dashboard' ]), }), { setPeriod, setPlatform, fetchMetadataOptions }) @withPageTitle('Metrics - OpenReplay') @withRouter export default class Dashboard extends React.PureComponent { constructor(props) { super(props) this.list = {}; menuList.forEach(item => { this.list[item.key] = React.createRef(); }); props.fetchMetadataOptions(); } state = { rangeName: this.props.period.rangeName, startDate: null, endDate: null, pageSection: 'metrics', }; componentDidMount() { const { history, location } = this.props; // TODO check the hash navigato it } onMenuItemClick = ({section, key}) => { const { history, location } = this.props; const path = location.pathname + '#' + key; history.push(path); this.setState({ pageSection: section }); setTimeout(function() { this.navigateHash(section, key); }.bind(this), 10); } navigateHash = (section, key) => { const { history, location } = this.props; const element = this.list[key].current; const offset = 110; const bodyRect = document.body.getBoundingClientRect().top; const elementRect = element.getBoundingClientRect().top; const elementPosition = elementRect - bodyRect; const offsetPosition = elementPosition - offset; const path = location.pathname + '#' + key; history.push(path); window.scrollTo({ top: offsetPosition, behavior: 'smooth' }); } render() { const { dashboardAppearance, comparing } = this.props; const { pageSection } = this.state; const noWidgets = WIDGET_KEYS .filter(key => dashboardAppearance[ key ]) .length === 0; return (