Skip to content

Commit

Permalink
Merge pull request #41 from CS3219-AY2425S1/collabServiceUIandFunction
Browse files Browse the repository at this point in the history
Collaboration Service Frontend + Basic Implementation
  • Loading branch information
bhnuka authored Nov 2, 2024
2 parents 1c964be + 497d036 commit f7a61b8
Show file tree
Hide file tree
Showing 11 changed files with 1,002 additions and 129 deletions.
536 changes: 534 additions & 2 deletions peerprep/frontend/package-lock.json

Large diffs are not rendered by default.

5 changes: 4 additions & 1 deletion peerprep/frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,10 @@
"react-codemirror2": "^8.0.0",
"react-dom": "^18.3.1",
"react-router-dom": "^6.26.2",
"socket.io-client": "^4.8.1"
"socket.io-client": "^4.8.1",
"y-codemirror": "^3.0.1",
"y-websocket": "^2.0.4",
"yjs": "^13.6.20"
},
"devDependencies": {
"@eslint/js": "^9.9.0",
Expand Down
6 changes: 5 additions & 1 deletion peerprep/frontend/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import QuestionService from './views/QuestionServiceViews/QuestionManagement';
import MatchingService from './views/MatchingServiceViews/MatchingServiceMainView';
import SessionStubView from './views/MatchingServiceViews/SessionStubView';
import CollaborationServiceView from './views/CollabServiceViews/CollabServiceMainView';
import CollaborationServiceIntegratedView from './views/CollabServiceViews/CollabServiceIntegratedView';

const App: React.FC = () => {
return (
Expand All @@ -47,9 +48,12 @@ const App: React.FC = () => {
{/* Public Route for Session View (Stub for now) */}
<Route path="/sessionStub" element={<SessionStubView />} />

{/* Public Route for Collaboration Service View */}
{/* Public Route for Collaboration Service View without sockets*/}
<Route path="/collab" element={<CollaborationServiceView topic={''} difficulty={''} sessionId={''} />} />

{/* Public Route for Collaboration Service Integrated View */}
<Route path="/collabFull/:topic/:difficulty/:questionId/:sessionId" element={<CollaborationServiceIntegratedView />} />

{/* Public Route for Sign-Up */}
<Route path="/signup" element={<SignUp />} /> {/* New Sign-Up Route */}

Expand Down
3 changes: 0 additions & 3 deletions peerprep/frontend/src/main.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import App from './App.tsx'
import './styles/index.css'
import './styles/App.css';

createRoot(document.getElementById('root')!).render(
<StrictMode>
<App />
</StrictMode>,
)


150 changes: 46 additions & 104 deletions peerprep/frontend/src/styles/App.css
Original file line number Diff line number Diff line change
Expand Up @@ -498,72 +498,43 @@ h2 {
flex-direction: column;
justify-content: space-between; /* Adjust layout */
align-items: center;
height: 90vh; /* Full height of the viewport */

height: 85vh; /* Full height of the viewport */
width: 80vw; /* Full width of the viewport */
background-color: #f5f5f5;

background-color: white;
padding: 20px;
box-sizing: border-box; /* Include padding in width and height calculations */
}

/* Header section styling */
.editor-header {
text-align: center;
margin-bottom: 20px;
}

/* Leave session button */
.leave-btn {
background-color: #ff4d4d;
color: white;
border: none;
border-radius: 6px;
padding: 10px 20px;
cursor: pointer;
margin-top: 10px;
}

.leave-btn:hover {
background-color: #ff1a1a;
.CodeMirror {
min-height: 1000px;
width: 100%;
}

/* Editor container styling */
.editor-container {
width: 100%; /* Make the editor responsive */
width: 100%;
height: 100%;
max-width: 1000px;
flex-grow: 1; /* Allow the editor to grow and fill available space */
min-height: 500px;
flex-grow: 1;
border: 2px solid #ccc;
border-radius: 10px;
overflow: hidden;
box-shadow: 0px 4px 8px rgba(0, 0, 0, 0.1);
background-color: #2d2d2d; /* Background color for the editor */
background-color: white;
color: white;

/* Add these properties */
overflow-y: auto;
text-align: left; /* Ensure text aligns to the left */
vertical-align: top; /* Ensures text starts from the top */
}





/* Parent container: Flexbox layout to divide the screen */
.collaboration-container {
display: flex;
height: 100vh; /* Full height of the viewport */
width: 100vw; /* Full width of the viewport */
background-color: #f5f5f5;
}

/* Editor section: Takes most of the space */
.editor-section {
flex: 3; /* 3/4 of the screen */
display: flex;
flex-direction: column;
padding: 20px;
box-sizing: border-box;
}

/* Header for the collaboration session */
/* Header section styling */
.editor-header {
text-align: center;
margin-bottom: 20px;
margin-top: -60px;
}

/* Leave session button */
Expand All @@ -581,66 +552,37 @@ h2 {
background-color: #ff1a1a;
}

/* Code editor container */
.editor-container {
flex-grow: 1; /* Take up remaining space */
border: 2px solid #ccc;
border-radius: 10px;
overflow: hidden;
box-shadow: 0px 4px 8px rgba(0, 0, 0, 0.1);
background-color: #2d2d2d;
color: white;
text-align: left;
}

/* Sidebar for messages */
.sidebar {
flex: 1; /* 1/4 of the screen */
display: flex;
flex-direction: column;
padding: 20px;
background-color: white;
border-left: 2px solid #ccc;
box-shadow: -2px 0px 8px rgba(0, 0, 0, 0.1);
}

/* Messages section */
.messages {
flex-grow: 1; /* Allow messages to grow */
overflow-y: auto; /* Scroll if messages overflow */
margin-bottom: 10px;
}

/* Individual message styling */
.message {
background-color: #f1f1f1;
margin: 5px 0;
padding: 10px;
border-radius: 5px;
/* Styles for the collaborative cursor to look like a blinking bar */
.CodeMirror-cursor {
position: absolute;
width: 2px;
background-color: blue; /* Adjust the color per user */
opacity: 0.8;
animation: blink 1s step-end infinite; /* Blinking effect */
}

/* Input section for new message */
.message-input {
display: flex;
gap: 10px;
.CodeMirror-cursor {
border-left: 1px solid white;
border-right: 1px solid black;
}

.message-input input {
flex-grow: 1; /* Take up most space */
padding: 10px;
border: 1px solid #ccc;
border-radius: 5px;
}

.message-input button {
background-color: #4CAF50;
/* Styles for the label (optional) */
.CodeMirror-cursor-label {
position: absolute;
background-color: orange;
color: white;
border: none;
border-radius: 5px;
padding: 10px 15px;
cursor: pointer;
padding: 2px 5px;
border-radius: 3px;
font-size: 12px;
top: -20px;
}

.message-input button:hover {
background-color: #45a049;
}
/* Blinking animation */
@keyframes blink {
from, to {
opacity: 0;
}
50% {
opacity: 1;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import React, { useState, useEffect, useRef } from 'react';
import { UnControlled as CodeMirror } from 'react-codemirror2';
import { useParams, useNavigate } from 'react-router-dom';
import 'codemirror/lib/codemirror.css';
import 'codemirror/theme/material.css';
import 'codemirror/mode/javascript/javascript';

import * as Y from 'yjs';
import { WebsocketProvider } from 'y-websocket';

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

const CollaborationServiceIntegratedView: React.FC = () => {
const { topic, difficulty, questionId, sessionId } = useParams<{ topic: string; difficulty: string; questionId: string; sessionId: string; }>();
const [code, setCode] = useState('// Start coding here...\n');
const editorRef = useRef<any>(null);
const navigate = useNavigate();

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

useEffect(() => {
document.body.style.overflow = 'hidden';
return () => {
document.body.style.overflow = 'auto';
};
}, []);

useEffect(() => {
const ydoc = new Y.Doc();
const provider = new WebsocketProvider('ws://localhost:1234/' + sessionId, 'collaborative-doc', ydoc);
const yText = ydoc.getText('codemirror');

if (editorRef.current) {
const binding = new CodemirrorBinding(yText, editorRef.current.editor, provider.awareness);
return () => {
binding.destroy();
provider.destroy();
ydoc.destroy();
};
}
}, []);

const handleBeforeCodeChange = (editor: any, data: any, value: string) => {
//setCode(value);
};

const handleLeaveSession = () => {
navigate('/matching');
};

return (
<div className="editor-container-parent">
<div className="editor-header">
<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 className="editor-container">
<CodeMirror
ref={editorRef}
value={code}
options={{
mode: 'javascript',
lineNumbers: true,
tabSize: 2,
indentWithTabs: true
}}
onBeforeChange={handleBeforeCodeChange}
/>
</div>
</div>
);
};

export default CollaborationServiceIntegratedView;
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import { useParams, useNavigate } from 'react-router-dom'; // For routing and se
import 'codemirror/lib/codemirror.css'; // Default CodeMirror styles
import 'codemirror/theme/material.css'; // CodeMirror theme
import 'codemirror/mode/javascript/javascript'; // Support for JavaScript mode
import 'codemirror/mode/swift/swift'; // Support for Swift mode

interface CollaborationServiceViewProps {
topic: string;
Expand All @@ -22,6 +21,17 @@ const CollaborationServiceView: React.FC<CollaborationServiceViewProps> = ({ top
console.log(`Session ID: ${sessionId}, Topic: ${topic}, Difficulty: ${difficulty}`);
}, [sessionId, topic, difficulty]);


useEffect(() => {
// Lock scroll when this component mounts
document.body.style.overflow = 'hidden';

// Cleanup function to unlock scroll when component unmounts
return () => {
document.body.style.overflow = 'auto';
};
}, []);

const handleCodeChange = (editor: any, data: any, value: string) => {
setCode(value); // Update local code state
// TODO: Later sync this code change with the backend using WebSocket/Socket.io
Expand All @@ -45,7 +55,7 @@ const CollaborationServiceView: React.FC<CollaborationServiceViewProps> = ({ top
value={code}
options={{
mode: 'javascript', // CodeMirror mode for syntax highlighting
theme: 'material', // Optional theme
// Optional theme
lineNumbers: true, // Show line numbers
tabSize: 2, // Set tab size
indentWithTabs: true, // Allow indentation with tabs
Expand Down
Loading

0 comments on commit f7a61b8

Please sign in to comment.