Compare commits

..
Author SHA1 Message Date
Mario Pesch 431719f242 add markdown editor 2021-09-16 15:02:10 +02:00
7 changed files with 10930 additions and 9552 deletions
+848 -110
View File
File diff suppressed because it is too large Load Diff
+2 -2
View File
@@ -19,7 +19,6 @@
"@testing-library/user-event": "^7.2.1", "@testing-library/user-event": "^7.2.1",
"axios": "^0.21.0", "axios": "^0.21.0",
"blockly": "^6.20210701.0", "blockly": "^6.20210701.0",
"diff-js-xml": "^1.0.6",
"file-saver": "^2.0.2", "file-saver": "^2.0.2",
"mnemonic-id": "^3.2.7", "mnemonic-id": "^3.2.7",
"moment": "^2.28.0", "moment": "^2.28.0",
@@ -35,7 +34,8 @@
"reactour": "^1.18.0", "reactour": "^1.18.0",
"redux": "^4.0.5", "redux": "^4.0.5",
"redux-thunk": "^2.3.0", "redux-thunk": "^2.3.0",
"styled-components": "^4.4.1", "rich-markdown-editor": "^11.17.7",
"styled-components": "^5.0.0",
"uuid": "^8.3.1" "uuid": "^8.3.1"
}, },
"scripts": { "scripts": {
+25 -29
View File
@@ -20,18 +20,16 @@ class BlocklyWindow extends Component {
componentDidMount() { componentDidMount() {
const workspace = Blockly.getMainWorkspace(); const workspace = Blockly.getMainWorkspace();
if (!this.props.readOnly) { this.props.onChangeWorkspace({});
this.props.onChangeWorkspace({}); this.props.clearStats();
this.props.clearStats(); workspace.addChangeListener((event) => {
workspace.addChangeListener((event) => { this.props.onChangeWorkspace(event);
this.props.onChangeWorkspace(event); // switch on that a block is displayed disabled or not depending on whether it is correctly connected
// 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
// for SVG display, a deactivated block in the display is undesirable if (this.props.blockDisabled) {
if (this.props.blockDisabled) { Blockly.Events.disableOrphans(event);
Blockly.Events.disableOrphans(event); }
} });
});
}
Blockly.svgResize(workspace); Blockly.svgResize(workspace);
const zoomToFit = new ZoomToFitControl(workspace); const zoomToFit = new ZoomToFitControl(workspace);
zoomToFit.init(); zoomToFit.init();
@@ -39,23 +37,21 @@ class BlocklyWindow extends Component {
componentDidUpdate(props) { componentDidUpdate(props) {
const workspace = Blockly.getMainWorkspace(); const workspace = Blockly.getMainWorkspace();
if (!this.props.readOnly) { 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 workspace.clear();
workspace.clear(); if (!xml) xml = initialXml;
if (!xml) xml = initialXml; Blockly.Xml.domToWorkspace(Blockly.Xml.textToDom(xml), workspace);
Blockly.Xml.domToWorkspace(Blockly.Xml.textToDom(xml), workspace); }
} if (props.language !== this.props.language) {
if (props.language !== this.props.language) { // change language
// change language if (!xml) xml = initialXml;
if (!xml) xml = initialXml; var xmlDom = Blockly.Xml.textToDom(xml);
var xmlDom = Blockly.Xml.textToDom(xml); Blockly.Xml.clearWorkspaceAndLoadFromXml(xmlDom, workspace);
Blockly.Xml.clearWorkspaceAndLoadFromXml(xmlDom, workspace); // var toolbox = workspace.getToolbox();
// var toolbox = workspace.getToolbox(); // workspace.updateToolbox(toolbox.toolboxDef_);
// workspace.updateToolbox(toolbox.toolboxDef_);
}
} }
Blockly.svgResize(workspace); Blockly.svgResize(workspace);
} }
+127 -103
View File
@@ -1,98 +1,124 @@
import React, { Component } from 'react'; import React, { Component } from "react";
import Breadcrumbs from './Breadcrumbs'; import Breadcrumbs from "./Breadcrumbs";
import { withRouter } from 'react-router-dom'; import { withRouter } from "react-router-dom";
import Button from '@material-ui/core/Button'; import Button from "@material-ui/core/Button";
import Typography from '@material-ui/core/Typography'; import Typography from "@material-ui/core/Typography";
import * as Blockly from 'blockly' import * as Blockly from "blockly";
import ReactMarkdown from 'react-markdown'; import ReactMarkdown from "react-markdown";
import Container from '@material-ui/core/Container'; import Container from "@material-ui/core/Container";
import ExpansionPanel from '@material-ui/core/ExpansionPanel'; import ExpansionPanel from "@material-ui/core/ExpansionPanel";
import ExpansionPanelSummary from '@material-ui/core/ExpansionPanelSummary'; import ExpansionPanelSummary from "@material-ui/core/ExpansionPanelSummary";
import ExpansionPanelDetails from '@material-ui/core/ExpansionPanelDetails'; import ExpansionPanelDetails from "@material-ui/core/ExpansionPanelDetails";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faChevronDown } from "@fortawesome/free-solid-svg-icons"; import { faChevronDown } from "@fortawesome/free-solid-svg-icons";
import { FaqQuestions } from '../data/faq' import { FaqQuestions } from "../data/faq";
import Editor from "rich-markdown-editor";
class Faq extends Component { class Faq extends Component {
state = {
panel: "",
expanded: false,
text: "",
};
state = { handleChange = (panel) => {
panel: '', this.setState({ panel: this.state.panel === panel ? "" : panel });
expanded: false };
}
componentDidMount() {
// Ensure that Blockly.setLocale is adopted in the component.
// Otherwise, the text will not be displayed until the next update of the component.
handleChange = (panel) => { window.scrollTo(0, 0);
this.setState({ panel: this.state.panel === panel ? '' : panel }); this.forceUpdate();
}; }
componentDidMount() { render() {
// Ensure that Blockly.setLocale is adopted in the component. const { panel } = this.state;
// Otherwise, the text will not be displayed until the next update of the component. return (
<div>
window.scrollTo(0, 0) <Breadcrumbs
this.forceUpdate(); content={[{ link: this.props.location.pathname, title: "FAQ" }]}
} />
<Container fixed>
render() { <div style={{ margin: "0px 24px 0px 24px" }}>
const { panel } = this.state; <h1>FAQ</h1>
return ( {FaqQuestions().map((object, i) => {
<div> return (
<Breadcrumbs content={[{ link: this.props.location.pathname, title: 'FAQ' }]} /> <ExpansionPanel
<Container fixed> expanded={panel === `panel${i}`}
<div style={{ margin: '0px 24px 0px 24px' }}> onChange={() => this.handleChange(`panel${i}`)}
<h1>FAQ</h1> >
{FaqQuestions().map((object, i) => { <ExpansionPanelSummary
return ( expandIcon={<FontAwesomeIcon icon={faChevronDown} />}
<ExpansionPanel expanded={panel === `panel${i}`} onChange={() => this.handleChange(`panel${i}`)}> >
<ExpansionPanelSummary <Typography variant="h6">{object.question}</Typography>
expandIcon={ </ExpansionPanelSummary>
<FontAwesomeIcon icon={faChevronDown} /> <ExpansionPanelDetails>
} <Typography>
> <ReactMarkdown
<Typography variant="h6">{object.question}</Typography> className="news"
</ExpansionPanelSummary> allowDangerousHtml="true"
<ExpansionPanelDetails> children={object.answer}
<Typography> ></ReactMarkdown>
<ReactMarkdown className="news" allowDangerousHtml="true" children={object.answer}> </Typography>
</ReactMarkdown> </ExpansionPanelDetails>
</Typography> </ExpansionPanel>
</ExpansionPanelDetails> );
</ExpansionPanel> })}
) {this.props.button ? (
})} <Button
{ style={{ marginTop: "20px" }}
this.props.button ? variant="contained"
<Button color="primary"
style={{ marginTop: '20px' }} onClick={() => {
variant="contained" this.props.history.push(this.props.button.link);
color="primary" }}
onClick={() => { this.props.history.push(this.props.button.link) }} >
> {this.props.button.title}
{this.props.button.title} </Button>
</Button> ) : (
: <Button
<Button style={{ marginTop: "20px" }}
style={{ marginTop: '20px' }} variant="contained"
variant="contained" color="primary"
color="primary" onClick={() => {
onClick={() => { this.props.history.push('/') }} this.props.history.push("/");
> }}
{Blockly.Msg.button_back} >
</Button> {Blockly.Msg.button_back}
} </Button>
</div> )}
</Container> <Editor
</div > defaultValue="Hello world!"
); // value={this.state.text}
}; onChange={(e) => {
this.setState({ text: e() });
}}
uploadImage={async (file) => {}}
/>
<Button
style={{ marginTop: "20px" }}
variant="contained"
color="primary"
onClick={() => {
console.log(this.state.text);
}}
>
{Blockly.Msg.button_back}
</Button>
</div>
</Container>
</div>
);
}
} }
export default withRouter(Faq); export default withRouter(Faq);
/* /*
<ExpansionPanel expanded={panel === 'panel1'} onChange={() => this.handleChange('panel1')}> <ExpansionPanel expanded={panel === 'panel1'} onChange={() => this.handleChange('panel1')}>
<ExpansionPanelSummary <ExpansionPanelSummary
expandIcon={ expandIcon={
@@ -155,25 +181,23 @@ vitae egestas augue. Duis vel est augue.
</ExpansionPanel> </ExpansionPanel>
*/ */
// {{ // {{
// this.props.button ? // this.props.button ?
// <Button // <Button
// style={{ marginTop: '20px' }} // style={{ marginTop: '20px' }}
// variant="contained" // variant="contained"
// color="primary" // color="primary"
// onClick={() => { this.props.history.push(this.props.button.link) }} // onClick={() => { this.props.history.push(this.props.button.link) }}
// > // >
// {this.props.button.title} // {this.props.button.title}
// </Button> // </Button>
// : // :
// <Button // <Button
// style={{ marginTop: '20px' }} // style={{ marginTop: '20px' }}
// variant="contained" // variant="contained"
// color="primary" // color="primary"
// onClick={() => { this.props.history.push('/') }} // onClick={() => { this.props.history.push('/') }}
// > // >
// {Blockly.Msg.button_back} // {Blockly.Msg.button_back}
// </Button> // </Button>
// }} // }}
+6 -14
View File
@@ -77,7 +77,7 @@ class Home extends Component {
componentWillUnmount() { componentWillUnmount() {
this.props.clearStats(); this.props.clearStats();
// this.props.workspaceName(null); this.props.workspaceName(null);
} }
onChange = () => { onChange = () => {
@@ -112,17 +112,10 @@ class Home extends Component {
</Tooltip> </Tooltip>
<TrashcanButtons /> <TrashcanButtons />
<div className='blocklyWindow'> <div className='blocklyWindow'>
{this.props.project ? ( {this.props.project ?
<BlocklyWindow < BlocklyWindow blocklyCSS={{ height: '80vH' }} initialXml={this.props.project.xml} />
blocklyCSS={{ height: "80vH" }} : < BlocklyWindow blocklyCSS={{ height: '80vH' }} />
initialXml={this.props.project.xml} }
/>
) : (
<BlocklyWindow
blocklyCSS={{ height: "80vH" }}
initialXml={this.props.workspaceCode?.xml}
/>
)}
</div> </div>
</Grid> </Grid>
{this.state.codeOn ? {this.state.codeOn ?
@@ -153,8 +146,7 @@ Home.propTypes = {
const mapStateToProps = state => ({ const mapStateToProps = state => ({
message: state.message, message: state.message,
statistics: state.general.statistics, statistics: state.general.statistics
workspaceCode: state.workspace.code
}); });
+5 -67
View File
@@ -18,11 +18,6 @@ import Divider from "@material-ui/core/Divider";
import Typography from "@material-ui/core/Typography"; import Typography from "@material-ui/core/Typography";
import Backdrop from "@material-ui/core/Backdrop"; import Backdrop from "@material-ui/core/Backdrop";
import CircularProgress from "@material-ui/core/CircularProgress"; import CircularProgress from "@material-ui/core/CircularProgress";
import Dialog from "../Dialog";
import Button from "@material-ui/core/Button";
import { initialXml } from "../Blockly/initialXml";
import {diffAsXml} from 'diff-js-xml';
const styles = (theme) => ({ const styles = (theme) => ({
link: { link: {
@@ -41,7 +36,6 @@ class ProjectHome extends Component {
type: "", type: "",
key: "", key: "",
message: "", message: "",
dialog: false,
}; };
componentDidMount() { componentDidMount() {
@@ -132,43 +126,10 @@ class ProjectHome extends Component {
overflow: "hidden", overflow: "hidden",
}} }}
> >
<div <Link
onClick={async () => { to={`/${
const isCodeDifferent = new Promise((resolve) => { data === "Projekte" ? "project" : "gallery"
// resolve successfully when there is no existing workspace XML code }/${project._id}`}
if(!this.props.workspaceCode.xml) {
resolve(false)
return
}
// get difference of XML
// TODO: check if code of project is different to workspace code
diffAsXml(
this.props.workspaceCode.xml,
initialXml,
undefined,
undefined,
(result) => {
resolve(result.length !== 0);
}
)
}
);
const showDialog = await isCodeDifferent;
if (showDialog)
this.setState({
dialog: true,
});
else {
this.props.history.push(
`/${
data === "Projekte" ? "project" : "gallery"
}/${project._id}`
);
}
}}
style={{ textDecoration: "none", color: "inherit" }} style={{ textDecoration: "none", color: "inherit" }}
> >
<h3 style={{ marginTop: 0 }}>{project.title}</h3> <h3 style={{ marginTop: 0 }}>{project.title}</h3>
@@ -178,7 +139,6 @@ class ProjectHome extends Component {
<BlocklyWindow <BlocklyWindow
svg svg
blockDisabled blockDisabled
readOnly
initialXml={project.xml} initialXml={project.xml}
/> />
<Typography <Typography
@@ -191,7 +151,7 @@ class ProjectHome extends Component {
> >
{project.description} {project.description}
</Typography> </Typography>
</div> </Link>
{this.props.user && {this.props.user &&
this.props.user.email === project.creator ? ( this.props.user.email === project.creator ? (
<div> <div>
@@ -246,27 +206,6 @@ class ProjectHome extends Component {
type={this.state.type} type={this.state.type}
key={this.state.key} key={this.state.key}
/> />
<Dialog
open={this.state.dialog}
title="Achtung"
actions={
<React.Fragment>
<Button
onClick={() => {
this.setState({ dialog: false });
// TODO: navigate to project
}}
>
Verwerfen
</Button>
<Button onClick={() => {}} color="primary">
Speichern
</Button>
</React.Fragment>
}
>
Möchtest du deinen bisherigen Code als Projekt speichern?
</Dialog>
</div> </div>
); );
} }
@@ -287,7 +226,6 @@ const mapStateToProps = (state) => ({
progress: state.project.progress, progress: state.project.progress,
user: state.auth.user, user: state.auth.user,
message: state.message, message: state.message,
workspaceCode: state.workspace.code,
}); });
export default connect(mapStateToProps, { export default connect(mapStateToProps, {
+9917 -9227
View File
File diff suppressed because it is too large Load Diff