From e8af53d5c5d42d0f8e3fd822d40852425ae7d706 Mon Sep 17 00:00:00 2001 From: Suryansh Kushwaha <112935210+suryanshkushwaha@users.noreply.github.com> Date: Wed, 6 Nov 2024 20:23:39 +0530 Subject: [PATCH 1/3] working chat NTH --- .../backend/collab-service/package-lock.json | 191 +++++++++++++++++ peerprep/backend/collab-service/package.json | 2 + peerprep/backend/collab-service/src/server.js | 30 ++- peerprep/frontend/package-lock.json | 196 +++++++++++++++++- peerprep/frontend/src/components/Chat.tsx | 69 ++++++ peerprep/frontend/src/styles/App.css | 92 +++++++- .../CollabServiceIntegratedView.tsx | 191 +++++++++-------- peerprep/frontend/yarn.lock | 56 +++-- 8 files changed, 695 insertions(+), 132 deletions(-) create mode 100644 peerprep/frontend/src/components/Chat.tsx diff --git a/peerprep/backend/collab-service/package-lock.json b/peerprep/backend/collab-service/package-lock.json index 91775fd89c..6aa511ab12 100644 --- a/peerprep/backend/collab-service/package-lock.json +++ b/peerprep/backend/collab-service/package-lock.json @@ -9,10 +9,12 @@ "version": "1.0.0", "license": "MIT", "dependencies": { + "cors": "^2.8.5", "dotenv": "^16.4.5", "express": "^4.21.1", "mongoose": "^8.7.3", "node-static": "^0.7.11", + "socket.io": "^4.8.1", "ws": "^7.4.2", "y-websocket": "^1.3.9", "yjs": "^13.4.12" @@ -30,6 +32,36 @@ "sparse-bitfield": "^3.0.3" } }, + "node_modules/@socket.io/component-emitter": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.2.tgz", + "integrity": "sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==", + "license": "MIT" + }, + "node_modules/@types/cookie": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.4.1.tgz", + "integrity": "sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==", + "license": "MIT" + }, + "node_modules/@types/cors": { + "version": "2.8.17", + "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.17.tgz", + "integrity": "sha512-8CGDvrBj1zgo2qE+oS3pOCyYNqCPryMWY2bGfwA0dcfopWGgxs+78df0Rs3rc9THP4JkOhLsAa+15VdpAqkcUA==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/node": { + "version": "22.9.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.9.0.tgz", + "integrity": "sha512-vuyHg81vvWA1Z1ELfvLko2c8f34gyA0zaic0+Rllc5lbCnbSyuvb2Oxpm6TAUAC/2xZN3QGqxBNggD1nNR2AfQ==", + "license": "MIT", + "dependencies": { + "undici-types": "~6.19.8" + } + }, "node_modules/@types/webidl-conversions": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-7.0.3.tgz", @@ -106,6 +138,15 @@ ], "optional": true }, + "node_modules/base64id": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz", + "integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==", + "license": "MIT", + "engines": { + "node": "^4.5.0 || >= 5.9" + } + }, "node_modules/body-parser": { "version": "1.20.3", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", @@ -250,6 +291,19 @@ "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", "license": "MIT" }, + "node_modules/cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "license": "MIT", + "dependencies": { + "object-assign": "^4", + "vary": "^1" + }, + "engines": { + "node": ">= 0.10" + } + }, "node_modules/debug": { "version": "4.3.7", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", @@ -358,6 +412,66 @@ "node": ">=6" } }, + "node_modules/engine.io": { + "version": "6.6.2", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.6.2.tgz", + "integrity": "sha512-gmNvsYi9C8iErnZdVcJnvCpSKbWTt1E8+JZo8b+daLninywUWi5NQ5STSHZ9rFjFO7imNcvb8Pc5pe/wMR5xEw==", + "license": "MIT", + "dependencies": { + "@types/cookie": "^0.4.1", + "@types/cors": "^2.8.12", + "@types/node": ">=10.0.0", + "accepts": "~1.3.4", + "base64id": "2.0.0", + "cookie": "~0.7.2", + "cors": "~2.8.5", + "debug": "~4.3.1", + "engine.io-parser": "~5.2.1", + "ws": "~8.17.1" + }, + "engines": { + "node": ">=10.2.0" + } + }, + "node_modules/engine.io-parser": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.3.tgz", + "integrity": "sha512-HqD3yTBfnBxIrbnM1DoD6Pcq8NECnh8d4As1Qgh0z5Gg3jRRIqijury0CL3ghu/edArpUYiYqQiDUQBIs4np3Q==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/engine.io/node_modules/cookie": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", + "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/engine.io/node_modules/ws": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", + "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, "node_modules/errno": { "version": "0.1.8", "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.8.tgz", @@ -1069,6 +1183,15 @@ "node": ">= 0.4.1" } }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/object-inspect": { "version": "1.13.2", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz", @@ -1333,6 +1456,68 @@ "integrity": "sha512-Rtlj66/b0ICeFzYTuNvX/EF1igRbbnGSvEyT79McoZa/DeGhMyC5pWKOEsZKnpkqtSeovd5FL/bjHWC3CIIvCQ==", "license": "MIT" }, + "node_modules/socket.io": { + "version": "4.8.1", + "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.8.1.tgz", + "integrity": "sha512-oZ7iUCxph8WYRHHcjBEc9unw3adt5CmSNlppj/5Q4k2RIrhl8Z5yY2Xr4j9zj0+wzVZ0bxmYoGSzKJnRl6A4yg==", + "license": "MIT", + "dependencies": { + "accepts": "~1.3.4", + "base64id": "~2.0.0", + "cors": "~2.8.5", + "debug": "~4.3.2", + "engine.io": "~6.6.0", + "socket.io-adapter": "~2.5.2", + "socket.io-parser": "~4.2.4" + }, + "engines": { + "node": ">=10.2.0" + } + }, + "node_modules/socket.io-adapter": { + "version": "2.5.5", + "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.5.5.tgz", + "integrity": "sha512-eLDQas5dzPgOWCk9GuuJC2lBqItuhKI4uxGgo9aIV7MYbk2h9Q6uULEh8WBzThoI7l+qU9Ast9fVUmkqPP9wYg==", + "license": "MIT", + "dependencies": { + "debug": "~4.3.4", + "ws": "~8.17.1" + } + }, + "node_modules/socket.io-adapter/node_modules/ws": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", + "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/socket.io-parser": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.4.tgz", + "integrity": "sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==", + "license": "MIT", + "dependencies": { + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.3.1" + }, + "engines": { + "node": ">=10.0.0" + } + }, "node_modules/sparse-bitfield": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz", @@ -1394,6 +1579,12 @@ "node": ">= 0.6" } }, + "node_modules/undici-types": { + "version": "6.19.8", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", + "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", + "license": "MIT" + }, "node_modules/unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", diff --git a/peerprep/backend/collab-service/package.json b/peerprep/backend/collab-service/package.json index 6c50e63204..ea60abe041 100644 --- a/peerprep/backend/collab-service/package.json +++ b/peerprep/backend/collab-service/package.json @@ -16,10 +16,12 @@ ] }, "dependencies": { + "cors": "^2.8.5", "dotenv": "^16.4.5", "express": "^4.21.1", "mongoose": "^8.7.3", "node-static": "^0.7.11", + "socket.io": "^4.8.1", "ws": "^7.4.2", "y-websocket": "^1.3.9", "yjs": "^13.4.12" diff --git a/peerprep/backend/collab-service/src/server.js b/peerprep/backend/collab-service/src/server.js index a6fac28f13..d37a4ed280 100644 --- a/peerprep/backend/collab-service/src/server.js +++ b/peerprep/backend/collab-service/src/server.js @@ -7,11 +7,14 @@ const setupWSConnection = ywsUtils.setupWSConnection; const docs = ywsUtils.docs; const connectDB = require('../config/db'); const { storeDocument, getDocument } = require('./controller/collab-controller'); +const { Server } = require("socket.io"); +const cors = require("cors"); const app = express(); const server = http.createServer(app); const wss = new WebSocket.Server({ server }); +app.use(cors()); app.use(express.json()); // Connect to MongoDB @@ -49,7 +52,30 @@ wss.on('connection', (conn, req) => { setupWSConnection(conn, req, { gc: req.url.slice(1) !== 'ws/prosemirror-versions' }); }); +const io = new Server(server, { + cors: { + origin: "http://localhost:5173", + methods: ["GET", "POST"], + }, +}); + +io.on("connection", (socket) => { + console.log(`User Connected: ${socket.id}`); + + socket.on("join_room", (data) => { + socket.join(data); + }); + + socket.on("send_message", (data) => { + socket.in(data.room).emit("receive_message", data); // Send to all clients except sender + }); + + socket.on("disconnect", () => { + console.log(`User Disconnected: ${socket.id}`); + }); +}); + const PORT = process.env.PORT || 1234; server.listen(PORT, () => { - console.log(`Server is running at http://localhost:1234`); -}); + console.log(`Server is running at http://localhost:${PORT}`); +}); \ No newline at end of file diff --git a/peerprep/frontend/package-lock.json b/peerprep/frontend/package-lock.json index 7feab7574e..e0f2bd3db9 100644 --- a/peerprep/frontend/package-lock.json +++ b/peerprep/frontend/package-lock.json @@ -12,7 +12,9 @@ "@types/testing-library__react": "^10.2.0", "axios": "^1.7.7", "codemirror": "^5.65.18", + "openai": "^4.71.0", "react": "^18.3.1", + "react-chatbotify": "^2.0.0-beta.22", "react-codemirror2": "^8.0.0", "react-dom": "^18.3.1", "react-router-dom": "^6.26.2", @@ -1662,12 +1664,21 @@ "version": "22.7.4", "resolved": "https://registry.npmjs.org/@types/node/-/node-22.7.4.tgz", "integrity": "sha512-y+NPi1rFzDs1NdQHHToqeiX2TIS79SWEAw9GYhkkx8bD0ChpfqC+n2j5OXOCpzfojBEBt6DnEnnG9MY0zk1XLg==", - "dev": true, "license": "MIT", "dependencies": { "undici-types": "~6.19.2" } }, + "node_modules/@types/node-fetch": { + "version": "2.6.11", + "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.11.tgz", + "integrity": "sha512-24xFj9R5+rfQJLRyM56qh+wnVSYhyXC2tkoBndtY0U+vubqNsYXGjufB2nn8Q6gt0LrARwL6UBtMCSVCwl4B1g==", + "license": "MIT", + "dependencies": { + "@types/node": "*", + "form-data": "^4.0.0" + } + }, "node_modules/@types/prop-types": { "version": "15.7.13", "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.13.tgz", @@ -1955,6 +1966,18 @@ "vite": "^4.2.0 || ^5.0.0" } }, + "node_modules/abort-controller": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", + "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "license": "MIT", + "dependencies": { + "event-target-shim": "^5.0.0" + }, + "engines": { + "node": ">=6.5" + } + }, "node_modules/abstract-leveldown": { "version": "6.2.3", "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-6.2.3.tgz", @@ -2008,6 +2031,18 @@ "node": ">=0.4.0" } }, + "node_modules/agentkeepalive": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.5.0.tgz", + "integrity": "sha512-5GG/5IbQQpC9FpkRGsSvZI5QYeSCzlJHdpBQntCsuTOxhKD8lqKhrleg2Yi7yvMIf82Ycmmqln9U8V9qwEiJew==", + "license": "MIT", + "dependencies": { + "humanize-ms": "^1.2.1" + }, + "engines": { + "node": ">= 8.0.0" + } + }, "node_modules/ajv": { "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", @@ -3181,6 +3216,15 @@ "node": ">=0.10.0" } }, + "node_modules/event-target-shim": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", + "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/execa": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", @@ -3420,6 +3464,25 @@ "node": ">= 6" } }, + "node_modules/form-data-encoder": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/form-data-encoder/-/form-data-encoder-1.7.2.tgz", + "integrity": "sha512-qfqtYan3rxrnCk1VYaA4H+Ms9xdpPqvLZa6xmMgFvhO32x7/3J/ExcTd6qpxM0vH2GdMI+poehyBZvqfMTto8A==", + "license": "MIT" + }, + "node_modules/formdata-node": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/formdata-node/-/formdata-node-4.4.1.tgz", + "integrity": "sha512-0iirZp3uVDjVGt9p49aTaqjk84TrglENEDuqfdlZQ1roC9CWlPk6Avf8EEnZNcAqPonwkG35x4n3ww/1THYAeQ==", + "license": "MIT", + "dependencies": { + "node-domexception": "1.0.0", + "web-streams-polyfill": "4.0.0-beta.3" + }, + "engines": { + "node": ">= 12.20" + } + }, "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -3592,6 +3655,15 @@ "node": ">=10.17.0" } }, + "node_modules/humanize-ms": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", + "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==", + "license": "MIT", + "dependencies": { + "ms": "^2.0.0" + } + }, "node_modules/ieee754": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", @@ -5025,6 +5097,45 @@ "dev": true, "license": "MIT" }, + "node_modules/node-domexception": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", + "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "github", + "url": "https://paypal.me/jimmywarting" + } + ], + "license": "MIT", + "engines": { + "node": ">=10.5.0" + } + }, + "node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "license": "MIT", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, "node_modules/node-gyp-build": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.1.1.tgz", @@ -5100,6 +5211,47 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/openai": { + "version": "4.71.0", + "resolved": "https://registry.npmjs.org/openai/-/openai-4.71.0.tgz", + "integrity": "sha512-jeJ7+6cZvj+ZbIsbX/Ag8+pug2+vjKbrD/v3Hwp6uv3KZyWjSkZa5MdUshzpNC3jsFzakfbUhEEFQXsKWNgm/g==", + "license": "Apache-2.0", + "dependencies": { + "@types/node": "^18.11.18", + "@types/node-fetch": "^2.6.4", + "abort-controller": "^3.0.0", + "agentkeepalive": "^4.2.1", + "form-data-encoder": "1.7.2", + "formdata-node": "^4.3.2", + "node-fetch": "^2.6.7" + }, + "bin": { + "openai": "bin/cli" + }, + "peerDependencies": { + "zod": "^3.23.8" + }, + "peerDependenciesMeta": { + "zod": { + "optional": true + } + } + }, + "node_modules/openai/node_modules/@types/node": { + "version": "18.19.64", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.64.tgz", + "integrity": "sha512-955mDqvO2vFf/oL7V3WiUtiz+BugyX8uVbaT2H8oj3+8dRyH2FLiNdowe7eNqRM7IOIZvzDH76EoAT+gwm6aIQ==", + "license": "MIT", + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/openai/node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "license": "MIT" + }, "node_modules/optionator": { "version": "0.9.4", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", @@ -5438,6 +5590,16 @@ "node": ">=0.10.0" } }, + "node_modules/react-chatbotify": { + "version": "2.0.0-beta.22", + "resolved": "https://registry.npmjs.org/react-chatbotify/-/react-chatbotify-2.0.0-beta.22.tgz", + "integrity": "sha512-NlD85BUuVug7VmkbNQTLNcYfXEjwDvz16vfshqx1IzvcMIYFqN4MqLJ36C3+RtGeVvPukuXi0tg1uNGbNSeAQw==", + "license": "MIT", + "peerDependencies": { + "react": ">=16.14.0 <20.0.0 || ^19.0.0-0", + "react-dom": ">=16.14.0 <20.0.0 || ^19.0.0-0" + } + }, "node_modules/react-codemirror2": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/react-codemirror2/-/react-codemirror2-8.0.0.tgz", @@ -6031,6 +6193,12 @@ "node": ">=8.0" } }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "license": "MIT" + }, "node_modules/ts-api-utils": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz", @@ -6215,7 +6383,6 @@ "version": "6.19.8", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", - "dev": true, "license": "MIT" }, "node_modules/update-browserslist-db": { @@ -6358,6 +6525,31 @@ "makeerror": "1.0.12" } }, + "node_modules/web-streams-polyfill": { + "version": "4.0.0-beta.3", + "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-4.0.0-beta.3.tgz", + "integrity": "sha512-QW95TCTaHmsYfHDybGMwO5IJIM93I/6vTRk+daHTWFPhwh+C8Cg7j7XyKrwrj8Ib6vYXe0ocYNrmzY4xAAN6ug==", + "license": "MIT", + "engines": { + "node": ">= 14" + } + }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "license": "BSD-2-Clause" + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "license": "MIT", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", diff --git a/peerprep/frontend/src/components/Chat.tsx b/peerprep/frontend/src/components/Chat.tsx new file mode 100644 index 0000000000..871bb8c887 --- /dev/null +++ b/peerprep/frontend/src/components/Chat.tsx @@ -0,0 +1,69 @@ +import React, { useState, useEffect } from 'react'; +import io from 'socket.io-client'; + +const socket = io('http://localhost:1234'); + +interface ChatProps { + sessionId: string; +} + +const Chat: React.FC = ({ sessionId }) => { + // Room State + const [room, setRoom] = useState(sessionId); + + // Messages States + const [message, setMessage] = useState(''); + const [messages, setMessages] = useState<{ text: string; sender: boolean }[]>([]); + + const joinRoom = () => { + if (room !== '') { + socket.emit('join_room', room); + } + }; + + const sendMessage = () => { + const messageData = { message, room, senderId: socket.id }; + socket.emit('send_message', messageData); + setMessages((prevMessages) => [...prevMessages, { text: message, sender: true }]); + setMessage(''); // Clear the input field after sending the message + }; + + useEffect(() => { + joinRoom(); // Automatically join the room based on sessionId + + socket.on('receive_message', (data) => { + if (data.senderId !== socket.id) { + setMessages((prevMessages) => [...prevMessages, { text: data.message, sender: false }]); + } + }); + + return () => { + socket.off('receive_message'); + }; + }, [room]); + + return ( +
+

Chat

+
+ {messages.map((msg, index) => ( +
+ {msg.text} +
+ ))} +
+
+ { + setMessage(event.target.value); + }} + /> + +
+
+ ); +}; + +export default Chat; \ No newline at end of file diff --git a/peerprep/frontend/src/styles/App.css b/peerprep/frontend/src/styles/App.css index 4b037f56c8..f59b3f0ed8 100644 --- a/peerprep/frontend/src/styles/App.css +++ b/peerprep/frontend/src/styles/App.css @@ -513,12 +513,22 @@ h2 { width: 100%; } -.editor-container { +.code-and-chat { + display: flex; width: 100%; height: 100%; max-width: 900px; min-height: 300px; flex-grow: 1; + position: relative; +} + +.editor-container { + width: 70%; + height: 100%; + max-width: 900px; + min-height: 300px; + flex-grow: 1; border: 2px solid #ccc; border-radius: 10px; box-shadow: 0px 4px 8px rgba(0, 0, 0, 0.1); @@ -531,6 +541,84 @@ h2 { vertical-align: top; /* Ensures text starts from the top */ } +.chat-box { + width: 30%; + display: flex; + flex-direction: column; + height: 100%; + border: 2px solid #ccc; + border-radius: 10px; + box-shadow: 0px 4px 8px rgba(0, 0, 0, 0.1); + background-color: white; + color: black; /* Changed to black for better readability */ +} + +.chat-heading{ + margin: 1px; +} + +.messages { + font-size: small; + flex-grow: 1; + overflow-y: auto; + padding: 5px; +} + +.message { + margin-bottom: 5px; + padding: 3px; + padding-left: 5px; + border-radius: 5px; + max-width: 60%; + overflow-x: scroll; + display: flex; +} + +.sent { + background-color: #dcf8c6; + align-self: flex-end; + margin-left: auto; +} + +.received { + background-color: #f1f0f0; + align-self: flex-start; + margin-right: auto; +} + +.input-container { + display: flex; + background-color: white; + padding-left: 2px; + padding-right: 2px; + padding-bottom: 2px; +} + +input { + flex-grow: 1; + padding: 5px; + border: 1px solid #ccc; + border-radius: 5px; + background-color: white; + margin-right: 2px; + color: black; + min-width: 0px; +} + +.sendBtn { + padding: 5px 10px; + border: none; + background-color: #007bff; + color: white; + border-radius: 5px; + cursor: pointer; + font-size: small; +} + +.sendBtn:hover { + background-color: #0056b3; +} + /* Header section styling */ .editor-header { text-align: center; @@ -681,4 +769,4 @@ h2 { font-size: 14px; margin-bottom: 15px; text-align: center; -} +} \ No newline at end of file diff --git a/peerprep/frontend/src/views/CollabServiceViews/CollabServiceIntegratedView.tsx b/peerprep/frontend/src/views/CollabServiceViews/CollabServiceIntegratedView.tsx index 95869ed215..2faf00c6d5 100644 --- a/peerprep/frontend/src/views/CollabServiceViews/CollabServiceIntegratedView.tsx +++ b/peerprep/frontend/src/views/CollabServiceViews/CollabServiceIntegratedView.tsx @@ -3,6 +3,7 @@ import { UnControlled as CodeMirror } from 'react-codemirror2'; import { useParams, useNavigate } from 'react-router-dom'; import axios from 'axios'; import * as Y from 'yjs'; +import Chat from '../../components/Chat.tsx'; import 'codemirror/lib/codemirror.css'; import 'codemirror/theme/material.css'; @@ -21,7 +22,7 @@ import { assesCode } from '../../api/assescodeApi.ts'; import { CodemirrorBinding } from 'y-codemirror'; import { WebsocketProvider } from 'y-websocket'; -import { listenToMatchStatus, deleteMatchedSession} from "../../api/matchingApi.ts"; +import { deleteMatchedSession} from "../../api/matchingApi.ts"; import { getQuestionById } from '../../api/questionApi.ts'; @@ -35,16 +36,17 @@ const CollaborationServiceIntegratedView: React.FC = () => { const navigate = useNavigate(); const [yText, setYText] = useState(null); const [commentoutput, setCommentOutput] = useState(null); + console.log(commentoutput); //let topic = 'topic'; //let difficulty = 'difficulty'; // Declare question object //extract questionID from session id (eg. 670d81daf90653ef4b9162b8-67094dcc6be97361a2e7cb1a-1730832550120-Q672890c43266d81a769bfaee) const [topics, setTopics] = useState('N/A'); const [difficulty, setDifficulty] = useState('N/A'); - const[questionTitle, setQuestionTitle] = useState('N/A'); - const[questionDescription, setQuestionDescription] = useState('N/A'); + const [questionTitle, setQuestionTitle] = useState('N/A'); + const [questionDescription, setQuestionDescription] = useState('N/A'); console.log(sessionId); - const questionId = sessionId? sessionId.split('-Q')[1] : "N/A"; + const questionId = sessionId ? sessionId.split('-Q')[1] : "N/A"; //set topic, difficulty, questionId by calling the API useEffect(() => { @@ -69,13 +71,6 @@ const CollaborationServiceIntegratedView: React.FC = () => { }, [sessionId]); // 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}, Topics: ${topics}, Difficulty: ${difficulty}`); @@ -121,13 +116,13 @@ const CollaborationServiceIntegratedView: React.FC = () => { const handleLangChange = (e: React.ChangeEvent) => { setLanguage(parseInt(e.target.value)); setSyntaxFullLang(e.target.textContent!); - 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'); + 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 () => { @@ -137,13 +132,13 @@ const CollaborationServiceIntegratedView: React.FC = () => { setOutput('Error: Yjs text instance is not available'); return; } - + const currentCode = yText.toString(); console.log('Submitting code for execution:', currentCode); - + // Base64 encode the source code if required by the API const base64EncodedCode = btoa(currentCode); // `btoa()` encodes a string to base64 - + // Make a POST request to Judge0 API for code execution const response = await axios.post('https://judge0-ce.p.rapidapi.com/submissions?base64_encoded=true&wait=false&fields=*', { language_id: language, // Ensure `language` is set correctly in your component @@ -156,13 +151,13 @@ const CollaborationServiceIntegratedView: React.FC = () => { 'x-rapidapi-key': 'f5d59ce024msha6cd5fccde3d182p14459fjsn8a83590f92b4' } }); - + console.log('Submission response:', response.data); - + // Polling for the result of the code execution const token = response.data.token; let result = null; - + while (!result || result.status.id <= 2) { console.log(`Polling result for token: ${token}`); const statusResponse = await axios.get(`https://judge0-ce.p.rapidapi.com/submissions/${token}?base64_encoded=true&fields=*`, { @@ -171,16 +166,16 @@ const CollaborationServiceIntegratedView: React.FC = () => { 'x-rapidapi-key': 'f5d59ce024msha6cd5fccde3d182p14459fjsn8a83590f92b4' } }); - + result = statusResponse.data; - + // Decode the output if it's base64-encoded const decodedOutput = result.stdout ? atob(result.stdout) : (result.stderr ? atob(result.stderr) : 'No output'); console.log('Polling response:', result); - + // Wait for a short duration before the next poll (e.g., 1 second) await new Promise(resolve => setTimeout(resolve, 1000)); - + // Set the output only when status is finished if (result.status.id > 2) { setOutput(decodedOutput); @@ -199,7 +194,7 @@ const CollaborationServiceIntegratedView: React.FC = () => { setCommentOutput('Error: Yjs text instance is not available'); return; } - + const currentCode = yText.toString(); const inputString = "LANGUAGE SPECIFIED IS: " + syntaxFullLang + "\n" + currentCode; const responseContent = await assesCode(inputString); @@ -218,92 +213,96 @@ const CollaborationServiceIntegratedView: React.FC = () => {

Topics: {topics} | Difficulty: {difficulty}

Question: {questionTitle}

Description: {questionDescription}

- - -
- + +
+
+ handleLangChange(e) - } - required - > - {/* Placeholder option */} - - - - - - - -
-
- - + {/* Placeholder option */} + + + + + + + +
+ + + +
- { - 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 }); - } - }); + 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 + // Let Yjs handle all updates; do not use setCode here }} - /> + />
- + {sessionId && } +
+

