all repos — caroster @ 03af7a10d52de5dfb6a7932411f389d37ea10d02

[Octree] Group carpool to your event https://caroster.io

merge masteer
Hadrien Froger hadrien@octree.ch
Mon, 07 Sep 2020 09:25:49 +0100
commit

03af7a10d52de5dfb6a7932411f389d37ea10d02

parent

00bb60ac613a07e402f536eb72696a8983451cdd

M DockerfileDockerfile

@@ -1,7 +1,9 @@

# Build stage FROM strapi/base:12-alpine -ARG NPM_REGISTRY=https://npm-8ee.hidora.com/ +ARG VERSION +ENV VERSION ${VERSION:-dev} +ENV NPM_REGISTRY https://npm-8ee.hidora.com/ ENV NODE_ENV production WORKDIR /srv/app
M app/package-lock.jsonapp/package-lock.json

@@ -2570,6 +2570,12 @@ "version": "1.10.0",

"resolved": "https://npm-8ee.hidora.com/aws4/-/aws4-1.10.0.tgz", "integrity": "sha512-3YDiu347mtVtjpyV3u5kVqQLP242c06zwDOgpeRnybmXlYYsLbtTrUBUm8i8srONt+FWobl5aibnU1030PeeuA==" }, + "axe-core": { + "version": "3.5.5", + "resolved": "https://npm-8ee.hidora.com/axe-core/-/axe-core-3.5.5.tgz", + "integrity": "sha512-5P0QZ6J5xGikH780pghEdbEKijCTrruK9KxtPZCFWUpef0f6GipO+xEZ5GKCb020mmqgbiNO6TcA55CriL784Q==", + "dev": true + }, "axobject-query": { "version": "2.2.0", "resolved": "https://npm-8ee.hidora.com/axobject-query/-/axobject-query-2.2.0.tgz",

@@ -10734,6 +10740,16 @@ "regenerator-runtime": "^0.13.3",

"whatwg-fetch": "^3.0.0" } }, + "react-axe": { + "version": "3.5.3", + "resolved": "https://npm-8ee.hidora.com/react-axe/-/react-axe-3.5.3.tgz", + "integrity": "sha512-WDKAoLVsC6rsmYboXThY7OnVDaQOOOecySHJJjggn1cFOJyWtzNh2uiV3oSxoAolONGTi22G9zKDxw53g/8Vqg==", + "dev": true, + "requires": { + "axe-core": "^3.5.0", + "requestidlecallback": "^0.3.0" + } + }, "react-dev-utils": { "version": "10.2.1", "resolved": "https://npm-8ee.hidora.com/react-dev-utils/-/react-dev-utils-10.2.1.tgz",

@@ -10946,6 +10962,22 @@ "version": "6.0.7",

"resolved": "https://npm-8ee.hidora.com/react-error-overlay/-/react-error-overlay-6.0.7.tgz", "integrity": "sha512-TAv1KJFh3RhqxNvhzxj6LeT5NWklP6rDr2a0jaTfsZ5wSZWHOGeqQyejUp3xxLfPt2UpyJEcVQB/zyPcmonNFA==" }, + "react-fast-compare": { + "version": "3.2.0", + "resolved": "https://npm-8ee.hidora.com/react-fast-compare/-/react-fast-compare-3.2.0.tgz", + "integrity": "sha512-rtGImPZ0YyLrscKI9xTpV8psd6I8VAtjKCzQDlzyDvqJA8XOW78TXYQwNRNd8g8JZnDu8q9Fu/1v4HPAVwVdHA==" + }, + "react-helmet": { + "version": "6.1.0", + "resolved": "https://npm-8ee.hidora.com/react-helmet/-/react-helmet-6.1.0.tgz", + "integrity": "sha512-4uMzEY9nlDlgxr61NL3XbKRy1hEkXmKNXhjbAIOVw5vcFrsdYbH2FEwcNyWvWinl103nXgzYNlns9ca+8kFiWw==", + "requires": { + "object-assign": "^4.1.1", + "prop-types": "^15.7.2", + "react-fast-compare": "^3.1.1", + "react-side-effect": "^2.1.0" + } + }, "react-i18next": { "version": "11.7.0", "resolved": "https://npm-8ee.hidora.com/react-i18next/-/react-i18next-11.7.0.tgz",

@@ -11050,6 +11082,11 @@ "webpack-dev-server": "3.10.3",

"webpack-manifest-plugin": "2.2.0", "workbox-webpack-plugin": "4.3.1" } + }, + "react-side-effect": { + "version": "2.1.0", + "resolved": "https://npm-8ee.hidora.com/react-side-effect/-/react-side-effect-2.1.0.tgz", + "integrity": "sha512-IgmcegOSi5SNX+2Snh1vqmF0Vg/CbkycU9XZbOHJlZ6kMzTmi3yc254oB1WCkgA7OQtIAoLmcSFuHTc/tlcqXg==" }, "react-slick": { "version": "0.26.1",

@@ -11351,6 +11388,12 @@ "request-promise-core": "1.1.3",

"stealthy-require": "^1.1.1", "tough-cookie": "^2.3.3" } + }, + "requestidlecallback": { + "version": "0.3.0", + "resolved": "https://npm-8ee.hidora.com/requestidlecallback/-/requestidlecallback-0.3.0.tgz", + "integrity": "sha1-b7dOBzP5DfP6pIOPn2oqX5t0KsU=", + "dev": true }, "require-directory": { "version": "2.1.1",
M app/package.jsonapp/package.json

@@ -16,6 +16,7 @@ "marked": "^1.1.0",

"moment": "^2.27.0", "react": "^16.13.1", "react-dom": "^16.13.1", + "react-helmet": "^6.1.0", "react-i18next": "^11.7.0", "react-router-dom": "^5.2.0", "react-scripts": "3.4.1",

@@ -46,6 +47,7 @@ ]

}, "devDependencies": { "eslint-config-google": "^0.14.0", + "react-axe": "^3.5.3", "react-test-renderer": "^16.13.1" } }
A app/src/assets/google-icon.svg

