Skip to content

Commit b6a4489

Browse files
Task/3850 show error info (#872)
* full width error highlight * Separate stacktrace and code cards * fix button styling * red border' * error colors and intent/emphasis * use our colors for highlighted line * fix: style --------- Co-authored-by: Cahllagerfeld <[email protected]>
1 parent d27c493 commit b6a4489

File tree

3 files changed

+83
-24
lines changed

3 files changed

+83
-24
lines changed

src/components/CodeSnippet.tsx

Lines changed: 33 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ type DisplayCodeProps = {
1212
codeClasses?: string;
1313
language?: "python" | "bash" | "ts" | "dockerfile";
1414
copyCode?: string;
15+
exceptionCodeLine?: number;
1516
};
1617

1718
export function Codesnippet({
@@ -22,7 +23,8 @@ export function Codesnippet({
2223
className,
2324
codeClasses,
2425
language = "python",
25-
copyCode = code
26+
copyCode = code,
27+
exceptionCodeLine
2628
}: DisplayCodeProps) {
2729
const [copied, setCopied] = useState(false);
2830

@@ -39,27 +41,39 @@ export function Codesnippet({
3941
}
4042

4143
return (
42-
<div
43-
className={cn(
44-
`flex ${
45-
fullWidth ? "w-full" : "max-w-fit"
46-
} justify-between gap-4 rounded-md border border-theme-border-moderate bg-theme-surface-tertiary px-4 py-3 font-normal`,
47-
className
48-
)}
49-
>
50-
<pre
44+
<div className="relative w-full">
45+
<div
5146
className={cn(
52-
`${
53-
wrap ? "" : "whitespace-nowrap"
54-
} overflow-auto text-left font-mono text-theme-text-primary`,
55-
codeClasses
47+
`flex ${
48+
fullWidth ? "w-full" : "max-w-fit"
49+
} justify-between gap-4 rounded-md border border-theme-border-moderate bg-theme-surface-tertiary px-4 py-3 font-normal`,
50+
className
5651
)}
5752
>
58-
{highlightCode ? <CodeHighlighter language={language} code={code} /> : <code>{code}</code>}
59-
</pre>
60-
<button onClick={() => copyToClipboard(copyCode)}>
61-
{copied ? <p>Copied!</p> : <Copy className="fill-neutral-500" width={24} height={24} />}
62-
</button>
53+
<pre
54+
className={cn(
55+
`${
56+
wrap ? "" : "whitespace-nowrap"
57+
} overflow-auto text-left font-mono text-theme-text-primary`,
58+
codeClasses
59+
)}
60+
>
61+
{highlightCode ? (
62+
<CodeHighlighter language={language} code={code} />
63+
) : (
64+
<code>{code}</code>
65+
)}
66+
</pre>
67+
{exceptionCodeLine && (
68+
<div
69+
className="error-highlight-line pointer-events-none absolute left-0 h-[24px] w-full bg-error-50"
70+
style={{ top: `${24 * exceptionCodeLine + 17}px` }}
71+
></div>
72+
)}
73+
<button onClick={() => copyToClipboard(copyCode)}>
74+
{copied ? <p>Copied!</p> : <Copy className="fill-neutral-500" width={24} height={24} />}
75+
</button>
76+
</div>
6377
</div>
6478
);
6579
}

src/components/CollapsibleCard.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import { CopyMetadataButton } from "./copy-metadata-button";
1313
type CollapsibleCardProps = {
1414
initialOpen?: boolean;
1515
children: React.ReactNode;
16-
title: string | React.ReactNode;
16+
title: React.ReactNode;
1717
className?: string;
1818
contentClassName?: string;
1919
intent?: CollapsibleHeaderProps["intent"];
Lines changed: 49 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,68 @@
11
import { Codesnippet } from "@/components/CodeSnippet";
22
import { CollapsibleCard } from "@/components/CollapsibleCard";
33
import { useStepDetail } from "@/data/steps/step-detail-query";
4-
import { Skeleton } from "@zenml-io/react-component-library";
4+
import { Button, Skeleton } from "@zenml-io/react-component-library";
55
import { ErrorFallback } from "../../Error";
6+
import AlertCircle from "@/assets/icons/alert-circle.svg?react";
7+
import ArrowLeft from "@/assets/icons/arrow-left.svg?react";
68

79
type Props = {
810
stepId: string;
911
};
1012

13+
function goToError() {
14+
const errorLineElement = document.querySelector(".error-highlight-line");
15+
if (errorLineElement) {
16+
errorLineElement.scrollIntoView({ behavior: "smooth" });
17+
}
18+
}
19+
1120
export function StepCodeTab({ stepId }: Props) {
1221
const { data, isPending, isError, error } = useStepDetail({ stepId });
1322

1423
if (isError) return <ErrorFallback err={error} />;
1524

1625
if (isPending) return <Skeleton className="h-[300px] w-full" />;
1726

27+
const traceback = data?.metadata?.exception_info?.traceback;
28+
1829
return (
19-
<CollapsibleCard initialOpen title="Code">
20-
<Codesnippet fullWidth highlightCode wrap code={data?.metadata?.source_code || ""} />
21-
</CollapsibleCard>
30+
<div className="flex flex-col gap-5">
31+
{traceback && (
32+
<CollapsibleCard
33+
initialOpen
34+
title={
35+
<>
36+
<AlertCircle className="h-5 w-5 fill-theme-text-error" /> Error
37+
</>
38+
}
39+
contentClassName="border-t border-error-200"
40+
className="border border-error-200"
41+
headerClassName="flex justify-between"
42+
headerChildren={
43+
<Button
44+
className="whitespace-nowrap"
45+
onClick={goToError}
46+
intent="danger"
47+
emphasis="subtle"
48+
>
49+
Go to error
50+
<ArrowLeft className="h-5 w-5 -rotate-90 fill-error-700" />
51+
</Button>
52+
}
53+
>
54+
<div className="whitespace-pre-wrap font-mono text-text-md">{traceback}</div>
55+
</CollapsibleCard>
56+
)}
57+
<CollapsibleCard initialOpen title="Code">
58+
<Codesnippet
59+
fullWidth
60+
highlightCode
61+
wrap
62+
code={data?.metadata?.source_code || ""}
63+
exceptionCodeLine={data?.metadata?.exception_info?.step_code_line ?? undefined}
64+
/>
65+
</CollapsibleCard>
66+
</div>
2267
);
2368
}

0 commit comments

Comments
 (0)