add block sharing
This commit is contained in:
		
							parent
							
								
									0cb7bba521
								
							
						
					
					
						commit
						e647d6e58e
					
				
							
								
								
									
										1
									
								
								.env
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								.env
									
									
									
									
									
								
							| @ -1,2 +1,3 @@ | |||||||
| REACT_APP_COMPILER_URL=https://compiler.sensebox.de | REACT_APP_COMPILER_URL=https://compiler.sensebox.de | ||||||
| REACT_APP_BOARD=sensebox-mcu | REACT_APP_BOARD=sensebox-mcu | ||||||
|  | REACT_APP_BLOCKLY_API=http://46.101.243.134:3000 | ||||||
|  | |||||||
							
								
								
									
										32
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										32
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							| @ -8720,6 +8720,11 @@ | |||||||
|         "minimist": "^1.2.5" |         "minimist": "^1.2.5" | ||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|  |     "mnemonic-id": { | ||||||
|  |       "version": "3.2.7", | ||||||
|  |       "resolved": "https://registry.npmjs.org/mnemonic-id/-/mnemonic-id-3.2.7.tgz", | ||||||
|  |       "integrity": "sha512-kysx9gAGbvrzuFYxKkcRjnsg/NK61ovJOV4F1cHTRl9T5leg+bo6WI0pWIvOFh1Z/yDL0cjA5R3EEGPPLDv/XA==" | ||||||
|  |     }, | ||||||
|     "moment": { |     "moment": { | ||||||
|       "version": "2.29.0", |       "version": "2.29.0", | ||||||
|       "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.0.tgz", |       "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.0.tgz", | ||||||
| @ -11394,6 +11399,13 @@ | |||||||
|         "tough-cookie": "~2.5.0", |         "tough-cookie": "~2.5.0", | ||||||
|         "tunnel-agent": "^0.6.0", |         "tunnel-agent": "^0.6.0", | ||||||
|         "uuid": "^3.3.2" |         "uuid": "^3.3.2" | ||||||
|  |       }, | ||||||
|  |       "dependencies": { | ||||||
|  |         "uuid": { | ||||||
|  |           "version": "3.4.0", | ||||||
|  |           "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", | ||||||
|  |           "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==" | ||||||
|  |         } | ||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     "request-promise-core": { |     "request-promise-core": { | ||||||
| @ -12125,6 +12137,13 @@ | |||||||
|       "requires": { |       "requires": { | ||||||
|         "faye-websocket": "^0.10.0", |         "faye-websocket": "^0.10.0", | ||||||
|         "uuid": "^3.0.1" |         "uuid": "^3.0.1" | ||||||
|  |       }, | ||||||
|  |       "dependencies": { | ||||||
|  |         "uuid": { | ||||||
|  |           "version": "3.4.0", | ||||||
|  |           "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", | ||||||
|  |           "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==" | ||||||
|  |         } | ||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     "sockjs-client": { |     "sockjs-client": { | ||||||
| @ -13269,9 +13288,9 @@ | |||||||
|       "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" |       "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" | ||||||
|     }, |     }, | ||||||
|     "uuid": { |     "uuid": { | ||||||
|       "version": "3.4.0", |       "version": "8.3.1", | ||||||
|       "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", |       "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.1.tgz", | ||||||
|       "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==" |       "integrity": "sha512-FOmRr+FmWEIG8uhZv6C2bTgEVXsHk08kE7mPlrBbEe+c3r9pjceVPgupIfNIhc4yx55H69OXANrUaSuu9eInKg==" | ||||||
|     }, |     }, | ||||||
|     "v8-compile-cache": { |     "v8-compile-cache": { | ||||||
|       "version": "2.1.1", |       "version": "2.1.1", | ||||||
| @ -13929,6 +13948,13 @@ | |||||||
|       "requires": { |       "requires": { | ||||||
|         "ansi-colors": "^3.0.0", |         "ansi-colors": "^3.0.0", | ||||||
|         "uuid": "^3.3.2" |         "uuid": "^3.3.2" | ||||||
|  |       }, | ||||||
|  |       "dependencies": { | ||||||
|  |         "uuid": { | ||||||
|  |           "version": "3.4.0", | ||||||
|  |           "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", | ||||||
|  |           "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==" | ||||||
|  |         } | ||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     "webpack-manifest-plugin": { |     "webpack-manifest-plugin": { | ||||||
|  | |||||||
| @ -15,6 +15,7 @@ | |||||||
|     "@testing-library/user-event": "^7.2.1", |     "@testing-library/user-event": "^7.2.1", | ||||||
|     "blockly": "^3.20200924.0", |     "blockly": "^3.20200924.0", | ||||||
|     "file-saver": "^2.0.2", |     "file-saver": "^2.0.2", | ||||||
|  |     "mnemonic-id": "^3.2.7", | ||||||
|     "moment": "^2.28.0", |     "moment": "^2.28.0", | ||||||
|     "prismjs": "^1.20.0", |     "prismjs": "^1.20.0", | ||||||
|     "react": "^16.13.1", |     "react": "^16.13.1", | ||||||
| @ -23,7 +24,8 @@ | |||||||
|     "react-router-dom": "^5.2.0", |     "react-router-dom": "^5.2.0", | ||||||
|     "react-scripts": "3.4.1", |     "react-scripts": "3.4.1", | ||||||
|     "redux": "^4.0.5", |     "redux": "^4.0.5", | ||||||
|     "redux-thunk": "^2.3.0" |     "redux-thunk": "^2.3.0", | ||||||
|  |     "uuid": "^8.3.1" | ||||||
|   }, |   }, | ||||||
|   "scripts": { |   "scripts": { | ||||||
|     "start": "react-scripts start", |     "start": "react-scripts start", | ||||||
|  | |||||||
| @ -6,7 +6,7 @@ import clsx from 'clsx'; | |||||||
| 
 | 
 | ||||||
| import Breadcrumbs from '../Breadcrumbs'; | import Breadcrumbs from '../Breadcrumbs'; | ||||||
| 
 | 
 | ||||||
| import gallery from './gallery.json'; | // import gallery from './gallery.json';
 | ||||||
| // import tutorials from '../../data/tutorials.json';
 | // import tutorials from '../../data/tutorials.json';
 | ||||||
| 
 | 
 | ||||||
| import { Link } from 'react-router-dom'; | import { Link } from 'react-router-dom'; | ||||||
| @ -49,8 +49,24 @@ const styles = (theme) => ({ | |||||||
| }); | }); | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| class GalleryHome extends Component { | class GalleryHome extends Component { | ||||||
| 
 | 
 | ||||||
|  |     state = { | ||||||
|  |         gallery: [] | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     componentDidMount() { | ||||||
|  |         console.log(process.env.REACT_APP_BLOCKLY_API) | ||||||
|  |         fetch(process.env.REACT_APP_BLOCKLY_API + this.props.location.pathname) | ||||||
|  |             .then(res => res.json()) | ||||||
|  |             .then((data) => { | ||||||
|  |                 this.setState({ gallery: data }) | ||||||
|  |             }) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|     render() { |     render() { | ||||||
|         return ( |         return ( | ||||||
|             <div> |             <div> | ||||||
| @ -58,7 +74,7 @@ class GalleryHome extends Component { | |||||||
| 
 | 
 | ||||||
|                 <h1>Gallery</h1> |                 <h1>Gallery</h1> | ||||||
|                 <Grid container spacing={2}> |                 <Grid container spacing={2}> | ||||||
|                     {gallery.map((gallery, i) => { |                     {this.state.gallery.map((gallery, i) => { | ||||||
|                         return ( |                         return ( | ||||||
|                             <Grid item xs={12} sm={6} md={4} xl={3} key={i} style={{}}> |                             <Grid item xs={12} sm={6} md={4} xl={3} key={i} style={{}}> | ||||||
|                                 <Link to={`/gallery/${gallery.id}`} style={{ textDecoration: 'none', color: 'inherit' }}> |                                 <Link to={`/gallery/${gallery.id}`} style={{ textDecoration: 'none', color: 'inherit' }}> | ||||||
|  | |||||||
| @ -10,6 +10,7 @@ import WorkspaceFunc from './WorkspaceFunc'; | |||||||
| import BlocklyWindow from './Blockly/BlocklyWindow'; | import BlocklyWindow from './Blockly/BlocklyWindow'; | ||||||
| import CodeViewer from './CodeViewer'; | import CodeViewer from './CodeViewer'; | ||||||
| import TrashcanButtons from './TrashcanButtons'; | import TrashcanButtons from './TrashcanButtons'; | ||||||
|  | import { createNameId } from 'mnemonic-id'; | ||||||
| 
 | 
 | ||||||
| import Grid from '@material-ui/core/Grid'; | import Grid from '@material-ui/core/Grid'; | ||||||
| import IconButton from '@material-ui/core/IconButton'; | import IconButton from '@material-ui/core/IconButton'; | ||||||
| @ -18,7 +19,6 @@ import { withStyles } from '@material-ui/core/styles'; | |||||||
| 
 | 
 | ||||||
| import { faCode } from "@fortawesome/free-solid-svg-icons"; | import { faCode } from "@fortawesome/free-solid-svg-icons"; | ||||||
| import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; | import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; | ||||||
| import gallery from './Gallery/gallery.json'; |  | ||||||
| 
 | 
 | ||||||
| const styles = (theme) => ({ | const styles = (theme) => ({ | ||||||
|   codeOn: { |   codeOn: { | ||||||
| @ -46,11 +46,19 @@ class Home extends Component { | |||||||
| 
 | 
 | ||||||
|   state = { |   state = { | ||||||
|     codeOn: false, |     codeOn: false, | ||||||
|  |     gallery: [], | ||||||
|  |     share: [], | ||||||
|     projectToLoad: undefined |     projectToLoad: undefined | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   componentDidMount() { |   componentDidMount() { | ||||||
|     this.setState({ projectToLoad: gallery.find(project => project.id == this.props.match.params.galleryId) }) | 
 | ||||||
|  |     this.props.workspaceName(createNameId()); | ||||||
|  |     fetch(process.env.BLOCKLY_API + this.props.location.pathname) | ||||||
|  |       .then(res => res.json()) | ||||||
|  |       .then((data) => { | ||||||
|  |         this.setState({ projectToLoad: data }) | ||||||
|  |       }) | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| @ -85,6 +93,7 @@ class Home extends Component { | |||||||
|     if (this.state.projectToLoad) { |     if (this.state.projectToLoad) { | ||||||
|       console.log(this.state.projectToLoad.xml) |       console.log(this.state.projectToLoad.xml) | ||||||
|     } |     } | ||||||
|  |     console.log(this.props); | ||||||
|     return ( |     return ( | ||||||
|       <div> |       <div> | ||||||
|         <div style={{ float: 'right', height: '40px', marginBottom: '20px' }}><WorkspaceFunc /></div> |         <div style={{ float: 'right', height: '40px', marginBottom: '20px' }}><WorkspaceFunc /></div> | ||||||
|  | |||||||
| @ -20,6 +20,7 @@ class Routes extends Component { | |||||||
|           <Route path="/tutorial" exact component={TutorialHome} /> |           <Route path="/tutorial" exact component={TutorialHome} /> | ||||||
|           <Route path="/gallery" exact component={GalleryHome} /> |           <Route path="/gallery" exact component={GalleryHome} /> | ||||||
|           <Route path="/gallery/:galleryId" exact component={Home} /> |           <Route path="/gallery/:galleryId" exact component={Home} /> | ||||||
|  |           <Route path="/share/:shareId" exact component={Home} /> | ||||||
|           <Route path="/tutorial/builder" exact component={Builder} /> |           <Route path="/tutorial/builder" exact component={Builder} /> | ||||||
|           <Route path="/tutorial/:tutorialId" exact component={Tutorial} /> |           <Route path="/tutorial/:tutorialId" exact component={Tutorial} /> | ||||||
|           <Route component={NotFound} /> |           <Route component={NotFound} /> | ||||||
|  | |||||||
| @ -12,7 +12,6 @@ import { initialXml } from './Blockly/initialXml.js'; | |||||||
| 
 | 
 | ||||||
| import Compile from './Compile'; | import Compile from './Compile'; | ||||||
| import SolutionCheck from './Tutorial/SolutionCheck'; | import SolutionCheck from './Tutorial/SolutionCheck'; | ||||||
| import Dialog from './Dialog'; |  | ||||||
| import Snackbar from './Snackbar'; | import Snackbar from './Snackbar'; | ||||||
| 
 | 
 | ||||||
| import withWidth, { isWidthDown } from '@material-ui/core/withWidth'; | import withWidth, { isWidthDown } from '@material-ui/core/withWidth'; | ||||||
| @ -22,8 +21,19 @@ import IconButton from '@material-ui/core/IconButton'; | |||||||
| import Tooltip from '@material-ui/core/Tooltip'; | import Tooltip from '@material-ui/core/Tooltip'; | ||||||
| import TextField from '@material-ui/core/TextField'; | import TextField from '@material-ui/core/TextField'; | ||||||
| import Typography from '@material-ui/core/Typography'; | import Typography from '@material-ui/core/Typography'; | ||||||
|  | import { createId } from 'mnemonic-id'; | ||||||
| 
 | 
 | ||||||
| import { faPen, faSave, faUpload, faCamera, faShare } from "@fortawesome/free-solid-svg-icons"; | 
 | ||||||
|  | import Dialog from './Dialog'; | ||||||
|  | // import Dialog from '@material-ui/core/Dialog';
 | ||||||
|  | import DialogActions from '@material-ui/core/DialogActions'; | ||||||
|  | import DialogContent from '@material-ui/core/DialogContent'; | ||||||
|  | import DialogContentText from '@material-ui/core/DialogContentText'; | ||||||
|  | import DialogTitle from '@material-ui/core/DialogTitle'; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | import { faPen, faSave, faUpload, faCamera, faShare, faShareAlt } from "@fortawesome/free-solid-svg-icons"; | ||||||
| import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; | import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; | ||||||
| 
 | 
 | ||||||
| const styles = (theme) => ({ | const styles = (theme) => ({ | ||||||
| @ -49,9 +59,10 @@ const styles = (theme) => ({ | |||||||
| }); | }); | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
| class WorkspaceFunc extends Component { | class WorkspaceFunc extends Component { | ||||||
| 
 | 
 | ||||||
|   constructor(props){ |   constructor(props) { | ||||||
|     super(props); |     super(props); | ||||||
|     this.inputRef = React.createRef(); |     this.inputRef = React.createRef(); | ||||||
|     this.state = { |     this.state = { | ||||||
| @ -60,21 +71,25 @@ class WorkspaceFunc extends Component { | |||||||
|       open: false, |       open: false, | ||||||
|       file: false, |       file: false, | ||||||
|       saveFile: false, |       saveFile: false, | ||||||
|  |       share: false, | ||||||
|       name: props.name, |       name: props.name, | ||||||
|       snackbar: false, |       snackbar: false, | ||||||
|       key: '', |       key: '', | ||||||
|       message: '' |       message: '', | ||||||
|  |       id: '' | ||||||
|     }; |     }; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   componentDidUpdate(props){ | 
 | ||||||
|     if(props.name !== this.props.name){ | 
 | ||||||
|       this.setState({name: this.props.name}); |   componentDidUpdate(props) { | ||||||
|  |     if (props.name !== this.props.name) { | ||||||
|  |       this.setState({ name: this.props.name }); | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   toggleDialog = () => { |   toggleDialog = () => { | ||||||
|     this.setState({ open: !this.state }); |     this.setState({ open: !this.state, share: false }); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   saveXmlFile = () => { |   saveXmlFile = () => { | ||||||
| @ -87,6 +102,41 @@ class WorkspaceFunc extends Component { | |||||||
|     saveAs(blob, fileName); |     saveAs(blob, fileName); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|  |   shareBlocks = () => { | ||||||
|  |     let code = this.props.xml; | ||||||
|  |     let requestOptions = ''; | ||||||
|  |     let id = ''; | ||||||
|  |     if (this.state.id !== '') { | ||||||
|  |       requestOptions = { | ||||||
|  |         method: 'PUT', | ||||||
|  |         headers: { 'Content-Type': 'application/json' }, | ||||||
|  |         body: JSON.stringify({ | ||||||
|  |           id: this.state.id, | ||||||
|  |           name: this.state.name, | ||||||
|  |           xml: code | ||||||
|  |         }) | ||||||
|  |       }; | ||||||
|  |       fetch(process.env.BLOCKLY_API + '/share' + this.state.id, requestOptions) | ||||||
|  |         .then(response => response.json()) | ||||||
|  |         .then(data => this.setState({ share: true })); | ||||||
|  |     } | ||||||
|  |     else { | ||||||
|  |       id = createId(10); | ||||||
|  |       requestOptions = { | ||||||
|  |         method: 'POST', | ||||||
|  |         headers: { 'Content-Type': 'application/json' }, | ||||||
|  |         body: JSON.stringify({ | ||||||
|  |           id: id, | ||||||
|  |           name: this.state.name, | ||||||
|  |           xml: code | ||||||
|  |         }) | ||||||
|  |       }; | ||||||
|  |       fetch(process.env.BLOCKLY_API + '/share', requestOptions) | ||||||
|  |         .then(response => response.json()) | ||||||
|  |         .then(data => this.setState({ id: data.id, share: true })); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|   getSvg = () => { |   getSvg = () => { | ||||||
|     const workspace = Blockly.getMainWorkspace(); |     const workspace = Blockly.getMainWorkspace(); | ||||||
|     var canvas = workspace.svgBlockCanvas_.cloneNode(true); |     var canvas = workspace.svgBlockCanvas_.cloneNode(true); | ||||||
| @ -98,7 +148,7 @@ class WorkspaceFunc extends Component { | |||||||
|       // var cssContent = Blockly.Css.CONTENT.join('');
 |       // var cssContent = Blockly.Css.CONTENT.join('');
 | ||||||
|       var cssContent = ''; |       var cssContent = ''; | ||||||
|       for (var i = 0; i < document.getElementsByTagName('style').length; i++) { |       for (var i = 0; i < document.getElementsByTagName('style').length; i++) { | ||||||
|         if(/^blockly.*$/.test(document.getElementsByTagName('style')[i].id)){ |         if (/^blockly.*$/.test(document.getElementsByTagName('style')[i].id)) { | ||||||
|           cssContent += document.getElementsByTagName('style')[i].firstChild.data.replace(/\..* \./g, '.'); |           cssContent += document.getElementsByTagName('style')[i].firstChild.data.replace(/\..* \./g, '.'); | ||||||
|         } |         } | ||||||
|       } |       } | ||||||
| @ -125,22 +175,22 @@ class WorkspaceFunc extends Component { | |||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   createFileName = (filetype) => { |   createFileName = (filetype) => { | ||||||
|     this.setState({file: filetype}, () => { |     this.setState({ file: filetype }, () => { | ||||||
|       if(this.state.name){ |       if (this.state.name) { | ||||||
|         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'.` }); | ||||||
|       } |       } | ||||||
|     }); |     }); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   setFileName = (e) => { |   setFileName = (e) => { | ||||||
|     this.setState({name: e.target.value}); |     this.setState({ name: e.target.value }); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   uploadXmlFile = (xmlFile) => { |   uploadXmlFile = (xmlFile) => { | ||||||
|     if(xmlFile.type !== 'text/xml'){ |     if (xmlFile.type !== 'text/xml') { | ||||||
|       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.' }); |       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 { |     else { | ||||||
| @ -155,18 +205,18 @@ class WorkspaceFunc extends Component { | |||||||
|           workspace.clear(); |           workspace.clear(); | ||||||
|           this.props.clearStats(); |           this.props.clearStats(); | ||||||
|           Blockly.Xml.domToWorkspace(xmlDom, workspace); |           Blockly.Xml.domToWorkspace(xmlDom, workspace); | ||||||
|           if(workspace.getAllBlocks().length < 1){ |           if (workspace.getAllBlocks().length < 1) { | ||||||
|             Blockly.Xml.domToWorkspace(Blockly.Xml.textToDom(xmlBefore), workspace) |             Blockly.Xml.domToWorkspace(Blockly.Xml.textToDom(xmlBefore), workspace) | ||||||
|             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.' }); |             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 { |           else { | ||||||
|             if(!this.props.solutionCheck){ |             if (!this.props.solutionCheck) { | ||||||
|               var extensionPosition = xmlFile.name.lastIndexOf('.'); |               var extensionPosition = xmlFile.name.lastIndexOf('.'); | ||||||
|               this.props.workspaceName(xmlFile.name.substr(0, extensionPosition)); |               this.props.workspaceName(xmlFile.name.substr(0, extensionPosition)); | ||||||
|             } |             } | ||||||
|             this.setState({ snackbar: true, key: Date.now(), message: 'Das Projekt aus gegebener XML-Datei wurde erfolgreich eingefügt.' }); |             this.setState({ snackbar: true, key: Date.now(), message: 'Das Projekt aus gegebener XML-Datei wurde erfolgreich eingefügt.' }); | ||||||
|           } |           } | ||||||
|         } catch(err){ |         } catch (err) { | ||||||
|           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.' }); |           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.' }); | ||||||
|         } |         } | ||||||
|       }; |       }; | ||||||
| @ -189,56 +239,60 @@ class WorkspaceFunc extends Component { | |||||||
|     workspace.options.maxBlocks = Infinity; |     workspace.options.maxBlocks = Infinity; | ||||||
|     this.props.onChangeCode(); |     this.props.onChangeCode(); | ||||||
|     this.props.clearStats(); |     this.props.clearStats(); | ||||||
|     if(!this.props.solutionCheck){ |     if (!this.props.solutionCheck) { | ||||||
|       this.props.workspaceName(null); |       this.props.workspaceName(null); | ||||||
|     } |     } | ||||||
|     this.setState({ snackbar: true, key: Date.now(), message: 'Das Projekt wurde erfolgreich zurückgesetzt.' }); |     this.setState({ snackbar: true, key: Date.now(), message: 'Das Projekt wurde erfolgreich zurückgesetzt.' }); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|   render() { |   render() { | ||||||
|     return ( |     return ( | ||||||
|       <div style={{width: 'max-content', display: 'flex'}}> |       <div style={{ width: 'max-content', display: 'flex' }}> | ||||||
|         {!this.props.solutionCheck ? |         {!this.props.solutionCheck ? | ||||||
|           <Tooltip title={`Name des Projekts${this.props.name ? `: ${this.props.name}` : ''}`} arrow style={{marginRight: '5px'}}> |           <Tooltip title={`Name des Projekts${this.props.name ? `: ${this.props.name}` : ''}`} arrow style={{ marginRight: '5px' }}> | ||||||
|           <div className={this.props.classes.workspaceName} onClick={() => {this.setState({file: true, open: true, saveFile: false, title: 'Projekt benennen', content: 'Bitte gib einen Namen für das Projekt ein und bestätige diesen mit einem Klick auf \'Eingabe\'.'})}}> |             <div className={this.props.classes.workspaceName} onClick={() => { this.setState({ file: true, open: true, saveFile: 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) ? <Typography style={{margin: 'auto -3px auto 12px'}}>{this.props.name}</Typography> : null} |               {this.props.name && !isWidthDown('xs', this.props.width) ? <Typography style={{ margin: 'auto -3px auto 12px' }}>{this.props.name}</Typography> : null} | ||||||
|             <div style={{width: '40px', display: 'flex'}}> |               <div style={{ width: '40px', display: 'flex' }}> | ||||||
|               <FontAwesomeIcon icon={faPen} style={{height: '18px', width: '18px', margin: 'auto'}}/> |                 <FontAwesomeIcon icon={faPen} style={{ height: '18px', width: '18px', margin: 'auto' }} /> | ||||||
|  |               </div> | ||||||
|             </div> |             </div> | ||||||
|           </div> |  | ||||||
|           </Tooltip> |           </Tooltip> | ||||||
|         : null} |           : null} | ||||||
|         {this.props.solutionCheck ? <SolutionCheck /> : <Compile iconButton />} |         {this.props.solutionCheck ? <SolutionCheck /> : <Compile iconButton />} | ||||||
|         <Tooltip title='Blöcke speichern' arrow style={{marginRight: '5px'}}> |         <Tooltip title='Blöcke speichern' arrow style={{ marginRight: '5px' }}> | ||||||
|           <IconButton |           <IconButton | ||||||
|             className={this.props.classes.button} |             className={this.props.classes.button} | ||||||
|             onClick={() => {this.createFileName('xml');}} |             onClick={() => { this.createFileName('xml'); }} | ||||||
|           > |           > | ||||||
|             <FontAwesomeIcon icon={faSave} size="xs"/> |             <FontAwesomeIcon icon={faSave} size="xs" /> | ||||||
|           </IconButton> |           </IconButton> | ||||||
|         </Tooltip> |         </Tooltip> | ||||||
|         <div ref={this.inputRef} style={{width: 'max-content', height: '40px', marginRight: '5px'}}> |         <div ref={this.inputRef} style={{ width: 'max-content', height: '40px', marginRight: '5px' }}> | ||||||
|           <input |           <input | ||||||
|             style={{display: 'none'}} |             style={{ display: 'none' }} | ||||||
|             accept="text/xml" |             accept="text/xml" | ||||||
|             onChange={(e) => {this.uploadXmlFile(e.target.files[0])}} |             onChange={(e) => { this.uploadXmlFile(e.target.files[0]) }} | ||||||
|             id="open-blocks" |             id="open-blocks" | ||||||
|             type="file" |             type="file" | ||||||
|           /> |           /> | ||||||
|           <label htmlFor="open-blocks"> |           <label htmlFor="open-blocks"> | ||||||
|             <Tooltip title='Blöcke öffnen' arrow style={{marginRight: '5px'}}> |             <Tooltip title='Blöcke öffnen' arrow style={{ marginRight: '5px' }}> | ||||||
|               <div className={this.props.classes.button} style={{borderRadius: '50%', cursor: 'pointer', display: 'table-cell', |               <div className={this.props.classes.button} style={{ | ||||||
|               verticalAlign: 'middle', |                 borderRadius: '50%', cursor: 'pointer', display: 'table-cell', | ||||||
|               textAlign: 'center'}}> |                 verticalAlign: 'middle', | ||||||
|                 <FontAwesomeIcon icon={faUpload} style={{width: '18px', height: '18px'}}/> |                 textAlign: 'center' | ||||||
|  |               }}> | ||||||
|  |                 <FontAwesomeIcon icon={faUpload} style={{ width: '18px', height: '18px' }} /> | ||||||
|               </div> |               </div> | ||||||
|             </Tooltip> |             </Tooltip> | ||||||
|           </label> |           </label> | ||||||
|         </div> |         </div> | ||||||
|         <Tooltip title='Screenshot erstellen' arrow style={{marginRight: '5px'}}> |         <Tooltip title='Screenshot erstellen' arrow style={{ marginRight: '5px' }}> | ||||||
|           <IconButton |           <IconButton | ||||||
|             className={this.props.classes.button} |             className={this.props.classes.button} | ||||||
|             onClick={() => {this.createFileName('svg');}} |             onClick={() => { this.createFileName('svg'); }} | ||||||
|           > |           > | ||||||
|             <FontAwesomeIcon icon={faCamera} size="xs" /> |             <FontAwesomeIcon icon={faCamera} size="xs" /> | ||||||
|           </IconButton> |           </IconButton> | ||||||
| @ -248,24 +302,55 @@ class WorkspaceFunc extends Component { | |||||||
|             className={this.props.classes.button} |             className={this.props.classes.button} | ||||||
|             onClick={() => this.resetWorkspace()} |             onClick={() => this.resetWorkspace()} | ||||||
|           > |           > | ||||||
|             <FontAwesomeIcon icon={faShare} size="xs" flip='horizontal'/> |             <FontAwesomeIcon icon={faShare} size="xs" flip='horizontal' /> | ||||||
|           </IconButton> |           </IconButton> | ||||||
|         </Tooltip> |         </Tooltip> | ||||||
|  |         <Tooltip title='Blöcke teilen' arrow> | ||||||
|  |           <IconButton | ||||||
|  |             className={this.props.classes.button} | ||||||
|  |             onClick={() => this.shareBlocks()} | ||||||
|  |           > | ||||||
|  |             <FontAwesomeIcon icon={faShareAlt} size="xs" flip='horizontal' /> | ||||||
|  |           </IconButton> | ||||||
|  |         </Tooltip> | ||||||
|  | 
 | ||||||
|  |         <Dialog open={this.state.share} onClose={this.toggleDialog} aria-labelledby="form-dialog-title"> | ||||||
|  |           <DialogTitle id="form-dialog-title">Dein Link wurde erstellt.</DialogTitle> | ||||||
|  |           <DialogContent> | ||||||
|  |             <DialogContentText> | ||||||
|  |               Über den folgenden Link kannst du dein Programm teilen. | ||||||
|  |           </DialogContentText> | ||||||
|  |             <TextField | ||||||
|  |               autoFocus | ||||||
|  |               margin="dense" | ||||||
|  |               id="name" | ||||||
|  |               defaultValue={"http://localhost:3000/share/" + this.state.id} | ||||||
|  |               label="url" | ||||||
|  |               type="email" | ||||||
|  |               fullWidth | ||||||
|  |             /> | ||||||
|  |           </DialogContent> | ||||||
|  |           <DialogActions> | ||||||
|  |             <Button onClick={this.toggleDialog} color="primary"> | ||||||
|  |               Cancel | ||||||
|  |           </Button> | ||||||
|  |           </DialogActions> | ||||||
|  |         </Dialog> | ||||||
| 
 | 
 | ||||||
|         <Dialog |         <Dialog | ||||||
|           open={this.state.open} |           open={this.state.open} | ||||||
|           title={this.state.title} |           title={this.state.title} | ||||||
|           content={this.state.content} |           content={this.state.content} | ||||||
|           onClose={this.toggleDialog} |           onClose={this.toggleDialog} | ||||||
|           onClick={this.state.file ? () => {this.toggleDialog(); this.setState({name: this.props.name})} : this.toggleDialog} |           onClick={this.state.file ? () => { this.toggleDialog(); this.setState({ name: this.props.name }) } : this.toggleDialog} | ||||||
|           button={this.state.file ? 'Abbrechen' : 'Schließen'} |           button={this.state.file ? 'Abbrechen' : 'Schließen'} | ||||||
|         > |         > | ||||||
|           {this.state.file ? |           {this.state.file ? | ||||||
|             <div style={{marginTop: '10px'}}> |             <div style={{ marginTop: '10px' }}> | ||||||
|               <TextField autoFocus placeholder={this.state.saveXml ?'Dateiname' : 'Projektname'} value={this.state.name} onChange={this.setFileName} style={{marginRight: '10px'}}/> |               <TextField autoFocus placeholder={this.state.saveXml ? 'Dateiname' : 'Projektname'} value={this.state.name} onChange={this.setFileName} style={{ marginRight: '10px' }} /> | ||||||
|               <Button disabled={!this.state.name} variant='contained' color='primary' onClick={() => {this.state.saveFile ? this.state.file === 'xml' ? this.saveXmlFile() : this.getSvg() : this.renameWorkspace(); this.toggleDialog();}}>Eingabe</Button> |               <Button disabled={!this.state.name} variant='contained' color='primary' onClick={() => { this.state.saveFile ? this.state.file === 'xml' ? this.saveXmlFile() : this.getSvg() : this.renameWorkspace(); this.toggleDialog(); }}>Eingabe</Button> | ||||||
|             </div> |             </div> | ||||||
|           : null} |             : null} | ||||||
|         </Dialog> |         </Dialog> | ||||||
| 
 | 
 | ||||||
|         <Snackbar |         <Snackbar | ||||||
| @ -295,4 +380,4 @@ const mapStateToProps = state => ({ | |||||||
|   name: state.workspace.name |   name: state.workspace.name | ||||||
| }); | }); | ||||||
| 
 | 
 | ||||||
| export default connect(mapStateToProps, { clearStats, onChangeCode, workspaceName })(withStyles(styles, {withTheme: true})(withWidth()(WorkspaceFunc))); | export default connect(mapStateToProps, { clearStats, onChangeCode, workspaceName })(withStyles(styles, { withTheme: true })(withWidth()(WorkspaceFunc))); | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user