@@ -0,0 +1,1 @@

+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48" width="48px" height="48px"><path fill="#FFC107" d="M43.611,20.083H42V20H24v8h11.303c-1.649,4.657-6.08,8-11.303,8c-6.627,0-12-5.373-12-12c0-6.627,5.373-12,12-12c3.059,0,5.842,1.154,7.961,3.039l5.657-5.657C34.046,6.053,29.268,4,24,4C12.955,4,4,12.955,4,24c0,11.045,8.955,20,20,20c11.045,0,20-8.955,20-20C44,22.659,43.862,21.35,43.611,20.083z"/><path fill="#FF3D00" d="M6.306,14.691l6.571,4.819C14.655,15.108,18.961,12,24,12c3.059,0,5.842,1.154,7.961,3.039l5.657-5.657C34.046,6.053,29.268,4,24,4C16.318,4,9.656,8.337,6.306,14.691z"/><path fill="#4CAF50" d="M24,44c5.166,0,9.86-1.977,13.409-5.192l-6.19-5.238C29.211,35.091,26.715,36,24,36c-5.202,0-9.619-3.317-11.283-7.946l-6.522,5.025C9.505,39.556,16.227,44,24,44z"/><path fill="#1976D2" d="M43.611,20.083H42V20H24v8h11.303c-0.792,2.237-2.231,4.166-4.087,5.571c0.001-0.001,0.002-0.001,0.003-0.002l6.19,5.238C36.971,39.205,44,34,44,24C44,22.659,43.862,21.35,43.611,20.083z"/></svg>
M app/src/containers/LoginGoogle/index.jsapp/src/containers/LoginGoogle/index.js

@@ -3,14 +3,19 @@ import CardContent from '@material-ui/core/CardContent';

