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
+2 -1
View File
@@ -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 {
</Grid>
<Grid item xs={12} md={6} lg={4} style={isWidthDown('sm', this.props.width) ? { height: 'max-content' } : {}}>
<Card style={{ height: 'calc(50% - 30px)', padding: '10px', marginBottom: '10px' }}>
<Typography variant='h5'>Arbeitsauftrag</Typography>
<Typography variant='h5'>{Blockly.Msg.tutorials_assessment_task}</Typography>
<Typography>{currentTask.text}</Typography>
</Card>
<div style={isWidthDown('sm', this.props.width) ? { height: '500px' } : { height: '50%' }}>
+21 -20
View File
@@ -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}
>
<div style={{ marginTop: '10px' }}>
<Paper style={{textAlign: 'center'}}>
<Paper style={{ textAlign: 'center' }}>
{this.props.message.msg.image && this.props.message.msg.image.path ?
<Avatar src={`${process.env.REACT_APP_MYBADGES}/media/${this.props.message.msg.image.path}`} style={{width: '200px', height: '200px', marginLeft: 'auto', marginRight: 'auto'}}/>
: <Avatar style={{width: '200px', height: '200px', marginLeft: 'auto', marginRight: 'auto'}}></Avatar>}
<Typography variant='h6' style={{display: 'flex', cursor: 'default', paddingBottom: '6px'}}>
<div style={{flexGrow:1, marginLeft: '10px', marginRight: '10px'}}>{this.props.message.msg.name}</div>
<Avatar src={`${process.env.REACT_APP_MYBADGES}/media/${this.props.message.msg.image.path}`} style={{ width: '200px', height: '200px', marginLeft: 'auto', marginRight: 'auto' }} />
: <Avatar style={{ width: '200px', height: '200px', marginLeft: 'auto', marginRight: 'auto' }}></Avatar>}
<Typography variant='h6' style={{ display: 'flex', cursor: 'default', paddingBottom: '6px' }}>
<div style={{ flexGrow: 1, marginLeft: '10px', marginRight: '10px' }}>{this.props.message.msg.name}</div>
</Typography>
</Paper>
<Typography style={{marginTop: '10px'}}>
Eine Übersicht über alle erhaltenen Badges im Kontext Blockly for senseBox findest du <Link to={'/user/badge'} className={this.props.classes.link}>hier</Link>.
<Typography style={{ marginTop: '10px' }}>
{Blockly.Msg.badges_explaination}<Link to={'/user/badge'} className={this.props.classes.link}>{Blockly.Msg.labels_here}</Link>.
</Typography>
</div>
</Dialog>
@@ -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
+4 -4
View File
@@ -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 (
<div style={{ marginTop: '10px', marginBottom: '5px' }}>
<Typography>Für die Umsetzung benötigst du folgende Hardware:</Typography>
<Typography>{Blockly.Msg.tutorials_hardware_head}</Typography>
<GridList cellHeight={100} cols={cols} spacing={10}>
{this.props.picture.map((picture, i) => {
@@ -91,11 +91,11 @@ class Hardware extends Component {
content={this.state.content}
onClose={this.handleClose}
onClick={this.handleClose}
button={'Schließen'}
button={Blockly.Msg.button_close}
>
<div>
<img src={`/media/hardware/${this.state.hardwareInfo.src}`} width="100%" alt={this.state.hardwareInfo.name} />
Weitere Informationen zur Hardware-Komponente findest du <Link rel="noreferrer" target="_blank" href={this.state.hardwareInfo.url} color="primary">hier</Link>.
{Blockly.Msg.tutorials_hardware_moreInformation} <Link rel="noreferrer" target="_blank" href={this.state.hardwareInfo.url} color="primary">{Blockly.Msg.tutorials_hardware_here}</Link>.
</div>
</Dialog>
+20 -19
View File
@@ -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: {
@@ -45,7 +46,7 @@ class HintTutorialExists extends Component {
window.localStorage.setItem('news', e.target.checked);
}
else {
window.localStorage.deleteItem('news');
window.localStorage.removeItem('news');
}
}
@@ -56,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={'Schließen'}
button={Blockly.Msg.button_close}
>
<div>
Es gibt ab jetzt Tutorials zu verschiedenen Themen. Schau mal <Link to="/tutorial" className={this.props.classes.link}>hier</Link> vorbei.
<FormControlLabel
style={{ marginTop: '20px' }}
classes={{ label: this.props.classes.label }}
control={
<Checkbox
size={'small'}
value={true}
checked={this.state.checked}
onChange={(e) => this.onChange(e)}
name="dialog"
color="primary"
/>
}
label={'Dialog nicht mehr anzeigen'}
/>
{Blockly.Msg.messages_newblockly_text}<Link to="/tutorial" className={this.props.classes.link}>test</Link>
</div>
<FormControlLabel
style={{ marginTop: '20px' }}
classes={{ label: this.props.classes.label }}
control={
<Checkbox
size={'small'}
value={true}
checked={this.state.checked}
onChange={(e) => this.onChange(e)}
name="dialog"
color="primary"
/>
}
label={Blockly.Msg.labels_donotshowagain}
/>
</Dialog>
);
};
+2 -1
View File
@@ -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 (
<div style={{ marginTop: '20px', marginBottom: '5px' }}>
<Typography>Bevor du mit diesem Tutorial fortfährst solltest du folgende Tutorials erfolgreich abgeschlossen haben:</Typography>
<Typography>{Blockly.Msg.tutorials_requirements}</Typography>
<List component="div">
{tutorialIds.map((tutorialId, i) => {
var title = requirements[i].title
+6 -4
View File
@@ -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 (
<div>
<Tooltip title='Lösung kontrollieren' arrow>
<Tooltip title={Blockly.Msg.tooltip_check_solution} arrow>
<IconButton
className={this.props.classes.compile}
style={{ width: '40px', height: '40px', marginRight: '5px' }}
@@ -76,7 +78,7 @@ class SolutionCheck extends Component {
content={this.state.msg.text}
onClose={this.toggleDialog}
onClick={this.toggleDialog}
button={'Schließen'}
button={Blockly.Msg.button_close}
>
{this.state.msg.type === 'success' ?
<div style={{ marginTop: '20px', display: 'flex' }}>
@@ -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}
</Button>
:
<Button
@@ -97,7 +99,7 @@ class SolutionCheck extends Component {
color="primary"
onClick={() => { this.toggleDialog(); this.props.tutorialStep(this.props.activeStep + 1) }}
>
nächster Schritt
{Blockly.Msg.button_next}
</Button>
}
</div>
+2 -3
View File
@@ -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 {
<div className={this.props.classes.stepper}>
<Button
disabled//={tutorialIndex === 0}
//onClick={() => { this.props.history.push(`/tutorial/${tutorials[tutorialIndex - 1].id}`) }}
//onClick={() => { this.props.history.push(`/tutorial/${tutorials[tutorialIndex - 1].id}`) }}
>
{'<'}
</Button>
@@ -83,7 +82,7 @@ class StepperHorizontal extends Component {
</Tooltip>
<Button
disabled//={tutorialIndex + 1 === tutorials.length}
//onClick={() => { this.props.history.push(`/tutorial/${tutorials[tutorialIndex + 1].id}`) }}
//onClick={() => { this.props.history.push(`/tutorial/${tutorials[tutorialIndex + 1].id}`) }}
>
{'>'}
</Button>
+30 -29
View File
@@ -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';
@@ -38,7 +38,7 @@ class Tutorial extends Component {
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'){
if (this.props.message.id === 'GET_TUTORIAL_FAIL') {
alert(this.props.message.msg);
}
}
@@ -46,7 +46,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();
}
}
@@ -56,37 +56,38 @@ class Tutorial extends Component {
<div>
{this.props.isLoading ? null :
!this.props.tutorial ?
this.props.message.id === 'GET_TUTORIAL_FAIL' ? <NotFound button={{ title: 'Zurück zur Tutorials-Übersicht', link: '/tutorial' }} /> : null
this.props.message.id === 'GET_TUTORIAL_FAIL' ? <NotFound button={{ title: Blockly.Msg.messages_GET_TUTORIAL_FAIL, link: '/tutorial' }} /> : 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(
<div>
<Breadcrumbs content={[{ link: '/tutorial', title: 'Tutorial' }, { link: `/tutorial/${this.props.tutorial._id}`, title: tutorial.title }]} />
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 (
<div>
<Breadcrumbs content={[{ link: '/tutorial', title: 'Tutorial' }, { link: `/tutorial/${this.props.tutorial._id}`, title: tutorial.title }]} />
<StepperHorizontal />
<Badge />
<StepperHorizontal />
<Badge />
<div style={{ display: 'flex' }}>
<StepperVertical steps={steps} />
{/* calc(Card-padding: 10px + Button-height: 35px + Button-marginTop: 15px)*/}
<Card style={{ padding: '10px 10px 60px 10px', display: 'block', position: 'relative', height: 'max-content', width: '100%' }}>
{step ?
step.type === 'instruction' ?
<Instruction step={step} />
: <Assessment step={step} name={name} /> // if step.type === 'assessment'
: null}
<div style={{ display: 'flex' }}>
<StepperVertical steps={steps} />
{/* calc(Card-padding: 10px + Button-height: 35px + Button-marginTop: 15px)*/}
<Card style={{ padding: '10px 10px 60px 10px', display: 'block', position: 'relative', height: 'max-content', width: '100%' }}>
{step ?
step.type === 'instruction' ?
<Instruction step={step} />
: <Assessment step={step} name={name} /> // if step.type === 'assessment'
: null}
<div style={{ marginTop: '20px', position: 'absolute', bottom: '10px' }}>
<Button style={{ marginRight: '10px', height: '35px' }} variant='contained' disabled={this.props.activeStep === 0} onClick={() => this.props.tutorialStep(this.props.activeStep - 1)}>Zurück</Button>
<Button style={{ height: '35px' }} variant='contained' color='primary' disabled={this.props.activeStep === tutorial.steps.length - 1} onClick={() => this.props.tutorialStep(this.props.activeStep + 1)}>Weiter</Button>
</div>
</Card>
</div>
<div style={{ marginTop: '20px', position: 'absolute', bottom: '10px' }}>
<Button style={{ marginRight: '10px', height: '35px' }} variant='contained' disabled={this.props.activeStep === 0} onClick={() => this.props.tutorialStep(this.props.activeStep - 1)}>Zurück</Button>
<Button style={{ height: '35px' }} variant='contained' color='primary' disabled={this.props.activeStep === tutorial.steps.length - 1} onClick={() => this.props.tutorialStep(this.props.activeStep + 1)}>Weiter</Button>
</div>
</Card>
</div>
)})()
</div>
)
})()
}
</div>
);