Skip to content

Commit 6787bf4

Browse files
committed
496: Handle createUserResponse
* Add banner to UserManagement * Add response within dialog when user is duplicate
1 parent dce46b2 commit 6787bf4

File tree

4 files changed

+41
-5
lines changed

4 files changed

+41
-5
lines changed

src/client/src/pages/UserManagement/Components/Dialog/NewUserDialog.jsx

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@ import { buildNameValidation, buildPasswordValidation, buildRoleValidation, buil
88

99

1010
export default function NewUserDialog(props) {
11-
const { onClose, token } = props;
11+
const [responseError, setResponseError] = React.useState(undefined);
12+
const { onClose, notifyResult, token } = props;
1213

1314
const validationSchema = Yup.object().shape({
1415
name: buildNameValidation(),
@@ -18,11 +19,13 @@ export default function NewUserDialog(props) {
1819
confirmPassword: Yup.string().oneOf([Yup.ref("password")], "Passwords must match"),
1920
});
2021

21-
const { register, handleSubmit, formState: { errors }, reset } = useForm({
22+
const { register, handleSubmit, formState: { errors }, reset, trigger } = useForm({
2223
resolver: yupResolver(validationSchema),
2324
});
2425

2526
const onSubmitHandler = (data) => {
27+
setResponseError(null);
28+
2629
const { username, name: full_name, role, password } = data;
2730

2831
createUser({
@@ -31,6 +34,15 @@ export default function NewUserDialog(props) {
3134
role,
3235
password
3336
}, token)
37+
.then((res) => {
38+
if (res.indexOf("duplicate key") > -1) {
39+
setResponseError(`User with username ${username} already exists`)
40+
} else {
41+
notifyResult({ success: true, message: `New user ${res} created successfully` });
42+
onClose();
43+
}
44+
})
45+
.catch(e => console.warn(e))
3446
}
3547

3648
return (
@@ -64,8 +76,8 @@ export default function NewUserDialog(props) {
6476
variant="standard"
6577
fullWidth
6678
/>
67-
{errors.username &&
68-
<Typography color="error">{errors.username.message}</Typography>
79+
{(responseError || errors.username) && // This is a little janky... Could be improved upon.
80+
<Typography color="error">{responseError || errors.username.message}</Typography>
6981
}
7082
<TextField
7183
{...register("role")}

src/client/src/pages/UserManagement/Components/Dialog/UserDialog.jsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,13 @@ export const DialogTypes = {
66
}
77

88
export default function UserDialog(props) {
9-
const { onClose, type, token } = props;
9+
const { onClose, type, notifyResult, token } = props;
1010

1111
switch (type) {
1212
case DialogTypes.NewUser:
1313
return (
1414
<NewUserDialog
15+
notifyResult={notifyResult}
1516
onClose={onClose}
1617
token={token}
1718
open

src/client/src/pages/UserManagement/UserManagement.jsx

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import {
1212
TableRow,
1313
Typography
1414
} from '@material-ui/core';
15+
import { Alert, AlertTitle } from '@material-ui/lab';
1516
import _ from 'lodash';
1617
import React from 'react';
1718
import { fetchUsers } from '../../utils/api';
@@ -21,6 +22,7 @@ import UserRow from './Components/UserRow';
2122
export default function UserManagement(props) {
2223
const [users, setUsers] = React.useState(undefined);
2324
const [isLoading, setIsLoading] = React.useState(undefined);
25+
const [resultBanner, setResultBanner] = React.useState(undefined);
2426
const [dialogOpen, setDialogOpen] = React.useState(false);
2527
const [dialogType, setDialogType] = React.useState(undefined)
2628
const { access_token: token } = props;
@@ -34,6 +36,16 @@ export default function UserManagement(props) {
3436
setIsLoading(false);
3537
}, [token]);
3638

39+
const notifyResult = ({ success, message }) => {
40+
setResultBanner({ success, message });
41+
42+
if (success) {
43+
setTimeout(() => {
44+
setResultBanner(null);
45+
}, 5000)
46+
}
47+
}
48+
3749
const openDialog = (opts) => {
3850
setDialogType(opts.type);
3951
setDialogOpen(true);
@@ -63,6 +75,12 @@ export default function UserManagement(props) {
6375
</Button>
6476
</Grid>
6577
</Grid >
78+
{resultBanner &&
79+
<Alert onClose={() => setResultBanner(null)} severity={resultBanner.success ? "success" : "error"} spacing={2}>
80+
<AlertTitle><Typography variant='h6'>{resultBanner.success ? "Success" : "Error"}</Typography></AlertTitle>
81+
<Typography>{resultBanner.message}</Typography>
82+
</Alert>
83+
}
6684
{isLoading &&
6785
<Backdrop open={true}>
6886
<CircularProgress size={60} />
@@ -90,6 +108,7 @@ export default function UserManagement(props) {
90108
}
91109
{dialogOpen &&
92110
<UserDialog
111+
notifyResult={notifyResult}
93112
onClose={closeDialog}
94113
token={token}
95114
type={dialogType}

src/client/src/pages/UserManagement/Validations.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,10 @@ export const buildPasswordValidation = () => {
3434
"no-disallowed-words",
3535
"Password cannot include 'dog', 'cat', 'password', or your username",
3636
(value, context) => {
37+
if (!value) {
38+
return true;
39+
}
40+
3741
const lowercasePassword = value.toLowerCase();
3842
const lowercaseUsername = context.parent.username.toLowerCase()
3943
return [...DISALLOWED_WORDS, lowercaseUsername].every((word) => !lowercasePassword.includes(word))

0 commit comments

Comments
 (0)