Skip to content

Commit

Permalink
Merge pull request #142 from CS3219-AY2425S1/feat/live_collaboration
Browse files Browse the repository at this point in the history
Feat/code execution
  • Loading branch information
tyouwei authored Nov 6, 2024
2 parents f679fe6 + 2deeb27 commit b4dc7ba
Show file tree
Hide file tree
Showing 11 changed files with 989 additions and 911 deletions.
4 changes: 3 additions & 1 deletion peerprep-fe/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
"pre-commit": "pnpm format && git add -u"
},
"dependencies": {
"@fortawesome/fontawesome-svg-core": "^6.6.0",
"@fortawesome/free-solid-svg-icons": "^6.6.0",
"@fortawesome/react-fontawesome": "^0.2.2",
"@monaco-editor/react": "^4.6.0",
Expand All @@ -27,13 +28,15 @@
"@radix-ui/react-toast": "^1.2.2",
"@stomp/stompjs": "^7.0.0",
"@types/js-cookie": "^3.0.6",
"@types/jshint": "^2.12.4",
"@types/simple-peer": "^9.11.8",
"amqplib": "^0.10.4",
"axios": "^1.7.7",
"class-variance-authority": "^0.7.0",
"clsx": "^2.1.1",
"cmdk": "1.0.0",
"js-cookie": "^3.0.5",
"jshint": "^2.13.6",
"lucide-react": "^0.441.0",
"monaco-editor": "^0.52.0",
"next": "14.2.12",
Expand All @@ -47,7 +50,6 @@
"tailwindcss-animate": "^1.0.7",
"ws": "^8.18.0",
"y-monaco": "^0.1.6",
"y-webrtc": "^10.3.0",
"y-websocket": "^2.0.4",
"yjs": "^13.6.20",
"zustand": "5.0.0-rc.2"
Expand Down
1,476 changes: 688 additions & 788 deletions peerprep-fe/pnpm-lock.yaml

Large diffs are not rendered by default.

25 changes: 25 additions & 0 deletions peerprep-fe/src/app/collaboration/api/codeRunner.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { LANGUAGE_EXTENSION, LANGUAGE_VERSIONS } from '@/lib/constants';
import axios from 'axios';

const API = axios.create({
baseURL: 'https://emkc.org/api/v2/piston',
});

export const executeCode = async (language: string, sourceCode: string) => {
console.log(`Language executed: ${language}`);
const response = await API.post('/execute', {
language: language,
version: LANGUAGE_VERSIONS[language],
files: [
{
name: 'main.' + LANGUAGE_EXTENSION[language],
content: sourceCode,
},
],
stdin: '', // Add stdin field
args: [], // Add args field
compile_timeout: 10000, // Add compile timeout
run_timeout: 10000, // Add run timeout
});
return response.data.run.output;
};
54 changes: 54 additions & 0 deletions peerprep-fe/src/app/collaboration/components/AlertDialogues.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
'use client';

import {
AlertDialog,
AlertDialogAction,
AlertDialogCancel,
AlertDialogContent,
AlertDialogDescription,
AlertDialogFooter,
AlertDialogHeader,
AlertDialogTitle,
AlertDialogTrigger,
} from '@/components/ui/alert-dialog';
import { Button } from '@/components/ui/button';

interface LeaveSessionDialogProps {
onLeave: () => void;
triggerClassName?: string;
}

const LeaveSessionDialog = ({
onLeave,
triggerClassName = 'border border-amber-700/50 bg-amber-950/90 text-amber-100 hover:bg-amber-900/90',
}: LeaveSessionDialogProps) => {
return (
<AlertDialog>
<AlertDialogTrigger asChild>
<Button size="sm" className={triggerClassName}>
Leave Session
</Button>
</AlertDialogTrigger>
<AlertDialogContent className="bg-black">
<AlertDialogHeader>
<AlertDialogTitle>Leave Collaboration Session?</AlertDialogTitle>
<AlertDialogDescription>
Are you sure you want to leave this session? Any unsaved progress
will be lost.
</AlertDialogDescription>
</AlertDialogHeader>
<AlertDialogFooter>
<AlertDialogCancel>Cancel</AlertDialogCancel>
<AlertDialogAction
onClick={onLeave}
className="border border-amber-700/50 bg-amber-950/90 text-amber-100 hover:bg-amber-900/90"
>
Leave Session
</AlertDialogAction>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>
);
};

export default LeaveSessionDialog;
8 changes: 4 additions & 4 deletions peerprep-fe/src/app/collaboration/components/AudioSharing.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ const AudioSharing = () => {
},
});

