@@ -112,7 +113,7 @@ class CodeViewer extends Component {
>
{unequal}
- XML Blöcke
+ {Blockly.Msg.codeviewer_xml}
diff --git a/src/components/Content.js b/src/components/Content.js
new file mode 100644
index 0000000..9260421
--- /dev/null
+++ b/src/components/Content.js
@@ -0,0 +1,54 @@
+import React, { Component } from 'react';
+import PropTypes from 'prop-types';
+import { connect } from 'react-redux';
+
+import * as Blockly from 'blockly/core';
+import { De } from './Blockly/msg/de';
+import { En } from './Blockly/msg/en';
+
+import Navbar from './Navbar';
+import Footer from './Footer';
+import Routes from './Route/Routes';
+import Cookies from './Cookies';
+
+class Content extends Component {
+
+ componentDidMount() {
+ if (this.props.language === 'de_DE') {
+ Blockly.setLocale(De);
+ } else if (this.props.language === 'en_US') {
+ Blockly.setLocale(En);
+ }
+ }
+
+ componentDidUpdate(props){
+ if(props.language !== this.props.language){
+ if (this.props.language === 'de_DE') {
+ Blockly.setLocale(De);
+ } else if (this.props.language === 'en_US') {
+ Blockly.setLocale(En);
+ }
+ }
+ }
+
+ render() {
+ return (
+
+
+
+
+
+
+ );
+ }
+}
+
+Content.propTypes = {
+ language: PropTypes.string.isRequired
+};
+
+const mapStateToProps = state => ({
+ language: state.general.language
+});
+
+export default connect(mapStateToProps, null)(Content);
diff --git a/src/components/Home.js b/src/components/Home.js
index 7c385ac..f5ec9cb 100644
--- a/src/components/Home.js
+++ b/src/components/Home.js
@@ -48,7 +48,6 @@ class Home extends Component {
state = {
codeOn: false,
- stats: window.localStorage.getItem('stats'),
snackbar: false,
type: '',
key: '',
@@ -91,7 +90,7 @@ class Home extends Component {
render() {
return (
- {this.state.stats ?
+ {this.props.statistics ?
: null
}
@@ -136,11 +135,13 @@ class Home extends Component {
Home.propTypes = {
clearStats: PropTypes.func.isRequired,
workspaceName: PropTypes.func.isRequired,
- message: PropTypes.object.isRequired
+ message: PropTypes.object.isRequired,
+ statistics: PropTypes.bool.isRequired
};
const mapStateToProps = state => ({
- message: state.message
+ message: state.message,
+ statistics: state.general.statistics
});
diff --git a/src/components/Navbar.js b/src/components/Navbar.js
index 2bc7b62..dbdd561 100644
--- a/src/components/Navbar.js
+++ b/src/components/Navbar.js
@@ -21,8 +21,10 @@ import ListItemIcon from '@material-ui/core/ListItemIcon';
import ListItemText from '@material-ui/core/ListItemText';
import LinearProgress from '@material-ui/core/LinearProgress';
-import { faBars, faChevronLeft, faLayerGroup, faSignInAlt, faSignOutAlt, faCertificate, faUserCircle, faIdCard, faEnvelope, faCog, faChalkboardTeacher, faFolderPlus, faTools, faLightbulb } from "@fortawesome/free-solid-svg-icons";
+import { faBars, faChevronLeft, faLayerGroup, faSignInAlt, faSignOutAlt, faCertificate, faUserCircle, faCog, faChalkboardTeacher, faTools, faLightbulb } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
+import * as Blockly from 'blockly'
+
const styles = (theme) => ({
drawerWidth: {
@@ -92,7 +94,7 @@ class Navbar extends Component {
- Menü
+ {Blockly.Msg.navbar_menu}
@@ -100,47 +102,47 @@ class Navbar extends Component {
- {[{ text: 'Tutorials', icon: faChalkboardTeacher, link: "/tutorial" },
- { text: 'Tutorial-Builder', icon: faTools, link: "/tutorial/builder", restriction: this.props.user && this.props.user.blocklyRole !== 'user' && this.props.isAuthenticated},
- { text: 'Galerie', icon: faLightbulb, link: "/gallery" },
- { text: 'Projekte', icon: faLayerGroup, link: "/project", restriction: this.props.isAuthenticated }].map((item, index) => {
- if(item.restriction || Object.keys(item).filter(attribute => attribute === 'restriction').length === 0){
- return(
-
-
-
-
-
-
- );
- }
+ {[{ text: Blockly.Msg.navbar_tutorials, icon: faChalkboardTeacher, link: "/tutorial" },
+ { text: Blockly.Msg.navbar_tutorialbuilder, icon: faTools, link: "/tutorial/builder", restriction: this.props.user && this.props.user.blocklyRole !== 'user' && this.props.isAuthenticated },
+ { text: Blockly.Msg.navbar_gallery, icon: faLightbulb, link: "/gallery" },
+ { text: Blockly.Msg.navbar_projects, icon: faLayerGroup, link: "/project", restriction: this.props.isAuthenticated }].map((item, index) => {
+ if (item.restriction || Object.keys(item).filter(attribute => attribute === 'restriction').length === 0) {
+ return (
+
+
+
+
+
+
+ );
}
+ }
)}
- {[{ text: 'Anmelden', icon: faSignInAlt, link: '/user/login', restriction: !this.props.isAuthenticated },
- { text: 'Konto', icon: faUserCircle, link: '/user', restriction: this.props.isAuthenticated },
- { text: 'MyBadges', icon: faCertificate, link: '/user/badge', restriction: this.props.isAuthenticated },
- { text: 'Abmelden', icon: faSignOutAlt, function: this.props.logout, restriction: this.props.isAuthenticated },
- { text: 'Einstellungen', icon: faCog, link: "/settings" }].map((item, index) => {
- if(item.restriction || Object.keys(item).filter(attribute => attribute === 'restriction').length === 0){
- return(
-
- {item.function(); this.toggleDrawer();} : this.toggleDrawer}>
-
-
-
-
- );
- }
+ {[{ text: Blockly.Msg.navbar_login, icon: faSignInAlt, link: '/user/login', restriction: !this.props.isAuthenticated },
+ { text: Blockly.Msg.navbar_account, icon: faUserCircle, link: '/user', restriction: this.props.isAuthenticated },
+ { text: Blockly.Msg.navbar_mybadges, icon: faCertificate, link: '/user/badge', restriction: this.props.isAuthenticated },
+ { text: Blockly.Msg.navbar_logout, icon: faSignOutAlt, function: this.props.logout, restriction: this.props.isAuthenticated },
+ { text: Blockly.Msg.navbar_settings, icon: faCog, link: "/settings" }].map((item, index) => {
+ if (item.restriction || Object.keys(item).filter(attribute => attribute === 'restriction').length === 0) {
+ return (
+
+ { item.function(); this.toggleDrawer(); } : this.toggleDrawer}>
+
+
+
+
+ );
}
+ }
)}
{this.props.tutorialIsLoading || this.props.projectIsLoading ?
-
- : null}
+
+ : null}
);
}
diff --git a/src/components/NotFound.js b/src/components/NotFound.js
index 85a9c6f..01b03f7 100644
--- a/src/components/NotFound.js
+++ b/src/components/NotFound.js
@@ -6,31 +6,39 @@ 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'
class NotFound 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();
+ }
+
render() {
return (
-
- Die von Ihnen angeforderte Seite kann nicht gefunden werden.
- Die gesuchte Seite wurde möglicherweise entfernt, ihr Name wurde geändert oder sie ist vorübergehend nicht verfügbar.
+
+ {Blockly.Msg.notfound_head}
+ {Blockly.Msg.notfound_text}
{this.props.button ?
- :
+ :
}
diff --git a/src/components/Project/Project.js b/src/components/Project/Project.js
index a3a2403..fa2353c 100644
--- a/src/components/Project/Project.js
+++ b/src/components/Project/Project.js
@@ -5,9 +5,7 @@ import { workspaceName } from '../../actions/workspaceActions';
import { getProject, resetProject } from '../../actions/projectActions';
import { clearMessages, returnErrors } from '../../actions/messageActions';
-import axios from 'axios';
import { withRouter } from 'react-router-dom';
-import { createNameId } from 'mnemonic-id';
import Home from '../Home';
import Breadcrumbs from '../Breadcrumbs';
@@ -24,16 +22,16 @@ class Project extends Component {
}
componentDidUpdate(props) {
- if(props.location.pathname !== this.props.location.pathname ||
- props.match.params[`${this.props.type}Id`] !== this.props.match.params[`${this.props.type}Id`]){
- if(this.props.message.msg){
+ if (props.location.pathname !== this.props.location.pathname ||
+ props.match.params[`${this.props.type}Id`] !== this.props.match.params[`${this.props.type}Id`]) {
+ if (this.props.message.msg) {
this.props.clearMessages();
}
this.getProject();
}
- if(this.props.message !== props.message){
- if(this.props.message.id === 'PROJECT_EMPTY' || this.props.message.id === 'GET_PROJECT_FAIL'){
- if(this.props.type!=='share'){
+ if (this.props.message !== props.message) {
+ if (this.props.message.id === 'PROJECT_EMPTY' || this.props.message.id === 'GET_PROJECT_FAIL') {
+ if (this.props.type !== 'share') {
this.props.returnErrors('', 404, 'GET_PROJECT_FAIL');
this.props.history.push(`/${this.props.type}`);
} else {
@@ -41,10 +39,10 @@ class Project extends Component {
this.props.returnErrors('', 404, 'GET_SHARE_FAIL');
}
}
- else if(this.props.message.id === 'GET_PROJECT_SUCCESS'){
+ else if (this.props.message.id === 'GET_PROJECT_SUCCESS') {
this.props.workspaceName(this.props.project.title);
}
- else if(this.props.message.id === 'PROJECT_DELETE_SUCCESS' || this.props.message.id === 'GALLERY_DELETE_SUCCESS'){
+ else if (this.props.message.id === 'PROJECT_DELETE_SUCCESS' || this.props.message.id === 'GALLERY_DELETE_SUCCESS') {
this.props.history.push(`/${this.props.type}`);
}
}
@@ -56,8 +54,8 @@ class Project extends Component {
}
getProject = () => {
- var id = this.props.location.pathname.replace(/\/[a-z]{1,}\//,'');
- var param = this.props.location.pathname.replace(`/${id}`,'').replace('/','');
+ var id = this.props.location.pathname.replace(/\/[a-z]{1,}\//, '');
+ var param = this.props.location.pathname.replace(`/${id}`, '').replace('/', '');
console.log('param', param);
console.log(id);
this.props.getProject(param, id);
@@ -70,13 +68,13 @@ class Project extends Component {
- : this.props.project ?
-
- {this.props.type !== 'share' ?
-
- : null}
-
- : null
+ : this.props.project ?
+
+ {this.props.type !== 'share' ?
+
+ : null}
+
+ : null
);
};
}
diff --git a/src/components/Project/ProjectHome.js b/src/components/Project/ProjectHome.js
index 07e559b..c7a8d8c 100644
--- a/src/components/Project/ProjectHome.js
+++ b/src/components/Project/ProjectHome.js
@@ -4,7 +4,6 @@ import { connect } from 'react-redux';
import { getProjects, resetProject } from '../../actions/projectActions';
import { clearMessages } from '../../actions/messageActions';
-import axios from 'axios';
import { Link, withRouter } from 'react-router-dom';
import Breadcrumbs from '../Breadcrumbs';
@@ -42,31 +41,31 @@ class ProjectHome extends Component {
}
componentDidMount() {
- var type = this.props.location.pathname.replace('/','');
+ var type = this.props.location.pathname.replace('/', '');
this.props.getProjects(type);
- if(this.props.message){
- if(this.props.message.id === 'PROJECT_DELETE_SUCCESS'){
+ if (this.props.message) {
+ if (this.props.message.id === 'PROJECT_DELETE_SUCCESS') {
this.setState({ snackbar: true, key: Date.now(), message: `Dein Projekt wurde erfolgreich gelöscht.`, type: 'success' });
}
- else if(this.props.message.id === 'GALLERY_DELETE_SUCCESS'){
+ else if (this.props.message.id === 'GALLERY_DELETE_SUCCESS') {
this.setState({ snackbar: true, key: Date.now(), message: `Dein Galerie-Projekt wurde erfolgreich gelöscht.`, type: 'success' });
}
- else if(this.props.message.id === 'GET_PROJECT_FAIL'){
- this.setState({ snackbar: true, key: Date.now(), message: `Dein angefragtes ${type === 'gallery' ? 'Galerie-':''}Projekt konnte nicht gefunden werden.`, type: 'error' });
+ else if (this.props.message.id === 'GET_PROJECT_FAIL') {
+ this.setState({ snackbar: true, key: Date.now(), message: `Dein angefragtes ${type === 'gallery' ? 'Galerie-' : ''}Projekt konnte nicht gefunden werden.`, type: 'error' });
}
}
}
componentDidUpdate(props) {
- if(props.location.pathname !== this.props.location.pathname){
- this.setState({snackbar: false});
- this.props.getProjects(this.props.location.pathname.replace('/',''));
+ if (props.location.pathname !== this.props.location.pathname) {
+ this.setState({ snackbar: false });
+ this.props.getProjects(this.props.location.pathname.replace('/', ''));
}
- if(props.message !== this.props.message){
- if(this.props.message.id === 'PROJECT_DELETE_SUCCESS'){
+ if (props.message !== this.props.message) {
+ if (this.props.message.id === 'PROJECT_DELETE_SUCCESS') {
this.setState({ snackbar: true, key: Date.now(), message: `Dein Projekt wurde erfolgreich gelöscht.`, type: 'success' });
}
- else if(this.props.message.id === 'GALLERY_DELETE_SUCCESS'){
+ else if (this.props.message.id === 'GALLERY_DELETE_SUCCESS') {
this.setState({ snackbar: true, key: Date.now(), message: `Dein Galerie-Projekt wurde erfolgreich gelöscht.`, type: 'success' });
}
}
@@ -88,7 +87,7 @@ class ProjectHome extends Component {
- :
+ :
{this.props.projects.length > 0 ?
@@ -97,37 +96,37 @@ class ProjectHome extends Component {
- {project.title}
-
+ {project.title}
+
- {project.description}
+ {project.description}
{this.props.user && this.props.user.email === project.creator ?
-
-
+
+
- : null}
+ : null}
)
})}
- :
- Es sind aktuell keine Projekte vorhanden.
- {this.props.location.pathname.replace('/','') === 'project' ?
+ :
+ Es sind aktuell keine Projekte vorhanden.
+ {this.props.location.pathname.replace('/', '') === 'project' ?
Erstelle jetzt dein eigenes Projekt oder lasse dich von Projektbeispielen in der Galerie inspirieren.
- : null}
+ : null}
}
diff --git a/src/components/Route/IsLoggedRoute.js b/src/components/Route/IsLoggedRoute.js
index f071b2b..2fb3617 100644
--- a/src/components/Route/IsLoggedRoute.js
+++ b/src/components/Route/IsLoggedRoute.js
@@ -9,6 +9,7 @@ class IsLoggedRoute extends Component {
render() {
return (
+ !this.props.progress ?
@@ -23,17 +24,19 @@ class IsLoggedRoute extends Component {
/>
)
}
- />
+ /> : null
);
}
}
IsLoggedRoute.propTypes = {
- isAuthenticated: PropTypes.bool.isRequired
+ isAuthenticated: PropTypes.bool.isRequired,
+ progress: PropTypes.bool.isRequired
};
const mapStateToProps = state => ({
isAuthenticated: state.auth.isAuthenticated,
+ progress: state.auth.progress
});
export default connect(mapStateToProps, null)(IsLoggedRoute);
diff --git a/src/components/Route/PrivateRoute.js b/src/components/Route/PrivateRoute.js
index ffd321a..0d41355 100644
--- a/src/components/Route/PrivateRoute.js
+++ b/src/components/Route/PrivateRoute.js
@@ -9,6 +9,7 @@ class PrivateRoute extends Component {
render() {
return (
+ !this.props.progress ?
@@ -25,17 +26,19 @@ class PrivateRoute extends Component {
)
})()
}
- />
+ /> : null
);
}
}
PrivateRoute.propTypes = {
- isAuthenticated: PropTypes.bool.isRequired
+ isAuthenticated: PropTypes.bool.isRequired,
+ progress: PropTypes.bool.isRequired
};
const mapStateToProps = state => ({
- isAuthenticated: state.auth.isAuthenticated
+ isAuthenticated: state.auth.isAuthenticated,
+ progress: state.auth.progress
});
export default connect(mapStateToProps, null)(withRouter(PrivateRoute));
diff --git a/src/components/Route/PrivateRouteCreator.js b/src/components/Route/PrivateRouteCreator.js
index 0efd48c..e279969 100644
--- a/src/components/Route/PrivateRouteCreator.js
+++ b/src/components/Route/PrivateRouteCreator.js
@@ -9,6 +9,7 @@ class PrivateRoute extends Component {
render() {
return (
+ !this.props.progress ?
@@ -27,19 +28,21 @@ class PrivateRoute extends Component {
)
})()
}
- />
+ /> : null
);
}
}
PrivateRoute.propTypes = {
isAuthenticated: PropTypes.bool.isRequired,
- user: PropTypes.object
+ user: PropTypes.object,
+ progress: PropTypes.bool.isRequired
};
const mapStateToProps = state => ({
isAuthenticated: state.auth.isAuthenticated,
- user: state.auth.user
+ user: state.auth.user,
+ progress: state.auth.progress
});
export default connect(mapStateToProps, null)(withRouter(PrivateRoute));
diff --git a/src/components/Route/PublicRoute.js b/src/components/Route/PublicRoute.js
new file mode 100644
index 0000000..99d4e5a
--- /dev/null
+++ b/src/components/Route/PublicRoute.js
@@ -0,0 +1,32 @@
+import React, { Component } from 'react';
+import PropTypes from 'prop-types';
+import { connect } from 'react-redux';
+
+import { Route } from 'react-router-dom';
+
+
+class PublicRoute extends Component {
+
+ render() {
+ return (
+ !this.props.progress ?
+
+ this.props.children
+ }
+ />
+ : null
+ );
+ }
+}
+
+PublicRoute.propTypes = {
+ progress: PropTypes.bool.isRequired
+};
+
+const mapStateToProps = state => ({
+ progress: state.auth.progress
+});
+
+export default connect(mapStateToProps, null)(PublicRoute);
diff --git a/src/components/Route/Routes.js b/src/components/Route/Routes.js
index 3121edf..5207d45 100644
--- a/src/components/Route/Routes.js
+++ b/src/components/Route/Routes.js
@@ -5,6 +5,7 @@ import { visitPage } from '../../actions/generalActions';
import { Route, Switch, withRouter } from 'react-router-dom';
+import PublicRoute from './PublicRoute';
import PrivateRoute from './PrivateRoute';
import PrivateRouteCreator from './PrivateRouteCreator';
import IsLoggedRoute from './IsLoggedRoute';
@@ -34,18 +35,30 @@ class Routes extends Component {
return (
-
+
+
+
{/* Tutorials */}
-
+
+
+
-
+
-
+
+
+
{/* Sharing */}
-
+
+
+
{/* Gallery-Projects */}
-
-
+
+
+
+
+
+
{/* User-Projects */}
@@ -64,12 +77,20 @@ class Routes extends Component {
{/* settings */}
-
+
+
+
{/* privacy */}
-
-
+
+
+
+
+
+
{/* Not Found */}
-
+
+
+
);
diff --git a/src/components/Settings/LanguageSelector.js b/src/components/Settings/LanguageSelector.js
index dea7465..f069b1b 100644
--- a/src/components/Settings/LanguageSelector.js
+++ b/src/components/Settings/LanguageSelector.js
@@ -1,43 +1,58 @@
-import React from 'react';
-import { makeStyles } from '@material-ui/core/styles';
+import React, { Component } from 'react';
+import PropTypes from 'prop-types';
+import { connect } from 'react-redux';
+import { setLanguage } from '../../actions/generalActions';
+
+import * as Blockly from 'blockly/core';
+
import InputLabel from '@material-ui/core/InputLabel';
import MenuItem from '@material-ui/core/MenuItem';
import FormControl from '@material-ui/core/FormControl';
import Select from '@material-ui/core/Select';
+import Typography from '@material-ui/core/Typography';
+import FormHelperText from '@material-ui/core/FormHelperText';
-const useStyles = makeStyles((theme) => ({
- formControl: {
- margin: theme.spacing(1),
- minWidth: 120,
- },
- selectEmpty: {
- marginTop: theme.spacing(2),
- },
-}));
+class LanguageSelector extends Component {
-export default function LanguageSelector() {
- const classes = useStyles();
- const [lang, setLang] = React.useState(window.localStorage.getItem('locale'));
+ 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();
+ }
- const handleChange = (event) => {
- setLang(event.target.value);
- window.localStorage.setItem('locale', event.target.value);
- };
+ handleChange = (event) => {
+ this.props.setLanguage(event.target.value);
+ }
- return (
-
-
- Sprache
-
-
-
+ render(){
+ return(
+
+ {Blockly.Msg.settings_language}
+ {Blockly.Msg.settings_language_text}
+
+ {Blockly.Msg.settings_language}
+
+
+
);
+ }
}
+
+LanguageSelector.propTypes = {
+ setLanguage: PropTypes.func.isRequired,
+ language: PropTypes.string.isRequired
+};
+
+const mapStateToProps = state => ({
+ language: state.general.language
+});
+
+export default connect(mapStateToProps, { setLanguage })(LanguageSelector);
diff --git a/src/components/Settings/RenderSelector.js b/src/components/Settings/RenderSelector.js
index 5cf7a9f..7359283 100644
--- a/src/components/Settings/RenderSelector.js
+++ b/src/components/Settings/RenderSelector.js
@@ -1,45 +1,57 @@
-import React from 'react';
-import { makeStyles } from '@material-ui/core/styles';
+import React, { Component } from 'react';
+import PropTypes from 'prop-types';
+import { connect } from 'react-redux';
+import { setRenderer } from '../../actions/generalActions';
+
+import * as Blockly from 'blockly/core'
+
import InputLabel from '@material-ui/core/InputLabel';
import MenuItem from '@material-ui/core/MenuItem';
import FormControl from '@material-ui/core/FormControl';
import Select from '@material-ui/core/Select';
+import Typography from '@material-ui/core/Typography';
+import FormHelperText from '@material-ui/core/FormHelperText';
-const useStyles = makeStyles((theme) => ({
- formControl: {
- margin: theme.spacing(1),
- minWidth: 400,
- },
- selectEmpty: {
- marginTop: theme.spacing(2),
- },
-}));
-export default function RenderSelector() {
- const classes = useStyles();
- const [renderer, setRenderer] = React.useState(window.localStorage.getItem('renderer'));
+class RenderSelector extends Component {
- const handleChange = (event) => {
- setRenderer(event.target.value);
- window.localStorage.setItem('renderer', event.target.value);
- };
+ 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();
+ }
+ render(){
return (
-
-
- Renderer
-
-
- Der Renderer bestimmt das aussehen der Blöcke
-
+
+ {Blockly.Msg.settings_renderer}
+ {Blockly.Msg.settings_renderer_text}
+
+ {Blockly.Msg.settings_renderer}
+
+
+
);
+ }
}
+
+RenderSelector.propTypes = {
+ setRenderer: PropTypes.func.isRequired,
+ language: PropTypes.string.isRequired,
+ renderer: PropTypes.string.isRequired
+};
+
+const mapStateToProps = state => ({
+ renderer: state.general.renderer,
+ language: state.general.language
+});
+
+export default connect(mapStateToProps, { setRenderer })(RenderSelector);
diff --git a/src/components/Settings/Settings.js b/src/components/Settings/Settings.js
index cbbedc9..24b3bfa 100644
--- a/src/components/Settings/Settings.js
+++ b/src/components/Settings/Settings.js
@@ -1,32 +1,65 @@
import React, { Component } from 'react';
+import PropTypes from 'prop-types';
+import { connect } from 'react-redux';
+
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/core';
+
+import Breadcrumbs from '../Breadcrumbs';
import LanguageSelector from './LanguageSelector';
import RenderSelector from './RenderSelector';
import StatsSelector from './StatsSelector';
+import Button from '@material-ui/core/Button';
+import Paper from '@material-ui/core/Paper';
class Settings extends Component {
- render() {
- return (
-
- Einstellungen
-
-
-
-
-
- );
- };
+
+ 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();
+ }
+
+ render() {
+ return (
+
+
+
+ {Blockly.Msg.settings_head}
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+ };
}
-export default withRouter(Settings);
+Settings.propTypes = {
+ language: PropTypes.string.isRequired,
+ pageVisits: PropTypes.number.isRequired
+};
+
+const mapStateToProps = state => ({
+ language: state.general.language,
+ pageVisits: state.general.pageVisits
+});
+
+export default connect(mapStateToProps, null)(withRouter(Settings));
diff --git a/src/components/Settings/StatsSelector.js b/src/components/Settings/StatsSelector.js
index 8c1322d..b0b3cfe 100644
--- a/src/components/Settings/StatsSelector.js
+++ b/src/components/Settings/StatsSelector.js
@@ -1,44 +1,56 @@
-import React from 'react';
-import { makeStyles } from '@material-ui/core/styles';
+import React, { Component } from 'react';
+import PropTypes from 'prop-types';
+import { connect } from 'react-redux';
+import { setStatistics } from '../../actions/generalActions';
+
+import * as Blockly from 'blockly/core'
+
import InputLabel from '@material-ui/core/InputLabel';
import MenuItem from '@material-ui/core/MenuItem';
import FormControl from '@material-ui/core/FormControl';
import Select from '@material-ui/core/Select';
+import Typography from '@material-ui/core/Typography';
+import FormHelperText from '@material-ui/core/FormHelperText';
-const useStyles = makeStyles((theme) => ({
- formControl: {
- margin: theme.spacing(1),
- minWidth: 400,
- },
- selectEmpty: {
- marginTop: theme.spacing(2),
- },
-}));
+class StatsSelector extends Component {
-export default function StatsSelector() {
- const classes = useStyles();
- const [stats, setStats] = React.useState(window.localStorage.getItem('stats'));
-
- const handleChange = (event) => {
- setStats(event.target.value);
- window.localStorage.setItem('stats', event.target.value);
- };
+ 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();
+ }
+ render(){
return (
-
-
- Statistiken
-
-
- Schaltet die Statistiken Oberhalb der Arbeitsfläche ein bzw. aus
-
+
+ {Blockly.Msg.settings_statistics}
+ {Blockly.Msg.settings_statistics_text}
+
+ {Blockly.Msg.settings_statistics}
+
+
+
);
+ }
}
+
+StatsSelector.propTypes = {
+ setStatistics: PropTypes.func.isRequired,
+ language: PropTypes.string.isRequired,
+ statistics: PropTypes.bool.isRequired
+};
+
+const mapStateToProps = state => ({
+ statistics: state.general.statistics,
+ language: state.general.language
+});
+
+export default connect(mapStateToProps, { setStatistics })(StatsSelector);
diff --git a/src/components/Tutorial/Assessment.js b/src/components/Tutorial/Assessment.js
index 75e180d..c869cc5 100644
--- a/src/components/Tutorial/Assessment.js
+++ b/src/components/Tutorial/Assessment.js
@@ -11,6 +11,7 @@ import withWidth, { isWidthDown } from '@material-ui/core/withWidth';
import Grid from '@material-ui/core/Grid';
import Card from '@material-ui/core/Card';
import Typography from '@material-ui/core/Typography';
+import * as Blockly from 'blockly'
class Assessment extends Component {
@@ -45,7 +46,7 @@ class Assessment extends Component {
- Arbeitsauftrag
+ {Blockly.Msg.tutorials_assessment_task}
{currentTask.text}
diff --git a/src/components/Tutorial/Badge.js b/src/components/Tutorial/Badge.js
index 97103fa..2727fa5 100644
--- a/src/components/Tutorial/Badge.js
+++ b/src/components/Tutorial/Badge.js
@@ -11,6 +11,7 @@ import { withStyles } from '@material-ui/core/styles';
import Paper from '@material-ui/core/Paper';
import Typography from '@material-ui/core/Typography';
import Avatar from '@material-ui/core/Avatar';
+import * as Blockly from 'blockly';
const styles = (theme) => ({
link: {
@@ -32,22 +33,22 @@ class Badge extends Component {
content: ''
};
- componentDidUpdate(props){
- if(this.props.message.id === 'TUTORIAL_CHECK_SUCCESS'){
- if(this.props.tutorial.badge){
+ componentDidUpdate(props) {
+ if (this.props.message.id === 'TUTORIAL_CHECK_SUCCESS') {
+ if (this.props.tutorial.badge) {
// is connected to MyBadges?
- if(this.props.isAuthenticated && this.props.user && this.props.user.badge){
- if(this.props.user.badges && !this.props.user.badges.includes(this.props.tutorial.badge)){
- if(this.isSuccess()){
+ if (this.props.isAuthenticated && this.props.user && this.props.user.badge) {
+ if (this.props.user.badges && !this.props.user.badges.includes(this.props.tutorial.badge)) {
+ if (this.isSuccess()) {
this.props.assigneBadge(this.props.tutorial.badge);
}
}
}
}
}
- if(props.message !== this.props.message){
- if(this.props.message.id === 'ASSIGNE_BADGE_SUCCESS'){
- this.setState({title: `Badge: ${this.props.message.msg.name}`, content: `Herzlichen Glückwunsch! Du hast den Badge ${this.props.message.msg.name} erhalten.`, open: true});
+ if (props.message !== this.props.message) {
+ if (this.props.message.id === 'ASSIGNE_BADGE_SUCCESS') {
+ this.setState({ title: `Badge: ${this.props.message.msg.name}`, content: `${Blockly.Msg.badges_ASSIGNE_BADGE_SUCCESS_01} ${this.props.message.msg.name} ${Blockly.Msg.badges_ASSIGNE_BADGE_SUCCESS_02}`, open: true });
}
}
}
@@ -57,7 +58,7 @@ class Badge extends Component {
var status = this.props.status.filter(status => status._id === tutorialId)[0];
var tasks = status.tasks;
var success = tasks.filter(task => task.type === 'success').length / tasks.length;
- if(success===1){
+ if (success === 1) {
return true;
}
return false;
@@ -74,21 +75,21 @@ class Badge extends Component {
open={this.state.open}
title={this.state.title}
content={this.state.content}
- onClose={() => {this.toggleDialog();}}
- onClick={() => {this.toggleDialog();}}
- button={'Schließen'}
+ onClose={() => { this.toggleDialog(); }}
+ onClick={() => { this.toggleDialog(); }}
+ button={Blockly.Msg.button_close}
>
-
+
{this.props.message.msg.image && this.props.message.msg.image.path ?
-
- : }
-
- {this.props.message.msg.name}
+
+ : }
+
+ {this.props.message.msg.name}
-
- Eine Übersicht über alle erhaltenen Badges im Kontext Blockly for senseBox findest du hier.
+
+ {Blockly.Msg.badges_explaination}{Blockly.Msg.labels_here}.
diff --git a/src/components/Tutorial/Builder/Badge.js b/src/components/Tutorial/Builder/Badge.js
new file mode 100644
index 0000000..88386a3
--- /dev/null
+++ b/src/components/Tutorial/Builder/Badge.js
@@ -0,0 +1,190 @@
+import React, { Component } from 'react';
+import PropTypes from 'prop-types';
+import { connect } from 'react-redux';
+import { tutorialBadge, deleteProperty, setError, deleteError } from '../../../actions/tutorialBuilderActions';
+
+import axios from 'axios';
+
+import { withStyles } from '@material-ui/core/styles';
+import Switch from '@material-ui/core/Switch';
+import FormControlLabel from '@material-ui/core/FormControlLabel';
+import FormHelperText from '@material-ui/core/FormHelperText';
+import List from '@material-ui/core/List';
+import ListItem from '@material-ui/core/ListItem';
+import ListItemText from '@material-ui/core/ListItemText';
+import IconButton from '@material-ui/core/IconButton';
+import OutlinedInput from '@material-ui/core/OutlinedInput';
+import InputLabel from '@material-ui/core/InputLabel';
+import FormControl from '@material-ui/core/FormControl';
+
+import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
+import { faTimes } from "@fortawesome/free-solid-svg-icons";
+
+const styles = (theme) => ({
+ errorColor: {
+ color: `${theme.palette.error.dark} !important`
+ },
+ errorColorShrink: {
+ color: `rgba(0, 0, 0, 0.54) !important`
+ },
+ errorBorder: {
+ borderColor: `${theme.palette.error.dark} !important`
+ }
+});
+
+class Badge extends Component {
+
+ constructor(props){
+ super(props);
+ this.state={
+ checked: props.badge ? true : false,
+ badgeName: '',
+ filteredBadges: [],
+ badges: []
+ };
+ }
+
+ componentDidMount(){
+ this.getBadges();
+ }
+
+ componentDidUpdate(props){
+ if(props.badge !== this.props.badge){
+ this.setState({ checked: this.props.badge !== undefined ? true : false, badgeName: this.props.badge ? this.state.badges.filter(badge => badge._id === this.props.badge)[0].name : '' });
+ }
+ }
+
+ getBadges = () => {
+ axios.get(`${process.env.REACT_APP_MYBADGES_API}/badge`)
+ .then(res => {
+ this.setState({badges: res.data.badges, badgeName: this.props.badge ? res.data.badges.filter(badge => badge._id === this.props.badge)[0].name : '' });
+ })
+ .catch(err => {
+ console.log(err);
+ });
+ };
+
+ deleteBadge = () => {
+ this.setState({ filteredBadges: [], badgeName: '' });
+ this.props.tutorialBadge(null);
+ this.props.setError(this.props.index, 'badge');
+ };
+
+ setBadge = (badge) => {
+ this.setState({ filteredBadges: [] });
+ this.props.tutorialBadge(badge._id);
+ this.props.deleteError(this.props.index, 'badge');
+ };
+
+ onChange = e => {
+ this.setState({ badgeName: e.target.value });
+ };
+
+ onChangeBadge = e => {
+ if(e.target.value && this.props.badge === null){
+ var filteredBadges = this.state.badges.filter(badge => new RegExp(e.target.value, 'i').test(badge.name));
+ if(filteredBadges.length < 1){
+ filteredBadges = ['Keine Übereinstimmung gefunden.'];
+ }
+ this.setState({filteredBadges: filteredBadges});
+ }
+ else {
+ this.setState({filteredBadges: []});
+ }
+ };
+
+ onChangeSwitch = (value) => {
+ var oldValue = this.state.checked;
+ this.setState({checked: value});
+ if(oldValue !== value){
+ if(value){
+ this.props.setError(this.props.index, 'badge');
+ this.props.tutorialBadge(null);
+ } else {
+ this.props.deleteError(this.props.index, 'badge');
+ this.props.tutorialBadge(undefined);
+ }
+ }
+ }
+
+ render() {
+ return (
+
+ this.onChangeSwitch(e.target.checked)}
+ color="primary"
+ />
+ }
+ />
+ {this.state.checked ?
+
+
+
+ {'Badge'}
+
+ this.onChange(e)}
+ onInput={(e) => this.onChangeBadge(e)}
+ fullWidth={true}
+ endAdornment={
+
+
+
+ }
+ />
+ {this.props.error && this.state.filteredBadges.length === 0 ?
+ Wähle ein Badge aus.
+ : null}
+
+
+ {this.state.filteredBadges.map((badge, i) => (
+ badge === 'Keine Übereinstimmung gefunden.' ?
+
+ {badge}
+
+ :
+ {this.setBadge(badge)}} style={{border: '1px solid rgba(0, 0, 0, 0.23)', borderRadius: '25px'}}>
+ {`${badge.name}`}
+
+ ))}
+
+
+ : null}
+
+ );
+ };
+}
+
+Badge.propTypes = {
+ tutorialBadge: PropTypes.func.isRequired,
+ deleteProperty: PropTypes.func.isRequired,
+ setError: PropTypes.func.isRequired,
+ deleteError: PropTypes.func.isRequired,
+ badge: PropTypes.string.isRequired
+};
+
+const mapStateToProps = state => ({
+ badge: state.builder.badge,
+ change: state.builder.change
+});
+
+
+export default connect(mapStateToProps, { tutorialBadge, deleteProperty, setError, deleteError })(withStyles(styles, {withTheme: true})(Badge));
diff --git a/src/components/Tutorial/Builder/BlocklyExample.js b/src/components/Tutorial/Builder/BlocklyExample.js
index 01f52f4..75dc222 100644
--- a/src/components/Tutorial/Builder/BlocklyExample.js
+++ b/src/components/Tutorial/Builder/BlocklyExample.js
@@ -29,7 +29,7 @@ const styles = (theme) => ({
marginTop: '5px',
height: '40px',
backgroundColor: theme.palette.error.dark,
- '&:hover':{
+ '&:hover': {
backgroundColor: theme.palette.error.dark
}
}
@@ -37,16 +37,16 @@ const styles = (theme) => ({
class BlocklyExample extends Component {
- constructor(props){
+ constructor(props) {
super(props);
- this.state={
+ this.state = {
checked: props.task ? props.task : props.value ? true : false,
input: null,
disabled: false
};
}
- componentDidMount(){
+ componentDidMount() {
moment.updateLocale('de', localization);
this.isError();
// if(this.props.task){
@@ -54,42 +54,42 @@ class BlocklyExample extends Component {
// }
}
- componentDidUpdate(props, state){
- if(props.task !== this.props.task || props.value !== this.props.value){
- this.setState({checked: this.props.task ? this.props.task : this.props.value ? true : false},
+ componentDidUpdate(props, state) {
+ if (props.task !== this.props.task || props.value !== this.props.value) {
+ this.setState({ checked: this.props.task ? this.props.task : this.props.value ? true : false },
() => this.isError()
);
}
- if(state.checked !== this.state.checked && this.state.checked){
+ if (state.checked !== this.state.checked && this.state.checked) {
this.isError();
}
- if(props.xml !== this.props.xml){
+ if (props.xml !== this.props.xml) {
// check if there is at least one block, otherwise the workspace cannot be submitted
var workspace = Blockly.getMainWorkspace();
var areBlocks = workspace.getAllBlocks().length > 0;
- this.setState({disabled: !areBlocks});
+ this.setState({ disabled: !areBlocks });
}
}
isError = () => {
- if(this.state.checked){
+ if (this.state.checked) {
var xml = this.props.value;
// check if value is valid xml;
- try{
+ try {
Blockly.Xml.textToDom(xml);
this.props.deleteError(this.props.index, 'xml');
}
- catch(err){
+ catch (err) {
xml = initialXml;
// not valid xml, throw error in redux store
this.props.setError(this.props.index, 'xml');
}
- if(!this.props.task){
+ if (!this.props.task) {
// instruction can also display only one block, which does not necessarily
// have to be the initial block
xml = xml.replace('deletable="false"', 'deletable="true"');
}
- this.setState({xml: xml});
+ this.setState({ xml: xml });
}
else {
this.props.deleteError(this.props.index, 'xml');
@@ -98,8 +98,8 @@ class BlocklyExample extends Component {
onChange = (value) => {
var oldValue = this.state.checked;
- this.setState({checked: value});
- if(oldValue !== value && !value){
+ this.setState({ checked: value });
+ if (oldValue !== value && !value) {
this.props.deleteError(this.props.index, 'xml');
this.props.deleteProperty(this.props.index, 'xml');
}
@@ -108,12 +108,12 @@ class BlocklyExample extends Component {
setXml = () => {
var xml = this.props.xml;
this.props.changeContent(xml, this.props.index, 'xml');
- this.setState({input: moment(Date.now()).format('LTS')});
+ this.setState({ input: moment(Date.now()).format('LTS') });
}
render() {
return (
-
+
{!this.props.task ?
}
/>
- : Musterlösung }
+ : {Blockly.Msg.builder_solution} }
{this.state.checked ? !this.props.value || this.props.error ?
- {`Reiche deine Blöcke ein, indem du auf den '${this.props.task ? 'Musterlösung einreichen' : 'Beispiel einreichen'}'-Button klickst.`}
- : this.state.input ? Die letzte Einreichung erfolgte um {this.state.input} Uhr. : null
- : null}
+ {`Reiche deine Blöcke ein, indem du auf den '${this.props.task ? Blockly.Msg.builder_solution_submit : Blockly.Msg.builder_example_submit}'-Button klickst.`}
+ : this.state.input ? Die letzte Einreichung erfolgte um {this.state.input} Uhr. : null
+ : null}
{this.state.checked && !this.props.task ?
- Anmerkung: Man kann den initialen Setup()- bzw. Endlosschleifen()-Block löschen. Zusätzlich ist es möglich u.a. nur einen beliebigen Block auszuwählen, ohne dass dieser als deaktiviert dargestellt wird.
- : null}
+ {Blockly.Msg.builder_comment}
+ : null}
{/* ensure that the correct xml-file is displayed in the workspace */}
- {this.state.checked && this.state.xml? (() => {
- return(
-
+ {this.state.checked && this.state.xml ? (() => {
+ return (
+
- )})()
- : null}
+ )
+ })()
+ : null}
);
};
@@ -179,4 +180,4 @@ const mapStateToProps = state => ({
});
-export default connect(mapStateToProps, { changeContent, deleteProperty, setError, deleteError })(withStyles(styles, {withTheme: true})(BlocklyExample));
+export default connect(mapStateToProps, { changeContent, deleteProperty, setError, deleteError })(withStyles(styles, { withTheme: true })(BlocklyExample));
diff --git a/src/components/Tutorial/Builder/Builder.js b/src/components/Tutorial/Builder/Builder.js
index 78c7657..74fbea4 100644
--- a/src/components/Tutorial/Builder/Builder.js
+++ b/src/components/Tutorial/Builder/Builder.js
@@ -2,16 +2,15 @@ import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { checkError, readJSON, jsonString, progress, tutorialId, resetTutorial as resetTutorialBuilder} from '../../../actions/tutorialBuilderActions';
-import { getTutorials, resetTutorial, deleteTutorial } from '../../../actions/tutorialActions';
+import { getTutorials, resetTutorial, deleteTutorial, tutorialProgress } from '../../../actions/tutorialActions';
import { clearMessages } from '../../../actions/messageActions';
import axios from 'axios';
import { withRouter } from 'react-router-dom';
-import { saveAs } from 'file-saver';
-import { detectWhitespacesAndReturnReadableResult } from '../../../helpers/whitespace';
import Breadcrumbs from '../../Breadcrumbs';
+import Badge from './Badge';
import Textfield from './Textfield';
import Step from './Step';
import Dialog from '../../Dialog';
@@ -43,7 +42,7 @@ const styles = (theme) => ({
marginTop: '5px',
height: '40px',
backgroundColor: theme.palette.error.dark,
- '&:hover':{
+ '&:hover': {
backgroundColor: theme.palette.error.dark
}
}
@@ -68,20 +67,29 @@ class Builder extends Component {
}
componentDidMount() {
- this.props.getTutorials();
+ this.props.tutorialProgress();
+ // retrieve tutorials only if a potential user is loaded - authentication
+ // is finished (success or failed)
+ if(!this.props.authProgress){
+ this.props.getTutorials();
+ }
}
componentDidUpdate(props, state) {
+ if(props.authProgress !== this.props.authProgress && !this.props.authProgress){
+ // authentication is completed
+ this.props.getTutorials();
+ }
if(props.message !== this.props.message){
if(this.props.message.id === 'GET_TUTORIALS_FAIL'){
// alert(this.props.message.msg);
this.props.clearMessages();
}
- else if(this.props.message.id === 'TUTORIAL_DELETE_SUCCESS'){
+ else if (this.props.message.id === 'TUTORIAL_DELETE_SUCCESS') {
this.onChange('new');
this.setState({ snackbar: true, key: Date.now(), message: `Das Tutorial wurde erfolgreich gelöscht.`, type: 'success' });
}
- else if(this.props.message.id === 'TUTORIAL_DELETE_FAIL'){
+ else if (this.props.message.id === 'TUTORIAL_DELETE_FAIL') {
this.setState({ snackbar: true, key: Date.now(), message: `Fehler beim Löschen des Tutorials. Versuche es noch einmal.`, type: 'error' });
}
}
@@ -90,7 +98,7 @@ class Builder extends Component {
componentWillUnmount() {
this.resetFull();
this.props.resetTutorial();
- if(this.props.message.msg){
+ if (this.props.message.msg) {
this.props.clearMessages();
}
}
@@ -143,12 +151,12 @@ class Builder extends Component {
onChange = (value) => {
this.props.resetTutorialBuilder();
this.props.tutorialId('');
- this.setState({tutorial: value});
+ this.setState({ tutorial: value });
}
onChangeId = (value) => {
this.props.tutorialId(value);
- if(this.state.tutorial === 'change'){
+ if (this.state.tutorial === 'change') {
this.props.progress(true);
var tutorial = this.props.tutorials.filter(tutorial => tutorial._id === value)[0];
this.props.readJSON(tutorial);
@@ -181,13 +189,18 @@ class Builder extends Component {
var steps = this.props.steps;
var newTutorial = new FormData();
newTutorial.append('title', this.props.title);
- newTutorial.append('badge', this.props.badge);
+ if(this.props.badge){
+ newTutorial.append('badge', this.props.badge);
+ }
steps.forEach((step, i) => {
+ if(step._id){
+ newTutorial.append(`steps[${i}][_id]`, step._id);
+ }
newTutorial.append(`steps[${i}][type]`, step.type);
newTutorial.append(`steps[${i}][headline]`, step.headline);
newTutorial.append(`steps[${i}][text]`, step.text);
- if(i === 0 && step.type === 'instruction'){
- if(step.requirements){ // optional
+ if (i === 0 && step.type === 'instruction') {
+ if (step.requirements) { // optional
step.requirements.forEach((requirement, j) => {
newTutorial.append(`steps[${i}][requirements][${j}]`, requirement);
});
@@ -196,14 +209,14 @@ class Builder extends Component {
newTutorial.append(`steps[${i}][hardware][${j}]`, hardware);
});
}
- if(step.xml){ // optional
+ if (step.xml) { // optional
newTutorial.append(`steps[${i}][xml]`, step.xml);
}
- if(step.media){ // optional
- if(step.media.youtube){
+ if (step.media) { // optional
+ if (step.media.youtube) {
newTutorial.append(`steps[${i}][media][youtube]`, step.media.youtube);
}
- if(step.media.picture){
+ if (step.media.picture) {
newTutorial.append(`steps[${i}][media][picture]`, step.media.picture);
}
}
@@ -215,14 +228,22 @@ class Builder extends Component {
submitNew = () => {
var newTutorial = this.submit();
if(newTutorial){
- axios.post(`${process.env.REACT_APP_BLOCKLY_API}/tutorial/`, newTutorial)
- .then(res => {
+ const config = {
+ success: res => {
var tutorial = res.data.tutorial;
this.props.history.push(`/tutorial/${tutorial._id}`);
- })
- .catch(err => {
+ },
+ error: err => {
this.setState({ snackbar: true, key: Date.now(), message: `Fehler beim Erstellen des Tutorials. Versuche es noch einmal.`, type: 'error' });
window.scrollTo(0, 0);
+ }
+ };
+ axios.post(`${process.env.REACT_APP_BLOCKLY_API}/tutorial/`, newTutorial, config)
+ .then(res => {
+ res.config.success(res);
+ })
+ .catch(err => {
+ err.config.error(err);
});
}
}
@@ -230,14 +251,22 @@ class Builder extends Component {
submitUpdate = () => {
var updatedTutorial = this.submit();
if(updatedTutorial){
- axios.put(`${process.env.REACT_APP_BLOCKLY_API}/tutorial/${this.props.id}`, updatedTutorial)
- .then(res => {
+ const config = {
+ success: res => {
var tutorial = res.data.tutorial;
this.props.history.push(`/tutorial/${tutorial._id}`);
- })
- .catch(err => {
+ },
+ error: err => {
this.setState({ snackbar: true, key: Date.now(), message: `Fehler beim Ändern des Tutorials. Versuche es noch einmal.`, type: 'error' });
window.scrollTo(0, 0);
+ }
+ };
+ axios.put(`${process.env.REACT_APP_BLOCKLY_API}/tutorial/${this.props.id}`, updatedTutorial, config)
+ .then(res => {
+ res.config.success(res);
+ })
+ .catch(err => {
+ err.config.error(err);
});
}
}
@@ -251,30 +280,30 @@ class Builder extends Component {
Tutorial-Builder
this.onChange(e.target.value)}>
- }
label="neues Tutorial erstellen"
labelPlacement="end"
/>
{filteredTutorials.length > 0 ?
-
- }
- label="bestehendes Tutorial ändern"
- labelPlacement="end"
- />
- }
- label="bestehendes Tutorial löschen"
- labelPlacement="end"
- />
-
- : null}
+
+ }
+ label="bestehendes Tutorial ändern"
+ labelPlacement="end"
+ />
+ }
+ label="bestehendes Tutorial löschen"
+ labelPlacement="end"
+ />
+
+ : null}
@@ -294,7 +323,7 @@ class Builder extends Component {
- :
+ :
Tutorial
*/}
-
+
{this.props.steps.map((step, i) =>
)}
{/*submit or reset*/}
-
- {this.state.tutorial === 'new' ?
+ {this.state.tutorial !== 'delete' ?
-
-
+
+ {this.state.tutorial === 'new' ?
+
+
+
+
+ :
+
+
+
+ }
- :
-
-
-
- }
+ : null}
-
-
-
-
- : null}
+
+
+
+
+ : null}
{this.state.tutorial === 'delete' && this.props.id !== '' ?
- : null}
+ : null}