add autosave and serialmonitor
This commit is contained in:
		
							parent
							
								
									19849d68ab
								
							
						
					
					
						commit
						d682accdbf
					
				
							
								
								
									
										57
									
								
								src/App.css
									
									
									
									
									
								
							
							
						
						
									
										57
									
								
								src/App.css
									
									
									
									
									
								
							| @ -1,51 +1,50 @@ | |||||||
| .wrapper { | .wrapper { | ||||||
|   min-height: calc(100vh - 60px); /* will cover the 100% of viewport - height of footer (padding-bottom) */ |   min-height: calc( | ||||||
|  |     100vh - 60px | ||||||
|  |   ); /* will cover the 100% of viewport - height of footer (padding-bottom) */ | ||||||
|   overflow: hidden; |   overflow: hidden; | ||||||
|   display: block; |   display: block; | ||||||
|   position: relative; |   position: relative; | ||||||
|   padding-bottom: 60px; /* height of your footer + 30px*/ |   padding-bottom: 60px; /* height of your footer + 30px*/ | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | .tutorial img { | ||||||
| .tutorial img{ |  | ||||||
|   display: flex; |   display: flex; | ||||||
|   align-items: center; |   align-items: center; | ||||||
|   max-height: 40vH; |   max-height: 40vh; | ||||||
|   max-width: 100%; |   max-width: 100%; | ||||||
|   margin: auto; |   margin: auto; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| .news img{ | .news img { | ||||||
|   display: flex; |   display: flex; | ||||||
|   align-items: center; |   align-items: center; | ||||||
|   max-height: 40vH; |   max-height: 40vh; | ||||||
|   max-width: 100%; |   max-width: 100%; | ||||||
|   margin: auto; |   margin: auto; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| .tutorial blockquote{ | .tutorial blockquote { | ||||||
|     background: #f9f9f9; |   background: #f9f9f9; | ||||||
|     border-left: 10px solid#4EAF47; |   border-left: 10px solid#4EAF47; | ||||||
|     margin: 1.5em 10px; |   margin: 1.5em 10px; | ||||||
|     padding: 0.5em 10px; |   padding: 0.5em 10px; | ||||||
|     quotes: "\201C""\201D""\2018""\2019"; |   quotes: "\201C""\201D""\2018""\2019"; | ||||||
|   } | } | ||||||
|   blockquote:before { | blockquote:before { | ||||||
|     color:#4EAF47; |   color: #4eaf47; | ||||||
|     content: open-quote; |   content: open-quote; | ||||||
|     font-size: 4em; |   font-size: 4em; | ||||||
|     line-height: 0.1em; |   line-height: 0.1em; | ||||||
|     margin-right: 0.25em; |   margin-right: 0.25em; | ||||||
|     vertical-align: -0.4em; |   vertical-align: -0.4em; | ||||||
|   } | } | ||||||
|   blockquote p { | blockquote p { | ||||||
|     display: inline; |   display: inline; | ||||||
|   } | } | ||||||
| 
 | 
 | ||||||
| .overlay { | .overlay { | ||||||
|     display: flex; |   display: flex; | ||||||
|     flex-direction: column; |   flex-direction: column; | ||||||
|     align-items: center; |   align-items: center; | ||||||
| } | } | ||||||
| 
 |  | ||||||
|    |  | ||||||
|  | |||||||
| @ -9,6 +9,7 @@ import { saveAs } from "file-saver"; | |||||||
| import Drawer from "@material-ui/core/Drawer"; | import Drawer from "@material-ui/core/Drawer"; | ||||||
| import Sidebar from "./Sidebar"; | import Sidebar from "./Sidebar"; | ||||||
| import Dialog from "../Dialog"; | import Dialog from "../Dialog"; | ||||||
|  | import Snackbar from "../Snackbar"; | ||||||
| 
 | 
 | ||||||
| const CodeEditor = (props) => { | const CodeEditor = (props) => { | ||||||
|   const [fileHandle, setFileHandle] = useState(); |   const [fileHandle, setFileHandle] = useState(); | ||||||
| @ -18,7 +19,21 @@ const CodeEditor = (props) => { | |||||||
|   const [open, setOpen] = useState(false); |   const [open, setOpen] = useState(false); | ||||||
|   const [error, setError] = useState(""); |   const [error, setError] = useState(""); | ||||||
|   const editorRef = useRef(null); |   const editorRef = useRef(null); | ||||||
|  |   const [autoSave, setAutoSave] = useState(false); | ||||||
|  |   const [time, setTime] = useState(null); | ||||||
|  |   const [value, setValue] = useState(""); | ||||||
|  |   const [defaultValue, setDefaultValue] = useState( | ||||||
|  |     sessionStorage.getItem("ArduinoCode") | ||||||
|  |       ? sessionStorage.getItem("ArduinoCode") | ||||||
|  |       : ` | ||||||
|  | void setup () { | ||||||
|           |           | ||||||
|  | } | ||||||
|  |            | ||||||
|  | void loop() { | ||||||
|  |            | ||||||
|  | }` | ||||||
|  |   ); | ||||||
|   const compile = () => { |   const compile = () => { | ||||||
|     setProgress(true); |     setProgress(true); | ||||||
|     const data = { |     const data = { | ||||||
| @ -86,6 +101,34 @@ const CodeEditor = (props) => { | |||||||
|     editorRef.current.setValue("test"); |     editorRef.current.setValue("test"); | ||||||
|   }; |   }; | ||||||
| 
 | 
 | ||||||
|  |   const handleChange = () => { | ||||||
|  |     setAutoSave(!autoSave); | ||||||
|  |   }; | ||||||
|  | 
 | ||||||
|  |   const resetTimeout = (id, newID) => { | ||||||
|  |     clearTimeout(id); | ||||||
|  |     return newID; | ||||||
|  |   }; | ||||||
|  | 
 | ||||||
|  |   const editValue = (value) => { | ||||||
|  |     setTime(resetTimeout(time, setTimeout(saveValue, 400))); | ||||||
|  |     setValue(value); | ||||||
|  |   }; | ||||||
|  | 
 | ||||||
|  |   const saveValue = () => { | ||||||
|  |     sessionStorage.setItem("ArduinoCode", value); | ||||||
|  |     setAutoSave(true); | ||||||
|  |     setTimeout(() => setAutoSave(false), 1000); | ||||||
|  |   }; | ||||||
|  | 
 | ||||||
|  |   const handleClose = (event, reason) => { | ||||||
|  |     if (reason === "clickaway") { | ||||||
|  |       return; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     setOpen(false); | ||||||
|  |   }; | ||||||
|  | 
 | ||||||
|   return ( |   return ( | ||||||
|     <div> |     <div> | ||||||
|       <Grid container spacing={2}> |       <Grid container spacing={2}> | ||||||
| @ -128,15 +171,11 @@ const CodeEditor = (props) => { | |||||||
|           <h1>Code Editor</h1> |           <h1>Code Editor</h1> | ||||||
|           <MonacoEditor |           <MonacoEditor | ||||||
|             height="80vh" |             height="80vh" | ||||||
|  |             onChange={(value) => { | ||||||
|  |               editValue(value); | ||||||
|  |             }} | ||||||
|             defaultLanguage="cpp" |             defaultLanguage="cpp" | ||||||
|             defaultValue={` |             defaultValue={defaultValue} | ||||||
| void setup () { |  | ||||||
| 
 |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void loop(){ |  | ||||||
| 
 |  | ||||||
| }`}
 |  | ||||||
|             value={fileContent} |             value={fileContent} | ||||||
|             onMount={(editor, monaco) => { |             onMount={(editor, monaco) => { | ||||||
|               editorRef.current = editor; |               editorRef.current = editor; | ||||||
| @ -176,25 +215,25 @@ void loop(){ | |||||||
|           > |           > | ||||||
|             Reset Editor |             Reset Editor | ||||||
|           </Button> |           </Button> | ||||||
|  |           <Snackbar | ||||||
|  |             open={autoSave} | ||||||
|  |             message={"Automatisch gespeichert"} | ||||||
|  |             type={"success"} | ||||||
|  |             key={Date.now()} | ||||||
|  |           /> | ||||||
|           <Sidebar /> |           <Sidebar /> | ||||||
|  | 
 | ||||||
|           <Dialog |           <Dialog | ||||||
|             style={{ zIndex: 9999999 }} |             style={{ zIndex: 9999999 }} | ||||||
|             fullWidth |             fullWidth | ||||||
|             maxWidth={"sm"} |             maxWidth={"sm"} | ||||||
|             open={progress} |             open={progress} | ||||||
|             title={Blockly.Msg.tabletDialog_headline} |             title={"Code wird kompiliert"} | ||||||
|             content={""} |             content={""} | ||||||
|           > |           > | ||||||
|             <div>{Blockly.Msg.tabletDialog_text}</div> |  | ||||||
|             <div> |             <div> | ||||||
|               {Blockly.Msg.tabletDialog_more}{" "} |               Dein Code wird nun kompiliert und anschließend auf deinen Computer | ||||||
|               <a |               heruntergeladen | ||||||
|                 href="https://sensebox.de/app" |  | ||||||
|                 target="_blank" |  | ||||||
|                 rel="noreferrer" |  | ||||||
|               > |  | ||||||
|                 https://sensebox.de/app
 |  | ||||||
|               </a> |  | ||||||
|             </div> |             </div> | ||||||
|           </Dialog> |           </Dialog> | ||||||
|         </Grid> |         </Grid> | ||||||
|  | |||||||
							
								
								
									
										92
									
								
								src/components/CodeEditor/SerialMonitor.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										92
									
								
								src/components/CodeEditor/SerialMonitor.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,92 @@ | |||||||
|  | import { useState } from "react"; | ||||||
|  | import Button from "@material-ui/core/Button"; | ||||||
|  | 
 | ||||||
|  | const SerialMonitor = () => { | ||||||
|  |   const [serialPortContent, setSerialPortContent] = useState([]); | ||||||
|  | 
 | ||||||
|  |   const [checked, setChecked] = useState(false); | ||||||
|  |   const handleClick = () => setChecked(!checked); | ||||||
|  | 
 | ||||||
|  |   const connectPort = async () => { | ||||||
|  |     try { | ||||||
|  |       const port = await navigator.serial.requestPort(); | ||||||
|  | 
 | ||||||
|  |       await port.open({ baudRate: 9600 }); | ||||||
|  | 
 | ||||||
|  |       while (port.readable) { | ||||||
|  |         const reader = port.readable.getReader(); | ||||||
|  | 
 | ||||||
|  |         try { | ||||||
|  |           while (true) { | ||||||
|  |             const { value, done } = await reader.read(); | ||||||
|  |             if (done) { | ||||||
|  |               // Allow the serial port to be closed later.
 | ||||||
|  |               reader.releaseLock(); | ||||||
|  |               break; | ||||||
|  |             } | ||||||
|  |             if (value) { | ||||||
|  |               //   byte array to string: https://stackoverflow.com/a/37542820
 | ||||||
|  |               const text = String.fromCharCode.apply(null, value); | ||||||
|  |               console.log(text); | ||||||
|  |               setSerialPortContent((prevContent) => [ | ||||||
|  |                 ...prevContent, | ||||||
|  |                 [new Date(), text], | ||||||
|  |               ]); | ||||||
|  |             } | ||||||
|  |           } | ||||||
|  |         } catch (error) { | ||||||
|  |           setSerialPortContent((prevContent) => [ | ||||||
|  |             ...prevContent, | ||||||
|  |             [new Date(), error], | ||||||
|  |           ]); | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  |     } catch (error) { | ||||||
|  |       setSerialPortContent((prevContent) => [ | ||||||
|  |         ...prevContent, | ||||||
|  |         [new Date(), error], | ||||||
|  |       ]); | ||||||
|  |     } | ||||||
|  |   }; | ||||||
|  | 
 | ||||||
|  |   return ( | ||||||
|  |     <> | ||||||
|  |       <div className="flex items-center"> | ||||||
|  |         <Button type="button" variant="outlined" onClick={() => connectPort()}> | ||||||
|  |           Connect to senseBox | ||||||
|  |         </Button> | ||||||
|  |         <label className="m-4 text-gray-700 text-base font-semibold px-6 py-3 rounded-lg"> | ||||||
|  |           Show timestamps | ||||||
|  |           <input | ||||||
|  |             onChange={handleClick} | ||||||
|  |             checked={checked} | ||||||
|  |             type="checkbox" | ||||||
|  |             className="mx-4" | ||||||
|  |           /> | ||||||
|  |         </label> | ||||||
|  |         <Button | ||||||
|  |           type="button" | ||||||
|  |           variant="outlined" | ||||||
|  |           onClick={() => setSerialPortContent([])} | ||||||
|  |         > | ||||||
|  |           Clear | ||||||
|  |         </Button> | ||||||
|  |       </div> | ||||||
|  |       <div className="font-mono"> | ||||||
|  |         {serialPortContent.map((log) => { | ||||||
|  |           return ( | ||||||
|  |             <p> | ||||||
|  |               {checked && ( | ||||||
|  |                 <span className="font-medium mr-4">{log[0].toISOString()}</span> | ||||||
|  |               )} | ||||||
|  | 
 | ||||||
|  |               <span>{log[1]}</span> | ||||||
|  |             </p> | ||||||
|  |           ); | ||||||
|  |         })} | ||||||
|  |       </div> | ||||||
|  |     </> | ||||||
|  |   ); | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | export default SerialMonitor; | ||||||
| @ -6,9 +6,10 @@ import AccordionDetails from "@material-ui/core/AccordionDetails"; | |||||||
| import Typography from "@material-ui/core/Typography"; | import Typography from "@material-ui/core/Typography"; | ||||||
| import { LibraryVersions } from "../../data/versions.js"; | import { LibraryVersions } from "../../data/versions.js"; | ||||||
| import { ArduinoExamples } from "../../data/arduinoExamples.js"; | import { ArduinoExamples } from "../../data/arduinoExamples.js"; | ||||||
| import Editor, { useMonaco } from "@monaco-editor/react"; | import { useMonaco } from "@monaco-editor/react"; | ||||||
| import { Button } from "@material-ui/core"; | import { Button } from "@material-ui/core"; | ||||||
| import Dialog from "../Dialog"; | import Dialog from "../Dialog"; | ||||||
|  | import SerialMonitor from "./SerialMonitor.js"; | ||||||
| 
 | 
 | ||||||
| const Sidebar = () => { | const Sidebar = () => { | ||||||
|   const [alert, setAlert] = React.useState(false); |   const [alert, setAlert] = React.useState(false); | ||||||
| @ -37,6 +38,23 @@ void loop(){ | |||||||
| 
 | 
 | ||||||
|   return ( |   return ( | ||||||
|     <div> |     <div> | ||||||
|  |       {"serial" in navigator ? ( | ||||||
|  |         <Accordion> | ||||||
|  |           <AccordionSummary | ||||||
|  |             expandIcon={""} | ||||||
|  |             aria-controls="panel1a-content" | ||||||
|  |             id="panel1a-header" | ||||||
|  |           > | ||||||
|  |             <Typography>Serial Monitor</Typography> | ||||||
|  |           </AccordionSummary> | ||||||
|  |           <AccordionDetails> | ||||||
|  |             <Typography> | ||||||
|  |               <SerialMonitor /> | ||||||
|  |             </Typography> | ||||||
|  |           </AccordionDetails> | ||||||
|  |         </Accordion> | ||||||
|  |       ) : null} | ||||||
|  | 
 | ||||||
|       <Accordion> |       <Accordion> | ||||||
|         <AccordionSummary |         <AccordionSummary | ||||||
|           expandIcon={""} |           expandIcon={""} | ||||||
| @ -70,8 +88,12 @@ void loop(){ | |||||||
|         > |         > | ||||||
|           <Typography>Installierte Libraries</Typography> |           <Typography>Installierte Libraries</Typography> | ||||||
|         </AccordionSummary> |         </AccordionSummary> | ||||||
|         <AccordionDetails> |         <AccordionDetails | ||||||
|           <Typography> |           style={{ padding: 0, height: "60vH", backgroundColor: "white" }} | ||||||
|  |         > | ||||||
|  |           <Typography | ||||||
|  |             style={{ overflow: "auto", width: "100%", padding: "1rem" }} | ||||||
|  |           > | ||||||
|             <p> |             <p> | ||||||
|               For Dokumentation take a look at the installed libraries and their |               For Dokumentation take a look at the installed libraries and their | ||||||
|               source |               source | ||||||
|  | |||||||
| @ -34,6 +34,7 @@ import { | |||||||
|   faChalkboardTeacher, |   faChalkboardTeacher, | ||||||
|   faTools, |   faTools, | ||||||
|   faLightbulb, |   faLightbulb, | ||||||
|  |   faCode, | ||||||
| } from "@fortawesome/free-solid-svg-icons"; | } from "@fortawesome/free-solid-svg-icons"; | ||||||
| import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; | import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; | ||||||
| import * as Blockly from "blockly"; | import * as Blockly from "blockly"; | ||||||
| @ -232,7 +233,7 @@ class Navbar extends Component { | |||||||
|               }, |               }, | ||||||
|               { |               { | ||||||
|                 text: "CodeEditor", |                 text: "CodeEditor", | ||||||
|                 icon: faLightbulb, |                 icon: faCode, | ||||||
|                 link: "/codeeditor", |                 link: "/codeeditor", | ||||||
|               }, |               }, | ||||||
|               { |               { | ||||||
|  | |||||||
| @ -1,5 +1,3 @@ | |||||||
| import * as Blockly from "blockly/core"; |  | ||||||
| 
 |  | ||||||
| export const ArduinoExamples = () => { | export const ArduinoExamples = () => { | ||||||
|   return [ |   return [ | ||||||
|     { |     { | ||||||
|  | |||||||
| @ -1,5 +1,3 @@ | |||||||
| import * as Blockly from "blockly/core"; |  | ||||||
| 
 |  | ||||||
| export const LibraryVersions = () => { | export const LibraryVersions = () => { | ||||||
|   return [ |   return [ | ||||||
|     { |     { | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user