From 1821ac4e40281fbe5ec59dc44a37478c5b63ae75 Mon Sep 17 00:00:00 2001
From: Delucse <46593742+Delucse@users.noreply.github.com>
Date: Fri, 11 Dec 2020 13:06:38 +0100
Subject: [PATCH 01/16] tutorial status is stored in user account if exists or
in local storage
---
src/actions/authActions.js | 46 ++++++++++++++++++++++++-
src/actions/tutorialActions.js | 33 ++++++++++++++++--
src/actions/types.js | 1 +
src/components/Tutorial/Tutorial.js | 24 +++++++++----
src/components/Tutorial/TutorialHome.js | 22 +++++++++---
src/reducers/authReducer.js | 2 +-
src/reducers/tutorialReducer.js | 34 +++++++++++-------
7 files changed, 133 insertions(+), 29 deletions(-)
diff --git a/src/actions/authActions.js b/src/actions/authActions.js
index 7cdd1c0..a6dee52 100644
--- a/src/actions/authActions.js
+++ b/src/actions/authActions.js
@@ -1,4 +1,4 @@
-import { MYBADGES_CONNECT, MYBADGES_DISCONNECT, USER_LOADED, USER_LOADING, AUTH_ERROR, LOGIN_SUCCESS, LOGIN_FAIL, LOGOUT_SUCCESS, LOGOUT_FAIL, REFRESH_TOKEN_SUCCESS } from '../actions/types';
+import { MYBADGES_CONNECT, MYBADGES_DISCONNECT, GET_STATUS, USER_LOADED, USER_LOADING, AUTH_ERROR, LOGIN_SUCCESS, LOGIN_FAIL, LOGOUT_SUCCESS, LOGOUT_FAIL, REFRESH_TOKEN_SUCCESS } from '../actions/types';
import axios from 'axios';
import { returnErrors, returnSuccess } from './messageActions'
@@ -12,6 +12,10 @@ export const loadUser = () => (dispatch) => {
});
const config = {
success: res => {
+ dispatch({
+ type: GET_STATUS,
+ payload: res.data.user.status
+ });
dispatch({
type: USER_LOADED,
payload: res.data.user
@@ -21,6 +25,15 @@ export const loadUser = () => (dispatch) => {
if(err.response){
dispatch(returnErrors(err.response.data.message, err.response.status));
}
+ console.log('auth failed');
+ var status = [];
+ if (window.localStorage.getItem('status')) {
+ status = JSON.parse(window.localStorage.getItem('status'));
+ }
+ dispatch({
+ type: GET_STATUS,
+ payload: status
+ });
dispatch({
type: AUTH_ERROR
});
@@ -31,6 +44,7 @@ export const loadUser = () => (dispatch) => {
res.config.success(res);
})
.catch(err => {
+ console.log(err);
err.config.error(err);
});
};
@@ -61,13 +75,26 @@ export const login = ({ email, password }) => (dispatch) => {
type: LOGIN_SUCCESS,
payload: res.data
});
+ dispatch({
+ type: GET_STATUS,
+ payload: res.data.user.status
+ });
dispatch(returnSuccess(res.data.message, res.status, 'LOGIN_SUCCESS'));
})
.catch(err => {
+ console.log(err);
dispatch(returnErrors(err.response.data.message, err.response.status, 'LOGIN_FAIL'));
dispatch({
type: LOGIN_FAIL
});
+ var status = [];
+ if (window.localStorage.getItem('status')) {
+ status = JSON.parse(window.localStorage.getItem('status'));
+ }
+ dispatch({
+ type: GET_STATUS,
+ payload: status
+ });
});
};
@@ -130,6 +157,14 @@ export const logout = () => (dispatch) => {
dispatch({
type: LOGOUT_SUCCESS
});
+ var status = [];
+ if (window.localStorage.getItem('status')) {
+ status = JSON.parse(window.localStorage.getItem('status'));
+ }
+ dispatch({
+ type: GET_STATUS,
+ payload: status
+ });
dispatch(returnSuccess(res.data.message, res.status, 'LOGOUT_SUCCESS'));
clearTimeout(logoutTimerId);
},
@@ -138,6 +173,14 @@ export const logout = () => (dispatch) => {
dispatch({
type: LOGOUT_FAIL
});
+ var status = [];
+ if (window.localStorage.getItem('status')) {
+ status = JSON.parse(window.localStorage.getItem('status'));
+ }
+ dispatch({
+ type: GET_STATUS,
+ payload: status
+ });
clearTimeout(logoutTimerId);
}
};
@@ -146,6 +189,7 @@ export const logout = () => (dispatch) => {
res.config.success(res);
})
.catch(err => {
+ console.log(err);
if(err.response.status !== 401){
err.config.error(err);
}
diff --git a/src/actions/tutorialActions.js b/src/actions/tutorialActions.js
index 8983da9..426317f 100644
--- a/src/actions/tutorialActions.js
+++ b/src/actions/tutorialActions.js
@@ -3,21 +3,28 @@ import { MYBADGES_DISCONNECT, TUTORIAL_PROGRESS, GET_TUTORIAL, GET_TUTORIALS, TU
import axios from 'axios';
import { returnErrors, returnSuccess } from './messageActions';
-export const getTutorial = (id) => (dispatch, getState) => {
+export const tutorialProgress = () => (dispatch) => {
dispatch({type: TUTORIAL_PROGRESS});
+};
+
+
+export const getTutorial = (id) => (dispatch, getState) => {
axios.get(`${process.env.REACT_APP_BLOCKLY_API}/tutorial/${id}`)
.then(res => {
var tutorial = res.data.tutorial;
existingTutorial(tutorial, getState().tutorial.status).then(status => {
+ console.log('progress',getState().auth.progress);
+ console.log('status');
dispatch({
type: TUTORIAL_SUCCESS,
payload: status
});
- dispatch({type: TUTORIAL_PROGRESS});
+ dispatch(updateStatus(status));
dispatch({
type: GET_TUTORIAL,
payload: tutorial
});
+ dispatch({type: TUTORIAL_PROGRESS});
dispatch(returnSuccess(res.data.message, res.status));
});
})
@@ -30,7 +37,6 @@ export const getTutorial = (id) => (dispatch, getState) => {
};
export const getTutorials = () => (dispatch, getState) => {
- dispatch({type: TUTORIAL_PROGRESS});
axios.get(`${process.env.REACT_APP_BLOCKLY_API}/tutorial`)
.then(res => {
var tutorials = res.data.tutorials;
@@ -40,6 +46,7 @@ export const getTutorials = () => (dispatch, getState) => {
type: TUTORIAL_SUCCESS,
payload: status
});
+ dispatch(updateStatus(status));
dispatch({
type: GET_TUTORIALS,
payload: tutorials
@@ -75,6 +82,24 @@ export const assigneBadge = (id) => (dispatch, getState) => {
});
};
+export const updateStatus = (status) => (dispatch, getState) => {
+ if(getState().auth.isAuthenticated){
+ // update user account in database - sync with redux store
+ axios.put(`${process.env.REACT_APP_BLOCKLY_API}/user/status`, {status: status})
+ .then(res => {
+ // dispatch(returnSuccess(badge, res.status, 'UPDATE_STATUS_SUCCESS'));
+ })
+ .catch(err => {
+ if(err.response){
+ // dispatch(returnErrors(err.response.data.message, err.response.status, 'UPDATE_STATUS_FAIL'));
+ }
+ });
+ } else {
+ // update locale storage - sync with redux store
+ window.localStorage.setItem('status', JSON.stringify(status));
+ }
+};
+
export const deleteTutorial = (id) => (dispatch, getState) => {
var tutorial = getState().tutorial;
var id = getState().builder.id;
@@ -127,6 +152,7 @@ export const tutorialCheck = (status, step) => (dispatch, getState) => {
type: status === 'success' ? TUTORIAL_SUCCESS : TUTORIAL_ERROR,
payload: tutorialsStatus
});
+ dispatch(updateStatus(tutorialsStatus));
dispatch(tutorialChange());
dispatch(returnSuccess('','','TUTORIAL_CHECK_SUCCESS'));
};
@@ -149,6 +175,7 @@ export const storeTutorialXml = (code) => (dispatch, getState) => {
type: TUTORIAL_XML,
payload: tutorialsStatus
});
+ dispatch(updateStatus(tutorialsStatus));
}
}
};
diff --git a/src/actions/types.js b/src/actions/types.js
index b3bff75..99ed6a6 100644
--- a/src/actions/types.js
+++ b/src/actions/types.js
@@ -23,6 +23,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_STATUS = 'GET_STATUS';
export const TUTORIAL_SUCCESS = 'TUTORIAL_SUCCESS';
export const TUTORIAL_ERROR = 'TUTORIAL_ERROR';
export const TUTORIAL_CHANGE = 'TUTORIAL_CHANGE';
diff --git a/src/components/Tutorial/Tutorial.js b/src/components/Tutorial/Tutorial.js
index d86a958..189386c 100644
--- a/src/components/Tutorial/Tutorial.js
+++ b/src/components/Tutorial/Tutorial.js
@@ -3,7 +3,7 @@ import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { workspaceName } from '../../actions/workspaceActions';
import { clearMessages } from '../../actions/messageActions';
-import { getTutorial, resetTutorial, tutorialStep } from '../../actions/tutorialActions';
+import { getTutorial, resetTutorial, tutorialStep,tutorialProgress } from '../../actions/tutorialActions';
import Breadcrumbs from '../Breadcrumbs';
import StepperHorizontal from './StepperHorizontal';
@@ -22,11 +22,20 @@ import Button from '@material-ui/core/Button';
class Tutorial extends Component {
componentDidMount() {
- this.props.getTutorial(this.props.match.params.tutorialId);
+ this.props.tutorialProgress();
+ // retrieve tutorials only if a potential user is loaded - authentication
+ // is finished (success or failed)
+ if(!this.props.progress){
+ this.props.getTutorial(this.props.match.params.tutorialId);
+ }
}
componentDidUpdate(props, state) {
- if(this.props.tutorial && !this.props.isLoading && this.props.tutorial._id != this.props.match.params.tutorialId) {
+ if(props.progress !== this.props.progress && !this.props.progress){
+ // authentication is completed
+ this.props.getTutorial(this.props.match.params.tutorialId);
+ }
+ else if(this.props.tutorial && !this.props.isLoading && this.props.tutorial._id != this.props.match.params.tutorialId) {
this.props.getTutorial(this.props.match.params.tutorialId);
}
if(this.props.message.id === 'GET_TUTORIAL_FAIL'){
@@ -89,13 +98,15 @@ Tutorial.propTypes = {
resetTutorial: PropTypes.func.isRequired,
clearMessages: PropTypes.func.isRequired,
tutorialStep: PropTypes.func.isRequired,
+ tutorialProgress: PropTypes.func.isRequired,
workspaceName: PropTypes.func.isRequired,
status: PropTypes.array.isRequired,
change: PropTypes.number.isRequired,
activeStep: PropTypes.number.isRequired,
tutorial: PropTypes.object.isRequired,
isLoading: PropTypes.bool.isRequired,
- message: PropTypes.object.isRequired
+ message: PropTypes.object.isRequired,
+ progress: PropTypes.bool.isRequired
};
const mapStateToProps = state => ({
@@ -104,7 +115,8 @@ const mapStateToProps = state => ({
activeStep: state.tutorial.activeStep,
tutorial: state.tutorial.tutorials[0],
isLoading: state.tutorial.progress,
- message: state.message
+ message: state.message,
+ progress: state.auth.progress
});
-export default connect(mapStateToProps, { getTutorial, resetTutorial, tutorialStep, clearMessages, workspaceName })(Tutorial);
+export default connect(mapStateToProps, { getTutorial, resetTutorial, tutorialStep, tutorialProgress, clearMessages, workspaceName })(Tutorial);
diff --git a/src/components/Tutorial/TutorialHome.js b/src/components/Tutorial/TutorialHome.js
index 9c7a2ce..42db1a9 100644
--- a/src/components/Tutorial/TutorialHome.js
+++ b/src/components/Tutorial/TutorialHome.js
@@ -1,7 +1,7 @@
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
-import { getTutorials, resetTutorial } from '../../actions/tutorialActions';
+import { getTutorials, resetTutorial, tutorialProgress } from '../../actions/tutorialActions';
import { clearMessages } from '../../actions/messageActions';
import clsx from 'clsx';
@@ -52,10 +52,19 @@ const styles = (theme) => ({
class TutorialHome 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.progress){
+ this.props.getTutorials();
+ }
}
componentDidUpdate(props, state) {
+ if(props.progress !== this.props.progress && !this.props.progress){
+ // authentication is completed
+ this.props.getTutorials();
+ }
if(this.props.message.id === 'GET_TUTORIALS_FAIL'){
alert(this.props.message.msg);
}
@@ -120,12 +129,14 @@ class TutorialHome extends Component {
TutorialHome.propTypes = {
getTutorials: PropTypes.func.isRequired,
resetTutorial: PropTypes.func.isRequired,
+ tutorialProgress: PropTypes.func.isRequired,
clearMessages: PropTypes.func.isRequired,
status: PropTypes.array.isRequired,
change: PropTypes.number.isRequired,
tutorials: PropTypes.array.isRequired,
isLoading: PropTypes.bool.isRequired,
- message: PropTypes.object.isRequired
+ message: PropTypes.object.isRequired,
+ progress: PropTypes.bool.isRequired
};
const mapStateToProps = state => ({
@@ -133,7 +144,8 @@ const mapStateToProps = state => ({
status: state.tutorial.status,
tutorials: state.tutorial.tutorials,
isLoading: state.tutorial.progress,
- message: state.message
+ message: state.message,
+ progress: state.auth.progress
});
-export default connect(mapStateToProps, { getTutorials, resetTutorial, clearMessages })(withStyles(styles, { withTheme: true })(TutorialHome));
+export default connect(mapStateToProps, { getTutorials, resetTutorial, clearMessages, tutorialProgress })(withStyles(styles, { withTheme: true })(TutorialHome));
diff --git a/src/reducers/authReducer.js b/src/reducers/authReducer.js
index 482af0c..7de6fb8 100644
--- a/src/reducers/authReducer.js
+++ b/src/reducers/authReducer.js
@@ -5,7 +5,7 @@ const initialState = {
token: localStorage.getItem('token'),
refreshToken: localStorage.getItem('refreshToken'),
isAuthenticated: null,
- progress: false,
+ progress: true,
user: null
};
diff --git a/src/reducers/tutorialReducer.js b/src/reducers/tutorialReducer.js
index 8b91f0f..0e368f8 100644
--- a/src/reducers/tutorialReducer.js
+++ b/src/reducers/tutorialReducer.js
@@ -1,18 +1,20 @@
-import { TUTORIAL_PROGRESS, GET_TUTORIAL, GET_TUTORIALS, TUTORIAL_SUCCESS, TUTORIAL_ERROR, TUTORIAL_CHANGE, TUTORIAL_XML, TUTORIAL_ID, TUTORIAL_STEP } from '../actions/types';
+import { TUTORIAL_PROGRESS, GET_TUTORIAL, GET_TUTORIALS, GET_STATUS, TUTORIAL_SUCCESS, TUTORIAL_ERROR, TUTORIAL_CHANGE, TUTORIAL_XML, TUTORIAL_ID, TUTORIAL_STEP } from '../actions/types';
-const initialStatus = () => {
- if (window.localStorage.getItem('status')) {
- var status = JSON.parse(window.localStorage.getItem('status'));
- return status;
- }
- return [];
- // // window.localStorage.getItem('status') does not exist
- // return tutorials.map(tutorial => { return { id: tutorial.id, tasks: tutorial.steps.filter(step => step.type === 'task').map(task => { return { id: task.id }; }) }; });
-};
+//
+// const initialStatus = () => {
+// if(store.getState().auth.user){
+// return store.getState().auth.user.status || []
+// }
+// else if (window.localStorage.getItem('status')) {
+// var status = JSON.parse(window.localStorage.getItem('status'));
+// return status;
+// }
+// return [];
+// };
const initialState = {
- status: initialStatus(),
+ status: [],
activeStep: 0,
change: 0,
tutorials: [],
@@ -39,8 +41,14 @@ export default function (state = initialState, action) {
case TUTORIAL_SUCCESS:
case TUTORIAL_ERROR:
case TUTORIAL_XML:
- // update locale storage - sync with redux store
- window.localStorage.setItem('status', JSON.stringify(action.payload));
+ // update store - sync with redux store is implemented outside reducer
+ // in every dispatch action with the types 'TUTORIAL_SUCCESS','TUTORIAL_ERROR'
+ // and 'TUTORIAL_XML' the function 'updateStatus' is called
+ return {
+ ...state,
+ status: action.payload
+ };
+ case GET_STATUS:
return {
...state,
status: action.payload
From 4f002d8694f4adc535b94f3ffb0bffea4de1a6ae Mon Sep 17 00:00:00 2001
From: Delucse <46593742+Delucse@users.noreply.github.com>
Date: Fri, 11 Dec 2020 14:35:24 +0100
Subject: [PATCH 02/16] definig success and error callbacks for every private
axios request
---
src/actions/authActions.js | 63 +++++++++++----------
src/actions/projectActions.js | 64 ++++++++++++++++------
src/actions/tutorialActions.js | 37 ++++++++++---
src/actions/tutorialBuilderActions.js | 3 +-
src/components/Project/Project.js | 1 -
src/components/Project/ProjectHome.js | 1 -
src/components/Tutorial/Builder/Builder.js | 55 +++++++++++++++----
src/components/Tutorial/Tutorial.js | 2 +-
src/components/User/MyBadges.js | 15 +++--
src/components/Workspace/SaveProject.js | 16 ++++--
10 files changed, 179 insertions(+), 78 deletions(-)
diff --git a/src/actions/authActions.js b/src/actions/authActions.js
index a6dee52..8e97232 100644
--- a/src/actions/authActions.js
+++ b/src/actions/authActions.js
@@ -44,7 +44,6 @@ export const loadUser = () => (dispatch) => {
res.config.success(res);
})
.catch(err => {
- console.log(err);
err.config.error(err);
});
};
@@ -82,7 +81,6 @@ export const login = ({ email, password }) => (dispatch) => {
dispatch(returnSuccess(res.data.message, res.status, 'LOGIN_SUCCESS'));
})
.catch(err => {
- console.log(err);
dispatch(returnErrors(err.response.data.message, err.response.status, 'LOGIN_FAIL'));
dispatch({
type: LOGIN_FAIL
@@ -101,51 +99,59 @@ export const login = ({ email, password }) => (dispatch) => {
// Connect to MyBadges-Account
export const connectMyBadges = ({ username, password }) => (dispatch, getState) => {
- // Headers
const config = {
- headers: {
- 'Content-Type': 'application/json'
+ success: res => {
+ var user = getState().auth.user;
+ user.badge = res.data.account;
+ user.badges = res.data.badges;
+ dispatch({
+ type: MYBADGES_CONNECT,
+ payload: user
+ });
+ dispatch(returnSuccess(res.data.message, res.status, 'MYBADGES_CONNECT_SUCCESS'));
+ },
+ error: err => {
+ dispatch(returnErrors(err.response.data.message, err.response.status, 'MYBADGES_CONNECT_FAIL'));
}
};
// Request Body
const body = JSON.stringify({ username, password });
axios.post(`${process.env.REACT_APP_BLOCKLY_API}/user/badge`, body, config)
.then(res => {
- var user = getState().auth.user;
- user.badge = res.data.account;
- user.badges = res.data.badges;
- dispatch({
- type: MYBADGES_CONNECT,
- payload: user
- });
- dispatch(returnSuccess(res.data.message, res.status, 'MYBADGES_CONNECT_SUCCESS'));
+ res.config.success(res);
})
.catch(err => {
- dispatch(returnErrors(err.response.data.message, err.response.status, 'MYBADGES_CONNECT_FAIL'));
+ if(err.response && err.response.status !== 401){
+ err.config.error(err);
+ }
});
};
// Disconnect MyBadges-Account
export const disconnectMyBadges = () => (dispatch, getState) => {
- // Headers
const config = {
- headers: {
- 'Content-Type': 'application/json'
+ success: res => {
+ var user = getState().auth.user;
+ user.badge = null;
+ user.badges = null;
+ dispatch({
+ type: MYBADGES_DISCONNECT,
+ payload: user
+ });
+ dispatch(returnSuccess(res.data.message, res.status, 'MYBADGES_DISCONNECT_SUCCESS'));
+ },
+ error: err => {
+ dispatch(returnErrors(err.response.data.message, err.response.status, 'MYBADGES_DISCONNECT_FAIL'));
}
};
- axios.put(`${process.env.REACT_APP_BLOCKLY_API}/user/badge`, config)
+ axios.put(`${process.env.REACT_APP_BLOCKLY_API}/user/badge`, {}, config)
.then(res => {
- var user = getState().auth.user;
- user.badge = null;
- user.badges = null;
- dispatch({
- type: MYBADGES_DISCONNECT,
- payload: user
- });
- dispatch(returnSuccess(res.data.message, res.status, 'MYBADGES_DISCONNECT_SUCCESS'));
+ res.config.success(res);
})
.catch(err => {
- dispatch(returnErrors(err.response.data.message, err.response.status, 'MYBADGES_DISCONNECT_FAIL'));
+ if(err.response && err.response.status !== 401){
+ err.config.error(err);
+ }
});
};
@@ -189,8 +195,7 @@ export const logout = () => (dispatch) => {
res.config.success(res);
})
.catch(err => {
- console.log(err);
- if(err.response.status !== 401){
+ if(err.response && err.response.status !== 401){
err.config.error(err);
}
});
diff --git a/src/actions/projectActions.js b/src/actions/projectActions.js
index 8ab01cf..149584d 100644
--- a/src/actions/projectActions.js
+++ b/src/actions/projectActions.js
@@ -21,8 +21,8 @@ export const setDescription = (description) => (dispatch) => {
export const getProject = (type, id) => (dispatch) => {
dispatch({type: PROJECT_PROGRESS});
dispatch(setType(type));
- axios.get(`${process.env.REACT_APP_BLOCKLY_API}/${type}/${id}`)
- .then(res => {
+ const config = {
+ success: res => {
var data = type === 'share' ? 'content' : type;
var project = res.data[data];
if(project){
@@ -41,19 +41,27 @@ export const getProject = (type, id) => (dispatch) => {
dispatch({type: PROJECT_PROGRESS});
dispatch(returnErrors(res.data.message, res.status, 'PROJECT_EMPTY'));
}
- })
- .catch(err => {
+ },
+ error: err => {
if(err.response){
dispatch(returnErrors(err.response.data.message, err.response.status, 'GET_PROJECT_FAIL'));
}
dispatch({type: PROJECT_PROGRESS});
+ }
+ };
+ axios.get(`${process.env.REACT_APP_BLOCKLY_API}/${type}/${id}`, config)
+ .then(res => {
+ res.config.success(res);
+ })
+ .catch(err => {
+ err.config.error(err);
});
};
export const getProjects = (type) => (dispatch) => {
dispatch({type: PROJECT_PROGRESS});
- axios.get(`${process.env.REACT_APP_BLOCKLY_API}/${type}`)
- .then(res => {
+ const config = {
+ success: res => {
var data = type === 'project' ? 'projects' : 'galleries';
var projects = res.data[data];
dispatch({
@@ -62,12 +70,20 @@ export const getProjects = (type) => (dispatch) => {
});
dispatch({type: PROJECT_PROGRESS});
dispatch(returnSuccess(res.data.message, res.status));
- })
- .catch(err => {
+ },
+ error: err => {
if(err.response){
dispatch(returnErrors(err.response.data.message, err.response.status, 'GET_PROJECTS_FAIL'));
}
dispatch({type: PROJECT_PROGRESS});
+ }
+ };
+ axios.get(`${process.env.REACT_APP_BLOCKLY_API}/${type}`, config)
+ .then(res => {
+ res.config.success(res);
+ })
+ .catch(err => {
+ err.config.error(err);
});
};
@@ -81,8 +97,8 @@ export const updateProject = (type, id) => (dispatch, getState) => {
if(type==='gallery'){
body.description = project.description;
}
- axios.put(`${process.env.REACT_APP_BLOCKLY_API}/${type}/${id}`, body)
- .then(res => {
+ const config = {
+ success: res => {
var project = res.data[type];
var projects = getState().project.projects;
var index = projects.findIndex(res => res._id === project._id);
@@ -96,8 +112,8 @@ export const updateProject = (type, id) => (dispatch, getState) => {
} else {
dispatch(returnSuccess(res.data.message, res.status, 'GALLERY_UPDATE_SUCCESS'));
}
- })
- .catch(err => {
+ },
+ error: err => {
if(err.response){
if(type === 'project'){
dispatch(returnErrors(err.response.data.message, err.response.status, 'PROJECT_UPDATE_FAIL'));
@@ -105,13 +121,21 @@ export const updateProject = (type, id) => (dispatch, getState) => {
dispatch(returnErrors(err.response.data.message, err.response.status, 'GALLERY_UPDATE_FAIL'));
}
}
+ }
+ };
+ axios.put(`${process.env.REACT_APP_BLOCKLY_API}/${type}/${id}`, body, config)
+ .then(res => {
+ res.config.success(res);
+ })
+ .catch(err => {
+ err.config.error(err);
});
};
export const deleteProject = (type, id) => (dispatch, getState) => {
var project = getState().project;
- axios.delete(`${process.env.REACT_APP_BLOCKLY_API}/${type}/${id}`)
- .then(res => {
+ const config = {
+ success: res => {
var projects = getState().project.projects;
var index = projects.findIndex(res => res._id === id);
projects.splice(index, 1)
@@ -124,10 +148,18 @@ export const deleteProject = (type, id) => (dispatch, getState) => {
} else {
dispatch(returnSuccess(res.data.message, res.status, 'GALLERY_DELETE_SUCCESS'));
}
+ },
+ error: err => {
+ dispatch(returnErrors(err.response.data.message, err.response.status, 'PROJECT_DELETE_FAIL'));
+ }
+ };
+ axios.delete(`${process.env.REACT_APP_BLOCKLY_API}/${type}/${id}`, config)
+ .then(res => {
+ res.config.success(res);
})
.catch(err => {
- if(err.response){
- dispatch(returnErrors(err.response.data.message, err.response.status, 'PROJECT_DELETE_FAIL'));
+ if(err.response && err.response.status !== 401){
+ err.config.error(err);
}
});
};
diff --git a/src/actions/tutorialActions.js b/src/actions/tutorialActions.js
index 426317f..ee120ca 100644
--- a/src/actions/tutorialActions.js
+++ b/src/actions/tutorialActions.js
@@ -12,6 +12,7 @@ export const getTutorial = (id) => (dispatch, getState) => {
axios.get(`${process.env.REACT_APP_BLOCKLY_API}/tutorial/${id}`)
.then(res => {
var tutorial = res.data.tutorial;
+ console.log('status', getState().tutorial.status);
existingTutorial(tutorial, getState().tutorial.status).then(status => {
console.log('progress',getState().auth.progress);
console.log('status');
@@ -19,6 +20,7 @@ export const getTutorial = (id) => (dispatch, getState) => {
type: TUTORIAL_SUCCESS,
payload: status
});
+ console.log('eins');
dispatch(updateStatus(status));
dispatch({
type: GET_TUTORIAL,
@@ -46,6 +48,7 @@ export const getTutorials = () => (dispatch, getState) => {
type: TUTORIAL_SUCCESS,
payload: status
});
+ console.log('zwei');
dispatch(updateStatus(status));
dispatch({
type: GET_TUTORIALS,
@@ -64,8 +67,8 @@ export const getTutorials = () => (dispatch, getState) => {
};
export const assigneBadge = (id) => (dispatch, getState) => {
- axios.put(`${process.env.REACT_APP_BLOCKLY_API}/user/badge/${id}`)
- .then(res => {
+ const config = {
+ success: res => {
var badge = res.data.badge;
var user = getState().auth.user;
user.badges.push(badge._id);
@@ -74,10 +77,18 @@ export const assigneBadge = (id) => (dispatch, getState) => {
payload: user
});
dispatch(returnSuccess(badge, res.status, 'ASSIGNE_BADGE_SUCCESS'));
+ },
+ error: err => {
+ dispatch(returnErrors(err.response.data.message, err.response.status, 'ASSIGNE_BADGE_FAIL'));
+ }
+ };
+ axios.put(`${process.env.REACT_APP_BLOCKLY_API}/user/badge/${id}`, {}, config)
+ .then(res => {
+ res.config.success(res);
})
.catch(err => {
- if(err.response){
- dispatch(returnErrors(err.response.data.message, err.response.status, 'ASSIGNE_BADGE_FAIL'));
+ if(err.response && err.response.status !== 401){
+ err.config.error(err);
}
});
};
@@ -103,8 +114,8 @@ export const updateStatus = (status) => (dispatch, getState) => {
export const deleteTutorial = (id) => (dispatch, getState) => {
var tutorial = getState().tutorial;
var id = getState().builder.id;
- axios.delete(`${process.env.REACT_APP_BLOCKLY_API}/tutorial/${id}`)
- .then(res => {
+ const config = {
+ success: res => {
var tutorials = tutorial.tutorials;
var index = tutorials.findIndex(res => res._id === id);
tutorials.splice(index, 1)
@@ -113,10 +124,18 @@ export const deleteTutorial = (id) => (dispatch, getState) => {
payload: tutorials
});
dispatch(returnSuccess(res.data.message, res.status, 'TUTORIAL_DELETE_SUCCESS'));
+ },
+ error: err => {
+ dispatch(returnErrors(err.response.data.message, err.response.status, 'TUTORIAL_DELETE_FAIL'));
+ }
+ };
+ axios.delete(`${process.env.REACT_APP_BLOCKLY_API}/tutorial/${id}`, config)
+ .then(res => {
+ res.config.success(res);
})
.catch(err => {
- if(err.response){
- dispatch(returnErrors(err.response.data.message, err.response.status, 'TUTORIAL_DELETE_FAIL'));
+ if(err.response && err.response.status !== 401){
+ err.config.error(err);
}
});
};
@@ -152,6 +171,7 @@ export const tutorialCheck = (status, step) => (dispatch, getState) => {
type: status === 'success' ? TUTORIAL_SUCCESS : TUTORIAL_ERROR,
payload: tutorialsStatus
});
+ console.log('drei');
dispatch(updateStatus(tutorialsStatus));
dispatch(tutorialChange());
dispatch(returnSuccess('','','TUTORIAL_CHECK_SUCCESS'));
@@ -208,6 +228,7 @@ const existingTutorials = (tutorials, status) => new Promise(function(resolve, r
});
const existingTutorial = (tutorial, status) => new Promise(function(resolve, reject){
+ console.log('st',status);
var tutorialsId = tutorial._id;
var statusIndex = status.findIndex(status => status._id === tutorialsId);
if (statusIndex > -1) {
diff --git a/src/actions/tutorialBuilderActions.js b/src/actions/tutorialBuilderActions.js
index 356e8fa..d7448f3 100644
--- a/src/actions/tutorialBuilderActions.js
+++ b/src/actions/tutorialBuilderActions.js
@@ -254,7 +254,6 @@ export const resetTutorial = () => (dispatch, getState) => {
dispatch(tutorialBadge(''));
var steps = [
{
- id: 1,
type: 'instruction',
headline: '',
text: '',
@@ -282,7 +281,7 @@ export const readJSON = (json) => (dispatch, getState) => {
// accept only valid attributes
var steps = json.steps.map((step, i) => {
var object = {
- // id: step.id,
+ _id: step._id,
type: step.type,
headline: step.headline,
text: step.text
diff --git a/src/components/Project/Project.js b/src/components/Project/Project.js
index a3a2403..7b16310 100644
--- a/src/components/Project/Project.js
+++ b/src/components/Project/Project.js
@@ -5,7 +5,6 @@ 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';
diff --git a/src/components/Project/ProjectHome.js b/src/components/Project/ProjectHome.js
index 07e559b..06c0c2b 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';
diff --git a/src/components/Tutorial/Builder/Builder.js b/src/components/Tutorial/Builder/Builder.js
index 78c7657..ac773f6 100644
--- a/src/components/Tutorial/Builder/Builder.js
+++ b/src/components/Tutorial/Builder/Builder.js
@@ -2,7 +2,7 @@ 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';
@@ -68,10 +68,19 @@ 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);
@@ -183,6 +192,9 @@ class Builder extends Component {
newTutorial.append('title', this.props.title);
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);
@@ -215,14 +227,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 +250,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);
});
}
}
@@ -399,6 +427,7 @@ Builder.propTypes = {
progress: PropTypes.func.isRequired,
deleteTutorial: PropTypes.func.isRequired,
resetTutorialBuilder: PropTypes.func.isRequired,
+ tutorialProgress: PropTypes.func.isRequired,
title: PropTypes.string.isRequired,
badge: PropTypes.string.isRequired,
id: PropTypes.string.isRequired,
@@ -410,7 +439,8 @@ Builder.propTypes = {
isProgress: PropTypes.bool.isRequired,
tutorials: PropTypes.array.isRequired,
message: PropTypes.object.isRequired,
- user: PropTypes.object.isRequired
+ user: PropTypes.object.isRequired,
+ authProgress: PropTypes.bool.isRequired
};
const mapStateToProps = state => ({
@@ -425,6 +455,7 @@ const mapStateToProps = state => ({
tutorials: state.tutorial.tutorials,
message: state.message,
user: state.auth.user,
+ authProgress: state.auth.progress
});
-export default connect(mapStateToProps, { checkError, readJSON, jsonString, progress, tutorialId, resetTutorialBuilder, getTutorials, resetTutorial, clearMessages, deleteTutorial })(withStyles(styles, { withTheme: true })(withRouter(Builder)));
+export default connect(mapStateToProps, { checkError, readJSON, jsonString, progress, tutorialId, resetTutorialBuilder, getTutorials, resetTutorial, tutorialProgress, clearMessages, deleteTutorial })(withStyles(styles, { withTheme: true })(withRouter(Builder)));
diff --git a/src/components/Tutorial/Tutorial.js b/src/components/Tutorial/Tutorial.js
index 189386c..edec484 100644
--- a/src/components/Tutorial/Tutorial.js
+++ b/src/components/Tutorial/Tutorial.js
@@ -23,7 +23,7 @@ class Tutorial extends Component {
componentDidMount() {
this.props.tutorialProgress();
- // retrieve tutorials only if a potential user is loaded - authentication
+ // retrieve tutorial only if a potential user is loaded - authentication
// is finished (success or failed)
if(!this.props.progress){
this.props.getTutorial(this.props.match.params.tutorialId);
diff --git a/src/components/User/MyBadges.js b/src/components/User/MyBadges.js
index 4d7dc47..0d55d4f 100644
--- a/src/components/User/MyBadges.js
+++ b/src/components/User/MyBadges.js
@@ -94,13 +94,20 @@ export class MyBadges extends Component {
getBadges = () => {
this.setState({progress: true});
- axios.get(`${process.env.REACT_APP_BLOCKLY_API}/user/badge`)
+ const config = {
+ success: res => {
+ this.setState({badges: res.data.badges, progress: false});
+ },
+ error: err => {
+ this.setState({progress: false});
+ }
+ };
+ axios.get(`${process.env.REACT_APP_BLOCKLY_API}/user/badge`, config)
.then(res => {
- this.setState({badges: res.data.badges, progress: false});
+ res.config.success(res);
})
.catch(err => {
- this.setState({progress: false});
- console.log(err);
+ err.config.error(err);
});
};
diff --git a/src/components/Workspace/SaveProject.js b/src/components/Workspace/SaveProject.js
index 0a46cf0..1a9ff3d 100644
--- a/src/components/Workspace/SaveProject.js
+++ b/src/components/Workspace/SaveProject.js
@@ -95,14 +95,22 @@ class SaveProject extends Component {
if(this.state.projectType === 'gallery'){
body.description = this.state.description;
}
- axios.post(`${process.env.REACT_APP_BLOCKLY_API}/${this.state.projectType}`, body)
- .then(res => {
+ const config = {
+ success: res => {
var project = res.data[this.state.projectType];
this.props.history.push(`/${this.state.projectType}/${project._id}`);
- })
- .catch(err => {
+ },
+ error: err => {
this.setState({ snackbar: true, key: Date.now(), message: `Fehler beim Speichern des ${this.state.projectType === 'gallery' ? 'Galerie-':''}Projektes. Versuche es noch einmal.`, type: 'error' });
window.scrollTo(0, 0);
+ }
+ };
+ axios.post(`${process.env.REACT_APP_BLOCKLY_API}/${this.state.projectType}`, body, config)
+ .then(res => {
+ res.config.success(res);
+ })
+ .catch(err => {
+ err.config.error(err);
});
}
From 42981a4f11db1313ce4fcd437552660e7965f104 Mon Sep 17 00:00:00 2001
From: Delucse <46593742+Delucse@users.noreply.github.com>
Date: Sun, 13 Dec 2020 20:52:23 +0100
Subject: [PATCH 03/16] badge selection
---
.env | 1 +
package.json | 2 +-
src/actions/authActions.js | 1 -
src/actions/tutorialBuilderActions.js | 7 +-
src/components/Tutorial/Builder/Badge.js | 189 +++++++++++++++++++++
src/components/Tutorial/Builder/Builder.js | 8 +-
src/reducers/tutorialBuilderReducer.js | 1 -
7 files changed, 201 insertions(+), 8 deletions(-)
create mode 100644 src/components/Tutorial/Builder/Badge.js
diff --git a/.env b/.env
index 3ba890f..81b9303 100644
--- a/.env
+++ b/.env
@@ -3,6 +3,7 @@ REACT_APP_BOARD=sensebox-mcu
REACT_APP_BLOCKLY_API=https://api.blockly.sensebox.de
REACT_APP_MYBADGES=https://mybadges.org
+REACT_APP_MYBADGES_API=https://mybadges.org/api/v1
# in days
REACT_APP_SHARE_LINK_EXPIRES=30
diff --git a/package.json b/package.json
index 60a336a..4a234e7 100644
--- a/package.json
+++ b/package.json
@@ -32,7 +32,7 @@
},
"scripts": {
"start": "react-scripts start",
- "dev": "set \"REACT_APP_BLOCKLY_API=http://localhost:8080\" && npm start",
+ "dev": "set \"REACT_APP_BLOCKLY_API=http://localhost:8080\" && set \"REACT_APP_MYBADGES_API=http://localhost:3001/api/v1\"&& npm start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
diff --git a/src/actions/authActions.js b/src/actions/authActions.js
index 8e97232..b5d6531 100644
--- a/src/actions/authActions.js
+++ b/src/actions/authActions.js
@@ -25,7 +25,6 @@ export const loadUser = () => (dispatch) => {
if(err.response){
dispatch(returnErrors(err.response.data.message, err.response.status));
}
- console.log('auth failed');
var status = [];
if (window.localStorage.getItem('status')) {
status = JSON.parse(window.localStorage.getItem('status'));
diff --git a/src/actions/tutorialBuilderActions.js b/src/actions/tutorialBuilderActions.js
index d7448f3..25f27b0 100644
--- a/src/actions/tutorialBuilderActions.js
+++ b/src/actions/tutorialBuilderActions.js
@@ -191,6 +191,9 @@ export const setSubmitError = () => (dispatch, getState) => {
if (builder.title === '') {
dispatch(setError(undefined, 'title'));
}
+ if (builder.title === null) {
+ dispatch(setError(undefined, 'badge'));
+ }
var type = builder.steps.map((step, i) => {
// media and xml are directly checked for errors in their components and
// therefore do not have to be checked again
@@ -230,7 +233,7 @@ export const setSubmitError = () => (dispatch, getState) => {
export const checkError = () => (dispatch, getState) => {
dispatch(setSubmitError());
var error = getState().builder.error;
- if (error.id || error.title || error.type) {
+ if (error.id || error.title || error.badge ||error.type) {
return true;
}
for (var i = 0; i < error.steps.length; i++) {
@@ -251,7 +254,7 @@ export const progress = (inProgress) => (dispatch) => {
export const resetTutorial = () => (dispatch, getState) => {
dispatch(jsonString(''));
dispatch(tutorialTitle(''));
- dispatch(tutorialBadge(''));
+ dispatch(tutorialBadge(undefined));
var steps = [
{
type: 'instruction',
diff --git a/src/components/Tutorial/Builder/Badge.js b/src/components/Tutorial/Builder/Badge.js
new file mode 100644
index 0000000..a2c08c5
--- /dev/null
+++ b/src/components/Tutorial/Builder/Badge.js
@@ -0,0 +1,189 @@
+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/Builder.js b/src/components/Tutorial/Builder/Builder.js
index ac773f6..bd4e8a0 100644
--- a/src/components/Tutorial/Builder/Builder.js
+++ b/src/components/Tutorial/Builder/Builder.js
@@ -12,6 +12,7 @@ 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';
@@ -190,7 +191,9 @@ 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);
@@ -348,7 +351,7 @@ class Builder extends Component {
: null}
{/* */}
-
+
{this.props.steps.map((step, i) =>
@@ -435,7 +438,6 @@ Builder.propTypes = {
change: PropTypes.number.isRequired,
error: PropTypes.object.isRequired,
json: PropTypes.string.isRequired,
- badge: PropTypes.string.isRequired,
isProgress: PropTypes.bool.isRequired,
tutorials: PropTypes.array.isRequired,
message: PropTypes.object.isRequired,
diff --git a/src/reducers/tutorialBuilderReducer.js b/src/reducers/tutorialBuilderReducer.js
index cad4c2e..bfbe654 100644
--- a/src/reducers/tutorialBuilderReducer.js
+++ b/src/reducers/tutorialBuilderReducer.js
@@ -5,7 +5,6 @@ const initialState = {
progress: false,
json: '',
title: '',
- badge: '',
id: '',
steps: [
{
From 7d1d2409e48cf6daa7776f374575dece5f84828f Mon Sep 17 00:00:00 2001
From: Mario
Date: Mon, 14 Dec 2020 08:51:31 +0100
Subject: [PATCH 04/16] add first translations
---
src/components/Blockly/msg/de.js | 147 ++++++++++++++++++
src/components/Blockly/msg/en.js | 83 ++++++++++
src/components/Blockly/toolbox/Toolbox.js | 16 +-
src/components/NotFound.js | 19 +--
src/components/Settings/LanguageSelector.js | 5 +-
src/components/Settings/RenderSelector.js | 4 +-
src/components/Settings/Settings.js | 8 +-
src/components/Tutorial/Assessment.js | 3 +-
src/components/Tutorial/Hardware.js | 6 +-
src/components/Tutorial/HintTutorialExists.js | 3 +-
src/components/Workspace/Compile.js | 7 +-
src/components/Workspace/DeleteProject.js | 11 +-
src/components/Workspace/DownloadProject.js | 4 +-
src/components/Workspace/OpenProject.js | 4 +-
src/components/Workspace/ResetWorkspace.js | 4 +-
src/components/Workspace/SaveProject.js | 43 ++---
src/components/Workspace/Screenshot.js | 2 +-
src/components/Workspace/ShareProject.js | 35 +++--
src/components/Workspace/TrashcanButtons.js | 18 +--
src/components/Workspace/WorkspaceName.js | 25 +--
20 files changed, 344 insertions(+), 103 deletions(-)
diff --git a/src/components/Blockly/msg/de.js b/src/components/Blockly/msg/de.js
index 2dec197..cca4e12 100644
--- a/src/components/Blockly/msg/de.js
+++ b/src/components/Blockly/msg/de.js
@@ -800,4 +800,151 @@ Blockly.Msg.senseBox_mqtt_password = "Passwort";
Blockly.Msg.sensebox_mqtt_subscribe = "Subscribe to Feed"
Blockly.Msg.senseBox_mqtt_publish = "Sende an Feed/Topic";
+
+
+/**
+ * Typed Variable Modal
+ *
+ */
+
+
+Blockly.Msg.TYPED_VAR_MODAL_CONFIRM_BUTTON = "Ok";
+Blockly.Msg.TYPED_VAR_MODAL_VARIABLE_NAME_LABEL = "Variablen Name: ";
+Blockly.Msg.TYPED_VAR_MODAL_TYPES_LABEL = "Variable Typen";
+Blockly.Msg.TYPED_VAR_MODAL_CANCEL_BUTTON = "Abbrechen";
+Blockly.Msg.TYPED_VAR_MODAL_TITLE = "Erstelle Variable";
+Blockly.Msg.TYPED_VAR_MODAL_INVALID_NAME = "Der Name ist ungültig, bitte versuche einen anderen."
+
+/**
+ * Add Translation for Blocks above
+ * ---------------------------------------------------------------
+ * Add Translation for the UI below
+ */
+
+/**
+ * Toolbox
+ */
+Blockly.Msg.toolbox_sensors = "Sensoren";
+Blockly.Msg.toolbox_logic = "Logik";
+Blockly.Msg.toolbox_loops = "Schleifen";
+Blockly.Msg.toolbox_math = "Mathematik";
+Blockly.Msg.toolbox_io = "Eingang/Ausgang";
+Blockly.Msg.toolbox_time = "Zeit";
+Blockly.Msg.toolbox_functions = "Funktionen";
+Blockly.Msg.toolbox_variables = "Variablen";
+
+/**
+ * Tooltips
+ *
+ */
+
+Blockly.Msg.tooltip_compile_code = "Code kompilieren"
+Blockly.Msg.tooltip_save_blocks = "Blöcke speichern";
+Blockly.Msg.tooltip_open_blocks = "Blöcke öffnen";
+Blockly.Msg.tooltip_screenshot = "Screenshot erstellen";
+Blockly.Msg.tooltip_clear_workspace = "Workspace zurücksetzen";
+Blockly.Msg.tooltip_share_blocks = "Blöcke teilen";
+Blockly.Msg.tooltip_show_code = "Code anzeigen";
+Blockly.Msg.tooltip_hide_code = "Code ausblenden"
+Blockly.Msg.tooltip_delete_project = "Projekt löschen"
+Blockly.Msg.tooltip_project_name = "Name des Projektes"
+Blockly.Msg.tooltip_download_project = "Projekt herunterladen"
+Blockly.Msg.tooltip_open_project = "Projekt öffnen"
+Blockly.Msg.tooltip_update_project = "Projekt aktualisieren"
+Blockly.Msg.tooltip_save_project = "Projekt speichern"
+Blockly.Msg.tooltip_create_project = "Projekt erstellen"
+Blockly.Msg.tooltip_share_project = "Projekt teilen"
+Blockly.Msg.tooltip_reset_workspace = "Workspace zurücksetzen"
+Blockly.Msg.tooltip_copy_link = "Link kopieren"
+Blockly.Msg.tooltip_trashcan_hide = 'gelöschte Blöcke ausblenden'
+Blockly.Msg.tooltip_trashcan_delete = 'Blöcke endgültig löschen'
+Blockly.Msg.tooltip_project_title = "Titel des Projektes"
+
+
+/**
+ * Messages
+ *
+ */
+
+Blockly.Msg.messages_delete_project_failed = "Fehler beim Löschen des Projektes. Versuche es noch einmal."
+Blockly.Msg.messages_reset_workspace_success = "Das Projekt wurde erfolgreich zurückgesetzt"
+Blockly.Msg.messages_PROJECT_UPDATE_SUCCESS = "Das Projekt wurde erfolgreich aktualisiert."
+Blockly.Msg.messages_GALLERY_UPDATE_SUCCESS = "Das Galerie-Projekt wurde erfolgreich aktualisiert."
+Blockly.Msg.messages_PROJECT_UPDATE_FAIL = "Fehler beim Aktualisieren des Projektes. Versuche es noch einmal."
+Blockly.Msg.messages_GALLERY_UPDATE_FAIL = "Fehler beim Aktualisieren des Galerie-Projektes. Versuche es noch einmal."
+Blockly.Msg.messages_gallery_save_fail_1 = "Fehler beim Speichern des "
+Blockly.Msg.messages_gallery_save_fail_2 = "Projektes. Versuche es noch einmal."
+Blockly.Msg.messages_SHARE_SUCCESS = 'Programm teilen'
+Blockly.Msg.messages_SHARE_FAIL = "Fehler beim Erstellen eines Links zum Teilen deines Programmes. Versuche es noch einmal."
+Blockly.Msg.messages_copylink_success = 'Link erfolgreich in Zwischenablage gespeichert.'
+Blockly.Msg.messages_rename_success_01 = 'Das Projekt wurde erfolgreich in '
+Blockly.Msg.messages_rename_success_02 = 'umbenannt.'
+/**
+ * Share Dialog
+ */
+
+Blockly.Msg.sharedialog_headline = "Dein Link wurde erstellt.";
+Blockly.Msg.sharedialog_text = "Über den folgenden Link kannst du dein Programm teilen.";
+
+/**
+ * Project rename Dialog
+ */
+
+Blockly.Msg.renamedialog_headline = "Projekt benennen";
+Blockly.Msg.renamedialog_text = "Bitte gib einen Namen für das Projekt ein und bestätige diesen mit einem Klick auf 'Bestätigen'."
+
+/**
+ * Compile Dialog
+ *
+ */
+
+Blockly.Msg.compiledialog_headline = "Fehler"
+Blockly.Msg.compiledialog_text = "Beim kompilieren ist ein Fehler aufgetreten. Überprüfe deine Blöcke und versuche es erneut"
+
+/**
+ * Buttons
+ *
+ */
+
+Blockly.Msg.button_cancel = "Abbrechen";
+Blockly.Msg.button_close = "Schließen";
+Blockly.Msg.button_accept = "Bestätigen";
+Blockly.Msg.button_compile = "Kompilieren";
+Blockly.Msg.button_create_variableCreate = "Erstelle Variable";
+Blockly.Msg.button_back = "Zurück"
+
+
+/**
+ *
+ */
+
+Blockly.Msg.filename = "Dateiname";
+Blockly.Msg.projectname = "Projektname";
+
+/**
+ * Settings
+ */
+Blockly.Msg.settings_head = "Einstellungen"
+Blockly.Msg.settings_language = "Sprache"
+Blockly.Msg.settings_language_de = "Deutsch"
+Blockly.Msg.settings_language_en = "Englisch"
+Blockly.Msg.settings_renderer_text = "Der Renderer bestimmt das aussehen der Blöcke"
+
+/**
+ * 404
+ */
+
+Blockly.Msg.notfound_head = "Die von Ihnen angeforderte Seite kann nicht gefunden werden."
+Blockly.Msg.notfound_text = "Die gesuchte Seite wurde möglicherweise entfernt, ihr Name wurde geändert oder sie ist vorübergehend nicht verfügbar."
+
+
+/**
+ * Tutorials
+ */
+
+Blockly.Msg.tutorials_assessment_task = "Aufgabe"
+Blockly.Msg.tutorials_hardware_head = "Für die Umsetzung benötigst du folgende Hardware:"
+Blockly.Msg.tutorials_hardware_moreInformation = "Weitere Informationen zur Hardware-Komponente findest du"
+Blockly.Msg.tutorials_hardware_here = "hier"
+
export const De = Blockly.Msg;
diff --git a/src/components/Blockly/msg/en.js b/src/components/Blockly/msg/en.js
index 696d68e..6479613 100644
--- a/src/components/Blockly/msg/en.js
+++ b/src/components/Blockly/msg/en.js
@@ -782,4 +782,87 @@ Blockly.Msg.senseBox_mqtt_password = "Password";
Blockly.Msg.sensebox_mqtt_subscribe = "Subscribe to Feed"
Blockly.Msg.senseBox_mqtt_publish = "Publish to Feed/Topic";
+
+/**
+ * Add Translation for Blocks above
+ * ---------------------------------------------------------------
+ * Add Translation for the UI below
+ */
+
+
+/**
+ * Toolbox
+ */
+Blockly.Msg.toolbox_sensors = "Sensors";
+Blockly.Msg.toolbox_logic = "Logic";
+Blockly.Msg.toolbox_loops = "Loops";
+Blockly.Msg.toolbox_math = "Math";
+Blockly.Msg.toolbox_io = "Input/Output";
+Blockly.Msg.toolbox_time = "Time";
+Blockly.Msg.toolbox_functions = "Functions";
+Blockly.Msg.toolbox_variables = "Variables";
+
+
+/**
+ * Tooltips
+ *
+ */
+
+Blockly.Msg.tooltip_compile_code = "Compile Code"
+Blockly.Msg.tooltip_save_blocks = "Save Blocks";
+Blockly.Msg.tooltip_open_blocks = "Open Blocks";
+Blockly.Msg.tooltip_screenshot = "Download Screenshot";
+Blockly.Msg.tooltip_clear_workspace = "Reset Workspace";
+Blockly.Msg.tooltip_share_blocks = "Share Blocks";
+Blockly.Msg.tooltip_show_code = "Show Code";
+Blockly.Msg.tooltip_hide_code = "Hide Code"
+
+Blockly.Msg.tooltip_project_name = "Projectname"
+/**
+ * Share Dialog
+ */
+
+Blockly.Msg.sharedialog_headline = "Your Share-Link was created";
+Blockly.Msg.sharedialog_text = "Share your project with the following link";
+
+/**
+ * Project rename Dialog
+ */
+
+Blockly.Msg.renamedialog_headline = "Rename Project";
+Blockly.Msg.renamedialog_text = "Please enter a name for the project and confirm it by clicking on 'Confirm'."
+
+/**
+ * Compile Dialog
+ *
+ */
+
+Blockly.Msg.compiledialog_headline = "Error"
+Blockly.Msg.compiledialog_text = "While compiling an error occured. Please check your blocks and try again"
+
+
+
+/**
+ * Buttons
+ *
+ */
+
+Blockly.Msg.button_cancel = "Cancel";
+Blockly.Msg.button_close = "Close";
+Blockly.Msg.button_accept = "Confirm";
+Blockly.Msg.button_compile = "Compile";
+Blockly.Msg.button_create_variableCreate = "Create Variable";
+
+
+/**
+ *
+ */
+
+Blockly.Msg.filename = "Filename";
+Blockly.Msg.projectname = "Projectname";
+
+
+
+
+
export const En = Blockly.Msg;
diff --git a/src/components/Blockly/toolbox/Toolbox.js b/src/components/Blockly/toolbox/Toolbox.js
index 47fede7..cce1097 100644
--- a/src/components/Blockly/toolbox/Toolbox.js
+++ b/src/components/Blockly/toolbox/Toolbox.js
@@ -38,7 +38,7 @@ class Toolbox extends React.Component {
render() {
return (
-
+
@@ -301,7 +301,7 @@ class Toolbox extends React.Component {
{/* */}
-
+
@@ -310,7 +310,7 @@ class Toolbox extends React.Component {
-
+
@@ -349,7 +349,7 @@ class Toolbox extends React.Component {
-
+
@@ -369,7 +369,7 @@ class Toolbox extends React.Component {
-
+
@@ -422,15 +422,15 @@ class Toolbox extends React.Component {
-
+
-
+
-
+
diff --git a/src/components/NotFound.js b/src/components/NotFound.js
index 85a9c6f..eb790f4 100644
--- a/src/components/NotFound.js
+++ b/src/components/NotFound.js
@@ -6,31 +6,32 @@ 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 {
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 ?
{this.props.history.push(this.props.button.link)}}
+ onClick={() => { this.props.history.push(this.props.button.link) }}
>
{this.props.button.title}
- :
+ :
{this.props.history.push('/')}}
+ onClick={() => { this.props.history.push('/') }}
>
- Zurück zur Startseite
+ {Blockly.Msg.button_back}
}
diff --git a/src/components/Settings/LanguageSelector.js b/src/components/Settings/LanguageSelector.js
index dea7465..7da299c 100644
--- a/src/components/Settings/LanguageSelector.js
+++ b/src/components/Settings/LanguageSelector.js
@@ -4,6 +4,7 @@ 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 * as Blockly from 'blockly/core';
const useStyles = makeStyles((theme) => ({
formControl: {
@@ -27,7 +28,7 @@ export default function LanguageSelector() {
return (
- Sprache
+ {Blockly.Msg.settings_language}
Deutsch
- English
+ Englisch
diff --git a/src/components/Settings/RenderSelector.js b/src/components/Settings/RenderSelector.js
index 5cf7a9f..d8284b6 100644
--- a/src/components/Settings/RenderSelector.js
+++ b/src/components/Settings/RenderSelector.js
@@ -4,7 +4,7 @@ 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 * as Blockly from 'blockly/core'
const useStyles = makeStyles((theme) => ({
formControl: {
margin: theme.spacing(1),
@@ -39,7 +39,7 @@ export default function RenderSelector() {
Zelos
- Der Renderer bestimmt das aussehen der Blöcke
+ {Blockly.Msg.settings_renderer_text}
);
}
diff --git a/src/components/Settings/Settings.js b/src/components/Settings/Settings.js
index cbbedc9..d43f33f 100644
--- a/src/components/Settings/Settings.js
+++ b/src/components/Settings/Settings.js
@@ -6,13 +6,13 @@ import Typography from '@material-ui/core/Typography';
import LanguageSelector from './LanguageSelector';
import RenderSelector from './RenderSelector';
import StatsSelector from './StatsSelector';
-
+import * as Blockly from 'blockly'
class Settings extends Component {
render() {
return (
- Einstellungen
+ {Blockly.Msg.settings_head}
@@ -22,8 +22,8 @@ class Settings extends Component {
color="primary"
onClick={() => { this.props.history.push('/') }}
>
- Zurück zur Startseite
-
+ {Blockly.Msg.button_back}
+
);
};
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/Hardware.js b/src/components/Tutorial/Hardware.js
index 35602bb..d91b0a0 100644
--- a/src/components/Tutorial/Hardware.js
+++ b/src/components/Tutorial/Hardware.js
@@ -15,7 +15,7 @@ import GridListTileBar from '@material-ui/core/GridListTileBar';
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faExpandAlt } from "@fortawesome/free-solid-svg-icons";
-
+import * as Blockly from 'blockly'
const styles = theme => ({
expand: {
'&:hover': {
@@ -56,7 +56,7 @@ class Hardware extends Component {
var cols = isWidthDown('md', this.props.width) ? isWidthDown('sm', this.props.width) ? isWidthDown('xs', this.props.width) ? 2 : 3 : 4 : 6;
return (
-
Für die Umsetzung benötigst du folgende Hardware:
+
{Blockly.Msg.tutorials_hardware_head}
{this.props.picture.map((picture, i) => {
@@ -95,7 +95,7 @@ class Hardware extends Component {
>
- Weitere Informationen zur Hardware-Komponente findest du
hier.
+ {Blockly.Msg.tutorials_hardware_moreInformation}
{Blockly.Msg.tutorials_hardware_here}.
diff --git a/src/components/Tutorial/HintTutorialExists.js b/src/components/Tutorial/HintTutorialExists.js
index 4b1fa2d..afd1468 100644
--- a/src/components/Tutorial/HintTutorialExists.js
+++ b/src/components/Tutorial/HintTutorialExists.js
@@ -9,6 +9,7 @@ import Dialog from '../Dialog';
import { withStyles } from '@material-ui/core/styles';
import Checkbox from '@material-ui/core/Checkbox';
import FormControlLabel from '@material-ui/core/FormControlLabel';
+import * as Blockly from 'blockly'
const styles = (theme) => ({
link: {
@@ -60,7 +61,7 @@ class HintTutorialExists extends Component {
content={''}
onClose={this.toggleDialog}
onClick={this.toggleDialog}
- button={'Schließen'}
+ button={Blockly.Msg.button_close}
>
Es gibt ab jetzt Tutorials zu verschiedenen Themen. Schau mal
hier vorbei.
diff --git a/src/components/Workspace/Compile.js b/src/components/Workspace/Compile.js
index f8a204a..648931f 100644
--- a/src/components/Workspace/Compile.js
+++ b/src/components/Workspace/Compile.js
@@ -17,6 +17,7 @@ import TextField from '@material-ui/core/TextField';
import { faClipboardCheck } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
+import * as Blockly from 'blockly/core';
const styles = (theme) => ({
backdrop: {
@@ -85,7 +86,7 @@ class Compile extends Component {
})
.catch(err => {
console.log(err);
- this.setState({ progress: false, file: false, open: true, title: 'Fehler', content: 'Etwas ist beim Kompilieren schief gelaufen. Versuche es nochmal.' });
+ this.setState({ progress: false, file: false, open: true, title: Blockly.Msg.compiledialog_headline, content: Blockly.Msg.compiledialog_text });
});
}
@@ -119,7 +120,7 @@ class Compile extends Component {
return (
{this.props.iconButton ?
-
+
this.compile()}
@@ -141,7 +142,7 @@ class Compile extends Component {
content={this.state.content}
onClose={this.toggleDialog}
onClick={this.state.file ? () => { this.toggleDialog(); this.setState({ name: this.props.name }) } : this.toggleDialog}
- button={this.state.file ? 'Abbrechen' : 'Schließen'}
+ button={this.state.file ? Blockly.Msg.button_cancel : Blockly.Msg.button_close}
>
{this.state.file ?
diff --git a/src/components/Workspace/DeleteProject.js b/src/components/Workspace/DeleteProject.js
index 3df813d..4566916 100644
--- a/src/components/Workspace/DeleteProject.js
+++ b/src/components/Workspace/DeleteProject.js
@@ -13,6 +13,7 @@ import Tooltip from '@material-ui/core/Tooltip';
import { faTrashAlt } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
+import * as Blockly from 'blockly/core';
const styles = (theme) => ({
buttonTrash: {
@@ -43,12 +44,12 @@ class DeleteProject extends Component {
}
componentDidUpdate(props) {
- if(this.props.message !== props.message){
- if(this.props.message.id === 'PROJECT_DELETE_SUCCESS'){
+ if (this.props.message !== props.message) {
+ if (this.props.message.id === 'PROJECT_DELETE_SUCCESS') {
this.props.history.push(`/${this.props.projectType}`);
}
- else if(this.props.message.id === 'PROJECT_DELETE_FAIL'){
- this.setState({ snackbar: true, key: Date.now(), message: `Fehler beim Löschen des Projektes. Versuche es noch einmal.`, type: 'error' });
+ else if (this.props.message.id === 'PROJECT_DELETE_FAIL') {
+ this.setState({ snackbar: true, key: Date.now(), message: Blockly.Msg.messages_delete_project_failed, type: 'error' });
}
}
}
@@ -56,7 +57,7 @@ class DeleteProject extends Component {
render() {
return (
-
+
this.props.deleteProject(this.props.projectType, this.props.project._id)}
diff --git a/src/components/Workspace/DownloadProject.js b/src/components/Workspace/DownloadProject.js
index 9b30273..1315625 100644
--- a/src/components/Workspace/DownloadProject.js
+++ b/src/components/Workspace/DownloadProject.js
@@ -12,6 +12,8 @@ import Tooltip from '@material-ui/core/Tooltip';
import { faFileDownload } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
+import * as Blockly from 'blockly/core';
+
const styles = (theme) => ({
button: {
@@ -40,7 +42,7 @@ class DownloadProject extends Component {
render() {
return (
-
+
this.downloadXmlFile()}
diff --git a/src/components/Workspace/OpenProject.js b/src/components/Workspace/OpenProject.js
index 6038a49..9045a32 100644
--- a/src/components/Workspace/OpenProject.js
+++ b/src/components/Workspace/OpenProject.js
@@ -97,7 +97,7 @@ class OpenProject extends Component {
type="file"
/>
-
+
-
+
this.resetWorkspace()}
diff --git a/src/components/Workspace/SaveProject.js b/src/components/Workspace/SaveProject.js
index 0a46cf0..c10faef 100644
--- a/src/components/Workspace/SaveProject.js
+++ b/src/components/Workspace/SaveProject.js
@@ -14,13 +14,14 @@ import Button from '@material-ui/core/Button';
import IconButton from '@material-ui/core/IconButton';
import Tooltip from '@material-ui/core/Tooltip';
import TextField from '@material-ui/core/TextField';
-import Typography from '@material-ui/core/Typography';
import Menu from '@material-ui/core/Menu';
import MenuItem from '@material-ui/core/MenuItem';
import { faSave } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
+import * as Blockly from 'blockly/core'
+
const styles = (theme) => ({
button: {
backgroundColor: theme.palette.primary.main,
@@ -63,18 +64,18 @@ class SaveProject extends Component {
if (props.description !== this.props.description) {
this.setState({ description: this.props.description });
}
- if(this.props.message !== props.message){
- if(this.props.message.id === 'PROJECT_UPDATE_SUCCESS'){
- this.setState({ snackbar: true, key: Date.now(), message: `Das Projekt wurde erfolgreich aktualisiert.`, type: 'success' });
+ if (this.props.message !== props.message) {
+ if (this.props.message.id === 'PROJECT_UPDATE_SUCCESS') {
+ this.setState({ snackbar: true, key: Date.now(), message: Blockly.Msg.messages_PROJECT_UPDATE_SUCCESS, type: 'success' });
}
- else if(this.props.message.id === 'GALLERY_UPDATE_SUCCESS'){
- this.setState({ snackbar: true, key: Date.now(), message: `Das Galerie-Projekt wurde erfolgreich aktualisiert.`, type: 'success' });
+ else if (this.props.message.id === 'GALLERY_UPDATE_SUCCESS') {
+ this.setState({ snackbar: true, key: Date.now(), message: Blockly.Msg.messages_GALLERY_UPDATE_SUCCESS, type: 'success' });
}
- else if(this.props.message.id === 'PROJECT_UPDATE_FAIL'){
- this.setState({ snackbar: true, key: Date.now(), message: `Fehler beim Aktualisieren des Projektes. Versuche es noch einmal.`, type: 'error' });
+ else if (this.props.message.id === 'PROJECT_UPDATE_FAIL') {
+ this.setState({ snackbar: true, key: Date.now(), message: Blockly.Msg.messages_PROJECT_UPDATE_FAIL, type: 'error' });
}
- else if(this.props.message.id === 'GALLERY_UPDATE_FAIL'){
- this.setState({ snackbar: true, key: Date.now(), message: `Fehler beim Aktualisieren des Galerie-Projektes. Versuche es noch einmal.`, type: 'error' });
+ else if (this.props.message.id === 'GALLERY_UPDATE_FAIL') {
+ this.setState({ snackbar: true, key: Date.now(), message: Blockly.Msg.messages_GALLERY_UPDATE_FAIL, type: 'error' });
}
}
}
@@ -92,7 +93,7 @@ class SaveProject extends Component {
xml: this.props.xml,
title: this.props.name
};
- if(this.state.projectType === 'gallery'){
+ if (this.state.projectType === 'gallery') {
body.description = this.state.description;
}
axios.post(`${process.env.REACT_APP_BLOCKLY_API}/${this.state.projectType}`, body)
@@ -101,7 +102,7 @@ class SaveProject extends Component {
this.props.history.push(`/${this.state.projectType}/${project._id}`);
})
.catch(err => {
- this.setState({ snackbar: true, key: Date.now(), message: `Fehler beim Speichern des ${this.state.projectType === 'gallery' ? 'Galerie-':''}Projektes. Versuche es noch einmal.`, type: 'error' });
+ this.setState({ snackbar: true, key: Date.now(), message: `${Blockly.Msg.messages_gallery_save_fail_1} ${this.state.projectType === 'gallery' ? 'Galerie-' : ''} ${Blockly.Msg.messages_gallery_save_fail_2}`, type: 'error' });
window.scrollTo(0, 0);
});
}
@@ -112,7 +113,7 @@ class SaveProject extends Component {
workspaceDescription = () => {
this.props.setDescription(this.state.description);
- this.setState({projectType: 'gallery'},
+ this.setState({ projectType: 'gallery' },
() => this.saveProject()
);
}
@@ -121,10 +122,10 @@ class SaveProject extends Component {
console.log(1, this.props);
return (
-
+
this.toggleMenu(e) : this.state.projectType === 'project' ? () => this.props.updateProject(this.state.projectType, this.props.project._id) : () => {this.setState({projectType: 'project'}, () => this.saveProject())}}
+ onClick={this.props.user.blocklyRole !== 'user' && (!this.props.project || this.props.user.email === this.props.project.creator) ? (e) => this.toggleMenu(e) : this.state.projectType === 'project' ? () => this.props.updateProject(this.state.projectType, this.props.project._id) : () => { this.setState({ projectType: 'project' }, () => this.saveProject()) }}
>
@@ -144,12 +145,12 @@ class SaveProject extends Component {
onClose={this.toggleMenu}
>
{this.toggleMenu(e); this.props.updateProject(this.state.projectType, this.props.project._id)} : (e) => {this.toggleMenu(e); this.setState({projectType: 'project'}, () => this.saveProject())}}
+ onClick={this.state.projectType === 'project' ? (e) => { this.toggleMenu(e); this.props.updateProject(this.state.projectType, this.props.project._id) } : (e) => { this.toggleMenu(e); this.setState({ projectType: 'project' }, () => this.saveProject()) }}
>
- {this.state.projectType === 'project' ? 'Projekt aktualisieren' : 'Projekt erstellen'}
+ {this.state.projectType === 'project' ? Blockly.Msg.tooltip_update_project : Blockly.Msg.tooltip_create_project}
{this.toggleMenu(e); this.props.updateProject(this.state.projectType, this.props.project._id)} : (e) => {this.toggleMenu(e); this.setState({ open: true, title: 'Projekbeschreibung ergänzen', content: 'Bitte gib eine Beschreibung für das Galerie-Projekt ein und bestätige deine Angabe mit einem Klick auf \'Eingabe\'.'});}}
+ onClick={this.state.projectType === 'gallery' ? (e) => { this.toggleMenu(e); this.props.updateProject(this.state.projectType, this.props.project._id) } : (e) => { this.toggleMenu(e); this.setState({ open: true, title: 'Projekbeschreibung ergänzen', content: 'Bitte gib eine Beschreibung für das Galerie-Projekt ein und bestätige deine Angabe mit einem Klick auf \'Eingabe\'.' }); }}
>
{this.state.projectType === 'gallery' ? 'Galerie-Projekt aktualisieren' : 'Galerie-Projekt erstellen'}
@@ -165,13 +166,13 @@ class SaveProject extends Component {
open={this.state.open}
title={this.state.title}
content={this.state.content}
- onClose={() => {this.toggleDialog(); this.setState({ description: this.props.description });}}
- onClick={() => {this.toggleDialog(); this.setState({ description: this.props.description });}}
+ onClose={() => { this.toggleDialog(); this.setState({ description: this.props.description }); }}
+ onClick={() => { this.toggleDialog(); this.setState({ description: this.props.description }); }}
button={'Abbrechen'}
>
- {this.workspaceDescription(); this.toggleDialog();}}>Eingabe
+ { this.workspaceDescription(); this.toggleDialog(); }}>Eingabe
diff --git a/src/components/Workspace/Screenshot.js b/src/components/Workspace/Screenshot.js
index c150db2..3dfc29b 100644
--- a/src/components/Workspace/Screenshot.js
+++ b/src/components/Workspace/Screenshot.js
@@ -73,7 +73,7 @@ class Screenshot extends Component {
render() {
return (
-
+
this.getSvg()}
diff --git a/src/components/Workspace/ShareProject.js b/src/components/Workspace/ShareProject.js
index 060e0e9..4eb487b 100644
--- a/src/components/Workspace/ShareProject.js
+++ b/src/components/Workspace/ShareProject.js
@@ -19,6 +19,8 @@ import Typography from '@material-ui/core/Typography';
import { faShareAlt, faCopy } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
+import * as Blockly from 'blockly/core';
+
const styles = (theme) => ({
button: {
backgroundColor: theme.palette.primary.main,
@@ -59,18 +61,18 @@ class WorkspaceFunc extends Component {
}
componentDidUpdate(props) {
- if(this.props.message !== props.message){
- if(this.props.message.id === 'SHARE_SUCCESS' && (!this.props.multiple || this.props.message.status === this.props.project._id)){
- this.setState({ share: true, open: true, title: 'Programm teilen', id: this.props.message.status });
+ if (this.props.message !== props.message) {
+ if (this.props.message.id === 'SHARE_SUCCESS' && (!this.props.multiple || this.props.message.status === this.props.project._id)) {
+ this.setState({ share: true, open: true, title: Blockly.Msg.messages_SHARE_SUCCESS, id: this.props.message.status });
}
- else if(this.props.message.id === 'SHARE_FAIL' && (!this.props.multiple || this.props.message.status === this.props.project._id)){
- this.setState({ snackbar: true, key: Date.now(), message: `Fehler beim Erstellen eines Links zum Teilen deines Programmes. Versuche es noch einmal.`, type: 'error' });
+ else if (this.props.message.id === 'SHARE_FAIL' && (!this.props.multiple || this.props.message.status === this.props.project._id)) {
+ this.setState({ snackbar: true, key: Date.now(), message: Blockly.Msg.messages_SHARE_FAIL, type: 'error' });
window.scrollTo(0, 0);
}
}
}
- componentWillUnmount(){
+ componentWillUnmount() {
this.props.clearMessages();
}
@@ -79,9 +81,9 @@ class WorkspaceFunc extends Component {
}
shareBlocks = () => {
- if(this.props.projectType === 'project' && this.props.project.shared){
+ if (this.props.projectType === 'project' && this.props.project.shared) {
// project is already shared
- this.setState({ open: true, title: 'Programm teilen', id: this.props.project._id });
+ this.setState({ open: true, title: Blockly.Msg.messages_SHARE_SUCCESS, id: this.props.project._id });
}
else {
this.props.shareProject(this.props.name || this.props.project.title, this.props.projectType, this.props.project ? this.props.project._id : undefined);
@@ -91,7 +93,7 @@ class WorkspaceFunc extends Component {
render() {
return (
-
+
this.shareBlocks()}
@@ -112,29 +114,28 @@ class WorkspaceFunc extends Component {
content={this.state.content}
onClose={this.toggleDialog}
onClick={this.toggleDialog}
- button={'Schließen'}
+ button={Blockly.Msg.button_close}
>
Über den folgenden Link kannst du dein Programm teilen:
this.toggleDialog()} className={this.props.classes.link}>{`${window.location.origin}/share/${this.state.id}`}
-
+
{
navigator.clipboard.writeText(`${window.location.origin}/share/${this.state.id}`);
- this.setState({ snackbar: true, key: Date.now(), message: 'Link erfolgreich in Zwischenablage gespeichert.', type: 'success' });
+ this.setState({ snackbar: true, key: Date.now(), message: Blockly.Msg.messages_copylink_success, type: 'success' });
}}
>
{this.props.project && this.props.project.shared && this.props.message.id !== 'SHARE_SUCCESS' ?
- {`Das Projekt wurde bereits geteilt. Der Link ist noch mindestens ${
- moment(this.props.project.shared).diff(moment().utc(), 'days') === 0 ?
- moment(this.props.project.shared).diff(moment().utc(), 'hours') === 0 ?
- `${moment(this.props.project.shared).diff(moment().utc(), 'minutes')} Minuten`
+ {`Das Projekt wurde bereits geteilt. Der Link ist noch mindestens ${moment(this.props.project.shared).diff(moment().utc(), 'days') === 0 ?
+ moment(this.props.project.shared).diff(moment().utc(), 'hours') === 0 ?
+ `${moment(this.props.project.shared).diff(moment().utc(), 'minutes')} Minuten`
: `${moment(this.props.project.shared).diff(moment().utc(), 'hours')} Stunden`
: `${moment(this.props.project.shared).diff(moment().utc(), 'days')} Tage`} gültig.`}
- : {`Der Link ist nun ${process.env.REACT_APP_SHARE_LINK_EXPIRES} Tage gültig.`} }
+ : {`Der Link ist nun ${process.env.REACT_APP_SHARE_LINK_EXPIRES} Tage gültig.`} }
diff --git a/src/components/Workspace/TrashcanButtons.js b/src/components/Workspace/TrashcanButtons.js
index 2545d59..de23cb9 100644
--- a/src/components/Workspace/TrashcanButtons.js
+++ b/src/components/Workspace/TrashcanButtons.js
@@ -36,8 +36,8 @@ class TrashcanButtons extends Component {
componentDidUpdate(previousProps, previousState) {
const workspace = Blockly.getMainWorkspace();
const contentsIsOpen = workspace.trashcan.contentsIsOpen();
- if(previousState.closeTrashFlyout !== contentsIsOpen){
- this.setState({ closeTrashFlyout: contentsIsOpen });
+ if (previousState.closeTrashFlyout !== contentsIsOpen) {
+ this.setState({ closeTrashFlyout: contentsIsOpen });
}
}
@@ -59,26 +59,26 @@ class TrashcanButtons extends Component {
return (
this.state.closeTrashFlyout ?
-
+
this.closeTrashcan()}
>
-
+
-
+
this.clearTrashcan()}
>
-
+
- : null
+ : null
);
};
}
diff --git a/src/components/Workspace/WorkspaceName.js b/src/components/Workspace/WorkspaceName.js
index 9efe915..0437f9a 100644
--- a/src/components/Workspace/WorkspaceName.js
+++ b/src/components/Workspace/WorkspaceName.js
@@ -16,6 +16,7 @@ import Typography from '@material-ui/core/Typography';
import { faPen } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
+import * as Blockly from 'blockly/core'
const styles = (theme) => ({
workspaceName: {
@@ -72,31 +73,31 @@ class WorkspaceName extends Component {
renameWorkspace = () => {
this.props.workspaceName(this.state.name);
this.toggleDialog();
- if(this.props.projectType === 'project' || this.props.projectType === 'gallery' || this.state.projectType === 'gallery'){
- if(this.props.projectType === 'gallery' || this.state.projectType === 'gallery'){
+ if (this.props.projectType === 'project' || this.props.projectType === 'gallery' || this.state.projectType === 'gallery') {
+ if (this.props.projectType === 'gallery' || this.state.projectType === 'gallery') {
this.props.setDescription(this.state.description);
}
- if(this.state.projectType === 'gallery'){
+ if (this.state.projectType === 'gallery') {
this.saveGallery();
} else {
this.props.updateProject(this.props.projectType, this.props.project._id);
}
} else {
- this.setState({ snackbar: true, type: 'success', key: Date.now(), message: `Das Projekt wurde erfolgreich in '${this.state.name}' umbenannt.` });
+ this.setState({ snackbar: true, type: 'success', key: Date.now(), message: `${Blockly.Msg.messages_rename_success_01} ${this.state.name} ${Blockly.Msg.messages_rename_success_02}` });
}
}
render() {
return (
-
+
{if(this.props.multiple){this.props.workspaceName(this.props.project.title);if(this.props.projectType === 'gallery'){this.props.setDescription(this.props.project.description);}} this.setState({ open: true, title: this.props.projectType === 'gallery' ? 'Projektdaten ändern': this.props.projectType === 'project' ? 'Projekt umbenennen' : 'Projekt benennen', content: this.props.projectType === 'gallery' ? 'Bitte gib einen Titel und eine Beschreibung für das Galerie-Projekt ein und bestätige die Angaben mit einem Klick auf \'Eingabe\'.':'Bitte gib einen Namen für das Projekt ein und bestätige diesen mit einem Klick auf \'Eingabe\'.' }) }}
+ onClick={() => { if (this.props.multiple) { this.props.workspaceName(this.props.project.title); if (this.props.projectType === 'gallery') { this.props.setDescription(this.props.project.description); } } this.setState({ open: true, title: this.props.projectType === 'gallery' ? 'Projektdaten ändern' : this.props.projectType === 'project' ? 'Projekt umbenennen' : 'Projekt benennen', content: this.props.projectType === 'gallery' ? 'Bitte gib einen Titel und eine Beschreibung für das Galerie-Projekt ein und bestätige die Angaben mit einem Klick auf \'Eingabe\'.' : 'Bitte gib einen Namen für das Projekt ein und bestätige diesen mit einem Klick auf \'Eingabe\'.' }) }}
>
- {this.props.name && !isWidthDown(this.props.projectType === 'project' || this.props.projectType === 'gallery' ? 'xl':'xs', this.props.width) ?
+ {this.props.name && !isWidthDown(this.props.projectType === 'project' || this.props.projectType === 'gallery' ? 'xl' : 'xs', this.props.width) ?
{this.props.name}
- : null}
+ : null}
@@ -113,17 +114,17 @@ class WorkspaceName extends Component {
open={this.state.open}
title={this.state.title}
content={this.state.content}
- onClose={() => {this.toggleDialog(); this.setState({ name: this.props.name, description: this.props.description });}}
- onClick={() => {this.toggleDialog(); this.setState({ name: this.props.name, description: this.props.description });}}
+ onClose={() => { this.toggleDialog(); this.setState({ name: this.props.name, description: this.props.description }); }}
+ onClick={() => { this.toggleDialog(); this.setState({ name: this.props.name, description: this.props.description }); }}
button={'Abbrechen'}
>
{this.props.projectType === 'gallery' || this.state.projectType === 'gallery' ?
-
+
- :
}
+ :
}
{ this.renameWorkspace(); this.toggleDialog(); }}>Eingabe
From e52e3943c1d085d5ab78eafc204da768543bcc6f Mon Sep 17 00:00:00 2001
From: Delucse <46593742+Delucse@users.noreply.github.com>
Date: Mon, 14 Dec 2020 13:06:55 +0100
Subject: [PATCH 05/16] add generalReducer to store settings
---
src/App.js | 12 +--
src/actions/generalActions.js | 23 +++++-
src/actions/types.js | 3 +
src/components/Blockly/BlocklyWindow.js | 35 ++++-----
src/components/Blockly/msg/de.js | 20 +++--
src/components/Blockly/msg/en.js | 22 +++++-
src/components/Content.js | 54 ++++++++++++++
src/components/Home.js | 9 ++-
src/components/NotFound.js | 7 ++
src/components/Settings/LanguageSelector.js | 82 ++++++++++++---------
src/components/Settings/RenderSelector.js | 82 ++++++++++++---------
src/components/Settings/Settings.js | 77 +++++++++++++------
src/components/Settings/StatsSelector.js | 80 +++++++++++---------
src/reducers/generalReducer.js | 24 +++++-
14 files changed, 360 insertions(+), 170 deletions(-)
create mode 100644 src/components/Content.js
diff --git a/src/App.js b/src/App.js
index 1eccac4..ef9ca04 100644
--- a/src/App.js
+++ b/src/App.js
@@ -11,10 +11,7 @@ import './App.css';
import { ThemeProvider, createMuiTheme } from '@material-ui/core/styles';
-import Navbar from './components/Navbar';
-import Footer from './components/Footer';
-import Routes from './components/Route/Routes';
-import Cookies from './components/Cookies';
+import Content from './components/Content';
const theme = createMuiTheme({
palette: {
@@ -43,12 +40,7 @@ class App extends Component {
-
-
-
-
-
-
+
diff --git a/src/actions/generalActions.js b/src/actions/generalActions.js
index 6585a9a..3bd0c64 100644
--- a/src/actions/generalActions.js
+++ b/src/actions/generalActions.js
@@ -1,4 +1,4 @@
-import { VISIT } from './types';
+import { VISIT, LANGUAGE, RENDERER, STATISTICS } from './types';
export const visitPage = () => (dispatch) => {
@@ -6,3 +6,24 @@ export const visitPage = () => (dispatch) => {
type: VISIT
});
};
+
+export const setLanguage = (language) => (dispatch) => {
+ dispatch({
+ type: LANGUAGE,
+ payload: language
+ });
+};
+
+export const setRenderer = (renderer) => (dispatch) => {
+ dispatch({
+ type: RENDERER,
+ payload: renderer
+ });
+};
+
+export const setStatistics = (showStatistics) => (dispatch) => {
+ dispatch({
+ type: STATISTICS,
+ payload: showStatistics
+ });
+};
diff --git a/src/actions/types.js b/src/actions/types.js
index b3bff75..3e80a5e 100644
--- a/src/actions/types.js
+++ b/src/actions/types.js
@@ -46,6 +46,9 @@ export const PROGRESS = 'PROGRESS';
export const VISIT = 'VISIT';
+export const LANGUAGE = 'LANGUAGE';
+export const RENDERER = 'RENDERER';
+export const STATISTICS = 'STATISTICS';
// messages
export const GET_ERRORS = 'GET_ERRORS';
diff --git a/src/components/Blockly/BlocklyWindow.js b/src/components/Blockly/BlocklyWindow.js
index f3c680d..60b3ee3 100644
--- a/src/components/Blockly/BlocklyWindow.js
+++ b/src/components/Blockly/BlocklyWindow.js
@@ -18,26 +18,21 @@ class BlocklyWindow extends Component {
constructor(props) {
super(props);
this.simpleWorkspace = React.createRef();
- var locale = window.localStorage.getItem('locale');
- this.state = {
- renderer: window.localStorage.getItem('renderer'),
- };
- if (locale === null) {
- if (navigator.language === 'de-DE') {
- locale = 'de';
- } else {
- locale = 'en';
- }
- }
- if (locale === 'de') {
+ // if (locale === null) {
+ // if (navigator.language === 'de-DE') {
+ // locale = 'de';
+ // } else {
+ // locale = 'en';
+ // }
+ // }
+ if (this.props.language === 'de') {
Blockly.setLocale(De);
- } else if (locale === 'en') {
+ } else if (this.props.language === 'en') {
Blockly.setLocale(En);
}
}
componentDidMount() {
-
const workspace = Blockly.getMainWorkspace();
this.props.onChangeWorkspace({});
this.props.clearStats();
@@ -72,7 +67,7 @@ class BlocklyWindow extends Component {
style={this.props.svg ? { height: 0 } : this.props.blocklyCSS}
readOnly={this.props.readOnly !== undefined ? this.props.readOnly : false}
trashcan={this.props.trashcan !== undefined ? this.props.trashcan : true}
- renderer={this.state.renderer}
+ renderer={this.props.renderer}
zoom={{ // https://developers.google.com/blockly/guides/configure/web/zoom
controls: this.props.zoomControls !== undefined ? this.props.zoomControls : true,
wheel: false,
@@ -106,8 +101,14 @@ class BlocklyWindow extends Component {
BlocklyWindow.propTypes = {
onChangeWorkspace: PropTypes.func.isRequired,
- clearStats: PropTypes.func.isRequired
+ clearStats: PropTypes.func.isRequired,
+ renderer: PropTypes.string.isRequired,
+ language: PropTypes.string.isRequired
};
+const mapStateToProps = state => ({
+ renderer: state.general.renderer,
+ language: state.general.language
+});
-export default connect(null, { onChangeWorkspace, clearStats })(BlocklyWindow);
+export default connect(mapStateToProps, { onChangeWorkspace, clearStats })(BlocklyWindow);
diff --git a/src/components/Blockly/msg/de.js b/src/components/Blockly/msg/de.js
index cca4e12..f8f8abb 100644
--- a/src/components/Blockly/msg/de.js
+++ b/src/components/Blockly/msg/de.js
@@ -804,7 +804,7 @@ Blockly.Msg.senseBox_mqtt_publish = "Sende an Feed/Topic";
/**
* Typed Variable Modal
- *
+ *
*/
@@ -835,7 +835,7 @@ Blockly.Msg.toolbox_variables = "Variablen";
/**
* Tooltips
- *
+ *
*/
Blockly.Msg.tooltip_compile_code = "Code kompilieren"
@@ -863,7 +863,7 @@ Blockly.Msg.tooltip_project_title = "Titel des Projektes"
/**
* Messages
- *
+ *
*/
Blockly.Msg.messages_delete_project_failed = "Fehler beim Löschen des Projektes. Versuche es noch einmal."
@@ -895,7 +895,7 @@ Blockly.Msg.renamedialog_text = "Bitte gib einen Namen für das Projekt ein und
/**
* Compile Dialog
- *
+ *
*/
Blockly.Msg.compiledialog_headline = "Fehler"
@@ -903,7 +903,7 @@ Blockly.Msg.compiledialog_text = "Beim kompilieren ist ein Fehler aufgetreten.
/**
* Buttons
- *
+ *
*/
Blockly.Msg.button_cancel = "Abbrechen";
@@ -915,7 +915,7 @@ Blockly.Msg.button_back = "Zurück"
/**
- *
+ *
*/
Blockly.Msg.filename = "Dateiname";
@@ -926,9 +926,15 @@ Blockly.Msg.projectname = "Projektname";
*/
Blockly.Msg.settings_head = "Einstellungen"
Blockly.Msg.settings_language = "Sprache"
+Blockly.Msg.settings_language_text = "Auswahl der Sprache gilt für die gesamte Anwendung. Es kann zwischen Deutsch und Englisch unterschieden werden."
Blockly.Msg.settings_language_de = "Deutsch"
Blockly.Msg.settings_language_en = "Englisch"
-Blockly.Msg.settings_renderer_text = "Der Renderer bestimmt das aussehen der Blöcke"
+Blockly.Msg.settings_renderer = "Renderer"
+Blockly.Msg.settings_renderer_text = "Der eingestellte Renderer bestimmt das Aussehen der Blöcke. Es kann zwischen 'Geras' und 'Zelos' unterschieden werden, wobei 'Zelos' insbesondere für eine Touch-Anwendung geeignet ist."
+Blockly.Msg.settings_statistics = "Statistiken"
+Blockly.Msg.settings_statistics_text = "Die Anzeige von Statistiken zur Nutzung der Blöcke oberhalb der Arbeitsfläche kann ein- oder ausgeblendet werden."
+Blockly.Msg.settings_statistics_on = "An"
+Blockly.Msg.settings_statistics_off = "Aus"
/**
* 404
diff --git a/src/components/Blockly/msg/en.js b/src/components/Blockly/msg/en.js
index 6479613..b895bac 100644
--- a/src/components/Blockly/msg/en.js
+++ b/src/components/Blockly/msg/en.js
@@ -805,7 +805,7 @@ Blockly.Msg.toolbox_variables = "Variables";
/**
* Tooltips
- *
+ *
*/
Blockly.Msg.tooltip_compile_code = "Compile Code"
@@ -834,7 +834,7 @@ Blockly.Msg.renamedialog_text = "Please enter a name for the project and confirm
/**
* Compile Dialog
- *
+ *
*/
Blockly.Msg.compiledialog_headline = "Error"
@@ -844,7 +844,7 @@ Blockly.Msg.compiledialog_text = "While compiling an error occured. Please check
/**
* Buttons
- *
+ *
*/
Blockly.Msg.button_cancel = "Cancel";
@@ -855,12 +855,26 @@ Blockly.Msg.button_create_variableCreate = "Create Variable";
/**
- *
+ *
*/
Blockly.Msg.filename = "Filename";
Blockly.Msg.projectname = "Projectname";
+/**
+ * Settings
+ */
+Blockly.Msg.settings_head = "Settings"
+Blockly.Msg.settings_language = "Language"
+Blockly.Msg.settings_language_text = "Selection of the language applies to the entire application. A distinction can be made between German and English."
+Blockly.Msg.settings_language_de = "German"
+Blockly.Msg.settings_language_en = "English"
+Blockly.Msg.settings_renderer = "Renderer"
+Blockly.Msg.settings_renderer_text = "The selected renderer determines the appearance of the blocks. A distinction can be made between 'Geras' and 'Zelos', whereby 'Zelos' is particularly suitable for a touch application."
+Blockly.Msg.settings_statistics = "Statistics"
+Blockly.Msg.settings_statistics_text = "The display of statistics on the usage of the blocks above the workspace can be shown or hidden."
+Blockly.Msg.settings_statistics_on = "On"
+Blockly.Msg.settings_statistics_off = "Off"
diff --git a/src/components/Content.js b/src/components/Content.js
new file mode 100644
index 0000000..38e6b85
--- /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') {
+ Blockly.setLocale(De);
+ } else if (this.props.language === 'en') {
+ Blockly.setLocale(En);
+ }
+ }
+
+ componentDidUpdate(props){
+ if(props.language !== this.props.language){
+ if (this.props.language === 'de') {
+ Blockly.setLocale(De);
+ } else if (this.props.language === 'en') {
+ 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/NotFound.js b/src/components/NotFound.js
index eb790f4..01b03f7 100644
--- a/src/components/NotFound.js
+++ b/src/components/NotFound.js
@@ -9,6 +9,13 @@ 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 (
diff --git a/src/components/Settings/LanguageSelector.js b/src/components/Settings/LanguageSelector.js
index 7da299c..7164868 100644
--- a/src/components/Settings/LanguageSelector.js
+++ b/src/components/Settings/LanguageSelector.js
@@ -1,44 +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 * as Blockly from 'blockly/core';
+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 (
-
-
- {Blockly.Msg.settings_language}
-
- Deutsch
- Englisch
-
-
-
+ render(){
+ return(
+
+ {Blockly.Msg.settings_language}
+ {Blockly.Msg.settings_language_text}
+
+ {Blockly.Msg.settings_language}
+
+ {Blockly.Msg.settings_language_de}
+ {Blockly.Msg.settings_language_en}
+
+
+
);
+ }
}
+
+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 d8284b6..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 * as Blockly from 'blockly/core'
-const useStyles = makeStyles((theme) => ({
- formControl: {
- margin: theme.spacing(1),
- minWidth: 400,
- },
- selectEmpty: {
- marginTop: theme.spacing(2),
- },
-}));
+import Typography from '@material-ui/core/Typography';
+import FormHelperText from '@material-ui/core/FormHelperText';
-export default function RenderSelector() {
- const classes = useStyles();
- const [renderer, setRenderer] = React.useState(window.localStorage.getItem('renderer'));
- const handleChange = (event) => {
- setRenderer(event.target.value);
- window.localStorage.setItem('renderer', event.target.value);
- };
+class RenderSelector 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 (
-
-
- Renderer
-
- Geras
- Zelos
-
-
-
{Blockly.Msg.settings_renderer_text}
-
+
+ {Blockly.Msg.settings_renderer}
+ {Blockly.Msg.settings_renderer_text}
+
+ {Blockly.Msg.settings_renderer}
+ this.props.setRenderer(e.target.value)}
+ >
+ Geras
+ Zelos
+
+
+
);
+ }
}
+
+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 d43f33f..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 * as Blockly from 'blockly'
+
+import Button from '@material-ui/core/Button';
+import Paper from '@material-ui/core/Paper';
class Settings extends Component {
- render() {
- return (
-
- {Blockly.Msg.settings_head}
-
-
-
- { this.props.history.push('/') }}
- >
- {Blockly.Msg.button_back}
-
-
- );
- };
+
+ 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}
+
+
+
+
+
+
+
+
+
+
+
+
0 ? () => this.props.history.goBack() : () => this.props.history.push('/')}
+ >
+ {Blockly.Msg.button_back}
+
+
+ );
+ };
}
-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
-
- On
- Off
-
-
-
Schaltet die Statistiken Oberhalb der Arbeitsfläche ein bzw. aus
-
+
+ {Blockly.Msg.settings_statistics}
+ {Blockly.Msg.settings_statistics_text}
+
+ {Blockly.Msg.settings_statistics}
+ this.props.setStatistics(e.target.value)}
+ >
+ {Blockly.Msg.settings_statistics_on}
+ {Blockly.Msg.settings_statistics_off}
+
+
+
);
+ }
}
+
+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/reducers/generalReducer.js b/src/reducers/generalReducer.js
index 2d1c875..35ab59a 100644
--- a/src/reducers/generalReducer.js
+++ b/src/reducers/generalReducer.js
@@ -1,8 +1,11 @@
-import { VISIT } from '../actions/types';
+import { VISIT, LANGUAGE, RENDERER, STATISTICS } from '../actions/types';
const initialState = {
- pageVisits: 0 // detect if previous URL was
+ pageVisits: 0, // detect if previous URL was
+ language: 'de',
+ renderer: window.localStorage.getItem('renderer') || 'geras',
+ statistics: window.localStorage.getItem('statistics') === 'true' ? true : window.localStorage.getItem('statistics') === 'false' ? false : false
};
export default function(state = initialState, action){
@@ -12,6 +15,23 @@ export default function(state = initialState, action){
...state,
pageVisits: state.pageVisits += 1
};
+ case LANGUAGE:
+ return {
+ ...state,
+ language: action.payload
+ };
+ case RENDERER:
+ window.localStorage.setItem('renderer', action.payload);
+ return {
+ ...state,
+ renderer: action.payload
+ };
+ case STATISTICS:
+ window.localStorage.setItem('statistics', action.payload);
+ return {
+ ...state,
+ statistics: action.payload
+ };
default:
return state;
}
From e5204bb4d54db3eb917b53f89d2b6d03b2e84821 Mon Sep 17 00:00:00 2001
From: Mario
Date: Mon, 14 Dec 2020 13:50:44 +0100
Subject: [PATCH 06/16] add more translations and resolve issues
---
src/actions/projectActions.js | 41 +++---
src/actions/tutorialActions.js | 30 ++--
src/components/Blockly/msg/de.js | 46 +++++-
src/components/Navbar.js | 60 ++++----
src/components/Project/Project.js | 36 +++--
src/components/Project/ProjectHome.js | 50 +++----
src/components/Tutorial/Badge.js | 41 +++---
.../Tutorial/Builder/BlocklyExample.js | 71 +++++-----
src/components/Tutorial/Builder/Builder.js | 133 +++++++++---------
src/components/Tutorial/Builder/Hardware.js | 6 +-
.../Tutorial/Builder/Requirements.js | 8 +-
src/components/Tutorial/Hardware.js | 2 +-
src/components/Tutorial/HintTutorialExists.js | 36 ++---
src/components/Tutorial/Requirement.js | 3 +-
src/components/Tutorial/SolutionCheck.js | 10 +-
src/components/Tutorial/StepperHorizontal.js | 5 +-
src/components/Tutorial/Tutorial.js | 61 ++++----
src/components/User/Login.js | 43 +++---
src/components/Workspace/OpenProject.js | 3 -
src/reducers/tutorialReducer.js | 2 +-
20 files changed, 362 insertions(+), 325 deletions(-)
diff --git a/src/actions/projectActions.js b/src/actions/projectActions.js
index 8ab01cf..c56a06d 100644
--- a/src/actions/projectActions.js
+++ b/src/actions/projectActions.js
@@ -1,7 +1,6 @@
import { PROJECT_PROGRESS, GET_PROJECT, GET_PROJECTS, PROJECT_TYPE, PROJECT_DESCRIPTION } from './types';
import axios from 'axios';
-import { workspaceName } from './workspaceActions';
import { returnErrors, returnSuccess } from './messageActions';
export const setType = (type) => (dispatch) => {
@@ -19,13 +18,13 @@ export const setDescription = (description) => (dispatch) => {
};
export const getProject = (type, id) => (dispatch) => {
- dispatch({type: PROJECT_PROGRESS});
+ dispatch({ type: PROJECT_PROGRESS });
dispatch(setType(type));
axios.get(`${process.env.REACT_APP_BLOCKLY_API}/${type}/${id}`)
.then(res => {
var data = type === 'share' ? 'content' : type;
var project = res.data[data];
- if(project){
+ if (project) {
dispatch({
type: GET_PROJECT,
payload: project
@@ -34,24 +33,24 @@ export const getProject = (type, id) => (dispatch) => {
type: PROJECT_DESCRIPTION,
payload: project.description
});
- dispatch({type: PROJECT_PROGRESS});
+ dispatch({ type: PROJECT_PROGRESS });
dispatch(returnSuccess(res.data.message, res.status, 'GET_PROJECT_SUCCESS'));
}
- else{
- dispatch({type: PROJECT_PROGRESS});
+ else {
+ dispatch({ type: PROJECT_PROGRESS });
dispatch(returnErrors(res.data.message, res.status, 'PROJECT_EMPTY'));
}
})
.catch(err => {
- if(err.response){
+ if (err.response) {
dispatch(returnErrors(err.response.data.message, err.response.status, 'GET_PROJECT_FAIL'));
}
- dispatch({type: PROJECT_PROGRESS});
+ dispatch({ type: PROJECT_PROGRESS });
});
};
export const getProjects = (type) => (dispatch) => {
- dispatch({type: PROJECT_PROGRESS});
+ dispatch({ type: PROJECT_PROGRESS });
axios.get(`${process.env.REACT_APP_BLOCKLY_API}/${type}`)
.then(res => {
var data = type === 'project' ? 'projects' : 'galleries';
@@ -60,14 +59,14 @@ export const getProjects = (type) => (dispatch) => {
type: GET_PROJECTS,
payload: projects
});
- dispatch({type: PROJECT_PROGRESS});
+ dispatch({ type: PROJECT_PROGRESS });
dispatch(returnSuccess(res.data.message, res.status));
})
.catch(err => {
- if(err.response){
+ if (err.response) {
dispatch(returnErrors(err.response.data.message, err.response.status, 'GET_PROJECTS_FAIL'));
}
- dispatch({type: PROJECT_PROGRESS});
+ dispatch({ type: PROJECT_PROGRESS });
});
};
@@ -78,7 +77,7 @@ export const updateProject = (type, id) => (dispatch, getState) => {
title: workspace.name
};
var project = getState().project;
- if(type==='gallery'){
+ if (type === 'gallery') {
body.description = project.description;
}
axios.put(`${process.env.REACT_APP_BLOCKLY_API}/${type}/${id}`, body)
@@ -91,15 +90,15 @@ export const updateProject = (type, id) => (dispatch, getState) => {
type: GET_PROJECTS,
payload: projects
});
- if(type === 'project'){
+ if (type === 'project') {
dispatch(returnSuccess(res.data.message, res.status, 'PROJECT_UPDATE_SUCCESS'));
} else {
dispatch(returnSuccess(res.data.message, res.status, 'GALLERY_UPDATE_SUCCESS'));
}
})
.catch(err => {
- if(err.response){
- if(type === 'project'){
+ if (err.response) {
+ if (type === 'project') {
dispatch(returnErrors(err.response.data.message, err.response.status, 'PROJECT_UPDATE_FAIL'));
} else {
dispatch(returnErrors(err.response.data.message, err.response.status, 'GALLERY_UPDATE_FAIL'));
@@ -119,14 +118,14 @@ export const deleteProject = (type, id) => (dispatch, getState) => {
type: GET_PROJECTS,
payload: projects
});
- if(type === 'project'){
+ if (type === 'project') {
dispatch(returnSuccess(res.data.message, res.status, 'PROJECT_DELETE_SUCCESS'));
} else {
dispatch(returnSuccess(res.data.message, res.status, 'GALLERY_DELETE_SUCCESS'));
}
})
.catch(err => {
- if(err.response){
+ if (err.response) {
dispatch(returnErrors(err.response.data.message, err.response.status, 'PROJECT_DELETE_FAIL'));
}
});
@@ -137,7 +136,7 @@ export const shareProject = (title, type, id) => (dispatch, getState) => {
var body = {
title: title
};
- if(type === 'project'){
+ if (type === 'project') {
body.projectId = id;
} else {
body.xml = getState().workspace.code.xml;
@@ -145,7 +144,7 @@ export const shareProject = (title, type, id) => (dispatch, getState) => {
axios.post(`${process.env.REACT_APP_BLOCKLY_API}/share`, body)
.then(res => {
var shareContent = res.data.content;
- if(body.projectId){
+ if (body.projectId) {
var projects = getState().project.projects;
var index = projects.findIndex(res => res._id === id);
projects[index].shared = shareContent.expiresAt;
@@ -157,7 +156,7 @@ export const shareProject = (title, type, id) => (dispatch, getState) => {
dispatch(returnSuccess(res.data.message, shareContent._id, 'SHARE_SUCCESS'));
})
.catch(err => {
- if(err.response){
+ if (err.response) {
dispatch(returnErrors(err.response.data.message, err.response.status, 'SHARE_FAIL'));
}
});
diff --git a/src/actions/tutorialActions.js b/src/actions/tutorialActions.js
index 8983da9..7ef8c8e 100644
--- a/src/actions/tutorialActions.js
+++ b/src/actions/tutorialActions.js
@@ -1,10 +1,10 @@
-import { MYBADGES_DISCONNECT, TUTORIAL_PROGRESS, GET_TUTORIAL, GET_TUTORIALS, TUTORIAL_SUCCESS, TUTORIAL_ERROR, TUTORIAL_CHANGE, TUTORIAL_XML, TUTORIAL_ID, TUTORIAL_STEP } from './types';
+import { MYBADGES_DISCONNECT, TUTORIAL_PROGRESS, GET_TUTORIAL, GET_TUTORIALS, TUTORIAL_SUCCESS, TUTORIAL_ERROR, TUTORIAL_CHANGE, TUTORIAL_XML, TUTORIAL_STEP } from './types';
import axios from 'axios';
import { returnErrors, returnSuccess } from './messageActions';
export const getTutorial = (id) => (dispatch, getState) => {
- dispatch({type: TUTORIAL_PROGRESS});
+ dispatch({ type: TUTORIAL_PROGRESS });
axios.get(`${process.env.REACT_APP_BLOCKLY_API}/tutorial/${id}`)
.then(res => {
var tutorial = res.data.tutorial;
@@ -13,7 +13,7 @@ export const getTutorial = (id) => (dispatch, getState) => {
type: TUTORIAL_SUCCESS,
payload: status
});
- dispatch({type: TUTORIAL_PROGRESS});
+ dispatch({ type: TUTORIAL_PROGRESS });
dispatch({
type: GET_TUTORIAL,
payload: tutorial
@@ -22,15 +22,15 @@ export const getTutorial = (id) => (dispatch, getState) => {
});
})
.catch(err => {
- if(err.response){
+ if (err.response) {
dispatch(returnErrors(err.response.data.message, err.response.status, 'GET_TUTORIAL_FAIL'));
}
- dispatch({type: TUTORIAL_PROGRESS});
+ dispatch({ type: TUTORIAL_PROGRESS });
});
};
export const getTutorials = () => (dispatch, getState) => {
- dispatch({type: TUTORIAL_PROGRESS});
+ dispatch({ type: TUTORIAL_PROGRESS });
axios.get(`${process.env.REACT_APP_BLOCKLY_API}/tutorial`)
.then(res => {
var tutorials = res.data.tutorials;
@@ -44,15 +44,15 @@ export const getTutorials = () => (dispatch, getState) => {
type: GET_TUTORIALS,
payload: tutorials
});
- dispatch({type: TUTORIAL_PROGRESS});
+ dispatch({ type: TUTORIAL_PROGRESS });
dispatch(returnSuccess(res.data.message, res.status));
});
})
.catch(err => {
- if(err.response){
+ if (err.response) {
dispatch(returnErrors(err.response.data.message, err.response.status, 'GET_TUTORIALS_FAIL'));
}
- dispatch({type: TUTORIAL_PROGRESS});
+ dispatch({ type: TUTORIAL_PROGRESS });
});
};
@@ -69,7 +69,7 @@ export const assigneBadge = (id) => (dispatch, getState) => {
dispatch(returnSuccess(badge, res.status, 'ASSIGNE_BADGE_SUCCESS'));
})
.catch(err => {
- if(err.response){
+ if (err.response) {
dispatch(returnErrors(err.response.data.message, err.response.status, 'ASSIGNE_BADGE_FAIL'));
}
});
@@ -90,7 +90,7 @@ export const deleteTutorial = (id) => (dispatch, getState) => {
dispatch(returnSuccess(res.data.message, res.status, 'TUTORIAL_DELETE_SUCCESS'));
})
.catch(err => {
- if(err.response){
+ if (err.response) {
dispatch(returnErrors(err.response.data.message, err.response.status, 'TUTORIAL_DELETE_FAIL'));
}
});
@@ -128,7 +128,7 @@ export const tutorialCheck = (status, step) => (dispatch, getState) => {
payload: tutorialsStatus
});
dispatch(tutorialChange());
- dispatch(returnSuccess('','','TUTORIAL_CHECK_SUCCESS'));
+ dispatch(returnSuccess('', '', 'TUTORIAL_CHECK_SUCCESS'));
};
export const storeTutorialXml = (code) => (dispatch, getState) => {
@@ -161,9 +161,9 @@ export const tutorialStep = (step) => (dispatch) => {
};
-const existingTutorials = (tutorials, status) => new Promise(function(resolve, reject){
+const existingTutorials = (tutorials, status) => new Promise(function (resolve, reject) {
var newstatus;
- new Promise(function(resolve, reject){
+ new Promise(function (resolve, reject) {
var existingTutorialIds = tutorials.map((tutorial, i) => {
existingTutorial(tutorial, status).then(status => {
newstatus = status;
@@ -180,7 +180,7 @@ const existingTutorials = (tutorials, status) => new Promise(function(resolve, r
});
});
-const existingTutorial = (tutorial, status) => new Promise(function(resolve, reject){
+const existingTutorial = (tutorial, status) => new Promise(function (resolve, reject) {
var tutorialsId = tutorial._id;
var statusIndex = status.findIndex(status => status._id === tutorialsId);
if (statusIndex > -1) {
diff --git a/src/components/Blockly/msg/de.js b/src/components/Blockly/msg/de.js
index cca4e12..71212f9 100644
--- a/src/components/Blockly/msg/de.js
+++ b/src/components/Blockly/msg/de.js
@@ -859,7 +859,7 @@ Blockly.Msg.tooltip_copy_link = "Link kopieren"
Blockly.Msg.tooltip_trashcan_hide = 'gelöschte Blöcke ausblenden'
Blockly.Msg.tooltip_trashcan_delete = 'Blöcke endgültig löschen'
Blockly.Msg.tooltip_project_title = "Titel des Projektes"
-
+Blockly.Msg.tooltip_check_solution = "Lösung kontrollieren"
/**
* Messages
@@ -879,6 +879,10 @@ Blockly.Msg.messages_SHARE_FAIL = "Fehler beim Erstellen eines Links zum Teilen
Blockly.Msg.messages_copylink_success = 'Link erfolgreich in Zwischenablage gespeichert.'
Blockly.Msg.messages_rename_success_01 = 'Das Projekt wurde erfolgreich in '
Blockly.Msg.messages_rename_success_02 = 'umbenannt.'
+Blockly.Msg.messages_newblockly_head = "Willkommen zur neuen Version Blockly für die senseBox"
+Blockly.Msg.messages_newblockly_text = "Die neue Blockly Version befindet sich zurzeit in der Testphase. Alle Neuigkeiten findet ihr hier:"
+Blockly.Msg.messages_GET_TUTORIAL_FAIL = 'Zurück zur Tutorials-Übersicht'
+Blockly.Msg.messages_LOGIN_FAIL = 'Der Benutzername oder das Passwort ist nicht korrekt.'
/**
* Share Dialog
*/
@@ -912,6 +916,8 @@ Blockly.Msg.button_accept = "Bestätigen";
Blockly.Msg.button_compile = "Kompilieren";
Blockly.Msg.button_create_variableCreate = "Erstelle Variable";
Blockly.Msg.button_back = "Zurück"
+Blockly.Msg.button_next = "nächster Schritt"
+Blockly.Msg.button_tutorial_overview = "Tutorial Übersicht"
/**
@@ -938,6 +944,21 @@ Blockly.Msg.notfound_head = "Die von Ihnen angeforderte Seite kann nicht gefunde
Blockly.Msg.notfound_text = "Die gesuchte Seite wurde möglicherweise entfernt, ihr Name wurde geändert oder sie ist vorübergehend nicht verfügbar."
+/**
+ * Labels
+ */
+
+Blockly.Msg.labels_donotshowagain = 'Dialog nicht mehr anzeigen'
+Blockly.Msg.labels_here = "hier"
+Blockly.Msg.labels_username = 'E-Mail oder Nutzername'
+
+/**
+ * Badges
+ */
+
+Blockly.Msg.badges_explaination = "Eine Übersicht über alle erhaltenen Badges im Kontext Blockly for senseBox findest du "
+Blockly.Msg.badges_ASSIGNE_BADGE_SUCCESS_01 = "Herzlichen Glückwunsch! Du hast den Badge "
+Blockly.Msg.badges_ASSIGNE_BADGE_SUCCESS_02 = " erhalten."
/**
* Tutorials
*/
@@ -945,6 +966,27 @@ Blockly.Msg.notfound_text = "Die gesuchte Seite wurde möglicherweise entfernt,
Blockly.Msg.tutorials_assessment_task = "Aufgabe"
Blockly.Msg.tutorials_hardware_head = "Für die Umsetzung benötigst du folgende Hardware:"
Blockly.Msg.tutorials_hardware_moreInformation = "Weitere Informationen zur Hardware-Komponente findest du"
-Blockly.Msg.tutorials_hardware_here = "hier"
+Blockly.Msg.tutorials_hardware_here = "hier";
+Blockly.Msg.tutorials_requirements = "Bevor du mit diesem Tutorial fortfährst solltest du folgende Tutorials erfolgreich abgeschlossen haben:"
+
+/**
+ * Tutorial Builder
+ */
+
+Blockly.Msg.builder_solution = "Lösung"
+Blockly.Msg.builder_solution_submit = "Lösung einreichen"
+Blockly.Msg.builder_example_submit = "Beispiel einreichen"
+Blockly.Msg.builder_comment = "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."
+Blockly.Msg.builder_hardware_order = "Beachte, dass die Reihenfolge des Auswählens maßgebend ist."
+Blockly.Msg.builder_hardware_helper = "Wähle mindestens eine Hardware-Komponente aus."
+Blockly.Msg.builder_requirements_head = "Voraussetzungen"
+Blockly.Msg.builder_requirements_order = "Beachte, dass die Reihenfolge des Anhakens maßgebend ist."
+
+/**
+ * Login
+ */
+
+
+Blockly.Msg.login_head = "Anmelden"
export const De = Blockly.Msg;
diff --git a/src/components/Navbar.js b/src/components/Navbar.js
index 2bc7b62..a3e6949 100644
--- a/src/components/Navbar.js
+++ b/src/components/Navbar.js
@@ -21,7 +21,7 @@ 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";
const styles = (theme) => ({
@@ -101,46 +101,46 @@ 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: '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: '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: '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}>
+
+
+
+
+ );
}
+ }
)}
{this.props.tutorialIsLoading || this.props.projectIsLoading ?
-
- : null}
+
+ : null}
);
}
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..1644b3e 100644
--- a/src/components/Project/ProjectHome.js
+++ b/src/components/Project/ProjectHome.js
@@ -4,7 +4,7 @@ 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 +42,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 +88,7 @@ class ProjectHome extends Component {
- :
+ :
{this.props.projects.length > 0 ?
@@ -97,37 +97,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/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/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 (
+
this.setXml()}
>
- {this.props.task ? 'Musterlösung einreichen' : 'Beispiel einreichen'}
+ {this.props.task ? Blockly.Msg.builder_solution_submit : Blockly.Msg.builder_example_submit}
- )})()
- : 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..d0d8885 100644
--- a/src/components/Tutorial/Builder/Builder.js
+++ b/src/components/Tutorial/Builder/Builder.js
@@ -1,15 +1,13 @@
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 { checkError, readJSON, jsonString, progress, tutorialId, resetTutorial as resetTutorialBuilder } from '../../../actions/tutorialBuilderActions';
import { getTutorials, resetTutorial, deleteTutorial } 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 Textfield from './Textfield';
@@ -43,7 +41,7 @@ const styles = (theme) => ({
marginTop: '5px',
height: '40px',
backgroundColor: theme.palette.error.dark,
- '&:hover':{
+ '&:hover': {
backgroundColor: theme.palette.error.dark
}
}
@@ -72,16 +70,16 @@ class Builder extends Component {
}
componentDidUpdate(props, state) {
- if(props.message !== this.props.message){
- if(this.props.message.id === 'GET_TUTORIALS_FAIL'){
+ 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 +88,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 +141,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);
@@ -186,8 +184,8 @@ class Builder extends Component {
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 +194,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);
}
}
@@ -214,7 +212,7 @@ class Builder extends Component {
submitNew = () => {
var newTutorial = this.submit();
- if(newTutorial){
+ if (newTutorial) {
axios.post(`${process.env.REACT_APP_BLOCKLY_API}/tutorial/`, newTutorial)
.then(res => {
var tutorial = res.data.tutorial;
@@ -229,7 +227,7 @@ class Builder extends Component {
submitUpdate = () => {
var updatedTutorial = this.submit();
- if(updatedTutorial){
+ if (updatedTutorial) {
axios.put(`${process.env.REACT_APP_BLOCKLY_API}/tutorial/${this.props.id}`, updatedTutorial)
.then(res => {
var tutorial = res.data.tutorial;
@@ -251,30 +249,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 +292,7 @@ class Builder extends Component {
this.uploadJsonString()}>String laden
- :
+ :
Tutorial
{this.state.tutorial === 'new' || (this.state.tutorial === 'change' && this.props.id !== '') ?
- /*Tutorial-Builder-Form*/
-
- {this.props.error.type ?
-
{`Ein Tutorial muss mindestens jeweils eine Instruktion und eine Aufgabe enthalten.`}
- : null}
- {/*
*/}
-
-
+ /*Tutorial-Builder-Form*/
+
+ {this.props.error.type ?
+
{`Ein Tutorial muss mindestens jeweils eine Instruktion und eine Aufgabe enthalten.`}
+ : null}
+ {/*
*/}
+
+
- {this.props.steps.map((step, i) =>
-
- )}
+ {this.props.steps.map((step, i) =>
+
+ )}
- {/*submit or reset*/}
-
- {this.state.tutorial === 'new' ?
-
- this.submitNew()}>Tutorial erstellen
- this.resetFull()}>Zurücksetzen
-
- :
-
this.submitUpdate()}>Tutorial ändern
-
this.resetTutorial()}>Zurücksetzen
+ {/*submit or reset*/}
+
+ {this.state.tutorial === 'new' ?
+
+ this.submitNew()}>Tutorial erstellen
+ this.resetFull()}>Zurücksetzen
+
+ :
+ this.submitUpdate()}>Tutorial ändern
+ this.resetTutorial()}>Zurücksetzen
+
+ }
+
+
+
+
- }
-
-
-
-
-
- : null}
+ : null}
{this.state.tutorial === 'delete' && this.props.id !== '' ?
this.props.deleteTutorial()}>Tutorial löschen
- : null}
+ : null}
({
multiGridListTile: {
@@ -67,8 +69,8 @@ class Requirements extends Component {
return (
Hardware
-
Beachte, dass die Reihenfolge des Auswählens maßgebend ist.
- {this.props.error ?
Wähle mindestens eine Hardware-Komponente aus. : null}
+
{Blockly.Msg.builder_hardware_order}
+ {this.props.error ?
{Blockly.Msg.builder_hardware_helper} : null}
{hardware.map((picture, i) => (
this.onChange(picture.id)} classes={{ tile: this.props.value.filter(value => value === picture.id).length > 0 ? this.props.classes.active : this.props.classes.border }}>
diff --git a/src/components/Tutorial/Builder/Requirements.js b/src/components/Tutorial/Builder/Requirements.js
index d5bd2ca..dfb542b 100644
--- a/src/components/Tutorial/Builder/Requirements.js
+++ b/src/components/Tutorial/Builder/Requirements.js
@@ -2,8 +2,6 @@ import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { changeContent } from '../../../actions/tutorialBuilderActions';
-import { getTutorials, resetTutorial } from '../../../actions/tutorialActions';
-import { clearMessages } from '../../../actions/messageActions';
import FormGroup from '@material-ui/core/FormGroup';
import Checkbox from '@material-ui/core/Checkbox';
@@ -11,7 +9,7 @@ import FormControlLabel from '@material-ui/core/FormControlLabel';
import FormLabel from '@material-ui/core/FormLabel';
import FormHelperText from '@material-ui/core/FormHelperText';
import FormControl from '@material-ui/core/FormControl';
-
+import * as Blockly from 'blockly'
class Requirements extends Component {
onChange = (e) => {
@@ -29,8 +27,8 @@ class Requirements extends Component {
render() {
return (
- Voraussetzungen
- Beachte, dass die Reihenfolge des Anhakens maßgebend ist.
+ {Blockly.Msg.builder_requirements_head}
+ {Blockly.Msg.builder_requirements_order}
{this.props.tutorials.filter(tutorial => tutorial._id !== this.props.id).map((tutorial, i) =>
diff --git a/src/components/Tutorial/HintTutorialExists.js b/src/components/Tutorial/HintTutorialExists.js
index afd1468..0c86c53 100644
--- a/src/components/Tutorial/HintTutorialExists.js
+++ b/src/components/Tutorial/HintTutorialExists.js
@@ -46,7 +46,7 @@ class HintTutorialExists extends Component {
window.localStorage.setItem('news', e.target.checked);
}
else {
- window.localStorage.deleteItem('news');
+ window.localStorage.removeItem('news');
}
}
@@ -57,30 +57,30 @@ class HintTutorialExists extends Component {
fullWidth
maxWidth={'sm'}
open={this.state.open}
- title={'Neuigkeiten'}
+ title={Blockly.Msg.messages_newblockly_head}
content={''}
onClose={this.toggleDialog}
onClick={this.toggleDialog}
button={Blockly.Msg.button_close}
>
- Es gibt ab jetzt Tutorials zu verschiedenen Themen. Schau mal hier vorbei.
- this.onChange(e)}
- name="dialog"
- color="primary"
- />
- }
- label={'Dialog nicht mehr anzeigen'}
- />
+ {Blockly.Msg.messages_newblockly_text} test
+
this.onChange(e)}
+ name="dialog"
+ color="primary"
+ />
+ }
+ label={Blockly.Msg.labels_donotshowagain}
+ />
);
};
diff --git a/src/components/Tutorial/Requirement.js b/src/components/Tutorial/Requirement.js
index a3c0c86..87784cc 100644
--- a/src/components/Tutorial/Requirement.js
+++ b/src/components/Tutorial/Requirement.js
@@ -13,6 +13,7 @@ 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'
const styles = theme => ({
outerDiv: {
@@ -63,7 +64,7 @@ class Requirement extends Component {
var tutorialIds = requirements.map(requirement => requirement._id);
return (
-
Bevor du mit diesem Tutorial fortfährst solltest du folgende Tutorials erfolgreich abgeschlossen haben:
+
{Blockly.Msg.tutorials_requirements}
{tutorialIds.map((tutorialId, i) => {
var title = requirements[i].title
diff --git a/src/components/Tutorial/SolutionCheck.js b/src/components/Tutorial/SolutionCheck.js
index f8c1383..ba8c434 100644
--- a/src/components/Tutorial/SolutionCheck.js
+++ b/src/components/Tutorial/SolutionCheck.js
@@ -18,6 +18,8 @@ import Button from '@material-ui/core/Button';
import { faClipboardCheck } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
+import * as Blockly from 'blockly'
+
const styles = (theme) => ({
compile: {
backgroundColor: theme.palette.button.compile,
@@ -57,7 +59,7 @@ class SolutionCheck extends Component {
const steps = this.props.tutorial.steps;
return (
-
+
{this.state.msg.type === 'success' ?
@@ -88,7 +90,7 @@ class SolutionCheck extends Component {
color="primary"
onClick={() => { this.toggleDialog(); this.props.history.push(`/tutorial/`) }}
>
- Tutorials-Übersicht
+ {Blockly.Msg.button_tutorial_overview}
:
{ this.toggleDialog(); this.props.tutorialStep(this.props.activeStep + 1) }}
>
- nächster Schritt
+ {Blockly.Msg.button_next}
}
diff --git a/src/components/Tutorial/StepperHorizontal.js b/src/components/Tutorial/StepperHorizontal.js
index 9886336..f045621 100644
--- a/src/components/Tutorial/StepperHorizontal.js
+++ b/src/components/Tutorial/StepperHorizontal.js
@@ -51,7 +51,6 @@ class StepperHorizontal extends Component {
render() {
var tutorialId = this.props.tutorial._id;
- var tutorialIndex = this.props.currentTutorialIndex;
var status = this.props.status.filter(status => status._id === tutorialId)[0];
var tasks = status.tasks;
var error = tasks.filter(task => task.type === 'error').length > 0;
@@ -71,7 +70,7 @@ class StepperHorizontal extends Component {
{ this.props.history.push(`/tutorial/${tutorials[tutorialIndex - 1].id}`) }}
+ //onClick={() => { this.props.history.push(`/tutorial/${tutorials[tutorialIndex - 1].id}`) }}
>
{'<'}
@@ -83,7 +82,7 @@ class StepperHorizontal extends Component {
{ this.props.history.push(`/tutorial/${tutorials[tutorialIndex + 1].id}`) }}
+ //onClick={() => { this.props.history.push(`/tutorial/${tutorials[tutorialIndex + 1].id}`) }}
>
{'>'}
diff --git a/src/components/Tutorial/Tutorial.js b/src/components/Tutorial/Tutorial.js
index d86a958..4288dbb 100644
--- a/src/components/Tutorial/Tutorial.js
+++ b/src/components/Tutorial/Tutorial.js
@@ -12,7 +12,7 @@ import Instruction from './Instruction';
import Assessment from './Assessment';
import Badge from './Badge';
import NotFound from '../NotFound';
-
+import * as Blockly from 'blockly'
import { detectWhitespacesAndReturnReadableResult } from '../../helpers/whitespace';
@@ -26,10 +26,10 @@ class Tutorial extends Component {
}
componentDidUpdate(props, state) {
- if(this.props.tutorial && !this.props.isLoading && this.props.tutorial._id != this.props.match.params.tutorialId) {
+ if (this.props.tutorial && !this.props.isLoading && this.props.tutorial._id != this.props.match.params.tutorialId) {
this.props.getTutorial(this.props.match.params.tutorialId);
}
- if(this.props.message.id === 'GET_TUTORIAL_FAIL'){
+ if (this.props.message.id === 'GET_TUTORIAL_FAIL') {
alert(this.props.message.msg);
}
}
@@ -37,7 +37,7 @@ class Tutorial extends Component {
componentWillUnmount() {
this.props.resetTutorial();
this.props.workspaceName(null);
- if(this.props.message.msg){
+ if (this.props.message.msg) {
this.props.clearMessages();
}
}
@@ -47,37 +47,38 @@ class Tutorial extends Component {
{this.props.isLoading ? null :
!this.props.tutorial ?
- this.props.message.id === 'GET_TUTORIAL_FAIL' ?
: null
+ this.props.message.id === 'GET_TUTORIAL_FAIL' ?
: null
: (() => {
- var tutorial = this.props.tutorial;
- var steps = this.props.tutorial.steps;
- var step = steps[this.props.activeStep];
- var name = `${detectWhitespacesAndReturnReadableResult(tutorial.title)}_${detectWhitespacesAndReturnReadableResult(step.headline)}`;
- return(
-
-
+ var tutorial = this.props.tutorial;
+ var steps = this.props.tutorial.steps;
+ var step = steps[this.props.activeStep];
+ var name = `${detectWhitespacesAndReturnReadableResult(tutorial.title)}_${detectWhitespacesAndReturnReadableResult(step.headline)}`;
+ return (
+
+
-
-
+
+
-
-
- {/* calc(Card-padding: 10px + Button-height: 35px + Button-marginTop: 15px)*/}
-
- {step ?
- step.type === 'instruction' ?
-
- : // if step.type === 'assessment'
- : null}
+
+
+ {/* calc(Card-padding: 10px + Button-height: 35px + Button-marginTop: 15px)*/}
+
+ {step ?
+ step.type === 'instruction' ?
+
+ : // if step.type === 'assessment'
+ : null}
-
- this.props.tutorialStep(this.props.activeStep - 1)}>Zurück
- this.props.tutorialStep(this.props.activeStep + 1)}>Weiter
-
-
-
+
+ this.props.tutorialStep(this.props.activeStep - 1)}>Zurück
+ this.props.tutorialStep(this.props.activeStep + 1)}>Weiter
+
+
- )})()
+
+ )
+ })()
}
);
diff --git a/src/components/User/Login.js b/src/components/User/Login.js
index 13d4497..75a4948 100644
--- a/src/components/User/Login.js
+++ b/src/components/User/Login.js
@@ -19,7 +19,7 @@ import Divider from '@material-ui/core/Divider';
import InputAdornment from '@material-ui/core/InputAdornment';
import CircularProgress from '@material-ui/core/CircularProgress';
import Link from '@material-ui/core/Link';
-
+import * as Blockly from 'blockly'
export class Login extends Component {
@@ -37,21 +37,21 @@ export class Login extends Component {
};
}
- componentDidUpdate(props){
+ componentDidUpdate(props) {
console.log(this.state.redirect);
const { message } = this.props;
if (message !== props.message) {
- if(message.id === 'LOGIN_SUCCESS'){
- if(this.state.redirect){
+ if (message.id === 'LOGIN_SUCCESS') {
+ if (this.state.redirect) {
this.props.history.push(this.state.redirect);
}
- else{
+ else {
this.props.history.goBack();
}
}
// Check for login error
- else if(message.id === 'LOGIN_FAIL'){
- this.setState({ email: '', password: '', snackbar: true, key: Date.now(), message: 'Der Benutzername oder das Passwort ist nicht korrekt.', type: 'error' });
+ else if (message.id === 'LOGIN_FAIL') {
+ this.setState({ email: '', password: '', snackbar: true, key: Date.now(), message: Blockly.Msg.messages_LOGIN_FAIL, type: 'error' });
}
}
}
@@ -62,8 +62,8 @@ export class Login extends Component {
onSubmit = e => {
e.preventDefault();
- const {email, password} = this.state;
- if(email !== '' && password !== ''){
+ const { email, password } = this.state;
+ if (email !== '' && password !== '') {
// create user object
const user = {
email,
@@ -83,13 +83,13 @@ export class Login extends Component {
e.preventDefault();
};
- render(){
- return(
+ render() {
+ return (
-
-
Anmelden
+
+
{Blockly.Msg.login_head}
Zur Anmeldung ist ein Konto auf openSenseMap Voraussetzung.
@@ -100,10 +100,10 @@ export class Login extends Component {
key={this.state.key}
/>
-
+
{this.props.progress ?
-
- : 'Anmelden'}
+
+ : 'Anmelden'}
-
+
Passwort vergessen?
-
-
+
+
Du hast noch kein Konto? Registriere dich auf openSenseMap.
@@ -156,7 +156,6 @@ Login.propTypes = {
message: PropTypes.object.isRequired,
login: PropTypes.func.isRequired,
clearMessages: PropTypes.func.isRequired,
- message: PropTypes.object.isRequired,
progress: PropTypes.bool.isRequired
};
diff --git a/src/components/Workspace/OpenProject.js b/src/components/Workspace/OpenProject.js
index 9045a32..5387e89 100644
--- a/src/components/Workspace/OpenProject.js
+++ b/src/components/Workspace/OpenProject.js
@@ -9,10 +9,7 @@ import Snackbar from '../Snackbar';
import Dialog from '../Dialog';
import { withStyles } from '@material-ui/core/styles';
-import Button from '@material-ui/core/Button';
-import IconButton from '@material-ui/core/IconButton';
import Tooltip from '@material-ui/core/Tooltip';
-import Typography from '@material-ui/core/Typography';
import { faUpload } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
diff --git a/src/reducers/tutorialReducer.js b/src/reducers/tutorialReducer.js
index 8b91f0f..f28d151 100644
--- a/src/reducers/tutorialReducer.js
+++ b/src/reducers/tutorialReducer.js
@@ -1,4 +1,4 @@
-import { TUTORIAL_PROGRESS, GET_TUTORIAL, GET_TUTORIALS, TUTORIAL_SUCCESS, TUTORIAL_ERROR, TUTORIAL_CHANGE, TUTORIAL_XML, TUTORIAL_ID, TUTORIAL_STEP } from '../actions/types';
+import { TUTORIAL_PROGRESS, GET_TUTORIAL, GET_TUTORIALS, TUTORIAL_SUCCESS, TUTORIAL_ERROR, TUTORIAL_CHANGE, TUTORIAL_XML, TUTORIAL_STEP } from '../actions/types';
const initialStatus = () => {
From c6a1e854d25dc45898234420b3a7da742f78e9d3 Mon Sep 17 00:00:00 2001
From: Delucse <46593742+Delucse@users.noreply.github.com>
Date: Mon, 14 Dec 2020 14:48:12 +0100
Subject: [PATCH 07/16] get locale from user if exists
---
src/actions/authActions.js | 11 ++++++--
src/actions/generalActions.js | 5 +++-
src/components/Blockly/BlocklyWindow.js | 11 ++------
src/components/Content.js | 8 +++---
src/components/Settings/LanguageSelector.js | 4 +--
src/reducers/generalReducer.js | 30 ++++++++++++++++++---
6 files changed, 48 insertions(+), 21 deletions(-)
diff --git a/src/actions/authActions.js b/src/actions/authActions.js
index 7cdd1c0..fb454ba 100644
--- a/src/actions/authActions.js
+++ b/src/actions/authActions.js
@@ -1,8 +1,8 @@
import { MYBADGES_CONNECT, MYBADGES_DISCONNECT, USER_LOADED, USER_LOADING, AUTH_ERROR, LOGIN_SUCCESS, LOGIN_FAIL, LOGOUT_SUCCESS, LOGOUT_FAIL, REFRESH_TOKEN_SUCCESS } from '../actions/types';
import axios from 'axios';
-import { returnErrors, returnSuccess } from './messageActions'
-
+import { returnErrors, returnSuccess } from './messageActions';
+import { setLanguage } from './generalActions';
// Check token & load user
export const loadUser = () => (dispatch) => {
@@ -16,6 +16,7 @@ export const loadUser = () => (dispatch) => {
type: USER_LOADED,
payload: res.data.user
});
+ dispatch(setLanguage(res.data.user.language));
},
error: err => {
if(err.response){
@@ -61,6 +62,7 @@ export const login = ({ email, password }) => (dispatch) => {
type: LOGIN_SUCCESS,
payload: res.data
});
+ dispatch(setLanguage(res.data.user.language));
dispatch(returnSuccess(res.data.message, res.status, 'LOGIN_SUCCESS'));
})
.catch(err => {
@@ -130,6 +132,11 @@ export const logout = () => (dispatch) => {
dispatch({
type: LOGOUT_SUCCESS
});
+ var locale = 'de_DE';
+ if (window.localStorage.getItem('locale')) {
+ locale = window.localStorage.getItem('locale');
+ }
+ dispatch(setLanguage(locale));
dispatch(returnSuccess(res.data.message, res.status, 'LOGOUT_SUCCESS'));
clearTimeout(logoutTimerId);
},
diff --git a/src/actions/generalActions.js b/src/actions/generalActions.js
index 3bd0c64..6d1838b 100644
--- a/src/actions/generalActions.js
+++ b/src/actions/generalActions.js
@@ -7,7 +7,10 @@ export const visitPage = () => (dispatch) => {
});
};
-export const setLanguage = (language) => (dispatch) => {
+export const setLanguage = (language) => (dispatch, getState) => {
+ if(!getState().auth.isAuthenticated){
+ window.localStorage.setItem('locale', language);
+ }
dispatch({
type: LANGUAGE,
payload: language
diff --git a/src/components/Blockly/BlocklyWindow.js b/src/components/Blockly/BlocklyWindow.js
index 60b3ee3..aa9ce69 100644
--- a/src/components/Blockly/BlocklyWindow.js
+++ b/src/components/Blockly/BlocklyWindow.js
@@ -18,16 +18,9 @@ class BlocklyWindow extends Component {
constructor(props) {
super(props);
this.simpleWorkspace = React.createRef();
- // if (locale === null) {
- // if (navigator.language === 'de-DE') {
- // locale = 'de';
- // } else {
- // locale = 'en';
- // }
- // }
- if (this.props.language === 'de') {
+ if (this.props.language === 'de_DE') {
Blockly.setLocale(De);
- } else if (this.props.language === 'en') {
+ } else if (this.props.language === 'en_US') {
Blockly.setLocale(En);
}
}
diff --git a/src/components/Content.js b/src/components/Content.js
index 38e6b85..9260421 100644
--- a/src/components/Content.js
+++ b/src/components/Content.js
@@ -14,18 +14,18 @@ import Cookies from './Cookies';
class Content extends Component {
componentDidMount() {
- if (this.props.language === 'de') {
+ if (this.props.language === 'de_DE') {
Blockly.setLocale(De);
- } else if (this.props.language === 'en') {
+ } else if (this.props.language === 'en_US') {
Blockly.setLocale(En);
}
}
componentDidUpdate(props){
if(props.language !== this.props.language){
- if (this.props.language === 'de') {
+ if (this.props.language === 'de_DE') {
Blockly.setLocale(De);
- } else if (this.props.language === 'en') {
+ } else if (this.props.language === 'en_US') {
Blockly.setLocale(En);
}
}
diff --git a/src/components/Settings/LanguageSelector.js b/src/components/Settings/LanguageSelector.js
index 7164868..f069b1b 100644
--- a/src/components/Settings/LanguageSelector.js
+++ b/src/components/Settings/LanguageSelector.js
@@ -37,8 +37,8 @@ class LanguageSelector extends Component {
value={this.props.language}
onChange={this.handleChange}
>
-
{Blockly.Msg.settings_language_de}
-
{Blockly.Msg.settings_language_en}
+
{Blockly.Msg.settings_language_de}
+
{Blockly.Msg.settings_language_en}
diff --git a/src/reducers/generalReducer.js b/src/reducers/generalReducer.js
index 35ab59a..b76d9c2 100644
--- a/src/reducers/generalReducer.js
+++ b/src/reducers/generalReducer.js
@@ -1,11 +1,35 @@
import { VISIT, LANGUAGE, RENDERER, STATISTICS } from '../actions/types';
+const initialLanguage = () => {
+ if (window.localStorage.getItem('locale')) {
+ return window.localStorage.getItem('locale');
+ }
+ if (navigator.language === 'de-DE'){
+ return 'de_DE';
+ }
+ return 'en_US';
+};
+
+const initialRenderer = () => {
+ if (window.localStorage.getItem('renderer')) {
+ return window.localStorage.getItem('renderer');
+ }
+ return 'geras';
+};
+
+const initialStatistics = () => {
+ if (window.localStorage.getItem('statistics')) {
+ return JSON.parse(window.localStorage.getItem('statistics'));
+ }
+ return false;
+};
+
const initialState = {
pageVisits: 0, // detect if previous URL was
- language: 'de',
- renderer: window.localStorage.getItem('renderer') || 'geras',
- statistics: window.localStorage.getItem('statistics') === 'true' ? true : window.localStorage.getItem('statistics') === 'false' ? false : false
+ language: initialLanguage(),
+ renderer: initialRenderer(),
+ statistics: initialStatistics()
};
export default function(state = initialState, action){
From a99ecc36a40c13a4f2dfda6f677428c14b297cec Mon Sep 17 00:00:00 2001
From: Delucse <46593742+Delucse@users.noreply.github.com>
Date: Mon, 14 Dec 2020 15:15:08 +0100
Subject: [PATCH 08/16] routing improvement
---
src/components/Route/IsLoggedRoute.js | 7 +++++--
src/components/Route/PrivateRoute.js | 9 ++++++---
src/components/Route/PrivateRouteCreator.js | 9 ++++++---
3 files changed, 17 insertions(+), 8 deletions(-)
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));
From 49730f51ac27581384423f0d7884592af85c0bdd Mon Sep 17 00:00:00 2001
From: Delucse <46593742+Delucse@users.noreply.github.com>
Date: Mon, 14 Dec 2020 19:26:07 +0100
Subject: [PATCH 09/16] public route
---
src/actions/authActions.js | 9 ++++--
src/components/Blockly/BlocklyWindow.js | 20 +++++++-----
src/components/Route/PublicRoute.js | 32 ++++++++++++++++++
src/components/Route/Routes.js | 43 ++++++++++++++++++-------
src/components/Tutorial/Tutorial.js | 5 ++-
src/components/Workspace/SaveProject.js | 6 ++--
6 files changed, 89 insertions(+), 26 deletions(-)
create mode 100644 src/components/Route/PublicRoute.js
diff --git a/src/actions/authActions.js b/src/actions/authActions.js
index 2da6b9e..ebd8151 100644
--- a/src/actions/authActions.js
+++ b/src/actions/authActions.js
@@ -16,11 +16,11 @@ export const loadUser = () => (dispatch) => {
type: GET_STATUS,
payload: res.data.user.status
});
+ dispatch(setLanguage(res.data.user.language));
dispatch({
type: USER_LOADED,
payload: res.data.user
});
- dispatch(setLanguage(res.data.user.language));
},
error: err => {
if(err.response){
@@ -74,11 +74,11 @@ export const login = ({ email, password }) => (dispatch) => {
type: LOGIN_SUCCESS,
payload: res.data
});
+ dispatch(setLanguage(res.data.user.language));
dispatch({
type: GET_STATUS,
payload: res.data.user.status
});
- dispatch(setLanguage(res.data.user.language));
dispatch(returnSuccess(res.data.message, res.status, 'LOGIN_SUCCESS'));
})
.catch(err => {
@@ -172,10 +172,13 @@ export const logout = () => (dispatch) => {
type: GET_STATUS,
payload: status
});
- var locale = 'de_DE';
+ var locale = 'en_US';
if (window.localStorage.getItem('locale')) {
locale = window.localStorage.getItem('locale');
}
+ else if (navigator.language === 'de-DE'){
+ locale = 'de_DE';
+ }
dispatch(setLanguage(locale));
dispatch(returnSuccess(res.data.message, res.status, 'LOGOUT_SUCCESS'));
clearTimeout(logoutTimerId);
diff --git a/src/components/Blockly/BlocklyWindow.js b/src/components/Blockly/BlocklyWindow.js
index aa9ce69..d77d620 100644
--- a/src/components/Blockly/BlocklyWindow.js
+++ b/src/components/Blockly/BlocklyWindow.js
@@ -2,15 +2,15 @@ import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { onChangeWorkspace, clearStats } from '../../actions/workspaceActions';
-import { De } from './msg/de';
-import { En } from './msg/en';
+
import BlocklyComponent from './BlocklyComponent';
import BlocklySvg from './BlocklySvg';
+
import * as Blockly from 'blockly/core';
import './blocks/index';
import './generator/index';
-import { initialXml } from './initialXml.js';
+import { initialXml } from './initialXml.js';
class BlocklyWindow extends Component {
@@ -18,11 +18,6 @@ class BlocklyWindow extends Component {
constructor(props) {
super(props);
this.simpleWorkspace = React.createRef();
- if (this.props.language === 'de_DE') {
- Blockly.setLocale(De);
- } else if (this.props.language === 'en_US') {
- Blockly.setLocale(En);
- }
}
componentDidMount() {
@@ -50,6 +45,15 @@ class BlocklyWindow extends Component {
if (!xml) xml = initialXml;
Blockly.Xml.domToWorkspace(Blockly.Xml.textToDom(xml), workspace);
}
+ if(props.language !== this.props.language){
+ // change language
+ if (!xml) xml = initialXml;
+ var xmlDom = Blockly.Xml.textToDom(xml);
+ Blockly.Xml.clearWorkspaceAndLoadFromXml(xmlDom, workspace);
+ // var toolbox = workspace.getToolbox();
+ // console.log(toolbox);
+ // workspace.updateToolbox(toolbox.toolboxDef_);
+ }
Blockly.svgResize(workspace);
}
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/Tutorial/Tutorial.js b/src/components/Tutorial/Tutorial.js
index b6fd1f7..299c788 100644
--- a/src/components/Tutorial/Tutorial.js
+++ b/src/components/Tutorial/Tutorial.js
@@ -5,6 +5,8 @@ import { workspaceName } from '../../actions/workspaceActions';
import { clearMessages } from '../../actions/messageActions';
import { getTutorial, resetTutorial, tutorialStep,tutorialProgress } from '../../actions/tutorialActions';
+import { withRouter } from 'react-router-dom';
+
import Breadcrumbs from '../Breadcrumbs';
import StepperHorizontal from './StepperHorizontal';
import StepperVertical from './StepperVertical';
@@ -26,6 +28,7 @@ class Tutorial extends Component {
// retrieve tutorial only if a potential user is loaded - authentication
// is finished (success or failed)
if(!this.props.progress){
+ console.log(this.props);
this.props.getTutorial(this.props.match.params.tutorialId);
}
}
@@ -120,4 +123,4 @@ const mapStateToProps = state => ({
progress: state.auth.progress
});
-export default connect(mapStateToProps, { getTutorial, resetTutorial, tutorialStep, tutorialProgress, clearMessages, workspaceName })(Tutorial);
+export default connect(mapStateToProps, { getTutorial, resetTutorial, tutorialStep, tutorialProgress, clearMessages, workspaceName })(withRouter(Tutorial));
diff --git a/src/components/Workspace/SaveProject.js b/src/components/Workspace/SaveProject.js
index a71e968..733ff76 100644
--- a/src/components/Workspace/SaveProject.js
+++ b/src/components/Workspace/SaveProject.js
@@ -100,10 +100,10 @@ class SaveProject extends Component {
success: res => {
var project = res.data[this.state.projectType];
this.props.history.push(`/${this.state.projectType}/${project._id}`);
- })
- .catch(err => {
+ },
+ error: err => {
this.setState({ snackbar: true, key: Date.now(), message: `${Blockly.Msg.messages_gallery_save_fail_1} ${this.state.projectType === 'gallery' ? 'Galerie-' : ''} ${Blockly.Msg.messages_gallery_save_fail_2}`, type: 'error' });
- window.scrollTo(0, 0);
+ window.scrollTo(0, 0);
}
};
axios.post(`${process.env.REACT_APP_BLOCKLY_API}/${this.state.projectType}`, body, config)
From b04a5bc591cfa9cd195069c7dece8e03d604bf6c Mon Sep 17 00:00:00 2001
From: Delucse <46593742+Delucse@users.noreply.github.com>
Date: Mon, 14 Dec 2020 20:04:49 +0100
Subject: [PATCH 10/16] store locale in localStorage only if user is not logged
in
---
src/actions/authActions.js | 5 ++++-
src/actions/generalActions.js | 2 +-
2 files changed, 5 insertions(+), 2 deletions(-)
diff --git a/src/actions/authActions.js b/src/actions/authActions.js
index ebd8151..77e3f4b 100644
--- a/src/actions/authActions.js
+++ b/src/actions/authActions.js
@@ -54,6 +54,9 @@ const timeToLogout = 14.9*60*1000; // nearly 15 minutes corresponding to the API
// Login user
export const login = ({ email, password }) => (dispatch) => {
+ dispatch({
+ type: USER_LOADING
+ });
// Headers
const config = {
headers: {
@@ -70,11 +73,11 @@ export const login = ({ email, password }) => (dispatch) => {
timeToLogout
);
logoutTimerId = logoutTimer();
+ dispatch(setLanguage(res.data.user.language));
dispatch({
type: LOGIN_SUCCESS,
payload: res.data
});
- dispatch(setLanguage(res.data.user.language));
dispatch({
type: GET_STATUS,
payload: res.data.user.status
diff --git a/src/actions/generalActions.js b/src/actions/generalActions.js
index 6d1838b..754f438 100644
--- a/src/actions/generalActions.js
+++ b/src/actions/generalActions.js
@@ -8,7 +8,7 @@ export const visitPage = () => (dispatch) => {
};
export const setLanguage = (language) => (dispatch, getState) => {
- if(!getState().auth.isAuthenticated){
+ if(!getState().auth.progress && !getState().auth.isAuthenticated){
window.localStorage.setItem('locale', language);
}
dispatch({
From 9d65f7b944927f669f78bcf667cdb0d350d589f3 Mon Sep 17 00:00:00 2001
From: Mario
Date: Tue, 15 Dec 2020 09:51:12 +0100
Subject: [PATCH 11/16] add en translations
---
src/components/Blockly/msg/de.js | 2 +
src/components/Blockly/msg/en.js | 125 ++++++++++++++++++++++++++-----
2 files changed, 107 insertions(+), 20 deletions(-)
diff --git a/src/components/Blockly/msg/de.js b/src/components/Blockly/msg/de.js
index 83207d7..7ca390d 100644
--- a/src/components/Blockly/msg/de.js
+++ b/src/components/Blockly/msg/de.js
@@ -995,4 +995,6 @@ Blockly.Msg.builder_requirements_order = "Beachte, dass die Reihenfolge des Anha
Blockly.Msg.login_head = "Anmelden"
+
+
export const De = Blockly.Msg;
diff --git a/src/components/Blockly/msg/en.js b/src/components/Blockly/msg/en.js
index b895bac..993b6b3 100644
--- a/src/components/Blockly/msg/en.js
+++ b/src/components/Blockly/msg/en.js
@@ -782,14 +782,12 @@ Blockly.Msg.senseBox_mqtt_password = "Password";
Blockly.Msg.sensebox_mqtt_subscribe = "Subscribe to Feed"
Blockly.Msg.senseBox_mqtt_publish = "Publish to Feed/Topic";
-
/**
* Add Translation for Blocks above
* ---------------------------------------------------------------
* Add Translation for the UI below
*/
-
/**
* Toolbox
*/
@@ -802,36 +800,70 @@ Blockly.Msg.toolbox_time = "Time";
Blockly.Msg.toolbox_functions = "Functions";
Blockly.Msg.toolbox_variables = "Variables";
-
/**
* Tooltips
*
*/
-Blockly.Msg.tooltip_compile_code = "Compile Code"
-Blockly.Msg.tooltip_save_blocks = "Save Blocks";
-Blockly.Msg.tooltip_open_blocks = "Open Blocks";
-Blockly.Msg.tooltip_screenshot = "Download Screenshot";
-Blockly.Msg.tooltip_clear_workspace = "Reset Workspace";
-Blockly.Msg.tooltip_share_blocks = "Share Blocks";
-Blockly.Msg.tooltip_show_code = "Show Code";
-Blockly.Msg.tooltip_hide_code = "Hide Code"
+Blockly.Msg.tooltip_compile_code = "Compile code"
+Blockly.Msg.tooltip_save_blocks = "Save blocks";
+Blockly.Msg.tooltip_open_blocks = "Open blocks";
+Blockly.Msg.tooltip_screenshot = "Download screenshot";
+Blockly.Msg.tooltip_clear_workspace = "Reset workspace";
+Blockly.Msg.tooltip_share_blocks = "Share blocks";
+Blockly.Msg.tooltip_show_code = "Show code";
+Blockly.Msg.tooltip_hide_code = "Hide code "
+Blockly.Msg.tooltip_delete_project = "Delete project"
+Blockly.Msg.tooltip_project_name = "Project name"
+Blockly.Msg.tooltip_download_project = "Download project"
+Blockly.Msg.tooltip_open_project = "Open project"
+Blockly.Msg.tooltip_update_project = "Update project"
+Blockly.Msg.tooltip_save_project = "Save project"
+Blockly.Msg.tooltip_create_project = "Create project"
+Blockly.Msg.tooltip_share_project = "Share project"
+Blockly.Msg.tooltip_reset_workspace = "Reset workspace"
+Blockly.Msg.tooltip_copy_link = "Cooy link"
+Blockly.Msg.tooltip_trashcan_hide = "hide deleted blocks"
+Blockly.Msg.tooltip_trashcan_delete = "empty trashcan"
+Blockly.Msg.tooltip_project_title = "Project title"
+Blockly.Msg.tooltip_check_solution = "Check solution"
+
+/**
+ * Messages
+ *
+ */
+
+Blockly.Msg.messages_delete_project_failed = "Error deleting the project. Try again."
+Blockly.Msg.messages_reset_workspace_success = "The project has been successfully reset."
+Blockly.Msg.messages_PROJECT_UPDATE_SUCCESS = "The project was successfully updated."
+Blockly.Msg.messages_GALLERY_UPDATE_SUCCESS = "The gallery project was successfully updated."
+Blockly.Msg.messages_PROJECT_UPDATE_FAIL = "Error updating the project. Try again."
+Blockly.Msg.messages_GALLERY_UPDATE_FAIL = "Error updating the gallery project. Try again."
+Blockly.Msg.messages_gallery_save_fail_1 = "Error saving the "
+Blockly.Msg.messages_gallery_save_fail_2 = "Project. Try again."
+Blockly.Msg.messages_SHARE_SUCCESS = 'Share program'
+Blockly.Msg.messages_SHARE_FAIL = "Error creating a link to share your program. Try again."
+Blockly.Msg.messages_copylink_success = 'Link successfully saved to clipboard.'
+Blockly.Msg.messages_rename_success_01 = 'The project was successfully saved to '
+Blockly.Msg.messages_rename_success_02 = 'renamed.'
+Blockly.Msg.messages_newblockly_head = 'Welcome to the new version Blockly for the senseBox'
+Blockly.Msg.messages_newblockly_text = "The new Blockly version is currently in testing. You can find all the news here:"
+Blockly.Msg.messages_GET_TUTORIAL_FAIL = 'Back to tutorials overview'
+Blockly.Msg.messages_LOGIN_FAIL = 'The username or password is incorrect.'
-Blockly.Msg.tooltip_project_name = "Projectname"
/**
* Share Dialog
*/
-Blockly.Msg.sharedialog_headline = "Your Share-Link was created";
-Blockly.Msg.sharedialog_text = "Share your project with the following link";
+Blockly.Msg.sharedialog_headline = "Your link has been created.";
+Blockly.Msg.sharedialog_text = "You can share your program using the following link.";
/**
* Project rename Dialog
*/
-Blockly.Msg.renamedialog_headline = "Rename Project";
-Blockly.Msg.renamedialog_text = "Please enter a name for the project and confirm it by clicking on 'Confirm'."
-
+Blockly.Msg.renamedialog_headline = "Rename project";
+Blockly.Msg.renamedialog_text = "Please enter a name for the project and confirm it by clicking 'Confirm'."
/**
* Compile Dialog
*
@@ -840,8 +872,6 @@ Blockly.Msg.renamedialog_text = "Please enter a name for the project and confirm
Blockly.Msg.compiledialog_headline = "Error"
Blockly.Msg.compiledialog_text = "While compiling an error occured. Please check your blocks and try again"
-
-
/**
* Buttons
*
@@ -849,9 +879,12 @@ Blockly.Msg.compiledialog_text = "While compiling an error occured. Please check
Blockly.Msg.button_cancel = "Cancel";
Blockly.Msg.button_close = "Close";
-Blockly.Msg.button_accept = "Confirm";
+Blockly.Msg.button_accept = "Ok";
Blockly.Msg.button_compile = "Compile";
Blockly.Msg.button_create_variableCreate = "Create Variable";
+Blockly.Msg.button_back = "Back"
+Blockly.Msg.button_next = "Next step"
+Blockly.Msg.button_tutorial_overview = "Tutorial overview"
/**
@@ -861,6 +894,58 @@ Blockly.Msg.button_create_variableCreate = "Create Variable";
Blockly.Msg.filename = "Filename";
Blockly.Msg.projectname = "Projectname";
+/**
+ * 404
+ */
+
+Blockly.Msg.notfound_head = "The page you requested cannot be found."
+Blockly.Msg.notfound_text = "The page you are looking for may have been removed, its name changed, or it may be temporarily unavailable."
+
+/**
+ * Labels
+ */
+Blockly.Msg.labels_donotshowagain = 'Do not show dialog again'
+Blockly.Msg.labels_here = 'here'
+Blockly.Msg.labels_username = 'Email or username'
+/**
+ * Badges
+ */
+
+Blockly.Msg.badges_explaination = "An overview of all badges received in the Blockly for senseBox context can be found "
+Blockly.Msg.badges_ASSIGNE_BADGE_SUCCESS_01 = "Congratulations! You have received the badge "
+Blockly.Msg.badges_ASSIGNE_BADGE_SUCCESS_02 = "."
+/**
+ * Tutorials
+ */
+
+Blockly.Msg.tutorials_assessment_task = "Task"
+Blockly.Msg.tutorials_hardware_head = "For the implementation you need the following hardware:"
+Blockly.Msg.tutorials_hardware_moreInformation = "You can find more information about the hardware component."
+Blockly.Msg.tutorials_hardware_here = "here";
+Blockly.Msg.tutorials_requirements = "Before continuing with this tutorial, you should have successfully completed the following tutorials:"
+
+
+/**
+ * Tutorial Builder
+ */
+
+Blockly.Msg.builder_solution = "Solution"
+Blockly.Msg.builder_solution_submit = "Submit Solution"
+Blockly.Msg.builder_example_submit = "Submit example"
+Blockly.Msg.builder_comment = "Note: You can delete the initial setup() or infinite loop() block. Additionally, it is possible to select only any block, among others, without displaying it as disabled."
+Blockly.Msg.builder_hardware_order = "Note that the order of selection is authoritative."
+Blockly.Msg.builder_hardware_helper = "Select at least one hardware component."
+Blockly.Msg.builder_requirements_head = "Requirements."
+Blockly.Msg.builder_requirements_order = "Note that the order of ticking is authoritative."
+
+/**
+ * Login
+ */
+
+
+Blockly.Msg.login_head = "Login"
+
+
/**
* Settings
*/
From 256593164f06a264ca8a549c4c86520d01c382c5 Mon Sep 17 00:00:00 2001
From: Mario
Date: Tue, 15 Dec 2020 10:04:33 +0100
Subject: [PATCH 12/16] add navbar translations
---
src/components/Blockly/msg/de.js | 17 +++++++++++++++++
src/components/Blockly/msg/en.js | 13 +++++++++++++
src/components/Navbar.js | 22 ++++++++++++----------
3 files changed, 42 insertions(+), 10 deletions(-)
diff --git a/src/components/Blockly/msg/de.js b/src/components/Blockly/msg/de.js
index 7ca390d..b8df029 100644
--- a/src/components/Blockly/msg/de.js
+++ b/src/components/Blockly/msg/de.js
@@ -997,4 +997,21 @@ Blockly.Msg.builder_requirements_order = "Beachte, dass die Reihenfolge des Anha
Blockly.Msg.login_head = "Anmelden"
+/**
+ * Navbar
+ */
+
+Blockly.Msg.navbar_tutorials = "Tutorials"
+Blockly.Msg.navbar_tutorialbuilder = "Tutorial erstellen"
+Blockly.Msg.navbar_gallery = "Gallerie"
+Blockly.Msg.navbar_projects = "Projekte"
+
+Blockly.Msg.navbar_menu = "Menü"
+Blockly.Msg.navbar_login = "Einloggen"
+Blockly.Msg.navbar_mybadges = "myBadges"
+Blockly.Msg.navbar_account = "Konto"
+Blockly.Msg.navbar_logout = "Abmelden"
+Blockly.Msg.navbar_settings = "Einstellungen"
+
+
export const De = Blockly.Msg;
diff --git a/src/components/Blockly/msg/en.js b/src/components/Blockly/msg/en.js
index 993b6b3..393502f 100644
--- a/src/components/Blockly/msg/en.js
+++ b/src/components/Blockly/msg/en.js
@@ -961,7 +961,20 @@ Blockly.Msg.settings_statistics_text = "The display of statistics on the usage o
Blockly.Msg.settings_statistics_on = "On"
Blockly.Msg.settings_statistics_off = "Off"
+/**
+ * Navbar
+ */
+Blockly.Msg.navbar_tutorials = "Tutorials"
+Blockly.Msg.navbar_tutorialbuilder = "Create tutorial"
+Blockly.Msg.navbar_gallery = "Gallery"
+Blockly.Msg.navbar_projects = "Projects"
+Blockly.Msg.navbar_menu = "Menu"
+Blockly.Msg.navbar_login = "Login"
+Blockly.Msg.navbar_mybadges = "myBadges"
+Blockly.Msg.navbar_account = "Account"
+Blockly.Msg.navbar_logout = "Logout"
+Blockly.Msg.navbar_settings = "Settings"
export const En = Blockly.Msg;
diff --git a/src/components/Navbar.js b/src/components/Navbar.js
index a3e6949..dbdd561 100644
--- a/src/components/Navbar.js
+++ b/src/components/Navbar.js
@@ -23,6 +23,8 @@ import LinearProgress from '@material-ui/core/LinearProgress';
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,10 +102,10 @@ 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) => {
+ {[{ 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 (
@@ -119,11 +121,11 @@ class Navbar extends Component {
- {[{ 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) => {
+ {[{ 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 (
From 813582bf9de62d37c9e7ac73c73c8ae7be8f4b36 Mon Sep 17 00:00:00 2001
From: Mario
Date: Tue, 15 Dec 2020 10:27:50 +0100
Subject: [PATCH 13/16] translations for login page
---
src/components/Blockly/msg/de.js | 9 ++++++---
src/components/Blockly/msg/en.js | 10 ++++++++--
src/components/User/Login.js | 14 +++++++-------
3 files changed, 21 insertions(+), 12 deletions(-)
diff --git a/src/components/Blockly/msg/de.js b/src/components/Blockly/msg/de.js
index b8df029..038843a 100644
--- a/src/components/Blockly/msg/de.js
+++ b/src/components/Blockly/msg/de.js
@@ -918,7 +918,7 @@ Blockly.Msg.button_create_variableCreate = "Erstelle Variable";
Blockly.Msg.button_back = "Zurück"
Blockly.Msg.button_next = "nächster Schritt"
Blockly.Msg.button_tutorial_overview = "Tutorial Übersicht"
-
+Blockly.Msg.button_login = "Anmelden"
/**
*
@@ -957,6 +957,7 @@ Blockly.Msg.notfound_text = "Die gesuchte Seite wurde möglicherweise entfernt,
Blockly.Msg.labels_donotshowagain = 'Dialog nicht mehr anzeigen'
Blockly.Msg.labels_here = "hier"
Blockly.Msg.labels_username = 'E-Mail oder Nutzername'
+Blockly.Msg.labels_password = "Passwort"
/**
* Badges
@@ -995,8 +996,10 @@ Blockly.Msg.builder_requirements_order = "Beachte, dass die Reihenfolge des Anha
Blockly.Msg.login_head = "Anmelden"
-
-
+Blockly.Msg.login_osem_account_01 = "Du benötigst einen "
+Blockly.Msg.login_osem_account_02 = "Account um dich einzuloggen"
+Blockly.Msg.login_lostpassword = "Du hast dein Passwort vergessen?"
+Blockly.Msg.login_createaccount = "Falls du noch keinen Account hast erstellen einen auf "
/**
* Navbar
*/
diff --git a/src/components/Blockly/msg/en.js b/src/components/Blockly/msg/en.js
index 393502f..a0a2724 100644
--- a/src/components/Blockly/msg/en.js
+++ b/src/components/Blockly/msg/en.js
@@ -850,7 +850,7 @@ Blockly.Msg.messages_newblockly_head = 'Welcome to the new version Blockly for t
Blockly.Msg.messages_newblockly_text = "The new Blockly version is currently in testing. You can find all the news here:"
Blockly.Msg.messages_GET_TUTORIAL_FAIL = 'Back to tutorials overview'
Blockly.Msg.messages_LOGIN_FAIL = 'The username or password is incorrect.'
-
+Blockly.Msg.messages_login_error = "Enter both a username and a password."
/**
* Share Dialog
*/
@@ -885,7 +885,7 @@ Blockly.Msg.button_create_variableCreate = "Create Variable";
Blockly.Msg.button_back = "Back"
Blockly.Msg.button_next = "Next step"
Blockly.Msg.button_tutorial_overview = "Tutorial overview"
-
+Blockly.Msg.button_login = "Login"
/**
*
@@ -907,6 +907,7 @@ Blockly.Msg.notfound_text = "The page you are looking for may have been removed,
Blockly.Msg.labels_donotshowagain = 'Do not show dialog again'
Blockly.Msg.labels_here = 'here'
Blockly.Msg.labels_username = 'Email or username'
+Blockly.Msg.labels_password = "Password"
/**
* Badges
*/
@@ -944,6 +945,11 @@ Blockly.Msg.builder_requirements_order = "Note that the order of ticking is auth
Blockly.Msg.login_head = "Login"
+Blockly.Msg.login_osem_account_01 = "You need to have an "
+Blockly.Msg.login_osem_account_02 = "Account to login"
+Blockly.Msg.login_lostpassword = "Lost your password?"
+Blockly.Msg.login_createaccount = "If you don't have an openSenseMap account please register on "
+
/**
diff --git a/src/components/User/Login.js b/src/components/User/Login.js
index 75a4948..a84b30a 100644
--- a/src/components/User/Login.js
+++ b/src/components/User/Login.js
@@ -71,7 +71,7 @@ export class Login extends Component {
};
this.props.login(user);
} else {
- this.setState({ snackbar: true, key: Date.now(), message: 'Gib sowohl ein Benutzername als auch ein Passwort ein.', type: 'error' });
+ this.setState({ snackbar: true, key: Date.now(), message: Blockly.Msg.messages_login_error, type: 'error' });
}
};
@@ -86,12 +86,12 @@ export class Login extends Component {
render() {
return (
-
+
{Blockly.Msg.login_head}
- Zur Anmeldung ist ein Konto auf openSenseMap Voraussetzung.
+ {Blockly.Msg.login_osem_account_01} openSenseMap {Blockly.Msg.login_osem_account_02}.
{this.props.progress ?
- : 'Anmelden'}
+ : Blockly.Msg.button_login}
- Passwort vergessen?
+ {Blockly.Msg.login_lostpassword}
- Du hast noch kein Konto? Registriere dich auf openSenseMap.
+ {Blockly.Msg.login_createaccount} openSenseMap.
From 7d876e8bf9c96e90fd8e006eab24a2252615642a Mon Sep 17 00:00:00 2001
From: Mario
Date: Tue, 15 Dec 2020 10:39:22 +0100
Subject: [PATCH 14/16] codeviewer translations
---
src/components/Blockly/msg/de.js | 7 +++++++
src/components/Blockly/msg/en.js | 4 ++++
src/components/CodeViewer.js | 5 +++--
3 files changed, 14 insertions(+), 2 deletions(-)
diff --git a/src/components/Blockly/msg/de.js b/src/components/Blockly/msg/de.js
index 038843a..7974c65 100644
--- a/src/components/Blockly/msg/de.js
+++ b/src/components/Blockly/msg/de.js
@@ -1016,5 +1016,12 @@ Blockly.Msg.navbar_account = "Konto"
Blockly.Msg.navbar_logout = "Abmelden"
Blockly.Msg.navbar_settings = "Einstellungen"
+/**
+ * Codeviewer
+ */
+
+Blockly.Msg.codeviewer_arduino = "Arduino Quellcode"
+Blockly.Msg.codeviewer_xml = "XML Blöcke"
+
export const De = Blockly.Msg;
diff --git a/src/components/Blockly/msg/en.js b/src/components/Blockly/msg/en.js
index a0a2724..e7ca221 100644
--- a/src/components/Blockly/msg/en.js
+++ b/src/components/Blockly/msg/en.js
@@ -983,4 +983,8 @@ Blockly.Msg.navbar_account = "Account"
Blockly.Msg.navbar_logout = "Logout"
Blockly.Msg.navbar_settings = "Settings"
+
+Blockly.Msg.codeviewer_arduino = "Arduino Source Code"
+Blockly.Msg.codeviewer_xml = "XML Blocks"
+
export const En = Blockly.Msg;
diff --git a/src/components/CodeViewer.js b/src/components/CodeViewer.js
index 35a972a..dd41fc4 100644
--- a/src/components/CodeViewer.js
+++ b/src/components/CodeViewer.js
@@ -13,6 +13,7 @@ import MuiAccordion from '@material-ui/core/Accordion';
import MuiAccordionSummary from '@material-ui/core/AccordionSummary';
import MuiAccordionDetails from '@material-ui/core/AccordionDetails';
import { Card } from '@material-ui/core';
+import * as Blockly from 'blockly'
const Accordion = withStyles((theme) => ({
@@ -94,7 +95,7 @@ class CodeViewer extends Component {
>
{curlyBrackets}
- Arduino Quellcode
+ {Blockly.Msg.codeviewer_arduino}
@@ -112,7 +113,7 @@ class CodeViewer extends Component {
>
{unequal}
- XML Blöcke
+ {Blockly.Msg.codeviewer_xml}
From 84ce074aec855723c7aec9c7b5f7c342e31c79fa Mon Sep 17 00:00:00 2001
From: Delucse <46593742+Delucse@users.noreply.github.com>
Date: Tue, 15 Dec 2020 11:18:59 +0100
Subject: [PATCH 15/16] aprovement of adding badge to tutorial
---
src/components/Tutorial/Builder/Badge.js | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/components/Tutorial/Builder/Badge.js b/src/components/Tutorial/Builder/Badge.js
index a2c08c5..88386a3 100644
--- a/src/components/Tutorial/Builder/Badge.js
+++ b/src/components/Tutorial/Builder/Badge.js
@@ -137,6 +137,7 @@ class Badge extends Component {
value={this.state.badgeName}
label={'Badge'}
id={'badge'}
+ disabled={this.props.badge}
onChange={(e) => this.onChange(e)}
onInput={(e) => this.onChangeBadge(e)}
fullWidth={true}
From 0239ae28aa862db2e9324b5453ceda91e1065e49 Mon Sep 17 00:00:00 2001
From: Delucse <46593742+Delucse@users.noreply.github.com>
Date: Tue, 15 Dec 2020 11:33:04 +0100
Subject: [PATCH 16/16] create tutorial buttons
---
src/components/Tutorial/Builder/Builder.js | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
diff --git a/src/components/Tutorial/Builder/Builder.js b/src/components/Tutorial/Builder/Builder.js
index 40595cc..74fbea4 100644
--- a/src/components/Tutorial/Builder/Builder.js
+++ b/src/components/Tutorial/Builder/Builder.js
@@ -355,6 +355,23 @@ class Builder extends Component {
)}
+ {/*submit or reset*/}
+ {this.state.tutorial !== 'delete' ?
+
+
+ {this.state.tutorial === 'new' ?
+
+ this.submitNew()}>Tutorial erstellen
+ this.resetFull()}>Zurücksetzen
+
+ :
+ this.submitUpdate()}>Tutorial ändern
+ this.resetTutorial()}>Zurücksetzen
+
+ }
+
+ : null}
+