├── .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 | [
](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 |
73 |
77 |
78 | >
79 | )
80 | }
81 |
82 | export default NewPlayground
--------------------------------------------------------------------------------
/src/components/ModalTypes/NewPlaygroundAndFolder.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 |
7 | import Select from 'react-select';
8 | import styled from 'styled-components';
9 |
10 | const InputWithSelect = styled.div`
11 | display: grid;
12 | grid-template-columns: 1fr 0.5fr;
13 | gap: 1rem;
14 | margin-top: 1.2rem;
15 | align-items: center;
16 |
17 | input {
18 | flex-grow: 1;
19 | height: 2rem;
20 | }
21 |
22 | button {
23 | background: #241f21;
24 | height: 2.5rem;
25 | color: white;
26 | padding: 0.3rem 2rem;
27 | }
28 |
29 | & > div {
30 | width: 8rem;
31 | }
32 |
33 | @media (max-width: 768px) {
34 | grid-template-columns: 1fr;
35 | }
36 | `;
37 |
38 | const NewPlaygroundAndFolder = () => {
39 | const { closeModal } = useContext(ModalContext);
40 | const { addPlaygroundAndFolder } = useContext(PlaygroundContext);
41 |
42 | const languageOptions = [
43 | { value: "cpp", label: "cpp" },
44 | { value: "java", label: "java" },
45 | { value: "javascript", label: "javascript" },
46 | { value: "python", label: "python" },
47 | ];
48 |
49 | const [playgroundName, setPlaygroundName] = useState("")
50 | const [folderName, setFolderName] = useState("")
51 | const [language, setLanguage] = useState(languageOptions[0]);
52 |
53 | const handleLanguageChange = (selectedOption) => {
54 | setLanguage(selectedOption);
55 | };
56 |
57 | return (
58 | <>
59 |
60 | Create New Playground & Create New Folder
61 | closeModal()}>
62 |
63 |
64 |
65 |
66 |
67 | setFolderName(e.target.value)} />
68 |
69 |
70 | setPlaygroundName(e.target.value)} />
71 |
72 |
77 |
78 |
82 |
83 | >
84 | )
85 | }
86 |
87 | export default NewPlaygroundAndFolder
--------------------------------------------------------------------------------
/src/components/ModalTypes/index.js:
--------------------------------------------------------------------------------
1 | import NewFolder from './NewFolder';
2 | import NewPlayground from './NewPlayground'
3 | import NewPlaygroundAndFolder from './NewPlaygroundAndFolder'
4 | import EditFolder from './EditFolder'
5 | import EditPlaygroundTitle from './EditPlaygroundTitle'
6 | import Loading from './Loading'
7 | export { NewFolder, NewPlayground, NewPlaygroundAndFolder, EditFolder, EditPlaygroundTitle, Loading };
--------------------------------------------------------------------------------
/src/context/ModalContext.jsx:
--------------------------------------------------------------------------------
1 | import { createContext, useState } from "react";
2 |
3 | export const ModalContext = createContext();
4 |
5 | // ModalFields: {foldername, filename, language, type, isopenmodel}
6 | function ModalProvider({children}){
7 | const initialModalFields = {
8 | show : false,
9 | modalType : "",
10 | identifiers : {
11 | folderId : "",
12 | cardId : "",
13 | }
14 | }
15 |
16 | const [isOpenModal, setIsOpenModal] = useState({ ...initialModalFields});
17 |
18 | const openModal = (value) => {
19 | setIsOpenModal(value)
20 | }
21 |
22 | const closeModal = () => {
23 | setIsOpenModal({ ...initialModalFields})
24 | }
25 |
26 | const ModalFeatures = {
27 | isOpenModal: isOpenModal,
28 | openModal: openModal,
29 | closeModal: closeModal,
30 | }
31 | return (
32 |
33 | {children}
34 |
35 | )
36 | }
37 |
38 | export default ModalProvider;
--------------------------------------------------------------------------------
/src/context/PlaygroundContext.jsx:
--------------------------------------------------------------------------------
1 | import { createContext, useState, useEffect } from "react";
2 | import { v4 as uuid } from 'uuid';
3 |
4 | export const PlaygroundContext = createContext();
5 |
6 | export const languageMap = {
7 | "cpp": {
8 | id: 54,
9 | defaultCode:
10 | "#include \n"
11 | + "using namespace std;\n\n"
12 | + "int main() {\n"
13 | + '\tcout << "Hello World!";\n'
14 | + "\treturn 0;\n"
15 | + "}",
16 | },
17 | "java": {
18 | id: 62,
19 | defaultCode: `public class Main {
20 | public static void main(String[] args) {
21 | System.out.println("Hello World!");
22 | }
23 | }`,
24 | },
25 | "python": {
26 | id: 71,
27 | defaultCode: `print("Hello World!")`,
28 | },
29 | "javascript": {
30 | id: 63,
31 | defaultCode: `console.log("Hello World!");`,
32 | }
33 | }
34 |
35 | const PlaygroundProvider = ({ children }) => {
36 |
37 | const initialItems = {
38 | [uuid()]: {
39 | title: "DSA",
40 | playgrounds: {
41 | [uuid()]: {
42 | title: "Stack Implementation",
43 | language: "cpp",
44 | code: languageMap["cpp"].defaultCode,
45 | },
46 | [uuid()]: {
47 | name: "Array",
48 | language: "javascript",
49 | code: languageMap["javascript"].defaultCode,
50 | },
51 | }
52 | },
53 | }
54 |
55 | const [folders, setFolders] = useState(() => {
56 | let localData = localStorage.getItem('playgrounds-data');
57 | if (localData === null || localData === undefined) {
58 | return initialItems;
59 | }
60 |
61 | return JSON.parse(localData);
62 | })
63 |
64 | useEffect(() => {
65 | localStorage.setItem('playgrounds-data', JSON.stringify(folders));
66 | }, [folders])
67 |
68 | const deleteCard = (folderId, cardId) => {
69 | setFolders((oldState) => {
70 | const newState = { ...oldState };
71 | delete newState[folderId].playgrounds[cardId];
72 | return newState;
73 | });
74 | }
75 |
76 | const deleteFolder = (folderId) => {
77 | setFolders((oldState) => {
78 | const newState = { ...oldState };
79 | delete newState[folderId];
80 | return newState;
81 | });
82 | }
83 |
84 | const addFolder = (folderName) => {
85 | setFolders((oldState) => {
86 | const newState = { ...oldState };
87 |
88 | newState[uuid()] = {
89 | title: folderName,
90 | playgrounds: {}
91 | }
92 |
93 | return newState;
94 | })
95 | }
96 |
97 | const addPlayground = (folderId, playgroundName, language) => {
98 | setFolders((oldState) => {
99 | const newState = { ...oldState };
100 |
101 | newState[folderId].playgrounds[uuid()] = {
102 | title: playgroundName,
103 | language: language,
104 | code: languageMap[language].defaultCode,
105 | }
106 |
107 | return newState;
108 | })
109 | }
110 |
111 | const addPlaygroundAndFolder = (folderName, playgroundName, cardLanguage) => {
112 | setFolders((oldState) => {
113 | const newState = { ...oldState }
114 |
115 | newState[uuid()] = {
116 | title: folderName,
117 | playgrounds: {
118 | [uuid()]: {
119 | title: playgroundName,
120 | language: cardLanguage,
121 | code: languageMap[cardLanguage].defaultCode,
122 | }
123 | }
124 | }
125 |
126 | return newState;
127 | })
128 | }
129 |
130 | const editFolderTitle = (folderId, folderName) => {
131 | setFolders((oldState) => {
132 | const newState = { ...oldState }
133 | newState[folderId].title = folderName;
134 | return newState;
135 | })
136 | }
137 |
138 | const editPlaygroundTitle = (folderId, cardId, PlaygroundTitle) => {
139 | setFolders((oldState) => {
140 | const newState = { ...oldState }
141 | newState[folderId].playgrounds[cardId].title = PlaygroundTitle;
142 | return newState;
143 | })
144 | }
145 |
146 | const savePlayground = (folderId, cardId, newCode, newLanguage) => {
147 | setFolders((oldState) => {
148 | const newState = { ...oldState };
149 | newState[folderId].playgrounds[cardId].code = newCode;
150 | newState[folderId].playgrounds[cardId].language = newLanguage;
151 | return newState;
152 | })
153 | }
154 |
155 | const PlayGroundFeatures = {
156 | folders: folders,
157 | deleteCard: deleteCard,
158 | deleteFolder: deleteFolder,
159 | addFolder: addFolder,
160 | addPlayground: addPlayground,
161 | addPlaygroundAndFolder: addPlaygroundAndFolder,
162 | editFolderTitle: editFolderTitle,
163 | editPlaygroundTitle: editPlaygroundTitle,
164 | savePlayground: savePlayground,
165 | }
166 |
167 | return (
168 |
169 | {children}
170 |
171 | )
172 | }
173 |
174 | export default PlaygroundProvider;
--------------------------------------------------------------------------------
/src/index.css:
--------------------------------------------------------------------------------
1 | body {
2 | margin: 0;
3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
4 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
5 | sans-serif;
6 | -webkit-font-smoothing: antialiased;
7 | -moz-osx-font-smoothing: grayscale;
8 | }
9 |
10 | code {
11 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
12 | monospace;
13 | }
14 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom/client';
3 | import './index.css';
4 | import App from './App';
5 |
6 | const root = ReactDOM.createRoot(document.getElementById('root'));
7 | root.render(
8 |
9 |
10 |
11 | );
--------------------------------------------------------------------------------
/src/screens/Error404/index.jsx:
--------------------------------------------------------------------------------
1 | import React, { useEffect } from 'react'
2 | import { useNavigate } from 'react-router-dom'
3 |
4 | const Error404 = () => {
5 | const navigate = useNavigate();
6 | useEffect(() => {
7 | setTimeout(() => {
8 | navigate('/');
9 | }, 3000)
10 | }, [])
11 | return (
12 | No Page Found, Redirecting to home page
13 | )
14 | }
15 |
16 | export default Error404
--------------------------------------------------------------------------------
/src/screens/Home/LeftComponent.jsx:
--------------------------------------------------------------------------------
1 | import React, { useContext } from 'react'
2 | import styled from 'styled-components'
3 | import logo from '../../assets/logo.png'
4 | import { ModalContext } from '../../context/ModalContext'
5 |
6 | const StyledLeftComponent = styled.div`
7 | position: fixed;
8 | top: 0;
9 | left: 0;
10 | width: 40%;
11 | height: 100vh;
12 | background-color: #1e1e1e;
13 |
14 | display: flex;
15 | justify-content: center;
16 | align-items: center;
17 |
18 | @media (max-width: 768px){
19 | position: relative;
20 | width: 100%;
21 | }
22 | `
23 | const ContentContainer = styled.div`
24 | text-align: center;
25 | `
26 |
27 | const Logo = styled.img`
28 | width: 165px;
29 | margin-bottom: 1rem;
30 | `
31 |
32 | const MainHeading = styled.h1`
33 | font-size: 2.5rem;
34 | font-weight: 400;
35 | color: #fff;
36 | margin-bottom: 0.75rem;
37 |
38 | span{
39 | font-weight: 700;
40 | }
41 | `
42 | const SubHeading = styled.div`
43 | font-size: 1.5rem;
44 | color: #fff;
45 | opacity: 0.7;
46 | margin-bottom: 1.5rem;
47 | `
48 |
49 | const AddNewButton = styled.button`
50 | padding: 0.25rem 1.5rem;
51 | font-size: 1rem;
52 | border: none;
53 | border-radius: 30px;
54 | box-shadow: 0px 0px 4px 2px #8b8b8b;
55 | display: flex;
56 | align-items: center;
57 | gap: 0.25rem;
58 | transition: all 0.2s ease-in-out;
59 | span{
60 | font-size: 2rem;
61 | font-weight: 700;
62 | }
63 |
64 | &:hover{
65 | cursor: pointer;
66 | scale: 1.05;
67 | box-shadow: 0px 0px 6px 2px #8b8b8b;
68 | }
69 | `
70 | const LeftComponent = () => {
71 | const { openModal } = useContext(ModalContext);
72 | return (
73 |
74 |
75 |
76 | Code Deck
77 | Code. Compile. Debug.
78 | openModal({
79 | show: true,
80 | modalType: 3,
81 | identifiers: {
82 | folderId: "",
83 | cardId: "",
84 | }
85 | })} >+ Create New Playground
86 |
87 |
88 | )
89 | }
90 |
91 | export default LeftComponent
--------------------------------------------------------------------------------
/src/screens/Home/RightComponent.jsx:
--------------------------------------------------------------------------------
1 | import React, { useContext } from 'react'
2 | import styled from 'styled-components'
3 | import { IoTrashOutline } from 'react-icons/io5'
4 | import { BiEditAlt } from 'react-icons/bi'
5 | import { FcOpenedFolder } from 'react-icons/fc'
6 | import logo from '../../assets/logo-small.png'
7 | import { ModalContext } from '../../context/ModalContext'
8 | import { PlaygroundContext } from '../../context/PlaygroundContext'
9 | import { useNavigate } from 'react-router-dom'
10 |
11 | const StyledRightComponent = styled.div`
12 | position: absolute;
13 | top: 0;
14 | right: 0;
15 | width: 60%;
16 | padding: 2rem;
17 |
18 | @media (max-width: 768px){
19 | position: relative;
20 | width: 100%;
21 | padding: 1rem 0.5rem;
22 | }
23 | `
24 |
25 | const Header = styled.div`
26 | display: flex;
27 | align-items: center;
28 | flex-wrap: wrap;
29 | justify-content: space-between;
30 | padding: 0.75rem 0;
31 | border-bottom: 1px solid #989898;
32 | margin-bottom: 1rem;
33 | `
34 |
35 | const Heading = styled.h3`
36 | font-size: ${props => props.size === 'small' ? "1.25rem" : "1.75rem"};
37 | font-weight: 400;
38 | display: flex;
39 | align-items: center;
40 | gap: 0.5rem;
41 | span{
42 | font-weight: 700;
43 | }
44 | `
45 |
46 | const AddButton = styled.div`
47 | font-size: 1rem;
48 | border-radius: 30px;
49 | color: black;
50 | display: flex;
51 | align-items: center;
52 | gap: 0.25rem;
53 | span{
54 | font-size: 1.5rem;
55 | font-weight: 700;
56 | }
57 |
58 | &:hover{
59 | cursor: pointer;
60 | }
61 | `
62 |
63 | const FolderCard = styled.div`
64 | margin-bottom: 1rem;
65 | `
66 |
67 | const FolderIcons = styled.div`
68 | display: flex;
69 | align-items: center;
70 | gap: 0.7rem;
71 | cursor: pointer;
72 | `
73 |
74 | const PlayGroundCards = styled.div`
75 | display: grid;
76 | grid-template-columns: 1fr 1fr;
77 | gap: 2rem;
78 |
79 | @media (max-width: 428px){
80 | grid-template-columns: 1fr;
81 | }
82 | `
83 |
84 | const Card = styled.div`
85 | padding: 0.5rem;
86 | display: flex;
87 | align-items: center;
88 | justify-content: space-between;
89 | border-radius: 8px;
90 | box-shadow: 0 0 4px 0px #989898;
91 | cursor: pointer;
92 | transition: all 0.2s ease-in-out;
93 |
94 | &:hover{
95 | scale: 1.05;
96 | box-shadow: 0 0 8px 0px #989898;
97 | }
98 | `
99 |
100 | const CardContainer = styled.div`
101 | display: flex;
102 | align-items: center;
103 | `
104 |
105 | const CardContent = styled.div`
106 | `
107 |
108 | const Logo = styled.img`
109 | width: 70px;
110 | margin-right: 1rem;
111 |
112 | @media (max-width: 425px){
113 | width: 50px;
114 | margin-right: 0.5rem;
115 | }
116 | `
117 | const RightComponent = () => {
118 | const navigate = useNavigate();
119 |
120 | const { openModal } = useContext(ModalContext);
121 | const { folders, deleteFolder, deleteCard } = useContext(PlaygroundContext);
122 |
123 | return (
124 |
125 |
126 |
127 | My Playground
128 |
129 | openModal({
130 | show: true,
131 | modalType: 1,
132 | identifiers: {
133 | folderId: "",
134 | cardId: "",
135 | }
136 | })}> + New Folder
137 |
138 |
139 | {
140 | Object.entries(folders).map(([folderId, folder]) => (
141 |
142 |
143 |
144 | {folder.title}
145 |
146 |
147 | deleteFolder(folderId)} />
148 | openModal({
149 | show: true,
150 | modalType: 4,
151 | identifiers: {
152 | folderId: folderId,
153 | cardId: "",
154 | }
155 | })} />
156 | openModal({
157 | show: true,
158 | modalType: 2,
159 | identifiers: {
160 | folderId: folderId,
161 | cardId: "",
162 | }
163 | })}>+ New Playground
164 |
165 |
166 |
167 |
168 | {
169 | Object.entries(folder['playgrounds']).map(([playgroundId, playground]) => (
170 | {
171 | navigate(`/playground/${folderId}/${playgroundId}`)
172 | }}>
173 |
174 |
175 |
176 | {playground.title}
177 | Language: {playground.language}
178 |
179 |
180 | {
181 | e.stopPropagation(); //stop click propagation from child to parent
182 | }}>
183 | deleteCard(folderId, playgroundId)} />
184 | openModal({
185 | show: true,
186 | modalType: 5,
187 | identifiers: {
188 | folderId: folderId,
189 | cardId: playgroundId,
190 | }
191 | })} />
192 |
193 |
194 | ))
195 | }
196 |
197 |
198 | ))
199 | }
200 |
201 | )
202 | }
203 |
204 | export default RightComponent;
--------------------------------------------------------------------------------
/src/screens/Home/index.jsx:
--------------------------------------------------------------------------------
1 | import React, {useContext} from 'react'
2 | import styled from 'styled-components'
3 | import LeftComponent from './LeftComponent'
4 | import RightComponent from './RightComponent'
5 | import Modal from '../../components/Modal'
6 | import { ModalContext } from '../../context/ModalContext'
7 |
8 | const StyledHome = styled.div`
9 | width: 100%;
10 | min-height: 100vh;
11 | `
12 |
13 | const Home = () => {
14 | const {isOpenModal} = useContext(ModalContext);
15 |
16 | return (
17 |
18 |
19 |
20 | { isOpenModal.show && }
21 |
22 | )
23 | }
24 |
25 | export default Home
--------------------------------------------------------------------------------
/src/screens/Playground/CodeEditor.jsx:
--------------------------------------------------------------------------------
1 | import React, { useState, useEffect } from 'react'
2 | import styled from 'styled-components'
3 | // npm i @uiw/react-codemirror
4 | import CodeMirror from '@uiw/react-codemirror'
5 | // npm i @uiw/codemirror-theme-bespin @uiw/codemirror-theme-duotone @uiw/codemirror-theme-dracula @uiw/codemirror-theme-github @uiw/codemirror-theme-xcode @uiw/codemirror-theme-vscode @uiw/codemirror-theme-okaidia
6 |
7 | // theme
8 | import { githubDark, githubLight } from '@uiw/codemirror-theme-github'
9 | import { bespin } from '@uiw/codemirror-theme-bespin'
10 | import { duotoneDark, duotoneLight } from '@uiw/codemirror-theme-duotone'
11 | import { dracula } from '@uiw/codemirror-theme-dracula'
12 | import { xcodeDark, xcodeLight } from '@uiw/codemirror-theme-xcode'
13 | import { vscodeDark } from '@uiw/codemirror-theme-vscode'
14 | import { okaidia } from '@uiw/codemirror-theme-okaidia'
15 |
16 | // npm i @codemirror/lang-cpp @codemirror/lang-java @codemirror/lang-javascript @codemirror/lang-python
17 |
18 | // language
19 | import { cpp } from '@codemirror/lang-cpp'
20 | import { java } from '@codemirror/lang-java'
21 | import { javascript } from '@codemirror/lang-javascript'
22 | import { python } from '@codemirror/lang-python'
23 |
24 | //configuration
25 | import { indentUnit } from '@codemirror/language'
26 | import { EditorState } from '@codemirror/state'
27 |
28 | const CodeEditor = ({
29 | currentLanguage,
30 | currentTheme,
31 | currentCode,
32 | setCurrentCode
33 | }) => {
34 |
35 | const [theme, setTheme] = useState(githubDark)
36 | const [language, setLanguage] = useState(javascript);
37 |
38 | useEffect(() => {
39 | if (currentLanguage === 'cpp') setLanguage(cpp);
40 | if (currentLanguage === 'java') setLanguage(java);
41 | if (currentLanguage === 'javascript') setLanguage(javascript);
42 | if (currentLanguage === 'python') setLanguage(python);
43 | }, [currentLanguage])
44 |
45 |
46 | useEffect(() => {
47 | if (currentTheme === 'githubDark') setTheme(githubDark);
48 | if (currentTheme === 'githubLight') setTheme(githubLight);
49 | if (currentTheme === 'bespin') setTheme(bespin);
50 | if (currentTheme === 'duotoneDark') setTheme(duotoneDark);
51 | if (currentTheme === 'duotoneLight') setTheme(duotoneLight);
52 | if (currentTheme === 'dracula') setTheme(dracula);
53 | if (currentTheme === 'xcodeDark') setTheme(xcodeDark);
54 | if (currentTheme === 'xcodeLight') setTheme(xcodeLight);
55 | if (currentTheme === 'vscodeDark') setTheme(vscodeDark);
56 | if (currentTheme === 'okaidia') setTheme(okaidia);
57 | }, [currentTheme])
58 |
59 | return (
60 | true)
69 | ]}
70 | onChange={(value) => setCurrentCode(value)}
71 | basicSetup={{
72 | lineNumbers: true,
73 | highlightActiveLineGutter: true,
74 | highlightSpecialChars: true,
75 | history: true,
76 | foldGutter: true,
77 | drawSelection: true,
78 | dropCursor: true,
79 | allowMultipleSelections: true,
80 | indentOnInput: true,
81 | syntaxHighlighting: true,
82 | bracketMatching: true,
83 | closeBrackets: true,
84 | autocompletion: true,
85 | rectangularSelection: true,
86 | crosshairCursor: true,
87 | highlightActiveLine: true,
88 | highlightSelectionMatches: true,
89 | closeBracketsKeymap: true,
90 | defaultKeymap: true,
91 | searchKeymap: true,
92 | historyKeymap: true,
93 | foldKeymap: true,
94 | completionKeymap: true,
95 | lintKeymap: true,
96 | }}
97 | />
98 | )
99 | }
100 |
101 | export default CodeEditor
--------------------------------------------------------------------------------
/src/screens/Playground/EditorContainer.jsx:
--------------------------------------------------------------------------------
1 | import React, { useContext, useState } from 'react'
2 | import CodeEditor from './CodeEditor'
3 | import styled from 'styled-components'
4 | import { BiEditAlt, BiImport, BiExport, BiFullscreen } from 'react-icons/bi'
5 | import { ModalContext } from '../../context/ModalContext'
6 | import Select from 'react-select';
7 | import { languageMap } from '../../context/PlaygroundContext'
8 |
9 | const StyledEditorContainer = styled.div`
10 | display: flex;
11 | flex-direction: column;
12 | width: 100%;
13 | min-height: ${({ isFullScreen }) => isFullScreen ? '100vh' : 'calc(100vh - 4.5rem)'};
14 | `
15 |
16 | const UpperToolBar = styled.div`
17 | background: #fff;
18 | display: flex;
19 | justify-content: space-between;
20 | align-items: center;
21 | flex-wrap: wrap;
22 | gap: 0.4rem;
23 | padding: 0.8rem 0.4rem;
24 |
25 | @media (max-width: 540px){
26 | height: 8rem;
27 | }
28 | `
29 |
30 | const Header = styled.div`
31 | display: flex;
32 | justify-content: space-between;
33 | align-items: center;
34 | @media (max-width: 540px){
35 | width: 100%;
36 | }
37 | `
38 |
39 | const Title = styled.div`
40 | display: flex;
41 | align-items: center;
42 | gap: 1rem;
43 | margin-right: 2.3rem;
44 | font-size: 1.3rem;
45 | @media (min-width: 540px){
46 | margin-right: 1rem;
47 | }
48 | `
49 |
50 | const SelectBars = styled.div`
51 | display: flex;
52 | align-items: center;
53 | flex-wrap: wrap;
54 | gap: 1rem;
55 |
56 | & > div{
57 | width: 8rem;
58 | }
59 |
60 | & > div:last-child{
61 | width: 10rem;
62 | }
63 | `
64 |
65 | const Button = styled.button`
66 | padding: 0.7rem 0.4rem;
67 | width: 6.2rem;
68 | background: #0097d7;
69 | border: none;
70 | border-radius: 32px;
71 | font-weight: 700;
72 | cursor: pointer;
73 | `
74 |
75 | const CodeEditorContainer = styled.div`
76 | height: calc(100% - 4rem);
77 |
78 | & > div{
79 | height: 100%;
80 | }
81 | `
82 |
83 | const LowerToolBar = styled.div`
84 | display: flex;
85 | align-items: center;
86 | justify-content: space-between;
87 | flex-wrap: wrap;
88 | gap: 0.8rem;
89 | padding: 0.8rem 1rem;
90 |
91 | input{
92 | display: none;
93 | }
94 |
95 | label, a, button{
96 | font-size: 1.2rem;
97 | border: none;
98 | display: flex;
99 | align-items: center;
100 | gap: 0.7rem;
101 | color: black;
102 | }
103 | button:first-child{
104 | background: none;
105 | }
106 | button:last-child{
107 | font-weight: 400;
108 | font-size: 1.1rem;
109 | }
110 | `
111 | const SaveAndRunButton = styled.button`
112 | padding: 0.6rem 1rem;
113 | background: #0097d7;
114 | border: none;
115 | border-radius: 32px;
116 | font-weight: 700;
117 | cursor: pointer;
118 | `
119 | const EditorContainer = ({
120 | title,
121 | currentLanguage,
122 | setCurrentLanguage,
123 | currentCode,
124 | setCurrentCode,
125 | folderId,
126 | playgroundId,
127 | saveCode,
128 | runCode,
129 | getFile,
130 | isFullScreen,
131 | setIsFullScreen
132 | }) => {
133 |
134 | const { openModal } = useContext(ModalContext)
135 | const themeOptions = [
136 | { value: 'githubDark', label: 'githubDark' },
137 | { value: 'githubLight', label: 'githubLight' },
138 | { value: 'bespin', label: 'bespin' },
139 | { value: 'duotoneDark', label: 'duotoneDark' },
140 | { value: 'duotoneLight', label: 'duotoneLight' },
141 | { value: 'dracula', label: 'dracula' },
142 | { value: 'xcodeDark', label: 'xcodeDark' },
143 | { value: 'xcodeLight', label: 'xcodeLight' },
144 | { value: 'vscodeDark', label: 'vscodeDark' },
145 | { value: 'vscodeLight', label: 'vscodeLight' },
146 | { value: 'okaidia', label: 'okaidia' },
147 | ]
148 |
149 | const languageOptions = [
150 | { value: 'cpp', label: 'cpp' },
151 | { value: 'javascript', label: 'javascript' },
152 | { value: 'java', label: 'java' },
153 | { value: 'python', label: 'python' },
154 | ]
155 |
156 | const handleThemeChange = (selectedOption) => {
157 | setCurrentTheme(selectedOption)
158 | }
159 |
160 | const handleLanguageChange = (selectedOption) => {
161 | setLanguage(selectedOption)
162 | setCurrentLanguage(selectedOption.value)
163 | setCurrentCode(languageMap[selectedOption.value].defaultCode)
164 | }
165 |
166 | const [currentTheme, setCurrentTheme] = useState({ value: 'githubDark', label: 'githubDark' })
167 | const [language, setLanguage] = useState(() => {
168 | for (let i = 0; i < languageOptions.length; i++) {
169 | if (languageOptions[i].value === currentLanguage) {
170 | return languageOptions[i]
171 | }
172 | }
173 | return languageOptions[0];
174 | })
175 |
176 | return (
177 |
178 | {!isFullScreen &&
179 |
180 |
181 | {title}
182 | openModal({
183 | show: true,
184 | modalType: 5,
185 | identifiers: {
186 | folderId: folderId,
187 | cardId: playgroundId,
188 | }
189 | })} />
190 |
191 |
192 |
193 |
194 |
199 |
204 |
205 |
206 | }
207 |
208 |
214 |
215 |
216 |
219 |
220 |
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 |
52 |
57 | )
58 | }
59 |
60 | export default InputConsole
--------------------------------------------------------------------------------
/src/screens/Playground/Navbar.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import styled from 'styled-components'
3 | import logo from '../../assets/logo.png'
4 | import { useNavigate } from 'react-router-dom'
5 | const NavbarContainer = styled.div`
6 | height: ${({isFullScreen}) => isFullScreen ? '0' : '4.5rem'};
7 | background: #1e1e1e;
8 | display: flex;
9 | align-items: center;
10 | justify-content: center;
11 | `
12 |
13 | const NavbarContent = styled.button`
14 | background: transparent;
15 | border: 0;
16 |
17 | display: flex;
18 | align-items: center;
19 | gap: 1rem;
20 | cursor: pointer;
21 | `
22 |
23 | const Logo = styled.img`
24 | width: 60px;
25 | `
26 |
27 | const MainHeading = styled.h1`
28 | font-size: 2rem;
29 | font-weight: 400;
30 | color: #fff;
31 |
32 | span{
33 | font-weight: 700;
34 | }
35 | `
36 |
37 | const Navbar = ({ isFullScreen }) => {
38 | const navigate = useNavigate()
39 | return (
40 |
41 | {
42 | navigate('/')
43 | }}>
44 |
45 |
46 | Code Deck
47 |
48 |
49 |
50 | )
51 | }
52 |
53 | export default Navbar
--------------------------------------------------------------------------------
/src/screens/Playground/OutputConsole.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { Console, Header, TextArea } from './InputConsole'
3 | import { BiExport } from 'react-icons/bi'
4 |
5 | const OutputConsole = ({ currentOutput }) => {
6 | return (
7 |
8 |
16 |
20 |
21 | )
22 | }
23 |
24 | export default OutputConsole
--------------------------------------------------------------------------------
/src/screens/Playground/index.jsx:
--------------------------------------------------------------------------------
1 | import React, { useContext, useState } from 'react'
2 | import EditorContainer from './EditorContainer'
3 | import InputConsole from './InputConsole'
4 | import OutputConsole from './OutputConsole'
5 | import Navbar from './Navbar'
6 | import styled from 'styled-components'
7 | import { useParams } from 'react-router-dom'
8 | import { languageMap, PlaygroundContext } from '../../context/PlaygroundContext'
9 | import { ModalContext } from '../../context/ModalContext'
10 | import Modal from '../../components/Modal'
11 | import { Buffer } from 'buffer'
12 | import axios from 'axios'
13 | const MainContainer = styled.div`
14 | display: grid;
15 | grid-template-columns: ${({ isFullScreen }) => isFullScreen ? '1fr' : '2fr 1fr'};
16 | min-height: ${({ isFullScreen }) => isFullScreen ? '100vh' : 'calc(100vh - 4.5rem)'};
17 | @media (max-width: 768px){
18 | grid-template-columns: 1fr;
19 | }
20 | `
21 |
22 | const Consoles = styled.div`
23 | display: grid;
24 | width: 100%;
25 | grid-template-rows: 1fr 1fr;
26 | grid-template-columns: 1fr;
27 | `
28 |
29 | const Playground = () => {
30 | const { folderId, playgroundId } = useParams()
31 | const { folders, savePlayground } = useContext(PlaygroundContext)
32 | const { isOpenModal, openModal, closeModal } = useContext(ModalContext)
33 | const { title, language, code } = folders[folderId].playgrounds[playgroundId]
34 |
35 | const [currentLanguage, setCurrentLanguage] = useState(language)
36 | const [currentCode, setCurrentCode] = useState(code)
37 | const [currentInput, setCurrentInput] = useState('')
38 | const [currentOutput, setCurrentOutput] = useState('')
39 | const [isFullScreen, setIsFullScreen] = useState(false)
40 |
41 | // all logic of the playground
42 | const saveCode = () => {
43 | savePlayground(folderId, playgroundId, currentCode, currentLanguage)
44 | }
45 |
46 | const encode = (str) => {
47 | return Buffer.from(str, "binary").toString("base64")
48 | }
49 |
50 | const decode = (str) => {
51 | return Buffer.from(str, 'base64').toString()
52 | }
53 |
54 | const postSubmission = async (language_id, source_code, stdin) => {
55 | const options = {
56 | method: 'POST',
57 | url: 'https://judge0-ce.p.rapidapi.com/submissions',
58 | params: { base64_encoded: 'true', fields: '*' },
59 | headers: {
60 | 'content-type': 'application/json',
61 | 'Content-Type': 'application/json',
62 | 'X-RapidAPI-Key': 'b4e5c5a05fmsh9adf6ec091523f8p165338jsncc58f31c26e1',
63 | 'X-RapidAPI-Host': 'judge0-ce.p.rapidapi.com'
64 | },
65 | data: JSON.stringify({
66 | language_id: language_id,
67 | source_code: source_code,
68 | stdin: stdin
69 | })
70 | };
71 |
72 | const res = await axios.request(options);
73 | return res.data.token
74 | }
75 |
76 | const getOutput = async (token) => {
77 | // we will make api call here
78 | const options = {
79 | method: 'GET',
80 | url: "https://judge0-ce.p.rapidapi.com/submissions/" + token,
81 | params: { base64_encoded: 'true', fields: '*' },
82 | headers: {
83 | 'X-RapidAPI-Key': '3ed7a75b44mshc9e28568fe0317bp17b5b2jsn6d89943165d8',
84 | 'X-RapidAPI-Host': 'judge0-ce.p.rapidapi.com'
85 | }
86 | };
87 |
88 | // call the api
89 | const res = await axios.request(options);
90 | if (res.data.status_id <= 2) {
91 | const res2 = await getOutput(token);
92 | return res2.data;
93 | }
94 | return res.data;
95 | }
96 |
97 | const runCode = async () => {
98 | openModal({
99 | show: true,
100 | modalType: 6,
101 | identifiers: {
102 | folderId: "",
103 | cardId: "",
104 | }
105 | })
106 | const language_id = languageMap[currentLanguage].id;
107 | const source_code = encode(currentCode);
108 | const stdin = encode(currentInput);
109 |
110 | // pass these things to Create Submissions
111 | const token = await postSubmission(language_id, source_code, stdin);
112 |
113 | // get the output
114 | const res = await getOutput(token);
115 | const status_name = res.status.description;
116 | const decoded_output = decode(res.stdout ? res.stdout : '');
117 | const decoded_compile_output = decode(res.compile_output ? res.compile_output : '');
118 | const decoded_error = decode(res.stderr ? res.stderr : '');
119 |
120 | let final_output = '';
121 | if (res.status_id !== 3) {
122 | // our code have some error
123 | if (decoded_compile_output === "") {
124 | final_output = decoded_error;
125 | }
126 | else {
127 | final_output = decoded_compile_output;
128 | }
129 | }
130 | else {
131 | final_output = decoded_output;
132 | }
133 | setCurrentOutput(status_name + "\n\n" + final_output);
134 | closeModal();
135 | }
136 |
137 | const getFile = (e, setState) => {
138 | const input = e.target;
139 | if ("files" in input && input.files.length > 0) {
140 | placeFileContent(input.files[0], setState);
141 | }
142 | };
143 |
144 | const placeFileContent = (file, setState) => {
145 | readFileContent(file)
146 | .then((content) => {
147 | setState(content)
148 | })
149 | .catch((error) => console.log(error));
150 | };
151 |
152 | function readFileContent(file) {
153 | const reader = new FileReader();
154 | return new Promise((resolve, reject) => {
155 | reader.onload = (event) => resolve(event.target.result);
156 | reader.onerror = (error) => reject(error);
157 | reader.readAsText(file);
158 | });
159 | }
160 |
161 | return (
162 |
163 |
164 |
165 |
179 |
180 |
185 |
188 |
189 |
190 | {isOpenModal.show && }
191 |
192 | )
193 | }
194 |
195 | export default Playground
--------------------------------------------------------------------------------
/src/style/global.js:
--------------------------------------------------------------------------------
1 | import { createGlobalStyle } from "styled-components";
2 |
3 | export const GlobalStyle = createGlobalStyle`
4 | *{
5 | padding: 0;
6 | margin: 0;
7 | box-sizing: border-box;
8 | font-family: 'Play', sans-serif;
9 | }
10 |
11 | a{
12 | text-decoration: none;
13 | }
14 | `
--------------------------------------------------------------------------------