Merge branch 'feature/mobile-examples' of https://github.com/ghalestrilo/p5.js-web-editor into feature/mobile-files-tab

This commit is contained in:
ghalestrilo 2020-08-12 11:50:40 -03:00
commit 352783a62f
6 changed files with 93 additions and 58 deletions

View file

@ -608,13 +608,13 @@ class Nav extends React.PureComponent {
<ul className="nav__items-right" title="user-menu"> <ul className="nav__items-right" title="user-menu">
<li className="nav__item"> <li className="nav__item">
<Link to="/login" className="nav__auth-button"> <Link to="/login" className="nav__auth-button">
<span className="nav__item-header">{this.props.t('Nav.Login.Login')}</span> <span className="nav__item-header">{this.props.t('Nav.Login')}</span>
</Link> </Link>
</li> </li>
<span className="nav__item-or">{this.props.t('Nav.Login.LoginOr')}</span> <span className="nav__item-or">{this.props.t('Nav.LoginOr')}</span>
<li className="nav__item"> <li className="nav__item">
<Link to="/signup" className="nav__auth-button"> <Link to="/signup" className="nav__auth-button">
<span className="nav__item-header">{this.props.t('Nav.Login.SignUp')}</span> <span className="nav__item-header">{this.props.t('Nav.SignUp')}</span>
</Link> </Link>
</li> </li>
</ul> </ul>

View file

@ -1,6 +1,7 @@
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import React from 'react'; import React from 'react';
import { withTranslation } from 'react-i18next';
import i18n from 'i18next';
import Button from '../../../common/Button'; import Button from '../../../common/Button';
import { domOnlyProps } from '../../../utils/reduxFormUtils'; import { domOnlyProps } from '../../../utils/reduxFormUtils';
@ -18,12 +19,10 @@ function LoginForm(props) {
onSubmit={handleSubmit(props.validateAndLoginUser.bind(this, props.previousPath))} onSubmit={handleSubmit(props.validateAndLoginUser.bind(this, props.previousPath))}
> >
<p className="form__field"> <p className="form__field">
<label htmlFor="email" className="form__label"> <label htmlFor="email" className="form__label">{props.t('LoginForm.UsernameOrEmail')}</label>
Email or Username
</label>
<input <input
className="form__input" className="form__input"
aria-label="email or username" aria-label={props.t('LoginForm.UsernameOrEmailARIA')}
type="text" type="text"
id="email" id="email"
{...domOnlyProps(email)} {...domOnlyProps(email)}
@ -33,12 +32,10 @@ function LoginForm(props) {
)} )}
</p> </p>
<p className="form__field"> <p className="form__field">
<label htmlFor="password" className="form__label"> <label htmlFor="password" className="form__label">{props.t('LoginForm.Password')}</label>
Password
</label>
<input <input
className="form__input" className="form__input"
aria-label="password" aria-label={props.t('LoginForm.PasswordARIA')}
type="password" type="password"
id="password" id="password"
{...domOnlyProps(password)} {...domOnlyProps(password)}
@ -47,8 +44,10 @@ function LoginForm(props) {
<span className="form-error">{password.error}</span> <span className="form-error">{password.error}</span>
)} )}
</p> </p>
<Button type="submit" disabled={submitting || pristine}> <Button
Log In type="submit"
disabled={submitting || pristine}
>{props.t('LoginForm.Submit')}
</Button> </Button>
</form> </form>
); );
@ -65,6 +64,7 @@ LoginForm.propTypes = {
pristine: PropTypes.bool, pristine: PropTypes.bool,
invalid: PropTypes.bool, invalid: PropTypes.bool,
previousPath: PropTypes.string.isRequired, previousPath: PropTypes.string.isRequired,
t: PropTypes.func.isRequired
}; };
LoginForm.defaultProps = { LoginForm.defaultProps = {
@ -73,4 +73,4 @@ LoginForm.defaultProps = {
invalid: false, invalid: false,
}; };
export default LoginForm; export default withTranslation()(LoginForm);

View file

@ -1,6 +1,8 @@
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import React from 'react'; import React from 'react';
import styled from 'styled-components'; import styled from 'styled-components';
import i18n from 'i18next';
import { withTranslation } from 'react-i18next';
import { remSize } from '../../../theme'; import { remSize } from '../../../theme';
@ -12,11 +14,6 @@ const authUrls = {
google: '/auth/google' google: '/auth/google'
}; };
const labels = {
github: 'Login with GitHub',
google: 'Login with Google'
};
const icons = { const icons = {
github: GithubIcon, github: GithubIcon,
google: GoogleIcon google: GoogleIcon
@ -31,11 +28,15 @@ const StyledButton = styled(Button)`
width: ${remSize(300)}; width: ${remSize(300)};
`; `;
function SocialAuthButton({ service }) { function SocialAuthButton({ service, t }) {
const ServiceIcon = icons[service]; const ServiceIcon = icons[service];
const labels = {
github: t('SocialAuthButton.Github'),
google: t('SocialAuthButton.Google')
};
return ( return (
<StyledButton <StyledButton
iconBefore={<ServiceIcon aria-label={`${service} logo`} />} iconBefore={<ServiceIcon aria-label={t('SocialAuthButton.LogoARIA', { serviceauth: service })} />}
href={authUrls[service]} href={authUrls[service]}
> >
{labels[service]} {labels[service]}
@ -46,7 +47,10 @@ function SocialAuthButton({ service }) {
SocialAuthButton.services = services; SocialAuthButton.services = services;
SocialAuthButton.propTypes = { SocialAuthButton.propTypes = {
service: PropTypes.oneOf(['github', 'google']).isRequired service: PropTypes.oneOf(['github', 'google']).isRequired,
t: PropTypes.func.isRequired
}; };
export default SocialAuthButton; const SocialAuthButtonPublic = withTranslation()(SocialAuthButton);
SocialAuthButtonPublic.services = services;
export default SocialAuthButtonPublic;

View file

@ -3,6 +3,8 @@ import React from 'react';
import { reduxForm } from 'redux-form'; import { reduxForm } from 'redux-form';
import { Link, browserHistory } from 'react-router'; import { Link, browserHistory } from 'react-router';
import { Helmet } from 'react-helmet'; import { Helmet } from 'react-helmet';
import { withTranslation } from 'react-i18next';
import i18n from 'i18next';
import { validateAndLoginUser } from '../actions'; import { validateAndLoginUser } from '../actions';
import LoginForm from '../components/LoginForm'; import LoginForm from '../components/LoginForm';
import { validateLogin } from '../../../utils/reduxFormUtils'; import { validateLogin } from '../../../utils/reduxFormUtils';
@ -34,23 +36,23 @@ class LoginView extends React.Component {
<Nav layout="dashboard" /> <Nav layout="dashboard" />
<main className="form-container"> <main className="form-container">
<Helmet> <Helmet>
<title>p5.js Web Editor | Login</title> <title>{this.props.t('LoginView.Title')}</title>
</Helmet> </Helmet>
<div className="form-container__content"> <div className="form-container__content">
<h2 className="form-container__title">Log In</h2> <h2 className="form-container__title">{this.props.t('LoginView.Login')}</h2>
<LoginForm {...this.props} /> <LoginForm {...this.props} />
<h2 className="form-container__divider">Or</h2> <h2 className="form-container__divider">{this.props.t('LoginView.LoginOr')}</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">
Don&apos;t have an account?&nbsp; {this.props.t('LoginView.DontHaveAccount')}
<Link className="form__signup-button" to="/signup">Sign Up</Link> <Link className="form__signup-button" to="/signup">{this.props.t('LoginView.SignUp')}</Link>
</p> </p>
<p className="form__navigation-options"> <p className="form__navigation-options">
Forgot your password?&nbsp; {this.props.t('LoginView.ForgotPassword')}
<Link className="form__reset-password-button" to="/reset-password">Reset your password</Link> <Link className="form__reset-password-button" to="/reset-password"> {this.props.t('LoginView.ResetPassword')}</Link>
</p> </p>
</div> </div>
</main> </main>
@ -76,7 +78,8 @@ LoginView.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
}; };
LoginView.defaultProps = { LoginView.defaultProps = {
@ -85,8 +88,8 @@ LoginView.defaultProps = {
} }
}; };
export default reduxForm({ export default withTranslation()(reduxForm({
form: 'login', form: 'login',
fields: ['email', 'password'], fields: ['email', 'password'],
validate: validateLogin validate: validateLogin
}, mapStateToProps, mapDispatchToProps)(LoginView); }, mapStateToProps, mapDispatchToProps)(LoginView));

View file

@ -33,18 +33,9 @@
"Lang": "Language", "Lang": "Language",
"BackEditor": "Back to Editor", "BackEditor": "Back to Editor",
"WarningUnsavedChanges": "Are you sure you want to leave this page? You have unsaved changes.", "WarningUnsavedChanges": "Are you sure you want to leave this page? You have unsaved changes.",
"Login": { "Login": "Log in",
"Login": "Log in", "LoginOr": "or",
"LoginOr": "or", "SignUp": "Sign up",
"SignUp": "Sign up",
"Email": "email",
"Username": "username",
"LoginGithub": "Login with Github",
"LoginGoogle": "Login with Google",
"DontHaveAccount": "Don't have an account?",
"ForgotPassword": "Forgot your password?",
"ResetPassword": "Reset your password"
},
"Auth": { "Auth": {
"Welcome": "Welcome", "Welcome": "Welcome",
"Hello": "Hello", "Hello": "Hello",
@ -57,6 +48,29 @@
"LogOut": "Log Out" "LogOut": "Log Out"
} }
}, },
"LoginForm": {
"UsernameOrEmail": "Email or Username",
"UsernameOrEmailARIA": "Email or Username",
"Password": "Password",
"PasswordARIA": "Password",
"Submit": "Log In"
},
"LoginView": {
"Title": "p5.js Web Editor | Login",
"Login": "Log In",
"LoginOr": "or",
"SignUp": "Sign Up",
"Email": "email",
"Username": "username",
"DontHaveAccount": "Don't have an account? ",
"ForgotPassword": "Forgot your password? ",
"ResetPassword": "Reset your password"
},
"SocialAuthButton": {
"Github": "Login with Github",
"LogoARIA": "{{serviceauth}} logo",
"Google": "Login with Google"
},
"About": { "About": {
"Title": "About", "Title": "About",
"TitleHelmet": "p5.js Web Editor | About", "TitleHelmet": "p5.js Web Editor | About",

View file

@ -33,18 +33,9 @@
"Lang": "Lenguaje", "Lang": "Lenguaje",
"BackEditor": "Regresa al editor", "BackEditor": "Regresa al editor",
"WarningUnsavedChanges": "¿Realmente quieres salir de la página? Tienes cambios sin guardar.", "WarningUnsavedChanges": "¿Realmente quieres salir de la página? Tienes cambios sin guardar.",
"Login": { "Login": "Ingresa",
"Login": "Ingresa", "LoginOr": "o",
"LoginOr": "o", "SignUp": "Registráte",
"SignUp": "registráte",
"Email": "correo electrónico",
"Username": "Identificación",
"LoginGithub": "Ingresa con Github",
"LoginGoogle": "Ingresa con Google",
"DontHaveAccount": "¿No tienes cuenta?",
"ForgotPassword": "¿Olvidaste tu contraseña?",
"ResetPassword": "Regenera tu contraseña"
},
"Auth": { "Auth": {
"Welcome": "Hola", "Welcome": "Hola",
"Hello": "Hola", "Hello": "Hola",
@ -57,6 +48,29 @@
"LogOut": "Cerrar sesión" "LogOut": "Cerrar sesión"
} }
}, },
"LoginForm": {
"UsernameOrEmail": "Correo o Identificación",
"UsernameOrEmailARIA": "Introduce Correo o Identificación",
"Password": "Contraseña",
"PasswordARIA": "Contraseña",
"Submit": "Ingresa"
},
"LoginView": {
"Title": " Editor Web p5.js | Ingreso",
"Login": "Ingresa",
"LoginOr": "o",
"SignUp": "Registráte",
"Email": "correo electrónico",
"Username": "Identificación",
"DontHaveAccount": "¿No tienes cuenta? ",
"ForgotPassword": "¿Olvidaste tu contraseña? ",
"ResetPassword": "Regenera tu contraseña"
},
"SocialAuthButton": {
"Github": "Ingresa con Github",
"LogoARIA": "Logo de {{serviceauth}}",
"Google": "Ingresa con Google"
},
"About": { "About": {
"Title": "Acerca de", "Title": "Acerca de",
"TitleHelmet": "Editor Web p5.js | Acerca de", "TitleHelmet": "Editor Web p5.js | Acerca de",