diff --git a/src/components/Compile.js b/src/components/Compile.js index 946466f..7fe5932 100644 --- a/src/components/Compile.js +++ b/src/components/Compile.js @@ -99,7 +99,7 @@ class Compile extends Component { this.download(); } else { - this.setState({ file: true, open: true, title: 'Blöcke kompilieren', content: 'Bitte gib einen Namen für die Bennenung des zu kompilierenden Programms ein und bestätige diesen mit einem Klick auf \'Eingabe\'.' }); + this.setState({ file: true, open: true, title: 'Projekt kompilieren', content: 'Bitte gib einen Namen für die Bennenung des zu kompilierenden Programms ein und bestätige diesen mit einem Klick auf \'Eingabe\'.' }); } } @@ -111,7 +111,7 @@ class Compile extends Component { return (
{this.props.iconButton ? - + this.compile()} diff --git a/src/components/Gallery/gallery.json b/src/components/Gallery/gallery.json deleted file mode 100644 index 0ff72ae..0000000 --- a/src/components/Gallery/gallery.json +++ /dev/null @@ -1,37 +0,0 @@ -[ - { - "id": 15212, - "title": "Das senseBox Buch Kapitel 1", - "name": "Mario", - "text": "Die Blöcke findest du in der Kategorie \"Schleifen\". Die einfachste Schleife, die du Verwenden kannst, ist der Block \"Wiederhole 10 mal\". Bei diesem Block kannst du die Blöcke, die eine bestimmte Zahl wiederholt werden soll einfach in den offenen Block abschnitt ziehen. ", - "xml": "\n \n \n \n 10\n \n \n \n" - }, - { - "id": 25451, - "title": "Das senseBox Buch Kapitel 2", - "name": "Mario", - "text": "", - "xml": "\n \n \n \n 1\n HIGH\n \n \n \n \n 1000\n \n \n \n \n 1\n LOW\n \n \n \n \n 1000\n \n \n \n \n \n \n \n \n \n \n \n" - }, - { - "id": 3541512, - "title": "Das senseBox Buch Kapitel 3", - "name": "Mario", - "text": "", - "xml": "\n \n \n \n \n \n \n \n \n WHITE,BLACK\n \n \n 1\n \n \n \n \n 0\n \n \n \n \n 0\n \n \n \n \n \n \n \n Helligkeit:\n \n \n \n \n Illuminance\n \n \n \n \n \n \n \n \n \n" - }, - { - "id": 7487454, - "title": "Das senseBox Buch Kapitel 4", - "name": "Mario", - "text": "", - "xml": "\n \n \n \n \n \n \n \n \n WHITE,BLACK\n \n \n 1\n \n \n \n \n 0\n \n \n \n \n 0\n \n \n \n \n \n \n \n Helligkeit:\n \n \n \n \n Illuminance\n \n \n \n \n \n \n \n \n \n" - }, - { - "id": 54541251, - "title": "Das senseBox Buch Kapitel 5", - "name": "Mario", - "text": "", - "xml": "" - } -] \ No newline at end of file diff --git a/src/components/Home.js b/src/components/Home.js index 432ec06..3bce82c 100644 --- a/src/components/Home.js +++ b/src/components/Home.js @@ -4,23 +4,19 @@ import { connect } from 'react-redux'; import { clearStats, workspaceName } from '../actions/workspaceActions'; import * as Blockly from 'blockly/core'; - -import axios from 'axios'; +import { createNameId } from 'mnemonic-id'; import WorkspaceStats from './WorkspaceStats'; import WorkspaceFunc from './WorkspaceFunc'; import BlocklyWindow from './Blockly/BlocklyWindow'; import CodeViewer from './CodeViewer'; import TrashcanButtons from './TrashcanButtons'; -import { createNameId } from 'mnemonic-id'; import HintTutorialExists from './Tutorial/HintTutorialExists'; import Grid from '@material-ui/core/Grid'; import IconButton from '@material-ui/core/IconButton'; import Tooltip from '@material-ui/core/Tooltip'; import { withStyles } from '@material-ui/core/styles'; -import Backdrop from '@material-ui/core/Backdrop'; -import CircularProgress from '@material-ui/core/CircularProgress'; import { faCode } from "@fortawesome/free-solid-svg-icons"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; @@ -51,22 +47,17 @@ class Home extends Component { state = { codeOn: false, - gallery: [], - share: [], - projectToLoad: undefined, - progress: false, - stats: window.localStorage.getItem('stats'), + stats: window.localStorage.getItem('stats') } componentDidMount() { - this.setState({ stats: window.localStorage.getItem('stats') }) - this.getProject(); + this.setState({ stats: window.localStorage.getItem('stats') }); + if(!this.props.project){ + this.props.workspaceName(createNameId()); + } } componentDidUpdate(props) { - if(props.location.path !== this.props.location.path){ - this.getProject(); - } /* Resize and reposition all of the workspace chrome (toolbox, trash, scrollbars etc.) This should be called when something changes that requires recalculating dimensions and positions of the trash, zoom, toolbox, etc. @@ -80,37 +71,6 @@ class Home extends Component { this.props.workspaceName(null); } - getProject = () => { - if(this.props.match.params.shareId || this.props.match.params.galleryId){ - var param = this.props.match.params.shareId ? 'share' : 'gallery'; - var id = this.props.match.params[`${param}Id`]; - this.setState({progress: true}); - axios.get(`${process.env.REACT_APP_BLOCKLY_API}/${param}/${id}`) - .then(res => { - var data = param === 'share' ? 'content' : param; - if(res.data[data]){ - this.props.workspaceName(res.data[data].name ? res.data[data].name : res.data[data].title); - this.setState({ projectToLoad: res.data[data], progress: false }); - } - else { - this.props.workspaceName(createNameId()); - this.setState({ progress: false }); - this.props.history.push('/'); - } - }) - .catch(err => { - // TODO: - this.setState({ progress: false, snackbar: true, key: Date.now(), message: `Fehler beim Aufrufen des angeforderten Programms. Versuche es noch einmal.`, type: 'error' }); - this.props.workspaceName(createNameId()); - this.props.history.push('/'); - window.scrollTo(0, 0); - }); - } - else { - this.props.workspaceName(createNameId()); - } - } - onChange = () => { this.setState({ codeOn: !this.state.codeOn }); const workspace = Blockly.getMainWorkspace(); @@ -123,44 +83,35 @@ class Home extends Component { render() { return (
- {this.state.progress ? - - - - : -
- {this.state.stats ? -
- : null - } -
- - - - this.onChange()} - > - - - - - {this.state.projectToLoad ? - < BlocklyWindow blocklyCSS={{ height: '80vH' }} initialXml={this.state.projectToLoad.xml} /> - : < BlocklyWindow blocklyCSS={{ height: '80vH' }} /> - } - - - {this.state.codeOn ? - - - - : null} + {this.state.stats ? +
+ : null + } +
+ + + + this.onChange()} + > + + + + + {this.props.project ? + < BlocklyWindow blocklyCSS={{ height: '80vH' }} initialXml={this.props.project} /> + : < BlocklyWindow blocklyCSS={{ height: '80vH' }} /> + } - -
- } + {this.state.codeOn ? + + + + : null} + +
); }; diff --git a/src/components/Navbar.js b/src/components/Navbar.js index a7137ed..f1d037b 100644 --- a/src/components/Navbar.js +++ b/src/components/Navbar.js @@ -20,7 +20,7 @@ import ListItemIcon from '@material-ui/core/ListItemIcon'; import ListItemText from '@material-ui/core/ListItemText'; import LinearProgress from '@material-ui/core/LinearProgress'; -import { faBars, faChevronLeft, faBuilding, faIdCard, faEnvelope, faCog, faChalkboardTeacher, faFolderPlus, faTools, faLightbulb } from "@fortawesome/free-solid-svg-icons"; +import { faBars, faChevronLeft, faLayerGroup, faBuilding, faIdCard, faEnvelope, faCog, faChalkboardTeacher, faFolderPlus, faTools, faLightbulb } from "@fortawesome/free-solid-svg-icons"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; const styles = (theme) => ({ @@ -99,7 +99,11 @@ class Navbar extends Component {
- {[{ text: 'Tutorials', icon: faChalkboardTeacher, link: "/tutorial" }, { text: 'Tutorial-Builder', icon: faTools, link: "/tutorial/builder" }, { text: 'Gallery', icon: faLightbulb, link: "/gallery" }, { text: 'Einstellungen', icon: faCog, link: "/settings" }].map((item, index) => ( + {[{ text: 'Tutorials', icon: faChalkboardTeacher, link: "/tutorial" }, + { text: 'Tutorial-Builder', icon: faTools, link: "/tutorial/builder" }, + { text: 'Galerie', icon: faLightbulb, link: "/gallery" }, + { text: 'Projekte', icon: faLayerGroup, link: "/project" }, + { text: 'Einstellungen', icon: faCog, link: "/settings" }].map((item, index) => ( diff --git a/src/components/Project/Project.js b/src/components/Project/Project.js new file mode 100644 index 0000000..da813e6 --- /dev/null +++ b/src/components/Project/Project.js @@ -0,0 +1,83 @@ +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; +import { connect } from 'react-redux'; +import { workspaceName } from '../../actions/workspaceActions'; + +import axios from 'axios'; +import { createNameId } from 'mnemonic-id'; + +import Home from '../Home'; +import Breadcrumbs from '../Breadcrumbs'; + +import Backdrop from '@material-ui/core/Backdrop'; +import CircularProgress from '@material-ui/core/CircularProgress'; + + +class Project extends Component { + + state = { + project: {}, + progress: false, + type: '' + } + + componentDidMount() { + this.getProject(); + } + + componentDidUpdate(props) { + if(props.location.path !== this.props.location.path){ + this.getProject(); + } + } + + getProject = () => { + var param = this.props.match.params.shareId ? 'share' : this.props.match.params.galleryId ? 'gallery' : 'project'; + this.setState({ type: param, progress: true }); + var id = this.props.match.params[`${param}Id`]; + axios.get(`${process.env.REACT_APP_BLOCKLY_API}/${param}/${id}`) + .then(res => { + var data = param === 'share' ? 'content' : param; + if(res.data[data]){ + this.props.workspaceName(res.data[data].title); + this.setState({ project: res.data[data], progress: false }); + } + else { + this.props.workspaceName(createNameId()); + this.setState({ progress: false }); + this.props.history.push('/'); + } + }) + .catch(err => { + // TODO: + this.setState({ progress: false, snackbar: true, key: Date.now(), message: `Fehler beim Aufrufen des angeforderten Programms. Versuche es noch einmal.`, type: 'error' }); + this.props.workspaceName(createNameId()); + this.props.history.push('/'); + window.scrollTo(0, 0); + }); + } + + render() { + var data = this.state.type === 'project' ? 'Projekte' : 'Galerie'; + return ( + this.state.progress ? + + + + : +
+ {this.state.type !== 'share' ? + + : null} + +
+ ); + }; +} + +Project.propTypes = { + workspaceName: PropTypes.func.isRequired +}; + + +export default connect(null, { workspaceName })(Project); diff --git a/src/components/Gallery/GalleryHome.js b/src/components/Project/ProjectHome.js similarity index 53% rename from src/components/Gallery/GalleryHome.js rename to src/components/Project/ProjectHome.js index ea142e6..1dd7708 100644 --- a/src/components/Gallery/GalleryHome.js +++ b/src/components/Project/ProjectHome.js @@ -12,16 +12,28 @@ import Divider from '@material-ui/core/Divider'; import Typography from '@material-ui/core/Typography'; -class GalleryHome extends Component { +class ProjectHome extends Component { state = { - gallery: [] + projects: [] } componentDidMount() { - axios.get(`${process.env.REACT_APP_BLOCKLY_API}/gallery`) + this.getProjects(); + } + + componentDidUpdate(props) { + if(props.match.path !== this.props.match.path){ + this.setState({projects: []}); + this.getProjects(); + } + } + + getProjects = () => { + var data = this.props.match.path === '/project' ? 'projects' : 'galleries'; + axios.get(`${process.env.REACT_APP_BLOCKLY_API}${this.props.match.path}`) .then(res => { - this.setState({ gallery: res.data.galleries }); + this.setState({ projects: res.data[data] }); }) .catch(err => { // TODO: @@ -29,25 +41,26 @@ class GalleryHome extends Component { } render() { + var data = this.props.match.path === '/project' ? 'Projekte' : 'Galerie'; return (
- + -

Gallery

+

{data}

- {this.state.gallery.map((gallery, i) => { + {this.state.projects.map((project, i) => { return ( - + -

{gallery.title}

+

{project.title}

- {gallery.description} + {project.description}
@@ -59,4 +72,4 @@ class GalleryHome extends Component { }; } -export default GalleryHome; +export default ProjectHome; diff --git a/src/components/Routes.js b/src/components/Routes.js index cf6b559..4dd5acc 100644 --- a/src/components/Routes.js +++ b/src/components/Routes.js @@ -10,7 +10,8 @@ import Tutorial from './Tutorial/Tutorial'; import TutorialHome from './Tutorial/TutorialHome'; import Builder from './Tutorial/Builder/Builder'; import NotFound from './NotFound'; -import GalleryHome from './Gallery/GalleryHome'; +import ProjectHome from './Project/ProjectHome'; +import Project from './Project/Project'; import Settings from './Settings/Settings'; import Impressum from './Impressum'; import Privacy from './Privacy'; @@ -27,15 +28,24 @@ class Routes extends Component {
+ // Tutorials + + + // Sharing + + // Gallery-Projects + + + // User-Projects + + + // settings - - + // privacy - - - + // Not Found
diff --git a/src/components/WorkspaceFunc.js b/src/components/WorkspaceFunc.js index ae3af26..86b3a55 100644 --- a/src/components/WorkspaceFunc.js +++ b/src/components/WorkspaceFunc.js @@ -5,6 +5,7 @@ import { clearStats, onChangeCode, workspaceName } from '../actions/workspaceAct import * as Blockly from 'blockly/core'; +import { withRouter } from 'react-router-dom'; import axios from 'axios'; import { saveAs } from 'file-saver'; @@ -14,6 +15,7 @@ import { initialXml } from './Blockly/initialXml.js'; import Compile from './Compile'; import SolutionCheck from './Tutorial/SolutionCheck'; import Snackbar from './Snackbar'; +import Dialog from './Dialog'; import { Link } from 'react-router-dom'; @@ -25,17 +27,7 @@ import Tooltip from '@material-ui/core/Tooltip'; import TextField from '@material-ui/core/TextField'; import Typography from '@material-ui/core/Typography'; - -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, faCopy } from "@fortawesome/free-solid-svg-icons"; +import { faPen, faSave, faUpload, faFileDownload, faCamera, faShare, faShareAlt, faCopy } from "@fortawesome/free-solid-svg-icons"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; const styles = (theme) => ({ @@ -101,7 +93,23 @@ class WorkspaceFunc extends Component { this.setState({ open: !this.state, share: false, file: false, saveFile: false, title: '', content: '' }); } - saveXmlFile = () => { + saveProject = () => { + var body = { + xml: this.props.xml, + title: this.props.name + }; + axios.post(`${process.env.REACT_APP_BLOCKLY_API}/project`, body) + .then(res => { + var project = res.data.project; + this.props.history.push(`/project/${project._id}`); + }) + .catch(err => { + this.setState({ snackbar: true, key: Date.now(), message: `Fehler beim Speichern des Projektes. Versuche es noch einmal.`, type: 'error' }); + window.scrollTo(0, 0); + }); + } + + downloadXmlFile = () => { var code = this.props.xml; this.toggleDialog(); var fileName = detectWhitespacesAndReturnReadableResult(this.state.name); @@ -173,10 +181,10 @@ class WorkspaceFunc extends Component { createFileName = (filetype) => { this.setState({ file: filetype }, () => { if (this.state.name) { - this.state.file === 'xml' ? this.saveXmlFile() : this.getSvg() + this.state.file === 'xml' ? this.downloadXmlFile() : this.getSvg() } 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' ? 'Projekt herunterladen' : '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'.` }); } }); } @@ -247,7 +255,7 @@ class WorkspaceFunc extends Component { return (
{!this.props.assessment ? - +
{ 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) ? {this.props.name} : null}
@@ -257,12 +265,20 @@ class WorkspaceFunc extends Component { : null} {this.props.assessment ? : } - + + this.saveProject()} + > + + + + { this.createFileName('xml'); }} > - + {!this.props.assessment? @@ -275,7 +291,7 @@ class WorkspaceFunc extends Component { type="file" />