import { DateTime } from 'luxon'; import { connect } from 'react-redux'; import cn from 'classnames'; import { connectPlayer } from 'Player'; import { Popup, TimelinePointer } from 'UI'; import TimeTracker from './TimeTracker'; import { ReduxTime } from './Time'; import stl from './timeline.css'; import { TYPES } from 'Types/session/event'; const getPointerIcon = (type) => { // exception, switch(type) { case 'fetch': return 'funnel/file-earmark-minus-fill'; case 'exception': return 'funnel/exclamation-circle'; case 'log': return 'funnel/exclamation-circle'; case 'stack': return 'funnel/patch-exclamation-fill'; case 'resource': return 'funnel/file-medical-alt'; case 'dead_click': return 'funnel/dizzy'; case 'click_rage': return 'funnel/dizzy'; case 'excessive_scrolling': return 'funnel/mouse'; case 'bad_request': return 'funnel/file-medical-alt'; case 'missing_resource': return 'funnel/file-earmark-minus-fill'; case 'memory': return 'funnel/sd-card'; case 'cpu': return 'funnel/microchip'; case 'slow_resource': return 'funnel/hourglass-top'; case 'slow_page_load': return 'funnel/hourglass-top'; case 'crash': return 'funnel/file-exclamation'; case 'js_exception': return 'funnel/exclamation-circle'; } return 'info'; } @connectPlayer(state => ({ skipIntervals: state.skipIntervals, events: state.eventList, skip: state.skip, skipToIssue: state.skipToIssue, disabled: state.cssLoading || state.messagesLoading || state.markedTargets, endTime: state.endTime, live: state.live, logList: state.logList, exceptionsList: state.exceptionsList, resourceList: state.resourceList, stackList: state.stackList, fetchList: state.fetchList, })) @connect(state => ({ issues: state.getIn([ 'sessions', 'current', 'issues' ]), clickRageTime: state.getIn([ 'sessions', 'current', 'clickRage' ]) && state.getIn([ 'sessions', 'current', 'clickRageTime' ]), returningLocationTime: state.getIn([ 'sessions', 'current', 'returningLocation' ]) && state.getIn([ 'sessions', 'current', 'returningLocationTime' ]), })) export default class Timeline extends React.PureComponent { seekProgress = (e) => { const { endTime } = this.props; const p = e.nativeEvent.offsetX / e.target.offsetWidth; const time = Math.max(Math.round(p * endTime), 0); this.props.jump(time); } createEventClickHandler = time => (e) => { e.stopPropagation(); this.props.jump(time) } componentDidMount() { const { issues, events, fetchList, skipToIssue } = this.props; const firstIssue = issues.get(0); if (firstIssue && skipToIssue) { this.props.jump(firstIssue.time); } } render() { const { events, skip, skipIntervals, disabled, endTime, live, logList, exceptionsList, resourceList, clickRageTime, stackList, fetchList, issues } = this.props; const scale = 100 / endTime; return (
{ !live && }
{ skip && skipIntervals.map(interval => (
)) }
{ events.map(e => (
)) } { issues.map(iss => (
{ iss.name }
} />
)) } { events.filter(e => e.type === TYPES.CLICKRAGE).map(e => (
{ "Click Rage" }
} />
// // } // content={ //
// { "Click Rage" } //
// } // /> ))} { typeof clickRageTime === 'number' &&
{ "Click Rage" }
} />
// // } // content={ //
// { "Click Rage" } //
// } // /> } { /* typeof returningLocationTime === 'number' && } content={
{ "Returning Location" }
} /> */ } { exceptionsList .map(e => (
{ "Exception" }
{ e.message }
} />
// // } // content={ //
// { "Exception:" } //
// { e.message } //
// } // /> )) } { logList .map(l => l.isRed() && (
{ "Console" }
{ l.value }
} />
// // } // content={ //
// { "Console:" } //
// { l.value } //
// } // /> )) } { resourceList .filter(r => r.isRed() || r.isYellow()) .map(r => (
{ r.success ? "Slow resource: " : "Missing resource:" }
{ r.name }
} /> // // // } // content={ //
// { r.success ? "Slow resource: " : "Missing resource:" } //
// { r.name } //
// } // /> )) } { fetchList .filter(e => e.isRed()) .map(e => (
{ "Failed Fetch" }
{ e.name }
} /> // // } // content={ //
// { "Failed Fetch:" } //
// { e.name } //
// } // /> )) } { stackList .filter(e => e.isRed()) .map(e => (
{ "Stack Event" }
{ e.name }
} /> // // } // content={ //
// { "Stack Event:" } //
// { e.name } //
// } // /> )) } { !live && } ); } }