auto Save Blocks

This commit is contained in:
Mario Pesch 2022-01-14 08:12:20 +01:00
parent f388828c88
commit 748c29c260
4 changed files with 228 additions and 68 deletions

View File

@ -1,22 +1,93 @@
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faCircleNotch, faSave, faSpinner } from "@fortawesome/free-solid-svg-icons"; import { useSelector } from "react-redux";
import {
faCircleNotch,
faSave,
faSpinner,
} from "@fortawesome/free-solid-svg-icons";
import Tooltip from "@material-ui/core/Tooltip"; import Tooltip from "@material-ui/core/Tooltip";
import { IconButton } from "@material-ui/core";
import PropTypes from "prop-types";
import React from "react";
const SaveIcon = ({ loading }) => ( const SaveIcon = ({ loading }) => {
<Tooltip const value = useSelector((state) => state.general.autoSave);
title={"Auto save enabled"}
arrow return (
placement="right" <div>
> {value === true ? (
<div style={{ position: 'relative', width: "2rem", height: "2rem", margin: "1rem" }}> <Tooltip title={"Auto save enabled"} arrow placement="right">
{loading && <FontAwesomeIcon style={{ position: "absolute" }} icon={faCircleNotch} spin={true} size="2x" color="grey" />} <IconButton
<FontAwesomeIcon style={{ style={{
width: "40px",
height: "40px",
position: "absolute",
}}
>
{loading && (
<FontAwesomeIcon
style={{ position: "absolute" }}
icon={faCircleNotch}
spin={true}
size="2x"
color="#4EAF47"
/>
)}
<FontAwesomeIcon
style={{
position: "absolute", position: "absolute",
left: "50%", left: "50%",
top: "50%", top: "50%",
transform: "translate(-50%,-50%)", transform: "translate(-50%,-50%)",
}} icon={faSave} color={loading ? 'grey' : 'green'} size={loading ? "1x" : "lg"} /> }}
</div> icon={faSave}
</Tooltip>) color={loading ? "gray" : "#4EAF47"}
size={loading ? "1x" : "md"}
/>
</IconButton>
</Tooltip>
) : (
<Tooltip title={"Auto save disabled"} arrow placement="right">
<IconButton
style={{
width: "40px",
height: "40px",
position: "absolute",
}}
onClick={() => {
this.propTypes.setAutoSave(true);
}}
>
{loading && (
<FontAwesomeIcon
style={{ position: "absolute" }}
icon={faCircleNotch}
spin={true}
size="2x"
color="#4EAF47"
/>
)}
<FontAwesomeIcon
style={{
position: "absolute",
left: "50%",
top: "50%",
transform: "translate(-50%,-50%)",
}}
icon={faSave}
color={loading ? "gray" : "#4EAF47"}
size={loading ? "1x" : "md"}
/>
</IconButton>
</Tooltip>
)}
</div>
);
};
export default SaveIcon SaveIcon.propTypes = {
setAutoSave: PropTypes.func.isRequired,
autoSave: PropTypes.bool.isRequired,
};
export default SaveIcon;

View File

