├── .gitignore ├── README.md ├── package-lock.json ├── package.json ├── public └── index.html └── src ├── App.js ├── assets ├── codedeck.png ├── logo-small.png └── logo.png ├── components ├── Modal.jsx └── ModalTypes │ ├── EditFolder.jsx │ ├── EditPlaygroundTitle.jsx │ ├── Loading.jsx │ ├── NewFolder.jsx │ ├── NewPlayground.jsx │ ├── NewPlaygroundAndFolder.jsx │ └── index.js ├── context ├── ModalContext.jsx └── PlaygroundContext.jsx ├── index.css ├── index.js ├── screens ├── Error404 │ └── index.jsx ├── Home │ ├── LeftComponent.jsx │ ├── RightComponent.jsx │ └── index.jsx └── Playground │ ├── CodeEditor.jsx │ ├── EditorContainer.jsx │ ├── InputConsole.jsx │ ├── Navbar.jsx │ ├── OutputConsole.jsx │ └── index.jsx └── style └── global.js /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Code Deck | An Online IDE 2 | 3 | ## Demo 4 | 5 | [Home Page](https://www.youtube.com/watch?v=mEFBdhQmpy4&t=3s&ab_channel=VishalRajput) 6 | 7 | ## Project Objective 8 | 9 | 1. Create a playground area where one can create multiple code snippets and run it using an online compiler and execution system(Judge0) 10 | 2. Create a Code Editor Frontend using ReactJS (CodeMirror package) 11 | 3. Implemented flexible layout structure using styled components 12 | 4. Use Rapid API to setup our Judge0 API 13 | 5. Add multi-language support (cpp, python, java, javascript) 14 | 6. Add multi-theme support 15 | 7. Upload and Download Code 16 | 8. Input and Output console(can upload text files for input & download output) 17 | 9. Functionality to save multiple playground in local storage 18 | 10. Add Fullscreen Support 19 | 20 | 21 | ## Technologies Used 22 | 23 | - React JS - for frontend 24 | - Styled Components - for styling 25 | - Judge0 CE API - to create and get submissions 26 | - Rapid API - to Setup Judge0 CE API 27 | - Axios - to make API calls 28 | - React Router - For routing 29 | 30 | # Link & References 31 | 32 | - [Live Project Link](https://code-deck.vercel.app/) 33 | - [Judge0 CE API Testing](https://rapidapi.com/judge0-official/api/judge0-ce) 34 | - [Judge0 CE API Documentation](https://ce.judge0.com/) 35 | - [Styled Component Documentation](https://styled-components.com/docs/basics) -> for styling 36 | - [CodeMirror](https://uiwjs.github.io/react-codemirror/) -> for Coding Editor 37 | - [Vercel](https://vercel.com/) -> for hoisting 38 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "code_deck_coding_ide", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@codemirror/lang-cpp": "^6.0.2", 7 | "@codemirror/lang-java": "^6.0.1", 8 | "@codemirror/lang-javascript": "^6.1.1", 9 | "@codemirror/lang-python": "^6.1.0", 10 | "@testing-library/jest-dom": "^5.16.5", 11 | "@testing-library/react": "^13.4.0", 12 | "@testing-library/user-event": "^13.5.0", 13 | "@uiw/codemirror-theme-bespin": "^4.15.1", 14 | "@uiw/codemirror-theme-dracula": "^4.15.1", 15 | "@uiw/codemirror-theme-duotone": "^4.15.1", 16 | "@uiw/codemirror-theme-github": "^4.15.1", 17 | "@uiw/codemirror-theme-okaidia": "^4.15.1", 18 | "@uiw/codemirror-theme-vscode": "^4.15.1", 19 | "@uiw/codemirror-theme-xcode": "^4.15.1", 20 | "@uiw/react-codemirror": "^4.15.1", 21 | "axios": "^1.2.0", 22 | "buffer": "^6.0.3", 23 | "react": "^18.2.0", 24 | "react-dom": "^18.2.0", 25 | "react-icons": "^4.6.0", 26 | "react-router-dom": "^6.4.3", 27 | "react-scripts": "5.0.1", 28 | "react-select": "^5.6.1", 29 | "styled-components": "^5.3.6", 30 | "uuid": "^9.0.0", 31 | "web-vitals": "^2.1.4" 32 | }, 33 | "scripts": { 34 | "start": "react-scripts start", 35 | "build": "react-scripts build", 36 | "test": "react-scripts test", 37 | "eject": "react-scripts eject" 38 | }, 39 | "eslintConfig": { 40 | "extends": [ 41 | "react-app", 42 | "react-app/jest" 43 | ] 44 | }, 45 | "browserslist": { 46 | "production": [ 47 | ">0.2%", 48 | "not dead", 49 | "not op_mini all" 50 | ], 51 | "development": [ 52 | "last 1 chrome version", 53 | "last 1 firefox version", 54 | "last 1 safari version" 55 | ] 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | Code Deck | An online Coding IDE 16 | 17 | 18 | 19 | 20 |
21 | 22 | 23 | -------------------------------------------------------------------------------- /src/App.js: -------------------------------------------------------------------------------- 1 | import { BrowserRouter, Route, Routes } from 'react-router-dom'; 2 | import Home from './screens/Home'; 3 | import Playground from './screens/Playground'; 4 | import Error404 from './screens/Error404'; 5 | import { GlobalStyle } from './style/global'; 6 | import ModalProvider from './context/ModalContext'; 7 | import PlaygroundProvider from './context/PlaygroundContext'; 8 | 9 | function App() { 10 | return ( 11 | 12 | 13 | 14 | 15 | 16 | } /> 17 | } /> 18 | } /> 19 | 20 | 21 | 22 | 23 | ); 24 | } 25 | 26 | export default App; 27 | -------------------------------------------------------------------------------- /src/assets/codedeck.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAMUDRALAARAVIND/code_deck/6b090714e93163433d7d4cacafdd96dd709e0c74/src/assets/codedeck.png -------------------------------------------------------------------------------- /src/assets/logo-small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAMUDRALAARAVIND/code_deck/6b090714e93163433d7d4cacafdd96dd709e0c74/src/assets/logo-small.png -------------------------------------------------------------------------------- /src/assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAMUDRALAARAVIND/code_deck/6b090714e93163433d7d4cacafdd96dd709e0c74/src/assets/logo.png -------------------------------------------------------------------------------- /src/components/Modal.jsx: -------------------------------------------------------------------------------- 1 | import React, {useContext} from 'react' 2 | import styled from 'styled-components' 3 | import { NewFolder, NewPlayground, NewPlaygroundAndFolder, EditFolder, EditPlaygroundTitle, Loading } from './ModalTypes' 4 | import { ModalContext } from '../context/ModalContext' 5 | 6 | const ModalContainer = styled.div` 7 | position: fixed; 8 | top: 0; 9 | left: 0; 10 | 11 | width: 100%; 12 | height: 100vh; 13 | background-color: rgba(0, 0, 0, 0.4); 14 | z-index: 2; 15 | display: flex; 16 | justify-content: center; 17 | align-items: center; 18 | ` 19 | 20 | const ModalContent = styled.div` 21 | background-color: #fff; 22 | padding: 1.5rem; 23 | width: 35%; 24 | min-width: 300px; 25 | border-radius: 10px; 26 | ` 27 | 28 | export const Header = styled.div` 29 | display: flex; 30 | align-items: center; 31 | justify-content: space-between; 32 | ` 33 | export const CloseButton = styled.button` 34 | background: transparent; 35 | outline: 0; 36 | border: 0; 37 | font-size: 2rem; 38 | cursor: pointer; 39 | `; 40 | 41 | export const Input = styled.div` 42 | display: flex; 43 | align-items: center; 44 | justify-content: space-between; 45 | flex-wrap: wrap; 46 | padding: 1.5rem 0; 47 | gap: 2rem; 48 | padding-bottom: 0; 49 | 50 | input { 51 | flex-grow: 1; 52 | height: 2rem; 53 | } 54 | 55 | button { 56 | background: #241f21; 57 | height: 2.5rem; 58 | color: white; 59 | padding: 0.3rem 2rem; 60 | } 61 | `; 62 | 63 | const Modal = () => { 64 | const { isOpenModal } = useContext(ModalContext) 65 | const { modalType } = isOpenModal; 66 | // ModalTypes 67 | // 1: New Folder 68 | // 2: New Playground 69 | // 3: New Playground and Folder 70 | // 4: Rename Folder 71 | // 5: Rename Playground 72 | return ( 73 | 74 | 75 | {modalType === 1 && } 76 | {modalType === 2 && } 77 | {modalType === 3 && } 78 | {modalType === 4 && } 79 | {modalType === 5 && } 80 | {modalType === 6 && } 81 | 82 | 83 | ) 84 | } 85 | 86 | export default Modal -------------------------------------------------------------------------------- /src/components/ModalTypes/EditFolder.jsx: -------------------------------------------------------------------------------- 1 | import React, { useContext, useState } from 'react' 2 | import { Header, CloseButton, Input } from '../Modal' 3 | import { IoCloseSharp } from 'react-icons/io5' 4 | import { ModalContext } from '../../context/ModalContext' 5 | import { PlaygroundContext } from '../../context/PlaygroundContext' 6 | 7 | const EditFolder = () => { 8 | const { closeModal, isOpenModal } = useContext(ModalContext); 9 | const { editFolderTitle, folders } = useContext(PlaygroundContext); 10 | 11 | const folderId = isOpenModal.identifiers.folderId; 12 | const [folderTitle, setFolderTitle] = useState(folders[folderId].title); 13 | 14 | return ( 15 | <> 16 |
17 |

Edit Folder Title

18 | closeModal()}> 19 | 20 | 21 |
22 | 23 | setFolderTitle(e.target.value)} /> 24 | 28 | 29 | 30 | ) 31 | } 32 | 33 | export default EditFolder; -------------------------------------------------------------------------------- /src/components/ModalTypes/EditPlaygroundTitle.jsx: -------------------------------------------------------------------------------- 1 | import React, { useContext, useState } from 'react' 2 | import { Header, CloseButton, Input } from '../Modal' 3 | import { IoCloseSharp } from 'react-icons/io5' 4 | import { ModalContext } from '../../context/ModalContext' 5 | import { PlaygroundContext } from '../../context/PlaygroundContext' 6 | 7 | const EditPlaygroundTitle = () => { 8 | const { isOpenModal, closeModal } = useContext(ModalContext); 9 | const { editPlaygroundTitle, folders } = useContext(PlaygroundContext); 10 | 11 | const { folderId, cardId } = isOpenModal.identifiers; 12 | const [playgroundTitle, setPlaygroundTitle] = useState(folders[folderId].playgrounds[cardId].title); 13 | 14 | return ( 15 | <> 16 |
17 |

Edit Card Title

18 | closeModal()}> 19 | 20 | 21 |
22 | 23 | setPlaygroundTitle(e.target.value)} /> 24 | 28 | 29 | 30 | ) 31 | } 32 | 33 | export default EditPlaygroundTitle -------------------------------------------------------------------------------- /src/components/ModalTypes/Loading.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | const Loading = () => { 4 | return ( 5 |
Loading...
6 | ) 7 | } 8 | 9 | export default Loading; -------------------------------------------------------------------------------- /src/components/ModalTypes/NewFolder.jsx: -------------------------------------------------------------------------------- 1 | import React, { useContext, useState } from 'react' 2 | import { Header, CloseButton, Input } from '../Modal' 3 | import { IoCloseSharp } from 'react-icons/io5' 4 | import { ModalContext } from '../../context/ModalContext' 5 | import { PlaygroundContext } from '../../context/PlaygroundContext' 6 | const NewFolder = () => { 7 | const { closeModal } = useContext(ModalContext); 8 | const { addFolder } = useContext(PlaygroundContext) 9 | const [folderTitle, setFolderTitle] = useState(""); 10 | 11 | return ( 12 | <> 13 |
14 |

Create New Folder

15 | closeModal()}> 16 | 17 | 18 |
19 | 20 | setFolderTitle(e.target.value)} /> 21 | 25 | 26 | 27 | ) 28 | } 29 | 30 | export default NewFolder -------------------------------------------------------------------------------- /src/components/ModalTypes/NewPlayground.jsx: -------------------------------------------------------------------------------- 1 | import React, { useContext, useState } from 'react' 2 | import { Header, CloseButton } from '../Modal' 3 | import { IoCloseSharp } from 'react-icons/io5' 4 | import { ModalContext } from '../../context/ModalContext' 5 | import { PlaygroundContext } from '../../context/PlaygroundContext' 6 | import Select from 'react-select'; 7 | import styled from 'styled-components'; 8 | const InputWithSelect = styled.div` 9 | display: grid; 10 | grid-template-columns: 1fr 0.5fr; 11 | gap: 1rem; 12 | margin-top: 1.2rem; 13 | align-items: center; 14 | 15 | input { 16 | flex-grow: 1; 17 | height: 2rem; 18 | } 19 | 20 | button { 21 | background: #241f21; 22 | height: 2.5rem; 23 | color: white; 24 | padding: 0.3rem 2rem; 25 | } 26 | 27 | & > div { 28 | width: 8rem; 29 | } 30 | 31 | @media (max-width: 768px) { 32 | grid-template-columns: 1fr; 33 | } 34 | `; 35 | 36 | const NewPlayground = () => { 37 | const { isOpenModal, closeModal } = useContext(ModalContext); 38 | const { addPlayground } = useContext(PlaygroundContext); 39 | 40 | const languageOptions = [ 41 | { value: "cpp", label: "cpp" }, 42 | { value: "java", label: "java" }, 43 | { value: "javascript", label: "javascript" }, 44 | { value: "python", label: "python" }, 45 | ]; 46 | 47 | const {folderId} = isOpenModal.identifiers; 48 | const [cardTitle, setCardTitle] = useState(""); 49 | const [language, setLanguage] = useState(languageOptions[0]); 50 | 51 | const handleLanguageChange = (selectedOption) => { 52 | setLanguage(selectedOption); 53 | }; 54 | 55 | return ( 56 | <> 57 |
58 |

Create New Playground

59 | closeModal()}> 60 | 61 | 62 |
63 | 64 | setCardTitle(e.target.value)} 67 | /> 68 | setFolderName(e.target.value)} /> 68 | 69 | 70 | setPlaygroundName(e.target.value)} /> 71 | 72 | 199 | getFile(e, setCurrentCode)} /> Import Code 222 | 223 | 224 | 225 | Export Code 226 | 227 | Run Code 228 | 229 | 230 | ) 231 | } 232 | 233 | export default EditorContainer -------------------------------------------------------------------------------- /src/screens/Playground/InputConsole.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import styled from 'styled-components' 3 | import { BiImport } from 'react-icons/bi' 4 | export const Console = styled.div` 5 | background: #fff; 6 | display: flex; 7 | flex-direction: column; 8 | ` 9 | 10 | export const Header = styled.div` 11 | background: #ededed; 12 | height: 4rem; 13 | box-shadow: 0 4px 4px rgba(0, 0, 0, 0.16); 14 | padding: 0 1rem; 15 | z-index: 2; 16 | font-size: 1.25rem; 17 | font-weight: 700; 18 | display: flex; 19 | align-items: center; 20 | justify-content: space-between; 21 | input{ 22 | display: none; 23 | } 24 | label, a{ 25 | font-weight: 400; 26 | display: flex; 27 | align-items: center; 28 | gap: 0.7rem; 29 | color: black; 30 | } 31 | ` 32 | 33 | export const TextArea = styled.textarea` 34 | flex-grow: 1; 35 | resize: none; 36 | border: 0; 37 | outline: 0; 38 | padding: 0.25rem; 39 | padding-top: 0.5rem; 40 | font-size: 1.1rem; 41 | min-height: 250px; 42 | ` 43 | const InputConsole = ({ currentInput, setCurrentInput, getFile }) => { 44 | return ( 45 | 46 |
47 | Input: 48 | 51 |
52 |