peer.on('signal', (data) => {
peer.on('signal', (data: any) => {
console.log('Sending signal data:', data);
socketRef.current?.emit('signal', data);
});
Expand All @@ -62,7 +62,7 @@ const AudioSharing = () => {
.catch((error) => console.error('Error playing audio:', error));
});

peer.on('error', (err) => {
peer.on('error', (err: any) => {
console.error('Peer connection error:', err);
cleanupAudio();
});
Expand Down Expand Up @@ -91,12 +91,12 @@ const AudioSharing = () => {
console.log('Socket connected');
});

socketRef.current.on('connect_error', (error) => {
socketRef.current.on('connect_error', (error: any) => {
console.error('Connection error:', error);
cleanupAudio();
});

socketRef.current.on('signal', async (data) => {
socketRef.current.on('signal', async (data: any) => {
console.log('Received signal data:', data);

if (data.type === 'offer' && !peerRef.current) {
Expand Down
127 changes: 104 additions & 23 deletions peerprep-fe/src/app/collaboration/components/CodeEditor.tsx
Original file line number Diff line number Diff line change
@@ -1,34 +1,115 @@
import React from 'react';
'use client';

import { useState, useEffect, useRef } from 'react';
import Editor, { OnMount } from '@monaco-editor/react';
import { Button } from '@/components/ui/button';
import { Play } from 'lucide-react';
import ConsoleCard from './ConsoleCard';
import { toast, useToast } from '@/hooks/use-toast';
import { executeCode } from '../api/codeRunner';

interface CodeEditorProps {
onMount: OnMount;
language: string;
defaultValue?: string;
}

const CodeEditor: React.FC<CodeEditorProps> = ({ onMount, language }) => {
const CodeEditor: React.FC<CodeEditorProps> = ({
onMount,
language,
defaultValue = '',
}) => {
const [showOutput, setShowOutput] = useState(false);
const [output, setOutput] = useState('');
const cardRef = useRef<HTMLDivElement>(null);
const editorRef = useRef<any>(null);

useEffect(() => {
const handleClickOutside = (event: MouseEvent) => {
if (cardRef.current && !cardRef.current.contains(event.target as Node)) {
setShowOutput(false);
}
};

if (showOutput) {
document.addEventListener('mousedown', handleClickOutside);
}

return () => {
document.removeEventListener('mousedown', handleClickOutside);
};
}, [showOutput]);

const handleEditorMount: OnMount = (editor, monaco) => {
editorRef.current = editor;
onMount(editor, monaco);
};

const handleRun = () => {
console.log('Run button clicked');
if (editorRef.current) {
const code = editorRef.current.getValue();
console.log('Setting output:', code);
runCode(code);
}
};

const runCode = async (code: string) => {
if (!code) return;
try {
const result = await executeCode(language, code);
console.log(result);
setOutput(result.split('\n'));
setShowOutput(true);
} catch (error) {
console.log(error);
toast({
title: 'An error occurred.',
description: 'Something went wrong, try running the code again later.',
duration: 6000,
});
}
};

return (
<div
style={{
borderRadius: '12px',
overflow: 'hidden',
boxShadow: '0 4px 12px rgba(0, 0, 0, 0.5)',
}}
className="flex-grow overflow-y-auto bg-gray-900 font-mono text-gray-100"
>
<Editor
height="100%"
width="100%"
language={language}
theme="vs-dark"
onMount={onMount}
options={{
fontSize: 14,
minimap: { enabled: false },
lineNumbers: 'on',
wordWrap: 'on',
}}
/>
<div className="relative flex h-full flex-col">
<div className="flex items-center justify-end rounded-t-xl bg-gray-900 px-4 py-2">
<Button
onClick={handleRun}
variant="ghost"
size="sm"
className="bg-gray-800 text-gray-100 hover:bg-gray-700"
>
Run
<Play className="ml-1 h-4 w-4" />
</Button>
</div>

<div className="relative flex-grow">
{' '}
{/* Added relative positioning */}
<Editor
height="100%"
width="100%"
language={language}
theme="vs-dark"
onMount={handleEditorMount}
defaultValue={defaultValue}
options={{
fontSize: 14,
minimap: { enabled: false },
lineNumbers: 'on',
wordWrap: 'on',
scrollBeyondLastLine: false,
automaticLayout: true,
}}
/>
{showOutput && (
<div className="absolute inset-0 flex items-center justify-center bg-black/50">
<ConsoleCard output={output} ref={cardRef} />
</div>
)}
</div>
</div>
);
};
Expand Down
Loading

0 comments on commit b4dc7ba

Please sign in to comment.