diff --git a/README.md b/README.md index bb00edd1b0..1985e724f4 100644 --- a/README.md +++ b/README.md @@ -6,3 +6,16 @@ - You can choose to develop individual microservices within separate folders within this repository **OR** use individual repositories (all public) for each microservice. - In the latter scenario, you should enable sub-modules on this GitHub classroom repository to manage the development/deployment **AND** add your mentor to the individual repositories as a collaborator. - The teaching team should be given access to the repositories as we may require viewing the history of the repository in case of any disputes or disagreements. + +### Run PeerPrep with docker-compose: +Prerequisite: Ensure that Docker is installed and running. +1. Clone the repository. +2. Ensure that the respective `.env` files for all microservices, and the frontend, have been added in. +3. In any IDE or terminal, `cd` to the project root directory, and run the following commands: + - `docker-compose build --no-cache` to build the images + - `docker-compose up -d` to run the web app on `localhost:3000` + - `docker-compose down` to stop running the containers + +### Production Deployment of PeerPrep +- The production build and deployment of PeerPrep is located under the `deployment` branch. +- Deployment link: http://g46-peerprep-env.eba-u9cm3q7g.ap-southeast-1.elasticbeanstalk.com/ \ No newline at end of file diff --git a/backend/collaboration-service/handler/socketHandler.js b/backend/collaboration-service/handler/socketHandler.js index 04f4d4ed02..8cc9c7f1b4 100644 --- a/backend/collaboration-service/handler/socketHandler.js +++ b/backend/collaboration-service/handler/socketHandler.js @@ -195,7 +195,6 @@ const handleSocketIO = (apiGatewaySocket) => { activeUserInRoom[roomId] - 1 ); - console.log("HELP", activeUserInRoom[roomId]); setTimeout(() => { if (!isRefreshOrClose) { //reconnected activeUserInRoom[roomId] += 1; diff --git a/backend/feedback-service/package-lock.json b/backend/feedback-service/package-lock.json deleted file mode 100644 index 238195c120..0000000000 --- a/backend/feedback-service/package-lock.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "name": "feedback-service", - "lockfileVersion": 3, - "requires": true, - "packages": {} -} diff --git a/backend/user-service/controller/userController.js b/backend/user-service/controller/userController.js index 4c2c9974df..87a993506c 100644 --- a/backend/user-service/controller/userController.js +++ b/backend/user-service/controller/userController.js @@ -204,7 +204,7 @@ const getHistory = async (req, res) => { return acc; }, {}); - console.log("Fetched matching history data: ", filteredHistoryData); + console.log("Fetched matching history data"); return res.status(200).send(filteredHistoryData); } catch (error) { diff --git a/docker-compose.yml b/docker-compose.yml index c4ffff3291..3edc5d2c81 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -46,12 +46,11 @@ services: container_name: matching-service environment: - RABBIT_HOSTNAME=rabbitmq # URL to connect to rabbitmq container in the network + - API_GATEWAY_URL=http://api-gateway:8000 depends_on: # condition to wait for rabbitmq container to be ready rabbitmq: condition: service_healthy build: ./backend/matching-service # Path to the directory containing the Dockerfile for building the matching-service image. - ports: - - 5002:5002 # Maps port 5002 on the host to port 5002 in the container, making the app accessible on the host. volumes: - ./backend/matching-service:/app # Mounts the host directory './backend/matching-service' to '/app' in the container. - /app/node_modules # Anonymous Volume @@ -60,18 +59,54 @@ services: collaboration-service: container_name: collaboration-service - build: ./backend/collaboration-service # Path to the directory containing the Dockerfile for building the matching-service image. + environment: + - URL_QUESTION_SERVICE=http://question-service:5000/question + - API_GATEWAY_URL=http://api-gateway:8000 + build: ./backend/collaboration-service # Path to the directory containing the Dockerfile for building the collaboration-service image. ports: - - 5003:5003 # Maps port 5002 on the host to port 5002 in the container, making the app accessible on the host. + - 5003:5003 # Maps port 5003 on the host to port 5003 in the container, making the app accessible on the host. volumes: - - ./backend/collaboration-service:/app # Mounts the host directory './backend/matching-service' to '/app' in the container. + - ./backend/collaboration-service:/app # Mounts the host directory './backend/collaboration-service' to '/app' in the container. - /app/node_modules # Anonymous Volume networks: - - peerprep-network # Connects the matching-service to the 'peerprep-network' network. + - peerprep-network # Connects the collaboration-service to the 'peerprep-network' network. + + api-gateway: + container_name: api-gateway + environment: + - QUESTION_SERVICE_URL=http://question-service:5000/question + - USER_SERVICE_URL=http://user-service:5001/user + - COLLABORATION_SERVICE_URL=http://collaboration-service:5003/collaboration + depends_on: + question-service: + condition: service_started + user-service: + condition: service_started + collaboration-service: + condition: service_started + build: ./backend/api-gateway # Path to the directory containing the Dockerfile for building the api-gateway image. + ports: + - 8000:8000 # Maps port 8000 on the host to port 8000 in the container, making the app accessible on the host. + volumes: + - ./backend/api-gateway:/app # Mounts the host directory './backend/api-gateway' to '/app' in the container. + - /app/node_modules # Anonymous Volume + networks: + - peerprep-network # Connects the api-gateway to the 'peerprep-network' network. + + frontend: + container_name: frontend environment: - # - QUESTION_SERVICE_URL=question-service - - QUESTION_SERVICE_URL=http://question-service:5000 - + - REACT_APP_API_GATEWAY_URL=http://localhost:8000 + build: ./frontend + ports: + - 3000:3000 + volumes: + - ./frontend:/app + - /app/node_modules + networks: + - peerprep-network + depends_on: + - api-gateway volumes: rabbitmq_data: diff --git a/frontend/src/components/OutputWindow.js b/frontend/src/components/OutputWindow.js index 6dbc14f9e2..e64220e862 100644 --- a/frontend/src/components/OutputWindow.js +++ b/frontend/src/components/OutputWindow.js @@ -1,3 +1,5 @@ +import "./styles/OutputWindow.css"; + const OutputWindow = ({ outputDetails }) => { const getOutput = () => { let statusId = outputDetails?.status?.id; @@ -5,13 +7,13 @@ const OutputWindow = ({ outputDetails }) => { if (statusId === 6) { // Compilation error return ( -
+        
           {atob(outputDetails?.compile_output)}
         
); } else if (statusId === 3) { return ( -
+        
           {outputDetails.stdout
             ? `${atob(outputDetails.stdout)}`
             : "Compiled successfully"}
@@ -19,13 +21,11 @@ const OutputWindow = ({ outputDetails }) => {
       );
     } else if (statusId === 5) {
       return (
-        
-          {`Time Limit Exceeded`}
-        
+
{`Time Limit Exceeded`}
); } else { return ( -
+        
           {atob(outputDetails?.stderr)}
         
); @@ -34,21 +34,11 @@ const OutputWindow = ({ outputDetails }) => { return ( <> -

- Output -

-
- {outputDetails ? <>{getOutput()} : null} +
+

Output

+
+ {outputDetails ? getOutput() : null} +
); diff --git a/frontend/src/components/styles/CodeEditor.css b/frontend/src/components/styles/CodeEditor.css index 22899bdd29..6f7f7c06bd 100644 --- a/frontend/src/components/styles/CodeEditor.css +++ b/frontend/src/components/styles/CodeEditor.css @@ -35,16 +35,3 @@ #codeButton:active { background-color: #e0e0e0; } - -#outputWindow { - background-color: #f9f9f9; /* Light grey background for output */ - border: 1px solid #ccc; - border-radius: 5px; - padding: 15px; - margin-top: 20px; - font-family: monospace; /* Use a monospace font for code output */ - white-space: pre-wrap; /* Preserve whitespace */ - max-height: 400px; /* Limit height for scrolling */ - overflow-y: auto; /* Add scrollbar if content overflows */ - box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); /* Subtle shadow for depth */ -} diff --git a/frontend/src/components/styles/OutputWindow.css b/frontend/src/components/styles/OutputWindow.css new file mode 100644 index 0000000000..4528907594 --- /dev/null +++ b/frontend/src/components/styles/OutputWindow.css @@ -0,0 +1,28 @@ +.output-title { + font-weight: bold; + font-size: 24px; + margin-bottom: 8px; +} + +.output-container { + border: 2px solid var(--sds-color-border-default-default); + height: 220px; + background-color: #1e293b; + border-radius: 8px; + color: white; + overflow-y: auto; + padding: 8px; +} + +.output-text { + padding: 8px; + font-size: 12px; +} + +.success-text { + color: green; +} + +.error-text { + color: red; +} diff --git a/frontend/src/pages/user-service/ChangePassword.js b/frontend/src/pages/user-service/ChangePassword.js index aa80020b36..f8009b8c99 100644 --- a/frontend/src/pages/user-service/ChangePassword.js +++ b/frontend/src/pages/user-service/ChangePassword.js @@ -54,7 +54,7 @@ function ChangePassword() { setErrorMessage(err.response.data.message); alert("You have exceeded the rate limit. Please wait a moment and try again."); } else { - setErrorMessage("An error occurred. Please try again."); + setErrorMessage("Old password is incorrect."); console.log(err); } });