Front End Project Structure

Front end Project Structure

Install MUI npm install @mui/material @emotion/react @emotion/styled

Install Monaco Editor npm i @monaco-editor/react

Creating AppBar.js inside widgets folder

import * as React from 'react';
import AppBar from '@mui/material/AppBar';
import Box from '@mui/material/Box';
import Toolbar from '@mui/material/Toolbar';
import Typography from '@mui/material/Typography';
import IconButton from '@mui/material/IconButton';
import MenuIcon from '@mui/icons-material/Menu';

export default function MyAppBar() {
  return (
    <Box sx={{ flexGrow: 1 }}>
      <AppBar position="sticky" elevation={0} >
        <Toolbar variant="dense">
          <IconButton edge="start" color="inherit" aria-label="menu" sx={{ mr: 2 }}>
            <MenuIcon />
          </IconButton>
          <Typography variant="h6" color="inherit" component="div">
            My Code Editor
          </Typography>
        </Toolbar>
      </AppBar>
    </Box>
  );
}

Create Code Component inside the pages folder

import Container from '@mui/material/Container';
import Box from '@mui/material/Box';
import Grid from '@mui/material/Grid';
import { CodeEditor } from '../components/CodeEditor';
import { Output } from '../components/Output';
import { useMonaco } from '@monaco-editor/react';
import MyAppBar from '../widgets/AppBar';
import { useState } from 'react';
export const Code = ()=>{
    const [display, setDisplay]= useState('');
   const showResult = (res)=>{
    console.log('Data is ',res);
    setDisplay(res.data.result);
   }
    return (<>
    <MyAppBar/>
    <Grid sx={{ flexGrow: 1 }} container spacing={2}>
        <Grid item md={8}>
            <CodeEditor showResult={showResult}/>
        </Grid>
        <Grid item md={4}>
            <Output result = {display}/>
        </Grid>
        </Grid>
      
  </>);
}

Create editor Component

import Editor, { useMonaco } from "@monaco-editor/react";
import { useRef } from "react";
import Button from '@mui/material/Button';
import { sendCode } from "../services/api-client";
import TextField from '@mui/material/TextField';

export const CodeEditor = ({showResult})=>{
  const editorRef = useRef(null);
  const fileName = useRef('');
  const getCode = async ()=>{
    const fName = fileName.current.value;
    const val = editorRef.current?.getValue();
    console.log('val ',val);
    const result = await sendCode(val, fName);
    showResult(result);    
  }
  const options = {"fontSize": 20, selectOnLineNumbers: true,cursorStyle: 'line',
  colorDecorators: true
  ,scrollbar: {
    // Subtle shadows to the left & top. Defaults to true.
    useShadows: false,
    // Render vertical arrows. Defaults to false.
    verticalHasArrows: true,
    // Render horizontal arrows. Defaults to false.
    horizontalHasArrows: true,
    // Render vertical scrollbar.
    // Accepted values: 'auto', 'visible', 'hidden'.
    // Defaults to 'auto'
    vertical: 'visible',
    // Render horizontal scrollbar.
    // Accepted values: 'auto', 'visible', 'hidden'.
    // Defaults to 'auto'
    horizontal: 'visible',
    verticalScrollbarSize: 17,
    horizontalScrollbarSize: 17,
    arrowSize: 30,
  },};
    
    const handleEditorDidMount = (editor, monaco) =>{
      editorRef.current = editor;
      
      editor.focus();
      // let options = {"fontSize": 20, selectOnLineNumbers: true,cursorStyle: 'line',scrollbar: {
      //   // Subtle shadows to the left & top. Defaults to true.
      //   useShadows: false,
      //   // Render vertical arrows. Defaults to false.
      //   verticalHasArrows: true,
      //   // Render horizontal arrows. Defaults to false.
      //   horizontalHasArrows: true,
      //   // Render vertical scrollbar.
      //   // Accepted values: 'auto', 'visible', 'hidden'.
      //   // Defaults to 'auto'
      //   vertical: 'visible',
      //   // Render horizontal scrollbar.
      //   // Accepted values: 'auto', 'visible', 'hidden'.
      //   // Defaults to 'auto'
      //   horizontal: 'visible',
      //   verticalScrollbarSize: 17,
      //   horizontalScrollbarSize: 17,
      //   arrowSize: 30,
      // },}
      //editor.updateOptions(options);
     
       
      }

    return (
      <>
      <TextField inputRef={fileName} id="outlined-basic" label="FileName" variant="outlined" />
        <Editor
        
        className="style"
        theme="vs-dark"
        onMount={handleEditorDidMount}
     height="80%"
     width="100%"
     defaultLanguage="java"
     defaultValue="// Write Code Here"
     options={options}
   />
   <Button onClick={getCode} color='success' variant="contained">Compile and Run</Button>
   </>
    );
}

Create Output Component


import * as React from 'react';
import Box from '@mui/material/Box';

export const Output = ({result})=>{
    return (<div>
       



        <Box
      sx={{
        width: "90%",
        height: "70vh",
        p: 2, border: '1px dashed grey'
      }}
    >
          {result}
    </Box>
 

    </div>)
}

Install axios for BackEnd API Call.   npm i axios

Create api-client.js inside the services folder

import axios from 'axios';
export const sendCode = async (code, fileName)=>{
    const URL = 'http://localhost:1234/compile-run';
    const codeObject  = {'code':code, 'filename':fileName};
    const result = await axios.post(URL,codeObject);
    return result;
}

Let's start with BackEnd Now

BackEnd Folder Structure

Install express and cors (npm i express cors)

const express = require('express');
const app = express();
const cors = require('cors');
app.use(cors());
app.use(express.json());
app.use('/', require('./routes/route'));
const server = app.listen(1234, err=>{
    if(err){
        console.log('Server Crash ', err);
    }
    else{
        console.log('Server Start ', server.address().port);
    }
})
const express = require('express');
const router = express.Router();
const childProcess = require('child_process');
const path = require('path');
router.post('/compile-run',(request, response)=>{
    const code = request.body.code;
    const fileName = request.body.filename;
    console.log('Body is ', request.body);
    const fs = require('fs');
    const parent = path.normalize(__dirname+'/..');
    const fullPath = path.join(parent,'/mycode',fileName);
    const sourceFile=fullPath+".java";
    console.log('Source File Path ', sourceFile);
    fs.writeFileSync(sourceFile,code);
    
    try{

        let result= childProcess.execSync('javac '+sourceFile);
        const mycodeDir = path.join(parent,'/mycode');
        console.log('Code DIR ', mycodeDir);
        console.log('My File ',fileName);
       
        console.log('PWD ',result.toString());
        const commands = ` cd ${mycodeDir} 
        pwd ${fileName}
        java ${fileName}
        `;
         result = childProcess.execSync(commands);
         console.log(result.toString());
        response.status(200).json({result:result.toString()});
    }
    catch(err){
        response.status(500).json({result:JSON.stringify(err)});
    }
    
});
module.exports = router;

That's All Folks, Happy Coding :)