init senseBox connect features

This commit is contained in:
Mario Pesch 2021-10-01 15:06:22 +02:00
parent e528a78e77
commit faabd9e693
5 changed files with 237 additions and 102 deletions

View File

@ -1,32 +1,38 @@
import { VISIT, LANGUAGE, RENDERER, STATISTICS } from './types'; import { VISIT, LANGUAGE, RENDERER, STATISTICS, PLATFORM } from "./types";
export const visitPage = () => (dispatch) => { export const visitPage = () => (dispatch) => {
dispatch({ dispatch({
type: VISIT type: VISIT,
});
};
export const setPlatform = (platform) => (dispatch) => {
dispatch({
type: PLATFORM,
payload: platform,
}); });
}; };
export const setLanguage = (language) => (dispatch, getState) => { export const setLanguage = (language) => (dispatch, getState) => {
if(!getState().auth.progress && !getState().auth.isAuthenticated){ if (!getState().auth.progress && !getState().auth.isAuthenticated) {
window.localStorage.setItem('locale', language); window.localStorage.setItem("locale", language);
} }
dispatch({ dispatch({
type: LANGUAGE, type: LANGUAGE,
payload: language payload: language,
}); });
}; };
export const setRenderer = (renderer) => (dispatch) => { export const setRenderer = (renderer) => (dispatch) => {
dispatch({ dispatch({
type: RENDERER, type: RENDERER,
payload: renderer payload: renderer,
}); });
}; };
export const setStatistics = (showStatistics) => (dispatch) => { export const setStatistics = (showStatistics) => (dispatch) => {
dispatch({ dispatch({
type: STATISTICS, type: STATISTICS,
payload: showStatistics payload: showStatistics,
}); });
}; };

View File

@ -43,6 +43,7 @@ export const PROGRESS = "PROGRESS";
export const VISIT = "VISIT"; export const VISIT = "VISIT";
export const LANGUAGE = "LANGUAGE"; export const LANGUAGE = "LANGUAGE";
export const PLATFORM = "PLATFORM";
export const RENDERER = "RENDERER"; export const RENDERER = "RENDERER";
export const STATISTICS = "STATISTICS"; export const STATISTICS = "STATISTICS";

View File

