Skip to content

Commit 4b678b9

Browse files
committed
implement code execution form
1 parent 5b3e58c commit 4b678b9

File tree

4 files changed

+287
-3
lines changed

4 files changed

+287
-3
lines changed
Lines changed: 234 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,234 @@
1+
import React, { useState } from "react";
2+
import {
3+
TextField,
4+
Button,
5+
Grid,
6+
FormControl,
7+
InputLabel,
8+
Select,
9+
MenuItem,
10+
useTheme,
11+
Typography,
12+
Paper,
13+
Box,
14+
} from "@mui/material";
15+
import { useDispatch, useSelector } from "react-redux";
16+
import { executeCode } from "@app/store/mailAppReducer/actions";
17+
18+
const languages = [
19+
{ name: "JavaScript", judge0Id: 63 },
20+
{ name: "Python", judge0Id: 71 },
21+
{ name: "Java", judge0Id: 62 },
22+
{ name: "C++", judge0Id: 54 },
23+
{ name: "Ruby", judge0Id: 72 },
24+
{ name: "Go", judge0Id: 60 },
25+
{ name: "C", judge0Id: 50 },
26+
{ name: "C#", judge0Id: 51 },
27+
{ name: "Swift", judge0Id: 75 },
28+
{ name: "Kotlin", judge0Id: 78 },
29+
{ name: "R", judge0Id: 76 },
30+
{ name: "PHP", judge0Id: 68 },
31+
{ name: "TypeScript", judge0Id: 74 },
32+
{ name: "Rust", judge0Id: 73 },
33+
{ name: "Perl", judge0Id: 59 },
34+
{ name: "Haskell", judge0Id: 67 },
35+
{ name: "Scala", judge0Id: 66 },
36+
{ name: "Dart", judge0Id: 69 },
37+
{ name: "Lua", judge0Id: 70 },
38+
{ name: "Elixir", judge0Id: 64 },
39+
{ name: "Julia", judge0Id: 77 },
40+
{ name: "Objective-C", judge0Id: 61 },
41+
{ name: "COBOL", judge0Id: 56 },
42+
{ name: "Fortran", judge0Id: 55 },
43+
{ name: "PL/SQL", judge0Id: 65 },
44+
{ name: "VHDL", judge0Id: 57 },
45+
{ name: "Verilog", judge0Id: 58 },
46+
{ name: "Assembly", judge0Id: 53 },
47+
{ name: "MATLAB", judge0Id: 52 },
48+
{ name: "Ada", judge0Id: 74 },
49+
{ name: "Pascal", judge0Id: 58 },
50+
{ name: "Groovy", judge0Id: 19 },
51+
{ name: "F#", judge0Id: 12 },
52+
{ name: "Scheme", judge0Id: 18 },
53+
{ name: "Prolog", judge0Id: 7 },
54+
{ name: "Lisp", judge0Id: 9 },
55+
{ name: "Bash", judge0Id: 14 },
56+
{ name: "PowerShell", judge0Id: 52 },
57+
{ name: "Racket", judge0Id: 19 },
58+
{ name: "Smalltalk", judge0Id: 10 },
59+
{ name: "Erlang", judge0Id: 16 },
60+
{ name: "Clojure", judge0Id: 20 },
61+
{ name: "COOL", judge0Id: 13 },
62+
{ name: "D", judge0Id: 21 },
63+
{ name: "Eiffel", judge0Id: 22 },
64+
{ name: "Forth", judge0Id: 23 },
65+
{ name: "Haxe", judge0Id: 24 },
66+
{ name: "Io", judge0Id: 25 },
67+
{ name: "J", judge0Id: 26 },
68+
{ name: "JScript", judge0Id: 27 },
69+
{ name: "LabVIEW", judge0Id: 28 },
70+
{ name: "Objective-J", judge0Id: 29 },
71+
{ name: "OCaml", judge0Id: 30 },
72+
{ name: "OpenCL", judge0Id: 31 },
73+
{ name: "PigLatin", judge0Id: 32 },
74+
{ name: "PureScript", judge0Id: 33 },
75+
{ name: "Q#", judge0Id: 34 },
76+
{ name: "Red", judge0Id: 35 },
77+
{ name: "Ring", judge0Id: 36 },
78+
{ name: "Scala", judge0Id: 37 },
79+
{ name: "Scratch", judge0Id: 38 },
80+
{ name: "SQL", judge0Id: 39 },
81+
{ name: "Tcl", judge0Id: 40 },
82+
{ name: "UnrealScript", judge0Id: 41 },
83+
{ name: "V", judge0Id: 42 },
84+
{ name: "XSLT", judge0Id: 43 },
85+
{ name: "Zsh", judge0Id: 44 },
86+
{ name: "Ada", judge0Id: 45 },
87+
{ name: "ALGOL", judge0Id: 46 },
88+
{ name: "APL", judge0Id: 47 },
89+
{ name: "Awk", judge0Id: 48 },
90+
{ name: "DIBOL", judge0Id: 49 },
91+
{ name: "Dylan", judge0Id: 50 },
92+
{ name: "Euphoria", judge0Id: 51 },
93+
{ name: "Fjölnir", judge0Id: 52 },
94+
{ name: "Gosu", judge0Id: 53 },
95+
{ name: "Harbour", judge0Id: 54 },
96+
{ name: "Idris", judge0Id: 55 },
97+
{ name: "Joule", judge0Id: 56 },
98+
{ name: "Kaleidoscope", judge0Id: 57 },
99+
{ name: "Ladder Logic", judge0Id: 58 },
100+
{ name: "Leda", judge0Id: 59 },
101+
{ name: "LiveScript", judge0Id: 60 },
102+
{ name: "M4", judge0Id: 61 },
103+
{ name: "MAD", judge0Id: 62 },
104+
{ name: "Maple", judge0Id: 63 },
105+
{ name: "Max", judge0Id: 64 },
106+
{ name: "Mercury", judge0Id: 65 },
107+
{ name: "Mirah", judge0Id: 66 },
108+
{ name: "MIVA Script", judge0Id: 67 },
109+
{ name: "MOO", judge0Id: 68 },
110+
{ name: "MUMPS", judge0Id: 69 },
111+
{ name: "Napier88", judge0Id: 70 },
112+
{ name: "Neko", judge0Id: 71 },
113+
{ name: "Nemerle", judge0Id: 72 },
114+
{ name: "Nim", judge0Id: 73 },
115+
{ name: "Nu", judge0Id: 74 },
116+
{ name: "NWScript", judge0Id: 75 },
117+
{ name: "Oberon", judge0Id: 76 },
118+
{ name: "Object Rexx", judge0Id: 77 },
119+
{ name: "Occam", judge0Id: 78 },
120+
{ name: "OPL", judge0Id: 79 },
121+
{ name: "Pike", judge0Id: 80 },
122+
{ name: "Pizza", judge0Id: 81 },
123+
{ name: "Pop-11", judge0Id: 82 },
124+
{ name: "PostScript", judge0Id: 83 },
125+
{ name: "Promela", judge0Id: 84 },
126+
{ name: "Pure Data", judge0Id: 85 },
127+
{ name: "REBOL", judge0Id: 86 },
128+
{ name: "Redcode", judge0Id: 87 },
129+
{ name: "Refal", judge0Id: 88 },
130+
{ name: "Ring", judge0Id: 89 },
131+
{ name: "S-Lang", judge0Id: 90 },
132+
{ name: "Sather", judge0Id: 91 },
133+
{ name: "Sed", judge0Id: 92 },
134+
{ name: "Setl", judge0Id: 93 },
135+
{ name: "Shakespeare", judge0Id: 94 },
136+
{ name: "SIMSCRIPT", judge0Id: 95 },
137+
{ name: "Singularity", judge0Id: 96 },
138+
{ name: "SPARK", judge0Id: 97 },
139+
{ name: "Squeak", judge0Id: 98 },
140+
{ name: "Standard ML", judge0Id: 99 },
141+
{ name: "SuperCollider", judge0Id: 100 },
142+
{ name: "Turing", judge0Id: 101 },
143+
{ name: "Ubercode", judge0Id: 102 },
144+
{ name: "Umple", judge0Id: 103 },
145+
{ name: "Vala", judge0Id: 104 },
146+
{ name: "Vim script", judge0Id: 105 },
147+
{ name: "Visual Basic", judge0Id: 106 },
148+
{ name: "WebAssembly", judge0Id: 107 },
149+
{ name: "xBase", judge0Id: 108 },
150+
];
151+
152+
const MailCodeExecute = () => {
153+
const theme = useTheme();
154+
const dispatch = useDispatch();
155+
const { codeResult } = useSelector(({ mailApp }) => mailApp);
156+
157+
const [language, setLanguage] = useState("");
158+
const [code, setCode] = useState("");
159+
160+
const handleSubmit = (e) => {
161+
e.preventDefault();
162+
const judge0LanguageId = languages.find(
163+
(lang) => lang.name === language
164+
)?.judge0Id;
165+
166+
dispatch(executeCode({ code: code, language_id: judge0LanguageId }));
167+
};
168+
169+
return (
170+
<Box component="form" onSubmit={handleSubmit} m={20}>
171+
<Typography variant="h2" gutterBottom>
172+
Execute Code
173+
</Typography>{" "}
174+
{/* Heading */}
175+
<Grid container spacing={2}>
176+
<Grid item xs={12}>
177+
<FormControl
178+
fullWidth
179+
sx={{ margin: theme.spacing(1), minWidth: 120 }}
180+
>
181+
<InputLabel>Language</InputLabel>
182+
<Select
183+
value={language}
184+
label="Language"
185+
onChange={(e) => setLanguage(e.target.value)}
186+
>
187+
{languages.map((lang) => (
188+
<MenuItem
189+
key={lang.id}
190+
value={lang.name}
191+
sx={{
192+
color: theme.palette.text.primary,
193+
backgroundColor: theme.palette.background.paper,
194+
}}
195+
>
196+
{lang.name}
197+
</MenuItem>
198+
))}
199+
</Select>
200+
</FormControl>
201+
</Grid>
202+
<Grid item xs={12}>
203+
<TextField
204+
fullWidth
205+
label="Code"
206+
multiline
207+
rows={5}
208+
variant="outlined"
209+
sx={{ margin: theme.spacing(1), width: "100%" }}
210+
value={code}
211+
onChange={(e) => setCode(e.target.value)}
212+
/>
213+
</Grid>
214+
<Grid item xs={12} mt={10}>
215+
<Button type="submit" variant="contained" color="primary">
216+
Execute Code
217+
</Button>
218+
</Grid>
219+
</Grid>
220+
<Typography variant="h2" gutterBottom mt={10}>
221+
Result:
222+
</Typography>
223+
{codeResult && (
224+
<Box mt={3}>
225+
<Paper elevation={3} sx={{ padding: theme.spacing(2) }}>
226+
<Typography variant="h6">{codeResult}</Typography>
227+
</Paper>
228+
</Box>
229+
)}
230+
</Box>
231+
);
232+
};
233+
234+
export default MailCodeExecute;

