error validation
This commit is contained in:
parent
b20bde4e83
commit
111b924988
@ -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) => {
|
export const changeTutorialBuilder = () => (dispatch) => {
|
||||||
dispatch({
|
dispatch({
|
||||||
@ -35,9 +35,19 @@ export const addStep = (index) => (dispatch, getState) => {
|
|||||||
type: BUILDER_ADD_STEP,
|
type: BUILDER_ADD_STEP,
|
||||||
payload: steps
|
payload: steps
|
||||||
});
|
});
|
||||||
|
dispatch(addErrorStep(index));
|
||||||
dispatch(changeTutorialBuilder());
|
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) => {
|
export const removeStep = (index) => (dispatch, getState) => {
|
||||||
var steps = getState().builder.steps;
|
var steps = getState().builder.steps;
|
||||||
steps.splice(index, 1);
|
steps.splice(index, 1);
|
||||||
@ -45,9 +55,19 @@ export const removeStep = (index) => (dispatch, getState) => {
|
|||||||
type: BUILDER_DELETE_STEP,
|
type: BUILDER_DELETE_STEP,
|
||||||
payload: steps
|
payload: steps
|
||||||
});
|
});
|
||||||
|
dispatch(removeErrorStep(index));
|
||||||
dispatch(changeTutorialBuilder());
|
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) => {
|
export const changeContent = (index, property, content) => (dispatch, getState) => {
|
||||||
var steps = getState().builder.steps;
|
var steps = getState().builder.steps;
|
||||||
var step = steps[index];
|
var step = steps[index];
|
||||||
@ -79,5 +99,83 @@ export const changeStepIndex = (fromIndex, toIndex) => (dispatch, getState) => {
|
|||||||
type: BUILDER_CHANGE_ORDER,
|
type: BUILDER_CHANGE_ORDER,
|
||||||
payload: steps
|
payload: steps
|
||||||
});
|
});
|
||||||
|
dispatch(changeErrorStepIndex(fromIndex, toIndex));
|
||||||
dispatch(changeTutorialBuilder());
|
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;
|
||||||
|
}
|
||||||
|
@ -24,3 +24,4 @@ export const BUILDER_DELETE_STEP = 'BUILDER_DELETE_STEP';
|
|||||||
export const BUILDER_CHANGE_STEP = 'BUILDER_CHANGE_STEP';
|
export const BUILDER_CHANGE_STEP = 'BUILDER_CHANGE_STEP';
|
||||||
export const BUILDER_CHANGE_ORDER = 'BUILDER_CHANGE_ORDER';
|
export const BUILDER_CHANGE_ORDER = 'BUILDER_CHANGE_ORDER';
|
||||||
export const BUILDER_DELETE_PROPERTY = 'BUILDER_DELETE_PROPERTY';
|
export const BUILDER_DELETE_PROPERTY = 'BUILDER_DELETE_PROPERTY';
|
||||||
|
export const BUILDER_ERROR = 'BUILDER_ERROR';
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { changeContent, deleteProperty } from '../../../actions/tutorialBuilderActions';
|
import { changeContent, deleteProperty, setError, deleteError } from '../../../actions/tutorialBuilderActions';
|
||||||
|
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
import localization from 'moment/locale/de';
|
import localization from 'moment/locale/de';
|
||||||
@ -11,7 +11,7 @@ import BlocklyWindow from '../../Blockly/BlocklyWindow';
|
|||||||
import { withStyles } from '@material-ui/core/styles';
|
import { withStyles } from '@material-ui/core/styles';
|
||||||
import Switch from '@material-ui/core/Switch';
|
import Switch from '@material-ui/core/Switch';
|
||||||
import FormControlLabel from '@material-ui/core/FormControlLabel';
|
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 Button from '@material-ui/core/Button';
|
||||||
import Grid from '@material-ui/core/Grid';
|
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){
|
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 ?
|
{this.state.checked ? !this.props.value ?
|
||||||
<FormLabel className={this.props.classes.errorColor}>Es ist noch keine Eingabe gemacht worden.</FormLabel>
|
<FormHelperText style={{lineHeight: 'initial', marginBottom: '10px'}} className={this.props.classes.errorColor}>Reiche deine Blöcke ein, indem du auf den rot gefärbten Button klickst.</FormHelperText>
|
||||||
: <FormLabel>Die letzte Einreichung erfolgte um {this.state.input} Uhr.</FormLabel>
|
: <FormHelperText style={{lineHeight: 'initial', marginBottom: '10px'}}>Die letzte Einreichung erfolgte um {this.state.input} Uhr.</FormHelperText>
|
||||||
: null}
|
: null}
|
||||||
{this.state.checked ?
|
{this.state.checked ?
|
||||||
<div>
|
<div>
|
||||||
@ -104,6 +124,8 @@ class BlocklyExample extends Component {
|
|||||||
BlocklyExample.propTypes = {
|
BlocklyExample.propTypes = {
|
||||||
changeContent: PropTypes.func.isRequired,
|
changeContent: PropTypes.func.isRequired,
|
||||||
deleteProperty: PropTypes.func.isRequired,
|
deleteProperty: PropTypes.func.isRequired,
|
||||||
|
setError: PropTypes.func.isRequired,
|
||||||
|
deleteError: PropTypes.func.isRequired,
|
||||||
xml: PropTypes.string.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));
|
||||||
|
@ -1,21 +1,14 @@
|
|||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
|
import { checkError } from '../../../actions/tutorialBuilderActions';
|
||||||
|
|
||||||
import Breadcrumbs from '../../Breadcrumbs';
|
import Breadcrumbs from '../../Breadcrumbs';
|
||||||
import Id from './Id';
|
import Id from './Id';
|
||||||
import Title from './Textfield';
|
import Title from './Textfield';
|
||||||
import Step from './Step';
|
import Step from './Step';
|
||||||
|
|
||||||
import Typography from '@material-ui/core/Typography';
|
|
||||||
import Button from '@material-ui/core/Button';
|
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 {
|
class Builder extends Component {
|
||||||
|
|
||||||
@ -27,8 +20,8 @@ class Builder extends Component {
|
|||||||
|
|
||||||
<h1>Tutorial-Builder</h1>
|
<h1>Tutorial-Builder</h1>
|
||||||
|
|
||||||
<Id />
|
<Id error={this.props.error} value={this.props.id}/>
|
||||||
<Title value={this.props.title} property={'title'} label={'Titel'}/>
|
<Title value={this.props.title} property={'title'} label={'Titel'} error={this.props.error}/>
|
||||||
|
|
||||||
{this.props.steps.map((step, i) =>
|
{this.props.steps.map((step, i) =>
|
||||||
<Step step={step} index={i} />
|
<Step step={step} index={i} />
|
||||||
@ -36,7 +29,7 @@ class Builder extends Component {
|
|||||||
)}
|
)}
|
||||||
|
|
||||||
|
|
||||||
<Button variant='contained' color='primary' onClick={() => {alert('hi')}}>Submit</Button>
|
<Button variant='contained' color='primary' onClick={() => {var error = this.props.checkError(); alert(error);}}>Tutorial-Vorlage erstellen</Button>
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
@ -49,15 +42,19 @@ class Builder extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Builder.propTypes = {
|
Builder.propTypes = {
|
||||||
|
checkError: PropTypes.func.isRequired,
|
||||||
title: PropTypes.string.isRequired,
|
title: PropTypes.string.isRequired,
|
||||||
steps: PropTypes.array.isRequired,
|
steps: PropTypes.array.isRequired,
|
||||||
change: PropTypes.number.isRequired
|
change: PropTypes.number.isRequired,
|
||||||
|
error: PropTypes.object.isRequired
|
||||||
};
|
};
|
||||||
|
|
||||||
const mapStateToProps = state => ({
|
const mapStateToProps = state => ({
|
||||||
title: state.builder.title,
|
title: state.builder.title,
|
||||||
|
id: state.builder.id,
|
||||||
steps: state.builder.steps,
|
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);
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { changeContent } from '../../../actions/tutorialBuilderActions';
|
import { changeContent, setError, deleteError } from '../../../actions/tutorialBuilderActions';
|
||||||
|
|
||||||
import hardware from '../../../data/hardware.json';
|
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 GridList from '@material-ui/core/GridList';
|
||||||
import GridListTile from '@material-ui/core/GridListTile';
|
import GridListTile from '@material-ui/core/GridListTile';
|
||||||
import GridListTileBar from '@material-ui/core/GridListTileBar';
|
import GridListTileBar from '@material-ui/core/GridListTileBar';
|
||||||
|
import FormHelperText from '@material-ui/core/FormHelperText';
|
||||||
|
|
||||||
const styles = theme => ({
|
const styles = theme => ({
|
||||||
multiGridListTile: {
|
multiGridListTile: {
|
||||||
@ -31,6 +32,11 @@ const styles = theme => ({
|
|||||||
width: 'calc(100% - 4px)',
|
width: 'calc(100% - 4px)',
|
||||||
height: 'calc(100% - 4px)',
|
height: 'calc(100% - 4px)',
|
||||||
border: `2px solid ${theme.palette.primary.main}`
|
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 {
|
else {
|
||||||
hardwareArray.push(hardware);
|
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);
|
this.props.changeContent(this.props.index, 'hardware', hardwareArray);
|
||||||
|
if(hardwareArray.length === 0){
|
||||||
|
this.props.setError(this.props.index, 'hardware');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
var cols = isWidthDown('md', this.props.width) ? isWidthDown('sm', this.props.width) ? isWidthDown('xs', this.props.width) ? 2 : 3 : 4 : 6;
|
var cols = isWidthDown('md', this.props.width) ? isWidthDown('sm', this.props.width) ? isWidthDown('xs', this.props.width) ? 2 : 3 : 4 : 6;
|
||||||
return (
|
return (
|
||||||
|
<div>
|
||||||
|
<FormHelperText style={this.props.error.steps[this.props.index].hardware ? {lineHeight: 'initial', marginTop: '5px'} : {marginTop: '5px', lineHeight: 'initial', marginBottom: '10px'}}>Beachte, dass die Reihenfolge des Auswählens maßgebend ist.</FormHelperText>
|
||||||
|
{this.props.error.steps[this.props.index].hardware ? <FormHelperText className={this.props.classes.errorColor}>Wähle mindestens eine Hardware aus.</FormHelperText> : null}
|
||||||
<GridList cellHeight={100} cols={cols} spacing={10}>
|
<GridList cellHeight={100} cols={cols} spacing={10}>
|
||||||
{hardware.map((picture,i) => (
|
{hardware.map((picture,i) => (
|
||||||
<GridListTile key={i} onClick={() => this.onChange(picture.id)} classes={{tile: this.props.value.filter(value => value === picture.id).length > 0 ? this.props.classes.active : this.props.classes.border}}>
|
<GridListTile key={i} onClick={() => 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 {
|
|||||||
</GridListTile>
|
</GridListTile>
|
||||||
))}
|
))}
|
||||||
</GridList>
|
</GridList>
|
||||||
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
Requirements.propTypes = {
|
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 => ({
|
const mapStateToProps = state => ({
|
||||||
change: state.builder.change
|
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)));
|
||||||
|
@ -1,5 +1,9 @@
|
|||||||
import React, { Component } from 'react';
|
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 Button from '@material-ui/core/Button';
|
||||||
import OutlinedInput from '@material-ui/core/OutlinedInput';
|
import OutlinedInput from '@material-ui/core/OutlinedInput';
|
||||||
import InputLabel from '@material-ui/core/InputLabel';
|
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 { faPlus, faMinus } from "@fortawesome/free-solid-svg-icons";
|
||||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||||
|
|
||||||
class Id extends Component {
|
const styles = theme => ({
|
||||||
|
errorColor: {
|
||||||
state = {
|
color: theme.palette.error.dark
|
||||||
id: 0,
|
|
||||||
error: false
|
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
class Id extends Component {
|
||||||
|
|
||||||
handleChange = (e) => {
|
handleChange = (e) => {
|
||||||
var value = parseInt(e.target.value);
|
var value = parseInt(e.target.value);
|
||||||
if(Number.isInteger(value)){
|
if(Number.isInteger(value) && value > 0){
|
||||||
this.setState({id: value, error: false});
|
this.props.tutorialId(value);
|
||||||
|
if(this.props.error.id){
|
||||||
|
this.props.deleteError(undefined, 'id');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
this.setState({id: e.target.value, error: true});
|
this.props.tutorialId(value);
|
||||||
|
this.props.setError(undefined,'id');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
handleCounter = (step) => {
|
handleCounter = (step) => {
|
||||||
if(!this.state.id){
|
if(this.props.value+step < 1){
|
||||||
this.setState({id: 0+step});
|
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 {
|
else {
|
||||||
this.setState({id: this.state.id+step});
|
this.props.tutorialId(this.props.value+step);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -41,8 +56,8 @@ class Id extends Component {
|
|||||||
<InputLabel htmlFor="id">ID</InputLabel>
|
<InputLabel htmlFor="id">ID</InputLabel>
|
||||||
<OutlinedInput
|
<OutlinedInput
|
||||||
style={{borderRadius: '25px', padding: '0 0 0 10px', width: '200px'}}
|
style={{borderRadius: '25px', padding: '0 0 0 10px', width: '200px'}}
|
||||||
error={this.state.error}
|
error={this.props.error.id}
|
||||||
value={this.state.id}
|
value={this.props.value}
|
||||||
name='id'
|
name='id'
|
||||||
label='ID'
|
label='ID'
|
||||||
id='id'
|
id='id'
|
||||||
@ -53,6 +68,7 @@ class Id extends Component {
|
|||||||
endAdornment={
|
endAdornment={
|
||||||
<div style={{display: 'flex'}}>
|
<div style={{display: 'flex'}}>
|
||||||
<Button
|
<Button
|
||||||
|
disabled={this.props.value === 1 || !this.props.value}
|
||||||
onClick={() => this.handleCounter(-1)}
|
onClick={() => this.handleCounter(-1)}
|
||||||
variant='contained'
|
variant='contained'
|
||||||
color='primary'
|
color='primary'
|
||||||
@ -71,10 +87,20 @@ class Id extends Component {
|
|||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
{this.state.error ? <FormHelperText style={{color: 'red'}}>Es muss eine positive ganzzahlige Zahl sein.</FormHelperText> : null}
|
{this.props.error.id ? <FormHelperText className={this.props.classes.errorColor}>Gib eine positive ganzzahlige Zahl ein.</FormHelperText> : null}
|
||||||
</FormControl>
|
</FormControl>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Id;
|
Id.propTypes = {
|
||||||
|
tutorialId: PropTypes.func.isRequired,
|
||||||
|
setError: PropTypes.func.isRequired,
|
||||||
|
deleteError: PropTypes.func.isRequired
|
||||||
|
};
|
||||||
|
|
||||||
|
const mapStateToProps = state => ({
|
||||||
|
change: state.builder.change
|
||||||
|
});
|
||||||
|
|
||||||
|
export default connect(mapStateToProps, { tutorialId, setError, deleteError })(withStyles(styles, { withTheme: true })(Id));
|
||||||
|
@ -9,6 +9,7 @@ import FormGroup from '@material-ui/core/FormGroup';
|
|||||||
import Checkbox from '@material-ui/core/Checkbox';
|
import Checkbox from '@material-ui/core/Checkbox';
|
||||||
import FormControlLabel from '@material-ui/core/FormControlLabel';
|
import FormControlLabel from '@material-ui/core/FormControlLabel';
|
||||||
import FormLabel from '@material-ui/core/FormLabel';
|
import FormLabel from '@material-ui/core/FormLabel';
|
||||||
|
import FormHelperText from '@material-ui/core/FormHelperText';
|
||||||
import FormControl from '@material-ui/core/FormControl';
|
import FormControl from '@material-ui/core/FormControl';
|
||||||
|
|
||||||
class Requirements extends Component {
|
class Requirements extends Component {
|
||||||
@ -29,7 +30,7 @@ class Requirements extends Component {
|
|||||||
return (
|
return (
|
||||||
<FormControl style={{marginBottom: '10px'}}>
|
<FormControl style={{marginBottom: '10px'}}>
|
||||||
<FormLabel style={{color: 'black'}}>Voraussetzungen</FormLabel>
|
<FormLabel style={{color: 'black'}}>Voraussetzungen</FormLabel>
|
||||||
<FormLabel style={{marginTop: '5px'}}>Beachte, dass die Reihenfolge des Anhakens maßgebend ist.</FormLabel>
|
<FormHelperText style={{marginTop: '5px'}}>Beachte, dass die Reihenfolge des Anhakens maßgebend ist.</FormHelperText>
|
||||||
<FormGroup>
|
<FormGroup>
|
||||||
{tutorials.map((tutorial, i) =>
|
{tutorials.map((tutorial, i) =>
|
||||||
<FormControlLabel
|
<FormControlLabel
|
||||||
|
@ -13,9 +13,6 @@ import { withStyles } from '@material-ui/core/styles';
|
|||||||
import Typography from '@material-ui/core/Typography';
|
import Typography from '@material-ui/core/Typography';
|
||||||
import IconButton from '@material-ui/core/IconButton';
|
import IconButton from '@material-ui/core/IconButton';
|
||||||
import Tooltip from '@material-ui/core/Tooltip';
|
import Tooltip from '@material-ui/core/Tooltip';
|
||||||
import OutlinedInput from '@material-ui/core/OutlinedInput';
|
|
||||||
import InputLabel from '@material-ui/core/InputLabel';
|
|
||||||
import FormControl from '@material-ui/core/FormControl';
|
|
||||||
|
|
||||||
import { faPlus, faAngleDoubleUp, faAngleDoubleDown, faTrash } from "@fortawesome/free-solid-svg-icons";
|
import { faPlus, faAngleDoubleUp, faAngleDoubleDown, faTrash } from "@fortawesome/free-solid-svg-icons";
|
||||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||||
@ -88,15 +85,15 @@ class Step extends Component {
|
|||||||
</div>
|
</div>
|
||||||
<div style={{width: '100%', marginLeft: '54px'}}>
|
<div style={{width: '100%', marginLeft: '54px'}}>
|
||||||
<StepType value={this.props.step.type} index={index} />
|
<StepType value={this.props.step.type} index={index} />
|
||||||
<Textfield value={this.props.step.headline} property={'headline'} label={'Überschrift'} index={index}/>
|
<Textfield value={this.props.step.headline} property={'headline'} label={'Überschrift'} index={index} error={this.props.error} errorText={`Gib eine Überschrift für die ${this.props.step.type === 'task' ? 'Aufgabe' : 'Anleitung'} ein.`} />
|
||||||
<Textfield value={this.props.step.text} property={'text'} label={this.props.step.type === 'task' ? 'Aufgabenstellung' : 'Instruktionen'} index={index} multiline/>
|
<Textfield value={this.props.step.text} property={'text'} label={this.props.step.type === 'task' ? 'Aufgabenstellung' : 'Instruktionen'} index={index} multiline error={this.props.error} errorText={`Gib Instruktionen für die ${this.props.step.type === 'task' ? 'Aufgabe' : 'Anleitung'} ein.`}/>
|
||||||
{index === 0 ?
|
{index === 0 ?
|
||||||
<div>
|
<div>
|
||||||
<Requirements value={this.props.step.requirements} index={index}/>
|
<Requirements value={this.props.step.requirements} index={index}/>
|
||||||
<Hardware value={this.props.step.hardware} index={index} />
|
<Hardware value={this.props.step.hardware} index={index} error={this.props.error}/>
|
||||||
</div>
|
</div>
|
||||||
: null}
|
: null}
|
||||||
<BlocklyExample value={this.props.step.xml} index={index} task={this.props.step.type === 'task'}/>
|
<BlocklyExample value={this.props.step.xml} index={index} task={this.props.step.type === 'task'} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -109,12 +106,14 @@ Step.propTypes = {
|
|||||||
removeStep: PropTypes.func.isRequired,
|
removeStep: PropTypes.func.isRequired,
|
||||||
changeStepIndex: PropTypes.func.isRequired,
|
changeStepIndex: PropTypes.func.isRequired,
|
||||||
steps: PropTypes.array.isRequired,
|
steps: PropTypes.array.isRequired,
|
||||||
change: PropTypes.number.isRequired
|
change: PropTypes.number.isRequired,
|
||||||
|
error: PropTypes.object.isRequired,
|
||||||
};
|
};
|
||||||
|
|
||||||
const mapStateToProps = state => ({
|
const mapStateToProps = state => ({
|
||||||
steps: state.builder.steps,
|
steps: state.builder.steps,
|
||||||
change: state.builder.change
|
change: state.builder.change,
|
||||||
|
error: state.builder.error
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(mapStateToProps, { addStep, removeStep, changeStepIndex })(withStyles(styles, {withTheme: true})(Step));
|
export default connect(mapStateToProps, { addStep, removeStep, changeStepIndex })(withStyles(styles, {withTheme: true})(Step));
|
||||||
|
@ -1,45 +1,62 @@
|
|||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { tutorialTitle, changeContent } from '../../../actions/tutorialBuilderActions';
|
import { tutorialTitle, changeContent, setError, deleteError } from '../../../actions/tutorialBuilderActions';
|
||||||
|
|
||||||
import Button from '@material-ui/core/Button';
|
import { withStyles } from '@material-ui/core/styles';
|
||||||
import OutlinedInput from '@material-ui/core/OutlinedInput';
|
import OutlinedInput from '@material-ui/core/OutlinedInput';
|
||||||
import InputLabel from '@material-ui/core/InputLabel';
|
import InputLabel from '@material-ui/core/InputLabel';
|
||||||
import FormControl from '@material-ui/core/FormControl';
|
import FormControl from '@material-ui/core/FormControl';
|
||||||
import FormHelperText from '@material-ui/core/FormHelperText';
|
import FormHelperText from '@material-ui/core/FormHelperText';
|
||||||
|
|
||||||
|
const styles = theme => ({
|
||||||
|
multiline: {
|
||||||
|
padding: '18.5px 14px 18.5px 24px'
|
||||||
|
},
|
||||||
|
errorColor: {
|
||||||
|
color: theme.palette.error.dark
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
class Textfield extends Component {
|
class Textfield extends Component {
|
||||||
|
|
||||||
// handleChange = (e) => {
|
handleChange = (e) => {
|
||||||
// var value = e.target.value;
|
var value = e.target.value;
|
||||||
// if(value.replace(/\s/g,'') !== ''){
|
if(this.props.property === 'title'){
|
||||||
// this.setState({[e.target.name]: value, error: false});
|
this.props.tutorialTitle(value);
|
||||||
// }
|
}
|
||||||
// else {
|
else {
|
||||||
// this.setState({[e.target.name]: value, error: true});
|
this.props.changeContent(this.props.index, this.props.property, value);
|
||||||
// }
|
}
|
||||||
// };
|
if(value.replace(/\s/g,'') === ''){
|
||||||
|
this.props.setError(this.props.index, this.props.property);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
this.props.deleteError(this.props.index, this.props.property);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<FormControl variant="outlined" fullWidth style={{marginBottom: '10px'}}>
|
<FormControl variant="outlined" fullWidth style={{marginBottom: '10px'}}>
|
||||||
<InputLabel htmlFor={this.props.property}>{this.props.label}</InputLabel>
|
<InputLabel htmlFor={this.props.property}>{this.props.label}</InputLabel>
|
||||||
<OutlinedInput
|
<OutlinedInput
|
||||||
style={this.props.multiline ? {borderRadius: '25px', padding: '18.5px 14px 18.5px 24px'} : {borderRadius: '25px', padding: '0 0 0 10px'}}
|
style={{borderRadius: '25px'}}
|
||||||
/* error={this.state.error}*/
|
classes={{multiline: this.props.classes.multiline}}
|
||||||
|
error={this.props.index !== undefined ? this.props.error.steps[this.props.index][this.props.property] : this.props.error[this.props.property]}
|
||||||
value={this.props.value}
|
value={this.props.value}
|
||||||
label={this.props.label}
|
label={this.props.label}
|
||||||
id={this.props.property}
|
id={this.props.property}
|
||||||
multiline={this.props.multiline}
|
multiline={this.props.multiline}
|
||||||
rows={2}
|
rows={2}
|
||||||
rowsMax={10}
|
rowsMax={10}
|
||||||
onChange={(e) => {this.props.property === 'title' ?
|
onChange={(e) => this.handleChange(e)}
|
||||||
this.props.tutorialTitle(e.target.value)
|
|
||||||
: this.props.changeContent(this.props.index, this.props.property, e.target.value)
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
{/* {this.state.error ? <FormHelperText style={{color: 'red'}}>Gib einen Titel für das Tutorial ein.</FormHelperText> : null}*/}
|
{this.props.index !== undefined ?
|
||||||
|
this.props.error.steps[this.props.index][this.props.property] ? <FormHelperText className={this.props.classes.errorColor}>{this.props.errorText}</FormHelperText>
|
||||||
|
: null
|
||||||
|
: this.props.error[this.props.property] ? <FormHelperText className={this.props.classes.errorColor}>Gib einen Titel für das Tutorial ein.</FormHelperText>
|
||||||
|
: null}
|
||||||
</FormControl>
|
</FormControl>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@ -47,7 +64,14 @@ class Textfield extends Component {
|
|||||||
|
|
||||||
Textfield.propTypes = {
|
Textfield.propTypes = {
|
||||||
tutorialTitle: PropTypes.func.isRequired,
|
tutorialTitle: PropTypes.func.isRequired,
|
||||||
changeContent: PropTypes.func.isRequired
|
changeContent: PropTypes.func.isRequired,
|
||||||
|
error: PropTypes.object.isRequired,
|
||||||
|
change: PropTypes.number.isRequired
|
||||||
};
|
};
|
||||||
|
|
||||||
export default connect(null, { tutorialTitle, changeContent })(Textfield);
|
const mapStateToProps = state => ({
|
||||||
|
error: state.builder.error,
|
||||||
|
change: state.builder.change
|
||||||
|
});
|
||||||
|
|
||||||
|
export default connect(mapStateToProps, { tutorialTitle, changeContent, setError, deleteError })(withStyles(styles, { withTheme: true })(Textfield));
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
import { BUILDER_CHANGE, BUILDER_TITLE, BUILDER_ID, BUILDER_ADD_STEP, BUILDER_DELETE_STEP, BUILDER_CHANGE_STEP,BUILDER_CHANGE_ORDER, BUILDER_DELETE_PROPERTY } from '../actions/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 '../actions/types';
|
||||||
|
|
||||||
const initialState = {
|
const initialState = {
|
||||||
change: 0,
|
change: 0,
|
||||||
title: '',
|
title: '',
|
||||||
id: 0,
|
id: '',
|
||||||
steps: [
|
steps: [
|
||||||
{
|
{
|
||||||
id: 1,
|
id: 1,
|
||||||
@ -13,7 +13,10 @@ const initialState = {
|
|||||||
hardware: [],
|
hardware: [],
|
||||||
requirements: []
|
requirements: []
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
error: {
|
||||||
|
steps: [{}]
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function(state = initialState, action){
|
export default function(state = initialState, action){
|
||||||
@ -42,6 +45,11 @@ export default function(state = initialState, action){
|
|||||||
...state,
|
...state,
|
||||||
steps: action.payload
|
steps: action.payload
|
||||||
};
|
};
|
||||||
|
case BUILDER_ERROR:
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
error: action.payload
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user