change(ui): add visual display for frustrations

This commit is contained in:
nick-delirium 2023-03-16 17:11:13 +01:00
parent d6526464c6
commit f360ce3d2c
20 changed files with 245 additions and 47 deletions

View file

@ -1,7 +1,7 @@
import React from 'react';
import copy from 'copy-to-clipboard';
import cn from 'classnames';
import { Icon, TextEllipsis } from 'UI';
import { Icon, TextEllipsis, Tooltip } from 'UI';
import { TYPES } from 'Types/session/event';
import { prorata } from 'App/utils';
import withOverlay from 'Components/hocs/withOverlay';
@ -9,6 +9,16 @@ import LoadInfo from './LoadInfo';
import cls from './event.module.css';
import { numberWithCommas } from 'App/utils';
function isFrustrationEvent(evt) {
if (evt.type === 'mouse_thrashing' || evt.type === TYPES.CLICKRAGE) {
return true;
}
if (evt.type === TYPES.CLICK || evt.type === TYPES.INPUT) {
return evt.hesitation > 1000
}
return false
}
@withOverlay()
export default class Event extends React.PureComponent {
state = {
@ -44,35 +54,50 @@ export default class Event extends React.PureComponent {
const { event } = this.props;
let title = event.type;
let body;
let icon;
const isFrustration = isFrustrationEvent(event);
const tooltip = { disabled: true, text: '' }
switch (event.type) {
case TYPES.LOCATION:
title = 'Visited';
body = event.url;
icon = 'location';
break;
case TYPES.CLICK:
title = 'Clicked';
body = event.label;
icon = isFrustration ? 'click_hesitation' : 'click';
isFrustration ? Object.assign(tooltip, { disabled: false, text: `User hesitated to click for ${Math.round(event.hesitation/1000)}s`, }) : null;
break;
case TYPES.INPUT:
title = 'Input';
body = event.value;
icon = isFrustration ? 'input_hesitation' : 'input';
isFrustration ? Object.assign(tooltip, { disabled: false, text: `User hesitated to enter a value for ${Math.round(event.hesitation/1000)}s`, }) : null;
break;
case TYPES.CLICKRAGE:
title = `${ event.count } Clicks`;
body = event.label;
icon = 'clickrage'
break;
case TYPES.IOS_VIEW:
title = 'View';
body = event.name;
icon = 'ios_view'
break;
case 'mouse_thrashing':
title = 'Mouse Thrashing';
icon = 'mouse_thrashing'
break;
}
const isLocation = event.type === TYPES.LOCATION;
const isClickrage = event.type === TYPES.CLICKRAGE;
return (
<Tooltip title={tooltip.text} disabled={tooltip.disabled} placement={"left"} anchorClassName={"w-full"} containerClassName={"w-full"}>
<div className={ cn(cls.main, 'flex flex-col w-full') } >
<div className="flex items-center w-full">
{ event.type && <Icon name={`event/${event.type.toLowerCase()}`} size="16" color={isClickrage? 'red' : 'gray-dark' } /> }
{ event.type && <Icon name={`event/${icon}`} size="16" color={'gray-dark' } /> }
<div className="ml-3 w-full">
<div className="flex w-full items-first justify-between">
<div className="flex items-center w-full" style={{ minWidth: '0'}}>
@ -100,6 +125,7 @@ export default class Event extends React.PureComponent {
</div>
}
</div>
</Tooltip>
);
};
@ -110,17 +136,15 @@ export default class Event extends React.PureComponent {
isCurrent,
onClick,
showSelection,
onCheckboxClick,
showLoadInfo,
toggleLoadInfo,
isRed,
extended,
highlight = false,
presentInSearch = false,
isLastInGroup,
whiteBg,
} = this.props;
const { menuOpen } = this.state;
const isFrustration = isFrustrationEvent(event);
return (
<div
ref={ ref => { this.wrapper = ref } }
@ -135,7 +159,7 @@ export default class Event extends React.PureComponent {
[ cls.red ]: isRed,
[ cls.clickType ]: event.type === TYPES.CLICK,
[ cls.inputType ]: event.type === TYPES.INPUT,
[ cls.clickrageType ]: event.type === TYPES.CLICKRAGE,
[ cls.frustration ]: isFrustration,
[ cls.highlight ] : presentInSearch,
[ cls.lastInGroup ]: whiteBg,
}) }
@ -146,13 +170,10 @@ export default class Event extends React.PureComponent {
{ event.target ? 'Copy CSS' : 'Copy URL' }
</button>
}
<div className={ cls.topBlock }>
<div className={ cls.firstLine }>
<div className={ cn(cls.topBlock, 'w-full') }>
<div className={ cn(cls.firstLine, 'w-full') }>
{ this.renderBody() }
</div>
{/* { event.type === TYPES.LOCATION &&
<div className="text-sm font-normal color-gray-medium">{event.url}</div>
} */}
</div>
{ event.type === TYPES.LOCATION && (event.fcpTime || event.visuallyComplete || event.timeToInteractive) &&
<LoadInfo

View file

@ -141,6 +141,13 @@
cursor: pointer;
}
.frustration {
background-color: rgba(204, 0, 0, 0.1)!important;
box-shadow:
2px 2px 1px 1px white,
2px 2px 0px 1px rgba(0,0,0,0.4);
}
.clickrageType {
background-color: #FFF3F3;
border: 1px solid #CC0000;

View file

@ -2,7 +2,6 @@ import React, { useEffect } from 'react';
import { toggleBottomBlock } from 'Duck/components/player';
import BottomBlock from '../BottomBlock';
import EventRow from './components/EventRow';
import { TYPES } from 'Types/session/event';
import { connect } from 'react-redux';
import TimelineScale from './components/TimelineScale';
import FeatureSelection, { HELP_MESSAGE } from './components/FeatureSelection/FeatureSelection';
@ -28,6 +27,7 @@ function OverviewPanel({ issuesList }: { issuesList: Record<string, any>[] }) {
performanceChartData,
stackList: stackEventList,
eventList: eventsList,
frustrationsList,
exceptionsList,
resourceList: resourceListUnmap,
fetchList,
@ -46,8 +46,8 @@ function OverviewPanel({ issuesList }: { issuesList: Record<string, any>[] }) {
NETWORK: resourceList,
ERRORS: exceptionsList,
EVENTS: stackEventList,
CLICKRAGE: eventsList.filter((item: any) => item.type === TYPES.CLICKRAGE),
PERFORMANCE: performanceChartData,
FRUSTRATIONS: frustrationsList,
};
}, [dataLoaded]);

View file

@ -4,15 +4,15 @@ import { Checkbox, Tooltip } from 'UI';
const NETWORK = 'NETWORK';
const ERRORS = 'ERRORS';
const EVENTS = 'EVENTS';
const CLICKRAGE = 'CLICKRAGE';
const FRUSTRATIONS = 'FRUSTRATIONS';
const PERFORMANCE = 'PERFORMANCE';
export const HELP_MESSAGE: any = {
NETWORK: 'Network requests made in this session',
EVENTS: 'Visualizes the events that takes place in the DOM',
ERRORS: 'Visualizes native JS errors like Type, URI, Syntax etc.',
CLICKRAGE: 'Indicates user frustration when repeated clicks are recorded',
PERFORMANCE: 'Summary of this sessions memory, and CPU consumption on the timeline',
FRUSTRATIONS: 'Indicates user frustrations in the session',
};
interface Props {
@ -21,7 +21,7 @@ interface Props {
}
function FeatureSelection(props: Props) {
const { list } = props;
const features = [NETWORK, ERRORS, EVENTS, CLICKRAGE, PERFORMANCE];
const features = [NETWORK, ERRORS, EVENTS, PERFORMANCE, FRUSTRATIONS];
const disabled = list.length >= 5;
return (
@ -30,7 +30,7 @@ function FeatureSelection(props: Props) {
const checked = list.includes(feature);
const _disabled = disabled && !checked;
return (
<Tooltip key={index} title="X-RAY supports up to 3 views" disabled={!_disabled} delay={0}>
<Tooltip key={index} title="X-RAY supports up to 5 views" disabled={!_disabled} delay={0}>
<Checkbox
key={index}
label={feature}

View file

@ -7,10 +7,12 @@ import ErrorDetailsModal from 'App/components/Dashboard/components/Errors/ErrorD
import FetchDetails from 'Shared/FetchDetailsModal';
import GraphQLDetailsModal from 'Shared/GraphQLDetailsModal';
import { PlayerContext } from 'App/components/Session/playerContext';
import { TYPES } from 'App/types/session/event'
import { types as issueTypes } from 'App/types/session/issue'
interface Props {
pointer: any;
type: any;
type: 'ERRORS' | 'EVENT' | 'NETWORK' | 'FRUSTRATIONS' | 'EVENTS' | 'PERFORMANCE';
noClick?: boolean;
fetchPresented?: boolean;
}
@ -71,19 +73,25 @@ const TimelinePointer = React.memo((props: Props) => {
);
};
const renderClickRageElement = (item: any) => {
const renderFrustrationElement = (item: any) => {
const elData = { name: '', icon: ''}
if (item.type === TYPES.CLICK) Object.assign(elData, { name: `User hesitated to click for ${Math.round(item.hesitation/1000)}s`, icon: 'click-hesitation' })
if (item.type === TYPES.INPUT) Object.assign(elData, { name: `User hesitated to enter a value for ${Math.round(item.hesitation/1000)}s`, icon: 'input-hesitation' })
if (item.type === TYPES.CLICKRAGE) Object.assign(elData, { name: 'Click Rage', icon: 'click-rage' })
if (item.type === issueTypes.MOUSE_THRASHING) Object.assign(elData, { name: 'Mouse Thrashing', icon: 'cursor-trash' })
return (
<Tooltip
title={
<div className="">
<b>{'Click Rage'}</b>
<b>{elData.name}</b>
</div>
}
delay={0}
placement="top"
>
<div onClick={createEventClickHandler(item, null)} className="cursor-pointer">
<Icon className="bg-white" name="funnel/emoji-angry" color="red" size="16" />
<Icon name={elData.icon} color="black" size="16" />
</div>
</Tooltip>
);
@ -158,8 +166,8 @@ const TimelinePointer = React.memo((props: Props) => {
if (type === 'NETWORK') {
return renderNetworkElement(pointer);
}
if (type === 'CLICKRAGE') {
return renderClickRageElement(pointer);
if (type === 'FRUSTRATIONS') {
return renderFrustrationElement(pointer);
}
if (type === 'ERRORS') {
return renderExceptionElement(pointer);

File diff suppressed because one or more lines are too long

View file

@ -23,6 +23,7 @@ function Tooltip(props: Props) {
placement,
className = '',
anchorClassName = '',
containerClassName = '',
delay = 500,
style = {},
offset = 5,
@ -39,7 +40,7 @@ function Tooltip(props: Props) {
});
return (
<div className="relative">
<div className={cn("relative", containerClassName)}>
<TooltipAnchor className={anchorClassName} state={state}>{props.children}</TooltipAnchor>
<FloatingTooltip
state={state}

View file

@ -3,7 +3,7 @@ import ListWalkerWithMarks from '../common/ListWalkerWithMarks';
import type { Timed } from '../common/types';
const SIMPLE_LIST_NAMES = [ "event", "redux", "mobx", "vuex", "zustand", "ngrx", "graphql", "exceptions", "profiles"] as const
const SIMPLE_LIST_NAMES = [ "event", "redux", "mobx", "vuex", "zustand", "ngrx", "graphql", "exceptions", "profiles", "frustrations"] as const
const MARKED_LIST_NAMES = [ "log", "resource", "fetch", "stack" ] as const
//const entityNamesSimple = [ "event", "profile" ];

View file

@ -31,6 +31,7 @@ export default class WebPlayer extends Player {
let initialLists = live ? {} : {
event: session.events || [],
stack: session.stackEvents || [],
frustrations: session.frustrations || [],
exceptions: session.errors?.map(({ name, ...rest }: any) =>
Log({
level: LogLevel.ERROR,

View file

@ -0,0 +1,15 @@
<svg viewBox="0 0 33 34" fill="none" xmlns="http://www.w3.org/2000/svg">
<g>
<rect width="32" height="32" fill="transparent" transform="translate(1 1.5)"/>
<g>
<rect width="27.6335" height="27.6335" fill="transparent" transform="translate(0.640625 5.68311)"/>
<path d="M12.2974 7.4102C12.641 7.4102 12.9704 7.54667 13.2133 7.78959C13.4563 8.03251 13.5927 8.36198 13.5927 8.70552V19.4999C13.5927 19.7289 13.6837 19.9486 13.8457 20.1105C14.0076 20.2724 14.2273 20.3634 14.4563 20.3634C14.6853 20.3634 14.905 20.2724 15.0669 20.1105C15.2289 19.9486 15.3198 19.7289 15.3198 19.4999V15.1251L15.4684 15.1182C16.0159 15.0975 16.5685 15.1044 16.8777 15.1649C17.1091 15.2115 17.3854 15.3307 17.6514 15.4792C17.7844 15.5517 17.9105 15.7331 17.9105 16.0215V19.4999C17.9105 19.7289 18.0015 19.9486 18.1634 20.1105C18.3254 20.2724 18.545 20.3634 18.774 20.3634C19.0031 20.3634 19.2227 20.2724 19.3846 20.1105C19.5466 19.9486 19.6376 19.7289 19.6376 19.4999V16.797C19.6985 16.7906 19.7596 16.7848 19.8206 16.7797C20.3664 16.7383 20.8293 16.7624 21.0434 16.8488C21.2472 16.9282 21.5616 17.2063 21.8828 17.5914C22.0227 17.7572 22.1419 17.9196 22.2282 18.0388V20.3634C22.2282 20.5925 22.3192 20.8121 22.4811 20.974C22.6431 21.136 22.8627 21.227 23.0918 21.227C23.3208 21.227 23.5404 21.136 23.7024 20.974C23.8643 20.8121 23.9553 20.5925 23.9553 20.3634V18.6363H24.546C24.7874 18.6363 25.0261 18.6869 25.2467 18.7848C25.4673 18.8828 25.6649 19.0258 25.8268 19.2048C25.9888 19.3839 26.1114 19.5948 26.1867 19.8241C26.2621 20.0534 26.2886 20.296 26.2644 20.5361L25.7964 25.2252C25.736 25.8278 25.5494 26.4109 25.2489 26.9368L22.8396 31.1543C22.7641 31.2865 22.655 31.3964 22.5234 31.4728C22.3918 31.5492 22.2423 31.5895 22.0901 31.5896H11.0625C10.9203 31.5895 10.7803 31.5543 10.655 31.4871C10.5297 31.4199 10.4229 31.3228 10.3441 31.2044L7.86914 27.4912C7.63935 27.1468 7.49543 26.7523 7.44946 26.3409L6.85361 20.9783C6.82952 20.7634 6.88696 20.5472 7.01456 20.3726C7.14216 20.198 7.33064 20.0776 7.54272 20.0353L9.275 19.6899V21.227C9.275 21.456 9.36598 21.6756 9.52792 21.8376C9.68987 21.9995 9.90952 22.0905 10.1385 22.0905C10.3676 22.0905 10.5872 21.9995 10.7492 21.8376C10.9111 21.6756 11.0021 21.456 11.0021 21.227V8.70552C11.0021 8.36198 11.1386 8.03251 11.3815 7.78959C11.6244 7.54667 11.9539 7.4102 12.2974 7.4102V7.4102ZM15.3198 13.3963V8.70552C15.3198 7.90393 15.0014 7.13516 14.4346 6.56835C13.8678 6.00154 13.099 5.68311 12.2974 5.68311C11.4958 5.68311 10.7271 6.00154 10.1602 6.56835C9.59343 7.13516 9.275 7.90393 9.275 8.70552V17.9282L7.20248 18.3427C6.56722 18.4701 6.00273 18.8309 5.62036 19.3539C5.23799 19.877 5.06549 20.5243 5.13687 21.1683L5.73272 26.5326C5.80935 27.2184 6.04921 27.8757 6.4322 28.4497L8.90713 32.1629C9.14368 32.5178 9.46418 32.8088 9.84018 33.01C10.2162 33.2113 10.6361 33.3166 11.0625 33.3167H22.0901C22.5467 33.3165 22.9952 33.1957 23.3901 32.9664C23.785 32.7371 24.1122 32.4075 24.3387 32.011L26.748 27.7951C27.1692 27.0582 27.4305 26.2408 27.5149 25.3962L27.9829 20.7071C28.0309 20.2269 27.9778 19.742 27.8269 19.2836C27.6761 18.8252 27.4308 18.4035 27.107 18.0457C26.7832 17.6879 26.388 17.4019 25.9469 17.2061C25.5058 17.0104 25.0286 16.9093 24.546 16.9092H23.5425C23.4347 16.763 23.3224 16.6202 23.2058 16.4809C22.8759 16.0854 22.3249 15.4999 21.6859 15.2443C21.0572 14.9922 20.2248 15.0163 19.6859 15.0578L19.458 15.0785C19.2741 14.6078 18.9321 14.2158 18.4908 13.9697C18.0934 13.7406 17.6637 13.5729 17.2162 13.4723C16.6808 13.3652 15.9399 13.3721 15.4027 13.3929L15.3198 13.3963Z" fill-opacity="0.54"/>
</g>
<g >
<rect width="14" height="14" fill="transparent" transform="translate(15 0.683105)"/>
<path d="M23.7172 6.89409L23.7171 6.89407L23.7138 6.89751L23.19 7.4329C23.1898 7.4331 23.1896 7.43331 23.1894 7.43351C22.9725 7.65353 22.7581 7.89061 22.6072 8.21025C22.5038 8.42919 22.4371 8.67099 22.4047 8.95345H22.0954C22.1311 8.49095 22.3346 8.07169 22.6463 7.75567L22.6467 7.75533L23.367 7.02342C23.6645 6.73202 23.8398 6.32907 23.8398 5.89095C23.8398 5.00766 23.119 4.28678 22.2357 4.28678C21.5039 4.28678 20.8837 4.78151 20.6924 5.45345H20.3905C20.5879 4.61704 21.3387 3.99512 22.2357 3.99512C23.2832 3.99512 24.1315 4.84341 24.1315 5.89095C24.1315 6.2836 23.971 6.64029 23.7172 6.89409ZM22.2357 1.37012C18.7741 1.37012 15.9648 4.17933 15.9648 7.64095C15.9648 11.1026 18.7741 13.9118 22.2357 13.9118C25.6973 13.9118 28.5065 11.1026 28.5065 7.64095C28.5065 4.17933 25.6973 1.37012 22.2357 1.37012ZM22.0898 11.2868V10.9951H22.3815V11.2868H22.0898Z" fill-opacity="0.87" stroke="white" stroke-width="0.875"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.5 KiB

View file

@ -0,0 +1,9 @@
<svg viewBox="0 0 31 30" fill="none" xmlns="http://www.w3.org/2000/svg">
<g>
<rect width="27.9992" height="28" fill="transparent" transform="matrix(1 0 -2.76372e-05 1 1.75 1)"/>
<path d="M6.7336 24.0156C9.12456 26.4067 12.3674 27.75 15.7489 27.75C19.1303 27.75 22.3733 26.4067 24.7644 24.0156C27.1554 21.6245 28.4988 18.3815 28.4989 15C28.499 11.6185 27.1558 8.37548 24.7649 5.98439C22.3739 3.5933 19.131 2.25 15.7496 2.25C12.3682 2.25 9.12519 3.5933 6.7341 5.98439C4.34301 8.37548 2.99966 11.6185 2.99956 15C2.99947 18.3815 4.34264 21.6245 6.7336 24.0156ZM25.2946 24.5459C22.7629 27.0777 19.3292 28.5 15.7489 28.5C12.1685 28.5 8.7349 27.0777 6.2033 24.5459C3.6717 22.0142 2.24951 18.5804 2.24961 15C2.24971 11.4196 3.67209 7.98579 6.20383 5.45405C8.73557 2.92231 12.1693 1.5 15.7496 1.5C19.3299 1.5 22.7636 2.92231 25.2952 5.45405C27.8268 7.98579 29.2489 11.4196 29.2488 15C29.2487 18.5804 27.8264 22.0142 25.2946 24.5459Z" stroke="black"/>
<path d="M9.24618 22.7574C9.44714 22.8734 9.68596 22.9048 9.9101 22.8448C10.1343 22.7847 10.3254 22.6381 10.4414 22.4371C10.9789 21.5055 11.7523 20.732 12.6837 20.1943C13.6152 19.6567 14.6719 19.374 15.7473 19.3746C18.0135 19.3746 19.9927 20.6049 21.0531 22.4371C21.17 22.6364 21.3609 22.7815 21.5843 22.8405C21.8077 22.8996 22.0453 22.8679 22.2454 22.7524C22.4455 22.6368 22.5918 22.4468 22.6523 22.2238C22.7129 22.0009 22.6828 21.763 22.5686 21.5621C21.8776 20.3645 20.8834 19.37 19.6859 18.6788C18.4884 17.9876 17.13 17.624 15.7474 17.6246C14.3648 17.6243 13.0065 17.9881 11.8091 18.6793C10.6117 19.3705 9.61729 20.3647 8.92597 21.5621C8.80994 21.7631 8.77849 22.0019 8.83854 22.2261C8.89859 22.4502 9.04522 22.6413 9.24618 22.7574ZM21.4805 8.09237C21.5833 8.03984 21.6955 8.00818 21.8107 7.99922C21.9258 7.99026 22.0416 8.00418 22.1513 8.04017C22.261 8.07617 22.3625 8.13353 22.45 8.20894C22.5374 8.28435 22.6091 8.37633 22.6608 8.47957C22.7125 8.58281 22.7433 8.69527 22.7514 8.81046C22.7594 8.92566 22.7446 9.04131 22.7078 9.15075C22.6709 9.26019 22.6128 9.36126 22.5367 9.44813C22.4606 9.53499 22.3681 9.60593 22.2644 9.65687L20.4987 10.5389C20.8067 11.0114 20.9974 11.6589 20.9974 12.3746C20.9973 13.8236 20.2133 14.9996 19.2474 14.9996C18.2814 14.9996 17.4974 13.8236 17.4975 12.3746C17.4975 11.9424 17.5675 11.5346 17.69 11.1741C17.6086 11.0721 17.551 10.9531 17.5213 10.826C17.4917 10.6989 17.4907 10.5667 17.5186 10.4392C17.5464 10.3116 17.6023 10.1919 17.6822 10.0886C17.7621 9.98539 17.864 9.90127 17.9805 9.84237L21.4805 8.09237V8.09237ZM10.0148 8.09237C9.8076 7.99053 9.56854 7.97472 9.34972 8.04838C9.1309 8.12205 8.95006 8.27922 8.84662 8.48564C8.74317 8.69207 8.72551 8.93101 8.79747 9.15039C8.86943 9.36978 9.02518 9.55183 9.23079 9.65687L10.9965 10.5389C10.6587 11.0908 10.4856 11.7277 10.4977 12.3746C10.4976 13.8236 11.2816 14.9996 12.2476 14.9996C13.2135 14.9996 13.9975 13.8236 13.9976 12.3746C13.9976 11.9424 13.9276 11.5346 13.8051 11.1741C13.8865 11.0721 13.9441 10.9531 13.9738 10.826C14.0035 10.6989 14.0044 10.5667 13.9766 10.4392C13.9488 10.3116 13.8929 10.1919 13.813 10.0886C13.7331 9.98539 13.6312 9.90127 13.5147 9.84237L10.0148 8.09237V8.09237Z" fill="black"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.1 KiB

View file

@ -0,0 +1,15 @@
<svg viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
<g >
<rect width="32" height="32" fill="transparent"/>
<g opacity="0.5" >
<rect width="24.2141" height="24.2141" fill="transparent" transform="matrix(0.912552 0.40896 -0.408989 0.912539 15.2246 -3.63281)"/>
<path d="M18.7221 2.84405L18.7221 2.84411L29.3225 13.7986C29.3225 13.7986 29.3226 13.7987 29.3226 13.7987C29.4624 13.9435 29.5575 14.1256 29.5963 14.3232C29.6352 14.5207 29.6162 14.7253 29.5415 14.9123C29.4669 15.0993 29.3399 15.2608 29.1757 15.3774C29.0115 15.4939 28.8172 15.5606 28.6161 15.5694C28.616 15.5694 28.616 15.5694 28.616 15.5694L24.2534 15.7529L23.7405 15.7744L23.9232 16.2541L26.0744 21.9023L26.0745 21.9024C26.1733 22.1616 26.1652 22.4494 26.0518 22.7025C25.9385 22.9556 25.7292 23.1534 25.4701 23.2522C25.2109 23.3511 24.9231 23.343 24.67 23.2296C24.4169 23.1163 24.2192 22.9071 24.1203 22.648C24.1203 22.648 24.1203 22.6479 24.1203 22.6479L21.9705 17.0006L21.7878 16.5208L21.3905 16.8459L18.011 19.6106L18.0108 19.6108C17.8548 19.7385 17.6653 19.8184 17.465 19.8409C17.2647 19.8635 17.0622 19.8276 16.8818 19.7377C16.7014 19.6478 16.5509 19.5076 16.4483 19.3341C16.3457 19.1607 16.2955 18.9612 16.3036 18.7599C16.3036 18.7599 16.3036 18.7598 16.3036 18.7598L16.9259 3.52856L16.9259 3.52847C16.9342 3.32399 17.0024 3.12645 17.1219 2.96033C17.2414 2.79421 17.407 2.66681 17.5983 2.59394C17.7895 2.52107 17.9979 2.50593 18.1977 2.55038C18.3975 2.59484 18.5798 2.69695 18.7221 2.84405Z" stroke="black" stroke-width="0.739831"/>
</g>
<path fill-rule="evenodd" clip-rule="evenodd" d="M8.24907 5.52226C7.9014 5.38309 7.52053 5.34903 7.15369 5.42428C6.78684 5.49953 6.45014 5.68079 6.18534 5.9456C5.92054 6.2104 5.73928 6.54709 5.66403 6.91394C5.58877 7.28079 5.62284 7.66165 5.762 8.00932L13.4145 27.1406C13.5516 27.483 13.7848 27.7785 14.0859 27.9914C14.3871 28.2044 14.7434 28.3258 15.1119 28.3409C15.4804 28.3561 15.8455 28.2644 16.1631 28.0769C16.4807 27.8894 16.7374 27.6141 16.9021 27.2841L19.5423 22.0058L25.3161 27.7834C25.675 28.1421 26.1618 28.3436 26.6693 28.3434C27.1768 28.3432 27.6635 28.1414 28.0222 27.7824C28.3809 27.4235 28.5823 26.9367 28.5822 26.4292C28.582 25.9217 28.3802 25.4351 28.0212 25.0763L22.2455 19.2987L27.5257 16.6605C27.8551 16.4953 28.1297 16.2385 28.3167 15.921C28.5036 15.6035 28.5949 15.2388 28.5796 14.8706C28.5642 14.5025 28.4429 14.1466 28.2301 13.8458C28.0174 13.5449 27.7223 13.3119 27.3803 13.1748L8.24907 5.52226Z" fill-opacity="0.87"/>
<g opacity="0.3">
<path d="M3.83765 12.8923L3.83756 12.8922C3.6146 12.8574 3.38631 12.8887 3.18101 12.9824C2.9757 13.0761 2.8024 13.2279 2.68259 13.4192C2.56278 13.6104 2.50174 13.8326 2.50701 14.0582C2.51229 14.2838 2.58367 14.5029 2.71229 14.6883L2.71235 14.6884L12.2901 28.5028C12.2902 28.5029 12.2902 28.5029 12.2902 28.5029C12.4169 28.6855 12.5937 28.8275 12.7992 28.912C13.0048 28.9964 13.2305 29.0197 13.4489 28.9789C13.6674 28.9381 13.8695 28.835 14.0307 28.682C14.192 28.5291 14.3056 28.3328 14.3578 28.1167L14.3579 28.1165L15.4934 23.4376L15.6269 22.8875L16.1064 23.1882L21.7521 26.7278L3.83765 12.8923ZM3.83765 12.8923L20.4463 15.484L3.83765 12.8923ZM22.9758 24.7729L22.9757 24.7728L17.3283 21.2334L16.8487 20.9328L17.2855 20.5729L21.0018 17.5116C21.0018 17.5116 21.0019 17.5115 21.0019 17.5115C21.173 17.3701 21.2997 17.1823 21.3666 16.9706C21.4336 16.7589 21.438 16.5324 21.3793 16.3183C21.3207 16.1041 21.2014 15.9115 21.0359 15.7635C20.8705 15.6156 20.6659 15.5185 20.4467 15.484L22.9758 24.7729ZM22.9758 24.7729C23.2351 24.9352 23.4192 25.1938 23.4878 25.4919C23.5563 25.79 23.5037 26.103 23.3414 26.3623C23.1791 26.6215 22.9205 26.8056 22.6224 26.8742C22.3245 26.9427 22.0115 26.8901 21.7523 26.7279L22.9758 24.7729Z" stroke="black" stroke-width="0.815817"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.7 KiB

View file

@ -0,0 +1,15 @@
<svg viewBox="0 0 33 34" fill="none" xmlns="http://www.w3.org/2000/svg">
<g>
<rect width="32" height="32" fill="transparent" transform="translate(1 1.5)"/>
<g>
<rect width="27.6335" height="27.6335" fill="transparent" transform="translate(0.640625 5.68311)"/>
<path d="M12.2974 7.4102C12.641 7.4102 12.9704 7.54667 13.2133 7.78959C13.4563 8.03251 13.5927 8.36198 13.5927 8.70552V19.4999C13.5927 19.7289 13.6837 19.9486 13.8457 20.1105C14.0076 20.2724 14.2273 20.3634 14.4563 20.3634C14.6853 20.3634 14.905 20.2724 15.0669 20.1105C15.2289 19.9486 15.3198 19.7289 15.3198 19.4999V15.1251L15.4684 15.1182C16.0159 15.0975 16.5685 15.1044 16.8777 15.1649C17.1091 15.2115 17.3854 15.3307 17.6514 15.4792C17.7844 15.5517 17.9105 15.7331 17.9105 16.0215V19.4999C17.9105 19.7289 18.0015 19.9486 18.1634 20.1105C18.3254 20.2724 18.545 20.3634 18.774 20.3634C19.0031 20.3634 19.2227 20.2724 19.3846 20.1105C19.5466 19.9486 19.6376 19.7289 19.6376 19.4999V16.797C19.6985 16.7906 19.7596 16.7848 19.8206 16.7797C20.3664 16.7383 20.8293 16.7624 21.0434 16.8488C21.2472 16.9282 21.5616 17.2063 21.8828 17.5914C22.0227 17.7572 22.1419 17.9196 22.2282 18.0388V20.3634C22.2282 20.5925 22.3192 20.8121 22.4811 20.974C22.6431 21.136 22.8627 21.227 23.0918 21.227C23.3208 21.227 23.5404 21.136 23.7024 20.974C23.8643 20.8121 23.9553 20.5925 23.9553 20.3634V18.6363H24.546C24.7874 18.6363 25.0261 18.6869 25.2467 18.7848C25.4673 18.8828 25.6649 19.0258 25.8268 19.2048C25.9888 19.3839 26.1114 19.5948 26.1867 19.8241C26.2621 20.0534 26.2886 20.296 26.2644 20.5361L25.7964 25.2252C25.736 25.8278 25.5494 26.4109 25.2489 26.9368L22.8396 31.1543C22.7641 31.2865 22.655 31.3964 22.5234 31.4728C22.3918 31.5492 22.2423 31.5895 22.0901 31.5896H11.0625C10.9203 31.5895 10.7803 31.5543 10.655 31.4871C10.5297 31.4199 10.4229 31.3228 10.3441 31.2044L7.86914 27.4912C7.63935 27.1468 7.49543 26.7523 7.44946 26.3409L6.85361 20.9783C6.82952 20.7634 6.88696 20.5472 7.01456 20.3726C7.14216 20.198 7.33064 20.0776 7.54272 20.0353L9.275 19.6899V21.227C9.275 21.456 9.36598 21.6756 9.52792 21.8376C9.68987 21.9995 9.90952 22.0905 10.1385 22.0905C10.3676 22.0905 10.5872 21.9995 10.7492 21.8376C10.9111 21.6756 11.0021 21.456 11.0021 21.227V8.70552C11.0021 8.36198 11.1386 8.03251 11.3815 7.78959C11.6244 7.54667 11.9539 7.4102 12.2974 7.4102V7.4102ZM15.3198 13.3963V8.70552C15.3198 7.90393 15.0014 7.13516 14.4346 6.56835C13.8678 6.00154 13.099 5.68311 12.2974 5.68311C11.4958 5.68311 10.7271 6.00154 10.1602 6.56835C9.59343 7.13516 9.275 7.90393 9.275 8.70552V17.9282L7.20248 18.3427C6.56722 18.4701 6.00273 18.8309 5.62036 19.3539C5.23799 19.877 5.06549 20.5243 5.13687 21.1683L5.73272 26.5326C5.80935 27.2184 6.04921 27.8757 6.4322 28.4497L8.90713 32.1629C9.14368 32.5178 9.46418 32.8088 9.84018 33.01C10.2162 33.2113 10.6361 33.3166 11.0625 33.3167H22.0901C22.5467 33.3165 22.9952 33.1957 23.3901 32.9664C23.785 32.7371 24.1122 32.4075 24.3387 32.011L26.748 27.7951C27.1692 27.0582 27.4305 26.2408 27.5149 25.3962L27.9829 20.7071C28.0309 20.2269 27.9778 19.742 27.8269 19.2836C27.6761 18.8252 27.4308 18.4035 27.107 18.0457C26.7832 17.6879 26.388 17.4019 25.9469 17.2061C25.5058 17.0104 25.0286 16.9093 24.546 16.9092H23.5425C23.4347 16.763 23.3224 16.6202 23.2058 16.4809C22.8759 16.0854 22.3249 15.4999 21.6859 15.2443C21.0572 14.9922 20.2248 15.0163 19.6859 15.0578L19.458 15.0785C19.2741 14.6078 18.9321 14.2158 18.4908 13.9697C18.0934 13.7406 17.6637 13.5729 17.2162 13.4723C16.6808 13.3652 15.9399 13.3721 15.4027 13.3929L15.3198 13.3963Z" fill-opacity="0.54"/>
</g>
<g >
<rect width="14" height="14" fill="transparent" transform="translate(15 0.683105)"/>
<path d="M23.7172 6.89409L23.7171 6.89407L23.7138 6.89751L23.19 7.4329C23.1898 7.4331 23.1896 7.43331 23.1894 7.43351C22.9725 7.65353 22.7581 7.89061 22.6072 8.21025C22.5038 8.42919 22.4371 8.67099 22.4047 8.95345H22.0954C22.1311 8.49095 22.3346 8.07169 22.6463 7.75567L22.6467 7.75533L23.367 7.02342C23.6645 6.73202 23.8398 6.32907 23.8398 5.89095C23.8398 5.00766 23.119 4.28678 22.2357 4.28678C21.5039 4.28678 20.8837 4.78151 20.6924 5.45345H20.3905C20.5879 4.61704 21.3387 3.99512 22.2357 3.99512C23.2832 3.99512 24.1315 4.84341 24.1315 5.89095C24.1315 6.2836 23.971 6.64029 23.7172 6.89409ZM22.2357 1.37012C18.7741 1.37012 15.9648 4.17933 15.9648 7.64095C15.9648 11.1026 18.7741 13.9118 22.2357 13.9118C25.6973 13.9118 28.5065 11.1026 28.5065 7.64095C28.5065 4.17933 25.6973 1.37012 22.2357 1.37012ZM22.0898 11.2868V10.9951H22.3815V11.2868H22.0898Z" fill-opacity="0.87" stroke="white" stroke-width="0.875"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.5 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 8.9 KiB

View file

@ -0,0 +1,15 @@
<svg viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
<g >
<rect width="32" height="32" fill="transparent"/>
<g opacity="0.5" >
<rect width="24.2141" height="24.2141" fill="transparent" transform="matrix(0.912552 0.40896 -0.408989 0.912539 15.2246 -3.63281)"/>
<path d="M18.7221 2.84405L18.7221 2.84411L29.3225 13.7986C29.3225 13.7986 29.3226 13.7987 29.3226 13.7987C29.4624 13.9435 29.5575 14.1256 29.5963 14.3232C29.6352 14.5207 29.6162 14.7253 29.5415 14.9123C29.4669 15.0993 29.3399 15.2608 29.1757 15.3774C29.0115 15.4939 28.8172 15.5606 28.6161 15.5694C28.616 15.5694 28.616 15.5694 28.616 15.5694L24.2534 15.7529L23.7405 15.7744L23.9232 16.2541L26.0744 21.9023L26.0745 21.9024C26.1733 22.1616 26.1652 22.4494 26.0518 22.7025C25.9385 22.9556 25.7292 23.1534 25.4701 23.2522C25.2109 23.3511 24.9231 23.343 24.67 23.2296C24.4169 23.1163 24.2192 22.9071 24.1203 22.648C24.1203 22.648 24.1203 22.6479 24.1203 22.6479L21.9705 17.0006L21.7878 16.5208L21.3905 16.8459L18.011 19.6106L18.0108 19.6108C17.8548 19.7385 17.6653 19.8184 17.465 19.8409C17.2647 19.8635 17.0622 19.8276 16.8818 19.7377C16.7014 19.6478 16.5509 19.5076 16.4483 19.3341C16.3457 19.1607 16.2955 18.9612 16.3036 18.7599C16.3036 18.7599 16.3036 18.7598 16.3036 18.7598L16.9259 3.52856L16.9259 3.52847C16.9342 3.32399 17.0024 3.12645 17.1219 2.96033C17.2414 2.79421 17.407 2.66681 17.5983 2.59394C17.7895 2.52107 17.9979 2.50593 18.1977 2.55038C18.3975 2.59484 18.5798 2.69695 18.7221 2.84405Z" stroke="black" stroke-width="0.739831"/>
</g>
<path fill-rule="evenodd" clip-rule="evenodd" d="M8.24907 5.52226C7.9014 5.38309 7.52053 5.34903 7.15369 5.42428C6.78684 5.49953 6.45014 5.68079 6.18534 5.9456C5.92054 6.2104 5.73928 6.54709 5.66403 6.91394C5.58877 7.28079 5.62284 7.66165 5.762 8.00932L13.4145 27.1406C13.5516 27.483 13.7848 27.7785 14.0859 27.9914C14.3871 28.2044 14.7434 28.3258 15.1119 28.3409C15.4804 28.3561 15.8455 28.2644 16.1631 28.0769C16.4807 27.8894 16.7374 27.6141 16.9021 27.2841L19.5423 22.0058L25.3161 27.7834C25.675 28.1421 26.1618 28.3436 26.6693 28.3434C27.1768 28.3432 27.6635 28.1414 28.0222 27.7824C28.3809 27.4235 28.5823 26.9367 28.5822 26.4292C28.582 25.9217 28.3802 25.4351 28.0212 25.0763L22.2455 19.2987L27.5257 16.6605C27.8551 16.4953 28.1297 16.2385 28.3167 15.921C28.5036 15.6035 28.5949 15.2388 28.5796 14.8706C28.5642 14.5025 28.4429 14.1466 28.2301 13.8458C28.0174 13.5449 27.7223 13.3119 27.3803 13.1748L8.24907 5.52226Z" fill-opacity="0.87"/>
<g opacity="0.3">
<path d="M3.83765 12.8923L3.83756 12.8922C3.6146 12.8574 3.38631 12.8887 3.18101 12.9824C2.9757 13.0761 2.8024 13.2279 2.68259 13.4192C2.56278 13.6104 2.50174 13.8326 2.50701 14.0582C2.51229 14.2838 2.58367 14.5029 2.71229 14.6883L2.71235 14.6884L12.2901 28.5028C12.2902 28.5029 12.2902 28.5029 12.2902 28.5029C12.4169 28.6855 12.5937 28.8275 12.7992 28.912C13.0048 28.9964 13.2305 29.0197 13.4489 28.9789C13.6674 28.9381 13.8695 28.835 14.0307 28.682C14.192 28.5291 14.3056 28.3328 14.3578 28.1167L14.3579 28.1165L15.4934 23.4376L15.6269 22.8875L16.1064 23.1882L21.7521 26.7278L3.83765 12.8923ZM3.83765 12.8923L20.4463 15.484L3.83765 12.8923ZM22.9758 24.7729L22.9757 24.7728L17.3283 21.2334L16.8487 20.9328L17.2855 20.5729L21.0018 17.5116C21.0018 17.5116 21.0019 17.5115 21.0019 17.5115C21.173 17.3701 21.2997 17.1823 21.3666 16.9706C21.4336 16.7589 21.438 16.5324 21.3793 16.3183C21.3207 16.1041 21.2014 15.9115 21.0359 15.7635C20.8705 15.6156 20.6659 15.5185 20.4467 15.484L22.9758 24.7729ZM22.9758 24.7729C23.2351 24.9352 23.4192 25.1938 23.4878 25.4919C23.5563 25.79 23.5037 26.103 23.3414 26.3623C23.1791 26.6215 22.9205 26.8056 22.6224 26.8742C22.3245 26.9427 22.0115 26.8901 21.7523 26.7279L22.9758 24.7729Z" stroke="black" stroke-width="0.815817"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.8 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 8.8 KiB

View file

@ -7,16 +7,18 @@ const CLICKRAGE = 'CLICKRAGE';
const IOS_VIEW = 'VIEW';
export const TYPES = { CONSOLE, CLICK, INPUT, LOCATION, CUSTOM, CLICKRAGE, IOS_VIEW };
export type EventType =
| typeof CONSOLE
| typeof CLICK
| typeof INPUT
| typeof LOCATION
| typeof CUSTOM
| typeof CLICKRAGE;
interface IEvent {
time: number;
timestamp: number;
type:
| typeof CONSOLE
| typeof CLICK
| typeof INPUT
| typeof LOCATION
| typeof CUSTOM
| typeof CLICKRAGE;
type: EventType
name: string;
key: number;
label: string;
@ -35,6 +37,7 @@ interface ConsoleEvent extends IEvent {
interface ClickEvent extends IEvent {
targetContent: string;
count: number;
hesitation: number;
}
interface InputEvent extends IEvent {
@ -98,12 +101,13 @@ export class Click extends Event {
readonly name = 'Click';
targetContent = '';
count: number;
hesitation: number = 0;
constructor(evt: ClickEvent, isClickRage?: boolean) {
console.log(evt);
super(evt);
this.targetContent = evt.targetContent;
this.count = evt.count;
this.hesitation = evt.hesitation;
if (isClickRage) {
this.type = CLICKRAGE;
}

View file

@ -1,6 +1,6 @@
import Record from 'Types/Record';
const types = {
export const types = {
ALL: 'all',
JS_EXCEPTION: 'js_exception',
BAD_REQUEST: 'bad_request',

View file

@ -2,12 +2,37 @@ import { Duration } from 'luxon';
import SessionEvent, { TYPES, EventData, InjectedEvent } from './event';
import StackEvent from './stackEvent';
import SessionError, { IError } from './error';
import Issue, { IIssue } from './issue';
import Issue, { IIssue, types as issueTypes } from './issue';
import { Note } from 'App/services/NotesService'
const HASH_MOD = 1610612741;
const HASH_P = 53;
function mergeEventLists(arr1: any[], arr2: any[]) {
let merged = [];
let index1 = 0;
let index2 = 0;
let current = 0;
while (current < (arr1.length + arr2.length)) {
let isArr1Depleted = index1 >= arr1.length;
let isArr2Depleted = index2 >= arr2.length;
if (!isArr1Depleted && (isArr2Depleted || (arr1[index1].timestamp < arr2[index2].timestamp))) {
merged[current] = arr1[index1];
index1++;
} else {
merged[current] = arr2[index2];
index2++;
}
current++;
}
return merged;
}
function hashString(s: string): number {
let mul = 1;
let hash = 0;
@ -158,6 +183,8 @@ export default class Session {
agentToken: ISession["agentToken"]
notes: ISession["notes"]
notesWithEvents: ISession["notesWithEvents"]
frustrations: Array<IIssue | InjectedEvent>
fileKey: ISession["fileKey"]
constructor(plainSession?: ISession) {
@ -217,8 +244,20 @@ export default class Session {
(i, k) => new Issue({ ...i, time: i.timestamp - startedAt, key: k })) || [];
const rawNotes = notes;
const notesWithEvents = [...rawEvents, ...rawNotes].sort((a, b) => {
// @ts-ignore just in case
const frustrationEvents = events.filter(ev => {
if (ev.type === TYPES.CLICK || ev.type === TYPES.INPUT) {
// @ts-ignore
return ev.hesitation > 1000
}
return ev.type === TYPES.CLICKRAGE
}
)
const frustrationIssues = issuesList.filter(i => i.type === issueTypes.MOUSE_THRASHING)
const frustrationList = [...frustrationEvents, ...frustrationIssues].sort((a, b) => {
// @ts-ignore
const aTs = a.timestamp || a.time;
// @ts-ignore
const bTs = b.timestamp || b.time;
@ -226,6 +265,11 @@ export default class Session {
return aTs - bTs;
}) || [];
const mixedEventsWithIssues = mergeEventLists(
mergeEventLists(rawEvents, rawNotes),
frustrationIssues
)
Object.assign(this, {
...session,
isIOS: session.platform === 'ios',
@ -255,7 +299,8 @@ export default class Session {
domURL,
devtoolsURL,
notes,
notesWithEvents: notesWithEvents,
notesWithEvents: mixedEventsWithIssues,
frustrations: frustrationList,
})
}
}

View file

@ -32,6 +32,8 @@ const plugins = (removeFill = true) => {
name: 'preset-default',
params: {
overrides: {
cleanupIds: false,
prefixIds: false,
inlineStyles: {
onlyMatchedOnce: false,
},
@ -63,12 +65,10 @@ const plugins = (removeFill = true) => {
]
}
}
// fs.promises.mkdir('/tmp/a/apple', { recursive: true })
// .then(() => {
fs.writeFileSync(`${UI_DIRNAME}/SVG.tsx`, `
fs.writeFileSync(`${UI_DIRNAME}/SVG.tsx`, `
import React from 'react';
export type IconNames = ${icons.map(icon => "'"+ icon.slice(0, -4) + "'").join(' | ')};
export type IconNames = ${icons.map((icon) => "'"+ icon.slice(0, -4) + "'").join(' | ')};
interface Props {
name: IconNames;
@ -88,10 +88,11 @@ ${icons.map(icon => {
const { data } = optimize(svg, plugins(canOptimize));
return ` case '${icon.slice(0, -4)}': return ${data.replace(/xlink\:href/g, 'xlinkHref')
.replace(/xmlns\:xlink/g, 'xmlnsXlink')
.replace(/clip-path/g, 'clipPath')
.replace(/clip-rule/g, 'clipRule')
.replace(/clip\-path/g, 'clipPath')
.replace(/clip\-rule/g, 'clipRule')
// hack to keep fill rule for some icons like stop recording square
.replace(/clipRule="evenoddCustomFill"/g, 'clipRule="evenodd" fillRule="evenodd"')
.replace(/fill-rule/g, 'fillRule')
.replace(/fill-opacity/g, 'fillOpacity')
.replace(/stop-color/g, 'stopColor')