Merge branch 'add-translations' into backend-connection

This commit is contained in:
Delucse
2020-12-14 15:23:01 +01:00
45 changed files with 1033 additions and 548 deletions
@@ -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 (
<div style={{marginBottom: '10px', padding: '18.5px 14px', borderRadius: '25px', border: '1px solid lightgrey', width: 'calc(100% - 28px)'}}>
<div style={{ marginBottom: '10px', padding: '18.5px 14px', borderRadius: '25px', border: '1px solid lightgrey', width: 'calc(100% - 28px)' }}>
{!this.props.task ?
<FormControlLabel
labelPlacement="end"
@@ -126,41 +126,42 @@ class BlocklyExample extends Component {
/>
}
/>
: <FormLabel style={{color: 'black'}}>Musterlösung</FormLabel>}
: <FormLabel style={{ color: 'black' }}>{Blockly.Msg.builder_solution}</FormLabel>}
{this.state.checked ? !this.props.value || this.props.error ?
<FormHelperText style={{lineHeight: 'initial'}} className={this.props.classes.errorColor}>{`Reiche deine Blöcke ein, indem du auf den '${this.props.task ? 'Musterlösung einreichen' : 'Beispiel einreichen'}'-Button klickst.`}</FormHelperText>
: this.state.input ? <FormHelperText style={{lineHeight: 'initial'}}>Die letzte Einreichung erfolgte um {this.state.input} Uhr.</FormHelperText> : null
: null}
<FormHelperText style={{ lineHeight: 'initial' }} className={this.props.classes.errorColor}>{`Reiche deine Blöcke ein, indem du auf den '${this.props.task ? Blockly.Msg.builder_solution_submit : Blockly.Msg.builder_example_submit}'-Button klickst.`}</FormHelperText>
: this.state.input ? <FormHelperText style={{ lineHeight: 'initial' }}>Die letzte Einreichung erfolgte um {this.state.input} Uhr.</FormHelperText> : null
: null}
{this.state.checked && !this.props.task ?
<FormHelperText style={{lineHeight: 'initial'}}>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.</FormHelperText>
: null}
<FormHelperText style={{ lineHeight: 'initial' }}>{Blockly.Msg.builder_comment}</FormHelperText>
: null}
{/* ensure that the correct xml-file is displayed in the workspace */}
{this.state.checked && this.state.xml? (() => {
return(
<div style={{marginTop: '10px'}}>
{this.state.checked && this.state.xml ? (() => {
return (
<div style={{ marginTop: '10px' }}>
<Grid container className={!this.props.value || this.props.error ? this.props.classes.errorBorder : null}>
<Grid item xs={12}>
<BlocklyWindow
blockDisabled={this.props.task}
trashcan={false}
initialXml={this.state.xml}
blocklyCSS={{height: '500px'}}
blocklyCSS={{ height: '500px' }}
/>
</Grid>
</Grid>
<Button
className={!this.props.value || this.props.error ? this.props.classes.errorButton : null }
style={{marginTop: '5px', height: '40px'}}
className={!this.props.value || this.props.error ? this.props.classes.errorButton : null}
style={{ marginTop: '5px', height: '40px' }}
variant='contained'
color='primary'
disabled={this.state.disabled}
onClick={() => this.setXml()}
>
{this.props.task ? 'Musterlösung einreichen' : 'Beispiel einreichen'}
{this.props.task ? Blockly.Msg.builder_solution_submit : Blockly.Msg.builder_example_submit}
</Button>
</div>
)})()
: null}
)
})()
: null}
</div>
);
};
@@ -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));
+36 -51
View File
@@ -8,8 +8,6 @@ import { clearMessages } from '../../../actions/messageActions';
import axios from 'axios';
import { withRouter } from 'react-router-dom';
import { saveAs } from 'file-saver';
import { detectWhitespacesAndReturnReadableResult } from '../../../helpers/whitespace';
import Breadcrumbs from '../../Breadcrumbs';
import Badge from './Badge';
@@ -44,7 +42,7 @@ const styles = (theme) => ({
marginTop: '5px',
height: '40px',
backgroundColor: theme.palette.error.dark,
'&:hover':{
'&:hover': {
backgroundColor: theme.palette.error.dark
}
}
@@ -87,11 +85,11 @@ class Builder extends Component {
// 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' });
}
}
@@ -100,7 +98,7 @@ class Builder extends Component {
componentWillUnmount() {
this.resetFull();
this.props.resetTutorial();
if(this.props.message.msg){
if (this.props.message.msg) {
this.props.clearMessages();
}
}
@@ -153,12 +151,12 @@ class Builder extends Component {
onChange = (value) => {
this.props.resetTutorialBuilder();
this.props.tutorialId('');
this.setState({tutorial: value});
this.setState({ tutorial: value });
}
onChangeId = (value) => {
this.props.tutorialId(value);
if(this.state.tutorial === 'change'){
if (this.state.tutorial === 'change') {
this.props.progress(true);
var tutorial = this.props.tutorials.filter(tutorial => tutorial._id === value)[0];
this.props.readJSON(tutorial);
@@ -201,8 +199,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);
});
@@ -211,14 +209,14 @@ class Builder extends Component {
newTutorial.append(`steps[${i}][hardware][${j}]`, hardware);
});
}
if(step.xml){ // optional
if (step.xml) { // optional
newTutorial.append(`steps[${i}][xml]`, step.xml);
}
if(step.media){ // optional
if(step.media.youtube){
if (step.media) { // optional
if (step.media.youtube) {
newTutorial.append(`steps[${i}][media][youtube]`, step.media.youtube);
}
if(step.media.picture){
if (step.media.picture) {
newTutorial.append(`steps[${i}][media][picture]`, step.media.picture);
}
}
@@ -282,30 +280,30 @@ class Builder extends Component {
<h1>Tutorial-Builder</h1>
<RadioGroup row value={this.state.tutorial} onChange={(e) => this.onChange(e.target.value)}>
<FormControlLabel style={{color: 'black'}}
<FormControlLabel style={{ color: 'black' }}
value="new"
control={<Radio color="primary" />}
label="neues Tutorial erstellen"
labelPlacement="end"
/>
{filteredTutorials.length > 0 ?
<div>
<FormControlLabel style={{color: 'black'}}
disabled={this.props.index === 0}
value="change"
control={<Radio color="primary" />}
label="bestehendes Tutorial ändern"
labelPlacement="end"
/>
<FormControlLabel style={{color: 'black'}}
disabled={this.props.index === 0}
value="delete"
control={<Radio color="primary" />}
label="bestehendes Tutorial löschen"
labelPlacement="end"
/>
</div>
: null}
<div>
<FormControlLabel style={{ color: 'black' }}
disabled={this.props.index === 0}
value="change"
control={<Radio color="primary" />}
label="bestehendes Tutorial ändern"
labelPlacement="end"
/>
<FormControlLabel style={{ color: 'black' }}
disabled={this.props.index === 0}
value="delete"
control={<Radio color="primary" />}
label="bestehendes Tutorial löschen"
labelPlacement="end"
/>
</div>
: null}
</RadioGroup>
<Divider variant='fullWidth' style={{ margin: '10px 0 15px 0' }} />
@@ -325,7 +323,7 @@ class Builder extends Component {
</label>
<Button style={{ marginRight: '10px', marginBottom: '10px' }} variant='contained' color='primary' onClick={() => this.uploadJsonString()}>String laden</Button>
</div>
: <FormControl variant="outlined" style={{width: '100%'}}>
: <FormControl variant="outlined" style={{ width: '100%' }}>
<InputLabel id="select-outlined-label">Tutorial</InputLabel>
<Select
color='primary'
@@ -357,24 +355,11 @@ class Builder extends Component {
<Step step={step} index={i} key={i} />
)}
{/*submit or reset*/}
<Divider variant='fullWidth' style={{ margin: '30px 0 10px 0' }} />
{this.state.tutorial === 'new' ?
<div>
<Button style={{ marginRight: '10px', marginTop: '10px' }} variant='contained' color='primary' onClick={() => this.submitNew()}>Tutorial erstellen</Button>
<Button style={{ marginTop: '10px' }} variant='contained' onClick={() => this.resetFull()}>Zurücksetzen</Button>
</div>
: <div>
<Button style={{ marginRight: '10px', marginTop: '10px' }} variant='contained' color='primary' onClick={() => this.submitUpdate()}>Tutorial ändern</Button>
<Button style={{ marginTop: '10px' }} variant='contained' onClick={() => this.resetTutorial()}>Zurücksetzen</Button>
<Backdrop className={this.props.classes.backdrop} open={this.props.isProgress}>
<CircularProgress color="inherit" />
</Backdrop>
</div>
}
<Backdrop className={this.props.classes.backdrop} open={this.props.isProgress}>
<CircularProgress color="inherit" />
</Backdrop>
</div>
: null}
: null}
{this.state.tutorial === 'delete' && this.props.id !== '' ?
<Button
@@ -382,7 +367,7 @@ class Builder extends Component {
variant='contained'
color='primary'
onClick={() => this.props.deleteTutorial()}>Tutorial löschen</Button>
: null}
: null}
<Dialog
open={this.state.open}
+4 -2
View File
@@ -12,6 +12,8 @@ import GridListTile from '@material-ui/core/GridListTile';
import GridListTileBar from '@material-ui/core/GridListTileBar';
import FormHelperText from '@material-ui/core/FormHelperText';
import FormLabel from '@material-ui/core/FormLabel';
import * as Blockly from 'blockly'
const styles = theme => ({
multiGridListTile: {
@@ -67,8 +69,8 @@ class Requirements extends Component {
return (
<div style={{ marginBottom: '10px', padding: '18.5px 14px', borderRadius: '25px', border: '1px solid lightgrey', width: 'calc(100% - 28px)' }}>
<FormLabel style={{ color: 'black' }}>Hardware</FormLabel>
<FormHelperText style={this.props.error ? { lineHeight: 'initial', marginTop: '5px' } : { marginTop: '5px', lineHeight: 'initial', marginBottom: '10px' }}>Beachte, dass die Reihenfolge des Auswählens maßgebend ist.</FormHelperText>
{this.props.error ? <FormHelperText className={this.props.classes.errorColor}>Wähle mindestens eine Hardware-Komponente aus.</FormHelperText> : null}
<FormHelperText style={this.props.error ? { lineHeight: 'initial', marginTop: '5px' } : { marginTop: '5px', lineHeight: 'initial', marginBottom: '10px' }}>{Blockly.Msg.builder_hardware_order}</FormHelperText>
{this.props.error ? <FormHelperText className={this.props.classes.errorColor}>{Blockly.Msg.builder_hardware_helper}</FormHelperText> : null}
<GridList cellHeight={100} cols={cols} spacing={10}>
{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 }}>
@@ -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 (
<FormControl style={{ marginBottom: '10px', padding: '18.5px 14px', borderRadius: '25px', border: '1px solid lightgrey', width: 'calc(100% - 28px)' }}>
<FormLabel style={{ color: 'black' }}>Voraussetzungen</FormLabel>
<FormHelperText style={{ marginTop: '5px' }}>Beachte, dass die Reihenfolge des Anhakens maßgebend ist.</FormHelperText>
<FormLabel style={{ color: 'black' }}>{Blockly.Msg.builder_requirements_head}</FormLabel>
<FormHelperText style={{ marginTop: '5px' }}>{Blockly.Msg.builder_requirements_order}</FormHelperText>
<FormGroup>
{this.props.tutorials.filter(tutorial => tutorial._id !== this.props.id).map((tutorial, i) =>
<FormControlLabel