change(ui): change wording for error summary, add custom tags section
This commit is contained in:
parent
a166482227
commit
414bec8cc1
4 changed files with 146 additions and 103 deletions
|
|
@ -19,101 +19,138 @@ 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,
|
||||
}
|
||||
(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;
|
||||
const isPlayer = window.location.pathname.includes('/session/')
|
||||
render() {
|
||||
const {
|
||||
error,
|
||||
trace,
|
||||
sourcemapUploaded,
|
||||
ignoreLoading,
|
||||
resolveToggleLoading,
|
||||
toggleFavoriteLoading,
|
||||
className,
|
||||
traceLoading,
|
||||
} = this.props;
|
||||
const isPlayer = window.location.pathname.includes('/session/');
|
||||
|
||||
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 flex-col">
|
||||
<div className="flex items-center color-gray-dark font-semibold" style={{ wordBreak: 'break-all' }}>
|
||||
{error.message}
|
||||
</div>
|
||||
<div className="flex items-center mt-2">
|
||||
<div className="flex">
|
||||
<Label topValue={error.sessions} horizontal topValueSize="text-lg" bottomValue="Sessions" />
|
||||
<Label topValue={error.users} horizontal topValueSize="text-lg" bottomValue="Users" />
|
||||
</div>
|
||||
<div className="text-xs color-gray-medium">Over the past 30 days</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Divider />
|
||||
<div className="m-4">
|
||||
<div className="flex items-center">
|
||||
<h3 className="text-xl inline-block mr-2">Last session with this error</h3>
|
||||
<span className="font-thin text-sm">{resentOrDate(error.lastOccurrence)}</span>
|
||||
<Button className="ml-auto" variant="text-primary" onClick={this.findSessions}>
|
||||
Find all sessions with this error
|
||||
<Icon className="ml-1" name="next1" color="teal" />
|
||||
</Button>
|
||||
</div>
|
||||
<SessionBar className="my-4" session={error.lastHydratedSession} />
|
||||
{/* meta tags place */}
|
||||
</div>
|
||||
<Divider />
|
||||
<div className="m-4">
|
||||
<Loader loading={traceLoading}>
|
||||
<ErrorDetails
|
||||
name={error.name}
|
||||
message={error.message}
|
||||
errorStack={trace}
|
||||
error={error}
|
||||
sourcemapUploaded={sourcemapUploaded}
|
||||
/>
|
||||
</Loader>
|
||||
</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 flex-col">
|
||||
<div
|
||||
className="flex items-center color-gray-dark font-semibold"
|
||||
style={{ wordBreak: 'break-all' }}
|
||||
>
|
||||
{error.message}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
<div className="flex items-center mt-2">
|
||||
<div className="flex">
|
||||
<Label
|
||||
topValue={error.sessions}
|
||||
horizontal
|
||||
topValueSize="text-lg"
|
||||
bottomValue="Sessions"
|
||||
/>
|
||||
<Label
|
||||
topValue={error.users}
|
||||
horizontal
|
||||
topValueSize="text-lg"
|
||||
bottomValue="Users"
|
||||
/>
|
||||
</div>
|
||||
<div className="text-xs color-gray-medium">Over the past 30 days</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Divider />
|
||||
<div className="m-4">
|
||||
<div className="flex items-center">
|
||||
<h3 className="text-xl inline-block mr-2">Last session with this error</h3>
|
||||
<span className="font-thin text-sm">{resentOrDate(error.lastOccurrence)}</span>
|
||||
<Button className="ml-auto" variant="text-primary" onClick={this.findSessions}>
|
||||
Find all sessions with this error
|
||||
<Icon className="ml-1" name="next1" color="teal" />
|
||||
</Button>
|
||||
</div>
|
||||
<SessionBar className="my-4" session={error.lastHydratedSession} />
|
||||
{error.customTags ? (
|
||||
<div className="flex items-start flex-col">
|
||||
<div>
|
||||
<span className="font-semibold">More Info</span> (most recent call)
|
||||
</div>
|
||||
<div className="mt-4 flex items-center gap-3 w-full flex-wrap">
|
||||
{error.customTags.map((tag) => (
|
||||
<div className="flex items-center rounded overflow-hidden bg-gray-lightest">
|
||||
<div className="bg-gray-light-shade py-1 px-2 text-disabled-text">{Object.entries(tag)[0][0]}</div> <div className="py-1 px-2 text-gray-dark">{Object.entries(tag)[0][1]}</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
) : null}
|
||||
</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>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,12 +31,12 @@ function partitionsWrapper(partitions = [], mapCountry = false) {
|
|||
.sort((a, b) => b.count - a.count)
|
||||
.slice(0, showLength)
|
||||
.map(p => ({
|
||||
label: mapCountry
|
||||
? (countries[p.name] || "Unknown")
|
||||
label: mapCountry
|
||||
? (countries[p.name] || "Unknown")
|
||||
: p.name,
|
||||
prc: p.count/sum * 100,
|
||||
}))
|
||||
|
||||
|
||||
if (otherPrcsSum > 0) {
|
||||
show.push({
|
||||
label: "Other",
|
||||
|
|
@ -47,9 +47,9 @@ function partitionsWrapper(partitions = [], mapCountry = false) {
|
|||
return show;
|
||||
}
|
||||
function tagsWrapper(tags = []) {
|
||||
return tags.map(({ name, partitions }) => ({
|
||||
name,
|
||||
partitions: partitionsWrapper(partitions, name === "country")
|
||||
return tags.map(({ name, partitions }) => ({
|
||||
name,
|
||||
partitions: partitionsWrapper(partitions, name === "country")
|
||||
}))
|
||||
}
|
||||
|
||||
|
|
@ -59,7 +59,7 @@ function dataWrapper(data = {}) {
|
|||
chart30: data.chart30 || [],
|
||||
tags: tagsWrapper(data.tags),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@connect(state => ({
|
||||
error: state.getIn([ "errors", "instance" ])
|
||||
|
|
@ -75,7 +75,7 @@ export default class SideSection extends React.PureComponent {
|
|||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
const {
|
||||
className,
|
||||
error,
|
||||
data,
|
||||
|
|
@ -96,20 +96,20 @@ export default class SideSection extends React.PureComponent {
|
|||
timeFormat={'l'}
|
||||
/>
|
||||
<div className="mb-6" />
|
||||
<DateAgo
|
||||
<DateAgo
|
||||
className="my-4"
|
||||
title="First Seen"
|
||||
timestamp={ error.firstOccurrence }
|
||||
/>
|
||||
<DateAgo
|
||||
<DateAgo
|
||||
className="my-4"
|
||||
title="Last Seen"
|
||||
timestamp={ error.lastOccurrence }
|
||||
/>
|
||||
{ data.tags.length > 0 && <h4 className="text-xl mt-6 mb-3">Tags</h4> }
|
||||
{ data.tags.length > 0 && <h4 className="text-xl mt-6 mb-3">Summary</h4> }
|
||||
<Loader loading={loading}>
|
||||
{ data.tags.map(({ name, partitions }) =>
|
||||
<DistributionBar
|
||||
<DistributionBar
|
||||
key={ name }
|
||||
title={name}
|
||||
partitions={partitions}
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ const ErrorInfo = Record({
|
|||
chart24: [],
|
||||
chart30: [],
|
||||
tags: [],
|
||||
customTags: [],
|
||||
lastHydratedSession: Session(),
|
||||
disabled: false,
|
||||
}, {
|
||||
|
|
|
|||
|
|
@ -140,8 +140,13 @@ export function PageRenderTiming(
|
|||
return [Messages.Type.PageRenderTiming, speedIndex, visuallyComplete, timeToInteractive]
|
||||
}
|
||||
|
||||
export function JSException(name: string, message: string, payload: string): Messages.JSException {
|
||||
return [Messages.Type.JSException, name, message, payload]
|
||||
export function JSException(
|
||||
name: string,
|
||||
message: string,
|
||||
payload: string,
|
||||
metadata: string,
|
||||
): Messages.JSException {
|
||||
return [Messages.Type.JSException, name, message, payload, metadata]
|
||||
}
|
||||
|
||||
export function RawCustomEvent(name: string, payload: string): Messages.RawCustomEvent {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue