From c908aa5b633bc4a7f7151c938df8bc2dcb1ea16d Mon Sep 17 00:00:00 2001
From: fbruc03 <65135023+fbruc03@users.noreply.github.com>
Date: Thu, 17 Feb 2022 18:33:31 +0100
Subject: [PATCH 1/5] file upload with multer
---
package.json | 4 +-
src/components/Tutorial/Builder/Builder.js | 2 +
.../Tutorial/Builder/MarkdownEditor.js | 83 +++++++++++++++++++
src/components/Tutorial/Builder/Step.js | 79 +++++++++++-------
4 files changed, 139 insertions(+), 29 deletions(-)
create mode 100644 src/components/Tutorial/Builder/MarkdownEditor.js
diff --git a/package.json b/package.json
index 6196f1a..1ba65e0 100644
--- a/package.json
+++ b/package.json
@@ -21,6 +21,7 @@
"axios": "^0.22.0",
"blockly": "^6.20210701.0",
"file-saver": "^2.0.2",
+ "markdown-it": "^12.3.2",
"mnemonic-id": "^3.2.7",
"moment": "^2.28.0",
"prismjs": "^1.25.0",
@@ -28,6 +29,7 @@
"react-cookie-consent": "^7.0.0",
"react-dom": "^17.0.2",
"react-markdown": "^5.0.2",
+ "react-markdown-editor-lite": "^1.3.2",
"react-mde": "^11.5.0",
"react-redux": "^7.2.4",
"react-router-dom": "^5.2.0",
@@ -39,7 +41,7 @@
"uuid": "^8.3.1"
},
"scripts": {
- "start": "react-scripts start",
+ "start": "node_modules/react-scripts/bin/react-scripts.js start",
"dev": "set \"REACT_APP_BLOCKLY_API=http://localhost:8080\" && npm start",
"build": "react-scripts build",
"test": "react-scripts test",
diff --git a/src/components/Tutorial/Builder/Builder.js b/src/components/Tutorial/Builder/Builder.js
index 12803c2..4bbad7f 100644
--- a/src/components/Tutorial/Builder/Builder.js
+++ b/src/components/Tutorial/Builder/Builder.js
@@ -41,6 +41,8 @@ import FormControl from "@material-ui/core/FormControl";
import Select from "@material-ui/core/Select";
import * as Blockly from "blockly";
+import MarkdownEditor from "./MarkdownEditor";
+
const styles = (theme) => ({
backdrop: {
zIndex: theme.zIndex.drawer + 1,
diff --git a/src/components/Tutorial/Builder/MarkdownEditor.js b/src/components/Tutorial/Builder/MarkdownEditor.js
new file mode 100644
index 0000000..6155c3b
--- /dev/null
+++ b/src/components/Tutorial/Builder/MarkdownEditor.js
@@ -0,0 +1,83 @@
+import React, { Component, useRef } from "react";
+import PropTypes from "prop-types";
+import { connect } from "react-redux";
+import {
+ tutorialTitle,
+ jsonString,
+ changeContent,
+ setError,
+ deleteError,
+} from "../../../actions/tutorialBuilderActions";
+
+import FormControl from "@material-ui/core/FormControl";
+import Button from "@material-ui/core/Button";
+import MarkdownIt from "markdown-it";
+import Editor from "react-markdown-editor-lite";
+import "react-markdown-editor-lite/lib/index.css";
+
+import axios from "axios";
+
+const mdParser = new MarkdownIt(/* Markdown-it options */);
+
+const MarkdownEditor = (props) => {
+ const [value, setValue] = React.useState(props.value);
+
+ const mdEditor = React.useRef(null);
+
+ function handleChange({ html, text }) {
+ setValue(text);
+ var value = text;
+ console.log(text);
+ props.changeContent(value, props.index, props.property, props.property2);
+ if (value.replace(/\s/g, "") === "") {
+ props.setError(props.index, props.property);
+ } else {
+ props.deleteError(props.index, props.property);
+ }
+ }
+
+ async function uploadImage(files) {
+ return new Promise((resolve, reject) => {
+ const formData = new FormData();
+ formData.append("files", files);
+ axios({
+ method: "post",
+ url: `${process.env.REACT_APP_BLOCKLY_API}/upload/uploadImage`,
+ data: formData,
+ headers: { "Content-Type": "multipart/form-data" },
+ })
+ .then((res) => {
+ console.log(res);
+ resolve(`${process.env.REACT_APP_BLOCKLY_API}/upload/`+res.data.filename);
+ })
+ .catch((err) => {
+ reject(new Error("error"));
+ })
+ })
+ }
+
+ return (
+
+ mdParser.render(text)}
+ onChange={handleChange}
+ value={value}
+ id={props.property}
+ label={props.label}
+ property={props.property}
+ onImageUpload={uploadImage}
+ plugins={[]}
+ />
+
+ );
+};
+
+export default connect(null, {
+ tutorialTitle,
+ jsonString,
+ changeContent,
+ setError,
+ deleteError,
+})(MarkdownEditor);
\ No newline at end of file
diff --git a/src/components/Tutorial/Builder/Step.js b/src/components/Tutorial/Builder/Step.js
index ba0e18c..6cee443 100644
--- a/src/components/Tutorial/Builder/Step.js
+++ b/src/components/Tutorial/Builder/Step.js
@@ -20,6 +20,8 @@ import Tooltip from '@material-ui/core/Tooltip';
import { faPlus, faAngleDoubleUp, faAngleDoubleDown, faTrash } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
+import MarkdownEditor from "./MarkdownEditor";
+
const styles = (theme) => ({
button: {
backgroundColor: theme.palette.primary.main,
@@ -47,67 +49,88 @@ class Step extends Component {
var index = this.props.index;
var steps = this.props.steps;
return (
-
-
Schritt {index+1}
-
-
+
+
Schritt {index + 1}
+
+
this.props.addStep(index+1)}
+ style={index === 0 ? {} : { marginBottom: '5px' }}
+ onClick={() => this.props.addStep(index + 1)}
>
-
+
{index !== 0 ?
-
+
this.props.changeStepIndex(index, index-1)}
+ style={{ marginBottom: '5px' }}
+ onClick={() => this.props.changeStepIndex(index, index - 1)}
>
-
+
-
+
this.props.changeStepIndex(index, index+1)}
+ style={{ marginBottom: '5px' }}
+ onClick={() => this.props.changeStepIndex(index, index + 1)}
>
-
+
-
+
this.props.removeStep(index)}
>
-
+
- : null}
+ : null}
-
+
-
-
+
+
{index === 0 ?
-
-
+
+
- : null}
+ : null}
{this.props.step.type === 'instruction' ?
- : null}
-
+ : null}
+
@@ -130,4 +153,4 @@ const mapStateToProps = state => ({
error: state.builder.error
});
-export default connect(mapStateToProps, { addStep, removeStep, changeStepIndex })(withStyles(styles, {withTheme: true})(Step));
+export default connect(mapStateToProps, { addStep, removeStep, changeStepIndex })(withStyles(styles, { withTheme: true })(Step));
From f3f6819f05a3a772aa7e510e593dfa91519f7528 Mon Sep 17 00:00:00 2001
From: fbruc03 <65135023+fbruc03@users.noreply.github.com>
Date: Fri, 18 Feb 2022 10:56:42 +0100
Subject: [PATCH 2/5] bring plugins back
---
src/components/Tutorial/Builder/MarkdownEditor.js | 1 -
1 file changed, 1 deletion(-)
diff --git a/src/components/Tutorial/Builder/MarkdownEditor.js b/src/components/Tutorial/Builder/MarkdownEditor.js
index 6155c3b..86a7676 100644
--- a/src/components/Tutorial/Builder/MarkdownEditor.js
+++ b/src/components/Tutorial/Builder/MarkdownEditor.js
@@ -68,7 +68,6 @@ const MarkdownEditor = (props) => {
label={props.label}
property={props.property}
onImageUpload={uploadImage}
- plugins={[]}
/>
);
From 3a8f0c38f60fe1c9403bdaf008ef6bb017ebf0d9 Mon Sep 17 00:00:00 2001
From: fbruc03 <65135023+fbruc03@users.noreply.github.com>
Date: Fri, 18 Feb 2022 11:12:55 +0100
Subject: [PATCH 3/5] add markdown
---
src/components/Tutorial/Assessment.js | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/src/components/Tutorial/Assessment.js b/src/components/Tutorial/Assessment.js
index 5dd24b7..e981be4 100644
--- a/src/components/Tutorial/Assessment.js
+++ b/src/components/Tutorial/Assessment.js
@@ -14,6 +14,8 @@ import Typography from "@material-ui/core/Typography";
import * as Blockly from "blockly";
import { initialXml } from "../Blockly/initialXml";
+import ReactMarkdown from 'react-markdown'
+
class Assessment extends Component {
componentDidMount() {
this.props.workspaceName(this.props.name);
@@ -81,7 +83,8 @@ class Assessment extends Component {
{Blockly.Msg.tutorials_assessment_task}
-
{currentTask.text}
+
+ {currentTask.text}
Date: Fri, 18 Feb 2022 11:33:07 +0100
Subject: [PATCH 4/5] fix double ReactMarkdown import
---
src/components/Tutorial/Assessment.js | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/src/components/Tutorial/Assessment.js b/src/components/Tutorial/Assessment.js
index 76e527c..d69821f 100644
--- a/src/components/Tutorial/Assessment.js
+++ b/src/components/Tutorial/Assessment.js
@@ -42,8 +42,6 @@ const styles = (theme) => ({
},
});
-import ReactMarkdown from 'react-markdown'
-
class Assessment extends Component {
constructor(props) {
super(props);
@@ -105,7 +103,7 @@ class Assessment extends Component {
{currentTask.text}
-
+
Date: Fri, 18 Feb 2022 12:20:22 +0100
Subject: [PATCH 5/5] resolve warnings
---
src/App.js | 4 +-
src/components/CodeEditor/CodeEditor.js | 37 ++-
src/components/Faq.js | 251 ++++++------------
src/components/Route/PrivateRoute.js | 49 ++--
src/components/Tutorial/Assessment.js | 2 +-
src/components/Tutorial/Builder/Builder.js | 17 --
src/components/Tutorial/Builder/Hardware.js | 172 +++++++-----
.../Tutorial/Builder/MarkdownEditor.js | 117 ++++----
src/components/Tutorial/Builder/Step.js | 165 ++++++++----
src/components/Tutorial/Builder/Textfield.js | 8 -
src/components/Tutorial/Hardware.js | 115 +++++---
src/components/Workspace/WorkspaceName.js | 2 +-
src/index.js | 18 +-
13 files changed, 492 insertions(+), 465 deletions(-)
diff --git a/src/App.js b/src/App.js
index 1ca2aba..f4aad55 100644
--- a/src/App.js
+++ b/src/App.js
@@ -9,11 +9,11 @@ import { loadUser } from "./actions/authActions";
import "./App.css";
-import { ThemeProvider, createMuiTheme } from "@material-ui/core/styles";
+import { ThemeProvider, createTheme } from "@material-ui/core/styles";
import Content from "./components/Content";
-const theme = createMuiTheme({
+const theme = createTheme({
palette: {
primary: {
main: "#4EAF47",
diff --git a/src/components/CodeEditor/CodeEditor.js b/src/components/CodeEditor/CodeEditor.js
index 73f86b3..ff33ab4 100644
--- a/src/components/CodeEditor/CodeEditor.js
+++ b/src/components/CodeEditor/CodeEditor.js
@@ -13,10 +13,10 @@ import SaveIcon from "./SaveIcon";
import store from "../../store";
const CodeEditor = (props) => {
- const [fileHandle, setFileHandle] = useState();
+ //const [filehandle, setFileHandle] = useState();
const [fileContent, setFileContent] = useState("");
const [progress, setProgress] = useState(false);
- const [id, setId] = useState("");
+ // const [id, setId] = useState("");
const [open, setOpen] = useState(false);
const [error, setError] = useState("");
const editorRef = useRef(null);
@@ -24,20 +24,6 @@ const CodeEditor = (props) => {
const [time, setTime] = useState(null);
const [value, setValue] = useState("");
const [resetDialog, setResetDialog] = useState(false);
- const [defaultValue, setDefaultValue] = useState(
- localStorage.getItem("ArduinoCode")
- ? localStorage.getItem("ArduinoCode")
- : `
-#include //needs to be always included
-
-void setup () {
-
-}
-
-void loop() {
-
-}`
- );
const compile = () => {
setProgress(true);
@@ -60,7 +46,7 @@ void loop() {
}
setProgress(false);
const result = data.data.id;
- setId(result);
+ //setId(result);
const filename = "sketch";
window.open(
`${process.env.REACT_APP_COMPILER_URL}/download?id=${result}&board=${process.env.REACT_APP_BOARD}&filename=${filename}`,
@@ -83,7 +69,7 @@ void loop() {
const openIno = async () => {
const [myFileHandle] = await window.showOpenFilePicker();
- setFileHandle(myFileHandle);
+ //setFileHandle(myFileHandle);
const file = await myFileHandle.getFile();
const contents = await file.text();
@@ -187,7 +173,20 @@ void loop() {
editValue(value);
}}
defaultLanguage="cpp"
- defaultValue={defaultValue}
+ defaultValue={
+ localStorage.getItem("ArduinoCode")
+ ? localStorage.getItem("ArduinoCode")
+ : `
+ #include //needs to be always included
+
+ void setup () {
+
+ }
+
+ void loop() {
+
+ }`
+ }
value={fileContent}
onMount={(editor, monaco) => {
editorRef.current = editor;
diff --git a/src/components/Faq.js b/src/components/Faq.js
index 4269c1e..2909fc7 100644
--- a/src/components/Faq.js
+++ b/src/components/Faq.js
@@ -1,179 +1,100 @@
-import React, { Component } from 'react';
+import React, { Component } from "react";
-import Breadcrumbs from './Breadcrumbs';
+import Breadcrumbs from "./Breadcrumbs";
-import { withRouter } from 'react-router-dom';
+import { withRouter } from "react-router-dom";
-import Button from '@material-ui/core/Button';
-import Typography from '@material-ui/core/Typography';
-import * as Blockly from 'blockly'
-import ReactMarkdown from 'react-markdown';
-import Container from '@material-ui/core/Container';
-import ExpansionPanel from '@material-ui/core/ExpansionPanel';
-import ExpansionPanelSummary from '@material-ui/core/ExpansionPanelSummary';
-import ExpansionPanelDetails from '@material-ui/core/ExpansionPanelDetails';
+import Button from "@material-ui/core/Button";
+import Typography from "@material-ui/core/Typography";
+import * as Blockly from "blockly";
+import ReactMarkdown from "react-markdown";
+import Container from "@material-ui/core/Container";
+import ExpansionPanel from "@material-ui/core/ExpansionPanel";
+import ExpansionPanelSummary from "@material-ui/core/ExpansionPanelSummary";
+import ExpansionPanelDetails from "@material-ui/core/ExpansionPanelDetails";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faChevronDown } from "@fortawesome/free-solid-svg-icons";
-import { FaqQuestions } from '../data/faq'
-
+import { FaqQuestions } from "../data/faq";
class Faq extends Component {
+ state = {
+ panel: "",
+ expanded: false,
+ };
- state = {
- panel: '',
- expanded: false
- }
+ handleChange = (panel) => {
+ this.setState({ panel: this.state.panel === panel ? "" : panel });
+ };
+ componentDidMount() {
+ // Ensure that Blockly.setLocale is adopted in the component.
+ // Otherwise, the text will not be displayed until the next update of the component.
- handleChange = (panel) => {
- this.setState({ panel: this.state.panel === panel ? '' : panel });
- };
+ window.scrollTo(0, 0);
+ this.forceUpdate();
+ }
- componentDidMount() {
- // Ensure that Blockly.setLocale is adopted in the component.
- // Otherwise, the text will not be displayed until the next update of the component.
-
- window.scrollTo(0, 0)
- this.forceUpdate();
- }
-
- render() {
- const { panel } = this.state;
- return (
-
-
-
-
-
FAQ
- {FaqQuestions().map((object, i) => {
- return (
- this.handleChange(`panel${i}`)}>
-
- }
- >
- {object.question}
-
-
-
-
-
-
-
-
- )
- })}
- {
- this.props.button ?
-
- :
-
- }
-
-
-
- );
- };
+ render() {
+ const { panel } = this.state;
+ return (
+
+
+
+
+
FAQ
+ {FaqQuestions().map((object, i) => {
+ return (
+ this.handleChange(`panel${i}`)}
+ >
+ }
+ >
+ {object.question}
+
+
+
+
+
+
+
+ );
+ })}
+ {this.props.button ? (
+
+ ) : (
+
+ )}
+
+
+
+ );
+ }
}
export default withRouter(Faq);
- /*
- this.handleChange('panel1')}>
-
-}
->
-{Blockly.Msg.faq_q1_question}
-
-
-
-
-
-
-
-
- this.handleChange('panel2')}>
-
-}
->
-Frage 2
-
-
-
-Donec placerat, lectus sed mattis semper, neque lectus feugiat lectus, varius pulvinar
-diam eros in elit. Pellentesque convallis laoreet laoreet.
-
-
-
- this.handleChange('panel3')}>
-
-}
->
-Frage 3
-
-
-
-Nunc vitae orci ultricies, auctor nunc in, volutpat nisl. Integer sit amet egestas eros,
-vitae egestas augue. Duis vel est augue.
-
-
-
- this.handleChange('panel4')}>
-
-}
->
-Frage 4
-
-
-
-Nunc vitae orci ultricies, auctor nunc in, volutpat nisl. Integer sit amet egestas eros,
-vitae egestas augue. Duis vel est augue.
-
-
-
-*/
-
- // {{
- // this.props.button ?
- //
- // :
- //
- // }}
-
-
diff --git a/src/components/Route/PrivateRoute.js b/src/components/Route/PrivateRoute.js
index 0d41355..92fe708 100644
--- a/src/components/Route/PrivateRoute.js
+++ b/src/components/Route/PrivateRoute.js
@@ -1,44 +1,41 @@
-import React, { Component } from 'react';
-import PropTypes from 'prop-types';
-import { connect } from 'react-redux';
-
-import { Route, Redirect, withRouter } from 'react-router-dom';
+import React, { Component } from "react";
+import PropTypes from "prop-types";
+import { connect } from "react-redux";
+import { Route, Redirect, withRouter } from "react-router-dom";
class PrivateRoute extends Component {
-
render() {
- return (
- !this.props.progress ?
+ return !this.props.progress ? (
- this.props.isAuthenticated ? (
- this.props.children
- ) : (()=>{
- return (
-
- )
- })()
+ this.props.isAuthenticated
+ ? this.props.children
+ : (() => {
+ return (
+
+ );
+ })()
}
- /> : null
- );
+ />
+ ) : null;
}
}
PrivateRoute.propTypes = {
- isAuthenticated: PropTypes.bool.isRequired,
- progress: PropTypes.bool.isRequired
+ isAuthenticated: PropTypes.bool,
+ progress: PropTypes.bool.isRequired,
};
-const mapStateToProps = state => ({
+const mapStateToProps = (state) => ({
isAuthenticated: state.auth.isAuthenticated,
- progress: state.auth.progress
+ progress: state.auth.progress,
});
export default connect(mapStateToProps, null)(withRouter(PrivateRoute));
diff --git a/src/components/Tutorial/Assessment.js b/src/components/Tutorial/Assessment.js
index d69821f..73d3f63 100644
--- a/src/components/Tutorial/Assessment.js
+++ b/src/components/Tutorial/Assessment.js
@@ -74,7 +74,7 @@ class Assessment extends Component {
(task) => task._id === currentTask._id
);
var statusTask = status.tasks[taskIndex];
-
+ console.log(statusTask);
return (
diff --git a/src/components/Tutorial/Builder/Builder.js b/src/components/Tutorial/Builder/Builder.js
index 4bbad7f..c512aa2 100644
--- a/src/components/Tutorial/Builder/Builder.js
+++ b/src/components/Tutorial/Builder/Builder.js
@@ -41,8 +41,6 @@ import FormControl from "@material-ui/core/FormControl";
import Select from "@material-ui/core/Select";
import * as Blockly from "blockly";
-import MarkdownEditor from "./MarkdownEditor";
-
const styles = (theme) => ({
backdrop: {
zIndex: theme.zIndex.drawer + 1,
@@ -285,21 +283,6 @@ class Builder extends Component {
// optional
newTutorial.append(`steps[${i}][xml]`, step.xml);
}
- if (step.media) {
- // optional
- if (step.media.youtube) {
- newTutorial.append(
- `steps[${i}][media][youtube]`,
- step.media.youtube
- );
- }
- if (step.media.picture) {
- newTutorial.append(
- `steps[${i}][media][picture]`,
- step.media.picture
- );
- }
- }
});
return newTutorial;
}
diff --git a/src/components/Tutorial/Builder/Hardware.js b/src/components/Tutorial/Builder/Hardware.js
index e4b63c6..817e5fe 100644
--- a/src/components/Tutorial/Builder/Hardware.js
+++ b/src/components/Tutorial/Builder/Hardware.js
@@ -1,107 +1,159 @@
-import React, { Component } from 'react';
-import PropTypes from 'prop-types';
-import { connect } from 'react-redux';
-import { changeContent, setError, deleteError } from '../../../actions/tutorialBuilderActions';
+import React, { Component } from "react";
+import PropTypes from "prop-types";
+import { connect } from "react-redux";
+import {
+ changeContent,
+ setError,
+ deleteError,
+} from "../../../actions/tutorialBuilderActions";
-import hardware from '../../../data/hardware.json';
+import hardware from "../../../data/hardware.json";
-import { withStyles } from '@material-ui/core/styles';
-import withWidth, { isWidthDown } from '@material-ui/core/withWidth';
-import GridList from '@material-ui/core/GridList';
-import GridListTile from '@material-ui/core/GridListTile';
-import GridListTileBar from '@material-ui/core/GridListTileBar';
-import FormHelperText from '@material-ui/core/FormHelperText';
-import FormLabel from '@material-ui/core/FormLabel';
-import * as Blockly from 'blockly'
+import { withStyles } from "@material-ui/core/styles";
+import withWidth, { isWidthDown } from "@material-ui/core/withWidth";
+import ImageList from "@material-ui/core/ImageList";
+import ImageListTile from "@material-ui/core/ImageListItem";
+import ImageListTileBar from "@material-ui/core/ImageListItemBar";
+import FormHelperText from "@material-ui/core/FormHelperText";
+import FormLabel from "@material-ui/core/FormLabel";
+import * as Blockly from "blockly";
-
-const styles = theme => ({
- multiGridListTile: {
+const styles = (theme) => ({
+ multiImageListTile: {
background: theme.palette.primary.main,
opacity: 0.9,
- height: '30px'
+ height: "30px",
},
- multiGridListTileTitle: {
- color: theme.palette.text.primary
+ multiImageListTileTitle: {
+ color: theme.palette.text.primary,
},
border: {
- cursor: 'pointer',
- '&:hover': {
- width: 'calc(100% - 4px)',
- height: 'calc(100% - 4px)',
- border: `2px solid ${theme.palette.primary.main}`
- }
+ cursor: "pointer",
+ "&:hover": {
+ width: "calc(100% - 4px)",
+ height: "calc(100% - 4px)",
+ border: `2px solid ${theme.palette.primary.main}`,
+ },
},
active: {
- cursor: 'pointer',
- width: 'calc(100% - 4px)',
- height: 'calc(100% - 4px)',
- border: `2px solid ${theme.palette.primary.main}`
+ cursor: "pointer",
+ width: "calc(100% - 4px)",
+ height: "calc(100% - 4px)",
+ border: `2px solid ${theme.palette.primary.main}`,
},
errorColor: {
color: theme.palette.error.dark,
- lineHeight: 'initial',
- marginBottom: '10px'
- }
+ lineHeight: "initial",
+ marginBottom: "10px",
+ },
});
class Requirements extends Component {
-
onChange = (hardware) => {
var hardwareArray = this.props.value;
- if (hardwareArray.filter(value => value === hardware).length > 0) {
- hardwareArray = hardwareArray.filter(value => value !== hardware);
- }
- else {
+ if (hardwareArray.filter((value) => value === hardware).length > 0) {
+ hardwareArray = hardwareArray.filter((value) => value !== hardware);
+ } else {
hardwareArray.push(hardware);
if (this.props.error) {
- this.props.deleteError(this.props.index, 'hardware');
+ this.props.deleteError(this.props.index, "hardware");
}
}
- this.props.changeContent(hardwareArray, this.props.index, 'hardware');
+ this.props.changeContent(hardwareArray, this.props.index, "hardware");
if (hardwareArray.length === 0) {
- this.props.setError(this.props.index, 'hardware');
+ this.props.setError(this.props.index, "hardware");
}
- }
+ };
render() {
- var cols = isWidthDown('md', this.props.width) ? isWidthDown('sm', this.props.width) ? isWidthDown('xs', this.props.width) ? 2 : 3 : 4 : 6;
+ var cols = isWidthDown("md", this.props.width)
+ ? isWidthDown("sm", this.props.width)
+ ? isWidthDown("xs", this.props.width)
+ ? 2
+ : 3
+ : 4
+ : 6;
return (
-
-
Hardware
-
{Blockly.Msg.builder_hardware_order}
- {this.props.error ?
{Blockly.Msg.builder_hardware_helper} : null}
-
+
+
Hardware
+
+ {Blockly.Msg.builder_hardware_order}
+
+ {this.props.error ? (
+
+ {Blockly.Msg.builder_hardware_helper}
+
+ ) : null}
+
{hardware.map((picture, i) => (
- this.onChange(picture.id)} classes={{ tile: this.props.value.filter(value => value === picture.id).length > 0 ? this.props.classes.active : this.props.classes.border }}>
-
-

+
this.onChange(picture.id)}
+ classes={{
+ item:
+ this.props.value.filter((value) => value === picture.id)
+ .length > 0
+ ? this.props.classes.active
+ : this.props.classes.border,
+ }}
+ >
+
+
-
+
{picture.name}
}
/>
-
+
))}
-
+
);
- };
+ }
}
Requirements.propTypes = {
changeContent: PropTypes.func.isRequired,
setError: PropTypes.func.isRequired,
deleteError: PropTypes.func.isRequired,
- change: PropTypes.number.isRequired
+ change: PropTypes.number.isRequired,
};
-const mapStateToProps = state => ({
- change: state.builder.change
+const mapStateToProps = (state) => ({
+ change: state.builder.change,
});
-export default connect(mapStateToProps, { changeContent, setError, deleteError })(withStyles(styles, { withTheme: true })(withWidth()(Requirements)));
+export default connect(mapStateToProps, {
+ changeContent,
+ setError,
+ deleteError,
+})(withStyles(styles, { withTheme: true })(withWidth()(Requirements)));
diff --git a/src/components/Tutorial/Builder/MarkdownEditor.js b/src/components/Tutorial/Builder/MarkdownEditor.js
index 86a7676..06342d7 100644
--- a/src/components/Tutorial/Builder/MarkdownEditor.js
+++ b/src/components/Tutorial/Builder/MarkdownEditor.js
@@ -1,16 +1,14 @@
-import React, { Component, useRef } from "react";
-import PropTypes from "prop-types";
+import React from "react";
import { connect } from "react-redux";
import {
- tutorialTitle,
- jsonString,
- changeContent,
- setError,
- deleteError,
+ tutorialTitle,
+ jsonString,
+ changeContent,
+ setError,
+ deleteError,
} from "../../../actions/tutorialBuilderActions";
import FormControl from "@material-ui/core/FormControl";
-import Button from "@material-ui/core/Button";
import MarkdownIt from "markdown-it";
import Editor from "react-markdown-editor-lite";
import "react-markdown-editor-lite/lib/index.css";
@@ -20,63 +18,64 @@ import axios from "axios";
const mdParser = new MarkdownIt(/* Markdown-it options */);
const MarkdownEditor = (props) => {
- const [value, setValue] = React.useState(props.value);
+ //const [value, setValue] = React.useState(props.value);
- const mdEditor = React.useRef(null);
+ const mdEditor = React.useRef(null);
- function handleChange({ html, text }) {
- setValue(text);
- var value = text;
- console.log(text);
- props.changeContent(value, props.index, props.property, props.property2);
- if (value.replace(/\s/g, "") === "") {
- props.setError(props.index, props.property);
- } else {
- props.deleteError(props.index, props.property);
- }
+ function handleChange({ html, text }) {
+ //setValue(text);
+ var value = text;
+ props.changeContent(value, props.index, props.property, props.property2);
+ if (value.replace(/\s/g, "") === "") {
+ props.setError(props.index, props.property);
+ } else {
+ props.deleteError(props.index, props.property);
}
+ }
- async function uploadImage(files) {
- return new Promise((resolve, reject) => {
- const formData = new FormData();
- formData.append("files", files);
- axios({
- method: "post",
- url: `${process.env.REACT_APP_BLOCKLY_API}/upload/uploadImage`,
- data: formData,
- headers: { "Content-Type": "multipart/form-data" },
- })
- .then((res) => {
- console.log(res);
- resolve(`${process.env.REACT_APP_BLOCKLY_API}/upload/`+res.data.filename);
- })
- .catch((err) => {
- reject(new Error("error"));
- })
+ async function uploadImage(files) {
+ return new Promise((resolve, reject) => {
+ const formData = new FormData();
+ formData.append("files", files);
+ axios({
+ method: "post",
+ url: `${process.env.REACT_APP_BLOCKLY_API}/upload/uploadImage`,
+ data: formData,
+ headers: { "Content-Type": "multipart/form-data" },
+ })
+ .then((res) => {
+ console.log(res);
+ resolve(
+ `${process.env.REACT_APP_BLOCKLY_API}/upload/` + res.data.filename
+ );
})
- }
+ .catch((err) => {
+ reject(new Error("error"));
+ });
+ });
+ }
- return (
-
- mdParser.render(text)}
- onChange={handleChange}
- value={value}
- id={props.property}
- label={props.label}
- property={props.property}
- onImageUpload={uploadImage}
- />
-
- );
+ return (
+
+ mdParser.render(text)}
+ onChange={handleChange}
+ //value={value}
+ id={props.property}
+ label={props.label}
+ property={props.property}
+ onImageUpload={uploadImage}
+ />
+
+ );
};
export default connect(null, {
- tutorialTitle,
- jsonString,
- changeContent,
- setError,
- deleteError,
-})(MarkdownEditor);
\ No newline at end of file
+ tutorialTitle,
+ jsonString,
+ changeContent,
+ setError,
+ deleteError,
+})(MarkdownEditor);
diff --git a/src/components/Tutorial/Builder/Step.js b/src/components/Tutorial/Builder/Step.js
index 6cee443..35ed9f7 100644
--- a/src/components/Tutorial/Builder/Step.js
+++ b/src/components/Tutorial/Builder/Step.js
@@ -1,23 +1,31 @@
-import React, { Component } from 'react';
-import PropTypes from 'prop-types';
-import { connect } from 'react-redux';
-import { addStep, removeStep, changeStepIndex } from '../../../actions/tutorialBuilderActions';
+import React, { Component } from "react";
+import PropTypes from "prop-types";
+import { connect } from "react-redux";
+import {
+ addStep,
+ removeStep,
+ changeStepIndex,
+} from "../../../actions/tutorialBuilderActions";
-import clsx from 'clsx';
+import clsx from "clsx";
-import Textfield from './Textfield';
-import StepType from './StepType';
-import BlocklyExample from './BlocklyExample';
-import Requirements from './Requirements';
-import Hardware from './Hardware';
-import Media from './Media';
+import Textfield from "./Textfield";
+import StepType from "./StepType";
+import BlocklyExample from "./BlocklyExample";
+import Requirements from "./Requirements";
+import Hardware from "./Hardware";
-import { withStyles } from '@material-ui/core/styles';
-import Typography from '@material-ui/core/Typography';
-import IconButton from '@material-ui/core/IconButton';
-import Tooltip from '@material-ui/core/Tooltip';
+import { withStyles } from "@material-ui/core/styles";
+import Typography from "@material-ui/core/Typography";
+import IconButton from "@material-ui/core/IconButton";
+import Tooltip from "@material-ui/core/Tooltip";
-import { faPlus, faAngleDoubleUp, faAngleDoubleDown, faTrash } from "@fortawesome/free-solid-svg-icons";
+import {
+ faPlus,
+ faAngleDoubleUp,
+ faAngleDoubleDown,
+ faTrash,
+} from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import MarkdownEditor from "./MarkdownEditor";
@@ -26,59 +34,84 @@ const styles = (theme) => ({
button: {
backgroundColor: theme.palette.primary.main,
color: theme.palette.primary.contrastText,
- width: '40px',
- height: '40px',
- '&:hover': {
+ width: "40px",
+ height: "40px",
+ "&:hover": {
backgroundColor: theme.palette.primary.main,
color: theme.palette.primary.contrastText,
- }
+ },
},
delete: {
backgroundColor: theme.palette.error.dark,
color: theme.palette.error.contrastText,
- '&:hover': {
+ "&:hover": {
backgroundColor: theme.palette.error.dark,
color: theme.palette.error.contrastText,
- }
- }
+ },
+ },
});
class Step extends Component {
-
render() {
var index = this.props.index;
var steps = this.props.steps;
return (
-
-
Schritt {index + 1}
-
-
-
+
+
+ Schritt {index + 1}
+
+
+
+
this.props.addStep(index + 1)}
>
- {index !== 0 ?
+ {index !== 0 ? (
-
+
this.props.changeStepIndex(index, index - 1)}
>
-
+
this.props.changeStepIndex(index, index + 1)}
>
@@ -87,16 +120,19 @@ class Step extends Component {
this.props.removeStep(index)}
>
- : null}
+ ) : null}
-
+
- {index === 0 ?
+ {index === 0 ? (
-
-
+
+
- : null}
- {this.props.step.type === 'instruction' ?
-
- : null}
-
+ ) : null}
+
);
- };
+ }
}
Step.propTypes = {
@@ -147,10 +200,14 @@ Step.propTypes = {
error: PropTypes.object.isRequired,
};
-const mapStateToProps = state => ({
+const mapStateToProps = (state) => ({
steps: state.builder.steps,
change: state.builder.change,
- error: state.builder.error
+ error: state.builder.error,
});
-export default connect(mapStateToProps, { addStep, removeStep, changeStepIndex })(withStyles(styles, { withTheme: true })(Step));
+export default connect(mapStateToProps, {
+ addStep,
+ removeStep,
+ changeStepIndex,
+})(withStyles(styles, { withTheme: true })(Step));
diff --git a/src/components/Tutorial/Builder/Textfield.js b/src/components/Tutorial/Builder/Textfield.js
index 2cd3bd3..80d69ee 100644
--- a/src/components/Tutorial/Builder/Textfield.js
+++ b/src/components/Tutorial/Builder/Textfield.js
@@ -31,14 +31,6 @@ const styles = (theme) => ({
});
class Textfield extends Component {
- componentDidMount() {
- if (this.props.error) {
- if (this.props.property !== "media") {
- this.props.deleteError(this.props.index, this.props.property);
- }
- }
- }
-
handleChange = (e) => {
var value = e.target.value;
if (this.props.property === "title") {
diff --git a/src/components/Tutorial/Hardware.js b/src/components/Tutorial/Hardware.js
index a8ce1f1..e581e3b 100644
--- a/src/components/Tutorial/Hardware.js
+++ b/src/components/Tutorial/Hardware.js
@@ -1,47 +1,45 @@
-import React, { Component } from 'react';
+import React, { Component } from "react";
-import Dialog from '../Dialog';
+import Dialog from "../Dialog";
-import hardware from '../../data/hardware.json';
+import hardware from "../../data/hardware.json";
-import { withStyles } from '@material-ui/core/styles';
-import withWidth, { isWidthDown } from '@material-ui/core/withWidth';
-import Link from '@material-ui/core/Link';
-import Typography from '@material-ui/core/Typography';
-import IconButton from '@material-ui/core/IconButton';
-import GridList from '@material-ui/core/GridList';
-import GridListTile from '@material-ui/core/GridListTile';
-import GridListTileBar from '@material-ui/core/GridListTileBar';
+import { withStyles } from "@material-ui/core/styles";
+import withWidth, { isWidthDown } from "@material-ui/core/withWidth";
+import Link from "@material-ui/core/Link";
+import Typography from "@material-ui/core/Typography";
+import IconButton from "@material-ui/core/IconButton";
+import ImageList from "@material-ui/core/ImageList";
+import ImageListTile from "@material-ui/core/ImageList";
+import ImageListTileBar from "@material-ui/core/ImageListItemBar";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faExpandAlt } from "@fortawesome/free-solid-svg-icons";
-import * as Blockly from 'blockly'
-const styles = theme => ({
+import * as Blockly from "blockly";
+const styles = (theme) => ({
expand: {
- '&:hover': {
+ "&:hover": {
color: theme.palette.primary.main,
},
- '&:active': {
+ "&:active": {
color: theme.palette.primary.main,
},
- color: theme.palette.text.primary
+ color: theme.palette.text.primary,
},
- multiGridListTile: {
+ multiImageListTile: {
background: theme.palette.primary.main,
opacity: 0.9,
- height: '30px'
+ height: "30px",
+ },
+ multiImageListTileTitle: {
+ color: theme.palette.text.primary,
},
- multiGridListTileTitle: {
- color: theme.palette.text.primary
- }
});
-
class Hardware extends Component {
-
state = {
open: false,
- hardwareInfo: {}
+ hardwareInfo: {},
};
handleClickOpen = (hardwareInfo) => {
@@ -53,36 +51,57 @@ class Hardware extends Component {
};
render() {
- var cols = isWidthDown('md', this.props.width) ? isWidthDown('sm', this.props.width) ? isWidthDown('xs', this.props.width) ? 2 : 3 : 4 : 6;
+ var cols = isWidthDown("md", this.props.width)
+ ? isWidthDown("sm", this.props.width)
+ ? isWidthDown("xs", this.props.width)
+ ? 2
+ : 3
+ : 4
+ : 6;
return (
-
+
{Blockly.Msg.tutorials_hardware_head}
-
+
{this.props.picture.map((picture, i) => {
- var hardwareInfo = hardware.filter(hardware => hardware.id === picture)[0];
+ var hardwareInfo = hardware.filter(
+ (hardware) => hardware.id === picture
+ )[0];
return (
-
-
-

this.handleClickOpen(hardwareInfo)} />
+
+
+

this.handleClickOpen(hardwareInfo)}
+ />
-
+
{hardwareInfo.name}
}
actionIcon={
- this.handleClickOpen(hardwareInfo)}>
+ this.handleClickOpen(hardwareInfo)}
+ >
}
/>
-
- )
+
+ );
})}
-
+
-
);
- };
+ }
}
export default withWidth()(withStyles(styles, { withTheme: true })(Hardware));
diff --git a/src/components/Workspace/WorkspaceName.js b/src/components/Workspace/WorkspaceName.js
index 98e4c0e..d53c027 100644
--- a/src/components/Workspace/WorkspaceName.js
+++ b/src/components/Workspace/WorkspaceName.js
@@ -235,7 +235,7 @@ WorkspaceName.propTypes = {
workspaceName: PropTypes.func.isRequired,
setDescription: PropTypes.func.isRequired,
updateProject: PropTypes.func.isRequired,
- name: PropTypes.string.isRequired,
+ name: PropTypes.string,
description: PropTypes.string.isRequired,
message: PropTypes.object.isRequired,
};
diff --git a/src/index.js b/src/index.js
index 34c2f28..2c20c0a 100644
--- a/src/index.js
+++ b/src/index.js
@@ -1,30 +1,26 @@
-import React from 'react';
-import ReactDOM from 'react-dom';
-import './index.css';
-import App from './App';
-import * as serviceWorker from './serviceWorker';
+import React from "react";
+import ReactDOM from "react-dom";
+import "./index.css";
+import App from "./App";
+import * as serviceWorker from "./serviceWorker";
import * as Sentry from "@sentry/react";
import { Integrations } from "@sentry/tracing";
-
Sentry.init({
dsn: "https://ffe5d54461f64c46b4bed5d77c130d6f@o507523.ingest.sentry.io/5598758",
autoSessionTracking: true,
- integrations: [
- new Integrations.BrowserTracing(),
- ],
+ integrations: [new Integrations.BrowserTracing()],
// We recommend adjusting this value in production, or using tracesSampler
// for finer control
tracesSampleRate: 1.0,
});
-
ReactDOM.render(
,
- document.getElementById('root')
+ document.getElementById("root")
);
// If you want your app to work offline and load faster, you can change