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

N2H N4 (Code Execution) and N5 (Enhanced Collab Service) #48

Merged
merged 4 commits into from
Nov 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
102 changes: 99 additions & 3 deletions peerprep/frontend/src/styles/App.css
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
margin: 0 auto;
padding: 5rem;
text-align: center;
background-color: white;
}

/* Global Styling */
Expand Down Expand Up @@ -515,8 +516,8 @@ h2 {
.editor-container {
width: 100%;
height: 100%;
max-width: 1000px;
min-height: 500px;
max-width: 900px;
min-height: 300px;
flex-grow: 1;
border: 2px solid #ccc;
border-radius: 10px;
Expand All @@ -533,10 +534,19 @@ h2 {
/* Header section styling */
.editor-header {
text-align: center;
margin-bottom: 20px;
margin-bottom: -10px;
margin-top: -60px;
}

.leave-btn,
.run-btn {
margin-top: 10px; /* Additional spacing if needed for each button */
}

#language-select {
margin-bottom: 20px;
}

/* Leave session button */
.leave-btn {
background-color: #ff4d4d;
Expand Down Expand Up @@ -586,3 +596,89 @@ h2 {
opacity: 1;
}
}

.editor-header2 {
text-align: center;
margin-bottom: 20px;
margin-top: 10px;
display: flex;
flex-direction: row; /* Arrange items in a vertical stack */
align-items: center; /* Align items to the left */
gap: 100px; /* Add vertical spacing between items */
}

.matching-form2 {
padding: 0px;
max-width: 40%;
margin: 0 auto; /* Center the form */
border-radius: 10px; /* Rounded corners for the form */
background-color: white;
}

/* Styles for inputs, textarea, and select within .question-form */
.matching-form2 input,
.matching-form2 textarea,
.matching-form2 select {
width: 100%;
padding: 10px;
margin-top: 5px; /* Space between input boxes */
border: 1px solid #ccc; /* Border */
border-radius: 4px; /* Rounded corners */
background-color: #f4f4f4;
color: #333;
font-size: 16px;
box-sizing: border-box; /* Ensures padding is included within the width */
}

/* Input Fields Focus State */
.matching-form2 input:focus,
.matching-form2 textarea:focus,
.matching-form2 select:focus {
outline: none;
border: 2px solid #4CAF50; /* Green border on focus */
background-color: #fff; /* White background on focus */
}

/* Custom styling for the difficulty select dropdown */
.matching-form2 select {
width: 100%;
padding: 10px;
margin-top: 5px;
border: 2px solid #ccc; /* border */
border-radius: 4px; /* Rounded corners */
background-color: #f9f9f9;
color: #333;
font-size: 16px;
appearance: none;
}

/* Focus state for select dropdown */
.matching-form2 select:focus {
outline: none;
border-color: #4CAF50; /* Green border on focus */
background-color: #fff; /* White background on focus */
}

/* Submit Button */
.matching-form2 button.submit-btn {
background-color: #4CAF50;
color: white;
padding: 10px 20px;
border: none;
border-radius: 4px;
cursor: pointer;
font-size: 16px;
margin-top: 10px;
}

.matching-form2 button.submit-btn:hover {
background-color: #45a049;
}

/* Error Message styling, to be expanded later most likely split into diff types */
.matching-form2 .error-message {
color: red;
font-size: 14px;
margin-bottom: 15px;
text-align: center;
}
Original file line number Diff line number Diff line change
@@ -1,30 +1,50 @@
import React, { useState, useEffect, useRef } from 'react';
import { UnControlled as CodeMirror } from 'react-codemirror2';
import { useParams, useNavigate } from 'react-router-dom';
import axios from 'axios';
import * as Y from 'yjs';

import 'codemirror/lib/codemirror.css';
import 'codemirror/theme/material.css';
import 'codemirror/mode/javascript/javascript';
import axios from 'axios';
import 'codemirror/addon/hint/show-hint';
import 'codemirror/addon/hint/show-hint.css';
import 'codemirror/addon/hint/javascript-hint'; // For JavaScript hints

import * as Y from 'yjs';
import { WebsocketProvider } from 'y-websocket';
import 'codemirror/mode/javascript/javascript'; // For JavaScript
import 'codemirror/mode/clike/clike'; // For C, C++, Java (these use the 'clike' mode)
import 'codemirror/mode/python/python'; // For Python
import 'codemirror/mode/swift/swift'; // For Swift

// @ts-check
import { CodemirrorBinding } from 'y-codemirror';
import { WebsocketProvider } from 'y-websocket';


const CollaborationServiceIntegratedView: React.FC = () => {
const { topic, difficulty, questionId, sessionId } = useParams<{ topic: string; difficulty: string; questionId: string; sessionId: string; }>();
const [output, setOutput] = useState<string | null>(null);
const [language, setLanguage] = useState<number>(63); // Default to JavaScript (Node.js)
const [syntaxLang, setSyntaxLang] = useState<string>('javascript');
const editorRef = useRef<any>(null);
const navigate = useNavigate();
const [yText, setYText] = useState<Y.Text | null>(null);

// Mapping for CodeMirror modes
const languageModes = {
javascript: 'javascript',
cpp: 'text/x-c++src', // Mode for C++
c: 'text/x-csrc', // Mode for C
java: 'text/x-java', // Mode for Java
python: 'python', // Mode for Python
};

useEffect(() => {
console.log(`Session ID: ${sessionId}, Topic: ${topic}, Difficulty: ${difficulty}`);
console.log(`Question: ${questionId}`);
}, [sessionId, topic, difficulty, questionId]);

useEffect(() => {
document.body.style.overflow = 'hidden';
document.body.style.overflow = 'auto';
return () => {
document.body.style.overflow = 'auto';
};
Expand All @@ -51,6 +71,17 @@ const CollaborationServiceIntegratedView: React.FC = () => {
navigate('/matching');
};

const handleLangChange = (e: React.ChangeEvent<HTMLSelectElement>) => {
setLanguage(parseInt(e.target.value));
setSyntaxLang(e.target.value === '63' ? 'javascript'
: e.target.value === '54' ? 'text/x-c++src'
: e.target.value === '50' ? 'text/x-csrc'
: e.target.value === '71' ? 'python'
: e.target.value === '62' ? 'text/x-java'
: e.target.value === '83' ? 'swift'
: 'javascript');
}

const handleRunCode = async () => {
try {
if (!yText) {
Expand Down Expand Up @@ -119,39 +150,77 @@ const CollaborationServiceIntegratedView: React.FC = () => {
<h2>Collaboration Session</h2>
<p>Topic: {topic} | Difficulty: {difficulty} | Session: {sessionId}</p>
<p>Question: {questionId}</p>
<button onClick={handleLeaveSession} className="leave-btn">Leave Session</button>
</div>
</div>

<div className="editor-header2">
<button
onClick={handleLeaveSession}
className="leave-btn"
style={{ marginBottom: '0px' }}
>
Leave Session
</button>

<div className="editor-container">
<CodeMirror
ref={editorRef}
options={{
mode: 'javascript',
lineNumbers: true,
tabSize: 2,
indentWithTabs: true
}}
onChange={() => {
// Let Yjs handle all updates; do not use setCode here
}}
/>
</div>
<div className="matching-form2">
<div>
<select
name="topic"
value={language}
onChange={
(e) => handleLangChange(e)
}
required
>
<option value="" disabled>Select Language</option> {/* Placeholder option */}
<option value="63">JavaScript</option>
<option value="54">C++</option>
<option value="50">C</option>
<option value="71">Python</option>
<option value="62">Java</option>
<option value="83">Swift</option>
</select>
</div>
</div>
<button
onClick={handleRunCode}
className="run-btn"
style={{ marginBottom: '0px' }}
> Run Code
</button>
</div>

<div className="editor-container">
<CodeMirror
ref={editorRef}
options={{
mode: syntaxLang,
lineNumbers: true,
tabSize: 2,
indentWithTabs: true,
showHint: true,
extraKeys: {
'Ctrl-Space': 'autocomplete', // Trigger autocomplete with Ctrl-Space
},
hintOptions: { completeSingle: false },
}}

<label htmlFor="language-select" style={{ marginTop: '20px' }}>Select Language:</label>
<select
id="language-select"
value={language}
onChange={(e) => setLanguage(parseInt(e.target.value))}
style={{ marginBottom: '20px' }}
>
<option value="63">JavaScript (Node.js)</option>
<option value="54">C++ (GCC 9.2.0)</option>
<option value="50">C (GCC 9.2.0)</option>
<option value="71">Python (3.8.1)</option>
<option value="62">Java (OpenJDK 13.0.1)</option>
</select>

<button onClick={handleRunCode} className="run-btn" style={{ marginBottom: '20px' }}>Run Code</button>
editorDidMount={(editor) => {
editor.on('keyup', (cm: any, event: any) => {
// Only trigger autocomplete on specific characters
const triggerKeys = /^[a-zA-Z0-9_]$/; // Allow letters, numbers, and underscore
if (
triggerKeys.test(event.key) &&
!cm.state.completionActive // Ensure that completion is not already active
) {
cm.showHint({ completeSingle: false });
}
});
}}
onChange={() => {
// Let Yjs handle all updates; do not use setCode here
}}
/>
</div>

<h3 style={{ textAlign: 'left', marginBottom: '5px' }}>Output</h3>
<div className="output-container" style={{ width: '900px', textAlign: 'left', border: '1px solid #ddd', padding: '10px', borderRadius: '5px', backgroundColor: '#f9f9f9' }}>
Expand Down
Loading