import {useTranslation} from 'react-i18next'; import {makeStyles} from '@material-ui/core/styles'; import Button from '@material-ui/core/Button'; - +import {ReactComponent as GoogleIcon} from '../../assets/google-icon.svg'; const LoginGoogle = () => { const {t} = useTranslation(); const classes = useStyles(); return ( <CardContent className={classes.content}> - <Button variant="contained" color="primary" href="/connect/google"> + <Button + variant="outlined" + color="primary" + href="/connect/google" + startIcon={<GoogleIcon className={classes.googleIcon} />} + > {t('signin.withGoogle')} </Button> </CardContent>

@@ -23,6 +28,10 @@ display: 'flex',

flexDirection: 'column', alignItems: 'center', padding: theme.spacing(4, 0), + }, + googleIcon: { + height: 32, + width: 32, }, }));
M app/src/containers/SignInForm/index.jsapp/src/containers/SignInForm/index.js

@@ -8,7 +8,8 @@ import Button from '@material-ui/core/Button';

import Link from '@material-ui/core/Link'; import Typography from '@material-ui/core/Typography'; import CardContent from '@material-ui/core/CardContent'; -import {CircularProgress} from '@material-ui/core'; +import CircularProgress from '@material-ui/core/CircularProgress'; +import FormHelperText from '@material-ui/core/FormHelperText'; import CardActions from '@material-ui/core/CardActions'; import {makeStyles} from '@material-ui/core/styles'; import {useToast} from '../../contexts/Toast';

@@ -76,6 +77,7 @@ return (

<form onSubmit={onSubmit}> <CardContent className={classes.content}> <Typography variant="h6">{t('signin.title')}</Typography> + {error && <FormHelperText error={true}>{error}</FormHelperText>} <TextField label={t('signin.email')} fullWidth

@@ -87,7 +89,6 @@ id="SignInEmail"

name="email" type="email" error={!!error} - helperText={error} /> <TextField label={t('signin.password')}

@@ -100,16 +101,18 @@ id="SignInEmail"

name="password" type="password" error={!!error} - helperText={ - error && ( - <RouterLink to="/lost-password" component={Link}> - {t('lost_password.message')} - </RouterLink> - ) - } + gutterBottom /> + <RouterLink to="/reset-password" component={Link}> + <Typography align="center" variant="body2"> + {t('lost_password.message')} + </Typography> + </RouterLink> </CardContent> - <CardActions className={classes.actions}> + <CardActions className={classes.actions} align="center"> + <Button id="SignInRegister" href="/register" size="small"> + {t('signin.register')} + </Button> <Button color="primary" variant="contained"

@@ -117,16 +120,13 @@ type="submit"

disabled={!canSubmit} aria-disabled={!canSubmit} id="SignInSubmit" - fullWidth + endIcon={ + isLoading && ( + <CircularProgress className={classes.loader} size={20} /> + ) + } > - {isLoading ? ( - <CircularProgress className={classes.loader} size={20} /> - ) : ( - t('signin.login') - )} - </Button> - <Button id="SignInRegister" href="/register" fullWidth size="small"> - {t('signin.register')} + {t('signin.login')} </Button> </CardActions> </form>

@@ -141,11 +141,11 @@ alignItems: 'center',

}, loader: { marginLeft: '14px', + color: theme.palette.background.paper, }, actions: { - display: 'flex', - flexDirection: 'column', - alignItems: 'center', + justifyContent: 'center', + marginBottom: theme.spacing(2), }, })); export default SignIn;
M app/src/containers/SignUpForm/index.jsapp/src/containers/SignUpForm/index.js

@@ -8,7 +8,7 @@ import CardActions from '@material-ui/core/CardActions';

import Typography from '@material-ui/core/Typography'; import {useToast} from '../../contexts/Toast'; import {Redirect} from 'react-router-dom'; -import {CircularProgress} from '@material-ui/core'; +import CircularProgress from '@material-ui/core/CircularProgress'; import {makeStyles} from '@material-ui/core/styles'; import {useHistory} from 'react-router-dom';

