diff --git a/frontend/src/pages/leaderboard/LeaderboardEditor.tsx b/frontend/src/pages/leaderboard/LeaderboardEditor.tsx index e26ef832..6df68373 100644 --- a/frontend/src/pages/leaderboard/LeaderboardEditor.tsx +++ b/frontend/src/pages/leaderboard/LeaderboardEditor.tsx @@ -44,6 +44,17 @@ import { const DEFAULT_CODE = `# Write your code here`; +function isTerminalErrorStatus(status?: string | null) { + const v = typeof status === "string" ? status.toLowerCase() : ""; + return ( + v.includes("fail") || + v.includes("err") || + v.includes("hack") || + v.includes("timed") || + v.includes("timeout") + ); +} + export default function LeaderboardEditor() { const { id } = useParams<{ id: string }>(); const navigate = useNavigate(); @@ -428,8 +439,17 @@ export default function LeaderboardEditor() { )} {editorStatus.kind === "done" && ( - - Submission completed! + + {isTerminalErrorStatus(editorStatus.result.status) + ? `Submission completed with status: ${editorStatus.result.status}` + : "Submission completed!"} )} diff --git a/frontend/src/pages/leaderboard/components/editor/JobOutputPanel.tsx b/frontend/src/pages/leaderboard/components/editor/JobOutputPanel.tsx index 31c97aea..4a04e97d 100644 --- a/frontend/src/pages/leaderboard/components/editor/JobOutputPanel.tsx +++ b/frontend/src/pages/leaderboard/components/editor/JobOutputPanel.tsx @@ -8,7 +8,30 @@ interface JobOutputPanelProps { uploadStatus: SubmitStatus; } +function isTerminalErrorStatus(status?: string | null) { + const v = typeof status === "string" ? status.toLowerCase() : ""; + return ( + v.includes("fail") || + v.includes("err") || + v.includes("hack") || + v.includes("timed") || + v.includes("timeout") + ); +} + export function JobOutputPanel({ editorStatus, uploadStatus }: JobOutputPanelProps) { + const completedResult = + editorStatus.kind === "done" + ? editorStatus.result + : uploadStatus.kind === "done" + ? uploadStatus.result + : undefined; + const completedWithError = isTerminalErrorStatus(completedResult?.status); + const doneLabel = completedWithError + ? (completedResult?.status ?? "failed") + : "Done"; + const doneColor = completedWithError ? "error" : "success"; + return ( @@ -28,8 +51,8 @@ export function JobOutputPanel({ editorStatus, uploadStatus }: JobOutputPanelPro {(editorStatus.kind === "done" || uploadStatus.kind === "done") && ( } - label="Done" - color="success" + label={doneLabel} + color={doneColor} size="small" sx={{ height: 20, fontSize: "0.7rem" }} /> @@ -109,7 +132,7 @@ export function JobOutputPanel({ editorStatus, uploadStatus }: JobOutputPanelPro {editorStatus.kind === "done" && editorStatus.result && ( -
+
Submission #{editorStatus.submissionId} completed
{editorStatus.result.error && ( @@ -154,7 +177,16 @@ export function JobOutputPanel({ editorStatus, uploadStatus }: JobOutputPanelPro )} ))} -
$ Done
+
+ {completedWithError + ? `$ ${editorStatus.result.status ?? "failed"}` + : "$ Done"} +
)} diff --git a/frontend/src/pages/leaderboard/components/submission-history/SubmissionDoneCell.tsx b/frontend/src/pages/leaderboard/components/submission-history/SubmissionDoneCell.tsx index 08f3ccad..2a9601cd 100644 --- a/frontend/src/pages/leaderboard/components/submission-history/SubmissionDoneCell.tsx +++ b/frontend/src/pages/leaderboard/components/submission-history/SubmissionDoneCell.tsx @@ -1,8 +1,39 @@ import { Tooltip } from "@mui/material"; import CheckCircleOutlineIcon from "@mui/icons-material/CheckCircleOutline"; +import ErrorOutlineIcon from "@mui/icons-material/ErrorOutline"; import HourglassEmptyIcon from "@mui/icons-material/HourglassEmpty"; -function SubmissionDoneCell({ done }: { done: boolean }) { +function SubmissionDoneCell({ + done, + status, +}: { + done: boolean; + status?: string | null; +}) { + const v = typeof status === "string" ? status.toLowerCase() : ""; + const hasErrorStatus = + v.includes("fail") || + v.includes("err") || + v.includes("hack") || + v.includes("timed") || + v.includes("timeout"); + + if (!done) { + return ( + + + + ); + } + + if (hasErrorStatus) { + return ( + + + + ); + } + return done ? ( diff --git a/frontend/src/pages/leaderboard/components/submission-history/SubmissionHistorySection.tsx b/frontend/src/pages/leaderboard/components/submission-history/SubmissionHistorySection.tsx index 7ac1cb3a..34947acb 100644 --- a/frontend/src/pages/leaderboard/components/submission-history/SubmissionHistorySection.tsx +++ b/frontend/src/pages/leaderboard/components/submission-history/SubmissionHistorySection.tsx @@ -293,7 +293,10 @@ export default function SubmissionHistorySection({ - + {hasRuns ? ( diff --git a/frontend/src/pages/leaderboard/components/submission-history/SubmissionStatusChip.tsx b/frontend/src/pages/leaderboard/components/submission-history/SubmissionStatusChip.tsx index 2da80fa0..657b0d39 100644 --- a/frontend/src/pages/leaderboard/components/submission-history/SubmissionStatusChip.tsx +++ b/frontend/src/pages/leaderboard/components/submission-history/SubmissionStatusChip.tsx @@ -3,19 +3,27 @@ import { Chip, Tooltip } from "@mui/material"; function SubmissionStatusChip({ status }: { status?: string | null }) { const str = typeof status === "string" ? status : ""; // normalize const v = str.toLowerCase(); + const isSuccess = v.includes("ok") || v.includes("succ"); + const isRunning = v.includes("run"); + const isError = + v.includes("fail") || + v.includes("err") || + v.includes("hack") || + v.includes("timed") || + v.includes("timeout"); - const color: "default" | "success" | "warning" | "error" = v.includes("run") + const color: "default" | "success" | "warning" | "error" = isRunning ? "warning" - : v.includes("ok") || v.includes("succ") + : isSuccess ? "success" - : v.includes("fail") || v.includes("err") + : isError ? "error" : "default"; const showFallback = !str; const label = showFallback ? "via CLI/Discord bot" - : v.includes("ok") || v.includes("succ") + : isSuccess ? "finished" : v;