Add Signup page.
parent
99016871de
commit
6970ebc503
@ -0,0 +1,218 @@
|
||||
// SPDX-FileCopyrightText: © 2017 EteSync Authors
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import * as React from "react";
|
||||
import * as Etebase from "etebase";
|
||||
import Button from "@material-ui/core/Button";
|
||||
import TextField from "@material-ui/core/TextField";
|
||||
import FormGroup from "@material-ui/core/FormGroup";
|
||||
import FormControlLabel from "@material-ui/core/FormControlLabel";
|
||||
import Switch from "@material-ui/core/Switch";
|
||||
|
||||
import { routeResolver } from "./App";
|
||||
|
||||
import ExternalLink from "./widgets/ExternalLink";
|
||||
import Container from "./widgets/Container";
|
||||
|
||||
import * as C from "./constants";
|
||||
import LoadingIndicator from "./widgets/LoadingIndicator";
|
||||
import Alert from "@material-ui/lab/Alert";
|
||||
import { CircularProgress } from "@material-ui/core";
|
||||
import { Redirect } from "react-router";
|
||||
import { useCredentials } from "./credentials";
|
||||
import { useDispatch } from "react-redux";
|
||||
import { startTask } from "./helpers";
|
||||
import { login } from "./store/actions";
|
||||
|
||||
interface FormErrors {
|
||||
errorUsername?: string;
|
||||
errorEmail?: string;
|
||||
errorPassword?: string;
|
||||
errorEncryptionPassword?: string;
|
||||
errorServer?: string;
|
||||
|
||||
errorGeneral?: string;
|
||||
}
|
||||
|
||||
export default function SignupPage() {
|
||||
const credentials = useCredentials();
|
||||
const dispatch = useDispatch();
|
||||
const [username, setUsername] = React.useState("");
|
||||
const [email, setEmail] = React.useState("");
|
||||
const [password, setPassword] = React.useState("");
|
||||
const [server, setServer] = React.useState("");
|
||||
const [showAdvanced, setShowAdvanced] = React.useState(false);
|
||||
const [loading, setLoading] = React.useState(false);
|
||||
const [errors, setErrors] = React.useState<FormErrors>({});
|
||||
|
||||
if (credentials) {
|
||||
return (
|
||||
<Redirect to={routeResolver.getRoute("home")} />
|
||||
);
|
||||
}
|
||||
|
||||
async function signup(e: React.FormEvent<any>) {
|
||||
e.preventDefault();
|
||||
setLoading(true);
|
||||
try {
|
||||
const errors: FormErrors = {};
|
||||
const fieldRequired = "This field is required!";
|
||||
if (!username) {
|
||||
errors.errorUsername = fieldRequired;
|
||||
}
|
||||
if (!email) {
|
||||
errors.errorEmail = fieldRequired;
|
||||
}
|
||||
if (!password) {
|
||||
errors.errorPassword = fieldRequired;
|
||||
}
|
||||
|
||||
if (process.env.NODE_ENV !== "development") {
|
||||
if (showAdvanced && !server.startsWith("https://")) {
|
||||
errors.errorServer = "Server URI must start with https://";
|
||||
}
|
||||
}
|
||||
|
||||
if (Object.keys(errors).length) {
|
||||
setErrors(errors);
|
||||
return;
|
||||
} else {
|
||||
setErrors({});
|
||||
}
|
||||
|
||||
const serverUrl = (showAdvanced) ? server : undefined;
|
||||
const user: Etebase.User = {
|
||||
username,
|
||||
email,
|
||||
};
|
||||
const etebase = await startTask((async () => {
|
||||
return await Etebase.Account.signup(user, password, serverUrl);
|
||||
}));
|
||||
dispatch(login(etebase));
|
||||
} catch (e) {
|
||||
errors.errorGeneral = e.toString();
|
||||
setErrors(errors);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
}
|
||||
|
||||
const styles = {
|
||||
form: {
|
||||
},
|
||||
forgotPassword: {
|
||||
paddingTop: 20,
|
||||
},
|
||||
textField: {
|
||||
marginTop: 20,
|
||||
},
|
||||
submit: {
|
||||
marginTop: 40,
|
||||
textAlign: "right" as any,
|
||||
},
|
||||
};
|
||||
|
||||
function handleInputChange(func: (value: string) => void) {
|
||||
return (event: React.ChangeEvent<any>) => {
|
||||
func(event.target.value);
|
||||
};
|
||||
}
|
||||
|
||||
let advancedSettings = null;
|
||||
if (showAdvanced) {
|
||||
advancedSettings = (
|
||||
<React.Fragment>
|
||||
<TextField
|
||||
type="url"
|
||||
style={styles.textField}
|
||||
error={!!errors.errorServer}
|
||||
helperText={errors.errorServer}
|
||||
label="Server"
|
||||
value={server}
|
||||
onChange={handleInputChange(setServer)}
|
||||
/>
|
||||
<br />
|
||||
</React.Fragment>
|
||||
);
|
||||
}
|
||||
|
||||
if (loading) {
|
||||
return (
|
||||
<div style={{ textAlign: "center" }}>
|
||||
<LoadingIndicator />
|
||||
<p>Deriving encryption data...</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Container style={{ maxWidth: "30rem" }}>
|
||||
<h2>Signup</h2>
|
||||
<form style={styles.form} onSubmit={signup}>
|
||||
<TextField
|
||||
type="text"
|
||||
style={styles.textField}
|
||||
error={!!errors.errorUsername}
|
||||
helperText={errors.errorUsername}
|
||||
label="Username"
|
||||
value={username}
|
||||
onChange={handleInputChange(setUsername)}
|
||||
/>
|
||||
<br />
|
||||
<TextField
|
||||
type="email"
|
||||
style={styles.textField}
|
||||
error={!!errors.errorEmail}
|
||||
helperText={errors.errorEmail}
|
||||
label="Email"
|
||||
value={email}
|
||||
onChange={handleInputChange(setEmail)}
|
||||
/>
|
||||
<br />
|
||||
<TextField
|
||||
type="password"
|
||||
style={styles.textField}
|
||||
error={!!errors.errorPassword}
|
||||
helperText={errors.errorPassword}
|
||||
label="Password"
|
||||
name="password"
|
||||
value={password}
|
||||
onChange={handleInputChange(setPassword)}
|
||||
/>
|
||||
<div style={styles.forgotPassword}>
|
||||
<ExternalLink href={C.forgotPassword}>Forgot password?</ExternalLink>
|
||||
</div>
|
||||
<FormGroup>
|
||||
<FormControlLabel
|
||||
control={
|
||||
<Switch
|
||||
color="primary"
|
||||
checked={showAdvanced}
|
||||
onChange={() => setShowAdvanced(!showAdvanced)}
|
||||
/>
|
||||
}
|
||||
label="Advanced settings"
|
||||
/>
|
||||
</FormGroup>
|
||||
{advancedSettings}
|
||||
{errors.errorGeneral && (
|
||||
<Alert severity="error" style={styles.textField}>{errors.errorGeneral}</Alert>
|
||||
)}
|
||||
|
||||
<div style={styles.submit}>
|
||||
<Button
|
||||
variant="contained"
|
||||
type="submit"
|
||||
color="secondary"
|
||||
disabled={loading}
|
||||
>
|
||||
{loading ? (
|
||||
<CircularProgress />
|
||||
) : "Sign Up"
|
||||
}
|
||||
</Button>
|
||||
</div>
|
||||
</form>
|
||||
</Container>
|
||||
);
|
||||
}
|
Loading…
Reference in New Issue