@@ -22,6 +22,7 @@ } = history;

const {signUp, token} = useAuth(); const [isLoading, setIsLoading] = useState(false); + const [error, setError] = useState(''); const [firstName, setFirstName] = useState(''); const [lastName, setLastName] = useState(''); const [email, setEmail] = useState('');

@@ -29,7 +30,7 @@ const [password, setPassword] = useState('');

const canSubmit = useMemo( () => - [firstName, lastName, email, password].filter(s => s.length < 4) + [firstName, lastName, email, password].filter(s => s.length < 2) .length === 0, [firstName, lastName, email, password] );

@@ -46,9 +47,9 @@ lastName,

events: historyState.event ? [historyState.event] : [], }); } catch (error) { - if (error.kind && error.kind === 'bad_data') - addToast(t('signup.errors.email_taken')); - else if (error.kind) { + if (error.kind && error.kind === 'bad_data') { + setError(t('signup.errors.email_taken')); + } else if (error.kind) { addToast(t(`generic.errors.${error.kind}`)); } else { addToast(t(`generic.errors.unknown`));

@@ -91,6 +92,8 @@ <TextField

label={t('signup.email')} fullWidth required={true} + error={!!error} + helperText={error} margin="dense" value={email} onChange={({target: {value = ''}}) => setEmail(value)}

@@ -101,6 +104,7 @@ />

<TextField label={t('signup.password')} fullWidth + gutterBottom required={true} margin="dense" value={password}

@@ -111,27 +115,28 @@ type="password"

/> </CardContent> <CardActions className={classes.actions}> + <Button id="SignUpLogin" href="/login" variant="text"> + {t('signup.login')} + </Button> <Button color="primary" variant="contained" type="submit" disabled={!canSubmit} className={classes.button} - fullWidth aria-disabled={!canSubmit} id="SignUpSubmit" + iconEnd={ + isLoading && ( + <CircularProgress + class={classes.loader} + size={20} + color="secondary" + /> + ) + } > {t('signup.submit')} - {isLoading && ( - <CircularProgress - class={classes.loader} - size={20} - color="secondary" - /> - )} - </Button> - <Button id="SignUpLogin" href="/login" fullWidth> - {t('signup.login')} </Button> </CardActions> </form>

@@ -146,11 +151,11 @@ alignItems: 'center',

}, loader: { marginLeft: '14px', + color: theme.palette.background.paper, }, actions: { - display: 'flex', - flexDirection: 'column', - alignItems: 'center', + justifyContent: 'center', + marginBottom: theme.spacing(2), }, button: { margin: theme.spacing(1),
M app/src/index.jsapp/src/index.js

@@ -6,6 +6,15 @@ import 'moment/locale/fr-ch';

import * as serviceWorker from './serviceWorker'; import App from './App'; +if (process.env.NODE_ENV !== 'production') { + // Require to not be embed in production builds + const axe = require('react-axe'); + const {config} = require('./setupA11y'); + // Throws some accessibility warning on rendered DOM. + // @see https://github.com/dequelabs/react-axe + axe(React, ReactDOM, 1000, config); +} + ReactDOM.render( <React.StrictMode> <App />
M app/src/layouts/Default.jsapp/src/layouts/Default.js

@@ -1,4 +1,5 @@

import React from 'react'; +import {Helmet} from 'react-helmet'; import GenericMenu from '../containers/GenericMenu'; const DefaultLayout = ({

@@ -6,11 +7,16 @@ children,

className, menuTitle = 'Caroster', menuActions, + pageTitle = undefined, + displayMenu = true, goBack = false, }) => { return ( <> - {(menuTitle || menuActions) && ( + <Helmet> + <title>{pageTitle || menuTitle}</title> + </Helmet> + {displayMenu && (menuTitle || menuActions) && ( <GenericMenu title={menuTitle} actions={menuActions} goBack={goBack} /> )} <div className={className}>{children}</div>
M app/src/locales/fr.jsonapp/src/locales/fr.json

@@ -167,7 +167,7 @@ "firstName": "Prénom",

"lastName": "Nom", "password": "Mot de passe", "submit": "Créer son compte", - "login": "Déjà un compte ?", + "login": "Se connecter", "errors": { "email_taken": "Email déjà pris" },

@@ -185,7 +185,7 @@ "password": "Mot de passe",

"login": "Se connecter", "register": "S'inscrire", "errors": "Vérifier votre email et mot de passe", - "withGoogle": "Se connecter avec Google" + "withGoogle": "Utiliser un compte Google" }, "lost_password": { "title": "Récupération de mot de passe",
M app/src/pages/Event.jsapp/src/pages/Event.js

@@ -46,7 +46,11 @@

if (!event) return <Loading />; return ( - <Layout> + <Layout + pageTitle={t('event.title')} + menuTitle={t('meta.title', {title: event.name})} + displayMenu={false} + > <EventBar event={event} isEditing={isEditing}
M app/src/pages/SignIn.jsapp/src/pages/SignIn.js

@@ -14,10 +14,9 @@ return (

<Layout menuTitle={t('signin.title')}> <Card> <CardMedia component={Logo} /> + <SignInForm /> <Divider /> <LoginGoogle /> - <Divider /> - <SignInForm /> </Card> </Layout> );
M app/src/pages/SignUp.jsapp/src/pages/SignUp.js

@@ -14,10 +14,9 @@ return (

<Layout menuTitle={t('signup.title')}> <Card> <CardMedia component={Logo} /> + <SignUpForm /> <Divider /> <LoginGoogle /> - <Divider /> - <SignUpForm /> </Card> </Layout> );
D app/src/pages/__snapshots__/Profile.test.js.snap

@@ -1,17 +0,0 @@

-// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Profile page match snapshot 1`] = ` -<div> - <div - className="makeStyles-layout-1" - > - <div - className="MuiContainer-root MuiContainer-maxWidthSm" - > - <div> - Mon ami - </div> - </div> - </div> -</div> -`;
D app/src/pages/__snapshots__/SignIn.test.js.snap

@@ -1,35 +0,0 @@

-// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`SignIn page match snapshot 1`] = ` -<div> - <div - className="makeStyles-layout-1" - > - <div - className="MuiContainer-root MuiContainer-maxWidthSm" - > - <div - className="MuiPaper-root MuiCard-root MuiPaper-elevation1 MuiPaper-rounded" - > - <div - className="makeStyles-layout-2" - > - <a - className="makeStyles-link-3" - href="https://caroster.io" - > - <img - alt="Caroster" - className="makeStyles-logo-4" - src="logo.png" - /> - </a> - </div> - <span> - /containers/SignIn component - </span> - </div> - </div> - </div> -</div> -`;
D app/src/pages/__snapshots__/SignUp.test.js.snap

@@ -1,35 +0,0 @@

-// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`SignUp page match snapshot 1`] = ` -<div> - <div - className="makeStyles-layout-1" - > - <div - className="MuiContainer-root MuiContainer-maxWidthSm" - > - <div - className="MuiPaper-root MuiCard-root MuiPaper-elevation1 MuiPaper-rounded" - > - <div - className="makeStyles-layout-2" - > - <a - className="makeStyles-link-3" - href="https://caroster.io" - > - <img - alt="Caroster" - className="makeStyles-logo-4" - src="logo.png" - /> - </a> - </div> - <span> - /containers/SignUp component - </span> - </div> - </div> - </div> -</div> -`;
A app/src/setupA11y.js

@@ -0,0 +1,24 @@

+export const config = { + rules: [ + { + id: 'landmark-one-main', + enabled: false, + }, + { + id: 'page-has-heading-one', + enabled: false, + }, + { + id: 'region', + enabled: false, + }, + { + id: 'color-contrast', + enabled: false, + }, + { + id: 'button-name', + enabled: false, + }, + ], +};