1
0
mirror of https://github.com/sasjs/server.git synced 2025-12-10 19:34:34 +00:00

feat(web): add the UI for updating user password

This commit is contained in:
2022-11-22 00:03:25 +05:00
parent 4581f32534
commit 8b8c43c21b
2 changed files with 254 additions and 69 deletions

View File

@@ -0,0 +1,141 @@
import React, { useEffect, useState } from 'react'
import {
Grid,
DialogContent,
DialogActions,
Button,
OutlinedInput,
InputAdornment,
IconButton,
FormControl,
InputLabel,
FormHelperText
} from '@mui/material'
import Visibility from '@mui/icons-material/Visibility'
import VisibilityOff from '@mui/icons-material/VisibilityOff'
import { BootstrapDialogTitle } from './dialogTitle'
import { BootstrapDialog } from './modal'
type Props = {
open: boolean
setOpen: React.Dispatch<React.SetStateAction<boolean>>
title: string
updatePassword: (currentPassword: string, newPassword: string) => void
}
const UpdatePasswordModal = (props: Props) => {
const { open, setOpen, title, updatePassword } = props
const [currentPassword, setCurrentPassword] = useState('')
const [newPassword, setNewPassword] = useState('')
const [hasError, setHasError] = useState(false)
const [errorText, setErrorText] = useState('')
useEffect(() => {
if (newPassword.length >= 6) {
setErrorText('')
setHasError(false)
}
}, [newPassword])
const handleBlur = () => {
if (newPassword.length < 6) {
setErrorText('Password length should be at least 6 characters.')
setHasError(true)
} else {
setErrorText('')
setHasError(false)
}
}
return (
<div>
<BootstrapDialog onClose={() => setOpen(false)} open={open}>
<BootstrapDialogTitle id="abort-modal" handleOpen={setOpen}>
{title}
</BootstrapDialogTitle>
<DialogContent dividers>
<Grid container spacing={2}>
<Grid item xs={12}>
<PasswordInput
label="Current Password"
password={currentPassword}
setPassword={setCurrentPassword}
/>
</Grid>
<Grid item xs={12}>
<PasswordInput
label="New Password"
password={newPassword}
setPassword={setNewPassword}
hasError={hasError}
errorText={errorText}
handleBlur={handleBlur}
/>
</Grid>
</Grid>
</DialogContent>
<DialogActions>
<Button variant="contained" onClick={() => setOpen(false)}>
Cancel
</Button>
<Button
variant="contained"
onClick={() => updatePassword(currentPassword, newPassword)}
disabled={hasError || !currentPassword || !newPassword}
>
Update
</Button>
</DialogActions>
</BootstrapDialog>
</div>
)
}
export default UpdatePasswordModal
type PasswordInputProps = {
label: string
password: string
setPassword: React.Dispatch<React.SetStateAction<string>>
hasError?: boolean
errorText?: string
handleBlur?: () => void
}
const PasswordInput = ({
label,
password,
setPassword,
hasError,
errorText,
handleBlur
}: PasswordInputProps) => {
const [showPassword, setShowPassword] = useState(false)
return (
<FormControl sx={{ width: '100%' }} variant="outlined" error={hasError}>
<InputLabel htmlFor="outlined-adornment-password">{label}</InputLabel>
<OutlinedInput
id="outlined-adornment-password"
type={showPassword ? 'text' : 'password'}
label={label}
value={password}
onChange={(e) => setPassword(e.target.value)}
onBlur={handleBlur}
endAdornment={
<InputAdornment position="end">
<IconButton
onClick={() => setShowPassword((val) => !val)}
edge="end"
>
{showPassword ? <VisibilityOff /> : <Visibility />}
</IconButton>
</InputAdornment>
}
/>
{errorText && <FormHelperText>{errorText}</FormHelperText>}
</FormControl>
)
}

View File