Output

-
+
+
{output}
{/*
{commentoutput}
*/} -
+ ); }; diff --git a/peerprep/frontend/yarn.lock b/peerprep/frontend/yarn.lock index 76667be07e..00d9591bb7 100644 --- a/peerprep/frontend/yarn.lock +++ b/peerprep/frontend/yarn.lock @@ -664,10 +664,8 @@ resolved "https://registry.npmjs.org/@remix-run/router/-/router-1.19.2.tgz" integrity sha512-baiMx18+IMuD1yyvOGaHM9QrVUPGGG0jC+z+IPHnRJWUAUvaKuWKyE8gjDj2rzv3sz9zOGoRSPgeBVHRhZnBlA== -"@rollup/rollup-darwin-arm64@4.24.4": - version "4.24.4" - resolved "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.24.4.tgz" - integrity sha512-GmU/QgGtBTeraKyldC7cDVVvAJEOr3dFLKneez/n7BvX57UdhOqDsVwzU7UOnYA7AAOt+Xb26lk79PldDHgMIQ== +"@rollup/rollup-darwin-arm64@4.22.0": + version "4.22.0" "@sinclair/typebox@^0.27.8": version "0.27.8" @@ -785,10 +783,10 @@ dependencies: "@babel/types" "^7.20.7" -"@types/estree@1.0.6": - version "1.0.6" - resolved "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz" - integrity sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw== +"@types/estree@1.0.5": + version "1.0.5" + resolved "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz" + integrity sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw== "@types/graceful-fs@^4.1.3": version "4.1.9" @@ -3186,30 +3184,28 @@ reusify@^1.0.4: integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== rollup@^4.20.0: - version "4.24.4" - resolved "https://registry.npmjs.org/rollup/-/rollup-4.24.4.tgz" - integrity sha512-vGorVWIsWfX3xbcyAS+I047kFKapHYivmkaT63Smj77XwvLSJos6M1xGqZnBPFQFBRZDOcG1QnYEIxAvTr/HjA== + version "4.22.0" + resolved "https://registry.npmjs.org/rollup/-/rollup-4.22.0.tgz" + integrity sha512-W21MUIFPZ4+O2Je/EU+GP3iz7PH4pVPUXSbEZdatQnxo29+3rsUjgrJmzuAZU24z7yRAnFN6ukxeAhZh/c7hzg== dependencies: - "@types/estree" "1.0.6" + "@types/estree" "1.0.5" optionalDependencies: - "@rollup/rollup-android-arm-eabi" "4.24.4" - "@rollup/rollup-android-arm64" "4.24.4" - "@rollup/rollup-darwin-arm64" "4.24.4" - "@rollup/rollup-darwin-x64" "4.24.4" - "@rollup/rollup-freebsd-arm64" "4.24.4" - "@rollup/rollup-freebsd-x64" "4.24.4" - "@rollup/rollup-linux-arm-gnueabihf" "4.24.4" - "@rollup/rollup-linux-arm-musleabihf" "4.24.4" - "@rollup/rollup-linux-arm64-gnu" "4.24.4" - "@rollup/rollup-linux-arm64-musl" "4.24.4" - "@rollup/rollup-linux-powerpc64le-gnu" "4.24.4" - "@rollup/rollup-linux-riscv64-gnu" "4.24.4" - "@rollup/rollup-linux-s390x-gnu" "4.24.4" - "@rollup/rollup-linux-x64-gnu" "4.24.4" - "@rollup/rollup-linux-x64-musl" "4.24.4" - "@rollup/rollup-win32-arm64-msvc" "4.24.4" - "@rollup/rollup-win32-ia32-msvc" "4.24.4" - "@rollup/rollup-win32-x64-msvc" "4.24.4" + "@rollup/rollup-android-arm-eabi" "4.22.0" + "@rollup/rollup-android-arm64" "4.22.0" + "@rollup/rollup-darwin-arm64" "4.22.0" + "@rollup/rollup-darwin-x64" "4.22.0" + "@rollup/rollup-linux-arm-gnueabihf" "4.22.0" + "@rollup/rollup-linux-arm-musleabihf" "4.22.0" + "@rollup/rollup-linux-arm64-gnu" "4.22.0" + "@rollup/rollup-linux-arm64-musl" "4.22.0" + "@rollup/rollup-linux-powerpc64le-gnu" "4.22.0" + "@rollup/rollup-linux-riscv64-gnu" "4.22.0" + "@rollup/rollup-linux-s390x-gnu" "4.22.0" + "@rollup/rollup-linux-x64-gnu" "4.22.0" + "@rollup/rollup-linux-x64-musl" "4.22.0" + "@rollup/rollup-win32-arm64-msvc" "4.22.0" + "@rollup/rollup-win32-ia32-msvc" "4.22.0" + "@rollup/rollup-win32-x64-msvc" "4.22.0" fsevents "~2.3.2" run-parallel@^1.1.9: From b3639745a779099e2e6d16f7816e10235ea0c7c3 Mon Sep 17 00:00:00 2001 From: Suryansh Kushwaha <112935210+suryanshkushwaha@users.noreply.github.com> Date: Wed, 6 Nov 2024 20:38:07 +0530 Subject: [PATCH 2/3] fixed genAi integration --- peerprep/backend/question-service/.env | 2 +- peerprep/frontend/src/styles/App.css | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/peerprep/backend/question-service/.env b/peerprep/backend/question-service/.env index 8262f85978..89aa0b5e2d 100644 --- a/peerprep/backend/question-service/.env +++ b/peerprep/backend/question-service/.env @@ -1,2 +1,2 @@ PORT=8080 -MONGODB_URI = "mongodb+srv://common:T4mRbfIFytNk4xuU@questionservice.true3.mongodb.net/?retryWrites=true&w=majority&appName=QuestionService" \ No newline at end of file +MONGODB_URI = "mongodb+srv://common:T4mRbfIFytNk4xuU@questionservice.true3.mongodb.net/?retryWrites=true&w=majority&appName=QuestionService" diff --git a/peerprep/frontend/src/styles/App.css b/peerprep/frontend/src/styles/App.css index f59b3f0ed8..306cb0b92a 100644 --- a/peerprep/frontend/src/styles/App.css +++ b/peerprep/frontend/src/styles/App.css @@ -769,4 +769,8 @@ input { font-size: 14px; margin-bottom: 15px; text-align: center; +} + +.output-container{ + overflow-y: scroll; } \ No newline at end of file From 228828c08e5c531cd9ff2d318d855f9130465ad3 Mon Sep 17 00:00:00 2001 From: Rubesh Date: Wed, 6 Nov 2024 23:56:09 +0800 Subject: [PATCH 3/3] Update peerprep/frontend/src/views/CollabServiceViews/CollabServiceIntegratedView.tsx --- .../views/CollabServiceViews/CollabServiceIntegratedView.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/peerprep/frontend/src/views/CollabServiceViews/CollabServiceIntegratedView.tsx b/peerprep/frontend/src/views/CollabServiceViews/CollabServiceIntegratedView.tsx index 2faf00c6d5..8032759d3a 100644 --- a/peerprep/frontend/src/views/CollabServiceViews/CollabServiceIntegratedView.tsx +++ b/peerprep/frontend/src/views/CollabServiceViews/CollabServiceIntegratedView.tsx @@ -295,7 +295,7 @@ const CollaborationServiceIntegratedView: React.FC = () => {

Output

-
+
{output}