Skip to content

Commit 44805d9

Browse files
committed
Merge branch 'master' into kevin/table
2 parents 2ae1555 + d2cf336 commit 44805d9

File tree

29 files changed

+469
-278
lines changed

29 files changed

+469
-278
lines changed

deployment/docker-compose.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,8 @@ services:
7575
MONGODB_URL: ${MONGODB_URL}
7676
BUCKET_NAME: ${BUCKET_NAME}
7777
USERS_SERVICE_URL: ${USERS_SERVICE_URL}
78+
INITIALIZATION_VECTOR: ${INITIALIZATION_VECTOR}
79+
ENCRYPTION_KEY: ${ENCRYPTION_KEY}
7880

7981
users:
8082
image: ghcr.io/peerprep/peerprep-users-service:latest

executor/src/exec_endpoint.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,9 +75,12 @@ cppevent::awaitable_task<void> executor::exec_endpoint::process(const cppevent::
7575
auto& lang = lang_opt.value();
7676
long content_len = cont.get_content_len();
7777
auto it = source_file_names.find(lang);
78-
if (it == source_file_names.end() || content_len == 0) {
78+
if (it == source_file_names.end()) {
7979
co_await o_stdout.write("status: 400\ncontent-length: 16\n\nunknown language");
8080
co_return;
81+
} else if (content_len == 0) {
82+
co_await o_stdout.write("status: 400\ncontent-length: 23\n\nNo source code provided");
83+
co_return;
8184
}
8285

8386
char dir_name[DIR_NAME_LEN];

frontend/package.json

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,16 +24,16 @@
2424
"@types/codemirror": "^5.60.10",
2525
"@types/node": "20.7.1",
2626
"@types/react": "18.2.31",
27-
"@types/react-dom": "18.2.7",
28-
"@uiw/react-codemirror": "^4.21.13",
27+
"@types/react-dom": "18.2.14",
28+
"@uiw/react-codemirror": "^4.21.20",
2929
"antd": "^5.10.2",
3030
"autoprefixer": "10.4.16",
31-
"bufferutil": "^4.0.7",
31+
"bufferutil": "^4.0.8",
3232
"daisyui": "^3.9.3",
3333
"encoding": "^0.1.13",
34-
"eslint": "8.51.0",
34+
"eslint": "8.52.0",
3535
"eslint-config-next": "^13.5.4",
36-
"firebase": "^10.4.0",
36+
"firebase": "^10.5.2",
3737
"firebase-admin": "^11.11.0",
3838
"jotai": "^2.4.3",
3939
"jotai-optics": "^0.3.1",

frontend/src/app/api/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ export const FetchAuth = {
3737
// Perform the fetch request with the modified options
3838
const res = await fetch(url, options);
3939
if (!res.ok) {
40-
console.log(res);
40+
// console.log(res);
4141
// throw Error();
4242
}
4343
return res;

frontend/src/app/components/button/QueueButton.tsx

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,13 @@ import { useState } from "react";
33
import useAccurateInterval from "../../hooks/useAccurateInterval";
44
import Button from "./Button";
55
import { RxCross1 } from "react-icons/rx";
6-
import { innkeeperWriteAtom } from "@/libs/room-jotai";
6+
import { innkeeperWriteAtom, isQueuingAtom } from "@/libs/room-jotai";
77
import { atom, useAtom, useSetAtom } from "jotai";
8+
import { notification } from "antd";
89

910
interface QueueButtonProps {
1011
enterQueue: () => void;
12+
selectedDifficulty: "EASY" | "MEDIUM" | "HARD";
1113
}
1214

1315
const triggerLeaveQueueAtom = atom(null, (get, set) => {
@@ -17,15 +19,32 @@ const triggerLeaveQueueAtom = atom(null, (get, set) => {
1719
});
1820
});
1921

20-
const QueueButton = ({ enterQueue }: QueueButtonProps) => {
22+
const QueueButton = ({ enterQueue, selectedDifficulty }: QueueButtonProps) => {
2123
const [time, setTime] = useState(0);
2224
const [isStarted, setIsStarted] = useState(false);
2325
const [_, handleLeaveQueue] = useAtom(triggerLeaveQueueAtom);
26+
const setIsQueueing = useSetAtom(isQueuingAtom);
27+
28+
const [api, contextHolder] = notification.useNotification();
29+
30+
const openNotification = () => {
31+
api.error({
32+
message: `Match not Found`,
33+
description: (
34+
<span>
35+
There appears to be no match for <b>{selectedDifficulty}</b> at this
36+
time. Please try again later or with another difficulty.
37+
</span>
38+
),
39+
placement: "top",
40+
});
41+
};
2442

2543
const handleClick = () => {
2644
setTime(0);
2745
if (isStarted) {
2846
handleLeaveQueue();
47+
setIsQueueing(false);
2948
} else {
3049
enterQueue();
3150
}
@@ -40,6 +59,8 @@ const QueueButton = ({ enterQueue }: QueueButtonProps) => {
4059
} else {
4160
handleLeaveQueue();
4261
setIsStarted(false);
62+
setIsQueueing(false);
63+
openNotification();
4364
}
4465
},
4566
isStarted ? 1000 : null,
@@ -56,6 +77,7 @@ const QueueButton = ({ enterQueue }: QueueButtonProps) => {
5677

5778
return (
5879
<div>
80+
{contextHolder}
5981
<Button
6082
className={`${isStarted ? "btn-accent" : "btn-success"} w-48`}
6183
onClick={handleClick}

frontend/src/app/components/code-editor/CodeEditor.tsx

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,20 @@
22
import {
33
codeLangAtom,
44
codeMirrorValueAtom,
5+
innkeeperWriteAtom,
56
isMatchedAtom,
67
} from "@/libs/room-jotai";
78
import { ExclamationCircleFilled } from "@ant-design/icons";
89
import { Button } from "antd";
9-
import { useAtom, useAtomValue, useSetAtom } from "jotai";
10+
import { atom, useAtom, useAtomValue, useSetAtom } from "jotai";
1011
import dynamic from "next/dynamic";
1112
import { useEffect, useState } from "react";
1213
import Skeleton from "react-loading-skeleton";
1314
import { yCollab } from "y-codemirror.next";
1415
import { SocketIOProvider } from "y-socket.io";
1516
import * as Y from "yjs";
1617
import Tabs from "../tab/Tabs";
18+
import { fetchProfileUrl } from "@/app/api";
1719

1820
const CodeMirror = dynamic(() => import("@uiw/react-codemirror"), {
1921
ssr: false,
@@ -32,18 +34,16 @@ if (typeof window !== "undefined") {
3234
desiredWidth = window.innerWidth >= 1024 ? "50vw" : "90vw";
3335
}
3436

35-
// TODO: idk what FE plan is for this, so i just slapped a random text box thing here.
36-
const UiElementOnClose = () => {
37-
return (
38-
<div className="flex items-center gap-4 bg-slate-800 p-2">
39-
<ExclamationCircleFilled />
40-
Your room has been closed.
41-
<Button className="btn-accent" onClick={() => window.location.reload()}>
42-
Restart
43-
</Button>
44-
</div>
45-
);
46-
};
37+
const codeLangAtomWrapper = atom(
38+
(get) => get(codeLangAtom),
39+
(_get, set, lang: string) => {
40+
set(codeLangAtom, lang);
41+
set(innkeeperWriteAtom, {
42+
eventName: "sendUpdate",
43+
eventArgs: [{ language: lang }],
44+
});
45+
},
46+
);
4747

4848
const CodeMirrorEditor = ({
4949
userId,
@@ -58,7 +58,7 @@ const CodeMirrorEditor = ({
5858
const setCodeMirrorValue = useSetAtom(codeMirrorValueAtom);
5959
const isMatched = useAtomValue(isMatchedAtom);
6060

61-
const [selectedLanguage, setSelectedLanguage] = useAtom(codeLangAtom);
61+
const [selectedLanguage, setSelectedLanguage] = useAtom(codeLangAtomWrapper);
6262
const [languageExtension, setLanguageExtension] = useState<any>(null);
6363
const [dragging, setDragging] = useState<boolean>(false);
6464
const [startY, setStartY] = useState<number>(0); // To track the Y position where drag started
@@ -67,6 +67,9 @@ const CodeMirrorEditor = ({
6767
const [extensions, setExtensions] = useState<any>([]);
6868

6969
useEffect(() => {
70+
fetchProfileUrl().then((res) => {
71+
setSelectedLanguage(res.payload.preferredLang || "python");
72+
});
7073
if (!innkeeperUrl) {
7174
console.error(
7275
"NEXT_PUBLIC_PEERPREP_INNKEEPER_SOCKET_URL not set in .env",
@@ -192,7 +195,6 @@ const CodeMirrorEditor = ({
192195
</select>
193196
</div>
194197
</div>
195-
{isMatched !== "MATCHED" && <UiElementOnClose />}
196198
<CodeMirror
197199
className="max-h-[70svw] w-[90svw] lg:w-[50svw]"
198200
height={`${editorHeight}px`}

frontend/src/app/components/matching/MatchingPage.tsx

Lines changed: 66 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,10 @@ import { useState } from "react";
33
import QueueButton from "../button/QueueButton";
44
import { QuestionType } from "../../admin/question/page";
55
import { atom, useAtom } from "jotai";
6-
import { innkeeperWriteAtom } from "@/libs/room-jotai";
6+
import { innkeeperWriteAtom, isQueuingAtom } from "@/libs/room-jotai";
77
import { fetchAllQuestionsDoneByUser } from "@/app/api";
88
import { useQuery } from "@tanstack/react-query";
9-
import { Skeleton, Table } from "antd";
9+
import { Skeleton, Table, notification } from "antd";
1010

1111
const sendMatchRequestAtom = atom(
1212
null,
@@ -23,9 +23,17 @@ const MatchingPage = () => {
2323
questionDifficulty: "EASY" | "MEDIUM" | "HARD",
2424
) => void = useAtom(sendMatchRequestAtom)[1];
2525

26+
const [isQueueing, setIsQueueing] = useAtom(isQueuingAtom);
27+
2628
const [difficulty, setDifficulty] = useState<"EASY" | "MEDIUM" | "HARD">(
2729
"EASY",
2830
);
31+
32+
const handleChangeDiff = (difficulty: "EASY" | "MEDIUM" | "HARD") => {
33+
if (!isQueueing) {
34+
setDifficulty(difficulty);
35+
}
36+
};
2937
const activityTableColumns: any = [
3038
{
3139
title: "Question",
@@ -105,55 +113,63 @@ const MatchingPage = () => {
105113
console.log({ allQuestions });
106114

107115
return (
108-
<main className="flex h-full flex-col items-center justify-center">
109-
<section className="flex items-center gap-4">
110-
<label>
111-
<span>Difficulty Setting:</span>
112-
</label>
113-
<div className="join">
114-
<button
115-
type="button"
116-
className={`btn btn-primary join-item text-white ${
117-
difficulty == "EASY" && "btn-success"
118-
}`}
119-
onClick={() => setDifficulty("EASY")}
120-
>
121-
Easy
122-
</button>
123-
<button
124-
type="button"
125-
className={`btn btn-primary join-item text-white ${
126-
difficulty == "MEDIUM" && "btn-warning"
127-
}`}
128-
onClick={() => setDifficulty("MEDIUM")}
129-
>
130-
Medium
131-
</button>
132-
<button
133-
type="button"
134-
className={`btn btn-primary join-item text-white ${
135-
difficulty == "HARD" && "btn-error"
136-
}`}
137-
onClick={() => setDifficulty("HARD")}
138-
>
139-
Hard
140-
</button>
116+
<>
117+
<main className="flex h-full flex-col items-center justify-center">
118+
<section className="flex items-center gap-4">
119+
<label>
120+
<span>Difficulty Setting:</span>
121+
</label>
122+
<div className="join">
123+
<button
124+
type="button"
125+
className={`btn btn-primary join-item text-white ${
126+
difficulty == "EASY" && "btn-success"
127+
}`}
128+
onClick={() => handleChangeDiff("EASY")}
129+
>
130+
Easy
131+
</button>
132+
<button
133+
type="button"
134+
className={`btn btn-primary join-item text-white ${
135+
difficulty == "MEDIUM" && "btn-warning"
136+
}`}
137+
onClick={() => handleChangeDiff("MEDIUM")}
138+
>
139+
Medium
140+
</button>
141+
<button
142+
type="button"
143+
className={`btn btn-primary join-item text-white ${
144+
difficulty == "HARD" && "btn-error"
145+
}`}
146+
onClick={() => handleChangeDiff("HARD")}
147+
>
148+
Hard
149+
</button>
150+
</div>
151+
<QueueButton
152+
enterQueue={() => {
153+
setIsQueueing(true);
154+
sendMatchRequest(difficulty);
155+
}}
156+
selectedDifficulty={difficulty}
157+
/>
158+
</section>
159+
<div className="m-7">
160+
<h1 className="mb-2 block text-5xl font-bold text-white underline">
161+
Completed Questions
162+
</h1>
163+
<Table
164+
className="mt-4"
165+
bordered
166+
columns={activityTableColumns}
167+
dataSource={allQuestions as any}
168+
pagination={{ position: ["bottomCenter"] }}
169+
/>
141170
</div>
142-
<QueueButton enterQueue={() => sendMatchRequest(difficulty)} />
143-
</section>
144-
<div className="m-7">
145-
<h1 className="mb-2 block text-5xl font-bold text-white underline">
146-
Completed Questions
147-
</h1>
148-
<Table
149-
className="mt-4"
150-
bordered
151-
columns={activityTableColumns}
152-
dataSource={allQuestions as any}
153-
pagination={{ position: ["bottomCenter"] }}
154-
/>
155-
</div>
156-
</main>
171+
</main>
172+
</>
157173
);
158174
};
159175

0 commit comments

Comments
 (0)