Skip to content

Commit 533b3c4

Browse files
committed
Merge branch 'main' of https://github.com/CS3219-AY2425S1/cs3219-ay2425s1-project-g15 into persist-language-change
2 parents 27904ab + c93470e commit 533b3c4

File tree

11 files changed

+119
-23
lines changed

11 files changed

+119
-23
lines changed

backend/collaboration/src/models/Session.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,10 @@ import mongoose, { Document, Schema } from "mongoose";
77
export type TSession = {
88
collabid: string;
99
users: [string];
10-
language: [string];
10+
language: string;
1111
question_id: number;
1212
code: string;
13+
createdAt: Date;
1314
};
1415

1516
// Document provides an id field
@@ -37,6 +38,10 @@ const sessionSchema: Schema = new Schema(
3738
type: String,
3839
required: false,
3940
},
41+
createdAt: {
42+
type: Date,
43+
required: false,
44+
}
4045
},
4146
{ collection: "sessions" }
4247
);

backend/collaboration/src/routes/collaborationRoutes.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ router.post(
4646
language,
4747
question_id,
4848
code: "",
49+
createdAt: new Date(),
4950
};
5051

5152
const newSession = new Session(session);
@@ -75,7 +76,7 @@ router.get("/sessions", async (req: Request, res: Response) => {
7576
router.post("/sessions/:id", async (req: Request, res: Response) => {
7677
try {
7778
const { id } = req.params;
78-
const sessions: TSession[] = await Session.find({ users: id }).exec();
79+
const sessions: TSession[] = await Session.find({ users: id }).sort({ createdAt: -1 }).exec();
7980

8081
return res.status(200).json(sessions);
8182
} catch (error) {

frontend/package-lock.json

Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

frontend/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
"class-variance-authority": "^0.7.0",
2929
"clsx": "^2.1.1",
3030
"cmdk": "^1.0.0",
31+
"date-fns": "^4.1.0",
3132
"dotenv": "^16.4.5",
3233
"framer-motion": "^11.9.0",
3334
"js-base64": "^3.7.7",

frontend/src/app/(home)/components/code-snippet/CodeSnippetHighlight.tsx

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,18 @@ import { useEffect, useState, useRef } from "react";
66

77
const CodeSnippetHighlight = () => {
88
const code = `
9-
class Solution:
10-
def twoSum(self, nums: List[int], target: int) -> List[int]:
11-
idxDict = {}
12-
for i, num in enumerate(nums):
13-
idxDict[num] = i
14-
15-
for i, num in enumerate(nums):
16-
diff = target - num
17-
if diff in idxDict and i != idxDict[diff]:
18-
return [i, idxDict[diff]]`;
9+
class Solution:
10+
def twoSum(self, nums: List[int], target: int) -> List[int]:
11+
idxDict = {}
12+
for i, num in enumerate(nums):
13+
idxDict[num] = i
14+
15+
for i, num in enumerate(nums):
16+
diff = target - num
17+
if diff in idxDict and i != idxDict[diff]:
18+
return [i, idxDict[diff]]
19+
20+
`;
1921

2022
const [displayedText, setDisplayedText] = useState(""); // Store the currently displayed text
2123
const currentCharIndexRef = useRef(0); // Track the current character index
@@ -52,7 +54,8 @@ const CodeSnippetHighlight = () => {
5254
borderRadius: "10px",
5355
}}
5456
>
55-
{displayedText}
57+
{displayedText}
58+
5659
</SyntaxHighlighter>
5760
);
5861
};

frontend/src/app/(home)/components/landing-page/LandingPage.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ const LandingPage = () => {
2727
return (
2828
<div className="flex flex-col min-h-full">
2929
<Navbar />
30-
<div className="grid grid-cols-2 gap-10 h-full items-center justify-center pl-10 pr-10">
30+
<div className="grid grid-cols-[1.45fr,1.55fr] gap-10 h-full items-center justify-center pl-10 pr-10">
3131
<div className="">
3232
<h1 className="text-6xl font-extrabold text-white pb-8">
3333
Collaborative Coding, <br></br> Competitive Results.

frontend/src/app/(user)/dashboard/components/DashboardDataTable.tsx

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ import {
1010
useReactTable,
1111
} from "@tanstack/react-table";
1212

13+
import { format } from 'date-fns';
14+
1315
import { Button } from "@/components/ui/button";
1416
import {
1517
Table,
@@ -92,6 +94,19 @@ export const columns: ColumnDef<TCombinedSession>[] = [
9294
);
9395
},
9496
},
97+
{
98+
accessorKey: "createdAt",
99+
header: () => <Cell>Date</Cell>,
100+
cell: ({ row }) => {
101+
const date: Date = row.getValue("createdAt");
102+
103+
return (
104+
<Cell>
105+
{format(date, 'dd-MM-yyyy HH:mm:ss')}
106+
</Cell>
107+
);
108+
},
109+
},
95110
{
96111
accessorKey: "collabid",
97112
header: () => <Cell>Collab Space</Cell>,
@@ -133,8 +148,8 @@ export function DashboardDataTable({ data }: { data: TCombinedSession[] }) {
133148
<div>
134149
<Table className="font-light">
135150
<TableHeader className="w-full">
136-
<TableRow className="text-white bg-primary-900 font-medium hover:bg-transparent h-[5rem] text-md">
137-
<TableCell colSpan={6} className="pl-10">
151+
<TableRow className="text-white w-full bg-primary-900 font-medium hover:bg-transparent h-[5rem] text-md">
152+
<TableCell colSpan={7} className="pl-10">
138153
Past Collaborations
139154
</TableCell>
140155
</TableRow>

frontend/src/app/collaboration/components/editor.tsx

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ function Collaboration({ room, language, code, setLanguage }: Readonly<Props>) {
2727
const [username, setUsername] = useState<string | null>(null);
2828
const [selectionRange, setSelectionRange] = useState(null);
2929
const [saving, setSaving] = useState(false);
30+
const [peerOnline, setPeerOnline] = useState(false);
3031
const [editorTheme, setEditorTheme] = useState("dark-plus");
3132

3233
// Fetch username on component mount
@@ -88,6 +89,35 @@ function Collaboration({ room, language, code, setLanguage }: Readonly<Props>) {
8889
}
8990
}, [code]);
9091

92+
useEffect(() => {
93+
const awarenessListener = ({
94+
added,
95+
removed,
96+
}: {
97+
added: number[];
98+
removed: number[];
99+
}) => {
100+
added.forEach((clientId) => {
101+
if (clientId !== providerRef.current?.awareness.clientID) {
102+
setPeerOnline(true);
103+
}
104+
});
105+
106+
removed.forEach((clientId) => {
107+
if (clientId !== providerRef.current?.awareness.clientID) {
108+
setPeerOnline(false);
109+
}
110+
}
111+
)
112+
};
113+
114+
providerRef.current?.awareness.on("change", awarenessListener);
115+
116+
return () => {
117+
providerRef.current?.awareness.off("change", awarenessListener);
118+
};
119+
}, [providerRef.current]);
120+
91121
async function initializeShiki(monaco: any, editor: any) {
92122
const highlighter = await createHighlighter({
93123
themes: ["dark-plus", "light-plus"],
@@ -179,6 +209,7 @@ function Collaboration({ room, language, code, setLanguage }: Readonly<Props>) {
179209
setTheme={setEditorTheme}
180210
saving={saving}
181211
room={room}
212+
peerOnline={peerOnline}
182213
/>
183214
<div className="w-full h-[1px] mx-auto my-2"></div>
184215
<Editor

frontend/src/app/collaboration/components/question.tsx

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -63,11 +63,12 @@ const Question = ({
6363
console.log(question);
6464

6565
const packageMessage = (message: SingleChatLogApiResponse): ChatLog => {
66+
const userId = getUserId();
6667
return {
6768
text: message.message,
68-
title: collaborator,
69+
title: message.senderId === userId ? username : collaborator,
6970
date: new Date(message.timestamp),
70-
position: message.senderId === getUserId() ? "right" : "left",
71+
position: message.senderId === userId ? "right" : "left",
7172
type: "text",
7273
};
7374
};
@@ -117,9 +118,22 @@ const Question = ({
117118
}, [collaboratorId]);
118119

119120
useEffect(() => {
121+
const scrollToPercentage = (percentage: number) => {
122+
if (chatLogsListRef.current && hasMoreMessages.current) {
123+
const chatContainer = chatLogsListRef.current;
124+
const targetPosition = chatContainer.scrollHeight * percentage;
125+
chatContainer.scrollTop = targetPosition - chatContainer.clientHeight;
126+
}
127+
};
128+
120129
const handleScroll = () => {
121130
if (chatLogsListRef.current && chatLogsListRef.current.scrollTop === 0) {
122-
fetchChatLogs();
131+
fetchChatLogs().then(() => {
132+
requestAnimationFrame(() => {
133+
const percentage = Math.min(1 - (chatLogsPage - 1) / chatLogsPage);
134+
scrollToPercentage(percentage);
135+
});
136+
});
123137
}
124138
};
125139

@@ -152,7 +166,9 @@ const Question = ({
152166
});
153167

154168
client.subscribe("/user/queue/language", (message) => {
155-
const messageReceived: SingleChatLogApiResponse = JSON.parse(message.body);
169+
const messageReceived: SingleChatLogApiResponse = JSON.parse(
170+
message.body
171+
);
156172
isLanguageChangeActive.current = false;
157173
setLanguage(messageReceived.message);
158174
Swal.fire({
@@ -360,7 +376,9 @@ const Question = ({
360376
</Button>
361377
</div>
362378
<span className="row-span-1 text-primary-300 text-md max-h-[100%] h-full overflow-y-auto flex flex-col gap-2 bg-primary-800 p-3 rounded-md">
363-
<span className="text-yellow-500 font-bold text-md">Question Description</span>
379+
<span className="text-yellow-500 font-bold text-md">
380+
Question Description
381+
</span>
364382
<span className="text-white py-2 text-xs">{question?.description}</span>
365383
<span className="text-yellow-500 font-bold text-md">Examples</span>
366384
{question?.examples?.map((example, idx) => (
@@ -394,7 +412,7 @@ const Question = ({
394412
className="mb-3"
395413
>
396414
{showAnswer ? "Hide" : "Show"} Answer
397-
{showAnswer ? " " : " "}
415+
{showAnswer ? " " : " "}
398416
</Button>
399417
{showAnswer && question?.solution && (
400418
<div className="h-[50px] text-sm">

frontend/src/app/collaboration/components/toolbar.tsx

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ type Props = {
1414
language: string;
1515
saving: boolean;
1616
setLanguage: (language: string) => void;
17+
peerOnline: boolean;
1718
theme: string;
1819
setTheme: (theme: string) => void;
1920
room: string;
@@ -29,7 +30,7 @@ type ThemeOption = {
2930
label: string;
3031
}
3132

32-
export function Toolbar({ editor, language, saving, setLanguage, theme, setTheme, room }: Props) {
33+
export function Toolbar({ editor, language, saving, setLanguage, peerOnline, theme, setTheme, room }: Readonly<Props>) {
3334
const languages: LanguageOption[] = [
3435
{ value: 'javascript', label: 'JavaScript' },
3536
{ value: 'python', label: 'Python' },
@@ -85,6 +86,15 @@ export function Toolbar({ editor, language, saving, setLanguage, theme, setTheme
8586
>
8687
<RedoIcon />
8788
</button>
89+
<div className="flex items-center justify-items-center mx-4">
90+
<div
91+
className={`${
92+
peerOnline ? 'bg-green' : 'bg-red'
93+
} text-black text-xs font-semibold px-2 py-1 rounded-2xl`}
94+
>
95+
{peerOnline ? "Peer Online" : "Peer Offline"}
96+
</div>
97+
</div>
8898
<div className="text-grey-300 h-6 py-1 px-2 ml-auto mr-2 gap-4 rounded-full text-xs flex items-center justify-center">
8999
{saving && (
90100
<div className="flex flex-row gap-1 items-center">

0 commit comments

Comments
 (0)