diff --git a/package.json b/package.json
index b57e05d..2799fb2 100644
--- a/package.json
+++ b/package.json
@@ -33,6 +33,7 @@
"react-markdown": "^8.0.0",
"react-markdown-editor-lite": "^1.3.2",
"react-mde": "^11.5.0",
+ "react-rating-stars-component": "^2.2.0",
"react-redux": "^7.2.4",
"react-router-dom": "^5.2.0",
"react-scripts": "^5.0.0",
diff --git a/src/App.css b/src/App.css
index 9903a22..8457170 100644
--- a/src/App.css
+++ b/src/App.css
@@ -43,6 +43,20 @@ blockquote p {
display: inline;
}
+.tutorial table,
+th,
+td {
+ border: 1px solid #ddd;
+}
+
+.tutorial th {
+ padding-top: 12px;
+ padding-bottom: 12px;
+ text-align: left;
+ background-color: #4eaf47;
+ color: white;
+}
+
.overlay {
display: flex;
flex-direction: column;
diff --git a/src/App.js b/src/App.js
index f4aad55..29289e5 100644
--- a/src/App.js
+++ b/src/App.js
@@ -1,6 +1,6 @@
import React, { Component } from "react";
-import { BrowserRouter as Router } from "react-router-dom";
+import { Router } from "react-router-dom";
import { createBrowserHistory } from "history";
import { Provider } from "react-redux";
diff --git a/src/actions/tutorialActions.js b/src/actions/tutorialActions.js
index 372697a..226bba6 100644
--- a/src/actions/tutorialActions.js
+++ b/src/actions/tutorialActions.js
@@ -84,6 +84,77 @@ export const getTutorials = () => (dispatch, getState) => {
});
};
+export const getAllTutorials = () => (dispatch, getState) => {
+ axios
+ .get(`${process.env.REACT_APP_BLOCKLY_API}/tutorial/getAllTutorials`)
+ .then((res) => {
+ var tutorials = res.data.tutorials;
+ existingTutorials(tutorials, getState().tutorial.status).then(
+ (status) => {
+ dispatch({
+ type: TUTORIAL_SUCCESS,
+ payload: status,
+ });
+ dispatch(updateStatus(status));
+ dispatch({
+ type: GET_TUTORIALS,
+ payload: tutorials,
+ });
+ dispatch({ type: TUTORIAL_PROGRESS });
+ dispatch(returnSuccess(res.data.message, res.status));
+ }
+ );
+ })
+ .catch((err) => {
+ if (err.response) {
+ dispatch(
+ returnErrors(
+ err.response.data.message,
+ err.response.status,
+ "GET_TUTORIALS_FAIL"
+ )
+ );
+ }
+ dispatch({ type: TUTORIAL_PROGRESS });
+ });
+};
+
+export const getUserTutorials = () => (dispatch, getState) => {
+ axios
+ .get(`${process.env.REACT_APP_BLOCKLY_API}/tutorial/getUserTutorials`)
+ .then((res) => {
+ var tutorials = res.data.tutorials;
+ existingTutorials(tutorials, getState().tutorial.status).then(
+ (status) => {
+ dispatch({
+ type: TUTORIAL_SUCCESS,
+ payload: status,
+ });
+ dispatch(updateStatus(status));
+ dispatch({
+ type: GET_TUTORIALS,
+ payload: tutorials,
+ });
+ dispatch({ type: TUTORIAL_PROGRESS });
+ dispatch(returnSuccess(res.data.message, res.status));
+ }
+ );
+ })
+ .catch((err) => {
+ console.log(err);
+ if (err.response) {
+ dispatch(
+ returnErrors(
+ err.response.data.message,
+ err.response.status,
+ "GET_TUTORIALS_FAIL"
+ )
+ );
+ }
+ dispatch({ type: TUTORIAL_PROGRESS });
+ });
+};
+
export const updateStatus = (status) => (dispatch, getState) => {
if (getState().auth.isAuthenticated) {
// update user account in database - sync with redux store
diff --git a/src/actions/tutorialBuilderActions.js b/src/actions/tutorialBuilderActions.js
index 72d7f3e..cb4e798 100644
--- a/src/actions/tutorialBuilderActions.js
+++ b/src/actions/tutorialBuilderActions.js
@@ -4,6 +4,9 @@ import {
BUILDER_CHANGE,
BUILDER_ERROR,
BUILDER_TITLE,
+ BUILDER_PUBLIC,
+ BUILDER_DIFFICULTY,
+ BUILDER_REVIEW,
BUILDER_ID,
BUILDER_ADD_STEP,
BUILDER_DELETE_STEP,
@@ -35,6 +38,30 @@ export const tutorialTitle = (title) => (dispatch) => {
dispatch(changeTutorialBuilder());
};
+export const tutorialPublic = (pub) => (dispatch) => {
+ dispatch({
+ type: BUILDER_PUBLIC,
+ payload: pub,
+ });
+ dispatch(changeTutorialBuilder());
+};
+
+export const tutorialDifficulty = (difficulty) => (dispatch) => {
+ dispatch({
+ type: BUILDER_DIFFICULTY,
+ payload: difficulty,
+ });
+ dispatch(changeTutorialBuilder());
+};
+
+export const tutorialReview = (review) => (dispatch) => {
+ dispatch({
+ type: BUILDER_REVIEW,
+ payload: review,
+ });
+ dispatch(changeTutorialBuilder());
+};
+
export const tutorialSteps = (steps) => (dispatch) => {
dispatch({
type: BUILDER_ADD_STEP,
@@ -320,6 +347,7 @@ export const readJSON = (json) => (dispatch, getState) => {
return object;
});
dispatch(tutorialTitle(json.title));
+ dispatch(tutorialDifficulty(json.difficulty));
dispatch(tutorialSteps(steps));
dispatch(setSubmitError());
dispatch(progress(false));
diff --git a/src/actions/types.js b/src/actions/types.js
index 6a10987..84e2580 100644
--- a/src/actions/types.js
+++ b/src/actions/types.js
@@ -21,6 +21,7 @@ export const NAME = "NAME";
export const TUTORIAL_PROGRESS = "TUTORIAL_PROGRESS";
export const GET_TUTORIAL = "GET_TUTORIAL";
export const GET_TUTORIALS = "GET_TUTORIALS";
+export const GET_USERTUTORIALS = "GET_USERTUTORIALS";
export const GET_STATUS = "GET_STATUS";
export const TUTORIAL_SUCCESS = "TUTORIAL_SUCCESS";
export const TUTORIAL_ERROR = "TUTORIAL_ERROR";
@@ -32,6 +33,9 @@ export const JSON_STRING = "JSON_STRING";
export const BUILDER_CHANGE = "BUILDER_CHANGE";
export const BUILDER_TITLE = "BUILDER_TITLE";
+export const BUILDER_DIFFICULTY = "BUILDER_DIFFICULTY";
+export const BUILDER_PUBLIC = "BUILDER_PUBLIC";
+export const BUILDER_REVIEW = "BUILDER_REVIEW";
export const BUILDER_ID = "BUILDER_ID";
export const BUILDER_ADD_STEP = "BUILDER_ADD_STEP";
export const BUILDER_DELETE_STEP = "BUILDER_DELETE_STEP";
diff --git a/src/components/Alert.js b/src/components/Alert.js
index ce10c87..01bac66 100644
--- a/src/components/Alert.js
+++ b/src/components/Alert.js
@@ -1,34 +1,29 @@
-import React, { Component } from 'react';
+import React, { Component } from "react";
-import { withStyles } from '@material-ui/core/styles';
-import { fade } from '@material-ui/core/styles/colorManipulator';
+import { withStyles } from "@material-ui/core/styles";
+import { alpha } from "@material-ui/core/styles";
-import Typography from '@material-ui/core/Typography';
+import Typography from "@material-ui/core/Typography";
const styles = (theme) => ({
alert: {
- marginBottom: '20px',
+ marginBottom: "20px",
border: `1px solid ${theme.palette.primary.main}`,
- padding: '10px 20px',
- borderRadius: '4px',
- background: fade(theme.palette.primary.main, 0.3),
- color: 'rgb(70,70,70)'
- }
+ padding: "10px 20px",
+ borderRadius: "4px",
+ background: alpha(theme.palette.primary.main, 0.3),
+ color: "rgb(70,70,70)",
+ },
});
-
export class Alert extends Component {
-
- render(){
- return(
+ render() {
+ return (
-
- {this.props.children}
-
+ {this.props.children}
);
}
}
-
export default withStyles(styles, { withTheme: true })(Alert);
diff --git a/src/components/Blockly/BlocklyWindow.js b/src/components/Blockly/BlocklyWindow.js
index 599005b..4ff8341 100644
--- a/src/components/Blockly/BlocklyWindow.js
+++ b/src/components/Blockly/BlocklyWindow.js
@@ -128,7 +128,7 @@ BlocklyWindow.propTypes = {
onChangeWorkspace: PropTypes.func.isRequired,
clearStats: PropTypes.func.isRequired,
renderer: PropTypes.string.isRequired,
- sounds: PropTypes.string.isRequired,
+ sounds: PropTypes.bool.isRequired,
language: PropTypes.string.isRequired,
};
diff --git a/src/components/Blockly/msg/de/ui.js b/src/components/Blockly/msg/de/ui.js
index 3d0ce92..bd2e96b 100644
--- a/src/components/Blockly/msg/de/ui.js
+++ b/src/components/Blockly/msg/de/ui.js
@@ -228,6 +228,12 @@ export const UI = {
builder_requirements_head: "Voraussetzungen",
builder_requirements_order:
"Beachte, dass die Reihenfolge des Anhakens maßgebend ist.",
+ builder_difficulty: "Schwierigkeitsgrad",
+ builder_public_head: "Tutorial veröffentlichen",
+ builder_public_label: "Tutorial für alle Nutzer:innen veröffentlichen",
+ builder_review_head: "Tutorial veröffentlichen",
+ builder_review_text:
+ "Du kannst dein Tutorial direkt über den Link mit anderen Personen teilen. Wenn du dein Tutorial für alle Nutzer:innen in der Überischt veröffenltichen wollen kannst du es hier aktivieren. Ein Administrator wird dein Tutorial ansehen und anschließend freischalten.",
/**
* Login
diff --git a/src/components/Blockly/msg/en/ui.js b/src/components/Blockly/msg/en/ui.js
index 3c25df5..fc49196 100644
--- a/src/components/Blockly/msg/en/ui.js
+++ b/src/components/Blockly/msg/en/ui.js
@@ -222,6 +222,12 @@ export const UI = {
builder_requirements_head: "Requirements.",
builder_requirements_order:
"Note that the order of ticking is authoritative.",
+ builder_difficulty: "Difficulty level",
+ builder_public_head: "Publish tutorial",
+ builder_public_label: "Publish tutorial for all users",
+ builder_review_head: "Publish tutorial",
+ builder_review_text:
+ "You can share your tutorial with other people directly from the link. If you want to publish your tutorial for all users in the overview you can activate it here. An administrator will view your tutorial and then activate it.",
/**
* Login
diff --git a/src/components/CodeEditor/Compile.js b/src/components/CodeEditor/Compile.js
index 2a357af..b3d477e 100644
--- a/src/components/CodeEditor/Compile.js
+++ b/src/components/CodeEditor/Compile.js
@@ -190,7 +190,7 @@ class Compile extends Component {
className={`compileBlocks ${this.props.classes.iconButton}`}
onClick={() => this.compile()}
>
-
+
) : (
diff --git a/src/components/CodeEditor/Sidebar.js b/src/components/CodeEditor/Sidebar.js
index a30bd74..072b504 100644
--- a/src/components/CodeEditor/Sidebar.js
+++ b/src/components/CodeEditor/Sidebar.js
@@ -1,20 +1,21 @@
import React from "react";
import Blockly from "blockly";
+import { useSelector } from "react-redux";
import Accordion from "@material-ui/core/Accordion";
import AccordionSummary from "@material-ui/core/AccordionSummary";
import AccordionDetails from "@material-ui/core/AccordionDetails";
import Typography from "@material-ui/core/Typography";
import { LibraryVersions } from "../../data/versions.js";
-//import { useMonaco } from "@monaco-editor/react";
-//import { Button } from "@material-ui/core";
+import { useMonaco } from "@monaco-editor/react";
+import { Button } from "@material-ui/core";
import Dialog from "../Dialog";
import SerialMonitor from "./SerialMonitor.js";
-//import axios from "axios";
+import axios from "axios";
const Sidebar = () => {
const [alert, setAlert] = React.useState(false);
//const [examples, setExamples] = React.useState([]);
-
+ const user = useSelector((state) => state.auth.user);
// useEffect(() => {
// axios
// .get("https://coelho.opensensemap.org/items/blocklysamples")
@@ -22,16 +23,23 @@ const Sidebar = () => {
// setExamples(res.data.data);
// });
// }, []);
-
- //const monaco = useMonaco();
- // const loadCode = (code) => {
- // monaco.editor.getModels()[0].setValue(code);
- // };
+ const monaco = useMonaco();
+ const loadCode = (code) => {
+ monaco.editor.getModels()[0].setValue(code);
+ };
const toggleDialog = () => {
setAlert(false);
};
+ const getOsemScript = (id) => {
+ axios
+ .get(`https://api.opensensemap.org/boxes/${id}/script/`)
+ .then((res) => {
+ loadCode(res.data);
+ });
+ };
+
return (
{"serial" in navigator ? (
@@ -50,7 +58,6 @@ const Sidebar = () => {
) : null}
-
{/*
{
style={{ padding: "1rem", margin: "1rem" }}
variant="contained"
color="primary"
+ key={i}
onClick={() => loadCode(object.code)}
>
{object.name}
@@ -76,6 +84,34 @@ const Sidebar = () => {
*/}
+ {user ? (
+
+
+
+
+ {user.boxes.map((box, i) => {
+ return (
+
+ );
+ })}
+
+
+
+ ) : null}
({
diff --git a/src/components/TooltipViewer.js b/src/components/TooltipViewer.js
index 47790e1..7d69a57 100644
--- a/src/components/TooltipViewer.js
+++ b/src/components/TooltipViewer.js
@@ -1,47 +1,55 @@
-import React, { Component } from 'react';
-import PropTypes from 'prop-types';
-import { connect } from 'react-redux';
+import React, { Component } from "react";
+import PropTypes from "prop-types";
+import { connect } from "react-redux";
-import withWidth from '@material-ui/core/withWidth';
+import withWidth from "@material-ui/core/withWidth";
-import { Card } from '@material-ui/core';
-import * as Blockly from 'blockly'
-import CardContent from '@material-ui/core/CardContent';
+import { Card } from "@material-ui/core";
+import * as Blockly from "blockly";
+import CardContent from "@material-ui/core/CardContent";
-import Typography from '@material-ui/core/Typography';
-import ReactMarkdown from 'react-markdown';
+import Typography from "@material-ui/core/Typography";
+import ReactMarkdown from "react-markdown";
class TooltipViewer extends Component {
-
-
render() {
-
return (
-
+
{Blockly.Msg.tooltip_viewer}
-
- {this.props.tooltip}
- {this.props.helpurl !== '' ? {`${Blockly.Msg.tooltip_moreInformation} [${Blockly.Msg.labels_here}](${this.props.helpurl})`} : null}
+
+ {this.props.tooltip}
+
-
+ {this.props.helpurl !== "" ? (
+ {`${Blockly.Msg.tooltip_moreInformation} [${Blockly.Msg.labels_here}](${this.props.helpurl})`}
+ ) : null}
);
- };
+ }
}
TooltipViewer.propTypes = {
tooltip: PropTypes.string.isRequired,
- helpurl: PropTypes.string.isRequired
+ helpurl: PropTypes.string.isRequired,
};
-const mapStateToProps = state => ({
+const mapStateToProps = (state) => ({
tooltip: state.workspace.code.tooltip,
- helpurl: state.workspace.code.helpurl
+ helpurl: state.workspace.code.helpurl,
});
export default connect(mapStateToProps, null)(withWidth()(TooltipViewer));
diff --git a/src/components/Tutorial/Assessment.js b/src/components/Tutorial/Assessment.js
index 73d3f63..4272185 100644
--- a/src/components/Tutorial/Assessment.js
+++ b/src/components/Tutorial/Assessment.js
@@ -20,6 +20,8 @@ import ReactMarkdown from "react-markdown";
import { faCode } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { withStyles } from "@material-ui/core/styles";
+import remarkGfm from "remark-gfm";
+import remarkGemoji from "remark-gemoji";
const styles = (theme) => ({
codeOn: {
@@ -101,7 +103,9 @@ class Assessment extends Component {
}}
>
- {currentTask.text}
+
+ {currentTask.text}
+
{
if (step._id) {
newTutorial.append(`steps[${i}][_id]`, step._id);
@@ -284,6 +304,7 @@ class Builder extends Component {
newTutorial.append(`steps[${i}][xml]`, step.xml);
}
});
+ console.log(newTutorial);
return newTutorial;
}
};
@@ -362,6 +383,12 @@ class Builder extends Component {
(tutorial) => tutorial.creator === this.props.user.email
);
}
+
+ // } else {
+ // filteredTutorials = this.props.userTutorials.filter(
+ // (tutorial) => tutorial.creator === this.props.user.email
+ // );
+
return (
{filteredTutorials.map((tutorial) => (
-
+
+ /* ) : tutorial.public === false ? (
+
+ ) : (
+
+ )} */
))}
@@ -476,6 +520,45 @@ class Builder extends Component {
label={"Titel"}
error={this.props.error.title}
/>
+
+
+
+
+
+
+
+ {this.props.user.blocklyRole === "admin" ? (
+
+ ) : null}
+
{this.props.steps.map((step, i) => (
@@ -608,6 +691,8 @@ class Builder extends Component {
}
Builder.propTypes = {
+ getAllTutorials: PropTypes.func.isRequired,
+ getUserTutorials: PropTypes.func.isRequired,
getTutorials: PropTypes.func.isRequired,
resetTutorial: PropTypes.func.isRequired,
clearMessages: PropTypes.func.isRequired,
@@ -620,6 +705,9 @@ Builder.propTypes = {
resetTutorialBuilder: PropTypes.func.isRequired,
tutorialProgress: PropTypes.func.isRequired,
title: PropTypes.string.isRequired,
+ difficulty: PropTypes.number.isRequired,
+ public: PropTypes.bool.isRequired,
+ review: PropTypes.bool.isRequired,
id: PropTypes.string.isRequired,
steps: PropTypes.array.isRequired,
change: PropTypes.number.isRequired,
@@ -634,12 +722,16 @@ Builder.propTypes = {
const mapStateToProps = (state) => ({
title: state.builder.title,
+ difficulty: state.builder.difficulty,
+ review: state.builder.review,
+ public: state.builder.public,
id: state.builder.id,
steps: state.builder.steps,
change: state.builder.change,
error: state.builder.error,
json: state.builder.json,
isProgress: state.builder.progress,
+ userTutorials: state.tutorial.userTutorials,
tutorials: state.tutorial.tutorials,
message: state.message,
user: state.auth.user,
@@ -654,6 +746,8 @@ export default connect(mapStateToProps, {
tutorialId,
resetTutorialBuilder,
getTutorials,
+ getUserTutorials,
+ getAllTutorials,
resetTutorial,
tutorialProgress,
clearMessages,
diff --git a/src/components/Tutorial/Builder/Difficulty.js b/src/components/Tutorial/Builder/Difficulty.js
new file mode 100644
index 0000000..18111b9
--- /dev/null
+++ b/src/components/Tutorial/Builder/Difficulty.js
@@ -0,0 +1,101 @@
+import React, { Component } from "react";
+import PropTypes from "prop-types";
+import { connect } from "react-redux";
+import {
+ tutorialDifficulty,
+ jsonString,
+ changeContent,
+ setError,
+ deleteError,
+} from "../../../actions/tutorialBuilderActions";
+
+import { withStyles } from "@material-ui/core/styles";
+import ReactStars from "react-rating-stars-component";
+import * as Blockly from "blockly";
+import FormGroup from "@material-ui/core/FormGroup";
+import FormControlLabel from "@material-ui/core/FormControlLabel";
+import FormControl from "@material-ui/core/FormControl";
+import FormLabel from "@material-ui/core/FormLabel";
+
+const styles = (theme) => ({
+ multiline: {
+ padding: "18.5px 14px 18.5px 24px",
+ },
+ errorColor: {
+ color: `${theme.palette.error.dark} !important`,
+ },
+ errorColorShrink: {
+ color: `rgba(0, 0, 0, 0.54) !important`,
+ },
+ errorBorder: {
+ borderColor: `${theme.palette.error.dark} !important`,
+ },
+});
+
+class Difficulty extends Component {
+ ratingChanged = (newRating) => {
+ console.log(newRating);
+ this.handleChange(newRating);
+ };
+
+ handleChange = (e) => {
+ var value = e;
+ console.log(value);
+ if (this.props.property === "difficulty") {
+ this.props.tutorialDifficulty(value);
+ } else if (this.props.property === "json") {
+ this.props.jsonString(value);
+ } else {
+ this.props.changeContent(
+ value,
+ this.props.index,
+ this.props.property,
+ this.props.property2
+ );
+ }
+ };
+
+ render() {
+ return (
+
+
+ {Blockly.Msg.builder_difficulty}
+
+
+ }
+ halfIcon={}
+ fullIcon={}
+ activeColor="#ffd700"
+ />
+ }
+ label="Schwierigkeitsgrad"
+ labelPlacement="start"
+ />
+
+
+ );
+ }
+}
+
+Difficulty.propTypes = {
+ tutorialDifficulty: PropTypes.func.isRequired,
+ jsonString: PropTypes.func.isRequired,
+ changeContent: PropTypes.func.isRequired,
+};
+
+export default connect(null, {
+ tutorialDifficulty,
+ jsonString,
+ changeContent,
+ setError,
+ deleteError,
+})(withStyles(styles, { withTheme: true })(Difficulty));
diff --git a/src/components/Tutorial/Builder/Public.js b/src/components/Tutorial/Builder/Public.js
new file mode 100644
index 0000000..6ad001b
--- /dev/null
+++ b/src/components/Tutorial/Builder/Public.js
@@ -0,0 +1,93 @@
+import React, { Component } from "react";
+import PropTypes from "prop-types";
+import { connect } from "react-redux";
+import {
+ tutorialPublic,
+ jsonString,
+ changeContent,
+ setError,
+ deleteError,
+} from "../../../actions/tutorialBuilderActions";
+
+import { withStyles } from "@material-ui/core/styles";
+
+import * as Blockly from "blockly";
+import Checkbox from "@material-ui/core/Checkbox";
+import FormGroup from "@material-ui/core/FormGroup";
+import FormControlLabel from "@material-ui/core/FormControlLabel";
+import FormControl from "@material-ui/core/FormControl";
+import FormLabel from "@material-ui/core/FormLabel";
+
+const styles = (theme) => ({
+ multiline: {
+ padding: "18.5px 14px 18.5px 24px",
+ },
+ errorColor: {
+ color: `${theme.palette.error.dark} !important`,
+ },
+ errorColorShrink: {
+ color: `rgba(0, 0, 0, 0.54) !important`,
+ },
+ errorBorder: {
+ borderColor: `${theme.palette.error.dark} !important`,
+ },
+});
+
+class Public extends Component {
+ handleChange = (e) => {
+ var value = e.target.checked;
+ console.log(value);
+ if (this.props.property === "public") {
+ this.props.tutorialPublic(value);
+ } else if (this.props.property === "json") {
+ this.props.jsonString(value);
+ } else {
+ this.props.changeContent(
+ value,
+ this.props.index,
+ this.props.property,
+ this.props.property2
+ );
+ }
+ };
+
+ render() {
+ return (
+
+
+ {Blockly.Msg.builder_public_head}
+
+
+
+ }
+ label={Blockly.Msg.builder_public_label}
+ labelPlacement="start"
+ />
+
+
+ );
+ }
+}
+
+Public.propTypes = {
+ tutorialPublic: PropTypes.func.isRequired,
+ jsonString: PropTypes.func.isRequired,
+ changeContent: PropTypes.func.isRequired,
+};
+
+export default connect(null, {
+ tutorialPublic,
+ jsonString,
+ changeContent,
+ setError,
+ deleteError,
+})(withStyles(styles, { withTheme: true })(Public));
diff --git a/src/components/Tutorial/Builder/Review.js b/src/components/Tutorial/Builder/Review.js
new file mode 100644
index 0000000..add30e0
--- /dev/null
+++ b/src/components/Tutorial/Builder/Review.js
@@ -0,0 +1,93 @@
+import React, { Component } from "react";
+import PropTypes from "prop-types";
+import { connect } from "react-redux";
+import {
+ tutorialReview,
+ jsonString,
+ changeContent,
+ setError,
+ deleteError,
+} from "../../../actions/tutorialBuilderActions";
+
+import { withStyles } from "@material-ui/core/styles";
+
+import * as Blockly from "blockly";
+import Checkbox from "@material-ui/core/Checkbox";
+import FormGroup from "@material-ui/core/FormGroup";
+import FormControlLabel from "@material-ui/core/FormControlLabel";
+import FormControl from "@material-ui/core/FormControl";
+import FormLabel from "@material-ui/core/FormLabel";
+
+const styles = (theme) => ({
+ multiline: {
+ padding: "18.5px 14px 18.5px 24px",
+ },
+ errorColor: {
+ color: `${theme.palette.error.dark} !important`,
+ },
+ errorColorShrink: {
+ color: `rgba(0, 0, 0, 0.54) !important`,
+ },
+ errorBorder: {
+ borderColor: `${theme.palette.error.dark} !important`,
+ },
+});
+
+class Review extends Component {
+ handleChange = (e) => {
+ var value = e.target.checked;
+ if (this.props.property === "review") {
+ this.props.tutorialReview(value);
+ } else if (this.props.property === "json") {
+ this.props.jsonString(value);
+ } else {
+ this.props.changeContent(
+ value,
+ this.props.index,
+ this.props.property,
+ this.props.property2
+ );
+ }
+ };
+
+ render() {
+ return (
+
+
+ {Blockly.Msg.builder_review_head}
+
+ {Blockly.Msg.builder_review_text}
+
+
+ }
+ label="Ich möchte mein Tutorial öffentlich machen"
+ labelPlacement="start"
+ />
+
+
+ );
+ }
+}
+
+Review.propTypes = {
+ tutorialReview: PropTypes.func.isRequired,
+ jsonString: PropTypes.func.isRequired,
+ changeContent: PropTypes.func.isRequired,
+};
+
+export default connect(null, {
+ tutorialReview,
+ jsonString,
+ changeContent,
+ setError,
+ deleteError,
+})(withStyles(styles, { withTheme: true })(Review));
diff --git a/src/components/Tutorial/Requirement.js b/src/components/Tutorial/Requirement.js
index 87784cc..42e3165 100644
--- a/src/components/Tutorial/Requirement.js
+++ b/src/components/Tutorial/Requirement.js
@@ -1,124 +1,233 @@
-import React, { Component } from 'react';
-import PropTypes from 'prop-types';
-import { connect } from 'react-redux';
+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 { 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 clsx from "clsx";
+import { withRouter, Link } from "react-router-dom";
+import { alpha } from "@material-ui/core/styles";
+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";
-import * as Blockly from 'blockly'
+import * as Blockly from "blockly";
-const styles = theme => ({
+const styles = (theme) => ({
outerDiv: {
- width: '50px',
- height: '50px',
- position: 'absolute',
- color: fade(theme.palette.secondary.main, 0.6)
+ width: "50px",
+ height: "50px",
+ position: "absolute",
+ color: alpha(theme.palette.secondary.main, 0.6),
},
outerDivError: {
- stroke: fade(theme.palette.error.dark, 0.6),
- color: fade(theme.palette.error.dark, 0.6)
+ stroke: alpha(theme.palette.error.dark, 0.6),
+ color: alpha(theme.palette.error.dark, 0.6),
},
outerDivSuccess: {
- stroke: fade(theme.palette.primary.main, 0.6),
- color: fade(theme.palette.primary.main, 0.6)
+ stroke: alpha(theme.palette.primary.main, 0.6),
+ color: alpha(theme.palette.primary.main, 0.6),
},
outerDivOther: {
- stroke: fade(theme.palette.secondary.main, 0.6)
+ stroke: alpha(theme.palette.secondary.main, 0.6),
},
innerDiv: {
- width: 'inherit',
- height: 'inherit',
- display: 'table-cell',
- verticalAlign: 'middle',
- textAlign: 'center'
+ 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'
+ 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 '
- }
- }
+ "&:hover": {
+ background: alpha(theme.palette.secondary.main, 0.5),
+ borderRadius: "0 25px 25px 0 ",
+ },
+ },
});
-
class Requirement extends Component {
-
render() {
var requirements = this.props.requirements;
- var tutorialIds = requirements.map(requirement => requirement._id);
+ var tutorialIds = requirements.map((requirement) => requirement._id);
return (
-
+
{Blockly.Msg.tutorials_requirements}
{tutorialIds.map((tutorialId, i) => {
- var title = requirements[i].title
- var status = this.props.status.filter(status => status._id === tutorialId)[0];
+ var title = requirements[i].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';
+ 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 (
-
-
+
+
-
-