16212: Adds login form when PAM Login is enabled. (WIP)
[arvados-workbench2.git] / src / views-components / login-form / login-form.tsx
1 // Copyright (C) The Arvados Authors. All rights reserved.
2 //
3 // SPDX-License-Identifier: AGPL-3.0
4
5 import * as React from 'react';
6 import { useState, useEffect } from 'react';
7 import { withStyles, WithStyles, StyleRulesCallback } from '@material-ui/core/styles';
8 import CircularProgress from '@material-ui/core/CircularProgress';
9 import { Button, Card, CardContent, TextField, CardActions } from '@material-ui/core';
10 import { green } from '@material-ui/core/colors';
11 import { AxiosPromise } from 'axios';
12
13 type CssRules = 'root' | 'loginBtn' | 'card' | 'wrapper' | 'progress';
14
15 const styles: StyleRulesCallback<CssRules> = theme => ({
16     root: {
17         display: 'flex',
18         flexWrap: 'wrap',
19         width: '100%',
20         margin: `${theme.spacing.unit} auto`
21     },
22     loginBtn: {
23         marginTop: theme.spacing.unit,
24         flexGrow: 1
25     },
26     card: {
27         marginTop: theme.spacing.unit,
28         width: '100%'
29     },
30     wrapper: {
31         margin: theme.spacing.unit,
32         position: 'relative',
33     },
34     progress: {
35         color: green[500],
36         position: 'absolute',
37         top: '50%',
38         left: '50%',
39         marginTop: -12,
40         marginLeft: -12,
41     },
42 });
43
44 interface LoginFormProps {
45     handleSubmit: (username: string, password: string) => AxiosPromise;
46 }
47
48 export const LoginForm = withStyles(styles)(
49     ({ handleSubmit, classes }: LoginFormProps & WithStyles<CssRules>) => {
50         const [username, setUsername] = useState('');
51         const [password, setPassword] = useState('');
52         const [isButtonDisabled, setIsButtonDisabled] = useState(true);
53         const [isSubmitting, setSubmitting] = useState(false);
54         const [helperText, setHelperText] = useState('');
55         const [error, setError] = useState(false);
56
57         useEffect(() => {
58             setError(false);
59             setHelperText('');
60             if (username.trim() && password.trim()) {
61                 setIsButtonDisabled(false);
62             } else {
63                 setIsButtonDisabled(true);
64             }
65         }, [username, password]);
66
67         const handleLogin = () => {
68             setSubmitting(true);
69             handleSubmit(username, password)
70             .then((response) => {
71                 setError(false);
72                 console.log("LOGIN SUCESSFUL: ", response);
73                 setSubmitting(false);
74             })
75             .catch((err) => {
76                 setError(true);
77                 console.log("ERROR: ", err.response);
78                 setHelperText(`${err.response && err.response.data && err.response.data.errors[0] || 'Error logging in: '+err}`);
79                 setSubmitting(false);
80             });
81         };
82
83         const handleKeyPress = (e: any) => {
84             if (e.keyCode === 13 || e.which === 13) {
85                 if (!isButtonDisabled) {
86                     handleLogin();
87                 }
88             }
89         };
90
91         return (
92             <React.Fragment>
93                 <form className={classes.root} noValidate autoComplete="off">
94                     <Card className={classes.card}>
95                     <div className={classes.wrapper}>
96                         <CardContent>
97                             <div>
98                                 <TextField
99                                     disabled={isSubmitting}
100                                     error={error} fullWidth id="username" type="email"
101                                     label="Username" margin="normal"
102                                     onChange={(e) => setUsername(e.target.value)}
103                                     onKeyPress={(e) => handleKeyPress(e)}
104                                 />
105                                 <TextField
106                                     disabled={isSubmitting}
107                                     error={error} fullWidth id="password" type="password"
108                                     label="Password" margin="normal"
109                                     helperText={helperText}
110                                     onChange={(e) => setPassword(e.target.value)}
111                                     onKeyPress={(e) => handleKeyPress(e)}
112                                 />
113                             </div>
114                         </CardContent>
115                         <CardActions>
116                             <Button variant="contained" size="large" color="primary"
117                                 className={classes.loginBtn} onClick={() => handleLogin()}
118                                 disabled={isSubmitting || isButtonDisabled}>
119                                 Log in
120                             </Button>
121                         </CardActions>
122                         { isSubmitting && <CircularProgress color='secondary' className={classes.progress} />}
123                     </div>
124                     </Card>
125                 </form>
126             </React.Fragment>
127         );
128     });