import { connect } from 'react-redux'; import cn from 'classnames'; import withPageTitle from 'HOCs/withPageTitle'; import withPermissions from 'HOCs/withPermissions' import { setPeriod, setPlatform, fetchMetadataOptions } from 'Duck/dashboard'; import { NoContent, Icon } from 'UI'; import { WIDGET_KEYS, WIDGET_LIST } from 'Types/dashboard'; // import CustomMetrics from 'Shared/CustomMetrics'; import CustomMetricsModal from 'Shared/CustomMetrics/CustomMetricsModal'; import SessionListModal from 'Shared/CustomMetrics/SessionListModal'; 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 CustomMetricsWidgets from './Widgets/CustomMetricsWidgets/CustomMetricsWidgets'; 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'; const RESOURCES = 'resources'; const CUSTOM_METRICS = 'custom_metrics'; const menuList = [ { key: OVERVIEW, section: 'metrics', icon: "info-square", label: getStatusLabel(OVERVIEW), active: status === OVERVIEW, }, { key: CUSTOM_METRICS, section: 'metrics', icon: "sliders", label: getStatusLabel(CUSTOM_METRICS), active: status === CUSTOM_METRICS, }, { 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 CUSTOM_METRICS: return "Custom Metrics"; 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) ); } @withPermissions(['METRICS'], 'page-margin container-90') @connect(state => ({ period: state.getIn([ 'dashboard', 'period' ]), comparing: state.getIn([ 'dashboard', 'comparing' ]), platform: state.getIn([ 'dashboard', 'platform' ]), dashboardAppearance: state.getIn([ 'user', 'account', 'appearance', 'dashboard' ]), activeWidget: state.getIn(['customMetrics', 'activeWidget']), appearance: state.getIn([ 'user', 'account', 'appearance' ]), }), { 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', }; getWidgetsByKey = (widgetType) => { return WIDGET_LIST.filter(({ key, type }) => !this.props.appearance.dashboard[ key ] && type === widgetType); } 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, activeWidget } = this.props; const { pageSection } = this.state; const noWidgets = WIDGET_KEYS .filter(key => dashboardAppearance[ key ]) .length === 0; return (
{ activeWidget && }
{comparing && (
Custom Metrics are not supported for comparison.
)}
} >
null}/>
{ dashboardAppearance.impactedSessionsByJsErrors && } { dashboardAppearance.errorsPerDomains && } { dashboardAppearance.errorsPerType && } { dashboardAppearance.resourcesByParty && } { dashboardAppearance.domainsErrors_4xx && } { dashboardAppearance.domainsErrors_5xx && } { dashboardAppearance.callsErrors &&
}
{ dashboardAppearance.speedLocation && } { dashboardAppearance.crashes && } { dashboardAppearance.pagesResponseTime && } { dashboardAppearance.impactedSessionsBySlowPages && } { dashboardAppearance.pagesResponseTimeDistribution &&
} { dashboardAppearance.pagesDomBuildtime && } { dashboardAppearance.timeToRender && } { dashboardAppearance.memoryConsumption && } { dashboardAppearance.cpu && } { dashboardAppearance.slowestDomains && } { dashboardAppearance.resourcesVsVisuallyComplete && } { dashboardAppearance.fps && } { dashboardAppearance.sessionsPerBrowser && }
{ dashboardAppearance.resourcesCountByType && } { dashboardAppearance.resourcesLoadingTime && } { dashboardAppearance.resourceTypeVsResponseEnd && } { dashboardAppearance.missingResources && } { dashboardAppearance.slowestResources &&
}
); } }