feat(ui) - overview - error details modal
This commit is contained in:
parent
f3bf7be8cc
commit
8805c84735
8 changed files with 201 additions and 225 deletions
|
|
@ -2,82 +2,77 @@ import React from 'react';
|
|||
import { connect } from 'react-redux';
|
||||
import withSiteIdRouter from 'HOCs/withSiteIdRouter';
|
||||
import { errors as errorsRoute, error as errorRoute } from 'App/routes';
|
||||
import { NoContent , Loader, IconButton, Icon, Popup, BackLink, } from 'UI';
|
||||
import { NoContent, Loader, IconButton, Icon, Popup, BackLink } from 'UI';
|
||||
import { fetch, fetchTrace } from 'Duck/errors';
|
||||
import MainSection from './MainSection';
|
||||
import SideSection from './SideSection';
|
||||
import AnimatedSVG, { ICONS } from 'Shared/AnimatedSVG/AnimatedSVG';
|
||||
|
||||
@connect(state =>({
|
||||
errorIdInStore: state.getIn(["errors", "instance"]).errorId,
|
||||
loading: state.getIn([ "errors", "fetch", "loading" ]) || state.getIn([ "errors", "fetchTrace", "loading" ]),
|
||||
errorOnFetch: state.getIn(["errors", "fetch", "errors"]) || state.getIn([ "errors", "fetchTrace", "errors" ]),
|
||||
}), {
|
||||
fetch,
|
||||
fetchTrace,
|
||||
})
|
||||
@connect(
|
||||
(state) => ({
|
||||
errorIdInStore: state.getIn(['errors', 'instance']).errorId,
|
||||
loading: state.getIn(['errors', 'fetch', 'loading']) || state.getIn(['errors', 'fetchTrace', 'loading']),
|
||||
errorOnFetch: state.getIn(['errors', 'fetch', 'errors']) || state.getIn(['errors', 'fetchTrace', 'errors']),
|
||||
}),
|
||||
{
|
||||
fetch,
|
||||
fetchTrace,
|
||||
}
|
||||
)
|
||||
@withSiteIdRouter
|
||||
export default class ErrorInfo extends React.PureComponent {
|
||||
ensureInstance() {
|
||||
const { errorId, loading, errorOnFetch } = this.props;
|
||||
if (!loading &&
|
||||
this.props.errorIdInStore !== errorId &&
|
||||
errorId != null) {
|
||||
this.props.fetch(errorId);
|
||||
this.props.fetchTrace(errorId)
|
||||
}
|
||||
}
|
||||
componentDidMount() {
|
||||
this.ensureInstance();
|
||||
}
|
||||
componentDidUpdate() {
|
||||
this.ensureInstance();
|
||||
}
|
||||
next = () => {
|
||||
const { list, errorId } = this.props;
|
||||
const curIndex = list.findIndex(e => e.errorId === errorId);
|
||||
const next = list.get(curIndex + 1);
|
||||
if (next != null) {
|
||||
this.props.history.push(errorRoute(next.errorId))
|
||||
}
|
||||
}
|
||||
prev = () => {
|
||||
const { list, errorId } = this.props;
|
||||
const curIndex = list.findIndex(e => e.errorId === errorId);
|
||||
const prev = list.get(curIndex - 1);
|
||||
if (prev != null) {
|
||||
this.props.history.push(errorRoute(prev.errorId))
|
||||
}
|
||||
|
||||
}
|
||||
render() {
|
||||
const {
|
||||
loading,
|
||||
errorIdInStore,
|
||||
list,
|
||||
errorId,
|
||||
} = this.props;
|
||||
ensureInstance() {
|
||||
const { errorId, loading, errorOnFetch } = this.props;
|
||||
if (!loading && this.props.errorIdInStore !== errorId && errorId != null) {
|
||||
this.props.fetch(errorId);
|
||||
this.props.fetchTrace(errorId);
|
||||
}
|
||||
}
|
||||
componentDidMount() {
|
||||
this.ensureInstance();
|
||||
}
|
||||
componentDidUpdate() {
|
||||
this.ensureInstance();
|
||||
}
|
||||
next = () => {
|
||||
const { list, errorId } = this.props;
|
||||
const curIndex = list.findIndex((e) => e.errorId === errorId);
|
||||
const next = list.get(curIndex + 1);
|
||||
if (next != null) {
|
||||
this.props.history.push(errorRoute(next.errorId));
|
||||
}
|
||||
};
|
||||
prev = () => {
|
||||
const { list, errorId } = this.props;
|
||||
const curIndex = list.findIndex((e) => e.errorId === errorId);
|
||||
const prev = list.get(curIndex - 1);
|
||||
if (prev != null) {
|
||||
this.props.history.push(errorRoute(prev.errorId));
|
||||
}
|
||||
};
|
||||
render() {
|
||||
const { loading, errorIdInStore, list, errorId } = this.props;
|
||||
|
||||
let nextDisabled = true,
|
||||
prevDisabled = true;
|
||||
if (list.size > 0) {
|
||||
nextDisabled = loading || list.last().errorId === errorId;
|
||||
prevDisabled = loading || list.first().errorId === errorId;
|
||||
}
|
||||
let nextDisabled = true,
|
||||
prevDisabled = true;
|
||||
if (list.size > 0) {
|
||||
nextDisabled = loading || list.last().errorId === errorId;
|
||||
prevDisabled = loading || list.first().errorId === errorId;
|
||||
}
|
||||
|
||||
return (
|
||||
<NoContent
|
||||
title={
|
||||
<div className="flex flex-col items-center justify-center">
|
||||
<AnimatedSVG name={ICONS.EMPTY_STATE} size="170" />
|
||||
<div className="mt-6 text-2xl">No Error Found!</div>
|
||||
</div>
|
||||
}
|
||||
subtext="Please try to find existing one."
|
||||
// animatedIcon="no-results"
|
||||
show={ !loading && errorIdInStore == null }
|
||||
>
|
||||
{/* <div className="w-9/12 mb-4 flex justify-between">
|
||||
return (
|
||||
<NoContent
|
||||
title={
|
||||
<div className="flex flex-col items-center justify-center">
|
||||
<AnimatedSVG name={ICONS.EMPTY_STATE} size="170" />
|
||||
<div className="mt-6 text-2xl">No Error Found!</div>
|
||||
</div>
|
||||
}
|
||||
subtext="Please try to find existing one."
|
||||
// animatedIcon="no-results"
|
||||
show={!loading && errorIdInStore == null}
|
||||
>
|
||||
{/* <div className="w-9/12 mb-4 flex justify-between">
|
||||
<BackLink to={ errorsRoute() } label="Back" />
|
||||
<div />
|
||||
<div className="flex items-center">
|
||||
|
|
@ -111,13 +106,13 @@ export default class ErrorInfo extends React.PureComponent {
|
|||
</Popup>
|
||||
</div>
|
||||
</div> */}
|
||||
<div className="flex" >
|
||||
<Loader loading={ loading } className="w-9/12">
|
||||
<MainSection className="w-9/12" />
|
||||
<SideSection className="w-3/12" />
|
||||
</Loader>
|
||||
</div>
|
||||
</NoContent>
|
||||
);
|
||||
}
|
||||
}
|
||||
<div className="flex">
|
||||
<Loader loading={loading} className="w-9/12">
|
||||
<MainSection className="w-9/12" />
|
||||
<SideSection className="w-3/12" />
|
||||
</Loader>
|
||||
</div>
|
||||
</NoContent>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,105 +5,89 @@ import withSiteIdRouter from 'HOCs/withSiteIdRouter';
|
|||
import { ErrorDetails, IconButton, Icon, Loader, Button } from 'UI';
|
||||
import { sessions as sessionsRoute } from 'App/routes';
|
||||
import { TYPES as EV_FILER_TYPES } from 'Types/filter/event';
|
||||
import { UNRESOLVED, RESOLVED, IGNORED } from "Types/errorInfo";
|
||||
import { UNRESOLVED, RESOLVED, IGNORED } from 'Types/errorInfo';
|
||||
import { addFilterByKeyAndValue } from 'Duck/search';
|
||||
import { resolve,unresolve,ignore, toggleFavorite } from "Duck/errors";
|
||||
import { resolve, unresolve, ignore, toggleFavorite } from 'Duck/errors';
|
||||
import { resentOrDate } from 'App/date';
|
||||
import Divider from 'Components/Errors/ui/Divider';
|
||||
import ErrorName from 'Components/Errors/ui/ErrorName';
|
||||
import Label from 'Components/Errors/ui/Label';
|
||||
import SharePopup from 'Shared/SharePopup'
|
||||
import SharePopup from 'Shared/SharePopup';
|
||||
import { FilterKey } from 'Types/filter/filterType';
|
||||
|
||||
import SessionBar from './SessionBar';
|
||||
|
||||
@withSiteIdRouter
|
||||
@connect(state => ({
|
||||
error: state.getIn([ "errors", "instance" ]),
|
||||
trace: state.getIn([ "errors", "instanceTrace" ]),
|
||||
sourcemapUploaded: state.getIn([ "errors", "sourcemapUploaded" ]),
|
||||
resolveToggleLoading: state.getIn(["errors", "resolve", "loading"]) ||
|
||||
state.getIn(["errors", "unresolve", "loading"]),
|
||||
ignoreLoading: state.getIn([ "errors", "ignore", "loading" ]),
|
||||
toggleFavoriteLoading: state.getIn([ "errors", "toggleFavorite", "loading" ]),
|
||||
traceLoading: state.getIn([ "errors", "fetchTrace", "loading"]),
|
||||
}),{
|
||||
resolve,
|
||||
unresolve,
|
||||
ignore,
|
||||
toggleFavorite,
|
||||
addFilterByKeyAndValue,
|
||||
})
|
||||
@connect(
|
||||
(state) => ({
|
||||
error: state.getIn(['errors', 'instance']),
|
||||
trace: state.getIn(['errors', 'instanceTrace']),
|
||||
sourcemapUploaded: state.getIn(['errors', 'sourcemapUploaded']),
|
||||
resolveToggleLoading: state.getIn(['errors', 'resolve', 'loading']) || state.getIn(['errors', 'unresolve', 'loading']),
|
||||
ignoreLoading: state.getIn(['errors', 'ignore', 'loading']),
|
||||
toggleFavoriteLoading: state.getIn(['errors', 'toggleFavorite', 'loading']),
|
||||
traceLoading: state.getIn(['errors', 'fetchTrace', 'loading']),
|
||||
}),
|
||||
{
|
||||
resolve,
|
||||
unresolve,
|
||||
ignore,
|
||||
toggleFavorite,
|
||||
addFilterByKeyAndValue,
|
||||
}
|
||||
)
|
||||
export default class MainSection extends React.PureComponent {
|
||||
resolve = () => {
|
||||
const { error } = this.props;
|
||||
this.props.resolve(error.errorId)
|
||||
}
|
||||
resolve = () => {
|
||||
const { error } = this.props;
|
||||
this.props.resolve(error.errorId);
|
||||
};
|
||||
|
||||
unresolve = () => {
|
||||
const { error } = this.props;
|
||||
this.props.unresolve(error.errorId)
|
||||
}
|
||||
unresolve = () => {
|
||||
const { error } = this.props;
|
||||
this.props.unresolve(error.errorId);
|
||||
};
|
||||
|
||||
ignore = () => {
|
||||
const { error } = this.props;
|
||||
this.props.ignore(error.errorId)
|
||||
}
|
||||
bookmark = () => {
|
||||
const { error } = this.props;
|
||||
this.props.toggleFavorite(error.errorId);
|
||||
}
|
||||
ignore = () => {
|
||||
const { error } = this.props;
|
||||
this.props.ignore(error.errorId);
|
||||
};
|
||||
bookmark = () => {
|
||||
const { error } = this.props;
|
||||
this.props.toggleFavorite(error.errorId);
|
||||
};
|
||||
|
||||
findSessions = () => {
|
||||
this.props.addFilterByKeyAndValue(FilterKey.ERROR, this.props.error.message);
|
||||
this.props.history.push(sessionsRoute());
|
||||
}
|
||||
findSessions = () => {
|
||||
this.props.addFilterByKeyAndValue(FilterKey.ERROR, this.props.error.message);
|
||||
this.props.history.push(sessionsRoute());
|
||||
};
|
||||
|
||||
render() {
|
||||
const {
|
||||
error,
|
||||
trace,
|
||||
sourcemapUploaded,
|
||||
ignoreLoading,
|
||||
resolveToggleLoading,
|
||||
toggleFavoriteLoading,
|
||||
className,
|
||||
traceLoading,
|
||||
} = this.props;
|
||||
render() {
|
||||
const { error, trace, sourcemapUploaded, ignoreLoading, resolveToggleLoading, toggleFavoriteLoading, className, traceLoading } = this.props;
|
||||
|
||||
return (
|
||||
<div className={cn(className, "bg-white border-radius-3 thin-gray-border mb-6")} >
|
||||
<div className="m-4">
|
||||
<ErrorName
|
||||
className="text-lg leading-relaxed"
|
||||
name={ error.name }
|
||||
message={ error.stack0InfoString }
|
||||
lineThrough={ error.status === RESOLVED }
|
||||
/>
|
||||
<div className="flex justify-between items-center">
|
||||
<div className="flex items-center color-gray-dark" style={{ wordBreak: 'break-all'}}>
|
||||
{ error.message }
|
||||
</div>
|
||||
<div className="text-center">
|
||||
<div className="flex">
|
||||
<Label
|
||||
topValue={ error.sessions }
|
||||
topValueSize="text-lg"
|
||||
bottomValue="Sessions"
|
||||
/>
|
||||
<Label
|
||||
topValue={ error.users }
|
||||
topValueSize="text-lg"
|
||||
bottomValue="Users"
|
||||
/>
|
||||
</div>
|
||||
<div className="text-xs color-gray-medium">Over the past 30 days</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
return (
|
||||
<div className={cn(className, 'bg-white border-radius-3 thin-gray-border mb-6')}>
|
||||
<div className="m-4">
|
||||
<ErrorName
|
||||
className="text-lg leading-relaxed"
|
||||
name={error.name}
|
||||
message={error.stack0InfoString}
|
||||
lineThrough={error.status === RESOLVED}
|
||||
/>
|
||||
<div className="flex justify-between items-center">
|
||||
<div className="flex items-center color-gray-dark" style={{ wordBreak: 'break-all' }}>
|
||||
{error.message}
|
||||
</div>
|
||||
<div className="text-center">
|
||||
<div className="flex">
|
||||
<Label topValue={error.sessions} topValueSize="text-lg" bottomValue="Sessions" />
|
||||
<Label topValue={error.users} topValueSize="text-lg" bottomValue="Users" />
|
||||
</div>
|
||||
<div className="text-xs color-gray-medium">Over the past 30 days</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* <Divider />
|
||||
{/* <Divider />
|
||||
<div className="flex m-4">
|
||||
{ error.status === UNRESOLVED
|
||||
? <IconButton
|
||||
|
|
@ -158,35 +142,29 @@ export default class MainSection extends React.PureComponent {
|
|||
}
|
||||
/>
|
||||
</div> */}
|
||||
<Divider />
|
||||
<div className="m-4">
|
||||
<h3 className="text-xl inline-block mr-2">Last session with this error</h3>
|
||||
<span className="font-thin text-sm">{ resentOrDate(error.lastOccurrence) }</span>
|
||||
<SessionBar
|
||||
className="my-4"
|
||||
session={ error.lastHydratedSession }
|
||||
/>
|
||||
<Button
|
||||
variant="text-primary"
|
||||
onClick={ this.findSessions }
|
||||
>
|
||||
Find all sessions with this error
|
||||
<Icon className="ml-1" name="next1" color="teal" />
|
||||
</Button>
|
||||
</div>
|
||||
<Divider />
|
||||
<div className="m-4">
|
||||
<Loader loading={ traceLoading }>
|
||||
<ErrorDetails
|
||||
name={error.name}
|
||||
message={error.message}
|
||||
errorStack={trace}
|
||||
sourcemapUploaded={sourcemapUploaded}
|
||||
/>
|
||||
</Loader>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
<Divider />
|
||||
<div className="m-4">
|
||||
<h3 className="text-xl inline-block mr-2">Last session with this error</h3>
|
||||
<span className="font-thin text-sm">{resentOrDate(error.lastOccurrence)}</span>
|
||||
<SessionBar className="my-4" session={error.lastHydratedSession} />
|
||||
<Button variant="text-primary" onClick={this.findSessions}>
|
||||
Find all sessions with this error
|
||||
<Icon className="ml-1" name="next1" color="teal" />
|
||||
</Button>
|
||||
</div>
|
||||
<Divider />
|
||||
<div className="m-4">
|
||||
<Loader loading={traceLoading}>
|
||||
<ErrorDetails
|
||||
name={error.name}
|
||||
message={error.message}
|
||||
errorStack={trace}
|
||||
error={error}
|
||||
sourcemapUploaded={sourcemapUploaded}
|
||||
/>
|
||||
</Loader>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -64,7 +64,7 @@ export default class Exceptions extends React.PureComponent {
|
|||
show={ !loading && errorStack.size === 0 }
|
||||
title="Nothing found!"
|
||||
>
|
||||
<ErrorDetails error={ currentError.name } errorStack={errorStack} sourcemapUploaded={sourcemapUploaded} />
|
||||
<ErrorDetails error={ currentError } errorStack={errorStack} sourcemapUploaded={sourcemapUploaded} />
|
||||
</NoContent>
|
||||
</Loader>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -36,10 +36,10 @@ function OverviewPanel(props: Props) {
|
|||
};
|
||||
|
||||
return (
|
||||
<BottomBlock style={{ height: '260px' }}>
|
||||
<BottomBlock style={{ height: '263px' }}>
|
||||
<BottomBlock.Header>
|
||||
<span className="font-semibold color-gray-medium mr-4">Overview</span>
|
||||
<div className="flex items-center">
|
||||
<div className="flex items-center h-20">
|
||||
<FeatureSelection list={selectedFeatures} updateList={setSelectedFeatures} />
|
||||
</div>
|
||||
</BottomBlock.Header>
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ interface Props {
|
|||
endTime?: number;
|
||||
renderElement?: (item: any) => React.ReactNode;
|
||||
}
|
||||
function EventRow(props: Props) {
|
||||
const EventRow = React.memo((props: Props) => {
|
||||
const { title, className, list = [], endTime = 0 } = props;
|
||||
const scale = 100 / endTime;
|
||||
const _list = React.useMemo(() => {
|
||||
|
|
@ -22,8 +22,8 @@ function EventRow(props: Props) {
|
|||
})
|
||||
}, [list]);
|
||||
return (
|
||||
<div className={cn('h-20 w-full flex flex-col py-2 px-4', className)}>
|
||||
<div className="uppercase color-gray-medium">{title}</div>
|
||||
<div className={cn('w-full flex flex-col py-2', className)} style={{ height: '66px'}}>
|
||||
<div className="uppercase color-gray-medium ml-4">{title}</div>
|
||||
<div className="relative w-full py-3">
|
||||
{_list.map((item: any, index: number) => {
|
||||
return (
|
||||
|
|
@ -36,7 +36,7 @@ function EventRow(props: Props) {
|
|||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
export default connectPlayer((state: any) => ({
|
||||
endTime: state.endTime,
|
||||
|
|
|
|||
|
|
@ -2,16 +2,17 @@ import React from 'react';
|
|||
import { connectPlayer, Controls } from 'App/player';
|
||||
import { toggleBottomBlock, NETWORK, EXCEPTIONS, PERFORMANCE } from 'Duck/components/player';
|
||||
import { useModal } from 'App/components/Modal';
|
||||
import { Icon, ErrorDetails } from 'UI';
|
||||
import { Icon, ErrorDetails, Popup } from 'UI';
|
||||
import { Tooltip } from 'react-tippy';
|
||||
import { TYPES as EVENT_TYPES } from 'Types/session/event';
|
||||
import StackEventModal from '../StackEventModal';
|
||||
import ErrorDetailsModal from 'App/components/Dashboard/components/Errors/ErrorDetailsModal';
|
||||
|
||||
interface Props {
|
||||
pointer: any;
|
||||
type: any;
|
||||
}
|
||||
function TimelinePointer(props: Props) {
|
||||
const TimelinePointer = React.memo((props: Props) => {
|
||||
const { showModal, hideModal } = useModal();
|
||||
const createEventClickHandler = (pointer: any, type: any) => (e: any) => {
|
||||
e.stopPropagation();
|
||||
|
|
@ -20,8 +21,8 @@ function TimelinePointer(props: Props) {
|
|||
return;
|
||||
}
|
||||
|
||||
if (type === 'EXCEPTIONS') {
|
||||
showModal(<ErrorDetails error={pointer} />, { right: true });
|
||||
if (type === 'ERRORS') {
|
||||
showModal(<ErrorDetailsModal errorId={pointer.errorId} />, { right: true });
|
||||
}
|
||||
|
||||
if (type === 'EVENT') {
|
||||
|
|
@ -32,8 +33,8 @@ function TimelinePointer(props: Props) {
|
|||
|
||||
const renderNetworkElement = (item: any) => {
|
||||
return (
|
||||
<Tooltip
|
||||
html={
|
||||
<Popup
|
||||
content={
|
||||
<div className="">
|
||||
<b>{item.success ? 'Slow resource: ' : 'Missing resource:'}</b>
|
||||
<br />
|
||||
|
|
@ -46,14 +47,14 @@ function TimelinePointer(props: Props) {
|
|||
<div onClick={createEventClickHandler(item, NETWORK)} className="cursor-pointer">
|
||||
<div className="h-2 w-2 rounded-full bg-red" />
|
||||
</div>
|
||||
</Tooltip>
|
||||
</Popup>
|
||||
);
|
||||
};
|
||||
|
||||
const renderClickRageElement = (item: any) => {
|
||||
return (
|
||||
<Tooltip
|
||||
html={
|
||||
<Popup
|
||||
content={
|
||||
<div className="">
|
||||
<b>{'Click Rage'}</b>
|
||||
</div>
|
||||
|
|
@ -64,14 +65,14 @@ function TimelinePointer(props: Props) {
|
|||
<div onClick={createEventClickHandler(item, null)} className="cursor-pointer">
|
||||
<Icon className="bg-white" name="funnel/emoji-angry" color="red" size="16" />
|
||||
</div>
|
||||
</Tooltip>
|
||||
</Popup>
|
||||
);
|
||||
};
|
||||
|
||||
const renderStackEventElement = (item: any) => {
|
||||
return (
|
||||
<Tooltip
|
||||
html={
|
||||
<Popup
|
||||
content={
|
||||
<div className="">
|
||||
<b>{'Stack Event'}</b>
|
||||
</div>
|
||||
|
|
@ -82,15 +83,14 @@ function TimelinePointer(props: Props) {
|
|||
<div onClick={createEventClickHandler(item, 'EVENT')} className="cursor-pointer w-1 h-4 bg-red">
|
||||
{/* <Icon className="rounded-full bg-white" name="funnel/exclamation-circle-fill" color="red" size="16" /> */}
|
||||
</div>
|
||||
</Tooltip>
|
||||
</Popup>
|
||||
);
|
||||
};
|
||||
|
||||
const renderPerformanceElement = (item: any) => {
|
||||
console.log('item', item)
|
||||
return (
|
||||
<Tooltip
|
||||
html={
|
||||
<Popup
|
||||
content={
|
||||
<div className="">
|
||||
<b>{item.name}</b>
|
||||
</div>
|
||||
|
|
@ -101,14 +101,14 @@ function TimelinePointer(props: Props) {
|
|||
<div onClick={createEventClickHandler(item, EXCEPTIONS)} className="cursor-pointer w-1 h-4 bg-red">
|
||||
{/* <Icon className="rounded-full bg-white" name="funnel/exclamation-circle-fill" color="red" size="16" /> */}
|
||||
</div>
|
||||
</Tooltip>
|
||||
</Popup>
|
||||
);
|
||||
};
|
||||
|
||||
const renderExceptionElement = (item: any) => {
|
||||
return (
|
||||
<Tooltip
|
||||
html={
|
||||
<Popup
|
||||
content={
|
||||
<div className="">
|
||||
<b>{'Exception'}</b>
|
||||
<br />
|
||||
|
|
@ -118,10 +118,10 @@ function TimelinePointer(props: Props) {
|
|||
delay={0}
|
||||
position="top"
|
||||
>
|
||||
<div onClick={createEventClickHandler(item, EXCEPTIONS)} className="cursor-pointer">
|
||||
<div onClick={createEventClickHandler(item, 'ERRORS')} className="cursor-pointer">
|
||||
<Icon className="rounded-full bg-white" name="funnel/exclamation-circle-fill" color="red" size="16" />
|
||||
</div>
|
||||
</Tooltip>
|
||||
</Popup>
|
||||
);
|
||||
};
|
||||
|
||||
|
|
@ -145,6 +145,6 @@ function TimelinePointer(props: Props) {
|
|||
}
|
||||
};
|
||||
return <div>{render()}</div>;
|
||||
}
|
||||
});
|
||||
|
||||
export default TimelinePointer;
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ import CustomDragLayer from './CustomDragLayer';
|
|||
import { debounce } from 'App/utils';
|
||||
import { Tooltip } from 'react-tippy';
|
||||
|
||||
const BOUNDRY = 15;
|
||||
const BOUNDRY = 0;
|
||||
|
||||
function getTimelinePosition(value, scale) {
|
||||
const pos = value * scale;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import React, { useEffect, useState } from 'react';
|
||||
import ErrorFrame from '../ErrorFrame/ErrorFrame';
|
||||
import { fetchErrorStackList } from 'Duck/sessions';
|
||||
import { IconButton, Icon } from 'UI';
|
||||
import { Button, Icon } from 'UI';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
const docLink = 'https://docs.openreplay.com/installation/upload-sourcemaps';
|
||||
|
|
@ -46,8 +46,12 @@ function ErrorDetails(props: Props) {
|
|||
<div className="flex items-center my-3">
|
||||
<h3 className="text-xl mr-auto">Stacktrace</h3>
|
||||
<div className="flex justify-end mr-2">
|
||||
<IconButton onClick={() => setShowRaw(false)} label="FULL" plain={!showRaw} primaryText={!showRaw} />
|
||||
<IconButton primaryText={showRaw} onClick={() => setShowRaw(true)} plain={showRaw} label="RAW" />
|
||||
<Button variant={!showRaw ? 'text-primary' : 'text'} onClick={() => setShowRaw(false)}>
|
||||
FULL
|
||||
</Button>
|
||||
<Button variant={showRaw ? 'text-primary' : 'text'} onClick={() => setShowRaw(true)}>
|
||||
RAW
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
<div className="mb-6 code-font" data-hidden={showRaw}>
|
||||
|
|
@ -59,7 +63,6 @@ function ErrorDetails(props: Props) {
|
|||
{error.name} : {firstFunc ? firstFunc : '?'}
|
||||
</div>
|
||||
)}
|
||||
;
|
||||
{errorStack.map((frame: any, i: any) => (
|
||||
<div className="mb-3" key={frame.key}>
|
||||
<ErrorFrame frame={frame} showRaw={showRaw} isFirst={i == 0} />
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue