From 111b9249889e57b8ba21327211fb7e8ae1638b7e Mon Sep 17 00:00:00 2001
From: Delucse <46593742+Delucse@users.noreply.github.com>
Date: Sat, 19 Sep 2020 09:38:38 +0200
Subject: [PATCH] error validation
---
src/actions/tutorialBuilderActions.js | 100 +++++++++++++++++-
src/actions/types.js | 1 +
.../Tutorial/Builder/BlocklyExample.js | 36 +++++--
src/components/Tutorial/Builder/Builder.js | 25 ++---
src/components/Tutorial/Builder/Hardware.js | 25 ++++-
src/components/Tutorial/Builder/Id.js | 56 +++++++---
.../Tutorial/Builder/Requirements.js | 3 +-
src/components/Tutorial/Builder/Step.js | 17 ++-
src/components/Tutorial/Builder/Textfield.js | 64 +++++++----
src/reducers/tutorialBuilderReducer.js | 14 ++-
10 files changed, 268 insertions(+), 73 deletions(-)
diff --git a/src/actions/tutorialBuilderActions.js b/src/actions/tutorialBuilderActions.js
index a26f5b6..2ccca5b 100644
--- a/src/actions/tutorialBuilderActions.js
+++ b/src/actions/tutorialBuilderActions.js
@@ -1,4 +1,4 @@
-import { BUILDER_CHANGE, BUILDER_TITLE, BUILDER_ID, BUILDER_ADD_STEP, BUILDER_DELETE_STEP, BUILDER_CHANGE_STEP, BUILDER_CHANGE_ORDER, BUILDER_DELETE_PROPERTY } from './types';
+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';
export const changeTutorialBuilder = () => (dispatch) => {
dispatch({
@@ -35,9 +35,19 @@ export const addStep = (index) => (dispatch, getState) => {
type: BUILDER_ADD_STEP,
payload: steps
});
+ dispatch(addErrorStep(index));
dispatch(changeTutorialBuilder());
};
+export const addErrorStep = (index) => (dispatch, getState) => {
+ var error = getState().builder.error;
+ error.steps.splice(index, 0, {});
+ dispatch({
+ type: BUILDER_ERROR,
+ payload: error
+ });
+};
+
export const removeStep = (index) => (dispatch, getState) => {
var steps = getState().builder.steps;
steps.splice(index, 1);
@@ -45,9 +55,19 @@ export const removeStep = (index) => (dispatch, getState) => {
type: BUILDER_DELETE_STEP,
payload: steps
});
+ dispatch(removeErrorStep(index));
dispatch(changeTutorialBuilder());
};
+export const removeErrorStep = (index) => (dispatch, getState) => {
+ var error = getState().builder.error;
+ error.steps.splice(index, 1);
+ dispatch({
+ type: BUILDER_ERROR,
+ payload: error
+ });
+};
+
export const changeContent = (index, property, content) => (dispatch, getState) => {
var steps = getState().builder.steps;
var step = steps[index];
@@ -79,5 +99,83 @@ export const changeStepIndex = (fromIndex, toIndex) => (dispatch, getState) => {
type: BUILDER_CHANGE_ORDER,
payload: steps
});
+ dispatch(changeErrorStepIndex(fromIndex, toIndex));
dispatch(changeTutorialBuilder());
};
+
+export const changeErrorStepIndex = (fromIndex, toIndex) => (dispatch, getState) => {
+ var error = getState().builder.error;
+ var errorStep = error.steps[fromIndex];
+ error.steps.splice(fromIndex, 1);
+ error.steps.splice(toIndex, 0, errorStep);
+ dispatch({
+ type: BUILDER_ERROR,
+ payload: error
+ });
+};
+
+export const setError = (index, property) => (dispatch, getState) => {
+ var error = getState().builder.error;
+ console.log(index);
+ if(index !== undefined){
+ error.steps[index][property] = true;
+ }
+ else {
+ error[property] = true;
+ }
+ dispatch({
+ type: BUILDER_ERROR,
+ payload: error
+ });
+ dispatch(changeTutorialBuilder());
+};
+
+export const deleteError = (index, property) => (dispatch, getState) => {
+ var error = getState().builder.error;
+ if(index !== undefined){
+ delete error.steps[index][property];
+ }
+ else {
+ delete error[property];
+ }
+ dispatch({
+ type: BUILDER_ERROR,
+ payload: error
+ });
+ dispatch(changeTutorialBuilder());
+};
+
+export const setSubmitError = () => (dispatch, getState) => {
+ var builder = getState().builder;
+ if(builder.id === ''){
+ dispatch(setError(undefined, 'id'));
+ }
+ if(builder.title === ''){
+ dispatch(setError(undefined, 'title'));
+ }
+ for(var i = 0; i < builder.steps.length; i++){
+ if(i === 0 && builder.steps[i].hardware.length < 1){
+ dispatch(setError(i, 'hardware'));
+ }
+ if(builder.steps[i].headline === ''){
+ dispatch(setError(i, 'headline'));
+ }
+ if(builder.steps[i].text === ''){
+ dispatch(setError(i, 'text'));
+ }
+ }
+};
+
+export const checkError = () => (dispatch, getState) => {
+ dispatch(setSubmitError());
+ var error = getState().builder.error;
+ if(error.id || error.title){
+ return false;
+ }
+ for(var i = 0; i < error.steps.length; i++){
+ if(Object.keys(error.steps[i]).length > 0){
+ return false
+ }
+ }
+ return true;
+}
diff --git a/src/actions/types.js b/src/actions/types.js
index a8fde8a..c5fb2a5 100644
--- a/src/actions/types.js
+++ b/src/actions/types.js
@@ -24,3 +24,4 @@ export const BUILDER_DELETE_STEP = 'BUILDER_DELETE_STEP';
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';
diff --git a/src/components/Tutorial/Builder/BlocklyExample.js b/src/components/Tutorial/Builder/BlocklyExample.js
index 9029bec..c8e8994 100644
--- a/src/components/Tutorial/Builder/BlocklyExample.js
+++ b/src/components/Tutorial/Builder/BlocklyExample.js
@@ -1,7 +1,7 @@
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
-import { changeContent, deleteProperty } from '../../../actions/tutorialBuilderActions';
+import { changeContent, deleteProperty, setError, deleteError } from '../../../actions/tutorialBuilderActions';
import moment from 'moment';
import localization from 'moment/locale/de';
@@ -11,7 +11,7 @@ import BlocklyWindow from '../../Blockly/BlocklyWindow';
import { withStyles } from '@material-ui/core/styles';
import Switch from '@material-ui/core/Switch';
import FormControlLabel from '@material-ui/core/FormControlLabel';
-import FormLabel from '@material-ui/core/FormLabel';
+import FormHelperText from '@material-ui/core/FormHelperText';
import Button from '@material-ui/core/Button';
import Grid from '@material-ui/core/Grid';
@@ -42,9 +42,29 @@ class BlocklyExample extends Component {
};
}
- componentDidUpdate(props){
+ componentDidMount(){
+ if(this.props.task){
+ this.props.setError(this.props.index, 'xml');
+ }
+ }
+
+ 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.setState({checked: this.props.task ? this.props.task : this.props.value ? true : false},
+ () => this.isError()
+ );
+ }
+ if(state.checked !== this.state.checked){
+ this.isError();
+ }
+ }
+
+ isError = () => {
+ if(this.state.checked && !this.props.value){
+ this.props.setError(this.props.index, 'xml');
+ }
+ else {
+ this.props.deleteError(this.props.index, 'xml');
}
}
@@ -75,8 +95,8 @@ class BlocklyExample extends Component {
}
/>
{this.state.checked ? !this.props.value ?
- Es ist noch keine Eingabe gemacht worden.
- : Die letzte Einreichung erfolgte um {this.state.input} Uhr.
+ 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 ?
@@ -104,6 +124,8 @@ class BlocklyExample extends Component {
BlocklyExample.propTypes = {
changeContent: PropTypes.func.isRequired,
deleteProperty: PropTypes.func.isRequired,
+ setError: PropTypes.func.isRequired,
+ deleteError: PropTypes.func.isRequired,
xml: PropTypes.string.isRequired
};
@@ -112,4 +134,4 @@ const mapStateToProps = state => ({
});
-export default connect(mapStateToProps, { changeContent, deleteProperty })(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 948c3e1..aaea9c3 100644
--- a/src/components/Tutorial/Builder/Builder.js
+++ b/src/components/Tutorial/Builder/Builder.js
@@ -1,21 +1,14 @@
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
+import { checkError } from '../../../actions/tutorialBuilderActions';
import Breadcrumbs from '../../Breadcrumbs';
import Id from './Id';
import Title from './Textfield';
import Step from './Step';
-import Typography from '@material-ui/core/Typography';
import Button from '@material-ui/core/Button';
-import TextField from '@material-ui/core/TextField';
-import OutlinedInput from '@material-ui/core/OutlinedInput';
-import InputLabel from '@material-ui/core/InputLabel';
-import FormControl from '@material-ui/core/FormControl';
-
-import { faPlus, faMinus } from "@fortawesome/free-solid-svg-icons";
-import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
class Builder extends Component {
@@ -27,8 +20,8 @@ class Builder extends Component {
Tutorial-Builder
-
-
+
+
{this.props.steps.map((step, i) =>
@@ -36,7 +29,7 @@ class Builder extends Component {
)}
-
+
@@ -49,15 +42,19 @@ class Builder extends Component {
}
Builder.propTypes = {
+ checkError: PropTypes.func.isRequired,
title: PropTypes.string.isRequired,
steps: PropTypes.array.isRequired,
- change: PropTypes.number.isRequired
+ change: PropTypes.number.isRequired,
+ error: PropTypes.object.isRequired
};
const mapStateToProps = state => ({
title: state.builder.title,
+ id: state.builder.id,
steps: state.builder.steps,
- change: state.builder.change
+ change: state.builder.change,
+ error: state.builder.error
});
-export default connect(mapStateToProps, null)(Builder);
+export default connect(mapStateToProps, { checkError })(Builder);
diff --git a/src/components/Tutorial/Builder/Hardware.js b/src/components/Tutorial/Builder/Hardware.js
index 6bf50c2..f0e3cd3 100644
--- a/src/components/Tutorial/Builder/Hardware.js
+++ b/src/components/Tutorial/Builder/Hardware.js
@@ -1,7 +1,7 @@
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
-import { changeContent } from '../../../actions/tutorialBuilderActions';
+import { changeContent, setError, deleteError } from '../../../actions/tutorialBuilderActions';
import hardware from '../../../data/hardware.json';
@@ -11,6 +11,7 @@ import withWidth, { isWidthDown } from '@material-ui/core/withWidth';
import GridList from '@material-ui/core/GridList';
import GridListTile from '@material-ui/core/GridListTile';
import GridListTileBar from '@material-ui/core/GridListTileBar';
+import FormHelperText from '@material-ui/core/FormHelperText';
const styles = theme => ({
multiGridListTile: {
@@ -31,6 +32,11 @@ const styles = theme => ({
width: 'calc(100% - 4px)',
height: 'calc(100% - 4px)',
border: `2px solid ${theme.palette.primary.main}`
+ },
+ errorColor: {
+ color: theme.palette.error.dark,
+ lineHeight: 'initial',
+ marginBottom: '10px'
}
});
@@ -43,13 +49,22 @@ class Requirements extends Component {
}
else {
hardwareArray.push(hardware);
+ if(this.props.error.steps[this.props.index].hardware){
+ this.props.deleteError(this.props.index, 'hardware');
+ }
}
this.props.changeContent(this.props.index, 'hardware', hardwareArray);
+ if(hardwareArray.length === 0){
+ this.props.setError(this.props.index, 'hardware');
+ }
}
render() {
var cols = isWidthDown('md', this.props.width) ? isWidthDown('sm', this.props.width) ? isWidthDown('xs', this.props.width) ? 2 : 3 : 4 : 6;
return (
+
+ Beachte, dass die Reihenfolge des Auswählens maßgebend ist.
+ {this.props.error.steps[this.props.index].hardware ? Wähle mindestens eine Hardware aus. : 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}}>
@@ -67,16 +82,20 @@ class Requirements extends Component {
))}
+
);
};
}
Requirements.propTypes = {
- changeContent: PropTypes.func.isRequired
+ changeContent: PropTypes.func.isRequired,
+ setError: PropTypes.func.isRequired,
+ deleteError: PropTypes.func.isRequired,
+ change: PropTypes.number.isRequired
};
const mapStateToProps = state => ({
change: state.builder.change
});
-export default connect(mapStateToProps, { changeContent })(withStyles(styles, { withTheme: true })(withWidth()(Requirements)));
+export default connect(mapStateToProps, { changeContent, setError, deleteError })(withStyles(styles, { withTheme: true })(withWidth()(Requirements)));
diff --git a/src/components/Tutorial/Builder/Id.js b/src/components/Tutorial/Builder/Id.js
index 2f8d5cd..e329d77 100644
--- a/src/components/Tutorial/Builder/Id.js
+++ b/src/components/Tutorial/Builder/Id.js
@@ -1,5 +1,9 @@
import React, { Component } from 'react';
+import PropTypes from 'prop-types';
+import { connect } from 'react-redux';
+import { tutorialId, setError, deleteError } from '../../../actions/tutorialBuilderActions';
+import { withStyles } from '@material-ui/core/styles';
import Button from '@material-ui/core/Button';
import OutlinedInput from '@material-ui/core/OutlinedInput';
import InputLabel from '@material-ui/core/InputLabel';
@@ -9,29 +13,40 @@ import FormHelperText from '@material-ui/core/FormHelperText';
import { faPlus, faMinus } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
-class Id extends Component {
-
- state = {
- id: 0,
- error: false
+const styles = theme => ({
+ errorColor: {
+ color: theme.palette.error.dark
}
+});
+
+class Id extends Component {
handleChange = (e) => {
var value = parseInt(e.target.value);
- if(Number.isInteger(value)){
- this.setState({id: value, error: false});
+ if(Number.isInteger(value) && value > 0){
+ this.props.tutorialId(value);
+ if(this.props.error.id){
+ this.props.deleteError(undefined, 'id');
+ }
}
else {
- this.setState({id: e.target.value, error: true});
+ this.props.tutorialId(value);
+ this.props.setError(undefined,'id');
}
};
handleCounter = (step) => {
- if(!this.state.id){
- this.setState({id: 0+step});
+ if(this.props.value+step < 1){
+ this.props.setError(undefined,'id');
+ }
+ else if(this.props.error.id){
+ this.props.deleteError(undefined, 'id');
+ }
+ if(!this.props.value){
+ this.props.tutorialId(0+step);
}
else {
- this.setState({id: this.state.id+step});
+ this.props.tutorialId(this.props.value+step);
}
}
@@ -41,8 +56,8 @@ class Id extends Component {
ID