@@ -69,6 +72,7 @@ class Tutorial extends Component {
Tutorial.propTypes = {
tutorialId: PropTypes.func.isRequired,
tutorialStep: PropTypes.func.isRequired,
+ workspaceName: PropTypes.func.isRequired,
currentTutorialId: PropTypes.number,
status: PropTypes.array.isRequired,
change: PropTypes.number.isRequired,
@@ -82,4 +86,4 @@ const mapStateToProps = state => ({
activeStep: state.tutorial.activeStep
});
-export default connect(mapStateToProps, { tutorialId, tutorialStep })(Tutorial);
+export default connect(mapStateToProps, { tutorialId, tutorialStep, workspaceName })(Tutorial);
diff --git a/src/components/WorkspaceFunc.js b/src/components/WorkspaceFunc.js
index c8b6ca7..856dea5 100644
--- a/src/components/WorkspaceFunc.js
+++ b/src/components/WorkspaceFunc.js
@@ -1,7 +1,7 @@
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
-import { clearStats, onChangeCode } from '../actions/workspaceActions';
+import { clearStats, onChangeCode, workspaceName } from '../actions/workspaceActions';
import * as Blockly from 'blockly/core';
@@ -12,6 +12,7 @@ import { initialXml } from './Blockly/initialXml.js';
import Compile from './Compile';
import SolutionCheck from './Tutorial/SolutionCheck';
+import withWidth, { isWidthDown } from '@material-ui/core/withWidth';
import { withStyles } from '@material-ui/core/styles';
import Button from '@material-ui/core/Button';
import DialogTitle from '@material-ui/core/DialogTitle';
@@ -21,8 +22,9 @@ import Dialog from '@material-ui/core/Dialog';
import IconButton from '@material-ui/core/IconButton';
import Tooltip from '@material-ui/core/Tooltip';
import TextField from '@material-ui/core/TextField';
+import Typography from '@material-ui/core/Typography';
-import { faSave, faUpload, faShare } from "@fortawesome/free-solid-svg-icons";
+import { faPen, faSave, faUpload, faShare } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
const styles = (theme) => ({
@@ -35,6 +37,15 @@ const styles = (theme) => ({
backgroundColor: theme.palette.primary.main,
color: theme.palette.primary.contrastText,
}
+ },
+ workspaceName: {
+ backgroundColor: theme.palette.secondary.main,
+ borderRadius: '25px',
+ display: 'inline-flex',
+ cursor: 'pointer',
+ '&:hover': {
+ color: theme.palette.primary.main,
+ }
}
});
@@ -48,35 +59,48 @@ class WorkspaceFunc extends Component {
title: '',
content: '',
open: false,
- fileName: '',
- file: false
+ file: false,
+ saveXml: false,
+ name: props.name
};
}
- toggleDialog = () => {
- this.setState({ open: !this.state, fileName: '', file: false });
+ componentDidUpdate(props){
+ if(props.name !== this.props.name){
+ this.setState({name: this.props.name});
+ }
}
- saveXmlFile = (code) => {
+ toggleDialog = () => {
+ this.setState({ open: !this.state });
+ }
+
+ saveXmlFile = () => {
+ var code = this.props.xml;
this.toggleDialog();
- var fileName = this.state.fileName;
- if(fileName === '') fileName = 'unbekannt';
+ var fileName = this.state.name;
+ this.props.workspaceName(fileName);
fileName = `${fileName}.xml`
var blob = new Blob([code], { type: 'text/xml' });
saveAs(blob, fileName);
}
createFileName = () => {
- this.setState({ file: true, open: true, title: 'Blöcke speichern', content: 'Bitte gib einen Namen für die Bennenung der XML-Datei ein und bestätige diesen mit einem Klick auf \'Eingabe\'.' });
+ if(this.state.name){
+ this.saveXmlFile();
+ }
+ else{
+ this.setState({ file: true, saveXml: true, open: true, title: 'Blöcke speichern', content: 'Bitte gib einen Namen für die Bennenung der XML-Datei ein und bestätige diesen mit einem Klick auf \'Eingabe\'.' });
+ }
}
setFileName = (e) => {
- this.setState({ fileName: e.target.value });
+ this.setState({name: e.target.value});
}
uploadXmlFile = (xmlFile) => {
if(xmlFile.type !== 'text/xml'){
- this.setState({ open: true, title: 'Unzulässiger Dateityp', content: 'Die übergebene Datei entsprach nicht dem geforderten Format. Es sind nur XML-Dateien zulässig.' });
+ this.setState({ open: true, file: false, title: 'Unzulässiger Dateityp', content: 'Die übergebene Datei entsprach nicht dem geforderten Format. Es sind nur XML-Dateien zulässig.' });
}
else {
var reader = new FileReader();
@@ -92,10 +116,16 @@ class WorkspaceFunc extends Component {
Blockly.Xml.domToWorkspace(xmlDom, workspace);
if(workspace.getAllBlocks().length < 1){
Blockly.Xml.domToWorkspace(Blockly.Xml.textToDom(xmlBefore), workspace)
- this.setState({ open: true, title: 'Keine Blöcke', content: 'Es wurden keine Blöcke detektiert. Bitte überprüfe den XML-Code und versuche es erneut.' });
+ this.setState({ open: true, file: false, title: 'Keine Blöcke', content: 'Es wurden keine Blöcke detektiert. Bitte überprüfe den XML-Code und versuche es erneut.' });
+ }
+ else {
+ if(!this.props.solutionCheck){
+ var extensionPosition = xmlFile.name.lastIndexOf('.');
+ this.props.workspaceName(xmlFile.name.substr(0, extensionPosition));
+ }
}
} catch(err){
- this.setState({ open: true, title: 'Ungültige XML', content: 'Die XML-Datei konnte nicht in Blöcke zerlegt werden. Bitte überprüfe den XML-Code und versuche es erneut.' });
+ this.setState({ open: true, file: false, title: 'Ungültige XML', content: 'Die XML-Datei konnte nicht in Blöcke zerlegt werden. Bitte überprüfe den XML-Code und versuche es erneut.' });
}
};
}
@@ -111,11 +141,24 @@ class WorkspaceFunc extends Component {
workspace.options.maxBlocks = Infinity;
this.props.onChangeCode();
this.props.clearStats();
+ if(!this.props.solutionCheck){
+ this.props.workspaceName(null);
+ }
}
render() {
return (
+ {!this.props.solutionCheck ?
+
+
{this.setState({file: true, open: true, saveXml: false, title: 'Projekt benennen', content: 'Bitte gib einen Namen für das Projekt ein und bestätige diesen mit einem Klick auf \'Eingabe\'.'})}}>
+ {this.props.name && !isWidthDown('xs', this.props.width) ? {this.props.name} : null}
+