diff --git a/public/media/hardware/breadboard.png b/public/media/hardware/breadboard.png
new file mode 100644
index 0000000..e6f1458
Binary files /dev/null and b/public/media/hardware/breadboard.png differ
diff --git a/public/media/hardware/jst-adapter.png b/public/media/hardware/jst-adapter.png
new file mode 100644
index 0000000..e6f1458
Binary files /dev/null and b/public/media/hardware/jst-adapter.png differ
diff --git a/public/media/hardware/led.png b/public/media/hardware/led.png
new file mode 100644
index 0000000..e6f1458
Binary files /dev/null and b/public/media/hardware/led.png differ
diff --git a/public/media/hardware/resistor.png b/public/media/hardware/resistor.png
new file mode 100644
index 0000000..e6f1458
Binary files /dev/null and b/public/media/hardware/resistor.png differ
diff --git a/public/media/hardware/senseboxmcu.png b/public/media/hardware/senseboxmcu.png
new file mode 100644
index 0000000..e6f1458
Binary files /dev/null and b/public/media/hardware/senseboxmcu.png differ
diff --git a/src/components/Blockly/BlocklyWindow.js b/src/components/Blockly/BlocklyWindow.js
index 7b66b81..3746676 100644
--- a/src/components/Blockly/BlocklyWindow.js
+++ b/src/components/Blockly/BlocklyWindow.js
@@ -32,10 +32,12 @@ class BlocklyWindow extends Component {
componentDidUpdate(props) {
const workspace = Blockly.getMainWorkspace();
- if(props.initialXml !== this.props.initialXml){
+ var initialXML = this.props.initialXml
+ if(props.initialXml !== initialXml){
// guarantees that the current xml-code (this.props.initialXml) is rendered
workspace.clear();
- Blockly.Xml.domToWorkspace(Blockly.Xml.textToDom(this.props.initialXml), workspace);
+ if(!initialXML) initialXML = initialXml;
+ Blockly.Xml.domToWorkspace(Blockly.Xml.textToDom(initialXML), workspace) ;
}
Blockly.svgResize(workspace);
}
diff --git a/src/components/Breadcrumbs.js b/src/components/Breadcrumbs.js
index bc3874d..71a57ea 100644
--- a/src/components/Breadcrumbs.js
+++ b/src/components/Breadcrumbs.js
@@ -15,7 +15,9 @@ class MyBreadcrumbs extends Component {
{content.title}
))}
- {this.props.content.slice(-1)[0].title}
+
+ {this.props.content.slice(-1)[0].title}
+
: null
);
diff --git a/src/components/Tutorial/Assessment.js b/src/components/Tutorial/Assessment.js
index 3e2db26..0ff93e0 100644
--- a/src/components/Tutorial/Assessment.js
+++ b/src/components/Tutorial/Assessment.js
@@ -18,14 +18,14 @@ class Assessment extends Component {
var status = this.props.status.filter(status => status.id === tutorialId)[0];
var taskIndex = status.tasks.findIndex(task => task.id === currentTask.id);
var statusTask = status.tasks[taskIndex];
-
+
return (
{currentTask.headline}
-
+
diff --git a/src/components/Tutorial/Hardware.js b/src/components/Tutorial/Hardware.js
new file mode 100644
index 0000000..7bbbac4
--- /dev/null
+++ b/src/components/Tutorial/Hardware.js
@@ -0,0 +1,104 @@
+import React, { Component } from 'react';
+
+import { fade } from '@material-ui/core/styles/colorManipulator';
+import { withStyles } from '@material-ui/core/styles';
+import withWidth, { isWidthDown } from '@material-ui/core/withWidth';
+import Typography from '@material-ui/core/Typography';
+import IconButton from '@material-ui/core/IconButton';
+import Button from '@material-ui/core/Button';
+import GridList from '@material-ui/core/GridList';
+import GridListTile from '@material-ui/core/GridListTile';
+import GridListTileBar from '@material-ui/core/GridListTileBar';
+import Dialog from '@material-ui/core/Dialog';
+import DialogActions from '@material-ui/core/DialogActions';
+import DialogContent from '@material-ui/core/DialogContent';
+import DialogTitle from '@material-ui/core/DialogTitle';
+
+import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
+import { faExpandAlt } from "@fortawesome/free-solid-svg-icons";
+
+const styles = theme => ({
+ expand: {
+ '&:hover': {
+ color: theme.palette.primary.main,
+ },
+ '&:active': {
+ color: theme.palette.primary.main,
+ },
+ color: theme.palette.text.primary
+ },
+ multiGridListTile: {
+ background: fade(theme.palette.secondary.main, 0.5),
+ height: '30px'
+ },
+ multiGridListTileTitle: {
+ color: theme.palette.text.primary
+ }
+});
+
+
+class Hardware extends Component {
+
+ state = {
+ open: false,
+ title: '',
+ url: ''
+ };
+
+ handleClickOpen = (title, url) => {
+ this.setState({open: true, title, url});
+ };
+
+ handleClose = () => {
+ this.setState({open: false, title: '', url: ''});
+ };
+
+ render() {
+ var cols = isWidthDown('md', this.props.width) ? isWidthDown('sm', this.props.width) ? isWidthDown('xs', this.props.width) ? 2 : 3 : 4 : 6;
+ return (
+
+
Für die Umsetzung benötigst du folgende Hardware:
+
+
+ {this.props.picture.map((picture,i) => (
+
+
this.handleClickOpen(picture, `/media/hardware/${picture}.png`)}/>
+
+ {picture}
+
+ }
+ actionIcon={
+ this.handleClickOpen(picture, `/media/hardware/${picture}.png`)}>
+
+
+ }
+ />
+
+ ))}
+
+
+
+
+ );
+ };
+}
+
+export default withWidth()(withStyles(styles, { withTheme: true })(Hardware));
diff --git a/src/components/Tutorial/Instruction.js b/src/components/Tutorial/Instruction.js
index 2b0c8d8..ee5c82a 100644
--- a/src/components/Tutorial/Instruction.js
+++ b/src/components/Tutorial/Instruction.js
@@ -2,6 +2,8 @@ import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
+import Hardware from './Hardware';
+import Requirement from './Requirement';
import BlocklyWindow from '../Blockly/BlocklyWindow';
import Grid from '@material-ui/core/Grid';
@@ -18,9 +20,9 @@ class Instruction extends Component {
{step.headline}
{step.text1}
{isHardware ?
- Hardware: todo : null}
+ : null}
{areRequirements > 0 ?
- Voraussetzungen: todo : null}
+ : null}
{step.xml ?
diff --git a/src/components/Tutorial/Requirement.js b/src/components/Tutorial/Requirement.js
new file mode 100644
index 0000000..c0c70aa
--- /dev/null
+++ b/src/components/Tutorial/Requirement.js
@@ -0,0 +1,123 @@
+import React, { Component } from 'react';
+import PropTypes from 'prop-types';
+import { connect } from 'react-redux';
+
+import clsx from 'clsx';
+import { withRouter, Link } from 'react-router-dom';
+
+import tutorials from './tutorials.json';
+
+import { fade } from '@material-ui/core/styles/colorManipulator';
+import { withStyles } from '@material-ui/core/styles';
+import Typography from '@material-ui/core/Typography';
+import List from '@material-ui/core/List';
+import Tooltip from '@material-ui/core/Tooltip';
+
+import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
+import { faCheck, faTimes } from "@fortawesome/free-solid-svg-icons";
+
+const styles = theme => ({
+ outerDiv: {
+ width: '50px',
+ height: '50px',
+ position: 'absolute',
+ color: fade(theme.palette.secondary.main, 0.6)
+ },
+ outerDivError: {
+ stroke: fade(theme.palette.error.dark, 0.2),
+ color: fade(theme.palette.error.dark, 0.2)
+ },
+ outerDivSuccess: {
+ stroke: fade(theme.palette.primary.main, 0.2),
+ color: fade(theme.palette.primary.main, 0.2)
+ },
+ outerDivOther: {
+ stroke: fade(theme.palette.secondary.main, 0.2)
+ },
+ innerDiv: {
+ width: 'inherit',
+ height: 'inherit',
+ display: 'table-cell',
+ verticalAlign: 'middle',
+ textAlign: 'center'
+ },
+ link: {
+ color: theme.palette.text.primary,
+ position: 'relative',
+ height: '50px',
+ display: 'flex',
+ margin: '5px 0 5px 10px',
+ textDecoration: 'none'
+ },
+ hoverLink: {
+ '&:hover': {
+ background: fade(theme.palette.secondary.main, 0.5),
+ borderRadius: '0 25px 25px 0 '
+ }
+ }
+});
+
+
+class Requirement extends Component {
+
+ render() {
+ var tutorialIds = this.props.tutorialIds;
+ return (
+
+
Es bietet sich an folgende Tutorials vorab erfolgreich gelöst zu haben:
+
+ {tutorialIds.map((tutorialId, i) => {
+ var title = tutorials.filter(tutorial => tutorial.id === tutorialId)[0].title;
+ var status = this.props.status.filter(status => status.id === tutorialId)[0];
+ var tasks = status.tasks;
+ var error = status.tasks.filter(task => task.type === 'error').length > 0;
+ var success = status.tasks.filter(task => task.type === 'success').length/tasks.length
+ var tutorialStatus = success === 1 ? 'Success' : error ? 'Error' : 'Other';
+ return(
+
+
+
+
+
+
+
+
+ {error || success === 1 ?
+
+ : 0 ? this.props.classes.outerDivSuccess : {}}>{Math.round(success*100)}%
+ }
+
+
+
+
+
+ {title}
+
+
+ )}
+ )}
+
+
+ );
+ };
+}
+
+Requirement.propTypes = {
+ status: PropTypes.array.isRequired,
+ change: PropTypes.number.isRequired,
+};
+
+const mapStateToProps = state => ({
+ change: state.tutorial.change,
+ status: state.tutorial.status
+});
+
+export default connect(mapStateToProps, null)(withStyles(styles, {withTheme: true})(withRouter(Requirement)));
diff --git a/src/components/Tutorial/StepperHorizontal.js b/src/components/Tutorial/StepperHorizontal.js
index b54c1f7..46e73dc 100644
--- a/src/components/Tutorial/StepperHorizontal.js
+++ b/src/components/Tutorial/StepperHorizontal.js
@@ -10,10 +10,9 @@ import tutorials from './tutorials.json';
import { fade } from '@material-ui/core/styles/colorManipulator';
import { withStyles } from '@material-ui/core/styles';
+import Typography from '@material-ui/core/Typography';
+import Tooltip from '@material-ui/core/Tooltip';
import Button from '@material-ui/core/Button';
-import Stepper from '@material-ui/core/Stepper';
-import Step from '@material-ui/core/Step';
-import StepLabel from '@material-ui/core/StepLabel';
import { faCheck, faTimes } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
@@ -57,6 +56,7 @@ class StepperHorizontal extends Component {
var error = tasks.filter(task => task.type === 'error').length > 0;
var success = tasks.filter(task => task.type === 'success').length / tasks.length;
var tutorialStatus = success === 1 ? 'Success' : error ? 'Error' : 'Other';
+ var title = tutorials.filter(tutorial => tutorial.id === tutorialId)[0].title;
return (
{error || success > 0 ?
@@ -74,14 +74,12 @@ class StepperHorizontal extends Component {
>
{'<'}
-
-
-
: ''}>
- {tutorials.filter(tutorial => tutorial.id === tutorialId)[0].title}
-
-
-
+
+
+ {tutorialStatus !== 'Other' ?
: null}
+
{title}
+
+