Skip to content

Commit 852ab75

Browse files
authored
enable editor in gpu mode as beta in home page (#222)
enable editor in gpu mode as beta in home page
1 parent aa9ab21 commit 852ab75

File tree

5 files changed

+170
-20
lines changed

5 files changed

+170
-20
lines changed

frontend/src/api/api.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -452,7 +452,7 @@ export async function submitCode(
452452

453453
const details = payloadData?.details as Record<string, unknown> | undefined;
454454
const sub_id = (details?.id as number) || 0;
455-
console.log("Submission successful with sub_id", sub_id);
455+
console.log("Submission successful with details", details);
456456
return {
457457
sub_id
458458
};

frontend/src/pages/home/Home.test.tsx

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,20 @@ import { vi, expect, it, describe, beforeEach } from "vitest";
99
// Mock the API hook
1010
vi.mock("../../lib/hooks/useApi");
1111

12+
// Mock react-syntax-highlighter to avoid ESM issues
13+
vi.mock("react-syntax-highlighter", () => ({
14+
default: ({ children }: { children: string }) => <pre>{children}</pre>,
15+
Prism: ({ children }: { children: string }) => <pre>{children}</pre>,
16+
}));
17+
18+
vi.mock("react-syntax-highlighter/dist/esm/styles/prism", () => ({
19+
vscDarkPlus: {},
20+
}));
21+
1222
// Mock utility functions
1323
vi.mock("../../lib/date/utils", () => ({
1424
getTimeLeft: vi.fn(() => "2 days 5 hours remaining"),
25+
isExpired: vi.fn(() => false),
1526
}));
1627

1728
vi.mock("../../lib/utils/ranking", () => ({
@@ -41,6 +52,7 @@ describe("Home", () => {
4152
const mockHookReturn = {
4253
data: null,
4354
loading: true,
55+
hasLoaded: false,
4456
error: null,
4557
errorStatus: null,
4658
call: mockCall,
@@ -52,13 +64,18 @@ describe("Home", () => {
5264

5365
renderWithProviders(<Home />);
5466

55-
expect(screen.getByText(/Summoning/i)).toBeInTheDocument();
67+
// Page structure is visible during loading
68+
expect(screen.getByText("Leaderboards")).toBeInTheDocument();
69+
expect(screen.getByText("Submit your first kernel")).toBeInTheDocument();
70+
// Loading indicator is present
71+
expect(screen.getByRole("progressbar")).toBeInTheDocument();
5672
});
5773

5874
it("shows error message", () => {
5975
const mockHookReturn = {
6076
data: null,
6177
loading: false,
78+
hasLoaded: true,
6279
error: "Something went wrong",
6380
errorStatus: 500,
6481
call: mockCall,
@@ -78,6 +95,7 @@ describe("Home", () => {
7895
const mockHookReturn = {
7996
data: null,
8097
loading: false,
98+
hasLoaded: true,
8199
error: "Network error",
82100
errorStatus: null,
83101
call: mockCall,
@@ -117,6 +135,7 @@ describe("Home", () => {
117135
const mockHookReturn = {
118136
data: mockData,
119137
loading: false,
138+
hasLoaded: true,
120139
error: null,
121140
errorStatus: null,
122141
call: mockCall,
@@ -143,6 +162,7 @@ describe("Home", () => {
143162
const mockHookReturn = {
144163
data: mockData,
145164
loading: false,
165+
hasLoaded: true,
146166
error: null,
147167
errorStatus: null,
148168
call: mockCall,
@@ -202,6 +222,7 @@ describe("Home", () => {
202222
const mockHookReturn = {
203223
data: mockData,
204224
loading: false,
225+
hasLoaded: true,
205226
error: null,
206227
errorStatus: null,
207228
call: mockCall,
@@ -240,6 +261,7 @@ describe("Home", () => {
240261
const mockHookReturn = {
241262
data: mockData,
242263
loading: false,
264+
hasLoaded: true,
243265
error: null,
244266
errorStatus: null,
245267
call: mockCall,
@@ -273,6 +295,7 @@ describe("Home", () => {
273295
const mockHookReturn = {
274296
data: mockData,
275297
loading: false,
298+
hasLoaded: true,
276299
error: null,
277300
errorStatus: null,
278301
call: mockCall,
@@ -313,6 +336,7 @@ describe("Home", () => {
313336
const mockHookReturn = {
314337
data: mockData,
315338
loading: false,
339+
hasLoaded: true,
316340
error: null,
317341
errorStatus: null,
318342
call: mockCall,
@@ -351,6 +375,7 @@ describe("Home", () => {
351375
const mockHookReturn = {
352376
data: mockData,
353377
loading: false,
378+
hasLoaded: true,
354379
error: null,
355380
errorStatus: null,
356381
call: mockCall,
@@ -399,6 +424,7 @@ describe("Home", () => {
399424
const mockHookReturn = {
400425
data: mockData,
401426
loading: false,
427+
hasLoaded: true,
402428
error: null,
403429
errorStatus: null,
404430
call: mockCall,
@@ -439,6 +465,7 @@ describe("Home", () => {
439465
const mockHookReturn = {
440466
data: mockData,
441467
loading: false,
468+
hasLoaded: true,
442469
error: null,
443470
errorStatus: null,
444471
call: mockCall,
@@ -478,6 +505,7 @@ describe("Home", () => {
478505
const mockHookReturn = {
479506
data: mockData,
480507
loading: false,
508+
hasLoaded: true,
481509
error: null,
482510
errorStatus: null,
483511
call: mockCall,
@@ -528,6 +556,7 @@ describe("Home", () => {
528556
const mockHookReturn = {
529557
data: mockData,
530558
loading: false,
559+
hasLoaded: true,
531560
error: null,
532561
errorStatus: null,
533562
call: mockCall,
@@ -568,6 +597,7 @@ describe("Home", () => {
568597
const mockHookReturn = {
569598
data: mockData,
570599
loading: false,
600+
hasLoaded: true,
571601
error: null,
572602
errorStatus: null,
573603
call: mockCall,
@@ -610,6 +640,7 @@ describe("Home", () => {
610640
const mockHookReturn = {
611641
data: mockData,
612642
loading: false,
643+
hasLoaded: true,
613644
error: null,
614645
errorStatus: null,
615646
call: mockCall,
@@ -649,6 +680,7 @@ describe("Home", () => {
649680
const mockHookReturn = {
650681
data: mockData,
651682
loading: false,
683+
hasLoaded: true,
652684
error: null,
653685
errorStatus: null,
654686
call: mockCall,

frontend/src/pages/home/Home.tsx

Lines changed: 125 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,16 @@ import {
66
DialogContent,
77
DialogTitle,
88
Typography,
9+
List,
10+
ListItemButton,
11+
ListItemText,
12+
Stack,
13+
Chip,
914
} from "@mui/material";
15+
import CodeIcon from "@mui/icons-material/Code";
1016
import Grid from "@mui/material/Grid";
1117
import { useEffect, useState } from "react";
12-
import { useSearchParams } from "react-router-dom";
18+
import { useNavigate, useSearchParams } from "react-router-dom";
1319
import { fetchLeaderboardSummaries } from "../../api/api";
1420
import { fetcherApiCallback } from "../../lib/hooks/useApi";
1521
import { ErrorAlert } from "../../components/alert/ErrorAlert";
@@ -18,6 +24,8 @@ import Loading from "../../components/common/loading";
1824
import { ConstrainedContainer } from "../../components/app-layout/ConstrainedContainer";
1925
import MarkdownRenderer from "../../components/markdown-renderer/MarkdownRenderer";
2026
import quickStartMarkdown from "./quick-start.md?raw";
27+
import { isExpired, getTimeLeft } from "../../lib/date/utils";
28+
import { ColoredSquare } from "../../components/common/ColoredSquare";
2129

2230
interface TopUser {
2331
rank: number;
@@ -41,7 +49,9 @@ interface LeaderboardSummaries {
4149

4250
export default function Home() {
4351
const [searchParams] = useSearchParams();
52+
const navigate = useNavigate();
4453
const [isQuickStartOpen, setIsQuickStartOpen] = useState(false);
54+
const [isLeaderboardSelectOpen, setIsLeaderboardSelectOpen] = useState(false);
4555
const useBeta = searchParams.has("use_beta");
4656
const forceRefresh = searchParams.has("force_refresh");
4757

@@ -59,36 +69,137 @@ export default function Home() {
5969
}, [call, useBeta, forceRefresh]);
6070

6171
const leaderboards = data?.leaderboards || [];
72+
const activeLeaderboards = leaderboards.filter(
73+
(lb) => !isExpired(lb.deadline)
74+
);
75+
76+
const handleLeaderboardSelect = (id: number) => {
77+
setIsLeaderboardSelectOpen(false);
78+
navigate(`/leaderboard/${id}/editor`);
79+
};
6280

6381
return (
6482
<ConstrainedContainer>
6583
<Box>
6684
<Typography variant="h1" component="h1" sx={{ mb: 3 }}>
6785
Leaderboards
6886
</Typography>
69-
7087
<Box sx={{ mb: 4 }}>
71-
<Button
72-
variant="contained"
73-
onClick={() => setIsQuickStartOpen(true)}
74-
sx={{
75-
textTransform: "none",
76-
fontWeight: 500,
77-
px: 3,
78-
py: 1.5,
79-
}}
80-
>
88+
<Typography variant="h6" sx={{ mb: 1.5 }}>
8189
Submit your first kernel
82-
</Button>
90+
</Typography>
91+
<Stack direction={{ xs: "column", sm: "row" }} spacing={2}>
92+
<Button
93+
variant="contained"
94+
startIcon={<CodeIcon />}
95+
onClick={() => setIsLeaderboardSelectOpen(true)}
96+
sx={{
97+
textTransform: "none",
98+
fontWeight: 500,
99+
px: 3,
100+
py: 1.5,
101+
}}
102+
>
103+
Submit via browser
104+
<Chip
105+
label="beta"
106+
size="small"
107+
sx={{
108+
ml: 1,
109+
height: 20,
110+
fontSize: "0.7rem",
111+
bgcolor: "warning.main",
112+
color: "warning.contrastText",
113+
}}
114+
/>
115+
</Button>
116+
<Button
117+
variant="outlined"
118+
onClick={() => setIsQuickStartOpen(true)}
119+
sx={{
120+
textTransform: "none",
121+
fontWeight: 500,
122+
px: 3,
123+
py: 1.5,
124+
}}
125+
>
126+
Submit via cli
127+
</Button>
128+
</Stack>
83129
</Box>
84130

131+
{/* Leaderboard Selection Dialog */}
132+
<Dialog
133+
open={isLeaderboardSelectOpen}
134+
onClose={() => setIsLeaderboardSelectOpen(false)}
135+
maxWidth="sm"
136+
fullWidth
137+
sx={{
138+
"& .MuiDialog-paper": {
139+
maxHeight: { xs: "80vh", sm: "70vh" },
140+
},
141+
}}
142+
>
143+
<DialogTitle>Select an active leaderboard</DialogTitle>
144+
<DialogContent dividers sx={{ p: 0 }}>
145+
{activeLeaderboards.length > 0 ? (
146+
<List sx={{ width: "100%", py: 0 }}>
147+
{activeLeaderboards.map((lb) => (
148+
<ListItemButton
149+
key={lb.id}
150+
onClick={() => handleLeaderboardSelect(lb.id)}
151+
sx={{
152+
py: 1,
153+
px: { xs: 1.5, sm: 2 },
154+
borderBottom: "1px solid",
155+
borderColor: "divider",
156+
"&:last-child": { borderBottom: "none" },
157+
}}
158+
>
159+
<ListItemText
160+
primary={
161+
<Box sx={{ display: "flex", alignItems: "center" }}>
162+
<ColoredSquare name={lb.name} />
163+
{lb.name}
164+
</Box>
165+
}
166+
secondary={getTimeLeft(lb.deadline)}
167+
slotProps={{
168+
primary: {
169+
fontWeight: 500,
170+
fontSize: { xs: "0.9rem", sm: "0.95rem" },
171+
component: "div",
172+
},
173+
secondary: {
174+
fontSize: "0.8rem",
175+
},
176+
}}
177+
/>
178+
</ListItemButton>
179+
))}
180+
</List>
181+
) : (
182+
<Box sx={{ p: 3, textAlign: "center" }}>
183+
<Typography color="text.secondary">
184+
No active leaderboards available.
185+
</Typography>
186+
</Box>
187+
)}
188+
</DialogContent>
189+
<DialogActions>
190+
<Button onClick={() => setIsLeaderboardSelectOpen(false)}>
191+
Cancel
192+
</Button>
193+
</DialogActions>
194+
</Dialog>
195+
85196
<Dialog
86197
open={isQuickStartOpen}
87198
onClose={() => setIsQuickStartOpen(false)}
88199
maxWidth="md"
89200
fullWidth
90201
>
91-
<DialogTitle>Submit Your First Kernel</DialogTitle>
202+
<DialogTitle>Submit Your First Kernel via cli tool!</DialogTitle>
92203
<DialogContent dividers>
93204
<MarkdownRenderer content={quickStartMarkdown} />
94205
</DialogContent>

0 commit comments

Comments
 (0)