Skip to content

Commit 0671ebc

Browse files
authored
Merge pull request #2573 from devtron-labs/fix/login-passwprd-re-rendering
chore: login rerendering on login page
2 parents bfb5067 + bede79f commit 0671ebc

File tree

6 files changed

+177
-212
lines changed

6 files changed

+177
-212
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
"private": true,
55
"homepage": "/dashboard",
66
"dependencies": {
7-
"@devtron-labs/devtron-fe-common-lib": "1.9.6",
7+
"@devtron-labs/devtron-fe-common-lib": "1.9.7",
88
"@esbuild-plugins/node-globals-polyfill": "0.2.3",
99
"@rjsf/core": "^5.13.3",
1010
"@rjsf/utils": "^5.13.3",

src/components/login/Login.tsx

Lines changed: 4 additions & 148 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,11 @@
1414
* limitations under the License.
1515
*/
1616

17-
import React, { useEffect, useState } from 'react'
17+
import { useEffect, useState } from 'react'
1818
import { Switch, Redirect, Route, useLocation, useHistory } from 'react-router-dom'
1919
import {
2020
getCookie,
21-
ServerErrors,
2221
Host,
23-
showError,
24-
CustomInput,
2522
URLS as CommonURL,
2623
ToastVariantType,
2724
ToastManager,
@@ -30,8 +27,6 @@ import {
3027
ButtonComponentType,
3128
ButtonVariantType,
3229
ButtonStyleType,
33-
useUserEmail,
34-
PasswordField,
3530
useSearchString,
3631
getComponentSpecificThemeClass,
3732
AppThemeType,
@@ -40,15 +35,13 @@ import {
4035
Icon,
4136
} from '@devtron-labs/devtron-fe-common-lib'
4237
import { importComponentFromFELibrary } from '@Components/common'
43-
import { ReactComponent as Help } from '@Icons/ic-help-outline.svg'
44-
import { REQUIRED_FIELD_MSG } from '@Config/constantMessaging'
45-
import { URLS, DOCUMENTATION, TOKEN_COOKIE_NAME } from '../../config'
46-
import { loginAsAdmin } from './login.service'
38+
import { URLS, TOKEN_COOKIE_NAME } from '../../config'
4739
import { dashboardAccessed } from '../../services/service'
4840
import './login.scss'
4941
import { getSSOConfigList } from '../../Pages/GlobalConfigurations/Authorization/SSOLoginServices/service'
5042
import { SSOConfigLoginList } from './login.types'
5143
import { SSOProvider } from './constants'
44+
import { LoginForm } from './LoginForm'
5245

5346
const NetworkStatusInterface = !importComponentFromFELibrary('NetworkStatusInterface', null, 'function')
5447

@@ -57,26 +50,10 @@ const getTermsAndConditions = importComponentFromFELibrary('getTermsAndCondition
5750
const Login = () => {
5851
const [continueUrl, setContinueUrl] = useState('')
5952
const [loginList, setLoginList] = useState<SSOConfigLoginList[]>([])
60-
const [loading, setLoading] = useState(false)
61-
const [form, setForm] = useState({
62-
username: 'admin',
63-
password: '',
64-
})
65-
const [errorMessage, setErrorMessage] = useState({
66-
username: {
67-
message: '',
68-
isValid: true,
69-
},
70-
password: {
71-
message: '',
72-
isValid: true,
73-
},
74-
})
7553

7654
const { searchParams } = useSearchString()
7755
const location = useLocation()
7856
const history = useHistory()
79-
const { setEmail } = useUserEmail()
8057

8158
const [initLoading, initResult] = useAsync(() => Promise.allSettled([getSSOConfigList(), dashboardAccessed()]), [])
8259

@@ -134,58 +111,6 @@ const Login = () => {
134111
}
135112
}, [initLoading, initResult])
136113

137-
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
138-
e.persist()
139-
140-
const { name, value } = e.target
141-
setErrorMessage((prevState) => ({
142-
...prevState,
143-
[name]: {
144-
message: value ? '' : REQUIRED_FIELD_MSG,
145-
isValid: !!value,
146-
},
147-
}))
148-
149-
setForm({
150-
...form,
151-
[name]: value,
152-
})
153-
}
154-
155-
const getDefaultRedirectionURL = () => {
156-
const queryString = location.search.split('continue=')[1]
157-
if (queryString) {
158-
return queryString
159-
}
160-
161-
if (!window._env_.HIDE_NETWORK_STATUS_INTERFACE && !!NetworkStatusInterface) {
162-
return CommonURL.NETWORK_STATUS_INTERFACE
163-
}
164-
165-
// NOTE: we don't have serverMode therefore defaulting to flag value
166-
return window._env_.FEATURE_DEFAULT_LANDING_RB_ENABLE ? URLS.RESOURCE_BROWSER : URLS.APP
167-
}
168-
169-
const onSubmitLogin = (e): void => {
170-
e.preventDefault()
171-
const data = form
172-
setLoading(true)
173-
loginAsAdmin(data)
174-
.then((response) => {
175-
if (response.result.token) {
176-
setLoading(false)
177-
const url = getDefaultRedirectionURL()
178-
setEmail(data.username)
179-
history.push(url)
180-
localStorage.setItem('isAdminLogin', 'true')
181-
}
182-
})
183-
.catch((errors: ServerErrors) => {
184-
showError(errors)
185-
setLoading(false)
186-
})
187-
}
188-
189114
const onClickSSO = () => {
190115
if (typeof Storage !== 'undefined') {
191116
localStorage.setItem('isSSOLogin', 'true')
@@ -228,76 +153,7 @@ const Login = () => {
228153
</div>
229154
)
230155

231-
const renderAdminLoginPage = () => {
232-
const { search } = location
233-
234-
return (
235-
<form className="flexbox-col dc__gap-32" autoComplete="on" onSubmit={onSubmitLogin} noValidate>
236-
<div className="flexbox-col dc__gap-16">
237-
<CustomInput
238-
placeholder="Enter username"
239-
value={form.username}
240-
name="username"
241-
onChange={handleChange}
242-
label="User ID"
243-
required
244-
error={errorMessage.username.message}
245-
/>
246-
<div className="flexbox-col dc__gap-4">
247-
<PasswordField
248-
placeholder="Enter password"
249-
value={form.password}
250-
name="password"
251-
onChange={handleChange}
252-
label="Password"
253-
required
254-
shouldShowDefaultPlaceholderOnBlur={false}
255-
autoFocus
256-
error={errorMessage.password.message}
257-
/>
258-
259-
<div className="flex left dc__gap-4">
260-
<Help className="fcb-5 icon-dim-16" />
261-
262-
<a
263-
className="anchor fs-11 cb-5 lh-20"
264-
rel="noreferrer noopener"
265-
target="_blank"
266-
href={DOCUMENTATION.ADMIN_PASSWORD}
267-
>
268-
What is my admin password?
269-
</a>
270-
</div>
271-
</div>
272-
</div>
273-
<div className="flexbox-col dc__gap-12">
274-
<Button
275-
disabled={loading}
276-
isLoading={loading}
277-
dataTestId="login-button"
278-
text="Login"
279-
fullWidth
280-
size={ComponentSizeType.xl}
281-
buttonProps={{
282-
type: 'submit',
283-
}}
284-
/>
285-
286-
{loginList.length > 0 && (
287-
<Button
288-
dataTestId="sso-login"
289-
text="Login using SSO service"
290-
component={ButtonComponentType.link}
291-
linkProps={{
292-
to: `${URLS.LOGIN_SSO}${search}`,
293-
}}
294-
variant={ButtonVariantType.text}
295-
/>
296-
)}
297-
</div>
298-
</form>
299-
)
300-
}
156+
const renderAdminLoginPage = () => <LoginForm loginList={loginList} />
301157

302158
const renderDevtronLogo = () => (
303159
<div className="flex column dc__gap-16 dc__text-center">

src/components/login/LoginForm.tsx

Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
import { REQUIRED_FIELD_MSG } from '@Config/constantMessaging'
2+
import {
3+
CustomInput,
4+
PasswordField,
5+
Button,
6+
ComponentSizeType,
7+
ButtonComponentType,
8+
URLS,
9+
ButtonVariantType,
10+
ServerErrors,
11+
showError,
12+
useUserEmail,
13+
URLS as CommonURL,
14+
Icon,
15+
} from '@devtron-labs/devtron-fe-common-lib'
16+
import { useState } from 'react'
17+
import { useHistory, useLocation } from 'react-router-dom'
18+
import { importComponentFromFELibrary } from '@Components/common'
19+
import { DOCUMENTATION } from '@Config/constants'
20+
import { loginAsAdmin } from './login.service'
21+
import { LoginFormType } from './login.types'
22+
23+
export const LoginForm = ({ loginList }: LoginFormType) => {
24+
const [loading, setLoading] = useState(false)
25+
const [form, setForm] = useState({
26+
username: 'admin',
27+
password: '',
28+
})
29+
const [errorMessage, setErrorMessage] = useState({
30+
username: {
31+
message: '',
32+
isValid: true,
33+
},
34+
password: {
35+
message: '',
36+
isValid: true,
37+
},
38+
})
39+
40+
const { setEmail } = useUserEmail()
41+
const history = useHistory()
42+
const location = useLocation()
43+
44+
const NetworkStatusInterface = !importComponentFromFELibrary('NetworkStatusInterface', null, 'function')
45+
46+
const getDefaultRedirectionURL = () => {
47+
const queryString = history.location.search.split('continue=')[1]
48+
if (queryString) {
49+
return queryString
50+
}
51+
52+
if (!window._env_.HIDE_NETWORK_STATUS_INTERFACE && !!NetworkStatusInterface) {
53+
return CommonURL.NETWORK_STATUS_INTERFACE
54+
}
55+
56+
// NOTE: we don't have serverMode therefore defaulting to flag value
57+
return window._env_.FEATURE_DEFAULT_LANDING_RB_ENABLE ? URLS.RESOURCE_BROWSER : URLS.APP
58+
}
59+
60+
const onSubmitLogin = (e): void => {
61+
e.preventDefault()
62+
const data = form
63+
setLoading(true)
64+
loginAsAdmin(data)
65+
.then((response) => {
66+
if (response.result.token) {
67+
setLoading(false)
68+
const url = getDefaultRedirectionURL()
69+
setEmail(data.username)
70+
history.push(url)
71+
localStorage.setItem('isAdminLogin', 'true')
72+
}
73+
})
74+
.catch((errors: ServerErrors) => {
75+
showError(errors)
76+
setLoading(false)
77+
})
78+
}
79+
80+
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
81+
e.persist()
82+
83+
const { name, value } = e.target
84+
setErrorMessage((prevState) => ({
85+
...prevState,
86+
[name]: {
87+
message: value ? '' : REQUIRED_FIELD_MSG,
88+
isValid: !!value,
89+
},
90+
}))
91+
92+
setForm({
93+
...form,
94+
[name]: value,
95+
})
96+
}
97+
98+
return (
99+
<form className="flexbox-col dc__gap-32" autoComplete="on" onSubmit={onSubmitLogin} noValidate>
100+
<div className="flexbox-col dc__gap-16">
101+
<CustomInput
102+
placeholder="Enter username"
103+
value={form.username}
104+
name="username"
105+
onChange={handleChange}
106+
label="User ID"
107+
required
108+
error={errorMessage.username.message}
109+
/>
110+
<div className="flexbox-col dc__gap-4">
111+
<PasswordField
112+
placeholder="Enter password"
113+
value={form.password}
114+
name="password"
115+
onChange={handleChange}
116+
label="Password"
117+
required
118+
shouldShowDefaultPlaceholderOnBlur={false}
119+
autoFocus
120+
error={errorMessage.password.message}
121+
/>
122+
123+
<div className="flex left dc__gap-4">
124+
<Icon name="ic-help-outline" color="B500" size={12} />
125+
126+
<a
127+
className="anchor fs-11 cb-5"
128+
rel="noreferrer noopener"
129+
target="_blank"
130+
href={DOCUMENTATION.ADMIN_PASSWORD}
131+
>
132+
What is my admin password?
133+
</a>
134+
</div>
135+
</div>
136+
</div>
137+
<div className="flexbox-col dc__gap-12">
138+
<Button
139+
disabled={loading}
140+
isLoading={loading}
141+
dataTestId="login-button"
142+
text="Login"
143+
fullWidth
144+
size={ComponentSizeType.xl}
145+
buttonProps={{
146+
type: 'submit',
147+
}}
148+
/>
149+
150+
{loginList.length > 0 && (
151+
<Button
152+
dataTestId="sso-login"
153+
text="Login using SSO service"
154+
component={ButtonComponentType.link}
155+
linkProps={{
156+
to: `${URLS.LOGIN_SSO}${location.search}`,
157+
}}
158+
variant={ButtonVariantType.text}
159+
/>
160+
)}
161+
</div>
162+
</form>
163+
)
164+
}

0 commit comments

Comments
 (0)