@ -22,6 +22,7 @@ import { faCode } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import TooltipViewer from "./TooltipViewer"; import TooltipViewer from "./TooltipViewer";
import Dialog from "./Dialog"; import Dialog from "./Dialog";
import AutoSave from "./Workspace/AutoSave";
const styles = (theme) => ({ const styles = (theme) => ({
codeOn: { codeOn: {
@ -54,6 +55,7 @@ class Home extends Component {
key: "", key: "",
message: "", message: "",
open: true, open: true,
initialXml: sessionStorage.getItem("autoSaveXML"),
}; };
} }
@ -114,11 +116,13 @@ class Home extends Component {
render() { render() {
return ( return (
<div> <div>
<AutoSave />
{this.props.statistics ? ( {this.props.statistics ? (
<div style={{ float: "left", height: "40px", position: "relative" }}> <div style={{ float: "left", height: "40px", position: "relative" }}>
<WorkspaceStats /> <WorkspaceStats />
</div> </div>
) : null} ) : null}
<div <div
className="workspaceFunc" className="workspaceFunc"
style={{ float: "right", height: "40px", marginBottom: "20px" }} style={{ float: "right", height: "40px", marginBottom: "20px" }}
@ -161,6 +165,7 @@ class Home extends Component {
<FontAwesomeIcon icon={faCode} size="xs" /> <FontAwesomeIcon icon={faCode} size="xs" />
</IconButton> </IconButton>
</Tooltip> </Tooltip>
<TrashcanButtons /> <TrashcanButtons />
<div className="blocklyWindow"> <div className="blocklyWindow">
{this.props.project ? ( {this.props.project ? (
@ -169,7 +174,10 @@ class Home extends Component {
initialXml={this.props.project.xml} initialXml={this.props.project.xml}
/> />
) : ( ) : (
<BlocklyWindow blocklyCSS={{ height: "80vH" }} /> <BlocklyWindow
blocklyCSS={{ height: "80vH" }}
initialXml={this.state.initialXml}
/>
)} )}
</div> </div>
</Grid> </Grid>

View File

@ -0,0 +1,72 @@
import React, { Component } from "react";
import PropTypes from "prop-types";
import { connect } from "react-redux";
import { workspaceName } from "../../actions/workspaceActions";
import SaveIcon from "../CodeEditor/SaveIcon";
const resetTimeout = (id, newID) => {
clearTimeout(id);
return newID;
};
class AutoSave extends Component {
constructor(props) {
super(props);
this.state = {
timeout: null,
value: "",
saved: false,
autosave: false,
};
}
editValue = (value) => {
this.setState({
timeout: resetTimeout(
this.state.timeout,
setTimeout(this.saveValue, 400)
),
value: value,
});
};
saveValue = () => {
this.setState({ ...this.state, saved: true });
sessionStorage.setItem("autoSaveXML", this.props.xml);
setTimeout(() => this.setState({ ...this.state, saved: false }), 1000);
};
componentDidMount() {
console.log(this.props.xml);
}
componentDidUpdate(prevProps) {
if (prevProps.xml !== this.props.xml) {
this.editValue(this.props.xml);
}
}
render() {
return (
<div>
<SaveIcon loading={this.state.saved} autosave={this.props.autosave} />
</div>
);
}
}
AutoSave.propTypes = {
xml: PropTypes.string.isRequired,
name: PropTypes.string,
workspaceName: PropTypes.func.isRequired,
setAutosave: PropTypes.func.isRequired,
autosave: PropTypes.bool.isRequired,
};
const mapStateToProps = (state) => ({
auto: state.general.autosave,
xml: state.workspace.code.xml,
name: state.workspace.name,
});
export default connect(mapStateToProps, { workspaceName })(AutoSave);

View File

@ -1,101 +1,110 @@
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 WorkspaceName from './WorkspaceName'; import WorkspaceName from "./WorkspaceName";
import SaveProject from './SaveProject'; import SaveProject from "./SaveProject";
import Compile from './Compile'; import Compile from "./Compile";
import SolutionCheck from '../Tutorial/SolutionCheck'; import SolutionCheck from "../Tutorial/SolutionCheck";
import DownloadProject from './DownloadProject'; import DownloadProject from "./DownloadProject";
import OpenProject from './OpenProject'; import OpenProject from "./OpenProject";
import Screenshot from './Screenshot'; import Screenshot from "./Screenshot";
import ShareProject from './ShareProject'; import ShareProject from "./ShareProject";
import ResetWorkspace from './ResetWorkspace'; import ResetWorkspace from "./ResetWorkspace";
import DeleteProject from './DeleteProject'; import DeleteProject from "./DeleteProject";
import CopyCode from './CopyCode'; import CopyCode from "./CopyCode";
class WorkspaceFunc extends Component { class WorkspaceFunc extends Component {
componentDidUpdate() {
console.log(this.props.autosave);
}
render() { render() {
return ( return (
<div style={{ width: 'max-content', display: 'flex' }}> <div style={{ width: "max-content", display: "flex" }}>
{!this.props.assessment ? (
{!this.props.assessment ?
<WorkspaceName <WorkspaceName
style={{ marginRight: '5px' }} style={{ marginRight: "5px" }}
multiple={this.props.multiple} multiple={this.props.multiple}
project={this.props.project} project={this.props.project}
projectType={this.props.projectType} projectType={this.props.projectType}
/> />
: null} ) : null}
{this.props.assessment ? {this.props.assessment ? (
<SolutionCheck /> <SolutionCheck />
: !this.props.multiple ? ) : !this.props.multiple ? (
<Compile iconButton /> <Compile iconButton />
: null} ) : null}
{!this.props.multiple ? {!this.props.multiple ? <CopyCode iconButton /> : null}
<CopyCode iconButton />
: null}
{this.props.user && !this.props.multiple ? (
{this.props.user && !this.props.multiple ?
<SaveProject <SaveProject
style={{ marginRight: '5px' }} style={{ marginRight: "5px" }}
projectType={this.props.projectType} projectType={this.props.projectType}
project={this.props.project} project={this.props.project}
/> />
: null} ) : null}
{!this.props.multiple ? {!this.props.multiple ? (
<DownloadProject style={{ marginRight: '5px' }} /> <DownloadProject style={{ marginRight: "5px" }} />
: null} ) : null}
{!this.props.assessment && !this.props.multiple ? (
{!this.props.assessment && !this.props.multiple ?
<OpenProject <OpenProject
style={{ marginRight: '5px' }} style={{ marginRight: "5px" }}
assessment={this.props.assessment} assessment={this.props.assessment}
/> />
: null} ) : null}
{!this.props.assessment && !this.props.multiple ? {!this.props.assessment && !this.props.multiple ? (
<Screenshot style={{ marginRight: '5px' }} /> <Screenshot style={{ marginRight: "5px" }} />
: null} ) : null}
{this.props.projectType !== 'gallery' && !this.props.assessment ? {this.props.projectType !== "gallery" && !this.props.assessment ? (
<ShareProject <ShareProject
style={{ marginRight: '5px' }} style={{ marginRight: "5px" }}
multiple={this.props.multiple} multiple={this.props.multiple}
project={this.props.project} project={this.props.project}
projectType={this.props.projectType} projectType={this.props.projectType}
/> />
: null} ) : null}
{!this.props.multiple ? {!this.props.multiple ? (
<ResetWorkspace style={this.props.projectType === 'project' || this.props.projectType === 'gallery' ? { marginRight: '5px' } : null} <ResetWorkspace
style={
this.props.projectType === "project" ||
this.props.projectType === "gallery"
? { marginRight: "5px" }
: null
}
/> />
: null} ) : null}
{!this.props.assessment && (this.props.projectType === 'project' || this.props.projectType === 'gallery') && this.props.user && this.props.user.email === this.props.project.creator ? {!this.props.assessment &&
(this.props.projectType === "project" ||
this.props.projectType === "gallery") &&
this.props.user &&
this.props.user.email === this.props.project.creator ? (
<DeleteProject <DeleteProject
project={this.props.project} project={this.props.project}
projectType={this.props.projectType} projectType={this.props.projectType}
/> />
: null} ) : null}
</div> </div>
); );
}; }
} }
WorkspaceFunc.propTypes = { WorkspaceFunc.propTypes = {
user: PropTypes.object user: PropTypes.object,
autosave: PropTypes.bool.isRequired,
}; };
const mapStateToProps = state => ({ const mapStateToProps = (state) => ({
user: state.auth.user user: state.auth.user,
autosave: state.workspace.autosave,
}); });
export default connect(mapStateToProps, null)(WorkspaceFunc); export default connect(mapStateToProps, null)(WorkspaceFunc);