@ -1,68 +1,72 @@
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 { clearStats, workspaceName } from '../actions/workspaceActions'; import { clearStats, workspaceName } from "../actions/workspaceActions";
import * as Blockly from 'blockly/core'; import * as Blockly from "blockly/core";
import { createNameId } from 'mnemonic-id'; import { createNameId } from "mnemonic-id";
import WorkspaceStats from './Workspace/WorkspaceStats'; import WorkspaceStats from "./Workspace/WorkspaceStats";
import WorkspaceFunc from './Workspace/WorkspaceFunc'; import WorkspaceFunc from "./Workspace/WorkspaceFunc";
import BlocklyWindow from './Blockly/BlocklyWindow'; import BlocklyWindow from "./Blockly/BlocklyWindow";
import CodeViewer from './CodeViewer'; import CodeViewer from "./CodeViewer";
import TrashcanButtons from './Workspace/TrashcanButtons'; import TrashcanButtons from "./Workspace/TrashcanButtons";
import HintTutorialExists from './Tutorial/HintTutorialExists'; import HintTutorialExists from "./Tutorial/HintTutorialExists";
import Snackbar from './Snackbar';
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";
import Tooltip from '@material-ui/core/Tooltip'; import Tooltip from "@material-ui/core/Tooltip";
import { withStyles } from '@material-ui/core/styles'; 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 TooltipViewer from './TooltipViewer'; import TooltipViewer from "./TooltipViewer";
import Dialog from "./Dialog";
const styles = (theme) => ({ const styles = (theme) => ({
codeOn: { codeOn: {
backgroundColor: theme.palette.primary.main, backgroundColor: theme.palette.primary.main,
color: theme.palette.primary.contrastText, color: theme.palette.primary.contrastText,
'&:hover': { "&:hover": {
backgroundColor: theme.palette.primary.contrastText, backgroundColor: theme.palette.primary.contrastText,
color: theme.palette.primary.main, color: theme.palette.primary.main,
border: `1px solid ${theme.palette.secondary.main}` border: `1px solid ${theme.palette.secondary.main}`,
} },
}, },
codeOff: { codeOff: {
backgroundColor: theme.palette.primary.contrastText, backgroundColor: theme.palette.primary.contrastText,
color: theme.palette.primary.main, color: theme.palette.primary.main,
border: `1px solid ${theme.palette.secondary.main}`, border: `1px solid ${theme.palette.secondary.main}`,
'&:hover': { "&:hover": {
backgroundColor: theme.palette.primary.main, backgroundColor: theme.palette.primary.main,
color: theme.palette.primary.contrastText, color: theme.palette.primary.contrastText,
} },
} },
}); });
class Home extends Component { class Home extends Component {
state = { state = {
codeOn: true, codeOn: true,
snackbar: false, snackbar: false,
type: '', type: "",
key: '', key: "",
message: '' message: "",
} open: true,
};
componentDidMount() { componentDidMount() {
this.setState({ stats: window.localStorage.getItem('stats') }); console.log(this.props.platform);
this.setState({ stats: window.localStorage.getItem("stats") });
if (!this.props.project) { if (!this.props.project) {
this.props.workspaceName(createNameId()); this.props.workspaceName(createNameId());
} }
if (this.props.message && this.props.message.id === 'GET_SHARE_FAIL') { if (this.props.message && this.props.message.id === "GET_SHARE_FAIL") {
this.setState({ snackbar: true, key: Date.now(), message: `Das angefragte geteilte Projekt konnte nicht gefunden werden.`, type: 'error' }); this.setState({
snackbar: true,
key: Date.now(),
message: `Das angefragte geteilte Projekt konnte nicht gefunden werden.`,
type: "error",
});
} }
} }
@ -80,6 +84,10 @@ class Home extends Component {
this.props.workspaceName(null); this.props.workspaceName(null);
} }
toggleDialog = () => {
this.setState({ open: !this.state });
};
onChange = () => { onChange = () => {
this.setState({ codeOn: !this.state.codeOn }); this.setState({ codeOn: !this.state.codeOn });
const workspace = Blockly.getMainWorkspace(); const workspace = Blockly.getMainWorkspace();
@ -87,67 +95,113 @@ class Home extends Component {
if (workspace.trashcan && workspace.trashcan.flyout) { if (workspace.trashcan && workspace.trashcan.flyout) {
workspace.trashcan.flyout.hide(); // in case of resize, the trash flyout does not reposition workspace.trashcan.flyout.hide(); // in case of resize, the trash flyout does not reposition
} }
} };
render() { render() {
return ( return (
<div> <div>
{this.props.statistics ? {this.props.statistics ? (
<div style={{ float: 'left', height: '40px', position: 'relative' }}><WorkspaceStats /></div> <div style={{ float: "left", height: "40px", position: "relative" }}>
: null <WorkspaceStats />
} </div>
<div className='workspaceFunc' style={{ float: 'right', height: '40px', marginBottom: '20px' }}> ) : null}
<WorkspaceFunc project={this.props.project} projectType={this.props.projectType} /> <div
className="workspaceFunc"
style={{ float: "right", height: "40px", marginBottom: "20px" }}
>
<WorkspaceFunc
project={this.props.project}
projectType={this.props.projectType}
/>
</div> </div>
<Grid container spacing={2}> <Grid container spacing={2}>
<Grid item xs={12} md={this.state.codeOn ? 8 : 12} style={{ position: 'relative' }}> <Grid
<Tooltip title={this.state.codeOn ? 'Code ausblenden' : 'Code anzeigen'} > item
xs={12}
md={this.state.codeOn ? 8 : 12}
style={{ position: "relative" }}
>
<Tooltip
title={this.state.codeOn ? "Code ausblenden" : "Code anzeigen"}
>
<IconButton <IconButton
className={`showCode ${this.state.codeOn ? this.props.classes.codeOn : this.props.classes.codeOff}`} className={`showCode ${
style={{ width: '40px', height: '40px', position: 'absolute', top: -12, right: 8, zIndex: 21 }} this.state.codeOn
? this.props.classes.codeOn
: this.props.classes.codeOff
}`}
style={{
width: "40px",
height: "40px",
position: "absolute",
top: -12,
right: 8,
zIndex: 21,
}}
onClick={() => this.onChange()} onClick={() => this.onChange()}
> >
<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 ? (
< BlocklyWindow blocklyCSS={{ height: '80vH' }} initialXml={this.props.project.xml} /> <BlocklyWindow
: < BlocklyWindow blocklyCSS={{ height: '80vH' }} /> blocklyCSS={{ height: "80vH" }}
} initialXml={this.props.project.xml}
/>
) : (
<BlocklyWindow blocklyCSS={{ height: "80vH" }} />
)}
</div> </div>
</Grid> </Grid>
{this.state.codeOn ? {this.state.codeOn ? (
<Grid item xs={12} md={4}> <Grid item xs={12} md={4}>
<CodeViewer /> <CodeViewer />
<TooltipViewer /> <TooltipViewer />
</Grid> </Grid>
: null} ) : null}
</Grid> </Grid>
<HintTutorialExists /> <HintTutorialExists />
<Snackbar {this.props.platform ? (
open={this.state.snackbar} <Dialog
message={this.state.message} style={{ zIndex: 9999999 }}
type={this.state.type} fullWidth
key={this.state.key} maxWidth={"sm"}
/> open={this.state.open}
title=""
content={""}
onClose={this.toggleDialog}
onClick={this.toggleDialog}
button={Blockly.Msg.button_close}
>
<div>Du verwendest: {this.props.platform}</div>
<div>Lade die App hier herunter: </div>
<div>
Testlink:{" "}
<a href="blocklyconnect-app://sketch/123456">Öffne App</a>
</div>
</Dialog>
) : null}
</div> </div>
); );
}; }
} }
Home.propTypes = { Home.propTypes = {
clearStats: PropTypes.func.isRequired, clearStats: PropTypes.func.isRequired,
workspaceName: PropTypes.func.isRequired, workspaceName: PropTypes.func.isRequired,
message: PropTypes.object.isRequired, message: PropTypes.object.isRequired,
statistics: PropTypes.bool.isRequired statistics: PropTypes.bool.isRequired,
platform: PropTypes.object.isRequired,
}; };
const mapStateToProps = state => ({ const mapStateToProps = (state) => ({
message: state.message, message: state.message,
statistics: state.general.statistics statistics: state.general.statistics,
platform: state.general.platform,
}); });
export default connect(mapStateToProps, { clearStats, workspaceName })(
export default connect(mapStateToProps, { clearStats, workspaceName })(withStyles(styles, { withTheme: true })(Home)); withStyles(styles, { withTheme: true })(Home)
);

