add generalReducer to store settings

This commit is contained in:
Delucse 2020-12-14 13:06:55 +01:00
parent 7d1d2409e4
commit e52e3943c1
14 changed files with 360 additions and 170 deletions

View File

@ -11,10 +11,7 @@ import './App.css';
import { ThemeProvider, createMuiTheme } from '@material-ui/core/styles'; import { ThemeProvider, createMuiTheme } from '@material-ui/core/styles';
import Navbar from './components/Navbar'; import Content from './components/Content';
import Footer from './components/Footer';
import Routes from './components/Route/Routes';
import Cookies from './components/Cookies';
const theme = createMuiTheme({ const theme = createMuiTheme({
palette: { palette: {
@ -43,12 +40,7 @@ class App extends Component {
<ThemeProvider theme={theme}> <ThemeProvider theme={theme}>
<Provider store={store}> <Provider store={store}>
<Router history={customHistory}> <Router history={customHistory}>
<div className="wrapper"> <Content />
<Navbar />
<Routes />
<Cookies />
<Footer />
</div>
</Router> </Router>
</Provider> </Provider>
</ThemeProvider> </ThemeProvider>

View File

@ -1,4 +1,4 @@
import { VISIT } from './types'; import { VISIT, LANGUAGE, RENDERER, STATISTICS } from './types';
export const visitPage = () => (dispatch) => { export const visitPage = () => (dispatch) => {
@ -6,3 +6,24 @@ export const visitPage = () => (dispatch) => {
type: VISIT type: VISIT
}); });
}; };
export const setLanguage = (language) => (dispatch) => {
dispatch({
type: LANGUAGE,
payload: language
});
};
export const setRenderer = (renderer) => (dispatch) => {
dispatch({
type: RENDERER,
payload: renderer
});
};
export const setStatistics = (showStatistics) => (dispatch) => {
dispatch({
type: STATISTICS,
payload: showStatistics
});
};

View File

@ -46,6 +46,9 @@ export const PROGRESS = 'PROGRESS';
export const VISIT = 'VISIT'; export const VISIT = 'VISIT';
export const LANGUAGE = 'LANGUAGE';
export const RENDERER = 'RENDERER';
export const STATISTICS = 'STATISTICS';
// messages // messages
export const GET_ERRORS = 'GET_ERRORS'; export const GET_ERRORS = 'GET_ERRORS';

View File

@ -18,26 +18,21 @@ class BlocklyWindow extends Component {
constructor(props) { constructor(props) {
super(props); super(props);
this.simpleWorkspace = React.createRef(); this.simpleWorkspace = React.createRef();
var locale = window.localStorage.getItem('locale'); // if (locale === null) {
this.state = { // if (navigator.language === 'de-DE') {
renderer: window.localStorage.getItem('renderer'), // locale = 'de';
}; // } else {
if (locale === null) { // locale = 'en';
if (navigator.language === 'de-DE') { // }
locale = 'de'; // }
} else { if (this.props.language === 'de') {
locale = 'en';
}
}
if (locale === 'de') {
Blockly.setLocale(De); Blockly.setLocale(De);
} else if (locale === 'en') { } else if (this.props.language === 'en') {
Blockly.setLocale(En); Blockly.setLocale(En);
} }
} }
componentDidMount() { componentDidMount() {
const workspace = Blockly.getMainWorkspace(); const workspace = Blockly.getMainWorkspace();
this.props.onChangeWorkspace({}); this.props.onChangeWorkspace({});
this.props.clearStats(); this.props.clearStats();
@ -72,7 +67,7 @@ class BlocklyWindow extends Component {
style={this.props.svg ? { height: 0 } : this.props.blocklyCSS} style={this.props.svg ? { height: 0 } : this.props.blocklyCSS}
readOnly={this.props.readOnly !== undefined ? this.props.readOnly : false} readOnly={this.props.readOnly !== undefined ? this.props.readOnly : false}
trashcan={this.props.trashcan !== undefined ? this.props.trashcan : true} trashcan={this.props.trashcan !== undefined ? this.props.trashcan : true}
renderer={this.state.renderer} renderer={this.props.renderer}
zoom={{ // https://developers.google.com/blockly/guides/configure/web/zoom zoom={{ // https://developers.google.com/blockly/guides/configure/web/zoom
controls: this.props.zoomControls !== undefined ? this.props.zoomControls : true, controls: this.props.zoomControls !== undefined ? this.props.zoomControls : true,
wheel: false, wheel: false,
@ -106,8 +101,14 @@ class BlocklyWindow extends Component {
BlocklyWindow.propTypes = { BlocklyWindow.propTypes = {
onChangeWorkspace: PropTypes.func.isRequired, onChangeWorkspace: PropTypes.func.isRequired,
clearStats: PropTypes.func.isRequired clearStats: PropTypes.func.isRequired,
renderer: PropTypes.string.isRequired,
language: PropTypes.string.isRequired
}; };
const mapStateToProps = state => ({
renderer: state.general.renderer,
language: state.general.language
});
export default connect(null, { onChangeWorkspace, clearStats })(BlocklyWindow); export default connect(mapStateToProps, { onChangeWorkspace, clearStats })(BlocklyWindow);

View File

@ -926,9 +926,15 @@ Blockly.Msg.projectname = "Projektname";
*/ */
Blockly.Msg.settings_head = "Einstellungen" Blockly.Msg.settings_head = "Einstellungen"
Blockly.Msg.settings_language = "Sprache" Blockly.Msg.settings_language = "Sprache"
Blockly.Msg.settings_language_text = "Auswahl der Sprache gilt für die gesamte Anwendung. Es kann zwischen Deutsch und Englisch unterschieden werden."
Blockly.Msg.settings_language_de = "Deutsch" Blockly.Msg.settings_language_de = "Deutsch"
Blockly.Msg.settings_language_en = "Englisch" Blockly.Msg.settings_language_en = "Englisch"
Blockly.Msg.settings_renderer_text = "Der Renderer bestimmt das aussehen der Blöcke" Blockly.Msg.settings_renderer = "Renderer"
Blockly.Msg.settings_renderer_text = "Der eingestellte Renderer bestimmt das Aussehen der Blöcke. Es kann zwischen 'Geras' und 'Zelos' unterschieden werden, wobei 'Zelos' insbesondere für eine Touch-Anwendung geeignet ist."
Blockly.Msg.settings_statistics = "Statistiken"
Blockly.Msg.settings_statistics_text = "Die Anzeige von Statistiken zur Nutzung der Blöcke oberhalb der Arbeitsfläche kann ein- oder ausgeblendet werden."
Blockly.Msg.settings_statistics_on = "An"
Blockly.Msg.settings_statistics_off = "Aus"
/** /**
* 404 * 404

View File

@ -861,6 +861,20 @@ Blockly.Msg.button_create_variableCreate = "Create Variable";
Blockly.Msg.filename = "Filename"; Blockly.Msg.filename = "Filename";
Blockly.Msg.projectname = "Projectname"; Blockly.Msg.projectname = "Projectname";
/**
* Settings
*/
Blockly.Msg.settings_head = "Settings"
Blockly.Msg.settings_language = "Language"
Blockly.Msg.settings_language_text = "Selection of the language applies to the entire application. A distinction can be made between German and English."
Blockly.Msg.settings_language_de = "German"
Blockly.Msg.settings_language_en = "English"
Blockly.Msg.settings_renderer = "Renderer"
Blockly.Msg.settings_renderer_text = "The selected renderer determines the appearance of the blocks. A distinction can be made between 'Geras' and 'Zelos', whereby 'Zelos' is particularly suitable for a touch application."
Blockly.Msg.settings_statistics = "Statistics"
Blockly.Msg.settings_statistics_text = "The display of statistics on the usage of the blocks above the workspace can be shown or hidden."
Blockly.Msg.settings_statistics_on = "On"
Blockly.Msg.settings_statistics_off = "Off"

54
src/components/Content.js Normal file
View File

@ -0,0 +1,54 @@
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import * as Blockly from 'blockly/core';
import { De } from './Blockly/msg/de';
import { En } from './Blockly/msg/en';
import Navbar from './Navbar';
import Footer from './Footer';
import Routes from './Route/Routes';
import Cookies from './Cookies';
class Content extends Component {
componentDidMount() {
if (this.props.language === 'de') {
Blockly.setLocale(De);
} else if (this.props.language === 'en') {
Blockly.setLocale(En);
}
}
componentDidUpdate(props){
if(props.language !== this.props.language){
if (this.props.language === 'de') {
Blockly.setLocale(De);
} else if (this.props.language === 'en') {
Blockly.setLocale(En);
}
}
}
render() {
return (
<div className="wrapper">
<Navbar />
<Routes />
<Cookies />
<Footer />
</div>
);
}
}
Content.propTypes = {
language: PropTypes.string.isRequired
};
const mapStateToProps = state => ({
language: state.general.language
});
export default connect(mapStateToProps, null)(Content);

View File

@ -48,7 +48,6 @@ class Home extends Component {
state = { state = {
codeOn: false, codeOn: false,
stats: window.localStorage.getItem('stats'),
snackbar: false, snackbar: false,
type: '', type: '',
key: '', key: '',
@ -91,7 +90,7 @@ class Home extends Component {
render() { render() {
return ( return (
<div> <div>
{this.state.stats ? {this.props.statistics ?
<div style={{ float: 'left', height: '40px', position: 'relative' }}><WorkspaceStats /></div> <div style={{ float: 'left', height: '40px', position: 'relative' }}><WorkspaceStats /></div>
: null : null
} }
@ -136,11 +135,13 @@ class Home extends Component {
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
}; };
const mapStateToProps = state => ({ const mapStateToProps = state => ({
message: state.message message: state.message,
statistics: state.general.statistics
}); });

View File

@ -9,6 +9,13 @@ import Typography from '@material-ui/core/Typography';
import * as Blockly from 'blockly' import * as Blockly from 'blockly'
class NotFound extends Component { class NotFound extends Component {
componentDidMount(){
// Ensure that Blockly.setLocale is adopted in the component.
// Otherwise, the text will not be displayed until the next update of the component.
this.forceUpdate();
}
render() { render() {
return ( return (
<div> <div>

View File

@ -1,44 +1,58 @@
import React from 'react'; import React, { Component } from 'react';
import { makeStyles } from '@material-ui/core/styles'; import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { setLanguage } from '../../actions/generalActions';
import * as Blockly from 'blockly/core';
import InputLabel from '@material-ui/core/InputLabel'; import InputLabel from '@material-ui/core/InputLabel';
import MenuItem from '@material-ui/core/MenuItem'; import MenuItem from '@material-ui/core/MenuItem';
import FormControl from '@material-ui/core/FormControl'; import FormControl from '@material-ui/core/FormControl';
import Select from '@material-ui/core/Select'; import Select from '@material-ui/core/Select';
import * as Blockly from 'blockly/core'; import Typography from '@material-ui/core/Typography';
import FormHelperText from '@material-ui/core/FormHelperText';
const useStyles = makeStyles((theme) => ({ class LanguageSelector extends Component {
formControl: {
margin: theme.spacing(1),
minWidth: 120,
},
selectEmpty: {
marginTop: theme.spacing(2),
},
}));
export default function LanguageSelector() { componentDidMount(){
const classes = useStyles(); // Ensure that Blockly.setLocale is adopted in the component.
const [lang, setLang] = React.useState(window.localStorage.getItem('locale')); // Otherwise, the text will not be displayed until the next update of the component.
this.forceUpdate();
}
const handleChange = (event) => { handleChange = (event) => {
setLang(event.target.value); this.props.setLanguage(event.target.value);
window.localStorage.setItem('locale', event.target.value); }
};
return ( render(){
<div> return(
<FormControl className={classes.formControl}> <div>
<InputLabel id="demo-simple-select-label">{Blockly.Msg.settings_language}</InputLabel> <Typography style={{fontWeight: 'bold'}}>{Blockly.Msg.settings_language}</Typography>
<Select <FormHelperText style={{color: 'black', lineHeight: 1.3, marginBottom: '8px'}}>{Blockly.Msg.settings_language_text}</FormHelperText>
labelId="demo-simple-select-label" <FormControl>
id="demo-simple-select" <InputLabel id="demo-simple-select-label">{Blockly.Msg.settings_language}</InputLabel>
value={lang} <Select
onChange={handleChange} labelId="demo-simple-select-label"
> id="demo-simple-select"
<MenuItem value={'de'}>Deutsch</MenuItem> value={this.props.language}
<MenuItem value={'en'}>Englisch</MenuItem> onChange={this.handleChange}
</Select> >
</FormControl> <MenuItem value={'de'}>{Blockly.Msg.settings_language_de}</MenuItem>
</div> <MenuItem value={'en'}>{Blockly.Msg.settings_language_en}</MenuItem>
</Select>
</FormControl>
</div>
); );
}
} }
LanguageSelector.propTypes = {
setLanguage: PropTypes.func.isRequired,
language: PropTypes.string.isRequired
};
const mapStateToProps = state => ({
language: state.general.language
});
export default connect(mapStateToProps, { setLanguage })(LanguageSelector);

View File

@ -1,45 +1,57 @@
import React from 'react'; import React, { Component } from 'react';
import { makeStyles } from '@material-ui/core/styles'; import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { setRenderer } from '../../actions/generalActions';
import * as Blockly from 'blockly/core'
import InputLabel from '@material-ui/core/InputLabel'; import InputLabel from '@material-ui/core/InputLabel';
import MenuItem from '@material-ui/core/MenuItem'; import MenuItem from '@material-ui/core/MenuItem';
import FormControl from '@material-ui/core/FormControl'; import FormControl from '@material-ui/core/FormControl';
import Select from '@material-ui/core/Select'; import Select from '@material-ui/core/Select';
import * as Blockly from 'blockly/core' import Typography from '@material-ui/core/Typography';
const useStyles = makeStyles((theme) => ({ import FormHelperText from '@material-ui/core/FormHelperText';
formControl: {
margin: theme.spacing(1),
minWidth: 400,
},
selectEmpty: {
marginTop: theme.spacing(2),
},
}));
export default function RenderSelector() {
const classes = useStyles();
const [renderer, setRenderer] = React.useState(window.localStorage.getItem('renderer'));
const handleChange = (event) => { class RenderSelector extends Component {
setRenderer(event.target.value);
window.localStorage.setItem('renderer', event.target.value);
};
componentDidMount(){
// Ensure that Blockly.setLocale is adopted in the component.
// Otherwise, the text will not be displayed until the next update of the component.
this.forceUpdate();
}
render(){
return ( return (
<div> <div>
<FormControl className={classes.formControl}> <Typography style={{fontWeight: 'bold'}}>{Blockly.Msg.settings_renderer}</Typography>
<InputLabel id="demo-simple-select-label">Renderer</InputLabel> <FormHelperText style={{color: 'black', lineHeight: 1.3, marginBottom: '8px'}}>{Blockly.Msg.settings_renderer_text}</FormHelperText>
<Select <FormControl>
labelId="demo-simple-select-label" <InputLabel id="demo-simple-select-label">{Blockly.Msg.settings_renderer}</InputLabel>
id="demo-simple-select" <Select
value={renderer} labelId="demo-simple-select-label"
onChange={handleChange} id="demo-simple-select"
value={this.props.renderer}
> onChange={(e) => this.props.setRenderer(e.target.value)}
<MenuItem value={'geras'}>Geras</MenuItem> >
<MenuItem value={'zelos'}>Zelos</MenuItem> <MenuItem value={'geras'}>Geras</MenuItem>
</Select> <MenuItem value={'zelos'}>Zelos</MenuItem>
</FormControl> </Select>
<p>{Blockly.Msg.settings_renderer_text}</p> </FormControl>
</div> </div>
); );
}
} }
RenderSelector.propTypes = {
setRenderer: PropTypes.func.isRequired,
language: PropTypes.string.isRequired,
renderer: PropTypes.string.isRequired
};
const mapStateToProps = state => ({
renderer: state.general.renderer,
language: state.general.language
});
export default connect(mapStateToProps, { setRenderer })(RenderSelector);

View File

@ -1,32 +1,65 @@
import React, { Component } from 'react'; import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { withRouter } from 'react-router-dom'; import { withRouter } from 'react-router-dom';
import Button from '@material-ui/core/Button'; import * as Blockly from 'blockly/core';
import Typography from '@material-ui/core/Typography';
import Breadcrumbs from '../Breadcrumbs';
import LanguageSelector from './LanguageSelector'; import LanguageSelector from './LanguageSelector';
import RenderSelector from './RenderSelector'; import RenderSelector from './RenderSelector';
import StatsSelector from './StatsSelector'; import StatsSelector from './StatsSelector';
import * as Blockly from 'blockly'
import Button from '@material-ui/core/Button';
import Paper from '@material-ui/core/Paper';
class Settings extends Component { class Settings extends Component {
render() {
return ( componentDidMount(){
<div> // Ensure that Blockly.setLocale is adopted in the component.
<Typography variant='h4' style={{ marginBottom: '5px' }}>{Blockly.Msg.settings_head}</Typography> // Otherwise, the text will not be displayed until the next update of the component.
<LanguageSelector /> this.forceUpdate();
<RenderSelector /> }
<StatsSelector />
<Button render() {
style={{ marginTop: '20px' }} return (
variant="contained" <div>
color="primary" <Breadcrumbs content={[{ link: this.props.location.pathname, title: Blockly.Msg.settings_head }]} />
onClick={() => { this.props.history.push('/') }}
> <h1>{Blockly.Msg.settings_head}</h1>
{Blockly.Msg.button_back}
</Button> <Paper style={{margin: '10px 0px', padding: '10px'}}>
</div> <LanguageSelector />
); </Paper>
}; <Paper style={{margin: '10px 0px', padding: '10px'}}>
<RenderSelector />
</Paper>
<Paper style={{margin: '10px 0px', padding: '10px'}}>
<StatsSelector />
</Paper>
<Button
style={{ marginTop: '10px' }}
variant="contained"
color="primary"
onClick={this.props.pageVisits > 0 ? () => this.props.history.goBack() : () => this.props.history.push('/')}
>
{Blockly.Msg.button_back}
</Button>
</div>
);
};
} }
export default withRouter(Settings); Settings.propTypes = {
language: PropTypes.string.isRequired,
pageVisits: PropTypes.number.isRequired
};
const mapStateToProps = state => ({
language: state.general.language,
pageVisits: state.general.pageVisits
});
export default connect(mapStateToProps, null)(withRouter(Settings));

View File

@ -1,44 +1,56 @@
import React from 'react'; import React, { Component } from 'react';
import { makeStyles } from '@material-ui/core/styles'; import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { setStatistics } from '../../actions/generalActions';
import * as Blockly from 'blockly/core'
import InputLabel from '@material-ui/core/InputLabel'; import InputLabel from '@material-ui/core/InputLabel';
import MenuItem from '@material-ui/core/MenuItem'; import MenuItem from '@material-ui/core/MenuItem';
import FormControl from '@material-ui/core/FormControl'; import FormControl from '@material-ui/core/FormControl';
import Select from '@material-ui/core/Select'; import Select from '@material-ui/core/Select';
import Typography from '@material-ui/core/Typography';
import FormHelperText from '@material-ui/core/FormHelperText';
const useStyles = makeStyles((theme) => ({ class StatsSelector extends Component {
formControl: {
margin: theme.spacing(1),
minWidth: 400,
},
selectEmpty: {
marginTop: theme.spacing(2),
},
}));
export default function StatsSelector() { componentDidMount(){
const classes = useStyles(); // Ensure that Blockly.setLocale is adopted in the component.
const [stats, setStats] = React.useState(window.localStorage.getItem('stats')); // Otherwise, the text will not be displayed until the next update of the component.
this.forceUpdate();
const handleChange = (event) => { }
setStats(event.target.value);
window.localStorage.setItem('stats', event.target.value);
};
render(){
return ( return (
<div> <div>
<FormControl className={classes.formControl}> <Typography style={{fontWeight: 'bold'}}>{Blockly.Msg.settings_statistics}</Typography>
<InputLabel id="demo-simple-select-label">Statistiken</InputLabel> <FormHelperText style={{color: 'black', lineHeight: 1.3, marginBottom: '8px'}}>{Blockly.Msg.settings_statistics_text}</FormHelperText>
<Select <FormControl>
labelId="demo-simple-select-label" <InputLabel id="demo-simple-select-label">{Blockly.Msg.settings_statistics}</InputLabel>
id="demo-simple-select" <Select
value={stats} labelId="demo-simple-select-label"
onChange={handleChange} id="demo-simple-select"
> value={this.props.statistics}
<MenuItem value={true}>On</MenuItem> onChange={(e) => this.props.setStatistics(e.target.value)}
<MenuItem value={false}>Off</MenuItem> >
</Select> <MenuItem value={true}>{Blockly.Msg.settings_statistics_on}</MenuItem>
</FormControl> <MenuItem value={false}>{Blockly.Msg.settings_statistics_off}</MenuItem>
<p>Schaltet die Statistiken Oberhalb der Arbeitsfläche ein bzw. aus</p> </Select>
</div> </FormControl>
</div>
); );
}
} }
StatsSelector.propTypes = {
setStatistics: PropTypes.func.isRequired,
language: PropTypes.string.isRequired,
statistics: PropTypes.bool.isRequired
};
const mapStateToProps = state => ({
statistics: state.general.statistics,
language: state.general.language
});
export default connect(mapStateToProps, { setStatistics })(StatsSelector);

View File

@ -1,8 +1,11 @@
import { VISIT } from '../actions/types'; import { VISIT, LANGUAGE, RENDERER, STATISTICS } from '../actions/types';
const initialState = { const initialState = {
pageVisits: 0 // detect if previous URL was pageVisits: 0, // detect if previous URL was
language: 'de',
renderer: window.localStorage.getItem('renderer') || 'geras',
statistics: window.localStorage.getItem('statistics') === 'true' ? true : window.localStorage.getItem('statistics') === 'false' ? false : false
}; };
export default function(state = initialState, action){ export default function(state = initialState, action){
@ -12,6 +15,23 @@ export default function(state = initialState, action){
...state, ...state,
pageVisits: state.pageVisits += 1 pageVisits: state.pageVisits += 1
}; };
case LANGUAGE:
return {
...state,
language: action.payload
};
case RENDERER:
window.localStorage.setItem('renderer', action.payload);
return {
...state,
renderer: action.payload
};
case STATISTICS:
window.localStorage.setItem('statistics', action.payload);
return {
...state,
statistics: action.payload
};
default: default:
return state; return state;
} }