@@ -17,11 +17,13 @@ import {
import { toast } from 'react-toastify'
import { AppContext, ModeType } from '../../context/appContext'
import UpdatePasswordModal from '../../components/passwordModal'
const Profile = () => {
const [isLoading, setIsLoading] = useState(false)
const appContext = useContext(AppContext)
const [user, setUser] = useState({} as any)
const [isPasswordModalOpen, setIsPasswordModalOpen] = useState(false)
useEffect(() => {
setIsLoading(true)
@@ -36,7 +38,7 @@ const Profile = () => {
.finally(() => {
setIsLoading(false)
})
}, [])
}, [appContext.userId])
const handleChange = (event: any) => {
const { name, value } = event.target
@@ -68,82 +70,124 @@ const Profile = () => {
})
}
const updatePassword = (currentPassword: string, newPassword: string) => {
setIsLoading(true)
setIsPasswordModalOpen(false)
axios
.patch(`/SASjsApi/auth/updatePassword`, {
currentPassword,
newPassword
})
.then((res: any) => {
toast.success('Password updated', {
theme: 'dark',
position: toast.POSITION.BOTTOM_RIGHT
})
})
.catch((err) => {
toast.error('Failed: ' + err.response?.data || err.text, {
theme: 'dark',
position: toast.POSITION.BOTTOM_RIGHT
})
})
.finally(() => {
setIsLoading(false)
})
}
return isLoading ? (
<CircularProgress
style={{ position: 'absolute', left: '50%', top: '50%' }}
/>
) : (
<Card>
<CardHeader title="Profile Information" />
<Divider />
<CardContent>
<Grid container spacing={4}>
<Grid item md={6} xs={12}>
<TextField
fullWidth
error={user.displayName?.length === 0}
helperText="Please specify display name"
label="Display Name"
name="displayName"
onChange={handleChange}
required
value={user.displayName}
variant="outlined"
disabled={appContext.mode === ModeType.Desktop}
/>
</Grid>
<Grid item md={6} xs={12}>
<TextField
fullWidth
error={user.username?.length === 0}
helperText="Please specify username"
label="Username"
name="username"
onChange={handleChange}
required
value={user.username}
variant="outlined"
disabled={appContext.mode === ModeType.Desktop}
/>
</Grid>
<Grid item lg={6} md={8} sm={12} xs={12}>
<TextField
fullWidth
label="autoExec"
name="autoExec"
onChange={handleChange}
multiline
rows="10"
value={user.autoExec}
variant="outlined"
/>
</Grid>
<Grid item xs={6}>
<FormGroup row>
<FormControlLabel
disabled
control={<Checkbox checked={user.isActive} />}
label="isActive"
<>
<Card>
<CardHeader title="Profile Information" />
<Divider />
<CardContent>
<Grid container spacing={4}>
<Grid item md={6} xs={12}>
<TextField
fullWidth
error={user.displayName?.length === 0}
helperText="Please specify display name"
label="Display Name"
name="displayName"
onChange={handleChange}
required
value={user.displayName}
variant="outlined"
disabled={appContext.mode === ModeType.Desktop}
/>
<FormControlLabel
disabled
control={<Checkbox checked={user.isAdmin} />}
label="isAdmin"
</Grid>
<Grid item md={6} xs={12}>
<TextField
fullWidth
error={user.username?.length === 0}
helperText="Please specify username"
label="Username"
name="username"
onChange={handleChange}
required
value={user.username}
variant="outlined"
disabled={appContext.mode === ModeType.Desktop}
/>
</FormGroup>
</Grid>
<Grid item lg={6} md={8} sm={12} xs={12}>
<TextField
fullWidth
label="autoExec"
name="autoExec"
onChange={handleChange}
multiline
rows="10"
value={user.autoExec}
variant="outlined"
/>
</Grid>
<Grid item xs={6}>
<FormGroup row>
<FormControlLabel
disabled
control={<Checkbox checked={user.isActive} />}
label="isActive"
/>
<FormControlLabel
disabled
control={<Checkbox checked={user.isAdmin} />}
label="isAdmin"
/>
</FormGroup>
</Grid>
<Grid item xs={12}>
<Button
variant="contained"
onClick={() => setIsPasswordModalOpen(true)}
>
Update Password
</Button>
</Grid>
</Grid>
</Grid>
</CardContent>
<Divider />
<CardActions>
<Button type="submit" variant="contained" onClick={handleSubmit}>
Save Changes
</Button>
</CardActions>
</Card>
</CardContent>
<Divider />
<CardActions>
<Button type="submit" variant="contained" onClick={handleSubmit}>
Save Changes
</Button>
</CardActions>
</Card>
<UpdatePasswordModal
open={isPasswordModalOpen}
setOpen={setIsPasswordModalOpen}
title="Update Password"
updatePassword={updatePassword}
/>
</>
)
}