src/components/MailDetail/index.jsx

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import Typography from "@mui/material/Typography";
1010
import ReplyMailForm from "./ReplyMailForm";
1111
import DetailHeader from "./DetailHeader";
1212
import MailReply from "./MailReply";
13+
import MailCodeExecute from "./MailCodeExecute";
1314
import IconButton from "@mui/material/IconButton";
1415
import PropTypes from "prop-types";
1516
import PerfectScrollbar from "react-perfect-scrollbar";
@@ -76,7 +77,11 @@ const MailDetail = ({ width, onClickForwardMail }) => {
7677
selectedMail;
7778

7879
return (
79-
<>
80+
<Box
81+
sx={{
82+
width: "100%",
83+
}}
84+
>
8085
<PerfectScrollbar
8186
style={{
8287
flex: 1,
@@ -206,9 +211,10 @@ const MailDetail = ({ width, onClickForwardMail }) => {
206211
threadId={selectedMail.thread_id}
207212
onClickReplyMail={onClickReplyMail}
208213
/>
214+
<MailCodeExecute />
209215
</Box>
210216
</PerfectScrollbar>
211-
</>
217+
</Box>
212218
);
213219
};
214220

src/store/mailAppReducer/actions/index.js

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -336,6 +336,29 @@ export const replyToMail = createAsyncThunk(
336336
}
337337
);
338338

339+
export const executeCode = createAsyncThunk(
340+
"mailbox/executeCode",
341+
async ({ code, language_id }, { rejectWithValue }) => {
342+
try {
343+
const config = {
344+
headers: {
345+
"Content-Type": "application/json",
346+
Authorization: JSON.parse(localStorage.getItem("token")),
347+
email: JSON.parse(localStorage.getItem("user")).email,
348+
},
349+
};
350+
const response = await axios.post(
351+
`${baseURL}/nylas/execute-code`,
352+
{ code, language_id },
353+
config
354+
);
355+
return response.data;
356+
} catch (error) {
357+
return rejectWithValue(error.response?.data || "Something went wrong");
358+
}
359+
}
360+
);
361+
339362
export const nullifySelectedMail = createAsyncThunk(
340363
"mailbox/nullifySelectedMail",
341364
async () => {

src/store/mailAppReducer/index.js

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import {
1919
getSelectedMail,
2020
updateSelectedMail,
2121
replyToMail,
22+
executeCode,
2223
searchEmails,
2324
nullifySelectedMail as nullifySelectedMailThunk,
2425
} from "./actions";
@@ -29,6 +30,7 @@ const initialState = {
2930
contactsList: [],
3031
allMailList: [],
3132
mailsList: [],
33+
codeResult: null,
3234
filterType: {
3335
selectedFolder: "inbox",
3436
selectedFilter: "",
@@ -40,6 +42,7 @@ const initialState = {
4042
totalMailCount: null,
4143
loading: {
4244
searchEmails: false,
45+
codeResult: false,
4346
isSideBarCollapsed: false,
4447
setFilterType: false,
4548
getLabelsList: false,
@@ -63,6 +66,7 @@ const initialState = {
6366
},
6467
error: {
6568
isSideBarCollapsed: null,
69+
codeResult: null,
6670
searchEmails: null,
6771
setFilterType: null,
6872
getLabelsList: null,
@@ -601,7 +605,7 @@ const mailAppReducer = createSlice({
601605
state.error.replyToMail = action.payload;
602606
});
603607

604-
// Async Thunk: replyToMail
608+
// Async Thunk: searchEmails
605609
builder
606610
.addCase(searchEmails.pending, (state) => {
607611
state.loading.searchEmails = true;
@@ -617,6 +621,23 @@ const mailAppReducer = createSlice({
617621
state.loading.searchEmails = false;
618622
state.error.searchEmails = "Something went wrong!";
619623
});
624+
625+
// Async Thunk: executeCode
626+
builder
627+
.addCase(executeCode.pending, (state) => {
628+
state.loading.codeResult = true;
629+
state.error.codeResult = null;
630+
})
631+
.addCase(executeCode.fulfilled, (state, action) => {
632+
state.loading.codeResult = false;
633+
if (action.payload) {
634+
state.codeResult = action.payload.stdout;
635+
}
636+
})
637+
.addCase(executeCode.rejected, (state, action) => {
638+
state.loading.codeResult = false;
639+
state.error.codeResult = "Something went wrong!";
640+
});
620641
},
621642
});
622643

0 commit comments

Comments
 (0)