change: timeline issue pointers and static issue types
|
|
@ -6,6 +6,7 @@ import stl from './sessionMenu.css';
|
|||
import { fetchList, fetchWatchdogStatus } from 'Duck/watchdogs';
|
||||
import { setActiveFlow, clearEvents } from 'Duck/filters';
|
||||
import { setActiveTab } from 'Duck/sessions';
|
||||
import { issues_types } from 'Types/session/issue'
|
||||
|
||||
function SessionsMenu(props) {
|
||||
const {
|
||||
|
|
@ -62,7 +63,7 @@ function SessionsMenu(props) {
|
|||
/>
|
||||
</div>
|
||||
|
||||
{ watchdogs.filter(item => item.visible).map(item => (
|
||||
{ issues_types.filter(item => item.visible).map(item => (
|
||||
<SideMenuitem
|
||||
key={item.key}
|
||||
disabled={!keyMap[item.type] && !wdTypeCount[item.type]}
|
||||
|
|
@ -88,7 +89,7 @@ function SessionsMenu(props) {
|
|||
}
|
||||
|
||||
export default connect(state => ({
|
||||
watchdogs: state.getIn(['watchdogs', 'list']).sortBy(i => i.order),
|
||||
// watchdogs: state.getIn(['watchdogs', 'list']).sortBy(i => i.order),
|
||||
activeTab: state.getIn([ 'sessions', 'activeTab' ]),
|
||||
keyMap: state.getIn([ 'sessions', 'keyMap' ]),
|
||||
wdTypeCount: state.getIn([ 'sessions', 'wdTypeCount' ]),
|
||||
|
|
|
|||
|
|
@ -24,6 +24,8 @@ const getPointerIcon = (type) => {
|
|||
|
||||
case 'dead_click':
|
||||
return 'funnel/dizzy';
|
||||
case 'click_rage':
|
||||
return 'funnel/dizzy';
|
||||
case 'excessive_scrolling':
|
||||
return 'funnel/mouse';
|
||||
case 'bad_request':
|
||||
|
|
@ -61,6 +63,7 @@ const getPointerIcon = (type) => {
|
|||
fetchList: state.fetchList,
|
||||
}))
|
||||
@connect(state => ({
|
||||
issues: state.getIn([ 'sessions', 'current', 'issues' ]),
|
||||
showDevTools: state.getIn([ 'user', 'account', 'appearance', 'sessionsDevtools' ]),
|
||||
clickRageTime: state.getIn([ 'sessions', 'current', 'clickRage' ]) &&
|
||||
state.getIn([ 'sessions', 'current', 'clickRageTime' ]),
|
||||
|
|
@ -95,6 +98,7 @@ export default class Timeline extends React.PureComponent {
|
|||
clickRageTime,
|
||||
stackList,
|
||||
fetchList,
|
||||
issues
|
||||
} = this.props;
|
||||
|
||||
const scale = 100 / endTime;
|
||||
|
|
@ -124,6 +128,28 @@ export default class Timeline extends React.PureComponent {
|
|||
/>
|
||||
))
|
||||
}
|
||||
{
|
||||
issues.map(iss => (
|
||||
<div
|
||||
style={ {
|
||||
left: `${ iss.time * scale }%`,
|
||||
top: '-30px'
|
||||
//width: `${ 2000 * scale }%`
|
||||
} }
|
||||
className={ stl.clickRage }
|
||||
onClick={ this.createEventClickHandler(iss.time) }
|
||||
>
|
||||
<TimelinePointer
|
||||
icon={iss.icon}
|
||||
content={
|
||||
<div className={ stl.popup }>
|
||||
<b>{ iss.name }</b>
|
||||
</div>
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
))
|
||||
}
|
||||
{ events.filter(e => e.type === TYPES.CLICKRAGE).map(e => (
|
||||
<div
|
||||
style={ {
|
||||
|
|
|
|||
3
frontend/app/svg/icons/funnel/cpu.svg
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" class="bi bi-cpu" viewBox="0 0 16 16">
|
||||
<path d="M5 0a.5.5 0 0 1 .5.5V2h1V.5a.5.5 0 0 1 1 0V2h1V.5a.5.5 0 0 1 1 0V2h1V.5a.5.5 0 0 1 1 0V2A2.5 2.5 0 0 1 14 4.5h1.5a.5.5 0 0 1 0 1H14v1h1.5a.5.5 0 0 1 0 1H14v1h1.5a.5.5 0 0 1 0 1H14v1h1.5a.5.5 0 0 1 0 1H14a2.5 2.5 0 0 1-2.5 2.5v1.5a.5.5 0 0 1-1 0V14h-1v1.5a.5.5 0 0 1-1 0V14h-1v1.5a.5.5 0 0 1-1 0V14h-1v1.5a.5.5 0 0 1-1 0V14A2.5 2.5 0 0 1 2 11.5H.5a.5.5 0 0 1 0-1H2v-1H.5a.5.5 0 0 1 0-1H2v-1H.5a.5.5 0 0 1 0-1H2v-1H.5a.5.5 0 0 1 0-1H2A2.5 2.5 0 0 1 4.5 2V.5A.5.5 0 0 1 5 0zm-.5 3A1.5 1.5 0 0 0 3 4.5v7A1.5 1.5 0 0 0 4.5 13h7a1.5 1.5 0 0 0 1.5-1.5v-7A1.5 1.5 0 0 0 11.5 3h-7zM5 6.5A1.5 1.5 0 0 1 6.5 5h3A1.5 1.5 0 0 1 11 6.5v3A1.5 1.5 0 0 1 9.5 11h-3A1.5 1.5 0 0 1 5 9.5v-3zM6.5 6a.5.5 0 0 0-.5.5v3a.5.5 0 0 0 .5.5h3a.5.5 0 0 0 .5-.5v-3a.5.5 0 0 0-.5-.5h-3z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 854 B |
1
frontend/app/svg/icons/funnel/dizzy.svg
Normal file
|
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 496 512"><path d="M248 8C111 8 0 119 0 256s111 248 248 248 248-111 248-248S385 8 248 8zm0 464c-119.1 0-216-96.9-216-216S128.9 40 248 40s216 96.9 216 216-96.9 216-216 216zm0-184c-35.3 0-64 28.7-64 64s28.7 64 64 64 64-28.7 64-64-28.7-64-64-64zm0 96c-17.6 0-32-14.4-32-32s14.4-32 32-32 32 14.4 32 32-14.4 32-32 32zm-28.7-140.7c6.2-6.2 6.2-16.4 0-22.6L190.6 192l28.7-28.7c6.2-6.2 6.2-16.4 0-22.6s-16.4-6.2-22.6 0L168 169.4l-28.7-28.7c-6.2-6.2-16.4-6.2-22.6 0s-6.2 16.4 0 22.6l28.7 28.7-28.7 28.7c-6.2 6.2-6.2 16.4 0 22.6 6.2 6.2 16.4 6.3 22.6 0l28.7-28.7 28.7 28.7c6.2 6.3 16.4 6.3 22.6 0zm160-102.6c-6.2-6.2-16.4-6.2-22.6 0L328 169.4l-28.7-28.7c-6.2-6.2-16.4-6.2-22.6 0s-6.2 16.4 0 22.6l28.7 28.7-28.7 28.7c-6.2 6.2-6.2 16.4 0 22.6 6.2 6.2 16.4 6.3 22.6 0l28.7-28.7 28.7 28.7c6.2 6.2 16.4 6.3 22.6 0 6.2-6.2 6.2-16.4 0-22.6L350.6 192l28.7-28.7c6.3-6.2 6.3-16.4 0-22.6z"/></svg>
|
||||
|
After Width: | Height: | Size: 927 B |
4
frontend/app/svg/icons/funnel/emoji-angry.svg
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" class="bi bi-emoji-angry" viewBox="0 0 16 16">
|
||||
<path d="M8 15A7 7 0 1 1 8 1a7 7 0 0 1 0 14zm0 1A8 8 0 1 0 8 0a8 8 0 0 0 0 16z"/>
|
||||
<path d="M4.285 12.433a.5.5 0 0 0 .683-.183A3.498 3.498 0 0 1 8 10.5c1.295 0 2.426.703 3.032 1.75a.5.5 0 0 0 .866-.5A4.498 4.498 0 0 0 8 9.5a4.5 4.5 0 0 0-3.898 2.25.5.5 0 0 0 .183.683zm6.991-8.38a.5.5 0 1 1 .448.894l-1.009.504c.176.27.285.64.285 1.049 0 .828-.448 1.5-1 1.5s-1-.672-1-1.5c0-.247.04-.48.11-.686a.502.502 0 0 1 .166-.761l2-1zm-6.552 0a.5.5 0 0 0-.448.894l1.009.504A1.94 1.94 0 0 0 5 6.5C5 7.328 5.448 8 6 8s1-.672 1-1.5c0-.247-.04-.48-.11-.686a.502.502 0 0 0-.166-.761l-2-1z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 672 B |
3
frontend/app/svg/icons/funnel/file-earmark-break.svg
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" class="bi bi-file-earmark-break" viewBox="0 0 16 16">
|
||||
<path d="M14 4.5V9h-1V4.5h-2A1.5 1.5 0 0 1 9.5 3V1H4a1 1 0 0 0-1 1v7H2V2a2 2 0 0 1 2-2h5.5L14 4.5zM13 12h1v2a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2v-2h1v2a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1v-2zM.5 10a.5.5 0 0 0 0 1h15a.5.5 0 0 0 0-1H.5z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 328 B |
4
frontend/app/svg/icons/funnel/image.svg
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" class="bi bi-image" viewBox="0 0 16 16">
|
||||
<path d="M6.002 5.5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0z"/>
|
||||
<path d="M2.002 1a2 2 0 0 0-2 2v10a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V3a2 2 0 0 0-2-2h-12zm12 1a1 1 0 0 1 1 1v6.5l-3.777-1.947a.5.5 0 0 0-.577.093l-3.71 3.71-2.66-1.772a.5.5 0 0 0-.63.062L1.002 12V3a1 1 0 0 1 1-1h12z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 367 B |
|
|
@ -1 +1,4 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 384 512"><defs><style>.fa-secondary{opacity:.4}</style></defs><path d="M112 160h48V64h-48zm80 0h48V64h-48zm80-96v96h48V64z" class="fa-secondary"/><path d="M320 0H128L0 128v320a64.06 64.06 0 0 0 64 64h256a64.06 64.06 0 0 0 64-64V64a64.06 64.06 0 0 0-64-64zM160 160h-48V64h48zm80 0h-48V64h48zm80 0h-48V64h48z" class="fa-primary"/></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="bi bi-sd-card" viewBox="0 0 16 16">
|
||||
<path d="M6.25 3.5a.75.75 0 0 0-1.5 0v2a.75.75 0 0 0 1.5 0v-2zm2 0a.75.75 0 0 0-1.5 0v2a.75.75 0 0 0 1.5 0v-2zm2 0a.75.75 0 0 0-1.5 0v2a.75.75 0 0 0 1.5 0v-2zm2 0a.75.75 0 0 0-1.5 0v2a.75.75 0 0 0 1.5 0v-2z"/>
|
||||
<path fill-rule="evenodd" d="M5.914 0H12.5A1.5 1.5 0 0 1 14 1.5v13a1.5 1.5 0 0 1-1.5 1.5h-9A1.5 1.5 0 0 1 2 14.5V3.914c0-.398.158-.78.44-1.06L4.853.439A1.5 1.5 0 0 1 5.914 0zM13 1.5a.5.5 0 0 0-.5-.5H5.914a.5.5 0 0 0-.353.146L3.146 3.561A.5.5 0 0 0 3 3.914V14.5a.5.5 0 0 0 .5.5h9a.5.5 0 0 0 .5-.5v-13z"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 387 B After Width: | Height: | Size: 607 B |
42
frontend/app/types/session/issue.js
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
import Record from 'Types/Record';
|
||||
import { List } from 'immutable';
|
||||
import Watchdog from 'Types/watchdog'
|
||||
|
||||
export const issues_types = List([
|
||||
{ 'type': 'js_exception', 'visible': true, 'order': 0, 'name': 'Errors', 'icon': 'funnel/exclamation-circle' },
|
||||
{ 'type': 'bad_request', 'visible': true, 'order': 1, 'name': 'Bad Requests', 'icon': 'funnel/file-medical-alt' },
|
||||
{ 'type': 'missing_resource', 'visible': true, 'order': 2, 'name': 'Missing Images', 'icon': 'funnel/image' },
|
||||
{ 'type': 'click_rage', 'visible': true, 'order': 3, 'name': 'Click Rage', 'icon': 'funnel/dizzy' },
|
||||
{ 'type': 'dead_click', 'visible': true, 'order': 4, 'name': 'Dead Clicks', 'icon': 'funnel/emoji-angry' },
|
||||
{ 'type': 'memory', 'visible': true, 'order': 5, 'name': 'High Memory', 'icon': 'funnel/sd-card' },
|
||||
{ 'type': 'cpu', 'visible': true, 'order': 6, 'name': 'High CPU', 'icon': 'funnel/cpu' },
|
||||
{ 'type': 'crash', 'visible': true, 'order': 7, 'name': 'Crashes', 'icon': 'funnel/file-earmark-break' }
|
||||
]).map(Watchdog)
|
||||
|
||||
export const issues_types_map = {}
|
||||
issues_types.forEach(i => {
|
||||
issues_types_map[i.type] = { type: i.type, visible: i.visible, order: i.order, name: i.name, }
|
||||
});
|
||||
|
||||
export default Record({
|
||||
issueId: undefined,
|
||||
name: '',
|
||||
visible: true,
|
||||
sessionId: undefined,
|
||||
time: undefined,
|
||||
seqIndex: undefined,
|
||||
payload: {},
|
||||
projectId: undefined,
|
||||
type: '',
|
||||
contextString: '',
|
||||
context: '',
|
||||
icon: 'info'
|
||||
}, {
|
||||
idKey: 'issueId',
|
||||
fromJS: ({ type, ...rest }) => ({
|
||||
...rest,
|
||||
type,
|
||||
icon: issues_types_map[type].icon,
|
||||
name: issues_types_map[type].name,
|
||||
}),
|
||||
});
|
||||
|
|
@ -7,7 +7,7 @@ import StackEvent from './stackEvent';
|
|||
import Resource from './resource';
|
||||
import CustomField from './customField';
|
||||
import SessionError from './error';
|
||||
|
||||
import Issue from './issue';
|
||||
|
||||
const SOURCE_JS = 'js_exception';
|
||||
|
||||
|
|
@ -66,6 +66,7 @@ export default Record({
|
|||
errorsCount: 0,
|
||||
watchdogs: [],
|
||||
issueTypes: [],
|
||||
issues: [],
|
||||
userDeviceHeapSize: 0,
|
||||
userDeviceMemorySize: 0,
|
||||
errors: List(),
|
||||
|
|
@ -80,6 +81,7 @@ export default Record({
|
|||
projectId,
|
||||
errors,
|
||||
stackEvents = [],
|
||||
issues = [],
|
||||
...session
|
||||
}) => {
|
||||
const duration = Duration.fromMillis(session.duration < 1000 ? 1000 : session.duration);
|
||||
|
|
@ -109,6 +111,10 @@ export default Record({
|
|||
.map(se => StackEvent({ ...se, time: se.timestamp - startedAt }));
|
||||
const exceptions = List(errors)
|
||||
.map(SessionError)
|
||||
|
||||
const issuesList = List(issues)
|
||||
.map(e => Issue({ ...e, time: e.timestamp - startedAt }))
|
||||
|
||||
return {
|
||||
...session,
|
||||
isIOS: session.platform === "ios",
|
||||
|
|
@ -128,6 +134,7 @@ export default Record({
|
|||
userNumericHash: hashString(session.userId || session.userAnonymousId || session.userUuid || ""),
|
||||
userDisplayName: session.userId || session.userAnonymousId || 'Anonymous User',
|
||||
firstResourceTime,
|
||||
issues: issuesList,
|
||||
};
|
||||
},
|
||||
idKey: "sessionId",
|
||||
|
|
|
|||
|
|
@ -22,7 +22,6 @@ const WATCHDOG_TYPES = [
|
|||
]
|
||||
|
||||
export const names = {
|
||||
// 'all' : { label: 'All', icon: 'all' },
|
||||
'js_exception' : { label: 'JS Exceptions', icon: 'funnel/exclamation-circle' },
|
||||
'bad_request': { label: 'Bad Request', icon: 'funnel/patch-exclamation-fill' },
|
||||
'missing_resource': { label: 'Missing Resources', icon: 'funnel/image-fill' },
|
||||
|
|
@ -33,13 +32,6 @@ export const names = {
|
|||
'cpu': { label: 'CPU', icon: 'funnel/hdd-fill' },
|
||||
'dead_click': { label: 'Dead Click', icon: 'funnel/emoji-dizzy-fill' },
|
||||
'custom': { label: 'Custom', icon: 'funnel/exclamation-circle-fill' },
|
||||
|
||||
// 'errors' : { label: 'Errors', icon: 'console/error' },
|
||||
// 'missing_image': { label: 'Missing Images', icon: 'image' },
|
||||
// 'slow_session': { label: 'Slow Sessions', icon: 'turtle' },
|
||||
// 'high_engagement': { label: 'High Engagements', icon: 'high-engagement' },
|
||||
// 'performance_issues': { label: 'Mem/CPU Issues', icon: 'tachometer-slowest' },
|
||||
// 'default': { label: 'Default', icon: 'window-alt' },
|
||||
}
|
||||
|
||||
const CONJUGATED_ISSUE_TYPES = {
|
||||
|
|
@ -93,8 +85,6 @@ export default Record({
|
|||
}
|
||||
},
|
||||
fromJS: (item) => ({
|
||||
...item,
|
||||
name: item.name,
|
||||
icon: names[item.type] ? names[item.type].icon : 'turtle'
|
||||
...item
|
||||
}),
|
||||
});
|
||||
|
|
|
|||