diff --git a/frontend/app/components/Session_/Exceptions/Exceptions.js b/frontend/app/components/Session_/Exceptions/Exceptions.js index d6e812b1e..334e57688 100644 --- a/frontend/app/components/Session_/Exceptions/Exceptions.js +++ b/frontend/app/components/Session_/Exceptions/Exceptions.js @@ -113,6 +113,7 @@ export default class Exceptions extends React.PureComponent { iconPosition="left" name="filter" onChange={this.onFilterChange} + height={28} /> 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 && ( - toggleBottomTools(EXCEPTIONS)} - active={bottomBlock === EXCEPTIONS && !inspectorMode} - label="EXCEPTIONS" - noIcon - labelClassName="!text-base font-semibold" - containerClassName="mx-2" - // count={exceptionsCount} - hasErrors={exceptionsCount > 0} - /> - )} {!live && showStack && ( 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" diff --git a/frontend/app/components/Session_/Player/Player.js b/frontend/app/components/Session_/Player/Player.js index 580a8a538..48d881c29 100644 --- a/frontend/app/components/Session_/Player/Player.js +++ b/frontend/app/components/Session_/Player/Player.js @@ -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 && } {bottomBlock === STORAGE && } - {bottomBlock === PROFILER && } + {bottomBlock === PROFILER && } {bottomBlock === PERFORMANCE && } {bottomBlock === GRAPHQL && } {bottomBlock === EXCEPTIONS && } diff --git a/frontend/app/components/Session_/Profiler/Profiler.js b/frontend/app/components/Session_/Profiler/Profiler.js index 1d9c8a5a3..398560a3d 100644 --- a/frontend/app/components/Session_/Profiler/Profiler.js +++ b/frontend/app/components/Session_/Profiler/Profiler.js @@ -51,6 +51,7 @@ export default class Profiler extends React.PureComponent { icon="search" name="filter" onChange={ this.onFilterChange } + height={28} /> diff --git a/frontend/app/components/shared/DevTools/ConsolePanel/ConsolePanel.tsx b/frontend/app/components/shared/DevTools/ConsolePanel/ConsolePanel.tsx index 53941c23d..361084221 100644 --- a/frontend/app/components/shared/DevTools/ConsolePanel/ConsolePanel.tsx +++ b/frontend/app/components/shared/DevTools/ConsolePanel/ConsolePanel.tsx @@ -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); diff --git a/frontend/app/components/shared/DevTools/ConsoleRow/ConsoleRow.tsx b/frontend/app/components/shared/DevTools/ConsoleRow/ConsoleRow.tsx index 16ea132b9..8e24e4c7b 100644 --- a/frontend/app/components/shared/DevTools/ConsoleRow/ConsoleRow.tsx +++ b/frontend/app/components/shared/DevTools/ConsoleRow/ConsoleRow.tsx @@ -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(, { right: true }); + }; return (
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)) : () => {} + } >
diff --git a/frontend/app/components/shared/DevTools/ProfilerModal/ProfilerModal.tsx b/frontend/app/components/shared/DevTools/ProfilerModal/ProfilerModal.tsx new file mode 100644 index 000000000..a5909ada7 --- /dev/null +++ b/frontend/app/components/shared/DevTools/ProfilerModal/ProfilerModal.tsx @@ -0,0 +1,26 @@ +import React from 'react'; + +interface Props { + profile: any; +} +function ProfilerModal(props: Props) { + const { + profile: { name, args, result }, + } = props; + + return ( +
+
{name}
+
{'Arguments'}
+
    + {args.split(',').map((arg: any) => ( +
  • {`${arg}`}
  • + ))} +
+
{'Result'}
+
{`${result}`}
+
+ ); +} + +export default ProfilerModal; diff --git a/frontend/app/components/shared/DevTools/ProfilerModal/index.ts b/frontend/app/components/shared/DevTools/ProfilerModal/index.ts new file mode 100644 index 000000000..dbb2c0fa8 --- /dev/null +++ b/frontend/app/components/shared/DevTools/ProfilerModal/index.ts @@ -0,0 +1 @@ +export { default } from './ProfilerModal'; diff --git a/frontend/app/components/shared/DevTools/ProfilerPanel/ProfilerPanel.tsx b/frontend/app/components/shared/DevTools/ProfilerPanel/ProfilerPanel.tsx new file mode 100644 index 000000000..f1fa16219 --- /dev/null +++ b/frontend/app/components/shared/DevTools/ProfilerPanel/ProfilerPanel.tsx @@ -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) => ; + +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(, { right: true }); + }; + return ( + + +
+ Profiler +
+ +
+ + + {[ + { + label: 'Name', + dataKey: 'name', + width: 200, + render: renderName, + }, + { + label: 'Time', + key: 'duration', + width: 80, + render: renderDuration, + }, + ]} + + +
+ ); +} + +export default connectPlayer((state: any) => { + return { + profiles: state.profilesList, + }; +})(ProfilerPanel); diff --git a/frontend/app/components/shared/DevTools/ProfilerPanel/index.ts b/frontend/app/components/shared/DevTools/ProfilerPanel/index.ts new file mode 100644 index 000000000..53bccddef --- /dev/null +++ b/frontend/app/components/shared/DevTools/ProfilerPanel/index.ts @@ -0,0 +1 @@ +export { default } from './ProfilerPanel'; diff --git a/frontend/app/types/session/log.js b/frontend/app/types/session/log.js index 4c24f9141..78b17340c 100644 --- a/frontend/app/types/session/log.js +++ b/frontend/app/types/session/log.js @@ -24,6 +24,7 @@ export default Record({ value: '', time: undefined, index: undefined, + errorId: undefined, }, { methods: { isRed() {