View File

@ -21,6 +21,7 @@ import "prismjs/themes/prism.css";
import "prismjs/plugins/line-numbers/prism-line-numbers"; import "prismjs/plugins/line-numbers/prism-line-numbers";
import "prismjs/plugins/line-numbers/prism-line-numbers.css"; import "prismjs/plugins/line-numbers/prism-line-numbers.css";
import MuiDrawer from "@material-ui/core/Drawer"; import MuiDrawer from "@material-ui/core/Drawer";
import Dialog from "../Dialog";
const styles = (theme) => ({ const styles = (theme) => ({
backdrop: { backdrop: {
@ -65,6 +66,8 @@ class Compile extends Component {
content: "", content: "",
name: props.name, name: props.name,
error: "", error: "",
appLink: "",
appDialog: false,
}; };
} }
@ -126,10 +129,16 @@ class Compile extends Component {
}; };
toggleDialog = () => { toggleDialog = () => {
this.setState({ open: !this.state, progress: false }); this.setState({ open: !this.state, progress: false, appDialog: false });
}; };
createFileName = () => { createFileName = () => {
if (this.props.platform === "iOS") {
this.setState({
link: `blocklyconnect-app://${this.state.name}/${this.state.id}`,
});
this.setState({ appDialog: true });
} else {
if (this.state.name) { if (this.state.name) {
this.download(); this.download();
} else { } else {
@ -141,6 +150,19 @@ class Compile extends Component {
"Bitte gib einen Namen für die Bennenung des zu kompilierenden Programms ein und bestätige diesen mit einem Klick auf 'Eingabe'.", "Bitte gib einen Namen für die Bennenung des zu kompilierenden Programms ein und bestätige diesen mit einem Klick auf 'Eingabe'.",
}); });
} }
}
// if (this.state.name) {
// this.download();
// } else {
// 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'.",
// });
// }
}; };
setFileName = (e) => { setFileName = (e) => {
@ -240,6 +262,24 @@ class Compile extends Component {
{`${this.state.error}`}{" "} {`${this.state.error}`}{" "}
</p> </p>
</Drawer> </Drawer>
<Dialog
style={{ zIndex: 9999999 }}
fullWidth
maxWidth={"sm"}
open={this.state.appDialog}
title=""
content={""}
onClose={this.toggleDialog}
onClick={this.toggleDialog}
button={Blockly.Msg.button_close}
>
<div>Du verwendest: {this.props.platform}</div>
<div>Lade die App hier herunter: </div>
<div>
Testlink: <a href={this.state.link}>Öffne App</a>
</div>
</Dialog>
{/* <Dialog {/* <Dialog
open={this.state.open} open={this.state.open}
title={this.state.title} title={this.state.title}
@ -272,11 +312,13 @@ Compile.propTypes = {
arduino: PropTypes.string.isRequired, arduino: PropTypes.string.isRequired,
name: PropTypes.string, name: PropTypes.string,
workspaceName: PropTypes.func.isRequired, workspaceName: PropTypes.func.isRequired,
platform: PropTypes.object.isRequired,
}; };
const mapStateToProps = (state) => ({ const mapStateToProps = (state) => ({
arduino: state.workspace.code.arduino, arduino: state.workspace.code.arduino,
name: state.workspace.name, name: state.workspace.name,
platform: state.general.platform,
}); });
export default connect(mapStateToProps, { workspaceName })( export default connect(mapStateToProps, { workspaceName })(

View File

@ -1,60 +1,92 @@
import { VISIT, LANGUAGE, RENDERER, STATISTICS } from '../actions/types'; import {
VISIT,
LANGUAGE,
RENDERER,
STATISTICS,
PLATFORM,
} from "../actions/types";
const initialLanguage = () => { const initialLanguage = () => {
if (window.localStorage.getItem('locale')) { if (window.localStorage.getItem("locale")) {
return window.localStorage.getItem('locale'); return window.localStorage.getItem("locale");
} }
if (navigator.language === 'de-DE'){ if (navigator.language === "de-DE") {
return 'de_DE'; return "de_DE";
} }
return 'en_US'; return "en_US";
};
const getPlatform = () => {
var userAgent = window.navigator.userAgent,
platform = window.navigator.platform,
macosPlatforms = ["Macintosh", "MacIntel", "MacPPC", "Mac68K"],
windowsPlatforms = ["Win32", "Win64", "Windows", "WinCE"],
iosPlatforms = ["iPhone", "iPad", "iPod"],
os = null;
if (macosPlatforms.indexOf(platform) !== -1) {
os = "Mac OS";
} else if (iosPlatforms.indexOf(platform) !== -1) {
os = "iOS";
} else if (windowsPlatforms.indexOf(userAgent) !== -1) {
os = "Windows";
} else if (/Android/.test(userAgent)) {
os = "Android";
} else if (!os && /Linux/.test(platform)) {
os = "Linux";
}
return os;
}; };
const initialRenderer = () => { const initialRenderer = () => {
if (window.localStorage.getItem('renderer')) { if (window.localStorage.getItem("renderer")) {
return window.localStorage.getItem('renderer'); return window.localStorage.getItem("renderer");
} }
return 'geras'; return "geras";
}; };
const initialStatistics = () => { const initialStatistics = () => {
if (window.localStorage.getItem('statistics')) { if (window.localStorage.getItem("statistics")) {
return JSON.parse(window.localStorage.getItem('statistics')); return JSON.parse(window.localStorage.getItem("statistics"));
} }
return false; return false;
}; };
const initialState = { const initialState = {
pageVisits: 0, // detect if previous URL was pageVisits: 0, // detect if previous URL was
language: initialLanguage(), language: initialLanguage(),
renderer: initialRenderer(), renderer: initialRenderer(),
statistics: initialStatistics() statistics: initialStatistics(),
platform: getPlatform(),
}; };
export default function foo(state = initialState, action){ export default function foo(state = initialState, action) {
switch(action.type){ switch (action.type) {
case VISIT: case VISIT:
return { return {
...state, ...state,
pageVisits: state.pageVisits += 1 pageVisits: (state.pageVisits += 1),
}; };
case LANGUAGE: case LANGUAGE:
return { return {
...state, ...state,
language: action.payload language: action.payload,
};
case PLATFORM:
return {
...state,
platform: action.payload,
}; };
case RENDERER: case RENDERER:
window.localStorage.setItem('renderer', action.payload); window.localStorage.setItem("renderer", action.payload);
return { return {
...state, ...state,
renderer: action.payload renderer: action.payload,
}; };
case STATISTICS: case STATISTICS:
window.localStorage.setItem('statistics', action.payload); window.localStorage.setItem("statistics", action.payload);
return { return {
...state, ...state,
statistics: action.payload statistics: action.payload,
}; };
default: default:
return state; return state;