Passwords: add and use a new PasswordField widget.
parent
3ea16cd0d9
commit
12f5f482cd
|
@ -12,6 +12,7 @@ import Switch from "@material-ui/core/Switch";
|
||||||
import { routeResolver } from "./App";
|
import { routeResolver } from "./App";
|
||||||
|
|
||||||
import Container from "./widgets/Container";
|
import Container from "./widgets/Container";
|
||||||
|
import PasswordField from "./widgets/PasswordField";
|
||||||
|
|
||||||
import LoadingIndicator from "./widgets/LoadingIndicator";
|
import LoadingIndicator from "./widgets/LoadingIndicator";
|
||||||
import Alert from "@material-ui/lab/Alert";
|
import Alert from "@material-ui/lab/Alert";
|
||||||
|
@ -122,8 +123,12 @@ export default function SignupPage() {
|
||||||
const styles = {
|
const styles = {
|
||||||
form: {
|
form: {
|
||||||
},
|
},
|
||||||
|
infoAlert: {
|
||||||
|
marginTop: 20,
|
||||||
|
},
|
||||||
textField: {
|
textField: {
|
||||||
marginTop: 20,
|
marginTop: 20,
|
||||||
|
width: "18em",
|
||||||
},
|
},
|
||||||
submit: {
|
submit: {
|
||||||
marginTop: 40,
|
marginTop: 40,
|
||||||
|
@ -189,14 +194,15 @@ export default function SignupPage() {
|
||||||
onChange={handleInputChange(setEmail)}
|
onChange={handleInputChange(setEmail)}
|
||||||
/>
|
/>
|
||||||
<br />
|
<br />
|
||||||
<TextField
|
<PasswordField
|
||||||
type="password"
|
|
||||||
style={styles.textField}
|
style={styles.textField}
|
||||||
error={!!errors.errorPassword}
|
error={!!errors.errorPassword}
|
||||||
helperText={errors.errorPassword}
|
helperText={errors.errorPassword}
|
||||||
label="Password"
|
label="Password"
|
||||||
name="password"
|
name="password"
|
||||||
inputProps={{ minLength: PASSWORD_MIN_LENGTH }}
|
inputProps={{
|
||||||
|
minLength: PASSWORD_MIN_LENGTH,
|
||||||
|
}}
|
||||||
value={password}
|
value={password}
|
||||||
onChange={handleInputChange(setPassword)}
|
onChange={handleInputChange(setPassword)}
|
||||||
/>
|
/>
|
||||||
|
@ -215,10 +221,10 @@ export default function SignupPage() {
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
{advancedSettings}
|
{advancedSettings}
|
||||||
{errors.errorGeneral && (
|
{errors.errorGeneral && (
|
||||||
<Alert severity="error" style={styles.textField}>{errors.errorGeneral}</Alert>
|
<Alert severity="error" style={styles.infoAlert}>{errors.errorGeneral}</Alert>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<Alert severity="warning" style={styles.textField}>
|
<Alert severity="warning" style={styles.infoAlert}>
|
||||||
Please make sure you remember your password, as it <em>can't</em> be recovered if lost!
|
Please make sure you remember your password, as it <em>can't</em> be recovered if lost!
|
||||||
</Alert>
|
</Alert>
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,7 @@ import FormControlLabel from "@material-ui/core/FormControlLabel";
|
||||||
import Switch from "@material-ui/core/Switch";
|
import Switch from "@material-ui/core/Switch";
|
||||||
|
|
||||||
import ExternalLink from "../widgets/ExternalLink";
|
import ExternalLink from "../widgets/ExternalLink";
|
||||||
|
import PasswordField from "../widgets/PasswordField";
|
||||||
|
|
||||||
import * as C from "../constants";
|
import * as C from "../constants";
|
||||||
import LoadingIndicator from "../widgets/LoadingIndicator";
|
import LoadingIndicator from "../widgets/LoadingIndicator";
|
||||||
|
@ -67,8 +68,12 @@ export default function LoginForm(props: PropsType) {
|
||||||
forgotPassword: {
|
forgotPassword: {
|
||||||
paddingTop: 20,
|
paddingTop: 20,
|
||||||
},
|
},
|
||||||
|
infoAlert: {
|
||||||
|
marginTop: 20,
|
||||||
|
},
|
||||||
textField: {
|
textField: {
|
||||||
marginTop: 20,
|
marginTop: 20,
|
||||||
|
width: "18em",
|
||||||
},
|
},
|
||||||
submit: {
|
submit: {
|
||||||
marginTop: 40,
|
marginTop: 40,
|
||||||
|
@ -122,8 +127,7 @@ export default function LoginForm(props: PropsType) {
|
||||||
onChange={handleInputChange(setUsername)}
|
onChange={handleInputChange(setUsername)}
|
||||||
/>
|
/>
|
||||||
<br />
|
<br />
|
||||||
<TextField
|
<PasswordField
|
||||||
type="password"
|
|
||||||
style={styles.textField}
|
style={styles.textField}
|
||||||
error={!!errors.errorPassword}
|
error={!!errors.errorPassword}
|
||||||
helperText={errors.errorPassword}
|
helperText={errors.errorPassword}
|
||||||
|
@ -150,7 +154,7 @@ export default function LoginForm(props: PropsType) {
|
||||||
{advancedSettings}
|
{advancedSettings}
|
||||||
|
|
||||||
{props.error && (
|
{props.error && (
|
||||||
<Alert severity="error" style={styles.textField}>{props.error.message}</Alert>
|
<Alert severity="error" style={styles.infoAlert}>{props.error.message}</Alert>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<div style={styles.submit}>
|
<div style={styles.submit}>
|
||||||
|
|
|
@ -0,0 +1,44 @@
|
||||||
|
// SPDX-FileCopyrightText: © 2017 EteSync Authors
|
||||||
|
// SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
|
import * as React from "react";
|
||||||
|
import Input, { InputProps } from "@material-ui/core/Input";
|
||||||
|
import InputLabel from "@material-ui/core/InputLabel";
|
||||||
|
import InputAdornment from "@material-ui/core/InputAdornment";
|
||||||
|
import FormHelperText from "@material-ui/core/FormHelperText";
|
||||||
|
import IconButton from "@material-ui/core/IconButton";
|
||||||
|
import FormControl from "@material-ui/core/FormControl";
|
||||||
|
import Visibility from "@material-ui/icons/Visibility";
|
||||||
|
import VisibilityOff from "@material-ui/icons/VisibilityOff";
|
||||||
|
|
||||||
|
let formIdCounter = 0;
|
||||||
|
|
||||||
|
export default function PasswordField(props_: Omit<InputProps, "type"> & { helperText?: string, label?: string }) {
|
||||||
|
const [showPassword, setShowPassword] = React.useState(false);
|
||||||
|
const formId_ = React.useMemo(() => formIdCounter++, []);
|
||||||
|
const { helperText, label, style, id, ...props } = props_;
|
||||||
|
const formId = `password-field-${id ?? formId_}`;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<FormControl style={style}>
|
||||||
|
<InputLabel htmlFor={formId}>{label}</InputLabel>
|
||||||
|
<Input
|
||||||
|
{...props}
|
||||||
|
id={formId}
|
||||||
|
type={showPassword ? "text" : "password"}
|
||||||
|
endAdornment={(
|
||||||
|
<InputAdornment position="end">
|
||||||
|
<IconButton
|
||||||
|
aria-label="Toggle password visibility"
|
||||||
|
title="Toggle password visibility"
|
||||||
|
onClick={() => setShowPassword(!showPassword)}
|
||||||
|
>
|
||||||
|
{showPassword ? <Visibility /> : <VisibilityOff />}
|
||||||
|
</IconButton>
|
||||||
|
</InputAdornment>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
<FormHelperText id={formId}>{helperText}</FormHelperText>
|
||||||
|
</FormControl>
|
||||||
|
);
|
||||||
|
}
|
Loading…
Reference in New Issue