11import React , { useState } from "react" ;
2- import Row from "react-bootstrap/Row" ;
32import Card from "react-bootstrap/Card" ;
43import Form from "react-bootstrap/Form" ;
5- import Col from "react-bootstrap/Col" ;
64import Button from "react-bootstrap/Button" ;
75import { auth , AuthenticationError , setup , SETUP_STATE_INITIALIZED } from "../../lib/api" ;
86import { AlertError , Loading } from "../../lib/components/controls"
@@ -32,77 +30,86 @@ export interface LoginConfig {
3230const LoginForm = ( { loginConfig} : { loginConfig : LoginConfig } ) => {
3331 const router = useRouter ( ) ;
3432 const navigate = useNavigate ( ) ;
35- const [ loginError , setLoginError ] = useState ( null ) ;
33+ const [ loginError , setLoginError ] = useState < React . ReactNode > ( null ) ;
3634 const { next } = router . query ;
3735 const usernamePlaceholder = loginConfig . username_ui_placeholder || "Access Key ID" ;
3836 const passwordPlaceholder = loginConfig . password_ui_placeholder || "Secret Access Key" ;
37+
3938 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 } ` ||
5761 "Credentials don't match." } ;
58- setLoginError ( < span dangerouslySetInnerHTML = { contents } /> ) ;
59- }
62+ setLoginError ( < span dangerouslySetInnerHTML = { contents } /> ) ;
6063 }
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 >
7075
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 >
7884
79- { ( ! ! loginError ) && < AlertError error = { loginError } /> }
85+ { ( ! ! loginError ) && < AlertError error = { loginError } /> }
8086
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 >
106113 )
107114}
108115
@@ -151,4 +158,4 @@ const LoginPage = () => {
151158 ) ;
152159} ;
153160
154- export default LoginPage ;
161+ export default LoginPage ;
0 commit comments