diff options
Diffstat (limited to 'modern/src/components')
-rw-r--r-- | modern/src/components/registration/LoginForm.js | 170 | ||||
-rw-r--r-- | modern/src/components/registration/RegisterForm.js | 126 | ||||
-rw-r--r-- | modern/src/components/registration/ResetPasswordForm.js | 129 |
3 files changed, 0 insertions, 425 deletions
diff --git a/modern/src/components/registration/LoginForm.js b/modern/src/components/registration/LoginForm.js deleted file mode 100644 index 3d030a89..00000000 --- a/modern/src/components/registration/LoginForm.js +++ /dev/null @@ -1,170 +0,0 @@ -import React, { useState } from 'react'; -import { - Grid, useMediaQuery, makeStyles, InputLabel, Select, MenuItem, FormControl, Button, TextField, Link, Snackbar, IconButton, Tooltip, -} from '@material-ui/core'; -import CloseIcon from '@material-ui/icons/Close'; -import CachedIcon from '@material-ui/icons/Cached'; -import { useTheme } from '@material-ui/core/styles'; -import { useDispatch, useSelector } from 'react-redux'; -import { useHistory } from 'react-router-dom'; -import { sessionActions } from '../../store'; -import { useLocalization, useTranslation } from '../../LocalizationProvider'; -import StartPage from '../../StartPage'; -import usePersistedState from '../../common/usePersistedState'; - -const useStyles = makeStyles((theme) => ({ - legacy: { - position: 'absolute', - top: theme.spacing(1), - right: theme.spacing(1), - }, - logoContainer: { - textAlign: 'center', - color: theme.palette.primary.main, - }, - resetPassword: { - cursor: 'pointer', - }, -})); - -const LoginForm = () => { - const classes = useStyles(); - const dispatch = useDispatch(); - const history = useHistory(); - const theme = useTheme(); - const t = useTranslation(); - - const { languages, language, setLanguage } = useLocalization(); - const languageList = Object.entries(languages).map((values) => ({ code: values[0], name: values[1].name })); - - const [failed, setFailed] = useState(false); - - const [email, setEmail] = usePersistedState('loginEmail', ''); - const [password, setPassword] = useState(''); - - const registrationEnabled = useSelector((state) => state.session.server?.registration); - const emailEnabled = useSelector((state) => state.session.server?.emailEnabled); - - const [announcementShown, setAnnouncementShown] = useState(false); - const announcement = useSelector((state) => state.session.server?.announcement); - - const handleSubmit = async (event) => { - event.preventDefault(); - const response = await fetch('/api/session', { - method: 'POST', - body: new URLSearchParams(`email=${encodeURIComponent(email)}&password=${encodeURIComponent(password)}`), - }); - if (response.ok) { - const user = await response.json(); - dispatch(sessionActions.updateUser(user)); - history.push('/'); - } else { - setFailed(true); - setPassword(''); - } - }; - - const handleSpecialKey = (e) => { - if (e.keyCode === 13 && email && password) { - handleSubmit(e); - } - }; - - return ( - <StartPage> - <Tooltip title="Switch to Legacy App" className={classes.legacy}> - <IconButton onClick={() => window.localStorage.setItem('legacyApp', true) || window.location.replace('/')}> - <CachedIcon /> - </IconButton> - </Tooltip> - <Grid container direction="column" spacing={2}> - {useMediaQuery(theme.breakpoints.down('md')) - && ( - <Grid item className={classes.logoContainer}> - <svg height="64" width="240"> - <use xlinkHref="/logo.svg#img" /> - </svg> - </Grid> - )} - <Grid item> - <TextField - required - fullWidth - error={failed} - label={t('userEmail')} - name="email" - value={email} - autoComplete="email" - autoFocus={!email} - onChange={(e) => setEmail(e.target.value)} - onKeyUp={handleSpecialKey} - helperText={failed && 'Invalid username or password'} - variant="filled" - /> - </Grid> - <Grid item> - <TextField - required - fullWidth - error={failed} - label={t('userPassword')} - name="password" - value={password} - type="password" - autoComplete="current-password" - autoFocus={!!email} - onChange={(e) => setPassword(e.target.value)} - onKeyUp={handleSpecialKey} - variant="filled" - /> - </Grid> - <Grid item> - <Button - onClick={handleSubmit} - onKeyUp={handleSpecialKey} - variant="contained" - color="secondary" - disabled={!email || !password} - fullWidth - > - {t('loginLogin')} - </Button> - </Grid> - <Grid item container spacing={2}> - <Grid item> - <Button onClick={() => history.push('/register')} disabled={!registrationEnabled} color="secondary"> - {t('loginRegister')} - </Button> - </Grid> - <Grid item xs> - <FormControl variant="filled" fullWidth> - <InputLabel>{t('loginLanguage')}</InputLabel> - <Select value={language} onChange={(e) => setLanguage(e.target.value)}> - {languageList.map((it) => <MenuItem key={it.code} value={it.code}>{it.name}</MenuItem>)} - </Select> - </FormControl> - </Grid> - </Grid> - {emailEnabled && ( - <Grid item container justifyContent="flex-end"> - <Grid item> - <Link onClick={() => history.push('/reset-password')} className={classes.resetPassword} underline="none">{t('loginReset')}</Link> - </Grid> - </Grid> - )} - <Snackbar - anchorOrigin={{ vertical: 'top', horizontal: 'center' }} - open={!!announcement && !announcementShown} - message={announcement} - action={( - <IconButton size="small" color="inherit" onClick={() => setAnnouncementShown(true)}> - <CloseIcon fontSize="small" /> - </IconButton> - )} - /> - </Grid> - </StartPage> - ); -}; - -export default LoginForm; diff --git a/modern/src/components/registration/RegisterForm.js b/modern/src/components/registration/RegisterForm.js deleted file mode 100644 index 11dd510e..00000000 --- a/modern/src/components/registration/RegisterForm.js +++ /dev/null @@ -1,126 +0,0 @@ -import React, { useState } from 'react'; -import { - Grid, Button, TextField, Typography, Link, makeStyles, Snackbar, -} from '@material-ui/core'; -import { useHistory } from 'react-router-dom'; -import ArrowBackIcon from '@material-ui/icons/ArrowBack'; -import StartPage from '../../StartPage'; -import { useTranslation } from '../../LocalizationProvider'; -import { snackBarDurationShortMs } from '../../common/duration'; - -const useStyles = makeStyles((theme) => ({ - title: { - fontSize: theme.spacing(3), - fontWeight: 500, - marginLeft: theme.spacing(2), - textTransform: 'uppercase', - }, - link: { - fontSize: theme.spacing(3), - fontWeight: 500, - marginTop: theme.spacing(0.5), - cursor: 'pointer', - }, -})); - -const RegisterForm = () => { - const classes = useStyles(); - const history = useHistory(); - const t = useTranslation(); - - const [name, setName] = useState(''); - const [email, setEmail] = useState(''); - const [password, setPassword] = useState(''); - const [snackbarOpen, setSnackbarOpen] = useState(false); - - const handleSubmit = async () => { - const response = await fetch('/api/users', { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ name, email, password }), - }); - if (response.ok) { - setSnackbarOpen(true); - } - }; - - return ( - <StartPage> - <Snackbar - anchorOrigin={{ vertical: 'top', horizontal: 'center' }} - open={snackbarOpen} - onClose={() => history.push('/login')} - autoHideDuration={snackBarDurationShortMs} - message={t('loginCreated')} - /> - <Grid container direction="column" spacing={2}> - <Grid container item> - <Grid item> - <Typography className={classes.link} color="primary"> - <Link onClick={() => history.push('/login')}> - <ArrowBackIcon /> - </Link> - </Typography> - </Grid> - <Grid item xs> - <Typography className={classes.title} color="primary"> - {t('loginRegister')} - </Typography> - </Grid> - </Grid> - <Grid item> - <TextField - required - fullWidth - label={t('sharedName')} - name="name" - value={name} - autoComplete="name" - autoFocus - onChange={(event) => setName(event.target.value)} - variant="filled" - /> - </Grid> - <Grid item> - <TextField - required - fullWidth - type="email" - label={t('userEmail')} - name="email" - value={email} - autoComplete="email" - onChange={(event) => setEmail(event.target.value)} - variant="filled" - /> - </Grid> - <Grid item> - <TextField - required - fullWidth - label={t('userPassword')} - name="password" - value={password} - type="password" - autoComplete="current-password" - onChange={(event) => setPassword(event.target.value)} - variant="filled" - /> - </Grid> - <Grid item> - <Button - variant="contained" - color="secondary" - onClick={handleSubmit} - disabled={!name || !/(.+)@(.+)\.(.{2,})/.test(email) || !password} - fullWidth - > - {t('loginRegister')} - </Button> - </Grid> - </Grid> - </StartPage> - ); -}; - -export default RegisterForm; diff --git a/modern/src/components/registration/ResetPasswordForm.js b/modern/src/components/registration/ResetPasswordForm.js deleted file mode 100644 index 6c41a9ea..00000000 --- a/modern/src/components/registration/ResetPasswordForm.js +++ /dev/null @@ -1,129 +0,0 @@ -import React, { useState } from 'react'; -import { - Grid, Button, TextField, Typography, Link, makeStyles, Snackbar, -} from '@material-ui/core'; -import { useHistory } from 'react-router-dom'; -import ArrowBackIcon from '@material-ui/icons/ArrowBack'; -import StartPage from '../../StartPage'; -import { useTranslation } from '../../LocalizationProvider'; -import useQuery from '../../common/useQuery'; -import { snackBarDurationShortMs } from '../../common/duration'; - -const useStyles = makeStyles((theme) => ({ - title: { - fontSize: theme.spacing(3), - fontWeight: 500, - marginLeft: theme.spacing(2), - textTransform: 'uppercase', - }, - link: { - fontSize: theme.spacing(3), - fontWeight: 500, - marginTop: theme.spacing(0.5), - cursor: 'pointer', - }, -})); - -const ResetPasswordForm = () => { - const classes = useStyles(); - const history = useHistory(); - const t = useTranslation(); - const query = useQuery(); - - const token = query.get('passwordReset'); - - const [email, setEmail] = useState(''); - const [password, setPassword] = useState(''); - const [snackbarOpen, setSnackbarOpen] = useState(false); - - const handleSubmit = async (event) => { - event.preventDefault(); - let response; - if (!token) { - response = await fetch('/api/password/reset', { - method: 'POST', - body: new URLSearchParams(`email=${encodeURIComponent(email)}`), - }); - } else { - response = await fetch('/api/password/update', { - method: 'POST', - body: new URLSearchParams(`token=${encodeURIComponent(token)}&password=${encodeURIComponent(password)}`), - }); - } - if (response.ok) { - setSnackbarOpen(true); - } - }; - - return ( - <StartPage> - <Snackbar - anchorOrigin={{ vertical: 'top', horizontal: 'center' }} - open={snackbarOpen} - onClose={() => history.push('/login')} - autoHideDuration={snackBarDurationShortMs} - message={!token ? t('loginResetSuccess') : t('loginUpdateSuccess')} - /> - <Grid container direction="column" spacing={2}> - <Grid container item> - <Grid item> - <Typography className={classes.link} color="primary"> - <Link onClick={() => history.push('/login')}> - <ArrowBackIcon /> - </Link> - </Typography> - </Grid> - <Grid item xs> - <Typography className={classes.title} color="primary"> - {t('loginReset')} - </Typography> - </Grid> - </Grid> - {!token - ? ( - <Grid item> - <TextField - required - fullWidth - type="email" - label={t('userEmail')} - name="email" - value={email} - autoComplete="email" - onChange={(event) => setEmail(event.target.value)} - variant="filled" - /> - </Grid> - ) - : ( - <Grid item> - <TextField - required - fullWidth - label={t('userPassword')} - name="password" - value={password} - type="password" - autoComplete="current-password" - onChange={(event) => setPassword(event.target.value)} - variant="filled" - /> - </Grid> - )} - <Grid item> - <Button - variant="contained" - color="secondary" - onClick={handleSubmit} - disabled={!/(.+)@(.+)\.(.{2,})/.test(email) && !password} - fullWidth - > - {t('loginReset')} - </Button> - </Grid> - </Grid> - </StartPage> - ); -}; - -export default ResetPasswordForm; |