From ced3dfd25b97d34ddea254a5dcfbd76fbad90188 Mon Sep 17 00:00:00 2001 From: zylee348 Date: Tue, 17 Oct 2023 22:45:55 +0800 Subject: [PATCH 01/76] Add files --- package-lock.json | 173 +++++++++++ package.json | 4 + src/App.jsx | 4 +- .../collab_elements/codeEditorWindow.jsx | 27 ++ .../collab_elements/customInput.jsx | 21 ++ .../collab_elements/customStyles.js | 54 ++++ src/components/collab_elements/defineTheme.js | 66 ++++ src/components/collab_elements/general.js | 3 + .../collab_elements/languageOptions.js | 280 +++++++++++++++++ .../collab_elements/languagesDropdown.jsx | 18 ++ .../collab_elements/outputDetails.jsx | 28 ++ .../collab_elements/outputWindow.jsx | 48 +++ .../collab_elements/themeDropdown.jsx | 23 ++ src/components/hooks/useKeyPress.js | 31 ++ src/pages/Room.jsx | 282 ++++++++++++++++++ 15 files changed, 1060 insertions(+), 2 deletions(-) create mode 100644 src/components/collab_elements/codeEditorWindow.jsx create mode 100644 src/components/collab_elements/customInput.jsx create mode 100644 src/components/collab_elements/customStyles.js create mode 100644 src/components/collab_elements/defineTheme.js create mode 100644 src/components/collab_elements/general.js create mode 100644 src/components/collab_elements/languageOptions.js create mode 100644 src/components/collab_elements/languagesDropdown.jsx create mode 100644 src/components/collab_elements/outputDetails.jsx create mode 100644 src/components/collab_elements/outputWindow.jsx create mode 100644 src/components/collab_elements/themeDropdown.jsx create mode 100644 src/components/hooks/useKeyPress.js create mode 100644 src/pages/Room.jsx diff --git a/package-lock.json b/package-lock.json index efb8c4ca..7b7a7d5f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16,6 +16,7 @@ "@mantine/hooks": "^7.1.3", "@mantine/modals": "^7.1.3", "@mantine/notifications": "^7.1.3", + "@monaco-editor/react": "^4.6.0", "@mui/material": "^5.14.8", "@reduxjs/toolkit": "^1.9.6", "@tabler/icons-react": "^2.36.0", @@ -31,6 +32,7 @@ "express-jsdoc-swagger": "^1.8.0", "i": "^0.3.7", "js-cookie": "^3.0.5", + "monaco-themes": "^0.4.4", "mongoose": "^7.5.2", "nodemon": "^3.0.1", "pg": "^8.11.3", @@ -41,6 +43,8 @@ "react-redux": "^8.1.3", "react-router-dom": "^6.16.0", "react-scripts": "^5.0.1", + "react-select": "^5.7.7", + "react-toastify": "^9.1.3", "redux-persist": "^6.0.0", "sass": "^1.68.0", "semantic-ui-css": "^2.5.0", @@ -4048,6 +4052,30 @@ "react": "^18.2.0" } }, + "node_modules/@monaco-editor/loader": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@monaco-editor/loader/-/loader-1.4.0.tgz", + "integrity": "sha512-00ioBig0x642hytVspPl7DbQyaSWRaolYie/UFNjoTdvoKPzo6xrXLhTk9ixgIKcLH5b5vDOjVNiGyY+uDCUlg==", + "dependencies": { + "state-local": "^1.0.6" + }, + "peerDependencies": { + "monaco-editor": ">= 0.21.0 < 1" + } + }, + "node_modules/@monaco-editor/react": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/@monaco-editor/react/-/react-4.6.0.tgz", + "integrity": "sha512-RFkU9/i7cN2bsq/iTkurMWOEErmYcY6JiQI3Jn+WeR/FGISH8JbHERjpS9oRuSOPvDMJI0Z8nJeKkbOs9sBYQw==", + "dependencies": { + "@monaco-editor/loader": "^1.4.0" + }, + "peerDependencies": { + "monaco-editor": ">= 0.25.0 < 1", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, "node_modules/@mongodb-js/saslprep": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.1.0.tgz", @@ -9639,6 +9667,11 @@ "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==" }, + "node_modules/fast-plist": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/fast-plist/-/fast-plist-0.1.3.tgz", + "integrity": "sha512-d9cEfo/WcOezgPLAC/8t8wGb6YOD6JTCPMw2QcG2nAdFmyY+9rTUizCTaGjIZAloWENTEUMAPpkUAIJJJ0i96A==" + }, "node_modules/fastq": { "version": "1.15.0", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", @@ -14021,6 +14054,11 @@ "node": ">= 4.0.0" } }, + "node_modules/memoize-one": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-6.0.0.tgz", + "integrity": "sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw==" + }, "node_modules/memory-pager": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz", @@ -14231,6 +14269,20 @@ "ufo": "^1.3.0" } }, + "node_modules/monaco-editor": { + "version": "0.44.0", + "resolved": "https://registry.npmjs.org/monaco-editor/-/monaco-editor-0.44.0.tgz", + "integrity": "sha512-5SmjNStN6bSuSE5WPT2ZV+iYn1/yI9sd4Igtk23ChvqB7kDk9lZbB9F5frsuvpB+2njdIeGGFf2G4gbE6rCC9Q==", + "peer": true + }, + "node_modules/monaco-themes": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/monaco-themes/-/monaco-themes-0.4.4.tgz", + "integrity": "sha512-Hbb9pvRrpSi0rZezcB/IOdQnpx10o55Lx4zFdRAAVpFMa1HP7FgaqEZdKffb4ovd90fETCixeFO9JPYFMAq+TQ==", + "dependencies": { + "fast-plist": "^0.1.3" + } + }, "node_modules/mongodb": { "version": "5.9.0", "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-5.9.0.tgz", @@ -17151,6 +17203,26 @@ "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" }, + "node_modules/react-select": { + "version": "5.7.7", + "resolved": "https://registry.npmjs.org/react-select/-/react-select-5.7.7.tgz", + "integrity": "sha512-HhashZZJDRlfF/AKj0a0Lnfs3sRdw/46VJIRd8IbB9/Ovr74+ZIwkAdSBjSPXsFMG+u72c5xShqwLSKIJllzqw==", + "dependencies": { + "@babel/runtime": "^7.12.0", + "@emotion/cache": "^11.4.0", + "@emotion/react": "^11.8.1", + "@floating-ui/dom": "^1.0.1", + "@types/react-transition-group": "^4.4.0", + "memoize-one": "^6.0.0", + "prop-types": "^15.6.0", + "react-transition-group": "^4.3.0", + "use-isomorphic-layout-effect": "^1.1.2" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, "node_modules/react-style-singleton": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/react-style-singleton/-/react-style-singleton-2.2.1.tgz", @@ -17189,6 +17261,26 @@ "react": "^16.8.0 || ^17.0.0 || ^18.0.0" } }, + "node_modules/react-toastify": { + "version": "9.1.3", + "resolved": "https://registry.npmjs.org/react-toastify/-/react-toastify-9.1.3.tgz", + "integrity": "sha512-fPfb8ghtn/XMxw3LkxQBk3IyagNpF/LIKjOBflbexr2AWxAH1MJgvnESwEwBn9liLFXgTKWgBSdZpw9m4OTHTg==", + "dependencies": { + "clsx": "^1.1.1" + }, + "peerDependencies": { + "react": ">=16", + "react-dom": ">=16" + } + }, + "node_modules/react-toastify/node_modules/clsx": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-1.2.1.tgz", + "integrity": "sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==", + "engines": { + "node": ">=6" + } + }, "node_modules/react-transition-group": { "version": "4.4.5", "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz", @@ -18364,6 +18456,11 @@ "resolved": "https://registry.npmjs.org/stackframe/-/stackframe-1.3.4.tgz", "integrity": "sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw==" }, + "node_modules/state-local": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/state-local/-/state-local-1.0.7.tgz", + "integrity": "sha512-HTEHMNieakEnoe33shBYcZ7NX83ACUjCu8c40iOGEZsngj9zRnkqS9j1pqQPXwobB0ZcVTk27REb7COQ0UR59w==" + }, "node_modules/static-eval": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/static-eval/-/static-eval-2.0.2.tgz", @@ -23677,6 +23774,22 @@ "integrity": "sha512-fjgZyW9TPk/rCewYaMygyUB6Bos0PspgYiSGCx3g81OzzdTjBhtq+xU2Lgb8YPaPhMsTDWZI+TOqceqQg12Cqw==", "requires": {} }, + "@monaco-editor/loader": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@monaco-editor/loader/-/loader-1.4.0.tgz", + "integrity": "sha512-00ioBig0x642hytVspPl7DbQyaSWRaolYie/UFNjoTdvoKPzo6xrXLhTk9ixgIKcLH5b5vDOjVNiGyY+uDCUlg==", + "requires": { + "state-local": "^1.0.6" + } + }, + "@monaco-editor/react": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/@monaco-editor/react/-/react-4.6.0.tgz", + "integrity": "sha512-RFkU9/i7cN2bsq/iTkurMWOEErmYcY6JiQI3Jn+WeR/FGISH8JbHERjpS9oRuSOPvDMJI0Z8nJeKkbOs9sBYQw==", + "requires": { + "@monaco-editor/loader": "^1.4.0" + } + }, "@mongodb-js/saslprep": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.1.0.tgz", @@ -27770,6 +27883,11 @@ "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==" }, + "fast-plist": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/fast-plist/-/fast-plist-0.1.3.tgz", + "integrity": "sha512-d9cEfo/WcOezgPLAC/8t8wGb6YOD6JTCPMw2QcG2nAdFmyY+9rTUizCTaGjIZAloWENTEUMAPpkUAIJJJ0i96A==" + }, "fastq": { "version": "1.15.0", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", @@ -31078,6 +31196,11 @@ "fs-monkey": "^1.0.4" } }, + "memoize-one": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-6.0.0.tgz", + "integrity": "sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw==" + }, "memory-pager": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz", @@ -31230,6 +31353,20 @@ "ufo": "^1.3.0" } }, + "monaco-editor": { + "version": "0.44.0", + "resolved": "https://registry.npmjs.org/monaco-editor/-/monaco-editor-0.44.0.tgz", + "integrity": "sha512-5SmjNStN6bSuSE5WPT2ZV+iYn1/yI9sd4Igtk23ChvqB7kDk9lZbB9F5frsuvpB+2njdIeGGFf2G4gbE6rCC9Q==", + "peer": true + }, + "monaco-themes": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/monaco-themes/-/monaco-themes-0.4.4.tgz", + "integrity": "sha512-Hbb9pvRrpSi0rZezcB/IOdQnpx10o55Lx4zFdRAAVpFMa1HP7FgaqEZdKffb4ovd90fETCixeFO9JPYFMAq+TQ==", + "requires": { + "fast-plist": "^0.1.3" + } + }, "mongodb": { "version": "5.9.0", "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-5.9.0.tgz", @@ -33130,6 +33267,22 @@ } } }, + "react-select": { + "version": "5.7.7", + "resolved": "https://registry.npmjs.org/react-select/-/react-select-5.7.7.tgz", + "integrity": "sha512-HhashZZJDRlfF/AKj0a0Lnfs3sRdw/46VJIRd8IbB9/Ovr74+ZIwkAdSBjSPXsFMG+u72c5xShqwLSKIJllzqw==", + "requires": { + "@babel/runtime": "^7.12.0", + "@emotion/cache": "^11.4.0", + "@emotion/react": "^11.8.1", + "@floating-ui/dom": "^1.0.1", + "@types/react-transition-group": "^4.4.0", + "memoize-one": "^6.0.0", + "prop-types": "^15.6.0", + "react-transition-group": "^4.3.0", + "use-isomorphic-layout-effect": "^1.1.2" + } + }, "react-style-singleton": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/react-style-singleton/-/react-style-singleton-2.2.1.tgz", @@ -33150,6 +33303,21 @@ "use-latest": "^1.2.1" } }, + "react-toastify": { + "version": "9.1.3", + "resolved": "https://registry.npmjs.org/react-toastify/-/react-toastify-9.1.3.tgz", + "integrity": "sha512-fPfb8ghtn/XMxw3LkxQBk3IyagNpF/LIKjOBflbexr2AWxAH1MJgvnESwEwBn9liLFXgTKWgBSdZpw9m4OTHTg==", + "requires": { + "clsx": "^1.1.1" + }, + "dependencies": { + "clsx": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-1.2.1.tgz", + "integrity": "sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==" + } + } + }, "react-transition-group": { "version": "4.4.5", "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz", @@ -34024,6 +34192,11 @@ "resolved": "https://registry.npmjs.org/stackframe/-/stackframe-1.3.4.tgz", "integrity": "sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw==" }, + "state-local": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/state-local/-/state-local-1.0.7.tgz", + "integrity": "sha512-HTEHMNieakEnoe33shBYcZ7NX83ACUjCu8c40iOGEZsngj9zRnkqS9j1pqQPXwobB0ZcVTk27REb7COQ0UR59w==" + }, "static-eval": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/static-eval/-/static-eval-2.0.2.tgz", diff --git a/package.json b/package.json index d0e9d369..4e096333 100644 --- a/package.json +++ b/package.json @@ -17,6 +17,7 @@ "@mantine/hooks": "^7.1.3", "@mantine/modals": "^7.1.3", "@mantine/notifications": "^7.1.3", + "@monaco-editor/react": "^4.6.0", "@mui/material": "^5.14.8", "@reduxjs/toolkit": "^1.9.6", "@tabler/icons-react": "^2.36.0", @@ -32,6 +33,7 @@ "express-jsdoc-swagger": "^1.8.0", "i": "^0.3.7", "js-cookie": "^3.0.5", + "monaco-themes": "^0.4.4", "mongoose": "^7.5.2", "nodemon": "^3.0.1", "pg": "^8.11.3", @@ -42,6 +44,8 @@ "react-redux": "^8.1.3", "react-router-dom": "^6.16.0", "react-scripts": "^5.0.1", + "react-select": "^5.7.7", + "react-toastify": "^9.1.3", "redux-persist": "^6.0.0", "sass": "^1.68.0", "semantic-ui-css": "^2.5.0", diff --git a/src/App.jsx b/src/App.jsx index 27ec440d..cc1f47c4 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -5,7 +5,7 @@ import ViewQuestions from "./pages/ViewQuestions"; import Settings from "./pages/Settings"; import UserProfile from "./pages/UserProfile"; import Home from "./pages/Home"; -import MatchFound from "./components/matching_elements/matchFound" +import Room from "./pages/Room" // import Login from "./pages/Login"; // import Profile from "./components/profile"; import { BrowserRouter as Router, Route, Routes } from "react-router-dom"; @@ -29,7 +29,7 @@ function App() { } /> } /> } /> - }/> + }/> } /> diff --git a/src/components/collab_elements/codeEditorWindow.jsx b/src/components/collab_elements/codeEditorWindow.jsx new file mode 100644 index 00000000..370d5924 --- /dev/null +++ b/src/components/collab_elements/codeEditorWindow.jsx @@ -0,0 +1,27 @@ +import React, { useState } from "react"; + +import Editor from "@monaco-editor/react"; + +const CodeEditorWindow = ({ onChange, language, code, theme }) => { + const [value, setValue] = useState(code || ""); + + const handleEditorChange = (value) => { + setValue(value); + onChange("code", value); + }; + + return ( +
+ +
+ ); +}; +export default CodeEditorWindow; \ No newline at end of file diff --git a/src/components/collab_elements/customInput.jsx b/src/components/collab_elements/customInput.jsx new file mode 100644 index 00000000..bf8a811b --- /dev/null +++ b/src/components/collab_elements/customInput.jsx @@ -0,0 +1,21 @@ +import React from "react"; +import { classnames } from "./general"; + +const CustomInput = ({ customInput, setCustomInput }) => { + return ( + <> + {" "} + + + ); +}; + +export default CustomInput; \ No newline at end of file diff --git a/src/components/collab_elements/customStyles.js b/src/components/collab_elements/customStyles.js new file mode 100644 index 00000000..9d6cc23f --- /dev/null +++ b/src/components/collab_elements/customStyles.js @@ -0,0 +1,54 @@ +export const customStyles = { + control: (styles) => ({ + ...styles, + width: "100%", + maxWidth: "14rem", + minWidth: "12rem", + borderRadius: "5px", + color: "#000", + fontSize: "0.8rem", + lineHeight: "1.75rem", + backgroundColor: "#FFFFFF", + cursor: "pointer", + border: "2px solid #000000", + boxShadow: "5px 5px 0px 0px rgba(0,0,0);", + ":hover": { + border: "2px solid #000000", + boxShadow: "none", + }, + }), + option: (styles) => { + return { + ...styles, + color: "#000", + fontSize: "0.8rem", + lineHeight: "1.75rem", + width: "100%", + background: "#fff", + ":hover": { + backgroundColor: "rgb(243 244 246)", + color: "#000", + cursor: "pointer", + }, + }; + }, + menu: (styles) => { + return { + ...styles, + backgroundColor: "#fff", + maxWidth: "14rem", + border: "2px solid #000000", + borderRadius: "5px", + boxShadow: "5px 5px 0px 0px rgba(0,0,0);", + }; + }, + + placeholder: (defaultStyles) => { + return { + ...defaultStyles, + color: "#000", + fontSize: "0.8rem", + lineHeight: "1.75rem", + }; + }, + }; \ No newline at end of file diff --git a/src/components/collab_elements/defineTheme.js b/src/components/collab_elements/defineTheme.js new file mode 100644 index 00000000..f093dc51 --- /dev/null +++ b/src/components/collab_elements/defineTheme.js @@ -0,0 +1,66 @@ +import { loader } from "@monaco-editor/react"; + +const monacoThemes = { + active4d: "Active4D", + "all-hallows-eve": "All Hallows Eve", + amy: "Amy", + "birds-of-paradise": "Birds of Paradise", + blackboard: "Blackboard", + "brilliance-black": "Brilliance Black", + "brilliance-dull": "Brilliance Dull", + "chrome-devtools": "Chrome DevTools", + "clouds-midnight": "Clouds Midnight", + clouds: "Clouds", + cobalt: "Cobalt", + dawn: "Dawn", + dreamweaver: "Dreamweaver", + eiffel: "Eiffel", + "espresso-libre": "Espresso Libre", + github: "GitHub", + idle: "IDLE", + katzenmilch: "Katzenmilch", + "kuroir-theme": "Kuroir Theme", + lazy: "LAZY", + "magicwb--amiga-": "MagicWB (Amiga)", + "merbivore-soft": "Merbivore Soft", + merbivore: "Merbivore", + "monokai-bright": "Monokai Bright", + monokai: "Monokai", + "night-owl": "Night Owl", + "oceanic-next": "Oceanic Next", + "pastels-on-dark": "Pastels on Dark", + "slush-and-poppies": "Slush and Poppies", + "solarized-dark": "Solarized-dark", + "solarized-light": "Solarized-light", + spacecadet: "SpaceCadet", + sunburst: "Sunburst", + "textmate--mac-classic-": "Textmate (Mac Classic)", + "tomorrow-night-blue": "Tomorrow-Night-Blue", + "tomorrow-night-bright": "Tomorrow-Night-Bright", + "tomorrow-night-eighties": "Tomorrow-Night-Eighties", + "tomorrow-night": "Tomorrow-Night", + tomorrow: "Tomorrow", + twilight: "Twilight", + "upstream-sunburst": "Upstream Sunburst", + "vibrant-ink": "Vibrant Ink", + "xcode-default": "Xcode_default", + zenburnesque: "Zenburnesque", + iplastic: "iPlastic", + idlefingers: "idleFingers", + krtheme: "krTheme", + monoindustrial: "monoindustrial", +}; + +const defineTheme = (theme) => { + return new Promise((res) => { + Promise.all([ + loader.init(), + import(`monaco-themes/themes/${monacoThemes[theme]}.json`), + ]).then(([monaco, themeData]) => { + monaco.editor.defineTheme(theme, themeData); + res(); + }); + }); +}; + +export { defineTheme }; \ No newline at end of file diff --git a/src/components/collab_elements/general.js b/src/components/collab_elements/general.js new file mode 100644 index 00000000..3d5eea33 --- /dev/null +++ b/src/components/collab_elements/general.js @@ -0,0 +1,3 @@ +export const classnames = (...args) => { + return args.join(" "); + }; \ No newline at end of file diff --git a/src/components/collab_elements/languageOptions.js b/src/components/collab_elements/languageOptions.js new file mode 100644 index 00000000..ad4e75d1 --- /dev/null +++ b/src/components/collab_elements/languageOptions.js @@ -0,0 +1,280 @@ +export const languageOptions = [ + { + id: 63, + name: "JavaScript (Node.js 12.14.0)", + label: "JavaScript (Node.js 12.14.0)", + value: "javascript", + }, + { + id: 45, + name: "Assembly (NASM 2.14.02)", + label: "Assembly (NASM 2.14.02)", + value: "assembly", + }, + { + id: 46, + name: "Bash (5.0.0)", + label: "Bash (5.0.0)", + value: "bash", + }, + { + id: 47, + name: "Basic (FBC 1.07.1)", + label: "Basic (FBC 1.07.1)", + value: "basic", + }, + { + id: 75, + name: "C (Clang 7.0.1)", + label: "C (Clang 7.0.1)", + value: "c", + }, + { + id: 76, + name: "C++ (Clang 7.0.1)", + label: "C++ (Clang 7.0.1)", + value: "cpp", + }, + { + id: 48, + name: "C (GCC 7.4.0)", + label: "C (GCC 7.4.0)", + value: "c", + }, + { + id: 52, + name: "C++ (GCC 7.4.0)", + label: "C++ (GCC 7.4.0)", + value: "cpp", + }, + { + id: 49, + name: "C (GCC 8.3.0)", + label: "C (GCC 8.3.0)", + value: "c", + }, + { + id: 53, + name: "C++ (GCC 8.3.0)", + label: "C++ (GCC 8.3.0)", + value: "cpp", + }, + { + id: 50, + name: "C (GCC 9.2.0)", + label: "C (GCC 9.2.0)", + value: "c", + }, + { + id: 54, + name: "C++ (GCC 9.2.0)", + label: "C++ (GCC 9.2.0)", + value: "cpp", + }, + { + id: 86, + name: "Clojure (1.10.1)", + label: "Clojure (1.10.1)", + value: "clojure", + }, + { + id: 51, + name: "C# (Mono 6.6.0.161)", + label: "C# (Mono 6.6.0.161)", + value: "csharp", + }, + { + id: 77, + name: "COBOL (GnuCOBOL 2.2)", + label: "COBOL (GnuCOBOL 2.2)", + value: "cobol", + }, + { + id: 55, + name: "Common Lisp (SBCL 2.0.0)", + label: "Common Lisp (SBCL 2.0.0)", + value: "lisp", + }, + { + id: 56, + name: "D (DMD 2.089.1)", + label: "D (DMD 2.089.1)", + value: "d", + }, + { + id: 57, + name: "Elixir (1.9.4)", + label: "Elixir (1.9.4)", + value: "elixir", + }, + { + id: 58, + name: "Erlang (OTP 22.2)", + label: "Erlang (OTP 22.2)", + value: "erlang", + }, + { + id: 44, + label: "Executable", + name: "Executable", + value: "exe", + }, + { + id: 87, + name: "F# (.NET Core SDK 3.1.202)", + label: "F# (.NET Core SDK 3.1.202)", + value: "fsharp", + }, + { + id: 59, + name: "Fortran (GFortran 9.2.0)", + label: "Fortran (GFortran 9.2.0)", + value: "fortran", + }, + { + id: 60, + name: "Go (1.13.5)", + label: "Go (1.13.5)", + value: "go", + }, + { + id: 88, + name: "Groovy (3.0.3)", + label: "Groovy (3.0.3)", + value: "groovy", + }, + { + id: 61, + name: "Haskell (GHC 8.8.1)", + label: "Haskell (GHC 8.8.1)", + value: "haskell", + }, + { + id: 62, + name: "Java (OpenJDK 13.0.1)", + label: "Java (OpenJDK 13.0.1)", + value: "java", + }, + + { + id: 78, + name: "Kotlin (1.3.70)", + label: "Kotlin (1.3.70)", + value: "kotlin", + }, + { + id: 64, + name: "Lua (5.3.5)", + label: "Lua (5.3.5)", + value: "lua", + }, + + { + id: 79, + name: "Objective-C (Clang 7.0.1)", + label: "Objective-C (Clang 7.0.1)", + value: "objectivec", + }, + { + id: 65, + name: "OCaml (4.09.0)", + label: "OCaml (4.09.0)", + value: "ocaml", + }, + { + id: 66, + name: "Octave (5.1.0)", + label: "Octave (5.1.0)", + value: "octave", + }, + { + id: 67, + name: "Pascal (FPC 3.0.4)", + label: "Pascal (FPC 3.0.4)", + value: "pascal", + }, + { + id: 85, + name: "Perl (5.28.1)", + label: "Perl (5.28.1)", + value: "perl", + }, + { + id: 68, + name: "PHP (7.4.1)", + label: "PHP (7.4.1)", + value: "php", + }, + { + id: 43, + label: "Plain Text", + name: "Plain Text", + value: "text", + }, + { + id: 69, + name: "Prolog (GNU Prolog 1.4.5)", + label: "Prolog (GNU Prolog 1.4.5)", + value: "prolog", + }, + { + id: 70, + name: "Python (2.7.17)", + label: "Python (2.7.17)", + value: "python", + }, + { + id: 71, + name: "Python (3.8.1)", + label: "Python (3.8.1)", + value: "python", + }, + { + id: 80, + name: "R (4.0.0)", + label: "R (4.0.0)", + value: "r", + }, + { + id: 72, + name: "Ruby (2.7.0)", + label: "Ruby (2.7.0)", + value: "ruby", + }, + { + id: 73, + name: "Rust (1.40.0)", + label: "Rust (1.40.0)", + value: "rust", + }, + { + id: 81, + name: "Scala (2.13.2)", + label: "Scala (2.13.2)", + value: "scala", + }, + { + id: 82, + name: "SQL (SQLite 3.27.2)", + label: "SQL (SQLite 3.27.2)", + value: "sql", + }, + { + id: 83, + name: "Swift (5.2.3)", + label: "Swift (5.2.3)", + value: "swift", + }, + { + id: 74, + name: "TypeScript (3.7.4)", + label: "TypeScript (3.7.4)", + value: "typescript", + }, + { + id: 84, + name: "Visual Basic.Net (vbnc 0.0.0.5943)", + label: "Visual Basic.Net (vbnc 0.0.0.5943)", + value: "vbnet", + }, + ]; \ No newline at end of file diff --git a/src/components/collab_elements/languagesDropdown.jsx b/src/components/collab_elements/languagesDropdown.jsx new file mode 100644 index 00000000..17d6ac88 --- /dev/null +++ b/src/components/collab_elements/languagesDropdown.jsx @@ -0,0 +1,18 @@ +import React from "react"; +import Select from "react-select"; +// import { customStyles } from "../constants/customStyles"; +import { languageOptions } from "./languageOptions"; + +const LanguagesDropdown = ({ onSelectChange }) => { + return ( + ({ + label: themeName, + value: themeId, + key: themeId, + }))} + value={theme} + styles={customStyles} + onChange={handleThemeChange} + /> + ); +}; + +export default ThemeDropdown; \ No newline at end of file diff --git a/src/components/hooks/useKeyPress.js b/src/components/hooks/useKeyPress.js new file mode 100644 index 00000000..c72ddc4c --- /dev/null +++ b/src/components/hooks/useKeyPress.js @@ -0,0 +1,31 @@ +import React, { useState } from "react"; + +const useKeyPress = function (targetKey) { + const [keyPressed, setKeyPressed] = useState(false); + + function downHandler({ key }) { + if (key === targetKey) { + setKeyPressed(true); + } + } + + const upHandler = ({ key }) => { + if (key === targetKey) { + setKeyPressed(false); + } + }; + + React.useEffect(() => { + document.addEventListener("keydown", downHandler); + document.addEventListener("keyup", upHandler); + + return () => { + document.removeEventListener("keydown", downHandler); + document.removeEventListener("keyup", upHandler); + }; + }); + + return keyPressed; +}; + +export default useKeyPress; \ No newline at end of file diff --git a/src/pages/Room.jsx b/src/pages/Room.jsx new file mode 100644 index 00000000..e3289f3d --- /dev/null +++ b/src/pages/Room.jsx @@ -0,0 +1,282 @@ +import React, { useEffect, useState } from "react"; +import CodeEditorWindow from "../components/collab_elements/codeEditorWindow"; +import axios from "axios"; +import { classnames } from "../components/collab_elements/general"; +import { languageOptions } from "../components/collab_elements/languageOptions"; +import { ToastContainer, toast } from "react-toastify"; +import "react-toastify/dist/ReactToastify.css"; +import useKeyPress from "../components/hooks/useKeyPress"; +import LanguagesDropdown from "../components/collab_elements/languagesDropdown"; + +const javascriptDefault = `/** +* Problem: Binary Search: Search a sorted array for a target value. +*/ + +// Time: O(log n) +const binarySearch = (arr, target) => { + return binarySearchHelper(arr, target, 0, arr.length - 1); +}; + +const binarySearchHelper = (arr, target, start, end) => { + if (start > end) { + return false; + } + let mid = Math.floor((start + end) / 2); + if (arr[mid] === target) { + return mid; + } + if (arr[mid] < target) { + return binarySearchHelper(arr, target, mid + 1, end); + } + if (arr[mid] > target) { + return binarySearchHelper(arr, target, start, mid - 1); + } +}; + +const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; +const target = 5; +console.log(binarySearch(arr, target)); +`; + +const Room = () => { + const [code, setCode] = useState(javascriptDefault); + const [customInput, setCustomInput] = useState(""); + const [outputDetails, setOutputDetails] = useState(null); + const [processing, setProcessing] = useState(null); + const [theme, setTheme] = useState("cobalt"); + const [language, setLanguage] = useState(languageOptions[0]); + + const enterPress = useKeyPress("Enter"); + const ctrlPress = useKeyPress("Control"); + + const onSelectChange = (sl) => { + console.log("selected Option...", sl); + setLanguage(sl); + }; + + useEffect(() => { + if (enterPress && ctrlPress) { + console.log("enterPress", enterPress); + console.log("ctrlPress", ctrlPress); + handleCompile(); + } + }, [ctrlPress, enterPress]); + const onChange = (action, data) => { + switch (action) { + case "code": { + setCode(data); + break; + } + default: { + console.warn("case not handled!", action, data); + } + } + }; + const handleCompile = () => { + setProcessing(true); + const formData = { + language_id: language.id, + // encode source code in base64 + source_code: btoa(code), + stdin: btoa(customInput), + }; + const options = { + method: "POST", + url: process.env.REACT_APP_RAPID_API_URL, + params: { base64_encoded: "true", fields: "*" }, + headers: { + "content-type": "application/json", + "Content-Type": "application/json", + "X-RapidAPI-Host": process.env.REACT_APP_RAPID_API_HOST, + "X-RapidAPI-Key": process.env.REACT_APP_RAPID_API_KEY, + }, + data: formData, + }; + + axios + .request(options) + .then(function (response) { + console.log("res.data", response.data); + const token = response.data.token; + checkStatus(token); + }) + .catch((err) => { + let error = err.response ? err.response.data : err; + // get error status + let status = err.response.status; + console.log("status", status); + if (status === 429) { + console.log("too many requests", status); + + showErrorToast( + `Quota of 100 requests exceeded for the Day! Please read the blog on freeCodeCamp to learn how to setup your own RAPID API Judge0!`, + 10000 + ); + } + setProcessing(false); + console.log("catch block...", error); + }); + }; + + const checkStatus = async (token) => { + const options = { + method: "GET", + url: process.env.REACT_APP_RAPID_API_URL + "/" + token, + params: { base64_encoded: "true", fields: "*" }, + headers: { + "X-RapidAPI-Host": process.env.REACT_APP_RAPID_API_HOST, + "X-RapidAPI-Key": process.env.REACT_APP_RAPID_API_KEY, + }, + }; + try { + let response = await axios.request(options); + let statusId = response.data.status?.id; + + // Processed - we have a result + if (statusId === 1 || statusId === 2) { + // still processing + setTimeout(() => { + checkStatus(token); + }, 2000); + return; + } else { + setProcessing(false); + setOutputDetails(response.data); + showSuccessToast(`Compiled Successfully!`); + console.log("response.data", response.data); + return; + } + } catch (err) { + console.log("err", err); + setProcessing(false); + showErrorToast(); + } + }; + + function handleThemeChange(th) { + const theme = th; + console.log("theme...", theme); + + if (["light", "vs-dark"].includes(theme.value)) { + setTheme(theme); + } else { + defineTheme(theme.value).then((_) => setTheme(theme)); + } + } + useEffect(() => { + defineTheme("oceanic-next").then((_) => + setTheme({ value: "oceanic-next", label: "Oceanic Next" }) + ); + }, []); + + const showSuccessToast = (msg) => { + toast.success(msg || `Compiled Successfully!`, { + position: "top-right", + autoClose: 1000, + hideProgressBar: false, + closeOnClick: true, + pauseOnHover: true, + draggable: true, + progress: undefined, + }); + }; + const showErrorToast = (msg, timer) => { + toast.error(msg || `Something went wrong! Please try again.`, { + position: "top-right", + autoClose: timer ? timer : 1000, + hideProgressBar: false, + closeOnClick: true, + pauseOnHover: true, + draggable: true, + progress: undefined, + }); + }; + + return ( + <> + + + + + Fork me on GitHub + + + + + + +
+
+
+ +
+
+ +
+
+
+
+ +
+ +
+ +
+ + +
+ {outputDetails && } +
+
+ {/*