change(ui) - merge exceptions with console

This commit is contained in:
Shekar Siri 2022-10-13 14:19:31 +02:00
parent c47d06ae43
commit a708405fb8
11 changed files with 143 additions and 65 deletions

View file

@ -113,6 +113,7 @@ export default class Exceptions extends React.PureComponent {
iconPosition="left"
name="filter"
onChange={this.onFilterChange}
height={28}
/>
<QuestionMarkHint
className={'mx-4'}

View file

@ -8,7 +8,7 @@ import {
selectStorageListNow,
} from 'Player/store';
import LiveTag from 'Shared/LiveTag';
import { toggleTimetravel, jumpToLive } from 'Player';
import { jumpToLive } from 'Player';
import { Icon } from 'UI';
import { toggleInspectorMode } from 'Player';
@ -25,8 +25,6 @@ import {
PROFILER,
PERFORMANCE,
GRAPHQL,
FETCH,
EXCEPTIONS,
INSPECTOR,
} from 'Duck/components/player';
import { AssistDuration } from './Time';
@ -38,23 +36,6 @@ import styles from './controls.module.css';
import { Tooltip } from 'react-tippy';
import XRayButton from 'Shared/XRayButton';
function getStorageIconName(type) {
switch (type) {
case STORAGE_TYPES.REDUX:
return 'vendors/redux';
case STORAGE_TYPES.MOBX:
return 'vendors/mobx';
case STORAGE_TYPES.VUEX:
return 'vendors/vuex';
case STORAGE_TYPES.NGRX:
return 'vendors/ngrx';
case STORAGE_TYPES.ZUSTAND:
return 'vendors/zustand';
case STORAGE_TYPES.NONE:
return 'store';
}
}
const SKIP_INTERVALS = {
2: 2e3,
5: 5e3,
@ -95,7 +76,7 @@ function getStorageName(type) {
disabled: state.cssLoading || state.messagesLoading || state.inspectorMode || state.markedTargets,
inspectorMode: state.inspectorMode,
fullscreenDisabled: state.messagesLoading,
logCount: state.logList.length,
// logCount: state.logList.length,
logRedCount: state.logRedCount,
resourceRedCount: state.resourceRedCount,
fetchRedCount: state.fetchRedCount,
@ -111,8 +92,6 @@ function getStorageName(type) {
showFetch: state.fetchCount > 0,
fetchCount: state.fetchCount,
graphqlCount: state.graphqlList.length,
exceptionsCount: state.exceptionsList.length,
showExceptions: state.exceptionsList.length > 0,
showLongtasks: state.longtasksList.length > 0,
liveTimeTravel: state.liveTimeTravel,
}))
@ -163,7 +142,7 @@ export default class Controls extends React.Component {
nextProps.disabled !== this.props.disabled ||
nextProps.fullscreenDisabled !== this.props.fullscreenDisabled ||
// nextProps.inspectorMode !== this.props.inspectorMode ||
nextProps.logCount !== this.props.logCount ||
// nextProps.logCount !== this.props.logCount ||
nextProps.logRedCount !== this.props.logRedCount ||
nextProps.resourceRedCount !== this.props.resourceRedCount ||
nextProps.fetchRedCount !== this.props.fetchRedCount ||
@ -179,8 +158,6 @@ export default class Controls extends React.Component {
nextProps.showFetch !== this.props.showFetch ||
nextProps.fetchCount !== this.props.fetchCount ||
nextProps.graphqlCount !== this.props.graphqlCount ||
nextProps.showExceptions !== this.props.showExceptions ||
nextProps.exceptionsCount !== this.props.exceptionsCount ||
nextProps.showLongtasks !== this.props.showLongtasks ||
nextProps.liveTimeTravel !== this.props.liveTimeTravel ||
nextProps.skipInterval !== this.props.skipInterval
@ -286,24 +263,14 @@ export default class Controls extends React.Component {
skip,
speed,
disabled,
logCount,
logRedCount,
resourceRedCount,
fetchRedCount,
showStack,
stackCount,
stackRedCount,
profilesCount,
storageCount,
showStorage,
storageType,
showProfiler,
showGraphql,
showFetch,
fetchCount,
graphqlCount,
exceptionsCount,
showExceptions,
fullscreen,
inspectorMode,
closedLive,
@ -380,7 +347,6 @@ export default class Controls extends React.Component {
label="CONSOLE"
noIcon
labelClassName="!text-base font-semibold"
// count={logCount}
hasErrors={logRedCount > 0}
containerClassName="mx-2"
/>
@ -412,7 +378,6 @@ export default class Controls extends React.Component {
disabled={disabled && !inspectorMode}
onClick={() => toggleBottomTools(GRAPHQL)}
active={bottomBlock === GRAPHQL && !inspectorMode}
// count={graphqlCount}
label="GRAPHQL"
noIcon
labelClassName="!text-base font-semibold"
@ -424,26 +389,12 @@ export default class Controls extends React.Component {
disabled={disabled && !inspectorMode}
onClick={() => toggleBottomTools(STORAGE)}
active={bottomBlock === STORAGE && !inspectorMode}
// count={storageCount}
label={getStorageName(storageType)}
noIcon
labelClassName="!text-base font-semibold"
containerClassName="mx-2"
/>
)}
{showExceptions && (
<ControlButton
disabled={disabled && !inspectorMode}
onClick={() => toggleBottomTools(EXCEPTIONS)}
active={bottomBlock === EXCEPTIONS && !inspectorMode}
label="EXCEPTIONS"
noIcon
labelClassName="!text-base font-semibold"
containerClassName="mx-2"
// count={exceptionsCount}
hasErrors={exceptionsCount > 0}
/>
)}
{!live && showStack && (
<ControlButton
disabled={disabled && !inspectorMode}
@ -453,7 +404,6 @@ export default class Controls extends React.Component {
noIcon
labelClassName="!text-base font-semibold"
containerClassName="mx-2"
// count={stackCount}
hasErrors={stackRedCount > 0}
/>
)}
@ -462,7 +412,6 @@ export default class Controls extends React.Component {
disabled={disabled && !inspectorMode}
onClick={() => toggleBottomTools(PROFILER)}
active={bottomBlock === PROFILER && !inspectorMode}
// count={profilesCount}
label="PROFILER"
noIcon
labelClassName="!text-base font-semibold"

View file

@ -41,6 +41,7 @@ import stl from './player.module.css';
import { updateLastPlayedSession } from 'Duck/sessions';
import OverviewPanel from '../OverviewPanel';
import ConsolePanel from 'Shared/DevTools/ConsolePanel';
import ProfilerPanel from 'Shared/DevTools/ProfilerPanel';
@connectPlayer((state) => ({
live: state.live,
@ -116,7 +117,7 @@ export default class Player extends React.PureComponent {
)}
{bottomBlock === STACKEVENTS && <StackEvents />}
{bottomBlock === STORAGE && <Storage />}
{bottomBlock === PROFILER && <Profiler />}
{bottomBlock === PROFILER && <ProfilerPanel />}
{bottomBlock === PERFORMANCE && <ConnectedPerformance />}
{bottomBlock === GRAPHQL && <GraphQL />}
{bottomBlock === EXCEPTIONS && <Exceptions />}

View file

@ -51,6 +51,7 @@ export default class Profiler extends React.PureComponent {
icon="search"
name="filter"
onChange={ this.onFilterChange }
height={28}
/>
</BottomBlock.Header>
<BottomBlock.Content>

View file

@ -1,6 +1,6 @@
import React, { useState } from 'react';
import { connectPlayer, jump } from 'Player';
// import Log from 'Types/session/log';
import Log from 'Types/session/log';
import BottomBlock from '../BottomBlock';
import { LEVEL } from 'Types/session/log';
import { Tabs, Input, Icon, NoContent } from 'UI';
@ -124,8 +124,16 @@ function ConsolePanel(props: Props) {
export default connectPlayer((state: any) => {
const logs = state.logList;
// const exceptions = state.exceptionsList; // TODO merge
const exceptions = state.exceptionsList; // TODO merge
const logExceptions = exceptions.map(({ time, errorId, name, projectId }: any) =>
Log({
level: LEVEL.ERROR,
value: name,
time,
errorId,
})
);
return {
logs,
logs: logs.concat(logExceptions),
};
})(ConsolePanel);

View file

@ -3,6 +3,8 @@ import cn from 'classnames';
// import stl from '../console.module.css';
import { Icon } from 'UI';
import JumpButton from 'Shared/DevTools/JumpButton';
import { useModal } from 'App/components/Modal';
import ErrorDetailsModal from 'App/components/Dashboard/components/Errors/ErrorDetailsModal';
interface Props {
log: any;
@ -12,18 +14,30 @@ interface Props {
}
function ConsoleRow(props: Props) {
const { log, iconProps, jump, renderWithNL } = props;
const { showModal } = useModal();
const [expanded, setExpanded] = useState(false);
const lines = log.value.split('\n').filter((l: any) => !!l);
const canExpand = lines.length > 1;
const clickable = canExpand || !!log.errorId;
const onErrorClick = () => {
showModal(<ErrorDetailsModal errorId={log.errorId} />, { right: true });
};
return (
<div
className={cn('border-b flex items-center py-2 px-4 overflow-hidden group relative select-none', {
info: !log.isYellow() && !log.isRed(),
warn: log.isYellow(),
error: log.isRed(),
'cursor-pointer': canExpand,
})}
onClick={() => setExpanded(!expanded)}
className={cn(
'border-b flex items-center py-2 px-4 overflow-hidden group relative select-none',
{
info: !log.isYellow() && !log.isRed(),
warn: log.isYellow(),
error: log.isRed(),
'cursor-pointer': clickable,
}
)}
onClick={
clickable ? () => (!!log.errorId ? onErrorClick() : setExpanded(!expanded)) : () => {}
}
>
<div className="mr-2">
<Icon size="14" {...iconProps} />

View file

@ -0,0 +1,26 @@
import React from 'react';
interface Props {
profile: any;
}
function ProfilerModal(props: Props) {
const {
profile: { name, args, result },
} = props;
return (
<div className="bg-white overflow-y-auto h-screen p-5" style={{ width: '500px' }}>
<h5 className="mb-2 text-2xl">{name}</h5>
<h5 className="py-3">{'Arguments'}</h5>
<ul className="color-gray-medium">
{args.split(',').map((arg: any) => (
<li> {`${arg}`} </li>
))}
</ul>
<h5 className="py-3">{'Result'}</h5>
<div className="color-gray-medium">{`${result}`}</div>
</div>
);
}
export default ProfilerModal;

View file

@ -0,0 +1 @@
export { default } from './ProfilerModal';

View file

@ -0,0 +1,75 @@
import React, { useState } from 'react';
import { connectPlayer } from 'Player';
import { TextEllipsis, Input } from 'UI';
import { getRE } from 'App/utils';
// import ProfileInfo from './ProfileInfo';
import TimeTable from '../TimeTable';
import BottomBlock from '../BottomBlock';
import { useModal } from 'App/components/Modal';
import ProfilerModal from '../ProfilerModal';
const renderDuration = (p: any) => `${p.duration}ms`;
const renderName = (p: any) => <TextEllipsis text={p.name} />;
interface Props {
profiles: any;
}
function ProfilerPanel(props: Props) {
const { profiles } = props;
const { showModal } = useModal();
const [filter, setFilter] = useState('');
const filtered: any = React.useMemo(() => {
const filterRE = getRE(filter, 'i');
let list = profiles;
list = list.filter(({ name }: any) => (!!filter ? filterRE.test(name) : true));
return list;
}, [filter]);
const onFilterChange = ({ target: { value } }: any) => setFilter(value);
const onRowClick = (profile: any) => {
showModal(<ProfilerModal profile={profile} />, { right: true });
};
return (
<BottomBlock>
<BottomBlock.Header>
<div className="flex items-center">
<span className="font-semibold color-gray-medium mr-4">Profiler</span>
</div>
<Input
// className="input-small"
placeholder="Filter by name"
icon="search"
name="filter"
onChange={onFilterChange}
height={28}
/>
</BottomBlock.Header>
<BottomBlock.Content>
<TimeTable rows={filtered} onRowClick={onRowClick} hoverable>
{[
{
label: 'Name',
dataKey: 'name',
width: 200,
render: renderName,
},
{
label: 'Time',
key: 'duration',
width: 80,
render: renderDuration,
},
]}
</TimeTable>
</BottomBlock.Content>
</BottomBlock>
);
}
export default connectPlayer((state: any) => {
return {
profiles: state.profilesList,
};
})(ProfilerPanel);

View file

@ -0,0 +1 @@
export { default } from './ProfilerPanel';

View file

@ -24,6 +24,7 @@ export default Record({
value: '',
time: undefined,
index: undefined,
errorId: undefined,
}, {
methods: {
isRed() {