template created for not deactivated blocks in the instructions
This commit is contained in:
parent
8ec8409504
commit
4a5d24f2d1
@ -26,14 +26,18 @@ class BlocklyWindow extends Component {
|
|||||||
this.props.clearStats();
|
this.props.clearStats();
|
||||||
workspace.addChangeListener((event) => {
|
workspace.addChangeListener((event) => {
|
||||||
this.props.onChangeWorkspace(event);
|
this.props.onChangeWorkspace(event);
|
||||||
Blockly.Events.disableOrphans(event);
|
// switch on that a block is displayed disabled or not depending on whether it is correctly connected
|
||||||
|
// for SVG display, a deactivated block in the display is undesirable
|
||||||
|
if(this.props.blockDisabled){
|
||||||
|
Blockly.Events.disableOrphans(event);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
Blockly.svgResize(workspace);
|
Blockly.svgResize(workspace);
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidUpdate(props) {
|
componentDidUpdate(props) {
|
||||||
const workspace = Blockly.getMainWorkspace();
|
const workspace = Blockly.getMainWorkspace();
|
||||||
var xml = this.props.initialXml
|
var xml = this.props.initialXml;
|
||||||
// if svg is true, then the update process is done in the BlocklySvg component
|
// if svg is true, then the update process is done in the BlocklySvg component
|
||||||
if(props.initialXml !== xml && !this.props.svg){
|
if(props.initialXml !== xml && !this.props.svg){
|
||||||
// guarantees that the current xml-code (this.props.initialXml) is rendered
|
// guarantees that the current xml-code (this.props.initialXml) is rendered
|
||||||
|
@ -87,7 +87,7 @@ class Home extends Component {
|
|||||||
</IconButton>
|
</IconButton>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
<TrashcanButtons />
|
<TrashcanButtons />
|
||||||
<BlocklyWindow blocklyCSS={{height: '500px'}}/>
|
<BlocklyWindow blocklyCSS={{height: '500px'}} blockDisabled/>
|
||||||
</Grid>
|
</Grid>
|
||||||
{this.state.codeOn ?
|
{this.state.codeOn ?
|
||||||
<Grid item xs={12} md={6}>
|
<Grid item xs={12} md={6}>
|
||||||
|
@ -41,6 +41,7 @@ class Assessment extends Component {
|
|||||||
<Grid item xs={12} md={6} lg={8}>
|
<Grid item xs={12} md={6} lg={8}>
|
||||||
<BlocklyWindow
|
<BlocklyWindow
|
||||||
initialXml={statusTask ? statusTask.xml ? statusTask.xml : null : null}
|
initialXml={statusTask ? statusTask.xml ? statusTask.xml : null : null}
|
||||||
|
blockDisabled
|
||||||
blocklyCSS={{height: '500px'}}
|
blocklyCSS={{height: '500px'}}
|
||||||
/>
|
/>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
@ -7,6 +7,7 @@ import moment from 'moment';
|
|||||||
import localization from 'moment/locale/de';
|
import localization from 'moment/locale/de';
|
||||||
import * as Blockly from 'blockly/core';
|
import * as Blockly from 'blockly/core';
|
||||||
|
|
||||||
|
import { initialXml } from '../../Blockly//initialXml.js';
|
||||||
import BlocklyWindow from '../../Blockly/BlocklyWindow';
|
import BlocklyWindow from '../../Blockly/BlocklyWindow';
|
||||||
|
|
||||||
import { withStyles } from '@material-ui/core/styles';
|
import { withStyles } from '@material-ui/core/styles';
|
||||||
@ -41,10 +42,12 @@ class BlocklyExample extends Component {
|
|||||||
this.state={
|
this.state={
|
||||||
checked: props.task ? props.task : props.value ? true : false,
|
checked: props.task ? props.task : props.value ? true : false,
|
||||||
input: null,
|
input: null,
|
||||||
|
disabled: false
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount(){
|
componentDidMount(){
|
||||||
|
moment.updateLocale('de', localization);
|
||||||
this.isError();
|
this.isError();
|
||||||
// if(this.props.task){
|
// if(this.props.task){
|
||||||
// this.props.setError(this.props.index, 'xml');
|
// this.props.setError(this.props.index, 'xml');
|
||||||
@ -57,14 +60,36 @@ class BlocklyExample extends Component {
|
|||||||
() => this.isError()
|
() => this.isError()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if(state.checked !== this.state.checked){
|
if(state.checked !== this.state.checked && this.state.checked){
|
||||||
this.isError();
|
this.isError();
|
||||||
}
|
}
|
||||||
|
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});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
isError = () => {
|
isError = () => {
|
||||||
if(this.state.checked && !this.props.value){
|
if(this.state.checked){
|
||||||
this.props.setError(this.props.index, 'xml');
|
var xml = this.props.value;
|
||||||
|
// check if value is valid xml;
|
||||||
|
try{
|
||||||
|
Blockly.Xml.textToDom(xml);
|
||||||
|
this.props.deleteError(this.props.index, 'xml');
|
||||||
|
}
|
||||||
|
catch(err){
|
||||||
|
xml = initialXml;
|
||||||
|
// not valid xml, throw error in redux store
|
||||||
|
this.props.setError(this.props.index, 'xml');
|
||||||
|
}
|
||||||
|
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});
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
this.props.deleteError(this.props.index, 'xml');
|
this.props.deleteError(this.props.index, 'xml');
|
||||||
@ -79,8 +104,13 @@ class BlocklyExample extends Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setXml = () => {
|
||||||
|
var xml = this.props.xml;
|
||||||
|
this.props.changeContent(this.props.index, 'xml', xml);
|
||||||
|
this.setState({input: moment(Date.now()).format('LTS')});
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
moment.locale('de', localization);
|
|
||||||
return (
|
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 ?
|
{!this.props.task ?
|
||||||
@ -100,22 +130,18 @@ class BlocklyExample extends Component {
|
|||||||
<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>
|
<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
|
: this.state.input ? <FormHelperText style={{lineHeight: 'initial'}}>Die letzte Einreichung erfolgte um {this.state.input} Uhr.</FormHelperText> : null
|
||||||
: 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}
|
||||||
{this.state.checked ? (() => {
|
{this.state.checked ? (() => {
|
||||||
var initialXml = this.props.value;
|
return(
|
||||||
// check if value is valid xml;
|
|
||||||
try{
|
|
||||||
Blockly.Xml.textToDom(initialXml);
|
|
||||||
}
|
|
||||||
catch(err){
|
|
||||||
initialXml = null;
|
|
||||||
// this.props.setError(this.props.index, 'xml');
|
|
||||||
}
|
|
||||||
return (
|
|
||||||
<div style={{marginTop: '10px'}}>
|
<div style={{marginTop: '10px'}}>
|
||||||
<Grid container className={!this.props.value || this.props.error ? this.props.classes.errorBorder : null}>
|
<Grid container className={!this.props.value || this.props.error ? this.props.classes.errorBorder : null}>
|
||||||
<Grid item xs={12}>
|
<Grid item xs={12}>
|
||||||
<BlocklyWindow
|
<BlocklyWindow
|
||||||
initialXml={initialXml}
|
blockDisabled={this.props.task}
|
||||||
|
trashcan={false}
|
||||||
|
initialXml={this.state.xml}
|
||||||
blocklyCSS={{height: '500px'}}
|
blocklyCSS={{height: '500px'}}
|
||||||
/>
|
/>
|
||||||
</Grid>
|
</Grid>
|
||||||
@ -125,7 +151,8 @@ class BlocklyExample extends Component {
|
|||||||
style={{marginTop: '5px', height: '40px'}}
|
style={{marginTop: '5px', height: '40px'}}
|
||||||
variant='contained'
|
variant='contained'
|
||||||
color='primary'
|
color='primary'
|
||||||
onClick={() => {this.props.changeContent(this.props.index, 'xml', this.props.xml); this.setState({input: moment(Date.now()).format('LTS')})}}
|
disabled={this.state.disabled}
|
||||||
|
onClick={() => this.setXml()}
|
||||||
>
|
>
|
||||||
{this.props.task ? 'Musterlösung einreichen' : 'Beispiel einreichen'}
|
{this.props.task ? 'Musterlösung einreichen' : 'Beispiel einreichen'}
|
||||||
</Button>
|
</Button>
|
||||||
|
@ -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, deleteProperty } from '../../../actions/tutorialBuilderActions';
|
||||||
|
|
||||||
import Radio from '@material-ui/core/Radio';
|
import Radio from '@material-ui/core/Radio';
|
||||||
import RadioGroup from '@material-ui/core/RadioGroup';
|
import RadioGroup from '@material-ui/core/RadioGroup';
|
||||||
@ -9,9 +9,15 @@ import FormControlLabel from '@material-ui/core/FormControlLabel';
|
|||||||
|
|
||||||
class StepType extends Component {
|
class StepType extends Component {
|
||||||
|
|
||||||
|
onChange = (value) => {
|
||||||
|
this.props.changeContent(this.props.index, 'type', value);
|
||||||
|
// delete property 'xml', so that all used blocks are reset
|
||||||
|
this.props.deleteProperty(this.props.index, 'xml');
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<RadioGroup row value={this.props.value === 'task' ? 'task' : 'instruction'} onChange={(e) => {this.props.changeContent(this.props.index, 'type', e.target.value)}}>
|
<RadioGroup row value={this.props.value === 'task' ? 'task' : 'instruction'} onChange={(e) => this.onChange(e.target.value)}>
|
||||||
<FormControlLabel style={{color: 'black'}}
|
<FormControlLabel style={{color: 'black'}}
|
||||||
value="instruction"
|
value="instruction"
|
||||||
control={<Radio color="primary" />}
|
control={<Radio color="primary" />}
|
||||||
@ -31,7 +37,8 @@ class StepType extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
StepType.propTypes = {
|
StepType.propTypes = {
|
||||||
changeContent: PropTypes.func.isRequired
|
changeContent: PropTypes.func.isRequired,
|
||||||
|
deleteProperty: PropTypes.func.isRequired
|
||||||
};
|
};
|
||||||
|
|
||||||
export default connect(null, { changeContent })(StepType);
|
export default connect(null, { changeContent, deleteProperty })(StepType);
|
||||||
|
@ -28,6 +28,7 @@ class Instruction extends Component {
|
|||||||
<Grid item xs={12}>
|
<Grid item xs={12}>
|
||||||
<BlocklyWindow
|
<BlocklyWindow
|
||||||
svg
|
svg
|
||||||
|
blockDisabled
|
||||||
initialXml={step.xml}
|
initialXml={step.xml}
|
||||||
/>
|
/>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
@ -42,7 +42,7 @@ class Tutorial extends Component {
|
|||||||
var step = steps ? steps[this.props.activeStep] : null;
|
var step = steps ? steps[this.props.activeStep] : null;
|
||||||
var name = step ? `${detectWhitespacesAndReturnReadableResult(tutorial.title)}_${detectWhitespacesAndReturnReadableResult(step.headline)}` : null;
|
var name = step ? `${detectWhitespacesAndReturnReadableResult(tutorial.title)}_${detectWhitespacesAndReturnReadableResult(step.headline)}` : null;
|
||||||
return (
|
return (
|
||||||
!Number.isInteger(currentTutorialId) || currentTutorialId < 1 || currentTutorialId > tutorials.length ?
|
!Number.isInteger(currentTutorialId) || currentTutorialId < 1 || !tutorial ?
|
||||||
<NotFound button={{title: 'Zurück zur Tutorials-Übersicht', link: '/tutorial'}}/>
|
<NotFound button={{title: 'Zurück zur Tutorials-Übersicht', link: '/tutorial'}}/>
|
||||||
:
|
:
|
||||||
<div>
|
<div>
|
||||||
|
@ -125,7 +125,7 @@ class WorkspaceFunc extends Component {
|
|||||||
this.state.file === 'xml' ? this.saveXmlFile() : this.getSvg()
|
this.state.file === 'xml' ? this.saveXmlFile() : this.getSvg()
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
this.setState({ saveFile: true, file: filetype, open: true, title: this.state.file === 'xml' ? 'Blöcke speichern' : 'Screenshot erstellen', content: `Bitte gib einen Namen für die Bennenung der ${this.state.file === 'xml' ? 'XML' : 'SVG'}-Datei ein und bestätige diesen mit einem Klick auf \'Eingabe\'.` });
|
this.setState({ saveFile: true, file: filetype, open: true, title: this.state.file === 'xml' ? 'Blöcke speichern' : 'Screenshot erstellen', content: `Bitte gib einen Namen für die Bennenung der ${this.state.file === 'xml' ? 'XML' : 'SVG'}-Datei ein und bestätige diesen mit einem Klick auf 'Eingabe'.` });
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user