Compare commits

..
Author SHA1 Message Date
fbruc03 cb04ec6e43 remove log 2022-12-05 13:59:19 +01:00
fbruc03 42a8d3db4f remove background on focus 2022-11-25 11:53:04 +01:00
fbruc03 3959de86f4 fix translations in complie screen (tablet mode) 2022-11-17 18:12:32 +01:00
fbruc03 360169c8c9 add language and mcu settings to navbar 2022-11-17 17:42:40 +01:00
16 changed files with 187 additions and 714 deletions
+1
View File
@@ -29,6 +29,7 @@
"qrcode.react": "^3.1.0", "qrcode.react": "^3.1.0",
"react": "^17.0.2", "react": "^17.0.2",
"react-cookie-consent": "^7.2.1", "react-cookie-consent": "^7.2.1",
"react-country-flag": "^3.0.2",
"react-dom": "^17.0.2", "react-dom": "^17.0.2",
"react-markdown": "^8.0.0", "react-markdown": "^8.0.0",
"react-markdown-editor-lite": "^1.3.3", "react-markdown-editor-lite": "^1.3.3",
+1 -10
View File
@@ -301,21 +301,12 @@ export const resetTutorial = () => (dispatch, getState) => {
hardware: [], hardware: [],
requirements: [], requirements: [],
}, },
{
id: 2,
type: "finalpage",
headline: "",
text: "",
samplesolutions: false,
solutions: [],
furthertutorials: false,
},
]; ];
dispatch(tutorialSteps(steps)); dispatch(tutorialSteps(steps));
dispatch({ dispatch({
type: BUILDER_ERROR, type: BUILDER_ERROR,
payload: { payload: {
steps: [{}, {}], steps: [{}],
}, },
}); });
}; };
+4 -1
View File
@@ -99,11 +99,14 @@ export const UI = {
* Tablet Dialog * Tablet Dialog
*/ */
tabletDialog_connect: "senseBox Connect App öffnen",
tabletDialog_headline: "Tablet Modus ist aktiviert!", tabletDialog_headline: "Tablet Modus ist aktiviert!",
tabletDialog_text: tabletDialog_text:
"Der Tablet Modus wurde aktiviert. Du kannst nun Programmcodes über die senseBox Connect App auf deine senseBox kopieren. Der Tablet Modus kann in den Einstellungen deaktiviert werden", "Der Tablet Modus wurde aktiviert. Du kannst nun Programmcodes über die senseBox Connect App auf deine senseBox kopieren. Der Tablet Modus kann in den Einstellungen deaktiviert werden",
tabletDialog_more: tabletDialog_more:
"Weitere Informationen und den Link zum Download der App findest du unter: ", "Weitere Informationen und den Link zum Download der App findest du unter: ",
compiledialog_process: "Dein Code wird compiliert!",
compiledialog_instructions: "Übertrage ihn anschließend mithlfe der senseBoxConnect-App..",
/** /**
* Reset Dialog * Reset Dialog
@@ -132,7 +135,7 @@ export const UI = {
* Compile Dialog * Compile Dialog
* *
*/ */
compiledialog_success: "Dein Programm wurde erfolgreich kompiliert.",
compiledialog_headline: "Fehler", compiledialog_headline: "Fehler",
compiledialog_text: compiledialog_text:
"Beim kompilieren ist ein Fehler aufgetreten. Überprüfe deine Blöcke und versuche es erneut", "Beim kompilieren ist ein Fehler aufgetreten. Überprüfe deine Blöcke und versuche es erneut",
+2 -2
View File
@@ -13,8 +13,8 @@ export const IO = {
ARD_DIGITALREAD_TIP: "Read digital value on a pin: HIGH or LOW", ARD_DIGITALREAD_TIP: "Read digital value on a pin: HIGH or LOW",
ARD_DIGITALWRITE: "set digitial pin#", ARD_DIGITALWRITE: "set digitial pin#",
ARD_DIGITALWRITE_TIP: "Write digital value HIGH or LOW to a specific Port", ARD_DIGITALWRITE_TIP: "Write digital value HIGH or LOW to a specific Port",
ARD_FUN_RUN_LOOP: "Arduino loop forever:", ARD_FUN_RUN_LOOP: "Loop()",
ARD_FUN_RUN_SETUP: "Arduino run first:", ARD_FUN_RUN_SETUP: "Setup()",
ARD_FUN_RUN_TIP: "Defines the Arduino setup() and loop() functions.", ARD_FUN_RUN_TIP: "Defines the Arduino setup() and loop() functions.",
ARD_HIGH: "HIGH", ARD_HIGH: "HIGH",
ARD_HIGHLOW_TIP: "Set a pin state logic High or Low.", ARD_HIGHLOW_TIP: "Set a pin state logic High or Low.",
+4 -1
View File
@@ -101,6 +101,7 @@ export const UI = {
"Tablet mode has been activated. You can now copy program codes to your senseBox via the senseBox Connect app. Tablet mode can be deactivated in the settings", "Tablet mode has been activated. You can now copy program codes to your senseBox via the senseBox Connect app. Tablet mode can be deactivated in the settings",
tabletDialog_more: tabletDialog_more:
"For more information and the link to download the app, please visit: ", "For more information and the link to download the app, please visit: ",
tabletDialog_connect: "Open senseBox Connect App",
/** /**
* Reset Dialog * Reset Dialog
@@ -128,10 +129,12 @@ export const UI = {
* Compile Dialog * Compile Dialog
* *
*/ */
compiledialog_success: "Your code has been compiled successfully.",
compiledialog_headline: "Error", compiledialog_headline: "Error",
compiledialog_text: compiledialog_text:
"While compiling an error occured. Please check your blocks and try again", "While compiling an error occured. Please check your blocks and try again",
compiledialog_process: "Your code is being compiled!",
compiledialog_instructions: "After that, transfer it using the senseBoxConnect app.",
/** /**
* Buttons * Buttons
+5 -5
View File
@@ -68,7 +68,7 @@ class Compile extends Component {
}; };
} }
componentDidMount() {} componentDidMount() { }
componentDidUpdate(props) { componentDidUpdate(props) {
if (props.name !== this.props.name) { if (props.name !== this.props.name) {
@@ -232,8 +232,8 @@ class Compile extends Component {
> >
<div className="overlay"> <div className="overlay">
{/* <img src={Copy} width="400" alt="copyimage"></img> */} {/* <img src={Copy} width="400" alt="copyimage"></img> */}
<h2>Dein Code wird kompiliert!</h2> <h2>{Blockly.Msg.compiledialog_process}</h2>
<p>übertrage ihn anschließend mithlfe der senseBoxConnect-App</p> <p>{Blockly.Msg.compiledialog_instructions}</p>
<p> <p>
{Blockly.Msg.compile_overlay_help} {Blockly.Msg.compile_overlay_help}
<a href="/faq" target="_blank"> <a href="/faq" target="_blank">
@@ -291,7 +291,7 @@ class Compile extends Component {
button={Blockly.Msg.button_close} button={Blockly.Msg.button_close}
> >
<div> <div>
<p>Dein Code wurde erfolgreich kompiliert</p> <p>{Blockly.Msg.compiledialog_success}</p>
<a href={this.state.link}> <a href={this.state.link}>
<Button <Button
style={{ color: "white" }} style={{ color: "white" }}
@@ -303,7 +303,7 @@ class Compile extends Component {
icon={faClipboardCheck} icon={faClipboardCheck}
style={{ marginRight: "5px" }} style={{ marginRight: "5px" }}
/>{" "} />{" "}
Starte Übertragung {Blockly.Msg.tabletDialog_connect}
</Button> </Button>
</a> </a>
</div> </div>
+4 -2
View File
@@ -41,6 +41,7 @@ import {
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import * as Blockly from "blockly"; import * as Blockly from "blockly";
import Tooltip from "@material-ui/core/Tooltip"; import Tooltip from "@material-ui/core/Tooltip";
import NavbarSettings from "./NavbarSettings";
const styles = (theme) => ({ const styles = (theme) => ({
drawerWidth: { drawerWidth: {
@@ -127,6 +128,7 @@ class Navbar extends Component {
<Link to={"/"} style={{ marginLeft: "10px" }}> <Link to={"/"} style={{ marginLeft: "10px" }}>
<img src={senseboxLogo} alt="senseBox-Logo" width="30" /> <img src={senseboxLogo} alt="senseBox-Logo" width="30" />
</Link> </Link>
<NavbarSettings />
{isTutorial ? ( {isTutorial ? (
<Link <Link
to={"/tutorial"} to={"/tutorial"}
@@ -149,7 +151,7 @@ class Navbar extends Component {
onClick={() => { onClick={() => {
this.openTour(); this.openTour();
}} }}
style={{ margin: "0 30px 0 auto" }} style={{ margin: "0 30px 0 0" }}
> >
<FontAwesomeIcon icon={faQuestionCircle} /> <FontAwesomeIcon icon={faQuestionCircle} />
</IconButton> </IconButton>
@@ -163,7 +165,7 @@ class Navbar extends Component {
onClick={() => { onClick={() => {
this.openTour(); this.openTour();
}} }}
style={{ margin: "0 30px 0 auto" }} style={{ margin: "0 30px 0 0" }}
> >
<FontAwesomeIcon icon={faQuestionCircle} /> <FontAwesomeIcon icon={faQuestionCircle} />
</IconButton> </IconButton>
+88
View File
@@ -0,0 +1,88 @@
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { setLanguage } from '../actions/generalActions';
import MenuItem from '@material-ui/core/MenuItem';
import Select from '@material-ui/core/Select';
import { setBoard } from '../actions/boardAction';
import ReactCountryFlag from "react-country-flag";
import { MuiThemeProvider, createTheme } from '@material-ui/core/styles';
const theme = createTheme({
overrides: {
MuiSelect: {
select: {
'&:focus': {
backgroundColor: 'transparent',
},
},
},
},
});
class NavbarSettings extends Component {
componentDidMount() {
// Ensure that Blockly.setLocale is adopted in the component.
// Otherwise, the text will not be displayed until the next update of the component.
this.forceUpdate();
}
handleChange = (event) => {
this.props.setLanguage(event.target.value);
}
render() {
return (
<div style={{ margin: "0 0 0 auto", display: "flex" }}>
<div style={{ margin: "0 30px 0 auto", display: "flex" }}>
<MuiThemeProvider theme={theme}>
<Select
value={this.props.selectedBoard}
onChange={(e) => this.props.setBoard(e.target.value)}
disableUnderline={true}
style={{ backgroundColor: "transparent !important" }}
// IconComponent={() => <div />}
>
<MenuItem value="mcu">senseBox MCU</MenuItem>
<MenuItem value="mini">senseBox MCU mini</MenuItem>
</Select>
</MuiThemeProvider>
</div>
<div style={{ margin: "0 0 0 auto", display: "flex" }}>
<MuiThemeProvider theme={theme}>
<Select
value={this.props.language}
onChange={this.handleChange}
disableUnderline={true}
IconComponent={() => null}
>
<MenuItem value={'en_US'} >
<ReactCountryFlag
countryCode="US"
svg
cdnSuffix="svg"
title="US"
/>
</MenuItem>
<MenuItem value={'de_DE'}>
<ReactCountryFlag
countryCode="DE"
svg
cdnSuffix="svg"
title="DE"
/>
</MenuItem>
</Select>
</MuiThemeProvider>
</div>
</div >
);
}
}
const mapStateToProps = state => ({
language: state.general.language,
selectedBoard: state.board.board
});
export default connect(mapStateToProps, { setLanguage, setBoard })(NavbarSettings);
+1 -22
View File
@@ -259,7 +259,7 @@ class Builder extends Component {
window.scrollTo(0, 0); window.scrollTo(0, 0);
}; };
submit = () => {; submit = () => {
var isError = this.props.checkError(); var isError = this.props.checkError();
if (isError) { if (isError) {
this.setState({ this.setState({
@@ -273,8 +273,6 @@ class Builder extends Component {
} else { } else {
// export steps without attribute 'url' // export steps without attribute 'url'
var steps = this.props.steps; var steps = this.props.steps;
// console.log(steps);
var length = steps.length;
var newTutorial = new FormData(); var newTutorial = new FormData();
newTutorial.append("title", this.props.title); newTutorial.append("title", this.props.title);
newTutorial.append("difficulty", this.props.difficulty); newTutorial.append("difficulty", this.props.difficulty);
@@ -301,30 +299,11 @@ class Builder extends Component {
newTutorial.append(`steps[${i}][hardware][${j}]`, hardware); newTutorial.append(`steps[${i}][hardware][${j}]`, hardware);
}); });
} }
if (i === length-1 && step.type === "finalpage") {
newTutorial.append(`steps[${i}][samplesolutions]`, step.samplesolutions);
newTutorial.append(`steps[${i}][furthertutorials]`, step.furthertutorials);
if (step.samplesolutions === true) {
var solutionindex = 0;
steps.forEach((solutionstep) => {
if (solutionstep.type === "task"&& solutionstep.xml) {
newTutorial.append(`steps[${i}][solutions][${solutionindex}][type]`, solutionstep.type);
newTutorial.append(`steps[${i}][solutions][${solutionindex}][headline]`, solutionstep.headline);
newTutorial.append(`steps[${i}][solutions][${solutionindex}][xml]`, solutionstep.xml);
solutionindex++;
}
});
}
}
if (step.xml) { if (step.xml) {
// optional // optional
newTutorial.append(`steps[${i}][xml]`, step.xml); newTutorial.append(`steps[${i}][xml]`, step.xml);
} }
}); });
for (const pair of newTutorial.entries()) {
console.log(`${pair[0]}, ${pair[1]}`);
}
return newTutorial; return newTutorial;
} }
}; };
@@ -1,107 +0,0 @@
import React, { Component } from "react";
import PropTypes from "prop-types";
import { connect } from "react-redux";
import { changeContent } from "../../../actions/tutorialBuilderActions";
import { withStyles } from "@material-ui/core/styles";
import Switch from "@material-ui/core/Switch";
import FormGroup from '@material-ui/core/FormGroup';
import FormControlLabel from "@material-ui/core/FormControlLabel";
const styles = (theme) => ({
errorColor: {
color: theme.palette.error.dark,
},
errorBorder: {
border: `1px solid ${theme.palette.error.dark}`,
},
errorButton: {
marginTop: "5px",
height: "40px",
backgroundColor: theme.palette.error.dark,
"&:hover": {
backgroundColor: theme.palette.error.dark,
},
},
});
class FinalPageOptions extends Component {
constructor(props) {
super(props);
this.state = {
checkedSampleSolutions: props.checkedSampleSolutions,
checkedFurtherTutorials: props.checkedFurtherTutorials,
};
}
onChangeSampleSolutions = (value) => {
var oldValue = this.state.checked;
this.setState({ checked: value });
if (oldValue !== value) {
this.props.changeContent(value, this.props.index, "samplesolutions");
}
};
onChangeFurtherTutorials = (value) => {
var oldValue = this.state.checked;
this.setState({ checked: value });
if (oldValue !== value) {
this.props.changeContent(value, this.props.index, "furthertutorials");
}
}
render() {
var steps = this.props.steps;
return (
<div
style={{
marginBottom: "10px",
padding: "18.5px 14px",
borderRadius: "25px",
border: "1px solid lightgrey",
width: "calc(100% - 28px)",
}}
>
<FormGroup>
<FormControlLabel
labelPlacement="end"
label={
"Musterlösung(en) der Aufgabe(n) auf der Abschlussseite anzeigen"
}
control={
<Switch
checked={this.state.checked}
onChange={(e) => this.onChangeSampleSolutions(e.target.checked)}
color="primary"
/>
}
/>
<FormControlLabel
labelPlacement="end"
label={
"Vorschläge für weitere Tutorials auf der Abschlussseite anzeigen"
}
control={
<Switch
checked={this.state.checked}
onChange={(e) => this.onChangeFurtherTutorials(e.target.checked)}
color="primary"
/>
}
/>
</FormGroup>
</div>
);
}
}
FinalPageOptions.propTypes = {
changeContent: PropTypes.func.isRequired,
};
const mapStateToProps = (state) => ({
});
export default connect(mapStateToProps, {
changeContent,
})(withStyles(styles, { withTheme: true })(FinalPageOptions));
+2 -29
View File
@@ -29,7 +29,6 @@ import {
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import MarkdownEditor from "./MarkdownEditor"; import MarkdownEditor from "./MarkdownEditor";
import FinalPageOptions from "./FinalPageOptions";
const styles = (theme) => ({ const styles = (theme) => ({
button: { button: {
@@ -56,8 +55,6 @@ class Step extends Component {
render() { render() {
var index = this.props.index; var index = this.props.index;
var steps = this.props.steps; var steps = this.props.steps;
// console.log(this.props.steps);
// console.log(this.props.step);
return ( return (
<div <div
style={{ style={{
@@ -67,21 +64,12 @@ class Step extends Component {
marginBottom: "20px", marginBottom: "20px",
}} }}
> >
{this.props.step.type !== "finalpage" ? (
<Typography <Typography
variant="h6" variant="h6"
style={{ marginBottom: "10px", marginLeft: "4px" }} style={{ marginBottom: "10px", marginLeft: "4px" }}
> >
Schritt {index + 1} Schritt {index + 1}
</Typography> </Typography>
) : (
<Typography
variant="h6"
style={{ marginBottom: "10px", marginLeft: "4px" }}
>
Abschlussseite
</Typography>
)}
<div style={{ display: "flex", position: "relative" }}> <div style={{ display: "flex", position: "relative" }}>
<div <div
style={{ style={{
@@ -92,8 +80,6 @@ class Step extends Component {
bottom: "10px", bottom: "10px",
}} }}
> >
{this.props.step.type !== "finalpage" ? (
<div>
<Tooltip title="Schritt hinzufügen" arrow> <Tooltip title="Schritt hinzufügen" arrow>
<IconButton <IconButton
className={this.props.classes.button} className={this.props.classes.button}
@@ -123,7 +109,7 @@ class Step extends Component {
arrow arrow
> >
<IconButton <IconButton
disabled={index >= this.props.steps.length - 2} disabled={index === steps.length - 1}
className={this.props.classes.button} className={this.props.classes.button}
style={{ marginBottom: "5px" }} style={{ marginBottom: "5px" }}
onClick={() => this.props.changeStepIndex(index, index + 1)} onClick={() => this.props.changeStepIndex(index, index + 1)}
@@ -133,7 +119,7 @@ class Step extends Component {
</Tooltip> </Tooltip>
<Tooltip title={`Schritt ${index + 1} löschen`} arrow> <Tooltip title={`Schritt ${index + 1} löschen`} arrow>
<IconButton <IconButton
disabled={index === 0 && index === steps.length - 1} disabled={index === 0}
className={clsx( className={clsx(
this.props.classes.button, this.props.classes.button,
this.props.classes.delete this.props.classes.delete
@@ -146,12 +132,8 @@ class Step extends Component {
</div> </div>
) : null} ) : null}
</div> </div>
) : null}
</div>
<div style={{ width: "100%", marginLeft: "54px" }}> <div style={{ width: "100%", marginLeft: "54px" }}>
{this.props.step.type !== "finalpage" ? (
<StepType value={this.props.step.type} index={index} /> <StepType value={this.props.step.type} index={index} />
) : null}
<Textfield <Textfield
value={this.props.step.headline} value={this.props.step.headline}
property={"headline"} property={"headline"}
@@ -196,21 +178,12 @@ class Step extends Component {
/> />
</div> </div>
) : null} ) : null}
{this.props.step.type !== "finalpage" ? (
<BlocklyExample <BlocklyExample
value={this.props.step.xml} value={this.props.step.xml}
index={index} index={index}
task={this.props.step.type === "task"} task={this.props.step.type === "task"}
error={this.props.error.steps[index].xml ? true : false} error={this.props.error.steps[index].xml ? true : false}
/> />
) : (
<FinalPageOptions
steps={steps}
checkedSampleSolutions={this.props.step.samplesolutions}
checkedFurtherTutorials={this.props.step.furthertutorials}
index={index}
/>
)}
</div> </div>
</div> </div>
</div> </div>
-430
View File
@@ -1,430 +0,0 @@
import React, { Component } from "react";
import { connect } from "react-redux";
import axios from "axios";
import BlocklyWindow from "../Blockly/BlocklyWindow";
import clsx from "clsx";
import { alpha } from "@material-ui/core/styles";
import { withStyles } from "@material-ui/core/styles";
import {
faCheck,
faTimes,
} from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { Link } from "react-router-dom";
import ReactStars from "react-rating-stars-component";
import Grid from "@material-ui/core/Grid";
import Typography from "@material-ui/core/Typography";
import Paper from "@material-ui/core/Paper";
import ReactMarkdown from "react-markdown";
import remarkGfm from "remark-gfm";
import remarkGemoji from "remark-gemoji";
import Dialog from "../Dialog";
import { IconButton } from "@material-ui/core";
import { clearMessages } from "../../actions/messageActions";
import * as Blockly from "blockly/core";
// import { getTutorials,
// tutorialProgress,
// resetTutorial
// } from "../../actions/tutorialActions";
const styles = (theme) => ({
outerDiv: {
position: "absolute",
right: "-30px",
bottom: "-30px",
width: "160px",
height: "160px",
color: alpha(theme.palette.secondary.main, 0.6),
},
outerDivError: {
stroke: alpha(theme.palette.error.dark, 0.6),
color: alpha(theme.palette.error.dark, 0.6),
},
outerDivSuccess: {
stroke: alpha(theme.palette.primary.main, 0.6),
color: alpha(theme.palette.primary.main, 0.6),
},
outerDivOther: {
stroke: alpha(theme.palette.secondary.main, 0.6),
},
innerDiv: {
width: "inherit",
height: "inherit",
display: "table-cell",
verticalAlign: "middle",
textAlign: "center",
},
// button: {
// backgroundColor: theme.palette.primary.main,
// color: theme.palette.primary.contrastText,
// width: "40px",
// height: "40px",
// "&:hover": {
// backgroundColor: theme.palette.primary.main,
// color: theme.palette.primary.contrastText,
// },
// },
// link: {
// color: theme.palette.primary.main,
// textDecoration: "none",
// "&:hover": {
// color: theme.palette.primary.main,
// textDecoration: "underline",
// },
// },
});
class FinalPage extends Component {
constructor(props) {
super(props);
this.state = {
open: false,
title: "",
content: "",
tutorials: [],
randomtutorials: [],
activeXML: "",
};
}
componentWillMount() {
if (this.props.step.furthertutorials === true) {
axios
.get(`${process.env.REACT_APP_BLOCKLY_API}/tutorial`)
.then((res) => {
this.setState({ tutorials: res.data.tutorials });
this.setState({ randomtutorials: this.getRandomTutorials(this.state.tutorials, 3) });
})
}
}
toggleDialog = (solution) => {
console.log(solution)
if (this.state.open === true) {
this.setState({ open: !this.state.open, title: "", activeXML: "" });
} else if (this.state.open === false) {
this.setState({ open: !this.state.open, title: "Task - " + solution.headline, activeXML: solution.xml });
}
};
getRandomTutorials = (tutorials, n) => {
var length = tutorials.length;
var taken = new Array(length);
var result = new Array(n);
if (n > length)
throw new RangeError("getRandom: more elements taken than available");
while (n--) {
var x = Math.floor(Math.random() * length);
result[n] = tutorials[x in taken ? taken[x] : x];
taken[x] = --length in taken ? taken[length] : length;
}
return result;
}
// toggleDialog = (solution) => {
// this.setState({ open: !this.state.open });
// // if (solution) {
// // this.setState({ open: !this.state.open, activeSolution: solution });
// // } else {
// // this.setState({ open: !this.state.open, activeSolution: null });
// // }
// };
render() {
var step = this.props.step;
var tutorials = this.state.tutorials;
var randomtutorials = this.state.randomtutorials;
// var randomtutorials = this.getRandomTutorials(tutorials, 3);
// console.log(randomtutorials)
return (
<div>
<Typography>
<ReactMarkdown
className={"tutorial"}
linkTarget={"_blank"}
skipHtml={false}
allowDangerousHtml={true}
remarkPlugins={[remarkGfm, remarkGemoji]}
>
{step.text}
</ReactMarkdown>
</Typography>
{step.media ? (
step.media.picture ? (
<div
style={{
display: "flex",
justifyContent: "center",
marginBottom: "5px",
}}
>
<img
src={`${process.env.REACT_APP_BLOCKLY_API}/media/${step.media.picture.path}`}
alt=""
style={{ maxHeight: "40vH", maxWidth: "100%" }}
/>
</div>
) : step.media.youtube ? (
/*16:9; width: 800px; height: width/16*9=450px*/
<div style={{ maxWidth: "800px", margin: "auto" }}>
<div
style={{
position: "relative",
height: 0,
paddingBottom: "calc(100% / 16 * 9)",
}}
>
<iframe
title={step.media.youtube}
style={{
position: "absolute",
top: "0",
left: "0",
width: "100%",
maxWidth: "800px",
height: "100%",
maxHeight: "450px",
}}
src={`https://www.youtube.com/embed/${step.media.youtube}`}
frameBorder="0"
allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture"
allowFullScreen
/>
</div>
</div>
) : null
) : null}
{step.samplesolutions === true ? (
<div>
<h2 style={{ justifyContent: "center" }}>Musterlösungen</h2>
<Grid
container
spacing={2}
style={{ marginBottom: "5px", justifyContent: "space-evenly" }}
>
{step.solutions.map((solution) => {
return (
<Grid
item
xs={12}
sm={6}
md={4}
xl={3}
style={{ display: "flex", justifyContent: "center" }}
// onclick={this.toggleDialog(solution)}
>
<IconButton
onClick={() => this.toggleDialog(solution)}
>
<Paper
style={{
padding: "10px",
position: "relative",
overflow: "hidden",
}}
>
<h3>{"Task - " + solution.headline}</h3>
<BlocklyWindow
svg
blockDisabled
initialXml={solution.xml}
/>
</Paper>
</IconButton>
</Grid>
);
})}
</Grid>
<Dialog
open={this.state.open}
onClose={this.toggleDialog}
onClick={this.toggleDialog}
title={this.state.title}
button={Blockly.Msg.button_close}
>
<BlocklyWindow
svg
blockDisabled
initialXml={this.state.activeXML}
/>
</Dialog>
</div>
) : null}
{step.furthertutorials === true ? (
<div>
<h2 style={{ justifyContent: "center" }}>Weitere Tutorials</h2>
<Grid
container
spacing={2}
style={{ justifyContent: "space-evenly" }}
>
{randomtutorials.map((tutorial, i) => {
var status = this.props.status.filter(
(status) => status._id === tutorial._id
)[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";
const firstExample = {
size: 30,
value: tutorial.difficulty,
edit: false,
isHalf: true,
};
return (
<Grid item xs={12} sm={6} md={4} xl={3} key={i} style={{}}>
<Link
to={`/tutorial/${tutorial._id}`}
style={{ textDecoration: "none", color: "inherit" }}
>
<Paper
style={{
height: "150px",
padding: "10px",
position: "relative",
overflow: "hidden",
}}
>
{tutorial.title}
<ReactStars {...firstExample} />
<div
className={clsx(this.props.classes.outerDiv)}
style={{ width: "160px", height: "160px", border: 0 }}
>
<svg style={{ width: "100%", height: "100%" }}>
{error || success === 1 ? (
<circle
className={
error
? this.props.classes.outerDivError
: this.props.classes.outerDivSuccess
}
style={{
transform: "rotate(-44deg)",
transformOrigin: "50% 50%",
}}
r="75"
cx="50%"
cy="50%"
fill="none"
stroke-width="10"
></circle>
) : (
<circle
className={this.props.classes.outerDivOther}
style={{
transform: "rotate(-44deg)",
transformOrigin: "50% 50%",
}}
r="75"
cx="50%"
cy="50%"
fill="none"
stroke-width="10"
stroke-dashoffset={`${75 * 2 * Math.PI * (1 - (50 / 100 + success / 2))
}`}
stroke-dasharray={`${75 * 2 * Math.PI * (1 - (50 / 100 - success / 2))
} ${75 * 2 * Math.PI * (1 - (50 / 100 + success / 2))
}`}
></circle>
)}
{success < 1 && !error ? (
<circle
className={this.props.classes.outerDivSuccess}
style={{
transform: "rotate(-44deg)",
transformOrigin: "50% 50%",
}}
r="75"
cx="50%"
cy="50%"
fill="none"
stroke-width="10"
stroke-dashoffset={`${75 * 2 * Math.PI * (1 - (50 / 100 + success / 2))
}`}
stroke-dasharray={`${75 * 2 * Math.PI}`}
></circle>
) : null}
</svg>
</div>
<div
className={clsx(
this.props.classes.outerDiv,
tutorialStatus === "Error"
? this.props.classes.outerDivError
: tutorialStatus === "Success"
? this.props.classes.outerDivSuccess
: null
)}
>
<div className={this.props.classes.innerDiv}>
{error || success === 1 ? (
<FontAwesomeIcon
size="4x"
icon={
tutorialStatus === "Success" ? faCheck : faTimes
}
/>
) : (
<Typography
variant="h3"
className={
success > 0
? this.props.classes.outerDivSuccess
: {}
}
>
{Math.round(success * 100)}%
</Typography>
)}
</div>
</div>
</Paper>
</Link>
</Grid>
);
})}
</Grid>
</div>
) : null}
</div>
);
}
}
const mapStateToProps = (state) => ({
tutorials: state.tutorial.tutorials,
status: state.tutorial.status,
isLoading: state.tutorial.progress,
message: state.message,
progress: state.auth.progress,
user: state.auth.user,
authProgress: state.auth.progress,
});
export default connect(mapStateToProps, {
// getTutorials,
// resetTutorial,
// tutorialProgress,
clearMessages,
})(withStyles(styles, { withTheme: true })(FinalPage));
+2 -18
View File
@@ -31,9 +31,6 @@ const styles = (theme) => ({
width: "24px", width: "24px",
height: "24px", height: "24px",
}, },
stepIconSuccess: {
borderColor: theme.palette.primary.main,
},
stepIconLargeSuccess: { stepIconLargeSuccess: {
borderColor: theme.palette.primary.main, borderColor: theme.palette.primary.main,
}, },
@@ -133,25 +130,12 @@ class StepperVertical extends Component {
"stepIconLarge" + taskStatus "stepIconLarge" + taskStatus
] ]
) )
: step.type === "instruction" : i === activeStep
? i === activeStep
? clsx( ? clsx(
this.props.classes.stepIcon, this.props.classes.stepIcon,
this.props.classes.stepIconActiveOther this.props.classes.stepIconActiveOther
) )
: clsx(this.props.classes.stepIcon) : clsx(this.props.classes.stepIcon),
: step.type === "finalpage"
? i === activeStep
? clsx(
this.props.classes.stepIcon,
this.props.classes.stepIconSuccess,
this.props.classes.stepIconActiveSuccess
)
: clsx(
this.props.classes.stepIcon,
this.props.classes.stepIconSuccess
)
: null,
}} }}
></StepLabel> ></StepLabel>
</div> </div>
+1 -6
View File
@@ -17,7 +17,6 @@ import StepperHorizontal from "./StepperHorizontal";
import StepperVertical from "./StepperVertical"; import StepperVertical from "./StepperVertical";
import Instruction from "./Instruction"; import Instruction from "./Instruction";
import Assessment from "./Assessment"; import Assessment from "./Assessment";
import FinalPage from "./FinalPage";
import NotFound from "../NotFound"; import NotFound from "../NotFound";
import * as Blockly from "blockly"; import * as Blockly from "blockly";
import { detectWhitespacesAndReturnReadableResult } from "../../helpers/whitespace"; import { detectWhitespacesAndReturnReadableResult } from "../../helpers/whitespace";
@@ -75,9 +74,7 @@ class Tutorial extends Component {
(() => { (() => {
var tutorial = this.props.tutorial; var tutorial = this.props.tutorial;
var steps = this.props.tutorial.steps; var steps = this.props.tutorial.steps;
console.log(steps)
var step = steps[this.props.activeStep]; var step = steps[this.props.activeStep];
console.log(step)
var name = `${detectWhitespacesAndReturnReadableResult( var name = `${detectWhitespacesAndReturnReadableResult(
tutorial.title tutorial.title
)}_${detectWhitespacesAndReturnReadableResult(step.headline)}`; )}_${detectWhitespacesAndReturnReadableResult(step.headline)}`;
@@ -110,10 +107,8 @@ class Tutorial extends Component {
{step ? ( {step ? (
step.type === "instruction" ? ( step.type === "instruction" ? (
<Instruction step={step} /> <Instruction step={step} />
) : step.type === "task" ? (
<Assessment step={step} name={name} />
) : ( ) : (
<FinalPage step={step} /> <Assessment step={step} name={name} />
) // if step.type === 'assessment' ) // if step.type === 'assessment'
) : null} ) : null}
+5 -5
View File
@@ -68,7 +68,7 @@ class Compile extends Component {
}; };
} }
componentDidMount() {} componentDidMount() { }
componentDidUpdate(props) { componentDidUpdate(props) {
if (props.name !== this.props.name) { if (props.name !== this.props.name) {
@@ -232,8 +232,8 @@ class Compile extends Component {
> >
<div className="overlay"> <div className="overlay">
{/* <img src={Copy} width="400" alt="copyimage"></img> */} {/* <img src={Copy} width="400" alt="copyimage"></img> */}
<h2>Dein Code wird kompiliert!</h2> <h2>{Blockly.Msg.compiledialog_process}</h2>
<p>übertrage ihn anschließend mithlfe der senseBoxConnect-App</p> <p>{Blockly.Msg.compiledialog_instructions}</p>
<p> <p>
{Blockly.Msg.compile_overlay_help} {Blockly.Msg.compile_overlay_help}
<a href="/faq" target="_blank"> <a href="/faq" target="_blank">
@@ -291,7 +291,7 @@ class Compile extends Component {
button={Blockly.Msg.button_close} button={Blockly.Msg.button_close}
> >
<div> <div>
<p>Dein Code wurde erfolgreich kompiliert</p> <p>{Blockly.Msg.compiledialog_success}</p>
<a href={this.state.link}> <a href={this.state.link}>
<Button <Button
style={{ color: "white" }} style={{ color: "white" }}
@@ -303,7 +303,7 @@ class Compile extends Component {
icon={faClipboardCheck} icon={faClipboardCheck}
style={{ marginRight: "5px" }} style={{ marginRight: "5px" }}
/>{" "} />{" "}
Starte Übertragung {Blockly.Msg.tabletDialog_connect}
</Button> </Button>
</a> </a>
</div> </div>
+1 -10
View File
@@ -33,18 +33,9 @@ const initialState = {
hardware: [], hardware: [],
requirements: [], requirements: [],
}, },
{
id: 2,
type: "finalpage",
headline: "",
text: "",
samplesolutions: false,
solutions: [],
furthertutorials: false,
},
], ],
error: { error: {
steps: [{},{}], steps: [{}],
}, },
}; };