Merge branch 'develop' into console-scroll-to-bottom
This commit is contained in:
commit
f1b2cb5ee0
13 changed files with 114 additions and 34 deletions
|
@ -9,7 +9,7 @@ import i18next from 'i18next';
|
||||||
import * as IDEActions from '../modules/IDE/actions/ide';
|
import * as IDEActions from '../modules/IDE/actions/ide';
|
||||||
import * as toastActions from '../modules/IDE/actions/toast';
|
import * as toastActions from '../modules/IDE/actions/toast';
|
||||||
import * as projectActions from '../modules/IDE/actions/project';
|
import * as projectActions from '../modules/IDE/actions/project';
|
||||||
import { setAllAccessibleOutput } from '../modules/IDE/actions/preferences';
|
import { setAllAccessibleOutput, setLanguage } from '../modules/IDE/actions/preferences';
|
||||||
import { logoutUser } from '../modules/User/actions';
|
import { logoutUser } from '../modules/User/actions';
|
||||||
|
|
||||||
import getConfig from '../utils/getConfig';
|
import getConfig from '../utils/getConfig';
|
||||||
|
@ -72,7 +72,6 @@ class Nav extends React.PureComponent {
|
||||||
document.removeEventListener('mousedown', this.handleClick, false);
|
document.removeEventListener('mousedown', this.handleClick, false);
|
||||||
document.removeEventListener('keydown', this.closeDropDown, false);
|
document.removeEventListener('keydown', this.closeDropDown, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
setDropdown(dropdown) {
|
setDropdown(dropdown) {
|
||||||
this.setState({
|
this.setState({
|
||||||
dropdownOpen: dropdown
|
dropdownOpen: dropdown
|
||||||
|
@ -170,7 +169,7 @@ class Nav extends React.PureComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
handleLangSelection(event) {
|
handleLangSelection(event) {
|
||||||
i18next.changeLanguage(event.target.value);
|
this.props.setLanguage(event.target.value);
|
||||||
this.props.showToast(1500);
|
this.props.showToast(1500);
|
||||||
this.props.setToastText('Toast.LangChange');
|
this.props.setToastText('Toast.LangChange');
|
||||||
this.setDropdown('none');
|
this.setDropdown('none');
|
||||||
|
@ -808,8 +807,8 @@ Nav.propTypes = {
|
||||||
params: PropTypes.shape({
|
params: PropTypes.shape({
|
||||||
username: PropTypes.string
|
username: PropTypes.string
|
||||||
}),
|
}),
|
||||||
t: PropTypes.func.isRequired
|
t: PropTypes.func.isRequired,
|
||||||
|
setLanguage: PropTypes.func.isRequired,
|
||||||
};
|
};
|
||||||
|
|
||||||
Nav.defaultProps = {
|
Nav.defaultProps = {
|
||||||
|
@ -839,7 +838,8 @@ const mapDispatchToProps = {
|
||||||
...projectActions,
|
...projectActions,
|
||||||
...toastActions,
|
...toastActions,
|
||||||
logoutUser,
|
logoutUser,
|
||||||
setAllAccessibleOutput
|
setAllAccessibleOutput,
|
||||||
|
setLanguage
|
||||||
};
|
};
|
||||||
|
|
||||||
export default withTranslation()(withRouter(connect(mapStateToProps, mapDispatchToProps)(Nav)));
|
export default withTranslation()(withRouter(connect(mapStateToProps, mapDispatchToProps)(Nav)));
|
||||||
|
|
|
@ -45,7 +45,8 @@ describe('Nav', () => {
|
||||||
rootFile: {
|
rootFile: {
|
||||||
id: 'root-file'
|
id: 'root-file'
|
||||||
},
|
},
|
||||||
t: jest.fn()
|
t: jest.fn(),
|
||||||
|
setLanguage: jest.fn()
|
||||||
};
|
};
|
||||||
|
|
||||||
it('renders correctly', () => {
|
it('renders correctly', () => {
|
||||||
|
|
|
@ -93,6 +93,7 @@ export const SHOW_TOAST = 'SHOW_TOAST';
|
||||||
export const HIDE_TOAST = 'HIDE_TOAST';
|
export const HIDE_TOAST = 'HIDE_TOAST';
|
||||||
export const SET_TOAST_TEXT = 'SET_TOAST_TEXT';
|
export const SET_TOAST_TEXT = 'SET_TOAST_TEXT';
|
||||||
export const SET_THEME = 'SET_THEME';
|
export const SET_THEME = 'SET_THEME';
|
||||||
|
export const SET_LANGUAGE = 'SET_LANGUAGE';
|
||||||
|
|
||||||
export const SET_UNSAVED_CHANGES = 'SET_UNSAVED_CHANGES';
|
export const SET_UNSAVED_CHANGES = 'SET_UNSAVED_CHANGES';
|
||||||
export const SET_AUTOREFRESH = 'SET_AUTOREFRESH';
|
export const SET_AUTOREFRESH = 'SET_AUTOREFRESH';
|
||||||
|
|
|
@ -4,6 +4,7 @@ import { connect } from 'react-redux';
|
||||||
import getConfig from '../../utils/getConfig';
|
import getConfig from '../../utils/getConfig';
|
||||||
import DevTools from './components/DevTools';
|
import DevTools from './components/DevTools';
|
||||||
import { setPreviousPath } from '../IDE/actions/ide';
|
import { setPreviousPath } from '../IDE/actions/ide';
|
||||||
|
import { setLanguage } from '../IDE/actions/preferences';
|
||||||
|
|
||||||
class App extends React.Component {
|
class App extends React.Component {
|
||||||
constructor(props, context) {
|
constructor(props, context) {
|
||||||
|
@ -23,6 +24,10 @@ class App extends React.Component {
|
||||||
if (locationWillChange && !shouldSkipRemembering) {
|
if (locationWillChange && !shouldSkipRemembering) {
|
||||||
this.props.setPreviousPath(this.props.location.pathname);
|
this.props.setPreviousPath(this.props.location.pathname);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.props.language !== nextProps.language) {
|
||||||
|
this.props.setLanguage(nextProps.language, { persistPreference: false });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidUpdate(prevProps) {
|
componentDidUpdate(prevProps) {
|
||||||
|
@ -50,18 +55,22 @@ App.propTypes = {
|
||||||
}),
|
}),
|
||||||
}).isRequired,
|
}).isRequired,
|
||||||
setPreviousPath: PropTypes.func.isRequired,
|
setPreviousPath: PropTypes.func.isRequired,
|
||||||
|
setLanguage: PropTypes.func.isRequired,
|
||||||
|
language: PropTypes.string,
|
||||||
theme: PropTypes.string,
|
theme: PropTypes.string,
|
||||||
};
|
};
|
||||||
|
|
||||||
App.defaultProps = {
|
App.defaultProps = {
|
||||||
children: null,
|
children: null,
|
||||||
|
language: null,
|
||||||
theme: 'light'
|
theme: 'light'
|
||||||
};
|
};
|
||||||
|
|
||||||
const mapStateToProps = state => ({
|
const mapStateToProps = state => ({
|
||||||
theme: state.preferences.theme,
|
theme: state.preferences.theme,
|
||||||
|
language: state.preferences.language,
|
||||||
});
|
});
|
||||||
|
|
||||||
const mapDispatchToProps = { setPreviousPath };
|
const mapDispatchToProps = { setPreviousPath, setLanguage };
|
||||||
|
|
||||||
export default connect(mapStateToProps, mapDispatchToProps)(App);
|
export default connect(mapStateToProps, mapDispatchToProps)(App);
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import i18next from 'i18next';
|
||||||
import apiClient from '../../../utils/apiClient';
|
import apiClient from '../../../utils/apiClient';
|
||||||
import * as ActionTypes from '../../../constants';
|
import * as ActionTypes from '../../../constants';
|
||||||
|
|
||||||
|
@ -210,3 +211,22 @@ export function setAllAccessibleOutput(value) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function setLanguage(value, { persistPreference = true } = {}) {
|
||||||
|
return (dispatch, getState) => {
|
||||||
|
i18next.changeLanguage(value);
|
||||||
|
dispatch({
|
||||||
|
type: ActionTypes.SET_LANGUAGE,
|
||||||
|
language: value
|
||||||
|
});
|
||||||
|
const state = getState();
|
||||||
|
if (persistPreference && state.user.authenticated) {
|
||||||
|
const formParams = {
|
||||||
|
preferences: {
|
||||||
|
language: value
|
||||||
|
}
|
||||||
|
};
|
||||||
|
updatePreferences(formParams, dispatch);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -35,6 +35,7 @@ import AddToCollectionList from '../components/AddToCollectionList';
|
||||||
import Feedback from '../components/Feedback';
|
import Feedback from '../components/Feedback';
|
||||||
import { CollectionSearchbar } from '../components/Searchbar';
|
import { CollectionSearchbar } from '../components/Searchbar';
|
||||||
|
|
||||||
|
|
||||||
function getTitle(props) {
|
function getTitle(props) {
|
||||||
const { id } = props.project;
|
const { id } = props.project;
|
||||||
return id ? `p5.js Web Editor | ${props.project.name}` : 'p5.js Web Editor';
|
return id ? `p5.js Web Editor | ${props.project.name}` : 'p5.js Web Editor';
|
||||||
|
@ -144,13 +145,11 @@ class IDEView extends React.Component {
|
||||||
this.props.router.setRouteLeaveHook(this.props.route, () => warnIfUnsavedChanges(this.props));
|
this.props.router.setRouteLeaveHook(this.props.route, () => warnIfUnsavedChanges(this.props));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillUnmount() {
|
componentWillUnmount() {
|
||||||
document.removeEventListener('keydown', this.handleGlobalKeydown, false);
|
document.removeEventListener('keydown', this.handleGlobalKeydown, false);
|
||||||
clearTimeout(this.autosaveInterval);
|
clearTimeout(this.autosaveInterval);
|
||||||
this.autosaveInterval = null;
|
this.autosaveInterval = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
handleGlobalKeydown(e) {
|
handleGlobalKeydown(e) {
|
||||||
// 83 === s
|
// 83 === s
|
||||||
if (e.keyCode === 83 && ((e.metaKey && this.isMac) || (e.ctrlKey && !this.isMac))) {
|
if (e.keyCode === 83 && ((e.metaKey && this.isMac) || (e.ctrlKey && !this.isMac))) {
|
||||||
|
@ -367,6 +366,7 @@ class IDEView extends React.Component {
|
||||||
expandConsole={this.props.expandConsole}
|
expandConsole={this.props.expandConsole}
|
||||||
clearConsole={this.props.clearConsole}
|
clearConsole={this.props.clearConsole}
|
||||||
cmController={this.cmController}
|
cmController={this.cmController}
|
||||||
|
language={this.props.preferences.language}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
@ -527,7 +527,8 @@ IDEView.propTypes = {
|
||||||
gridOutput: PropTypes.bool.isRequired,
|
gridOutput: PropTypes.bool.isRequired,
|
||||||
soundOutput: PropTypes.bool.isRequired,
|
soundOutput: PropTypes.bool.isRequired,
|
||||||
theme: PropTypes.string.isRequired,
|
theme: PropTypes.string.isRequired,
|
||||||
autorefresh: PropTypes.bool.isRequired
|
autorefresh: PropTypes.bool.isRequired,
|
||||||
|
language: PropTypes.string.isRequired
|
||||||
}).isRequired,
|
}).isRequired,
|
||||||
closePreferences: PropTypes.func.isRequired,
|
closePreferences: PropTypes.func.isRequired,
|
||||||
setFontSize: PropTypes.func.isRequired,
|
setFontSize: PropTypes.func.isRequired,
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
|
import i18next from 'i18next';
|
||||||
import * as ActionTypes from '../../../constants';
|
import * as ActionTypes from '../../../constants';
|
||||||
|
|
||||||
|
|
||||||
const initialState = {
|
const initialState = {
|
||||||
fontSize: 18,
|
fontSize: 18,
|
||||||
autosave: true,
|
autosave: true,
|
||||||
|
@ -10,7 +12,8 @@ const initialState = {
|
||||||
gridOutput: false,
|
gridOutput: false,
|
||||||
soundOutput: false,
|
soundOutput: false,
|
||||||
theme: 'light',
|
theme: 'light',
|
||||||
autorefresh: false
|
autorefresh: false,
|
||||||
|
language: 'en-US'
|
||||||
};
|
};
|
||||||
|
|
||||||
const preferences = (state = initialState, action) => {
|
const preferences = (state = initialState, action) => {
|
||||||
|
@ -37,6 +40,8 @@ const preferences = (state = initialState, action) => {
|
||||||
return Object.assign({}, state, { autorefresh: action.value });
|
return Object.assign({}, state, { autorefresh: action.value });
|
||||||
case ActionTypes.SET_LINE_NUMBERS:
|
case ActionTypes.SET_LINE_NUMBERS:
|
||||||
return Object.assign({}, state, { lineNumbers: action.value });
|
return Object.assign({}, state, { lineNumbers: action.value });
|
||||||
|
case ActionTypes.SET_LANGUAGE:
|
||||||
|
return Object.assign({}, state, { language: action.language });
|
||||||
default:
|
default:
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ import { browserHistory } from 'react-router';
|
||||||
import * as ActionTypes from '../../constants';
|
import * as ActionTypes from '../../constants';
|
||||||
import apiClient from '../../utils/apiClient';
|
import apiClient from '../../utils/apiClient';
|
||||||
import { showErrorModal, justOpenedProject } from '../IDE/actions/ide';
|
import { showErrorModal, justOpenedProject } from '../IDE/actions/ide';
|
||||||
|
import { setLanguage } from '../IDE/actions/preferences';
|
||||||
import { showToast, setToastText } from '../IDE/actions/toast';
|
import { showToast, setToastText } from '../IDE/actions/toast';
|
||||||
|
|
||||||
export function authError(error) {
|
export function authError(error) {
|
||||||
|
@ -59,6 +60,7 @@ export function validateAndLoginUser(previousPath, formProps, dispatch) {
|
||||||
type: ActionTypes.SET_PREFERENCES,
|
type: ActionTypes.SET_PREFERENCES,
|
||||||
preferences: response.data.preferences
|
preferences: response.data.preferences
|
||||||
});
|
});
|
||||||
|
setLanguage(response.data.preferences.language, { persistPreference: false });
|
||||||
dispatch(justOpenedProject());
|
dispatch(justOpenedProject());
|
||||||
browserHistory.push(previousPath);
|
browserHistory.push(previousPath);
|
||||||
resolve();
|
resolve();
|
||||||
|
@ -80,8 +82,8 @@ export function getUser() {
|
||||||
type: ActionTypes.SET_PREFERENCES,
|
type: ActionTypes.SET_PREFERENCES,
|
||||||
preferences: response.data.preferences
|
preferences: response.data.preferences
|
||||||
});
|
});
|
||||||
})
|
setLanguage(response.data.preferences.language, { persistPreference: false });
|
||||||
.catch((error) => {
|
}).catch((error) => {
|
||||||
const { response } = error;
|
const { response } = error;
|
||||||
const message = response.message || response.data.error;
|
const message = response.message || response.data.error;
|
||||||
dispatch(authError(message));
|
dispatch(authError(message));
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import { withTranslation } from 'react-i18next';
|
||||||
|
|
||||||
import { domOnlyProps } from '../../../utils/reduxFormUtils';
|
import { domOnlyProps } from '../../../utils/reduxFormUtils';
|
||||||
import Button from '../../../common/Button';
|
import Button from '../../../common/Button';
|
||||||
|
@ -13,10 +14,10 @@ function SignupForm(props) {
|
||||||
return (
|
return (
|
||||||
<form className="form" onSubmit={handleSubmit(props.signUpUser.bind(this, props.previousPath))}>
|
<form className="form" onSubmit={handleSubmit(props.signUpUser.bind(this, props.previousPath))}>
|
||||||
<p className="form__field">
|
<p className="form__field">
|
||||||
<label htmlFor="username" className="form__label">User Name</label>
|
<label htmlFor="username" className="form__label">{props.t('SignupForm.Title')}</label>
|
||||||
<input
|
<input
|
||||||
className="form__input"
|
className="form__input"
|
||||||
aria-label="username"
|
aria-label={props.t('SignupForm.TitleARIA')}
|
||||||
type="text"
|
type="text"
|
||||||
id="username"
|
id="username"
|
||||||
{...domOnlyProps(username)}
|
{...domOnlyProps(username)}
|
||||||
|
@ -24,10 +25,10 @@ function SignupForm(props) {
|
||||||
{username.touched && username.error && <span className="form-error">{username.error}</span>}
|
{username.touched && username.error && <span className="form-error">{username.error}</span>}
|
||||||
</p>
|
</p>
|
||||||
<p className="form__field">
|
<p className="form__field">
|
||||||
<label htmlFor="email" className="form__label">Email</label>
|
<label htmlFor="email" className="form__label">{props.t('SignupForm.Email')}</label>
|
||||||
<input
|
<input
|
||||||
className="form__input"
|
className="form__input"
|
||||||
aria-label="email"
|
aria-label={props.t('SignupForm.EmailARIA')}
|
||||||
type="text"
|
type="text"
|
||||||
id="email"
|
id="email"
|
||||||
{...domOnlyProps(email)}
|
{...domOnlyProps(email)}
|
||||||
|
@ -35,10 +36,10 @@ function SignupForm(props) {
|
||||||
{email.touched && email.error && <span className="form-error">{email.error}</span>}
|
{email.touched && email.error && <span className="form-error">{email.error}</span>}
|
||||||
</p>
|
</p>
|
||||||
<p className="form__field">
|
<p className="form__field">
|
||||||
<label htmlFor="password" className="form__label">Password</label>
|
<label htmlFor="password" className="form__label">{props.t('SignupForm.Password')}</label>
|
||||||
<input
|
<input
|
||||||
className="form__input"
|
className="form__input"
|
||||||
aria-label="password"
|
aria-label={props.t('SignupForm.PasswordARIA')}
|
||||||
type="password"
|
type="password"
|
||||||
id="password"
|
id="password"
|
||||||
{...domOnlyProps(password)}
|
{...domOnlyProps(password)}
|
||||||
|
@ -46,11 +47,11 @@ function SignupForm(props) {
|
||||||
{password.touched && password.error && <span className="form-error">{password.error}</span>}
|
{password.touched && password.error && <span className="form-error">{password.error}</span>}
|
||||||
</p>
|
</p>
|
||||||
<p className="form__field">
|
<p className="form__field">
|
||||||
<label htmlFor="confirm password" className="form__label">Confirm Password</label>
|
<label htmlFor="confirm password" className="form__label">{props.t('SignupForm.ConfirmPassword')}</label>
|
||||||
<input
|
<input
|
||||||
className="form__input"
|
className="form__input"
|
||||||
type="password"
|
type="password"
|
||||||
aria-label="confirm password"
|
aria-label={props.t('SignupForm.ConfirmPasswordARIA')}
|
||||||
id="confirm password"
|
id="confirm password"
|
||||||
{...domOnlyProps(confirmPassword)}
|
{...domOnlyProps(confirmPassword)}
|
||||||
/>
|
/>
|
||||||
|
@ -63,7 +64,7 @@ function SignupForm(props) {
|
||||||
<Button
|
<Button
|
||||||
type="submit"
|
type="submit"
|
||||||
disabled={submitting || invalid || pristine}
|
disabled={submitting || invalid || pristine}
|
||||||
>Sign Up
|
>{props.t('SignupForm.SubmitSignup')}
|
||||||
</Button>
|
</Button>
|
||||||
</form>
|
</form>
|
||||||
);
|
);
|
||||||
|
@ -81,7 +82,8 @@ SignupForm.propTypes = {
|
||||||
submitting: PropTypes.bool,
|
submitting: PropTypes.bool,
|
||||||
invalid: PropTypes.bool,
|
invalid: PropTypes.bool,
|
||||||
pristine: PropTypes.bool,
|
pristine: PropTypes.bool,
|
||||||
previousPath: PropTypes.string.isRequired
|
previousPath: PropTypes.string.isRequired,
|
||||||
|
t: PropTypes.func.isRequired
|
||||||
};
|
};
|
||||||
|
|
||||||
SignupForm.defaultProps = {
|
SignupForm.defaultProps = {
|
||||||
|
@ -90,4 +92,4 @@ SignupForm.defaultProps = {
|
||||||
invalid: false
|
invalid: false
|
||||||
};
|
};
|
||||||
|
|
||||||
export default SignupForm;
|
export default withTranslation()(SignupForm);
|
||||||
|
|
|
@ -4,6 +4,7 @@ import { bindActionCreators } from 'redux';
|
||||||
import { Link, browserHistory } from 'react-router';
|
import { Link, browserHistory } from 'react-router';
|
||||||
import { Helmet } from 'react-helmet';
|
import { Helmet } from 'react-helmet';
|
||||||
import { reduxForm } from 'redux-form';
|
import { reduxForm } from 'redux-form';
|
||||||
|
import { withTranslation } from 'react-i18next';
|
||||||
import * as UserActions from '../actions';
|
import * as UserActions from '../actions';
|
||||||
import SignupForm from '../components/SignupForm';
|
import SignupForm from '../components/SignupForm';
|
||||||
import apiClient from '../../../utils/apiClient';
|
import apiClient from '../../../utils/apiClient';
|
||||||
|
@ -26,19 +27,19 @@ class SignupView extends React.Component {
|
||||||
<Nav layout="dashboard" />
|
<Nav layout="dashboard" />
|
||||||
<main className="form-container">
|
<main className="form-container">
|
||||||
<Helmet>
|
<Helmet>
|
||||||
<title>p5.js Web Editor | Signup</title>
|
<title>{this.props.t('SignupView.Title')}</title>
|
||||||
</Helmet>
|
</Helmet>
|
||||||
<div className="form-container__content">
|
<div className="form-container__content">
|
||||||
<h2 className="form-container__title">Sign Up</h2>
|
<h2 className="form-container__title">{this.props.t('SignupView.Description')}</h2>
|
||||||
<SignupForm {...this.props} />
|
<SignupForm {...this.props} />
|
||||||
<h2 className="form-container__divider">Or</h2>
|
<h2 className="form-container__divider">{this.props.t('SignupView.Or')}</h2>
|
||||||
<div className="form-container__stack">
|
<div className="form-container__stack">
|
||||||
<SocialAuthButton service={SocialAuthButton.services.github} />
|
<SocialAuthButton service={SocialAuthButton.services.github} />
|
||||||
<SocialAuthButton service={SocialAuthButton.services.google} />
|
<SocialAuthButton service={SocialAuthButton.services.google} />
|
||||||
</div>
|
</div>
|
||||||
<p className="form__navigation-options">
|
<p className="form__navigation-options">
|
||||||
Already have an account?
|
{this.props.t('SignupView.AlreadyHave')}
|
||||||
<Link className="form__login-button" to="/login">Log In</Link>
|
<Link className="form__login-button" to="/login">{this.props.t('SignupView.Login')}</Link>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</main>
|
</main>
|
||||||
|
@ -108,7 +109,8 @@ SignupView.propTypes = {
|
||||||
previousPath: PropTypes.string.isRequired,
|
previousPath: PropTypes.string.isRequired,
|
||||||
user: PropTypes.shape({
|
user: PropTypes.shape({
|
||||||
authenticated: PropTypes.bool
|
authenticated: PropTypes.bool
|
||||||
})
|
}),
|
||||||
|
t: PropTypes.func.isRequired
|
||||||
};
|
};
|
||||||
|
|
||||||
SignupView.defaultProps = {
|
SignupView.defaultProps = {
|
||||||
|
@ -117,11 +119,11 @@ SignupView.defaultProps = {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export default reduxForm({
|
export default withTranslation()(reduxForm({
|
||||||
form: 'signup',
|
form: 'signup',
|
||||||
fields: ['username', 'email', 'password', 'confirmPassword'],
|
fields: ['username', 'email', 'password', 'confirmPassword'],
|
||||||
onSubmitFail,
|
onSubmitFail,
|
||||||
validate: validateSignup,
|
validate: validateSignup,
|
||||||
asyncValidate,
|
asyncValidate,
|
||||||
asyncBlurFields: ['username', 'email']
|
asyncBlurFields: ['username', 'email']
|
||||||
}, mapStateToProps, mapDispatchToProps)(SignupView);
|
}, mapStateToProps, mapDispatchToProps)(SignupView));
|
||||||
|
|
|
@ -65,7 +65,8 @@ const userSchema = new Schema({
|
||||||
gridOutput: { type: Boolean, default: false },
|
gridOutput: { type: Boolean, default: false },
|
||||||
soundOutput: { type: Boolean, default: false },
|
soundOutput: { type: Boolean, default: false },
|
||||||
theme: { type: String, default: 'light' },
|
theme: { type: String, default: 'light' },
|
||||||
autorefresh: { type: Boolean, default: false }
|
autorefresh: { type: Boolean, default: false },
|
||||||
|
language: { type: String, default: 'en-US' }
|
||||||
},
|
},
|
||||||
totalSize: { type: Number, default: 0 }
|
totalSize: { type: Number, default: 0 }
|
||||||
}, { timestamps: true, usePushEach: true });
|
}, { timestamps: true, usePushEach: true });
|
||||||
|
|
|
@ -289,5 +289,23 @@
|
||||||
"ConfirmPassword": "Confirm Password",
|
"ConfirmPassword": "Confirm Password",
|
||||||
"ConfirmPasswordARIA": "Confirm Password",
|
"ConfirmPasswordARIA": "Confirm Password",
|
||||||
"SubmitSetNewPassword": "Set New Password"
|
"SubmitSetNewPassword": "Set New Password"
|
||||||
|
},
|
||||||
|
"SignupForm": {
|
||||||
|
"Title": "User Name",
|
||||||
|
"TitleARIA": "username",
|
||||||
|
"Email": "Email",
|
||||||
|
"EmailARIA": "email",
|
||||||
|
"Password": "Password",
|
||||||
|
"PasswordARIA": "password",
|
||||||
|
"ConfirmPassword": "Confirm Password",
|
||||||
|
"ConfirmPasswordARIA": "Confirm password",
|
||||||
|
"SubmitSignup": "Sign Up"
|
||||||
|
},
|
||||||
|
"SignupView": {
|
||||||
|
"Title": "p5.js Web Editor | Signup",
|
||||||
|
"Description": "Sign Up",
|
||||||
|
"Or": "Or",
|
||||||
|
"AlreadyHave": "Already have an account?",
|
||||||
|
"Login": "Log In"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -289,5 +289,23 @@
|
||||||
"ConfirmPassword": "Confirmar Contraseña",
|
"ConfirmPassword": "Confirmar Contraseña",
|
||||||
"ConfirmPasswordARIA": "Confirmar contraseña",
|
"ConfirmPasswordARIA": "Confirmar contraseña",
|
||||||
"SubmitSetNewPassword": "Crear Nueva Contraseña"
|
"SubmitSetNewPassword": "Crear Nueva Contraseña"
|
||||||
|
},
|
||||||
|
"SignupForm": {
|
||||||
|
"Title": "Identificación",
|
||||||
|
"TitleARIA": "Identificación",
|
||||||
|
"Email": "Correo electrónico",
|
||||||
|
"EmailARIA": "correo electrónico",
|
||||||
|
"Password": "Contraseña",
|
||||||
|
"PasswordARIA": "contraseña",
|
||||||
|
"ConfirmPassword": "Confirma tu contraseña",
|
||||||
|
"ConfirmPasswordARIA": "Confirma tu contraseña",
|
||||||
|
"SubmitSignup": "Registráte"
|
||||||
|
},
|
||||||
|
"SignupView": {
|
||||||
|
"Title": " Editor Web p5.js | Registráte",
|
||||||
|
"Description": "Registráte",
|
||||||
|
"Or": "o",
|
||||||
|
"AlreadyHave": "¿Ya tienes cuenta? ",
|
||||||
|
"Login": "Ingresa"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue