Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create release 1.3.0 #260

Merged
merged 46 commits into from
Nov 15, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
18599e2
Back-merge prod into master (#233)
yhtMinceraft1010X Nov 11, 2023
1a4c94d
Add @types for sanitize-html
yhtMinceraft1010X Nov 11, 2023
4f0f5b7
Update admin-service readme
yhtMinceraft1010X Nov 11, 2023
a4776c7
Remove unused import in frontend
yhtMinceraft1010X Nov 11, 2023
92045b3
linked room and user logic
ong6 Nov 11, 2023
ef21152
kick one user out the moment the other user leaves
ong6 Nov 11, 2023
c250df1
fixed bug
ong6 Nov 11, 2023
6e38480
fixed locked loading state
ong6 Nov 12, 2023
4aabdcb
Add timer to find-match
chunweii Nov 12, 2023
536b279
fixed small bugs and update user flow for question submission
ong6 Nov 12, 2023
6fcb29f
update code editor to allow for language change
ong6 Nov 12, 2023
e90f93a
Do not redirect if the router query is undefined
chunweii Nov 12, 2023
848a6b6
Merge remote-tracking branch 'origin/master'
chunweii Nov 12, 2023
0f83c36
Remove extra semicolon thanks to linter
chunweii Nov 12, 2023
defe45f
Fix swap question (#242)
chunweii Nov 12, 2023
d94259c
Fix duplicate sockets and display name in video (#247)
chunweii Nov 12, 2023
9bd3f10
Update root README
yhtMinceraft1010X Nov 12, 2023
2a69311
Merge branch 'prod' into master
yhtMinceraft1010X Nov 13, 2023
40cef62
Force image pull upon deployment
yhtMinceraft1010X Nov 13, 2023
9463e1e
Update matchingController and questionAdapter, add getDifficultyColor…
chunweii Nov 13, 2023
d418db5
Merge branch 'prod' into master
yhtMinceraft1010X Nov 13, 2023
1095896
fix: remove unused buttons
ckcherry23 Nov 13, 2023
54f04c5
style: increase text area height
ckcherry23 Nov 13, 2023
0038a52
style: fix admin page formatting
ckcherry23 Nov 13, 2023
fea973d
Increase CPU millicore request on prod
yhtMinceraft1010X Nov 14, 2023
f909d54
Merge branch 'prod' into master
yhtMinceraft1010X Nov 14, 2023
2154d5a
Add error toast for twilio connection errors
chunweii Nov 14, 2023
49fb0cc
Fix default code replacing empty string in form
chunweii Nov 14, 2023
a7c4796
Update question form and solution fields
chunweii Nov 14, 2023
6456c1b
fix cursor issues
ong6 Nov 14, 2023
6307604
Use monaco editor for question forms
chunweii Nov 14, 2023
64dea21
fix language issues on monaco
ong6 Nov 14, 2023
3cc2d5f
Merge branch 'master' of https://github.com/CS3219-AY2324S1/ay2324s1-…
ong6 Nov 14, 2023
5f3c0e2
Use monaco editor for attempt display
chunweii Nov 14, 2023
fbccce3
Merge remote-tracking branch 'origin/master'
chunweii Nov 14, 2023
8314d4e
implement text op
ong6 Nov 14, 2023
db4e3f8
Merge branch 'master' of https://github.com/CS3219-AY2324S1/ay2324s1-…
ong6 Nov 14, 2023
1b3fc09
style: increase z index of cancel search button
ckcherry23 Nov 14, 2023
d95a738
feat: add leaderboard api (#258)
ckcherry23 Nov 14, 2023
789f6d6
Merge branch 'master' of https://github.com/CS3219-AY2324S1/ay2324s1-…
ckcherry23 Nov 14, 2023
d012fcf
Update root README
yhtMinceraft1010X Nov 14, 2023
3ef6efb
feat: limit to top 10 in leaderboard
ckcherry23 Nov 14, 2023
46bc086
Merge branch 'master' of https://github.com/CS3219-AY2324S1/ay2324s1-…
ckcherry23 Nov 14, 2023
a1b6823
fix: lower limit test case size to 1 char
ckcherry23 Nov 14, 2023
2228814
feat: add error messages for invalid test cases
ckcherry23 Nov 15, 2023
135ff7e
Merge branch 'prod' into master
yhtMinceraft1010X Nov 15, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 29 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ Prerequisites for PeerPrep Monorepo:

3. **Node.js:** Check each application's documentation for the recommended
Node.js version.
4. **Git (Optional but Recommended):**
4. **Git**
5. **Docker (If deploying with Docker):**
6. **Kubernetes Tools (If deploying with Kubernetes):**

Expand Down Expand Up @@ -72,7 +72,8 @@ The difference between it and `FIREBASE_SERVICE_ACCOUNT` are shown below:
pip install pre-commit
pre-commit install
```

This step requires Git to be installed.

**Disclaimer:** There is no guarantee that all secrets will be detected.
As a tip, if you think a file will eventually store secrets, immediately add it to .gitignore upon creating
it in case you forget later on when you have a lot more files to commit.
Expand All @@ -92,8 +93,11 @@ it in case you forget later on when you have a lot more files to commit.

(if you have hadoop yarn installed)

If you want to use the exact `yarn.lock` versions without any modification, add a `--frozen-lockfile` flag to the
command.

This command will install dependencies for all services and the frontend in a
centralized `node_modules` directory at the root.
centralized `node_modules` directory at the root as well as within the respective directories.

4. **Adding Dependencies:** To add a dependency to a specific workspace (e.g.,
`user-service`), use:
Expand Down Expand Up @@ -155,11 +159,7 @@ yarn docker:devup
```
This will start all the containers.

3. **Once done, run yarn docker:devdown:** From the root repo, run
```bash
yarn docker:devdown
```
This will stop and delete all the containers.


#### If you want to do all the above steps at once, see the below section

Expand All @@ -172,14 +172,32 @@ This will stop and delete all the containers.
```
This will create new Docker images everytime it is run. Be careful of how much disk space you have left.

3. **Once done, run yarn docker:devdown:** From the root repo, run
```bash
yarn docker:devdown
```
This will stop and delete all the containers. You must run this to delete containers regardless of whether you used
`./start-app-with-docker.sh` or `yarn docker:devup`.

Any edits you make to the source code will not be automatically reflected on the site. We recommend using Docker
Compose to check if your changes are likely to work on the production environment once they have been proven to work
in your local development environment.

### Notes:
### Playing around with the app locally

- To test all features of the application, you will need 2 GitHub accounts.
- You must login on both accounts on the same computer, since the setup assumes that services are centralised
services just like in the production environment.
- You can do the login for your second account by opening a new browser tab in
incognito mode.

#### Note on NUS WiFi:

Access to remote databases may be blocked when using NUS WiFi. You will need a VPN to overcome this limitation if you
are running the local app on campus.

### Dependency Notes:

- After setting up Yarn Workspaces, any `node_modules` directories in individual
services or applications can be safely removed.
- Always ensure thorough testing after adding or updating dependencies to ensure
all parts of the system function as expected.

Expand Down
12 changes: 7 additions & 5 deletions frontend/src/components/interviews/leaderboard/columns.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,17 @@ import { Button } from "@/components/ui/button";
import { ColumnDef } from "@tanstack/react-table";

export type PublicUser = {
uid: string;
displayName: string;
attempts: number;
photoURL: string;
photoUrl: string;
};

const getInitials = (name: string) => {
const names = name.split(" ");
let initials = "";
names.forEach((n) => {
initials += n[0].toUpperCase();
initials += n[0]?.toUpperCase() || "";
});
return initials;
};
Expand All @@ -24,13 +25,14 @@ export const columns: ColumnDef<PublicUser>[] = [
header: "User",
cell: ({ row }) => {
const displayName = row.getValue("displayName") as string;
const photoURL = row.original.photoURL;
const photoURL = row.original.photoUrl;
const uid = row.original.uid;

return (
<Button
variant="ghost"
onClick={() => {
window.location.href = `/profile/Y4sCNQ4ZBqOlHjqoXmCAFAHnBWU2`;
window.location.href = `/profile/${uid}`;
}}
className="w-64"
>
Expand All @@ -47,7 +49,7 @@ export const columns: ColumnDef<PublicUser>[] = [
},
{
accessorKey: "attempts",
header: "Solved",
header: "Attempts",
invertSorting: true,
},
];
2 changes: 1 addition & 1 deletion frontend/src/components/interviews/loader.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
export default function Loader() {
return (
<div className="loader">
<div className="loader z-0">
<div className="box box0">
<div></div>
</div>
Expand Down
36 changes: 34 additions & 2 deletions frontend/src/components/room/code-editor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ type CodeEditorProps = {
hasRoom?: boolean;
onSubmitClick?: (param: string, solved: boolean) => void;
onLeaveRoomClick?: () => void;
onLanguageChange?: (param: string) => void;
};

export const languages = [
Expand Down Expand Up @@ -69,6 +70,7 @@ export default function CodeEditor({
hasRoom = true,
onSubmitClick = () => {},
onLeaveRoomClick = () => {},
onLanguageChange,
}: CodeEditorProps) {
const [open, setOpen] = React.useState(false);
const [value, setValue] = React.useState("");
Expand All @@ -82,6 +84,8 @@ export default function CodeEditor({
setMonacoInstance(editorL);
};

const [previousText, setPreviousText] = React.useState(text);

const setCursorPosition = React.useCallback(
(cursor: number) => {
if (!monacoInstance) return;
Expand All @@ -92,11 +96,33 @@ export default function CodeEditor({
[monacoInstance]
);

const updateCursorPosition = (prevText: any, newText: any) => {
if (!monacoInstance) return;
if (!cursor) return;
if (prevText.slice(0, cursor) !== newText.slice(0, cursor)) {
return true;
}
return false;
};

React.useEffect(() => {
if (cursor !== undefined) {
setCursorPosition(cursor);
console.log(cursor);
if (updateCursorPosition(previousText, text)) {
setCursorPosition(cursor + 1);
} else {
setCursorPosition(cursor);
}
}
}, [cursor, setCursorPosition]);

monacoInstance?.onDidChangeCursorPosition((e) => {
if (onCursorChange === undefined) return;
const cursor = monacoInstance
.getModel()!
.getOffsetAt(monacoInstance.getPosition()!);
onCursorChange(cursor);
});
}, [text, cursor, setCursorPosition, monacoInstance, onCursorChange]);

const editorOnChange = React.useCallback(
(value: string | undefined) => {
Expand All @@ -111,6 +137,7 @@ export default function CodeEditor({
onCursorChange(cursor);
}
onChange(value);
setPreviousText(value);
},
[onChange, onCursorChange, monacoInstance]
);
Expand Down Expand Up @@ -157,6 +184,11 @@ export default function CodeEditor({
setFrameWork(
currentValue === frameWork ? "" : currentValue
);
if (onLanguageChange) {
onLanguageChange(
currentValue === frameWork ? "" : currentValue
);
}
setOpen(false);
}}
>
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/components/room/solution.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export default function Solution({
<div className="pb-6 w-[43vw]">
<TypographySmall>
<SyntaxHighlighter language="python" style={vscDarkPlus} showLineNumbers wrapLines>
{ question.solution ? question.solution : `# Sample solution code to demo syntax highlighting.
{ question.solution?.python ? question.solution.python : `# Sample solution code to demo syntax highlighting.
import sys
class Solution(object):
def isValidBST(self, root):
Expand Down
1 change: 1 addition & 0 deletions frontend/src/hooks/useCollaboration.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ const useCollaboration = ({
setRoom(room);
})
.catch((err) => {
toast.error("An error occured when starting video: " + (err as Error).message);
console.log(err, token, userId, roomId);
});
});
Expand Down
17 changes: 17 additions & 0 deletions frontend/src/hooks/useLeaderboard.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { useContext } from "react";
import { AuthContext } from "@/contexts/AuthContext";
import {
getLeaderboard,
} from "@/pages/api/leaderboardHandler";

export const useLeaderboard = () => {
const { user: currentUser, authIsReady } = useContext(AuthContext);

const fetchLeaderboard = async () => {
if (authIsReady) {
return getLeaderboard(currentUser);
}
}

return { fetchLeaderboard };
};
31 changes: 31 additions & 0 deletions frontend/src/pages/api/leaderboardHandler.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { userApiPathAddress } from "@/gateway-address/gateway-address";

export const getLeaderboard = async (user: any) => {
try {
const url = `${userApiPathAddress}leaderboard`;
const idToken = await user.getIdToken(true);

const response = await fetch(url, {
method: "GET",
headers: {
"Content-Type": "application/json",
"User-Id-Token": idToken,
},
});

if (!response.ok) {
throw new Error(`Unable to get leaderboard: ${await response.text()}`);
}
return response.json().then((arr: Array<any>) => {
return arr.map((obj) => {
obj["time_saved_at"] = new Date(obj["time_saved_at"]);
obj["time_updated"] = new Date(obj["time_updated"]);
obj["time_created"] = new Date(obj["time_created"]);
return obj;
});
});
} catch (error) {
console.error("There was an error fetching the leaderboard", error);
throw error;
}
};
12 changes: 7 additions & 5 deletions frontend/src/pages/api/questionHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ export const fetchRandomQuestion = async (
difficulty: data.difficulty,
topics: data.topics,
description: data.content,
solution: "", // Not supported atm
solution: data.solution || {}, // Not supported atm
author: data.author, // Author id
defaultCode: {
...data.defaultCode
Expand Down Expand Up @@ -139,14 +139,14 @@ export const fetchQuestion = async (currentUser: User, questionId: string) => {
difficulty: data.difficulty,
topics: data.topics,
description: data.content,
solution: "", // Not supported atm
solution: data.solution || {}, // Not supported atm
author: data.author, // Author id
defaultCode: {
...data.defaultCode
},
testCasesInputs: data.testCasesInputs,
testCasesOutputs: data.testCasesOutputs
}
};
} catch (error) {
console.error("There was an error fetching the questions", error);
}
Expand All @@ -167,7 +167,8 @@ export const postQuestion = async (user: any, question: z.infer<typeof formSchem
content: question.description,
testCasesInputs: question.testCasesInputs,
testCasesOutputs: question.testCasesOutputs,
defaultCode: question.defaultCode
defaultCode: question.defaultCode,
solution: question.solution,
}),
headers: {
"Content-Type": "application/json",
Expand Down Expand Up @@ -199,7 +200,8 @@ export const putQuestion = async (user: any, question: z.infer<typeof formSchema
content: question.description,
testCasesInputs: question.testCasesInputs,
testCasesOutputs: question.testCasesOutputs,
defaultCode: question.defaultCode
defaultCode: question.defaultCode,
solution: question.solution,
}),
headers: {
"Content-Type": "application/json",
Expand Down
7 changes: 3 additions & 4 deletions frontend/src/pages/attempt/[id]/index.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { Button } from "@/components/ui/button";
import { Label } from "@/components/ui/label";
import { Textarea } from "@/components/ui/textarea";
import { TypographyBody, TypographyCode, TypographyH2 } from "@/components/ui/typography";
import { TypographyBody, TypographyH2 } from "@/components/ui/typography";
import { ArrowLeft } from "lucide-react";
import { useRouter } from "next/router";
import { useEffect, useState } from "react";
Expand All @@ -10,6 +9,7 @@ import { useHistory } from "@/hooks/useHistory";
import { useQuestions } from "@/hooks/useQuestions";
import { Question } from "@/types/QuestionTypes";
import { DotWave } from "@uiball/loaders";
import { Editor } from "@monaco-editor/react";

export default function Page() {
const router = useRouter();
Expand Down Expand Up @@ -84,8 +84,7 @@ export default function Page() {
<div>
<Label className="text-primary">Solution</Label>
<TypographyBody>{attempt?.solved ? "Solved": "Unsolved"}</TypographyBody>
<Textarea disabled={true} className="my-4" rows={10} defaultValue={attempt?.answer || ""}>
</Textarea>
<Editor className="my-4" height="50vh" defaultLanguage="plaintext" defaultValue={attempt?.answer || ""} options={{readOnly: true}} theme="vs-dark" />
</div></>}
</div>
)
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/pages/interviews/find-match.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ export default function FindMatch() {

<Loader />

<Button variant="secondary" onClick={onClickCancel}>
<Button className="z-50" variant="secondary" onClick={onClickCancel}>
Cancel Search
</Button>
</div>
Expand Down
Loading