Skip to content

Commit b86f636

Browse files
committed
Site UI changes
1 parent daa025f commit b86f636

File tree

7 files changed

+160
-1
lines changed

7 files changed

+160
-1
lines changed

site/src/api/api.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -661,6 +661,15 @@ export const activateUser = async (
661661
return response.data
662662
}
663663

664+
export const markUserDormant = async (
665+
userId: TypesGen.User["id"],
666+
): Promise<TypesGen.User> => {
667+
const response = await axios.put<TypesGen.User>(
668+
`/api/v2/users/${userId}/status/dormant`,
669+
)
670+
return response.data
671+
}
672+
664673
export const suspendUser = async (
665674
userId: TypesGen.User["id"],
666675
): Promise<TypesGen.User> => {

site/src/components/UsersTable/UsersTable.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ export interface UsersTableProps {
2626
isLoading?: boolean
2727
onSuspendUser: (user: TypesGen.User) => void
2828
onActivateUser: (user: TypesGen.User) => void
29+
onMarkUserDormant: (user: TypesGen.User) => void
2930
onDeleteUser: (user: TypesGen.User) => void
3031
onListWorkspaces: (user: TypesGen.User) => void
3132
onViewActivity: (user: TypesGen.User) => void
@@ -46,6 +47,7 @@ export const UsersTable: FC<React.PropsWithChildren<UsersTableProps>> = ({
4647
onListWorkspaces,
4748
onViewActivity,
4849
onActivateUser,
50+
onMarkUserDormant,
4951
onResetUserPassword,
5052
onUpdateUserRoles,
5153
isUpdatingUserRoles,
@@ -83,6 +85,7 @@ export const UsersTable: FC<React.PropsWithChildren<UsersTableProps>> = ({
8385
canViewActivity={canViewActivity}
8486
isUpdatingUserRoles={isUpdatingUserRoles}
8587
onActivateUser={onActivateUser}
88+
onMarkUserDormant={onMarkUserDormant}
8689
onDeleteUser={onDeleteUser}
8790
onListWorkspaces={onListWorkspaces}
8891
onViewActivity={onViewActivity}

site/src/components/UsersTable/UsersTableBody.tsx

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ interface UsersTableBodyProps {
4141
onListWorkspaces: (user: TypesGen.User) => void
4242
onViewActivity: (user: TypesGen.User) => void
4343
onActivateUser: (user: TypesGen.User) => void
44+
onMarkUserDormant: (user: TypesGen.User) => void
4445
onResetUserPassword: (user: TypesGen.User) => void
4546
onUpdateUserRoles: (
4647
user: TypesGen.User,
@@ -60,6 +61,7 @@ export const UsersTableBody: FC<
6061
onListWorkspaces,
6162
onViewActivity,
6263
onActivateUser,
64+
onMarkUserDormant,
6365
onResetUserPassword,
6466
onUpdateUserRoles,
6567
isUpdatingUserRoles,
@@ -176,15 +178,39 @@ export const UsersTableBody: FC<
176178
onClick: onSuspendUser,
177179
disabled: false,
178180
},
181+
{
182+
label: t(
183+
"markUserDormantMenuItem",
184+
) as React.ReactNode,
185+
onClick: onMarkUserDormant,
186+
disabled: user.id === actorID,
187+
}
188+
]
189+
: user.status === "suspended"
190+
? [
191+
{
192+
label: t(
193+
"activateMenuItem",
194+
) as React.ReactNode,
195+
onClick: onActivateUser,
196+
disabled: false,
197+
},
179198
]
180-
: [
199+
: [ // User account is dormant
181200
{
182201
label: t(
183202
"activateMenuItem",
184203
) as React.ReactNode,
185204
onClick: onActivateUser,
186205
disabled: false,
187206
},
207+
{
208+
label: t(
209+
"suspendMenuItem",
210+
) as React.ReactNode,
211+
onClick: onSuspendUser,
212+
disabled: false,
213+
},
188214
]
189215
).concat(
190216
{

site/src/i18n/en/usersPage.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
"deleteMenuItem": "Delete",
66
"listWorkspacesMenuItem": "View workspaces",
77
"activateMenuItem": "Activate",
8+
"markUserDormantMenuItem": "Mark user as dormant",
89
"resetPasswordMenuItem": "Reset password",
910
"editUserRolesTooltip": "Edit user roles",
1011
"fieldSetRolesTooltip": "Available roles",

site/src/pages/UsersPage/UsersPage.tsx

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@ export const Language = {
2828
activateDialogTitle: "Activate user",
2929
activateDialogAction: "Activate",
3030
activateDialogMessagePrefix: "Do you want to activate the user",
31+
markUserDormantDialogTitle: "Mark user dormant",
32+
markUserDormantDialogAction: "Mark dormant",
33+
markUserDormantDialogMessagePrefix: "Do you want to mark the user account dormant",
3134
}
3235

3336
const getSelectedUser = (id: string, users?: User[]) =>
@@ -55,6 +58,7 @@ export const UsersPage: FC<{ children?: ReactNode }> = () => {
5558
usernameToDelete,
5659
usernameToSuspend,
5760
usernameToActivate,
61+
usernameToMarkDormant,
5862
userIdToResetPassword,
5963
newUserPassword,
6064
paginationRef,
@@ -137,6 +141,13 @@ export const UsersPage: FC<{ children?: ReactNode }> = () => {
137141
username: user.username,
138142
})
139143
}}
144+
onMarkUserDormant={(user) => {
145+
usersSend({
146+
type: "MARK_USER_DORMANT",
147+
userId: user.id,
148+
username: user.username,
149+
})
150+
}}
140151
onResetUserPassword={(user) => {
141152
usersSend({ type: "RESET_USER_PASSWORD", userId: user.id })
142153
}}
@@ -230,6 +241,31 @@ export const UsersPage: FC<{ children?: ReactNode }> = () => {
230241
}
231242
/>
232243

244+
<ConfirmDialog
245+
type="info"
246+
hideCancel={false}
247+
open={
248+
usersState.matches("confirmUserDormant") ||
249+
usersState.matches("markingUserDormant")
250+
}
251+
confirmLoading={usersState.matches("markingUserDormant")}
252+
title={Language.markUserDormantDialogTitle}
253+
confirmText={Language.markUserDormantDialogAction}
254+
onConfirm={() => {
255+
usersSend("CONFIRM_USER_DORMANT")
256+
}}
257+
onClose={() => {
258+
usersSend("CANCEL_USER_DORMANT")
259+
}}
260+
description={
261+
<>
262+
{Language.markUserDormantDialogMessagePrefix}
263+
{usernameToMarkDormant && " "}
264+
<strong>{usernameToMarkDormant ?? ""}</strong>?
265+
</>
266+
}
267+
/>
268+
233269
{userIdToResetPassword && (
234270
<ResetPasswordDialog
235271
open={

site/src/pages/UsersPage/UsersPageView.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ export interface UsersPageViewProps {
2323
onListWorkspaces: (user: TypesGen.User) => void
2424
onViewActivity: (user: TypesGen.User) => void
2525
onActivateUser: (user: TypesGen.User) => void
26+
onMarkUserDormant: (user: TypesGen.User) => void
2627
onResetUserPassword: (user: TypesGen.User) => void
2728
onUpdateUserRoles: (
2829
user: TypesGen.User,
@@ -43,6 +44,7 @@ export const UsersPageView: FC<React.PropsWithChildren<UsersPageViewProps>> = ({
4344
onListWorkspaces,
4445
onViewActivity,
4546
onActivateUser,
47+
onMarkUserDormant,
4648
onResetUserPassword,
4749
onUpdateUserRoles,
4850
isUpdatingUserRoles,
@@ -73,6 +75,7 @@ export const UsersPageView: FC<React.PropsWithChildren<UsersPageViewProps>> = ({
7375
onListWorkspaces={onListWorkspaces}
7476
onViewActivity={onViewActivity}
7577
onActivateUser={onActivateUser}
78+
onMarkUserDormant={onMarkUserDormant}
7679
onResetUserPassword={onResetUserPassword}
7780
onUpdateUserRoles={onUpdateUserRoles}
7881
isUpdatingUserRoles={isUpdatingUserRoles}

site/src/xServices/users/usersXService.ts

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ export const Language = {
2525
deleteUserError: "Error deleting user.",
2626
activateUserSuccess: "Successfully activated the user.",
2727
activateUserError: "Error activating user.",
28+
markUserDormantSuccess: "Successfully marked the user account as dormant.",
29+
markUserDormantError: "Error marking user account as dormant.",
2830
resetUserPasswordSuccess: "Successfully updated the user password.",
2931
resetUserPasswordError: "Error on resetting the user password.",
3032
updateUserRolesSuccess: "Successfully updated the user roles.",
@@ -48,6 +50,10 @@ export interface UsersContext {
4850
userIdToActivate?: TypesGen.User["id"]
4951
usernameToActivate?: TypesGen.User["username"]
5052
activateUserError?: Error | unknown
53+
// Mark user dormant
54+
userIdToMarkDormant?: TypesGen.User["id"]
55+
usernameToMarkDormant?: TypesGen.User["username"]
56+
markUserDormantError?: Error | unknown
5157
// Reset user password
5258
userIdToResetPassword?: TypesGen.User["id"]
5359
resetUserPasswordError?: Error | unknown
@@ -86,6 +92,14 @@ export type UsersEvent =
8692
}
8793
| { type: "CONFIRM_USER_ACTIVATION" }
8894
| { type: "CANCEL_USER_ACTIVATION" }
95+
// Mark as dormant events
96+
| {
97+
type: "MARK_USER_DORMANT"
98+
userId: TypesGen.User["id"]
99+
username: TypesGen.User["username"]
100+
}
101+
| { type: "CONFIRM_USER_DORMANT" }
102+
| { type: "CANCEL_USER_DORMANT" }
89103
// Reset password events
90104
| { type: "RESET_USER_PASSWORD"; userId: TypesGen.User["id"] }
91105
| { type: "CONFIRM_USER_PASSWORD_RESET" }
@@ -125,6 +139,9 @@ export const usersMachine =
125139
activateUser: {
126140
data: TypesGen.User
127141
}
142+
markUserDormant: {
143+
data: TypesGen.User
144+
}
128145
updateUserPassword: {
129146
data: undefined
130147
}
@@ -187,6 +204,10 @@ export const usersMachine =
187204
target: "confirmUserActivation",
188205
actions: "assignUserToActivate",
189206
},
207+
MARK_USER_DORMANT: {
208+
target: "confirmUserDormant",
209+
actions: "assignUserToMarkDormant",
210+
},
190211
RESET_USER_PASSWORD: {
191212
target: "confirmUserPasswordReset",
192213
actions: [
@@ -230,6 +251,16 @@ export const usersMachine =
230251
},
231252
},
232253
},
254+
confirmUserDormant: {
255+
on: {
256+
CONFIRM_USER_DORMANT: {
257+
target: "markingUserDormant",
258+
},
259+
CANCEL_USER_DORMANT: {
260+
target: "idle",
261+
},
262+
},
263+
},
233264
suspendingUser: {
234265
entry: "clearSuspendUserError",
235266
invoke: {
@@ -293,6 +324,28 @@ export const usersMachine =
293324
],
294325
},
295326
},
327+
markingUserDormant: {
328+
entry: "clearMarkUserDormantError",
329+
invoke: {
330+
src: "markUserDormant",
331+
id: "markUserDormant",
332+
onDone: [
333+
{
334+
target: "gettingUsers",
335+
actions: "displayMarkUserDormantSuccess",
336+
},
337+
],
338+
onError: [
339+
{
340+
target: "idle",
341+
actions: [
342+
"assignMarkUserDormantError",
343+
"displayMarkUserDormantErrorMessage",
344+
],
345+
},
346+
],
347+
},
348+
},
296349
confirmUserPasswordReset: {
297350
on: {
298351
CONFIRM_USER_PASSWORD_RESET: {
@@ -382,6 +435,12 @@ export const usersMachine =
382435

383436
return API.activateUser(context.userIdToActivate)
384437
},
438+
markUserDormant: (context) => {
439+
if (!context.userIdToMarkDormant) {
440+
throw new Error("userIdToMarkDormant is undefined")
441+
}
442+
return API.markUserDormant(context.userIdToMarkDormant)
443+
},
385444
resetUserPassword: (context) => {
386445
if (!context.userIdToResetPassword) {
387446
throw new Error("userIdToResetPassword is undefined")
@@ -413,6 +472,8 @@ export const usersMachine =
413472
usernameToDelete: (_) => undefined,
414473
userIdToActivate: (_) => undefined,
415474
usernameToActivate: (_) => undefined,
475+
userIdToMarkDormant: (_) => undefined,
476+
usernameToMarkDormant: (_) => undefined,
416477
userIdToResetPassword: (_) => undefined,
417478
userIdToUpdateRoles: (_) => undefined,
418479
}),
@@ -438,6 +499,10 @@ export const usersMachine =
438499
userIdToActivate: (_, event) => event.userId,
439500
usernameToActivate: (_, event) => event.username,
440501
}),
502+
assignUserToMarkDormant: assign({
503+
userIdToMarkDormant: (_, event) => event.userId,
504+
usernameToMarkDormant: (_, event) => event.username,
505+
}),
441506
assignUserIdToResetPassword: assign({
442507
userIdToResetPassword: (_, event) => event.userId,
443508
}),
@@ -457,6 +522,9 @@ export const usersMachine =
457522
assignActivateUserError: assign({
458523
activateUserError: (_, event) => event.data,
459524
}),
525+
assignMarkUserDormantError: assign({
526+
markUserDormantError: (_, event) => event.data,
527+
}),
460528
assignResetUserPasswordError: assign({
461529
resetUserPasswordError: (_, event) => event.data,
462530
}),
@@ -477,6 +545,9 @@ export const usersMachine =
477545
clearActivateUserError: assign({
478546
activateUserError: (_) => undefined,
479547
}),
548+
clearMarkUserDormantError: assign({
549+
markUserDormantError: (_) => undefined,
550+
}),
480551
clearResetUserPasswordError: assign({
481552
resetUserPasswordError: (_) => undefined,
482553
}),
@@ -513,6 +584,16 @@ export const usersMachine =
513584
)
514585
displayError(message)
515586
},
587+
displayMarkUserDormantSuccess: () => {
588+
displaySuccess(Language.markUserDormantSuccess)
589+
},
590+
displayMarkUserDormantErrorMessage: (context) => {
591+
const message = getErrorMessage(
592+
context.markUserDormantError,
593+
Language.markUserDormantError,
594+
)
595+
displayError(message)
596+
},
516597
displayResetPasswordSuccess: () => {
517598
displaySuccess(Language.resetUserPasswordSuccess)
518599
},

0 commit comments

Comments
 (0)