@@ -30,6 +30,7 @@ import {
3030 WarningTwoTone ,
3131} from '@ant-design/icons' ;
3232import {
33+ Alert ,
3334 App ,
3435 Button ,
3536 Dropdown ,
@@ -52,6 +53,8 @@ type ConnectionMode = 'SESSION' | 'API';
5253interface LoginFormPanelProps {
5354 isOpen : boolean ;
5455 isLoading : boolean ;
56+ loginError : { message : string ; description ?: string } | null ;
57+ onClearLoginError ?: ( ) => void ;
5558 connectionMode : ConnectionMode ;
5659 loginConfig : LoginConfigState ;
5760 apiEndpoint : string ;
@@ -82,6 +85,8 @@ interface LoginFormPanelProps {
8285const LoginFormPanel : React . FC < LoginFormPanelProps > = ( {
8386 isOpen,
8487 isLoading,
88+ loginError,
89+ onClearLoginError,
8590 connectionMode,
8691 loginConfig,
8792 apiEndpoint,
@@ -182,7 +187,10 @@ const LoginFormPanel: React.FC<LoginFormPanelProps> = ({
182187 { /* SESSION login fields */ }
183188 { connectionMode === 'SESSION' && (
184189 < >
185- < Form . Item name = "user_id" style = { { marginBottom : 8 } } >
190+ < Form . Item
191+ name = "user_id"
192+ style = { { marginBottom : token . marginSM } }
193+ >
186194 < Input
187195 prefix = { < MailOutlined /> }
188196 placeholder = { t ( 'login.E-mailOrUsername' ) }
@@ -192,7 +200,10 @@ const LoginFormPanel: React.FC<LoginFormPanelProps> = ({
192200 disabled = { isLoading }
193201 />
194202 </ Form . Item >
195- < Form . Item name = "password" style = { { marginBottom : 8 } } >
203+ < Form . Item
204+ name = "password"
205+ style = { { marginBottom : token . marginSM } }
206+ >
196207 < Input . Password
197208 prefix = { < KeyOutlined /> }
198209 placeholder = { t ( 'login.Password' ) }
@@ -202,7 +213,7 @@ const LoginFormPanel: React.FC<LoginFormPanelProps> = ({
202213 />
203214 </ Form . Item >
204215 { otpRequired && (
205- < Form . Item name = "otp" style = { { marginBottom : 8 } } >
216+ < Form . Item name = "otp" style = { { marginBottom : token . marginSM } } >
206217 < Input
207218 prefix = { < LockOutlined /> }
208219 placeholder = { t ( 'totp.OTP' ) }
@@ -217,15 +228,21 @@ const LoginFormPanel: React.FC<LoginFormPanelProps> = ({
217228 { /* API login fields */ }
218229 { connectionMode === 'API' && (
219230 < >
220- < Form . Item name = "api_key" style = { { marginBottom : 8 } } >
231+ < Form . Item
232+ name = "api_key"
233+ style = { { marginBottom : token . marginSM } }
234+ >
221235 < Input
222236 prefix = { < LockOutlined /> }
223237 placeholder = { t ( 'login.APIKey' ) }
224238 maxLength = { 20 }
225239 disabled = { isLoading }
226240 />
227241 </ Form . Item >
228- < Form . Item name = "secret_key" style = { { marginBottom : 8 } } >
242+ < Form . Item
243+ name = "secret_key"
244+ style = { { marginBottom : token . marginSM } }
245+ >
229246 < Input . Password
230247 prefix = { < KeyOutlined /> }
231248 placeholder = { t ( 'login.SecretKey' ) }
@@ -236,8 +253,23 @@ const LoginFormPanel: React.FC<LoginFormPanelProps> = ({
236253 </ >
237254 ) }
238255
256+ { /* Login error alert */ }
257+ { loginError && (
258+ < Alert
259+ type = "error"
260+ showIcon
261+ title = { loginError . message }
262+ description = { loginError . description }
263+ style = { { marginBottom : token . marginSM } }
264+ closable = { {
265+ closeIcon : true ,
266+ onClose : onClearLoginError ,
267+ } }
268+ />
269+ ) }
270+
239271 { /* Login button */ }
240- < Form . Item style = { { marginBottom : 8 } } >
272+ < Form . Item style = { { marginBottom : token . marginSM } } >
241273 < Button
242274 type = "primary"
243275 block
@@ -251,14 +283,14 @@ const LoginFormPanel: React.FC<LoginFormPanelProps> = ({
251283
252284 { /* SSO buttons */ }
253285 { loginConfig . singleSignOnVendors . includes ( 'saml' ) && (
254- < Form . Item style = { { marginBottom : 8 } } >
286+ < Form . Item style = { { marginBottom : token . marginSM } } >
255287 < Button block onClick = { onSAMLLogin } >
256288 { t ( 'login.singleSignOn.LoginWithSAML' ) }
257289 </ Button >
258290 </ Form . Item >
259291 ) }
260292 { loginConfig . singleSignOnVendors . includes ( 'openid' ) && (
261- < Form . Item style = { { marginBottom : 8 } } >
293+ < Form . Item style = { { marginBottom : token . marginSM } } >
262294 < Button block onClick = { onOpenIDLogin } >
263295 { t ( 'login.singleSignOn.LoginWithRealm' , {
264296 realmName : loginConfig . ssoRealmName || 'OpenID' ,
0 commit comments