-
Notifications
You must be signed in to change notification settings - Fork 899
feat: ability to activate suspended users #2344
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
resolves #2254
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -13,15 +13,20 @@ export const Language = { | |
suspendDialogTitle: "Suspend user", | ||
suspendDialogAction: "Suspend", | ||
suspendDialogMessagePrefix: "Do you want to suspend the user", | ||
activateDialogTitle: "Activate user", | ||
activateDialogAction: "Activate", | ||
activateDialogMessagePrefix: "Do you want to active the user", | ||
} | ||
|
||
export const UsersPage: React.FC = () => { | ||
const xServices = useContext(XServiceContext) | ||
const [usersState, usersSend] = useActor(xServices.usersXService) | ||
const [rolesState, rolesSend] = useActor(xServices.siteRolesXService) | ||
const { users, getUsersError, userIdToSuspend, userIdToResetPassword, newUserPassword } = usersState.context | ||
const { users, getUsersError, userIdToSuspend, userIdToActivate, userIdToResetPassword, newUserPassword } = | ||
usersState.context | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Wondering what the ideal linting should be here. Something like:
Thoughts? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oh, sorry I missed this! I agree, that is nicer. I left it up to the formatter and it didn't print it as clearly. I can update on my next UI PR. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I missed it in my initial review too. Next PR sounds good! I wonder if we can add something to the formatter though. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah, yeah, just tried it out and we'd have to adjust the prettier rule. I think the default is 80 and we've got it set to 120. This would be a good thing to chat about in FE variety if you'd like. |
||
const navigate = useNavigate() | ||
const userToBeSuspended = users?.find((u) => u.id === userIdToSuspend) | ||
const userToBeActivated = users?.find((u) => u.id === userIdToActivate) | ||
const userToResetPassword = users?.find((u) => u.id === userIdToResetPassword) | ||
const permissions = useSelector(xServices.authXService, selectPermissions) | ||
const canEditUsers = permissions && permissions.updateUsers | ||
|
@@ -62,6 +67,9 @@ export const UsersPage: React.FC = () => { | |
onSuspendUser={(user) => { | ||
usersSend({ type: "SUSPEND_USER", userId: user.id }) | ||
}} | ||
onActivateUser={(user) => { | ||
usersSend({ type: "ACTIVATE_USER", userId: user.id }) | ||
}} | ||
onResetUserPassword={(user) => { | ||
usersSend({ type: "RESET_USER_PASSWORD", userId: user.id }) | ||
}} | ||
|
@@ -99,6 +107,25 @@ export const UsersPage: React.FC = () => { | |
} | ||
/> | ||
|
||
<ConfirmDialog | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We have a There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. good idea! |
||
hideCancel={false} | ||
open={usersState.matches("confirmUserActivation")} | ||
confirmLoading={usersState.matches("activatingUser")} | ||
title={Language.activateDialogTitle} | ||
confirmText={Language.activateDialogAction} | ||
onConfirm={() => { | ||
usersSend("CONFIRM_USER_ACTIVATION") | ||
}} | ||
onClose={() => { | ||
usersSend("CANCEL_USER_ACTIVATION") | ||
}} | ||
description={ | ||
<> | ||
{Language.activateDialogMessagePrefix} <strong>{userToBeActivated?.username}</strong>? | ||
</> | ||
} | ||
/> | ||
|
||
<ResetPasswordDialog | ||
loading={usersState.matches("resettingUserPassword")} | ||
user={userToResetPassword} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -16,7 +16,9 @@ export const Language = { | |
createUserSuccess: "Successfully created user.", | ||
createUserError: "Error on creating the user.", | ||
suspendUserSuccess: "Successfully suspended the user.", | ||
suspendUserError: "Error on suspending the user.", | ||
suspendUserError: "Error suspending user.", | ||
activateUserSuccess: "Successfully activated the user", | ||
activateUserError: "Error activating user", | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
resetUserPasswordSuccess: "Successfully updated the user password.", | ||
resetUserPasswordError: "Error on resetting the user password.", | ||
updateUserRolesSuccess: "Successfully updated the user roles.", | ||
|
@@ -32,6 +34,9 @@ export interface UsersContext { | |
// Suspend user | ||
userIdToSuspend?: TypesGen.User["id"] | ||
suspendUserError?: Error | unknown | ||
// Activate user | ||
userIdToActivate?: TypesGen.User["id"] | ||
activateUserError?: Error | unknown | ||
// Reset user password | ||
userIdToResetPassword?: TypesGen.User["id"] | ||
resetUserPasswordError?: Error | unknown | ||
|
@@ -49,6 +54,10 @@ export type UsersEvent = | |
| { type: "SUSPEND_USER"; userId: TypesGen.User["id"] } | ||
| { type: "CONFIRM_USER_SUSPENSION" } | ||
| { type: "CANCEL_USER_SUSPENSION" } | ||
// Activate events | ||
| { type: "ACTIVATE_USER"; userId: TypesGen.User["id"] } | ||
| { type: "CONFIRM_USER_ACTIVATION" } | ||
| { type: "CANCEL_USER_ACTIVATION" } | ||
// Reset password events | ||
| { type: "RESET_USER_PASSWORD"; userId: TypesGen.User["id"] } | ||
| { type: "CONFIRM_USER_PASSWORD_RESET" } | ||
|
@@ -72,6 +81,9 @@ export const usersMachine = createMachine( | |
suspendUser: { | ||
data: TypesGen.User | ||
} | ||
activateUser: { | ||
data: TypesGen.User | ||
} | ||
updateUserPassword: { | ||
data: undefined | ||
} | ||
|
@@ -92,6 +104,10 @@ export const usersMachine = createMachine( | |
target: "confirmUserSuspension", | ||
actions: ["assignUserIdToSuspend"], | ||
}, | ||
ACTIVATE_USER: { | ||
target: "confirmUserActivation", | ||
actions: ["assignUserIdToActivate"], | ||
}, | ||
RESET_USER_PASSWORD: { | ||
target: "confirmUserPasswordReset", | ||
actions: ["assignUserIdToResetPassword", "generateRandomPassword"], | ||
|
@@ -150,6 +166,12 @@ export const usersMachine = createMachine( | |
CANCEL_USER_SUSPENSION: "idle", | ||
}, | ||
}, | ||
confirmUserActivation: { | ||
on: { | ||
CONFIRM_USER_ACTIVATION: "activatingUser", | ||
CANCEL_USER_ACTIVATION: "idle", | ||
}, | ||
}, | ||
suspendingUser: { | ||
entry: "clearSuspendUserError", | ||
invoke: { | ||
|
@@ -166,6 +188,22 @@ export const usersMachine = createMachine( | |
}, | ||
}, | ||
}, | ||
activatingUser: { | ||
entry: "clearActivateUserError", | ||
invoke: { | ||
src: "activateUser", | ||
id: "activateUser", | ||
onDone: { | ||
// Update users list | ||
target: "gettingUsers", | ||
actions: ["displayActivateSuccess"], | ||
}, | ||
onError: { | ||
target: "idle", | ||
actions: ["assignActivateUserError", "displayActivatedErrorMessage"], | ||
}, | ||
}, | ||
}, | ||
confirmUserPasswordReset: { | ||
on: { | ||
CONFIRM_USER_PASSWORD_RESET: "resettingUserPassword", | ||
|
@@ -223,6 +261,13 @@ export const usersMachine = createMachine( | |
|
||
return API.suspendUser(context.userIdToSuspend) | ||
}, | ||
activateUser: (context) => { | ||
if (!context.userIdToActivate) { | ||
throw new Error("userIdToActivate is undefined") | ||
} | ||
|
||
return API.activateUser(context.userIdToActivate) | ||
}, | ||
resetUserPassword: (context) => { | ||
if (!context.userIdToResetPassword) { | ||
throw new Error("userIdToResetPassword is undefined") | ||
|
@@ -258,6 +303,9 @@ export const usersMachine = createMachine( | |
assignUserIdToSuspend: assign({ | ||
userIdToSuspend: (_, event) => event.userId, | ||
}), | ||
assignUserIdToActivate: assign({ | ||
userIdToActivate: (_, event) => event.userId, | ||
}), | ||
assignUserIdToResetPassword: assign({ | ||
userIdToResetPassword: (_, event) => event.userId, | ||
}), | ||
|
@@ -278,6 +326,9 @@ export const usersMachine = createMachine( | |
assignSuspendUserError: assign({ | ||
suspendUserError: (_, event) => event.data, | ||
}), | ||
assignActivateUserError: assign({ | ||
activateUserError: (_, event) => event.data, | ||
}), | ||
assignResetUserPasswordError: assign({ | ||
resetUserPasswordError: (_, event) => event.data, | ||
}), | ||
|
@@ -292,6 +343,9 @@ export const usersMachine = createMachine( | |
clearSuspendUserError: assign({ | ||
suspendUserError: (_) => undefined, | ||
}), | ||
clearActivateUserError: assign({ | ||
activateUserError: (_) => undefined, | ||
}), | ||
clearResetUserPasswordError: assign({ | ||
resetUserPasswordError: (_) => undefined, | ||
}), | ||
|
@@ -308,6 +362,13 @@ export const usersMachine = createMachine( | |
const message = getErrorMessage(context.suspendUserError, Language.suspendUserError) | ||
displayError(message) | ||
}, | ||
displayActivateSuccess: () => { | ||
displaySuccess(Language.activateUserSuccess) | ||
}, | ||
displayActivatedErrorMessage: (context) => { | ||
const message = getErrorMessage(context.activateUserError, Language.activateUserError) | ||
displayError(message) | ||
}, | ||
displayResetPasswordSuccess: () => { | ||
displaySuccess(Language.resetUserPasswordSuccess) | ||
}, | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this be
activate
in place ofactive
?