1
1
import React , { useState } from "react" ;
2
- import Row from "react-bootstrap/Row" ;
3
2
import Card from "react-bootstrap/Card" ;
4
3
import Form from "react-bootstrap/Form" ;
5
- import Col from "react-bootstrap/Col" ;
6
4
import Button from "react-bootstrap/Button" ;
7
5
import { auth , AuthenticationError , setup , SETUP_STATE_INITIALIZED } from "../../lib/api" ;
8
6
import { AlertError , Loading } from "../../lib/components/controls"
@@ -32,77 +30,86 @@ export interface LoginConfig {
32
30
const LoginForm = ( { loginConfig} : { loginConfig : LoginConfig } ) => {
33
31
const router = useRouter ( ) ;
34
32
const navigate = useNavigate ( ) ;
35
- const [ loginError , setLoginError ] = useState ( null ) ;
33
+ const [ loginError , setLoginError ] = useState < React . ReactNode > ( null ) ;
36
34
const { next } = router . query ;
37
35
const usernamePlaceholder = loginConfig . username_ui_placeholder || "Access Key ID" ;
38
36
const passwordPlaceholder = loginConfig . password_ui_placeholder || "Secret Access Key" ;
37
+
39
38
return (
40
- < Row >
41
- < Col md = { { offset : 4 , span : 4 } } >
42
- < Card className = "login-widget shadow-lg border-0" >
43
- < Card . Header className = "text" >
44
- < h4 className = "mb-0" > Login</ h4 >
45
- </ Card . Header >
46
- < Card . Body className = "p-4" >
47
- < Form onSubmit = { async ( e ) => {
48
- e . preventDefault ( )
49
- try {
50
- setLoginError ( null ) ;
51
- await auth . login ( e . target . username . value , e . target . password . value )
52
- router . push ( next || '/' ) ;
53
- navigate ( 0 ) ;
54
- } catch ( err ) {
55
- if ( err instanceof AuthenticationError && err . status === 401 ) {
56
- const contents = { __html : `${ loginConfig . login_failed_message } ` ||
39
+ < div className = "d-flex align-items-center justify-content-center" >
40
+ < Card className = "shadow-lg border-0 login-card" >
41
+ < Card . Header className = "text-center" >
42
+ < div className = "mt-3 mb-3" >
43
+ < img src = "/logo.svg" alt = "lakeFS" className = "login-logo" />
44
+ </ div >
45
+ </ Card . Header >
46
+ < Card . Body className = "p-4" >
47
+ < Form onSubmit = { async ( e ) => {
48
+ e . preventDefault ( )
49
+ const form = e . target as HTMLFormElement ;
50
+ const formData = new FormData ( form ) ;
51
+ try {
52
+ setLoginError ( null ) ;
53
+ const username = formData . get ( 'username' ) ;
54
+ const password = formData . get ( 'password' ) ;
55
+ await auth . login ( username , password ) ;
56
+ router . push ( next || '/' ) ;
57
+ navigate ( 0 ) ;
58
+ } catch ( err ) {
59
+ if ( err instanceof AuthenticationError && err . status === 401 ) {
60
+ const contents = { __html : `${ loginConfig . login_failed_message } ` ||
57
61
"Credentials don't match." } ;
58
- setLoginError ( < span dangerouslySetInnerHTML = { contents } /> ) ;
59
- }
62
+ setLoginError ( < span dangerouslySetInnerHTML = { contents } /> ) ;
60
63
}
61
- } } >
62
- < Form . Group controlId = "username" className = "mb-3" >
63
- < Form . Control
64
- type = "text"
65
- placeholder = { usernamePlaceholder }
66
- autoFocus
67
- className = "bg-light"
68
- />
69
- </ Form . Group >
64
+ }
65
+ } } >
66
+ < Form . Group controlId = "username" className = "mb-3" >
67
+ < Form . Control
68
+ name = "username"
69
+ type = "text"
70
+ placeholder = { usernamePlaceholder }
71
+ autoFocus
72
+ className = "bg-light"
73
+ />
74
+ </ Form . Group >
70
75
71
- < Form . Group controlId = "password" className = "mb-3" >
72
- < Form . Control
73
- type = "password"
74
- placeholder = { passwordPlaceholder }
75
- className = "bg-light"
76
- />
77
- </ Form . Group >
76
+ < Form . Group controlId = "password" className = "mb-3" >
77
+ < Form . Control
78
+ name = "password"
79
+ type = "password"
80
+ placeholder = { passwordPlaceholder }
81
+ className = "bg-light"
82
+ />
83
+ </ Form . Group >
78
84
79
- { ( ! ! loginError ) && < AlertError error = { loginError } /> }
85
+ { ( ! ! loginError ) && < AlertError error = { loginError } /> }
80
86
81
- < Button
82
- variant = "primary"
83
- type = "submit"
84
- className = "w-100 mt-3 py-2"
85
- >
86
- Login
87
- </ Button >
88
- </ Form >
89
- < div className = { "mt-2 mb-1" } >
90
- { loginConfig . fallback_login_url ?
91
- < Button variant = "link" className = "text-secondary mt-2" onClick = { async ( ) => {
92
- loginConfig . login_cookie_names ?. forEach (
93
- cookie => {
94
- document . cookie = `${ cookie } =; Path=/; Expires=Thu, 01 Jan 1970 00:00:01 GMT;` ;
95
- }
96
- ) ;
97
- window . location = loginConfig . fallback_login_url ;
98
- } } > { loginConfig . fallback_login_label || 'Try another way to login' } </ Button >
99
- : ""
100
- }
101
- </ div >
102
- </ Card . Body >
103
- </ Card >
104
- </ Col >
105
- </ Row >
87
+ < Button
88
+ variant = "primary"
89
+ type = "submit"
90
+ className = "w-100 mt-3 py-2"
91
+ >
92
+ Login
93
+ </ Button >
94
+ </ Form >
95
+ < div className = { "mt-2 mb-1" } >
96
+ { loginConfig . fallback_login_url ?
97
+ < Button variant = "link" className = "text-secondary mt-2" onClick = { async ( ) => {
98
+ loginConfig . login_cookie_names ?. forEach (
99
+ cookie => {
100
+ document . cookie = `${ cookie } =; Path=/; Expires=Thu, 01 Jan 1970 00:00:01 GMT;` ;
101
+ }
102
+ ) ;
103
+ if ( loginConfig . fallback_login_url ) {
104
+ window . location . href = loginConfig . fallback_login_url ;
105
+ }
106
+ } } > { loginConfig . fallback_login_label || 'Try another way to login' } </ Button >
107
+ : ""
108
+ }
109
+ </ div >
110
+ </ Card . Body >
111
+ </ Card >
112
+ </ div >
106
113
)
107
114
}
108
115
@@ -151,4 +158,4 @@ const LoginPage = () => {
151
158
) ;
152
159
} ;
153
160
154
- export default LoginPage ;
161
+ export default LoginPage ;
0 commit comments