diff --git a/src/actions/tutorialBuilderActions.js b/src/actions/tutorialBuilderActions.js
index 4cfee80..03f7662 100644
--- a/src/actions/tutorialBuilderActions.js
+++ b/src/actions/tutorialBuilderActions.js
@@ -1,4 +1,4 @@
-import { BUILDER_CHANGE, BUILDER_ERROR, BUILDER_TITLE, BUILDER_ID, BUILDER_ADD_STEP, BUILDER_DELETE_STEP, BUILDER_CHANGE_STEP, BUILDER_CHANGE_ORDER, BUILDER_DELETE_PROPERTY } from './types';
+import { PROGRESS, BUILDER_CHANGE, BUILDER_ERROR, BUILDER_TITLE, BUILDER_ID, BUILDER_ADD_STEP, BUILDER_DELETE_STEP, BUILDER_CHANGE_STEP, BUILDER_CHANGE_ORDER, BUILDER_DELETE_PROPERTY } from './types';
export const changeTutorialBuilder = () => (dispatch) => {
dispatch({
@@ -14,6 +14,14 @@ export const tutorialTitle = (title) => (dispatch) => {
dispatch(changeTutorialBuilder());
};
+export const tutorialSteps = (steps) => (dispatch) => {
+ dispatch({
+ type: BUILDER_ADD_STEP,
+ payload: steps
+ });
+ dispatch(changeTutorialBuilder());
+};
+
export const tutorialId = (id) => (dispatch) => {
dispatch({
type: BUILDER_ID,
@@ -116,7 +124,6 @@ export const changeErrorStepIndex = (fromIndex, toIndex) => (dispatch, getState)
export const setError = (index, property) => (dispatch, getState) => {
var error = getState().builder.error;
- console.log(index);
if(index !== undefined){
error.steps[index][property] = true;
}
@@ -147,21 +154,21 @@ export const deleteError = (index, property) => (dispatch, getState) => {
export const setSubmitError = () => (dispatch, getState) => {
var builder = getState().builder;
- if(builder.id === ''){
+ if(builder.id === undefined || builder.id === ''){
dispatch(setError(undefined, 'id'));
}
- if(builder.title === ''){
+ if(builder.id === undefined || builder.title === ''){
dispatch(setError(undefined, 'title'));
}
for(var i = 0; i < builder.steps.length; i++){
builder.steps[i].id = i+1;
- if(i === 0 && builder.steps[i].hardware.length < 1){
+ if(i === 0 && (builder.steps[i].hardware === undefined || builder.steps[i].hardware.length < 1)){
dispatch(setError(i, 'hardware'));
}
- if(builder.steps[i].headline === ''){
+ if(builder.steps[i].headline === undefined || builder.steps[i].headline === ''){
dispatch(setError(i, 'headline'));
}
- if(builder.steps[i].text === ''){
+ if(builder.steps[i].text === undefined || builder.steps[i].text === ''){
dispatch(setError(i, 'text'));
}
}
@@ -180,3 +187,45 @@ export const checkError = () => (dispatch, getState) => {
}
return false;
}
+
+export const progress = (inProgress) => (dispatch) => {
+ dispatch({
+ type: PROGRESS,
+ payload: inProgress
+ })
+};
+
+export const resetTutorial = () => (dispatch, getState) => {
+ dispatch(tutorialTitle(''));
+ dispatch(tutorialId(''));
+ var steps = [
+ {
+ id: 1,
+ type: 'instruction',
+ headline: '',
+ text: '',
+ hardware: [],
+ requirements: []
+ }
+ ];
+ dispatch(tutorialSteps(steps));
+ dispatch({
+ type: BUILDER_ERROR,
+ payload: {
+ steps: [{}]
+ }
+ });
+};
+
+export const readJSON = (json) => (dispatch, getState) => {
+ dispatch(resetTutorial());
+ dispatch({
+ type: BUILDER_ERROR,
+ payload: {steps: [{},{}]}
+ });
+ dispatch(tutorialTitle(json.title));
+ dispatch(tutorialId(json.id));
+ dispatch(tutorialSteps(json.steps));
+ dispatch(setSubmitError());
+ dispatch(progress(false));
+};
diff --git a/src/actions/types.js b/src/actions/types.js
index c5fb2a5..e31e72f 100644
--- a/src/actions/types.js
+++ b/src/actions/types.js
@@ -25,3 +25,4 @@ export const BUILDER_CHANGE_STEP = 'BUILDER_CHANGE_STEP';
export const BUILDER_CHANGE_ORDER = 'BUILDER_CHANGE_ORDER';
export const BUILDER_DELETE_PROPERTY = 'BUILDER_DELETE_PROPERTY';
export const BUILDER_ERROR = 'BUILDER_ERROR';
+export const PROGRESS = 'PROGRESS';
diff --git a/src/components/Tutorial/Builder/BlocklyExample.js b/src/components/Tutorial/Builder/BlocklyExample.js
index c8e8994..9c64bf4 100644
--- a/src/components/Tutorial/Builder/BlocklyExample.js
+++ b/src/components/Tutorial/Builder/BlocklyExample.js
@@ -5,7 +5,9 @@ import { changeContent, deleteProperty, setError, deleteError } from '../../../a
import moment from 'moment';
import localization from 'moment/locale/de';
+import * as Blockly from 'blockly/core';
+import { parseXml } from '../../../helpers/compareXml';
import BlocklyWindow from '../../Blockly/BlocklyWindow';
import { withStyles } from '@material-ui/core/styles';
@@ -94,27 +96,38 @@ class BlocklyExample extends Component {
/>
}
/>
- {this.state.checked ? !this.props.value ?
+ {this.state.checked ? !this.props.value || this.props.error.steps[this.props.index].xml ?
Reiche deine Blöcke ein, indem du auf den rot gefärbten Button klickst.
: Die letzte Einreichung erfolgte um {this.state.input} Uhr.
: null}
- {this.state.checked ?
-
-
-
-
+ {this.state.checked ? () => {
+ var initialXml = this.props.value;
+ // check if value is valid xml;
+ try{
+ Blockly.Xml.textToDom(initialXml);
+ }
+ catch(err){
+ initialXml = null;
+ this.props.setError(this.props.index, 'xml');
+ }
+ return(
+
+
+
+
+
-
-
-
+
+
+ )}
: null}
);
diff --git a/src/components/Tutorial/Builder/Builder.js b/src/components/Tutorial/Builder/Builder.js
index 2789fd3..9b3aa8e 100644
--- a/src/components/Tutorial/Builder/Builder.js
+++ b/src/components/Tutorial/Builder/Builder.js
@@ -1,10 +1,11 @@
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
-import { checkError } from '../../../actions/tutorialBuilderActions';
+import { checkError, readJSON, progress, resetTutorial } from '../../../actions/tutorialBuilderActions';
import { saveAs } from 'file-saver';
+import data from '../../../data/hardware.json';
import { detectWhitespacesAndReturnReadableResult } from '../../../helpers/whitespace';
import Breadcrumbs from '../../Breadcrumbs';
@@ -12,14 +13,30 @@ import Id from './Id';
import Title from './Textfield';
import Step from './Step';
+import { withStyles } from '@material-ui/core/styles';
import Button from '@material-ui/core/Button';
+import Backdrop from '@material-ui/core/Backdrop';
+import CircularProgress from '@material-ui/core/CircularProgress';
+import Divider from '@material-ui/core/Divider';
+
+const styles = (theme) => ({
+ backdrop: {
+ zIndex: theme.zIndex.drawer + 1,
+ color: '#fff',
+ }
+});
class Builder extends Component {
+ constructor(props){
+ super(props);
+ this.inputRef = React.createRef();
+ }
+
submit = () => {
var isError = this.props.checkError();
if(isError){
- alert('Error');
+ window.scrollTo(0, 0);
}
else{
var tutorial = {
@@ -32,6 +49,74 @@ class Builder extends Component {
}
}
+ reset = () => {
+ this.props.resetTutorial();
+ window.scrollTo(0, 0);
+ }
+
+ uploadJsonFile = (jsonFile) => {
+ this.props.progress(true);
+ if(jsonFile.type !== 'application/json'){
+ alert('falscher Dateityp');
+ this.props.progress(false);
+ this.setState({ open: true, file: false, title: 'Unzulässiger Dateityp', content: 'Die übergebene Datei entsprach nicht dem geforderten Format. Es sind nur JSON-Dateien zulässig.' });
+ }
+ else {
+ var reader = new FileReader();
+ reader.readAsText(jsonFile);
+ reader.onloadend = () => {
+ try {
+ var result = JSON.parse(reader.result);
+ if(this.checkSteps(result.steps)){
+ alert('Hier');
+ this.props.readJSON(result);
+ }
+ else{
+ this.props.progress(false);
+ alert('die JSON-Datei hat nicht die richtige Form');
+ }
+ } catch(err){
+ this.props.progress(false);
+ alert('ungültige JSON-Datei');
+ this.setState({ open: true, file: false, title: 'Ungültige XML', content: 'Die XML-Datei konnte nicht in Blöcke zerlegt werden. Bitte überprüfe den XML-Code und versuche es erneut.' });
+ }
+ };
+ }
+ }
+
+ checkSteps = (steps) => {
+ if(!(steps && steps.length > 0)){
+ alert(1);
+ return false;
+ }
+ steps.map((step, i) => {
+ if(i === 0){
+ if(!(step.requirements &&
+ step.requirements.length > 0 &&
+ step.requirements.filter(requirement => typeof(requirement) === 'number').length === step.requirements.length)){
+ alert(3);
+ return false;
+ }
+ var hardwareIds = data.map(hardware => hardware.id);
+ if(!(step.hardware &&
+ step.hardware.length > 0 &&
+ step.hardware.filter(hardware => typeof(hardware) === 'string' && hardwareIds.includes(hardware)).length === step.hardware.length)){
+ alert(4);
+ return false;
+ }
+ }
+ if(!(step.headline && typeof(step.headline)==='string')){
+ alert(5);
+ return false;
+ }
+ if(!(step.text && typeof(step.text)==='string')){
+ alert(6);
+ return false;
+ }
+ });
+ return true;
+ }
+
render() {
return (
@@ -40,6 +125,20 @@ class Builder extends Component {
Tutorial-Builder
+
+ {this.uploadJsonFile(e.target.files[0])}}
+ id="open-json"
+ type="file"
+ />
+
+
+
+
@@ -49,7 +148,11 @@ class Builder extends Component {
)}
-
+
+
+
+
+
@@ -63,10 +166,14 @@ class Builder extends Component {
Builder.propTypes = {
checkError: PropTypes.func.isRequired,
+ readJSON: PropTypes.func.isRequired,
+ progress: PropTypes.func.isRequired,
+ resetTutorial: PropTypes.func.isRequired,
title: PropTypes.string.isRequired,
steps: PropTypes.array.isRequired,
change: PropTypes.number.isRequired,
- error: PropTypes.object.isRequired
+ error: PropTypes.object.isRequired,
+ isProgress: PropTypes.bool.isRequired
};
const mapStateToProps = state => ({
@@ -74,7 +181,8 @@ const mapStateToProps = state => ({
id: state.builder.id,
steps: state.builder.steps,
change: state.builder.change,
- error: state.builder.error
+ error: state.builder.error,
+ isProgress: state.builder.progress
});
-export default connect(mapStateToProps, { checkError })(Builder);
+export default connect(mapStateToProps, { checkError, readJSON, progress, resetTutorial })(withStyles(styles, {withTheme: true})(Builder));
diff --git a/src/components/Tutorial/Builder/Step.js b/src/components/Tutorial/Builder/Step.js
index 7124131..740a686 100644
--- a/src/components/Tutorial/Builder/Step.js
+++ b/src/components/Tutorial/Builder/Step.js
@@ -89,11 +89,11 @@ class Step extends Component {
{index === 0 ?
-
-
+
+
: null}
-
+
diff --git a/src/components/Tutorial/Builder/StepType.js b/src/components/Tutorial/Builder/StepType.js
index f482990..910b2df 100644
--- a/src/components/Tutorial/Builder/StepType.js
+++ b/src/components/Tutorial/Builder/StepType.js
@@ -11,7 +11,7 @@ class StepType extends Component {
render() {
return (
- {this.props.changeContent(this.props.index, 'type', e.target.value)}}>
+ {this.props.changeContent(this.props.index, 'type', e.target.value)}}>
}
diff --git a/src/reducers/tutorialBuilderReducer.js b/src/reducers/tutorialBuilderReducer.js
index 3103403..6296da2 100644
--- a/src/reducers/tutorialBuilderReducer.js
+++ b/src/reducers/tutorialBuilderReducer.js
@@ -1,7 +1,8 @@
-import { BUILDER_CHANGE, BUILDER_ERROR, BUILDER_TITLE, BUILDER_ID, BUILDER_ADD_STEP, BUILDER_DELETE_STEP, BUILDER_CHANGE_STEP,BUILDER_CHANGE_ORDER, BUILDER_DELETE_PROPERTY } from '../actions/types';
+import { PROGRESS, BUILDER_CHANGE, BUILDER_ERROR, BUILDER_TITLE, BUILDER_ID, BUILDER_ADD_STEP, BUILDER_DELETE_STEP, BUILDER_CHANGE_STEP,BUILDER_CHANGE_ORDER, BUILDER_DELETE_PROPERTY } from '../actions/types';
const initialState = {
change: 0,
+ progress: false,
title: '',
id: '',
steps: [
@@ -50,6 +51,11 @@ export default function(state = initialState, action){
...state,
error: action.payload
}
+ case PROGRESS:
+ return {
+ ...state,
+ progress: action.payload
+ }
default:
return state;
}